U
    d!                     @   sL   d dl Z d dlmZ d dlmZ d dlmZ d dlmZ G dd deZdS )    N)Distribution)Categorical)constraints)Dictc                       s   e Zd ZU dZi Zeeejf e	d< dZ
d fdd	Zd  fdd	Zejd	d
 Zedd Zedd Zedd Zedd Zdd Zdd Ze fddZdd Zdd Zdd Z  ZS )!MixtureSameFamilya  
    The `MixtureSameFamily` distribution implements a (batch of) mixture
    distribution where all component are from different parameterizations of
    the same distribution type. It is parameterized by a `Categorical`
    "selecting distribution" (over `k` component) and a component
    distribution, i.e., a `Distribution` with a rightmost batch shape
    (equal to `[k]`) which indexes each (batch of) component.

    Examples::

        # Construct Gaussian Mixture Model in 1D consisting of 5 equally
        # weighted normal distributions
        >>> mix = D.Categorical(torch.ones(5,))
        >>> comp = D.Normal(torch.randn(5,), torch.rand(5,))
        >>> gmm = MixtureSameFamily(mix, comp)

        # Construct Gaussian Mixture Modle in 2D consisting of 5 equally
        # weighted bivariate normal distributions
        >>> mix = D.Categorical(torch.ones(5,))
        >>> comp = D.Independent(D.Normal(
                     torch.randn(5,2), torch.rand(5,2)), 1)
        >>> gmm = MixtureSameFamily(mix, comp)

        # Construct a batch of 3 Gaussian Mixture Models in 2D each
        # consisting of 5 random weighted bivariate normal distributions
        >>> mix = D.Categorical(torch.rand(3,5))
        >>> comp = D.Independent(D.Normal(
                    torch.randn(3,5,2), torch.rand(3,5,2)), 1)
        >>> gmm = MixtureSameFamily(mix, comp)

    Args:
        mixture_distribution: `torch.distributions.Categorical`-like
            instance. Manages the probability of selecting component.
            The number of categories must match the rightmost batch
            dimension of the `component_distribution`. Must have either
            scalar `batch_shape` or `batch_shape` matching
            `component_distribution.batch_shape[:-1]`
        component_distribution: `torch.distributions.Distribution`-like
            instance. Right-most batch dimension indexes component.
    arg_constraintsFNc                    s  || _ || _t| j ts tdt| jts4td| j j}| jjd d }tt|t|D ]0\}}|dkr^|dkr^||kr^td	||q^| j j
jd }| jjd }	|d k	r|	d k	r||	krtd	||	|| _| jj}
t|
| _tt| j||
|d d S )NzV The Mixture distribution needs to be an  instance of torch.distribtutions.CategoricalzUThe Component distribution need to be an instance of torch.distributions.Distribution   zi`mixture_distribution.batch_shape` ({0}) is not compatible with `component_distribution.batch_shape`({1})zd`mixture_distribution component` ({0}) does not equal `component_distribution.batch_shape[-1]` ({1})batch_shapeevent_shapevalidate_args)_mixture_distribution_component_distribution
isinstancer   
ValueErrorr   r   zipreversedformatlogitsshape_num_componentr   len_event_ndimssuperr   __init__)selfmixture_distributioncomponent_distributionr   ZmdbsZcdbsZsize1Zsize2kmZkcr   	__class__ K/tmp/pip-unpacked-wheel-ua33x9lu/torch/distributions/mixture_same_family.pyr   4   s8      
zMixtureSameFamily.__init__c                    sx   t |}|| jf }| t|}| j||_| j||_| j|_| j|_|jj	}t
t|j||dd | j|_|S )NFr
   )torchSizer   Z_get_checked_instancer   r   expandr   r   r   r   r   _validate_args)r   r   Z	_instanceZbatch_shape_compnewr   r    r"   r#   r&   [   s     


zMixtureSameFamily.expandc                 C   s   | j jS N)r   supportr   r"   r"   r#   r*   l   s    zMixtureSameFamily.supportc                 C   s   | j S r)   )r   r+   r"   r"   r#   r   r   s    z&MixtureSameFamily.mixture_distributionc                 C   s   | j S r)   )r   r+   r"   r"   r#   r   v   s    z(MixtureSameFamily.component_distributionc                 C   s*   |  | jj}tj|| jj d| j dS Nr   Zdim)_pad_mixture_dimensionsr   probsr$   sumr   meanr   )r   r/   r"   r"   r#   r1   z   s    zMixtureSameFamily.meanc                 C   s`   |  | jj}tj|| jj d| j d}tj|| jj| 	| j 
d d| j d}|| S )Nr   r-   g       @)r.   r   r/   r$   r0   r   variancer   r1   _padpow)r   r/   Zmean_cond_varZvar_cond_meanr"   r"   r#   r2      s    
zMixtureSameFamily.variancec                 C   s0   |  |}| j|}| jj}tj|| ddS r,   )r3   r   cdfr   r/   r$   r0   )r   xZcdf_xZmix_probr"   r"   r#   r5      s    
zMixtureSameFamily.cdfc                 C   sJ   | j r| | | |}| j|}tj| jjdd}tj	|| ddS r,   )
r'   Z_validate_sampler3   r   log_probr$   Zlog_softmaxr   r   Z	logsumexp)r   r6   Z
log_prob_xZlog_mix_probr"   r"   r#   r7      s    


zMixtureSameFamily.log_probc              
   C   s   t   t|}t| j}|| }| j}| j|}|j}| j|}|	|t 
dgt|d   }	|	t 
dgt| t 
dg | }	t |||	}
|
|W  5 Q R  S Q R X d S )Nr	   )r$   Zno_gradr   r   r   r   sampler   r   reshaper%   repeatZgatherZsqueeze)r   Zsample_shapeZ
sample_lenZ	batch_lenZ
gather_dimesZ
mix_sampleZ	mix_shapeZcomp_samplesZmix_sample_rZsamplesr"   r"   r#   r8      s     

"zMixtureSameFamily.samplec                 C   s   | d| j S )Nr   )Z	unsqueezer   )r   r6   r"   r"   r#   r3      s    zMixtureSameFamily._padc                 C   st   | j  }| jj  }|dkr"dn|| }|j}||d d t|dg  |dd   t| jdg  }|S )Nr	   r   r   )r   Znumelr   r   r9   r$   r%   r   )r   r6   Zdist_batch_ndimsZcat_batch_ndimsZ	pad_ndimsxsr"   r"   r#   r.      s    

z)MixtureSameFamily._pad_mixture_dimensionsc                 C   s   d | j| j}d| d S )Nz
  {},
  {}zMixtureSameFamily())r   r   r   )r   args_stringr"   r"   r#   __repr__   s    zMixtureSameFamily.__repr__)N)N)__name__
__module____qualname____doc__r   r   strr   Z
Constraint__annotations__Zhas_rsampler   r&   Zdependent_propertyr*   propertyr   r   r1   r2   r5   r7   r$   r%   r8   r3   r.   r?   __classcell__r"   r"   r    r#   r      s,   
( '





	
r   )	r$   Z torch.distributions.distributionr   Ztorch.distributionsr   r   typingr   r   r"   r"   r"   r#   <module>   s
   