/*
* Licensed to GraphHopper GmbH under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* GraphHopper GmbH licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.graphhopper.routing;
import com.graphhopper.GraphHopper;
import com.graphhopper.reader.PrinctonReader;
import com.graphhopper.routing.util.EncodingManager;
import com.graphhopper.routing.util.FlagEncoder;
import com.graphhopper.routing.util.HintsMap;
import com.graphhopper.routing.util.TestAlgoCollector.AlgoHelperEntry;
import com.graphhopper.routing.util.TraversalMode;
import com.graphhopper.routing.weighting.Weighting;
import com.graphhopper.storage.CHGraph;
import com.graphhopper.storage.Directory;
import com.graphhopper.storage.GraphBuilder;
import com.graphhopper.storage.GraphHopperStorage;
import com.graphhopper.storage.index.LocationIndex;
import com.graphhopper.storage.index.LocationIndexTree;
import com.graphhopper.util.Parameters;
import com.graphhopper.util.StopWatch;
import org.junit.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
import java.util.zip.GZIPInputStream;
import static com.graphhopper.util.Parameters.Algorithms.*;
import static org.junit.Assert.assertTrue;
/**
* Try algorithms, indices and graph storages with real data
*
* @author Peter Karich
*/
public class RoutingAlgorithmIT {
public static List<AlgoHelperEntry> createAlgos(final GraphHopper hopper, final HintsMap hints, TraversalMode tMode) {
GraphHopperStorage ghStorage = hopper.getGraphHopperStorage();
LocationIndex idx = hopper.getLocationIndex();
String addStr = "";
if (tMode.isEdgeBased())
addStr = "turn|";
FlagEncoder encoder = hopper.getEncodingManager().getEncoder(hints.getVehicle());
Weighting weighting = hopper.createWeighting(hints, encoder, hopper.getGraphHopperStorage());
HintsMap defaultHints = new HintsMap().put(Parameters.CH.DISABLE, true).put(Parameters.Landmark.DISABLE, true)
.setVehicle(hints.getVehicle()).setWeighting(hints.getWeighting());
AlgorithmOptions defaultOpts = AlgorithmOptions.start(new AlgorithmOptions("", weighting, tMode)).hints(defaultHints).build();
List<AlgoHelperEntry> prepare = new ArrayList<>();
prepare.add(new AlgoHelperEntry(ghStorage, AlgorithmOptions.start(defaultOpts).algorithm(ASTAR).build(), idx, "astar|beeline|" + addStr + weighting));
// later: include dijkstraOneToMany
prepare.add(new AlgoHelperEntry(ghStorage, AlgorithmOptions.start(defaultOpts).algorithm(DIJKSTRA).build(), idx, "dijkstra|" + addStr + weighting));
AlgorithmOptions astarbiOpts = AlgorithmOptions.start(defaultOpts).algorithm(ASTAR_BI).build();
astarbiOpts.getHints().put(ASTAR_BI + ".approximation", "BeelineSimplification");
AlgorithmOptions dijkstrabiOpts = AlgorithmOptions.start(defaultOpts).algorithm(DIJKSTRA_BI).build();
prepare.add(new AlgoHelperEntry(ghStorage, astarbiOpts, idx, "astarbi|beeline|" + addStr + weighting));
prepare.add(new AlgoHelperEntry(ghStorage, dijkstrabiOpts, idx, "dijkstrabi|" + addStr + weighting));
// add additional preparations if CH and LM preparation are enabled
if (hopper.getLMFactoryDecorator().isEnabled()) {
final HintsMap lmHints = new HintsMap(defaultHints).put(Parameters.Landmark.DISABLE, false);
prepare.add(new AlgoHelperEntry(ghStorage, AlgorithmOptions.start(astarbiOpts).hints(lmHints).build(), idx, "astarbi|landmarks|" + weighting) {
@Override
public RoutingAlgorithmFactory createRoutingFactory() {
return hopper.getAlgorithmFactory(lmHints);
}
});
}
if (hopper.getCHFactoryDecorator().isEnabled()) {
final HintsMap chHints = new HintsMap(defaultHints).put(Parameters.CH.DISABLE, false);
Weighting pickedWeighting = null;
for (Weighting tmpWeighting : hopper.getCHFactoryDecorator().getWeightings()) {
if (tmpWeighting.equals(weighting)) {
pickedWeighting = tmpWeighting;
break;
}
}
if (pickedWeighting == null)
throw new IllegalStateException("Didn't find weighting " + hints.getWeighting() + " in " + hopper.getCHFactoryDecorator().getWeightings());
prepare.add(new AlgoHelperEntry(ghStorage.getGraph(CHGraph.class, pickedWeighting),
AlgorithmOptions.start(dijkstrabiOpts).hints(chHints).build(), idx, "dijkstrabi|ch|prepare|" + hints.getWeighting()) {
@Override
public RoutingAlgorithmFactory createRoutingFactory() {
return hopper.getAlgorithmFactory(chHints);
}
});
prepare.add(new AlgoHelperEntry(ghStorage.getGraph(CHGraph.class, pickedWeighting),
AlgorithmOptions.start(astarbiOpts).hints(chHints).build(), idx, "astarbi|ch|prepare|" + hints.getWeighting()) {
@Override
public RoutingAlgorithmFactory createRoutingFactory() {
return hopper.getAlgorithmFactory(chHints);
}
});
}
return prepare;
}
@Test
public void testPerformance() throws IOException {
int N = 10;
int noJvmWarming = N / 4;
Random rand = new Random(0);
final EncodingManager eManager = new EncodingManager("car");
final GraphHopperStorage graph = new GraphBuilder(eManager).create();
String bigFile = "10000EWD.txt.gz";
new PrinctonReader(graph).setStream(new GZIPInputStream(PrinctonReader.class.getResourceAsStream(bigFile))).read();
GraphHopper hopper = new GraphHopper() {
{
setCHEnabled(false);
setEncodingManager(eManager);
loadGraph(graph);
}
@Override
protected LocationIndex createLocationIndex(Directory dir) {
return new LocationIndexTree(graph, dir);
}
};
Collection<AlgoHelperEntry> prepares = createAlgos(hopper, new HintsMap().setWeighting("shortest").setVehicle("car"), TraversalMode.NODE_BASED);
for (AlgoHelperEntry entry : prepares) {
StopWatch sw = new StopWatch();
for (int i = 0; i < N; i++) {
int node1 = Math.abs(rand.nextInt(graph.getNodes()));
int node2 = Math.abs(rand.nextInt(graph.getNodes()));
RoutingAlgorithm d = entry.createRoutingFactory().createAlgo(graph, entry.getAlgorithmOptions());
if (i >= noJvmWarming)
sw.start();
Path p = d.calcPath(node1, node2);
// avoid jvm optimization => call p.distance
if (i >= noJvmWarming && p.getDistance() > -1)
sw.stop();
// System.out.println("#" + i + " " + name + ":" + sw.getSeconds() + " " + p.nodes());
}
float perRun = sw.stop().getSeconds() / ((float) (N - noJvmWarming));
System.out.println("# " + getClass().getSimpleName() + " " + entry
+ ":" + sw.stop().getSeconds() + ", per run:" + perRun);
assertTrue("speed to low!? " + perRun + " per run", perRun < 0.08);
}
}
}