o
    Gis                     @   s   d dl Z d dlmZ d dlmZ d dlZd dlZddlm	Z	m
Z
 ddlmZ ddlmZmZ eG dd	 d	eZG d
d dee	ZdS )    N)	dataclass)Literal   )ConfigMixinregister_to_config)SchedulerMixin)
BaseOutput	deprecatec                   @   sL   e Zd ZU ejed< dZejdB ed< dZejdB ed< dZe	dB ed< dS )HeliosSchedulerOutputprev_sampleNmodel_outputslast_sample
this_order)
__name__
__module____qualname__torchFloatTensor__annotations__r   r   r   int r   r   Z/home/ubuntu/.local/lib/python3.10/site-packages/diffusers/schedulers/scheduling_helios.pyr
      s
   
 
r
   c                %   @   s  e Zd Zg ZdZedddg ddddd	d
dd
g dd
dddfdededededede	de
dede	de
de	dee dede	de
de	ded  f"d!d"Zd#d$ Zd%d& Zed'd( Zed)d* Zdld,efd-d.Zd/d0 Z					dmd1ed2edB d3e
ejB d4e	dB d5e	dB d6e	fd7d8Zd5ed9ed:ejfd;d<Zd=d> Zd?d@ ZdndAdBZdCdD Z						
dodEejdFeejB dGejdHejdB d9ejdB dIejdB dJe	dKe e!B fdLdMZ"dNdO Z#dddPdEejdGejd9ejdKejfdQdRZ$dddddSdEejdGejdTed9ejdIejdKejfdUdVZ%ddddddWdXejdYejdZejdTed[ejd9ejdKejfd\d]Z&			
									dpdEejdFeejB dGejdJe	d^ed_ed[ejd9ejdIejd`edaedbedcejdKe e!B fdddeZ'				
dqdEejdFeejB dGejdHejdB dJe	dKe e!B fdfdgZ(dhdi Z)djdk Z*dS )rHeliosScheduler   i        ?   )r   UUUUUU?gUUUUUU?r   r   Fflow_predictionr   Tbh2Nunipcexponentialnum_train_timestepsshiftstagesstage_rangegammathresholdingprediction_typesolver_order
predict_x0solver_typelower_order_finaldisable_correctorsolver_puse_flow_sigmasscheduler_typeuse_dynamic_shiftingtime_shift_type)r    linearc                 C   s   i | _ i | _i | _i | _i | _i | _|   | jd  | _	| jd  | _
|| _|
dvrB|
dv r8| jdd n
t|
 d| j |	| _d g| | _d g| | _d| _|| _|| _d | _d | _d | _d S )Nr   )bh1r   )midpointheunlogrhor   )r*   z is not implemented for )timestep_ratiostimesteps_per_stagesigmas_per_stagestart_sigmas
end_sigmasori_start_sigmasinit_sigmas_for_each_stagesigmasitem	sigma_min	sigma_maxr%   r   NotImplementedError	__class__r)   r   timestep_listlower_order_numsr,   r-   r   _step_index_begin_index)selfr!   r"   r#   r$   r%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r   r   r   __init__'   s.   
zHeliosScheduler.__init__c                 C   s   | j j}| j j}tdd| |d }d| }t|| d|d |   dd  }t|}|| 	 }d| _
d| _|| _|d| _dS )z<
        initialize the global timesteps and sigmas
        r   r   Nr3   cpu)configr!   r"   nplinspaceflipcopyr   
from_numpyclonerG   rH   	timestepstor?   )rI   r!   r"   alphasr?   rS   r   r   r   init_sigmasZ   s   *
zHeliosScheduler.init_sigmasc                 C   s8  |    g }| jj}| jj}| jj}t|D ]k}t|| | }t|d}t||d  | }t||}| j	| 
 }||k rF| j	| 
 nd}	|| j|< |dkrpd| }
| jj}dtdd|  d|
  |
  |
 }d| }|||	  || j|< |	| j|< qt|}t|D ]/}|dkrd}n
t|d| | }||d krd}nt|d|d  | }||f| j|< qt|D ][}| j| }t| jt|d |  d}| jtt|d | |d  }t|||d }t|tjr|dd nt|dd | j|< tdd|d }t|dd | j|< qdS )	z3
        Init the timesteps for each stage
        r   r   g        Ng?i  r3   g+?)rV   rL   r#   r!   r$   ranger   maxminr?   r@   r=   r%   mathsqrtappendr;   r<   sumr8   rS   rM   rN   
isinstancer   TensorrQ   r9   r:   )rI   stage_distancer#   training_stepsr$   i_sstart_indice
end_indicestart_sigma	end_sigma	ori_sigmar%   corrected_sigmatot_distancestart_ratio	end_ratiotimestep_ratiotimestep_maxtimestep_minrS   stage_sigmasr   r   r   r>   l   sP   


&

 (z*HeliosScheduler.init_sigmas_for_each_stagec                 C      | j S )zg
        The index counter for current timestep. It will increase 1 after each scheduler step.
        )rG   rI   r   r   r   
step_index      zHeliosScheduler.step_indexc                 C   rp   )zq
        The index for the first timestep. It should be set from pipeline with `set_begin_index` method.
        rH   rq   r   r   r   begin_index   rs   zHeliosScheduler.begin_indexr   ru   c                 C   s
   || _ dS )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   r   r   r   set_begin_index   s   
zHeliosScheduler.set_begin_indexc                 C   s   || j j S NrL   r!   )rI   sigmar   r   r   _sigma_to_t   s   zHeliosScheduler._sigma_to_tnum_inference_stepsstage_indexdevicer?   muis_amplify_first_chunkc                 C   s(  | j jdkr|r|d d }n|d }|| _|   | j jdkr\|du rNtdd| j j |d dd tj	}| j j
dkrN| j jrEJ | | j j
d|}|| j j  }t|}n-| j| }t|d  |d  |}| j| }	t|	d  |	d  |}
t|
}t|j|d| _t|tdgj|d| _d| _|   | j jdkr| jdd | _t| jdd	 | jdd g| _| j jr| j j
dksJ | |d| j| _| j jdkr| jdd | j j | _dS | j|  | jdd | j|  | j|     | _dS dS )
zA
        Setting the timesteps and sigmas for each stage
        dmdr   r   Nr3   r   r   r}   )rL   r/   r{   rV   r#   rM   rN   r!   astypefloat32r"   r0   
time_shiftrP   r   rQ   r9   r@   r:   rT   rS   catzerosr?   rG   reset_scheduler_historyrY   rX   )rI   r{   r|   r}   r?   r~   r   rS   stage_timestepsro   ratiosr   r   r   set_timesteps   sR   "




$
zHeliosScheduler.set_timestepsry   tc                 C   s8   | j jdkr| |||S | j jdkr| |||S dS )a  
        Apply time shifting to the sigmas.

        Args:
            mu (`float`):
                The mu parameter for the time shift.
            sigma (`float`):
                The sigma parameter for the time shift.
            t (`torch.Tensor`):
                The input timesteps.

        Returns:
            `torch.Tensor`:
                The time-shifted timesteps.
        r    r2   N)rL   r1   _time_shift_exponential_time_shift_linearrI   r~   ry   r   r   r   r   r     s
   zHeliosScheduler.time_shiftc                 C   s$   t |t |d| d |   S Nr   )rZ   expr   r   r   r   r     s   $z'HeliosScheduler._time_shift_exponentialc                 C   s   ||d| d |   S r   r   r   r   r   r   r     s   z"HeliosScheduler._time_shift_linearc                 C   s:   |d u r| j }||k }t|dkrdnd}||  S )Nr   r   )rS   nonzerolenr@   )rI   timestepschedule_timestepsindicesposr   r   r   index_for_timestep!  s
   z"HeliosScheduler.index_for_timestepc                 C   s@   | j d u rt|tjr|| jj}| || _d S | j	| _d S rw   )
ru   r^   r   r_   rT   rS   r}   r   rG   rH   )rI   r   r   r   r   _init_step_index/  s
   
z HeliosScheduler._init_step_indexmodel_outputr   sample	generator
sigma_nextreturn_dictreturnc           	      C   s   |d u |d u ksJ d|d u r)|d u r)t |ts%t |tjs%t |tjr)td| jd u r1d| _|tj	}|d u rM|d u rM| j
| j }| j
| jd  }||| |  }||j}|  jd7  _|sg|fS t|dS )Nz:sigma and sigma_next must both be None or both be not NonezPassing integer indices (e.g. from `enumerate(timesteps)`) as timesteps to `EulerDiscreteScheduler.step()` is not supported. Make sure to pass one of the `scheduler.timesteps` as a timestep.r   r   )r   )r^   r   r   	IntTensor
LongTensor
ValueErrorrr   rG   rT   r   r?   dtyper
   )	rI   r   r   r   r   ry   r   r   r   r   r   r   
step_euler7  s.   




zHeliosScheduler.step_eulerc                 C   sJ   | j jrd| }tj|dd}||fS d|d d d  }|| }||fS )Nr   g:0yE>)rY   r         ?)rL   r.   r   clamp)rI   ry   alpha_tsigma_tr   r   r   _sigma_to_alpha_sigma_ti  s   z'HeliosScheduler._sigma_to_alpha_sigma_tr   ry   c                O   s  t |dkr
|d n|dd}|du r#t |dkr|d }ntd|dur-tddd d	}|du r;d
}| j| j }| |\}}	| jr| jj	dkrT||	|  | }
n:| jj	dkr]|}
n1| jj	dkrl|| |	|  }
n"| jj	dkr|r{| j| j }	n|}	||	|  }
n
td| jj	 d| jj
r| |
}
|
S | jj	dkr|S | jj	dkr|||  |	 }|S | jj	dkr|| |	|  }|S td| jj	 d)a  
        Convert the model output to the corresponding type the UniPC algorithm needs.

        Args:
            model_output (`torch.Tensor`):
                The direct output from the learned diffusion model.
            timestep (`int`):
                The current discrete timestep in the diffusion chain.
            sample (`torch.Tensor`):
                A current instance of a sample created by the diffusion process.

        Returns:
            `torch.Tensor`:
                The converted model output.
        r   r   Nr   /missing `sample` as a required keyword argumentrS   1.0.0zPassing `timesteps` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`FTepsilonr   v_predictionr   zprediction_type given as zj must be one of `epsilon`, `sample`, `v_prediction`, or `flow_prediction` for the UniPCMultistepScheduler.zW must be one of `epsilon`, `sample`, or `v_prediction` for the UniPCMultistepScheduler.)r   popr   r	   r?   rr   r   r)   rL   r'   r&   _threshold_sample)rI   r   r   ry   argskwargsr   flagr   r   x0_predr   r   r   r   convert_model_outputs  sZ    

z$HeliosScheduler.convert_model_output)r   orderry   r   r   c          )      O   s  t |dkr
|d n|dd}|du r#t |dkr|d }ntd|du r6t |dkr2|d }ntd|dur@tddd	 | j}	| jd
 }
|	d
 }|}| jr\| j||
|j}|S |du rt|du rt| j	| j
d  | j	| j
 }}n||}}| |\}}| |\}}t|t| }t|t| }|| }|j}g }g }td|D ]6}| j
| }|	|d   }| | j	| \}}t|t| }|| | }|| ||| |  q|d tj||d}g }g } | jr| n|}!t|!}"|"|! d }#d}$| jjdkr|!}%n| jjdkrt|!}%nt td|d D ]%}|t||d  | |#|$ |%  |$|d 9 }$|#|! d|$  }#q(t|}tj| |d} t |dkrtj|dd}|dkrxtjdg|j|d}&ntj|dd
dd
f | dd
 ||j}&nd}| jr|| | ||" |  }'|durtd|&|}(nd}(|'||% |(  }n#|| | ||" |  }'|durtd|&|}(nd}(|'||% |(  }||j}|S )a  
        One step for the UniP (B(h) version). Alternatively, `self.solver_p` is used if is specified.

        Args:
            model_output (`torch.Tensor`):
                The direct output from the learned diffusion model at the current timestep.
            prev_timestep (`int`):
                The previous discrete timestep in the diffusion chain.
            sample (`torch.Tensor`):
                A current instance of a sample created by the diffusion process.
            order (`int`):
                The order of UniP at this timestep (corresponds to the *p* in UniPC-p).

        Returns:
            `torch.Tensor`:
                The sample tensor at the previous timestep.
        r   prev_timestepNr   r   r   .missing `order` as a required keyword argumentr   zPassing `prev_timestep` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`r3   r   r   r4   r   dimr   r   r}   k,bkc...->bc...)r   r   r   r	   r   rE   r-   stepr   r?   rr   r   r   logr}   rW   r\   tensorr)   expm1rL   r*   rC   powstackr   linalgsolverT   einsum))rI   r   r   r   ry   r   r   r   r   model_output_lists0m0xx_tr   sigma_s0r   alpha_s0lambda_t	lambda_s0hr}   rksD1sisimialpha_sisigma_si	lambda_sirkRbhhh_phi_1h_phi_kfactorial_iB_hrhos_px_t_pred_resr   r   r   multistep_uni_p_bh_update  s    


 






6

z)HeliosScheduler.multistep_uni_p_bh_update)r   this_sampler   sigma_beforery   this_model_outputr   r   r   c          +      O   s  t |dkr
|d n|dd}	|du r#t |dkr|d }ntd|du r6t |dkr2|d }ntd|du rIt |dkrE|d }ntd	|	durStdd
d | j}
|
d }|}|}|}|du rx|du rx| j| j | j| jd  }}n||}}| |\}}| |\}}t	|t	| }t	|t	| }|| }|j
}g }g }td|D ]8}| j|d  }|
|d   }| | j| \}}t	|t	| }|| | }|| ||| |  q|d tj||d}g } g }!| jr| n|}"t|"}#|#|" d }$d}%| jjdkr|"}&n| jjdkr$t|"}&nt td|d D ]%}| t||d  |!|$|% |&  |%|d 9 }%|$|" d|%  }$q.t| } tj|!|d}!t |dkrotj|dd}nd}|dkrtjdg|j|d}'ntj| |!||j}'| jr|| | ||# |  }(|durtd|'dd |})nd})|| }*|(||& |)|'d |*    }n1|| | ||# |  }(|durtd|'dd |})nd})|| }*|(||& |)|'d |*    }||j}|S )a  
        One step for the UniC (B(h) version).

        Args:
            this_model_output (`torch.Tensor`):
                The model outputs at `x_t`.
            this_timestep (`int`):
                The current timestep `t`.
            last_sample (`torch.Tensor`):
                The generated sample before the last predictor `x_{t-1}`.
            this_sample (`torch.Tensor`):
                The generated sample after the last predictor `x_{t}`.
            order (`int`):
                The `p` of UniC-p at this step. The effective order of accuracy should be `order + 1`.

        Returns:
            `torch.Tensor`:
                The corrected sample tensor at the current timestep.
        r   this_timestepNr   z4missing `last_sample` as a required keyword argumentr   z4missing `this_sample` as a required keyword argumentr   r   r   zPassing `this_timestep` is deprecated and has no effect as model output conversion is now handled via an internal counter `self.step_index`r3   r   r   r4   r   r   r   r   r   )r   r   r   r	   r   r?   rr   r   r   r   r}   rW   r\   r   r)   r   rL   r*   rC   r   r   r   r   r   rT   r   )+rI   r   r   r   r   r   ry   r   r   r   r   r   r   r   model_tr   r   r   r   r   r   r   r}   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rhos_cr   corr_resD1_tr   r   r   multistep_uni_c_bh_updateI  s    


 







z)HeliosScheduler.multistep_uni_c_bh_updater   rE   cus_step_indexcus_lower_order_numcus_this_ordercus_last_samplec                 C   s0  | j d u r	td|
d u r| jd u rd| _n|
| _|d ur || _|d ur'|| _|d ur.|| _| jdko?| jd | jvo?| jd u}| j|||d}|d ur^|d ur^|d d | _	|d d | _
|rm| j|| j|| j||d}|d ur|d ur||d< |dd  | _	|dd  | _
n)t| jjd D ]}| j	|d  | j	|< | j
|d  | j
|< q|| j	d< || j
d< | jjrt| jjt| j| j }n| jj}t|| jd | _| jdksJ || _| j||| j||	d}|d u r| j| jjk r|  jd7  _|
d u r|  jd7  _|s||| j| jfS t||| j| jdS )	NzaNumber of inference steps is 'None', you need to run 'set_timesteps' after creating the schedulerr   r   r   r3   )r   r   r   r   r   ry   )r   r   r   ry   r   )r   r   r   r   )r{   r   rr   rG   rF   r   r   r,   r   r   rE   r   rW   rL   r(   r+   rY   r   rS   r   r
   )rI   r   r   r   r   r   rE   r   ry   r   r   r   r   r   use_correctormodel_output_convertr   r   r   r   r   r   
step_unipc  s   

"	


zHeliosScheduler.step_unipcc                 C   sB   | j jdkr| j|||||dS | j jdkr| j||||dS t)Neuler)r   r   r   r   r   r   )r   r   r   r   )rL   r/   r   r   rC   )rI   r   r   r   r   r   r   r   r   r   >  s    zHeliosScheduler.stepc                 C   sP   d g| j j | _d g| j j | _d| _| j j| _| j j| _d | _d | _d | _	d S )Nr   )
rL   r(   r   rE   rF   r,   r-   r   rG   rH   rq   r   r   r   r   X  s   


z'HeliosScheduler.reset_scheduler_historyc                 C   s   | j jS rw   rx   rq   r   r   r   __len__b  s   zHeliosScheduler.__len__)r   )NNNNFrw   )NNNNNT)NNTNNNNNNNNN)NNNT)+r   r   r   _compatiblesr   r   r   floatlistboolstrr   r   rJ   rV   r>   propertyrr   ru   rv   rz   r   r}   r   r_   r   r   r   r   r   r   	Generatorr
   tupler   r   r   r   r   r   r   r   r   r   r   r   r   r   #   s   	
2<



@
	
2
T	
 

 	

j

r   )rZ   dataclassesr   typingr   numpyrM   r   configuration_utilsr   r   schedulers.scheduling_utilsr   utilsr   r	   r
   r   r   r   r   r   <module>   s   