B
    zdX                 @   s   d dl Z d dlmZ ddlmZmZmZ ddlmZ G dd deZ	G dd	 d	eZ
G d
d dee	ZG dd dee
ZG dd dee	ZG dd dee
Zdd Zdd ZdS )    N)stats   )NormalAdaptiveSupportSSAdaptiveSupport)BoundedNormalc                   s`   e Zd ZdZdZdZdZd fdd	Zedd	 Z	e	j
d
d	 Z	dd Zdd Zdd Z  ZS )NormalDiscretea	  A proposal for discrete parameters.

    The jump proposals produced by this are always integer values. For a given
    point :math:`x \in \mathbb{Z}`, a new point :math:`x' = x + \bar{\Delta x}`
    is generated by using

    .. math::

        \bar{\Delta x} = \begin{cases}
            \lfloor \Delta x \rfloor \textrm{ if } \Delta x < 0, \\
            \lceil \Delta x \rceil \textrm{ if } \Delta x > 0,
            \end{cases}

    where :math:`\Delta x \sim \mathcal{N}(0, \sigma)` if `successive`
    is False. This results in a stepped probability density that is zero
    :math:`\in [0, 1)`. In other words, the proposal will never produce the
    same integer on successive jumps, and it will most often draw integers
    closest to the current point.

    If `successive` is True, then for a given point :math:`x \in \mathbb{Z}`,
    a new point :math:`x' = x + \bar{\Delta x}` is generated by using

    .. math:: \bar{\Delta x} = Round\left(\mathcal{N}(0, \sigma)\right),

    meaning that the proposal can now propose the same integer on successive
    jumps.

    The variance used for drawing :math:`\Delta x` need not be an integer,
    and can be set. Multiple parameters are supported, however, they all must
    be independent of each other.

    Parameters
    ----------
    parameters : (list of) str
        The names of the parameters to produce proposals for.
    cov : array, optional
        The covariance matrix of the parameters. May provide either a single
        float, a 1D array with length ``ndim``, or an ``ndim x ndim`` array,
        where ``ndim`` = the number of parameters given. If 2D array is given,
        the off-diagonal terms must be zero. Default is 1 for all parameters.
    successive: dict, optional
        Dictionary of bools, keys must be parameters and items bools. If False
        then the proposal never produces the same integer on successive jumps.
        Default is False for all parameters
    jump_interval : int, optional
        The jump interval of the proposal, the proposal only gets called every
        jump interval-th time. After ``jump_interval_duration`` number of
        proposal steps elapses the proposal will again be called on every
        chain iteration. By default ``jump_interval`` = 1.
    jump_interval_duration : int, optional
        The number of proposals steps during which values of ``jump_interval``
        other than 1 are used. After this elapses the proposal is called on
        each iteration.
    ZdiscreteTNr   c                sP   t  j||||d | js"td|| _i gt| j | _d gt| j | _d S )N)covjump_intervaljump_interval_durationz`Only independent variables are supported (all off-diagonal terms in the covariance must be zero))	super__init__Z
isdiagonal
ValueError
successivelen
parameters	_cdfcache
_cachedstd)selfr   r	   r   r
   r   )	__class__ e/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/epsie/proposals/discrete.pyr   S   s    zNormalDiscrete.__init__c             C   s   | j S )z~Dictionary of `successive` toggles for each parameter. If True
        allows two equal integers on successive jumps.
        )_successive)r   r   r   r   r   b   s    zNormalDiscrete.successivec                s    d krdd | j D | _d S t fddt  D sDtdy fdd| j D | _W n tk
rz   tdY nX d S )Nc             S   s   i | ]
}d |qS )Fr   ).0pr   r   r   
<dictcomp>l   s    z-NormalDiscrete.successive.<locals>.<dictcomp>c                s   g | ]}t  | tqS r   )
isinstancebool)r   r   )r   r   r   
<listcomp>n   s   z-NormalDiscrete.successive.<locals>.<listcomp>z#all dictionary values must be boolsc                s   i | ]} | |qS r   r   )r   r   )r   r   r   r   r   s    z,must provide `successive` for each parameter)r   r   alllistkeysr   KeyError)r   r   r   )r   r   r   i   s    c             C   sl   || j | kr| j|   y| j| | S  tk
rf   tjj||d}|| j| |< || j |< |S X dS )aT  Caches CDF for faster call back.

        Parameters
        ----------
        pi : int
            Index of parameter that is being evaluated.
        dx : int
            Value to evaulate. Should be the difference between a point and
            the mean.
        std : float
            Standard deviation of the distribution.
        )scaleN)r   r   clearr"   r   Znormcdf)r   pidxstdr%   r   r   r   _cdfw   s    
zNormalDiscrete._cdfc             C   sn   i }xdt | jD ]V\}}| jd| j| }| j| rFtt|d}ntt|}t|| | ||< qW |S )Nr   )		enumerater   random_generatornormal_stdr   intround
_floorceil)r   fromxto_xiir   r'   r   r   r   _jump   s    
zNormalDiscrete._jumpc       
      C   s  d}xt | jD ]\}}| j| rttj|| ||  dd}t|}| ||d | j| }| ||d | j| }|| }	nvtt	|| ||  }|dkrtj
 S t|}| ||d | j| }| ||| j| }|| }	|	dkrtj
 S |t|	7 }qW |S )Nr   )Zdecimalsg      ?r   )r*   r   r   r.   numpyr/   absr)   r-   floorinflog)
r   xigivenxlogpr3   r   r'   p0p1Zdpr   r   r   _logpdf   s&    

zNormalDiscrete._logpdf)NNr   N)__name__
__module____qualname____doc__name	symmetricr   r   propertyr   setterr)   r4   r?   __classcell__r   r   )r   r   r      s   6 r   c                   s`   e Zd ZdZdZdZdZd fdd	Zedd	 Z	e	j
d
d	 Z	dd Zdd Zdd Z  ZS )BoundedDiscretea  A proposal for discrete parameters with bounds.

    This is a discretized form of :py:class:`BoundedNormal`. Jump proposals
    are produced in the same manner as :py:class:`NormalDiscrete`, except
    that the distribution used to draw :math:`\Delta x` (before applying the
    floor/ceil or round) is a truncated normal. As such, this is not a
    symmetric distribution.

    The variance used for drawing :math:`\Delta x` need not be an integer,
    and can be set. Multiple parameters are supported, however, they all must
    be independent of each other.

    Parameters
    ----------
    parameters : (list of) str
        The names of the parameters to produce proposals for.
    boundaries : dict
        Dictionary mapping parameters to boundaries. Boundaries must be a
        tuple or iterable of length two. If floats are provided, the floor
        (ceil) of the lower (upper) bound will be used.
    cov : array, optional
        The covariance matrix of the parameters. May provide either a single
        float, a 1D array with length ``ndim``, or an ``ndim x ndim`` array,
        where ``ndim`` = the number of parameters given. If 2D array is given,
        the off-diagonal terms must be zero. Default is 1 for all parameters.
    successive: dict, optional
        Dictionary of bools, keys must be parameters and items bools. If False
        then the proposal never produces the same integer on successive jumps.
        Default is False for all parameters
    jump_interval : int, optional
        The jump interval of the proposal, the proposal only gets called every
        jump interval-th time. After ``jump_interval_duration`` number of
        proposal steps elapses the proposal will again be called on every
        chain iteration. By default ``jump_interval`` = 1.
    jump_interval_duration : int, optional
        The number of proposals steps during which values of ``jump_interval``
        other than 1 are used. After this elapses the proposal is called on
        each iteration.
    Zbounded_discreteFNr   c                sZ   t  j|||||d || _dd | j D | _i gt| j | _d gt| j | _d S )N)r	   r
   r   c             S   s2   i | ]*\}}t t|jt t|jf|qS r   )r.   r5   r7   lowerceilupper)r   r   br   r   r   r      s   z,BoundedDiscrete.__init__.<locals>.<dictcomp>)	r   r   r   
boundariesitemsr   r   r   r   )r   r   rN   r	   r   r
   r   )r   r   r   r      s    zBoundedDiscrete.__init__c             C   s   | j S )z~Dictionary of `successive` toggles for each parameter. If True
        allows two equal integers on successive jumps.
        )r   )r   r   r   r   r      s    zBoundedDiscrete.successivec                s    d krdd | j D | _d S t fddt  D sDtdy fdd| j D | _W n tk
rz   tdY nX d S )Nc             S   s   i | ]
}d |qS )Fr   )r   r   r   r   r   r      s    z.BoundedDiscrete.successive.<locals>.<dictcomp>c                s   g | ]}t  | tqS r   )r   r   )r   r   )r   r   r   r      s   z.BoundedDiscrete.successive.<locals>.<listcomp>z#all dictionary values must be boolsc                s   i | ]} | |qS r   r   )r   r   )r   r   r   r      s    z,must provide `successive` for each parameter)r   r   r   r    r!   r   r"   )r   r   r   )r   r   r      s    c          
   C   s   || j | kr| j|   y| j| ||||f S  tk
r   tjj||| || ||d}|| j| ||||f< || j |< |S X dS )a  Caches CDF for faster call back.

        Parameters
        ----------
        pi : int
            Index of parameter that is being evaluated.
        x : int
            Value to evaulate.
        a : int
            Lower bound of the distribution (with respect to mu).
        b : int
            Upper bound of the distribution (with respect to mu).
        mu : int
            Mean of the distribution.
        std : float
            Standard deviation of the distribution.
        )locr#   N)r   r   r$   r"   r   Z	truncnormr%   )r   r&   xarM   mur(   r%   r   r   r   r)     s    
zBoundedDiscrete._cdfc             C   s   || krt di }xt| jD ]v\}}d}x^|s| jd| j| }| j| r`tt|d}ntt	|}|t|| | i}|| k}q.W |
| q W |S )NzBGiven point is not in bounds; I don't know how to jump from there.Fg        r   )r   r*   r   r+   r,   r-   r   r.   r/   r0   update)r   r1   r2   r3   r   ZinbndsZdeltaxZnewptr   r   r   r4     s    
zBoundedDiscrete._jumpc          
   C   st  d}xht | jD ]X\}}| j| rtt|| d}tt|| d}| j| | }| j| | }	| ||d ||	|| j| }
| ||d ||	|| j| }|t	
||
 7 }qtt|| }tt|| }||krt	j S | j| | }| j| | }	||kr|d }|}n|}|d }| ||||	|| j| }
| ||||	|| j| }|t	
||
 7 }qW |S )Nr   g      ?r   )r*   r   r   r.   r/   Z	_lowerbndZ	_upperbndr)   r-   r5   r9   r0   
_ceilfloorr8   )r   r:   r;   r<   r3   r   rS   rQ   rR   rM   r=   r>   Zx0x1r   r   r   r?   8  s2    

zBoundedDiscrete._logpdf)NNr   N)r@   rA   rB   rC   rD   rE   r   r   rF   r   rG   r)   r4   r?   rH   r   r   )r   r   rI      s   ' rI   c                   s*   e Zd ZdZdZdZd fdd	Z  ZS )	SSAdaptiveNormalDiscretea=  A discrete proposoal with adaptive variance, using the algorithm from
    Sivia and Skilling.

    See :py:class:`SSAdaptiveSupport` for details on the adaptation algorithm.

    Parameters
    ----------
    parameters : (list of) str
        The names of the parameters to produce proposals for.
    cov : array, optional
        The covariance matrix of the parameters. May provide either a single
        float, a 1D array with length ``ndim``, or an ``ndim x ndim`` array,
        where ``ndim`` = the number of parameters given. If 2D array is given,
        the off-diagonal terms must be zero. Default is 1 for all parameters.
    jump_interval : int, optional
        The jump interval of the proposal, the proposal only gets called every
        jump interval-th time. After ``jump_interval_duration`` number of
        proposal steps elapses the proposal will again be called on every
        chain iteration. By default ``jump_interval`` = 1.
    jump_interval_duration : int, optional
        The number of proposals steps during which values of ``jump_interval``
        other than 1 are used. After this elapses the proposal is called on
        each iteration.
    \**kwargs :
        All other keyword arguments are passed to
        :py:func:`SSAdaptiveSupport.setup_adaptation`. See that function for
        details.
    Zss_adaptive_discreteTNr   c                s&   t  j|||||d | jf | d S )N)r	   r   r
   r   )r   r   setup_adaptation)r   r   r	   r   r
   r   kwargs)r   r   r   r     s
    z!SSAdaptiveNormalDiscrete.__init__)NNr   N)r@   rA   rB   rC   rD   rE   r   rH   r   r   )r   r   rW   d  s
    rW   c                   s*   e Zd ZdZdZdZd fdd	Z  ZS )	SSAdaptiveBoundedDiscretea&  A bounded discrete proposoal with adaptive variance, using the
    algorithm from Sivia and Skilling.

    See :py:class:`AdaptiveSupport` for details on the adaptation algorithm.

    Parameters
    ----------
    parameters : (list of) str
        The names of the parameters to produce proposals for.
    boundaries : dict
        Dictionary mapping parameters to boundaries. Boundaries must be a
        tuple or iterable of length two. If floats are provided, the floor
        (ceil) of the lower (upper) bound will be used.
    cov : array, optional
        The covariance matrix of the parameters. May provide either a single
        float, a 1D array with length ``ndim``, or an ``ndim x ndim`` array,
        where ``ndim`` = the number of parameters given. If 2D array is given,
        the off-diagonal terms must be zero. Default is 1 for all parameters.
    jump_interval : int, optional
        The jump interval of the proposal, the proposal only gets called every
        jump interval-th time. After ``jump_interval_duration`` number of
        proposal steps elapses the proposal will again be called on every
        chain iteration. By default ``jump_interval`` = 1.
    jump_interval_duration : int, optional
        The number of proposals steps during which values of ``jump_interval``
        other than 1 are used. After this elapses the proposal is called on
        each iteration.
    \**kwargs :
        All other keyword arguments are passed to
        :py:func:`SSAdaptiveSupport.setup_adaptation`. See that function for
        details.
    Zss_adaptive_bounded_discreteFNr   c       	         sT   t  j||||||d d|krDttt| j }d| d |d< | jf | d S )N)r	   r   r
   r   Zmax_covgףp=
?   )r   r   maxmapr6   rN   valuesrX   )	r   r   rN   r	   r   r
   r   rY   Zmaxwidth)r   r   r   r     s    z"SSAdaptiveBoundedDiscrete.__init__)NNr   N)r@   rA   rB   rC   rD   rE   r   rH   r   r   )r   r   rZ     s
     rZ   c                   s*   e Zd ZdZdZdZd fdd	Z  ZS )	AdaptiveNormalDiscretea  A discrete proposoal with adaptive variance, using the algorithm from
    Veitch et al.

    See :py:class:`AdaptiveSupport` for details on the adaptation algorithm.

    Parameters
    ----------
    parameters : (list of) str
        The names of the parameters to produce proposals for.
    prior_widths : dict
        Dictionary mapping parameter names to values giving the width of each
        parameter's prior. The values may be floats, or any object that has
        an ``__abs__`` method that will return a float.
    adaptation_duration: int
        The number of proposal steps over which to apply the adaptation. No
        more adaptation will be done once a proposal exceeds this value.
    jump_interval : int, optional
        The jump interval of the proposal, the proposal only gets called every
        jump interval-th time. After ``adaptation_duration`` number of
        proposal steps elapses the proposal will again be called on every
        chain iteration. By default ``jump_interval`` = 1.
    \**kwargs :
        All other keyword arguments are passed to
        :py:func:`AdaptiveSupport.setup_adaptation`. See that function for
        details.
    Zadaptive_discreteTNr   c                s(   t  j||||d | j||f| d S )N)r   r
   r   )r   r   rX   )r   r   Zprior_widthsadaptation_durationr   r
   rY   )r   r   r   r     s    zAdaptiveNormalDiscrete.__init__)Nr   )r@   rA   rB   rC   rD   rE   r   rH   r   r   )r   r   r_     s   r_   c                   s*   e Zd ZdZdZdZd fdd	Z  ZS )	AdaptiveBoundedDiscreteas  A bounded discrete proposoal with adaptive variance.

    See :py:class:`AdaptiveSupport` for details on the adaptation algorithm.

    Parameters
    ----------
    parameters : (list of) str
        The names of the parameters to produce proposals for.
    boundaries : dict
        Dictionary mapping parameters to boundaries. Boundaries must be a
        tuple or iterable of length two. If floats are provided, the floor
        (ceil) of the lower (upper) bound will be used.
    adaptation_duration: int
        The number of proposal steps over which to apply the adaptation. No
        more adaptation will be done once a proposal exceeds this value.
    jump_interval : int, optional
        The jump interval of the proposal, the proposal only gets called every
        jump interval-th time. After ``adaptation_duration`` number of
        proposal steps elapses the proposal will again be called on every
        chain iteration. By default ``jump_interval`` = 1.
    \**kwargs :
        All other keyword arguments are passed to
        :py:func:`AdaptiveSupport.setup_adaptation`. See that function for
        details.
    Zadaptive_bounded_discreteFNr   c                s,   t  j|||d|d | j| j|f| d S )Nr   )r   r
   r   )r   r   rX   rN   )r   r   rN   r`   r   r
   rY   )r   r   r   r     s    z AdaptiveBoundedDiscrete.__init__)Nr   )r@   rA   rB   rC   rD   rE   r   rH   r   r   )r   r   ra     s   ra   c             C   s   t | t t|  S )z'Returns floor (ceil) of values < (>) 0.)r5   signrK   r6   )rQ   r   r   r   r0     s    r0   c             C   s   t | t t|  S )z+Returns the ceil (floor) of values < (>) 0.)r5   rb   r7   r6   )rQ   r   r   r   rU     s    rU   )r5   Zscipyr   r,   r   r   r   Zbounded_normalr   r   rI   rW   rZ   r_   ra   r0   rU   r   r   r   r   <module>   s     0+3(0