Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v31r0 (aeb156f0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
FuncMinimum.cpp
Go to the documentation of this file.
1 // Include files
2 
3 #include <cstdio>
4 #include <cstdlib>
5 // from Gaudi
7 // from GSL
8 #include "gsl/gsl_blas.h"
9 #include "gsl/gsl_errno.h"
10 #include "gsl/gsl_linalg.h"
11 #include "gsl/gsl_math.h"
12 #include "gsl/gsl_matrix.h"
13 #include "gsl/gsl_multimin.h"
14 #include "gsl/gsl_vector.h"
15 
16 // local
17 #include "FuncMinimum.h"
18 
19 // Handle CLHEP 2.0.x move to CLHEP namespace
20 namespace CLHEP {}
21 using namespace CLHEP;
22 
30 // ============================================================================
31 // ============================================================================
32 FuncMinimum::FuncMinimumMisc::FuncMinimumMisc( const FuncMinimum::GenFunc& func, FuncMinimum::Arg& arg )
33  : m_argum( arg ), m_eq( &func ), m_grad() {
34  const size_t N = func.dimensionality();
35 
36  for ( size_t i = 0; i < N; ++i ) {
37  Genfun::GENFUNCTION fun = func.partial( i );
38  m_grad.push_back( fun.clone() );
39  }
40 }
41 //=============================================================================
42 namespace {
43  using namespace Genfun;
45  double fun_gsl( const gsl_vector* v, void* params ) {
46  FuncMinimum::FuncMinimumMisc* local = static_cast<FuncMinimum::FuncMinimumMisc*>( params );
47  const FuncMinimum::GenFunc& eq = *( local->equation() );
48  Argument& arg = local->argument();
49 
50  for ( unsigned int i = 0; i < v->size; ++i ) { arg[i] = gsl_vector_get( v, i ); }
51 
52  return eq( arg );
53  }
54 
56  void dfun_gsl( const gsl_vector* v, void* params, gsl_vector* df ) {
57  FuncMinimum::FuncMinimumMisc* local = static_cast<FuncMinimum::FuncMinimumMisc*>( params );
58  const FuncMinimum::Gradient& grad = local->gradient();
59  Argument& arg = local->argument();
60 
61  for ( unsigned int i = 0; i < v->size; ++i ) { arg[i] = gsl_vector_get( v, i ); }
62 
63  for ( unsigned int i = 0; i < df->size; ++i ) {
64  Genfun::GENFUNCTION f = *( grad[i] );
65  gsl_vector_set( df, i, f( arg ) );
66  }
67  }
68 
71  void fdfun_gsl( const gsl_vector* v, void* params, double* f, gsl_vector* df ) {
72  *f = fun_gsl( v, params );
73  dfun_gsl( v, params, df );
74  }
75 } // namespace
76 
77 //=============================================================================
83 //=============================================================================
84 {
85  using namespace Genfun;
86 
87  gsl_vector_view vect = gsl_vector_view_array( &arg[0], arg.dimension() );
88  FuncMinimumMisc local( func, arg );
89 
90  gsl_multimin_function_fdf function;
91 
92  function.f = &fun_gsl;
93  function.df = &dfun_gsl;
94  function.fdf = &fdfun_gsl;
95  function.n = vect.vector.size;
96  function.params = (void*)&local;
97 
98  size_t iter = 0;
99  int status = 0;
100  const gsl_multimin_fdfminimizer_type* T = m_type;
101 
102  gsl_multimin_fdfminimizer* s;
103 
104  s = gsl_multimin_fdfminimizer_alloc( T, vect.vector.size );
105 
106  gsl_multimin_fdfminimizer_set( s, &function, &vect.vector, m_step_size, m_tol );
107 
108  for ( iter = 0; iter < m_max_iter; ++iter ) {
109  status = gsl_multimin_fdfminimizer_iterate( s );
110 
111  if ( status ) {
112  return Error( "Error from gsl_multimin_fdfminimizer_iterate '" + std::string( gsl_strerror( status ) ) + "'" );
113  }
114 
115  status = gsl_multimin_test_gradient( s->gradient, m_norm_gradient );
116 
117  if ( status != GSL_CONTINUE ) { break; }
118  }
119 
120  for ( unsigned int i = 0; i < vect.vector.size; ++i ) {
121  gsl_vector_set( &vect.vector, i, gsl_vector_get( s->x, i ) );
122  }
123 
124  if ( status == GSL_SUCCESS ) {
125  debug() << "We stopped in the method on the " << iter << " iteration (we have maximum " << m_max_iter
126  << " iterations)" << endmsg;
127 
128  msgStream() << "The Euclidean norm of gradient = " << gsl_blas_dnrm2( s->gradient )
129  << " by the absolute tolerance = " << m_norm_gradient << endmsg;
130  } else if ( status == GSL_CONTINUE && iter <= m_max_iter ) {
131  return Error( "Method finished with '" + std::string( gsl_strerror( status ) ) + "' error" );
132  } else {
133  return Error( "Method finished with '" + std::string( gsl_strerror( status ) ) + "' error" );
134  }
135 
136  gsl_multimin_fdfminimizer_free( s );
137 
138  if ( status ) { return Error( "Method finished with '" + std::string( gsl_strerror( status ) ) + "' error" ); }
139 
140  return StatusCode::SUCCESS;
141 }
142 
143 //=============================================================================
149  IFuncMinimum::Covariance& covar ) const
150 //=============================================================================
151 {
153  StatusCode sc = minimum( func, arg );
154 
155  if ( sc.isFailure() ) {
156  return Error( "MINIMUM IS NOT FOUND. StatusCode = '" + std::to_string( sc.getCode() ) + '\'', sc );
157  }
158  HepSymMatrix cov( arg.dimension(), 0 );
159  for ( unsigned int i = 0; i < arg.dimension(); ++i ) {
160  auto f = func.partial( i );
161  for ( unsigned int j = i; j < arg.dimension(); ++j ) {
162  auto fij = f.partial( j );
163  cov( i + 1, j + 1 ) = 0.5 * fij( arg );
164  }
165  }
166 
167  int inv;
168  covar = cov.inverse( inv );
169  return inv == 0 ? StatusCode::SUCCESS : Error( "Matrix of Error is not complete successful" );
170 }
171 
172 //=============================================================================
174 
175 {
177 
178  if ( sc.isFailure() ) { return Error( "Could not initialize base class GaudiTool", sc ); }
179 
181  if ( "conjugate_fr" == m_algType ) {
182  m_type = gsl_multimin_fdfminimizer_conjugate_fr;
183  debug() << "Minimization algorithm to be used: "
184  << "'gsl_multimin_fdfminimizer_conjugate_fr'" << endmsg;
185  } else if ( "conjugate_pr" == m_algType ) {
186  m_type = gsl_multimin_fdfminimizer_conjugate_pr;
187  debug() << "Minimization algorithm to be used: "
188  << "'gsl_multimin_fdfminimizer_conjugate_pr'" << endmsg;
189  } else if ( "vector_bfgs" == m_algType ) {
190  m_type = gsl_multimin_fdfminimizer_vector_bfgs;
191  debug() << "Minimization algorithm to be used: "
192  << "'gsl_multimin_fdfminimizer_vector_bfgs'" << endmsg;
193  } else if ( "steepest_descent" == m_algType ) {
194  m_type = gsl_multimin_fdfminimizer_steepest_descent;
195  debug() << "Minimization algorithm to be used: "
196  << "'gsl_multimin_fdfminimizer_steepest_descent'" << endmsg;
197  } else {
198  return Error( " Unknown algorithm type '" + m_algType + "'" );
199  }
200 
201  return StatusCode::SUCCESS;
202 }
203 //=============================================================================
204 
205 // Declaration of the Tool Factory
Genfun::Argument Arg
Argument of function "GenFunc" (.
Definition: IFuncMinimum.h:34
T to_string(T...args)
constexpr static const auto SUCCESS
Definition: StatusCode.h:85
const Arg & argument() const
Definition: FuncMinimum.h:52
const GenFunc * equation() const
Definition: FuncMinimum.h:54
bool isFailure() const
Definition: StatusCode.h:130
STL class.
#define DECLARE_COMPONENT(type)
Gaudi::Property< std::string > m_algType
Definition: EqSolver.h:79
int N
Definition: IOTest.py:99
Gaudi::Property< double > m_max_iter
Definition: EqSolver.h:81
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:50
Genfun::AbsFunction GenFunc
Function which we minimize (.
Definition: IFuncMinimum.h:32
CLHEP::HepSymMatrix Covariance
Covariance matrix (matrix of error) (.
Definition: IFuncMinimum.h:36
The simplest concrete implementation of IFuncMinimum interface.
Definition: FuncMinimum.h:24
const Gradient & gradient() const
Definition: FuncMinimum.h:55
StatusCode Error(const std::string &msg, const StatusCode st=StatusCode::FAILURE, const size_t mx=10) const
Print the error message and return with the given StatusCode.
Definition: GaudiTool.h:663
StatusCode minimum(const GenFunc &func, Arg &arg) const override
Find minimum of the function "GenFunc".
double fun(const std::vector< double > &x)
Definition: PFuncTest.cpp:26
string s
Definition: gaudirun.py:312
const gsl_multiroot_fdfsolver_type * m_type
Definition: EqSolver.h:84
CLHEP.
Definition: IEqSolver.h:13
code_t getCode() const
Retrieve value ("checks" the StatusCode)
Definition: StatusCode.h:137
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:192
StatusCode initialize() override
standard initialization method
Definition: GaudiTool.cpp:144
StatusCode initialize() override
Overriding initialize.