o
    Gir                  	   @   s   d dl Z 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 ddlmZmZ e rAd dlZd d	lmZ eG d
d deZ		ddededed dejfddZG dd dee
ZdS )    N)	dataclass)Literal   )ConfigMixinregister_to_config)
BaseOutputis_scipy_available   )KarrasDiffusionSchedulersSchedulerMixin)	integratec                   @   s.   e Zd ZU dZejed< dZejdB ed< dS )LMSDiscreteSchedulerOutputaq  
    Output class for the scheduler's `step` function output.

    Args:
        prev_sample (`torch.Tensor` 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.
        pred_original_sample (`torch.Tensor` of shape `(batch_size, num_channels, height, width)` for images):
            The predicted denoised sample `(x_{0})` based on the model output from the current timestep.
            `pred_original_sample` can be used to preview progress or for guidance.
    prev_sampleNpred_original_sample)__name__
__module____qualname____doc__torchTensor__annotations__r    r   r   `/home/ubuntu/.local/lib/python3.10/site-packages/diffusers/schedulers/scheduling_lms_discrete.pyr       s   
 
r   +?cosinenum_diffusion_timestepsmax_betaalpha_transform_type)r   explaplacereturnc                 C   s   |dkr	dd }n|dkrdd }n|dkrdd }nt d| g }t| D ]}||  }|d	 |  }|td	||||  | q(tj|tjd
S )a>  
    Create a beta schedule that discretizes the given alpha_t_bar function, which defines the cumulative product of
    (1-beta) over time from t = [0,1].

    Contains a function alpha_bar that takes an argument t and transforms it to the cumulative product of (1-beta) up
    to that part of the diffusion process.

    Args:
        num_diffusion_timesteps (`int`):
            The number of betas to produce.
        max_beta (`float`, defaults to `0.999`):
            The maximum beta to use; use values lower than 1 to avoid numerical instability.
        alpha_transform_type (`str`, defaults to `"cosine"`):
            The type of noise schedule for `alpha_bar`. Choose from `cosine`, `exp`, or `laplace`.

    Returns:
        `torch.Tensor`:
            The betas used by the scheduler to step the model outputs.
    r   c                 S   s    t | d d t j d d S )NgMb?gT㥛 ?r   )mathcospitr   r   r   alpha_bar_fnN   s    z)betas_for_alpha_bar.<locals>.alpha_bar_fnr   c              	   S   sP   dt dd|   t ddt d|    d  }t |}t |d|  S )Ng      r	         ?r   gư>)r!   copysignlogfabsr   sqrt)r%   lmbsnrr   r   r   r&   S   s   4
r   c                 S   s   t | d S )Ng      ()r!   r   r$   r   r   r   r&   Z   s   z"Unsupported alpha_transform_type: r	   dtype)
ValueErrorrangeappendminr   tensorfloat32)r   r   r   r&   betasit1t2r   r   r   betas_for_alpha_bar4   s   


"r:   c                   @   sD  e Zd ZdZdd eD ZdZe							
	
	
			dTdede	de	de
dejee	 B d	B dedededed ded defddZede	ejB fddZedefd d!Zedefd"d#ZdUd$edd	fd%d&Zd'ejd(e	ejB dejfd)d*Zd+ed,ed-ede	fd.d/ZdVd0ed1e
ejB fd2d3Z		dVd(e	ejB d4ejd	B defd5d6Zd(e	ejB dd	fd7d8Zd9ejd:ejdejfd;d<Zd=ejdejfd>d?Zd=ejd0edejfd@dAZ 	BdWd=ejd0edCe	dDe	dejf
dEdFZ!	G	HdXdIejd(e	ejB d'ejd+edJede"e#B fdKdLZ$dMejdNejdOejdejfdPdQZ%defdRdSZ&d	S )YLMSDiscreteScheduleru	  
    A linear multistep scheduler for discrete beta schedules.

    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.
        beta_start (`float`, defaults to `0.0001`):
            The starting `beta` value of inference.
        beta_end (`float`, defaults to `0.02`):
            The final `beta` value.
        beta_schedule (`"linear"`, `"scaled_linear"`, or `"squaredcos_cap_v2"`, defaults to `"linear"`):
            The beta schedule, a mapping from a beta range to a sequence of betas for stepping the model.
        trained_betas (`np.ndarray`, *optional*):
            Pass an array of betas directly to the constructor to bypass `beta_start` and `beta_end`.
        use_karras_sigmas (`bool`, *optional*, defaults to `False`):
            Whether to use Karras sigmas for step sizes in the noise schedule during the sampling process. If `True`,
            the sigmas are determined according to a sequence of noise levels {σi}.
        use_exponential_sigmas (`bool`, *optional*, defaults to `False`):
            Whether to use exponential sigmas for step sizes in the noise schedule during the sampling process.
        use_beta_sigmas (`bool`, *optional*, defaults to `False`):
            Whether to use beta sigmas for step sizes in the noise schedule during the sampling process. Refer to [Beta
            Sampling is All You Need](https://huggingface.co/papers/2407.12173) for more information.
        prediction_type (`"epsilon"`, `"sample"`, or `"v_prediction"`, defaults to `"epsilon"`):
            Prediction type of the scheduler function; can be `epsilon` (predicts the noise of the diffusion process),
            `sample` (directly predicts the noisy sample`) or `v_prediction` (see section 2.4 of [Imagen
            Video](https://huggingface.co/papers/2210.02303) paper).
        timestep_spacing (`"linspace"`, `"leading"`, or `"trailing"`, defaults to `"linspace"`):
            The way the timesteps should be scaled. Refer to Table 2 of the [Common Diffusion Noise Schedules and
            Sample Steps are Flawed](https://huggingface.co/papers/2305.08891) for more information.
        steps_offset (`int`, defaults to `0`):
            An offset added to the inference steps, as required by some model families.
    c                 C   s   g | ]}|j qS r   )name).0er   r   r   
<listcomp>   s    zLMSDiscreteScheduler.<listcomp>r	     -C6?{Gz?linearNFepsilonlinspacer   num_train_timesteps
beta_startbeta_endbeta_scheduletrained_betasuse_karras_sigmasuse_exponential_sigmasuse_beta_sigmasprediction_type)rD   samplev_predictiontimestep_spacing)rE   leadingtrailingsteps_offsetc                 C   s^  t | jj| jj| jjgdkrtd|d ur!tj|tjd| _	n:|dkr1tj
|||tjd| _	n*|dkrGtj
|d |d |tjdd | _	n|dkrQt|| _	n
t| d	| j d
| j	 | _tj| jdd| _td| j | j d }t|d d d dggtj}t|| _d | _|| _| |d  g | _d| _d | _d | _| jd| _d S )Nr	   znOnly one of `config.use_beta_sigmas`, `config.use_exponential_sigmas`, `config.use_karras_sigmas` can be used.r.   rC   scaled_linearr'   r   squaredcos_cap_v2z is not implemented for       ?r   )dim        Fcpu)sumconfigrM   rL   rK   r0   r   r4   r5   r6   rE   r:   NotImplementedError	__class__alphascumprodalphas_cumprodnparrayconcatenateastype
from_numpysigmasnum_inference_stepsset_timestepsderivativesis_scale_input_called_step_index_begin_indexto)selfrF   rG   rH   rI   rJ   rK   rL   rM   rN   rQ   rT   rh   r   r   r   __init__   s4   $"zLMSDiscreteScheduler.__init__r    c                 C   s,   | j jdv r| j S | j d d d S )a0  
        The standard deviation of the initial noise distribution.

        Returns:
            `float` or `torch.Tensor`:
                The standard deviation of the initial noise distribution, computed based on the maximum sigma value and
                the timestep spacing configuration.
        )rE   rS   r   r	   r'   )r]   rQ   rh   maxrp   r   r   r   init_noise_sigma   s   
z%LMSDiscreteScheduler.init_noise_sigmac                 C      | j S )z
        The index counter for current timestep. It will increase by 1 after each scheduler step.

        Returns:
            `int` or `None`:
                The current step index, or `None` if not initialized.
        )rm   rs   r   r   r   
step_index      	zLMSDiscreteScheduler.step_indexc                 C   ru   )z
        The index for the first timestep. It should be set from pipeline with `set_begin_index` method.

        Returns:
            `int` or `None`:
                The begin index for the scheduler, or `None` if not set.
        rn   rs   r   r   r   begin_index   rw   z LMSDiscreteScheduler.begin_indexry   c                 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.
        Nrx   )rp   ry   r   r   r   set_begin_index   s   
z$LMSDiscreteScheduler.set_begin_indexrO   timestepc                 C   s>   | j du r
| | | j| j  }||d d d  }d| _|S )a  
        Ensures interchangeability with schedulers that need to scale the denoising model input depending on the
        current timestep.

        Args:
            sample (`torch.Tensor`):
                The input sample.
            timestep (`float` or `torch.Tensor`):
                The current timestep in the diffusion chain.

        Returns:
            `torch.Tensor`:
                A scaled input sample.
        Nr   r	   r'   T)rv   _init_step_indexrh   rl   )rp   rO   r{   sigmar   r   r   scale_model_input   s   

z&LMSDiscreteScheduler.scale_model_inputorderr%   current_orderc                    s<    fdd}t j|j jd  ddd }|S )a  
        Compute the linear multistep coefficient.

        Args:
            order (`int`):
                The order of the linear multistep method.
            t (`int`):
                The current timestep index.
            current_order (`int`):
                The current order for which to compute the coefficient.

        Returns:
            `float`:
                The computed linear multistep coefficient.
        c                    sR   d}t D ] } |krq|| j|   j   j|    9 }q|S )NrW   )r1   rh   )tauprodkr   r   rp   r%   r   r   lms_derivative  s   4z@LMSDiscreteScheduler.get_lms_coefficient.<locals>.lms_derivativer	   rA   )epsrelr   )r   quadrh   )rp   r   r%   r   r   integrated_coeffr   r   r   get_lms_coefficient  s   &z(LMSDiscreteScheduler.get_lms_coefficientri   devicec                    s"  |_ jjdkrtjdjjd |tjdddd  }nVjjdkrHjjj  }td|| 	 ddd  
tj}|jj7 }n-jjdkrljjj  }tjjd| 	  
tj}|d8 }n	tjj d	tdj j d
 }t| t|tdt||}jjrj|d}t fdd|D }n1jjrňj||d}t fdd|D }njjr݈j||d}t fdd|D }t|dgg
tj}t|j|d_t|j|tjd_d_d_jd_g _ dS )a  
        Sets the discrete timesteps used for the diffusion chain (to be run before inference).

        Args:
            num_inference_steps (`int`):
                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.
        rE   r   r	   r.   NrY   rR   rS   zY is not supported. Please make sure to choose one of 'linspace', 'leading' or 'trailing'.r'   )	in_sigmasc                       g | ]} | qS r   _sigma_to_tr=   r}   
log_sigmasrp   r   r   r?   P      z6LMSDiscreteScheduler.set_timesteps.<locals>.<listcomp>)r   ri   c                    r   r   r   r   r   r   r   r?   S  r   c                    r   r   r   r   r   r   r   r?   V  r   rZ   )r   r   r/   r[   )!ri   r]   rQ   rc   rE   rF   r5   copyarangeroundrf   rT   r0   rd   rb   r)   interplenrK   _convert_to_karrasrL   _convert_to_exponentialrM   _convert_to_betare   r   rg   ro   rh   	timestepsrm   rn   rk   )rp   ri   r   r   
step_ratiorh   r   r   r   rj   (  sJ   
*$


z"LMSDiscreteScheduler.set_timestepsschedule_timestepsc                 C   s:   |du r| j }||k }t|dkrdnd}||  S )ak  
        Find the index of a given timestep in the timestep schedule.

        Args:
            timestep (`float` or `torch.Tensor`):
                The timestep value to find in the schedule.
            schedule_timesteps (`torch.Tensor`, *optional*):
                The timestep schedule to search in. If `None`, uses `self.timesteps`.

        Returns:
            `int`:
                The index of the timestep in the schedule. For the very first step, returns the second index if
                multiple matches exist to avoid skipping a sigma when starting mid-schedule (e.g., for image-to-image).
        Nr	   r   )r   nonzeror   item)rp   r{   r   indicesposr   r   r   index_for_timestepc  s
   z'LMSDiscreteScheduler.index_for_timestepc                 C   s@   | j du rt|tjr|| jj}| || _dS | j	| _dS )z
        Initialize the step index for the scheduler based on the given timestep.

        Args:
            timestep (`float` or `torch.Tensor`):
                The current timestep to initialize the step index from.
        N)
ry   
isinstancer   r   ro   r   r   r   rm   rn   )rp   r{   r   r   r   r|     s
   
z%LMSDiscreteScheduler._init_step_indexr}   r   c                 C   s   t t |d}||ddt jf  }t j|dkddjddj|jd d d}|d }|| }|| }|| ||  }	t |	dd}	d|	 | |	|  }
|
|j}
|
S )a  
        Convert sigma values to corresponding timestep values through interpolation.

        Args:
            sigma (`np.ndarray`):
                The sigma value(s) to convert to timestep(s).
            log_sigmas (`np.ndarray`):
                The logarithm of the sigma schedule used for interpolation.

        Returns:
            `np.ndarray`:
                The interpolated timestep value(s) corresponding to the input sigma(s).
        g|=Nr   )axisr   )rr   r	   )	rc   r)   maximumnewaxiscumsumargmaxclipshapereshape)rp   r}   r   	log_sigmadistslow_idxhigh_idxlowhighwr%   r   r   r   r     s   ,z LMSDiscreteScheduler._sigma_to_tr   c           	      C   s\   |d   }|d   }d}tdd| j}|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.

        Returns:
            `torch.Tensor`:
                The converted sigma values following the Karras noise schedule.
        rY   r   g      @r	   )r   rc   rE   ri   )	rp   r   	sigma_min	sigma_maxrhorampmin_inv_rhomax_inv_rhorh   r   r   r   r     s   z'LMSDiscreteScheduler._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.
        r   Nr   rY   r   )
hasattrr]   r   r   r   rc   r   rE   r!   r)   )rp   r   ri   r   r   rh   r   r   r   r     s   

 z,LMSDiscreteScheduler._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.
        r   Nr   rY   r   c                    s   g | ]
}|    qS r   r   )r=   ppf)r   r   r   r   r?     s    z9LMSDiscreteScheduler._convert_to_beta.<locals>.<listcomp>c                    s   g | ]}t jj| qS r   )scipystatsr   r   )r=   r{   )r   r   r   r   r?     s    r	   )r   r]   r   r   r   rc   rd   rE   )rp   r   ri   r   r   rh   r   )r   r   r   r   r   r     s    

	z%LMSDiscreteScheduler._convert_to_beta   Tmodel_outputreturn_dictc                    sJ  j std jdu r| jj }jjdkr%|||  }n/jjdkrA|| |d d d   ||d d   }njjdkrJ|}n
td	jj d
|| | }j	
| tj	 krmj	d tjd    fddt D }	|tdd t|	tj	D  }
 jd7  _|s|
|fS t|
|dS )aa  
        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.Tensor`):
                The direct output from learned diffusion model.
            timestep (`float` or `torch.Tensor`):
                The current discrete timestep in the diffusion chain.
            sample (`torch.Tensor`):
                A current instance of a sample created by the diffusion process.
            order (`int`, defaults to 4):
                The order of the linear multistep method.
            return_dict (`bool`, *optional*, defaults to `True`):
                Whether or not to return a [`~schedulers.scheduling_utils.SchedulerOutput`] or tuple.

        Returns:
            [`~schedulers.scheduling_utils.SchedulerOutput`] or `tuple`:
                If return_dict is `True`, [`~schedulers.scheduling_utils.SchedulerOutput`] is returned, otherwise a
                tuple is returned where the first element is the sample tensor.

        zThe `scale_model_input` function should be called before `step` to ensure correct denoising. See `StableDiffusionPipeline` for a usage example.NrD   rP   r   r	   r'   rO   zprediction_type given as z, must be one of `epsilon`, or `v_prediction`r   c                    s   g | ]
}  j|qS r   )r   rv   )r=   
curr_orderr   rp   r   r   r?   _  s    z-LMSDiscreteScheduler.step.<locals>.<listcomp>c                 s   s    | ]	\}}|| V  qd S Nr   )r=   coeff
derivativer   r   r   	<genexpr>b  s    
z,LMSDiscreteScheduler.step.<locals>.<genexpr>)r   r   )rl   warningswarnrv   r|   rh   r]   rN   r0   rk   r2   r   popr3   r1   r\   zipreversedrm   r   )rp   r   r{   rO   r   r   r}   r   r   
lms_coeffsr   r   r   r   step!  s>   

,

zLMSDiscreteScheduler.steporiginal_samplesnoiser   c                    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|||  }|S )	am  
        Add noise to the original samples according to the noise schedule at the specified timesteps.

        Args:
            original_samples (`torch.Tensor`):
                The original samples to which noise will be added.
            noise (`torch.Tensor`):
                The noise tensor to add to the original samples.
            timesteps (`torch.Tensor`):
                The timesteps at which to add noise, determining the noise level from the schedule.

        Returns:
            `torch.Tensor`:
                The noisy samples with added noise scaled according to the timestep schedule.
        r   mpsr.   Nc                    r   r   )r   )r=   r%   r   rp   r   r   r?     r   z2LMSDiscreteScheduler.add_noise.<locals>.<listcomp>r   rY   )rh   ro   r   r/   typer   is_floating_pointr   r5   ry   rv   r   flattenr   	unsqueeze)rp   r   r   r   rh   step_indicesr}   noisy_samplesr   r   r   	add_noiser  s"   


zLMSDiscreteScheduler.add_noisec                 C   s   | j jS r   )r]   rF   rs   r   r   r   __len__  s   zLMSDiscreteScheduler.__len__)r@   rA   rB   rC   NFFFrD   rE   r   )r   r   )r   r   )r   T)'r   r   r   r   r
   _compatiblesr   r   intfloatstrrc   ndarraylistboolr   rq   propertyr   r   rt   rv   ry   rz   r~   r   r   rj   r   r|   r   r   r   r   r   tupler   r   r   r   r   r   r   r;   h   s    $	
1
 
<
$#
5
Q
0r;   )r   r   )r!   r   dataclassesr   typingr   numpyrc   r   configuration_utilsr   r   utilsr   r   scheduling_utilsr
   r   scipy.statsr   r   r   r   r   r   r:   r;   r   r   r   r   <module>   s4   
4