Update.
This commit is contained in:
@@ -1,22 +1,40 @@
|
||||
package org.insa.algo ;
|
||||
|
||||
import java.io.* ;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public abstract class AbstractAlgorithm {
|
||||
public abstract class AbstractAlgorithm implements Runnable {
|
||||
|
||||
protected PrintStream output;
|
||||
protected AbstractInstance instance;
|
||||
protected AbstractSolution solution;
|
||||
|
||||
protected ArrayList<AbstractObserver> observers;
|
||||
|
||||
protected AbstractAlgorithm(AbstractInstance instance) {
|
||||
this.instance = instance;
|
||||
this.observers = new ArrayList<AbstractObserver>();
|
||||
this.solution = null;
|
||||
}
|
||||
|
||||
protected AbstractAlgorithm(AbstractInstance instance, ArrayList<AbstractObserver> observers) {
|
||||
this.instance = instance;
|
||||
this.observers = observers;;
|
||||
this.solution = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an observer to this algorithm.
|
||||
*
|
||||
* @param instance
|
||||
* @param logOutput
|
||||
* @param observer
|
||||
*/
|
||||
protected AbstractAlgorithm(AbstractInstance instance, PrintStream logOutput) {
|
||||
this.instance = instance;
|
||||
this.output = logOutput;
|
||||
this.solution = null;
|
||||
public void addObserver(AbstractObserver observer) {
|
||||
observers.add(observer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The list of observers for this algorithm.
|
||||
*/
|
||||
public ArrayList<AbstractObserver> getObservers() {
|
||||
return observers;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,9 +62,8 @@ public abstract class AbstractAlgorithm {
|
||||
*
|
||||
* @return true if a feasible solution was found (even non-optimal).
|
||||
*/
|
||||
public boolean run() {
|
||||
public void run() {
|
||||
this.solution = this.doRun();
|
||||
return this.solution != null && this.solution.isFeasible();
|
||||
}
|
||||
|
||||
/**
|
||||
|
20
src/main/org/insa/algo/AbstractObserver.java
Normal file
20
src/main/org/insa/algo/AbstractObserver.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package org.insa.algo;
|
||||
|
||||
public abstract class AbstractObserver {
|
||||
|
||||
// Specify if the observer is graphic or not.
|
||||
private final boolean isgraphic;
|
||||
|
||||
protected AbstractObserver(boolean isGraphic) {
|
||||
this.isgraphic = isGraphic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if this observer is graphic (use drawing to display
|
||||
* information).
|
||||
*/
|
||||
public boolean isGraphic() {
|
||||
return isgraphic;
|
||||
}
|
||||
|
||||
}
|
@@ -1,30 +0,0 @@
|
||||
package org.insa.algo.connectivity ;
|
||||
|
||||
import java.io.* ;
|
||||
|
||||
import org.insa.algo.AbstractAlgorithm;
|
||||
import org.insa.algo.AbstractSolution;
|
||||
|
||||
public class ConnectivityAlgorithm extends AbstractAlgorithm {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param instance
|
||||
* @param logOutput
|
||||
*/
|
||||
public ConnectivityAlgorithm(ConnectivityInstance instance, PrintStream logOutput) {
|
||||
super(instance, logOutput);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected AbstractSolution doRun() {
|
||||
ConnectivityInstance instance = (ConnectivityInstance)getInstance();
|
||||
ConnectivitySolution solution = null;
|
||||
// TODO:
|
||||
return solution;
|
||||
}
|
||||
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
package org.insa.algo.connectivity;
|
||||
|
||||
import org.insa.algo.AbstractInstance;
|
||||
import org.insa.graph.Graph;
|
||||
|
||||
public class ConnectivityInstance extends AbstractInstance {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param graph
|
||||
*/
|
||||
public ConnectivityInstance(Graph graph) {
|
||||
super(graph);
|
||||
}
|
||||
|
||||
}
|
@@ -1,20 +0,0 @@
|
||||
package org.insa.algo.connectivity;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.insa.algo.AbstractSolution;
|
||||
|
||||
public class ConnectivitySolution extends AbstractSolution {
|
||||
|
||||
protected ConnectivitySolution(ConnectivityInstance instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
protected ConnectivitySolution(ConnectivityInstance instance,
|
||||
Duration solvingTime, Status status) {
|
||||
super(instance, solvingTime, status);
|
||||
|
||||
// TODO:
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
package org.insa.algo.weakconnectivity;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.insa.drawing.Drawing;
|
||||
import org.insa.drawing.graph.GraphDrawing;
|
||||
import org.insa.graph.Node;
|
||||
|
||||
public class WeaklyConnectedComponentGraphicObserver extends WeaklyConnectedComponentObserver {
|
||||
|
||||
private static final Color[] COLORS = {
|
||||
Color.BLUE, Color.ORANGE, Color.GREEN, Color.YELLOW, Color.RED
|
||||
};
|
||||
|
||||
// Drawing + Graph drawing
|
||||
private Drawing drawing;
|
||||
private GraphDrawing gdrawing;
|
||||
|
||||
// Current index color
|
||||
private int cindex = 0;
|
||||
|
||||
public WeaklyConnectedComponentGraphicObserver(Drawing drawing) {
|
||||
super(true);
|
||||
this.drawing = drawing;
|
||||
this.gdrawing = new GraphDrawing(drawing);
|
||||
this.drawing.setAutoRepaint(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyStartComponent(Node curNode) {
|
||||
this.drawing.setColor(COLORS[cindex]);
|
||||
cindex = (cindex + 1) % COLORS.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNewNodeInComponent(Node node) {
|
||||
this.gdrawing.drawPoint(node.getPoint(), 5);
|
||||
this.drawing.repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyEndComponent(ArrayList<Node> nodes) {
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
package org.insa.algo.weakconnectivity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.insa.algo.AbstractObserver;
|
||||
import org.insa.graph.Node;
|
||||
|
||||
public abstract class WeaklyConnectedComponentObserver extends AbstractObserver {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected WeaklyConnectedComponentObserver(boolean isGraphic) {
|
||||
super(isGraphic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify that the algorithm is entering a new component.
|
||||
*
|
||||
* @param curNode Starting node for the component.
|
||||
*/
|
||||
public abstract void notifyStartComponent(Node curNode);
|
||||
|
||||
/**
|
||||
* Notify that a new node has been found for the current component.
|
||||
*
|
||||
* @param node New node found for the current component.
|
||||
*/
|
||||
public abstract void notifyNewNodeInComponent(Node node);
|
||||
|
||||
/**
|
||||
* Notify that the algorithm has computed a new component.
|
||||
*
|
||||
* @param nodes List of nodes in the component.
|
||||
*/
|
||||
public abstract void notifyEndComponent(ArrayList<Node> nodes);
|
||||
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package org.insa.algo.weakconnectivity;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.insa.graph.Node;
|
||||
|
||||
public class WeaklyConnectedComponentTextObserver extends WeaklyConnectedComponentObserver {
|
||||
|
||||
// Number of the current component.
|
||||
private int numComponent = 1;
|
||||
|
||||
// Output stream
|
||||
PrintStream stream;
|
||||
|
||||
public WeaklyConnectedComponentTextObserver(PrintStream stream) {
|
||||
super(false);
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyStartComponent(Node curNode) {
|
||||
stream.print("Entering component #" + numComponent + " from node #" + curNode.getId() + "... ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNewNodeInComponent(Node node) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyEndComponent(ArrayList<Node> nodes) {
|
||||
stream.println(nodes.size() + " nodes found.");
|
||||
stream.flush();
|
||||
numComponent += 1;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,127 @@
|
||||
package org.insa.algo.weakconnectivity;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.insa.algo.AbstractAlgorithm;
|
||||
import org.insa.algo.AbstractObserver;
|
||||
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 WeaklyConnectedComponentsAlgorithm extends AbstractAlgorithm {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param instance
|
||||
* @param logOutput
|
||||
*/
|
||||
public WeaklyConnectedComponentsAlgorithm(WeaklyConnectedComponentsInstance instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An adjacency list for the undirected graph equivalent to the stored graph.
|
||||
*/
|
||||
protected ArrayList<HashSet<Integer>> createUndirectedGraph() {
|
||||
int nNodes = getInstance().getGraph().getNodes().size();
|
||||
ArrayList<HashSet<Integer>> res = new ArrayList<HashSet<Integer>>(nNodes);
|
||||
for (int i = 0; i < nNodes; ++i) {
|
||||
res.add(new HashSet<Integer>());
|
||||
}
|
||||
|
||||
for (Node node: getInstance().getGraph().getNodes()) {
|
||||
for (Arc arc: node.getSuccessors()) {
|
||||
res.get(node.getId()).add(arc.getDestination().getId());
|
||||
if (arc.getInfo().isOneWay()) {
|
||||
res.get(arc.getDestination().getId()).add(node.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply a breadth first search algorithm on the given undirected graph (adjacency list),
|
||||
* starting at node cur, and marking nodes in marked.
|
||||
*
|
||||
* @param marked
|
||||
* @param cur
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected ArrayList<Node> bfs(ArrayList<HashSet<Integer>> ugraph, boolean[] marked, int cur) {
|
||||
ArrayList<Node> nodes = getInstance().getGraph().getNodes();
|
||||
ArrayList<Node> component = new ArrayList<Node>();
|
||||
|
||||
// Using a queue because we are doing a BFS
|
||||
Queue<Integer> queue = new LinkedList<Integer>();
|
||||
|
||||
for (AbstractObserver obs: getObservers()) {
|
||||
((WeaklyConnectedComponentObserver)obs).notifyStartComponent(nodes.get(cur));
|
||||
}
|
||||
|
||||
// Add original node and loop until the queue is empty.
|
||||
queue.add(cur);
|
||||
marked[cur] = true;
|
||||
while (!queue.isEmpty()) {
|
||||
Node node = nodes.get(queue.remove());
|
||||
component.add(node);
|
||||
|
||||
// notify observers
|
||||
for (AbstractObserver obs: getObservers()) ((WeaklyConnectedComponentObserver)obs).notifyNewNodeInComponent(node);
|
||||
|
||||
for (Integer destId: ugraph.get(node.getId())) {
|
||||
Node dest = nodes.get(destId);
|
||||
if (!marked[dest.getId()]) {
|
||||
queue.add(destId);
|
||||
marked[destId] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (AbstractObserver obs: getObservers()) {
|
||||
((WeaklyConnectedComponentObserver)obs).notifyEndComponent(component);
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractSolution doRun() {
|
||||
|
||||
Instant start = Instant.now();
|
||||
|
||||
Graph graph = getInstance().getGraph();
|
||||
ArrayList<HashSet<Integer>> ugraph = createUndirectedGraph();
|
||||
boolean[] marked = new boolean[graph.getNodes().size()];
|
||||
Arrays.fill(marked, false);
|
||||
|
||||
ArrayList<ArrayList<Node>> components = new ArrayList<ArrayList<Node>>();
|
||||
|
||||
// perform algorithm
|
||||
int cur = 0;
|
||||
while (cur < marked.length) {
|
||||
// Apply BFS
|
||||
components.add(this.bfs(ugraph, marked, cur));
|
||||
|
||||
// Find next non-marked
|
||||
for (; cur < marked.length && marked[cur]; ++cur);
|
||||
}
|
||||
|
||||
Duration solvingTime = Duration.between(start, Instant.now());
|
||||
|
||||
return new WeaklyConnectedComponentsSolution((WeaklyConnectedComponentsInstance)getInstance(),
|
||||
solvingTime, Status.OPTIMAL, components);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
package org.insa.algo.weakconnectivity;
|
||||
|
||||
import org.insa.algo.AbstractInstance;
|
||||
import org.insa.graph.Graph;
|
||||
|
||||
public class WeaklyConnectedComponentsInstance extends AbstractInstance {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param graph
|
||||
*/
|
||||
public WeaklyConnectedComponentsInstance(Graph graph) {
|
||||
super(graph);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package org.insa.algo.weakconnectivity;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.insa.algo.AbstractSolution;
|
||||
import org.insa.graph.Node;
|
||||
|
||||
public class WeaklyConnectedComponentsSolution extends AbstractSolution {
|
||||
|
||||
// Components
|
||||
private ArrayList<ArrayList<Node>> components;
|
||||
|
||||
protected WeaklyConnectedComponentsSolution(WeaklyConnectedComponentsInstance instance) {
|
||||
super(instance);
|
||||
}
|
||||
|
||||
protected WeaklyConnectedComponentsSolution(WeaklyConnectedComponentsInstance 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; }
|
||||
|
||||
}
|
Reference in New Issue
Block a user