8 if (0 == stateId )
return "FALSE";
9 else if (1 == stateId )
return "TRUE";
10 else return "UNDEFINED";
24 daughter->initialize(algname_index_map);
44 const std::vector<int>& node_decisions,
45 const unsigned int& recursionLevel)
const {
47 output << std::string(recursionLevel,
' ') <<
m_nodeName <<
" (" <<
m_nodeIndex <<
")" <<
", w/ decision: "
50 daughter->printState(output,states,node_decisions,recursionLevel+2);
56 std::vector<int>& node_decisions)
const {
60 bool hasUndecidedChild =
false;
62 if (
m_isLazy && (-1 !=decision || hasUndecidedChild ) ) {
65 auto res = daughter->updateState(states, node_decisions);
66 if ( -1 == res) {hasUndecidedChild =
true;}
67 else if (
false ==
m_modeOR && res == 0 ){decision = 0;}
68 else if (
true ==
m_modeOR && res == 1){decision = 1;}
71 if (!hasUndecidedChild && -1 == decision ) {
73 if (
true ==
m_modeOR){ decision = 0; }
75 else { decision = 1; }
86 std::vector<int>& node_decisions,
90 bool keepGoing =
true;
91 bool hasUndecidedChild =
false;
107 int& res = node_decisions[daughter->getNodeIndex()];
109 hasUndecidedChild =
true;
112 algod->promoteToControlReadyState(slotNum,states,node_decisions);
113 bool result = algod->promoteToDataReadyState(slotNum, requestor);
117 daughter->updateDecision(slotNum, states, node_decisions, requestor);
121 }
else if (
false ==
m_modeOR && res == 0) {
125 }
else if (
true ==
m_modeOR && res == 1) {
132 if (!hasUndecidedChild && -1 == decision ) {
148 p->updateDecision(slotNum, states, node_decisions, requestor);
156 std::vector<int>& node_decisions)
const {
163 auto res = node_decisions[daughter->getNodeIndex()];
165 daughter->promoteToControlReadyState(slotNum, states, node_decisions);
168 if ((
false ==
m_modeOR && res == 0) || (
true ==
m_modeOR && res == 1))
return true;
179 bool result = visitor.
visit(*
this);
184 bool keepGoing = child->accept(visitor);
210 std::vector<int>& )
const {
215 if (State::INITIAL ==
state) {
219 }
else if (State::CONTROLREADY ==
state) {
233 if (State::CONTROLREADY ==
state) {
252 }
else if (State::DATAREADY ==
state) {
254 }
else if (State::SCHEDULED ==
state) {
269 for (
auto algoNode : dataNode->getProducers())
270 if (State::EVTACCEPTED == states[algoNode->getAlgoIndex()]) {
287 for (
auto algoNode : dataNode->getProducers())
288 if (State::EVTACCEPTED == states[algoNode->getAlgoIndex()]) {
302 const std::vector<int>& node_decisions,
303 const unsigned int& recursionLevel)
const {
304 output << std::string(recursionLevel,
' ') <<
m_nodeName <<
" (" <<
m_nodeIndex <<
")" <<
", w/ decision: "
306 <<
", in state: " << states[
m_algoIndex] << std::endl;
311 std::vector<int>& node_decisions)
const {
317 unsigned int decision = -1;
322 }
else if (State::EVTACCEPTED == state) {
324 }
else if (State::EVTREJECTED == state) {
336 std::vector<int>& node_decisions,
346 }
else if (State::EVTACCEPTED == state) {
348 }
else if (State::EVTREJECTED == state) {
356 if (-1 != decision) {
358 for (
auto consumer : output->getConsumers())
359 consumer->promoteToDataReadyState(slotNum, requestor);
362 p->updateDecision(slotNum, states, node_decisions, requestor);
370 bool result = visitor.
visit(*
this);
371 if (result)
return false;
407 error() <<
"Could not build the data dependency realm." <<
endmsg;
414 std::vector<EventSlot>& eventSlots){
422 error() <<
"Could not build the data dependency realm." <<
endmsg;
434 const std::string& algoName = algo->
name();
439 debug() <<
"Inputs of " << algoName <<
": ";
440 for (
auto tag : inputDOCollection) {
441 if (inputDOCollection[tag].isValid())
442 debug() << inputDOCollection[tag].dataProductName() <<
" | ";
449 debug() <<
"Outputs of " << algoName <<
": ";
450 for (
auto tag : outputDOCollection) {
451 if (outputDOCollection[tag].isValid())
452 debug() << outputDOCollection[tag].dataProductName() <<
" | ";
464 auto targetNode = m_algoNameToAlgoNodeMap[algo.first];
468 for (
auto inputTag : targetInCollection) {
469 auto& input2Match = targetInCollection[inputTag].dataProductName();
471 auto& outputs = *m_algoNameToAlgoOutputsMap[producer.first];
472 for (
auto outputTag : outputs) {
473 if (outputs[outputTag].isValid() && outputs[outputTag].dataProductName() == input2Match) {
474 auto& known_producers = targetNode->getSupplierNodes();
475 auto valid_producer = m_algoNameToAlgoNodeMap[producer.first];
476 auto& known_consumers = valid_producer->getConsumerNodes();
477 if (std::find(known_producers.begin(),known_producers.end(),valid_producer) == known_producers.end())
478 targetNode->addSupplierNode(valid_producer);
479 if (std::find(known_consumers.begin(),known_consumers.end(),targetNode) == known_consumers.end())
480 valid_producer->addConsumerNode(targetNode);
488 for (
auto outputTag : targetOutCollection) {
489 auto& output2Match = targetOutCollection[outputTag].dataProductName();
491 auto& inputs = *m_algoNameToAlgoInputsMap[consumer.first];
492 for (
auto inputTag : inputs) {
493 if (inputs[inputTag].isValid() && inputs[inputTag].dataProductName() == output2Match) {
494 auto& known_consumers = targetNode->getConsumerNodes();
495 auto valid_consumer = m_algoNameToAlgoNodeMap[consumer.first];
496 auto& known_producers = valid_consumer->getSupplierNodes();
497 if (std::find(known_producers.begin(),known_producers.end(),targetNode) == known_producers.end())
498 valid_consumer->addSupplierNode(targetNode);
499 if (std::find(known_consumers.begin(),known_consumers.end(),valid_consumer) == known_consumers.end())
500 targetNode->addConsumerNode(valid_consumer);
520 for (
auto outputTag : outCollection) {
521 if (outCollection[outputTag].isValid()) {
522 auto& output = outCollection[outputTag].dataProductName();
525 error() <<
"Extra producer (" << algo.first <<
") for DataObject @ " << output
526 <<
" has been detected: this is not allowed." <<
endmsg;
530 dataNode->addProducerNode(algo.second);
531 algo.second->addOutputDataNode(dataNode);
537 for (
auto algo : m_algoNameToAlgoNodeMap) {
539 for (
auto inputTag : inCollection) {
540 if (inCollection[inputTag].isValid()) {
542 auto& primaryPath = inCollection[inputTag].dataProductName();
546 if (!inCollection[inputTag].alternativeDataProductNames().empty())
547 warning() <<
"Dropping all alternative data dependencies in the graph, but '" << primaryPath
548 <<
"', for algorithm " << algo.first <<
endmsg;
550 for (
auto alterPath : inCollection[inputTag].alternativeDataProductNames()) {
554 warning() <<
"Dropping all alternative data dependencies in the graph, but '" << alterPath
555 <<
"', for algorithm " << algo.first <<
endmsg;
562 algo.second->addInputDataNode(dataNode);
577 auto& algoName = algo->
name();
582 parentNode = itP->second;
586 algoNode = itA->second;
591 debug() <<
"AlgoNode " << algoName <<
" added @ " << algoNode <<
endmsg;
599 error() <<
"DecisionHubNode " << parentName <<
", meant to be used as parent, is not registered in the EFG." <<
endmsg;
619 dataNode = itD->second;
625 debug() <<
" DataNode for " << dataPath <<
" added @ " << dataNode <<
endmsg;
643 auto& decisionHubName = decisionHubAlgo->
name();
648 parentNode = itP->second;
652 decisionHubNode = itA->second;
657 debug() <<
"DecisionHubNode " << decisionHubName <<
" added @ " << decisionHubNode <<
endmsg;
664 error() <<
"DecisionHubNode " << parentName <<
", meant to be used as parent, is not registered in the EFG." <<
endmsg;
686 std::vector<int>& node_decisions)
const {
694 std::vector<int>& node_decisions)
const {
702 info() <<
"Starting ranking by data outputs .. " <<
endmsg;
704 pair.second->accept(ranker);
705 debug() <<
" Rank of " << pair.first <<
": " << pair.second->getRank() <<
endmsg;
712 std::vector<AlgorithmNode*> result;
716 for (
auto tag : collection)
717 if (collection[tag].isValid()) {
729 debug() <<
"====================================" <<
endmsg;
730 debug() <<
"Data origins and destinations:" <<
endmsg;
731 debug() <<
"====================================" <<
endmsg;
735 for (
auto algoNode : pair.second->getProducers())
736 debug() <<
" " << algoNode->getNodeName() <<
endmsg;
742 for (
auto algoNode : pair.second->getConsumers())
743 debug() <<
" " << algoNode->getNodeName() <<
endmsg;
745 debug() <<
" ====================================" <<
endmsg;
750 std::ofstream myfile;
753 boost::dynamic_properties dp;
770 source = itT->second;
778 source = itS->second;
781 if (!cruncher)
fatal() <<
"Conversion from IAlgorithm to CPUCruncher failed" <<
endmsg;
790 target = itP->second;
793 if (!cruncher)
fatal() <<
"Conversion from IAlgorithm to CPUCruncher failed" <<
endmsg;
798 debug() <<
"Edge added to execution plan" <<
endmsg;
void dumpDataFlow() const
Print out all data origins and destinations, as reflected in the EF graph.
bool m_isLazy
Whether to evaluate lazily - i.e. whether to stop once result known.
std::string stateToString(const int &stateId) const
Translation between state id and name.
std::vector< DataNode * > m_outputs
Vectors, used in augmented data dependencies realm Outputs of the algorithm, represented as DataNode'...
const std::vector< AlgorithmNode * > getDataIndependentNodes() const
const unsigned int & getAlgoIndex() const
XXX: CF tests.
virtual bool promoteToControlReadyState(const int &slotNum, AlgsExecutionStates &states, std::vector< int > &node_decisions) const
XXX: CF tests.
virtual bool visitLeave(DecisionNode &) const =0
std::vector< DecisionNode * > m_parents
XXX: CF tests. All direct parent nodes in the tree.
StatusCode initialize(const std::unordered_map< std::string, unsigned int > &algname_index_map)
Initialize graph.
unsigned int m_algoIndex
The index of the algorithm.
unsigned int m_nodeCounter
Total number of nodes in the graph.
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
const DataObjectDescriptorCollection & outputDataObjects() const override
boost::ExecPlan m_ExecPlan
temporary items to experiment with execution planning
StatusCode buildAugmentedDataDependenciesRealm()
Build data dependency realm WITH data object nodes participating.
void addDaughterNode(ControlFlowNode *node)
Add a daughter node.
StatusCode addDecisionHubNode(Algorithm *daughterAlgo, const std::string &parentName, bool modeOR, bool allPass, bool isLazy)
Add a node, which aggregates decisions of direct daughter nodes.
virtual int updateState(AlgsExecutionStates &states, std::vector< int > &node_decisions) const
Method to set algos to CONTROLREADY, if possible.
virtual bool accept(IGraphVisitor &visitor)
std::string m_algoName
The name of the algorithm.
bool dataDependenciesSatisfied(const int &slotNum) const
Method to check whether the Algorithm has its all data dependency satisfied.
bool isSuccess() const
Test for a status code of SUCCESS.
std::vector< ControlFlowNode * > m_children
All direct daughter nodes in the tree.
DataNodesMap m_dataPathToDataNodeMap
Index: map of data path to DataNode.
AlgoOutputsMap m_algoNameToAlgoOutputsMap
MsgStream & warning() const
shortcut for the method msgStream(MSG::WARNING)
const std::vector< IAlgorithm * > & getAlgorithmRepresentatives() const
get Algorithm representatives
std::vector< DecisionNode * > m_parents
XXX: CF tests.
void updateDecision(const std::string &algo_name, const int &slotNum, AlgsExecutionStates &states, std::vector< int > &node_decisions) const
A method to update algorithm node decision, and propagate it upwards.
std::map< std::string, boost::AlgoVertex > m_exec_plan_map
bool m_inverted
Whether the selection result is negated or not.
bool m_allPass
Whether always passing regardless of daughter results.
ExecutionFlowGraph * m_graph
~AlgorithmNode()
Destructor.
virtual void initialize(const std::unordered_map< std::string, unsigned int > &algname_index_map)
Initialize.
AlgoNodesMap m_algoNameToAlgoNodeMap
Index: map of algorithm's name to AlgorithmNode.
AlgsExecutionStates & getAlgoStates(const int &slotNum) const
const std::string & name() const override
The identifying name of the algorithm object.
void registerIODataObjects(const Algorithm *algo)
Register algorithm in the Data Dependency index.
bool m_modeOR
Whether acting as "and" (false) or "or" node (true)
void addInputDataNode(DataNode *node)
Associate an AlgorithmNode, which is a data consumer of this one.
const float & getRank() const
Get Algorithm rank.
DecisionNode * m_headNode
the head node of the control flow graph; may want to have multiple ones once supporting trigger paths...
The AlgsExecutionStates encodes the state machine for the execution of algorithms within a single eve...
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
This class is used for returning status codes from appropriate routines.
virtual bool accept(IGraphVisitor &visitor)
graph_traits< ExecPlan >::vertex_descriptor AlgoVertex
virtual void printState(std::stringstream &output, AlgsExecutionStates &states, const std::vector< int > &node_decisions, const unsigned int &recursionLevel) const
Print a string representing the control flow state.
virtual bool visit(DecisionNode &)=0
virtual ~DecisionNode()
Destructor.
StatusCode buildDataDependenciesRealm()
Build data dependency realm WITHOUT data object nodes: just interconnect algorithm nodes directly...
DecisionHubsMap m_decisionNameToDecisionHubMap
Index: map of decision's name to DecisionHub.
virtual void initialize(const std::unordered_map< std::string, unsigned int > &algname_index_map)
Initialize.
void addOutputDataNode(DataNode *node)
Associate an AlgorithmNode, which is a data supplier for this one.
Base class from which all concrete algorithm classes should be derived.
void rankAlgorithms(IGraphVisitor &ranker) const
Rank Algorithm nodes by the number of data outputs.
virtual void updateDecision(const int &slotNum, AlgsExecutionStates &states, std::vector< int > &node_decisions, const AlgorithmNode *requestor=nullptr) const
XXX: CF tests.
void addEdgeToExecutionPlan(const AlgorithmNode *u, const AlgorithmNode *v)
set cause-effect connection between two algorithms in the execution plan
StatusCode addAlgorithmNode(Algorithm *daughterAlgo, const std::string &parentName, bool inverted, bool allPass)
Add algorithm node.
std::vector< DataNode * > m_inputs
Inputs of the algorithm, represented as DataNode's.
void addParentNode(DecisionNode *node)
XXX: CF tests. Method to add a parent node.
StatusCode addDataNode(const std::string &dataPath)
Add DataNode that represents DataObject.
DataNode * getDataNode(const std::string &dataPath) const
Get DataNode by DataObject path using graph index.
virtual int updateState(AlgsExecutionStates &states, std::vector< int > &node_decisions) const
Method to set algos to CONTROLREADY, if possible.
void dumpExecutionPlan()
dump to file encountered execution plan
std::vector< EventSlot > * m_eventSlots
void addHeadNode(const std::string &headName, bool modeOR, bool allPass, bool isLazy)
Add a node, which has no parents.
MsgStream & fatal() const
shortcut for the method msgStream(MSG::FATAL)
void addParentNode(DecisionNode *node)
XXX: CF tests. Method to add a parent node.
virtual void printState(std::stringstream &output, AlgsExecutionStates &states, const std::vector< int > &node_decisions, const unsigned int &recursionLevel) const
Print a string representing the control flow state.
virtual void updateDecision(const int &slotNum, AlgsExecutionStates &states, std::vector< int > &node_decisions, const AlgorithmNode *requestor=nullptr) const
XXX: CF tests.
AlgoInputsMap m_algoNameToAlgoInputsMap
Indexes: maps of algorithm's name to algorithm's inputs/outputs.
const std::string & getNodeName() const
__attribute__((deprecated)) const std const DataObjectDescriptorCollection & inputDataObjects() const override
Return the handles declared in the algorithm.
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
State
Execution states of the algorithms.
virtual bool visitEnter(DecisionNode &) const =0
void updateEventState(AlgsExecutionStates &states, std::vector< int > &node_decisions) const
XXX CF tests. Is needed for older CF implementation.
AlgorithmNode * getAlgorithmNode(const std::string &algoName) const
Get the AlgorithmNode from by algorithm name using graph index.
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
bool m_allPass
Whether the selection result is relevant or always "pass".
bool promoteToDataReadyState(const int &slotNum, const AlgorithmNode *requestor=nullptr) const
MSG::Level msgLevel() const
get the output level from the embedded MsgStream
void addConsumerNode(AlgorithmNode *node)
Associate an AlgorithmNode, which is a data consumer of this one.
virtual bool promoteToControlReadyState(const int &slotNum, AlgsExecutionStates &states, std::vector< int > &node_decisions) const
XXX: CF tests. Method to set algos to CONTROLREADY, if possible.
StatusCode updateState(unsigned int iAlgo, State newState)