The Gaudi Framework  v29r0 (ff2e7097)
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 );
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_allPass && !foundNonResolvedChild ) decision = 1;
186 
187  if ( decision != -1 ) {
188  m_slot->controlFlowState[node.getNodeIndex()] = decision;
189  return true;
190  }
191  return false;
192  }
193 
194  //---------------------------------------------------------------------------
196  {
197 
198  if ( m_slot->controlFlowState[node.getNodeIndex()] != -1 ) return false;
199  return true;
200  }
201 
202  //--------------------------------------------------------------------------
204  {
205 
206  bool result = false;
207 
208  auto& states = m_slot->algsStates;
209  auto& state = states[node.getAlgoIndex()];
210 
211  // Promote with INITIAL->CR
212  if ( State::INITIAL == state ) states.updateState( node.getAlgoIndex(), State::CONTROLREADY ).ignore();
213 
214  // Try to promote with CR->DR
215  if ( State::CONTROLREADY == state ) {
216  auto promoter = DataReadyPromoter( *m_slot, m_cause, m_trace );
217  result = promoter.visit( node );
218  } else {
219  result = true;
220  }
221 
222  // return true only when an algorithm is not lower than DR in its FSM
223  // i.e., the visitor has done everything it could with this algorithm
224  return result;
225  }
226 
227  //--------------------------------------------------------------------------
229  {
230 
231  auto& products = node.getOutputDataNodes();
232  float rank = 0;
233 
234  for ( auto p : products ) rank += p->getConsumers().size();
235 
236  node.setRank( rank );
237  /*std::stringstream s;
238  s << node.getNodeName() << ", " << rank << "\n";
239  std::ofstream myfile;
240  myfile.open("AlgoRank.csv", std::ios::app);
241  myfile << s.str();
242  myfile.close();*/
243 
244  return true;
245  }
246 
247  //--------------------------------------------------------------------------
249  {
250 
251  std::ifstream myfile;
252  myfile.open( "InputExecutionPlan.graphml", std::ios::in );
253 
254  precedence::PrecTrace execPlan;
255 
257  using boost::get;
258 
259  boost::dynamic_properties dp;
260  dp.property( "name", get( &AlgoTraceProps::m_name, execPlan ) );
261  dp.property( "index", get( &AlgoTraceProps::m_index, execPlan ) );
262  dp.property( "dataRank", get( &AlgoTraceProps::m_rank, execPlan ) );
263  dp.property( "runtime", get( &AlgoTraceProps::m_runtime, execPlan ) );
264 
265  boost::read_graphml( myfile, execPlan, dp );
266 
267  typedef boost::graph_traits<precedence::PrecTrace>::vertex_iterator itV;
269 
270  for ( vp = boost::vertices( execPlan ); vp.first != vp.second; ++vp.first ) {
271  precedence::AlgoTraceVertex v = *vp.first;
272  auto index = get( &AlgoTraceProps::m_name, execPlan );
273  if ( index[v] == node.getNodeName() ) {
274  runThroughAdjacents( v, execPlan );
275  float rank = m_nodesSucceeded;
276  node.setRank( rank );
277  reset();
278  // std::cout << "Rank of " << index[v] << " is " << rank << std::endl;
279  }
280  }
281 
282  return true;
283  }
284 
285  //--------------------------------------------------------------------------
287  boost::graph_traits<precedence::PrecTrace>::vertex_descriptor vertex, precedence::PrecTrace graph )
288  {
289  typename boost::graph_traits<precedence::PrecTrace>::adjacency_iterator itVB;
290  typename boost::graph_traits<precedence::PrecTrace>::adjacency_iterator itVE;
291 
292  for ( boost::tie( itVB, itVE ) = adjacent_vertices( vertex, graph ); itVB != itVE; ++itVB ) {
293  m_nodesSucceeded += 1;
294  runThroughAdjacents( *itVB, graph );
295  }
296  }
297 
298  //--------------------------------------------------------------------------
300  {
301 
302  std::ifstream myfile;
303  myfile.open( "InputExecutionPlan.graphml", std::ios::in );
304 
305  precedence::PrecTrace execPlan;
307  using boost::get;
308 
309  boost::dynamic_properties dp;
310  dp.property( "name", get( &AlgoTraceProps::m_name, execPlan ) );
311  dp.property( "index", get( &AlgoTraceProps::m_index, execPlan ) );
312  dp.property( "dataRank", get( &AlgoTraceProps::m_rank, execPlan ) );
313  dp.property( "runtime", get( &AlgoTraceProps::m_runtime, execPlan ) );
314 
315  boost::read_graphml( myfile, execPlan, dp );
316 
317  typedef boost::graph_traits<precedence::PrecTrace>::vertex_iterator itV;
319 
320  for ( vp = boost::vertices( execPlan ); vp.first != vp.second; ++vp.first ) {
321  precedence::AlgoTraceVertex v = *vp.first;
322  auto index = get( &AlgoTraceProps::m_name, execPlan );
323  if ( index[v] == node.getNodeName() ) {
324  auto index_runtime = get( &AlgoTraceProps::m_runtime, execPlan );
325  float rank = index_runtime[v];
326  node.setRank( rank );
327  // std::cout << "Rank of " << index[v] << " is " << rank << std::endl;
328  }
329  }
330  return true;
331  }
332 
333  //--------------------------------------------------------------------------
335  {
336 
337  std::ifstream myfile;
338  myfile.open( "Eccentricity.graphml", std::ios::in );
339 
340  precedence::PrecTrace execPlan;
341 
342  boost::dynamic_properties dp;
343  using boost::get;
344 
345  dp.property( "name", get( &precedence::AlgoTraceProps::m_name, execPlan ) );
346  dp.property( "Eccentricity", get( &precedence::AlgoTraceProps::m_eccentricity, execPlan ) );
347 
348  boost::read_graphml( myfile, execPlan, dp );
349 
350  typedef boost::graph_traits<precedence::PrecTrace>::vertex_iterator itV;
352 
353  for ( vp = boost::vertices( execPlan ); vp.first != vp.second; ++vp.first ) {
354  precedence::AlgoTraceVertex v = *vp.first;
355  auto index = get( &precedence::AlgoTraceProps::m_name, execPlan );
356  if ( index[v] == node.getNodeName() ) {
357  auto index_eccentricity = get( &precedence::AlgoTraceProps::m_eccentricity, execPlan );
358  float rank = index_eccentricity[v];
359  node.setRank( rank );
360  // std::cout << "Rank of " << index[v] << " is " << rank << std::endl;
361  }
362  }
363  return true;
364  }
365 
366  //--------------------------------------------------------------------------
368  {
369 
370  // Find eccentricity of the node (only within the data realm of the execution flow graph)
371  recursiveVisit( node );
372 
373  float rank = m_maxKnownDepth;
374  node.setRank( rank );
375 
376  // Reset visitor for next nodes, if any
377  reset();
378 
379  return true;
380  }
381 
382  //--------------------------------------------------------------------------
384  {
385 
386  m_currentDepth += 1;
387 
388  auto& products = node.getOutputDataNodes();
389 
390  if ( products.empty() )
391  if ( ( m_currentDepth - 1 ) > m_maxKnownDepth ) m_maxKnownDepth = m_currentDepth - 1;
392 
393  for ( auto p : products )
394  for ( auto algoNode : p->getConsumers() ) recursiveVisit( *algoNode );
395 
396  m_currentDepth -= 1;
397  }
398 
399  //---------------------------------------------------------------------------
401  {
402 
403  if ( m_slot->controlFlowState[node.getNodeIndex()] != 1 ) return true;
404  return false;
405  }
406 
407  //---------------------------------------------------------------------------
409  {
410 
411  // std::cout << "1-st level Decision: " << node.getNodeName() << std::endl;
412  bool allChildDecisionsResolved = true;
413  for ( auto child : node.getDaughters() ) {
414  int& childDecision = m_slot->controlFlowState[child->getNodeIndex()];
415 
416  if ( childDecision == 1 && node.m_modeOR && node.m_modePromptDecision ) {
417  m_slot->controlFlowState[node.getNodeIndex()] = 1;
418  return true;
419  }
420 
421  if ( childDecision == -1 ) {
422  allChildDecisionsResolved = false;
423  }
424  }
425 
426  if ( allChildDecisionsResolved ) m_slot->controlFlowState[node.getNodeIndex()] = 1;
427 
428  return allChildDecisionsResolved;
429  }
430 
431  //---------------------------------------------------------------------------
433  {
434 
435  if ( m_slot->controlFlowState[node.getNodeIndex()] != 1 ) return true;
436  return false;
437  }
438 
439  //--------------------------------------------------------------------------
441  {
442 
443  auto& states = m_slot->algsStates;
444  int& decision = m_slot->controlFlowState[node.getNodeIndex()];
445 
446  auto dataPromoter = DataReadyPromoter( *m_slot, m_cause );
447 
448  if ( State::INITIAL == states[node.getAlgoIndex()] ) {
449  states.updateState( node.getAlgoIndex(), State::CONTROLREADY );
450  if ( dataPromoter.visit( node ) ) {
451  states.updateState( node.getAlgoIndex(), State::SCHEDULED );
452  states.updateState( node.getAlgoIndex(), State::EVTACCEPTED );
453  decision = 1;
454  ++m_nodesSucceeded;
455  // std::cout << "Algorithm decided: " << node.getNodeName() << std::endl;
456  return true;
457  }
458  } else if ( State::CONTROLREADY == states[node.getAlgoIndex()] && dataPromoter.visit( node ) ) {
459  states.updateState( node.getAlgoIndex(), State::SCHEDULED );
460  states.updateState( node.getAlgoIndex(), State::EVTACCEPTED );
461  decision = 1;
462  ++m_nodesSucceeded;
463  // std::cout << "Algorithm decided: " << node.getNodeName() << std::endl;
464  return true;
465  }
466 
467  return false;
468  }
469 }
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:37
EventContext * eventContext
Cache for the eventContext.
Definition: EventSlot.h:32
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:43
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 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)