use of com.carrotsearch.hppc.cursors.IntCursor in project graphhopper by graphhopper.
the class EdgeBasedTarjanSCCTest method withTurnRestriction.
@Test
public void withTurnRestriction() {
GraphHopperStorage g = new GraphBuilder(em).create();
// here 0-1-2-3 would be a circle and thus belong to same connected component. but if there is a
// turn restriction for going 0->2->3 this splits the graph into multiple components
// 0->1
// | |
// 3<-2->4
// edge-keys 0,1
GHUtility.setSpeed(60, true, false, encoder, g.edge(0, 1).setDistance(1));
// edge-keys 2,3
GHUtility.setSpeed(60, true, false, encoder, g.edge(1, 2).setDistance(1));
// edge-keys 4,5
GHUtility.setSpeed(60, true, false, encoder, g.edge(2, 3).setDistance(1));
// edge-keys 6,7
GHUtility.setSpeed(60, true, false, encoder, g.edge(3, 0).setDistance(1));
// edge-keys 8,9
GHUtility.setSpeed(60, true, false, encoder, g.edge(2, 4).setDistance(1));
// first lets check what happens without turn costs
ConnectedComponents result = EdgeBasedTarjanSCC.findComponentsRecursive(g, fwdAccessFilter, false);
assertEquals(7, result.getTotalComponents());
assertEquals(1, result.getComponents().size());
assertEquals(IntArrayList.from(6, 4, 2, 0), result.getBiggestComponent());
assertEquals(6, result.getSingleEdgeComponents().cardinality());
for (IntCursor c : IntArrayList.from(1, 3, 5, 7, 8, 9)) {
assertTrue(result.getSingleEdgeComponents().get(c.value));
}
// now lets try with a restricted turn
result = EdgeBasedTarjanSCC.findComponentsRecursive(g, (prev, edge) -> fwdAccessFilter.accept(prev, edge) && !(prev == 1 && edge.getBaseNode() == 2 && edge.getEdge() == 2), false);
// none of the edges are strongly connected anymore!
assertEquals(10, result.getTotalComponents());
assertEquals(0, result.getComponents().size());
assertEquals(IntArrayList.from(), result.getBiggestComponent());
assertEquals(10, result.getSingleEdgeComponents().cardinality());
for (IntCursor c : IntArrayList.from(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)) {
assertTrue(result.getSingleEdgeComponents().get(c.value));
}
}
use of com.carrotsearch.hppc.cursors.IntCursor in project graphhopper by graphhopper.
the class EdgeBasedTarjanSCCTest method biggerGraph.
@Test
public void biggerGraph() {
GraphHopperStorage g = new GraphBuilder(em).create();
// this graph has two bigger components (nodes 0, 1, 3 and the others). Still there are some (directed) edges
// that do not belong to these components but rather represent isolated single-edge components
// 0 - 1 < 2 - 4 > 5
// | | |
// | \< 6 - 7
// 3 \- 8
// edge-keys 0,1
GHUtility.setSpeed(60, true, true, encoder, g.edge(0, 1).setDistance(1));
// edge-keys 2,3
GHUtility.setSpeed(60, true, false, encoder, g.edge(2, 1).setDistance(1));
// edge-keys 4,5
GHUtility.setSpeed(60, true, true, encoder, g.edge(1, 3).setDistance(1));
// edge-keys 6,7
GHUtility.setSpeed(60, true, true, encoder, g.edge(2, 4).setDistance(1));
// edge-keys 8,9
GHUtility.setSpeed(60, true, false, encoder, g.edge(6, 2).setDistance(1));
// edge-keys 10,11
GHUtility.setSpeed(60, true, false, encoder, g.edge(4, 5).setDistance(1));
// edge-keys 12,13
GHUtility.setSpeed(60, true, true, encoder, g.edge(5, 7).setDistance(1));
// edge-keys 14,15
GHUtility.setSpeed(60, true, true, encoder, g.edge(6, 7).setDistance(1));
// edge-keys 16,17
GHUtility.setSpeed(60, true, true, encoder, g.edge(6, 8).setDistance(1));
ConnectedComponents result = EdgeBasedTarjanSCC.findComponentsRecursive(g, fwdAccessFilter, false);
assertEquals(18, result.getEdgeKeys());
assertEquals(6, result.getTotalComponents());
assertEquals(2, result.getComponents().size());
assertEquals(result.getComponents().get(1), result.getBiggestComponent());
assertEquals(IntArrayList.from(1, 5, 4, 0), result.getComponents().get(0));
assertEquals(IntArrayList.from(7, 8, 13, 14, 17, 16, 15, 12, 10, 6), result.getComponents().get(1));
assertEquals(4, result.getSingleEdgeComponents().cardinality());
for (IntCursor c : IntArrayList.from(9, 2, 3, 11)) {
assertTrue(result.getSingleEdgeComponents().get(c.value));
}
}
use of com.carrotsearch.hppc.cursors.IntCursor in project graphhopper by graphhopper.
the class TarjanSCCTest method buildComponentSet.
/**
* Takes a list of arrays like [[0,1,3],[2,4],[6]] and turns it into a Set like
* {[0:[0,1,3], 1:[0,1,3], 2:[2,4], 3:[0,1,3], 4:[2,4], 6:[6]}
*/
public static Set<IntWithArray> buildComponentSet(List<IntArrayList> arrays) {
Set<IntWithArray> result = new HashSet<>();
for (IntArrayList c : arrays) {
c.trimToSize();
Arrays.sort(c.buffer);
for (IntCursor cursor : c) {
result.add(new IntWithArray(cursor.value, c));
}
}
return result;
}
use of com.carrotsearch.hppc.cursors.IntCursor in project mosaic by eclipse.
the class AbstractCamvitChoiceRouting method determineRelevantEdges.
/**
* Collects all edges which have been traversed by both forward and backward path searches. All
* edges receive a weighting depending on their distances towards the target and source node.
* Furthermore, edges which are far away from the best path are ignored to speed up the search.
*
* @param optimalWeight the weight of the optimal path.
*/
private void determineRelevantEdges(double optimalWeight) {
relevantEdgesQ = new PriorityQueue<>(Math.max(1, shortestWeightsFrom.size() / 10), Comparator.comparingDouble(o -> o.rating));
relevantEdgesIDs = new HashSet<>();
double maxWeight = optimalWeight * (1.0d + constraintMaxStretch);
for (IntCursor key : shortestWeightsFrom.keys()) {
SPTEntry edge = shortestWeightsFrom.get(key.value);
if (edge.parent != null) {
SPTEntry edgeOfTargetTree = shortestWeightsTo.get(key.value);
if (edgeOfTargetTree != null && edgeOfTargetTree.edge == edge.edge && edge.adjNode != edgeOfTargetTree.adjNode) {
// create a new relevant edge if it has been found in both search trees
// the rating is composed by the distances of the edge towards source and target
RelEdge relEdge = new RelEdge();
relEdge.fwd = edge;
relEdge.bwd = edgeOfTargetTree;
relEdge.rating = (edgeOfTargetTree.parent != null) ? edge.weight + edgeOfTargetTree.parent.weight : edgeOfTargetTree.weight + edge.parent.weight;
if (relEdge.rating < maxWeight && relEdge.fwd.weight < Double.MAX_VALUE && relEdge.bwd.weight < Double.MAX_VALUE) {
relevantEdgesQ.add(relEdge);
relevantEdgesIDs.add(key.value);
}
}
}
}
}
use of com.carrotsearch.hppc.cursors.IntCursor in project graphhopper by graphhopper.
the class PrepareContractionHierarchies method contractNodesUsingHeuristicNodeOrdering.
private void contractNodesUsingHeuristicNodeOrdering() {
StopWatch sw = new StopWatch().start();
logger.info("Building initial queue of nodes to be contracted: {} nodes, {}", nodes, getMemInfo());
// note that we update the priorities before preparing the node contractor. this does not make much sense,
// but has always been like that and changing it would possibly require retuning the contraction parameters
updatePrioritiesOfRemainingNodes();
logger.info("Finished building queue, took: {}s, {}", sw.stop().getSeconds(), getMemInfo());
final int initSize = sortedNodes.size();
int level = 0;
checkCounter = 0;
final long logSize = params.getLogMessagesPercentage() == 0 ? Long.MAX_VALUE : Math.round(Math.max(10, initSize * (params.getLogMessagesPercentage() / 100d)));
// specifies after how many contracted nodes the queue of remaining nodes is rebuilt. this takes time but the
// more often we do this the more up-to-date the node priorities will be
// todo: instead of using a fixed interval size maybe try adjusting it depending on the number of remaining
// nodes ?
final long periodicUpdatesCount = params.getPeriodicUpdatesPercentage() == 0 ? Long.MAX_VALUE : Math.round(Math.max(10, initSize * (params.getPeriodicUpdatesPercentage() / 100d)));
int updateCounter = 0;
// enable lazy updates for last x percentage of nodes. lazy updates make preparation slower but potentially
// keep node priorities more up to date, possibly resulting in a better preparation.
final long lastNodesLazyUpdates = Math.round(initSize * (params.getLastNodesLazyUpdatePercentage() / 100d));
// according to paper "Polynomial-time Construction of Contraction Hierarchies for Multi-criteria Objectives" by Funke and Storandt
// we don't need to wait for all nodes to be contracted
final long nodesToAvoidContract = Math.round(initSize * ((100 - params.getNodesContractedPercentage()) / 100d));
// Recompute priority of (the given percentage of) uncontracted neighbors. Doing neighbor updates takes additional
// time during preparation but keeps node priorities more up to date. this potentially improves query time and
// reduces number of shortcuts.
final boolean neighborUpdate = (params.getNeighborUpdatePercentage() != 0);
while (!sortedNodes.isEmpty()) {
stopIfInterrupted();
// periodically update priorities of ALL nodes
if (checkCounter > 0 && checkCounter % periodicUpdatesCount == 0) {
updatePrioritiesOfRemainingNodes();
updateCounter++;
if (sortedNodes.isEmpty())
throw new IllegalStateException("Cannot prepare as no unprepared nodes where found. Called preparation twice?");
}
if (checkCounter % logSize == 0) {
logHeuristicStats(updateCounter);
}
checkCounter++;
int polledNode = sortedNodes.poll();
if (!sortedNodes.isEmpty() && sortedNodes.size() < lastNodesLazyUpdates) {
lazyUpdateSW.start();
float priority = calculatePriority(polledNode);
if (priority > sortedNodes.peekValue()) {
// current node got more important => insert as new value and contract it later
sortedNodes.push(polledNode, priority);
lazyUpdateSW.stop();
continue;
}
lazyUpdateSW.stop();
}
// contract node v!
IntContainer neighbors = contractNode(polledNode, level);
level++;
if (sortedNodes.size() < nodesToAvoidContract)
// skipped nodes are already set to maxLevel
break;
int neighborCount = 0;
// there might be multiple edges going to the same neighbor nodes -> only calculate priority once per node
for (IntCursor neighbor : neighbors) {
if (neighborUpdate && (params.getMaxNeighborUpdates() < 0 || neighborCount < params.getMaxNeighborUpdates()) && rand.nextInt(100) < params.getNeighborUpdatePercentage()) {
neighborCount++;
neighborUpdateSW.start();
float priority = calculatePriority(neighbor.value);
sortedNodes.update(neighbor.value, priority);
neighborUpdateSW.stop();
}
}
}
nodeContractor.finishContraction();
logHeuristicStats(updateCounter);
logger.info("new shortcuts: " + nf(nodeContractor.getAddedShortcutsCount()) + ", initSize:" + nf(initSize) + ", " + chConfig.getWeighting() + ", periodic:" + params.getPeriodicUpdatesPercentage() + ", lazy:" + params.getLastNodesLazyUpdatePercentage() + ", neighbor:" + params.getNeighborUpdatePercentage() + ", " + getTimesAsString() + ", lazy-overhead: " + (int) (100 * ((checkCounter / (double) initSize) - 1)) + "%" + ", " + Helper.getMemInfo());
// Preparation works only once so we can release temporary data.
// The preparation object itself has to be intact to create the algorithm.
_close();
}
Aggregations