
    bi3T                         d dl mZ d dlmZmZmZ d dlZd dl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	             Ze G d
 de             Z G d dee      Zy)    )	dataclass)OptionalTupleUnionN   )ConfigMixinregister_to_config   )CommonSchedulerStateFlaxKarrasDiffusionSchedulersFlaxSchedulerMixinFlaxSchedulerOutputadd_noise_commonc            	          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<   dZeej                     ed<   dZeej                     ed	<   dZeej                     ed
<   dZeej                     ed<   dZeej                     ed<   ededej                  dej                  dej                  fd       Zy)PNDMSchedulerStatecommonfinal_alpha_cumprodinit_noise_sigma	timestepsNnum_inference_stepsprk_timestepsplms_timestepscur_model_outputcounter
cur_sampleetsc                      | ||||      S )Nr   r   r   r    )clsr   r   r   r   s        d/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/diffusers/schedulers/scheduling_pndm_flax.pycreatezPNDMSchedulerState.create4   s      3-	
 	
    )__name__
__module____qualname__r   __annotations__jnpndarrayr   r   intr   r   r   r   int32r   r   classmethodr"   r   r#   r!   r   r   "   s      $ kk!{{)-#-+/M8CKK(/,0NHS[[)0 /3hs{{+2#'GXcii '(,J%,!%C#++	%
$
 ![[
 ++	

 ;;
 
r#   r   c                       e Zd ZU eed<   y)FlaxPNDMSchedulerOutputstateN)r$   r%   r&   r   r'   r   r#   r!   r.   r.   D   s    r#   r.   c                   
   e Zd ZU dZeD  cg c]  }|j
                   c}} Zej                  e	d<   e
e	d<   ed        Zeddd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de
dedej                  fd       Zd,dee   defdZdede
dedefdZ	 d,dedej$                  dee
   dej$                  fd Z	 d-ded!ej$                  de
dej$                  d"edeeef   fd#Zded!ej$                  de
dej$                  deeef   f
d$Zded!ej$                  de
dej$                  deeef   f
d%Zdefd&Z ded'ej$                  d(ej$                  d)ej$                  dej$                  f
d*Z!d+ Z"y	c c}} w ).FlaxPNDMSchedulerab	  
    Pseudo numerical methods for diffusion models (PNDM) proposes using more advanced ODE integration techniques,
    namely Runge-Kutta method and a linear multi-step method.

    [`~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.

    For more details, see the original paper: https://huggingface.co/papers/2202.09778

    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`, `scaled_linear`, or `squaredcos_cap_v2`.
        trained_betas (`jnp.ndarray`, optional):
            option to pass an array of betas directly to the constructor to bypass `beta_start`, `beta_end` etc.
        skip_prk_steps (`bool`):
            allows the scheduler to skip the Runge-Kutta steps that are defined in the original paper as being required
            before plms steps; defaults to `False`.
        set_alpha_to_one (`bool`, default `False`):
            each diffusion step uses the value of alphas product at that step and at the previous one. For the final
            step there is no previous alpha. When this option is `True` the previous alpha product is fixed to `1`,
            otherwise it uses the value of alpha at step 0.
        steps_offset (`int`, default `0`):
            An offset added to the inference steps, as required by some model families.
        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.
    dtype
pndm_orderc                      y)NTr   selfs    r!   	has_statezFlaxPNDMScheduler.has_statet   s    r#   i  g-C6?g{Gz?linearNFr   epsilonnum_train_timesteps
beta_startbeta_endbeta_scheduletrained_betasskip_prk_stepsset_alpha_to_onesteps_offsetprediction_typec                      |
| _         d| _        y )N   )r2   r3   )r6   r:   r;   r<   r=   r>   r?   r@   rA   rB   r2   s              r!   __init__zFlaxPNDMScheduler.__init__x   s     

 r#   r   returnc                    |t        j                  |       }| j                  j                  r!t	        j
                  d| j                        n|j                  d   }t	        j
                  d| j                        }t	        j                  d| j                  j                        j                         d d d   }t        j                  ||||      S )Ng      ?r2   r   r   )r   r"   configr@   r(   arrayr2   alphas_cumprodaranger:   roundr   )r6   r   r   r   r   s        r!   create_statezFlaxPNDMScheduler.create_state   s    >)006F 150L0LCIIc,RXRgRghiRj 	
 99S

;JJq$++"A"ABHHJ4R4P	!(( 3-	 ) 
 	
r#   r/   r   shapec           
         | j                   j                  |z  }t        j                  d|      |z  j	                         | j                   j
                  z   }| j                   j                  rMt        j                  g t        j                        }t        j                  |dd |dd |dd g      ddd   }n|| j                   d j                  d      t        j                  t        j                  d| j                   j                  |z  dz  gt        j                        | j                        z   }|dd j                  d      dd ddd   }|dd ddd   }t        j                  ||g      }t        j                  || j                        }	t        j                  d      }
t        j                  || j                        }t        j                  d	|z   | j                        }|j                  |||||	|
||
      S )a  
        Sets the discrete timesteps used for the diffusion chain. Supporting function to be run before inference.

        Args:
            state (`PNDMSchedulerState`):
                the `FlaxPNDMScheduler` state data class instance.
            num_inference_steps (`int`):
                the number of diffusion steps used when generating samples with a pre-trained model.
            shape (`Tuple`):
                the shape of the samples to be generated.
        r   rH   NrI   r   r
   )rD   )r   r   r   r   r   r   r   r   )rJ   r:   r(   rM   rN   rA   r?   rK   r+   concatenater3   repeattilezerosr2   replace)r6   r/   r   rP   
step_ratio
_timestepsr   r   r   r   r   r   r   s                r!   set_timestepszFlaxPNDMScheduler.set_timesteps   s    [[448KK
 jj$78:ELLNQUQ\Q\QiQii
;;%%
  IIb		:M __j"oz"R?PR\]_]`Ra-bcdhfhdhiN ''7'9:AA!Dsxx		1dkk==ATTXYYZbebkbklH M
 +3B/66q9!B?2FM'_TrT2NOO]N$CD	 99U$**=))A,YYuDJJ7
iiuDJJ7}} 3')-!  	
 		
r#   sampletimestepc                     |S )a  
        Ensures interchangeability with schedulers that need to scale the denoising model input depending on the
        current timestep.

        Args:
            state (`PNDMSchedulerState`): the `FlaxPNDMScheduler` state data class instance.
            sample (`jnp.ndarray`): input sample
            timestep (`int`, optional): current timestep

        Returns:
            `jnp.ndarray`: scaled input sample
        r   )r6   r/   r\   r]   s       r!   scale_model_inputz#FlaxPNDMScheduler.scale_model_input   s	     r#   model_outputreturn_dictc           
      X   |j                   t        d      | j                  j                  r| j	                  ||||      \  }}nR| j                  ||||      \  }}| j	                  ||||      \  }	}
|j                  t        |j                        k  }t        j                  j                  |||	      }|j                  t        j                  j                  ||j                  |
j                        t        j                  j                  ||j                  |
j                        t        j                  j                  ||j                  |
j                        t        j                  j                  ||j                  |
j                              }|s||fS t!        ||      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).

        This function calls `step_prk()` or `step_plms()` depending on the internal variable `counter`.

        Args:
            state (`PNDMSchedulerState`): the `FlaxPNDMScheduler` 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.
            return_dict (`bool`): option for returning tuple rather than FlaxPNDMSchedulerOutput class

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

        aNumber of inference steps is 'None', you need to run 'set_timesteps' after creating the scheduler)r   r   r   r   )prev_sampler/   )r   
ValueErrorrJ   r?   	step_plmsstep_prkr   lenr   jaxlaxselectrX   r   r   r   r.   )r6   r/   r`   r]   r\   ra   rd   prk_prev_sample	prk_stateplms_prev_sample
plms_stateconds               r!   stepzFlaxPNDMScheduler.step   sZ   8 $$,s  ;;%%!%|Xv!VK)-ulHV\)]&OY+/>>%xY_+`(j==3u':':#;;D''..@PQKMM!$i6P6PR\RmRm!nGGNN4
G77>>$	0D0DjF[F[\tY->->
@R@RS	 " E ''&;eLLr#   c                    |j                   t        d      t        j                  |j                  dz  d| j
                  j                  |j                   z  dz        }||z
  }|j                  |j                  dz  dz     }t        j                  j                  |j                  dz  dk7  ||j                  d|z  z         }|j                  t        j                  j                  |j                  dz  |j                  d|z  z   |j                  d|z  z   |j                  d|z  z   t        j                  |j                              t        j                  j                  |j                  dz  dk(  |j                  j                   dd j#                  |j                  dd       j                   d   j#                  |      |j                        t        j                  j                  |j                  dz  dk(  ||j$                        	      }|j$                  }| j'                  |||||      }|j                  |j                  dz   
      }||fS )ay  
        Step function propagating the sample with the Runge-Kutta method. RK takes 4 forward passes to approximate the
        solution to the differential equation.

        Args:
            state (`PNDMSchedulerState`): the `FlaxPNDMScheduler` 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.
            return_dict (`bool`): option for returning tuple rather than FlaxPNDMSchedulerOutput class

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

        rc   r   r   rD      gUUUUUU?gUUUUUU?r
   )r   r   r   r   )r   re   r(   wherer   rJ   r:   r   ri   rj   rk   r   rX   select_n
zeros_liker   atsetr   _get_prev_sample)	r6   r/   r`   r]   r\   diff_to_prevprev_timestepr   rd   s	            r!   rg   zFlaxPNDMScheduler.step_prk$  s   2 $$,s  yyMMAq$++"A"AUE^E^"^bc"c
 !</&&u}}'9A'=>ww~~]]Q1$""U\%99
  WW--!&&)==&&)==&&)==u556 "q(		Qq!%%eii!n588;??M		
 ww~~"q(    
( %%
++E:xXdeemma&78U##r#   c                    |j                   t        d      || j                  j                  |j                   z  z
  }t	        j
                  |dkD  |d      }t	        j
                  |j                  dk(  ||      }t	        j
                  |j                  dk(  || j                  j                  |j                   z  z   |      }|j                  t        j                  j                  |j                  dk7  |j                  j                  dd j                  |j                  dd       j                  d   j                  |      |j                        t        j                  j                  |j                  dk7  ||j                              }|j                  t        j                  j                  t	        j                   |j                  dd      |||j                  d   z   dz  d|j                  d   z  |j                  d	   z
  dz  d
|j                  d   z  d|j                  d	   z  z
  d|j                  d   z  z   dz  dd|j                  d   z  d|j                  d	   z  z
  d|j                  d   z  z   d|j                  d   z  z
  z              }|j                  }|j"                  }| j%                  |||||      }|j                  |j                  dz         }||fS )av  
        Step function propagating the sample with the linear multi-step method. This has one forward pass with multiple
        times to approximate the solution.

        Args:
            state (`PNDMSchedulerState`): the `FlaxPNDMScheduler` 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.
            return_dict (`bool`): option for returning tuple rather than FlaxPNDMSchedulerOutput class

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

        rc   r   r
   rs   rD   )r   r   rI   r   rR            rS      gUUUUUU?7   ;   %   	   )r   rt   )r   re   rJ   r:   r(   ru   r   rX   ri   rj   rk   r   rx   ry   r   rv   clipr   rz   )r6   r/   r`   r]   r\   r|   rd   s          r!   rf   zFlaxPNDMScheduler.step_plmsh  s   2 $$,s  !4;;#B#BeF_F_#__		-!"3]AF 		%--1"4hN99MMQ4;;+J+JeNgNg+g giq
& "		Qq!%%eii!n588;??M		
 ww~~"    
  WW--1-		"-2UYYr]"UYYr]2a7eiim#b599R=&881uyy};LLPRR		"%UYYr](::R%))B-=OORSV[V_V_`bVcRcce  

 !!--++E68]T`aemma&78U##r#   c                    |j                   j                  |   }t        j                  |dk\  |j                   j                  |   |j                        }d|z
  }d|z
  }	| j
                  j                  dk(  r|dz  |z  |dz  |z  z   }n<| j
                  j                  dk7  r#t        d| j
                  j                   d      ||z  dz  }
||	dz  z  ||z  |z  dz  z   }|
|z  ||z
  |z  |z  z
  }|S )Nr   r
   v_predictiong      ?r9   zprediction_type given as z+ must be one of `epsilon` or `v_prediction`)r   rL   r(   ru   r   rJ   rB   re   )r6   r/   r\   r]   r|   r`   alpha_prod_talpha_prod_t_prevbeta_prod_tbeta_prod_t_prevsample_coeffmodel_output_denom_coeffrd   s                r!   rz   z"FlaxPNDMScheduler._get_prev_sample  s5    ||228<IIQ ; ;M JELeLe
 ,&00;;&&.8(#-=cAQU[@[[L[[((I5+DKK,G,G+HHst  *L8cB $02Bs2K#K;&)::O $  6!%6%E$UXp$pp 	 r#   original_samplesnoiser   c                 2    t        |j                  |||      S N)r   r   )r6   r/   r   r   r   s        r!   	add_noisezFlaxPNDMScheduler.add_noise  s      .>yQQr#   c                 .    | j                   j                  S r   )rJ   r:   r5   s    r!   __len__zFlaxPNDMScheduler.__len__  s    {{...r#   r   )T)#r$   r%   r&   __doc__r   name_compatiblesr(   r2   r'   r*   propertyr7   r	   float32floatstrr   r)   boolrE   r   r   rO   r   r[   r_   r   r.   rq   rg   rf   rz   r   r   ).0es   00r!   r1   r1   I   s   #J %BBqAFFBL99O   $("%/3$!&(;;   	
   ,     yy (
8,@#A 
M_ 
05
#5 5
C 5
X] 5
bt 5
p Y]'14HPQT	. !5M!5M kk5M 	5M
 5M 5M 
&-	.5MnB$!B$ kkB$ 	B$
 B$ 
&-	.B$H\$!\$ kk\$ 	\$
 \$ 
&-	.\$|+&8 +ZR!R ++R {{	R
 ;;R 
R/[ Cs   E?r1   )dataclassesr   typingr   r   r   flaxri   	jax.numpynumpyr(   configuration_utilsr   r	   scheduling_utils_flaxr   r   r   r   r   structr   r.   r1   r   r#   r!   <module>r      sw   " " ) )  
  A  
 
 
B 1  t/*K t/r#   