o
    Gi+                     @   s   d dl mZ d dlZd dlmZ ddlmZmZ ddl	m
Z
 ddlmZmZmZmZmZ e
e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 )    )	dataclassN   )ConfigMixinregister_to_config)logging   )CommonSchedulerStateFlaxKarrasDiffusionSchedulersFlaxSchedulerMixinFlaxSchedulerOutputbroadcast_to_shape_from_leftc                	   @   sd   e Zd ZU eed< ejed< ejed< ejed< dZeed< e	dedejdejdejfddZ
dS )	EulerDiscreteSchedulerStatecommoninit_noise_sigma	timestepssigmasNnum_inference_stepsc                 C   s   | ||||dS )Nr   r   r   r    )clsr   r   r   r   r   r   g/home/ubuntu/.local/lib/python3.10/site-packages/diffusers/schedulers/scheduling_euler_discrete_flax.pycreate,   s   z"EulerDiscreteSchedulerState.create)__name__
__module____qualname__r   __annotations__jnpndarrayr   intclassmethodr   r   r   r   r   r   "   s    
 


r   c                   @   s   e Zd ZU eed< dS ) FlaxEulerDiscreteSchedulerOutputstateN)r   r   r   r   r   r   r   r   r   r    <   s   
 r    c                   @   s0  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dejfdededededejdB dededejfddZd1dedB defddZdedejdedejfddZ	 d2ded!ed"edefd#d$Z	%d3ded&ejdedejd'edeeB fd(d)Zded*ejd+ejd,ejdejf
d-d.Zd/d0 ZdS )4FlaxEulerDiscreteSchedulera  
    Euler scheduler (Algorithm 2) from Karras et al. (2022) https://huggingface.co/papers/2206.00364. . Based on the
    original k-diffusion implementation by Katherine Crowson:
    https://github.com/crowsonkb/k-diffusion/blob/481677d114f6ea445aa009cf5bd7a9cdee909e47/k_diffusion/sampling.py#L51


    [`~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://huggingface.co/papers/2210.02303)
        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>^   s    z%FlaxEulerDiscreteScheduler.<listcomp>dtypec                 C   s   dS )NTr   selfr   r   r   	has_stateb   s   z$FlaxEulerDiscreteScheduler.has_statei  g-C6?g{Gz?linearNepsilonlinspacenum_train_timesteps
beta_startbeta_endbeta_scheduletrained_betasprediction_typetimestep_spacingc	           	      C   s   t d || _d S )NzFlax classes are deprecated and will be removed in Diffusers v1.0.0. We recommend migrating to PyTorch classes or pinning your version of Diffusers.)loggerwarningr'   )	r)   r.   r/   r0   r1   r2   r3   r4   r'   r   r   r   __init__f   s   
z#FlaxEulerDiscreteScheduler.__init__r   returnc                 C   s   |d u r	t | }td| jj d d d }d|j |j d }t|tdt	||}t
|tjdg| jdg}| jjdv rH| }n
| d d d }tj||||d	S )
Nr   r         ?        r'   r-   trailingr   r   )r   r   r   arangeconfigr.   roundalphas_cumprodinterplenconcatenatearrayr'   r4   maxr   )r)   r   r   r   r   r   r   r   create_statex   s   

z'FlaxEulerDiscreteScheduler.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 Euler algorithm.

        Args:
            state (`EulerDiscreteSchedulerState`):
                the `FlaxEulerDiscreteScheduler` 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!   rI   rJ   
step_indexsigmar   r   r   scale_model_input   s
   
z,FlaxEulerDiscreteScheduler.scale_model_inputr   r   shapec                 C   s  | j jdkrtj| j jd d|| jd}n.| j jdkr:| j j| }td||  ddd  	t
}|d7 }n	td| j j d|jj |jj d	 }t|tdt||}t|tjd
g| jdg}| j jdv ru| }n
| d d d	 }|j||||dS )a  
        Sets the timesteps used for the diffusion chain. Supporting function to be run before inference.

        Args:
            state (`EulerDiscreteSchedulerState`):
                the `FlaxEulerDiscreteScheduler` state data class instance.
            num_inference_steps (`int`):
                the number of diffusion steps used when generating samples with a pre-trained model.
        r-   r   r   r<   leadingNr9   z=timestep_spacing must be one of ['linspace', 'leading'], got r:   r;   r=   r   )r   r   r   r   )r@   r4   r   r-   r.   r'   r?   rA   copyastypefloat
ValueErrorr   rB   rC   rD   rE   rF   rG   replace)r)   r!   r   rQ   r   
step_ratior   r   r   r   r   set_timesteps   s4   
(

z(FlaxEulerDiscreteScheduler.set_timestepsTmodel_outputreturn_dictc                 C   s   |j du r	tdtj|j|kdd\}|d }|j| }| jjdkr*|||  }n&| jjdkrF|| |d d d	   ||d d   }n
td
| jj d|| | }	|j|d  | }
||	|
  }|sk||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 (`EulerDiscreteSchedulerState`):
                the `FlaxEulerDiscreteScheduler` 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 FlaxEulerDiscreteScheduler class

        Returns:
            [`FlaxEulerDiscreteScheduler`] or `tuple`: [`FlaxEulerDiscreteScheduler`] 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 schedulerr   rK   r   r,   v_predictionr   r:   zprediction_type given as z, must be one of `epsilon`, or `v_prediction`)prev_sampler!   )	r   rV   r   rM   r   r   r@   r3   r    )r)   r!   rZ   rJ   rI   r[   rN   rO   pred_original_sample
derivativedtr]   r   r   r   step   s(   

,zFlaxEulerDiscreteScheduler.steporiginal_samplesnoiser   c                 C   s*   |j |  }t||j}|||  }|S N)r   flattenr   rQ   )r)   r!   rb   rc   r   rO   noisy_samplesr   r   r   	add_noise  s   z$FlaxEulerDiscreteScheduler.add_noisec                 C   s   | j jS rd   )r@   r.   r(   r   r   r   __len__   s   z"FlaxEulerDiscreteScheduler.__len__rd   )r   )T)r   r   r   __doc__r	   _compatiblesr   r'   r   propertyr*   r   float32r   rU   strr   r7   r   r   rH   rP   tuplerY   boolr    ra   rg   rh   r   r   r   r   r"   A   s   
 

	
7
=
r"   )dataclassesr   flax	jax.numpynumpyr   configuration_utilsr   r   utilsr   scheduling_utils_flaxr   r	   r
   r   r   
get_loggerr   r5   structr   r    r"   r   r   r   r   <module>   s   
	