
    bi4_                         d dl Z 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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 e G d
 de             Z	 	 ddZ G d dee      Zy)    N)	dataclass)ListOptionalTupleUnion)	integrate   )ConfigMixinregister_to_config)
BaseOutput   )KarrasDiffusionSchedulersSchedulerMixinc                   X    e Zd ZU dZej
                  ed<   dZeej
                     ed<   y)LMSDiscreteSchedulerOutputaq  
    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        g/home/cdr/jupyterlab/.venv/lib/python3.12/site-packages/diffusers/schedulers/scheduling_lms_discrete.pyr   r      s'    
 37(5<<07r   r   c           
      $   |dk(  rd }n|dk(  rd }nt        d|       g }t        |       D ]<  }|| z  }|dz   | z  }|j                  t        d ||       ||      z  z
  |             > t	        j
                  |t        j                        S )a  
    Create a beta schedule that discretizes the given alpha_t_bar function, which defines the cumulative product of
    (1-beta) over time from t = [0,1].

    Contains a function alpha_bar that takes an argument t and transforms it to the cumulative product of (1-beta) up
    to that part of the diffusion process.


    Args:
        num_diffusion_timesteps (`int`): the number of betas to produce.
        max_beta (`float`): the maximum beta to use; use values lower than 1 to
                     prevent singularities.
        alpha_transform_type (`str`, *optional*, default to `cosine`): the type of noise schedule for alpha_bar.
                     Choose from `cosine` or `exp`

    Returns:
        betas (`np.ndarray`): the betas used by the scheduler to step the model outputs
    cosinec                 f    t        j                  | dz   dz  t         j                  z  dz        dz  S )NgMb?gT㥛 ?r	   )mathcospits    r   alpha_bar_fnz)betas_for_alpha_bar.<locals>.alpha_bar_fnJ   s-    88QY%/$''9A=>!CCr   expc                 2    t        j                  | dz        S )Ng      ()r!   r'   r$   s    r   r&   z)betas_for_alpha_bar.<locals>.alpha_bar_fnO   s    88AI&&r   z"Unsupported alpha_transform_type: r   dtype)
ValueErrorrangeappendminr   tensorfloat32)num_diffusion_timestepsmax_betaalpha_transform_typer&   betasit1t2s           r   betas_for_alpha_barr8   1   s    . x'	D 
	&	' =>R=STUUE*+ M((!e..S\"-R0@@@(KLM <<U]]33r   c                   l   e Zd ZdZeD  cg c]  }|j
                   c}} ZdZe	 	 	 	 	 	 	 	 	 	 	 d/de	de
de
dedeeej                  ee
   f      d	ee   d
ee   dee   dedede	fd       Zed        Zed        Zed        Zd0de	fdZdej2                  dee
ej2                  f   dej2                  fdZd Zd1de	deeej8                  f   fdZd1dZd Zd Z d ej2                  dej2                  fd!Z!d ej2                  de	dej2                  fd"Z"	 d2d ej2                  de	d#e
d$e
dej2                  f
d%Z#	 	 d3d&ej2                  dee
ej2                  f   dej2                  d'e	d(edee$e%f   fd)Z&d*ej2                  d+ej2                  d,ej2                  dej2                  fd-Z'd. Z(yc c}} w )4LMSDiscreteScheduleru	  
    A linear multistep scheduler for discrete beta schedules.

    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:
        num_train_timesteps (`int`, defaults to 1000):
            The number of diffusion steps to train the model.
        beta_start (`float`, defaults to 0.0001):
            The starting `beta` value of inference.
        beta_end (`float`, defaults to 0.02):
            The final `beta` value.
        beta_schedule (`str`, defaults to `"linear"`):
            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 (`np.ndarray`, *optional*):
            Pass an array of betas directly to the constructor to bypass `beta_start` and `beta_end`.
        use_karras_sigmas (`bool`, *optional*, defaults to `False`):
            Whether to use Karras sigmas for step sizes in the noise schedule during the sampling process. If `True`,
            the sigmas are determined according to a sequence of noise levels {σi}.
        use_exponential_sigmas (`bool`, *optional*, defaults to `False`):
            Whether to use exponential sigmas for step sizes in the noise schedule during the sampling process.
        use_beta_sigmas (`bool`, *optional*, defaults to `False`):
            Whether to use beta sigmas for step sizes in the noise schedule during the sampling process. Refer to [Beta
            Sampling is All You Need](https://huggingface.co/papers/2407.12173) for more information.
        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).
        timestep_spacing (`str`, defaults to `"linspace"`):
            The way the timesteps should be scaled. Refer to Table 2 of the [Common Diffusion Noise Schedules and
            Sample Steps are Flawed](https://huggingface.co/papers/2305.08891) for more information.
        steps_offset (`int`, defaults to 0):
            An offset added to the inference steps, as required by some model families.
    r   Nnum_train_timesteps
beta_startbeta_endbeta_scheduletrained_betasuse_karras_sigmasuse_exponential_sigmasuse_beta_sigmasprediction_typetimestep_spacingsteps_offsetc                    t        | j                  j                  | j                  j                  | j                  j                  g      dkD  rt        d      |+t        j                  |t        j                        | _	        n|dk(  r-t        j                  |||t        j                        | _	        nk|dk(  r6t        j                  |dz  |dz  |t        j                        dz  | _	        n0|dk(  rt        |      | _	        nt        | d	| j                         d
| j                  z
  | _        t        j                  | j                  d      | _        t#        j$                  d| j                   z
  | j                   z  dz        }t#        j&                  |d d d   dgg      j)                  t"        j                        }t        j*                  |      | _        d | _        || _        | j1                  |d        g | _        d| _        d | _        d | _        | j,                  j;                  d      | _        y )Nr   znOnly one of `config.use_beta_sigmas`, `config.use_exponential_sigmas`, `config.use_karras_sigmas` can be used.r)   linearscaled_linear      ?r	   squaredcos_cap_v2z is not implemented for       ?r   )dim        Fcpu)sumconfigrB   rA   r@   r+   r   r/   r0   r4   linspacer8   NotImplementedError	__class__alphascumprodalphas_cumprodnparrayconcatenateastype
from_numpysigmasnum_inference_stepsset_timestepsderivativesis_scale_input_called_step_index_begin_indexto)selfr;   r<   r=   r>   r?   r@   rA   rB   rC   rD   rE   r]   s                r   __init__zLMSDiscreteScheduler.__init__   s    ++T[[-O-OQUQ\Q\QnQnopstt A  $m5==IDJh&
H>QY^YfYfgDJo-
C3H[chcpcpquvvDJ11,-@ADJ%7OPTP^P^O_&`aaDJJ&#mmDKKQ?A 3 33t7J7JJsRS"u 56==bjjI&&v. $( !2.5%*" kknnU+r   c                     | j                   j                  dv r| j                  j                         S | j                  j                         dz  dz   dz  S )N)rR   trailingr	   r   rI   )rQ   rD   r]   maxre   s    r   init_noise_sigmaz%LMSDiscreteScheduler.init_noise_sigma   sH     ;;''+CC;;??$$!Q&*s22r   c                     | j                   S )zg
        The index counter for current timestep. It will increase 1 after each scheduler step.
        )rb   rj   s    r   
step_indexzLMSDiscreteScheduler.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.
        rc   rj   s    r   begin_indexz LMSDiscreteScheduler.begin_index   s    
    r   rp   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.
        Nro   )re   rp   s     r   set_begin_indexz$LMSDiscreteScheduler.set_begin_index   s     (r   sampletimestepreturnc                     | j                   | j                  |       | j                  | j                      }||dz  dz   dz  z  }d| _        |S )a  
        Ensures interchangeability with schedulers that need to scale the denoising model input depending on the
        current timestep.

        Args:
            sample (`torch.Tensor`):
                The input sample.
            timestep (`float` or `torch.Tensor`):
                The current timestep in the diffusion chain.

        Returns:
            `torch.Tensor`:
                A scaled input sample.
        r	   r   rI   T)rm   _init_step_indexr]   ra   )re   rs   rt   sigmas       r   scale_model_inputz&LMSDiscreteScheduler.scale_model_input   sR      ??"!!(+DOO,E1HqLS01%)"r   c                       fd}t        j                  | j                      j                  dz      d      d   }|S )z
        Compute the linear multistep coefficient.

        Args:
            order ():
            t ():
            current_order ():
        c                     d}t              D ]F  }|k(  r	|| j                  |z
     z
  j                  z
     j                  |z
     z
  z  z  }H |S )NrK   )r,   r]   )tauprodkcurrent_orderorderre   r%   s      r   lms_derivativez@LMSDiscreteScheduler.get_lms_coefficient.<locals>.lms_derivative   sv    D5\ k A%t{{1q511dkk!mBS6TW[WbWbcdghchWi6ijjk Kr   r   -C6?)epsrelr   )r   quadr]   )re   r   r%   r   r   integrated_coeffs   ````  r   get_lms_coefficientz(LMSDiscreteScheduler.get_lms_coefficient   sD    	 %>>.$++a.$++VWZ[V[J\eijklmr   r^   devicec           	         || _         | j                  j                  dk(  rTt        j                  d| j                  j
                  dz
  |t        j                        ddd   j                         }nw| j                  j                  dk(  r| j                  j
                  | j                   z  }t        j                  d|      |z  j                         ddd   j                         j                  t        j                        }|| j                  j                  z  }n| j                  j                  dk(  r| j                  j
                  | j                   z  }t        j                  | j                  j
                  d|       j                         j                         j                  t        j                        }|dz  }n"t        | j                  j                   d	      t        j                  d| j                  z
  | j                  z  d
z        }t        j                  |      }t        j                   |t        j                  dt#        |            |      }| j                  j$                  rF| j'                  |      }t        j                  |D cg c]  }| j)                  ||       c}      }n| j                  j*                  rG| j-                  ||      }t        j                  |D cg c]  }| j)                  ||       c}      }n\| j                  j.                  rF| j1                  ||      }t        j                  |D cg c]  }| j)                  ||       c}      }t        j2                  |dgg      j                  t        j                        }t5        j6                  |      j9                  |      | _        t5        j6                  |      j9                  |t4        j                        | _        d| _        d| _         | j:                  j9                  d      | _        g | _!        yc c}w c c}w c c}w )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.
        rR   r   r   r)   NrM   leadingrh   zY is not supported. Please make sure to choose one of 'linspace', 'leading' or 'trailing'.rI   )	in_sigmas)r   r^   rN   )r   r   r*   rO   )"r^   rQ   rD   rX   rR   r;   r0   copyarangeroundr[   rE   r+   rY   rW   loginterplenr@   _convert_to_karras_sigma_to_trA   _convert_to_exponentialrB   _convert_to_betarZ   r   r\   rd   r]   	timestepsrb   rc   r`   )re   r^   r   r   
step_ratior]   
log_sigmasrx   s           r   r_   z"LMSDiscreteScheduler.set_timesteps  sh    $7  ;;'':5At{{'F'F'JL_gigqgqr"df  [[))Y688D<T<TTJ 1&9:ZGNNPQUSUQUV[[]ddegeoeopI111I[[))Z7884;S;SSJ 4;;#B#BA
{SZZ\aacjjkmkukuvINI;;//0  1J  K  A 3 33t7J7JJsRSVVF^
9bii3v;&?H;;((,,v,>FSY!Z%$"2"25*"E!Z[I[[//11FXk1lFSY!Z%$"2"25*"E!Z[I[[((**VQd*eFSY!Z%$"2"25*"E!Z[I#077

C&&v.111@)))477vU]]7[ kknnU+! "[ "[ "[s   "Q
?QQc                     || j                   }||k(  j                         }t        |      dkD  rdnd}||   j                         S )Nr   r   )r   nonzeror   item)re   rt   schedule_timestepsindicesposs        r   index_for_timestepz'LMSDiscreteScheduler.index_for_timestepB  sL    %!%%1::< w<!#as|  ""r   c                     | j                   Vt        |t        j                        r%|j	                  | j
                  j                        }| j                  |      | _        y | j                  | _        y N)
rp   
isinstancer   r   rd   r   r   r   rb   rc   )re   rt   s     r   rw   z%LMSDiscreteScheduler._init_step_indexQ  sU    #(ELL1#;;t~~'<'<=#66x@D#00Dr   c                    t        j                  t        j                  |d            }||d d t         j                  f   z
  }t        j                  |dk\  d      j                  d      j                  |j                  d   dz
        }|dz   }||   }||   }||z
  ||z
  z  }	t        j                  |	dd      }	d|	z
  |z  |	|z  z   }
|
j                  |j                        }
|
S )Ng|=r   )axisr	   )ri   r   )	rX   r   maximumnewaxiscumsumargmaxclipshapereshape)re   rx   r   	log_sigmadistslow_idxhigh_idxlowhighwr%   s              r   r   z LMSDiscreteScheduler._sigma_to_tZ  s    FF2::eU34	 Jq"**}55 ))UaZq188a8@EE*JZJZ[\J]`aJaEbQ;!(# 9_t,GGAq! UgH,IIekk"r   r   c                     |d   j                         }|d   j                         }d}t        j                  dd| j                        }|d|z  z  }|d|z  z  }||||z
  z  z   |z  }|S )z6Constructs the noise schedule of Karras et al. (2022).rM   r   g      @r   )r   rX   rR   r^   )	re   r   	sigma_min	sigma_maxrhorampmin_inv_rhomax_inv_rhor]   s	            r   r   z'LMSDiscreteScheduler._convert_to_karrasr  s     %R=--/	$Q<,,.	{{1a!9!9:AG,AG,k(A BBsJr   c                    t        | j                  d      r| j                  j                  }nd}t        | j                  d      r| j                  j                  }nd}||n|d   j	                         }||n|d   j	                         }t        j                  t        j                  t        j                  |      t        j                  |      |            }|S )z)Constructs an exponential noise schedule.r   Nr   rM   r   )
hasattrrQ   r   r   r   rX   r'   rR   r!   r   )re   r   r^   r   r   r]   s         r   r   z,LMSDiscreteScheduler._convert_to_exponential  s    
 4;;,--II4;;,--II!*!6IIbM<N<N<P	!*!6IIaL<M<M<O	DHHY$7)9LNabcr   alphabetac           
      (   t        | j                  d      r| j                  j                  }nd}t        | j                  d      r| j                  j                  }nd}||n|d   j	                         }||n|d   j	                         }t        j                  dt        j                  dd|      z
  D cg c]-  }t        j                  j                  j                  |||      / c}D cg c]  }||||z
  z  z    c}      }	|	S c c}w c c}w )zJFrom "Beta Sampling is All You Need" [arXiv:2407.12173] (Lee et. al, 2024)r   Nr   rM   r   r   )r   rQ   r   r   r   rX   rY   rR   scipystatsr   ppf)
re   r   r^   r   r   r   r   rt   r   r]   s
             r   r   z%LMSDiscreteScheduler._convert_to_beta  s     4;;,--II4;;,--II!*!6IIbM<N<N<P	!*!6IIaL<M<M<O	
 %&Aq:M(N$N  KK$$((5$? SI	$9:;
 s   82D
/Dmodel_outputr   return_dictc           
         | j                   st        j                  d       | j                  | j	                  |       | j
                  | j                     }| j                  j                  dk(  r	|||z  z
  }nw| j                  j                  dk(  r|| |dz  dz   dz  z  z  ||dz  dz   z  z   }n?| j                  j                  dk(  r|}n#t        d| j                  j                   d	      ||z
  |z  }| j                  j                  |       t        | j                        |kD  r| j                  j                  d
       t        | j                  dz   |      }t        |      D 	cg c]  }	| j                  || j                  |	      ! }
}	|t!        d t#        |
t%        | j                              D              z   }| xj&                  dz  c_        |s||fS t)        ||      S c c}	w )aa  
        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` or `torch.Tensor`):
                The current discrete timestep in the diffusion chain.
            sample (`torch.Tensor`):
                A current instance of a sample created by the diffusion process.
            order (`int`, defaults to 4):
                The order of the linear multistep method.
            return_dict (`bool`, *optional*, defaults to `True`):
                Whether or not to return a [`~schedulers.scheduling_utils.SchedulerOutput`] or tuple.

        Returns:
            [`~schedulers.scheduling_utils.SchedulerOutput`] or `tuple`:
                If return_dict is `True`, [`~schedulers.scheduling_utils.SchedulerOutput`] is returned, otherwise a
                tuple is returned where the first element is the sample tensor.

        zThe `scale_model_input` function should be called before `step` to ensure correct denoising. See `StableDiffusionPipeline` for a usage example.epsilonv_predictionr	   r   rI   rs   zprediction_type given as z, must be one of `epsilon`, or `v_prediction`r   c              3   ,   K   | ]  \  }}||z    y wr   r   ).0coeff
derivatives      r   	<genexpr>z,LMSDiscreteScheduler.step.<locals>.<genexpr>  s      #
#45*EJ#
s   )r   r   )ra   warningswarnrm   rw   r]   rQ   rC   r+   r`   r-   r   popr.   r,   r   rP   zipreversedrb   r   )re   r   rt   rs   r   r   rx   r   r   
curr_order
lms_coeffsr   s               r   stepzLMSDiscreteScheduler.step  s   < ))MME
 ??"!!(+DOO, ;;&&)3#)EL,@#@ [[((N:#/E6UAX\c<Q3Q#RV\`egh`hkl`lVm#n [[((H4#/ +DKK,G,G+HHtu 
 33u<

+t 5(  # DOOa'/ejkpeqrWad..udoozRr
r s #
8;JQUQaQaHb8c#
  
 

 	A$ 
 *kXlmm! ss   -$G-original_samplesnoiser   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 )Nr   mpsr)   r   rM   )r]   rd   r   r*   typer   is_floating_pointr   r0   rp   r   rm   r   flattenr   	unsqueeze)
re   r   r   r   r]   r   r%   step_indicesrx   noisy_sampless
             r   	add_noisezLMSDiscreteScheduler.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                 .    | j                   j                  S r   )rQ   r;   rj   s    r   __len__zLMSDiscreteScheduler.__len__'  s    {{...r   )i  r   g{Gz?rG   NFFFr   rR   r   )r   r   )333333?r   )   T))r   r   r   r   r   name_compatiblesr   r   intfloatstrr   r   rX   ndarrayr   boolrf   propertyrk   rm   rp   rr   r   r   ry   r   r   r_   r   rw   r   r   r   r   r   r   r   r   r   )r   es   00r   r:   r:   ]   s   #J %>>qAFF>LE $("%BF,116*/( */, /, /, 	/,
 /,  bjj$u+&= >?/, $D>/, !)/, "$/, /, /, /, /,b 3 3     ! !(3 ( eU\\FY@Z _d_k_k 0 ,8 8eCDU>V 8v#10ELL U\\  TW \a\h\h . dg<?HM[`	H  NnllNn u||+,Nn 	Nn
 Nn Nn 
)50	1Nnb,, || <<	
 
B/I ?s   F0r:   )g+?r   )r!   r   dataclassesr   typingr   r   r   r   numpyrX   scipy.statsr   r   r   configuration_utilsr
   r   utilsr   scheduling_utilsr   r   r   r8   r:   r   r   r   <module>r      sd      ! / /     A  G 8 8 8( !)4XK/>; K/r   