Skip to content

Commit 9a5efe6

Browse files
authored
Move path extraction logic out of Path class (graphhopper#1730)
* Remove PathBidirRef#switchFromTo * Remove unnecessary statement in edge-based CH algo * Remove unnecessary check in AlternativeRoute * Use dedicated path extraction class for bidir algos * Remove PathBidirRef and subclasses * Make AStar more similar to Dijkstra * Move path extraction for unidir algos into new PathExtractor * Remove extract stuff from Path class
1 parent bdfd55f commit 9a5efe6

22 files changed

+461
-469
lines changed

core/files/changelog.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
0.14
22
conditional turn restrictions now supported, #1683
3+
removed PathNative,PathBidirRef,Path4CH,EdgeBasedPathCH and moved path extraction code out of Path class, added PathExtractor,BidirPathExtractor(+subclasses for CH) instead, #1730
34

45
0.13
56
removed docker compose file

core/src/main/java/com/graphhopper/routing/AStar.java

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,12 @@
3838
* @author Peter Karich
3939
*/
4040
public class AStar extends AbstractRoutingAlgorithm {
41-
private WeightApproximator weightApprox;
42-
private int visitedCount;
4341
private GHIntObjectHashMap<AStarEntry> fromMap;
44-
private PriorityQueue<AStarEntry> prioQueueOpenSet;
42+
private PriorityQueue<AStarEntry> fromHeap;
4543
private AStarEntry currEdge;
46-
private int to1 = -1;
44+
private int visitedNodes;
45+
private int to = -1;
46+
private WeightApproximator weightApprox;
4747

4848
public AStar(Graph graph, Weighting weighting, TraversalMode tMode) {
4949
super(graph, weighting, tMode);
@@ -64,97 +64,94 @@ public AStar setApproximation(WeightApproximator approx) {
6464

6565
protected void initCollections(int size) {
6666
fromMap = new GHIntObjectHashMap<>();
67-
prioQueueOpenSet = new PriorityQueue<>(size);
67+
fromHeap = new PriorityQueue<>(size);
6868
}
6969

7070
@Override
7171
public Path calcPath(int from, int to) {
7272
checkAlreadyRun();
73-
to1 = to;
74-
73+
this.to = to;
7574
weightApprox.setTo(to);
7675
double weightToGoal = weightApprox.approximate(from);
7776
currEdge = new AStarEntry(EdgeIterator.NO_EDGE, from, 0 + weightToGoal, 0);
7877
if (!traversalMode.isEdgeBased()) {
7978
fromMap.put(from, currEdge);
8079
}
81-
return runAlgo();
80+
runAlgo();
81+
return extractPath();
8282
}
8383

84-
private Path runAlgo() {
84+
private void runAlgo() {
8585
double currWeightToGoal, estimationFullWeight;
8686
EdgeExplorer explorer = outEdgeExplorer;
8787
while (true) {
88-
int currVertex = currEdge.adjNode;
89-
visitedCount++;
90-
if (isMaxVisitedNodesExceeded())
91-
return createEmptyPath();
92-
93-
if (finished())
88+
visitedNodes++;
89+
if (isMaxVisitedNodesExceeded() || finished())
9490
break;
9591

96-
EdgeIterator iter = explorer.setBaseNode(currVertex);
92+
int currNode = currEdge.adjNode;
93+
EdgeIterator iter = explorer.setBaseNode(currNode);
9794
while (iter.next()) {
9895
if (!accept(iter, currEdge.edge))
9996
continue;
10097

101-
double alreadyVisitedWeight = weighting.calcWeight(iter, false, currEdge.edge)
102-
+ currEdge.weightOfVisitedPath;
103-
if (Double.isInfinite(alreadyVisitedWeight))
98+
double tmpWeight = weighting.calcWeight(iter, false, currEdge.edge) + currEdge.weightOfVisitedPath;
99+
if (Double.isInfinite(tmpWeight)) {
104100
continue;
105-
101+
}
106102
int traversalId = traversalMode.createTraversalId(iter, false);
103+
107104
AStarEntry ase = fromMap.get(traversalId);
108-
if (ase == null || ase.weightOfVisitedPath > alreadyVisitedWeight) {
105+
if (ase == null || ase.weightOfVisitedPath > tmpWeight) {
109106
int neighborNode = iter.getAdjNode();
110107
currWeightToGoal = weightApprox.approximate(neighborNode);
111-
estimationFullWeight = alreadyVisitedWeight + currWeightToGoal;
108+
estimationFullWeight = tmpWeight + currWeightToGoal;
112109
if (ase == null) {
113-
ase = new AStarEntry(iter.getEdge(), neighborNode, estimationFullWeight, alreadyVisitedWeight);
110+
ase = new AStarEntry(iter.getEdge(), neighborNode, estimationFullWeight, tmpWeight);
114111
fromMap.put(traversalId, ase);
115112
} else {
116113
// assert (ase.weight > 0.9999999 * estimationFullWeight) : "Inconsistent distance estimate. It is expected weight >= estimationFullWeight but was "
117114
// + ase.weight + " < " + estimationFullWeight + " (" + ase.weight / estimationFullWeight + "), and weightOfVisitedPath:"
118115
// + ase.weightOfVisitedPath + " vs. alreadyVisitedWeight:" + alreadyVisitedWeight + " (" + ase.weightOfVisitedPath / alreadyVisitedWeight + ")";
119116

120-
prioQueueOpenSet.remove(ase);
117+
fromHeap.remove(ase);
121118
ase.edge = iter.getEdge();
122119
ase.weight = estimationFullWeight;
123-
ase.weightOfVisitedPath = alreadyVisitedWeight;
120+
ase.weightOfVisitedPath = tmpWeight;
124121
}
125122

126123
ase.parent = currEdge;
127-
prioQueueOpenSet.add(ase);
124+
fromHeap.add(ase);
128125

129126
updateBestPath(iter, ase, traversalId);
130127
}
131128
}
132129

133-
if (prioQueueOpenSet.isEmpty())
134-
return createEmptyPath();
130+
if (fromHeap.isEmpty())
131+
break;
135132

136-
currEdge = prioQueueOpenSet.poll();
133+
currEdge = fromHeap.poll();
137134
if (currEdge == null)
138135
throw new AssertionError("Empty edge cannot happen");
139136
}
140-
141-
return extractPath();
142137
}
143138

144139
@Override
145-
protected Path extractPath() {
146-
return new Path(graph, weighting).
147-
setWeight(currEdge.weight).setSPTEntry(currEdge).extract();
140+
protected boolean finished() {
141+
return currEdge.adjNode == to;
148142
}
149143

150144
@Override
151-
protected boolean finished() {
152-
return currEdge.adjNode == to1;
145+
protected Path extractPath() {
146+
if (currEdge == null || !finished())
147+
return createEmptyPath();
148+
149+
return PathExtractor.extractPath(graph, weighting, currEdge);
153150
}
154151

155152
@Override
156153
public int getVisitedNodes() {
157-
return visitedCount;
154+
return visitedNodes;
158155
}
159156

160157
protected void updateBestPath(EdgeIteratorState edgeState, SPTEntry bestSPTEntry, int traversalId) {

core/src/main/java/com/graphhopper/routing/AStarBidirectionCH.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
*/
1818
package com.graphhopper.routing;
1919

20-
import com.graphhopper.routing.ch.Path4CH;
20+
import com.graphhopper.routing.ch.NodeBasedCHBidirPathExtractor;
2121
import com.graphhopper.routing.util.TraversalMode;
2222
import com.graphhopper.routing.weighting.Weighting;
2323
import com.graphhopper.storage.Graph;
@@ -39,13 +39,12 @@ protected boolean finished() {
3939
return true;
4040

4141
// changed finish condition for CH
42-
return currFrom.weight >= bestPath.getWeight() && currTo.weight >= bestPath.getWeight();
42+
return currFrom.weight >= bestWeight && currTo.weight >= bestWeight;
4343
}
4444

4545
@Override
46-
protected Path createAndInitPath() {
47-
bestPath = new Path4CH(graph, graph.getBaseGraph(), weighting);
48-
return bestPath;
46+
protected BidirPathExtractor createPathExtractor(Graph graph, Weighting weighting) {
47+
return new NodeBasedCHBidirPathExtractor(graph, graph.getBaseGraph(), weighting);
4948
}
5049

5150
@Override

core/src/main/java/com/graphhopper/routing/AStarBidirectionEdgeCHNoSOD.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,12 @@ public void init(int from, double fromWeight, int to, double toWeight) {
4545

4646
@Override
4747
protected boolean fwdSearchCanBeStopped() {
48-
return getMinCurrFromPathWeight() > bestPath.getWeight();
48+
return getMinCurrFromPathWeight() > bestWeight;
4949
}
5050

5151
@Override
5252
protected boolean bwdSearchCanBeStopped() {
53-
return getMinCurrToPathWeight() > bestPath.getWeight();
53+
return getMinCurrToPathWeight() > bestWeight;
5454
}
5555

5656
@Override

core/src/main/java/com/graphhopper/routing/AbstractBidirAlgo.java

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ public abstract class AbstractBidirAlgo extends AbstractRoutingAlgorithm {
5050
protected IntObjectMap<SPTEntry> bestWeightMapOther;
5151
protected SPTEntry currFrom;
5252
protected SPTEntry currTo;
53-
protected PathBidirRef bestPath;
53+
protected SPTEntry bestFwdEntry;
54+
protected SPTEntry bestBwdEntry;
55+
protected double bestWeight;
5456
PriorityQueue<SPTEntry> pqOpenSetFrom;
5557
PriorityQueue<SPTEntry> pqOpenSetTo;
5658
private boolean updateBestPath = true;
@@ -63,6 +65,7 @@ public AbstractBidirAlgo(Graph graph, Weighting weighting, TraversalMode tMode)
6365
super(graph, weighting, tMode);
6466
fromOutEdge = ANY_EDGE;
6567
toInEdge = ANY_EDGE;
68+
bestWeight = Double.MAX_VALUE;
6669
int size = Math.min(Math.max(200, graph.getNodes() / 10), 150_000);
6770
initCollections(size);
6871
}
@@ -115,15 +118,13 @@ public Path calcPath(int from, int to, int fromOutEdge, int toInEdge) {
115118
this.fromOutEdge = fromOutEdge;
116119
this.toInEdge = toInEdge;
117120
checkAlreadyRun();
118-
createAndInitPath();
119121
init(from, 0, to, 0);
120122
runAlgo();
121123
return extractPath();
122124
}
123125

124-
protected Path createAndInitPath() {
125-
bestPath = new PathBidirRef(graph, weighting);
126-
return bestPath;
126+
protected BidirPathExtractor createPathExtractor(Graph graph, Weighting weighting) {
127+
return new BidirPathExtractor(graph, weighting);
127128
}
128129

129130
void init(int from, double fromWeight, int to, double toWeight) {
@@ -162,9 +163,9 @@ protected void postInit(int from, int to) {
162163
if (currFrom.weight != 0 || currTo.weight != 0) {
163164
throw new IllegalStateException("If from=to, the starting weight must be zero for from and to");
164165
}
165-
bestPath.sptEntry = currFrom;
166-
bestPath.edgeTo = currTo;
167-
bestPath.setWeight(0);
166+
bestFwdEntry = currFrom;
167+
bestBwdEntry = currTo;
168+
bestWeight = 0;
168169
finishedFrom = true;
169170
finishedTo = true;
170171
return;
@@ -244,7 +245,7 @@ protected boolean finished() {
244245
if (finishedFrom || finishedTo)
245246
return true;
246247

247-
return currFrom.weight + currTo.weight >= bestPath.getWeight();
248+
return currFrom.weight + currTo.weight >= bestWeight;
248249
}
249250

250251
boolean fillEdgesFrom() {
@@ -327,11 +328,10 @@ protected void updateBestPath(EdgeIteratorState edgeState, SPTEntry entry, int t
327328
weight -= weighting.calcWeight(edgeState, reverse, EdgeIterator.NO_EDGE);
328329
}
329330

330-
if (weight < bestPath.getWeight()) {
331-
bestPath.setSwitchToFrom(reverse);
332-
bestPath.setSPTEntry(entry);
333-
bestPath.setSPTEntryTo(entryOther);
334-
bestPath.setWeight(weight);
331+
if (weight < bestWeight) {
332+
bestFwdEntry = reverse ? entryOther : entry;
333+
bestBwdEntry = reverse ? entry : entryOther;
334+
bestWeight = weight;
335335
}
336336
}
337337

@@ -364,9 +364,9 @@ protected double calcWeight(EdgeIteratorState iter, SPTEntry currEdge, boolean r
364364
@Override
365365
protected Path extractPath() {
366366
if (finished())
367-
return bestPath.extract();
367+
return createPathExtractor(graph, weighting).extract(bestFwdEntry, bestBwdEntry, bestWeight);
368368

369-
return bestPath;
369+
return createEmptyPath();
370370
}
371371

372372
protected boolean fromEntryCanBeSkipped() {
@@ -409,10 +409,6 @@ protected void setUpdateBestPath(boolean b) {
409409
updateBestPath = b;
410410
}
411411

412-
void setBestPath(PathBidirRef bestPath) {
413-
this.bestPath = bestPath;
414-
}
415-
416412
@Override
417413
public int getVisitedNodes() {
418414
return visitedCountFrom + visitedCountTo;

core/src/main/java/com/graphhopper/routing/AbstractBidirectionEdgeCHNoSOD.java

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@
1818
package com.graphhopper.routing;
1919

2020
import com.graphhopper.routing.ch.CHEntry;
21-
import com.graphhopper.routing.ch.EdgeBasedPathCH;
21+
import com.graphhopper.routing.ch.EdgeBasedCHBidirPathExtractor;
2222
import com.graphhopper.routing.util.DefaultEdgeFilter;
2323
import com.graphhopper.routing.util.EdgeFilter;
2424
import com.graphhopper.routing.util.TraversalMode;
2525
import com.graphhopper.routing.weighting.TurnWeighting;
26+
import com.graphhopper.routing.weighting.Weighting;
2627
import com.graphhopper.storage.Graph;
2728
import com.graphhopper.storage.SPTEntry;
2829
import com.graphhopper.util.EdgeExplorer;
@@ -65,7 +66,6 @@ public boolean accept(EdgeIteratorState edgeState) {
6566
}
6667
});
6768
}
68-
finishedFrom = bestPath.isFound();
6969
}
7070

7171
@Override
@@ -80,7 +80,6 @@ public boolean accept(EdgeIteratorState edgeState) {
8080
}
8181
});
8282
}
83-
finishedTo = bestPath.isFound();
8483
}
8584

8685
@Override
@@ -95,7 +94,7 @@ public boolean finished() {
9594
return true;
9695

9796
// changed also the final finish condition for CH
98-
return currFrom.weight >= bestPath.getWeight() && currTo.weight >= bestPath.getWeight();
97+
return currFrom.weight >= bestWeight && currTo.weight >= bestWeight;
9998
}
10099

101100
@Override
@@ -107,11 +106,10 @@ protected void updateBestPath(EdgeIteratorState edgeState, SPTEntry entry, int t
107106
int oppositeEdge = reverse ? fromOutEdge : toInEdge;
108107
boolean oppositeEdgeRestricted = reverse ? (fromOutEdge != ANY_EDGE) : (toInEdge != ANY_EDGE);
109108
if (edgeState.getAdjNode() == oppositeNode && (!oppositeEdgeRestricted || getOrigEdgeId(edgeState, reverse) == oppositeEdge)) {
110-
if (entry.getWeightOfVisitedPath() < bestPath.getWeight()) {
111-
bestPath.setSwitchToFrom(reverse);
112-
bestPath.setSPTEntry(entry);
113-
bestPath.setSPTEntryTo(new CHEntry(oppositeNode, 0));
114-
bestPath.setWeight(entry.getWeightOfVisitedPath());
109+
if (entry.getWeightOfVisitedPath() < bestWeight) {
110+
bestFwdEntry = reverse ? new CHEntry(oppositeNode, 0) : entry;
111+
bestBwdEntry = reverse ? entry : new CHEntry(oppositeNode, 0);
112+
bestWeight = entry.getWeightOfVisitedPath();
115113
return;
116114
}
117115
}
@@ -137,19 +135,17 @@ protected void updateBestPath(EdgeIteratorState edgeState, SPTEntry entry, int t
137135
turnWeighting.calcTurnWeight(prevOrNextOrigEdgeId, iter.getBaseNode(), edgeId);
138136

139137
double newWeight = entry.getWeightOfVisitedPath() + entryOther.getWeightOfVisitedPath() + turnCostsAtBridgeNode;
140-
if (newWeight < bestPath.getWeight()) {
141-
bestPath.setSwitchToFrom(reverse);
142-
bestPath.setSPTEntry(entry);
143-
bestPath.setSPTEntryTo(entryOther);
144-
bestPath.setWeight(newWeight);
138+
if (newWeight < bestWeight) {
139+
bestFwdEntry = reverse ? entryOther : entry;
140+
bestBwdEntry = reverse ? entry : entryOther;
141+
bestWeight = newWeight;
145142
}
146143
}
147144
}
148145

149146
@Override
150-
protected Path createAndInitPath() {
151-
bestPath = new EdgeBasedPathCH(graph, graph.getBaseGraph(), weighting);
152-
return bestPath;
147+
protected BidirPathExtractor createPathExtractor(Graph graph, Weighting weighting) {
148+
return new EdgeBasedCHBidirPathExtractor(graph, graph.getBaseGraph(), weighting);
153149
}
154150

155151
@Override

0 commit comments

Comments
 (0)