MUQ  0.4.3
WorkPiece.cpp
Go to the documentation of this file.
2 
5 
6 // define the muq namespace
7 using namespace muq::Modeling;
8 
9 // Create a muq::Modeling::WorkPiece with no fixed number of inputs and outputs and variable input/output types.
11  numInputs(-1), // the number of inputs is unfixed
12  numOutputs(-1), // the number of ouputs is unfixed
13  id(CreateID()), // the unique id of this WorkPiece
14  name("")
15 {}
16 
17 // Create a muq::Modeling::WorkPiece with either a fixed number of inputs or outputs and variable input/output types.
18 WorkPiece::WorkPiece(int const num, WorkPiece::Fix const fix) :
19  numInputs(fix==WorkPiece::Fix::Inputs? num : -1), // possibly fix the number of inputs
20  numOutputs(fix==WorkPiece::Fix::Outputs? num : -1), // possibly fix the number of outputs
21  id(CreateID()), // the unique id of this WorkPiece
22  name("")
23 {}
24 
25 // Create a muq::Modeling::WorkPiece with either a fixed number of inputs or outputs and variable input/output types.
26 WorkPiece::WorkPiece(int const numIns, int const numOuts) :
27  numInputs(numIns), // fix the number of inputs
28  numOutputs(numOuts), // fix the number of outputs
29  id(CreateID()), // the unique id of this WorkPiece
30  name("")
31 {}
32 
33 // Create a muq::Modeling::WorkPiece with either a fixed number of inputs with specified types or a fixed number of outputs with specified types
34 WorkPiece::WorkPiece(std::vector<std::string> const& types, WorkPiece::Fix const fix) :
35  numInputs(fix==WorkPiece::Fix::Inputs? types.size() : -1), // possibly fix the number of inputs
36  numOutputs(fix==WorkPiece::Fix::Outputs? types.size() : -1), // possibly fix the number of outputs
37  inputTypes(fix==WorkPiece::Fix::Inputs? Types(types) : std::map<unsigned int, std::string>()), // possibly fix the input types
38  outputTypes(fix==WorkPiece::Fix::Outputs? Types(types) : std::map<unsigned int, std::string>()), // possibly fix the output types
39  id(CreateID()), // the unique id of this WorkPiece
40  name("")
41 {}
42 
43 // Create a muq::Modeling::WorkPiece where either some of the inputs have specified types or some of the outputs have specified types
44 WorkPiece::WorkPiece(std::map<unsigned int, std::string> const& types, WorkPiece::Fix const fix) :
45  numInputs(-1), // the number of inputs is unfixed
46  numOutputs(-1), // the number of ouputs is unfixed
47  inputTypes(fix==WorkPiece::Fix::Inputs? types : std::map<unsigned int, std::string>()), // possibly fix the input types
48  outputTypes(fix==WorkPiece::Fix::Outputs? types : std::map<unsigned int, std::string>()), // possibly fix the output types
49  id(CreateID()), // the unique id of this WorkPiece
50  name("")
51 {}
52 
53 // Create a muq::Modeling::WorkPiece where either some of the inputs have specified types or some of the outputs have specified types and either the number of inputs or the number of outputs is fixed
54 WorkPiece::WorkPiece(std::map<unsigned int, std::string> const& types, int const num, WorkPiece::Fix const fixTypes, WorkPiece::Fix const fixNum) :
55  numInputs(fixNum==WorkPiece::Fix::Inputs? num : -1), // possibly fix the number of inputs
56  numOutputs(fixNum==WorkPiece::Fix::Outputs? num : -1), // possibly fix the number of outputs
57  inputTypes(fixTypes==WorkPiece::Fix::Inputs? types : std::map<unsigned int, std::string>()), // possibly fix the input types
58  outputTypes(fixTypes==WorkPiece::Fix::Outputs? types : std::map<unsigned int, std::string>()), // possibly fix the output types
59  id(CreateID()), // the unique id of this WorkPiece
60  name("")
61 {}
62 
63 // Create a muq::Modeling::WorkPiece with a fixed number of inputs with specified types and a fixed number of outputs (of uknown type)
64 WorkPiece::WorkPiece(std::vector<std::string> const& types, int const num) :
65  numInputs(types.size()), // fix the number of inputs
66  numOutputs(num), // fix the number of outputs
67  inputTypes(Types(types)), // fix the input types
68  id(CreateID()), // the unique id of this WorkPiece
69  name("")
70 {}
71 
72 // Create a muq::Modeling::WorkPiece with a fixed number of outputs with specified types and a fixed number of inputs (of uknown type)
73 WorkPiece::WorkPiece(int const num, std::vector<std::string> const& types) :
74  numInputs(num), // fix the number of inputs
75  numOutputs(types.size()), // fix the number of outputs
76  outputTypes(Types(types)), // fix the input types
77  id(CreateID()), // the unique id of this WorkPiece
78  name("")
79 {}
80 
81 // Create a muq::Modeling::WorkPiece where some of the inputs are known and we know the input and output numbers
82 WorkPiece::WorkPiece(std::map<unsigned int, std::string> const& inTypes, int const numIns, int const numOuts) :
83  numInputs(numIns), // fix the number inputs
84  numOutputs(numOuts), // fix the number of outputs
85  inputTypes(inTypes), // fix the input types
86  id(CreateID()), // the unique id of this WorkPiece
87  name("")
88 {}
89 
90 // Create a muq::Modeling::WorkPiece where some of the outputs are known and we know the input and output numbers
91 WorkPiece::WorkPiece(int const numIns, std::map<unsigned int, std::string> const& outTypes, int const numOuts) :
92  numInputs(numIns), // fix the number inputs
93  numOutputs(numOuts), // fix the number of outputs
94  outputTypes(outTypes), // fix the output types
95  id(CreateID()), // the unique id of this WorkPiece
96  name("")
97 {}
98 
99 // Create a muq::Modeling::WorkPiece with a fixed number of inputs and outputs with specified types
100 WorkPiece::WorkPiece(std::vector<std::string> const& inTypes, std::vector<std::string> const& outTypes) :
101  numInputs(inTypes.size()), // fix the number of inputs
102  numOutputs(outTypes.size()), // fix the number of outputs
103  inputTypes(Types(inTypes)), // fix the input types
104  outputTypes(Types(outTypes)), // fix the output types
105  id(CreateID()), // the unique id of this WorkPiece
106  name("")
107 {}
108 
109 // Create a muq::Mdoeling::WorkPiece where some of the inputs and all of the outputs have specified types
110 WorkPiece::WorkPiece(std::map<unsigned int, std::string> const& inTypes, std::vector<std::string> const& outTypes) :
111  numInputs(-1), // the number of inputs is unfixed
112  numOutputs(outTypes.size()), // fix the number of outputs
113  inputTypes(inTypes), // fix the inputs types
114  outputTypes(Types(outTypes)), // fix the output types
115  id(CreateID()), // the unique id of this WorkPiece
116  name("")
117 {}
118 
119 // Create a muq::Modeling::WorkPiece where some of the inputs are known with a known number of inputs and all of the outputs have specified types
120 WorkPiece::WorkPiece(std::map<unsigned int, std::string> const& inTypes, int const num, std::vector<std::string> const& outTypes) :
121  numInputs(num), // fix the number of inputs
122  numOutputs(outTypes.size()), // fix the number of outputs
123  inputTypes(inTypes), // fix the inputs types
124  outputTypes(Types(outTypes)), // fix the output types
125  id(CreateID()), // the unique id of this WorkPiece
126  name("")
127 {}
128 
129 // Create a muq::Mdoeling::WorkPiece where some of the outputs and all of the inputs have specified types
130 WorkPiece::WorkPiece(std::vector<std::string> const& inTypes, std::map<unsigned int, std::string> const& outTypes) :
131  numInputs(inTypes.size()), // fix the number of inputs
132  numOutputs(-1), // the number of outputs is unfixed
133  inputTypes(Types(inTypes)), // fix the inputs types
134  outputTypes(outTypes), // fix the output types
135  id(CreateID()), // the unique id of this WorkPiece
136  name("")
137 {}
138 
139 // Create a muq::Modeling::WorkPiece where some of the outputs with a known number of outputs and all of the inputs have specified types
140 WorkPiece::WorkPiece(std::vector<std::string> const& inTypes, std::map<unsigned int, std::string> const& outTypes, int const num) :
141  numInputs(inTypes.size()), // fix the number of inputs
142  numOutputs(num), // fix the number of outputs
143  inputTypes(Types(inTypes)), // fix the inputs types
144  outputTypes(outTypes), // fix the output types
145  id(CreateID()), // the unique id of this WorkPiece
146  name("")
147 {}
148 
149 // Create a muq::Mdoeling::WorkPiece where some of the inputs and some of the outputs have specified types
150 WorkPiece::WorkPiece(std::map<unsigned int, std::string> const& inTypes, std::map<unsigned int, std::string> const& outTypes) :
151  numInputs(-1), // the number of inputs is unfixed
152  numOutputs(-1), // the number of outputs is unfixed
153  inputTypes(inTypes), // fix the input types
154  outputTypes(outTypes), // fix the output types
155  id(CreateID()), // the unique id of this WorkPiece
156  name("")
157 {}
158 
159 // Create a muq::Mdoeling::WorkPiece where some of the inputs and some of the outputs have specified types with a fixed number of inputs
160 WorkPiece::WorkPiece(std::map<unsigned int, std::string> const& inTypes, int const numIn, std::map<unsigned int, std::string> const& outTypes) :
161  numInputs(numIn), // fix the number of inputs
162  numOutputs(-1), // the number of outputs is unfixed
163  inputTypes(inTypes), // fix the input types
164  outputTypes(outTypes), // fix the output types
165  id(CreateID()), // the unique id of this WorkPiece
166  name("")
167 {}
168 
169 // Create a muq::Mdoeling::WorkPiece where some of the inputs and some of the outputs have specified types with a fixed number of outputs
170 WorkPiece::WorkPiece(std::map<unsigned int, std::string> const& inTypes, std::map<unsigned int, std::string> const& outTypes, int const numOut) :
171  numInputs(-1), // the number of inputs is unfixed
172  numOutputs(numOut), // fix the number of outputs
173  inputTypes(inTypes), // fix the input types
174  outputTypes(outTypes), // fix the output types
175  id(CreateID()), // the unique id of this WorkPiece
176  name("")
177 {}
178 
179 // Create a muq::Modeling::WorkPiece where some of the inputs and some of the outputs have specified types with a fixed number of inputs and outputs
180 WorkPiece::WorkPiece(std::map<unsigned int, std::string> const& inTypes, int const numIn, std::map<unsigned int, std::string> const& outTypes, int const numOut) :
181  numInputs(numIn), // fix the number of inputs
182  numOutputs(numOut), // fix the number of outputs
183  inputTypes(inTypes), // fix the input types
184  outputTypes(outTypes), // fix the output types
185  id(CreateID()), // the unique id of this WorkPiece
186  name("")
187 {}
188 
189 std::map<unsigned int, std::string> WorkPiece::Types(std::vector<std::string> const& typesVec) const {
190  // initialize the map from input/output number to input/output type
191  std::map<unsigned int, std::string> typesMap;
192 
193  // populate the map with the elments in the type vector
194  for( unsigned int i=0; i<typesVec.size(); ++i ) {
195  typesMap[i] = typesVec.at(i);
196  }
197 
198  return typesMap;
199 }
200 
201 std::vector<std::string> WorkPiece::Types(std::vector<boost::any> const& vec) const {
202  // create a vector of the types
203  std::vector<std::string> types;
204  types.reserve(vec.size());
205 
206  // populate types with the type of each element of vec
207  for( auto it : vec ) {
208  types.push_back(it.type().name());
209  }
210 
211  // the types and vector should be the same size
212  assert(types.size()==vec.size());
213 
214  return types;
215 }
216 
217 unsigned int WorkPiece::CreateID() {
218  static unsigned int workPieceId = 0;
219  return ++workPieceId;
220 }
221 
222 std::vector<boost::any> const& WorkPiece::Evaluate() {
223  // make sure we have the correct number of inputs
224  assert(numInputs<=0);
225 
226  // clear the outputs
227  Clear();
228 
229  // evaluate the WorkPiece
230  std::vector<std::reference_wrapper<const boost::any>> emptyVec;
231  EvaluateImpl(emptyVec);
232 
233  // make sure we have the correct number of outputs
234  assert(numOutputs<0 || outputs.size()==numOutputs);
235 
236  // make sure the output types are correct
237  for(unsigned int i=0; i<outputTypes.size(); ++i ) {
238  assert(outputTypes[i].compare(outputs[i].type().name())==0);
239  }
240 
241  // return the outputs
242  return outputs;
243 }
244 
245 std::vector<boost::any> const& WorkPiece::Evaluate(ref_vector<boost::any> const& ins) {
246  // make sure we have the correct number of inputs
247  if((numInputs>=0) && (ins.size()!=numInputs))
248  throw muq::WrongSizeError("In WorkPiece::Evaluate: Expected " + std::to_string(numInputs) + " inputs, but " + std::to_string(ins.size()) + " were given.");
249 
250 
251  // we have new outputs
252  Clear();
253 
254  // the inputs are set, so call evaluate with no inputs
255  EvaluateImpl(ins);
256 
257  // make sure the output types are correct
258  if((numOutputs>=0) && (outputs.size()!=numOutputs))
259  throw muq::WrongSizeError("In WorkPiece::Evaluate: EvaluateImpl function returned " + std::to_string(outputs.size()) + " outputs, but " + std::to_string(numOutputs) + " were expected.");
260 
261  // check the output types
262  for( unsigned int i=0; i<outputs.size(); ++i ) {
263  assert(CheckOutputType(i, outputs[i].type().name()));
264  }
265 
266  return outputs;
267 }
268 
269 std::vector<boost::any> const& WorkPiece::Evaluate(std::vector<boost::any> const& ins) {
270  // make sure we have the correct number of inputs
271  assert(numInputs<0 || ins.size()==numInputs);
272 
273  // make sure the input types are correct
274  assert(inputTypes.size()==0 || inputTypes.size()==ins.size());
275  for(unsigned int i=0; i<inputTypes.size(); ++i ) {
276  assert(CheckInputType(i, ins[i].type().name()));
277  }
278 
279  return Evaluate(ToRefVector(ins));
280 }
281 //
282 // boost::any WorkPiece::Jacobian(unsigned int const wrtIn, unsigned int const wrtOut, std::vector<boost::any> const& ins) {
283 // // make sure we have the correct number of inputs
284 // assert(numInputs<0 || ins.size()==numInputs);
285 //
286 // // make sure the input and output number are valid
287 // assert(numInputs<0 || wrtIn<numInputs);
288 // assert(numOutputs<0 || wrtOut<numOutputs);
289 //
290 // // make sure the input types are correct
291 // assert(inputTypes.size()==0 || inputTypes.size()==ins.size());
292 // for(unsigned int i=0; i<inputTypes.size(); ++i ) {
293 // assert(CheckInputType(i, ins[i].type().name()));
294 // }
295 //
296 // return Jacobian(wrtIn, wrtOut, ToRefVector(ins));
297 // }
298 //
299 // boost::any WorkPiece::Jacobian(unsigned int const wrtIn, unsigned int const wrtOut, ref_vector<boost::any> const& ins) {
300 // // make sure we have the correct number of inputs
301 // assert(numInputs<0 || ins.size()==numInputs);
302 //
303 // // make sure the input and output number are valid
304 // assert(numInputs<0 || wrtIn<numInputs);
305 // assert(numOutputs<0 || wrtOut<numOutputs);
306 //
307 // // clear the derivative information
308 // ClearDerivatives();
309 //
310 // // the inputs are set, so call evaluate with no inputs
311 // JacobianImpl(wrtIn, wrtOut, ins);
312 //
313 // // make sure the jacobian was computed (the optional jacobian member has a value)
314 // if( !jacobian ) {
315 // std::cerr << std::endl << "ERROR: The Jacobian was not computed properly, make sure JacobianImpl gives muq::Modeling::WorkPiece::jacobian a value" << std::endl << std::endl;
316 // assert(jacobian);
317 // }
318 //
319 // if( jacobian ) {
320 // // return the jacobian (use the * operator because it is a boost::optional)
321 // return *jacobian;
322 // }
323 //
324 // // jacobian has not been computed --- return an empty boost optional
325 // return jacobian;
326 // }
327 //
328 // void WorkPiece::JacobianImpl(unsigned int const wrtIn, unsigned int const wrtOut, ref_vector<boost::any> const& inputs) {
329 // // the name of the Eigen::VectorXd's
330 // const std::string eigenType = typeid(Eigen::VectorXd).name();
331 //
332 // // if both the input and output type is Eigen::VectorXd, default to finite difference
333 // if( InputType(wrtIn, false).compare(eigenType)==0 && OutputType(wrtOut, false).compare(eigenType)==0 ) {
334 // // compute the jacobian with finite difference
335 // JacobianByFD(wrtIn, wrtOut, inputs);
336 //
337 // return;
338 // }
339 //
340 // jacobian = boost::none;
341 //
342 // // invalid! The user has not implemented the Jacobian
343 // std::cerr << std::endl << "ERROR: No JacobianImpl function for muq::Modeling::WorkPiece implemented, cannot compute Jacobian" << std::endl << std::endl;
344 // assert(false);
345 // }
346 //
347 // void WorkPiece::JacobianByFD(unsigned int const wrtIn, unsigned int const wrtOut, ref_vector<boost::any> const& inputs, double const relTol, double const minTol) {
348 // // the input we are computing the derivative wrt (the value will change so we need a hard copy)
349 // boost::any in = inputs[wrtIn];
350 //
351 // // a reference to the input that we can change
352 // Eigen::VectorXd& inref = boost::any_cast<Eigen::VectorXd&>(in);
353 //
354 // // get a copy of the inputs (note, we are only copying the references)
355 // ref_vector<const boost::any> tempIns = inputs;
356 // tempIns[wrtIn] = in;
357 //
358 // // compute the base result
359 // const std::vector<boost::any>& base = Evaluate(inputs);
360 //
361 // // const reference to the output of interest
362 // const Eigen::VectorXd& outbase = boost::any_cast<const Eigen::VectorXd&>(base[wrtOut]);
363 //
364 // // initalize the jacobian and a reference that we can change
365 // jacobian = (Eigen::MatrixXd)Eigen::MatrixXd::Zero(outbase.size(), inref.size());
366 // Eigen::MatrixXd& jac = boost::any_cast<Eigen::MatrixXd&>(*jacobian); // use * operator because it is a boost::optional
367 //
368 // // loop thorugh the inputs (columns of the Jacobian)
369 // for( unsigned int col=0; col<inref.size(); ++col ) {
370 // // compute the step length
371 // const double dx = std::fmax(minTol, relTol*inref(col));
372 //
373 // // increment the col's input (change the reference to the boost any)
374 // inref(col) += dx;
375 //
376 // // compute the perturbed result
377 // const std::vector<boost::any>& plus = Evaluate(tempIns);
378 //
379 // // const reference to the output of interest
380 // const Eigen::VectorXd& outplus = boost::any_cast<const Eigen::VectorXd&>(plus[wrtOut]);
381 //
382 // // compute the Jacobian for this column
383 // jac.col(col) = (outplus-outbase)/dx;
384 //
385 // // reset the the col's input
386 // inref(col) -= dx;
387 // }
388 // }
389 //
390 // boost::any WorkPiece::JacobianAction(unsigned int const wrtIn, unsigned int const wrtOut, boost::any const& vec, std::vector<boost::any> const& ins) {
391 // // make sure we have the correct number of inputs
392 // assert(numInputs<0 || ins.size()==numInputs);
393 //
394 // // make sure the input and output number are valid
395 // assert(numInputs<0 || wrtIn<numInputs);
396 // assert(numOutputs<0 || wrtOut<numOutputs);
397 //
398 // // clear the derivative information
399 // ClearDerivatives();
400 //
401 // // make sure the input types are correct
402 // assert(inputTypes.size()==0 || inputTypes.size()==ins.size());
403 // for(unsigned int i=0; i<inputTypes.size(); ++i ) {
404 // assert(CheckInputType(i, ins[i].type().name()));
405 // }
406 //
407 // return JacobianAction(wrtIn, wrtOut, vec, ToRefVector(ins));
408 // }
409 //
410 // boost::any WorkPiece::JacobianAction(unsigned int const wrtIn, unsigned int const wrtOut, boost::any const& vec, ref_vector<boost::any> const& ins) {
411 // // make sure we have the correct number of inputs
412 // assert(numInputs<0 || ins.size()==numInputs);
413 //
414 // // make sure the input and output number are valid
415 // assert(numInputs<0 || wrtIn<numInputs);
416 // assert(numOutputs<0 || wrtOut<numOutputs);
417 //
418 // // the inputs are set, so call evaluate with no inputs
419 // JacobianActionImpl(wrtIn, wrtOut, vec, ins);
420 //
421 // // make sure the jacobian was computed (the optional jacobian member has a value)
422 // if( !jacobianAction ) {
423 // std::cerr << std::endl << "ERROR: The Jacobian was not computed properly, make sure JacobianActionImpl gives muq::Modeling::WorkPiece::jacobianAction a value" << std::endl << std::endl;
424 // assert(jacobianAction);
425 // }
426 //
427 // // return the jacobian action (use the * operator because it is a boost::optional)
428 // return *jacobianAction;
429 // }
430 //
431 // void WorkPiece::JacobianActionImpl(unsigned int const wrtIn, unsigned int const wrtOut, boost::any const& vec, ref_vector<boost::any> const& inputs) {
432 // // the name of the Eigen::VectorXd's
433 // const std::string eigenType = typeid(Eigen::VectorXd).name();
434 //
435 // // if both the input and output type is Eigen::VectorXd, default to finite difference
436 // if( eigenType.compare(vec.type().name())==0 && InputType(wrtIn, false).compare(eigenType)==0 && OutputType(wrtOut, false).compare(eigenType)==0 ) {
437 // // compute the action of the jacobian using finite differences
438 // JacobianActionByFD(wrtIn, wrtOut, vec, inputs);
439 //
440 // return;
441 // }
442 //
443 // // invalid! The user has not implemented the JacobianAction
444 // std::cerr << std::endl << "ERROR: No JacobianActionImpl function for muq::Modeling::WorkPiece implemented, cannot compute the action of the Jacobian" << std::endl << std::endl;
445 // assert(false);
446 // }
447 //
448 // void WorkPiece::JacobianActionByFD(unsigned int const wrtIn, unsigned int const wrtOut, boost::any const& vec, ref_vector<boost::any> const& inputs) {
449 // // compute the jacobian matrix with finite differences (if the jacobian is implemented then this is actually exact)
450 // Jacobian(wrtIn, wrtOut, inputs);
451 // assert(jacobian);
452 //
453 // // get a reference to the jacobian and the input vector
454 // const Eigen::MatrixXd& jac = boost::any_cast<const Eigen::MatrixXd&>(*jacobian); // * operator because it is a boost::optional
455 // const Eigen::VectorXd& vecref = boost::any_cast<const Eigen::VectorXd&>(vec);
456 //
457 // // check input sizes
458 // assert(jac.cols()==vecref.size());
459 //
460 // // apply the jacobian to the input vector
461 // jacobianAction = (Eigen::VectorXd)(jac*vecref);
462 // }
463 //
464 // boost::any WorkPiece::JacobianTransposeAction(unsigned int const wrtIn, unsigned int const wrtOut, boost::any const& vec, std::vector<boost::any> const& ins) {
465 // // make sure we have the correct number of inputs
466 // assert(numInputs<0 || ins.size()==numInputs);
467 //
468 // // make sure the input and output number are valid
469 // assert(numInputs<0 || wrtIn<numInputs);
470 // assert(numOutputs<0 || wrtOut<numOutputs);
471 //
472 // // clear the derivative information
473 // ClearDerivatives();
474 //
475 // // make sure the input types are correct
476 // assert(inputTypes.size()==0 || inputTypes.size()==ins.size());
477 // for(unsigned int i=0; i<inputTypes.size(); ++i ) {
478 // assert(CheckInputType(i, ins[i].type().name()));
479 // }
480 //
481 // return JacobianTransposeAction(wrtIn, wrtOut, vec, ToRefVector(ins));
482 // }
483 //
484 // boost::any WorkPiece::JacobianTransposeAction(unsigned int const wrtIn, unsigned int const wrtOut, boost::any const& vec, ref_vector<boost::any> const& ins) {
485 // // make sure we have the correct number of inputs
486 // assert(numInputs<0 || ins.size()==numInputs);
487 //
488 // // make sure the input and output number are valid
489 // assert(numInputs<0 || wrtIn<numInputs);
490 // assert(numOutputs<0 || wrtOut<numOutputs);
491 //
492 // // the inputs are set, so call evaluate with no inputs
493 // JacobianTransposeActionImpl(wrtIn, wrtOut, vec, ins);
494 //
495 // // make sure the jacobian was computed (the optional jacobian member has a value)
496 // if( !jacobianTransposeAction ) {
497 // std::cerr << std::endl << "ERROR: The Jacobian was not computed properly, make sure JacobianTransposeActionImpl gives muq::Modeling::WorkPiece::jacobianTransposeAction a value" << std::endl << std::endl;
498 // assert(jacobianTransposeAction);
499 // }
500 //
501 // // return the jacobian action (use the * operator because it is a boost::optional)
502 // return *jacobianTransposeAction;
503 // }
504 //
505 // void WorkPiece::JacobianTransposeActionImpl(unsigned int const wrtIn, unsigned int const wrtOut, boost::any const& vec, ref_vector<boost::any> const& inputs) {
506 // // the name of the Eigen::VectorXd's
507 // const std::string eigenType = typeid(Eigen::VectorXd).name();
508 //
509 // // if both the input and output type is Eigen::VectorXd, default to finite difference
510 // if( eigenType.compare(vec.type().name())==0 && InputType(wrtIn, false).compare(eigenType)==0 && OutputType(wrtOut, false).compare(eigenType)==0 ) {
511 // // compute the action of the jacobian transpose using finite differences
512 // JacobianTransposeActionByFD(wrtIn, wrtOut, vec, inputs);
513 //
514 // return;
515 // }
516 //
517 // // invalid! The user has not implemented the JacobianAction
518 // std::cerr << std::endl << "ERROR: No JacobianTransposeActionImpl function for muq::Modeling::WorkPiece implemented, cannot compute the action of the Jacobian transpose" << std::endl << std::endl;
519 // assert(false);
520 // }
521 //
522 // void WorkPiece::JacobianTransposeActionByFD(unsigned int const wrtIn, unsigned int const wrtOut, boost::any const& vec, ref_vector<boost::any> const& inputs) {
523 // // compute the jacobian matrix with finite differences (if the jacobian is implemented this is exact)
524 // Jacobian(wrtIn, wrtOut, inputs);
525 // assert(jacobian);
526 //
527 // // get a reference to the jacobian and the input vector
528 // const Eigen::MatrixXd& jac = boost::any_cast<const Eigen::MatrixXd&>(*jacobian); // * operator because it is a boost::optional
529 // const Eigen::VectorXd& vecref = boost::any_cast<const Eigen::VectorXd&>(vec);
530 //
531 // // check input sizes
532 // assert(jac.rows()==vecref.size());
533 //
534 // // apply the jacobian to the input vector
535 // jacobianTransposeAction = (Eigen::VectorXd)(jac.transpose()*vecref);
536 // }
537 
538 std::string const& WorkPiece::Name()
539 {
540  if(name.length()==0)
541  name = CreateName();
542 
543  return name;
544 }
545 
546 std::string WorkPiece::CreateName() const {
547  int status;
548  std::stringstream ss;
549 
550  std::string className = muq::Utilities::demangle(typeid(*this).name());
551 
552  // Check to see if the class name starts with muq::Modeling. If it does, remove it.
553  if(className.rfind("muq::Modeling", 0) == 0)
554  className.erase(0,15);
555 
556  // Remote templates
557  std::string simpleName = "";
558  int openCnt = 0;
559  for(int i=0; i<className.size(); ++i){
560  if(className[i]=='<'){
561  openCnt++;
562  }else if(className[i]=='>'){
563  openCnt--;
564  }else if(openCnt==0){
565  simpleName += className[i];
566  }
567  }
568 
569  ss << simpleName << "_" << id;
570 
571  return ss.str();
572 }
573 
574 
575 void WorkPiece::SetName(std::string const& newName)
576 {
577  name = newName;
578 }
579 
580 double WorkPiece::GetRunTime(const std::string& method) const
581 {
582  const double toMilli = 1.0e-6;
583 
584  if (method.compare("Evaluate") == 0) {
585  return (numEvalCalls == 0) ? -1.0 : toMilli *static_cast<double>(evalTime) / static_cast<double>(numEvalCalls);
586  }else{
587  assert(method.compare("Evaluate") == 0);
588  return -999.0;
589  }
590 }
591 
593 {
594  numEvalCalls = 0;
595  evalTime = 0;
596 }
597 
598 unsigned long int WorkPiece::GetNumCalls(const std::string& method) const
599 {
600  if (method.compare("Evaluate") == 0) {
601  return numEvalCalls;
602  } else {
603  assert(method.compare("Evaluate") == 0);
604  return -999;
605  }
606 }
607 
608 
609 std::string WorkPiece::InputType(unsigned int inputNum, bool const demangle) const {
610  // make sure the inputNum is less than the number of inputs or that we don't know the number of inputs
611  assert(numInputs<0 || inputNum<numInputs);
612 
613  // an iterator to the input type
614  auto it = inputTypes.find(inputNum);
615 
616  // we don't know the input type
617  if( it==inputTypes.end() ) {
618  return "";
619  }
620 
621  // make it human readable
622  if( demangle ) {
623  return boost::core::demangle(it->second.c_str());
624  }
625 
626  // return the input type
627  return it->second;
628 }
629 
630 std::string WorkPiece::OutputType(unsigned int outputNum, bool const demangle) const {
631  // make sure the outputNum is less than the number of outputs or that we don't know the number of outputs
632  assert(numOutputs<0 || outputNum<numOutputs);
633 
634  // an iterator to the output type
635  auto it = outputTypes.find(outputNum);
636 
637  // we don't know the output type
638  if( it==outputTypes.end() ) {
639  return "";
640  }
641 
642  // make it human readable
643  if( demangle ) {
644  return boost::core::demangle(it->second.c_str());
645  }
646 
647  // return the output type
648  return it->second;
649 }
650 
651 unsigned int WorkPiece::ID() const{
652  return id;
653 }
654 
655 std::map<unsigned int, std::string> WorkPiece::OutputTypes() const {
656  return outputTypes;
657 }
658 
659 std::map<unsigned int, std::string> WorkPiece::InputTypes() const {
660  return inputTypes;
661 }
662 
663 ref_vector<const Eigen::VectorXd> WorkPiece::ToRefVector(std::vector<Eigen::VectorXd> const& vec) {
664 
666  refs.reserve(vec.size());
667 
668  // populate the input vector
669  for(int i=0; i<vec.size(); ++i)
670  refs.push_back(std::cref(vec.at(i)));
671 
672  return refs;
673 }
674 
675 ref_vector<const boost::any> WorkPiece::ToRefVector(std::vector<boost::any> const& anyVec) {
676 
678  refs.reserve(anyVec.size());
679 
680  // populate the input vector
681  for(int i=0; i<anyVec.size(); ++i)
682  refs.push_back(std::cref(anyVec.at(i)));
683 
684  return refs;
685 }
686 
687 void WorkPiece::DestroyAnyImpl(boost::any& obj) const {}
688 
689 void WorkPiece::DestroyAny(boost::any& obj) const {
690  // the output time
691  const std::string outtype = obj.type().name();
692 
693 #if MUQ_HAS_SUNDIALS==1
694  // destroy N_Vector type
695  if(outtype.compare(typeid(N_Vector).name())==0){
696  N_VDestroy(boost::any_cast<N_Vector&>(obj));
697  return;
698  }
699 
700  // destroy std::vector<N_Vector> type
701  if( outtype.compare(typeid(std::vector<N_Vector>).name())==0 ) { // if it is a vector of N_Vectors
702  std::vector<N_Vector>& vec = boost::any_cast<std::vector<N_Vector>&>(obj);
703  for( auto it : vec ) {
704  N_VDestroy(it);
705  }
706  vec.clear();
707  return;
708  }
709 
710  // destroy DlsMat type
711  if( outtype.compare(typeid(DlsMat).name())==0 ) {
712  DestroyMat(boost::any_cast<DlsMat&>(obj));
713  return;
714  }
715 
716  // destroy std::vector<DlsMat> type
717  if( outtype.compare(typeid(std::vector<DlsMat>).name())==0 ) {
718  std::vector<DlsMat>& vec = boost::any_cast<std::vector<DlsMat>&>(obj);
719  for( auto it : vec ) {
720  DestroyMat(it);
721  }
722  vec.clear();
723  return;
724  }
725 #endif
726 
727  DestroyAnyImpl(obj);
728 }
729 
731  // we have new outputs --- some WorkPiece's have the outputs stored in a child class so we don't always want to clear them
732  if( clearOutputs ) {
733  // destroy the output
734  for( unsigned int i=0; i<outputs.size(); ++i ) {
735  DestroyAny(outputs[i]);
736  }
737 
738  // clear the output
739  outputs.clear();
740  }
741 }
742 
743 bool WorkPiece::CheckInputType(unsigned int const inputNum, std::string const& type) const {
744  // find the input type
745  auto it = inputTypes.find(inputNum);
746 
747  // check to see that the types match (or that we don't know the type)
748  if( it!=inputTypes.end() && it->second.compare(type)!=0 ) {
749  std::cerr << std::endl << "ERROR: Input types do not match." << std::endl << "\tGiven input: " << boost::core::demangle(type.c_str()) << ", expected " << boost::core::demangle(it->second.c_str()) << std::endl << std::endl;
750  return false;
751  }
752 
753  return true;
754 }
755 
756 bool WorkPiece::CheckOutputType(unsigned int const outputNum, std::string const& type) const {
757  // find the output type
758  auto it = outputTypes.find(outputNum);
759 
760  // check to see that the types match (or that we don't know the type)
761  if( it!=outputTypes.end() && it->second.compare(type)!=0 ) {
762  std::cerr << std::endl << "ERROR: Output types do not match." << std::endl << "\tGiven output: " << boost::core::demangle(type.c_str()) << ", expected " << boost::core::demangle(it->second.c_str()) << std::endl << std::endl;
763  return false;
764  }
765 
766  return true;
767 }
768 
769 
770 int WorkPiece::InputSize(unsigned int inputNum) const
771 {
772  auto iter = inputSizes.find(inputNum);
773  if(iter != inputSizes.end()){
774  return iter->second;
775  }else{
776  return -1;
777  }
778 }
779 
780 void WorkPiece::SetInputSize(unsigned int inputNum, int newSize)
781 {
782  inputSizes[inputNum] = newSize;
783 }
Base class for MUQ's modelling envronment.
Definition: WorkPiece.h:40
void Clear()
Clear muq::Modeling::WorkPiece::outputs when muq::Modeling::Evaluate is called.
Definition: WorkPiece.cpp:730
std::string const & Name()
Get the (unique) name of this work piece.
Definition: WorkPiece.cpp:538
std::map< unsigned int, std::string > outputTypes
The output types.
Definition: WorkPiece.h:558
std::map< unsigned int, int > inputSizes
Definition: WorkPiece.h:560
bool CheckOutputType(unsigned int const outputNum, std::string const &type) const
Check the output type.
Definition: WorkPiece.cpp:756
std::map< unsigned int, std::string > OutputTypes() const
Get the output types.
Definition: WorkPiece.cpp:655
bool CheckInputType(unsigned int const inputNum, std::string const &type) const
Check the input type.
Definition: WorkPiece.cpp:743
const unsigned int id
A unique ID number assigned by the constructor.
Definition: WorkPiece.h:580
virtual unsigned long int GetNumCalls(const std::string &method="Evaluate") const
get the number of times one of the implemented methods has been called.
Definition: WorkPiece.cpp:598
std::map< unsigned int, std::string > inputTypes
The input types.
Definition: WorkPiece.h:552
WorkPiece()
Create a muq::Modeling::WorkPiece with no fixed number of inputs and outputs and variable input/outpu...
Definition: WorkPiece.cpp:10
std::string OutputType(unsigned int outputNum, bool const demangle=true) const
Get the output type (if we know it) for a specific output.
Definition: WorkPiece.cpp:630
virtual double GetRunTime(const std::string &method="Evaluate") const
Get the average run time for one of the implemented methods.
Definition: WorkPiece.cpp:580
virtual void EvaluateImpl(ref_vector< boost::any > const &inputs)=0
User-implemented function that determines the behavior of this muq::Modeling::WorkPiece.
unsigned long int numEvalCalls
Definition: WorkPiece.h:573
virtual void ResetCallTime()
Resets the number of call and times.
Definition: WorkPiece.cpp:592
std::map< unsigned int, std::string > InputTypes() const
Get the input types.
Definition: WorkPiece.cpp:659
std::vector< std::string > Types(std::vector< boost::any > const &vec) const
Get the types from a vector of boost::any's.
Definition: WorkPiece.cpp:201
static ref_vector< const boost::any > ToRefVector(std::vector< boost::any > const &anyVec)
Create vector of references from a vector of boost::any's.
Definition: WorkPiece.cpp:675
void SetName(std::string const &newName)
Set the name of this work piece.
Definition: WorkPiece.cpp:575
std::string InputType(unsigned int inputNum, bool const demangle=true) const
Get the input type (if we know it) for a specific input.
Definition: WorkPiece.cpp:609
unsigned int ID() const
Get the unique ID number.
Definition: WorkPiece.cpp:651
bool clearOutputs
Clear outputs every time Evaluate is called.
Definition: WorkPiece.h:540
void DestroyAny(boost::any &obj) const
Destroy a boost any.
Definition: WorkPiece.cpp:689
int numOutputs
The number of outputs.
Definition: WorkPiece.h:504
void SetInputSize(unsigned int inputNum, int newSize)
Definition: WorkPiece.cpp:780
Fix
Does the constructor fix the inputs or the outputs?
Definition: WorkPiece.h:49
virtual std::string CreateName() const
Definition: WorkPiece.cpp:546
virtual void DestroyAnyImpl(boost::any &obj) const
Destroy a boost any.
Definition: WorkPiece.cpp:687
std::vector< boost::any > outputs
The outputs.
Definition: WorkPiece.h:546
std::vector< boost::any > const & Evaluate()
Evaluate this muq::Modeling::WorkPiece in the case that there are no inputs.
Definition: WorkPiece.cpp:222
static unsigned int CreateID()
Creates a unique ID number, must be called by the constructor.
Definition: WorkPiece.cpp:217
int InputSize(unsigned int inputNum) const
Get the length of a vector valued input with fixed size.
Definition: WorkPiece.cpp:770
std::string name
A unique name for this WorkPiece. Defaults to <ClassName>_<id>
Definition: WorkPiece.h:583
int numInputs
The number of inputs.
Definition: WorkPiece.h:501
Exception to throw when matrices, vectors, or arrays are the wrong size.
Definition: Exceptions.h:58
std::vector< std::reference_wrapper< const T > > ref_vector
A vector of references to something ...
Definition: WorkPiece.h:37
std::string demangle(const char *name)
Definition: Demangler.cpp:6
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition: json.h:25172