a
    Aþd”  ã                   @   sR   d dl Z d dlZd dlZG dd„ dƒZddd„ZG d	d
„ d
ƒZdd„ Zdd„ ZdS )é    Nc                   @   s>   e Zd Zddd„Zdd„ Zd	d
„ Zdd„ Zdd„ Zdd„ ZdS )ÚNoiseScheduleVPÚdiscreteNçš™™™™™¹?ç      4@c                 C   sF  |dvrt d|› dƒ‚|| _|dkr¦|durJdt d| ¡jdd	 }n|dusVJ ‚dt |¡ }t|ƒ| _d
| _t dd
| jd ¡dd…  	d¡| _
| 	d¡| _nœd| _|| _|| _d| _d| _t | jd
| j  tj ¡d d
| j  tj | j | _t t | jd
| j  tj d ¡¡| _|| _|dkr<d| _nd
| _dS )aH  Create a wrapper class for the forward SDE (VP type).

        ***
        Update: We support discrete-time diffusion models by implementing a picewise linear interpolation for log_alpha_t.
                We recommend to use schedule='discrete' for the discrete-time diffusion models, especially for high-resolution images.
        ***

        The forward SDE ensures that the condition distribution q_{t|0}(x_t | x_0) = N ( alpha_t * x_0, sigma_t^2 * I ).
        We further define lambda_t = log(alpha_t) - log(sigma_t), which is the half-logSNR (described in the DPM-Solver paper).
        Therefore, we implement the functions for computing alpha_t, sigma_t and lambda_t. For t in [0, T], we have:

            log_alpha_t = self.marginal_log_mean_coeff(t)
            sigma_t = self.marginal_std(t)
            lambda_t = self.marginal_lambda(t)

        Moreover, as lambda(t) is an invertible function, we also support its inverse function:

            t = self.inverse_lambda(lambda_t)

        ===============================================================

        We support both discrete-time DPMs (trained on n = 0, 1, ..., N-1) and continuous-time DPMs (trained on t in [t_0, T]).

        1. For discrete-time DPMs:

            For discrete-time DPMs trained on n = 0, 1, ..., N-1, we convert the discrete steps to continuous time steps by:
                t_i = (i + 1) / N
            e.g. for N = 1000, we have t_0 = 1e-3 and T = t_{N-1} = 1.
            We solve the corresponding diffusion ODE from time T = 1 to time t_0 = 1e-3.

            Args:
                betas: A `torch.Tensor`. The beta array for the discrete-time DPM. (See the original DDPM paper for details)
                alphas_cumprod: A `torch.Tensor`. The cumprod alphas for the discrete-time DPM. (See the original DDPM paper for details)

            Note that we always have alphas_cumprod = cumprod(betas). Therefore, we only need to set one of `betas` and `alphas_cumprod`.

            **Important**:  Please pay special attention for the args for `alphas_cumprod`:
                The `alphas_cumprod` is the \hat{alpha_n} arrays in the notations of DDPM. Specifically, DDPMs assume that
                    q_{t_n | 0}(x_{t_n} | x_0) = N ( \sqrt{\hat{alpha_n}} * x_0, (1 - \hat{alpha_n}) * I ).
                Therefore, the notation \hat{alpha_n} is different from the notation alpha_t in DPM-Solver. In fact, we have
                    alpha_{t_n} = \sqrt{\hat{alpha_n}},
                and
                    log(alpha_{t_n}) = 0.5 * log(\hat{alpha_n}).


        2. For continuous-time DPMs:

            We support two types of VPSDEs: linear (DDPM) and cosine (improved-DDPM). The hyperparameters for the noise
            schedule are the default settings in DDPM and improved-DDPM:

            Args:
                beta_min: A `float` number. The smallest beta for the linear schedule.
                beta_max: A `float` number. The largest beta for the linear schedule.
                cosine_s: A `float` number. The hyperparameter in the cosine schedule.
                cosine_beta_max: A `float` number. The hyperparameter in the cosine schedule.
                T: A `float` number. The ending time of the forward process.

        ===============================================================

        Args:
            schedule: A `str`. The noise schedule of the forward SDE. 'discrete' for discrete-time DPMs,
                    'linear' or 'cosine' for continuous-time DPMs.
        Returns:
            A wrapper object of the forward SDE (VP type).

        ===============================================================

        Example:

        # For discrete-time DPMs, given betas (the beta array for n = 0, 1, ..., N - 1):
        >>> ns = NoiseScheduleVP('discrete', betas=betas)

        # For discrete-time DPMs, given alphas_cumprod (the \hat{alpha_n} array for n = 0, 1, ..., N - 1):
        >>> ns = NoiseScheduleVP('discrete', alphas_cumprod=alphas_cumprod)

        # For continuous-time DPMs (VPSDE), linear schedule:
        >>> ns = NoiseScheduleVP('linear', continuous_beta_0=0.1, continuous_beta_1=20.)

        )r   ÚlinearÚcosinezUnsupported noise schedule z=. The schedule needs to be 'discrete' or 'linear' or 'cosine'r   Nç      à?é   r   ©Údimç      ð?g        )r	   éÿÿÿÿiè  gü©ñÒMb€?g     8@ç       @r   gO@aÃÓï?)Ú
ValueErrorÚscheduleÚtorchÚlogÚcumsumÚlenÚtotal_NÚTÚlinspaceÚreshapeÚt_arrayÚlog_alpha_arrayÚbeta_0Úbeta_1Úcosine_sZcosine_beta_maxÚmathÚatanÚpiZcosine_t_maxÚcosÚcosine_log_alpha_0)Úselfr   ÚbetasÚalphas_cumprodZcontinuous_beta_0Zcontinuous_beta_1Z
log_alphas© r&   úN/var/www/html/stable-diffusion-webui/modules/models/diffusion/uni_pc/uni_pc.pyÚ__init__   s.    X
$8(
zNoiseScheduleVP.__init__c                    s’   ˆ j dkr6t| d¡ˆ j |j¡ˆ j |j¡ƒ d¡S ˆ j dkrfd|d  ˆ jˆ j  d| ˆ j  S ˆ j dkrŽ‡ fd	d
„}||ƒˆ j	 }|S dS )zT
        Compute log(alpha_t) of a given continuous-time label t in [0, T].
        r   ©r   r	   r   r   g      Ð¿é   r   r   c                    s*   t  t  | ˆ j dˆ j  tj d ¡¡S )Nr   r   )r   r   r!   r   r   r    )Ús©r#   r&   r'   Ú<lambda>†   ó    z9NoiseScheduleVP.marginal_log_mean_coeff.<locals>.<lambda>N)
r   Úinterpolate_fnr   r   ÚtoÚdevicer   r   r   r"   )r#   ÚtZlog_alpha_fnÚlog_alpha_tr&   r,   r'   Úmarginal_log_mean_coeff}   s    
,
&
z'NoiseScheduleVP.marginal_log_mean_coeffc                 C   s   t  |  |¡¡S )zO
        Compute alpha_t of a given continuous-time label t in [0, T].
        )r   Úexpr4   ©r#   r2   r&   r&   r'   Úmarginal_alphaŠ   s    zNoiseScheduleVP.marginal_alphac              	   C   s   t  dt  d|  |¡ ¡ ¡S )zO
        Compute sigma_t of a given continuous-time label t in [0, T].
        r   r   )r   Úsqrtr5   r4   r6   r&   r&   r'   Úmarginal_std   s    zNoiseScheduleVP.marginal_stdc                 C   s.   |   |¡}dt dt d| ¡ ¡ }|| S )zn
        Compute lambda_t = log(alpha_t) - log(sigma_t) of a given continuous-time label t in [0, T].
        r   r   r   )r4   r   r   r5   )r#   r2   Zlog_mean_coeffZlog_stdr&   r&   r'   Úmarginal_lambda–   s    
zNoiseScheduleVP.marginal_lambdac                    s  ˆ j dkrddˆ jˆ j  t d| t d¡ |¡¡ }ˆ jd | }|t |¡ˆ j  ˆ jˆ j  S ˆ j dkrÔdt t d¡ |j¡d| ¡ }t	| 
d¡t ˆ j |j¡d	g¡t ˆ j |j¡d	g¡ƒ}| 
d
¡S dt d| t d¡ |¡¡ }‡ fdd„}||ƒ}|S dS )z`
        Compute the continuous-time label t in [0, T] of a given half-logSNR lambda_t.
        r   r   g       À)r	   r*   r   g      à¿r)   r	   ©r   c                    s0   t  t  | ˆ j ¡¡d dˆ j  tj ˆ j S )Nr   r   )r   Úarccosr5   r"   r   r   r    )r3   r,   r&   r'   r-   ¬   r.   z0NoiseScheduleVP.inverse_lambda.<locals>.<lambda>N)r   r   r   r   Ú	logaddexpÚzerosr0   r8   r1   r/   r   Úflipr   r   )r#   ÚlambÚtmpÚDeltaZ	log_alphar2   Út_fnr&   r,   r'   Úinverse_lambdaž   s    
, 
":
 zNoiseScheduleVP.inverse_lambda)r   NNr   r   )	Ú__name__Ú
__module__Ú__qualname__r(   r4   r7   r9   r:   rD   r&   r&   r&   r'   r      s        ú
vr   ÚnoiseÚuncondr   c           	         st   ˆpi ‰ˆpi ‰‡
fdd„‰d‡‡‡‡‡
fdd„	‰	‡ ‡fdd„‰‡ ‡‡‡‡‡	‡
fdd	„}ˆd
v sdJ ‚ˆdv spJ ‚|S )a!  Create a wrapper function for the noise prediction model.

    DPM-Solver needs to solve the continuous-time diffusion ODEs. For DPMs trained on discrete-time labels, we need to
    firstly wrap the model function to a noise prediction model that accepts the continuous time as the input.

    We support four types of the diffusion model by setting `model_type`:

        1. "noise": noise prediction model. (Trained by predicting noise).

        2. "x_start": data prediction model. (Trained by predicting the data x_0 at time 0).

        3. "v": velocity prediction model. (Trained by predicting the velocity).
            The "v" prediction is derivation detailed in Appendix D of [1], and is used in Imagen-Video [2].

            [1] Salimans, Tim, and Jonathan Ho. "Progressive distillation for fast sampling of diffusion models."
                arXiv preprint arXiv:2202.00512 (2022).
            [2] Ho, Jonathan, et al. "Imagen Video: High Definition Video Generation with Diffusion Models."
                arXiv preprint arXiv:2210.02303 (2022).

        4. "score": marginal score function. (Trained by denoising score matching).
            Note that the score function and the noise prediction model follows a simple relationship:
            ```
                noise(x_t, t) = -sigma_t * score(x_t, t)
            ```

    We support three types of guided sampling by DPMs by setting `guidance_type`:
        1. "uncond": unconditional sampling by DPMs.
            The input `model` has the following format:
            ``
                model(x, t_input, **model_kwargs) -> noise | x_start | v | score
            ``

        2. "classifier": classifier guidance sampling [3] by DPMs and another classifier.
            The input `model` has the following format:
            ``
                model(x, t_input, **model_kwargs) -> noise | x_start | v | score
            ``

            The input `classifier_fn` has the following format:
            ``
                classifier_fn(x, t_input, cond, **classifier_kwargs) -> logits(x, t_input, cond)
            ``

            [3] P. Dhariwal and A. Q. Nichol, "Diffusion models beat GANs on image synthesis,"
                in Advances in Neural Information Processing Systems, vol. 34, 2021, pp. 8780-8794.

        3. "classifier-free": classifier-free guidance sampling by conditional DPMs.
            The input `model` has the following format:
            ``
                model(x, t_input, cond, **model_kwargs) -> noise | x_start | v | score
            ``
            And if cond == `unconditional_condition`, the model output is the unconditional DPM output.

            [4] Ho, Jonathan, and Tim Salimans. "Classifier-free diffusion guidance."
                arXiv preprint arXiv:2207.12598 (2022).


    The `t_input` is the time label of the model, which may be discrete-time labels (i.e. 0 to 999)
    or continuous-time labels (i.e. epsilon to T).

    We wrap the model function to accept only `x` and `t_continuous` as inputs, and outputs the predicted noise:
    ``
        def model_fn(x, t_continuous) -> noise:
            t_input = get_model_input_time(t_continuous)
            return noise_pred(model, x, t_input, **model_kwargs)
    ``
    where `t_continuous` is the continuous time labels (i.e. epsilon to T). And we use `model_fn` for DPM-Solver.

    ===============================================================

    Args:
        model: A diffusion model with the corresponding format described above.
        noise_schedule: A noise schedule object, such as NoiseScheduleVP.
        model_type: A `str`. The parameterization type of the diffusion model.
                    "noise" or "x_start" or "v" or "score".
        model_kwargs: A `dict`. A dict for the other inputs of the model function.
        guidance_type: A `str`. The type of the guidance for sampling.
                    "uncond" or "classifier" or "classifier-free".
        condition: A pytorch tensor. The condition for the guided sampling.
                    Only used for "classifier" or "classifier-free" guidance type.
        unconditional_condition: A pytorch tensor. The condition for the unconditional sampling.
                    Only used for "classifier-free" guidance type.
        guidance_scale: A `float`. The scale for the guided sampling.
        classifier_fn: A classifier function. Only used for the classifier guidance.
        classifier_kwargs: A `dict`. A dict for the other inputs of the classifier function.
    Returns:
        A noise prediction model that accepts the noised data and the continuous time as the inputs.
    c                    s$   ˆ j dkr| dˆ j  d S | S dS )a  
        Convert the continuous-time `t_continuous` (in [epsilon, T]) to the model input time.
        For discrete-time DPMs, we convert `t_continuous` in [1 / N, 1] to `t_input` in [0, 1000 * (N - 1) / N].
        For continuous-time DPMs, we just use `t_continuous`.
        r   r   g     @@N)r   r   )Út_continuous)Únoise_scheduler&   r'   Úget_model_input_time  s    
z+model_wrapper.<locals>.get_model_input_timeNc                    s  |  d¡jd dkr$| | jd ¡}ˆ |ƒ}|d u rJˆ| |d fi ˆ¤Ž}nˆ| ||fi ˆ¤Ž}ˆdkrj|S ˆdkr¬ˆ |¡ˆ |¡ }}|  ¡ }| t||ƒ|  t||ƒ S ˆdkrîˆ |¡ˆ |¡ }}|  ¡ }t||ƒ| t||ƒ|   S ˆdkrˆ |¡}|  ¡ }t||ƒ | S d S )Nr;   r   r	   rH   Úx_startÚvÚscore)r   ÚshapeÚexpandr7   r9   r   Úexpand_dims)ÚxrJ   ÚcondÚt_inputÚoutputÚalpha_tÚsigma_tÚdims)rL   ÚmodelÚmodel_kwargsÚ
model_typerK   r&   r'   Únoise_pred_fn$  s(    

z$model_wrapper.<locals>.noise_pred_fnc                    sd   t  ¡ H |  ¡  d¡}ˆ |||fi ˆ¤Ž}t j | ¡ |¡d W  d  ƒ S 1 sV0    Y  dS )z]
        Compute the gradient of the classifier, i.e. nabla_{x} log p_t(cond | x_t).
        Tr   N)r   Úenable_gradÚdetachÚrequires_grad_ÚautogradÚgradÚsum)rS   rU   Ú	conditionÚx_inÚlog_prob)Úclassifier_fnÚclassifier_kwargsr&   r'   Úcond_grad_fn;  s    
z#model_wrapper.<locals>.cond_grad_fnc                    sà  |  d¡jd dkr$| | jd ¡}ˆdkr6ˆ| |ƒS ˆdkrŽˆdusJJ ‚ˆ|ƒ}ˆ| |ˆ ƒ}ˆ	 |¡}ˆ| |ƒ}|ˆt|| ¡ d |  S ˆdkrÜˆd	ks¨ˆdu r¶ˆ| |ˆ d
S t | gd ¡}t |gd ¡}	tˆ t	ƒrTtˆt	ƒsðJ ‚i }
ˆ D ]X‰tˆ ˆ t
ƒr4‡ ‡‡fdd„ttˆ ˆ ƒƒD ƒ|
ˆ< nt ˆˆ ˆ ˆ g¡|
ˆ<  qøn`tˆ t
ƒr¦g }
tˆt
ƒstJ ‚ttˆ ƒƒD ]"}|
 t ˆ| ˆ | g¡¡ q€nt ˆˆ g¡}
ˆ||	|
d
 d¡\}}|ˆ||   S dS )zS
        The noise predicition model function that is used for DPM-Solver.
        r;   r   r	   rI   Ú
classifierN)rY   úclassifier-freer   )rT   r*   c                    s*   g | ]"}t  ˆˆ | ˆ ˆ | g¡‘qS r&   )r   Úcat)Ú.0Úi©rd   ÚkÚunconditional_conditionr&   r'   Ú
<listcomp>^  s
   þ

þz3model_wrapper.<locals>.model_fn.<locals>.<listcomp>)r   rP   rQ   r9   rR   r   r   rl   Ú
isinstanceÚdictÚlistÚranger   ÚappendÚchunk)rS   rJ   rd   rq   rU   Z	cond_gradrX   rH   re   Út_inÚc_inrn   Znoise_uncond)rg   ri   rL   Úguidance_scaleÚguidance_typer]   rK   ro   r'   Úmodel_fnD  sH    



þþ"zmodel_wrapper.<locals>.model_fn)rH   rM   rN   )rI   rj   rk   )Nr&   )	rZ   rK   r\   r[   r|   r{   rg   rh   r}   r&   )rg   rh   ri   rL   r{   r|   rZ   r[   r\   r]   rK   r'   Úmodel_wrapper±   s    e	+r~   c                   @   s~   e Zd Zd'dd„Zd(dd	„Zd
d„ Zdd„ Zdd„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zd)dd„Zd*dd„Zd+d%d&„ZdS ),ÚUniPCTFr   Úbh1Nc                 C   sF   || _ || _|| _|| _|| _|| _|| _|| _|	| _|
| _	|| _
dS )zZConstruct a UniPC.

        We support both data_prediction and noise_prediction.
        N)Ú	model_fn_rK   ÚvariantÚ
predict_x0ÚthresholdingÚmax_valrd   rq   Úbefore_sampleÚafter_sampleÚafter_update)r#   r}   rK   rƒ   r„   r…   r‚   rd   rq   r†   r‡   rˆ   r&   r&   r'   r(   u  s    zUniPC.__init__c                 C   sr   |  ¡ }| j}tjt |¡ |jd df¡|dd}tt || j	t 
|¡ |j¡ ¡|ƒ}t || |¡| }|S )z2
        The dynamic thresholding method.
        r   r   r	   r
   )r   Zdynamic_thresholding_ratior   ÚquantileÚabsr   rP   rR   ÚmaximumZthresholding_max_valÚ	ones_liker0   r1   Úclamp)r#   Úx0r2   rY   Úpr+   r&   r&   r'   Údynamic_thresholding_fn“  s    &&zUniPC.dynamic_thresholding_fnc                 C   sz   | j }| j}| jd ur.|  ||||¡\}}}}|  ||||¡}| jd urd|  |||||¡\}}}}}t|tƒrv|d }|S )Nr	   )rd   rq   r†   r   r‡   rs   Útuple)r#   rS   r2   rT   rI   Úresr&   r&   r'   rZ   ž  s    


zUniPC.modelc                 C   s   |   ||¡S )z4
        Return the noise prediction model.
        )rZ   ©r#   rS   r2   r&   r&   r'   Únoise_prediction_fn­  s    zUniPC.noise_prediction_fnc           
      C   s¸   |   ||¡}| ¡ }| j |¡| j |¡ }}|t||ƒ|  t||ƒ }| jr´d}tjt 	|¡ 
|jd df¡|dd}	tt |	| jt |	¡ |	j¡ ¡|ƒ}	t ||	 |	¡|	 }|S )zG
        Return the data prediction model (with thresholding).
        g×£p=
×ï?r   r   r	   r
   )r”   r   rK   r7   r9   rR   r„   r   r‰   rŠ   r   rP   r‹   r…   rŒ   r0   r1   r   )
r#   rS   r2   rH   rY   rW   rX   rŽ   r   r+   r&   r&   r'   Údata_prediction_fn³  s    &&zUniPC.data_prediction_fnc                 C   s"   | j r|  ||¡S |  ||¡S dS )z_
        Convert the model to the noise prediction model or the data prediction model.
        N)rƒ   r•   r”   r“   r&   r&   r'   r}   Â  s    zUniPC.model_fnc                 C   sÞ   |dkrl| j  t |¡ |¡¡}| j  t |¡ |¡¡}t | ¡  ¡ | ¡  ¡ |d ¡ |¡}| j  |¡S |dkrŒt |||d ¡ |¡S |dkrÊd}	t |d|	  |d|	  |d ¡ 	|	¡ |¡}
|
S t
d|› dƒ‚d	S )
z:Compute the intermediate time steps for sampling.
        ÚlogSNRr	   Útime_uniformÚtime_quadraticr*   r   zUnsupported skip_type z;, need to be 'logSNR' or 'time_uniform' or 'time_quadratic'N)rK   r:   r   Útensorr0   r   ÚcpuÚitemrD   Úpowr   )r#   Ú	skip_typeÚt_TÚt_0ÚNr1   Zlambda_TZlambda_0ZlogSNR_stepsZt_orderr2   r&   r&   r'   Úget_time_stepsË  s    (.zUniPC.get_time_stepsc           
      C   s.  |dkrp|d d }|d dkr8dg|d  ddg }qÚ|d dkrZdg|d  dg }qÚdg|d  dg }nj|dkrº|d dkr˜|d }dg| }qÚ|d d }dg|d  dg }n |dkrÒ|}dg| }nt dƒ‚|dkrö|  |||||¡}	n0|  |||||¡t t dg| ¡d¡ |¡ }	|	|fS )zW
        Get the order of each step for sampling by the singlestep DPM-Solver.
        é   r	   r   r*   z"'order' must be '1' or '2' or '3'.r–   )r   r¡   r   r   r™   r0   )
r#   ÚstepsÚorderr   rž   rŸ   r1   ÚKÚordersZtimesteps_outerr&   r&   r'   Ú.get_orders_and_timesteps_for_singlestep_solverÜ  s*    0z4UniPC.get_orders_and_timesteps_for_singlestep_solverc                 C   s   |   ||¡S )z‡
        Denoise at the final step, which is equivalent to solve the ODE from lambda_s to infty by first-order discretization.
        )r•   )r#   rS   r+   r&   r&   r'   Údenoise_to_zero_fnû  s    zUniPC.denoise_to_zero_fnc                 K   sh   t |jƒdkr| d¡}d| jv r<| j|||||fi |¤ŽS | jdksJJ ‚| j|||||fi |¤ŽS d S )Nr   r   ÚbhÚ
vary_coeff)r   rP   Úviewr‚   Úmultistep_uni_pc_bh_updateÚmultistep_uni_pc_vary_update)r#   rS   Úmodel_prev_listÚt_prev_listr2   r¤   Úkwargsr&   r&   r'   Úmultistep_uni_pc_update  s    

zUniPC.multistep_uni_pc_updatec           *   
   C   sú  | j }|t|ƒksJ ‚|d }| |¡}	| |¡}
|d }| |¡| |¡ }}| |¡}t |¡}|
|	 }g }g }td|ƒD ]R}||d   }||d   }| |¡}||	 | }| |¡ | || | ¡ q~| d¡ tj	||j
d}t|ƒ}g }t |¡}td|d ƒD ] }| |¡ || |d  }qtj|dd}t|ƒdkr|tj|dd}tj |d d…d d…f ¡}|}|r’tj |¡}|}| jr | n|} t | ¡}!g }"d}#|!}$td|d ƒD ],}|" |$¡ |$|  d|#  }$|#|d 9 }#qÈd }%| jrî|| | ||! |  }&|&}'t|ƒdkrft|d ƒD ],}|'||"|d   t d||| ¡  }'q8|rò|  |'|¡}%|%| }(|&}'d}t|d ƒD ]4}|'||"|d   t d||| d d… ¡  }'q”|'||"|  |(|| d    }'n| |¡| |¡ })}t ||) ¡| ||! |  }&|&}'t|ƒdkrnt|d ƒD ],}|'||"|d   t d||| ¡  }'q@|rò|  |'|¡}%|%| }(|&}'d}t|d ƒD ]4}|'||"|d   t d||| d d… ¡  }'qœ|'||"|  |(|| d    }'|'|%fS )	Nr   r	   r   ©r1   r
   r   r*   zbkchw,k->bchw)rK   r   r:   r9   r4   r   r5   rv   rw   r™   r1   rŒ   ÚstackÚlinalgÚinvrƒ   Úexpm1Úeinsumr}   )*r#   rS   r®   r¯   r2   r¤   Úuse_correctorÚnsÚt_prev_0Úlambda_prev_0Úlambda_tÚmodel_prev_0Úsigma_prev_0rX   r3   rW   ÚhÚrksÚD1srn   Út_prev_iÚmodel_prev_iÚlambda_prev_iÚrkr¥   ÚCÚcolrp   ZC_inv_pZA_pÚC_invZA_cÚhhÚh_phi_1Zh_phi_ksZfactorial_kÚh_phi_kÚmodel_tÚx_t_Úx_tÚD1_tÚlog_alpha_prev_0r&   r&   r'   r­   
  s     












ÿÿ*2$
ÿÿ*2 z"UniPC.multistep_uni_pc_vary_updatec           *      C   s8  | j }|t|ƒksJ ‚| ¡ }	|d }
| |
¡}| |¡}|d }| |
¡| |¡ }}| |
¡| |¡ }}t |¡}|| }g }g }td|ƒD ]V}||d   }||d   }| |¡}|| | d }| 	|¡ | 	|| | ¡ q’| 	d¡ tj
||jd}g }g }| jr|d  n|d }t |¡}|| d }d} | jdkrR|}!n| jdkrjt |¡}!ntƒ ‚td|d ƒD ]J}| 	t ||d ¡¡ | 	||  |! ¡ | |d 9 } || d|   }q~t |¡}tj
||jd}t|ƒdkoø|d u }"t|ƒdkrftj|dd}|d u rj|d	kr>tj
d
g|jd}#n&tj |d d…d d…f |d d… ¡}#nd }|rœ|dkrŽtj
d
g|jd}$ntj ||¡}$d }%| jrjt|| |	ƒ| t|| |	ƒ|  }&|d u r|"rìt d|#|¡}'nd}'|&t||! |	ƒ|'  }|r0|  ||¡}%|d ur:t d|$d d… |¡}(nd}(|%| })|&t||! |	ƒ|(|$d |)    }nÆtt || ¡|	ƒ| t|| |	ƒ|  }&|d u rÎ|"r´t d|#|¡}'nd}'|&t||! |	ƒ|'  }|r0|  ||¡}%|d urt d|$d d… |¡}(nd}(|%| })|&t||! |	ƒ|(|$d |)    }||%fS )Nr   r	   r   r   r²   r€   Úbh2r
   r*   r   zk,bkchw->bchw)rK   r   r   r:   r9   r4   r   r5   rv   rw   r™   r1   rƒ   r¶   r‚   ÚNotImplementedErrorrœ   r³   r´   ÚsolverR   r·   r}   )*r#   rS   r®   r¯   r2   r¤   rÎ   r¸   r¹   rY   rº   r»   r¼   r½   r¾   rX   rÐ   r3   rW   r¿   rÀ   rÁ   rn   rÂ   rÃ   rÄ   rÅ   ÚRÚbrÉ   rÊ   rË   Zfactorial_iZB_hZuse_predictorZrhos_pZrhos_crÌ   rÍ   Zpred_resZcorr_resrÏ   r&   r&   r'   r¬   q  s®    









(
ÿÿ

$ÿÿ

"z UniPC.multistep_uni_pc_bh_updateé   r¢   r—   Ú
singlestepÚ
dpm_solverçÞqŠŽäò?çš™™™™™©?c                 C   s²  |d u rd| j j n|}|d u r(| j jn|}|j}|dkr~||ksLJ dƒ‚| j|||||d}|jd d |ksvJ ‚t ¡ ê |d  |jd ¡}|  	||¡g}|g}t
j
|d’}td|ƒD ]|}||  |jd ¡}| j|||||dd	\}}|d u r|  	||¡}| jd ur$|  ||¡ | |¡ | |¡ | ¡  qÄt||d ƒD ]ê}||  |jd ¡}|r‚t||d | ƒ}n|}||kr–d
}nd}| j||||||d	\}}| jd urÌ|  ||¡ t|d ƒD ]&}||d  ||< ||d  ||< qØ||d< ||k r0|d u r(|  	||¡}||d< | ¡  qPW d   ƒ n1 sR0    Y  W d   ƒ n1 sr0    Y  ntƒ ‚|	r®|  |t |jd f¡ |¡| ¡}|S )Nr   Ú	multistepz$UniPC order must be < sampling steps)r   rž   rŸ   r    r1   r   r	   )ÚtotalT)r¸   Fr   )rK   r   r   r1   r¡   rP   r   Úno_gradrQ   r}   Útqdmrv   r±   rˆ   rw   ÚupdateÚminrÒ   r¨   Úonesr0   )r#   rS   r£   Út_startÚt_endr¤   r   ÚmethodÚlower_order_finalZdenoise_to_zeroÚsolver_typeÚatolÚrtolZ	correctorrŸ   rž   r1   Ú	timestepsZvec_tr®   r¯   ÚpbarZ
init_orderÚmodel_xÚstepZ
step_orderr¸   rn   r&   r&   r'   Úsampleê  s\    







N$zUniPC.sample)	TFr   r€   NNNNN)N)T)NT)rÖ   NNr¢   r—   r×   TFrØ   rÙ   rÚ   F)rE   rF   rG   r(   r   rZ   r”   r•   r}   r¡   r§   r¨   r±   r­   r¬   rí   r&   r&   r&   r'   r   t  s2            ô

		
g
y   þr   c                 C   s¶  | j d |j d  }}tj|  d¡| d¡ |ddf¡gdd}tj|dd\}}tj|dd}|d }	t t |d¡tj	d| j
dt t ||¡tj	|d | j
d|	¡¡}
t t |
|	¡|
d |
d ¡}tj|d|
 d¡d d¡}tj|d| d¡d d¡}t t |d¡tj	d| j
dt t ||¡tj	|d | j
d|	¡¡}| d¡ |dd¡}tj|d| d¡d d¡}tj|d|d  d¡d d¡}|| | ||  ||   }|S )a  
    A piecewise linear function y = f(x), using xp and yp as keypoints.
    We implement f(x) in a differentiable way (i.e. applicable for autograd).
    The function f(x) is well-defined for all x-axis. (For x beyond the bounds of xp, we use the outmost points of xp to define the linear function.)

    Args:
        x: PyTorch tensor with shape [N, C], where N is the batch size, C is the number of channels (we use C = 1 for DPM-Solver).
        xp: PyTorch tensor with shape [C, K], where K is the number of keypoints.
        yp: PyTorch tensor with shape [C, K].
    Returns:
        The function values f(x), with shape [N, C].
    r   r	   r*   r
   r²   )r   Úindexr   )rP   r   rl   Ú	unsqueezeÚrepeatÚsortÚargminÚwhereÚeqr™   r1   ÚgatherÚsqueezerQ   )rS   ÚxpÚypr    r¥   Zall_xZsorted_all_xÚ	x_indicesÚx_idxZcand_start_idxÚ	start_idxÚend_idxÚstart_xÚend_xZ
start_idx2Zy_positions_expandedÚstart_yÚend_yÚcandr&   r&   r'   r/   +  s6    *
ÿý
ÿý r/   c                 C   s   | dd|d    S )zé
    Expand the tensor `v` to the dim `dims`.

    Args:
        `v`: a PyTorch tensor with shape [N].
        `dim`: a `int`.
    Returns:
        a PyTorch tensor with shape [N, 1, 1, ..., 1] and the total dimension is `dims`.
    ).)Nr	   r&   )rN   rY   r&   r&   r'   rR   U  s    
rR   )rH   NrI   r   NN)r   r   rÞ   r   r~   r   r/   rR   r&   r&   r&   r'   Ú<module>   s$    /      ö
 D   :*