§
    Ÿ²ÅjÏ"  ã                   óˆ   — d dl mZ d dlZd dlmZ d dlmZ d dlmZ d dl	m
Z
mZ d dlmZ d dlmZ d	gZ G d
„ d	e¦  «        ZdS )é    )ÚDictN)Úconstraints)ÚDistribution)ÚIndependent)ÚComposeTransformÚ	Transform)Ú_sum_rightmost)Ú_sizeÚTransformedDistributionc                   ó  ‡ — e Zd ZU dZi Zeeej        f         e	d<   dˆ fd„	Z
dˆ fd„	Z ej        d¬¦  «        d„ ¦   «         Zed	„ ¦   «         Z ej        ¦   «         fd
„Z ej        ¦   «         fdedej        fd„Zd„ Zd„ Zd„ Zd„ Zˆ xZS )r   a±  
    Extension of the Distribution class, which applies a sequence of Transforms
    to a base distribution.  Let f be the composition of transforms applied::

        X ~ BaseDistribution
        Y = f(X) ~ TransformedDistribution(BaseDistribution, f)
        log p(Y) = log p(X) + log |det (dX/dY)|

    Note that the ``.event_shape`` of a :class:`TransformedDistribution` is the
    maximum shape of its base distribution and its transforms, since transforms
    can introduce correlations among events.

    An example for the usage of :class:`TransformedDistribution` would be::

        # Building a Logistic Distribution
        # X ~ Uniform(0, 1)
        # f = a + b * logit(X)
        # Y ~ f(X) ~ Logistic(a, b)
        base_distribution = Uniform(0, 1)
        transforms = [SigmoidTransform().inv, AffineTransform(loc=a, scale=b)]
        logistic = TransformedDistribution(base_distribution, transforms)

    For more examples, please look at the implementations of
    :class:`~torch.distributions.gumbel.Gumbel`,
    :class:`~torch.distributions.half_cauchy.HalfCauchy`,
    :class:`~torch.distributions.half_normal.HalfNormal`,
    :class:`~torch.distributions.log_normal.LogNormal`,
    :class:`~torch.distributions.pareto.Pareto`,
    :class:`~torch.distributions.weibull.Weibull`,
    :class:`~torch.distributions.relaxed_bernoulli.RelaxedBernoulli` and
    :class:`~torch.distributions.relaxed_categorical.RelaxedOneHotCategorical`
    Úarg_constraintsNc                 ó  •— t          |t          ¦  «        r	|g| _        nWt          |t          ¦  «        r0t	          d„ |D ¦   «         ¦  «        st          d¦  «        ‚|| _        nt          d|› �¦  «        ‚|j        |j        z   }t          |j        ¦  «        }t          | j        ¦  «        }t          |¦  «        |j
        j        k     r t          d|j
        j        › d|› d�¦  «        ‚|                     |¦  «        }|                     |¦  «        }||k    r/|d t          |¦  «        |z
  …         }	|                     |	¦  «        }|j
        j        |z
  }
|
dk    rt          ||
¦  «        }|| _        |j        j        |j
        j        z
  }t%          |j        j        ||z   ¦  «        }t          |¦  «        |k    sJ ‚t          |¦  «        |z
  }|d |…         }||d …         }t'          ¦   «                              |||¬¦  «         d S )	Nc              3   ó@   K  — | ]}t          |t          ¦  «        V — Œd S ©N)Ú
isinstancer   )Ú.0Úts     ú]C:\Projects\Historical\venv\Lib\site-packages\torch/distributions/transformed_distribution.pyú	<genexpr>z3TransformedDistribution.__init__.<locals>.<genexpr>9   s,   è è € ÐDÐD°A•z !¥YÑ/Ô/ÐDÐDÐDÐDÐDÐDó    z6transforms must be a Transform or a list of Transformsz0transforms must be a Transform or list, but was z9base_distribution needs to have shape with size at least z
, but got ú.r   ©Úvalidate_args)r   r   Ú
transformsÚlistÚallÚ
ValueErrorÚbatch_shapeÚevent_shapeÚlenr   ÚdomainÚ	event_dimÚforward_shapeÚinverse_shapeÚexpandr   Ú	base_distÚcodomainÚmaxÚsuperÚ__init__)ÚselfÚbase_distributionr   r   Ú
base_shapeÚbase_event_dimÚ	transformr#   Úexpanded_base_shapeÚbase_batch_shapeÚreinterpreted_batch_ndimsÚtransform_change_in_event_dimr"   Úcutr   r   Ú	__class__s                   €r   r*   z TransformedDistribution.__init__3   s`  ø€ Ý�j¥)Ñ,Ô,ð 	àðˆDŒOˆOõ ˜
¥DÑ)Ô)ð 		ÝÐDÐD¸ÐDÑDÔDÑDÔDð Ý ØLñô ð ð )ˆDŒOˆOåØOÀ:ÐOÐOñô ð ð
 'Ô2Ð5FÔ5RÑRˆ
ÝÐ.Ô:Ñ;Ô;ˆÝ$ T¤_Ñ5Ô5ˆ	Ýˆz‰?Œ?˜YÔ-Ô7Ò7Ð7ÝØÈIÔL\ÔLfÐÐÐr|ÐÐÐñô ð ð "×/Ò/°
Ñ;Ô;ˆØ'×5Ò5°mÑDÔDÐØÐ,Ò,Ð,Ø2Ø;•#Ð)Ñ*Ô*¨^Ñ;Ð;ô Ðð !2× 8Ò 8Ð9IÑ JÔ JÐØ$-Ô$4Ô$>ÀÑ$OÐ!Ø$ qÒ(Ð(Ý +Ø!Ð#<ñ!ô !Ðð +ˆŒð ÔÔ(¨9Ô+;Ô+EÑEð 	&õ ØÔÔ(ØÐ:Ñ:ñ
ô 
ˆ	õ �=Ñ!Ô! YÒ.Ð.Ð.Ð.Ý�-Ñ Ô  9Ñ,ˆØ# D S DÔ)ˆØ# C D DÔ)ˆÝ‰Œ×Ò˜ kÀÐÑOÔOÐOÐOÐOr   c                 ó  •— |                       t          |¦  «        }t          j        |¦  «        }|| j        z   }t          | j        ¦  «        D ]}|                     |¦  «        }Œ|d t          |¦  «        t          | j	        j        ¦  «        z
  …         }| j	         
                    |¦  «        |_	        | j        |_        t          t          |¦  «                             || j        d¬¦  «         | j        |_        |S )NFr   )Ú_get_checked_instancer   ÚtorchÚSizer   Úreversedr   r$   r    r&   r%   r)   r*   Ú_validate_args)r+   r   Ú	_instanceÚnewÚshaper   r1   r5   s          €r   r%   zTransformedDistribution.expandg   sï   ø€ Ø×(Ò(Õ)@À)ÑLÔLˆÝ”j Ñ-Ô-ˆØ˜dÔ.Ñ.ˆÝ˜$œ/Ñ*Ô*ð 	+ð 	+ˆAØ—O’O EÑ*Ô*ˆEˆEØ Ð!O¥3 u¡:¤:µ°D´NÔ4NÑ0OÔ0OÑ#OÐ!OÔPÐØœ×-Ò-Ð.>Ñ?Ô?ˆŒØœˆŒÝÕ% sÑ+Ô+×4Ò4Ø˜Ô)¸ð 	5ñ 	
ô 	
ð 	
ð "Ô0ˆÔØˆ
r   F)Úis_discretec                 óè   — | j         s| j        j        S | j         d         j        }t	          | j        ¦  «        |j        k    r/t          j        |t	          | j        ¦  «        |j        z
  ¦  «        }|S )Néÿÿÿÿ)	r   r&   Úsupportr'   r    r   r"   r   Úindependent)r+   rB   s     r   rB   zTransformedDistribution.supportv   sp   € àŒð 	*Ø”>Ô)Ð)Ø”/ "Ô%Ô.ˆÝˆtÔÑ Ô  7Ô#4Ò4Ð4Ý!Ô-Ø�˜TÔ-Ñ.Ô.°Ô1BÑBñô ˆGð ˆr   c                 ó   — | j         j        S r   )r&   Úhas_rsample)r+   s    r   rE   z#TransformedDistribution.has_rsample�   s   € àŒ~Ô)Ð)r   c                 ó¾   — t          j        ¦   «         5  | j                             |¦  «        }| j        D ]} ||¦  «        }Œ|cddd¦  «         S # 1 swxY w Y   dS )a  
        Generates a sample_shape shaped sample or sample_shape shaped batch of
        samples if the distribution parameters are batched. Samples first from
        base distribution and applies `transform()` for every transform in the
        list.
        N)r8   Úno_gradr&   Úsampler   ©r+   Úsample_shapeÚxr/   s       r   rH   zTransformedDistribution.sample…   s¬   € õ Œ]‰_Œ_ð 	ð 	Ø”×%Ò% lÑ3Ô3ˆAØ!œ_ð !ð !�	Ø�I˜a‘L”L��Øð		ð 	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s   ”1AÁAÁArJ   Úreturnc                 ód   — | j                              |¦  «        }| j        D ]} ||¦  «        }Œ|S )a$  
        Generates a sample_shape shaped reparameterized sample or sample_shape
        shaped batch of reparameterized samples if the distribution parameters
        are batched. Samples first from base distribution and applies
        `transform()` for every transform in the list.
        )r&   Úrsampler   rI   s       r   rN   zTransformedDistribution.rsample’   s>   € ð ŒN×"Ò" <Ñ0Ô0ˆØœð 	ð 	ˆIØ�	˜!‘”ˆAˆAØˆr   c                 óô  — | j         r|                      |¦  «         t          | j        ¦  «        }d}|}t	          | j        ¦  «        D ]i}|                     |¦  «        }||j        j        |j	        j        z
  z  }|t          |                     ||¦  «        ||j        j        z
  ¦  «        z
  }|}Œj|t          | j                             |¦  «        |t          | j        j        ¦  «        z
  ¦  «        z   }|S )z¨
        Scores the sample by inverting the transform(s) and computing the score
        using the score of the base distribution and the log abs det jacobian.
        g        )r;   Ú_validate_sampler    r   r:   r   Úinvr!   r"   r'   r	   Úlog_abs_det_jacobianr&   Úlog_prob)r+   Úvaluer"   rS   Úyr/   rK   s          r   rS   z TransformedDistribution.log_probž   s  € ð
 Ôð 	)Ø×!Ò! %Ñ(Ô(Ð(Ý˜Ô(Ñ)Ô)ˆ	ØˆØˆÝ! $¤/Ñ2Ô2ð 	ð 	ˆIØ—’˜aÑ Ô ˆAØ˜Ô)Ô3°iÔ6HÔ6RÑRÑRˆIØ¥.Ø×.Ò.¨q°!Ñ4Ô4Ø˜IÔ,Ô6Ñ6ñ#ô #ñ ˆHð ˆAˆAà�nØŒN×#Ò# AÑ&Ô&¨	µC¸¼Ô8RÑ4SÔ4SÑ(Sñ
ô 
ñ 
ˆð ˆr   c                 ó~   — d}| j         D ]}||j        z  }Œt          |t          ¦  «        r|dk    r|S ||dz
  z  dz   S )zu
        This conditionally flips ``value -> 1-value`` to ensure :meth:`cdf` is
        monotone increasing.
        é   g      à?)r   Úsignr   Úint)r+   rT   rX   r/   s       r   Ú_monotonize_cdfz'TransformedDistribution._monotonize_cdf¶   s[   € ð
 ˆØœð 	)ð 	)ˆIØ˜)œ.Ñ(ˆDˆDÝ�d�CÑ Ô ð 	 T¨Q¢Y YØˆLØ�u˜s‘{Ñ# cÑ)Ð)r   c                 óö   — | j         ddd…         D ]}|                     |¦  «        }Œ| j        r| j                             |¦  «         | j                             |¦  «        }|                      |¦  «        }|S )z—
        Computes the cumulative distribution function by inverting the
        transform(s) and computing the score of the base distribution.
        NrA   )r   rQ   r;   r&   rP   ÚcdfrZ   ©r+   rT   r/   s      r   r\   zTransformedDistribution.cdfÂ   s�   € ð
 œ¨¨¨2¨Ô.ð 	)ð 	)ˆIØ—M’M %Ñ(Ô(ˆEˆEØÔð 	3ØŒN×+Ò+¨EÑ2Ô2Ð2Ø”×"Ò" 5Ñ)Ô)ˆØ×$Ò$ UÑ+Ô+ˆØˆr   c                 óŽ   — |                       |¦  «        }| j                             |¦  «        }| j        D ]} ||¦  «        }Œ|S )z”
        Computes the inverse cumulative distribution function using
        transform(s) and computing the score of the base distribution.
        )rZ   r&   Úicdfr   r]   s      r   r_   zTransformedDistribution.icdfÏ   sS   € ð
 ×$Ò$ UÑ+Ô+ˆØ”×#Ò# EÑ*Ô*ˆØœð 	%ð 	%ˆIØ�I˜eÑ$Ô$ˆEˆEØˆr   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   Ústrr   Ú
ConstraintÚ__annotations__r*   r%   Údependent_propertyrB   ÚpropertyrE   r8   r9   rH   r
   ÚTensorrN   rS   rZ   r\   r_   Ú__classcell__)r5   s   @r   r   r      sh  ø€ € € € € € ðð ð@ :<€O�T˜#˜{Ô5Ð5Ô6Ð;Ð;Ñ;ð2Pð 2Pð 2Pð 2Pð 2Pð 2Pðhð ð ð ð ð ð $€[Ô#°Ð6Ñ6Ô6ðð ñ 7Ô6ðð ð*ð *ñ „Xð*ð #- %¤*¡,¤,ð ð ð ð ð -7¨E¬J©L¬Lð 
ð 
 Eð 
¸U¼\ð 
ð 
ð 
ð 
ðð ð ð0
*ð 
*ð 
*ðð ð ð	ð 	ð 	ð 	ð 	ð 	ð 	r   )Útypingr   r8   Útorch.distributionsr   Ú torch.distributions.distributionr   Útorch.distributions.independentr   Útorch.distributions.transformsr   r   Útorch.distributions.utilsr	   Útorch.typesr
   Ú__all__r   © r   r   ú<module>rt      sÚ   ðà Ð Ð Ð Ð Ð à €€€Ø +Ð +Ð +Ð +Ð +Ð +Ø 9Ð 9Ð 9Ð 9Ð 9Ð 9Ø 7Ð 7Ð 7Ð 7Ð 7Ð 7Ø FÐ FÐ FÐ FÐ FÐ FÐ FÐ FØ 4Ð 4Ð 4Ð 4Ð 4Ð 4Ø Ð Ð Ð Ð Ð ð %Ð
%€ðHð Hð Hð Hð H˜lñ Hô Hð Hð Hð Hr   