20 package ch.sbb.matsim.routing.pt.raptor;
75 this.arrivalPathPerRouteStop =
new PathElement[data.countRouteStops];
76 this.egressCostsPerRouteStop =
new double[data.countRouteStops];
77 this.leastArrivalCostAtRouteStop =
new double[data.countRouteStops];
78 this.leastArrivalCostAtStop =
new double[data.countStops];
79 this.improvedRouteStopIndices =
new BitSet(this.data.countRouteStops);
80 this.reachedRouteStopIndices =
new BitSet(this.data.countRouteStops);
81 this.destinationRouteStopIndices =
new BitSet(this.data.countRouteStops);
82 this.improvedStops =
new BitSet(this.data.countStops);
83 this.arrivalPathPerStop =
new PathElement[this.data.countStops];
84 this.tmpArrivalPathPerStop =
new PathElement[this.data.countStops];
85 this.tmpImprovedStops =
new BitSet(this.data.countStops);
94 Arrays.fill(this.arrivalPathPerRouteStop, null);
95 Arrays.fill(this.egressCostsPerRouteStop, Double.POSITIVE_INFINITY);
96 Arrays.fill(this.arrivalPathPerStop, null);
97 Arrays.fill(this.leastArrivalCostAtRouteStop, Double.POSITIVE_INFINITY);
98 Arrays.fill(this.leastArrivalCostAtStop, Double.POSITIVE_INFINITY);
99 this.improvedStops.clear();
100 this.improvedRouteStopIndices.clear();
101 this.reachedRouteStopIndices.clear();
102 this.destinationRouteStopIndices.clear();
103 this.bestArrivalCost = Double.POSITIVE_INFINITY;
107 final int maxTransfers = 20;
108 final int maxTransfersAfterFirstArrival = 2;
114 Map<TransitStopFacility, InitialStop> destinationStops =
new LinkedHashMap<>();
119 InitialStop alternative = destinationStops.get(egressStop.stop);
120 if (alternative == null || egressStop.accessCost < alternative.accessCost) {
121 destinationStops.put(egressStop.stop, egressStop);
125 for (
InitialStop egressStop : destinationStops.values()) {
126 int[] routeStopIndices = this.data.routeStopsPerStopFacility.get(egressStop.stop);
127 if (routeStopIndices != null) {
128 for (
int routeStopIndex : routeStopIndices) {
129 this.destinationRouteStopIndices.set(routeStopIndex);
130 this.egressCostsPerRouteStop[routeStopIndex] = egressStop.accessCost;
138 Map<TransitStopFacility, InitialStop> initialStops =
new LinkedHashMap<>();
140 InitialStop alternative = initialStops.get(accessStop.stop);
141 if (alternative == null || accessStop.accessCost < alternative.accessCost) {
142 initialStops.put(accessStop.stop, accessStop);
146 boolean hasIntermodalAccess =
false;
150 int[] routeStopIndices = this.data.routeStopsPerStopFacility.get(stop.stop);
152 for (
int routeStopIndex : routeStopIndices) {
154 int arrivalTime = (int) (depTime + stop.accessTime);
155 double arrivalCost = stop.accessCost;
157 RRouteStop routeStop = this.data.routeStops[routeStopIndex];
159 boolean isIntermodalAccess = stop.planElements != null;
163 if (!isIntermodalAccess && routeStop.routeStop == routeStop.route.getStops().get(routeStop.route.getStops().size() - 1)) {
168 if (!routeStop.routeStop.isAllowBoarding()) {
172 RRoute route = this.data.routes[routeStop.transitRouteIndex];
173 int depOffset = routeStop.departureOffset;
176 if (departureIndex >= 0) {
177 int nextDepartureTimeAtStop = this.data.departures[departureIndex] + depOffset;
178 int waitingTime = nextDepartureTimeAtStop - arrivalTime;
181 RRouteStop toRouteStop = this.data.routeStops[routeStopIndex];
182 PathElement pe =
new PathElement(null, toRouteStop, TIME_UNDEFINED, nextDepartureTimeAtStop, nextDepartureTimeAtStop, arrivalTime, arrivalCost, 0, stop.distance, 0,
true, null, stop);
195 double xCost = arrivalCost + waitingCost;
197 if (xCost < this.leastArrivalCostAtRouteStop[routeStopIndex]) {
198 this.arrivalPathPerRouteStop[routeStopIndex] = pe;
199 this.leastArrivalCostAtRouteStop[routeStopIndex] = xCost;
200 this.improvedRouteStopIndices.set(routeStopIndex);
201 if (xCost < this.leastArrivalCostAtStop[toRouteStop.stopFacilityIndex]) {
202 this.improvedStops.set(toRouteStop.stopFacilityIndex);
203 this.arrivalPathPerStop[toRouteStop.stopFacilityIndex] = pe;
204 this.leastArrivalCostAtStop[toRouteStop.stopFacilityIndex] = xCost;
207 }
else if (isIntermodalAccess) {
209 RRouteStop toRouteStop = this.data.routeStops[routeStopIndex];
210 PathElement pe =
new PathElement(null, toRouteStop, TIME_UNDEFINED, TIME_UNDEFINED, TIME_UNDEFINED,arrivalTime, arrivalCost, 0, stop.distance, 0,
true, null, stop);
215 if (arrivalCost < this.leastArrivalCostAtRouteStop[routeStopIndex]) {
216 hasIntermodalAccess =
true;
217 this.arrivalPathPerRouteStop[routeStopIndex] = pe;
218 this.leastArrivalCostAtRouteStop[routeStopIndex] = arrivalCost;
219 this.improvedRouteStopIndices.set(routeStopIndex);
220 if (arrivalCost < this.leastArrivalCostAtStop[toRouteStop.stopFacilityIndex]) {
221 this.improvedStops.set(toRouteStop.stopFacilityIndex);
222 this.arrivalPathPerStop[toRouteStop.stopFacilityIndex] = pe;
223 this.leastArrivalCostAtStop[toRouteStop.stopFacilityIndex] = arrivalCost;
230 if (hasIntermodalAccess) {
237 BitSet initialRouteStopIndices =
new BitSet();
238 initialRouteStopIndices.or(this.improvedRouteStopIndices);
241 this.improvedRouteStopIndices.or(initialRouteStopIndices);
244 int allowedTransfersLeft = maxTransfersAfterFirstArrival;
246 for (
int k = 0; k <= maxTransfers; k++) {
255 if (leastCostPath != null) {
256 if (allowedTransfersLeft == 0) {
259 allowedTransfersLeft--;
262 if (this.improvedStops.isEmpty()) {
270 if (this.improvedRouteStopIndices.isEmpty()) {
281 public List<RaptorRoute>
calcRoutes(
double earliestDepTime,
double desiredDepTime,
double latestDepTime,
Facility fromFacility,
Facility toFacility, List<InitialStop> accessStops, List<InitialStop> egressStops,
RaptorParameters parameters,
Person person) {
282 List<RaptorRoute> foundRoutes =
new ArrayList<>();
283 int maxTransfers = 20;
284 final int maxTransfersAfterFirstArrival = 2;
285 Map<PathElement, InitialStop> initialStopsPerStartPath =
new HashMap<>();
292 PathElement lastFoundBestPath = null;
309 List<DepartureAtRouteStop> departures =
new ArrayList<>();
311 double earliestTimeAtStop = earliestDepTime + accessStop.accessTime;
312 double latestTimeAtStop = latestDepTime + accessStop.accessTime;
314 int[] routeStopIndices = this.data.routeStopsPerStopFacility.get(stop);
315 if (routeStopIndices != null) {
316 for (
int routeStopIndex : routeStopIndices) {
317 RRouteStop routeStop = this.data.routeStops[routeStopIndex];
318 if (routeStop.routeStop == routeStop.route.getStops().get(routeStop.route.getStops().size() - 1)) {
322 if (!routeStop.routeStop.isAllowBoarding()) {
325 RRoute route = this.data.routes[routeStop.transitRouteIndex];
326 int depOffset = routeStop.departureOffset;
327 for (
int depIndex = route.indexFirstDeparture; depIndex < route.indexFirstDeparture + route.countDepartures; depIndex++) {
328 int depTimeAtStart = this.data.departures[depIndex];
329 int depTimeAtStop = depTimeAtStart + depOffset;
330 if (depTimeAtStop >= earliestTimeAtStop && depTimeAtStop <= latestTimeAtStop) {
331 double costOffset = (depTimeAtStop - earliestTimeAtStop) * marginalUtilityOfWaitingPt_utl_s;
332 departures.add(
new DepartureAtRouteStop(routeStop, routeStopIndex, depIndex, depTimeAtStop, costOffset, accessStop));
338 departures.sort((d1, d2) -> {
340 double c1 = d1.costOffset + d1.accessStop.accessCost;
341 double c2 = d2.costOffset + d2.accessStop.accessCost;
342 int cmp = Double.compare(c1, c2);
344 cmp = Integer.compare(d1.departureIndex, d2.departureIndex);
349 Map<TransitStopFacility, InitialStop> destinationStops =
new HashMap<>();
351 InitialStop alternative = destinationStops.get(egressStop.stop);
352 if (alternative == null || egressStop.accessCost < alternative.accessCost) {
353 destinationStops.put(egressStop.stop, egressStop);
356 for (
InitialStop egressStop : destinationStops.values()) {
357 int[] routeStopIndices = this.data.routeStopsPerStopFacility.get(egressStop.stop);
358 if (routeStopIndices != null) {
359 for (
int routeStopIndex : routeStopIndices) {
360 this.destinationRouteStopIndices.set(routeStopIndex);
361 this.egressCostsPerRouteStop[routeStopIndex] = egressStop.accessCost;
367 this.improvedStops.clear();
368 this.improvedRouteStopIndices.clear();
369 this.bestArrivalCost = Double.POSITIVE_INFINITY;
371 int arrivalTime = depAtRouteStop.depTime;
372 double arrivalCost = depAtRouteStop.accessStop.accessCost + depAtRouteStop.costOffset;
373 RRouteStop toRouteStop = depAtRouteStop.routeStop;
374 int routeStopIndex = depAtRouteStop.routeStopIndex;
375 PathElement pe =
new PathElement(null, toRouteStop, depAtRouteStop.depTime, depAtRouteStop.depTime, depAtRouteStop.depTime, arrivalTime, arrivalCost, 0, depAtRouteStop.accessStop.distance, 0,
true, null, depAtRouteStop.accessStop);
376 this.arrivalPathPerRouteStop[routeStopIndex] = pe;
377 this.leastArrivalCostAtRouteStop[routeStopIndex] = arrivalCost;
378 this.arrivalPathPerStop[toRouteStop.stopFacilityIndex] = pe;
379 this.leastArrivalCostAtStop[toRouteStop.stopFacilityIndex] = arrivalCost;
380 this.improvedRouteStopIndices.set(routeStopIndex);
381 initialStopsPerStartPath.put(pe, depAtRouteStop.accessStop);
385 for (
int k = 0; k <= maxTransfers; k++) {
393 if (leastCostPath != null && (lastFoundBestPath == null || leastCostPath.comingFrom != lastFoundBestPath.comingFrom)) {
394 lastFoundBestPath = leastCostPath;
397 leastCostPath.arrivalTravelCost -= depAtRouteStop.costOffset;
399 leastCostPath.arrivalTravelCost += depAtRouteStop.costOffset;
400 foundRoutes.add(raptorRoute);
402 int optimizedTransferLimit = leastCostPath.transferCount + maxTransfersAfterFirstArrival;
403 if (optimizedTransferLimit < maxTransfers) {
404 maxTransfers = optimizedTransferLimit;
406 if (k == maxTransfers) {
411 if (this.improvedStops.isEmpty()) {
419 if (this.improvedRouteStopIndices.isEmpty()) {
430 PathElement firstPE = leastCostPath;
431 while (firstPE.comingFrom != null) {
432 firstPE = firstPE.comingFrom;
434 double depTime = firstPE.arrivalTime;
439 InitialStop accessStop = initialStopsPerStartPath.get(firstPE);
440 depTime -= accessStop.accessTime;
441 return Math.floor(depTime);
446 allRoutes.sort((r1, r2) -> {
447 int cmp = Integer.compare(r1.getNumberOfTransfers(), r2.getNumberOfTransfers());
449 cmp = Double.compare(r1.getDepartureTime(), r2.getDepartureTime());
452 cmp = Double.compare(r1.getTravelTime(), r2.getTravelTime());
456 List<RaptorRoute> uniqueRoutes =
new ArrayList<>();
457 int lastTransferCount = -1;
458 double lastDepTime = Double.NaN;
459 double lastTravelTime = Double.NaN;
461 if (route.getNumberOfTransfers() != lastTransferCount
462 || route.getDepartureTime() != lastDepTime
463 || route.getTravelTime() != lastTravelTime) {
464 uniqueRoutes.add(route);
465 lastTransferCount = route.getNumberOfTransfers();
466 lastDepTime = route.getDepartureTime();
467 lastTravelTime = route.getTravelTime();
472 List<RaptorRoute> routesToKeep =
new ArrayList<>();
474 boolean addRoute1 =
true;
476 if (route1 != route2) {
478 double arrTime1 = route1.getDepartureTime() + route1.getTravelTime();
479 double arrTime2 = route2.getDepartureTime() + route2.getTravelTime();
480 if (route2.getNumberOfTransfers() <=route1.getNumberOfTransfers()
481 && route2.getDepartureTime() >= route1.getDepartureTime()
482 && arrTime2 <= arrTime1) {
489 routesToKeep.add(route1);
503 BitSet initialRouteStopIndices =
new BitSet();
504 BitSet initialStopIndices =
new BitSet();
506 int[] routeStopIndices = this.data.routeStopsPerStopFacility.get(stop.stop);
507 for (
int routeStopIndex : routeStopIndices) {
508 boolean useStop =
true;
509 RRouteStop routeStop = this.data.routeStops[routeStopIndex];
510 if (!routeStop.routeStop.isAllowBoarding()) {
513 if (useStop && parameters.isExactDeparturesOnly()) {
514 int routeIndex = routeStop.transitRouteIndex;
515 RRoute route = this.data.routes[routeIndex];
517 if (currentDepartureIndex >= 0) {
518 int firstDepartureTime = this.data.departures[currentDepartureIndex];
519 int stopDepartureTime = firstDepartureTime + routeStop.departureOffset;
520 useStop = Math.abs(depTime - stopDepartureTime) < 1e-5;
526 int arrivalTime = (int) (depTime + stop.accessTime);
527 double arrivalCost = stop.accessCost;
528 RRouteStop toRouteStop = this.data.routeStops[routeStopIndex];
529 PathElement pe =
new PathElement(null, toRouteStop, TIME_UNDEFINED, TIME_UNDEFINED, TIME_UNDEFINED, arrivalTime, arrivalCost, 0, stop.distance, 0,
true, null, stop);
530 this.arrivalPathPerRouteStop[routeStopIndex] = pe;
531 this.arrivalPathPerStop[toRouteStop.stopFacilityIndex] = pe;
532 this.leastArrivalCostAtRouteStop[routeStopIndex] = arrivalCost;
533 this.leastArrivalCostAtStop[toRouteStop.stopFacilityIndex] = arrivalCost;
534 this.improvedRouteStopIndices.set(routeStopIndex);
536 initialRouteStopIndices.set(routeStopIndex);
537 initialStopIndices.set(toRouteStop.stopFacilityIndex);
543 int maxTransfers = parameters.getMaxTransfers();
552 if (this.improvedStops.isEmpty()) {
556 if (initialRouteStopIndices != null) {
557 this.improvedRouteStopIndices.or(initialRouteStopIndices);
558 this.improvedStops.or(initialStopIndices);
559 initialRouteStopIndices = null;
560 initialStopIndices = null;
563 if (transfers > maxTransfers) {
567 if (observer != null) {
568 for (
int stopIndex = this.improvedStops.nextSetBit(0); stopIndex >= 0; stopIndex = this.improvedStops.nextSetBit(stopIndex + 1)) {
569 PathElement fromPE = this.arrivalPathPerStop[stopIndex];
579 if (this.improvedRouteStopIndices.isEmpty()) {
583 if (observer != null) {
584 for (
int stopIndex = this.tmpImprovedStops.nextSetBit(0); stopIndex >= 0; stopIndex = this.tmpImprovedStops.nextSetBit(stopIndex + 1)) {
585 PathElement fromPE = this.arrivalPathPerStop[stopIndex];
593 Map<Id<TransitStopFacility>,
TravelInfo> result =
new HashMap<>();
594 for (Map.Entry<
TransitStopFacility, Integer> e :
this.data.stopFacilityIndices.entrySet()) {
596 int index = e.getValue();
597 PathElement destination = this.arrivalPathPerStop[index];
598 if (destination != null) {
600 result.put(stop.
getId(), ti);
607 PathElement backpointer = pe.comingFrom;
608 if (backpointer != null) {
609 while (backpointer.comingFrom != null) {
610 backpointer = backpointer.comingFrom;
612 TransitStopFacility departureStopFacility = backpointer.toRouteStop.routeStop.getStopFacility();
613 if (departureStopFacility != null) {
615 observer.
arrivedAtStop(pe.firstDepartureTime, arrivalStopFacility, pe.arrivalTime, pe.transferCount, () ->
createRaptorRoute(departureStopFacility, arrivalStopFacility, pe, pe.firstDepartureTime));
621 PathElement firstStage = destination;
622 PathElement secondStage = null;
623 while (firstStage.comingFrom != null) {
624 secondStage = firstStage;
625 firstStage = firstStage.comingFrom;
627 int arrivalTimeAtLastStop = destination.arrivalTime;
628 int departureTimeAtFirstStop = destination.firstDepartureTime;
629 if (departureTimeAtFirstStop == TIME_UNDEFINED) {
631 departureTimeAtFirstStop = arrivalTimeAtLastStop;
633 double accessTime = firstStage.initialStop.
accessTime;
634 double accessCost = firstStage.initialStop.accessCost;
636 double waitingTime = departureTimeAtFirstStop - firstStage.arrivalTime;
639 double travelCost = destination.arrivalTravelCost - firstStage.arrivalTravelCost - waitingCost;
640 int transferCount = destination.transferCount;
641 if (destination.isTransfer && transferCount > 0) {
644 if (secondStage != null && secondStage.isTransfer && transferCount > 0) {
648 return new TravelInfo(departureStopId, departureTimeAtFirstStop, arrivalTimeAtLastStop, travelCost, accessTime, accessCost, transferCount, waitingTime, waitingCost, destination);
652 this.improvedStops.clear();
653 this.reachedRouteStopIndices.clear();
659 for (
int firstRouteStopIndex = this.improvedRouteStopIndices.nextSetBit(0); firstRouteStopIndex >= 0; firstRouteStopIndex = this.improvedRouteStopIndices.nextSetBit(firstRouteStopIndex+1)) {
660 RRouteStop firstRouteStop = this.data.routeStops[firstRouteStopIndex];
661 if (firstRouteStop.transitRouteIndex == routeIndex) {
664 int tmpRouteIndex = firstRouteStop.transitRouteIndex;
667 RRoute route = this.data.routes[tmpRouteIndex];
671 PathElement boardingPE = this.arrivalPathPerRouteStop[firstRouteStopIndex];
672 int agentFirstArrivalTime = boardingPE.arrivalTime;
673 int currentBoardingRouteStopIndex = firstRouteStopIndex;
675 if (currentDepartureIndex >= 0) {
676 Vehicle currentVehicle = this.data.departureVehicles[currentDepartureIndex];
677 int currentDepartureTime = this.data.departures[currentDepartureIndex];
678 int currentAgentBoardingTime;
679 double currentTravelCostWhenBoarding;
680 double currentTransferCostWhenBoarding;
682 int vehicleArrivalTime = currentDepartureTime + firstRouteStop.arrivalOffset;
683 currentAgentBoardingTime = Math.max(agentFirstArrivalTime, vehicleArrivalTime);
684 int waitingTime = currentAgentBoardingTime - agentFirstArrivalTime;
685 double waitingCost = -marginalUtilityOfWaitingPt_utl_s * waitingTime;
686 currentTravelCostWhenBoarding = boardingPE.arrivalTravelCost + waitingCost;
687 currentTransferCostWhenBoarding = boardingPE.arrivalTransferCost;
690 if ((currentTravelCostWhenBoarding + currentTransferCostWhenBoarding) > this.bestArrivalCost) {
693 routeIndex = tmpRouteIndex;
694 int firstDepartureTime = (boardingPE.firstDepartureTime ==
TIME_UNDEFINED) ? currentAgentBoardingTime : boardingPE.firstDepartureTime;
697 !useTransportModeUtilities ? boardingPE.toRouteStop.mode : boardingPE.toRouteStop.route.getTransportMode());
698 transferProvider.reset(boardingPE.transfer);
700 for (
int toRouteStopIndex = firstRouteStopIndex + 1; toRouteStopIndex < route.indexFirstRouteStop + route.countRouteStops; toRouteStopIndex++) {
701 RRouteStop toRouteStop = this.data.routeStops[toRouteStopIndex];
702 if (!toRouteStop.routeStop.isAllowAlighting()) {
705 this.routeSegmentIterator.reset(currentDepartureIndex, currentAgentBoardingTime, currentBoardingRouteStopIndex, toRouteStopIndex);
706 int arrivalTime = currentDepartureTime + toRouteStop.arrivalOffset;
707 int inVehicleTime = arrivalTime - currentAgentBoardingTime;
708 double inVehicleCost = this.inVehicleCostCalculator.
getInVehicleCost(inVehicleTime, marginalUtilityOfTravelTime_utl_s, person, currentVehicle, parameters, routeSegmentIterator);
709 double arrivalTravelCost = currentTravelCostWhenBoarding + inVehicleCost;
710 double arrivalTransferCost = (boardingPE.firstDepartureTime !=
TIME_UNDEFINED) ? (currentTransferCostWhenBoarding + this.transferCostCalculator.
calcTransferCost(boardingPE,transferProvider, data.config, parameters, arrivalTime - firstDepartureTime, boardingPE.transferCount, boardingPE.arrivalTransferCost, boardingPE.arrivalTime)) : 0;
711 double previousArrivalCost = this.leastArrivalCostAtRouteStop[toRouteStopIndex];
712 double totalArrivalCost = arrivalTravelCost + arrivalTransferCost;
713 if (totalArrivalCost <= previousArrivalCost) {
714 double distance = toRouteStop.distanceAlongRoute - boardingPE.toRouteStop.distanceAlongRoute;
715 PathElement pe =
new PathElement(boardingPE, toRouteStop, firstDepartureTime, currentAgentBoardingTime, currentDepartureTime + firstRouteStop.departureOffset, arrivalTime, arrivalTravelCost, arrivalTransferCost, distance, boardingPE.transferCount,
false, null, null);
716 this.arrivalPathPerRouteStop[toRouteStopIndex] = pe;
717 this.leastArrivalCostAtRouteStop[toRouteStopIndex] = totalArrivalCost;
718 if (totalArrivalCost <= this.leastArrivalCostAtStop[toRouteStop.stopFacilityIndex]) {
719 this.leastArrivalCostAtStop[toRouteStop.stopFacilityIndex] = totalArrivalCost;
720 this.arrivalPathPerStop[toRouteStop.stopFacilityIndex] = pe;
721 this.improvedStops.set(toRouteStop.stopFacilityIndex);
727 PathElement alternativeBoardingPE = this.arrivalPathPerRouteStop[toRouteStopIndex];
728 int alternativeAgentFirstArrivalTime = alternativeBoardingPE.arrivalTime;
729 int alternativeDepartureIndex =
findNextDepartureIndex(route, toRouteStop, alternativeAgentFirstArrivalTime);
730 if (alternativeDepartureIndex >= 0) {
731 int alternativeDepartureTime = this.data.departures[alternativeDepartureIndex];
732 int alternativeVehicleArrivalTime = alternativeDepartureTime + toRouteStop.arrivalOffset;
733 int alternativeAgentBoardingTime = Math.max(alternativeAgentFirstArrivalTime, alternativeVehicleArrivalTime);
734 int alternativeWaitingTime = alternativeAgentBoardingTime - alternativeAgentFirstArrivalTime;
735 double alternativeWaitingCost = -marginalUtilityOfWaitingPt_utl_s * alternativeWaitingTime;
736 double alternativeTravelCostWhenBoarding = alternativeBoardingPE.arrivalTravelCost + alternativeWaitingCost;
737 double alternativeTotalCostWhenBoarding = alternativeTravelCostWhenBoarding + alternativeBoardingPE.arrivalTransferCost;
738 if (alternativeTotalCostWhenBoarding < totalArrivalCost) {
739 currentDepartureIndex = alternativeDepartureIndex;
740 currentVehicle = this.data.departureVehicles[currentDepartureIndex];
741 currentDepartureTime = alternativeDepartureTime;
742 if (alternativeBoardingPE.isTransfer) {
743 firstRouteStop = this.data.routeStops[toRouteStopIndex];
747 alternativeBoardingPE = alternativeBoardingPE.comingFrom;
748 alternativeAgentFirstArrivalTime = alternativeBoardingPE.arrivalTime;
749 alternativeVehicleArrivalTime = alternativeDepartureTime + alternativeBoardingPE.toRouteStop.arrivalOffset;
750 alternativeAgentBoardingTime = Math.max(alternativeAgentFirstArrivalTime, alternativeVehicleArrivalTime);
752 alternativeWaitingTime = alternativeAgentBoardingTime - alternativeAgentFirstArrivalTime;
753 alternativeWaitingCost = -marginalUtilityOfWaitingPt_utl_s * alternativeWaitingTime;
754 alternativeTravelCostWhenBoarding = alternativeBoardingPE.arrivalTravelCost + alternativeWaitingCost;
756 firstRouteStop = alternativeBoardingPE.toRouteStop;
758 currentAgentBoardingTime = alternativeAgentBoardingTime;
759 currentTravelCostWhenBoarding = alternativeTravelCostWhenBoarding;
760 currentTransferCostWhenBoarding = alternativeBoardingPE.arrivalTransferCost;
761 boardingPE = alternativeBoardingPE;
762 firstDepartureTime = (boardingPE.firstDepartureTime ==
TIME_UNDEFINED) ? currentAgentBoardingTime : boardingPE.firstDepartureTime;
763 currentBoardingRouteStopIndex = alternativeBoardingPE.toRouteStop.index;
767 firstRouteStopIndex = toRouteStopIndex;
774 if (this.destinationRouteStopIndices.get(routeStopIndex)) {
776 double totalCost = arrivalCost + this.egressCostsPerRouteStop[routeStopIndex];
777 if (totalCost < this.bestArrivalCost) {
778 this.bestArrivalCost = totalCost;
784 if (this.useCapacityConstraints) {
787 int depTimeAtRouteStart = time - routeStop.departureOffset;
788 int fromIndex = route.indexFirstDeparture;
789 int toIndex = fromIndex + route.countDepartures;
790 int pos = Arrays.binarySearch(this.data.departures, fromIndex, toIndex, depTimeAtRouteStart);
799 if (pos >= toIndex) {
811 this.improvedRouteStopIndices.clear();
812 this.tmpImprovedStops.clear();
816 for (
int stopIndex = this.improvedStops.nextSetBit(0); stopIndex >= 0; stopIndex = this.improvedStops.nextSetBit(stopIndex + 1)) {
817 PathElement fromPE = this.arrivalPathPerStop[stopIndex];
818 int arrivalTime = fromPE.arrivalTime;
819 double arrivalTravelCost = fromPE.arrivalTravelCost;
820 double arrivalTransferCost = fromPE.arrivalTransferCost;
821 double totalArrivalCost = arrivalTravelCost + arrivalTransferCost;
822 if (totalArrivalCost > this.bestArrivalCost) {
825 RRouteStop fromRouteStop = fromPE.toRouteStop;
827 final int firstTransferIndex;
828 final int lastTransferIndex;
831 if (!useAdaptiveTransferCalculation) {
833 transfers = this.data.transfers;
834 firstTransferIndex = fromRouteStop.indexFirstTransfer;
835 lastTransferIndex = firstTransferIndex + fromRouteStop.countTransfers;
838 transfers = this.data.calculateTransfers(fromRouteStop);
839 firstTransferIndex = 0;
840 lastTransferIndex = transfers.length;
843 for (
int transferIndex = firstTransferIndex; transferIndex < lastTransferIndex; transferIndex++) {
844 RTransfer transfer = transfers[transferIndex];
846 int toRouteStopIndex = transfer.toRouteStop;
847 transferProvider.reset(transfer);
848 int newArrivalTime = arrivalTime + transfer.transferTime;
849 double newArrivalTravelCost = arrivalTravelCost - transfer.transferTime * margUtilityTransitWalk;
850 double newArrivalTransferCost = (fromPE.firstDepartureTime !=
TIME_UNDEFINED) ? (arrivalTransferCost + this.transferCostCalculator.
calcTransferCost(fromPE, transferProvider, data.config, raptorParams, newArrivalTime - fromPE.firstDepartureTime, fromPE.transferCount + 1, arrivalTransferCost, arrivalTime)) : 0;
851 double newTotalArrivalCost = newArrivalTravelCost + newArrivalTransferCost;
852 double prevLeastArrivalCost = this.leastArrivalCostAtRouteStop[toRouteStopIndex];
853 if (newTotalArrivalCost < prevLeastArrivalCost || (!strict && newTotalArrivalCost <= prevLeastArrivalCost)) {
854 RRouteStop toRouteStop = this.data.routeStops[toRouteStopIndex];
855 PathElement pe =
new PathElement(fromPE, toRouteStop, fromPE.firstDepartureTime, TIME_UNDEFINED, TIME_UNDEFINED, newArrivalTime, newArrivalTravelCost, newArrivalTransferCost, transfer.transferDistance, fromPE.transferCount + 1,
true, transfer, null);
856 this.arrivalPathPerRouteStop[toRouteStopIndex] = pe;
857 this.leastArrivalCostAtRouteStop[toRouteStopIndex] = newTotalArrivalCost;
858 this.improvedRouteStopIndices.set(toRouteStopIndex);
859 int toStopFacilityIndex = toRouteStop.stopFacilityIndex;
860 prevLeastArrivalCost = this.leastArrivalCostAtStop[toStopFacilityIndex];
861 if (newTotalArrivalCost < prevLeastArrivalCost || (!strict && newTotalArrivalCost <= prevLeastArrivalCost)) {
863 this.leastArrivalCostAtStop[toStopFacilityIndex] = newTotalArrivalCost;
864 this.tmpArrivalPathPerStop[toStopFacilityIndex] = pe;
865 this.tmpImprovedStops.set(toStopFacilityIndex);
871 for (
int stopIndex = this.tmpImprovedStops.nextSetBit(0); stopIndex >= 0; stopIndex = this.tmpImprovedStops.nextSetBit(stopIndex + 1)) {
872 PathElement pe = this.tmpArrivalPathPerStop[stopIndex];
873 this.arrivalPathPerStop[stopIndex] = pe;
878 double leastCost = Double.POSITIVE_INFINITY;
879 double leastCostFeederOnly = Double.POSITIVE_INFINITY;
880 PathElement leastCostPath = null;
881 PathElement leastCostPathFeederOnly = null;
887 int stopIndex = this.data.stopFacilityIndices.get(stop);
888 PathElement pe = this.arrivalPathPerStop[stopIndex];
891 int arrivalTime = (int) (pe.arrivalTime + egressStop.accessTime);
892 double arrivalTravelCost = pe.arrivalTravelCost + egressStop.accessCost;
893 double totalCost = arrivalTravelCost + pe.arrivalTransferCost;
894 if ((totalCost < leastCost) || (totalCost == leastCost && pe.transferCount < leastCostPath.transferCount)) {
895 PathElement egressLegCandidate =
new PathElement(pe, null, pe.firstDepartureTime, TIME_UNDEFINED, TIME_UNDEFINED, arrivalTime, arrivalTravelCost, pe.arrivalTransferCost, egressStop.distance, pe.transferCount,
true, null, egressStop);
897 if (pe.comingFrom == null && checkBothPtAndPurelyIntermodalRoutes) {
898 if (totalCost < leastCostFeederOnly) {
899 leastCostFeederOnly = totalCost;
900 leastCostPathFeederOnly = egressLegCandidate;
904 leastCostPath = egressLegCandidate;
905 leastCost = totalCost;
913 if (checkBothPtAndPurelyIntermodalRoutes){
914 if (Double.isInfinite(leastCost)){
915 return leastCostPathFeederOnly;
918 return leastCostPath;
922 ArrayList<PathElement> pes =
new ArrayList<>();
923 double arrivalCost = Double.POSITIVE_INFINITY;
924 if (destinationPathElement != null) {
925 arrivalCost = destinationPathElement.arrivalTravelCost + destinationPathElement.arrivalTransferCost;
926 PathElement pe = destinationPathElement;
927 while (pe.comingFrom != null) {
933 Collections.reverse(pes);
936 double time = departureTime;
938 int peCount = pes.size();
940 for (PathElement pe : pes) {
942 TransitStopFacility toStop = pe.toRouteStop == null ? null : pe.toRouteStop.routeStop.getStopFacility();
943 double travelTime = pe.arrivalTime - time;
944 if (pe.initialStop != null && pe.initialStop.planElements != null) {
945 raptorRoute.addPlanElements(time, travelTime, pe.initialStop.planElements);
946 }
else if (pe.isTransfer) {
952 if ((peCount > 2 || peCount == 2 && !pes.get(0).isTransfer) && i == peCount - 2 && pes.get(i + 1).isTransfer && (!
isIntermodal(pes.get(i + 1).initialStop))) {
959 raptorRoute.addNonPt(fromStop, toStop, time, travelTime, pe.distance, mode);
963 raptorRoute.addPt(fromStop, toStop, line, route, pe.toRouteStop.mode, time, pe.boardingTime, pe.vehDepartureTime, pe.arrivalTime, pe.distance);
965 time = pe.arrivalTime;
972 return initialStop != null && initialStop.planElements != null;
975 static class PathElement {
976 final PathElement comingFrom;
977 final RRouteStop toRouteStop;
978 final int firstDepartureTime;
979 final int boardingTime;
980 final int vehDepartureTime;
981 final int arrivalTime;
982 double arrivalTravelCost;
983 double arrivalTransferCost;
984 final double distance;
985 final int transferCount;
986 final boolean isTransfer;
990 PathElement(PathElement comingFrom, RRouteStop toRouteStop,
int firstDepartureTime,
int boardingTime,
int vehDeparturetime,
int arrivalTime,
double arrivalTravelCost,
double arrivalTransferCost,
double distance,
int transferCount,
boolean isTransfer,
RTransfer transfer,
InitialStop initialStop) {
991 this.comingFrom = comingFrom;
992 this.toRouteStop = toRouteStop;
993 this.firstDepartureTime = firstDepartureTime;
994 this.boardingTime = boardingTime;
995 this.vehDepartureTime = vehDeparturetime;
996 this.arrivalTime = arrivalTime;
997 this.arrivalTravelCost = arrivalTravelCost;
998 this.arrivalTransferCost = arrivalTransferCost;
999 this.distance = distance;
1000 this.transferCount = transferCount;
1001 this.isTransfer = isTransfer;
1002 this.transfer = transfer;
1003 this.initialStop = initialStop;
1008 final RRouteStop routeStop;
1010 final int departureIndex;
1011 final int routeStopIndex;
1013 final double costOffset;
1016 this.routeStop = routeStop;
1017 this.routeStopIndex = routeStopIndex;
1018 this.departureIndex = departureIndex;
1019 this.depTime = depTime;
1020 this.costOffset = costOffset;
1021 this.accessStop = accessStop;
1049 TravelInfo(
Id<TransitStopFacility> departureStop,
double departureTime,
double arrivalTime,
double travelCost,
double accessTime,
double accessCost,
int transferCount,
double waitingTime,
double waitingCost, PathElement destinationPath) {
1050 this.departureStop = departureStop;
1051 this.ptDepartureTime = departureTime;
1052 this.ptArrivalTime = arrivalTime;
1053 this.ptTravelTime = arrivalTime - departureTime;
1054 this.travelCost = travelCost;
1055 this.accessTime = accessTime;
1056 this.accessCost = accessCost;
1057 this.transferCount = transferCount;
1058 this.waitingTime = waitingTime;
1059 this.waitingCost = waitingCost;
1060 this.destinationPath = destinationPath;
1064 PathElement firstPath = this.destinationPath;
1065 while (firstPath.comingFrom != null) {
1066 firstPath = firstPath.comingFrom;
1069 Facility fromFacility = firstPath.toRouteStop.routeStop.getStopFacility();
1070 Facility toFacility = this.destinationPath.toRouteStop.routeStop.getStopFacility();
1071 return createRaptorRoute(fromFacility, toFacility, this.destinationPath, firstPath.arrivalTime);
1075 if (this.destinationPath.comingFrom == null) {
1078 PathElement pe = this.destinationPath;
1079 while (pe != null) {
1080 if (!pe.isTransfer) {
1099 private double currentInVehicleTime = -1;
1100 private double currentPassengerCount = -1;
1101 private double currentTimeOfDay = -1;
1108 void reset(
int departureIndex,
int boardingTime,
int fromRouteStopIndex,
int toRouteStopIndex) {
1109 this.boardingTime = boardingTime;
1110 this.fromRouteStopIndex = fromRouteStopIndex;
1111 this.toRouteStopIndex = toRouteStopIndex;
1113 this.routeDepartureTime = this.data.departures[departureIndex];
1114 this.currentRouteStopIndex = fromRouteStopIndex;
1115 this.currentInVehicleTime = -1;
1116 this.currentPassengerCount = -1;
1117 this.currentTimeOfDay = -1;
1118 this.currentDepartureId = this.data.departureIds[departureIndex];
1123 return this.currentRouteStopIndex < this.toRouteStopIndex;
1128 if (this.currentRouteStopIndex >= this.toRouteStopIndex) {
1129 throw new NoSuchElementException();
1132 int departureRouteStopIndex = this.currentRouteStopIndex;
1133 this.currentRouteStopIndex++;
1134 int nextRouteStopIndex = this.currentRouteStopIndex;
1135 RRouteStop depRouteStop = this.data.routeStops[departureRouteStopIndex];
1136 int startTime = this.routeDepartureTime + depRouteStop.departureOffset;
1137 if (departureRouteStopIndex == this.fromRouteStopIndex) {
1138 startTime = this.boardingTime;
1140 RRouteStop nextRouteStop = this.data.routeStops[nextRouteStopIndex];
1141 int endTime = this.routeDepartureTime + nextRouteStop.departureOffset;
1142 if (nextRouteStopIndex == this.toRouteStopIndex) {
1143 endTime = this.routeDepartureTime + nextRouteStop.arrivalOffset;
1145 this.currentInVehicleTime = endTime - startTime;
1146 this.currentTimeOfDay = startTime;
1148 DepartureData depData = this.data.occupancyData.
getDepartureData(nextRouteStop.line.getId(), nextRouteStop.route.getId(), depRouteStop.routeStop.getStopFacility().getId(), this.currentDepartureId);
1149 this.currentPassengerCount = depData == null ? 0 : depData.paxCountAtDeparture;
1154 return this.currentInVehicleTime;
1159 return this.currentPassengerCount;
1164 return this.currentTimeOfDay;
double getMinimalTransferTime()
double getMarginalUtilityOfTravelTime_utl_s(String mode)
void arrivedAtStop(double departureTime, TransitStopFacility stopFacility, double arrivalTime, int transferCount, Supplier< RaptorRoute > route)
double getInVehicleCost(double inVehicleTime, double marginalUtility_utl_s, Person person, Vehicle vehicle, RaptorParameters paramters, RouteSegmentIterator iterator)
RouteSegmentIteratorImpl(SwissRailRaptorData data)
void observeArrival(PathElement pe, RaptorObserver observer)
final PathElement [] arrivalPathPerStop
RaptorRoute calcLeastCostRoute(double depTime, Facility fromFacility, Facility toFacility, List< InitialStop > accessStops, List< InitialStop > egressStops, RaptorParameters parameters, Person person)
DepartureData getDepartureData(Id< TransitLine > transitLine, Id< TransitRoute > transitRoute, Id< TransitStopFacility > stopFacility, Id< Departure > departure)
SwissRailRaptorConfigGroup.IntermodalLegOnlyHandling getIntermodalLegOnlyHandling()
boolean isUseCapacityConstraints()
List< RaptorRoute > filterRoutes(List< RaptorRoute > allRoutes)
final BitSet destinationRouteStopIndices
final BitSet reachedRouteStopIndices
double getInVehicleTime()
double getPassengerCount()
final SwissRailRaptorData data
final double ptTravelTime
final boolean useAdaptiveTransferCalculation
final BitSet improvedStops
int findNextDepartureIndex(RRoute route, RRouteStop routeStop, int time)
final double ptDepartureTime
double getMarginalUtilityOfWaitingPt_utl_s()
final double [] leastArrivalCostAtStop
PathElement findLeastCostArrival(Map< TransitStopFacility, InitialStop > destinationStops)
void checkForBestArrival(int routeStopIndex, double arrivalCost)
static final int TIME_UNDEFINED
void exploreRoutes(RaptorParameters parameters, Person person, CachingTransferProvider transferProvider)
final RouteSegmentIteratorImpl routeSegmentIterator
boolean isUseTransportModeUtilities()
final BitSet improvedRouteStopIndices
List< RaptorRoute > calcRoutes(double earliestDepTime, double desiredDepTime, double latestDepTime, Facility fromFacility, Facility toFacility, List< InitialStop > accessStops, List< InitialStop > egressStops, RaptorParameters parameters, Person person)
final BitSet tmpImprovedStops
final PathElement destinationPath
final RaptorTransferCostCalculator transferCostCalculator
static RaptorRoute createRaptorRoute(Facility fromFacility, Facility toFacility, PathElement destinationPathElement, double departureTime)
Map< Id< TransitStopFacility >, TravelInfo > calcLeastCostTree(double depTime, Collection< InitialStop > startStops, RaptorParameters parameters, Person person, RaptorObserver observer)
RaptorTransferCalculation getTransferCalculation()
Map< Id< TransitStopFacility >, TravelInfo > calcLeastCostTree(double depTime, Collection< InitialStop > startStops, RaptorParameters parameters, Person person)
final double [] leastArrivalCostAtRouteStop
final double [] egressCostsPerRouteStop
double calcTransferCost(SwissRailRaptorCore.PathElement currentPE, Supplier< Transfer > transfer, RaptorStaticConfig staticConfig, RaptorParameters raptorParams, int totalTravelTime, int totalTransferCount, double existingTransferCosts, double currentTime)
RaptorRoute getRaptorRoute()
final Id< TransitStopFacility > departureStop
TravelInfo getTravelInfo(PathElement destination, RaptorParameters parameters)
DepartureData getNextAvailableDeparture(Id< TransitLine > transitLine, Id< TransitRoute > transitRoute, Id< TransitStopFacility > stopFacility, double time)
void handleTransfers(boolean strict, RaptorParameters raptorParams, CachingTransferProvider transferProvider)
final double ptArrivalTime
final PathElement [] arrivalPathPerRouteStop
int findNextDepartureIndexWithConstraints(RRoute route, RRouteStop routeStop, int time)
int currentRouteStopIndex
final PathElement [] tmpArrivalPathPerStop
double calculateOptimalDepartureTime(PathElement leastCostPath, Map< PathElement, InitialStop > initialStopsPerStartPath)
static boolean isIntermodal(InitialStop initialStop)
final RaptorInVehicleCostCalculator inVehicleCostCalculator
final boolean useCapacityConstraints