Source code for chaospy.distributions.copulas.gumbel

r"""
Gumbel Copula.

As a short hand:

.. math::

    s_n = \sigma(u, n, \theta)

The calculation of the derivative of the ``iphi`` function:

.. math::
  \begin{eqnarray}
    iphi(u)     &= e^{-u^{1/\theta}}
    iphi'(u)    &= e^{-u^{1/theta}}*(-1/theta*u^{1/theta-1})
                = iphi(u)*s_1 \\
    iphi''(u)   &= iphi'(u)*s_1+iphi(u)*s_2
                = iphi(u)*s_1^2+iphi(u)*s_2
                = iphi(u)*(s_1^2+s_2) \\
    iphi'''(u)  &= iphi'(u)*(s_1^2+s_2)+iphi(u)*(2*s_1*s_2+s_3)
                = iphi(u)*s_1*(s_1^2+s_2)+iphi(u)*(2*s_1*s_2+s_3)
                = iphi(u)*(s_1^3+3*s_1*s_2+s_3) \\
    iphi''''(u) &= iphi'(u)*(s_1^3+3*s_1*s_2+s_3) +
                   iphi(u)*(3*s_1^2*s_2+3*s_2^2+3*s_1*s_3+s_4)
                = iphi(u)*s_1*(s_1^3+3*s_1*s_2+s_3) +
                  iphi(u)*(3*s_1^2*s_2+3*s_2^2+3*s_1*s_3+s_4)
                = iphi(u)*(s_1^4 + 3*s_1^2*s_2 + s_1*s_3 +
                           3*s_1^2*s_2 + 3*s_2^2 + 3*s_1*s_3 + s_4)
                = iphi(u)*(s_1^4 + 6*s_1^2*s_2 +
                           s_1*s_3 + 3*s_2^2 + 3*s_1*s_3 + s_4)
  \end{eqnarray}

The same formula defined recursively:

.. math::
  \begin{eqnarray}
    iphi'(u)    &= iphi(u)*\sigma(u, 1, \theta) \\
    iphi''(u)   &= d/du ( iphi(u)*\sigma(u, 1, \theta) )
                = iphi'(u)*\sigma(u, 1, \theta) +
                  iphi(u)*\sigma(u, 2, \theta) \\
    iphi'''(u)  &= d/du (iphi'(u)*\sigma(u, 1, \theta) +
                          iphi(u)*\sigma(u, 2, \theta))
                = iphi''(u)*\sigma(u, 1, \theta) +
                  iphi'(u)*\sigma(u, 2, \theta) +
                  iphi'(u)*\sigma(u, 2, \theta) +
                  iphi(u)*\sigma(u, 3, \theta)
                = iphi''(u)*\sigma(u, 1, \theta) +
                  2*iphi'(u)*\sigma(u, 2, \theta) +
                  iphi(u)*\sigma(u, 3, \theta) \\
    iphi''''(u) &= d/du (iphi''(u)*\sigma(u, 1, \theta) +
                         2*iphi'(u)*\sigma(u, 2, \theta) +
                         iphi(u)*\sigma(u, 3, \theta))
                = iphi'''(u)*\sigma(u, 1, \theta) +
                  iphi''(u)*\sigma(u, 2, \theta) +
                  2*iphi''(u)*\sigma(u, 2, \theta) +
                  2*iphi'(u)*\sigma(u, 3, \theta) +
                  iphi'(u)*\sigma(u, 3, \theta) +
                  iphi(u)*\sigma(u, 4, \theta)
                = iphi'''(u)*\sigma(u, 1, \theta) +
                  3*iphi''(u)*\sigma(u, 2, \theta) +
                  3*iphi'(u)*\sigma(u, 3, \theta) +
                  iphi(u)*\sigma(u, 4, \theta) \\
                & \vdots \\
    iphi^{n}(u) &= sum_{i=1}^{n} comb(n, i-1) iphi^{n-i}(u) \sigma(u, i, \theta)
  \end{eqnarray}
"""
try:
    from functools import lru_cache
except ImportError:
    from functools32 import lru_cache
import numpy
from scipy import special

from ..baseclass import CopulaDistribution
from .archimedean import Archimedean


class gumbel(Archimedean):
    """Gumbel backend."""

    def _phi(self, t_loc, theta):
        return (-numpy.log(t_loc)) ** theta

    def _delta_phi(self, t_loc, theta):
        return -theta * (-numpy.log(t_loc)) ** (theta - 1) / t_loc

    def _inverse_phi(self, u_loc, theta, order):
        @lru_cache(None)
        def iphi(n):
            if n:
                return sum(
                    special.comb(n, i - 1) * iphi(n - i) * sigma(i)
                    for i in range(1, n + 1)
                )
            return numpy.e ** (-(u_loc ** (1 / theta)))

        @lru_cache(None)
        def sigma(n):
            return self._sigma(u_loc, theta, n)

        return iphi(order)


[docs]class Gumbel(CopulaDistribution): r""" Gumbel Copula. .. math:: \phi(x; \theta) = \frac{x^{-\theta}-1}{\theta} \phi^{-1}(q; \theta) = (q*\theta + 1)^{-1/\theta} where :math:`\theta` is defined on the interval `[1,inf)`. Examples: >>> distribution = chaospy.Gumbel( ... chaospy.Iid(chaospy.Uniform(-1, 1), 2), theta=2) >>> distribution Gumbel(Iid(Uniform(lower=-1, upper=1), 2), theta=2) >>> samples = distribution.sample(3) >>> samples.round(4) array([[ 0.3072, -0.77 , 0.9006], [ 0.4709, 0.2101, 0.8696]]) >>> distribution.pdf(samples).round(4) array([7.9977000e+00, 5.0700000e-02, 3.6733563e+03]) >>> 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.0022, 0.1573, 0.3174], [ 0.109 , 0.2591, 0.4062], [ 0.2181, 0.3564, 0.489 ]]]) """
[docs] def __init__(self, dist, theta): """ Args: dist (Distribution): The distribution to wrap theta (float): Copula parameter """ super(Gumbel, self).__init__( dist=dist, trans=gumbel(len(dist), theta), repr_args=[dist, "theta=%s" % theta], )