Switch to Maven project.
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
package org.insa.graphs.algorithm.shortestpath;
|
||||
|
||||
public class AStarAlgorithm extends DijkstraAlgorithm {
|
||||
|
||||
public AStarAlgorithm(ShortestPathData data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,100 @@
|
||||
package org.insa.graphs.algorithm.shortestpath;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
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;
|
||||
import org.insa.graphs.model.Path;
|
||||
|
||||
public class BellmanFordAlgorithm extends ShortestPathAlgorithm {
|
||||
|
||||
public BellmanFordAlgorithm(ShortestPathData data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ShortestPathSolution doRun() {
|
||||
|
||||
// Retrieve the graph.
|
||||
ShortestPathData data = getInputData();
|
||||
Graph graph = data.getGraph();
|
||||
|
||||
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;
|
||||
|
||||
// Notify observers about the first event (origin processed).
|
||||
notifyOriginProcessed(data.getOrigin());
|
||||
|
||||
// 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.getNodes()) {
|
||||
for (Arc arc: node.getSuccessors()) {
|
||||
|
||||
// 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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShortestPathSolution solution = null;
|
||||
|
||||
// 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());
|
||||
|
||||
// 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);
|
||||
|
||||
// Create the final solution.
|
||||
solution = new ShortestPathSolution(data, Status.OPTIMAL, new Path(graph, arcs));
|
||||
}
|
||||
|
||||
return solution;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package org.insa.graphs.algorithm.shortestpath;
|
||||
|
||||
public class DijkstraAlgorithm extends ShortestPathAlgorithm {
|
||||
|
||||
public DijkstraAlgorithm(ShortestPathData data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ShortestPathSolution doRun() {
|
||||
final ShortestPathData data = getInputData();
|
||||
ShortestPathSolution solution = null;
|
||||
// TODO:
|
||||
return solution;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,69 @@
|
||||
package org.insa.graphs.algorithm.shortestpath;
|
||||
|
||||
import org.insa.graphs.algorithm.AbstractAlgorithm;
|
||||
import org.insa.graphs.model.Node;
|
||||
|
||||
public abstract class ShortestPathAlgorithm extends AbstractAlgorithm<ShortestPathObserver> {
|
||||
|
||||
protected ShortestPathAlgorithm(ShortestPathData data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShortestPathSolution run() {
|
||||
return (ShortestPathSolution) super.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected abstract ShortestPathSolution doRun();
|
||||
|
||||
@Override
|
||||
public ShortestPathData getInputData() {
|
||||
return (ShortestPathData) super.getInputData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all observers that the origin has been processed.
|
||||
*
|
||||
* @param node Origin.
|
||||
*/
|
||||
public void notifyOriginProcessed(Node node) {
|
||||
for (ShortestPathObserver obs: getObservers()) {
|
||||
obs.notifyOriginProcessed(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all observers that a node has been reached for the first time.
|
||||
*
|
||||
* @param node Node that has been reached.
|
||||
*/
|
||||
public void notifyNodeReached(Node node) {
|
||||
for (ShortestPathObserver obs: getObservers()) {
|
||||
obs.notifyNodeReached(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all observers that a node has been marked, i.e. its final value has
|
||||
* been set.
|
||||
*
|
||||
* @param node Node that has been marked.
|
||||
*/
|
||||
public void notifyNodeMarked(Node node) {
|
||||
for (ShortestPathObserver obs: getObservers()) {
|
||||
obs.notifyNodeMarked(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all observers that the destination has been reached.
|
||||
*
|
||||
* @param node Destination.
|
||||
*/
|
||||
public void notifyDestinationReached(Node node) {
|
||||
for (ShortestPathObserver obs: getObservers()) {
|
||||
obs.notifyDestinationReached(node);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
package org.insa.graphs.algorithm.shortestpath;
|
||||
|
||||
import org.insa.graphs.algorithm.AbstractInputData;
|
||||
import org.insa.graphs.algorithm.ArcInspector;
|
||||
import org.insa.graphs.model.Graph;
|
||||
import org.insa.graphs.model.Node;
|
||||
|
||||
public class ShortestPathData extends AbstractInputData {
|
||||
|
||||
// Origin and destination nodes.
|
||||
private final Node origin, destination;
|
||||
|
||||
/**
|
||||
* Construct a new instance of ShortestPathInputData with the given parameters.
|
||||
*
|
||||
* @param graph Graph in which the path should be looked for.
|
||||
* @param origin Origin node of the path.
|
||||
* @param destination Destination node of the path.
|
||||
* @param arcInspector Filter for arcs (used to allow only a specific set of
|
||||
* arcs in the graph to be used).
|
||||
*/
|
||||
public ShortestPathData(Graph graph, Node origin, Node destination, ArcInspector arcInspector) {
|
||||
super(graph, arcInspector);
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Origin node for the path.
|
||||
*/
|
||||
public Node getOrigin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Destination node for the path.
|
||||
*/
|
||||
public Node getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Shortest-path from #" + origin.getId() + " to #" + destination.getId() + " ["
|
||||
+ this.arcInspector.toString().toLowerCase() + "]";
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package org.insa.graphs.algorithm.shortestpath;
|
||||
|
||||
import org.insa.graphs.model.Node;
|
||||
|
||||
public interface ShortestPathObserver {
|
||||
|
||||
/**
|
||||
* Notify the observer that the origin has been processed.
|
||||
*
|
||||
* @param node Origin.
|
||||
*/
|
||||
public void notifyOriginProcessed(Node node);
|
||||
|
||||
/**
|
||||
* Notify the observer that a node has been reached for the first
|
||||
* time.
|
||||
*
|
||||
* @param node Node that has been reached.
|
||||
*/
|
||||
public void notifyNodeReached(Node node);
|
||||
|
||||
/**
|
||||
* Notify the observer that a node has been marked, i.e. its final
|
||||
* value has been set.
|
||||
*
|
||||
* @param node Node that has been marked.
|
||||
*/
|
||||
public void notifyNodeMarked(Node node);
|
||||
|
||||
/**
|
||||
* Notify the observer that the destination has been reached.
|
||||
*
|
||||
* @param node Destination.
|
||||
*/
|
||||
public void notifyDestinationReached(Node node);
|
||||
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
package org.insa.graphs.algorithm.shortestpath;
|
||||
|
||||
import org.insa.graphs.algorithm.AbstractInputData.Mode;
|
||||
import org.insa.graphs.model.Arc;
|
||||
import org.insa.graphs.model.Path;
|
||||
import org.insa.graphs.algorithm.AbstractSolution;
|
||||
|
||||
public class ShortestPathSolution extends AbstractSolution {
|
||||
|
||||
// Optimal solution.
|
||||
private final Path path;
|
||||
|
||||
/**
|
||||
* Create a new infeasible shortest-path solution for the given input and
|
||||
* status.
|
||||
*
|
||||
* @param data Original input data for this solution.
|
||||
* @param status Status of the solution (UNKNOWN / INFEASIBLE).
|
||||
*/
|
||||
public ShortestPathSolution(ShortestPathData data, Status status) {
|
||||
super(data, status);
|
||||
this.path = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new shortest-path solution.
|
||||
*
|
||||
* @param data Original input data for this solution.
|
||||
* @param status Status of the solution (FEASIBLE / OPTIMAL).
|
||||
* @param path Path corresponding to the solution.
|
||||
*/
|
||||
public ShortestPathSolution(ShortestPathData data, Status status, Path path) {
|
||||
super(data, status);
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShortestPathData getInputData() {
|
||||
return (ShortestPathData) super.getInputData();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The path of this solution, if any.
|
||||
*/
|
||||
public Path getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String info = null;
|
||||
if (!isFeasible()) {
|
||||
info = String.format("No path found from node #%d to node #%d",
|
||||
getInputData().getOrigin().getId(), getInputData().getDestination().getId());
|
||||
}
|
||||
else {
|
||||
double cost = 0;
|
||||
for (Arc arc: getPath().getArcs()) {
|
||||
cost += getInputData().getCost(arc);
|
||||
}
|
||||
info = String.format("Found a path from node #%d to node #%d",
|
||||
getInputData().getOrigin().getId(), getInputData().getDestination().getId());
|
||||
if (getInputData().getMode() == Mode.LENGTH) {
|
||||
info = String.format("%s, %.4f kilometers", info, cost / 1000.0);
|
||||
}
|
||||
else {
|
||||
info = String.format("%s, %.4f minutes", info, cost / 60.0);
|
||||
}
|
||||
}
|
||||
info += " in " + getSolvingTime().getSeconds() + " seconds.";
|
||||
return info;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
package org.insa.graphs.algorithm.shortestpath;
|
||||
|
||||
import java.io.PrintStream;
|
||||
|
||||
import org.insa.graphs.model.Node;
|
||||
|
||||
public class ShortestPathTextObserver implements ShortestPathObserver {
|
||||
|
||||
private final PrintStream stream;
|
||||
|
||||
public ShortestPathTextObserver(PrintStream stream) {
|
||||
this.stream = stream;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyOriginProcessed(Node node) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNodeReached(Node node) {
|
||||
stream.println("Node " + node.getId() + " reached.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyNodeMarked(Node node) {
|
||||
stream.println("Node " + node.getId() + " marked.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDestinationReached(Node node) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user