o
    piMC                     @   s   d dl Z d dlmZ d dlmZmZm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 eeZeG d
d deZG dd dee	ZdS )    N)	dataclass)OptionalTupleUnion   )ConfigMixinregister_to_config)
BaseOutputlogging)randn_tensor   )SchedulerMixinc                   @   s.   e Zd ZU dZejed< dZeej ed< dS )EDMEulerSchedulerOutputaq  
    Output class for the scheduler's `step` function output.

    Args:
        prev_sample (`torch.Tensor` of shape `(batch_size, num_channels, height, width)` for images):
            Computed sample `(x_{t-1})` of previous timestep. `prev_sample` should be used as next model input in the
            denoising loop.
        pred_original_sample (`torch.Tensor` of shape `(batch_size, num_channels, height, width)` for images):
            The predicted denoised sample `(x_{0})` based on the model output from the current timestep.
            `pred_original_sample` can be used to preview progress or for guidance.
    prev_sampleNpred_original_sample)	__name__
__module____qualname____doc__torchTensor__annotations__r   r    r   r   g/home/ubuntu/SoloSpeech/.venv/lib/python3.10/site-packages/diffusers/schedulers/scheduling_edm_euler.pyr      s   
 
r   c                   @   s  e Zd ZdZg ZdZe								dId
edededede	dedefddZ
edd Zedd Zedd ZdJde	fddZdd Zdd  Zd!d" Zd#ejd$eeejf d%ejfd&d'ZdKd)e	d*eeejf fd+d,ZdLd%ejfd-d.ZdLd%ejfd/d0ZdKd1d2Zd3d4 Zd5d5ed6d7d(d8fd9ejd$eeejf d#ejd:ed;ed<ed=ed>eej d?ed%ee e!f fd@dAZ"dBejdCejdDejd%ejfdEdFZ#dGdH Z$d(S )MEDMEulerSchedulera  
    Implements the Euler scheduler in EDM formulation as presented in Karras et al. 2022 [1].

    [1] Karras, Tero, et al. "Elucidating the Design Space of Diffusion-Based Generative Models."
    https://arxiv.org/abs/2206.00364

    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:
        sigma_min (`float`, *optional*, defaults to 0.002):
            Minimum noise magnitude in the sigma schedule. This was set to 0.002 in the EDM paper [1]; a reasonable
            range is [0, 10].
        sigma_max (`float`, *optional*, defaults to 80.0):
            Maximum noise magnitude in the sigma schedule. This was set to 80.0 in the EDM paper [1]; a reasonable
            range is [0.2, 80.0].
        sigma_data (`float`, *optional*, defaults to 0.5):
            The standard deviation of the data distribution. This is set to 0.5 in the EDM paper [1].
        sigma_schedule (`str`, *optional*, defaults to `karras`):
            Sigma schedule to compute the `sigmas`. By default, we the schedule introduced in the EDM paper
            (https://arxiv.org/abs/2206.00364). Other acceptable value is "exponential". The exponential schedule was
            incorporated in this model: https://huggingface.co/stabilityai/cosxl.
        num_train_timesteps (`int`, defaults to 1000):
            The number of diffusion steps to train the model.
        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).
        rho (`float`, *optional*, defaults to 7.0):
            The rho parameter used for calculating the Karras sigma schedule, which is set to 7.0 in the EDM paper [1].
    r   Mb`?      T@      ?karras  epsilon      @	sigma_min	sigma_max
sigma_datasigma_schedulenum_train_timestepsprediction_typerhoc           
      C   s   |dvrt d|dd | _tdd|}|dkr | |}	n	|dkr)| |}	| |	| _t|	tj	d|	j
dg| _d	| _d | _d | _| jd
| _d S )N)r   exponentialz-Wrong value for provided for `sigma_schedule=z`.`r   r   r   r)   deviceFcpu)
ValueErrornum_inference_stepsr   linspace_compute_karras_sigmas_compute_exponential_sigmasprecondition_noise	timestepscatzerosr+   sigmasis_scale_input_called_step_index_begin_indexto)
selfr"   r#   r$   r%   r&   r'   r(   rampr6   r   r   r   __init__U   s   
zEDMEulerScheduler.__init__c                 C   s   | j jd d d S )Nr   r   r   )configr#   r;   r   r   r   init_noise_sigmav   s   z"EDMEulerScheduler.init_noise_sigmac                 C      | j S )zg
        The index counter for current timestep. It will increase 1 after each scheduler step.
        )r8   r?   r   r   r   
step_index{      zEDMEulerScheduler.step_indexc                 C   rA   )zq
        The index for the first timestep. It should be set from pipeline with `set_begin_index` method.
        r9   r?   r   r   r   begin_index   rC   zEDMEulerScheduler.begin_indexr   rE   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.
        NrD   )r;   rE   r   r   r   set_begin_index   s   
z!EDMEulerScheduler.set_begin_indexc                 C   s(   d|d | j jd  d  }|| }|S )Nr   r   r   )r>   r$   )r;   samplesigmac_inscaled_sampler   r   r   precondition_inputs   s   z%EDMEulerScheduler.precondition_inputsc                 C   s*   t |tjst|g}dt| }|S )Ng      ?)
isinstancer   r   tensorlog)r;   rH   c_noiser   r   r   r2      s   z$EDMEulerScheduler.precondition_noisec                 C   s   | j j}|d |d |d   }| j jdkr%|| |d |d  d  }n | j jdkr;| | |d |d  d  }n
td| j j d|| ||  }|S )Nr   r    r   v_predictionzPrediction type z is not supported.)r>   r$   r'   r-   )r;   rG   model_outputrH   r$   c_skipc_outdenoisedr   r   r   precondition_outputs   s    z&EDMEulerScheduler.precondition_outputsrG   timestepreturnc                 C   s6   | j du r
| | | j| j  }| ||}d| _|S )a   
        Ensures interchangeability with schedulers that need to scale the denoising model input depending on the
        current timestep. Scales the denoising model input by `(sigma**2 + 1) ** 0.5` to match the Euler algorithm.

        Args:
            sample (`torch.Tensor`):
                The input sample.
            timestep (`int`, *optional*):
                The current timestep in the diffusion chain.

        Returns:
            `torch.Tensor`:
                A scaled input sample.
        NT)rB   _init_step_indexr6   rK   r7   )r;   rG   rV   rH   r   r   r   scale_model_input   s   

z#EDMEulerScheduler.scale_model_inputNr.   r+   c                 C   s   || _ tdd| j }| jjdkr| |}n| jjdkr"| |}|jtj|d}| 	|| _
t|tjd|jdg| _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.
        r   r   r   r)   )dtyper+   r*   Nr,   )r.   r   r/   r>   r%   r0   r1   r:   float32r2   r3   r4   r5   r+   r6   r8   r9   )r;   r.   r+   r<   r6   r   r   r   set_timesteps   s   

zEDMEulerScheduler.set_timestepsc                 C   sP   |p| j j}|p| j j}| j j}|d|  }|d|  }||||   | }|S )z6Constructs the noise schedule of Karras et al. (2022).r   )r>   r"   r#   r(   )r;   r<   r"   r#   r(   min_inv_rhomax_inv_rhor6   r   r   r   r0      s   z(EDMEulerScheduler._compute_karras_sigmasc                 C   sD   |p| j j}|p| j j}tt|t|t| 	d}|S )zImplementation closely follows k-diffusion.

        https://github.com/crowsonkb/k-diffusion/blob/6ab5146d4a5ef63901326489f31f1d8e7dd36b48/k_diffusion/sampling.py#L26
        r   )
r>   r"   r#   r   r/   mathrN   lenexpflip)r;   r<   r"   r#   r6   r   r   r   r1      s   (z-EDMEulerScheduler._compute_exponential_sigmasc                 C   s:   |d u r| j }||k }t|dkrdnd}||  S )Nr   r   )r3   nonzeror`   item)r;   rV   schedule_timestepsindicesposr   r   r   index_for_timestep   s
   z$EDMEulerScheduler.index_for_timestepc                 C   s@   | j d u rt|tjr|| jj}| || _d S | j	| _d S N)
rE   rL   r   r   r:   r3   r+   rh   r8   r9   )r;   rV   r   r   r   rX     s
   
z"EDMEulerScheduler._init_step_index        infg      ?TrQ   s_churns_tmins_tmaxs_noise	generatorreturn_dictc
                 C   sD  t |ttjtjfrtd| jstd | j	du r | 
| |tj}| j| j	 }
||
  kr6|krDn nt|t| jd  dnd}t|j|j|j|d}|| }|
|d  }|dkrm|||d	 |
d	  d
   }| |||}|| | }| j| j	d  | }|||  }||j}|  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.
            s_churn (`float`):
            s_tmin  (`float`):
            s_tmax  (`float`):
            s_noise (`float`, defaults to 1.0):
                Scaling factor for noise added to the sample.
            generator (`torch.Generator`, *optional*):
                A random number generator.
            return_dict (`bool`):
                Whether or not to return a [`~schedulers.scheduling_euler_discrete.EDMEulerSchedulerOutput`] or tuple.

        Returns:
            [`~schedulers.scheduling_euler_discrete.EDMEulerSchedulerOutput`] or `tuple`:
                If return_dict is `True`, [`~schedulers.scheduling_euler_discrete.EDMEulerSchedulerOutput`] is
                returned, otherwise a tuple is returned where the first element is the sample tensor.
        zPassing integer indices (e.g. from `enumerate(timesteps)`) as timesteps to `EDMEulerScheduler.step()` is not supported. Make sure to pass one of the `scheduler.timesteps` as a timestep.zThe `scale_model_input` function should be called before `step` to ensure correct denoising. See `StableDiffusionPipeline` for a usage example.Nr   g4y?rj   )rZ   r+   rp   r   r   r   )r   r   )rL   intr   	IntTensor
LongTensorr-   r7   loggerwarningrB   rX   r:   r[   r6   minr`   r   shaperZ   r+   rU   r8   r   )r;   rQ   rV   rG   rl   rm   rn   ro   rp   rq   rH   gammanoiseeps	sigma_hatr   
derivativedtr   r   r   r   step  s:   '

4zEDMEulerScheduler.steporiginal_samplesrz   r3   c                    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)r+   rZ   mps)rZ   c                    s   g | ]} | qS r   )rh   ).0tre   r;   r   r   
<listcomp>  s    z/EDMEulerScheduler.add_noise.<locals>.<listcomp>r   )r6   r:   r+   rZ   typer   is_floating_pointr3   r[   rE   rB   rx   flattenr`   	unsqueeze)r;   r   rz   r3   r6   step_indicesrH   noisy_samplesr   r   r   	add_noisep  s"   


zEDMEulerScheduler.add_noisec                 C   s   | j jS ri   )r>   r&   r?   r   r   r   __len__  s   zEDMEulerScheduler.__len__)r   r   r   r   r   r    r!   )r   ri   )NN)%r   r   r   r   _compatiblesorderr   floatstrrr   r=   propertyr@   rB   rE   rF   rK   r2   rU   r   r   r   rY   r+   r\   r0   r1   rh   rX   r   	Generatorboolr   r   r   r   r   r   r   r   r   r   1   s      



$
	


`
!r   )r_   dataclassesr   typingr   r   r   r   configuration_utilsr   r   utilsr	   r
   utils.torch_utilsr   scheduling_utilsr   
get_loggerr   ru   r   r   r   r   r   r   <module>   s   
