a
    ‘º”h  ã                   @   sr   d dl mZ d dlZd dlmZ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 )
é    )ÚOptionalN)ÚinfÚTensor)Ú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
edœdd„ƒZe
edœdd„ƒZd"eee ee ee d
dœ‡ fdd„Zd#‡ fdd„	Zdd„ Zejdd	ddd„ ƒZe
edœdd„ƒZe
edœdd„ƒZe
ejdœ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_count)Úreturnc                 C   s   | j | j S ©N)r   r   ©Úself© r   úM/var/www/auris/lib/python3.9/site-packages/torch/distributions/multinomial.pyÚmean8   s    zMultinomial.meanc                 C   s   | j | j d| j  S )Né   ©r   r   r   r   r   r   Úvariance<   s    zMultinomial.variancer   N)r   r   r   Úvalidate_argsr   c                    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   éÿÿÿÿ©r   )Ú
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*   P   s    

ÿzMultinomial.expandc                 O   s   | j j|i |¤ŽS r   )r   Ú_new)r   ÚargsÚkwargsr   r   r   r-   [   s    zMultinomial._newT)Zis_discreteZ	event_dimc                 C   s   t  | j¡S r   )r   Zmultinomialr   r   r   r   r   Úsupport^   s    zMultinomial.supportc                 C   s   | j jS r   )r   r   r   r   r   r   r   b   s    zMultinomial.logitsc                 C   s   | j jS r   )r   r   r   r   r   r   r   f   s    zMultinomial.probsc                 C   s   | j jS r   )r   r"   r   r   r   r   r"   j   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ÚrangeZ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   r1   n   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term1r0   Zbinomial_probsÚweightsZterm2r   r   r   r7   |   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_formatr8   r;   r   )r   Úvaluer   Zlog_factorial_nZlog_factorial_xsZ
log_powersr   r   r   r:   ‰   s    
zMultinomial.log_prob)r   NNN)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   ZsimplexZreal_vectorZarg_constraintsr   Ú__annotations__Úpropertyr   r   r   r   Úboolr$   r*   r-   Zdependent_propertyr0   r   r   r(   r)   r"   r1   r7   r:   Ú__classcell__r   r   r&   r   r
      s>   
%    ûú
)Útypingr   r(   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   