o
    piE+                     @   s   d dl mZ d dlmZmZmZ d dlZd dlmZ	 d dl
mZ ddlmZmZ ddlmZmZmZmZmZ ejjG d	d
 d
ZeG dd deZG dd deeZdS )    )	dataclass)OptionalTupleUnionN)	integrate   )ConfigMixinregister_to_config   )CommonSchedulerStateFlaxKarrasDiffusionSchedulersFlaxSchedulerMixinFlaxSchedulerOutputbroadcast_to_shape_from_leftc                	   @   sz   e Zd ZU eed< ejed< ejed< ejed< dZee	 ed< dZ
eej ed< ededejdejdejfdd	ZdS )
LMSDiscreteSchedulerStatecommoninit_noise_sigma	timestepssigmasNnum_inference_stepsderivativesc                 C   s   | ||||dS )Nr   r   r   r    )clsr   r   r   r   r   r   o/home/ubuntu/SoloSpeech/.venv/lib/python3.10/site-packages/diffusers/schedulers/scheduling_lms_discrete_flax.pycreate-   s   z LMSDiscreteSchedulerState.create)__name__
__module____qualname__r   __annotations__jnpndarrayr   r   intr   classmethodr   r   r   r   r   r       s"   
 


r   c                   @   s   e Zd ZU eed< dS )FlaxLMSSchedulerOutputstateN)r   r   r   r   r   r   r   r   r   r$   4   s   
 r$   c                   @   sB  e Zd ZU dZdd eD Zejed< e	dd Z
eddd	d
ddejfdededededeej dedejfddZd3dee defddZdedejdedejfddZdefddZ	 d4ded!ed"edefd#d$Z	%	&d5ded'ejdedejd(ed)edeeef fd*d+Zded,ejd-ejd.ejdejf
d/d0Zd1d2 ZdS )6FlaxLMSDiscreteSchedulera  
    Linear Multistep Scheduler for discrete beta schedules. Based on the original k-diffusion implementation by
    Katherine Crowson:
    https://github.com/crowsonkb/k-diffusion/blob/481677d114f6ea445aa009cf5bd7a9cdee909e47/k_diffusion/sampling.py#L181

    [`~ConfigMixin`] takes care of storing all config attributes that are passed in the scheduler's `__init__`
    function, such as `num_train_timesteps`. They can be accessed via `scheduler.config.num_train_timesteps`.
    [`SchedulerMixin`] provides general loading and saving functionality via the [`SchedulerMixin.save_pretrained`] and
    [`~SchedulerMixin.from_pretrained`] functions.

    Args:
        num_train_timesteps (`int`): number of diffusion steps used to train the model.
        beta_start (`float`): the starting `beta` value of inference.
        beta_end (`float`): the final `beta` value.
        beta_schedule (`str`):
            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 (`jnp.ndarray`, optional):
            option to pass an array of betas directly to the constructor to bypass `beta_start`, `beta_end` etc.
        prediction_type (`str`, default `epsilon`, optional):
            prediction type of the scheduler function, one of `epsilon` (predicting the noise of the diffusion
            process), `sample` (directly predicting the noisy sample`) or `v_prediction` (see section 2.4
            https://imagen.research.google/video/paper.pdf)
        dtype (`jnp.dtype`, *optional*, defaults to `jnp.float32`):
            the `dtype` used for params and computation.
    c                 C   s   g | ]}|j qS r   )name).0er   r   r   
<listcomp>U   s    z#FlaxLMSDiscreteScheduler.<listcomp>dtypec                 C   s   dS )NTr   selfr   r   r   	has_stateY   s   z"FlaxLMSDiscreteScheduler.has_statei  -C6?g{Gz?linearNepsilonnum_train_timesteps
beta_startbeta_endbeta_scheduletrained_betasprediction_typec                 C   s
   || _ d S Nr+   )r-   r2   r3   r4   r5   r6   r7   r+   r   r   r   __init__]   s   
z!FlaxLMSDiscreteScheduler.__init__r   returnc                 C   s^   |d u r	t | }td| jj d d d }d|j |j d }| }t	j||||dS )Nr   r
         ?r   )
r   r   r    arangeconfigr2   roundalphas_cumprodmaxr   )r-   r   r   r   r   r   r   r   create_statej   s   
z%FlaxLMSDiscreteScheduler.create_stater%   sampletimestepc                 C   s@   t j|j|kdd\}|d }|j| }||d d d  }|S )a	  
        Scales the denoising model input by `(sigma**2 + 1) ** 0.5` to match the K-LMS algorithm.

        Args:
            state (`LMSDiscreteSchedulerState`):
                the `FlaxLMSDiscreteScheduler` state data class instance.
            sample (`jnp.ndarray`):
                current instance of sample being created by diffusion process.
            timestep (`int`):
                current discrete timestep in the diffusion chain.

        Returns:
            `jnp.ndarray`: scaled input sample
        r
   )sizer   r   r=   )r    wherer   r   )r-   r%   rD   rE   
step_indexsigmar   r   r   scale_model_input{   s
   
z*FlaxLMSDiscreteScheduler.scale_model_inputc                    s<    fdd}t j|j jd  ddd }|S )z
        Compute a linear multistep coefficient.

        Args:
            order (TODO):
            t (TODO):
            current_order (TODO):
        c                    sR   d}t D ] } |krq|| j|   j   j|    9 }q|S )N      ?)ranger   )tauprodkcurrent_orderorderr%   tr   r   lms_derivative   s   4zDFlaxLMSDiscreteScheduler.get_lms_coefficient.<locals>.lms_derivativer
   r/   )epsrelr   )r   quadr   )r-   r%   rR   rS   rQ   rT   integrated_coeffr   rP   r   get_lms_coefficient   s   
&z,FlaxLMSDiscreteScheduler.get_lms_coefficientr   r   shapec           
      C   s   t j| jjd d|| jd}t |t j}t |t j}t 	|d}d|j
j |j
j d }d| ||  |||   }t |t jdg| jdg}|t j}t jd| | jd}	|j||||	dS )	a  
        Sets the timesteps used for the diffusion chain. Supporting function to be run before inference.

        Args:
            state (`LMSDiscreteSchedulerState`):
                the `FlaxLMSDiscreteScheduler` state data class instance.
            num_inference_steps (`int`):
                the number of diffusion steps used when generating samples with a pre-trained model.
        r
   r   r9   rK   r=   g        )r   )r   r   r   r   )r    linspacer?   r2   r+   floorastypeint32ceilmodr   rA   concatenatearrayzerosreplace)
r-   r%   r   rY   r   low_idxhigh_idxfracr   r   r   r   r   set_timesteps   s   z&FlaxLMSDiscreteScheduler.set_timesteps   Tmodel_outputrR   return_dictc                    s,  j du r	tdj }jjdkr|||  }n&jjdkr7|| |d d d   ||d d   }n
tdjj d	|| | }	jtj|	d
t	j krdjt
jdd
td    fddt D }
|tdd t|
tjD  }|s|fS t|dS )a  
        Predict the sample at the previous timestep by reversing the SDE. Core function to propagate the diffusion
        process from the learned model outputs (most often the predicted noise).

        Args:
            state (`LMSDiscreteSchedulerState`): the `FlaxLMSDiscreteScheduler` state data class instance.
            model_output (`jnp.ndarray`): direct output from learned diffusion model.
            timestep (`int`): current discrete timestep in the diffusion chain.
            sample (`jnp.ndarray`):
                current instance of sample being created by diffusion process.
            order: coefficient for multi-step inference.
            return_dict (`bool`): option for returning tuple rather than FlaxLMSSchedulerOutput class

        Returns:
            [`FlaxLMSSchedulerOutput`] or `tuple`: [`FlaxLMSSchedulerOutput`] if `return_dict` is True, otherwise a
            `tuple`. When returning a tuple, the first element is the sample tensor.

        NzaNumber of inference steps is 'None', you need to run 'set_timesteps' after creating the schedulerr1   v_predictionr   r
   r=   zprediction_type given as z, must be one of `epsilon`, or `v_prediction`)r   r   c                    s   g | ]
}  |qS r   )rX   )r(   
curr_orderrR   r-   r%   rE   r   r   r*      s    z1FlaxLMSDiscreteScheduler.step.<locals>.<listcomp>c                 s   s    | ]	\}}|| V  qd S r8   r   )r(   coeff
derivativer   r   r   	<genexpr>  s    
z0FlaxLMSDiscreteScheduler.step.<locals>.<genexpr>)prev_sampler%   )r   
ValueErrorr   r?   r7   rc   r    appendr   lendeleteminrL   sumzipreversedr$   )r-   r%   ri   rE   rD   rR   rj   rI   pred_original_samplero   
lms_coeffsrq   r   rm   r   step   s0   

,

zFlaxLMSDiscreteScheduler.steporiginal_samplesnoiser   c                 C   s*   |j |  }t||j}|||  }|S r8   )r   flattenr   rY   )r-   r%   r}   r~   r   rI   noisy_samplesr   r   r   	add_noise  s   z"FlaxLMSDiscreteScheduler.add_noisec                 C   s   | j jS r8   )r?   r2   r,   r   r   r   __len__  s   z FlaxLMSDiscreteScheduler.__len__r8   )r   )rh   T) r   r   r   __doc__r   _compatiblesr    r+   r   propertyr.   r	   float32r"   floatstrr   r!   r:   r   r   rC   rJ   rX   r   rg   boolr   r$   r|   r   r   r   r   r   r   r&   9   s   
 


*

A
r&   )dataclassesr   typingr   r   r   flax	jax.numpynumpyr    scipyr   configuration_utilsr   r	   scheduling_utils_flaxr   r   r   r   r   structr   r$   r&   r   r   r   r   <module>   s   	