
    zjO7                    Z   U d dl mZ d dlmZmZ d dlZd dlZd dlm	Z	m
Z
 d dlmZ d dlm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 d dlmZ d dlmZ d dlmZ eee         ee         ej        eej         ej!        f                  ef         Z"de#d<    G d dej$                  Z%dS )    )annotations)TYPE_CHECKINGUnionN)
check_typeconvert_dtype)Variable)distribution)in_dynamic_mode)multinomial)Sequence)	TypeAlias)Tensor)NestedSequence)_DTypeLiteralr   _CategoricalBoundaryc                  `    e Zd ZU dZded<   ded<   	 dddZg fddZddZddZddZ	ddZ
dS )Categoricala	  
    Categorical distribution is a discrete probability distribution that
    describes the possible results of a random variable that can take on
    one of K possible categories, with the probability of each category
    separately specified.

    The probability mass function (pmf) is:

    .. math::

        pmf(k; p_i) = \prod_{i=1}^{k} p_i^{[x=i]}

    In the above equation:

    * :math:`[x=i]` : it evaluates to 1 if :math:`x==i` , 0 otherwise.

    Args:
        logits(list|tuple|numpy.ndarray|Tensor): The logits input of categorical distribution. The data type is float32 or float64.
        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 Categorical

            >>> paddle.seed(100) # on CPU device
            >>> x = paddle.rand([6])
            >>> print(x)
            Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
            [0.55355281, 0.20714243, 0.01162981, 0.51577556, 0.36369765, 0.26091650])

            >>> paddle.seed(200) # on CPU device
            >>> y = paddle.rand([6])
            >>> print(y)
            Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
            [0.77663314, 0.90824795, 0.15685187, 0.04279523, 0.34468332, 0.79557180])

            >>> cat = Categorical(x)
            >>> cat2 = Categorical(y)

            >>> paddle.seed(1000) # on CPU device
            >>> print(cat.sample([2, 3]))
            Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
            [[0, 1, 5],
            [3, 4, 5]])

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

            >>> print(cat.kl_divergence(cat2))
            Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,
            [0.07195196])

            >>> value = paddle.to_tensor([2, 1, 3])
            >>> print(cat.probs(value))
            Tensor(shape=[3], dtype=float32, place=Place(cpu), stop_gradient=True,
            [0.00608027, 0.10829761, 0.26965630])

            >>> print(cat.log_prob(value))
            Tensor(shape=[3], dtype=float32, place=Place(cpu), stop_gradient=True,
            [-5.10270691, -2.22287226, -1.31060708])
    r   logitsr   dtypeNr   name
str | NonereturnNonec           	        t                      s?t          |dt          j        t          t
          j        j        t          t          fd           ||nd| _
        d| _        |                     |          r!|| _        t          |j                  | _        nt          |t          j                  r/t!          |j                  dv rt          |j                  | _        |                     |          d         | _        | j        t          | j        j                  k    r%t          j        | j        | j                  | _        t          j        | j        dd	
          }| j        |z  | _        dS )a1  
        Args:
            logits(list|tuple|numpy.ndarray|Tensor): The logits input of categorical distribution. The data type is float32 or float64.
            name(str, optional): Name for the operation (optional, default is None). For more information, please refer to :ref:`api_guide_Name`.
        r   r   Nfloat32)r   float64r   )r   Taxiskeepdim)r
   r   npndarrayr   paddlepirValuelisttupler   r   _validate_argsr   r   
isinstancestr
_to_tensorcastsum_prob)selfr   r   dist_sums       o/lsinfo/ai/hellotax_ai/data_center/backend/venv/lib/python3.11/site-packages/paddle/distribution/categorical.py__init__zCategorical.__init__s   sE       	Xvz'7uE	   !,DD-	
v&& 	I DK&v|44DJJ&"*-- 9#fl2C2C H 3 3 +6<88
//&11!4DKz]4;+<====$k$+TZHHH:dkDAAA[8+


    shapeSequence[int]c                   | j         dz   }t                      st          |dt          t          fd           t          j        t          j        |                    }t          | j        j	                  }t          |          dk    rJ||dd         z   }t          j        | j        t          j        |dd                   |d         g          }n	|}| j        }t          |                     |          |d          }t          t          |                                                    }|                    d|                    d                     |                    |          }t          j        |||	          S )
a  Generate samples of the specified shape.

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

        Returns:
            Tensor: A tensor with prepended dimensions shape.

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Categorical

                >>> paddle.seed(100) # on CPU device
                >>> x = paddle.rand([6])
                >>> print(x)
                Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.55355281, 0.20714243, 0.01162981, 0.51577556, 0.36369765, 0.26091650])

                >>> # doctest: +SKIP('Random output')
                >>> cat = Categorical(x)
                >>> paddle.seed(1000) # on CPU device
                >>> print(cat.sample([2, 3]))
                Tensor(shape=[2, 3], dtype=int64, place=Place(cpu), stop_gradient=True,
                [[0, 1, 5],
                [3, 4, 5]])
        _sampler4   sample   Nr   Tr   r   )r   r
   r   r&   r'   r!   prodarrayr   r4   lenr#   reshaper   _logits_to_probsrangediminsertpop	transpose)	r/   r4   r   num_sampleslogits_shapesample_shaper   sample_indexpermutes	            r1   r8   zCategorical.sample   sZ   : y9$   	@uge}h???gbhuoo..DK-..|q   <#44L^bgl3B3&788,r:JK FF !L[F"!!&));
 
 u\--//0011q'++b//***#--g66~lLtDDDDr3   otherc                :   | j         dz   }t                      st          |dt          d           | j        t          j        | j        dd          z
  }|j        t          j        |j        dd          z
  }t          j        |          }t          j        |          }t          j        |dd          }t          j        |dd          }||z  }	t          j        |	|t          j	        |          z
  |z
  t          j	        |          z   z  dd|          }
|
S )a  The KL-divergence between two Categorical distributions.

        Args:
            other (Categorical): instance of Categorical. The data type is float32.

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

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Categorical

                >>> paddle.seed(100) # on CPU device
                >>> x = paddle.rand([6])
                >>> print(x)
                Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.55355281, 0.20714243, 0.01162981, 0.51577556, 0.36369765, 0.26091650])

                >>> paddle.seed(200) # on CPU device
                >>> y = paddle.rand([6])
                >>> print(y)
                Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.77663314, 0.90824795, 0.15685187, 0.04279523, 0.34468332, 0.79557180])

                >>> cat = Categorical(x)
                >>> cat2 = Categorical(y)

                >>> print(cat.kl_divergence(cat2))
                Tensor(shape=[1], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.07195196])
        _kl_divergencerJ   kl_divergencer   Tr   )r   r    r   )
r   r
   r   r   r   r#   maxexpr-   log)r/   rJ   r   r   other_logitse_logitsother_e_logitszother_zprobkls              r1   rM   zCategorical.kl_divergence   s$   D y++   	Eug{ODDDvz$+BMMMM|fjLr4'
 '
 '
 
 :f%%L11Jxb$777*^"dCCC!|Z
1%4vz'7J7JJL
 
 
 	r3   c                L   | j         dz   }| j        t          j        | j        dd          z
  }t          j        |          }t          j        |dd          }||z  }t          j        ||t          j        |          z
  z  d          }t          j        |d|          }|S )a  Shannon entropy in nats.

        Returns:
            Tensor: Shannon entropy of Categorical distribution. The data type is float32.

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Categorical

                >>> paddle.seed(100) # on CPU device
                >>> x = paddle.rand([6])
                >>> print(x)
                Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.55355281, 0.20714243, 0.01162981, 0.51577556, 0.36369765, 0.26091650])

                >>> cat = Categorical(x)

                >>> print(cat.entropy())
                Tensor(shape=[], dtype=float32, place=Place(cpu), stop_gradient=True,
                1.77528250)
        _entropyr   Tr   r   g      )scaler   )r   r   r#   rN   rO   r-   rP   r[   )r/   r   r   rR   rT   rV   neg_entropyentropys           r1   r]   zCategorical.entropy	  s    0 y:%vz$+BMMMM:f%%Jxb$777!|j&*Q--)?!@rJJJ,{$TBBBr3   valuec           	        | j         dz   }t          | j        j                  dk    rLt	          j        | j        |                    dg|          |                              |j        |          S t          |j                  dk    rSt	          j        | j        t	          j        |t          | j        j                  dz
  dgz  dgz   |          d          S t	          j        | j        |d          S )a  Probabilities of the given category (``value``).

        If ``logits`` is 2-D or higher dimension, the last dimension will be regarded as
        category, and the others represents the different distributions.
        At the same time, if ``value`` is 1-D Tensor, ``value`` will be broadcast to the
        same number of distributions as ``logits``.
        If ``value`` is not 1-D Tensor, ``value`` should have the same number distributions
        with ``logits. That is, ``value[:-1] = logits[:-1]``.

        Args:
            value (Tensor): The input tensor represents the selected category index.

        Returns:
            Tensor: probability according to the category index.

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Categorical

                >>> paddle.seed(100) # on CPU device
                >>> x = paddle.rand([6])
                >>> print(x)
                Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.55355281, 0.20714243, 0.01162981, 0.51577556, 0.36369765, 0.26091650])

                >>> cat = Categorical(x)

                >>> value = paddle.to_tensor([2, 1, 3])
                >>> print(cat.probs(value))
                Tensor(shape=[3], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.00608027, 0.10829761, 0.26965630])
        _probsr9   r   r:   rZ   )r   r=   r.   r4   r#   gatherr>   take_along_axisr/   r^   r   s      r1   probszCategorical.probs+  s   F y8#tz  A%%=
EMM2$TM::  gekg--. 5;1$$-JNTZ-..2qc9RD@!  
     -dj%bIIIIr3   c                h    | j         dz   }t          j        |                     |          |          S )a  Log probabilities of the given category. Refer to ``probs`` method.

        Args:
            value (Tensor): The input tensor represents the selected category index.

        Returns:
            Tensor: Log probability.

        Examples:
            .. code-block:: python

                >>> import paddle
                >>> from paddle.distribution import Categorical

                >>> paddle.seed(100) # on CPU device
                >>> x = paddle.rand([6])
                >>> print(x)
                Tensor(shape=[6], dtype=float32, place=Place(cpu), stop_gradient=True,
                [0.55355281, 0.20714243, 0.01162981, 0.51577556, 0.36369765, 0.26091650])

                >>> cat = Categorical(x)

                >>> value = paddle.to_tensor([2, 1, 3])
                >>> print(cat.log_prob(value))
                Tensor(shape=[3], dtype=float32, place=Place(cpu), stop_gradient=True,
                [-5.10270691, -2.22287226, -1.31060708])
        	_log_probr:   )r   r#   rP   rd   rc   s      r1   log_probzCategorical.log_proba  s1    8 y;&z$**U++$7777r3   )N)r   r   r   r   r   r   )r4   r5   r   r   )rJ   r   r   r   )r   r   )r^   r   r   r   )__name__
__module____qualname____doc____annotations__r2   r8   rM   r]   rd   rg    r3   r1   r   r   .   s         ? ?B NNN
  ", ", ", ", ",H -/ 7E 7E 7E 7E 7Er7 7 7 7r       D4J 4J 4J 4Jl8 8 8 8 8 8r3   r   )&
__future__r   typingr   r   numpyr!   r#   paddle.base.data_feederr   r   paddle.base.frameworkr   paddle.distributionr	   paddle.frameworkr
   paddle.tensorr   collections.abcr   numpy.typingnpttyping_extensionsr   r   paddle._typingr   paddle._typing.dtype_liker   floatNDArrayr   r   r   rl   Distributionr   rm   r3   r1   <module>r      s   # " " " " " " ' ' ' ' ' ' ' '      = = = = = = = = * * * * * * , , , , , , , , , , , , % % % % % % ((((((++++++------777777&+uE"*bj012	'    Q8 Q8 Q8 Q8 Q8,+ Q8 Q8 Q8 Q8 Q8r3   