void RecurrentNN::strongConnect(long v, long index, std::vector<long> &stack,  std::vector<RecurrentNN::CycleNode> &nodes,  std::vector<std::vector<long> > &components)
{
    std::vector<long> connectedComponent;
    
    CycleNode &cn = nodes[v];
    cn.index = index;
    cn.lowlink = index;
    index = index+1;
    stack.push_back(v);
    
    std::vector<DelayEdge> succesors = outputsFromNode(v);
    for (long i=0; i<succesors.size(); i++) {
        long toNode = succesors[i].nodeTo;
        CycleNode &nextN = nodes[toNode];
        if (nextN.index < 0) {
            strongConnect(toNode, index, stack, nodes, components);
            cn.lowlink = std::min(nextN.lowlink, cn.lowlink);
        } else if (std::find(stack.begin(), stack.end(), toNode) != stack.end()) {
            // Successor w is in stack S and hence in the current SCC
            cn.lowlink = std::min(nextN.index, cn.lowlink);
        }
    }
    
    if (cn.lowlink == cn.index) {
        long nodeFrom = v;
        long nodeTo = -1;
        do {
            nodeTo = stack.back();
            stack.pop_back();
            connectedComponent.push_back(nodeTo);
        } while (nodeFrom != nodeTo);
        components.push_back(connectedComponent);
    }
}
void SCCDetector::strongConnect(uint v)
{
    // Set the depth index for v to the smallest unused index
    m_indexes[v] = m_index;
    m_lowlinks[v] = m_index;
    m_index++;
    m_stack.push(v);
    m_in_stack[v] = true;

    // Consider successors of v
    for (uint edgeInd = 0; edgeInd < m_graph->conn_vec.size(); ++edgeInd)
    {
        // for each (v, w) in E
        cola::Edge edge = m_graph->edges[edgeInd];
        if ( (edge.first == v) && m_graph->conn_vec[edgeInd]->isDirected() &&
                m_graph->conn_vec[edgeInd]->obeysDirectedEdgeConstraints() )
        {
            int w = edge.second;
            if (m_indexes[w] == k_undefined)
            {
                // Successor w has not yet been visited; recurse on it
                strongConnect(w);
                m_lowlinks[v] = qMin(m_lowlinks[v], m_lowlinks[w]);
            }
            else if (m_in_stack[w])
            {
                // Successor w is in stack S and hence in the current SCC
                m_lowlinks[v] = qMin(m_lowlinks[v], m_indexes[w]);
            }
        }
    }

    // If v is a root node, pop the stack and generate an SCC
    if (m_lowlinks[v] == m_indexes[v])
    {
        // start a new strongly connected component
        m_scc_index++;
        uint w;
        do
        {
            w = m_stack.pop();
            m_in_stack[w] = false;
            // add w to current strongly connected component
            m_scc_indexes[w] = m_scc_index;
        }
        while (w != v);
    }
}
Exemple #3
0
int main() {
	int N, P; // number of persons number of shares link
	int scanRes = 0;
  //read N and read P;
  scanRes = scanf("%d %d", &N, &P);
  if(scanRes <= 0 && scanRes != EOF) {
			std::cout << "Error reading from standard input." << std::endl;
		}

  //initialize the shared vector equal to number of person
	for(int i = 0; i < N+1 ; i++) {
		nodes.push_back(new Node());
	}
	
  adjacencias = std::vector<std::vector<int> > (N+1);
	
   
  //for each share, read
  for(int i = 0 ; i < P ; i++) {
  	int u, v;
		scanRes = scanf("%d %d", &u, &v);
		if(scanRes <= 0 && scanRes != EOF) {
			std::cout << "Error reading from standard input." << std::endl;
		}

		adjacencias[u].push_back(v);
	}
	
		
	for(unsigned long u = 1; u != nodes.size(); u++) {
		if (nodes[u]->getIndex() == UNDEFINED){
			strongConnect(u);
		}
	}
	
	#ifdef DEBUG
	std::cout << "--- Scc associado ---" << std::endl; 
	for(unsigned long u = 1; u != nodes.size(); u++) {
		std::cout << u << ": " << nodes[u]->getScc() << std::endl;
	}
	#endif
	
  printf("%d\n", numberOfSCC);
  printf("%d\n", sccMaxSize);
  printf("%d\n", numberOfIsolatedSCC + numberOfSCC);
  return 0;
} 
Exemple #4
0
ClusteringResult TarjansAlgorithm::run(const Eigen::MatrixXd & adjacencies_)
{
	adjacencies = &adjacencies_;

	n = adjacencies->rows();
	if (n != adjacencies->cols())
	{
		throw std::runtime_error("Adjacency matrix must be quadratic!");
	}

	index = 0;

	nodes.clear();
	for (unsigned i = 0; i < n; i++)
	{
		nodes.emplace_back();
		nodes.back().adjacencyIdx = i;
	}

	stack = std::stack<Node*>();

	ClusteringResult res;
	res.labels.resize(n);

	for (auto & node : nodes)
	{
		if (node.index == -1)
		{
			std::vector<unsigned> componentIndexes = strongConnect(node);
			if (componentIndexes.size() > 0)
			{
				for (unsigned idx : componentIndexes)
				{
					res.labels[idx] = res.numClusters;
				}
				res.numClusters++;				
			}
		}
	}

	return res; 	
}
Exemple #5
0
std::vector<unsigned> TarjansAlgorithm::strongConnect(Node & v)
{
	v.index = index;
	v.lowLink = index;
	index++;
	stack.push(&v);
	v.onStack = true;

	// consider successors of v
	for (unsigned e = 0; e < n; e++)
	{
		if ((*adjacencies)(v.adjacencyIdx, e) > 0) // edge
		{
			Node & w = nodes[e];
			if (w.index == -1)
			{
				strongConnect(w);
				v.lowLink = std::min(v.lowLink, w.lowLink);
			} else if (w.onStack)
			{
				v.lowLink = std::min(v.lowLink, w.index);
			}
		}
	}

	// If v is a root node, pop the stack and generate a strongly connected component
	std::vector<unsigned> componentIndexes;
	if (v.lowLink == v.index)
	{
		Node * w;
		do
		{
			w = stack.top();
			stack.pop();
			w->onStack = false;
			componentIndexes.push_back(w->adjacencyIdx);
		} while (w != &v);

	}

	return componentIndexes;
}
QVector<int> SCCDetector::stronglyConnectedComponentIndexes(GraphData *graph)
{
    m_graph = graph;
    m_index = 0;
    m_scc_index = 0;
    int shapesCount = m_graph->shape_vec.size();

    m_indexes = QVector<int>(shapesCount, k_undefined);
    m_scc_indexes = QVector<int>(shapesCount, 0);
    m_lowlinks = QVector<int>(shapesCount, 0);
    m_in_stack = QVector<bool>(shapesCount, false);
    m_stack.clear();

    for (int i = 0; i < shapesCount; ++i)
    {
        if (m_indexes[i] == k_undefined)
        {
            strongConnect(i);
        }
    }
    return m_scc_indexes;
}
//http://en.wikipedia.org/wiki/Tarjan’s_strongly_connected_components_algorithm
std::vector<std::vector<long> > RecurrentNN::cycleSort()
{
    std::vector<std::vector<long> > sorted;
    std::vector<long> stack;
    
    std::vector<RecurrentNN::CycleNode> cycleNodes;

    long index = 0;
    // make a CycleNode for each actual node
    for (long i=0; i<nodes.size(); i++) {
        CycleNode cn = CycleNode(i);
        cycleNodes.push_back(cn);
    }
    
    for (long i=0; i<cycleNodes.size(); i++) {
        if (cycleNodes[i].index < 0) {
            strongConnect(i, index, stack, cycleNodes, sorted);
        }
    }
    
    
    return sorted;
}
Exemple #8
0
void strongConnect(int u) {
	Node* raiz = nodes[u];

	raiz->setup();
	nodeStack.push(u);
	raiz->setInStack(true);
	

	for(unsigned long v = 0; v < adjacencias[u].size(); v++) {

		int vizinho = adjacencias[u][v];
		Node* noVizinho = nodes[vizinho];

		if(noVizinho->getIndex() == UNDEFINED){
			strongConnect(vizinho);
			raiz->setLowIndex(std::min(raiz->getLowIndex(), noVizinho->getLowIndex()));
		}
		else if (noVizinho->isInStack()){
			raiz->setLowIndex(std::min(raiz->getLowIndex(), noVizinho->getIndex()));
		}
	}
  
  
	if(raiz->getLowIndex() == raiz->getIndex() ){
		numberOfSCC++;
		int currentSCCSize = 0;
		int poppedNodeIndex = 0;
		Node* node = NULL;
		bool run_once = false;
		
		#ifdef DEBUG
		std::cout << "--- popping ---" << std::endl;
		#endif

		do {
			poppedNodeIndex = nodeStack.top();
			#ifdef DEBUG
			std::cout << "popped: " << poppedNodeIndex << std::endl;
			#endif
			nodeStack.pop();
			nodes[poppedNodeIndex]->setInStack(false);
			node = nodes[poppedNodeIndex];
			currentSCCSize++;
			node->setScc(numberOfSCC);
			
			if(!run_once && find(poppedNodeIndex, last_rootNode_popped)){
				#ifdef DEBUG
				std::cout << "!! found: " << poppedNodeIndex << " " << last_rootNode_popped << std::endl;
				#endif
				numberOfIsolatedSCC--;
				run_once = true;
			}
		} while(raiz->getIndex() != node->getIndex());

		last_rootNode_popped = poppedNodeIndex;
		run_once = false;


		node->setScc(numberOfSCC);
		
		sccMaxSize = std::max(sccMaxSize, currentSCCSize);
	}
}