File: WrappedParamFunction.h

package info (click to toggle)
bornagain 23.0-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 103,956 kB
  • sloc: cpp: 423,131; python: 40,997; javascript: 11,167; awk: 630; sh: 356; ruby: 173; xml: 130; makefile: 45; ansic: 24
file content (304 lines) | stat: -rw-r--r-- 9,681 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
// @(#)root/mathcore:$Id$
// Author: L. Moneta Thu Nov 23 10:38:32 2006

/**********************************************************************
 *                                                                    *
 * Copyright (c) 2006  LCG ROOT Math Team, CERN/PH-SFT                *
 *                                                                    *
 *                                                                    *
 **********************************************************************/

// Header file for class WrappedParamFunction

#ifndef ROOT_Math_WrappedParamFunction
#define ROOT_Math_WrappedParamFunction

#include "Math/IParamFunction.h"

//#include <iostream>
//#include <iterator>

#include <vector>


namespace ROOT {

   namespace Math {


typedef double( * FreeParamMultiFunctionPtr ) (const double *, const double * );

/**
   WrappedParamFunction class to wrap any multi-dimensional function pbject
   implementing the operator()(const double * x, const double * p)
   in an interface-like IParamFunction with a vector storing and caching internally the
   parameter values

   @ingroup  ParamFunc

*/
template< typename FuncPtr =  FreeParamMultiFunctionPtr   >
class WrappedParamFunction : public IParamMultiFunction {

public:

   /**
      Constructor a wrapped function from a pointer to a callable object, the function dimension and number of parameters
      which are set to zero by default
   */
   WrappedParamFunction (FuncPtr  func, unsigned int dim = 1, unsigned int npar = 0, double * par = 0) :
      fFunc(func),
      fDim(dim),
      fParams(std::vector<double>(npar) )
   {
      if (par != 0) std::copy(par,par+npar,fParams.begin() );
   }

//    /**
//       Constructor a wrapped function from a non-const pointer to a callable object, the function dimension and number of parameters
//       which are set to zero by default
//       This constructor is needed in the case FuncPtr is a std::unique_ptr which has a copy ctor taking non const objects
//    */
//    WrappedParamFunction (FuncPtr & func, unsigned int dim = 1, unsigned int npar = 0, double * par = 0) :
//       fFunc(func),
//       fDim(dim),
//       fParams(std::vector<double>(npar) )
//    {
//       if (par != 0) std::copy(par,par+npar,fParams.begin() );
//    }

   /**
      Constructor a wrapped function from a pointer to a callable object, the function dimension and an iterator specifying begin and end
      of parameters
   */
   template<class Iterator>
   WrappedParamFunction (FuncPtr func, unsigned int dim, Iterator begin, Iterator end) :
      fFunc(func),
      fDim(dim),
      fParams(std::vector<double>(begin,end) )
   {}

//    /**
//       Constructor a wrapped function from a non - const pointer to a callable object, the function dimension and an iterator specifying begin and end of parameters.
//       This constructor is needed in the case FuncPtr is a std::unique_ptr which has a copy ctor taking non const objects
//    */
//    template<class Iterator>
//    WrappedParamFunction (FuncPtr func, unsigned int dim, Iterator begin, Iterator end) :
//       fFunc(func),
//       fDim(dim),
//       fParams(std::vector<double>(begin,end) )
//    {}

   /// clone the function
   IMultiGenFunction * Clone() const {
      return new WrappedParamFunction(fFunc, fDim, fParams.begin(), fParams.end());
   }

   const double * Parameters() const {
      return fParams.empty() ? nullptr : &fParams.front();
   }

   void SetParameters(const double * p)  {
      std::copy(p, p+NPar(), fParams.begin() );
   }

   unsigned int NPar() const { return fParams.size(); }

   unsigned int NDim() const { return fDim; }


private:

   /// evaluate the function given values and parameters (requested interface)
   double DoEvalPar(const double * x, const double * p) const {
      return (*fFunc)( x, p );
   }


   FuncPtr fFunc;
   unsigned int fDim;
   std::vector<double> fParams;



};


typedef double( * FreeMultiFunctionPtr ) (const double *);

/**
   WrappedParamGenFunction class to wrap any multi-dimensional function
   implementing the operator()(const double * )
   in an interface-like IParamFunction, by fixing some of the variables and define them as
   parameters.
   i.e. transform any multi-dim function in a parametric function

   @ingroup  ParamFunc

*/
template< typename FuncPtr =  FreeMultiFunctionPtr   >
class WrappedParamFunctionGen : public IParamMultiFunction {

public:

   /**
      Constructor a wrapped function from a pointer to a generic callable object implemention operator()(const double *), the new function dimension, the number of parameters (number of fixed variables) and an array specifying the index of the fixed variables which becames
      parameters in the new API
   */

   WrappedParamFunctionGen (const FuncPtr & func, unsigned int dim, unsigned int npar, const double * par, const unsigned int * idx) :
      fFunc(func),
      fDim(dim),
      fParams(std::vector<double>(par,par+npar) ),
      fParIndices(std::vector<unsigned int>(idx, idx + npar) ),
      fX(std::vector<double>(npar+dim) )  // cached vector
   {
      DoInit();
   }

   /**
      Constructor as before but taking now a non - const pointer to a callable object.
      This constructor is needed in the case FuncPtr is a std::unique_ptr which has a copy ctor taking non const objects
   */
   WrappedParamFunctionGen (FuncPtr & func, unsigned int dim, unsigned int npar, const double * par, const unsigned int * idx) :
      fFunc(func),
      fDim(dim),
      fParams(std::vector<double>(par,par+npar) ),
      fParIndices(std::vector<unsigned int>(idx, idx + npar) ),
      fX(std::vector<double>(npar+dim) ) // cached vector
   {
      DoInit();
   }

   /// clone the function
   IMultiGenFunction * Clone() const {
      return new WrappedParamFunctionGen(fFunc, fDim, fParams.size(), fParams.empty() ? nullptr : &fParams.front(), fParIndices.empty() ? nullptr : &fParIndices.front());
   }

private:
   // copy ctor
   WrappedParamFunctionGen(const  WrappedParamFunctionGen &);   // not implemented
   WrappedParamFunctionGen & operator=(const  WrappedParamFunctionGen &); // not implemented

public:

   const double * Parameters() const {
      return fParams.empty() ? nullptr : &fParams.front();
   }

   void SetParameters(const double * p)  {
      unsigned int npar = NPar();
      std::copy(p, p+ npar, fParams.begin() );
      SetParValues(npar, p);
   }

   unsigned int NPar() const { return fParams.size(); }

   unsigned int NDim() const { return fDim; }

//    // re-implement this since is more efficient
//    double operator() (const double * x, const double * p) {
//       unsigned int n = fX.size();
//       unsigned int npar = fParams.size();
//       unsigned j = 0;
//       return (*fFunc)( fX);
//    }

private:

   /// evaluate the function (re-implement for being more efficient)
   double DoEval(const double * x) const {

//       std::cout << this << fDim << " x : ";
//       std::ostream_iterator<double> oix(std::cout," ,  ");
//       std::copy(x, x+fDim, oix);
//       std::cout << std::endl;
//       std::cout << "npar " << npar << std::endl;
//       std::cout <<  fVarIndices.size() << std::endl;
//       assert ( fVarIndices.size() == fDim);  // otherwise something is wrong

      for (unsigned int i = 0; i < fDim; ++i) {
         unsigned int j = fVarIndices[i];
         assert ( j  < NPar() + fDim);
         fX[ j ] = x[i];
      }
//       std::cout << "X : (";
//       std::ostream_iterator<double> oi(std::cout," ,  ");
//       std::copy(fX.begin(), fX.end(), oi);
//       std::cout << std::endl;

      return (*fFunc)( fX.empty() ? nullptr : &fX.front() );
   }


   /**
       implement the required IParamFunction interface
   */
   double DoEvalPar(const double * x, const double * p ) const {
      SetParValues(NPar(), p);
      return DoEval(x);
   }


   void DoInit() {
      // calculate variable indices and set in X the parameter values
      fVarIndices.reserve(fDim);
      unsigned int npar = NPar();
      for (unsigned int i = 0; i < npar + fDim; ++i) {
         bool isVar = true;
         for (unsigned int j = 0; j < npar; ++j) {
            if (fParIndices[j] == i) {
               isVar = false;
               break;
            }
         }
         if (isVar) fVarIndices.push_back(i);
      }
      assert ( fVarIndices.size() == fDim);  // otherwise something is wrong

//       std::cout << "n variables " << fVarIndices.size() << std::endl;
//       std::ostream_iterator<int> oi(std::cout,"  ");
//       std::copy(fVarIndices.begin(), fVarIndices.end(), oi);
//       std::cout << std::endl;
//       assert( fVarIndices.size() == fDim);
//       std::cout << this << std::endl;

      // set parameter values in fX
      SetParValues(npar, fParams.empty() ? nullptr : &fParams.front());
      for (unsigned int i = 0; i < npar; ++i) {
         unsigned int j = fParIndices[i];
         assert ( j  < npar + fDim);
         fX[j] = fParams[i];
      }

   }

   // set the parameter values in the cached fX vector
   // makme const because it might be called from const methods
   void SetParValues(unsigned int npar, const double * p) const {
      for (unsigned int i = 0; i < npar; ++i) {
         unsigned int j = fParIndices[i];
         assert ( j  < npar + fDim);
         fX[j] = p[i];
      }
   }


   mutable FuncPtr fFunc;
   unsigned int fDim;
   std::vector<double> fParams;
   std::vector<unsigned int> fVarIndices;
   std::vector<unsigned int> fParIndices;
   mutable std::vector<double> fX;



};


   } // end namespace Math

} // end namespace ROOT


#endif /* ROOT_Math_WrappedParamFunction */