From bdeba2f1c6c459d431d7739e759dffff0909c9bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 6 Mar 2024 07:16:45 +0100 Subject: [PATCH] feat: transit routing by transport mode utilities --- .../routing/pt/raptor/RaptorParameters.java | 10 +++++ .../pt/raptor/SwissRailRaptorCore.java | 4 +- .../pt/raptor/SwissRailRaptorTest.java | 45 ++++++++++++++++++- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorParameters.java b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorParameters.java index ba79214ff73..3aa0443b9e0 100644 --- a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorParameters.java +++ b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/RaptorParameters.java @@ -65,6 +65,8 @@ public class RaptorParameters { private double transferPenaltyPerTravelTimeHour = 0.0; private double transferPenaltyMinimum = Double.NEGATIVE_INFINITY; private double transferPenaltyMaximum = Double.POSITIVE_INFINITY; + + private boolean useTransportModeUtilities = false; private final SwissRailRaptorConfigGroup config; @@ -159,5 +161,13 @@ public double getTransferPenaltyMaximum() { public void setTransferPenaltyMaximum(double transferPenaltyMaximum) { this.transferPenaltyMaximum = transferPenaltyMaximum; } + + public boolean isUseTransportModeUtilities() { + return useTransportModeUtilities; + } + + public void setUseTransportModeUtilities(boolean useTransportModeUtilities) { + this.useTransportModeUtilities = useTransportModeUtilities; + } } diff --git a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java index 09cef257e09..0242f5e91ab 100644 --- a/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java +++ b/matsim/src/main/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorCore.java @@ -588,6 +588,7 @@ private void exploreRoutes(RaptorParameters parameters, Person person) { CachingTransferProvider transferProvider = this.data.new CachingTransferProvider(); double marginalUtilityOfWaitingPt_utl_s = parameters.getMarginalUtilityOfWaitingPt_utl_s(); + boolean useTransportModeUtilities = parameters.isUseTransportModeUtilities(); int routeIndex = -1; for (int firstRouteStopIndex = this.improvedRouteStopIndices.nextSetBit(0); firstRouteStopIndex >= 0; firstRouteStopIndex = this.improvedRouteStopIndices.nextSetBit(firstRouteStopIndex+1)) { @@ -627,7 +628,8 @@ private void exploreRoutes(RaptorParameters parameters, Person person) { routeIndex = tmpRouteIndex; int firstDepartureTime = (boardingPE.firstDepartureTime == TIME_UNDEFINED) ? currentAgentBoardingTime : boardingPE.firstDepartureTime; - double marginalUtilityOfTravelTime_utl_s = parameters.getMarginalUtilityOfTravelTime_utl_s(boardingPE.toRouteStop.mode); + double marginalUtilityOfTravelTime_utl_s = parameters.getMarginalUtilityOfTravelTime_utl_s( + !useTransportModeUtilities ? boardingPE.toRouteStop.mode : boardingPE.toRouteStop.route.getTransportMode()); transferProvider.reset(boardingPE.transfer); for (int toRouteStopIndex = firstRouteStopIndex + 1; toRouteStopIndex < route.indexFirstRouteStop + route.countRouteStops; toRouteStopIndex++) { diff --git a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java index 98431e35cc7..567c6ace568 100644 --- a/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java +++ b/matsim/src/test/java/ch/sbb/matsim/routing/pt/raptor/SwissRailRaptorTest.java @@ -33,6 +33,7 @@ import org.matsim.api.core.v01.network.Node; import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.PlanElement; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; @@ -337,7 +338,7 @@ void testLineChange() { assertEquals(Math.ceil(expectedTravelTime), actualTravelTime, MatsimTestUtils.EPSILON); } @Test - void testLineChangeWithDifferentUtils() { + void testLineChangeWithDifferentModeChangeUtils() { Fixture f = new Fixture(); f.init(); f.blueLine.getRoutes().values().forEach(transitRoute -> transitRoute.setTransportMode(TransportMode.ship)); @@ -355,6 +356,48 @@ void testLineChangeWithDifferentUtils() { //changing from train to ship is so expensive that direct walk is cheaper assertNull(legs); } + + @Test + void testLineChangeWithDifferentTravelTimeUtils() { + Fixture f = new Fixture(); + f.init(); + f.blueLine.getRoutes().values().forEach(transitRoute -> transitRoute.setTransportMode("bus")); + SwissRailRaptorConfigGroup swissRailRaptorConfigGroup = ConfigUtils.addOrGetModule(f.config, SwissRailRaptorConfigGroup.class); + swissRailRaptorConfigGroup.setTransferWalkMargin(0); + RaptorParameters raptorParams = RaptorUtils.createParameters(f.config); + SwissRailRaptorData data = SwissRailRaptorData.create(f.schedule, null, RaptorUtils.createStaticConfig(f.config), f.network, null); + TransitRouter router = new SwissRailRaptor.Builder(data, f.config).with(new RaptorParametersForPerson() { + @Override + public RaptorParameters getRaptorParameters(Person person) { + return raptorParams; + } + }).build(); + + // from C to G (see Fixture), competing between red line (express) and blue line (regular) + Coord fromCoord = new Coord(12000, 5000); + Coord toCoord = new Coord(28000, 5000); + + // default case + List legs = router.calcRoute(DefaultRoutingRequest.withoutAttributes(new FakeFacility(fromCoord), new FakeFacility(toCoord), 6.0*3600 - 60.0, null)); + assertEquals(3, legs.size()); + assertEquals("red", ((TransitPassengerRoute) ((Leg) legs.get(1)).getRoute()).getLineId().toString()); + + // routing by transport mode, same costs, choose red (train) again + raptorParams.setUseTransportModeUtilities(true); + raptorParams.setMarginalUtilityOfTravelTime_utl_s("train", -1e-3); + raptorParams.setMarginalUtilityOfTravelTime_utl_s("bus", -1e-3); + legs = router.calcRoute(DefaultRoutingRequest.withoutAttributes(new FakeFacility(fromCoord), new FakeFacility(toCoord), 6.0*3600 - 60.0, null)); + assertEquals(3, legs.size()); + assertEquals("red", ((TransitPassengerRoute) ((Leg) legs.get(1)).getRoute()).getLineId().toString()); + + // routing by transport mode, train is quicker, but more costly now, so choose blue (bus) + raptorParams.setUseTransportModeUtilities(true); + raptorParams.setMarginalUtilityOfTravelTime_utl_s("train", -1e-2); + raptorParams.setMarginalUtilityOfTravelTime_utl_s("bus", -1e-3); + legs = router.calcRoute(DefaultRoutingRequest.withoutAttributes(new FakeFacility(fromCoord), new FakeFacility(toCoord), 6.0*3600 - 60.0, null)); + assertEquals(3, legs.size()); + assertEquals("blue", ((TransitPassengerRoute) ((Leg) legs.get(1)).getRoute()).getLineId().toString()); + } @Test void testFasterAlternative() {