B
    dz                 @   s   d Z ddlZddlZddlZddlZddlmZmZ ddl	m
Z
mZmZmZ ddlmZmZmZmZ ddd	gZd
d Zdd Zdd Zdd Zdd Zdd ZG dd deZedej_ edej_ G dd de
Zedej_ G dd	 d	ZdS )z
The top-level interface (defined natively upon initialization) that
provides access to the two main sampler "super-classes" via
:meth:`NestedSampler` and :meth:`DynamicNestedSampler`.

    N   )	_SAMPLINGSuperSampler)DynamicSampler_get_update_interval_ratio	_SAMPLERS_initialize_live_points)LogLikelihoodget_random_generatorget_enlarge_bootstrapget_nonboundedNestedSamplerDynamicNestedSampler_function_wrapperc             C   s   ddg}ddg}dg}dddd	d
gd	d
gd}ddgdddgdddgddddgd}dd }||}	||}
|| |d}|| |d}| dkst| dkr||}d| }nd}d|	 d|
 d| d| d| d}|S )aO  
    Return a string of citations for given dynesty run

    Parameters
    ----------
    nested_type: string
        Either dynamic or static
    bound: string
        Bound type used
    sampler: string
        Internal sampler type

    Returns
    -------
    citations: string
         The long printable string of citations
    )zSpeagle (2020)z-ui.adsabs.harvard.edu/abs/2020MNRAS.493.3132S)zKoposov et al. (2023)zdoi.org/10.5281/zenodo.3348367)zSkilling (2004)z-ui.adsabs.harvard.edu/abs/2004AIPC..735..395S)zSkilling (2006)z&projecteuclid.org/euclid.ba/1340370944)zHigson et al. (2019)z!doi.org/10.1007/s11222-018-9844-0 )z$Mukherjee, Parkinson & Liddle (2006)z-ui.adsabs.harvard.edu/abs/2006ApJ...638L..51M)zFeroz, Hobson & Bridges (2009)z-ui.adsabs.harvard.edu/abs/2009MNRAS.398.1601F)zBuchner (2016)z-ui.adsabs.harvard.edu/abs/2014arXiv1407.5459B)zBuchner (2017)z-ui.adsabs.harvard.edu/abs/2017arXiv170704476B)noneZsinglemultiZballsZcubes)zNeal (2003)z'projecteuclid.org/euclid.aos/1056562461)z!Handley, Hobson & Lasenby (2015a)z-ui.adsabs.harvard.edu/abs/2015MNRAS.450L..61H)z!Handley, Hobson & Lasenby (2015b)z-ui.adsabs.harvard.edu/abs/2015MNRAS.453.4384H)zNeal (2003):z'projecteuclid.org/euclid.aos/1056562461)zSkilling (2012)z+aip.scitation.org/doi/abs/10.1063/1.3703630)zFeroz & Skilling (2013)z-ui.adsabs.harvard.edu/abs/2013AIPC.1553..106F)unifrwalkslicerslicehslicec             S   sV   t | tr| S t | tr,| d d | d  S t | trJddd | D S t| S dS )zT internal function to convert reference lists to
        a printable string
        r   z: r   
c             S   s    g | ]}|d  d |d  qS )r   z: r    ).0_r   r   \/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/dynesty/dynesty.py
<listcomp>p   s    z<_get_citations.<locals>.reflist_tostring.<locals>.<listcomp>N)
isinstancestrtuplelistjoin)xr   r   r   reflist_tostringg   s    


z(_get_citations.<locals>.reflist_tostring)dynamicstaticr%   z1Dynamic Nested Sampling:
=======================
z$Code and Methods:
 ================
z#

Nested Sampling:
===============
r   z#

Bounding Method:
===============
z#

Sampling Method:
===============
)getAssertionError)Znested_typeboundsamplerZdefault_refsZnested_refsZdynamic_refsZ
bound_refsZsampler_refsr$   Zdefault_citationsZnested_citationsZbound_citationsZsampler_citationsZdynamic_citationsZ	citationsr   r   r   _get_citations   sJ    

$r+   c             C   sB   | dk rd}n0d|   kr"dkr,n nd}n|dkr:d}nd}|S )z Decode which sampling method to use

    Arguments:
    ndim: int (dimensionality)
    gradient: (None or function/true)
    Returns: sampler string
    
   r      r   Nr   r   r   )ndimgradientsampler   r   r   _get_auto_sample   s    r1   c             C   sP   d\}}|dkrd| }n|dkr(d}n|dkr8d| }|p>|}| pF|}||fS )av  
    Get the best number of steps for random walk/slicing based on
    the type of sampler and dimension

    Arguments:
    walks0: integer (provided by user or none for auto)
    slices0: integer (provided by user or none for auto)
    sample: string (sampler type)
    ndim: int (dimensionality)
    Returns the tuple with number of walk steps, number of slice steps
    )NN)r   r      r   r   r-   r   )Zwalks0Zslices0r0   r.   walksslicesr   r   r   _get_walks_slices   s    
r5   c          
   C   s   |dk	r|dk rt dnz|dks2| dkr<|dkr<t}d}nX| dk	r| j}|dkry
| j}W q tk
r } zt d|W dd}~X Y qX nt d||fS )zz
    Common functionality of interpretign the pool and queue_size
    arguments to Dynamic and static nested samplers
    Nr   z,The queue must contain at least one element!zCannot initialize `queue_size` because `pool.size` has not been provided. Pleasedefine `pool.size` or specify `queue_size` explicitly.z(`queue_size > 1` but no `pool` provided.)
ValueErrormapsizeAttributeError)pool
queue_sizeMer   r   r   _parse_pool_queue   s    

r>   c             C   s&   x |   D ]}|dkr
tdq
W dS )zv
    Verify that the first_update dictionary is valid
    Specifically that it doesn't have unrecognized keywords
    )Z	min_ncallZmin_effz%Unrecognized keywords in first_updateN)keysr6   )first_updatekr   r   r   _check_first_update   s    rB   c             C   s,   d}d| d}d| d}| r$|S |S dS )z
    Assemble the docstring for the NestedSampler and DynamicNestedSampler
    We do that to avoid duplicating the parameter descriptions
    a/  
        Parameters
        ----------
        loglikelihood : function
            Function returning ln(likelihood) given parameters as a 1-d
            `~numpy` array of length `ndim`.

        prior_transform : function
            Function translating a unit cube to the parameter space according
            to the prior. The input is a 1-d `~numpy` array with length
            `ndim`, where each value is in the range [0, 1). The return
            value should also be a 1-d `~numpy` array with length `ndim`,
            where each value is a parameter.
            The return value is passed to the loglikelihood function. For
            example, for a 2 parameter model with flat priors in the range
            [0, 2), the function would be::

                def prior_transform(u):
                    return 2.0 * u

        ndim : int
            Number of parameters returned by `prior_transform` and accepted by
            `loglikelihood`.

        nlive : int, optional
            Number of "live" points. Larger numbers result in a more finely
            sampled posterior (more accurate evidence), but also a larger
            number of iterations required to converge. Default is `500`.

        bound : {`'none'`, `'single'`, `'multi'`, `'balls'`, `'cubes'`}, optional
            Method used to approximately bound the prior using the current
            set of live points. Conditions the sampling methods used to
            propose new live points. Choices are no bound (`'none'`), a single
            bounding ellipsoid (`'single'`), multiple bounding ellipsoids
            (`'multi'`), balls centered on each live point (`'balls'`), and
            cubes centered on each live point (`'cubes'`). Default is
            `'multi'`.

        sample : {`'auto'`, `'unif'`, `'rwalk'`, `'slice'`, `'rslice'`,
            `'hslice'`, callable}, optional
            Method used to sample uniformly within the likelihood constraint,
            conditioned on the provided bounds. Unique methods available are:
            uniform sampling within the bounds(`'unif'`),
            random walks with fixed proposals (`'rwalk'`),
            multivariate slice sampling along preferred orientations
            (`'slice'`),
            "random" slice sampling along all orientations (`'rslice'`),
            "Hamiltonian" slices along random trajectories (`'hslice'`), and
            any callable function which follows the pattern of the sample
            methods
            defined in dynesty.sampling.
            `'auto'` selects the sampling method based on the dimensionality
            of the problem (from `ndim`).
            When `ndim < 10`, this defaults to `'unif'`.
            When `10 <= ndim <= 20`, this defaults to `'rwalk'`.
            When `ndim > 20`, this defaults to `'hslice'` if a `gradient` is
            provided and `'rslice'` otherwise. `'slice'`
            is provided as alternatives for`'rslice'`.
            Default is `'auto'`.

        periodic : iterable, optional
            A list of indices for parameters with periodic boundary conditions.
            These parameters *will not* have their positions constrained to be
            within the unit cube, enabling smooth behavior for parameters
            that may wrap around the edge. Default is `None` (i.e. no periodic
            boundary conditions).

        reflective : iterable, optional
            A list of indices for parameters with reflective boundary
            conditions.
            These parameters *will not* have their positions constrained to be
            within the unit cube, enabling smooth behavior for parameters
            that may reflect at the edge. Default is `None` (i.e. no reflective
            boundary conditions).

        update_interval : int or float, optional
            If an integer is passed, only update the proposal distribution
            every `update_interval`-th likelihood call. If a float is passed,
            update the proposal after every
            `round(update_interval * nlive)`-th likelihood
            call. Larger update intervals larger can be more efficient
            when the likelihood function is quick to evaluate. Default behavior
            is to target a roughly constant change in prior volume, with
            `1.5` for `'unif'`, `0.15 * walks` for `'rwalk'`.
            `0.9 * ndim * slices` for `'slice'`, `2.0 * slices` for `'rslice'`,
            and `25.0 * slices` for `'hslice'`.

        first_update : dict, optional
            A dictionary containing parameters governing when the sampler
            should
            first update the bounding distribution from the unit cube
            (`'none'`)
            to the one specified by `sample`. Options are the minimum number of
            likelihood calls (`'min_ncall'`) and the minimum allowed overall
            efficiency in percent (`'min_eff'`). Defaults are `2 * nlive` and
            `10.`, respectively.

        npdim : int, optional
            Number of parameters accepted by `prior_transform`. This might
            differ from `ndim` in the case where a parameter of loglikelihood
            is dependent upon multiple independently distributed parameters,
            some of which may
            be nuisance parameters.

        rstate : `~numpy.random.Generator`, optional
            `~numpy.random.Generator` instance. If not given, the
             global random state of the `~numpy.random` module will be used.

        queue_size : int, optional
            Carry out likelihood evaluations in parallel by queueing up new
            live point proposals using (at most) `queue_size` many threads.
            Each thread independently proposes new live points until the
            proposal distribution
            is updated. If no value is passed, this defaults to `pool.size` (if
            a `pool` has been provided) and `1` otherwise (no parallelism).

        pool : user-provided pool, optional
            Use this pool of workers to execute operations in parallel.

        use_pool : dict, optional
            A dictionary containing flags indicating where a pool should be
            used to execute operations in parallel. These govern whether
            `prior_transform`
            is executed in parallel during initialization
            (`'prior_transform'`),
            `loglikelihood` is executed in parallel during initialization
            (`'loglikelihood'`), live points are proposed in parallel during
            a run
            (`'propose_point'`), and bounding distributions are updated in
            parallel during a run (`'update_bound'`). Default is `True` for all
            options.

        live_points : list of 3 `~numpy.ndarray` each with shape (nlive, ndim)
            A set of live points used to initialize the nested sampling run.
            Contains `live_u`, the coordinates on the unit cube, `live_v`, the
            transformed variables, and `live_logl`, the associated
            loglikelihoods.
            By default, if these are not provided the initial set of live
            points will be drawn uniformly from the unit `npdim`-cube.
            **WARNING: It is crucial that the initial set of live points have
            been sampled from the prior. Failure to provide a set of valid
            live points
            will result in incorrect results.**

        logl_args : iterable, optional
            Additional arguments that can be passed to `loglikelihood`.

        logl_kwargs : dict, optional
            Additional keyword arguments that can be passed to `loglikelihood`.

        ptform_args : iterable, optional
            Additional arguments that can be passed to `prior_transform`.

        ptform_kwargs : dict, optional
            Additional keyword arguments that can be passed to
            `prior_transform`.

        gradient : function, optional
            A function which returns the gradient corresponding to
            the provided `loglikelihood` *with respect to the unit cube*.
            If provided, this will be used when computing reflections
            when sampling with `'hslice'`. If not provided, gradients are
            approximated numerically using 2-sided differencing.

        grad_args : iterable, optional
            Additional arguments that can be passed to `gradient`.

        grad_kwargs : dict, optional
            Additional keyword arguments that can be passed to `gradient`.

        compute_jac : bool, optional
            Whether to compute and apply the Jacobian `dv/du`
            from the target space `v` to the unit cube `u` when evaluating the
            `gradient`. If `False`, the gradient provided is assumed to be
            already defined with respect to the unit cube. If `True`, the
            gradient
            provided is assumed to be defined with respect to the target space
            so the Jacobian needs to be numerically computed and applied.
            Default is `False`.

        enlarge : float, optional
            Enlarge the volumes of the specified bounding object(s) by this
            fraction. The preferred method is to determine this organically
            using bootstrapping. If `bootstrap > 0`, this defaults to `1.0`.
            If `bootstrap = 0`, this instead defaults to `1.25`.

        bootstrap : int, optional
            Compute this many bootstrapped realizations of the bounding
            objects. Use the maximum distance found to the set of points left
            out during each iteration to enlarge the resulting volumes. Can
            lead to unstable bounding ellipsoids. Default is `None` (no
            bootstrap
            unless the sampler is uniform). If bootstrap is set to zero,
            bootstrap is disabled.

        walks : int, optional
            For the `'rwalk'` sampling option, the minimum number of steps
            (minimum 2) before proposing a new live point. Default is `25`.

        facc : float, optional
            The target acceptance fraction for the `'rwalk'` sampling option.
            Default is `0.5`. Bounded to be between `[1. / walks, 1.]`.

        slices : int, optional
            For the `'slice'`, `'rslice'`, and `'hslice'` sampling
            options, the number of times to execute a "slice update"
            before proposing a new live point. Default is 3 for
            `'slice'` and 3+ndim for rslice and hslice.
            Note that `'slice'` cycles through **all dimensions**
            when executing a "slice update".

        fmove : float, optional
            The target fraction of samples that are proposed along a trajectory
            (i.e. not reflecting) for the `'hslice'` sampling option.
            Default is `0.9`.

        max_move : int, optional
            The maximum number of timesteps allowed for `'hslice'`
            per proposal forwards and backwards in time. Default is `100`.

        update_func : function, optional
            Any callable function which takes in a `blob` and `scale`
            as input and returns a modification to the internal `scale` as
            output.
            Must follow the pattern of the update methods defined
            in dynesty.nestedsamplers. If provided, this will supersede the
            default functions used to update proposals. In the case where a
            custom
            callable function is passed to `sample` but no similar function is
            passed to `update_func`, this will default to no update.

        ncdim: int, optional
            The number of clustering dimensions. The first ncdim dimensions
            will be sampled using the sampling method, the remaining
            dimensions will
            just sample uniformly from the prior distribution.
            If this is `None` (default), this will default to npdim.

        blob: bool, optional
            The default value is False. If it is true, then the log-likelihood
            should return the tuple of logl and a numpy-array "blob" that will
            stored as part of the chain. That blob can contain auxiliary
            information computed inside the likelihood function.
    zN
        Initializes and returns a sampler object for Static Nested Sampling.
z
        Returns
        -------
        sampler : sampler from :mod:`~dynesty.nestedsamplers`
            An initialized instance of the chosen sampler specified via
            `bound`.
        zD
        Initializes a sampler object for Dynamic Nested Sampling.

z
        Returns
        -------
        sampler : a :class:`dynesty.DynamicSampler` instance
            An initialized instance of the dynamic nested sampler.

        Nr   )r%   commonZstatic_docstringZdynamic_docstringr   r   r   _assemble_sampler_docstring   s     z
rD   c            !       s"   e Zd ZdZd fd
d	Z  ZS )r   z
    The main class performing the static nested sampling.
    It inherits all the methods of the dynesty.sampler.SuperSampler.
      r   autoNF      ??d   c%       0         s$  |d kr|}|!d kr|}!|t kr.td||dkr@t||}t||||\}}|!|krj|dkrjtd|tkrt|std|i }%| d k	rt| std| | |%d< td|||%d	< |d
| krt	d t
|||}&|&|%d< ||%d< ||%d< |
d kri }
nt|
 |d kr$t }|d kr2g }|d kr@i }|d krNg }|d kr\i }|d krjg }|d krxi }t|||\}}||%d< ||%d< |d k	r||%d< |d k	r||%d< |d k	r||%d< |d k	r||%d< |d k	r||%d< t|	||||||}'tttt|'| tjd}	t||\}(}|d krBi }t|||dd})|ddrf|}*nd }*tt|||dd||#|"|$pd|*d}+|d k	rt|||dd},|,|%d< ||%d< t||)|+|(||||"|ddd 	\}}-}.t t | }/|/j|+|)||||	|
|||||%|!|"|-d! |.|/_|/S )"NzUnknown bounding method: '{0}'rF   )r   r   r   z$ncdim unsupported for slice samplingzUnknown sampling method: '{0}'zUnknown update function: '{0}'update_funcr&   cite   z6Beware! Having `nlive <= 2 * ndim` is extremely risky!
nonboundedperiodic
reflectiveenlarge	bootstrapr3   faccr4   fmovemax_mover   prior_transform)nameloglikelihoodTzdynesty_logl_history.h5)saveblobhistory_filenamer:   r/   gradcompute_jac)nlivenpdimrstaterY   Zuse_pool_ptform)ncdimrY   logvol_init)r   r6   formatr1   r5   r   callabler+   warningswarnr   rB   r
   r   r   intmaxminnproundsysmaxsizer>   r   r'   r	   r   super__new____init__Zncalls)0clsrW   rU   r.   r]   r)   r0   rN   rO   update_intervalr@   r^   r_   r;   r:   use_poolZlive_points	logl_argslogl_kwargsptform_argsptform_kwargsr/   	grad_argsgrad_kwargsr\   rP   rQ   r3   rR   r4   rS   rT   rJ   r`   rY   save_historyrZ   kwargsrM   update_interval_ratior<   ptform	pool_logllogliker[   ra   Zinit_ncallsr*   )	__class__r   r   rn      s    '















zNestedSampler.__new__)!rE   r   rF   NNNNNNNNNNNNNNNNNFNNNrG   NrH   rI   NNFFN)__name__
__module____qualname____doc__rn   __classcell__r   r   )r   r   r     sD                                   Fc                    s"   e Zd ZdZd fd	d
	Z  ZS )r   z
    The main class for performing dynamic nested sampling.
    It inherits all the methods from dynesty.dynamicsampler.DynamicSampler
    Nr   rF   F      ??rI   c$       +         s  |d kr|}| d kr|} |pd}|t kr6td| |dkrHt||}t||||\}}| |krr|dkrrtdt|	||||||}$i }%|tkrt|std| |d k	rt|std| d||%d	< td
|||%d< t|||}&|&|%d< ||%d< ||%d< |!|%d< |
d kri }
nt	|
 |d kr4t
 }|d krBg }|d krPi }|d kr^g }|d krli }|d krzg }|d kri }t|||\}}||%d< ||%d< |d k	r||%d< |d k	r||%d< |d k	r||%d< |d k	r||%d< |d k	r||%d< t||d }|d kri }t|||dd}'|ddrB|}(nd }(tt|||dd||(|#pbd|"|!d})|d k	rt|||dd}*|*|%d< ||%d < t |)|'||||$|
||||| ||% d S )!Ni  zUnknown bounding method: rF   )r   r   r   z$ncdim unsupported for slice samplingzUnknown sampling method: zUnknown update function: ''rJ   r%   rK   rM   rN   rO   rY   rP   rQ   r3   rR   r4   rS   rT   r   rU   )rV   rW   Tzdynesty_logl_history.h5)r:   rZ   rX   rY   r/   r[   r\   )r   r6   r1   r5   r   r   rc   r+   r   rB   r
   r   r>   r   r'   r	   rm   ro   )+selfrW   rU   r.   r]   r)   r0   rN   rO   rq   r@   r^   r_   r;   r:   rr   rs   rt   ru   rv   r/   rw   rx   r\   rP   rQ   r3   rR   r4   rS   rT   rJ   r`   rY   ry   rZ   r{   rz   rM   r|   r}   r~   r[   )r   r   r   ro     s    &















zDynamicNestedSampler.__init__) Nr   rF   NNNNNNNNNNNNNNNNFNNNr   Nr   rI   NNFFN)r   r   r   r   ro   r   r   r   )r   r   r     sB                                  Tc               @   s"   e Zd ZdZdddZdd ZdS )	r   z
    A hack to make functions pickleable when `args` or `kwargs` are
    also included. Based on the implementation in
    `emcee <http://dan.iel.fm/emcee/>`_.

    inputc             C   s   || _ || _|| _|| _d S )N)funcargsrz   rV   )r   r   r   rz   rV   r   r   r   ro     s    z_function_wrapper.__init__c             C   sx   y | j t| f| j| jS    td| j d td| td| j td| j td t	   Y nX d S )NzException while calling z
 function:z	  params:z  args:z	  kwargs:z  exception:)
r   ri   Zasarraycopyr   rz   printrV   	traceback	print_exc)r   r#   r   r   r   __call__  s     
z_function_wrapper.__call__N)r   )r   r   r   r   ro   r   r   r   r   r   r   x  s   
)r   rk   rd   r   numpyri   Znestedsamplersr   r   Zdynamicsamplerr   r   r   r   utilsr	   r
   r   r   __all__r+   r1   r5   r>   rB   rD   r   rn   ro   r   r   r   r   r   r   <module>   s0   
z
   L -