123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- package org.insa.graphs.algorithm.weakconnectivity;
-
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.HashSet;
- import java.util.LinkedList;
- import java.util.Queue;
-
- import org.insa.graphs.algorithm.AbstractAlgorithm;
- import org.insa.graphs.algorithm.AbstractSolution.Status;
- import org.insa.graphs.model.Arc;
- import org.insa.graphs.model.Graph;
- import org.insa.graphs.model.Node;
-
- public class WeaklyConnectedComponentsAlgorithm
- extends AbstractAlgorithm<WeaklyConnectedComponentObserver> {
-
- /**
- * @param data Input data for this algorithm.
- */
- public WeaklyConnectedComponentsAlgorithm(WeaklyConnectedComponentsData data) {
- super(data);
- }
-
- @Override
- public WeaklyConnectedComponentsSolution run() {
- return (WeaklyConnectedComponentsSolution) super.run();
- }
-
- @Override
- public WeaklyConnectedComponentsData getInputData() {
- return (WeaklyConnectedComponentsData) super.getInputData();
- }
-
- /**
- * Notify all observers that the algorithm is entering a new component.
- *
- * @param curNode Starting node for the component.
- */
- protected void notifyStartComponent(Node curNode) {
- for (WeaklyConnectedComponentObserver obs: getObservers()) {
- obs.notifyStartComponent(curNode);
- }
- }
-
- /**
- * Notify all observers that a new node has been found for the current
- * component.
- *
- * @param node New node found for the current component.
- */
- protected void notifyNewNodeInComponent(Node node) {
- for (WeaklyConnectedComponentObserver obs: getObservers()) {
- obs.notifyNewNodeInComponent(node);
- }
- }
-
- /**
- * Notify all observers that the algorithm has computed a new component.
- *
- * @param nodes List of nodes in the component.
- */
- protected void notifyEndComponent(ArrayList<Node> nodes) {
- for (WeaklyConnectedComponentObserver obs: getObservers()) {
- obs.notifyEndComponent(nodes);
- }
- }
-
- /**
- * @return An adjacency list for the undirected graph equivalent to the stored
- * graph.
- */
- protected ArrayList<HashSet<Integer>> createUndirectedGraph() {
- int nNodes = getInputData().getGraph().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: getInputData().getGraph().getNodes()) {
- for (Arc arc: node.getSuccessors()) {
- res.get(node.getId()).add(arc.getDestination().getId());
- if (arc.getRoadInformation().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) {
- Graph graph = getInputData().getGraph();
- ArrayList<Node> component = new ArrayList<Node>();
-
- // Using a queue because we are doing a BFS
- Queue<Integer> queue = new LinkedList<Integer>();
-
- // Notify observers about the current component.
- notifyStartComponent(graph.get(cur));
-
- // Add original node and loop until the queue is empty.
- queue.add(cur);
- marked[cur] = true;
- while (!queue.isEmpty()) {
- Node node = graph.get(queue.remove());
- component.add(node);
-
- // Notify observers
- notifyNewNodeInComponent(node);
-
- for (Integer destId: ugraph.get(node.getId())) {
- Node dest = graph.get(destId);
- if (!marked[dest.getId()]) {
- queue.add(destId);
- marked[destId] = true;
- }
- }
- }
-
- notifyEndComponent(component);
-
- return component;
- }
-
- @Override
- protected WeaklyConnectedComponentsSolution doRun() {
-
- Graph graph = getInputData().getGraph();
- ArrayList<HashSet<Integer>> ugraph = createUndirectedGraph();
- boolean[] marked = new boolean[graph.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)
- ;
- }
-
- return new WeaklyConnectedComponentsSolution(getInputData(), Status.OPTIMAL, components);
- }
-
- }
|