
    bi]                         d dl Z d dlmZ d dlmZmZmZ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j0                  e      Ze G d
 de             Z G d dee      Zy)    N)	dataclass)ListOptionalTupleUnion   )ConfigMixinregister_to_config)
BaseOutputis_scipy_availablelogging)randn_tensor   )SchedulerMixinc                   0    e Zd ZU dZej
                  ed<   y)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FloatTensor__annotations__     i/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/diffusers/schedulers/scheduling_flow_match_lcm.pyr   r   "   s     """r   r   c            !          e Zd ZdZg ZdZe	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d:dedede	de
e   de
e   d	e
e   d
e
e   de	de
e   de
e	   de
e	   de
e	   dede
ee      de
e   fd       Zed        Zed        Zed        Zd;defdZdefdZdefdZ	 d<dej.                  deeej.                  f   de
ej.                     dej.                  fdZd  Zd!ed"ed#ej6                  fd$Zd#ej6                  dej6                  fd%Z	 	 	 	 	 d=d&e
e   d'eeej<                  f   d(e
ee      d!e
e   d)e
ee      f
d*Zd<d+Z d, Z!	 	 d>d-ej.                  deeej.                  f   dej.                  d.e
ejD                     d/e	dee#e$f   fd0Z%d1ej6                  dej6                  fd2Z&d1ej6                  d&edej6                  fd3Z'	 d?d1ej6                  d&ed4ed5edej6                  f
d6Z(d7 Z)d8 Z*d9 Z+y)@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. Either "exponential" or "linear".
        scale_factors ('list', defaults to None)
            It defines how to scale the latents at which predictions are made.
        upscale_mode ('str', defaults to 'bicubic')
            Upscaling method, applied if scale-wise generation is considered
    r   N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scale_factorsupscale_modec                 P   | j                   j                  rt               st        d      t	        | j                   j                  | j                   j
                  | j                   j                  g      dkD  rt        d      |dvrt        d      t        j                  d||t        j                        d d d   j                         }t        j                  |      j                  t        j                        }||z  }|s||z  d|dz
  |z  z   z  }||z  | _        d | _        d | _        || _        d | _        || _        || _        |j                  d      | _        | j,                  d   j/                         | _        | j,                  d	   j/                         | _        y )
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.>   linearexponentialz;`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-   r.   r@   rG   s                     r   __init__zFlowMatchLCMScheduler.__init__]   s|   & ;;&&/A/CZ[[++T[[-O-OQUQ\Q\QnQnopstt A  ";;Z[[KK#68KSUS]S]^_cac_cdiik	$$Y/222G	00#V^qEAI+?'?@F"55 +)ii&R--/Q,,.r   c                     | j                   S )z.
        The value used for shifting.
        rC   rK   s    r   r!   zFlowMatchLCMScheduler.shift   s    
 {{r   c                     | j                   S )zg
        The index counter for current timestep. It will increase 1 after each scheduler step.
        )rA   rO   s    r   
step_indexz FlowMatchLCMScheduler.step_index   s    
 r   c                     | j                   S )zq
        The index for the first timestep. It should be set from pipeline with `set_begin_index` method.
        rB   rO   s    r   begin_indexz!FlowMatchLCMScheduler.begin_index   s    
    r   rT   c                     || _         y)z
        Sets the begin index for the scheduler. This function should be run from pipeline before the inference.

        Args:
            begin_index (`int`):
                The begin index for the scheduler.
        NrS   )rK   rT   s     r   set_begin_indexz%FlowMatchLCMScheduler.set_begin_index   s     (r   c                     || _         y NrN   )rK   r!   s     r   	set_shiftzFlowMatchLCMScheduler.set_shift   s	    r   c                      || _         || _        y)z
        Sets scale factors for a scale-wise generation regime.

        Args:
            scale_factors (`list`):
                The scale factors for each step
            upscale_mode (`str`):
                Upscaling method
        N)rE   rF   )rK   r-   r.   s      r   set_scale_factorsz'FlowMatchLCMScheduler.set_scale_factors   s     ,)r   sampletimestepnoisereturnc                    | j                   j                  |j                  |j                        }|j                  j                  dk(  rvt        j                  |      ra| j                  j                  |j                  t
        j                        }|j                  |j                  t
        j                        }n@| j                  j                  |j                        }|j                  |j                        }| j                   |D cg c]  }| j                  ||       }}nG| j                  | j                  g|j                  d   z  }n| j                  g|j                  d   z  }||   j                         }t        |j                        t        |j                        k  r=|j                  d      }t        |j                        t        |j                        k  r=||z  d|z
  |z  z   }|S c c}w )aN  
        Forward process in flow-matching

        Args:
            sample (`torch.FloatTensor`):
                The input sample.
            timestep (`int`, *optional*):
                The current timestep in the diffusion chain.

        Returns:
            `torch.FloatTensor`:
                A scaled input sample.
        )devicer3   mpsr2   r   r4         ?)rG   r?   ra   r3   typer   is_floating_pointr@   r<   rT   index_for_timesteprQ   shapeflattenlen	unsqueeze)	rK   r\   r]   r^   rG   schedule_timestepststep_indicessigmas	            r   scale_noisez!FlowMatchLCMScheduler.scale_noise   s   ( v}}FLLI==&5+B+B8+L!%!2!26==!2!V{{6=={FH!%!2!26==!A{{6==1H #T\]qD33A7IJ]L]__( OO,x~~a/@@L !,,-q0AAL|$,,.%++V\\!22OOB'E %++V\\!22 #+!77 ^s   G?c                 4    || j                   j                  z  S rX   r6   r    )rK   rn   s     r   _sigma_to_tz!FlowMatchLCMScheduler._sigma_to_t   s    t{{6666r   murn   rl   c                     | j                   j                  dk(  r| j                  |||      S | j                   j                  dk(  r| j                  |||      S y )Nr1   r0   )r6   r,   _time_shift_exponential_time_shift_linearrK   rs   rn   rl   s       r   
time_shiftz FlowMatchLCMScheduler.time_shift   sU    ;;&&-7//E1==[[((H4**2ua88 5r   c                 ^    d|z
  }|d   d| j                   j                  z
  z  }d||z  z
  }|S )a,  
        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`):
                A tensor of timesteps to be stretched and shifted.

        Returns:
            `torch.Tensor`:
                A tensor of adjusted timesteps such that the final value equals `self.config.shift_terminal`.
        r   r4   )r6   r(   )rK   rl   one_minus_zscale_factorstretched_ts        r   stretch_shift_to_terminalz/FlowMatchLCMScheduler.stretch_shift_to_terminal   s?      !e"2!dkk.H.H*HI;56r   num_inference_stepsra   rG   r@   c                 N   | j                   j                  r|t        d      |$|"t        |      t        |      k7  rt        d      |+|t        |      |k7  s|1t        |      |k7  r#t        d      |t        |      n
t        |      }|| _        |du}|r2t        j                  |      j                  t
        j                        }|e|It        j                  | j                  | j                        | j                  | j                        |      }|| j                   j                  z  }n=t        j                  |      j                  t
        j                        }t        |      }| j                   j                  r| j                  |d|      }n%| j                  |z  d| j                  dz
  |z  z   z  }| j                   j                   r| j#                  |      }| j                   j$                  r| j'                  ||      }nS| j                   j(                  r| j+                  ||      }n)| j                   j,                  r| j/                  ||      }t1        j2                  |      j5                  t0        j                  |      }|s|| j                   j                  z  }n4t1        j2                  |      j5                  t0        j                  |      }| j                   j6                  rUd|z
  }|| j                   j                  z  }t1        j8                  |t1        j:                  d|j<                  	      g      }n6t1        j8                  |t1        j>                  d|j<                  	      g      }|| _         || _!        d| _"        d| _#        y)
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 providedrc   r   )	in_sigmasr~   )r3   ra   )ra   )$r6   r"   r9   ri   r~   r:   arrayastyper<   r;   rr   rJ   rI   r    rx   r!   r(   r}   r)   _convert_to_karrasr*   _convert_to_exponentialr+   _convert_to_betar   r>   r?   r'   catonesra   zerosr@   rG   rA   rB   )rK   r~   ra   rG   rs   r@   is_timesteps_provideds          r   set_timestepsz#FlowMatchLCMScheduler.set_timesteps  s   4 ;;++
bcc)"76{c)n, !WXX*"s6{6I'I%#i.<O*O  H  281C#f+Y#6  !* 5 +222::>I> KK$$T^^4d6F6Ft~~6VXk	 !@!@@FXXf%,,RZZ8F"%f+ ;;++__Rf5FZZ&(Aa60I,IJF ;;%%33F;F ;;((,,vSf,gF[[//11FXk1lF[[((**VQd*eF !!&),,5==,P$!@!@@I((366U]]SY6ZI
 ;;$$6\F!@!@@IYY

1V]](KLMFYYAfmm(LMNF" r   c                     || j                   }||k(  j                         }t        |      dkD  rdnd}||   j                         S )Nr   r   )r@   nonzerori   rH   )rK   r]   rk   indicesposs        r   rf   z(FlowMatchLCMScheduler.index_for_timestept  sL    %!%%1::< w<!#as|  ""r   c                     | j                   Vt        |t        j                        r%|j	                  | j
                  j                        }| j                  |      | _        y | j                  | _        y rX   )
rT   
isinstancer   Tensorr?   r@   ra   rf   rA   rB   )rK   r]   s     r   _init_step_indexz&FlowMatchLCMScheduler._init_step_index  sU    #(ELL1#;;t~~'<'<=#66x@D#00Dr   model_output	generatorreturn_dictc                    t        |t              s4t        |t        j                        st        |t        j                        rt        d      | j                  rE| j                  r9t        | j                        t        | j                        dz   k7  rt        d      | j                  | j                  |j                         dd | _
        | j                  | j                  |       |j                  t        j                        }| j                   | j                     }| j                   | j                  dz      }|||z  z
  }| j                  r| j                  r| j"                  t        | j                        k  rs| j                  D 	cg c]'  }	t%        | j                  | j"                     |	z        ) c}	}	t        j&                  j(                  j+                  ||	| j                        }t-        |j.                  ||j0                  |j2                        }
d|z
  |z  ||
z  z   }| xj"                  dz  c_        |j                  |j2                        }|s|fS t5        |      S c c}	w )	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   )sizemode)r   ra   r3   )r   )r   intr   	IntTensor
LongTensorr9   rE   rF   ri   r@   rD   rQ   r   r   r?   r<   rG   rA   roundnn
functionalinterpolater   rg   ra   r3   r   )rK   r   r]   r\   r   r   rn   
sigma_nextx0_predr   r^   r   s               r   stepzFlowMatchLCMScheduler.step  s   @ x%(EOO4(E$4$45G  4#5#5#dnn:MQTUYUhUhQilmQm:mo  ??"doo&=*//1!"5DO??"!!(+ 5==)DOO,[[1!45
5<//4#5#5#d&9&9"::X\XgXghPTd11$2B2BCdJKh((--99'SWSeSe9fW]]i^e^k^kl:~0:3EE 	A!nn\%7%78>!*{CC is   ,I3r   c                    t        | j                  d      r| j                  j                  }nd}t        | j                  d      r| j                  j                  }nd}||n|d   j	                         }||n|d   j	                         }d}t        j                  dd|      }|d|z  z  }|d|z  z  }||||z
  z  z   |z  }	|	S )z6Constructs the noise schedule of Karras et al. (2022).rI   NrJ   r4   r   g      @r   )hasattrr6   rI   rJ   rH   r:   r;   )
rK   r   r~   rI   rJ   rhorampmin_inv_rhomax_inv_rhorG   s
             r   r   z(FlowMatchLCMScheduler._convert_to_karras  s    
 4;;,--II4;;,--II!*!6IIbM<N<N<P	!*!6IIaL<M<M<O	{{1a!45AG,AG,k(A BBsJr   c                    t        | j                  d      r| j                  j                  }nd}t        | j                  d      r| j                  j                  }nd}||n|d   j	                         }||n|d   j	                         }t        j                  t        j                  t        j                  |      t        j                  |      |            }|S )z)Constructs an exponential noise schedule.rI   NrJ   r4   r   )
r   r6   rI   rJ   rH   r:   expr;   mathlog)rK   r   r~   rI   rJ   rG   s         r   r   z-FlowMatchLCMScheduler._convert_to_exponential  s    
 4;;,--II4;;,--II!*!6IIbM<N<N<P	!*!6IIaL<M<M<O	DHHY$7)9LNabcr   alphabetac           
      (   t        | j                  d      r| j                  j                  }nd}t        | j                  d      r| j                  j                  }nd}||n|d   j	                         }||n|d   j	                         }t        j                  dt        j                  dd|      z
  D cg c]-  }t        j                  j                  j                  |||      / c}D cg c]  }||||z
  z  z    c}      }	|	S c c}w c c}w )zJFrom "Beta Sampling is All You Need" [arXiv:2407.12173] (Lee et. al, 2024)rI   NrJ   r4   r   r   )r   r6   rI   rJ   rH   r:   r   r;   scipystatsr   ppf)
rK   r   r~   r   r   rI   rJ   r]   r   rG   s
             r   r   z&FlowMatchLCMScheduler._convert_to_beta  s     4;;,--II4;;,--II!*!6IIbM<N<N<P	!*!6IIaL<M<M<O	
 %&Aq:M(N$N  KK$$((5$? SI	$9:;
 s   82D
/Dc                 p    t        j                  |      t        j                  |      d|z  dz
  |z  z   z  S Nr   )r   r   rw   s       r   ru   z-FlowMatchLCMScheduler._time_shift_exponential*  s/    xx|txx|q1uqyU.BBCCr   c                 $    ||d|z  dz
  |z  z   z  S r   r   rw   s       r   rv   z(FlowMatchLCMScheduler._time_shift_linear-  s    R1q519..//r   c                 .    | j                   j                  S rX   rq   rO   s    r   __len__zFlowMatchLCMScheduler.__len__0  s    {{...r   )i  rc   Fg      ?gffffff?   i   FNFFFr1   Nbicubic)r   rX   )NNNNN)NT)333333?r   ),r   r   r   r   _compatiblesorderr
   r   floatboolr   strr   rL   propertyr!   rQ   rT   rV   rY   listr[   r   r   r   ro   rr   r   rx   r}   ra   r   rf   r   	Generatorr   r   r   r   r   r   ru   rv   r   r   r   r   r   r   0   s   'R LE $(%*&)%),/+/#*.,116*/,/3&/!0/ 0/ 0/ #	0/
 UO0/ E?0/ %SM0/ $C=0/ 0/ !0/ $D>0/ !)0/ "$0/ 0/  U,0/  sm!0/ 0/d       ! !(3 (u *t *" .2	.!!. u0001. ))*	.
 
		.`79U 95 9U\\ 95<< ELL . .2+/(,"+/d!%c]d! c5<<'(d! e%	d!
 UOd! DK(d!L#1 04 ND''ND u0001ND !!	ND
 EOO,ND ND 
*E1	2NDbELL RWR^R^ 4 TW \a\h\h . dg<?HM[`	>D0/r   r   )r   dataclassesr   typingr   r   r   r   numpyr:   r   configuration_utilsr	   r
   utilsr   r   r   utils.torch_utilsr   scheduling_utilsr   scipy.statsr   
get_loggerr   loggerr   r   r   r   r   <module>r      sp     ! / /   A ; ; , , 			H	% 
#* 
# 
#A/NK A/r   