-
Paul McCarthy authoredPaul McCarthy authored
Simplex.h 4.08 KiB
/*! \file Simplex.h
\brief Contains declaration of Simplex class that can be used for Nelder-Mead simplex minimisation.
\author Jesper Andersson
\version 1.0b, Oct., 2013.
*/
// Contains declaration of Simplex class that can
// be used for Nelder-Mead simplex minimisation.
//
// Simplex.h
//
// Jesper Andersson, FMRIB Image Analysis Group
//
// Copyright (C) 2013 University of Oxford
//
#ifndef Simplex_h
#define Simplex_h
#include <iostream>
#include <cfloat>
#include <cmath>
#include <string>
#include <vector>
#include "armawrap/newmat.h"
#include "miscmaths.h"
#include "nonlin.h"
namespace MISCMATHS {
/****************************************************************//**
*
* \brief Class used for implementing Nelder-Mead minimisation.
*
* Implements a class for implementing Nelder-Mead downhill slope
* simplex minimisation. It implements the full minimisation through
* its member function Minimise, but it also provides a set of utility
* functions for anyone wanting to provide a slightly different
* implementation.
*
********************************************************************/
class Simplex
{
public:
Simplex(const NEWMAT::ColumnVector& p,
const MISCMATHS::NonlinCF& cf);
Simplex(const NEWMAT::ColumnVector& p,
const MISCMATHS::NonlinCF& cf,
const NEWMAT::ColumnVector& l);
~Simplex() {}
/// Minimises the costunction until the fractional difference between points in simplex is < ftol
bool Minimise(double ftol, unsigned int miter);
/// Checks if the fractional difference between points in simplex is < ftol
bool HasConverged(double ftol) const {
return(2.0*std::abs(WorstFuncVal()-BestFuncVal()) < ftol*(std::abs(BestFuncVal())+std::abs(WorstFuncVal())));
}
/// Returns the number of parameters
unsigned int NoPar() const { return(static_cast<unsigned int>(_sp.Nrows())); }
/// Returns the "best" (lowest function value) parameters in the simplex
const NEWMAT::ColumnVector& BestPar() const { return(_smx[_bsti]); }
/// Returns the "best" (lowest) function value in the simplex
double BestFuncVal() const { return(_fv[_bsti]); }
/// Returns the 2nd to worst (highest) function value in the simplex
double SecondWorstFuncVal() const { return(_fv[_nwsti]); }
/// Returns the worst (highest) function value in the simplex
double WorstFuncVal() const { return(_fv[_wrsti]); }
/// Reflects the worst point through the average of the remaining points
double Reflect();
/// Expands upon a previous reflexion
double Expand();
/// Contracts the worst point half-way towards the average of the remaining points
double Contract();
/// Contracts all except the best point half-way towards the best point
void MultiContract();
/// Update the indicies for best, worst and 2nd to worst points.
void UpdateRankIndicies();
// Global function. Prints out the points of the simplex and the associated function values
friend std::ostream& operator<<(std::ostream& op, const Simplex& smplx)
{
op << "Simplex = " << std::endl;
for (unsigned int i=0; i<smplx._smx.size(); i++) {
for (unsigned int j=1; j<smplx._smx.size(); j++) {
op << std::setw(10) << std::setprecision(4) << smplx._smx[i](j);
}
op << " | " << std::setw(10) << std::setprecision(4) << smplx._fv[i] << std::endl;
}
return(op);
}
private:
const MISCMATHS::NonlinCF& _cf;
const NEWMAT::ColumnVector _sp;
std::vector<NEWMAT::ColumnVector> _smx;
std::vector<double> _fv;
unsigned int _bsti; // Best (lowest function value) point
unsigned int _wrsti; // Worst (highest function value) point
unsigned int _nwsti; // Second worst (2nd highest function value) point
NEWMAT::ColumnVector _rp; // Latest reflexion point
void setup_simplex(const NEWMAT::ColumnVector& l);
void calculate_reflexion_point(unsigned int ii);
};
} // End namespace MISCMATHS
#endif // End #ifndef Simplex_h