
    M/Phٖ                     r
   d Z ddlZddlmZ ddlmZ ddlmZ d dfd	Z	d
 dddddfdZ
d Z G d d          Z G d d          Z G d d          Z G d de          Zej        Zej        Zej        Z G d de          Zd ddfdZedk    rddlmZmZ dgZd Z ej        d!d"gd"d!gg          Zg d#Z  ej        g d$g d%g d&g          Z!dev r eee          Z"e"#                    d'(          Z# e$e#%                    d                      e$ ej&        e#d)                      e$e"'                                            e$e"(                    ddg                      ee ej)        d*                    Z* eed+ ej)        d*          z            Z+d, Z, e$e*'                    e,                      e$e*-                    e+          e*.                    e+                      e$e+-                    e*          e+.                    e*                      e$e*-                    e"          e*.                    e"                      eee          Z/e/0                    ddg           e/0                     ej1        d-                      ej        g d$g d%g d&g          Z!g d#Z  ee e!          Z2e20                    d.           e23                    d.           g d/Z4 ee23                    e!          e4d01           g d2Z4 ee20                    e!          e4d31            e ej        g d4          e!          Z5g d5Z4 ee50                    e!          e4d61            ed4d          Z6d7 Z, e$e2	                    e,                      e$e2	                    e,d8(                      ed dd9          Z7 ee73                     ej        d:d:g                    d;d<1            ee70                     ej        d:d:g                    d=d<1           e73                     ej        d!d!g                    d>z
    ed dd          Z8e83                     ej        d!d!g                    d?z
   e7#                    d@          Z# e ej&        e#d)          e7j&        d1            ee e!d          Z9 ee90                    e!          g dAdB1            ee e!dC          Z7 ee70                    e!          g dDd31           dS dS )Ea  Multivariate Normal and t distributions



Created on Sat May 28 15:38:23 2011

@author: Josef Perktold

TODO:
* renaming,
    - after adding t distribution, cov does not make sense for Sigma    DONE
    - should mean also be renamed to mu, if there will be distributions
      with mean != mu
* not sure about corner cases
    - behavior with (almost) singular sigma or transforms
    - df <= 2, is everything correct if variance is not finite or defined ?
* check to return possibly univariate distribution for marginals or conditional
    distributions, does univariate special case work? seems ok for conditional
* are all the extra transformation methods useful outside of testing ?
  - looks like I have some mixup in definitions of standardize, normalize
* new methods marginal, conditional, ... just added, typos ?
  - largely tested for MVNormal, not yet for MVT   DONE
* conditional: reusing, vectorizing, should we reuse a projection matrix or
  allow for a vectorized, conditional_mean similar to OLS.predict
* add additional things similar to LikelihoodModelResults? quadratic forms,
  F distribution, and others ???
* add Delta method for nonlinear functions here, current function is hidden
  somewhere in miscmodels
* raise ValueErrors for wrong input shapes, currently only partially checked

* quantile method (ppf for equal bounds for multiple testing) is missing
  http://svitsrv25.epfl.ch/R-doc/library/mvtnorm/html/qmvt.html seems to use
  just a root finder for inversion of cdf

* normalize has ambiguous definition, and mixing it up in different versions
  std from sigma or std from cov ?
  I would like to get what I need for mvt-cdf, or not
  univariate standard t distribution has scale=1 but std>1
  FIXED: add std_sigma, and normalize uses std_sigma

* more work: bivariate distributions,
  inherit from multivariate but overwrite some methods for better efficiency,
  e.g. cdf and expect

I kept the original MVNormal0 class as reference, can be deleted


See Also
--------
sandbox/examples/ex_mvelliptical.py

Examples
--------

Note, several parts of these examples are random and the numbers will not be
(exactly) the same.

>>> import numpy as np
>>> import statsmodels.sandbox.distributions.mv_normal as mvd
>>>
>>> from numpy.testing import assert_array_almost_equal
>>>
>>> cov3 = np.array([[ 1.  ,  0.5 ,  0.75],
...                    [ 0.5 ,  1.5 ,  0.6 ],
...                    [ 0.75,  0.6 ,  2.  ]])

>>> mu = np.array([-1, 0.0, 2.0])

multivariate normal distribution
--------------------------------

>>> mvn3 = mvd.MVNormal(mu, cov3)
>>> mvn3.rvs(size=3)
array([[-0.08559948, -1.0319881 ,  1.76073533],
       [ 0.30079522,  0.55859618,  4.16538667],
       [-1.36540091, -1.50152847,  3.87571161]])

>>> mvn3.std
array([ 1.        ,  1.22474487,  1.41421356])
>>> a = [0.0, 1.0, 1.5]
>>> mvn3.pdf(a)
0.013867410439318712
>>> mvn3.cdf(a)
0.31163181123730122

Monte Carlo integration

>>> mvn3.expect_mc(lambda x: (x<a).all(-1), size=100000)
0.30958999999999998
>>> mvn3.expect_mc(lambda x: (x<a).all(-1), size=1000000)
0.31197399999999997

multivariate t distribution
---------------------------

>>> mvt3 = mvd.MVT(mu, cov3, 4)
>>> mvt3.rvs(size=4)
array([[-0.94185437,  0.3933273 ,  2.40005487],
       [ 0.07563648,  0.06655433,  7.90752238],
       [ 1.06596474,  0.32701158,  2.03482886],
       [ 3.80529746,  7.0192967 ,  8.41899229]])

>>> mvt3.pdf(a)
0.010402959362646937
>>> mvt3.cdf(a)
0.30269483623249821
>>> mvt3.expect_mc(lambda x: (x<a).all(-1), size=1000000)
0.30271199999999998

>>> mvt3.cov
array([[ 2. ,  1. ,  1.5],
       [ 1. ,  3. ,  1.2],
       [ 1.5,  1.2,  4. ]])
>>> mvt3.corr
array([[ 1.        ,  0.40824829,  0.53033009],
       [ 0.40824829,  1.        ,  0.34641016],
       [ 0.53033009,  0.34641016,  1.        ]])

get normalized distribution

>>> mvt3n = mvt3.normalized()
>>> mvt3n.sigma
array([[ 1.        ,  0.40824829,  0.53033009],
       [ 0.40824829,  1.        ,  0.34641016],
       [ 0.53033009,  0.34641016,  1.        ]])
>>> mvt3n.cov
array([[ 2.        ,  0.81649658,  1.06066017],
       [ 0.81649658,  2.        ,  0.69282032],
       [ 1.06066017,  0.69282032,  2.        ]])

What's currently there?

>>> [i for i in dir(mvn3) if not i[0]=='_']
['affine_transformed', 'cdf', 'cholsigmainv', 'conditional', 'corr', 'cov',
'expect_mc', 'extra_args', 'logdetsigma', 'logpdf', 'marginal', 'mean',
'normalize', 'normalized', 'normalized2', 'nvars', 'pdf', 'rvs', 'sigma',
'sigmainv', 'standardize', 'standardized', 'std', 'std_sigma', 'whiten']

>>> [i for i in dir(mvt3) if not i[0]=='_']
['affine_transformed', 'cdf', 'cholsigmainv', 'corr', 'cov', 'df', 'expect_mc',
'extra_args', 'logdetsigma', 'logpdf', 'marginal', 'mean', 'normalize',
'normalized', 'normalized2', 'nvars', 'pdf', 'rvs', 'sigma', 'sigmainv',
'standardize', 'standardized', 'std', 'std_sigma', 'whiten']

    N)special)
mvstdtprob   )	mvnormcdfc                     dS Nr    xs    k/var/www/html/test/jupyter/venv/lib/python3.11/site-packages/statsmodels/sandbox/distributions/mv_normal.py<lambda>r      s    1     iP  c                 v    fd}|                      |          } ||                              d          S )a  calculate expected value of function by Monte Carlo integration

    Parameters
    ----------
    dist : distribution instance
        needs to have rvs defined as a method for drawing random numbers
    func : callable
        function for which expectation is calculated, this function needs to
        be vectorized, integration is over axis=0
    size : int
        number of random samples to use in the Monte Carlo integration,


    Notes
    -----
    this does not batch

    Returns
    -------
    expected value : ndarray
        return of function func integrated over axis=0 by MonteCarlo, this will
        have the same shape as the return of func without axis=0

    Examples
    --------

    integrate probability that both observations are negative

    >>> mvn = mve.MVNormal([0,0],2.)
    >>> mve.expect_mc(mvn, lambda x: (x<np.array([0,0])).all(-1), size=100000)
    0.25306000000000001

    get tail probabilities of marginal distribution (should be 0.1)

    >>> c = stats.norm.isf(0.05, scale=np.sqrt(2.))
    >>> expect_mc(mvn, lambda x: (np.abs(x)>np.array([c, c])), size=100000)
    array([ 0.09969,  0.0986 ])

    or calling the method

    >>> mvn.expect_mc(lambda x: (np.abs(x)>np.array([c, c])), size=100000)
    array([ 0.09937,  0.10075])


    c                      |           S Nr	   r   funcs    r   funzexpect_mc.<locals>.fun       tAwwr   sizer   rvsmean)distr   r   r   r   s    `   r   	expect_mcr      sJ    \    
(((

C3s88==r   c                     dS r   r	   r
   s    r   r   r      s    ! r   Fg333333?c                 |   |                      d          j        d         }|#t          j         t          j        |          z  }nt          j        |          }|"t          j        t          j        |          z  }nt          j        |          }fd}g }	d}
d}	 ||
z
  }|                      t          ||z                      }|t          ||z            z  }|||k    ||k    z                      d                   }t          j        |          }|
|j        d         z  }
|		                    |           t          |
           |
|k    rnt          j        |	          }t          |j                   |
|j        d         k    sJ  ||                              d          }|r|S ||
dz  |z  z  S )	a  calculate expected value of function by Monte Carlo integration

    Parameters
    ----------
    dist : distribution instance
        needs to have rvs defined as a method for drawing random numbers
    func : callable
        function for which expectation is calculated, this function needs to
        be vectorized, integration is over axis=0
    size : int
        minimum number of random samples to use in the Monte Carlo integration,
        the actual number used can be larger because of oversampling.
    lower : None or array_like
        lower integration bounds, if None, then it is set to -inf
    upper : None or array_like
        upper integration bounds, if None, then it is set to +inf
    conditional : bool
        If true, then the expectation is conditional on being in within
        [lower, upper] bounds, otherwise it is unconditional
    overfact : float
        oversampling factor, the actual number of random variables drawn in
        each attempt are overfact * remaining draws. Extra draws are also
        used in the integration.


    Notes
    -----
    this does not batch

    Returns
    -------
    expected value : ndarray
        return of function func integrated over axis=0 by MonteCarlo, this will
        have the same shape as the return of func without axis=0

    Examples
    --------
    >>> mvn = mve.MVNormal([0,0],2.)
    >>> mve.expect_mc_bounds(mvn, lambda x: np.ones(x.shape[0]),
                                lower=[-10,-10],upper=[0,0])
    0.24990416666666668

    get 3 marginal moments with one integration

    >>> mvn = mve.MVNormal([0,0],1.)
    >>> mve.expect_mc_bounds(mvn, lambda x: np.dstack([x, x**2, x**3, x**4]),
        lower=[-np.inf,-np.inf], upper=[np.inf,np.inf])
    array([[  2.88629497e-03,   9.96706297e-01,  -2.51005344e-03,
              2.95240921e+00],
           [ -5.48020088e-03,   9.96004409e-01,  -2.23803072e-02,
              2.96289203e+00]])
    >>> from scipy import stats
    >>> [stats.norm.moment(i) for i in [1,2,3,4]]
    [0.0, 1.0, 0.0, 3.0]


    r   r   Nc                      |           S r   r	   r   s    r   r   zexpect_mc_bounds.<locals>.fun  r   r   r   T      ?)r   shapenpinfonesasarrayintall
atleast_2dappendprintvstackr   )r   r   r   lowerupperconditionaloverfactrvsdimr   rvsliusedtotalremainr   rvsokmean_conditionals    `              r   expect_mc_boundsr8      s   x XX1X#B'F}"'&//)
5!!}(
5!!     EDEhhC 122h33TH_%%%cUlse|499"==>e$$AUd4<< )E

C	#)39Q<s3xx}}Q'' 64"9u#455r   c                    t          j        |           \  }}|\  }}t          j        |          \  }}}	}
t          j        |          t          j        |
          }
}||z
  }||z
  }|||
z  z  }|dz  |dz  z  |dz  |
dz  z  z   d|z  |z  |z  ||
z  z  z
  }dt           j        z  |z  |
z  t          j        d|dz  z
            z  }t          j        | dd|dz  z
  z  z            |z  S )z
    Bivariate Gaussian distribution for equal shape *X*, *Y*.

    See `bivariate normal
    <http://mathworld.wolfram.com/BivariateNormalDistribution.html>`_
    at mathworld.
       r   )r#   	transposeravelsqrtpiexp)r   mucovXYmuxmuysigmaxsigmaxytmpsigmayXmuYmurhozdenoms                   r   bivariate_normalrO   0  s     <??DAqHC#%8C== FGS&WV__bgfooFF
C%C
C%C
6&=
!CQvqy36&!)++aeCimVF].KKAbeGFN6!"'!CF("3"33E6A2q!CF(|$%%--r   c                   L    e Zd Zd ZddZd Zd Zd Zd dd	fd
Zd Z	ddZ
dS )BivariateNormalc                     t           | _        || _        t          j        |          \  | _        | _        }| _        d| _        d S )Nr:   )	r@   r   rA   r#   r<   rF   rG   rI   nvars)selfr   rA   rH   s       r   __init__zBivariateNormal.__init__L  s7    	68hsmm3T\3


r   r   c                 Z    t           j                            | j        | j        |          S )Nr   r#   randommultivariate_normalr   rA   rT   r   s     r   r   zBivariateNormal.rvsR  s#    y,,TYt,LLLr   c                 8    t          || j        | j                  S r   )rO   r   rA   rT   r   s     r   pdfzBivariateNormal.pdfU  s    49dh777r   c                 P    t          j        |                     |                    S r   )r#   logr]   r\   s     r   logpdfzBivariateNormal.logpdfX  s    vdhhqkk"""r   c                 .    |                      |          S )N)r.   expectr\   s     r   cdfzBivariateNormal.cdf\  s    {{{###r   c                     dS r   r	   r
   s    r   r   zBivariateNormal.<lambda>_  s    A r   rg   
   ri   c                 d      fd}ddl m}  ||d         d         fdfd          S )Nc                 r    t          j        | |f          }  |                               |           z  S r   )r#   column_stackr]   )r   yr   rT   s     r   r   z#BivariateNormal.expect.<locals>.fun`  s3    1&&A477TXXa[[((r   r   dblquadc                     d         S r   r	   rm   r-   s    r   r   z(BivariateNormal.expect.<locals>.<lambda>d  s    %( r   c                     d         S r   r	   rm   r.   s    r   r   z(BivariateNormal.expect.<locals>.<lambda>e  s    q r   scipy.integratero   )rT   r   r-   r.   r   ro   s   ````  r   rc   zBivariateNormal.expect_  sr    	) 	) 	) 	) 	) 	) 	,+++++wsE!HeAh0B0B0B0B))))+ + 	+r   c                 <      fd}                      |          S )a  Kullback-Leibler divergence between this and another distribution

        int f(x) (log f(x) - log g(x)) dx

        where f is the pdf of self, and g is the pdf of other

        uses double integration with scipy.integrate.dblquad

        limits currently hardcoded

        c                 Z                         |                                |           z
  S r   r`   r   otherrT   s    r   r   z$BivariateNormal.kl.<locals>.<lambda>s       Q%,,q//9 r   rb   )rT   rz   r   s   `` r   klzBivariateNormal.klg  s)     :9999{{3r     c                 x      fd}                      |          } ||                                          S )Nc                 Z                         |                                |           z
  S r   rx   ry   s    r   r   z'BivariateNormal.kl_mc.<locals>.<lambda>w  r{   r   r   r   )rT   rz   r   r   r   s   ``   r   kl_mczBivariateNormal.kl_mcv  s>    99999hhDh!!s3xx}}r   Nr   )r}   )__name__
__module____qualname__rU   r   r]   r`   rd   rc   r|   r   r	   r   r   rQ   rQ   F  s          M M M M8 8 8# # #$ $ $ &+Yg + + + +          r   rQ   c                       e Zd ZdZd ZddZd Zd Zd Zd Z	d	 Z
d
 Zd Zd ZddZddZed             Zed             Zed             ZeZd ZdS )MVEllipticalzBase Class for multivariate elliptical distributions, normal and t

    contains common initialization, and some common methods
    subclass needs to implement at least rvs and logpdf methods

    c                    g | _         t          j        |          | _        t          j        |          x| _        }t          j        |          }t          |          x| _        }|j        dk    rgt          j	        |          |z  | _        t          j	        |          |z  | _
        t          j	        |          t          j        |          z  | _        n|j        dk    rwt          |          |k    rdt          j        |          | _        t          j        d|z            | _
        t          j        dt          j        |          z            | _        no|j        ||fk    rSt          j                            |          | _
        t          j                            | j
                  j        | _        nt'          d          t          j        t          j                            | j                            | _        dS )  initialize instance

        Parameters
        ----------
        mean : array_like
            parameter mu (might be renamed), for symmetric distributions this
            is the mean
        sigma : array_like, 2d
            dispersion matrix, covariance matrix in normal distribution, but
            only proportional to covariance matrix in t distribution
        args : list
            distribution specific arguments, e.g. df for t distribution
        kwds : dict
            currently not used

        r	   r   r!   zsigma has invalid shapeN)
extra_argsr#   r&   r   sigmasqueezelenrS   r"   eyesigmainvr=   cholsigmainvndimdiaglinalgpinvcholeskyT
ValueErrorr_   detlogdetsigma)rT   r   r   argskwdsrS   s         r   rU   zMVElliptical.__init__  s   $ Jt$$	Z...
U
5!! YY&
U
 ;".DJF5MME1DM "u >DjAooCJJ%$7$7DJGBJ//DM "bgenn)< = =D[UEN**INN511DM "	 2 24= A A CD6777 6")--
";";<<r   r   c                     t           )a~  random variable

        Parameters
        ----------
        size : int or tuple
            the number and shape of random variables to draw.

        Returns
        -------
        rvs : ndarray
            the returned random variables with shape given by size and the
            dimension of the multivariate random vector as additional last
            dimension


        NotImplementedErrorrZ   s     r   r   zMVElliptical.rvs  
    " "!r   c                     t           )  logarithm of probability density function

        Parameters
        ----------
        x : array_like
            can be 1d or 2d, if 2d, then each row is taken as independent
            multivariate random vector

        Returns
        -------
        logpdf : float or array
            probability density value of each random vector


        this should be made to work with 2d x,
        with multivariate normal vector in each row and iid across rows
        does not work now because of dot in whiten

        r   r\   s     r   r`   zMVElliptical.logpdf  s
    , "!r   c                     t           a  cumulative distribution function

        Parameters
        ----------
        x : array_like
            can be 1d or 2d, if 2d, then each row is taken as independent
            multivariate random vector
        kwds : dict
            contains options for the numerical calculation of the cdf

        Returns
        -------
        cdf : float or array
            probability density value of each random vector

        r   rT   r   r   s      r   rd   zMVElliptical.cdf  r   r   c                     t           )z^affine transformation define in subclass because of distribution
        specific restrictionsr   )rT   shiftscale_matrixs      r   affine_transformedzMVElliptical.affine_transformed  s
     "!r   c                 h    t          j        |          }t          j        || j        j                  S )aG  
        whiten the data by linear transformation

        Parameters
        ----------
        x : array_like, 1d or 2d
            Data to be whitened, if 2d then each row contains an independent
            sample of the multivariate random vector

        Returns
        -------
        np.dot(x, self.cholsigmainv.T)

        Notes
        -----
        This only does rescaling, it does not subtract the mean, use standardize
        for this instead

        See Also
        --------
        standardize : subtract mean and rescale to standardized random variable.
        )r#   r&   dotr   r   r\   s     r   whitenzMVElliptical.whiten  s)    . JqMMva*,---r   c                 P    t          j        |                     |                    S aO  probability density function

        Parameters
        ----------
        x : array_like
            can be 1d or 2d, if 2d, then each row is taken as independent
            multivariate random vector

        Returns
        -------
        pdf : float or array
            probability density value of each random vector

        r#   r?   r`   r\   s     r   r]   zMVElliptical.pdf  s     vdkk!nn%%%r   c                 <    |                      || j        z
            S )a  standardize the random variable, i.e. subtract mean and whiten

        Parameters
        ----------
        x : array_like, 1d or 2d
            Data to be whitened, if 2d then each row contains an independent
            sample of the multivariate random vector

        Returns
        -------
        np.dot(x - self.mean, self.cholsigmainv.T)

        Notes
        -----


        See Also
        --------
        whiten : rescale random variable, standardize without subtracting mean.


        )r   r   r\   s     r   standardizezMVElliptical.standardize$  s    . {{1ty=)))r   c                 D    |                      | j         | j                  S )z2return new standardized MVNormal instance
        )r   r   r   rT   s    r   standardizedzMVElliptical.standardized=  s!     &&	z43DEEEr   c                 N    t          j        | j                  }|| j        z
  |z  S )a3  normalize the random variable, i.e. subtract mean and rescale

        The distribution will have zero mean and sigma equal to correlation

        Parameters
        ----------
        x : array_like, 1d or 2d
            Data to be whitened, if 2d then each row contains an independent
            sample of the multivariate random vector

        Returns
        -------
        (x - self.mean)/std_sigma

        Notes
        -----


        See Also
        --------
        whiten : rescale random variable, standardize without subtracting mean.


        )r#   r)   	std_sigmar   )rT   r   std_s      r   	normalizezMVElliptical.normalizeC  s&    2 }T^,,DIt##r   Tc                      |rt          j         j                  }n j         j        z  } j        } fd j        D             }  j        ||g|R  S )zwreturn a normalized distribution where sigma=corr

        if demeaned is True, then mean will be set to zero

        c                 0    g | ]}t          |          S r	   getattr.0earT   s     r   
<listcomp>z+MVElliptical.normalized.<locals>.<listcomp>j  #    <<<bb!!<<<r   )r#   
zeros_liker   r   corrr   	__class__)rT   demeanedmean_new	sigma_newr   s   `    r   
normalizedzMVElliptical.normalized_  sl      	2}TY//HHy4>1HI	<<<<DO<<<t~h	9D9999r   c                     |r	| j          }n| j         d| j        z  dz
  z  }|                     |t          j        d| j        z                      S )z}return a normalized distribution where sigma=corr



        second implementation for testing affine transformation
        r!   )r   r   r   r#   r   )rT   r   r   s      r   normalized2zMVElliptical.normalized2m  sV      	;YJEEIdn!4r!9:E&&ubgb4>6I.J.JKKKr   c                 X    t          j        t          j        | j                            S )zDstandard deviation, square root of diagonal elements of cov
        )r#   r=   r   rA   r   s    r   stdzMVElliptical.std~  s      wrwtx(()))r   c                 X    t          j        t          j        | j                            S )zFstandard deviation, square root of diagonal elements of sigma
        )r#   r=   r   r   r   s    r   r   zMVElliptical.std_sigma  s      wrwtz**+++r   c                 P    | j         t          j        | j        | j                  z  S )zcorrelation matrix)rA   r#   outerr   r   s    r   r   zMVElliptical.corr  s!     x"(48TX6666r   c                      t          j        |          } j        |         } j        |dddf         |f         } fd j        D             }  j        ||g|R  S )a  return marginal distribution for variables given by indices

        this should be correct for normal and t distribution

        Parameters
        ----------
        indices : array_like, int
            list of indices of variables in the marginal distribution

        Returns
        -------
        mvdist : instance
            new instance of the same multivariate distribution class that
            contains the marginal distribution of the variables given in
            indices

        Nc                 0    g | ]}t          |          S r	   r   r   s     r   r   z)MVElliptical.marginal.<locals>.<listcomp>  r   r   )r#   r&   r   r   r   r   )rT   indicesr   r   r   s   `    r   marginalzMVElliptical.marginal  st    $ *W%%9W%Jwqqqv78	<<<<DO<<<t~h	9D9999r   Nr   )T)r   r   r   __doc__rU   r   r`   rd   r   r   r]   r   r   r   r   r   propertyr   r   r   r   r   r	   r   r   r   r   {  sP        -= -= -=^" " " "&" " "0" " "(" " ". . .4& & &"* * *2F F F$ $ $8: : : :L L L L" * * X*
 , , X, 7 7 X7 I: : : : :r   r   c                   6    e Zd ZdZd Zd Zd	dZd Zd Ze	Z	dS )
	MVNormal0zClass for Multivariate Normal Distribution

    original full version, kept for testing, new version inherits from
    MVElliptical

    uses Cholesky decomposition of covariance matrix for the transformation
    of the data

    c                    || _         t          j        |          x| _        }t          j        |          }t          |          x| _        }|j        dk    rgt          j        |          |z  | _        t          j        |          |z  | _	        t          j        |          t          j
        |          z  | _        n|j        dk    rwt          |          |k    rdt          j        |          | _        t          j        d|z            | _	        t          j        dt          j
        |          z            | _        no|j        ||fk    rSt          j                            |          | _	        t          j                            | j	                  j        | _        nt%          d          t          j        t          j                            | j                            | _        d S )Nr	   r   r!   zcov has invalid shape)r   r#   r&   rA   r   r   rS   r"   r   covinvr=   
cholcovinvr   r   r   r   r   r   r   r_   r   	logdetcov)rT   r   rA   rS   s       r   rU   zMVNormal0.__init__  sh   	C(3joo YY&
U 9??ve}}s*DH&--#-DK fUmmbgcll:DOOh!mm#c((e"3"3ws||DH'"s(++DK grBGCLL'899DOOY5%.(()..--DK i00==?DOO4555 	dh 7 788r   c                     t          j        |          }t          j        | j                  rt          j        || j        j                  S |S )aE  
        whiten the data by linear transformation

        Parameters
        ----------
        X : array_like, 1d or 2d
            Data to be whitened, if 2d then each row contains an independent
            sample of the multivariate random vector

        Returns
        -------
        np.dot(x, self.cholcovinv.T)

        Notes
        -----
        This only does rescaling, it does not subtract the mean, use standardize
        for this instead

        See Also
        --------
        standardize : subtract mean and rescale to standardized random variable.
        )r#   r&   anyrA   r   r   r   r\   s     r   r   zMVNormal0.whiten  sA    . JqMM6$( 	6!T_.///Hr   r   c                 Z    t           j                            | j        | j        |          S a  random variable

        Parameters
        ----------
        size : int or tuple
            the number and shape of random variables to draw.

        Returns
        -------
        rvs : ndarray
            the returned random variables with shape given by size and the
            dimension of the multivariate random vector as additional last
            dimension

        Notes
        -----
        uses numpy.random.multivariate_normal directly

        r   rW   rZ   s     r   r   zMVNormal0.rvs  s%    ( y,,TYt,LLLr   c                 P    t          j        |                     |                    S r   r   r\   s     r   r]   zMVNormal0.pdf  s      vdkk!nn%%%r   c                    t          j        |          }|                     || j        z
            }t          j        |dz  d          }| }|| j        t          j        dt           j        z            z  z  }|| j        z  }|dz  }|S r   r:   r          @      ?)	r#   r&   r   r   sumrS   r_   r>   r   rT   r   
x_whitenedSSRllfs        r   r`   zMVNormal0.logpdf  s    ( JqMM[[TY//
fZ]B''dtzBF2:....t~s

r   Nr   )
r   r   r   r   rU   r   r   r]   r`   r   r	   r   r   r   r     ss         9 9 98  <M M M M,& & &$  : IIIr   r   c                   T    e Zd ZdZe dk     ddZd Zd Zed             Zd Z	d	 Z
d
S )MVNormalzClass for Multivariate Normal Distribution

    uses Cholesky decomposition of covariance matrix for the transformation
    of the data

    z Multivariate Normal Distributionr   c                 Z    t           j                            | j        | j        |          S r   )r#   rX   rY   r   r   rZ   s     r   r   zMVNormal.rvsD  s%    ( y,,TY
,NNNr   c                    t          j        |          }|                     || j        z
            }t          j        |dz  d          }| }|| j        t          j        dt           j        z            z  z  }|| j        z  }|dz  }|S r   )	r#   r&   r   r   r   rS   r_   r>   r   r   s        r   r`   zMVNormal.logpdfZ  s    ( JqMM[[TY//
fZ]B''dtzBF2:....ts

r   c                 4    t          || j        | j        fi |S r   )r   r   rA   r   s      r   rd   zMVNormal.cdfw  s"    & DItx884888r   c                     | j         S )zcovariance matrix)r   r   s    r   rA   zMVNormal.cov  s     zr   c                     |}t          j        || j                  |z   }t          j        t          j        || j                  |j                  }t          ||          S )a,  return distribution of an affine transform

        for full rank scale_matrix only

        Parameters
        ----------
        shift : array_like
            shift of mean
        scale_matrix : array_like
            linear transformation matrix

        Returns
        -------
        mvt : instance of MVNormal
            instance of multivariate normal distribution given by affine
            transformation

        Notes
        -----
        the affine transformation is defined by
        y = a + B x

        where a is shift,
        B is a scale matrix for the linear transformation

        Notes
        -----
        This should also work to select marginal distributions, but not
        tested for this case yet.

        currently only tested because it's called by standardized

        )r#   r   r   r   r   r   rT   r   r   Br   r   s         r   r   zMVNormal.affine_transformed  sS    D 6!TY''%/F26!TZ00!#66	),,,r   c           
        
 t          j        |          
t          j        
fdt          | j                  D                       }| j        
dddf         
f         }| j        |dddf         |f         }| j        
dddf         |f         }| j        |dddf         
f         }|t          j        |t           j                            ||                    z
  }| j        
         t          j        |t           j                            ||| j        |         z
                      z   }	t          |	|          S )ai  return conditional distribution

        indices are the variables to keep, the complement is the conditioning
        set
        values are the values of the conditioning variables

        \bar{\mu} = \mu_1 + \Sigma_{12} \Sigma_{22}^{-1} \left( a - \mu_2 \right)

        and covariance matrix

        \overline{\Sigma} = \Sigma_{11} - \Sigma_{12} \Sigma_{22}^{-1} \Sigma_{21}.T

        Parameters
        ----------
        indices : array_like, int
            list of indices of variables in the marginal distribution
        given : array_like
            values of the conditioning variables

        Returns
        -------
        mvn : instance of MVNormal
            new instance of the MVNormal class that contains the conditional
            distribution of the variables given in indices for given
             values of the excluded variables.


        c                     g | ]}|v|	S r	   r	   )r   ikeeps     r   r   z(MVNormal.conditional.<locals>.<listcomp>  s    JJJ!ATMMAMMMr   N)
r#   r&   rangerS   r   r   r   solver   r   )rT   r   valuesgivensigmakksigmaggsigmakgsigmagkr   r   r   s             @r   r/   zMVNormal.conditional  s,   < z'""
JJJJuTZ'8'8JJJKK*T!!!T']D01*U111d7^U23*T!!!T']E12*U111d7^T12 bfWbioogw.O.OPPP	9T?F7BIOOGVDIe<L5LMMNNO ),,,r   Nr   )r   r   r   r   r   r`   rd   r   rA   r   r/   r	   r   r   r   r   :  s          222O O O O,  :9 9 9*   X%- %- %-N.- .- .- .- .-r   r   c                   Z     e Zd Ze dk      fdZd	dZd Zd Zed             Zd Z	 xZ
S )
MVTz#Multivariate Student T Distributionc                 j    t                                          ||           dg| _        || _        dS )r   dfN)superrU   r   r   )rT   r   r   r   r   s       r   rU   zMVT.__init__  s3    " 	u%%%&r   r   c                 J    ddl m}  || j        | j        | j        |          S )a{  random variables with Student T distribution

        Parameters
        ----------
        size : int or tuple
            the number and shape of random variables to draw.

        Returns
        -------
        rvs : ndarray
            the returned random variables with shape given by size and the
            dimension of the multivariate random vector as additional last
            dimension
            - TODO: Not sure if this works for size tuples with len>1.

        Notes
        -----
        generated as a chi-square mixture of multivariate normal random
        variables.
        does this require df>2 ?


        r   )multivariate_t_rvs)r   n)multivariater  r   r   r   )rT   r   r  s      r   r   zMVT.rvs  s6    0 	544444!!$)TZDGtLLLLr   c           	         t          j        |          }| j        }| j        }|                     || j        z
            }| t          |t          z            z  }|| j        z  }|||z   t          dt          j	        |dz  d          |z  z             z  z  }|dz  }|t          ||z   dz            t          |dz            z
  z  }|S )a_  logarithm of probability density function

        Parameters
        ----------
        x : array_like
            can be 1d or 2d, if 2d, then each row is taken as independent
            multivariate random vector

        Returns
        -------
        logpdf : float or array
            probability density value of each random vector

        r   r:   r   r   r   )r#   r&   r   rS   r   r   np_lognp_pir   r   	sps_gamln)rT   r   r   rS   r   r   s         r   r`   z
MVT.logpdf#  s      JqMMW
[[TY//
grEz***tU
fQ
Ab)A)AB)F%FGGGGs
y"u**++iR.@.@@@
r   c                     t           j         t          j        |          z  }|| j        z
  | j        z  }t          ||| j        | j        fi |S r   )r#   r$   	ones_liker   r   r   r   r   )rT   r   r   r-   r.   s        r   rd   zMVT.cdfB  sL    " ",q//)TY.%	47CCdCCCr   c                     | j         dk    r&t          j        t          j        | j                  z  S | j         | j         dz
  z  | j        z  S )zcovariance matrix

        The covariance matrix for the t distribution does not exist for df<=2,
        and is equal to sigma * df/(df-2) for df>2

        r:   r   )r   r#   nanr  r   r   s    r   rA   zMVT.covZ  sB     7a<<6BL44447dgl+dj88r   c                    |}|j         | j        | j        fk    sDt          j                            |          dk                                    rt          d          t          j        || j                  |z   }t          j        t          j        || j	                  |j
                  }t          ||| j                  S )a^  return distribution of a full rank affine transform

        for full rank scale_matrix only

        Parameters
        ----------
        shift : array_like
            shift of mean
        scale_matrix : array_like
            linear transformation matrix

        Returns
        -------
        mvt : instance of MVT
            instance of multivariate t distribution given by affine
            transformation


        Notes
        -----

        This checks for eigvals<=0, so there are possible problems for cases
        with positive eigenvalues close to zero.

        see: http://www.statlect.com/mcdstu1.htm

        I'm not sure about general case, non-full rank transformation are not
        multivariate t distributed.

        y = a + B x

        where a is shift,
        B is full rank scale matrix with same dimension as sigma

        r   z$affine transform has to be full rank)r"   rS   r#   r   eigvalsr   r   r   r   r   r   r   r   r   s         r   r   zMVT.affine_transformedg  s    L w4:tz222	!!!$$)..00 I !GHHH6!TY''%/F26!TZ00!#66	8Y000r   r   )r   r   r   rU   r   r`   rd   r   rA   r   __classcell__)r   s   @r   r   r     s        555    *M M M M8  >D D D0 
9 
9 X
9-1 -1 -1 -1 -1 -1 -1r   r   c                     dS r   r	   r
   s    r   r   r     s    ! r   rf   rh   c                 `      fd}ddl m}  ||d         d         fdfd          S )Nc                 F    t          j        | |f          }  |           S r   )r#   rl   )r   rm   r   s     r   r   zquad2d.<locals>.fun  s#    OQqE""tAwwr   r   rn   c                     d         S r   r	   rq   s    r   r   zquad2d.<locals>.<lambda>  s    eAh r   c                     d         S r   r	   rs   s    r   r   zquad2d.<locals>.<lambda>  s    U1X r   rt   )r   r-   r.   r   ro   s   ```  r   quad2dr    sl         ('''''73a%(,>,>,>,>%%%%' ' 'r   __main__)assert_almost_equalassert_array_almost_equalmvn)r   r   r!   r   )r           r   )r!   r         ?)r   g      ?333333?)r  r  r   i  r   )rowvarr:      c                     t          j        t                              |                     t          j        t                              |                     z
  S r   )r#   r_   bvn1r]   bvnr
   s    r   r   r     s3    ,,rvcggajj/A/AA r   )r:   r:   )r  r   g      @)g&Ng&Ng&N   )decimal)gue>?g7P?gTw?   )r   r   r   )gEOQם?g4x=?g9"8?   c                     t          j        t                              |                     t          j        t                              |                     z
  S r   )r#   r_   mvn3r]   mvn3br
   s    r   r   r     s3    ,,rveiill/C/CC r   i@    r  gdg   gm0_?gX*#g!4i )g<G?gx-ZP?gD5If?      )gvML?gzDT?g/o6q?):r   numpyr#   scipyr   .statsmodels.sandbox.distributions.multivariater   extrasr   r   r8   rO   rQ   r   r   r   r_   r  r>   r  gammalnr	  r   r  r   numpy.testingr  r  examplesr@   arraycovxmu3cov3r"  r   r+   r   rA   rc   rd   r   r!  bvn2r   r|   r   r  r]   zerosr(  r`   r_valmvn3cr)  mvtmvt1mvt31r	   r   r   <module>r@     s^  P Pb           E E E E E E       %5 1 1 1 1f !,%t4!&a6 a6 a6 a6H. . .,3 3 3 3 3 3 3 3jm: m: m: m: m: m: m: m:b	K K K K K K K K\l- l- l- l- l-| l- l- l-` 

O	f1 f1 f1 f1 f1, f1 f1 f1R 9G ' ' ' ' zLLLLLLLLwH	B28c3Z#s,--D
,,C28*********, - -D
 ob$''gg4g  chhqkkfbfS###$$$cjjllcggqennr626!99--r1VRVAYY;//AAdkk#dggdmmTZZ--...dggdmmTZZ--...dggcllDJJsOO,,,hr4  1    rx.........0 1 1 llxT""L!!! MLL!!4;;t#4#4erJJJJRRR!!488D>>5BGGGG '''**D11OOO!!599T??ERHHHH!$$CCdnnS!!"""dnnSvn../// #eQ

C

828RG#4#4557I "$ $ $ $"R 1 1224F "$ $ $ $ JJxrxB  !!#4553uaDKK"R!!""$566
''&//Cs1---swBBBBCT1E		$MMM    #c4

CJJJ     q r   