Skip to content

Commit

Permalink
Picks recent changes from stable branch - tests are failing.
Browse files Browse the repository at this point in the history
  • Loading branch information
easbar committed Oct 12, 2018
1 parent e829f13 commit 60b4da9
Show file tree
Hide file tree
Showing 25 changed files with 331 additions and 125 deletions.
19 changes: 13 additions & 6 deletions core/src/main/java/com/graphhopper/GraphHopper.java
Expand Up @@ -57,6 +57,8 @@
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import static com.graphhopper.routing.ch.CHAlgoFactoryDecorator.EdgeBasedCHMode.EDGE_OR_NODE;
import static com.graphhopper.routing.ch.CHAlgoFactoryDecorator.EdgeBasedCHMode.OFF;
import static com.graphhopper.util.Helper.*;
import static com.graphhopper.util.Parameters.Algorithms.*;

Expand Down Expand Up @@ -514,7 +516,7 @@ public FlagEncoderFactory getFlagEncoderFactory() {
}

/**
* Reads the configuration from a CmdArgs object which can be manually filled, or via
* Reads the configuration from a CmdArgs object which can be manually filled, or via
* CmdArgs.read(String[] args)
*/
public GraphHopper init(CmdArgs args) {
Expand Down Expand Up @@ -757,8 +759,8 @@ public boolean load(String graphHopperFolder) {

if (chFactoryDecorator.isEnabled()) {
initCHAlgoFactoryDecorator();
ghStorage = new GraphHopperStorage(chFactoryDecorator.getWeightings(), dir, encodingManager, hasElevation(),
encodingManager.needsTurnCostsSupport(), ext);
ghStorage = new GraphHopperStorage(chFactoryDecorator.getNodeBasedWeightings(), chFactoryDecorator.getEdgeBasedWeightings(),
dir, encodingManager, hasElevation(), ext);
} else {
ghStorage = new GraphHopperStorage(dir, encodingManager, hasElevation(), ext);
}
Expand Down Expand Up @@ -817,8 +819,13 @@ private void initCHAlgoFactoryDecorator() {
for (FlagEncoder encoder : encodingManager.fetchEdgeEncoders()) {
for (String chWeightingStr : chFactoryDecorator.getWeightingsAsStrings()) {
// ghStorage is null at this point
Weighting weighting = createWeighting(new HintsMap(chWeightingStr), encoder, null);
chFactoryDecorator.addWeighting(weighting);
CHAlgoFactoryDecorator.EdgeBasedCHMode edgeBasedCHMode = chFactoryDecorator.getEdgeBasedCHMode();
if (!(edgeBasedCHMode == EDGE_OR_NODE && encoder.supports(TurnWeighting.class))) {
chFactoryDecorator.addNodeBasedWeighting(createWeighting(new HintsMap(chWeightingStr), encoder, null));
}
if (edgeBasedCHMode != OFF && encoder.supports(TurnWeighting.class)) {
chFactoryDecorator.addEdgeBasedWeighting(createWeighting(new HintsMap(chWeightingStr), encoder, null));
}
}
}
}
Expand Down Expand Up @@ -864,7 +871,7 @@ public void postProcessing() {
initLocationIndex();

if (chFactoryDecorator.isEnabled())
chFactoryDecorator.createPreparations(ghStorage, traversalMode);
chFactoryDecorator.createPreparations(ghStorage);
if (!isCHPrepared())
prepareCH();

Expand Down
Expand Up @@ -42,7 +42,7 @@ public AbstractNodeContractor(Directory dir, GraphHopperStorage ghStorage, CHGra
this.ghStorage = ghStorage;
this.prepareGraph = prepareGraph;
this.encoder = weighting.getFlagEncoder();
originalEdges = dir.find("original_edges_" + AbstractWeighting.weightingToFileName(weighting));
originalEdges = dir.find("original_edges_" + AbstractWeighting.weightingToFileName(weighting, isEdgeBased()));
originalEdges.create(1000);
}

Expand Down Expand Up @@ -88,4 +88,6 @@ int getOrigEdgeCount(int edgeId) {
originalEdges.ensureCapacity(tmp + 4);
return originalEdges.getInt(tmp);
}

abstract boolean isEdgeBased();
}
Expand Up @@ -25,8 +25,8 @@
import com.graphhopper.routing.weighting.Weighting;
import com.graphhopper.storage.*;
import com.graphhopper.util.CmdArgs;
import com.graphhopper.util.Parameters;
import com.graphhopper.util.PMap;
import com.graphhopper.util.Parameters;
import com.graphhopper.util.Parameters.CH;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -48,11 +48,13 @@ public class CHAlgoFactoryDecorator implements RoutingAlgorithmFactoryDecorator
private final List<PrepareContractionHierarchies> preparations = new ArrayList<>();
// we need to decouple weighting objects from the weighting list of strings
// as we need the strings to create the GraphHopperStorage and the GraphHopperStorage to create the preparations from the Weighting objects currently requiring the encoders
private final List<Weighting> weightings = new ArrayList<>();
private final List<Weighting> nodeBasedWeightings = new ArrayList<>();
private final List<Weighting> edgeBasedWeightings = new ArrayList<>();
private final Set<String> weightingsAsStrings = new LinkedHashSet<>();
private boolean disablingAllowed = false;
// for backward compatibility enable CH by default.
private boolean enabled = true;
private EdgeBasedCHMode edgeBasedCHMode = EdgeBasedCHMode.OFF;
private int preparationThreads;
private ExecutorService threadPool;
private PMap pMap = new PMap();
Expand Down Expand Up @@ -88,6 +90,9 @@ public void init(CmdArgs args) {
if (enableThis)
setDisablingAllowed(args.getBool(CH.INIT_DISABLING_ALLOWED, isDisablingAllowed()));

String edgeBasedCHStr = args.get(CH.PREPARE + "edge_based", "off");
edgeBasedCHMode = EdgeBasedCHMode.valueOf(edgeBasedCHStr.trim().toUpperCase());

pMap = args;
}

Expand Down Expand Up @@ -116,12 +121,27 @@ public final CHAlgoFactoryDecorator setDisablingAllowed(boolean disablingAllowed
return this;
}

/**
* This method specifies whether or not edge-based CH preparation (needed for turn costs) should be performed.
*
* @see EdgeBasedCHMode
*/
public final CHAlgoFactoryDecorator setEdgeBasedCHMode(EdgeBasedCHMode edgeBasedCHMode) {
this.edgeBasedCHMode = edgeBasedCHMode;
return this;
}

/**
* Decouple weightings from PrepareContractionHierarchies as we need weightings for the
* graphstorage and the graphstorage for the preparation.
*/
public CHAlgoFactoryDecorator addWeighting(Weighting weighting) {
weightings.add(weighting);
public CHAlgoFactoryDecorator addNodeBasedWeighting(Weighting weighting) {
nodeBasedWeightings.add(weighting);
return this;
}

public CHAlgoFactoryDecorator addEdgeBasedWeighting(Weighting weighting) {
edgeBasedWeightings.add(weighting);
return this;
}

Expand All @@ -131,24 +151,42 @@ public CHAlgoFactoryDecorator addWeighting(String weighting) {
}

public CHAlgoFactoryDecorator addPreparation(PrepareContractionHierarchies pch) {
preparations.add(pch);
int lastIndex = preparations.size() - 1;
if (lastIndex >= weightings.size())
// we want to make sure that edge- and node-based preparations are added in the same order as their corresponding
// weightings, but changing the order between edge- and node-based preparations is accepted
int index = 0;
for (PrepareContractionHierarchies p : preparations) {
if (p.isEdgeBased() == pch.isEdgeBased()) {
index++;
}
}
List<Weighting> weightings = pch.isEdgeBased() ? edgeBasedWeightings : nodeBasedWeightings;
if (index >= weightings.size())
throw new IllegalStateException("Cannot access weighting for PrepareContractionHierarchies with " + pch.getWeighting()
+ ". Call add(Weighting) before");

if (preparations.get(lastIndex).getWeighting() != weightings.get(lastIndex))
throw new IllegalArgumentException("Weighting of PrepareContractionHierarchies " + preparations.get(lastIndex).getWeighting()
+ " needs to be identical to previously added " + weightings.get(lastIndex));
Weighting expectedWeighting = weightings.get(index);
if (pch.getWeighting() != expectedWeighting)
throw new IllegalArgumentException("Weighting of PrepareContractionHierarchies " + pch
+ " needs to be identical to previously added " + expectedWeighting);

preparations.add(pch);
return this;
}

public final boolean hasWeightings() {
return !weightings.isEmpty();
return !nodeBasedWeightings.isEmpty() || !edgeBasedWeightings.isEmpty();
}

public final List<Weighting> getNodeBasedWeightings() {
return nodeBasedWeightings;
}

public final List<Weighting> getEdgeBasedWeightings() {
return edgeBasedWeightings;
}

public final List<Weighting> getWeightings() {
return weightings;
public EdgeBasedCHMode getEdgeBasedCHMode() {
return edgeBasedCHMode;
}

public CHAlgoFactoryDecorator setWeightingsAsStrings(String... weightingNames) {
Expand Down Expand Up @@ -195,15 +233,16 @@ public RoutingAlgorithmFactory getDecoratedAlgorithmFactory(RoutingAlgorithmFact
if (!isEnabled() || disablingAllowed && disableCH)
return defaultAlgoFactory;

if (preparations.isEmpty())
List<PrepareContractionHierarchies> allPreparations = getPreparations();
if (allPreparations.isEmpty())
throw new IllegalStateException("No preparations added to this decorator");

if (map.getWeighting().isEmpty())
map.setWeighting(getDefaultWeighting());

boolean edgeBased = map.getBool(Parameters.Routing.EDGE_BASED, false);
String entriesStr = "";
for (PrepareContractionHierarchies p : preparations) {
boolean edgeBased = map.getBool(Parameters.Routing.EDGE_BASED, false);
for (PrepareContractionHierarchies p : allPreparations) {
if (p.isEdgeBased() == edgeBased && p.getWeighting().matches(map))
return p;

Expand All @@ -230,8 +269,9 @@ public void prepare(final StorableProperties properties) {
ExecutorCompletionService completionService = new ExecutorCompletionService<>(threadPool);
int counter = 0;
for (final PrepareContractionHierarchies prepare : getPreparations()) {
LOGGER.info((++counter) + "/" + getPreparations().size() + " calling CH prepare.doWork for " + prepare.getWeighting() + " ... (" + getMemInfo() + ")");
final String name = AbstractWeighting.weightingToFileName(prepare.getWeighting());
LOGGER.info((++counter) + "/" + getPreparations().size() + " calling " +
(prepare.isEdgeBased() ? "edge" : "node") + "-based CH prepare.doWork for " + prepare.getWeighting() + " ... (" + getMemInfo() + ")");
final String name = AbstractWeighting.weightingToFileName(prepare.getWeighting(), prepare.isEdgeBased());
completionService.submit(new Runnable() {
@Override
public void run() {
Expand All @@ -256,17 +296,44 @@ public void run() {
}
}

public void createPreparations(GraphHopperStorage ghStorage, TraversalMode traversalMode) {
if (!isEnabled() || !preparations.isEmpty())
public void createPreparations(GraphHopperStorage ghStorage) {
if (!isEnabled() || !getPreparations().isEmpty())
return;
if (weightings.isEmpty())
if (!hasWeightings())
throw new IllegalStateException("No CH weightings found");

for (Weighting weighting : getWeightings()) {
PrepareContractionHierarchies tmpPrepareCH = new PrepareContractionHierarchies(
new GHDirectory("", DAType.RAM_INT), ghStorage, ghStorage.getGraph(CHGraph.class, weighting), traversalMode);
tmpPrepareCH.setParams(pMap);
addPreparation(tmpPrepareCH);
for (Weighting weighting : nodeBasedWeightings) {
addPreparation(createCHPreparation(ghStorage, weighting, TraversalMode.NODE_BASED));
}
for (Weighting weighting : edgeBasedWeightings) {
addPreparation(createCHPreparation(ghStorage, weighting, TraversalMode.EDGE_BASED_2DIR));
}
}

private PrepareContractionHierarchies createCHPreparation(GraphHopperStorage ghStorage, Weighting weighting,
TraversalMode traversalMode) {
PrepareContractionHierarchies tmpPrepareCH = new PrepareContractionHierarchies(
new GHDirectory("", DAType.RAM_INT), ghStorage, ghStorage.getGraph(CHGraph.class, weighting), traversalMode);
tmpPrepareCH.setParams(pMap);
return tmpPrepareCH;
}

/**
* Determines whether or not edge-based CH will be prepared for the different weightings/encoders.
*/
public enum EdgeBasedCHMode {
/**
* no edge-based CH preparation will be performed
*/
OFF,
/**
* for encoders with enabled turn costs edge-based CH and otherwise node-based CH preparation will be performed
*/
EDGE_OR_NODE,
/**
* for encoders with enabled turn costs edge-based CH will be performed and node-based CH preparation will be
* performed for all encoders
*/
EDGE_AND_NODE
}
}
Expand Up @@ -71,7 +71,7 @@ public class EdgeBasedNodeContractor extends AbstractNodeContractor {
private EdgeExplorer loopAvoidanceOutEdgeExplorer;

// counts the total number of added shortcuts
private long addedShortcutsCount;
private int addedShortcutsCount;

// edge counts used to calculate priority
private int numShortcuts;
Expand Down Expand Up @@ -205,6 +205,11 @@ public int getNumPolledEdges() {
return numPolledEdges;
}

@Override
boolean isEdgeBased() {
return true;
}

public int getNumSearches() {
return numSearches;
}
Expand Down
Expand Up @@ -40,7 +40,7 @@ class NodeBasedNodeContractor extends AbstractNodeContractor {
private CHEdgeExplorer remainingEdgeExplorer;
private IgnoreNodeFilter ignoreNodeFilter;
private DijkstraOneToMany prepareAlgo;
private long addedShortcutsCount;
private int addedShortcutsCount;
private long dijkstraCount;
private StopWatch dijkstraSW = new StopWatch();
// meanDegree is the number of edges / number of nodes ratio of the graph, not really the average degree, because
Expand Down Expand Up @@ -149,6 +149,11 @@ public String getStatisticsString() {
meanDegree, nf(dijkstraCount), prepareAlgo.getMemoryUsageAsString());
}

@Override
boolean isEdgeBased() {
return false;
}

/**
* Searches for shortcuts and calls the given handler on each shortcut that is found. The graph is not directly
* changed by this method.
Expand Down
Expand Up @@ -185,7 +185,7 @@ private void initFromGraph() {
// but we need the additional oldPriorities array to keep the old value which is necessary for the update method
sortedNodes = new GHTreeMapComposed();
oldPriorities = new float[prepareGraph.getNodes()];
nodeContractor = createNodeContractor(ghStorage, traversalMode, pMap);
nodeContractor = createNodeContractor(ghStorage, traversalMode);
nodeContractor.initFromGraph();
}

Expand Down Expand Up @@ -310,7 +310,7 @@ private void contractNodes() {
neighborUpdateSW.start();
float oldPrio = oldPriorities[nn];
float priority = oldPriorities[nn] = calculatePriority(nn);
if (Float.compare(oldPrio, priority) != 0) {
if (priority != oldPrio) {
sortedNodes.update(nn, oldPrio, priority);
updatedNeighors.add(nn);
}
Expand Down Expand Up @@ -393,7 +393,7 @@ public String toString() {
return traversalMode.isEdgeBased() ? "prepare|dijkstrabi|edge|ch" : "prepare|dijkstrabi|ch";
}

private NodeContractor createNodeContractor(Graph graph, TraversalMode traversalMode, PMap pMap) {
private NodeContractor createNodeContractor(Graph graph, TraversalMode traversalMode) {
if (traversalMode.isEdgeBased()) {
TurnWeighting chTurnWeighting = createTurnWeightingForEdgeBased(graph);
return new EdgeBasedNodeContractor(dir, ghStorage, prepareGraph, chTurnWeighting, pMap);
Expand Down
Expand Up @@ -277,7 +277,7 @@ public boolean loadOrDoWork(final StorableProperties properties) {
for (final PrepareLandmarks plm : preparations) {
counter++;
final int tmpCounter = counter;
final String name = AbstractWeighting.weightingToFileName(plm.getWeighting());
final String name = AbstractWeighting.weightingToFileName(plm.getWeighting(), false);
completionService.submit(new Runnable() {
@Override
public void run() {
Expand Down
Expand Up @@ -105,7 +105,7 @@ public String toString() {
// Edge based is not really necessary because when adding turn costs while routing we can still
// use the node based traversal as this is a smaller weight approximation and will still produce correct results
this.traversalMode = TraversalMode.NODE_BASED;
final String name = AbstractWeighting.weightingToFileName(weighting);
final String name = AbstractWeighting.weightingToFileName(weighting, false);
this.landmarkWeightDA = dir.find("landmarks_" + name);

this.landmarks = landmarks;
Expand Down
Expand Up @@ -401,9 +401,7 @@ public void applyWayTags(ReaderWay way, EdgeIteratorState edge) {
* The returned list is never empty.
*/
public List<FlagEncoder> fetchEdgeEncoders() {
List<FlagEncoder> list = new ArrayList<>();
list.addAll(edgeEncoders);
return list;
return new ArrayList<FlagEncoder>(edgeEncoders);
}

public boolean needsTurnCostsSupport() {
Expand Down
Expand Up @@ -92,8 +92,8 @@ static final boolean isValidName(String name) {
/**
* Replaces all characters which are not numbers, characters or underscores with underscores
*/
public static String weightingToFileName(Weighting w) {
return toLowerCase(w.toString()).replaceAll("\\|", "_");
public static String weightingToFileName(Weighting w, boolean edgeBased) {
return toLowerCase(w.toString()).replaceAll("\\|", "_") + (edgeBased ? "_edge" : "_node");
}

@Override
Expand Down

0 comments on commit 60b4da9

Please sign in to comment.