o
    wi#                     @   s   d dl mZmZ d dlmZ d dlZd dlZd dlmZ d dl	m
Z
 G dd deZG dd	 d	eZG d
d deZG dd deZdS )    )ABCabstractmethod)TupleN)mask_sequence_tensor)loggingc                   @   s"  e Zd ZdZddedefddZedejd	ejd
ejdejfddZ	edejd	ejd
ejdejfddZ
edejd	ejd
ejdejdejf
ddZedejdedejfddZd dedejjdejfddZdejd	ejd
ejdejfddZdejd	ejd
ejdejdejf
ddZdS )!ConditionalFlowa-  
    Abstract class for different conditional flow-matching (CFM) classes

    Time horizon is [time_min, time_max (should be 1)]

    every path is "conditioned" on endpoints of the path
    endpoints are just our paired data samples
    subclasses need to implement mean, std, and vector_field

    :0yE>      ?time_mintime_maxc                 C   s   || _ || _d S Nr
   r   )selfr
   r    r   i/home/ubuntu/sommelier/.venv/lib/python3.10/site-packages/nemo/collections/audio/parts/submodules/flow.py__init__$   s   
zConditionalFlow.__init__timex_startx_endreturnc                C      dS )zF
        Return the mean of p_t(x | x_start, x_end) at time t
        Nr   r   r   r   r   r   r   r   mean(      zConditionalFlow.meanc                C   r   )zT
        Return the standard deviation of p_t(x | x_start, x_end) at time t
        Nr   r   r   r   r   std/   r   zConditionalFlow.stdpointc                C   r   )zS
        Compute the conditional vector field v_t( point | x_start, x_end)
        Nr   )r   r   r   r   r   r   r   r   vector_field6   s   zConditionalFlow.vector_fieldn_dimc                 C   s:   | j dkrddgdg|d   }t| d| } | S )zK
        Broadcast time tensor to the desired number of dimensions
            B1zB -> )ndimjoineinops	rearrange)r   r   target_shaper   r   r   _broadcast_time?   s   
zConditionalFlow._broadcast_timeN
batch_sizerngc                 C   s"   t j|f|d| j| j  | j S )z
        Randomly sample a batchsize of time_steps from U[self.time_min, self.time_max]
        Supports an external random number generator for better reproducibility
        )	generator)torchrandr   r
   )r   r(   r)   r   r   r   generate_timeJ   s   "zConditionalFlow.generate_timec                C   sB   | j ||jd}| j|||d}| j|||d}||t|  S )z
        Generate a sample from p_t(x | x_start, x_end) at time t.
        Note that this implementation assumes all path marginals are normally distributed.
        r   r   r   r   )r'   r"   r   r   r+   
randn_like)r   r   r   r   r   r   r   r   r   sampleQ   s   zConditionalFlow.samplec                C   s0   | j |||d}| j|||d}||||   S )zn
        Compute the conditional flow phi_t( point | x_start, x_end).
        This is an affine flow.
        r/   )r   r   )r   r   r   r   r   r   r   r   r   r   flow\   s   zConditionalFlow.flow)r   r	   r   )__name__
__module____qualname____doc__floatr   r   r+   Tensorr   r   r   staticmethodintr'   random	Generatorr-   r1   r2   r   r   r   r   r      sD    $$
"r   c                       s   e Zd ZdZ	ddedededef fd	d
ZdejdejdejdejfddZdejdejdejdejfddZ	dddejdejdejdejdedejfddZ
  ZS )OptimalTransportFlowa  The OT-CFM model from [Lipman et at, 2023]

    Every conditional path the following holds:
    p_0 = N(x_start, sigma_start)
    p_1 = N(x_end, sigma_end),

    mean(x, t) = (time_max - t) * x_start + t * x_end
        (linear interpolation between x_start and x_end)

    std(x, t) = (time_max - t) * sigma_start + t * sigma_end

    Every conditional path is optimal transport map from p_0(x_start, x_end) to p_1(x_start, x_end)
    Marginal path is not guaranteed to be an optimal transport map from p_0 to p_1

    To get the OT-CFM model from [Lipman et at, 2023] just pass zeroes for x_start
    To get the I-CFM model, set sigma_min=sigma_max
    To get the rectified flow model, set sigma_min=sigma_max=0

    Args:
        time_min: minimum time value used in the process
        time_max: maximum time value used in the process
        sigma_start: the standard deviation of the initial distribution
        sigma_end: the standard deviation of the target distribution
    r   r	   -C6?r
   r   sigma_start	sigma_endc                    sh   t  j||d || _|| _td| jj td| j td| j	 td| j td| j d S )Nr   Initialized %s with	time_min:       %s	time_max:       %sz	sgima_start:    %sz	sigma_end:      %s)
superr   r?   r@   r   debug	__class__r3   r
   r   )r   r
   r   r?   r@   rF   r   r   r      s   zOptimalTransportFlow.__init__r   r   r   r   c                C   s   | j | | ||  S r   )r   r   r   r   r   r   r   r   r      s   zOptimalTransportFlow.meanc                C   s   | j | | j || j  S r   )r   r?   r@   rH   r   r   r   r      s   zOptimalTransportFlow.stdgư>)epsr   rI   c                C   sd   | j ||jd}| j| jkr|| S | j||  | j||   }d| | j || j  }|||  S )Nr.   r   )r'   r"   r?   r@   )r   r   r   r   r   rI   numdenomr   r   r   r      s   	z!OptimalTransportFlow.vector_field)r   r	   r	   r>   )r3   r4   r5   r6   r7   r   r+   r8   r   r   r   __classcell__r   r   rG   r   r=   h   s8    ""
r=   c                   @   sr   e Zd ZdZ			ddejjdededefd	d
Z	e
dd Zedejdejdejdeejejf fddZdS )ConditionalFlowMatchingSampleraH  
    Abstract class for different sampler to solve the ODE in CFM

    Args:
        estimator: the NN-based conditional vector field estimator
        num_steps: How many time steps to iterate in the process
        time_min: minimum time value used in the process
        time_max: maximum time value used in the process

       r   r	   	estimator	num_stepsr
   r   c                 C   s   || _ || _|| _|| _d S r   rO   rP   r
   r   r   rO   rP   r
   r   r   r   r   r      s   
z'ConditionalFlowMatchingSampler.__init__c                 C   s   | j | j | j S r   )r   r
   rP   )r   r   r   r   	time_step   s   z(ConditionalFlowMatchingSampler.time_stepstateestimator_conditionstate_lengthr   c                 C   s   d S r   r   )r   rT   rU   rV   r   r   r   forward   s   z&ConditionalFlowMatchingSampler.forwardNrN   r   r	   )r3   r4   r5   r6   r+   nnModuler:   r7   r   propertyrS   r   r8   r   rW   r   r   r   r   rM      s4    

rM   c                       sz   e Zd ZdZ			ddejjdededef fd	d
Z	dd Z
e dejdejdejdeejejf fddZ  ZS )#ConditionalFlowMatchingEulerSamplerzM
    The Euler Sampler for solving the ODE in CFM on a uniform time grid
    rN   r   r	   rO   rP   r
   r   c                    sR   t  j||||d td| jj td| j td| j td| j d S )NrQ   rA   z	num_steps:      %srB   rC   )	rD   r   r   rE   rF   r3   rP   r
   r   rR   rG   r   r   r      s   z,ConditionalFlowMatchingEulerSampler.__init__c                 O   s   | j |i |S r   )rW   )r   argskwargsr   r   r   __call__   s   z,ConditionalFlowMatchingEulerSampler.__call__rT   rU   rV   r   c           
      C   s   t | j| j| jd }|d urt||}|d d D ]9}|t j|jd |jd }|d u r1|}n	t j	||gdd}| j
|||d\}}	||| j  }|d urTt||}q||fS )Nr   r   )device)dim)inputinput_length	condition)r+   linspacer
   r   rP   r   onesshapera   catrO   rS   )
r   rT   rU   rV   
time_stepstr   estimator_inputr   _r   r   r   rW      s   

z+ConditionalFlowMatchingEulerSampler.forwardrX   )r3   r4   r5   r6   r+   rY   rZ   r:   r7   r   r_   inference_moder8   r   rW   rL   r   r   rG   r   r\      s2    r\   )abcr   r   typingr   r$   r+   #nemo.collections.common.parts.utilsr   
nemo.utilsr   r   r=   rM   r\   r   r   r   r   <module>   s   P@#