All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.transit.raptor.rangeraptor.standard.StdRangeRaptorWorkerState Maven / Gradle / Ivy

There is a newer version: 2.5.0
Show newest version
package org.opentripplanner.transit.raptor.rangeraptor.standard;


import org.opentripplanner.transit.raptor.api.path.Path;
import org.opentripplanner.transit.raptor.api.transit.IntIterator;
import org.opentripplanner.transit.raptor.api.transit.RaptorTransfer;
import org.opentripplanner.transit.raptor.api.transit.RaptorTripSchedule;
import org.opentripplanner.transit.raptor.rangeraptor.standard.besttimes.BestTimes;
import org.opentripplanner.transit.raptor.rangeraptor.transit.TransitCalculator;
import org.opentripplanner.transit.raptor.util.BitSetIterator;

import java.util.Collection;
import java.util.Iterator;


/**
 * Tracks the state of a standard Range Raptor search, specifically the best arrival times at each transit stop
 * at the end of a particular round, along with associated data to reconstruct paths etc.
 * 

* This is grouped into a separate class (rather than just having the fields in the raptor worker class) because we * want to separate the logic of maintaining stop arrival state and performing the steps of the algorithm. This * also make it possible to have more than one state implementation, which have ben used in the past to test different * memory optimizations. *

* Note that this represents the entire state of the Range Raptor search for all rounds. The {@code stopArrivalsState} * implementation can be swapped to achieve different results. * * @param The TripSchedule type defined by the user of the raptor API. */ public final class StdRangeRaptorWorkerState implements StdWorkerState { /** * The best times to reach each stop, whether via a transfer or via transit directly. * This is the bare minimum to execute the algorithm. */ private final BestTimes bestTimes; /** * Track the stop arrivals to be able to return some kind of result. Depending on the * desired result, different implementation is injected. */ private final StopArrivalsState stopArrivalsState; /** * The list of egress stops, can be used to terminate the search when the stops are reached. */ private final ArrivedAtDestinationCheck arrivedAtDestinationCheck; /** * The calculator is used to calculate transit related times/events like access arrival time. */ private final TransitCalculator calculator; /** * create a BestTimes Range Raptor State for given context. */ public StdRangeRaptorWorkerState( TransitCalculator calculator, BestTimes bestTimes, StopArrivalsState stopArrivalsState, ArrivedAtDestinationCheck arrivedAtDestinationCheck ) { this.calculator = calculator; this.bestTimes = bestTimes; this.stopArrivalsState = stopArrivalsState; this.arrivedAtDestinationCheck = arrivedAtDestinationCheck; } @Override public final void setInitialTimeForIteration(RaptorTransfer accessEgressLeg, int departureTime) { int durationInSeconds = accessEgressLeg.durationInSeconds(); int stop = accessEgressLeg.stop(); // The time of arrival at the given stop for the current iteration // (or departure time at the last stop if we search backwards). int arrivalTime = calculator.plusDuration(departureTime, durationInSeconds); bestTimes.setAccessStopTime(stop, arrivalTime, accessEgressLeg.stopReachedOnBoard()); stopArrivalsState.setAccess(stop, arrivalTime, accessEgressLeg); } @Override public final boolean isNewRoundAvailable() { return bestTimes.isCurrentRoundUpdated(); } @Override public final BitSetIterator stopsTouchedByTransitCurrentRound() { return bestTimes.transitStopsReachedCurrentRound(); } @Override public final IntIterator stopsTouchedPreviousRound() { return bestTimes.stopsReachedLastRound(); } @Override public final boolean isStopReachedInPreviousRound(int stop) { return bestTimes.isStopReachedLastRound(stop); } /** * Return the "best time" found in the previous round. This is used to calculate the board/alight * time in the next round. *

* PLEASE OVERRIDE! *

* The implementation here is not correct - please override if you plan to use any result paths * or "rounds" as "number of transfers". The implementation is OK if the only thing you care * about is the "arrival time". */ @Override public int bestTimePreviousRound(int stop) { // This is a simplification, *bestTimes* might get updated during the current round; // Hence leading to a new boarding from the same stop in the same round. // If we do not count rounds or track paths, this is OK. But be sure to override this // method with the best time from the previous round if you care about number of // transfers and results paths. return stopArrivalsState.bestTimePreviousRound(stop); } /** * Set the time at a transit stop iff it is optimal. This sets both the bestTime and the transitTime. */ @Override public final void transitToStop(int stop, int alightTime, int boardStop, int boardTime, T trip) { if (exceedsTimeLimit(alightTime)) { return; } if (newTransitBestTime(stop, alightTime)) { // transitTimes upper bounds bestTimes final boolean newBestOverall = newOverallBestTime(stop, alightTime); stopArrivalsState.setNewBestTransitTime(stop, alightTime, trip, boardStop, boardTime, newBestOverall); } else { stopArrivalsState.rejectNewBestTransitTime(stop, alightTime, trip, boardStop, boardTime); } } /** * Set the arrival time at all transit stop if time is optimal for the given list of transfers. */ @Override public final void transferToStops(int fromStop, Iterator transfers) { int arrivalTimeTransit = bestTimes.transitTime(fromStop); while (transfers.hasNext()) { transferToStop(arrivalTimeTransit, fromStop, transfers.next()); } } @Override public Collection> extractPaths() { return stopArrivalsState.extractPaths(); } private void transferToStop(int arrivalTimeTransit, int fromStop, RaptorTransfer transferLeg) { // Use the calculator to make sure the calculation is done correct for a normal // forward search and a reverse search. final int arrivalTime = calculator.plusDuration(arrivalTimeTransit, transferLeg.durationInSeconds()); if (exceedsTimeLimit(arrivalTime)) { return; } final int toStop = transferLeg.stop(); // transitTimes upper bounds bestTimes so we don't need to update wait time and in-vehicle time here, if we // enter this conditional it has already been updated. if (newOverallBestTime(toStop, arrivalTime)) { stopArrivalsState.setNewBestTransferTime(fromStop, arrivalTime, transferLeg); } else { stopArrivalsState.rejectNewBestTransferTime(fromStop, arrivalTime, transferLeg); } } @Override public boolean isDestinationReachedInCurrentRound() { return arrivedAtDestinationCheck.arrivedAtDestinationCurrentRound(); } /* private methods */ private boolean newTransitBestTime(int stop, int alightTime) { return bestTimes.transitUpdateNewBestTime(stop, alightTime); } private boolean newOverallBestTime(int stop, int alightTime) { return bestTimes.updateNewBestTime(stop, alightTime); } private boolean exceedsTimeLimit(int time) { return calculator.exceedsTimeLimit(time); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy