
    (ti0              	           d dl Z d dl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       rd dlZ	 	 dd	ed
eded   dej.                  fdZ G d dee      Zy)    N)CallableLiteral   )ConfigMixinregister_to_config)	deprecateis_scipy_available)randn_tensor   )KarrasDiffusionSchedulersSchedulerMixinSchedulerOutputnum_diffusion_timestepsmax_betaalpha_transform_type)cosineexplaplacereturnc           
      6   |dk(  rd }n |dk(  rd }n|dk(  rd }nt        d|       g }t        |       D ]<  }|| z  }|dz   | z  }|j                  t        d ||       ||      z  z
  |             > t	        j
                  |t        j                  	      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                 f    t        j                  | dz   dz  t         j                  z  dz        dz  S )NgMb?gT㥛 ?r   )mathcospits    w/Volumes/fast/ai/experiments/MLX_z-image/.venv/lib/python3.12/site-packages/diffusers/schedulers/scheduling_sasolver.pyalpha_bar_fnz)betas_for_alpha_bar.<locals>.alpha_bar_fn=   s-    88QY%/$''9A=>!CC    r   c           	         dt        j                  dd| z
        z  t        j                  ddt        j                  d| z
        z  z
  dz         z  }t        j                  |      }t        j
                  |d|z   z        S )Ng      r         ?r   gư>)r   copysignlogfabsr   sqrt)r   lmbsnrs      r   r   z)betas_for_alpha_bar.<locals>.alpha_bar_fnB   sm    q#'22TXXa!diiPSVWPWFXBX>X[_>_5``C((3-C99SAG_--r   r   c                 2    t        j                  | dz        S )Ng      ()r   r   r   s    r   r   z)betas_for_alpha_bar.<locals>.alpha_bar_fnI   s    88AI&&r   z"Unsupported alpha_transform_type: r   dtype)
ValueErrorrangeappendmintorchtensorfloat32)r   r   r   r   betasit1t2s           r   betas_for_alpha_barr6   #   s    0 x'	D 
	*	.
 
	&	' =>R=STUUE*+((!e..S\"-R0@@@(KL , <<U]]33r   c            0       f   e Zd ZdZeD  cg c]  }|j
                   c}} 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ej                  ee	   z  dz  de
de
dededz  dede	de	deded ed!ed"ed#ed$e	d%e	d&edz  d'ed(e
f.d)       Zed*        Zed+        ZdWd,e
fd-ZdXd.e
d/eej.                  z  fd0Zd1ej2                  d2ej2                  fd3Zd4 Zd5 Zd6ej2                  d2ej2                  fd7Zd6ej2                  d.e
d2ej2                  fd8Z	 dYd6ej2                  d.e
d9e	d:e	d2ej2                  f
d;Zdd<d=ej2                  d1ej2                  d2ej2                  fd>Z d? Z!d@ Z"dA Z#dB Z$d=ej2                  d1ej2                  dCej2                  dDe
dEej2                  d2ej2                  fdFZ%dGej2                  dHej2                  dIej2                  dJej2                  dDe
dEej2                  d2ej2                  fdKZ&	 dZdLe
ej2                  z  dMej2                  dz  d2e
fdNZ'dO Z(	 	 d[d=ej2                  dLe
d1ej2                  dPed2e)e*z  f
dQZ+d1ej2                  d2ej2                  fdRZ,dSej2                  dCej2                  dTejZ                  d2ej2                  fdUZ.dV Z/yc c}} w )\SASolverScheduleru  
    `SASolverScheduler` is a fast dedicated high-order solver for diffusion SDEs.

    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`.
        predictor_order (`int`, defaults to 2):
            The predictor order which can be `1` or `2` or `3` or '4'. It is recommended to use `predictor_order=2` for
            guided sampling, and `predictor_order=3` for unconditional sampling.
        corrector_order (`int`, defaults to 2):
            The corrector order which can be `1` or `2` or `3` or '4'. It is recommended to use `corrector_order=2` for
            guided sampling, and `corrector_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://huggingface.co/papers/2210.02303) paper).
        tau_func (`Callable`, *optional*):
            Stochasticity during the sampling. Default in init is `lambda t: 1 if t >= 200 and t <= 800 else 0`.
            SA-Solver will sample from vanilla diffusion ODE if tau_func is set to `lambda t: 0`. SA-Solver will sample
            from vanilla diffusion SDE if tau_func is set to `lambda t: 1`. For more details, please check
            https://huggingface.co/papers/2309.05019
        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 `data_prediction`):
            Algorithm type for the solver; can be `data_prediction` or `noise_prediction`. It is recommended to use
            `data_prediction` with `solver_order=2` for guided sampling like in Stable Diffusion.
        lower_order_final (`bool`, defaults to `True`):
            Whether to use lower-order solvers in the final steps. Default = True.
        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.
        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.
        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.
    r   i  g-C6?g{Gz?linearNr   epsilonFgףp=
?      ?data_predictionTinflinspacer   num_train_timesteps
beta_startbeta_endbeta_scheduletrained_betaspredictor_ordercorrector_orderprediction_typetau_functhresholdingdynamic_thresholding_ratiosample_max_valuealgorithm_typelower_order_finaluse_karras_sigmasuse_exponential_sigmasuse_beta_sigmasuse_flow_sigmas
flow_shiftlambda_min_clippedvariance_typetimestep_spacingsteps_offsetc                    | j                   j                  rt               st        d      t	        | j                   j                  | j                   j
                  | j                   j                  g      dkD  rt        d      |+t        j                  |t        j                        | _        n|dk(  r-t        j                  |||t        j                        | _        nk|dk(  r6t        j                  |dz  |dz  |t        j                        dz  | _        n0|d	k(  rt        |      | _        nt        | d
| j                         d| j                  z
  | _        t        j"                  | j                   d      | _        t        j&                  | j$                        | _        t        j&                  d| j$                  z
        | _        t        j,                  | j(                        t        j,                  | j*                        z
  | _        d| j$                  z
  | j$                  z  dz  | _        d| _        |dvrt        | d
| j                         d | _        t7        j                  d|dz
  |t6        j                        d d d   j9                         }t        j:                  |      | _        d gt?        ||dz
        z  | _         d gt?        ||dz
        z  | _!        |		d | _"        n|	| _"        |dk(  | _#        d| _$        d | _%        d | _&        d | _'        | j0                  jQ                  d      | _        y )Nz:Make sure to install scipy if you want to use beta sigmas.r   znOnly one of `config.use_beta_sigmas`, `config.use_exponential_sigmas`, `config.use_karras_sigmas` can be used.r)   r9   scaled_linearr!   r   squaredcos_cap_v2z is not implemented for r;   r   dim)r<   noise_predictionc                     | dk\  r| dk  rdS dS )N   i   r   r    r   s    r   <lambda>z,SASolverScheduler.__init__.<locals>.<lambda>   s    18Sa&Ga&Gr   r<   cpu))configrO   r	   ImportErrorsumrN   rM   r+   r/   r0   r1   r2   r>   r6   NotImplementedError	__class__alphascumprodalphas_cumprodr%   alpha_tsigma_tr#   lambda_tsigmasinit_noise_sigmanum_inference_stepsnpcopy
from_numpy	timestepsmaxtimestep_listmodel_outputsrG   
predict_x0lower_order_numslast_sample_step_index_begin_indexto)selfr?   r@   rA   rB   rC   rD   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   rU   rs   s                            r   __init__zSASolverScheduler.__init__   s   6 ;;&&/A/CZ[[++T[[-O-OQUQ\Q\QnQnopstt A  $m5==IDJh&
H>QY^YfYfgDJo- OcM'--	  J 11,-@ADJ%7OPTP^P^O_&`aaDJJ&#mmDKKQ?zz$"5"56zz!d&9&9"9:		$,,/%))DLL2IID///43F3FF3N !$!HH%(88PQUQ_Q_P`&abb $( KK#6#:<OWYWaWabcgegcghmmo	)))4"Vc/?Q;N&OO"Vc/?Q;N&OOGDM$DM(,== ! kknnU+r   c                     | j                   S )zg
        The index counter for current timestep. It will increase 1 after each scheduler step.
        )rz   r}   s    r   
step_indexzSASolverScheduler.step_index   s    
 r   c                     | j                   S )zq
        The index for the first timestep. It should be set from pipeline with `set_begin_index` method.
        r{   r   s    r   begin_indexzSASolverScheduler.begin_index   s    
    r   r   c                     || _         y)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   s     r   set_begin_indexz!SASolverScheduler.set_begin_index  s     (r   ro   devicec           	      ~   t        j                  t        j                  | j                  dg      | j                  j
                        }| j                  j                  |z
  j                         j                         }| j                  j                  dk(  rat        j                  d|dz
  |dz         j                         ddd   dd j                         j                  t        j                        }nD| j                  j                  dk(  r||dz   z  }t        j                   d|dz         |z  j                         ddd   dd j                         j                  t        j                        }|| j                  j"                  z  }n| j                  j                  dk(  rp| j                  j                  |z  }t        j                   |d|       j                         j                         j                  t        j                        }|dz  }n"t%        | j                  j                   d      t        j&                  d| j(                  z
  | j(                  z  d	z        }t        j*                  |      }| j                  j,                  rt        j                  |      j                         }| j/                  ||
      }t        j&                  |D 	cg c]  }	| j1                  |	|       c}	      j                         }t        j2                  ||dd g      j                  t        j4                        }n| j                  j6                  rt        j                  |      j                         }| j9                  ||
      }t        j&                  |D 	cg c]  }	| j1                  |	|       c}	      }t        j2                  ||dd g      j                  t        j4                        }nN| j                  j:                  rt        j                  |      j                         }| j=                  ||
      }t        j&                  |D 	cg c]  }	| j1                  |	|       c}	      }t        j2                  ||dd g      j                  t        j4                        }n| j                  j>                  rt        j                  dd| j                  j                  z  |dz         }
d|
z
  }t        j                  | j                  j@                  |z  d| j                  j@                  dz
  |z  z   z        dd j                         }|| j                  j                  z  j                         }t        j2                  ||dd g      j                  t        j4                        }nt        jB                  |t        j                   dtE        |            |      }d| j(                  d   z
  | j(                  d   z  d	z  }t        j2                  ||gg      j                  t        j4                        }t        jF                  |      | _$        t        jF                  |      jK                  |t         j                        | _&        tE        |      | _'        dgtQ        | j                  jR                  | j                  jT                  dz
        z  | _+        d| _,        d| _-        d| _.        d| _/        | jH                  jK                  d      | _$        yc c}	w c c}	w c c}	w )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.
        r   r>   r   Nr\   leadingtrailingzY is not supported. Please make sure to choose one of 'linspace', 'leading' or 'trailing'.r!   )	in_sigmasro   r;   )r   r*   ra   )0r/   searchsortedfliprl   rb   rR   r?   numpyitemrT   rp   r>   roundrq   astypeint64arangerU   r+   arrayri   r#   rM   _convert_to_karras_sigma_to_tconcatenater1   rN   _convert_to_exponentialrO   _convert_to_betarP   rQ   interplenrr   rm   r|   rs   ro   rt   rD   rE   rv   rx   ry   rz   r{   )r}   ro   r   clipped_idxlast_timesteprs   
step_ratiorm   
log_sigmassigmarg   
sigma_lasts               r   set_timestepszSASolverScheduler.set_timesteps  s    ((DMMA3)GIgIgh++99KGNNPVVX ;;'':5A}q02E2IJPPRSWUWSWXY\Z\]bbdkklnltltu  [[))Y6&+>+BCJ 1&9A&=>KRRTUYWYUYZ[^\^_ddfmmnpnvnvwI111I[[))Z788;NNJ 		-ZK@FFHMMOVVWYW_W_`INI;;//0  1J  K  A 3 33t7J7JJsRSVVF^
;;((WWV_))+F,,vSf,gFSY!ZSY%$"2"25*"ESY!Z[aacI^^VVBC[$9:AA"**MF[[//WWV_))+F11FXk1lFSY!ZSY%$"2"25*"ESY!Z[I^^VVBC[$9:AA"**MF[[((WWV_))+F**VQd*eFSY!ZSY%$"2"25*"ESY!Z[I^^VVBC[$9:AA"**MF[[(([[A(G(G$GI\_`I`aF6\FWWT[[33f<T[[E[E[^_E_ciDi@ijklomopuuwF$++"A"AAGGII^^VVBC[$9:AA"**MFYYy"))As6{*CVLFt221559L9LQ9OOTWWJ^^Vj\$:;BB2::NF&&v.)))477vU[[7Y#&y> 
++T[[-H-H1-LMN !"   kknnU+I "[
 "[
 "[s   #\0)\5!\:sampler   c                 b   |j                   }|j                  ^}}}|t        j                  t        j                  fvr|j                         }|j                  ||t        j                  |      z        }|j                         }t        j                  || j                  j                  d      }t        j                  |d| j                  j                        }|j                  d      }t        j                  || |      |z  } |j                  ||g| }|j!                  |      }|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   rY   )r.   rt   )r*   shaper/   r1   float64floatreshaperp   prodabsquantilerb   rI   clamprJ   	unsqueezer|   )r}   r   r*   
batch_sizechannelsremaining_dims
abs_sampless           r   _threshold_samplez#SASolverScheduler._threshold_sample_  s    ( 06-
H~66\\^F 
Hrww~7N,NOZZ\
NN:t{{'M'MSTUKK1$++66
 KKNVaR+a/
HF~F5!r   c                    t        j                  t        j                  |d            }||ddt         j                  f   z
  }t        j                  |dk\  d      j                  d      j                  |j                  d   dz
        }|dz   }||   }||   }||z
  ||z
  z  }	t        j                  |	dd      }	d|	z
  |z  |	|z  z   }
|
j                  |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   )rt   r   )	rp   r#   maximumnewaxiscumsumargmaxclipr   r   )r}   r   r   	log_sigmadistslow_idxhigh_idxlowhighwr   s              r   r   zSASolverScheduler._sigma_to_t  s     FF2::eU34	 Jq"**}55 ))UaZq188a8@EE*JZJZ[\J]`aJaEbQ;!(# 9_t,GGAq! UgH,IIekk"r   c                 r    | j                   j                  rd|z
  }|}||fS d|dz  dz   dz  z  }||z  }||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!   )rb   rP   )r}   r   rj   rk   s       r   _sigma_to_alpha_sigma_tz)SASolverScheduler._sigma_to_alpha_sigma_t  sY     ;;&&%iGG
  E1HqLS01GgoGr   r   c                    t        | j                  d      r| j                  j                  }nd}t        | j                  d      r| j                  j                  }nd}||n|d   j	                         }||n|d   j	                         }d}t        j                  dd|      }|d|z  z  }|d|z  z  }||||z
  z  z   |z  }	|	S )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.
        	sigma_minN	sigma_maxr\   r   g      @r   )hasattrrb   r   r   r   rp   r>   )
r}   r   ro   r   r   rhorampmin_inv_rhomax_inv_rhorm   s
             r   r   z$SASolverScheduler._convert_to_karras  s    $ 4;;,--II4;;,--II!*!6IIbM<N<N<P	!*!6IIaL<M<M<O	{{1a!45AG,AG,k(A BBsJr   c                    t        | j                  d      r| j                  j                  }nd}t        | j                  d      r| j                  j                  }nd}||n|d   j	                         }||n|d   j	                         }t        j                  t        j                  t        j                  |      t        j                  |      |            }|S )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   r\   r   )
r   rb   r   r   r   rp   r   r>   r   r#   )r}   r   ro   r   r   rm   s         r   r   z)SASolverScheduler._convert_to_exponential  s    " 4;;,--II4;;,--II!*!6IIbM<N<N<P	!*!6IIaL<M<M<O	DHHY$7)9LNabcr   alphabetac           
      (   t        | j                  d      r| j                  j                  }nd}t        | j                  d      r| j                  j                  }nd}||n|d   j	                         }||n|d   j	                         }t        j                  dt        j                  dd|      z
  D cg c]-  }t        j                  j                  j                  |||      / c}D cg c]  }||||z
  z  z    c}      }	|	S c c}w c c}w )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   r\   r   r   )r   rb   r   r   r   rp   r   r>   scipystatsr   ppf)
r}   r   ro   r   r   r   r   timestepr   rm   s
             r   r   z"SASolverScheduler._convert_to_beta  s   0 4;;,--II4;;,--II!*!6IIbM<N<N<P	!*!6IIaL<M<M<O	
 %&Aq:M(N$N$N KK$$((5$?$NC SI	$9:;
 s   82D
/Dr   model_outputc                   t        |      dkD  r|d   n|j                  dd      }|t        |      dkD  r|d   }nt        d      |t        ddd       | j                  | j
                     }| j                  |      \  }}| j                  j                  d	v r| j                  j                  d
k(  r/| j                  j                  dv r|ddddf   }|||z  z
  |z  }	n| j                  j                  dk(  r|}	n| j                  j                  dk(  r||z  ||z  z
  }	n^| j                  j                  dk(  r"| j                  | j
                     }|||z  z
  }	n#t        d| j                  j                   d      | j                  j                  r| j                  |	      }	|	S | j                  j                  dv r
| j                  j                  d
k(  r'| j                  j                  dv r|ddddf   }
np|}
nm| j                  j                  dk(  r|||z  z
  |z  }
nH| j                  j                  dk(  r||z  ||z  z   }
n#t        d| j                  j                   d      | j                  j                  rE| j                  |   | j                  |   }}|||
z  z
  |z  }	| j                  |	      }	|||	z  z
  |z  }
|
S y)a=  
        Convert the model output to the corresponding type the data_prediction/noise_prediction algorithm needs.
        Noise_prediction is designed to discretize an integral of the noise prediction model, and data_prediction is
        designed to discretize an integral of the data prediction model.

        > [!TIP] > The algorithm and model type are decoupled. You can use either data_prediction or noise_prediction
        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 argumentrs   1.0.0zPassing `timesteps` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`)r<   r:   )learnedlearned_range   r   v_predictionflow_predictionzprediction_type given as zd must be one of `epsilon`, `sample`, `v_prediction`, or `flow_prediction` for the SASolverScheduler.)r[   zQ must be one of `epsilon`, `sample`, or `v_prediction` for the SASolverScheduler.)r   popr+   r   rm   r   r   rb   rK   rF   rS   rH   r   rj   rk   )r}   r   r   argskwargsr   r   rj   rk   x0_predr:   s              r   convert_model_outputz&SASolverScheduler.convert_model_output?  s   2 "$i!m47J1M>4y1}a !RSS Z DOO,77>;;%%)<<{{**i7;;,,0LL#/2A2#6L!Gl$::gE,,8&,,>!F*W|-CC,,0AA++doo6 7\#99 /0K0K/L MV V 
 {{''009N [[''+??{{**i7;;,,0LL*1bqb51G*G,,8!Gl$::gE,,>!L07V3CC /0K0K/L MA A 
 {{''#'<<#94<<;Q!Gg$55@009!Gg$55@N/ @r   c                 t   |dv sJ d       |dk(  r2t        j                  |       t        j                  ||z
        dz
  z  S |dk(  r;t        j                  |       |dz   t        j                  ||z
        z  |dz   z
  z  S |dk(  rMt        j                  |       |dz  d|z  z   dz   t        j                  ||z
        z  |dz  d|z  z   dz   z
  z  S |dk(  r_t        j                  |       |dz  d|dz  z  z   d|z  z   dz   t        j                  ||z
        z  |dz  d|dz  z  z   d|z  z   dz   z
  z  S y)	zd
        Calculate the integral of exp(-x) * x^order dx from interval_start to interval_end
        r   r   r   r   )order is only supported for 0, 1, 2 and 3r   r   r   r      Nr/   r   )r}   orderinterval_startinterval_ends       r   %get_coefficients_exponential_negativez7SASolverScheduler.get_coefficients_exponential_negative  s    $Q&QQ$A:99l]+uyy9V/WZ[/[\\aZ99l]+!#uyy1N'OOS_bcScd  aZ99l]+"Q%77!;uyyXfIf?gg?Q%559;  aZ99l]+"Q):%::Q=OORSS))L>9:;?Qq%881|;KKaOQ  r   c                    |dv sJ d       d|dz  z   |z  }d|dz  z   |z  }|dk(  r;t        j                  |      dt        j                  ||z
         z
  z  d|dz  z   z  S |dk(  rGt        j                  |      |dz
  |dz
  t        j                  ||z
         z  z
  z  d|dz  z   dz  z  S |dk(  rYt        j                  |      |dz  d|z  z
  dz   |dz  d|z  z
  dz   t        j                  ||z
         z  z
  z  d|dz  z   dz  z  S |dk(  rkt        j                  |      |dz  d|dz  z  z
  d|z  z   dz
  |dz  d|dz  z  z
  d|z  z   dz
  t        j                  ||z
         z  z
  z  d|dz  z   dz  z  S y	)
zl
        Calculate the integral of exp(x(1+tau^2)) * x^order dx from interval_start to interval_end
        r   r   r   r   r   r   r      Nr   )r}   r   r   r   tauinterval_end_covinterval_start_covs          r   %get_coefficients_exponential_positivez7SASolverScheduler.get_coefficients_exponential_positive  s&    $Q&QQ$ QJ,6#q&jN:A:		*+q599?ORd?d=e3f/fgklortuoukuv aZ		*+%))A-=MPb=b;c1dde
 QJ1$& aZ		*+%q(1/?+??!C)1,q3E/EEIii"25G"G HIJJ QJ1$& aZ		*+%q(1/?/B+BBQIYEYY\]])1,q3Eq3H/HH1OaKaadeeii"25G"G HIJJ QJ1$& r   c           	         |dv sJ |t        |      dz
  k(  sJ |dk(  rdggS |dk(  r@d|d   |d   z
  z  |d    |d   |d   z
  z  gd|d   |d   z
  z  |d    |d   |d   z
  z  ggS |dk(  r|d   |d   z
  |d   |d   z
  z  }|d   |d   z
  |d   |d   z
  z  }|d   |d   z
  |d   |d   z
  z  }d|z  |d    |d   z
  |z  |d   |d   z  |z  gd|z  |d    |d   z
  |z  |d   |d   z  |z  gd|z  |d    |d   z
  |z  |d   |d   z  |z  ggS |dk(  r|d   |d   z
  |d   |d   z
  z  |d   |d   z
  z  }|d   |d   z
  |d   |d   z
  z  |d   |d   z
  z  }|d   |d   z
  |d   |d   z
  z  |d   |d   z
  z  }|d   |d   z
  |d   |d   z
  z  |d   |d   z
  z  }d|z  |d    |d   z
  |d   z
  |z  |d   |d   z  |d   |d   z  z   |d   |d   z  z   |z  |d    |d   z  |d   z  |z  gd|z  |d    |d   z
  |d   z
  |z  |d   |d   z  |d   |d   z  z   |d   |d   z  z   |z  |d    |d   z  |d   z  |z  gd|z  |d    |d   z
  |d   z
  |z  |d   |d   z  |d   |d   z  z   |d   |d   z  z   |z  |d    |d   z  |d   z  |z  gd|z  |d    |d   z
  |d   z
  |z  |d   |d   z  |d   |d   z  z   |d   |d   z  z   |z  |d    |d   z  |d   z  |z  ggS y)zB
        Calculate the coefficient of lagrange polynomial
        r   r   r   r   r   N)r   )r}   r   lambda_listdenominator1denominator2denominator3denominator4s          r   lagrange_polynomial_coefficientz1SASolverScheduler.lagrange_polynomial_coefficient  sa   
 $$$K(1,,,,A:C5LaZ Q+a.89 ^O{1~A'FG
 Q+a.89 ^O{1~A'FG	 	 aZ'N[^;AQ\]^Q_@_`L'N[^;AQ\]^Q_@_`L'N[^;AQ\]^Q_@_`L $!!n_{1~5EN[^3lB $!!n_{1~5EN[^3lB $!!n_{1~5EN[^3lB " aZQ+a.0q>KN24q>KN24  Q+a.0q>KN24q>KN24  Q+a.0q>KN24q>KN24  Q+a.0q>KN24q>KN24  $!!n_{1~5AF,V#AQ7%a.;q>9:%a.;q>9: ## "!n_{1~5AF,V
 $!!n_{1~5AF,V#AQ7%a.;q>9:%a.;q>9: ## "!n_{1~5AF,V
 $!!n_{1~5AF,V#AQ7%a.;q>9:%a.;q>9: ## "!n_{1~5AF,V
 $!!n_{1~5AF,V#AQ7%a.;q>9:%a.;q>9: ## "!n_{1~5AF,V
E- -+ r   c           
         |dv sJ |t        |      k(  sJ d       g }| j                  |dz
  |      }t        |      D ]}  }d}	t        |      D ]Z  }
| j                  r'|	||   |
   | j	                  |dz
  |
z
  |||      z  z  }	6|	||   |
   | j                  |dz
  |
z
  ||      z  z  }	\ |j                  |	        t        |      |k(  sJ d       |S )N)r   r   r   r   z4the length of lambda list must be equal to the orderr   r   z3the length of coefficients does not match the order)r   r   r,   rw   r   r   r-   )r}   r   r   r   r   r   coefficientslagrange_coefficientr3   coefficientjs              r   get_coefficients_fnz%SASolverScheduler.get_coefficients_fnK  s   $$$K((`*``(#CCEAI{[uAK5\??#7#:1#=@j@j	A~|SA $ K  #7#:1#=@j@j	A~|A $ K " ,  < E)`+``)r   noiser   r   c                	   t        |      dkD  r|d   n|j                  dd      }|t        |      dkD  r|d   }nt        d      |t        |      dkD  r|d   }nt        d      |t        |      dkD  r|d   }nt        d	      |t        |      d
kD  r|d
   }nt        d      |t        ddd       | j                  }	| j
                  | j                  dz      | j
                  | j                     }}
| j                  |
      \  }}
| j                  |      \  }}t        j                  |      t        j                  |
      z
  }t        j                  |      t        j                  |      z
  }t        j                  |      }||z
  }g }t        |      D ]n  }| j                  |z
  }| j                  | j
                  |         \  }}t        j                  |      t        j                  |      z
  }|j                  |       p | j                  |||||      }|}| j                  rM|dk(  rG| j
                  | j                  dz
     }| j                  |      \  }}t        j                  |      t        j                  |      z
  }|dxx   dt        j                  d|dz  z   |z        z  |dz  dz  |d|dz  z   z  dz
  t        j                  d|dz  z   | z        z   d|dz  z   dz  z  z
  z  ||z
  z  z  cc<   |dxx   dt        j                  d|dz  z   |z        z  |dz  dz  |d|dz  z   z  dz
  t        j                  d|dz  z   | z        z   d|dz  z   dz  z  z
  z  ||z
  z  z  cc<   t        |      D ]i  }| j                  r<|d|dz  z   |
z  t        j                  |dz   |z        z  ||   z  |	|dz       z  z  }K|d|dz  z    |z  ||   z  |	|dz       z  z  }k | j                  r;|
t        j                   dt        j                  d|dz  z  |z        z
        z  |z  }n7||
z  t        j                   t        j                  d|z        dz
        z  |z  }| j                  r,t        j                  |dz   |z        |
|z  z  |z  |z   |z   }n||z  |z  |z   |z   }|j#                  |j$                        }|S )ag  
        One step for the SA-Predictor.

        Args:
            model_output (`torch.Tensor`):
                The direct output from the learned diffusion model at the current timestep.
            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.
            order (`int`):
                The order of SA-Predictor at this timestep.

        Returns:
            `torch.Tensor`:
                The sample tensor at the previous timestep.
        r   prev_timestepNr   r   r   z.missing `noise` as a required keyword argumentr   .missing `order` as a required keyword argumentr   ,missing `tau` as a required keyword argumentr   zPassing `prev_timestep` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`r;   r   r   r+   r   rv   rm   r   r   r/   r#   
zeros_liker,   r-   r   rw   r   r%   r|   r*   ) r}   r   r   r   r   r   r   r   r  model_output_listrk   sigma_s0rj   alpha_s0rl   	lambda_s0gradient_parthr   r3   sialpha_sisigma_si	lambda_sigradient_coefficientsx
temp_sigmatemp_alpha_stemp_sigma_stemp_lambda_s
noise_partx_ts                                    r   !stochastic_adams_bashforth_updatez3SASolverScheduler.stochastic_adams_bashforth_update_  s/   6 $'t9q=QfjjRV6W>4y1}a !RSS=4y1}Q !QRR=4y1}Q !QRR;4y1}1g !OPP$ ^
 !..KK!+,KK(   77@!99(C(99W%		'(::IIh'%))H*==	((0y uA1$B!%!=!=dkk"o!NHh		(+eii.AAIy)	  !% 8 8	8U`be f??
 "[[1)<=
-1-I-I*-U*l %		, 7%))L:Q Q%a(iiS!Vx 789!tax1CF
#3a#7%))QaZUVTVDW:X#X^_beghbh^hmn]n"ooq !=02( &a(iiS!Vx 789!tax1CF
#3a#7%))QaZUVTVDW:X#X^_beghbh^hmn]n"ooq !=02( uAaZii#q&	H 456 ,A./ (!a%1	2 1sAv:!8;PQR;S!SVgjknojohpVq!qq  ?? 5::a%))BaK!O2L.L#MMPUUJwEIIa!e4Dq4H)IIEQJ??))c1fIM*g.@AAEUXbbCX%*]:ZGCffQWWo
r   this_model_outputry   
last_noisethis_samplec                .	   t        |      dkD  r|d   n|j                  dd      }	|t        |      dkD  r|d   }nt        d      |t        |      dkD  r|d   }nt        d      |t        |      dkD  r|d   }nt        d	      |t        |      d
kD  r|d
   }nt        d      |t        |      dkD  r|d   }nt        d      |	t        ddd       | j                  }
| j
                  | j                     | j
                  | j                  dz
     }}| j                  |      \  }}| j                  |      \  }}t        j                  |      t        j                  |      z
  }t        j                  |      t        j                  |      z
  }t        j                  |      }||z
  }g }t        |      D ]n  }| j                  |z
  }| j                  | j
                  |         \  }}t        j                  |      t        j                  |      z
  }|j                  |       p |
|gz   }| j                  |||||      }|}| j                  r|dk(  r|dxx   dt        j                  d|dz  z   |z        z  |dz  |d|dz  z   z  dz
  t        j                  d|dz  z   | z        z   d|dz  z   dz  |z  z  z
  z  z  cc<   |dxx   dt        j                  d|dz  z   |z        z  |dz  |d|dz  z   z  dz
  t        j                  d|dz  z   | z        z   d|dz  z   dz  |z  z  z
  z  z  cc<   t        |      D ]i  }| j                  r<|d|dz  z   |z  t        j                  |dz   |z        z  ||   z  ||dz       z  z  }K|d|dz  z    |z  ||   z  ||dz       z  z  }k | j                  r;|t        j                   dt        j                  d|dz  z  |z        z
        z  |z  }n7||z  t        j                   t        j                  d|z        dz
        z  |z  }| j                  r,t        j                  |dz   |z        ||z  z  |z  |z   |z   }n||z  |z  |z   |z   }|j#                  |j$                        }|S )a  
        One step for the SA-Corrector.

        Args:
            this_model_output (`torch.Tensor`):
                The model outputs at `x_t`.
            this_timestep (`int`):
                The current timestep `t`.
            last_sample (`torch.Tensor`):
                The generated sample before the last predictor `x_{t-1}`.
            this_sample (`torch.Tensor`):
                The generated sample after the last predictor `x_{t}`.
            order (`int`):
                The order of SA-Corrector at this step.

        Returns:
            `torch.Tensor`:
                The corrected sample tensor at the current timestep.
        r   this_timestepNr   z4missing `last_sample` as a required keyword argumentr   z3missing `last_noise` as a required keyword argumentr   z4missing `this_sample` as a required keyword argumentr   r     r  r   zPassing `this_timestep` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`r;   r  r  )r}   r  ry   r  r  r   r   r   r   r  r  rk   r  rj   r	  rl   r
  r  r  r   r3   r  r  r  r  model_prev_listr  r  r  r  s                                 r   stochastic_adams_moulton_updatez1SASolverScheduler.stochastic_adams_moulton_update  s   > $'t9q=QfjjRV6W4y1}"1g !WXX4y1}!!W
 !VWW4y1}"1g !WXX=4y1}Q !QRR;4y1}1g !OPP$ ^ !..KK(KK!+,   77@!99(C(99W%		'(::IIh'%))H*==	((5y uA1$B!%!=!=dkk"o!NHh		(+eii.AAIy)	  ,/@.AA $ 8 8	8U`be f??
 &a(iiS!Vx 7891uQaZ 01 4uyy!c1f*RSQSAT7U U[\_bde_e[ejkZknoZoppr(
 &a(iiS!Vx 7891uQaZ 01 4uyy!c1f*RSQSAT7U U[\_bde_e[ejkZknoZoppr( uAaZii#q&	H 456 ,A./ &Ah/	0 1sAv:!8;PQR;S!SVehilmhmfnVo!oo  ?? 5::a%))BaK!O2L.L#MMPZZJwEIIa!e4Dq4H)IIJVJ??))c1fIM*g.@AAEUXbbCX%*]:ZGCffQWWo
r   r   schedule_timestepsc                    || j                   }||k(  j                         }t        |      dk(  rt        | j                         dz
  }|S t        |      dkD  r|d   j                         }|S |d   j                         }|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.
        r   r   )rs   nonzeror   r   )r}   r   r"  index_candidatesr   s        r   index_for_timestepz$SASolverScheduler.index_for_timestepd  s    $ %!%.(:CCE A%T^^,q0J  !"Q&)!,113J  *!,113Jr   c                     | j                   Vt        |t        j                        r%|j	                  | j
                  j                        }| j                  |      | _        y| j                  | _        y)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|   rs   r   r&  rz   r{   )r}   r   s     r   _init_step_indexz"SASolverScheduler._init_step_index  sW     #(ELL1#;;t~~'<'<=#66x@D#00Dr   return_dictc                    | j                   t        d      | j                  | j                  |       | j                  dkD  xr | j                  du}| j                  ||      }|rS| j                  | j                  d         }| j                  || j                  | j                  || j                  |      }t        t        | j                  j                  | j                  j                  dz
        dz
        D ]@  }	| j                   |	dz      | j                   |	<   | j                  |	dz      | j                  |	<   B || j                   d<   || j                  d<   t#        |j$                  ||j&                  |j(                        }
| j                  j*                  rt-        | j                  j                  t/        | j0                        | j                  z
        }t-        | j                  j                  t/        | j0                        | j                  z
  dz         }n,| j                  j                  }| j                  j                  }t-        || j2                  dz         | _        t-        || j2                  d	z         | _
        | j4                  dkD  sJ | j                  dkD  sJ || _        |
| _	        | j                  | j                  d         }| j7                  |||
| j4                  |
      }| j2                  t        | j                  j                  | j                  j                  dz
        k  r| xj2                  dz  c_        | xj8                  dz  c_        |s|fS t;        |      S )a  
        Predict the sample from the previous timestep by reversing the SDE. This function propagates the sample with
        the SA-Solver.

        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.
            generator (`torch.Generator`, *optional*):
                A random number generator.
            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\   )r  ry   r  r  r   r   r   )	generatorr   r*   r   )r   r   r   r   r   )prev_sample)ro   r+   r   r*  ry   r   rG   ru   r!  r  this_corrector_orderr,   rt   rb   rD   rE   rv   r
   r   r   r*   rL   r.   r   rs   rx   this_predictor_orderr  rz   r   )r}   r   r   r   r-  r+  use_correctormodel_output_convertcurrent_taur3   r   r0  r/  r.  s                 r   stepzSASolverScheduler.step  s,   < ##+s  ??"!!(+!+L0@0@0L#88f8U--(:(:2(>?K99"6 ,,??"// : F s4;;668S8SVW8WX[\\]A$($6$6q1u$=Dq!$($6$6q1u$=Dq! ^ "62!)2&&$$	
 ;;((#&t{{'B'BCDWZ^ZiZiDi#j #&t{{'B'BCDWZ^ZiZiDilmDm#n #';;#>#> #';;#>#> $'(<d>S>SVW>W$X!$'(<d>S>SVW>W$X!((1,,,((1,,,!mmD$6$6r$:;<<-++ = 
   3t{{'B'BDKKD_D_bcDc#dd!!Q&! 	A>!;77r   c                     |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}   r   r   r   s       r   scale_model_inputz#SASolverScheduler.scale_model_input  s	     r   original_samplesrs   c                    | j                   j                  |j                        | _         | j                   j                  |j                        }|j                  |j                        }||   dz  }|j	                         }t        |j                        t        |j                        k  r=|j                  d      }t        |j                        t        |j                        k  r=d||   z
  dz  }|j	                         }t        |j                        t        |j                        k  r=|j                  d      }t        |j                        t        |j                        k  r=||z  ||z  z   }|S )a2  
        Add noise to the original samples according to the noise magnitude at each timestep (this is the forward
        diffusion process).

        Args:
            original_samples (`torch.Tensor`):
                The original samples to which noise will be added.
            noise (`torch.Tensor`):
                The noise to add to the samples.
            timesteps (`torch.IntTensor`):
                The timesteps indicating the noise level for each sample.

        Returns:
            `torch.Tensor`:
                The noisy samples.
        )r   r)   r!   r\   r   )ri   r|   r   r*   flattenr   r   r   )r}   r7  r   rs   ri   sqrt_alpha_prodsqrt_one_minus_alpha_prodnoisy_sampless           r   	add_noisezSASolverScheduler.add_noise  sa   2 #1144<L<S<S4T,,//6F6L6L/MLL!1!8!89	(3s:)113/''(3/?/E/E+FF-77;O /''(3/?/E/E+FF &'	)B%Bs$J!$=$E$E$G!+112S9I9O9O5PP(A(K(KB(O% +112S9I9O9O5PP (*::=VY^=^^r   c                 .    | j                   j                  S N)rb   r?   r   s    r   __len__zSASolverScheduler.__len__9  s    {{...r   )r   )NN)333333?rA  r?  )NT)0__name__
__module____qualname____doc__r   name_compatiblesr   r   r   intstrrp   ndarraylistr   boolr~   propertyr   r   r   r/   r   r   r)  r   r   r   r   r   r   r   r   r   r   r   r  r!  r&  r*  r   tupler4  r6  	IntTensorr=  r@  ).0es   00r   r8   r8   W   s   AF %>>$=qAFF$=>LE $("%9=  ($(",1"%/"&"'', % %%*5\M$( *1S, S, S, 	S,
 S, zzDK/$6S, S, S, S, T/S, S, %*S,  S, S,  S,   !S," !%#S,$ %S,& 'S,( )S,* "+S,, Tz-S,. /S,0 1S, S,j     ! !(3 (O, O,S5<<EW O,d) ) )X"J ,$ELL $RWR^R^ $N TW \a\h\h F dg..<?.HM.[`.	.h  $	YllY 	Y 
Yv0*XkZ(}ll} 	}
 ||} } \\} 
}~C <<C \\	C
 LLC \\C C \\C 
CR 37"$" "LL4/" 
	"J1*  d8lld8 d8 	d8 d8 
5	 d8L %,,  (,,( ||( ??	(
 
(T/}$ ?s   J-r8   )g+?r   )r   typingr   r   r   rp   r/   configuration_utilsr   r   utilsr   r	   utils.torch_utilsr
   scheduling_utilsr   r   r   scipy.statsr   rH  r   r)  r6   r8   r_   r   r   <module>rX     sy   $  $   A 1 , X X  @H14 1414 ""<=14 \\	14hc/ c/r   