Skip to content

Commit

Permalink
feat: drt now supported by default in the core module (#185)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
tkchouaki authored Jan 17, 2024
1 parent e23f643 commit 4b87117
Show file tree
Hide file tree
Showing 40 changed files with 708 additions and 368 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import org.eqasim.core.analysis.trips.TripReaderFromEvents;
import org.eqasim.core.analysis.trips.TripReaderFromPopulation;
import org.eqasim.core.analysis.trips.TripWriter;
import org.eqasim.core.components.EqasimMainModeIdentifier;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.network.Network;
import org.matsim.core.config.CommandLine;
Expand All @@ -25,6 +24,7 @@
import org.matsim.core.network.NetworkUtils;
import org.matsim.core.network.io.MatsimNetworkReader;
import org.matsim.core.router.MainModeIdentifier;
import org.matsim.core.router.RoutingModeMainModeIdentifier;
import org.matsim.core.scenario.ScenarioUtils;
import org.matsim.facilities.ActivityFacilities;
import org.matsim.facilities.MatsimFacilitiesReader;
Expand Down Expand Up @@ -65,7 +65,7 @@ public static void run(CommandLine cmd, PersonAnalysisFilter personAnalysisFilte

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

MainModeIdentifier mainModeIdentifier = new EqasimMainModeIdentifier();
MainModeIdentifier mainModeIdentifier = new RoutingModeMainModeIdentifier();

Collection<String> vehicleModes = Arrays.asList(cmd.getOption("vehicle-modes").orElse("car,pt").split(","))
.stream().map(s -> s.trim()).collect(Collectors.toSet());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.matsim.api.core.v01.events.handler.PersonEntersVehicleEventHandler;
import org.matsim.api.core.v01.events.handler.PersonLeavesVehicleEventHandler;
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.population.Leg;
import org.matsim.api.core.v01.population.Person;
import org.matsim.api.core.v01.population.PopulationFactory;
import org.matsim.core.api.experimental.events.TeleportationArrivalEvent;
Expand Down Expand Up @@ -92,7 +93,9 @@ public void handleEvent(ActivityEndEvent event) {
@Override
public void handleEvent(PersonDepartureEvent event) {
if (personFilter.analyzePerson(event.getPersonId())) {
ongoing.get(event.getPersonId()).elements.add(factory.createLeg(event.getLegMode()));
Leg leg = factory.createLeg(event.getLegMode());
leg.getAttributes().putAttribute("routingMode", event.getRoutingMode());
ongoing.get(event.getPersonId()).elements.add(leg);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

import org.matsim.core.controler.AbstractModule;
import org.matsim.core.router.MainModeIdentifier;
import org.matsim.core.router.RoutingModeMainModeIdentifier;

public class EqasimComponentsModule extends AbstractModule {
@Override
public void install() {
bind(MainModeIdentifier.class).to(EqasimMainModeIdentifier.class);
bind(MainModeIdentifier.class).to(RoutingModeMainModeIdentifier.class);
}
}
31 changes: 31 additions & 0 deletions core/src/main/java/org/eqasim/core/misc/ClassUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.eqasim.core.misc;

import java.lang.reflect.InvocationTargetException;

public class ClassUtils {
public static <T> T getInstanceOfClassExtendingOtherClass(String className, Class<T> otherClass) {
try {
Class<?> classDescription = Class.forName(className);
Object instance = null;
try {
instance = classDescription.getConstructor().newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(String.format("The class %s does not have a constructor that does not require arguments", classDescription.getCanonicalName()), e);
}

if (otherClass.isInstance(instance)) {
return (T) instance;
} else {
throw new IllegalStateException(String.format("Class %s does not extend %s", classDescription.getCanonicalName(), otherClass.getCanonicalName()));
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@
import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.population.Person;
import org.matsim.contrib.drt.routing.DrtRoute;
import org.matsim.contrib.drt.routing.DrtRouteFactory;
import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
import org.matsim.contrib.drt.run.MultiModeDrtModule;
import org.matsim.contrib.dvrp.run.DvrpConfigGroup;
import org.matsim.contrib.dvrp.run.DvrpModule;
import org.matsim.contrib.dvrp.run.DvrpQSimComponents;
import org.matsim.contrib.dvrp.run.MultiModal;
import org.matsim.contribs.discrete_mode_choice.modules.DiscreteModeChoiceModule;
import org.matsim.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup;
import org.matsim.core.config.Config;
Expand Down Expand Up @@ -53,6 +61,14 @@ public EqasimConfigurator() {
new EqasimTransitQSimModule(), //
new EqasimTrafficQSimModule() //
));

this.registerOptionalConfigGroup(new MultiModeDrtConfigGroup(),
Collections.singleton(new MultiModeDrtModule()),
Collections.emptyList(),
Collections.singletonList((controller, components) ->
DvrpQSimComponents.activateAllModes((MultiModal<?>) controller.getConfig().getModules().get(MultiModeDrtConfigGroup.GROUP_NAME)).configure(components)));

this.registerOptionalConfigGroup(new DvrpConfigGroup(), Collections.singleton(new DvrpModule()));
}

public ConfigGroup[] getConfigGroups() {
Expand Down Expand Up @@ -132,6 +148,7 @@ public void addOptionalConfigGroups(Config config) {
}

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

public void adjustScenario(Scenario scenario) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,29 @@
import org.eqasim.core.analysis.legs.LegListener;
import org.eqasim.core.analysis.pt.PublicTransportLegListener;
import org.eqasim.core.analysis.trips.TripListener;
import org.eqasim.core.simulation.modes.drt.analysis.DrtAnalysisModule;
import org.matsim.api.core.v01.network.Network;
import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
import org.matsim.core.controler.AbstractModule;
import org.matsim.core.router.MainModeIdentifier;
import org.matsim.pt.transitSchedule.api.TransitSchedule;

import com.google.inject.Provides;
import com.google.inject.Singleton;


public class EqasimAnalysisModule extends AbstractModule {
@Override
public void install() {
addControlerListenerBinding().to(AnalysisOutputListener.class);
bind(DefaultPersonAnalysisFilter.class);
bind(PersonAnalysisFilter.class).to(DefaultPersonAnalysisFilter.class);
if(getConfig().getModules().containsKey(MultiModeDrtConfigGroup.GROUP_NAME)) {
install(new DrtAnalysisModule());
} else {
// Would be better if there was a way to add the module above as an overriding module from this method.
// That way we could simply bind the two classes below before the if clause
bind(DefaultPersonAnalysisFilter.class);
bind(PersonAnalysisFilter.class).to(DefaultPersonAnalysisFilter.class);
}
}

@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

import org.eqasim.core.components.config.EqasimConfigGroup;
import org.eqasim.core.simulation.mode_choice.constraints.EqasimVehicleTourConstraint;
Expand All @@ -24,9 +25,15 @@
import org.eqasim.core.simulation.mode_choice.utilities.predictors.PersonPredictor;
import org.eqasim.core.simulation.mode_choice.utilities.predictors.PtPredictor;
import org.eqasim.core.simulation.mode_choice.utilities.predictors.WalkPredictor;
import org.eqasim.core.simulation.modes.drt.mode_choice.constraints.DrtWalkConstraint;
import org.eqasim.core.simulation.modes.drt.mode_choice.predictors.DefaultDrtPredictor;
import org.eqasim.core.simulation.modes.drt.mode_choice.predictors.DrtPredictor;
import org.eqasim.core.simulation.modes.drt.mode_choice.utilities.estimators.DrtUtilityEstimator;
import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
import org.matsim.contribs.discrete_mode_choice.components.utils.home_finder.HomeFinder;
import org.matsim.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup;
import org.matsim.contribs.discrete_mode_choice.modules.config.VehicleTourConstraintConfigGroup;
import org.matsim.core.config.Config;
import org.matsim.core.router.TripRouter;
import org.matsim.core.utils.timing.TimeInterpretation;
import org.matsim.facilities.ActivityFacilities;
Expand All @@ -39,7 +46,7 @@
public class EqasimModeChoiceModule extends AbstractEqasimExtension {
public static final String PASSENGER_CONSTRAINT_NAME = "PassengerConstraint";
public static final String OUTSIDE_CONSTRAINT_NAME = "OutsideConstraint";

public static final String DRT_WALK_CONSTRAINT = "DrtWalkConstraint";
public static final String TOUR_LENGTH_FILTER_NAME = "TourLengthFilter";
public static final String OUTSIDE_FILTER_NAME = "OutsideFilter";

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

public static final String ZERO_COST_MODEL_NAME = "ZeroCostModel";

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

bindTourFilter(TOUR_LENGTH_FILTER_NAME).to(TourLengthFilter.class);
bindTourFilter(OUTSIDE_FILTER_NAME).to(OutsideFilter.class);
Expand All @@ -71,12 +80,14 @@ protected void installEqasimExtension() {
bind(BikePredictor.class);
bind(WalkPredictor.class);
bind(PersonPredictor.class);
bind(DrtPredictor.class).to(DefaultDrtPredictor.class);

bindUtilityEstimator(ZERO_ESTIMATOR_NAME).to(ZeroUtilityEstimator.class);
bindUtilityEstimator(CAR_ESTIMATOR_NAME).to(CarUtilityEstimator.class);
bindUtilityEstimator(PT_ESTIMATOR_NAME).to(PtUtilityEstimator.class);
bindUtilityEstimator(BIKE_ESTIMATOR_NAME).to(BikeUtilityEstimator.class);
bindUtilityEstimator(WALK_ESTIMATOR_NAME).to(WalkUtilityEstimator.class);
bindUtilityEstimator(DRT_ESTIMATOR_NAME).to(DrtUtilityEstimator.class);

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

Expand Down Expand Up @@ -124,4 +135,14 @@ public EqasimVehicleTourConstraint.Factory provideEqasimVehicleTourConstraintFac
VehicleTourConstraintConfigGroup config = dmcConfig.getVehicleTourConstraintConfig();
return new EqasimVehicleTourConstraint.Factory(config.getRestrictedModes(), homeFinder);
}

@Provides
public DefaultDrtPredictor provideDefaultDrtPredictor(Config config, Map<String, Provider<CostModel>> factory) {
if(!config.getModules().containsKey(MultiModeDrtConfigGroup.GROUP_NAME)) {
throw new IllegalStateException(String.format("%s module not found", MultiModeDrtConfigGroup.GROUP_NAME));
}
EqasimConfigGroup eqasimConfigGroup = (EqasimConfigGroup) config.getModules().get(EqasimConfigGroup.GROUP_NAME);
MultiModeDrtConfigGroup multiModeDrtConfigGroup = (MultiModeDrtConfigGroup) config.getModules().get(MultiModeDrtConfigGroup.GROUP_NAME);
return new DefaultDrtPredictor(multiModeDrtConfigGroup.modes().collect(Collectors.toMap(mode -> mode, mode -> getCostModel(factory, eqasimConfigGroup, mode))));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ public class WalkParameters {
public double betaTravelTime_u_min = 0.0;
}

public class DrtParameters {
public double alpha_u = 0.0;
public double betaTravelTime_u_min = 0.0;
public double betaWaitingTime_u_min = 0.0;
public double betaAccessEgressTime_u_min = 0.0;
}


public double lambdaCostEuclideanDistance = 0.0;
public double referenceEuclideanDistance_km = 0.0;

Expand All @@ -39,4 +47,5 @@ public class WalkParameters {
public final PtParameters pt = new PtParameters();
public final BikeParameters bike = new BikeParameters();
public final WalkParameters walk = new WalkParameters();
public final DrtParameters drt = new DrtParameters();
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
package org.eqasim.examples.corsica_drt.analysis;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.stream.Collectors;
package org.eqasim.core.simulation.modes.drt.analysis;

import com.google.inject.Singleton;
import org.eqasim.core.components.config.EqasimConfigGroup;
import org.eqasim.examples.corsica_drt.analysis.passengers.PassengerAnalysisListener;
import org.eqasim.examples.corsica_drt.analysis.passengers.PassengerAnalysisWriter;
import org.eqasim.examples.corsica_drt.analysis.utils.LinkFinder;
import org.eqasim.examples.corsica_drt.analysis.utils.VehicleRegistry;
import org.eqasim.examples.corsica_drt.analysis.vehicles.VehicleAnalysisListener;
import org.eqasim.examples.corsica_drt.analysis.vehicles.VehicleAnalysisWriter;
import org.eqasim.core.simulation.modes.drt.analysis.dvrp_vehicles.VehicleAnalysisListener;
import org.eqasim.core.simulation.modes.drt.analysis.dvrp_vehicles.VehicleAnalysisWriter;
import org.eqasim.core.simulation.modes.drt.analysis.passengers.PassengerAnalysisListener;
import org.eqasim.core.simulation.modes.drt.analysis.passengers.PassengerAnalysisWriter;
import org.eqasim.core.simulation.modes.drt.analysis.utils.LinkFinder;
import org.eqasim.core.simulation.modes.drt.analysis.utils.VehicleRegistry;
import org.matsim.api.core.v01.network.Network;
import org.matsim.contrib.drt.run.DrtConfigGroup;
import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup;
import org.matsim.core.controler.OutputDirectoryHierarchy;
import org.matsim.core.controler.events.IterationEndsEvent;
Expand All @@ -22,11 +19,13 @@
import org.matsim.core.controler.listener.IterationStartsListener;
import org.matsim.core.controler.listener.ShutdownListener;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.stream.Collectors;

@Singleton
public class DvrpAnalysisListener implements IterationStartsListener, IterationEndsListener, ShutdownListener {
public class DrtAnalysisListener implements IterationStartsListener, IterationEndsListener, ShutdownListener {
private static final String PASSENGER_RIDES_FILE_NAME = "eqasim_drt_passenger_rides.csv";
private static final String VEHICLE_MOVEMENTS_FILE_NAME = "eqasim_drt_vehicle_movements.csv";
private static final String VEHICLE_ACTIVITIES_FILE_NAME = "eqasim_drt_vehicle_activities.csv";
Expand All @@ -39,19 +38,16 @@ public class DvrpAnalysisListener implements IterationStartsListener, IterationE
private final PassengerAnalysisListener passengerAnalysisListener;
private final VehicleAnalysisListener vehicleAnalysisListener;

private final VehicleRegistry vehicleRegistry;

@Inject
public DvrpAnalysisListener(EqasimConfigGroup config, MultiModeDrtConfigGroup drtConfig,
OutputDirectoryHierarchy outputDirectory, Network network) {
public DrtAnalysisListener(EqasimConfigGroup config, MultiModeDrtConfigGroup drtConfig,
OutputDirectoryHierarchy outputDirectory, Network network,
VehicleRegistry vehicleRegistry) {
this.outputDirectory = outputDirectory;
this.analysisInterval = config.getAnalysisInterval();

LinkFinder linkFinder = new LinkFinder(network);
this.vehicleRegistry = new VehicleRegistry();

this.passengerAnalysisListener = new PassengerAnalysisListener(
drtConfig.getModalElements().stream().map(e -> e.getMode()).collect(Collectors.toSet()), linkFinder,
drtConfig.getModalElements().stream().map(DrtConfigGroup::getMode).collect(Collectors.toSet()), linkFinder,
vehicleRegistry);
this.vehicleAnalysisListener = new VehicleAnalysisListener(linkFinder, vehicleRegistry);
}
Expand All @@ -65,16 +61,13 @@ public void notifyIterationStarts(IterationStartsEvent event) {
if (isActive) {
event.getServices().getEvents().addHandler(passengerAnalysisListener);
event.getServices().getEvents().addHandler(vehicleAnalysisListener);
event.getServices().getEvents().addHandler(vehicleRegistry);
}
}

@Override
public void notifyIterationEnds(IterationEndsEvent event) {
try {
if (isActive) {
event.getServices().getEvents().removeHandler(vehicleRegistry);

event.getServices().getEvents().removeHandler(passengerAnalysisListener);

String path = outputDirectory.getIterationFilename(event.getIteration(), PASSENGER_RIDES_FILE_NAME);
Expand Down Expand Up @@ -102,23 +95,26 @@ public void notifyShutdown(ShutdownEvent event) {
outputDirectory.getIterationFilename(event.getIteration(), PASSENGER_RIDES_FILE_NAME));
File outputPath = new File(outputDirectory.getOutputFilename(PASSENGER_RIDES_FILE_NAME));
Files.copy(iterationPath.toPath(), outputPath.toPath());
} catch (IOException e) {
} catch (IOException exception) {
throw new RuntimeException(exception);
}

try {
File iterationPath = new File(
outputDirectory.getIterationFilename(event.getIteration(), VEHICLE_MOVEMENTS_FILE_NAME));
File outputPath = new File(outputDirectory.getOutputFilename(VEHICLE_MOVEMENTS_FILE_NAME));
Files.copy(iterationPath.toPath(), outputPath.toPath());
} catch (IOException e) {
} catch (IOException exception) {
throw new RuntimeException(exception);
}

try {
File iterationPath = new File(
outputDirectory.getIterationFilename(event.getIteration(), VEHICLE_ACTIVITIES_FILE_NAME));
File outputPath = new File(outputDirectory.getOutputFilename(VEHICLE_ACTIVITIES_FILE_NAME));
Files.copy(iterationPath.toPath(), outputPath.toPath());
} catch (IOException e) {
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
}
Loading

0 comments on commit 4b87117

Please sign in to comment.