Skip to content

Commit 4b87117

Browse files
authored
feat: drt now supported by default in the core module (#185)
* feat: CreateDrtVehicles * feat: random seed parameter in CreateDrtVehicles * feat: using RoutingModeMainModeIdentifier instead of EqasimMainModeIdentifier The EqasimMainModeIdentifier is not removed by this commit. * feat: support for DRT in core * feat: Drt analysis * feat: DrtAnalysisModule is used properly now * refractor: removed redundant classes
1 parent e23f643 commit 4b87117

40 files changed

+708
-368
lines changed

core/src/main/java/org/eqasim/core/analysis/run/RunTripAnalysis.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import org.eqasim.core.analysis.trips.TripReaderFromEvents;
1616
import org.eqasim.core.analysis.trips.TripReaderFromPopulation;
1717
import org.eqasim.core.analysis.trips.TripWriter;
18-
import org.eqasim.core.components.EqasimMainModeIdentifier;
1918
import org.matsim.api.core.v01.Scenario;
2019
import org.matsim.api.core.v01.network.Network;
2120
import org.matsim.core.config.CommandLine;
@@ -25,6 +24,7 @@
2524
import org.matsim.core.network.NetworkUtils;
2625
import org.matsim.core.network.io.MatsimNetworkReader;
2726
import org.matsim.core.router.MainModeIdentifier;
27+
import org.matsim.core.router.RoutingModeMainModeIdentifier;
2828
import org.matsim.core.scenario.ScenarioUtils;
2929
import org.matsim.facilities.ActivityFacilities;
3030
import org.matsim.facilities.MatsimFacilitiesReader;
@@ -65,7 +65,7 @@ public static void run(CommandLine cmd, PersonAnalysisFilter personAnalysisFilte
6565

6666
String outputPath = cmd.getOptionStrict("output-path");
6767

68-
MainModeIdentifier mainModeIdentifier = new EqasimMainModeIdentifier();
68+
MainModeIdentifier mainModeIdentifier = new RoutingModeMainModeIdentifier();
6969

7070
Collection<String> vehicleModes = Arrays.asList(cmd.getOption("vehicle-modes").orElse("car,pt").split(","))
7171
.stream().map(s -> s.trim()).collect(Collectors.toSet());

core/src/main/java/org/eqasim/core/analysis/trips/TripListener.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.matsim.api.core.v01.events.handler.PersonEntersVehicleEventHandler;
2525
import org.matsim.api.core.v01.events.handler.PersonLeavesVehicleEventHandler;
2626
import org.matsim.api.core.v01.network.Network;
27+
import org.matsim.api.core.v01.population.Leg;
2728
import org.matsim.api.core.v01.population.Person;
2829
import org.matsim.api.core.v01.population.PopulationFactory;
2930
import org.matsim.core.api.experimental.events.TeleportationArrivalEvent;
@@ -92,7 +93,9 @@ public void handleEvent(ActivityEndEvent event) {
9293
@Override
9394
public void handleEvent(PersonDepartureEvent event) {
9495
if (personFilter.analyzePerson(event.getPersonId())) {
95-
ongoing.get(event.getPersonId()).elements.add(factory.createLeg(event.getLegMode()));
96+
Leg leg = factory.createLeg(event.getLegMode());
97+
leg.getAttributes().putAttribute("routingMode", event.getRoutingMode());
98+
ongoing.get(event.getPersonId()).elements.add(leg);
9699
}
97100
}
98101

core/src/main/java/org/eqasim/core/components/EqasimComponentsModule.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
import org.matsim.core.controler.AbstractModule;
44
import org.matsim.core.router.MainModeIdentifier;
5+
import org.matsim.core.router.RoutingModeMainModeIdentifier;
56

67
public class EqasimComponentsModule extends AbstractModule {
78
@Override
89
public void install() {
9-
bind(MainModeIdentifier.class).to(EqasimMainModeIdentifier.class);
10+
bind(MainModeIdentifier.class).to(RoutingModeMainModeIdentifier.class);
1011
}
1112
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package org.eqasim.core.misc;
2+
3+
import java.lang.reflect.InvocationTargetException;
4+
5+
public class ClassUtils {
6+
public static <T> T getInstanceOfClassExtendingOtherClass(String className, Class<T> otherClass) {
7+
try {
8+
Class<?> classDescription = Class.forName(className);
9+
Object instance = null;
10+
try {
11+
instance = classDescription.getConstructor().newInstance();
12+
} catch (InstantiationException e) {
13+
throw new RuntimeException(e);
14+
} catch (IllegalAccessException e) {
15+
throw new RuntimeException(e);
16+
} catch (InvocationTargetException e) {
17+
throw new RuntimeException(e);
18+
} catch (NoSuchMethodException e) {
19+
throw new RuntimeException(String.format("The class %s does not have a constructor that does not require arguments", classDescription.getCanonicalName()), e);
20+
}
21+
22+
if (otherClass.isInstance(instance)) {
23+
return (T) instance;
24+
} else {
25+
throw new IllegalStateException(String.format("Class %s does not extend %s", classDescription.getCanonicalName(), otherClass.getCanonicalName()));
26+
}
27+
} catch (ClassNotFoundException e) {
28+
throw new RuntimeException(e);
29+
}
30+
}
31+
}

core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@
1212
import org.matsim.api.core.v01.Id;
1313
import org.matsim.api.core.v01.Scenario;
1414
import org.matsim.api.core.v01.population.Person;
15+
import org.matsim.contrib.drt.routing.DrtRoute;
16+
import org.matsim.contrib.drt.routing.DrtRouteFactory;
17+
import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
18+
import org.matsim.contrib.drt.run.MultiModeDrtModule;
19+
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
20+
import org.matsim.contrib.dvrp.run.DvrpModule;
21+
import org.matsim.contrib.dvrp.run.DvrpQSimComponents;
22+
import org.matsim.contrib.dvrp.run.MultiModal;
1523
import org.matsim.contribs.discrete_mode_choice.modules.DiscreteModeChoiceModule;
1624
import org.matsim.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup;
1725
import org.matsim.core.config.Config;
@@ -53,6 +61,14 @@ public EqasimConfigurator() {
5361
new EqasimTransitQSimModule(), //
5462
new EqasimTrafficQSimModule() //
5563
));
64+
65+
this.registerOptionalConfigGroup(new MultiModeDrtConfigGroup(),
66+
Collections.singleton(new MultiModeDrtModule()),
67+
Collections.emptyList(),
68+
Collections.singletonList((controller, components) ->
69+
DvrpQSimComponents.activateAllModes((MultiModal<?>) controller.getConfig().getModules().get(MultiModeDrtConfigGroup.GROUP_NAME)).configure(components)));
70+
71+
this.registerOptionalConfigGroup(new DvrpConfigGroup(), Collections.singleton(new DvrpModule()));
5672
}
5773

5874
public ConfigGroup[] getConfigGroups() {
@@ -132,6 +148,7 @@ public void addOptionalConfigGroups(Config config) {
132148
}
133149

134150
public void configureScenario(Scenario scenario) {
151+
scenario.getPopulation().getFactory().getRouteFactories().setRouteFactory(DrtRoute.class, new DrtRouteFactory());
135152
}
136153

137154
public void adjustScenario(Scenario scenario) {

core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,29 @@
55
import org.eqasim.core.analysis.legs.LegListener;
66
import org.eqasim.core.analysis.pt.PublicTransportLegListener;
77
import org.eqasim.core.analysis.trips.TripListener;
8+
import org.eqasim.core.simulation.modes.drt.analysis.DrtAnalysisModule;
89
import org.matsim.api.core.v01.network.Network;
10+
import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
911
import org.matsim.core.controler.AbstractModule;
1012
import org.matsim.core.router.MainModeIdentifier;
1113
import org.matsim.pt.transitSchedule.api.TransitSchedule;
1214

1315
import com.google.inject.Provides;
1416
import com.google.inject.Singleton;
1517

18+
1619
public class EqasimAnalysisModule extends AbstractModule {
1720
@Override
1821
public void install() {
1922
addControlerListenerBinding().to(AnalysisOutputListener.class);
20-
bind(DefaultPersonAnalysisFilter.class);
21-
bind(PersonAnalysisFilter.class).to(DefaultPersonAnalysisFilter.class);
23+
if(getConfig().getModules().containsKey(MultiModeDrtConfigGroup.GROUP_NAME)) {
24+
install(new DrtAnalysisModule());
25+
} else {
26+
// Would be better if there was a way to add the module above as an overriding module from this method.
27+
// That way we could simply bind the two classes below before the if clause
28+
bind(DefaultPersonAnalysisFilter.class);
29+
bind(PersonAnalysisFilter.class).to(DefaultPersonAnalysisFilter.class);
30+
}
2231
}
2332

2433
@Provides

core/src/main/java/org/eqasim/core/simulation/mode_choice/EqasimModeChoiceModule.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.util.Collections;
44
import java.util.HashMap;
55
import java.util.Map;
6+
import java.util.stream.Collectors;
67

78
import org.eqasim.core.components.config.EqasimConfigGroup;
89
import org.eqasim.core.simulation.mode_choice.constraints.EqasimVehicleTourConstraint;
@@ -24,9 +25,15 @@
2425
import org.eqasim.core.simulation.mode_choice.utilities.predictors.PersonPredictor;
2526
import org.eqasim.core.simulation.mode_choice.utilities.predictors.PtPredictor;
2627
import org.eqasim.core.simulation.mode_choice.utilities.predictors.WalkPredictor;
28+
import org.eqasim.core.simulation.modes.drt.mode_choice.constraints.DrtWalkConstraint;
29+
import org.eqasim.core.simulation.modes.drt.mode_choice.predictors.DefaultDrtPredictor;
30+
import org.eqasim.core.simulation.modes.drt.mode_choice.predictors.DrtPredictor;
31+
import org.eqasim.core.simulation.modes.drt.mode_choice.utilities.estimators.DrtUtilityEstimator;
32+
import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
2733
import org.matsim.contribs.discrete_mode_choice.components.utils.home_finder.HomeFinder;
2834
import org.matsim.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup;
2935
import org.matsim.contribs.discrete_mode_choice.modules.config.VehicleTourConstraintConfigGroup;
36+
import org.matsim.core.config.Config;
3037
import org.matsim.core.router.TripRouter;
3138
import org.matsim.core.utils.timing.TimeInterpretation;
3239
import org.matsim.facilities.ActivityFacilities;
@@ -39,7 +46,7 @@
3946
public class EqasimModeChoiceModule extends AbstractEqasimExtension {
4047
public static final String PASSENGER_CONSTRAINT_NAME = "PassengerConstraint";
4148
public static final String OUTSIDE_CONSTRAINT_NAME = "OutsideConstraint";
42-
49+
public static final String DRT_WALK_CONSTRAINT = "DrtWalkConstraint";
4350
public static final String TOUR_LENGTH_FILTER_NAME = "TourLengthFilter";
4451
public static final String OUTSIDE_FILTER_NAME = "OutsideFilter";
4552

@@ -50,6 +57,7 @@ public class EqasimModeChoiceModule extends AbstractEqasimExtension {
5057
public static final String BIKE_ESTIMATOR_NAME = "BikeUtilityEstimator";
5158
public static final String WALK_ESTIMATOR_NAME = "WalkUtilityEstimator";
5259
public static final String ZERO_ESTIMATOR_NAME = "ZeroUtilityEstimator";
60+
public static final String DRT_ESTIMATOR_NAME = "DrtUtilityEstimator";
5361

5462
public static final String ZERO_COST_MODEL_NAME = "ZeroCostModel";
5563

@@ -60,6 +68,7 @@ public class EqasimModeChoiceModule extends AbstractEqasimExtension {
6068
protected void installEqasimExtension() {
6169
bindTripConstraintFactory(PASSENGER_CONSTRAINT_NAME).to(PassengerConstraint.Factory.class);
6270
bindTripConstraintFactory(OUTSIDE_CONSTRAINT_NAME).to(OutsideConstraint.Factory.class);
71+
bindTripConstraintFactory(DRT_WALK_CONSTRAINT).to(DrtWalkConstraint.Factory.class);
6372

6473
bindTourFilter(TOUR_LENGTH_FILTER_NAME).to(TourLengthFilter.class);
6574
bindTourFilter(OUTSIDE_FILTER_NAME).to(OutsideFilter.class);
@@ -71,12 +80,14 @@ protected void installEqasimExtension() {
7180
bind(BikePredictor.class);
7281
bind(WalkPredictor.class);
7382
bind(PersonPredictor.class);
83+
bind(DrtPredictor.class).to(DefaultDrtPredictor.class);
7484

7585
bindUtilityEstimator(ZERO_ESTIMATOR_NAME).to(ZeroUtilityEstimator.class);
7686
bindUtilityEstimator(CAR_ESTIMATOR_NAME).to(CarUtilityEstimator.class);
7787
bindUtilityEstimator(PT_ESTIMATOR_NAME).to(PtUtilityEstimator.class);
7888
bindUtilityEstimator(BIKE_ESTIMATOR_NAME).to(BikeUtilityEstimator.class);
7989
bindUtilityEstimator(WALK_ESTIMATOR_NAME).to(WalkUtilityEstimator.class);
90+
bindUtilityEstimator(DRT_ESTIMATOR_NAME).to(DrtUtilityEstimator.class);
8091

8192
bindCostModel(ZERO_COST_MODEL_NAME).to(ZeroCostModel.class);
8293

@@ -124,4 +135,14 @@ public EqasimVehicleTourConstraint.Factory provideEqasimVehicleTourConstraintFac
124135
VehicleTourConstraintConfigGroup config = dmcConfig.getVehicleTourConstraintConfig();
125136
return new EqasimVehicleTourConstraint.Factory(config.getRestrictedModes(), homeFinder);
126137
}
138+
139+
@Provides
140+
public DefaultDrtPredictor provideDefaultDrtPredictor(Config config, Map<String, Provider<CostModel>> factory) {
141+
if(!config.getModules().containsKey(MultiModeDrtConfigGroup.GROUP_NAME)) {
142+
throw new IllegalStateException(String.format("%s module not found", MultiModeDrtConfigGroup.GROUP_NAME));
143+
}
144+
EqasimConfigGroup eqasimConfigGroup = (EqasimConfigGroup) config.getModules().get(EqasimConfigGroup.GROUP_NAME);
145+
MultiModeDrtConfigGroup multiModeDrtConfigGroup = (MultiModeDrtConfigGroup) config.getModules().get(MultiModeDrtConfigGroup.GROUP_NAME);
146+
return new DefaultDrtPredictor(multiModeDrtConfigGroup.modes().collect(Collectors.toMap(mode -> mode, mode -> getCostModel(factory, eqasimConfigGroup, mode))));
147+
}
127148
}

core/src/main/java/org/eqasim/core/simulation/mode_choice/parameters/ModeParameters.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ public class WalkParameters {
3030
public double betaTravelTime_u_min = 0.0;
3131
}
3232

33+
public class DrtParameters {
34+
public double alpha_u = 0.0;
35+
public double betaTravelTime_u_min = 0.0;
36+
public double betaWaitingTime_u_min = 0.0;
37+
public double betaAccessEgressTime_u_min = 0.0;
38+
}
39+
40+
3341
public double lambdaCostEuclideanDistance = 0.0;
3442
public double referenceEuclideanDistance_km = 0.0;
3543

@@ -39,4 +47,5 @@ public class WalkParameters {
3947
public final PtParameters pt = new PtParameters();
4048
public final BikeParameters bike = new BikeParameters();
4149
public final WalkParameters walk = new WalkParameters();
50+
public final DrtParameters drt = new DrtParameters();
4251
}

examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/DvrpAnalysisListener.java renamed to core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtAnalysisListener.java

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
1-
package org.eqasim.examples.corsica_drt.analysis;
2-
3-
import java.io.File;
4-
import java.io.IOException;
5-
import java.nio.file.Files;
6-
import java.util.stream.Collectors;
1+
package org.eqasim.core.simulation.modes.drt.analysis;
72

3+
import com.google.inject.Singleton;
84
import org.eqasim.core.components.config.EqasimConfigGroup;
9-
import org.eqasim.examples.corsica_drt.analysis.passengers.PassengerAnalysisListener;
10-
import org.eqasim.examples.corsica_drt.analysis.passengers.PassengerAnalysisWriter;
11-
import org.eqasim.examples.corsica_drt.analysis.utils.LinkFinder;
12-
import org.eqasim.examples.corsica_drt.analysis.utils.VehicleRegistry;
13-
import org.eqasim.examples.corsica_drt.analysis.vehicles.VehicleAnalysisListener;
14-
import org.eqasim.examples.corsica_drt.analysis.vehicles.VehicleAnalysisWriter;
5+
import org.eqasim.core.simulation.modes.drt.analysis.dvrp_vehicles.VehicleAnalysisListener;
6+
import org.eqasim.core.simulation.modes.drt.analysis.dvrp_vehicles.VehicleAnalysisWriter;
7+
import org.eqasim.core.simulation.modes.drt.analysis.passengers.PassengerAnalysisListener;
8+
import org.eqasim.core.simulation.modes.drt.analysis.passengers.PassengerAnalysisWriter;
9+
import org.eqasim.core.simulation.modes.drt.analysis.utils.LinkFinder;
10+
import org.eqasim.core.simulation.modes.drt.analysis.utils.VehicleRegistry;
1511
import org.matsim.api.core.v01.network.Network;
12+
import org.matsim.contrib.drt.run.DrtConfigGroup;
1613
import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
1714
import org.matsim.core.controler.OutputDirectoryHierarchy;
1815
import org.matsim.core.controler.events.IterationEndsEvent;
@@ -22,11 +19,13 @@
2219
import org.matsim.core.controler.listener.IterationStartsListener;
2320
import org.matsim.core.controler.listener.ShutdownListener;
2421

25-
import com.google.inject.Inject;
26-
import com.google.inject.Singleton;
22+
import java.io.File;
23+
import java.io.IOException;
24+
import java.nio.file.Files;
25+
import java.util.stream.Collectors;
2726

2827
@Singleton
29-
public class DvrpAnalysisListener implements IterationStartsListener, IterationEndsListener, ShutdownListener {
28+
public class DrtAnalysisListener implements IterationStartsListener, IterationEndsListener, ShutdownListener {
3029
private static final String PASSENGER_RIDES_FILE_NAME = "eqasim_drt_passenger_rides.csv";
3130
private static final String VEHICLE_MOVEMENTS_FILE_NAME = "eqasim_drt_vehicle_movements.csv";
3231
private static final String VEHICLE_ACTIVITIES_FILE_NAME = "eqasim_drt_vehicle_activities.csv";
@@ -39,19 +38,16 @@ public class DvrpAnalysisListener implements IterationStartsListener, IterationE
3938
private final PassengerAnalysisListener passengerAnalysisListener;
4039
private final VehicleAnalysisListener vehicleAnalysisListener;
4140

42-
private final VehicleRegistry vehicleRegistry;
43-
44-
@Inject
45-
public DvrpAnalysisListener(EqasimConfigGroup config, MultiModeDrtConfigGroup drtConfig,
46-
OutputDirectoryHierarchy outputDirectory, Network network) {
41+
public DrtAnalysisListener(EqasimConfigGroup config, MultiModeDrtConfigGroup drtConfig,
42+
OutputDirectoryHierarchy outputDirectory, Network network,
43+
VehicleRegistry vehicleRegistry) {
4744
this.outputDirectory = outputDirectory;
4845
this.analysisInterval = config.getAnalysisInterval();
4946

5047
LinkFinder linkFinder = new LinkFinder(network);
51-
this.vehicleRegistry = new VehicleRegistry();
5248

5349
this.passengerAnalysisListener = new PassengerAnalysisListener(
54-
drtConfig.getModalElements().stream().map(e -> e.getMode()).collect(Collectors.toSet()), linkFinder,
50+
drtConfig.getModalElements().stream().map(DrtConfigGroup::getMode).collect(Collectors.toSet()), linkFinder,
5551
vehicleRegistry);
5652
this.vehicleAnalysisListener = new VehicleAnalysisListener(linkFinder, vehicleRegistry);
5753
}
@@ -65,16 +61,13 @@ public void notifyIterationStarts(IterationStartsEvent event) {
6561
if (isActive) {
6662
event.getServices().getEvents().addHandler(passengerAnalysisListener);
6763
event.getServices().getEvents().addHandler(vehicleAnalysisListener);
68-
event.getServices().getEvents().addHandler(vehicleRegistry);
6964
}
7065
}
7166

7267
@Override
7368
public void notifyIterationEnds(IterationEndsEvent event) {
7469
try {
7570
if (isActive) {
76-
event.getServices().getEvents().removeHandler(vehicleRegistry);
77-
7871
event.getServices().getEvents().removeHandler(passengerAnalysisListener);
7972

8073
String path = outputDirectory.getIterationFilename(event.getIteration(), PASSENGER_RIDES_FILE_NAME);
@@ -102,23 +95,26 @@ public void notifyShutdown(ShutdownEvent event) {
10295
outputDirectory.getIterationFilename(event.getIteration(), PASSENGER_RIDES_FILE_NAME));
10396
File outputPath = new File(outputDirectory.getOutputFilename(PASSENGER_RIDES_FILE_NAME));
10497
Files.copy(iterationPath.toPath(), outputPath.toPath());
105-
} catch (IOException e) {
98+
} catch (IOException exception) {
99+
throw new RuntimeException(exception);
106100
}
107101

108102
try {
109103
File iterationPath = new File(
110104
outputDirectory.getIterationFilename(event.getIteration(), VEHICLE_MOVEMENTS_FILE_NAME));
111105
File outputPath = new File(outputDirectory.getOutputFilename(VEHICLE_MOVEMENTS_FILE_NAME));
112106
Files.copy(iterationPath.toPath(), outputPath.toPath());
113-
} catch (IOException e) {
107+
} catch (IOException exception) {
108+
throw new RuntimeException(exception);
114109
}
115110

116111
try {
117112
File iterationPath = new File(
118113
outputDirectory.getIterationFilename(event.getIteration(), VEHICLE_ACTIVITIES_FILE_NAME));
119114
File outputPath = new File(outputDirectory.getOutputFilename(VEHICLE_ACTIVITIES_FILE_NAME));
120115
Files.copy(iterationPath.toPath(), outputPath.toPath());
121-
} catch (IOException e) {
116+
} catch (IOException exception) {
117+
throw new RuntimeException(exception);
122118
}
123119
}
124120
}

0 commit comments

Comments
 (0)