o
    "jC                     @   sF   d dl Z d dlZd dlZd dlmZ d dlmZ G dd dejZ	dS )    N)	framework)distributionc                       s   e Zd ZdZd fdd	Zedd Zedd Zed	d
 ZdddZ	dddZ
dd Zdd Zdd Zdd Z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, 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])
    Nc                    s   |d ur|nd| _ t|tjtjfstdt| t|tjtjfs-tdt| t|tjr:tj	d|d}t|tjrGtj	d|d}|j
|j
krYt||g\| _| _n||| _| _| jj| _t j| jj
dd d S )Nr   z/Expected type of loc is Real|Variable, but got z1Expected type of scale is Real|Variable, but got  )shapeZ
fill_value)Zbatch_shapeZevent_shape)name
isinstancenumbersRealr   Variable	TypeErrortypepaddlefullr   broadcast_tensorslocscaledtypesuper__init__)selfr   r   r   	__class__r   [/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/paddle/distribution/cauchy.pyr   :   s$   
zCauchy.__init__c                 C      t d)zMean of Cauchy distribution.z Cauchy distribution has no mean.
ValueErrorr   r   r   r   meanU      zCauchy.meanc                 C   r   )z Variance of Cauchy distribution.z$Cauchy distribution has no variance.r   r   r   r   r   varianceZ   r   zCauchy.variancec                 C   r   )z*Standard Deviation of Cauchy distribution.z"Cauchy distribution has no stddev.r   r   r   r   r   stddev_   r   zCauchy.stddevc                 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]): Sample shape.
            name (str, 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]
        N_sample)r   r   Zno_gradrsample)r   r   r   r   r   r   sampled   s   ,

$zCauchy.samplec              
   C   s   |dur|n| j d }t|tjt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]): Sample shape.
            name (str, 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   listtupler   r   Z_extend_shaper   expandr   r   Zrandr   addmultiplytanpi)r   r   r   r   r   Zuniformsr   r   r   r#      s   )
zCauchy.rsamplec                 C   s:   | j d }t|tj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_prob,Expected type of value is Variable, but got r'   )r   r   r   r   r   r   log_probexp)r   valuer   r   r   r   prob   s   
,zCauchy.probc              	   C   s   | j d }t|tj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 densitiy function.

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

        Returns:
            Tensor: Log of probability densitiy 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_probr0   r%   r'   )r   r   r   r   r   r   _check_values_dtype_in_probsr   r   r   r   subtractZsquaredividelog1pr,   r   r   r(   logr/   r   r   r3   r   r   r   r   r   r   r1     s&   
(
zCauchy.log_probc                 C   sx   | j d }t|tj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_cdfr0   r'   r&   )r   r   r   r   r   r   r5   r   r   r   r   atanr7   r6   r(   r/   r:   r   r   r   cdfD  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   r%   r'   )r   r   r,   r   r   r   r(   r9   r/   r   r   )r   r   r   r   r   entropy  s   
 zCauchy.entropyc           	   	   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    r=   r'   )r   r   r   r   r   r   r   r   r,   powr6   r9   r-   )	r   otherr   Za_locZb_locZa_scaleZb_scalet1t2r   r   r   kl_divergence  s"   

zCauchy.kl_divergence)N)__name__
__module____qualname____doc__r   propertyr   r    r!   r$   r#   r4   r1   r<   r>   rD   __classcell__r   r   r   r   r      s     !




0<5?@%r   )
r	   numpyr(   r   Zpaddle.baser   Zpaddle.distributionr   Distributionr   r   r   r   r   <module>   s   