o
    Gith                     @   s   d dl Z d dlmZ d dlmZ d dlZd dlZddlm	Z	m
Z
 ddlmZmZmZ ddlmZ dd	lmZ e r=d dlZeeZeG d
d deZG dd dee	ZdS )    N)	dataclass)Literal   )ConfigMixinregister_to_config)
BaseOutputis_scipy_availablelogging)randn_tensor   )SchedulerMixinc                   @   s   e Zd ZU dZejed< dS )FlowMatchLCMSchedulerOutputaJ  
    Output class for the scheduler's `step` function output.

    Args:
        prev_sample (`torch.FloatTensor` of shape `(batch_size, num_channels, height, width)` for images):
            Computed sample `(x_{t-1})` of previous timestep. `prev_sample` should be used as next model input in the
            denoising loop.
    prev_sampleN)__name__
__module____qualname____doc__torchTensor__annotations__ r   r   b/home/ubuntu/.local/lib/python3.10/site-packages/diffusers/schedulers/scheduling_flow_match_lcm.pyr   "   s   
 	r   c                !   @   s<  e Zd ZdZg ZdZe										
					
	d^dedede	dedededede	ded
B de	d
B de	d
B de	d
B de
d dee d
B de
d fddZed d! Zed"d# Zed$d% Zd_d'ed(d
fd)d*Zded(d
fd+d,Zdee ded(d
fd-d.Z	
d`d/ejd0eejB d1ejd
B d(ejfd2d3Zd4eejB d(eejB fd5d6Zd7ed4ed8eejB ejB d(eejB ejB fd9d:Zd8ejejB d(ejejB fd;d<Z	
	
	
	
	
dad=ed
B d>eejB d
B d?ee d
B d7ed
B d@ee d
B d(d
fdAdBZ	
d`d0eejB dCejd
B d(efdDdEZ d0eejB d(d
fdFdGZ!	
	HdbdIejd0eejB d/ejdJej"d
B dKe	d(e#e$B fdLdMZ%dNejd=ed(ejfdOdPZ&dNejd=ed(ejfdQdRZ'	SdcdNejd=edTedUed(ejf
dVdWZ(d7ed4ed8eejB ejB d(eejB ejB fdXdYZ)d7ed4ed8eejB ejB d(eejB ejB fdZd[Z*d(efd\d]Z+d
S )dFlowMatchLCMSchedulera	  
    LCM scheduler for Flow Matching.

    This model inherits from [`SchedulerMixin`] and [`ConfigMixin`]. Check the superclass documentation for the generic
    methods the library implements for all schedulers such as loading and saving.

    Args:
        num_train_timesteps (`int`, defaults to 1000):
            The number of diffusion steps to train the model.
        shift (`float`, defaults to 1.0):
            The shift value for the timestep schedule.
        use_dynamic_shifting (`bool`, defaults to False):
            Whether to apply timestep shifting on-the-fly based on the image resolution.
        base_shift (`float`, defaults to 0.5):
            Value to stabilize image generation. Increasing `base_shift` reduces variation and image is more consistent
            with desired output.
        max_shift (`float`, defaults to 1.15):
            Value change allowed to latent vectors. Increasing `max_shift` encourages more variation and image may be
            more exaggerated or stylized.
        base_image_seq_len (`int`, defaults to 256):
            The base image sequence length.
        max_image_seq_len (`int`, defaults to 4096):
            The maximum image sequence length.
        invert_sigmas (`bool`, defaults to False):
            Whether to invert the sigmas.
        shift_terminal (`float`, defaults to None):
            The end value of the shifted timestep schedule.
        use_karras_sigmas (`bool`, defaults to False):
            Whether to use Karras sigmas for step sizes in the noise schedule during sampling.
        use_exponential_sigmas (`bool`, defaults to False):
            Whether to use exponential sigmas for step sizes in the noise schedule during sampling.
        use_beta_sigmas (`bool`, defaults to False):
            Whether to use beta sigmas for step sizes in the noise schedule during sampling.
        time_shift_type (`str`, defaults to "exponential"):
            The type of dynamic resolution-dependent timestep shifting to apply.
        scale_factors (`list[float]`, *optional*, defaults to `None`):
            It defines how to scale the latents at which predictions are made.
        upscale_mode (`str`, *optional*, defaults to "bicubic"):
            Upscaling method, applied if scale-wise generation is considered.
    r           ?F      ?ffffff?      Nexponentialbicubicnum_train_timestepsshiftuse_dynamic_shifting
base_shift	max_shiftbase_image_seq_lenmax_image_seq_leninvert_sigmasshift_terminaluse_karras_sigmasuse_exponential_sigmasuse_beta_sigmastime_shift_type)r   linearscale_factorsupscale_mode)nearestr.   bilinearr    	trilinearareaznearest-exactc                 C   s  | j jrt stdt| j j| j j| j jgdkrtd|dvr&tdtj	d||tj
dd d d  }t|jtj
d}|| }|sS|| d|d |   }|| | _d | _d | _|| _d | _|| _|| _|d| _| jd  | _| jd	  | _d S )
Nz:Make sure to install scipy if you want to use beta sigmas.r   znOnly one of `config.use_beta_sigmas`, `config.use_exponential_sigmas`, `config.use_karras_sigmas` can be used.>   r.   r   z;`time_shift_type` must either be 'exponential' or 'linear'.dtypecpur   )configr,   r   ImportErrorsumr+   r*   
ValueErrornplinspacefloat32copyr   
from_numpyto	timesteps_step_index_begin_index_shift
_init_size_scale_factors_upscale_modesigmasitem	sigma_min	sigma_max)selfr!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r/   r0   rC   rJ   r   r   r   __init__]   s<   	"
zFlowMatchLCMScheduler.__init__c                 C      | j S )z.
        The value used for shifting.
        rF   rN   r   r   r   r"         zFlowMatchLCMScheduler.shiftc                 C   rP   )zg
        The index counter for current timestep. It will increase 1 after each scheduler step.
        )rD   rR   r   r   r   
step_index   rS   z FlowMatchLCMScheduler.step_indexc                 C   rP   )zq
        The index for the first timestep. It should be set from pipeline with `set_begin_index` method.
        rE   rR   r   r   r   begin_index   rS   z!FlowMatchLCMScheduler.begin_indexr   rV   returnc                 C   s
   || _ dS )z
        Sets the begin index for the scheduler. This function should be run from pipeline before the inference.

        Args:
            begin_index (`int`, defaults to `0`):
                The begin index for the scheduler.
        NrU   )rN   rV   r   r   r   set_begin_index   s   
z%FlowMatchLCMScheduler.set_begin_indexc                 C   s
   || _ d S NrQ   )rN   r"   r   r   r   	set_shift   s   
zFlowMatchLCMScheduler.set_shiftc                 C   s   || _ || _dS )z
        Sets scale factors for a scale-wise generation regime.

        Args:
            scale_factors (`list[float]`):
                The scale factors for each step.
            upscale_mode (`str`):
                Upscaling method.
        N)rH   rI   )rN   r/   r0   r   r   r   set_scale_factors   s   

z'FlowMatchLCMScheduler.set_scale_factorssampletimestepnoisec                    s  j j|j|jd}|jjdkr)t|r)jj|jtjd |j|jtjd}nj|j ||j}j	du rF fdd|D }nj
durUj
g|jd  }n	j	g|jd  }||  }t|jt|jk r}|d}t|jt|jk sn|| d	| |  }|S )
a  
        Forward process in flow-matching

        Args:
            sample (`torch.FloatTensor`):
                The input sample.
            timestep (`torch.FloatTensor`):
                The current timestep in the diffusion chain.
            noise (`torch.FloatTensor`):
                The noise tensor.

        Returns:
            `torch.FloatTensor`:
                A scaled input sample.
        )devicer6   mpsr5   Nc                    s   g | ]} | qS r   )index_for_timestep).0tschedule_timestepsrN   r   r   
<listcomp>   s    z5FlowMatchLCMScheduler.scale_noise.<locals>.<listcomp>r   r7   r   )rJ   rB   r_   r6   typer   is_floating_pointrC   r?   rV   rT   shapeflattenlen	unsqueeze)rN   r\   r]   r^   rJ   step_indicessigmar   rd   r   scale_noise   s"   


z!FlowMatchLCMScheduler.scale_noisern   c                 C   s   || j j S rY   r9   r!   )rN   rn   r   r   r   _sigma_to_t  s   z!FlowMatchLCMScheduler._sigma_to_tmurc   c                 C   s8   | j jdkr| |||S | j jdkr| |||S d S )Nr   r.   )r9   r-   _time_shift_exponential_time_shift_linearrN   rr   rn   rc   r   r   r   
time_shift  s
   z FlowMatchLCMScheduler.time_shiftc                 C   s,   d| }|d d| j j  }d||  }|S )az  
        Stretches and shifts the timestep schedule to ensure it terminates at the configured `shift_terminal` config
        value.

        Reference:
        https://github.com/Lightricks/LTX-Video/blob/a01a171f8fe3d99dce2728d60a73fecf4d4238ae/ltx_video/schedulers/rf.py#L51

        Args:
            t (`torch.Tensor` or `np.ndarray`):
                A tensor or numpy array of timesteps to be stretched and shifted.

        Returns:
            `torch.Tensor` or `np.ndarray`:
                A tensor or numpy array of adjusted timesteps such that the final value equals
                `self.config.shift_terminal`.
        r   r7   )r9   r)   )rN   rc   one_minus_zscale_factorstretched_tr   r   r   stretch_shift_to_terminal  s   z/FlowMatchLCMScheduler.stretch_shift_to_terminalnum_inference_stepsr_   rJ   rC   c                 C   sF  | j jr|du rtd|dur |dur t|t|kr td|dur=|dur.t||ks8|dur<t||kr<tdn|durEt|nt|}|| _|du}|r[t|tj}|du ry|du rrt	| 
| j| 
| j|}|| j j }nt|tj}t|}| j jr| |d|}n| j| d| jd |   }| j jr| |}| j jr| j||d}n| j jr| j||d}n| j jr| j||d}t|jtj|d}|s|| j j }nt|jtj|d}| j jrd| }|| j j }t|tjd|jd	g}nt|tjd|jd	g}|| _ || _!d| _"d| _#dS )
a  
        Sets the discrete timesteps used for the diffusion chain (to be run before inference).

        Args:
            num_inference_steps (`int`, *optional*):
                The number of diffusion steps used when generating samples with a pre-trained model.
            device (`str` or `torch.device`, *optional*):
                The device to which the timesteps should be moved to. If `None`, the timesteps are not moved.
            sigmas (`list[float]`, *optional*):
                Custom values for sigmas to be used for each diffusion step. If `None`, the sigmas are computed
                automatically.
            mu (`float`, *optional*):
                Determines the amount of shifting applied to sigmas when performing resolution-dependent timestep
                shifting.
            timesteps (`list[float]`, *optional*):
                Custom values for timesteps to be used for each diffusion step. If `None`, the timesteps are computed
                automatically.
        NzC`mu` must be passed when `use_dynamic_shifting` is set to be `True`z4`sigmas` and `timesteps` should have the same lengthzq`sigmas` and `timesteps` should have the same length as num_inference_steps, if `num_inference_steps` is providedr   r   )	in_sigmasr{   )r6   r_   )r_   )$r9   r#   r<   rk   r{   r=   arrayastyper?   r>   rq   rM   rL   r!   rv   r"   r)   rz   r*   _convert_to_karrasr+   _convert_to_exponentialr,   _convert_to_betar   rA   rB   r(   catonesr_   zerosrC   rJ   rD   rE   )rN   r{   r_   rJ   rr   rC   is_timesteps_providedr   r   r   set_timesteps$  sf   




z#FlowMatchLCMScheduler.set_timestepsre   c                 C   s>   |d u r| j }||k }t|dkrdnd}t||  S )Nr   r   )rC   nonzerork   intrK   )rN   r]   re   indicesposr   r   r   ra     s
   z(FlowMatchLCMScheduler.index_for_timestepc                 C   s@   | j d u rt|tjr|| jj}| || _d S | j	| _d S rY   )
rV   
isinstancer   r   rB   rC   r_   ra   rD   rE   )rN   r]   r   r   r   _init_step_index  s
   
z&FlowMatchLCMScheduler._init_step_indexTmodel_output	generatorreturn_dictc                    sb  t |tst |tjst |tjrtd jr+ jr+t j	t jd kr+td j
du s5 jdu r>| dd  _
 jdu rH | |tj} j j } j jd  }|||  } jr jr jt jk r fdd j
D }	tjjj||	 jd}t|j||j|jd	}
d| | ||
  }  jd7  _||j}|s|fS t|d
S )a  
        Predict the sample from the previous timestep by reversing the SDE. This function propagates the diffusion
        process from the learned model outputs (most often the predicted noise).

        Args:
            model_output (`torch.FloatTensor`):
                The direct output from learned diffusion model.
            timestep (`float`):
                The current discrete timestep in the diffusion chain.
            sample (`torch.FloatTensor`):
                A current instance of a sample created by the diffusion process.
            generator (`torch.Generator`, *optional*):
                A random number generator.
            return_dict (`bool`):
                Whether or not to return a [`~schedulers.scheduling_flow_match_lcm.FlowMatchLCMSchedulerOutput`] or
                tuple.

        Returns:
            [`~schedulers.scheduling_flow_match_lcm.FlowMatchLCMSchedulerOutput`] or `tuple`:
                If return_dict is `True`, [`~schedulers.scheduling_flow_match_lcm.FlowMatchLCMSchedulerOutput`] is
                returned, otherwise a tuple is returned where the first element is the sample tensor.
        zPassing integer indices (e.g. from `enumerate(timesteps)`) as timesteps to `FlowMatchLCMScheduler.step()` is not supported. Make sure to pass one of the `scheduler.timesteps` as a timestep.r   z]`_scale_factors` should have the same length as `timesteps` - 1, if `_scale_factors` are set.Nr   c                    s    g | ]}t  j j | qS r   )roundrH   rD   )rb   sizerR   r   r   rf     s     z.FlowMatchLCMScheduler.step.<locals>.<listcomp>)r   mode)r   r_   r6   )r   )r   r   r   	IntTensor
LongTensorr<   rH   rI   rk   rC   rG   rT   r   r   rB   r?   rJ   rD   nn
functionalinterpolater
   ri   r_   r6   r   )rN   r   r]   r\   r   r   rn   
sigma_nextx0_predr   r^   r   r   rR   r   step  sJ    

$


zFlowMatchLCMScheduler.stepr|   c           
      C   s   t | jdr| jj}nd}t | jdr| jj}nd}|dur |n|d  }|dur,|n|d  }d}tdd|}|d|  }|d|  }||||   | }	|	S )a  
        Construct the noise schedule as proposed in [Elucidating the Design Space of Diffusion-Based Generative
        Models](https://huggingface.co/papers/2206.00364).

        Args:
            in_sigmas (`torch.Tensor`):
                The input sigma values to be converted.
            num_inference_steps (`int`):
                The number of inference steps to generate the noise schedule for.

        Returns:
            `torch.Tensor`:
                The converted sigma values following the Karras noise schedule.
        rL   NrM   r7   r   g      @r   )hasattrr9   rL   rM   rK   r=   r>   )
rN   r|   r{   rL   rM   rhorampmin_inv_rhomax_inv_rhorJ   r   r   r   r     s   

z(FlowMatchLCMScheduler._convert_to_karrasc                 C   s   t | jdr| jj}nd}t | jdr| jj}nd}|dur |n|d  }|dur,|n|d  }ttt	|t	||}|S )a  
        Construct an exponential noise schedule.

        Args:
            in_sigmas (`torch.Tensor`):
                The input sigma values to be converted.
            num_inference_steps (`int`):
                The number of inference steps to generate the noise schedule for.

        Returns:
            `torch.Tensor`:
                The converted sigma values following an exponential schedule.
        rL   NrM   r7   r   )
r   r9   rL   rM   rK   r=   expr>   mathlog)rN   r|   r{   rL   rM   rJ   r   r   r   r   #  s   

 z-FlowMatchLCMScheduler._convert_to_exponential333333?alphabetac              
      s   t | jdr| jjndt | jdr| jjnddur n|d  dur,n|d  tfdd fddd	tdd	| D D }|S )
a  
        Construct a beta noise schedule as proposed in [Beta Sampling is All You
        Need](https://huggingface.co/papers/2407.12173).

        Args:
            in_sigmas (`torch.Tensor`):
                The input sigma values to be converted.
            num_inference_steps (`int`):
                The number of inference steps to generate the noise schedule for.
            alpha (`float`, *optional*, defaults to `0.6`):
                The alpha parameter for the beta distribution.
            beta (`float`, *optional*, defaults to `0.6`):
                The beta parameter for the beta distribution.

        Returns:
            `torch.Tensor`:
                The converted sigma values following a beta distribution schedule.
        rL   NrM   r7   r   c                    s   g | ]
}|    qS r   r   )rb   ppf)rM   rL   r   r   rf   k  s    z:FlowMatchLCMScheduler._convert_to_beta.<locals>.<listcomp>c                    s   g | ]}t jj| qS r   )scipystatsr   r   )rb   r]   )r   r   r   r   rf   m  s    r   )r   r9   rL   rM   rK   r=   r}   r>   )rN   r|   r{   r   r   rJ   r   )r   r   rM   rL   r   r   E  s    

	z&FlowMatchLCMScheduler._convert_to_betac                 C   s$   t |t |d| d |   S Nr   )r   r   ru   r   r   r   rs   u  s   $z-FlowMatchLCMScheduler._time_shift_exponentialc                 C   s   ||d| d |   S r   r   ru   r   r   r   rt   z  s   z(FlowMatchLCMScheduler._time_shift_linearc                 C   s   | j jS rY   rp   rR   r   r   r   __len__  s   zFlowMatchLCMScheduler.__len__)r   r   Fr   r   r   r   FNFFFr   Nr    )r   rY   )NNNNN)NT)r   r   ),r   r   r   r   _compatiblesorderr   r   floatboolr   listrO   propertyr"   rT   rV   rX   rZ   strr[   r   FloatTensorro   rq   r=   ndarrayr   rv   rz   r_   r   ra   r   	Generatorr   tupler   r   r   r   rs   rt   r   r   r   r   r   r   0   s<   )		

C




2
"


k

V'#
0

r   )r   dataclassesr   typingr   numpyr=   r   configuration_utilsr   r   utilsr   r   r	   utils.torch_utilsr
   scheduling_utilsr   scipy.statsr   
get_loggerr   loggerr   r   r   r   r   r   <module>   s   
