| The Gaudi Framework v29r1 (5cd95fa2)

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

ControlFlowGraph.cpp
Go to the documentation of this file.
1 #include "ControlFlowGraph.h"
2 #include <algorithm>
3
4 namespace concurrency
5 {
6
7 namespace recursive_CF
8 {
9
10 //---------------------------------------------------------------------------
11 std::string ControlFlowNode::stateToString( const int& stateId ) const
12 {
13
14 if ( 0 == stateId )
15 return "FALSE";
16 else if ( 1 == stateId )
17 return "TRUE";
18 else
19 return "UNDEFINED";
20 }
21
22 //---------------------------------------------------------------------------
23 DecisionNode::~DecisionNode()
24 {
25
26 for ( auto node : m_children ) delete node;
27 }
28
29 //---------------------------------------------------------------------------
30 void DecisionNode::initialize( const std::unordered_map<std::string, unsigned int>& algname_index_map )
31 {
32
33 for ( auto daughter : m_children ) daughter->initialize( algname_index_map );
34 }
35
36 //--------------------------------------------------------------------------
37 void DecisionNode::addDaughterNode( ControlFlowNode* node )
38 {
39
40 if ( std::find( m_children.begin(), m_children.end(), node ) == m_children.end() ) m_children.push_back( node );
41 }
42
43 //---------------------------------------------------------------------------
44 void DecisionNode::printState( std::stringstream& output, AlgsExecutionStates& states,
45 const std::vector<int>& node_decisions, const unsigned int& recursionLevel ) const
46 {
47
48 output << std::string( recursionLevel, ' ' ) << m_nodeName << " (" << m_nodeIndex << ")"
49 << ", w/ decision: " << stateToString( node_decisions[m_nodeIndex] ) << "(" << node_decisions[m_nodeIndex]
50 << ")" << std::endl;
51 for ( auto daughter : m_children ) {
52 daughter->printState( output, states, node_decisions, recursionLevel + 2 );
53 }
54 }
55
56 //---------------------------------------------------------------------------
57 int DecisionNode::updateState( AlgsExecutionStates& states, std::vector<int>& node_decisions ) const
58 {
59 // check whether we already had a result earlier
60 // if (-1 != node_decisions[m_nodeIndex] ) { return node_decisions[m_nodeIndex]; }
61 int decision = ( ( m_allPass && m_modePromptDecision ) ? 1 : -1 );
62 bool hasUndecidedChild = false;
63 for ( auto daughter : m_children ) {
64 if ( m_modePromptDecision && ( -1 != decision || hasUndecidedChild ) ) {
65 node_decisions[m_nodeIndex] = decision;
66 return decision;
67 } // if prompt decision, return once result is known already or we can't
68 // fully evaluate right now because one daugther decision is missing still
69 auto res = daughter->updateState( states, node_decisions );
70 if ( -1 == res ) {
71 hasUndecidedChild = true;
72 } else if ( false == m_modeOR && res == 0 ) {
73 decision = 0;
74 } // "and"-mode (once first result false, the overall decision is false)
75 else if ( true == m_modeOR && res == 1 ) {
76 decision = 1;
77 } // "or"-mode (once first result true, the overall decision is true)
78 }
79 // what to do with yet undefined answers depends on whether AND or OR mode applies
80 if ( !hasUndecidedChild && -1 == decision ) {
81 // OR mode: all results known, and none true -> reject
82 if ( true == m_modeOR ) {
83 decision = 0;
84 }
85 // AND mode: all results known, and no false -> accept
86 else {
87 decision = 1;
88 }
89 }
90 // in all other cases I stay with previous decisions
91 node_decisions[m_nodeIndex] = decision;
92 if ( m_allPass ) decision = 1;
93 return decision;
94 }
95
96 //---------------------------------------------------------------------------
97 void AlgorithmNode::initialize( const std::unordered_map<std::string, unsigned int>& algname_index_map )
98 {
99
100 m_algoIndex = algname_index_map.at( m_algoName );
101 }
102
103 //---------------------------------------------------------------------------
104 void AlgorithmNode::printState( std::stringstream& output, AlgsExecutionStates& states,
105 const std::vector<int>& node_decisions, const unsigned int& recursionLevel ) const
106 {
107 output << std::string( recursionLevel, ' ' ) << m_nodeName << " (" << m_nodeIndex << ")"
108 << ", w/ decision: " << stateToString( node_decisions[m_nodeIndex] ) << "(" << node_decisions[m_nodeIndex]
109 << ")"
110 << ", in state: " << AlgsExecutionStates::stateNames[states[m_algoIndex]] << std::endl;
111 }
112
113 //---------------------------------------------------------------------------
114 int AlgorithmNode::updateState( AlgsExecutionStates& states, std::vector<int>& node_decisions ) const
115 {
116 // check whether we already had a result earlier
117 // if (-1 != node_decisions[m_nodeIndex] ) { return node_decisions[m_nodeIndex]; }
118 // since we reached this point in the control flow, this algorithm is supposed to run
119 // if it hasn't already
120 const State& state = states[m_algoIndex];
121 unsigned int decision = -1;
122 if ( State::INITIAL == state ) {
123 states.updateState( m_algoIndex, State::CONTROLREADY ).ignore();
124 }
125 // now derive the proper result to pass back
126 if ( true == m_allPass ) {
127 decision = 1;
128 } else if ( State::EVTACCEPTED == state ) {
129 decision = !m_inverted;
130 } else if ( State::EVTREJECTED == state ) {
131 decision = m_inverted;
132 } else {
133 decision = -1; // result not known yet
134 }
135 node_decisions[m_nodeIndex] = decision;
136 return decision;
137 }
138
139 //---------------------------------------------------------------------------
140 void ControlFlowGraph::initialize( const std::unordered_map<std::string, unsigned int>& algname_index_map )
141 {
142 m_headNode->initialize( algname_index_map );
143 }
144
145 //---------------------------------------------------------------------------
146 StatusCode ControlFlowGraph::addAlgorithmNode( Algorithm* algo, const std::string& parentName, bool inverted,
147 bool allPass )
148 {
149
150 StatusCode sc = StatusCode::SUCCESS;
151
152 auto& algoName = algo->name();
153
154 auto itP = m_decisionNameToDecisionHubMap.find( parentName );
155 concurrency::recursive_CF::DecisionNode* parentNode;
156 if ( itP != m_decisionNameToDecisionHubMap.end() ) {
157 parentNode = itP->second;
158 auto itA = m_algoNameToAlgoNodeMap.find( algoName );
159 concurrency::recursive_CF::AlgorithmNode* algoNode;
160 if ( itA != m_algoNameToAlgoNodeMap.end() ) {
161 algoNode = itA->second;
162 } else {
163 algoNode = new concurrency::recursive_CF::AlgorithmNode( *this, algo, m_nodeCounter, m_algoCounter, inverted,
164 allPass );
165 ++m_nodeCounter;
166 ++m_algoCounter;
167 m_algoNameToAlgoNodeMap[algoName] = algoNode;
168 if ( msgLevel( MSG::VERBOSE ) ) verbose() << "AlgoNode " << algoName << " added @ " << algoNode << endmsg;
169 }
170
171 parentNode->addDaughterNode( algoNode );
172 } else {
173 sc = StatusCode::FAILURE;
174 error() << "Decision hub node " << parentName << ", requested to be parent, is not registered." << endmsg;
175 }
176
177 return sc;
178 }
179
180 //---------------------------------------------------------------------------
181 StatusCode ControlFlowGraph::addDecisionHubNode( Algorithm* decisionHubAlgo, const std::string& parentName,
182 bool modeConcurrent, bool modePromptDecision, bool modeOR,
183 bool allPass )
184 {
185
186 StatusCode sc = StatusCode::SUCCESS;
187
188 auto& decisionHubName = decisionHubAlgo->name();
189
190 auto itP = m_decisionNameToDecisionHubMap.find( parentName );
191 concurrency::recursive_CF::DecisionNode* parentNode;
192 if ( itP != m_decisionNameToDecisionHubMap.end() ) {
193 parentNode = itP->second;
194 auto itA = m_decisionNameToDecisionHubMap.find( decisionHubName );
195 concurrency::recursive_CF::DecisionNode* decisionHubNode;
196 if ( itA != m_decisionNameToDecisionHubMap.end() ) {
197 decisionHubNode = itA->second;
198 } else {
199 decisionHubNode = new concurrency::recursive_CF::DecisionNode(
200 *this, m_nodeCounter, decisionHubName, modeConcurrent, modePromptDecision, modeOR, allPass );
201 ++m_nodeCounter;
202 m_decisionNameToDecisionHubMap[decisionHubName] = decisionHubNode;
203 if ( msgLevel( MSG::VERBOSE ) )
204 verbose() << "Decision hub node " << decisionHubName << " added @ " << decisionHubNode << endmsg;
205 }
206
207 parentNode->addDaughterNode( decisionHubNode );
208 } else {
209 sc = StatusCode::FAILURE;
210 error() << "Decision hub node " << parentName << ", requested to be parent, is not registered." << endmsg;
211 }
212
213 return sc;
214 }
215
216 //---------------------------------------------------------------------------
217 void ControlFlowGraph::addHeadNode( const std::string& headName, bool modeConcurrent, bool modePromptDecision,
218 bool modeOR, bool allPass )
219 {
220
221 auto itH = m_decisionNameToDecisionHubMap.find( headName );
222 if ( itH != m_decisionNameToDecisionHubMap.end() ) {
223 m_headNode = itH->second;
224 } else {
225 m_headNode = new concurrency::recursive_CF::DecisionNode( *this, m_nodeCounter, headName, modeConcurrent,
226 modePromptDecision, modeOR, allPass );
227 ++m_nodeCounter;
228 m_decisionNameToDecisionHubMap[headName] = m_headNode;
229 }
230 }
231
232 //---------------------------------------------------------------------------
233 void ControlFlowGraph::updateEventState( AlgsExecutionStates& algo_states, std::vector<int>& node_decisions ) const
234 {
235 m_headNode->updateState( algo_states, node_decisions );
236 }
237
238 //---------------------------------------------------------------------------
239 std::string ControlFlowGraph::dumpControlFlow() const
240 {
241 std::ostringstream ost;
242 dumpControlFlow( ost, m_headNode, 0 );
243 return ost.str();
244 }
245
246 //---------------------------------------------------------------------------
247 void ControlFlowGraph::dumpControlFlow( std::ostringstream& ost, ControlFlowNode* node, const int& indent ) const
248 {
249 ost << std::string( indent * 2, ' ' );
250 DecisionNode* dn = dynamic_cast<DecisionNode*>( node );
251 AlgorithmNode* an = dynamic_cast<AlgorithmNode*>( node );
252 if ( dn != 0 ) {
253 if ( node != m_headNode ) {
254 ost << node->getNodeName() << " [Seq] ";
255 ost << ( ( dn->m_modeConcurrent ) ? " [Concurrent] " : " [Sequential] " );
256 ost << ( ( dn->m_modePromptDecision ) ? " [Prompt] " : "" );
257 ost << ( ( dn->m_modeOR ) ? " [OR] " : "" );
258 ost << ( ( dn->m_allPass ) ? " [PASS] " : "" );
259 ost << "\n";
260 }
261 const std::vector<ControlFlowNode*>& dth = dn->getDaughters();
262 for ( std::vector<ControlFlowNode*>::const_iterator itr = dth.begin(); itr != dth.end(); ++itr ) {
263 dumpControlFlow( ost, *itr, indent + 1 );
264 }
265 } else if ( an != 0 ) {
266 ost << node->getNodeName() << " [Alg] ";
267 if ( an != 0 ) {
268 auto ar = an->getAlgorithm();
269 ost << " [n= " << ar->cardinality() << "]";
270 ost << ( ( !ar->isClonable() ) ? " [unclonable] " : "" );
271 }
272 ost << "\n";
273 }
274 }
275
276 } // namespace
277 } // namespace
concurrency::recursive_CF::DecisionNode::addDaughterNode
void addDaughterNode(ControlFlowNode *node)
Add a daughter node.
Definition: ControlFlowGraph.cpp:37
StatusCode::SUCCESS
Definition: StatusCode.h:31
Algorithm::name
const std::string & name() const override
The identifying name of the algorithm object.
Definition: Algorithm.cpp:731
StatusCode::FAILURE
Definition: StatusCode.h:31
compareRootHistos.state
state
Definition: compareRootHistos.py:424
gaudirun.output
output
Definition: gaudirun.py:404
concurrency::recursive_CF::ControlFlowGraph::addHeadNode
void addHeadNode(const std::string &headName, bool modeConcurrent, bool modePromptDecision, bool modeOR, bool allPass)
Add a node, which has no parents.
Definition: ControlFlowGraph.cpp:217
concurrency
Definition: ControlFlowGraph.cpp:4
concurrency::recursive_CF::ControlFlowNode::getNodeName
const std::string & getNodeName() const
Get node name.
Definition: ControlFlowGraph.h:45
concurrency::recursive_CF::ControlFlowNode::stateToString
std::string stateToString(const int &stateId) const
Translation between state id and name.
Definition: ControlFlowGraph.cpp:11
concurrency::recursive_CF::ControlFlowGraph::dumpControlFlow
std::string dumpControlFlow() const
Print out control flow of Algorithms and Sequences.
Definition: ControlFlowGraph.cpp:239
concurrency::recursive_CF::DecisionNode::m_modePromptDecision
bool m_modePromptDecision
Whether to evaluate the hub decision ASA its child decisions allow to do that.
Definition: ControlFlowGraph.h:90
concurrency::recursive_CF::ControlFlowGraph::addDecisionHubNode
StatusCode addDecisionHubNode(Algorithm *daughterAlgo, const std::string &parentName, bool modeConcurrent, bool modePromptDecision, bool modeOR, bool allPass)
Add a node, which aggregates decisions of direct daughter nodes.
Definition: ControlFlowGraph.cpp:181
std::endl
T endl(T...args)
concurrency::recursive_CF::DecisionNode
Definition: ControlFlowGraph.h:57
concurrency::recursive_CF::DecisionNode::m_allPass
bool m_allPass
Whether always passing regardless of daughter results.
Definition: ControlFlowGraph.h:94
concurrency::recursive_CF::ControlFlowGraph::updateEventState
void updateEventState(AlgsExecutionStates &states, std::vector< int > &node_decisions) const
Start revision of states and decisions.
Definition: ControlFlowGraph.cpp:233
concurrency::recursive_CF::AlgorithmNode::getAlgorithm
Algorithm * getAlgorithm() const
get Algorithm representatives
Definition: ControlFlowGraph.h:117
std::vector::end
T end(T...args)
concurrency::recursive_CF::AlgorithmNode::updateState
int updateState(AlgsExecutionStates &states, std::vector< int > &node_decisions) const override
Method to set algos to CONTROLREADY, if possible.
Definition: ControlFlowGraph.cpp:114
MSG::VERBOSE
Definition: IMessageSvc.h:16
concurrency::recursive_CF::DecisionNode::printState
void printState(std::stringstream &output, AlgsExecutionStates &states, const std::vector< int > &node_decisions, const unsigned int &recursionLevel) const override
Print a string representing the control flow state.
Definition: ControlFlowGraph.cpp:44
std::stringstream
STL class.
concurrency::recursive_CF::ControlFlowNode
Definition: ControlFlowGraph.h:25
std::string
STL class.
std::unordered_map::at
T at(T...args)
concurrency::recursive_CF::AlgorithmNode::printState
void printState(std::stringstream &output, AlgsExecutionStates &states, const std::vector< int > &node_decisions, const unsigned int &recursionLevel) const override
Print a string representing the control flow state.
Definition: ControlFlowGraph.cpp:104
concurrency::recursive_CF::DecisionNode::updateState
int updateState(AlgsExecutionStates &states, std::vector< int > &node_decisions) const override
Method to set algos to CONTROLREADY, if possible.
Definition: ControlFlowGraph.cpp:57
ControlFlowGraph.h
AlgsExecutionStates
The AlgsExecutionStates encodes the state machine for the execution of algorithms within a single eve...
Definition: AlgsExecutionStates.h:28
concurrency::recursive_CF::DecisionNode::getDaughters
const std::vector< ControlFlowNode * > & getDaughters() const
Definition: ControlFlowGraph.h:80
StatusCode
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:28
std::ostringstream
STL class.
concurrency::recursive_CF::DecisionNode::~DecisionNode
~DecisionNode() override
Destructor.
Definition: ControlFlowGraph.cpp:23
std::ostringstream::str
T str(T...args)
concurrency::recursive_CF::AlgorithmNode
Definition: ControlFlowGraph.h:101
concurrency::recursive_CF::AlgorithmNode::initialize
void initialize(const std::unordered_map< std::string, unsigned int > &algname_index_map) override
Initialize.
Definition: ControlFlowGraph.cpp:97
Algorithm
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:79
std::find
T find(T...args)
std::vector< int >
concurrency::recursive_CF::ControlFlowNode::m_nodeName
std::string m_nodeName
Definition: ControlFlowGraph.h:54
concurrency::recursive_CF::DecisionNode::initialize
void initialize(const std::unordered_map< std::string, unsigned int > &algname_index_map) override
Initialize.
Definition: ControlFlowGraph.cpp:30
std::vector::begin
T begin(T...args)
genconfuser.verbose
verbose
Definition: genconfuser.py:19
concurrency::recursive_CF::ControlFlowGraph::initialize
void initialize(const std::unordered_map< std::string, unsigned int > &algname_index_map)
Initialize graph.
Definition: ControlFlowGraph.cpp:140
StatusCode::ignore
void ignore() const
Definition: StatusCode.h:109
AlgsExecutionStates::State
State
Execution states of the algorithms.
Definition: AlgsExecutionStates.h:32
concurrency::recursive_CF::ControlFlowGraph::addAlgorithmNode
StatusCode addAlgorithmNode(Algorithm *daughterAlgo, const std::string &parentName, bool inverted, bool allPass)
Add algorithm node.
Definition: ControlFlowGraph.cpp:146
concurrency::recursive_CF::DecisionNode::m_modeOR
bool m_modeOR
Whether acting as "and" (false) or "or" node (true)
Definition: ControlFlowGraph.h:92
concurrency::recursive_CF::DecisionNode::m_modeConcurrent
bool m_modeConcurrent
Whether all daughters will be evaluated concurrently or sequentially.
Definition: ControlFlowGraph.h:87
endmsg
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
AlgsExecutionStates::stateNames
static std::map< State, std::string > stateNames
Definition: AlgsExecutionStates.h:42
concurrency::recursive_CF::ControlFlowNode::m_nodeIndex
unsigned int m_nodeIndex
Definition: ControlFlowGraph.h:53
std::unordered_map< std::string, unsigned int >
AlgsExecutionStates::updateState
StatusCode updateState(unsigned int iAlgo, State newState)
Definition: AlgsExecutionStates.cpp:8