Source code for pints.toy._rosenbrock

#
# Rosenbrock error measure and log-pdf.
#
# This file is part of PINTS (https://github.com/pints-team/pints/) which is
# released under the BSD 3-clause license. See accompanying LICENSE.md for
# copyright notice and full license details.
#
import numpy as np
import pints

from . import ToyLogPDF


[docs]class RosenbrockError(pints.ErrorMeasure): r""" Error measure based on the rosenbrock function [1]_. .. math:: f(x,y) = (1 - x)^2 + 100(y - x^2)^2 Extends :class:`pints.ErrorMeasure`. References ---------- .. [1] https://en.wikipedia.org/wiki/Rosenbrock_function """ def __init__(self): self._a = 1 self._b = 100 def __call__(self, x): return (self._a - x[0])**2 + self._b * (x[1] - x[0]**2)**2
[docs] def n_parameters(self): """ See :meth:`pints.ErrorMeasure.n_parameters()`. """ return 2
[docs] def optimum(self): """ Returns the global optimum for this function. """ return self._a, self._a**2
[docs]class RosenbrockLogPDF(ToyLogPDF): r""" Unnormalised LogPDF based on the Rosenbrock function [2]_ with an addition of 1 on the denominator to avoid a discontinuity: .. math:: f(x,y) = -log[1 + (1 - x)^2 + 100(y - x^2)^2 ] Extends :class:`pints.toy.ToyLogPDF`. References ---------- .. [2] https://en.wikipedia.org/wiki/Rosenbrock_function """ def __init__(self): self._f = RosenbrockError() # assumes uniform prior with bounds given by suggested_bounds self._true_mean = np.array([0.8693578490590254, 2.599780856590108]) self._true_cov = np.array([[1.805379677045191, 2.702575590274159], [2.702575590274159, 8.526583078612177]]) def __call__(self, x): return -np.log(1.0 + self._f(x))
[docs] def distance(self, samples): """ Calculates a measure of normed distance of samples from exact mean and covariance matrix assuming uniform prior with bounds given by :meth:`suggested_bounds()`. See :meth:`pints.toy.ToyLogPDF.distance()`. """ # Check size of input if not len(samples.shape) == 2: raise ValueError('Given samples list must be n x 2.') if samples.shape[1] != self._f.n_parameters(): raise ValueError( 'Given samples must have length ' + str(self._f.n_parameters())) distance = ( np.linalg.norm(self._true_mean - np.mean(samples, axis=0)) + np.linalg.norm(self._true_cov - np.cov(np.transpose(samples))) ) return distance
[docs] def evaluateS1(self, x): """ See :meth:`LogPDF.evaluateS1()`. """ L = self.__call__(x) x1 = x[0] y1 = x[1] a = self._f._a b = self._f._b dx = -(-2 * (a - x1) - 4 * b * x1 * (y1 - x1**2)) / ( 1 + (a - x1)**2 + b * (y1 - x1**2)**2 ) dy = -2 * b * (y1 - x1**2) / ( 1 + (a - x1)**2 + b * (y1 - x1**2)**2 ) # derivative wrt x dL = np.array([dx, dy]) return L, dL
[docs] def n_parameters(self): """ See :meth:`pints.LogPDF.n_parameters()`. """ return self._f.n_parameters()
[docs] def optimum(self): """ Returns the global optimum for this LogPDF. """ return self._f.optimum()
[docs] def suggested_bounds(self): """ See :meth:`pints.toy.ToyLogPDF.suggested_bounds()`. """ # think the following hard bounds are ok bounds = [[-2, 4], [-1, 12]] return np.transpose(bounds).tolist()