TPCCLIB
Loading...
Searching...
No Matches
simplex.c File Reference

Nelder-Mead algorithm (Downhill simplex) for function minimization. More...

#include "libtpcmodel.h"

Go to the source code of this file.

Functions

double simplex (double(*_fun)(double *), int parNr, double *par, double *delta, double maxerr, int maxiter, int verbose)
 

Detailed Description

Nelder-Mead algorithm (Downhill simplex) for function minimization.

Author
Vesa Oikonen

Definition in file simplex.c.

Function Documentation

◆ simplex()

double simplex ( double(* _fun )(double *),
int parNr,
double * par,
double * delta,
double maxerr,
int maxiter,
int verbose )

Downhill simplex function minimization routine.

Note that if any constraints are required for the parameter values they must be set in the function.

Returns
Function returns the least calculated value of func.
See also
powell, tgo, bobyqa, nlopt1D
Parameters
_funPointer to the function to be minimized. It must be defined in main program as: double func(double *p); where p is the parameter array.
parNrThe number of unknown parameters
parThis double array contains the minimized parameters. Initial values must be set.
deltaThis double array contains the initial changes to parameters. To fix a parameter, set the corresponding delta to 0.
maxerrMaximal error allowed (stopping rule #1)
maxiterMaximal nr of iterations allowed (stopping rule #2)
verboseVerbose level; if zero, then only warnings are printed into stderr

Definition at line 27 of file simplex.c.

45 {
46 int i, j, Meas, it;
47 double Max, Min, Max2, Min2, LastChi;
48 int NextBest, New2, Best;
49
50
51 if(verbose>0) printf("%s(func, %d, p[], delta[], %g, %d)\n", __func__, parNr, maxerr, maxiter);
52 /* SetUp */
53 _simplexFunc=_fun;
54 _simplexParNr=parNr; it=0; NewPnt=_simplexParNr+1;
55 for(i=0; i<_simplexParNr; i++) for(Meas=0; Meas<_simplexParNr+3; Meas++) _simplexP[Meas][i]=par[i];
56 if(verbose>1) {
57 for(int i=0; i<_simplexParNr; i++) printf("%12g %12g\n", _simplexP[0][i], delta[i]);
58 printf("ChiSqr of guesses: %f\n", (*_simplexFunc)(_simplexP[0]));
59 }
60 New2=NewPnt+1;
61 for(Meas=0; Meas<=_simplexParNr; Meas++) {
62 it++;
63 _simplexR[Meas] = (*_simplexFunc)(_simplexP[Meas]);
64 for (i=0; i<_simplexParNr; i++) {
65 if(i==Meas) delta[i]= -delta[i];
66 _simplexP[Meas+1][i] = _simplexP[Meas][i] + delta[i];
67 }
68 }
69
70 /* Simplex minimization */
71 LastChi = 1.0E30; NextBest=Best=0;
72 do {
73 for(j=0; j<100; j++) {
74 /* Find the max and min response measured */
75 Max=0.; Min=1.0E30;
76 for (i=0; i<=_simplexParNr; i++) {
77 if(_simplexR[i] > Max) {Max=_simplexR[i]; Worst=i;}
78 if(_simplexR[i] < Min) {Min=_simplexR[i]; Best=i; }
79 }
80 /* Find 2nd best and 2nd worst, too */
81 Max2=0.; Min2=1.0E30;
82 for (i=0; i<=_simplexParNr; i++) {
83 if((_simplexR[i] > Max2) && (_simplexR[i] < Max)) Max2=_simplexR[i];
84 if((_simplexR[i] < Min2) && (_simplexR[i] > Min)) {
85 Min2=_simplexR[i]; NextBest=i;}
86 }
87 /* Calculate centroid of all measurements */
88 for(i=0; i<_simplexParNr; i++) {
89 _simplexC[i]=0.;
90 for(Meas=0; Meas<=_simplexParNr; Meas++)
91 if(Meas!=Worst) _simplexC[i]+=_simplexP[Meas][i];
92 _simplexC[i]/=(double)_simplexParNr;
93 }
94 /* Measure the response at the point reflected away from worst */
95 for(i=0; i<_simplexParNr; i++)
96 _simplexP[NewPnt][i] = 2.*_simplexC[i] - _simplexP[Worst][i];
97 _simplexR[NewPnt]= (*_simplexFunc)(_simplexP[NewPnt]);
98 it++;
99 /* If this one is better than previous best, then expand in this
100 direction */
101 if(_simplexR[NewPnt] < _simplexR[Best]) {
102 _simplexGenNew(New2,2.0); it++;
103 } else {
104 /* If this one is worse than previous worst, measure point halfway
105 between worst and centroid */
106 if(_simplexR[NewPnt] > _simplexR[Worst]) {
107 _simplexGenNew(New2,-0.5); it++;
108 } else {
109 /* If newest response is worse than next best point
110 but better than worst, measure response halfway
111 between centroid and newest point */
112 if((_simplexR[NextBest] < _simplexR[NewPnt]) &&
113 (_simplexR[NewPnt] < _simplexR[Worst])) {
114 _simplexGenNew(New2,0.5); it++;
115 } else {
116 /* If none of the above, keep the new point as best */
117 for(i=0; i<_simplexParNr; i++)
118 _simplexP[Worst][i] = _simplexP[NewPnt][i];
119 _simplexR[Worst] = _simplexR[NewPnt];
120 }
121 }
122 }
123 }
124 if(verbose>1) printf(" it=%i; ChiSqr=%f\n", it, _simplexR[Best]);
125 if(verbose>2)
126 for(i=0; i<_simplexParNr; i++) printf(" %12g\n", _simplexP[Best][i]);
127 /* Check if fitting is not proceeding */
128 if(_simplexR[Best] == LastChi) {
129 for(i=0; i<_simplexParNr; i++) par[i]=_simplexP[Best][i];
130 return _simplexR[Best];
131 }
132 LastChi = _simplexR[Best];
133 } while ((_simplexR[Best]>maxerr) && (it<=maxiter));
134
135 for(i=0; i<_simplexParNr; i++) par[i]=_simplexP[Best][i];
136 return _simplexR[Best];
137}