|
@@ -1,5 +1,16 @@
|
1
|
1
|
package org.insa.graphs.algorithm.shortestpath;
|
2
|
2
|
|
|
3
|
+import java.util.ArrayList;
|
|
4
|
+import java.util.Collections;
|
|
5
|
+
|
|
6
|
+import org.insa.graphs.algorithm.AbstractInputData.Mode;
|
|
7
|
+import org.insa.graphs.algorithm.AbstractSolution.Status;
|
|
8
|
+import org.insa.graphs.algorithm.utils.BinaryHeap;
|
|
9
|
+import org.insa.graphs.model.Arc;
|
|
10
|
+import org.insa.graphs.model.Label;
|
|
11
|
+import org.insa.graphs.model.Node;
|
|
12
|
+import org.insa.graphs.model.Path;
|
|
13
|
+
|
3
|
14
|
public class DijkstraAlgorithm extends ShortestPathAlgorithm {
|
4
|
15
|
|
5
|
16
|
public DijkstraAlgorithm(ShortestPathData data) {
|
|
@@ -9,9 +20,124 @@ public class DijkstraAlgorithm extends ShortestPathAlgorithm {
|
9
|
20
|
@Override
|
10
|
21
|
protected ShortestPathSolution doRun() {
|
11
|
22
|
final ShortestPathData data = getInputData();
|
12
|
|
- ShortestPathSolution solution = null;
|
13
|
|
- // TODO:
|
14
|
|
- return solution;
|
|
23
|
+
|
|
24
|
+ int numberOfNodes = data.getGraph().size();
|
|
25
|
+
|
|
26
|
+ double shortestCostToDestination = Double.POSITIVE_INFINITY;
|
|
27
|
+
|
|
28
|
+ // it's the cost of the last marked node. In order to stop algorithm when it's not
|
|
29
|
+ // useful
|
|
30
|
+ double lastMarkedNodeCost = 0;
|
|
31
|
+
|
|
32
|
+ // Dijkstra Init
|
|
33
|
+ Label[] labels = new Label[numberOfNodes];
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+ for(Node node : data.getGraph().getNodes()) {
|
|
37
|
+ labels[node.getId()] = new Label(node);
|
|
38
|
+ }
|
|
39
|
+
|
|
40
|
+ // Let's set the origin cost at 0
|
|
41
|
+ labels[data.getOrigin().getId()].setNewCost(null, 0d);
|
|
42
|
+
|
|
43
|
+ // We need to add a binaryMinHeap to get min at each iteration
|
|
44
|
+ BinaryHeap<Label> minHeap = new BinaryHeap<Label>();
|
|
45
|
+
|
|
46
|
+ // We add into our binaryMinHeap the origin
|
|
47
|
+ minHeap.insert(labels[data.getOrigin().getId()]);
|
|
48
|
+
|
|
49
|
+ // We can start searching for the shortestPath
|
|
50
|
+
|
|
51
|
+ // We stop the algorithm when the cost of last marked point is equal to the shortest found path
|
|
52
|
+ // or if we searched all the graph
|
|
53
|
+ while(lastMarkedNodeCost < shortestCostToDestination && !minHeap.isEmpty()) {
|
|
54
|
+
|
|
55
|
+ //We get the shortest not marked label
|
|
56
|
+ Label minLabel = minHeap.deleteMin();
|
|
57
|
+
|
|
58
|
+ //We mark it
|
|
59
|
+ minLabel.setMarked();
|
|
60
|
+ lastMarkedNodeCost = minLabel.getCost();
|
|
61
|
+
|
|
62
|
+ //We look at their successors
|
|
63
|
+ for(Arc successor : minLabel.getCurrent().getSuccessors()) {
|
|
64
|
+ //We see if we need to update
|
|
65
|
+ Label label = labels[successor.getDestination().getId()];
|
|
66
|
+
|
|
67
|
+ if(!label.isMarked() ) {
|
|
68
|
+
|
|
69
|
+ //We calculate new costs
|
|
70
|
+ double newCost;
|
|
71
|
+
|
|
72
|
+ // If the arc can't be reached thanks to transport mode (car, bike)
|
|
73
|
+ // Then it's like the cost to reach it is equal to infinity
|
|
74
|
+ if(!data.isAllowed(successor)) {
|
|
75
|
+ newCost = Double.POSITIVE_INFINITY;
|
|
76
|
+ }
|
|
77
|
+ else if(data.getMode() == Mode.TIME) {
|
|
78
|
+ newCost = minLabel.getCost() + successor.getMinimumTravelTime();
|
|
79
|
+ }
|
|
80
|
+ else {
|
|
81
|
+ newCost = minLabel.getCost() + successor.getLength();
|
|
82
|
+ }
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+ if(newCost < label.getCost()) {
|
|
87
|
+ //we need to update !
|
|
88
|
+
|
|
89
|
+ //if the result is finite, then we need to remove first
|
|
90
|
+ //on the heap
|
|
91
|
+ if(Double.isFinite(label.getCost())) {
|
|
92
|
+ minHeap.remove(label);
|
|
93
|
+ }
|
|
94
|
+ label.setNewCost(successor, newCost);
|
|
95
|
+ minHeap.insert(label);
|
|
96
|
+
|
|
97
|
+ //we see if we have updated the destination
|
|
98
|
+
|
|
99
|
+ if(successor.getDestination().equals(data.getDestination())) {
|
|
100
|
+ shortestCostToDestination = newCost;
|
|
101
|
+ }
|
|
102
|
+
|
|
103
|
+ }
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+ }
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+ }
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+ }
|
|
113
|
+
|
|
114
|
+ //Here we have calculated minimum cost to destination, or no destination is unreachable
|
|
115
|
+
|
|
116
|
+ //We see if we find something
|
|
117
|
+ if(labels[data.getDestination().getId()].getFather() == null) {
|
|
118
|
+ //here there is no route available
|
|
119
|
+ return new ShortestPathSolution(data, Status.INFEASIBLE);
|
|
120
|
+ }
|
|
121
|
+
|
|
122
|
+ //There is a path, let's find it
|
|
123
|
+
|
|
124
|
+ ArrayList<Arc> path = new ArrayList<Arc>();
|
|
125
|
+
|
|
126
|
+ //First arc
|
|
127
|
+ Arc arc = labels[data.getDestination().getId()].getFather();
|
|
128
|
+
|
|
129
|
+ while(arc != null) {
|
|
130
|
+ //while there is a father
|
|
131
|
+ //add the arc to the path
|
|
132
|
+ path.add(arc);
|
|
133
|
+ arc = labels[arc.getOrigin().getId()].getFather();
|
|
134
|
+ }
|
|
135
|
+
|
|
136
|
+ // We need to reverse the path to get in the right order
|
|
137
|
+ Collections.reverse(path);
|
|
138
|
+
|
|
139
|
+ // Send the solution
|
|
140
|
+ return new ShortestPathSolution(data, Status.OPTIMAL, new Path(data.getGraph(), path));
|
15
|
141
|
}
|
16
|
142
|
|
17
|
143
|
}
|