tensorflow/core/grappler/utils/scc.cc
// This is an implementation of Tarjan's Strongly Connected Components
// DFS algorithm.  Most of the hard work is done in the function
// StrongConnect, which is an iterative reimplementation of the
// recursive version described here:
//   https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm
//
// The edges for the purpose of this algorithm are directed from input
// to op (the reverse of the declarations of the NodeDef, which
// contain in-edges)
This is an implementation of Tarjan's Strongly Connected Components
DFS algorithm.

The edges for the purpose of this algorithm are directed from input
to op (the reverse of the declarations of the NodeDef, which
contain in-edges)
This is an implementation of Tarjan ' s Strongly Connected Components DFS algorithm . The edges for the purpose of this algorithm are directed from input to op ( the reverse of the declarations of the NodeDef which contain in - edges )
void StronglyConnectedComponents(
    const GraphDef& graph, std::unordered_map<const NodeDef*, int>* components,
    int* num_components) {
  std::stack<SCCNodeData*> stack;
  std::unordered_map<string, SCCNodeData*> name_to_data;
  std::vector<SCCNodeData> node_data_container;
  node_data_container.reserve(graph.node_size());
  std::unordered_map<const NodeDef*, SCCNodeData*> node_to_data;
  for (const NodeDef& node : graph.node()) {
    SCCNodeData node_data;
    node_data.node = &node;
    node_data_container.push_back(node_data);
    name_to_data[node.name()] = &(*node_data_container.rbegin());
    node_to_data[&node] = &(*node_data_container.rbegin());
  }
  for (const NodeDef& node : graph.node()) {
    for (const string& input : node.input()) {
      auto it = name_to_data.find(NodeName(input));
      if (it != name_to_data.end()) {
        it->second->children.push_back(node_to_data[&node]);
      }
    }
  }
  components->clear();
  *num_components = 0;
  int index = 0;
  for (auto& v : node_data_container) {
    if (v.index == -1) {
      StrongConnect(&v, &stack, &index, components, num_components);
    }
  }
  std::vector<int> counts_per_component(*num_components, 0);
  for (auto& component : *components) {
    DCHECK(component.second >= 0);
    DCHECK(component.second < *num_components);
    counts_per_component[component.second]++;
  }
  bool has_single_element_component = false;
  for (auto& component : *components) {
    if (counts_per_component[component.second] == 1) {
      component.second = -1;
      (*num_components)--;
      has_single_element_component = true;
    }
  }
  if (has_single_element_component) {
    (*num_components) += 1;
  }
}
void StronglyConnectedComponents ( const GraphDef & graph , std :: unordered_map < const NodeDef * , int > * components , int * num_components ) { std :: stack < SCCNodeData * > stack ; std :: unordered_map < string , SCCNodeData * > name_to_data ; std :: vector < SCCNodeData > node_data_container ; node_data_container . reserve ( graph . node_size ( ) ) ; std :: unordered_map < const NodeDef * , SCCNodeData * > node_to_data ; for ( const NodeDef & node : graph . node ( ) ) { SCCNodeData node_data ; node_data . node = & node ; node_data_container . push_back ( node_data ) ; name_to_data [ node . name ( ) ] = & ( * node_data_container . rbegin ( ) ) ; node_to_data [ & node ] = & ( * node_data_container . rbegin ( ) ) ; } for ( const NodeDef & node : graph . node ( ) ) { for ( const string & input : node . input ( ) ) { auto it = name_to_data . find ( NodeName ( input ) ) ; if ( it != name_to_data . end ( ) ) { it -> second -> children . push_back ( node_to_data [ & node ] ) ; } } } components -> clear ( ) ; * num_components = 0 ; int index = 0 ; for ( auto & v : node_data_container ) { if ( v . index == -1 ) { StrongConnect ( & v , & stack , & index , components , num_components ) ; } } std :: vector < int > counts_per_component ( * num_components , 0 ) ; for ( auto & component : * components ) { DCHECK ( component . second >= 0 ) ; DCHECK ( component . second < * num_components ) ; counts_per_component [ component . second ] ++ ; } bool has_single_element_component = false ; for ( auto & component : * components ) { if ( counts_per_component [ component . second ] == 1 ) { component . second = -1 ; ( * num_components ) -- ; has_single_element_component = true ; } } if ( has_single_element_component ) { ( * num_components ) += 1 ; } }
This is an implementation of Tarjan's Strongly Connected Components
DFS algorithm.
This is an implementation of Tarjan ' s Strongly Connected Components DFS algorithm .
// Create a list of top-level parents (add them to object queue) // Also create a mapping from nodes to their children. // Inputs might not be present if called on a subgraph. // Node has not yet been visited.  Start a DFS at v.