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
18namespace MEAL {
19
21
27
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
44
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
126template<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
142template<class T>
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
153template<class T>
154void 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
184template<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
196template<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
210template<class T>
212{
213 composite.clear();
214 model.clear();
215}
216
217template<class T>
218void MEAL::GroupRule<T>::initialize ()
219{
220 result = get_identity();
221
222 for (unsigned jgrad=0; jgrad<gradient.size(); jgrad++)
223 gradient[jgrad] = get_identity();
224}
225
226template<class T>
227void MEAL::GroupRule<T>::calculate (Result& retval,
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
Parameter policy for composite functions.
Definition Composite.h:20
Pure virtual base class of all functions.
Definition Function.h:49
virtual void parse(const std::string &text)
Parses the values of model parameters and fit flags from a string.
Definition Function_parse.C:16
static Function * factory(const std::string &text)
Construct a new Function instance from a string.
Definition Function_factory.C:41
virtual std::string get_name() const =0
Return the name of the class.
Abstract base class of closed, associative, binary operators.
Definition GroupRule.h:30
~GroupRule()
Destructor.
Definition GroupRule.h:46
void calculate(Result &result, std::vector< Result > *grad)
Return the result and its gradient.
Definition GroupRule.h:227
virtual void operate(Result &total, const Result &element)=0
Set the total equal to "total group operation element".
void add_model(T *model)
Add an element to the result.
Definition GroupRule.h:185
T * get_model(unsigned i)
Get the specified component.
Definition GroupRule.h:55
unsigned get_nmodel() const
Get the number of components.
Definition GroupRule.h:59
virtual const Result get_identity() const =0
Return the group identity.
GroupRule()
Default constructor.
Definition GroupRule.h:37
virtual const Result partial(const Result &element) const =0
Neighbouring terms stay in each other's partial derivatives.
void parse(const std::string &text)
Parse the values of model parameters and fit flags from a string.
Definition GroupRule.h:154
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
void remove_model(T *model)
Remove an element from the result.
Definition GroupRule.h:197
GroupRule & operator=(const GroupRule &meta)
Assignment operator.
Definition GroupRule.h:128
GroupRule(const GroupRule &meta)
Copy constructor.
Definition GroupRule.h:40
void clear()
Clear all models.
Definition GroupRule.h:211
Template combines a reference to a Component and its Projection.
Definition Projection.h:60
Namespace in which all modeling and calibration related code is declared.
Definition ExampleComplex2.h:16

Generated using doxygen 1.14.0