def __init__(self):
     self._t = pints.vector([1, 2, 3])
     self._v = pints.vector([-1, 2, 3])
Exemple #2
0
    def tell(self, reply):
        """ See :meth:`pints.SingleChainMCMC.tell()`. """

        # Check if we had a proposal
        if not self._ready_for_tell:
            raise RuntimeError('Tell called before proposal was set.')
        self._ready_for_tell = False

        # Unpack reply
        fx, log_gradient = reply

        # Check reply, copy gradient
        fx = float(fx)
        log_gradient = pints.vector(log_gradient)
        assert(log_gradient.shape == (self._n_parameters, ))

        # First point?
        if self._current is None:
            if not np.isfinite(fx):
                raise ValueError(
                    'Initial point for MCMC must have finite log_pdf.')

            # Accept
            self._current = self._proposed
            self._current_log_pdf = fx
            self._current_gradient = log_gradient

            # Increase iteration count
            self._iterations += 1

            # Clear proposal
            self._proposed = None

            # Return first point for chain
            return self._current

        # Calculate alpha
        proposed_gradient = log_gradient
        self._backward_mu = self._proposed + (
            0.5 * self._epsilon**2 * proposed_gradient)
        self._backward_q = scipy.stats.multivariate_normal.logpdf(
            self._current, self._backward_mu,
            self._epsilon**2 * (np.diag(np.ones(self._n_parameters))))
        alpha = fx + self._backward_q - (
            self._current_log_pdf + self._forward_q)

        # Check if the proposed point can be accepted
        accepted = 0
        if np.isfinite(fx):
            u = np.log(np.random.uniform(0, 1))
            if alpha > u:
                accepted = 1
                self._current = self._proposed
                self._current_log_pdf = fx
                self._current_gradient = log_gradient

        # Clear proposal
        self._proposed = None

        # Update acceptance rate (only used for output!)
        self._acceptance = ((self._iterations * self._acceptance + accepted) /
                            (self._iterations + 1))

        # Increase iteration count
        self._iterations += 1

        # Return new point for chain
        return self._current
Exemple #3
0
    def tell(self, reply):
        """ See :meth:`pints.SingleChainMCMC.tell()`. """
        if not self._ready_for_tell:
            raise RuntimeError('Tell called before proposal was set.')
        self._ready_for_tell = False

        # Unpack reply
        energy, gradient = reply

        # Check reply, copy gradient
        energy = float(energy)
        gradient = pints.vector(gradient)
        assert gradient.shape == (self._n_parameters, )

        # Energy = -log_pdf, so flip both signs!
        energy = -energy
        gradient = -gradient

        # Very first call
        if self._current is None:

            # Check first point is somewhere sensible
            if not np.isfinite(energy):
                raise ValueError(
                    'Initial point for MCMC must have finite logpdf.')

            # Set current sample, energy, and gradient
            self._current = self._x0
            self._current_energy = energy
            self._current_gradient = gradient

            # Increase iteration count
            self._mcmc_iteration += 1

            # Mark current as read-only, so it can be safely returned.
            # Gradient won't be returned (only -gradient, so no need.
            self._current.setflags(write=False)

            # Return first point in chain
            return (self._current, (-self._current_energy,
                                    -self._current_gradient), False)

        # Set gradient of current leapfrog position
        self._gradient = gradient

        # Update the leapfrog iteration count
        self._frog_iteration += 1

        # Not the last iteration? Then perform a leapfrog step and return
        if self._frog_iteration < self._n_frog_iterations:
            self._momentum -= self._scaled_epsilon * self._gradient

            # Return None to indicate there is no new sample for the chain
            return None

        # Final leapfrog iteration: only do half a step
        self._momentum -= self._scaled_epsilon * self._gradient * 0.5

        # Before starting accept/reject procedure, check if the leapfrog
        # procedure has led to a finite momentum and logpdf. If not, reject.
        accept = 0
        if np.isfinite(energy) and np.all(np.isfinite(self._momentum)):

            # Evaluate potential and kinetic energies at start and end of
            # leapfrog trajectory
            current_U = self._current_energy
            current_K = np.sum(self._current_momentum**2 / 2)
            proposed_U = energy
            proposed_K = np.sum(self._momentum**2 / 2)

            # Check for divergent iterations by testing whether the
            # Hamiltonian difference is above a threshold
            div = proposed_U + proposed_K - (self._current_energy + current_K)
            if np.abs(div) > self._hamiltonian_threshold:  # pragma: no cover
                self._divergent = np.append(self._divergent,
                                            self._mcmc_iteration)
                self._momentum = self._position = self._gradient = None
                self._frog_iteration = 0

                # Update MCMC iteration count
                self._mcmc_iteration += 1

                # Update acceptance rate (only used for output!)
                self._mcmc_acceptance = (
                    (self._mcmc_iteration * self._mcmc_acceptance + accept) /
                    (self._mcmc_iteration + 1))

                # Return current state
                return (self._current, (-self._current_energy,
                                        -self._current_gradient), False)

            # Accept/reject
            else:
                r = np.exp(current_U - proposed_U + current_K - proposed_K)
                if np.random.uniform(0, 1) < r:
                    accept = 1
                    self._current = self._position
                    self._current_energy = energy
                    self._current_gradient = gradient

                    # Mark current as read-only, so it can be safely returned.
                    # Gradient won't be returned (only -gradient, so no need.
                    self._current.setflags(write=False)

        # Reset leapfrog mechanism
        self._momentum = self._position = self._gradient = None
        self._frog_iteration = 0

        # Update MCMC iteration count
        self._mcmc_iteration += 1

        # Update acceptance rate (only used for output!)
        self._mcmc_acceptance = (
            (self._mcmc_iteration * self._mcmc_acceptance + accept) /
            (self._mcmc_iteration + 1))

        # Return current position as next sample in the chain
        return (self._current, (-self._current_energy,
                                -self._current_gradient), accept > 0)
Exemple #4
0
def surface(points, values, boundaries=None, markers='+', figsize=None):
    """
    Takes irregularly spaced points and function evaluations in a
    two-dimensional parameter space and creates a coloured surface plot using a
    voronoi diagram.

    Returns a ``matplotlib`` figure object and axes handle.

    Parameters
    ----------
    points
        A list of (two-dimensional) points in parameter space.
    values
        The values (e.g. error measure evaluations) corresponding to these
        points.
    boundaries
        An optional :class:`pints.RectangularBoundaries` object to restrict the
        area shown. If set to ``None`` boundaries will be determined from the
        given ``points``.
    markers
        An optional string indicating the matplotlib markers to use to plot
        the ``points``. Set to ``None`` to hide.
    figsize
        An optional tuple ``(width, height)`` that will be passed to
        matplotlib when creating the figure. If set to ``None`` matplotlib will
        use its default figure size.

    """
    import matplotlib.pyplot as plt
    from matplotlib.collections import PolyCollection

    # Check points and values
    points = pints.matrix2d(points)
    n, d = points.shape
    if d != 2:
        raise ValueError('Only two-dimensional parameters are supported.')
    values = pints.vector(values)
    if len(values) != n:
        raise ValueError(
            'The number of values must match the number of points.')

    # Extract x and y points
    x = points[:, 0]
    y = points[:, 1]
    del (points)

    # Check boundaries
    if boundaries is None:
        xmin, xmax = np.min(x), np.max(x)
        r = 0.1 * (xmax - xmin)
        xmin -= r
        xmax += r
        ymin, ymax = np.min(y), np.max(y)
        r = 0.1 * (ymax - ymin)
        ymin -= r
        ymax += r
    else:
        if boundaries.n_parameters() != 2:
            raise ValueError('The boundaries must be two-dimensional.')

        xmin, ymin = boundaries.lower()
        xmax, ymax = boundaries.upper()

    # Get voronoi regions (and filter points and evaluations)
    xlim = xmin, xmax
    ylim = ymin, ymax
    x, y, values, regions = _voronoi_regions(x, y, values, xlim, ylim)

    # Create figure and axes
    figure, axes = plt.subplots(figsize=figsize)
    axes.set_xlim(xmin, xmax)
    axes.set_ylim(ymin, ymax)

    # Add coloured voronoi regions
    c = PolyCollection(regions,
                       array=values,
                       edgecolors='none',
                       cmap='viridis_r')
    axes.add_collection(c)

    # Add markers
    if markers:
        axes.plot(x, y, markers, color='#ffffff', alpha=0.75)

    # Add colorbar
    figure.colorbar(c, ax=axes)

    return figure, axes
Exemple #5
0
    def test_vector(self):
        # Test correct use with 1d arrays
        x = np.array([1, 2, 3])
        v = pints.vector(x)
        x = np.array([1])
        v = pints.vector(x)
        x = np.array([])
        v = pints.vector(x)

        # Test correct use with higher dimensional arrays
        x = np.array([1, 2, 3])
        w = pints.vector(x)
        x = x.reshape((3, 1, 1, 1, 1))
        v = pints.vector(x)
        self.assertTrue(np.all(w == v))
        x = x.reshape((1, 3, 1, 1, 1))
        v = pints.vector(x)
        self.assertTrue(np.all(w == v))
        x = x.reshape((1, 1, 1, 1, 3))
        v = pints.vector(x)
        self.assertTrue(np.all(w == v))

        # Test correct use with lists
        x = [1, 2, 3]
        v = pints.vector(x)
        self.assertTrue(np.all(w == v))
        x = [4]
        v = pints.vector(x)
        x = []
        v = pints.vector(x)

        # Test incorrect use with higher dimensional arrays
        x = np.array([4, 5, 6, 3, 2, 4])
        x = x.reshape((2, 3))
        self.assertRaises(ValueError, pints.vector, x)
        x = x.reshape((3, 2))
        self.assertRaises(ValueError, pints.vector, x)
        x = x.reshape((6, 1))
        v = pints.vector(x)

        # Test correct use with scalar
        x = 5
        v = pints.vector(x)
        self.assertEqual(len(v), 1)
        self.assertEqual(v[0], 5)

        # Test read-only
        def assign():
            v[0] = 10

        self.assertRaises(ValueError, assign)
Exemple #6
0
def function_between_points(f, point_1, point_2, padding=0.25, evaluations=20):
    """
    Creates and returns a plot of a function between two points in parameter
    space.

    Returns a ``matplotlib`` figure object and axes handle.

    Parameters
    ----------
    f
        A :class:`pints.LogPDF` or :class:`pints.ErrorMeasure` to plot.
    point_1
        The first point in parameter space. The method will find a line from
        ``point_1`` to ``point_2`` and plot ``f`` at several points along it.
    point_2
        The second point.
    padding
        Specifies the amount of padding around the line segment
        ``[point_1, point_2]`` that will be shown in the plot.
    evaluations
        The number of evaluation along the line in parameter space.
    """
    import matplotlib.pyplot as plt
    import numpy as np
    import pints

    # Check function and get n_parameters
    if not (isinstance(f, pints.LogPDF) or isinstance(f, pints.ErrorMeasure)):
        raise ValueError(
            'Given function must be pints.LogPDF or pints.ErrorMeasure.')
    n_param = f.n_parameters()

    # Check points
    point_1 = pints.vector(point_1)
    point_2 = pints.vector(point_2)
    if not (len(point_1) == len(point_2) == n_param):
        raise ValueError('Both points must have the same number of parameters'
                         + ' as the given function.')

    # Check padding
    padding = float(padding)
    if padding < 0:
        raise ValueError('Padding cannot be negative.')

    # Check evaluation
    evaluations = int(evaluations)
    if evaluations < 3:
        raise ValueError('The number of evaluations must be 3 or greater.')

    # Figure setting
    fig, axes = plt.subplots(1, 1, figsize=(6, 4))
    axes.set_xlabel('Point 1 to point 2')
    axes.set_ylabel('Function')

    # Generate some x-values near the given parameters
    s = np.linspace(-padding, 1 + padding, evaluations)

    # Direction
    r = point_2 - point_1

    # Calculate function with other parameters fixed
    x = [point_1 + sj * r for sj in s]
    y = pints.evaluate(f, x, parallel=False)

    # Plot
    axes.plot(s, y, color='green')
    axes.axvline(0, color='#1f77b4', label='Point 1')
    axes.axvline(1, color='#7f7f7f', label='Point 2')
    axes.legend()

    return fig, axes
Exemple #7
0
 def to_model(self, q):
     """ See :meth:`Transformation.to_model()`. """
     q = pints.vector(q)
     return np.exp(q)
Exemple #8
0
 def log_jacobian_det(self, q):
     """ See :meth:`Transformation.log_jacobian_det()`. """
     q = pints.vector(q)
     return np.sum(q)
Exemple #9
0
 def log_jacobian_det_S1(self, q):
     """ See :meth:`Transformation.log_jacobian_det_S1()`. """
     q = pints.vector(q)
     logjacdet = self.log_jacobian_det(q)
     dlogjacdet = np.ones(self._n_parameters)
     return logjacdet, dlogjacdet
Exemple #10
0
                                                           boundaries,
                                                           method=pints.CMAES)

        sampler = pints.AdaptiveCovarianceMCMC(found_parameters)
        samplers.append(sampler)

    pickle.dump((samplers, log_posteriors), open(pickle_file, 'wb'))
else:
    samplers, log_posteriors = pickle.load(open(pickle_file, 'rb'))
    print('using starting points:')
    for i, (sampler, log_posterior) in enumerate(zip(samplers,
                                                     log_posteriors)):
        print('\t', sampler._x0)
        sampled_true_parameters[:, i] = sampler._x0[:-1]
        if not use_cmaes:
            sampler._x0 = pints.vector(x0)

        plt.clf()
        times = log_posterior._log_likelihood._problem._times
        values = log_posterior._log_likelihood._problem._values
        sim_values = log_posterior._log_likelihood._problem.evaluate(
            sampled_true_parameters[:, i])
        E_0, T_0, L_0, I_0 = model._calculate_characteristic_values()
        plt.plot(T_0 * times, I_0 * values * 1e6, label='experiment')
        plt.plot(T_0 * times, I_0 * sim_values * 1e6, label='simulation')
        plt.xlabel(r'$t$ (s)')
        plt.ylabel(r'$I_{tot}$ ($\mu A$)')
        plt.legend()
        filename = filenames[i]
        print('plotting fit for ', filename)
        plt.savefig('fit%s.pdf' % filename)
Exemple #11
0
 def to_model(self, q):
     """ See :meth:`Transformation.to_model()`. """
     return pints.vector(q)
 def __init__(self, bad_value=float('inf')):
     super(BadMiniProblem, self).__init__()
     self._v = pints.vector([bad_value, 2, -3])
 def __init__(self):
     super(BigMiniProblem, self).__init__()
     self._t = pints.vector([1, 2, 3, 4, 5, 6])
     self._v = pints.vector([-1, 2, 3, 4, 5, -6])
 def __init__(self):
     self._t = pints.vector([1, 2, 3])
     self._v = pints.matrix2d(
         np.array([[-1, 2, 3], [-1, 2, 3]]).swapaxes(0, 1))
Exemple #15
0
 def x_best(self):
     """ See: :meth:`pints.Optimiser.x_best()`. """
     return pints.vector(self._xs[0] if self._running else self._x0)
Exemple #16
0
 def jacobian(self, q):
     """ See :meth:`Transformation.jacobian()`. """
     q = pints.vector(q)
     diag = (self._b - self._a) / (np.exp(q) * (1. + np.exp(-q))**2)
     return np.diag(diag)
Exemple #17
0
    def tell(self, reply):
        """ See :meth:`pints.SingleChainMCMC.tell()`. """

        # Check ask/tell pattern
        if not self._ready_for_tell:
            raise RuntimeError('Tell called before proposal was set.')
        self._ready_for_tell = False

        # Unpack reply
        fx, grad = reply

        # Check reply, copy gradient
        fx = float(fx)
        grad = pints.vector(grad)
        assert grad.shape == (self._n_parameters, )

        # Very first call
        if self._current is None:
            # Check first point is somewhere sensible
            if not np.isfinite(fx):
                raise ValueError(
                    'Initial point for MCMC must have finite logpdf.')

            # Set current sample, log pdf of current sample and initialise
            # proposed sample for next iteration
            self._current = np.array(self._x0, copy=True)
            self._proposed = np.array(self._current, copy=True)

            # Sample height of the slice log_y for next iteration
            e = np.random.exponential(1)
            self._current_log_y = fx - e

            # Return first point in chain, which is x0
            # Note: `grad` is not stored in this iteration, so can return
            return np.copy(self._current), (fx, grad), True

        # Acceptance check
        if fx >= self._current_log_y:
            # The accepted sample becomes the new current sample
            self._current = np.copy(self._proposed)

            # Sample new log_y used to define the next slice
            e = np.random.exponential(1)
            self._current_log_y = fx - e

            # Reset parameters
            self._J = np.zeros((self._n_parameters, 0), float)
            self._k = 0
            self._c_bar = 0

            # Return accepted sample
            # Note: `grad` is not stored in this iteration, so can return
            return np.copy(self._current), (fx, grad), True

        # If proposal is reject, shrink rank of the next proposal distribution
        # by adding new orthonormal column to ``J``. This will represent a new
        # direction in which the conditional covariance of the proposal
        # distribution will be 0.
        else:
            # If J has less non-zero columns than``number of
            # parameters - 1``, shrink rank by adding new orthonormal
            # column

            if self._J.shape[1] < self._n_parameters - 1:
                # Gradient projection
                g_star = self._p(self._J, grad)

                # To prevent meaningless adaptations, we only perform this
                # operation when the angle between the gradient and its
                # projection into the nullspace of J is less than 60 degrees.
                if np.dot(g_star.transpose(), grad) > (
                        .5 * np.linalg.norm(g_star) * np.linalg.norm(grad)):
                    new_column = np.array(g_star / np.linalg.norm(g_star))
                    self._J = np.column_stack([self._J, new_column])
            return None
Exemple #18
0
 def log_jacobian_det(self, q):
     """ See :meth:`Transformation.log_jacobian_det()`. """
     q = pints.vector(q)
     s = self._softplus(-q)
     return np.sum(np.log(self._b - self._a) - 2. * s - q)
Exemple #19
0
 def jacobian(self, q):
     """ See :meth:`Transformation.jacobian()`. """
     q = pints.vector(q)
     return np.diag(np.exp(q))
Exemple #20
0
 def log_jacobian_det_S1(self, q):
     """ See :meth:`Transformation.log_jacobian_det_S1()`. """
     q = pints.vector(q)
     logjacdet = self.log_jacobian_det(q)
     dlogjacdet = 2. * np.exp(-q) * expit(q) - 1.
     return logjacdet, dlogjacdet
Exemple #21
0
def function(f, x, lower=None, upper=None, evaluations=20):
    """
    Creates 1d plots of a :class:`LogPDF` or a :class:`ErrorMeasure` around a
    point `x` (i.e. a 1-dimensional plot in each direction).

    Returns a ``matplotlib`` figure object and axes handle.

    Parameters
    ----------
    f
        A :class:`pints.LogPDF` or :class:`pints.ErrorMeasure` to plot.
    x
        A point in the function's input space.
    lower
        Optional lower bounds for each parameter, used to specify the lower
        bounds of the plot.
    upper
        Optional upper bounds for each parameter, used to specify the upper
        bounds of the plot.
    evaluations
        The number of evaluations to use in each plot.
    """
    import matplotlib.pyplot as plt

    # Check function and get n_parameters
    if not (isinstance(f, pints.LogPDF) or isinstance(f, pints.ErrorMeasure)):
        raise ValueError(
            'Given function must be pints.LogPDF or pints.ErrorMeasure.')
    n_param = f.n_parameters()

    # Check point
    x = pints.vector(x)
    if len(x) != n_param:
        raise ValueError(
            'Given point `x` must have same number of parameters as function.')

    # Check boundaries
    if lower is None:
        # Guess boundaries based on point x
        lower = x * 0.95
        lower[lower == 0] = -1
    else:
        lower = pints.vector(lower)
        if len(lower) != n_param:
            raise ValueError('Lower bounds must have same number of' +
                             ' parameters as function.')
    if upper is None:
        # Guess boundaries based on point x
        upper = x * 1.05
        upper[upper == 0] = 1
    else:
        upper = pints.vector(upper)
        if len(upper) != n_param:
            raise ValueError('Upper bounds must have same number of' +
                             ' parameters as function.')

    # Check number of evaluations
    evaluations = int(evaluations)
    if evaluations < 1:
        raise ValueError('Number of evaluations must be greater than zero.')

    # Create points to plot
    xs = np.tile(x, (n_param * evaluations, 1))
    for j in range(n_param):
        i1 = j * evaluations
        i2 = i1 + evaluations
        xs[i1:i2, j] = np.linspace(lower[j], upper[j], evaluations)

    # Evaluate points
    fs = pints.evaluate(f, xs, parallel=False)

    # Create figure
    fig, axes = plt.subplots(n_param, 1, figsize=(6, 2 * n_param))
    if n_param == 1:
        axes = np.asarray([axes], dtype=object)
    for j, p in enumerate(x):
        i1 = j * evaluations
        i2 = i1 + evaluations
        axes[j].plot(xs[i1:i2, j], fs[i1:i2], c='green', label='Function')
        axes[j].axvline(p, c='blue', label='Value')
        axes[j].set_xlabel('Parameter ' + str(1 + j))
        axes[j].legend()

    plt.tight_layout()
    return fig, axes
Exemple #22
0
 def to_model(self, q):
     """ See :meth:`Transformation.to_model()`. """
     q = pints.vector(q)
     return (self._b - self._a) * expit(q) + self._a
Exemple #23
0
 def xbest(self):
     """ See: :meth:`pints.Optimiser.xbest()`. """
     if not self._running:
         return pints.vector(self._x0)
     return pints.vector(self._xs[0])
Exemple #24
0
 def to_search(self, p):
     p = pints.vector(p)
     """ See :meth:`Transformation.to_search()`. """
     return np.log(p - self._a) - np.log(self._b - p)
Exemple #25
0
    def set_initial_position(self, x0=None, sigma0=None):
        """
        Updates the initial position and standard deviation used by this
        optimiser.

        Arguments:

        ``x0=None``
            An optional starting point for searches in the parameter space.
            This value may be used directly (for example as the initial
            position of a particle in :class:`PSO`) or indirectly (for example
            as the center of a distribution in :class:`XNES`).
        ``sigma0=None``
            An optional initial standard deviation around ``x0``. Can be
            specified either as a scalar value (one standard deviation for all
            coordinates) or as an array with one entry per dimension. Not all
            methods will use this information.
        """
        # Check initial solution
        if x0 is None:
            # Use value in middle of search space
            if self._boundaries is None:
                self._x0 = np.zeros(self._dimension)
            else:
                self._x0 = self._boundaries.center()
            self._x0.setflags(write=False)
        else:
            # Check given value
            self._x0 = pints.vector(x0)
            if len(self._x0) != self._dimension:
                raise ValueError(
                    'Initial position must have same dimension as function.')
            if self._boundaries is not None:
                if not self._boundaries.check(self._x0):
                    raise ValueError(
                        'Initial position must lie within given boundaries.')

        # Check initial standard deviation
        if sigma0 is None:
            if self._boundaries:
                # Use boundaries to guess
                self._sigma0 = (1 / 6.0) * self._boundaries.range()
            else:
                # Use initial position to guess at parameter scaling
                self._sigma0 = (1 / 3.0) * np.abs(self._x0)
                # But add 1 for any initial value that's zero
                self._sigma0 += (self._sigma0 == 0)
            self._sigma0.setflags(write=False)

        elif np.isscalar(sigma0):
            # Single number given, convert to vector
            sigma0 = float(sigma0)
            if sigma0 <= 0:
                raise ValueError(
                    'Initial standard deviation must be greater than zero.')
            self._sigma0 = np.ones(self._dimension) * sigma0
            self._sigma0.setflags(write=False)

        else:
            # Vector given
            self._sigma0 = pints.vector(sigma0)
            if len(self._sigma0) != self._dimension:
                raise ValueError(
                    'Initial standard deviation must be None, scalar, or have'
                    ' same dimension as function.')
            if np.any(self._sigma0 <= 0):
                raise ValueError(
                    'Initial standard deviations must be greater than zero.')
Exemple #26
0
 def __init__(self, scalings):
     self.s = pints.vector(scalings)
     self.inv_s = 1. / self.s
     self._n_parameters = len(self.s)
Exemple #27
0
    def __init__(
            self, function, x0, sigma0=None, boundaries=None,
            transformation=None, method=None):

        # Convert x0 to vector
        # This converts e.g. (1, 7) shapes to (7, ), giving users a bit more
        # freedom with the exact shape passed in. For example, to allow the
        # output of LogPrior.sample(1) to be passed in.
        x0 = pints.vector(x0)

        # Check dimension of x0 against function
        if function.n_parameters() != len(x0):
            raise ValueError(
                'Starting point must have same dimension as function to'
                ' optimise.')

        # Check if minimising or maximising
        self._minimising = not isinstance(function, pints.LogPDF)

        # Apply a transformation (if given). From this point onward the
        # optimiser will see only the transformed search space and will know
        # nothing about the model parameter space.
        if transformation is not None:
            # Convert error measure or log pdf
            if self._minimising:
                function = transformation.convert_error_measure(function)
            else:
                function = transformation.convert_log_pdf(function)

            # Convert initial position
            x0 = transformation.to_search(x0)

            # Convert sigma0, if provided
            if sigma0 is not None:
                sigma0 = transformation.convert_standard_deviation(sigma0, x0)
            if boundaries:
                boundaries = transformation.convert_boundaries(boundaries)

        # Store transformation for later detransformation: if using a
        # transformation, any parameters logged to the filesystem or printed to
        # screen should be detransformed first!
        self._transformation = transformation

        # Store function
        if self._minimising:
            self._function = function
        else:
            self._function = pints.ProbabilityBasedError(function)
        del function

        # Create optimiser
        if method is None:
            method = pints.CMAES
        elif not issubclass(method, pints.Optimiser):
            raise ValueError('Method must be subclass of pints.Optimiser.')
        self._optimiser = method(x0, sigma0, boundaries)

        # Check if sensitivities are required
        self._needs_sensitivities = self._optimiser.needs_sensitivities()

        # Track optimiser's f_best or f_guessed
        self._use_f_guessed = None
        self.set_f_guessed_tracking()

        # Logging
        self._log_to_screen = True
        self._log_filename = None
        self._log_csv = False
        self.set_log_interval()

        # Parallelisation
        self._parallel = False
        self._n_workers = 1
        self.set_parallel()

        # User callback
        self._callback = None

        # :meth:`run` can only be called once
        self._has_run = False

        #
        # Stopping criteria
        #

        # Maximum iterations
        self._max_iterations = None
        self.set_max_iterations()

        # Maximum unchanged iterations
        self._unchanged_max_iterations = None  # n_iter w/o change until stop
        self._unchanged_threshold = 1          # smallest significant f change
        self.set_max_unchanged_iterations()

        # Maximum evaluations
        self._max_evaluations = None

        # Threshold value
        self._threshold = None

        # Post-run statistics
        self._evaluations = None
        self._iterations = None
        self._time = None
Exemple #28
0
 def to_search(self, p):
     """ See :meth:`Transformation.to_search()`. """
     p = pints.vector(p)
     return self.s * p
Exemple #29
0
    def __init__(self,
                 function,
                 x0,
                 sigma0=None,
                 boundaries=None,
                 method=None):

        # Convert x0 to vector
        # This converts e.g. (1, 7) shapes to (7, ), giving users a bit more
        # freedom with the exact shape passed in. For example, to allow the
        # output of LogPrior.sample(1) to be passed in.
        x0 = pints.vector(x0)

        # Check dimension of x0 against function
        if function.n_parameters() != len(x0):
            raise ValueError(
                'Starting point must have same dimension as function to'
                ' optimise.')

        # Check if minimising or maximising
        self._minimising = not isinstance(function, pints.LogPDF)

        # Store function
        if self._minimising:
            self._function = function
        else:
            self._function = pints.ProbabilityBasedError(function)
        del (function)

        # Create optimiser
        if method is None:
            method = pints.CMAES
        elif not issubclass(method, pints.Optimiser):
            raise ValueError('Method must be subclass of pints.Optimiser.')
        self._optimiser = method(x0, sigma0, boundaries)

        # Check if sensitivities are required
        self._needs_sensitivities = self._optimiser.needs_sensitivities()

        # Logging
        self._log_to_screen = True
        self._log_filename = None
        self._log_csv = False
        self.set_log_interval()

        # Parallelisation
        self._parallel = False
        self._n_workers = 1
        self.set_parallel()

        #
        # Stopping criteria
        #

        # Maximum iterations
        self._max_iterations = None
        self.set_max_iterations()

        # Maximum unchanged iterations
        self._max_unchanged_iterations = None
        self._min_significant_change = 1
        self.set_max_unchanged_iterations()

        # Threshold value
        self._threshold = None

        # Post-run statistics
        self._evaluations = None
        self._iterations = None
        self._time = None
Exemple #30
0
 def __init__(self, c=[0, 0]):
     self._c = pints.vector(c)
     self._n = len(self._c)