o
    pisW                     @   sx   d dl Z d dlmZmZmZmZ d dlZd dlZddl	m
Z
mZ ddlmZmZmZ 		dd	d
ZG dd dee
ZdS )    N)ListOptionalTupleUnion   )ConfigMixinregister_to_config   )KarrasDiffusionSchedulersSchedulerMixinSchedulerOutput+?cosinec                 C   s   |dkr	dd }n|dkrdd }nt d| g }t| D ]}||  }|d |  }|td||||  | qtj|tjdS )	a  
    Create a beta schedule that discretizes the given alpha_t_bar function, which defines the cumulative product of
    (1-beta) over time from t = [0,1].

    Contains a function alpha_bar that takes an argument t and transforms it to the cumulative product of (1-beta) up
    to that part of the diffusion process.


    Args:
        num_diffusion_timesteps (`int`): the number of betas to produce.
        max_beta (`float`): the maximum beta to use; use values lower than 1 to
                     prevent singularities.
        alpha_transform_type (`str`, *optional*, default to `cosine`): the type of noise schedule for alpha_bar.
                     Choose from `cosine` or `exp`

    Returns:
        betas (`np.ndarray`): the betas used by the scheduler to step the model outputs
    r   c                 S   s    t | d d t j d d S )NgMb?gT㥛 ?r   )mathcospit r   k/home/ubuntu/SoloSpeech/.venv/lib/python3.10/site-packages/diffusers/schedulers/scheduling_heun_discrete.pyalpha_bar_fn3   s    z)betas_for_alpha_bar.<locals>.alpha_bar_fnexpc                 S   s   t | d S )Ng      ()r   r   r   r   r   r   r   8   s   z"Unsupported alpha_transform_type: r	   dtype)
ValueErrorrangeappendmintorchtensorfloat32)num_diffusion_timestepsmax_betaalpha_transform_typer   betasit1t2r   r   r   betas_for_alpha_bar   s   

"r(   c                   @   s  e Zd ZdZdd eD ZdZe							
					dEdede	de	de
deeejee	 f  de
dee dee de	de
defddZdFddZedd Zed d! Zed"d# ZdGd$efd%d&Zd'ejd(ee	ejf d)ejfd*d+Z								dHd,ee d-ee
ejf dee d.eee  fd/d0Zd1d2 Zd3ejd)ejfd4d5Zed6d7 Zd8d9 Z 	:dId;eejejf d(ee	ejf d'eejejf d<ed)ee!e"f f
d=d>Z#d?ejd@ejd.ejd)ejfdAdBZ$dCdD Z%d	S )JHeunDiscreteScheduleru  
    Scheduler with Heun steps for discrete beta schedules.

    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` or `scaled_linear`.
        trained_betas (`np.ndarray`, *optional*):
            Pass an array of betas directly to the constructor to bypass `beta_start` and `beta_end`.
        prediction_type (`str`, defaults to `epsilon`, *optional*):
            Prediction type of the scheduler function; can be `epsilon` (predicts the noise of the diffusion process),
            `sample` (directly predicts the noisy sample`) or `v_prediction` (see section 2.4 of [Imagen
            Video](https://imagen.research.google/video/paper.pdf) paper).
        clip_sample (`bool`, defaults to `True`):
            Clip the predicted sample for numerical stability.
        clip_sample_range (`float`, defaults to 1.0):
            The maximum magnitude for sample clipping. Valid only when `clip_sample=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}.
        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.
    c                 C   s   g | ]}|j qS r   )name).0er   r   r   
<listcomp>k   s    z HeunDiscreteScheduler.<listcomp>r     _QK?~jt?linearNepsilonF      ?linspacer   num_train_timesteps
beta_startbeta_endbeta_scheduletrained_betasprediction_typeuse_karras_sigmasclip_sampleclip_sample_rangetimestep_spacingsteps_offsetc                 C   s   |d urt j|t jd| _nH|dkrt j|||t jd| _n8|dkr4t j|d |d |t jdd | _n"|dkr@t|dd| _n|d	krLt|d	d| _n
t| d
| j d| j | _t j	| jdd| _
| |d | || _d | _d | _| jd| _d S )Nr   r1   scaled_linear      ?r   squaredcos_cap_v2r   )r#   r   z is not implemented for r3   r   )dimcpu)r   r   r    r$   r4   r(   NotImplementedError	__class__alphascumprodalphas_cumprodset_timestepsr;   _step_index_begin_indexsigmasto)selfr5   r6   r7   r8   r9   r:   r;   r<   r=   r>   r?   r   r   r   __init__n   s$   $zHeunDiscreteScheduler.__init__c                 C   s:   |d u r| j }||k }t|dkrdnd}||  S )Nr	   r   )	timestepsnonzerolenitem)rO   timestepschedule_timestepsindicesposr   r   r   index_for_timestep   s
   z(HeunDiscreteScheduler.index_for_timestepc                 C   s,   | j jdv r| j S | j d d d S )N)r4   trailingr   r	   rA   )configr>   rM   maxrO   r   r   r   init_noise_sigma   s   
z&HeunDiscreteScheduler.init_noise_sigmac                 C      | j S )zg
        The index counter for current timestep. It will increase 1 after each scheduler step.
        )rK   r]   r   r   r   
step_index      z HeunDiscreteScheduler.step_indexc                 C   r_   )zq
        The index for the first timestep. It should be set from pipeline with `set_begin_index` method.
        rL   r]   r   r   r   begin_index   ra   z!HeunDiscreteScheduler.begin_indexrc   c                 C   s
   || _ dS )z
        Sets the begin index for the scheduler. This function should be run from pipeline before the inference.

        Args:
            begin_index (`int`):
                The begin index for the scheduler.
        Nrb   )rO   rc   r   r   r   set_begin_index   s   
z%HeunDiscreteScheduler.set_begin_indexsamplerU   returnc                 C   s8   | j du r
| | | j| j  }||d d d  }|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.
            timestep (`int`, *optional*):
                The current timestep in the diffusion chain.

        Returns:
            `torch.Tensor`:
                A scaled input sample.
        Nr   r	   rA   )r`   _init_step_indexrM   )rO   re   rU   sigmar   r   r   scale_model_input   s
   

z'HeunDiscreteScheduler.scale_model_inputnum_inference_stepsdevicerQ   c                    s  |du r|du rt d|dur|durt d|dur$jjr$t d|p)t|}|_|p2jj}|dur@tj|tjd}njjj	dkrZtj
d|d |tjdddd	  }nPjj	d
kr|j }td||  ddd	  tj}|jj7 }n)jj	dkr|j }t|d|   tj}|d8 }n	t jj	 dtdj j d }t| t|tdt||}jjrj|jd}t fdd|D }t|dggtj}t|j|d}t|dd |dd	 d|d	d g_t|}t|dd |dd dg}|j|d_d_d_d_d_jd_dS )a  
        Sets the discrete timesteps used for the diffusion chain (to be run before inference).

        Args:
            num_inference_steps (`int`):
                The number of diffusion steps used when generating samples with a pre-trained model.
            device (`str` or `torch.device`, *optional*):
                The device to which the timesteps should be moved to. If `None`, the timesteps are not moved.
            num_train_timesteps (`int`, *optional*):
                The number of diffusion steps used when training the model. If `None`, the default
                `num_train_timesteps` attribute is used.
            timesteps (`List[int]`, *optional*):
                Custom timesteps used to support arbitrary spacing between timesteps. If `None`, timesteps will be
                generated based on the `timestep_spacing` attribute. If `timesteps` is passed, `num_inference_steps`
                must be `None`, and `timestep_spacing` attribute will be ignored.
        NzEMust pass exactly one of `num_inference_steps` or `custom_timesteps`.zACan only pass one of `num_inference_steps` or `custom_timesteps`.z=Cannot use `timesteps` with `config.use_karras_sigmas = True`r   r4   r   r	   leadingrZ   zY is not supported. Please make sure to choose one of 'linspace', 'leading' or 'trailing'.rA   )	in_sigmasrj   c                       g | ]} | qS r   )_sigma_to_t)r+   rh   
log_sigmasrO   r   r   r-          z7HeunDiscreteScheduler.set_timesteps.<locals>.<listcomp>g        )rk   r   rD   ) r   r[   r;   rS   rj   r5   nparrayr    r>   r4   copyarangeroundastyper?   rI   loginterp_convert_to_karrasconcatenater   
from_numpyrN   catrepeat_interleaverM   rQ   prev_derivativedtrK   rL   )rO   rj   rk   r5   rQ   
step_ratiorM   r   rq   r   rJ      sR   (
*
 

0
$z#HeunDiscreteScheduler.set_timestepsc                 C   s   t t |d}||d d t jf  }t j|dkddjddj|jd d d}|d }|| }|| }|| ||  }	t |	dd}	d|	 | |	|  }
|
|j}
|
S )Ng|=r   )axisr   )r\   r	   )	rt   rz   maximumnewaxiscumsumargmaxclipshapereshape)rO   rh   rr   	log_sigmadistslow_idxhigh_idxlowhighwr   r   r   r   rp   4  s   ,z!HeunDiscreteScheduler._sigma_to_trn   c           
      C   s   t | jdr| jj}nd}t | jdr| jj}nd}|dur |n|d  }|dur,|n|d  }d}tdd|}|d|  }|d|  }||||   | }	|	S )z6Constructs the noise schedule of Karras et al. (2022).	sigma_minN	sigma_maxrl   r   g      @r	   )hasattrr[   r   r   rT   rt   r4   )
rO   rn   rj   r   r   rhorampmin_inv_rhomax_inv_rhorM   r   r   r   r|   L  s   

z(HeunDiscreteScheduler._convert_to_karrasc                 C   s
   | j d u S N)r   r]   r   r   r   state_in_first_ordere  s   
z*HeunDiscreteScheduler.state_in_first_orderc                 C   s@   | j d u rt|tjr|| jj}| || _d S | j	| _d S r   )
rc   
isinstancer   TensorrN   rQ   rk   rY   rK   rL   )rO   rU   r   r   r   rg   j  s
   
z&HeunDiscreteScheduler._init_step_indexTmodel_outputreturn_dictc                 C   s  | j du r
| | | jr| j| j  }| j| j d  }n| j| j d  }| j| j  }d}||d  }| jjdkrF| jr=|n|}	||	|  }
n6| jjdkri| jrQ|n|}	||	 |	d d d   ||	d d   }
n| jjdkrr|}
n
td	| jj d
| jjr|
| jj	 | jj	}
| jr||
 | }|| }|| _
|| _|| _n||
 | }| j
| d }| j}| j}d| _
d| _d| _|||  }|  jd7  _|s|fS t|dS )a  
        Predict the sample from the previous timestep by reversing the SDE. This function propagates the diffusion
        process from the learned model outputs (most often the predicted noise).

        Args:
            model_output (`torch.Tensor`):
                The direct output from learned diffusion model.
            timestep (`float`):
                The current discrete timestep in the diffusion chain.
            sample (`torch.Tensor`):
                A current instance of a sample created by the diffusion process.
            return_dict (`bool`):
                Whether or not to return a [`~schedulers.scheduling_utils.SchedulerOutput`] or tuple.

        Returns:
            [`~schedulers.scheduling_utils.SchedulerOutput`] or `tuple`:
                If return_dict is `True`, [`~schedulers.scheduling_utils.SchedulerOutput`] is returned, otherwise a
                tuple is returned where the first element is the sample tensor.
        Nr	   r   r2   v_predictionr   rA   re   zprediction_type given as z, must be one of `epsilon`, or `v_prediction`)prev_sample)r`   rg   r   rM   r[   r:   r   r<   clampr=   r   r   re   rK   r   )rO   r   rU   re   r   rh   
sigma_nextgamma	sigma_hatsigma_inputpred_original_sample
derivativer   r   r   r   r   stepr  sX   


zHeunDiscreteScheduler.steporiginal_samplesnoisec                    s
  j j|j|jd}|jjdkr)t|r)jj|jtjd |j|jtjd}nj|j ||j}j	d u rF fdd|D }nj
d urUj
g|jd  }n	j	g|jd  }||  }t|jt|jk r}|d}t|jt|jk sn|||  }|S )N)rk   r   mpsr   c                    ro   r   )rY   )r+   r   rV   rO   r   r   r-     rs   z3HeunDiscreteScheduler.add_noise.<locals>.<listcomp>r   rl   )rM   rN   rk   r   typer   is_floating_pointrQ   r    rc   r`   r   flattenrS   	unsqueeze)rO   r   r   rQ   rM   step_indicesrh   noisy_samplesr   r   r   	add_noise  s"   


zHeunDiscreteScheduler.add_noisec                 C   s   | j jS r   )r[   r5   r]   r   r   r   __len__  s   zHeunDiscreteScheduler.__len__)r.   r/   r0   r1   Nr2   FFr3   r4   r   r   )r   )NNNN)T)&__name__
__module____qualname____doc__r
   _compatiblesorderr   intfloatstrr   r   rt   ndarrayr   boolrP   rY   propertyr^   r`   rc   rd   r   r   ri   rk   rJ   rp   r|   r   rg   r   r   r   r   r   r   r   r   r   r)   F   s    $	

)






S


d
!r)   )r   r   )r   typingr   r   r   r   numpyrt   r   configuration_utilsr   r   scheduling_utilsr
   r   r   r(   r)   r   r   r   r   <module>   s   
,