o
    ¶Ïi£˜  ã                   @   s˜   d dl Z d dlZd dlZd dlmZ G dd„ dƒZdi dddddi fdd	„ZG d
d„ dƒZdd„ Zdd„ Z	G dd„ dƒZ
dd„ Zddd„Zddd„ZdS )é    N)Útrangec                   @   sH   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krS|dur$dt d| ¡jdd }n|dus*J ‚dt |¡ }t|ƒ| _d	| _t 	d
d	| jd ¡dd…  
d¡| _| 
d¡| _dS 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| _dS 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ÚcosinezZUnsupported noise schedule {}. 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ÚformatÚscheduleÚtorchÚlogÚcumsumÚlenÚtotal_NÚTÚlinspaceÚreshapeÚt_arrayÚlog_alpha_arrayÚbeta_0Úbeta_1Úcosine_sÚcosine_beta_maxÚmathÚatanÚpiÚcosine_t_maxÚcosÚcosine_log_alpha_0)Úselfr   ÚbetasÚalphas_cumprodÚcontinuous_beta_0Úcontinuous_beta_1Ú
log_alphas© r-   ú9/mnt/c/Users/fbmor/ComfyUI/comfy/extra_samplers/uni_pc.pyÚ__init__   s.   X
$8(

zNoiseScheduleVP.__init__c                    s’   ˆ j dkrt| d¡ˆ j |j¡ˆ j |j¡ƒ d¡S ˆ j dkr3d|d  ˆ jˆ j  d| ˆ j  S ˆ j dkrG‡ 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>Š   s   * z9NoiseScheduleVP.marginal_log_mean_coeff.<locals>.<lambda>N)
r   Úinterpolate_fnr   r   ÚtoÚdevicer   r   r   r&   )r'   ÚtÚlog_alpha_fnÚlog_alpha_tr-   r4   r.   Úmarginal_log_mean_coeff   s   
,
&
ýz'NoiseScheduleVP.marginal_log_mean_coeffc                 C   ó   t  |  |¡¡S )zO
        Compute alpha_t of a given continuous-time label t in [0, T].
        ©r   Úexpr<   ©r'   r9   r-   r-   r.   Úmarginal_alphaŽ   s   zNoiseScheduleVP.marginal_alphac              	   C   ó   t  dt  d|  |¡ ¡ ¡S )zO
        Compute sigma_t of a given continuous-time label t in [0, T].
        r   r   ©r   Úsqrtr?   r<   r@   r-   r-   r.   Úmarginal_std”   s   zNoiseScheduleVP.marginal_stdc                 C   ó.   |   |¡}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   ©r<   r   r   r?   ©r'   r9   Úlog_mean_coeffÚlog_stdr-   r-   r.   Úmarginal_lambdaš   ó   
zNoiseScheduleVP.marginal_lambdac                    s  ˆ j dkr2dˆ jˆ j  t d| t d¡ |¡¡ }ˆ jd | }|t |¡ˆ j  ˆ jˆ j  S ˆ j dkrjd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 )z`
        Compute the continuous-time label t in [0, T] of a given half-logSNR lambda_t.
        r   r   g       À©r
   r1   r   g      à¿r0   r
   ©r   c                    s0   t  t  | ˆ j ¡¡d dˆ j  tj ˆ j S )Nr   r   )r   Úarccosr?   r&   r   r!   r#   )r;   r4   r-   r.   r5   °   s   0 z0NoiseScheduleVP.inverse_lambda.<locals>.<lambda>)r   r   r   r   Ú	logaddexpÚzerosr7   rD   r8   r6   r   Úflipr   r   )r'   ÚlambÚtmpÚDeltaÚ	log_alphar9   Út_fnr-   r4   r.   Úinverse_lambda¢   s   
, 
":
 zNoiseScheduleVP.inverse_lambda)r   NNr   r   )	Ú__name__Ú
__module__Ú__qualname__r/   r<   rA   rE   rL   rY   r-   r-   r-   r.   r   
   s    
úvr   ÚnoiseÚuncondr   c
              	      sj   ‡fdd„‰d‡‡‡‡	‡fdd„	‰
‡ ‡‡fdd„‰‡ ‡‡‡‡‡‡
‡‡f	dd	„}
ˆ	d
v s-J ‚ˆdv s3J ‚|
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 )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     @@)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 ¡}ˆ |ƒ}ˆ| |fi ˆ¤Ž}ˆdkr%|S ˆdkrFˆ |¡ˆ |¡}}|  ¡ }| t||ƒ|  t||ƒ S ˆdkrgˆ |¡ˆ |¡}}|  ¡ }t||ƒ| t||ƒ|   S ˆdkr|ˆ |¡}|  ¡ }t||ƒ | S d S )NrO   r   r
   r]   Úx_startÚvÚscore)r   ÚshapeÚexpandrA   rE   r   Úexpand_dims)Úxr_   ÚcondÚt_inputÚoutputÚalpha_tÚsigma_tÚdims)ra   ÚmodelÚmodel_kwargsÚ
model_typer`   r-   r.   Únoise_pred_fn%  s&   
ýz$model_wrapper.<locals>.noise_pred_fnc                    sd   t  ¡ $ |  ¡  d¡}ˆ ||ˆfi ˆ¤Ž}t j | ¡ |¡d W  d  ƒ S 1 s+w   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)rh   rj   Úx_inÚlog_prob)Úclassifier_fnÚclassifier_kwargsÚ	conditionr-   r.   Úcond_grad_fn9  s
   
$ýz#model_wrapper.<locals>.cond_grad_fnc           
         s  |  d¡jd dkr| | jd ¡}ˆdkrˆ| |ƒS ˆdkrFˆ dus%J ‚ˆ|ƒ}ˆ| |ƒ}ˆ |¡}ˆ| |ƒ}|ˆt|| ¡ d |  S ˆdkr„ˆd	ksRˆdu rYˆ| |ˆd
S t | gd ¡}t |gd ¡}t ˆˆg¡}ˆ|||d
 d¡\}	}|	ˆ||	   S dS )zS
        The noise predicition model function that is used for DPM-Solver.
        rO   r   r
   r^   Ú
classifierN©rn   úclassifier-freer   )ri   r1   )	r   re   rf   rE   rg   r   r   ÚcatÚchunk)
rh   r_   rj   Ú	cond_gradrm   r]   ry   Út_inÚc_inÚnoise_uncond)	r{   r~   r}   ra   Úguidance_scaleÚguidance_typerr   r`   Úunconditional_conditionr-   r.   Úmodel_fnB  s(   



øzmodel_wrapper.<locals>.model_fn)r]   rb   rc   )r^   r   r   ©Nr-   )ro   r`   rq   rp   r‰   r}   rŠ   rˆ   r{   r|   r‹   r-   )r{   r|   r~   r}   ra   rˆ   r‰   ro   rp   rq   rr   r`   rŠ   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d„Zd'dd„Z			d(d"d#„ZdS ))ÚUniPCTFr   Úbh1c                 C   s(   || _ || _|| _|| _|| _|| _dS )zZConstruct a UniPC.

        We support both data_prediction and noise_prediction.
        N)ro   r`   ÚvariantÚ
predict_x0ÚthresholdingÚmax_val)r'   r‹   r`   r‘   r’   r“   r   r-   r-   r.   r/   a  s   
zUniPC.__init__Nc                 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   Údynamic_thresholding_ratior   ÚquantileÚabsr   re   rg   ÚmaximumÚthresholding_max_valÚ	ones_liker7   r8   Úclamp)r'   Úx0r9   rn   Úpr3   r-   r-   r.   Údynamic_thresholding_fnu  s   &&zUniPC.dynamic_thresholding_fnc                 C   ó   |   ||¡S )z4
        Return the noise prediction model.
        ©ro   ©r'   rh   r9   r-   r-   r.   Únoise_prediction_fn€  ó   zUniPC.noise_prediction_fnc           
      C   s¸   |   ||¡}| ¡ }| j |¡| j |¡}}|t||ƒ|  t||ƒ }| jrZd}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   r`   rA   rE   rg   r’   r   r•   r–   r   re   r—   r“   r™   r7   r8   rš   )
r'   rh   r9   r]   rn   rl   rm   r›   rœ   r3   r-   r-   r.   Údata_prediction_fn†  s   &&zUniPC.data_prediction_fnc                 C   s   | j r	|  ||¡S |  ||¡S )z_
        Convert the model to the noise prediction model or the data prediction model.
        )r‘   r£   r¡   r    r-   r-   r.   r‹   •  s   zUniPC.model_fnc                 C   sØ   |dkr6| j  t |¡ |¡¡}| j  t |¡ |¡¡}t | ¡  ¡ | ¡  ¡ |d ¡ |¡}| j  |¡S |dkrFt |||d ¡ |¡S |dkred}	t |d|	  |d|	  |d ¡ 	|	¡ |¡}
|
S t
d |¡ƒ‚)z:Compute the intermediate time steps for sampling.
        ÚlogSNRr
   Útime_uniformÚtime_quadraticr1   r   zSUnsupported skip_type {}, need to be 'logSNR' or 'time_uniform' or 'time_quadratic')r`   rL   r   Útensorr7   r   ÚcpuÚitemrY   Úpowr   r   )r'   Ú	skip_typeÚt_TÚt_0ÚNr8   Úlambda_TÚlambda_0ÚlogSNR_stepsÚt_orderr9   r-   r-   r.   Úget_time_stepsž  s   (.zUniPC.get_time_stepsc           
      C   s4  |dkr8|d d }|d dkrdg|d  ddg }nQ|d dkr-dg|d  dg }n@dg|d  dg }n5|dkr]|d dkrL|d }dg| }n!|d d }dg|d  dg }n|dkri|}dg| }nt dƒ‚|dkr~|  |||||¡}	|	|fS |  |||||¡t t dg| ¡d¡ |¡ }	|	|fS )zW
        Get the order of each step for sampling by the singlestep DPM-Solver.
        é   r
   r   r1   z"'order' must be '1' or '2' or '3'.r¤   )r   r³   r   r   r§   r7   )
r'   ÚstepsÚorderr«   r¬   r­   r8   ÚKÚordersÚtimesteps_outerr-   r-   r.   Ú.get_orders_and_timesteps_for_singlestep_solver¯  s,   0ÿz4UniPC.get_orders_and_timesteps_for_singlestep_solverc                 C   rž   )z‡
        Denoise at the final step, which is equivalent to solve the ODE from lambda_s to infty by first-order discretization.
        )r£   )r'   rh   r3   r-   r-   r.   Údenoise_to_zero_fnÎ  r¢   zUniPC.denoise_to_zero_fnc                 K   sd   t |jƒdkr| d¡}d| jv r| j|||||fi |¤ŽS | jdks%J ‚| j|||||fi |¤ŽS )Nr   r   ÚbhÚ
vary_coeff)r   re   Úviewr   Úmultistep_uni_pc_bh_updateÚmultistep_uni_pc_vary_update)r'   rh   Úmodel_prev_listÚt_prev_listr9   r¶   Úkwargsr-   r-   r.   Úmultistep_uni_pc_updateÔ  s   

zUniPC.multistep_uni_pc_updatec           *   
   C   s  t  d|› d¡ | j}|t|ƒksJ ‚|d }| |¡}	| |¡}
|d }| |¡| |¡}}| |¡}t |¡}|
|	 }g }g }t	d|ƒD ])}||d   }||d   }| |¡}||	 | }| 
|¡ | 
|| | ¡ qH| 
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r7t	|d ƒD ]}|'||"|d   t d
||| ¡  }'q |ry|  |'|¡}%|%| }(|&}'d}t	|d ƒD ]}|'||"|d   t d
||| d d… ¡  }'qN|'||"|  |(|| d    }'|'|%fS | |¡| |¡})}t ||) ¡| ||! |  }&|&}'t|ƒdkr½t	|d ƒD ]}|'||"|d   t d
||| ¡  }'q¦|rÿ|  |'|¡}%|%| }(|&}'d}t	|d ƒD ]}|'||"|d   t d
||| d d… ¡  }'qÔ|'||"|  |(|| d    }'|'|%fS )Nz-using unified predictor-corrector with order z (solver type: vary coeff)r   r
   r   ©r8   r   r   r1   zbkchw,k->bchw)ÚloggingÚinfor`   r   rL   rE   r<   r   r?   ÚrangeÚappendr§   r8   r™   ÚstackÚlinalgÚinvr‘   Úexpm1Úeinsumr‹   )*r'   rh   rÁ   rÂ   r9   r¶   Úuse_correctorÚnsÚt_prev_0Úlambda_prev_0Úlambda_tÚmodel_prev_0Úsigma_prev_0rm   r;   rl   ÚhÚrksÚD1sÚiÚt_prev_iÚmodel_prev_iÚlambda_prev_iÚrkr·   ÚCÚcolÚkÚC_inv_pÚA_pÚC_invÚA_cÚhhÚh_phi_1Úh_phi_ksÚ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   sH  | j }|t|ƒksJ ‚| ¡ }	|d }
| |
¡}| |¡}|d }| |
¡| |¡}}| |
¡| |¡}}t |¡}|| }g }g }td|ƒD ]+}||d   }||d   }| |¡}|| | d }| 	|¡ | 	|| | ¡ qI| 	d¡ tj
||jd}g }g }| jrŽ|d  n|d }t |¡}|| d }d} | jdkr§|}!n| jdkr²t |¡}!ntƒ ‚td|d ƒD ]$}| 	t ||d ¡¡ | 	||  |! ¡ | |d 9 } || d|   }q¼t |¡}tj
||jd}t|ƒdko÷|d u }"t|ƒdkr.tj|dd}|d u r-|d	krtj
d
g|jd}#ntj |d d…d d…f |d d… ¡}#nd }|rI|dkrBtj
d
g|jd}$ntj ||¡}$d }%| jr½t|| |	ƒ| t|| |	ƒ|  }&|d u rƒ|"rvtj||#dgdgfd}'nd}'|&t||! |	ƒ|'  }|r¹|  ||¡}%|d ur¢tj||$d d… dgdgfd}(nd}(|%| })|&t||! |	ƒ|(|$d |)    }||%fS tt || ¡|	ƒ| t|| |	ƒ|  }&|d u rï|"rât d|#|¡}'nd}'|&t||! |	ƒ|'  }|r |  ||¡}%|d ur	t d|$d d… |¡}(nd}(|%| })|&t||! |	ƒ|(|$d |)    }||%fS )Nr   r
   r   r   rÅ   r   Úbh2r   r1   r	   r€   zk,bkchw->bchw)r`   r   r   rL   rE   r<   r   r?   rÈ   rÉ   r§   r8   r‘   rÍ   r   ÚNotImplementedErrorrª   rÊ   rË   Úsolverg   Ú	tensordotr‹   rÎ   )*r'   rh   rÁ   rÂ   r9   r¶   rì   rÏ   rÐ   rn   rÑ   rÒ   rÓ   rÔ   rÕ   rm   rî   r;   rl   rÖ   r×   rØ   rÙ   rÚ   rÛ   rÜ   rÝ   ÚRÚbrå   ræ   ré   Úfactorial_iÚB_hÚuse_predictorÚrhos_pÚrhos_crê   rë   Úpred_resÚcorr_resrí   r-   r-   r.   r¿   C  s²   











&€
ÿÿ

""îÿÿ

"z UniPC.multistep_uni_pc_bh_updater´   r¥   Ú
singlestepÚ
dpm_solverçÞqŠŽäò?çš™™™™™©?c              
   C   sê  t |ƒd }|dkrò||ksJ ‚|jd d |ksJ ‚t||dD ]Î}|dkr<|d  |jd ¡}|  ||¡g}|g}n¥||k rn|}||  |jd ¡}| j|||||dd\}}|d u rc|  ||¡}| |¡ | |¡ nsd}||d krxd}t||d | ƒD ]_}||  |jd ¡}|r™t||d | ƒ}n|}||kr¢d}nd}| j||||||d\}}t|d ƒD ]}||d  ||< ||d  ||< q·||d< ||k rà|d u rÜ|  ||¡}||d< q|d urï||||d d	œƒ q!|S t	ƒ ‚)
Nr
   Ú	multistepr   )ÚdisableT)rÏ   Fr   )rh   rÙ   Údenoised)
r   re   r   rf   r‹   rÄ   rÉ   rÈ   Úminrð   )r'   rh   Ú	timestepsÚt_startÚt_endr¶   r«   ÚmethodÚlower_order_finalÚdenoise_to_zeroÚsolver_typeÚatolÚrtolÚ	correctorÚcallbackÚdisable_pbarrµ   Ú
step_indexÚvec_trÁ   rÂ   Ú
init_orderÚmodel_xÚextra_final_stepÚstepÚ
step_orderrÏ   rÙ   r-   r-   r.   Úsample¼  sV   
€€ýzUniPC.sample)TFr   r   rŒ   )T)NT)NNr´   r¥   rü   TFrý   rþ   rÿ   FNF)rZ   r[   r\   r/   r   r¡   r£   r‹   r³   rº   r»   rÄ   rÀ   r¿   r  r-   r-   r-   r.   rŽ   `  s(    
ù
	
	
f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
   r1   r   rÅ   )r   Úindexr   )re   r   r‚   Ú	unsqueezeÚrepeatÚsortÚargminÚwhereÚeqr§   r8   ÚgatherÚsqueezerf   )rh   ÚxpÚypr®   r·   Úall_xÚsorted_all_xÚ	x_indicesÚx_idxÚcand_start_idxÚ	start_idxÚend_idxÚstart_xÚend_xÚ
start_idx2Úy_positions_expandedÚstart_yÚend_yÚcandr-   r-   r.   r6   þ  s6   *
ÿý
ÿý r6   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`.
    ).rŒ   r
   r-   )rc   rn   r-   r-   r.   rg   (  s   
rg   c                   @   s0   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
S )ÚSigmaConvertÚ c                 C   s   dt  d|| d  ¡ S )Nr	   r
   )r   r   )r'   Úsigmar-   r-   r.   r<   7  s   z$SigmaConvert.marginal_log_mean_coeffc                 C   r=   rŒ   r>   r@   r-   r-   r.   rA   :  s   zSigmaConvert.marginal_alphac              	   C   rB   r2   rC   r@   r-   r-   r.   rE   =  s   zSigmaConvert.marginal_stdc                 C   rF   rG   rH   rI   r-   r-   r.   rL   @  rM   zSigmaConvert.marginal_lambdaN)rZ   r[   r\   r   r<   rA   rE   rL   r-   r-   r-   r.   r1  5  s    r1  c                 K   sP   |  |jd d… d|jd   ¡}||d d d  }|| ||fi |¤Ž | S )Nr
   rN   r1   r   r	   )r¾   re   Úndim)ro   ÚinputÚsigma_inrÃ   r3  r-   r-   r.   Úpredict_eps_sigmaH  s   "r7  Fr   c              
      sÄ   |  ¡ }|d dkr|d d … }d|d< n|  ¡ }tƒ }|t d|d d  ¡ }d}	t‡ fdd„||	d	|d
}
tdt|ƒd ƒ}t|
|dd|d}|j||dd|d||d}|| 	|d ¡ }|S )Nr   r   gü©ñÒMbP?r   r   r]   c                    s   t ˆ | |fi |¤ŽS rŒ   )r7  )r5  r3  rÃ   rŸ   r-   r.   r5   [  s    zsample_unipc.<locals>.<lambda>r^   )rq   r‰   rp   r´   r1   TF)r‘   r’   r   r¥   r   )r  r«   r  r¶   r  r  r  )
Úcloner1  r   rD   r   r  r   rŽ   r  rA   )ro   r]   ÚsigmasÚ
extra_argsr  r  r   r  rÐ   rq   r‹   r¶   Úuni_pcrh   r-   rŸ   r.   Úsample_unipcN  s(   

ûr<  c              	   C   s   t | |||||ddS )Nrï   )r   )r<  )ro   r]   r9  r:  r  r  r-   r-   r.   Úsample_unipc_bh2h  s   r=  )NNFr   )NNF)r   r!   rÆ   Ú	tqdm.autor   r   r   rŽ   r6   rg   r1  r7  r<  r=  r-   r-   r-   r.   Ú<module>   s4    /
ö ,   !*
