Skip to content

Commit

Permalink
Merge branch 'master' into traveltime_cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
mrieser authored Oct 11, 2023
2 parents 5e02149 + ea46da1 commit 7e07e6c
Show file tree
Hide file tree
Showing 10 changed files with 271 additions and 151 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* *********************************************************************** *
* project: org.matsim.*
* *********************************************************************** *
* *
* copyright : (C) 2023 by the members listed in the COPYING, *
* LICENSE and WARRANTY file. *
* email : info at matsim dot org *
* *
* *********************************************************************** *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* See also COPYING, LICENSE and WARRANTY file *
* *
* *********************************************************************** */

package org.matsim.contrib.drt.optimizer.rebalancing;

import org.matsim.core.config.ReflectiveConfigGroup;

/**
* Custom rebalancing strategy parameters. User is responsible for installing rebalancing module and parameters.
*/
public final class CustomRebalancingStrategyParams extends ReflectiveConfigGroup
implements RebalancingParams.RebalancingStrategyParams {
public static final String SET_NAME = "CustomRebalancingStrategy";

public CustomRebalancingStrategyParams() {
super(SET_NAME);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public void install() {
install(new DrtModePlusOneRebalanceModule(drtCfg));
} else if (rebalancingParams.getRebalancingStrategyParams() instanceof FeedforwardRebalancingStrategyParams) {
install(new DrtModeFeedforwardRebalanceModule(drtCfg));
} else if (rebalancingParams.getRebalancingStrategyParams() instanceof CustomRebalancingStrategyParams) {
// User is responsible for installing custom module
} else {
throw new RuntimeException(
"Unsupported rebalancingStrategyParams: " + rebalancingParams.getRebalancingStrategyParams());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ private void initSingletonParameterSets() {
addDefinition(PlusOneRebalancingStrategyParams.SET_NAME, PlusOneRebalancingStrategyParams::new,
() -> (ConfigGroup)rebalancingStrategyParams,
params -> rebalancingStrategyParams = (RebalancingStrategyParams)params);
addDefinition(CustomRebalancingStrategyParams.SET_NAME, CustomRebalancingStrategyParams::new,
() -> (ConfigGroup)rebalancingStrategyParams,
params -> rebalancingStrategyParams = (RebalancingStrategyParams)params);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public class SwissRailRaptorConfigGroup extends ReflectiveConfigGroup {

private static final String PARAM_TRANSFER_WALK_MARGIN = "transferWalkMargin";
private static final String PARAM_TRANSFER_WALK_MARGIN_DESC = "time deducted from transfer walk leg during transfers between pt legs in order to avoid missing a vehicle by a few seconds due to delays.";
private static final String PARAM_INTERMODAL_LEG_ONLYHANDLING = "intermodalLegOnlyHandling";
private static final String PARAM_INTERMODAL_LEG_ONLYHANDLING_DESC = "Define how routes containing only intermodal legs are handled: Useful options: alllow, avoid, forbid";

private boolean useRangeQuery = false;
private boolean useIntermodality = false;
Expand All @@ -57,6 +59,7 @@ public class SwissRailRaptorConfigGroup extends ReflectiveConfigGroup {
private double transferPenaltyMaxCost = Double.POSITIVE_INFINITY;
private double transferPenaltyHourlyCost = 0;
private double transferWalkMargin = 5;
private IntermodalLegOnlyHandling intermodalLegOnlyHandling = IntermodalLegOnlyHandling.forbid;

private ScoringParameters scoringParameters = ScoringParameters.Default;

Expand All @@ -69,7 +72,27 @@ public class SwissRailRaptorConfigGroup extends ReflectiveConfigGroup {
public enum IntermodalAccessEgressModeSelection {
CalcLeastCostModePerStop, RandomSelectOneModePerRoutingRequestAndDirection
}


public enum IntermodalLegOnlyHandling {
/**
* allows transit routes that only consist of intermodal feeder legs if these have the lowest cost.
*/
allow,
/**
* avoids transit routes that only consist of feeder routes, unless no route containing at least one pt leg is found
*/
avoid,
/**
* explicitly forbids such routes, tries to find a pt route and returns null if nothing is found
*/
forbid,
/**
* mimics the behaviour implemented between 2019 and 2023. Returns null if a purely intermodal route has the lowest cost, does not check if a real pt route exists.
*/
@Deprecated
returnNull
}

public enum ScoringParameters {
Default, Individual
}
Expand All @@ -78,7 +101,24 @@ public SwissRailRaptorConfigGroup() {
super(GROUP);
}

@StringGetter(PARAM_USE_RANGE_QUERY)
@StringSetter(PARAM_INTERMODAL_LEG_ONLYHANDLING)
public void setIntermodalLegOnlyHandling(String intermodalLegOnlyHandling) {
this.intermodalLegOnlyHandling = IntermodalLegOnlyHandling.valueOf(intermodalLegOnlyHandling);
}
public void setIntermodalLegOnlyHandling(IntermodalLegOnlyHandling intermodalLegOnlyHandling) {
this.intermodalLegOnlyHandling = intermodalLegOnlyHandling;
}

@StringGetter(PARAM_INTERMODAL_LEG_ONLYHANDLING)
public String getIntermodalLegOnlyHandlingString() {
return intermodalLegOnlyHandling.toString();
}

public IntermodalLegOnlyHandling getIntermodalLegOnlyHandling() {
return intermodalLegOnlyHandling;
}

@StringGetter(PARAM_USE_RANGE_QUERY)
public boolean isUseRangeQuery() {
return this.useRangeQuery;
}
Expand Down Expand Up @@ -284,7 +324,8 @@ public Collection<ModeMappingForPassengersParameterSet> getModeMappingForPasseng
return this.modeMappingForPassengersByRouteMode.values();
}

public static class RangeQuerySettingsParameterSet extends ReflectiveConfigGroup {

public static class RangeQuerySettingsParameterSet extends ReflectiveConfigGroup {

private static final String TYPE = "rangeQuerySettings";

Expand Down Expand Up @@ -459,7 +500,7 @@ public IntermodalAccessEgressParameterSet setMaxRadius(double maxRadius) {
this.maxRadius = maxRadius;
return this ;
}

@StringGetter(PARAM_INITIAL_SEARCH_RADIUS)
public double getInitialSearchRadius() {
return initialSearchRadius;
Expand All @@ -470,7 +511,7 @@ public IntermodalAccessEgressParameterSet setInitialSearchRadius(double initialS
this.initialSearchRadius = initialSearchRadius;
return this ;
}

@StringGetter(PARAM_SEARCH_EXTENSION_RADIUS)
public double getSearchExtensionRadius() {
return searchExtensionRadius;
Expand Down Expand Up @@ -536,7 +577,7 @@ public IntermodalAccessEgressParameterSet setStopFilterValue(String stopFilterVa
this.stopFilterValue = stopFilterValue;
return this ;
}

@StringGetter(PARAM_SHARE_TRIP_SEARCH_RADIUS)
public double getShareTripSearchRadius() {
return shareTripSearchRadius;
Expand All @@ -560,7 +601,7 @@ public Map<String, String> getComments() {
map.put(PARAM_INITIAL_SEARCH_RADIUS, "Radius from the origin / destination coord in which transit stops are searched. Only if less than 2 transit stops are found the search radius is increased step-wise until the maximum search radius set in param radius is reached.");
map.put(PARAM_SEARCH_EXTENSION_RADIUS, "If less than 2 stops were found in initialSearchRadius take the distance of the closest transit stop and add this extension radius to search again.The search radius will not exceed the maximum search radius set in param radius. Default is 200 meters.");
map.put(PARAM_SHARE_TRIP_SEARCH_RADIUS, "The share of the trip crowfly distance within which the stops for access and egress will be searched for. This is a harder constraint than initial search radius. Default is positive infinity.");

return map;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

package ch.sbb.matsim.routing.pt.raptor;

import ch.sbb.matsim.config.SwissRailRaptorConfigGroup;

import java.util.HashMap;
import java.util.Map;

Expand All @@ -29,7 +31,8 @@ public enum RaptorOptimization {
*/
OneToAllRouting }

/**

/**
* The distance in meters that agents can walk to get from one stop to
* another stop of a nearby transit line.
*/
Expand All @@ -47,6 +50,8 @@ public enum RaptorOptimization {

private RaptorOptimization optimization = RaptorOptimization.OneToOneRouting;

private SwissRailRaptorConfigGroup.IntermodalLegOnlyHandling intermodalLegOnlyHandling = SwissRailRaptorConfigGroup.IntermodalLegOnlyHandling.forbid;

public double getBeelineWalkConnectionDistance() {
return this.beelineWalkConnectionDistance;
}
Expand Down Expand Up @@ -118,4 +123,12 @@ public RaptorOptimization getOptimization() {
public void setOptimization(RaptorOptimization optimization) {
this.optimization = optimization;
}

public SwissRailRaptorConfigGroup.IntermodalLegOnlyHandling getIntermodalLegOnlyHandling() {
return intermodalLegOnlyHandling;
}

public void setIntermodalLegOnlyHandling(SwissRailRaptorConfigGroup.IntermodalLegOnlyHandling intermodalLegOnlyHandling) {
this.intermodalLegOnlyHandling = intermodalLegOnlyHandling;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ public static RaptorStaticConfig createStaticConfig(Config config) {

RaptorStaticConfig staticConfig = new RaptorStaticConfig();

staticConfig.setBeelineWalkConnectionDistance(config.transitRouter().getMaxBeelineWalkConnectionDistance());

PlansCalcRouteConfigGroup.TeleportedModeParams walk = pcrConfig.getModeRoutingParams().get(TransportMode.walk );
staticConfig.setBeelineWalkSpeed(walk.getTeleportedModeSpeed() / walk.getBeelineDistanceFactor());
staticConfig.setBeelineWalkDistanceFactor(walk.getBeelineDistanceFactor());
staticConfig.setTransferWalkMargin(srrConfig.getTransferWalkMargin());
staticConfig.setMinimalTransferTime(config.transitRouter().getAdditionalTransferTime());
staticConfig.setBeelineWalkConnectionDistance(config.transitRouter().getMaxBeelineWalkConnectionDistance());
PlansCalcRouteConfigGroup.TeleportedModeParams walk = pcrConfig.getModeRoutingParams().get(TransportMode.walk );
staticConfig.setBeelineWalkSpeed(walk.getTeleportedModeSpeed() / walk.getBeelineDistanceFactor());
staticConfig.setBeelineWalkDistanceFactor(walk.getBeelineDistanceFactor());
staticConfig.setTransferWalkMargin(srrConfig.getTransferWalkMargin());
staticConfig.setIntermodalLegOnlyHandling(srrConfig.getIntermodalLegOnlyHandling());
staticConfig.setMinimalTransferTime(config.transitRouter().getAdditionalTransferTime());

staticConfig.setUseModeMappingForPassengers(srrConfig.isUseModeMappingForPassengers());
if (srrConfig.isUseModeMappingForPassengers()) {
Expand Down Expand Up @@ -81,7 +81,7 @@ public static RaptorParameters createParameters(Config config) {
double marginalUtility_utl_s = modeParams.getMarginalUtilityOfTraveling()/3600.0 - marginalUtilityPerforming;
raptorParams.setMarginalUtilityOfTravelTime_utl_s(mode, marginalUtility_utl_s);
}

double costPerHour = advancedConfig.getTransferPenaltyCostPerTravelTimeHour();
if (costPerHour == 0.0) {
// for backwards compatibility, use the default utility of line switch.
Expand All @@ -104,9 +104,8 @@ public static List<? extends PlanElement> convertRouteToLegs(RaptorRoute route,
for (RaptorRoute.RoutePart part : route.parts) {
if (part.planElements != null) {
for (PlanElement pe : part.planElements) {
if (pe instanceof Leg) {
Leg leg = (Leg) pe;
legs.add(leg);
if (pe instanceof Leg leg) {
legs.add(leg);
if (leg.getDepartureTime().isUndefined()) {
leg.setDepartureTime(lastArrivalTime);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public List<? extends PlanElement> calcRoute(RoutingRequest request) {
final double departureTime = request.getDepartureTime();
final Person person = request.getPerson();
final Attributes routingAttributes = request.getAttributes();

RaptorParameters parameters = this.parametersForPerson.getRaptorParameters(person);
if (parameters.getConfig().isUseRangeQuery()) {
return this.performRangeQuery(fromFacility, toFacility, departureTime, person, routingAttributes, parameters);
Expand All @@ -79,50 +79,32 @@ public List<? extends PlanElement> calcRoute(RoutingRequest request) {
RaptorRoute directWalk = createDirectWalk(fromFacility, toFacility, departureTime, person, parameters);

/*
* The pt trip is compared with a direct walk from trip origin to trip destination. This is useful for backwards
* compatibility, but leads to many trips with only a single "transit_walk" leg which are then considered pt
* trips by the main mode identifier even though they do not contain any pt leg and should rather be considered
* "walk" trips.
*
* That problem can be avoided by setting a very high direct walk factor in TransitRouterConfigGroup. However
* this should be combined with enabling mode choice for pt and walk trips such that slow pt trips can be
* replaced by (faster) walk trips by mode choice. Otherwise agents can be stuck with very slow pt trips.
*
* Comparison is only made between a pt trip and a direct walk trip, other modes (e.g. intermodal access/egress
* modes) are not considered. If they had been considered here, the router would effectively be a mode choice
* module although it is supposed not to change mode choice but rather to simply return a route for a given
* mode. Furthermore there is the problem that the generalized cost calculated by the router can be different
* from the cost the agent will be exposed to in scoring, because the mode performed differently in mobsim than
* anticipated by the router (e.g. the drt travel time turns out to be higher than expected, but the router will
* always chose a direct drt trip over the pt trip, because the router might consistently underestimate drt
* travel time). So it seems a bad idea to compare other modes than walk here. Walk is usually teleported at a
* fixed speed, so it is usually completely deterministic whereas other modes are not.
*
* Overall enabling mode choice and setting a very high direct walk factor (e.g. Double.POSITIVE_INFINITY which
* effectively excludes all direct walks) seems cleaner and better.
*
* vsp-gleich sep'19 (after talking with KN)
*
*
* foundRoute.parts.size() == 0 can happen if SwissRasilRaptorCore.createRaptorRoute() finds a trip made up of,
* only 2 parts which consists only of an access and an egress leg without any pt leg inbetween.
*/
if (foundRoute == null || foundRoute.parts.size() == 0 || hasNoPtLeg(foundRoute.parts)) {
if (directWalk.getTotalCosts() * parameters.getDirectWalkFactor() < foundRoute.getTotalCosts()) {
foundRoute = directWalk;
}
boolean forbidPurelyIntermodalRoutes = data.config.getIntermodalLegOnlyHandling().equals(SwissRailRaptorConfigGroup.IntermodalLegOnlyHandling.forbid) || data.config.getIntermodalLegOnlyHandling().equals(SwissRailRaptorConfigGroup.IntermodalLegOnlyHandling.returnNull);
if (foundRoute == null || (foundRoute.parts.size() == 0 && forbidPurelyIntermodalRoutes)) {
if (person == null) {
log.debug("No route found for person null: trip from x=" + fromFacility.getCoord().getX() + ",y=" + fromFacility.getCoord().getY() + " departure at " + departureTime + " to x=" + toFacility.getCoord().getX() + ",y=" + toFacility.getCoord().getY());
} else {
log.debug("No route found for person " + person.getId() + ": trip from x=" + fromFacility.getCoord().getX() + ",y=" + fromFacility.getCoord().getY() + " departure at " + departureTime + " to x=" + toFacility.getCoord().getX() + ",y=" + toFacility.getCoord().getY());
}
return null;
}
if (directWalk.getTotalCosts() * parameters.getDirectWalkFactor() < foundRoute.getTotalCosts()) {
foundRoute = directWalk;
return null;
}
else if ((hasNoPtLeg(foundRoute.parts))){
if (forbidPurelyIntermodalRoutes){
return null;
}
}


List<? extends PlanElement> legs = RaptorUtils.convertRouteToLegs(foundRoute, this.data.config.getTransferWalkMargin());
return legs;
}

private boolean hasNoPtLeg(List<RoutePart> parts) {
for (RoutePart part : parts) {
// if the route part has a TransitLine, it must be a real pt leg
Expand All @@ -142,10 +124,9 @@ private List<? extends PlanElement> performRangeQuery(Facility fromFacility, Fac
double earliestDepartureTime = desiredDepartureTime - rangeSettings.getMaxEarlierDeparture();
double latestDepartureTime = desiredDepartureTime + rangeSettings.getMaxLaterDeparture();

if (this.defaultRouteSelector instanceof ConfigurableRaptorRouteSelector) {
ConfigurableRaptorRouteSelector selector = (ConfigurableRaptorRouteSelector) this.defaultRouteSelector;
if (this.defaultRouteSelector instanceof ConfigurableRaptorRouteSelector selector) {

SwissRailRaptorConfigGroup.RouteSelectorParameterSet params = srrConfig.getRouteSelector(subpopulation);
SwissRailRaptorConfigGroup.RouteSelectorParameterSet params = srrConfig.getRouteSelector(subpopulation);

selector.setBetaTransfer(params.getBetaTransfers());
selector.setBetaTravelTime(params.getBetaTravelTime());
Expand Down Expand Up @@ -174,7 +155,7 @@ public List<? extends PlanElement> calcRoute(Facility fromFacility, Facility toF
} else {
log.debug("No route found for person " + person.getId() + ": trip from x=" + fromFacility.getCoord().getX() + ",y=" + fromFacility.getCoord().getY() + " departure at " + desiredDepartureTime + " to x=" + toFacility.getCoord().getX() + ",y=" + toFacility.getCoord().getY());
}
return null;
return null;
}
if (directWalk.getTotalCosts() * parameters.getDirectWalkFactor() < foundRoute.getTotalCosts()) {
foundRoute = directWalk;
Expand Down
Loading

0 comments on commit 7e07e6c

Please sign in to comment.