B
    z‹dõ7  ã               @   sx   d dl mZmZ d dlZd dlmZ d dlZd dl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ÚabstractmethodN)Ú	Generatorc               @   sŽ   e Zd ZdZdZdZedd„ ƒZejdd„ ƒZedd„ ƒZ	edd	„ ƒZ
e
jd
d	„ ƒZ
eedd„ ƒƒZedd„ ƒZedd„ ƒZejdd„ ƒZdS )Ú
BaseRandomaƒ  Abstract base class for handling random number generation for proposals
    ans birth distributions.

    All proposals must inherit from this class, as it handles random number
    generation.

    .. warning ::
        All proposals must use the random number generator provided by this
        class (see the ``random_generator`` attribute) for creating random
        numbers. **Do not attempt to use scipy/numpy's random number
        generator.** Use of any other generator may result in chains not being
        independent of each other when run in a parallel environment.

    In addition to the abstract methods/properties, all samplers must set
    a ``parameters`` attribute. This is a list of the names of the parameters
    the proposal produces jumps and births for.

    Attributes
    ----------
    bit_generator
    random_generator
    random_state
    parameters
    state
    Nc             C   s,   y| j S  tk
r&   t ¡ | _ | j S X dS )z6The random bit generator instance being used.
        N)Ú_bit_generatorÚAttributeErrorÚepsieÚcreate_bit_generator)Úself© r   úa/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/epsie/proposals/base.pyÚbit_generator6   s
    
zBaseRandom.bit_generatorc             C   s    t |tjƒst |¡}|| _dS )aw  Sets the random bit generator.

        Parameters
        ----------
        bit_generator : :py:class:`epsie.BIT_GENERATOR`, int, or None
            Either the bit generator to use or an integer/None. If the latter,
            a generator will be created by passing ``bit_generator`` as the
            ``seed`` argument to :py:func:`epsie.create_bit_generator`.
        N)Ú
isinstancer   ZBIT_GENERATORr	   r   )r
   r   r   r   r   r   @   s    
c             C   s
   t | jƒS )zçThe random number generator.

        This is an instance of :py:class:`numpy.random.Generator` that is
        derived from the bit generator. It provides methods to create random
        draws from various distributions.
        )r   r   )r
   r   r   r   Úrandom_generatorO   s    zBaseRandom.random_generatorc             C   s   | j jS )z7The current state of the random bit generator.
        )r   Ústate)r
   r   r   r   Úrandom_stateY   s    zBaseRandom.random_statec             C   s   || j _dS )z”Sets the state of bit_generator.
        Parameters
        ----------
        state : dict
            Dictionary giving the state to set.
        N)r   r   )r
   r   r   r   r   r   _   s    c             C   s   dS )a  Returns all information needed to produce a deterministic jump.
        The information returned by this property should be everything needed
        such that if you pass it to set_state, you will get the same proposal
        on the next call of jump.
        The information should be returned as a dictionary. At the very least,
        this should include the current state of the proposal's
        ``random_state``. For adaptive proposals, this may also include the
        buffer used to adjust the proposal distribution.
        Nr   )r
   r   r   r   r   i   s    zBaseRandom.statec             C   s   dS )zDSet all information needed to produce a deterministic jump.
        Nr   )r
   r   r   r   r   Ú	set_statew   s    zBaseRandom.set_statec             C   s   | j dkrtdƒ‚| j S )z?Sorted tuple of the parameters that proposals are produced for.Nzno parameters set)Ú_parametersr   )r
   r   r   r   Ú
parameters}   s    
zBaseRandom.parametersc             C   s    t |tjƒr|g}t|ƒ| _dS )a  Sets the parameters.

        The parameters are stored as a tuple.

        Parameters
        ----------
        parameters : (list of) str
            The names of the parameters. This may either be a list of strings,
            or (for a single parameter), a string.
        N)r   ÚsixÚstring_typesÚtupler   )r
   r   r   r   r   r   „   s    )Ú__name__Ú
__module__Ú__qualname__Ú__doc__Únamer   Úpropertyr   Úsetterr   r   r   r   r   r   r   r   r   r   r      s   


r   c               @   sª   e Zd ZdZdZdZdZdZdZe	dd„ ƒZ
e	dd„ ƒZe	dd	„ ƒZdd
d„Ze	edd„ ƒƒZdd„ Zdd„ Zedd„ ƒZdd„ Zedd„ ƒZdd„ Zdd„ Zdd„ ZdS )ÚBaseProposala¹  Abstract base class for all proposal classes.

    All proposals must inherit from this class, as it lays out all of the
    functions/attributes that a sampler will try to access.

    In addition to the abstract methods/properties, all samplers must set
    a ``parameters`` attribute. This is a list of the names of the parameters
    the proposal produces jumps for.

    Attributes
    ----------
    symmetric
    state
    nsteps
    Nr   c             C   s   | j | j S )zÌReturns number of update iterations with this proposal.

        While for a standard adaptive MCMC this will match the length of the
        chain for a transdimensional proposal it will differ.
        )Ú_nstepsÚjump_interval)r
   r   r   r   Únsteps«   s    zBaseProposal.nstepsc             C   s   | j S )z)Returns the jump interval for a proposal.)Ú_jump_interval)r
   r   r   r   r!   ´   s    zBaseProposal.jump_intervalc             C   s   | j S )zZReturns the number of steps after which no more fast jumps are
        performed.
        )Ú_jump_interval_duration)r
   r   r   r   Újump_interval_duration¹   s    z#BaseProposal.jump_interval_durationc             C   sL   |dkst dƒ‚t|ƒ| _| jdkrH|dk	r8t|ƒ| _nt d | j¡ƒ‚dS )z(Sets the jump interval and the duration.é   z``jump_interval`` must be >= 1NzJFor '{}' must provide ``jump_interval_duration`` if jump interval is not 1)Ú
ValueErrorÚintr#   r!   r$   Úformatr   )r
   r!   Údurationr   r   r   Úset_jump_intervalÀ   s    

zBaseProposal.set_jump_intervalc             C   s   dS )a¡  Boolean indicating whether the proposal distribution is symmetric.

        A jump proposal is symmetric if the proposal probability
        density has the property that :math:`p(x'|x) = p(x|x')`,
        where :math:`x` is the current position, :math:`x'` is the proposed
        position. In this, case, the Metropolis-Hastings ratio simplfies to
        just the ratio of posterior values at the two points.

        Note that an adaptive proposal may still be symmetric. Symmetry only
        means that the current state of the proposal satisfies the above
        condition; it does not necessarily mean that transitions between states
        be symmetric.
        Nr   )r
   r   r   r   Ú	symmetricÎ   s    zBaseProposal.symmetricc             C   s`   y| j | j d }W n tk
r.   | j }Y nX | jdksD|| jkrHdS | j| j dkr\dS dS )zrDecides whether to propose a unique jump with this proposal
        or whether to copy the last position.
        r&   Tr   F)r"   Ú
start_stepr   r!   r%   r    )r
   Zdkr   r   r   Ú
_call_jumpà   s    zBaseProposal._call_jumpc             C   s   |   ¡ s|S |  |¡S )z¹Depending on the current number of chain iterations and the
        ``jump_interval`` either calls the ``_jump`` method to provide a
        random sample or returns ``fromx``.
        )r.   Ú_jump)r
   Úfromxr   r   r   Újumpï   s    zBaseProposal.jumpc             C   s   dS )z°This should provide random samples from the proposal distribution.

        Samples should be returned as a dictionary mapping parameters to
        the proposed jump.
        Nr   )r
   r0   r   r   r   r/   ø   s    zBaseProposal._jumpc             C   s   |   ¡ sdS |  ||¡S )zÖDepending on the current number of chain iterations and the
        ``jump_interval`` either calls the ``_logpdf`` method or returns 0.0
        as the jump from ``givenx`` to ``xi`` was fully determinate.
        g        )r.   Ú_logpdf)r
   ÚxiÚgivenxr   r   r   Úlogpdf  s    zBaseProposal.logpdfc             C   s   dS )a³  The log pdf of the proposal distribution at a point.

        Parameters
        ----------
        xi : dict
            Dictionary mapping parameter names to values to evaluate.
        givenx : dict
            Dictionary mapping parameter names to values of the point from
            which ``xi`` is evaluated.

        Returns
        -------
        float :
            The log pdf of jumping from ``givenx`` to ``xi``.
        Nr   )r
   r3   r4   r   r   r   r2   
  s    zBaseProposal._logpdfc             C   s   t  |  ||¡¡S )aÝ  The pdf of the proposal at the given values.

        This just expoentiates ``logpdf``.

        Parameters
        ----------
        xi : dict
            Dictionary mapping parameter names to values to evaluate.
        givenx : dict, optional
            Dictionary mapping parameter names to values of the point from
            which ``xi`` is evaluated.

        Returns
        -------
        float :
            The pdf of jumping from ``givenx`` to ``xi``.
        )ÚnumpyÚexpr5   )r
   r3   r4   r   r   r   Úpdf  s    zBaseProposal.pdfc             C   s$   |   ¡ r|  |¡ |  jd7  _dS )zÃDepending on the current number of chain iterations and the
        ``jump_interval`` calls the ``_update`` method if the proposal
        distribution was used to sample a new position.
        r&   N)r.   Ú_updater    )r
   Úchainr   r   r   Úupdate1  s    
zBaseProposal.updatec             C   s   dS )aP  Update the state of the proposal distribution after a jump.

        This method may optionally be implemented by a proposal. It is called
        by the Markov chains just after a jump is evaluated. It can be used by,
        e.g., adaptive jump proposals that change their state depending on
        the history of the chain.
        Nr   )r
   r:   r   r   r   r9   ;  s    zBaseProposal._update)N)r   r   r   r   r   r    r#   Z_burnin_durationr$   r   r"   r!   r%   r+   r   r,   r.   r1   r/   r5   r2   r8   r;   r9   r   r   r   r   r   •   s(   	
			
r   c               @   s@   e Zd ZdZdZeedd„ ƒƒZedd„ ƒZdd„ Z	d	d
„ Z
dS )Ú	BaseBirthaµ  Abstract base class for all birth classes.

    All birth distributions must inherit from this class, as it lays out all of
    the functions/attributes that a sampler will try to access.

    In addition to the abstract methods/properties, all samplers must set
    a ``parameters`` attribute. This is a list of the names of the parameters
    the proposal produces jumps for.

    Attributes
    ----------
    symmetric
    state
    Nc             C   s   dS )z®This should provide random samples from the birth distribution.

        Samples should be returned as a dictionary mapping parameters to
        the proposed birth.
        Nr   )r
   r   r   r   ÚbirthW  s    zBaseBirth.birthc             C   s   dS )a  The log pdf of the birth distribution at a point.

        Parameters
        ----------
        xi : dict
            Dictionary mapping parameter names to values to evaluate.

        Returns
        -------
        float :
            The log pdf of a birth at ``xi``.
        Nr   )r
   r3   r   r   r   r5   a  s    zBaseBirth.logpdfc             C   s   t  |  |¡¡S )aA  The pdf of the birth proposal at the given values.

        This just expoentiates ``logpdf``.

        Parameters
        ----------
        xi : dict
            Dictionary mapping parameter names to values to evaluate.

        Returns
        -------
        float :
            The pdf of a birth at ``xi``.
        )r6   r7   r5   )r
   r3   r   r   r   r8   q  s    zBaseBirth.pdfc             C   s   dS )z±Update the state of the birth distribution after a jump.

        This method may optionally be implemented by a birth. It is called
        after a birth is evaluated.
        Nr   )r
   r:   r   r   r   r;   ‚  s    zBaseBirth.update)r   r   r   r   r   r   r   r=   r5   r8   r;   r   r   r   r   r<   F  s   	r<   c               @   sv   e Zd ZdZdZdZdZedd„ ƒZej	dd„ ƒZedd„ ƒZ
e
j	dd„ ƒZ
ed	d
„ ƒZej	dd
„ ƒZedd„ ƒZdS )ÚBaseAdaptiveSupportz2Abstract base class for all proposal classes.
    Nc             C   s   | j S )z'The iteration that the adaption begins.)Ú_start_step)r
   r   r   r   r-   ’  s    zBaseAdaptiveSupport.start_stepc             C   s   |dk rt dƒ‚|| _dS )z1Sets the start iteration, making sure it is >= 1.r&   zstart_step must be >= 1N)r'   r?   )r
   r-   r   r   r   r-   —  s    c             C   s   | j S )zThe adaptation duration used.)Ú_adaptation_duration)r
   r   r   r   Úadaptation_durationž  s    z'BaseAdaptiveSupport.adaptation_durationc             C   s   |dk rt dƒ‚|| _dS )zbSets the adaptation duration to the given value, making sure it is
        larger than 1.
        r&   z adaptation duration must be >= 1N)r'   r@   )r
   rA   r   r   r   rA   £  s    c             C   s   | j S )zTarget acceptance ratio.)Ú_target_rate)r
   r   r   r   Útarget_rate¬  s    zBaseAdaptiveSupport.target_ratec             C   s(   d|  k rdk sn t dƒ‚|| _dS )zKSets the target rate, making sure its more than 0 and less than 1.
        g        g      ð?z.Target acceptance rate must be in range (0, 1)N)r'   rB   )r
   rC   r   r   r   rC   ±  s    c             C   s   dS )z_Updates the proposal distribution and prepares the proposal for the
        next jump.
        Nr   )r
   r:   r   r   r   r9   ¹  s    zBaseAdaptiveSupport._update)r   r   r   r   r?   r@   rB   r   r-   r   rA   rC   r   r9   r   r   r   r   r>   ‹  s   	r>   )Úabcr   r   r6   Znumpy.randomr   r   r   r   r   r<   r>   r   r   r   r   Ú<module>   s   | 2E