From d8470055f148dc7ccbb0240276d0168053a6cc3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Mon, 18 Mar 2019 20:05:49 +0100 Subject: [PATCH] Add getNodes() and getSuccessors() methods and remove iterable from Graph and Node. --- .../shortestpath/BellmanFordAlgorithm.java | 131 +++++++++--------- .../WeaklyConnectedComponentsAlgorithm.java | 4 +- src/main/org/insa/graph/Graph.java | 15 +- src/main/org/insa/graph/Node.java | 14 +- .../org/insa/graphics/NodesInputPanel.java | 2 +- .../drawing/components/BasicDrawing.java | 4 +- src/test/org/insa/graph/GraphTest.java | 2 +- src/test/org/insa/graph/NodeTest.java | 2 +- 8 files changed, 91 insertions(+), 83 deletions(-) diff --git a/src/main/org/insa/algo/shortestpath/BellmanFordAlgorithm.java b/src/main/org/insa/algo/shortestpath/BellmanFordAlgorithm.java index 3c34c67..666d5c8 100644 --- a/src/main/org/insa/algo/shortestpath/BellmanFordAlgorithm.java +++ b/src/main/org/insa/algo/shortestpath/BellmanFordAlgorithm.java @@ -12,88 +12,89 @@ import org.insa.graph.Path; public class BellmanFordAlgorithm extends ShortestPathAlgorithm { - public BellmanFordAlgorithm(ShortestPathData data) { - super(data); - } + public BellmanFordAlgorithm(ShortestPathData data) { + super(data); + } - @Override - protected ShortestPathSolution doRun() { + @Override + protected ShortestPathSolution doRun() { - // Retrieve the graph. - ShortestPathData data = getInputData(); - Graph graph = data.getGraph(); + // Retrieve the graph. + ShortestPathData data = getInputData(); + Graph graph = data.getGraph(); - final int nbNodes = graph.size(); + final int nbNodes = graph.size(); - // Initialize array of distances. - double[] distances = new double[nbNodes]; - Arrays.fill(distances, Double.POSITIVE_INFINITY); - distances[data.getOrigin().getId()] = 0; + // Initialize array of distances. + double[] distances = new double[nbNodes]; + Arrays.fill(distances, Double.POSITIVE_INFINITY); + distances[data.getOrigin().getId()] = 0; - // Notify observers about the first event (origin processed). - notifyOriginProcessed(data.getOrigin()); + // Notify observers about the first event (origin processed). + notifyOriginProcessed(data.getOrigin()); - // Initialize array of predecessors. - Arc[] predecessorArcs = new Arc[nbNodes]; + // Initialize array of predecessors. + Arc[] predecessorArcs = new Arc[nbNodes]; - // Actual algorithm, we will assume the graph does not contain negative - // cycle... - boolean found = false; - for (int i = 0; !found && i < nbNodes; ++i) { - found = true; - for (Node node : graph) { - for (Arc arc : node) { + // Actual algorithm, we will assume the graph does not contain negative + // cycle... + boolean found = false; + for (int i = 0; !found && i < nbNodes; ++i) { + found = true; + for (Node node: graph.getNodes()) { + for (Arc arc: node.getSuccessors()) { - // Small test to check allowed roads... - if (!data.isAllowed(arc)) { - continue; - } + // Small test to check allowed roads... + if (!data.isAllowed(arc)) { + continue; + } - // Retrieve weight of the arc. - double w = data.getCost(arc); - double oldDistance = distances[arc.getDestination().getId()]; - double newDistance = distances[node.getId()] + w; + // Retrieve weight of the arc. + double w = data.getCost(arc); + double oldDistance = distances[arc.getDestination().getId()]; + double newDistance = distances[node.getId()] + w; - if (Double.isInfinite(oldDistance) && Double.isFinite(newDistance)) { - notifyNodeReached(arc.getDestination()); - } + if (Double.isInfinite(oldDistance) && Double.isFinite(newDistance)) { + notifyNodeReached(arc.getDestination()); + } - // Check if new distances would be better, if so update... - if (newDistance < oldDistance) { - found = false; - distances[arc.getDestination().getId()] = distances[node.getId()] + w; - predecessorArcs[arc.getDestination().getId()] = arc; - } - } - } - } + // Check if new distances would be better, if so update... + if (newDistance < oldDistance) { + found = false; + distances[arc.getDestination().getId()] = distances[node.getId()] + w; + predecessorArcs[arc.getDestination().getId()] = arc; + } + } + } + } - ShortestPathSolution solution = null; + ShortestPathSolution solution = null; - // Destination has no predecessor, the solution is infeasible... - if (predecessorArcs[data.getDestination().getId()] == null) { - solution = new ShortestPathSolution(data, Status.INFEASIBLE); - } else { + // Destination has no predecessor, the solution is infeasible... + if (predecessorArcs[data.getDestination().getId()] == null) { + solution = new ShortestPathSolution(data, Status.INFEASIBLE); + } + else { - // The destination has been found, notify the observers. - notifyDestinationReached(data.getDestination()); + // The destination has been found, notify the observers. + notifyDestinationReached(data.getDestination()); - // Create the path from the array of predecessors... - ArrayList arcs = new ArrayList<>(); - Arc arc = predecessorArcs[data.getDestination().getId()]; - while (arc != null) { - arcs.add(arc); - arc = predecessorArcs[arc.getOrigin().getId()]; - } + // Create the path from the array of predecessors... + ArrayList arcs = new ArrayList<>(); + Arc arc = predecessorArcs[data.getDestination().getId()]; + while (arc != null) { + arcs.add(arc); + arc = predecessorArcs[arc.getOrigin().getId()]; + } - // Reverse the path... - Collections.reverse(arcs); + // Reverse the path... + Collections.reverse(arcs); - // Create the final solution. - solution = new ShortestPathSolution(data, Status.OPTIMAL, new Path(graph, arcs)); - } + // Create the final solution. + solution = new ShortestPathSolution(data, Status.OPTIMAL, new Path(graph, arcs)); + } - return solution; - } + return solution; + } } diff --git a/src/main/org/insa/algo/weakconnectivity/WeaklyConnectedComponentsAlgorithm.java b/src/main/org/insa/algo/weakconnectivity/WeaklyConnectedComponentsAlgorithm.java index 04f5138..83f8946 100644 --- a/src/main/org/insa/algo/weakconnectivity/WeaklyConnectedComponentsAlgorithm.java +++ b/src/main/org/insa/algo/weakconnectivity/WeaklyConnectedComponentsAlgorithm.java @@ -77,8 +77,8 @@ public class WeaklyConnectedComponentsAlgorithm res.add(new HashSet()); } - for (Node node: getInputData().getGraph()) { - for (Arc arc: node) { + 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()); diff --git a/src/main/org/insa/graph/Graph.java b/src/main/org/insa/graph/Graph.java index a7d1323..867b715 100644 --- a/src/main/org/insa/graph/Graph.java +++ b/src/main/org/insa/graph/Graph.java @@ -2,7 +2,6 @@ package org.insa.graph; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; /** @@ -12,7 +11,7 @@ import java.util.List; * holds a list of nodes and each node holds a list of its successors. * */ -public final class Graph implements Iterable { +public final class Graph { // Map identifier. private final String mapId; @@ -68,9 +67,13 @@ public final class Graph implements Iterable { return this.nodes.size(); } - @Override - public Iterator iterator() { - return this.nodes.iterator(); + /** + * @return List of nodes in this graph (unmodifiable). + * + * @see Collections#unmodifiableList(List) + */ + public List getNodes() { + return this.nodes; } /** @@ -97,7 +100,7 @@ public final class Graph implements Iterable { } for (Node node: nodes) { Node orig = trNodes.get(node.getId()); - for (Arc arc: node) { + for (Arc arc: node.getSuccessors()) { if (arc.getRoadInformation().isOneWay()) { Node dest = trNodes.get(arc.getDestination().getId()); dest.addSuccessor(new ArcBackward(new ArcForward(orig, dest, arc.getLength(), diff --git a/src/main/org/insa/graph/Node.java b/src/main/org/insa/graph/Node.java index 694b5a5..964c8fb 100644 --- a/src/main/org/insa/graph/Node.java +++ b/src/main/org/insa/graph/Node.java @@ -2,7 +2,7 @@ package org.insa.graph; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; +import java.util.List; /** * Class representing a Node in a {@link Graph}. @@ -13,7 +13,7 @@ import java.util.Iterator; * Nodes are comparable based on their ID. * */ -public final class Node implements Comparable, Iterable { +public final class Node implements Comparable { /** * Link the two given nodes with one or two arcs (depending on roadInformation), @@ -107,9 +107,13 @@ public final class Node implements Comparable, Iterable { return !this.successors.isEmpty(); } - @Override - public Iterator iterator() { - return Collections.unmodifiableList(this.successors).iterator(); + /** + * @return List of successors of this node (unmodifiable list). + * + * @see Collections#unmodifiableList(List) + */ + public List getSuccessors() { + return Collections.unmodifiableList(this.successors); } /** diff --git a/src/main/org/insa/graphics/NodesInputPanel.java b/src/main/org/insa/graphics/NodesInputPanel.java index b9a020e..f5dc5e9 100644 --- a/src/main/org/insa/graphics/NodesInputPanel.java +++ b/src/main/org/insa/graphics/NodesInputPanel.java @@ -65,7 +65,7 @@ public class NodesInputPanel extends JPanel public Node findClosestNode(Point point) { Node minNode = null; double minDis = Double.POSITIVE_INFINITY; - for (Node node: graph) { + for (Node node: graph.getNodes()) { double dlon = point.getLongitude() - node.getPoint().getLongitude(); double dlat = point.getLatitude() - node.getPoint().getLatitude(); double dis = dlon * dlon + dlat * dlat; // No need to square diff --git a/src/main/org/insa/graphics/drawing/components/BasicDrawing.java b/src/main/org/insa/graphics/drawing/components/BasicDrawing.java index 7c532d6..200665f 100644 --- a/src/main/org/insa/graphics/drawing/components/BasicDrawing.java +++ b/src/main/org/insa/graphics/drawing/components/BasicDrawing.java @@ -679,8 +679,8 @@ public class BasicDrawing extends JPanel implements Drawing { this.removeMouseMotionListener(zoomAndPanListener); this.removeMouseWheelListener(zoomAndPanListener); - for (Node node: graph) { - for (Arc arc: node) { + for (Node node: graph.getNodes()) { + for (Arc arc: node.getSuccessors()) { // Draw arcs only if there are one-way arcs or if origin is lower than // destination, avoid drawing two-ways arc twice. if (arc.getRoadInformation().isOneWay() diff --git a/src/test/org/insa/graph/GraphTest.java b/src/test/org/insa/graph/GraphTest.java index 25e934c..d91d9da 100644 --- a/src/test/org/insa/graph/GraphTest.java +++ b/src/test/org/insa/graph/GraphTest.java @@ -62,7 +62,7 @@ public class GraphTest { */ private List getArcsBetween(Node a, Node b) { List arcs = new ArrayList<>(); - for (Arc arc: a) { + for (Arc arc: a.getSuccessors()) { if (arc.getDestination().equals(b)) { arcs.add(arc); } diff --git a/src/test/org/insa/graph/NodeTest.java b/src/test/org/insa/graph/NodeTest.java index c64a5dd..a467303 100644 --- a/src/test/org/insa/graph/NodeTest.java +++ b/src/test/org/insa/graph/NodeTest.java @@ -54,7 +54,7 @@ public class NodeTest { * @return The first arc between from a to b, or null. */ private Arc getFirstArcBetween(Node a, Node b) { - for (Arc arc: a) { + for (Arc arc: a.getSuccessors()) { if (arc.getDestination().equals(b)) { return arc; }