use of gnu.trove.map.TIntIntMap in project OpenTripPlanner by opentripplanner.
the class RepeatedRaptorProfileRouter method findInitialStops.
/**
* Find all transit stops accessible by streets around the origin, leaving behind a shortest path tree of the
* reachable area in the field preTransitSpt.
*
* @param data the raptor data table to use. If this is null (i.e. there is no transit) range is extended,
* and we don't care if we actually find any stops, we just want the tree of on-street distances.
*/
@VisibleForTesting
public TIntIntMap findInitialStops(boolean dest, RaptorWorkerData data) {
LOG.info("Finding initial stops");
double lat = dest ? request.toLat : request.fromLat;
double lon = dest ? request.toLon : request.fromLon;
QualifiedModeSet modes = dest ? request.egressModes : request.accessModes;
RoutingRequest rr = new RoutingRequest(modes);
rr.batch = true;
rr.from = new GenericLocation(lat, lon);
// rr.walkSpeed = request.walkSpeed;
rr.to = rr.from;
rr.setRoutingContext(graph);
rr.dateTime = request.date.toDateMidnight(DateTimeZone.forTimeZone(graph.getTimeZone())).getMillis() / 1000 + request.fromTime;
rr.walkSpeed = request.walkSpeed;
rr.bikeSpeed = request.bikeSpeed;
if (data == null) {
// Non-transit mode. Search out to the full 120 minutes.
// Should really use directModes.
rr.worstTime = rr.dateTime + RaptorWorker.MAX_DURATION;
rr.dominanceFunction = new DominanceFunction.EarliestArrival();
} else {
// Transit mode, limit pre-transit travel.
if (rr.modes.contains(TraverseMode.BICYCLE)) {
rr.dominanceFunction = new DominanceFunction.EarliestArrival();
rr.worstTime = rr.dateTime + request.maxBikeTime * 60;
} else {
// We use walk-distance limiting and a least-walk dominance function in order to be consistent with egress walking
// which is implemented this way because walk times can change when walk speed changes. Also, walk times are floating
// point and can change slightly when streets are split. Street lengths are internally fixed-point ints, which do not
// suffer from roundoff. Great care is taken when splitting to preserve sums.
// When cycling, this is not an issue; we already have an explicitly asymmetrical search (cycling at the origin, walking at the destination),
// so we need not preserve symmetry.
// We use the max walk time for the search at the origin, but we clamp it to MAX_WALK_METERS so that we don;t
// have every transit stop in the state as an initial transit stop if someone sets max walk time to four days,
// and so that symmetry is preserved.
// FIXME kind of arbitrary
rr.maxWalkDistance = Math.min(request.maxWalkTime * 60 * request.walkSpeed, GraphIndex.MAX_WALK_METERS);
rr.softWalkLimiting = false;
rr.dominanceFunction = new DominanceFunction.LeastWalk();
}
}
rr.numItineraries = 1;
rr.longDistance = true;
AStar aStar = new AStar();
preTransitSpt = aStar.getShortestPathTree(rr, 5);
// otherwise return null and leave preTransitSpt around for later use.
if (data != null) {
TIntIntMap accessTimes = data.findStopsNear(preTransitSpt, graph, rr.modes.contains(TraverseMode.BICYCLE), request.walkSpeed);
LOG.info("Found {} transit stops", accessTimes.size());
return accessTimes;
} else {
return null;
}
}
use of gnu.trove.map.TIntIntMap in project OpenTripPlanner by opentripplanner.
the class InitialStopsTest method testInitialStopWalkSpeedIncrease.
/**
* Test that increasing the walk speed on a walk-to-transit search
* a) decreases or leaves unchanged all access times.
* b) allows access to a superset of the originally accessible stops.
* c) decreases at least some access times.
*
* There was once a bug where bike speed was not correctly applied because we used the distance not the speed.
*/
@Test
public void testInitialStopWalkSpeedIncrease() throws Exception {
Graph g = buildGraphNoTransit();
addRegularStopGrid(g);
addTransitMultipleLines(g);
link(g);
g.index(new DefaultStreetVertexIndexFactory());
ProfileRequest req = new ProfileRequest();
req.fromLon = req.toLon = -83.0118;
req.fromLat = req.toLat = 39.9908;
req.date = new LocalDate(2015, 9, 17);
req.bikeSpeed = 4.1f;
req.walkSpeed = 1.3f;
req.fromTime = 7 * 3600;
req.toTime = 9 * 3600;
req.maxBikeTime = 20;
req.maxWalkTime = 20;
req.transitModes = new TraverseModeSet("TRANSIT");
req.accessModes = req.egressModes = req.directModes = new QualifiedModeSet("WALK");
RaptorWorkerData data = RepeatedRaptorProfileRouter.getRaptorWorkerData(req, g, null, new TaskStatistics());
assertNotNull(data);
RepeatedRaptorProfileRouter rrpr = new RepeatedRaptorProfileRouter(g, req);
TIntIntMap initialStops1 = rrpr.findInitialStops(false, data);
assertFalse(initialStops1.isEmpty());
// let's get crazy, set walk speed really high.
req.walkSpeed = 25f;
data = RepeatedRaptorProfileRouter.getRaptorWorkerData(req, g, null, new TaskStatistics());
assertNotNull(data);
rrpr = new RepeatedRaptorProfileRouter(g, req);
TIntIntMap initialStops2 = rrpr.findInitialStops(false, data);
// we should find decreases to at least some stops
boolean foundDecreases = false;
for (TIntIntIterator it = initialStops1.iterator(); it.hasNext(); ) {
it.advance();
// the reached stops from the faster search should be a superset of the reached stops from the slower search
assertTrue(initialStops2.containsKey(it.key()));
assertTrue("Found increase in travel time to stop", initialStops2.get(it.key()) <= it.value());
foundDecreases = foundDecreases || initialStops2.get(it.key()) < it.value() - EPSILON;
}
assertTrue("No decreases were found due to increased walk speed", foundDecreases);
}
use of gnu.trove.map.TIntIntMap in project OpenTripPlanner by opentripplanner.
the class InitialStopsTest method testInitialStopBikeSpeedIncrease.
/**
* Test that increasing the bike speed on a bike-to-transit search
* a) decreases or leaves unchanged all access times.
* b) allows access to a superset of the originally accessible stops.
*
* There was once a bug where bike speed was not correctly applied because we used the distance not the speed.
*/
@Test
public void testInitialStopBikeSpeedIncrease() throws Exception {
Graph g = buildGraphNoTransit();
addRegularStopGrid(g);
addTransitMultipleLines(g);
link(g);
g.index(new DefaultStreetVertexIndexFactory());
ProfileRequest req = new ProfileRequest();
req.fromLon = req.toLon = -83.0118;
req.fromLat = req.toLat = 39.9908;
req.date = new LocalDate(2015, 9, 17);
req.bikeSpeed = 4.1f;
req.walkSpeed = 1.3f;
req.fromTime = 7 * 3600;
req.toTime = 9 * 3600;
req.maxBikeTime = 20;
req.transitModes = new TraverseModeSet("TRANSIT");
req.accessModes = req.egressModes = req.directModes = new QualifiedModeSet("BICYCLE");
RaptorWorkerData data = RepeatedRaptorProfileRouter.getRaptorWorkerData(req, g, null, new TaskStatistics());
assertNotNull(data);
RepeatedRaptorProfileRouter rrpr = new RepeatedRaptorProfileRouter(g, req);
TIntIntMap initialStops1 = rrpr.findInitialStops(false, data);
assertFalse(initialStops1.isEmpty());
// let's get crazy, set bike speed really high.
req.bikeSpeed = 25f;
data = RepeatedRaptorProfileRouter.getRaptorWorkerData(req, g, null, new TaskStatistics());
assertNotNull(data);
rrpr = new RepeatedRaptorProfileRouter(g, req);
TIntIntMap initialStops2 = rrpr.findInitialStops(false, data);
// we should find decreases to at least some stops
boolean foundDecreases = false;
for (TIntIntIterator it = initialStops1.iterator(); it.hasNext(); ) {
it.advance();
// the reached stops from the faster search should be a superset of the reached stops from the slower search
assertTrue(initialStops2.containsKey(it.key()));
assertTrue("Found increase in travel time to stop", initialStops2.get(it.key()) <= it.value());
foundDecreases = foundDecreases || initialStops2.get(it.key()) < it.value() - EPSILON;
}
assertTrue(foundDecreases);
}
use of gnu.trove.map.TIntIntMap in project BiomeTweaker by superckl.
the class PropertyDecorationPerChunk method get.
@Override
public Integer get(final Object obj) throws IllegalStateException, IllegalArgumentException {
if (!(obj instanceof Biome))
throw new IllegalArgumentException("Passed object is not an instance of Biome!");
if (!BiomeEventHandler.getDecorationsPerChunk().containsKey(this.type))
throw new IllegalStateException("Decoration " + this.type.name() + " has not been set for biome" + ((Biome) obj).getBiomeName() + "!");
final int id = Biome.getIdForBiome((Biome) obj);
final TIntIntMap map = BiomeEventHandler.getDecorationsPerChunk().get(this.type);
if (!map.containsKey(id))
throw new IllegalStateException("Decoration " + this.type.name() + " has not been set for biome" + ((Biome) obj).getBiomeName() + "!");
return map.get(id);
}
use of gnu.trove.map.TIntIntMap in project OpenTripPlanner by opentripplanner.
the class RaptorWorker method runRaptor.
/**
* @param accessTimes a map from transit stops to the time it takes to reach those stops
* @param nonTransitTimes the time to reach all targets without transit. Targets can be vertices or points/samples.
*/
public PropagatedTimesStore runRaptor(Graph graph, TIntIntMap accessTimes, int[] nonTransitTimes, TaskStatistics ts) {
long beginCalcTime = System.currentTimeMillis();
TIntIntMap initialStops = new TIntIntHashMap();
TIntIntIterator initialIterator = accessTimes.iterator();
while (initialIterator.hasNext()) {
initialIterator.advance();
int stopIndex = initialIterator.key();
int accessTime = initialIterator.value();
initialStops.put(stopIndex, accessTime);
}
PropagatedTimesStore propagatedTimesStore = new PropagatedTimesStore(graph, this.req, data.nTargets);
// optimization: if no schedules, only run Monte Carlo
int fromTime = req.fromTime;
int monteCarloDraws = MONTE_CARLO_COUNT_PER_MINUTE;
if (!data.hasSchedules) {
// only do one iteration
fromTime = req.toTime - 60;
monteCarloDraws = TOTAL_MONTE_CARLO_COUNT;
}
// if no frequencies, don't run Monte Carlo
int iterations = (req.toTime - fromTime - 60) / 60 + 1;
// if we multiply when we're not doing monte carlo, we'll end up with too many iterations.
if (data.hasFrequencies)
// we add 2 because we do two "fake" draws where we do min or max instead of a monte carlo draw
iterations *= (monteCarloDraws + 2);
ts.searchCount = iterations;
// Iterate backward through minutes (range-raptor) taking a snapshot of router state after each call
int[][] timesAtTargetsEachIteration = new int[iterations][data.nTargets];
// for each iteration, whether it is the result of a schedule or Monte Carlo search, or whether it is an extrema.
// extrema are not included in averages.
boolean[] includeIterationInAverages = new boolean[iterations];
Arrays.fill(includeIterationInAverages, true);
// TODO don't hardwire timestep below
ts.timeStep = 60;
// times at targets from scheduled search
int[] scheduledTimesAtTargets = new int[data.nTargets];
Arrays.fill(scheduledTimesAtTargets, UNREACHED);
// current iteration
int iteration = 0;
// FIXME this should be changed to tolerate a zero-width time range
for (int departureTime = req.toTime - 60, n = 0; departureTime >= fromTime; departureTime -= 60, n++) {
if (n % 15 == 0) {
LOG.info("minute {}", n);
}
// run the scheduled search
this.runRaptorScheduled(initialStops, departureTime);
this.doPropagation(bestNonTransferTimes, scheduledTimesAtTargets, departureTime);
// walking a block
for (int i = 0; i < scheduledTimesAtTargets.length; i++) {
if (nonTransitTimes[i] != UNREACHED && nonTransitTimes[i] + departureTime < scheduledTimesAtTargets[i])
scheduledTimesAtTargets[i] = nonTransitTimes[i] + departureTime;
}
// run the frequency searches
if (data.hasFrequencies) {
for (int i = 0; i < monteCarloDraws + 2; i++) {
// make copies for just this search. We need copies because we can't use dynamic
// programming/range-raptor with randomized schedules
int[] bestTimesCopy = Arrays.copyOf(bestTimes, bestTimes.length);
int[] bestNonTransferTimesCopy = Arrays.copyOf(bestNonTransferTimes, bestNonTransferTimes.length);
int[] previousPatternsCopy = Arrays.copyOf(previousPatterns, previousPatterns.length);
// special cases: calculate the best and the worst cases as well
// Note that this (intentionally) does not affect searches where the user has requested
// an assumption other than RANDOM, or stops with transfer rules.
RaptorWorkerTimetable.BoardingAssumption requestedBoardingAssumption = req.boardingAssumption;
if (i == 0 && req.boardingAssumption == RaptorWorkerTimetable.BoardingAssumption.RANDOM) {
req.boardingAssumption = RaptorWorkerTimetable.BoardingAssumption.WORST_CASE;
// don't include extrema in averages
includeIterationInAverages[iteration] = false;
} else if (i == 1 && req.boardingAssumption == RaptorWorkerTimetable.BoardingAssumption.RANDOM) {
req.boardingAssumption = RaptorWorkerTimetable.BoardingAssumption.BEST_CASE;
// don't include extrema in averages
includeIterationInAverages[iteration] = false;
} else if (requestedBoardingAssumption == RaptorWorkerTimetable.BoardingAssumption.RANDOM)
// use a new Monte Carlo draw each time
// included in averages by default
offsets.randomize();
this.runRaptorFrequency(departureTime, bestTimesCopy, bestNonTransferTimesCopy, previousPatternsCopy);
req.boardingAssumption = requestedBoardingAssumption;
// do propagation
int[] frequencyTimesAtTargets = timesAtTargetsEachIteration[iteration++];
System.arraycopy(scheduledTimesAtTargets, 0, frequencyTimesAtTargets, 0, scheduledTimesAtTargets.length);
// updates timesAtTargetsEachIteration directly because it has a reference into the array.
this.doPropagation(bestNonTransferTimesCopy, frequencyTimesAtTargets, departureTime);
// convert to elapsed time
for (int t = 0; t < frequencyTimesAtTargets.length; t++) {
if (frequencyTimesAtTargets[t] != UNREACHED)
frequencyTimesAtTargets[t] -= departureTime;
}
}
} else {
final int dt = departureTime;
timesAtTargetsEachIteration[iteration++] = IntStream.of(scheduledTimesAtTargets).map(i -> i != UNREACHED ? i - dt : i).toArray();
}
}
// iteration should be incremented past end of array by ++ in assignment above
if (iteration != iterations)
throw new IllegalStateException("Iterations did not completely fill output array");
long calcTime = System.currentTimeMillis() - beginCalcTime;
LOG.info("calc time {}sec", calcTime / 1000.0);
LOG.info(" propagation {}sec", totalPropagationTime / 1000.0);
LOG.info(" raptor {}sec", (calcTime - totalPropagationTime) / 1000.0);
ts.propagation = (int) totalPropagationTime;
ts.transitSearch = (int) (calcTime - totalPropagationTime);
// dumpVariableByte(timesAtTargetsEachMinute);
// we can use min_max here as we've also run it once with best case and worst case board,
// so the best and worst cases are meaningful.
propagatedTimesStore.setFromArray(timesAtTargetsEachIteration, includeIterationInAverages, PropagatedTimesStore.ConfidenceCalculationMethod.MIN_MAX);
return propagatedTimesStore;
}
Aggregations