Update.
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
package org.insa.algo.strongconnectivity ;
|
||||
|
||||
import org.insa.algo.AbstractAlgorithm;
|
||||
|
||||
public abstract class StronglyConnectedComponentsAlgorithm extends AbstractAlgorithm {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param instance
|
||||
* @param logOutput
|
||||
*/
|
||||
public StronglyConnectedComponentsAlgorithm(StronglyConnectedComponentsInstance instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
package org.insa.algo.strongconnectivity;
|
||||
|
||||
import org.insa.algo.AbstractInstance;
|
||||
import org.insa.graph.Graph;
|
||||
|
||||
public class StronglyConnectedComponentsInstance extends AbstractInstance {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param graph
|
||||
*/
|
||||
public StronglyConnectedComponentsInstance(Graph graph) {
|
||||
super(graph);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package org.insa.algo.strongconnectivity;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.insa.algo.AbstractSolution;
|
||||
import org.insa.graph.Node;
|
||||
|
||||
public class StronglyConnectedComponentsSolution extends AbstractSolution {
|
||||
|
||||
// Components
|
||||
private ArrayList<ArrayList<Node>> components;
|
||||
|
||||
protected StronglyConnectedComponentsSolution(StronglyConnectedComponentsInstance instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
protected StronglyConnectedComponentsSolution(StronglyConnectedComponentsInstance instance,
|
||||
Duration solvingTime, Status status, ArrayList<ArrayList<Node>> components) {
|
||||
super(instance, solvingTime, status);
|
||||
this.components = components;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Components of the solution, if any.
|
||||
*/
|
||||
public ArrayList<ArrayList<Node>> getComponents() { return components; }
|
||||
|
||||
}
|
155
src/main/org/insa/algo/strongconnectivity/TarjanAlgorithm.java
Normal file
155
src/main/org/insa/algo/strongconnectivity/TarjanAlgorithm.java
Normal file
@@ -0,0 +1,155 @@
|
||||
package org.insa.algo.strongconnectivity;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.insa.algo.AbstractSolution;
|
||||
import org.insa.algo.AbstractSolution.Status;
|
||||
import org.insa.graph.Arc;
|
||||
import org.insa.graph.Graph;
|
||||
import org.insa.graph.Node;
|
||||
|
||||
public class TarjanAlgorithm extends StronglyConnectedComponentsAlgorithm {
|
||||
|
||||
private final static int UNDEFINED = -1;
|
||||
|
||||
// Stack of nodes and flags.
|
||||
private Stack<Node> stack;
|
||||
private boolean[] inStack;
|
||||
|
||||
// Current index.
|
||||
private int index;
|
||||
|
||||
// Information of nodes
|
||||
private int[] indexes;
|
||||
private int[] lowlink;
|
||||
|
||||
// Array of strongly connected components
|
||||
ArrayList<ArrayList<Node>> components;
|
||||
|
||||
public TarjanAlgorithm(StronglyConnectedComponentsInstance instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Push the given node to the stack.
|
||||
*
|
||||
* @param node
|
||||
*/
|
||||
protected void pushNode(Node node) {
|
||||
stack.push(node);
|
||||
inStack[node.getId()] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop and return a node from the stack.
|
||||
*
|
||||
* @return Node popped from the stack
|
||||
*/
|
||||
protected Node popNode() {
|
||||
Node top = stack.pop();
|
||||
inStack[top.getId()] = false;
|
||||
return top;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given node is in the stack.
|
||||
*
|
||||
* @param node
|
||||
*
|
||||
* @return true if the given node is in the stack, false otherwize.
|
||||
*/
|
||||
protected boolean isInStack(Node node) {
|
||||
return inStack[node.getId()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the strong component containing the given node.
|
||||
*
|
||||
* @param node
|
||||
*
|
||||
* @return The strong component containing the given node.
|
||||
*/
|
||||
protected void findAndAddStrongComponent(Node v) {
|
||||
Graph graph = getInstance().getGraph();
|
||||
|
||||
// Update node info, index and push the node.
|
||||
indexes[v.getId()] = index;
|
||||
lowlink[v.getId()] = index;
|
||||
index += 1;
|
||||
pushNode(v);
|
||||
|
||||
for (Arc a: v.getSuccessors()) {
|
||||
Node w = a.getDestination();
|
||||
if (!hasBeenVisited(w)) {
|
||||
findAndAddStrongComponent(w);
|
||||
lowlink[v.getId()] = Math.min(lowlink[v.getId()], lowlink[w.getId()]);
|
||||
}
|
||||
else if (isInStack(w)) {
|
||||
lowlink[v.getId()] = Math.min(lowlink[v.getId()], indexes[w.getId()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the component (if any)
|
||||
if (lowlink[v.getId()] == indexes[v.getId()]) {
|
||||
ArrayList<Node> component = new ArrayList<Node>();
|
||||
Node w;
|
||||
do {
|
||||
w = popNode();
|
||||
component.add(w);
|
||||
} while (!w.equals(v));
|
||||
components.add(component);
|
||||
System.out.println("Size of the stack: " + stack.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given node has not been visited yet.
|
||||
*
|
||||
* @return true if the node has been visited.
|
||||
*/
|
||||
protected boolean hasBeenVisited(Node node) {
|
||||
return this.indexes[node.getId()] != UNDEFINED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractSolution doRun() {
|
||||
Graph graph = getInstance().getGraph();
|
||||
|
||||
components = new ArrayList<ArrayList<Node>>();
|
||||
|
||||
// Starting time...
|
||||
Instant start = Instant.now();
|
||||
|
||||
// Initialize everything
|
||||
final int nbNodes = graph.getNodes().size();
|
||||
stack = new Stack<Node>();
|
||||
inStack = new boolean[nbNodes];
|
||||
|
||||
// Current index.
|
||||
index = 0;
|
||||
|
||||
// Information of nodes
|
||||
indexes = new int[nbNodes];
|
||||
Arrays.fill(indexes, UNDEFINED);
|
||||
lowlink = new int[nbNodes];
|
||||
|
||||
// Find components
|
||||
for (Node node: graph.getNodes()) {
|
||||
if (!hasBeenVisited(node)) {
|
||||
findAndAddStrongComponent(node);
|
||||
}
|
||||
}
|
||||
|
||||
// Duration...
|
||||
Duration solvingTime = Duration.between(start, Instant.now());
|
||||
|
||||
return new StronglyConnectedComponentsSolution((StronglyConnectedComponentsInstance)getInstance(),
|
||||
solvingTime, Status.OPTIMAL, components);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user