ROOT
master
Reference Guide
Loading...
Searching...
No Matches
TMinuit.cxx
Go to the documentation of this file.
1
// @(#)root/minuit:$Id$
2
// Author: Rene Brun, Frederick James 12/08/95
3
4
/*************************************************************************
5
* Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6
* All rights reserved. *
7
* *
8
* For the licensing terms see $ROOTSYS/LICENSE. *
9
* For the list of contributors see $ROOTSYS/README/CREDITS. *
10
*************************************************************************/
11
12
13
/*! \class TMinuit
14
\note See ROOT::Minuit2 for a newer version of this package
15
\ingroup MinuitOld
16
17
Implementation in C++ of the Minuit package written by Fred James.
18
This is a straightforward conversion of the original Fortran version.
19
20
The main changes are:
21
22
- The variables in the various Minuit labelled common blocks
23
have been changed to the TMinuit class data members.
24
25
- The internal arrays with a maximum dimension depending on the
26
maximum number of parameters are now data members arrays with
27
a dynamic dimension such that one can fit very large problems
28
by simply initialising the TMinuit constructor with the maximum
29
number of parameters.
30
31
- The include file Minuit.h has been commented as much as possible
32
using existing comments in the code or the printed documentation
33
34
- The original Minuit subroutines are now member functions.
35
36
- Constructors and destructor have been added.
37
38
- Instead of passing the FCN function in the argument
39
list, the addresses of this function is stored as pointer
40
in the data members of the class. This is by far more elegant
41
and flexible in an interactive environment.
42
The member function SetFCN can be used to define this pointer.
43
44
- The ROOT static function Printf is provided to replace all
45
format statements and to print on currently defined output file.
46
- The functions SetObjectFit(TObject * obj)/GetObjectFit() can be
47
used inside the FCN function to set/get a referenced object
48
instead of using global variables.
49
50
51
## Basic concepts of MINUIT
52
53
The [MINUIT](https://root.cern/download/minuit.pdf)
54
package acts on a multiparameter Fortran function to which one
55
must give the generic name <TT>FCN</TT>. In the ROOT implementation,
56
the function <TT>FCN</TT> is defined via the MINUIT SetFCN member function
57
when an Histogram.Fit command is invoked.
58
The value of <TT>FCN</TT> will in general depend on one
59
or more variable parameters.
60
61
To take a simple example, in case of ROOT histograms (classes TH1C,TH1S,TH1F,TH1D)
62
the Fit function defines the Minuit fitting function as being H1FitChisquare
63
or H1FitLikelihood depending on the options selected.
64
H1FitChisquare
65
calculates the chisquare between the user fitting function (gaussian, polynomial,
66
user defined,etc) and the data for given values of the parameters.
67
It is the task of MINUIT to find those values of the parameters
68
which give the lowest value of chisquare.
69
70
### Basic concepts - The transformation for parameters with limits.
71
72
For variable parameters with limits, MINUIT uses the following
73
transformation:
74
75
\f[
76
P_{\mathrm{int}} = \arcsin
77
\left( 2\: \frac{P_{\mathrm{ext}}-a}{b-a} - 1 \right)
78
P_{\mathrm{ext}} = a + \frac{b - a}{2} \left( \sin P_{\mathrm{int}} + 1 \right)
79
\f]
80
81
so that the internal value \f$P_{\mathrm{int}}\f$ can take on any value, while
82
the external value \f$P_{\mathrm{ext}}\f$ can take on values only between the lower
83
limit \f$a\f$ and the upper limit \f$b\f$.
84
Since the transformation is necessarily non-linear, it would transform a
85
nice linear problem into a nasty non-linear one, which is the reason why
86
limits should be avoided if not necessary.
87
In addition, the transformation
88
does require some computer time, so it slows down the computation a little
89
bit, and more importantly, it introduces additional numerical inaccuracy into
90
the problem in addition to what is introduced in the numerical calculation
91
of the FCN value.
92
The effects of non-linearity and numerical roundoff both
93
become more important as the external value gets closer to one of the limits
94
(expressed as the distance to nearest limit divided by distance between limits).
95
The user must therefore be aware of the fact that, for example,
96
if he puts limits of \f$(0,10^{10})\f$ on a parameter, then the values \f$0.0\f$
97
and \f$1.0\f$ will be indistinguishable to the accuracy of most machines.
98
99
The transformation also affects the parameter error matrix, of course,
100
so Minuit does a transformation of the error matrix (and the
101
``parabolic'' parameter errors) when there are parameter limits.
102
Users should however realize that the transformation is only a linear
103
approximation, and that it cannot give a meaningful result if one or more
104
parameters is very close to a limit, where
105
\f$\partial P_{\mathrm{ext}} / \partial P_{\mathrm{int}} \approx 0\f$.
106
Therefore, it is recommended that:
107
108
1. Limits on variable parameters should be used only when needed in order
109
to prevent the parameter from taking on unphysical values.
110
111
2. When a satisfactory minimum has been found using limits, the limits
112
should then be removed if possible, in order to perform or re-perform the
113
error analysis without limits.
114
115
116
### How to get the right answer from MINUIT.
117
118
MINUIT offers the user a choice of several minimization algorithms. The
119
MIGRAD algorithm is in general the best minimizer for
120
nearly all functions. It is a variable-metric method with inexact line
121
search, a stable metric updating scheme, and checks for
122
positive-definiteness. Its main weakness is that it depends heavily on
123
knowledge of the first derivatives, and fails miserably if they are very
124
inaccurate.
125
126
If parameter limits are needed, in spite of the side effects, then the
127
user should be aware of the following techniques to alleviate problems
128
caused by limits:
129
130
#### Getting the right minimum with limits.
131
132
If MIGRAD converges normally to a point where no parameter is near one of
133
its limits, then the existence of limits has probably not prevented MINUIT
134
from finding the right minimum. On the other hand, if one or more
135
parameters is near its limit at the minimum, this may be because the true
136
minimum is indeed at a limit, or it may be because the minimizer has
137
become ``blocked'' at a limit. This may normally happen only if the
138
parameter is so close to a limit (internal value at an odd multiple of
139
\f$\pm \frac{\pi}{2}\f$
140
that MINUIT prints a warning to this effect when it prints
141
the parameter values.
142
143
The minimizer can become blocked at a limit, because at a limit
144
the derivative seen by the minimizer
145
\f$\partial F / \partial P_{\mathrm{int}}\f$
146
is zero no matter what the real derivative
147
\f$\partial F / \partial P_{\mathrm{ext}}\f$ is.
148
149
\f[
150
\frac{\partial F}{\partial P_{\mathrm{int}}} =
151
\frac{\partial F}{\partial P_{\mathrm{ext}}}
152
\frac{\partial P_{\mathrm{ext}}}{\partial P_{\mathrm{int}}} =
153
\frac{\partial F}{\partial P_{\mathrm{ext}}} = 0
154
\f]
155
156
#### Getting the right parameter errors with limits.
157
158
In the best case, where the minimum is far from any limits, MINUIT will
159
correctly transform the error matrix, and the parameter errors it reports
160
should be accurate and very close to those you would have got without
161
limits. In other cases (which should be more common, since otherwise you
162
wouldn't need limits), the very meaning of parameter errors becomes
163
problematic. Mathematically, since the limit is an absolute constraint on
164
the parameter, a parameter at its limit has no error, at least in one
165
direction. The error matrix, which can assign only symmetric errors, then
166
becomes essentially meaningless.
167
168
### Interpretation of Parameter Errors:
169
170
There are two kinds of problems that can arise: the reliability of
171
MINUIT's error estimates, and their statistical interpretation, assuming
172
they are accurate.
173
174
### Statistical interpretation:
175
176
For discussion of basic concepts, such as the meaning of the elements of
177
the error matrix, or setting of exact confidence levels see:
178
179
1. F.James.
180
Determining the statistical Significance of experimental Results.
181
Technical Report DD/81/02 and CERN Report 81-03, CERN, 1981.
182
183
2. W.T.Eadie, D.Drijard, F.James, M.Roos, and B.Sadoulet.
184
Statistical Methods in Experimental Physics.
185
North-Holland, 1971.
186
187
### Reliability of MINUIT error estimates.
188
189
MINUIT always carries around its own current estimates of the parameter
190
errors, which it will print out on request, no matter how accurate they
191
are at any given point in the execution. For example, at initialization,
192
these estimates are just the starting step sizes as specified by the user.
193
After a HESSE step, the errors are usually quite accurate,
194
unless there has been a problem. MINUIT, when it prints out error values,
195
also gives some indication of how reliable it thinks they are. For
196
example, those marked <TT>CURRENT GUESS ERROR</TT> are only working values
197
not to be believed, and <TT>APPROXIMATE ERROR</TT> means that they have
198
been calculated but there is reason to believe that they may not be
199
accurate.
200
201
If no mitigating adjective is given, then at least MINUIT believes the
202
errors are accurate, although there is always a small chance that MINUIT
203
has been fooled. Some visible signs that MINUIT may have been fooled are:
204
205
206
1. Warning messages produced during the minimization or error analysis.
207
208
2. Failure to find new minimum.
209
210
3. Value of <TT>EDM</TT> too big (estimated Distance to Minimum).
211
212
4. Correlation coefficients exactly equal to zero, unless some parameters
213
are known to be uncorrelated with the others.
214
215
5. Correlation coefficients very close to one (greater than 0.99). This
216
indicates both an exceptionally difficult problem, and one which has been
217
badly parameterised so that individual errors are not very meaningful
218
because they are so highly correlated.
219
220
6. Parameter at limit. This condition, signalled by a MINUIT warning
221
message, may make both the function minimum and parameter errors
222
unreliable. See the discussion above ``Getting the right parameter errors
223
with limits''.
224
225
226
The best way to be absolutely sure of the errors, is to use
227
``independent'' calculations and compare them, or compare the calculated
228
errors with a picture of the function. Theoretically, the covariance
229
matrix for a ``physical'' function must be positive-definite at the
230
minimum, although it may not be so for all points far away from the
231
minimum, even for a well-determined physical problem. Therefore, if MIGRAD
232
reports that it has found a non-positive-definite covariance matrix, this
233
may be a sign of one or more of the following:
234
235
##### A non-physical region:
236
237
On its way to the minimum, MIGRAD may have traversed a region which has
238
unphysical behaviour, which is of course not a serious problem as long as
239
it recovers and leaves such a region.
240
241
##### An underdetermined problem:
242
243
If the matrix is not positive-definite even at the minimum, this may mean
244
that the solution is not well-defined, for example that there are more
245
unknowns than there are data points, or that the parameterisation of the
246
fit contains a linear dependence. If this is the case, then MINUIT (or any
247
other program) cannot solve your problem uniquely, and the error matrix
248
will necessarily be largely meaningless, so the user must remove the
249
under-determinedness by reformulating the parameterisation. MINUIT cannot
250
do this itself.
251
252
##### Numerical inaccuracies:
253
254
It is possible that the apparent lack of positive-definiteness is in fact
255
only due to excessive roundoff errors in numerical calculations in the
256
user function or not enough precision. This is unlikely in general, but
257
becomes more likely if the number of free parameters is very large, or if
258
259
the parameters are badly scaled (not all of the same order of magnitude),
260
and correlations are also large. In any case, whether the
261
non-positive-definiteness is real or only numerical is largely irrelevant,
262
since in both cases the error matrix will be unreliable and the minimum
263
suspicious.
264
265
##### An ill-posed problem:
266
267
For questions of parameter dependence, see the discussion above on
268
positive-definiteness.
269
270
Possible other mathematical problems are the following:
271
272
##### Excessive numerical roundoff:
273
274
Be especially careful of exponential and factorial functions which get big
275
very quickly and lose accuracy.
276
277
##### Starting too far from the solution:
278
279
The function may have unphysical local minima, especially at infinity in
280
some variables.
281
282
##### Minuit parameter errors in the presence of limits
283
This concerns the way Minuit reports the symmetric (or parabolic) errors
284
on parameters. It does not apply to the errors reported from Minos, which
285
are in general asymmetric.
286
287
The symmetric errors reported by Minuit are always calculated from
288
the covariance matrix, assuming that this matrix has been calculated,
289
usually as the result of a Migrad minimization or a direct
290
calculation by Hesse which inverts the second derivative matrix.
291
292
When there are no limits on the parameter in question, the error reported
293
by Minuit should therefore be exactly equal to the square root of the
294
corresponding diagonal element of the error matrix reported by Minuit.
295
296
However, when there are limits on the parameter, there is a transformation
297
between the internal parameter values seen by Minuit (which are unbounded)
298
and the external parameter values seen by the user in FCN (which remain
299
inside the desired limits). Therefore the internal error matrix kept by
300
Minuit must be transformed to an external error matrix for the user.
301
This is done by multiplying the (I,J)th element by DEXDIN(I)*DEXDIN(J),
302
where DEXDIN is the derivative of the external value with respect to the
303
internal value at the minimum. This is a linearisation of the
304
transformation, and is the only way to produce an error matrix in external
305
coordinates meaningful to the user. But when reporting the individual
306
parabolic errors for limited parameters, Minuit can do a little better, so
307
it does. In this case, Minuit actually transforms the ends of the
308
internal "error bar" to external coordinates and reports the length of
309
this transformed interval. Strictly speaking, it is now asymmetric, but
310
since the origin of the asymmetry is only an artificial transformation it
311
does not make much sense, so the transformed errors are symmetrized.
312
313
The result of all the above is that for parameters with limits, the error
314
reported by Minuit is not exactly equal to the square root of the diagonal
315
element of the error matrix. The difference is a measure of how much the
316
limits deform the problem. If possible, it is suggested not to use limits
317
on parameters, and the problem goes away. If for some reason limits are
318
necessary, and you are sensitive to the difference between the two ways of
319
calculating the errors, it is suggested to use Minos errors which take
320
into account the non-linearities much more precisely.
321
322
*/
323
324
#include <cstdlib>
325
#include <cstdio>
326
327
#include "
TROOT.h
"
328
#include "
TList.h
"
329
#include "
TMinuit.h
"
330
#include "
TMath.h
"
331
#include "
TError.h
"
332
#include "
TPluginManager.h
"
333
#include "
TClass.h
"
334
335
#include <atomic>
336
337
TMinuit
*
gMinuit
;
338
339
static
const
char
charal
[29] =
" .ABCDEFGHIJKLMNOPQRSTUVWXYZ"
;
340
341
342
////////////////////////////////////////////////////////////////////////////////
343
/// Minuit normal constructor
344
///
345
346
TMinuit::TMinuit
():
TNamed
(
"MINUIT"
,
"The Minimization package"
)
347
{
348
if
(
TMinuit::Class
()->IsCallingNew() !=
TClass::kRealNew
) {
349
//preset all pointers to null
350
fCpnam
=
nullptr
;
351
fU
=
nullptr
;
352
fAlim
=
nullptr
;
353
fBlim
=
nullptr
;
354
fPstar
=
nullptr
;
355
fGin
=
nullptr
;
356
fNvarl
=
nullptr
;
357
fNiofex
=
nullptr
;
358
359
fNexofi
=
nullptr
;
360
fIpfix
=
nullptr
;
361
fErp
=
nullptr
;
362
fErn
=
nullptr
;
363
fWerr
=
nullptr
;
364
fGlobcc
=
nullptr
;
365
fX
=
nullptr
;
366
fXt
=
nullptr
;
367
fDirin
=
nullptr
;
368
fXs
=
nullptr
;
369
fXts
=
nullptr
;
370
fDirins
=
nullptr
;
371
fGrd
=
nullptr
;
372
fG2
=
nullptr
;
373
fGstep
=
nullptr
;
374
fDgrd
=
nullptr
;
375
fGrds
=
nullptr
;
376
fG2s
=
nullptr
;
377
fGsteps
=
nullptr
;
378
fPstst
=
nullptr
;
379
fPbar
=
nullptr
;
380
fPrho
=
nullptr
;
381
fWord7
=
nullptr
;
382
fVhmat
=
nullptr
;
383
fVthmat
=
nullptr
;
384
fP
=
nullptr
;
385
fXpt
=
nullptr
;
386
fYpt
=
nullptr
;
387
fChpt
=
nullptr
;
388
fCONTgcc
=
nullptr
;
389
fCONTw
=
nullptr
;
390
fFIXPyy
=
nullptr
;
391
fGRADgf
=
nullptr
;
392
fHESSyy
=
nullptr
;
393
fIMPRdsav
=
nullptr
;
394
fIMPRy
=
nullptr
;
395
fMATUvline
=
nullptr
;
396
fMIGRflnu
=
nullptr
;
397
fMIGRstep
=
nullptr
;
398
fMIGRgs
=
nullptr
;
399
fMIGRvg
=
nullptr
;
400
fMIGRxxs
=
nullptr
;
401
fMNOTxdev
=
nullptr
;
402
fMNOTw
=
nullptr
;
403
fMNOTgcc
=
nullptr
;
404
fPSDFs
=
nullptr
;
405
fSEEKxmid
=
nullptr
;
406
fSEEKxbest
=
nullptr
;
407
fSIMPy
=
nullptr
;
408
fVERTq
=
nullptr
;
409
fVERTs
=
nullptr
;
410
fVERTpp
=
nullptr
;
411
fCOMDplist
=
nullptr
;
412
fPARSplist
=
nullptr
;
413
414
fUp
= 0;
415
fEpsi
= 0;
416
fApsi
= 0;
417
fXmidcr
= 0;
418
fYmidcr
= 0;
419
fXdircr
= 0;
420
fYdircr
= 0;
421
422
fStatus
= 0;
423
fEmpty
= 0;
424
fObjectFit
=
nullptr
;
425
fMethodCall
=
nullptr
;
426
fPlot
=
nullptr
;
427
fGraphicsMode
=
kTRUE
;
428
429
}
else
{
430
BuildArrays
(25);
431
432
fUp
= 0;
433
fEpsi
= 0;
434
fApsi
= 0;
435
fXmidcr
= 0;
436
fYmidcr
= 0;
437
fXdircr
= 0;
438
fYdircr
= 0;
439
440
fStatus
= 0;
441
fEmpty
= 0;
442
fObjectFit
=
nullptr
;
443
fMethodCall
=
nullptr
;
444
fPlot
=
nullptr
;
445
fGraphicsMode
=
kTRUE
;
446
SetMaxIterations
();
447
mninit
(5,6,7);
448
}
449
450
fFCN
=
nullptr
;
451
{
452
R__LOCKGUARD
(
gROOTMutex
);
453
gROOT
->GetListOfSpecials()->Add(
this
);
454
}
455
gMinuit
=
this
;
456
}
457
458
////////////////////////////////////////////////////////////////////////////////
459
/// Minuit normal constructor
460
///
461
/// maxpar is the maximum number of parameters used with this TMinuit object.
462
463
TMinuit::TMinuit
(
Int_t
maxpar
):
TNamed
(
"MINUIT"
,
"The Minimization package"
)
464
{
465
fFCN
=
nullptr
;
466
467
BuildArrays
(
maxpar
);
468
469
fStatus
= 0;
470
fEmpty
= 0;
471
fObjectFit
=
nullptr
;
472
fMethodCall
=
nullptr
;
473
fPlot
=
nullptr
;
474
fGraphicsMode
=
kTRUE
;
475
SetMaxIterations
();
476
477
mninit
(5,6,7);
478
{
479
R__LOCKGUARD
(
gROOTMutex
);
480
gROOT
->GetListOfSpecials()->Add(
this
);
481
}
482
gMinuit
=
this
;
483
}
484
485
////////////////////////////////////////////////////////////////////////////////
486
/// Private TMinuit copy ctor. TMinuit can not be copied.
487
488
TMinuit::TMinuit
(
const
TMinuit
&
minuit
) :
TNamed
(
minuit
)
489
{
490
Error
(
"TMinuit"
,
"can not copy construct TMinuit"
);
491
}
492
493
////////////////////////////////////////////////////////////////////////////////
494
/// Minuit default destructor
495
496
TMinuit::~TMinuit
()
497
{
498
DeleteArrays
();
499
delete
fPlot
;
500
delete
fMethodCall
;
501
{
502
R__LOCKGUARD
(
gROOTMutex
);
503
if
(
gROOT
!=
nullptr
&&
gROOT
->GetListOfSpecials() !=
nullptr
)
gROOT
->GetListOfSpecials()->Remove(
this
);
504
}
505
if
(
gMinuit
==
this
)
gMinuit
=
nullptr
;
506
}
507
508
////////////////////////////////////////////////////////////////////////////////
509
/// Create internal Minuit arrays for the maxpar parameters
510
511
void
TMinuit::BuildArrays
(
Int_t
maxpar
)
512
{
513
fMaxpar
= 25;
514
if
(
maxpar
>=
fMaxpar
)
fMaxpar
=
maxpar
+1;
515
fMaxpar1
=
fMaxpar
*(
fMaxpar
+1);
516
fMaxpar2
= 2*
fMaxpar
;
517
fMaxpar5
=
fMaxpar1
/2;
518
fMaxcpt
= 101;
519
fCpnam
=
new
TString
[
fMaxpar2
];
520
fU
=
new
Double_t
[
fMaxpar2
];
521
fAlim
=
new
Double_t
[
fMaxpar2
];
522
fBlim
=
new
Double_t
[
fMaxpar2
];
523
fPstar
=
new
Double_t
[
fMaxpar2
];
524
fGin
=
new
Double_t
[
fMaxpar2
];
525
fNvarl
=
new
Int_t
[
fMaxpar2
];
526
fNiofex
=
new
Int_t
[
fMaxpar2
];
527
528
fNexofi
=
new
Int_t
[
fMaxpar
];
529
fIpfix
=
new
Int_t
[
fMaxpar
];
530
fErp
=
new
Double_t
[
fMaxpar
];
531
fErn
=
new
Double_t
[
fMaxpar
];
532
fWerr
=
new
Double_t
[
fMaxpar
];
533
fGlobcc
=
new
Double_t
[
fMaxpar
];
534
fX
=
new
Double_t
[
fMaxpar
];
535
fXt
=
new
Double_t
[
fMaxpar
];
536
fDirin
=
new
Double_t
[
fMaxpar
];
537
fXs
=
new
Double_t
[
fMaxpar
];
538
fXts
=
new
Double_t
[
fMaxpar
];
539
fDirins
=
new
Double_t
[
fMaxpar
];
540
fGrd
=
new
Double_t
[
fMaxpar
];
541
fG2
=
new
Double_t
[
fMaxpar
];
542
fGstep
=
new
Double_t
[
fMaxpar
];
543
fDgrd
=
new
Double_t
[
fMaxpar
];
544
fGrds
=
new
Double_t
[
fMaxpar
];
545
fG2s
=
new
Double_t
[
fMaxpar
];
546
fGsteps
=
new
Double_t
[
fMaxpar
];
547
fPstst
=
new
Double_t
[
fMaxpar
];
548
fPbar
=
new
Double_t
[
fMaxpar
];
549
fPrho
=
new
Double_t
[
fMaxpar
];
550
fWord7
=
new
Double_t
[
fMaxpar
];
551
fVhmat
=
new
Double_t
[
fMaxpar5
];
552
fVthmat
=
new
Double_t
[
fMaxpar5
];
553
fP
=
new
Double_t
[
fMaxpar1
];
554
fXpt
=
new
Double_t
[
fMaxcpt
];
555
fYpt
=
new
Double_t
[
fMaxcpt
];
556
fChpt
=
new
char
[
fMaxcpt
+1];
557
// initialisation of dynamic arrays used internally in some functions
558
// these arrays had a fix dimension in Minuit
559
fCONTgcc
=
new
Double_t
[
fMaxpar
];
560
fCONTw
=
new
Double_t
[
fMaxpar
];
561
fFIXPyy
=
new
Double_t
[
fMaxpar
];
562
fGRADgf
=
new
Double_t
[
fMaxpar
];
563
fHESSyy
=
new
Double_t
[
fMaxpar
];
564
fIMPRdsav
=
new
Double_t
[
fMaxpar
];
565
fIMPRy
=
new
Double_t
[
fMaxpar
];
566
fMATUvline
=
new
Double_t
[
fMaxpar
];
567
fMIGRflnu
=
new
Double_t
[
fMaxpar
];
568
fMIGRstep
=
new
Double_t
[
fMaxpar
];
569
fMIGRgs
=
new
Double_t
[
fMaxpar
];
570
fMIGRvg
=
new
Double_t
[
fMaxpar
];
571
fMIGRxxs
=
new
Double_t
[
fMaxpar
];
572
fMNOTxdev
=
new
Double_t
[
fMaxpar
];
573
fMNOTw
=
new
Double_t
[
fMaxpar
];
574
fMNOTgcc
=
new
Double_t
[
fMaxpar
];
575
fPSDFs
=
new
Double_t
[
fMaxpar
];
576
fSEEKxmid
=
new
Double_t
[
fMaxpar
];
577
fSEEKxbest
=
new
Double_t
[
fMaxpar
];
578
fSIMPy
=
new
Double_t
[
fMaxpar
];
579
fVERTq
=
new
Double_t
[
fMaxpar
];
580
fVERTs
=
new
Double_t
[
fMaxpar
];
581
fVERTpp
=
new
Double_t
[
fMaxpar
];
582
fCOMDplist
=
new
Double_t
[
fMaxpar
];
583
fPARSplist
=
new
Double_t
[
fMaxpar
];
584
585
for
(
int
i = 0; i <
fMaxpar
; i++) {
586
fErp
[i] = 0;
587
fErn
[i] = 0;
588
}
589
}
590
591
////////////////////////////////////////////////////////////////////////////////
592
/// Make a clone of an object using the Streamer facility.
593
/// Function pointer is copied to Clone
594
595
TObject
*
TMinuit::Clone
(
const
char
*
newname
)
const
596
{
597
TMinuit
*
named
= (
TMinuit
*)
TNamed::Clone
(
newname
);
598
named
->fFCN=
fFCN
;
599
return
named
;
600
}
601
602
////////////////////////////////////////////////////////////////////////////////
603
/// Execute a Minuit command
604
///
605
/// Equivalent to MNEXCM except that the command is given as a character string.
606
/// See TMinuit::mnhelp for the full list of available commands
607
/// See also the
608
/// [complete documentation of all the available commands](https://root.cern/sites/d35c7d8c.web.cern.ch/files/minuit.pdf)
609
///
610
/// Returns the status of the execution:
611
/// - 0: command executed normally
612
/// - 1: command is blank, ignored
613
/// - 2: command line unreadable, ignored
614
/// - 3: unknown command, ignored
615
/// - 4: abnormal termination (e.g., MIGRAD not converged)
616
/// - 5: command is a request to read PARAMETER definitions
617
/// - 6: 'SET INPUT' command
618
/// - 7: 'SET TITLE' command
619
/// - 8: 'SET COVAR' command
620
/// - 9: reserved
621
/// - 10: END command
622
/// - 11: EXIT or STOP command
623
/// - 12: RETURN command
624
625
Int_t
TMinuit::Command
(
const
char
*
command
)
626
{
627
Int_t
status = 0;
628
mncomd
(
command
,status);
629
return
status;
630
}
631
632
////////////////////////////////////////////////////////////////////////////////
633
/// Creates a TGraph object describing the n-sigma contour of a
634
/// TMinuit fit. The contour of the parameters pa1 and pa2 is calculated
635
/// using npoints (>=4) points. The TMinuit status will be
636
/// - 0 on success and
637
/// - -1 if errors in the calling sequence (pa1, pa2 not variable)
638
/// - 1 if less than four points can be found
639
/// - 2 if npoints<4
640
/// - n>3 if only n points can be found (n < npoints)
641
/// The status can be obtained via TMinuit::GetStatus().
642
///
643
/// To get the n-sigma contour the ERRDEF parameter in Minuit has to set
644
/// to n^2. The fcn function has to be set before the routine is called.
645
///
646
/// The TGraph object is created via the interpreter. The user must cast it
647
/// to a TGraph*. Note that the TGraph is created with npoints+1 in order to
648
/// close the contour (setting last point equal to first point).
649
///
650
/// You can find an example in fitcont.C
651
652
TObject
*
TMinuit::Contour
(
Int_t
npoints
,
Int_t
pa1
,
Int_t
pa2
)
653
{
654
if
(
npoints
<4) {
655
// we need at least 4 points
656
fStatus
= 2;
657
return
(
TObject
*)
nullptr
;
658
}
659
Int_t
npfound
;
660
Double_t
*
xcoor
=
new
Double_t
[
npoints
+1];
661
Double_t
*
ycoor
=
new
Double_t
[
npoints
+1];
662
mncont
(
pa1
,
pa2
,
npoints
,
xcoor
,
ycoor
,
npfound
);
663
if
(
npfound
<4) {
664
// mncont did go wrong
665
Warning
(
"Contour"
,
"Cannot find more than 4 points, no TGraph returned"
);
666
fStatus
= (
npfound
==0 ? 1 :
npfound
);
667
delete
[]
xcoor
;
668
delete
[]
ycoor
;
669
return
(
TObject
*)
nullptr
;
670
}
671
if
(
npfound
!=
npoints
) {
672
// mncont did go wrong
673
Warning
(
"Contour"
,
"Returning a TGraph with %d points only"
,
npfound
);
674
npoints
=
npfound
;
675
}
676
fStatus
=0;
677
// create graph via the PluginManager
678
xcoor
[
npoints
] =
xcoor
[0];
// add first point at end to get closed polyline
679
ycoor
[
npoints
] =
ycoor
[0];
680
TObject
*
gr
=
nullptr
;
681
TPluginHandler
*
h
;
682
if
((
h
=
gROOT
->GetPluginManager()->FindHandler(
"TMinuitGraph"
))) {
683
if
(
h
->LoadPlugin() != -1)
684
gr
= (
TObject
*)
h
->ExecPlugin(3,
npoints
+1,
xcoor
,
ycoor
);
685
}
686
delete
[]
xcoor
;
687
delete
[]
ycoor
;
688
return
gr
;
689
}
690
691
////////////////////////////////////////////////////////////////////////////////
692
/// Define a parameter
693
694
Int_t
TMinuit::DefineParameter
(
Int_t
parNo
,
const
char
*
name
,
Double_t
initVal
,
Double_t
initErr
,
Double_t
lowerLimit
,
Double_t
upperLimit
)
695
{
696
Int_t
err;
697
698
TString
sname
=
name
;
699
mnparm
(
parNo
,
sname
,
initVal
,
initErr
,
lowerLimit
,
upperLimit
, err);
700
701
return
err;
702
}
703
704
////////////////////////////////////////////////////////////////////////////////
705
/// Delete internal Minuit arrays
706
707
void
TMinuit::DeleteArrays
()
708
{
709
if
(
fEmpty
)
return
;
710
delete
[]
fCpnam
;
711
delete
[]
fU
;
712
delete
[]
fAlim
;
713
delete
[]
fBlim
;
714
delete
[]
fErp
;
715
delete
[]
fErn
;
716
delete
[]
fWerr
;
717
delete
[]
fGlobcc
;
718
delete
[]
fNvarl
;
719
delete
[]
fNiofex
;
720
delete
[]
fNexofi
;
721
delete
[]
fX
;
722
delete
[]
fXt
;
723
delete
[]
fDirin
;
724
delete
[]
fXs
;
725
delete
[]
fXts
;
726
delete
[]
fDirins
;
727
delete
[]
fGrd
;
728
delete
[]
fG2
;
729
delete
[]
fGstep
;
730
delete
[]
fGin
;
731
delete
[]
fDgrd
;
732
delete
[]
fGrds
;
733
delete
[]
fG2s
;
734
delete
[]
fGsteps
;
735
delete
[]
fIpfix
;
736
delete
[]
fVhmat
;
737
delete
[]
fVthmat
;
738
delete
[]
fP
;
739
delete
[]
fPstar
;
740
delete
[]
fPstst
;
741
delete
[]
fPbar
;
742
delete
[]
fPrho
;
743
delete
[]
fWord7
;
744
delete
[]
fXpt
;
745
delete
[]
fYpt
;
746
delete
[]
fChpt
;
747
748
delete
[]
fCONTgcc
;
749
delete
[]
fCONTw
;
750
delete
[]
fFIXPyy
;
751
delete
[]
fGRADgf
;
752
delete
[]
fHESSyy
;
753
delete
[]
fIMPRdsav
;
754
delete
[]
fIMPRy
;
755
delete
[]
fMATUvline
;
756
delete
[]
fMIGRflnu
;
757
delete
[]
fMIGRstep
;
758
delete
[]
fMIGRgs
;
759
delete
[]
fMIGRvg
;
760
delete
[]
fMIGRxxs
;
761
delete
[]
fMNOTxdev
;
762
delete
[]
fMNOTw
;
763
delete
[]
fMNOTgcc
;
764
delete
[]
fPSDFs
;
765
delete
[]
fSEEKxmid
;
766
delete
[]
fSEEKxbest
;
767
delete
[]
fSIMPy
;
768
delete
[]
fVERTq
;
769
delete
[]
fVERTs
;
770
delete
[]
fVERTpp
;
771
delete
[]
fCOMDplist
;
772
delete
[]
fPARSplist
;
773
774
fEmpty
= 1;
775
}
776
777
////////////////////////////////////////////////////////////////////////////////
778
/// Evaluate the minimisation function
779
/// Input parameters:
780
/// - npar: number of currently variable parameters
781
/// - par: array of (constant and variable) parameters
782
/// - flag: Indicates what is to be calculated (see example below)
783
/// - grad: array of gradients
784
/// Output parameters:
785
/// - fval: The calculated function value.
786
/// - grad: The (optional) vector of first derivatives).
787
///
788
/// The meaning of the parameters par is of course defined by the user,
789
/// who uses the values of those parameters to calculate their function value.
790
/// The starting values must be specified by the user.
791
/// Later values are determined by Minuit as it searches for the minimum
792
/// or performs whatever analysis is requested by the user.
793
///
794
/// Note that this virtual function may be redefined in a class derived from TMinuit.
795
/// The default function calls the function specified in SetFCN
796
///
797
/// Example of Minimisation function:
798
799
Int_t
TMinuit::Eval
(
Int_t
npar
,
Double_t
*grad,
Double_t
&
fval
,
Double_t
*par,
Int_t
flag
)
800
{
801
/*
802
if (flag == 1) {
803
read input data,
804
calculate any necessary constants, etc.
805
}
806
if (flag == 2) {
807
calculate GRAD, the first derivatives of FVAL
808
(this is optional)
809
}
810
Always calculate the value of the function, FVAL,
811
which is usually a chisquare or log likelihood.
812
if (iflag == 3) {
813
will come here only after the fit is finished.
814
Perform any final calculations, output fitted data, etc.
815
}
816
*/
817
// See concrete examples in TH1::H1FitChisquare, H1FitLikelihood
818
819
if
(
fFCN
) (*fFCN)(
npar
,grad,
fval
,par,
flag
);
820
return
0;
821
}
822
823
////////////////////////////////////////////////////////////////////////////////
824
/// fix a parameter
825
826
Int_t
TMinuit::FixParameter
(
Int_t
parNo
)
827
{
828
Int_t
err;
829
Double_t
tmp
[1];
830
tmp
[0] =
parNo
+1;
//set internal Minuit numbering
831
832
mnexcm
(
"FIX"
,
tmp
, 1, err );
833
834
return
err;
835
}
836
837
////////////////////////////////////////////////////////////////////////////////
838
/// return parameter value and error
839
840
Int_t
TMinuit::GetParameter
(
Int_t
parNo
,
Double_t
&
currentValue
,
Double_t
&
currentError
)
const
841
{
842
Int_t
err;
843
TString
name
;
// ignored
844
Double_t
bnd1
,
bnd2
;
// ignored
845
846
mnpout
(
parNo
,
name
,
currentValue
,
currentError
,
bnd1
,
bnd2
, err );
847
848
return
err;
849
}
850
851
////////////////////////////////////////////////////////////////////////////////
852
/// returns the number of currently fixed parameters
853
854
Int_t
TMinuit::GetNumFixedPars
()
const
855
{
856
return
fNpfix
;
857
}
858
859
////////////////////////////////////////////////////////////////////////////////
860
/// returns the number of currently free parameters
861
862
Int_t
TMinuit::GetNumFreePars
()
const
863
{
864
return
fNpar
;
865
}
866
867
////////////////////////////////////////////////////////////////////////////////
868
/// returns the total number of parameters that have been defined
869
/// as fixed or free. The constant parameters are not counted.
870
871
Int_t
TMinuit::GetNumPars
()
const
872
{
873
return
fNpar
+
fNpfix
;
874
}
875
876
////////////////////////////////////////////////////////////////////////////////
877
/// invokes the MIGRAD minimizer
878
879
Int_t
TMinuit::Migrad
()
880
{
881
Int_t
err;
882
Double_t
tmp
[1];
883
tmp
[0] = 0;
884
885
mnexcm
(
"MIGRAD"
,
tmp
, 0, err );
886
887
return
err;
888
}
889
890
////////////////////////////////////////////////////////////////////////////////
891
/// release a parameter
892
893
Int_t
TMinuit::Release
(
Int_t
parNo
)
894
{
895
Int_t
err;
896
Double_t
tmp
[1];
897
tmp
[0] =
parNo
+1;
//set internal Minuit numbering
898
899
mnexcm
(
"RELEASE"
,
tmp
, 1, err );
900
901
return
err;
902
}
903
904
////////////////////////////////////////////////////////////////////////////////
905
/// To get the n-sigma contour the error def parameter "up" has to set to n^2.
906
907
Int_t
TMinuit::SetErrorDef
(
Double_t
up
)
908
{
909
Int_t
err;
910
911
mnexcm
(
"SET ERRDEF"
, &
up
, 1, err );
912
913
return
err;
914
}
915
916
////////////////////////////////////////////////////////////////////////////////
917
/// To set the address of the minimization function
918
919
void
TMinuit::SetFCN
(
void
(*
fcn
)(
Int_t
&,
Double_t
*,
Double_t
&
f
,
Double_t
*,
Int_t
))
920
{
921
fFCN
=
fcn
;
922
}
923
924
////////////////////////////////////////////////////////////////////////////////
925
/// Static function called when SetFCN is called in interactive mode
926
927
void
InteractiveFCNm
(
Int_t
&
npar
,
Double_t
*
gin
,
Double_t
&
f
,
Double_t
*
u
,
Int_t
flag
)
928
{
929
TMethodCall
*
m
=
gMinuit
->
GetMethodCall
();
930
if
(!
m
)
return
;
931
932
Longptr_t
args[5];
933
args[0] = (
Longptr_t
)&
npar
;
934
args[1] = (
Longptr_t
)
gin
;
935
args[2] = (
Longptr_t
)&
f
;
936
args[3] = (
Longptr_t
)
u
;
937
args[4] = (
Longptr_t
)
flag
;
938
m
->SetParamPtrs(args);
939
Double_t
result
;
940
m
->
Execute
(
result
);
941
}
942
943
////////////////////////////////////////////////////////////////////////////////
944
/// set Minuit print level.
945
///
946
/// printlevel:
947
/// - = -1 quiet (also suppress all warnings)
948
/// - = 0 normal
949
/// - = 1 verbose
950
951
Int_t
TMinuit::SetPrintLevel
(
Int_t
printLevel
)
952
{
953
Int_t
err;
954
Double_t
tmp
[1];
955
tmp
[0] =
printLevel
;
956
957
mnexcm
(
"SET PRINT"
,
tmp
, 1, err );
958
959
if
(
printLevel
<=-1)
mnexcm
(
"SET NOWarnings"
,
tmp
,0,err);
960
961
return
err;
962
}
963
964
////////////////////////////////////////////////////////////////////////////////
965
/// Initialize AMIN
966
///
967
/// Called from many places. Initializes the value of AMIN by
968
/// calling the user function. Prints out the function value and
969
/// parameter values if Print Flag value is high enough.
970
971
void
TMinuit::mnamin
()
972
{
973
/* Local variables */
974
Double_t
fnew
;
975
Int_t
nparx
;
976
977
nparx
=
fNpar
;
978
if
(
fISW
[4] >= 1) {
979
Printf
(
" FIRST CALL TO USER FUNCTION AT NEW START POINT, WITH IFLAG=4."
);
980
}
981
mnexin
(
fX
);
982
Eval
(
nparx
,
fGin
,
fnew
,
fU
, 4); ++
fNfcn
;
983
fAmin
=
fnew
;
984
fEDM
=
fBigedm
;
985
}
986
987
////////////////////////////////////////////////////////////////////////////////
988
/// Compute reasonable histogram intervals
989
///
990
/// Function TO DETERMINE REASONABLE HISTOGRAM INTERVALS
991
/// GIVEN ABSOLUTE UPPER AND LOWER BOUNDS A1 AND A2
992
/// AND DESIRED MAXIMUM NUMBER OF BINS NAA
993
/// PROGRAM MAKES REASONABLE BINNING FROM BL TO BH OF WIDTH BWID
994
/// F. JAMES, AUGUST, 1974 , stolen for Minuit, 1988
995
996
void
TMinuit::mnbins
(
Double_t
a1
,
Double_t
a2
,
Int_t
naa
,
Double_t
&
bl
,
Double_t
&
bh
,
Int_t
&
nb
,
Double_t
&
bwid
)
997
{
998
/* Local variables */
999
Double_t
awid
,
ah
,
al
,
sigfig
,
sigrnd
,
alb
;
1000
Int_t
kwid
,
lwid
,
na
=0,
log_
;
1001
1002
al
=
TMath::Min
(
a1
,
a2
);
1003
ah
=
TMath::Max
(
a1
,
a2
);
1004
if
(
al
==
ah
)
ah
=
al
+ 1;
1005
1006
// IF NAA .EQ. -1 , PROGRAM USES BWID INPUT FROM CALLING ROUTINE
1007
if
(
naa
== -1)
goto
L150
;
1008
L10
:
1009
na
=
naa
- 1;
1010
if
(
na
< 1)
na
= 1;
1011
1012
// GET NOMINAL BIN WIDTH IN EXPON FORM
1013
L20
:
1014
awid
= (
ah
-
al
) /
Double_t
(
na
);
1015
log_
=
Int_t
(
TMath::Log10
(
awid
));
1016
if
(
awid
<= 1) --
log_
;
1017
sigfig
=
awid
*
TMath::Power
(10, -
log_
);
1018
// ROUND MANTISSA UP TO 2, 2.5, 5, OR 10
1019
if
(
sigfig
> 2)
goto
L40
;
1020
sigrnd
= 2;
1021
goto
L100
;
1022
L40
:
1023
if
(
sigfig
> 2.5)
goto
L50
;
1024
sigrnd
= 2.5;
1025
goto
L100
;
1026
L50
:
1027
if
(
sigfig
> 5)
goto
L60
;
1028
sigrnd
= 5;
1029
goto
L100
;
1030
L60
:
1031
sigrnd
= 1;
1032
++
log_
;
1033
L100
:
1034
bwid
=
sigrnd
*
TMath::Power
(10,
log_
);
1035
goto
L200
;
1036
// GET NEW BOUNDS FROM NEW WIDTH BWID
1037
L150
:
1038
if
(
bwid
<= 0)
goto
L10
;
1039
L200
:
1040
alb
=
al
/
bwid
;
1041
lwid
=
Int_t
(
alb
);
1042
if
(
alb
< 0) --
lwid
;
1043
bl
=
bwid
*
Double_t
(
lwid
);
1044
alb
=
ah
/
bwid
+ 1;
1045
kwid
=
Int_t
(
alb
);
1046
if
(
alb
< 0) --
kwid
;
1047
bh
=
bwid
*
Double_t
(
kwid
);
1048
nb
=
kwid
-
lwid
;
1049
if
(
naa
> 5)
goto
L240
;
1050
if
(
naa
== -1)
return
;
1051
// REQUEST FOR ONE BIN IS DIFFICULT CASE
1052
if
(
naa
> 1 ||
nb
== 1)
return
;
1053
bwid
*= 2;
1054
nb
= 1;
1055
return
;
1056
L240
:
1057
if
(
nb
<< 1 !=
naa
)
return
;
1058
++
na
;
1059
goto
L20
;
1060
}
1061
1062
////////////////////////////////////////////////////////////////////////////////
1063
/// Transform FCN to find further minima
1064
///
1065
/// Called only from MNIMPR. Transforms the function FCN
1066
/// by dividing out the quadratic part in order to find further
1067
/// minima. Calculates `ycalf = (f-fmin)/(x-xmin)*v*(x-xmin)`
1068
1069
void
TMinuit::mncalf
(
Double_t
*
pvec
,
Double_t
&
ycalf
)
1070
{
1071
/* Local variables */
1072
Int_t
ndex
, i,
j
,
m
,
n
,
nparx
;
1073
Double_t
denom
,
f
;
1074
1075
nparx
=
fNpar
;
1076
mninex
(&
pvec
[0]);
1077
Eval
(
nparx
,
fGin
,
f
,
fU
, 4); ++
fNfcn
;
1078
for
(i = 1; i <=
fNpar
; ++i) {
1079
fGrd
[i-1] = 0;
1080
for
(
j
= 1;
j
<=
fNpar
; ++
j
) {
1081
m
=
TMath::Max
(i,
j
);
1082
n
=
TMath::Min
(i,
j
);
1083
ndex
=
m
*(
m
-1) / 2 +
n
;
1084
fGrd
[i-1] +=
fVthmat
[
ndex
-1]*(
fXt
[
j
-1] -
pvec
[
j
-1]);
1085
}
1086
}
1087
denom
= 0;
1088
for
(i = 1; i <=
fNpar
; ++i) {
denom
+=
fGrd
[i-1]*(
fXt
[i-1] -
pvec
[i-1]); }
1089
if
(
denom
<= 0) {
1090
fDcovar
= 1;
1091
fISW
[1] = 0;
1092
denom
= 1;
1093
}
1094
ycalf
= (
f
-
fApsi
) /
denom
;
1095
}
1096
1097
////////////////////////////////////////////////////////////////////////////////
1098
/// Resets the parameter list to UNDEFINED
1099
///
1100
/// Called from MINUIT and by option from MNEXCM
1101
1102
void
TMinuit::mncler
()
1103
{
1104
Int_t
i;
1105
1106
fNpfix
= 0;
1107
fNu
= 0;
1108
fNpar
= 0;
1109
fNfcn
= 0;
1110
fNwrmes
[0] = 0;
1111
fNwrmes
[1] = 0;
1112
for
(i = 1; i <=
fMaxext
; ++i) {
1113
fU
[i-1] = 0;
1114
fCpnam
[i-1] =
fCundef
;
1115
fNvarl
[i-1] = -1;
1116
fNiofex
[i-1] = 0;
1117
}
1118
mnrset
(1);
1119
fCfrom
=
"CLEAR "
;
1120
fNfcnfr
=
fNfcn
;
1121
fCstatu
=
"UNDEFINED "
;
1122
fLnolim
=
kTRUE
;
1123
fLphead
=
kTRUE
;
1124
}
1125
1126
////////////////////////////////////////////////////////////////////////////////
1127
/// Print function contours in two variables, on line printer
1128
///
1129
/// input arguments: parx, pary, devs, ngrid
1130
1131
void
TMinuit::mncntr
(
Int_t
ike1
,
Int_t
ike2
,
Int_t
&
ierrf
)
1132
{
1133
static
const
char
*
const
clabel
=
"0123456789ABCDEFGHIJ"
;
1134
1135
/* Local variables */
1136
Double_t
d__1
,
d__2
;
1137
Double_t
fcna
[115],
fcnb
[115],
contur
[20];
1138
Double_t
ylabel
,
fmn
,
fmx
, xlo,
ylo
, xup, yup;
1139
Double_t
devs
,
xsav
,
ysav
,
bwidx
,
bwidy
,
unext
,
ff
,
xb4
;
1140
Int_t
i,
ngrid
,
ixmid
,
nparx
, ix,
nx
,
ny
,
ki1
,
ki2
,
ixzero
, iy,
ics
;
1141
TString
chmid
,
chln
,
chzero
;
1142
1143
Int_t
ke1
=
ike1
+1;
1144
Int_t
ke2
=
ike2
+1;
1145
if
(
ke1
<= 0 ||
ke2
<= 0)
goto
L1350
;
1146
if
(
ke1
>
fNu
||
ke2
>
fNu
)
goto
L1350
;
1147
ki1
=
fNiofex
[
ke1
-1];
1148
ki2
=
fNiofex
[
ke2
-1];
1149
if
(
ki1
<= 0 ||
ki2
<= 0)
goto
L1350
;
1150
if
(
ki1
==
ki2
)
goto
L1350
;
1151
1152
if
(
fISW
[1] < 1) {
1153
mnhess
();
1154
mnwerr
();
1155
}
1156
nparx
=
fNpar
;
1157
xsav
=
fU
[
ke1
-1];
1158
ysav
=
fU
[
ke2
-1];
1159
devs
=
fWord7
[2];
1160
if
(
devs
<= 0)
devs
= 2;
1161
xlo =
fU
[
ke1
-1] -
devs
*
fWerr
[
ki1
-1];
1162
xup =
fU
[
ke1
-1] +
devs
*
fWerr
[
ki1
-1];
1163
ylo
=
fU
[
ke2
-1] -
devs
*
fWerr
[
ki2
-1];
1164
yup =
fU
[
ke2
-1] +
devs
*
fWerr
[
ki2
-1];
1165
ngrid
=
Int_t
(
fWord7
[3]);
1166
if
(
ngrid
<= 0) {
1167
ngrid
= 25;
1168
// Computing MIN
1169
nx
=
TMath::Min
(
fNpagwd
- 15,
ngrid
);
1170
// Computing MIN
1171
ny
=
TMath::Min
(
fNpagln
- 7,
ngrid
);
1172
}
else
{
1173
nx
=
ngrid
;
1174
ny
=
ngrid
;
1175
}
1176
if
(
nx
< 11)
nx
= 11;
1177
if
(
ny
< 11)
ny
= 11;
1178
if
(
nx
>= 115)
nx
= 114;
1179
1180
// ask if parameter outside limits
1181
if
(
fNvarl
[
ke1
-1] > 1) {
1182
if
(xlo <
fAlim
[
ke1
-1]) xlo =
fAlim
[
ke1
-1];
1183
if
(xup >
fBlim
[
ke1
-1]) xup =
fBlim
[
ke1
-1];
1184
}
1185
if
(
fNvarl
[
ke2
-1] > 1) {
1186
if
(
ylo
<
fAlim
[
ke2
-1])
ylo
=
fAlim
[
ke2
-1];
1187
if
(yup >
fBlim
[
ke2
-1]) yup =
fBlim
[
ke2
-1];
1188
}
1189
bwidx
= (xup - xlo) /
Double_t
(
nx
);
1190
bwidy
= (yup -
ylo
) /
Double_t
(
ny
);
1191
ixmid
=
Int_t
(((
xsav
- xlo)*
Double_t
(
nx
) / (xup - xlo)) + 1);
1192
if
(
ixmid
< 1)
ixmid
= 1;
1193
if
(
fAmin
==
fUndefi
)
mnamin
();
1194
1195
for
(i = 1; i <= 20; ++i) {
contur
[i-1] =
fAmin
+
fUp
*(i-1)*(i-1); }
1196
contur
[0] +=
fUp
*.01;
1197
// fill FCNB to prepare first row, and find column zero/
1198
fU
[
ke2
-1] = yup;
1199
ixzero
= 0;
1200
xb4
= 1;
1201
//TH
1202
chmid
.Resize(
nx
+1);
1203
chzero
.Resize(
nx
+1);
1204
chln
.Resize(
nx
+1);
1205
for
(ix = 1; ix <=
nx
+ 1; ++ix) {
1206
fU
[
ke1
-1] = xlo +
Double_t
(ix-1)*
bwidx
;
1207
Eval
(
nparx
,
fGin
,
ff
,
fU
, 4);
1208
fcnb
[ix-1] =
ff
;
1209
if
(
xb4
< 0 &&
fU
[
ke1
-1] > 0)
ixzero
= ix - 1;
1210
xb4
=
fU
[
ke1
-1];
1211
chmid
[ix-1] =
'*'
;
1212
chzero
[ix-1] =
'-'
;
1213
}
1214
Printf
(
" Y-AXIS: PARAMETER %3d: %s"
,
ke2
,(
const
char
*)
fCpnam
[
ke2
-1]);
1215
if
(
ixzero
> 0) {
1216
chzero
[
ixzero
-1] =
'+'
;
1217
chln
=
" "
;
1218
Printf
(
" X=0"
);
1219
}
1220
// loop over rows
1221
for
(iy = 1; iy <=
ny
; ++iy) {
1222
unext
=
fU
[
ke2
-1] -
bwidy
;
1223
// prepare this line background pattern for contour
1224
chln
=
" "
;
1225
// TH
1226
chln
.Resize(
nx
+1);
1227
chln
[
ixmid
-1] =
'*'
;
1228
if
(
ixzero
!= 0)
chln
[
ixzero
-1] =
':'
;
1229
if
(
fU
[
ke2
-1] >
ysav
&&
unext
<
ysav
)
chln
=
chmid
;
1230
if
(
fU
[
ke2
-1] > 0 &&
unext
< 0)
chln
=
chzero
;
1231
fU
[
ke2
-1] =
unext
;
1232
ylabel
=
fU
[
ke2
-1] +
bwidy
*.5;
1233
// move FCNB to FCNA and fill FCNB with next row
1234
for
(ix = 1; ix <=
nx
+ 1; ++ix) {
1235
fcna
[ix-1] =
fcnb
[ix-1];
1236
fU
[
ke1
-1] = xlo +
Double_t
(ix-1)*
bwidx
;
1237
Eval
(
nparx
,
fGin
,
ff
,
fU
, 4);
1238
fcnb
[ix-1] =
ff
;
1239
}
1240
// look for contours crossing the FCNxy squares
1241
for
(ix = 1; ix <=
nx
; ++ix) {
1242
d__1
=
TMath::Max
(
fcna
[ix-1],
fcnb
[ix-1]),
1243
d__2
=
TMath::Max
(
fcna
[ix],
fcnb
[ix]);
1244
fmx
=
TMath::Max
(
d__1
,
d__2
);
1245
d__1
=
TMath::Min
(
fcna
[ix-1],
fcnb
[ix-1]),
1246
d__2
=
TMath::Min
(
fcna
[ix],
fcnb
[ix]);
1247
fmn
=
TMath::Min
(
d__1
,
d__2
);
1248
for
(
ics
= 1;
ics
<= 20; ++
ics
) {
1249
if
(
contur
[
ics
-1] >
fmn
)
goto
L240
;
1250
}
1251
continue
;
1252
L240
:
1253
if
(
contur
[
ics
-1] <
fmx
)
chln
[ix-1] =
clabel
[
ics
-1];
1254
}
1255
// print a row of the contour plot
1256
Printf
(
" %12.4g %s"
,
ylabel
,(
const
char
*)
chln
);
1257
}
1258
// contours printed, label x-axis
1259
chln
=
" "
;
1260
chln
(0,1) =
'I'
;
1261
chln
(
ixmid
-1,1) =
'I'
;
1262
chln
(
nx
-1,1) =
'I'
;
1263
Printf
(
" %s"
,(
const
char
*)
chln
);
1264
1265
// the hardest of all: print x-axis scale!
1266
chln
=
" "
;
1267
if
(
nx
<= 26) {
1268
Printf
(
" %12.4g%s%12.4g"
,xlo,(
const
char
*)
chln
,xup);
1269
Printf
(
" %s%12.4g"
,(
const
char
*)
chln
,
xsav
);
1270
}
else
{
1271
Printf
(
" %12.4g%s%12.4g%s%12.4g"
,xlo,(
const
char
*)
chln
,
xsav
,(
const
char
*)
chln
,xup);
1272
}
1273
Printf
(
" X-AXIS: PARAMETER %3d %s ONE COLUMN=%12.4g"
1274
,
ke1
,(
const
char
*)
fCpnam
[
ke1
-1],
bwidx
);
1275
Printf
(
" FUNCTION VALUES: F(I)=%12.4g +%12.4g *I**2"
,
fAmin
,
fUp
);
1276
// finished. reset input values
1277
fU
[
ke1
-1] =
xsav
;
1278
fU
[
ke2
-1] =
ysav
;
1279
ierrf
= 0;
1280
return
;
1281
L1350
:
1282
Printf
(
" INVALID PARAMETER NUMBER(S) REQUESTED. IGNORED."
);
1283
ierrf
= 1;
1284
}
1285
1286
////////////////////////////////////////////////////////////////////////////////
1287
/// Reads a command string and executes
1288
///
1289
/// Called by user. 'Reads' a command string and executes.
1290
/// Equivalent to MNEXCM except that the command is given as a
1291
/// character string.
1292
///
1293
/// ICONDN =
1294
/// - 0: command executed normally
1295
/// - 1: command is blank, ignored
1296
/// - 2: command line unreadable, ignored
1297
/// - 3: unknown command, ignored
1298
/// - 4: abnormal termination (e.g., MIGRAD not converged)
1299
/// - 5: command is a request to read PARAMETER definitions
1300
/// - 6: 'SET INPUT' command
1301
/// - 7: 'SET TITLE' command
1302
/// - 8: 'SET COVAR' command
1303
/// - 9: reserved
1304
/// - 10: END command
1305
/// - 11: EXIT or STOP command
1306
/// - 12: RETURN command
1307
///
1308
1309
void
TMinuit::mncomd
(
const
char
*
crdbin
,
Int_t
&
icondn
)
1310
{
1311
/* Local variables */
1312
Int_t
ierr
,
ipos
, i,
llist
, lenbuf,
lnc
;
1313
Bool_t
leader
;
1314
TString
comand
,
crdbuf
,
ctemp
;
1315
1316
crdbuf
=
crdbin
;
1317
crdbuf
.ToUpper();
1318
lenbuf =
crdbuf
.Length();
1319
icondn
= 0;
1320
// record not case-sensitive, get upper case, strip leading blanks
1321
leader
=
kTRUE
;
1322
ipos
= 1;
1323
for
(i = 1; i <=
TMath::Min
(20,lenbuf); ++i) {
1324
if
(
crdbuf
[i-1] ==
'\''
)
break
;
1325
if
(
crdbuf
[i-1] ==
' '
) {
1326
if
(
leader
) ++
ipos
;
1327
continue
;
1328
}
1329
leader
=
kFALSE
;
1330
}
1331
1332
// blank or null command
1333
if
(
ipos
> lenbuf) {
1334
Printf
(
" BLANK COMMAND IGNORED."
);
1335
icondn
= 1;
1336
return
;
1337
}
1338
// preemptive commands
1339
// if command is 'PARAMETER'
1340
if
(
crdbuf
(
ipos
-1,3) ==
"PAR"
) {
1341
icondn
= 5;
1342
fLphead
=
kTRUE
;
1343
return
;
1344
}
1345
// if command is 'SET INPUT'
1346
if
(
crdbuf
(
ipos
-1,3) ==
"SET INP"
) {
1347
icondn
= 6;
1348
fLphead
=
kTRUE
;
1349
return
;
1350
}
1351
// if command is 'SET TITLE'
1352
if
(
crdbuf
(
ipos
-1,7) ==
"SET TIT"
) {
1353
icondn
= 7;
1354
fLphead
=
kTRUE
;
1355
return
;
1356
}
1357
// if command is 'SET COVARIANCE'
1358
if
(
crdbuf
(
ipos
-1,7) ==
"SET COV"
) {
1359
icondn
= 8;
1360
fLphead
=
kTRUE
;
1361
return
;
1362
}
1363
// crack the command
1364
ctemp
=
crdbuf
(
ipos
-1,lenbuf-
ipos
+1);
1365
mncrck
(
ctemp
, 20,
comand
,
lnc
,
fMaxpar
,
fCOMDplist
,
llist
,
ierr
,
fIsyswr
);
1366
if
(
ierr
> 0) {
1367
Printf
(
" COMMAND CANNOT BE INTERPRETED"
);
1368
icondn
= 2;
1369
return
;
1370
}
1371
1372
mnexcm
(
comand
.Data(),
fCOMDplist
,
llist
,
ierr
);
1373
icondn
=
ierr
;
1374
}
1375
1376
////////////////////////////////////////////////////////////////////////////////
1377
/// Find points along a contour where FCN is minimum
1378
///
1379
/// Find NPTU points along a contour where the function
1380
///
1381
/// FMIN (X(KE1),X(KE2)) = AMIN+UP
1382
///
1383
/// where FMIN is the minimum of FCN with respect to all
1384
/// the other NPAR-2 variable parameters (if any).
1385
///
1386
/// IERRF on return will be equal to the number of points found:
1387
/// - NPTU if normal termination with NPTU points found
1388
/// - -1 if errors in the calling sequence (KE1, KE2 not variable)
1389
/// - 0 if less than four points can be found (using MNMNOT)
1390
/// - n>3 if only n points can be found (n < NPTU)
1391
///
1392
/// input arguments: parx, pary, devs, ngrid
1393
1394
void
TMinuit::mncont
(
Int_t
ike1
,
Int_t
ike2
,
Int_t
nptu
,
Double_t
*
xptu
,
Double_t
*
yptu
,
Int_t
&
ierrf
)
1395
{
1396
/* System generated locals */
1397
Int_t
i__1
;
1398
1399
/* Local variables */
1400
Double_t
d__1
,
d__2
;
1401
Double_t
dist,
xdir
,
ydir
,
aopt
,
u1min
,
u2min
;
1402
Double_t
abest
,
scalx
,
scaly
;
1403
Double_t
a1
,
a2
,
val2mi
,
val2pl
,
dc
,
sclfac
,
bigdis
,
sigsav
;
1404
Int_t
nall
,
iold
,
line
,
mpar
,
ierr
,
inew
,
move
, next, i,
j
,
nfcol
,
iercr
;
1405
Int_t
idist
=0,
npcol
,
kints
,
i2
,
i1
,
lr
,
nfcnco
=0,
ki1
,
ki2
,
ki3
,
ke3
;
1406
Int_t
nowpts
,
istrav
,
nfmxin
,
isw2
,
isw4
;
1407
Bool_t
ldebug
;
1408
1409
/* Function Body */
1410
Int_t
ke1
=
ike1
+1;
1411
Int_t
ke2
=
ike2
+1;
1412
ldebug
=
fIdbg
[6] >= 1;
1413
if
(
ke1
<= 0 ||
ke2
<= 0)
goto
L1350
;
1414
if
(
ke1
>
fNu
||
ke2
>
fNu
)
goto
L1350
;
1415
ki1
=
fNiofex
[
ke1
-1];
1416
ki2
=
fNiofex
[
ke2
-1];
1417
if
(
ki1
<= 0 ||
ki2
<= 0)
goto
L1350
;
1418
if
(
ki1
==
ki2
)
goto
L1350
;
1419
if
(
nptu
< 4)
goto
L1400
;
1420
1421
nfcnco
=
fNfcn
;
1422
fNfcnmx
= (
nptu
+ 5)*100*(
fNpar
+ 1);
1423
// The minimum
1424
mncuve
();
1425
u1min
=
fU
[
ke1
-1];
1426
u2min
=
fU
[
ke2
-1];
1427
ierrf
= 0;
1428
fCfrom
=
"MNContour "
;
1429
fNfcnfr
=
nfcnco
;
1430
if
(
fISW
[4] >= 0) {
1431
Printf
(
" START MNCONTOUR CALCULATION OF %4d POINTS ON CONTOUR."
,
nptu
);
1432
if
(
fNpar
> 2) {
1433
if
(
fNpar
== 3) {
1434
ki3
= 6 -
ki1
-
ki2
;
1435
ke3
=
fNexofi
[
ki3
-1];
1436
Printf
(
" EACH POINT IS A MINIMUM WITH RESPECT TO PARAMETER %3d %s"
,
ke3
,(
const
char
*)
fCpnam
[
ke3
-1]);
1437
}
else
{
1438
Printf
(
" EACH POINT IS A MINIMUM WITH RESPECT TO THE OTHER %3d VARIABLE PARAMETERS."
,
fNpar
- 2);
1439
}
1440
}
1441
}
1442
1443
// Find the first four points using MNMNOT
1444
// first two points
1445
mnmnot
(
ke1
,
ke2
,
val2pl
,
val2mi
);
1446
if
(
fErn
[
ki1
-1] ==
fUndefi
) {
1447
xptu
[0] =
fAlim
[
ke1
-1];
1448
mnwarn
(
"W"
,
"MNContour "
,
"Contour squeezed by parameter limits."
);
1449
}
else
{
1450
if
(
fErn
[
ki1
-1] >= 0)
goto
L1500
;
1451
xptu
[0] =
u1min
+
fErn
[
ki1
-1];
1452
}
1453
yptu
[0] =
val2mi
;
1454
1455
if
(
fErp
[
ki1
-1] ==
fUndefi
) {
1456
xptu
[2] =
fBlim
[
ke1
-1];
1457
mnwarn
(
"W"
,
"MNContour "
,
"Contour squeezed by parameter limits."
);
1458
}
else
{
1459
if
(
fErp
[
ki1
-1] <= 0)
goto
L1500
;
1460
xptu
[2] =
u1min
+
fErp
[
ki1
-1];
1461
}
1462
yptu
[2] =
val2pl
;
1463
scalx
= 1 / (
xptu
[2] -
xptu
[0]);
1464
// next two points
1465
mnmnot
(
ke2
,
ke1
,
val2pl
,
val2mi
);
1466
if
(
fErn
[
ki2
-1] ==
fUndefi
) {
1467
yptu
[1] =
fAlim
[
ke2
-1];
1468
mnwarn
(
"W"
,
"MNContour "
,
"Contour squeezed by parameter limits."
);
1469
}
else
{
1470
if
(
fErn
[
ki2
-1] >= 0)
goto
L1500
;
1471
yptu
[1] =
u2min
+
fErn
[
ki2
-1];
1472
}
1473
xptu
[1] =
val2mi
;
1474
if
(
fErp
[
ki2
-1] ==
fUndefi
) {
1475
yptu
[3] =
fBlim
[
ke2
-1];
1476
mnwarn
(
"W"
,
"MNContour "
,
"Contour squeezed by parameter limits."
);
1477
}
else
{
1478
if
(
fErp
[
ki2
-1] <= 0)
goto
L1500
;
1479
yptu
[3] =
u2min
+
fErp
[
ki2
-1];
1480
}
1481
xptu
[3] =
val2pl
;
1482
scaly
= 1 / (
yptu
[3] -
yptu
[1]);
1483
nowpts
= 4;
1484
next = 5;
1485
if
(
ldebug
) {
1486
Printf
(
" Plot of four points found by MINOS"
);
1487
fXpt
[0] =
u1min
;
1488
fYpt
[0] =
u2min
;
1489
fChpt
[0] =
' '
;
1490
// Computing MIN
1491
nall
=
TMath::Min
(
nowpts
+ 1,101);
1492
for
(i = 2; i <=
nall
; ++i) {
1493
fXpt
[i-1] =
xptu
[i-2];
1494
fYpt
[i-1] =
yptu
[i-2];
1495
}
1496
snprintf
(
fChpt
,
fMaxcpt
+1,
"%s"
,
" ABCD"
);
1497
mnplot
(
fXpt
,
fYpt
,
fChpt
,
nall
,
fNpagwd
,
fNpagln
);
1498
}
1499
1500
// save some values before fixing
1501
isw2
=
fISW
[1];
1502
isw4
=
fISW
[3];
1503
sigsav
=
fEDM
;
1504
istrav
=
fIstrat
;
1505
dc
=
fDcovar
;
1506
fApsi
=
fEpsi
*.5;
1507
abest
=
fAmin
;
1508
mpar
=
fNpar
;
1509
nfmxin
=
fNfcnmx
;
1510
for
(i = 1; i <=
mpar
; ++i) {
fXt
[i-1] =
fX
[i-1]; }
1511
i__1
=
mpar
*(
mpar
+ 1) / 2;
1512
for
(
j
= 1;
j
<=
i__1
; ++
j
) {
fVthmat
[
j
-1] =
fVhmat
[
j
-1]; }
1513
for
(i = 1; i <=
mpar
; ++i) {
1514
fCONTgcc
[i-1] =
fGlobcc
[i-1];
1515
fCONTw
[i-1] =
fWerr
[i-1];
1516
}
1517
// fix the two parameters in question
1518
kints
=
fNiofex
[
ke1
-1];
1519
mnfixp
(
kints
-1,
ierr
);
1520
kints
=
fNiofex
[
ke2
-1];
1521
mnfixp
(
kints
-1,
ierr
);
1522
// Fill in the rest of the points
1523
for
(
inew
= next;
inew
<=
nptu
; ++
inew
) {
1524
// find the two neighbouring points with largest separation
1525
bigdis
= 0;
1526
for
(
iold
= 1;
iold
<=
inew
- 1; ++
iold
) {
1527
i2
=
iold
+ 1;
1528
if
(
i2
==
inew
)
i2
= 1;
1529
d__1
=
scalx
*(
xptu
[
iold
-1] -
xptu
[
i2
-1]);
1530
d__2
=
scaly
*(
yptu
[
iold
-1] -
yptu
[
i2
-1]);
1531
dist =
d__1
*
d__1
+
d__2
*
d__2
;
1532
if
(dist >
bigdis
) {
1533
bigdis
= dist;
1534
idist
=
iold
;
1535
}
1536
}
1537
i1
=
idist
;
1538
i2
=
i1
+ 1;
1539
if
(
i2
==
inew
)
i2
= 1;
1540
// next point goes between I1 and I2
1541
a1
= .5;
1542
a2
= .5;
1543
L300
:
1544
fXmidcr
=
a1
*
xptu
[
i1
-1] +
a2
*
xptu
[
i2
-1];
1545
fYmidcr
=
a1
*
yptu
[
i1
-1] +
a2
*
yptu
[
i2
-1];
1546
xdir
=
yptu
[
i2
-1] -
yptu
[
i1
-1];
1547
ydir
=
xptu
[
i1
-1] -
xptu
[
i2
-1];
1548
sclfac
=
TMath::Max
(
TMath::Abs
(
xdir
*
scalx
),
TMath::Abs
(
ydir
*
scaly
));
1549
fXdircr
=
xdir
/
sclfac
;
1550
fYdircr
=
ydir
/
sclfac
;
1551
fKe1cr
=
ke1
;
1552
fKe2cr
=
ke2
;
1553
// Find the contour crossing point along DIR
1554
fAmin
=
abest
;
1555
mncros
(
aopt
,
iercr
);
1556
if
(
iercr
> 1) {
1557
// If cannot find mid-point, try closer to point 1
1558
if
(
a1
> .5) {
1559
if
(
fISW
[4] >= 0) {
1560
Printf
(
" MNCONT CANNOT FIND NEXT POINT ON CONTOUR. ONLY %3d POINTS FOUND."
,
nowpts
);
1561
}
1562
goto
L950
;
1563
}
1564
mnwarn
(
"W"
,
"MNContour "
,
"Cannot find midpoint, try closer."
);
1565
a1
= .75;
1566
a2
= .25;
1567
goto
L300
;
1568
}
1569
// Contour has been located, insert new point in list
1570
for
(
move
=
nowpts
;
move
>=
i1
+ 1; --
move
) {
1571
xptu
[
move
] =
xptu
[
move
-1];
1572
yptu
[
move
] =
yptu
[
move
-1];
1573
}
1574
++
nowpts
;
1575
xptu
[
i1
] =
fXmidcr
+
fXdircr
*
aopt
;
1576
yptu
[
i1
] =
fYmidcr
+
fYdircr
*
aopt
;
1577
}
1578
L950
:
1579
1580
ierrf
=
nowpts
;
1581
fCstatu
=
"SUCCESSFUL"
;
1582
if
(
nowpts
<
nptu
)
fCstatu
=
"INCOMPLETE"
;
1583
1584
// make a lineprinter plot of the contour
1585
if
(
fISW
[4] >= 0) {
1586
fXpt
[0] =
u1min
;
1587
fYpt
[0] =
u2min
;
1588
fChpt
[0] =
' '
;
1589
nall
=
TMath::Min
(
nowpts
+ 1,101);
1590
for
(i = 2; i <=
nall
; ++i) {
1591
fXpt
[i-1] =
xptu
[i-2];
1592
fYpt
[i-1] =
yptu
[i-2];
1593
fChpt
[i-1] =
'X'
;
1594
}
1595
fChpt
[
nall
] = 0;
1596
Printf
(
" Y-AXIS: PARAMETER %3d %s"
,
ke2
,(
const
char
*)
fCpnam
[
ke2
-1]);
1597
1598
mnplot
(
fXpt
,
fYpt
,
fChpt
,
nall
,
fNpagwd
,
fNpagln
);
1599
1600
Printf
(
" X-AXIS: PARAMETER %3d %s"
,
ke1
,(
const
char
*)
fCpnam
[
ke1
-1]);
1601
}
1602
// print out the coordinates around the contour
1603
if
(
fISW
[4] >= 1) {
1604
npcol
= (
nowpts
+ 1) / 2;
1605
nfcol
=
nowpts
/ 2;
1606
Printf
(
"%5d POINTS ON CONTOUR. FMIN=%13.5e ERRDEF=%11.3g"
,
nowpts
,
abest
,
fUp
);
1607
Printf
(
" %s%s%s%s"
,(
const
char
*)
fCpnam
[
ke1
-1],
1608
(
const
char
*)
fCpnam
[
ke2
-1],
1609
(
const
char
*)
fCpnam
[
ke1
-1],
1610
(
const
char
*)
fCpnam
[
ke2
-1]);
1611
for
(
line
= 1;
line
<=
nfcol
; ++
line
) {
1612
lr
=
line
+
npcol
;
1613
Printf
(
" %5d%13.5e%13.5e %5d%13.5e%13.5e"
,
line
,
xptu
[
line
-1],
yptu
[
line
-1],
lr
,
xptu
[
lr
-1],
yptu
[
lr
-1]);
1614
}
1615
if
(
nfcol
<
npcol
) {
1616
Printf
(
" %5d%13.5e%13.5e"
,
npcol
,
xptu
[
npcol
-1],
yptu
[
npcol
-1]);
1617
}
1618
}
1619
// contour finished. reset v
1620
fItaur
= 1;
1621
mnfree
(1);
1622
mnfree
(1);
1623
i__1
=
mpar
*(
mpar
+ 1) / 2;
1624
for
(
j
= 1;
j
<=
i__1
; ++
j
) {
fVhmat
[
j
-1] =
fVthmat
[
j
-1]; }
1625
for
(i = 1; i <=
mpar
; ++i) {
1626
fGlobcc
[i-1] =
fCONTgcc
[i-1];
1627
fWerr
[i-1] =
fCONTw
[i-1];
1628
fX
[i-1] =
fXt
[i-1];
1629
}
1630
mninex
(
fX
);
1631
fEDM
=
sigsav
;
1632
fAmin
=
abest
;
1633
fISW
[1] =
isw2
;
1634
fISW
[3] =
isw4
;
1635
fDcovar
=
dc
;
1636
fItaur
= 0;
1637
fNfcnmx
=
nfmxin
;
1638
fIstrat
=
istrav
;
1639
fU
[
ke1
-1] =
u1min
;
1640
fU
[
ke2
-1] =
u2min
;
1641
goto
L2000
;
1642
// Error returns
1643
L1350
:
1644
Printf
(
" INVALID PARAMETER NUMBERS."
);
1645
goto
L1450
;
1646
L1400
:
1647
Printf
(
" LESS THAN FOUR POINTS REQUESTED."
);
1648
L1450
:
1649
ierrf
= -1;
1650
fCstatu
=
"USER ERROR"
;
1651
goto
L2000
;
1652
L1500
:
1653
Printf
(
" MNCONT UNABLE TO FIND FOUR POINTS."
);
1654
fU
[
ke1
-1] =
u1min
;
1655
fU
[
ke2
-1] =
u2min
;
1656
ierrf
= 0;
1657
fCstatu
=
"FAILED"
;
1658
L2000
:
1659
fCfrom
=
"MNContour "
;
1660
fNfcnfr
=
nfcnco
;
1661
}
1662
1663
////////////////////////////////////////////////////////////////////////////////
1664
/// Cracks the free-format input
1665
///
1666
/// Cracks the free-format input, expecting zero or more
1667
/// alphanumeric fields (which it joins into COMAND(1:LNC))
1668
/// followed by one or more numeric fields separated by
1669
/// blanks and/or one comma. The numeric fields are put into
1670
/// the LLIST (but at most MXP) elements of PLIST.
1671
///
1672
/// IERR :
1673
/// - = 0 if no errors,
1674
/// - = 1 if error(s).
1675
1676
void
TMinuit::mncrck
(
TString
cardbuf
,
Int_t
maxcwd
,
TString
&
comand
,
Int_t
&
lnc
,
1677
Int_t
mxp
,
Double_t
*
plist
,
Int_t
&
llist
,
Int_t
&
ierr
,
Int_t
)
1678
{
1679
/* Initialized data */
1680
1681
char
*
cnull
=
nullptr
;
1682
const
char
*
cnumer
=
"123456789-.0+"
;
1683
1684
/* Local variables */
1685
Int_t
ifld
,
iend
,
lend
, left,
nreq
,
ipos
,
kcmnd
,
nextb
,
ic
,
ibegin
,
ltoadd
;
1686
Int_t
ielmnt
,
lelmnt
[25],
nelmnt
;
1687
TString
ctemp
;
1688
char
*
celmnt
[25];
1689
char
command
[25];
1690
1691
/* Function Body */
1692
char
*
crdbuf
= (
char
*)
cardbuf
.Data();
1693
lend
=
cardbuf
.Length();
1694
ielmnt
= 0;
1695
nextb
= 1;
1696
ierr
= 0;
1697
// loop over words CELMNT
1698
L10
:
1699
for
(
ipos
=
nextb
;
ipos
<=
lend
; ++
ipos
) {
1700
ibegin
=
ipos
;
1701
if
(
crdbuf
[
ipos
-1] ==
' '
)
continue
;
1702
if
(
crdbuf
[
ipos
-1] ==
','
)
goto
L250
;
1703
goto
L150
;
1704
}
1705
goto
L300
;
1706
L150
:
1707
// found beginning of word, look for end
1708
for
(
ipos
=
ibegin
+ 1;
ipos
<=
lend
; ++
ipos
) {
1709
if
(
crdbuf
[
ipos
-1] ==
' '
)
goto
L250
;
1710
if
(
crdbuf
[
ipos
-1] ==
','
)
goto
L250
;
1711
}
1712
ipos
=
lend
+ 1;
1713
L250
:
1714
iend
=
ipos
- 1;
1715
++
ielmnt
;
1716
if
(
iend
>=
ibegin
)
celmnt
[
ielmnt
-1] = &
crdbuf
[
ibegin
-1];
1717
else
celmnt
[
ielmnt
-1] =
cnull
;
1718
lelmnt
[
ielmnt
-1] =
iend
-
ibegin
+ 1;
1719
if
(
lelmnt
[
ielmnt
-1] > 19) {
1720
Printf
(
" MINUIT WARNING: INPUT DATA WORD TOO LONG."
);
1721
ctemp
=
cardbuf
(
ibegin
-1,
iend
-
ibegin
+1);
1722
Printf
(
" ORIGINAL:%s"
,
ctemp
.Data());
1723
Printf
(
" TRUNCATED TO:%s"
,
celmnt
[
ielmnt
-1]);
1724
lelmnt
[
ielmnt
-1] = 19;
1725
}
1726
if
(
ipos
>=
lend
)
goto
L300
;
1727
if
(
ielmnt
>= 25)
goto
L300
;
1728
// look for comma or beginning of next word
1729
for
(
ipos
=
iend
+ 1;
ipos
<=
lend
; ++
ipos
) {
1730
if
(
crdbuf
[
ipos
-1] ==
' '
)
continue
;
1731
nextb
=
ipos
;
1732
if
(
crdbuf
[
ipos
-1] ==
','
)
nextb
=
ipos
+ 1;
1733
goto
L10
;
1734
}
1735
// All elements found, join the alphabetic ones to
1736
// form a command
1737
L300
:
1738
nelmnt
=
ielmnt
;
1739
command
[0] =
' '
;
command
[1] = 0;
1740
lnc
= 1;
1741
plist
[0] = 0;
1742
llist
= 0;
1743
if
(
ielmnt
== 0)
goto
L900
;
1744
kcmnd
= 0;
1745
for
(
ielmnt
= 1;
ielmnt
<=
nelmnt
; ++
ielmnt
) {
1746
if
(
celmnt
[
ielmnt
-1] ==
cnull
)
goto
L450
;
1747
for
(
ic
= 1;
ic
<= 13; ++
ic
) {
1748
if
(*
celmnt
[
ielmnt
-1] ==
cnumer
[
ic
-1])
goto
L450
;
1749
}
1750
if
(
kcmnd
>=
maxcwd
)
continue
;
1751
left =
maxcwd
-
kcmnd
;
1752
ltoadd
=
lelmnt
[
ielmnt
-1];
1753
if
(
ltoadd
> left)
ltoadd
= left;
1754
strncpy
(&
command
[
kcmnd
],
celmnt
[
ielmnt
-1],
ltoadd
);
1755
kcmnd
+=
ltoadd
;
1756
if
(
kcmnd
==
maxcwd
)
continue
;
1757
command
[
kcmnd
] =
' '
;
1758
++
kcmnd
;
1759
command
[
kcmnd
] = 0;
1760
}
1761
lnc
=
kcmnd
;
1762
goto
L900
;
1763
L450
:
1764
lnc
=
kcmnd
;
1765
// we have come to a numeric field
1766
llist
= 0;
1767
for
(
ifld
=
ielmnt
;
ifld
<=
nelmnt
; ++
ifld
) {
1768
++
llist
;
1769
if
(
llist
>
mxp
) {
1770
nreq
=
nelmnt
-
ielmnt
+ 1;
1771
Printf
(
" MINUIT WARNING IN MNCRCK: "
);
1772
Printf
(
" COMMAND HAS INPUT %5d NUMERIC FIELDS, BUT MINUIT CAN ACCEPT ONLY%3d"
,
nreq
,
mxp
);
1773
goto
L900
;
1774
}
1775
if
(
celmnt
[
ifld
-1] ==
cnull
)
plist
[
llist
-1] = 0;
1776
else
{
1777
sscanf
(
celmnt
[
ifld
-1],
"%lf"
,&
plist
[
llist
-1]);
1778
}
1779
}
1780
// end loop over numeric fields
1781
L900
:
1782
if
(
lnc
<= 0)
lnc
= 1;
1783
comand
=
command
;
1784
}
1785
1786
////////////////////////////////////////////////////////////////////////////////
1787
/// Find point where MNEVAL=AMIN+UP
1788
///
1789
/// Find point where MNEVAL=AMIN+UP, along the line through
1790
/// XMIDCR,YMIDCR with direction XDIRCR,YDIRCR, where X and Y
1791
/// are parameters KE1CR and KE2CR. If KE2CR=0 (from MINOS),
1792
/// only KE1CR is varied. From MNCONT, both are varied.
1793
/// Crossing point is at
1794
///
1795
/// (U(KE1),U(KE2)) = (XMID,YMID) + AOPT*(XDIR,YDIR)
1796
1797
void
TMinuit::mncros
(
Double_t
&
aopt
,
Int_t
&
iercr
)
1798
{
1799
/* Local variables */
1800
Double_t
alsb
[3],
flsb
[3],
bmin
,
bmax
,
zmid
,
sdev
,
zdir
,
zlim
;
1801
Double_t
coeff
[3],
aleft
,
aulim
, fdist,
adist
,
aminsv
;
1802
Double_t
anext
,
fnext
,
slope
,
s1
,
s2
,
x1
,
x2
,
ecarmn
,
ecarmx
;
1803
Double_t
determ
,
rt
,
smalla
,
aright
,
aim
,
tla
,
tlf
,
dfda
,
ecart
;
1804
Int_t
iout
=0, i,
ileft
,
ierev
,
maxlk
,
ibest
, ik, it;
1805
Int_t
noless
,
iworst
=0,
iright
,
itoohi
,
kex
,
ipt
;
1806
Bool_t
ldebug
;
1807
const
char
*
chsign
;
1808
x2
= 0;
1809
1810
ldebug
=
fIdbg
[6] >= 1;
1811
aminsv
=
fAmin
;
1812
// convergence when F is within TLF of AIM and next prediction
1813
// of AOPT is within TLA of previous value of AOPT
1814
aim
=
fAmin
+
fUp
;
1815
tlf
=
fUp
*.01;
1816
tla
= .01;
1817
fXpt
[0] = 0;
1818
fYpt
[0] =
aim
;
1819
fChpt
[0] =
' '
;
1820
ipt
= 1;
1821
if
(
fKe2cr
== 0) {
1822
fXpt
[1] = -1;
1823
fYpt
[1] =
fAmin
;
1824
fChpt
[1] =
'.'
;
1825
ipt
= 2;
1826
}
1827
// find the largest allowed A
1828
aulim
= 100;
1829
for
(ik = 1; ik <= 2; ++ik) {
1830
if
(ik == 1) {
1831
kex
=
fKe1cr
;
1832
zmid
=
fXmidcr
;
1833
zdir
=
fXdircr
;
1834
}
else
{
1835
if
(
fKe2cr
== 0)
continue
;
1836
kex
=
fKe2cr
;
1837
zmid
=
fYmidcr
;
1838
zdir
=
fYdircr
;
1839
}
1840
if
(
fNvarl
[
kex
-1] <= 1)
continue
;
1841
if
(
zdir
== 0)
continue
;
1842
zlim
=
fAlim
[
kex
-1];
1843
if
(
zdir
> 0)
zlim
=
fBlim
[
kex
-1];
1844
aulim
=
TMath::Min
(
aulim
,(
zlim
-
zmid
) /
zdir
);
1845
}
1846
// LSB = Line Search Buffer
1847
// first point
1848
anext
= 0;
1849
aopt
=
anext
;
1850
fLimset
=
kFALSE
;
1851
if
(
aulim
<
aopt
+
tla
)
fLimset
=
kTRUE
;
1852
mneval
(
anext
,
fnext
,
ierev
);
1853
// debug printout:
1854
if
(
ldebug
) {
1855
Printf
(
" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f"
,
fNfcn
,
aim
,
fnext
,
aopt
);
1856
}
1857
if
(
ierev
> 0)
goto
L900
;
1858
if
(
fLimset
&&
fnext
<=
aim
)
goto
L930
;
1859
++
ipt
;
1860
fXpt
[
ipt
-1] =
anext
;
1861
fYpt
[
ipt
-1] =
fnext
;
1862
fChpt
[
ipt
-1] =
charal
[
ipt
-1];
1863
alsb
[0] =
anext
;
1864
flsb
[0] =
fnext
;
1865
fnext
=
TMath::Max
(
fnext
,
aminsv
+
fUp
*.1);
1866
aopt
=
TMath::Sqrt
(
fUp
/ (
fnext
-
aminsv
)) - 1;
1867
if
(
TMath::Abs
(
fnext
-
aim
) <
tlf
)
goto
L800
;
1868
1869
if
(
aopt
< -.5)
aopt
= -.5;
1870
if
(
aopt
> 1)
aopt
= 1;
1871
fLimset
=
kFALSE
;
1872
if
(
aopt
>
aulim
) {
1873
aopt
=
aulim
;
1874
fLimset
=
kTRUE
;
1875
}
1876
mneval
(
aopt
,
fnext
,
ierev
);
1877
// debug printout:
1878
if
(
ldebug
) {
1879
Printf
(
" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f"
,
fNfcn
,
aim
,
fnext
,
aopt
);
1880
}
1881
if
(
ierev
> 0)
goto
L900
;
1882
if
(
fLimset
&&
fnext
<=
aim
)
goto
L930
;
1883
alsb
[1] =
aopt
;
1884
++
ipt
;
1885
fXpt
[
ipt
-1] =
alsb
[1];
1886
fYpt
[
ipt
-1] =
fnext
;
1887
fChpt
[
ipt
-1] =
charal
[
ipt
-1];
1888
flsb
[1] =
fnext
;
1889
dfda
= (
flsb
[1] -
flsb
[0]) / (
alsb
[1] -
alsb
[0]);
1890
// DFDA must be positive on the contour
1891
if
(
dfda
> 0)
goto
L460
;
1892
L300
:
1893
mnwarn
(
"D"
,
"MNCROS "
,
"Looking for slope of the right sign"
);
1894
maxlk
= 15 -
ipt
;
1895
for
(it = 1; it <=
maxlk
; ++it) {
1896
alsb
[0] =
alsb
[1];
1897
flsb
[0] =
flsb
[1];
1898
aopt
=
alsb
[0] +
Double_t
(it)*.2;
1899
fLimset
=
kFALSE
;
1900
if
(
aopt
>
aulim
) {
1901
aopt
=
aulim
;
1902
fLimset
=
kTRUE
;
1903
}
1904
mneval
(
aopt
,
fnext
,
ierev
);
1905
// debug printout:
1906
if
(
ldebug
) {
1907
Printf
(
" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f"
,
fNfcn
,
aim
,
fnext
,
aopt
);
1908
}
1909
if
(
ierev
> 0)
goto
L900
;
1910
if
(
fLimset
&&
fnext
<=
aim
)
goto
L930
;
1911
alsb
[1] =
aopt
;
1912
++
ipt
;
1913
fXpt
[
ipt
-1] =
alsb
[1];
1914
fYpt
[
ipt
-1] =
fnext
;
1915
fChpt
[
ipt
-1] =
charal
[
ipt
-1];
1916
flsb
[1] =
fnext
;
1917
dfda
= (
flsb
[1] -
flsb
[0]) / (
alsb
[1] -
alsb
[0]);
1918
if
(
dfda
> 0)
goto
L450
;
1919
}
1920
mnwarn
(
"W"
,
"MNCROS "
,
"Cannot find slope of the right sign"
);
1921
goto
L950
;
1922
L450
:
1923
// we have two points with the right slope
1924
L460
:
1925
aopt
=
alsb
[1] + (
aim
-
flsb
[1]) /
dfda
;
1926
fdist =
TMath::Min
(
TMath::Abs
(
aim
-
flsb
[0]),
TMath::Abs
(
aim
-
flsb
[1]));
1927
adist
=
TMath::Min
(
TMath::Abs
(
aopt
-
alsb
[0]),
TMath::Abs
(
aopt
-
alsb
[1]));
1928
tla
= .01;
1929
if
(
TMath::Abs
(
aopt
) > 1)
tla
=
TMath::Abs
(
aopt
)*.01;
1930
if
(
adist
<
tla
&& fdist <
tlf
)
goto
L800
;
1931
if
(
ipt
>= 15)
goto
L950
;
1932
bmin
=
TMath::Min
(
alsb
[0],
alsb
[1]) - 1;
1933
if
(
aopt
<
bmin
)
aopt
=
bmin
;
1934
bmax
=
TMath::Max
(
alsb
[0],
alsb
[1]) + 1;
1935
if
(
aopt
>
bmax
)
aopt
=
bmax
;
1936
// Try a third point
1937
fLimset
=
kFALSE
;
1938
if
(
aopt
>
aulim
) {
1939
aopt
=
aulim
;
1940
fLimset
=
kTRUE
;
1941
}
1942
mneval
(
aopt
,
fnext
,
ierev
);
1943
// debug printout:
1944
if
(
ldebug
) {
1945
Printf
(
" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f"
,
fNfcn
,
aim
,
fnext
,
aopt
);
1946
}
1947
if
(
ierev
> 0)
goto
L900
;
1948
if
(
fLimset
&&
fnext
<=
aim
)
goto
L930
;
1949
alsb
[2] =
aopt
;
1950
++
ipt
;
1951
fXpt
[
ipt
-1] =
alsb
[2];
1952
fYpt
[
ipt
-1] =
fnext
;
1953
fChpt
[
ipt
-1] =
charal
[
ipt
-1];
1954
flsb
[2] =
fnext
;
1955
// now we have three points, ask how many <AIM
1956
ecarmn
=
TMath::Abs
(
fnext
-
aim
);
1957
ibest
= 3;
1958
ecarmx
= 0;
1959
noless
= 0;
1960
for
(i = 1; i <= 3; ++i) {
1961
ecart
=
TMath::Abs
(
flsb
[i-1] -
aim
);
1962
if
(
ecart
>
ecarmx
) {
ecarmx
=
ecart
;
iworst
= i; }
1963
if
(
ecart
<
ecarmn
) {
ecarmn
=
ecart
;
ibest
= i; }
1964
if
(
flsb
[i-1] <
aim
) ++
noless
;
1965
}
1966
// if at least one on each side of AIM, fit a parabola
1967
if
(
noless
== 1 ||
noless
== 2)
goto
L500
;
1968
// if all three are above AIM, third must be closest to AIM
1969
if
(
noless
== 0 &&
ibest
!= 3)
goto
L950
;
1970
// if all three below, and third is not best, then slope
1971
// has again gone negative, look for positive slope.
1972
if
(
noless
== 3 &&
ibest
!= 3) {
1973
alsb
[1] =
alsb
[2];
1974
flsb
[1] =
flsb
[2];
1975
goto
L300
;
1976
}
1977
// in other cases, new straight line thru last two points
1978
alsb
[
iworst
-1] =
alsb
[2];
1979
flsb
[
iworst
-1] =
flsb
[2];
1980
dfda
= (
flsb
[1] -
flsb
[0]) / (
alsb
[1] -
alsb
[0]);
1981
goto
L460
;
1982
// parabola fit
1983
L500
:
1984
mnpfit
(
alsb
,
flsb
, 3,
coeff
,
sdev
);
1985
if
(
coeff
[2] <= 0) {
1986
mnwarn
(
"D"
,
"MNCROS "
,
"Curvature is negative near contour line."
);
1987
}
1988
determ
=
coeff
[1]*
coeff
[1] -
coeff
[2]*4*(
coeff
[0] -
aim
);
1989
if
(
determ
<= 0) {
1990
mnwarn
(
"D"
,
"MNCROS "
,
"Problem 2, impossible determinant"
);
1991
goto
L950
;
1992
}
1993
// Find which root is the right one
1994
rt
=
TMath::Sqrt
(
determ
);
1995
x1
= (-
coeff
[1] +
rt
) / (
coeff
[2]*2);
1996
x2
= (-
coeff
[1] -
rt
) / (
coeff
[2]*2);
1997
s1
=
coeff
[1] +
x1
*2*
coeff
[2];
1998
s2
=
coeff
[1] +
x2
*2*
coeff
[2];
1999
if
(
s1
*
s2
> 0) {
2000
Printf
(
" MNCONTour problem 1"
);
2001
}
2002
aopt
=
x1
;
2003
slope
=
s1
;
2004
if
(
s2
> 0) {
2005
aopt
=
x2
;
2006
slope
=
s2
;
2007
}
2008
// ask if converged
2009
tla
= .01;
2010
if
(
TMath::Abs
(
aopt
) > 1)
tla
=
TMath::Abs
(
aopt
)*.01;
2011
if
(
TMath::Abs
(
aopt
-
alsb
[
ibest
-1]) <
tla
&&
TMath::Abs
(
flsb
[
ibest
-1] -
aim
) <
tlf
) {
2012
goto
L800
;
2013
}
2014
if
(
ipt
>= 15)
goto
L950
;
2015
2016
// see if proposed point is in acceptable zone between L and R
2017
// first find ILEFT, IRIGHT, IOUT and IBEST
2018
ileft
= 0;
2019
iright
= 0;
2020
ibest
= 1;
2021
ecarmx
= 0;
2022
ecarmn
=
TMath::Abs
(
aim
-
flsb
[0]);
2023
for
(i = 1; i <= 3; ++i) {
2024
ecart
=
TMath::Abs
(
flsb
[i-1] -
aim
);
2025
if
(
ecart
<
ecarmn
) {
ecarmn
=
ecart
;
ibest
= i; }
2026
if
(
ecart
>
ecarmx
) {
ecarmx
=
ecart
; }
2027
if
(
flsb
[i-1] >
aim
) {
2028
if
(
iright
== 0)
iright
= i;
2029
else
if
(
flsb
[i-1] >
flsb
[
iright
-1])
iout
= i;
2030
else
{
iout
=
iright
;
iright
= i; }
2031
}
2032
else
if
(
ileft
== 0)
ileft
= i;
2033
else
if
(
flsb
[i-1] <
flsb
[
ileft
-1])
iout
= i;
2034
else
{
iout
=
ileft
;
ileft
= i; }
2035
}
2036
// avoid keeping a very bad point next time around
2037
if
(
ecarmx
>
TMath::Abs
(
flsb
[
iout
-1] -
aim
)*10) {
2038
aopt
=
aopt
*.5 + (
alsb
[
iright
-1] +
alsb
[
ileft
-1])*.25;
2039
}
2040
// knowing ILEFT and IRIGHT, get acceptable window
2041
smalla
=
tla
*.1;
2042
if
(
slope
*
smalla
>
tlf
)
smalla
=
tlf
/
slope
;
2043
aleft
=
alsb
[
ileft
-1] +
smalla
;
2044
aright
=
alsb
[
iright
-1] -
smalla
;
2045
// move proposed point AOPT into window if necessary
2046
if
(
aopt
<
aleft
)
aopt
=
aleft
;
2047
if
(
aopt
>
aright
)
aopt
=
aright
;
2048
if
(
aleft
>
aright
)
aopt
= (
aleft
+
aright
)*.5;
2049
2050
// see if proposed point outside limits (should be impossible!)
2051
fLimset
=
kFALSE
;
2052
if
(
aopt
>
aulim
) {
2053
aopt
=
aulim
;
2054
fLimset
=
kTRUE
;
2055
}
2056
// Evaluate function at new point AOPT
2057
mneval
(
aopt
,
fnext
,
ierev
);
2058
// debug printout:
2059
if
(
ldebug
) {
2060
Printf
(
" MNCROS: calls=%8d AIM=%10.5f F,A=%10.5f%10.5f"
,
fNfcn
,
aim
,
fnext
,
aopt
);
2061
}
2062
if
(
ierev
> 0)
goto
L900
;
2063
if
(
fLimset
&&
fnext
<=
aim
)
goto
L930
;
2064
++
ipt
;
2065
fXpt
[
ipt
-1] =
aopt
;
2066
fYpt
[
ipt
-1] =
fnext
;
2067
fChpt
[
ipt
-1] =
charal
[
ipt
-1];
2068
// Replace odd point by new one
2069
alsb
[
iout
-1] =
aopt
;
2070
flsb
[
iout
-1] =
fnext
;
2071
// the new point may not be the best, but it is the only one
2072
// which could be good enough to pass convergence criteria
2073
ibest
=
iout
;
2074
goto
L500
;
2075
2076
// Contour has been located, return point to MNCONT OR MINOS
2077
L800
:
2078
iercr
= 0;
2079
goto
L1000
;
2080
// error in the minimization
2081
L900
:
2082
if
(
ierev
== 1)
goto
L940
;
2083
goto
L950
;
2084
// parameter up against limit
2085
L930
:
2086
iercr
= 1;
2087
goto
L1000
;
2088
// too many calls to FCN
2089
L940
:
2090
iercr
= 2;
2091
goto
L1000
;
2092
// cannot find next point
2093
L950
:
2094
iercr
= 3;
2095
// in any case
2096
L1000
:
2097
if
(
ldebug
) {
2098
itoohi
= 0;
2099
for
(i = 1; i <=
ipt
; ++i) {
2100
if
(
fYpt
[i-1] >
aim
+
fUp
) {
2101
fYpt
[i-1] =
aim
+
fUp
;
2102
fChpt
[i-1] =
'+'
;
2103
itoohi
= 1;
2104
}
2105
}
2106
fChpt
[
ipt
] = 0;
2107
chsign
=
"POSI"
;
2108
if
(
fXdircr
< 0)
chsign
=
"NEGA"
;
2109
if
(
fKe2cr
== 0) {
2110
Printf
(
" %sTIVE MINOS ERROR, PARAMETER %3d"
,
chsign
,
fKe1cr
);
2111
}
2112
if
(
itoohi
== 1) {
2113
Printf
(
"POINTS LABELLED '+' WERE TOO HIGH TO PLOT."
);
2114
}
2115
if
(
iercr
== 1) {
2116
Printf
(
"RIGHTMOST POINT IS UP AGAINST LIMIT."
);
2117
}
2118
mnplot
(
fXpt
,
fYpt
,
fChpt
,
ipt
,
fNpagwd
,
fNpagln
);
2119
}
2120
}
2121
2122
////////////////////////////////////////////////////////////////////////////////
2123
/// Makes sure that the current point is a local minimum
2124
///
2125
/// Makes sure that the current point is a local
2126
/// minimum and that the error matrix exists,
2127
/// or at least something good enough for MINOS and MNCONT
2128
2129
void
TMinuit::mncuve
()
2130
{
2131
/* Local variables */
2132
Double_t
dxdi
,
wint
;
2133
Int_t
ndex
,
iext
, i,
j
;
2134
2135
if
(
fISW
[3] < 1) {
2136
Printf
(
" FUNCTION MUST BE MINIMIZED BEFORE CALLING %s"
,(
const
char
*)
fCfrom
);
2137
fApsi
=
fEpsi
;
2138
mnmigr
();
2139
}
2140
if
(
fISW
[1] < 3) {
2141
mnhess
();
2142
if
(
fISW
[1] < 1) {
2143
mnwarn
(
"W"
,
fCfrom
,
"NO ERROR MATRIX. WILL IMPROVISE."
);
2144
for
(i = 1; i <=
fNpar
; ++i) {
2145
ndex
= i*(i-1) / 2;
2146
for
(
j
= 1;
j
<= i-1; ++
j
) {
2147
++
ndex
;
2148
fVhmat
[
ndex
-1] = 0;
2149
}
2150
++
ndex
;
2151
if
(
fG2
[i-1] <= 0) {
2152
wint
=
fWerr
[i-1];
2153
iext
=
fNexofi
[i-1];
2154
if
(
fNvarl
[
iext
-1] > 1) {
2155
mndxdi
(
fX
[i-1], i-1,
dxdi
);
2156
if
(
TMath::Abs
(
dxdi
) < .001)
wint
= .01;
2157
else
wint
/=
TMath::Abs
(
dxdi
);
2158
}
2159
fG2
[i-1] =
fUp
/ (
wint
*
wint
);
2160
}
2161
fVhmat
[
ndex
-1] = 2 /
fG2
[i-1];
2162
}
2163
fISW
[1] = 1;
2164
fDcovar
= 1;
2165
}
else
mnwerr
();
2166
}
2167
}
2168
2169
////////////////////////////////////////////////////////////////////////////////
2170
/// Calculates the first derivatives of FCN (GRD)
2171
///
2172
/// Calculates the first derivatives of FCN (GRD),
2173
/// either by finite differences or by transforming the user-
2174
/// supplied derivatives to internal coordinates,
2175
/// according to whether fISW[2] is zero or one.
2176
2177
void
TMinuit::mnderi
()
2178
{
2179
/* Local variables */
2180
Double_t
step,
dfmin
,
stepb4
,
dd
, df,
fs1
;
2181
Double_t
tlrstp
,
tlrgrd
,
epspri
,
optstp
,
stpmax
,
stpmin
,
fs2
,
grbfor
=0,
d1d2
,
xtf
;
2182
Int_t
icyc
,
ncyc
,
iint
,
iext
, i,
nparx
;
2183
Bool_t
ldebug
;
2184
2185
nparx
=
fNpar
;
2186
ldebug
=
fIdbg
[2] >= 1;
2187
if
(
fAmin
==
fUndefi
)
mnamin
();
2188
if
(
fISW
[2] == 1)
goto
L100
;
2189
2190
if
(
ldebug
) {
2191
// make sure starting at the right place
2192
mninex
(
fX
);
2193
nparx
=
fNpar
;
2194
Eval
(
nparx
,
fGin
,
fs1
,
fU
, 4); ++
fNfcn
;
2195
if
(
fs1
!=
fAmin
) {
2196
df =
fAmin
-
fs1
;
2197
mnwarn
(
"D"
,
"MNDERI"
,
TString::Format
(
"function value differs from AMIN by %12.3g"
,df));
2198
fAmin
=
fs1
;
2199
}
2200
Printf
(
" FIRST DERIVATIVE DEBUG PRINTOUT. MNDERI"
);
2201
Printf
(
" PAR DERIV STEP MINSTEP OPTSTEP D1-D2 2ND DRV"
);
2202
}
2203
dfmin
=
fEpsma2
*8*(
TMath::Abs
(
fAmin
) +
fUp
);
2204
if
(
fIstrat
<= 0) {
2205
ncyc
= 2;
2206
tlrstp
= .5;
2207
tlrgrd
= .1;
2208
}
else
if
(
fIstrat
== 1) {
2209
ncyc
= 3;
2210
tlrstp
= .3;
2211
tlrgrd
= .05;
2212
}
else
{
2213
ncyc
= 5;
2214
tlrstp
= .1;
2215
tlrgrd
= .02;
2216
}
2217
// loop over variable parameters
2218
for
(i = 1; i <=
fNpar
; ++i) {
2219
epspri
=
fEpsma2
+
TMath::Abs
(
fGrd
[i-1]*
fEpsma2
);
2220
// two-point derivatives always assumed necessary
2221
// maximum number of cycles over step size depends on strategy
2222
xtf
=
fX
[i-1];
2223
stepb4
= 0;
2224
// loop as little as possible here!/
2225
for
(
icyc
= 1;
icyc
<=
ncyc
; ++
icyc
) {
2226
// theoretically best step
2227
optstp
=
TMath::Sqrt
(
dfmin
/ (
TMath::Abs
(
fG2
[i-1]) +
epspri
));
2228
// step cannot decrease by more than a factor of ten
2229
step =
TMath::Max
(
optstp
,
TMath::Abs
(
fGstep
[i-1]*.1));
2230
// but if parameter has limits, max step size = 0.5
2231
if
(
fGstep
[i-1] < 0 && step > .5) step = .5;
2232
// and not more than ten times the previous step
2233
stpmax
=
TMath::Abs
(
fGstep
[i-1])*10;
2234
if
(step >
stpmax
) step =
stpmax
;
2235
// minimum step size allowed by machine precision
2236
stpmin
=
TMath::Abs
(
fEpsma2
*
fX
[i-1])*8;
2237
if
(step <
stpmin
) step =
stpmin
;
2238
// end of iterations if step change less than factor 2
2239
if
(
TMath::Abs
((step -
stepb4
) / step) <
tlrstp
)
goto
L50
;
2240
// take step positive
2241
stepb4
= step;
2242
if
(
fGstep
[i-1] > 0)
fGstep
[i-1] =
TMath::Abs
(step);
2243
else
fGstep
[i-1] = -
TMath::Abs
(step);
2244
stepb4
= step;
2245
fX
[i-1] =
xtf
+ step;
2246
mninex
(
fX
);
2247
Eval
(
nparx
,
fGin
,
fs1
,
fU
, 4); ++
fNfcn
;
2248
// take step negative
2249
fX
[i-1] =
xtf
- step;
2250
mninex
(
fX
);
2251
Eval
(
nparx
,
fGin
,
fs2
,
fU
, 4); ++
fNfcn
;
2252
grbfor
=
fGrd
[i-1];
2253
fGrd
[i-1] = (
fs1
-
fs2
) / (step*2);
2254
fG2
[i-1] = (
fs1
+
fs2
-
fAmin
*2) / (step*step);
2255
fX
[i-1] =
xtf
;
2256
if
(
ldebug
) {
2257
d1d2
= (
fs1
+
fs2
-
fAmin
*2) / step;
2258
Printf
(
"%4d%11.3g%11.3g%10.2g%10.2g%10.2g%10.2g"
,i,
fGrd
[i-1],step,
stpmin
,
optstp
,
d1d2
,
fG2
[i-1]);
2259
}
2260
// see if another iteration is necessary
2261
if
(
TMath::Abs
(
grbfor
-
fGrd
[i-1]) / (
TMath::Abs
(
fGrd
[i-1]) +
dfmin
/step) <
tlrgrd
)
2262
goto
L50
;
2263
}
2264
// end of ICYC loop. too many iterations
2265
if
(
ncyc
== 1)
goto
L50
;
2266
mnwarn
(
"D"
,
"MNDERI"
,
TString::Format
(
"First derivative not converged. %g%g"
,
fGrd
[i-1],
grbfor
));
2267
L50
:
2268
;
2269
}
2270
mninex
(
fX
);
2271
return
;
2272
// derivatives calc by fcn
2273
L100
:
2274
for
(
iint
= 1;
iint
<=
fNpar
; ++
iint
) {
2275
iext
=
fNexofi
[
iint
-1];
2276
if
(
fNvarl
[
iext
-1] <= 1) {
2277
fGrd
[
iint
-1] =
fGin
[
iext
-1];
2278
}
else
{
2279
dd
= (
fBlim
[
iext
-1] -
fAlim
[
iext
-1])*.5*
TMath::Cos
(
fX
[
iint
-1]);
2280
fGrd
[
iint
-1] =
fGin
[
iext
-1]*
dd
;
2281
}
2282
}
2283
}
2284
2285
////////////////////////////////////////////////////////////////////////////////
2286
/// Calculates the transformation factor between ext/internal values
2287
///
2288
/// calculates the transformation factor between external and
2289
/// internal parameter values. this factor is one for
2290
/// parameters which are not limited. called from MNEMAT.
2291
2292
void
TMinuit::mndxdi
(
Double_t
pint
,
Int_t
ipar,
Double_t
&
dxdi
)
2293
{
2294
Int_t
i =
fNexofi
[ipar];
2295
dxdi
= 1;
2296
if
(
fNvarl
[i-1] > 1) {
2297
dxdi
=
TMath::Abs
((
fBlim
[i-1] -
fAlim
[i-1])*
TMath::Cos
(
pint
))*.5;
2298
}
2299
}
2300
2301
////////////////////////////////////////////////////////////////////////////////
2302
/// Compute matrix eigen values
2303
2304
void
TMinuit::mneig
(
Double_t
*
a
,
Int_t
ndima
,
Int_t
n
,
Int_t
mits
,
Double_t
*
work
,
Double_t
precis
,
Int_t
&
ifault
)
2305
{
2306
/* System generated locals */
2307
Int_t
a_offset
;
2308
Double_t
d__1
;
2309
2310
/* Local variables */
2311
Double_t
b
,
c
,
f
,
h
,
r
, s,
hh
,
gl
,
pr
,
pt
;
2312
Int_t
i,
j
, k,
l
,
m
=0,
i0
,
i1
,
j1
, m1,
n1
;
2313
2314
// PRECIS is the machine precision EPSMAC
2315
/* Parameter adjustments */
2316
a_offset
=
ndima
+ 1;
2317
a
-=
a_offset
;
2318
--
work
;
2319
2320
/* Function Body */
2321
ifault
= 1;
2322
2323
i =
n
;
2324
for
(
i1
= 2;
i1
<=
n
; ++
i1
) {
2325
l
= i-2;
2326
f
=
a
[i + (i-1)*
ndima
];
2327
gl
= 0;
2328
2329
if
(
l
< 1)
goto
L25
;
2330
2331
for
(k = 1; k <=
l
; ++k) {
2332
d__1
=
a
[i + k*
ndima
];
2333
gl
+=
d__1
*
d__1
;
2334
}
2335
L25
:
2336
h
=
gl
+
f
*
f
;
2337
2338
if
(
gl
> 1
e
-35)
goto
L30
;
2339
2340
work
[i] = 0;
2341
work
[
n
+ i] =
f
;
2342
goto
L65
;
2343
L30
:
2344
++
l
;
2345
gl
=
TMath::Sqrt
(
h
);
2346
if
(
f
>= 0)
gl
= -
gl
;
2347
work
[
n
+ i] =
gl
;
2348
h
-=
f
*
gl
;
2349
a
[i + (i-1)*
ndima
] =
f
-
gl
;
2350
f
= 0;
2351
for
(
j
= 1;
j
<=
l
; ++
j
) {
2352
a
[
j
+ i*
ndima
] =
a
[i +
j
*
ndima
] /
h
;
2353
gl
= 0;
2354
for
(k = 1; k <=
j
; ++k) {
gl
+=
a
[
j
+ k*
ndima
]*
a
[i + k*
ndima
]; }
2355
if
(
j
>=
l
)
goto
L47
;
2356
j1
=
j
+ 1;
2357
for
(k =
j1
; k <=
l
; ++k) {
gl
+=
a
[k +
j
*
ndima
]*
a
[i + k*
ndima
]; }
2358
L47
:
2359
work
[
n
+
j
] =
gl
/
h
;
2360
f
+=
gl
*
a
[
j
+ i*
ndima
];
2361
}
2362
hh
=
f
/ (
h
+
h
);
2363
for
(
j
= 1;
j
<=
l
; ++
j
) {
2364
f
=
a
[i +
j
*
ndima
];
2365
gl
=
work
[
n
+
j
] -
hh
*
f
;
2366
work
[
n
+
j
] =
gl
;
2367
for
(k = 1; k <=
j
; ++k) {
2368
a
[
j
+ k*
ndima
] =
a
[
j
+ k*
ndima
] -
f
*
work
[
n
+ k] -
gl
*
a
[i + k*
ndima
];
2369
}
2370
}
2371
work
[i] =
h
;
2372
L65
:
2373
--i;
2374
}
2375
work
[1] = 0;
2376
work
[
n
+ 1] = 0;
2377
for
(i = 1; i <=
n
; ++i) {
2378
l
= i-1;
2379
if
(
work
[i] == 0 ||
l
== 0)
goto
L100
;
2380
2381
for
(
j
= 1;
j
<=
l
; ++
j
) {
2382
gl
= 0;
2383
for
(k = 1; k <=
l
; ++k) {
gl
+=
a
[i + k*
ndima
]*
a
[k +
j
*
ndima
]; }
2384
for
(k = 1; k <=
l
; ++k) {
a
[k +
j
*
ndima
] -=
gl
*
a
[k + i*
ndima
]; }
2385
}
2386
L100
:
2387
work
[i] =
a
[i + i*
ndima
];
2388
a
[i + i*
ndima
] = 1;
2389
if
(
l
== 0)
continue
;
2390
2391
for
(
j
= 1;
j
<=
l
; ++
j
) {
2392
a
[i +
j
*
ndima
] = 0;
2393
a
[
j
+ i*
ndima
] = 0;
2394
}
2395
}
2396
2397
n1
=
n
- 1;
2398
for
(i = 2; i <=
n
; ++i) {
2399
i0
=
n
+ i-1;
2400
work
[
i0
] =
work
[
i0
+ 1];
2401
}
2402
work
[
n
+
n
] = 0;
2403
b
= 0;
2404
f
= 0;
2405
for
(
l
= 1;
l
<=
n
; ++
l
) {
2406
j
= 0;
2407
h
=
precis
*(
TMath::Abs
(
work
[
l
]) +
TMath::Abs
(
work
[
n
+
l
]));
2408
if
(
b
<
h
)
b
=
h
;
2409
for
(m1 =
l
; m1 <=
n
; ++m1) {
2410
m
= m1;
2411
if
(
TMath::Abs
(
work
[
n
+
m
]) <=
b
)
goto
L150
;
2412
}
2413
2414
L150
:
2415
if
(
m
==
l
)
goto
L205
;
2416
2417
L160
:
2418
if
(
j
==
mits
)
return
;
2419
++
j
;
2420
pt
= (
work
[
l
+ 1] -
work
[
l
]) / (
work
[
n
+
l
]*2);
2421
r
=
TMath::Sqrt
(
pt
*
pt
+ 1);
2422
pr
=
pt
+
r
;
2423
if
(
pt
< 0)
pr
=
pt
-
r
;
2424
2425
h
=
work
[
l
] -
work
[
n
+
l
] /
pr
;
2426
for
(i =
l
; i <=
n
; ++i) {
work
[i] -=
h
; }
2427
f
+=
h
;
2428
pt
=
work
[
m
];
2429
c
= 1;
2430
s = 0;
2431
m1 =
m
- 1;
2432
i =
m
;
2433
for
(
i1
=
l
;
i1
<= m1; ++
i1
) {
2434
j
= i;
2435
--i;
2436
gl
=
c
*
work
[
n
+ i];
2437
h
=
c
*
pt
;
2438
if
(
TMath::Abs
(
pt
) >=
TMath::Abs
(
work
[
n
+ i]))
goto
L180
;
2439
2440
c
=
pt
/
work
[
n
+ i];
2441
r
=
TMath::Sqrt
(
c
*
c
+ 1);
2442
work
[
n
+
j
] = s*
work
[
n
+ i]*
r
;
2443
s = 1 /
r
;
2444
c
/=
r
;
2445
goto
L190
;
2446
L180
:
2447
c
=
work
[
n
+ i] /
pt
;
2448
r
=
TMath::Sqrt
(
c
*
c
+ 1);
2449
work
[
n
+
j
] = s*
pt
*
r
;
2450
s =
c
/
r
;
2451
c
= 1 /
r
;
2452
L190
:
2453
pt
=
c
*
work
[i] - s*
gl
;
2454
work
[
j
] =
h
+ s*(
c
*
gl
+ s*
work
[i]);
2455
for
(k = 1; k <=
n
; ++k) {
2456
h
=
a
[k +
j
*
ndima
];
2457
a
[k +
j
*
ndima
] = s*
a
[k + i*
ndima
] +
c
*
h
;
2458
a
[k + i*
ndima
] =
c
*
a
[k + i*
ndima
] - s*
h
;
2459
}
2460
}
2461
work
[
n
+
l
] = s*
pt
;
2462
work
[
l
] =
c
*
pt
;
2463
2464
if
(
TMath::Abs
(
work
[
n
+
l
]) >
b
)
goto
L160
;
2465
2466
L205
:
2467
work
[
l
] +=
f
;
2468
}
2469
for
(i = 1; i <=
n1
; ++i) {
2470
k = i;
2471
pt
=
work
[i];
2472
i1
= i + 1;
2473
for
(
j
=
i1
;
j
<=
n
; ++
j
) {
2474
if
(
work
[
j
] >=
pt
)
continue
;
2475
k =
j
;
2476
pt
=
work
[
j
];
2477
}
2478
2479
if
(k == i)
continue
;
2480
2481
work
[k] =
work
[i];
2482
work
[i] =
pt
;
2483
for
(
j
= 1;
j
<=
n
; ++
j
) {
2484
pt
=
a
[
j
+ i*
ndima
];
2485
a
[
j
+ i*
ndima
] =
a
[
j
+ k*
ndima
];
2486
a
[
j
+ k*
ndima
] =
pt
;
2487
}
2488
}
2489
ifault
= 0;
2490
}
2491
2492
////////////////////////////////////////////////////////////////////////////////
2493
/// Calculates the external error matrix from the internal matrix
2494
///
2495
/// Note that if the matrix is declared like Double_t matrix[5][5]
2496
/// in the calling program, one has to call mnemat with, eg
2497
///
2498
/// gMinuit->mnemat(&matrix[0][0],5);
2499
2500
void
TMinuit::mnemat
(
Double_t
*
emat
,
Int_t
ndim)
2501
{
2502
/* System generated locals */
2503
Int_t
emat_dim1
,
emat_offset
;
2504
2505
/* Local variables */
2506
Double_t
dxdi
,
dxdj
;
2507
Int_t
i,
j
, k,
npard
,
k2
,
kk
, iz,
nperln
,
kga
,
kgb
;
2508
TString
ctemp
;
2509
2510
/* Parameter adjustments */
2511
emat_dim1
= ndim;
2512
emat_offset
=
emat_dim1
+ 1;
2513
emat
-=
emat_offset
;
2514
2515
/* Function Body */
2516
if
(
fISW
[1] < 1)
return
;
2517
if
(
fISW
[4] >= 2) {
2518
Printf
(
" EXTERNAL ERROR MATRIX. NDIM=%4d NPAR=%3d ERR DEF=%g"
,ndim,
fNpar
,
fUp
);
2519
}
2520
// size of matrix to be printed
2521
npard
=
fNpar
;
2522
if
(ndim <
fNpar
) {
2523
npard
= ndim;
2524
if
(
fISW
[4] >= 0) {
2525
Printf
(
" USER-DIMENSIONED ARRAY EMAT NOT BIG ENOUGH. REDUCED MATRIX CALCULATED."
);
2526
}
2527
}
2528
// NPERLN is the number of elements that fit on one line
2529
2530
nperln
= (
fNpagwd
- 5) / 10;
2531
nperln
=
TMath::Min
(
nperln
,13);
2532
if
(
fISW
[4] >= 1 &&
npard
>
nperln
) {
2533
Printf
(
" ELEMENTS ABOVE DIAGONAL ARE NOT PRINTED."
);
2534
}
2535
// I counts the rows of the matrix
2536
for
(i = 1; i <=
npard
; ++i) {
2537
mndxdi
(
fX
[i-1], i-1,
dxdi
);
2538
kga
= i*(i-1) / 2;
2539
for
(
j
= 1;
j
<= i; ++
j
) {
2540
mndxdi
(
fX
[
j
-1],
j
-1,
dxdj
);
2541
kgb
=
kga
+
j
;
2542
emat
[i +
j
*
emat_dim1
] =
dxdi
*
fVhmat
[
kgb
-1]*
dxdj
*
fUp
;
2543
emat
[
j
+ i*
emat_dim1
] =
emat
[i +
j
*
emat_dim1
];
2544
}
2545
}
2546
// IZ is number of columns to be printed in row I
2547
if
(
fISW
[4] >= 2) {
2548
for
(i = 1; i <=
npard
; ++i) {
2549
iz =
npard
;
2550
if
(
npard
>=
nperln
) iz = i;
2551
ctemp
=
" "
;
2552
for
(k = 1;
nperln < 0 ? k >
= iz : k <= iz; k +=
nperln
) {
2553
k2
= k +
nperln
- 1;
2554
if
(
k2
> iz)
k2
= iz;
2555
for
(
kk
= k;
kk
<=
k2
; ++
kk
) {
2556
ctemp
+=
TString::Format
(
"%10.3e "
,
emat
[i +
kk
*
emat_dim1
]);
2557
}
2558
Printf
(
"%s"
,(
const
char
*)
ctemp
);
2559
}
2560
}
2561
}
2562
}
2563
2564
////////////////////////////////////////////////////////////////////////////////
2565
/// Utility routine to get MINOS errors
2566
///
2567
/// Called by user.
2568
///
2569
/// NUMBER is the parameter number
2570
///
2571
/// values returned by MNERRS:
2572
/// - EPLUS, EMINUS are MINOS errors of parameter NUMBER,
2573
/// - EPARAB is 'parabolic' error (from error matrix).
2574
/// (Errors not calculated are set = 0)
2575
/// - GCC is global correlation coefficient from error matrix
2576
2577
void
TMinuit::mnerrs
(
Int_t
number,
Double_t
&eplus,
Double_t
&
eminus
,
Double_t
&
eparab
,
Double_t
&
gcc
)
2578
{
2579
Double_t
dxdi
;
2580
Int_t
ndiag
,
iin
,
iex
;
2581
2582
iex
= number+1;
2583
2584
if
(
iex
>
fNu
||
iex
<= 0)
goto
L900
;
2585
iin
=
fNiofex
[
iex
-1];
2586
if
(
iin
<= 0)
goto
L900
;
2587
2588
// IEX is external number, IIN is internal number
2589
eplus =
fErp
[
iin
-1];
2590
if
(eplus ==
fUndefi
) eplus = 0;
2591
eminus
=
fErn
[
iin
-1];
2592
if
(
eminus
==
fUndefi
)
eminus
= 0;
2593
mndxdi
(
fX
[
iin
-1],
iin
-1,
dxdi
);
2594
ndiag
=
iin
*(
iin
+ 1) / 2;
2595
eparab
=
TMath::Abs
(
dxdi
*
TMath::Sqrt
(
TMath::Abs
(
fUp
*
fVhmat
[
ndiag
- 1])));
2596
// global correlation coefficient
2597
gcc
= 0;
2598
if
(
fISW
[1] < 2)
return
;
2599
gcc
=
fGlobcc
[
iin
-1];
2600
return
;
2601
// ERROR. parameter number not valid
2602
L900
:
2603
eplus = 0;
2604
eminus
= 0;
2605
eparab
= 0;
2606
gcc
= 0;
2607
}
2608
2609
////////////////////////////////////////////////////////////////////////////////
2610
/// Evaluates the function being analysed by MNCROS
2611
///
2612
/// Evaluates the function being analysed by MNCROS, which is
2613
/// generally the minimum of FCN with respect to all remaining
2614
/// variable parameters. The class data members contains the
2615
/// data necessary to know the values of U(KE1CR) and U(KE2CR)
2616
/// to be used, namely U(KE1CR) = XMIDCR + ANEXT*XDIRCR
2617
/// and (if KE2CR .NE. 0) U(KE2CR) = YMIDCR + ANEXT*YDIRCR
2618
2619
void
TMinuit::mneval
(
Double_t
anext
,
Double_t
&
fnext
,
Int_t
&
ierev
)
2620
{
2621
Int_t
nparx
;
2622
2623
fU
[
fKe1cr
-1] =
fXmidcr
+
anext
*
fXdircr
;
2624
if
(
fKe2cr
!= 0)
fU
[
fKe2cr
-1] =
fYmidcr
+
anext
*
fYdircr
;
2625
mninex
(
fX
);
2626
nparx
=
fNpar
;
2627
Eval
(
nparx
,
fGin
,
fnext
,
fU
, 4); ++
fNfcn
;
2628
ierev
= 0;
2629
if
(
fNpar
> 0) {
2630
fItaur
= 1;
2631
fAmin
=
fnext
;
2632
fISW
[0] = 0;
2633
mnmigr
();
2634
fItaur
= 0;
2635
fnext
=
fAmin
;
2636
if
(
fISW
[0] >= 1)
ierev
= 1;
2637
if
(
fISW
[3] < 1)
ierev
= 2;
2638
}
2639
}
2640
2641
////////////////////////////////////////////////////////////////////////////////
2642
/// Interprets a command and takes appropriate action
2643
///
2644
/// either directly by skipping to the corresponding code in
2645
/// MNEXCM, or by setting up a call to a function
2646
///
2647
/// recognized MINUIT commands:
2648
/// obsolete commands:
2649
/// IERFLG is now (94.5) defined the same as ICONDN in MNCOMD =
2650
/// - 0: command executed normally
2651
/// - 1: command is blank, ignored
2652
/// - 2: command line unreadable, ignored
2653
/// - 3: unknown command, ignored
2654
/// - 4: abnormal termination (e.g., MIGRAD not converged)
2655
/// - 9: reserved
2656
/// - 10: END command
2657
/// - 11: EXIT or STOP command
2658
/// - 12: RETURN command
2659
///
2660
/// see also
2661
/// [the possible list of all Minuit commands](https://root.cern/sites/d35c7d8c.web.cern.ch/files/minuit.pdf).
2662
2663
void
TMinuit::mnexcm
(
const
char
*
command
,
Double_t
*
plist
,
Int_t
llist
,
Int_t
&
ierflg
)
2664
{
2665
/* Initialized data */
2666
2667
TString
comand
=
command
;
2668
static
const
char
*
const
cname
[40] = {
2669
"MINImize "
,
2670
"SEEk "
,
2671
"SIMplex "
,
2672
"MIGrad "
,
2673
"MINOs "
,
2674
"SET xxx "
,
2675
"SHOw xxx "
,
2676
"TOP of pag"
,
2677
"FIX "
,
2678
"REStore "
,
2679
"RELease "
,
2680
"SCAn "
,
2681
"CONtour "
,
2682
"HESse "
,
2683
"SAVe "
,
2684
"IMProve "
,
2685
"CALl fcn "
,
2686
"STAndard "
,
2687
"END "
,
2688
"EXIt "
,
2689
"RETurn "
,
2690
"CLEar "
,
2691
"HELP "
,
2692
"MNContour "
,
2693
"STOp "
,
2694
"JUMp "
,
2695
" "
,
2696
" "
,
2697
" "
,
2698
" "
,
2699
" "
,
2700
" "
,
2701
" "
,
2702
"COVARIANCE"
,
2703
"PRINTOUT "
,
2704
"GRADIENT "
,
2705
"MATOUT "
,
2706
"ERROR DEF "
,
2707
"LIMITS "
,
2708
"PUNCH "
};
2709
2710
Int_t
nntot
= 40;
2711
2712
/* Local variables */
2713
Double_t
step,
xptu
[101],
yptu
[101],
f
,
rno
;
2714
Int_t
icol
,
kcol
,
ierr
,
iint
,
iext
,
lnow
,
nptu
, i,
iflag
,
ierrf
;
2715
Int_t
ilist
,
nparx
,
izero
,
nf
,
lk
, it,
iw
,
inonde
,
nsuper
;
2716
Int_t
it2
,
ke1
,
ke2
,
nowprt
,
kll
,
krl
;
2717
TString
chwhy
,
c26
,
cvblnk
,
cneway
,
comd
;
2718
TString
ctemp
;
2719
Bool_t
lfreed
,
ltofix
,
lfixed
;
2720
2721
// alphabetical order of command names!
2722
2723
/* Function Body */
2724
2725
lk
=
comand
.Length();
2726
if
(
lk
> 20)
lk
= 20;
2727
fCword
=
comand
;
2728
fCword
.
ToUpper
();
2729
// Copy the first MAXP arguments into WORD7, making
2730
// sure that WORD7(1)=0 if LLIST=0
2731
for
(
iw
= 1;
iw
<=
fMaxpar
; ++
iw
) {
2732
fWord7
[
iw
-1] = 0;
2733
if
(
iw
<=
llist
)
fWord7
[
iw
-1] =
plist
[
iw
-1];
2734
}
2735
++
fIcomnd
;
2736
fNfcnlc
=
fNfcn
;
2737
if
(
fCword
(0,7) !=
"SET PRI"
||
fWord7
[0] >= 0) {
2738
if
(
fISW
[4] >= 0) {
2739
lnow
=
llist
;
2740
if
(
lnow
> 4)
lnow
= 4;
2741
Printf
(
" **********"
);
2742
ctemp
.Form(
" **%5d **%s"
,
fIcomnd
,(
const
char
*)
fCword
);
2743
for
(i = 1; i <=
lnow
; ++i) {
2744
ctemp
+=
TString::Format
(
"%12.4g"
,
plist
[i-1]);
2745
}
2746
Printf
(
"%s"
,(
const
char
*)
ctemp
);
2747
inonde
= 0;
2748
if
(
llist
>
lnow
) {
2749
kll
=
llist
;
2750
if
(
llist
>
fMaxpar
) {
2751
inonde
= 1;
2752
kll
=
fMaxpar
;
2753
}
2754
Printf
(
" ***********"
);
2755
for
(i =
lnow
+ 1; i <=
kll
; ++i) {
2756
Printf
(
"%12.4g"
,
plist
[i-1]);
2757
}
2758
}
2759
Printf
(
" **********"
);
2760
if
(
inonde
> 0) {
2761
Printf
(
" ERROR: ABOVE CALL TO MNEXCM TRIED TO PASS MORE THAN %d PARAMETERS."
,
fMaxpar
);
2762
}
2763
}
2764
}
2765
fNfcnmx
=
Int_t
(
fWord7
[0]);
2766
if
(
fNfcnmx
<= 0) {
2767
fNfcnmx
=
fNpar
*100 + 200 +
fNpar
*
fNpar
*5;
2768
}
2769
fEpsi
=
fWord7
[1];
2770
if
(
fEpsi
<= 0) {
2771
fEpsi
=
fUp
*.1;
2772
}
2773
fLnewmn
=
kFALSE
;
2774
fLphead
=
kTRUE
;
2775
fISW
[0] = 0;
2776
ierflg
= 0;
2777
// look for command in list CNAME
2778
ctemp
=
fCword
(0,3);
2779
for
(i = 1; i <=
nntot
; ++i) {
2780
if
(
strncmp
(
ctemp
.Data(),
cname
[i-1],3) == 0)
goto
L90
;
2781
}
2782
Printf
(
"UNKNOWN COMMAND IGNORED:%s"
,
comand
.Data());
2783
ierflg
= 3;
2784
return
;
2785
// normal case: recognized MINUIT command
2786
L90
:
2787
if
(
fCword
(0,4) ==
"MINO"
) i = 5;
2788
if
(i != 6 && i != 7 && i != 8 && i != 23) {
2789
fCfrom
=
cname
[i-1];
2790
fNfcnfr
=
fNfcn
;
2791
}
2792
// 1 2 3 4 5 6 7 8 9 10
2793
switch
(i) {
2794
case
1:
goto
L400
;
2795
case
2:
goto
L200
;
2796
case
3:
goto
L300
;
2797
case
4:
goto
L400
;
2798
case
5:
goto
L500
;
2799
case
6:
goto
L700
;
2800
case
7:
goto
L700
;
2801
case
8:
goto
L800
;
2802
case
9:
goto
L900
;
2803
case
10:
goto
L1000
;
2804
case
11:
goto
L1100
;
2805
case
12:
goto
L1200
;
2806
case
13:
goto
L1300
;
2807
case
14:
goto
L1400
;
2808
case
15:
goto
L1500
;
2809
case
16:
goto
L1600
;
2810
case
17:
goto
L1700
;
2811
case
18:
goto
L1800
;
2812
case
19:
goto
L1900
;
2813
case
20:
goto
L1900
;
2814
case
21:
goto
L1900
;
2815
case
22:
goto
L2200
;
2816
case
23:
goto
L2300
;
2817
case
24:
goto
L2400
;
2818
case
25:
goto
L1900
;
2819
case
26:
goto
L2600
;
2820
case
27:
goto
L3300
;
2821
case
28:
goto
L3300
;
2822
case
29:
goto
L3300
;
2823
case
30:
goto
L3300
;
2824
case
31:
goto
L3300
;
2825
case
32:
goto
L3300
;
2826
case
33:
goto
L3300
;
2827
case
34:
goto
L3400
;
2828
case
35:
goto
L3500
;
2829
case
36:
goto
L3600
;
2830
case
37:
goto
L3700
;
2831
case
38:
goto
L3800
;
2832
case
39:
goto
L3900
;
2833
case
40:
goto
L4000
;
2834
}
2835
// seek
2836
L200
:
2837
mnseek
();
2838
return
;
2839
// simplex
2840
L300
:
2841
mnsimp
();
2842
if
(
fISW
[3] < 1)
ierflg
= 4;
2843
return
;
2844
// migrad, minimize
2845
L400
:
2846
nf
=
fNfcn
;
2847
fApsi
=
fEpsi
;
2848
mnmigr
();
2849
mnwerr
();
2850
if
(
fISW
[3] >= 1)
return
;
2851
ierflg
= 4;
2852
if
(
fISW
[0] == 1)
return
;
2853
if
(
fCword
(0,3) ==
"MIG"
)
return
;
2854
2855
fNfcnmx
=
fNfcnmx
+
nf
-
fNfcn
;
2856
nf
=
fNfcn
;
2857
mnsimp
();
2858
if
(
fISW
[0] == 1)
return
;
2859
fNfcnmx
=
fNfcnmx
+
nf
-
fNfcn
;
2860
mnmigr
();
2861
if
(
fISW
[3] >= 1)
ierflg
= 0;
2862
mnwerr
();
2863
return
;
2864
// minos
2865
L500
:
2866
nsuper
=
fNfcn
+ ((
fNpar
+ 1) << 1)*
fNfcnmx
;
2867
// possible loop over new minima
2868
fEpsi
=
fUp
*.1;
2869
L510
:
2870
fCfrom
=
cname
[i-1];
// ensure that mncuve complains about MINOS not MIGRAD
2871
mncuve
();
2872
mnmnos
();
2873
if
(!
fLnewmn
)
return
;
2874
mnrset
(0);
2875
mnmigr
();
2876
mnwerr
();
2877
if
(
fNfcn
<
nsuper
)
goto
L510
;
2878
Printf
(
" TOO MANY FUNCTION CALLS. MINOS GIVES UP"
);
2879
ierflg
= 4;
2880
return
;
2881
// set, show
2882
L700
:
2883
mnset
();
2884
return
;
2885
// top of page
2886
2887
L800
:
2888
Printf
(
"1"
);
2889
return
;
2890
// fix
2891
L900
:
2892
ltofix
=
kTRUE
;
2893
// (also release)
2894
L901
:
2895
lfreed
=
kFALSE
;
2896
lfixed
=
kFALSE
;
2897
if
(
llist
== 0) {
2898
Printf
(
"%s: NO PARAMETERS REQUESTED "
,(
const
char
*)
fCword
);
2899
return
;
2900
}
2901
for
(
ilist
= 1;
ilist
<=
llist
; ++
ilist
) {
2902
iext
=
Int_t
(
plist
[
ilist
-1]);
2903
chwhy
=
" IS UNDEFINED."
;
2904
if
(
iext
<= 0)
goto
L930
;
2905
if
(
iext
>
fNu
)
goto
L930
;
2906
if
(
fNvarl
[
iext
-1] < 0)
goto
L930
;
2907
chwhy
=
" IS CONSTANT. "
;
2908
if
(
fNvarl
[
iext
-1] == 0)
goto
L930
;
2909
iint
=
fNiofex
[
iext
-1];
2910
if
(
ltofix
) {
2911
chwhy
=
" ALREADY FIXED."
;
2912
if
(
iint
== 0)
goto
L930
;
2913
mnfixp
(
iint
-1,
ierr
);
2914
if
(
ierr
== 0)
lfixed
=
kTRUE
;
2915
else
ierflg
= 4;
2916
}
else
{
2917
chwhy
=
" ALREADY VARIABLE."
;
2918
if
(
iint
> 0)
goto
L930
;
2919
krl
= -abs(
iext
);
2920
mnfree
(
krl
);
2921
lfreed
=
kTRUE
;
2922
}
2923
continue
;
2924
L930
:
2925
if
(
fISW
[4] >= 0)
Printf
(
" PARAMETER %4d %s IGNORED."
,
iext
,(
const
char
*)
chwhy
);
2926
}
2927
if
(
lfreed
||
lfixed
)
mnrset
(0);
2928
if
(
lfreed
) {
2929
fISW
[1] = 0;
2930
fDcovar
= 1;
2931
fEDM
=
fBigedm
;
2932
fISW
[3] = 0;
2933
}
2934
mnwerr
();
2935
if
(
fISW
[4] > 1)
mnprin
(5,
fAmin
);
2936
return
;
2937
// restore
2938
L1000
:
2939
it =
Int_t
(
fWord7
[0]);
2940
if
(it > 1 || it < 0)
goto
L1005
;
2941
lfreed
=
fNpfix
> 0;
2942
mnfree
(it);
2943
if
(
lfreed
) {
2944
mnrset
(0);
2945
fISW
[1] = 0;
2946
fDcovar
= 1;
2947
fEDM
=
fBigedm
;
2948
}
2949
return
;
2950
L1005
:
2951
Printf
(
" IGNORED. UNKNOWN ARGUMENT:%4d"
,it);
2952
ierflg
= 3;
2953
return
;
2954
// release
2955
L1100
:
2956
ltofix
=
kFALSE
;
2957
goto
L901
;
2958
// scan
2959
L1200
:
2960
iext
=
Int_t
(
fWord7
[0]);
2961
if
(
iext
<= 0)
goto
L1210
;
2962
it2
= 0;
2963
if
(
iext
<=
fNu
)
it2
=
fNiofex
[
iext
-1];
2964
if
(
it2
<= 0)
goto
L1250
;
2965
2966
L1210
:
2967
mnscan
();
2968
return
;
2969
L1250
:
2970
Printf
(
" PARAMETER %4d NOT VARIABLE."
,
iext
);
2971
ierflg
= 3;
2972
return
;
2973
// contour
2974
L1300
:
2975
ke1
=
Int_t
(
fWord7
[0]);
2976
ke2
=
Int_t
(
fWord7
[1]);
2977
if
(
ke1
== 0) {
2978
if
(
fNpar
== 2) {
2979
ke1
=
fNexofi
[0];
2980
ke2
=
fNexofi
[1];
2981
}
else
{
2982
Printf
(
"%s: NO PARAMETERS REQUESTED "
,(
const
char
*)
fCword
);
2983
ierflg
= 3;
2984
return
;
2985
}
2986
}
2987
fNfcnmx
= 1000;
2988
mncntr
(
ke1
-1,
ke2
-1,
ierrf
);
2989
if
(
ierrf
> 0)
ierflg
= 3;
2990
return
;
2991
// hesse
2992
L1400
:
2993
mnhess
();
2994
mnwerr
();
2995
if
(
fISW
[4] >= 0)
mnprin
(2,
fAmin
);
2996
if
(
fISW
[4] >= 1)
mnmatu
(1);
2997
return
;
2998
// save
2999
L1500
:
3000
mnsave
();
3001
return
;
3002
// improve
3003
L1600
:
3004
mncuve
();
3005
mnimpr
();
3006
if
(
fLnewmn
)
goto
L400
;
3007
ierflg
= 4;
3008
return
;
3009
// call fcn
3010
L1700
:
3011
iflag
=
Int_t
(
fWord7
[0]);
3012
nparx
=
fNpar
;
3013
f
=
fUndefi
;
3014
Eval
(
nparx
,
fGin
,
f
,
fU
,
iflag
); ++
fNfcn
;
3015
nowprt
= 0;
3016
if
(
f
!=
fUndefi
) {
3017
if
(
fAmin
==
fUndefi
) {
3018
fAmin
=
f
;
3019
nowprt
= 1;
3020
}
else
if
(
f
<
fAmin
) {
3021
fAmin
=
f
;
3022
nowprt
= 1;
3023
}
3024
if
(
fISW
[4] >= 0 &&
iflag
<= 5 &&
nowprt
== 1) {
3025
mnprin
(5,
fAmin
);
3026
}
3027
if
(
iflag
== 3)
fFval3
=
f
;
3028
}
3029
if
(
iflag
> 5)
mnrset
(1);
3030
return
;
3031
// standard
3032
L1800
:
3033
// stand();
3034
return
;
3035
// return, stop, end, exit
3036
L1900
:
3037
it =
Int_t
(
fWord7
[0]);
3038
if
(
fFval3
!=
fAmin
&& it == 0) {
3039
iflag
= 3;
3040
if
(
fISW
[4] >= 0)
Printf
(
" CALL TO USER FUNCTION WITH IFLAG = 3"
);
3041
nparx
=
fNpar
;
3042
Eval
(
nparx
,
fGin
,
f
,
fU
,
iflag
); ++
fNfcn
;
3043
}
3044
ierflg
= 11;
3045
if
(
fCword
(0,3) ==
"END"
)
ierflg
= 10;
3046
if
(
fCword
(0,3) ==
"RET"
)
ierflg
= 12;
3047
return
;
3048
// clear
3049
L2200
:
3050
mncler
();
3051
if
(
fISW
[4] >= 1) {
3052
Printf
(
" MINUIT MEMORY CLEARED. NO PARAMETERS NOW DEFINED."
);
3053
}
3054
return
;
3055
// help
3056
L2300
:
3057
kcol
= 0;
3058
for
(
icol
= 5;
icol
<=
lk
; ++
icol
) {
3059
if
(
fCword
[
icol
-1] ==
' '
)
continue
;
3060
kcol
=
icol
;
3061
goto
L2320
;
3062
}
3063
L2320
:
3064
if
(
kcol
== 0)
comd
=
"* "
;
3065
else
comd
=
fCword
(
kcol
-1,
lk
-
kcol
+1);
3066
mnhelp
(
comd
);
3067
return
;
3068
// MNContour
3069
L2400
:
3070
fEpsi
=
fUp
*.05;
3071
ke1
=
Int_t
(
fWord7
[0]);
3072
ke2
=
Int_t
(
fWord7
[1]);
3073
if
(
ke1
== 0 &&
fNpar
== 2) {
3074
ke1
=
fNexofi
[0];
3075
ke2
=
fNexofi
[1];
3076
}
3077
nptu
=
Int_t
(
fWord7
[2]);
3078
if
(
nptu
<= 0)
nptu
= 20;
3079
if
(
nptu
> 101)
nptu
= 101;
3080
fNfcnmx
= (
nptu
+ 5)*100*(
fNpar
+ 1);
3081
mncont
(
ke1
-1,
ke2
-1,
nptu
,
xptu
,
yptu
,
ierrf
);
3082
if
(
ierrf
<
nptu
)
ierflg
= 4;
3083
if
(
ierrf
== -1)
ierflg
= 3;
3084
return
;
3085
// jump
3086
L2600
:
3087
step =
fWord7
[0];
3088
if
(step <= 0) step = 2;
3089
rno
= 0;
3090
izero
= 0;
3091
for
(i = 1; i <=
fNpar
; ++i) {
3092
mnrn15
(
rno
,
izero
);
3093
rno
=
rno
*2 - 1;
3094
fX
[i-1] +=
rno
*step*
fWerr
[i-1];
3095
}
3096
mninex
(
fX
);
3097
mnamin
();
3098
mnrset
(0);
3099
return
;
3100
// blank line
3101
L3300
:
3102
Printf
(
" BLANK COMMAND IGNORED."
);
3103
ierflg
= 1;
3104
return
;
3105
// obsolete commands
3106
// covariance
3107
L3400
:
3108
Printf
(
" THE *COVARIANCE* COMMAND IS OSBSOLETE. THE COVARIANCE MATRIX IS NOW SAVED IN A DIFFERENT FORMAT WITH THE *SAVE* COMMAND AND READ IN WITH:*SET COVARIANCE*"
);
3109
ierflg
= 3;
3110
return
;
3111
// printout
3112
L3500
:
3113
cneway
=
"SET PRInt "
;
3114
goto
L3100
;
3115
// gradient
3116
L3600
:
3117
cneway
=
"SET GRAd "
;
3118
goto
L3100
;
3119
// matout
3120
L3700
:
3121
cneway
=
"SHOW COVar"
;
3122
goto
L3100
;
3123
// error def
3124
L3800
:
3125
cneway
=
"SET ERRdef"
;
3126
goto
L3100
;
3127
// limits
3128
L3900
:
3129
cneway
=
"SET LIMits"
;
3130
goto
L3100
;
3131
// punch
3132
L4000
:
3133
cneway
=
"SAVE "
;
3134
// come from obsolete commands
3135
L3100
:
3136
Printf
(
" OBSOLETE COMMAND:%s PLEASE USE:%s"
,(
const
char
*)
fCword
3137
,(
const
char
*)
cneway
);
3138
fCword
=
cneway
;
3139
if
(
fCword
==
"SAVE "
)
goto
L1500
;
3140
goto
L700
;
3141
//
3142
}
3143
3144
////////////////////////////////////////////////////////////////////////////////
3145
/// Transforms the external parameter values U to internal values
3146
///
3147
/// Transforms the external parameter values U to internal
3148
/// values in the dense array PINT.
3149
3150
void
TMinuit::mnexin
(
Double_t
*
pint
)
3151
{
3152
Double_t
pinti
;
3153
Int_t
iint
,
iext
;
3154
3155
fLimset
=
kFALSE
;
3156
for
(
iint
= 1;
iint
<=
fNpar
; ++
iint
) {
3157
iext
=
fNexofi
[
iint
-1];
3158
mnpint
(
fU
[
iext
-1],
iext
-1,
pinti
);
3159
pint
[
iint
-1] =
pinti
;
3160
}
3161
}
3162
3163
////////////////////////////////////////////////////////////////////////////////
3164
/// Removes parameter IINT from the internal parameter list
3165
///
3166
/// and arranges the rest of the list to fill the hole.
3167
3168
void
TMinuit::mnfixp
(
Int_t
iint1
,
Int_t
&
ierr
)
3169
{
3170
/* Local variables */
3171
Double_t
yyover
;
3172
Int_t
kold
,
nold
,
ndex
,
knew
,
iext
, i,
j
,
m
,
n
,
lc
, ik;
3173
3174
// first see if it can be done
3175
ierr
= 0;
3176
Int_t
iint
=
iint1
+1;
3177
if
(
iint
>
fNpar
||
iint
<= 0) {
3178
ierr
= 1;
3179
Printf
(
" MINUIT ERROR. ARGUMENT TO MNFIXP=%4d"
,
iint
);
3180
return
;
3181
}
3182
iext
=
fNexofi
[
iint
-1];
3183
if
(
fNpfix
>=
fMaxpar
) {
3184
ierr
= 1;
3185
Printf
(
" MINUIT CANNOT FIX PARAMETER %4d MAXIMUM NUMBER THAT CAN BE FIXED IS %d"
,
iext
,
fMaxpar
);
3186
return
;
3187
}
3188
// reduce number of variable parameters by one
3189
3190
fNiofex
[
iext
-1] = 0;
3191
nold
=
fNpar
;
3192
--
fNpar
;
3193
// save values in case parameter is later restored
3194
3195
++
fNpfix
;
3196
fIpfix
[
fNpfix
-1] =
iext
;
3197
lc
=
iint
;
3198
fXs
[
fNpfix
-1] =
fX
[
lc
-1];
3199
fXts
[
fNpfix
-1] =
fXt
[
lc
-1];
3200
fDirins
[
fNpfix
-1] =
fWerr
[
lc
-1];
3201
fGrds
[
fNpfix
-1] =
fGrd
[
lc
-1];
3202
fG2s
[
fNpfix
-1] =
fG2
[
lc
-1];
3203
fGsteps
[
fNpfix
-1] =
fGstep
[
lc
-1];
3204
// shift values for other parameters to fill hole
3205
for
(ik =
iext
+ 1; ik <=
fNu
; ++ik) {
3206
if
(
fNiofex
[ik-1] > 0) {
3207
lc
=
fNiofex
[ik-1] - 1;
3208
fNiofex
[ik-1] =
lc
;
3209
fNexofi
[
lc
-1] = ik;
3210
fX
[
lc
-1] =
fX
[
lc
];
3211
fXt
[
lc
-1] =
fXt
[
lc
];
3212
fDirin
[
lc
-1] =
fDirin
[
lc
];
3213
fWerr
[
lc
-1] =
fWerr
[
lc
];
3214
fGrd
[
lc
-1] =
fGrd
[
lc
];
3215
fG2
[
lc
-1] =
fG2
[
lc
];
3216
fGstep
[
lc
-1] =
fGstep
[
lc
];
3217
}
3218
}
3219
if
(
fISW
[1] <= 0)
return
;
3220
// remove one row and one column from variance matrix
3221
if
(
fNpar
<= 0)
return
;
3222
for
(i = 1; i <=
nold
; ++i) {
3223
m
=
TMath::Max
(i,
iint
);
3224
n
=
TMath::Min
(i,
iint
);
3225
ndex
=
m
*(
m
-1) / 2 +
n
;
3226
fFIXPyy
[i-1] =
fVhmat
[
ndex
-1];
3227
}
3228
yyover
= 1 /
fFIXPyy
[
iint
-1];
3229
knew
= 0;
3230
kold
= 0;
3231
for
(i = 1; i <=
nold
; ++i) {
3232
for
(
j
= 1;
j
<= i; ++
j
) {
3233
++
kold
;
3234
if
(
j
==
iint
|| i ==
iint
)
continue
;
3235
++
knew
;
3236
fVhmat
[
knew
-1] =
fVhmat
[
kold
-1] -
fFIXPyy
[
j
-1]*
fFIXPyy
[i-1]*
yyover
;
3237
}
3238
}
3239
}
3240
3241
////////////////////////////////////////////////////////////////////////////////
3242
/// Restores one or more fixed parameter(s) to variable status
3243
///
3244
/// Restores one or more fixed parameter(s) to variable status
3245
/// by inserting it into the internal parameter list at the
3246
/// appropriate place.
3247
///
3248
/// - K = 0 means restore all parameters
3249
/// - K = 1 means restore the last parameter fixed
3250
/// - K = -I means restore external parameter I (if possible)
3251
/// - IQ = fix-location where internal parameters were stored
3252
/// - IR = external number of parameter being restored
3253
/// - IS = internal number of parameter being restored
3254
3255
void
TMinuit::mnfree
(
Int_t
k)
3256
{
3257
/* Local variables */
3258
Double_t
grdv
,
xv
,
dirinv
,
g2v
,
gstepv
,
xtv
;
3259
Int_t
i,
ipsav
,
ka
,
lc
, ik,
iq
,
ir
,
is
;
3260
3261
if
(k > 1) {
3262
Printf
(
" CALL TO MNFREE IGNORED. ARGUMENT GREATER THAN ONE"
);
3263
}
3264
if
(
fNpfix
< 1) {
3265
Printf
(
" CALL TO MNFREE IGNORED. THERE ARE NO FIXED PARAMETERS"
);
3266
}
3267
if
(k == 1 || k == 0)
goto
L40
;
3268
3269
// release parameter with specified external number
3270
ka
= abs(k);
3271
if
(
fNiofex
[
ka
-1] == 0)
goto
L15
;
3272
Printf
(
" IGNORED. PARAMETER SPECIFIED IS ALREADY VARIABLE."
);
3273
return
;
3274
L15
:
3275
if
(
fNpfix
< 1)
goto
L21
;
3276
for
(ik = 1; ik <=
fNpfix
; ++ik) {
if
(
fIpfix
[ik-1] ==
ka
)
goto
L24
; }
3277
L21
:
3278
Printf
(
" PARAMETER %4d NOT FIXED. CANNOT BE RELEASED."
,
ka
);
3279
return
;
3280
L24
:
3281
if
(ik ==
fNpfix
)
goto
L40
;
3282
3283
// move specified parameter to end of list
3284
ipsav
=
ka
;
3285
xv
=
fXs
[ik-1];
3286
xtv
=
fXts
[ik-1];
3287
dirinv
=
fDirins
[ik-1];
3288
grdv
=
fGrds
[ik-1];
3289
g2v
=
fG2s
[ik-1];
3290
gstepv
=
fGsteps
[ik-1];
3291
for
(i = ik + 1; i <=
fNpfix
; ++i) {
3292
fIpfix
[i-2] =
fIpfix
[i-1];
3293
fXs
[i-2] =
fXs
[i-1];
3294
fXts
[i-2] =
fXts
[i-1];
3295
fDirins
[i-2] =
fDirins
[i-1];
3296
fGrds
[i-2] =
fGrds
[i-1];
3297
fG2s
[i-2] =
fG2s
[i-1];
3298
fGsteps
[i-2] =
fGsteps
[i-1];
3299
}
3300
fIpfix
[
fNpfix
-1] =
ipsav
;
3301
fXs
[
fNpfix
-1] =
xv
;
3302
fXts
[
fNpfix
-1] =
xtv
;
3303
fDirins
[
fNpfix
-1] =
dirinv
;
3304
fGrds
[
fNpfix
-1] =
grdv
;
3305
fG2s
[
fNpfix
-1] =
g2v
;
3306
fGsteps
[
fNpfix
-1] =
gstepv
;
3307
// restore last parameter in fixed list -- IPFIX(NPFIX)
3308
L40
:
3309
if
(
fNpfix
< 1)
goto
L300
;
3310
ir
=
fIpfix
[
fNpfix
-1];
3311
is
= 0;
3312
for
(ik =
fNu
; ik >=
ir
; --ik) {
3313
if
(
fNiofex
[ik-1] > 0) {
3314
lc
=
fNiofex
[ik-1] + 1;
3315
is
=
lc
- 1;
3316
fNiofex
[ik-1] =
lc
;
3317
fNexofi
[
lc
-1] = ik;
3318
fX
[
lc
-1] =
fX
[
lc
-2];
3319
fXt
[
lc
-1] =
fXt
[
lc
-2];
3320
fDirin
[
lc
-1] =
fDirin
[
lc
-2];
3321
fWerr
[
lc
-1] =
fWerr
[
lc
-2];
3322
fGrd
[
lc
-1] =
fGrd
[
lc
-2];
3323
fG2
[
lc
-1] =
fG2
[
lc
-2];
3324
fGstep
[
lc
-1] =
fGstep
[
lc
-2];
3325
}
3326
}
3327
++
fNpar
;
3328
if
(
is
== 0)
is
=
fNpar
;
3329
fNiofex
[
ir
-1] =
is
;
3330
fNexofi
[
is
-1] =
ir
;
3331
iq
=
fNpfix
;
3332
fX
[
is
-1] =
fXs
[
iq
-1];
3333
fXt
[
is
-1] =
fXts
[
iq
-1];
3334
fDirin
[
is
-1] =
fDirins
[
iq
-1];
3335
fWerr
[
is
-1] =
fDirins
[
iq
-1];
3336
fGrd
[
is
-1] =
fGrds
[
iq
-1];
3337
fG2
[
is
-1] =
fG2s
[
iq
-1];
3338
fGstep
[
is
-1] =
fGsteps
[
iq
-1];
3339
--
fNpfix
;
3340
fISW
[1] = 0;
3341
fDcovar
= 1;
3342
if
(
fISW
[4] -
fItaur
>= 1) {
3343
Printf
(
" PARAMETER %4d %s RESTORED TO VARIABLE."
,
ir
,
3344
(
const
char
*)
fCpnam
[
ir
-1]);
3345
}
3346
if
(k == 0)
goto
L40
;
3347
L300
:
3348
// if different from internal, external values are taken
3349
mnexin
(
fX
);
3350
}
3351
3352
////////////////////////////////////////////////////////////////////////////////
3353
/// Interprets the SET GRAD command
3354
///
3355
/// - Called from MNSET
3356
/// - Interprets the SET GRAD command, which informs MINUIT whether
3357
/// - the first derivatives of FCN will be calculated by the user
3358
/// - inside FCN. It can check the user derivative calculation
3359
/// - by comparing it with a finite difference approximation.
3360
3361
void
TMinuit::mngrad
()
3362
{
3363
/* Local variables */
3364
Double_t
fzero
, err;
3365
Int_t
i,
nparx
,
lc
,
istsav
;
3366
Bool_t
lnone
;
3367
3368
fISW
[2] = 1;
3369
nparx
=
fNpar
;
3370
if
(
fWord7
[0] > 0)
goto
L2000
;
3371
3372
// get user-calculated first derivatives from FCN
3373
for
(i = 1; i <=
fNu
; ++i) {
fGin
[i-1] =
fUndefi
; }
3374
mninex
(
fX
);
3375
Eval
(
nparx
,
fGin
,
fzero
,
fU
, 2); ++
fNfcn
;
3376
mnderi
();
3377
for
(i = 1; i <=
fNpar
; ++i) {
fGRADgf
[i-1] =
fGrd
[i-1]; }
3378
// get MINUIT-calculated first derivatives
3379
fISW
[2] = 0;
3380
istsav
=
fIstrat
;
3381
fIstrat
= 2;
3382
mnhes1
();
3383
fIstrat
=
istsav
;
3384
Printf
(
" CHECK OF GRADIENT CALCULATION IN FCN"
);
3385
Printf
(
" PARAMETER G(IN FCN) G(MINUIT) DG(MINUIT) AGREEMENT"
);
3386
fISW
[2] = 1;
3387
lnone
=
kFALSE
;
3388
for
(
lc
= 1;
lc
<=
fNpar
; ++
lc
) {
3389
i =
fNexofi
[
lc
-1];
3390
const
char
*
cwd
=
"GOOD"
;
3391
err =
fDgrd
[
lc
-1];
3392
if
(
TMath::Abs
(
fGRADgf
[
lc
-1] -
fGrd
[
lc
-1]) > err) {
3393
cwd
=
" BAD"
;
3394
fISW
[2] = 0;
3395
}
3396
if
(
fGin
[i-1] ==
fUndefi
) {
3397
cwd
=
"NONE"
;
3398
lnone
=
kTRUE
;
3399
fGRADgf
[
lc
-1] = 0;
3400
fISW
[2] = 0;
3401
}
3402
Printf
(
" %5d %10s%12.4e%12.4e%12.4e %s"
,i
3403
,(
const
char
*)
fCpnam
[i-1]
3404
,
fGRADgf
[
lc
-1],
fGrd
[
lc
-1],err,
cwd
);
3405
}
3406
if
(
lnone
) {
3407
Printf
(
" AGREEMENT=NONE MEANS FCN DID NOT CALCULATE THE DERIVATIVE"
);
3408
}
3409
if
(
fISW
[2] == 0) {
3410
Printf
(
" MINUIT DOES NOT ACCEPT DERIVATIVE CALCULATIONS BY FCN"
);
3411
Printf
(
" TO FORCE ACCEPTANCE, ENTER *SET GRAD 1*"
);
3412
}
3413
3414
L2000
:
3415
return
;
3416
}
3417
3418
////////////////////////////////////////////////////////////////////////////////
3419
/// interface to Minuit help
3420
3421
void
TMinuit::mnhelp
(
const
char
*
command
)
3422
{
3423
TString
comd
=
command
;
3424
mnhelp
(
comd
);
3425
}
3426
3427
////////////////////////////////////////////////////////////////////////////////
3428
/// HELP routine for MINUIT interactive commands
3429
///
3430
/// - COMD ='*' or "" prints a global help for all commands
3431
/// - COMD =Command_name: print detailed help for one command.
3432
/// Note that at least 3 characters must be given for the command
3433
/// name.
3434
///
3435
/// Author: Rene Brun
3436
/// comments extracted from the MINUIT documentation file.
3437
3438
void
TMinuit::mnhelp
(
TString
comd
)
3439
{
3440
//______________________________________________________________________________
3441
//
3442
// Global HELP: Summary of all commands
3443
//
3444
comd
.ToUpper();
3445
if
(
comd
.Length() == 0 ||
comd
[0] ==
'*'
||
comd
[0] ==
'?'
||
comd
[0] == 0 ||
comd
==
"HELP"
) {
3446
Printf
(
" ==>List of MINUIT Interactive commands:"
);
3447
Printf
(
" CLEar Reset all parameter names and values undefined"
);
3448
Printf
(
" CONtour Make contour map of the user function"
);
3449
Printf
(
" EXIT Exit from Interactive Minuit"
);
3450
Printf
(
" FIX Cause parameter(s) to remain constant"
);
3451
Printf
(
" HESse Calculate the Hessian or error matrix."
);
3452
Printf
(
" IMPROVE Search for a new minimum around current minimum"
);
3453
Printf
(
" MIGrad Minimize by the method of Migrad"
);
3454
Printf
(
" MINImize MIGRAD + SIMPLEX method if Migrad fails"
);
3455
Printf
(
" MINOs Exact (non-linear) parameter error analysis"
);
3456
Printf
(
" MNContour Calculate one MINOS function contour"
);
3457
Printf
(
" PARameter Define or redefine new parameters and values"
);
3458
Printf
(
" RELease Make previously FIXed parameters variable again"
);
3459
Printf
(
" REStore Release last parameter fixed"
);
3460
Printf
(
" SAVe Save current parameter values on a file"
);
3461
Printf
(
" SCAn Scan the user function by varying parameters"
);
3462
Printf
(
" SEEk Minimize by the method of Monte Carlo"
);
3463
Printf
(
" SET Set various MINUIT constants or conditions"
);
3464
Printf
(
" SHOw Show values of current constants or conditions"
);
3465
Printf
(
" SIMplex Minimize by the method of Simplex"
);
3466
goto
L99
;
3467
}
3468
3469
//______________________________________________________________________________
3470
//
3471
// Command CLEAR
3472
//
3473
if
( !
strncmp
(
comd
.Data(),
"CLE"
,3) ) {
3474
Printf
(
" ***>CLEAR"
);
3475
Printf
(
" Resets all parameter names and values to undefined."
);
3476
Printf
(
" Must normally be followed by a PARameters command or "
);
3477
Printf
(
" equivalent, in order to define parameter values."
);
3478
goto
L99
;
3479
}
3480
//______________________________________________________________________________
3481
//
3482
// Command CONTOUR
3483
//
3484
if
( !
strncmp
(
comd
.Data(),
"CON"
,3) ) {
3485
Printf
(
" ***>CONTOUR <par1> <par2> [devs] [ngrid]"
);
3486
Printf
(
" Instructs Minuit to trace contour lines of the user function"
);
3487
Printf
(
" with respect to the two parameters whose external numbers"
);
3488
Printf
(
" are <par1> and <par2>."
);
3489
Printf
(
" Other variable parameters of the function, if any, will have"
);
3490
Printf
(
" their values fixed at the current values during the contour"
);
3491
Printf
(
" tracing. The optional parameter [devs] (default value 2.)"
);
3492
Printf
(
" gives the number of standard deviations in each parameter"
);
3493
Printf
(
" which should lie entirely within the plotting area."
);
3494
Printf
(
" Optional parameter [ngrid] (default value 25 unless page"
);
3495
Printf
(
" size is too small) determines the resolution of the plot,"
);
3496
Printf
(
" i.e. the number of rows and columns of the grid at which the"
);
3497
Printf
(
" function will be evaluated. [See also MNContour.]"
);
3498
goto
L99
;
3499
}
3500
//______________________________________________________________________________
3501
//
3502
// Command END
3503
//
3504
if
( !
strncmp
(
comd
.Data(),
"END"
,3) ) {
3505
Printf
(
" ***>END"
);
3506
Printf
(
" Signals the end of a data block (i.e., the end of a fit),"
);
3507
Printf
(
" and implies that execution should continue, because another"
);
3508
Printf
(
" Data Block follows. A Data Block is a set of Minuit data"
);
3509
Printf
(
" consisting of"
);
3510
Printf
(
" (1) A Title,"
);
3511
Printf
(
" (2) One or more Parameter Definitions,"
);
3512
Printf
(
" (3) A blank line, and"
);
3513
Printf
(
" (4) A set of Minuit Commands."
);
3514
Printf
(
" The END command is used when more than one Data Block is to"
);
3515
Printf
(
" be used with the same FCN function. It first causes Minuit"
);
3516
Printf
(
" to issue a CALL FCN with IFLAG=3, in order to allow FCN to"
);
3517
Printf
(
" perform any calculations associated with the final fitted"
);
3518
Printf
(
" parameter values, unless a CALL FCN 3 command has already"
);
3519
Printf
(
" been executed at the current FCN value."
);
3520
goto
L99
;
3521
}
3522
//______________________________________________________________________________
3523
//
3524
// Command EXIT
3525
//
3526
if
( !
strncmp
(
comd
.Data(),
"EXI"
,3) ) {
3527
Printf
(
" ***>EXIT"
);
3528
Printf
(
" Signals the end of execution."
);
3529
Printf
(
" The EXIT command first causes Minuit to issue a CALL FCN"
);
3530
Printf
(
" with IFLAG=3, to allow FCN to perform any calculations"
);
3531
Printf
(
" associated with the final fitted parameter values, unless a"
);
3532
Printf
(
" CALL FCN 3 command has already been executed."
);
3533
goto
L99
;
3534
}
3535
//______________________________________________________________________________
3536
//
3537
// Command FIX
3538
//
3539
if
( !
strncmp
(
comd
.Data(),
"FIX"
,3) ) {
3540
Printf
(
" ***>FIX} <parno> [parno] ... [parno]"
);
3541
Printf
(
" Causes parameter(s) <parno> to be removed from the list of"
);
3542
Printf
(
" variable parameters, and their value(s) will remain constant"
);
3543
Printf
(
" during subsequent minimizations, etc., until another command"
);
3544
Printf
(
" changes their value(s) or status."
);
3545
goto
L99
;
3546
}
3547
//______________________________________________________________________________
3548
//
3549
// Command HESSE
3550
//
3551
if
( !
strncmp
(
comd
.Data(),
"HES"
,3) ) {
3552
Printf
(
" ***>HESse [maxcalls]"
);
3553
Printf
(
" Calculate, by finite differences, the Hessian or error matrix."
);
3554
Printf
(
" That is, it calculates the full matrix of second derivatives"
);
3555
Printf
(
" of the function with respect to the currently variable"
);
3556
Printf
(
" parameters, and inverts it, printing out the resulting error"
);
3557
Printf
(
" matrix. The optional argument [maxcalls] specifies the"
);
3558
Printf
(
" (approximate) maximum number of function calls after which"
);
3559
Printf
(
" the calculation will be stopped."
);
3560
goto
L99
;
3561
}
3562
//______________________________________________________________________________
3563
//
3564
// Command IMPROVE
3565
//
3566
if
( !
strncmp
(
comd
.Data(),
"IMP"
,3) ) {
3567
Printf
(
" ***>IMPROVE [maxcalls]"
);
3568
Printf
(
" If a previous minimization has converged, and the current"
);
3569
Printf
(
" values of the parameters therefore correspond to a local"
);
3570
Printf
(
" minimum of the function, this command requests a search for"
);
3571
Printf
(
" additional distinct local minima."
);
3572
Printf
(
" The optional argument [maxcalls] specifies the (approximate"
);
3573
Printf
(
" maximum number of function calls after which the calculation"
);
3574
Printf
(
" will be stopped."
);
3575
goto
L99
;
3576
}
3577
//______________________________________________________________________________
3578
//
3579
// Command MIGRAD
3580
//
3581
if
( !
strncmp
(
comd
.Data(),
"MIG"
,3) ) {
3582
Printf
(
" ***>MIGrad [maxcalls] [tolerance]"
);
3583
Printf
(
" Causes minimization of the function by the method of Migrad,"
);
3584
Printf
(
" the most efficient and complete single method, recommended"
);
3585
Printf
(
" for general functions (see also MINImize)."
);
3586
Printf
(
" The minimization produces as a by-product the error matrix"
);
3587
Printf
(
" of the parameters, which is usually reliable unless warning"
);
3588
Printf
(
" messages are produced."
);
3589
Printf
(
" The optional argument [maxcalls] specifies the (approximate)"
);
3590
Printf
(
" maximum number of function calls after which the calculation"
);
3591
Printf
(
" will be stopped even if it has not yet converged."
);
3592
Printf
(
" The optional argument [tolerance] specifies required tolerance"
);
3593
Printf
(
" on the function value at the minimum."
);
3594
Printf
(
" The default tolerance is 0.1, and the minimization will stop"
);
3595
Printf
(
" when the estimated vertical distance to the minimum (EDM) is"
);
3596
Printf
(
" less than 0.001*[tolerance]*UP (see [SET ERRordef])."
);
3597
goto
L99
;
3598
}
3599
//______________________________________________________________________________
3600
//
3601
// Command MINIMIZE
3602
//
3603
if
( !
strncmp
(
comd
.Data(),
"MINI"
,4) ) {
3604
Printf
(
" ***>MINImize [maxcalls] [tolerance]"
);
3605
Printf
(
" Causes minimization of the function by the method of Migrad,"
);
3606
Printf
(
" as does the MIGrad command, but switches to the SIMplex method"
);
3607
Printf
(
" if Migrad fails to converge. Arguments are as for MIGrad."
);
3608
Printf
(
" Note that command requires four characters to be unambiguous."
);
3609
goto
L99
;
3610
}
3611
//______________________________________________________________________________
3612
//
3613
// Command MINOS
3614
//
3615
if
( !
strncmp
(
comd
.Data(),
"MIN0"
,4) ) {
3616
Printf
(
" ***>MINOs [maxcalls] [parno] [parno] ..."
);
3617
Printf
(
" Causes a Minos error analysis to be performed on the parameters"
);
3618
Printf
(
" whose numbers [parno] are specified. If none are specified,"
);
3619
Printf
(
" Minos errors are calculated for all variable parameters."
);
3620
Printf
(
" Minos errors may be expensive to calculate, but are very"
);
3621
Printf
(
" reliable since they take account of non-linearities in the"
);
3622
Printf
(
" problem as well as parameter correlations, and are in general"
);
3623
Printf
(
" asymmetric."
);
3624
Printf
(
" The optional argument [maxcalls] specifies the (approximate)"
);
3625
Printf
(
" maximum number of function calls per parameter requested,"
);
3626
Printf
(
" after which the calculation will stop for that parameter."
);
3627
goto
L99
;
3628
}
3629
//______________________________________________________________________________
3630
//
3631
// Command MNCONTOUR
3632
//
3633
if
( !
strncmp
(
comd
.Data(),
"MNC"
,3) ) {
3634
Printf
(
" ***>MNContour <par1> <par2> [npts]"
);
3635
Printf
(
" Calculates one function contour of FCN with respect to"
);
3636
Printf
(
" parameters par1 and par2, with FCN minimized always with"
);
3637
Printf
(
" respect to all other NPAR-2 variable parameters (if any)."
);
3638
Printf
(
" Minuit will try to find npts points on the contour (default 20)"
);
3639
Printf
(
" If only two parameters are variable at the time, it is not"
);
3640
Printf
(
" necessary to specify their numbers. To calculate more than"
);
3641
Printf
(
" one contour, it is necessary to SET ERRordef to the appropriate"
);
3642
Printf
(
" value and issue the MNContour command for each contour."
);
3643
goto
L99
;
3644
}
3645
//______________________________________________________________________________
3646
//
3647
// Command PARAMETER
3648
//
3649
if
( !
strncmp
(
comd
.Data(),
"PAR"
,3) ) {
3650
Printf
(
" ***>PARameters"
);
3651
Printf
(
" followed by one or more parameter definitions."
);
3652
Printf
(
" Parameter definitions are of the form:"
);
3653
Printf
(
" <number> ''name'' <value> <step> [lolim] [uplim] "
);
3654
Printf
(
" for example:"
);
3655
Printf
(
" 3 ''K width'' 1.2 0.1"
);
3656
Printf
(
" the last definition is followed by a blank line or a zero."
);
3657
goto
L99
;
3658
}
3659
//______________________________________________________________________________
3660
//
3661
// Command RELEASE
3662
//
3663
if
( !
strncmp
(
comd
.Data(),
"REL"
,3) ) {
3664
Printf
(
" ***>RELease <parno> [parno] ... [parno]"
);
3665
Printf
(
" If <parno> is the number of a previously variable parameter"
);
3666
Printf
(
" which has been fixed by a command: FIX <parno>, then that"
);
3667
Printf
(
" parameter will return to variable status. Otherwise a warning"
);
3668
Printf
(
" message is printed and the command is ignored."
);
3669
Printf
(
" Note that this command operates only on parameters which were"
);
3670
Printf
(
" at one time variable and have been FIXed. It cannot make"
);
3671
Printf
(
" constant parameters variable; that must be done by redefining"
);
3672
Printf
(
" the parameter with a PARameters command."
);
3673
goto
L99
;
3674
}
3675
//______________________________________________________________________________
3676
//
3677
// Command RESTORE
3678
//
3679
if
( !
strncmp
(
comd
.Data(),
"RES"
,3) ) {
3680
Printf
(
" ***>REStore [code]"
);
3681
Printf
(
" If no [code] is specified, this command restores all previously"
);
3682
Printf
(
" FIXed parameters to variable status. If [code]=1, then only"
);
3683
Printf
(
" the last parameter FIXed is restored to variable status."
);
3684
Printf
(
" If code is neither zero nor one, the command is ignored."
);
3685
goto
L99
;
3686
}
3687
//______________________________________________________________________________
3688
//
3689
// Command RETURN
3690
//
3691
if
( !
strncmp
(
comd
.Data(),
"RET"
,3) ) {
3692
Printf
(
" ***>RETURN"
);
3693
Printf
(
" Signals the end of a data block, and instructs Minuit to return"
);
3694
Printf
(
" to the program which called it. The RETurn command first"
);
3695
Printf
(
" causes Minuit to CALL FCN with IFLAG=3, in order to allow FCN"
);
3696
Printf
(
" to perform any calculations associated with the final fitted"
);
3697
Printf
(
" parameter values, unless a CALL FCN 3 command has already been"
);
3698
Printf
(
" executed at the current FCN value."
);
3699
goto
L99
;
3700
}
3701
//______________________________________________________________________________
3702
//
3703
// Command SAVE
3704
//
3705
if
( !
strncmp
(
comd
.Data(),
"SAV"
,3) ) {
3706
Printf
(
" ***>SAVe"
);
3707
Printf
(
" Causes the current parameter values to be saved on a file in"
);
3708
Printf
(
" such a format that they can be read in again as Minuit"
);
3709
Printf
(
" parameter definitions. If the covariance matrix exists, it is"
);
3710
Printf
(
" also output in such a format. The unit number is by default 7,"
);
3711
Printf
(
" or that specified by the user in their call to MINTIO or"
);
3712
Printf
(
" MNINIT. The user is responsible for opening the file previous"
);
3713
Printf
(
" to issuing the [SAVe] command (except where this can be done"
);
3714
Printf
(
" interactively)."
);
3715
goto
L99
;
3716
}
3717
//______________________________________________________________________________
3718
//
3719
// Command SCAN
3720
//
3721
if
( !
strncmp
(
comd
.Data(),
"SCA"
,3) ) {
3722
Printf
(
" ***>SCAn [parno] [numpts] [from] [to]"
);
3723
Printf
(
" Scans the value of the user function by varying parameter"
);
3724
Printf
(
" number [parno], leaving all other parameters fixed at the"
);
3725
Printf
(
" current value. If [parno] is not specified, all variable"
);
3726
Printf
(
" parameters are scanned in sequence."
);
3727
Printf
(
" The number of points [numpts] in the scan is 40 by default,"
);
3728
Printf
(
" and cannot exceed 100. The range of the scan is by default"
);
3729
Printf
(
" 2 standard deviations on each side of the current best value,"
);
3730
Printf
(
" but can be specified as from [from] to [to]."
);
3731
Printf
(
" After each scan, if a new minimum is found, the best parameter"
);
3732
Printf
(
" values are retained as start values for future scans or"
);
3733
Printf
(
" minimizations. The curve resulting from each scan is plotted"
);
3734
Printf
(
" on the output unit in order to show the approximate behaviour"
);
3735
Printf
(
" of the function."
);
3736
Printf
(
" This command is not intended for minimization, but is sometimes"
);
3737
Printf
(
" useful for debugging the user function or finding a"
);
3738
Printf
(
" reasonable starting point."
);
3739
goto
L99
;
3740
}
3741
//______________________________________________________________________________
3742
//
3743
// Command SEEK
3744
//
3745
if
( !
strncmp
(
comd
.Data(),
"SEE"
,3) ) {
3746
Printf
(
" ***>SEEk [maxcalls] [devs]"
);
3747
Printf
(
" Causes a Monte Carlo minimization of the function, by choosing"
);
3748
Printf
(
" random values of the variable parameters, chosen uniformly"
);
3749
Printf
(
" over a hypercube centered at the current best value."
);
3750
Printf
(
" The region size is by default 3 standard deviations on each"
);
3751
Printf
(
" side, but can be changed by specifying the value of [devs]."
);
3752
goto
L99
;
3753
}
3754
//______________________________________________________________________________
3755
//
3756
// Command SET
3757
//
3758
if
( !
strncmp
(
comd
.Data(),
"SET"
,3) ) {
3759
Printf
(
" ***>SET <option_name>"
);
3760
Printf
(
" SET BATch"
);
3761
Printf
(
" Informs Minuit that it is running in batch mode."
);
3762
3763
Printf
(
" "
);
3764
Printf
(
" SET EPSmachine <accuracy>"
);
3765
Printf
(
" Informs Minuit that the relative floating point arithmetic"
);
3766
Printf
(
" precision is <accuracy>. Minuit determines the nominal"
);
3767
Printf
(
" precision itself, but the SET EPSmachine command can be"
);
3768
Printf
(
" used to override Minuit own determination, when the user"
);
3769
Printf
(
" knows that the FCN function value is not calculated to"
);
3770
Printf
(
" the nominal machine accuracy. Typical values of <accuracy>"
);
3771
Printf
(
" are between 10**-5 and 10**-14."
);
3772
3773
Printf
(
" "
);
3774
Printf
(
" SET ERRordef <up>"
);
3775
Printf
(
" Sets the value of UP (default value= 1.), defining parameter"
);
3776
Printf
(
" errors. Minuit defines parameter errors as the change"
);
3777
Printf
(
" in parameter value required to change the function value"
);
3778
Printf
(
" by UP. Normally, for chisquared fits UP=1, and for negative"
);
3779
Printf
(
" log likelihood, UP=0.5."
);
3780
3781
Printf
(
" "
);
3782
Printf
(
" SET GRAdient [force]"
);
3783
Printf
(
" Informs Minuit that the user function is prepared to"
);
3784
Printf
(
" calculate its own first derivatives and return their values"
);
3785
Printf
(
" in the array GRAD when IFLAG=2 (see specs of FCN)."
);
3786
Printf
(
" If [force] is not specified, Minuit will calculate"
);
3787
Printf
(
" the FCN derivatives by finite differences at the current"
);
3788
Printf
(
" point and compare with the user calculation at that point,"
);
3789
Printf
(
" accepting the user values only if they agree."
);
3790
Printf
(
" If [force]=1, Minuit does not do its own derivative"
);
3791
Printf
(
" calculation, and uses the derivatives calculated in FCN."
);
3792
3793
Printf
(
" "
);
3794
Printf
(
" SET INPut [unitno] [filename]"
);
3795
Printf
(
" Causes Minuit, in data-driven mode only, to read subsequent"
);
3796
Printf
(
" commands (or parameter definitions) from a different input"
);
3797
Printf
(
" file. If no [unitno] is specified, reading reverts to the"
);
3798
Printf
(
" previous input file, assuming that there was one."
);
3799
Printf
(
" If [unitno] is specified, and that unit has not been opened,"
);
3800
Printf
(
" then Minuit attempts to open the file [filename]} if a"
);
3801
Printf
(
" name is specified. If running in interactive mode and"
);
3802
Printf
(
" [filename] is not specified and [unitno] is not opened,"
);
3803
Printf
(
" Minuit prompts the user to enter a file name."
);
3804
Printf
(
" If the word REWIND is added to the command (note:no blanks"
);
3805
Printf
(
" between INPUT and REWIND), the file is rewound before"
);
3806
Printf
(
" reading. Note that this command is implemented in standard"
);
3807
Printf
(
" Fortran 77 and the results may depend on the system;"
);
3808
Printf
(
" for example, if a filename is given under VM/CMS, it must"
);
3809
Printf
(
" be preceded by a slash."
);
3810
3811
Printf
(
" "
);
3812
Printf
(
" SET INTeractive"
);
3813
Printf
(
" Informs Minuit that it is running interactively."
);
3814
3815
Printf
(
" "
);
3816
Printf
(
" SET LIMits [parno] [lolim] [uplim]"
);
3817
Printf
(
" Allows the user to change the limits on one or all"
);
3818
Printf
(
" parameters. If no arguments are specified, all limits are"
);
3819
Printf
(
" removed from all parameters. If [parno] alone is specified,"
);
3820
Printf
(
" limits are removed from parameter [parno]."
);
3821
Printf
(
" If all arguments are specified, then parameter [parno] will"
);
3822
Printf
(
" be bounded between [lolim] and [uplim]."
);
3823
Printf
(
" Limits can be specified in either order, Minuit will take"
);
3824
Printf
(
" the smaller as [lolim] and the larger as [uplim]."
);
3825
Printf
(
" However, if [lolim] is equal to [uplim], an error condition"
);
3826
Printf
(
" results."
);
3827
3828
Printf
(
" "
);
3829
Printf
(
" SET LINesperpage"
);
3830
Printf
(
" Sets the number of lines for one page of output."
);
3831
Printf
(
" Default value is 24 for interactive mode"
);
3832
3833
Printf
(
" "
);
3834
Printf
(
" SET NOGradient"
);
3835
Printf
(
" The inverse of SET GRAdient, instructs Minuit not to"
);
3836
Printf
(
" use the first derivatives calculated by the user in FCN."
);
3837
3838
Printf
(
" "
);
3839
Printf
(
" SET NOWarnings"
);
3840
Printf
(
" Suppresses Minuit warning messages."
);
3841
3842
Printf
(
" "
);
3843
Printf
(
" SET OUTputfile <unitno>"
);
3844
Printf
(
" Instructs Minuit to write further output to unit <unitno>."
);
3845
3846
Printf
(
" "
);
3847
Printf
(
" SET PAGethrow <integer>"
);
3848
Printf
(
" Sets the carriage control character for ``new page'' to"
);
3849
Printf
(
" <integer>. Thus the value 1 produces a new page, and 0"
);
3850
Printf
(
" produces a blank line, on some devices (see TOPofpage)"
);
3851
3852
3853
Printf
(
" "
);
3854
Printf
(
" SET PARameter <parno> <value>"
);
3855
Printf
(
" Sets the value of parameter <parno> to <value>."
);
3856
Printf
(
" The parameter in question may be variable, fixed, or"
);
3857
Printf
(
" constant, but must be defined."
);
3858
3859
Printf
(
" "
);
3860
Printf
(
" SET PRIntout <level>"
);
3861
Printf
(
" Sets the print level, determining how much output will be"
);
3862
Printf
(
" produced. Allowed values and their meanings are displayed"
);
3863
Printf
(
" after a SHOw PRInt command, and are currently <level>=:"
);
3864
Printf
(
" [-1] no output except from SHOW commands"
);
3865
Printf
(
" [0] minimum output"
);
3866
Printf
(
" [1] default value, normal output"
);
3867
Printf
(
" [2] additional output giving intermediate results."
);
3868
Printf
(
" [3] maximum output, showing progress of minimizations."
);
3869
Printf
(
" Note: See also the SET WARnings command."
);
3870
3871
Printf
(
" "
);
3872
Printf
(
" SET RANdomgenerator <seed>"
);
3873
Printf
(
" Sets the seed of the random number generator used in SEEk."
);
3874
Printf
(
" This can be any integer between 10000 and 900000000, for"
);
3875
Printf
(
" example one which was output from a SHOw RANdom command of"
);
3876
Printf
(
" a previous run."
);
3877
3878
Printf
(
" "
);
3879
Printf
(
" SET STRategy <level>"
);
3880
Printf
(
" Sets the strategy to be used in calculating first and second"
);
3881
Printf
(
" derivatives and in certain minimization methods."
);
3882
Printf
(
" In general, low values of <level> mean fewer function calls"
);
3883
Printf
(
" and high values mean more reliable minimization."
);
3884
Printf
(
" Currently allowed values are 0, 1 (default), and 2."
);
3885
3886
Printf
(
" "
);
3887
Printf
(
" SET TITle"
);
3888
Printf
(
" Informs Minuit that the next input line is to be considered"
);
3889
Printf
(
" the (new) title for this task or sub-task. This is for"
);
3890
Printf
(
" the convenience of the user in reading their output."
);
3891
3892
Printf
(
" "
);
3893
Printf
(
" SET WARnings"
);
3894
Printf
(
" Instructs Minuit to output warning messages when suspicious"
);
3895
Printf
(
" conditions arise which may indicate unreliable results."
);
3896
Printf
(
" This is the default."
);
3897
3898
Printf
(
" "
);
3899
Printf
(
" SET WIDthpage"
);
3900
Printf
(
" Informs Minuit of the output page width."
);
3901
Printf
(
" Default values are 80 for interactive jobs"
);
3902
goto
L99
;
3903
}
3904
//______________________________________________________________________________
3905
//
3906
// Command SHOW
3907
//
3908
if
( !
strncmp
(
comd
.Data(),
"SHO"
,3) ) {
3909
Printf
(
" ***>SHOw <option_name>"
);
3910
Printf
(
" All SET XXXX commands have a corresponding SHOw XXXX command."
);
3911
Printf
(
" In addition, the SHOw commands listed starting here have no"
);
3912
Printf
(
" corresponding SET command for obvious reasons."
);
3913
3914
Printf
(
" "
);
3915
Printf
(
" SHOw CORrelations"
);
3916
Printf
(
" Calculates and prints the parameter correlations from the"
);
3917
Printf
(
" error matrix."
);
3918
3919
Printf
(
" "
);
3920
Printf
(
" SHOw COVariance"
);
3921
Printf
(
" Prints the (external) covariance (error) matrix."
);
3922
3923
Printf
(
" "
);
3924
Printf
(
" SHOw EIGenvalues"
);
3925
Printf
(
" Calculates and prints the eigenvalues of the covariance"
);
3926
Printf
(
" matrix."
);
3927
3928
Printf
(
" "
);
3929
Printf
(
" SHOw FCNvalue"
);
3930
Printf
(
" Prints the current value of FCN."
);
3931
goto
L99
;
3932
}
3933
//______________________________________________________________________________
3934
//
3935
// Command SIMPLEX
3936
//
3937
if
( !
strncmp
(
comd
.Data(),
"SIM"
,3) ) {
3938
Printf
(
" ***>SIMplex [maxcalls] [tolerance]"
);
3939
Printf
(
" Performs a function minimization using the simplex method of"
);
3940
Printf
(
" Nelder and Mead. Minimization terminates either when the"
);
3941
Printf
(
" function has been called (approximately) [maxcalls] times,"
);
3942
Printf
(
" or when the estimated vertical distance to minimum (EDM) is"
);
3943
Printf
(
" less than [tolerance]."
);
3944
Printf
(
" The default value of [tolerance] is 0.1*UP(see SET ERRordef)."
);
3945
goto
L99
;
3946
}
3947
//______________________________________________________________________________
3948
//
3949
// Command STANDARD
3950
//
3951
if
( !
strncmp
(
comd
.Data(),
"STA"
,3) ) {
3952
Printf
(
" ***>STAndard"
);
3953
goto
L99
;
3954
}
3955
//______________________________________________________________________________
3956
//
3957
// Command STOP
3958
//
3959
if
( !
strncmp
(
comd
.Data(),
"STO"
,3) ) {
3960
Printf
(
" ***>STOP"
);
3961
Printf
(
" Same as EXIT."
);
3962
goto
L99
;
3963
}
3964
//______________________________________________________________________________
3965
//
3966
// Command TOPOFPAGE
3967
//
3968
if
( !
strncmp
(
comd
.Data(),
"TOP"
,3) ) {
3969
Printf
(
" ***>TOPofpage"
);
3970
Printf
(
" Causes Minuit to write the character specified in a"
);
3971
Printf
(
" SET PAGethrow command (default = 1) to column 1 of the output"
);
3972
Printf
(
" file, which may or may not position your output medium to"
);
3973
Printf
(
" the top of a page depending on the device and system."
);
3974
goto
L99
;
3975
}
3976
//______________________________________________________________________________
3977
Printf
(
" Unknown MINUIT command. Type HELP for list of commands."
);
3978
3979
L99
:
3980
return
;
3981
}
3982
3983
////////////////////////////////////////////////////////////////////////////////
3984
/// Calculates the full second-derivative matrix of FCN
3985
///
3986
/// by taking finite differences. When calculating diagonal
3987
/// elements, it may iterate so that step size is nearly that
3988
/// which gives function change= UP/10. The first derivatives
3989
/// of course come as a free side effect, but with a smaller
3990
/// step size in order to obtain a known accuracy.
3991
3992
void
TMinuit::mnhess
()
3993
{
3994
/* Local variables */
3995
Double_t
dmin_
,
dxdi
,
elem
,
wint
,
tlrg2
,
d
,
dlast
,
ztemp
,
g2bfor
;
3996
Double_t
df,
aimsag
,
fs1
,
tlrstp
,
fs2
,
stpinm
,
g2i
,
sag
=0,
xtf
,
xti
,
xtj
;
3997
Int_t
icyc
,
ncyc
,
ndex
,
idrv
,
iext
,
npar2
, i,
j
,
ifail
,
npard
,
nparx
,
id
,
multpy
;
3998
Bool_t
ldebug
;
3999
4000
ldebug
=
fIdbg
[3] >= 1;
4001
if
(
fAmin
==
fUndefi
) {
4002
mnamin
();
4003
}
4004
if
(
fIstrat
<= 0) {
4005
ncyc
= 3;
4006
tlrstp
= .5;
4007
tlrg2
= .1;
4008
}
else
if
(
fIstrat
== 1) {
4009
ncyc
= 5;
4010
tlrstp
= .3;
4011
tlrg2
= .05;
4012
}
else
{
4013
ncyc
= 7;
4014
tlrstp
= .1;
4015
tlrg2
= .02;
4016
}
4017
if
(
fISW
[4] >= 2 ||
ldebug
) {
4018
Printf
(
" START COVARIANCE MATRIX CALCULATION."
);
4019
}
4020
fCfrom
=
"HESSE "
;
4021
fNfcnfr
=
fNfcn
;
4022
fCstatu
=
"OK "
;
4023
npard
=
fNpar
;
4024
// make sure starting at the right place
4025
mninex
(
fX
);
4026
nparx
=
fNpar
;
4027
Eval
(
nparx
,
fGin
,
fs1
,
fU
, 4); ++
fNfcn
;
4028
if
(
fs1
!=
fAmin
) {
4029
df =
fAmin
-
fs1
;
4030
mnwarn
(
"D"
,
"MNHESS"
,
TString::Format
(
"function value differs from AMIN by %g"
,df));
4031
}
4032
fAmin
=
fs1
;
4033
if
(
ldebug
) {
4034
Printf
(
" PAR D GSTEP D G2 GRD SAG "
);
4035
}
4036
// diagonal elements .
4037
4038
// fISW[1] = 1 if approx, 2 if not posdef, 3 if ok
4039
// AIMSAG is the sagitta we are aiming for in second deriv calc.
4040
4041
aimsag
=
TMath::Sqrt
(
fEpsma2
)*(
TMath::Abs
(
fAmin
) +
fUp
);
4042
// Zero the second derivative matrix
4043
npar2
=
fNpar
*(
fNpar
+ 1) / 2;
4044
for
(i = 1; i <=
npar2
; ++i) {
fVhmat
[i-1] = 0; }
4045
4046
// Loop over variable parameters for second derivatives
4047
idrv
= 2;
4048
for
(
id
= 1;
id
<=
npard
; ++
id
) {
4049
i =
id
+
fNpar
-
npard
;
4050
iext
=
fNexofi
[i-1];
4051
if
(
fG2
[i-1] == 0) {
4052
mnwarn
(
"W"
,
"HESSE"
,
Form
(
"Second derivative enters zero, param %d"
,
iext
));
4053
wint
=
fWerr
[i-1];
4054
if
(
fNvarl
[
iext
-1] > 1) {
4055
mndxdi
(
fX
[i-1], i-1,
dxdi
);
4056
if
(
TMath::Abs
(
dxdi
) < .001)
wint
= .01;
4057
else
wint
/=
TMath::Abs
(
dxdi
);
4058
}
4059
fG2
[i-1] =
fUp
/ (
wint
*
wint
);
4060
}
4061
xtf
=
fX
[i-1];
4062
dmin_
=
fEpsma2
*8*
TMath::Abs
(
xtf
);
4063
4064
// find step which gives sagitta = AIMSAG
4065
d
=
TMath::Abs
(
fGstep
[i-1]);
4066
int
skip50
= 0;
4067
for
(
icyc
= 1;
icyc
<=
ncyc
; ++
icyc
) {
4068
// loop here only if SAG=0
4069
for
(
multpy
= 1;
multpy
<= 5; ++
multpy
) {
4070
// take two steps
4071
fX
[i-1] =
xtf
+
d
;
4072
mninex
(
fX
);
4073
nparx
=
fNpar
;
4074
Eval
(
nparx
,
fGin
,
fs1
,
fU
, 4); ++
fNfcn
;
4075
fX
[i-1] =
xtf
-
d
;
4076
mninex
(
fX
);
4077
Eval
(
nparx
,
fGin
,
fs2
,
fU
, 4); ++
fNfcn
;
4078
fX
[i-1] =
xtf
;
4079
sag
= (
fs1
+
fs2
-
fAmin
*2)*.5;
4080
if
(
sag
!= 0)
goto
L30
;
4081
if
(
fGstep
[i-1] < 0) {
4082
if
(
d
>= .5)
goto
L26
;
4083
d
*= 10;
4084
if
(
d
> .5)
d
= .51;
4085
continue
;
4086
}
4087
d
*= 10;
4088
}
4089
L26
:
4090
mnwarn
(
"W"
,
"HESSE"
,
TString::Format
(
"Second derivative zero for parameter%d"
,
iext
));
4091
goto
L390
;
4092
// SAG is not zero
4093
L30
:
4094
g2bfor
=
fG2
[i-1];
4095
fG2
[i-1] =
sag
*2 / (
d
*
d
);
4096
fGrd
[i-1] = (
fs1
-
fs2
) / (
d
*2);
4097
if
(
ldebug
) {
4098
Printf
(
"%4d%2d%12.5g%12.5g%12.5g%12.5g%12.5g"
,i,
idrv
,
fGstep
[i-1],
d
,
fG2
[i-1],
fGrd
[i-1],
sag
);
4099
}
4100
if
(
fGstep
[i-1] > 0)
fGstep
[i-1] =
TMath::Abs
(
d
);
4101
else
fGstep
[i-1] = -
TMath::Abs
(
d
);
4102
fDirin
[i-1] =
d
;
4103
fHESSyy
[i-1]=
fs1
;
4104
dlast
=
d
;
4105
d
=
TMath::Sqrt
(
aimsag
*2 /
TMath::Abs
(
fG2
[i-1]));
4106
// if parameter has limits, max int step size = 0.5
4107
stpinm
= .5;
4108
if
(
fGstep
[i-1] < 0)
d
=
TMath::Min
(
d
,
stpinm
);
4109
if
(
d
<
dmin_
)
d
=
dmin_
;
4110
// see if converged
4111
if
(
TMath::Abs
((
d
-
dlast
) /
d
) <
tlrstp
||
4112
TMath::Abs
((
fG2
[i-1] -
g2bfor
) /
fG2
[i-1]) <
tlrg2
) {
4113
skip50
= 1;
4114
break
;
4115
}
4116
d
=
TMath::Min
(
d
,
dlast
*102);
4117
d
=
TMath::Max
(
d
,
dlast
*.1);
4118
}
4119
// end of step size loop
4120
if
(!
skip50
)
4121
mnwarn
(
"D"
,
"MNHESS"
,
TString::Format
(
"Second Deriv. SAG,AIM= %d%g%g"
,
iext
,
sag
,
aimsag
));
4122
4123
ndex
= i*(i + 1) / 2;
4124
fVhmat
[
ndex
-1] =
fG2
[i-1];
4125
}
4126
// end of diagonal second derivative loop
4127
mninex
(
fX
);
4128
// refine the first derivatives
4129
if
(
fIstrat
> 0)
mnhes1
();
4130
fISW
[1] = 3;
4131
fDcovar
= 0;
4132
// off-diagonal elements
4133
4134
if
(
fNpar
== 1)
goto
L214
;
4135
for
(i = 1; i <=
fNpar
; ++i) {
4136
for
(
j
= 1;
j
<= i-1; ++
j
) {
4137
xti
=
fX
[i-1];
4138
xtj
=
fX
[
j
-1];
4139
fX
[i-1] =
xti
+
fDirin
[i-1];
4140
fX
[
j
-1] =
xtj
+
fDirin
[
j
-1];
4141
mninex
(
fX
);
4142
Eval
(
nparx
,
fGin
,
fs1
,
fU
, 4); ++
fNfcn
;
4143
fX
[i-1] =
xti
;
4144
fX
[
j
-1] =
xtj
;
4145
elem
= (
fs1
+
fAmin
-
fHESSyy
[i-1] -
fHESSyy
[
j
-1]) / (
4146
fDirin
[i-1]*
fDirin
[
j
-1]);
4147
ndex
= i*(i-1) / 2 +
j
;
4148
fVhmat
[
ndex
-1] =
elem
;
4149
}
4150
}
4151
L214
:
4152
mninex
(
fX
);
4153
// verify matrix positive-definite
4154
mnpsdf
();
4155
for
(i = 1; i <=
fNpar
; ++i) {
4156
for
(
j
= 1;
j
<= i; ++
j
) {
4157
ndex
= i*(i-1) / 2 +
j
;
4158
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1] =
fVhmat
[
ndex
-1];
4159
fP
[
j
+ i*
fMaxpar
-
fMaxpar
-1] =
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1];
4160
}
4161
}
4162
mnvert
(
fP
,
fMaxint
,
fMaxint
,
fNpar
,
ifail
);
4163
if
(
ifail
> 0) {
4164
mnwarn
(
"W"
,
"HESSE"
,
"Matrix inversion fails."
);
4165
goto
L390
;
4166
}
4167
// calculate e d m
4168
fEDM
= 0;
4169
4170
for
(i = 1; i <=
fNpar
; ++i) {
4171
// off-diagonal elements
4172
ndex
= i*(i-1) / 2;
4173
for
(
j
= 1;
j
<= i-1; ++
j
) {
4174
++
ndex
;
4175
ztemp
=
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1]*2;
4176
fEDM
+=
fGrd
[i-1]*
ztemp
*
fGrd
[
j
-1];
4177
fVhmat
[
ndex
-1] =
ztemp
;
4178
}
4179
// diagonal elements
4180
++
ndex
;
4181
fVhmat
[
ndex
-1] =
fP
[i + i*
fMaxpar
-
fMaxpar
-1]*2;
4182
fEDM
+=
fP
[i + i*
fMaxpar
-
fMaxpar
-1]*(
fGrd
[i-1]*
fGrd
[i-1]);
4183
}
4184
if
(
fISW
[4] >= 1 &&
fISW
[1] == 3 &&
fItaur
== 0) {
4185
Printf
(
" COVARIANCE MATRIX CALCULATED SUCCESSFULLY"
);
4186
}
4187
goto
L900
;
4188
// failure to invert 2nd deriv matrix
4189
L390
:
4190
fISW
[1] = 1;
4191
fDcovar
= 1;
4192
fCstatu
=
"FAILED "
;
4193
if
(
fISW
[4] >= 0) {
4194
Printf
(
" MNHESS FAILS AND WILL RETURN DIAGONAL MATRIX. "
);
4195
}
4196
for
(i = 1; i <=
fNpar
; ++i) {
4197
ndex
= i*(i-1) / 2;
4198
for
(
j
= 1;
j
<= i-1; ++
j
) {
4199
++
ndex
;
4200
fVhmat
[
ndex
-1] = 0;
4201
}
4202
++
ndex
;
4203
g2i
=
fG2
[i-1];
4204
if
(
g2i
<= 0)
g2i
= 1;
4205
fVhmat
[
ndex
-1] = 2 /
g2i
;
4206
}
4207
L900
:
4208
return
;
4209
}
4210
4211
////////////////////////////////////////////////////////////////////////////////
4212
/// Calculate first derivatives (GRD) and uncertainties (DGRD)
4213
///
4214
/// and appropriate step sizes GSTEP
4215
/// Called from MNHESS and MNGRAD
4216
4217
void
TMinuit::mnhes1
()
4218
{
4219
/* Local variables */
4220
Double_t
dmin_
,
d
,
dfmin
,
dgmin
=0, change,
chgold
,
grdold
=0,
epspri
;
4221
Double_t
fs1
,
optstp
,
fs2
,
grdnew
=0,
sag
,
xtf
;
4222
Int_t
icyc
,
ncyc
=0,
idrv
, i,
nparx
;
4223
Bool_t
ldebug
;
4224
4225
ldebug
=
fIdbg
[5] >= 1;
4226
if
(
fIstrat
<= 0)
ncyc
= 1;
4227
if
(
fIstrat
== 1)
ncyc
= 2;
4228
if
(
fIstrat
> 1)
ncyc
= 6;
4229
idrv
= 1;
4230
nparx
=
fNpar
;
4231
dfmin
=
fEpsma2
*4*(
TMath::Abs
(
fAmin
) +
fUp
);
4232
// main loop over parameters
4233
for
(i = 1; i <=
fNpar
; ++i) {
4234
xtf
=
fX
[i-1];
4235
dmin_
=
fEpsma2
*4*
TMath::Abs
(
xtf
);
4236
epspri
=
fEpsma2
+
TMath::Abs
(
fGrd
[i-1]*
fEpsma2
);
4237
optstp
=
TMath::Sqrt
(
dfmin
/ (
TMath::Abs
(
fG2
[i-1]) +
epspri
));
4238
d
=
TMath::Abs
(
fGstep
[i-1])*.2;
4239
if
(
d
>
optstp
)
d
=
optstp
;
4240
if
(
d
<
dmin_
)
d
=
dmin_
;
4241
chgold
= 1
e4
;
4242
// iterate reducing step size
4243
for
(
icyc
= 1;
icyc
<=
ncyc
; ++
icyc
) {
4244
fX
[i-1] =
xtf
+
d
;
4245
mninex
(
fX
);
4246
Eval
(
nparx
,
fGin
,
fs1
,
fU
, 4); ++
fNfcn
;
4247
fX
[i-1] =
xtf
-
d
;
4248
mninex
(
fX
);
4249
Eval
(
nparx
,
fGin
,
fs2
,
fU
, 4); ++
fNfcn
;
4250
fX
[i-1] =
xtf
;
4251
// check if step sizes appropriate
4252
sag
= (
fs1
+
fs2
-
fAmin
*2)*.5;
4253
grdold
=
fGrd
[i-1];
4254
grdnew
= (
fs1
-
fs2
) / (
d
*2);
4255
dgmin
=
fEpsmac
*(
TMath::Abs
(
fs1
) +
TMath::Abs
(
fs2
)) /
d
;
4256
if
(
ldebug
) {
4257
Printf
(
"%4d%2d%12.5g%12.5g%12.5g%12.5g%12.5g"
,i,
idrv
,
fGstep
[i-1],
d
,
fG2
[i-1],
grdnew
,
sag
);
4258
}
4259
if
(
grdnew
== 0)
goto
L60
;
4260
change =
TMath::Abs
((
grdold
-
grdnew
) /
grdnew
);
4261
if
(change >
chgold
&&
icyc
> 1)
goto
L60
;
4262
chgold
= change;
4263
fGrd
[i-1] =
grdnew
;
4264
if
(
fGstep
[i-1] > 0)
fGstep
[i-1] =
TMath::Abs
(
d
);
4265
else
fGstep
[i-1] = -
TMath::Abs
(
d
);
4266
// decrease step until first derivative changes by <5%
4267
if
(change < .05)
goto
L60
;
4268
if
(
TMath::Abs
(
grdold
-
grdnew
) <
dgmin
)
goto
L60
;
4269
if
(
d
<
dmin_
) {
4270
mnwarn
(
"D"
,
"MNHES1"
,
"Step size too small for 1st drv."
);
4271
goto
L60
;
4272
}
4273
d
*= .2;
4274
}
4275
// loop satisfied = too many iter
4276
mnwarn
(
"D"
,
"MNHES1"
,
TString::Format
(
"Too many iterations on D1.%g%g"
,
grdold
,
grdnew
));
4277
L60
:
4278
fDgrd
[i-1] =
TMath::Max
(
dgmin
,
TMath::Abs
(
grdold
-
grdnew
));
4279
}
4280
// end of first deriv. loop
4281
mninex
(
fX
);
4282
}
4283
4284
////////////////////////////////////////////////////////////////////////////////
4285
/// Attempts to improve on a good local minimum
4286
///
4287
/// Attempts to improve on a good local minimum by finding a
4288
/// better one. The quadratic part of FCN is removed by MNCALF
4289
/// and this transformed function is minimised using the simplex
4290
/// method from several random starting points.
4291
///
4292
/// ref. -- Goldstein and Price, Math.Comp. 25, 569 (1971)
4293
4294
void
TMinuit::mnimpr
()
4295
{
4296
/* Initialized data */
4297
4298
Double_t
rnum
= 0;
4299
4300
/* Local variables */
4301
Double_t
amax
,
ycalf
,
ystar
,
ystst
;
4302
Double_t
pb
,
ep
,
wg
, xi,
sigsav
,
reg
,
sig2
;
4303
Int_t
npfn
,
ndex
, loop=0, i,
j
,
ifail
,
iseed
=0;
4304
Int_t
jhold
,
nloop
,
nparx
,
nparp1
,
jh
,
jl
,
iswtr
;
4305
4306
if
(
fNpar
<= 0)
return
;
4307
if
(
fAmin
==
fUndefi
)
mnamin
();
4308
fCstatu
=
"UNCHANGED "
;
4309
fItaur
= 1;
4310
fEpsi
=
fUp
*.1;
4311
npfn
=
fNfcn
;
4312
nloop
=
Int_t
(
fWord7
[1]);
4313
if
(
nloop
<= 0)
nloop
=
fNpar
+ 4;
4314
nparx
=
fNpar
;
4315
nparp1
=
fNpar
+ 1;
4316
wg
= 1 /
Double_t
(
fNpar
);
4317
sigsav
=
fEDM
;
4318
fApsi
=
fAmin
;
4319
iswtr
=
fISW
[4] - 2*
fItaur
;
4320
for
(i = 1; i <=
fNpar
; ++i) {
4321
fXt
[i-1] =
fX
[i-1];
4322
fIMPRdsav
[i-1] =
fWerr
[i-1];
4323
for
(
j
= 1;
j
<= i; ++
j
) {
4324
ndex
= i*(i-1) / 2 +
j
;
4325
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1] =
fVhmat
[
ndex
-1];
4326
fP
[
j
+ i*
fMaxpar
-
fMaxpar
-1] =
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1];
4327
}
4328
}
4329
mnvert
(
fP
,
fMaxint
,
fMaxint
,
fNpar
,
ifail
);
4330
if
(
ifail
>= 1)
goto
L280
;
4331
// Save inverted matrix in VT
4332
for
(i = 1; i <=
fNpar
; ++i) {
4333
ndex
= i*(i-1) / 2;
4334
for
(
j
= 1;
j
<= i; ++
j
) {
4335
++
ndex
;
4336
fVthmat
[
ndex
-1] =
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1];
4337
}
4338
}
4339
loop = 0;
4340
4341
L20
:
4342
for
(i = 1; i <=
fNpar
; ++i) {
4343
fDirin
[i-1] =
fIMPRdsav
[i-1]*2;
4344
mnrn15
(
rnum
,
iseed
);
4345
fX
[i-1] =
fXt
[i-1] +
fDirin
[i-1]*2*(
rnum
- .5);
4346
}
4347
++loop;
4348
reg
= 2;
4349
if
(
fISW
[4] >= 0) {
4350
Printf
(
"START ATTEMPT NO.%2d TO FIND NEW MINIMUM"
,loop);
4351
}
4352
L30
:
4353
mncalf
(
fX
,
ycalf
);
4354
fAmin
=
ycalf
;
4355
// set up random simplex
4356
jl
=
nparp1
;
4357
jh
=
nparp1
;
4358
fIMPRy
[
nparp1
-1] =
fAmin
;
4359
amax
=
fAmin
;
4360
for
(i = 1; i <=
fNpar
; ++i) {
4361
xi =
fX
[i-1];
4362
mnrn15
(
rnum
,
iseed
);
4363
fX
[i-1] = xi -
fDirin
[i-1]*(
rnum
- .5);
4364
mncalf
(
fX
,
ycalf
);
4365
fIMPRy
[i-1] =
ycalf
;
4366
if
(
fIMPRy
[i-1] <
fAmin
) {
4367
fAmin
=
fIMPRy
[i-1];
4368
jl
= i;
4369
}
else
if
(
fIMPRy
[i-1] >
amax
) {
4370
amax
=
fIMPRy
[i-1];
4371
jh
= i;
4372
}
4373
for
(
j
= 1;
j
<=
fNpar
; ++
j
) {
fP
[
j
+ i*
fMaxpar
-
fMaxpar
-1] =
fX
[
j
-1]; }
4374
fP
[i +
nparp1
*
fMaxpar
-
fMaxpar
-1] = xi;
4375
fX
[i-1] = xi;
4376
}
4377
4378
fEDM
=
fAmin
;
4379
sig2
=
fEDM
;
4380
// start main loop
4381
L50
:
4382
if
(
fAmin
< 0)
goto
L95
;
4383
if
(
fISW
[1] <= 2)
goto
L280
;
4384
ep
=
fAmin
*.1;
4385
if
(
sig2
<
ep
&&
fEDM
<
ep
)
goto
L100
;
4386
sig2
=
fEDM
;
4387
if
(
fNfcn
-
npfn
>
fNfcnmx
)
goto
L300
;
4388
// calculate new point * by reflection
4389
for
(i = 1; i <=
fNpar
; ++i) {
4390
pb
= 0;
4391
for
(
j
= 1;
j
<=
nparp1
; ++
j
) {
pb
+=
wg
*
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1]; }
4392
fPbar
[i-1] =
pb
-
wg
*
fP
[i +
jh
*
fMaxpar
-
fMaxpar
-1];
4393
fPstar
[i-1] =
fPbar
[i-1]*2 -
fP
[i +
jh
*
fMaxpar
-
fMaxpar
-1]*1;
4394
}
4395
mncalf
(
fPstar
,
ycalf
);
4396
ystar
=
ycalf
;
4397
if
(
ystar
>=
fAmin
)
goto
L70
;
4398
// point * better than jl, calculate new point **
4399
for
(i = 1; i <=
fNpar
; ++i) {
4400
fPstst
[i-1] =
fPstar
[i-1]*2 +
fPbar
[i- 1]*-1;
4401
}
4402
mncalf
(
fPstst
,
ycalf
);
4403
ystst
=
ycalf
;
4404
if
(
ystst
<
fIMPRy
[
jl
-1])
goto
L67
;
4405
mnrazz
(
ystar
,
fPstar
,
fIMPRy
,
jh
,
jl
);
4406
goto
L50
;
4407
L67
:
4408
mnrazz
(
ystst
,
fPstst
,
fIMPRy
,
jh
,
jl
);
4409
goto
L50
;
4410
// point * is not as good as jl
4411
L70
:
4412
if
(
ystar
>=
fIMPRy
[
jh
-1])
goto
L73
;
4413
jhold
=
jh
;
4414
mnrazz
(
ystar
,
fPstar
,
fIMPRy
,
jh
,
jl
);
4415
if
(
jhold
!=
jh
)
goto
L50
;
4416
// calculate new point **
4417
L73
:
4418
for
(i = 1; i <=
fNpar
; ++i) {
4419
fPstst
[i-1] =
fP
[i +
jh
*
fMaxpar
-
fMaxpar
-1]*.5 +
fPbar
[i-1]*.5;
4420
}
4421
mncalf
(
fPstst
,
ycalf
);
4422
ystst
=
ycalf
;
4423
if
(
ystst
>
fIMPRy
[
jh
-1])
goto
L30
;
4424
// point ** is better than jh
4425
if
(
ystst
<
fAmin
)
goto
L67
;
4426
mnrazz
(
ystst
,
fPstst
,
fIMPRy
,
jh
,
jl
);
4427
goto
L50
;
4428
// end main loop
4429
L95
:
4430
if
(
fISW
[4] >= 0) {
4431
Printf
(
" AN IMPROVEMENT ON THE PREVIOUS MINIMUM HAS BEEN FOUND"
);
4432
}
4433
reg
= .1;
4434
// ask if point is new
4435
L100
:
4436
mninex
(
fX
);
4437
Eval
(
nparx
,
fGin
,
fAmin
,
fU
, 4); ++
fNfcn
;
4438
for
(i = 1; i <=
fNpar
; ++i) {
4439
fDirin
[i-1] =
reg
*
fIMPRdsav
[i-1];
4440
if
(
TMath::Abs
(
fX
[i-1] -
fXt
[i-1]) >
fDirin
[i-1])
goto
L150
;
4441
}
4442
goto
L230
;
4443
L150
:
4444
fNfcnmx
=
fNfcnmx
+
npfn
-
fNfcn
;
4445
npfn
=
fNfcn
;
4446
mnsimp
();
4447
if
(
fAmin
>=
fApsi
)
goto
L325
;
4448
for
(i = 1; i <=
fNpar
; ++i) {
4449
fDirin
[i-1] =
fIMPRdsav
[i-1]*.1;
4450
if
(
TMath::Abs
(
fX
[i-1] -
fXt
[i-1]) >
fDirin
[i-1])
goto
L250
;
4451
}
4452
L230
:
4453
if
(
fAmin
<
fApsi
)
goto
L350
;
4454
goto
L325
;
4455
/* truly new minimum */
4456
L250
:
4457
fLnewmn
=
kTRUE
;
4458
if
(
fISW
[1] >= 1) {
4459
fISW
[1] = 1;
4460
fDcovar
=
TMath::Max
(
fDcovar
,.5);
4461
}
else
fDcovar
= 1;
4462
fItaur
= 0;
4463
fNfcnmx
=
fNfcnmx
+
npfn
-
fNfcn
;
4464
fCstatu
=
"NEW MINIMU"
;
4465
if
(
fISW
[4] >= 0) {
4466
Printf
(
" IMPROVE HAS FOUND A TRULY NEW MINIMUM"
);
4467
Printf
(
" *************************************"
);
4468
}
4469
return
;
4470
// return to previous region
4471
L280
:
4472
if
(
fISW
[4] > 0) {
4473
Printf
(
" COVARIANCE MATRIX WAS NOT POSITIVE-DEFINITE"
);
4474
}
4475
goto
L325
;
4476
L300
:
4477
fISW
[0] = 1;
4478
L325
:
4479
for
(i = 1; i <=
fNpar
; ++i) {
4480
fDirin
[i-1] =
fIMPRdsav
[i-1]*.01;
4481
fX
[i-1] =
fXt
[i-1];
4482
}
4483
fAmin
=
fApsi
;
4484
fEDM
=
sigsav
;
4485
L350
:
4486
mninex
(
fX
);
4487
if
(
fISW
[4] > 0) {
4488
Printf
(
" IMPROVE HAS RETURNED TO REGION OF ORIGINAL MINIMUM"
);
4489
}
4490
fCstatu
=
"UNCHANGED "
;
4491
mnrset
(0);
4492
if
(
fISW
[1] < 2)
goto
L380
;
4493
if
(loop <
nloop
&&
fISW
[0] < 1)
goto
L20
;
4494
L380
:
4495
if
(
iswtr
>= 0)
mnprin
(5,
fAmin
);
4496
fItaur
= 0;
4497
}
4498
4499
////////////////////////////////////////////////////////////////////////////////
4500
/// Transforms from internal coordinates (PINT) to external (U)
4501
///
4502
/// The minimising routines which work in
4503
/// internal coordinates call this routine before calling FCN.
4504
4505
void
TMinuit::mninex
(
Double_t
*
pint
)
4506
{
4507
Int_t
i,
j
;
4508
4509
for
(
j
= 0;
j
<
fNpar
; ++
j
) {
4510
i =
fNexofi
[
j
]-1;
4511
if
(
fNvarl
[i] == 1) {
4512
fU
[i] =
pint
[
j
];
4513
}
else
{
4514
fU
[i] =
fAlim
[i] + (
TMath::Sin
(
pint
[
j
]) + 1)*.5*(
fBlim
[i] -
fAlim
[i]);
4515
}
4516
}
4517
}
4518
4519
////////////////////////////////////////////////////////////////////////////////
4520
/// Main initialization member function for MINUIT
4521
///
4522
/// It initializes some constants
4523
/// (including the logical I/O unit nos.),
4524
4525
void
TMinuit::mninit
(
Int_t
i1
,
Int_t
i2
,
Int_t
i3
)
4526
{
4527
/* Local variables */
4528
volatile
Double_t
epsp1
;
4529
Double_t
piby2
,
epstry
,
epsbak
,
distnn
;
4530
Int_t
i,
idb
;
4531
4532
// I/O unit numbers
4533
fIsysrd
=
i1
;
4534
fIsyswr
=
i2
;
4535
fIstkwr
[0] =
fIsyswr
;
4536
fNstkwr
= 1;
4537
fIsyssa
=
i3
;
4538
fNstkrd
= 0;
4539
// version identifier
4540
fCvrsn
=
"95.03++ "
;
4541
// some CONSTANT
4542
fMaxint
=
fMaxpar
;
4543
fMaxext
= 2*
fMaxpar
;
4544
fUndefi
= -54321;
4545
fBigedm
= 123456;
4546
fCundef
=
")UNDEFINED"
;
4547
fCovmes
[0] =
"NO ERROR MATRIX "
;
4548
fCovmes
[1] =
"ERR MATRIX APPROXIMATE"
;
4549
fCovmes
[2] =
"ERR MATRIX NOT POS-DEF"
;
4550
fCovmes
[3] =
"ERROR MATRIX ACCURATE "
;
4551
// some starting values
4552
fNblock
= 0;
4553
fIcomnd
= 0;
4554
fCtitl
=
fCundef
;
4555
fCfrom
=
"INPUT "
;
4556
fNfcn
= 0;
4557
fNfcnfr
=
fNfcn
;
4558
fCstatu
=
"INITIALIZE"
;
4559
fISW
[2] = 0;
4560
fISW
[3] = 0;
4561
fISW
[4] = 1;
4562
// fISW[5]=0 for batch jobs, =1 for interactive jobs
4563
// =-1 for originally interactive temporarily batch
4564
4565
fISW
[5] = 0;
4566
// if (intrac(&dummy)) fISW[5] = 1;
4567
// DEBUG options set to default values
4568
for
(
idb
= 0;
idb
<= 10; ++
idb
) {
fIdbg
[
idb
] = 0; }
4569
fLrepor
=
kFALSE
;
4570
fLwarn
=
kTRUE
;
4571
fLimset
=
kFALSE
;
4572
fLnewmn
=
kFALSE
;
4573
fIstrat
= 1;
4574
fItaur
= 0;
4575
// default page dimensions and 'new page' carriage control integer
4576
fNpagwd
= 120;
4577
fNpagln
= 56;
4578
fNewpag
= 1;
4579
if
(
fISW
[5] > 0) {
4580
fNpagwd
= 80;
4581
fNpagln
= 30;
4582
fNewpag
= 0;
4583
}
4584
fUp
= 1;
4585
fUpdflt
=
fUp
;
4586
// determine machine accuracy epsmac
4587
epstry
= .5;
4588
for
(i = 1; i <= 100; ++i) {
4589
epstry
*= .5;
4590
epsp1
=
epstry
+ 1;
4591
mntiny
(
epsp1
,
epsbak
);
4592
if
(
epsbak
<
epstry
)
goto
L35
;
4593
}
4594
epstry
= 1
e
-7;
4595
fEpsmac
=
epstry
*4;
4596
Printf
(
" MNINIT UNABLE TO DETERMINE ARITHMETIC PRECISION. WILL ASSUME:%g"
,
fEpsmac
);
4597
L35
:
4598
fEpsmac
=
epstry
*8;
4599
fEpsma2
=
TMath::Sqrt
(
fEpsmac
)*2;
4600
// the vlims are a non-negligible distance from pi/2
4601
// used by MNPINT to set variables "near" the physical limits
4602
piby2
=
TMath::ATan
(1)*2;
4603
distnn
=
TMath::Sqrt
(
fEpsma2
)*8;
4604
fVlimhi
=
piby2
-
distnn
;
4605
fVlimlo
= -
piby2
+
distnn
;
4606
mncler
();
4607
// Printf(" MINUIT RELEASE %s INITIALIZED. DIMENSIONS 100/50 EPSMAC=%g",(const char*)fCvrsn,fEpsmac);
4608
}
4609
4610
////////////////////////////////////////////////////////////////////////////////
4611
/// Interprets the SET LIM command, to reset the parameter limits
4612
///
4613
/// Called from MNSET
4614
4615
void
TMinuit::mnlims
()
4616
{
4617
/* Local variables */
4618
Double_t
dxdi
,
snew
;
4619
Int_t
kint,
i2
,
newcod
,
ifx
=0,
inu
;
4620
4621
fCfrom
=
"SET LIM "
;
4622
fNfcnfr
=
fNfcn
;
4623
fCstatu
=
"NO CHANGE "
;
4624
i2
=
Int_t
(
fWord7
[0]);
4625
if
(
i2
>
fMaxext
||
i2
< 0)
goto
L900
;
4626
if
(
i2
> 0)
goto
L30
;
4627
// set limits on all parameters
4628
newcod
= 4;
4629
if
(
fWord7
[1] ==
fWord7
[2])
newcod
= 1;
4630
for
(
inu
= 1;
inu
<=
fNu
; ++
inu
) {
4631
if
(
fNvarl
[
inu
-1] <= 0)
continue
;
4632
if
(
fNvarl
[
inu
-1] == 1 &&
newcod
== 1)
continue
;
4633
kint =
fNiofex
[
inu
-1];
4634
// see if parameter has been fixed
4635
if
(kint <= 0) {
4636
if
(
fISW
[4] >= 0) {
4637
Printf
(
" LIMITS NOT CHANGED FOR FIXED PARAMETER:%4d"
,
inu
);
4638
}
4639
continue
;
4640
}
4641
if
(
newcod
== 1) {
4642
// remove limits from parameter
4643
if
(
fISW
[4] > 0) {
4644
Printf
(
" LIMITS REMOVED FROM PARAMETER :%3d"
,
inu
);
4645
}
4646
fCstatu
=
"NEW LIMITS"
;
4647
mndxdi
(
fX
[kint-1], kint-1,
dxdi
);
4648
snew
=
fGstep
[kint-1]*
dxdi
;
4649
fGstep
[kint-1] =
TMath::Abs
(
snew
);
4650
fNvarl
[
inu
-1] = 1;
4651
}
else
{
4652
// put limits on parameter
4653
fAlim
[
inu
-1] =
TMath::Min
(
fWord7
[1],
fWord7
[2]);
4654
fBlim
[
inu
-1] =
TMath::Max
(
fWord7
[1],
fWord7
[2]);
4655
if
(
fISW
[4] > 0) {
4656
Printf
(
" PARAMETER %3d LIMITS SET TO %15.5g%15.5g"
,
inu
,
fAlim
[
inu
-1],
fBlim
[
inu
-1]);
4657
}
4658
fNvarl
[
inu
-1] = 4;
4659
fCstatu
=
"NEW LIMITS"
;
4660
fGstep
[kint-1] = -.1;
4661
}
4662
}
4663
goto
L900
;
4664
// set limits on one parameter
4665
L30
:
4666
if
(
fNvarl
[
i2
-1] <= 0) {
4667
Printf
(
" PARAMETER %3d IS NOT VARIABLE."
,
i2
);
4668
goto
L900
;
4669
}
4670
kint =
fNiofex
[
i2
-1];
4671
// see if parameter was fixed
4672
if
(kint == 0) {
4673
Printf
(
" REQUEST TO CHANGE LIMITS ON FIXED PARAMETER:%3d"
,
i2
);
4674
for
(
ifx
= 1;
ifx
<=
fNpfix
; ++
ifx
) {
4675
if
(
i2
==
fIpfix
[
ifx
-1])
goto
L92
;
4676
}
4677
Printf
(
" MINUIT BUG IN MNLIMS. SEE F. JAMES"
);
4678
L92
:
4679
;
4680
}
4681
if
(
fWord7
[1] !=
fWord7
[2])
goto
L235
;
4682
// remove limits
4683
if
(
fNvarl
[
i2
-1] != 1) {
4684
if
(
fISW
[4] > 0) {
4685
Printf
(
" LIMITS REMOVED FROM PARAMETER %2d"
,
i2
);
4686
}
4687
fCstatu
=
"NEW LIMITS"
;
4688
if
(kint <= 0) {
4689
fGsteps
[
ifx
-1] =
TMath::Abs
(
fGsteps
[
ifx
-1]);
4690
}
else
{
4691
mndxdi
(
fX
[kint-1], kint-1,
dxdi
);
4692
if
(
TMath::Abs
(
dxdi
) < .01)
dxdi
= .01;
4693
fGstep
[kint-1] =
TMath::Abs
(
fGstep
[kint-1]*
dxdi
);
4694
fGrd
[kint-1] *=
dxdi
;
4695
}
4696
fNvarl
[
i2
-1] = 1;
4697
}
else
{
4698
Printf
(
" NO LIMITS SPECIFIED. PARAMETER %3d IS ALREADY UNLIMITED. NO CHANGE."
,
i2
);
4699
}
4700
goto
L900
;
4701
// put on limits
4702
L235
:
4703
fAlim
[
i2
-1] =
TMath::Min
(
fWord7
[1],
fWord7
[2]);
4704
fBlim
[
i2
-1] =
TMath::Max
(
fWord7
[1],
fWord7
[2]);
4705
fNvarl
[
i2
-1] = 4;
4706
if
(
fISW
[4] > 0) {
4707
Printf
(
" PARAMETER %3d LIMITS SET TO %15.5g%15.5g"
,
i2
,
fAlim
[
i2
-1],
fBlim
[
i2
-1]);
4708
}
4709
fCstatu
=
"NEW LIMITS"
;
4710
if
(kint <= 0)
fGsteps
[
ifx
-1] = -.1;
4711
else
fGstep
[kint-1] = -.1;
4712
4713
L900
:
4714
if
(
fCstatu
!=
"NO CHANGE "
) {
4715
mnexin
(
fX
);
4716
mnrset
(1);
4717
}
4718
}
4719
4720
////////////////////////////////////////////////////////////////////////////////
4721
/// Perform a line search from position START
4722
///
4723
/// along direction STEP, where the length of vector STEP
4724
/// gives the expected position of minimum.
4725
/// - FSTART is value of function at START
4726
/// - SLOPE (if non-zero) is df/dx along STEP at START
4727
/// - TOLER is initial tolerance of minimum in direction STEP
4728
///
4729
/// SLAMBG and ALPHA control the maximum individual steps allowed.
4730
/// The first step is always =1. The max length of second step is SLAMBG.
4731
/// The max size of subsequent steps is the maximum previous successful
4732
/// step multiplied by ALPHA + the size of most recent successful step,
4733
/// but cannot be smaller than SLAMBG.
4734
4735
void
TMinuit::mnline
(
Double_t
*start,
Double_t
fstart
,
Double_t
*step,
Double_t
slope
,
Double_t
toler
)
4736
{
4737
/* Local variables */
4738
Double_t
xpq
[12],
ypq
[12],
slam
,
sdev
,
coeff
[3],
denom
,
flast
;
4739
Double_t
fvals
[3],
xvals
[3],
f1
,
fvmin
,
xvmin
, ratio, f2, f3 = 0.,
fvmax
;
4740
Double_t
toler8
,
toler9
,
overal
,
undral
,
slamin
,
slamax
,
slopem
;
4741
Int_t
i,
nparx
=0,
nvmax
=0,
nxypt
,
kk
,
ipt
;
4742
Bool_t
ldebug
;
4743
TString
cmess
;
4744
char
chpq
[13];
4745
int
l65
,
l70
,
l80
;
4746
4747
/* Function Body */
4748
l65
= 0;
l70
= 0;
l80
= 0;
4749
ldebug
=
fIdbg
[1] >= 1;
4750
// starting values for overall limits on total step SLAM
4751
overal
= 1
e3
;
4752
undral
= -100;
4753
// debug check if start is ok
4754
if
(
ldebug
) {
4755
mninex
(&start[0]);
4756
Eval
(
nparx
,
fGin
,
f1
,
fU
, 4); ++
fNfcn
;
4757
if
(
f1
!=
fstart
) {
4758
Printf
(
" MNLINE start point not consistent, F values, parameters="
);
4759
for
(
kk
= 1;
kk
<=
fNpar
; ++
kk
) {
4760
Printf
(
" %14.5e"
,
fX
[
kk
-1]);
4761
}
4762
}
4763
}
4764
// set up linear search along STEP
4765
fvmin
=
fstart
;
4766
xvmin
= 0;
4767
nxypt
= 1;
4768
chpq
[0] =
charal
[0];
4769
xpq
[0] = 0;
4770
ypq
[0] =
fstart
;
4771
// SLAMIN = smallest possible value of ABS(SLAM)
4772
slamin
= 0;
4773
for
(i = 1; i <=
fNpar
; ++i) {
4774
if
(step[i-1] != 0) {
4775
ratio =
TMath::Abs
(start[i-1] / step[i-1]);
4776
if
(
slamin
== 0)
slamin
= ratio;
4777
if
(ratio <
slamin
)
slamin
= ratio;
4778
}
4779
fX
[i-1] = start[i-1] + step[i-1];
4780
}
4781
if
(
slamin
== 0)
slamin
=
fEpsmac
;
4782
slamin
*=
fEpsma2
;
4783
nparx
=
fNpar
;
4784
4785
mninex
(
fX
);
4786
Eval
(
nparx
,
fGin
,
f1
,
fU
, 4); ++
fNfcn
;
4787
++
nxypt
;
4788
chpq
[
nxypt
-1] =
charal
[
nxypt
-1];
4789
xpq
[
nxypt
-1] = 1;
4790
ypq
[
nxypt
-1] =
f1
;
4791
if
(
f1
<
fstart
) {
4792
fvmin
=
f1
;
4793
xvmin
= 1;
4794
}
4795
// quadr interp using slope GDEL and two points
4796
slam
= 1;
4797
toler8
=
toler
;
4798
slamax
= 5;
4799
flast
=
f1
;
4800
// can iterate on two-points (cut) if no imprvmnt
4801
4802
do
{
4803
denom
= (
flast
-
fstart
-
slope
*
slam
)*2 / (
slam
*
slam
);
4804
slam
= 1;
4805
if
(
denom
!= 0)
slam
= -
slope
/
denom
;
4806
if
(
slam
< 0)
slam
=
slamax
;
4807
if
(
slam
>
slamax
)
slam
=
slamax
;
4808
if
(
slam
<
toler8
)
slam
=
toler8
;
4809
if
(
slam
<
slamin
) {
4810
l80
= 1;
4811
break
;
4812
}
4813
if
(
TMath::Abs
(
slam
- 1) <
toler8
&&
f1
<
fstart
) {
4814
l70
= 1;
4815
break
;
4816
}
4817
if
(
TMath::Abs
(
slam
- 1) <
toler8
)
slam
=
toler8
+ 1;
4818
if
(
nxypt
>= 12) {
4819
l65
= 1;
4820
break
;
4821
}
4822
for
(i = 1; i <=
fNpar
; ++i) {
fX
[i-1] = start[i-1] +
slam
*step[i-1]; }
4823
mninex
(
fX
);
4824
nparx
=
fNpar
;
4825
Eval
(
nparx
,
fGin
, f2,
fU
, 4); ++
fNfcn
;
4826
++
nxypt
;
4827
chpq
[
nxypt
-1] =
charal
[
nxypt
-1];
4828
xpq
[
nxypt
-1] =
slam
;
4829
ypq
[
nxypt
-1] = f2;
4830
if
(f2 <
fvmin
) {
4831
fvmin
= f2;
4832
xvmin
=
slam
;
4833
}
4834
if
(
fstart
==
fvmin
) {
4835
flast
= f2;
4836
toler8
=
toler
*
slam
;
4837
overal
=
slam
-
toler8
;
4838
slamax
=
overal
;
4839
}
4840
}
while
(
fstart
==
fvmin
);
4841
4842
if
(!
l65
&& !
l70
&& !
l80
) {
4843
// quadr interp using 3 points
4844
xvals
[0] =
xpq
[0];
4845
fvals
[0] =
ypq
[0];
4846
xvals
[1] =
xpq
[
nxypt
-2];
4847
fvals
[1] =
ypq
[
nxypt
-2];
4848
xvals
[2] =
xpq
[
nxypt
-1];
4849
fvals
[2] =
ypq
[
nxypt
-1];
4850
// begin iteration, calculate desired step
4851
do
{
4852
slamax
=
TMath::Max
(
slamax
,
TMath::Abs
(
xvmin
)*2);
4853
mnpfit
(
xvals
,
fvals
, 3,
coeff
,
sdev
);
4854
if
(
coeff
[2] <= 0) {
4855
slopem
=
coeff
[2]*2*
xvmin
+
coeff
[1];
4856
if
(
slopem
<= 0)
slam
=
xvmin
+
slamax
;
4857
else
slam
=
xvmin
-
slamax
;
4858
}
else
{
4859
slam
= -
coeff
[1] / (
coeff
[2]*2);
4860
if
(
slam
>
xvmin
+
slamax
)
slam
=
xvmin
+
slamax
;
4861
if
(
slam
<
xvmin
-
slamax
)
slam
=
xvmin
-
slamax
;
4862
}
4863
if
(
slam
> 0) {
4864
if
(
slam
>
overal
)
4865
slam
=
overal
;
4866
else
if
(
slam
<
undral
)
4867
slam
=
undral
;
4868
}
4869
4870
// come here if step was cut below
4871
do
{
4872
toler9
=
TMath::Max
(
toler8
,
TMath::Abs
(
toler8
*
slam
));
4873
for
(
ipt
= 1;
ipt
<= 3; ++
ipt
) {
4874
if
(
TMath::Abs
(
slam
-
xvals
[
ipt
-1]) <
toler9
) {
4875
l70
= 1;
4876
break
;
4877
}
4878
}
4879
if
(
l70
)
break
;
4880
// take the step
4881
if
(
nxypt
>= 12) {
4882
l65
= 1;
4883
break
;
4884
}
4885
for
(i = 1; i <=
fNpar
; ++i) {
fX
[i-1] = start[i-1] +
slam
*step[i-1]; }
4886
mninex
(
fX
);
4887
Eval
(
nparx
,
fGin
, f3,
fU
, 4); ++
fNfcn
;
4888
++
nxypt
;
4889
chpq
[
nxypt
-1] =
charal
[
nxypt
-1];
4890
xpq
[
nxypt
-1] =
slam
;
4891
ypq
[
nxypt
-1] = f3;
4892
// find worst previous point out of three
4893
fvmax
=
fvals
[0];
4894
nvmax
= 1;
4895
if
(
fvals
[1] >
fvmax
) {
4896
fvmax
=
fvals
[1];
4897
nvmax
= 2;
4898
}
4899
if
(
fvals
[2] >
fvmax
) {
4900
fvmax
=
fvals
[2];
4901
nvmax
= 3;
4902
}
4903
// if latest point worse than all three previous, cut step
4904
if
(f3 >=
fvmax
) {
4905
if
(
nxypt
>= 12) {
4906
l65
= 1;
4907
break
;
4908
}
4909
if
(
slam
>
xvmin
)
overal
=
TMath::Min
(
overal
,
slam
-
toler8
);
4910
if
(
slam
<
xvmin
)
undral
=
TMath::Max
(
undral
,
slam
+
toler8
);
4911
slam
= (
slam
+
xvmin
)*.5;
4912
}
4913
}
while
(f3 >=
fvmax
);
4914
4915
// prepare another iteration, replace worst previous point
4916
if
(
l65
||
l70
)
break
;
4917
4918
xvals
[
nvmax
-1] =
slam
;
4919
fvals
[
nvmax
-1] = f3;
4920
if
(f3 <
fvmin
) {
4921
fvmin
= f3;
4922
xvmin
=
slam
;
4923
}
else
{
4924
if
(
slam
>
xvmin
)
overal
=
TMath::Min
(
overal
,
slam
-
toler8
);
4925
if
(
slam
<
xvmin
)
undral
=
TMath::Max
(
undral
,
slam
+
toler8
);
4926
}
4927
}
while
(
nxypt
< 12);
4928
}
4929
4930
// end of iteration
4931
// stop because too many iterations
4932
if
(!
l70
&& !
l80
&&
ldebug
) {
4933
cmess
=
" LINE SEARCH HAS EXHAUSTED THE LIMIT OF FUNCTION CALLS "
;
4934
Printf
(
" MNLINE DEBUG: steps="
);
4935
for
(
kk
= 1;
kk
<=
fNpar
; ++
kk
) {
4936
Printf
(
" %12.4g"
,step[
kk
-1]);
4937
}
4938
}
4939
// stop because within tolerance
4940
if
(
l70
&&
ldebug
)
cmess
=
" LINE SEARCH HAS ATTAINED TOLERANCE "
;
4941
if
(
l80
&&
ldebug
)
cmess
=
" STEP SIZE AT ARITHMETICALLY ALLOWED MINIMUM"
;
4942
4943
fAmin
=
fvmin
;
4944
for
(i = 1; i <=
fNpar
; ++i) {
4945
fDirin
[i-1] = step[i-1]*
xvmin
;
4946
fX
[i-1] = start[i-1] +
fDirin
[i-1];
4947
}
4948
mninex
(
fX
);
4949
if
(
xvmin
< 0) {
4950
mnwarn
(
"D"
,
"MNLINE"
,
" LINE MINIMUM IN BACKWARDS DIRECTION"
);
4951
}
4952
if
(
fvmin
==
fstart
) {
4953
mnwarn
(
"D"
,
"MNLINE"
,
" LINE SEARCH FINDS NO IMPROVEMENT "
);
4954
}
4955
if
(
ldebug
) {
4956
Printf
(
" AFTER %3d POINTS,%s"
,
nxypt
,(
const
char
*)
cmess
);
4957
mnplot
(
xpq
,
ypq
,
chpq
,
nxypt
,
fNpagwd
,
fNpagln
);
4958
}
4959
}
4960
4961
////////////////////////////////////////////////////////////////////////////////
4962
/// Prints the covariance matrix v when KODE=1
4963
///
4964
/// always prints the global correlations, and
4965
/// calculates and prints the individual correlation coefficients
4966
4967
void
TMinuit::mnmatu
(
Int_t
kode
)
4968
{
4969
/* Local variables */
4970
Int_t
ndex
, i,
j
,
m
,
n
,
ncoef
,
nparm
,
id
, it, ix;
4971
Int_t
nsofar
,
ndi
,
ndj
,
iso
,
isw2
,
isw5
;
4972
TString
ctemp
;
4973
4974
isw2
=
fISW
[1];
4975
if
(
isw2
< 1) {
4976
Printf
(
"%s"
,(
const
char
*)
fCovmes
[
isw2
]);
4977
return
;
4978
}
4979
if
(
fNpar
== 0) {
4980
Printf
(
" MNMATU: NPAR=0"
);
4981
return
;
4982
}
4983
// external error matrix
4984
if
(
kode
== 1) {
4985
isw5
=
fISW
[4];
4986
fISW
[4] = 2;
4987
mnemat
(
fP
,
fMaxint
);
4988
if
(
isw2
< 3) {
4989
Printf
(
"%s"
,(
const
char
*)
fCovmes
[
isw2
]);
4990
}
4991
fISW
[4] =
isw5
;
4992
}
4993
// correlation coeffs
4994
if
(
fNpar
<= 1)
return
;
4995
mnwerr
();
4996
// NCOEF is number of coeff. that fit on one line, not to exceed 20
4997
ncoef
= (
fNpagwd
- 19) / 6;
4998
ncoef
=
TMath::Min
(
ncoef
,20);
4999
nparm
=
TMath::Min
(
fNpar
,
ncoef
);
5000
Printf
(
" PARAMETER CORRELATION COEFFICIENTS "
);
5001
ctemp
=
" NO. GLOBAL"
;
5002
for
(
id
= 1;
id
<=
nparm
; ++
id
) {
5003
ctemp
+=
TString::Format
(
" %6d"
,
fNexofi
[
id
-1]);
5004
}
5005
Printf
(
"%s"
,(
const
char
*)
ctemp
);
5006
for
(i = 1; i <=
fNpar
; ++i) {
5007
ix =
fNexofi
[i-1];
5008
ndi
= i*(i + 1) / 2;
5009
for
(
j
= 1;
j
<=
fNpar
; ++
j
) {
5010
m
=
TMath::Max
(i,
j
);
5011
n
=
TMath::Min
(i,
j
);
5012
ndex
=
m
*(
m
-1) / 2 +
n
;
5013
ndj
=
j
*(
j
+ 1) / 2;
5014
fMATUvline
[
j
-1] =
fVhmat
[
ndex
-1] /
TMath::Sqrt
(
TMath::Abs
(
fVhmat
[
ndi
-1]*
fVhmat
[
ndj
-1]));
5015
}
5016
nparm
=
TMath::Min
(
fNpar
,
ncoef
);
5017
ctemp
.Form(
" %3d %7.5f "
,ix,
fGlobcc
[i-1]);
5018
for
(it = 1; it <=
nparm
; ++it) {
5019
ctemp
+=
TString::Format
(
" %6.3f"
,
fMATUvline
[it-1]);
5020
}
5021
Printf
(
"%s"
,(
const
char
*)
ctemp
);
5022
if
(i <=
nparm
)
continue
;
5023
ctemp
=
" "
;
5024
for
(
iso
= 1;
iso
<= 10; ++
iso
) {
5025
nsofar
=
nparm
;
5026
nparm
=
TMath::Min
(
fNpar
,
nsofar
+
ncoef
);
5027
for
(it =
nsofar
+ 1; it <=
nparm
; ++it) {
5028
ctemp
=
ctemp
+
TString::Format
(
" %6.3f"
,
fMATUvline
[it-1]);
5029
}
5030
Printf
(
"%s"
,(
const
char
*)
ctemp
);
5031
if
(i <=
nparm
)
break
;
5032
}
5033
}
5034
if
(
isw2
< 3) {
5035
Printf
(
" %s"
,(
const
char
*)
fCovmes
[
isw2
]);
5036
}
5037
}
5038
5039
////////////////////////////////////////////////////////////////////////////////
5040
/// Performs a local function minimization
5041
///
5042
/// Performs a local function minimization using basically the
5043
/// method of Davidon-Fletcher-Powell as modified by Fletcher
5044
///
5045
/// ref. -- Fletcher, Comp.J. 13,317 (1970) "switching method"
5046
5047
void
TMinuit::mnmigr
()
5048
{
5049
/* Local variables */
5050
Double_t
gdel
,
gami
,
vlen
,
dsum
,
gssq
,
vsum
,
d
;
5051
Double_t
fzero
,
fs
, ri,
delgam
,
rhotol
;
5052
Double_t
gdgssq
,
gvg
,
vgi
;
5053
Int_t
npfn
,
ndex
,
iext
, i,
j
,
m
,
n
,
npsdf
,
nparx
;
5054
Int_t
iswtr
,
lined2
,
kk
,
nfcnmg
,
nrstrt
,iter;
5055
Bool_t
ldebug
;
5056
Double_t
toler
= 0.05;
5057
5058
if
(
fNpar
<= 0)
return
;
5059
if
(
fAmin
==
fUndefi
)
mnamin
();
5060
ldebug
=
kFALSE
;
if
(
fIdbg
[4] >= 1)
ldebug
=
kTRUE
;
5061
fCfrom
=
"MIGRAD "
;
5062
fNfcnfr
=
fNfcn
;
5063
nfcnmg
=
fNfcn
;
5064
fCstatu
=
"INITIATE "
;
5065
iswtr
=
fISW
[4] - 2*
fItaur
;
5066
npfn
=
fNfcn
;
5067
nparx
=
fNpar
;
5068
vlen
= (
Double_t
) (
fNpar
*(
fNpar
+ 1) / 2);
5069
nrstrt
= 0;
5070
npsdf
= 0;
5071
lined2
= 0;
5072
fISW
[3] = -1;
5073
rhotol
=
fApsi
*.001;
5074
if
(
iswtr
>= 1) {
5075
Printf
(
" START MIGRAD MINIMIZATION. STRATEGY %2d. CONVERGENCE WHEN EDM .LT.%9.2e"
,
fIstrat
,
rhotol
);
5076
}
5077
// initialization strategy
5078
if
(
fIstrat
< 2 ||
fISW
[1] >= 3)
goto
L2;
5079
// come (back) here to restart completely
5080
L1:
5081
if
(
nrstrt
>
fIstrat
) {
5082
fCstatu
=
"FAILED "
;
5083
fISW
[3] = -1;
5084
goto
L230
;
5085
}
5086
// get full covariance and gradient
5087
mnhess
();
5088
mnwerr
();
5089
npsdf
= 0;
5090
if
(
fISW
[1] >= 1)
goto
L10
;
5091
// get gradient at start point
5092
L2:
5093
mninex
(
fX
);
5094
if
(
fISW
[2] == 1) {
5095
Eval
(
nparx
,
fGin
,
fzero
,
fU
, 2); ++
fNfcn
;
5096
}
5097
mnderi
();
5098
if
(
fISW
[1] >= 1)
goto
L10
;
5099
// sometimes start with diagonal matrix
5100
for
(i = 1; i <=
fNpar
; ++i) {
5101
fMIGRxxs
[i-1] =
fX
[i-1];
5102
fMIGRstep
[i-1] = 0;
5103
}
5104
// do line search if second derivative negative
5105
++
lined2
;
5106
if
(
lined2
< (
fIstrat
+ 1)*
fNpar
) {
5107
for
(i = 1; i <=
fNpar
; ++i) {
5108
if
(
fG2
[i-1] > 0)
continue
;
5109
if
(
fGrd
[i-1] > 0)
fMIGRstep
[i-1] = -
TMath::Abs
(
fGstep
[i-1]);
5110
else
fMIGRstep
[i-1] =
TMath::Abs
(
fGstep
[i-1]);
5111
gdel
=
fMIGRstep
[i-1]*
fGrd
[i-1];
5112
fs
=
fAmin
;
5113
mnline
(
fMIGRxxs
,
fs
,
fMIGRstep
,
gdel
,
toler
);
5114
mnwarn
(
"D"
,
"MNMIGR"
,
"Negative G2 line search"
);
5115
iext
=
fNexofi
[i-1];
5116
if
(
ldebug
) {
5117
Printf
(
" Negative G2 line search, param %3d %13.3g%13.3g"
,
iext
,
fs
,
fAmin
);
5118
}
5119
goto
L2;
5120
}
5121
}
5122
// make diagonal error matrix
5123
for
(i = 1; i <=
fNpar
; ++i) {
5124
ndex
= i*(i-1) / 2;
5125
for
(
j
= 1;
j
<= i-1; ++
j
) {
5126
++
ndex
;
5127
fVhmat
[
ndex
-1] = 0;
5128
}
5129
++
ndex
;
5130
if
(
fG2
[i-1] <= 0)
fG2
[i-1] = 1;
5131
fVhmat
[
ndex
-1] = 2 /
fG2
[i-1];
5132
}
5133
fDcovar
= 1;
5134
if
(
ldebug
) {
5135
Printf
(
" DEBUG MNMIGR, STARTING MATRIX DIAGONAL, VHMAT="
);
5136
for
(
kk
= 1;
kk
<=
Int_t
(
vlen
); ++
kk
) {
5137
Printf
(
" %10.2g"
,
fVhmat
[
kk
-1]);
5138
}
5139
}
5140
// ready to start first iteration
5141
L10
:
5142
++
nrstrt
;
5143
if
(
nrstrt
>
fIstrat
+ 1) {
5144
fCstatu
=
"FAILED "
;
5145
goto
L230
;
5146
}
5147
fs
=
fAmin
;
5148
// get EDM and set up loop
5149
fEDM
= 0;
5150
for
(i = 1; i <=
fNpar
; ++i) {
5151
fMIGRgs
[i-1] =
fGrd
[i-1];
5152
fMIGRxxs
[i-1] =
fX
[i-1];
5153
ndex
= i*(i-1) / 2;
5154
for
(
j
= 1;
j
<= i-1; ++
j
) {
5155
++
ndex
;
5156
fEDM
+=
fMIGRgs
[i-1]*
fVhmat
[
ndex
-1]*
fMIGRgs
[
j
-1];
5157
}
5158
++
ndex
;
5159
fEDM
+=
fMIGRgs
[i-1]*
fMIGRgs
[i-1]*.5*
fVhmat
[
ndex
-1];
5160
}
5161
fEDM
=
fEDM
*.5*(
fDcovar
*3 + 1);
5162
if
(
fEDM
< 0) {
5163
mnwarn
(
"W"
,
"MIGRAD"
,
"STARTING MATRIX NOT POS-DEFINITE."
);
5164
fISW
[1] = 0;
5165
fDcovar
= 1;
5166
goto
L2;
5167
}
5168
if
(
fISW
[1] == 0)
fEDM
=
fBigedm
;
5169
iter = 0;
5170
mninex
(
fX
);
5171
mnwerr
();
5172
if
(
iswtr
>= 1)
mnprin
(3,
fAmin
);
5173
if
(
iswtr
>= 2)
mnmatu
(0);
5174
// start main loop
5175
L24
:
5176
if
(
fNfcn
-
npfn
>=
fNfcnmx
)
goto
L190
;
5177
gdel
= 0;
5178
gssq
= 0;
5179
for
(i = 1; i <=
fNpar
; ++i) {
5180
ri = 0;
5181
gssq
+=
fMIGRgs
[i-1]*
fMIGRgs
[i-1];
5182
for
(
j
= 1;
j
<=
fNpar
; ++
j
) {
5183
m
=
TMath::Max
(i,
j
);
5184
n
=
TMath::Min
(i,
j
);
5185
ndex
=
m
*(
m
-1) / 2 +
n
;
5186
ri +=
fVhmat
[
ndex
-1]*
fMIGRgs
[
j
-1];
5187
}
5188
fMIGRstep
[i-1] = ri*-.5;
5189
gdel
+=
fMIGRstep
[i-1]*
fMIGRgs
[i-1];
5190
}
5191
if
(
gssq
== 0) {
5192
mnwarn
(
"D"
,
"MIGRAD"
,
" FIRST DERIVATIVES OF FCN ARE ALL ZERO"
);
5193
goto
L300
;
5194
}
5195
// if gdel positive, V not posdef
5196
if
(
gdel
>= 0) {
5197
mnwarn
(
"D"
,
"MIGRAD"
,
" NEWTON STEP NOT DESCENT."
);
5198
if
(
npsdf
== 1)
goto
L1;
5199
mnpsdf
();
5200
npsdf
= 1;
5201
goto
L24
;
5202
}
5203
// do line search
5204
mnline
(
fMIGRxxs
,
fs
,
fMIGRstep
,
gdel
,
toler
);
5205
if
(
fAmin
==
fs
)
goto
L200
;
5206
fCfrom
=
"MIGRAD "
;
5207
fNfcnfr
=
nfcnmg
;
5208
fCstatu
=
"PROGRESS "
;
5209
// get gradient at new point
5210
mninex
(
fX
);
5211
if
(
fISW
[2] == 1) {
5212
Eval
(
nparx
,
fGin
,
fzero
,
fU
, 2); ++
fNfcn
;
5213
}
5214
mnderi
();
5215
// calculate new EDM
5216
npsdf
= 0;
5217
L81
:
5218
fEDM
= 0;
5219
gvg
= 0;
5220
delgam
= 0;
5221
gdgssq
= 0;
5222
for
(i = 1; i <=
fNpar
; ++i) {
5223
ri = 0;
5224
vgi
= 0;
5225
for
(
j
= 1;
j
<=
fNpar
; ++
j
) {
5226
m
=
TMath::Max
(i,
j
);
5227
n
=
TMath::Min
(i,
j
);
5228
ndex
=
m
*(
m
-1) / 2 +
n
;
5229
vgi
+=
fVhmat
[
ndex
-1]*(
fGrd
[
j
-1] -
fMIGRgs
[
j
-1]);
5230
ri +=
fVhmat
[
ndex
-1]*
fGrd
[
j
-1];
5231
}
5232
fMIGRvg
[i-1] =
vgi
*.5;
5233
gami
=
fGrd
[i-1] -
fMIGRgs
[i-1];
5234
gdgssq
+=
gami
*
gami
;
5235
gvg
+=
gami
*
fMIGRvg
[i-1];
5236
delgam
+=
fDirin
[i-1]*
gami
;
5237
fEDM
+=
fGrd
[i-1]*ri*.5;
5238
}
5239
fEDM
=
fEDM
*.5*(
fDcovar
*3 + 1);
5240
// if EDM negative, not positive-definite
5241
if
(
fEDM
< 0 ||
gvg
<= 0) {
5242
mnwarn
(
"D"
,
"MIGRAD"
,
"NOT POS-DEF. EDM OR GVG NEGATIVE."
);
5243
fCstatu
=
"NOT POSDEF"
;
5244
if
(
npsdf
== 1)
goto
L230
;
5245
mnpsdf
();
5246
npsdf
= 1;
5247
goto
L81
;
5248
}
5249
// print information about this iteration
5250
++iter;
5251
if
(
iswtr
>= 3 || (
iswtr
== 2 && iter % 10 == 1)) {
5252
mnwerr
();
5253
mnprin
(3,
fAmin
);
5254
}
5255
if
(
gdgssq
== 0) {
5256
mnwarn
(
"D"
,
"MIGRAD"
,
"NO CHANGE IN FIRST DERIVATIVES OVER LAST STEP"
);
5257
}
5258
if
(
delgam
< 0) {
5259
mnwarn
(
"D"
,
"MIGRAD"
,
"FIRST DERIVATIVES INCREASING ALONG SEARCH LINE"
);
5260
}
5261
// update covariance matrix
5262
fCstatu
=
"IMPROVEMENT"
;
5263
if
(
ldebug
) {
5264
Printf
(
" VHMAT 1 ="
);
5265
for
(
kk
= 1;
kk
<= 10; ++
kk
) {
5266
Printf
(
" %10.2g"
,
fVhmat
[
kk
-1]);
5267
}
5268
}
5269
dsum
= 0;
5270
vsum
= 0;
5271
for
(i = 1; i <=
fNpar
; ++i) {
5272
for
(
j
= 1;
j
<= i; ++
j
) {
5273
if
(
delgam
== 0 ||
gvg
== 0)
d
= 0;
5274
else
d
=
fDirin
[i-1]*
fDirin
[
j
-1] /
delgam
-
fMIGRvg
[i-1]*
fMIGRvg
[
j
-1] /
gvg
;
5275
dsum
+=
TMath::Abs
(
d
);
5276
ndex
= i*(i-1) / 2 +
j
;
5277
fVhmat
[
ndex
-1] +=
d
*2;
5278
vsum
+=
TMath::Abs
(
fVhmat
[
ndex
-1]);
5279
}
5280
}
5281
// smooth local fluctuations by averaging DCOVAR
5282
fDcovar
= (
fDcovar
+
dsum
/
vsum
)*.5;
5283
if
(
iswtr
>= 3 ||
ldebug
) {
5284
Printf
(
" RELATIVE CHANGE IN COV. MATRIX=%5.1f per cent"
,
fDcovar
*100);
5285
}
5286
if
(
ldebug
) {
5287
Printf
(
" VHMAT 2 ="
);
5288
for
(
kk
= 1;
kk
<= 10; ++
kk
) {
5289
Printf
(
" %10.3g"
,
fVhmat
[
kk
-1]);
5290
}
5291
}
5292
if
(
delgam
<=
gvg
)
goto
L135
;
5293
for
(i = 1; i <=
fNpar
; ++i) {
5294
fMIGRflnu
[i-1] =
fDirin
[i-1] /
delgam
-
fMIGRvg
[i-1] /
gvg
;
5295
}
5296
for
(i = 1; i <=
fNpar
; ++i) {
5297
for
(
j
= 1;
j
<= i; ++
j
) {
5298
ndex
= i*(i-1) / 2 +
j
;
5299
fVhmat
[
ndex
-1] +=
gvg
*2*
fMIGRflnu
[i-1]*
fMIGRflnu
[
j
-1];
5300
}
5301
}
5302
L135
:
5303
// and see if converged
5304
if
(
fEDM
<
rhotol
*.1)
goto
L300
;
5305
// if not, prepare next iteration
5306
for
(i = 1; i <=
fNpar
; ++i) {
5307
fMIGRxxs
[i-1] =
fX
[i-1];
5308
fMIGRgs
[i-1] =
fGrd
[i-1];
5309
}
5310
fs
=
fAmin
;
5311
if
(
fISW
[1] == 0 &&
fDcovar
< .5)
fISW
[1] = 1;
5312
if
(
fISW
[1] == 3 &&
fDcovar
> .1)
fISW
[1] = 1;
5313
if
(
fISW
[1] == 1 &&
fDcovar
< .05)
fISW
[1] = 3;
5314
goto
L24
;
5315
// end main loop
5316
// call limit in MNMIGR
5317
L190
:
5318
fISW
[0] = 1;
5319
if
(
fISW
[4] >= 0) {
5320
Printf
(
" CALL LIMIT EXCEEDED IN MIGRAD."
);
5321
}
5322
fCstatu
=
"CALL LIMIT"
;
5323
goto
L230
;
5324
// fails to improve
5325
L200
:
5326
if
(
iswtr
>= 1) {
5327
Printf
(
" MIGRAD FAILS TO FIND IMPROVEMENT"
);
5328
}
5329
for
(i = 1; i <=
fNpar
; ++i) {
fX
[i-1] =
fMIGRxxs
[i-1]; }
5330
if
(
fEDM
<
rhotol
)
goto
L300
;
5331
if
(
fEDM
<
TMath::Abs
(
fEpsma2
*
fAmin
)) {
5332
if
(
iswtr
>= 0) {
5333
Printf
(
" MACHINE ACCURACY LIMITS FURTHER IMPROVEMENT."
);
5334
}
5335
goto
L300
;
5336
}
5337
if
(
fIstrat
< 1) {
5338
if
(
fISW
[4] >= 0) {
5339
Printf
(
" MIGRAD FAILS WITH STRATEGY=0. WILL TRY WITH STRATEGY=1."
);
5340
}
5341
fIstrat
= 1;
5342
}
5343
goto
L1;
5344
// fails to converge
5345
L230
:
5346
if
(
iswtr
>= 0) {
5347
Printf
(
" MIGRAD TERMINATED WITHOUT CONVERGENCE."
);
5348
}
5349
if
(
fISW
[1] == 3)
fISW
[1] = 1;
5350
fISW
[3] = -1;
5351
goto
L400
;
5352
// apparent convergence
5353
L300
:
5354
if
(
iswtr
>= 0) {
5355
Printf
(
" MIGRAD MINIMIZATION HAS CONVERGED."
);
5356
}
5357
if
(
fItaur
== 0) {
5358
if
(
fIstrat
>= 2 || (
fIstrat
== 1 &&
fISW
[1] < 3)) {
5359
if
(
fISW
[4] >= 0) {
5360
Printf
(
" MIGRAD WILL VERIFY CONVERGENCE AND ERROR MATRIX."
);
5361
}
5362
mnhess
();
5363
mnwerr
();
5364
npsdf
= 0;
5365
if
(
fEDM
>
rhotol
)
goto
L10
;
5366
}
5367
}
5368
fCstatu
=
"CONVERGED "
;
5369
fISW
[3] = 1;
5370
// come here in any case
5371
L400
:
5372
fCfrom
=
"MIGRAD "
;
5373
fNfcnfr
=
nfcnmg
;
5374
mninex
(
fX
);
5375
mnwerr
();
5376
if
(
iswtr
>= 0)
mnprin
(3,
fAmin
);
5377
if
(
iswtr
>= 1)
mnmatu
(1);
5378
}
5379
5380
////////////////////////////////////////////////////////////////////////////////
5381
/// Performs a MINOS error analysis
5382
///
5383
/// Performs a MINOS error analysis on those parameters for
5384
/// which it is requested on the MINOS command by calling
5385
/// MNMNOT for each parameter requested.
5386
5387
void
TMinuit::mnmnos
()
5388
{
5389
/* Local variables */
5390
Double_t
val2mi
,
val2pl
;
5391
Int_t
nbad
,
ilax
,
ilax2
,
ngood
,
nfcnmi
,
iin
,
knt
;
5392
5393
if
(
fNpar
<= 0)
goto
L700
;
5394
ngood
= 0;
5395
nbad
= 0;
5396
nfcnmi
=
fNfcn
;
5397
// loop over parameters requested
5398
for
(
knt
= 1;
knt
<=
fNpar
; ++
knt
) {
5399
if
(
Int_t
(
fWord7
[1]) == 0) {
5400
ilax
=
fNexofi
[
knt
-1];
5401
}
else
{
5402
if
(
knt
>= 7)
break
;
5403
ilax
=
Int_t
(
fWord7
[
knt
]);
5404
if
(
ilax
== 0)
break
;
5405
if
(
ilax
> 0 &&
ilax
<=
fNu
) {
5406
if
(
fNiofex
[
ilax
-1] > 0)
goto
L565
;
5407
}
5408
Printf
(
" PARAMETER NUMBER %3d NOT A VARIABLE. IGNORED."
,
ilax
);
5409
continue
;
5410
}
5411
L565
:
5412
// calculate one pair of M E s
5413
ilax2
= 0;
5414
mnmnot
(
ilax
,
ilax2
,
val2pl
,
val2mi
);
5415
if
(
fLnewmn
)
goto
L650
;
5416
// update NGOOD and NBAD
5417
iin
=
fNiofex
[
ilax
-1];
5418
if
(
fErp
[
iin
-1] > 0) ++
ngood
;
5419
else
++
nbad
;
5420
if
(
fErn
[
iin
-1] < 0) ++
ngood
;
5421
else
++
nbad
;
5422
}
5423
// end of loop
5424
// printout final values
5425
fCfrom
=
"MINOS "
;
5426
fNfcnfr
=
nfcnmi
;
5427
fCstatu
=
"UNCHANGED "
;
5428
if
(
ngood
== 0 &&
nbad
== 0)
goto
L700
;
5429
if
(
ngood
> 0 &&
nbad
== 0)
fCstatu
=
"SUCCESSFUL"
;
5430
if
(
ngood
== 0 &&
nbad
> 0)
fCstatu
=
"FAILURE "
;
5431
if
(
ngood
> 0 &&
nbad
> 0)
fCstatu
=
"PROBLEMS "
;
5432
if
(
fISW
[4] >= 0)
mnprin
(4,
fAmin
);
5433
if
(
fISW
[4] >= 2)
mnmatu
(0);
5434
return
;
5435
// new minimum found
5436
L650
:
5437
fCfrom
=
"MINOS "
;
5438
fNfcnfr
=
nfcnmi
;
5439
fCstatu
=
"NEW MINIMU"
;
5440
if
(
fISW
[4] >= 0)
mnprin
(4,
fAmin
);
5441
Printf
(
" NEW MINIMUM FOUND. GO BACK TO MINIMIZATION STEP."
);
5442
Printf
(
" ================================================="
);
5443
Printf
(
" V"
);
5444
Printf
(
" V"
);
5445
Printf
(
" V"
);
5446
Printf
(
" VVVVVVV"
);
5447
Printf
(
" VVVVV"
);
5448
Printf
(
" VVV"
);
5449
Printf
(
" V\n"
);
5450
return
;
5451
L700
:
5452
Printf
(
" THERE ARE NO MINOS ERRORS TO CALCULATE."
);
5453
}
5454
5455
////////////////////////////////////////////////////////////////////////////////
5456
/// Performs a MINOS error analysis on one parameter
5457
///
5458
/// The parameter ILAX is varied, and the minimum of the
5459
/// function with respect to the other parameters is followed
5460
/// until it crosses the value FMIN+UP.
5461
5462
void
TMinuit::mnmnot
(
Int_t
ilax
,
Int_t
ilax2
,
Double_t
&
val2pl
,
Double_t
&
val2mi
)
5463
{
5464
/* System generated locals */
5465
Int_t
i__1
;
5466
5467
/* Local variables */
5468
Double_t
delu
,
aopt
,
eros
;
5469
Double_t
abest
,
xunit
,
dc
,
ut
,
sigsav
,
du1
;
5470
Double_t
fac
, sig,
sav
;
5471
Int_t
marc
,
isig
,
mpar
,
ndex
,
imax
,
indx
,
ierr
, i,
j
;
5472
Int_t
iercr
, it,
istrav
,
nfmxin
,
nlimit
,
isw2
,
isw4
;
5473
TString
csig
;
5474
5475
// save and prepare start vals
5476
isw2
=
fISW
[1];
5477
isw4
=
fISW
[3];
5478
sigsav
=
fEDM
;
5479
istrav
=
fIstrat
;
5480
dc
=
fDcovar
;
5481
fLnewmn
=
kFALSE
;
5482
fApsi
=
fEpsi
*.5;
5483
abest
=
fAmin
;
5484
mpar
=
fNpar
;
5485
nfmxin
=
fNfcnmx
;
5486
for
(i = 1; i <=
mpar
; ++i) {
fXt
[i-1] =
fX
[i-1]; }
5487
i__1
=
mpar
*(
mpar
+ 1) / 2;
5488
for
(
j
= 1;
j
<=
i__1
; ++
j
) {
fVthmat
[
j
-1] =
fVhmat
[
j
-1]; }
5489
for
(i = 1; i <=
mpar
; ++i) {
5490
fMNOTgcc
[i-1] =
fGlobcc
[i-1];
5491
fMNOTw
[i-1] =
fWerr
[i-1];
5492
}
5493
it =
fNiofex
[
ilax
-1];
5494
fErp
[it-1] = 0;
5495
fErn
[it-1] = 0;
5496
mninex
(
fXt
);
5497
ut
=
fU
[
ilax
-1];
5498
if
(
fNvarl
[
ilax
-1] == 1) {
5499
fAlim
[
ilax
-1] =
ut
-
fMNOTw
[it-1]*100;
5500
fBlim
[
ilax
-1] =
ut
+
fMNOTw
[it-1]*100;
5501
}
5502
ndex
= it*(it + 1) / 2;
5503
xunit
=
TMath::Sqrt
(
fUp
/
fVthmat
[
ndex
-1]);
5504
marc
= 0;
5505
for
(i = 1; i <=
mpar
; ++i) {
5506
if
(i == it)
continue
;
5507
++
marc
;
5508
imax
=
TMath::Max
(it,i);
5509
indx
=
imax
*(
imax
-1) / 2 +
TMath::Min
(it,i);
5510
fMNOTxdev
[
marc
-1] =
xunit
*
fVthmat
[
indx
-1];
5511
}
5512
// fix the parameter in question
5513
mnfixp
(it-1,
ierr
);
5514
if
(
ierr
> 0) {
5515
Printf
(
" MINUIT ERROR. CANNOT FIX PARAMETER %4d INTERNAL %3d"
,
ilax
,it);
5516
goto
L700
;
5517
}
5518
// Nota Bene: from here on, NPAR=MPAR-1
5519
// Remember: MNFIXP squeezes IT out of X, XT, WERR, and VHMAT,
5520
// not W, VTHMAT
5521
for
(
isig
= 1;
isig
<= 2; ++
isig
) {
5522
if
(
isig
== 1) {
5523
sig = 1;
5524
csig
=
"POSI"
;
5525
}
else
{
5526
sig = -1;
5527
csig
=
"NEGA"
;
5528
}
5529
// sig=sign of error being calcd
5530
if
(
fISW
[4] > 1) {
5531
Printf
(
" DETERMINATION OF %sTIVE MINOS ERROR FOR PARAMETER %d %s"
5532
,(
const
char
*)
csig
,
ilax
5533
,(
const
char
*)
fCpnam
[
ilax
-1]);
5534
}
5535
if
(
fISW
[1] <= 0) {
5536
mnwarn
(
"D"
,
"MINOS"
,
"NO COVARIANCE MATRIX."
);
5537
}
5538
nlimit
=
fNfcn
+
nfmxin
;
5539
fIstrat
=
TMath::Max
(
istrav
-1,0);
5540
du1
=
fMNOTw
[it-1];
5541
fU
[
ilax
-1] =
ut
+ sig*
du1
;
5542
fU
[
ilax
-1] =
TMath::Min
(
fU
[
ilax
-1],
fBlim
[
ilax
-1]);
5543
fU
[
ilax
-1] =
TMath::Max
(
fU
[
ilax
-1],
fAlim
[
ilax
-1]);
5544
delu
=
fU
[
ilax
-1] -
ut
;
5545
// stop if already at limit with negligible step size
5546
// add also a check if both numerator and denominarot are not zero (ROOT-10835)(LM)
5547
if
( (
delu
== 0 &&
ut
== 0) ||
5548
(
TMath::Abs
(
delu
) / (
TMath::Abs
(
ut
) +
TMath::Abs
(
fU
[
ilax
-1])) <
fEpsmac
))
goto
L440
;
5549
fac
=
delu
/
fMNOTw
[it-1];
5550
for
(i = 1; i <=
fNpar
; ++i) {
5551
fX
[i-1] =
fXt
[i-1] +
fac
*
fMNOTxdev
[i-1];
5552
}
5553
if
(
fISW
[4] > 1) {
5554
Printf
(
" PARAMETER %4d SET TO%11.3e + %10.3e = %12.3e"
,
ilax
,
ut
,
delu
,
fU
[
ilax
-1]);
5555
}
5556
// loop to hit AMIN+UP
5557
fKe1cr
=
ilax
;
5558
fKe2cr
= 0;
5559
fXmidcr
=
fU
[
ilax
-1];
5560
fXdircr
=
delu
;
5561
5562
fAmin
=
abest
;
5563
fNfcnmx
=
nlimit
-
fNfcn
;
5564
mncros
(
aopt
,
iercr
);
5565
if
(
abest
-
fAmin
>
fUp
*.01)
goto
L650
;
5566
if
(
iercr
== 1)
goto
L440
;
5567
if
(
iercr
== 2)
goto
L450
;
5568
if
(
iercr
== 3)
goto
L460
;
5569
// error successfully calculated
5570
eros
=
fXmidcr
-
ut
+
aopt
*
fXdircr
;
5571
if
(
fISW
[4] > 1) {
5572
Printf
(
" THE %4sTIVE MINOS ERROR OF PARAMETER %3d %10s, IS %12.4e"
5573
,(
const
char
*)
csig
,
ilax
5574
,(
const
char
*)
fCpnam
[
ilax
-1],
eros
);
5575
}
5576
goto
L480
;
5577
// failure returns
5578
L440
:
5579
if
(
fISW
[4] >= 1) {
5580
Printf
(
" THE %4sTIVE MINOS ERROR OF PARAMETER %3d, %s EXCEEDS ITS LIMIT."
5581
,(
const
char
*)
csig
,
ilax
5582
,(
const
char
*)
fCpnam
[
ilax
-1]);
5583
}
5584
eros
=
fUndefi
;
5585
goto
L480
;
5586
L450
:
5587
if
(
fISW
[4] >= 1) {
5588
Printf
(
" THE %4sTIVE MINOS ERROR %4d REQUIRES MORE THAN %5d FUNCTION CALLS."
5589
,(
const
char
*)
csig
,
ilax
,
nfmxin
);
5590
}
5591
eros
= 0;
5592
goto
L480
;
5593
L460
:
5594
if
(
fISW
[4] >= 1) {
5595
Printf
(
" %4sTIVE MINOS ERROR NOT CALCULATED FOR PARAMETER %d"
5596
,(
const
char
*)
csig
,
ilax
);
5597
}
5598
eros
= 0;
5599
5600
L480
:
5601
if
(
fISW
[4] > 1) {
5602
Printf
(
" **************************************************************************"
);
5603
}
5604
if
(sig < 0) {
5605
fErn
[it-1] =
eros
;
5606
if
(
ilax2
> 0 &&
ilax2
<=
fNu
)
val2mi
=
fU
[
ilax2
-1];
5607
}
else
{
5608
fErp
[it-1] =
eros
;
5609
if
(
ilax2
> 0 &&
ilax2
<=
fNu
)
val2pl
=
fU
[
ilax2
-1];
5610
}
5611
}
5612
// parameter finished. reset v
5613
// normal termination */
5614
fItaur
= 1;
5615
mnfree
(1);
5616
i__1
=
mpar
*(
mpar
+ 1) / 2;
5617
for
(
j
= 1;
j
<=
i__1
; ++
j
) {
fVhmat
[
j
-1] =
fVthmat
[
j
-1]; }
5618
for
(i = 1; i <=
mpar
; ++i) {
5619
fWerr
[i-1] =
fMNOTw
[i-1];
5620
fGlobcc
[i-1] =
fMNOTgcc
[i-1];
5621
fX
[i-1] =
fXt
[i-1];
5622
}
5623
mninex
(
fX
);
5624
fEDM
=
sigsav
;
5625
fAmin
=
abest
;
5626
fISW
[1] =
isw2
;
5627
fISW
[3] =
isw4
;
5628
fDcovar
=
dc
;
5629
goto
L700
;
5630
// new minimum
5631
L650
:
5632
fLnewmn
=
kTRUE
;
5633
fISW
[1] = 0;
5634
fDcovar
= 1;
5635
fISW
[3] = 0;
5636
sav
=
fU
[
ilax
-1];
5637
fItaur
= 1;
5638
mnfree
(1);
5639
fU
[
ilax
-1] =
sav
;
5640
mnexin
(
fX
);
5641
fEDM
=
fBigedm
;
5642
// in any case
5643
L700
:
5644
fItaur
= 0;
5645
fNfcnmx
=
nfmxin
;
5646
fIstrat
=
istrav
;
5647
}
5648
5649
////////////////////////////////////////////////////////////////////////////////
5650
/// Implements one parameter definition
5651
///
5652
/// Called from MNPARS and user-callable
5653
/// Implements one parameter definition, that is:
5654
/// - K (external) parameter number
5655
/// - CNAMK parameter name
5656
/// - UK starting value
5657
/// - WK starting step size or uncertainty
5658
/// - A, B lower and upper physical parameter limits
5659
/// and sets up (updates) the parameter lists.
5660
/// Output:
5661
/// - IERFLG=0 if no problems
5662
/// - >0 if MNPARM unable to implement definition
5663
5664
void
TMinuit::mnparm
(
Int_t
k1
,
TString
cnamj
,
Double_t
uk
,
Double_t
wk
,
Double_t
a
,
Double_t
b
,
Int_t
&
ierflg
)
5665
{
5666
/* Local variables */
5667
Double_t
vplu
,
a_small
,
gsmin
,
pinti
,
vminu
,
danger
,
sav
,
sav2
;
5668
Int_t
ierr
, kint, in, ix,
ktofix
,
lastin
,
kinfix
,
nvl
;
5669
TString
cnamk
,
chbufi
;
5670
5671
Int_t
k =
k1
+1;
5672
cnamk
=
cnamj
;
5673
kint =
fNpar
;
5674
if
(
k < 1 || k >
fMaxext
) {
5675
// parameter number exceeds allowed maximum value
5676
Printf
(
" MINUIT USER ERROR. PARAMETER NUMBER IS %3d ALLOWED RANGE IS ONE TO %4d"
,k,
fMaxext
);
5677
goto
L800
;
5678
}
5679
// normal parameter request
5680
ktofix
= 0;
5681
if
(
fNvarl
[k-1] < 0)
goto
L50
;
5682
// previously defined parameter is being redefined
5683
// find if parameter was fixed
5684
for
(ix = 1; ix <=
fNpfix
; ++ix) {
5685
if
(
fIpfix
[ix-1] == k)
ktofix
= k;
5686
}
5687
if
(
ktofix
> 0) {
5688
mnwarn
(
"W"
,
"PARAM DEF"
,
"REDEFINING A FIXED PARAMETER."
);
5689
if
(kint >=
fMaxint
) {
5690
Printf
(
" CANNOT RELEASE. MAX NPAR EXCEEDED."
);
5691
goto
L800
;
5692
}
5693
mnfree
(-k);
5694
}
5695
// if redefining previously variable parameter
5696
if
(
fNiofex
[k-1] > 0) kint =
fNpar
- 1;
5697
L50
:
5698
5699
// print heading
5700
if
(
fLphead
&&
fISW
[4] >= 0) {
5701
Printf
(
" PARAMETER DEFINITIONS:"
);
5702
Printf
(
" NO. NAME VALUE STEP SIZE LIMITS"
);
5703
fLphead
=
kFALSE
;
5704
}
5705
if
(
wk
> 0)
goto
L122
;
5706
// constant parameter
5707
if
(
fISW
[4] >= 0) {
5708
Printf
(
" %5d %-10s %13.5e constant"
,k,(
const
char
*)
cnamk
,
uk
);
5709
}
5710
nvl
= 0;
5711
goto
L200
;
5712
L122
:
5713
if
(
a
== 0 &&
b
== 0) {
5714
// variable parameter without limits
5715
nvl
= 1;
5716
if
(
fISW
[4] >= 0) {
5717
Printf
(
" %5d %-10s %13.5e%13.5e no limits"
,k,(
const
char
*)
cnamk
,
uk
,
wk
);
5718
}
5719
}
else
{
5720
// variable parameter with limits
5721
nvl
= 4;
5722
fLnolim
=
kFALSE
;
5723
if
(
fISW
[4] >= 0) {
5724
Printf
(
" %5d %-10s %13.5e%13.5e %13.5e%13.5e"
,k,(
const
char
*)
cnamk
,
uk
,
wk
,
a
,
b
);
5725
}
5726
}
5727
// request for another variable parameter
5728
++kint;
5729
if
(kint >
fMaxint
) {
5730
Printf
(
" MINUIT USER ERROR. TOO MANY VARIABLE PARAMETERS."
);
5731
goto
L800
;
5732
}
5733
if
(
nvl
== 1)
goto
L200
;
5734
if
(
a
==
b
) {
5735
Printf
(
" USER ERROR IN MINUIT PARAMETER"
);
5736
Printf
(
" DEFINITION"
);
5737
Printf
(
" UPPER AND LOWER LIMITS EQUAL."
);
5738
goto
L800
;
5739
}
5740
if
(
b
<
a
) {
5741
sav
=
b
;
5742
b
=
a
;
5743
a
=
sav
;
5744
mnwarn
(
"W"
,
"PARAM DEF"
,
"PARAMETER LIMITS WERE REVERSED."
);
5745
if
(
fLwarn
)
fLphead
=
kTRUE
;
5746
}
5747
if
(
b
-
a
> 1
e7
) {
5748
mnwarn
(
"W"
,
"PARAM DEF"
,
TString::Format
(
"LIMITS ON PARAM%d TOO FAR APART."
,k));
5749
if
(
fLwarn
)
fLphead
=
kTRUE
;
5750
}
5751
danger
= (
b
-
uk
)*(
uk
-
a
);
5752
if
(
danger
< 0) {
5753
mnwarn
(
"W"
,
"PARAM DEF"
,
"STARTING VALUE OUTSIDE LIMITS."
);
5754
}
5755
if
(
danger
== 0) {
5756
mnwarn
(
"W"
,
"PARAM DEF"
,
"STARTING VALUE IS AT LIMIT."
);
5757
}
5758
L200
:
5759
// input OK, set values, arrange lists,
5760
// calculate step sizes GSTEP, DIRIN
5761
fCfrom
=
"PARAMETR"
;
5762
fNfcnfr
=
fNfcn
;
5763
fCstatu
=
"NEW VALUES"
;
5764
fNu
=
TMath::Max
(
fNu
,k);
5765
fCpnam
[k-1] =
cnamk
;
5766
fU
[k-1] =
uk
;
5767
fAlim
[k-1] =
a
;
5768
fBlim
[k-1] =
b
;
5769
fNvarl
[k-1] =
nvl
;
5770
mnrset
(1);
5771
// K is external number of new parameter
5772
// LASTIN is the number of var. params with ext. param. no.< K
5773
lastin
= 0;
5774
for
(ix = 1; ix <= k-1; ++ix) {
if
(
fNiofex
[ix-1] > 0) ++
lastin
; }
5775
// KINT is new number of variable params, NPAR is old
5776
if
(kint ==
fNpar
)
goto
L280
;
5777
if
(kint >
fNpar
) {
5778
// insert new variable parameter in list
5779
for
(in =
fNpar
; in >=
lastin
+ 1; --in) {
5780
ix =
fNexofi
[in-1];
5781
fNiofex
[ix-1] = in + 1;
5782
fNexofi
[in] = ix;
5783
fX
[in] =
fX
[in-1];
5784
fXt
[in] =
fXt
[in-1];
5785
fDirin
[in] =
fDirin
[in-1];
5786
fG2
[in] =
fG2
[in-1];
5787
fGstep
[in] =
fGstep
[in-1];
5788
fWerr
[in] =
fWerr
[in-1];
5789
fGrd
[in] =
fGrd
[in-1];
5790
}
5791
}
else
{
5792
// remove variable parameter from list
5793
for
(in =
lastin
+ 1; in <= kint; ++in) {
5794
ix =
fNexofi
[in];
5795
fNiofex
[ix-1] = in;
5796
fNexofi
[in-1] = ix;
5797
fX
[in-1] =
fX
[in];
5798
fXt
[in-1] =
fXt
[in];
5799
fDirin
[in-1] =
fDirin
[in];
5800
fG2
[in-1] =
fG2
[in];
5801
fGstep
[in-1] =
fGstep
[in];
5802
fWerr
[in-1] =
fWerr
[in];
5803
fGrd
[in-1] =
fGrd
[in];
5804
}
5805
}
5806
L280
:
5807
ix = k;
5808
fNiofex
[ix-1] = 0;
5809
fNpar
= kint;
5810
// lists are now arranged
5811
if
(
nvl
> 0) {
5812
in =
lastin
+ 1;
5813
fNexofi
[in-1] = ix;
5814
fNiofex
[ix-1] = in;
5815
sav
=
fU
[ix-1];
5816
mnpint
(
sav
, ix-1,
pinti
);
5817
fX
[in-1] =
pinti
;
5818
fXt
[in-1] =
fX
[in-1];
5819
fWerr
[in-1] =
wk
;
5820
sav2
=
sav
+
wk
;
5821
mnpint
(
sav2
, ix-1,
pinti
);
5822
vplu
=
pinti
-
fX
[in-1];
5823
sav2
=
sav
-
wk
;
5824
mnpint
(
sav2
, ix-1,
pinti
);
5825
vminu
=
pinti
-
fX
[in-1];
5826
fDirin
[in-1] = (
TMath::Abs
(
vplu
) +
TMath::Abs
(
vminu
))*.5;
5827
fG2
[in-1] =
fUp
*2 / (
fDirin
[in-1]*
fDirin
[in-1]);
5828
gsmin
=
fEpsma2
*8*
TMath::Abs
(
fX
[in-1]);
5829
fGstep
[in-1] =
TMath::Max
(
gsmin
,
fDirin
[in-1]*.1);
5830
if
(
fAmin
!=
fUndefi
) {
5831
a_small
=
TMath::Sqrt
(
fEpsma2
*(
fAmin
+
fUp
) /
fUp
);
5832
fGstep
[in-1] =
TMath::Max
(
gsmin
,
a_small
*
fDirin
[in-1]);
5833
}
5834
fGrd
[in-1] =
fG2
[in-1]*
fDirin
[in-1];
5835
// if parameter has limits
5836
if
(
fNvarl
[k-1] > 1) {
5837
if
(
fGstep
[in-1] > .5)
fGstep
[in-1] = .5;
5838
fGstep
[in-1] = -
fGstep
[in-1];
5839
}
5840
}
5841
if
(
ktofix
> 0) {
5842
ierr
= 0;
5843
kinfix
=
fNiofex
[
ktofix
-1];
5844
if
(
kinfix
> 0)
mnfixp
(
kinfix
-1,
ierr
);
5845
if
(
ierr
> 0)
goto
L800
;
5846
}
5847
ierflg
= 0;
5848
return
;
5849
// error on input, unable to implement request
5850
L800
:
5851
ierflg
= 1;
5852
}
5853
5854
////////////////////////////////////////////////////////////////////////////////
5855
/// Implements one parameter definition
5856
///
5857
/// Called from MNREAD and user-callable
5858
/// Implements one parameter definition, that is:
5859
/// parses the string CRDBUF and calls MNPARM
5860
///
5861
/// output conditions:
5862
/// - ICONDN = 0 all OK
5863
/// - ICONDN = 1 error, attempt to define parameter is ignored
5864
/// - ICONDN = 2 end of parameter definitions
5865
5866
void
TMinuit::mnpars
(
TString
&
crdbuf
,
Int_t
&
icondn
)
5867
{
5868
/* Local variables */
5869
Double_t
a
=0,
b
=0, fk=0,
uk
=0,
wk
=0,
xk
=0;
5870
Int_t
ierr
,
kapo1
,
kapo2
;
5871
Int_t
k,
llist
,
ibegin
, lenbuf,
istart
,
lnc
,
icy
;
5872
TString
cnamk
,
comand
,
celmnt
,
ctemp
;
5873
char
stmp
[128];
5874
5875
lenbuf =
strlen
((
const
char
*)
crdbuf
);
5876
// find out whether fixed or free-field format
5877
kapo1
=
strspn
((
const
char
*)
crdbuf
,
"'"
);
5878
if
(
kapo1
== 0)
goto
L150
;
5879
kapo2
=
strspn
((
const
char
*)
crdbuf
+
kapo1
,
"'"
);
5880
if
(
kapo2
== 0)
goto
L150
;
5881
// new (free-field) format
5882
kapo2
+=
kapo1
;
5883
// skip leading blanks if any
5884
for
(
istart
= 1;
istart
<=
kapo1
-1; ++
istart
) {
5885
if
(
crdbuf
(
istart
-1,1) !=
' '
)
goto
L120
;
5886
}
5887
goto
L210
;
5888
L120
:
5889
// parameter number integer
5890
celmnt
=
crdbuf
(
istart
-1,
kapo1
-
istart
);
5891
if
(
scanf
((
const
char
*)
celmnt
,&fk)) {;}
5892
k =
Int_t
(fk);
5893
if
(k <= 0)
goto
L210
;
5894
cnamk
=
"PARAM "
+
celmnt
;
5895
if
(
kapo2
-
kapo1
> 1) {
5896
cnamk
=
crdbuf
(
kapo1
,
kapo2
-1-
kapo1
);
5897
}
5898
// special handling if comma or blanks and a comma follow 'name'
5899
for
(
icy
=
kapo2
+ 1;
icy
<= lenbuf; ++
icy
) {
5900
if
(
crdbuf
(
icy
-1,1) ==
','
)
goto
L139
;
5901
if
(
crdbuf
(
icy
-1,1) !=
' '
)
goto
L140
;
5902
}
5903
uk
= 0;
5904
wk
= 0;
5905
a
= 0;
5906
b
= 0;
5907
goto
L170
;
5908
L139
:
5909
++
icy
;
5910
L140
:
5911
ibegin
=
icy
;
5912
ctemp
=
crdbuf
(
ibegin
-1,lenbuf-
ibegin
);
5913
mncrck
(
ctemp
, 20,
comand
,
lnc
,
fMaxpar
,
fPARSplist
,
llist
,
ierr
,
fIsyswr
);
5914
if
(
ierr
> 0)
goto
L180
;
5915
uk
=
fPARSplist
[0];
5916
wk
= 0;
5917
if
(
llist
>= 2)
wk
=
fPARSplist
[1];
5918
a
= 0;
5919
if
(
llist
>= 3)
a
=
fPARSplist
[2];
5920
b
= 0;
5921
if
(
llist
>= 4)
b
=
fPARSplist
[3];
5922
goto
L170
;
5923
// old (fixed-field) format
5924
L150
:
5925
if
(
scanf
((
const
char
*)
crdbuf
,&
xk
,
stmp
,&
uk
,&
wk
,&
a
,&
b
)) {;}
5926
cnamk
=
stmp
;
5927
k =
Int_t
(
xk
);
5928
if
(k == 0)
goto
L210
;
5929
// parameter format cracked, implement parameter definition
5930
L170
:
5931
mnparm
(k-1,
cnamk
,
uk
,
wk
,
a
,
b
,
ierr
);
5932
icondn
=
ierr
;
5933
return
;
5934
// format or other error
5935
L180
:
5936
icondn
= 1;
5937
return
;
5938
// end of data
5939
L210
:
5940
icondn
= 2;
5941
}
5942
5943
////////////////////////////////////////////////////////////////////////////////
5944
/// To fit a parabola to npar2p points
5945
///
5946
/// - npar2p no. of points
5947
/// - parx2p(i) x value of point i
5948
/// - pary2p(i) y value of point i
5949
///
5950
/// - coef2p(1...3) coefficients of the fitted parabola
5951
/// - y=coef2p(1) + coef2p(2)*x + coef2p(3)*x**2
5952
/// - sdev2p= variance
5953
/// - method : chi**2 = min equation solved explicitly
5954
5955
void
TMinuit::mnpfit
(
Double_t
*
parx2p
,
Double_t
*
pary2p
,
Int_t
npar2p
,
Double_t
*
coef2p
,
Double_t
&
sdev2p
)
5956
{
5957
/* Local variables */
5958
Double_t
a
,
f
, s, t,
y
,
s2
,
x2
,
x3
,
x4
,
y2
,
cz
[3],
xm
,
xy
,
x2y
;
5959
x2
=
x3
= 0;
5960
Int_t
i;
5961
5962
/* Function Body */
5963
for
(i = 1; i <= 3; ++i) {
cz
[i - 1] = 0; }
5964
sdev2p
= 0;
5965
if
(
npar2p
< 3)
goto
L10
;
5966
f
= (
Double_t
) (
npar2p
);
5967
// center x values for reasons of machine precision
5968
xm
= 0;
5969
for
(i = 1; i <=
npar2p
; ++i) {
xm
+=
parx2p
[i - 1]; }
5970
xm
/=
f
;
5971
x2
= 0;
5972
x3
= 0;
5973
x4
= 0;
5974
y
= 0;
5975
y2
= 0;
5976
xy
= 0;
5977
x2y
= 0;
5978
for
(i = 1; i <=
npar2p
; ++i) {
5979
s =
parx2p
[i - 1] -
xm
;
5980
t =
pary2p
[i - 1];
5981
s2
= s*s;
5982
x2
+=
s2
;
5983
x3
+= s*
s2
;
5984
x4
+=
s2
*
s2
;
5985
y
+= t;
5986
y2
+= t*t;
5987
xy
+= s*t;
5988
x2y
+=
s2
*t;
5989
}
5990
a
= (
f
*
x4
-
x2
*
x2
)*
x2
-
f
*(
x3
*
x3
);
5991
if
(
a
== 0)
goto
L10
;
5992
cz
[2] = (
x2
*(
f
*
x2y
-
x2
*
y
) -
f
*
x3
*
xy
) /
a
;
5993
cz
[1] = (
xy
-
x3
*
cz
[2]) /
x2
;
5994
cz
[0] = (
y
-
x2
*
cz
[2]) /
f
;
5995
if
(
npar2p
== 3)
goto
L6
;
5996
sdev2p
=
y2
- (
cz
[0]*
y
+
cz
[1]*
xy
+
cz
[2]*
x2y
);
5997
if
(
sdev2p
< 0)
sdev2p
= 0;
5998
sdev2p
/=
f
- 3;
5999
L6
:
6000
cz
[0] +=
xm
*(
xm
*
cz
[2] -
cz
[1]);
6001
cz
[1] -=
xm
*2*
cz
[2];
6002
L10
:
6003
for
(i = 1; i <= 3; ++i) {
coef2p
[i - 1] =
cz
[i - 1]; }
6004
}
6005
6006
////////////////////////////////////////////////////////////////////////////////
6007
/// Calculates the internal parameter value PINTI
6008
///
6009
/// corresponding to the external value PEXTI for parameter I.
6010
6011
void
TMinuit::mnpint
(
Double_t
&
pexti
,
Int_t
i1
,
Double_t
&
pinti
)
6012
{
6013
/* Local variables */
6014
Double_t
a
,
alimi
,
blimi
,
yy
,
yy2
;
6015
Int_t
igo
;
6016
TString
chbuf2
,
chbufi
;
6017
6018
Int_t
i =
i1
+1;
6019
pinti
=
pexti
;
6020
igo
=
fNvarl
[i-1];
6021
if
(
igo
== 4) {
6022
// there are two limits
6023
alimi
=
fAlim
[i-1];
6024
blimi
=
fBlim
[i-1];
6025
yy
= (
pexti
-
alimi
)*2 / (
blimi
-
alimi
) - 1;
6026
yy2
=
yy
*
yy
;
6027
if
(
yy2
>= 1 -
fEpsma2
) {
6028
if
(
yy
< 0) {
6029
a
=
fVlimlo
;
6030
chbuf2
=
" IS AT ITS LOWER ALLOWED LIMIT."
;
6031
}
else
{
6032
a
=
fVlimhi
;
6033
chbuf2
=
" IS AT ITS UPPER ALLOWED LIMIT."
;
6034
}
6035
pinti
=
a
;
6036
pexti
=
alimi
+ (
blimi
-
alimi
)*.5*(
TMath::Sin
(
a
) + 1);
6037
fLimset
=
kTRUE
;
6038
if
(
yy2
> 1)
chbuf2
=
" BROUGHT BACK INSIDE LIMITS."
;
6039
mnwarn
(
"W"
,
fCfrom
,
TString::Format
(
"VARIABLE%d%s"
,i,
chbuf2
.Data()));
6040
}
else
{
6041
pinti
=
TMath::ASin
(
yy
);
6042
}
6043
}
6044
}
6045
6046
////////////////////////////////////////////////////////////////////////////////
6047
/// Plots points in array xypt onto one page with labelled axes
6048
///
6049
/// - NXYPT is the number of points to be plotted
6050
/// - XPT(I) = x-coord. of ith point
6051
/// - YPT(I) = y-coord. of ith point
6052
/// - CHPT(I) = character to be plotted at this position
6053
/// the input point arrays XPT, YPT, CHPT are destroyed.
6054
///
6055
/// If fGraphicsmode is true (default), a TGraph object is produced
6056
/// via the Plug-in handler. To get the plot, you can do:
6057
/// ~~~ {.cpp}
6058
/// TGraph *gr = (TGraph*)gMinuit->GetPlot();
6059
/// gr->Draw("al");
6060
/// ~~~
6061
6062
void
TMinuit::mnplot
(
Double_t
*xpt,
Double_t
*ypt,
char
*
chpt
,
Int_t
nxypt
,
Int_t
npagwd
,
Int_t
npagln
)
6063
{
6064
6065
if
(
fGraphicsMode
) {
6066
TPluginHandler
*
h
;
6067
if
((
h
=
gROOT
->GetPluginManager()->FindHandler(
"TMinuitGraph"
))) {
6068
//remove the first two points
6069
if
(
h
->LoadPlugin() != -1)
6070
fPlot
= (
TObject
*)
h
->ExecPlugin(3,
nxypt
-2,&xpt[2],&ypt[2]);
6071
}
6072
return
;
6073
}
6074
6075
/* Local variables */
6076
Double_t
xmin
,
ymin
,
xmax
,
ymax
,
savx
,
savy
,
yprt
;
6077
Double_t
bwidx
,
bwidy
,
xbest
,
ybest
,
ax
,
ay
,
bx
,
by
;
6078
Double_t
xvalus
[12], any,
dxx
,
dyy
;
6079
Int_t
iten
, i,
j
, k,
maxnx
,
maxny
,
iquit
,
ni
,
linodd
;
6080
Int_t
nxbest
,
nybest
,
km1
,
ibk
,
isp1
,
nx
,
ny
,
ks
, ix;
6081
TString
chmess
,
ctemp
;
6082
Bool_t
overpr
;
6083
char
cline
[144];
6084
char
chsav
,
chbest
;
6085
6086
/* Function Body */
6087
// Computing MIN
6088
maxnx
=
TMath::Min
(
npagwd
-20,100);
6089
if
(
maxnx
< 10)
maxnx
= 10;
6090
maxny
=
npagln
;
6091
if
(
maxny
< 10)
maxny
= 10;
6092
if
(
nxypt
<= 1)
return
;
6093
xbest
= xpt[0];
6094
ybest
= ypt[0];
6095
chbest
=
chpt
[0];
6096
// order the points by decreasing y
6097
km1
=
nxypt
- 1;
6098
for
(i = 1; i <=
km1
; ++i) {
6099
iquit
= 0;
6100
ni
=
nxypt
- i;
6101
for
(
j
= 1;
j
<=
ni
; ++
j
) {
6102
if
(ypt[
j
-1] > ypt[
j
])
continue
;
6103
savx
= xpt[
j
-1];
6104
xpt[
j
-1] = xpt[
j
];
6105
xpt[
j
] =
savx
;
6106
savy
= ypt[
j
-1];
6107
ypt[
j
-1] = ypt[
j
];
6108
ypt[
j
] =
savy
;
6109
chsav
=
chpt
[
j
-1];
6110
chpt
[
j
-1]=
chpt
[
j
];
6111
chpt
[
j
] =
chsav
;
6112
iquit
= 1;
6113
}
6114
if
(
iquit
== 0)
break
;
6115
}
6116
// find extreme values
6117
xmax
= xpt[0];
6118
xmin
=
xmax
;
6119
for
(i = 1; i <=
nxypt
; ++i) {
6120
if
(xpt[i-1] >
xmax
)
xmax
= xpt[i-1];
6121
if
(xpt[i-1] <
xmin
)
xmin
= xpt[i-1];
6122
}
6123
dxx
= (
xmax
-
xmin
)*.001;
6124
xmax
+=
dxx
;
6125
xmin
-=
dxx
;
6126
mnbins
(
xmin
,
xmax
,
maxnx
,
xmin
,
xmax
,
nx
,
bwidx
);
6127
ymax
= ypt[0];
6128
ymin
= ypt[
nxypt
-1];
6129
if
(
ymax
==
ymin
)
ymax
=
ymin
+ 1;
6130
dyy
= (
ymax
-
ymin
)*.001;
6131
ymax
+=
dyy
;
6132
ymin
-=
dyy
;
6133
mnbins
(
ymin
,
ymax
,
maxny
,
ymin
,
ymax
,
ny
,
bwidy
);
6134
any = (
Double_t
)
ny
;
6135
// if first point is blank, it is an 'origin'
6136
if
(
chbest
==
' '
)
goto
L50
;
6137
xbest
= (
xmax
+
xmin
)*.5;
6138
ybest
= (
ymax
+
ymin
)*.5;
6139
L50
:
6140
// find scale constants
6141
ax
= 1 /
bwidx
;
6142
ay
= 1 /
bwidy
;
6143
bx
= -
ax
*
xmin
+ 2;
6144
by
= -
ay
*
ymin
- 2;
6145
// convert points to grid positions
6146
for
(i = 1; i <=
nxypt
; ++i) {
6147
xpt[i-1] =
ax
*xpt[i-1] +
bx
;
6148
ypt[i-1] = any -
ay
*ypt[i-1] -
by
;
6149
}
6150
nxbest
=
Int_t
((
ax
*
xbest
+
bx
));
6151
nybest
=
Int_t
((any -
ay
*
ybest
-
by
));
6152
// print the points
6153
ny
+= 2;
6154
nx
+= 2;
6155
isp1
= 1;
6156
linodd
= 1;
6157
overpr
=
kFALSE
;
6158
for
(i = 1; i <=
ny
; ++i) {
6159
for
(
ibk
= 1;
ibk
<=
nx
; ++
ibk
) {
cline
[
ibk
-1] =
' '
; }
6160
cline
[
nx
] =
'\0'
;
6161
cline
[
nx
+1] =
'\0'
;
6162
cline
[0] =
'.'
;
6163
// not needed - but to avoid a wrongly reported compiler warning (see ROOT-6496)
6164
if
(
nx
>0)
cline
[
nx
-1] =
'.'
;
6165
cline
[
nxbest
-1] =
'.'
;
6166
if
(i != 1 && i !=
nybest
&& i !=
ny
)
goto
L320
;
6167
for
(
j
= 1;
j
<=
nx
; ++
j
) {
cline
[
j
-1] =
'.'
; }
6168
L320
:
6169
yprt
=
ymax
-
Double_t
(i-1)*
bwidy
;
6170
if
(
isp1
>
nxypt
)
goto
L350
;
6171
// find the points to be plotted on this line
6172
for
(k =
isp1
; k <=
nxypt
; ++k) {
6173
ks
=
Int_t
(ypt[k-1]);
6174
if
(
ks
> i)
goto
L345
;
6175
ix =
Int_t
(xpt[k-1]);
6176
if
(
cline
[ix-1] ==
'.'
)
goto
L340
;
6177
if
(
cline
[ix-1] ==
' '
)
goto
L340
;
6178
if
(
cline
[ix-1] ==
chpt
[k-1])
continue
;
6179
overpr
=
kTRUE
;
6180
// OVERPR is true if one or more positions contains more than
6181
// one point
6182
cline
[ix-1] =
'&'
;
6183
continue
;
6184
L340
:
6185
cline
[ix-1] =
chpt
[k-1];
6186
}
6187
isp1
=
nxypt
+ 1;
6188
goto
L350
;
6189
L345
:
6190
isp1
= k;
6191
L350
:
6192
if
(
linodd
== 1 || i ==
ny
)
goto
L380
;
6193
linodd
= 1;
6194
ctemp
=
cline
;
6195
Printf
(
" %s"
,(
const
char
*)
ctemp
);
6196
goto
L400
;
6197
L380
:
6198
ctemp
=
cline
;
6199
Printf
(
" %14.7g ..%s"
,
yprt
,(
const
char
*)
ctemp
);
6200
linodd
= 0;
6201
L400
:
6202
;
6203
}
6204
// print labels on x-axis every ten columns
6205
for
(
ibk
= 1;
ibk
<=
nx
; ++
ibk
) {
6206
cline
[
ibk
-1] =
' '
;
6207
if
(
ibk
% 10 == 1)
cline
[
ibk
-1] =
'/'
;
6208
}
6209
Printf
(
" %s"
,
cline
);
6210
6211
for
(
ibk
= 1;
ibk
<= 12; ++
ibk
) {
6212
xvalus
[
ibk
-1] =
xmin
+
Double_t
(
ibk
-1)*10*
bwidx
;
6213
}
6214
iten
= (
nx
+ 9) / 10;
6215
Printf
(
" "
);
6216
for
(
ibk
= 1;
ibk
<=
iten
; ++
ibk
)
6217
Printf
(
"%# 8.3g "
,
xvalus
[
ibk
-1]);
6218
Printf
(
"\n"
);
6219
chmess
=
" "
;
6220
if
(
overpr
)
chmess
=
" Overprint character is &"
;
6221
Printf
(
" ONE COLUMN=%13.7g%s"
,
bwidx
,(
const
char
*)
chmess
);
6222
}
6223
6224
////////////////////////////////////////////////////////////////////////////////
6225
/// Provides the user with information concerning the current status
6226
///
6227
/// of parameter number IUEXT. Namely, it returns:
6228
/// - CHNAM: the name of the parameter
6229
/// - VAL: the current (external) value of the parameter
6230
/// - ERR: the current estimate of the parameter uncertainty
6231
/// - XLOLIM: the lower bound (or zero if no limits)
6232
/// - XUPLIM: the upper bound (or zero if no limits)
6233
/// - IUINT: the internal parameter number (or zero if not variable,
6234
/// or negative if undefined).
6235
///
6236
/// Note also: If IUEXT is negative, then it is -internal parameter
6237
/// number, and IUINT is returned as the EXTERNAL number.
6238
/// Except for IUINT, this is exactly the inverse of MNPARM
6239
/// User-called
6240
6241
void
TMinuit::mnpout
(
Int_t
iuext1
,
TString
&
chnam
,
Double_t
&val,
Double_t
&err,
Double_t
&
xlolim
,
Double_t
&
xuplim
,
Int_t
&
iuint
)
const
6242
{
6243
/* Local variables */
6244
Int_t
iint
,
iext
,
nvl
;
6245
6246
Int_t
iuext
=
iuext1
+ 1;
6247
xlolim
= 0;
6248
xuplim
= 0;
6249
err = 0;
6250
if
(
iuext
== 0)
goto
L100
;
6251
if
(
iuext
< 0) {
6252
// internal parameter number specified
6253
iint
= -(
iuext
);
6254
if
(
iint
>
fNpar
)
goto
L100
;
6255
iext
=
fNexofi
[
iint
-1];
6256
iuint
=
iext
;
6257
}
else
{
6258
// external parameter number specified
6259
iext
=
iuext
;
6260
if
(
iext
>
fNu
)
goto
L100
;
6261
iint
=
fNiofex
[
iext
-1];
6262
iuint
=
iint
;
6263
}
6264
// in both cases
6265
nvl
=
fNvarl
[
iext
-1];
6266
if
(
nvl
< 0)
goto
L100
;
6267
chnam
=
fCpnam
[
iext
-1];
6268
val =
fU
[
iext
-1];
6269
if
(
iint
> 0) err =
fWerr
[
iint
-1];
6270
if
(
nvl
== 4) {
6271
xlolim
=
fAlim
[
iext
-1];
6272
xuplim
=
fBlim
[
iext
-1];
6273
}
6274
return
;
6275
// parameter is undefined
6276
L100
:
6277
iuint
= -1;
6278
chnam
=
"undefined"
;
6279
val = 0;
6280
}
6281
6282
////////////////////////////////////////////////////////////////////////////////
6283
/// Prints the values of the parameters at the time of the call
6284
///
6285
/// also prints other relevant information such as function value,
6286
/// estimated distance to minimum, parameter errors, step sizes.
6287
///
6288
/// According to the value of IKODE, the printout is:
6289
/// IKODE=INKODE=
6290
/// - 0 only info about function value
6291
/// - 1 parameter values, errors, limits
6292
/// - 2 values, errors, step sizes, internal values
6293
/// - 3 values, errors, step sizes, first derivs.
6294
/// - 4 values, parabolic errors, MINOS errors
6295
///
6296
/// when INKODE=5, MNPRIN chooses IKODE=1,2, or 3, according to fISW[1]
6297
6298
void
TMinuit::mnprin
(
Int_t
inkode
,
Double_t
fval
)
6299
{
6300
/* Initialized data */
6301
6302
static
const
TString
cblank
=
" "
;
6303
TString
cnambf
=
" "
;
6304
6305
/* Local variables */
6306
Double_t
dcmax
,
x1
,
x2
,
x3
,
dc
;
6307
x2
=
x3
= 0;
6308
Int_t
nadd
, i, k,
l
,
m
,
ikode
,
ic
,
nc
,
ntrail
,
lbl
;
6309
TString
chedm
;
6310
TString
colhdl
[6],
colhdu
[6],
cx2
,
cx3
,
cheval
;
6311
6312
if
(
fNu
== 0) {
6313
Printf
(
" THERE ARE CURRENTLY NO PARAMETERS DEFINED"
);
6314
return
;
6315
}
6316
// get value of IKODE based in INKODE, fISW[1]
6317
ikode
=
inkode
;
6318
if
(
inkode
== 5) {
6319
ikode
=
fISW
[1] + 1;
6320
if
(
ikode
> 3)
ikode
= 3;
6321
}
6322
// set 'default' column headings
6323
for
(k = 1; k <= 6; ++k) {
6324
colhdu
[k-1] =
"UNDEFINED"
;
6325
colhdl
[k-1] =
"COLUMN HEAD"
;
6326
}
6327
// print title if Minos errors, and title exists.
6328
if
(
ikode
== 4 &&
fCtitl
!=
fCundef
) {
6329
Printf
(
" MINUIT TASK: %s"
,(
const
char
*)
fCtitl
);
6330
}
6331
// report function value and status
6332
if
(
fval
==
fUndefi
)
cheval
=
" unknown "
;
6333
else
cheval
.Form(
"%g"
,
fval
);
6334
6335
if
(
fEDM
==
fBigedm
)
chedm
=
" unknown "
;
6336
else
chedm
.Form(
"%g"
,
fEDM
);
6337
6338
nc
=
fNfcn
-
fNfcnfr
;
6339
Printf
(
" FCN=%s FROM %8s STATUS=%10s %6d CALLS %9d TOTAL"
6340
,(
const
char
*)
cheval
6341
,(
const
char
*)
fCfrom
6342
,(
const
char
*)
fCstatu
,
nc
,
fNfcn
);
6343
m
=
fISW
[1];
6344
if
(
m
== 0 ||
m
== 2 ||
fDcovar
== 0) {
6345
Printf
(
" EDM=%s STRATEGY=%2d %s"
6346
,(
const
char
*)
chedm
,
fIstrat
6347
,(
const
char
*)
fCovmes
[
m
]);
6348
}
else
{
6349
dcmax
= 1;
6350
dc
=
TMath::Min
(
fDcovar
,
dcmax
)*100;
6351
Printf
(
" EDM=%s STRATEGY=%2d ERROR MATRIX UNCERTAINTY %5.1f per cent"
6352
,(
const
char
*)
chedm
,
fIstrat
,
dc
);
6353
}
6354
6355
if
(
ikode
== 0)
return
;
6356
// find longest name (for Rene!)
6357
ntrail
= 10;
6358
for
(i = 1; i <=
fNu
; ++i) {
6359
if
(
fNvarl
[i-1] < 0)
continue
;
6360
for
(
ic
= 10;
ic
>= 1; --
ic
) {
6361
if
(
fCpnam
[i-1](
ic
-1,1) !=
" "
)
goto
L16
;
6362
}
6363
ic
= 1;
6364
L16
:
6365
lbl
= 10 -
ic
;
6366
if
(
lbl
<
ntrail
)
ntrail
=
lbl
;
6367
}
6368
nadd
=
ntrail
/ 2 + 1;
6369
if
(
ikode
== 1) {
6370
colhdu
[0] =
" "
;
6371
colhdl
[0] =
" ERROR "
;
6372
colhdu
[1] =
" PHYSICAL"
;
6373
colhdu
[2] =
" LIMITS "
;
6374
colhdl
[1] =
" NEGATIVE "
;
6375
colhdl
[2] =
" POSITIVE "
;
6376
}
6377
if
(
ikode
== 2) {
6378
colhdu
[0] =
" "
;
6379
colhdl
[0] =
" ERROR "
;
6380
colhdu
[1] =
" INTERNAL "
;
6381
colhdl
[1] =
" STEP SIZE "
;
6382
colhdu
[2] =
" INTERNAL "
;
6383
colhdl
[2] =
" VALUE "
;
6384
}
6385
if
(
ikode
== 3) {
6386
colhdu
[0] =
" "
;
6387
colhdl
[0] =
" ERROR "
;
6388
colhdu
[1] =
" STEP "
;
6389
colhdl
[1] =
" SIZE "
;
6390
colhdu
[2] =
" FIRST "
;
6391
colhdl
[2] =
" DERIVATIVE "
;
6392
}
6393
if
(
ikode
== 4) {
6394
colhdu
[0] =
" PARABOLIC "
;
6395
colhdl
[0] =
" ERROR "
;
6396
colhdu
[1] =
" MINOS "
;
6397
colhdu
[2] =
"ERRORS "
;
6398
colhdl
[1] =
" NEGATIVE "
;
6399
colhdl
[2] =
" POSITIVE "
;
6400
}
6401
6402
if
(
ikode
!= 4) {
6403
if
(
fISW
[1] < 3)
colhdu
[0] =
" APPROXIMATE "
;
6404
if
(
fISW
[1] < 1)
colhdu
[0] =
" CURRENT GUESS"
;
6405
}
6406
Printf
(
" EXT PARAMETER %-14s%-14s%-14s"
,(
const
char
*)
colhdu
[0]
6407
,(
const
char
*)
colhdu
[1]
6408
,(
const
char
*)
colhdu
[2]);
6409
Printf
(
" NO. NAME VALUE %-14s%-14s%-14s"
,(
const
char
*)
colhdl
[0]
6410
,(
const
char
*)
colhdl
[1]
6411
,(
const
char
*)
colhdl
[2]);
6412
// loop over parameters
6413
for
(i = 1; i <=
fNu
; ++i) {
6414
if
(
fNvarl
[i-1] < 0)
continue
;
6415
l
=
fNiofex
[i-1];
6416
cnambf
=
cblank
(0,
nadd
) +
fCpnam
[i-1];
6417
if
(
l
== 0)
goto
L55
;
6418
// variable parameter.
6419
x1
=
fWerr
[
l
-1];
6420
cx2
=
"PLEASE GET X.."
;
6421
cx3
=
"PLEASE GET X.."
;
6422
if
(
ikode
== 1) {
6423
if
(
fNvarl
[i-1] <= 1) {
6424
Printf
(
"%4d %-11s%14.5e%14.5e"
,i,(
const
char
*)
cnambf
,
fU
[i-1],
x1
);
6425
continue
;
6426
}
else
{
6427
x2
=
fAlim
[i-1];
6428
x3
=
fBlim
[i-1];
6429
}
6430
}
6431
if
(
ikode
== 2) {
6432
x2
=
fDirin
[
l
-1];
6433
x3
=
fX
[
l
-1];
6434
}
6435
if
(
ikode
== 3) {
6436
x2
=
fDirin
[
l
-1];
6437
x3
=
fGrd
[
l
-1];
6438
if
(
fNvarl
[i-1] > 1 &&
TMath::Abs
(
TMath::Cos
(
fX
[
l
-1])) < .001) {
6439
cx3
=
"** at limit **"
;
6440
}
6441
}
6442
if
(
ikode
== 4) {
6443
x2
=
fErn
[
l
-1];
6444
if
(
x2
== 0)
cx2
=
" "
;
6445
if
(
x2
==
fUndefi
)
cx2
=
" at limit "
;
6446
x3
=
fErp
[
l
-1];
6447
if
(
x3
== 0)
cx3
=
" "
;
6448
if
(
x3
==
fUndefi
)
cx3
=
" at limit "
;
6449
}
6450
if
(
cx2
==
"PLEASE GET X.."
)
cx2
.Form(
"%14.5e"
,
x2
);
6451
if
(
cx3
==
"PLEASE GET X.."
)
cx3
.Form(
"%14.5e"
,
x3
);
6452
Printf
(
"%4d %-11s%14.5e%14.5e%-14s%-14s"
,i
6453
,(
const
char
*)
cnambf
,
fU
[i-1],
x1
6454
,(
const
char
*)
cx2
,(
const
char
*)
cx3
);
6455
6456
// check if parameter is at limit
6457
if
(
fNvarl
[i-1] <= 1 ||
ikode
== 3)
continue
;
6458
if
(
TMath::Abs
(
TMath::Cos
(
fX
[
l
-1])) < .001) {
6459
Printf
(
" WARNING - - ABOVE PARAMETER IS AT LIMIT."
);
6460
}
6461
continue
;
6462
6463
// print constant or fixed parameter.
6464
L55
:
6465
colhdu
[0] =
" constant "
;
6466
if
(
fNvarl
[i-1] > 0)
colhdu
[0] =
" fixed "
;
6467
if
(
fNvarl
[i-1] == 4 &&
ikode
== 1) {
6468
Printf
(
"%4d %-11s%14.5e%-14s%14.5e%14.5e"
,i
6469
,(
const
char
*)
cnambf
,
fU
[i-1]
6470
,(
const
char
*)
colhdu
[0],
fAlim
[i-1],
fBlim
[i-1]);
6471
}
else
{
6472
Printf
(
"%4d %-11s%14.5e%s"
,i
6473
,(
const
char
*)
cnambf
,
fU
[i-1],(
const
char
*)
colhdu
[0]);
6474
}
6475
}
6476
6477
if
(
fUp
!=
fUpdflt
) {
6478
Printf
(
" ERR DEF= %g"
,
fUp
);
6479
}
6480
return
;
6481
}
6482
6483
////////////////////////////////////////////////////////////////////////////////
6484
/// Calculates the eigenvalues of v to see if positive-def
6485
///
6486
/// if not, adds constant along diagonal to make positive.
6487
6488
void
TMinuit::mnpsdf
()
6489
{
6490
/* Local variables */
6491
Double_t
dgmin
,
pAdd
,
pmin
,
pmax
,
dg
,
epspdf
, epsmin;
6492
Int_t
ndex
, i,
j
,
ndexd
,
ip
,
ifault
;
6493
TString
chbuff
,
ctemp
;
6494
6495
epsmin = 1
e
-6;
6496
epspdf
=
TMath::Max
(epsmin,
fEpsma2
);
6497
dgmin
=
fVhmat
[0];
6498
// Check if negative or zero on diagonal
6499
for
(i = 1; i <=
fNpar
; ++i) {
6500
ndex
= i*(i + 1) / 2;
6501
if
(
fVhmat
[
ndex
-1] <= 0) {
6502
mnwarn
(
"W"
,
fCfrom
,
TString::Format
(
"Negative diagonal element %d in Error Matrix"
,i));
6503
}
6504
if
(
fVhmat
[
ndex
-1] <
dgmin
)
dgmin
=
fVhmat
[
ndex
-1];
6505
}
6506
if
(
dgmin
<= 0) {
6507
dg
=
epspdf
+ 1 -
dgmin
;
6508
mnwarn
(
"W"
,
fCfrom
,
TString::Format
(
"%g added to diagonal of error matrix"
,
dg
));
6509
}
else
{
6510
dg
= 0;
6511
}
6512
// Store VHMAT in P, make sure diagonal pos.
6513
for
(i = 1; i <=
fNpar
; ++i) {
6514
ndex
= i*(i-1) / 2;
6515
ndexd
=
ndex
+ i;
6516
fVhmat
[
ndexd
-1] +=
dg
;
6517
if
(
fVhmat
[
ndexd
-1]==0) {
6518
fPSDFs
[i-1] = 1 / 1
e
-19;
// a totally arbitrary silly small value
6519
}
else
{
6520
fPSDFs
[i-1] = 1 /
TMath::Sqrt
(
fVhmat
[
ndexd
-1]);
6521
}
6522
for
(
j
= 1;
j
<= i; ++
j
) {
6523
++
ndex
;
6524
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1] =
fVhmat
[
ndex
-1]*
fPSDFs
[i-1]*
fPSDFs
[
j
-1];
6525
}
6526
}
6527
// call eigen (p,p,maxint,npar,pstar,-npar)
6528
mneig
(
fP
,
fMaxint
,
fNpar
,
fMaxint
,
fPstar
,
epspdf
,
ifault
);
6529
pmin
=
fPstar
[0];
6530
pmax
=
fPstar
[0];
6531
for
(
ip
= 2;
ip
<=
fNpar
; ++
ip
) {
6532
if
(
fPstar
[
ip
-1] <
pmin
)
pmin
=
fPstar
[
ip
-1];
6533
if
(
fPstar
[
ip
-1] >
pmax
)
pmax
=
fPstar
[
ip
-1];
6534
}
6535
pmax
=
TMath::Max
(
TMath::Abs
(
pmax
),
Double_t
(1));
6536
if
((
pmin
<= 0 &&
fLwarn
) ||
fISW
[4] >= 2) {
6537
Printf
(
" EIGENVALUES OF SECOND-DERIVATIVE MATRIX:"
);
6538
ctemp
=
" "
;
6539
for
(
ip
= 1;
ip
<=
fNpar
; ++
ip
) {
6540
ctemp
+=
TString::Format
(
" %11.4e"
,
fPstar
[
ip
-1]);
6541
}
6542
Printf
(
"%s"
,
ctemp
.Data());
6543
}
6544
if
(
pmin
>
epspdf
*
pmax
)
return
;
6545
if
(
fISW
[1] == 3)
fISW
[1] = 2;
6546
pAdd
=
pmax
*.001 -
pmin
;
6547
for
(
ip
= 1;
ip
<=
fNpar
; ++
ip
) {
6548
ndex
=
ip
*(
ip
+ 1) / 2;
6549
fVhmat
[
ndex
-1] *=
pAdd
+ 1;
6550
}
6551
fCstatu
=
"NOT POSDEF"
;
6552
mnwarn
(
"W"
,
fCfrom
,
Form
(
"MATRIX FORCED POS-DEF BY ADDING %f TO DIAGONAL."
,
pAdd
));
6553
6554
}
6555
6556
////////////////////////////////////////////////////////////////////////////////
6557
/// Called only by MNSIMP (and MNIMPR) to add a new point
6558
///
6559
/// and remove an old one from the current simplex, and get the
6560
/// estimated distance to minimum.
6561
6562
void
TMinuit::mnrazz
(
Double_t
ynew
,
Double_t
*
pnew
,
Double_t
*
y
,
Int_t
&
jh
,
Int_t
&
jl
)
6563
{
6564
/* Local variables */
6565
Double_t
pbig
,
plit
;
6566
Int_t
i,
j
,
nparp1
;
6567
6568
/* Function Body */
6569
for
(i = 1; i <=
fNpar
; ++i) {
fP
[i +
jh
*
fMaxpar
-
fMaxpar
-1] =
pnew
[i-1]; }
6570
y
[
jh
-1] =
ynew
;
6571
if
(
ynew
<
fAmin
) {
6572
for
(i = 1; i <=
fNpar
; ++i) {
fX
[i-1] =
pnew
[i-1]; }
6573
mninex
(
fX
);
6574
fAmin
=
ynew
;
6575
fCstatu
=
"PROGRESS "
;
6576
jl
=
jh
;
6577
}
6578
jh
= 1;
6579
nparp1
=
fNpar
+ 1;
6580
for
(
j
= 2;
j
<=
nparp1
; ++
j
) {
if
(
y
[
j
-1] >
y
[
jh
-1])
jh
=
j
; }
6581
fEDM
=
y
[
jh
-1] -
y
[
jl
-1];
6582
if
(
fEDM
<= 0)
goto
L45
;
6583
for
(i = 1; i <=
fNpar
; ++i) {
6584
pbig
=
fP
[i-1];
6585
plit
=
pbig
;
6586
for
(
j
= 2;
j
<=
nparp1
; ++
j
) {
6587
if
(
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1] >
pbig
)
pbig
=
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1];
6588
if
(
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1] <
plit
)
plit
=
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1];
6589
}
6590
fDirin
[i-1] =
pbig
-
plit
;
6591
}
6592
L40
:
6593
return
;
6594
L45
:
6595
if
(
fISW
[4] >= 0) {
6596
Printf
(
" FUNCTION VALUE DOES NOT SEEM TO DEPEND ON ANY OF THE %d VARIABLE PARAMETERS."
,
fNpar
);
6597
Printf
(
" VERIFY THAT STEP SIZES ARE BIG ENOUGH AND CHECK FCN LOGIC."
);
6598
Printf
(
" *******************************************************************************"
);
6599
Printf
(
" *******************************************************************************"
);
6600
}
6601
goto
L40
;
6602
}
6603
6604
////////////////////////////////////////////////////////////////////////////////
6605
/// This is a super-portable random number generator
6606
///
6607
/// It should not overflow on any 32-bit machine.
6608
/// The cycle is only ~10**9, so use with care!
6609
/// Note especially that VAL must not be undefined on input.
6610
///
6611
/// Set Default Starting Seed
6612
6613
void
TMinuit::mnrn15
(
Double_t
&val,
Int_t
&
inseed
)
6614
{
6615
/* Initialized data */
6616
6617
static
std::atomic<Int_t>
g_iseed
( 12345 );
6618
6619
Int_t
k;
6620
6621
if
(val == 3) {
6622
// "entry" to set seed, flag is VAL=3
6623
g_iseed
.store(
inseed
, std::memory_order_release);
6624
}
else
{
6625
// Grab the local value. Two threads might comes here at the same
6626
// time and will end up with the same results.
6627
int
starting_seed
=
g_iseed
.load( std::memory_order_acquire );
6628
int
next_seed
;
6629
6630
do
{
6631
next_seed
=
inseed
=
starting_seed
;
6632
6633
// Determine the next seed.
6634
k =
next_seed
/ 53668;
6635
next_seed
= (
next_seed
- k*53668)*40014 - k*12211;
6636
if
(
next_seed
< 0)
next_seed
+= 2147483563;
6637
6638
val =
Double_t
(
next_seed
*4.656613e-10);
6639
6640
// If more than one thread gets here, one will manage the update
6641
// of g_iseed the other we go for at least one more round.
6642
// This is not reproduceable
6643
}
while
(!
g_iseed
.compare_exchange_strong(
starting_seed
,
next_seed
) );
6644
}
6645
}
6646
6647
////////////////////////////////////////////////////////////////////////////////
6648
/// Resets function value and errors to UNDEFINED
6649
///
6650
/// - If IOPT=1,
6651
/// - If IOPT=0, sets only MINOS errors to undefined
6652
/// Called from MNCLER and whenever problem changes, for example
6653
/// after SET LIMITS, SET PARAM, CALL FCN 6
6654
6655
void
TMinuit::mnrset
(
Int_t
iopt
)
6656
{
6657
Int_t
iext
, i;
6658
6659
fCstatu
=
"RESET "
;
6660
if
(
iopt
>= 1) {
6661
fAmin
=
fUndefi
;
6662
fFval3
=
TMath::Abs
(
fAmin
)*2 + 1;
6663
fEDM
=
fBigedm
;
6664
fISW
[3] = 0;
6665
fISW
[1] = 0;
6666
fDcovar
= 1;
6667
fISW
[0] = 0;
6668
}
6669
fLnolim
=
kTRUE
;
6670
for
(i = 1; i <=
fNpar
; ++i) {
6671
iext
=
fNexofi
[i-1];
6672
if
(
fNvarl
[
iext
-1] >= 4)
fLnolim
=
kFALSE
;
6673
fErp
[i-1] = 0;
6674
fErn
[i-1] = 0;
6675
fGlobcc
[i-1] = 0;
6676
}
6677
if
(
fISW
[1] >= 1) {
6678
fISW
[1] = 1;
6679
fDcovar
=
TMath::Max
(
fDcovar
,.5);
6680
}
6681
}
6682
6683
////////////////////////////////////////////////////////////////////////////////
6684
/// Writes current parameter values and step sizes onto file ISYSSA
6685
///
6686
/// in format which can be reread by Minuit for restarting.
6687
/// The covariance matrix is also output if it exists.
6688
6689
void
TMinuit::mnsave
()
6690
{
6691
Printf
(
"mnsave is dummy in TMinuit"
);
6692
6693
}
6694
6695
////////////////////////////////////////////////////////////////////////////////
6696
/// Scans the values of FCN as a function of one parameter
6697
///
6698
/// and plots the resulting values as a curve using MNPLOT.
6699
/// It may be called to scan one parameter or all parameters.
6700
/// retains the best function and parameter values found.
6701
6702
void
TMinuit::mnscan
()
6703
{
6704
/* Local variables */
6705
Double_t
step,
uhigh
,
xhreq
,
xlreq
,
ubest
,
fnext
,
unext
,
xh
,
xl
;
6706
Int_t
ipar,
iint
,
icall
,
ncall
,
nbins
,
nparx
;
6707
Int_t
nxypt
,
nccall
,
iparwd
;
6708
6709
xlreq
=
TMath::Min
(
fWord7
[2],
fWord7
[3]);
6710
xhreq
=
TMath::Max
(
fWord7
[2],
fWord7
[3]);
6711
ncall
=
Int_t
((
fWord7
[1] + .01));
6712
if
(
ncall
<= 1)
ncall
= 41;
6713
if
(
ncall
> 98)
ncall
= 98;
6714
nccall
=
ncall
;
6715
if
(
fAmin
==
fUndefi
)
mnamin
();
6716
iparwd
=
Int_t
((
fWord7
[0] + .1));
6717
ipar =
TMath::Max
(
iparwd
,0);
6718
fCstatu
=
"NO CHANGE"
;
6719
if
(
iparwd
> 0)
goto
L200
;
6720
6721
// equivalent to a loop over parameters requested
6722
L100
:
6723
++ipar;
6724
if
(ipar >
fNu
)
goto
L900
;
6725
iint
=
fNiofex
[ipar-1];
6726
if
(
iint
<= 0)
goto
L100
;
6727
// set up range for parameter IPAR
6728
L200
:
6729
iint
=
fNiofex
[ipar-1];
6730
ubest
=
fU
[ipar-1];
6731
fXpt
[0] =
ubest
;
6732
fYpt
[0] =
fAmin
;
6733
fChpt
[0] =
' '
;
6734
fXpt
[1] =
ubest
;
6735
fYpt
[1] =
fAmin
;
6736
fChpt
[1] =
'X'
;
6737
nxypt
= 2;
6738
if
(
fNvarl
[ipar-1] > 1)
goto
L300
;
6739
6740
// no limits on parameter
6741
if
(
xlreq
==
xhreq
)
goto
L250
;
6742
unext
=
xlreq
;
6743
step = (
xhreq
-
xlreq
) /
Double_t
(
ncall
-1);
6744
goto
L500
;
6745
L250
:
6746
xl
=
ubest
-
fWerr
[
iint
-1];
6747
xh
=
ubest
+
fWerr
[
iint
-1];
6748
mnbins
(
xl
,
xh
,
ncall
,
unext
,
uhigh
,
nbins
, step);
6749
nccall
=
nbins
+ 1;
6750
goto
L500
;
6751
// limits on parameter
6752
L300
:
6753
if
(
xlreq
==
xhreq
)
goto
L350
;
6754
// Computing MAX
6755
xl
=
TMath::Max
(
xlreq
,
fAlim
[ipar-1]);
6756
// Computing MIN
6757
xh
=
TMath::Min
(
xhreq
,
fBlim
[ipar-1]);
6758
if
(
xl
>=
xh
)
goto
L700
;
6759
unext
=
xl
;
6760
step = (
xh
-
xl
) /
Double_t
(
ncall
-1);
6761
goto
L500
;
6762
L350
:
6763
unext
=
fAlim
[ipar-1];
6764
step = (
fBlim
[ipar-1] -
fAlim
[ipar-1]) /
Double_t
(
ncall
-1);
6765
// main scanning loop over parameter IPAR
6766
L500
:
6767
for
(
icall
= 1;
icall
<=
nccall
; ++
icall
) {
6768
fU
[ipar-1] =
unext
;
6769
nparx
=
fNpar
;
6770
Eval
(
nparx
,
fGin
,
fnext
,
fU
, 4); ++
fNfcn
;
6771
++
nxypt
;
6772
fXpt
[
nxypt
-1] =
unext
;
6773
fYpt
[
nxypt
-1] =
fnext
;
6774
fChpt
[
nxypt
-1] =
'*'
;
6775
if
(
fnext
<
fAmin
) {
6776
fAmin
=
fnext
;
6777
ubest
=
unext
;
6778
fCstatu
=
"IMPROVED "
;
6779
}
6780
unext
+= step;
6781
}
6782
fChpt
[
nccall
] = 0;
6783
6784
// finished with scan of parameter IPAR
6785
fU
[ipar-1] =
ubest
;
6786
mnexin
(
fX
);
6787
if
(
fISW
[4] >= 1)
6788
Printf
(
"%dSCAN OF PARAMETER NO. %d, %s"
6789
,
fNewpag
,ipar,(
const
char
*)
fCpnam
[ipar-1]);
6790
mnplot
(
fXpt
,
fYpt
,
fChpt
,
nxypt
,
fNpagwd
,
fNpagln
);
6791
goto
L800
;
6792
L700
:
6793
Printf
(
" REQUESTED RANGE OUTSIDE LIMITS FOR PARAMETER %d"
,ipar);
6794
L800
:
6795
if
(
iparwd
<= 0)
goto
L100
;
6796
// finished with all parameters
6797
L900
:
6798
if
(
fISW
[4] >= 0)
mnprin
(5,
fAmin
);
6799
}
6800
6801
////////////////////////////////////////////////////////////////////////////////
6802
/// Performs a rough (but global) minimization by monte carlo search
6803
///
6804
/// Each time a new minimum is found, the search area is shifted
6805
/// to be centered at the best value. Random points are chosen
6806
/// uniformly over a hypercube determined by current step sizes.
6807
/// The Metropolis algorithm accepts a worse point with probability
6808
/// exp(-d/UP), where d is the degradation. Improved points
6809
/// are of course always accepted. Actual steps are random
6810
/// multiples of the nominal steps (DIRIN).
6811
6812
void
TMinuit::mnseek
()
6813
{
6814
/* Local variables */
6815
Double_t
dxdi
,
rnum
,
ftry
,
rnum1
,
rnum2
, alpha;
6816
Double_t
flast
, bar;
6817
Int_t
ipar,
iext
,
j
,
ifail
,
iseed
=0,
nparx
,
istep
,
ib
,
mxfail
,
mxstep
;
6818
6819
mxfail
=
Int_t
(
fWord7
[0]);
6820
if
(
mxfail
<= 0)
mxfail
=
fNpar
*20 + 100;
6821
mxstep
=
mxfail
*10;
6822
if
(
fAmin
==
fUndefi
)
mnamin
();
6823
alpha =
fWord7
[1];
6824
if
(alpha <= 0) alpha = 3;
6825
if
(
fISW
[4] >= 1) {
6826
Printf
(
" MNSEEK: MONTE CARLO MINIMIZATION USING METROPOLIS ALGORITHM"
);
6827
Printf
(
" TO STOP AFTER %6d SUCCESSIVE FAILURES, OR %7d STEPS"
,
mxfail
,
mxstep
);
6828
Printf
(
" MAXIMUM STEP SIZE IS %9.3f ERROR BARS."
,alpha);
6829
}
6830
fCstatu
=
"INITIAL "
;
6831
if
(
fISW
[4] >= 2)
mnprin
(2,
fAmin
);
6832
fCstatu
=
"UNCHANGED "
;
6833
ifail
= 0;
6834
rnum
= 0;
6835
rnum1
= 0;
6836
rnum2
= 0;
6837
nparx
=
fNpar
;
6838
flast
=
fAmin
;
6839
// set up step sizes, starting values
6840
for
(ipar = 1; ipar <=
fNpar
; ++ipar) {
6841
iext
=
fNexofi
[ipar-1];
6842
fDirin
[ipar-1] = alpha*2*
fWerr
[ipar-1];
6843
if
(
fNvarl
[
iext
-1] > 1) {
6844
// parameter with limits
6845
mndxdi
(
fX
[ipar-1], ipar-1,
dxdi
);
6846
if
(
dxdi
== 0)
dxdi
= 1;
6847
fDirin
[ipar-1] = alpha*2*
fWerr
[ipar-1] /
dxdi
;
6848
if
(
TMath::Abs
(
fDirin
[ipar-1]) > 6.2831859999999997) {
6849
fDirin
[ipar-1] = 6.2831859999999997;
6850
}
6851
}
6852
fSEEKxmid
[ipar-1] =
fX
[ipar-1];
6853
fSEEKxbest
[ipar-1] =
fX
[ipar-1];
6854
}
6855
// search loop
6856
for
(
istep
= 1;
istep
<=
mxstep
; ++
istep
) {
6857
if
(
ifail
>=
mxfail
)
break
;
6858
for
(ipar = 1; ipar <=
fNpar
; ++ipar) {
6859
mnrn15
(
rnum1
,
iseed
);
6860
mnrn15
(
rnum2
,
iseed
);
6861
fX
[ipar-1] =
fSEEKxmid
[ipar-1] + (
rnum1
+
rnum2
- 1)*.5*
fDirin
[ipar-1];
6862
}
6863
mninex
(
fX
);
6864
Eval
(
nparx
,
fGin
,
ftry
,
fU
, 4); ++
fNfcn
;
6865
if
(
ftry
<
flast
) {
6866
if
(
ftry
<
fAmin
) {
6867
fCstatu
=
"IMPROVEMENT"
;
6868
fAmin
=
ftry
;
6869
for
(
ib
= 1;
ib
<=
fNpar
; ++
ib
) {
fSEEKxbest
[
ib
-1] =
fX
[
ib
-1]; }
6870
ifail
= 0;
6871
if
(
fISW
[4] >= 2)
mnprin
(2,
fAmin
);
6872
}
6873
goto
L300
;
6874
}
else
{
6875
++
ifail
;
6876
// Metropolis algorithm
6877
bar = (
fAmin
-
ftry
) /
fUp
;
6878
mnrn15
(
rnum
,
iseed
);
6879
if
(bar <
TMath::Log
(
rnum
))
continue
;
6880
}
6881
// Accept new point, move there
6882
L300
:
6883
for
(
j
= 1;
j
<=
fNpar
; ++
j
) {
fSEEKxmid
[
j
-1] =
fX
[
j
-1]; }
6884
flast
=
ftry
;
6885
}
6886
// end search loop
6887
if
(
fISW
[4] > 1) {
6888
Printf
(
" MNSEEK: %5d SUCCESSIVE UNSUCCESSFUL TRIALS."
,
ifail
);
6889
}
6890
for
(
ib
= 1;
ib
<=
fNpar
; ++
ib
) {
fX
[
ib
-1] =
fSEEKxbest
[
ib
-1]; }
6891
mninex
(
fX
);
6892
if
(
fISW
[4] >= 1)
mnprin
(2,
fAmin
);
6893
if
(
fISW
[4] == 0)
mnprin
(0,
fAmin
);
6894
}
6895
6896
////////////////////////////////////////////////////////////////////////////////
6897
/// Interprets the commands that start with SET and SHOW
6898
///
6899
/// Called from MNEXCM
6900
/// file characteristics for SET INPUT
6901
/// 'SET ' or 'SHOW', 'ON ' or 'OFF', 'SUPPRESSED' or 'REPORTED '
6902
/// explanation of print level numbers -1:3 and strategies 0:2
6903
/// identification of debug options
6904
/// things that can be set or shown
6905
/// options not intended for normal users
6906
6907
void
TMinuit::mnset
()
6908
{
6909
/* Initialized data */
6910
6911
static
const
char
*
const
cname
[30] = {
6912
"FCN value "
,
6913
"PARameters"
,
6914
"LIMits "
,
6915
"COVariance"
,
6916
"CORrelatio"
,
6917
"PRInt levl"
,
6918
"NOGradient"
,
6919
"GRAdient "
,
6920
"ERRor def "
,
6921
"INPut file"
,
6922
"WIDth page"
,
6923
"LINes page"
,
6924
"NOWarnings"
,
6925
"WARnings "
,
6926
"RANdom gen"
,
6927
"TITle "
,
6928
"STRategy "
,
6929
"EIGenvalue"
,
6930
"PAGe throw"
,
6931
"MINos errs"
,
6932
"EPSmachine"
,
6933
"OUTputfile"
,
6934
"BATch "
,
6935
"INTeractiv"
,
6936
"VERsion "
,
6937
"reserve "
,
6938
"NODebug "
,
6939
"DEBug "
,
6940
"SHOw "
,
6941
"SET "
};
6942
6943
static
constexpr
Int_t
nname
= 25;
// Must less than sizeof(cname)/sizeof(char*)
6944
static
constexpr
Int_t
nntot
=
sizeof
(
cname
)/
sizeof
(
char
*);
6945
static
const
TString
cprlev
[5] = {
6946
"-1: NO OUTPUT EXCEPT FROM SHOW "
,
6947
" 0: REDUCED OUTPUT "
,
6948
" 1: NORMAL OUTPUT "
,
6949
" 2: EXTRA OUTPUT FOR PROBLEM CASES"
,
6950
" 3: MAXIMUM OUTPUT "
};
6951
6952
static
const
TString
cstrat
[3] = {
6953
" 0: MINIMIZE THE NUMBER OF CALLS TO FUNCTION"
,
6954
" 1: TRY TO BALANCE SPEED AGAINST RELIABILITY"
,
6955
" 2: MAKE SURE MINIMUM TRUE, ERRORS CORRECT "
};
6956
6957
static
const
TString
cdbopt
[7] = {
6958
"REPORT ALL EXCEPTIONAL CONDITIONS "
,
6959
"MNLINE: LINE SEARCH MINIMIZATION "
,
6960
"MNDERI: FIRST DERIVATIVE CALCULATIONS "
,
6961
"MNHESS: SECOND DERIVATIVE CALCULATIONS "
,
6962
"MNMIGR: COVARIANCE MATRIX UPDATES "
,
6963
"MNHES1: FIRST DERIVATIVE UNCERTAINTIES "
,
6964
"MNCONT: MNCONTOUR PLOT (MNCROS SEARCH) "
};
6965
6966
/* System generated locals */
6967
//Int_t f_inqu();
6968
6969
/* Local variables */
6970
Double_t
val;
6971
Int_t
iset
,
iprm
, i,
jseed
,
kname
,
iseed
,
iunit
,
id
,
ii
,
kk
;
6972
Int_t
ikseed
,
idbopt
,
igrain
=0,
iswsav
,
isw2
;
6973
TString
cfname
,
cmode
,
ckind
,
cwarn
,
copt
,
ctemp
,
ctemp2
;
6974
Bool_t
lname
=
kFALSE
;
6975
6976
for
(i = 1; i <=
nntot
; ++i) {
6977
ctemp
=
cname
[i-1];
6978
ckind
=
ctemp
(0,3);
6979
ctemp2
=
fCword
(4,6);
6980
if
(
strstr
(
ctemp2
.Data(),
ckind
.Data()))
goto
L5
;
6981
}
6982
i = 0;
6983
L5
:
6984
kname
= i;
6985
6986
// Command could be SET xxx, SHOW xxx, HELP SET or HELP SHOW
6987
ctemp2
=
fCword
(0,3);
6988
if
(
ctemp2
.Contains(
"HEL"
))
goto
L2000
;
6989
if
(
ctemp2
.Contains(
"SHO"
))
goto
L1000
;
6990
if
(!
ctemp2
.Contains(
"SET"
))
goto
L1900
;
6991
// ---
6992
ckind
=
"SET "
;
6993
// set unknown
6994
if
(
kname
<= 0)
goto
L1900
;
6995
// set known
6996
switch
((
int
)
kname
) {
6997
case
1:
goto
L3000
;
6998
case
2:
goto
L20
;
6999
case
3:
goto
L30
;
7000
case
4:
goto
L40
;
7001
case
5:
goto
L3000
;
7002
case
6:
goto
L60
;
7003
case
7:
goto
L70
;
7004
case
8:
goto
L80
;
7005
case
9:
goto
L90
;
7006
case
10:
goto
L100
;
7007
case
11:
goto
L110
;
7008
case
12:
goto
L120
;
7009
case
13:
goto
L130
;
7010
case
14:
goto
L140
;
7011
case
15:
goto
L150
;
7012
case
16:
goto
L160
;
7013
case
17:
goto
L170
;
7014
case
18:
goto
L3000
;
7015
case
19:
goto
L190
;
7016
case
20:
goto
L3000
;
7017
case
21:
goto
L210
;
7018
case
22:
goto
L220
;
7019
case
23:
goto
L230
;
7020
case
24:
goto
L240
;
7021
case
25:
goto
L3000
;
7022
case
26:
goto
L1900
;
7023
case
27:
goto
L270
;
7024
case
28:
goto
L280
;
7025
case
29:
goto
L290
;
7026
case
30:
goto
L300
;
7027
}
7028
7029
// set param
7030
L20
:
7031
iprm
=
Int_t
(
fWord7
[0]);
7032
if
(
iprm
>
fNu
)
goto
L25
;
7033
if
(
iprm
<= 0)
goto
L25
;
7034
if
(
fNvarl
[
iprm
-1] < 0)
goto
L25
;
7035
fU
[
iprm
-1] =
fWord7
[1];
7036
mnexin
(
fX
);
7037
isw2
=
fISW
[1];
7038
mnrset
(1);
7039
// Keep approximate covariance matrix, even if new param value
7040
fISW
[1] =
TMath::Min
(
isw2
,1);
7041
fCfrom
=
"SET PARM"
;
7042
fNfcnfr
=
fNfcn
;
7043
fCstatu
=
"NEW VALUES"
;
7044
return
;
7045
L25
:
7046
Printf
(
" UNDEFINED PARAMETER NUMBER. IGNORED."
);
7047
return
;
7048
// set limits
7049
L30
:
7050
mnlims
();
7051
return
;
7052
// set covar
7053
L40
:
7054
// this command must be handled by MNREAD, and is not Fortran-callable
7055
goto
L3000
;
7056
// set print
7057
L60
:
7058
fISW
[4] =
Int_t
(
fWord7
[0]);
7059
return
;
7060
// set nograd
7061
L70
:
7062
fISW
[2] = 0;
7063
return
;
7064
// set grad
7065
L80
:
7066
mngrad
();
7067
return
;
7068
// set errdef
7069
L90
:
7070
if
(
fWord7
[0] ==
fUp
)
return
;
7071
if
(
fWord7
[0] <= 0) {
7072
if
(
fUp
==
fUpdflt
)
return
;
7073
fUp
=
fUpdflt
;
7074
}
else
{
7075
fUp
=
fWord7
[0];
7076
}
7077
for
(i = 1; i <=
fNpar
; ++i) {
7078
fErn
[i-1] = 0;
7079
fErp
[i-1] = 0;
7080
}
7081
mnwerr
();
7082
return
;
7083
// set input
7084
// This command must be handled by MNREAD. If it gets this far,
7085
// it is illegal.
7086
L100
:
7087
goto
L3000
;
7088
// set width
7089
L110
:
7090
fNpagwd
=
Int_t
(
fWord7
[0]);
7091
fNpagwd
=
TMath::Max
(
fNpagwd
,50);
7092
return
;
7093
7094
L120
:
7095
fNpagln
=
Int_t
(
fWord7
[0]);
7096
return
;
7097
// set nowarn
7098
7099
L130
:
7100
fLwarn
=
kFALSE
;
7101
return
;
7102
// set warn
7103
L140
:
7104
fLwarn
=
kTRUE
;
7105
mnwarn
(
"W"
,
"SHO"
,
"SHO"
);
7106
return
;
7107
// set random
7108
L150
:
7109
jseed
=
Int_t
(
fWord7
[0]);
7110
val = 3;
7111
mnrn15
(val,
jseed
);
7112
if
(
fISW
[4] > 0) {
7113
Printf
(
" MINUIT RANDOM NUMBER SEED SET TO %d"
,
jseed
);
7114
}
7115
return
;
7116
// set title
7117
L160
:
7118
// this command must be handled by MNREAD, and is not Fortran-callable
7119
goto
L3000
;
7120
// set strategy
7121
L170
:
7122
fIstrat
=
Int_t
(
fWord7
[0]);
7123
fIstrat
=
TMath::Max
(
fIstrat
,0);
7124
fIstrat
=
TMath::Min
(
fIstrat
,2);
7125
if
(
fISW
[4] > 0)
goto
L1172
;
7126
return
;
7127
// set page throw
7128
L190
:
7129
fNewpag
=
Int_t
(
fWord7
[0]);
7130
goto
L1190
;
7131
// set epsmac
7132
L210
:
7133
if
(
fWord7
[0] > 0 &&
fWord7
[0] < .1) {
7134
fEpsmac
=
fWord7
[0];
7135
}
7136
fEpsma2
=
TMath::Sqrt
(
fEpsmac
);
7137
goto
L1210
;
7138
// set outputfile
7139
L220
:
7140
iunit
=
Int_t
(
fWord7
[0]);
7141
fIsyswr
=
iunit
;
7142
fIstkwr
[0] =
iunit
;
7143
if
(
fISW
[4] >= 0)
goto
L1220
;
7144
return
;
7145
// set batch
7146
L230
:
7147
fISW
[5] = 0;
7148
if
(
fISW
[4] >= 0)
goto
L1100
;
7149
return
;
7150
// set interactive
7151
L240
:
7152
fISW
[5] = 1;
7153
if
(
fISW
[4] >= 0)
goto
L1100
;
7154
return
;
7155
// set nodebug
7156
L270
:
7157
iset
= 0;
7158
goto
L281
;
7159
// set debug
7160
L280
:
7161
iset
= 1;
7162
L281
:
7163
idbopt
=
Int_t
(
fWord7
[0]);
7164
if
(
idbopt
> 6)
goto
L288
;
7165
if
(
idbopt
>= 0) {
7166
fIdbg
[
idbopt
] =
iset
;
7167
if
(
iset
== 1)
fIdbg
[0] = 1;
7168
}
else
{
7169
// SET DEBUG -1 sets all debug options
7170
for
(
id
= 0;
id
<= 6; ++
id
) {
fIdbg
[
id
] =
iset
; }
7171
}
7172
fLrepor
=
fIdbg
[0] >= 1;
7173
mnwarn
(
"D"
,
"SHO"
,
"SHO"
);
7174
return
;
7175
L288
:
7176
Printf
(
" UNKNOWN DEBUG OPTION %d REQUESTED. IGNORED"
,
idbopt
);
7177
return
;
7178
// set show
7179
L290
:
7180
// set set
7181
L300
:
7182
goto
L3000
;
7183
// -----------------------------------------------------
7184
L1000
:
7185
// at this point, CWORD must be 'SHOW'
7186
ckind
=
"SHOW"
;
7187
if
(
kname
<= 0)
goto
L1900
;
7188
7189
switch
((
int
)
kname
) {
7190
case
1:
goto
L1010
;
7191
case
2:
goto
L1020
;
7192
case
3:
goto
L1030
;
7193
case
4:
goto
L1040
;
7194
case
5:
goto
L1050
;
7195
case
6:
goto
L1060
;
7196
case
7:
goto
L1070
;
7197
case
8:
goto
L1070
;
7198
case
9:
goto
L1090
;
7199
case
10:
goto
L1100
;
7200
case
11:
goto
L1110
;
7201
case
12:
goto
L1120
;
7202
case
13:
goto
L1130
;
7203
case
14:
goto
L1130
;
7204
case
15:
goto
L1150
;
7205
case
16:
goto
L1160
;
7206
case
17:
goto
L1170
;
7207
case
18:
goto
L1180
;
7208
case
19:
goto
L1190
;
7209
case
20:
goto
L1200
;
7210
case
21:
goto
L1210
;
7211
case
22:
goto
L1220
;
7212
case
23:
goto
L1100
;
7213
case
24:
goto
L1100
;
7214
case
25:
goto
L1250
;
7215
case
26:
goto
L1900
;
7216
case
27:
goto
L1270
;
7217
case
28:
goto
L1270
;
7218
case
29:
goto
L1290
;
7219
case
30:
goto
L1300
;
7220
}
7221
7222
// show fcn
7223
L1010
:
7224
if
(
fAmin
==
fUndefi
)
mnamin
();
7225
mnprin
(0,
fAmin
);
7226
return
;
7227
// show param
7228
L1020
:
7229
if
(
fAmin
==
fUndefi
)
mnamin
();
7230
mnprin
(5,
fAmin
);
7231
return
;
7232
// show limits
7233
L1030
:
7234
if
(
fAmin
==
fUndefi
)
mnamin
();
7235
mnprin
(1,
fAmin
);
7236
return
;
7237
// show covar
7238
L1040
:
7239
mnmatu
(1);
7240
return
;
7241
// show corre
7242
L1050
:
7243
mnmatu
(0);
7244
return
;
7245
// show print
7246
L1060
:
7247
if
(
fISW
[4] < -1)
fISW
[4] = -1;
7248
if
(
fISW
[4] > 3)
fISW
[4] = 3;
7249
Printf
(
" ALLOWED PRINT LEVELS ARE:"
);
7250
Printf
(
" %s"
,
cprlev
[0].Data());
7251
Printf
(
" %s"
,
cprlev
[1].Data());
7252
Printf
(
" %s"
,
cprlev
[2].Data());
7253
Printf
(
" %s"
,
cprlev
[3].Data());
7254
Printf
(
" %s"
,
cprlev
[4].Data());
7255
Printf
(
" CURRENT PRINTOUT LEVEL IS %s"
,
cprlev
[
fISW
[4]+1].Data());
7256
return
;
7257
// show nograd, grad
7258
L1070
:
7259
if
(
fISW
[2] <= 0) {
7260
Printf
(
" NOGRAD IS SET. DERIVATIVES NOT COMPUTED IN FCN."
);
7261
}
else
{
7262
Printf
(
" GRAD IS SET. USER COMPUTES DERIVATIVES IN FCN."
);
7263
}
7264
return
;
7265
// show errdef
7266
L1090
:
7267
Printf
(
" ERRORS CORRESPOND TO FUNCTION CHANGE OF %g"
,
fUp
);
7268
return
;
7269
// show input,
7270
// batch, or interactive
7271
L1100
:
7272
// ioin__1.inerr = 0;
7273
// ioin__1.inunit = fIsysrd;
7274
// ioin__1.infile = 0;
7275
// ioin__1.inex = 0;
7276
// ioin__1.inopen = 0;
7277
// ioin__1.innum = 0;
7278
// ioin__1.innamed = &lname;
7279
// ioin__1.innamlen = 64;
7280
// ioin__1.inname = cfname;
7281
// ioin__1.inacc = 0;
7282
// ioin__1.inseq = 0;
7283
// ioin__1.indir = 0;
7284
// ioin__1.infmt = 0;
7285
// ioin__1.inform = 0;
7286
// ioin__1.inunf = 0;
7287
// ioin__1.inrecl = 0;
7288
// ioin__1.innrec = 0;
7289
// ioin__1.inblank = 0;
7290
// f_inqu(&ioin__1);
7291
cmode
=
"BATCH MODE "
;
7292
if
(
fISW
[5] == 1)
cmode
=
"INTERACTIVE MODE"
;
7293
if
(!
lname
)
cfname
=
"unknown"
;
7294
Printf
(
" INPUT NOW BEING READ IN %s FROM UNIT NO. %d FILENAME: %s"
7295
,(
const
char
*)
cmode
,
fIsysrd
,(
const
char
*)
cfname
);
7296
return
;
7297
// show width
7298
L1110
:
7299
Printf
(
" PAGE WIDTH IS SET TO %d COLUMNS"
,
fNpagwd
);
7300
return
;
7301
// show lines
7302
L1120
:
7303
Printf
(
" PAGE LENGTH IS SET TO %d LINES"
,
fNpagln
);
7304
return
;
7305
// show nowarn, warn
7306
L1130
:
7307
cwarn
=
"SUPPRESSED"
;
7308
if
(
fLwarn
)
cwarn
=
"REPORTED "
;
7309
Printf
(
"%s"
,(
const
char
*)
cwarn
);
7310
if
(!
fLwarn
)
mnwarn
(
"W"
,
"SHO"
,
"SHO"
);
7311
return
;
7312
// show random
7313
L1150
:
7314
val = 0;
7315
mnrn15
(val,
igrain
);
7316
ikseed
=
igrain
;
7317
Printf
(
" MINUIT RNDM SEED IS CURRENTLY=%d"
,
ikseed
);
7318
val = 3;
7319
iseed
=
ikseed
;
7320
mnrn15
(val,
iseed
);
7321
return
;
7322
// show title
7323
L1160
:
7324
Printf
(
" TITLE OF CURRENT TASK IS:%s"
,(
const
char
*)
fCtitl
);
7325
return
;
7326
// show strategy
7327
L1170
:
7328
Printf
(
" ALLOWED STRATEGIES ARE:"
);
7329
Printf
(
" %s"
,
cstrat
[0].Data());
7330
Printf
(
" %s"
,
cstrat
[1].Data());
7331
Printf
(
" %s"
,
cstrat
[2].Data());
7332
L1172
:
7333
Printf
(
" NOW USING STRATEGY %s"
,(
const
char
*)
cstrat
[
fIstrat
]);
7334
return
;
7335
// show eigenvalues
7336
L1180
:
7337
iswsav
=
fISW
[4];
7338
fISW
[4] = 3;
7339
if
(
fISW
[1] < 1) {
7340
Printf
(
"%s"
,(
const
char
*)
fCovmes
[0]);
7341
}
else
{
7342
mnpsdf
();
7343
}
7344
fISW
[4] =
iswsav
;
7345
return
;
7346
// show page throw
7347
L1190
:
7348
Printf
(
" PAGE THROW CARRIAGE CONTROL = %d"
,
fNewpag
);
7349
if
(
fNewpag
== 0) {
7350
Printf
(
" NO PAGE THROWS IN MINUIT OUTPUT"
);
7351
}
7352
return
;
7353
// show minos errors
7354
L1200
:
7355
for
(
ii
= 1;
ii
<=
fNpar
; ++
ii
) {
7356
if
(
fErp
[
ii
-1] > 0 ||
fErn
[
ii
-1] < 0)
goto
L1204
;
7357
}
7358
Printf
(
" THERE ARE NO MINOS ERRORS CURRENTLY VALID."
);
7359
return
;
7360
L1204
:
7361
mnprin
(4,
fAmin
);
7362
return
;
7363
// show epsmac
7364
L1210
:
7365
Printf
(
" FLOATING-POINT NUMBERS ASSUMED ACCURATE TO %g"
,
fEpsmac
);
7366
return
;
7367
// show outputfiles
7368
L1220
:
7369
Printf
(
" MINUIT PRIMARY OUTPUT TO UNIT %d"
,
fIsyswr
);
7370
return
;
7371
// show version
7372
L1250
:
7373
Printf
(
" THIS IS MINUIT VERSION:%s"
,(
const
char
*)
fCvrsn
);
7374
return
;
7375
// show nodebug, debug
7376
L1270
:
7377
for
(
id
= 0;
id
<= 6; ++
id
) {
7378
copt
=
"OFF"
;
7379
if
(
fIdbg
[
id
] >= 1)
copt
=
"ON "
;
7380
Printf
(
" DEBUG OPTION %3d IS %3s :%s"
7381
,
id
,(
const
char
*)
copt
,(
const
char
*)
cdbopt
[
id
]);
7382
}
7383
if
(!
fLrepor
)
mnwarn
(
"D"
,
"SHO"
,
"SHO"
);
7384
return
;
7385
// show show
7386
L1290
:
7387
ckind
=
"SHOW"
;
7388
goto
L2100
;
7389
// show set
7390
L1300
:
7391
ckind
=
"SET "
;
7392
goto
L2100
;
7393
// -----------------------------------------------------
7394
// UNKNOWN COMMAND
7395
L1900
:
7396
Printf
(
" THE COMMAND:%10s IS UNKNOWN."
,(
const
char
*)
fCword
);
7397
goto
L2100
;
7398
// -----------------------------------------------------
7399
// HELP SHOW, HELP SET, SHOW SET, or SHOW SHOW
7400
L2000
:
7401
ckind
=
"SET "
;
7402
ctemp2
=
fCword
(3,7);
7403
if
(
strcmp
(
ctemp2
.Data(),
"SHO"
))
ckind
=
"SHOW"
;
7404
L2100
:
7405
Printf
(
" THE FORMAT OF THE %4s COMMAND IS:"
,(
const
char
*)
ckind
);
7406
Printf
(
" %s xxx [numerical arguments if any]"
,(
const
char
*)
ckind
);
7407
Printf
(
" WHERE xxx MAY BE ONE OF THE FOLLOWING:"
);
7408
for
(
kk
= 1;
kk
<=
nname
; ++
kk
) {
7409
Printf
(
" %s"
,
cname
[
kk
-1]);
7410
}
7411
return
;
7412
// -----------------------------------------------------
7413
// ILLEGAL COMMAND
7414
L3000
:
7415
Printf
(
" ABOVE COMMAND IS ILLEGAL. IGNORED"
);
7416
7417
}
7418
7419
////////////////////////////////////////////////////////////////////////////////
7420
/// Minimization using the simplex method of Nelder and Mead
7421
///
7422
/// Performs a minimization using the simplex method of Nelder
7423
/// and Mead (ref. -- Comp. J. 7,308 (1965)).
7424
7425
void
TMinuit::mnsimp
()
7426
{
7427
/* Initialized data */
7428
7429
static
constexpr
Double_t
alpha = 1;
7430
static
constexpr
Double_t
beta = .5;
7431
static
constexpr
Double_t
gamma = 2;
7432
static
constexpr
Double_t
rhomin
= 4;
7433
static
constexpr
Double_t
rhomax
= 8;
7434
7435
/* Local variables */
7436
Double_t
dmin_
,
dxdi
,
yrho
,
f
,
ynpp1
,
aming
,
ypbar
;
7437
Double_t
bestx
,
ystar
,
y1
,
y2
,
ystst
,
pb
,
wg
;
7438
Double_t
absmin
, rho,
sig2
, rho1, rho2;
7439
Int_t
npfn
, i,
j
, k,
jhold
,
ncycl
,
nparx
;
7440
Int_t
nparp1
, kg,
jh
,
nf
,
jl
, ns;
7441
7442
if
(
fNpar
<= 0)
return
;
7443
if
(
fAmin
==
fUndefi
)
mnamin
();
7444
fCfrom
=
"SIMPLEX "
;
7445
fNfcnfr
=
fNfcn
;
7446
fCstatu
=
"UNCHANGED "
;
7447
npfn
=
fNfcn
;
7448
nparp1
=
fNpar
+ 1;
7449
nparx
=
fNpar
;
7450
rho1 = alpha + 1;
7451
rho2 = rho1 + alpha*gamma;
7452
wg
= 1 /
Double_t
(
fNpar
);
7453
if
(
fISW
[4] >= 0) {
7454
Printf
(
" START SIMPLEX MINIMIZATION. CONVERGENCE WHEN EDM .LT. %g"
,
fEpsi
);
7455
}
7456
for
(i = 1; i <=
fNpar
; ++i) {
7457
fDirin
[i-1] =
fWerr
[i-1];
7458
mndxdi
(
fX
[i-1], i-1,
dxdi
);
7459
if
(
dxdi
!= 0)
fDirin
[i-1] =
fWerr
[i-1] /
dxdi
;
7460
dmin_
=
fEpsma2
*
TMath::Abs
(
fX
[i-1]);
7461
if
(
fDirin
[i-1] <
dmin_
)
fDirin
[i-1] =
dmin_
;
7462
}
7463
// choose the initial simplex using single-parameter searches
7464
L1:
7465
ynpp1
=
fAmin
;
7466
jl
=
nparp1
;
7467
fSIMPy
[
nparp1
-1] =
fAmin
;
7468
absmin
=
fAmin
;
7469
for
(i = 1; i <=
fNpar
; ++i) {
7470
aming
=
fAmin
;
7471
fPbar
[i-1] =
fX
[i-1];
7472
bestx
=
fX
[i-1];
7473
kg = 0;
7474
ns = 0;
7475
nf
= 0;
7476
L4
:
7477
fX
[i-1] =
bestx
+
fDirin
[i-1];
7478
mninex
(
fX
);
7479
Eval
(
nparx
,
fGin
,
f
,
fU
, 4); ++
fNfcn
;
7480
if
(
f
<=
aming
)
goto
L6
;
7481
// failure
7482
if
(kg == 1)
goto
L8
;
7483
kg = -1;
7484
++
nf
;
7485
fDirin
[i-1] *= -.4;
7486
if
(
nf
< 3)
goto
L4
;
7487
ns = 6;
7488
// success
7489
L6
:
7490
bestx
=
fX
[i-1];
7491
fDirin
[i-1] *= 3;
7492
aming
=
f
;
7493
fCstatu
=
"PROGRESS "
;
7494
kg = 1;
7495
++ns;
7496
if
(ns < 6)
goto
L4
;
7497
// local minimum found in ith direction
7498
L8
:
7499
fSIMPy
[i-1] =
aming
;
7500
if
(
aming
<
absmin
)
jl
= i;
7501
if
(
aming
<
absmin
)
absmin
=
aming
;
7502
fX
[i-1] =
bestx
;
7503
for
(k = 1; k <=
fNpar
; ++k) {
fP
[k + i*
fMaxpar
-
fMaxpar
-1] =
fX
[k-1]; }
7504
}
7505
jh
=
nparp1
;
7506
fAmin
=
fSIMPy
[
jl
-1];
7507
mnrazz
(
ynpp1
,
fPbar
,
fSIMPy
,
jh
,
jl
);
7508
for
(i = 1; i <=
fNpar
; ++i) {
fX
[i-1] =
fP
[i +
jl
*
fMaxpar
-
fMaxpar
-1]; }
7509
mninex
(
fX
);
7510
fCstatu
=
"PROGRESS "
;
7511
if
(
fISW
[4] >= 1)
mnprin
(5,
fAmin
);
7512
fEDM
=
fBigedm
;
7513
sig2
=
fEDM
;
7514
ncycl
= 0;
7515
// start main loop
7516
L50
:
7517
if
(
sig2
<
fEpsi
&&
fEDM
<
fEpsi
)
goto
L76
;
7518
sig2
=
fEDM
;
7519
if
(
fNfcn
-
npfn
>
fNfcnmx
)
goto
L78
;
7520
// calculate new point * by reflection
7521
for
(i = 1; i <=
fNpar
; ++i) {
7522
pb
= 0;
7523
for
(
j
= 1;
j
<=
nparp1
; ++
j
) {
pb
+=
wg
*
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1]; }
7524
fPbar
[i-1] =
pb
-
wg
*
fP
[i +
jh
*
fMaxpar
-
fMaxpar
-1];
7525
fPstar
[i-1] = (alpha + 1)*
fPbar
[i-1] - alpha*
fP
[i +
jh
*
fMaxpar
-
fMaxpar
-1];
7526
}
7527
mninex
(
fPstar
);
7528
Eval
(
nparx
,
fGin
,
ystar
,
fU
, 4); ++
fNfcn
;
7529
if
(
ystar
>=
fAmin
)
goto
L70
;
7530
// point * better than jl, calculate new point **
7531
for
(i = 1; i <=
fNpar
; ++i) {
7532
fPstst
[i-1] = gamma*
fPstar
[i-1] + (1 - gamma)*
fPbar
[i-1];
7533
}
7534
mninex
(
fPstst
);
7535
Eval
(
nparx
,
fGin
,
ystst
,
fU
, 4); ++
fNfcn
;
7536
// try a parabola through ph, pstar, pstst. min = prho
7537
y1
= (
ystar
-
fSIMPy
[
jh
-1])*rho2;
7538
y2
= (
ystst
-
fSIMPy
[
jh
-1])*rho1;
7539
rho = (rho2*
y1
- rho1*
y2
)*.5 / (
y1
-
y2
);
7540
if
(rho <
rhomin
)
goto
L66
;
7541
if
(rho >
rhomax
) rho =
rhomax
;
7542
for
(i = 1; i <=
fNpar
; ++i) {
7543
fPrho
[i-1] = rho*
fPbar
[i-1] + (1 - rho)*
fP
[i +
jh
*
fMaxpar
-
fMaxpar
-1];
7544
}
7545
mninex
(
fPrho
);
7546
Eval
(
nparx
,
fGin
,
yrho
,
fU
, 4); ++
fNfcn
;
7547
if
(
yrho
<
fSIMPy
[
jl
-1] &&
yrho
<
ystst
)
goto
L65
;
7548
if
(
ystst
<
fSIMPy
[
jl
-1])
goto
L67
;
7549
if
(
yrho
>
fSIMPy
[
jl
-1])
goto
L66
;
7550
// accept minimum point of parabola, PRHO
7551
L65
:
7552
mnrazz
(
yrho
,
fPrho
,
fSIMPy
,
jh
,
jl
);
7553
goto
L68
;
7554
L66
:
7555
if
(
ystst
<
fSIMPy
[
jl
-1])
goto
L67
;
7556
mnrazz
(
ystar
,
fPstar
,
fSIMPy
,
jh
,
jl
);
7557
goto
L68
;
7558
L67
:
7559
mnrazz
(
ystst
,
fPstst
,
fSIMPy
,
jh
,
jl
);
7560
L68
:
7561
++
ncycl
;
7562
if
(
fISW
[4] < 2)
goto
L50
;
7563
if
(
fISW
[4] >= 3 ||
ncycl
% 10 == 0) {
7564
mnprin
(5,
fAmin
);
7565
}
7566
goto
L50
;
7567
// point * is not as good as jl
7568
L70
:
7569
if
(
ystar
>=
fSIMPy
[
jh
-1])
goto
L73
;
7570
jhold
=
jh
;
7571
mnrazz
(
ystar
,
fPstar
,
fSIMPy
,
jh
,
jl
);
7572
if
(
jhold
!=
jh
)
goto
L50
;
7573
// calculate new point **
7574
L73
:
7575
for
(i = 1; i <=
fNpar
; ++i) {
7576
fPstst
[i-1] = beta*
fP
[i +
jh
*
fMaxpar
-
fMaxpar
-1] + (1 - beta)*
fPbar
[i-1];
7577
}
7578
mninex
(
fPstst
);
7579
Eval
(
nparx
,
fGin
,
ystst
,
fU
, 4); ++
fNfcn
;
7580
if
(
ystst
>
fSIMPy
[
jh
-1])
goto
L1;
7581
// point ** is better than jh
7582
if
(
ystst
<
fAmin
)
goto
L67
;
7583
mnrazz
(
ystst
,
fPstst
,
fSIMPy
,
jh
,
jl
);
7584
goto
L50
;
7585
// end main loop
7586
L76
:
7587
if
(
fISW
[4] >= 0) {
7588
Printf
(
" SIMPLEX MINIMIZATION HAS CONVERGED."
);
7589
}
7590
fISW
[3] = 1;
7591
goto
L80
;
7592
L78
:
7593
if
(
fISW
[4] >= 0) {
7594
Printf
(
" SIMPLEX TERMINATES WITHOUT CONVERGENCE."
);
7595
}
7596
fCstatu
=
"CALL LIMIT"
;
7597
fISW
[3] = -1;
7598
fISW
[0] = 1;
7599
L80
:
7600
for
(i = 1; i <=
fNpar
; ++i) {
7601
pb
= 0;
7602
for
(
j
= 1;
j
<=
nparp1
; ++
j
) {
pb
+=
wg
*
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1]; }
7603
fPbar
[i-1] =
pb
-
wg
*
fP
[i +
jh
*
fMaxpar
-
fMaxpar
-1];
7604
}
7605
mninex
(
fPbar
);
7606
Eval
(
nparx
,
fGin
,
ypbar
,
fU
, 4); ++
fNfcn
;
7607
if
(
ypbar
<
fAmin
)
mnrazz
(
ypbar
,
fPbar
,
fSIMPy
,
jh
,
jl
);
7608
mninex
(
fX
);
7609
if
(
fNfcnmx
+
npfn
-
fNfcn
<
fNpar
*3)
goto
L90
;
7610
if
(
fEDM
>
fEpsi
*2)
goto
L1;
7611
L90
:
7612
if
(
fISW
[4] >= 0)
mnprin
(5,
fAmin
);
7613
}
7614
7615
////////////////////////////////////////////////////////////////////////////////
7616
/// Returns concerning the current status of the minimization
7617
///
7618
/// User-called
7619
/// Namely, it returns:
7620
/// - FMIN: the best function value found so far
7621
/// - FEDM: the estimated vertical distance remaining to minimum
7622
/// - ERRDEF: the value of UP defining parameter uncertainties
7623
/// - NPARI: the number of currently variable parameters
7624
/// - NPARX: the highest (external) parameter number defined by user
7625
/// - ISTAT: a status integer indicating how good is the covariance
7626
/// matrix:
7627
/// - 0= not calculated at all
7628
/// - 1= approximation only, not accurate
7629
/// - 2= full matrix, but forced positive-definite
7630
/// - 3= full accurate covariance matrix
7631
7632
void
TMinuit::mnstat
(
Double_t
&
fmin
,
Double_t
&
fedm
,
Double_t
&
errdef
,
Int_t
&
npari
,
Int_t
&
nparx
,
Int_t
&
istat
)
7633
{
7634
fmin
=
fAmin
;
7635
fedm
=
fEDM
;
7636
errdef
=
fUp
;
7637
npari
=
fNpar
;
7638
nparx
=
fNu
;
7639
istat
=
fISW
[1];
7640
if
(
fEDM
==
fBigedm
)
fedm
=
fUp
;
7641
if
(
fAmin
==
fUndefi
) {
7642
fmin
= 0;
7643
fedm
=
fUp
;
7644
istat
= 0;
7645
}
7646
}
7647
7648
////////////////////////////////////////////////////////////////////////////////
7649
/// To find the machine precision
7650
///
7651
/// Compares its argument with the value 1.0, and returns
7652
/// the value .TRUE. if they are equal. To find EPSMAC
7653
/// safely by foiling the Fortran optimiser
7654
7655
void
TMinuit::mntiny
(
Double_t
epsp1
,
Double_t
&
epsbak
)
7656
{
7657
epsbak
=
epsp1
- 1;
7658
}
7659
7660
////////////////////////////////////////////////////////////////////////////////
7661
/// Returns .TRUE. if CFNAME contains unprintable characters
7662
///
7663
7664
Bool_t
TMinuit::mnunpt
(
TString
&
cfname
)
7665
{
7666
Int_t
i,
l
,
ic
;
7667
Bool_t
ret_val
;
7668
static
const
TString
cpt
=
" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890./;:[]$%*_!@#&+()"
;
7669
7670
ret_val
=
kFALSE
;
7671
l
=
strlen
((
const
char
*)
cfname
);
7672
for
(i = 1; i <=
l
; ++i) {
7673
for
(
ic
= 1;
ic
<= 80; ++
ic
) {
7674
if
(
cfname
[i-1] ==
cpt
[
ic
-1])
goto
L100
;
7675
}
7676
return
kTRUE
;
7677
L100
:
7678
;
7679
}
7680
return
ret_val
;
7681
}
7682
7683
////////////////////////////////////////////////////////////////////////////////
7684
/// Inverts a symmetric matrix
7685
///
7686
/// inverts a symmetric matrix. matrix is first scaled to
7687
/// have all ones on the diagonal (equivalent to change of units)
7688
/// but no pivoting is done since matrix is positive-definite.
7689
7690
void
TMinuit::mnvert
(
Double_t
*
a
,
Int_t
l
,
Int_t
,
Int_t
n
,
Int_t
&
ifail
)
7691
{
7692
/* System generated locals */
7693
Int_t
a_offset
;
7694
7695
/* Local variables */
7696
Double_t
si
;
7697
Int_t
i,
j
, k,
kp1
,
km1
;
7698
7699
/* Parameter adjustments */
7700
a_offset
=
l
+ 1;
7701
a
-=
a_offset
;
7702
7703
/* Function Body */
7704
ifail
= 0;
7705
if
(
n
< 1)
goto
L100
;
7706
if
(
n
>
fMaxint
)
goto
L100
;
7707
// scale matrix by sqrt of diag elements
7708
for
(i = 1; i <=
n
; ++i) {
7709
si
=
a
[i + i*
l
];
7710
if
(
si
<= 0)
goto
L100
;
7711
fVERTs
[i-1] = 1 /
TMath::Sqrt
(
si
);
7712
}
7713
for
(i = 1; i <=
n
; ++i) {
7714
for
(
j
= 1;
j
<=
n
; ++
j
) {
7715
a
[i +
j
*
l
] =
a
[i +
j
*
l
]*
fVERTs
[i-1]*
fVERTs
[
j
-1];
7716
}
7717
}
7718
// start main loop
7719
for
(i = 1; i <=
n
; ++i) {
7720
k = i;
7721
// preparation for elimination step1
7722
if
(
a
[k + k*
l
] != 0)
fVERTq
[k-1] = 1 /
a
[k + k*
l
];
7723
else
goto
L100
;
7724
fVERTpp
[k-1] = 1;
7725
a
[k + k*
l
] = 0;
7726
kp1
= k + 1;
7727
km1
= k - 1;
7728
if
(
km1
< 0)
goto
L100
;
7729
else
if
(
km1
== 0)
goto
L50
;
7730
else
goto
L40
;
7731
L40
:
7732
for
(
j
= 1;
j
<=
km1
; ++
j
) {
7733
fVERTpp
[
j
-1] =
a
[
j
+ k*
l
];
7734
fVERTq
[
j
-1] =
a
[
j
+ k*
l
]*
fVERTq
[k-1];
7735
a
[
j
+ k*
l
] = 0;
7736
}
7737
L50
:
7738
if
(k -
n
< 0)
goto
L51
;
7739
else
if
(k -
n
== 0)
goto
L60
;
7740
else
goto
L100
;
7741
L51
:
7742
for
(
j
=
kp1
;
j
<=
n
; ++
j
) {
7743
fVERTpp
[
j
-1] =
a
[k +
j
*
l
];
7744
fVERTq
[
j
-1] = -
a
[k +
j
*
l
]*
fVERTq
[k-1];
7745
a
[k +
j
*
l
] = 0;
7746
}
7747
// elimination proper
7748
L60
:
7749
for
(
j
= 1;
j
<=
n
; ++
j
) {
7750
for
(k =
j
; k <=
n
; ++k) {
a
[
j
+ k*
l
] +=
fVERTpp
[
j
-1]*
fVERTq
[k-1]; }
7751
}
7752
}
7753
// elements of left diagonal and unscaling
7754
for
(
j
= 1;
j
<=
n
; ++
j
) {
7755
for
(k = 1; k <=
j
; ++k) {
7756
a
[k +
j
*
l
] =
a
[k +
j
*
l
]*
fVERTs
[k-1]*
fVERTs
[
j
-1];
7757
a
[
j
+ k*
l
] =
a
[k +
j
*
l
];
7758
}
7759
}
7760
return
;
7761
// failure return
7762
L100
:
7763
ifail
= 1;
7764
}
7765
7766
////////////////////////////////////////////////////////////////////////////////
7767
/// Prints Warning messages
7768
///
7769
/// - If COPT='W', CMES is a WARning message from CORG.
7770
/// - If COPT='D', CMES is a DEBug message from CORG.
7771
/// - If SET WARnings is in effect (the default), this routine
7772
/// prints the warning message CMES coming from CORG.
7773
/// - If SET NOWarnings is in effect, the warning message is
7774
/// stored in a circular buffer of length kMAXMES.
7775
/// - If called with CORG=CMES='SHO', it prints the messages in
7776
/// the circular buffer, FIFO, and empties the buffer.
7777
7778
void
TMinuit::mnwarn
(
const
char
*
copt1
,
const
char
*
corg1
,
const
char
*
cmes1
)
7779
{
7780
TString
copt
=
copt1
;
7781
TString
corg
=
corg1
;
7782
TString
cmes
=
cmes1
;
7783
7784
const
Int_t
kMAXMES
= 10;
7785
Int_t
ityp
, i,
ic
, nm;
7786
TString
englsh
,
ctyp
;
7787
7788
if
(
corg
(0,3) !=
"SHO"
||
cmes
(0,3) !=
"SHO"
) {
7789
7790
// Either print warning or put in buffer
7791
if
(
copt
==
"W"
) {
7792
ityp
= 1;
7793
if
(
fLwarn
) {
7794
Printf
(
" MINUIT WARNING IN %s"
,(
const
char
*)
corg
);
7795
Printf
(
" ============== %s"
,(
const
char
*)
cmes
);
7796
return
;
7797
}
7798
}
else
{
7799
ityp
= 2;
7800
if
(
fLrepor
) {
7801
Printf
(
" MINUIT DEBUG FOR %s"
,(
const
char
*)
corg
);
7802
Printf
(
" =============== %s "
,(
const
char
*)
cmes
);
7803
return
;
7804
}
7805
}
7806
// if appropriate flag is off, fill circular buffer
7807
if
(
fNwrmes
[
ityp
-1] == 0)
fIcirc
[
ityp
-1] = 0;
7808
++
fNwrmes
[
ityp
-1];
7809
++
fIcirc
[
ityp
-1];
7810
if
(
fIcirc
[
ityp
-1] > 10)
fIcirc
[
ityp
-1] = 1;
7811
ic
=
fIcirc
[
ityp
-1];
7812
fOrigin
[
ic
] =
corg
;
7813
fWarmes
[
ic
] =
cmes
;
7814
fNfcwar
[
ic
] =
fNfcn
;
7815
return
;
7816
}
7817
7818
// 'SHO WARnings', ask if any suppressed mess in buffer
7819
if
(
copt
==
"W"
) {
7820
ityp
= 1;
7821
ctyp
=
"WARNING"
;
7822
}
else
{
7823
ityp
= 2;
7824
ctyp
=
"*DEBUG*"
;
7825
}
7826
if
(
fNwrmes
[
ityp
-1] > 0) {
7827
englsh
=
" WAS SUPPRESSED. "
;
7828
if
(
fNwrmes
[
ityp
-1] > 1)
englsh
=
"S WERE SUPPRESSED."
;
7829
Printf
(
" %5d MINUIT %s MESSAGE%s"
,
fNwrmes
[
ityp
-1]
7830
,(
const
char
*)
ctyp
,(
const
char
*)
englsh
);
7831
nm =
fNwrmes
[
ityp
-1];
7832
ic
= 0;
7833
if
(nm >
kMAXMES
) {
7834
Printf
(
" ONLY THE MOST RECENT 10 WILL BE LISTED BELOW."
);
7835
nm =
kMAXMES
;
7836
ic
=
fIcirc
[
ityp
-1];
7837
}
7838
Printf
(
" CALLS ORIGIN MESSAGE"
);
7839
for
(i = 1; i <= nm; ++i) {
7840
++
ic
;
7841
if
(
ic
>
kMAXMES
)
ic
= 1;
7842
Printf
(
" %6d %s %s"
,
fNfcwar
[
ic
],
fOrigin
[
ic
].Data(),
fWarmes
[
ic
].Data());
7843
}
7844
fNwrmes
[
ityp
-1] = 0;
7845
Printf
(
" "
);
7846
}
7847
}
7848
7849
////////////////////////////////////////////////////////////////////////////////
7850
/// Calculates the WERR, external parameter errors
7851
///
7852
/// and the global correlation coefficients, to be called
7853
/// whenever a new covariance matrix is available.
7854
7855
void
TMinuit::mnwerr
()
7856
{
7857
Double_t
denom
,
ba
,
al
,
dx
,
du1
,
du2
;
7858
Int_t
ndex
,
ierr
, i,
j
, k,
l
,
ndiag
,
k1
,
iin
;
7859
7860
// calculate external error if v exists
7861
if
(
fISW
[1] >= 1) {
7862
for
(
l
= 1;
l
<=
fNpar
; ++
l
) {
7863
ndex
=
l
*(
l
+ 1) / 2;
7864
dx
=
TMath::Sqrt
(
TMath::Abs
(
fVhmat
[
ndex
-1]*
fUp
));
7865
i =
fNexofi
[
l
-1];
7866
if
(
fNvarl
[i-1] > 1) {
7867
al
=
fAlim
[i-1];
7868
ba
=
fBlim
[i-1] -
al
;
7869
du1
=
al
+ 0.5*(
TMath::Sin
(
fX
[
l
-1] +
dx
) + 1)*
ba
-
fU
[i-1];
7870
du2
=
al
+ 0.5*(
TMath::Sin
(
fX
[
l
-1] -
dx
) + 1)*
ba
-
fU
[i-1];
7871
if
(
dx
> 1)
du1
=
ba
;
7872
dx
= 0.5*(
TMath::Abs
(
du1
) +
TMath::Abs
(
du2
));
7873
}
7874
fWerr
[
l
-1] =
dx
;
7875
}
7876
}
7877
// global correlation coefficients
7878
if
(
fISW
[1] >= 1) {
7879
for
(i = 1; i <=
fNpar
; ++i) {
7880
fGlobcc
[i-1] = 0;
7881
k1
= i*(i-1) / 2;
7882
for
(
j
= 1;
j
<= i; ++
j
) {
7883
k =
k1
+
j
;
7884
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1] =
fVhmat
[k-1];
7885
fP
[
j
+ i*
fMaxpar
-
fMaxpar
-1] =
fP
[i +
j
*
fMaxpar
-
fMaxpar
-1];
7886
}
7887
}
7888
mnvert
(
fP
,
fMaxint
,
fMaxint
,
fNpar
,
ierr
);
7889
if
(
ierr
== 0) {
7890
for
(
iin
= 1;
iin
<=
fNpar
; ++
iin
) {
7891
ndiag
=
iin
*(
iin
+ 1) / 2;
7892
denom
=
fP
[
iin
+
iin
*
fMaxpar
-
fMaxpar
-1]*
fVhmat
[
ndiag
-1];
7893
if
(
denom <= 1 && denom >
= 0)
fGlobcc
[
iin
-1] = 0;
7894
else
fGlobcc
[
iin
-1] =
TMath::Sqrt
(1 - 1 /
denom
);
7895
}
7896
}
7897
}
7898
}
d
#define d(i)
Definition
RSha256.hxx:102
b
#define b(i)
Definition
RSha256.hxx:100
f
#define f(i)
Definition
RSha256.hxx:104
c
#define c(i)
Definition
RSha256.hxx:101
a
#define a(i)
Definition
RSha256.hxx:99
s1
#define s1(x)
Definition
RSha256.hxx:91
h
#define h(i)
Definition
RSha256.hxx:106
e
#define e(i)
Definition
RSha256.hxx:103
Int_t
int Int_t
Signed integer 4 bytes (int)
Definition
RtypesCore.h:60
Longptr_t
long Longptr_t
Integer large enough to hold a pointer (platform-dependent)
Definition
RtypesCore.h:90
kFALSE
constexpr Bool_t kFALSE
Definition
RtypesCore.h:109
Double_t
double Double_t
Double 8 bytes.
Definition
RtypesCore.h:74
kTRUE
constexpr Bool_t kTRUE
Definition
RtypesCore.h:108
TClass.h
TRangeDynCast
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Definition
TCollection.h:359
TError.h
r
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
Defin