Skip to content

Commit

Permalink
RSPS-1243: Implement fail fast option for matrix calculation (#28)
Browse files Browse the repository at this point in the history
* Temporal changes

* Work in progress

* Add errors

* Add fail fast support for matrix calculation

* Improvement tests

* Fix sonar warnings

* Fix sonar warnings

---------

Co-authored-by: jp-lopez <[email protected]>
  • Loading branch information
HDBandit and jp-lopez authored Apr 19, 2023
1 parent 74f8c3d commit 630bd38
Show file tree
Hide file tree
Showing 11 changed files with 233 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@

import com.carrotsearch.hppc.IntArrayList;

class MultiplePointsNotFoundException extends RuntimeException {
public class MultiplePointsNotFoundException extends RuntimeException {

private final IntArrayList pointsNotFound;

MultiplePointsNotFoundException(IntArrayList pointsNotFound) {
this.pointsNotFound = pointsNotFound;
}

IntArrayList getPointsNotFound() {
public IntArrayList getPointsNotFound() {
return pointsNotFound;
}
}
19 changes: 9 additions & 10 deletions core/src/main/java/com/graphhopper/routing/ViaRouting.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import com.graphhopper.routing.ev.EnumEncodedValue;
import com.graphhopper.routing.ev.RoadClass;
import com.graphhopper.routing.ev.RoadEnvironment;
import com.graphhopper.routing.matrix.MatrixSnapResult;
import com.graphhopper.routing.querygraph.QueryGraph;
import com.graphhopper.routing.util.*;
import com.graphhopper.storage.index.LocationIndex;
Expand All @@ -47,13 +48,9 @@
*/
public class ViaRouting {


/**
* @throws MultiplePointsNotFoundException in case one or more points could not be resolved
*/
public static List<Snap> lookupMatrix(EncodedValueLookup lookup, List<GHPoint> points, EdgeFilter snapFilter,
LocationIndex locationIndex, List<String> snapPreventions, List<String> pointHints,
DirectedEdgeFilter directedSnapFilter, List<Double> headings) {
public static MatrixSnapResult lookupMatrix(boolean failFast, EncodedValueLookup lookup, List<GHPoint> points, EdgeFilter snapFilter,
LocationIndex locationIndex, List<String> snapPreventions, List<String> pointHints,
DirectedEdgeFilter directedSnapFilter, List<Double> headings) {
if (points.size() < 1)
throw new IllegalArgumentException("At least 1 point have to be specified, but was:" + points.size());

Expand Down Expand Up @@ -84,13 +81,15 @@ public static List<Snap> lookupMatrix(EncodedValueLookup lookup, List<GHPoint> p
if (!snap.isValid())
pointsNotFound.add(placeIndex);

snaps.add(snap);
if (snap.isValid())
snaps.add(snap);
}

if (!pointsNotFound.isEmpty())
if (!pointsNotFound.isEmpty() && failFast)
throw new MultiplePointsNotFoundException(pointsNotFound);

return snaps;
return new MatrixSnapResult(snaps,pointsNotFound);

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,9 @@
import com.graphhopper.routing.AlgorithmOptions;
import com.graphhopper.routing.matrix.algorithm.MatrixAlgorithm;
import com.graphhopper.routing.matrix.algorithm.MatrixRoutingAlgorithmFactory;
import com.graphhopper.storage.index.Snap;
import com.graphhopper.util.StopWatch;
import com.graphhopper.util.exceptions.MaximumNodesExceededException;

import java.util.List;

import static com.graphhopper.util.Parameters.Routing.MAX_VISITED_NODES;

public class CHMatrixCalculator implements MatrixCalculator {
Expand All @@ -42,12 +39,12 @@ public CHMatrixCalculator(MatrixRoutingAlgorithmFactory algoFactory, AlgorithmOp
}

@Override
public DistanceMatrix calcMatrix(List<Snap> origins, List<Snap> destinations) {
public DistanceMatrix calcMatrix(MatrixSnapResult origins, MatrixSnapResult destinations) {
MatrixAlgorithm algo = createAlgo();
return calcMatrix(origins, destinations, algo);
}

private DistanceMatrix calcMatrix(List<Snap> origins, List<Snap> destinations, MatrixAlgorithm algo) {
private DistanceMatrix calcMatrix(MatrixSnapResult origins, MatrixSnapResult destinations, MatrixAlgorithm algo) {
StopWatch sw = new StopWatch().start();
DistanceMatrix matrix = algo.calcMatrix(origins, destinations);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.graphhopper.routing.matrix;


import java.util.Arrays;
import com.carrotsearch.hppc.IntArrayList;

import java.util.*;
import java.util.function.Consumer;

/**
* Holds the resulting distance matrix for a given set of
Expand All @@ -14,13 +17,19 @@
*/
public final class DistanceMatrix {

public static final double DISTANCE_SNAP_ERROR_VALUE = -1;
public static final long TIME_SNAP_ERROR_VALUE = -1;

private final int numberOfOrigins;
private final int numberOfDestinations;

private final double[][] distances;

private final long[][] times;

private IntArrayList snapOriginsErrors;
private IntArrayList snapDestinationErrors;

public double[][] getDistances() {
return distances;
}
Expand All @@ -35,13 +44,36 @@ public long[][] getTimes() {
* @param numberOfOrigins The number of origin points (rows)
* @param numberOfDestinations The number of destination points (columns)
*/
public DistanceMatrix(int numberOfOrigins, int numberOfDestinations) {

public DistanceMatrix(int numberOfOrigins, int numberOfDestinations, IntArrayList originsErrors, IntArrayList destinationsErros) {
this.numberOfOrigins = numberOfOrigins;
this.numberOfDestinations = numberOfDestinations;

distances = new double[numberOfOrigins][numberOfDestinations];
times = new long[numberOfOrigins][numberOfDestinations];

this.snapOriginsErrors = originsErrors;
this.snapDestinationErrors = destinationsErros;

for(int i = 0; i < numberOfOrigins; i++){
setSnapErrorsValues(i);
}

}

private void setSnapErrorValue(int origin, int destination){
distances[origin][destination] = DISTANCE_SNAP_ERROR_VALUE;
times[origin][destination] = TIME_SNAP_ERROR_VALUE;
}

private void setSnapErrorsValues(int originIdx){

boolean originError = snapOriginsErrors.contains(originIdx);
for(int i = 0; i < numberOfDestinations; i++){
if(originError || snapDestinationErrors.contains(i)){
setSnapErrorValue(originIdx,i);
}
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class GHMatrixRequest {
private final List<GHPoint> origins = new ArrayList<>();
private final List<GHPoint> destinations = new ArrayList<>();
private final PMap hints = new PMap();
private boolean failFast = false;

/**
* One or more locations to use as the starting point for calculating travel distance and time.
Expand Down Expand Up @@ -68,4 +69,12 @@ public GHMatrixRequest putHint(String fieldName, Object value) {
this.hints.putObject(fieldName, value);
return this;
}

public boolean isFailFast() {
return failFast;
}

public void setFailFast(boolean failFast) {
this.failFast = failFast;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import java.util.List;

public interface MatrixCalculator {
DistanceMatrix calcMatrix(List<Snap> origins, List<Snap> destinations);
DistanceMatrix calcMatrix(MatrixSnapResult origins, MatrixSnapResult destinations);

String getDebugString();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.graphhopper.routing.matrix;

import com.carrotsearch.hppc.IntArrayList;
import com.graphhopper.storage.index.Snap;

import java.util.List;


public class MatrixSnapResult {

List<Snap> snaps;
private IntArrayList pointsNotFound = new IntArrayList();

int size;

public MatrixSnapResult(List<Snap> snaps, IntArrayList pointsNotFound) {
this.snaps = snaps;
this.pointsNotFound = pointsNotFound;
this.size = snaps.size() + pointsNotFound.size();
}

public int size(){
return size;
}

public Snap get(int idx){
return this.snaps.get(idx);
}

public boolean isNotFound(int idx){
return this.getPointsNotFound().contains(idx);
}

public boolean isFound(int idx){
return !isNotFound(idx);
}


public IntArrayList getPointsNotFound() {
return pointsNotFound;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
import com.graphhopper.routing.ViaRouting;
import com.graphhopper.routing.WeightingFactory;
import com.graphhopper.routing.lm.LandmarkStorage;
import com.graphhopper.routing.matrix.DistanceMatrix;
import com.graphhopper.routing.matrix.GHMatrixRequest;
import com.graphhopper.routing.matrix.GHMatrixResponse;
import com.graphhopper.routing.matrix.MatrixCalculator;
import com.graphhopper.routing.matrix.solver.CHMatrixSolver;
import com.graphhopper.routing.matrix.solver.MatrixSolver;
import com.graphhopper.routing.querygraph.QueryGraph;
Expand Down Expand Up @@ -48,21 +44,19 @@ public GHMatrixResponse matrix(GHMatrixRequest request) {
List<Double> headings = new ArrayList<>();
List<String> pointHints = new ArrayList<>();
List<String> snapPreventions = new ArrayList<>();
List<Snap> origins = ViaRouting.lookupMatrix(encodingManager, request.getOrigins(), solver.createSnapFilter(), locationIndex,
snapPreventions, pointHints, directedEdgeFilter, headings);

List<Snap> destinations = ViaRouting.lookupMatrix(encodingManager, request.getDestinations(), solver.createSnapFilter(), locationIndex,
MatrixSnapResult originsResult = ViaRouting.lookupMatrix(request.isFailFast(), encodingManager, request.getOrigins(), solver.createSnapFilter(), locationIndex,
snapPreventions, pointHints, directedEdgeFilter, headings);
MatrixSnapResult destinationsResult = ViaRouting.lookupMatrix(request.isFailFast(), encodingManager, request.getDestinations(), solver.createSnapFilter(), locationIndex,
snapPreventions, pointHints, directedEdgeFilter, headings);

// (base) query graph used to resolve headings, curbsides etc. this is not necessarily the same thing as
// the (possibly implementation specific) query graph used by PathCalculator
List<Snap> allSnaps = new ArrayList<>(origins);
allSnaps.addAll(destinations);
QueryGraph queryGraph = QueryGraph.create(graph, allSnaps);
List<Snap> allCorrectSnaps = new ArrayList<>(originsResult.snaps);
allCorrectSnaps.addAll(destinationsResult.snaps);

QueryGraph queryGraph = QueryGraph.create(graph, allCorrectSnaps);

MatrixCalculator matrixCalculator = solver.createMatrixCalculator(queryGraph);
DistanceMatrix matrix = matrixCalculator.calcMatrix(origins, destinations);
DistanceMatrix matrix = matrixCalculator.calcMatrix(originsResult, destinationsResult);
ghMtxRsp.setMatrix(matrix);

return ghMtxRsp;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,20 +87,22 @@ public boolean accept(RoutingCHEdgeIteratorState edgeState) {
}

@Override
public DistanceMatrix calcMatrix(List<Snap> sources, List<Snap> targets) {
public DistanceMatrix calcMatrix(MatrixSnapResult sources, MatrixSnapResult targets) {

checkAlreadyRun();

int numTargets = targets.size();
int numSources = sources.size();
DistanceMatrix matrix = new DistanceMatrix(numSources, numTargets);
DistanceMatrix matrix = new DistanceMatrix(numSources, numTargets,sources.getPointsNotFound(),targets.getPointsNotFound());

//Backward

int idxTarget = 0;
while (idxTarget < numTargets) {
int closestNode = targets.get(idxTarget).getClosestNode();
findInitialNodesBackward(closestNode, idxTarget,null);
if(targets.isFound(idxTarget)){
int closestNode = targets.get(idxTarget).getClosestNode();
findInitialNodesBackward(closestNode, idxTarget,null);
}
idxTarget++;
}

Expand All @@ -115,14 +117,17 @@ public DistanceMatrix calcMatrix(List<Snap> sources, List<Snap> targets) {
//Forward
int idxSource = 0;
while (idxSource < numSources) {
int closestNode = sources.get(idxSource).getClosestNode();
findInitialNodesForward(closestNode, idxSource,matrix);
if(sources.isFound(idxSource)) {
int closestNode = sources.get(idxSource).getClosestNode();
findInitialNodesForward(closestNode, idxSource, matrix);
}
idxSource++;
}

forward(matrix);

return matrix;

}

protected void checkAlreadyRun() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.graphhopper.routing.matrix.algorithm;

import com.graphhopper.routing.matrix.DistanceMatrix;
import com.graphhopper.routing.matrix.MatrixSnapResult;
import com.graphhopper.storage.index.Snap;

import java.util.List;
Expand All @@ -20,7 +21,8 @@ public interface MatrixAlgorithm {
* @return Returns a row for each origin, with duration/distance info to each destination
* @throws IllegalArgumentException Thrown when origin.size() < 1 or desitnations.size() < 1
*/
DistanceMatrix calcMatrix(List<Snap> origins, List<Snap> destinations);

DistanceMatrix calcMatrix(MatrixSnapResult origins, MatrixSnapResult destinations);

/**
* Limit the search to numberOfNodes. See #681
Expand Down
Loading

0 comments on commit 630bd38

Please sign in to comment.