Add getNodes() and getSuccessors() methods and remove iterable from Graph and Node.

This commit is contained in:
Mikaël Capelle 2019-03-18 20:05:49 +01:00
parent 71a0085d59
commit d8470055f1
8 changed files with 91 additions and 83 deletions

View File

@ -12,88 +12,89 @@ import org.insa.graph.Path;
public class BellmanFordAlgorithm extends ShortestPathAlgorithm { public class BellmanFordAlgorithm extends ShortestPathAlgorithm {
public BellmanFordAlgorithm(ShortestPathData data) { public BellmanFordAlgorithm(ShortestPathData data) {
super(data); super(data);
} }
@Override @Override
protected ShortestPathSolution doRun() { protected ShortestPathSolution doRun() {
// Retrieve the graph. // Retrieve the graph.
ShortestPathData data = getInputData(); ShortestPathData data = getInputData();
Graph graph = data.getGraph(); Graph graph = data.getGraph();
final int nbNodes = graph.size(); final int nbNodes = graph.size();
// Initialize array of distances. // Initialize array of distances.
double[] distances = new double[nbNodes]; double[] distances = new double[nbNodes];
Arrays.fill(distances, Double.POSITIVE_INFINITY); Arrays.fill(distances, Double.POSITIVE_INFINITY);
distances[data.getOrigin().getId()] = 0; distances[data.getOrigin().getId()] = 0;
// Notify observers about the first event (origin processed). // Notify observers about the first event (origin processed).
notifyOriginProcessed(data.getOrigin()); notifyOriginProcessed(data.getOrigin());
// Initialize array of predecessors. // Initialize array of predecessors.
Arc[] predecessorArcs = new Arc[nbNodes]; Arc[] predecessorArcs = new Arc[nbNodes];
// Actual algorithm, we will assume the graph does not contain negative // Actual algorithm, we will assume the graph does not contain negative
// cycle... // cycle...
boolean found = false; boolean found = false;
for (int i = 0; !found && i < nbNodes; ++i) { for (int i = 0; !found && i < nbNodes; ++i) {
found = true; found = true;
for (Node node : graph) { for (Node node: graph.getNodes()) {
for (Arc arc : node) { for (Arc arc: node.getSuccessors()) {
// Small test to check allowed roads... // Small test to check allowed roads...
if (!data.isAllowed(arc)) { if (!data.isAllowed(arc)) {
continue; continue;
} }
// Retrieve weight of the arc. // Retrieve weight of the arc.
double w = data.getCost(arc); double w = data.getCost(arc);
double oldDistance = distances[arc.getDestination().getId()]; double oldDistance = distances[arc.getDestination().getId()];
double newDistance = distances[node.getId()] + w; double newDistance = distances[node.getId()] + w;
if (Double.isInfinite(oldDistance) && Double.isFinite(newDistance)) { if (Double.isInfinite(oldDistance) && Double.isFinite(newDistance)) {
notifyNodeReached(arc.getDestination()); notifyNodeReached(arc.getDestination());
} }
// Check if new distances would be better, if so update... // Check if new distances would be better, if so update...
if (newDistance < oldDistance) { if (newDistance < oldDistance) {
found = false; found = false;
distances[arc.getDestination().getId()] = distances[node.getId()] + w; distances[arc.getDestination().getId()] = distances[node.getId()] + w;
predecessorArcs[arc.getDestination().getId()] = arc; predecessorArcs[arc.getDestination().getId()] = arc;
} }
} }
} }
} }
ShortestPathSolution solution = null; ShortestPathSolution solution = null;
// Destination has no predecessor, the solution is infeasible... // Destination has no predecessor, the solution is infeasible...
if (predecessorArcs[data.getDestination().getId()] == null) { if (predecessorArcs[data.getDestination().getId()] == null) {
solution = new ShortestPathSolution(data, Status.INFEASIBLE); solution = new ShortestPathSolution(data, Status.INFEASIBLE);
} else { }
else {
// The destination has been found, notify the observers. // The destination has been found, notify the observers.
notifyDestinationReached(data.getDestination()); notifyDestinationReached(data.getDestination());
// Create the path from the array of predecessors... // Create the path from the array of predecessors...
ArrayList<Arc> arcs = new ArrayList<>(); ArrayList<Arc> arcs = new ArrayList<>();
Arc arc = predecessorArcs[data.getDestination().getId()]; Arc arc = predecessorArcs[data.getDestination().getId()];
while (arc != null) { while (arc != null) {
arcs.add(arc); arcs.add(arc);
arc = predecessorArcs[arc.getOrigin().getId()]; arc = predecessorArcs[arc.getOrigin().getId()];
} }
// Reverse the path... // Reverse the path...
Collections.reverse(arcs); Collections.reverse(arcs);
// Create the final solution. // Create the final solution.
solution = new ShortestPathSolution(data, Status.OPTIMAL, new Path(graph, arcs)); solution = new ShortestPathSolution(data, Status.OPTIMAL, new Path(graph, arcs));
} }
return solution; return solution;
} }
} }

View File

@ -77,8 +77,8 @@ public class WeaklyConnectedComponentsAlgorithm
res.add(new HashSet<Integer>()); res.add(new HashSet<Integer>());
} }
for (Node node: getInputData().getGraph()) { for (Node node: getInputData().getGraph().getNodes()) {
for (Arc arc: node) { for (Arc arc: node.getSuccessors()) {
res.get(node.getId()).add(arc.getDestination().getId()); res.get(node.getId()).add(arc.getDestination().getId());
if (arc.getRoadInformation().isOneWay()) { if (arc.getRoadInformation().isOneWay()) {
res.get(arc.getDestination().getId()).add(node.getId()); res.get(arc.getDestination().getId()).add(node.getId());

View File

@ -2,7 +2,6 @@ package org.insa.graph;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator;
import java.util.List; 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. * holds a list of nodes and each node holds a list of its successors.
* *
*/ */
public final class Graph implements Iterable<Node> { public final class Graph {
// Map identifier. // Map identifier.
private final String mapId; private final String mapId;
@ -68,9 +67,13 @@ public final class Graph implements Iterable<Node> {
return this.nodes.size(); return this.nodes.size();
} }
@Override /**
public Iterator<Node> iterator() { * @return List of nodes in this graph (unmodifiable).
return this.nodes.iterator(); *
* @see Collections#unmodifiableList(List)
*/
public List<Node> getNodes() {
return this.nodes;
} }
/** /**
@ -97,7 +100,7 @@ public final class Graph implements Iterable<Node> {
} }
for (Node node: nodes) { for (Node node: nodes) {
Node orig = trNodes.get(node.getId()); Node orig = trNodes.get(node.getId());
for (Arc arc: node) { for (Arc arc: node.getSuccessors()) {
if (arc.getRoadInformation().isOneWay()) { if (arc.getRoadInformation().isOneWay()) {
Node dest = trNodes.get(arc.getDestination().getId()); Node dest = trNodes.get(arc.getDestination().getId());
dest.addSuccessor(new ArcBackward(new ArcForward(orig, dest, arc.getLength(), dest.addSuccessor(new ArcBackward(new ArcForward(orig, dest, arc.getLength(),

View File

@ -2,7 +2,7 @@ package org.insa.graph;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.List;
/** /**
* Class representing a Node in a {@link Graph}. * Class representing a Node in a {@link Graph}.
@ -13,7 +13,7 @@ import java.util.Iterator;
* Nodes are comparable based on their ID. * Nodes are comparable based on their ID.
* *
*/ */
public final class Node implements Comparable<Node>, Iterable<Arc> { public final class Node implements Comparable<Node> {
/** /**
* Link the two given nodes with one or two arcs (depending on roadInformation), * Link the two given nodes with one or two arcs (depending on roadInformation),
@ -107,9 +107,13 @@ public final class Node implements Comparable<Node>, Iterable<Arc> {
return !this.successors.isEmpty(); return !this.successors.isEmpty();
} }
@Override /**
public Iterator<Arc> iterator() { * @return List of successors of this node (unmodifiable list).
return Collections.unmodifiableList(this.successors).iterator(); *
* @see Collections#unmodifiableList(List)
*/
public List<Arc> getSuccessors() {
return Collections.unmodifiableList(this.successors);
} }
/** /**

View File

@ -65,7 +65,7 @@ public class NodesInputPanel extends JPanel
public Node findClosestNode(Point point) { public Node findClosestNode(Point point) {
Node minNode = null; Node minNode = null;
double minDis = Double.POSITIVE_INFINITY; double minDis = Double.POSITIVE_INFINITY;
for (Node node: graph) { for (Node node: graph.getNodes()) {
double dlon = point.getLongitude() - node.getPoint().getLongitude(); double dlon = point.getLongitude() - node.getPoint().getLongitude();
double dlat = point.getLatitude() - node.getPoint().getLatitude(); double dlat = point.getLatitude() - node.getPoint().getLatitude();
double dis = dlon * dlon + dlat * dlat; // No need to square double dis = dlon * dlon + dlat * dlat; // No need to square

View File

@ -679,8 +679,8 @@ public class BasicDrawing extends JPanel implements Drawing {
this.removeMouseMotionListener(zoomAndPanListener); this.removeMouseMotionListener(zoomAndPanListener);
this.removeMouseWheelListener(zoomAndPanListener); this.removeMouseWheelListener(zoomAndPanListener);
for (Node node: graph) { for (Node node: graph.getNodes()) {
for (Arc arc: node) { for (Arc arc: node.getSuccessors()) {
// Draw arcs only if there are one-way arcs or if origin is lower than // Draw arcs only if there are one-way arcs or if origin is lower than
// destination, avoid drawing two-ways arc twice. // destination, avoid drawing two-ways arc twice.
if (arc.getRoadInformation().isOneWay() if (arc.getRoadInformation().isOneWay()

View File

@ -62,7 +62,7 @@ public class GraphTest {
*/ */
private List<Arc> getArcsBetween(Node a, Node b) { private List<Arc> getArcsBetween(Node a, Node b) {
List<Arc> arcs = new ArrayList<>(); List<Arc> arcs = new ArrayList<>();
for (Arc arc: a) { for (Arc arc: a.getSuccessors()) {
if (arc.getDestination().equals(b)) { if (arc.getDestination().equals(b)) {
arcs.add(arc); arcs.add(arc);
} }

View File

@ -54,7 +54,7 @@ public class NodeTest {
* @return The first arc between from a to b, or null. * @return The first arc between from a to b, or null.
*/ */
private Arc getFirstArcBetween(Node a, Node b) { private Arc getFirstArcBetween(Node a, Node b) {
for (Arc arc: a) { for (Arc arc: a.getSuccessors()) {
if (arc.getDestination().equals(b)) { if (arc.getDestination().equals(b)) {
return arc; return arc;
} }