From 636f36ba3bc42d77cb2aad252a3fddaa4f85f954 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 5 Jul 2023 22:01:10 +0300 Subject: [PATCH 01/36] Add cost function to RemoveTransitIfStreetOnlyIsBetter filter --- .../ItineraryListFilterChainBuilder.java | 19 ++++++++---- ...moveTransitIfStreetOnlyIsBetterFilter.java | 20 ++++++++---- .../RouteRequestToFilterChainMapper.java | 4 ++- .../ItineraryFilterPreferences.java | 31 ++++++++++++++++++- .../routerequest/ItineraryFiltersConfig.java | 19 ++++++++++++ ...TransitIfStreetOnlyIsBetterFilterTest.java | 13 +++++--- 6 files changed, 87 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java index 3597558978b..2cefe6dde11 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java @@ -56,7 +56,7 @@ public class ItineraryListFilterChainBuilder { private ItineraryFilterDebugProfile debug = ItineraryFilterDebugProfile.OFF; private int maxNumberOfItineraries = NOT_SET; private ListSection maxNumberOfItinerariesCrop = ListSection.TAIL; - private boolean removeTransitWithHigherCostThanBestOnStreetOnly = true; + private DoubleAlgorithmFunction removeTransitWithHigherCostThanBestOnStreetOnly; private boolean removeWalkAllTheWayResults; private boolean sameFirstOrLastTripFilter; private TransitGeneralizedCostFilterParams transitGeneralizedCostFilterParams; @@ -193,7 +193,7 @@ public ItineraryListFilterChainBuilder withParkAndRideDurationRatio(double value * exist. */ public ItineraryListFilterChainBuilder withRemoveTransitWithHigherCostThanBestOnStreetOnly( - boolean value + DoubleAlgorithmFunction value ) { this.removeTransitWithHigherCostThanBestOnStreetOnly = value; return this; @@ -337,6 +337,17 @@ public ItineraryListFilterChain build() { ); } + // Filter transit itineraries by comparing against non-transit using generalized-cost + if (removeTransitWithHigherCostThanBestOnStreetOnly != null) { + filters.add( + new DeletionFlaggingFilter( + new RemoveTransitIfStreetOnlyIsBetterFilter( + removeTransitWithHigherCostThanBestOnStreetOnly + ) + ) + ); + } + // Apply all absolute filters AFTER the groupBy filters. Absolute filters are filters that // remove elements/ based on the given itinerary properties - not considering other // itineraries. This may remove itineraries in the "groupBy" filters that are considered @@ -347,10 +358,6 @@ public ItineraryListFilterChain build() { // is worse). B is removed by the {@link LatestDepartureTimeFilter} below. This is exactly // what we want, since both itineraries are none optimal. { - if (removeTransitWithHigherCostThanBestOnStreetOnly) { - filters.add(new DeletionFlaggingFilter(new RemoveTransitIfStreetOnlyIsBetterFilter())); - } - if (removeWalkAllTheWayResults) { filters.add(new DeletionFlaggingFilter(new RemoveWalkOnlyFilter())); } diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java index 7296f9b22de..ce554666f36 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java @@ -2,9 +2,10 @@ import java.util.Comparator; import java.util.List; -import java.util.Optional; +import java.util.OptionalDouble; import java.util.stream.Collectors; import org.opentripplanner.model.plan.Itinerary; +import org.opentripplanner.routing.api.request.framework.DoubleAlgorithmFunction; /** * Filter itineraries based on generalizedCost, compared with a on-street-all-the-way itinerary(if @@ -13,6 +14,12 @@ */ public class RemoveTransitIfStreetOnlyIsBetterFilter implements ItineraryDeletionFlagger { + private final DoubleAlgorithmFunction costLimitFunction; + + public RemoveTransitIfStreetOnlyIsBetterFilter(DoubleAlgorithmFunction costLimitFunction) { + this.costLimitFunction = costLimitFunction; + } + /** * Required for {@link org.opentripplanner.routing.algorithm.filterchain.ItineraryListFilterChain}, * to know which filters removed @@ -27,18 +34,19 @@ public String name() { @Override public List flagForRemoval(List itineraries) { // Find the best walk-all-the-way option - Optional bestStreetOp = itineraries + OptionalDouble minStreetCost = itineraries .stream() .filter(Itinerary::isOnStreetAllTheWay) - .min(Comparator.comparingInt(Itinerary::getGeneralizedCost)); + .mapToDouble(Itinerary::getGeneralizedCost) + .min(); - if (bestStreetOp.isEmpty()) { + if (minStreetCost.isEmpty()) { return List.of(); } - final long limit = bestStreetOp.get().getGeneralizedCost(); + final double limit = costLimitFunction.calculate(minStreetCost.getAsDouble()); - // Filter away itineraries that have higher cost than the best non-transit option. + // Filter away itineraries that have higher cost than limit cost computed above return itineraries .stream() .filter(it -> !it.isOnStreetAllTheWay() && it.getGeneralizedCost() >= limit) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java b/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java index 7f5c72c261c..e9c2b63f9fe 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java @@ -60,6 +60,9 @@ public static ItineraryListFilterChain createFilterChain( .withBikeRentalDistanceRatio(params.bikeRentalDistanceRatio()) .withParkAndRideDurationRatio(params.parkAndRideDurationRatio()) .withNonTransitGeneralizedCostLimit(params.nonTransitGeneralizedCostLimit()) + .withRemoveTransitWithHigherCostThanBestOnStreetOnlyh( + params.removeTransitWithHigherCostThanBestOnStreetOnly() + ) .withSameFirstOrLastTripFilter(params.filterItinerariesWithSameFirstOrLastTrip()) .withAccessibilityScore( params.useAccessibilityScore() && request.wheelchair(), @@ -74,7 +77,6 @@ public static ItineraryListFilterChain createFilterChain( context.transitService().getTransitAlertService(), context.transitService()::getMultiModalStationForStation ) - .withRemoveTransitWithHigherCostThanBestOnStreetOnly(true) .withLatestDepartureTimeLimit(filterOnLatestDepartureTime) .withMaxLimitReachedSubscriber(maxLimitReachedSubscriber) .withRemoveWalkAllTheWayResults(removeWalkAllTheWayResults) diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java index bc43df55733..5f65196e581 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java @@ -45,6 +45,8 @@ private ItineraryFilterPreferences() { this.removeItinerariesWithSameRoutesAndStops = false; this.transitGeneralizedCostLimit = new TransitGeneralizedCostFilterParams(RequestFunctions.createLinearFunction(900, 1.5), 0.4); + this.removeTransitWithHigherCostThanBestOnStreetOnly = + RequestFunctions.createLinearFunction(200, 1.5); } private ItineraryFilterPreferences(Builder builder) { @@ -63,6 +65,8 @@ private ItineraryFilterPreferences(Builder builder) { this.parkAndRideDurationRatio = Units.ratio(builder.parkAndRideDurationRatio); this.removeItinerariesWithSameRoutesAndStops = builder.removeItinerariesWithSameRoutesAndStops; this.transitGeneralizedCostLimit = Objects.requireNonNull(builder.transitGeneralizedCostLimit); + this.removeTransitWithHigherCostThanBestOnStreetOnly = + Objects.requireNonNull(builder.removeTransitWithHigherCostThanBestOnStreetOnly); } public static Builder of() { @@ -121,6 +125,10 @@ public TransitGeneralizedCostFilterParams transitGeneralizedCostLimit() { return transitGeneralizedCostLimit; } + public DoubleAlgorithmFunction removeTransitWithHigherCostThanBestOnStreetOnly() { + return removeTransitWithHigherCostThanBestOnStreetOnly; + } + @Override public String toString() { return ToStringBuilder @@ -163,6 +171,11 @@ public String toString() { "removeItinerariesWithSameRoutesAndStops", removeItinerariesWithSameRoutesAndStops ) + .addObj( + "removeTransitWithHigherCostThanBestOnStreetOnly", + nonTransitGeneralizedCostLimit, + DEFAULT.nonTransitGeneralizedCostLimit + ) .toString(); } @@ -187,6 +200,10 @@ public boolean equals(Object o) { Double.compare(that.parkAndRideDurationRatio, parkAndRideDurationRatio) == 0 && removeItinerariesWithSameRoutesAndStops == that.removeItinerariesWithSameRoutesAndStops && Objects.equals(nonTransitGeneralizedCostLimit, that.nonTransitGeneralizedCostLimit) && + Objects.equals( + removeTransitWithHigherCostThanBestOnStreetOnly, + that.removeTransitWithHigherCostThanBestOnStreetOnly + ) && Objects.equals(transitGeneralizedCostLimit, that.transitGeneralizedCostLimit) ); } @@ -205,7 +222,8 @@ public int hashCode() { nonTransitGeneralizedCostLimit, parkAndRideDurationRatio, removeItinerariesWithSameRoutesAndStops, - transitGeneralizedCostLimit + transitGeneralizedCostLimit, + removeTransitWithHigherCostThanBestOnStreetOnly ); } @@ -224,6 +242,7 @@ public static class Builder { private double parkAndRideDurationRatio; private boolean removeItinerariesWithSameRoutesAndStops; private TransitGeneralizedCostFilterParams transitGeneralizedCostLimit; + private DoubleAlgorithmFunction removeTransitWithHigherCostThanBestOnStreetOnly; public ItineraryFilterPreferences original() { return original; @@ -299,6 +318,14 @@ public Builder withTransitGeneralizedCostLimit( return this; } + public Builder withRemoveTransitWithHigherCostThanBestOnStreetOnly( + DoubleAlgorithmFunction removeTransitWithHigherCostThanBestOnStreetOnly + ) { + this.removeTransitWithHigherCostThanBestOnStreetOnly = + removeTransitWithHigherCostThanBestOnStreetOnly; + return this; + } + public Builder(ItineraryFilterPreferences original) { this.original = original; this.accessibilityScore = original.accessibilityScore; @@ -316,6 +343,8 @@ public Builder(ItineraryFilterPreferences original) { this.removeItinerariesWithSameRoutesAndStops = original.removeItinerariesWithSameRoutesAndStops; this.transitGeneralizedCostLimit = original.transitGeneralizedCostLimit; + this.removeTransitWithHigherCostThanBestOnStreetOnly = + original.removeTransitWithHigherCostThanBestOnStreetOnly; } public Builder apply(Consumer body) { diff --git a/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java index aa6c88bf44b..bf97fe4254a 100644 --- a/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java +++ b/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java @@ -154,6 +154,25 @@ public static void mapItineraryFilterParams( ) .asLinearFunction(dft.nonTransitGeneralizedCostLimit()) ) + .withRemoveTransitWithHigherCostThanBestOnStreetOnly( + c + .of("removeTransitWithHigherCostThanBestOnStreetOnly") + .since(V2_1) + .summary( + "Limit function for generalized-cost computed from non-transit itineries for transit itineraries." + ) + .description( + """ +The max-limit is applied to itineraries with transit *legs*, and only itineraries +without transit legs are considered when calculating the minimum cost. The smallest +generalized-cost value is used as input to the function. The function is used to calculate a +*max-limit*. The max-limit is then used to filter *transit* itineraries by +*generalized-cost*. Itineraries with a cost higher than the max-limit are dropped from the result +set. +""" + ) + .asLinearFunction(dft.removeTransitWithHigherCostThanBestOnStreetOnly()) + ) .withBikeRentalDistanceRatio( c .of("bikeRentalDistanceRatio") diff --git a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilterTest.java b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilterTest.java index 5598c97cd57..0d086b51cd0 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilterTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilterTest.java @@ -8,6 +8,7 @@ import org.junit.jupiter.api.Test; import org.opentripplanner.model.plan.Itinerary; import org.opentripplanner.model.plan.PlanTestConstants; +import org.opentripplanner.routing.api.request.framework.RequestFunctions; public class RemoveTransitIfStreetOnlyIsBetterFilterTest implements PlanTestConstants { @@ -20,7 +21,7 @@ public void filterAwayNothingIfNoWalking() { // When: List result = DeletionFlaggerTestHelper.process( List.of(i1, i2), - new RemoveTransitIfStreetOnlyIsBetterFilter() + new RemoveTransitIfStreetOnlyIsBetterFilter(RequestFunctions.createLinearFunction(200, 1.2)) ); // Then: @@ -33,20 +34,22 @@ public void filterAwayLongTravelTimeWithoutWaitTime() { Itinerary walk = newItinerary(A, 6).walk(1, E).build(); walk.setGeneralizedCost(300); - // Given: a bicycle itinerary with low cost - transit with higher cost is removed + // Given: a bicycle itinerary with low cost - transit with clearly higher cost are removed Itinerary bicycle = newItinerary(A).bicycle(6, 8, E).build(); bicycle.setGeneralizedCost(200); + // transit with almost equal cost should not be dropped Itinerary i1 = newItinerary(A).bus(21, 6, 8, E).build(); - i1.setGeneralizedCost(199); + i1.setGeneralizedCost(220); + // transit with considerably higher cost will be dropped Itinerary i2 = newItinerary(A).bus(31, 6, 8, E).build(); - i2.setGeneralizedCost(200); + i2.setGeneralizedCost(360); // When: List result = DeletionFlaggerTestHelper.process( List.of(i2, bicycle, walk, i1), - new RemoveTransitIfStreetOnlyIsBetterFilter() + new RemoveTransitIfStreetOnlyIsBetterFilter(RequestFunctions.createLinearFunction(60, 1.2)) ); // Then: From 3621260ea483868d011b6f0cf0d457080cd22b06 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 6 Jul 2023 12:05:06 +0300 Subject: [PATCH 02/36] Apply hard filter for walking Softer cost limit function based filtering will sometimes preserve transit itineraries, which contain more walking than a plain walk itinerary. Therefore, apply harder filtering logic wrt. walking. --- ...moveTransitIfStreetOnlyIsBetterFilter.java | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java index ce554666f36..e0f38307843 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java @@ -5,6 +5,7 @@ import java.util.OptionalDouble; import java.util.stream.Collectors; import org.opentripplanner.model.plan.Itinerary; +import org.opentripplanner.model.plan.Leg; import org.opentripplanner.routing.api.request.framework.DoubleAlgorithmFunction; /** @@ -31,6 +32,14 @@ public String name() { return TAG; } + private double getWalkDistance(Itinerary it) { + return it + .getStreetLegs() + .filter(l -> l.isWalkingLeg()) + .mapToDouble(Leg::getDistanceMeters) + .sum(); + } + @Override public List flagForRemoval(List itineraries) { // Find the best walk-all-the-way option @@ -47,10 +56,33 @@ public List flagForRemoval(List itineraries) { final double limit = costLimitFunction.calculate(minStreetCost.getAsDouble()); // Filter away itineraries that have higher cost than limit cost computed above - return itineraries + List filtered = itineraries .stream() .filter(it -> !it.isOnStreetAllTheWay() && it.getGeneralizedCost() >= limit) .collect(Collectors.toList()); + + // Filter the most common silly itinerary case: transit itinerary has more walking than plain walk itinerary + // This never makes sense + OptionalDouble walkDistance = itineraries + .stream() + .filter(Itinerary::isWalkingAllTheWay) + .mapToDouble(Itinerary::distanceMeters) + .min(); + + if (walkDistance.isEmpty()) { + return filtered; + } + final double walkLimit = walkDistance.getAsDouble(); + List filtered2 = itineraries + .stream() + .filter(it -> getWalkDistance(it) > walkLimit) + .collect(Collectors.toList()); + + // remove duplicates + filtered2.removeAll(filtered); + filtered.addAll(filtered2); + + return filtered; } @Override From bfe2b61610b43057937875d99f27f1a664ab97e4 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 6 Jul 2023 13:42:19 +0300 Subject: [PATCH 03/36] Pass linear function as parameter for RemoveTransitIfStreetOnlyIsBetterFilter --- docs/RouteRequest.md | 254 ++++++++++-------- .../RouteRequestToFilterChainMapper.java | 2 +- .../ItineraryFilterPreferences.java | 13 +- .../routerequest/ItineraryFiltersConfig.java | 3 +- .../ItineraryListFilterChainTest.java | 17 +- .../ItineraryFilterPreferencesTest.java | 8 +- 6 files changed, 164 insertions(+), 133 deletions(-) diff --git a/docs/RouteRequest.md b/docs/RouteRequest.md index 77580b29a59..01a185ce24e 100644 --- a/docs/RouteRequest.md +++ b/docs/RouteRequest.md @@ -13,125 +13,126 @@ and in the [transferRequests in build-config.json](BuildConfiguration.md#transfe -| Config Parameter | Type | Summary | Req./Opt. | Default Value | Since | -|------------------------------------------------------------------------------------------------------|:----------------------:|------------------------------------------------------------------------------------------------------------------------------------------------|:----------:|--------------------------|:-----:| -| [alightSlack](#rd_alightSlack) | `duration` | The minimum extra time after exiting a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | -| arriveBy | `boolean` | Whether the trip should depart or arrive at the specified date and time. | *Optional* | `false` | 2.0 | -| [bikeBoardCost](#rd_bikeBoardCost) | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. | *Optional* | `600` | 2.0 | -| bikeParkCost | `integer` | Cost to park a bike. | *Optional* | `120` | 2.0 | -| bikeParkTime | `integer` | Time to park a bike. | *Optional* | `60` | 2.0 | -| bikeReluctance | `double` | A multiplier for how bad biking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| bikeSpeed | `double` | Max bike speed along streets, in meters per second | *Optional* | `5.0` | 2.0 | -| bikeStairsReluctance | `double` | How bad is it to walk the bicycle up/down a flight of stairs compared to taking a detour. | *Optional* | `10.0` | 2.3 | -| bikeSwitchCost | `integer` | The cost of the user fetching their bike and parking it again. | *Optional* | `0` | 2.0 | -| bikeSwitchTime | `integer` | The time it takes the user to fetch their bike and park it again in seconds. | *Optional* | `0` | 2.0 | -| bikeTriangleSafetyFactor | `double` | For bike triangle routing, how much safety matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeTriangleSlopeFactor | `double` | For bike triangle routing, how much slope matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeTriangleTimeFactor | `double` | For bike triangle routing, how much time matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeWalkingReluctance | `double` | A multiplier for how bad walking with a bike is, compared to being in transit for equal lengths of time. | *Optional* | `5.0` | 2.1 | -| bikeWalkingSpeed | `double` | The user's bike walking speed in meters/second. Defaults to approximately 3 MPH. | *Optional* | `1.33` | 2.1 | -| [boardSlack](#rd_boardSlack) | `duration` | The boardSlack is the minimum extra time to board a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | -| carAccelerationSpeed | `double` | The acceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | -| carDecelerationSpeed | `double` | The deceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | -| carDropoffTime | `integer` | Time to park a car in a park and ride, w/o taking into account driving and walking cost. | *Optional* | `120` | 2.0 | -| carParkCost | `integer` | Cost of parking a car. | *Optional* | `120` | 2.1 | -| carParkTime | `integer` | Time to park a car | *Optional* | `60` | 2.1 | -| carPickupCost | `integer` | Add a cost for car pickup changes when a pickup or drop off takes place | *Optional* | `120` | 2.1 | -| carPickupTime | `integer` | Add a time for car pickup changes when a pickup or drop off takes place | *Optional* | `60` | 2.1 | -| carReluctance | `double` | A multiplier for how bad driving is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| carSpeed | `double` | Max car speed along streets, in meters per second | *Optional* | `40.0` | 2.0 | -| [drivingDirection](#rd_drivingDirection) | `enum` | The driving direction to use in the intersection traversal calculation | *Optional* | `"right"` | 2.2 | -| elevatorBoardCost | `integer` | What is the cost of boarding a elevator? | *Optional* | `90` | 2.0 | -| elevatorBoardTime | `integer` | How long does it take to get on an elevator, on average. | *Optional* | `90` | 2.0 | -| elevatorHopCost | `integer` | What is the cost of travelling one floor on an elevator? | *Optional* | `20` | 2.0 | -| elevatorHopTime | `integer` | How long does it take to advance one floor on an elevator? | *Optional* | `20` | 2.0 | -| geoidElevation | `boolean` | If true, the Graph's ellipsoidToGeoidDifference is applied to all elevations returned by this query. | *Optional* | `false` | 2.0 | -| ignoreRealtimeUpdates | `boolean` | When true, realtime updates are ignored during this search. | *Optional* | `false` | 2.0 | -| [intersectionTraversalModel](#rd_intersectionTraversalModel) | `enum` | The model that computes the costs of turns. | *Optional* | `"simple"` | 2.2 | -| locale | `locale` | TODO | *Optional* | `"en_US"` | 2.0 | -| [maxAccessEgressDuration](#rd_maxAccessEgressDuration) | `duration` | This is the maximum duration for access/egress for street searches. | *Optional* | `"PT45M"` | 2.1 | -| [maxDirectStreetDuration](#rd_maxDirectStreetDuration) | `duration` | This is the maximum duration for a direct street search for each mode. | *Optional* | `"PT4H"` | 2.1 | -| [maxJourneyDuration](#rd_maxJourneyDuration) | `duration` | The expected maximum time a journey can last across all possible journeys for the current deployment. | *Optional* | `"PT24H"` | 2.1 | -| [modes](RoutingModes.md) | `string` | The set of access/egress/direct/transit modes to be used for the route search. | *Optional* | `"TRANSIT,WALK"` | 2.0 | -| nonpreferredTransferPenalty | `integer` | Penalty (in seconds) for using a non-preferred transfer. | *Optional* | `180` | 2.0 | -| numItineraries | `integer` | The maximum number of itineraries to return. | *Optional* | `50` | 2.0 | -| [optimize](#rd_optimize) | `enum` | The set of characteristics that the user wants to optimize for. | *Optional* | `"safe"` | 2.0 | -| [otherThanPreferredRoutesPenalty](#rd_otherThanPreferredRoutesPenalty) | `integer` | Penalty added for using every route that is not preferred if user set any route as preferred. | *Optional* | `300` | 2.0 | -| [relaxTransitSearchGeneralizedCostAtDestination](#rd_relaxTransitSearchGeneralizedCostAtDestination) | `double` | Whether non-optimal transit paths at the destination should be returned | *Optional* | | 2.3 | -| [searchWindow](#rd_searchWindow) | `duration` | The duration of the search-window. | *Optional* | | 2.0 | -| stairsReluctance | `double` | Used instead of walkReluctance for stairs. | *Optional* | `2.0` | 2.0 | -| [stairsTimeFactor](#rd_stairsTimeFactor) | `double` | How much more time does it take to walk a flight of stairs compared to walking a similar horizontal length. | *Optional* | `3.0` | 2.1 | -| [streetRoutingTimeout](#rd_streetRoutingTimeout) | `duration` | The maximum time a street routing request is allowed to take before returning the results. | *Optional* | `"PT5S"` | 2.2 | -| [transferPenalty](#rd_transferPenalty) | `integer` | An additional penalty added to boardings after the first. | *Optional* | `0` | 2.0 | -| [transferSlack](#rd_transferSlack) | `integer` | The extra time needed to make a safe transfer in seconds. | *Optional* | `120` | 2.0 | -| turnReluctance | `double` | Multiplicative factor on expected turning time. | *Optional* | `1.0` | 2.0 | -| [unpreferredCost](#rd_unpreferredCost) | `linear-function` | A cost function used to calculate penalty for an unpreferred route. | *Optional* | `"f(x) = 0 + 1.0 x"` | 2.2 | -| [unpreferredVehicleParkingTagCost](#rd_unpreferredVehicleParkingTagCost) | `integer` | What cost to add if a parking facility doesn't contain a preferred tag. | *Optional* | `300` | 2.3 | -| waitReluctance | `double` | How much worse is waiting for a transit vehicle than being on a transit vehicle, as a multiplier. | *Optional* | `1.0` | 2.0 | -| walkBoardCost | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. This is the cost that is used when boarding while walking. | *Optional* | `600` | 2.0 | -| [walkReluctance](#rd_walkReluctance) | `double` | A multiplier for how bad walking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| [walkSafetyFactor](#rd_walkSafetyFactor) | `double` | Factor for how much the walk safety is considered in routing. | *Optional* | `1.0` | 2.2 | -| walkSpeed | `double` | The user's walking speed in meters/second. | *Optional* | `1.33` | 2.0 | -| [accessEgressPenalty](#rd_accessEgressPenalty) | `enum map of object` | Penalty for access/egress by street mode. | *Optional* | | 2.4 | -| [alightSlackForMode](#rd_alightSlackForMode) | `enum map of duration` | How much extra time should be given when alighting a vehicle for each given mode. | *Optional* | | 2.0 | -| [bannedVehicleParkingTags](#rd_bannedVehicleParkingTags) | `string[]` | Tags with which a vehicle parking will not be used. If empty, no tags are banned. | *Optional* | | 2.1 | -| [boardSlackForMode](#rd_boardSlackForMode) | `enum map of duration` | How much extra time should be given when boarding a vehicle for each given mode. | *Optional* | | 2.0 | -| [itineraryFilters](#rd_itineraryFilters) | `object` | Configure itinerary filters that may modify itineraries, sort them, and filter away less preferable results. | *Optional* | | 2.0 | -|    [accessibilityScore](#rd_if_accessibilityScore) | `boolean` | An experimental feature contributed by IBI which adds a sandbox accessibility *score* between 0 and 1 for each leg and itinerary. | *Optional* | `false` | 2.2 | -|    [bikeRentalDistanceRatio](#rd_if_bikeRentalDistanceRatio) | `double` | Filter routes that consist of bike-rental and walking by the minimum fraction of the bike-rental leg using _distance_. | *Optional* | `0.0` | 2.1 | -|    [debug](#rd_if_debug) | `enum` | Enable this to attach a system notice to itineraries instead of removing them. This is very convenient when tuning the itinerary-filter-chain. | *Optional* | `"off"` | 2.0 | -|    [filterItinerariesWithSameFirstOrLastTrip](#rd_if_filterItinerariesWithSameFirstOrLastTrip) | `boolean` | If more than one itinerary begins or ends with same trip, filter out one of those itineraries so that only one remains. | *Optional* | `false` | 2.2 | -|    groupSimilarityKeepOne | `double` | Pick ONE itinerary from each group after putting itineraries that are 85% similar together. | *Optional* | `0.85` | 2.1 | -|    groupSimilarityKeepThree | `double` | Reduce the number of itineraries to three itineraries by reducing each group of itineraries grouped by 68% similarity. | *Optional* | `0.68` | 2.1 | -|    [groupedOtherThanSameLegsMaxCostMultiplier](#rd_if_groupedOtherThanSameLegsMaxCostMultiplier) | `double` | Filter grouped itineraries, where the non-grouped legs are more expensive than in the lowest cost one. | *Optional* | `2.0` | 2.1 | -|    [minBikeParkingDistance](#rd_if_minBikeParkingDistance) | `double` | Filter out bike park+ride results that have fewer meters of cycling than this value. | *Optional* | `0.0` | 2.3 | -|    [nonTransitGeneralizedCostLimit](#rd_if_nonTransitGeneralizedCostLimit) | `linear-function` | The function define a max-limit for generalized-cost for non-transit itineraries. | *Optional* | `"f(x) = 3,600 + 2.0 x"` | 2.1 | -|    [parkAndRideDurationRatio](#rd_if_parkAndRideDurationRatio) | `double` | Filter P+R routes that consist of driving and walking by the minimum fraction of the driving using of _time_. | *Optional* | `0.0` | 2.1 | -|    [removeItinerariesWithSameRoutesAndStops](#rd_if_removeItinerariesWithSameRoutesAndStops) | `boolean` | Set to true if you want to list only the first itinerary which goes through the same stops and routes. | *Optional* | `false` | 2.2 | -|    [transitGeneralizedCostLimit](#rd_if_transitGeneralizedCostLimit) | `object` | A relative limit for the generalized-cost for transit itineraries. | *Optional* | | 2.1 | -|       [costLimitFunction](#rd_if_transitGeneralizedCostLimit_costLimitFunction) | `linear-function` | The base function used by the filter. | *Optional* | `"f(x) = 900 + 1.5 x"` | 2.2 | -|       [intervalRelaxFactor](#rd_if_transitGeneralizedCostLimit_intervalRelaxFactor) | `double` | How much the filter should be relaxed for itineraries that do not overlap in time. | *Optional* | `0.4` | 2.2 | -| [maxAccessEgressDurationForMode](#rd_maxAccessEgressDurationForMode) | `enum map of duration` | Limit access/egress per street mode. | *Optional* | | 2.1 | -| [maxDirectStreetDurationForMode](#rd_maxDirectStreetDurationForMode) | `enum map of duration` | Limit direct route duration per street mode. | *Optional* | | 2.2 | -| [preferredVehicleParkingTags](#rd_preferredVehicleParkingTags) | `string[]` | Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised. | *Optional* | | 2.3 | -| [requiredVehicleParkingTags](#rd_requiredVehicleParkingTags) | `string[]` | Tags without which a vehicle parking will not be used. If empty, no tags are required. | *Optional* | | 2.1 | -| [transferOptimization](#rd_transferOptimization) | `object` | Optimize where a transfer between to trip happens. | *Optional* | | 2.1 | -|    [backTravelWaitTimeFactor](#rd_to_backTravelWaitTimeFactor) | `double` | To reduce back-travel we favor waiting, this reduces the cost of waiting. | *Optional* | `1.0` | 2.1 | -|    [extraStopBoardAlightCostsFactor](#rd_to_extraStopBoardAlightCostsFactor) | `double` | Add an extra board- and alight-cost for prioritized stops. | *Optional* | `0.0` | 2.1 | -|    [minSafeWaitTimeFactor](#rd_to_minSafeWaitTimeFactor) | `double` | Used to set a maximum wait-time cost, base on min-safe-transfer-time. | *Optional* | `5.0` | 2.1 | -|    [optimizeTransferWaitTime](#rd_to_optimizeTransferWaitTime) | `boolean` | This enables the transfer wait time optimization. | *Optional* | `true` | 2.1 | -| [transitReluctanceForMode](#rd_transitReluctanceForMode) | `enum map of double` | Transit reluctance for a given transport mode | *Optional* | | 2.1 | -| [unpreferred](#rd_unpreferred) | `object` | Parameters listing authorities or lines that preferably should not be used in trip patters. | *Optional* | | 2.2 | -|    [agencies](#rd_unpreferred_agencies) | `feed-scoped-id[]` | The ids of the agencies that incur an extra cost when being used. Format: `FeedId:AgencyId` | *Optional* | | 2.2 | -|    [routes](#rd_unpreferred_routes) | `feed-scoped-id[]` | The ids of the routes that incur an extra cost when being used. Format: `FeedId:RouteId` | *Optional* | | 2.2 | -| vehicleRental | `object` | Vehicle rental options | *Optional* | | 2.3 | -|    allowKeepingAtDestination | `boolean` | If a vehicle should be allowed to be kept at the end of a station-based rental. | *Optional* | `false` | 2.2 | -|    dropOffCost | `integer` | Cost to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | -|    dropOffTime | `integer` | Time to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | -|    keepingAtDestinationCost | `double` | The cost of arriving at the destination with the rented vehicle, to discourage doing so. | *Optional* | `0.0` | 2.2 | -|    pickupCost | `integer` | Cost to rent a vehicle. | *Optional* | `120` | 2.0 | -|    pickupTime | `integer` | Time to rent a vehicle. | *Optional* | `60` | 2.0 | -|    useAvailabilityInformation | `boolean` | Whether or not vehicle rental availability information will be used to plan vehicle rental trips. | *Optional* | `false` | 2.0 | -|    [allowedNetworks](#rd_vehicleRental_allowedNetworks) | `string[]` | The vehicle rental networks which may be used. If empty all networks may be used. | *Optional* | | 2.1 | -|    [bannedNetworks](#rd_vehicleRental_bannedNetworks) | `string[]` | The vehicle rental networks which may not be used. If empty, no networks are banned. | *Optional* | | 2.1 | -| wheelchairAccessibility | `object` | See [Wheelchair Accessibility](Accessibility.md) | *Optional* | | 2.2 | -|    enabled | `boolean` | Enable wheelchair accessibility. | *Optional* | `false` | 2.0 | -|    inaccessibleStreetReluctance | `double` | The factor to multiply the cost of traversing a street edge that is not wheelchair-accessible. | *Optional* | `25.0` | 2.2 | -|    [maxSlope](#rd_wheelchairAccessibility_maxSlope) | `double` | The maximum slope as a fraction of 1. | *Optional* | `0.083` | 2.0 | -|    [slopeExceededReluctance](#rd_wheelchairAccessibility_slopeExceededReluctance) | `double` | How much streets with high slope should be avoided. | *Optional* | `1.0` | 2.2 | -|    [stairsReluctance](#rd_wheelchairAccessibility_stairsReluctance) | `double` | How much stairs should be avoided. | *Optional* | `100.0` | 2.2 | -|    elevator | `object` | Configuration for when to use inaccessible elevators. | *Optional* | | 2.2 | -|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | -|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `false` | 2.2 | -|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `20` | 2.2 | -|    stop | `object` | Configuration for when to use inaccessible stops. | *Optional* | | 2.2 | -|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | -|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `true` | 2.2 | -|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `600` | 2.2 | -|    trip | `object` | Configuration for when to use inaccessible trips. | *Optional* | | 2.2 | -|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | -|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `true` | 2.2 | -|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `600` | 2.2 | +| Config Parameter | Type | Summary | Req./Opt. | Default Value | Since | +|--------------------------------------------------------------------------------------------------------------|:----------------------:|------------------------------------------------------------------------------------------------------------------------------------------------|:----------:|--------------------------|:-----:| +| [alightSlack](#rd_alightSlack) | `duration` | The minimum extra time after exiting a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | +| arriveBy | `boolean` | Whether the trip should depart or arrive at the specified date and time. | *Optional* | `false` | 2.0 | +| [bikeBoardCost](#rd_bikeBoardCost) | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. | *Optional* | `600` | 2.0 | +| bikeParkCost | `integer` | Cost to park a bike. | *Optional* | `120` | 2.0 | +| bikeParkTime | `integer` | Time to park a bike. | *Optional* | `60` | 2.0 | +| bikeReluctance | `double` | A multiplier for how bad biking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | +| bikeSpeed | `double` | Max bike speed along streets, in meters per second | *Optional* | `5.0` | 2.0 | +| bikeStairsReluctance | `double` | How bad is it to walk the bicycle up/down a flight of stairs compared to taking a detour. | *Optional* | `10.0` | 2.3 | +| bikeSwitchCost | `integer` | The cost of the user fetching their bike and parking it again. | *Optional* | `0` | 2.0 | +| bikeSwitchTime | `integer` | The time it takes the user to fetch their bike and park it again in seconds. | *Optional* | `0` | 2.0 | +| bikeTriangleSafetyFactor | `double` | For bike triangle routing, how much safety matters (range 0-1). | *Optional* | `0.0` | 2.0 | +| bikeTriangleSlopeFactor | `double` | For bike triangle routing, how much slope matters (range 0-1). | *Optional* | `0.0` | 2.0 | +| bikeTriangleTimeFactor | `double` | For bike triangle routing, how much time matters (range 0-1). | *Optional* | `0.0` | 2.0 | +| bikeWalkingReluctance | `double` | A multiplier for how bad walking with a bike is, compared to being in transit for equal lengths of time. | *Optional* | `5.0` | 2.1 | +| bikeWalkingSpeed | `double` | The user's bike walking speed in meters/second. Defaults to approximately 3 MPH. | *Optional* | `1.33` | 2.1 | +| [boardSlack](#rd_boardSlack) | `duration` | The boardSlack is the minimum extra time to board a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | +| carAccelerationSpeed | `double` | The acceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | +| carDecelerationSpeed | `double` | The deceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | +| carDropoffTime | `integer` | Time to park a car in a park and ride, w/o taking into account driving and walking cost. | *Optional* | `120` | 2.0 | +| carParkCost | `integer` | Cost of parking a car. | *Optional* | `120` | 2.1 | +| carParkTime | `integer` | Time to park a car | *Optional* | `60` | 2.1 | +| carPickupCost | `integer` | Add a cost for car pickup changes when a pickup or drop off takes place | *Optional* | `120` | 2.1 | +| carPickupTime | `integer` | Add a time for car pickup changes when a pickup or drop off takes place | *Optional* | `60` | 2.1 | +| carReluctance | `double` | A multiplier for how bad driving is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | +| carSpeed | `double` | Max car speed along streets, in meters per second | *Optional* | `40.0` | 2.0 | +| [drivingDirection](#rd_drivingDirection) | `enum` | The driving direction to use in the intersection traversal calculation | *Optional* | `"right"` | 2.2 | +| elevatorBoardCost | `integer` | What is the cost of boarding a elevator? | *Optional* | `90` | 2.0 | +| elevatorBoardTime | `integer` | How long does it take to get on an elevator, on average. | *Optional* | `90` | 2.0 | +| elevatorHopCost | `integer` | What is the cost of travelling one floor on an elevator? | *Optional* | `20` | 2.0 | +| elevatorHopTime | `integer` | How long does it take to advance one floor on an elevator? | *Optional* | `20` | 2.0 | +| geoidElevation | `boolean` | If true, the Graph's ellipsoidToGeoidDifference is applied to all elevations returned by this query. | *Optional* | `false` | 2.0 | +| ignoreRealtimeUpdates | `boolean` | When true, realtime updates are ignored during this search. | *Optional* | `false` | 2.0 | +| [intersectionTraversalModel](#rd_intersectionTraversalModel) | `enum` | The model that computes the costs of turns. | *Optional* | `"simple"` | 2.2 | +| locale | `locale` | TODO | *Optional* | `"en_US"` | 2.0 | +| [maxAccessEgressDuration](#rd_maxAccessEgressDuration) | `duration` | This is the maximum duration for access/egress for street searches. | *Optional* | `"PT45M"` | 2.1 | +| [maxDirectStreetDuration](#rd_maxDirectStreetDuration) | `duration` | This is the maximum duration for a direct street search for each mode. | *Optional* | `"PT4H"` | 2.1 | +| [maxJourneyDuration](#rd_maxJourneyDuration) | `duration` | The expected maximum time a journey can last across all possible journeys for the current deployment. | *Optional* | `"PT24H"` | 2.1 | +| [modes](RoutingModes.md) | `string` | The set of access/egress/direct/transit modes to be used for the route search. | *Optional* | `"TRANSIT,WALK"` | 2.0 | +| nonpreferredTransferPenalty | `integer` | Penalty (in seconds) for using a non-preferred transfer. | *Optional* | `180` | 2.0 | +| numItineraries | `integer` | The maximum number of itineraries to return. | *Optional* | `50` | 2.0 | +| [optimize](#rd_optimize) | `enum` | The set of characteristics that the user wants to optimize for. | *Optional* | `"safe"` | 2.0 | +| [otherThanPreferredRoutesPenalty](#rd_otherThanPreferredRoutesPenalty) | `integer` | Penalty added for using every route that is not preferred if user set any route as preferred. | *Optional* | `300` | 2.0 | +| [relaxTransitSearchGeneralizedCostAtDestination](#rd_relaxTransitSearchGeneralizedCostAtDestination) | `double` | Whether non-optimal transit paths at the destination should be returned | *Optional* | | 2.3 | +| [searchWindow](#rd_searchWindow) | `duration` | The duration of the search-window. | *Optional* | | 2.0 | +| stairsReluctance | `double` | Used instead of walkReluctance for stairs. | *Optional* | `2.0` | 2.0 | +| [stairsTimeFactor](#rd_stairsTimeFactor) | `double` | How much more time does it take to walk a flight of stairs compared to walking a similar horizontal length. | *Optional* | `3.0` | 2.1 | +| [streetRoutingTimeout](#rd_streetRoutingTimeout) | `duration` | The maximum time a street routing request is allowed to take before returning the results. | *Optional* | `"PT5S"` | 2.2 | +| [transferPenalty](#rd_transferPenalty) | `integer` | An additional penalty added to boardings after the first. | *Optional* | `0` | 2.0 | +| [transferSlack](#rd_transferSlack) | `integer` | The extra time needed to make a safe transfer in seconds. | *Optional* | `120` | 2.0 | +| turnReluctance | `double` | Multiplicative factor on expected turning time. | *Optional* | `1.0` | 2.0 | +| [unpreferredCost](#rd_unpreferredCost) | `linear-function` | A cost function used to calculate penalty for an unpreferred route. | *Optional* | `"f(x) = 0 + 1.0 x"` | 2.2 | +| [unpreferredVehicleParkingTagCost](#rd_unpreferredVehicleParkingTagCost) | `integer` | What cost to add if a parking facility doesn't contain a preferred tag. | *Optional* | `300` | 2.3 | +| waitReluctance | `double` | How much worse is waiting for a transit vehicle than being on a transit vehicle, as a multiplier. | *Optional* | `1.0` | 2.0 | +| walkBoardCost | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. This is the cost that is used when boarding while walking. | *Optional* | `600` | 2.0 | +| [walkReluctance](#rd_walkReluctance) | `double` | A multiplier for how bad walking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | +| [walkSafetyFactor](#rd_walkSafetyFactor) | `double` | Factor for how much the walk safety is considered in routing. | *Optional* | `1.0` | 2.2 | +| walkSpeed | `double` | The user's walking speed in meters/second. | *Optional* | `1.33` | 2.0 | +| [accessEgressPenalty](#rd_accessEgressPenalty) | `enum map of object` | Penalty for access/egress by street mode. | *Optional* | | 2.4 | +| [alightSlackForMode](#rd_alightSlackForMode) | `enum map of duration` | How much extra time should be given when alighting a vehicle for each given mode. | *Optional* | | 2.0 | +| [bannedVehicleParkingTags](#rd_bannedVehicleParkingTags) | `string[]` | Tags with which a vehicle parking will not be used. If empty, no tags are banned. | *Optional* | | 2.1 | +| [boardSlackForMode](#rd_boardSlackForMode) | `enum map of duration` | How much extra time should be given when boarding a vehicle for each given mode. | *Optional* | | 2.0 | +| [itineraryFilters](#rd_itineraryFilters) | `object` | Configure itinerary filters that may modify itineraries, sort them, and filter away less preferable results. | *Optional* | | 2.0 | +|    [accessibilityScore](#rd_if_accessibilityScore) | `boolean` | An experimental feature contributed by IBI which adds a sandbox accessibility *score* between 0 and 1 for each leg and itinerary. | *Optional* | `false` | 2.2 | +|    [bikeRentalDistanceRatio](#rd_if_bikeRentalDistanceRatio) | `double` | Filter routes that consist of bike-rental and walking by the minimum fraction of the bike-rental leg using _distance_. | *Optional* | `0.0` | 2.1 | +|    [debug](#rd_if_debug) | `enum` | Enable this to attach a system notice to itineraries instead of removing them. This is very convenient when tuning the itinerary-filter-chain. | *Optional* | `"off"` | 2.0 | +|    [filterItinerariesWithSameFirstOrLastTrip](#rd_if_filterItinerariesWithSameFirstOrLastTrip) | `boolean` | If more than one itinerary begins or ends with same trip, filter out one of those itineraries so that only one remains. | *Optional* | `false` | 2.2 | +|    groupSimilarityKeepOne | `double` | Pick ONE itinerary from each group after putting itineraries that are 85% similar together. | *Optional* | `0.85` | 2.1 | +|    groupSimilarityKeepThree | `double` | Reduce the number of itineraries to three itineraries by reducing each group of itineraries grouped by 68% similarity. | *Optional* | `0.68` | 2.1 | +|    [groupedOtherThanSameLegsMaxCostMultiplier](#rd_if_groupedOtherThanSameLegsMaxCostMultiplier) | `double` | Filter grouped itineraries, where the non-grouped legs are more expensive than in the lowest cost one. | *Optional* | `2.0` | 2.1 | +|    [minBikeParkingDistance](#rd_if_minBikeParkingDistance) | `double` | Filter out bike park+ride results that have fewer meters of cycling than this value. | *Optional* | `0.0` | 2.3 | +|    [nonTransitGeneralizedCostLimit](#rd_if_nonTransitGeneralizedCostLimit) | `linear-function` | The function define a max-limit for generalized-cost for non-transit itineraries. | *Optional* | `"f(x) = 3,600 + 2.0 x"` | 2.1 | +|    [parkAndRideDurationRatio](#rd_if_parkAndRideDurationRatio) | `double` | Filter P+R routes that consist of driving and walking by the minimum fraction of the driving using of _time_. | *Optional* | `0.0` | 2.1 | +|    [removeItinerariesWithSameRoutesAndStops](#rd_if_removeItinerariesWithSameRoutesAndStops) | `boolean` | Set to true if you want to list only the first itinerary which goes through the same stops and routes. | *Optional* | `false` | 2.2 | +|    [removeTransitWithHigherCostThanBestOnStreetOnly](#rd_if_removeTransitWithHigherCostThanBestOnStreetOnly) | `linear-function` | Limit function for generalized-cost computed from non-transit itineries for transit itineraries. | *Optional* | `"f(x) = 60 + 1.3 x"` | 2.4 | +|    [transitGeneralizedCostLimit](#rd_if_transitGeneralizedCostLimit) | `object` | A relative limit for the generalized-cost for transit itineraries. | *Optional* | | 2.1 | +|       [costLimitFunction](#rd_if_transitGeneralizedCostLimit_costLimitFunction) | `linear-function` | The base function used by the filter. | *Optional* | `"f(x) = 900 + 1.5 x"` | 2.2 | +|       [intervalRelaxFactor](#rd_if_transitGeneralizedCostLimit_intervalRelaxFactor) | `double` | How much the filter should be relaxed for itineraries that do not overlap in time. | *Optional* | `0.4` | 2.2 | +| [maxAccessEgressDurationForMode](#rd_maxAccessEgressDurationForMode) | `enum map of duration` | Limit access/egress per street mode. | *Optional* | | 2.1 | +| [maxDirectStreetDurationForMode](#rd_maxDirectStreetDurationForMode) | `enum map of duration` | Limit direct route duration per street mode. | *Optional* | | 2.2 | +| [preferredVehicleParkingTags](#rd_preferredVehicleParkingTags) | `string[]` | Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised. | *Optional* | | 2.3 | +| [requiredVehicleParkingTags](#rd_requiredVehicleParkingTags) | `string[]` | Tags without which a vehicle parking will not be used. If empty, no tags are required. | *Optional* | | 2.1 | +| [transferOptimization](#rd_transferOptimization) | `object` | Optimize where a transfer between to trip happens. | *Optional* | | 2.1 | +|    [backTravelWaitTimeFactor](#rd_to_backTravelWaitTimeFactor) | `double` | To reduce back-travel we favor waiting, this reduces the cost of waiting. | *Optional* | `1.0` | 2.1 | +|    [extraStopBoardAlightCostsFactor](#rd_to_extraStopBoardAlightCostsFactor) | `double` | Add an extra board- and alight-cost for prioritized stops. | *Optional* | `0.0` | 2.1 | +|    [minSafeWaitTimeFactor](#rd_to_minSafeWaitTimeFactor) | `double` | Used to set a maximum wait-time cost, base on min-safe-transfer-time. | *Optional* | `5.0` | 2.1 | +|    [optimizeTransferWaitTime](#rd_to_optimizeTransferWaitTime) | `boolean` | This enables the transfer wait time optimization. | *Optional* | `true` | 2.1 | +| [transitReluctanceForMode](#rd_transitReluctanceForMode) | `enum map of double` | Transit reluctance for a given transport mode | *Optional* | | 2.1 | +| [unpreferred](#rd_unpreferred) | `object` | Parameters listing authorities or lines that preferably should not be used in trip patters. | *Optional* | | 2.2 | +|    [agencies](#rd_unpreferred_agencies) | `feed-scoped-id[]` | The ids of the agencies that incur an extra cost when being used. Format: `FeedId:AgencyId` | *Optional* | | 2.2 | +|    [routes](#rd_unpreferred_routes) | `feed-scoped-id[]` | The ids of the routes that incur an extra cost when being used. Format: `FeedId:RouteId` | *Optional* | | 2.2 | +| vehicleRental | `object` | Vehicle rental options | *Optional* | | 2.3 | +|    allowKeepingAtDestination | `boolean` | If a vehicle should be allowed to be kept at the end of a station-based rental. | *Optional* | `false` | 2.2 | +|    dropOffCost | `integer` | Cost to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | +|    dropOffTime | `integer` | Time to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | +|    keepingAtDestinationCost | `double` | The cost of arriving at the destination with the rented vehicle, to discourage doing so. | *Optional* | `0.0` | 2.2 | +|    pickupCost | `integer` | Cost to rent a vehicle. | *Optional* | `120` | 2.0 | +|    pickupTime | `integer` | Time to rent a vehicle. | *Optional* | `60` | 2.0 | +|    useAvailabilityInformation | `boolean` | Whether or not vehicle rental availability information will be used to plan vehicle rental trips. | *Optional* | `false` | 2.0 | +|    [allowedNetworks](#rd_vehicleRental_allowedNetworks) | `string[]` | The vehicle rental networks which may be used. If empty all networks may be used. | *Optional* | | 2.1 | +|    [bannedNetworks](#rd_vehicleRental_bannedNetworks) | `string[]` | The vehicle rental networks which may not be used. If empty, no networks are banned. | *Optional* | | 2.1 | +| wheelchairAccessibility | `object` | See [Wheelchair Accessibility](Accessibility.md) | *Optional* | | 2.2 | +|    enabled | `boolean` | Enable wheelchair accessibility. | *Optional* | `false` | 2.0 | +|    inaccessibleStreetReluctance | `double` | The factor to multiply the cost of traversing a street edge that is not wheelchair-accessible. | *Optional* | `25.0` | 2.2 | +|    [maxSlope](#rd_wheelchairAccessibility_maxSlope) | `double` | The maximum slope as a fraction of 1. | *Optional* | `0.083` | 2.0 | +|    [slopeExceededReluctance](#rd_wheelchairAccessibility_slopeExceededReluctance) | `double` | How much streets with high slope should be avoided. | *Optional* | `1.0` | 2.2 | +|    [stairsReluctance](#rd_wheelchairAccessibility_stairsReluctance) | `double` | How much stairs should be avoided. | *Optional* | `100.0` | 2.2 | +|    elevator | `object` | Configuration for when to use inaccessible elevators. | *Optional* | | 2.2 | +|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | +|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `false` | 2.2 | +|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `20` | 2.2 | +|    stop | `object` | Configuration for when to use inaccessible stops. | *Optional* | | 2.2 | +|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | +|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `true` | 2.2 | +|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `600` | 2.2 | +|    trip | `object` | Configuration for when to use inaccessible trips. | *Optional* | | 2.2 | +|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | +|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `true` | 2.2 | +|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `600` | 2.2 | @@ -611,6 +612,21 @@ Set to true if you want to list only the first itinerary which goes through the Itineraries visiting the same set of stops and riding the exact same routes, departing later are removed from the result. +

removeTransitWithHigherCostThanBestOnStreetOnly

+ +**Since version:** `2.4` ∙ **Type:** `linear-function` ∙ **Cardinality:** `Optional` ∙ **Default value:** `"f(x) = 60 + 1.3 x"` +**Path:** /routingDefaults/itineraryFilters + +Limit function for generalized-cost computed from non-transit itineries for transit itineraries. + +The max-limit is applied to itineraries with transit *legs*, and only itineraries +without transit legs are considered when calculating the minimum cost. The smallest +generalized-cost value is used as input to the function. The function is used to calculate a +*max-limit*. The max-limit is then used to filter *transit* itineraries by +*generalized-cost*. Itineraries with a cost higher than the max-limit are dropped from the result +set. + +

transitGeneralizedCostLimit

**Since version:** `2.1` ∙ **Type:** `object` ∙ **Cardinality:** `Optional` diff --git a/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java b/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java index e9c2b63f9fe..b98077dc1db 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java @@ -60,7 +60,7 @@ public static ItineraryListFilterChain createFilterChain( .withBikeRentalDistanceRatio(params.bikeRentalDistanceRatio()) .withParkAndRideDurationRatio(params.parkAndRideDurationRatio()) .withNonTransitGeneralizedCostLimit(params.nonTransitGeneralizedCostLimit()) - .withRemoveTransitWithHigherCostThanBestOnStreetOnlyh( + .withRemoveTransitWithHigherCostThanBestOnStreetOnly( params.removeTransitWithHigherCostThanBestOnStreetOnly() ) .withSameFirstOrLastTripFilter(params.filterItinerariesWithSameFirstOrLastTrip()) diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java index 5f65196e581..3c898e20301 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java @@ -30,6 +30,7 @@ public final class ItineraryFilterPreferences { private final double parkAndRideDurationRatio; private final boolean removeItinerariesWithSameRoutesAndStops; private final TransitGeneralizedCostFilterParams transitGeneralizedCostLimit; + private final DoubleAlgorithmFunction removeTransitWithHigherCostThanBestOnStreetOnly; private ItineraryFilterPreferences() { this.accessibilityScore = false; @@ -46,7 +47,7 @@ private ItineraryFilterPreferences() { this.transitGeneralizedCostLimit = new TransitGeneralizedCostFilterParams(RequestFunctions.createLinearFunction(900, 1.5), 0.4); this.removeTransitWithHigherCostThanBestOnStreetOnly = - RequestFunctions.createLinearFunction(200, 1.5); + RequestFunctions.createLinearFunction(60, 1.3); } private ItineraryFilterPreferences(Builder builder) { @@ -167,15 +168,15 @@ public String toString() { transitGeneralizedCostLimit, DEFAULT.transitGeneralizedCostLimit ) + .addObj( + "removeTransitWithHigherCostThanBestOnStreetOnly", + removeTransitWithHigherCostThanBestOnStreetOnly, + DEFAULT.removeTransitWithHigherCostThanBestOnStreetOnly + ) .addBoolIfTrue( "removeItinerariesWithSameRoutesAndStops", removeItinerariesWithSameRoutesAndStops ) - .addObj( - "removeTransitWithHigherCostThanBestOnStreetOnly", - nonTransitGeneralizedCostLimit, - DEFAULT.nonTransitGeneralizedCostLimit - ) .toString(); } diff --git a/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java index bf97fe4254a..2a441d68287 100644 --- a/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java +++ b/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java @@ -5,6 +5,7 @@ import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_1; import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_2; import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_3; +import static org.opentripplanner.standalone.config.framework.json.OtpVersion.V2_4; import org.opentripplanner.routing.algorithm.filterchain.api.TransitGeneralizedCostFilterParams; import org.opentripplanner.routing.api.request.framework.RequestFunctions; @@ -157,7 +158,7 @@ public static void mapItineraryFilterParams( .withRemoveTransitWithHigherCostThanBestOnStreetOnly( c .of("removeTransitWithHigherCostThanBestOnStreetOnly") - .since(V2_1) + .since(V2_4) .summary( "Limit function for generalized-cost computed from non-transit itineries for transit itineraries." ) diff --git a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java index c7fe995ba26..5ebbdc44222 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java @@ -21,6 +21,7 @@ import org.opentripplanner.model.plan.PlanTestConstants; import org.opentripplanner.model.plan.TestItineraryBuilder; import org.opentripplanner.routing.alertpatch.StopCondition; +import org.opentripplanner.routing.api.request.framework.RequestFunctions; import org.opentripplanner.routing.api.response.RoutingError; import org.opentripplanner.routing.api.response.RoutingErrorCode; import org.opentripplanner.routing.services.TransitAlertService; @@ -162,7 +163,9 @@ public void testSameFirstOrLastTripFilter() { void testRoutingErrorsOriginDestinationTooCloseTest() { ItineraryListFilterChain chain = createBuilder(false, false, 20) .withRemoveWalkAllTheWayResults(true) - .withRemoveTransitWithHigherCostThanBestOnStreetOnly(true) + .withRemoveTransitWithHigherCostThanBestOnStreetOnly( + RequestFunctions.createLinearFunction(0, 1.0) + ) .build(); Itinerary walk = newItinerary(A, T11_06).walk(D10m, E).build(); @@ -243,7 +246,9 @@ private ItineraryListFilterChainBuilder createBuilder( var sortOrder = arriveBy ? STREET_AND_DEPARTURE_TIME : STREET_AND_ARRIVAL_TIME; return new ItineraryListFilterChainBuilder(sortOrder) .withMaxNumberOfItineraries(numOfItineraries) - .withRemoveTransitWithHigherCostThanBestOnStreetOnly(true) + .withRemoveTransitWithHigherCostThanBestOnStreetOnly( + RequestFunctions.createLinearFunction(0, 1.0) + ) .withDebugEnabled(ofDebugEnabled(debug)); } @@ -297,9 +302,9 @@ public void setUpItineraries() { @Test public void removeTransitWithHigherCostThanBestOnStreetOnlyDisabled() { - // Disable filter and allow none optimal bus itinerary pass through + // Allow non-optimal bus itinerary pass through ItineraryListFilterChain chain = builder - .withRemoveTransitWithHigherCostThanBestOnStreetOnly(false) + .withRemoveTransitWithHigherCostThanBestOnStreetOnly(null) .build(); assertEquals(toStr(List.of(walk, bus)), toStr(chain.filter(List.of(walk, bus)))); } @@ -308,7 +313,9 @@ public void removeTransitWithHigherCostThanBestOnStreetOnlyDisabled() { public void removeTransitWithHigherCostThanBestOnStreetOnlyEnabled() { // Enable filter and remove bus itinerary ItineraryListFilterChain chain = builder - .withRemoveTransitWithHigherCostThanBestOnStreetOnly(true) + .withRemoveTransitWithHigherCostThanBestOnStreetOnly( + RequestFunctions.createLinearFunction(0, 1.0) + ) .build(); assertEquals(toStr(List.of(walk)), toStr(chain.filter(List.of(walk, bus)))); } diff --git a/src/test/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferencesTest.java b/src/test/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferencesTest.java index 80c3ab99ef0..781ebfe1677 100644 --- a/src/test/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferencesTest.java +++ b/src/test/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferencesTest.java @@ -28,6 +28,10 @@ class ItineraryFilterPreferencesTest { RequestFunctions.createLinearFunction(3.5, 5.0), 3.0 ); + private static final DoubleAlgorithmFunction TRANSIT_BEST_STREET_COST_LIMIT = RequestFunctions.createLinearFunction( + 60, + 1.3 + ); private final ItineraryFilterPreferences subject = ItineraryFilterPreferences .of() @@ -42,6 +46,7 @@ class ItineraryFilterPreferencesTest { .withNonTransitGeneralizedCostLimit(NON_TRANSIT_GENERALIZED_COST_LIMIT) .withParkAndRideDurationRatio(PARK_AND_RIDE_DURATION_RATIO) .withTransitGeneralizedCostLimit(TRANSIT_GENERALIZED_COST_LIMIT) + .withRemoveTransitWithHigherCostThanBestOnStreetOnly(TRANSIT_BEST_STREET_COST_LIMIT) .build(); @Test @@ -133,7 +138,8 @@ void testToString() { "minBikeParkingDistance: 2,000.0, " + "nonTransitGeneralizedCostLimit: f(x) = 4 + 5.0 x, " + "parkAndRideDurationRatio: 0.44, " + - "transitGeneralizedCostLimit: TransitGeneralizedCostFilterParams[costLimitFunction=f(x) = 4 + 5.0 x, intervalRelaxFactor=3.0]" + + "transitGeneralizedCostLimit: TransitGeneralizedCostFilterParams[costLimitFunction=f(x) = 4 + 5.0 x, intervalRelaxFactor=3.0], " + + "removeTransitWithHigherCostThanBestOnStreetOnly: f(x) = 60 + 1.3 x" + "}", subject.toString() ); From 709a94ae3c1e4cd376b24ec24e30fe2157742a35 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 6 Jul 2023 14:34:34 +0300 Subject: [PATCH 04/36] Add two missing itinerary filter configuration examples --- src/test/resources/standalone/config/router-config.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/resources/standalone/config/router-config.json b/src/test/resources/standalone/config/router-config.json index b3bfb71d11f..9b5ebb63ebb 100644 --- a/src/test/resources/standalone/config/router-config.json +++ b/src/test/resources/standalone/config/router-config.json @@ -59,6 +59,8 @@ "costLimitFunction": "900 + 1.5 x", "intervalRelaxFactor": 0.4 }, + "nonTransitGeneralizedCostLimit": "400 + 1.5x", + "removeTransitWithHigherCostThanBestOnStreetOnly": "60 + 1.3x", "bikeRentalDistanceRatio": 0.3, "accessibilityScore": true, "minBikeParkingDistance": 300 From 3463eb6238061f01228093ceefb38e514844c62a Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 6 Jul 2023 14:47:47 +0300 Subject: [PATCH 05/36] Update docs --- docs/RouteRequest.md | 5 ++++- docs/RouterConfiguration.md | 2 ++ .../config/routerequest/ItineraryFiltersConfig.java | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/RouteRequest.md b/docs/RouteRequest.md index 01a185ce24e..dbeab075ea2 100644 --- a/docs/RouteRequest.md +++ b/docs/RouteRequest.md @@ -624,7 +624,8 @@ without transit legs are considered when calculating the minimum cost. The small generalized-cost value is used as input to the function. The function is used to calculate a *max-limit*. The max-limit is then used to filter *transit* itineraries by *generalized-cost*. Itineraries with a cost higher than the max-limit are dropped from the result -set. + set. Walking is handled with a different logic: if a transit itinerary has more walking than + a plain walk itinerary, it will be removed even if the cost limit function would keep it.

transitGeneralizedCostLimit

@@ -930,6 +931,8 @@ include stairs as a last result. "costLimitFunction" : "900 + 1.5 x", "intervalRelaxFactor" : 0.4 }, + "nonTransitGeneralizedCostLimit" : "400 + 1.5x", + "removeTransitWithHigherCostThanBestOnStreetOnly" : "60 + 1.3x", "bikeRentalDistanceRatio" : 0.3, "accessibilityScore" : true, "minBikeParkingDistance" : 300 diff --git a/docs/RouterConfiguration.md b/docs/RouterConfiguration.md index 485ceaff448..7d6d0163820 100644 --- a/docs/RouterConfiguration.md +++ b/docs/RouterConfiguration.md @@ -493,6 +493,8 @@ HTTP headers to add to the request. Any header key, value can be inserted. "costLimitFunction" : "900 + 1.5 x", "intervalRelaxFactor" : 0.4 }, + "nonTransitGeneralizedCostLimit" : "400 + 1.5x", + "removeTransitWithHigherCostThanBestOnStreetOnly" : "60 + 1.3x", "bikeRentalDistanceRatio" : 0.3, "accessibilityScore" : true, "minBikeParkingDistance" : 300 diff --git a/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java index 2a441d68287..81093e4bdf8 100644 --- a/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java +++ b/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java @@ -169,7 +169,8 @@ public static void mapItineraryFilterParams( generalized-cost value is used as input to the function. The function is used to calculate a *max-limit*. The max-limit is then used to filter *transit* itineraries by *generalized-cost*. Itineraries with a cost higher than the max-limit are dropped from the result -set. + set. Walking is handled with a different logic: if a transit itinerary has more walking than + a plain walk itinerary, it will be removed even if the cost limit function would keep it. """ ) .asLinearFunction(dft.removeTransitWithHigherCostThanBestOnStreetOnly()) From e9811216bc550ae742bb04f653103c759de5a493 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Tue, 18 Jul 2023 11:41:43 +0300 Subject: [PATCH 06/36] Update auto generated docs --- docs/RouteRequest.md | 127 +----------------------------------- docs/RouterConfiguration.md | 2 + 2 files changed, 4 insertions(+), 125 deletions(-) diff --git a/docs/RouteRequest.md b/docs/RouteRequest.md index 8594ff60563..bf17b5b939c 100644 --- a/docs/RouteRequest.md +++ b/docs/RouteRequest.md @@ -13,7 +13,6 @@ and in the [transferRequests in build-config.json](BuildConfiguration.md#transfe -<<<<<<< HEAD | Config Parameter | Type | Summary | Req./Opt. | Default Value | Since | |--------------------------------------------------------------------------------------------------------------|:----------------------:|------------------------------------------------------------------------------------------------------------------------------------------------|:----------:|--------------------------|:-----:| | [alightSlack](#rd_alightSlack) | `duration` | The minimum extra time after exiting a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | @@ -46,7 +45,7 @@ and in the [transferRequests in build-config.json](BuildConfiguration.md#transfe | elevatorBoardTime | `integer` | How long does it take to get on an elevator, on average. | *Optional* | `90` | 2.0 | | elevatorHopCost | `integer` | What is the cost of travelling one floor on an elevator? | *Optional* | `20` | 2.0 | | elevatorHopTime | `integer` | How long does it take to advance one floor on an elevator? | *Optional* | `20` | 2.0 | -| escalatorReluctance | `double` | A multiplier for how bad being in an escalator is compared to being in transit for equal lengths of time | *Optional* | `1.5` | na | +| escalatorReluctance | `double` | A multiplier for how bad being in an escalator is compared to being in transit for equal lengths of time | *Optional* | `1.5` | 2.4 | | geoidElevation | `boolean` | If true, the Graph's ellipsoidToGeoidDifference is applied to all elevations returned by this query. | *Optional* | `false` | 2.0 | | ignoreRealtimeUpdates | `boolean` | When true, realtime updates are ignored during this search. | *Optional* | `false` | 2.0 | | [intersectionTraversalModel](#rd_intersectionTraversalModel) | `enum` | The model that computes the costs of turns. | *Optional* | `"simple"` | 2.2 | @@ -54,7 +53,7 @@ and in the [transferRequests in build-config.json](BuildConfiguration.md#transfe | [maxAccessEgressDuration](#rd_maxAccessEgressDuration) | `duration` | This is the maximum duration for access/egress for street searches. | *Optional* | `"PT45M"` | 2.1 | | [maxDirectStreetDuration](#rd_maxDirectStreetDuration) | `duration` | This is the maximum duration for a direct street search for each mode. | *Optional* | `"PT4H"` | 2.1 | | [maxJourneyDuration](#rd_maxJourneyDuration) | `duration` | The expected maximum time a journey can last across all possible journeys for the current deployment. | *Optional* | `"PT24H"` | 2.1 | -| [modes](RoutingModes.md) | `string` | The set of access/egress/direct/transit modes to be used for the route search. | *Optional* | `"TRANSIT,WALK"` | 2.0 | +| modes | `string` | The set of access/egress/direct/transit modes to be used for the route search. | *Optional* | `"TRANSIT,WALK"` | 2.0 | | nonpreferredTransferPenalty | `integer` | Penalty (in seconds) for using a non-preferred transfer. | *Optional* | `180` | 2.0 | | numItineraries | `integer` | The maximum number of itineraries to return. | *Optional* | `50` | 2.0 | | [optimize](#rd_optimize) | `enum` | The set of characteristics that the user wants to optimize for. | *Optional* | `"safe"` | 2.0 | @@ -135,128 +134,6 @@ and in the [transferRequests in build-config.json](BuildConfiguration.md#transfe |       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | |       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `true` | 2.2 | |       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `600` | 2.2 | -======= -| Config Parameter | Type | Summary | Req./Opt. | Default Value | Since | -|------------------------------------------------------------------------------------------------------|:----------------------:|------------------------------------------------------------------------------------------------------------------------------------------------|:----------:|--------------------------|:-----:| -| [alightSlack](#rd_alightSlack) | `duration` | The minimum extra time after exiting a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | -| arriveBy | `boolean` | Whether the trip should depart or arrive at the specified date and time. | *Optional* | `false` | 2.0 | -| [bikeBoardCost](#rd_bikeBoardCost) | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. | *Optional* | `600` | 2.0 | -| bikeParkCost | `integer` | Cost to park a bike. | *Optional* | `120` | 2.0 | -| bikeParkTime | `integer` | Time to park a bike. | *Optional* | `60` | 2.0 | -| bikeReluctance | `double` | A multiplier for how bad biking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| bikeSpeed | `double` | Max bike speed along streets, in meters per second | *Optional* | `5.0` | 2.0 | -| bikeStairsReluctance | `double` | How bad is it to walk the bicycle up/down a flight of stairs compared to taking a detour. | *Optional* | `10.0` | 2.3 | -| bikeSwitchCost | `integer` | The cost of the user fetching their bike and parking it again. | *Optional* | `0` | 2.0 | -| bikeSwitchTime | `integer` | The time it takes the user to fetch their bike and park it again in seconds. | *Optional* | `0` | 2.0 | -| bikeTriangleSafetyFactor | `double` | For bike triangle routing, how much safety matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeTriangleSlopeFactor | `double` | For bike triangle routing, how much slope matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeTriangleTimeFactor | `double` | For bike triangle routing, how much time matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeWalkingReluctance | `double` | A multiplier for how bad walking with a bike is, compared to being in transit for equal lengths of time. | *Optional* | `5.0` | 2.1 | -| bikeWalkingSpeed | `double` | The user's bike walking speed in meters/second. Defaults to approximately 3 MPH. | *Optional* | `1.33` | 2.1 | -| [boardSlack](#rd_boardSlack) | `duration` | The boardSlack is the minimum extra time to board a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | -| carAccelerationSpeed | `double` | The acceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | -| carDecelerationSpeed | `double` | The deceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | -| carDropoffTime | `integer` | Time to park a car in a park and ride, w/o taking into account driving and walking cost. | *Optional* | `120` | 2.0 | -| carParkCost | `integer` | Cost of parking a car. | *Optional* | `120` | 2.1 | -| carParkTime | `integer` | Time to park a car | *Optional* | `60` | 2.1 | -| carPickupCost | `integer` | Add a cost for car pickup changes when a pickup or drop off takes place | *Optional* | `120` | 2.1 | -| carPickupTime | `integer` | Add a time for car pickup changes when a pickup or drop off takes place | *Optional* | `60` | 2.1 | -| carReluctance | `double` | A multiplier for how bad driving is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| carSpeed | `double` | Max car speed along streets, in meters per second | *Optional* | `40.0` | 2.0 | -| [drivingDirection](#rd_drivingDirection) | `enum` | The driving direction to use in the intersection traversal calculation | *Optional* | `"right"` | 2.2 | -| elevatorBoardCost | `integer` | What is the cost of boarding a elevator? | *Optional* | `90` | 2.0 | -| elevatorBoardTime | `integer` | How long does it take to get on an elevator, on average. | *Optional* | `90` | 2.0 | -| elevatorHopCost | `integer` | What is the cost of travelling one floor on an elevator? | *Optional* | `20` | 2.0 | -| elevatorHopTime | `integer` | How long does it take to advance one floor on an elevator? | *Optional* | `20` | 2.0 | -| escalatorReluctance | `double` | A multiplier for how bad being in an escalator is compared to being in transit for equal lengths of time | *Optional* | `1.5` | 2.4 | -| geoidElevation | `boolean` | If true, the Graph's ellipsoidToGeoidDifference is applied to all elevations returned by this query. | *Optional* | `false` | 2.0 | -| ignoreRealtimeUpdates | `boolean` | When true, realtime updates are ignored during this search. | *Optional* | `false` | 2.0 | -| [intersectionTraversalModel](#rd_intersectionTraversalModel) | `enum` | The model that computes the costs of turns. | *Optional* | `"simple"` | 2.2 | -| locale | `locale` | TODO | *Optional* | `"en_US"` | 2.0 | -| [maxAccessEgressDuration](#rd_maxAccessEgressDuration) | `duration` | This is the maximum duration for access/egress for street searches. | *Optional* | `"PT45M"` | 2.1 | -| [maxDirectStreetDuration](#rd_maxDirectStreetDuration) | `duration` | This is the maximum duration for a direct street search for each mode. | *Optional* | `"PT4H"` | 2.1 | -| [maxJourneyDuration](#rd_maxJourneyDuration) | `duration` | The expected maximum time a journey can last across all possible journeys for the current deployment. | *Optional* | `"PT24H"` | 2.1 | -| modes | `string` | The set of access/egress/direct/transit modes to be used for the route search. | *Optional* | `"TRANSIT,WALK"` | 2.0 | -| nonpreferredTransferPenalty | `integer` | Penalty (in seconds) for using a non-preferred transfer. | *Optional* | `180` | 2.0 | -| numItineraries | `integer` | The maximum number of itineraries to return. | *Optional* | `50` | 2.0 | -| [optimize](#rd_optimize) | `enum` | The set of characteristics that the user wants to optimize for. | *Optional* | `"safe"` | 2.0 | -| [otherThanPreferredRoutesPenalty](#rd_otherThanPreferredRoutesPenalty) | `integer` | Penalty added for using every route that is not preferred if user set any route as preferred. | *Optional* | `300` | 2.0 | -| [relaxTransitSearchGeneralizedCostAtDestination](#rd_relaxTransitSearchGeneralizedCostAtDestination) | `double` | Whether non-optimal transit paths at the destination should be returned | *Optional* | | 2.3 | -| [searchWindow](#rd_searchWindow) | `duration` | The duration of the search-window. | *Optional* | | 2.0 | -| stairsReluctance | `double` | Used instead of walkReluctance for stairs. | *Optional* | `2.0` | 2.0 | -| [stairsTimeFactor](#rd_stairsTimeFactor) | `double` | How much more time does it take to walk a flight of stairs compared to walking a similar horizontal length. | *Optional* | `3.0` | 2.1 | -| [streetRoutingTimeout](#rd_streetRoutingTimeout) | `duration` | The maximum time a street routing request is allowed to take before returning the results. | *Optional* | `"PT5S"` | 2.2 | -| [transferPenalty](#rd_transferPenalty) | `integer` | An additional penalty added to boardings after the first. | *Optional* | `0` | 2.0 | -| [transferSlack](#rd_transferSlack) | `integer` | The extra time needed to make a safe transfer in seconds. | *Optional* | `120` | 2.0 | -| turnReluctance | `double` | Multiplicative factor on expected turning time. | *Optional* | `1.0` | 2.0 | -| [unpreferredCost](#rd_unpreferredCost) | `linear-function` | A cost function used to calculate penalty for an unpreferred route. | *Optional* | `"f(x) = 0 + 1.0 x"` | 2.2 | -| [unpreferredVehicleParkingTagCost](#rd_unpreferredVehicleParkingTagCost) | `integer` | What cost to add if a parking facility doesn't contain a preferred tag. | *Optional* | `300` | 2.3 | -| waitReluctance | `double` | How much worse is waiting for a transit vehicle than being on a transit vehicle, as a multiplier. | *Optional* | `1.0` | 2.0 | -| walkBoardCost | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. This is the cost that is used when boarding while walking. | *Optional* | `600` | 2.0 | -| [walkReluctance](#rd_walkReluctance) | `double` | A multiplier for how bad walking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| [walkSafetyFactor](#rd_walkSafetyFactor) | `double` | Factor for how much the walk safety is considered in routing. | *Optional* | `1.0` | 2.2 | -| walkSpeed | `double` | The user's walking speed in meters/second. | *Optional* | `1.33` | 2.0 | -| [accessEgressPenalty](#rd_accessEgressPenalty) | `enum map of object` | Penalty for access/egress by street mode. | *Optional* | | 2.4 | -| [alightSlackForMode](#rd_alightSlackForMode) | `enum map of duration` | How much extra time should be given when alighting a vehicle for each given mode. | *Optional* | | 2.0 | -| [bannedVehicleParkingTags](#rd_bannedVehicleParkingTags) | `string[]` | Tags with which a vehicle parking will not be used. If empty, no tags are banned. | *Optional* | | 2.1 | -| [boardSlackForMode](#rd_boardSlackForMode) | `enum map of duration` | How much extra time should be given when boarding a vehicle for each given mode. | *Optional* | | 2.0 | -| [itineraryFilters](#rd_itineraryFilters) | `object` | Configure itinerary filters that may modify itineraries, sort them, and filter away less preferable results. | *Optional* | | 2.0 | -|    [accessibilityScore](#rd_if_accessibilityScore) | `boolean` | An experimental feature contributed by IBI which adds a sandbox accessibility *score* between 0 and 1 for each leg and itinerary. | *Optional* | `false` | 2.2 | -|    [bikeRentalDistanceRatio](#rd_if_bikeRentalDistanceRatio) | `double` | Filter routes that consist of bike-rental and walking by the minimum fraction of the bike-rental leg using _distance_. | *Optional* | `0.0` | 2.1 | -|    [debug](#rd_if_debug) | `enum` | Enable this to attach a system notice to itineraries instead of removing them. This is very convenient when tuning the itinerary-filter-chain. | *Optional* | `"off"` | 2.0 | -|    [filterItinerariesWithSameFirstOrLastTrip](#rd_if_filterItinerariesWithSameFirstOrLastTrip) | `boolean` | If more than one itinerary begins or ends with same trip, filter out one of those itineraries so that only one remains. | *Optional* | `false` | 2.2 | -|    groupSimilarityKeepOne | `double` | Pick ONE itinerary from each group after putting itineraries that are 85% similar together. | *Optional* | `0.85` | 2.1 | -|    groupSimilarityKeepThree | `double` | Reduce the number of itineraries to three itineraries by reducing each group of itineraries grouped by 68% similarity. | *Optional* | `0.68` | 2.1 | -|    [groupedOtherThanSameLegsMaxCostMultiplier](#rd_if_groupedOtherThanSameLegsMaxCostMultiplier) | `double` | Filter grouped itineraries, where the non-grouped legs are more expensive than in the lowest cost one. | *Optional* | `2.0` | 2.1 | -|    [minBikeParkingDistance](#rd_if_minBikeParkingDistance) | `double` | Filter out bike park+ride results that have fewer meters of cycling than this value. | *Optional* | `0.0` | 2.3 | -|    [nonTransitGeneralizedCostLimit](#rd_if_nonTransitGeneralizedCostLimit) | `linear-function` | The function define a max-limit for generalized-cost for non-transit itineraries. | *Optional* | `"f(x) = 3,600 + 2.0 x"` | 2.1 | -|    [parkAndRideDurationRatio](#rd_if_parkAndRideDurationRatio) | `double` | Filter P+R routes that consist of driving and walking by the minimum fraction of the driving using of _time_. | *Optional* | `0.0` | 2.1 | -|    [removeItinerariesWithSameRoutesAndStops](#rd_if_removeItinerariesWithSameRoutesAndStops) | `boolean` | Set to true if you want to list only the first itinerary which goes through the same stops and routes. | *Optional* | `false` | 2.2 | -|    [transitGeneralizedCostLimit](#rd_if_transitGeneralizedCostLimit) | `object` | A relative limit for the generalized-cost for transit itineraries. | *Optional* | | 2.1 | -|       [costLimitFunction](#rd_if_transitGeneralizedCostLimit_costLimitFunction) | `linear-function` | The base function used by the filter. | *Optional* | `"f(x) = 900 + 1.5 x"` | 2.2 | -|       [intervalRelaxFactor](#rd_if_transitGeneralizedCostLimit_intervalRelaxFactor) | `double` | How much the filter should be relaxed for itineraries that do not overlap in time. | *Optional* | `0.4` | 2.2 | -| [maxAccessEgressDurationForMode](#rd_maxAccessEgressDurationForMode) | `enum map of duration` | Limit access/egress per street mode. | *Optional* | | 2.1 | -| [maxDirectStreetDurationForMode](#rd_maxDirectStreetDurationForMode) | `enum map of duration` | Limit direct route duration per street mode. | *Optional* | | 2.2 | -| [preferredVehicleParkingTags](#rd_preferredVehicleParkingTags) | `string[]` | Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised. | *Optional* | | 2.3 | -| [requiredVehicleParkingTags](#rd_requiredVehicleParkingTags) | `string[]` | Tags without which a vehicle parking will not be used. If empty, no tags are required. | *Optional* | | 2.1 | -| [transferOptimization](#rd_transferOptimization) | `object` | Optimize where a transfer between to trip happens. | *Optional* | | 2.1 | -|    [backTravelWaitTimeFactor](#rd_to_backTravelWaitTimeFactor) | `double` | To reduce back-travel we favor waiting, this reduces the cost of waiting. | *Optional* | `1.0` | 2.1 | -|    [extraStopBoardAlightCostsFactor](#rd_to_extraStopBoardAlightCostsFactor) | `double` | Add an extra board- and alight-cost for prioritized stops. | *Optional* | `0.0` | 2.1 | -|    [minSafeWaitTimeFactor](#rd_to_minSafeWaitTimeFactor) | `double` | Used to set a maximum wait-time cost, base on min-safe-transfer-time. | *Optional* | `5.0` | 2.1 | -|    [optimizeTransferWaitTime](#rd_to_optimizeTransferWaitTime) | `boolean` | This enables the transfer wait time optimization. | *Optional* | `true` | 2.1 | -| [transitReluctanceForMode](#rd_transitReluctanceForMode) | `enum map of double` | Transit reluctance for a given transport mode | *Optional* | | 2.1 | -| [unpreferred](#rd_unpreferred) | `object` | Parameters listing authorities or lines that preferably should not be used in trip patters. | *Optional* | | 2.2 | -|    [agencies](#rd_unpreferred_agencies) | `feed-scoped-id[]` | The ids of the agencies that incur an extra cost when being used. Format: `FeedId:AgencyId` | *Optional* | | 2.2 | -|    [routes](#rd_unpreferred_routes) | `feed-scoped-id[]` | The ids of the routes that incur an extra cost when being used. Format: `FeedId:RouteId` | *Optional* | | 2.2 | -| vehicleRental | `object` | Vehicle rental options | *Optional* | | 2.3 | -|    allowKeepingAtDestination | `boolean` | If a vehicle should be allowed to be kept at the end of a station-based rental. | *Optional* | `false` | 2.2 | -|    dropOffCost | `integer` | Cost to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | -|    dropOffTime | `integer` | Time to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | -|    keepingAtDestinationCost | `double` | The cost of arriving at the destination with the rented vehicle, to discourage doing so. | *Optional* | `0.0` | 2.2 | -|    pickupCost | `integer` | Cost to rent a vehicle. | *Optional* | `120` | 2.0 | -|    pickupTime | `integer` | Time to rent a vehicle. | *Optional* | `60` | 2.0 | -|    useAvailabilityInformation | `boolean` | Whether or not vehicle rental availability information will be used to plan vehicle rental trips. | *Optional* | `false` | 2.0 | -|    [allowedNetworks](#rd_vehicleRental_allowedNetworks) | `string[]` | The vehicle rental networks which may be used. If empty all networks may be used. | *Optional* | | 2.1 | -|    [bannedNetworks](#rd_vehicleRental_bannedNetworks) | `string[]` | The vehicle rental networks which may not be used. If empty, no networks are banned. | *Optional* | | 2.1 | -| wheelchairAccessibility | `object` | See [Wheelchair Accessibility](Accessibility.md) | *Optional* | | 2.2 | -|    enabled | `boolean` | Enable wheelchair accessibility. | *Optional* | `false` | 2.0 | -|    inaccessibleStreetReluctance | `double` | The factor to multiply the cost of traversing a street edge that is not wheelchair-accessible. | *Optional* | `25.0` | 2.2 | -|    [maxSlope](#rd_wheelchairAccessibility_maxSlope) | `double` | The maximum slope as a fraction of 1. | *Optional* | `0.083` | 2.0 | -|    [slopeExceededReluctance](#rd_wheelchairAccessibility_slopeExceededReluctance) | `double` | How much streets with high slope should be avoided. | *Optional* | `1.0` | 2.2 | -|    [stairsReluctance](#rd_wheelchairAccessibility_stairsReluctance) | `double` | How much stairs should be avoided. | *Optional* | `100.0` | 2.2 | -|    elevator | `object` | Configuration for when to use inaccessible elevators. | *Optional* | | 2.2 | -|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | -|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `false` | 2.2 | -|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `20` | 2.2 | -|    stop | `object` | Configuration for when to use inaccessible stops. | *Optional* | | 2.2 | -|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | -|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `true` | 2.2 | -|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `600` | 2.2 | -|    trip | `object` | Configuration for when to use inaccessible trips. | *Optional* | | 2.2 | -|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | -|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `true` | 2.2 | -|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `600` | 2.2 | ->>>>>>> otp/dev-2.x diff --git a/docs/RouterConfiguration.md b/docs/RouterConfiguration.md index bdb39df2bf6..bcbf798a70e 100644 --- a/docs/RouterConfiguration.md +++ b/docs/RouterConfiguration.md @@ -494,6 +494,8 @@ HTTP headers to add to the request. Any header key, value can be inserted. "costLimitFunction" : "900 + 1.5 x", "intervalRelaxFactor" : 0.4 }, + "nonTransitGeneralizedCostLimit" : "400 + 1.5x", + "removeTransitWithHigherCostThanBestOnStreetOnly" : "60 + 1.3x", "bikeRentalDistanceRatio" : 0.3, "accessibilityScore" : true, "minBikeParkingDistance" : 300 From 8e3e2c18ba0b0266199412aafd7525dc34bd0649 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Mon, 21 Aug 2023 12:00:35 +0300 Subject: [PATCH 07/36] Use CostLinearFunction --- docs/RouteRequest.md | 367 ++++++------------ ...moveTransitIfStreetOnlyIsBetterFilter.java | 9 +- .../ItineraryListFilterChainTest.java | 9 +- ...TransitIfStreetOnlyIsBetterFilterTest.java | 11 +- .../ItineraryFilterPreferencesTest.java | 16 +- 5 files changed, 153 insertions(+), 259 deletions(-) diff --git a/docs/RouteRequest.md b/docs/RouteRequest.md index 121514588bd..bfe06777618 100644 --- a/docs/RouteRequest.md +++ b/docs/RouteRequest.md @@ -13,250 +13,127 @@ and in the [transferRequests in build-config.json](BuildConfiguration.md#transfe -<<<<<<< HEAD -| Config Parameter | Type | Summary | Req./Opt. | Default Value | Since | -|--------------------------------------------------------------------------------------------------------------|:----------------------:|------------------------------------------------------------------------------------------------------------------------------------------------|:----------:|--------------------------|:-----:| -| [alightSlack](#rd_alightSlack) | `duration` | The minimum extra time after exiting a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | -| arriveBy | `boolean` | Whether the trip should depart or arrive at the specified date and time. | *Optional* | `false` | 2.0 | -| [bikeBoardCost](#rd_bikeBoardCost) | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. | *Optional* | `600` | 2.0 | -| bikeParkCost | `integer` | Cost to park a bike. | *Optional* | `120` | 2.0 | -| bikeParkTime | `integer` | Time to park a bike. | *Optional* | `60` | 2.0 | -| bikeReluctance | `double` | A multiplier for how bad biking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| bikeSpeed | `double` | Max bike speed along streets, in meters per second | *Optional* | `5.0` | 2.0 | -| bikeStairsReluctance | `double` | How bad is it to walk the bicycle up/down a flight of stairs compared to taking a detour. | *Optional* | `10.0` | 2.3 | -| bikeSwitchCost | `integer` | The cost of the user fetching their bike and parking it again. | *Optional* | `0` | 2.0 | -| bikeSwitchTime | `integer` | The time it takes the user to fetch their bike and park it again in seconds. | *Optional* | `0` | 2.0 | -| bikeTriangleSafetyFactor | `double` | For bike triangle routing, how much safety matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeTriangleSlopeFactor | `double` | For bike triangle routing, how much slope matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeTriangleTimeFactor | `double` | For bike triangle routing, how much time matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeWalkingReluctance | `double` | A multiplier for how bad walking with a bike is, compared to being in transit for equal lengths of time. | *Optional* | `5.0` | 2.1 | -| bikeWalkingSpeed | `double` | The user's bike walking speed in meters/second. Defaults to approximately 3 MPH. | *Optional* | `1.33` | 2.1 | -| [boardSlack](#rd_boardSlack) | `duration` | The boardSlack is the minimum extra time to board a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | -| carAccelerationSpeed | `double` | The acceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | -| carDecelerationSpeed | `double` | The deceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | -| carDropoffTime | `integer` | Time to park a car in a park and ride, w/o taking into account driving and walking cost. | *Optional* | `120` | 2.0 | -| carParkCost | `integer` | Cost of parking a car. | *Optional* | `120` | 2.1 | -| carParkTime | `integer` | Time to park a car | *Optional* | `60` | 2.1 | -| carPickupCost | `integer` | Add a cost for car pickup changes when a pickup or drop off takes place | *Optional* | `120` | 2.1 | -| carPickupTime | `integer` | Add a time for car pickup changes when a pickup or drop off takes place | *Optional* | `60` | 2.1 | -| carReluctance | `double` | A multiplier for how bad driving is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| carSpeed | `double` | Max car speed along streets, in meters per second | *Optional* | `40.0` | 2.0 | -| [drivingDirection](#rd_drivingDirection) | `enum` | The driving direction to use in the intersection traversal calculation | *Optional* | `"right"` | 2.2 | -| elevatorBoardCost | `integer` | What is the cost of boarding a elevator? | *Optional* | `90` | 2.0 | -| elevatorBoardTime | `integer` | How long does it take to get on an elevator, on average. | *Optional* | `90` | 2.0 | -| elevatorHopCost | `integer` | What is the cost of travelling one floor on an elevator? | *Optional* | `20` | 2.0 | -| elevatorHopTime | `integer` | How long does it take to advance one floor on an elevator? | *Optional* | `20` | 2.0 | -| escalatorReluctance | `double` | A multiplier for how bad being in an escalator is compared to being in transit for equal lengths of time | *Optional* | `1.5` | 2.4 | -| geoidElevation | `boolean` | If true, the Graph's ellipsoidToGeoidDifference is applied to all elevations returned by this query. | *Optional* | `false` | 2.0 | -| ignoreRealtimeUpdates | `boolean` | When true, realtime updates are ignored during this search. | *Optional* | `false` | 2.0 | -| [intersectionTraversalModel](#rd_intersectionTraversalModel) | `enum` | The model that computes the costs of turns. | *Optional* | `"simple"` | 2.2 | -| locale | `locale` | TODO | *Optional* | `"en_US"` | 2.0 | -| [maxAccessEgressDuration](#rd_maxAccessEgressDuration) | `duration` | This is the maximum duration for access/egress for street searches. | *Optional* | `"PT45M"` | 2.1 | -| [maxDirectStreetDuration](#rd_maxDirectStreetDuration) | `duration` | This is the maximum duration for a direct street search for each mode. | *Optional* | `"PT4H"` | 2.1 | -| [maxJourneyDuration](#rd_maxJourneyDuration) | `duration` | The expected maximum time a journey can last across all possible journeys for the current deployment. | *Optional* | `"PT24H"` | 2.1 | -| modes | `string` | The set of access/egress/direct/transit modes to be used for the route search. | *Optional* | `"TRANSIT,WALK"` | 2.0 | -| nonpreferredTransferPenalty | `integer` | Penalty (in seconds) for using a non-preferred transfer. | *Optional* | `180` | 2.0 | -| numItineraries | `integer` | The maximum number of itineraries to return. | *Optional* | `50` | 2.0 | -| [optimize](#rd_optimize) | `enum` | The set of characteristics that the user wants to optimize for. | *Optional* | `"safe"` | 2.0 | -| [otherThanPreferredRoutesPenalty](#rd_otherThanPreferredRoutesPenalty) | `integer` | Penalty added for using every route that is not preferred if user set any route as preferred. | *Optional* | `300` | 2.0 | -| [relaxTransitSearchGeneralizedCostAtDestination](#rd_relaxTransitSearchGeneralizedCostAtDestination) | `double` | Whether non-optimal transit paths at the destination should be returned | *Optional* | | 2.3 | -| [searchWindow](#rd_searchWindow) | `duration` | The duration of the search-window. | *Optional* | | 2.0 | -| stairsReluctance | `double` | Used instead of walkReluctance for stairs. | *Optional* | `2.0` | 2.0 | -| [stairsTimeFactor](#rd_stairsTimeFactor) | `double` | How much more time does it take to walk a flight of stairs compared to walking a similar horizontal length. | *Optional* | `3.0` | 2.1 | -| [streetRoutingTimeout](#rd_streetRoutingTimeout) | `duration` | The maximum time a street routing request is allowed to take before returning the results. | *Optional* | `"PT5S"` | 2.2 | -| [transferPenalty](#rd_transferPenalty) | `integer` | An additional penalty added to boardings after the first. | *Optional* | `0` | 2.0 | -| [transferSlack](#rd_transferSlack) | `integer` | The extra time needed to make a safe transfer in seconds. | *Optional* | `120` | 2.0 | -| turnReluctance | `double` | Multiplicative factor on expected turning time. | *Optional* | `1.0` | 2.0 | -| [unpreferredCost](#rd_unpreferredCost) | `linear-function` | A cost function used to calculate penalty for an unpreferred route. | *Optional* | `"f(x) = 0 + 1.0 x"` | 2.2 | -| [unpreferredVehicleParkingTagCost](#rd_unpreferredVehicleParkingTagCost) | `integer` | What cost to add if a parking facility doesn't contain a preferred tag. | *Optional* | `300` | 2.3 | -| waitReluctance | `double` | How much worse is waiting for a transit vehicle than being on a transit vehicle, as a multiplier. | *Optional* | `1.0` | 2.0 | -| walkBoardCost | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. This is the cost that is used when boarding while walking. | *Optional* | `600` | 2.0 | -| [walkReluctance](#rd_walkReluctance) | `double` | A multiplier for how bad walking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| [walkSafetyFactor](#rd_walkSafetyFactor) | `double` | Factor for how much the walk safety is considered in routing. | *Optional* | `1.0` | 2.2 | -| walkSpeed | `double` | The user's walking speed in meters/second. | *Optional* | `1.33` | 2.0 | -| [accessEgressPenalty](#rd_accessEgressPenalty) | `enum map of object` | Penalty for access/egress by street mode. | *Optional* | | 2.4 | -| [alightSlackForMode](#rd_alightSlackForMode) | `enum map of duration` | How much extra time should be given when alighting a vehicle for each given mode. | *Optional* | | 2.0 | -| [bannedVehicleParkingTags](#rd_bannedVehicleParkingTags) | `string[]` | Tags with which a vehicle parking will not be used. If empty, no tags are banned. | *Optional* | | 2.1 | -| [boardSlackForMode](#rd_boardSlackForMode) | `enum map of duration` | How much extra time should be given when boarding a vehicle for each given mode. | *Optional* | | 2.0 | -| [itineraryFilters](#rd_itineraryFilters) | `object` | Configure itinerary filters that may modify itineraries, sort them, and filter away less preferable results. | *Optional* | | 2.0 | -|    [accessibilityScore](#rd_if_accessibilityScore) | `boolean` | An experimental feature contributed by IBI which adds a sandbox accessibility *score* between 0 and 1 for each leg and itinerary. | *Optional* | `false` | 2.2 | -|    [bikeRentalDistanceRatio](#rd_if_bikeRentalDistanceRatio) | `double` | Filter routes that consist of bike-rental and walking by the minimum fraction of the bike-rental leg using _distance_. | *Optional* | `0.0` | 2.1 | -|    [debug](#rd_if_debug) | `enum` | Enable this to attach a system notice to itineraries instead of removing them. This is very convenient when tuning the itinerary-filter-chain. | *Optional* | `"off"` | 2.0 | -|    [filterItinerariesWithSameFirstOrLastTrip](#rd_if_filterItinerariesWithSameFirstOrLastTrip) | `boolean` | If more than one itinerary begins or ends with same trip, filter out one of those itineraries so that only one remains. | *Optional* | `false` | 2.2 | -|    groupSimilarityKeepOne | `double` | Pick ONE itinerary from each group after putting itineraries that are 85% similar together. | *Optional* | `0.85` | 2.1 | -|    groupSimilarityKeepThree | `double` | Reduce the number of itineraries to three itineraries by reducing each group of itineraries grouped by 68% similarity. | *Optional* | `0.68` | 2.1 | -|    [groupedOtherThanSameLegsMaxCostMultiplier](#rd_if_groupedOtherThanSameLegsMaxCostMultiplier) | `double` | Filter grouped itineraries, where the non-grouped legs are more expensive than in the lowest cost one. | *Optional* | `2.0` | 2.1 | -|    [minBikeParkingDistance](#rd_if_minBikeParkingDistance) | `double` | Filter out bike park+ride results that have fewer meters of cycling than this value. | *Optional* | `0.0` | 2.3 | -|    [nonTransitGeneralizedCostLimit](#rd_if_nonTransitGeneralizedCostLimit) | `linear-function` | The function define a max-limit for generalized-cost for non-transit itineraries. | *Optional* | `"f(x) = 3,600 + 2.0 x"` | 2.1 | -|    [parkAndRideDurationRatio](#rd_if_parkAndRideDurationRatio) | `double` | Filter P+R routes that consist of driving and walking by the minimum fraction of the driving using of _time_. | *Optional* | `0.0` | 2.1 | -|    [removeItinerariesWithSameRoutesAndStops](#rd_if_removeItinerariesWithSameRoutesAndStops) | `boolean` | Set to true if you want to list only the first itinerary which goes through the same stops and routes. | *Optional* | `false` | 2.2 | -|    [removeTransitWithHigherCostThanBestOnStreetOnly](#rd_if_removeTransitWithHigherCostThanBestOnStreetOnly) | `linear-function` | Limit function for generalized-cost computed from non-transit itineries for transit itineraries. | *Optional* | `"f(x) = 60 + 1.3 x"` | 2.4 | -|    [transitGeneralizedCostLimit](#rd_if_transitGeneralizedCostLimit) | `object` | A relative limit for the generalized-cost for transit itineraries. | *Optional* | | 2.1 | -|       [costLimitFunction](#rd_if_transitGeneralizedCostLimit_costLimitFunction) | `linear-function` | The base function used by the filter. | *Optional* | `"f(x) = 900 + 1.5 x"` | 2.2 | -|       [intervalRelaxFactor](#rd_if_transitGeneralizedCostLimit_intervalRelaxFactor) | `double` | How much the filter should be relaxed for itineraries that do not overlap in time. | *Optional* | `0.4` | 2.2 | -| [maxAccessEgressDurationForMode](#rd_maxAccessEgressDurationForMode) | `enum map of duration` | Limit access/egress per street mode. | *Optional* | | 2.1 | -| [maxDirectStreetDurationForMode](#rd_maxDirectStreetDurationForMode) | `enum map of duration` | Limit direct route duration per street mode. | *Optional* | | 2.2 | -| [preferredVehicleParkingTags](#rd_preferredVehicleParkingTags) | `string[]` | Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised. | *Optional* | | 2.3 | -| [requiredVehicleParkingTags](#rd_requiredVehicleParkingTags) | `string[]` | Tags without which a vehicle parking will not be used. If empty, no tags are required. | *Optional* | | 2.1 | -| [transferOptimization](#rd_transferOptimization) | `object` | Optimize where a transfer between to trip happens. | *Optional* | | 2.1 | -|    [backTravelWaitTimeFactor](#rd_to_backTravelWaitTimeFactor) | `double` | To reduce back-travel we favor waiting, this reduces the cost of waiting. | *Optional* | `1.0` | 2.1 | -|    [extraStopBoardAlightCostsFactor](#rd_to_extraStopBoardAlightCostsFactor) | `double` | Add an extra board- and alight-cost for prioritized stops. | *Optional* | `0.0` | 2.1 | -|    [minSafeWaitTimeFactor](#rd_to_minSafeWaitTimeFactor) | `double` | Used to set a maximum wait-time cost, base on min-safe-transfer-time. | *Optional* | `5.0` | 2.1 | -|    [optimizeTransferWaitTime](#rd_to_optimizeTransferWaitTime) | `boolean` | This enables the transfer wait time optimization. | *Optional* | `true` | 2.1 | -| [transitReluctanceForMode](#rd_transitReluctanceForMode) | `enum map of double` | Transit reluctance for a given transport mode | *Optional* | | 2.1 | -| [unpreferred](#rd_unpreferred) | `object` | Parameters listing authorities or lines that preferably should not be used in trip patters. | *Optional* | | 2.2 | -|    [agencies](#rd_unpreferred_agencies) | `feed-scoped-id[]` | The ids of the agencies that incur an extra cost when being used. Format: `FeedId:AgencyId` | *Optional* | | 2.2 | -|    [routes](#rd_unpreferred_routes) | `feed-scoped-id[]` | The ids of the routes that incur an extra cost when being used. Format: `FeedId:RouteId` | *Optional* | | 2.2 | -| vehicleRental | `object` | Vehicle rental options | *Optional* | | 2.3 | -|    allowKeepingAtDestination | `boolean` | If a vehicle should be allowed to be kept at the end of a station-based rental. | *Optional* | `false` | 2.2 | -|    dropOffCost | `integer` | Cost to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | -|    dropOffTime | `integer` | Time to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | -|    keepingAtDestinationCost | `double` | The cost of arriving at the destination with the rented vehicle, to discourage doing so. | *Optional* | `0.0` | 2.2 | -|    pickupCost | `integer` | Cost to rent a vehicle. | *Optional* | `120` | 2.0 | -|    pickupTime | `integer` | Time to rent a vehicle. | *Optional* | `60` | 2.0 | -|    useAvailabilityInformation | `boolean` | Whether or not vehicle rental availability information will be used to plan vehicle rental trips. | *Optional* | `false` | 2.0 | -|    [allowedNetworks](#rd_vehicleRental_allowedNetworks) | `string[]` | The vehicle rental networks which may be used. If empty all networks may be used. | *Optional* | | 2.1 | -|    [bannedNetworks](#rd_vehicleRental_bannedNetworks) | `string[]` | The vehicle rental networks which may not be used. If empty, no networks are banned. | *Optional* | | 2.1 | -| wheelchairAccessibility | `object` | See [Wheelchair Accessibility](Accessibility.md) | *Optional* | | 2.2 | -|    enabled | `boolean` | Enable wheelchair accessibility. | *Optional* | `false` | 2.0 | -|    inaccessibleStreetReluctance | `double` | The factor to multiply the cost of traversing a street edge that is not wheelchair-accessible. | *Optional* | `25.0` | 2.2 | -|    [maxSlope](#rd_wheelchairAccessibility_maxSlope) | `double` | The maximum slope as a fraction of 1. | *Optional* | `0.083` | 2.0 | -|    [slopeExceededReluctance](#rd_wheelchairAccessibility_slopeExceededReluctance) | `double` | How much streets with high slope should be avoided. | *Optional* | `1.0` | 2.2 | -|    [stairsReluctance](#rd_wheelchairAccessibility_stairsReluctance) | `double` | How much stairs should be avoided. | *Optional* | `100.0` | 2.2 | -|    elevator | `object` | Configuration for when to use inaccessible elevators. | *Optional* | | 2.2 | -|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | -|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `false` | 2.2 | -|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `20` | 2.2 | -|    stop | `object` | Configuration for when to use inaccessible stops. | *Optional* | | 2.2 | -|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | -|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `true` | 2.2 | -|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `600` | 2.2 | -|    trip | `object` | Configuration for when to use inaccessible trips. | *Optional* | | 2.2 | -|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | -|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `true` | 2.2 | -|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `600` | 2.2 | -======= -| Config Parameter | Type | Summary | Req./Opt. | Default Value | Since | -|------------------------------------------------------------------------------------------------------|:----------------------:|------------------------------------------------------------------------------------------------------------------------------------------------|:----------:|------------------|:-----:| -| [alightSlack](#rd_alightSlack) | `duration` | The minimum extra time after exiting a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | -| arriveBy | `boolean` | Whether the trip should depart or arrive at the specified date and time. | *Optional* | `false` | 2.0 | -| [bikeBoardCost](#rd_bikeBoardCost) | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. | *Optional* | `600` | 2.0 | -| bikeParkCost | `integer` | Cost to park a bike. | *Optional* | `120` | 2.0 | -| bikeParkTime | `integer` | Time to park a bike. | *Optional* | `60` | 2.0 | -| bikeReluctance | `double` | A multiplier for how bad biking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| bikeSpeed | `double` | Max bike speed along streets, in meters per second | *Optional* | `5.0` | 2.0 | -| bikeStairsReluctance | `double` | How bad is it to walk the bicycle up/down a flight of stairs compared to taking a detour. | *Optional* | `10.0` | 2.3 | -| bikeSwitchCost | `integer` | The cost of the user fetching their bike and parking it again. | *Optional* | `0` | 2.0 | -| bikeSwitchTime | `integer` | The time it takes the user to fetch their bike and park it again in seconds. | *Optional* | `0` | 2.0 | -| bikeTriangleSafetyFactor | `double` | For bike triangle routing, how much safety matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeTriangleSlopeFactor | `double` | For bike triangle routing, how much slope matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeTriangleTimeFactor | `double` | For bike triangle routing, how much time matters (range 0-1). | *Optional* | `0.0` | 2.0 | -| bikeWalkingReluctance | `double` | A multiplier for how bad walking with a bike is, compared to being in transit for equal lengths of time. | *Optional* | `5.0` | 2.1 | -| bikeWalkingSpeed | `double` | The user's bike walking speed in meters/second. Defaults to approximately 3 MPH. | *Optional* | `1.33` | 2.1 | -| [boardSlack](#rd_boardSlack) | `duration` | The boardSlack is the minimum extra time to board a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | -| carAccelerationSpeed | `double` | The acceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | -| carDecelerationSpeed | `double` | The deceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | -| carDropoffTime | `integer` | Time to park a car in a park and ride, w/o taking into account driving and walking cost. | *Optional* | `120` | 2.0 | -| carParkCost | `integer` | Cost of parking a car. | *Optional* | `120` | 2.1 | -| carParkTime | `integer` | Time to park a car | *Optional* | `60` | 2.1 | -| carPickupCost | `integer` | Add a cost for car pickup changes when a pickup or drop off takes place | *Optional* | `120` | 2.1 | -| carPickupTime | `integer` | Add a time for car pickup changes when a pickup or drop off takes place | *Optional* | `60` | 2.1 | -| carReluctance | `double` | A multiplier for how bad driving is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| carSpeed | `double` | Max car speed along streets, in meters per second | *Optional* | `40.0` | 2.0 | -| [drivingDirection](#rd_drivingDirection) | `enum` | The driving direction to use in the intersection traversal calculation | *Optional* | `"right"` | 2.2 | -| elevatorBoardCost | `integer` | What is the cost of boarding a elevator? | *Optional* | `90` | 2.0 | -| elevatorBoardTime | `integer` | How long does it take to get on an elevator, on average. | *Optional* | `90` | 2.0 | -| elevatorHopCost | `integer` | What is the cost of travelling one floor on an elevator? | *Optional* | `20` | 2.0 | -| elevatorHopTime | `integer` | How long does it take to advance one floor on an elevator? | *Optional* | `20` | 2.0 | -| escalatorReluctance | `double` | A multiplier for how bad being in an escalator is compared to being in transit for equal lengths of time | *Optional* | `1.5` | 2.4 | -| geoidElevation | `boolean` | If true, the Graph's ellipsoidToGeoidDifference is applied to all elevations returned by this query. | *Optional* | `false` | 2.0 | -| ignoreRealtimeUpdates | `boolean` | When true, realtime updates are ignored during this search. | *Optional* | `false` | 2.0 | -| [intersectionTraversalModel](#rd_intersectionTraversalModel) | `enum` | The model that computes the costs of turns. | *Optional* | `"simple"` | 2.2 | -| locale | `locale` | TODO | *Optional* | `"en_US"` | 2.0 | -| [maxAccessEgressDuration](#rd_maxAccessEgressDuration) | `duration` | This is the maximum duration for access/egress for street searches. | *Optional* | `"PT45M"` | 2.1 | -| [maxDirectStreetDuration](#rd_maxDirectStreetDuration) | `duration` | This is the maximum duration for a direct street search for each mode. | *Optional* | `"PT4H"` | 2.1 | -| [maxJourneyDuration](#rd_maxJourneyDuration) | `duration` | The expected maximum time a journey can last across all possible journeys for the current deployment. | *Optional* | `"PT24H"` | 2.1 | -| modes | `string` | The set of access/egress/direct/transit modes to be used for the route search. | *Optional* | `"TRANSIT,WALK"` | 2.0 | -| nonpreferredTransferPenalty | `integer` | Penalty (in seconds) for using a non-preferred transfer. | *Optional* | `180` | 2.0 | -| numItineraries | `integer` | The maximum number of itineraries to return. | *Optional* | `50` | 2.0 | -| [optimize](#rd_optimize) | `enum` | The set of characteristics that the user wants to optimize for. | *Optional* | `"safe"` | 2.0 | -| [otherThanPreferredRoutesPenalty](#rd_otherThanPreferredRoutesPenalty) | `integer` | Penalty added for using every route that is not preferred if user set any route as preferred. | *Optional* | `300` | 2.0 | -| [relaxTransitSearchGeneralizedCostAtDestination](#rd_relaxTransitSearchGeneralizedCostAtDestination) | `double` | Whether non-optimal transit paths at the destination should be returned | *Optional* | | 2.3 | -| [searchWindow](#rd_searchWindow) | `duration` | The duration of the search-window. | *Optional* | | 2.0 | -| stairsReluctance | `double` | Used instead of walkReluctance for stairs. | *Optional* | `2.0` | 2.0 | -| [stairsTimeFactor](#rd_stairsTimeFactor) | `double` | How much more time does it take to walk a flight of stairs compared to walking a similar horizontal length. | *Optional* | `3.0` | 2.1 | -| [streetRoutingTimeout](#rd_streetRoutingTimeout) | `duration` | The maximum time a street routing request is allowed to take before returning the results. | *Optional* | `"PT5S"` | 2.2 | -| [transferPenalty](#rd_transferPenalty) | `integer` | An additional penalty added to boardings after the first. | *Optional* | `0` | 2.0 | -| [transferSlack](#rd_transferSlack) | `integer` | The extra time needed to make a safe transfer in seconds. | *Optional* | `120` | 2.0 | -| turnReluctance | `double` | Multiplicative factor on expected turning time. | *Optional* | `1.0` | 2.0 | -| [unpreferredCost](#rd_unpreferredCost) | `cost-linear-function` | A cost function used to calculate penalty for an unpreferred route. | *Optional* | `"0s + 1.00 t"` | 2.2 | -| [unpreferredVehicleParkingTagCost](#rd_unpreferredVehicleParkingTagCost) | `integer` | What cost to add if a parking facility doesn't contain a preferred tag. | *Optional* | `300` | 2.3 | -| waitReluctance | `double` | How much worse is waiting for a transit vehicle than being on a transit vehicle, as a multiplier. | *Optional* | `1.0` | 2.0 | -| walkBoardCost | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. This is the cost that is used when boarding while walking. | *Optional* | `600` | 2.0 | -| [walkReluctance](#rd_walkReluctance) | `double` | A multiplier for how bad walking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | -| [walkSafetyFactor](#rd_walkSafetyFactor) | `double` | Factor for how much the walk safety is considered in routing. | *Optional* | `1.0` | 2.2 | -| walkSpeed | `double` | The user's walking speed in meters/second. | *Optional* | `1.33` | 2.0 | -| [accessEgressPenalty](#rd_accessEgressPenalty) | `enum map of object` | Penalty for access/egress by street mode. | *Optional* | | 2.4 | -| [alightSlackForMode](#rd_alightSlackForMode) | `enum map of duration` | How much extra time should be given when alighting a vehicle for each given mode. | *Optional* | | 2.0 | -| [bannedVehicleParkingTags](#rd_bannedVehicleParkingTags) | `string[]` | Tags with which a vehicle parking will not be used. If empty, no tags are banned. | *Optional* | | 2.1 | -| [boardSlackForMode](#rd_boardSlackForMode) | `enum map of duration` | How much extra time should be given when boarding a vehicle for each given mode. | *Optional* | | 2.0 | -| [itineraryFilters](#rd_itineraryFilters) | `object` | Configure itinerary filters that may modify itineraries, sort them, and filter away less preferable results. | *Optional* | | 2.0 | -|    [accessibilityScore](#rd_if_accessibilityScore) | `boolean` | An experimental feature contributed by IBI which adds a sandbox accessibility *score* between 0 and 1 for each leg and itinerary. | *Optional* | `false` | 2.2 | -|    [bikeRentalDistanceRatio](#rd_if_bikeRentalDistanceRatio) | `double` | Filter routes that consist of bike-rental and walking by the minimum fraction of the bike-rental leg using _distance_. | *Optional* | `0.0` | 2.1 | -|    [debug](#rd_if_debug) | `enum` | Enable this to attach a system notice to itineraries instead of removing them. This is very convenient when tuning the itinerary-filter-chain. | *Optional* | `"off"` | 2.0 | -|    [filterItinerariesWithSameFirstOrLastTrip](#rd_if_filterItinerariesWithSameFirstOrLastTrip) | `boolean` | If more than one itinerary begins or ends with same trip, filter out one of those itineraries so that only one remains. | *Optional* | `false` | 2.2 | -|    groupSimilarityKeepOne | `double` | Pick ONE itinerary from each group after putting itineraries that are 85% similar together. | *Optional* | `0.85` | 2.1 | -|    groupSimilarityKeepThree | `double` | Reduce the number of itineraries to three itineraries by reducing each group of itineraries grouped by 68% similarity. | *Optional* | `0.68` | 2.1 | -|    [groupedOtherThanSameLegsMaxCostMultiplier](#rd_if_groupedOtherThanSameLegsMaxCostMultiplier) | `double` | Filter grouped itineraries, where the non-grouped legs are more expensive than in the lowest cost one. | *Optional* | `2.0` | 2.1 | -|    [minBikeParkingDistance](#rd_if_minBikeParkingDistance) | `double` | Filter out bike park+ride results that have fewer meters of cycling than this value. | *Optional* | `0.0` | 2.3 | -|    [nonTransitGeneralizedCostLimit](#rd_if_nonTransitGeneralizedCostLimit) | `cost-linear-function` | The function define a max-limit for generalized-cost for non-transit itineraries. | *Optional* | `"1h + 2.0 t"` | 2.1 | -|    [parkAndRideDurationRatio](#rd_if_parkAndRideDurationRatio) | `double` | Filter P+R routes that consist of driving and walking by the minimum fraction of the driving using of _time_. | *Optional* | `0.0` | 2.1 | -|    [removeItinerariesWithSameRoutesAndStops](#rd_if_removeItinerariesWithSameRoutesAndStops) | `boolean` | Set to true if you want to list only the first itinerary which goes through the same stops and routes. | *Optional* | `false` | 2.2 | -|    [transitGeneralizedCostLimit](#rd_if_transitGeneralizedCostLimit) | `object` | A relative limit for the generalized-cost for transit itineraries. | *Optional* | | 2.1 | -|       [costLimitFunction](#rd_if_transitGeneralizedCostLimit_costLimitFunction) | `cost-linear-function` | The base function used by the filter. | *Optional* | `"15m + 1.50 t"` | 2.2 | -|       [intervalRelaxFactor](#rd_if_transitGeneralizedCostLimit_intervalRelaxFactor) | `double` | How much the filter should be relaxed for itineraries that do not overlap in time. | *Optional* | `0.4` | 2.2 | -| [maxAccessEgressDurationForMode](#rd_maxAccessEgressDurationForMode) | `enum map of duration` | Limit access/egress per street mode. | *Optional* | | 2.1 | -| [maxDirectStreetDurationForMode](#rd_maxDirectStreetDurationForMode) | `enum map of duration` | Limit direct route duration per street mode. | *Optional* | | 2.2 | -| [preferredVehicleParkingTags](#rd_preferredVehicleParkingTags) | `string[]` | Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised. | *Optional* | | 2.3 | -| [requiredVehicleParkingTags](#rd_requiredVehicleParkingTags) | `string[]` | Tags without which a vehicle parking will not be used. If empty, no tags are required. | *Optional* | | 2.1 | -| [transferOptimization](#rd_transferOptimization) | `object` | Optimize where a transfer between to trip happens. | *Optional* | | 2.1 | -|    [backTravelWaitTimeFactor](#rd_to_backTravelWaitTimeFactor) | `double` | To reduce back-travel we favor waiting, this reduces the cost of waiting. | *Optional* | `1.0` | 2.1 | -|    [extraStopBoardAlightCostsFactor](#rd_to_extraStopBoardAlightCostsFactor) | `double` | Add an extra board- and alight-cost for prioritized stops. | *Optional* | `0.0` | 2.1 | -|    [minSafeWaitTimeFactor](#rd_to_minSafeWaitTimeFactor) | `double` | Used to set a maximum wait-time cost, base on min-safe-transfer-time. | *Optional* | `5.0` | 2.1 | -|    [optimizeTransferWaitTime](#rd_to_optimizeTransferWaitTime) | `boolean` | This enables the transfer wait time optimization. | *Optional* | `true` | 2.1 | -| [transitReluctanceForMode](#rd_transitReluctanceForMode) | `enum map of double` | Transit reluctance for a given transport mode | *Optional* | | 2.1 | -| [unpreferred](#rd_unpreferred) | `object` | Parameters listing authorities or lines that preferably should not be used in trip patters. | *Optional* | | 2.2 | -|    [agencies](#rd_unpreferred_agencies) | `feed-scoped-id[]` | The ids of the agencies that incur an extra cost when being used. Format: `FeedId:AgencyId` | *Optional* | | 2.2 | -|    [routes](#rd_unpreferred_routes) | `feed-scoped-id[]` | The ids of the routes that incur an extra cost when being used. Format: `FeedId:RouteId` | *Optional* | | 2.2 | -| vehicleRental | `object` | Vehicle rental options | *Optional* | | 2.3 | -|    allowKeepingAtDestination | `boolean` | If a vehicle should be allowed to be kept at the end of a station-based rental. | *Optional* | `false` | 2.2 | -|    dropOffCost | `integer` | Cost to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | -|    dropOffTime | `integer` | Time to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | -|    keepingAtDestinationCost | `double` | The cost of arriving at the destination with the rented vehicle, to discourage doing so. | *Optional* | `0.0` | 2.2 | -|    pickupCost | `integer` | Cost to rent a vehicle. | *Optional* | `120` | 2.0 | -|    pickupTime | `integer` | Time to rent a vehicle. | *Optional* | `60` | 2.0 | -|    useAvailabilityInformation | `boolean` | Whether or not vehicle rental availability information will be used to plan vehicle rental trips. | *Optional* | `false` | 2.0 | -|    [allowedNetworks](#rd_vehicleRental_allowedNetworks) | `string[]` | The vehicle rental networks which may be used. If empty all networks may be used. | *Optional* | | 2.1 | -|    [bannedNetworks](#rd_vehicleRental_bannedNetworks) | `string[]` | The vehicle rental networks which may not be used. If empty, no networks are banned. | *Optional* | | 2.1 | -| wheelchairAccessibility | `object` | See [Wheelchair Accessibility](Accessibility.md) | *Optional* | | 2.2 | -|    enabled | `boolean` | Enable wheelchair accessibility. | *Optional* | `false` | 2.0 | -|    inaccessibleStreetReluctance | `double` | The factor to multiply the cost of traversing a street edge that is not wheelchair-accessible. | *Optional* | `25.0` | 2.2 | -|    [maxSlope](#rd_wheelchairAccessibility_maxSlope) | `double` | The maximum slope as a fraction of 1. | *Optional* | `0.083` | 2.0 | -|    [slopeExceededReluctance](#rd_wheelchairAccessibility_slopeExceededReluctance) | `double` | How much streets with high slope should be avoided. | *Optional* | `1.0` | 2.2 | -|    [stairsReluctance](#rd_wheelchairAccessibility_stairsReluctance) | `double` | How much stairs should be avoided. | *Optional* | `100.0` | 2.2 | -|    elevator | `object` | Configuration for when to use inaccessible elevators. | *Optional* | | 2.2 | -|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | -|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `false` | 2.2 | -|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `20` | 2.2 | -|    stop | `object` | Configuration for when to use inaccessible stops. | *Optional* | | 2.2 | -|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | -|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `true` | 2.2 | -|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `600` | 2.2 | -|    trip | `object` | Configuration for when to use inaccessible trips. | *Optional* | | 2.2 | -|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | -|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `true` | 2.2 | -|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `600` | 2.2 | ->>>>>>> otp/dev-2.x +| Config Parameter | Type | Summary | Req./Opt. | Default Value | Since | +|--------------------------------------------------------------------------------------------------------------|:----------------------:|------------------------------------------------------------------------------------------------------------------------------------------------|:----------:|------------------|:-----:| +| [alightSlack](#rd_alightSlack) | `duration` | The minimum extra time after exiting a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | +| arriveBy | `boolean` | Whether the trip should depart or arrive at the specified date and time. | *Optional* | `false` | 2.0 | +| [bikeBoardCost](#rd_bikeBoardCost) | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. | *Optional* | `600` | 2.0 | +| bikeParkCost | `integer` | Cost to park a bike. | *Optional* | `120` | 2.0 | +| bikeParkTime | `integer` | Time to park a bike. | *Optional* | `60` | 2.0 | +| bikeReluctance | `double` | A multiplier for how bad biking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | +| bikeSpeed | `double` | Max bike speed along streets, in meters per second | *Optional* | `5.0` | 2.0 | +| bikeStairsReluctance | `double` | How bad is it to walk the bicycle up/down a flight of stairs compared to taking a detour. | *Optional* | `10.0` | 2.3 | +| bikeSwitchCost | `integer` | The cost of the user fetching their bike and parking it again. | *Optional* | `0` | 2.0 | +| bikeSwitchTime | `integer` | The time it takes the user to fetch their bike and park it again in seconds. | *Optional* | `0` | 2.0 | +| bikeTriangleSafetyFactor | `double` | For bike triangle routing, how much safety matters (range 0-1). | *Optional* | `0.0` | 2.0 | +| bikeTriangleSlopeFactor | `double` | For bike triangle routing, how much slope matters (range 0-1). | *Optional* | `0.0` | 2.0 | +| bikeTriangleTimeFactor | `double` | For bike triangle routing, how much time matters (range 0-1). | *Optional* | `0.0` | 2.0 | +| bikeWalkingReluctance | `double` | A multiplier for how bad walking with a bike is, compared to being in transit for equal lengths of time. | *Optional* | `5.0` | 2.1 | +| bikeWalkingSpeed | `double` | The user's bike walking speed in meters/second. Defaults to approximately 3 MPH. | *Optional* | `1.33` | 2.1 | +| [boardSlack](#rd_boardSlack) | `duration` | The boardSlack is the minimum extra time to board a public transport vehicle. | *Optional* | `"PT0S"` | 2.0 | +| carAccelerationSpeed | `double` | The acceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | +| carDecelerationSpeed | `double` | The deceleration speed of an automobile, in meters per second per second. | *Optional* | `2.9` | 2.0 | +| carDropoffTime | `integer` | Time to park a car in a park and ride, w/o taking into account driving and walking cost. | *Optional* | `120` | 2.0 | +| carParkCost | `integer` | Cost of parking a car. | *Optional* | `120` | 2.1 | +| carParkTime | `integer` | Time to park a car | *Optional* | `60` | 2.1 | +| carPickupCost | `integer` | Add a cost for car pickup changes when a pickup or drop off takes place | *Optional* | `120` | 2.1 | +| carPickupTime | `integer` | Add a time for car pickup changes when a pickup or drop off takes place | *Optional* | `60` | 2.1 | +| carReluctance | `double` | A multiplier for how bad driving is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | +| carSpeed | `double` | Max car speed along streets, in meters per second | *Optional* | `40.0` | 2.0 | +| [drivingDirection](#rd_drivingDirection) | `enum` | The driving direction to use in the intersection traversal calculation | *Optional* | `"right"` | 2.2 | +| elevatorBoardCost | `integer` | What is the cost of boarding a elevator? | *Optional* | `90` | 2.0 | +| elevatorBoardTime | `integer` | How long does it take to get on an elevator, on average. | *Optional* | `90` | 2.0 | +| elevatorHopCost | `integer` | What is the cost of travelling one floor on an elevator? | *Optional* | `20` | 2.0 | +| elevatorHopTime | `integer` | How long does it take to advance one floor on an elevator? | *Optional* | `20` | 2.0 | +| escalatorReluctance | `double` | A multiplier for how bad being in an escalator is compared to being in transit for equal lengths of time | *Optional* | `1.5` | 2.4 | +| geoidElevation | `boolean` | If true, the Graph's ellipsoidToGeoidDifference is applied to all elevations returned by this query. | *Optional* | `false` | 2.0 | +| ignoreRealtimeUpdates | `boolean` | When true, realtime updates are ignored during this search. | *Optional* | `false` | 2.0 | +| [intersectionTraversalModel](#rd_intersectionTraversalModel) | `enum` | The model that computes the costs of turns. | *Optional* | `"simple"` | 2.2 | +| locale | `locale` | TODO | *Optional* | `"en_US"` | 2.0 | +| [maxAccessEgressDuration](#rd_maxAccessEgressDuration) | `duration` | This is the maximum duration for access/egress for street searches. | *Optional* | `"PT45M"` | 2.1 | +| [maxDirectStreetDuration](#rd_maxDirectStreetDuration) | `duration` | This is the maximum duration for a direct street search for each mode. | *Optional* | `"PT4H"` | 2.1 | +| [maxJourneyDuration](#rd_maxJourneyDuration) | `duration` | The expected maximum time a journey can last across all possible journeys for the current deployment. | *Optional* | `"PT24H"` | 2.1 | +| modes | `string` | The set of access/egress/direct/transit modes to be used for the route search. | *Optional* | `"TRANSIT,WALK"` | 2.0 | +| nonpreferredTransferPenalty | `integer` | Penalty (in seconds) for using a non-preferred transfer. | *Optional* | `180` | 2.0 | +| numItineraries | `integer` | The maximum number of itineraries to return. | *Optional* | `50` | 2.0 | +| [optimize](#rd_optimize) | `enum` | The set of characteristics that the user wants to optimize for. | *Optional* | `"safe"` | 2.0 | +| [otherThanPreferredRoutesPenalty](#rd_otherThanPreferredRoutesPenalty) | `integer` | Penalty added for using every route that is not preferred if user set any route as preferred. | *Optional* | `300` | 2.0 | +| [relaxTransitSearchGeneralizedCostAtDestination](#rd_relaxTransitSearchGeneralizedCostAtDestination) | `double` | Whether non-optimal transit paths at the destination should be returned | *Optional* | | 2.3 | +| [searchWindow](#rd_searchWindow) | `duration` | The duration of the search-window. | *Optional* | | 2.0 | +| stairsReluctance | `double` | Used instead of walkReluctance for stairs. | *Optional* | `2.0` | 2.0 | +| [stairsTimeFactor](#rd_stairsTimeFactor) | `double` | How much more time does it take to walk a flight of stairs compared to walking a similar horizontal length. | *Optional* | `3.0` | 2.1 | +| [streetRoutingTimeout](#rd_streetRoutingTimeout) | `duration` | The maximum time a street routing request is allowed to take before returning the results. | *Optional* | `"PT5S"` | 2.2 | +| [transferPenalty](#rd_transferPenalty) | `integer` | An additional penalty added to boardings after the first. | *Optional* | `0` | 2.0 | +| [transferSlack](#rd_transferSlack) | `integer` | The extra time needed to make a safe transfer in seconds. | *Optional* | `120` | 2.0 | +| turnReluctance | `double` | Multiplicative factor on expected turning time. | *Optional* | `1.0` | 2.0 | +| [unpreferredCost](#rd_unpreferredCost) | `cost-linear-function` | A cost function used to calculate penalty for an unpreferred route. | *Optional* | `"0s + 1.00 t"` | 2.2 | +| [unpreferredVehicleParkingTagCost](#rd_unpreferredVehicleParkingTagCost) | `integer` | What cost to add if a parking facility doesn't contain a preferred tag. | *Optional* | `300` | 2.3 | +| waitReluctance | `double` | How much worse is waiting for a transit vehicle than being on a transit vehicle, as a multiplier. | *Optional* | `1.0` | 2.0 | +| walkBoardCost | `integer` | Prevents unnecessary transfers by adding a cost for boarding a vehicle. This is the cost that is used when boarding while walking. | *Optional* | `600` | 2.0 | +| [walkReluctance](#rd_walkReluctance) | `double` | A multiplier for how bad walking is, compared to being in transit for equal lengths of time. | *Optional* | `2.0` | 2.0 | +| [walkSafetyFactor](#rd_walkSafetyFactor) | `double` | Factor for how much the walk safety is considered in routing. | *Optional* | `1.0` | 2.2 | +| walkSpeed | `double` | The user's walking speed in meters/second. | *Optional* | `1.33` | 2.0 | +| [accessEgressPenalty](#rd_accessEgressPenalty) | `enum map of object` | Penalty for access/egress by street mode. | *Optional* | | 2.4 | +| [alightSlackForMode](#rd_alightSlackForMode) | `enum map of duration` | How much extra time should be given when alighting a vehicle for each given mode. | *Optional* | | 2.0 | +| [bannedVehicleParkingTags](#rd_bannedVehicleParkingTags) | `string[]` | Tags with which a vehicle parking will not be used. If empty, no tags are banned. | *Optional* | | 2.1 | +| [boardSlackForMode](#rd_boardSlackForMode) | `enum map of duration` | How much extra time should be given when boarding a vehicle for each given mode. | *Optional* | | 2.0 | +| [itineraryFilters](#rd_itineraryFilters) | `object` | Configure itinerary filters that may modify itineraries, sort them, and filter away less preferable results. | *Optional* | | 2.0 | +|    [accessibilityScore](#rd_if_accessibilityScore) | `boolean` | An experimental feature contributed by IBI which adds a sandbox accessibility *score* between 0 and 1 for each leg and itinerary. | *Optional* | `false` | 2.2 | +|    [bikeRentalDistanceRatio](#rd_if_bikeRentalDistanceRatio) | `double` | Filter routes that consist of bike-rental and walking by the minimum fraction of the bike-rental leg using _distance_. | *Optional* | `0.0` | 2.1 | +|    [debug](#rd_if_debug) | `enum` | Enable this to attach a system notice to itineraries instead of removing them. This is very convenient when tuning the itinerary-filter-chain. | *Optional* | `"off"` | 2.0 | +|    [filterItinerariesWithSameFirstOrLastTrip](#rd_if_filterItinerariesWithSameFirstOrLastTrip) | `boolean` | If more than one itinerary begins or ends with same trip, filter out one of those itineraries so that only one remains. | *Optional* | `false` | 2.2 | +|    groupSimilarityKeepOne | `double` | Pick ONE itinerary from each group after putting itineraries that are 85% similar together. | *Optional* | `0.85` | 2.1 | +|    groupSimilarityKeepThree | `double` | Reduce the number of itineraries to three itineraries by reducing each group of itineraries grouped by 68% similarity. | *Optional* | `0.68` | 2.1 | +|    [groupedOtherThanSameLegsMaxCostMultiplier](#rd_if_groupedOtherThanSameLegsMaxCostMultiplier) | `double` | Filter grouped itineraries, where the non-grouped legs are more expensive than in the lowest cost one. | *Optional* | `2.0` | 2.1 | +|    [minBikeParkingDistance](#rd_if_minBikeParkingDistance) | `double` | Filter out bike park+ride results that have fewer meters of cycling than this value. | *Optional* | `0.0` | 2.3 | +|    [nonTransitGeneralizedCostLimit](#rd_if_nonTransitGeneralizedCostLimit) | `cost-linear-function` | The function define a max-limit for generalized-cost for non-transit itineraries. | *Optional* | `"1h + 2.0 t"` | 2.1 | +|    [parkAndRideDurationRatio](#rd_if_parkAndRideDurationRatio) | `double` | Filter P+R routes that consist of driving and walking by the minimum fraction of the driving using of _time_. | *Optional* | `0.0` | 2.1 | +|    [removeItinerariesWithSameRoutesAndStops](#rd_if_removeItinerariesWithSameRoutesAndStops) | `boolean` | Set to true if you want to list only the first itinerary which goes through the same stops and routes. | *Optional* | `false` | 2.2 | +|    [removeTransitWithHigherCostThanBestOnStreetOnly](#rd_if_removeTransitWithHigherCostThanBestOnStreetOnly) | `cost-linear-function` | Limit function for generalized-cost computed from non-transit itineries for transit itineraries. | *Optional* | `"1m + 1.30 t"` | 2.4 | +|    [transitGeneralizedCostLimit](#rd_if_transitGeneralizedCostLimit) | `object` | A relative limit for the generalized-cost for transit itineraries. | *Optional* | | 2.1 | +|       [costLimitFunction](#rd_if_transitGeneralizedCostLimit_costLimitFunction) | `cost-linear-function` | The base function used by the filter. | *Optional* | `"15m + 1.50 t"` | 2.2 | +|       [intervalRelaxFactor](#rd_if_transitGeneralizedCostLimit_intervalRelaxFactor) | `double` | How much the filter should be relaxed for itineraries that do not overlap in time. | *Optional* | `0.4` | 2.2 | +| [maxAccessEgressDurationForMode](#rd_maxAccessEgressDurationForMode) | `enum map of duration` | Limit access/egress per street mode. | *Optional* | | 2.1 | +| [maxDirectStreetDurationForMode](#rd_maxDirectStreetDurationForMode) | `enum map of duration` | Limit direct route duration per street mode. | *Optional* | | 2.2 | +| [preferredVehicleParkingTags](#rd_preferredVehicleParkingTags) | `string[]` | Vehicle parking facilities that don't have one of these tags will receive an extra cost and will therefore be penalised. | *Optional* | | 2.3 | +| [requiredVehicleParkingTags](#rd_requiredVehicleParkingTags) | `string[]` | Tags without which a vehicle parking will not be used. If empty, no tags are required. | *Optional* | | 2.1 | +| [transferOptimization](#rd_transferOptimization) | `object` | Optimize where a transfer between to trip happens. | *Optional* | | 2.1 | +|    [backTravelWaitTimeFactor](#rd_to_backTravelWaitTimeFactor) | `double` | To reduce back-travel we favor waiting, this reduces the cost of waiting. | *Optional* | `1.0` | 2.1 | +|    [extraStopBoardAlightCostsFactor](#rd_to_extraStopBoardAlightCostsFactor) | `double` | Add an extra board- and alight-cost for prioritized stops. | *Optional* | `0.0` | 2.1 | +|    [minSafeWaitTimeFactor](#rd_to_minSafeWaitTimeFactor) | `double` | Used to set a maximum wait-time cost, base on min-safe-transfer-time. | *Optional* | `5.0` | 2.1 | +|    [optimizeTransferWaitTime](#rd_to_optimizeTransferWaitTime) | `boolean` | This enables the transfer wait time optimization. | *Optional* | `true` | 2.1 | +| [transitReluctanceForMode](#rd_transitReluctanceForMode) | `enum map of double` | Transit reluctance for a given transport mode | *Optional* | | 2.1 | +| [unpreferred](#rd_unpreferred) | `object` | Parameters listing authorities or lines that preferably should not be used in trip patters. | *Optional* | | 2.2 | +|    [agencies](#rd_unpreferred_agencies) | `feed-scoped-id[]` | The ids of the agencies that incur an extra cost when being used. Format: `FeedId:AgencyId` | *Optional* | | 2.2 | +|    [routes](#rd_unpreferred_routes) | `feed-scoped-id[]` | The ids of the routes that incur an extra cost when being used. Format: `FeedId:RouteId` | *Optional* | | 2.2 | +| vehicleRental | `object` | Vehicle rental options | *Optional* | | 2.3 | +|    allowKeepingAtDestination | `boolean` | If a vehicle should be allowed to be kept at the end of a station-based rental. | *Optional* | `false` | 2.2 | +|    dropOffCost | `integer` | Cost to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | +|    dropOffTime | `integer` | Time to drop-off a rented vehicle. | *Optional* | `30` | 2.0 | +|    keepingAtDestinationCost | `double` | The cost of arriving at the destination with the rented vehicle, to discourage doing so. | *Optional* | `0.0` | 2.2 | +|    pickupCost | `integer` | Cost to rent a vehicle. | *Optional* | `120` | 2.0 | +|    pickupTime | `integer` | Time to rent a vehicle. | *Optional* | `60` | 2.0 | +|    useAvailabilityInformation | `boolean` | Whether or not vehicle rental availability information will be used to plan vehicle rental trips. | *Optional* | `false` | 2.0 | +|    [allowedNetworks](#rd_vehicleRental_allowedNetworks) | `string[]` | The vehicle rental networks which may be used. If empty all networks may be used. | *Optional* | | 2.1 | +|    [bannedNetworks](#rd_vehicleRental_bannedNetworks) | `string[]` | The vehicle rental networks which may not be used. If empty, no networks are banned. | *Optional* | | 2.1 | +| wheelchairAccessibility | `object` | See [Wheelchair Accessibility](Accessibility.md) | *Optional* | | 2.2 | +|    enabled | `boolean` | Enable wheelchair accessibility. | *Optional* | `false` | 2.0 | +|    inaccessibleStreetReluctance | `double` | The factor to multiply the cost of traversing a street edge that is not wheelchair-accessible. | *Optional* | `25.0` | 2.2 | +|    [maxSlope](#rd_wheelchairAccessibility_maxSlope) | `double` | The maximum slope as a fraction of 1. | *Optional* | `0.083` | 2.0 | +|    [slopeExceededReluctance](#rd_wheelchairAccessibility_slopeExceededReluctance) | `double` | How much streets with high slope should be avoided. | *Optional* | `1.0` | 2.2 | +|    [stairsReluctance](#rd_wheelchairAccessibility_stairsReluctance) | `double` | How much stairs should be avoided. | *Optional* | `100.0` | 2.2 | +|    elevator | `object` | Configuration for when to use inaccessible elevators. | *Optional* | | 2.2 | +|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | +|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `false` | 2.2 | +|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `20` | 2.2 | +|    stop | `object` | Configuration for when to use inaccessible stops. | *Optional* | | 2.2 | +|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | +|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `true` | 2.2 | +|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `600` | 2.2 | +|    trip | `object` | Configuration for when to use inaccessible trips. | *Optional* | | 2.2 | +|       inaccessibleCost | `integer` | The cost to add when traversing an entity which is know to be inaccessible. | *Optional* | `3600` | 2.2 | +|       onlyConsiderAccessible | `boolean` | Whether to only use this entity if it is explicitly marked as wheelchair accessible. | *Optional* | `true` | 2.2 | +|       unknownCost | `integer` | The cost to add when traversing an entity with unknown accessibility information. | *Optional* | `600` | 2.2 | @@ -728,7 +605,7 @@ Itineraries visiting the same set of stops and riding the exact same routes, dep

removeTransitWithHigherCostThanBestOnStreetOnly

-**Since version:** `2.4` ∙ **Type:** `linear-function` ∙ **Cardinality:** `Optional` ∙ **Default value:** `"f(x) = 60 + 1.3 x"` +**Since version:** `2.4` ∙ **Type:** `cost-linear-function` ∙ **Cardinality:** `Optional` ∙ **Default value:** `"1m + 1.30 t"` **Path:** /routingDefaults/itineraryFilters Limit function for generalized-cost computed from non-transit itineries for transit itineraries. diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java index 87fef627568..e32fc9f4d9c 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java @@ -3,6 +3,7 @@ import java.util.Comparator; import java.util.List; import java.util.OptionalDouble; +import java.util.OptionalInt; import java.util.stream.Collectors; import org.opentripplanner.framework.model.Cost; import org.opentripplanner.model.plan.Itinerary; @@ -44,17 +45,19 @@ private double getWalkDistance(Itinerary it) { @Override public List flagForRemoval(List itineraries) { // Find the best walk-all-the-way option - OptionalDouble minStreetCost = itineraries + OptionalInt minStreetCost = itineraries .stream() .filter(Itinerary::isOnStreetAllTheWay) - .mapToDouble(Itinerary::getGeneralizedCost) + .mapToInt(Itinerary::getGeneralizedCost) .min(); if (minStreetCost.isEmpty()) { return List.of(); } - final Cost limit = costLimitFunction.calculate(minStreetCost.getAsDouble()); + var limit = costLimitFunction + .calculate(Cost.costOfSeconds(minStreetCost.getAsInt())) + .toSeconds(); // Filter away itineraries that have higher cost than limit cost computed above List filtered = itineraries diff --git a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java index 5ebbdc44222..065695b09a2 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java @@ -11,6 +11,7 @@ import static org.opentripplanner.model.plan.TestItineraryBuilder.newTime; import static org.opentripplanner.routing.api.request.preference.ItineraryFilterDebugProfile.ofDebugEnabled; +import java.time.Duration; import java.time.Instant; import java.util.List; import org.junit.jupiter.api.BeforeEach; @@ -21,7 +22,7 @@ import org.opentripplanner.model.plan.PlanTestConstants; import org.opentripplanner.model.plan.TestItineraryBuilder; import org.opentripplanner.routing.alertpatch.StopCondition; -import org.opentripplanner.routing.api.request.framework.RequestFunctions; +import org.opentripplanner.routing.api.request.framework.CostLinearFunction; import org.opentripplanner.routing.api.response.RoutingError; import org.opentripplanner.routing.api.response.RoutingErrorCode; import org.opentripplanner.routing.services.TransitAlertService; @@ -164,7 +165,7 @@ void testRoutingErrorsOriginDestinationTooCloseTest() { ItineraryListFilterChain chain = createBuilder(false, false, 20) .withRemoveWalkAllTheWayResults(true) .withRemoveTransitWithHigherCostThanBestOnStreetOnly( - RequestFunctions.createLinearFunction(0, 1.0) + CostLinearFunction.of(Duration.ofSeconds(0), 1.0) ) .build(); @@ -247,7 +248,7 @@ private ItineraryListFilterChainBuilder createBuilder( return new ItineraryListFilterChainBuilder(sortOrder) .withMaxNumberOfItineraries(numOfItineraries) .withRemoveTransitWithHigherCostThanBestOnStreetOnly( - RequestFunctions.createLinearFunction(0, 1.0) + CostLinearFunction.of(Duration.ofSeconds(0), 1.0) ) .withDebugEnabled(ofDebugEnabled(debug)); } @@ -314,7 +315,7 @@ public void removeTransitWithHigherCostThanBestOnStreetOnlyEnabled() { // Enable filter and remove bus itinerary ItineraryListFilterChain chain = builder .withRemoveTransitWithHigherCostThanBestOnStreetOnly( - RequestFunctions.createLinearFunction(0, 1.0) + CostLinearFunction.of(Duration.ofSeconds(0), 1.0) ) .build(); assertEquals(toStr(List.of(walk)), toStr(chain.filter(List.of(walk, bus)))); diff --git a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilterTest.java b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilterTest.java index 0d086b51cd0..931953e013f 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilterTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilterTest.java @@ -4,11 +4,12 @@ import static org.opentripplanner.model.plan.Itinerary.toStr; import static org.opentripplanner.model.plan.TestItineraryBuilder.newItinerary; +import java.time.Duration; import java.util.List; import org.junit.jupiter.api.Test; import org.opentripplanner.model.plan.Itinerary; import org.opentripplanner.model.plan.PlanTestConstants; -import org.opentripplanner.routing.api.request.framework.RequestFunctions; +import org.opentripplanner.routing.api.request.framework.CostLinearFunction; public class RemoveTransitIfStreetOnlyIsBetterFilterTest implements PlanTestConstants { @@ -21,7 +22,9 @@ public void filterAwayNothingIfNoWalking() { // When: List result = DeletionFlaggerTestHelper.process( List.of(i1, i2), - new RemoveTransitIfStreetOnlyIsBetterFilter(RequestFunctions.createLinearFunction(200, 1.2)) + new RemoveTransitIfStreetOnlyIsBetterFilter( + CostLinearFunction.of(Duration.ofSeconds(200), 1.2) + ) ); // Then: @@ -49,7 +52,9 @@ public void filterAwayLongTravelTimeWithoutWaitTime() { // When: List result = DeletionFlaggerTestHelper.process( List.of(i2, bicycle, walk, i1), - new RemoveTransitIfStreetOnlyIsBetterFilter(RequestFunctions.createLinearFunction(60, 1.2)) + new RemoveTransitIfStreetOnlyIsBetterFilter( + CostLinearFunction.of(Duration.ofSeconds(60), 1.2) + ) ); // Then: diff --git a/src/test/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferencesTest.java b/src/test/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferencesTest.java index 9da4304c18b..f59586b0af9 100644 --- a/src/test/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferencesTest.java +++ b/src/test/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferencesTest.java @@ -28,8 +28,8 @@ class ItineraryFilterPreferencesTest { CostLinearFunction.of(Duration.ofSeconds(4), 5.0), 3.0 ); - private static final DoubleAlgorithmFunction TRANSIT_BEST_STREET_COST_LIMIT = RequestFunctions.createLinearFunction( - 60, + private static final CostLinearFunction TRANSIT_BEST_STREET_COST_LIMIT = CostLinearFunction.of( + Duration.ofSeconds(30), 1.3 ); @@ -110,6 +110,14 @@ void transitGeneralizedCostLimit() { assertEquals(TRANSIT_GENERALIZED_COST_LIMIT, subject.transitGeneralizedCostLimit()); } + @Test + void removeTransitWithHigherCostThanBestOnStreetOnly() { + assertEquals( + TRANSIT_BEST_STREET_COST_LIMIT, + subject.removeTransitWithHigherCostThanBestOnStreetOnly() + ); + } + @Test void testCopyOfEqualsAndHashCode() { // Return same object if no value is set @@ -138,8 +146,8 @@ void testToString() { "minBikeParkingDistance: 2,000.0, " + "nonTransitGeneralizedCostLimit: 4s + 5.0 t, " + "parkAndRideDurationRatio: 0.44, " + - "transitGeneralizedCostLimit: TransitGeneralizedCostFilterParams[costLimitFunction=4s + 5.0 t, intervalRelaxFactor=3.0]" + - "removeTransitWithHigherCostThanBestOnStreetOnly: 1m + 1.3 t" + + "transitGeneralizedCostLimit: TransitGeneralizedCostFilterParams[costLimitFunction=4s + 5.0 t, intervalRelaxFactor=3.0], " + + "removeTransitWithHigherCostThanBestOnStreetOnly: 30s + 1.30 t" + "}", subject.toString() ); From 4d12fd8ec7d67212a15aa7d358f42ad313b00cb1 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Mon, 21 Aug 2023 15:22:53 +0300 Subject: [PATCH 08/36] Split RemoveTransitIfStreetOnlyIsBetterFilter.java into two simpler filters --- .../ItineraryListFilterChainBuilder.java | 19 +++++- .../filterchain/RoutingErrorsAttacher.java | 12 +++- ...moveTransitIfStreetOnlyIsBetterFilter.java | 27 +------- .../RemoveTransitWithMoreWalking.java | 62 +++++++++++++++++++ .../RouteRequestToFilterChainMapper.java | 1 + .../ItineraryFilterPreferences.java | 19 +++++- 6 files changed, 112 insertions(+), 28 deletions(-) create mode 100644 src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalking.java diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java index c3baa491a0d..4394b9430e8 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java @@ -23,6 +23,7 @@ import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveItinerariesWithShortStreetLeg; import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveParkAndRideWithMostlyWalkingFilter; import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveTransitIfStreetOnlyIsBetterFilter; +import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveTransitWithMoreWalking; import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveWalkOnlyFilter; import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.TransitGeneralizedCostFilter; import org.opentripplanner.routing.algorithm.filterchain.filter.DeletionFlaggingFilter; @@ -72,6 +73,7 @@ public class ItineraryListFilterChainBuilder { private Function getMultiModalStation; private boolean removeItinerariesWithSameRoutesAndStops; private double minBikeParkingDistance; + private boolean removeTransitWithMoreWalking = true; @Sandbox private ItineraryListFilter rideHailingFilter; @@ -184,7 +186,7 @@ public ItineraryListFilterChainBuilder withParkAndRideDurationRatio(double value /** * The direct street search(walk, bicycle, car) is not pruning the transit search, so in some * cases we get "silly" transit itineraries that is marginally better on travel-duration compared - * with a on-street-all-the-way itinerary. Use this method to turn this filter on/off. + * with a on-street-all-the-way itinerary. Use this method to turn filter worse enough itineraries. *

* The filter remove all itineraries with a generalized-cost that is higher than the best * on-street-all-the-way itinerary. @@ -199,6 +201,17 @@ public ItineraryListFilterChainBuilder withRemoveTransitWithHigherCostThanBestOn return this; } + /** + * An itinerary which has transit legs and more walking than the plain walk itinerary are silly. + * This filter removes such itineraries. + *

+ * This filter only have an effect, if an on-street-all-the-way(WALK) itinerary exist. + */ + public ItineraryListFilterChainBuilder withRemoveTransitWithMoreWalking(boolean value) { + this.removeTransitWithMoreWalking = value; + return this; + } + /** * This will NOT delete itineraries, but tag them as deleted using the {@link * Itinerary#getSystemNotices()}. @@ -351,6 +364,10 @@ public ItineraryListFilterChain build() { ); } + if (removeTransitWithMoreWalking) { + filters.add(new DeletionFlaggingFilter(new RemoveTransitWithMoreWalking())); + } + // Apply all absolute filters AFTER the groupBy filters. Absolute filters are filters that // remove elements/ based on the given itinerary properties - not considering other // itineraries. This may remove itineraries in the "groupBy" filters that are considered diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/RoutingErrorsAttacher.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/RoutingErrorsAttacher.java index f09d601b04f..357104682d9 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/RoutingErrorsAttacher.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/RoutingErrorsAttacher.java @@ -11,6 +11,7 @@ import org.opentripplanner.model.plan.StreetLeg; import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.OutsideSearchWindowFilter; import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveTransitIfStreetOnlyIsBetterFilter; +import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveTransitWithMoreWalking; import org.opentripplanner.routing.api.response.RoutingError; /** @@ -50,7 +51,16 @@ static List computeErrors( .getSystemNotices() .stream() .anyMatch(notice -> notice.tag.equals(RemoveTransitIfStreetOnlyIsBetterFilter.TAG)); - if (filteredItineraries.stream().allMatch(isOnStreetAllTheWay.or(isWorseThanStreet))) { + Predicate isWorseThanWalking = it -> + it + .getSystemNotices() + .stream() + .anyMatch(notice -> notice.tag.equals(RemoveTransitWithMoreWalking.TAG)); + if ( + filteredItineraries + .stream() + .allMatch(isOnStreetAllTheWay.or(isWorseThanStreet).or(isWorseThanWalking)) + ) { var nonTransitIsWalking = filteredItineraries .stream() .flatMap(Itinerary::getStreetLegs) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java index e32fc9f4d9c..d3783d94695 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java @@ -12,7 +12,7 @@ /** * Filter itineraries based on generalizedCost, compared with a on-street-all-the-way itinerary(if - * it exist). If an itinerary is slower than the best all-the-way-on-street itinerary, then the + * it exist). If an itinerary cost exceeds the limit computed from the best all-the-way-on-street itinerary, then the * transit itinerary is removed. */ public class RemoveTransitIfStreetOnlyIsBetterFilter implements ItineraryDeletionFlagger { @@ -60,33 +60,10 @@ public List flagForRemoval(List itineraries) { .toSeconds(); // Filter away itineraries that have higher cost than limit cost computed above - List filtered = itineraries + return itineraries .stream() .filter(it -> !it.isOnStreetAllTheWay() && it.getGeneralizedCost() >= limit) .collect(Collectors.toList()); - - // Filter the most common silly itinerary case: transit itinerary has more walking than plain walk itinerary - // This never makes sense - OptionalDouble walkDistance = itineraries - .stream() - .filter(Itinerary::isWalkingAllTheWay) - .mapToDouble(Itinerary::distanceMeters) - .min(); - - if (walkDistance.isEmpty()) { - return filtered; - } - final double walkLimit = walkDistance.getAsDouble(); - List filtered2 = itineraries - .stream() - .filter(it -> getWalkDistance(it) > walkLimit) - .collect(Collectors.toList()); - - // remove duplicates - filtered2.removeAll(filtered); - filtered.addAll(filtered2); - - return filtered; } @Override diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalking.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalking.java new file mode 100644 index 00000000000..2e8b2e17b02 --- /dev/null +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalking.java @@ -0,0 +1,62 @@ +package org.opentripplanner.routing.algorithm.filterchain.deletionflagger; + +import java.util.Comparator; +import java.util.List; +import java.util.OptionalDouble; +import java.util.OptionalInt; +import java.util.stream.Collectors; +import org.opentripplanner.framework.model.Cost; +import org.opentripplanner.model.plan.Itinerary; +import org.opentripplanner.model.plan.Leg; +import org.opentripplanner.routing.api.request.framework.CostLinearFunction; + +/** + * Filter itineraries which contain more walking than a pure walk itinerary + */ +public class RemoveTransitWithMoreWalking implements ItineraryDeletionFlagger { + + /** + * Required for {@link org.opentripplanner.routing.algorithm.filterchain.ItineraryListFilterChain}, + * to know which filters removed + */ + public static final String TAG = "transit-vs-plain-walk-filter"; + + @Override + public String name() { + return TAG; + } + + private double getWalkDistance(Itinerary it) { + return it + .getStreetLegs() + .filter(l -> l.isWalkingLeg()) + .mapToDouble(Leg::getDistanceMeters) + .sum(); + } + + @Override + public List flagForRemoval(List itineraries) { + // Filter the most common silly itinerary case: transit itinerary has more walking than plain walk itinerary + // This never makes sense + OptionalDouble walkDistance = itineraries + .stream() + .filter(Itinerary::isWalkingAllTheWay) + .mapToDouble(Itinerary::distanceMeters) + .min(); + + if (walkDistance.isEmpty()) { + return List.of(); + } + + final double walkLimit = walkDistance.getAsDouble(); + return itineraries + .stream() + .filter(it -> !it.isOnStreetAllTheWay() && getWalkDistance(it) > walkLimit) + .collect(Collectors.toList()); + } + + @Override + public boolean skipAlreadyFlaggedItineraries() { + return false; + } +} diff --git a/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java b/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java index 4bf14a00ad4..c5af34f573a 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java @@ -85,6 +85,7 @@ public static ItineraryListFilterChain createFilterChain( .withLatestDepartureTimeLimit(filterOnLatestDepartureTime) .withMaxLimitReachedSubscriber(maxLimitReachedSubscriber) .withRemoveWalkAllTheWayResults(removeWalkAllTheWayResults) + .withRemoveTransitWithMoreWalking(true) .withDebugEnabled(params.debug()); if (!context.rideHailingServices().isEmpty()) { diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java index 04b517b09fd..569cb21e5f5 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java @@ -31,6 +31,7 @@ public final class ItineraryFilterPreferences { private final boolean removeItinerariesWithSameRoutesAndStops; private final TransitGeneralizedCostFilterParams transitGeneralizedCostLimit; private final CostLinearFunction removeTransitWithHigherCostThanBestOnStreetOnly; + private final boolean removeTransitWithMoreWalking; private ItineraryFilterPreferences() { this.accessibilityScore = false; @@ -51,6 +52,7 @@ private ItineraryFilterPreferences() { ); this.removeTransitWithHigherCostThanBestOnStreetOnly = CostLinearFunction.of(Duration.ofMinutes(1), 1.3); + this.removeTransitWithMoreWalking = false; } private ItineraryFilterPreferences(Builder builder) { @@ -71,6 +73,7 @@ private ItineraryFilterPreferences(Builder builder) { this.transitGeneralizedCostLimit = Objects.requireNonNull(builder.transitGeneralizedCostLimit); this.removeTransitWithHigherCostThanBestOnStreetOnly = Objects.requireNonNull(builder.removeTransitWithHigherCostThanBestOnStreetOnly); + this.removeTransitWithMoreWalking = builder.removeTransitWithMoreWalking; } public static Builder of() { @@ -133,6 +136,10 @@ public CostLinearFunction removeTransitWithHigherCostThanBestOnStreetOnly() { return removeTransitWithHigherCostThanBestOnStreetOnly; } + public boolean removeTransitWithMoreWalking() { + return removeTransitWithMoreWalking; + } + @Override public String toString() { return ToStringBuilder @@ -180,6 +187,7 @@ public String toString() { "removeItinerariesWithSameRoutesAndStops", removeItinerariesWithSameRoutesAndStops ) + .addBoolIfTrue("removeTransitWithMoreWalking", removeTransitWithMoreWalking) .toString(); } @@ -192,6 +200,7 @@ public boolean equals(Object o) { accessibilityScore == that.accessibilityScore && Double.compare(that.bikeRentalDistanceRatio, bikeRentalDistanceRatio) == 0 && debug == that.debug && + removeTransitWithMoreWalking == that.removeTransitWithMoreWalking && filterItinerariesWithSameFirstOrLastTrip == that.filterItinerariesWithSameFirstOrLastTrip && Double.compare( that.groupedOtherThanSameLegsMaxCostMultiplier, @@ -227,7 +236,8 @@ public int hashCode() { parkAndRideDurationRatio, removeItinerariesWithSameRoutesAndStops, transitGeneralizedCostLimit, - removeTransitWithHigherCostThanBestOnStreetOnly + removeTransitWithHigherCostThanBestOnStreetOnly, + removeTransitWithMoreWalking ); } @@ -247,6 +257,7 @@ public static class Builder { private boolean removeItinerariesWithSameRoutesAndStops; private TransitGeneralizedCostFilterParams transitGeneralizedCostLimit; private CostLinearFunction removeTransitWithHigherCostThanBestOnStreetOnly; + private boolean removeTransitWithMoreWalking; public ItineraryFilterPreferences original() { return original; @@ -330,6 +341,11 @@ public Builder withRemoveTransitWithHigherCostThanBestOnStreetOnly( return this; } + public Builder withRemoveTransitWithMoreWalking(boolean removeTransitWithMoreWalking) { + this.removeTransitWithMoreWalking = removeTransitWithMoreWalking; + return this; + } + public Builder(ItineraryFilterPreferences original) { this.original = original; this.accessibilityScore = original.accessibilityScore; @@ -349,6 +365,7 @@ public Builder(ItineraryFilterPreferences original) { this.transitGeneralizedCostLimit = original.transitGeneralizedCostLimit; this.removeTransitWithHigherCostThanBestOnStreetOnly = original.removeTransitWithHigherCostThanBestOnStreetOnly; + this.removeTransitWithMoreWalking = original.removeTransitWithMoreWalking; } public Builder apply(Consumer body) { From 94a738d3a4058ea1e6cb6b0c15a28683e3aef742 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Tue, 22 Aug 2023 10:03:29 +0300 Subject: [PATCH 09/36] Add test for the new itinerary filter --- .../RemoveTransitWithMoreWalkingTest.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalkingTest.java diff --git a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalkingTest.java b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalkingTest.java new file mode 100644 index 00000000000..3b7404fc6e7 --- /dev/null +++ b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalkingTest.java @@ -0,0 +1,52 @@ +package org.opentripplanner.routing.algorithm.filterchain.deletionflagger; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.opentripplanner.model.plan.Itinerary.toStr; +import static org.opentripplanner.model.plan.TestItineraryBuilder.newItinerary; + +import java.time.Duration; +import java.util.List; +import org.junit.jupiter.api.Test; +import org.opentripplanner.model.plan.Itinerary; +import org.opentripplanner.model.plan.PlanTestConstants; + +public class RemoveTransitWithMoreWalkingTest implements PlanTestConstants { + + @Test + public void filterAwayNothingIfNoWalking() { + // Given: + Itinerary i1 = newItinerary(A).bus(21, 6, 7, E).build(); + Itinerary i2 = newItinerary(A).rail(110, 6, 9, E).build(); + + // When: + List result = DeletionFlaggerTestHelper.process( + List.of(i1, i2), + new RemoveTransitWithMoreWalking() + ); + + // Then: + assertEquals(toStr(List.of(i1, i2)), toStr(result)); + } + + @Test + public void filterAwayLongTravelTimeWithoutWaitTime() { + // a walk itinerary + Itinerary walk = newItinerary(A, 6).walk(D2m, E).build(); + + // a bicycle itinerary will not be filtered + Itinerary bicycle = newItinerary(A).bicycle(6, 9, E).build(); + + // transit which has more walking as plain walk should be dropped + Itinerary i1 = newItinerary(A, 6).walk(D3m, D).bus(1, 9, 10, E).build(); + + // transit which has less walking than plain walk should be kept + Itinerary i2 = newItinerary(A, 6).walk(D1m, B).bus(2, 7, 10, E).build(); + + List result = DeletionFlaggerTestHelper.process( + List.of(i1, i2, bicycle, walk), + new RemoveTransitWithMoreWalking() + ); + + assertEquals(toStr(List.of(i2, bicycle, walk)), toStr(result)); + } +} From acc2bb988131cf53004f91a2051eb4ed9f7ebc5f Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Tue, 22 Aug 2023 10:32:00 +0300 Subject: [PATCH 10/36] Update test name --- .../deletionflagger/RemoveTransitWithMoreWalkingTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalkingTest.java b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalkingTest.java index 3b7404fc6e7..6d192787eeb 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalkingTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalkingTest.java @@ -29,7 +29,7 @@ public void filterAwayNothingIfNoWalking() { } @Test - public void filterAwayLongTravelTimeWithoutWaitTime() { + public void filterAwayTransitWithLongerWalk() { // a walk itinerary Itinerary walk = newItinerary(A, 6).walk(D2m, E).build(); From fc4f3cefe0fd7be319062eb6d4bdaf65e12c226e Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Tue, 22 Aug 2023 12:14:08 +0300 Subject: [PATCH 11/36] Remove unused function --- .../RemoveTransitIfStreetOnlyIsBetterFilter.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java index d3783d94695..60c6f8d6225 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java @@ -34,14 +34,6 @@ public String name() { return TAG; } - private double getWalkDistance(Itinerary it) { - return it - .getStreetLegs() - .filter(l -> l.isWalkingLeg()) - .mapToDouble(Leg::getDistanceMeters) - .sum(); - } - @Override public List flagForRemoval(List itineraries) { // Find the best walk-all-the-way option From e34e4e95e40ac124454abe9392045c5232c3b929 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Tue, 22 Aug 2023 12:14:32 +0300 Subject: [PATCH 12/36] Use cost, not distance --- .../RemoveTransitWithMoreWalking.java | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalking.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalking.java index 2e8b2e17b02..1438cfa14dc 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalking.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalking.java @@ -26,32 +26,26 @@ public String name() { return TAG; } - private double getWalkDistance(Itinerary it) { - return it - .getStreetLegs() - .filter(l -> l.isWalkingLeg()) - .mapToDouble(Leg::getDistanceMeters) - .sum(); - } - @Override public List flagForRemoval(List itineraries) { // Filter the most common silly itinerary case: transit itinerary has more walking than plain walk itinerary // This never makes sense - OptionalDouble walkDistance = itineraries + + OptionalInt minWalkCost = itineraries .stream() .filter(Itinerary::isWalkingAllTheWay) - .mapToDouble(Itinerary::distanceMeters) + .mapToInt(Itinerary::getGeneralizedCost) .min(); - if (walkDistance.isEmpty()) { + if (minWalkCost.isEmpty()) { return List.of(); } - final double walkLimit = walkDistance.getAsDouble(); + var limit = minWalkCost.getAsInt(); + return itineraries .stream() - .filter(it -> !it.isOnStreetAllTheWay() && getWalkDistance(it) > walkLimit) + .filter(it -> !it.isOnStreetAllTheWay() && it.getGeneralizedCost() >= limit) .collect(Collectors.toList()); } From f2e021fbecaf5ad221484512959c44ee2bbf15f3 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Tue, 22 Aug 2023 12:14:59 +0300 Subject: [PATCH 13/36] Update test --- .../algorithm/filterchain/ItineraryListFilterChainTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java index 065695b09a2..d9bb3f7dc80 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java @@ -306,6 +306,7 @@ public void removeTransitWithHigherCostThanBestOnStreetOnlyDisabled() { // Allow non-optimal bus itinerary pass through ItineraryListFilterChain chain = builder .withRemoveTransitWithHigherCostThanBestOnStreetOnly(null) + .withRemoveTransitWithMoreWalking(false) .build(); assertEquals(toStr(List.of(walk, bus)), toStr(chain.filter(List.of(walk, bus)))); } From 6fedd5dc72c914e958a44cfe785488b83d83aeff Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 13 Sep 2023 08:10:55 +0300 Subject: [PATCH 14/36] Rename transit vs walking filter --- .../RemoveTransitIfWalkingIsBetter.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetter.java diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetter.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetter.java new file mode 100644 index 00000000000..0199f0e3b66 --- /dev/null +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetter.java @@ -0,0 +1,56 @@ +package org.opentripplanner.routing.algorithm.filterchain.deletionflagger; + +import java.util.Comparator; +import java.util.List; +import java.util.OptionalDouble; +import java.util.OptionalInt; +import java.util.stream.Collectors; +import org.opentripplanner.framework.model.Cost; +import org.opentripplanner.model.plan.Itinerary; +import org.opentripplanner.model.plan.Leg; +import org.opentripplanner.routing.api.request.framework.CostLinearFunction; + +/** + * Filter itineraries which contain more walking than a pure walk itinerary + */ +public class RemoveTransitIfWalkingIsBetterFilter implements ItineraryDeletionFlagger { + + /** + * Required for {@link org.opentripplanner.routing.algorithm.filterchain.ItineraryListFilterChain}, + * to know which filters removed + */ + public static final String TAG = "transit-vs-walk-filter"; + + @Override + public String name() { + return TAG; + } + + @Override + public List flagForRemoval(List itineraries) { + // Filter the most common silly itinerary case: transit itinerary has more walking than plain walk itinerary + // This never makes sense + + OptionalInt minWalkCost = itineraries + .stream() + .filter(Itinerary::isWalkingAllTheWay) + .mapToInt(Itinerary::getGeneralizedCost) + .min(); + + if (minWalkCost.isEmpty()) { + return List.of(); + } + + var limit = minWalkCost.getAsInt(); + + return itineraries + .stream() + .filter(it -> !it.isOnStreetAllTheWay() && it.getGeneralizedCost() >= limit) + .collect(Collectors.toList()); + } + + @Override + public boolean skipAlreadyFlaggedItineraries() { + return false; + } +} From 07683a99b714cb76a995e4df2101a24ceca2ac33 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 13 Sep 2023 08:11:59 +0300 Subject: [PATCH 15/36] Update documentation to reflect changes in the filter --- .../RemoveTransitIfStreetOnlyIsBetterFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java index 60c6f8d6225..08307c16ade 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfStreetOnlyIsBetterFilter.java @@ -36,7 +36,7 @@ public String name() { @Override public List flagForRemoval(List itineraries) { - // Find the best walk-all-the-way option + // Find the best street-all-the-way option OptionalInt minStreetCost = itineraries .stream() .filter(Itinerary::isOnStreetAllTheWay) From 4985bd64c9ebece2a071a35915b001731f1a6533 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 13 Sep 2023 08:15:07 +0300 Subject: [PATCH 16/36] update docs Co-authored-by: Thomas Gran --- .../algorithm/filterchain/ItineraryListFilterChainBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java index 4394b9430e8..093d071f104 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java @@ -205,7 +205,7 @@ public ItineraryListFilterChainBuilder withRemoveTransitWithHigherCostThanBestOn * An itinerary which has transit legs and more walking than the plain walk itinerary are silly. * This filter removes such itineraries. *

- * This filter only have an effect, if an on-street-all-the-way(WALK) itinerary exist. + * This filter only have an effect, if an walk-all-the-way itinerary exist. */ public ItineraryListFilterChainBuilder withRemoveTransitWithMoreWalking(boolean value) { this.removeTransitWithMoreWalking = value; From c42861c86bdb55ec63ec6b1f683fb16776aa2c6c Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 13 Sep 2023 08:15:27 +0300 Subject: [PATCH 17/36] Use new class name Co-authored-by: Thomas Gran --- .../algorithm/filterchain/ItineraryListFilterChainBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java index 093d071f104..2742879742d 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java @@ -207,7 +207,7 @@ public ItineraryListFilterChainBuilder withRemoveTransitWithHigherCostThanBestOn *

* This filter only have an effect, if an walk-all-the-way itinerary exist. */ - public ItineraryListFilterChainBuilder withRemoveTransitWithMoreWalking(boolean value) { + public ItineraryListFilterChainBuilder withRemoveTransitIfWalkingIsBetter(boolean value) { this.removeTransitWithMoreWalking = value; return this; } From db41b92473439899d49c859c59789f9ce1e07824 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 13 Sep 2023 08:15:42 +0300 Subject: [PATCH 18/36] Use new class name Co-authored-by: Thomas Gran --- .../algorithm/filterchain/ItineraryListFilterChainBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java index 2742879742d..d48aac5e5d0 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java @@ -208,7 +208,7 @@ public ItineraryListFilterChainBuilder withRemoveTransitWithHigherCostThanBestOn * This filter only have an effect, if an walk-all-the-way itinerary exist. */ public ItineraryListFilterChainBuilder withRemoveTransitIfWalkingIsBetter(boolean value) { - this.removeTransitWithMoreWalking = value; + this.removeTransitIfWalkingIsBetter = value; return this; } From 056f8f22db2665443921c0374f7135ff25b55e60 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 13 Sep 2023 08:16:38 +0300 Subject: [PATCH 19/36] Remove old class --- .../RemoveTransitWithMoreWalking.java | 56 ------------------- 1 file changed, 56 deletions(-) delete mode 100644 src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalking.java diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalking.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalking.java deleted file mode 100644 index 1438cfa14dc..00000000000 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalking.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.opentripplanner.routing.algorithm.filterchain.deletionflagger; - -import java.util.Comparator; -import java.util.List; -import java.util.OptionalDouble; -import java.util.OptionalInt; -import java.util.stream.Collectors; -import org.opentripplanner.framework.model.Cost; -import org.opentripplanner.model.plan.Itinerary; -import org.opentripplanner.model.plan.Leg; -import org.opentripplanner.routing.api.request.framework.CostLinearFunction; - -/** - * Filter itineraries which contain more walking than a pure walk itinerary - */ -public class RemoveTransitWithMoreWalking implements ItineraryDeletionFlagger { - - /** - * Required for {@link org.opentripplanner.routing.algorithm.filterchain.ItineraryListFilterChain}, - * to know which filters removed - */ - public static final String TAG = "transit-vs-plain-walk-filter"; - - @Override - public String name() { - return TAG; - } - - @Override - public List flagForRemoval(List itineraries) { - // Filter the most common silly itinerary case: transit itinerary has more walking than plain walk itinerary - // This never makes sense - - OptionalInt minWalkCost = itineraries - .stream() - .filter(Itinerary::isWalkingAllTheWay) - .mapToInt(Itinerary::getGeneralizedCost) - .min(); - - if (minWalkCost.isEmpty()) { - return List.of(); - } - - var limit = minWalkCost.getAsInt(); - - return itineraries - .stream() - .filter(it -> !it.isOnStreetAllTheWay() && it.getGeneralizedCost() >= limit) - .collect(Collectors.toList()); - } - - @Override - public boolean skipAlreadyFlaggedItineraries() { - return false; - } -} From ca179775ec41c52203bf27138edb9fb6e17f3115 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 13 Sep 2023 08:24:34 +0300 Subject: [PATCH 20/36] Rename references to changed filter class name --- .../filterchain/ItineraryListFilterChainBuilder.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java index d48aac5e5d0..d2c1073dedb 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java @@ -23,7 +23,7 @@ import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveItinerariesWithShortStreetLeg; import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveParkAndRideWithMostlyWalkingFilter; import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveTransitIfStreetOnlyIsBetterFilter; -import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveTransitWithMoreWalking; +import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveTransitIfWalkingIsBetterFilter; import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveWalkOnlyFilter; import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.TransitGeneralizedCostFilter; import org.opentripplanner.routing.algorithm.filterchain.filter.DeletionFlaggingFilter; @@ -73,7 +73,7 @@ public class ItineraryListFilterChainBuilder { private Function getMultiModalStation; private boolean removeItinerariesWithSameRoutesAndStops; private double minBikeParkingDistance; - private boolean removeTransitWithMoreWalking = true; + private boolean removeTransitIfWalkingIsBetter = true; @Sandbox private ItineraryListFilter rideHailingFilter; @@ -364,8 +364,8 @@ public ItineraryListFilterChain build() { ); } - if (removeTransitWithMoreWalking) { - filters.add(new DeletionFlaggingFilter(new RemoveTransitWithMoreWalking())); + if (removeTransitIfWalkingIsBetter) { + filters.add(new DeletionFlaggingFilter(new RemoveTransitIfWalkingIsBetterFilter())); } // Apply all absolute filters AFTER the groupBy filters. Absolute filters are filters that From 10949a0e0132ac9c6c88508c0a50903d47336ed4 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 13 Sep 2023 08:25:56 +0300 Subject: [PATCH 21/36] Move street vs transit filters to the block of absolute filters --- .../ItineraryListFilterChainBuilder.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java index d2c1073dedb..f38d0f6da36 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java @@ -353,21 +353,6 @@ public ItineraryListFilterChain build() { ); } - // Filter transit itineraries by comparing against non-transit using generalized-cost - if (removeTransitWithHigherCostThanBestOnStreetOnly != null) { - filters.add( - new DeletionFlaggingFilter( - new RemoveTransitIfStreetOnlyIsBetterFilter( - removeTransitWithHigherCostThanBestOnStreetOnly - ) - ) - ); - } - - if (removeTransitIfWalkingIsBetter) { - filters.add(new DeletionFlaggingFilter(new RemoveTransitIfWalkingIsBetterFilter())); - } - // Apply all absolute filters AFTER the groupBy filters. Absolute filters are filters that // remove elements/ based on the given itinerary properties - not considering other // itineraries. This may remove itineraries in the "groupBy" filters that are considered @@ -378,6 +363,21 @@ public ItineraryListFilterChain build() { // is worse). B is removed by the {@link LatestDepartureTimeFilter} below. This is exactly // what we want, since both itineraries are none optimal. { + // Filter transit itineraries by comparing against non-transit using generalized-cost + if (removeTransitWithHigherCostThanBestOnStreetOnly != null) { + filters.add( + new DeletionFlaggingFilter( + new RemoveTransitIfStreetOnlyIsBetterFilter( + removeTransitWithHigherCostThanBestOnStreetOnly + ) + ) + ); + } + + if (removeTransitIfWalkingIsBetter) { + filters.add(new DeletionFlaggingFilter(new RemoveTransitIfWalkingIsBetterFilter())); + } + if (removeWalkAllTheWayResults) { filters.add(new DeletionFlaggingFilter(new RemoveWalkOnlyFilter())); } From 089a4a7091bbe0a444f957bb143dd8bbdfb937f3 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 13 Sep 2023 08:46:38 +0300 Subject: [PATCH 22/36] Rename remaining references to old filter class name and rename the tests --- .../filterchain/ItineraryListFilterChainBuilder.java | 2 +- .../algorithm/filterchain/RoutingErrorsAttacher.java | 4 ++-- ...etter.java => RemoveTransitIfWalkingIsBetterFilter.java} | 0 .../algorithm/mapping/RouteRequestToFilterChainMapper.java | 2 +- .../algorithm/filterchain/ItineraryListFilterChainTest.java | 2 +- ...ingTest.java => RemoveTransitIfWalkingIsBetterTest.java} | 6 +++--- 6 files changed, 8 insertions(+), 8 deletions(-) rename src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/{RemoveTransitIfWalkingIsBetter.java => RemoveTransitIfWalkingIsBetterFilter.java} (100%) rename src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/{RemoveTransitWithMoreWalkingTest.java => RemoveTransitIfWalkingIsBetterTest.java} (89%) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java index f38d0f6da36..e81e82664ed 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java @@ -363,7 +363,7 @@ public ItineraryListFilterChain build() { // is worse). B is removed by the {@link LatestDepartureTimeFilter} below. This is exactly // what we want, since both itineraries are none optimal. { - // Filter transit itineraries by comparing against non-transit using generalized-cost + // Filter transit itineraries by comparing against non-transit using generalized-cost if (removeTransitWithHigherCostThanBestOnStreetOnly != null) { filters.add( new DeletionFlaggingFilter( diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/RoutingErrorsAttacher.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/RoutingErrorsAttacher.java index 357104682d9..c7433f93a22 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/RoutingErrorsAttacher.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/RoutingErrorsAttacher.java @@ -11,7 +11,7 @@ import org.opentripplanner.model.plan.StreetLeg; import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.OutsideSearchWindowFilter; import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveTransitIfStreetOnlyIsBetterFilter; -import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveTransitWithMoreWalking; +import org.opentripplanner.routing.algorithm.filterchain.deletionflagger.RemoveTransitIfWalkingIsBetterFilter; import org.opentripplanner.routing.api.response.RoutingError; /** @@ -55,7 +55,7 @@ static List computeErrors( it .getSystemNotices() .stream() - .anyMatch(notice -> notice.tag.equals(RemoveTransitWithMoreWalking.TAG)); + .anyMatch(notice -> notice.tag.equals(RemoveTransitIfWalkingIsBetterFilter.TAG)); if ( filteredItineraries .stream() diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetter.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java similarity index 100% rename from src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetter.java rename to src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java diff --git a/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java b/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java index c5af34f573a..e8a3f226d8a 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/mapping/RouteRequestToFilterChainMapper.java @@ -85,7 +85,7 @@ public static ItineraryListFilterChain createFilterChain( .withLatestDepartureTimeLimit(filterOnLatestDepartureTime) .withMaxLimitReachedSubscriber(maxLimitReachedSubscriber) .withRemoveWalkAllTheWayResults(removeWalkAllTheWayResults) - .withRemoveTransitWithMoreWalking(true) + .withRemoveTransitIfWalkingIsBetter(true) .withDebugEnabled(params.debug()); if (!context.rideHailingServices().isEmpty()) { diff --git a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java index d9bb3f7dc80..2bbb5a25e3b 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainTest.java @@ -306,7 +306,7 @@ public void removeTransitWithHigherCostThanBestOnStreetOnlyDisabled() { // Allow non-optimal bus itinerary pass through ItineraryListFilterChain chain = builder .withRemoveTransitWithHigherCostThanBestOnStreetOnly(null) - .withRemoveTransitWithMoreWalking(false) + .withRemoveTransitIfWalkingIsBetter(false) .build(); assertEquals(toStr(List.of(walk, bus)), toStr(chain.filter(List.of(walk, bus)))); } diff --git a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalkingTest.java b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterTest.java similarity index 89% rename from src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalkingTest.java rename to src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterTest.java index 6d192787eeb..b68ac9c46a2 100644 --- a/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitWithMoreWalkingTest.java +++ b/src/test/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterTest.java @@ -10,7 +10,7 @@ import org.opentripplanner.model.plan.Itinerary; import org.opentripplanner.model.plan.PlanTestConstants; -public class RemoveTransitWithMoreWalkingTest implements PlanTestConstants { +public class RemoveTransitIfWalkingIsBetterTest implements PlanTestConstants { @Test public void filterAwayNothingIfNoWalking() { @@ -21,7 +21,7 @@ public void filterAwayNothingIfNoWalking() { // When: List result = DeletionFlaggerTestHelper.process( List.of(i1, i2), - new RemoveTransitWithMoreWalking() + new RemoveTransitIfWalkingIsBetterFilter() ); // Then: @@ -44,7 +44,7 @@ public void filterAwayTransitWithLongerWalk() { List result = DeletionFlaggerTestHelper.process( List.of(i1, i2, bicycle, walk), - new RemoveTransitWithMoreWalking() + new RemoveTransitIfWalkingIsBetterFilter() ); assertEquals(toStr(List.of(i2, bicycle, walk)), toStr(result)); From 43e00c9d2dbef8edc8e447d4dc1e7f05ee562866 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 13 Sep 2023 09:17:22 +0300 Subject: [PATCH 23/36] Update docs --- .../config/routerequest/ItineraryFiltersConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java index 27e488ca894..418d46f9cf4 100644 --- a/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java +++ b/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java @@ -168,8 +168,8 @@ public static void mapItineraryFilterParams( generalized-cost value is used as input to the function. The function is used to calculate a *max-limit*. The max-limit is then used to filter *transit* itineraries by *generalized-cost*. Itineraries with a cost higher than the max-limit are dropped from the result - set. Walking is handled with a different logic: if a transit itinerary has more walking than - a plain walk itinerary, it will be removed even if the cost limit function would keep it. +set. Walking is handled with a different logic: if a transit itinerary has higher cost than +a plain walk itinerary, it will be removed even if the cost limit function would keep it. """ ) .asCostLinearFunction(dft.removeTransitWithHigherCostThanBestOnStreetOnly()) From 59f114b56b1e50785d193ae98fa4aab16e9f1a13 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Wed, 13 Sep 2023 09:22:17 +0300 Subject: [PATCH 24/36] Update RouteRequest doc --- docs/RouteRequest.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/RouteRequest.md b/docs/RouteRequest.md index db6324d3e7c..e9b4da3eacf 100644 --- a/docs/RouteRequest.md +++ b/docs/RouteRequest.md @@ -641,8 +641,8 @@ without transit legs are considered when calculating the minimum cost. The small generalized-cost value is used as input to the function. The function is used to calculate a *max-limit*. The max-limit is then used to filter *transit* itineraries by *generalized-cost*. Itineraries with a cost higher than the max-limit are dropped from the result - set. Walking is handled with a different logic: if a transit itinerary has more walking than - a plain walk itinerary, it will be removed even if the cost limit function would keep it. +set. Walking is handled with a different logic: if a transit itinerary has higher cost than +a plain walk itinerary, it will be removed even if the cost limit function would keep it.

transitGeneralizedCostLimit

From 2aa2120c9522717503df40073ae7957fbe42e3a1 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 14 Sep 2023 15:02:40 +0300 Subject: [PATCH 25/36] Update src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java Co-authored-by: Thomas Gran --- .../filterchain/ItineraryListFilterChainBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java index e81e82664ed..d31f33ef282 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java @@ -202,8 +202,8 @@ public ItineraryListFilterChainBuilder withRemoveTransitWithHigherCostThanBestOn } /** - * An itinerary which has transit legs and more walking than the plain walk itinerary are silly. - * This filter removes such itineraries. + * A transit itinerary with higher generalized-cost than a walk-only itinerary is silly. This filter removes such + * itineraries. *

* This filter only have an effect, if an walk-all-the-way itinerary exist. */ From 775cd16e3a6f2476b42eef53f00f782be21d5c19 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 14 Sep 2023 15:03:19 +0300 Subject: [PATCH 26/36] Update src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java Co-authored-by: Thomas Gran --- .../deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java index 0199f0e3b66..376e5d62af8 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java @@ -11,7 +11,7 @@ import org.opentripplanner.routing.api.request.framework.CostLinearFunction; /** - * Filter itineraries which contain more walking than a pure walk itinerary + * Filter itineraries which have a higher generalized-cost than a pure walk itinerary. */ public class RemoveTransitIfWalkingIsBetterFilter implements ItineraryDeletionFlagger { From 38ac2bdadcfd9884d6b0386827a2b55974ac219d Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 14 Sep 2023 15:05:17 +0300 Subject: [PATCH 27/36] Update src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java Co-authored-by: Thomas Gran --- .../api/request/preference/ItineraryFilterPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java index 569cb21e5f5..01c8b5c91ca 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java @@ -31,7 +31,7 @@ public final class ItineraryFilterPreferences { private final boolean removeItinerariesWithSameRoutesAndStops; private final TransitGeneralizedCostFilterParams transitGeneralizedCostLimit; private final CostLinearFunction removeTransitWithHigherCostThanBestOnStreetOnly; - private final boolean removeTransitWithMoreWalking; + private final boolean removeTransitIfWalkingIsBetter; private ItineraryFilterPreferences() { this.accessibilityScore = false; From 79c907ed00b3cc4870ea3885b637025a52736767 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 14 Sep 2023 15:05:26 +0300 Subject: [PATCH 28/36] Update src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java Co-authored-by: Thomas Gran --- .../api/request/preference/ItineraryFilterPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java index 01c8b5c91ca..f446e8c00d5 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java @@ -52,7 +52,7 @@ private ItineraryFilterPreferences() { ); this.removeTransitWithHigherCostThanBestOnStreetOnly = CostLinearFunction.of(Duration.ofMinutes(1), 1.3); - this.removeTransitWithMoreWalking = false; + this.removeTransitIfWalkingIsBetter = true; } private ItineraryFilterPreferences(Builder builder) { From 2bfd928f45c518f510631d7d5d846e523c95de38 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 14 Sep 2023 15:06:10 +0300 Subject: [PATCH 29/36] Update src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java Co-authored-by: Thomas Gran --- .../api/request/preference/ItineraryFilterPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java index f446e8c00d5..db9cb90b0e7 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java @@ -200,7 +200,7 @@ public boolean equals(Object o) { accessibilityScore == that.accessibilityScore && Double.compare(that.bikeRentalDistanceRatio, bikeRentalDistanceRatio) == 0 && debug == that.debug && - removeTransitWithMoreWalking == that.removeTransitWithMoreWalking && + removeTransitIfWalkingIsBetter == that.removeTransitIfWalkingIsBetter && filterItinerariesWithSameFirstOrLastTrip == that.filterItinerariesWithSameFirstOrLastTrip && Double.compare( that.groupedOtherThanSameLegsMaxCostMultiplier, From a2d109f1edf67cc18d9016976b0a2944312bf43b Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 14 Sep 2023 15:06:18 +0300 Subject: [PATCH 30/36] Update src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java Co-authored-by: Thomas Gran --- .../api/request/preference/ItineraryFilterPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java index db9cb90b0e7..ffee46f2614 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java @@ -257,7 +257,7 @@ public static class Builder { private boolean removeItinerariesWithSameRoutesAndStops; private TransitGeneralizedCostFilterParams transitGeneralizedCostLimit; private CostLinearFunction removeTransitWithHigherCostThanBestOnStreetOnly; - private boolean removeTransitWithMoreWalking; + private boolean removeTransitIfWalkingIsBetter; public ItineraryFilterPreferences original() { return original; From 5a3b13fc04e9e357969c0d7c8c676ea0c2081cc0 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 14 Sep 2023 15:06:30 +0300 Subject: [PATCH 31/36] Update src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java Co-authored-by: Thomas Gran --- .../api/request/preference/ItineraryFilterPreferences.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java index ffee46f2614..f731f372855 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java @@ -365,7 +365,7 @@ public Builder(ItineraryFilterPreferences original) { this.transitGeneralizedCostLimit = original.transitGeneralizedCostLimit; this.removeTransitWithHigherCostThanBestOnStreetOnly = original.removeTransitWithHigherCostThanBestOnStreetOnly; - this.removeTransitWithMoreWalking = original.removeTransitWithMoreWalking; + this.removeTransitIfWalkingIsBetter = original.removeTransitIfWalkingIsBetter; } public Builder apply(Consumer body) { From 4bab50a7ed87161c26ce02c5b15f86021e56c4dd Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 14 Sep 2023 15:07:05 +0300 Subject: [PATCH 32/36] Update src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java Co-authored-by: Thomas Gran --- .../api/request/preference/ItineraryFilterPreferences.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java index f731f372855..2061e6891ce 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java @@ -341,8 +341,8 @@ public Builder withRemoveTransitWithHigherCostThanBestOnStreetOnly( return this; } - public Builder withRemoveTransitWithMoreWalking(boolean removeTransitWithMoreWalking) { - this.removeTransitWithMoreWalking = removeTransitWithMoreWalking; + public Builder withRemoveTransitIfWalkingIsBetter(boolean removeTransitIfWalkingIsBetter) { + this.removeTransitIfWalkingIsBetter = removeTransitIfWalkingIsBetter; return this; } From 061c0bb26e71bf1b26a181e0cbddf83ca309b1e2 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 14 Sep 2023 15:07:45 +0300 Subject: [PATCH 33/36] Update src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java Co-authored-by: Thomas Gran --- .../standalone/config/routerequest/ItineraryFiltersConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java b/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java index 418d46f9cf4..82e2c0839f9 100644 --- a/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java +++ b/src/main/java/org/opentripplanner/standalone/config/routerequest/ItineraryFiltersConfig.java @@ -159,7 +159,7 @@ public static void mapItineraryFilterParams( .of("removeTransitWithHigherCostThanBestOnStreetOnly") .since(V2_4) .summary( - "Limit function for generalized-cost computed from non-transit itineries for transit itineraries." + "Limit function for generalized-cost computed from street-only itineries applied to transit itineraries." ) .description( """ From 46f5291455141165c7b8854e9f15611e021db686 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 14 Sep 2023 15:22:13 +0300 Subject: [PATCH 34/36] Fix naming issues pointed out in review --- docs/RouteRequest.md | 4 ++-- .../ItineraryListFilterChainBuilder.java | 4 ++-- .../preference/ItineraryFilterPreferences.java | 14 +++++++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/RouteRequest.md b/docs/RouteRequest.md index e9b4da3eacf..bff42168c1e 100644 --- a/docs/RouteRequest.md +++ b/docs/RouteRequest.md @@ -95,7 +95,7 @@ and in the [transferRequests in build-config.json](BuildConfiguration.md#transfe |    [nonTransitGeneralizedCostLimit](#rd_if_nonTransitGeneralizedCostLimit) | `cost-linear-function` | The function define a max-limit for generalized-cost for non-transit itineraries. | *Optional* | `"1h + 2.0 t"` | 2.1 | |    [parkAndRideDurationRatio](#rd_if_parkAndRideDurationRatio) | `double` | Filter P+R routes that consist of driving and walking by the minimum fraction of the driving using of _time_. | *Optional* | `0.0` | 2.1 | |    [removeItinerariesWithSameRoutesAndStops](#rd_if_removeItinerariesWithSameRoutesAndStops) | `boolean` | Set to true if you want to list only the first itinerary which goes through the same stops and routes. | *Optional* | `false` | 2.2 | -|    [removeTransitWithHigherCostThanBestOnStreetOnly](#rd_if_removeTransitWithHigherCostThanBestOnStreetOnly) | `cost-linear-function` | Limit function for generalized-cost computed from non-transit itineries for transit itineraries. | *Optional* | `"1m + 1.30 t"` | 2.4 | +|    [removeTransitWithHigherCostThanBestOnStreetOnly](#rd_if_removeTransitWithHigherCostThanBestOnStreetOnly) | `cost-linear-function` | Limit function for generalized-cost computed from street-only itineries applied to transit itineraries. | *Optional* | `"1m + 1.30 t"` | 2.4 | |    [transitGeneralizedCostLimit](#rd_if_transitGeneralizedCostLimit) | `object` | A relative limit for the generalized-cost for transit itineraries. | *Optional* | | 2.1 | |       [costLimitFunction](#rd_if_transitGeneralizedCostLimit_costLimitFunction) | `cost-linear-function` | The base function used by the filter. | *Optional* | `"15m + 1.50 t"` | 2.2 | |       [intervalRelaxFactor](#rd_if_transitGeneralizedCostLimit_intervalRelaxFactor) | `double` | How much the filter should be relaxed for itineraries that do not overlap in time. | *Optional* | `0.4` | 2.2 | @@ -634,7 +634,7 @@ Itineraries visiting the same set of stops and riding the exact same routes, dep **Since version:** `2.4` ∙ **Type:** `cost-linear-function` ∙ **Cardinality:** `Optional` ∙ **Default value:** `"1m + 1.30 t"` **Path:** /routingDefaults/itineraryFilters -Limit function for generalized-cost computed from non-transit itineries for transit itineraries. +Limit function for generalized-cost computed from street-only itineries applied to transit itineraries. The max-limit is applied to itineraries with transit *legs*, and only itineraries without transit legs are considered when calculating the minimum cost. The smallest diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java index d31f33ef282..a0f03427e64 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/ItineraryListFilterChainBuilder.java @@ -186,9 +186,9 @@ public ItineraryListFilterChainBuilder withParkAndRideDurationRatio(double value /** * The direct street search(walk, bicycle, car) is not pruning the transit search, so in some * cases we get "silly" transit itineraries that is marginally better on travel-duration compared - * with a on-street-all-the-way itinerary. Use this method to turn filter worse enough itineraries. + * with a on-street-all-the-way itinerary. Use this method to filter worse enough itineraries. *

- * The filter remove all itineraries with a generalized-cost that is higher than the best + * The filter removes all itineraries with a generalized-cost that is higher than the best * on-street-all-the-way itinerary. *

* This filter only have an effect, if an on-street-all-the-way(WALK, BICYCLE, CAR) itinerary diff --git a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java index 2061e6891ce..91f3071d4ed 100644 --- a/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java +++ b/src/main/java/org/opentripplanner/routing/api/request/preference/ItineraryFilterPreferences.java @@ -52,7 +52,7 @@ private ItineraryFilterPreferences() { ); this.removeTransitWithHigherCostThanBestOnStreetOnly = CostLinearFunction.of(Duration.ofMinutes(1), 1.3); - this.removeTransitIfWalkingIsBetter = true; + this.removeTransitIfWalkingIsBetter = false; } private ItineraryFilterPreferences(Builder builder) { @@ -73,7 +73,7 @@ private ItineraryFilterPreferences(Builder builder) { this.transitGeneralizedCostLimit = Objects.requireNonNull(builder.transitGeneralizedCostLimit); this.removeTransitWithHigherCostThanBestOnStreetOnly = Objects.requireNonNull(builder.removeTransitWithHigherCostThanBestOnStreetOnly); - this.removeTransitWithMoreWalking = builder.removeTransitWithMoreWalking; + this.removeTransitIfWalkingIsBetter = builder.removeTransitIfWalkingIsBetter; } public static Builder of() { @@ -136,8 +136,8 @@ public CostLinearFunction removeTransitWithHigherCostThanBestOnStreetOnly() { return removeTransitWithHigherCostThanBestOnStreetOnly; } - public boolean removeTransitWithMoreWalking() { - return removeTransitWithMoreWalking; + public boolean removeTransitIfWalkingIsBetter() { + return removeTransitIfWalkingIsBetter; } @Override @@ -187,7 +187,7 @@ public String toString() { "removeItinerariesWithSameRoutesAndStops", removeItinerariesWithSameRoutesAndStops ) - .addBoolIfTrue("removeTransitWithMoreWalking", removeTransitWithMoreWalking) + .addBoolIfTrue("removeTransitIfWalkingIsBetter", removeTransitIfWalkingIsBetter) .toString(); } @@ -200,7 +200,7 @@ public boolean equals(Object o) { accessibilityScore == that.accessibilityScore && Double.compare(that.bikeRentalDistanceRatio, bikeRentalDistanceRatio) == 0 && debug == that.debug && - removeTransitIfWalkingIsBetter == that.removeTransitIfWalkingIsBetter && + removeTransitIfWalkingIsBetter == that.removeTransitIfWalkingIsBetter && filterItinerariesWithSameFirstOrLastTrip == that.filterItinerariesWithSameFirstOrLastTrip && Double.compare( that.groupedOtherThanSameLegsMaxCostMultiplier, @@ -237,7 +237,7 @@ public int hashCode() { removeItinerariesWithSameRoutesAndStops, transitGeneralizedCostLimit, removeTransitWithHigherCostThanBestOnStreetOnly, - removeTransitWithMoreWalking + removeTransitIfWalkingIsBetter ); } From a49c89046be1df665b32caadfcf5bca20e359ce9 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 14 Sep 2023 16:02:23 +0300 Subject: [PATCH 35/36] Update src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java Co-authored-by: Thomas Gran --- .../deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java index 376e5d62af8..9d7aaa45e46 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java @@ -28,8 +28,6 @@ public String name() { @Override public List flagForRemoval(List itineraries) { - // Filter the most common silly itinerary case: transit itinerary has more walking than plain walk itinerary - // This never makes sense OptionalInt minWalkCost = itineraries .stream() From 200ed4ed450ec6ae4259dd39b632671427a40758 Mon Sep 17 00:00:00 2001 From: Vesa Meskanen Date: Thu, 14 Sep 2023 16:11:21 +0300 Subject: [PATCH 36/36] Fix formatting --- .../deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java index 9d7aaa45e46..4b645e45a79 100644 --- a/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java +++ b/src/main/java/org/opentripplanner/routing/algorithm/filterchain/deletionflagger/RemoveTransitIfWalkingIsBetterFilter.java @@ -28,7 +28,6 @@ public String name() { @Override public List flagForRemoval(List itineraries) { - OptionalInt minWalkCost = itineraries .stream() .filter(Itinerary::isWalkingAllTheWay)