Add Path, ShortestPath, etc. without implementation.
This commit is contained in:
		
							
								
								
									
										128
									
								
								src/main/org/insa/algo/AlgorithmFactory.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								src/main/org/insa/algo/AlgorithmFactory.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | ||||
| package org.insa.algo; | ||||
|  | ||||
| import java.lang.reflect.Constructor; | ||||
| import java.util.IdentityHashMap; | ||||
| import java.util.LinkedHashMap; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
| import java.util.TreeSet; | ||||
|  | ||||
| import org.insa.algo.shortestpath.AStarAlgorithm; | ||||
| import org.insa.algo.shortestpath.BellmanFordAlgorithm; | ||||
| import org.insa.algo.shortestpath.DijkstraAlgorithm; | ||||
| import org.insa.algo.shortestpath.ShortestPathAlgorithm; | ||||
| import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsAlgorithm; | ||||
|  | ||||
| /** | ||||
|  * Factory class used to register and retrieve algorithms based on their common | ||||
|  * ancestor and name. | ||||
|  * | ||||
|  */ | ||||
| public class AlgorithmFactory { | ||||
|  | ||||
|     // Map between algorithm names and class. | ||||
|     private final static Map<Class<? extends AbstractAlgorithm<?>>, Map<String, Class<? extends AbstractAlgorithm<?>>>> ALGORITHMS = new IdentityHashMap<>(); | ||||
|  | ||||
|     static { | ||||
|         // Register weakly-connected components algorithm: | ||||
|         registerAlgorithm(WeaklyConnectedComponentsAlgorithm.class, "WCC basic", | ||||
|                 WeaklyConnectedComponentsAlgorithm.class); | ||||
|  | ||||
|         // Register shortest path algorithm: | ||||
|         registerAlgorithm(ShortestPathAlgorithm.class, "Bellman-Ford", BellmanFordAlgorithm.class); | ||||
|         registerAlgorithm(ShortestPathAlgorithm.class, "Dijkstra", DijkstraAlgorithm.class); | ||||
|         registerAlgorithm(ShortestPathAlgorithm.class, "A*", AStarAlgorithm.class); | ||||
|  | ||||
|         // Register your algorithms here: | ||||
|         // registerAlgorithm(CarPoolingAlgorithm.class, "My Awesome Algorithm", | ||||
|         // MyCarPoolingAlgorithm.class); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Register the given algorithm class with the given name as a child class of | ||||
|      * the given base algorithm. | ||||
|      *  | ||||
|      * @param baseAlgorithm Base algorithm class that corresponds to the newly | ||||
|      *        registered algorithm class (e.g., generic algorithm class for the | ||||
|      *        problem). | ||||
|      * @param name Name for the registered algorithm class. | ||||
|      * @param algoClass Algorithm class to register. | ||||
|      */ | ||||
|     public static void registerAlgorithm(Class<? extends AbstractAlgorithm<?>> baseAlgorithm, | ||||
|             String name, Class<? extends AbstractAlgorithm<?>> algoClass) { | ||||
|         if (!ALGORITHMS.containsKey(baseAlgorithm)) { | ||||
|             ALGORITHMS.put(baseAlgorithm, new LinkedHashMap<>()); | ||||
|         } | ||||
|         ALGORITHMS.get(baseAlgorithm).put(name, algoClass); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create an instance of the given algorithm class using the given input data. | ||||
|      * Assuming algorithm correspond to a class "Algorithm", this function returns | ||||
|      * an object equivalent to `new Algorithm(data)`. | ||||
|      *  | ||||
|      * @param algorithm Class of the algorithm to create. | ||||
|      * @param data Input data for the algorithm. | ||||
|      *  | ||||
|      * @return A new instance of the given algorithm class using the given data. | ||||
|      *  | ||||
|      * @throws Exception if something wrong happens when constructing the object, | ||||
|      *         i.e. the given input data does not correspond to the given algorithm | ||||
|      *         and/or no constructor that takes a single parameter of type | ||||
|      *         (data.getClass()) exists. | ||||
|      */ | ||||
|     public static AbstractAlgorithm<?> createAlgorithm( | ||||
|             Class<? extends AbstractAlgorithm<?>> algorithm, AbstractInputData data) | ||||
|             throws Exception { | ||||
|         // Retrieve the set of constructors for the given algorithm class. | ||||
|         Constructor<?>[] constructors = algorithm.getDeclaredConstructors(); | ||||
|  | ||||
|         // Within this set, find the constructor that can be called with "data" (only). | ||||
|         AbstractAlgorithm<?> constructed = null; | ||||
|         for (Constructor<?> c: constructors) { | ||||
|             Class<?>[] params = c.getParameterTypes(); | ||||
|             if (params.length == 1 && params[0].isAssignableFrom(data.getClass())) { | ||||
|                 c.setAccessible(true); | ||||
|                 constructed = (AbstractAlgorithm<?>) c.newInstance(new Object[]{ data }); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|         return constructed; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Return the algorithm class corresponding to the given base algorithm class | ||||
|      * and name. The algorithm must have been previously registered using | ||||
|      * registerAlgorithm. | ||||
|      *  | ||||
|      * @param baseAlgorithm Base algorithm class for the algorithm to retrieve. | ||||
|      * @param name Name of the algorithm to retrieve. | ||||
|      *  | ||||
|      * @return Class corresponding to the given name. | ||||
|      *  | ||||
|      * @see #registerAlgorithm | ||||
|      */ | ||||
|     public static Class<? extends AbstractAlgorithm<?>> getAlgorithmClass( | ||||
|             Class<? extends AbstractAlgorithm<?>> baseAlgorithm, String name) { | ||||
|         return ALGORITHMS.get(baseAlgorithm).get(name); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Return the list of names corresponding to the registered algorithm classes | ||||
|      * for the given base algorithm class. | ||||
|      *  | ||||
|      * @param baseAlgorithm Base algorithm class for the algorithm class names to | ||||
|      *        retrieve. | ||||
|      *  | ||||
|      * @return Names of the currently registered algorithms. | ||||
|      *  | ||||
|      * @see #registerAlgorithm | ||||
|      */ | ||||
|     public static Set<String> getAlgorithmNames( | ||||
|             Class<? extends AbstractAlgorithm<?>> baseAlgorithm) { | ||||
|         if (!ALGORITHMS.containsKey(baseAlgorithm)) { | ||||
|             return new TreeSet<>(); | ||||
|         } | ||||
|         return ALGORITHMS.get(baseAlgorithm).keySet(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										9
									
								
								src/main/org/insa/algo/shortestpath/AStarAlgorithm.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/main/org/insa/algo/shortestpath/AStarAlgorithm.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| package org.insa.algo.shortestpath; | ||||
|  | ||||
| public class AStarAlgorithm extends DijkstraAlgorithm { | ||||
|  | ||||
|     public AStarAlgorithm(ShortestPathData data) { | ||||
|         super(data); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										102
									
								
								src/main/org/insa/algo/shortestpath/BellmanFordAlgorithm.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								src/main/org/insa/algo/shortestpath/BellmanFordAlgorithm.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| package org.insa.algo.shortestpath; | ||||
|  | ||||
| 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; | ||||
| import org.insa.graph.Node; | ||||
| import org.insa.graph.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.getNodes().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.getMode() == AbstractInputData.Mode.LENGTH ? arc.getLength() | ||||
|                             : arc.getMinimumTravelTime(); | ||||
|  | ||||
|                     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; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										17
									
								
								src/main/org/insa/algo/shortestpath/DijkstraAlgorithm.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/main/org/insa/algo/shortestpath/DijkstraAlgorithm.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| package org.insa.algo.shortestpath; | ||||
|  | ||||
| public class DijkstraAlgorithm extends ShortestPathAlgorithm { | ||||
|  | ||||
|     public DijkstraAlgorithm(ShortestPathData data) { | ||||
|         super(data); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected ShortestPathSolution doRun() { | ||||
|         ShortestPathData data = getInputData(); | ||||
|         ShortestPathSolution solution = null; | ||||
|         // TODO: | ||||
|         return solution; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,69 @@ | ||||
| package org.insa.algo.shortestpath; | ||||
|  | ||||
| import org.insa.algo.AbstractAlgorithm; | ||||
| import org.insa.graph.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); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										63
									
								
								src/main/org/insa/algo/shortestpath/ShortestPathData.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								src/main/org/insa/algo/shortestpath/ShortestPathData.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| package org.insa.algo.shortestpath; | ||||
|  | ||||
| import org.insa.algo.AbstractInputData; | ||||
| import org.insa.graph.Graph; | ||||
| import org.insa.graph.Node; | ||||
|  | ||||
| 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). | ||||
|      */ | ||||
|     public ShortestPathData(Graph graph, Node origin, Node destination, Mode mode, | ||||
|             AbstractInputData.ArcFilter arcFilter) { | ||||
|         super(graph, mode, arcFilter); | ||||
|         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() + " [" | ||||
|                 + getMode().toString().toLowerCase() + "]"; | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,41 @@ | ||||
| package org.insa.algo.shortestpath; | ||||
|  | ||||
| import java.awt.Color; | ||||
|  | ||||
| import org.insa.graph.Node; | ||||
| import org.insa.graphics.drawing.Drawing; | ||||
| import org.insa.graphics.drawing.overlays.PointSetOverlay; | ||||
|  | ||||
| public class ShortestPathGraphicObserver implements ShortestPathObserver { | ||||
|  | ||||
|     // Drawing and Graph drawing | ||||
|     protected Drawing drawing; | ||||
|     protected PointSetOverlay psOverlay1, psOverlay2; | ||||
|  | ||||
|     public ShortestPathGraphicObserver(Drawing drawing) { | ||||
|         this.drawing = drawing; | ||||
|         psOverlay1 = drawing.createPointSetOverlay(1, Color.CYAN); | ||||
|         psOverlay2 = drawing.createPointSetOverlay(1, Color.BLUE); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void notifyOriginProcessed(Node node) { | ||||
|         // drawing.drawMarker(node.getPoint(), Color.RED); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void notifyNodeReached(Node node) { | ||||
|         psOverlay1.addPoint(node.getPoint()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void notifyNodeMarked(Node node) { | ||||
|         psOverlay2.addPoint(node.getPoint()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void notifyDestinationReached(Node node) { | ||||
|         // drawing.drawMarker(node.getPoint(), Color.RED); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,37 @@ | ||||
| package org.insa.algo.shortestpath; | ||||
|  | ||||
| import org.insa.graph.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,76 @@ | ||||
| package org.insa.algo.shortestpath; | ||||
|  | ||||
| import org.insa.algo.AbstractInputData; | ||||
| import org.insa.algo.AbstractSolution; | ||||
| import org.insa.graph.Path; | ||||
|  | ||||
| public class ShortestPathSolution extends AbstractSolution { | ||||
|  | ||||
|     // Optimal solution. | ||||
|     private Path path; | ||||
|  | ||||
|     /** | ||||
|      * {@inheritDoc} | ||||
|      */ | ||||
|     public ShortestPathSolution(ShortestPathData data) { | ||||
|         super(data); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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 { | ||||
|             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)); | ||||
|             } | ||||
|             else { | ||||
|                 info = String.format("%s, %.4f minutes", info, | ||||
|                         (getPath().getMinimumTravelTime() / 60.0)); | ||||
|             } | ||||
|         } | ||||
|         info += " in " + getSolvingTime().getSeconds() + " seconds."; | ||||
|         return info; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -0,0 +1,37 @@ | ||||
| package org.insa.algo.shortestpath; | ||||
|  | ||||
| import java.io.PrintStream; | ||||
|  | ||||
| import org.insa.graph.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 | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										224
									
								
								src/main/org/insa/graph/Path.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								src/main/org/insa/graph/Path.java
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,224 @@ | ||||
| package org.insa.graph; | ||||
|  | ||||
| import java.util.ArrayList; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * Class representing a path between nodes in a graph. | ||||
|  *  | ||||
|  * A path is represented as a list of {@link Arc} and not a list of {@link Node} | ||||
|  * due to the multigraph nature of the considered graphs. | ||||
|  * | ||||
|  */ | ||||
| public class Path { | ||||
|  | ||||
|     /** | ||||
|      * Create a new path that goes through the given list of nodes (in order), | ||||
|      * choosing the fastest route if multiple are available. | ||||
|      *  | ||||
|      * @param graph Graph containing the nodes in the list. | ||||
|      * @param nodes List of nodes to build the path. | ||||
|      *  | ||||
|      * @return A path that goes through the given list of nodes. | ||||
|      *  | ||||
|      * @throws IllegalArgumentException If the list of nodes is not valid, i.e. two | ||||
|      *         consecutive nodes in the list are not connected in the graph. | ||||
|      *  | ||||
|      * @deprecated Need to be implement. | ||||
|      */ | ||||
|     public static Path createFastestPathFromNodes(Graph graph, List<Node> nodes) | ||||
|             throws IllegalArgumentException { | ||||
|         List<Arc> arcs = new ArrayList<Arc>(); | ||||
|         // TODO: | ||||
|         return new Path(graph, arcs); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create a new path that goes through the given list of nodes (in order), | ||||
|      * choosing the shortest route if multiple are available. | ||||
|      *  | ||||
|      * @param graph Graph containing the nodes in the list. | ||||
|      * @param nodes List of nodes to build the path. | ||||
|      *  | ||||
|      * @return A path that goes through the given list of nodes. | ||||
|      *  | ||||
|      * @throws IllegalArgumentException If the list of nodes is not valid, i.e. two | ||||
|      *         consecutive nodes in the list are not connected in the graph. | ||||
|      *  | ||||
|      * @deprecated Need to be implement. | ||||
|      */ | ||||
|     public static Path createShortestPathFromNodes(Graph graph, List<Node> nodes) | ||||
|             throws IllegalArgumentException { | ||||
|         List<Arc> arcs = new ArrayList<Arc>(); | ||||
|         // TODO: | ||||
|         return new Path(graph, arcs); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Concatenate the given paths. | ||||
|      *  | ||||
|      * @param paths Array of paths to concatenate. | ||||
|      *  | ||||
|      * @return Concatenated path. | ||||
|      *  | ||||
|      * @throws IllegalArgumentException if the paths cannot be concatenated (IDs of | ||||
|      *         map do not match, or the end of a path is not the beginning of the | ||||
|      *         next). | ||||
|      */ | ||||
|     public static Path concatenate(Path... paths) throws IllegalArgumentException { | ||||
|         if (paths.length == 0) { | ||||
|             throw new IllegalArgumentException("Cannot concatenate an empty list of paths."); | ||||
|         } | ||||
|         final String mapId = paths[0].getGraph().getMapId(); | ||||
|         for (int i = 1; i < paths.length; ++i) { | ||||
|             if (!paths[i].getGraph().getMapId().equals(mapId)) { | ||||
|                 throw new IllegalArgumentException( | ||||
|                         "Cannot concatenate paths from different graphs."); | ||||
|             } | ||||
|         } | ||||
|         ArrayList<Arc> arcs = new ArrayList<>(); | ||||
|         for (Path path: paths) { | ||||
|             arcs.addAll(path.getArcs()); | ||||
|         } | ||||
|         Path path = new Path(paths[0].getGraph(), arcs); | ||||
|         if (!path.isValid()) { | ||||
|             throw new IllegalArgumentException( | ||||
|                     "Cannot concatenate paths that do not form a single path."); | ||||
|         } | ||||
|         return path; | ||||
|     } | ||||
|  | ||||
|     // Graph containing this path. | ||||
|     private final Graph graph; | ||||
|  | ||||
|     // Origin of the path | ||||
|     private final Node origin; | ||||
|  | ||||
|     // List of arcs in this path. | ||||
|     private final List<Arc> arcs; | ||||
|  | ||||
|     /** | ||||
|      * Create an empty path corresponding to the given graph. | ||||
|      *  | ||||
|      * @param graph Graph containing the path. | ||||
|      */ | ||||
|     public Path(Graph graph) { | ||||
|         this.graph = graph; | ||||
|         this.origin = null; | ||||
|         this.arcs = new ArrayList<>(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create a new path containing a single node. | ||||
|      *  | ||||
|      * @param graph Graph containing the path. | ||||
|      * @param node Single node of the path. | ||||
|      */ | ||||
|     public Path(Graph graph, Node node) { | ||||
|         this.graph = graph; | ||||
|         this.origin = node; | ||||
|         this.arcs = new ArrayList<>(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create a new path with the given list of arcs. | ||||
|      *  | ||||
|      * @param graph Graph containing the path. | ||||
|      * @param arcs Arcs to construct the path. | ||||
|      */ | ||||
|     public Path(Graph graph, List<Arc> arcs) { | ||||
|         this.graph = graph; | ||||
|         this.arcs = arcs; | ||||
|         this.origin = arcs.size() > 0 ? arcs.get(0).getOrigin() : null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Graph containing the path. | ||||
|      */ | ||||
|     public Graph getGraph() { | ||||
|         return graph; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return First node of the path. | ||||
|      */ | ||||
|     public Node getOrigin() { | ||||
|         return origin; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Last node of the path. | ||||
|      */ | ||||
|     public Node getDestination() { | ||||
|         return arcs.get(arcs.size() - 1).getDestination(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return List of arcs in the path. | ||||
|      */ | ||||
|     public List<Arc> getArcs() { | ||||
|         return Collections.unmodifiableList(arcs); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check if this path is empty (it does not contain any node). | ||||
|      *  | ||||
|      * @return true if this path is empty, false otherwise. | ||||
|      */ | ||||
|     public boolean isEmpty() { | ||||
|         return arcs.isEmpty(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check if this path is valid. | ||||
|      *  | ||||
|      * A path is valid if it is empty, contains a single node (without arcs) or if | ||||
|      * the first arc has for origin the origin of the path and, for two consecutive | ||||
|      * arcs, the destination of the first one is the origin of the second one. | ||||
|      *  | ||||
|      * @return true if the path is valid, false otherwise. | ||||
|      *  | ||||
|      * @deprecated Need to be implement. | ||||
|      */ | ||||
|     public boolean isValid() { | ||||
|         // TODO: | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Total length of the path. | ||||
|      *  | ||||
|      * @deprecated Need to be implement. | ||||
|      */ | ||||
|     public float getLength() { | ||||
|         // TODO: | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Compute the time required to travel this path if moving at the given speed. | ||||
|      *  | ||||
|      * @param speed Speed to compute the travel time. | ||||
|      *  | ||||
|      * @return Time (in seconds) required to travel this path at the given speed (in | ||||
|      *         kilometers-per-hour). | ||||
|      *  | ||||
|      * @deprecated Need to be implement. | ||||
|      */ | ||||
|     public double getTravelTime(double speed) { | ||||
|         // TODO: | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Minimum travel time of the in seconds (assuming maximum speed). | ||||
|      *  | ||||
|      * @deprecated Need to be implement. | ||||
|      */ | ||||
|     public double getMinimumTravelTime() { | ||||
|         // TODO: | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user