o
    * i,#                     @  sj   d dl mZ d dlmZ d dlmZ d dlZd dlmZ er*d dlm	Z	 d dl
mZ G dd	 d	ejZdS )
    )annotations)Sequence)TYPE_CHECKINGN)distribution)Tensor)_DTypeLiteralc                      s   e Zd ZU dZded< ded< ded< d$ fddZd%ddZed&ddZe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d)d"d#Z  ZS )*Binomiala  
    The Binomial distribution with size `total_count` and `probs` parameters.

    In probability theory and statistics, the binomial distribution is the most basic discrete probability distribution defined on :math:`[0, n] \cap \mathbb{N}`,
    which can be viewed as the number of times a potentially unfair coin is tossed to get heads, and the result
    of its random variable can be viewed as the sum of a series of independent Bernoulli experiments.

    The probability mass function (pmf) is

    .. math::

        pmf(x; n, p) = \frac{n!}{x!(n-x)!}p^{x}(1-p)^{n-x}

    In the above equation:

    * :math:`total\_count = n`: is the size, meaning the total number of Bernoulli experiments.
    * :math:`probs = p`: is the probability of the event happening in one Bernoulli experiments.

    Args:
        total_count(int|Tensor): The size of Binomial distribution which should be greater than 0, meaning the number of independent bernoulli
            trials with probability parameter :math:`p`. The data type will be converted to 1-D Tensor with paddle global default dtype if the input
            :attr:`probs` is not Tensor, otherwise will be converted to the same as :attr:`probs`.
        probs(float|Tensor): The probability of Binomial distribution which should reside in [0, 1], meaning the probability of success
            for each individual bernoulli trial. If the input data type is float, it will be converted to a 1-D Tensor with paddle global default dtype.

    Examples:
        .. code-block:: python

            >>> import paddle
            >>> from paddle.distribution import Binomial
            >>> paddle.set_device('cpu')
            >>> paddle.seed(100)
            >>> rv = Binomial(100, paddle.to_tensor([0.3, 0.6, 0.9]))

            >>> print(rv.sample([2]))
            Tensor(shape=[2, 3], dtype=float32, place=Place(cpu), stop_gradient=True,
            [[31., 62., 93.],
             [29., 54., 91.]])

            >>> print(rv.mean)
            Tensor(shape=[3], dtype=float32, place=Place(cpu), stop_gradient=True,
            [30.00000191, 60.00000381, 90.        ])

            >>> print(rv.entropy())
            Tensor(shape=[3], dtype=float32, place=Place(cpu), stop_gradient=True,
            [2.94053698, 3.00781751, 2.51124287])
    r   dtyper   total_countprobsint | Tensorfloat | TensorreturnNonec                   s6   t  | _| ||\| _| _| jj}t | d S )N)	paddleZget_default_dtyper	   
_to_tensorr
   r   shapesuper__init__)selfr
   r   batch_shape	__class__ h/home/app/PaddleOCR-VL-test/.venv_paddleocr/lib/python3.10/site-packages/paddle/distribution/binomial.pyr   Q   s   
zBinomial.__init__list[Tensor]c                 C  s^   t |trtj|| jd}n|j| _t |tr tj|| jd}ntj|| jd}t||gS )zConvert the input parameters into Tensors if they were not and broadcast them

        Returns:
            list[Tensor]: converted total_count and probs.
        r	   )
isinstancefloatr   Z	to_tensorr	   intcastZbroadcast_tensors)r   r
   r   r   r   r   r   Z   s   
	
zBinomial._to_tensorc                 C  s   | j | j S )zYMean of binomial distribution.

        Returns:
            Tensor: mean value.
        r
   r   r   r   r   r   meano   s   zBinomial.meanc                 C  s   | j | j d| j  S )zaVariance of binomial distribution.

        Returns:
            Tensor: variance value.
           r!   r"   r   r   r   variancex   s   zBinomial.variancer   Sequence[int]c                 C  s   t |ts	tdtd9 t|}t| j}t|| }tj| j|d}tj| j	|d}t
tj|dd|}t|| jW  d   S 1 sJw   Y  dS )a^  Generate binomial samples of the specified shape. The final shape would be ``shape+batch_shape`` .

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

        Returns:
            Tensor: Sampled data with shape `sample_shape` + `batch_shape`. The returned data type is the same as `probs`.
        z%sample shape must be Sequence object.F)r   Zint32r   N)r   r   	TypeErrorr   Zset_grad_enabledtupler   Zbroadcast_tor
   r   Zbinomialr    r	   )r   r   r   Zoutput_shapeZoutput_sizeZoutput_probsampler   r   r   r)      s   
	
$zBinomial.samplec                 C  s(   |   }| |}t|| d S )ae  Shannon entropy in nats.

        The entropy is

        .. math::

            \mathcal{H}(X) = - \sum_{x \in \Omega} p(x) \log{p(x)}

        In the above equation:

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

        Returns:
            Tensor: Shannon entropy of binomial distribution. The data type is the same as `probs`.
        r   )_enumerate_supportlog_probr   expsum)r   valuesr+   r   r   r   entropy   s   
zBinomial.entropyc                 C  s8   t jdt | j | jd}|ddt| j  }|S )zReturn the support of binomial distribution [0, 1, ... ,n]

        Returns:
            Tensor: the support of binomial distribution
        r$   r   ))r$   )r   Zarangemaxr
   r	   Zreshapelenr   )r   r.   r   r   r   r*      s
   zBinomial._enumerate_supportvaluec                 C  s   t j|| jd}t | jd t | j| d  t |d  }t | jjj}t j| j|d| d}t j	||t 
|  | j| t 
d|   | dS )zLog probability density/mass function.

        Args:
            value (Tensor): The input tensor.

        Returns:
            Tensor: log probability. The data type is the same as `probs`.
        r   g      ?r$   )minr1   )Zneginf)r   r    r	   lgammar
   Zfinfor   epsZclipZ
nan_to_numlog)r   r3   Zlog_combr6   r   r   r   r   r+      s"   	zBinomial.log_probc                 C  s   t | |S )zProbability density/mass function.

        Args:
            value (Tensor): The input tensor.

        Returns:
            Tensor: probability. The data type is the same as `probs`.
        )r   r,   r+   )r   r3   r   r   r   prob   s   	zBinomial.probotherc                 C  s<   |   }| |}||}tt|t||dS )av  The KL-divergence between two binomial distributions with the same :attr:`total_count`.

        The probability density function (pdf) is

        .. math::

            KL\_divergence(n_1, p_1, n_2, p_2) = \sum_x p_1(x) \log{\frac{p_1(x)}{p_2(x)}}

        .. math::

            p_1(x) = \frac{n_1!}{x!(n_1-x)!}p_1^{x}(1-p_1)^{n_1-x}

        .. math::

            p_2(x) = \frac{n_2!}{x!(n_2-x)!}p_2^{x}(1-p_2)^{n_2-x}

        Args:
            other (Binomial): instance of ``Binomial``.

        Returns:
            Tensor: kl-divergence between two binomial distributions. The data type is the same as `probs`.

        r   )r*   r+   r   multiplyr,   subtractr-   )r   r9   ZsupportZ
log_prob_1Z
log_prob_2r   r   r   kl_divergence   s   


zBinomial.kl_divergence)r
   r   r   r   r   r   )r
   r   r   r   r   r   )r   r   )r   r&   r   r   )r3   r   r   r   )r9   r   r   r   )__name__
__module____qualname____doc____annotations__r   r   propertyr#   r%   r)   r/   r*   r+   r8   r<   __classcell__r   r   r   r   r      s"   
 0
	



r   )
__future__r   collections.abcr   typingr   r   Zpaddle.distributionr   r   Zpaddle._typing.dtype_liker   Distributionr   r   r   r   r   <module>   s   