o
    Git                  	   @   s   d dl 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mZmZ e r;d dlZe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)Literal   )ConfigMixinregister_to_config)	deprecateis_scipy_availablelogging)randn_tensor   )KarrasDiffusionSchedulersSchedulerMixinSchedulerOutput+?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t r   h/home/ubuntu/.local/lib/python3.10/site-packages/diffusers/schedulers/scheduling_dpmsolver_singlestep.pyalpha_bar_fn>   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   C   s   4
r   c                 S   s   t | d S )Ng      ()r   r   r   r   r   r   r   J   s   z"Unsupported alpha_transform_type: r
   dtype)
ValueErrorrangeappendmintorchtensorfloat32)r   r   r   r   betasit1t2r   r   r   betas_for_alpha_bar$   s   


"r2   c                2   @   s  e Zd ZdZdd eD ZdZeddddd	d
ddddddddddddded d	ddfde	dedede
d dejee B d	B de	de
d dededed e
d! d"e
d# d$ed%ed&ed'ed(ed)ed*e
d+ d,ed-e
d. d	B d/ed0e
d d1d	f0d2d3Zd4e	d1ee	 fd5d6Zed1e	fd7d8Zed1e	fd9d:Zdzd<e	d1d	fd=d>Z								d{d4e	d?eejB d@ed	B dAee	 d	B fdBdCZdDejd1ejfdEdFZdGejdHejd1ejfdIdJZdGejd1eejejf fdKdLZdMejd4e	d1ejfdNdOZdMejd4e	d1ejfdPdQZ	Rd|dMejd4e	dSedTed1ejf
dUdVZ d	dWdXejdDejd	B d1ejfdYdZZ!d	d	d[dXejdDejd	B d\ejd	B d1ejfd]d^Z"d	d	d[d_eej dDejd	B d\ejd	B d1ejfd`daZ#d	d	d[d_eej dDejd	B d\ejd	B d1ejfdbdcZ$d	d	d	ddd_eej dDejd	B dee	d\ejd	B d1ejf
dfdgZ%		d}dhe	ejB diejd	B d1e	fdjdkZ&dhe	ejB d1d	fdldmZ'			nd~dXejdhe	ejB dDejdoej(d	B dped1e)eB fdqdrZ*dDejd1ejfdsdtZ+duejd\ejdAej,d1ejfdvdwZ-d1e	fdxdyZ.d	S )DPMSolverSinglestepScheduleru  
    `DPMSolverSinglestepScheduler` is a fast dedicated high-order solver for diffusion 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 (`"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. Choose from
            `linear`, `scaled_linear`, or `squaredcos_cap_v2`.
        trained_betas (`np.ndarray` or `list[float]`, *optional*):
            Pass an array of betas directly to the constructor to bypass `beta_start` and `beta_end`.
        solver_order (`int`, defaults to `2`):
            The DPMSolver 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 (`"epsilon"`, `"sample"`, `"v_prediction"`, or `"flow_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`), `v_prediction` (see section 2.4 of [Imagen
            Video](https://huggingface.co/papers/2210.02303) paper), or `flow_prediction`.
        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` and
            `algorithm_type="dpmsolver++"`.
        algorithm_type (`"dpmsolver"`, `"dpmsolver++"`, or `"sde-dpmsolver++"`, defaults to `"dpmsolver++"`):
            Algorithm type for the solver; can be `dpmsolver`, `dpmsolver++`, or `sde-dpmsolver++`. The `dpmsolver`
            type implements the algorithms in the [DPMSolver](https://huggingface.co/papers/2206.00927) paper, and the
            `dpmsolver++` type implements the algorithms in the [DPMSolver++](https://huggingface.co/papers/2211.01095)
            paper. It is recommended to use `dpmsolver++` or `sde-dpmsolver++` with `solver_order=2` for guided
            sampling like in Stable Diffusion.
        solver_type (`"midpoint"` or `"heun"`, defaults to `"midpoint"`):
            Solver type for the second-order solver; can be `midpoint` or `heun`. The solver type slightly affects the
            sample quality, especially for a small number of steps. It is recommended to use `midpoint` solvers.
        lower_order_final (`bool`, defaults to `False`):
            Whether to use lower-order solvers in the final steps. Only valid for < 15 inference steps. This can
            stabilize the sampling of DPMSolver for steps < 15, especially for steps <= 10.
        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.
        use_flow_sigmas (`bool`, *optional*, defaults to `False`):
            Whether to use flow sigmas for step sizes in the noise schedule during the sampling process.
        flow_shift (`float`, *optional*, defaults to `1.0`):
            The flow shift parameter for flow-based models.
        final_sigmas_type (`"zero"` or `"sigma_min"`, *optional*, defaults to `"zero"`):
            The final `sigma` value for the noise schedule during the sampling process. If `"sigma_min"`, the final
            sigma is the same as the last sigma in the training schedule. If `"zero"`, the final sigma is set to 0.
        lambda_min_clipped (`float`, defaults to `-inf`):
            Clipping threshold for the minimum value of `lambda(t)` for numerical stability. This is critical for the
            cosine (`squaredcos_cap_v2`) noise schedule.
        variance_type (`"learned"` or `"learned_range"`, *optional*):
            Set to `"learned"` or `"learned_range"` for diffusion models that predict variance. If set, the model's
            output contains the predicted Gaussian variance.
        use_dynamic_shifting (`bool`, defaults to `False`):
            Whether to use dynamic shifting for the noise schedule.
        time_shift_type (`"exponential"`, defaults to `"exponential"`):
            The type of time shifting to apply.
    c                 C   s   g | ]}|j qS r   )name).0er   r   r   
<listcomp>   s    z'DPMSolverSinglestepScheduler.<listcomp>r
   i  g-C6?g{Gz?linearNr   epsilonFgףp=
?      ?dpmsolver++midpointzeroinfexponentialnum_train_timesteps
beta_startbeta_endbeta_schedule)r8   scaled_linearsquaredcos_cap_v2trained_betassolver_orderprediction_type)r9   samplev_predictionflow_predictionthresholdingdynamic_thresholding_ratiosample_max_valuealgorithm_type	dpmsolverr;   sde-dpmsolver++solver_typer<   heunlower_order_finaluse_karras_sigmasuse_exponential_sigmasuse_beta_sigmasuse_flow_sigmas
flow_shiftfinal_sigmas_type)r=   	sigma_minlambda_min_clippedvariance_typelearnedlearned_rangeuse_dynamic_shiftingtime_shift_typer   c                 C   sV  | j jrt stdt| j j| j j| j jgdkrtd|dkr*d}tdd| |d ur8t	j
|t	jd| _n:|d	krHt	j|||t	jd| _n*|d
kr^t	j|d |d |t	jdd | _n|dkrht|| _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kr| jdd n
t| d| j |dvr|dv r| jdd n
t| d| j |dvr|dkrtd| d| dd | _tjd|d |tjdd d d  }t	|| _ d g| | _!d | _"| #|| _$d | _%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.rQ   zalgorithm_type `dpmsolver` is deprecated and will be removed in a future version. Choose from `dpmsolver++` or `sde-dpmsolver++` insteadzalgorithm_types=dpmsolver1.0.0r%   r8   rD   r   r   rE   z is not implemented for r:   r   dimrP   deisr;   )rO   rT   )logrhobh1bh2r<   )rS   r;   rR   r=   z`final_sigmas_type` z' is not supported for `algorithm_type` z$. Please choose `sigma_min` instead.cpu)(configrY   r   ImportErrorsumrX   rW   r'   r   r+   r,   r-   r.   linspacer2   NotImplementedError	__class__alphascumprodalphas_cumprodr"   alpha_tsigma_tr    lambda_tsigmasinit_noise_sigmar   num_inference_stepsnpcopy
from_numpy	timestepsmodel_outputsrI   get_order_list
order_list_step_index_begin_indexto)selfr@   rA   rB   rC   rF   rG   rH   rL   rM   rN   rO   rS   rV   rW   rX   rY   rZ   r[   r\   r^   r_   rc   rd   deprecation_messager   r   r   r   __init__   s\   $&z%DPMSolverSinglestepScheduler.__init__r}   c                 C   sV  |}| j j}|dkrtd| j jr||dkrM|d dkr.g d|d d  ddg dg }nq|d dkr@g d|d  dg }n_g d|d  ddg }nR|dkrr|d dkrfddg|d d  ddg }n9ddg|d  dg }n-|dkr{dg| }n#|dkrg d|d  }n|dkrddg|d  }n	|dkrdg| }| j jdkrd|d< |S )	aC  
        Computes the solver order at each time step.

        Args:
            num_inference_steps (`int`):
                The number of diffusion steps used when generating samples with a pre-trained model.

        Returns:
            `list[int]`:
                The list of solver orders for each timestep.
           z,Order > 3 is not supported by this schedulerr   )r
   r   r   r
   r   r=   rm   )ro   rG   r'   rV   r\   )r   r}   stepsorderordersr   r   r   r      s6   $

z+DPMSolverSinglestepScheduler.get_order_listc                 C      | j S )z
        The index counter for current timestep. It will increase 1 after each scheduler step.

        Returns:
            `int` or `None`:
                The current step index.
        )r   r   r   r   r   
step_index)     	z'DPMSolverSinglestepScheduler.step_indexc                 C   r   )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.
        r   r   r   r   r   begin_index4  r   z(DPMSolverSinglestepScheduler.begin_indexr   r   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.
        Nr   )r   r   r   r   r   set_begin_index@  s   
z,DPMSolverSinglestepScheduler.set_begin_indexdevicemur   c           	         s  |durj jrj jdksJ t|j _|du r#|du r#td|dur/|dur/td|dur;j jr;td|durGj jrGtd|durSj j	rStd|pXt
|}|_|durjt|tj}n2ttjdgj j}| }tdj jd | |d  ddd	 dd	  tj}tdj j d
 }t| j jrt| }j||d}t fdd|D  }nj jrt| }j||d}t fdd|D }nfj j	rt| }j||d}t fdd|D }nEj jrItddj j |d }d| }tj j| dj jd |   dd	  }|j j  }nt|t dt
||}j j!dkrldjd  jd  d
 }nj j!dkrvd}n	tdj j! t"||ggtj#}t$|j%|d_&t$|j%|tjd_'dgj j( _)d_*j j+s|j j( dkrt,-d j.dd j j+s܈j j!dkrt,-d j.dd /|_0d_1d_2j&%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.
            timesteps (`list[int]`, *optional*):
                Custom timesteps used to support arbitrary spacing between timesteps. If `None`, then the default
                timestep spacing strategy of equal spacing between timesteps schedule is used. If `timesteps` is
                passed, `num_inference_steps` must be `None`.
        Nr?   z?Must pass exactly one of  `num_inference_steps` or `timesteps`.z<Cannot use `timesteps` when `config.use_karras_sigmas=True`.zCCannot set `timesteps` with `config.use_exponential_sigmas = True`.z<Cannot set `timesteps` with `config.use_beta_sigmas = True`.r   r
   rm   r   )	in_sigmasr}   c                       g | ]} | qS r   _sigma_to_tr5   sigma
log_sigmasr   r   r   r7         z>DPMSolverSinglestepScheduler.set_timesteps.<locals>.<listcomp>c                    r   r   r   r   r   r   r   r7     r   c                    r   r   r   r   r   r   r   r7     r   r:   r]   r=   zC `final_sigmas_type` must be one of `sigma_min` or `zero`, but got )r   r   r&   zChanging scheduler {self.config} to have `lower_order_final` set to True to handle uneven amount of inference steps. Please make sure to always use an even number of `num_inference steps when using `lower_order_final=False`.T)rV   z `last_sigmas_type='zero'` is not supported for `lower_order_final=False`. Changing scheduler {self.config} to have `lower_order_final` set to True.rn   )3ro   rc   rd   r~   r   r[   r'   rW   rX   rY   lenr}   arrayastypeint64r+   searchsortedfliprz   r^   itemrr   r@   roundr   rw   r    _convert_to_karras_convert_to_exponential_convert_to_betarZ   interparanger\   concatenater-   r   r   r{   r   rG   r   rI   rV   loggerwarningr   r   r   r   r   )	r   r}   r   r   r   clipped_idxr{   ru   
sigma_lastr   r   r   set_timestepsJ  s   
 

2z*DPMSolverSinglestepScheduler.set_timestepsrI   c                 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 )az  
        Apply dynamic thresholding to the predicted sample.

        "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://huggingface.co/papers/2205.11487

        Args:
            sample (`torch.Tensor`):
                The predicted sample to be thresholded.

        Returns:
            `torch.Tensor`:
                The thresholded sample.
        r
   rf   )r*   max)r&   shaper+   r-   float64floatreshaper~   prodabsquantilero   rM   clamprN   	unsqueezer   )r   rI   r&   
batch_sizechannelsremaining_dims
abs_samplesr   r   r   _threshold_sample  s   


z.DPMSolverSinglestepScheduler._threshold_sampler   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   )r   r
   )	r~   r    maximumnewaxiscumsumargmaxclipr   r   )r   r   r   	log_sigmadistslow_idxhigh_idxlowhighwr   r   r   r   r     s   ,z(DPMSolverSinglestepScheduler._sigma_to_tc                 C   s@   | j jrd| }|}||fS d|d d d  }|| }||fS )a(  
        Convert sigma values to alpha_t and sigma_t values.

        Args:
            sigma (`torch.Tensor`):
                The sigma value(s) to convert.

        Returns:
            `tuple[torch.Tensor, torch.Tensor]`:
                A tuple containing (alpha_t, sigma_t) values.
        r
   r   r   )ro   rZ   )r   r   rx   ry   r   r   r   _sigma_to_alpha_sigma_t  s   z4DPMSolverSinglestepScheduler._sigma_to_alpha_sigma_tr   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.
        r]   N	sigma_maxrm   r   g      @r
   )hasattrro   r]   r   r   r~   rr   )
r   r   r}   r]   r   rhorampmin_inv_rhomax_inv_rhor{   r   r   r   r     s   

z/DPMSolverSinglestepScheduler._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   rm   r   )
r   ro   r]   r   r   r~   r   rr   r   r    )r   r   r}   r]   r   r{   r   r   r   r   E  s   

 z4DPMSolverSinglestepScheduler._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   rm   r   c                    s   g | ]
}|    qS r   r   )r5   ppf)r   r]   r   r   r7     s    zADPMSolverSinglestepScheduler._convert_to_beta.<locals>.<listcomp>c                    s   g | ]}t jj| qS r   )scipystatsr   r   )r5   timestep)r   r   r   r   r7     s    r
   )r   ro   r]   r   r   r~   r   rr   )r   r   r}   r   r   r{   r   )r   r   r   r]   r   r   g  s    

	z-DPMSolverSinglestepScheduler._convert_to_betarI   model_outputc                O   sr  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d	v r| jjd
kr_| jjdv rI|ddddf }| j| j	 }| 
|\}}|||  | }	nB| jjdkrh|}	n9| jjdkr| j| j	 }| 
|\}}|| ||  }	n| jjdkr| j| j	 }|||  }	n
td| jj d| jjr| |	}	|	S | jjdkr7| jjd
kr| jjdv r|ddddf }
nF|}
nC| jjdkr| j| j	 }| 
|\}}|||  | }
n'| jjdkr| j| j	 }| 
|\}}|| ||  }
n
td| jj d| jjr5| j| | j| }}|||
  | }	| |	}	|||	  | }
|
S dS )a  
        Convert the model output to the corresponding type the DPMSolver/DPMSolver++ algorithm needs. DPM-Solver is
        designed to discretize an integral of the noise prediction model, and DPM-Solver++ is designed to discretize an
        integral of the data prediction model.

        > [!TIP] > The algorithm and model type are decoupled. You can use either DPMSolver or DPMSolver++ for both
        noise > prediction and data prediction models.

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

        Returns:
            `torch.Tensor`:
                The converted model output.
        r   r   Nr
   /missing `sample` as a required keyword argumentr   re   Passing `timesteps` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`rl   r9   r`   r   rI   rJ   rK   zprediction_type given as zo must be one of `epsilon`, `sample`, `v_prediction`, or `flow_prediction` for the DPMSolverSinglestepScheduler.rQ   z\ must be one of `epsilon`, `sample`, or `v_prediction` for the DPMSolverSinglestepScheduler.)r   popr'   r   ro   rO   rH   r_   r{   r   r   rL   r   rx   ry   )r   r   rI   argskwargsr   r   rx   ry   x0_predr9   r   r   r   convert_model_output  sp    



z1DPMSolverSinglestepScheduler.convert_model_outputrI   noiser   c             	   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 }}	| |\}
}| |	\}}	t|
t| }t|t|	 }|| }| j	j
dkr||	 | |
t| d  |  }|S | j	j
dkr|
| | |t|d  |  }|S | j	j
dkr|dusJ ||	 t|  | |
dtd|   |  |tdtd|   |  }|S )az  
        One step for the first-order DPMSolver (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   r   r   re   r   Passing `prev_timestep` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`r;   r:   rQ   rR          )r   r   r'   r   r{   r   r   r+   r    ro   rO   r   r"   )r   r   rI   r   r   r   r   r   ry   sigma_srx   alpha_srz   lambda_shx_tr   r   r   dpm_solver_first_order_update  sN     
$
"z:DPMSolverSinglestepScheduler.dpm_solver_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  }}	}
| |\}}| |	\}}	| |
\}}
t|t| }t|t|	 }t|t|
 }|d |d }}|| || }}|| }|d| ||  }}| j	j
dkr| j	jdkr||
 | |t| d  |  d|t| d   |  }|S | j	jdkr||
 | |t| d  |  |t| d | d  |  }|S | j	j
dkrd| j	jdkr;|| | |t|d  |  d|t|d   |  }|S | j	jdkrb|| | |t|d  |  |t|d | d  |  }|S | j	j
dkr|dusrJ | j	jdkr||
 t|  | |dtd|   |  d|dtd|    |  |tdtd|   |  }|S | j	jdkr||
 t|  | |dtd|   |  |dtd|  d|  d  |  |tdtd|   |  }|S )a  
        One step for the second-order singlestep DPMSolver that computes the solution at time `prev_timestep` from the
        time `timestep_list[-2]`.

        Args:
            model_output_list (`list[torch.Tensor]`):
                The direct outputs from learned diffusion model at current and latter timesteps.
            timestep (`int`):
                The current and latter 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   timestep_listNr
   r   r   r   re   Passing `timestep_list` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`r   rm   r   r:   r;   r<   r   rU   rQ   rR   r   r   r   r'   r   r{   r   r   r+   r    ro   rO   rS   r   r"   )r   r   rI   r   r   r   r   r   ry   sigma_s0sigma_s1rx   alpha_s0alpha_s1rz   	lambda_s0	lambda_s1m0m1r   h_0r0D0D1r   r   r   r   )singlestep_dpm_solver_second_order_update7  s     



)
#

$zFDPMSolverSinglestepScheduler.singlestep_dpm_solver_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\}}	}
}| |\}}| |	\}}	| |
\}}
| |\}}t|t| }t|t|	 }t|t|
 }t|t| }|d |d |d }}}|| || || }}}|| || }}|}d| ||  d| ||  }}|| ||  ||  }d||  ||  } | j	j
dkrj| j	jdkr+|| | |t| d  |  |t| d | d  |  }!|!S | j	jdkrh|| | |t| d  |  |t| d | d  |  |t| d | |d  d  |   }!|!S | j	j
dkr| j	jdkr|| | |t|d  |  |t|d | d  |  }!|!S | j	jdkr|| | |t|d  |  |t|d | d  |  |t|d | |d  d  |   }!|!S | j	j
dkr|dusJ | j	jdkr)|| t|  | |dtd|   |  |dtd|  d|  d  |  |tdtd|   |  }!|!S | j	jdkr|| t|  | |dtd|   |  |dtd|  d|  d  |  |dtd|  d|  d| d  d  |   |tdtd|   |  }!|!S )a  
        One step for the third-order singlestep DPMSolver that computes the solution at time `prev_timestep` from the
        time `timestep_list[-3]`.

        Args:
            model_output_list (`list[torch.Tensor]`):
                The direct outputs from learned diffusion model at current and latter timesteps.
            timestep (`int`):
                The current and latter 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 diffusion process.

        Returns:
            `torch.Tensor`:
                The sample tensor at the previous timestep.
        r   r   Nr
   r   r   r   re   r   r   rm   r   r:   g       @r;   r<   rU   r   rQ   rR   r   r   )"r   r   rI   r   r   r   r   r   ry   r   r   sigma_s2rx   r   r   alpha_s2rz   r   r   	lambda_s2r   r   m2r   r  h_1r  r1r  D1_0D1_1r  D2r   r   r   r   (singlestep_dpm_solver_third_order_update  s     

"
,
&&

$$$0zEDPMSolverSinglestepScheduler.singlestep_dpm_solver_third_order_updaterI   r   r   r   c          	      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 rFt |dkrB|d }ntd	|durPtdd
d |durZtdd
d |dkrh| j|d ||dS |dkrt| j|||dS |dkr| j|||dS td| )a  
        One step for the singlestep DPMSolver.

        Args:
            model_output_list (`list[torch.Tensor]`):
                The direct outputs from learned diffusion model at current and latter timesteps.
            timestep (`int`):
                The current and latter 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 diffusion process.
            order (`int`):
                The solver order at this step.

        Returns:
            `torch.Tensor`:
                The sample tensor at the previous timestep.
        r   r   Nr
   r   r   r   r   z.missing `order` as a required keyword argumentre   r   r   rm   r   zOrder must be 1, 2, 3, got )r   r   r'   r   r   r  r  )	r   r   rI   r   r   r   r   r   r   r   r   r   singlestep_dpm_solver_update   s:     

z9DPMSolverSinglestepScheduler.singlestep_dpm_solver_updater   schedule_timestepsc                 C   sd   |du r| j }||k }t|dkrt| j d }|S t|dkr*|d  }|S |d  }|S )a  
        Find the index for a given timestep in the schedule.

        Args:
            timestep (`int` or `torch.Tensor`):
                The timestep for which to find the index.
            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.
        Nr   r
   )r   nonzeror   r   )r   r   r  index_candidatesr   r   r   r   index_for_timestep`  s   
z/DPMSolverSinglestepScheduler.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 counter for the scheduler.

        Args:
            timestep (`int` or `torch.Tensor`):
                The current timestep for which to initialize the step index.
        N)
r   
isinstancer+   Tensorr   r   r   r  r   r   )r   r   r   r   r   _init_step_index  s
   
	z-DPMSolverSinglestepScheduler._init_step_indexT	generatorreturn_dictc           
      C   s
  | j du r	td| jdu r| | | j||d}t| jjd D ]}| j|d  | j|< q"|| jd< | jj	dkrFt
|j||j|jd}nd}| j| j }| j|  du rb|d8 }| j|  du sV|dkri|| _| j| j| j||d}	|  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 singlestep DPMSolver.

        Args:
            model_output (`torch.Tensor`):
                The direct output from learned diffusion model.
            timestep (`int` 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.
            generator (`torch.Generator`, *optional*):
                A random number generator for stochastic sampling.
            return_dict (`bool`, 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.

        NzaNumber of inference steps is 'None', you need to run 'set_timesteps' after creating the schedulerr   r
   rm   rR   )r  r   r&   r  )prev_sample)r}   r'   r   r  r   r(   ro   rG   r   rO   r	   r   r   r&   r   rI   r  r   r   )
r   r   r   rI   r  r  r/   r   r   r  r   r   r   step  s8   




z!DPMSolverSinglestepScheduler.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   )r   rI   r   r   r   r   r   scale_model_input  s   z.DPMSolverSinglestepScheduler.scale_model_inputoriginal_samplesc           
         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 )	a  
        Add noise to the original samples according to the noise schedule at the specified timesteps.

        Args:
            original_samples (`torch.Tensor`):
                The original samples without noise.
            noise (`torch.Tensor`):
                The noise to add to the samples.
            timesteps (`torch.IntTensor`):
                The timesteps at which to add noise to the samples.

        Returns:
            `torch.Tensor`:
                The noisy samples.
        r   mpsr%   Nc                    r   r   )r  )r5   r   r  r   r   r   r7     r   z:DPMSolverSinglestepScheduler.add_noise.<locals>.<listcomp>r   rm   )r{   r   r   r&   typer+   is_floating_pointr   r-   r   r   r   flattenr   r   r   )
r   r  r   r   r{   step_indicesr   rx   ry   noisy_samplesr   r!  r   	add_noise  s$   


z&DPMSolverSinglestepScheduler.add_noisec                 C   s   | j jS N)ro   r@   r   r   r   r   __len__  s   z$DPMSolverSinglestepScheduler.__len__)r   )NNNN)r   r   r(  )NT)/__name__
__module____qualname____doc__r   _compatiblesr   r   r   intr   r~   ndarraylistboolr   r   propertyr   r   r   strr+   r   r   r  r   r   tupler   r   r   r   r   r   r  r  r  r  r  	Generatorr   r  r  	IntTensorr'  r)  r   r   r   r   r3   X   s   H	

X,


m, %'#
4
d
D
s
~
C
%
I
1r3   )r   r   )r   typingr   numpyr~   r+   configuration_utilsr   r   utilsr   r   r   utils.torch_utilsr	   scheduling_utilsr   r   r   scipy.statsr   
get_loggerr*  r   r/  r   r  r2   r3   r   r   r   r   <module>   s.   

4