1 // @(#)root/minuit2:$Id$
2 // Authors: M. Winkler, F. James, L. Moneta, A. Zsenei   2003-2005
3 
4 /**********************************************************************
5  *                                                                    *
6  * Copyright (c) 2005 LCG ROOT Math team,  CERN/PH-SFT                *
7  *                                                                    *
8  **********************************************************************/
9 
10 #ifndef ROOT_Minuit2_FunctionMinimum
11 #define ROOT_Minuit2_FunctionMinimum
12 
13 #include "Minuit2/MinimumSeed.h"
14 #include "Minuit2/MinimumState.h"
15 #include "Minuit2/MnUserParameterState.h"
16 #include "Minuit2/MnUserTransformation.h"
17 
18 #include <vector>
19 #include <memory>
20 
21 #ifdef G__DICTIONARY
22 typedef ROOT::Minuit2::MinimumState MinimumState;
23 #endif
24 
25 namespace ROOT {
26 
27 namespace Minuit2 {
28 
29 //______________________________________________________________________________________________
30 /**
31     class holding the full result of the minimization;
32     both internal and external (MnUserParameterState) representation available
33     for the parameters at the Minimum
34  */
35 
36 class FunctionMinimum {
37 
38 public:
39    enum Status {
40       MnValid,
41       MnReachedCallLimit,
42       MnAboveMaxEdm,
43    };
44 
45 public:
46    /// Constructor from only MinimumSeed. Minimum is only from seed result not the full minimization
FunctionMinimum(const MinimumSeed & seed,double up)47    FunctionMinimum(const MinimumSeed &seed, double up)
48       : FunctionMinimum(seed,
49                         std::vector<MinimumState>(1, MinimumState(seed.Parameters(), seed.Error(), seed.Gradient(),
50                                                                   seed.Parameters().Fval(), seed.NFcn())),
51                         up)
52    {
53    }
54 
55    /// Constructor at the end of a minimization from seed and vector of states
56    FunctionMinimum(const MinimumSeed &seed, const std::vector<MinimumState> &states, double up, Status status = MnValid)
57       : fPtr{new Data{seed, states, up, status == MnAboveMaxEdm, status == MnReachedCallLimit, {}}}
58    {
59    }
60 
61    /// add latest minimization state (for example add Hesse result after Migrad)
62    void Add(const MinimumState &state, Status status = MnValid)
63    {
64       fPtr->fStates.push_back(state);
65       // LM : update also the user state
66       fPtr->fUserState = MnUserParameterState(State(), Up(), Seed().Trafo());
67       // reset maxedm flag. If new state has edm over max other method must be used
68       fPtr->fAboveMaxEdm = status == MnAboveMaxEdm;
69       fPtr->fReachedCallLimit = status == MnReachedCallLimit;
70    }
71 
Seed()72    const MinimumSeed &Seed() const { return fPtr->fSeed; }
States()73    const std::vector<MinimumState> &States() const { return fPtr->fStates; }
74 
75    // user representation of state at Minimum
UserState()76    const MnUserParameterState &UserState() const
77    {
78       if (!fPtr->fUserState.IsValid())
79          fPtr->fUserState = MnUserParameterState(State(), Up(), Seed().Trafo());
80       return fPtr->fUserState;
81    }
UserParameters()82    const MnUserParameters &UserParameters() const { return UserState().Parameters(); }
UserCovariance()83    const MnUserCovariance &UserCovariance() const { return UserState().Covariance(); }
84 
85    // forward interface of last state
State()86    const MinimumState &State() const { return States().back(); }
Parameters()87    const MinimumParameters &Parameters() const { return States().back().Parameters(); }
Error()88    const MinimumError &Error() const { return States().back().Error(); }
Grad()89    const FunctionGradient &Grad() const { return States().back().Gradient(); }
Fval()90    double Fval() const { return States().back().Fval(); }
Edm()91    double Edm() const { return States().back().Edm(); }
NFcn()92    int NFcn() const { return States().back().NFcn(); }
93 
Up()94    double Up() const { return fPtr->fErrorDef; }
IsValid()95    bool IsValid() const { return State().IsValid() && !IsAboveMaxEdm() && !HasReachedCallLimit(); }
HasValidParameters()96    bool HasValidParameters() const { return State().Parameters().IsValid(); }
HasValidCovariance()97    bool HasValidCovariance() const { return State().Error().IsValid(); }
HasAccurateCovar()98    bool HasAccurateCovar() const { return State().Error().IsAccurate(); }
HasPosDefCovar()99    bool HasPosDefCovar() const { return State().Error().IsPosDef(); }
HasMadePosDefCovar()100    bool HasMadePosDefCovar() const { return State().Error().IsMadePosDef(); }
HesseFailed()101    bool HesseFailed() const { return State().Error().HesseFailed(); }
HasCovariance()102    bool HasCovariance() const { return State().Error().IsAvailable(); }
IsAboveMaxEdm()103    bool IsAboveMaxEdm() const { return fPtr->fAboveMaxEdm; }
HasReachedCallLimit()104    bool HasReachedCallLimit() const { return fPtr->fReachedCallLimit; }
105 
SetErrorDef(double up)106    void SetErrorDef(double up)
107    {
108       fPtr->fErrorDef = up;
109       // update user state for new valeu of up (scaling of errors)
110       fPtr->fUserState = MnUserParameterState(State(), up, Seed().Trafo());
111    }
112 
113 private:
114    struct Data {
115       MinimumSeed fSeed;
116       std::vector<MinimumState> fStates;
117       double fErrorDef;
118       bool fAboveMaxEdm;
119       bool fReachedCallLimit;
120       mutable MnUserParameterState fUserState;
121    };
122 
123    std::shared_ptr<Data> fPtr;
124 };
125 
126 } // namespace Minuit2
127 
128 } // namespace ROOT
129 
130 #endif // ROOT_Minuit2_FunctionMinimum
131