Exemplo n.º 1
0
 def test_init_walkers_dict(self, pipe):
     sam_set = lhd(10, pipe._modellink._n_par, pipe._modellink._par_rng,
                   'center', pipe._criterion, 100)
     sam_dict = sdict(zip(pipe._modellink._par_name, sam_set.T))
     p0_walkers = get_walkers(pipe, init_walkers=sam_dict)[1]
     if pipe._is_controller:
         assert isinstance(p0_walkers, dict)
Exemplo n.º 2
0
 def test_3_2_constraints_outside(self):
     constraints = np.random.rand(2, 2)
     val_rng = [[1, 2], [2, 3]]
     assert np.allclose(lhd(3, 2, val_rng=val_rng,
                            constraints=constraints),
                        np.array([[1.54863137, 2.46114717],
                                  [1.14121827, 2.32122092],
                                  [1.81252907, 2.93057501]]))
Exemplo n.º 3
0
 def test_3_2_fixed(self):
     assert np.allclose(lhd(3, 2, method='fixed'),
                        np.array([[1, 1], [0.5, 0], [0, 0.5]]))
Exemplo n.º 4
0
 def test_3_2_random(self):
     assert np.allclose(lhd(3, 2, method='random'),
                        np.array([[0.18293783, 0.47919574],
                                  [0.86758779, 0.96392433],
                                  [0.57172979, 0.21529804]]))
Exemplo n.º 5
0
 def test_3_2_maximin_str(self):
     assert np.allclose(lhd(3, 2, method='random', criterion='maximin'),
                        np.array([[1, 1], [0.5, 0], [0, 0.5]]))
Exemplo n.º 6
0
 def test_3_2_no_constraints(self):
     assert np.allclose(lhd(3, 2, constraints=[]),
                        np.array([[0.18293783, 0.47919574],
                                  [0.86758779, 0.96392433],
                                  [0.57172979, 0.21529804]]))
Exemplo n.º 7
0
 def test_3_2_same_constraints(self):
     constraints = [0, 0]
     assert np.allclose(lhd(3, 2, constraints=constraints, criterion=0),
                        np.array([[0, 1], [1, 0], [0.5, 0.5]]))
Exemplo n.º 8
0
 def test_3_3_invalid_val_rng_shape(self):
     val_rng = [[0, 2], [0, 1]]
     with pytest.raises(ShapeError):
         lhd(3, 3, val_rng=val_rng)
Exemplo n.º 9
0
 def test_2_2_fixed(self):
     assert np.allclose(lhd(2, 2, method='fixed', criterion=0),
                        np.array([[1, 0], [0, 1]]))
Exemplo n.º 10
0
 def test_1_2_fixed(self):
     assert np.allclose(lhd(1, 2, method='fixed', criterion=0),
                        np.array([[0.5, 0.5]]))
Exemplo n.º 11
0
 def test_3_2_multi_float(self):
     assert np.allclose(lhd(3, 2, method='fixed', criterion=0.5),
                        np.array([[1, 1], [0.5, 0], [0, 0.5]]))
Exemplo n.º 12
0
 def test_3_2_multi_str(self):
     assert np.allclose(lhd(3, 2, method='center', criterion='multi'),
                        np.array([[0.83333333, 0.83333333],
                                  [0.5, 0.16666667], [0.16666667, 0.5]]))
Exemplo n.º 13
0
 def test_3_2_correlation_float(self):
     assert np.allclose(lhd(3, 2, method='center', criterion=1),
                        np.array([[0.83333333, 0.83333333],
                                  [0.5, 0.16666667], [0.16666667, 0.5]]))
Exemplo n.º 14
0
 def test_no_plausible_init_walkers(self, pipe):
     with pytest.raises(InputError):
         get_walkers(pipe,
                     init_walkers=lhd(1, pipe._modellink._n_par,
                                      pipe._modellink._par_rng, 'center',
                                      pipe._criterion, 100))
Exemplo n.º 15
0
 def test_3_2_center(self):
     assert np.allclose(lhd(3, 2, method='center'),
                        np.array([[0.83333333, 0.83333333],
                                  [0.5, 0.16666667], [0.16666667, 0.5]]))
Exemplo n.º 16
0
 def test_3_2_custom_rng(self):
     val_rng = [[0, 2], [1, 4]]
     assert np.allclose(lhd(3, 2, val_rng=val_rng),
                        np.array([[0.36587567, 2.43758721],
                                  [1.73517558, 3.89177300],
                                  [1.14345958, 1.64589411]]))
Exemplo n.º 17
0
 def test_3_1_fixed(self):
     assert np.allclose(lhd(3, 1, method='fixed', criterion=0),
                        np.array([[1], [0.5], [0]]))
Exemplo n.º 18
0
 def test_3_2_constraints(self):
     constraints = np.random.rand(2, 2)
     assert np.allclose(lhd(3, 2, constraints=constraints, criterion=0),
                        np.array([[1., 1], [0.5, 0], [0, 0.5]]))
Exemplo n.º 19
0
 def test_3_2_invalid_criterion_str(self):
     with pytest.raises(ValueError):
         lhd(3, 2, criterion='test')
Exemplo n.º 20
0
 def test_3_2_invalid_criterion_float(self):
     with pytest.raises(ValueError):
         lhd(3, 2, criterion=1.5)
Exemplo n.º 21
0
 def test_3_2_score(self):
     results = lhd(3, 2, criterion=0, get_score=True)
     assert np.allclose(results[0], np.array([[1, 1], [0.5, 0], [0, 0.5]]))
     assert np.allclose(results[1], np.array([0.80444958, 0.5, 0.80444958]))
Exemplo n.º 22
0
 def test_3_2_invalid_constraints(self):
     constraints = np.random.rand(2, 3)
     with pytest.raises(ShapeError):
         lhd(3, 2, constraints=constraints)
Exemplo n.º 23
0
 def test_4_2_no_quick_scan(self):
     assert np.allclose(lhd(4, 2, criterion=0, iterations=100,
                            quickscan=False),
                        np.array([[0.33333333, 0], [0, 0.66666667],
                                  [1, 0.33333333], [0.66666667, 1]]))
Exemplo n.º 24
0
def get_walkers(pipeline_obj,
                *,
                emul_i=None,
                init_walkers=None,
                req_n_walkers=None,
                unit_space=False,
                lnpost_fn=None,
                **kwargs):
    """
    Analyzes proposed `init_walkers` and returns plausible `p0_walkers`.

    Analyzes sample set `init_walkers` in the provided `pipeline_obj` at
    iteration `emul_i` and returns all samples that are plausible to be used as
    starting positions for MCMC walkers. The provided samples and returned
    walkers should be/are given in unit space if `unit_space` is *True*.

    If `init_walkers` is *None*, returns :attr:`~prism.Pipeline.impl_sam`
    instead if it is available.

    This function needs to be called by all MPI ranks.

    Parameters
    ----------
    pipeline_obj : :obj:`~prism.Pipeline` object
        The instance of the :class:`~prism.Pipeline` class that needs to be
        used for determining the plausibility of the proposed starting
        positions.

    Optional
    --------
    %(emul_i)s
    init_walkers : 2D array_like, dict, int or None. Default: None
        Sample set of proposed initial MCMC walker positions. All plausible
        samples in `init_walkers` will be returned.
        If int, generate an LHD of provided size and return all plausible
        samples.
        If *None*, return :attr:`~prism.Pipeline.impl_sam` corresponding to
        iteration `emul_i` instead.
    req_n_walkers : int or None. Default: None
        The minimum required number of plausible starting positions that should
        be returned. If *None*, all plausible starting positions in
        `init_walkers` are returned instead.

        .. versionadded:: 1.2.0
    unit_space : bool. Default: False
        Bool determining whether or not the provided samples and returned
        walkers are given in unit space.
    lnpost_fn : function or None. Default: None
        If function, call :func:`~get_hybrid_lnpost_fn` using `lnpost_fn` and
        the same values for `pipeline_obj`, `emul_i` and `unit_space`, and
        return the resulting function definition `hybrid_lnpost()`. Any
        additionally provided `kwargs` are also passed to it.

    Returns
    -------
    n_walkers : int
        Number of returned MCMC walkers. Note that this number can be higher
        than `req_n_walkers` if not *None*.
    p0_walkers : 2D :obj:`~numpy.ndarray` object or dict
        Array containing plausible starting positions of valid MCMC walkers.
        If `init_walkers` was provided as a dict, `p0_walkers` will be a dict.
    hybrid_lnpost : function (if `lnpost_fn` is a function)
        The function returned by :func:`~get_hybrid_lnpost_fn` using
        `lnpost_fn`, `pipeline_obj`, `emul_i`, `unit_space` and `kwargs` as the
        input values.

    See also
    --------
    :func:`~get_hybrid_lnpost_fn`
        Returns a function definition ``hybrid_lnpost(par_set, *args,
        **kwargs)``.

    :attr:`~prism.Pipeline.worker_mode`
        Special context manager within which all code is executed in worker
        mode.

    Notes
    -----
    If `init_walkers` is *None* and emulator iteration `emul_i` has not been
    analyzed yet, a :class:`~prism._internal.RequestError` will be raised.

    If `req_n_walkers` is not *None*, a custom Metropolis-Hastings sampling
    algorithm is used to generate the required number of starting positions.
    All plausible samples in `init_walkers` are used as the start of every MCMC
    chain. Note that if the number of plausible samples in `init_walkers` is
    small, it is possible that the returned `p0_walkers` are not spread out
    properly over parameter space.

    """

    # Make abbreviation for pipeline_obj
    pipe = pipeline_obj

    # Check if provided pipeline_obj is an instance of the Pipeline class
    if not isinstance(pipe, Pipeline):
        raise TypeError("Input argument 'pipeline_obj' must be an instance of "
                        "the Pipeline class!")

    # Check if the provided pipeline_obj uses a default emulator
    if (pipe._emulator._emul_type != 'default'):
        raise InputError("Input argument 'pipeline_obj' does not use a default"
                         " emulator!")

    # Get emulator iteration
    emul_i = pipe._emulator._get_emul_i(emul_i)

    # If req_n_walkers is not None, check if it is an integer
    if req_n_walkers is not None:
        req_n_walkers = check_vals(req_n_walkers, 'req_n_walkers', 'int',
                                   'pos')

    # Check if unit_space is a bool
    unit_space = check_vals(unit_space, 'unit_space', 'bool')

    # Assume that walkers are not to be returned as a dict
    walker_dict = False

    # Check if lnpost_fn is None and try to get hybrid_lnpost function if not
    if lnpost_fn is not None:
        try:
            hybrid_lnpost =\
                get_hybrid_lnpost_fn(lnpost_fn, pipe, emul_i=emul_i,
                                     unit_space=unit_space, **kwargs)
        except InputError:
            raise InputError("Input argument 'lnpost_fn' is invalid!")

    # If init_walkers is None, use impl_sam of emul_i
    if init_walkers is None:
        # Controller checking if emul_i has already been analyzed
        if pipe._is_controller:
            # If iteration has not been analyzed, raise error
            if not pipe._n_eval_sam[emul_i]:
                raise RequestError("Emulator iteration %i has not been "
                                   "analyzed yet!" % (emul_i))
            # If iteration is last iteration, init_walkers is current impl_sam
            elif (emul_i == pipe._emulator._emul_i):
                init_walkers = pipe._impl_sam
            # If iteration is not last, init_walkers is previous impl_sam
            else:
                init_walkers = pipe._emulator._sam_set[emul_i + 1]

            # Make sure to make a copy of init_walkers to avoid modifications
            init_walkers = init_walkers.copy()

        # Broadcast init_walkers to workers as p0_walkers
        p0_walkers = pipe._comm.bcast(init_walkers, 0)

    # If init_walkers is not None, use provided samples or LHD size
    else:
        # Controller checking if init_walkers is valid
        if pipe._is_controller:
            # If init_walkers is an int, create LHD of provided size
            if isinstance(init_walkers, int):
                # Check if provided integer is positive
                n_sam = check_vals(init_walkers, 'init_walkers', 'pos')

                # Create LHD of provided size
                init_walkers = lhd(n_sam, pipe._modellink._n_par,
                                   pipe._modellink._par_rng, 'center',
                                   pipe._criterion, 100)

            # If init_walkers is not an int, it must be array_like or dict
            else:
                # If init_walkers is provided as a dict, convert it
                if isinstance(init_walkers, dict):
                    # Make sure that init_walkers is a SortedDict
                    init_walkers = sdict(init_walkers)

                    # Convert it to normal
                    init_walkers = np_array(init_walkers.values()).T

                    # Return p0_walkers as a dict
                    walker_dict = True

                # Make sure that init_walkers is a NumPy array
                init_walkers = np_array(init_walkers, ndmin=2)

                # If unit_space is True, convert init_walkers to par_space
                if unit_space:
                    init_walkers = pipe._modellink._to_par_space(init_walkers)

                # Check if init_walkers is valid
                init_walkers = pipe._modellink._check_sam_set(
                    init_walkers, 'init_walkers')

        # Broadcast init_walkers to workers
        init_walkers = pipe._comm.bcast(init_walkers, 0)

        # Analyze init_walkers and save them as p0_walkers
        p0_walkers = pipe._evaluate_sam_set(emul_i, init_walkers, 'analyze')

    # Check if init_walkers is not empty and raise error if it is
    if not p0_walkers.shape[0]:
        raise InputError("Input argument 'init_walkers' contains no plausible "
                         "samples!")

    # If req_n_walkers is not None, use MH MCMC to find all required walkers
    if req_n_walkers is not None:
        n_walkers, p0_walkers = _do_mh_walkers(pipe, p0_walkers, req_n_walkers)
    else:
        p0_walkers = np.unique(p0_walkers, axis=0)
        n_walkers = p0_walkers.shape[0]

    # Check if p0_walkers needs to be converted
    if unit_space:
        p0_walkers = pipe._modellink._to_unit_space(p0_walkers)

    # Check if p0_walkers needs to be returned as a dict
    if walker_dict:
        p0_walkers = sdict(zip(pipe._modellink._par_name, p0_walkers.T))

    # Check if hybrid_lnpost was requested and return it as well if so
    if lnpost_fn is not None:
        return (n_walkers, p0_walkers, hybrid_lnpost)
    else:
        return (n_walkers, p0_walkers)
Exemplo n.º 25
0
 def test_init_walkers_set(self, pipe):
     get_walkers(pipe,
                 init_walkers=lhd(10, pipe._modellink._n_par, None,
                                  'center', pipe._criterion, 100),
                 unit_space=True)