"""T-Copula."""
import numpy
from scipy import special
import chaospy
from ..baseclass import CopulaDistribution, Distribution
class t_copula(Distribution):
"""T-Copula."""
def __init__(self, df, covariance, rotation=None):
assert isinstance(df, float)
covariance = numpy.asarray(covariance)
assert covariance.ndim == 2, "Covariance must be a matrix"
assert (
covariance.shape[0] == covariance.shape[1]
), "Parameters 'covariance' not a square matrix."
dependencies, _, rotation = chaospy.declare_dependencies(
self,
parameters=dict(covariance=covariance),
rotation=rotation,
dependency_type="accumulate",
)
correlation = covariance / numpy.sqrt(
numpy.outer(numpy.diag(covariance), numpy.diag(covariance))
)
self._permute = numpy.eye(len(rotation), dtype=int)[rotation]
self._correlation = self._permute.dot(correlation).dot(self._permute.T)
cholesky = numpy.linalg.cholesky(self._correlation)
self._fwd_transform = self._permute.T.dot(numpy.linalg.inv(cholesky))
self._inv_transform = self._permute.T.dot(cholesky)
super(t_copula, self).__init__(
parameters=dict(df=df),
dependencies=dependencies,
rotation=rotation,
repr_args=[covariance.tolist()],
)
def _cdf(self, xloc, idx, df, cache):
dim = self._rotation.index(idx)
conditions = [
self._get_cache(dim_, cache, get=0) for dim_ in self._rotation[:dim]
]
assert not any(
[isinstance(condition, chaospy.Distribution) for condition in conditions]
)
xloc = numpy.vstack(conditions + [xloc])
zloc = self._fwd_transform[idx, : len(xloc)].dot(special.stdtrit(df, xloc))
out = special.stdtr(df, zloc)
return out
def _ppf(self, qloc, idx, df, cache):
dim = self._rotation.index(idx)
conditions = [
self._get_cache(dim_, cache, get=1) for dim_ in self._rotation[:dim]
]
assert not any(
[isinstance(condition, chaospy.Distribution) for condition in conditions]
)
qloc = numpy.vstack(conditions + [qloc])
zloc = special.stdtrit(df, qloc)
out = special.stdtr(df, self._inv_transform[idx, : len(qloc)].dot(zloc))
return out
def _pdf(self, xloc, idx, df, cache):
raise chaospy.UnsupportedFeature("Copula not supported.")
def _lower(self, idx, df, cache):
return 0.0
def _upper(self, idx, df, cache):
return 1.0
[docs]class TCopula(CopulaDistribution):
"""
T-Copula.
Examples:
>>> distribution = chaospy.TCopula(
... chaospy.Iid(chaospy.Uniform(-1, 1), 2),
... df=5, covariance=[[1, .5], [.5, 1]])
>>> distribution
TCopula(Iid(Uniform(lower=-1, upper=1), 2), 5.0, [[1.0, 0.5], [0.5, 1.0]])
>>> samples = distribution.sample(3)
>>> samples.round(4)
array([[ 0.3072, -0.77 , 0.9006],
[ 0.1274, 0.3147, 0.1928]])
>>> distribution.pdf(samples).round(4)
array([0.2932, 0.1367, 0.1969])
>>> distribution.fwd(samples).round(4)
array([[0.6536, 0.115 , 0.9503],
[0.4822, 0.8725, 0.2123]])
>>> mesh = numpy.meshgrid([.4, .5, .6], [.4, .5, .6])
>>> distribution.inv(mesh).round(4)
array([[[-0.2 , 0. , 0.2 ],
[-0.2 , 0. , 0.2 ],
[-0.2 , 0. , 0.2 ]],
<BLANKLINE>
[[-0.2699, -0.1738, -0.0741],
[-0.1011, 0. , 0.1011],
[ 0.0741, 0.1738, 0.2699]]])
"""
[docs] def __init__(self, dist, df, covariance):
"""
Args:
dist (Distribution):
The distribution to wrap in a copula.
R (numpy.ndarray):
Covariance matrix defining dependencies..
df (float):
The degree of freedom in the underlying student-t distribution.
"""
assert len(dist) == len(covariance)
df = float(df)
covariance = numpy.asfarray(covariance)
super(TCopula, self).__init__(
dist=dist,
trans=t_copula(df, covariance, dist._rotation),
repr_args=[dist, df, covariance.tolist()],
)