/*
* 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.ch;
import com.graphhopper.routing.*;
import com.graphhopper.routing.util.*;
import com.graphhopper.routing.weighting.FastestWeighting;
import com.graphhopper.routing.weighting.ShortestWeighting;
import com.graphhopper.routing.weighting.Weighting;
import com.graphhopper.storage.*;
import com.graphhopper.util.CHEdgeIteratorState;
import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.Helper;
import com.graphhopper.util.Parameters;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
/**
* Tests if a graph optimized by contraction hierarchies returns the same results as a none
* optimized one. Additionally fine grained path unpacking is tested.
* <p>
*
* @author Peter Karich
*/
public class DijkstraBidirectionCHTest extends AbstractRoutingAlgorithmTester {
@Override
protected CHGraph getGraph(GraphHopperStorage ghStorage, Weighting weighting) {
return ghStorage.getGraph(CHGraph.class, weighting);
}
@Override
protected GraphHopperStorage createGHStorage(EncodingManager em,
List<? extends Weighting> weightings, boolean is3D) {
return new GraphHopperStorage(weightings, new RAMDirectory(),
em, is3D, new GraphExtension.NoOpExtension()).
create(1000);
}
@Override
public RoutingAlgorithmFactory createFactory(GraphHopperStorage ghStorage, AlgorithmOptions opts) {
PrepareContractionHierarchies ch = new PrepareContractionHierarchies(new GHDirectory("", DAType.RAM_INT),
ghStorage, getGraph(ghStorage, opts.getWeighting()),
opts.getWeighting(), TraversalMode.NODE_BASED);
ch.doWork();
return ch;
}
@Test
public void testPathRecursiveUnpacking() {
// use an encoder where it is possible to store 2 weights per edge
FlagEncoder encoder = new Bike2WeightFlagEncoder();
EncodingManager em = new EncodingManager(encoder);
ShortestWeighting weighting = new ShortestWeighting(encoder);
GraphHopperStorage ghStorage = createGHStorage(em, Arrays.asList(weighting), false);
CHGraphImpl g2 = (CHGraphImpl) ghStorage.getGraph(CHGraph.class, weighting);
g2.edge(0, 1, 1, true);
EdgeIteratorState iter1_1 = g2.edge(0, 2, 1.4, false);
EdgeIteratorState iter1_2 = g2.edge(2, 5, 1.4, false);
g2.edge(1, 2, 1, true);
g2.edge(1, 3, 3, true);
g2.edge(2, 3, 1, true);
g2.edge(4, 3, 1, true);
g2.edge(2, 5, 1.4, true);
g2.edge(3, 5, 1, true);
g2.edge(5, 6, 1, true);
g2.edge(4, 6, 1, true);
g2.edge(6, 7, 1, true);
EdgeIteratorState iter2_2 = g2.edge(5, 7);
iter2_2.setDistance(1.4).setFlags(encoder.setProperties(10, true, false));
ghStorage.freeze();
// simulate preparation
CHEdgeIteratorState iter2_1 = g2.shortcut(0, 5);
iter2_1.setDistance(2.8).setFlags(encoder.setProperties(10, true, false));
iter2_1.setSkippedEdges(iter1_1.getEdge(), iter1_2.getEdge());
CHEdgeIteratorState tmp = g2.shortcut(0, 7);
tmp.setDistance(4.2).setFlags(encoder.setProperties(10, true, false));
tmp.setSkippedEdges(iter2_1.getEdge(), iter2_2.getEdge());
g2.setLevel(1, 0);
g2.setLevel(3, 1);
g2.setLevel(4, 2);
g2.setLevel(6, 3);
g2.setLevel(2, 4);
g2.setLevel(5, 5);
g2.setLevel(7, 6);
g2.setLevel(0, 7);
AlgorithmOptions opts = new AlgorithmOptions(Parameters.Algorithms.DIJKSTRA_BI, weighting);
Path p = new PrepareContractionHierarchies(new GHDirectory("", DAType.RAM_INT),
ghStorage, g2, weighting, TraversalMode.NODE_BASED).
createAlgo(g2, opts).calcPath(0, 7);
assertEquals(Helper.createTList(0, 2, 5, 7), p.calcNodes());
assertEquals(1064, p.getTime());
assertEquals(4.2, p.getDistance(), 1e-5);
}
@Test
public void testBaseGraph() {
CarFlagEncoder carFE = new CarFlagEncoder();
EncodingManager em = new EncodingManager(carFE);
AlgorithmOptions opts = AlgorithmOptions.start().
weighting(new ShortestWeighting(carFE)).build();
GraphHopperStorage ghStorage = createGHStorage(em,
Arrays.asList(opts.getWeighting()), false);
initDirectedAndDiffSpeed(ghStorage, carFE);
// do CH preparation for car
createFactory(ghStorage, opts);
// use base graph for solving normal Dijkstra
Path p1 = new RoutingAlgorithmFactorySimple().createAlgo(ghStorage, defaultOpts).calcPath(0, 3);
assertEquals(Helper.createTList(0, 1, 5, 2, 3), p1.calcNodes());
assertEquals(p1.toString(), 402.29, p1.getDistance(), 1e-2);
assertEquals(p1.toString(), 144823, p1.getTime());
}
@Test
public void testBaseGraphMultipleVehicles() {
AlgorithmOptions footOptions = AlgorithmOptions.start().
weighting(new FastestWeighting(footEncoder)).build();
AlgorithmOptions carOptions = AlgorithmOptions.start().
weighting(new FastestWeighting(carEncoder)).build();
GraphHopperStorage g = createGHStorage(encodingManager,
Arrays.asList(footOptions.getWeighting(), carOptions.getWeighting()), false);
initFootVsCar(g);
// do CH preparation for car
RoutingAlgorithmFactory contractedFactory = createFactory(g, carOptions);
// use contracted graph
Path p1 = contractedFactory.createAlgo(getGraph(g, carOptions.getWeighting()), carOptions).calcPath(0, 7);
assertEquals(Helper.createTList(0, 4, 6, 7), p1.calcNodes());
assertEquals(p1.toString(), 15000, p1.getDistance(), 1e-6);
// use base graph for solving normal Dijkstra via car
Path p2 = new RoutingAlgorithmFactorySimple().createAlgo(g, carOptions).calcPath(0, 7);
assertEquals(Helper.createTList(0, 4, 6, 7), p2.calcNodes());
assertEquals(p2.toString(), 15000, p2.getDistance(), 1e-6);
assertEquals(p2.toString(), 2700 * 1000, p2.getTime());
// use base graph for solving normal Dijkstra via foot
Path p3 = new RoutingAlgorithmFactorySimple().createAlgo(g, footOptions).calcPath(0, 7);
assertEquals(p3.toString(), 17000, p3.getDistance(), 1e-6);
assertEquals(p3.toString(), 12240 * 1000, p3.getTime());
assertEquals(Helper.createTList(0, 4, 5, 7), p3.calcNodes());
}
}