GroupRule.h
1 //-*-C++-*-
2 /***************************************************************************
3  *
4  * Copyright (C) 2004 by Willem van Straten
5  * Licensed under the Academic Free License version 2.1
6  *
7  ***************************************************************************/
8 
9 // psrchive/More/MEAL/MEAL/GroupRule.h
10 
11 #ifndef __GroupRule_H
12 #define __GroupRule_H
13 
14 #include "MEAL/ProjectGradient.h"
15 #include "MEAL/Composite.h"
16 #include "stringtok.h"
17 
18 namespace MEAL {
19 
21 
28  template<class T>
29  class GroupRule : public T
30  {
31 
32  public:
33 
34  typedef typename T::Result Result;
35 
37  GroupRule () : composite(this) { }
38 
40  GroupRule (const GroupRule& meta) : composite(this) { operator = (meta); }
41 
43  GroupRule& operator = (const GroupRule& meta);
44 
46  ~GroupRule () { }
47 
49  void add_model (T* model);
50 
52  void remove_model (T* model);
53 
55  T* get_model (unsigned i) { return model.at(i); }
56  const T* get_model (unsigned i) const { return model.at(i); }
57 
59  unsigned get_nmodel () const { return model.size(); }
60 
62  void clear ();
63 
64  // ///////////////////////////////////////////////////////////////////
65  //
66  // Function implementation
67  //
68  // ///////////////////////////////////////////////////////////////////
69 
71  void parse (const std::string& text);
72 
73  // ///////////////////////////////////////////////////////////////////
74  //
75  // Composite template implementation
76  //
77  // ///////////////////////////////////////////////////////////////////
78 
79  std::string class_name() const
80  { return "MEAL::GroupRule[" + this->get_name() + "]::"; }
81 
82  protected:
83 
84  // ///////////////////////////////////////////////////////////////////
85  //
86  // Function implementation
87  //
88  // ///////////////////////////////////////////////////////////////////
89 
91  void print_parameters (std::string& text, const std::string& sep) const;
92 
94  void calculate (Result& result, std::vector<Result>* grad);
95 
97  virtual const Result get_identity () const = 0;
98 
100  virtual void operate (Result& total, const Result& element) = 0;
101 
103  virtual const Result partial (const Result& element) const = 0;
104 
105  private:
106 
108  std::vector< Project<T> > model;
109 
111  Result result;
112 
114  std::vector<Result> gradient;
115 
117  void initialize ();
118 
120  Composite composite;
121 
122  };
123 }
124 
125 
126 template<class T>
129 {
130  if (this == &meta)
131  return *this;
132 
133  unsigned nmodel = meta.model.size();
134  for (unsigned imodel=0; imodel < nmodel; imodel++)
135  add_model (meta.model[imodel]);
136 
137  // name = meta.name;
138 
139  return *this;
140 }
141 
142 template<class T>
143 void MEAL::GroupRule<T>::print_parameters (std::string& text,
144  const std::string& sep) const
145 {
146  unsigned nmodel = model.size();
147  for (unsigned imodel=0; imodel < nmodel; imodel++) {
148  text += sep + model[imodel]->get_name ();
149  model[imodel]->print_parameters (text, sep + " ");
150  }
151 }
152 
153 template<class T>
154 void MEAL::GroupRule<T>::parse (const std::string& line)
155 {
156  if (model.size()) try
157  {
158  Function::parse(line);
159  return;
160  }
161  catch (Error& error) {
162  }
163 
164  // the key should be the name of a new class to be added
165  std::string temp = line;
166  std::string key = stringtok (temp, WHITESPACE);
167 
168  if (this->get_verbose())
169  std::cerr << class_name() << "::parse key '" << key << "'" << std::endl;
170 
171  Function* model = Function::factory (key);
172 
173  T* mtype = dynamic_cast<T*>(model);
174  if (!mtype)
175  throw Error (InvalidParam, class_name()+"parse",
176  model->get_name() + " is not of type " +
177  std::string(T::Name));
178 
179  add_model (mtype);
180 }
181 
182 
183 
184 template<class T>
186 {
187  model.push_back (Project<T>(x));
188  composite.map (model.back());
189 
190  FunctionPolicyTraits<T>::composite_component(this, x);
191 
192  if (this->get_verbose())
193  std::cerr << class_name() + "add_model size=" << model.size() << std::endl;
194 }
195 
196 template<class T>
198 {
199  for (unsigned i=0; i < model.size(); i++)
200  if (model[i].ptr() == x)
201  {
202  composite.unmap (model[i]);
203  model.erase( model.begin() + i );
204  return;
205  }
206 
207  throw Error (InvalidState, class_name() + "remove_model", "model not found");
208 }
209 
210 template<class T>
212 {
213  composite.clear();
214  model.clear();
215 }
216 
217 template<class T>
219 {
220  result = get_identity();
221 
222  for (unsigned jgrad=0; jgrad<gradient.size(); jgrad++)
223  gradient[jgrad] = get_identity();
224 }
225 
226 template<class T>
228  std::vector<Result>* grad)
229 {
230  unsigned nmodel = model.size();
231 
232  if (this->get_verbose())
233  std::cerr << class_name() + "calculate nmodel=" << nmodel << std::endl;
234 
235  // the result of each component
236  Result comp_result;
237 
238  // the gradient of each component
239  std::vector<Result> comp_gradient;
240 
241  // the pointer to the above array, if grad != 0
242  std::vector<Result>* comp_gradient_ptr = 0;
243 
244  unsigned total_nparam = 0;
245 
246  if (grad)
247  {
248  for (unsigned imodel=0; imodel < nmodel; imodel++)
249  total_nparam += model[imodel]->get_nparam();
250 
251  comp_gradient_ptr = &comp_gradient;
252  gradient.resize (total_nparam);
253  }
254 
255  // initialize the result and gradient attributes
256  initialize ();
257 
258  unsigned igradient = 0;
259 
260  for (unsigned imodel=0; imodel < nmodel; imodel++)
261  {
262  if (this->get_verbose())
263  std::cerr << class_name() + "calculate evaluate "
264  << model[imodel]->get_name() << std::endl;
265 
266  try {
267 
268  // evaluate the model and its gradient
269  comp_result = model[imodel]->evaluate (comp_gradient_ptr);
270 
271  if (this->get_verbose())
272  std::cerr << class_name() + "calculate "
273  << model[imodel]->get_name()
274  << " result=" << comp_result << std::endl;
275 
276  operate( result, comp_result );
277 
278  if (grad)
279  {
280  unsigned jgrad;
281  unsigned ngrad = comp_gradient_ptr->size();
282 
283  for (jgrad=0; jgrad<igradient; jgrad++)
284  operate( gradient[jgrad], partial(comp_result) );
285 
286  for (jgrad=0; jgrad<ngrad; jgrad++)
287  operate( gradient[igradient + jgrad], (*comp_gradient_ptr)[jgrad] );
288 
289  for (jgrad=igradient+ngrad; jgrad<gradient.size(); jgrad++)
290  operate( gradient[jgrad], partial(comp_result) );
291  }
292  }
293  catch (Error& error)
294  {
295  error += class_name() + "calculate";
296  throw error << " model=" << model[imodel]->get_name();
297  }
298 
299  if (grad)
300  {
301  if (model[imodel]->get_nparam() != comp_gradient.size())
302  throw Error (InvalidState, class_name() + "calculate",
303  "model[%d]=%s.get_nparam=%d != gradient.size=%d",
304  imodel, model[imodel]->get_name().c_str(),
305  model[imodel]->get_nparam(), comp_gradient.size());
306 
307  igradient += comp_gradient.size();
308  }
309  }
310 
311  retval = result;
312 
313  if (grad)
314  {
315  /* re-map the components of the gradient into the Composite space,
316  summing duplicates implements both the sum and product rules. */
317 
318  // sanity check, ensure that all elements have been set
319  if (igradient != total_nparam)
320  throw Error (InvalidState, (class_name() + "calculate").c_str(),
321  "after calculation igrad=%d != total_nparam=%d",
322  igradient, total_nparam);
323 
324  grad->resize (this->get_nparam());
325 
326  // this verion of ProjectGradient initializes the gradient vector to zero
327  ProjectGradient (model, gradient, *grad);
328  }
329 
330  if (this->get_verbose())
331  {
332  std::cerr << class_name() + "calculate result\n " << retval << std::endl;
333  if (grad)
334  {
335  std::cerr << class_name() + "calculate gradient" << std::endl;
336  for (unsigned i=0; i<grad->size(); i++)
337  std::cerr << " " << i << ":" << this->get_infit(i)
338  << "=" << (*grad)[i] << std::endl;
339  }
340  }
341 }
342 
343 #endif
344 
Abstract base class of closed, associative, binary operators.
Definition: GroupRule.h:34
void parse(const std::string &text)
Parse the values of model parameters and fit flags from a string.
Definition: GroupRule.h:154
void remove_model(T *model)
Remove an element from the result.
Definition: GroupRule.h:197
Parameter policy for composite functions.
Definition: Composite.h:25
virtual void operate(Result &total, const Result &element)=0
Set the total equal to "total group operation element".
void calculate(Result &result, std::vector< Result > *grad)
Return the result and its gradient.
Definition: GroupRule.h:227
Namespace in which all modeling and calibration related code is declared.
Definition: ExampleComplex2.h:16
void add_model(T *model)
Add an element to the result.
Definition: GroupRule.h:185
virtual const Result get_identity() const =0
Return the group identity.
T * get_model(unsigned i)
Get the specified component.
Definition: GroupRule.h:65
virtual std::string get_name() const =0
Return the name of the class.
Pure virtual base class of all functions.
Definition: Function.h:49
unsigned get_nmodel() const
Get the number of components.
Definition: GroupRule.h:69
~GroupRule()
Destructor.
Definition: GroupRule.h:56
void print_parameters(std::string &text, const std::string &sep) const
Prints the values of model parameters and fit flags to a string.
Definition: GroupRule.h:143
virtual const Result partial(const Result &element) const =0
Neighbouring terms stay in each other's partial derivatives.
GroupRule()
Default constructor.
Definition: GroupRule.h:47
void clear()
Clear all models.
Definition: GroupRule.h:211
GroupRule & operator=(const GroupRule &meta)
Assignment operator.
Definition: GroupRule.h:128
std::complex< double > Result
The return type of the evaluate method.
Definition: Evaluable.h:40

Generated using doxygen 1.8.17