Browse Source

A* working and tested

Yohan Simard 3 years ago
parent
commit
ba2f4fdf3d

+ 49
- 0
be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/AStarAlgorithm.java View File

@@ -1,9 +1,58 @@
1 1
 package org.insa.graphs.algorithm.shortestpath;
2 2
 
3
+import org.insa.graphs.algorithm.AbstractInputData;
4
+import org.insa.graphs.model.*;
5
+
6
+import java.util.ArrayList;
7
+import java.util.List;
8
+
9
+import static org.insa.graphs.model.GraphStatistics.NO_MAXIMUM_SPEED;
10
+
3 11
 public class AStarAlgorithm extends DijkstraAlgorithm {
4 12
 
5 13
     public AStarAlgorithm(ShortestPathData data) {
6 14
         super(data);
7 15
     }
8 16
 
17
+
18
+    /**
19
+     * Generates a list of labelStar associated with a graph
20
+     *
21
+     * @param data the data to use to construct the labels
22
+     * @return A list of labels in the same order as data.getGraph().getNodes()
23
+     */
24
+    @Override
25
+    protected List<Label> generateLabels(ShortestPathData data) {
26
+        List<Node> nodes = data.getGraph().getNodes();
27
+        List<Label> labels = new ArrayList<>();
28
+        int maxSpeed = getMaxSpeed(data);
29
+        for (Node node : nodes) {
30
+            double estimatedCost;
31
+            // if the cost is the distance, take straight line distance as heuristic
32
+            if (data.getMode() == AbstractInputData.Mode.LENGTH) {
33
+                estimatedCost = Point.distance(node.getPoint(), data.getDestination().getPoint());
34
+
35
+            } else {    // if the cost is the time, multiply straight line distance with the maximum speed
36
+                estimatedCost = Point.distance(node.getPoint(), data.getDestination().getPoint()) / maxSpeed;
37
+            }
38
+            labels.add(new LabelStar(node, estimatedCost));
39
+        }
40
+        return labels;
41
+    }
42
+
43
+    /**
44
+     * @return the maximum speed of this input data in m/s
45
+     */
46
+    private int getMaxSpeed(ShortestPathData data) {
47
+        int dataMaxSpeed = data.getMaximumSpeed();
48
+        int graphMaxSpeed = data.getGraph().getGraphInformation().getMaximumSpeed();
49
+        if (dataMaxSpeed == NO_MAXIMUM_SPEED && graphMaxSpeed == NO_MAXIMUM_SPEED)
50
+            return 1000;
51
+        if (dataMaxSpeed != NO_MAXIMUM_SPEED && graphMaxSpeed != NO_MAXIMUM_SPEED)
52
+            return (int) (Math.min(dataMaxSpeed, graphMaxSpeed)/3.6);
53
+        if (dataMaxSpeed != NO_MAXIMUM_SPEED)
54
+            return (int) (dataMaxSpeed/3.6);
55
+        return (int) (graphMaxSpeed/3.6);
56
+
57
+    }
9 58
 }

+ 25
- 12
be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/DijkstraAlgorithm.java View File

@@ -14,42 +14,56 @@ import java.util.Collections;
14 14
 import java.util.List;
15 15
 
16 16
 public class DijkstraAlgorithm extends ShortestPathAlgorithm {
17
+    protected List<Label> labels;
17 18
 
18 19
     public DijkstraAlgorithm(ShortestPathData data) {
19 20
         super(data);
21
+        // Generate the labels associated with all the nodes of the graph
22
+        labels = generateLabels(data);
23
+    }
24
+
25
+    /**
26
+     * Generates a list of labels associated with a graph
27
+     *
28
+     * @param data the data to use to construct the labels
29
+     * @return A list of labels in the same order as data.getGraph().getNodes()
30
+     */
31
+    protected List<Label> generateLabels(ShortestPathData data) {
32
+        List<Node> nodes = data.getGraph().getNodes();
33
+        List<Label> labels = new ArrayList<>();
34
+        for (Node node : nodes) {
35
+            labels.add(new Label(node));
36
+        }
37
+        return labels;
38
+
20 39
     }
21 40
 
22 41
     @Override
23 42
     protected ShortestPathSolution doRun() {
24 43
         // Retreive the graph
25 44
         final ShortestPathData data = getInputData();
26
-        Graph graph = data.getGraph();
27
-
28
-        final int nbNodes = graph.size();
29 45
 
30 46
         // Construct a binary heap for Label (comparison is based on their cost)
31 47
         PriorityQueue<Label> heap = new BinaryHeap<>();
32 48
 
33
-        // Generate the labels associated with all the nodes of the graph
34
-        List<Label> labels = Label.generateLabels(graph);
35
-
36
-
37 49
         // Initialize labels and heap with the origin node, then notify observers
38 50
         Node origin = data.getOrigin();
39 51
         int originId = origin.getId();
40 52
         labels.get(originId).mark();
41 53
         labels.get(originId).updateCost(0, null);
42 54
         heap.insert(labels.get(originId));
43
-        notifyOriginProcessed(data.getOrigin());
55
+        notifyOriginProcessed(origin);
44 56
 
45 57
 //        int iterationCounter = 0;
58
+        Node destination = data.getDestination();
59
+        Node currentNode = null;
46 60
 
47
-        while (!heap.isEmpty()) {
61
+        while (!heap.isEmpty() && (currentNode == null || !currentNode.equals(destination))) {
48 62
 //            iterationCounter++;
49 63
             // Get the node with the minimum cost
50 64
             Label currentLabel = heap.deleteMin();
51 65
             currentLabel.mark();
52
-            Node currentNode = currentLabel.getNode();
66
+            currentNode = currentLabel.getNode();
53 67
 
54 68
 //            System.out.printf("Label marked : cost = %f; %d succesors; heap valid = %b \n",
55 69
 //                    currentLabel.getCost(),
@@ -79,7 +93,6 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
79 93
             }
80 94
         }
81 95
 
82
-        Node destination = data.getDestination();
83 96
         Label destinationLabel = labels.get(destination.getId());
84 97
 
85 98
         // If path not found
@@ -102,7 +115,7 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
102 115
 
103 116
         Collections.reverse(path);
104 117
 
105
-        return new ShortestPathSolution(data, AbstractSolution.Status.OPTIMAL, new Path(graph, path));
118
+        return new ShortestPathSolution(data, AbstractSolution.Status.OPTIMAL, new Path(data.getGraph(), path));
106 119
     }
107 120
 
108 121
 }

+ 10
- 17
be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/Label.java View File

@@ -8,7 +8,7 @@ import java.util.ArrayList;
8 8
 import java.util.List;
9 9
 
10 10
 public class Label implements Comparable<Label> {
11
-    private Node node;
11
+    private final Node node;
12 12
     private boolean marked;
13 13
     private double cost;
14 14
     private Arc parent;
@@ -26,21 +26,6 @@ public class Label implements Comparable<Label> {
26 26
     }
27 27
 
28 28
     /**
29
-     * Generates a list of labels associated with a graph
30
-     *
31
-     * @param graph the graph used to construct the labels
32
-     * @return A list of labels in the same order as graph.getNodes()
33
-     */
34
-    public static List<Label> generateLabels(Graph graph) {
35
-        List<Node> nodes = graph.getNodes();
36
-        List<Label> labels = new ArrayList<>();
37
-        for (Node node : nodes) {
38
-            labels.add(new Label(node));
39
-        }
40
-        return labels;
41
-    }
42
-
43
-    /**
44 29
      * Marks a Label
45 30
      */
46 31
     public void mark() {
@@ -70,12 +55,20 @@ public class Label implements Comparable<Label> {
70 55
         return cost;
71 56
     }
72 57
 
58
+    public double getTotalCost() {
59
+        return cost;
60
+    }
61
+
73 62
     public Arc getParent() {
74 63
         return parent;
75 64
     }
76 65
 
77 66
     @Override
78 67
     public int compareTo(Label o) {
79
-        return Double.compare(cost, o.cost);
68
+        int comp = Double.compare(getTotalCost(), o.getTotalCost());
69
+        if (comp == 0 && this.getClass() == LabelStar.class && o.getClass() == LabelStar.class)
70
+            return Double.compare(((LabelStar)this).getEstimatedCost(), ((LabelStar)o).getEstimatedCost());
71
+        else
72
+            return comp;
80 73
     }
81 74
 }

+ 28
- 0
be-graphes-algos/src/main/java/org/insa/graphs/algorithm/shortestpath/LabelStar.java View File

@@ -0,0 +1,28 @@
1
+package org.insa.graphs.algorithm.shortestpath;
2
+
3
+import org.insa.graphs.model.Node;
4
+import org.insa.graphs.model.Point;
5
+
6
+public class LabelStar extends Label {
7
+
8
+    private final double estimatedCost;
9
+
10
+    /**
11
+     * Initalizes a LabelStar (not yet marked, with infinite cost)
12
+     *
13
+     * @param node The node associated with the label
14
+     */
15
+    public LabelStar(Node node, double estimatedCost) {
16
+        super(node);
17
+        this.estimatedCost = estimatedCost;
18
+    }
19
+
20
+    @Override
21
+    public double getTotalCost() {
22
+        return super.getCost() + getEstimatedCost();
23
+    }
24
+
25
+    public double getEstimatedCost() {
26
+        return estimatedCost;
27
+    }
28
+}

+ 11
- 0
be-graphes-algos/src/test/java/org/insa/graphs/algorithm/shortestpath/AStarAlgorithmTest.java View File

@@ -0,0 +1,11 @@
1
+package org.insa.graphs.algorithm.shortestpath;
2
+
3
+import junit.framework.TestCase;
4
+
5
+public class AStarAlgorithmTest extends ShortestPathTest {
6
+    @Override
7
+    protected ShortestPathSolution runShortestPathAlgo(ShortestPathData data) {
8
+        return new AStarAlgorithm(data).doRun();
9
+    }
10
+
11
+}

+ 4
- 85
be-graphes-algos/src/test/java/org/insa/graphs/algorithm/shortestpath/DijkstraAlgorithmTest.java View File

@@ -1,89 +1,8 @@
1 1
 package org.insa.graphs.algorithm.shortestpath;
2 2
 
3
-import org.insa.graphs.algorithm.ArcInspector;
4
-import org.insa.graphs.algorithm.ArcInspectorFactory;
5
-import org.insa.graphs.model.*;
6
-import org.insa.graphs.model.io.BinaryGraphReader;
7
-import org.insa.graphs.model.io.GraphReader;
8
-import org.junit.Test;
9
-
10
-import java.io.*;
11
-import java.util.List;
12
-import java.util.Random;
13
-
14
-import static org.junit.Assert.*;
15
-
16
-
17
-public class DijkstraAlgorithmTest {
18
-
19
-    String[] maps = {
20
-            "/home/yohan/Documents/etudes/be-graphes/maps/carre.mapgr",
21
-            "/home/yohan/Documents/etudes/be-graphes/maps/insa.mapgr",
22
-            "/home/yohan/Documents/etudes/be-graphes/maps/toulouse.mapgr",
23
-            "/home/yohan/Documents/etudes/be-graphes/maps/guadeloupe.mapgr",
24
-    };
25
-
26
-    int[] origIndexes = {
27
-            22,
28
-            553,
29
-            25643,
30
-            6187,
31
-    };
32
-    int[] destIndexes = {
33
-            15,
34
-            111,
35
-            17402,
36
-            15025,
37
-    };
38
-
39
-    ArcInspector[] arcInspectors = {
40
-            ArcInspectorFactory.getAllFilters().get(0),
41
-            ArcInspectorFactory.getAllFilters().get(2),
42
-    };
43
-
44
-    private ShortestPathSolution runDijkstra(String map, ArcInspector arcInspector, int origIndex, int destIndex) throws IOException {
45
-        try (GraphReader reader = new BinaryGraphReader(new DataInputStream(new BufferedInputStream(new FileInputStream(map))))) {
46
-            Graph graph = reader.read();
47
-            List<Node> nodes = graph.getNodes();
48
-            Node orig = nodes.get(origIndex);
49
-            Node dest = nodes.get(destIndex);
50
-            ShortestPathData data = new ShortestPathData(graph, orig, dest, arcInspector);
51
-            return new DijkstraAlgorithm(data).doRun();
52
-        }
53
-    }
54
-
55
-    @Test
56
-    public void testDoRun() throws IOException {
57
-        // test feasible paths
58
-        for (int i = 0; i < 3; i++) {
59
-            for (ArcInspector arcInspector : arcInspectors) {
60
-                ShortestPathSolution sol = runDijkstra(maps[i], arcInspector, origIndexes[i], destIndexes[i]);
61
-                assertTrue(sol.isFeasible());
62
-                Path path = sol.getPath();
63
-                assertTrue(path.isValid());
64
-                if (i == 0)
65
-                    assertEquals(path, Path.createShortestPathFromNodes(sol.getInputData().getGraph(), path.getNodes()));
66
-                if (i == 1)
67
-                    assertEquals(path, Path.createFastestPathFromNodes(sol.getInputData().getGraph(), path.getNodes()));
68
-            }
69
-        }
70
-
71
-        // test 0-length paths
72
-        for (int i = 0; i < 3; i++) {
73
-            for (ArcInspector arcInspector : arcInspectors) {
74
-                ShortestPathSolution sol = runDijkstra(maps[i], arcInspector, origIndexes[i], origIndexes[i]);
75
-                assertTrue(sol.isFeasible());
76
-                assertTrue(sol.getPath().isValid());
77
-                assertEquals(sol.getPath().getLength(), 0, 1e-5);
78
-            }
79
-        }
80
-
81
-        // test impossible path
82
-        for (ArcInspector arcInspector : arcInspectors) {
83
-            ShortestPathSolution sol = runDijkstra(maps[3], arcInspector, origIndexes[3], destIndexes[3]);
84
-            assertFalse(sol.isFeasible());
85
-        }
86
-
87
-
3
+public class DijkstraAlgorithmTest extends ShortestPathTest {
4
+    @Override
5
+    protected ShortestPathSolution runShortestPathAlgo(ShortestPathData data) {
6
+        return new DijkstraAlgorithm(data).doRun();
88 7
     }
89 8
 }

+ 98
- 0
be-graphes-algos/src/test/java/org/insa/graphs/algorithm/shortestpath/ShortestPathTest.java View File

@@ -0,0 +1,98 @@
1
+package org.insa.graphs.algorithm.shortestpath;
2
+
3
+import org.insa.graphs.algorithm.ArcInspector;
4
+import org.insa.graphs.algorithm.ArcInspectorFactory;
5
+import org.insa.graphs.model.Graph;
6
+import org.insa.graphs.model.Node;
7
+import org.insa.graphs.model.Path;
8
+import org.insa.graphs.model.io.BinaryGraphReader;
9
+import org.insa.graphs.model.io.GraphReader;
10
+import org.junit.Test;
11
+
12
+import java.io.BufferedInputStream;
13
+import java.io.DataInputStream;
14
+import java.io.FileInputStream;
15
+import java.io.IOException;
16
+import java.util.List;
17
+
18
+import static org.junit.Assert.*;
19
+
20
+public abstract class ShortestPathTest {
21
+    String[] maps = {
22
+            "/home/yohan/Documents/etudes/be-graphes/maps/carre.mapgr",
23
+            "/home/yohan/Documents/etudes/be-graphes/maps/insa.mapgr",
24
+            "/home/yohan/Documents/etudes/be-graphes/maps/toulouse.mapgr",
25
+            "/home/yohan/Documents/etudes/be-graphes/maps/guadeloupe.mapgr",
26
+    };
27
+
28
+    int[] origIndexes = {
29
+            22,
30
+            553,
31
+            25643,
32
+            6187,
33
+    };
34
+    int[] destIndexes = {
35
+            15,
36
+            111,
37
+            17402,
38
+            15025,
39
+    };
40
+
41
+    ArcInspector[] arcInspectors = {
42
+            ArcInspectorFactory.getAllFilters().get(0),
43
+            ArcInspectorFactory.getAllFilters().get(2),
44
+    };
45
+
46
+    private ShortestPathData createData(String map, ArcInspector arcInspector, int origIndex, int destIndex) throws IOException {
47
+        try (GraphReader reader = new BinaryGraphReader(new DataInputStream(new BufferedInputStream(new FileInputStream(map))))) {
48
+            Graph graph = reader.read();
49
+            List<Node> nodes = graph.getNodes();
50
+            Node orig = nodes.get(origIndex);
51
+            Node dest = nodes.get(destIndex);
52
+            return new ShortestPathData(graph, orig, dest, arcInspector);
53
+        }
54
+    }
55
+
56
+    protected abstract ShortestPathSolution runShortestPathAlgo(ShortestPathData data);
57
+
58
+    @Test
59
+    public void testDoRun() throws IOException {
60
+        // test feasible paths
61
+        for (int i = 0; i < 3; i++) {
62
+            for (ArcInspector arcInspector : arcInspectors) {
63
+                ShortestPathData data = createData(maps[i], arcInspector, origIndexes[i], destIndexes[i]);
64
+                ShortestPathSolution sol = runShortestPathAlgo(data);
65
+                ShortestPathSolution oracle = new BellmanFordAlgorithm(data).doRun();
66
+                assertTrue(sol.isFeasible());
67
+                Path path = sol.getPath();
68
+                assertTrue(path.isValid());
69
+                // check the optimality locally
70
+                if (i == 0)
71
+                    assertEquals(path, Path.createShortestPathFromNodes(data.getGraph(), path.getNodes()));
72
+                if (i == 1)
73
+                    assertEquals(path, Path.createFastestPathFromNodes(data.getGraph(), path.getNodes()));
74
+                // Check result against Bellman Ford algorithm (except for the square map or there may be several paths with the same cost)
75
+                if (i != 0)
76
+                    assertEquals(sol.getPath(), oracle.getPath());
77
+            }
78
+        }
79
+
80
+        // test 0-length paths
81
+        for (int i = 0; i < 3; i++) {
82
+            for (ArcInspector arcInspector : arcInspectors) {
83
+                ShortestPathData data = createData(maps[i], arcInspector, origIndexes[i], origIndexes[i]);
84
+                ShortestPathSolution sol = runShortestPathAlgo(data);
85
+                assertTrue(sol.isFeasible());
86
+                assertTrue(sol.getPath().isValid());
87
+                assertEquals(sol.getPath().getLength(), 0, 1e-5);
88
+            }
89
+        }
90
+
91
+        // test impossible path
92
+        for (ArcInspector arcInspector : arcInspectors) {
93
+            ShortestPathData data = createData(maps[3], arcInspector, origIndexes[3], destIndexes[3]);
94
+            ShortestPathSolution sol = runShortestPathAlgo(data);
95
+            assertFalse(sol.isFeasible());
96
+        }
97
+    }
98
+}

+ 1
- 1
be-graphes-model/src/main/java/org/insa/graphs/model/Path.java View File

@@ -299,7 +299,7 @@ public class Path {
299 299
     }
300 300
 
301 301
     /**
302
-     * Checks if the arcs in this path are the same as arcs in obj
302
+     * Checks if the arcs in this path are the same as arcs in obj.
303 303
      * Warning: shallow comparison for the arcs
304 304
      */
305 305
     @Override

Loading…
Cancel
Save