MUQ  0.4.3
ModPiece.cpp
Go to the documentation of this file.
4 
5 #include <chrono>
6 
7 using namespace muq::Modeling;
8 
9 ModPiece::ModPiece(std::vector<int> const& inputSizes,
10  std::vector<int> const& outputSizes) : ModPiece(Eigen::Map<const Eigen::VectorXi>(&inputSizes[0],inputSizes.size()),
11  Eigen::Map<const Eigen::VectorXi>(&outputSizes[0],outputSizes.size())){};
12 
13 
14 ModPiece::ModPiece(Eigen::VectorXi const& inputSizesIn,
15  Eigen::VectorXi const& outputSizesIn) :
16  WorkPiece(std::vector<std::string>(inputSizesIn.size(), typeid(Eigen::VectorXd).name()),
17  std::vector<std::string>(outputSizesIn.size(), typeid(Eigen::VectorXd).name())),
18  inputSizes(inputSizesIn),
19  outputSizes(outputSizesIn){};
20 
21 
22 std::vector<Eigen::VectorXd> const& ModPiece::Evaluate(std::vector<Eigen::VectorXd> const& input)
23 {
24  return Evaluate(ToRefVector(input));
25 }
26 
28 {
29  // Check to see if the input is the same as what's cached
30  if(input.size()!=cacheInput.size()){
31  return false;
32  }
33 
34  // Check the size of each input vector
35  for(int i=0; i<input.size(); ++i){
36  if(input.at(i).get().size()!=cacheInput.at(i).size()){
37  return false;
38  }
39  }
40 
41  // Check the contents of each input vector
42  for(int i=0; i<input.size(); ++i){
43  Eigen::VectorXd const& inVec = input.at(i).get();
44  for(int j=0; j<cacheInput[i].size(); ++j){
45  if(std::abs(inVec(j)-cacheInput[i](j))>std::numeric_limits<double>::epsilon()){
46  return false;
47  }
48  }
49  }
50 
51  return true;
52 }
53 
54 std::vector<Eigen::VectorXd> const& ModPiece::Evaluate(ref_vector<Eigen::VectorXd> const& input)
55 {
56  CheckInputs(input,"Evaluate");
57 
58  // If we're using the one-step cache, check to see if the inputs are the same as the previous evaluation
59  if(cacheEnabled){
60  if(ExistsInCache(input)){
61  return outputs;
62 
63  }else{
64  // Copy the contents
65  cacheInput.resize(input.size());
66  for(int i=0; i<input.size(); ++i)
67  cacheInput.at(i) = input.at(i);
68  }
69  }
70 
71  // Otherwise, evaluate the model
72  numEvalCalls++;
73  auto start_time = std::chrono::high_resolution_clock::now();
74 
75  EvaluateImpl(input);
76 
77  auto end_time = std::chrono::high_resolution_clock::now();
78  evalTime += static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count());
79 
80  return outputs;
81 }
82 
83 Eigen::VectorXd const& ModPiece::Gradient(unsigned int const outputDimWrt,
84  unsigned int const inputDimWrt,
85  std::vector<Eigen::VectorXd> const& input,
86  Eigen::VectorXd const& sensitivity)
87 {
88  return Gradient(outputDimWrt, inputDimWrt, ToRefVector(input), sensitivity);
89 }
90 
91 
92 Eigen::VectorXd const& ModPiece::Gradient(unsigned int const outputDimWrt,
93  unsigned int const inputDimWrt,
94  ref_vector<Eigen::VectorXd> const& input,
95  Eigen::VectorXd const& sensitivity)
96 {
97  CheckInputs(input,"Gradient");
98 
99  numGradCalls++;
100  auto start_time = std::chrono::high_resolution_clock::now();
101 
102  GradientImpl(outputDimWrt, inputDimWrt, input, sensitivity);
103 
104  auto end_time = std::chrono::high_resolution_clock::now();
105  gradTime += static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count());
106 
107  return gradient;
108 }
109 
110 
111 Eigen::VectorXd ModPiece::GradientByFD(unsigned int const outputDimWrt,
112  unsigned int const inputDimWrt,
113  std::vector<Eigen::VectorXd> const& input,
114  Eigen::VectorXd const& sensitivity)
115 {
116  return GradientByFD(outputDimWrt, inputDimWrt, ToRefVector(input), sensitivity);
117 }
118 
119 Eigen::VectorXd ModPiece::GradientByFD(unsigned int const outputDimWrt,
120  unsigned int const inputDimWrt,
121  ref_vector<Eigen::VectorXd> const& input,
122  Eigen::VectorXd const& sensitivity)
123 {
124  numGradFDCalls++;
125  return JacobianByFD(outputDimWrt,inputDimWrt, input).transpose()*sensitivity;
126 }
127 
128 Eigen::MatrixXd const& ModPiece::Jacobian(unsigned int const outputDimWrt,
129  unsigned int const inputDimWrt,
130  std::vector<Eigen::VectorXd> const& input)
131 {
132  return Jacobian(outputDimWrt, inputDimWrt, ToRefVector(input));
133 }
134 
135 Eigen::MatrixXd const& ModPiece::Jacobian(unsigned int const outputDimWrt,
136  unsigned int const inputDimWrt,
137  ref_vector<Eigen::VectorXd> const& input)
138 {
139  CheckInputs(input,"Jacobian");
140 
141  numJacCalls++;
142  auto start_time = std::chrono::high_resolution_clock::now();
143 
144  JacobianImpl(outputDimWrt, inputDimWrt, input);
145 
146  auto end_time = std::chrono::high_resolution_clock::now();
147  jacTime += static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count());
148 
149  return jacobian;
150 }
151 
152 
153 Eigen::VectorXd const& ModPiece::ApplyJacobian(unsigned int const outputDimWrt,
154  unsigned int const inputDimWrt,
155  std::vector<Eigen::VectorXd> const& input,
156  Eigen::VectorXd const& vec)
157 {
158  return ApplyJacobian(outputDimWrt, inputDimWrt, ToRefVector(input), vec);
159 }
160 
161 Eigen::VectorXd const& ModPiece::ApplyJacobian(unsigned int const outputDimWrt,
162  unsigned int const inputDimWrt,
163  ref_vector<Eigen::VectorXd> const& input,
164  Eigen::VectorXd const& vec)
165 {
166  CheckInputs(input,"ApplyJacobian");
167 
168  numJacActCalls++;
169  auto start_time = std::chrono::high_resolution_clock::now();
170 
171  ApplyJacobianImpl(outputDimWrt, inputDimWrt, input, vec);
172 
173  auto end_time = std::chrono::high_resolution_clock::now();
174  jacActTime += static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count());
175 
176  return jacobianAction;
177 }
178 
180  ref_vector<Eigen::VectorXd> eigenInputs;
181  for(int i=0; i<inputs.size(); ++i) {
182  eigenInputs.push_back( std::cref(boost::any_cast<Eigen::VectorXd const&>(inputs.at(i))) );
183  }
184 
185  EvaluateImpl(eigenInputs);
186 
187  WorkPiece::outputs.resize(outputs.size());
188  for(int i=0; i<outputs.size(); ++i)
189  WorkPiece::outputs.at(i) = boost::any(outputs.at(i));
190 }
191 
192 
193 // Eigen::VectorXd ModPiece::ApplyHessian(int const outputDimWrt,
194 // int const inputDimWrt1,
195 // int const inputDimWrt2,
196 // ref_vector<Eigen::VectorXd> const& input,
197 // Eigen::VectorXd const& sensitivity,
198 // Eigen::VectorXd const& vec)
199 // {
200 // CheckInputs(input);
201 //
202 // numHessCalls++;
203 // auto start_time = std::chrono::high_resolution_clock::now();
204 //
205 // ApplyHessianImpl(outputDimWrt, inputDimWrt1, inputDimWrt2, input, sensitivity, vec);
206 //
207 // auto end_time = std::chrono::high_resolution_clock::now();
208 // hessTime += 1e6*static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count());
209 // }
210 
211 void ModPiece::CheckInputs(ref_vector<Eigen::VectorXd> const& input, std::string const& funcName)
212 {
213  bool errorOccured = false;
214  std::string msg;
215 
216  if(input.size() != inputSizes.size()){
217  msg += " - Wrong number of input arguments. Expected " + std::to_string(inputSizes.size()) + " inputs, but " + std::to_string(input.size()) + " were given.\n";
218  errorOccured=true;
219  }
220 
221  for(int i=0; i<std::min<int>(input.size(), inputSizes.size()); ++i){
222  if(input.at(i).get().size() != inputSizes(i)){
223  msg += " - Input " + std::to_string(i) + " has the wrong size. Expected size " + std::to_string(inputSizes(i)) + ", but given input with size " + std::to_string(input.at(i).get().size()) + "\n";
224  errorOccured = true;
225  }
226  }
227 
228  if(errorOccured){
229  std::string className = muq::Utilities::demangle(typeid(*this).name());
230  msg = "\nError evaluating " + className + "::" + funcName + ":\n" + msg;
231 
232  throw muq::WrongSizeError(msg);
233  }
234 }
235 
236 
237 void ModPiece::GradientImpl(unsigned int const outputDimWrt,
238  unsigned int const inputDimWrt,
239  ref_vector<Eigen::VectorXd> const& input,
240  Eigen::VectorXd const& sensitivity)
241 {
242  gradient = Jacobian(outputDimWrt, inputDimWrt, input).transpose() * sensitivity;
243 }
244 
245 void ModPiece::JacobianImpl(unsigned int const outputDimWrt,
246  unsigned int const inputDimWrt,
247  ref_vector<Eigen::VectorXd> const& input)
248 {
249  if(fdWarnLevel==1){
250  std::string className = muq::Utilities::demangle(typeid(*this).name());
251  std::cout << "WARNING: In " << className << ", defaulting to finite difference approximation of JacobianImpl." << std::endl;
252  }else if(fdWarnLevel==2){
253  std::string className = muq::Utilities::demangle(typeid(*this).name());
254  std::stringstream msg;
255  msg << "Class " << className << " attempted to use a finite difference approximation of ApplyJacobianImpl.";
256  throw std::runtime_error(msg.str());
257  }
258 
259  jacobian = JacobianByFD(outputDimWrt, inputDimWrt, input);
260 }
261 
262 void ModPiece::ApplyJacobianImpl(unsigned int const outputDimWrt,
263  unsigned int const inputDimWrt,
264  ref_vector<Eigen::VectorXd> const& input,
265  Eigen::VectorXd const& vec)
266 {
267  if(fdWarnLevel==1){
268  std::string className = muq::Utilities::demangle(typeid(*this).name());
269  std::cout << "WARNING: In " << className << ", defaulting to finite difference approximation of ApplyJacobianImpl." << std::endl;
270  }else if(fdWarnLevel==2){
271  std::string className = muq::Utilities::demangle(typeid(*this).name());
272  std::stringstream msg;
273  msg << "Class " << className << " attempted to use a finite difference approximation of ApplyJacobianImpl.";
274  throw std::runtime_error(msg.str());
275  }
276 
277  jacobianAction = ApplyJacobianByFD(outputDimWrt, inputDimWrt, input, vec);
278 }
279 
280 // void ModPiece::ApplyHessianImpl(int const outputDimWrt,
281 // int const inputDimWrt1,
282 // int const inputDimWrt2,
283 // ref_vector<Eigen::VectorXd> const& input,
284 // Eigen::VectorXd const& sensitivity
285 // Eigen::VectorXd const& vec)
286 // {
287 // hessianAction = ApplyHessianByFD(outputDimWrt, inputDimWrt1, inputDimWrt2, input, sensitvity, vec);
288 // }
289 
290 Eigen::MatrixXd ModPiece::JacobianByFD(unsigned int const outputDimWrt,
291  unsigned int const inputDimWrt,
292  std::vector<Eigen::VectorXd> const& input)
293 {
294  return JacobianByFD(outputDimWrt, inputDimWrt, ToRefVector(input));
295 }
296 
297 Eigen::MatrixXd ModPiece::JacobianByFD(unsigned int const outputDimWrt,
298  unsigned int const inputDimWrt,
299  ref_vector<Eigen::VectorXd> const& input)
300 {
301  numJacFDCalls++;
302 
303  Eigen::VectorXd f0 = Evaluate(input).at(outputDimWrt);
304  Eigen::VectorXd f;
305 
306  double eps;
307  Eigen::VectorXd newInput(input.at(inputDimWrt).get());
308  ref_vector<Eigen::VectorXd> newInputVec = input;
309 
310  Eigen::MatrixXd jac(outputSizes(outputDimWrt), inputSizes(inputDimWrt));
311  for(int i=0; i<inputSizes(inputDimWrt); ++i){
312  eps = std::max(1e-8, 1e-10*std::abs(input.at(inputDimWrt)(i)));
313 
314  newInput(i) = input.at(inputDimWrt)(i) + eps;
315  newInputVec.at(inputDimWrt) = std::cref(newInput);
316 
317  f = Evaluate(newInputVec).at(outputDimWrt);
318 
319  jac.col(i) = (f-f0)/eps;
320 
321  newInput(i) = input.at(inputDimWrt)(i);
322  }
323 
324  return jac;
325 }
326 
327 Eigen::VectorXd ModPiece::ApplyJacobianByFD(unsigned int const outputDimWrt,
328  unsigned int const inputDimWrt,
329  std::vector<Eigen::VectorXd> const& input,
330  Eigen::VectorXd const& vec)
331 {
332  return ApplyJacobianByFD(outputDimWrt, inputDimWrt, ToRefVector(input), vec);
333 }
334 Eigen::VectorXd ModPiece::ApplyJacobianByFD(unsigned int const outputDimWrt,
335  unsigned int const inputDimWrt,
336  ref_vector<Eigen::VectorXd> const& input,
337  Eigen::VectorXd const& vec)
338 {
340 
341  const double eps = 1e-4;
342  double vecNorm = vec.norm();
343  const Eigen::VectorXd stepDir = vec/vecNorm;
344 
345  ref_vector<Eigen::VectorXd> newInputVec = input;
346  Eigen::VectorXd newInput = input.at(inputDimWrt).get() - 0.5*eps*stepDir;
347  newInputVec.at(inputDimWrt) = std::cref(newInput);
348  Eigen::VectorXd f0 = Evaluate(newInputVec).at(outputDimWrt);
349 
350  newInput = input.at(inputDimWrt).get() + 0.5*eps*stepDir;
351  newInputVec.at(inputDimWrt) = std::cref(newInput);
352 
353  Eigen::VectorXd f = Evaluate(newInputVec).at(outputDimWrt);
354 
355  return vecNorm*(f-f0)/eps;
356 }
357 
358 Eigen::VectorXd const& ModPiece::ApplyHessian(unsigned int const outWrt,
359  unsigned int const inWrt1,
360  unsigned int const inWrt2,
361  std::vector<Eigen::VectorXd> const& input,
362  Eigen::VectorXd const& sens,
363  Eigen::VectorXd const& vec)
364 {
365  return ApplyHessian(outWrt,inWrt1, inWrt2, ToRefVector(input), sens, vec);
366 }
367 
368 Eigen::VectorXd const& ModPiece::ApplyHessian(unsigned int const outWrt,
369  unsigned int const inWrt1,
370  unsigned int const inWrt2,
371  ref_vector<Eigen::VectorXd> const& input,
372  Eigen::VectorXd const& sens,
373  Eigen::VectorXd const& vec)
374 {
375 
376  if(inWrt2>inputSizes.size()){
377  std::string className = muq::Utilities::demangle(typeid(*this).name());
378  std::stringstream msg;
379  msg << "\nError evaluating " << className << "::ApplyHessian(" << outWrt << "," << inWrt1 << "," << inWrt2 << ")\n";
380  msg << " inWrt2 should be less than inputSizes.size()+1, but inWrt2 is \"" << inWrt2 << "\" and inputSizes.size() is \"" << inputSizes.size() << "\"";
381 
382  throw muq::WrongSizeError(msg.str());
383  }
384 
385  if(outWrt>=outputSizes.size()){
386  std::string className = muq::Utilities::demangle(typeid(*this).name());
387  std::stringstream msg;
388  msg << "\nError evaluating " << className << "::ApplyHessian(" << outWrt << "," << inWrt1 << "," << inWrt2 << ")\n";
389  msg << " outWrt should be less than outputSizes.size(), but outWrt is \"" << outWrt << "\" and outputSizes.size() is \"" << outputSizes.size() << "\"";
390 
391  throw muq::WrongSizeError(msg.str());
392  }
393 
394  if(sens.size()!=outputSizes(outWrt)){
395  std::string className = muq::Utilities::demangle(typeid(*this).name());
396  std::stringstream msg;
397  msg << "\nError evaluating " << className << "::ApplyHessian(" << outWrt << "," << inWrt1 << "," << inWrt2 << ")\n";
398  msg << " The sensitivity vector has sens.size()=" << sens.size() << " but it was expected to be outputSizes[outWrt]=" << outputSizes(outWrt);
399 
400  throw muq::WrongSizeError(msg.str());
401  }
402 
403  if(inWrt2<inputSizes.size()){
404  if(inputSizes(inWrt2)!=vec.size()){
405  std::string className = muq::Utilities::demangle(typeid(*this).name());
406  std::stringstream msg;
407  msg << "\nError evaluating " << className << "::ApplyHessian:\n";
408  msg << " The vector has size vec.size()=\"" << vec.size() << "\" but it was expected to be inputSizes(inWrt2)=\"" << inputSizes(inWrt2) << "\"";
409 
410  throw muq::WrongSizeError(msg.str());
411  }
412  }else{
413  if(outputSizes(outWrt)!=vec.size()){
414  std::string className = muq::Utilities::demangle(typeid(*this).name());
415  std::stringstream msg;
416  msg << "\nError evaluating " << className << "::ApplyHessian:\n";
417  msg << " The vector has size vec.size()=\"" << vec.size() << "\" but it was expected to be outputSizes(outWrt)=\"" << outputSizes(outWrt) << "\"";
418 
419  throw muq::WrongSizeError(msg.str());
420  }
421  }
422 
423  // /////////////////////
424  // Done with error checking...
425  numHessActCalls++;
426  auto start_time = std::chrono::high_resolution_clock::now();
427 
428  ApplyHessianImpl(outWrt, inWrt1, inWrt2, input, sens, vec);
429 
430  auto end_time = std::chrono::high_resolution_clock::now();
431  hessActTime += static_cast<double>(std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count());
432 
433  return hessAction;
434 }
435 
436 void ModPiece::ApplyHessianImpl(unsigned int const outWrt,
437  unsigned int const inWrt1,
438  unsigned int const inWrt2,
439  ref_vector<Eigen::VectorXd> const& input,
440  Eigen::VectorXd const& sens,
441  Eigen::VectorXd const& vec)
442 {
443  //std::cout << "Just before FD..." << std::endl;
444  hessAction = ApplyHessianByFD(outWrt, inWrt1, inWrt2, input, sens, vec);
445  //std::cout << "After FD, hessAction = " << hessAction << std::endl;
446 }
447 
448 Eigen::VectorXd ModPiece::ApplyHessianByFD(unsigned int const outWrt,
449  unsigned int const inWrt1,
450  unsigned int const inWrt2,
451  std::vector<Eigen::VectorXd> const& input,
452  Eigen::VectorXd const& sens,
453  Eigen::VectorXd const& vec)
454 {
455  return ApplyHessianByFD(outWrt,inWrt1, inWrt2, ToRefVector(input), sens, vec);
456 }
457 
458 Eigen::VectorXd ModPiece::ApplyHessianByFD(unsigned int const outWrt,
459  unsigned int const inWrt1,
460  unsigned int const inWrt2,
461  ref_vector<Eigen::VectorXd> const& input,
462  Eigen::VectorXd const& sens,
463  Eigen::VectorXd const& vec)
464 {
466 
467  const double stepSize = std::max(1e-4, 1e-8*vec.norm());
468 
469  Eigen::VectorXd grad1, grad2;
470 
471  // If the Hessian is wrt to one of the inputs, not the sensitivity vector
472  if(inWrt2<inputSizes.size()){
473 
474  ref_vector<Eigen::VectorXd> input2 = input;
475  Eigen::VectorXd x2 = input.at(inWrt2).get() - 0.5*stepSize * vec;
476  input2.at(inWrt2) = std::cref(x2);
477 
478  grad1 = Gradient(outWrt, inWrt1, input2, sens);
479 
480  x2 = input.at(inWrt2).get() + 0.5*stepSize * vec;
481  input2.at(inWrt2) = std::cref(x2);
482  grad2 = Gradient(outWrt, inWrt1, input2, sens);
483 
484  // Otherwise, we want the Jacobian of the Gradient piece wrt to the sensitivity vector
485  }else{
486  Eigen::VectorXd sens2 = sens - 0.5*stepSize * vec;
487  grad1 = Gradient(outWrt, inWrt1, input, sens2);
488 
489  sens2 = sens + 0.5*stepSize * vec;
490  grad2 = Gradient(outWrt, inWrt1, input, sens2);
491  }
492 
493  return (grad2 - grad1)/stepSize;
494 }
495 
496 
497 double ModPiece::GetRunTime(const std::string& method) const
498 {
499  const double toMilli = 1e-6;
500 
501  if (method.compare("Evaluate") == 0) {
502  return (numEvalCalls == 0) ? -1.0 : toMilli *static_cast<double>(evalTime) / static_cast<double>(numEvalCalls);
503  } else if (method.compare("Gradient") == 0) {
504  return (numGradCalls == 0) ? -1.0 : toMilli *static_cast<double>(gradTime) / static_cast<double>(numGradCalls);
505  } else if (method.compare("Jacobian") == 0) {
506  return (numJacCalls == 0) ? -1.0 : toMilli *static_cast<double>(jacTime) / static_cast<double>(numJacCalls);
507  } else if (method.compare("JacobianAction") == 0) {
508  return (numJacActCalls ==
509  0) ? -1.0 : toMilli *static_cast<double>(jacActTime) / static_cast<double>(numJacActCalls);
510  } else if (method.compare("HessianAction") == 0) {
511  return (numHessActCalls == 0) ? -1.0 : toMilli *static_cast<double>(hessActTime) / static_cast<double>(numHessActCalls);
512  } else {
513  assert(method.compare("Evaluate") == 0 || method.compare("Gradient") == 0 || method.compare(
514  "Jacobian") == 0 || method.compare("JacobianAction") == 0 || method.compare("HessianAction") == 0);
515  return -999.0;
516  }
517 }
518 
519 
521 {
522  numEvalCalls = 0;
523  numGradCalls = 0;
524  numJacCalls = 0;
525  numJacActCalls = 0;
526  numHessActCalls = 0;
527 
528  evalTime = 0;
529  gradTime = 0;
530  jacTime = 0;
531  jacActTime = 0;
532  hessActTime = 0;
533 }
534 
535 unsigned long int ModPiece::GetNumCalls(const std::string& method) const
536 {
537  if (method.compare("Evaluate") == 0) {
538  return numEvalCalls;
539  } else if (method.compare("Gradient") == 0) {
540  return numGradCalls;
541  } else if (method.compare("Jacobian") == 0) {
542  return numJacCalls;
543  } else if (method.compare("JacobianAction") == 0) {
544  return numJacActCalls;
545  } else if (method.compare("HessianAction") == 0) {
546  return numHessActCalls;
547  } else if (method.compare("GradientFD") == 0) {
548  return numGradFDCalls;
549  } else if (method.compare("JacobianFD") == 0) {
550  return numJacFDCalls;
551  } else if (method.compare("JacobianActionFD") == 0) {
552  return numJacActFDCalls;
553  } else if (method.compare("HessianActionFD") == 0) {
554  return numHessActFDCalls;
555  } else {
556  assert( (method.compare("Evaluate") == 0) || (method.compare("Gradient") == 0)
557  || (method.compare("Jacobian") == 0) || (method.compare("JacobianAction") == 0)
558  || (method.compare("HessianAction") == 0) || (method.compare("GradientFD")==0)
559  || (method.compare("JacobianFD")==0) || (method.compare("JacobianActionFD")==0)
560  || (method.compare("HessianActionFD")==0));
561  return -999;
562  }
563 }
564 // Eigen::VectorXd ModPiece::ApplyHessianByFD(int const outputDimWrt,
565 // int const inputDimWrt1,
566 // int const inputDimWrt2,
567 // ref_vector<Eigen::VectorXd> const& input,
568 // Eigen::VectorXd const& sensitivity
569 // Eigen::VectorXd const& vec)
570 // {
571 // Eigen::MatrixXd hess(inputSizes(inputDimWrt1), inputSizes(inputDimWrt2));
572 //
573 // const double eps = std::max(1e-8, 1e-10*vec.norm());
574 //
575 // Eigen::VectorXd newInput(input.at(inputDimWrt2));
576 // ref_vector<Eigen::VectorXd> newInputVec = input;
577 //
578 // Eigen::VectorXd newInput = input.at(inputDimWrt2) + eps*vec;
579 //
580 // Eigen::VectorXd f0 = Gradient(outputDimWrt, inputDimWrt1, input, sensitvity);
581 // Eigen::VectorXd f = Gradient(outputDimWrt, inputDimWrt1, newInput, sensitvity);
582 //
583 // return (f-f0)/eps;
584 // }
585 
586 std::vector<Eigen::VectorXd> ModPiece::ToStdVec(ref_vector<Eigen::VectorXd> const& input) {
587  std::vector<Eigen::VectorXd> newIns(input.size());
588 
589  for (int i=0; i<input.size(); ++i)
590  newIns.at(i) = input.at(i).get();
591 
592  return newIns;
593 }
Provides an abstract interface for defining vector-valued model components.
Definition: ModPiece.h:148
Eigen::MatrixXd jacobian
Definition: ModPiece.h:506
virtual void GradientImpl(unsigned int const outputDimWrt, unsigned int const inputDimWrt, ref_vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &sensitivity)
Definition: ModPiece.cpp:237
virtual void ApplyJacobianImpl(unsigned int const outputDimWrt, unsigned int const inputDimWrt, ref_vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &vec)
Definition: ModPiece.cpp:262
virtual Eigen::VectorXd GradientByFD(unsigned int const outputDimWrt, unsigned int const inputDimWrt, std::vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &sensitivity)
Definition: ModPiece.cpp:111
virtual Eigen::VectorXd const & Gradient(unsigned int const outputDimWrt, unsigned int const inputDimWrt, std::vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &sensitivity)
Compute the Gradient .
Definition: ModPiece.cpp:83
unsigned long int numJacActFDCalls
Definition: ModPiece.h:493
virtual Eigen::VectorXd ApplyHessianByFD(unsigned int const outWrt, unsigned int const inWrt1, unsigned int const inWrt2, std::vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &sens, Eigen::VectorXd const &vec)
Definition: ModPiece.cpp:448
const Eigen::VectorXi inputSizes
Definition: ModPiece.h:469
virtual Eigen::MatrixXd const & Jacobian(unsigned int const outputDimWrt, unsigned int const inputDimWrt, std::vector< Eigen::VectorXd > const &input)
Compute the Jacobian of this ModPiece.
Definition: ModPiece.cpp:128
Eigen::MatrixXd ApplyJacobianByFD(unsigned int outWrt, unsigned int inWrt, Args const &... args)
Definition: ModPiece.h:303
std::vector< Eigen::VectorXd > outputs
Definition: ModPiece.h:503
ModPiece(std::vector< int > const &inputSizes, std::vector< int > const &outputSizes)
Definition: ModPiece.cpp:9
virtual void EvaluateImpl(ref_vector< boost::any > const &inputs) override
User-implemented function that determines the behavior of this muq::Modeling::WorkPiece.
Definition: ModPiece.cpp:179
Eigen::VectorXd gradient
Definition: ModPiece.h:504
virtual double GetRunTime(const std::string &method="Evaluate") const override
Get the average run time for one of the implemented methods.
Definition: ModPiece.cpp:497
unsigned long int numJacActCalls
Definition: ModPiece.h:489
unsigned long int numHessActFDCalls
Definition: ModPiece.h:494
virtual void JacobianImpl(unsigned int const outputDimWrt, unsigned int const inputDimWrt, ref_vector< Eigen::VectorXd > const &input)
Definition: ModPiece.cpp:245
unsigned long int numJacCalls
Definition: ModPiece.h:488
virtual Eigen::VectorXd const & ApplyJacobian(unsigned int const outputDimWrt, unsigned int const inputDimWrt, std::vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &vec)
Apply the Jacobian of this ModPiece to a vector.
Definition: ModPiece.cpp:153
unsigned int fdWarnLevel
Definition: ModPiece.h:516
Eigen::VectorXd const & ApplyHessian(unsigned int outWrt, unsigned int inWrt1, unsigned int inWrt2, Eigen::VectorXd const &last, Eigen::VectorXd const &sens, Eigen::VectorXd const &vec)
Definition: ModPiece.h:245
unsigned long int numGradFDCalls
Definition: ModPiece.h:491
const Eigen::VectorXi outputSizes
Definition: ModPiece.h:472
void CheckInputs(ref_vector< Eigen::VectorXd > const &input, std::string const &funcName)
Definition: ModPiece.cpp:211
Eigen::MatrixXd JacobianByFD(unsigned int outWrt, unsigned int inWrt, Args const &... args)
Definition: ModPiece.h:297
bool ExistsInCache(ref_vector< Eigen::VectorXd > const &input) const
Definition: ModPiece.cpp:27
unsigned long int numJacFDCalls
Definition: ModPiece.h:492
std::vector< Eigen::VectorXd > ToStdVec(ref_vector< Eigen::VectorXd > const &input)
Definition: ModPiece.cpp:586
std::vector< Eigen::VectorXd > cacheInput
Definition: ModPiece.h:480
virtual unsigned long int GetNumCalls(const std::string &method="Evaluate") const override
get the number of times one of the implemented methods has been called.
Definition: ModPiece.cpp:535
virtual void ResetCallTime() override
Resets the number of call and times.
Definition: ModPiece.cpp:520
unsigned long int numGradCalls
Definition: ModPiece.h:487
Eigen::VectorXd hessAction
Definition: ModPiece.h:507
Eigen::VectorXd jacobianAction
Definition: ModPiece.h:505
virtual void ApplyHessianImpl(unsigned int const outWrt, unsigned int const inWrt1, unsigned int const inWrt2, ref_vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &sens, Eigen::VectorXd const &vec)
Definition: ModPiece.cpp:436
unsigned long int numHessActCalls
Definition: ModPiece.h:490
Base class for MUQ's modelling envronment.
Definition: WorkPiece.h:40
unsigned long int numEvalCalls
Definition: WorkPiece.h:573
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
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
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