o
    i                     @   s   d Z ddlZddlZddlZddlmZ ddlZddl	m
Z
 ddlZddlmZ edZG dd dejZedG dd	 d	eZdS )
z
Abstract SDE classes, Reverse SDE, and VE/VP SDEs.

Taken and adapted from https://github.com/yang-song/score_sde_pytorch/blob/1618ddea340f3e4a2ed7852a0694a809775cf8d0/sde_lib.py
    N)batch_broadcast)RegistrySDEc                       s   e Zd ZdZ fddZeejdd Zejdd Z	ejdd	 Z
ejd
d Zejdd Zeejdd Zdd ZdddZejdd Z  ZS )r   zFSDE abstract class. Functions are designed for a mini-batch of inputs.c                    s   t    || _dS )z]Construct an SDE.

        Args:
            N: number of discretization time steps.
        N)super__init__N)selfr   	__class__ =/home/ubuntu/.local/lib/python3.10/site-packages/geco/sdes.pyr      s   

zSDE.__init__c                 C      dS )zEnd time of the SDE.Nr   r   r   r   r   T    s   zSDE.Tc                 G      d S Nr   r   xtargsr   r   r   sde&      zSDE.sdec                 G   r   )zLParameters to determine the marginal distribution of the SDE, $p_t(x|args)$.Nr   r   r   r   r   marginal_prob*      zSDE.marginal_probc                 G   r   )zRGenerate one sample from the prior distribution, $p_T(x|args)$ with shape `shape`.Nr   )r   shaper   r   r   r   prior_sampling/   r   zSDE.prior_samplingc                 C   r   )zCompute log-density of the prior distribution.

        Useful for computing the log-likelihood via probability flow ODE.

        Args:
            z: latent code
        Returns:
            log probability density
        Nr   r   zr   r   r   
prior_logp4   s   zSDE.prior_logpc                 C   r   )zp
        Add the necessary arguments for instantiation of this SDE class to an argparse ArgumentParser.
        Nr   )parent_parserr   r   r   add_argparse_argsA   s   zSDE.add_argparse_argsc           
      C   s@   |}|  |||\}}|| }|ttj||jd }	||	fS )ai  Discretize the SDE in the form: x_{i+1} = x_i + f_i(x_i) + G_i z_i.

        Useful for reverse diffusion sampling and probabiliy flow sampling.
        Defaults to Euler-Maruyama discretization.

        Args:
            x: a torch tensor
            t: a torch float representing the time step (from 0 to `self.T`)

        Returns:
            f, G
        device)r   torchsqrttensorr"   )
r   r   r   ystepsizedtdrift	diffusionfGr   r   r   
discretizeI   s
   zSDE.discretizeFc                    s<   | j  | j| j}| jG  fddd| j}| S )zCreate the reverse-time SDE/ODE.

        Args:
            score_model: A function that takes x, t and y and returns the score.
            probability_flow: If `True`, create the reverse-time ODE used for probability flow sampling.
        c                       s@   e Zd Z fddZefddZdd ZfddZd	S )
zSDE.reverse.<locals>.RSDEc                    s    | _ | _d S r   r   probability_flowr   r.   r   r   r   k   s   
z"SDE.reverse.<locals>.RSDE.__init__c                    s    S r   r   r   r   r   r   r   o   r   zSDE.reverse.<locals>.RSDE.Tc                 W   s.   | j ||g|R  }|d |d }}||fS )zACreate the drift and diffusion functions for the reverse SDE/ODE.total_driftr*   )
rsde_parts)r   r   r   r   r2   r1   r*   r   r   r   r   s   s   zSDE.reverse.<locals>.RSDE.sdec           
         sv    ||||\}}t |r|j}||dddddf d |||| | jr)dnd  }| jr5t |n|}	||	fS )zECreate discretized iteration rules for the reverse diffusion sampler.N   g      ?g      ?)r#   
is_compleximagr/   
zeros_like)
r   r   r   r&   mr'   r+   r,   rev_frev_G)discretize_fnscore_modelr   r   r-   y   s   
8z$SDE.reverse.<locals>.RSDE.discretizeN)__name__
__module____qualname__r   propertyr   r   r-   r   r   r   r:   r/   r;   r   r   RSDEj   s    rA   )r   r   r   r-   r
   )oselfr;   r/   sde_fnrA   r   r@   r   reverse]   s   zSDE.reversec                 C   r   r   r   r   r   r   r   copy   r   zSDE.copy)F)r<   r=   r>   __doc__r   r?   abcabstractmethodr   r   r   r   r   staticmethodr    r-   rD   rE   __classcell__r   r   r	   r   r      s*    	




'bbedc                       sr   e Zd Zedd Zd fdd	Zd	d
 Zdd Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Z  ZS )BBEDc                 C   sL   | j dtddd | j dtddd | j dtd	d
d | j dtddd | S )Nz--sde-n   z@The number of timesteps in the SDE discretization. 30 by default)typedefaulthelpz--T_sampling+?z6The T so that t < T during sampling in the train step.z--k@zbase factor for diffusion termz--thetap=
ף?z%root scale factor for diffusion term.)add_argumentintfloat)parserr   r   r   r       s
   zBBED.add_argparse_argsrQ   rR   rS     c                    sN   t  | || _t| j| _|| _|| _t	d| j | _
|| _d| _dS )zConstruct an Brownian Bridge with Exploding Diffusion Coefficient SDE with parameterization as in the paper.
        dx = (y-x)/(Tc-t) dt + sqrt(theta)*k^t dw
           N)r   r   knploglogkthetar   scexpiEilogr   Tc)r   
T_samplingr[   r_   r   kwargsr	   r   r   r      s   
zBBED.__init__c                 C   s   t | j| j| j| jdS )N)r   )rL   r   r[   r_   r   r   r   r   r   rE         z	BBED.copyc                 C      | j S r   r0   r   r   r   r   r         zBBED.Tc                 C   rg   r   rc   r   r   r   r   rc      rh   zBBED.Tcc                 C   s4   || | j |  }| j| }|t| j }||fS r   )rc   r[   r\   r$   r_   )r   r   r   r&   r)   sigmar*   r   r   r   r      s   
zBBED.sdec                 C   s2   || j  d d d d d f }|d|  ||  }|S )NrZ   ri   )r   x0r   r&   timemeanr   r   r   _mean   s   z
BBED._meanc                 C   s   |    }td|d  | j | j }d| jd  | j }| jd|  d | |d|  |  }t	|j
|jdd|  | j }t|S )Nr3   rZ   r!   )cpudetachnumpyr`   ra   r^   rb   r[   r#   r%   tor"   r_   r$   )r   r   t_npEishvarr   r   r   _std   s   &"
z	BBED._stdc                 C   s   |  |||| |fS r   )rn   rw   )r   rk   r   r&   r   r   r   r      rf   zBBED.marginal_probc                 C   sv   ||j krtd| d|j  d | | jtj|j d f|jd }t|}|||d d d d d f   }||fS )NzTarget shape z does not match shape of y z! Ignoring target shape.r   r!   )	r   warningswarnrw   r   r#   onesr"   
randn_like)r   r   r&   stdr   x_Tr   r   r   r      s   
$
zBBED.prior_samplingc                 C   s   t d)Nz(prior_logp for BBED not yet implemented!)NotImplementedErrorr   r   r   r   r      s   zBBED.prior_logp)rQ   rR   rS   rX   )r<   r=   r>   rI   r    r   rE   r   rc   r   rn   rw   r   r   r   rJ   r   r   r	   r   rL      s    
rL   )rF   rG   rx   mathscipy.specialspecialr`   rq   r\   &solospeech.corrector.geco.util.tensorsr   r#   'solospeech.corrector.geco.util.registryr   SDERegistryABCr   registerrL   r   r   r   r   <module>   s    u