a
    h                     @   sr   d Z ddlZddlmZmZ ddlZddlmZ ddlmZm	Z	 ddl
mZ ddlmZ dgZG d	d deZdS )
z
This closely follows the implementation in NumPyro (https://github.com/pyro-ppl/numpyro).

Original copyright notice:

# Copyright: Contributors to the Pyro project.
# SPDX-License-Identifier: Apache-2.0
    N)OptionalUnion)Tensor)Betaconstraints)Distribution)broadcast_allLKJCholeskyc                       sp   e Zd ZdZdejiZejZde	e
eef ee dd fddZd fdd		Ze fd
dZdd Z  ZS )r	   a)  
    LKJ distribution for lower Cholesky factor of correlation matrices.
    The distribution is controlled by ``concentration`` parameter :math:`\eta`
    to make the probability of the correlation matrix :math:`M` generated from
    a Cholesky factor proportional to :math:`\det(M)^{\eta - 1}`. Because of that,
    when ``concentration == 1``, we have a uniform distribution over Cholesky
    factors of correlation matrices::

        L ~ LKJCholesky(dim, concentration)
        X = L @ L' ~ LKJCorr(dim, concentration)

    Note that this distribution samples the
    Cholesky factor of correlation matrices and not the correlation matrices
    themselves and thereby differs slightly from the derivations in [1] for
    the `LKJCorr` distribution. For sampling, this uses the Onion method from
    [1] Section 3.

    Example::

        >>> # xdoctest: +IGNORE_WANT("non-deterministic")
        >>> l = LKJCholesky(3, 0.5)
        >>> l.sample()  # l @ l.T is a sample of a correlation 3x3 matrix
        tensor([[ 1.0000,  0.0000,  0.0000],
                [ 0.3516,  0.9361,  0.0000],
                [-0.1899,  0.4748,  0.8593]])

    Args:
        dimension (dim): dimension of the matrices
        concentration (float or Tensor): concentration/shape parameter of the
            distribution (often referred to as eta)

    **References**

    [1] `Generating random correlation matrices based on vines and extended onion method` (2009),
    Daniel Lewandowski, Dorota Kurowicka, Harry Joe.
    Journal of Multivariate Analysis. 100. 10.1016/j.jmva.2009.04.008
    concentration      ?N)dimr
   validate_argsreturnc           
         s   |dk rt d| d|| _t|\| _| j }t||f}| jd| jd   }tj| jd | jj| jj	d}t
|d|g}|d }|dd|  }	t||	| _t ||| d S )	N   zDExpected dim to be an integer greater than or equal to 2. Found dim=.      ?   dtypedevice)r   )
ValueErrorr   r   r
   sizetorchSizearanger   r   catZ	new_zeros	unsqueezer   _betasuper__init__)
selfr   r
   r   batch_shapeevent_shapeZmarginal_concoffsetZ
beta_conc1Z
beta_conc0	__class__ N/var/www/auris/lib/python3.9/site-packages/torch/distributions/lkj_cholesky.pyr    B   s&    

zLKJCholesky.__init__c                    sf   |  t|}t|}| j|_| j||_| j|| jf |_tt|j	|| j
dd | j|_|S )NF)r   )Z_get_checked_instancer	   r   r   r   r
   expandr   r   r    r#   _validate_args)r!   r"   Z	_instancenewr%   r'   r(   r)   ]   s    

zLKJCholesky.expandc                 C   s   | j |d}tj| ||j|jdd}||j	ddd }|ddd d f 
d t|| }t|jj}tjdtj|d	 dd
 |d }|t|7 }|S )Nr   r   T)r   Zkeepdim.r   g        r   r   r   )min)r   sampler   r   ZrandnZ_extended_shaper   r   ZtrilZnormZfill_sqrtZfinfoZtinyclampsumZ
diag_embed)r!   Zsample_shapeyZu_normalZu_hyperspherewZeps
diag_elemsr'   r'   r(   r.   i   s    $zLKJCholesky.samplec                 C   s   | j r| | |jdddddd f }tjd| jd | jjd}d| jd d | j | }tj	||
  dd}| jd }| jd	|  }t|| }t|d	 |}d	| t
tj }	|	| | }
||
 S )
Nr   )Zdim1Zdim2.r   r   )r   r,   r   )r*   Z_validate_sampleZdiagonalr   r   r   r
   r   r   r1   loglgammaZmvlgammamathpi)r!   valuer4   orderZunnormalized_log_pdfZdm1alphadenominator	numeratorZpi_constantZnormalize_termr'   r'   r(   log_prob~   s    


zLKJCholesky.log_prob)r   N)N)__name__
__module____qualname____doc__r   ZpositiveZarg_constraintsZcorr_choleskyZsupportintr   r   floatr   boolr    r)   r   r   r.   r?   __classcell__r'   r'   r%   r(   r	      s   &
  
)rC   r8   typingr   r   r   r   Ztorch.distributionsr   r   Z torch.distributions.distributionr   Ztorch.distributions.utilsr   __all__r	   r'   r'   r'   r(   <module>   s   	