10 #include <boost/range/adaptor/reversed.hpp>
11 #include <boost/graph/topological_sort.hpp>
21 std::vector<std::shared_ptr<ConstantVector> >
const& constantPiecesIn,
22 std::vector<std::string>
const& inputNames,
23 std::shared_ptr<ModPiece> outputPieceIn) :
ModPiece(ConstructInputSizes(constantPiecesIn),
24 outputPieceIn->outputSizes),
26 outputID(outputPieceIn->ID()),
27 outputPiece(outputPieceIn),
28 constantPieces(constantPiecesIn) {
32 boost::topological_sort(
wgraph->graph, std::front_inserter(
runOrder));
41 for(
unsigned int i=0; i<
numInputs; ++i ) {
44 boost::graph_traits<Graph>::vertex_iterator
v, v_end;
45 boost::tie(
v, v_end) = vertices(
wgraph->graph);
52 filtered_graphs[i] = std::make_shared<boost::filtered_graph<Graph, DependentEdgePredicate, DependentPredicate> >(
wgraph->graph, eFilt, nFilt);
70 unsigned int const inputDimWrt)
79 std::vector<boost::graph_traits<Graph>::vertex_descriptor> inputNodes(
constantPieces.size());
82 inputNames.at(
constantPieces.size()) = outputName +
"_Sensitivity";
84 bool needsFinalSum =
false;
88 auto piece =
wgraph->graph[*node]->piece;
91 if(placeholderInd>=0){
92 auto pieceMod = std::dynamic_pointer_cast<ModPiece>(piece);
94 gradGraph.
AddNode(std::make_shared<IdentityOperator>(pieceMod->outputSizes(0)),
wgraph->graph[*node]->name);
95 inputNames.at(placeholderInd) =
wgraph->graph[*node]->name;
96 inputNodes.at(placeholderInd) = *node;
101 for(
auto es = in_edges(*node,
wgraph->graph); es.first!=es.second; ++es.first){
102 auto source = boost::source(*es.first,
wgraph->graph);
110 outputName+
"_Sensitivity");
115 std::string baseName =
wgraph->graph[node]->name;
117 auto piece = std::dynamic_pointer_cast<ModPiece>(filtGraph[node]->piece);
122 std::vector<std::vector<std::pair<boost::graph_traits<boost::filtered_graph<Graph, DependentEdgePredicate, DependentPredicate>>::vertex_descriptor,
unsigned int>>> outEdges(piece->outputSizes.size());
123 for(
auto eout = out_edges(node, filtGraph); eout.first!=eout.second; ++eout.first){
124 auto target = boost::target(*eout.first, filtGraph);
125 outEdges.at( filtGraph[*eout.first]->outputDim ).push_back(std::make_pair(target, filtGraph[*eout.first]->inputDim ));
129 std::vector<unsigned int> edgeCounts(outEdges.size());
130 for(
unsigned int outInd=0; outInd<outEdges.size(); ++outInd){
133 edgeCounts[outInd] = 0;
134 for(
unsigned int i = 0; i<outEdges.at(outInd).size(); ++i){
135 auto mod = std::dynamic_pointer_cast<ModPiece>(
wgraph->graph[outEdges.at(outInd).at(i).first]->piece);
137 edgeCounts[outInd] += mod->outputSizes.size();
141 if(edgeCounts[outInd]>1){
143 std::stringstream sumName;
144 sumName << baseName <<
"[" << outInd <<
"]_SensitivitySum";
145 gradGraph.
AddNode(std::make_shared<SumPiece>(piece->outputSizes(outInd), edgeCounts[outInd]), sumName.str());
147 if(baseName==inputNames.at(inputDimWrt)){
148 needsFinalSum =
true;
154 for(
auto e =in_edges(node, filtGraph);
e.first!=
e.second; ++
e.first ) {
155 auto source = boost::source(*
e.first,filtGraph);
159 std::stringstream nodeName;
161 unsigned int inDim = filtGraph[*
e.first]->inputDim;
162 auto gradPiece = std::make_shared<GradientPiece>(piece, outputDimWrt, inDim);
163 nodeName << filtGraph[
adjointRunOrders[inputDimWrt][0]]->name <<
"_Gradient[" << outputDimWrt <<
"," << inDim <<
"]";
165 gradGraph.
AddNode(gradPiece, nodeName.str());
166 }
catch(
const std::logic_error&){}
168 gradGraph.
AddEdge(outputName +
"_Sensitivity", 0 , nodeName.str(), gradPiece->inputSizes.size()-1);
171 for(
auto e2 =in_edges(node,
wgraph->graph); e2.first!=e2.second; ++e2.first ) {
172 auto source = boost::source(*e2.first,
wgraph->graph);
174 nodeName.str(),
wgraph->graph[*e2.first]->inputDim);
180 for(
unsigned int outInd=0; outInd<outEdges.size(); ++outInd){
182 unsigned int inDim = filtGraph[*
e.first]->inputDim;
183 auto gradPiece = std::make_shared<GradientPiece>(piece, outInd, inDim);
185 std::stringstream nodeName;
186 nodeName << filtGraph[node]->name <<
"_Gradient[" << outInd <<
"," << inDim <<
"]";
187 gradGraph.
AddNode(gradPiece, nodeName.str());
190 for(
auto e2 =in_edges(node,
wgraph->graph); e2.first!=e2.second; ++e2.first ) {
191 auto source = boost::source(*e2.first,
wgraph->graph);
193 nodeName.str(),
wgraph->graph[*e2.first]->inputDim);
203 if(edgeCounts[outInd]>1){
204 std::stringstream sumName;
205 sumName << baseName <<
"[" << outInd <<
"]_SensitivitySum";
208 unsigned int edgeInd = 0;
209 for(
unsigned int i = 0; i<outEdges.at(outInd).size(); ++i){
210 auto nextNode = filtGraph[outEdges.at(outInd).at(i).first];
211 auto nextMod = std::dynamic_pointer_cast<ModPiece>(nextNode->piece);
212 int nextNumOutputs = nextMod->outputSizes.size();
214 for(
unsigned int nextOutInd=0; nextOutInd<nextNumOutputs; ++nextOutInd){
215 std::stringstream otherNodeName;
216 otherNodeName << nextNode->name <<
"_Gradient[" << nextOutInd <<
"," << outEdges.at(outInd).at(i).second <<
"]";
217 gradGraph.
AddEdge(otherNodeName.str(),0, sumName.str(), edgeInd);
223 gradGraph.
AddEdge(sumName.str(), 0, nodeName.str(), gradPiece->inputSizes.size()-1);
226 }
else if(outEdges.at(outInd).size()>0){
227 auto es=out_edges(outEdges.at(outInd).at(0).first, filtGraph);
229 std::stringstream otherNodeName;
230 otherNodeName << filtGraph[
adjointRunOrders[inputDimWrt][0]]->name <<
"_Gradient[" << outputDimWrt <<
"," << outEdges.at(outInd).at(0).second <<
"]";
232 gradGraph.
AddEdge(otherNodeName.str(), 0, nodeName.str(), gradPiece->inputSizes.size()-1);
234 }
else if(es.first != es.second){
235 auto nextNode = filtGraph[outEdges.at(outInd).at(0).first];
237 std::stringstream otherNodeName;
238 otherNodeName << nextNode->name <<
"_Gradient[" << filtGraph[*es.first]->outputDim <<
"," << outEdges.at(outInd).at(0).second <<
"]";
240 gradGraph.
AddEdge(otherNodeName.str(), 0, nodeName.str(), gradPiece->inputSizes.size()-1);
251 std::string outNodeName;
254 outNodeName = inputNames.at(inputDimWrt) +
"[0]_SensitivitySum";
256 for(
auto eout=out_edges(inputNodes.at(inputDimWrt), filtGraph); eout.first!=eout.second; ++eout.first )
258 auto target = boost::target(*eout.first,filtGraph);
259 auto targetPiece = std::dynamic_pointer_cast<ModPiece>(
wgraph->graph[target]->piece);
262 for(
unsigned int otherOutInd=0; otherOutInd<targetPiece->outputSizes.size(); ++otherOutInd){
263 std::stringstream otherName;
264 otherName <<
wgraph->graph[target]->name <<
"_Gradient[" << otherOutInd <<
"," <<
wgraph->graph[*eout.first]->inputDim <<
"]";
265 gradGraph.
AddEdge(otherName.str(), 0, outNodeName, otherOutInd);
274 for(
auto vs = boost::vertices(gradGraph.
graph); vs.first!=vs.second; ++vs.first){
275 auto pieceMod = std::dynamic_pointer_cast<ModPiece>(gradGraph.
graph[*vs.first]->piece);
277 if(out_degree(*vs.first, gradGraph.
graph) <pieceMod->outputSizes.size()){
278 outNodeName = gradGraph.
graph[*vs.first]->name;
289 unsigned int const inputDimWrt)
301 auto piece =
wgraph->graph[*node]->piece;
304 if(placeholderInd>=0){
305 auto pieceMod = std::dynamic_pointer_cast<ModPiece>(piece);
307 jacGraph.
AddNode(std::make_shared<IdentityOperator>(pieceMod->outputSizes(0)),
wgraph->graph[*node]->name);
308 inputNames.at(placeholderInd) =
wgraph->graph[*node]->name;
314 for(
auto es = in_edges(*node,
wgraph->graph); es.first!=es.second; ++es.first){
315 auto source = boost::source(*es.first,
wgraph->graph);
322 jacGraph.
AddNode(std::make_shared<IdentityOperator>(
inputSizes(inputDimWrt)), inputNames.at(inputDimWrt) +
"_Vec");
325 std::unordered_map<std::string, std::vector<std::string>> cumNames;
328 std::string baseName =
wgraph->graph[*node]->name;
330 auto piece = std::dynamic_pointer_cast<ModPiece>(filtGraph[*node]->piece);
332 int inDegree = boost::in_degree(*node, filtGraph);
333 int outDegree = boost::out_degree(*node, filtGraph);
335 auto modCast = std::dynamic_pointer_cast<ModPiece>(filtGraph[*node]->piece);
341 cumNames[baseName] = std::vector<std::string>(out_degree(*node,filtGraph));
342 for(
auto eout = boost::out_edges(*node, filtGraph); eout.first!=eout.second; ++eout.first){
344 std::stringstream jacName;
345 jacName << baseName <<
"_CumulativeJacobian[" << filtGraph[*eout.first]->outputDim <<
"]";
346 cumNames[baseName].at(filtGraph[*eout.first]->outputDim) = jacName.str();
348 if(!jacGraph.
HasNode(jacName.str()))
349 jacGraph.
AddNode(std::make_shared<SumPiece>(modCast->outputSizes(filtGraph[*eout.first]->outputDim),inDegree), jacName.str());
350 }
else if(inDegree==1){
351 std::stringstream jacName;
352 jacName << baseName <<
"_Jacobian[" << filtGraph[*eout.first]->outputDim <<
",0]";
353 cumNames[baseName].at(filtGraph[*eout.first]->outputDim) = jacName.str();
358 for(
auto ein=boost::in_edges(*node, filtGraph); ein.first!=ein.second; ++ein.first){
361 std::stringstream jacName;
362 jacName << baseName <<
"_Jacobian[" << outputDimWrt <<
"," << filtGraph[*ein.first]->inputDim <<
"]";
363 auto jacPiece = std::make_shared<JacobianPiece>(piece, outputDimWrt, filtGraph[*ein.first]->inputDim);
365 jacGraph.
AddNode(jacPiece, jacName.str());
368 for(
auto es=boost::in_edges(*node,
wgraph->graph); es.first!=es.second; ++es.first){
369 auto source = boost::source(*es.first,
wgraph->graph);
370 jacGraph.
AddEdge(
wgraph->graph[source]->name,
wgraph->graph[*es.first]->outputDim, jacName.str(),
wgraph->graph[*es.first]->inputDim);
373 auto source = boost::source(*ein.first,filtGraph);
374 if(filtGraph[source]->
name == inputNames.at(inputDimWrt)){
375 jacGraph.
AddEdge(inputNames.at(inputDimWrt)+
"_Vec", 0, jacName.str(), jacPiece->inputSizes.size()-1);
376 }
else if(boost::in_degree(source,filtGraph)>0){
377 jacGraph.
AddEdge(cumNames[filtGraph[source]->
name].at(filtGraph[*ein.first]->outputDim), 0, jacName.str(), jacPiece->inputSizes.size()-1);
384 for(
auto eout = boost::out_edges(*node, filtGraph); eout.first!=eout.second; ++eout.first){
386 std::stringstream jacName;
387 jacName << baseName <<
"_Jacobian[" << filtGraph[*eout.first]->outputDim <<
"," << filtGraph[*ein.first]->inputDim <<
"]";
391 auto jacPiece = std::make_shared<JacobianPiece>(piece, filtGraph[*eout.first]->outputDim, filtGraph[*ein.first]->inputDim);
392 jacGraph.
AddNode(jacPiece, jacName.str());
395 for(
auto es=boost::in_edges(*node,
wgraph->graph); es.first!=es.second; ++es.first){
396 auto source = boost::source(*es.first,
wgraph->graph);
397 jacGraph.
AddEdge(
wgraph->graph[source]->name,
wgraph->graph[*es.first]->outputDim, jacName.str(),
wgraph->graph[*es.first]->inputDim);
401 auto source = boost::source(*ein.first,filtGraph);
402 if(filtGraph[source]->
name == inputNames.at(inputDimWrt)){
403 jacGraph.
AddEdge(inputNames.at(inputDimWrt)+
"_Vec", 0, jacName.str(), jacPiece->inputSizes.size()-1);
404 }
else if(boost::in_degree(source,filtGraph)>0){
405 jacGraph.
AddEdge(cumNames[filtGraph[source]->
name].at(filtGraph[*ein.first]->outputDim), 0, jacName.str(), jacPiece->inputSizes.size()-1);
407 }
catch(
const std::logic_error&
e){
415 for(
auto eout = boost::out_edges(*node, filtGraph); eout.first!=eout.second; ++eout.first){
417 std::stringstream cumName;
418 cumName << baseName <<
"_CumulativeJacobian[" << filtGraph[*eout.first]->outputDim <<
"]";
421 unsigned int tempInd = 0;
422 for(
auto ein = boost::in_edges(*node, filtGraph); ein.first!=ein.second; ++ein.first){
423 std::stringstream jacName;
424 jacName << baseName <<
"_Jacobian[" << filtGraph[*eout.first]->outputDim <<
"," << filtGraph[*ein.first]->inputDim <<
"]";
425 jacGraph.
AddEdge(jacName.str(),0, cumName.str(), tempInd);
433 unsigned int tempInd = 0;
436 std::stringstream jacName;
437 jacName << baseName <<
"_CumulativeJacobian[" << outputDimWrt <<
"]";
438 jacGraph.
AddNode(std::make_shared<SumPiece>(modCast->outputSizes(outputDimWrt), inDegree), jacName.str());
440 for(
auto ein = boost::in_edges(*node, filtGraph); ein.first!=ein.second; ++ein.first){
441 std::stringstream otherName;
442 otherName << baseName <<
"_Jacobian[" << outputDimWrt <<
"," << filtGraph[*ein.first]->inputDim <<
"]";
443 jacGraph.
AddEdge(otherName.str(), 0, jacName.str(), tempInd);
452 std::string outNodeName;
453 for(
auto vs = boost::vertices(jacGraph.
graph); vs.first!=vs.second; ++vs.first){
454 auto pieceMod = std::dynamic_pointer_cast<ModPiece>(jacGraph.
graph[*vs.first]->piece);
456 if(out_degree(*vs.first, jacGraph.
graph) <pieceMod->outputSizes.size()){
457 outNodeName = jacGraph.
graph[*vs.first]->name;
463 inputNames.at(
constantPieces.size()) = inputNames.at(inputDimWrt) +
"_Vec";
469 Eigen::VectorXi sizes(constantPiecesIn.size());
470 for(
int i=0; i<constantPiecesIn.size(); ++i){
471 sizes(i) = constantPiecesIn.at(i)->outputSizes(0);
472 assert(constantPiecesIn.at(i)->outputSizes.size()==1);
478 unsigned int const inWrt1,
479 unsigned int const inWrt2,
481 Eigen::VectorXd
const& sens,
482 Eigen::VectorXd
const& vec)
485 newInputs.push_back( std::cref(sens));
486 newInputs.push_back( std::cref(vec));
488 std::shared_ptr<ModGraphPiece> hessGraph;
489 std::tuple<unsigned int, unsigned int, unsigned int> wrts = std::make_tuple(outWrt,inWrt1,inWrt2);
499 unsigned int const inputDimWrt,
501 Eigen::VectorXd
const& vec)
504 newInputs.push_back( std::cref(vec));
507 std::pair<unsigned int, unsigned int> indexPair = std::make_pair(outputDimWrt, inputDimWrt);
526 for(
int i=0; i<
outputs.size(); ++i) {
532 unsigned int const inputDimWrt,
534 Eigen::VectorXd
const& sensitivity) {
537 newInputs.push_back( std::cref(sensitivity));
540 std::pair<unsigned int, unsigned int> indexPair = std::make_pair(outputDimWrt, inputDimWrt);
551 unsigned int const wrtIn,
561 std::map<unsigned int, std::vector<Eigen::MatrixXd> > jacMap;
566 std::shared_ptr<ModPiece> nodePiece = std::dynamic_pointer_cast<ModPiece>(
filtered_graphs[wrtIn]->
operator[](node)->piece);
570 const unsigned int nodeID = nodePiece->ID();
573 jacMap[nodeID] = std::vector<Eigen::MatrixXd>(nodePiece->outputSizes.size());
576 const std::vector<std::tuple<unsigned int, unsigned int, unsigned int> > & requiredOutNodes =
RequiredOutputs(node, wrtIn, wrtOut);
579 std::vector<unsigned int> requiredOuts;
580 requiredOuts.reserve(requiredOutNodes.size());
581 for(
auto out : requiredOutNodes ) {
582 auto it = std::find(requiredOuts.begin(), requiredOuts.end(), std::get<1>(out));
583 if( it==requiredOuts.end() ) {
584 requiredOuts.push_back(std::get<1>(out));
589 for(
int i=0; i<requiredOuts.size(); ++i)
590 jacMap[nodeID].at(requiredOuts.at(i)) = Eigen::MatrixXd::Zero(nodePiece->outputSizes(requiredOuts.at(i)),
inputSizes(wrtIn));
593 const std::vector<std::tuple<unsigned int, unsigned int, unsigned int> >& requiredIns =
RequiredInputs(node, wrtIn);
596 if(requiredIns.size()==0){
597 jacMap[nodeID][0] = Eigen::MatrixXd::Identity(nodePiece->outputSizes(0), nodePiece->outputSizes(0));
598 assert(jacMap[nodeID].size()==1);
605 for(
auto out : requiredOuts ) {
607 for(
auto in : requiredIns )
608 jacMap[nodeID][out] += nodePiece->Jacobian(out, std::get<2>(in), ins) * jacMap[std::get<0>(in)][std::get<1>(in)];
740 for(
unsigned int i=0; i<inputs.size(); ++i ) {
745 std::map<unsigned int, std::vector<std::pair<unsigned int, unsigned int> > >
ModGraphPiece::InputNodes(boost::graph_traits<Graph>::vertex_descriptor
const& node)
const {
747 std::map<unsigned int, std::vector<std::pair<unsigned int, unsigned int> > > inMap;
750 boost::graph_traits<Graph>::in_edge_iterator
e, e_end;
751 for( tie(
e, e_end)=boost::in_edges(node,
wgraph->graph);
e!=e_end; ++
e ) {
753 const unsigned int id =
wgraph->graph[boost::source(*
e,
wgraph->graph)]->piece->ID();
754 const unsigned int inNum =
wgraph->graph[*
e]->inputDim;
755 const unsigned int outNum =
wgraph->graph[*
e]->outputDim;
758 auto it = inMap.find(
id);
760 if( it==inMap.end() ) {
762 inMap[
id] = std::vector<std::pair<unsigned int, unsigned int> >(1, std::pair<unsigned int, unsigned int>(inNum, outNum));
765 inMap[
id].push_back(std::pair<unsigned int, unsigned int>(inNum, outNum));
783 auto wPiece =
wgraph->GetPiece(it);
784 auto currPiece = std::dynamic_pointer_cast<ModPiece>(wPiece);
790 std::vector<boost::any> anyIns(ins.size());
791 for(
int i=0; i<ins.size(); ++i)
792 anyIns.at(i) = boost::any(ins.at(i));
794 std::vector<boost::any>
const& anyOut = wPiece->Evaluate(anyIns);
796 for(
int i=0; i<anyOut.size(); ++i){
797 Eigen::VectorXd
const& temp =
AnyConstCast(anyOut.at(i));
798 output.push_back(std::cref(temp));
812 const int numIns =
wgraph->GetPiece(node)->numInputs;
815 const std::map<unsigned int, std::vector<std::pair<unsigned int, unsigned int> > >& inMap =
InputNodes(node);
817 Eigen::VectorXd empty;
821 for(
auto edge : inMap ) {
823 for(
auto in_out : edge.second ) {
824 ins[in_out.first] =
valMap.at(edge.first)[in_out.second];
831 std::vector<std::tuple<unsigned int, unsigned int, unsigned int> >
ModGraphPiece::RequiredOutputs(boost::graph_traits<FilteredGraph>::vertex_descriptor
const& node,
unsigned int const wrtIn,
unsigned int const wrtOut)
const {
833 const unsigned int nodeID =
filtered_graphs[wrtIn]->operator[](node)->piece->ID();
836 std::vector<std::tuple<unsigned int, unsigned int, unsigned int> > requiredOuts;
840 requiredOuts.push_back(std::tuple<unsigned int, unsigned int, unsigned int>(nodeID, wrtOut, wrtIn));
846 boost::graph_traits<FilteredGraph>::out_edge_iterator eout, eout_end;
847 for( tie(eout, eout_end)=boost::out_edges(node, *
filtered_graphs[wrtIn]); eout!=eout_end; ++eout ) {
850 const unsigned int outNum =
filtered_graphs[wrtIn]->operator[](*eout)->outputDim;
851 const unsigned int inNum =
filtered_graphs[wrtIn]->operator[](*eout)->inputDim;
854 auto it = std::find(requiredOuts.begin(), requiredOuts.end(), std::tuple<unsigned int, unsigned int, unsigned int>(
id, outNum, inNum));
855 if( it==requiredOuts.end() ) {
856 requiredOuts.push_back(std::tuple<unsigned int, unsigned int, unsigned int>(
id, outNum, inNum));
863 std::vector<std::tuple<unsigned int, unsigned int, unsigned int> >
ModGraphPiece::RequiredInputs(boost::graph_traits<FilteredGraph>::vertex_descriptor
const& node,
unsigned int const wrtIn)
const {
865 const int numIns =
filtered_graphs[wrtIn]->operator[](node)->piece->numInputs;
867 std::vector<std::tuple<unsigned int, unsigned int, unsigned int> > requiredIns;
868 requiredIns.reserve(numIns);
871 boost::graph_traits<FilteredGraph>::in_edge_iterator ein, ein_end;
872 for( tie(ein, ein_end)=boost::in_edges(node, *
filtered_graphs[wrtIn]); ein!=ein_end; ++ein ) {
875 const unsigned int outNum =
filtered_graphs[wrtIn]->operator[](*ein)->outputDim;
876 const unsigned int inNum =
filtered_graphs[wrtIn]->operator[](*ein)->inputDim;
879 requiredIns.push_back(std::tuple<unsigned int, unsigned int, unsigned int>(
id, outNum, inNum));
889 auto subGraph =
wgraph->Clone();
891 subGraph->RemoveNode(
wgraph->GetName(piece));
893 return subGraph->CreateModPiece(nodeName);
899 std::vector<std::shared_ptr<ConstantVector>> otherIns = otherPiece->GetConstantPieces();
900 std::shared_ptr<WorkGraph> otherGraph = otherPiece->GetGraph();
902 std::vector<int>
outputs(otherIns.size());
904 for(
int i=0; i<otherIns.size(); ++i)
907 std::string constName = otherGraph->GetName( otherIns.at(i) );
908 std::string sharedName = otherGraph->GetChildren( constName ).at(0);
911 if(
wgraph->HasNode(sharedName)){
912 int inputIndex = otherGraph->GetEdges( constName, sharedName ).at(0).second;
914 std::string upstreamName =
wgraph->GetParent( sharedName, inputIndex);
915 assert(upstreamName.size()>0);
Determine if the source of an edge is downstream of an input.
This class keeps track of which nodes are downstream of a specified input.
std::unordered_map< unsigned int, ref_vector< Eigen::VectorXd > > valMap
A the map from each node's muq::Modeling::WorkPiece::ID to its outputs.
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) override
virtual void JacobianImpl(unsigned int const outputDimWrt, unsigned int const inputDimWrt, ref_vector< Eigen::VectorXd > const &input) override
Compute the Jacobian for this muq::Modeling::WorkGraphPiece using the chain rule.
void SetInputs(ref_vector< Eigen::VectorXd > const &inputs)
Set the inputs.
unsigned int outputID
The ID of the WorkPiece corresponding to the output node.
std::vector< std::tuple< unsigned int, unsigned int, unsigned int > > RequiredOutputs(boost::graph_traits< FilteredGraph >::vertex_descriptor const &node, unsigned int const wrtIn, unsigned int wrtOut) const
Get the required outputs for a node in one of the filtered graphs.
virtual void EvaluateImpl(ref_vector< Eigen::VectorXd > const &inputs) override
Evaluate each muq::Modeling::WorkPiece in the graph.
std::vector< std::shared_ptr< ConstantVector > > constantPieces
The muq::Modeling::ConstantVector's that store the inputs.
void FillOutputMap()
Fill the map from each node's muq::Modeling::WorkPiece::ID to its outputs.
std::shared_ptr< WorkGraph > wgraph
The WorkGraph associated with this WorkGraphPiece.
virtual void GradientImpl(unsigned int const outputDimWrt, unsigned int const inputDimWrt, ref_vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &sensitivity) override
Compute the action of the Jacobian transpose for this muq::Modeling::WorkGraphPiece using the chain r...
int GetInputIndex(std::shared_ptr< WorkPiece > const &piece) const
std::shared_ptr< ModGraphPiece > JacobianGraph(unsigned int const outputDimWrt, unsigned int const inputDimWrt)
std::map< std::pair< unsigned int, unsigned int >, std::shared_ptr< ModGraphPiece > > gradientPieces
std::deque< boost::graph_traits< Graph >::vertex_descriptor > runOrder
Run order computed during construction (input->output order)
static Eigen::VectorXi ConstructInputSizes(std::vector< std::shared_ptr< ConstantVector > > const &constantPiecesIn)
std::vector< std::tuple< unsigned int, unsigned int, unsigned int > > RequiredInputs(boost::graph_traits< FilteredGraph >::vertex_descriptor const &node, unsigned int const wrtIn) const
Get the required inputs for a node in one of the filtered graphs.
std::map< std::pair< unsigned int, unsigned int >, std::shared_ptr< ModGraphPiece > > jacobianPieces
std::vector< std::deque< boost::graph_traits< Graph >::vertex_descriptor > > adjointRunOrders
ref_vector< Eigen::VectorXd > GetNodeInputs(boost::graph_traits< Graph >::vertex_descriptor node) const
Get the inputs from muq::Modeling::WorkGraphPiece::valMap to a specified node in the graph.
virtual void ApplyJacobianImpl(unsigned int const outputDimWrt, unsigned int const inputDimWrt, ref_vector< Eigen::VectorXd > const &input, Eigen::VectorXd const &vec) override
Compute the action of the Jacobian for this muq::Modeling::WorkGraphPiece using the chain rule.
std::shared_ptr< ModGraphPiece > GetSubModel(std::string const &nodeName) const
Returns another ModGraphPiece containing only part of the graph making up this model.
std::vector< int > MatchInputs(std::shared_ptr< ModGraphPiece > otherPiece) const
Matches inputs with another ModGraphPiece by looking at node names and edges.
std::shared_ptr< ModGraphPiece > GradientGraph(unsigned int const outputDimWrt, unsigned int const inputDimWrt)
std::map< unsigned int, std::vector< std::pair< unsigned int, unsigned int > > > InputNodes(boost::graph_traits< Graph >::vertex_descriptor const &node) const
Get a the input nodes for a node.
ModGraphPiece(std::shared_ptr< WorkGraph > graph, std::vector< std::shared_ptr< ConstantVector > > const &constantPieces, std::vector< std::string > const &inputNames, std::shared_ptr< ModPiece > outputNode)
Construct a muq::Modeling::ModGraphPiece.
std::vector< std::shared_ptr< FilteredGraph > > filtered_graphs
std::map< std::tuple< unsigned int, unsigned int, unsigned int >, std::shared_ptr< ModGraphPiece > > hessianPieces
Provides an abstract interface for defining vector-valued model components.
const Eigen::VectorXi inputSizes
std::vector< Eigen::VectorXd > outputs
const Eigen::VectorXi outputSizes
Eigen::VectorXd hessAction
Eigen::VectorXd jacobianAction
A graph of connected muq::Modeling::WorkPiece's.
void AddNode(std::shared_ptr< WorkPiece > input, std::string const &name)
Add a new node to the graph.
void AddEdge(std::string const &nameFrom, unsigned int const outputDim, std::string const &nameTo, unsigned int const inputDim)
Add a new edge to the graph.
Graph graph
The directed graph that represents this muq::Modeling::Core::WorkGraph.
std::shared_ptr< ModGraphPiece > CreateModPiece(std::string const &node, std::vector< std::string > const &inNames=std::vector< std::string >()) const
Create a muq::Modeling::ModPiece whose output matches a given node.
bool HasNode(std::string const &name) const
Is the given node in the graph?
const unsigned int id
A unique ID number assigned by the constructor.
static ref_vector< const boost::any > ToRefVector(std::vector< boost::any > const &anyVec)
Create vector of references from a vector of boost::any's.
unsigned int ID() const
Get the unique ID number.
std::string name
A unique name for this WorkPiece. Defaults to <ClassName>_<id>
int numInputs
The number of inputs.
std::vector< std::reference_wrapper< const T > > ref_vector
A vector of references to something ...
A helper struct that determines if a node in the graph has a given name.