
    ȅi=#                         S SK r S SK Jr  S SKJr  S SKJr  S SKJr  S SKJ	r	J
r
  S SKJr  S SKJr  S	/r " S
 S	\5      rg)    N)Tensor)constraints)Distribution)Independent)ComposeTransform	Transform)_sum_rightmost)_sizeTransformedDistributionc            	       R  ^  \ rS rSr% Sr0 r\\\R                  4   \
S'    SS\S\\\   -  S\S-  SS4U 4S	 jjjrSU 4S
 jjr\R"                  " SS9S 5       r\S\4S j5       r\R,                  " 5       4S jr\R,                  " 5       4S\S\4S jjrS rS rS rS rSrU =r $ )r      aI  
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_constraintsNbase_distribution
transformsvalidate_argsreturnc                   > [        U[        5      (       a	  U/U l        OL[        U[        5      (       a)  [	        S U 5       5      (       d  [        S5      eX l        O[        SU 35      eUR                  UR                  -   n[        UR                  5      n[        U R                  5      n[        U5      UR                  R                  :  a&  [        SUR                  R                   SU S35      eUR                  U5      nUR                  U5      nXH:w  a"  US [        U5      U-
   n	UR                  U	5      nUR                  R                  U-
  n
U
S:  a  [        X5      nXl        UR"                  R                  UR                  R                  -
  n[%        UR"                  R                  X[-   5      n[        U5      U:  a  ['        S[        U5       S	U 35      e[        U5      U-
  nUS U nX}S  n[(        TU ]U  XUS
9  g )Nc              3   B   #    U  H  n[        U[        5      v   M     g 7fN)
isinstancer   ).0ts     f/home/james-whalen/.local/lib/python3.13/site-packages/torch/distributions/transformed_distribution.py	<genexpr>3TransformedDistribution.__init__.<locals>.<genexpr>?   s     DAz!Y//s   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   zforward_shape length z must be >= event_dim r   )r   r   r   listall
ValueErrorbatch_shapeevent_shapelenr   domain	event_dimforward_shapeinverse_shapeexpandr   	base_distcodomainmaxAssertionErrorsuper__init__)selfr   r   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.    TransformedDistribution.__init__4   s.    j),,DO 
D))DDDD L  )OB:,O 
 '225F5R5RR
.::;$T__5	z?Y--777KIL\L\LfLfKggqr|q}}~  "//
;'55mD,2;#)*^;  !2 8 89I J$-$4$4$>$>$O!$q( +!! + ((9+;+;+E+EE 	& ((:
	 }	) 'M(:';;QR[Q\]  - 9,#DS)#D)O    c                   > U R                  [        U5      n[        R                  " U5      nXR                  -   n[        U R                  5       H  nUR                  U5      nM     US [        U5      [        U R                  R                  5      -
   nU R                  R                  U5      Ul	        U R                  Ul        [        [        U]3  XR                  SS9  U R                  Ul        U$ )NFr   )_get_checked_instancer   torchSizer"   reversedr   r'   r#   r)   r(   r-   r.   _validate_args)r/   r!   	_instancenewshaper   r4   r8   s          r   r(   TransformedDistribution.expandp   s    (()@)Ljj-...$//*AOOE*E + !O3u:DNN4N4N0O#OP--.>?%s4)) 	5 	
 "00
r:   F)is_discretec                 :   U R                   (       d  U R                  R                  $ U R                   S   R                  n[	        U R
                  5      UR                  :  a7  [        R                  " U[	        U R
                  5      UR                  -
  5      nU$ )N)	r   r)   supportr*   r#   r"   r%   r   independent)r/   rH   s     r   rH   TransformedDistribution.support   sz     >>)))//"%..t 7#4#44!--T--.1B1BBG r:   c                 .    U R                   R                  $ r   )r)   has_rsample)r/   s    r   rL   #TransformedDistribution.has_rsample   s    ~~)))r:   c                     [         R                  " 5          U R                  R                  U5      nU R                   H  nU" U5      nM     UsSSS5        $ ! , (       d  f       g= f)z
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)r=   no_gradr)   sampler   r/   sample_shapexr2   s       r   rP   TransformedDistribution.sample   sE     ]]_%%l3A!__	aL -	 __s   8A
A&rR   c                 r    U R                   R                  U5      nU R                   H  nU" U5      nM     U$ )z
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   rQ   s       r   rV   TransformedDistribution.rsample   s4     NN""<0I!A )r:   c                 0   U R                   (       a  U R                  U5        [        U R                  5      nSnUn[	        U R
                  5       Hy  nUR                  U5      nX%R                  R                  UR                  R                  -
  -  nU[        UR                  Xd5      X%R                  R                  -
  5      -
  nUnM{     U[        U R                  R                  U5      U[        U R                  R                  5      -
  5      -   nU$ )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%   r\   yr2   rS   s          r   r\    TransformedDistribution.log_prob   s    
 !!%((()	#&!$//2Ia A))33i6H6H6R6RRRI...q4,,666# H A 3 nNN##A&	C8R8R4S(S
 
 r:   c                     SnU R                    H  nX#R                  -  nM     [        U[        5      (       a  US:X  a  U$ X!S-
  -  S-   $ )z]
This conditionally flips ``value -> 1-value`` to ensure :meth:`cdf` is
monotone increasing.
   g      ?)r   signr   int)r/   r]   rb   r2   s       r   _monotonize_cdf'TransformedDistribution._monotonize_cdf   sM    
 I..(D )dC  TQYLs{#c))r:   c                 
   U R                   SSS2    H  nUR                  U5      nM     U R                  (       a  U R                  R	                  U5        U R                  R                  U5      nU R                  U5      nU$ )z
Computes the cumulative distribution function by inverting the
transform(s) and computing the score of the base distribution.
NrG   )r   rZ   r@   r)   rY   cdfrd   r/   r]   r2   s      r   rg   TransformedDistribution.cdf   sm    
 2.IMM%(E /NN++E2""5)$$U+r:   c                     U R                  U5      nU R                  R                  U5      nU R                   H  nU" U5      nM     U$ )z|
Computes the inverse cumulative distribution function using
transform(s) and computing the score of the base distribution.
)rd   r)   icdfr   rh   s      r   rk   TransformedDistribution.icdf   sE    
 $$U+##E*Ie$E )r:   )r)   r   r   )!__name__
__module____qualname____firstlineno____doc__r   dictstrr   
Constraint__annotations__r   r   r   boolr.   r(   dependent_propertyrH   propertyrL   r=   r>   rP   r
   r   rV   r\   rd   rg   rk   __static_attributes____classcell__)r8   s   @r   r   r      s    B :<OT#{5556; &*	:P':P Y/:P d{	:P
 
:P :Px ##6 7 *T * * #(**,  -2JJL 
E 
V 
0
*	 	r:   )r=   r   torch.distributionsr    torch.distributions.distributionr   torch.distributions.independentr   torch.distributions.transformsr   r   torch.distributions.utilsr	   torch.typesr
   __all__r    r:   r   <module>r      s7      + 9 7 F 4  %
%Rl Rr:   