New updates.
This commit is contained in:
@@ -2,6 +2,7 @@ package org.insa.algo;
|
||||
|
||||
import org.insa.graph.Arc;
|
||||
import org.insa.graph.Graph;
|
||||
import org.insa.graph.GraphStatistics;
|
||||
|
||||
/**
|
||||
* Base class for algorithm input data classes. This class contains the basic
|
||||
@@ -12,77 +13,29 @@ import org.insa.graph.Graph;
|
||||
public abstract class AbstractInputData {
|
||||
|
||||
/**
|
||||
* Mode for computing costs on the arc (time or length).
|
||||
*
|
||||
* Enum specifying the top mode of the algorithms.
|
||||
*
|
||||
* @see ArcInspector
|
||||
*/
|
||||
public enum Mode {
|
||||
TIME, LENGTH
|
||||
}
|
||||
|
||||
/**
|
||||
* Filtering interface for arcs - This class can be used to indicate to an
|
||||
* algorithm which arc can be used.
|
||||
*
|
||||
*/
|
||||
public interface ArcFilter {
|
||||
|
||||
/**
|
||||
* Check if the given arc can be used (is allowed).
|
||||
*
|
||||
* @param arc Arc to check.
|
||||
*
|
||||
* @return true if the given arc is allowed.
|
||||
*/
|
||||
public boolean isAllowed(Arc arc);
|
||||
|
||||
}
|
||||
|
||||
// Graph
|
||||
private final Graph graph;
|
||||
|
||||
// Mode for the computation of the costs.
|
||||
private final Mode mode;
|
||||
|
||||
// Arc filter.
|
||||
private final ArcFilter arcFilter;
|
||||
protected final ArcInspector arcInspector;
|
||||
|
||||
/**
|
||||
* Create a new AbstractInputData instance for the given graph, mode and filter.
|
||||
*
|
||||
* @param graph
|
||||
* @parma mode
|
||||
* @param arcFilter
|
||||
* @param graph Graph for this input data.
|
||||
* @param arcInspector Arc inspector for this input data.
|
||||
*/
|
||||
protected AbstractInputData(Graph graph, Mode mode, ArcFilter arcFilter) {
|
||||
protected AbstractInputData(Graph graph, ArcInspector arcInspector) {
|
||||
this.graph = graph;
|
||||
this.mode = mode;
|
||||
this.arcFilter = arcFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new AbstractInputData instance for the given graph and mode, with no
|
||||
* filtering on the arc.
|
||||
*
|
||||
* @param graph
|
||||
* @param mode
|
||||
*/
|
||||
protected AbstractInputData(Graph graph, Mode mode) {
|
||||
this(graph, mode, new AbstractInputData.ArcFilter() {
|
||||
@Override
|
||||
public boolean isAllowed(Arc arc) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new AbstractInputData instance for the given graph, with default
|
||||
* mode (LENGHT), with no filtering on the arc.
|
||||
*
|
||||
* @param graph
|
||||
*/
|
||||
protected AbstractInputData(Graph graph) {
|
||||
this(graph, Mode.LENGTH);
|
||||
this.arcInspector = arcInspector;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,12 +46,39 @@ public abstract class AbstractInputData {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Mode of the algorithm (time or length).
|
||||
* Retrieve the cost associated with the given arc according to the underlying
|
||||
* arc inspector.
|
||||
*
|
||||
* @param arc Arc for which cost should be retrieved.
|
||||
*
|
||||
* @return Cost for the given arc.
|
||||
*
|
||||
* @see ArcInspector
|
||||
*/
|
||||
public double getCost(Arc arc) {
|
||||
return this.arcInspector.getCost(arc);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Mode associated with this input data.
|
||||
*
|
||||
* @see Mode
|
||||
*/
|
||||
public Mode getMode() {
|
||||
return mode;
|
||||
return this.arcInspector.getMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the maximum speed associated with this input data, or
|
||||
* {@link GraphStatistics#NO_MAXIMUM_SPEED} if none is associated. The maximum
|
||||
* speed associated with input data is different from the maximum speed
|
||||
* associated with graph (accessible via {@link Graph#getGraphInformation()}).
|
||||
*
|
||||
* @return The maximum speed for this inspector, or
|
||||
* {@link GraphStatistics#NO_MAXIMUM_SPEED} if none is set.
|
||||
*/
|
||||
public int getMaximumSpeed() {
|
||||
return this.arcInspector.getMaximumSpeed();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,10 +88,10 @@ public abstract class AbstractInputData {
|
||||
*
|
||||
* @return true if the given arc is allowed.
|
||||
*
|
||||
* @see ArcFilter
|
||||
* @see ArcInspector
|
||||
*/
|
||||
public boolean isAllowed(Arc arc) {
|
||||
return this.arcFilter.isAllowed(arc);
|
||||
return this.arcInspector.isAllowed(arc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
package org.insa.algo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.insa.algo.AbstractInputData.ArcFilter;
|
||||
import org.insa.graph.AccessRestrictions.AccessMode;
|
||||
import org.insa.graph.AccessRestrictions.AccessRestriction;
|
||||
import org.insa.graph.Arc;
|
||||
|
||||
public class ArcFilterFactory {
|
||||
|
||||
/**
|
||||
* @return List of all arc filters in this factory.
|
||||
*/
|
||||
public static List<ArcFilter> getAllFilters() {
|
||||
List<ArcFilter> filters = new ArrayList<>();
|
||||
|
||||
// Common filters:
|
||||
|
||||
// 1. No filter (all arcs allowed):
|
||||
filters.add(new ArcFilter() {
|
||||
@Override
|
||||
public boolean isAllowed(Arc arc) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "All roads are allowed.";
|
||||
}
|
||||
});
|
||||
|
||||
// 2. Only road allowed for cars:
|
||||
filters.add(new ArcFilter() {
|
||||
@Override
|
||||
public boolean isAllowed(Arc arc) {
|
||||
return arc.getRoadInformation().getAccessRestrictions()
|
||||
.isAllowedForAny(AccessMode.MOTORCAR, EnumSet.complementOf(EnumSet
|
||||
.of(AccessRestriction.FORBIDDEN, AccessRestriction.PRIVATE)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Only roads open for cars.";
|
||||
}
|
||||
});
|
||||
|
||||
// 3. Non-private roads for pedestrian and bicycle:
|
||||
filters.add(new ArcFilter() {
|
||||
@Override
|
||||
public boolean isAllowed(Arc arc) {
|
||||
return arc.getRoadInformation().getAccessRestrictions()
|
||||
.isAllowedForAny(AccessMode.FOOT, EnumSet.complementOf(EnumSet
|
||||
.of(AccessRestriction.FORBIDDEN, AccessRestriction.PRIVATE)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Non-private roads for pedestrian.";
|
||||
}
|
||||
});
|
||||
|
||||
// 3. Add your own filters here (do not forget to implement toString() to get an
|
||||
// understandable output!):
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
}
|
||||
43
src/main/org/insa/algo/ArcInspector.java
Normal file
43
src/main/org/insa/algo/ArcInspector.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package org.insa.algo;
|
||||
|
||||
import org.insa.algo.AbstractInputData.Mode;
|
||||
import org.insa.graph.Arc;
|
||||
import org.insa.graph.GraphStatistics;
|
||||
|
||||
/**
|
||||
* This class can be used to indicate to an algorithm which arcs can be used and
|
||||
* the costs of the usable arcs..
|
||||
*
|
||||
*/
|
||||
public interface ArcInspector {
|
||||
|
||||
/**
|
||||
* Check if the given arc can be used (is allowed).
|
||||
*
|
||||
* @param arc Arc to check.
|
||||
*
|
||||
* @return true if the given arc is allowed.
|
||||
*/
|
||||
public boolean isAllowed(Arc arc);
|
||||
|
||||
/**
|
||||
* Find the cost of the given arc.
|
||||
*
|
||||
* @param arc Arc for which the cost should be returned.
|
||||
*
|
||||
* @return Cost of the arc.
|
||||
*/
|
||||
public double getCost(Arc arc);
|
||||
|
||||
/**
|
||||
* @return The maximum speed for this inspector, or
|
||||
* {@link GraphStatistics#NO_MAXIMUM_SPEED} if none is set.
|
||||
*/
|
||||
public int getMaximumSpeed();
|
||||
|
||||
/**
|
||||
* @return Mode for this arc inspector.
|
||||
*/
|
||||
public Mode getMode();
|
||||
|
||||
}
|
||||
149
src/main/org/insa/algo/ArcInspectorFactory.java
Normal file
149
src/main/org/insa/algo/ArcInspectorFactory.java
Normal file
@@ -0,0 +1,149 @@
|
||||
package org.insa.algo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.insa.algo.AbstractInputData.Mode;
|
||||
import org.insa.graph.AccessRestrictions.AccessMode;
|
||||
import org.insa.graph.AccessRestrictions.AccessRestriction;
|
||||
import org.insa.graph.Arc;
|
||||
import org.insa.graph.GraphStatistics;
|
||||
|
||||
public class ArcInspectorFactory {
|
||||
|
||||
/**
|
||||
* @return List of all arc filters in this factory.
|
||||
*/
|
||||
public static List<ArcInspector> getAllFilters() {
|
||||
List<ArcInspector> filters = new ArrayList<>();
|
||||
|
||||
// Common filters:
|
||||
|
||||
// No filter (all arcs allowed):
|
||||
filters.add(new ArcInspector() {
|
||||
@Override
|
||||
public boolean isAllowed(Arc arc) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCost(Arc arc) {
|
||||
return arc.getLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumSpeed() {
|
||||
return GraphStatistics.NO_MAXIMUM_SPEED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mode getMode() {
|
||||
return Mode.LENGTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Shortest path, all roads allowed";
|
||||
}
|
||||
});
|
||||
|
||||
// Only road allowed for cars and length:
|
||||
filters.add(new ArcInspector() {
|
||||
@Override
|
||||
public boolean isAllowed(Arc arc) {
|
||||
return arc.getRoadInformation().getAccessRestrictions()
|
||||
.isAllowedForAny(AccessMode.MOTORCAR, EnumSet.complementOf(EnumSet
|
||||
.of(AccessRestriction.FORBIDDEN, AccessRestriction.PRIVATE)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCost(Arc arc) {
|
||||
return arc.getLength();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumSpeed() {
|
||||
return GraphStatistics.NO_MAXIMUM_SPEED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mode getMode() {
|
||||
return Mode.LENGTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Shortest path, only roads open for cars";
|
||||
}
|
||||
});
|
||||
|
||||
// Only road allowed for cars and time:
|
||||
filters.add(new ArcInspector() {
|
||||
@Override
|
||||
public boolean isAllowed(Arc arc) {
|
||||
return arc.getRoadInformation().getAccessRestrictions()
|
||||
.isAllowedForAny(AccessMode.MOTORCAR, EnumSet.complementOf(EnumSet
|
||||
.of(AccessRestriction.FORBIDDEN, AccessRestriction.PRIVATE)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCost(Arc arc) {
|
||||
return arc.getMinimumTravelTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumSpeed() {
|
||||
return GraphStatistics.NO_MAXIMUM_SPEED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mode getMode() {
|
||||
return Mode.TIME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Fastest path, only roads open for cars";
|
||||
}
|
||||
});
|
||||
|
||||
// Non-private roads for pedestrian and bicycle:
|
||||
filters.add(new ArcInspector() {
|
||||
|
||||
@Override
|
||||
public boolean isAllowed(Arc arc) {
|
||||
return arc.getRoadInformation().getAccessRestrictions()
|
||||
.isAllowedForAny(AccessMode.FOOT, EnumSet.complementOf(EnumSet
|
||||
.of(AccessRestriction.FORBIDDEN, AccessRestriction.PRIVATE)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCost(Arc arc) {
|
||||
return arc.getTravelTime(
|
||||
Math.min(getMaximumSpeed(), arc.getRoadInformation().getMaximumSpeed()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Fastest path for pedestrian";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumSpeed() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mode getMode() {
|
||||
return Mode.TIME;
|
||||
}
|
||||
});
|
||||
|
||||
// Add your own filters here (do not forget to implement toString()
|
||||
// to get an understandable output!):
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,12 +1,13 @@
|
||||
package org.insa.algo.carpooling;
|
||||
|
||||
import org.insa.algo.AbstractInputData;
|
||||
import org.insa.algo.ArcInspector;
|
||||
import org.insa.graph.Graph;
|
||||
|
||||
public class CarPoolingData extends AbstractInputData {
|
||||
|
||||
protected CarPoolingData(Graph graph, Mode mode, ArcFilter arcFilter) {
|
||||
super(graph, mode, arcFilter);
|
||||
protected CarPoolingData(Graph graph, ArcInspector arcFilter) {
|
||||
super(graph, arcFilter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package org.insa.algo.packageswitch;
|
||||
|
||||
import org.insa.algo.AbstractInputData;
|
||||
import org.insa.algo.ArcInspector;
|
||||
import org.insa.graph.Graph;
|
||||
|
||||
public class PackageSwitchData extends AbstractInputData {
|
||||
|
||||
protected PackageSwitchData(Graph graph, Mode mode, ArcFilter arcFilter) {
|
||||
super(graph, mode, arcFilter);
|
||||
protected PackageSwitchData(Graph graph, ArcInspector arcFilter) {
|
||||
super(graph, arcFilter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.insa.algo.AbstractInputData;
|
||||
import org.insa.algo.AbstractSolution.Status;
|
||||
import org.insa.graph.Arc;
|
||||
import org.insa.graph.Graph;
|
||||
@@ -13,90 +12,88 @@ 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) {
|
||||
for (Arc arc : node) {
|
||||
|
||||
// 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.getMode() == AbstractInputData.Mode.LENGTH ? arc.getLength()
|
||||
: arc.getMinimumTravelTime();
|
||||
// Retrieve weight of the arc.
|
||||
double w = data.getCost(arc);
|
||||
double oldDistance = distances[arc.getDestination().getId()];
|
||||
double newDistance = distances[node.getId()] + w;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.insa.algo.shortestpath;
|
||||
|
||||
import org.insa.algo.AbstractInputData;
|
||||
import org.insa.algo.ArcInspector;
|
||||
import org.insa.graph.Graph;
|
||||
import org.insa.graph.Node;
|
||||
|
||||
@@ -9,34 +10,17 @@ public class ShortestPathData extends AbstractInputData {
|
||||
// Origin and destination nodes.
|
||||
private final Node origin, destination;
|
||||
|
||||
/**
|
||||
* Construct a new instance of ShortestPathData with the given parameters and
|
||||
* for which all arcs are allowed.
|
||||
*
|
||||
* @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 mode Cost mode for the path.
|
||||
*/
|
||||
public ShortestPathData(Graph graph, Node origin, Node destination, Mode mode) {
|
||||
super(graph, mode);
|
||||
this.origin = origin;
|
||||
this.destination = 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 mode Cost mode for the path.
|
||||
* @param arcFilter Filter for arcs (used to allow only a specific set of arcs
|
||||
* in the graph to be used).
|
||||
* @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, Mode mode,
|
||||
AbstractInputData.ArcFilter arcFilter) {
|
||||
super(graph, mode, arcFilter);
|
||||
public ShortestPathData(Graph graph, Node origin, Node destination, ArcInspector arcInspector) {
|
||||
super(graph, arcInspector);
|
||||
this.origin = origin;
|
||||
this.destination = destination;
|
||||
}
|
||||
@@ -58,6 +42,6 @@ public class ShortestPathData extends AbstractInputData {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Shortest-path from #" + origin.getId() + " to #" + destination.getId() + " ["
|
||||
+ getMode().toString().toLowerCase() + "]";
|
||||
+ this.arcInspector.toString().toLowerCase() + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package org.insa.algo.shortestpath;
|
||||
|
||||
import org.insa.algo.AbstractInputData;
|
||||
import org.insa.algo.AbstractInputData.Mode;
|
||||
import org.insa.algo.AbstractSolution;
|
||||
import org.insa.graph.Arc;
|
||||
import org.insa.graph.Path;
|
||||
|
||||
public class ShortestPathSolution extends AbstractSolution {
|
||||
@@ -59,14 +60,17 @@ public class ShortestPathSolution extends AbstractSolution {
|
||||
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() == AbstractInputData.Mode.LENGTH) {
|
||||
info = String.format("%s, %.4f kilometers", info, (getPath().getLength() / 1000.0));
|
||||
if (getInputData().getMode() == Mode.LENGTH) {
|
||||
info = String.format("%s, %.4f kilometers", info, cost / 1000.0);
|
||||
}
|
||||
else {
|
||||
info = String.format("%s, %.4f minutes", info,
|
||||
(getPath().getMinimumTravelTime() / 60.0));
|
||||
info = String.format("%s, %.4f minutes", info, cost / 60.0);
|
||||
}
|
||||
}
|
||||
info += " in " + getSolvingTime().getSeconds() + " seconds.";
|
||||
|
||||
@@ -18,14 +18,13 @@ import java.util.ArrayList;
|
||||
* @author Mark Allen Weiss
|
||||
* @author DLB
|
||||
*/
|
||||
public class BinaryHeap<E extends Comparable<E>> {
|
||||
public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
|
||||
|
||||
// Number of elements in heap.
|
||||
private int currentSize;
|
||||
|
||||
// The heap array. Java genericity does not work with arrays so we have to use
|
||||
// an ArrayList.
|
||||
private ArrayList<E> array;
|
||||
// The heap array.
|
||||
private final ArrayList<E> array;
|
||||
|
||||
/**
|
||||
* Construct a new empty binary heap.
|
||||
@@ -126,62 +125,37 @@ public class BinaryHeap<E extends Comparable<E>> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the heap is empty, false otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.currentSize == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Current size (number of elements) of this heap.
|
||||
*/
|
||||
@Override
|
||||
public int size() {
|
||||
return this.currentSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert the given element into the heap.
|
||||
*
|
||||
* @param x Item to insert.
|
||||
*/
|
||||
public void add(E x) {
|
||||
@Override
|
||||
public void insert(E x) {
|
||||
int index = this.currentSize++;
|
||||
this.arraySet(index, x);
|
||||
this.percolateUp(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the binary heap that the given element has been modified and should be
|
||||
* re-positioned inside the heap.
|
||||
*
|
||||
* @param x Item to update.
|
||||
*/
|
||||
public void update(E x) {
|
||||
@Override
|
||||
public void remove(E x) throws ElementNotFoundException {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the smallest item in the heap.
|
||||
*
|
||||
* @return The smallest item in the heap.
|
||||
*
|
||||
* @throws RuntimeException if this heap is empty.
|
||||
*/
|
||||
public E findMin() throws RuntimeException {
|
||||
@Override
|
||||
public E findMin() throws EmptyPriorityQueueException {
|
||||
if (isEmpty())
|
||||
throw new RuntimeException("Empty binary heap.");
|
||||
return this.array.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the smallest item from the heap.
|
||||
*
|
||||
* @return The smallest item in the heap.
|
||||
*
|
||||
* @throws RuntimeException if this heap is empty.
|
||||
*/
|
||||
public E deleteMin() throws RuntimeException {
|
||||
@Override
|
||||
public E deleteMin() throws EmptyPriorityQueueException {
|
||||
E minItem = findMin();
|
||||
E lastItem = this.array.get(--this.currentSize);
|
||||
this.arraySet(0, lastItem);
|
||||
|
||||
64
src/main/org/insa/algo/utils/BinarySearchTree.java
Normal file
64
src/main/org/insa/algo/utils/BinarySearchTree.java
Normal file
@@ -0,0 +1,64 @@
|
||||
package org.insa.algo.utils;
|
||||
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
public class BinarySearchTree<E extends Comparable<E>> implements PriorityQueue<E> {
|
||||
|
||||
// Underlying implementation
|
||||
private final SortedSet<E> sortedSet;
|
||||
|
||||
/**
|
||||
* Create a new empty binary search tree.
|
||||
*/
|
||||
public BinarySearchTree() {
|
||||
this.sortedSet = new TreeSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a copy of the given binary search tree.
|
||||
*
|
||||
* @param bst Binary search tree to copy.
|
||||
*/
|
||||
public BinarySearchTree(BinarySearchTree<E> bst) {
|
||||
this.sortedSet = new TreeSet<>(bst.sortedSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return sortedSet.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return sortedSet.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(E x) {
|
||||
sortedSet.add(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(E x) throws ElementNotFoundException {
|
||||
if (!sortedSet.remove(x)) {
|
||||
throw new ElementNotFoundException(x);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public E findMin() throws EmptyPriorityQueueException {
|
||||
if (isEmpty()) {
|
||||
throw new EmptyPriorityQueueException();
|
||||
}
|
||||
return sortedSet.first();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E deleteMin() throws EmptyPriorityQueueException {
|
||||
E min = findMin();
|
||||
remove(min);
|
||||
return min;
|
||||
}
|
||||
|
||||
}
|
||||
32
src/main/org/insa/algo/utils/ElementNotFoundException.java
Normal file
32
src/main/org/insa/algo/utils/ElementNotFoundException.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package org.insa.algo.utils;
|
||||
|
||||
public class ElementNotFoundException extends RuntimeException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// Element not found
|
||||
private final Object element;
|
||||
|
||||
/**
|
||||
* @param element Element that was not found.
|
||||
*/
|
||||
public ElementNotFoundException(Object element) {
|
||||
this.element = element;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The element that was not found.
|
||||
*/
|
||||
public Object getElement() {
|
||||
return this.element;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "element not found: " + element;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.insa.algo.utils;
|
||||
|
||||
public class EmptyPriorityQueueException extends RuntimeException {
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public EmptyPriorityQueueException() {
|
||||
}
|
||||
|
||||
}
|
||||
54
src/main/org/insa/algo/utils/PriorityQueue.java
Normal file
54
src/main/org/insa/algo/utils/PriorityQueue.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package org.insa.algo.utils;
|
||||
|
||||
/**
|
||||
* Interface representing a basic priority queue.
|
||||
*
|
||||
* @see https://en.wikipedia.org/wiki/Priority_queue
|
||||
*/
|
||||
public interface PriorityQueue<E extends Comparable<E>> {
|
||||
|
||||
/**
|
||||
* Check if the priority queue is empty.
|
||||
*
|
||||
* @return true if the queue is empty, false otherwise.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* @return Current size (number of elements) of this queue.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* Insert the given element into the queue.
|
||||
*
|
||||
* @param x Item to insert.
|
||||
*/
|
||||
public void insert(E x);
|
||||
|
||||
/**
|
||||
* Remove the given element from the priority queue.
|
||||
*
|
||||
* @param x Item to remove.
|
||||
*/
|
||||
public void remove(E x) throws ElementNotFoundException;
|
||||
|
||||
/**
|
||||
* Retrieve (but not remove) the smallest item in the queue.
|
||||
*
|
||||
* @return The smallest item in the queue.
|
||||
*
|
||||
* @throws EmptyPriorityQueueException if this queue is empty.
|
||||
*/
|
||||
public E findMin() throws EmptyPriorityQueueException;
|
||||
|
||||
/**
|
||||
* Remove and return the smallest item from the priority queue.
|
||||
*
|
||||
* @return The smallest item in the queue.
|
||||
*
|
||||
* @throws EmptyPriorityQueueException if this queue is empty.
|
||||
*/
|
||||
public E deleteMin() throws EmptyPriorityQueueException;
|
||||
|
||||
}
|
||||
@@ -9,7 +9,7 @@ public class WeaklyConnectedComponentsData extends AbstractInputData {
|
||||
* @param graph Graph for which components should be retrieved.
|
||||
*/
|
||||
public WeaklyConnectedComponentsData(Graph graph) {
|
||||
super(graph);
|
||||
super(graph, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user