No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

WeaklyConnectedComponentsAlgorithm.java 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package org.insa.graphs.algorithm.weakconnectivity;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.HashSet;
  5. import java.util.LinkedList;
  6. import java.util.Queue;
  7. import org.insa.graphs.algorithm.AbstractAlgorithm;
  8. import org.insa.graphs.algorithm.AbstractSolution.Status;
  9. import org.insa.graphs.model.Arc;
  10. import org.insa.graphs.model.Graph;
  11. import org.insa.graphs.model.Node;
  12. public class WeaklyConnectedComponentsAlgorithm
  13. extends AbstractAlgorithm<WeaklyConnectedComponentObserver> {
  14. /**
  15. * @param data Input data for this algorithm.
  16. */
  17. public WeaklyConnectedComponentsAlgorithm(WeaklyConnectedComponentsData data) {
  18. super(data);
  19. }
  20. @Override
  21. public WeaklyConnectedComponentsSolution run() {
  22. return (WeaklyConnectedComponentsSolution) super.run();
  23. }
  24. @Override
  25. public WeaklyConnectedComponentsData getInputData() {
  26. return (WeaklyConnectedComponentsData) super.getInputData();
  27. }
  28. /**
  29. * Notify all observers that the algorithm is entering a new component.
  30. *
  31. * @param curNode Starting node for the component.
  32. */
  33. protected void notifyStartComponent(Node curNode) {
  34. for (WeaklyConnectedComponentObserver obs: getObservers()) {
  35. obs.notifyStartComponent(curNode);
  36. }
  37. }
  38. /**
  39. * Notify all observers that a new node has been found for the current
  40. * component.
  41. *
  42. * @param node New node found for the current component.
  43. */
  44. protected void notifyNewNodeInComponent(Node node) {
  45. for (WeaklyConnectedComponentObserver obs: getObservers()) {
  46. obs.notifyNewNodeInComponent(node);
  47. }
  48. }
  49. /**
  50. * Notify all observers that the algorithm has computed a new component.
  51. *
  52. * @param nodes List of nodes in the component.
  53. */
  54. protected void notifyEndComponent(ArrayList<Node> nodes) {
  55. for (WeaklyConnectedComponentObserver obs: getObservers()) {
  56. obs.notifyEndComponent(nodes);
  57. }
  58. }
  59. /**
  60. * @return An adjacency list for the undirected graph equivalent to the stored
  61. * graph.
  62. */
  63. protected ArrayList<HashSet<Integer>> createUndirectedGraph() {
  64. int nNodes = getInputData().getGraph().size();
  65. ArrayList<HashSet<Integer>> res = new ArrayList<HashSet<Integer>>(nNodes);
  66. for (int i = 0; i < nNodes; ++i) {
  67. res.add(new HashSet<Integer>());
  68. }
  69. for (Node node: getInputData().getGraph().getNodes()) {
  70. for (Arc arc: node.getSuccessors()) {
  71. res.get(node.getId()).add(arc.getDestination().getId());
  72. if (arc.getRoadInformation().isOneWay()) {
  73. res.get(arc.getDestination().getId()).add(node.getId());
  74. }
  75. }
  76. }
  77. return res;
  78. }
  79. /**
  80. * Apply a breadth first search algorithm on the given undirected graph
  81. * (adjacency list), starting at node cur, and marking nodes in marked.
  82. *
  83. * @param marked
  84. * @param cur
  85. *
  86. * @return
  87. */
  88. protected ArrayList<Node> bfs(ArrayList<HashSet<Integer>> ugraph, boolean[] marked, int cur) {
  89. Graph graph = getInputData().getGraph();
  90. ArrayList<Node> component = new ArrayList<Node>();
  91. // Using a queue because we are doing a BFS
  92. Queue<Integer> queue = new LinkedList<Integer>();
  93. // Notify observers about the current component.
  94. notifyStartComponent(graph.get(cur));
  95. // Add original node and loop until the queue is empty.
  96. queue.add(cur);
  97. marked[cur] = true;
  98. while (!queue.isEmpty()) {
  99. Node node = graph.get(queue.remove());
  100. component.add(node);
  101. // Notify observers
  102. notifyNewNodeInComponent(node);
  103. for (Integer destId: ugraph.get(node.getId())) {
  104. Node dest = graph.get(destId);
  105. if (!marked[dest.getId()]) {
  106. queue.add(destId);
  107. marked[destId] = true;
  108. }
  109. }
  110. }
  111. notifyEndComponent(component);
  112. return component;
  113. }
  114. @Override
  115. protected WeaklyConnectedComponentsSolution doRun() {
  116. Graph graph = getInputData().getGraph();
  117. ArrayList<HashSet<Integer>> ugraph = createUndirectedGraph();
  118. boolean[] marked = new boolean[graph.size()];
  119. Arrays.fill(marked, false);
  120. ArrayList<ArrayList<Node>> components = new ArrayList<ArrayList<Node>>();
  121. // perform algorithm
  122. int cur = 0;
  123. while (cur < marked.length) {
  124. // Apply BFS
  125. components.add(this.bfs(ugraph, marked, cur));
  126. // Find next non-marked
  127. for (; cur < marked.length && marked[cur]; ++cur)
  128. ;
  129. }
  130. return new WeaklyConnectedComponentsSolution(getInputData(), Status.OPTIMAL, components);
  131. }
  132. }