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())){};
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){};
22 std::vector<Eigen::VectorXd>
const&
ModPiece::Evaluate(std::vector<Eigen::VectorXd>
const& input)
35 for(
int i=0; i<input.size(); ++i){
36 if(input.at(i).get().size()!=
cacheInput.at(i).size()){
42 for(
int i=0; i<input.size(); ++i){
43 Eigen::VectorXd
const& inVec = input.at(i).get();
45 if(std::abs(inVec(j)-
cacheInput[i](j))>std::numeric_limits<double>::epsilon()){
66 for(
int i=0; i<input.size(); ++i)
73 auto start_time = std::chrono::high_resolution_clock::now();
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());
84 unsigned int const inputDimWrt,
85 std::vector<Eigen::VectorXd>
const& input,
86 Eigen::VectorXd
const& sensitivity)
93 unsigned int const inputDimWrt,
95 Eigen::VectorXd
const& sensitivity)
100 auto start_time = std::chrono::high_resolution_clock::now();
102 GradientImpl(outputDimWrt, inputDimWrt, input, sensitivity);
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());
112 unsigned int const inputDimWrt,
113 std::vector<Eigen::VectorXd>
const& input,
114 Eigen::VectorXd
const& sensitivity)
120 unsigned int const inputDimWrt,
122 Eigen::VectorXd
const& sensitivity)
125 return JacobianByFD(outputDimWrt,inputDimWrt, input).transpose()*sensitivity;
129 unsigned int const inputDimWrt,
130 std::vector<Eigen::VectorXd>
const& input)
136 unsigned int const inputDimWrt,
142 auto start_time = std::chrono::high_resolution_clock::now();
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());
154 unsigned int const inputDimWrt,
155 std::vector<Eigen::VectorXd>
const& input,
156 Eigen::VectorXd
const& vec)
162 unsigned int const inputDimWrt,
164 Eigen::VectorXd
const& vec)
169 auto start_time = std::chrono::high_resolution_clock::now();
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());
181 for(
int i=0; i<inputs.size(); ++i) {
182 eigenInputs.push_back( std::cref(boost::any_cast<Eigen::VectorXd const&>(inputs.at(i))) );
188 for(
int i=0; i<
outputs.size(); ++i)
213 bool errorOccured =
false;
221 for(
int i=0; i<std::min<int>(input.size(),
inputSizes.size()); ++i){
222 if(input.at(i).get().size() !=
inputSizes(i)){
230 msg =
"\nError evaluating " + className +
"::" + funcName +
":\n" + msg;
238 unsigned int const inputDimWrt,
240 Eigen::VectorXd
const& sensitivity)
242 gradient =
Jacobian(outputDimWrt, inputDimWrt, input).transpose() * sensitivity;
246 unsigned int const inputDimWrt,
251 std::cout <<
"WARNING: In " << className <<
", defaulting to finite difference approximation of JacobianImpl." << std::endl;
254 std::stringstream msg;
255 msg <<
"Class " << className <<
" attempted to use a finite difference approximation of ApplyJacobianImpl.";
256 throw std::runtime_error(msg.str());
263 unsigned int const inputDimWrt,
265 Eigen::VectorXd
const& vec)
269 std::cout <<
"WARNING: In " << className <<
", defaulting to finite difference approximation of ApplyJacobianImpl." << std::endl;
272 std::stringstream msg;
273 msg <<
"Class " << className <<
" attempted to use a finite difference approximation of ApplyJacobianImpl.";
274 throw std::runtime_error(msg.str());
291 unsigned int const inputDimWrt,
292 std::vector<Eigen::VectorXd>
const& input)
298 unsigned int const inputDimWrt,
303 Eigen::VectorXd f0 =
Evaluate(input).at(outputDimWrt);
307 Eigen::VectorXd newInput(input.at(inputDimWrt).get());
312 eps = std::max(1
e-8, 1
e-10*std::abs(input.at(inputDimWrt)(i)));
314 newInput(i) = input.at(inputDimWrt)(i) + eps;
315 newInputVec.at(inputDimWrt) = std::cref(newInput);
317 f =
Evaluate(newInputVec).at(outputDimWrt);
319 jac.col(i) = (f-f0)/eps;
321 newInput(i) = input.at(inputDimWrt)(i);
328 unsigned int const inputDimWrt,
329 std::vector<Eigen::VectorXd>
const& input,
330 Eigen::VectorXd
const& vec)
335 unsigned int const inputDimWrt,
337 Eigen::VectorXd
const& vec)
341 const double eps = 1
e-4;
342 double vecNorm = vec.norm();
343 const Eigen::VectorXd stepDir = vec/vecNorm;
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);
350 newInput = input.at(inputDimWrt).get() + 0.5*eps*stepDir;
351 newInputVec.at(inputDimWrt) = std::cref(newInput);
353 Eigen::VectorXd f =
Evaluate(newInputVec).at(outputDimWrt);
355 return vecNorm*(f-f0)/eps;
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)
369 unsigned int const inWrt1,
370 unsigned int const inWrt2,
372 Eigen::VectorXd
const& sens,
373 Eigen::VectorXd
const& vec)
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() <<
"\"";
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() <<
"\"";
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);
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) <<
"\"";
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) <<
"\"";
426 auto start_time = std::chrono::high_resolution_clock::now();
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());
437 unsigned int const inWrt1,
438 unsigned int const inWrt2,
440 Eigen::VectorXd
const& sens,
441 Eigen::VectorXd
const& vec)
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)
459 unsigned int const inWrt1,
460 unsigned int const inWrt2,
462 Eigen::VectorXd
const& sens,
463 Eigen::VectorXd
const& vec)
467 const double stepSize = std::max(1
e-4, 1
e-8*vec.norm());
469 Eigen::VectorXd grad1, grad2;
475 Eigen::VectorXd x2 = input.at(inWrt2).get() - 0.5*stepSize * vec;
476 input2.at(inWrt2) = std::cref(x2);
478 grad1 =
Gradient(outWrt, inWrt1, input2, sens);
480 x2 = input.at(inWrt2).get() + 0.5*stepSize * vec;
481 input2.at(inWrt2) = std::cref(x2);
482 grad2 =
Gradient(outWrt, inWrt1, input2, sens);
486 Eigen::VectorXd sens2 = sens - 0.5*stepSize * vec;
487 grad1 =
Gradient(outWrt, inWrt1, input, sens2);
489 sens2 = sens + 0.5*stepSize * vec;
490 grad2 =
Gradient(outWrt, inWrt1, input, sens2);
493 return (grad2 - grad1)/stepSize;
499 const double toMilli = 1
e-6;
501 if (method.compare(
"Evaluate") == 0) {
503 }
else if (method.compare(
"Gradient") == 0) {
505 }
else if (method.compare(
"Jacobian") == 0) {
507 }
else if (method.compare(
"JacobianAction") == 0) {
510 }
else if (method.compare(
"HessianAction") == 0) {
513 assert(method.compare(
"Evaluate") == 0 || method.compare(
"Gradient") == 0 || method.compare(
514 "Jacobian") == 0 || method.compare(
"JacobianAction") == 0 || method.compare(
"HessianAction") == 0);
537 if (method.compare(
"Evaluate") == 0) {
539 }
else if (method.compare(
"Gradient") == 0) {
541 }
else if (method.compare(
"Jacobian") == 0) {
543 }
else if (method.compare(
"JacobianAction") == 0) {
545 }
else if (method.compare(
"HessianAction") == 0) {
547 }
else if (method.compare(
"GradientFD") == 0) {
549 }
else if (method.compare(
"JacobianFD") == 0) {
551 }
else if (method.compare(
"JacobianActionFD") == 0) {
553 }
else if (method.compare(
"HessianActionFD") == 0) {
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));
587 std::vector<Eigen::VectorXd> newIns(input.size());
589 for (
int i=0; i<input.size(); ++i)
590 newIns.at(i) = input.at(i).get();
Provides an abstract interface for defining vector-valued model components.
virtual void GradientImpl(unsigned int const outputDimWrt, unsigned int const inputDimWrt, ref_vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &sensitivity)
virtual void ApplyJacobianImpl(unsigned int const outputDimWrt, unsigned int const inputDimWrt, ref_vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &vec)
virtual Eigen::VectorXd GradientByFD(unsigned int const outputDimWrt, unsigned int const inputDimWrt, std::vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &sensitivity)
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 .
unsigned long int numJacActFDCalls
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)
const Eigen::VectorXi inputSizes
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.
Eigen::MatrixXd ApplyJacobianByFD(unsigned int outWrt, unsigned int inWrt, Args const &... args)
std::vector< Eigen::VectorXd > outputs
ModPiece(std::vector< int > const &inputSizes, std::vector< int > const &outputSizes)
virtual void EvaluateImpl(ref_vector< boost::any > const &inputs) override
User-implemented function that determines the behavior of this muq::Modeling::WorkPiece.
virtual double GetRunTime(const std::string &method="Evaluate") const override
Get the average run time for one of the implemented methods.
unsigned long int numJacActCalls
unsigned long int numHessActFDCalls
virtual void JacobianImpl(unsigned int const outputDimWrt, unsigned int const inputDimWrt, ref_vector< Eigen::VectorXd > const &input)
unsigned long int numJacCalls
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.
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)
unsigned long int numGradFDCalls
const Eigen::VectorXi outputSizes
void CheckInputs(ref_vector< Eigen::VectorXd > const &input, std::string const &funcName)
Eigen::MatrixXd JacobianByFD(unsigned int outWrt, unsigned int inWrt, Args const &... args)
bool ExistsInCache(ref_vector< Eigen::VectorXd > const &input) const
unsigned long int numJacFDCalls
std::vector< Eigen::VectorXd > ToStdVec(ref_vector< Eigen::VectorXd > const &input)
std::vector< Eigen::VectorXd > cacheInput
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.
virtual void ResetCallTime() override
Resets the number of call and times.
unsigned long int numGradCalls
Eigen::VectorXd hessAction
Eigen::VectorXd jacobianAction
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)
unsigned long int numHessActCalls
Base class for MUQ's modelling envronment.
unsigned long int numEvalCalls
static ref_vector< const boost::any > ToRefVector(std::vector< boost::any > const &anyVec)
Create vector of references from a vector of boost::any's.
std::vector< boost::any > outputs
The outputs.
std::vector< boost::any > const & Evaluate()
Evaluate this muq::Modeling::WorkPiece in the case that there are no inputs.
Exception to throw when matrices, vectors, or arrays are the wrong size.
std::vector< std::reference_wrapper< const T > > ref_vector
A vector of references to something ...
std::string demangle(const char *name)
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values