org.chocosolver.graphsolver.util.ConnectivityFinder Maven / Gradle / Ivy
Show all versions of choco-graph Show documentation
/**
* Copyright (c) 1999-2011, Ecole des Mines de Nantes
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Ecole des Mines de Nantes nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Created by IntelliJ IDEA.
* User: Jean-Guillaume Fages
* Date: 17/04/2016
* Time: 13:11
*/
/**
* Created by IntelliJ IDEA.
* User: Jean-Guillaume Fages
* Date: 17/04/2016
* Time: 13:11
*/
package org.chocosolver.graphsolver.util;
import gnu.trove.list.array.TIntArrayList;
import org.chocosolver.util.objects.graphs.IGraph;
import org.chocosolver.util.objects.setDataStructures.ISet;
import java.util.Iterator;
/**
* Class containing algorithms to find all connected components and articulation points of graph by performing one dfs
* it uses Tarjan algorithm in a non recursive way and can be performed in O(M+N) time c.f. Gondrand Minoux
*
* @author Jean-Guillaume Fages
*/
public class ConnectivityFinder {
//***********************************************************************************
// CONNECTED COMPONENTS ONLY
//***********************************************************************************
private int n;
private IGraph graph;
private int[] CC_firstNode, CC_nextNode, node_CC, p, fifo;
private int nbCC;
//bonus biconnection
private int[] numOfNode, nodeOfNum, inf;
private Iterator[] iterators;
/**
* Create an object that can compute Connected Components (CC) of a graph g
* Can also quickly tell whether g is biconnected or not (only for undirected graph)
*
* @param g graph
*/
public ConnectivityFinder(IGraph g) {
graph = g;
n = g.getNbMaxNodes();
p = new int[n];
fifo = new int[n];
iterators = new Iterator[n];
}
/**
* get the number of CC in g
* Beware you should call method findAllCC() first
*
* @return nbCC the number of CC in g
*/
public int getNBCC() {
return nbCC;
}
public int[] getCC_firstNode() {
return CC_firstNode;
}
public int[] getCC_nextNode() {
return CC_nextNode;
}
public int[] getNode_CC() {
return node_CC;
}
/**
* Find all connected components of graph by performing one dfs
* Complexity : O(M+N) light and fast in practice
*/
public void findAllCC() {
if (node_CC == null) {
CC_firstNode = new int[n];
CC_nextNode = new int[n];
node_CC = new int[n];
}
ISet act = graph.getNodes();
for (int i : act) {
p[i] = -1;
}
for(int i=0;i 1) {
return false;// ARTICULATION POINT DETECTED
}
}
i = j;
k++;
numOfNode[i] = k;
nodeOfNum[k] = i;
inf[i] = numOfNode[i];
} else if (p[i] != j) {
inf[i] = Math.min(inf[i], numOfNode[j]);
}
}else {
if (i == start) {
return k >= act.size() - 1;
}
q = inf[i];
i = p[i];
inf[i] = Math.min(q, inf[i]);
if (q >= numOfNode[i] && i != start) {
return false;
} // ARTICULATION POINT DETECTED
}
}
}
public TIntArrayList isthmusFrom, isthmusTo;
private int[] ND, L, H;
/**
* Only for undirected graphs
* @return true iff g is connected
*/
public boolean isConnectedAndFindIsthma() {
assert (!graph.isDirected());
if (numOfNode == null || CC_firstNode == null) {
CC_firstNode = new int[n];
CC_nextNode = new int[n];
node_CC = new int[n];
nodeOfNum = new int[n];
numOfNode = new int[n];
isthmusFrom = new TIntArrayList();
isthmusTo = new TIntArrayList();
ND = new int[n];
L = new int[n];
H = new int[n];
}
ISet act = graph.getNodes();
for (int i : act) {
p[i] = -1;
iterators[i] = graph.getSuccOrNeighOf(i).iterator();
}
for(int i=0;i= 0; i--) {
currentNode = nodeOfNum[i];
ND[currentNode] = 1;
L[currentNode] = i;
H[currentNode] = i;
for (int s : graph.getSuccOrNeighOf(currentNode)) {
if (p[s] == currentNode) {
ND[currentNode] += ND[s];
L[currentNode] = Math.min(L[currentNode], L[s]);
H[currentNode] = Math.max(H[currentNode], H[s]);
} else if (s != p[currentNode]) {
L[currentNode] = Math.min(L[currentNode], numOfNode[s]);
H[currentNode] = Math.max(H[currentNode], numOfNode[s]);
}
if (s != currentNode && p[s] == currentNode && L[s] >= numOfNode[s] && H[s] < numOfNode[s] + ND[s]) {
isthmusFrom.add(currentNode);
isthmusTo.add(s);
}
}
}
return true;
}
}