U
    d                     @   s   d dl Z d dlmZ d dlmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZmZmZmZmZ G dd	 d	eZG d
d deZdS )    N)Number)constraints)Distribution)TransformedDistribution)SigmoidTransform)broadcast_allprobs_to_logitslogits_to_probslazy_propertyclamp_probsc                       s   e Zd ZdZejejdZejZd fdd	Z	d fdd	Z
dd	 Zed
d Zedd Zedd Ze fddZdd Z  ZS )LogitRelaxedBernoullia  
    Creates a LogitRelaxedBernoulli distribution parameterized by :attr:`probs`
    or :attr:`logits` (but not both), which is the logit of a RelaxedBernoulli
    distribution.

    Samples are logits of values in (0, 1). See [1] for more details.

    Args:
        temperature (Tensor): relaxation temperature
        probs (Number, Tensor): the probability of sampling `1`
        logits (Number, Tensor): the log-odds of sampling `1`

    [1] The Concrete Distribution: A Continuous Relaxation of Discrete Random
    Variables (Maddison et al, 2017)

    [2] Categorical Reparametrization with Gumbel-Softmax
    (Jang et al, 2017)
    probslogitsNc                    s   || _ |d k|d kkrtd|d k	r>t|t}t|\| _nt|t}t|\| _|d k	rb| jn| j| _|rxt	 }n
| j
 }tt| j||d d S )Nz;Either `probs` or `logits` must be specified, but not both.validate_args)temperature
ValueError
isinstancer   r   r   r   _paramtorchSizesizesuperr   __init__)selfr   r   r   r   Z	is_scalarbatch_shape	__class__ I/tmp/pip-unpacked-wheel-ua33x9lu/torch/distributions/relaxed_bernoulli.pyr   !   s    



zLogitRelaxedBernoulli.__init__c                    s~   |  t|}t|}| j|_d| jkr>| j||_|j|_d| jkr^| j	||_	|j	|_t
t|j|dd | j|_|S )Nr   r   Fr   )_get_checked_instancer   r   r   r   __dict__r   expandr   r   r   r   _validate_argsr   r   	_instancenewr   r   r    r#   2   s    


zLogitRelaxedBernoulli.expandc                 O   s   | j j||S N)r   r'   )r   argskwargsr   r   r    _new@   s    zLogitRelaxedBernoulli._newc                 C   s   t | jddS NT)Z	is_binary)r   r   r   r   r   r    r   C   s    zLogitRelaxedBernoulli.logitsc                 C   s   t | jddS r,   )r	   r   r-   r   r   r    r   G   s    zLogitRelaxedBernoulli.probsc                 C   s
   | j  S r(   )r   r   r-   r   r   r    param_shapeK   s    z!LogitRelaxedBernoulli.param_shapec                 C   s\   |  |}t| j|}ttj||j|jd}| | 	  |  | 	  | j
 S )N)dtypedevice)Z_extended_shaper   r   r#   r   Zrandr/   r0   loglog1pr   )r   Zsample_shapeshaper   Zuniformsr   r   r    rsampleO   s    
zLogitRelaxedBernoulli.rsamplec                 C   sN   | j r| | t| j|\}}||| j }| j | d|    S )N   )	r$   Z_validate_sampler   r   mulr   r1   expr2   )r   valuer   Zdiffr   r   r    log_probU   s
    
zLogitRelaxedBernoulli.log_prob)NNN)N)__name__
__module____qualname____doc__r   unit_intervalrealarg_constraintssupportr   r#   r+   r
   r   r   propertyr.   r   r   r4   r9   __classcell__r   r   r   r    r   
   s    


r   c                       sl   e Zd ZdZejejdZejZdZ	d fdd	Z
d fdd	Zed	d
 Zedd Zedd Z  ZS )RelaxedBernoullia  
    Creates a RelaxedBernoulli distribution, parametrized by
    :attr:`temperature`, and either :attr:`probs` or :attr:`logits`
    (but not both). This is a relaxed version of the `Bernoulli` distribution,
    so the values are in (0, 1), and has reparametrizable samples.

    Example::

        >>> m = RelaxedBernoulli(torch.tensor([2.2]),
                                 torch.tensor([0.1, 0.2, 0.3, 0.99]))
        >>> m.sample()
        tensor([ 0.2951,  0.3442,  0.8918,  0.9021])

    Args:
        temperature (Tensor): relaxation temperature
        probs (Number, Tensor): the probability of sampling `1`
        logits (Number, Tensor): the log-odds of sampling `1`
    r   TNc                    s(   t |||}tt| j|t |d d S )Nr   )r   r   rD   r   r   )r   r   r   r   r   	base_distr   r   r    r   u   s
    zRelaxedBernoulli.__init__c                    s    |  t|}tt| j||dS )N)r&   )r!   rD   r   r#   r%   r   r   r    r#   {   s    zRelaxedBernoulli.expandc                 C   s   | j jS r(   )rE   r   r-   r   r   r    r      s    zRelaxedBernoulli.temperaturec                 C   s   | j jS r(   )rE   r   r-   r   r   r    r      s    zRelaxedBernoulli.logitsc                 C   s   | j jS r(   )rE   r   r-   r   r   r    r      s    zRelaxedBernoulli.probs)NNN)N)r:   r;   r<   r=   r   r>   r?   r@   rA   Zhas_rsampler   r#   rB   r   r   r   rC   r   r   r   r    rD   ]   s   

rD   )r   Znumbersr   Ztorch.distributionsr   Z torch.distributions.distributionr   Z,torch.distributions.transformed_distributionr   Ztorch.distributions.transformsr   Ztorch.distributions.utilsr   r   r	   r
   r   r   rD   r   r   r   r    <module>   s   S