o
    9iJ4                     @   s>  d Z ddlZddlmZ ddlZddlmZ ddlmZm	Z	 		d5de
deej d	ejd
ededejfddZ		d6ddZdd ZdefddZG dd dejjZdd ZG dd dejjZd7dd Zd!d" Zd#d$ Zd%d& Zd'd( ZG d)d* d*ejZG d+d, d,ejZd-d. Z d/d0 Z!d1d2 Z"G d3d4 d4ejZ#dS )8a  
partially adopted from
https://github.com/openai/improved-diffusion/blob/main/improved_diffusion/gaussian_diffusion.py
and
https://github.com/lucidrains/denoising-diffusion-pytorch/blob/7706bdfc6f527f58d33f84b7b522e61e6e3164b3/denoising_diffusion_pytorch/denoising_diffusion_pytorch.py
and
https://github.com/openai/guided-diffusion/blob/0ba878e517b276c45d1195eb29f6f5f72659a05b/guided_diffusion/nn.py

thanks!
    N)Optional)	rearrangerepeatTFmerge_strategy
mix_factorimage_only_indicatorapply_sigmoidis_attnreturnc                 C   s   | dks| dkr|}n;| dkr0t | t jdd|jdt|d}|r*t|d}nt|d}n| d	krD|}|r>t|d}nt|d}nt|rMt |S |S )
Nfixedlearnedlearned_with_images   device... -> ... 1b t -> (b t) 1 1zb t -> b 1 t 1 1fixed_with_images)torchwhereboolonesr   r   NotImplementedErrorsigmoid)r   r   r   r   r	   alpha r   K/data/cameron/vidgen/generative-models/sgm/modules/diffusionmodules/util.py	get_alpha   s$   r   -C6?{Gz?c                 C   s0   | dkrt j|d |d |t jdd }| S )Nlinearg      ?)dtype   )r   linspacefloat64numpy)schedule
n_timesteplinear_start
linear_endbetasr   r   r   make_beta_schedule2   s   r+   c                 C   s4   |j ^}}| d|}|j|gdt|d  R  S )N)r   r   )shapegatherreshapelen)atx_shapeb_outr   r   r   extract_into_tensorB   s   
r7   inputsc           	         s   |rC fdd D } fdd D } fdd D } fdd D }t |t | t | }tj| t|t|||g|R  S | di  S )a  
    Evaluate a function without caching intermediate activations, allowing for
    reduced memory at the expense of extra compute in the backward pass. This differs from the original checkpoint function
    borrowed from https://github.com/openai/guided-diffusion/blob/0ba878e517b276c45d1195eb29f6f5f72659a05b/guided_diffusion/nn.py in that
    it also works with non-tensor inputs
    :param func: the function to evaluate.
    :param inputs: the argument dictionary to pass to `func`.
    :param params: a sequence of parameters `func` depends on but does not
                   explicitly take as arguments.
    :param flag: if False, disable gradient checkpointing.
    c                    s    g | ]}t  | tjr|qS r   
isinstancer   Tensor.0keyr8   r   r   
<listcomp>U   s     z$mixed_checkpoint.<locals>.<listcomp>c                    s$   g | ]}t  | tjr | qS r   r9   r<   r?   r   r   r@   V   
    c                    s    g | ]}t  | tjs|qS r   r9   r<   r?   r   r   r@   Y   s
    c                    s$   g | ]}t  | tjs | qS r   r9   r<   r?   r   r   r@   \   rA   Nr   )tupleMixedCheckpointFunctionapplyr0   )	funcr8   paramsflagtensor_keystensor_inputsnon_tensor_keysnon_tensor_inputsargsr   r?   r   mixed_checkpointH   s,   


	rM   c                   @   $   e Zd Zedd Zedd ZdS )rC   c                 G   s   || _ || | _t t t d| _t||kr!t||ks#J dd t|t	|d | j  D | _
dd t|t	|| j | j D | _|| _t	|| jd  | _t  | jdi | j
| j}W d    |S 1 sqw   Y  |S )Nenabledr!   cache_enabledc                 S      i | ]\}}||qS r   r   r=   r>   valr   r   r   
<dictcomp>   s    
z3MixedCheckpointFunction.forward.<locals>.<dictcomp>c                 S   rR   r   r   rS   r   r   r   rU      s    r   )end_tensorsend_non_tensorsr   is_autocast_enabledget_autocast_gpu_dtypeis_autocast_cache_enabledgpu_autocast_kwargsr0   ziplistinput_tensorsinput_non_tensorsrun_functioninput_paramsno_grad)ctxr`   length_tensorslength_non_tensorsrH   rJ   rL   output_tensorsr   r   r   forwardm   s8   



zMixedCheckpointFunction.forwardc              	      s    fdd j D  _ t 8 tjjjdi  j  fdd j D } jdi | j}W d    n1 s;w   Y  W d    n1 sJw   Y  tj	j
|t j   j |dd} `  `~d|d  j  d j j   | jd   S )	Nc                    s"   i | ]}| j |  d qS T)r^   detachrequires_grad_r<   rc   r   r   rU      s    z4MixedCheckpointFunction.backward.<locals>.<dictcomp>c                    s$   i | ]}| j |  j | qS r   )r^   view_asr<   rk   r   r   rU      s    Tallow_unused)NNNNNNr   )r^   r   enable_gradcudaampautocastr[   r`   r_   autogradgradr]   valuesra   rV   rW   rc   output_gradsshallow_copiesrf   input_gradsr   rk   r   backward   s8   
"
 
z MixedCheckpointFunction.backwardN__name__
__module____qualname__staticmethodrg   r{   r   r   r   r   rC   l   s
    
'rC   c                 C   s4   |rt |t | }tj| t|g|R  S | | S )a  
    Evaluate a function without caching intermediate activations, allowing for
    reduced memory at the expense of extra compute in the backward pass.
    :param func: the function to evaluate.
    :param inputs: the argument sequence to pass to `func`.
    :param params: a sequence of parameters `func` depends on but does not
                   explicitly take as arguments.
    :param flag: if False, disable gradient checkpointing.
    )rB   CheckpointFunctionrD   r0   )rE   r8   rF   rG   rL   r   r   r   
checkpoint   s   
r   c                   @   rN   )r   c                 G   s~   || _ t|d | | _t||d  | _t t t d| _t	  | j | j }W d    |S 1 s8w   Y  |S )NrO   )
r`   r]   r^   ra   r   rX   rY   rZ   r[   rb   )rc   r`   lengthrL   rf   r   r   r   rg      s   

zCheckpointFunction.forwardc              	   G   s   dd | j D | _ t 0 tjjjdi | j dd | j D }| j| }W d    n1 s1w   Y  W d    n1 s@w   Y  tjj	|| j | j
 |dd}| ` | `
~d| S )Nc                 S   s   g | ]	}|  d qS rh   )ri   rj   r=   xr   r   r   r@      s    z/CheckpointFunction.backward.<locals>.<listcomp>c                 S   s   g | ]}| |qS r   )rl   r   r   r   r   r@      s    Trm   )NNr   )r^   r   rp   rq   rr   rs   r[   r`   rt   ru   ra   rw   r   r   r   r{      s"   " 
zCheckpointFunction.backwardNr|   r   r   r   r   r      s
    
r   '  c                 C   s   |sV|d }t t| t jd|t jd | j| jd}| dddf  |d  }t j	t 
|t |gdd}|d rTt j	|t |ddddf gdd}|S t| d	|d
}|S )aX  
    Create sinusoidal timestep embeddings.
    :param timesteps: a 1-D Tensor of N indices, one per batch element.
                      These may be fractional.
    :param dim: the dimension of the output.
    :param max_period: controls the minimum frequency of the embeddings.
    :return: an [N x dim] Tensor of positional embeddings.
    r"   r   )startendr!   r   Nr,   dimr   zb -> b d)d)r   expmathlogarangefloat32tor   floatcatcossin
zeros_liker   )	timestepsr   
max_periodrepeat_onlyhalffreqsrL   	embeddingr   r   r   timestep_embedding   s(   	
r   c                 C   s   |   D ]}|   q| S )z<
    Zero out the parameters of a module and return it.
    )
parametersri   zero_)modulepr   r   r   zero_module  s   r   c                 C   s    |   D ]	}| | q| S )z9
    Scale the parameters of a module and return it.
    )r   ri   mul_)r   scaler   r   r   r   scale_module  s   r   c                 C   s   | j ttdt| jdS )z6
    Take the mean over all non-batch dimensions.
    r   r   )meanr]   ranger0   r-   )tensorr   r   r   	mean_flat  s   r   c                 C   s
   t d| S )z
    Make a standard normalization layer.
    :param channels: number of input channels.
    :return: an nn.Module for normalization.
        )GroupNorm32)channelsr   r   r   normalization!  s   
r   c                   @   s   e Zd Zdd ZdS )SiLUc                 C   s   |t | S ro   )r   r   selfr   r   r   r   rg   ,  s   zSiLU.forwardN)r}   r~   r   rg   r   r   r   r   r   +  s    r   c                       s   e Zd Z fddZ  ZS )r   c                    s   t  | |jS ro   )superrg   r   typer!   r   	__class__r   r   rg   1  s   zGroupNorm32.forward)r}   r~   r   rg   __classcell__r   r   r   r   r   0  s    r   c                 O   V   | dkrt j|i |S | dkrt j|i |S | dkr$t j|i |S td|  )z4
    Create a 1D, 2D, or 3D convolution module.
    r   r"      unsupported dimensions: )nnConv1dConv2dConv3d
ValueErrordimsrL   kwargsr   r   r   conv_nd5     r   c                  O   s   t j| i |S )z!
    Create a linear module.
    )r   Linear)rL   r   r   r   r   r    B  s   r    c                 O   r   )z8
    Create a 1D, 2D, or 3D average pooling module.
    r   r"   r   r   )r   	AvgPool1d	AvgPool2d	AvgPool3dr   r   r   r   r   avg_pool_ndI  r   r   c                	       sx   e Zd Zg dZ		ddededef fddZd	ejd
ejfddZ		ddejdejd	e
ej d
ejfddZ  ZS )AlphaBlender)r   r   r   r   r   r   r   rearrange_patternc                    s   t    || _|| _|| jv sJ d| j | jdkr)| dt|g d S | jdks3| jdkrC| dtj	
t|g d S td| j )Nzmerge_strategy needs to be in r   r   r   r   zunknown merge strategy )r   __init__r   r   
strategiesregister_bufferr   r;   register_parameterr   	Parameterr   )r   r   r   r   r   r   r   r   Y  s   




zAlphaBlender.__init__r   r
   c                 C   s   | j dkr
| j}|S | j dkrt| j}|S | j dkrC|d us$J dt| tjdd|jdtt| jd}t|| j	}|S t
)Nr   r   r   zneed image_only_indicator ...r   r   r   )r   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   s  s    


zAlphaBlender.get_alphaN	x_spatial
x_temporalc                 C   s2   |  |}||j| d| |j|  }|S )Ng      ?)r   r   r!   )r   r   r   r   r   r   r   r   r   rg     s   
zAlphaBlender.forward)r   r   ro   )r}   r~   r   r   r   strr   r   r;   r   r   rg   r   r   r   r   r   r   V  s,    r   )TF)r   r   )r   F)$__doc__r   typingr   r   torch.nnr   einopsr   r   r   r;   r   r   r+   r7   dictrM   rt   FunctionrC   r   r   r   r   r   r   r   Moduler   	GroupNormr   r   r    r   r   r   r   r   r   <module>   sP    
!
$L
$		
