Update.
This commit is contained in:
@@ -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