B
    zd,                 @   s   d dl Z d dlmZ ddlmZmZmZmZ ddlm	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dS )    N)stats   )NormalAdaptiveSupportSSAdaptiveSupportATAdaptiveSupport)
Boundariesc                   sB   e Zd ZdZdZdZd fdd	Zdd	 Zd
d Zdd Z	  Z
S )Angulara  A propsal distribution for parameters that are cyclic over
    :math:`[0, 2\pi)`.

    To generate a jump proposal from a given point, a truncated normal
    distribution centered on the point and with bounds at :math:`\pm \pi`
    around the point. Cyclic bounds are then applied, resulting in a proposed
    point that is in :math:`[0, 2\pi)`. For example, if a the given point is
    at :math:`1.75\pi` and the jump is :math:`+0.5\pi`, then proposed point
    will be at :math:`0.25\pi`. Since the same proposal distribution is used
    regardless of the location, this is a symmetric proposal.

    This proposal can handle more than one parameter; however, parameters must
    all be independent of each other.

    Parameters
    ----------
    parameters : (list of) str
        The names of the parameters to create proposals for.
    cov : (array of) float, optional
        The covariance to use for the underlying truncated normal
        distribution, in squared radians. 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 sq. radian 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.

    angularTNr   c                s@   t  j||||d d| _tj| _dtj | _t| j| _d S )N)covjump_intervaljump_interval_durationg      ?)	super__init__
_halfwidthnumpypi_factor
_invfactorlog
_logfactor)self
parametersr   r   r   )	__class__ d/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/epsie/proposals/angular.pyr   @   s    zAngular.__init__c             C   s   |d| j   S )a9  Applies cyclic boundaries to the given value.

        This causes the value to lie within 0 and ``2*_halfwidth``. With the
        default ``_halfwidth`` = 1, this means the value will be within 0
        and 2.

        Parameters
        ----------
        value : float
            The value to apply the boundaries to.
        offset : float, optional
            Offset to apply. If none provided, will use the ``_offset``
            attribute.

        Returns
        -------
        float :
            The value remapped to be within the boundaries.
           )r   )r   valuer   r   r   _apply_cyclicL   s    zAngular._apply_cyclicc             C   s   i }xt | jD ]r\}}| j| | j }| jj|d}x t|| jkrV| jj|d}q8W ||| | j 7 }| |}|| j	 ||< qW |S )N)scale)
	enumerater   _stdr   Zrandom_generatornormalabsr   r   r   )r   ZfromxZto_xiipstdZnewptr   r   r   _jumpb   s    
zAngular._jumpc                s   t fddjD t  fddjD    j  }| jj }j| }| }tjj	||j|d
 j S )Nc                s   g | ]}|  j  qS r   )r   ).0r%   )r   xir   r   
<listcomp>v   s    z#Angular._logpdf.<locals>.<listcomp>c                s   g | ]} | j  qS r   )r   )r(   r%   )givenxr   r   r   r*   w   s   )locr   )r   arrayr   r   r   r!   r   r   Z	truncnormZlogpdfsumr   )r   r)   r+   Zdxr&   bar   )r+   r   r)   r   _logpdft   s    



zAngular._logpdf)Nr   N)__name__
__module____qualname____doc__name	symmetricr   r   r'   r1   __classcell__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 )AdaptiveAngulara(  An angular 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.
    boundaries : dict
        Dictionary mapping parameters to boundaries. Boundaries must be a
        tuple or iterable of length two. The boundaries will be used for the
        prior widths in the adaptation algorithm.
    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.
    start_step : int, optional
        The proposal step to start doing the adaptation (:math:`k_0+1` in the
        equation below). Must be greater than zero. Default is 1.
    \**kwargs :
        All other keyword arguments are passed to
        :py:func:`AdaptiveSupport.setup_adaptation`. See that function for
        details.
    Zadaptive_angularTr   c                sB   t  j|||d  fdd jD } j||fd|i| d S )N)r   r   c                s&   i | ]}t d d j  j f|qS )r   r   )r   r   r   )r(   r%   )r   r   r   
<dictcomp>   s   z,AdaptiveAngular.__init__.<locals>.<dictcomp>
start_step)r   r   r   setup_adaptation)r   r   adaptation_durationr   r;   kwargsZ
boundaries)r   )r   r   r      s    

zAdaptiveAngular.__init__)r   r   )r2   r3   r4   r5   r6   r7   r   r8   r   r   )r   r   r9      s
    r9   c                   s*   e Zd ZdZdZdZd fdd	Z  ZS )	SSAdaptiveAngulara  An angular 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.
    boundaries : dict
        Dictionary mapping parameters to boundaries. Boundaries must be a
        tuple or iterable of length two. The boundaries will be used for the
        prior widths in the adaptation algorithm.
    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_angularTNr   c                s>   t  j||||d d|kr.dtj d |d< | jf | d S )N)r   r   r   Zmax_covgףp=
@r   )r   r   r   r   r<   )r   r   r   r   r   r>   )r   r   r   r      s    zSSAdaptiveAngular.__init__)Nr   N)r2   r3   r4   r5   r6   r7   r   r8   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 )
ATAdaptiveAngulara  An angular proposal with adaptive variance, using the algorithm from
    Andrieu & Thoms.

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

    Parameters
    ----------
    parameters : (list of) str
        The names of the parameters.
    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.
    start_step: int, optional
        The proposal step index when adaptation phase begins.
    target_rate: float, optional
        Target acceptance ratio. By default 0.234 and 0.48 for componentwise
        scaling.
    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.
    Zat_adaptive_angularTFr   Nc                s*   t  j|||d | j|d|||d d S )N)r   r   T)r=   Zdiagonalcomponentwiser;   target_rate)r   r   r<   )r   r   r=   rA   r;   rB   r   )r   r   r   r     s    zATAdaptiveAngular.__init__)Fr   Nr   )r2   r3   r4   r5   r6   r7   r   r8   r   r   )r   r   r@      s
    r@   )r   Zscipyr   r"   r   r   r   r   Zbounded_normalr   r	   r9   r?   r@   r   r   r   r   <module>   s   s/,