/*! \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