/** * Prune raptor data to include only routes and boardings which have trips today. Doesn't actually * improve speed */ @SuppressWarnings("unchecked") private RaptorData pruneDataForServiceDays(Graph graph, ArrayList<ServiceDay> serviceDays) { if (serviceDays.equals(cachedServiceDays)) return cachedRaptorData; RaptorData data = graph.getService(RaptorDataService.class).getData(); RaptorData pruned = new RaptorData(); pruned.raptorStopsForStopId = data.raptorStopsForStopId; pruned.stops = data.stops; pruned.routes = new ArrayList<RaptorRoute>(); pruned.routesForStop = new List[pruned.stops.length]; for (RaptorRoute route : data.routes) { ArrayList<Integer> keep = new ArrayList<Integer>(); for (int i = 0; i < route.boards[0].length; ++i) { Edge board = route.boards[0][i]; int serviceId; if (board instanceof TransitBoardAlight) { serviceId = ((TransitBoardAlight) board).getPattern().getServiceId(); } else { log.debug("Unexpected nonboard among boards"); continue; } for (ServiceDay day : serviceDays) { if (day.serviceIdRunning(serviceId)) { keep.add(i); break; } } } if (keep.isEmpty()) continue; int nPatterns = keep.size(); RaptorRoute prunedRoute = new RaptorRoute(route.getNStops(), nPatterns); for (int stop = 0; stop < route.getNStops() - 1; ++stop) { for (int pattern = 0; pattern < nPatterns; ++pattern) { prunedRoute.boards[stop][pattern] = route.boards[stop][keep.get(pattern)]; } } pruned.routes.add(route); for (RaptorStop stop : route.stops) { List<RaptorRoute> routes = pruned.routesForStop[stop.index]; if (routes == null) { routes = new ArrayList<RaptorRoute>(); pruned.routesForStop[stop.index] = routes; } routes.add(route); } } for (RaptorStop stop : data.stops) { if (pruned.routesForStop[stop.index] == null) { pruned.routesForStop[stop.index] = Collections.emptyList(); } } cachedServiceDays = serviceDays; cachedRaptorData = pruned; return pruned; }
private boolean checkForInterliningArriveBy( RoutingRequest options, int nBoardings, RaptorRoute route, List<RaptorState> boardStates) { int firstStop = route.getNStops() - 1; boolean started = false; final List<RaptorState> states = statesByStop[route.stops[firstStop].index]; if (states == null) return false; INTERLINE: for (RaptorState oldState : states) { if (oldState.nBoardings != nBoardings - 1) { continue; } if (oldState.route == null) { continue; } if (oldState.route.stops[0] != oldState.stop) { continue; } RaptorInterlineData interline = oldState.route.interlinesIn.get(oldState.tripId); if (interline == null || interline.fromRoute != route) { continue; } RaptorState stayOn = oldState.clone(); stayOn.arrivalTime += options.getBoardSlack(); // go backwards in time stayOn.interlining = true; // generate a board state for this interline RaptorState boardState = new RaptorState(stayOn); // we need to subtract out the boardSlack that we are about to mistakenly pay boardState.weight = -options.getBoardSlack() - options.getAlightSlack(); boardState.nBoardings = boardState.nBoardings = nBoardings - 1; boardState.boardStop = route.stops[firstStop]; boardState.boardStopSequence = firstStop; TransitBoardAlight alight = route.alights[firstStop - 1][interline.fromPatternIndex]; TableTripPattern pattern = alight.getPattern(); boardState.tripTimes = pattern.getTripTimes(interline.fromTripIndex); final ServiceDay serviceDay = oldState.serviceDay; boardState.arrivalTime = (int) serviceDay.time(boardState.tripTimes.getArrivalTime(firstStop - 1)); boardState.patternIndex = interline.fromPatternIndex; boardState.tripId = interline.fromTripId; boardState.serviceDay = serviceDay; boardState.route = route; boardState.walkDistance = oldState.walkDistance; for (RaptorState state : boardStates) { if (state.eDominates(boardState)) { continue INTERLINE; } } boardStates.add(boardState); started = true; } return started; }
public List<RaptorState> transitPhase(RoutingRequest options, int nBoardings) { Collection<RaptorRoute> routesToVisit = new HashSet<RaptorRoute>(); if (data.routesForStop == null) { Collection<RaptorRoute> routes = data.routes; for (RaptorStop stop : visitedLastRound) { for (RaptorRoute route : data.routesForStop[stop.index]) { if (routes.contains(route)) { routesToVisit.add(route); } } } } else { for (RaptorStop stop : visitedLastRound) { for (RaptorRoute route : data.routesForStop[stop.index]) { routesToVisit.add(route); } } } HashSet<RaptorStop> visitedThisRound = new HashSet<RaptorStop>(); List<RaptorState> createdStates = new ArrayList<RaptorState>(); int boardSlack; if (options.isArriveBy()) { boardSlack = nBoardings == 1 ? options.getAlightSlack() : (options.getTransferSlack() - options.getBoardSlack()); } else { boardSlack = nBoardings == 1 ? options.getBoardSlack() : (options.getTransferSlack() - options.getAlightSlack()); } for (RaptorRoute route : routesToVisit) { List<RaptorState> boardStates = new ArrayList<RaptorState>(); // not really states boolean started; int firstStop, lastStop, direction, lastBoardStop; if (options.isArriveBy()) { firstStop = route.getNStops() - 1; lastStop = -1; direction = -1; lastBoardStop = 0; // check for interlining on the first stop started = checkForInterliningArriveBy(options, nBoardings, route, boardStates); } else { firstStop = 0; lastStop = route.getNStops(); direction = 1; lastBoardStop = lastStop - 1; started = checkForInterliningDepartAt(options, nBoardings, route, boardStates); } for (int stopNo = firstStop; stopNo != lastStop; stopNo += direction) { // find the current time at this stop RaptorStop stop = route.stops[stopNo]; if (!started && !visitedLastRound.contains(stop)) continue; started = true; // skip stops which aren't in this set of data; // this is used for the rush ahead search if (!data.raptorStopsForStopId.containsKey(stop.stopVertex.getStopId())) { continue; } // Skip banned stops if (options.getBannedStops().matches(stop.stopVertex.getStop())) { continue; } if (options.getBannedStopsHard().matches(stop.stopVertex.getStop())) { continue; } List<RaptorState> states = statesByStop[stop.index]; List<RaptorState> newStates = new ArrayList<RaptorState>(); if (states == null) { states = new ArrayList<RaptorState>(); statesByStop[stop.index] = states; } // this checks the case of continuing on the current trips. CONTINUE: for (RaptorState boardState : boardStates) { if (boardState.boardStop == stop) { // this only happens due to interlines where // the last stop of the first route is equal to the first stop of the // subsequent route. continue; } RaptorState newState = new RaptorState(boardState.getParent()); ServiceDay sd = boardState.serviceDay; int travelTime; if (options.isArriveBy()) { if (!route.alights[0][boardState.patternIndex].getPattern().canBoard(stopNo)) continue; int boardTime = route.getBoardTime(boardState.tripTimes, stopNo); newState.arrivalTime = (int) sd.time(boardTime); // add in slack newState.arrivalTime -= options.getBoardSlack(); travelTime = newState.getParent().arrivalTime - newState.arrivalTime; } else { if (!route.boards[0][boardState.patternIndex].getPattern().canAlight(stopNo)) continue; int alightTime = route.getAlightTime(boardState.tripTimes, stopNo); newState.arrivalTime = (int) sd.time(alightTime); // add in slack newState.arrivalTime += options.getAlightSlack(); travelTime = newState.arrivalTime - newState.getParent().arrivalTime; } newState.weight += travelTime; // TODO: consider transfer penalties newState.weight += boardState.weight; newState.boardStop = boardState.boardStop; newState.boardStopSequence = boardState.boardStopSequence; newState.route = route; newState.patternIndex = boardState.patternIndex; newState.tripTimes = boardState.tripTimes; newState.nBoardings = boardState.nBoardings; newState.walkDistance = boardState.walkDistance; newState.tripId = boardState.tripId; newState.stop = stop; newState.serviceDay = boardState.serviceDay; for (RaptorState oldState : states) { if (oldState.eDominates(newState)) { continue CONTINUE; } } for (RaptorState oldState : newStates) { if (oldState.eDominates(newState)) { continue CONTINUE; } } Iterator<RaptorState> it = states.iterator(); while (it.hasNext()) { RaptorState oldState = it.next(); if (newState.eDominates(oldState)) { it.remove(); } } it = newStates.iterator(); while (it.hasNext()) { RaptorState oldState = it.next(); if (newState.eDominates(oldState)) { it.remove(); } } visitedThisRound.add(stop); visitedEver.add(stop); newStates.add(newState); } if (stopNo != lastBoardStop) { if (stop.stopVertex.isLocal() && nBoardings > 1) { // cannot transfer at a local stop createdStates.addAll(newStates); states.addAll(newStates); continue; } // try boarding here TRYBOARD: for (RaptorState oldState : states) { if (oldState.nBoardings != nBoardings - 1) continue; if (oldState.getRoute() == route) continue; // we got here via this route, so no reason to transfer RaptorBoardSpec boardSpec; int waitTime; if (options.isArriveBy()) { int arrivalTime = oldState.arrivalTime - boardSlack; boardSpec = route.getTripIndexReverse(options, arrivalTime, stopNo); if (boardSpec == null) continue; waitTime = oldState.arrivalTime - boardSpec.departureTime; } else { int arrivalTime = oldState.arrivalTime + boardSlack; boardSpec = route.getTripIndex(options, arrivalTime, stopNo); if (boardSpec == null) continue; waitTime = boardSpec.departureTime - oldState.arrivalTime; } RaptorState boardState = new RaptorState(oldState); if (nBoardings == 1) { // do not count initial wait time, since it will be optimized away later boardState.initialWaitTime = waitTime; waitTime = 0; } boardState.weight = options.getBoardCost(route.mode) + waitTime; boardState.nBoardings = nBoardings; boardState.boardStop = stop; boardState.boardStopSequence = stopNo; boardState.arrivalTime = boardSpec.departureTime; boardState.patternIndex = boardSpec.patternIndex; boardState.tripTimes = boardSpec.tripTimes; boardState.serviceDay = boardSpec.serviceDay; boardState.route = route; boardState.walkDistance = oldState.walkDistance; boardState.tripId = boardSpec.tripId; for (RaptorState state : boardStates) { if (state.eDominates(boardState)) { continue TRYBOARD; } } for (RaptorState state : newStates) { if (state.eDominates(boardState)) { continue TRYBOARD; } } boardStates.add(boardState); } } createdStates.addAll(newStates); states.addAll(newStates); } } visitedLastRound = visitedThisRound; return createdStates; }