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 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<Arc> 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<Arc> 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;
}
}

View File

@ -77,8 +77,8 @@ public class WeaklyConnectedComponentsAlgorithm
res.add(new HashSet<Integer>());
}
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());

View File

@ -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<Node> {
public final class Graph {
// Map identifier.
private final String mapId;
@ -68,9 +67,13 @@ public final class Graph implements Iterable<Node> {
return this.nodes.size();
}
@Override
public Iterator<Node> iterator() {
return this.nodes.iterator();
/**
* @return List of nodes in this graph (unmodifiable).
*
* @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) {
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(),

View File

@ -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<Node>, Iterable<Arc> {
public final class Node implements Comparable<Node> {
/**
* 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();
}
@Override
public Iterator<Arc> iterator() {
return Collections.unmodifiableList(this.successors).iterator();
/**
* @return List of successors of this node (unmodifiable list).
*
* @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) {
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

View File

@ -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()

View File

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

View File

@ -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;
}