Skip to content

Commit 80d61b6

Browse files
committed
Revert "Replace Tarjan algorithm with slightly improved version" (tests are failing)
This reverts commit bf577d4
1 parent 69bd913 commit 80d61b6

File tree

6 files changed

+389
-623
lines changed

6 files changed

+389
-623
lines changed

core/src/main/java/com/graphhopper/routing/lm/LandmarkStorage.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@
2828
import com.graphhopper.routing.SPTEntry;
2929
import com.graphhopper.routing.ev.BooleanEncodedValue;
3030
import com.graphhopper.routing.subnetwork.SubnetworkStorage;
31-
import com.graphhopper.routing.subnetwork.TarjanSCC;
32-
import com.graphhopper.routing.subnetwork.TarjanSCC.ConnectedComponents;
31+
import com.graphhopper.routing.subnetwork.TarjansSCCAlgorithm;
3332
import com.graphhopper.routing.util.AllEdgesIterator;
3433
import com.graphhopper.routing.util.EdgeFilter;
3534
import com.graphhopper.routing.util.FlagEncoder;
@@ -254,11 +253,11 @@ public void createLandmarks() {
254253

255254
// we cannot reuse the components calculated in PrepareRoutingSubnetworks as the edgeIds changed in between (called graph.optimize)
256255
// also calculating subnetworks from scratch makes bigger problems when working with many oneways
257-
TarjanSCC tarjan = new TarjanSCC(graph, encoder.getAccessEnc(), true);
258-
tarjan.setAdditionalEdgeFilter(tarjanFilter);
259-
ConnectedComponents graphComponents = tarjan.findComponents();
256+
TarjansSCCAlgorithm tarjanAlgo = new TarjansSCCAlgorithm(graph, encoder.getAccessEnc(), true);
257+
tarjanAlgo.setAdditionalEdgeFilter(tarjanFilter);
258+
List<IntArrayList> graphComponents = tarjanAlgo.findComponents();
260259
if (logDetails)
261-
LOGGER.info("Calculated " + graphComponents.getComponents().size() + " subnetworks via tarjan in " + sw.stop().getSeconds() + "s, " + Helper.getMemInfo());
260+
LOGGER.info("Calculated " + graphComponents.size() + " subnetworks via tarjan in " + sw.stop().getSeconds() + "s, " + Helper.getMemInfo());
262261

263262
EdgeExplorer tmpExplorer = graph.createEdgeExplorer(new RequireBothDirectionsEdgeFilter(encoder));
264263
String additionalInfo = "";
@@ -269,7 +268,7 @@ public void createLandmarks() {
269268
// see estimateMaxWeight. If we pick the distance too big for small areas this could lead to (slightly)
270269
// suboptimal routes as there will be too big rounding errors. But picking it too small is bad for performance
271270
// e.g. for Germany at least 1500km is very important otherwise speed is at least twice as slow e.g. for 1000km
272-
double maxWeight = estimateMaxWeight(tmpExplorer, graphComponents.getComponents(), blockedEdges);
271+
double maxWeight = estimateMaxWeight(tmpExplorer, graphComponents, blockedEdges);
273272
setMaximumWeight(maxWeight);
274273
additionalInfo = ", maxWeight:" + maxWeight + " from quick estimation";
275274
}
@@ -278,13 +277,13 @@ public void createLandmarks() {
278277
LOGGER.info("init landmarks for subnetworks with node count greater than " + minimumNodes + " with factor:" + factor + additionalInfo);
279278

280279
int nodes = 0;
281-
for (IntArrayList subnetworkIds : graphComponents.getComponents()) {
280+
for (IntArrayList subnetworkIds : graphComponents) {
282281
nodes += subnetworkIds.size();
283282
if (subnetworkIds.size() < minimumNodes)
284283
continue;
285284
if (factor <= 0)
286285
throw new IllegalStateException("factor wasn't initialized " + factor + ", subnetworks:"
287-
+ graphComponents.getComponents().size() + ", minimumNodes:" + minimumNodes + ", current size:" + subnetworkIds.size());
286+
+ graphComponents.size() + ", minimumNodes:" + minimumNodes + ", current size:" + subnetworkIds.size());
288287

289288
int index = subnetworkIds.size() - 1;
290289
// ensure start node is reachable from both sides and no subnetwork is associated

core/src/main/java/com/graphhopper/routing/subnetwork/PrepareRoutingSubnetworks.java

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

20-
import com.carrotsearch.hppc.BitSet;
2120
import com.carrotsearch.hppc.IntArrayList;
2221
import com.carrotsearch.hppc.IntIndexedContainer;
2322
import com.graphhopper.routing.ev.BooleanEncodedValue;
@@ -106,22 +105,37 @@ public int getMaxSubnetworks() {
106105
int removeSmallSubNetworks(BooleanEncodedValue accessEnc) {
107106
// partition graph into strongly connected components using Tarjan's algorithm
108107
StopWatch sw = new StopWatch().start();
109-
TarjanSCC tarjan = new TarjanSCC(ghStorage, accessEnc, false);
110-
TarjanSCC.ConnectedComponents ccs = tarjan.findComponents();
111-
List<IntArrayList> components = ccs.getComponents();
112-
BitSet singleNodeComponents = ccs.getSingleNodeComponents();
113-
logger.info("Found " + ccs.getTotalComponents() + " subnetworks (" + singleNodeComponents.cardinality() + " single nodes and "
114-
+ components.size() + " components with more than one node, total nodes: " + ccs.getNodes() + "), took: " + sw.stop().getSeconds() + "s");
108+
TarjansSCCAlgorithm tarjan = new TarjansSCCAlgorithm(ghStorage, accessEnc, false);
109+
List<IntArrayList> components = tarjan.findComponents();
110+
int totalNodes = 0;
111+
int singleNodeComponents = 0;
112+
for (IntArrayList c : components) {
113+
totalNodes += c.size();
114+
if (c.size() == 1)
115+
singleNodeComponents++;
116+
}
117+
logger.info("Found " + components.size() + " subnetworks (" + singleNodeComponents + " single nodes and "
118+
+ (components.size() - singleNodeComponents) + " components with more than one node, total nodes: " + totalNodes + "), took: " + sw.stop().getSeconds() + "s");
119+
120+
sw = new StopWatch().start();
121+
// find the biggest component
122+
IntArrayList biggest = components.isEmpty() ? new IntArrayList(0) : components.get(0);
123+
for (IntArrayList component : components) {
124+
if (component.size() > biggest.size()) {
125+
biggest = component;
126+
}
127+
}
128+
logger.info("finding the biggest component took: " + sw.stop().getSeconds() + "s");
115129

116130
// remove all small networks except the biggest (even when its smaller than the given min_network_size)
117131
sw = new StopWatch().start();
118132
int removedComponents = 0;
119133
int removedEdges = 0;
120-
int smallestRemaining = ccs.getBiggestComponent().size();
134+
int smallestRemaining = biggest.size();
121135
int biggestRemoved = 0;
122136
EdgeExplorer explorer = ghStorage.createEdgeExplorer(DefaultEdgeFilter.allEdges(accessEnc));
123137
for (IntArrayList component : components) {
124-
if (component == ccs.getBiggestComponent())
138+
if (component == biggest)
125139
continue;
126140

127141
if (component.size() < minNetworkSize) {
@@ -138,9 +152,9 @@ int removeSmallSubNetworks(BooleanEncodedValue accessEnc) {
138152
throw new IllegalStateException("Too many total edges were removed: " + removedEdges + " out of " + ghStorage.getEdges() + "\n" +
139153
"The maximum number of removed edges is: " + allowedRemoved);
140154

141-
subnetworks = ccs.getTotalComponents() - removedComponents;
155+
subnetworks = components.size() - removedComponents;
142156
logger.info("Removed " + removedComponents + " subnetworks (biggest removed: " + biggestRemoved + " nodes) -> " +
143-
subnetworks + " subnetwork(s) left (smallest: " + smallestRemaining + ", biggest: " + ccs.getBiggestComponent().size() + " nodes)"
157+
subnetworks + " subnetwork(s) left (smallest: " + smallestRemaining + ", biggest: " + biggest.size() + " nodes)"
144158
+ ", total removed edges: " + removedEdges + ", took: " + sw.stop().getSeconds() + "s");
145159
return removedEdges;
146160
}

0 commit comments

Comments
 (0)