o
    * i5                     @  s   d dl mZ d dlZd dlZd dlmZ d dlmZ d dlm	Z	m
Z
 d dlZd dlmZmZ d dlmZ d dlmZ d d	lmZ d d
lmZ e	rTd dlmZ d dlmZ dgZdd ZdddZdddZ	 d ddZdd!ddZG dd dej Z!dS )"    )annotationsN)Sequence)reduce)TYPE_CHECKINGLiteral)
check_typeconvert_dtype)Variable)distribution)Beta)in_dynamic_mode)Tensor)_DTypeLiteralLKJCholeskyc                 C  sp   t jtj| jd}t jd|d | jd}t | dd| d  }t j|dd}||d  d t 	| | S )zW
    Computes the multivariate log gamma function for input `a` and dimension `p`.
    dtype      axis   )
paddleZ	to_tensormathpir   arangelgamma	unsqueezesumlog)apr   jZgammaln_termsZgammaln_sum r#   l/home/app/PaddleOCR-VL-test/.venv_paddleocr/lib/python3.10/site-packages/paddle/distribution/lkj_cholesky.pymvlgamma%   s
   r%   c                 C  sB   t j| | fdd}t j||d}t j|dd\}}| | fS )zk
    Returns the indices of the lower triangular part of an n x n matrix, including the k-th diagonal.
    Zint32r   diagonalT)as_tuple)r   ZonestrilZnonzeroflatten)nkZfull_matrixZtril_matrixrowscolsr#   r#   r$   tril_indices0   s   r/   c                 C  s*   t jt | |d}t | |d}|S )z|
    Extracts the lower triangular part of the input matrix or batch of matrices `x`, including the specified diagonal.
    r&   bool)r   r)   Z	ones_likemasked_selectZastype)xr'   	tril_maskZtril_elementsr#   r#   r$   matrix_to_tril:   s   r4   r#   c                 C  s   || }g ||t tj|d ||R }tt|t|\}}	||	k}
tj||
 |	|
 gdd}tj||dd}t|d	|dg}tj
||gdd}t|dddf }|| }tj|||f| jd}t||| |}|S )zX
    Constructs a batch of lower triangular matrices from a given input tensor `p`.
    r   r   r   Nshaper   )r   operatormulr   meshgridr   stackZrepeat_interleaver   ZtileconcatZargsortzerosr   Zscatter_nd_addreshape)Z	p_flattendimlast_dimflatten_shapesample_shapediagZshape0output_shaper-   r.   maskZlower_indicesZrepeated_lower_indicesZindex0Zindex_matrixZsorted_indicesmatrixr#   r#   r$   vec_to_tril_matrixC   s2   rF   matr   rB   intreturnc           	      C  s   | j dd }| j d }|| k s||kr&td| d|  d|d  dtt|t|\}}|| |k}|| || d  d	 }||f7 }t|| j }t| ||}|S )
z
    Convert a `D x D` matrix or a batch of matrices into a (batched) vector
    which comprises of lower triangular elements from the matrix in row order.
    Nr   zdiag (z) provided is outside [z, r   z].r   )r6   
ValueErrorr   r9   r   broadcast_tor1   r=   )	rG   rB   Z	out_shaper+   r-   r.   r3   Zvec_lenZvecr#   r#   r$   tril_matrix_to_vecj   s   
"
rM   c                      sx   e Zd ZU dZded< ded< ded< ded	< 	
		dd fddZdddZdddZg fdddZd ddZ	  Z
S )!r   ab  
    The LKJCholesky class represents the LKJ distribution over Cholesky factors of correlation matrices.
    This class implements the LKJ distribution over Cholesky factors of correlation matrices, as described in
    Lewandowski, Kurowicka, and Joe (2009). It supports two sampling methods: "onion" and "cvine".

    Args:
        dim (int): The dimension of the correlation matrices.
        concentration (float, optional): The concentration parameter of the LKJ distribution. Default is 1.0.
        sample_method (str, optional): The sampling method to use, either "onion" or "cvine". Default is "onion".

    Example:
        .. code-block:: python

            >>> import paddle

            >>> dim = 3
            >>> lkj = paddle.distribution.LKJCholesky(dim=dim)
            >>> sample = lkj.sample()
            >>> sample.shape
            [3, 3]
    r   concentrationr   r   rH   r>   Literal['onion', 'cvine']sample_methodr         ?onionfloatrI   Nonec                   s  t  st|dtttjjfd t|dttt	ttjjfd | 
|r,|| _t|j| _n| |\| _t | _|| _| jdksHtd| dt| jtsVtd| dt  ret| jdksetd	|| _| jj}||f}| jd
| jd   }tj| jd | jjd}|dkrttjd|jd|g}|d
 }|dd
|  }	t||	| _n(|dkrttd
| | jd | jd g}
|d|
 }t||| _ntdt  || d S )Nr>   r   rN   r   z3Expected dim greater than or equal to 2. Found dim=.z)Expected dim to be an integer. Found dim=r   z,The arg of `concentration` must be positive.      ?r   r   rR   )r   r   Zcvinez-`method` should be one of 'cvine' or 'onion'.)!r   r   rH   r	   r   ZpirValuerS   listtupleZ_validate_argsrN   r   r   Z
_to_tensorZget_default_dtyper>   rK   
isinstance	TypeErrorallrP   r6   r   r;   r<   r   r   _betar4   rL   super__init__)selfr>   rN   rP   Zbatch_shapeZevent_shapeZmarginal_concoffsetZ
beta_conc1Z
beta_conc0Zoffset_trilZ	beta_conc	__class__r#   r$   r_      sf   



zLKJCholesky.__init__rA   Sequence[int]c                 C  s   | j |d}tj| ||jdd}||jddd }|dddddf }g t	|j
dd d| jR }tj||jd	}tj||gdd
}t|| }t|jj}	tjdtj|d dd
 |	d }
|t|
7 }|S )zGenerate a sample using the "onion" method.

        Args:
            sample_shape (tuple): The shape of the samples to be generated.

        Returns:
            w (Tensor): The Cholesky factor of the sampled correlation matrix.
        r   r   T)r   Zkeepdim.r   NrJ   r5   r   r   )min)r]   sampler   r   ZrandnZ_extend_shaper   r)   ZnormrY   r6   r>   r<   r;   sqrtfinfotinyclipr   Z
diag_embed)r`   rA   yZu_normalZu_hypersphereZu_hypersphere_otherZ
zero_shapeZzero_rowweps
diag_elemsr#   r#   r$   _onion   s    
"$zLKJCholesky._onionc                 C  sB  | j |d}d| d }| jdkr|d}| j| jd  d }|ttj|d }t| jj	dkr<|| jj	d 9 }|
|f}t|| j|||d}t|jj}tj|d| d| d}|d }tjtd| dd}	ddg|	jd  ddg }
tjjj|	dd	df |
d
dd}|t|j	d |j	d 7 }|| }|S )zGenerate a sample using the "cvine" method.

        Args:
            sample_shape (tuple): The shape of the samples to be generated.

        Returns:
            r (Tensor): The Cholesky factor of the sampled correlation matrix.
        r   r   r   rJ   r   )re   max)r>   .NZconstantrQ   )padmodevalue)r]   rf   r   r>   r   r7   r8   lenrN   r6   r=   rF   r   rh   r   ri   rj   Zcumprodrg   ndimnnZ
functionalrq   eye)r`   rA   Zbeta_sampleZpartial_correlationr?   r@   rm   rzZz1m_cumprod_sqrtZ	pad_widthZz1m_cumprod_sqrt_shiftedr#   r#   r$   _cvine  sB   


zLKJCholesky._cvinec                 C  sd   t |ts	td| jdkr| |}n| |}t|}|| jj	 || j
| j
g ||S )z6Generate a sample using the specified sampling method.z%sample shape must be Sequence object.rR   )rZ   r   r[   rP   ro   rz   rX   extendrN   r6   r>   r=   )r`   rA   resrC   r#   r#   r$   rf   ?  s   



zLKJCholesky.samplers   c                 C  s   t j|dddddddf }t jd| jd | jjd	}d| jd d | j | }t j|t | dd
}| jd }| jd|  }t 	|| }t
|d |}d| ttj }	|	| | }
||
 S )a}  Compute the log probability density of the given Cholesky factor under the LKJ distribution.

        Args:
            value (Tensor): The Cholesky factor of the correlation matrix for which the log probability density is to be computed.

        Returns:
            log_prob (Tensor): The log probability density of the given Cholesky factor under the LKJ distribution.
        r   r   rJ   )ra   Zaxis1Zaxis2.r   Nr   r   r   rV   )r   r'   r   r>   rN   r   r   r   r   r   r%   r   r   )r`   rs   rn   orderZunnormalized_log_pdfZdm1alphadenominator	numeratorZpi_constantZnormalize_termr#   r#   r$   log_probO  s   


zLKJCholesky.log_prob)r   rQ   rR   )r>   rH   rN   rS   rP   rO   rI   rT   )rA   rd   rI   r   )rs   r   rI   r   )__name__
__module____qualname____doc____annotations__r_   ro   rz   rf   r   __classcell__r#   r#   rb   r$   r      s   
 
D
&9)r   )r#   r   )rG   r   rB   rH   rI   r   )"
__future__r   r   r7   collections.abcr   	functoolsr   typingr   r   r   Zpaddle.base.data_feederr   r   Zpaddle.base.frameworkr	   Zpaddle.distributionr
   Zpaddle.distribution.betar   Zpaddle.frameworkr   r   Zpaddle._typing.dtype_liker   __all__r%   r/   r4   rF   rM   Distributionr   r#   r#   r#   r$   <module>   s.   




'