Search in sources :

Example 76 with State

use of org.opentripplanner.routing.core.State in project OpenTripPlanner by opentripplanner.

the class GraphPathFinder method compactLegsByReversedSearch.

/**
 * Do a full reversed search to compact the legs of the path.
 *
 * By doing a reversed search we are looking for later departures that will still be in time for transfer
 * to the next trip, shortening the transfer wait time. Also considering other routes than the ones found
 * in the original search.
 *
 * For arrive-by searches, we are looking to shorten transfer wait time and rather arrive earlier.
 */
private List<GraphPath> compactLegsByReversedSearch(AStar aStar, RoutingRequest originalReq, RoutingRequest options, List<GraphPath> newPaths, double timeout, RemainingWeightHeuristic remainingWeightHeuristic) {
    List<GraphPath> reversedPaths = new ArrayList<>();
    for (GraphPath newPath : newPaths) {
        State targetAcceptedState = options.arriveBy ? newPath.states.getLast().reverse() : newPath.states.getLast();
        if (targetAcceptedState.stateData.getNumBooardings() < 2) {
            reversedPaths.add(newPath);
            continue;
        }
        final long arrDepTime = targetAcceptedState.getTimeSeconds();
        LOG.debug("Dep time: " + new Date(newPath.getStartTime() * 1000));
        LOG.debug("Arr time: " + new Date(newPath.getEndTime() * 1000));
        // find first/last transit stop
        Vertex transitStop = null;
        long transitStopTime = arrDepTime;
        while (transitStop == null) {
            if (targetAcceptedState.backEdge instanceof TransitBoardAlight) {
                if (options.arriveBy) {
                    transitStop = targetAcceptedState.backEdge.getFromVertex();
                } else {
                    transitStop = targetAcceptedState.backEdge.getToVertex();
                }
                transitStopTime = targetAcceptedState.getTimeSeconds();
            }
            targetAcceptedState = targetAcceptedState.getBackState();
        }
        // find the path from transitStop to origin/destination
        Vertex fromVertex = options.arriveBy ? options.rctx.fromVertex : transitStop;
        Vertex toVertex = options.arriveBy ? transitStop : options.rctx.toVertex;
        RoutingRequest reversedTransitRequest = createReversedTransitRequest(originalReq, options, fromVertex, toVertex, arrDepTime, new EuclideanRemainingWeightHeuristic());
        aStar.getShortestPathTree(reversedTransitRequest, timeout);
        List<GraphPath> pathsToTarget = aStar.getPathsToTarget();
        if (pathsToTarget.isEmpty()) {
            reversedPaths.add(newPath);
            continue;
        }
        GraphPath walkPath = pathsToTarget.get(0);
        // do the reversed search to/from transitStop
        Vertex fromTransVertex = options.arriveBy ? transitStop : options.rctx.fromVertex;
        Vertex toTransVertex = options.arriveBy ? options.rctx.toVertex : transitStop;
        RoutingRequest reversedMainRequest = createReversedMainRequest(originalReq, options, fromTransVertex, toTransVertex, transitStopTime, remainingWeightHeuristic);
        aStar.getShortestPathTree(reversedMainRequest, timeout);
        List<GraphPath> newRevPaths = aStar.getPathsToTarget();
        if (newRevPaths.isEmpty()) {
            reversedPaths.add(newPath);
        } else {
            List<GraphPath> joinedPaths = new ArrayList<>();
            for (GraphPath newRevPath : newRevPaths) {
                LOG.debug("REV Dep time: " + new Date(newRevPath.getStartTime() * 1000));
                LOG.debug("REV Arr time: " + new Date(newRevPath.getEndTime() * 1000));
                List<GraphPath> concatenatedPaths = Arrays.asList(newRevPath, walkPath);
                if (options.arriveBy) {
                    Collections.reverse(concatenatedPaths);
                }
                GraphPath joinedPath = joinPaths(concatenatedPaths);
                if ((!options.arriveBy && joinedPath.states.getFirst().getTimeInMillis() > options.dateTime * 1000) || (options.arriveBy && joinedPath.states.getLast().getTimeInMillis() < options.dateTime * 1000)) {
                    joinedPaths.add(joinedPath);
                    if (newPaths.size() > 1) {
                        for (AgencyAndId tripId : joinedPath.getTrips()) {
                            options.banTrip(tripId);
                        }
                    }
                }
            }
            reversedPaths.addAll(joinedPaths);
        }
    }
    return reversedPaths.isEmpty() ? newPaths : reversedPaths;
}
Also used : Vertex(org.opentripplanner.routing.graph.Vertex) AgencyAndId(org.onebusaway.gtfs.model.AgencyAndId) TransitBoardAlight(org.opentripplanner.routing.edgetype.TransitBoardAlight) State(org.opentripplanner.routing.core.State) GraphPath(org.opentripplanner.routing.spt.GraphPath) RoutingRequest(org.opentripplanner.routing.core.RoutingRequest) EuclideanRemainingWeightHeuristic(org.opentripplanner.routing.algorithm.strategies.EuclideanRemainingWeightHeuristic)

Example 77 with State

use of org.opentripplanner.routing.core.State in project OpenTripPlanner by opentripplanner.

the class NycFareServiceImpl method getCost.

@Override
public Fare getCost(GraphPath path) {
    final List<AgencyAndId> SIR_PAID_STOPS = makeMtaStopList("S31", "S30");
    final List<AgencyAndId> SUBWAY_FREE_TRANSFER_STOPS = makeMtaStopList("R11", "B08", "629");
    final List<AgencyAndId> SIR_BONUS_STOPS = makeMtaStopList("140", "420", "419", "418", "M22", "M23", "R27", "R26");
    final List<AgencyAndId> SIR_BONUS_ROUTES = makeMtaStopList("M5", "M20", "M15-SBS");
    final List<AgencyAndId> CANARSIE = makeMtaStopList("L29", "303345");
    // List of NYC agencies to set fares for
    final List<String> AGENCIES = new ArrayList<>();
    AGENCIES.add("MTABC");
    AGENCIES.add("MTA NYCT");
    LinkedList<State> states = path.states;
    // create rides
    List<Ride> rides = new ArrayList<Ride>();
    Ride newRide = null;
    final int SUBWAY = 1;
    final int SIR = 2;
    final int LOCAL_BUS = 3;
    final int EXPRESS_BUS = 30;
    final int EXPENSIVE_EXPRESS_BUS = 34;
    final int WALK = -1;
    for (State state : states) {
        Edge backEdge = state.getBackEdge();
        if (backEdge instanceof StreetEdge) {
            if (newRide == null || !newRide.classifier.equals(WALK)) {
                if (rides.size() == 0 || !rides.get(rides.size() - 1).classifier.equals(WALK)) {
                    newRide = new Ride();
                    newRide.classifier = WALK;
                    rides.add(newRide);
                }
            }
            continue;
        }
        // dwells do not affect fare.
        if (backEdge instanceof DwellEdge)
            continue;
        if (!(backEdge instanceof HopEdge)) {
            newRide = null;
            continue;
        }
        AgencyAndId routeId = state.getRoute();
        String agencyId = state.getBackTrip().getRoute().getAgency().getId();
        if (!AGENCIES.contains(agencyId)) {
            continue;
        }
        if (routeId == null) {
            newRide = null;
        } else {
            if (newRide == null || !routeId.equals(newRide.route)) {
                newRide = new Ride();
                rides.add(newRide);
                newRide.firstStop = ((HopEdge) backEdge).getBeginStop();
                newRide.route = routeId;
                Trip trip = state.getBackTrip();
                Route route = trip.getRoute();
                int type = route.getType();
                newRide.classifier = type;
                String shortName = route.getShortName();
                if (shortName == null) {
                    newRide.classifier = SUBWAY;
                } else if (shortName.equals("BxM4C")) {
                    newRide.classifier = EXPENSIVE_EXPRESS_BUS;
                } else if (shortName.startsWith("X") || shortName.startsWith("BxM") || shortName.startsWith("QM") || shortName.startsWith("BM")) {
                    // Express bus
                    newRide.classifier = EXPRESS_BUS;
                }
                newRide.startTime = state.getTimeSeconds();
            }
            newRide.lastStop = ((HopEdge) backEdge).getBeginStop();
        }
    }
    // There are no rides, so there's no fare.
    if (rides.size() == 0) {
        return null;
    }
    NycFareState state = NycFareState.INIT;
    boolean lexFreeTransfer = false;
    boolean canarsieFreeTransfer = false;
    boolean siLocalBus = false;
    boolean sirBonusTransfer = false;
    float totalFare = 0;
    for (Ride ride : rides) {
        AgencyAndId firstStopId = null;
        AgencyAndId lastStopId = null;
        if (ride.firstStop != null) {
            firstStopId = ride.firstStop.getId();
            lastStopId = ride.lastStop.getId();
        }
        switch(state) {
            case INIT:
                lexFreeTransfer = siLocalBus = canarsieFreeTransfer = false;
                if (ride.classifier.equals(WALK)) {
                // walking keeps you in init
                } else if (ride.classifier.equals(SUBWAY)) {
                    state = NycFareState.SUBWAY_PRE_TRANSFER;
                    totalFare += ORDINARY_FARE;
                    if (SUBWAY_FREE_TRANSFER_STOPS.contains(ride.lastStop.getId())) {
                        lexFreeTransfer = true;
                    }
                    if (CANARSIE.contains(ride.lastStop.getId())) {
                        canarsieFreeTransfer = true;
                    }
                } else if (ride.classifier.equals(SIR)) {
                    state = NycFareState.SIR_PRE_TRANSFER;
                    if (SIR_PAID_STOPS.contains(firstStopId) || SIR_PAID_STOPS.contains(lastStopId)) {
                        totalFare += ORDINARY_FARE;
                    }
                } else if (ride.classifier.equals(LOCAL_BUS)) {
                    state = NycFareState.BUS_PRE_TRANSFER;
                    totalFare += ORDINARY_FARE;
                    if (CANARSIE.contains(ride.lastStop.getId())) {
                        canarsieFreeTransfer = true;
                    }
                    siLocalBus = ride.route.getId().startsWith("S");
                } else if (ride.classifier.equals(EXPRESS_BUS)) {
                    state = NycFareState.BUS_PRE_TRANSFER;
                    totalFare += EXPRESS_FARE;
                } else if (ride.classifier.equals(EXPENSIVE_EXPRESS_BUS)) {
                    state = NycFareState.EXPENSIVE_EXPRESS_BUS;
                    totalFare += EXPENSIVE_EXPRESS_FARE;
                }
                break;
            case SUBWAY_PRE_TRANSFER_WALKED:
                if (ride.classifier.equals(SUBWAY)) {
                    // lex and 59/63
                    if (!(lexFreeTransfer && SUBWAY_FREE_TRANSFER_STOPS.contains(ride.firstStop.getId()))) {
                        totalFare += ORDINARY_FARE;
                    }
                    lexFreeTransfer = canarsieFreeTransfer = false;
                    if (SUBWAY_FREE_TRANSFER_STOPS.contains(ride.lastStop.getId())) {
                        lexFreeTransfer = true;
                    }
                    if (CANARSIE.contains(ride.lastStop.getId())) {
                        canarsieFreeTransfer = true;
                    }
                }
            /* FALL THROUGH */
            case SUBWAY_PRE_TRANSFER:
                // hours (if only just)
                if (ride.classifier.equals(WALK)) {
                    state = NycFareState.SUBWAY_PRE_TRANSFER_WALKED;
                } else if (ride.classifier.equals(SIR)) {
                    state = NycFareState.SIR_POST_TRANSFER_FROM_SUBWAY;
                } else if (ride.classifier.equals(LOCAL_BUS)) {
                    if (CANARSIE.contains(ride.firstStop.getId()) && canarsieFreeTransfer) {
                        state = NycFareState.BUS_PRE_TRANSFER;
                    } else {
                        state = NycFareState.INIT;
                    }
                } else if (ride.classifier.equals(EXPRESS_BUS)) {
                    // need to pay the upgrade cost
                    totalFare += EXPRESS_FARE - ORDINARY_FARE;
                } else if (ride.classifier.equals(EXPENSIVE_EXPRESS_BUS)) {
                    // no transfers to the
                    totalFare += EXPENSIVE_EXPRESS_FARE;
                // BxMM4C
                }
                break;
            case BUS_PRE_TRANSFER:
                if (ride.classifier.equals(SUBWAY)) {
                    if (CANARSIE.contains(ride.firstStop.getId()) && canarsieFreeTransfer) {
                        state = NycFareState.SUBWAY_PRE_TRANSFER;
                    } else {
                        state = NycFareState.INIT;
                    }
                } else if (ride.classifier.equals(SIR)) {
                    if (siLocalBus) {
                        // SI local bus to SIR, so it is as if we started on the
                        // SIR (except that when we enter the bus or subway system we need to do
                        // so at certain places)
                        sirBonusTransfer = true;
                        state = NycFareState.SIR_PRE_TRANSFER;
                    } else {
                        // transfers exhausted
                        state = NycFareState.INIT;
                    }
                } else if (ride.classifier.equals(LOCAL_BUS)) {
                    state = NycFareState.INIT;
                } else if (ride.classifier.equals(EXPRESS_BUS)) {
                    // need to pay the upgrade cost
                    totalFare += EXPRESS_FARE - ORDINARY_FARE;
                    state = NycFareState.INIT;
                } else if (ride.classifier.equals(EXPENSIVE_EXPRESS_BUS)) {
                    totalFare += EXPENSIVE_EXPRESS_FARE;
                // no transfers to the BxMM4C
                }
                break;
            case SIR_PRE_TRANSFER:
                if (ride.classifier.equals(SUBWAY)) {
                    if (sirBonusTransfer && !SIR_BONUS_STOPS.contains(ride.firstStop.getId())) {
                        // we were relying on the bonus transfer to be in the "pre-transfer state",
                        // but the bonus transfer does not apply here
                        totalFare += ORDINARY_FARE;
                    }
                    if (CANARSIE.contains(ride.lastStop.getId())) {
                        canarsieFreeTransfer = true;
                    }
                    state = NycFareState.SUBWAY_POST_TRANSFER;
                } else if (ride.classifier.equals(SIR)) {
                    /* should not happen, and unhandled */
                    LOG.warn("Should not transfer from SIR to SIR");
                } else if (ride.classifier.equals(LOCAL_BUS)) {
                    if (!SIR_BONUS_ROUTES.contains(ride.route)) {
                        totalFare += ORDINARY_FARE;
                    }
                    state = NycFareState.BUS_PRE_TRANSFER;
                } else if (ride.classifier.equals(EXPRESS_BUS)) {
                    totalFare += EXPRESS_BUS;
                    state = NycFareState.BUS_PRE_TRANSFER;
                } else if (ride.classifier.equals(EXPENSIVE_EXPRESS_BUS)) {
                    totalFare += EXPENSIVE_EXPRESS_BUS;
                    state = NycFareState.BUS_PRE_TRANSFER;
                }
                break;
            case SIR_POST_TRANSFER_FROM_SUBWAY:
                if (ride.classifier.equals(SUBWAY)) {
                    /* should not happen */
                    totalFare += ORDINARY_FARE;
                    state = NycFareState.SUBWAY_PRE_TRANSFER;
                } else if (ride.classifier.equals(SIR)) {
                    /* should not happen, and unhandled */
                    LOG.warn("Should not transfer from SIR to SIR");
                } else if (ride.classifier.equals(LOCAL_BUS)) {
                    if (!ride.route.getId().startsWith("S")) {
                        totalFare += ORDINARY_FARE;
                        state = NycFareState.BUS_PRE_TRANSFER;
                    } else {
                        state = NycFareState.INIT;
                    }
                } else if (ride.classifier.equals(EXPRESS_BUS)) {
                    // need to pay the full cost
                    totalFare += EXPRESS_FARE;
                    state = NycFareState.INIT;
                } else if (ride.classifier.equals(EXPENSIVE_EXPRESS_BUS)) {
                    /* should not happen */
                    // no transfers to the BxMM4C
                    totalFare += EXPENSIVE_EXPRESS_FARE;
                    state = NycFareState.BUS_PRE_TRANSFER;
                }
                break;
            case SUBWAY_POST_TRANSFER:
                if (ride.classifier.equals(WALK)) {
                    if (!canarsieFreeTransfer) {
                        /* note: if we end up walking to another subway after alighting
			    		 * at Canarsie, we will mistakenly not be charged, but nobody
			    		 * would ever do this */
                        state = NycFareState.INIT;
                    }
                } else if (ride.classifier.equals(SIR)) {
                    totalFare += ORDINARY_FARE;
                    state = NycFareState.SIR_PRE_TRANSFER;
                } else if (ride.classifier.equals(LOCAL_BUS)) {
                    if (!(CANARSIE.contains(ride.firstStop.getId()) && canarsieFreeTransfer)) {
                        totalFare += ORDINARY_FARE;
                    }
                    state = NycFareState.INIT;
                } else if (ride.classifier.equals(SUBWAY)) {
                    // walking transfer
                    totalFare += ORDINARY_FARE;
                    state = NycFareState.SUBWAY_PRE_TRANSFER;
                } else if (ride.classifier.equals(EXPRESS_BUS)) {
                    totalFare += EXPRESS_FARE;
                    state = NycFareState.BUS_PRE_TRANSFER;
                } else if (ride.classifier.equals(EXPENSIVE_EXPRESS_BUS)) {
                    totalFare += EXPENSIVE_EXPRESS_FARE;
                    state = NycFareState.BUS_PRE_TRANSFER;
                }
        }
    }
    Currency currency = Currency.getInstance("USD");
    Fare fare = new Fare();
    fare.addFare(FareType.regular, new WrappedCurrency(currency), (int) Math.round(totalFare * Math.pow(10, currency.getDefaultFractionDigits())));
    return fare;
}
Also used : Trip(org.onebusaway.gtfs.model.Trip) DwellEdge(org.opentripplanner.routing.edgetype.DwellEdge) AgencyAndId(org.onebusaway.gtfs.model.AgencyAndId) ArrayList(java.util.ArrayList) StreetEdge(org.opentripplanner.routing.edgetype.StreetEdge) WrappedCurrency(org.opentripplanner.routing.core.WrappedCurrency) Fare(org.opentripplanner.routing.core.Fare) HopEdge(org.opentripplanner.routing.edgetype.HopEdge) State(org.opentripplanner.routing.core.State) Currency(java.util.Currency) WrappedCurrency(org.opentripplanner.routing.core.WrappedCurrency) HopEdge(org.opentripplanner.routing.edgetype.HopEdge) DwellEdge(org.opentripplanner.routing.edgetype.DwellEdge) StreetEdge(org.opentripplanner.routing.edgetype.StreetEdge) Edge(org.opentripplanner.routing.graph.Edge) Route(org.onebusaway.gtfs.model.Route)

Example 78 with State

use of org.opentripplanner.routing.core.State in project OpenTripPlanner by opentripplanner.

the class BikeParkEdge method traversePark.

protected State traversePark(State s0) {
    RoutingRequest options = s0.getOptions();
    /*
         * To park a bike, we need to be riding one, (not rented) and be allowed to walk and to park
         * it.
         */
    if (s0.getNonTransitMode() != TraverseMode.BICYCLE || !options.modes.getWalk() || s0.isBikeRenting() || s0.isBikeParked())
        return null;
    BikeParkVertex bikeParkVertex = (BikeParkVertex) tov;
    if (bikeParkVertex.getSpacesAvailable() == 0) {
        return null;
    }
    StateEditor s0e = s0.edit(this);
    s0e.incrementWeight(options.bikeParkCost);
    s0e.incrementTimeInSeconds(options.bikeParkTime);
    s0e.setBackMode(TraverseMode.LEG_SWITCH);
    s0e.setBikeParked(true);
    State s1 = s0e.makeState();
    return s1;
}
Also used : BikeParkVertex(org.opentripplanner.routing.vertextype.BikeParkVertex) StateEditor(org.opentripplanner.routing.core.StateEditor) State(org.opentripplanner.routing.core.State) RoutingRequest(org.opentripplanner.routing.core.RoutingRequest)

Aggregations

State (org.opentripplanner.routing.core.State)78 RoutingRequest (org.opentripplanner.routing.core.RoutingRequest)42 GraphPath (org.opentripplanner.routing.spt.GraphPath)25 ShortestPathTree (org.opentripplanner.routing.spt.ShortestPathTree)24 Test (org.junit.Test)23 Edge (org.opentripplanner.routing.graph.Edge)22 Vertex (org.opentripplanner.routing.graph.Vertex)20 StreetEdge (org.opentripplanner.routing.edgetype.StreetEdge)13 Coordinate (com.vividsolutions.jts.geom.Coordinate)11 TransitStop (org.opentripplanner.routing.vertextype.TransitStop)8 Graph (org.opentripplanner.routing.graph.Graph)7 DominanceFunction (org.opentripplanner.routing.spt.DominanceFunction)7 NonLocalizedString (org.opentripplanner.util.NonLocalizedString)6 LineString (com.vividsolutions.jts.geom.LineString)5 HashSet (java.util.HashSet)5 AgencyAndId (org.onebusaway.gtfs.model.AgencyAndId)5 Trip (org.onebusaway.gtfs.model.Trip)5 StateEditor (org.opentripplanner.routing.core.StateEditor)5 TemporaryStreetLocation (org.opentripplanner.routing.location.TemporaryStreetLocation)5 IntersectionVertex (org.opentripplanner.routing.vertextype.IntersectionVertex)5