o
    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
defddZe
defddZ			
	
	
d$dedee dee dee dd
f
 fddZd% fdd	Zdd Zejdd	ddd Ze
defddZe
defddZe
dejf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   e/home/www/facesmatcher.com/frenv_anti/lib/python3.10/site-packages/torch/distributions/multinomial.pymean8      zMultinomial.meanc                 C   s   | j | j d| j  S )N   r   r   r   r   r   r   variance<   s   zMultinomial.variancer   Nr   r   validate_argsc                    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^   r   zMultinomial.supportc                 C      | j jS r   )r    r   r   r   r   r   r   b      zMultinomial.logitsc                 C   r2   r   )r    r   r   r   r   r   r   f   r3   zMultinomial.probsc                 C   r2   r   )r    r#   r   r   r   r   r#   j   r3   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   r4   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term1r1   Zbinomial_probsweightsZterm2r   r   r   r;   |   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_formatr<   r?   r   )r   valuer   Zlog_factorial_nZlog_factorial_xsZ
log_powersr   r   r   r>      s   
zMultinomial.log_prob)r   NNNr   )__name__
__module____qualname____doc__r   ZsimplexZreal_vectorZarg_constraintsr   __annotations__propertyr   r   r   r   boolr%   r+   r.   Zdependent_propertyr1   r   r   r)   r*   r#   r4   r;   r>   __classcell__r   r   r'   r   r
      sH   
 %
)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   