The Gaudi Framework  master (37c0b60a)
concurrency::TarjanSCCFinder Class Reference

#include </builds/gaudi/Gaudi/GaudiHive/src/PRGraph/Visitors/Validators.h>

Inheritance diagram for concurrency::TarjanSCCFinder:
Collaboration diagram for concurrency::TarjanSCCFinder:

Public Member Functions

bool visitEnter (ConditionNode &) const override
 
bool visitEnter (DecisionNode &) const override
 
bool visitEnter (AlgorithmNode &node) const override
 
bool visit (AlgorithmNode &nodeAt) override
 
bool passed () const
 
std::string reply ()
 
void reset () override
 
virtual bool visit (DecisionNode &)
 
virtual bool visit (AlgorithmNode &)
 
virtual bool visit (DataNode &)
 
virtual bool visit (ConditionNode &)
 
virtual bool visitEnter (DecisionNode &) const
 
virtual bool visitEnter (AlgorithmNode &) const
 
virtual bool visitEnter (DataNode &) const
 
virtual bool visitEnter (ConditionNode &) const
 
- Public Member Functions inherited from concurrency::IGraphVisitor
virtual ~IGraphVisitor ()=default
 
virtual bool visit (DecisionNode &)
 
virtual bool visitEnter (DataNode &) const
 
virtual bool visit (DataNode &)
 
virtual bool visit (ConditionNode &)
 

Private Member Functions

bool on_stack (const AlgorithmNode &node) const
 

Private Attributes

unsigned int m_nodes_count { 0 }
 
std::unordered_map< AlgorithmNode *, std::pair< unsigned int, unsigned int > > m_lowlinks
 
std::map< unsigned int, std::vector< AlgorithmNode * > > m_scc
 
std::vector< AlgorithmNode * > m_stack
 
std::ostringstream m_status { " No strongly connected components found in DF realm" }
 

Detailed Description

The visitor implements the Tarjan algorithm for searching strongly connected components in the data flow realm of precedence rules graph.

Definition at line 169 of file Validators.h.

Member Function Documentation

◆ on_stack()

bool concurrency::TarjanSCCFinder::on_stack ( const AlgorithmNode node) const
inlineprivate

Definition at line 199 of file Validators.h.

199  {
200  return std::find( m_stack.begin(), m_stack.end(), &node ) != m_stack.end() ? true : false;
201  }

◆ passed()

bool concurrency::TarjanSCCFinder::passed ( ) const
inline

Definition at line 183 of file Validators.h.

183  {
184  return m_scc.empty() ||
185  !std::any_of( m_scc.begin(), m_scc.end(), []( const auto& pr ) { return pr.second.size() > 1; } );
186  }

◆ reply()

std::string concurrency::TarjanSCCFinder::reply ( )

Definition at line 281 of file Validators.cpp.

281  {
282 
283  if ( !passed() ) {
284 
285  m_status << " Strongly connected components found in DF realm:";
286 
287  for ( auto& pr : m_scc ) {
288  if ( pr.second.size() > 1 ) {
289  m_status << "\n o [lowlink:" << std::to_string( pr.first ) << "] |";
290 
291  // rotate SCCs to get reproducible order
292  std::vector sortedSCC( pr.second.begin(), pr.second.end() );
293  std::sort( sortedSCC.begin(), sortedSCC.end(), CompareNodes<AlgorithmNode*>() );
294  std::rotate( pr.second.begin(), std::find( pr.second.begin(), pr.second.end(), sortedSCC.front() ),
295  pr.second.end() );
296 
297  for ( const auto& algoPtr : pr.second ) m_status << " " << algoPtr->name() << " |";
298  }
299  }
300  }
301 
302  return m_status.str();
303  }

◆ reset()

void concurrency::TarjanSCCFinder::reset ( )
inlineoverridevirtual

Reimplemented from concurrency::IGraphVisitor.

Definition at line 190 of file Validators.h.

190  {
191  m_nodes_count = 0;
192  m_stack.clear();
193  m_lowlinks.clear();
194  m_scc.clear();
195  m_status = std::ostringstream{ " No strongly connected components found in DF realm" };
196  }

◆ visit() [1/5]

virtual bool concurrency::IGraphVisitor::visit
inline

Definition at line 29 of file IGraphVisitor.h.

29 { return true; }

◆ visit() [2/5]

bool concurrency::TarjanSCCFinder::visit ( AlgorithmNode nodeAt)
overridevirtual

Reimplemented from concurrency::IGraphVisitor.

Definition at line 235 of file Validators.cpp.

235  {
236 
237  // DFS ******************************************************
238 
239  // put the node on stack
240  m_stack.push_back( &nodeAt );
241 
242  // initialize and cache the low-link value of this node
243  m_nodes_count += 1;
244  unsigned int lowlink_init{ m_nodes_count };
245  // record initial low-link value of this node
246  m_lowlinks.insert( { &nodeAt, { lowlink_init, lowlink_init } } );
247  auto& lowlink = m_lowlinks[&nodeAt].second;
248 
249  for ( const auto& output : nodeAt.getOutputDataNodes() ) {
250  for ( const auto& consumer : output->getConsumers() ) {
251  consumer->accept( *this );
252  // DFS callback ******************************************
253  // propagate the low-link value back
254  if ( on_stack( *consumer ) ) {
255  if ( lowlink > m_lowlinks[consumer].second ) lowlink = m_lowlinks[consumer].second;
256  // this allows to detect loops (i.e., a cycle consisting of a single algorithm node: A->d->A),
257  // but there is a protection against this case at Algorithm::initialize()
258  if ( consumer == &nodeAt ) m_scc.insert( { lowlink, { &nodeAt } } );
259  }
260  }
261  }
262 
263  // If an SCC is found, book-keep it and take it off the stack
264  if ( lowlink_init == lowlink ) {
265  if ( m_scc.find( lowlink ) == m_scc.end() ) m_scc.insert( { lowlink, {} } );
266 
267  for ( auto stackNodeRIter = m_stack.rbegin(); stackNodeRIter != m_stack.rend(); ++stackNodeRIter ) {
268 
269  bool lastSCCNodeOnStack{ *stackNodeRIter == &nodeAt };
270  if ( lowlink == m_lowlinks[*stackNodeRIter].second ) m_scc[lowlink].push_back( *stackNodeRIter );
271 
272  m_stack.pop_back();
273  if ( lastSCCNodeOnStack ) break;
274  }
275  }
276 
277  return true;
278  }

◆ visit() [3/5]

virtual bool concurrency::IGraphVisitor::visit
inline

Definition at line 35 of file IGraphVisitor.h.

35 { return true; }

◆ visit() [4/5]

virtual bool concurrency::IGraphVisitor::visit
inline

Definition at line 32 of file IGraphVisitor.h.

32 { return true; }

◆ visit() [5/5]

virtual bool concurrency::IGraphVisitor::visit
inline

Definition at line 26 of file IGraphVisitor.h.

26 { return true; }

◆ visitEnter() [1/7]

virtual bool concurrency::IGraphVisitor::visitEnter
inline

Definition at line 28 of file IGraphVisitor.h.

28 { return true; }

◆ visitEnter() [2/7]

bool concurrency::TarjanSCCFinder::visitEnter ( AlgorithmNode node) const
inlineoverridevirtual

Reimplemented from concurrency::IGraphVisitor.

Definition at line 176 of file Validators.h.

176  {
177  // check if the node was already visited
178  return m_lowlinks.find( &node ) != m_lowlinks.end() ? false : true;
179  }

◆ visitEnter() [3/7]

virtual bool concurrency::IGraphVisitor::visitEnter
inline

Definition at line 34 of file IGraphVisitor.h.

34 { return true; }

◆ visitEnter() [4/7]

bool concurrency::TarjanSCCFinder::visitEnter ( ConditionNode ) const
inlineoverridevirtual

Reimplemented from concurrency::IGraphVisitor.

Definition at line 174 of file Validators.h.

174 { return false; }

◆ visitEnter() [5/7]

virtual bool concurrency::IGraphVisitor::visitEnter
inline

Definition at line 31 of file IGraphVisitor.h.

31 { return true; }

◆ visitEnter() [6/7]

virtual bool concurrency::IGraphVisitor::visitEnter
inline

Definition at line 25 of file IGraphVisitor.h.

25 { return true; }

◆ visitEnter() [7/7]

bool concurrency::TarjanSCCFinder::visitEnter ( DecisionNode ) const
inlineoverridevirtual

Reimplemented from concurrency::IGraphVisitor.

Definition at line 175 of file Validators.h.

175 { return false; }

Member Data Documentation

◆ m_lowlinks

std::unordered_map<AlgorithmNode*, std::pair<unsigned int, unsigned int> > concurrency::TarjanSCCFinder::m_lowlinks
private

Definition at line 205 of file Validators.h.

◆ m_nodes_count

unsigned int concurrency::TarjanSCCFinder::m_nodes_count { 0 }
private

Definition at line 203 of file Validators.h.

◆ m_scc

std::map<unsigned int, std::vector<AlgorithmNode*> > concurrency::TarjanSCCFinder::m_scc
private

Definition at line 206 of file Validators.h.

◆ m_stack

std::vector<AlgorithmNode*> concurrency::TarjanSCCFinder::m_stack
private

Definition at line 207 of file Validators.h.

◆ m_status

std::ostringstream concurrency::TarjanSCCFinder::m_status { " No strongly connected components found in DF realm" }
private

Definition at line 209 of file Validators.h.


The documentation for this class was generated from the following files:
std::vector
STL class.
std::find
T find(T... args)
std::rotate
T rotate(T... args)
Gaudi::Units::second
constexpr double second
Definition: SystemOfUnits.h:139
std::any_of
T any_of(T... args)
gaudirun.output
output
Definition: gaudirun.py:521
std::sort
T sort(T... args)
concurrency::TarjanSCCFinder::m_stack
std::vector< AlgorithmNode * > m_stack
Definition: Validators.h:207
concurrency::TarjanSCCFinder::m_lowlinks
std::unordered_map< AlgorithmNode *, std::pair< unsigned int, unsigned int > > m_lowlinks
Definition: Validators.h:205
std::to_string
T to_string(T... args)
concurrency::TarjanSCCFinder::on_stack
bool on_stack(const AlgorithmNode &node) const
Definition: Validators.h:199
std::ostringstream
STL class.
concurrency::TarjanSCCFinder::m_scc
std::map< unsigned int, std::vector< AlgorithmNode * > > m_scc
Definition: Validators.h:206
concurrency::TarjanSCCFinder::passed
bool passed() const
Definition: Validators.h:183
std::ostringstream::str
T str(T... args)
concurrency::TarjanSCCFinder::m_status
std::ostringstream m_status
Definition: Validators.h:209
concurrency::TarjanSCCFinder::m_nodes_count
unsigned int m_nodes_count
Definition: Validators.h:203