The Gaudi Framework  v30r0 (c919700c)
PRGraphVisitors.cpp
Go to the documentation of this file.
1 #include "PRGraphVisitors.h"
2 #include "AlgsExecutionStates.h"
3 
5 #include "GaudiKernel/ICondSvc.h"
6 
7 namespace concurrency
8 {
9 
11 
12  //--------------------------------------------------------------------------
14  {
15 
16  if ( State::CONTROLREADY != m_slot->algsStates[node.getAlgoIndex()] ) return false;
17 
18  return true;
19  }
20 
21  //--------------------------------------------------------------------------
23  {
24 
25  bool result = true; // return true if this algorithm has no data inputs
26 
27  for ( auto dataNode : node.getInputDataNodes() ) {
28 
29  result = dataNode->accept( *this );
30 
31  // With ConditionNodes, one may decide NOT to break here so that associated
32  // ConditionAlgorithms are scheduled ASAP. This behavior can be made configurable
33  if ( !result ) break; // skip checking other inputs if this input was not produced yet
34  }
35 
36  if ( result ) {
37  m_slot->algsStates.updateState( node.getAlgoIndex(), State::DATAREADY ).ignore();
38 
39  if ( m_trace ) {
40  auto sourceNode = ( m_cause.m_source == Cause::source::Task )
42  : nullptr;
43  node.m_graph->addEdgeToPrecTrace( sourceNode, &node );
44  }
45  }
46 
47  // return true only if an algorithm is promoted to DR
48  return result;
49  }
50 
51  //--------------------------------------------------------------------------
52  bool DataReadyPromoter::visitEnter( DataNode& ) const { return true; }
53 
54  //--------------------------------------------------------------------------
56  {
57  /* Implements 'observer' strategy, i.e., only check if producer of this DataNode
58  * has been already executed or not */
59 
60  bool result = false; // return false if this DataNode has no producers at all
61 
62  for ( auto algoNode : node.getProducers() ) {
63  const auto& state = m_slot->algsStates[algoNode->getAlgoIndex()];
64  if ( State::EVTACCEPTED == state || State::EVTREJECTED == state ) {
65  result = true;
66  break; // skip checking other producers if one was found to be executed
67  }
68  }
69 
70  // return true only if this DataNode is produced
71  return result;
72  }
73 
74  //--------------------------------------------------------------------------
76  {
77 
78  if ( node.m_condSvc->isValidID( *( m_slot->eventContext ), node.getPath() ) )
79  return false; // do not enter this ConditionNode if the condition has bee already loaded
80 
81  return true;
82  }
83 
84  //--------------------------------------------------------------------------
86  {
87  /* Implements 'requester' strategy, i.e., requests this ConditionNode to be loaded
88  * by its associated ConditionAlgorithm */
89 
90  auto promoter = Supervisor( *m_slot, m_cause, m_trace );
91 
92  for ( auto condAlg : node.getProducers() ) condAlg->accept( promoter );
93 
94  // this method is called if, and only if, this ConditionNode is not yet produced.
95  // thus, by definition, this ConditionNode is not yet available at this moment
96  return false;
97  }
98 
99  //--------------------------------------------------------------------------
101  {
102 
103  auto& states = m_slot->algsStates;
104  const State& state = states[node.getAlgoIndex()];
105  int decision = -1;
106 
107  if ( true == node.isOptimist() )
108  decision = 1;
109  else if ( State::EVTACCEPTED == state )
110  decision = !node.isLiar();
111  else if ( State::EVTREJECTED == state )
112  decision = node.isLiar();
113 
114  if ( -1 != decision ) {
115 
116  m_slot->controlFlowState[node.getNodeIndex()] = decision;
117 
118  auto promoter = DataReadyPromoter( *m_slot, m_cause, m_trace );
119  for ( const auto& output : node.getOutputDataNodes() )
120  for ( auto& consumer : output->getConsumers() ) consumer->accept( promoter );
121 
123  for ( auto& p : node.getParentDecisionHubs() ) p->accept( vis );
124 
125  return true; // return true only if the algorithm produced a decision
126  }
127 
128  return false;
129  }
130 
131  //---------------------------------------------------------------------------
133  {
134 
135  if ( m_slot->controlFlowState[node.getNodeIndex()] != -1 ) return false;
136  return true;
137  }
138 
139  //---------------------------------------------------------------------------
141  {
142 
143  bool foundNonResolvedChild = false;
144  bool foundNegativeChild = false;
145  bool foundPositiveChild = false;
146  int decision = -1;
147 
148  for ( auto child : node.getDaughters() ) {
149  int& childDecision = m_slot->controlFlowState[child->getNodeIndex()];
150 
151  if ( childDecision == -1 )
152  foundNonResolvedChild = true;
153  else if ( childDecision == 1 )
154  foundPositiveChild = true;
155  else
156  foundNegativeChild = true;
157 
158  if ( node.m_modePromptDecision ) {
159  if ( node.m_modeOR && foundPositiveChild ) {
160  decision = 1;
161  break;
162  } else if ( !node.m_modeOR && foundNegativeChild ) {
163  decision = 0;
164  break;
165  }
166  } else {
167  if ( foundNonResolvedChild ) break;
168  }
169  } // end monitoring children
170 
171  if ( !foundNonResolvedChild && decision == -1 ) {
172  if ( node.m_modeOR ) { // OR
173  if ( foundPositiveChild )
174  decision = 1;
175  else
176  decision = 0;
177  } else { // AND
178  if ( foundNegativeChild )
179  decision = 0;
180  else
181  decision = 1;
182  }
183  }
184 
185  if ( node.m_inverted && decision == 1 )
186  decision = 0;
187  else if ( node.m_inverted && decision == 0 )
188  decision = 1;
189 
190  if ( node.m_allPass && !foundNonResolvedChild ) decision = 1;
191 
192  if ( decision != -1 ) {
193  m_slot->controlFlowState[node.getNodeIndex()] = decision;
194  return true;
195  }
196  return false;
197  }
198 
199  //---------------------------------------------------------------------------
201  {
202 
203  if ( m_slot->controlFlowState[node.getNodeIndex()] != -1 ) return false;
204  return true;
205  }
206 
207  //--------------------------------------------------------------------------
209  {
210 
211  bool result = false;
212 
213  auto& states = m_slot->algsStates;
214  auto& state = states[node.getAlgoIndex()];
215 
216  // Promote with INITIAL->CR
217  if ( State::INITIAL == state ) states.updateState( node.getAlgoIndex(), State::CONTROLREADY ).ignore();
218 
219  // Try to promote with CR->DR
220  if ( State::CONTROLREADY == state ) {
221  auto promoter = DataReadyPromoter( *m_slot, m_cause, m_trace );
222  result = promoter.visit( node );
223  } else {
224  result = true;
225  }
226 
227  // return true only when an algorithm is not lower than DR in its FSM
228  // i.e., the visitor has done everything it could with this algorithm
229  return result;
230  }
231 
232  //--------------------------------------------------------------------------
234  {
235 
236  auto& products = node.getOutputDataNodes();
237  float rank = 0;
238 
239  for ( auto p : products ) rank += p->getConsumers().size();
240 
241  node.setRank( rank );
242  /*std::stringstream s;
243  s << node.getNodeName() << ", " << rank << "\n";
244  std::ofstream myfile;
245  myfile.open("AlgoRank.csv", std::ios::app);
246  myfile << s.str();
247  myfile.close();*/
248 
249  return true;
250  }
251 
252  //--------------------------------------------------------------------------
254  {
255 
256  std::ifstream myfile;
257  myfile.open( "InputExecutionPlan.graphml", std::ios::in );
258 
259  precedence::PrecTrace execPlan;
260 
262  using boost::get;
263 
264  boost::dynamic_properties dp;
265  dp.property( "name", get( &AlgoTraceProps::m_name, execPlan ) );
266  dp.property( "index", get( &AlgoTraceProps::m_index, execPlan ) );
267  dp.property( "dataRank", get( &AlgoTraceProps::m_rank, execPlan ) );
268  dp.property( "runtime", get( &AlgoTraceProps::m_runtime, execPlan ) );
269 
270  boost::read_graphml( myfile, execPlan, dp );
271 
272  typedef boost::graph_traits<precedence::PrecTrace>::vertex_iterator itV;
274 
275  for ( vp = boost::vertices( execPlan ); vp.first != vp.second; ++vp.first ) {
276  precedence::AlgoTraceVertex v = *vp.first;
277  auto index = get( &AlgoTraceProps::m_name, execPlan );
278  if ( index[v] == node.getNodeName() ) {
279  runThroughAdjacents( v, execPlan );
280  float rank = m_nodesSucceeded;
281  node.setRank( rank );
282  reset();
283  // std::cout << "Rank of " << index[v] << " is " << rank << std::endl;
284  }
285  }
286 
287  return true;
288  }
289 
290  //--------------------------------------------------------------------------
292  boost::graph_traits<precedence::PrecTrace>::vertex_descriptor vertex, precedence::PrecTrace graph )
293  {
294  typename boost::graph_traits<precedence::PrecTrace>::adjacency_iterator itVB;
295  typename boost::graph_traits<precedence::PrecTrace>::adjacency_iterator itVE;
296 
297  for ( boost::tie( itVB, itVE ) = adjacent_vertices( vertex, graph ); itVB != itVE; ++itVB ) {
298  m_nodesSucceeded += 1;
299  runThroughAdjacents( *itVB, graph );
300  }
301  }
302 
303  //--------------------------------------------------------------------------
305  {
306 
307  std::ifstream myfile;
308  myfile.open( "InputExecutionPlan.graphml", std::ios::in );
309 
310  precedence::PrecTrace execPlan;
312  using boost::get;
313 
314  boost::dynamic_properties dp;
315  dp.property( "name", get( &AlgoTraceProps::m_name, execPlan ) );
316  dp.property( "index", get( &AlgoTraceProps::m_index, execPlan ) );
317  dp.property( "dataRank", get( &AlgoTraceProps::m_rank, execPlan ) );
318  dp.property( "runtime", get( &AlgoTraceProps::m_runtime, execPlan ) );
319 
320  boost::read_graphml( myfile, execPlan, dp );
321 
322  typedef boost::graph_traits<precedence::PrecTrace>::vertex_iterator itV;
324 
325  for ( vp = boost::vertices( execPlan ); vp.first != vp.second; ++vp.first ) {
326  precedence::AlgoTraceVertex v = *vp.first;
327  auto index = get( &AlgoTraceProps::m_name, execPlan );
328  if ( index[v] == node.getNodeName() ) {
329  auto index_runtime = get( &AlgoTraceProps::m_runtime, execPlan );
330  float rank = index_runtime[v];
331  node.setRank( rank );
332  // std::cout << "Rank of " << index[v] << " is " << rank << std::endl;
333  }
334  }
335  return true;
336  }
337 
338  //--------------------------------------------------------------------------
340  {
341 
342  std::ifstream myfile;
343  myfile.open( "Eccentricity.graphml", std::ios::in );
344 
345  precedence::PrecTrace execPlan;
346 
347  boost::dynamic_properties dp;
348  using boost::get;
349 
350  dp.property( "name", get( &precedence::AlgoTraceProps::m_name, execPlan ) );
351  dp.property( "Eccentricity", get( &precedence::AlgoTraceProps::m_eccentricity, execPlan ) );
352 
353  boost::read_graphml( myfile, execPlan, dp );
354 
355  typedef boost::graph_traits<precedence::PrecTrace>::vertex_iterator itV;
357 
358  for ( vp = boost::vertices( execPlan ); vp.first != vp.second; ++vp.first ) {
359  precedence::AlgoTraceVertex v = *vp.first;
360  auto index = get( &precedence::AlgoTraceProps::m_name, execPlan );
361  if ( index[v] == node.getNodeName() ) {
362  auto index_eccentricity = get( &precedence::AlgoTraceProps::m_eccentricity, execPlan );
363  float rank = index_eccentricity[v];
364  node.setRank( rank );
365  // std::cout << "Rank of " << index[v] << " is " << rank << std::endl;
366  }
367  }
368  return true;
369  }
370 
371  //--------------------------------------------------------------------------
373  {
374 
375  // Find eccentricity of the node (only within the data realm of the execution flow graph)
376  recursiveVisit( node );
377 
378  float rank = m_maxKnownDepth;
379  node.setRank( rank );
380 
381  // Reset visitor for next nodes, if any
382  reset();
383 
384  return true;
385  }
386 
387  //--------------------------------------------------------------------------
389  {
390 
391  m_currentDepth += 1;
392 
393  auto& products = node.getOutputDataNodes();
394 
395  if ( products.empty() )
396  if ( ( m_currentDepth - 1 ) > m_maxKnownDepth ) m_maxKnownDepth = m_currentDepth - 1;
397 
398  for ( auto p : products )
399  for ( auto algoNode : p->getConsumers() ) recursiveVisit( *algoNode );
400 
401  m_currentDepth -= 1;
402  }
403 
404  //---------------------------------------------------------------------------
406  {
407 
408  if ( m_slot->controlFlowState[node.getNodeIndex()] != 1 ) return true;
409  return false;
410  }
411 
412  //---------------------------------------------------------------------------
414  {
415 
416  // std::cout << "1-st level Decision: " << node.getNodeName() << std::endl;
417  bool allChildDecisionsResolved = true;
418  for ( auto child : node.getDaughters() ) {
419  int& childDecision = m_slot->controlFlowState[child->getNodeIndex()];
420 
421  if ( childDecision == 1 && node.m_modeOR && node.m_modePromptDecision ) {
422  m_slot->controlFlowState[node.getNodeIndex()] = 1;
423  return true;
424  }
425 
426  if ( childDecision == -1 ) {
427  allChildDecisionsResolved = false;
428  }
429  }
430 
431  if ( allChildDecisionsResolved ) m_slot->controlFlowState[node.getNodeIndex()] = 1;
432 
433  return allChildDecisionsResolved;
434  }
435 
436  //---------------------------------------------------------------------------
438  {
439 
440  if ( m_slot->controlFlowState[node.getNodeIndex()] != 1 ) return true;
441  return false;
442  }
443 
444  //--------------------------------------------------------------------------
446  {
447 
448  auto& states = m_slot->algsStates;
449  int& decision = m_slot->controlFlowState[node.getNodeIndex()];
450 
451  auto dataPromoter = DataReadyPromoter( *m_slot, m_cause );
452 
453  if ( State::INITIAL == states[node.getAlgoIndex()] ) {
454  states.updateState( node.getAlgoIndex(), State::CONTROLREADY );
455  if ( dataPromoter.visit( node ) ) {
456  states.updateState( node.getAlgoIndex(), State::SCHEDULED );
457  states.updateState( node.getAlgoIndex(), State::EVTACCEPTED );
458  decision = 1;
459  ++m_nodesSucceeded;
460  // std::cout << "Algorithm decided: " << node.getNodeName() << std::endl;
461  return true;
462  }
463  } else if ( State::CONTROLREADY == states[node.getAlgoIndex()] && dataPromoter.visit( node ) ) {
464  states.updateState( node.getAlgoIndex(), State::SCHEDULED );
465  states.updateState( node.getAlgoIndex(), State::EVTACCEPTED );
466  decision = 1;
467  ++m_nodesSucceeded;
468  // std::cout << "Algorithm decided: " << node.getNodeName() << std::endl;
469  return true;
470  }
471 
472  return false;
473  }
474 }
const unsigned int & getAlgoIndex() const
Get algorithm index.
T open(T...args)
bool visit(AlgorithmNode &) override
boost::graph_traits< PrecTrace >::vertex_descriptor AlgoTraceVertex
const std::vector< DataNode * > & getInputDataNodes() const
Get all consumer nodes.
bool isOptimist() const
Check if positive control flow decision is enforced.
AlgsExecutionStates algsStates
Vector of algorithms states.
Definition: EventSlot.h:33
EventContext * eventContext
Cache for the eventContext.
Definition: EventSlot.h:28
void setRank(float &rank)
Set Algorithm rank.
bool visit(AlgorithmNode &) override
void recursiveVisit(AlgorithmNode &)
Depth-first node parser to calculate node eccentricity (only within the data realm of the precedence ...
const std::vector< DataNode * > & getOutputDataNodes() const
Get all supplier nodes.
AlgorithmNode * getAlgorithmNode(const std::string &algoName) const
Get the AlgorithmNode from by algorithm name using graph index.
bool m_allPass
Whether always passing regardless of daughter results.
const std::vector< DecisionNode * > & getParentDecisionHubs() const
Get all parent decision hubs.
bool visit(DecisionNode &) override
bool visitEnter(AlgorithmNode &) const override
bool visit(AlgorithmNode &) override
bool visitEnter(DecisionNode &) const override
bool m_modeOR
Whether acting as "and" (false) or "or" node (true)
bool visit(AlgorithmNode &) override
PrecedenceRulesGraph * m_graph
bool visitEnter(DecisionNode &) const override
std::vector< int > controlFlowState
State of the control flow.
Definition: EventSlot.h:37
DataReadyPromoter(EventSlot &slot, const Cause &cause, bool ifTrace=false)
Constructor.
const DataObjID & getPath()
const std::vector< ControlFlowNode * > & getDaughters() const
Get children nodes.
bool visit(AlgorithmNode &) override
void runThroughAdjacents(boost::graph_traits< precedence::PrecTrace >::vertex_descriptor, precedence::PrecTrace)
boost::adjacency_list< boost::vecS, boost::vecS, boost::bidirectionalS, AlgoTraceProps > PrecTrace
virtual bool isValidID(const EventContext &ctx, const DataObjID &id) const =0
check to see if a specific condition object ID is valid for this event
bool m_modePromptDecision
Whether to evaluate the hub decision ASA its child decisions allow to do that.
void addEdgeToPrecTrace(const AlgorithmNode *u, const AlgorithmNode *v)
set cause-effect connection between two algorithms in the precedence trace
bool visit(DecisionNode &) override
bool visit(AlgorithmNode &) override
bool m_inverted
Whether the selection result is negated or not.
bool isLiar() const
Check if control flow logic is always inverted.
bool visit(AlgorithmNode &) override
const std::string & getNodeName() const
Get node name.
const unsigned int & getNodeIndex() const
Get node index.
State
Execution states of the algorithms.
STL class.
std::string m_sourceName
const std::vector< AlgorithmNode * > & getProducers() const
Get all data object producers.
AlgsExecutionStates::State State
StatusCode updateState(unsigned int iAlgo, State newState)