U
    ‰dT!  ã                   @   sp   d dl mZ d dlZd dlZd dlmZ d dlmZ d dlm	Z	m
Z
mZmZmZ d dlmZ G dd„ deƒZdS )	é    )ÚNumberN)Úconstraints)ÚExponentialFamily)Úbroadcast_allÚprobs_to_logitsÚlogits_to_probsÚlazy_propertyÚclamp_probs)Ú binary_cross_entropy_with_logitsc                       s  e Zd ZdZejejdœZejZdZ	dZ
d/‡ fdd„	Zd0‡ fd	d
„	Zdd„ Zdd„ Zdd„ Zdd„ Zedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZe ¡ fdd „Ze ¡ fd!d"„Zd#d$„ Zd%d&„ Zd'd(„ Zd)d*„ Z ed+d,„ ƒZ!d-d.„ Z"‡  Z#S )1ÚContinuousBernoullia›  
    Creates a continuous Bernoulli distribution parameterized by :attr:`probs`
    or :attr:`logits` (but not both).

    The distribution is supported in [0, 1] and parameterized by 'probs' (in
    (0,1)) or 'logits' (real-valued). Note that, unlike the Bernoulli, 'probs'
    does not correspond to a probability and 'logits' does not correspond to
    log-odds, but the same names are used due to the similarity with the
    Bernoulli. See [1] for more details.

    Example::

        >>> m = ContinuousBernoulli(torch.tensor([0.3]))
        >>> m.sample()
        tensor([ 0.2538])

    Args:
        probs (Number, Tensor): (0,1) valued parameters
        logits (Number, Tensor): real valued parameters whose sigmoid matches 'probs'

    [1] The continuous Bernoulli: fixing a pervasive error in variational
    autoencoders, Loaiza-Ganem G and Cunningham JP, NeurIPS 2019.
    https://arxiv.org/abs/1907.06845
    )ÚprobsÚlogitsr   TN©gV-²ïß?gÕxé&1à?c                    sÖ   |d k|d kkrt dƒ‚|d k	rtt|tƒ}t|ƒ\| _|d k	rf| jd  t| dƒ¡ ¡ sft d 	d¡ƒ‚t
| jƒ| _nt|tƒ}t|ƒ\| _|d k	r˜| jn| j| _|r®t ¡ }n
| j ¡ }|| _tt| ƒj||d d S )Nz;Either `probs` or `logits` must be specified, but not both.r   z#The parameter {} has invalid values©Úvalidate_args)Ú
ValueErrorÚ
isinstancer   r   r   Úarg_constraintsÚcheckÚgetattrÚallÚformatr	   r   Ú_paramÚtorchÚSizeÚsizeÚ_limsÚsuperr   Ú__init__)Úselfr   r   Zlimsr   Z	is_scalarÚbatch_shape©Ú	__class__© úL/tmp/pip-unpacked-wheel-ua33x9lu/torch/distributions/continuous_bernoulli.pyr   *   s"    



zContinuousBernoulli.__init__c                    s~   |   t|¡}| j|_t |¡}d| jkr>| j |¡|_|j|_d| jkr^| j	 |¡|_	|j	|_t
t|ƒj|dd | j|_|S )Nr   r   Fr   )Z_get_checked_instancer   r   r   r   Ú__dict__r   Úexpandr   r   r   r   Ú_validate_args)r   r    Z	_instanceÚnewr!   r#   r$   r&   A   s    


zContinuousBernoulli.expandc                 O   s   | j j||ŽS ©N)r   r(   )r   ÚargsÚkwargsr#   r#   r$   Ú_newO   s    zContinuousBernoulli._newc                 C   s,   t  t  | j| jd ¡t  | j| jd ¡¡S )Nr   é   )r   ÚmaxÚler   r   Úgt©r   r#   r#   r$   Ú_outside_unstable_regionR   s    ÿz,ContinuousBernoulli._outside_unstable_regionc                 C   s&   t  |  ¡ | j| jd t  | j¡ ¡S )Nr   )r   Úwherer2   r   r   Ú	ones_liker1   r#   r#   r$   Ú
_cut_probsV   s    
þzContinuousBernoulli._cut_probsc              	   C   sÎ   |   ¡ }t t |d¡|t |¡¡}t t |d¡|t |¡¡}t t t 	| ¡t |¡ ¡¡t t |d¡t 	d| ¡t d| d ¡¡ }t 
| jd d¡}t d¡dd|  |  }t |  ¡ ||¡S )zLcomputes the log normalizing constant as a function of the 'probs' parameterç      à?g       Àç       @ç      ð?é   gUUUUUUõ?gÒ'}Ò'}@)r5   r   r3   r/   Ú
zeros_likeÚger4   ÚlogÚabsÚlog1pÚpowr   Úmathr2   )r   Ú	cut_probsZcut_probs_below_halfZcut_probs_above_halfÚlog_normÚxÚtaylorr#   r#   r$   Ú_cont_bern_log_norm[   s"    þþ$
ýz'ContinuousBernoulli._cont_bern_log_normc                 C   sj   |   ¡ }|d| d  dt | ¡t |¡   }| jd }dddt |d¡  |  }t |  ¡ ||¡S )Nr7   r8   r6   gUUUUUUÕ?glÁlÁÖ?r9   )r5   r   r>   r<   r   r?   r3   r2   )r   rA   ZmusrC   rD   r#   r#   r$   Úmeanl   s
    *
zContinuousBernoulli.meanc                 C   s   t  | j¡S r)   )r   ÚsqrtÚvariancer1   r#   r#   r$   Ústddevt   s    zContinuousBernoulli.stddevc                 C   s‚   |   ¡ }||d  t dd|  d¡ dt t | ¡t |¡ d¡  }t | jd d¡}ddd|  |  }t |  ¡ ||¡S )Nr8   r7   r9   r6   gUUUUUUµ?g±?gg¼jVÁ?)r5   r   r?   r>   r<   r   r3   r2   )r   rA   ÚvarsrC   rD   r#   r#   r$   rH   x   s    $ ÿzContinuousBernoulli.variancec                 C   s   t | jddS ©NT)Z	is_binary)r   r   r1   r#   r#   r$   r      s    zContinuousBernoulli.logitsc                 C   s   t t| jddƒS rK   )r	   r   r   r1   r#   r#   r$   r   …   s    zContinuousBernoulli.probsc                 C   s
   | j  ¡ S r)   )r   r   r1   r#   r#   r$   Úparam_shape‰   s    zContinuousBernoulli.param_shapec              
   C   sL   |   |¡}tj|| jj| jjd}t ¡  |  |¡W  5 Q R £ S Q R X d S ©N)ÚdtypeÚdevice)Ú_extended_shaper   Úrandr   rN   rO   Zno_gradÚicdf©r   Zsample_shapeÚshapeÚur#   r#   r$   Úsample   s    

zContinuousBernoulli.samplec                 C   s,   |   |¡}tj|| jj| jjd}|  |¡S rM   )rP   r   rQ   r   rN   rO   rR   rS   r#   r#   r$   Úrsample“   s    
zContinuousBernoulli.rsamplec                 C   s8   | j r|  |¡ t| j|ƒ\}}t||dd |  ¡  S )NÚnone)Z	reduction)r'   Ú_validate_sampler   r   r
   rE   )r   Úvaluer   r#   r#   r$   Úlog_prob˜   s    
zContinuousBernoulli.log_probc              
   C   s’   | j r|  |¡ |  ¡ }t ||¡t d| d| ¡ | d d| d  }t |  ¡ ||¡}t t |d¡t |¡t t 	|d¡t 
|¡|¡¡S )Nr8   r7   g        )r'   rY   r5   r   r?   r3   r2   r/   r:   r;   r4   )r   rZ   rA   ZcdfsZunbounded_cdfsr#   r#   r$   Úcdfž   s     
ÿÿ
ÿ
ýzContinuousBernoulli.cdfc              	   C   sT   |   ¡ }t |  ¡ t | |d| d   ¡t | ¡ t |¡t | ¡  |¡S )Nr7   r8   )r5   r   r3   r2   r>   r<   )r   rZ   rA   r#   r#   r$   rR   ª   s    
ÿÿüzContinuousBernoulli.icdfc                 C   s4   t  | j ¡}t  | j¡}| j||  |  ¡  | S r)   )r   r>   r   r<   rF   rE   )r   Z
log_probs0Z
log_probs1r#   r#   r$   Úentropy²   s    zContinuousBernoulli.entropyc                 C   s   | j fS r)   )r   r1   r#   r#   r$   Ú_natural_params·   s    z#ContinuousBernoulli._natural_paramsc                 C   s²   t  t  || jd d ¡t  || jd d ¡¡}t  ||| jd d t  |¡ ¡}t  t  t  	|¡d ¡¡t  t  |¡¡ }d| t  
|d¡d  t  
|d¡d  }t  |||¡S )	zLcomputes the log normalizing constant as a function of the natural parameterr   r6   r-   r8   r9   g      8@é   g     €¦@)r   r.   r/   r   r0   r3   r4   r<   r=   Úexpr?   )r   rC   Zout_unst_regZcut_nat_paramsrB   rD   r#   r#   r$   Ú_log_normalizer»   s    ÿþ*(z#ContinuousBernoulli._log_normalizer)NNr   N)N)$Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   Zunit_intervalÚrealr   ZsupportZ_mean_carrier_measureZhas_rsampler   r&   r,   r2   r5   rE   ÚpropertyrF   rI   rH   r   r   r   rL   r   r   rV   rW   r[   r\   rR   r]   r^   ra   Ú__classcell__r#   r#   r!   r$   r      sD   ÿ






r   )Znumbersr   r@   r   Ztorch.distributionsr   Ztorch.distributions.exp_familyr   Ztorch.distributions.utilsr   r   r   r   r	   Ztorch.nn.functionalr
   r   r#   r#   r#   r$   Ú<module>   s   