Browse Source

Add Path, ShortestPath, etc. without implementation.

Mikael Capelle 6 years ago
parent
commit
2624681499

+ 128
- 0
src/main/org/insa/algo/AlgorithmFactory.java View File

@@ -0,0 +1,128 @@
1
+package org.insa.algo;
2
+
3
+import java.lang.reflect.Constructor;
4
+import java.util.IdentityHashMap;
5
+import java.util.LinkedHashMap;
6
+import java.util.Map;
7
+import java.util.Set;
8
+import java.util.TreeSet;
9
+
10
+import org.insa.algo.shortestpath.AStarAlgorithm;
11
+import org.insa.algo.shortestpath.BellmanFordAlgorithm;
12
+import org.insa.algo.shortestpath.DijkstraAlgorithm;
13
+import org.insa.algo.shortestpath.ShortestPathAlgorithm;
14
+import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsAlgorithm;
15
+
16
+/**
17
+ * Factory class used to register and retrieve algorithms based on their common
18
+ * ancestor and name.
19
+ *
20
+ */
21
+public class AlgorithmFactory {
22
+
23
+    // Map between algorithm names and class.
24
+    private final static Map<Class<? extends AbstractAlgorithm<?>>, Map<String, Class<? extends AbstractAlgorithm<?>>>> ALGORITHMS = new IdentityHashMap<>();
25
+
26
+    static {
27
+        // Register weakly-connected components algorithm:
28
+        registerAlgorithm(WeaklyConnectedComponentsAlgorithm.class, "WCC basic",
29
+                WeaklyConnectedComponentsAlgorithm.class);
30
+
31
+        // Register shortest path algorithm:
32
+        registerAlgorithm(ShortestPathAlgorithm.class, "Bellman-Ford", BellmanFordAlgorithm.class);
33
+        registerAlgorithm(ShortestPathAlgorithm.class, "Dijkstra", DijkstraAlgorithm.class);
34
+        registerAlgorithm(ShortestPathAlgorithm.class, "A*", AStarAlgorithm.class);
35
+
36
+        // Register your algorithms here:
37
+        // registerAlgorithm(CarPoolingAlgorithm.class, "My Awesome Algorithm",
38
+        // MyCarPoolingAlgorithm.class);
39
+    }
40
+
41
+    /**
42
+     * Register the given algorithm class with the given name as a child class of
43
+     * the given base algorithm.
44
+     * 
45
+     * @param baseAlgorithm Base algorithm class that corresponds to the newly
46
+     *        registered algorithm class (e.g., generic algorithm class for the
47
+     *        problem).
48
+     * @param name Name for the registered algorithm class.
49
+     * @param algoClass Algorithm class to register.
50
+     */
51
+    public static void registerAlgorithm(Class<? extends AbstractAlgorithm<?>> baseAlgorithm,
52
+            String name, Class<? extends AbstractAlgorithm<?>> algoClass) {
53
+        if (!ALGORITHMS.containsKey(baseAlgorithm)) {
54
+            ALGORITHMS.put(baseAlgorithm, new LinkedHashMap<>());
55
+        }
56
+        ALGORITHMS.get(baseAlgorithm).put(name, algoClass);
57
+    }
58
+
59
+    /**
60
+     * Create an instance of the given algorithm class using the given input data.
61
+     * Assuming algorithm correspond to a class "Algorithm", this function returns
62
+     * an object equivalent to `new Algorithm(data)`.
63
+     * 
64
+     * @param algorithm Class of the algorithm to create.
65
+     * @param data Input data for the algorithm.
66
+     * 
67
+     * @return A new instance of the given algorithm class using the given data.
68
+     * 
69
+     * @throws Exception if something wrong happens when constructing the object,
70
+     *         i.e. the given input data does not correspond to the given algorithm
71
+     *         and/or no constructor that takes a single parameter of type
72
+     *         (data.getClass()) exists.
73
+     */
74
+    public static AbstractAlgorithm<?> createAlgorithm(
75
+            Class<? extends AbstractAlgorithm<?>> algorithm, AbstractInputData data)
76
+            throws Exception {
77
+        // Retrieve the set of constructors for the given algorithm class.
78
+        Constructor<?>[] constructors = algorithm.getDeclaredConstructors();
79
+
80
+        // Within this set, find the constructor that can be called with "data" (only).
81
+        AbstractAlgorithm<?> constructed = null;
82
+        for (Constructor<?> c: constructors) {
83
+            Class<?>[] params = c.getParameterTypes();
84
+            if (params.length == 1 && params[0].isAssignableFrom(data.getClass())) {
85
+                c.setAccessible(true);
86
+                constructed = (AbstractAlgorithm<?>) c.newInstance(new Object[]{ data });
87
+                break;
88
+            }
89
+        }
90
+        return constructed;
91
+    }
92
+
93
+    /**
94
+     * Return the algorithm class corresponding to the given base algorithm class
95
+     * and name. The algorithm must have been previously registered using
96
+     * registerAlgorithm.
97
+     * 
98
+     * @param baseAlgorithm Base algorithm class for the algorithm to retrieve.
99
+     * @param name Name of the algorithm to retrieve.
100
+     * 
101
+     * @return Class corresponding to the given name.
102
+     * 
103
+     * @see #registerAlgorithm
104
+     */
105
+    public static Class<? extends AbstractAlgorithm<?>> getAlgorithmClass(
106
+            Class<? extends AbstractAlgorithm<?>> baseAlgorithm, String name) {
107
+        return ALGORITHMS.get(baseAlgorithm).get(name);
108
+    }
109
+
110
+    /**
111
+     * Return the list of names corresponding to the registered algorithm classes
112
+     * for the given base algorithm class.
113
+     * 
114
+     * @param baseAlgorithm Base algorithm class for the algorithm class names to
115
+     *        retrieve.
116
+     * 
117
+     * @return Names of the currently registered algorithms.
118
+     * 
119
+     * @see #registerAlgorithm
120
+     */
121
+    public static Set<String> getAlgorithmNames(
122
+            Class<? extends AbstractAlgorithm<?>> baseAlgorithm) {
123
+        if (!ALGORITHMS.containsKey(baseAlgorithm)) {
124
+            return new TreeSet<>();
125
+        }
126
+        return ALGORITHMS.get(baseAlgorithm).keySet();
127
+    }
128
+}

+ 9
- 0
src/main/org/insa/algo/shortestpath/AStarAlgorithm.java View File

@@ -0,0 +1,9 @@
1
+package org.insa.algo.shortestpath;
2
+
3
+public class AStarAlgorithm extends DijkstraAlgorithm {
4
+
5
+    public AStarAlgorithm(ShortestPathData data) {
6
+        super(data);
7
+    }
8
+
9
+}

+ 102
- 0
src/main/org/insa/algo/shortestpath/BellmanFordAlgorithm.java View File

@@ -0,0 +1,102 @@
1
+package org.insa.algo.shortestpath;
2
+
3
+import java.util.ArrayList;
4
+import java.util.Arrays;
5
+import java.util.Collections;
6
+
7
+import org.insa.algo.AbstractInputData;
8
+import org.insa.algo.AbstractSolution.Status;
9
+import org.insa.graph.Arc;
10
+import org.insa.graph.Graph;
11
+import org.insa.graph.Node;
12
+import org.insa.graph.Path;
13
+
14
+public class BellmanFordAlgorithm extends ShortestPathAlgorithm {
15
+
16
+    public BellmanFordAlgorithm(ShortestPathData data) {
17
+        super(data);
18
+    }
19
+
20
+    @Override
21
+    protected ShortestPathSolution doRun() {
22
+
23
+        // Retrieve the graph.
24
+        ShortestPathData data = getInputData();
25
+        Graph graph = data.getGraph();
26
+
27
+        final int nbNodes = graph.getNodes().size();
28
+
29
+        // Initialize array of distances.
30
+        double[] distances = new double[nbNodes];
31
+        Arrays.fill(distances, Double.POSITIVE_INFINITY);
32
+        distances[data.getOrigin().getId()] = 0;
33
+
34
+        // Notify observers about the first event (origin processed).
35
+        notifyOriginProcessed(data.getOrigin());
36
+
37
+        // Initialize array of predecessors.
38
+        Arc[] predecessorArcs = new Arc[nbNodes];
39
+
40
+        // Actual algorithm, we will assume the graph does not contain negative cycle...
41
+        boolean found = false;
42
+        for (int i = 0; !found && i < nbNodes; ++i) {
43
+            found = true;
44
+            for (Node node: graph.getNodes()) {
45
+                for (Arc arc: node.getSuccessors()) {
46
+
47
+                    // Small test to check allowed roads...
48
+                    if (!data.isAllowed(arc)) {
49
+                        continue;
50
+                    }
51
+
52
+                    // Retrieve weight of the arc.
53
+                    double w = data.getMode() == AbstractInputData.Mode.LENGTH ? arc.getLength()
54
+                            : arc.getMinimumTravelTime();
55
+
56
+                    double oldDistance = distances[arc.getDestination().getId()];
57
+                    double newDistance = distances[node.getId()] + w;
58
+
59
+                    if (Double.isInfinite(oldDistance) && Double.isFinite(newDistance)) {
60
+                        notifyNodeReached(arc.getDestination());
61
+                    }
62
+
63
+                    // Check if new distances would be better, if so update...
64
+                    if (newDistance < oldDistance) {
65
+                        found = false;
66
+                        distances[arc.getDestination().getId()] = distances[node.getId()] + w;
67
+                        predecessorArcs[arc.getDestination().getId()] = arc;
68
+                    }
69
+                }
70
+            }
71
+        }
72
+
73
+        ShortestPathSolution solution = null;
74
+
75
+        // Destination has no predecessor, the solution is infeasible...
76
+        if (predecessorArcs[data.getDestination().getId()] == null) {
77
+            solution = new ShortestPathSolution(data, Status.INFEASIBLE);
78
+        }
79
+        else {
80
+
81
+            // The destination has been found, notify the observers.
82
+            notifyDestinationReached(data.getDestination());
83
+
84
+            // Create the path from the array of predecessors...
85
+            ArrayList<Arc> arcs = new ArrayList<>();
86
+            Arc arc = predecessorArcs[data.getDestination().getId()];
87
+            while (arc != null) {
88
+                arcs.add(arc);
89
+                arc = predecessorArcs[arc.getOrigin().getId()];
90
+            }
91
+
92
+            // Reverse the path...
93
+            Collections.reverse(arcs);
94
+
95
+            // Create the final solution.
96
+            solution = new ShortestPathSolution(data, Status.OPTIMAL, new Path(graph, arcs));
97
+        }
98
+
99
+        return solution;
100
+    }
101
+
102
+}

+ 17
- 0
src/main/org/insa/algo/shortestpath/DijkstraAlgorithm.java View File

@@ -0,0 +1,17 @@
1
+package org.insa.algo.shortestpath;
2
+
3
+public class DijkstraAlgorithm extends ShortestPathAlgorithm {
4
+
5
+    public DijkstraAlgorithm(ShortestPathData data) {
6
+        super(data);
7
+    }
8
+
9
+    @Override
10
+    protected ShortestPathSolution doRun() {
11
+        ShortestPathData data = getInputData();
12
+        ShortestPathSolution solution = null;
13
+        // TODO:
14
+        return solution;
15
+    }
16
+
17
+}

+ 69
- 0
src/main/org/insa/algo/shortestpath/ShortestPathAlgorithm.java View File

@@ -0,0 +1,69 @@
1
+package org.insa.algo.shortestpath;
2
+
3
+import org.insa.algo.AbstractAlgorithm;
4
+import org.insa.graph.Node;
5
+
6
+public abstract class ShortestPathAlgorithm extends AbstractAlgorithm<ShortestPathObserver> {
7
+
8
+    protected ShortestPathAlgorithm(ShortestPathData data) {
9
+        super(data);
10
+    }
11
+
12
+    @Override
13
+    public ShortestPathSolution run() {
14
+        return (ShortestPathSolution) super.run();
15
+    }
16
+
17
+    @Override
18
+    protected abstract ShortestPathSolution doRun();
19
+
20
+    @Override
21
+    public ShortestPathData getInputData() {
22
+        return (ShortestPathData) super.getInputData();
23
+    }
24
+
25
+    /**
26
+     * Notify all observers that the origin has been processed.
27
+     * 
28
+     * @param node Origin.
29
+     */
30
+    public void notifyOriginProcessed(Node node) {
31
+        for (ShortestPathObserver obs: getObservers()) {
32
+            obs.notifyOriginProcessed(node);
33
+        }
34
+    }
35
+
36
+    /**
37
+     * Notify all observers that a node has been reached for the first time.
38
+     * 
39
+     * @param node Node that has been reached.
40
+     */
41
+    public void notifyNodeReached(Node node) {
42
+        for (ShortestPathObserver obs: getObservers()) {
43
+            obs.notifyNodeReached(node);
44
+        }
45
+    }
46
+
47
+    /**
48
+     * Notify all observers that a node has been marked, i.e. its final value has
49
+     * been set.
50
+     * 
51
+     * @param node Node that has been marked.
52
+     */
53
+    public void notifyNodeMarked(Node node) {
54
+        for (ShortestPathObserver obs: getObservers()) {
55
+            obs.notifyNodeMarked(node);
56
+        }
57
+    }
58
+
59
+    /**
60
+     * Notify all observers that the destination has been reached.
61
+     * 
62
+     * @param node Destination.
63
+     */
64
+    public void notifyDestinationReached(Node node) {
65
+        for (ShortestPathObserver obs: getObservers()) {
66
+            obs.notifyDestinationReached(node);
67
+        }
68
+    }
69
+}

+ 63
- 0
src/main/org/insa/algo/shortestpath/ShortestPathData.java View File

@@ -0,0 +1,63 @@
1
+package org.insa.algo.shortestpath;
2
+
3
+import org.insa.algo.AbstractInputData;
4
+import org.insa.graph.Graph;
5
+import org.insa.graph.Node;
6
+
7
+public class ShortestPathData extends AbstractInputData {
8
+
9
+    // Origin and destination nodes.
10
+    private final Node origin, destination;
11
+
12
+    /**
13
+     * Construct a new instance of ShortestPathData with the given parameters and
14
+     * for which all arcs are allowed.
15
+     * 
16
+     * @param graph Graph in which the path should be looked for.
17
+     * @param origin Origin node of the path.
18
+     * @param destination Destination node of the path.
19
+     * @param mode Cost mode for the path.
20
+     */
21
+    public ShortestPathData(Graph graph, Node origin, Node destination, Mode mode) {
22
+        super(graph, mode);
23
+        this.origin = origin;
24
+        this.destination = destination;
25
+    }
26
+
27
+    /**
28
+     * Construct a new instance of ShortestPathInputData with the given parameters.
29
+     * 
30
+     * @param graph Graph in which the path should be looked for.
31
+     * @param origin Origin node of the path.
32
+     * @param destination Destination node of the path.
33
+     * @param mode Cost mode for the path.
34
+     * @param arcFilter Filter for arcs (used to allow only a specific set of arcs
35
+     *        in the graph to be used).
36
+     */
37
+    public ShortestPathData(Graph graph, Node origin, Node destination, Mode mode,
38
+            AbstractInputData.ArcFilter arcFilter) {
39
+        super(graph, mode, arcFilter);
40
+        this.origin = origin;
41
+        this.destination = destination;
42
+    }
43
+
44
+    /**
45
+     * @return Origin node for the path.
46
+     */
47
+    public Node getOrigin() {
48
+        return origin;
49
+    }
50
+
51
+    /**
52
+     * @return Destination node for the path.
53
+     */
54
+    public Node getDestination() {
55
+        return destination;
56
+    }
57
+
58
+    @Override
59
+    public String toString() {
60
+        return "Shortest-path from #" + origin.getId() + " to #" + destination.getId() + " ["
61
+                + getMode().toString().toLowerCase() + "]";
62
+    }
63
+}

+ 41
- 0
src/main/org/insa/algo/shortestpath/ShortestPathGraphicObserver.java View File

@@ -0,0 +1,41 @@
1
+package org.insa.algo.shortestpath;
2
+
3
+import java.awt.Color;
4
+
5
+import org.insa.graph.Node;
6
+import org.insa.graphics.drawing.Drawing;
7
+import org.insa.graphics.drawing.overlays.PointSetOverlay;
8
+
9
+public class ShortestPathGraphicObserver implements ShortestPathObserver {
10
+
11
+    // Drawing and Graph drawing
12
+    protected Drawing drawing;
13
+    protected PointSetOverlay psOverlay1, psOverlay2;
14
+
15
+    public ShortestPathGraphicObserver(Drawing drawing) {
16
+        this.drawing = drawing;
17
+        psOverlay1 = drawing.createPointSetOverlay(1, Color.CYAN);
18
+        psOverlay2 = drawing.createPointSetOverlay(1, Color.BLUE);
19
+    }
20
+
21
+    @Override
22
+    public void notifyOriginProcessed(Node node) {
23
+        // drawing.drawMarker(node.getPoint(), Color.RED);
24
+    }
25
+
26
+    @Override
27
+    public void notifyNodeReached(Node node) {
28
+        psOverlay1.addPoint(node.getPoint());
29
+    }
30
+
31
+    @Override
32
+    public void notifyNodeMarked(Node node) {
33
+        psOverlay2.addPoint(node.getPoint());
34
+    }
35
+
36
+    @Override
37
+    public void notifyDestinationReached(Node node) {
38
+        // drawing.drawMarker(node.getPoint(), Color.RED);
39
+    }
40
+
41
+}

+ 37
- 0
src/main/org/insa/algo/shortestpath/ShortestPathObserver.java View File

@@ -0,0 +1,37 @@
1
+package org.insa.algo.shortestpath;
2
+
3
+import org.insa.graph.Node;
4
+
5
+public interface ShortestPathObserver {
6
+	
7
+	/**
8
+	 * Notify the observer that the origin has been processed.
9
+	 * 
10
+	 * @param node Origin.
11
+	 */
12
+	public void notifyOriginProcessed(Node node);
13
+	
14
+	/**
15
+	 * Notify the observer that a node has been reached for the first
16
+	 * time.
17
+	 * 
18
+	 * @param node Node that has been reached.
19
+	 */
20
+	public void notifyNodeReached(Node node);
21
+	
22
+	/**
23
+	 * Notify the observer that a node has been marked, i.e. its final
24
+	 * value has been set.
25
+	 * 
26
+	 * @param node Node that has been marked.
27
+	 */
28
+	public void notifyNodeMarked(Node node);
29
+
30
+	/**
31
+	 * Notify the observer that the destination has been reached.
32
+	 * 
33
+	 * @param node Destination.
34
+	 */
35
+	public void notifyDestinationReached(Node node);
36
+	
37
+}

+ 76
- 0
src/main/org/insa/algo/shortestpath/ShortestPathSolution.java View File

@@ -0,0 +1,76 @@
1
+package org.insa.algo.shortestpath;
2
+
3
+import org.insa.algo.AbstractInputData;
4
+import org.insa.algo.AbstractSolution;
5
+import org.insa.graph.Path;
6
+
7
+public class ShortestPathSolution extends AbstractSolution {
8
+
9
+    // Optimal solution.
10
+    private Path path;
11
+
12
+    /**
13
+     * {@inheritDoc}
14
+     */
15
+    public ShortestPathSolution(ShortestPathData data) {
16
+        super(data);
17
+    }
18
+
19
+    /**
20
+     * Create a new infeasible shortest-path solution for the given input and
21
+     * status.
22
+     * 
23
+     * @param data Original input data for this solution.
24
+     * @param status Status of the solution (UNKNOWN / INFEASIBLE).
25
+     */
26
+    public ShortestPathSolution(ShortestPathData data, Status status) {
27
+        super(data, status);
28
+    }
29
+
30
+    /**
31
+     * Create a new shortest-path solution.
32
+     * 
33
+     * @param data Original input data for this solution.
34
+     * @param status Status of the solution (FEASIBLE / OPTIMAL).
35
+     * @param path Path corresponding to the solution.
36
+     */
37
+    public ShortestPathSolution(ShortestPathData data, Status status, Path path) {
38
+        super(data, status);
39
+        this.path = path;
40
+    }
41
+
42
+    @Override
43
+    public ShortestPathData getInputData() {
44
+        return (ShortestPathData) super.getInputData();
45
+    }
46
+
47
+    /**
48
+     * @return The path of this solution, if any.
49
+     */
50
+    public Path getPath() {
51
+        return path;
52
+    }
53
+
54
+    @Override
55
+    public String toString() {
56
+        String info = null;
57
+        if (!isFeasible()) {
58
+            info = String.format("No path found from node #%d to node #%d",
59
+                    getInputData().getOrigin().getId(), getInputData().getDestination().getId());
60
+        }
61
+        else {
62
+            info = String.format("Found a path from node #%d to node #%d",
63
+                    getInputData().getOrigin().getId(), getInputData().getDestination().getId());
64
+            if (getInputData().getMode() == AbstractInputData.Mode.LENGTH) {
65
+                info = String.format("%s, %.4f kilometers", info, (getPath().getLength() / 1000.0));
66
+            }
67
+            else {
68
+                info = String.format("%s, %.4f minutes", info,
69
+                        (getPath().getMinimumTravelTime() / 60.0));
70
+            }
71
+        }
72
+        info += " in " + getSolvingTime().getSeconds() + " seconds.";
73
+        return info;
74
+    }
75
+
76
+}

+ 37
- 0
src/main/org/insa/algo/shortestpath/ShortestPathTextObserver.java View File

@@ -0,0 +1,37 @@
1
+package org.insa.algo.shortestpath;
2
+
3
+import java.io.PrintStream;
4
+
5
+import org.insa.graph.Node;
6
+
7
+public class ShortestPathTextObserver implements ShortestPathObserver {
8
+
9
+    private final PrintStream stream;
10
+
11
+    public ShortestPathTextObserver(PrintStream stream) {
12
+        this.stream = stream;
13
+    }
14
+
15
+    @Override
16
+    public void notifyOriginProcessed(Node node) {
17
+        // TODO Auto-generated method stub
18
+
19
+    }
20
+
21
+    @Override
22
+    public void notifyNodeReached(Node node) {
23
+        stream.println("Node " + node.getId() + " reached.");
24
+    }
25
+
26
+    @Override
27
+    public void notifyNodeMarked(Node node) {
28
+        stream.println("Node " + node.getId() + " marked.");
29
+    }
30
+
31
+    @Override
32
+    public void notifyDestinationReached(Node node) {
33
+        // TODO Auto-generated method stub
34
+
35
+    }
36
+
37
+}

+ 224
- 0
src/main/org/insa/graph/Path.java View File

@@ -0,0 +1,224 @@
1
+package org.insa.graph;
2
+
3
+import java.util.ArrayList;
4
+import java.util.Collections;
5
+import java.util.List;
6
+
7
+/**
8
+ * Class representing a path between nodes in a graph.
9
+ * 
10
+ * A path is represented as a list of {@link Arc} and not a list of {@link Node}
11
+ * due to the multigraph nature of the considered graphs.
12
+ *
13
+ */
14
+public class Path {
15
+
16
+    /**
17
+     * Create a new path that goes through the given list of nodes (in order),
18
+     * choosing the fastest route if multiple are available.
19
+     * 
20
+     * @param graph Graph containing the nodes in the list.
21
+     * @param nodes List of nodes to build the path.
22
+     * 
23
+     * @return A path that goes through the given list of nodes.
24
+     * 
25
+     * @throws IllegalArgumentException If the list of nodes is not valid, i.e. two
26
+     *         consecutive nodes in the list are not connected in the graph.
27
+     * 
28
+     * @deprecated Need to be implement.
29
+     */
30
+    public static Path createFastestPathFromNodes(Graph graph, List<Node> nodes)
31
+            throws IllegalArgumentException {
32
+        List<Arc> arcs = new ArrayList<Arc>();
33
+        // TODO:
34
+        return new Path(graph, arcs);
35
+    }
36
+
37
+    /**
38
+     * Create a new path that goes through the given list of nodes (in order),
39
+     * choosing the shortest route if multiple are available.
40
+     * 
41
+     * @param graph Graph containing the nodes in the list.
42
+     * @param nodes List of nodes to build the path.
43
+     * 
44
+     * @return A path that goes through the given list of nodes.
45
+     * 
46
+     * @throws IllegalArgumentException If the list of nodes is not valid, i.e. two
47
+     *         consecutive nodes in the list are not connected in the graph.
48
+     * 
49
+     * @deprecated Need to be implement.
50
+     */
51
+    public static Path createShortestPathFromNodes(Graph graph, List<Node> nodes)
52
+            throws IllegalArgumentException {
53
+        List<Arc> arcs = new ArrayList<Arc>();
54
+        // TODO:
55
+        return new Path(graph, arcs);
56
+    }
57
+
58
+    /**
59
+     * Concatenate the given paths.
60
+     * 
61
+     * @param paths Array of paths to concatenate.
62
+     * 
63
+     * @return Concatenated path.
64
+     * 
65
+     * @throws IllegalArgumentException if the paths cannot be concatenated (IDs of
66
+     *         map do not match, or the end of a path is not the beginning of the
67
+     *         next).
68
+     */
69
+    public static Path concatenate(Path... paths) throws IllegalArgumentException {
70
+        if (paths.length == 0) {
71
+            throw new IllegalArgumentException("Cannot concatenate an empty list of paths.");
72
+        }
73
+        final String mapId = paths[0].getGraph().getMapId();
74
+        for (int i = 1; i < paths.length; ++i) {
75
+            if (!paths[i].getGraph().getMapId().equals(mapId)) {
76
+                throw new IllegalArgumentException(
77
+                        "Cannot concatenate paths from different graphs.");
78
+            }
79
+        }
80
+        ArrayList<Arc> arcs = new ArrayList<>();
81
+        for (Path path: paths) {
82
+            arcs.addAll(path.getArcs());
83
+        }
84
+        Path path = new Path(paths[0].getGraph(), arcs);
85
+        if (!path.isValid()) {
86
+            throw new IllegalArgumentException(
87
+                    "Cannot concatenate paths that do not form a single path.");
88
+        }
89
+        return path;
90
+    }
91
+
92
+    // Graph containing this path.
93
+    private final Graph graph;
94
+
95
+    // Origin of the path
96
+    private final Node origin;
97
+
98
+    // List of arcs in this path.
99
+    private final List<Arc> arcs;
100
+
101
+    /**
102
+     * Create an empty path corresponding to the given graph.
103
+     * 
104
+     * @param graph Graph containing the path.
105
+     */
106
+    public Path(Graph graph) {
107
+        this.graph = graph;
108
+        this.origin = null;
109
+        this.arcs = new ArrayList<>();
110
+    }
111
+
112
+    /**
113
+     * Create a new path containing a single node.
114
+     * 
115
+     * @param graph Graph containing the path.
116
+     * @param node Single node of the path.
117
+     */
118
+    public Path(Graph graph, Node node) {
119
+        this.graph = graph;
120
+        this.origin = node;
121
+        this.arcs = new ArrayList<>();
122
+    }
123
+
124
+    /**
125
+     * Create a new path with the given list of arcs.
126
+     * 
127
+     * @param graph Graph containing the path.
128
+     * @param arcs Arcs to construct the path.
129
+     */
130
+    public Path(Graph graph, List<Arc> arcs) {
131
+        this.graph = graph;
132
+        this.arcs = arcs;
133
+        this.origin = arcs.size() > 0 ? arcs.get(0).getOrigin() : null;
134
+    }
135
+
136
+    /**
137
+     * @return Graph containing the path.
138
+     */
139
+    public Graph getGraph() {
140
+        return graph;
141
+    }
142
+
143
+    /**
144
+     * @return First node of the path.
145
+     */
146
+    public Node getOrigin() {
147
+        return origin;
148
+    }
149
+
150
+    /**
151
+     * @return Last node of the path.
152
+     */
153
+    public Node getDestination() {
154
+        return arcs.get(arcs.size() - 1).getDestination();
155
+    }
156
+
157
+    /**
158
+     * @return List of arcs in the path.
159
+     */
160
+    public List<Arc> getArcs() {
161
+        return Collections.unmodifiableList(arcs);
162
+    }
163
+
164
+    /**
165
+     * Check if this path is empty (it does not contain any node).
166
+     * 
167
+     * @return true if this path is empty, false otherwise.
168
+     */
169
+    public boolean isEmpty() {
170
+        return arcs.isEmpty();
171
+    }
172
+
173
+    /**
174
+     * Check if this path is valid.
175
+     * 
176
+     * A path is valid if it is empty, contains a single node (without arcs) or if
177
+     * the first arc has for origin the origin of the path and, for two consecutive
178
+     * arcs, the destination of the first one is the origin of the second one.
179
+     * 
180
+     * @return true if the path is valid, false otherwise.
181
+     * 
182
+     * @deprecated Need to be implement.
183
+     */
184
+    public boolean isValid() {
185
+        // TODO:
186
+        return false;
187
+    }
188
+
189
+    /**
190
+     * @return Total length of the path.
191
+     * 
192
+     * @deprecated Need to be implement.
193
+     */
194
+    public float getLength() {
195
+        // TODO:
196
+        return 0;
197
+    }
198
+
199
+    /**
200
+     * Compute the time required to travel this path if moving at the given speed.
201
+     * 
202
+     * @param speed Speed to compute the travel time.
203
+     * 
204
+     * @return Time (in seconds) required to travel this path at the given speed (in
205
+     *         kilometers-per-hour).
206
+     * 
207
+     * @deprecated Need to be implement.
208
+     */
209
+    public double getTravelTime(double speed) {
210
+        // TODO:
211
+        return 0;
212
+    }
213
+
214
+    /**
215
+     * @return Minimum travel time of the in seconds (assuming maximum speed).
216
+     * 
217
+     * @deprecated Need to be implement.
218
+     */
219
+    public double getMinimumTravelTime() {
220
+        // TODO:
221
+        return 0;
222
+    }
223
+
224
+}

Loading…
Cancel
Save