o
    pi3                     @  sz   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r2d dlmZ d dlmZ G dd	 d	ejZdS )
    )annotationsN)TYPE_CHECKING)	framework)distribution)Sequence)Tensorc                      s   e Zd ZU dZded< ded< d( fdd	Zed)d
dZed)ddZed)ddZ	d*ddZ
d+ddZd)ddZd+ddZd+ddZg fd,ddZg fd,d d!Zd-d#d$Zd.d&d'Z  ZS )/Laplacea  
    Creates a Laplace distribution parameterized by :attr:`loc` and :attr:`scale`.

    Mathematical details

    The probability density function (pdf) is

    .. math::
        pdf(x; \mu, \sigma) = \frac{1}{2 * \sigma} * e^{\frac{-|x - \mu|}{\sigma}}

    In the above equation:

    * :math:`loc = \mu`: is the location parameter.
    * :math:`scale = \sigma`: is the scale parameter.

    Args:
        loc (scalar|Tensor): The mean of the distribution.
        scale (scalar|Tensor): The scale of the distribution.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> paddle.seed(2023)
            >>> m = paddle.distribution.Laplace(paddle.to_tensor(0.0), paddle.to_tensor(1.0))
            >>> m.sample()  # Laplace distributed with loc=0, scale=1
            Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                1.31554604)

    r   locscalefloat | TensorreturnNonec                   s   t |tjtjtjjfstdt	| t |tjtjtjjfs*tdt	| t |tjr7tj
d|d}t |tjrDtj
d|d}t|jdksRt|jdkrd|j|jkrdt||g\| _| _n||| _| _t | jj d S )Nz/Expected type of loc is Real|Variable, but got z1Expected type of scale is Real|Variable, but got  shapeZ
fill_valuer   )
isinstancenumbersRealr   VariablepaddleZpirValue	TypeErrortypefulllenr   dtypebroadcast_tensorsr	   r
   super__init__)selfr	   r
   	__class__r   b/home/app/PaddleOCR-VL/.venv_paddleocr/lib/python3.10/site-packages/paddle/distribution/laplace.pyr   B   s*   zLaplace.__init__c                 C  s   | j S )zTMean of distribution.

        Returns:
            Tensor: The mean value.
        )r	   r   r   r   r"   mean`   s   zLaplace.meanc                 C  s
   d| j  S )zStandard deviation.

        The stddev is

        .. math::
            stddev = \sqrt{2} * \sigma

        In the above equation:

        * :math:`scale = \sigma`: is the scale parameter.

        Returns:
            Tensor: The std value.
        g;f?)r
   r#   r   r   r"   stddevi   s   
zLaplace.stddevc                 C  s   | j dS )a  Variance of distribution.

        The variance is

        .. math::
            variance = 2 * \sigma^2

        In the above equation:

        * :math:`scale = \sigma`: is the scale parameter.

        Returns:
            Tensor: The variance value.
           )r%   powr#   r   r   r"   variance{   s   zLaplace.variancevaluetuple[Tensor, Tensor, Tensor]c                 C  s   t |tjrtjd|d}|j| jjkrt|| jj}t| jj	dks3t| j
j	dks3t|j	dkrAt| j
| j|g\}}}n| j
| j}}|||fS )aH  Argument dimension check for distribution methods such as `log_prob`,
        `cdf` and `icdf`.

        Args:
          value (Tensor|Scalar): The input value, which can be a scalar or a tensor.

        Returns:
          loc, scale, value: The broadcasted loc, scale and value, with the same dimension and data type.
        r   r   r   )r   r   r   r   r   r   r
   castr   r   r	   r   )r   r)   r	   r
   r   r   r"   _validate_value   s   
zLaplace._validate_valuec                 C  s6   |  |\}}}td|  }|t|| |  S )a  Log probability density/mass function.

        The log_prob is

        .. math::
            log\_prob(value) = \frac{-log(2 * \sigma) - |value - \mu|}{\sigma}

        In the above equation:

        * :math:`loc = \mu`: is the location parameter.
        * :math:`scale = \sigma`: is the scale parameter.

        Args:
          value (Tensor|Scalar): The input value, can be a scalar or a tensor.

        Returns:
          Tensor: The log probability, whose data type is same with value.

        Examples:
            .. code-block:: python

                >>> import paddle

                >>> m = paddle.distribution.Laplace(paddle.to_tensor(0.0), paddle.to_tensor(1.0))
                >>> value = paddle.to_tensor(0.1)
                >>> m.log_prob(value)
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                        -0.79314721)

        r&   )r,   r   logabs)r   r)   r	   r
   Z	log_scaler   r   r"   log_prob   s   zLaplace.log_probc                 C  s   dt d| j  S )am  Entropy of Laplace distribution.

        The entropy is:

        .. math::
            entropy() = 1 + log(2 * \sigma)

        In the above equation:

        * :math:`scale = \sigma`: is the scale parameter.

        Returns:
            The entropy of distribution.

        Examples:
            .. code-block:: python

                >>> import paddle

                >>> m = paddle.distribution.Laplace(paddle.to_tensor(0.0), paddle.to_tensor(1.0))
                >>> m.entropy()
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                        1.69314718)
           r&   )r   r-   r
   r#   r   r   r"   entropy   s   zLaplace.entropyc                 C  s@   |  |\}}}d||   t||   |  }d| S )aZ  Cumulative distribution function.

        The cdf is

        .. math::
            cdf(value) = 0.5 - 0.5 * sign(value - \mu) * e^\frac{-|(\mu - \sigma)|}{\sigma}

        In the above equation:

        * :math:`loc = \mu`: is the location parameter.
        * :math:`scale = \sigma`: is the scale parameter.

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

        Returns:
            Tensor: The cumulative probability of value.

        Examples:
            .. code-block:: python

                >>> import paddle

                >>> m = paddle.distribution.Laplace(paddle.to_tensor(0.0), paddle.to_tensor(1.0))
                >>> value = paddle.to_tensor(0.1)
                >>> m.cdf(value)
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                        0.54758132)
              ?)r,   signr   expm1r.   )r   r)   r	   r
   itemr   r   r"   cdf   s   
zLaplace.cdfc                 C  s:   |  |\}}}|d }|||  td|    S )a`  Inverse Cumulative distribution function.

        The icdf is

        .. math::
            cdf^{-1}(value)= \mu - \sigma * sign(value - 0.5) * ln(1 - 2 * |value-0.5|)

        In the above equation:

        * :math:`loc = \mu`: is the location parameter.
        * :math:`scale = \sigma`: is the scale parameter.

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

        Returns:
            Tensor: The cumulative probability of value.

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> m = paddle.distribution.Laplace(paddle.to_tensor(0.0), paddle.to_tensor(1.0))
                >>> value = paddle.to_tensor(0.1)
                >>> m.icdf(value)
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                        -1.60943794)
        r2   )r,   r3   r   log1pr.   )r   r)   r	   r
   termr   r   r"   icdf  s   "zLaplace.icdfr   Sequence[int]c                 C  sL   t |tr|nt|}t  | |W  d   S 1 sw   Y  dS )a  Generate samples of the specified shape.

        Args:
            shape(Sequence[int], optional): The shape of generated samples.
                Defaults to [].

        Returns:
            Tensor: A sample tensor that fits the Laplace distribution.

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> paddle.seed(2023)
                >>> m = paddle.distribution.Laplace(paddle.to_tensor(0.0), paddle.to_tensor(1.0))
                >>> m.sample()  # Laplace distributed with loc=0, scale=1
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                    1.31554604)
        N)r   tupler   Zno_gradrsample)r   r   r   r   r"   sample2  s   
$zLaplace.samplec                 C  sh   |   }| |}tj|ttdd|d  d|d  | jjd}| j| j	|
  t|    S )a  Reparameterized sample.

        Args:
            shape(Sequence[int], optional): The shape of generated samples.
                Defaults to [].

        Returns:
            Tensor: A sample tensor that fits the Laplace distribution.

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> paddle.seed(2023)
                >>> m = paddle.distribution.Laplace(paddle.to_tensor([0.0]), paddle.to_tensor([1.0]))
                >>> m.rsample((1,))  # Laplace distributed with loc=0, scale=1
                Tensor(shape=[1, 1], dtype=float32, place=Place(cpu), stop_gradient=True,
                    [[1.31554604]])
        r0   r&   g      ?)r   minmaxr   )_get_epsZ_extend_shaper   uniformfloatnp	nextafterr	   r   r
   r3   r8   r.   )r   r   epsrC   r   r   r"   r=   J  s   

zLaplace.rsamplerD   c                 C  s(   d}| j jtjks| j jtjkrd}|S )z
        Get the eps of certain data type.

        Note:
            Since paddle.finfo is temporarily unavailable, we
            use hard-coding style to get eps value.

        Returns:
            Float: An eps value by different data types.
        gy>gǝ <)r	   r   r   Zfloat64Z
complex128)r   rG   r   r   r"   rB   k  s
   zLaplace._get_epsotherc                 C  sV   |j | j  }t| j|j }| j t| | j   | |j  }t|}|| d S )a  Calculate the KL divergence KL(self || other) with two Laplace instances.

        The kl_divergence between two Laplace distribution is

        .. math::
            KL\_divergence(\mu_0, \sigma_0; \mu_1, \sigma_1) = 0.5 (ratio^2 + (\frac{diff}{\sigma_1})^2 - 1 - 2 \ln {ratio})

        .. math::
            ratio = \frac{\sigma_0}{\sigma_1}

        .. math::
            diff = \mu_1 - \mu_0

        In the above equation:

        * :math:`loc = \mu`: is the location parameter of self.
        * :math:`scale = \sigma`: is the scale parameter of self.
        * :math:`loc = \mu_1`: is the location parameter of the reference Laplace distribution.
        * :math:`scale = \sigma_1`: is the scale parameter of the reference Laplace distribution.
        * :math:`ratio`: is the ratio between the two distribution.
        * :math:`diff`: is the difference between the two distribution.

        Args:
            other (Laplace): An instance of Laplace.

        Returns:
            Tensor: The kl-divergence between two laplace distributions.

        Examples:
            .. code-block:: python

                >>> import paddle

                >>> m1 = paddle.distribution.Laplace(paddle.to_tensor([0.0]), paddle.to_tensor([1.0]))
                >>> m2 = paddle.distribution.Laplace(paddle.to_tensor([1.0]), paddle.to_tensor([0.5]))
                >>> m1.kl_divergence(m2)
                Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,
                        [1.04261160])
        r0   )r
   r   r.   r	   expr-   )r   rH   Z	var_ratiotZterm1Zterm2r   r   r"   kl_divergence  s
   )"
zLaplace.kl_divergence)r	   r   r
   r   r   r   )r   r   )r)   r   r   r*   )r)   r   r   r   )r   r;   r   r   )r   rD   )rH   r   r   r   )__name__
__module____qualname____doc____annotations__r   propertyr$   r%   r(   r,   r/   r1   r6   r:   r>   r=   rB   rK   __classcell__r   r   r    r"   r      s(   
 


$

'"
!r   )
__future__r   r   typingr   numpyrE   r   Zpaddle.baser   Zpaddle.distributionr   collections.abcr   r   Distributionr   r   r   r   r"   <module>   s   