o
    ٷiՈ                     @   s   d dl Z d dlZd dlZd dlZd dlZddlmZ ddlm	Z	 ddl
mZmZmZmZmZ de d ZdZd	d
 Zdd Zdd Zdd Zdd ZdejdejdedejfddZG dd dZG dd deZG dd dZG dd  d ejeZdS )!    N   )brownian_base   )LEVY_AREA_APPROXIMATIONS)ScalarOptionalTupleUnionTensor   gUUUUUU?c                 C   s&   t |t|}t j| |||dS )N)dtypedevice	generator)torch	Generatormanual_seedintrandn)sizer   r   seedr    r   X/home/ubuntu/.local/lib/python3.10/site-packages/torchsde/_brownian/brownian_interval.py_randn   s   r   c                 C   s,   t | tpt | tpt | tjo|  dkS )Nr   )
isinstancer   floatr   r
   numelxr   r   r   
_is_scalar#   s   ,r   c                 C   s>   t |st|  d| d| st|  d| dd S )N=z should be a Tensor.z should be floating point.)r   	is_tensor
ValueErroris_floating_point)nametensorr   r   r   _assert_floating_tensor'   s
   
r%   c                    s>  t ttj|}|du rt|dkrt }|du r%t|dkr%td}| du r+g n| gdd |D 7 |du r=g n|gdd |D 7 |du rOg n|g  dd |D 7  tdkretdtfd	d
D sttdtfdd
D stdt fdd
 D stdt	d d  d fS )zQCheck if sizes, dtypes, and devices of input tensors all match prescribed values.Nr   cpuc                 S      g | ]}|j qS r   )shape.0tr   r   r   
<listcomp>8       z&_check_tensor_info.<locals>.<listcomp>c                 S   r'   r   )r   r)   r   r   r   r,   ;   r-   c                 S   r'   r   )r   r)   r   r   r   r,   >   r-   zOMust either specify `size` or pass in `W` or `H` to implicitly define the size.c                 3       | ]	}| d  kV  qdS r   Nr   r*   i)sizesr   r   	<genexpr>C       z%_check_tensor_info.<locals>.<genexpr>zEMultiple sizes found. Make sure `size` and `W` or `H` are consistent.c                 3   r.   r/   r   r0   )dtypesr   r   r3   E   r4   zGMultiple dtypes found. Make sure `dtype` and `W` or `H` are consistent.c                 3   r.   r/   r   r0   )devicesr   r   r3   G   r4   zIMultiple devices found. Make sure `device` and `W` or `H` are consistent.)
listfilterr   r    lenget_default_dtyper   r!   alltuple)r   r   r   tensorsr   )r6   r5   r2   r   _check_tensor_info.   s(   
r>   c                 C   s   |t jt jfv r
d S |  dv rt| S |d| d | d|d  }| }||dd }|t jkrRd| }|d }|||d |d  	 }	n	t
	t|d  }	|	| }
||
7 }|S )Nr   r   g?r   )r   none
space_time
ndimensionr   
zeros_like	unsqueeze	transposefostersqrtmath_r12)WHhlevy_area_approximation	get_noiseAnoisetenth_h	H_squaredstda_tilder   r   r   _davie_foster_approximationN   s   
(
"rW   rL   rM   rN   returnc                 C   s   |d|  |  S N      ?r   )rL   rM   rN   r   r   r   _H_to_Uf   s   r[   c                   @   s   e Zd Zdd Zdd ZdS )
_EmptyDictc                 C   s   d S Nr   selfkeyvaluer   r   r   __setitem__k      z_EmptyDict.__setitem__c                 C   s   t r]   )KeyError)r_   itemr   r   r   __getitem__n   rc   z_EmptyDict.__getitem__N)__name__
__module____qualname__rb   rf   r   r   r   r   r\   j   s    r\   c                       s(   e Zd Z fddZ fddZ  ZS )_LRUDictc                    s   t    || _g | _d S r]   )super__init__	_max_size_keys)r_   max_size	__class__r   r   rl   s   s   

z_LRUDict.__init__c                    sP   || v r| j | nt| | jkr| | j d= t || | j | d S Nr   )rn   remover9   rm   poprk   rb   appendr^   rp   r   r   rb   x   s   z_LRUDict.__setitem__)rg   rh   ri   rl   rb   __classcell__r   r   rp   r   rj   r   s    rj   c                   @   sh   e Zd Z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dd Zdd ZdS )	_Interval)_start_end_parent_is_left_top_midway
_spawn_key_depth_W_seed_H_seed_left_a_seed_right_a_seed_left_child_right_childc                 C   s4   | || _| || _|| _|| _|| _d | _d S r]   )_roundrx   ry   rz   r{   r|   r}   )r_   startendparentis_lefttopr   r   r   rl      s   
z_Interval.__init__c                 C   s:   t  |  \}}t||| j| j | jj| j}|||fS r]   )
trampoline#_increment_and_space_time_levy_arearW   ry   rx   r|   _levy_area_approximation_randn_levy)r_   rL   rM   rQ   r   r   r   _increment_and_levy_area   s
   
z"_Interval._increment_and_levy_areac              	   c   s   z| j j|  W S  ty   | j}| V \}}d|j|j  }|j|j }|j|j }| j jr|d }|d }|| }	|| }
dt	
|| |	|
   }|| | }|| | }|t }||j}||j}d|| ||   | }| jr|| }d| | | }|| ||  ||  }|d | ||  || |  }nP|| }d| | | }|| ||  ||  }|d | ||  || |  }n'|| | }|| | }||j}|t	
||  }| jr|}n|| }d }||f| j j| < ||f Y S w )Nr   r   rZ      )r|   )_increment_and_space_time_levy_area_cacherd   rz   r   ry   rx   r}   _have_HrJ   rI   _rsqrt3r   r   r   r{   )r_   r   rL   rM   h_reciprocal	left_diff
right_diffleft_diff_squaredright_diff_squaredleft_diff_cubedright_diff_cubedvabcX1X2third_coefffirst_coeffsecond_coeffout_Wout_HmeanvarrR   left_Wr   r   r   r      sR   ""z-_Interval._increment_and_space_time_levy_areac                 C   s   | j j}t|| j j| j j|S r]   )r|   _sizer   _dtype_device)r_   r   r   r   r   r   r      s   z_Interval._randnc                 C   s   | j r| jjS | jjS r]   )r{   rz   r   r   r_   r   r   r   _a_seed   s   z_Interval._a_seedc                 C   s8   g | j j| j jdd  R }t|| j j| j j|  S )Nr@   )r|   r   r   r   r   r   )r_   r   r   r   r   r      s   z_Interval._randn_levyc                 C   s4   g }| j |}| j |}t| ||| |S r]   )r|   r   r   
_loc_innerr_   tatboutr   r   r   _loc  s
   z_Interval._locc                 c   s   || j k s|| jkrt| j||||| j kr'|| jkr'||  d S | jd u rQ|| j krA| | t| j	|||| | t| j
||||| jkrat| j	||||| jkrqt| j
|||| j	|| j|V  t| j
| j||r]   )rx   ry   r   TailCallrz   r   ru   r}   _splitr   r   r   r   r   r   r     s$   






z_Interval._loc_innerc                 C   s.   d| j j | jr
dnd | _| j jd | _d S )Nr   r   r   )rz   r~   r{   r   r   r   r   r   _set_spawn_key_and_depth=  s   z"_Interval._set_spawn_key_and_depthc                 C   sd   | j jr+| d| j| j   || jkr| j| d S || jk r)| j| d S d S | | d S rY   )	r|   _halfway_tree_split_exactry   rx   r}   r   r   r   )r_   midwayr   r   r   r   A  s   

z_Interval._splitc                 C   s   | j || _|   tjj| j j| j| j	f| j j
d}|d\| _| _| _| _t| j|| d| j d| _t|| j| d| j d| _d S )N)entropy	spawn_key	pool_size   Tr   r   r   r   r   F)r|   r   r}   r   nprandomSeedSequence_entropyr~   r   
_pool_sizegenerate_stater   r   r   r   rw   rx   r   ry   r   )r_   r   r   r   r   r   r   L  s&   
z_Interval._split_exactN)rg   rh   ri   	__slots__rl   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rw      s    7'rw   c                       st  e Zd ZdZdZdddddddddddejddfd	ee d
ee dee	e
df  deej deeeejf  dee
 dee dede
dee
 dededee dee f fddZdd Zdd Zdd Zd>d d!Zd"d# Zd$d% Zd&d' Zed(d) Zed*d+ Zed,d- Zed.d/ Zed0d1 Zed2d3 Zed4d5 Zed6d7 Z ed8d9 Z!ed:d; Z"d<d= Z#  Z$S )?BrownianIntervala8  Brownian interval with fixed entropy.

    Computes increments (and optionally Levy area).

    To use:
    >>> bm = BrownianInterval(t0=0.0, t1=1.0, size=(4, 1), device='cuda')
    >>> bm(0., 0.5)
    tensor([[ 0.0733],
            [-0.5692],
            [ 0.1872],
            [-0.3889]], device='cuda:0')
    )r   r   r   r   r   _dt_tolr   _cache_sizer   r   r   _last_intervalr   _have_A_w_h_top_a_seed_average_dt_tree_dt_num_evaluations        g      ?N   -   Ft0t1r   .r   r   r   dttolr   
cache_sizehalfway_treerO   rL   rM   c                    s  t |stdt |std|durt |std||kr+td| d| dt|}t|}|dur;t|}|rN|dkrEtd	|durMtd
n|dk rVtdt|||||d\}}}|du rmtjdd}|tvr|tdt d| d|| _|| _	|| _
|| _|| _|| _|| _|	| _|
| _|| _|
du ri | _n|
dkrt | _nt|
d| _| | _| jtjtjtjfv | _| jtjtjfv | _|dkrdd | _ntt|   fdd| _tt | j!||dd| d tjj"||	d}|#d\}}}|du r| $|t%||  }nt&d| |du r+| $|t%|| d  }nt&d| ||f| _'|| _(| jsSd| _)|| | _*d| _+|durU| ,| dS dS dS )a?  Initialize the Brownian interval.

        Args:
            t0 (float or Tensor): Initial time.
            t1 (float or Tensor): Terminal time.
            size (tuple of int): The shape of each Brownian sample.
                If zero dimensional represents a scalar Brownian motion.
                If one dimensional represents a batch of scalar Brownian motions.
                If >two dimensional the last dimension represents the size of a
                a multidimensional Brownian motion, and all previous dimensions
                represent batch dimensions.
            dtype (torch.dtype): The dtype of each Brownian sample.
                Defaults to the PyTorch default.
            device (str or torch.device): The device of each Brownian sample.
                Defaults to the CPU.
            entropy (int): Global seed, defaults to `None` for random entropy.
            levy_area_approximation (str): Whether to also approximate Levy
                area. Defaults to 'none'. Valid options are 'none',
                'space-time', 'davie' or 'foster', corresponding to different
                approximation types.
                This is needed for some higher-order SDE solvers.
            dt (float or Tensor): The expected average step size of the SDE
                solver. Set it if you know it (e.g. when using a fixed-step
                solver); else it will be estimated from the first few queries.
                This is used to set up the data structure such that it is
                efficient to query at these intervals.
            tol (float or Tensor): What tolerance to resolve the Brownian motion
                to. Must be non-negative. Defaults to zero, i.e. floating point
                resolution. Usually worth setting in conjunction with
                `halfway_tree`, below.
            pool_size (int): Size of the pooled entropy. If you care about
                statistical randomness then increasing this will help (but will
                slow things down).
            cache_size (int): How big a cache of recent calculations to use.
                (As new calculations depend on old calculations, this speeds
                things up dramatically, rather than recomputing things.)
                Set this to `None` to use an infinite cache, which will be fast
                but memory inefficient.
            halfway_tree (bool): Whether the dependency tree (the internal data
                structure) should be the dyadic tree. Defaults to `False`.
                Normally, the sample path is determined by both `entropy`,
                _and_ the locations and order of the query points. Setting this
                 to `True` will make it deterministic with respect to just
                 `entropy`; however this is much slower.
            W (Tensor): The increment of the Brownian motion over the interval
                [t0, t1]. Will be generated randomly if not provided.
            H (Tensor): The space-time Levy area of the Brownian motion over the
                interval [t0, t1]. Will be generated randomly if not provided.
        z6Initial time t0 should be a float or 0-d torch.Tensor.z7Terminal time t1 should be a float or 0-d torch.Tensor.NzDExpected average time step dt should be a float or 0-d torch.Tensor.zInitial time z# should be less than terminal time .r   z`tol` should be positive.zG`dt` is not used and should be set to `None` if `halfway_tree` is True.z`tol` should be non-negative.)r   r   r   r   iz)`levy_area_approximation` must be one of z, but got 'z'.)ro   c                 S   s   | S r]   r   r   r   r   r   <lambda>  s    z+BrownianInterval.__init__.<locals>.<lambda>c                    s
   t |  S r]   )roundr   ndigitsr   r   r     s   
 r   )r   r   r   rL      rM   i)-r   r!   r   r>   r   r   randintr   r   r   r   r   r   r   r   r   r   r   r   r\   rj   r   rC   davierH   r   r   r   r   rJ   log10rk   r   rl   r   r   r   rI   r%   r   r   r   r   r   _create_dependency_tree)r_   r   r   r   r   r   r   r   r   r   r   r   rO   rL   rM   r   initial_W_seedinitial_H_seed
top_a_seedrp   r   r   rl     s   E









zBrownianInterval.__init__c                 c   s    | j S r]   )r   r   r   r   r   r   B  s   z4BrownianInterval._increment_and_space_time_levy_areac                 C      | j S r]   )r   r   r   r   r   r   F     zBrownianInterval._a_seedc                 C   s   d| _ d| _d S rr   )r~   r   r   r   r   r   r   I  s   
z)BrownianInterval._set_spawn_key_and_depthc                 C   sL  |d u rt | jj d | j|}}d}nd}t|}t|}|| jk r6t d| d| j d | j}|| jk rQt d| d| d	| d| j d	 | j}|| jkrft d
| d| j d | j}|| jkrt d| d| d	| d| j d	 | j}||krtd|dd|dd||krtj	| j
| j| jd}d }d }| jrtj	| j
| j| jd}| jrg | j
| j
dd  R }	tj	|	| j| jd}n| jd u r| js|  jd7  _| jdkr|| }
|
| j| jd   | j | _| jd| j k r| |
 | j||}|d | _|d  \}}}t|dkr|dd  D ]X}| \}}}| jrT|j|j |d|   }|j| |d|   }|| |j|  }| jrzt| j
dvrz|| d|d|d |d|d    }|| }q'd }| jrt|||| }|r|r|||fS ||fS |r||fS |S )Nz? is optimised for interval-based queries, not point evaluation.r   r   zShould have ta>=t0 but got ta=z and t0=r   zShould have z>=t0 but got r   zShould have ta<=t1 but got ta=z and t1=z<=t1 but got zQuery times ta=.3fz and tb=z must respect ta <= tb.)r   r   r@   r   r   rZ   r?   rA   )warningswarnrq   rg   rx   r   ry   RuntimeErrorr   zerosr   r   r   r   r   r   r   r   r   r   r   r   r   r   r9   rF   r[   )r_   r   r   return_Ureturn_Atb_namerL   rM   rQ   r   r   	intervalsintervalWiHiAiterm1term2Ur   r   r   __call__M  sz   

&

&

4
zBrownianInterval.__call__c                    sR   | j d u rd}nt| j d}t| j|| _| j| d  fdd  |  d S )Nd   g?c                    sL   | j }| j}|| kr$|| d }| ||  | j  | j d S d S )Nr   )rx   ry   r   r   r   )r   r   r   r   _set_pointspiece_lengthr   r   r     s   
z=BrownianInterval._create_dependency_tree.<locals>._set_points)r   minr   )r_   r   r   r   r   r   r     s   
	z(BrownianInterval._create_dependency_treec                 C   s   | j d u rd }n| j d}| jj d| jdd| jdd| j d| j dt| j d| j	 d| d	| j
 d
| j d| j dt| j dS )Nr   z(t0=z, t1=z, size=z, dtype=z	, device=z
, entropy=z, dt=z, tol=z, pool_size=z, cache_size=z, levy_area_approximation=))r   rq   rg   rx   ry   r   r   reprr   r   r   r   r   r   )r_   r   r   r   r   __repr__  s4   


	
zBrownianInterval.__repr__c                 C   s   | dfg}g }t |r@| \}}|d| d|j d|j d  |jd ur<||j|d f ||j|d f t |std	| d S )Nr    (z, r   r   
)
r9   rt   ru   rx   ry   r}   r   r   printjoin)r_   stackr   elemdepthr   r   r   display_binary_tree  s   
$
z$BrownianInterval.display_binary_treec                 C   r   r]   r   r   r   r   r   r(        zBrownianInterval.shapec                 C   r   r]   )r   r   r   r   r   r     r  zBrownianInterval.dtypec                 C   r   r]   )r   r   r   r   r   r     r  zBrownianInterval.devicec                 C   r   r]   )r   r   r   r   r   r     r  zBrownianInterval.entropyc                 C   r   r]   )r   r   r   r   r   rO     r  z(BrownianInterval.levy_area_approximationc                 C   r   r]   )r   r   r   r   r   r     r  zBrownianInterval.dtc                 C   r   r]   )r   r   r   r   r   r      r  zBrownianInterval.tolc                 C   r   r]   )r   r   r   r   r   r     r  zBrownianInterval.pool_sizec                 C   r   r]   )r   r   r   r   r   r     r  zBrownianInterval.cache_sizec                 C   r   r]   )r   r   r   r   r   r     r  zBrownianInterval.halfway_treec                 C   r   r]   r  r   r   r   r   r     r   zBrownianInterval.size)NFF)%rg   rh   ri   __doc__r   r   rB   r   r   r   r   r   r   r	   strr   boolr
   rl   r   r   r   r   r   r  r  propertyr(   r   rO   r   r   r   r   r   r   rv   r   r   rp   r   r   a  s    	
 9
d









r   ) rJ   r   r   numpyr   r    r   settingsr   typesr   r   r   r	   r
   rI   r   rK   r   r   r%   r>   rW   r   r[   r\   dictrj   rw   BaseBrownianr   r   r   r   r   <module>   s*      a