o
    * i?                     @  s   d dl mZ d dlZd dlmZ d dlmZ d dlZd dlm	Z	 d dl
mZ er4d dlmZ d dlmZ G d	d
 d
ejZdddZdddZdS )    )annotationsN)Sequence)TYPE_CHECKING)convert_dtype)distribution)Tensor)_DTypeLiteralc                      s   e Zd ZU dZded< ded< ded< ded< ded	< 	
	
	
d#d$ fddZed%ddZed%ddZg fd&ddZ	g fd&ddZ
d'ddZd'ddZd%ddZd(d!d"Z  ZS ))MultivariateNormala  The Multivariate Normal distribution is a type multivariate continuous distribution defined on the real set, with parameter: `loc` and any one
    of the following parameters characterizing the variance: `covariance_matrix`, `precision_matrix`, `scale_tril`.

    Mathematical details

    The probability density function (pdf) is

    .. math::

        p(X ;\mu, \Sigma) = \frac{1}{\sqrt{(2\pi)^k |\Sigma|}} \exp(-\frac{1}{2}(X - \mu)^{\intercal} \Sigma^{-1} (X - \mu))

    In the above equation:

    * :math:`X`: is a k-dim random vector.
    * :math:`loc = \mu`: is the k-dim mean vector.
    * :math:`covariance_matrix = \Sigma`: is the k-by-k covariance matrix.

    Args:
        loc(int|float|Tensor): The mean of Multivariate Normal distribution. If the input data type is int or float, the data type of `loc` will be
            convert to a 1-D Tensor the paddle global default dtype.
        covariance_matrix(Tensor|None): The covariance matrix of Multivariate Normal distribution. The data type of `covariance_matrix` will be convert
            to be the same as the type of loc.
        precision_matrix(Tensor|None): The inverse of the covariance matrix. The data type of `precision_matrix` will be convert to be the same as the
            type of loc.
        scale_tril(Tensor|None): The cholesky decomposition (lower triangular matrix) of the covariance matrix. The data type of `scale_tril` will be
            convert to be the same as the type of loc.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> from paddle.distribution import MultivariateNormal
            >>> paddle.set_device("cpu")
            >>> paddle.seed(100)

            >>> rv = MultivariateNormal(loc=paddle.to_tensor([2.,5.]), covariance_matrix=paddle.to_tensor([[2.,1.],[1.,2.]]))

            >>> print(rv.sample([3, 2]))
            Tensor(shape=[3, 2, 2], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[[-0.00339603,  4.31556797],
              [ 2.01385283,  4.63553190]],
             [[ 0.10132277,  3.11323833],
              [ 2.37435842,  3.56635118]],
             [[ 2.89701366,  5.10602522],
              [-0.46329355,  3.14768648]]])

            >>> print(rv.mean)
            Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
            [2., 5.])

            >>> print(rv.variance)
            Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
            [1.99999988, 2.        ])

            >>> print(rv.entropy())
            Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
            3.38718319)

            >>> rv1 = MultivariateNormal(loc=paddle.to_tensor([2.,5.]), covariance_matrix=paddle.to_tensor([[2.,1.],[1.,2.]]))
            >>> rv2 = MultivariateNormal(loc=paddle.to_tensor([-1.,3.]), covariance_matrix=paddle.to_tensor([[3.,2.],[2.,3.]]))
            >>> print(rv1.kl_divergence(rv2))
            Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
            1.55541301)
    r   locTensor | Nonecovariance_matrixprecision_matrix
scale_trilr   dtypeNfloat | Tensorc                   s<  t  | _t|ttfrt j|g| jd}nt|j| _| dk r'|	d}d | _
d | _d | _|d u|d u |d u dkrBtd|d ur{| dk rPtdt j|| jd}t |jd d |jd d }|g ||jd |jd | _nm|d ur| dk rtd	t j|| jd}t |jd d |jd d }|g ||jd |jd | _
n4| dk rtd
t j|| jd}t |jd d |jd d }|g ||jd |jd | _|g |d| _| jjdd  }|d ur|| _n|d urt j|| _nt|| _t || d S )Nr      )r   zTExactly one of covariance_matrix or precision_matrix or scale_tril may be specified.   zZscale_tril matrix must be at least two-dimensional, with optional leading batch dimensionszZcovariance_matrix must be at least two-dimensional, with optional leading batch dimensionszYprecision_matrix must be at least two-dimensional, with optional leading batch dimensions)paddleZget_default_dtyper   
isinstancefloatintZ	to_tensorr   dimreshaper   r   r   
ValueErrorcastZbroadcast_shapeshapeexpandr
   _unbroadcasted_scale_trillinalgcholeskyprecision_to_scale_trilsuper__init__)selfr
   r   r   r   Zbatch_shapeZevent_shape	__class__ s/home/app/PaddleOCR-VL-test/.venv_paddleocr/lib/python3.10/site-packages/paddle/distribution/multivariate_normal.pyr%   e   s   



zMultivariateNormal.__init__returnc                 C  s   | j S )zdMean of Multivariate Normal distribution.

        Returns:
            Tensor: mean value.
        )r
   r&   r)   r)   r*   mean   s   zMultivariateNormal.meanc                 C  s    t | jd| j| j S )zlVariance of Multivariate Normal distribution.

        Returns:
            Tensor: variance value.
        r   )r   Zsquarer    sumr   _batch_shape_event_shaper,   r)   r)   r*   variance   s   
zMultivariateNormal.variancer   Sequence[int]c                 C  s6   t   | |W  d   S 1 sw   Y  dS )  Generate Multivariate Normal samples of the specified shape. The final shape would be ``sample_shape + batch_shape + event_shape``.

        Args:
            shape (Sequence[int], optional): Prepended shape of the generated samples.

        Returns:
            Tensor, Sampled data with shape `sample_shape` + `batch_shape` + `event_shape`. The data type is the same as `self.loc`.
        N)r   Zno_gradrsample)r&   r   r)   r)   r*   sample   s   
	$zMultivariateNormal.samplec                 C  sT   t |ts	td| |}tjtj|d| jd}| jt	| j
|dd S )r3   z%sample shape must be Sequence object.)r   r   r   )r   r   	TypeErrorZ_extend_shaper   r   normalr   r
   matmulr    Z	unsqueezeZsqueeze)r&   r   Zoutput_shapeZepsr)   r)   r*   r4      s   
	
zMultivariateNormal.rsamplevaluec                 C  sf   t j|| jd}|| j }t| j|}| jjddd d}d| j	d t
dt
j  |  | S )zLog probability density function.

        Args:
          value (Tensor): The input tensor.

        Returns:
          Tensor: log probability. The data type is the same as `self.loc`.
        r   r   r   Zaxis1Zaxis2g      r   r   )r   r   r   r
   batch_mahalanobisr    diagonallogr.   r0   mathpi)r&   r9   diffMhalf_log_detr)   r)   r*   log_prob   s   	
 zMultivariateNormal.log_probc                 C  s   t | |S )zProbability density function.

        Args:
            value (Tensor): The input tensor.

        Returns:
            Tensor: probability. The data type is the same as `self.loc`.
        )r   exprC   )r&   r9   r)   r)   r*   prob  s   	zMultivariateNormal.probc                 C  s^   | j jddd d}d| jd  dtdtj   | }t| jdkr)|S |	| jS )a  Shannon entropy in nats.

        The entropy is

        .. math::

            \mathcal{H}(X) = \frac{n}{2} \log(2\pi) + \log {\det A} + \frac{n}{2}

        In the above equation:

        * :math:`\Omega`: is the support of the distribution.

        Returns:
            Tensor, Shannon entropy of Multivariate Normal distribution. The data type is the same as `self.loc`.
        r   r   r:         ?r   g      ?r   )
r    r<   r=   r.   r0   r>   r?   lenr/   r   )r&   rB   Hr)   r)   r*   entropy  s    zMultivariateNormal.entropyotherc                 C  s   | j |j kr| j|jkrtd| jjddd d}|jjddd d}ttt	| jj
}|d |d |d< |d< t| j| j|}t|j|j|}tj||jdddd}|t|j| j|j 7 }|| d|| jd    S )a^  The KL-divergence between two poisson distributions with the same `batch_shape` and `event_shape`.

        The probability density function (pdf) is

        .. math::

            KL\_divergence(\lambda_1, \lambda_2) = \log(\det A_2) - \log(\det A_1) -\frac{n}{2} +\frac{1}{2}[tr [\Sigma_2^{-1} \Sigma_1] + (\mu_1 - \mu_2)^{\intercal} \Sigma_2^{-1}  (\mu_1 - \mu_2)]

        Args:
            other (MultivariateNormal): instance of Multivariate Normal.

        Returns:
            Tensor, kl-divergence between two Multivariate Normal distributions. The data type is the same as `self.loc`.

        zmKL divergence of two Multivariate Normal distributions should share the same `batch_shape` and `event_shape`.r   r   r:   rF   r   )r/   r0   r   r    r<   r=   r.   listrangerG   r   r   r8   	transposer!   Zsolver;   r
   )r&   rJ   Zhalf_log_det_1Zhalf_log_det_2new_permZ	cov_mat_1Z	cov_mat_2Zexpectationr)   r)   r*   kl_divergence/  sJ   

z MultivariateNormal.kl_divergence)NNN)r
   r   r   r   r   r   r   r   )r+   r   )r   r2   r+   r   )r9   r   r+   r   )rJ   r	   r+   r   )__name__
__module____qualname____doc____annotations__r%   propertyr-   r1   r5   r4   rC   rE   rI   rO   __classcell__r)   r)   r'   r*   r	      s*   
 AW


r	   Pr   r+   c                 C  s   t jt | d}t |d}ttt|j}|d |d |d< |d< t ||}t j	| jd | j
d}t jj||dd}|S )zConvert precision matrix to scale tril matrix

    Args:
        P (Tensor): input precision matrix

    Returns:
        Tensor: scale tril matrix
    )r   r   r   r   r   Fupper)r   r!   r"   fliprK   rL   rG   r   rM   eyer   triangular_solve)rW   ZLftmprN   ZL_invZIdLr)   r)   r*   r#   i  s   	r#   bLbxc                 C  s  |j d }|j dd }t|}|  d }|| }|| }|d|  }|j d| }	t| j dd |j |d D ]\}
}|	||
 |
f7 }	q:|	|f7 }	||	}tt|tt||d tt|d |d |g }||}| d||f}|d|j d |f}|d}tj	j
||dd	dd}| }||j dd }tt|}t|D ]}||| || g7 }q||}||S )
aa  
    Computes the squared Mahalanobis distance of the Multivariate Normal distribution with cholesky decomposition of the covariance matrix.
    Accepts batches for both bL and bx.

    Args:
        bL (Tensor): scale trial matrix (batched)
        bx (Tensor): difference vector(batched)

    Returns:
        Tensor: squared Mahalanobis distance
    r   Nr   r   r   r   )r   r   r   FrX   )r   rG   r   zipr   rK   rL   rM   r   r!   r\   powr.   t)r_   r`   nZbx_batch_shapeZbx_batch_dimsZbL_batch_dimsZouter_batch_dimsZold_batch_dimsZnew_batch_dimsZbx_new_shapeZsLsxZpermute_dimsZflat_LZflat_xZflat_x_swapZM_swaprA   Z
permuted_MZpermute_inv_dimsiZ
reshaped_Mr)   r)   r*   r;   |  sJ   
&





r;   )rW   r   r+   r   )r_   r   r`   r   r+   r   )
__future__r   r>   collections.abcr   typingr   r   Zpaddle.base.data_feederr   Zpaddle.distributionr   r   Zpaddle._typing.dtype_liker   Distributionr	   r#   r;   r)   r)   r)   r*   <module>   s     
N