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mZ ddlmZ ddlmZmZmZ eeZ			
dddZG dd dee
ZdS )    N)ListOptionalTupleUnion   )ConfigMixinregister_to_config)	deprecatelogging)randn_tensor   )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   r/home/ubuntu/SoloSpeech/.venv/lib/python3.10/site-packages/diffusers/schedulers/scheduling_dpmsolver_singlestep.pyalpha_bar_fn:   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                %   @   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ed d	fd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e
 d"ed#ee
 f"d$d%Zd&e	d'ee	 fd(d)Zed*d+ Zed,d- Zdad/e	fd0d1Z						dbd&e	d2ee
ejf d3eee	  fd4d5Zd6ejd'ejfd7d8Zd9d: Zd;d< Zd=ejd'ejfd>d?Zd	d@dAejd6ejd'ejfdBdCZd	d	dDdAejd6ejdEeej d'ejfdFdGZ d	d	dDdHeej d6ejdEeej d'ejfdIdJZ!d	d@dHeej d6ejd'ejfdKdLZ"d	d	d	dMdHeej d6ejdNe	dEeej d'ejf
dOdPZ#dcdQdRZ$dSdT Z%			UdddAejdVee	ejf d6ejdWed'ee&e'f f
dXdYZ(d6ejd'ejfdZd[Z)d\ejdEejd3ej*d'ejfd]d^Z+d_d` Z,d	S )e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 (`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 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 (`str`, defaults to `epsilon`, *optional*):
            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` and
            `algorithm_type="dpmsolver++"`.
        algorithm_type (`str`, defaults to `dpmsolver++`):
            Algorithm type for the solver; can be `dpmsolver` or `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 (`str`, 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 `True`):
            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}.
        final_sigmas_type (`str`, *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 (`str`, *optional*):
            Set to "learned" or "learned_range" for diffusion models that predict variance. If set, the model's output
            contains the predicted Gaussian variance.
    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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final_sigmas_typelambda_min_clippedvariance_typec                 C   s  |dkrd}t dd| |d urtj|tjd| _n:|dkr*tj|||tjd| _n*|dkr@tj|d |d |tjdd	 | _n|d
krJt|| _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 )N	dpmsolverzalgorithm_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   r1   scaled_linear      ?r   squaredcos_cap_v2z is not implemented for r3   r   dimr   )rI   r4   sde-dpmsolver++deisr4   )rB   )r5   heun)logrhobh1bh2r5   )rC   r4   rP   r6   z`final_sigmas_type` z' is not supported for `algorithm_type` z%. Please chooose `sigma_min` instead.cpu)!r	   r!   r"   r#   r'   linspacer+   NotImplementedError	__class__alphascumprodalphas_cumprodsqrtalpha_tsigma_tloglambda_tsigmasinit_noise_sigmar   r   num_inference_stepsnpcopy
from_numpy	timestepsmodel_outputssampleget_order_list
order_list_step_index_begin_indexto)selfr8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   rF   rG   rH   deprecation_messagerj   r   r   r   __init__   sP   $&z%DPMSolverSinglestepScheduler.__init__rf   returnc                 C   sR  |}| j j}|dkrtd| j jr|dkrP|d dkr/g d|d d  ddg dg }|S |d dkrBg d|d  dg }|S g d|d  ddg }|S |dkrw|d dkrjddg|d d  ddg }|S ddg|d  dg }|S |dkrdg| }|S |dkrg d|d  }|S |dkrddg|d  }|S |dkrdg| }|S )z
        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.
           z,Order > 3 is not supported by this schedulerr   )r   r   rv   r   r   )configr=   r   rD   )rr   rf   stepsorderordersr   r   r   rm      s@   "


z+DPMSolverSinglestepScheduler.get_order_listc                 C      | j S )zg
        The index counter for current timestep. It will increase 1 after each scheduler step.
        )ro   rr   r   r   r   
step_index      z'DPMSolverSinglestepScheduler.step_indexc                 C   r{   )zq
        The index for the first timestep. It should be set from pipeline with `set_begin_index` method.
        rp   r|   r   r   r   begin_index  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`):
                The begin index for the scheduler.
        Nr   )rr   r   r   r   r   set_begin_index  s   
z,DPMSolverSinglestepScheduler.set_begin_indexdevicerj   c                    s  |du r|du rt d|dur|durt d|dur$jjr$t d|p)t|}|_|dur;t|tj}n.t	
t	jdgjj}tdjjd | |d  ddd dd  tj}tdj j d }jjrt| t| }j||d}t fd	d
|D  }nt|tdt||}jjdkrdjd  jd  d }njjdkrd}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rt"#d j$dd jj!s.jjdkr.t"#d j$d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.
            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`.
        Nz?Must pass exactly one of  `num_inference_steps` or `timesteps`.z<Cannot use `timesteps` when `config.use_karras_sigmas=True`.r   r   rW   rL   )	in_sigmasrf   c                       g | ]} | qS r   )_sigma_to_t)r.   sigma
log_sigmasrr   r   r   r0   E      z>DPMSolverSinglestepScheduler.set_timesteps.<locals>.<listcomp>	sigma_minr6   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)rD   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.rX   ))r   rw   rE   lenrf   rg   arrayastypeint64r!   searchsortedfliprc   rG   rY   r8   roundrh   r^   rb   _convert_to_karrasinterparangerF   concatenater#   ri   rq   rd   rj   r=   rk   rl   rD   loggerwarningr   rm   rn   ro   rp   )rr   rf   r   rj   clipped_idxrd   
sigma_lastr   r   r   set_timesteps  sh   
 z*DPMSolverSinglestepScheduler.set_timestepsrl   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 )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   rN   )r    max)r   shaper!   r#   float64floatreshaperg   prodabsquantilerw   r@   clamprA   	unsqueezerq   )rr   rl   r   
batch_sizechannelsremaining_dims
abs_samplesr   r   r   _threshold_samplem  s   



z.DPMSolverSinglestepScheduler._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   )	rg   rb   maximumnewaxiscumsumargmaxclipr   r   )rr   r   r   	log_sigmadistslow_idxhigh_idxlowhighwr   r   r   r   r     s   ,z(DPMSolverSinglestepScheduler._sigma_to_tc                 C   s$   d|d d d  }|| }||fS )Nr   r   rL   r   )rr   r   r`   ra   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 )z6Constructs the noise schedule of Karras et al. (2022).r   N	sigma_maxrW   r   g      @r   )hasattrrw   r   r   itemrg   rY   )
rr   r   rf   r   r   rhorampmin_inv_rhomax_inv_rhord   r   r   r   r     s   

z/DPMSolverSinglestepScheduler._convert_to_karrasrl   model_outputc                O   sJ  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	 }| 
|\}}|||  | }	n/| jjdkrh|}	n&| jjdkr| j| j	 }| 
|\}}|| ||  }	n
td| jj d| jjr| |	}	|	S | jjdkr#| jjd
kr| jjdv r|ddddf }
nE|}
nB| jjdkr| j| j	 }| 
|\}}|||  | }
n&| jjdkr| j| j	 }| 
|\}}|| ||  }
n
td| jj d| jjr!| j| | j| }}|||
  | }	| |	}	|||	  | }
|
S dS )a0  
        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.

        </Tip>

        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   timestepNr   z/missing `sample` as a required keyward argumentrj   rJ   Passing `timesteps` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`rV   r2   )learnedlearned_rangerv   rl   v_predictionzprediction_type given as z\ must be one of `epsilon`, `sample`, or `v_prediction` for the DPMSolverSinglestepScheduler.rI   )r   popr   r	   rw   rB   r>   rH   rd   r}   r   r?   r   r`   ra   )rr   r   rl   argskwargsr   r   r`   ra   x0_predr2   r   r   r   convert_model_output  sj    



z1DPMSolverSinglestepScheduler.convert_model_outputrl   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   0 missing `sample` as a required keyward argumentrj   rJ   r   Passing `prev_timestep` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`r4   r3   rI   rP          )r   r   r   r	   rd   r}   r   r!   rb   rw   rB   r   r_   )rr   r   rl   r   r   r   r   r   ra   sigma_sr`   alpha_src   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   rJ   Passing `timestep_list` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`r   rW   r   r3   r4   r5   rL   rR   rI   rP   r   )r   r   r   r	   rd   r}   r   r!   rb   rw   rB   rC   r   r_   )rr   r   rl   r   r   r   r   r   ra   sigma_s0sigma_s1r`   alpha_s0alpha_s1rc   	lambda_s0	lambda_s1m0m1r   h_0r0D0D1r   r   r   r   )singlestep_dpm_solver_second_order_updateh  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 )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   / missing`sample` as a required keyward argumentrJ   r   r   rW   r   r3   g       @r4   r5   rR   rL   rI   )r   r   r   r	   rd   r}   r   r!   rb   rw   rB   rC   r   )!rr   r   rl   r   r   r   r   ra   r   r   sigma_s2r`   r   r   alpha_s2rc   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     

"

&

$zEDPMSolverSinglestepScheduler.singlestep_dpm_solver_third_order_updaterl   ry   r   ry   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   rv   z/ missing `order` as a required keyward argumentrJ   r   r   rW   r   r   zOrder must be 1, 2, 3, got )r   r   r   r	   r   r   r   )	rr   r   rl   ry   r   r   r   r   r   r   r   r   singlestep_dpm_solver_update?  s:     

z9DPMSolverSinglestepScheduler.singlestep_dpm_solver_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   )rj   nonzeror   r   )rr   r   schedule_timesteps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 )zF
        Initialize the step_index counter for the scheduler.
        N)
r   
isinstancer!   Tensorrq   rj   r   r   ro   rp   )rr   r   r   r   r   _init_step_index  s
   
z-DPMSolverSinglestepScheduler._init_step_indexTr   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`):
                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   rW   rP   )	generatorr   r   r   )prev_sample)rf   r   r}   r   r   r   rw   r=   rk   rB   r   r   r   r   rn   rl   r   ro   r   )
rr   r   r   rl   r   r   r(   r   ry   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   )rr   rl   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 )Nr   mpsr   c                    r   r   )r   )r.   r   r   rr   r   r   r0     r   z:DPMSolverSinglestepScheduler.add_noise.<locals>.<listcomp>r   rW   )rd   rq   r   r   typer!   is_floating_pointrj   r#   r   r}   r   flattenr   r   r   )
rr   r  r   rj   rd   step_indicesr   r`   ra   noisy_samplesr   r  r   	add_noise  s$   


z&DPMSolverSinglestepScheduler.add_noisec                 C   s   | j jS N)rw   r8   r|   r   r   r   __len__  s   z$DPMSolverSinglestepScheduler.__len__)r   )NNNr  )NT)-__name__
__module____qualname____doc__r   _compatiblesry   r   r   intstrr   rg   ndarrayboolrt   r   rm   propertyr}   r   r   r   r!   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  	IntTensorr  r  r   r   r   r   r,   M   s6   ;	
L$



W"
e
D
s
l

@

G
"r,   )r   r   )r   typingr   r   r   r   numpyrg   r!   configuration_utilsr   r   utilsr	   r
   utils.torch_utilsr   scheduling_utilsr   r   r   
get_loggerr  r   r+   r,   r   r   r   r   <module>   s   

,