00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "Minuit2/SimplexBuilder.h"
00011 #include "Minuit2/FunctionMinimum.h"
00012 #include "Minuit2/MnFcn.h"
00013 #include "Minuit2/MinimumSeed.h"
00014 #include "Minuit2/SimplexParameters.h"
00015 #include "Minuit2/MinimumState.h"
00016
00017 #if defined(DEBUG) || defined(WARNINGMSG)
00018 #include "Minuit2/MnPrint.h"
00019 #endif
00020
00021
00022 namespace ROOT {
00023
00024 namespace Minuit2 {
00025
00026
00027
00028
00029 FunctionMinimum SimplexBuilder::Minimum(const MnFcn& mfcn, const GradientCalculator&, const MinimumSeed& seed, const MnStrategy&, unsigned int maxfcn, double minedm) const {
00030
00031
00032
00033
00034 #ifdef DEBUG
00035 std::cout << "Running Simplex with maxfcn = " << maxfcn << " minedm = " << minedm << std::endl;
00036 #endif
00037
00038 const MnMachinePrecision& prec = seed.Precision();
00039 MnAlgebraicVector x = seed.Parameters().Vec();
00040 MnAlgebraicVector step = 10.*seed.Gradient().Gstep();
00041
00042 unsigned int n = x.size();
00043 double wg = 1./double(n);
00044 double alpha = 1., beta = 0.5, gamma = 2., rhomin = 4., rhomax = 8.;
00045 double rho1 = 1. + alpha;
00046
00047
00048 double rho2 = 1. + alpha*gamma;
00049
00050
00051 std::vector<std::pair<double, MnAlgebraicVector> > simpl; simpl.reserve(n+1);
00052 simpl.push_back(std::pair<double, MnAlgebraicVector>(seed.Fval(), x));
00053
00054 unsigned int jl = 0, jh = 0;
00055 double amin = seed.Fval(), aming = seed.Fval();
00056
00057 for(unsigned int i = 0; i < n; i++) {
00058 double dmin = 8.*prec.Eps2()*(fabs(x(i)) + prec.Eps2());
00059 if(step(i) < dmin) step(i) = dmin;
00060 x(i) += step(i);
00061 double tmp = mfcn(x);
00062 if(tmp < amin) {
00063 amin = tmp;
00064 jl = i+1;
00065 }
00066 if(tmp > aming) {
00067 aming = tmp;
00068 jh = i+1;
00069 }
00070 simpl.push_back(std::pair<double, MnAlgebraicVector>(tmp, x));
00071 x(i) -= step(i);
00072 }
00073 SimplexParameters simplex(simpl, jh, jl);
00074
00075 #ifdef DEBUG
00076 std::cout << "simplex initial parameters - min " << jl << " " << amin << " max " << jh << " " << aming << std::endl;
00077 for (unsigned int i = 0; i < simplex.Simplex().size(); ++i)
00078 std::cout << " i = " << i << " x = " << simplex(i).second << " fval(x) = " << simplex(i).first << std::endl;
00079 #endif
00080
00081 double edmPrev = simplex.Edm();
00082 do {
00083 jl = simplex.Jl();
00084 jh = simplex.Jh();
00085 amin = simplex(jl).first;
00086 edmPrev = simplex.Edm();
00087
00088 #ifdef DEBUG
00089 std::cout << "\n\nsimplex iteration: edm = " << simplex.Edm()
00090 << "\n--> Min Param is " << jl << " pmin " << simplex(jl).second << " f(pmin) " << amin
00091 << "\n--> Max param is " << jh << " " << simplex(jh).first << std::endl;
00092
00093
00094
00095
00096 #endif
00097 MnAlgebraicVector pbar(n);
00098 for(unsigned int i = 0; i < n+1; i++) {
00099 if(i == jh) continue;
00100 pbar += (wg*simplex(i).second);
00101 }
00102
00103 MnAlgebraicVector pstar = (1. + alpha)*pbar - alpha*simplex(jh).second;
00104 double ystar = mfcn(pstar);
00105
00106 #ifdef DEBUG
00107 std::cout << " pbar = " << pbar << std::endl;
00108 std::cout << " pstar = " << pstar << " f(pstar) = " << ystar << std::endl;
00109 #endif
00110
00111 if(ystar > amin) {
00112 if(ystar < simplex(jh).first) {
00113 simplex.Update(ystar, pstar);
00114 if(jh != simplex.Jh()) continue;
00115 }
00116 MnAlgebraicVector pstst = beta*simplex(jh).second + (1. - beta)*pbar;
00117 double ystst = mfcn(pstst);
00118 #ifdef DEBUG
00119 std::cout << "Reduced simplex pstst = " << pstst << " f(pstst) = " << ystst << std::endl;
00120 #endif
00121 if(ystst > simplex(jh).first) break;
00122 simplex.Update(ystst, pstst);
00123 continue;
00124 }
00125
00126 MnAlgebraicVector pstst = gamma*pstar + (1. - gamma)*pbar;
00127 double ystst = mfcn(pstst);
00128 #ifdef DEBUG
00129 std::cout << " pstst = " << pstst << " f(pstst) = " << ystst << std::endl;
00130 #endif
00131
00132 double y1 = (ystar - simplex(jh).first)*rho2;
00133 double y2 = (ystst - simplex(jh).first)*rho1;
00134 double rho = 0.5*(rho2*y1 - rho1*y2)/(y1 - y2);
00135 if(rho < rhomin) {
00136 if(ystst < simplex(jl).first) simplex.Update(ystst, pstst);
00137 else simplex.Update(ystar, pstar);
00138 continue;
00139 }
00140 if(rho > rhomax) rho = rhomax;
00141 MnAlgebraicVector prho = rho*pbar + (1. - rho)*simplex(jh).second;
00142 double yrho = mfcn(prho);
00143 #ifdef DEBUG
00144 std::cout << " prho = " << prho << " f(prho) = " << yrho << std::endl;
00145 #endif
00146 if(yrho < simplex(jl).first && yrho < ystst) {
00147 simplex.Update(yrho, prho);
00148 continue;
00149 }
00150 if(ystst < simplex(jl).first) {
00151 simplex.Update(ystst, pstst);
00152 continue;
00153 }
00154 if(yrho > simplex(jl).first) {
00155 if(ystst < simplex(jl).first) simplex.Update(ystst, pstst);
00156 else simplex.Update(ystar, pstar);
00157 continue;
00158 }
00159 if(ystar > simplex(jh).first) {
00160 pstst = beta*simplex(jh).second + (1. - beta)*pbar;
00161 ystst = mfcn(pstst);
00162 if(ystst > simplex(jh).first) break;
00163 simplex.Update(ystst, pstst);
00164 }
00165 #ifdef DEBUG
00166 std::cout << "End loop : edm = " << simplex.Edm() << " pstst = " << pstst << " f(pstst) = " << ystst << std::endl;
00167 #endif
00168 } while( (simplex.Edm() > minedm || edmPrev > minedm ) && mfcn.NumOfCalls() < maxfcn);
00169
00170 jl = simplex.Jl();
00171 jh = simplex.Jh();
00172 amin = simplex(jl).first;
00173
00174 MnAlgebraicVector pbar(n);
00175 for(unsigned int i = 0; i < n+1; i++) {
00176 if(i == jh) continue;
00177 pbar += (wg*simplex(i).second);
00178 }
00179 double ybar = mfcn(pbar);
00180 if(ybar < amin) simplex.Update(ybar, pbar);
00181 else {
00182 pbar = simplex(jl).second;
00183 ybar = simplex(jl).first;
00184 }
00185
00186 MnAlgebraicVector dirin = simplex.Dirin();
00187
00188 dirin *= sqrt(mfcn.Up()/simplex.Edm());
00189
00190 #ifdef DEBUG
00191 std::cout << "End simplex " << simplex.Edm() << " pbar = " << pbar << " f(p) = " << ybar << std::endl;
00192 #endif
00193
00194
00195 MinimumState st(MinimumParameters(pbar, dirin, ybar), simplex.Edm(), mfcn.NumOfCalls());
00196
00197 if(mfcn.NumOfCalls() > maxfcn) {
00198 #ifdef WARNINGMSG
00199 MN_INFO_MSG("Simplex did not converge, #fcn calls exhausted.");
00200 #endif
00201 return FunctionMinimum(seed, std::vector<MinimumState>(1, st), mfcn.Up(), FunctionMinimum::MnReachedCallLimit());
00202 }
00203 if(simplex.Edm() > minedm) {
00204 #ifdef WARNINGMSG
00205 MN_INFO_MSG("Simplex did not converge, edm > minedm.");
00206 #endif
00207 return FunctionMinimum(seed, std::vector<MinimumState>(1, st), mfcn.Up(), FunctionMinimum::MnAboveMaxEdm());
00208 }
00209
00210 return FunctionMinimum(seed, std::vector<MinimumState>(1, st), mfcn.Up());
00211 }
00212
00213 }
00214
00215 }