11 #ifndef __MEAL_ChainRule_H
12 #define __MEAL_ChainRule_H
14 #include "MEAL/ProjectGradient.h"
15 #include "MEAL/Composite.h"
16 #include "MEAL/Scalar.h"
21 class ConstrainedParameter {
24 ConstrainedParameter (
unsigned iparam,
bool infit, Scalar* func)
63 typedef typename T::Result Result;
76 T* get_model () {
return model; }
80 bool has_constraint (
unsigned iparam);
81 Scalar* get_constraint (
unsigned iparam);
95 void calculate (Result& result, std::vector<Result>* gradient);
117 std::vector<unsigned>& imap,
118 std::vector< std::vector<double> >& covar);
125 return "ChainRule<" + std::string(T::Name)+
">";
135 set_model (rule.
model);
137 for (
unsigned ic=0; ic < rule.
constraints.size(); ic++)
148 for (
unsigned ifunc=0; ifunc<constraints.size(); ifunc++)
149 if (constraints[ifunc].parameter == iparam)
151 constraints[ifunc].
index = ifunc;
152 return &constraints[ifunc];
161 if (this->get_verbose())
162 std::cerr << get_name() +
"::set_constraint iparam=" << iparam
171 if (this->get_verbose())
172 std::cerr << get_name() +
"::set_constraint"
173 " remove param=" << iparam << std::endl;
175 composite.unmap (existing->scalar);
178 model->set_infit (iparam, existing->previously_infit);
180 constraints.erase (constraints.begin() + existing->index);
189 infit = model->get_infit (iparam);
193 if (this->get_verbose())
194 std::cerr << get_name() +
"::set_constraint"
195 " add param=" << iparam << std::endl;
197 composite.map (constraints.back().scalar);
200 model->set_infit (iparam,
false);
208 throw Error (InvalidParam,
"MEAL::ChainRule<T>::get_constraint",
209 "iparam=%u is not constrained", iparam);
211 return existing->scalar;
217 return find_constraint (iparam) != 0;
228 if (this->get_verbose())
229 std::cerr << get_name() +
"::set_model"
230 " unmap old model" << std::endl;
231 composite.unmap (model);
236 if (this->get_verbose())
237 std::cerr << get_name() +
"::set_model"
238 " map new model" << std::endl;
240 composite.map (model);
242 for (
unsigned ifunc=0; ifunc<constraints.size(); ifunc++)
244 unsigned iparam = constraints[ifunc].parameter;
245 constraints[ifunc].previously_infit = model->get_infit (iparam);
246 model->set_infit (iparam,
false);
252 std::vector<Result>* grad)
255 throw Error (InvalidState, get_name() +
"::calculate",
"no model");
257 if (this->get_verbose())
258 std::cerr << get_name() +
"::calculate" << std::endl;
260 for (
unsigned ifunc=0; ifunc<constraints.size(); ifunc++)
263 std::cerr << get_name() +
"::calculate constraint on iparam="
264 << constraints[ifunc].parameter <<
" by "
265 << constraints[ifunc].scalar->get_name () << std::endl;
267 std::vector<double>* fgrad = 0;
270 fgrad = &(constraints[ifunc].gradient);
272 model->set_param (constraints[ifunc].parameter,
273 constraints[ifunc].scalar->evaluate(fgrad));
276 std::vector<Result> model_grad;
277 std::vector<Result>* model_grad_ptr = 0;
279 model_grad_ptr = & model_grad;
281 result = model->evaluate (model_grad_ptr);
285 unsigned ngrad = this->get_nparam();
286 grad->resize (ngrad);
289 for (igrad=0; igrad<ngrad; igrad++)
290 (*grad)[igrad] = 0.0;
293 ProjectGradient (model, model_grad, *(grad));
296 std::vector<Result> fgrad;
298 for (
unsigned ifunc=0; ifunc<constraints.size(); ifunc++)
300 unsigned iparam = constraints[ifunc].parameter;
302 ngrad = constraints[ifunc].gradient.size();
303 fgrad.resize (ngrad);
306 for (igrad=0; igrad<ngrad; igrad++)
307 fgrad[igrad] = model_grad[iparam] * constraints[ifunc].gradient[igrad];
309 ProjectGradient (constraints[ifunc].scalar, fgrad, *(grad));
313 if (this->get_verbose())
315 std::cerr << get_name() +
"::calculate result\n"
316 " " << result << std::endl;
319 std::cerr << get_name() +
"::calculate gradient\n";
320 for (
unsigned i=0; i<grad->size(); i++)
321 std::cerr <<
" " << i <<
":" << this->get_infit(i) <<
"="
322 << (*grad)[i] << std::endl;