AmpTools
MinuitMinimizationManager.cc
Go to the documentation of this file.
1 
2 // This file is a part of MinuitInterface - a front end for the Minuit minimization
3 // package (Minuit itself was authored by Fred James, of CERN)
4 //
5 //
6 // Copyright Cornell University 1993, 1996, All Rights Reserved.
7 //
8 // This software written by Lawrence Gibbons, Cornell University.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions
12 // are met:
13 // 1. Redistributions of source code must retain the above copyright
14 // notice and author attribution, this list of conditions and the
15 // following disclaimer.
16 // 2. Redistributions in binary form must reproduce the above copyright
17 // notice and author attribution, this list of conditions and the
18 // following disclaimer in the documentation and/or other materials
19 // provided with the distribution.
20 // 3. Neither the name of the University nor the names of its contributors
21 // may be used to endorse or promote products derived from this software
22 // without specific prior written permission.
23 //
24 // Creation of derivative forms of this software for commercial
25 // utilization may be subject to restriction; written permission may be
26 // obtained from Cornell University.
27 //
28 // CORNELL MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. By way
29 // of example, but not limitation, CORNELL MAKES NO REPRESENTATIONS OR
30 // WARRANTIES OF MERCANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT
31 // THE USE OF THIS SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY PATENTS,
32 // COPYRIGHTS, TRADEMARKS, OR OTHER RIGHTS. Cornell University shall not be
33 // held liable for any liability with respect to any claim by the user or any
34 // other party arising from use of the program.
35 //
36 
37 #include <sstream>
38 #include "UpRootMinuit/URMinuit.h"
39 
42 
43 #include <sys/time.h>
44 
45 using namespace std;
46 
48  MISubject(),
49  URFcn(),
50  m_parameterManager(*this),
51  m_fitter( maxParameters ),
52  m_derivativesEnabled( false ),
53  m_status( kUndefinedStatus ),
54  m_newFlagFunction( 0 ),
55  m_lastMinuitFlag( -1 ),
56  m_bestMin( 0 ),
57  m_estDistToMin( 0 ),
58  m_eMatrixStat( 0 ),
59  m_strategy( 1 ),
60  m_precision( 0 ) // MINUIT determines automatically
61 {
62 // m_parameterManager = new MinuitParameterManager( *this );
63  // tell the fitter that this object is the function to evaluate
64  m_fitter.SetFCN( this );
65 
66  setStrategy( m_strategy );
67 }
68 
70 {}
71 
72 double
74 
75  m_parameterManager.update();
76  notify();
77 
78  double totalContribution = 0;
79  MISubject::ObserverList& contributors = observerList();
80  for ( MISubject::ObserverList::iterator iter = contributors.begin();
81  iter != contributors.end();
82  ++iter ) {
83  MIFunctionContribution* contributor = dynamic_cast<MIFunctionContribution*>(*iter);
84 
85  // if the dynamic cast fails, i.e., the MIObserver is
86  // not an MIFunctionContribution then don't ask for
87  // its contribution
88 
89  if( contributor != NULL )
90  totalContribution += contributor->contribution();
91  }
92 
93  ++m_functionCallCounter;
94 
95  return totalContribution;
96 }
97 
98 void
99 MinuitMinimizationManager::computeDerivatives( double* grad )
100 {
101  m_parameterManager.update();
102  notify();
103 
104  int gradIndex = 0;
105  for( MinuitParameterManager::const_iterator par = m_parameterManager.begin();
106  par != m_parameterManager.end();
107  ++par ){
108 
109  double thisDerivative = 0;
110  for ( MISubject::ObserverList::iterator iter = observerList().begin();
111  iter != observerList().end();
112  ++iter ) {
113  MIFunctionContribution* contributor = dynamic_cast<MIFunctionContribution*>(*iter);
114 
115  // if the dynamic cast fails, i.e., the MIObserver is
116  // not an MIFunctionContribution then don't ask for
117  // its contribution
118 
119  if( contributor != NULL )
120  thisDerivative += contributor->derivative( **par );
121  }
122 
123  grad[gradIndex++] = thisDerivative;
124  }
125 }
126 
127 void
129 
130  m_precision = precision;
131 
132  std::ostringstream command;
133  command << "SET EPS " << precision;
134 
135  m_fitter.Command( command.str().c_str() );
136 }
137 
138 double
140 
141  return m_precision;
142 }
143 
144 void
146 
147  m_fitter.SetMaxIterations( maxIter );
148 }
149 
150 int
152 
153  return m_fitter.GetMaxIterations();
154 }
155 
156 void
158 
159  m_strategy = strat;
160 
161  std::ostringstream command;
162  command << "SET STRATEGY " << strat;
163 
164  m_fitter.Command( command.str().c_str() );
165 }
166 
167 int
169 
170  return m_strategy;
171 }
172 
173 void
175 {
176  // set status flag first since subsequent commands
177  // may indireclty rely on it
178  m_derivativesEnabled = true;
179 
180  if( optionArg == kCheckDerivativeCalc ){
181 
182  m_fitter.Command( "SET GRADIENT" );
183  }
184  else{
185 
186  m_fitter.Command( "SET GRADIENT 1" );
187  }
188 }
189 
190 void
192 {
193  // set status flag first since subsequent commands
194  // may indireclty rely on it
195  m_derivativesEnabled = false;
196 
197  m_fitter.Command( "SET NOGRADIENT" );
198 }
199 
200 void
202 
203  m_functionCallCounter = 0;
204 
205  timeval tStart,tStop,tSpan;
206  double dTime;
207 
208  gettimeofday( &(tStart), NULL );
209 
210  int dummyI;
211  double dummyD;
212  m_lastMinuitFlag = -1;
213  m_lastCommand = kMigrad;
214  m_parameterManager.synchronizeMinuit();
215  m_parameterManager.fitInProgress();
216  m_status = m_fitter.Migrad();
217  m_fitter.mnstat( m_bestMin, m_estDistToMin, dummyD, dummyI, dummyI, m_eMatrixStat );
218  // minuit doesn't make a final function call after evaluation of
219  // errors. This ensures that final parameter and function values
220  // correspond to the minimimum found
222  m_parameterManager.noFitInProgress();
223 
224  gettimeofday( &(tStop), NULL );
225  timersub( &(tStop), &(tStart), &tSpan );
226  dTime = tSpan.tv_sec + tSpan.tv_usec/1000000.0; // 10^6 uSec per second
227 
228  cout << "\n MIGRAD evaluation total wall time: " << dTime << " s." << endl;
229  cout << " average time per function call: " << dTime * 1000 / m_functionCallCounter
230  << " ms." << endl << endl;
231 }
232 
233 void
235 
236  m_functionCallCounter = 0;
237 
238  timeval tStart,tStop,tSpan;
239  double dTime;
240 
241  gettimeofday( &(tStart), NULL );
242 
243  int dummyI;
244  double dummyD;
245  m_lastMinuitFlag = -1;
246  m_lastCommand = kMinos;
247  m_parameterManager.synchronizeMinuit();
248  m_parameterManager.fitInProgress();
249  m_status = m_fitter.Minos();
250  m_fitter.mnstat( m_bestMin, m_estDistToMin, dummyD, dummyI, dummyI, m_eMatrixStat );
251  // minuit doesn't make a final function call after evaluation of
252  // errors. This ensures that final parameter and function values
253  // correspond to the minimimum found
255  m_parameterManager.noFitInProgress();
256 
257  gettimeofday( &(tStop), NULL );
258  timersub( &(tStop), &(tStart), &tSpan );
259  dTime = tSpan.tv_sec + tSpan.tv_usec/1000000.0; // 10^6 uSec per second
260 
261  cout << "\n MINOS evaluation total wall time: " << dTime << " s." << endl;
262  cout << " average time per function call: " << dTime * 1000 / m_functionCallCounter
263  << " ms." << endl << endl;
264 
265 }
266 
267 vector< vector< double > >
269 
270  m_functionCallCounter = 0;
271 
272  timeval tStart,tStop,tSpan;
273  double dTime;
274 
275  gettimeofday( &(tStart), NULL );
276 
277  int dummyI;
278  double dummyD;
279  m_lastMinuitFlag = -1;
280  m_lastCommand = kHesse;
281  m_parameterManager.synchronizeMinuit();
282  m_parameterManager.fitInProgress();
283  m_status = m_fitter.Hesse();
284 
285  // copy out the Hessian matrix, which is filled internally,
286  // and return it to the user
287  int nPar = parameterManager().numFloatingPars();
288 
289  vector< vector< double > > secDerivMatrix;
290 
291  // first allocate space for the matrix
292  for( int i = 0; i < nPar; ++i )
293  secDerivMatrix.push_back( vector< double >( nPar ) );
294 
295  // then fill from the stored internal half matrix
296  for( int i = 0; i < nPar; ++i ){
297 
298  for( int j = 0; j <= i; ++j ){
299 
300  int index = i*(i+1)/2 + j;
301  secDerivMatrix[i][j] = m_fitter.fSecDer[index];
302  secDerivMatrix[j][i] = m_fitter.fSecDer[index];
303 
304  }
305  }
306 
307  m_fitter.mnstat( m_bestMin, m_estDistToMin, dummyD, dummyI, dummyI, m_eMatrixStat );
308  // minuit doesn't make a final function call after evaluation of
309  // errors. This ensures that final parameter and function values
310  // correspond to the minimimum found
312  m_parameterManager.noFitInProgress();
313 
314  gettimeofday( &(tStop), NULL );
315  timersub( &(tStop), &(tStart), &tSpan );
316  dTime = tSpan.tv_sec + tSpan.tv_usec/1000000.0; // 10^6 uSec per second
317 
318  cout << "\n HESSE evaluation total wall time: " << dTime << " s." << endl;
319  cout << " average time per function call: " << dTime * 1000 / m_functionCallCounter
320  << " ms." << endl << endl;
321 
322  return secDerivMatrix;
323 }
324 
325 void
326 MinuitMinimizationManager::setLogStream( std::ostream& logStream ) {
327  m_fitter.SetLogStream( logStream );
328 }
329 
330 void
331 MinuitMinimizationManager::operator()( int &npar, double *grad, double &fval, const std::vector<double>& par, int flag) {
332 
333  if ( m_newFlagFunction ) {
334  if ( flag != m_lastMinuitFlag ) {
335  (*m_newFlagFunction)(flag);
336  m_lastMinuitFlag = flag;
337  }
338  }
339 
340  if( flag == kComputeDerivatives ){
341 
342  // fill the grad array with the derivatives
343  computeDerivatives( grad );
344  }
345 
346  fval = evaluateFunction();
347 }
348 
349 int
351 
352  return m_status;
353 }
354 
355 int
357 
358  return m_lastCommand;
359 }
360 
361 int
363 
364  return m_eMatrixStat;
365 }
366 
367 double
369 
370  return m_bestMin;
371 }
372 
373 double
375 
376  return m_estDistToMin;
377 }
378 
379 const vector<double>&
381  return m_fitter.GetParameterList();
382 }
383 
384 URMinuit&
386  return m_fitter;
387 }
const std::vector< double > & minuitWorkingValues() const
void operator()(int &npar, double *grad, double &fval, const std::vector< double > &par, int flag)
Definition: URFcn.h:21
virtual Int_urt Migrad()
Definition: URMinuit.cc:486
void SetLogStream(std::ostream &aStream)
Definition: URMinuit.h:212
Double_urt * fSecDer
Definition: URMinuit.h:96
#define NULL
Definition: URtypes.h:72
Int_urt GetMaxIterations() const
Definition: URMinuit.h:202
virtual double derivative(const MinuitParameter &par)
void notify()
Definition: MISubject.cc:60
std::list< MIObserver * > ObserverList
Definition: MISubject.h:48
virtual Int_urt Minos()
Definition: URMinuit.cc:516
virtual Int_urt Command(const char *command)
Definition: URMinuit.cc:257
void setLogStream(std::ostream &logStream)
virtual Int_urt Hesse()
Definition: URMinuit.cc:501
virtual void mnstat(Double_urt &fmin, Double_urt &fedm, Double_urt &errdef, Int_urt &npari, Int_urt &nparx, Int_urt &istat)
Definition: URMinuit.cc:7648
MinuitMinimizationManager(int maxParameters=50)
MinuitParameterManager & parameterManager()
virtual void SetMaxIterations(Int_urt maxiter=5000)
Definition: URMinuit.h:278
ObserverList & observerList()
Definition: MISubject.h:56
vector< vector< double > > hesseEvaluation()
void enableDerivatives(Option optionArg=kCheckDerivativeCalc)
virtual void SetFCN(URFcn *fcn)
Definition: URMinuit.cc:555
const std::vector< Double_urt > & GetParameterList() const
Definition: URMinuit.h:208