o
    pi                     @   s   d dl 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 ddlmZmZmZ 			dd
dZG dd dee
ZdS )    N)ListOptionalTupleUnion   )ConfigMixinregister_to_config)	deprecate   )KarrasDiffusionSchedulersSchedulerMixinSchedulerOutput+?cosinec                 C   s   |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`): the maximum beta to use; use values lower than 1 to
                     prevent singularities.
        alpha_transform_type (`str`, *optional*, default to `cosine`): the type of noise schedule for alpha_bar.
                     Choose from `cosine` or `exp`

    Returns:
        betas (`np.ndarray`): 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t r   l/home/ubuntu/SoloSpeech/.venv/lib/python3.10/site-packages/diffusers/schedulers/scheduling_deis_multistep.pyalpha_bar_fn7   s    z)betas_for_alpha_bar.<locals>.alpha_bar_fnexpc                 S   s   t | d S )Ng      ()r   r   r   r   r   r   r   <   s   z"Unsupported alpha_transform_type: r
   dtype)
ValueErrorrangeappendmintorchtensorfloat32)num_diffusion_timestepsmax_betaalpha_transform_typer   betasit1t2r   r   r   betas_for_alpha_bar   s   

"r)   c                "   @   s8  e Zd ZdZdd eD ZdZe							
										dXdede	de	de
deej dede
dede	de	de
de
d ed!ee d"e
d#ef d$d%Zed&d' Zed(d) ZdYd*efd+d,ZdZd-ed.ee
ejf fd/d0Zd1ejd2ejfd3d4Zd5d6 Zd7d8 Zd9ejd2ejfd:d;Zd	d<d=ejd1ejd2ejfd>d?Zd	d<d=ejd1ejd2ejfd@dAZd	d<dBeej d1ejd2ejfdCdDZ d	d<dBeej d1ejd2ejfdEdFZ!dZdGdHZ"dIdJ Z#	d[d=ejdKeeejf d1ejdLed2ee$e%f f
dMdNZ&d1ejd2ejfdOdPZ'dQejdRejdSej(d2ejfdTdUZ)dVdW Z*d	S )\DEISMultistepScheduleru  
    `DEISMultistepScheduler` is a fast high order solver for diffusion ordinary differential equations (ODEs).

    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 (`str`, defaults to `"linear"`):
            The beta schedule, a mapping from a beta range to a sequence of betas for stepping the model. Choose from
            `linear`, `scaled_linear`, or `squaredcos_cap_v2`.
        trained_betas (`np.ndarray`, *optional*):
            Pass an array of betas directly to the constructor to bypass `beta_start` and `beta_end`.
        solver_order (`int`, defaults to 2):
            The DEIS order which can be `1` or `2` or `3`. It is recommended to use `solver_order=2` for guided
            sampling, and `solver_order=3` for unconditional sampling.
        prediction_type (`str`, 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://imagen.research.google/video/paper.pdf) paper).
        thresholding (`bool`, defaults to `False`):
            Whether to use the "dynamic thresholding" method. This is unsuitable for latent-space diffusion models such
            as Stable Diffusion.
        dynamic_thresholding_ratio (`float`, defaults to 0.995):
            The ratio for the dynamic thresholding method. Valid only when `thresholding=True`.
        sample_max_value (`float`, defaults to 1.0):
            The threshold value for dynamic thresholding. Valid only when `thresholding=True`.
        algorithm_type (`str`, defaults to `deis`):
            The algorithm type for the solver.
        lower_order_final (`bool`, defaults to `True`):
            Whether to use lower-order solvers in the final steps. Only valid for < 15 inference steps.
        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}.
        timestep_spacing (`str`, 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>y   s    z!DEISMultistepScheduler.<listcomp>r
     -C6?{Gz?linearNr   epsilonFףp=
?      ?deislogrhoTlinspacer   num_train_timesteps
beta_startbeta_endbeta_scheduletrained_betassolver_orderprediction_typethresholdingdynamic_thresholding_ratiosample_max_valuealgorithm_typesolver_typelower_order_finaluse_karras_sigmastimestep_spacingsteps_offsetc                 C   s  |d urt j|t jd| _n:|dkrt j|||t jd| _n*|dkr4t j|d |d |t jdd | _n|dkr>t|| _n
t| d| j d| j | _t j	| jd	d
| _
t | j
| _t d| j
 | _t | jt | j | _d| j
 | j
 d | _d| _|dvr|dv r| jdd n
t| d| j |dvr|dv r| jdd ntd| d| j d | _tjd	|d |tjdd d d  }t || _d g| | _d	| _d | _d | _| jd| _d S )Nr   r2   scaled_linear      ?r   squaredcos_cap_v2z is not implemented for r5   r   dimr
   )r6   )	dpmsolverzdpmsolver++r6   )rC   )r7   )midpointheunbh1bh2r7   )rD   zsolver type cpu)r   r    r!   r%   r8   r)   NotImplementedError	__class__alphascumprodalphas_cumprodsqrtalpha_tsigma_tloglambda_tsigmasinit_noise_sigmar   num_inference_stepsnpcopy
from_numpy	timestepsmodel_outputslower_order_nums_step_index_begin_indexto)selfr9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   re   r   r   r   __init__|   s@   $&zDEISMultistepScheduler.__init__c                 C      | j S )zg
        The index counter for current timestep. It will increase 1 after each scheduler step.
        )rh   rk   r   r   r   
step_index      z!DEISMultistepScheduler.step_indexc                 C   rm   )zq
        The index for the first timestep. It should be set from pipeline with `set_begin_index` method.
        ri   rn   r   r   r   begin_index   rp   z"DEISMultistepScheduler.begin_indexrr   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`):
                The begin index for the scheduler.
        Nrq   )rk   rr   r   r   r   set_begin_index   s   
z&DEISMultistepScheduler.set_begin_indexra   devicec                    s8  j jdkr%tdj jd |d  ddd dd  tj}n\j jdkrUj j|d  }t	d|d |  ddd dd  tj}|j j
7 }n,j jdkrxj j| }t	j jd|   tj}|d8 }n	tj j dtdj j d	 }j jrt| t| }j||d
}t fdd|D  }t||dd gtj}n't|t	dt||}djd  jd  d	 }t||ggtj}t|_t|j|tjd_t|_dgj j _d_d_d_ jd_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.
        r8   r   r
   NrS   leadingtrailingzY is not supported. Please make sure to choose one of 'linspace', 'leading' or 'trailing'.rJ   )	in_sigmasra   c                       g | ]} | qS r   )_sigma_to_t)r,   sigma
log_sigmasrk   r   r   r.          z8DEISMultistepScheduler.set_timesteps.<locals>.<listcomp>rt   r   rT   )!configrG   rb   r8   r9   roundrc   astypeint64arangerH   r   arrayrY   rF   r]   flip_convert_to_karrasconcatenater!   interplenr   rd   r_   rj   re   ra   r>   rf   rg   rh   ri   )rk   ra   rt   re   
step_ratior_   
sigma_lastr   r{   r   set_timesteps   sR   6$

 
z$DEISMultistepScheduler.set_timestepssamplereturnc                 C   s   |j }|j^}}}|tjtjfvr| }|||t| }|	 }tj
|| jjdd}tj|d| jjd}|d}t|| || }|j||g|R  }||}|S )as  
        "Dynamic thresholding: At each sampling step we set s to a certain percentile absolute pixel value in xt0 (the
        prediction of x_0 at timestep t), and if s > 1, then we threshold xt0 to the range [-s, s] and then divide by
        s. Dynamic thresholding pushes saturated pixels (those near -1 and 1) inwards, thereby actively preventing
        pixels from saturation at each step. We find that dynamic thresholding results in significantly better
        photorealism as well as better image-text alignment, especially when using very large guidance weights."

        https://arxiv.org/abs/2205.11487
        r
   rL   )r   max)r   shaper   r!   float64floatreshaperb   prodabsquantiler   rA   clamprB   	unsqueezerj   )rk   r   r   
batch_sizechannelsremaining_dims
abs_samplesr   r   r   _threshold_sample  s   



z(DEISMultistepScheduler._threshold_samplec                 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 )Ng|=r   )axisr   )r   r
   )	rb   r]   maximumnewaxiscumsumargmaxclipr   r   )rk   rz   r|   	log_sigmadistslow_idxhigh_idxlowhighwr   r   r   r   ry   9  s   ,z"DEISMultistepScheduler._sigma_to_tc                 C   s$   d|d d d  }|| }||fS )Nr
   r   rJ   r   )rk   rz   r[   r\   r   r   r   _sigma_to_alpha_sigma_tQ  s   z.DEISMultistepScheduler._sigma_to_alpha_sigma_trw   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 )z6Constructs the noise schedule of Karras et al. (2022).	sigma_minN	sigma_maxrS   r   g      @r
   )hasattrr   r   r   itemrb   r8   )
rk   rw   ra   r   r   rhorampmin_inv_rhomax_inv_rhor_   r   r   r   r   X  s   

z)DEISMultistepScheduler._convert_to_karrasr   model_outputc          
      O   s  t |dkr
|d n|dd}|du r#t |dkr|d }ntd|dur-tddd | j| j }| |\}}| jjd	krI|||  | }	n"| jjd
krR|}	n| jjdkra|| ||  }	n
td| jj d| jj	rt| 
|	}	| jjdkr|||	  | S td)a  
        Convert the model output to the corresponding type the DEIS algorithm needs.

        Args:
            model_output (`torch.Tensor`):
                The direct output from the learned diffusion model.
            timestep (`int`):
                The current discrete timestep in the diffusion chain.
            sample (`torch.Tensor`):
                A current instance of a sample created by the diffusion process.

        Returns:
            `torch.Tensor`:
                The converted model output.
        r   timestepNr
   z/missing `sample` as a required keyward argumentre   1.0.0Passing `timesteps` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`r3   r   v_predictionzprediction_type given as zV must be one of `epsilon`, `sample`, or `v_prediction` for the DEISMultistepScheduler.r6   'only support log-rho multistep deis now)r   popr   r	   r_   ro   r   r   r?   r@   r   rC   rU   )
rk   r   r   argskwargsr   rz   r[   r\   x0_predr   r   r   convert_model_outputq  s6    

z+DEISMultistepScheduler.convert_model_outputc                O   s2  t |dkr
|d n|dd}t |dkr|d n|dd}|du r3t |dkr/|d }ntd|dur=tdd	d
 |durGtdd	d | j| jd  | j| j }}| |\}	}| |\}
}t|	t| }t|
t| }|| }| j	j
dkr|	|
 | |t|d  |  }|S td)au  
        One step for the first-order DEIS (equivalent to DDIM).

        Args:
            model_output (`torch.Tensor`):
                The direct output from the learned diffusion model.
            timestep (`int`):
                The current discrete timestep in the diffusion chain.
            prev_timestep (`int`):
                The previous discrete timestep in the diffusion chain.
            sample (`torch.Tensor`):
                A current instance of a sample created by the diffusion process.

        Returns:
            `torch.Tensor`:
                The sample tensor at the previous timestep.
        r   r   Nr
   prev_timestepr   0 missing `sample` as a required keyward argumentre   r   r   Passing `prev_timestep` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`r6   r5   r   )r   r   r   r	   r_   ro   r   r   r]   r   rC   r   rU   )rk   r   r   r   r   r   r   r\   sigma_sr[   alpha_sr^   lambda_shx_tr   r   r   deis_first_order_update  s8     
"z.DEISMultistepScheduler.deis_first_order_updatemodel_output_listc                O   s  t |dkr
|d n|dd}t |dkr|d n|dd}|du r3t |dkr/|d }ntd|dur=tddd	 |durGtddd
 | j| jd  | j| j | j| jd  }}}	| |\}
}| |\}}| |	\}}	|d |d }}||
 || |	| }}}| jjdkrdd }|||||||| }|||||||| }|
|| ||  ||   }|S t	d)a  
        One step for the second-order multistep DEIS.

        Args:
            model_output_list (`List[torch.Tensor]`):
                The direct outputs from learned diffusion model at current and latter timesteps.
            sample (`torch.Tensor`):
                A current instance of a sample created by the diffusion process.

        Returns:
            `torch.Tensor`:
                The sample tensor at the previous timestep.
        r   timestep_listNr
   r   r   r   r   Passing `timestep_list` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`r   rS   r6   c                 S   s2   | t | t |  d  t |t |  S )Nr
   rb   r]   )r   bcr   r   r   ind_fn  s   2zIDEISMultistepScheduler.multistep_deis_second_order_update.<locals>.ind_fnr   
r   r   r   r	   r_   ro   r   r   rC   rU   )rk   r   r   r   r   r   r   r\   sigma_s0sigma_s1r[   alpha_s0alpha_s1m0m1rho_trho_s0rho_s1r   coef1coef2r   r   r   r   "multistep_deis_second_order_update  sD     


z9DEISMultistepScheduler.multistep_deis_second_order_updatec                O   s  t |dkr
|d n|dd}t |dkr|d n|dd}|du r3t |dkr/|d }ntd|dur=tddd	 |durGtddd
 | j| jd  | j| j | j| jd  | j| jd  f\}}}	}
| |\}}| |\}}| |	\}}	| |
\}}
|d |d |d }}}|| || |	| |
| f\}}}}| jjdkrdd }|||||||||| }|||||||||| }|||||||||| }||| ||  ||  ||   }|S t	d)a  
        One step for the third-order multistep DEIS.

        Args:
            model_output_list (`List[torch.Tensor]`):
                The direct outputs from learned diffusion model at current and latter timesteps.
            sample (`torch.Tensor`):
                A current instance of a sample created by diffusion process.

        Returns:
            `torch.Tensor`:
                The sample tensor at the previous timestep.
        r   r   Nr
   r   r   z/ missing`sample` as a required keyward argumentr   r   r   rS   r   r6   c                 S   s   | t |t |t |  d  t |t |   t | t | d  dt |   d  }t |t | t |t |  }|| S )Nr
   r   r   )r   r   r   d	numeratordenominatorr   r   r   r   j  s    (zHDEISMultistepScheduler.multistep_deis_third_order_update.<locals>.ind_fnr   r   )rk   r   r   r   r   r   r   r\   r   r   sigma_s2r[   r   r   alpha_s2r   r   m2r   r   r   rho_s2r   r   r   coef3r   r   r   r   !multistep_deis_third_order_update)  sR     

$z8DEISMultistepScheduler.multistep_deis_third_order_updatec                 C   sd   |d u r| j }||k }t|dkrt| j d }|S t|dkr*|d  }|S |d  }|S )Nr   r
   )re   nonzeror   r   )rk   r   schedule_timestepsindex_candidatesro   r   r   r   index_for_timestep  s   
z)DEISMultistepScheduler.index_for_timestepc                 C   s@   | j du rt|tjr|| jj}| || _dS | j	| _dS )zF
        Initialize the step_index counter for the scheduler.
        N)
rr   
isinstancer   Tensorrj   re   rt   r   rh   ri   )rk   r   r   r   r   _init_step_index  s
   
z'DEISMultistepScheduler._init_step_indexr   return_dictc           	      C   s`  | j du r	td| jdu r| | | jt| jd ko'| jjo't| jdk }| jt| jd ko<| jjo<t| jdk }| j||d}t	| jj
d D ]}| j|d  | j|< qL|| jd< | jj
dksk| jdk sk|rs| j||d}n| jj
dks| jdk s|r| j| j|d}n| j| j|d}| j| jj
k r|  jd7  _|  jd7  _|s|fS t|dS )	a  
        Predict the sample from the previous timestep by reversing the SDE. This function propagates the sample with
        the multistep DEIS.

        Args:
            model_output (`torch.Tensor`):
                The direct output from learned diffusion model.
            timestep (`int`):
                The current discrete timestep in the diffusion chain.
            sample (`torch.Tensor`):
                A current instance of a sample created by the diffusion process.
            return_dict (`bool`):
                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.

        NzaNumber of inference steps is 'None', you need to run 'set_timesteps' after creating the schedulerr
      r   r   rS   )prev_sample)ra   r   ro   r   r   re   r   rE   r   r   r>   rf   rg   r   r   r   rh   r   )	rk   r   r   r   r   rE   lower_order_secondr&   r   r   r   r   step  s2   


((

zDEISMultistepScheduler.stepc                 O   s   |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.

        Returns:
            `torch.Tensor`:
                A scaled input sample.
        r   )rk   r   r   r   r   r   r   scale_model_input  s   z(DEISMultistepScheduler.scale_model_inputoriginal_samplesnoisere   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 )Nr~   mpsr   c                    rx   r   )r   )r,   r   r   rk   r   r   r.     r}   z4DEISMultistepScheduler.add_noise.<locals>.<listcomp>r   rS   )r_   rj   rt   r   typer   is_floating_pointre   r!   rr   ro   r   flattenr   r   r   )
rk   r   r   re   r_   step_indicesrz   r[   r\   noisy_samplesr   r   r   	add_noise  s$   


z DEISMultistepScheduler.add_noisec                 C   s   | j jS N)r   r9   rn   r   r   r   __len__  s   zDEISMultistepScheduler.__len__)r/   r0   r1   r2   Nr   r3   Fr4   r5   r6   r7   TFr8   r   )r   r   )T)+__name__
__module____qualname____doc__r   _compatiblesorderr   intr   strr   rb   ndarrayboolrl   propertyro   rr   rs   r   r   rt   r   r   r   ry   r   r   r   r   r   r   r   r   r   r   r   r   r   	IntTensorr   r  r   r   r   r   r*   J   s    .	
B


?"
=
>
I

Y

A
"r*   )r   r   )r   typingr   r   r   r   numpyrb   r   configuration_utilsr   r   utilsr	   scheduling_utilsr   r   r   r)   r*   r   r   r   r   <module>   s   
,