Search in sources :

Example 1 with Subnetwork

use of com.graphhopper.routing.ev.Subnetwork in project graphhopper by graphhopper.

the class LandmarkStorage method createLandmarks.

/**
 * This method calculates the landmarks and initial weightings to & from them.
 */
public void createLandmarks() {
    if (isInitialized())
        throw new IllegalStateException("Initialize the landmark storage only once!");
    // fill 'from' and 'to' weights with maximum value
    long maxBytes = (long) graph.getNodes() * LM_ROW_LENGTH;
    this.landmarkWeightDA.create(2000);
    this.landmarkWeightDA.ensureCapacity(maxBytes);
    for (long pointer = 0; pointer < maxBytes; pointer += 2) {
        landmarkWeightDA.setShort(pointer, (short) SHORT_INFINITY);
    }
    int[] empty = new int[landmarks];
    Arrays.fill(empty, UNSET_SUBNETWORK);
    landmarkIDs.add(empty);
    byte[] subnetworks = new byte[graph.getNodes()];
    Arrays.fill(subnetworks, (byte) UNSET_SUBNETWORK);
    String snKey = Subnetwork.key(lmConfig.getName());
    // instead of using the subnetworkEnc from PrepareRoutingSubnetworks.
    if (!graph.getEncodingManager().hasEncodedValue(snKey))
        throw new IllegalArgumentException("EncodedValue '" + snKey + "' does not exist. For Landmarks this is " + "currently required (also used in PrepareRoutingSubnetworks). See #2256");
    // Exclude edges that we previously marked in PrepareRoutingSubnetworks to avoid problems like "connection not found".
    final BooleanEncodedValue edgeInSubnetworkEnc = graph.getEncodingManager().getBooleanEncodedValue(snKey);
    final IntHashSet blockedEdges;
    // landmarks for an area like Europe+Asia, which improves the query speed.
    if (areaIndex != null) {
        StopWatch sw = new StopWatch().start();
        blockedEdges = findBorderEdgeIds(areaIndex);
        if (logDetails)
            LOGGER.info("Made " + blockedEdges.size() + " edges inaccessible. Calculated country cut in " + sw.stop().getSeconds() + "s, " + Helper.getMemInfo());
    } else {
        blockedEdges = new IntHashSet();
    }
    EdgeFilter accessFilter = edge -> !edge.get(edgeInSubnetworkEnc) && !blockedEdges.contains(edge.getEdge());
    EdgeFilter tarjanFilter = edge -> accessFilter.accept(edge) && Double.isFinite(weighting.calcEdgeWeightWithAccess(edge, false));
    StopWatch sw = new StopWatch().start();
    ConnectedComponents graphComponents = TarjanSCC.findComponents(graph, tarjanFilter, true);
    if (logDetails)
        LOGGER.info("Calculated " + graphComponents.getComponents().size() + " subnetworks via tarjan in " + sw.stop().getSeconds() + "s, " + Helper.getMemInfo());
    String additionalInfo = "";
    // guess the factor
    if (factor <= 0) {
        // A 'factor' is necessary to store the weight in just a short value but without losing too much precision.
        // This factor is rather delicate to pick, we estimate it from an exploration with some "test landmarks",
        // see estimateMaxWeight. If we pick the distance too big for small areas this could lead to (slightly)
        // suboptimal routes as there will be too big rounding errors. But picking it too small is bad for performance
        // e.g. for Germany at least 1500km is very important otherwise speed is at least twice as slow e.g. for 1000km
        double maxWeight = estimateMaxWeight(graphComponents.getComponents(), accessFilter);
        setMaximumWeight(maxWeight);
        additionalInfo = ", maxWeight:" + maxWeight + " from quick estimation";
    }
    if (logDetails)
        LOGGER.info("init landmarks for subnetworks with node count greater than " + minimumNodes + " with factor:" + factor + additionalInfo);
    int nodes = 0;
    for (IntArrayList subnetworkIds : graphComponents.getComponents()) {
        nodes += subnetworkIds.size();
        if (subnetworkIds.size() < minimumNodes)
            continue;
        if (factor <= 0)
            throw new IllegalStateException("factor wasn't initialized " + factor + ", subnetworks:" + graphComponents.getComponents().size() + ", minimumNodes:" + minimumNodes + ", current size:" + subnetworkIds.size());
        int index = subnetworkIds.size() - 1;
        // ensure start node is reachable from both sides and no subnetwork is associated
        for (; index >= 0; index--) {
            int nextStartNode = subnetworkIds.get(index);
            if (subnetworks[nextStartNode] == UNSET_SUBNETWORK) {
                if (logDetails) {
                    GHPoint p = createPoint(graph, nextStartNode);
                    LOGGER.info("start node: " + nextStartNode + " (" + p + ") subnetwork " + index + ", subnetwork size: " + subnetworkIds.size() + ", " + Helper.getMemInfo() + ((areaIndex == null) ? "" : " area:" + areaIndex.query(p.lat, p.lon)));
                }
                if (createLandmarksForSubnetwork(nextStartNode, subnetworks, accessFilter))
                    break;
            }
        }
        if (index < 0)
            LOGGER.warn("next start node not found in big enough network of size " + subnetworkIds.size() + ", first element is " + subnetworkIds.get(0) + ", " + createPoint(graph, subnetworkIds.get(0)));
    }
    int subnetworkCount = landmarkIDs.size();
    // store all landmark node IDs and one int for the factor itself.
    this.landmarkWeightDA.ensureCapacity(maxBytes + /* landmark weights */
    subnetworkCount * landmarks);
    // calculate offset to point into landmark mapping
    long bytePos = maxBytes;
    for (int[] landmarks : landmarkIDs) {
        for (int lmNodeId : landmarks) {
            landmarkWeightDA.setInt(bytePos, lmNodeId);
            bytePos += 4L;
        }
    }
    landmarkWeightDA.setHeader(0 * 4, graph.getNodes());
    landmarkWeightDA.setHeader(1 * 4, landmarks);
    landmarkWeightDA.setHeader(2 * 4, subnetworkCount);
    if (factor * DOUBLE_MLTPL > Integer.MAX_VALUE)
        throw new UnsupportedOperationException("landmark weight factor cannot be bigger than Integer.MAX_VALUE " + factor * DOUBLE_MLTPL);
    landmarkWeightDA.setHeader(3 * 4, (int) Math.round(factor * DOUBLE_MLTPL));
    // serialize fast byte[] into DataAccess
    subnetworkStorage.create(graph.getNodes());
    for (int nodeId = 0; nodeId < subnetworks.length; nodeId++) {
        subnetworkStorage.setSubnetwork(nodeId, subnetworks[nodeId]);
    }
    if (logDetails)
        LOGGER.info("Finished landmark creation. Subnetwork node count sum " + nodes + " vs. nodes " + graph.getNodes());
    initialized = true;
}
Also used : java.util(java.util) LoggerFactory(org.slf4j.LoggerFactory) IntObjectPredicate(com.carrotsearch.hppc.predicates.IntObjectPredicate) Subnetwork(com.graphhopper.routing.ev.Subnetwork) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) GHUtility(com.graphhopper.util.GHUtility) SPTEntry(com.graphhopper.routing.SPTEntry) SubnetworkStorage(com.graphhopper.routing.subnetwork.SubnetworkStorage) StopWatch(com.graphhopper.util.StopWatch) ConnectedComponents(com.graphhopper.routing.subnetwork.TarjanSCC.ConnectedComponents) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) IntArrayList(com.carrotsearch.hppc.IntArrayList) IntObjectProcedure(com.carrotsearch.hppc.procedures.IntObjectProcedure) ConnectionNotFoundException(com.graphhopper.util.exceptions.ConnectionNotFoundException) com.graphhopper.storage(com.graphhopper.storage) Logger(org.slf4j.Logger) EdgeIteratorState(com.graphhopper.util.EdgeIteratorState) Helper(com.graphhopper.util.Helper) IntHashSet(com.carrotsearch.hppc.IntHashSet) MapEntry(com.graphhopper.coll.MapEntry) BooleanEncodedValue(com.graphhopper.routing.ev.BooleanEncodedValue) DijkstraBidirectionRef(com.graphhopper.routing.DijkstraBidirectionRef) TarjanSCC(com.graphhopper.routing.subnetwork.TarjanSCC) IntObjectMap(com.carrotsearch.hppc.IntObjectMap) Weighting(com.graphhopper.routing.weighting.Weighting) GHPoint(com.graphhopper.util.shapes.GHPoint) ShortestWeighting(com.graphhopper.routing.weighting.ShortestWeighting) com.graphhopper.routing.util(com.graphhopper.routing.util) IntHashSet(com.carrotsearch.hppc.IntHashSet) GHPoint(com.graphhopper.util.shapes.GHPoint) StopWatch(com.graphhopper.util.StopWatch) BooleanEncodedValue(com.graphhopper.routing.ev.BooleanEncodedValue) ConnectedComponents(com.graphhopper.routing.subnetwork.TarjanSCC.ConnectedComponents) IntArrayList(com.carrotsearch.hppc.IntArrayList) GHPoint(com.graphhopper.util.shapes.GHPoint)

Aggregations

IntArrayList (com.carrotsearch.hppc.IntArrayList)1 IntHashSet (com.carrotsearch.hppc.IntHashSet)1 IntObjectMap (com.carrotsearch.hppc.IntObjectMap)1 IntObjectPredicate (com.carrotsearch.hppc.predicates.IntObjectPredicate)1 IntObjectProcedure (com.carrotsearch.hppc.procedures.IntObjectProcedure)1 MapEntry (com.graphhopper.coll.MapEntry)1 DijkstraBidirectionRef (com.graphhopper.routing.DijkstraBidirectionRef)1 SPTEntry (com.graphhopper.routing.SPTEntry)1 BooleanEncodedValue (com.graphhopper.routing.ev.BooleanEncodedValue)1 Subnetwork (com.graphhopper.routing.ev.Subnetwork)1 SubnetworkStorage (com.graphhopper.routing.subnetwork.SubnetworkStorage)1 TarjanSCC (com.graphhopper.routing.subnetwork.TarjanSCC)1 ConnectedComponents (com.graphhopper.routing.subnetwork.TarjanSCC.ConnectedComponents)1 com.graphhopper.routing.util (com.graphhopper.routing.util)1 ShortestWeighting (com.graphhopper.routing.weighting.ShortestWeighting)1 Weighting (com.graphhopper.routing.weighting.Weighting)1 com.graphhopper.storage (com.graphhopper.storage)1 EdgeIteratorState (com.graphhopper.util.EdgeIteratorState)1 GHUtility (com.graphhopper.util.GHUtility)1 Helper (com.graphhopper.util.Helper)1