# Source code for copulas.bivariate.gumbel

"""Gumbel module."""

import numpy as np

from copulas.bivariate.base import Bivariate, CopulaTypes
from copulas.bivariate.utils import split_matrix

[docs]class Gumbel(Bivariate):
"""Class for clayton copula model."""

copula_type = CopulaTypes.GUMBEL
theta_interval = [1, float('inf')]
invalid_thetas = []

[docs]    def generator(self, t):
"""Return the generator function."""
return np.power(-np.log(t), self.theta)

[docs]    def probability_density(self, X):
r"""Compute probability density function for given copula family.

The probability density(PDF) for the Gumbel family of copulas correspond to the formula:

.. math::

\begin{align}
c(U,V)
&= \frac{\partial^2 C(u,v)}{\partial v \partial u}
&= \frac{C(u,v)}{uv} \frac{((-\ln u)^{\theta}  # noqa: JS101
+ (-\ln v)^{\theta})^{\frac{2}  # noqa: JS101
{\theta} - 2 }}{(\ln u \ln v)^{1 - \theta}}  # noqa: JS101
( 1 + (\theta-1) \big((-\ln u)^\theta
+ (-\ln v)^\theta\big)^{-1/\theta})
\end{align}

Args:
X (numpy.ndarray)

Returns:
numpy.ndarray

"""
self.check_fit()

U, V = split_matrix(X)

if self.theta == 1:
return U * V

else:
a = np.power(U * V, -1)
tmp = np.power(-np.log(U), self.theta) + np.power(-np.log(V), self.theta)
b = np.power(tmp, -2 + 2.0 / self.theta)
c = np.power(np.log(U) * np.log(V), self.theta - 1)
d = 1 + (self.theta - 1) * np.power(tmp, -1.0 / self.theta)
return self.cumulative_distribution(X) * a * b * c * d

[docs]    def cumulative_distribution(self, X):
r"""Compute the cumulative distribution function for the Gumbel copula.

The cumulative density(cdf), or distribution function for the Gumbel family of copulas
correspond to the formula:

.. math:: C(u,v) = e^{-((-\ln u)^{\theta} + (-\ln v)^{\theta})^{\frac{1}{\theta}}}

Args:
X (np.ndarray)

Returns:
np.ndarray: cumulative probability for the given datapoints, cdf(X).

"""
self.check_fit()

U, V = split_matrix(X)

if self.theta == 1:
return U * V

else:
h = np.power(-np.log(U), self.theta) + np.power(-np.log(V), self.theta)
h = -np.power(h, 1.0 / self.theta)
cdfs = np.exp(h)
return cdfs

[docs]    def percent_point(self, y, V):
"""Compute the inverse of conditional cumulative distribution :math:C(u|v)^{-1}.

Args:
y (np.ndarray): value of :math:C(u|v).
v (np.ndarray): given value of v.

"""
self.check_fit()

if self.theta == 1:
return y

else:
return super().percent_point(y, V)

[docs]    def partial_derivative(self, X):
r"""Compute partial derivative of cumulative distribution.

The partial derivative of the copula(CDF) is the conditional CDF.

.. math:: F(v|u) = \frac{\partial C(u,v)}{\partial u} =
C(u,v)\frac{((-\ln u)^{\theta} + (-\ln v)^{\theta})^{\frac{1}{\theta} - 1}}
{\theta(- \ln u)^{1 -\theta}}

Args:
X (np.ndarray)
y (float)

Returns:
numpy.ndarray

"""
self.check_fit()

U, V = split_matrix(X)

if self.theta == 1:
return V

else:
t1 = np.power(-np.log(U), self.theta)
t2 = np.power(-np.log(V), self.theta)
p1 = self.cumulative_distribution(X)
p2 = np.power(t1 + t2, -1 + 1.0 / self.theta)
p3 = np.power(-np.log(V), self.theta - 1)
return p1 * p2 * p3 / V

[docs]    def compute_theta(self):
r"""Compute theta parameter using Kendall's tau.

On Gumbel copula :math:\tau is defined as :math:τ = \frac{θ−1}{θ}
that we solve as :math:θ = \frac{1}{1-τ}
"""
if self.tau == 1:
raise ValueError("Tau value can't be 1")

return 1 / (1 - self.tau)