9 if (0 == stateId )
return "FALSE";
10 else if (1 == stateId )
return "TRUE";
11 else return "UNDEFINED";
25 daughter->initialize(algname_index_map);
46 const unsigned int& recursionLevel)
const {
51 daughter->printState(output,states,node_decisions,recursionLevel+2);
61 bool hasUndecidedChild =
false;
63 if (
m_isLazy && (-1 !=decision || hasUndecidedChild ) ) {
66 auto res = daughter->updateState(states, node_decisions);
67 if ( -1 == res) {hasUndecidedChild =
true;}
68 else if (
false ==
m_modeOR && res == 0 ){decision = 0;}
69 else if (
true ==
m_modeOR && res == 1){decision = 1;}
72 if (!hasUndecidedChild && -1 == decision ) {
74 if (
true ==
m_modeOR){ decision = 0; }
76 else { decision = 1; }
91 bool keepGoing =
true;
92 bool hasUndecidedChild =
false;
108 int& res = node_decisions[daughter->getNodeIndex()];
110 hasUndecidedChild =
true;
113 algod->promoteToControlReadyState(slotNum,states,node_decisions);
114 bool result = algod->promoteToDataReadyState(slotNum, requestor);
118 daughter->updateDecision(slotNum, states, node_decisions, requestor);
122 }
else if (
false ==
m_modeOR && res == 0) {
126 }
else if (
true ==
m_modeOR && res == 1) {
133 if (!hasUndecidedChild && -1 == decision ) {
149 p->updateDecision(slotNum, states, node_decisions, requestor);
164 auto res = node_decisions[daughter->getNodeIndex()];
166 daughter->promoteToControlReadyState(slotNum, states, node_decisions);
169 if ((
false ==
m_modeOR && res == 0) || (
true ==
m_modeOR && res == 1))
return true;
180 bool result = visitor.
visit(*
this);
185 bool keepGoing = child->accept(visitor);
216 if (State::INITIAL ==
state) {
220 }
else if (State::CONTROLREADY ==
state) {
235 if (State::CONTROLREADY ==
state) {
238 states.updateState(
m_algoIndex, State::DATAREADY).ignore();
254 }
else if (State::DATAREADY ==
state) {
256 }
else if (State::SCHEDULED ==
state) {
271 for (
auto algoNode : dataNode->getProducers())
272 if (State::EVTACCEPTED == states[algoNode->getAlgoIndex()]) {
289 for (
auto algoNode : dataNode->getProducers())
290 if (State::EVTACCEPTED == states[algoNode->getAlgoIndex()]) {
305 const unsigned int& recursionLevel)
const {
322 unsigned int decision = -1;
327 }
else if (State::EVTACCEPTED == state) {
329 }
else if (State::EVTREJECTED == state) {
351 }
else if (State::EVTACCEPTED == state) {
353 }
else if (State::EVTREJECTED == state) {
361 if (-1 != decision) {
363 for (
auto consumer : output->getConsumers())
364 consumer->promoteToDataReadyState(slotNum, requestor);
367 p->updateDecision(slotNum, states, node_decisions, requestor);
375 bool result = visitor.
visit(*
this);
376 if (result)
return false;
412 error() <<
"Could not build the data dependency realm." <<
endmsg;
427 error() <<
"Could not build the data dependency realm." <<
endmsg;
446 debug() <<
"Inputs of " << algoName <<
": ";
447 for (
auto tag : inputObjs) {
448 debug() << tag <<
" | ";
454 debug() <<
"Outputs of " << algoName <<
": ";
455 for (
auto tag : outputObjs) {
456 debug() << tag <<
" | ";
468 auto targetNode = m_algoNameToAlgoNodeMap[algo.first];
472 for (
auto inputTag : targetInCollection) {
475 auto& outputs = m_algoNameToAlgoOutputsMap[producer.first];
476 for (
auto outputTag : outputs) {
478 if (inputTag == outputTag) {
479 auto& known_producers = targetNode->getSupplierNodes();
480 auto valid_producer = m_algoNameToAlgoNodeMap[producer.first];
481 auto& known_consumers = valid_producer->getConsumerNodes();
482 if (
std::find(known_producers.begin(),known_producers.end(),valid_producer) == known_producers.end())
483 targetNode->addSupplierNode(valid_producer);
484 if (
std::find(known_consumers.begin(),known_consumers.end(),targetNode) == known_consumers.end())
485 valid_producer->addConsumerNode(targetNode);
493 for (
auto outputTag : targetOutCollection) {
496 auto& inputs = m_algoNameToAlgoInputsMap[consumer.first];
497 for (
auto inputTag : inputs) {
499 if (inputTag == outputTag) {
500 auto& known_consumers = targetNode->getConsumerNodes();
501 auto valid_consumer = m_algoNameToAlgoNodeMap[consumer.first];
502 auto& known_producers = valid_consumer->getSupplierNodes();
503 if (
std::find(known_producers.begin(),known_producers.end(),targetNode) == known_producers.end())
504 valid_consumer->addSupplierNode(targetNode);
505 if (
std::find(known_consumers.begin(),known_consumers.end(),valid_consumer) == known_consumers.end())
506 targetNode->addConsumerNode(valid_consumer);
526 for (
auto outputTag : outCollection) {
531 error() <<
"Extra producer (" << algo.first <<
") for DataObject @ "
533 <<
" has been detected: this is not allowed." <<
endmsg;
537 dataNode->addProducerNode(algo.second);
538 algo.second->addOutputDataNode(dataNode);
544 for (
auto algo : m_algoNameToAlgoNodeMap) {
546 for (
auto inputTag : inCollection) {
550 auto primaryPath = inputTag;
570 algo.second->addInputDataNode(dataNode);
585 auto& algoName = algo->
name();
590 parentNode = itP->second;
594 algoNode = itA->second;
599 debug() <<
"AlgoNode " << algoName <<
" added @ " << algoNode <<
endmsg;
607 error() <<
"DecisionHubNode " << parentName <<
", meant to be used as parent, is not registered in the EFG." <<
endmsg;
627 dataNode = itD->second;
633 debug() <<
" DataNode for " << dataPath <<
" added @ " << dataNode <<
endmsg;
651 auto& decisionHubName = decisionHubAlgo->
name();
656 parentNode = itP->second;
660 decisionHubNode = itA->second;
665 debug() <<
"DecisionHubNode " << decisionHubName <<
" added @ " << decisionHubNode <<
endmsg;
672 error() <<
"DecisionHubNode " << parentName <<
", meant to be used as parent, is not registered in the EFG." <<
endmsg;
710 info() <<
"Starting ranking by data outputs .. " <<
endmsg;
712 pair.second->accept(ranker);
713 debug() <<
" Rank of " << pair.first <<
": " << pair.second->getRank() <<
endmsg;
724 for (
auto tag : collection)
737 const char idt[] =
" ";
741 ost <<
"\n" << idt <<
"====================================\n";
742 ost << idt <<
"Data origins and destinations:\n";
743 ost << idt <<
"====================================\n";
747 for (
auto algoNode : pair.second->getProducers())
748 ost << idt <<
" " << algoNode->getNodeName() <<
"\n";
750 ost << idt <<
" V\n";
751 ost << idt <<
" o " << pair.first <<
"\n";
752 ost << idt <<
" V\n";
754 for (
auto algoNode : pair.second->getConsumers())
755 ost << idt <<
" " << algoNode->getNodeName() <<
"\n";
757 ost << idt <<
"====================================\n";
769 boost::dynamic_properties dp;
787 source = itT->second;
796 source = itS->second;
800 fatal() <<
"could not convert IAlgorithm to Algorithm!" <<
endmsg;
803 const Property& p = alg->getProperty(
"AvgRuntime" );
806 debug() <<
"no AvgRuntime for " << alg->name() <<
endmsg;
821 target = itP->second;
825 fatal() <<
"could not convert IAlgorithm to Algorithm!" <<
endmsg;
828 const Property& p = alg->getProperty(
"AvgRuntime" );
831 debug() <<
"no AvgRuntime for " << alg->name() <<
endmsg;
842 debug() <<
"Edge added to execution plan" <<
endmsg;
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.
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 std::string toString() const =0
value -> string
virtual int updateState(AlgsExecutionStates &states, std::vector< int > &node_decisions) const
Method to set algos to CONTROLREADY, if possible.
MsgStream & info() const
shortcut for the method msgStream(MSG::INFO)
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
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.
std::string dumpDataFlow() const
Print out all data origins and destinations, as reflected in the EF graph.
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.
DataNode * getDataNode(const DataObjID &dataPath) const
Get DataNode by DataObject path using graph index.
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.
MsgStream & error() const
shortcut for the method msgStream(MSG::ERROR)
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...
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.
Property base class allowing Property* collections to be "homogeneous".
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.
MsgStream & debug() const
shortcut for the method msgStream(MSG::DEBUG)
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.
virtual void acceptDHVisitor(IDataHandleVisitor *) const override
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.
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
MsgStream & fatal() const
shortcut for the method msgStream(MSG::FATAL)
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 & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
bool m_allPass
Whether the selection result is relevant or always "pass".
bool promoteToDataReadyState(const int &slotNum, const AlgorithmNode *requestor=nullptr) const
static std::map< State, std::string > stateNames
StatusCode addDataNode(const DataObjID &dataPath)
Add DataNode that represents DataObject.
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)