U
    ©Ê¹j  ã                   @   sb   d dl Z d dl mZ d dlmZmZ d dlmZ d dlmZ d dl	m
Z
 dgZG dd„ deƒZdS )	é    N)Úinf)ÚCategoricalÚconstraints)ÚBinomial)ÚDistribution)Úbroadcast_allÚMultinomialc                       sÂ   e Zd ZU dZejejdœZee	d< e
dd„ ƒZe
dd„ ƒZd ‡ fd
d„	Zd!‡ fdd„	Zdd„ Zejddd�dd„ ƒZe
dd„ ƒZe
dd„ ƒZe
dd„ ƒZe ¡ fdd„Zdd„ Zdd„ Z‡  ZS )"r   a`  
    Creates a Multinomial distribution parameterized by :attr:`total_count` and
    either :attr:`probs` or :attr:`logits` (but not both). The innermost dimension of
    :attr:`probs` indexes over categories. All other dimensions index over batches.

    Note that :attr:`total_count` need not be specified if only :meth:`log_prob` is
    called (see example below)

    .. note:: The `probs` argument must be non-negative, finite and have a non-zero sum,
              and it will be normalized to sum to 1 along the last dimension. :attr:`probs`
              will return this normalized value.
              The `logits` argument will be interpreted as unnormalized log probabilities
              and can therefore be any real number. It will likewise be normalized so that
              the resulting probabilities sum to 1 along the last dimension. :attr:`logits`
              will return this normalized value.

    -   :meth:`sample` requires a single shared `total_count` for all
        parameters and samples.
    -   :meth:`log_prob` allows different `total_count` for each parameter and
        sample.

    Example::

        >>> # xdoctest: +SKIP("FIXME: found invalid values")
        >>> m = Multinomial(100, torch.tensor([ 1., 1., 1., 1.]))
        >>> x = m.sample()  # equal probability of 0, 1, 2, 3
        tensor([ 21.,  24.,  30.,  25.])

        >>> Multinomial(probs=torch.tensor([1., 1., 1., 1.])).log_prob(x)
        tensor([-4.1338])

    Args:
        total_count (int): number of trials
        probs (Tensor): event probabilities
        logits (Tensor): event log probabilities (unnormalized)
    ©ÚprobsÚlogitsÚtotal_countc                 C   s   | j | j S ©N)r
   r   ©Úself© r   ú^/var/www/html/bwave/python/venv/lib/python3.8/site-packages/torch/distributions/multinomial.pyÚmean3   s    zMultinomial.meanc                 C   s   | j | j d| j  S )Né   ©r   r
   r   r   r   r   Úvariance7   s    zMultinomial.variancer   Nc                    sd   t |tƒstdƒ‚|| _t||d�| _t|| jd�| _| jj	}| jj
dd … }tƒ j|||d� d S )Nz*inhomogeneous total_count is not supportedr	   r   éÿÿÿÿ©Úvalidate_args)Ú
isinstanceÚintÚNotImplementedErrorr   r   Ú_categoricalr   r
   Ú	_binomialÚbatch_shapeÚparam_shapeÚsuperÚ__init__)r   r   r
   r   r   r   Úevent_shape©Ú	__class__r   r   r!   ;   s    
zMultinomial.__init__c                    sP   |   t|¡}t |¡}| j|_| j |¡|_tt|ƒj|| j	dd� | j
|_
|S )NFr   )Z_get_checked_instancer   ÚtorchÚSizer   r   Úexpandr    r!   r"   Ú_validate_args)r   r   Z	_instanceÚnewr#   r   r   r'   E   s    

  ÿzMultinomial.expandc                 O   s   | j j||ŽS r   )r   Ú_new)r   ÚargsÚkwargsr   r   r   r*   P   s    zMultinomial._newT)Zis_discreteZ	event_dimc                 C   s   t  | j¡S r   )r   Zmultinomialr   r   r   r   r   ÚsupportS   s    zMultinomial.supportc                 C   s   | j jS r   )r   r   r   r   r   r   r   W   s    zMultinomial.logitsc                 C   s   | j jS r   )r   r
   r   r   r   r   r
   [   s    zMultinomial.probsc                 C   s   | j jS r   )r   r   r   r   r   r   r   _   s    zMultinomial.param_shapec                 C   s‚   t  |¡}| j t  | jf¡| ¡}tt| ¡ ƒƒ}| | 	d¡¡ |j
|Ž }| |  |¡¡ ¡ }| d|t  |¡¡ | | j¡S )Nr   r   )r%   r&   r   Úsampler   ÚlistÚrangeÚdimÚappendÚpopZpermuter)   Z_extended_shapeZzero_Zscatter_add_Z	ones_likeZtype_asr
   )r   Zsample_shapeZsamplesZshifted_idxÚcountsr   r   r   r.   c   s    
ÿ
zMultinomial.samplec                 C   s|   t  | j¡}| j ¡ }|| t  |d ¡ }| jjdd�dd … }t  | j 	|¡¡}t  |d ¡}||  
ddg¡}|| S )Nr   F)r'   r   r   )r%   Ztensorr   r   ÚentropyÚlgammar   Zenumerate_supportÚexpÚlog_probÚsum)r   ÚnZcat_entropyZterm1r-   Zbinomial_probsÚweightsZterm2r   r   r   r5   q   s    
zMultinomial.entropyc                 C   s†   | j r|  |¡ t| j|ƒ\}}|jtjd�}t | d¡d ¡}t |d ¡ d¡}d||dk|t	 k@ < ||  d¡}|| | S )N)Zmemory_formatr   r   r   )
r(   Z_validate_sampler   r   Úcloner%   Zcontiguous_formatr6   r9   r   )r   Úvaluer   Zlog_factorial_nZlog_factorial_xsZ
log_powersr   r   r   r8   ~   s    
zMultinomial.log_prob)r   NNN)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   ZsimplexZreal_vectorZarg_constraintsr   Ú__annotations__Úpropertyr   r   r!   r'   r*   Zdependent_propertyr-   r   r
   r   r%   r&   r.   r5   r8   Ú__classcell__r   r   r#   r   r      s*   
$






)r%   r   Ztorch.distributionsr   r   Ztorch.distributions.binomialr   Z torch.distributions.distributionr   Ztorch.distributions.utilsr   Ú__all__r   r   r   r   r   Ú<module>   s   