
    bi,L                         d dl Z d dlmZ d dlmZ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j&                  e      Ze G d
 de             Z G d dee
      Zy)    N)	dataclass)ListOptionalTupleUnion   )ConfigMixinregister_to_config)
BaseOutputlogging)randn_tensor   )SchedulerMixinc                   X    e Zd ZU dZej
                  ed<   dZeej
                     ed<   y)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        d/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/diffusers/schedulers/scheduling_edm_euler.pyr   r      s'    
 37(5<<07r   r   c                      e Zd ZdZg ZdZe	 	 	 	 	 	 	 	 d4dedededede	ded	ed
efd       Z
ed        Zed        Zed        Zd5de	fdZd Zd Zd Zdej(                  deeej(                  f   dej(                  fdZ	 	 	 d6de	deeej.                  f   deeej(                  ee   f      fdZd7dej(                  fdZd7dej(                  fdZd8dZd  Zd!d! ed"      d#dd$dfd%e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j(                     dee!e"f   fd-Z#d.ej(                  d/ej(                  d0ej(                  dej(                  fd1Z$d2 Z%d3 Z&y)9EDMEulerSchedulera5	  
    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://huggingface.co/papers/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://huggingface.co/papers/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].
        final_sigmas_type (`str`, defaults to `"zero"`):
            The final `sigma` value for the noise schedule during the sampling process. If `"sigma_min"`, the final
            sigma is the same as the last sigma in the training schedule. If `zero`, the final sigma is set to 0.
    r   	sigma_min	sigma_max
sigma_datasigma_schedulenum_train_timestepsprediction_typerhofinal_sigmas_typec	                 b   |dvrt        d|d      d | _        t        j                  j                  j                         rt        j                  nt        j                  }	t        j                  |dz   |	      |z  }
|dk(  r| j                  |
      }
n|dk(  r| j                  |
      }
|
j                  t        j                        }
| j                  |
      | _        | j                  j                  dk(  r|
d	   }n>| j                  j                  d
k(  rd}n"t        d| j                  j                         t        j                   |
t        j"                  d||
j$                        g      | _        d| _        d | _        d | _        | j&                  j                  d      | _        y )N)karrasexponentialz-Wrong value for provided for `sigma_schedule=z`.`r   dtyper)   r*   r    zeror   C`final_sigmas_type` must be one of 'zero', or 'sigma_min', but got r   
fill_valuedeviceFcpu)
ValueErrornum_inference_stepsr   backendsmpsis_availablefloat32float64arange_compute_karras_sigmas_compute_exponential_sigmastoprecondition_noise	timestepsconfigr'   catfullr3   sigmasis_scale_input_called_step_index_begin_index)selfr    r!   r"   r#   r$   r%   r&   r'   sigmas_dtyperE   
sigma_lasts               r   __init__zEDMEulerScheduler.__init__X   so    !::Mn=NcRSS $( (-(:(:(G(G(Iu}}u}}1A5\JM``X%008F},55f=F5==)008;;((K7J[[**f4JUVZVaVaVsVsUtu  iiDZX^XeXe)f gh%*" kknnU+r   c                 @    | j                   j                  dz  dz   dz  S )Nr   r         ?)rB   r!   rI   s    r   init_noise_sigmaz"EDMEulerScheduler.init_noise_sigma   s#     %%q(1,44r   c                     | j                   S )zg
        The index counter for current timestep. It will increase 1 after each scheduler step.
        )rG   rO   s    r   
step_indexzEDMEulerScheduler.step_index   s    
 r   c                     | j                   S )zq
        The index for the first timestep. It should be set from pipeline with `set_begin_index` method.
        rH   rO   s    r   begin_indexzEDMEulerScheduler.begin_index   s    
    r   rU   c                     || _         y)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.
        NrT   )rI   rU   s     r   set_begin_indexz!EDMEulerScheduler.set_begin_index   s     (r   c                 2    | j                  |      }||z  }|S N)_get_conditioning_c_in)rI   samplesigmac_inscaled_samples        r   precondition_inputsz%EDMEulerScheduler.precondition_inputs   s!    **51r   c                     t        |t        j                        st        j                  |g      }dt        j                  |      z  }|S )Ng      ?)
isinstancer   r   tensorlog)rI   r\   c_noises      r   r@   z$EDMEulerScheduler.precondition_noise   s8    %.LL%)E5))r   c                 j   | j                   j                  }|dz  |dz  |dz  z   z  }| j                   j                  dk(  r||z  |dz  |dz  z   dz  z  }nR| j                   j                  dk(  r| |z  |dz  |dz  z   dz  z  }n#t        d| j                   j                   d      ||z  ||z  z   }|S )Nr   epsilonrN   v_predictionzPrediction type z is not supported.)rB   r"   r%   r5   )rI   r[   model_outputr\   r"   c_skipc_outdenoiseds           r   precondition_outputsz&EDMEulerScheduler.precondition_outputs   s    [[++
Q%(Z]":;;;&&)3J&%(Z]*Bs)JJE[[((N:FZ'5!8j!m+C*KKE/0K0K/LL^_``F?U\%99r   r[   timestepreturnc                     | j                   | j                  |       | j                  | 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.
        T)rR   _init_step_indexrE   r_   rF   )rI   r[   rm   r\   s       r   scale_model_inputz#EDMEulerScheduler.scale_model_input   sM     ??"!!(+DOO,))&%8%)"r   Nr6   r3   rE   c                    || _         t        j                  j                  j	                         rt        j
                  nt        j                  }|$t        j                  dd| j                   |      }n9t        |t              rt        j                  ||      }n|j                  |      }| j                  j                  dk(  r| j                  |      }n*| j                  j                  dk(  r| j                  |      }|j                  t        j
                  |      }| j!                  |      | _        | j                  j$                  dk(  r|d	   }n>| j                  j$                  d
k(  rd}n"t'        d| j                  j$                         t        j(                  |t        j*                  d||j,                        g      | _        d| _        d| _        | j.                  j                  d      | _        y)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.
            sigmas (`Union[torch.Tensor, List[float]]`, *optional*):
                Custom sigmas to use for the denoising process. If not defined, the default behavior when
                `num_inference_steps` is passed will be used.
        Nr   r   r+   r)   r*   )r,   r3   r    r-   r.   r/   r0   r1   r4   )r6   r   r7   r8   r9   r:   r;   linspacera   floatrb   r?   rB   r#   r=   r>   r@   rA   r'   r5   rC   rD   r3   rE   rG   rH   )rI   r6   r3   rE   rJ   rK   s         r   set_timestepszEDMEulerScheduler.set_timesteps   s   $ $7 (-(:(:(G(G(Iu}}u}}>^^Aq$*B*B,WF&\\&=FYY|,F;;%%1008F[[''=855f=Fv>008;;((K7J[[**f4JUVZVaVaVsVsUtu  iiDZX^XeXe)f gh kknnU+r   c                     |xs | j                   j                  }|xs | j                   j                  }| j                   j                  }|d|z  z  }|d|z  z  }||||z
  z  z   |z  }|S )z6Constructs the noise schedule of Karras et al. (2022).r   )rB   r    r!   r&   )rI   rampr    r!   r&   min_inv_rhomax_inv_rhorE   s           r   r=   z(EDMEulerScheduler._compute_karras_sigmas	  sq    6!6!6	6!6!6	kkooAG,AG,k(A BBsJr   c                 4   |xs | j                   j                  }|xs | j                   j                  }t        j                  t        j                  |      t        j                  |      t        |            j                         j                  d      }|S )zImplementation closely follows k-diffusion.

        https://github.com/crowsonkb/k-diffusion/blob/6ab5146d4a5ef63901326489f31f1d8e7dd36b48/k_diffusion/sampling.py#L26
        r   )
rB   r    r!   r   rs   mathrc   lenexpflip)rI   rw   r    r!   rE   s        r   r>   z-EDMEulerScheduler._compute_exponential_sigmas  sn    
 6!6!6	6!6!6	 3TXXi5H#d)TXXZ__`abr   c                     || j                   }||k(  j                         }t        |      dkD  rdnd}||   j                         S )Nr   r   )rA   nonzeror|   item)rI   rm   schedule_timestepsindicesposs        r   index_for_timestepz$EDMEulerScheduler.index_for_timestep  sL    %!%%1::< w<!#as|  ""r   c                     | j                   Vt        |t        j                        r%|j	                  | j
                  j                        }| j                  |      | _        y | j                  | _        y rY   )
rU   ra   r   r   r?   rA   r3   r   rG   rH   )rI   rm   s     r   rp   z"EDMEulerScheduler._init_step_index.  sU    #(ELL1#;;t~~'<'<=#66x@D#00Dr           infg      ?Trh   s_churns_tmins_tmaxs_noise	generatorreturn_dictr   c                    t        |t        t        j                  t        j                  f      rt        d      | j                  st        j                  d       | j                  | j                  |       |j                  t        j                        }| j                  | j                     }||cxk  r|k  r(n n%t        |t        | j                        dz
  z  d      nd}||dz   z  }|dkD  rFt!        |j"                  |j$                  |j&                  |      }||z  }|||dz  |dz  z
  d	z  z  z   }|
| j)                  |||      }
||
z
  |z  }| j                  | j                  dz      |z
  }|||z  z   }|j                  |j$                        }| xj*                  dz  c_        |	s||
fS t-        ||

      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.r   g4y?r   r   )r,   r3   r   r   rN   )r   r   )ra   intr   	IntTensor
LongTensorr5   rF   loggerwarningrR   rp   r?   r:   rE   minr|   r   shaper,   r3   rl   rG   r   )rI   rh   rm   r[   r   r   r   r   r   r   r   r\   gamma	sigma_hatnoiseeps
derivativedtr   s                      r   stepzEDMEulerScheduler.step6  s   P heoou7G7G HIG  ))NNE
 ??"!!(+ 5==)DOO,EKuE^X^E^Gs4;;/!34jAdgUQY'	19 "",*<*<\EXEXdmE '/CcY\E1H%<$DDDF  '#'#<#<V\S\#]  33y@
[[1,-	9zB. "nn\%7%78 	A$ 
 ';Uijjr   original_samplesr   rA   c                    | j                   j                  |j                  |j                        }|j                  j                  dk(  rvt        j                  |      ra| j                  j                  |j                  t
        j                        }|j                  |j                  t
        j                        }n@| j                  j                  |j                        }|j                  |j                        }| j                   |D cg c]  }| j                  ||       }}nG| j                  | j                  g|j                  d   z  }n| j                  g|j                  d   z  }||   j                         }t        |j                        t        |j                        k  r=|j                  d      }t        |j                        t        |j                        k  r=|||z  z   }	|	S c c}w )N)r3   r,   r8   r+   r   r-   )rE   r?   r3   r,   typer   is_floating_pointrA   r:   rU   r   rR   r   flattenr|   	unsqueeze)
rI   r   r   rA   rE   r   tstep_indicesr\   noisy_sampless
             r   	add_noisezEDMEulerScheduler.add_noise  s    '7'>'>FVF\F\]""''50U5L5LY5W!%!2!23C3J3JRWR_R_!2!`!%5%<%<EMMRI!%!2!23C3J3J!K!%5%<%<=I #T]^qD33A7IJ^L^__( OO,yq/AAL !,,-	0BBL|$,,.%++%5%;%;!<<OOB'E %++%5%;%;!<< )55=8 _s   G9c                 P    d|dz  | j                   j                  dz  z   dz  z  }|S )Nr   r   rN   )rB   r"   )rI   r\   r]   s      r   rZ   z(EDMEulerScheduler._get_conditioning_c_in  s.    UAX 6 6 99cABr   c                 .    | j                   j                  S rY   )rB   r$   rO   s    r   __len__zEDMEulerScheduler.__len__  s    {{...r   )gMb`?g      T@rN   r)   i  rf   g      @r.   )r   )NNN)NNrY   )'r   r   r   r   _compatiblesorderr
   rt   strr   rL   propertyrP   rR   rU   rW   r_   r@   rl   r   r   r   rq   r3   r   r   ru   r=   r>   r   rp   	Generatorboolr   r   r   r   rZ   r   r   r   r   r   r   1   s   !F LE !&#'(!'*,*, *, 	*,
 *, !*, *, *, *, *,X 5 5     ! !(3 (
 eU\\FY@Z _d_k_k 4 $(+/=A	/, /, c5<<'(/, u||T%[89:	/,d	ell 	SXS_S_ #1 e/3 7;akllak u||+,ak 	ak
 ak ak ak ak EOO,ak ak 'u||4ak 
&-	.akH,, || <<	
 
B/r   r   )r{   dataclassesr   typingr   r   r   r   r   configuration_utilsr	   r
   utilsr   r   utils.torch_utilsr   scheduling_utilsr   
get_loggerr   r   r   r   r   r   r   <module>r      sa     ! / /  A ' , , 
		H	% 8j 8 8"O/ O/r   