29 void PrintContourPoint(
const std::pair<double,double> & point) {
30 std::cout <<
"\t x = " << point.first <<
" y = " << point.second << std::endl;
33 std::vector<std::pair<double,double> > MnContours::operator()(
unsigned int px,
unsigned int py,
unsigned int npoints)
const {
35 ContoursError cont = Contour(px, py, npoints);
39 ContoursError MnContours::Contour(
unsigned int px,
unsigned int py,
unsigned int npoints)
const {
43 unsigned int maxcalls = 100*(npoints+5)*(fMinimum.UserState().VariableParameters()+1);
44 unsigned int nfcn = 0;
46 std::vector<std::pair<double,double> > result; result.reserve(npoints);
47 std::vector<MnUserParameterState> states;
55 MnMinos minos(fFCN, fMinimum, fStrategy);
57 double valx = fMinimum.UserState().Value(px);
58 double valy = fMinimum.UserState().Value(py);
60 MinosError mex = minos.Minos(px);
63 MN_ERROR_MSG(
"MnContours is unable to find first two points.");
64 return ContoursError(px, py, result, mex, mex, nfcn);
66 std::pair<double,double> ex = mex();
68 MinosError mey = minos.Minos(py);
71 MN_ERROR_MSG(
"MnContours is unable to find second two points.");
72 return ContoursError(px, py, result, mex, mey, nfcn);
74 std::pair<double,double> ey = mey();
76 MnMigrad migrad(fFCN, fMinimum.UserState(), MnStrategy(std::max(0,
int(fStrategy.Strategy()-1))));
79 migrad.SetValue(px, valx + ex.second);
80 FunctionMinimum exy_up = migrad();
81 nfcn += exy_up.NFcn();
82 if(!exy_up.IsValid()) {
83 MN_ERROR_VAL2(
"MnContours: unable to find Upper y Value for x Parameter",px);
84 return ContoursError(px, py, result, mex, mey, nfcn);
87 migrad.SetValue(px, valx + ex.first);
88 FunctionMinimum exy_lo = migrad();
89 nfcn += exy_lo.NFcn();
90 if(!exy_lo.IsValid()) {
91 MN_ERROR_VAL2(
"MnContours: unable to find Lower y Value for x Parameter",px);
92 return ContoursError(px, py, result, mex, mey, nfcn);
96 MnMigrad migrad1(fFCN, fMinimum.UserState(), MnStrategy(std::max(0,
int(fStrategy.Strategy()-1))));
98 migrad1.SetValue(py, valy + ey.second);
99 FunctionMinimum eyx_up = migrad1();
100 nfcn += eyx_up.NFcn();
101 if(!eyx_up.IsValid()) {
102 MN_ERROR_VAL2(
"MnContours: unable to find Upper x Value for y Parameter",py);
103 return ContoursError(px, py, result, mex, mey, nfcn);
106 migrad1.SetValue(py, valy + ey.first);
107 FunctionMinimum eyx_lo = migrad1();
108 nfcn += eyx_lo.NFcn();
109 if(!eyx_lo.IsValid()) {
110 MN_ERROR_VAL2(
"MnContours: unable to find Lower x Value for y Parameter",py);
111 return ContoursError(px, py, result, mex, mey, nfcn);
114 double scalx = 1./(ex.second - ex.first);
115 double scaly = 1./(ey.second - ey.first);
117 result.push_back(std::pair<double,double>(valx + ex.first, exy_lo.UserState().Value(py)));
118 result.push_back(std::pair<double,double>(eyx_lo.UserState().Value(px), valy + ey.first));
119 result.push_back(std::pair<double,double>(valx + ex.second, exy_up.UserState().Value(py)));
120 result.push_back(std::pair<double,double>(eyx_up.UserState().Value(px), valy + ey.second));
123 MnUserParameterState upar = fMinimum.UserState();
126 int printLevel = MnPrint::Level();
128 if (printLevel > 0 ) {
129 std::cout <<
"MnContour : List of found points " << std::endl;
130 std::cout <<
"\t Parameter x is " << upar.Name(px) << std::endl;
131 std::cout <<
"\t Parameter y is " << upar.Name(py) << std::endl;
134 if (printLevel > 0) {
135 for (
unsigned int i = 0; i < 4; ++i)
136 PrintContourPoint(result[i] );
142 std::vector<unsigned int> par(2); par[0] = px; par[1] = py;
143 MnFunctionCross cross(fFCN, upar, fMinimum.Fval(), fStrategy);
145 for(
unsigned int i = 4; i < npoints; i++) {
147 std::vector<std::pair<double,double> >::iterator idist1 = result.end()-1;
148 std::vector<std::pair<double,double> >::iterator idist2 = result.begin();
149 double dx = idist1->first - (idist2)->first;
150 double dy = idist1->second - (idist2)->second;
151 double bigdis = scalx*scalx*dx*dx + scaly*scaly*dy*dy;
153 for(std::vector<std::pair<double,double> >::iterator ipair = result.begin(); ipair != result.end()-1; ++ipair) {
154 double distx = ipair->first - (ipair+1)->first;
155 double disty = ipair->second - (ipair+1)->second;
156 double dist = scalx*scalx*distx*distx + scaly*scaly*disty*disty;
170 if(nfcn > maxcalls) {
171 MN_ERROR_MSG(
"MnContours: maximum number of function calls exhausted.");
172 return ContoursError(px, py, result, mex, mey, nfcn);
175 double xmidcr = a1*idist1->first + a2*(idist2)->first;
176 double ymidcr = a1*idist1->second + a2*(idist2)->second;
177 double xdir = (idist2)->second - idist1->second;
178 double ydir = idist1->first - (idist2)->first;
179 double scalfac = sca*std::max(fabs(xdir*scalx), fabs(ydir*scaly));
180 double xdircr = xdir/scalfac;
181 double ydircr = ydir/scalfac;
182 std::vector<double> pmid(2); pmid[0] = xmidcr; pmid[1] = ymidcr;
183 std::vector<double> pdir(2); pdir[0] = xdircr; pdir[1] = ydircr;
185 MnCross opt = cross(par, pmid, pdir, toler, maxcalls);
190 MN_ERROR_VAL2(
"MnContours : unable to find point on Contour",i+1);
191 MN_ERROR_VAL2(
"MnContours : found only i points",i);
192 return ContoursError(px, py, result, mex, mey, nfcn);
200 double aopt = opt.Value();
201 if(idist2 == result.begin()) {
202 result.push_back(std::pair<double,double>(xmidcr+(aopt)*xdircr, ymidcr + (aopt)*ydircr));
203 if (printLevel > 0) PrintContourPoint( result.back() );
206 result.insert(idist2, std::pair<double,double>(xmidcr+(aopt)*xdircr, ymidcr + (aopt)*ydircr));
207 if (printLevel > 0) PrintContourPoint( *idist2 );
211 std::cout <<
"MnContour: Number of contour points = " << result.size() << std::endl;
213 return ContoursError(px, py, result, mex, mey, nfcn);