o
    piF                     @  s   d dl mZ d dlZd dlmZ d dlZd dlZd dlm	Z	 d dl
mZ er:d dlmZ d dlmZ d dlmZmZ G d	d
 d
ejZdS )    )annotationsN)TYPE_CHECKING)	framework)distribution)Sequence)Never)Tensordtypec                      s   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ed*ddZed*ddZed*ddZ	g dfd+ddZ
g dfd+ddZd,ddZd,dd Zd,d!d"Zd-d#d$Zd.d&d'Z  ZS )/Cauchyu'  Cauchy distribution is also called Cauchy–Lorentz distribution. It is a continuous probability distribution named after Augustin-Louis Cauchy and Hendrik Lorentz. It has a very wide range of applications in natural sciences.

    The Cauchy distribution has the probability density function (PDF):

    .. math::

        { f(x; loc, scale) = \frac{1}{\pi scale \left[1 + \left(\frac{x - loc}{ scale}\right)^2\right]} = { 1 \over \pi } \left[ {  scale \over (x - loc)^2 +  scale^2 } \right], }

    Args:
        loc (float|Tensor): Location of the peak of the distribution. The data type is float32 or float64.
        scale (float|Tensor): The half-width at half-maximum (HWHM). The data type is float32 or float64. Must be positive values.
        name (str|None, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

    Examples:

        .. code-block:: python

            >>> import paddle
            >>> from paddle.distribution import Cauchy

            >>> # init Cauchy with float
            >>> rv = Cauchy(loc=0.1, scale=1.2)
            >>> print(rv.entropy())
            Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                    2.71334577)

            >>> # init Cauchy with N-Dim tensor
            >>> rv = Cauchy(loc=paddle.to_tensor(0.1), scale=paddle.to_tensor([1.0, 2.0]))
            >>> print(rv.entropy())
            Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
                    [2.53102422, 3.22417140])
    r   locscaler	   strnameNfloat | Tensor
str | NonereturnNonec                   s   |d ur|nd| _ t|tjtjtjjfst	dt
| t|tjtjtjjfs3t	dt
| t|tjr@tjd|d}t|tjrMtjd|d}|j|jkr_t||g\| _| _n||| _| _| jj| _t j| jjdd d S )Nr
   z5Expected type of loc is Real|Variable|Value, but got z7Expected type of scale is Real|Variable|Value, but got  )shapeZ
fill_value)Zbatch_shapeZevent_shape)r   
isinstancenumbersRealr   VariablepaddlepirValue	TypeErrortypefullr   broadcast_tensorsr   r   r	   super__init__)selfr   r   r   	__class__r   a/home/app/PaddleOCR-VL/.venv_paddleocr/lib/python3.10/site-packages/paddle/distribution/cauchy.pyr!   I   s,   
zCauchy.__init__r   c                 C     t d)zMean of Cauchy distribution.z Cauchy distribution has no mean.
ValueErrorr"   r   r   r%   meanm      zCauchy.meanc                 C  r&   )z Variance of Cauchy distribution.z$Cauchy distribution has no variance.r'   r)   r   r   r%   variancer   r+   zCauchy.variancec                 C  r&   )z*Standard Deviation of Cauchy distribution.z"Cauchy distribution has no stddev.r'   r)   r   r   r%   stddevw   r+   zCauchy.stddevr   Sequence[int]c                 C  sN   |dur|n| j d }t  | ||W  d   S 1 s w   Y  dS )a"  Sample from Cauchy distribution.

        Note:
            `sample` method has no grad, if you want so, please use `rsample` instead.

        Args:
            shape (Sequence[int], optional): Sample shape.
            name (str|None, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

        Returns:
            Tensor: Sampled data with shape `sample_shape` + `batch_shape` + `event_shape`.

        Examples:

            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Cauchy

                >>> # init Cauchy with float
                >>> rv = Cauchy(loc=0.1, scale=1.2)
                >>> print(rv.sample([10]).shape)
                [10]

                >>> # init Cauchy with 0-Dim tensor
                >>> rv = Cauchy(loc=paddle.full((), 0.1), scale=paddle.full((), 1.2))
                >>> print(rv.sample([10]).shape)
                [10]

                >>> # init Cauchy with N-Dim tensor
                >>> rv = Cauchy(loc=paddle.to_tensor(0.1), scale=paddle.to_tensor([1.0, 2.0]))
                >>> print(rv.sample([10]).shape)
                [10, 2]

                >>> # sample 2-Dim data
                >>> rv = Cauchy(loc=0.1, scale=1.2)
                >>> print(rv.sample([10, 2]).shape)
                [10, 2]

                >>> rv = Cauchy(loc=paddle.to_tensor(0.1), scale=paddle.to_tensor([1.0, 2.0]))
                >>> print(rv.sample([10, 2]).shape)
                [10, 2, 2]
        NZ_sample)r   r   Zno_gradrsample)r"   r   r   r   r   r%   sample|   s   .

$zCauchy.samplec              
   C  s   |dur|n| j d }t|tjtjtjjt	t
fs"tdt| t|t
r)|nt
|}| |}| j|}| j|}tj|| jd}tj|t|ttj|d  |dS )a  Sample from Cauchy distribution (reparameterized).

        Args:
            shape (Sequence[int], optional): Sample shape.
            name (str|None, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.

        Returns:
            Tensor: Sampled data with shape `sample_shape` + `batch_shape` + `event_shape`.

        Examples:

            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Cauchy

                >>> # init Cauchy with float
                >>> rv = Cauchy(loc=0.1, scale=1.2)
                >>> print(rv.rsample([10]).shape)
                [10]

                >>> # init Cauchy with 0-Dim tensor
                >>> rv = Cauchy(loc=paddle.full((), 0.1), scale=paddle.full((), 1.2))
                >>> print(rv.rsample([10]).shape)
                [10]

                >>> # init Cauchy with N-Dim tensor
                >>> rv = Cauchy(loc=paddle.to_tensor(0.1), scale=paddle.to_tensor([1.0, 2.0]))
                >>> print(rv.rsample([10]).shape)
                [10, 2]

                >>> # sample 2-Dim data
                >>> rv = Cauchy(loc=0.1, scale=1.2)
                >>> print(rv.rsample([10, 2]).shape)
                [10, 2]

                >>> rv = Cauchy(loc=paddle.to_tensor(0.1), scale=paddle.to_tensor([1.0, 2.0]))
                >>> print(rv.rsample([10, 2]).shape)
                [10, 2, 2]
        NZ_rsamplez1Expected type of shape is Sequence[int], but got r	         ?r   )r   r   npZndarrayr   r   r   r   r   listtupler   r   Z_extend_shaper   expandr   Zrandr	   addmultiplytanpi)r"   r   r   r   r   Zuniformsr   r   r%   r/      s$   +
zCauchy.rsamplevaluec                 C  sB   | j d }t|tjtjjfstdt| | 	|j
|dS )a/  Probability density function(PDF) evaluated at value.

        .. math::

            { f(x; loc, scale) = \frac{1}{\pi scale \left[1 + \left(\frac{x - loc}{ scale}\right)^2\right]} = { 1 \over \pi } \left[ {  scale \over (x - loc)^2 +  scale^2 } \right], }

        Args:
            value (Tensor): Value to be evaluated.

        Returns:
            Tensor: PDF evaluated at value.

        Examples:

            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Cauchy

                >>> # init Cauchy with float
                >>> rv = Cauchy(loc=0.1, scale=1.2)
                >>> print(rv.prob(paddle.to_tensor(1.5)))
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                        0.11234467)

                >>> # broadcast to value
                >>> rv = Cauchy(loc=0.1, scale=1.2)
                >>> print(rv.prob(paddle.to_tensor([1.5, 5.1])))
                Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
                        [0.11234467, 0.01444674])

                >>> # init Cauchy with N-Dim tensor
                >>> rv = Cauchy(loc=paddle.to_tensor([0.1, 0.1]), scale=paddle.to_tensor([1.0, 2.0]))
                >>> print(rv.prob(paddle.to_tensor([1.5, 5.1])))
                Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
                        [0.10753712, 0.02195240])

                >>> # init Cauchy with N-Dim tensor with broadcast
                >>> rv = Cauchy(loc=paddle.to_tensor(0.1), scale=paddle.to_tensor([1.0, 2.0]))
                >>> print(rv.prob(paddle.to_tensor([1.5, 5.1])))
                Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
                        [0.10753712, 0.02195240])
        Z_prob5Expected type of value is Variable or Value, but got r3   )r   r   r   r   r   r   r   r   r   log_probexp)r"   r<   r   r   r   r%   prob   s   
,zCauchy.probc              	   C  s   | j d }t|tjtjjfstdt| | 	| j
|}t| j
| j|g\}}}tjttt|||  ttj|jttj| jd| |dS )a  Log of probability density function.

        Args:
            value (Tensor): Value to be evaluated.

        Returns:
            Tensor: Log of probability density evaluated at value.

        Examples:

            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Cauchy

                >>> # init Cauchy with float
                >>> rv = Cauchy(loc=0.1, scale=1.2)
                >>> print(rv.log_prob(paddle.to_tensor(1.5)))
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                        -2.18618369)

                >>> # broadcast to value
                >>> rv = Cauchy(loc=0.1, scale=1.2)
                >>> print(rv.log_prob(paddle.to_tensor([1.5, 5.1])))
                Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
                        [-2.18618369, -4.23728657])

                >>> # init Cauchy with N-Dim tensor
                >>> rv = Cauchy(loc=paddle.to_tensor([0.1, 0.1]), scale=paddle.to_tensor([1.0, 2.0]))
                >>> print(rv.log_prob(paddle.to_tensor([1.5, 5.1])))
                Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
                        [-2.22991920, -3.81887865])

                >>> # init Cauchy with N-Dim tensor with broadcast
                >>> rv = Cauchy(loc=paddle.to_tensor(0.1), scale=paddle.to_tensor([1.0, 2.0]))
                >>> print(rv.log_prob(paddle.to_tensor([1.5, 5.1])))
                Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
                        [-2.22991920, -3.81887865])
        Z	_log_probr=   r1   r3   )r   r   r   r   r   r   r   r   r   _check_values_dtype_in_probsr   r   r   subtractZsquaredividelog1pr8   r   r   r4   logr;   r	   r"   r<   r   r   r   r   r   r%   r>   $  s&   
(
zCauchy.log_probc                 C  s   | j d }t|tjtjjfstdt| | 	| j
|}t| j
| j|g\}}}tjtt||||dtj d S )a  Cumulative distribution function(CDF) evaluated at value.

        .. math::

            { \frac{1}{\pi} \arctan\left(\frac{x-loc}{ scale}\right)+\frac{1}{2}\! }

        Args:
            value (Tensor): Value to be evaluated.

        Returns:
            Tensor: CDF evaluated at value.

        Examples:

            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Cauchy

                >>> # init Cauchy with float
                >>> rv = Cauchy(loc=0.1, scale=1.2)
                >>> print(rv.cdf(paddle.to_tensor(1.5)))
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                        0.77443725)

                >>> # broadcast to value
                >>> rv = Cauchy(loc=0.1, scale=1.2)
                >>> print(rv.cdf(paddle.to_tensor([1.5, 5.1])))
                Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
                        [0.77443725, 0.92502367])

                >>> # init Cauchy with N-Dim tensor
                >>> rv = Cauchy(loc=paddle.to_tensor([0.1, 0.1]), scale=paddle.to_tensor([1.0, 2.0]))
                >>> print(rv.cdf(paddle.to_tensor([1.5, 5.1])))
                Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
                        [0.80256844, 0.87888104])

                >>> # init Cauchy with N-Dim tensor with broadcast
                >>> rv = Cauchy(loc=paddle.to_tensor(0.1), scale=paddle.to_tensor([1.0, 2.0]))
                >>> print(rv.cdf(paddle.to_tensor([1.5, 5.1])))
                Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
                        [0.80256844, 0.87888104])
        Z_cdfr=   r3   r2   )r   r   r   r   r   r   r   r   r   rA   r   r   r   atanrC   rB   r4   r;   rF   r   r   r%   cdfc  s"   
,
z
Cauchy.cdfc                 C  s>   | j d }tjtj| jjtdtj | j	d| j
 |dS )a}  Entropy of Cauchy distribution.

        .. math::

            { \log(4\pi scale)\! }

        Returns:
            Tensor: Entropy of distribution.

        Examples:

            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Cauchy

                >>> # init Cauchy with float
                >>> rv = Cauchy(loc=0.1, scale=1.2)
                >>> print(rv.entropy())
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                        2.71334577)

                >>> # init Cauchy with N-Dim tensor
                >>> rv = Cauchy(loc=paddle.to_tensor(0.1), scale=paddle.to_tensor([1.0, 2.0]))
                >>> print(rv.entropy())
                Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
                        [2.53102422, 3.22417140])

        Z_entropy   r1   r3   )r   r   r8   r   r   r   r4   rE   r;   r	   r   )r"   r   r   r   r%   entropy  s   
 zCauchy.entropyotherc           	   	   C  s   | j d }t|tstdt| | j}|j}| j}|j}tt	t||dt	t
||d }dt||  }tj
|||dS )u]  The KL-divergence between two Cauchy distributions.

        Note:
            [1] Frédéric Chyzak, Frank Nielsen, A closed-form formula for the Kullback-Leibler divergence between Cauchy distributions, 2019

        Args:
            other (Cauchy): instance of Cauchy.

        Returns:
            Tensor: kl-divergence between two Cauchy distributions.

        Examples:

            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Cauchy

                >>> rv = Cauchy(loc=0.1, scale=1.2)
                >>> rv_other = Cauchy(loc=paddle.to_tensor(1.2), scale=paddle.to_tensor([2.3, 3.4]))
                >>> print(rv.kl_divergence(rv_other))
                Tensor(shape=[2], dtype=float32, place=Place(cpu), stop_gradient=True,
                        [0.19819736, 0.31532931])
        Z_kl_divergencez*Expected type of other is Cauchy, but got    rI   r3   )r   r   r
   r   r   r   r   r   r8   powrB   rE   r9   )	r"   rK   r   Za_locZb_locZa_scaleZb_scalet1t2r   r   r%   kl_divergence  s"   

zCauchy.kl_divergence)N)r   r   r   r   r   r   r   r   )r   r   )r   r.   r   r   r   r   )r<   r   r   r   )r   r   )rK   r
   r   r   )__name__
__module____qualname____doc____annotations__r!   propertyr*   r,   r-   r0   r/   r@   r>   rH   rJ   rP   __classcell__r   r   r#   r%   r
   "   s.   
 !$3
A
5
?
@%r
   )
__future__r   r   typingr   numpyr4   r   Zpaddle.baser   Zpaddle.distributionr   collections.abcr   Ztyping_extensionsr   r   r	   Distributionr
   r   r   r   r%   <module>   s   