o
    Me2                     @   sl   d dl Z d dlZd dlmZmZ zd dlmZ W n
   d dl mZ Y G dd dejZdd Z	dd	 Z
dS )
    N)categoricaldistribution)Iterablec                       sb   e Zd ZdZ fddZedd Zedd Zdd	 Zd
d Z	dddZ
dd Zdd Z  ZS )Multinomiala,  
    Multinomial distribution parameterized by :attr:`total_count` and 
    :attr:`probs`.

    In probability theory, the multinomial distribution is a generalization of 
    the binomial distribution, it models the probability of counts for each side
    of a k-sided die rolled n times. When k is 2 and n is 1, the multinomial is 
    the bernoulli distribution, when k is 2 and n is grater than 1, it is the 
    binomial distribution, when k is grater than 2 and n is 1, it is the 
    categorical distribution.

    The probability mass function (PMF) for multinomial is

    .. math::

        f(x_1, ..., x_k; n, p_1,...,p_k) = \frac{n!}{x_1!...x_k!}p_1^{x_1}...p_k^{x_k}

    where, :math:`n` is number of trials, k is the number of categories, 
    :math:`p_i` denote probability of a trial falling into each category, 
    :math:`{\textstyle \sum_{i=1}^{k}p_i=1}, p_i \ge 0`, and :math:`x_i` denote 
    count of each category. 

    Args:
        total_count (int): Number of trials.
        probs (Tensor): Probability of a trial falling into each category. Last 
            axis of probs indexes over categories, other axes index over batches.
            Probs value should between [0, 1], and sum to 1 along last axis. If 
            the value over 1, it will be normalized to sum to 1 along the last 
            axis. 

    Examples:

    .. code-block:: python

        import paddle

        multinomial = paddle.distribution.Multinomial(10, paddle.to_tensor([0.2, 0.3, 0.5]))
        print(multinomial.sample((2, 3)))
        # Tensor(shape=[2, 3, 3], dtype=float32, place=Place(gpu:0), stop_gradient=True,
        #        [[[1., 4., 5.],
        #          [0., 2., 8.],
        #          [2., 4., 4.]],

        #         [[1., 6., 3.],
        #          [3., 3., 4.],
        #          [3., 4., 3.]]])
    c                    s   t |tr	|dk rtd| dk rtd||jddd | _|| _tj| 	|d| _
tt| |jd d |jdd   d S )N   zBinput parameter total_count must be int type and grater than zero.z9probs parameter shoule not be none and over one dimensionT)Zkeepdim)logits)
isinstanceint
ValueErrordimsumprobstotal_countr   ZCategorical_probs_to_logits_categoricalsuperr   __init__shape)selfr   r   	__class__ OD:\Projects\ConvertPro\env\Lib\site-packages\paddle/distribution/multinomial.pyr   J   s   *zMultinomial.__init__c                 C   s   | j | j S )z[mean of multinomial distribuion.

        Returns:
            Tensor: mean value.
        )r   r   r   r   r   r   mean[   s   zMultinomial.meanc                 C   s   | j | j d| j  S )zdvariance of multinomial distribution.

        Returns:
            Tensor: variance value.
        r   )r   r   r   r   r   r   varianced   s   zMultinomial.variancec                 C   s   t | |S )zprobability mass function evaluated at value.

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

        Returns:
            Tensor: probability of value.
        )paddleexplog_prob)r   valuer   r   r   probm   s   	zMultinomial.probc                 C   s   t |rt || jj}t t | j|g\}}d||dkt |@ < t |	dd t |d 	d || 	d S )zprobability mass function evaluated at value

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

        Returns:
            Tensor: probability of value.
        r   r   r   )
r   
is_integercastr   dtypeZbroadcast_tensorslogisinflgammar   )r   r    r   r   r   r   r   x   s   
	zMultinomial.log_probr   c                 C   sR   t |ts	td| j| jgt| }tjj	
|| jjd | jjdS )zdraw sample data from multinomial distribution

        Args:
            sample_shape (tuple, optional): [description]. Defaults to ().
        z%sample shape must be Iterable object.r   r   )r	   r   	TypeErrorr   sampler   listr   nnZ
functionalZone_hotr   r   r#   r$   r   )r   r   Zsamplesr   r   r   r)      s   
zMultinomial.samplec                 C   s   t jdg| j| jjd}t j| jd | jjdddt| jj  dd }t 	| 
||}|| j  t |d  |t |d  ddg S )	z`entropy of multinomial distribution

        Returns:
            Tensor: entropy value
        r   )r   Z
fill_valuer$   r$   )r   )r   Nr   r   )r   fullr   r   r$   arangeZreshapelenr   r   _binomial_logpmfr   entropyr'   r   )r   nZsupportZbinomial_pmfr   r   r   r1      s"   zMultinomial.entropyc              	   C   s~   | j | jdd}t|d }t|d }t|| d }|t| |ttt|   | }|| | | | S )NT)Z	is_binaryr   )r   r   r   r'   _clip_by_zerolog1pr   abs)r   countr    r   Zfactor_nZfactor_kZ
factor_nmkZnormr   r   r   r0      s   
zMultinomial._binomial_logpmf)r   )__name__
__module____qualname____doc__r   propertyr   r   r!   r   r)   r1   r0   __classcell__r   r   r   r   r      s    0


r   c                 C   s   t j| d |dS )Nr   r,   )r   r.   )r6   r$   r   r   r   _binomial_support   s   r=   c                 C   s    | j dd|  | j dd d S )Nr   )min)max   )Zclip)xr   r   r   r3      s    r3   )collectionsr   Zpaddle.distributionr   r   collections.abcr   Distributionr   r=   r3   r   r   r   r   <module>   s    #