From 8aaf776d97de8e32da6ebae2e0bc4c8e3dd7d696 Mon Sep 17 00:00:00 2001 From: Tarek Chouaki Date: Fri, 15 Dec 2023 17:41:03 +0100 Subject: [PATCH 1/7] feat: CreateDrtVehicles --- .../modes/drt/utils/CreateDrtVehicles.java | 47 +++++++++++++++++++ pom.xml | 6 +++ 2 files changed, 53 insertions(+) create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/utils/CreateDrtVehicles.java diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/utils/CreateDrtVehicles.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/utils/CreateDrtVehicles.java new file mode 100644 index 000000000..a4896cbf0 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/utils/CreateDrtVehicles.java @@ -0,0 +1,47 @@ +package org.eqasim.core.simulation.modes.drt.utils; + +import org.apache.log4j.Logger; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.contrib.dvrp.fleet.*; +import org.matsim.core.config.CommandLine; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.network.io.MatsimNetworkReader; + +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class CreateDrtVehicles { + private final static Logger logger = Logger.getLogger(CreateDrtVehicles.class); + + public static void main(String[] args) throws CommandLine.ConfigurationException, MalformedURLException { + CommandLine cmd = new CommandLine.Builder(args) // + .requireOptions("network-path", "output-vehicles-path", "vehicles-number") + .allowOptions("vehicles-capacity", "service-begin-time", "service-end-time", "vehicle-id-prefix") + .build(); + int vehiclesNumber = Integer.parseInt(cmd.getOptionStrict("vehicles-number")); + int vehiclesCapacity = cmd.hasOption("vehicles-capacity") ? Integer.parseInt(cmd.getOptionStrict("vehicles-capacity")) : 4; + int serviceBeginTime = cmd.hasOption("service-begin-time") ? Integer.parseInt(cmd.getOptionStrict("service-begin-time")) : 0; + int serviceEndTime = cmd.hasOption("service-end-time") ? Integer.parseInt(cmd.getOptionStrict("service-end-time")) : 24 * 3600; + String vehicleIdPrefx = cmd.getOption("vehicle-id-prefix").orElse("vehicle_drt_"); + Network network = NetworkUtils.createNetwork(); + new MatsimNetworkReader(network).readFile(cmd.getOptionStrict("network-path")); + List> linksIds = new ArrayList<>(network.getLinks().keySet()); + Random random = new Random(); + FleetSpecification fleetSpecification = new FleetSpecificationImpl(); + for(int i=0; i linkId = null; + while(linkId == null || !network.getLinks().get(linkId).getAllowedModes().contains("car")) { + linkId = linksIds.get(random.nextInt(linksIds.size())); + } + Id vehicleId = Id.create(vehicleIdPrefx+i, DvrpVehicle.class); + logger.info("Creating vehicle " + vehicleId.toString() + " on link " + linkId.toString()); + DvrpVehicleSpecification dvrpVehicleSpecification = ImmutableDvrpVehicleSpecification.newBuilder().id(vehicleId).startLinkId(linkId).serviceBeginTime(serviceBeginTime).serviceEndTime(serviceEndTime).capacity(vehiclesCapacity).build(); + fleetSpecification.addVehicleSpecification(dvrpVehicleSpecification); + } + new FleetWriter(fleetSpecification.getVehicleSpecifications().values().stream()).write(cmd.getOptionStrict("output-vehicles-path")); + } +} diff --git a/pom.xml b/pom.xml index 392b6d3bb..a830cd978 100644 --- a/pom.xml +++ b/pom.xml @@ -100,6 +100,12 @@ ${matsim.version} + + org.matsim.contrib + drt + ${matsim.version} + + junit junit From 855cafa60ea3b05f098983444c284f1bf9256a77 Mon Sep 17 00:00:00 2001 From: Tarek Chouaki Date: Sat, 16 Dec 2023 13:13:06 +0100 Subject: [PATCH 2/7] feat: random seed parameter in CreateDrtVehicles --- .../core/simulation/modes/drt/utils/CreateDrtVehicles.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/utils/CreateDrtVehicles.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/utils/CreateDrtVehicles.java index a4896cbf0..feda7e3a4 100644 --- a/core/src/main/java/org/eqasim/core/simulation/modes/drt/utils/CreateDrtVehicles.java +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/utils/CreateDrtVehicles.java @@ -17,20 +17,24 @@ public class CreateDrtVehicles { private final static Logger logger = Logger.getLogger(CreateDrtVehicles.class); + public final static long DEFAULT_RANDOM_SEED = 1234; + public static void main(String[] args) throws CommandLine.ConfigurationException, MalformedURLException { CommandLine cmd = new CommandLine.Builder(args) // .requireOptions("network-path", "output-vehicles-path", "vehicles-number") .allowOptions("vehicles-capacity", "service-begin-time", "service-end-time", "vehicle-id-prefix") + .allowOptions("random-seed") .build(); int vehiclesNumber = Integer.parseInt(cmd.getOptionStrict("vehicles-number")); int vehiclesCapacity = cmd.hasOption("vehicles-capacity") ? Integer.parseInt(cmd.getOptionStrict("vehicles-capacity")) : 4; int serviceBeginTime = cmd.hasOption("service-begin-time") ? Integer.parseInt(cmd.getOptionStrict("service-begin-time")) : 0; int serviceEndTime = cmd.hasOption("service-end-time") ? Integer.parseInt(cmd.getOptionStrict("service-end-time")) : 24 * 3600; + long randomSeed = cmd.hasOption("random-seed") ? Long.parseLong(cmd.getOptionStrict("random-seed")) : DEFAULT_RANDOM_SEED; String vehicleIdPrefx = cmd.getOption("vehicle-id-prefix").orElse("vehicle_drt_"); Network network = NetworkUtils.createNetwork(); new MatsimNetworkReader(network).readFile(cmd.getOptionStrict("network-path")); List> linksIds = new ArrayList<>(network.getLinks().keySet()); - Random random = new Random(); + Random random = new Random(randomSeed); FleetSpecification fleetSpecification = new FleetSpecificationImpl(); for(int i=0; i linkId = null; From 38209d87f4da47a1db958def798a989265c18991 Mon Sep 17 00:00:00 2001 From: Tarek Chouaki Date: Sat, 16 Dec 2023 18:29:32 +0100 Subject: [PATCH 3/7] feat: using RoutingModeMainModeIdentifier instead of EqasimMainModeIdentifier The EqasimMainModeIdentifier is not removed by this commit. --- .../java/org/eqasim/core/analysis/run/RunTripAnalysis.java | 4 ++-- .../java/org/eqasim/core/analysis/trips/TripListener.java | 5 ++++- .../org/eqasim/core/components/EqasimComponentsModule.java | 3 ++- .../src/test/java/org/eqasim/ile_de_france/TestCorisica.java | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/analysis/run/RunTripAnalysis.java b/core/src/main/java/org/eqasim/core/analysis/run/RunTripAnalysis.java index f25438a3e..fb04de0d3 100644 --- a/core/src/main/java/org/eqasim/core/analysis/run/RunTripAnalysis.java +++ b/core/src/main/java/org/eqasim/core/analysis/run/RunTripAnalysis.java @@ -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; @@ -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; @@ -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 vehicleModes = Arrays.asList(cmd.getOption("vehicle-modes").orElse("car,pt").split(",")) .stream().map(s -> s.trim()).collect(Collectors.toSet()); diff --git a/core/src/main/java/org/eqasim/core/analysis/trips/TripListener.java b/core/src/main/java/org/eqasim/core/analysis/trips/TripListener.java index 974b6d5b4..812f9fd0d 100644 --- a/core/src/main/java/org/eqasim/core/analysis/trips/TripListener.java +++ b/core/src/main/java/org/eqasim/core/analysis/trips/TripListener.java @@ -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; @@ -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); } } diff --git a/core/src/main/java/org/eqasim/core/components/EqasimComponentsModule.java b/core/src/main/java/org/eqasim/core/components/EqasimComponentsModule.java index 9e9436b42..edfdfedbb 100644 --- a/core/src/main/java/org/eqasim/core/components/EqasimComponentsModule.java +++ b/core/src/main/java/org/eqasim/core/components/EqasimComponentsModule.java @@ -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); } } diff --git a/ile_de_france/src/test/java/org/eqasim/ile_de_france/TestCorisica.java b/ile_de_france/src/test/java/org/eqasim/ile_de_france/TestCorisica.java index a6b7ae128..bd4292a17 100644 --- a/ile_de_france/src/test/java/org/eqasim/ile_de_france/TestCorisica.java +++ b/ile_de_france/src/test/java/org/eqasim/ile_de_france/TestCorisica.java @@ -86,9 +86,9 @@ public void testCorsicaPipeline() Map counts = countLegs("corsica_test/cut_output/output_events.xml.gz"); Assert.assertEquals(3001, (long) counts.get("car")); Assert.assertEquals(387, (long) counts.get("car_passenger")); - Assert.assertEquals(847, (long) counts.get("walk")); + Assert.assertEquals(850, (long) counts.get("walk")); Assert.assertEquals(0, (long) counts.getOrDefault("bike", 0L)); - Assert.assertEquals(6, (long) counts.get("pt")); + Assert.assertEquals(9, (long) counts.get("pt")); Assert.assertEquals(95, (long) counts.get("outside")); } } From 523321727a94227945827b108e688e96cf0fff7d Mon Sep 17 00:00:00 2001 From: Tarek Chouaki Date: Sat, 16 Dec 2023 21:02:29 +0100 Subject: [PATCH 4/7] feat: support for DRT in core --- .../java/org/eqasim/core/misc/ClassUtils.java | 31 ++++ .../core/simulation/EqasimConfigurator.java | 17 ++ .../analysis/EqasimAnalysisModule.java | 13 +- .../mode_choice/EqasimModeChoiceModule.java | 23 ++- .../parameters/ModeParameters.java | 9 + .../drt/analysis/DrtPersonAnalysisFilter.java | 25 +++ .../modes/drt/analysis/VehicleRegistry.java | 24 +++ .../constraints/DrtWalkConstraint.java | 65 +++++++ .../predictors/DefaultDrtPredictor.java | 53 ++++++ .../mode_choice/predictors/DrtPredictor.java | 8 + .../estimators/DrtUtilityEstimator.java | 61 +++++++ .../mode_choice/variables/DrtVariables.java | 20 ++ .../modes/drt/utils/AdaptConfigForDrt.java | 172 ++++++++++++++++++ .../org/eqasim/TestSimulationPipeline.java | 42 ++++- .../corsica_drt/RunCorsicaDrtSimulation.java | 3 - 15 files changed, 554 insertions(+), 12 deletions(-) create mode 100644 core/src/main/java/org/eqasim/core/misc/ClassUtils.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtPersonAnalysisFilter.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/VehicleRegistry.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/constraints/DrtWalkConstraint.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/predictors/DefaultDrtPredictor.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/predictors/DrtPredictor.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/utilities/estimators/DrtUtilityEstimator.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/variables/DrtVariables.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/utils/AdaptConfigForDrt.java diff --git a/core/src/main/java/org/eqasim/core/misc/ClassUtils.java b/core/src/main/java/org/eqasim/core/misc/ClassUtils.java new file mode 100644 index 000000000..c81017dff --- /dev/null +++ b/core/src/main/java/org/eqasim/core/misc/ClassUtils.java @@ -0,0 +1,31 @@ +package org.eqasim.core.misc; + +import java.lang.reflect.InvocationTargetException; + +public class ClassUtils { + public static T getInstanceOfClassExtendingOtherClass(String className, Class 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); + } + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java b/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java index 2c7530c0f..9d8d67cee 100644 --- a/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java +++ b/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java @@ -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; @@ -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() { @@ -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) { diff --git a/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java b/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java index b4a08af6d..03af8c588 100644 --- a/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java +++ b/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java @@ -5,7 +5,10 @@ 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.DrtPersonAnalysisFilter; +import org.eqasim.core.simulation.modes.drt.analysis.VehicleRegistry; 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; @@ -17,8 +20,14 @@ 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)) { + bind(VehicleRegistry.class).asEagerSingleton(); + addEventHandlerBinding().to(VehicleRegistry.class); + bind(PersonAnalysisFilter.class).to(DrtPersonAnalysisFilter.class); + } else { + bind(DefaultPersonAnalysisFilter.class); + bind(PersonAnalysisFilter.class).to(DefaultPersonAnalysisFilter.class); + } } @Provides diff --git a/core/src/main/java/org/eqasim/core/simulation/mode_choice/EqasimModeChoiceModule.java b/core/src/main/java/org/eqasim/core/simulation/mode_choice/EqasimModeChoiceModule.java index b6bdf3773..3bf0fc947 100644 --- a/core/src/main/java/org/eqasim/core/simulation/mode_choice/EqasimModeChoiceModule.java +++ b/core/src/main/java/org/eqasim/core/simulation/mode_choice/EqasimModeChoiceModule.java @@ -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; @@ -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; @@ -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"; @@ -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"; @@ -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); @@ -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); @@ -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> 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)))); + } } diff --git a/core/src/main/java/org/eqasim/core/simulation/mode_choice/parameters/ModeParameters.java b/core/src/main/java/org/eqasim/core/simulation/mode_choice/parameters/ModeParameters.java index fb1edf678..934f83fef 100644 --- a/core/src/main/java/org/eqasim/core/simulation/mode_choice/parameters/ModeParameters.java +++ b/core/src/main/java/org/eqasim/core/simulation/mode_choice/parameters/ModeParameters.java @@ -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; @@ -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(); } diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtPersonAnalysisFilter.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtPersonAnalysisFilter.java new file mode 100644 index 000000000..c5079f0ed --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtPersonAnalysisFilter.java @@ -0,0 +1,25 @@ +package org.eqasim.core.simulation.modes.drt.analysis; + +import com.google.inject.Inject; +import org.eqasim.core.analysis.DefaultPersonAnalysisFilter; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.population.Person; + +public class DrtPersonAnalysisFilter extends DefaultPersonAnalysisFilter { + + private final VehicleRegistry vehicleRegistry; + + @Inject + public DrtPersonAnalysisFilter(VehicleRegistry vehicleRegistry) { + this.vehicleRegistry = vehicleRegistry; + } + + @Override + public boolean analyzePerson(Id personId) { + if(this.vehicleRegistry.isFleet(personId)) { + return false; + } + return super.analyzePerson(personId); + } +} + diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/VehicleRegistry.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/VehicleRegistry.java new file mode 100644 index 000000000..a3098b144 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/VehicleRegistry.java @@ -0,0 +1,24 @@ +package org.eqasim.core.simulation.modes.drt.analysis; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.IdMap; +import org.matsim.contrib.dvrp.fleet.DvrpVehicle; +import org.matsim.contrib.dvrp.vrpagent.TaskStartedEvent; +import org.matsim.contrib.dvrp.vrpagent.TaskStartedEventHandler; + +public class VehicleRegistry implements TaskStartedEventHandler { + private final IdMap vehicleModes = new IdMap<>(DvrpVehicle.class); + + @Override + public void handleEvent(TaskStartedEvent event) { + vehicleModes.computeIfAbsent(event.getDvrpVehicleId(), id -> event.getDvrpMode()); + } + + public boolean isFleet(Id id) { + return vehicleModes.containsKey(Id.create(id, DvrpVehicle.class)); + } + + public String getMode(Id id) { + return vehicleModes.get(Id.create(id, DvrpVehicle.class)); + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/constraints/DrtWalkConstraint.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/constraints/DrtWalkConstraint.java new file mode 100644 index 000000000..dd960595c --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/constraints/DrtWalkConstraint.java @@ -0,0 +1,65 @@ +package org.eqasim.core.simulation.modes.drt.mode_choice.constraints; + +import com.google.inject.Inject; +import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.Person; +import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; +import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; +import org.matsim.contribs.discrete_mode_choice.model.constraints.AbstractTripConstraint; +import org.matsim.contribs.discrete_mode_choice.model.trip_based.TripConstraint; +import org.matsim.contribs.discrete_mode_choice.model.trip_based.TripConstraintFactory; +import org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.RoutedTripCandidate; +import org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate; +import org.matsim.core.config.Config; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Note, this class can be made even more generic into something like a LegModeConstraint that checks if a leg with a certain mode is contained in a route. + * Then separate factories can be written outside of this class. + */ +public class DrtWalkConstraint extends AbstractTripConstraint { + + private final Set drtModes; + + public DrtWalkConstraint(Set drtModes) { + this.drtModes = drtModes; + } + + public boolean validateAfterEstimation(DiscreteModeChoiceTrip trip, TripCandidate candidate, List previousCandidates) { + if(this.drtModes.contains(candidate.getMode())) { + if (candidate instanceof RoutedTripCandidate) { + RoutedTripCandidate routedTripCandidate = (RoutedTripCandidate) candidate; + return routedTripCandidate.getRoutedPlanElements().stream() + .filter(planElement -> planElement instanceof Leg) + .map(planElement -> (Leg) planElement) + .map(Leg::getMode) + .anyMatch(candidate.getMode()::equals); + } + } + return true; + } + + + public static class Factory implements TripConstraintFactory { + + private Set drtModes = new HashSet<>(); + + @Inject + public Factory(Config config) { + if(config.getModules().containsKey(MultiModeDrtConfigGroup.GROUP_NAME)) { + MultiModeDrtConfigGroup multiModeDrtConfigGroup = (MultiModeDrtConfigGroup) config.getModules().get(MultiModeDrtConfigGroup.GROUP_NAME); + drtModes = multiModeDrtConfigGroup.modes().collect(Collectors.toSet()); + } + } + + @Override + public TripConstraint createConstraint(Person person, List list, Collection collection) { + return new DrtWalkConstraint(drtModes); + } + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/predictors/DefaultDrtPredictor.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/predictors/DefaultDrtPredictor.java new file mode 100644 index 000000000..baf401d91 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/predictors/DefaultDrtPredictor.java @@ -0,0 +1,53 @@ +package org.eqasim.core.simulation.modes.drt.mode_choice.predictors; + +import org.eqasim.core.simulation.mode_choice.cost.CostModel; +import org.eqasim.core.simulation.mode_choice.utilities.predictors.PredictorUtils; +import org.eqasim.core.simulation.modes.drt.mode_choice.variables.DrtVariables; +import org.matsim.api.core.v01.TransportMode; +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.contrib.drt.routing.DrtRoute; +import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; +import org.matsim.core.router.TripStructureUtils; + +import java.util.List; +import java.util.Map; + +public class DefaultDrtPredictor implements DrtPredictor { + private Map costModels; + + public DefaultDrtPredictor(Map costModels) { + this.costModels = costModels; + } + + + @Override + public DrtVariables predictVariables(Person person, DiscreteModeChoiceTrip trip, List elements) { + double travelTime_min = 0.0; + double accessEgressTime_min = 0.0; + double cost_MU = 0.0; + double waitingTime_min = 0.0; + + for (Leg leg : TripStructureUtils.getLegs(elements)) { + if (costModels.containsKey(leg.getMode())) { + DrtRoute route = (DrtRoute) leg.getRoute(); + + // We use worst case here + travelTime_min = route.getMaxTravelTime() / 60.0; + waitingTime_min = route.getMaxWaitTime() / 60.0; + + cost_MU = costModels.get(leg.getMode()).calculateCost_MU(person, trip, elements); + + } else if (leg.getMode().equals(TransportMode.walk)) { + accessEgressTime_min += leg.getTravelTime().seconds() / 60.0; + } else { + throw new IllegalStateException("Encountered unknown mode in DrtPredictor: " + leg.getMode()); + } + } + + double euclideanDistance_km = PredictorUtils.calculateEuclideanDistance_km(trip); + + return new DrtVariables(travelTime_min, cost_MU, euclideanDistance_km, waitingTime_min, accessEgressTime_min); + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/predictors/DrtPredictor.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/predictors/DrtPredictor.java new file mode 100644 index 000000000..bb547a700 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/predictors/DrtPredictor.java @@ -0,0 +1,8 @@ +package org.eqasim.core.simulation.modes.drt.mode_choice.predictors; + +import org.eqasim.core.simulation.mode_choice.utilities.predictors.VariablePredictor; +import org.eqasim.core.simulation.modes.drt.mode_choice.variables.DrtVariables; + +public interface DrtPredictor extends VariablePredictor { + +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/utilities/estimators/DrtUtilityEstimator.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/utilities/estimators/DrtUtilityEstimator.java new file mode 100644 index 000000000..30314786b --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/utilities/estimators/DrtUtilityEstimator.java @@ -0,0 +1,61 @@ +package org.eqasim.core.simulation.modes.drt.mode_choice.utilities.estimators; + +import com.google.inject.Inject; +import org.eqasim.core.simulation.mode_choice.parameters.ModeParameters; +import org.eqasim.core.simulation.mode_choice.utilities.UtilityEstimator; +import org.eqasim.core.simulation.mode_choice.utilities.estimators.EstimatorUtils; +import org.eqasim.core.simulation.modes.drt.mode_choice.predictors.DrtPredictor; +import org.eqasim.core.simulation.modes.drt.mode_choice.variables.DrtVariables; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.PlanElement; +import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; + +import java.util.List; + +public class DrtUtilityEstimator implements UtilityEstimator { + + private final ModeParameters modeParameters; + private final DrtPredictor drtPredictor; + + @Inject + public DrtUtilityEstimator(ModeParameters modeParameters, DrtPredictor drtPredictor) { + this.modeParameters = modeParameters; + this.drtPredictor = drtPredictor; + } + + protected double estimateConstantUtility() { + return this.modeParameters.drt.alpha_u; + } + + protected double estimateTravelTimeUtility(DrtVariables variables) { + return this.modeParameters.drt.betaTravelTime_u_min * variables.travelTime_min; + } + + protected double estimateWaitingTimeUtility(DrtVariables variables) { + return this.modeParameters.drt.betaWaitingTime_u_min * variables.waitingTime_min; + } + + protected double estimateMonetaryCostUtility(DrtVariables variables) { + return this.modeParameters.betaCost_u_MU * EstimatorUtils.interaction(variables.euclideanDistance_km, + this.modeParameters.referenceEuclideanDistance_km, this.modeParameters.lambdaCostEuclideanDistance) * variables.cost_MU; + } + + protected double estimateAccessEgressTimeUtility(DrtVariables variables) { + return this.modeParameters.drt.betaAccessEgressTime_u_min * variables.accessEgressTime_min; + } + + + @Override + public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { + DrtVariables variables = this.drtPredictor.predictVariables(person, trip, elements); + + double utility = 0.0; + + utility += estimateConstantUtility(); + utility += estimateTravelTimeUtility(variables); + utility += estimateWaitingTimeUtility(variables); + utility += estimateMonetaryCostUtility(variables); + utility += estimateAccessEgressTimeUtility(variables); + return utility; + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/variables/DrtVariables.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/variables/DrtVariables.java new file mode 100644 index 000000000..5d2610338 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/mode_choice/variables/DrtVariables.java @@ -0,0 +1,20 @@ +package org.eqasim.core.simulation.modes.drt.mode_choice.variables; + +import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; + +public class DrtVariables implements BaseVariables { + final public double travelTime_min; + final public double cost_MU; + final public double euclideanDistance_km; + final public double waitingTime_min; + final public double accessEgressTime_min; + + public DrtVariables(double travelTime_min, double cost_MU, double euclideanDistance_km, double waitingTime_min, + double accessEgressTime_min) { + this.travelTime_min = travelTime_min; + this.cost_MU = cost_MU; + this.euclideanDistance_km = euclideanDistance_km; + this.waitingTime_min = waitingTime_min; + this.accessEgressTime_min = accessEgressTime_min; + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/utils/AdaptConfigForDrt.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/utils/AdaptConfigForDrt.java new file mode 100644 index 000000000..00c37cd48 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/utils/AdaptConfigForDrt.java @@ -0,0 +1,172 @@ +package org.eqasim.core.simulation.modes.drt.utils; + +import org.eqasim.core.components.config.EqasimConfigGroup; +import org.eqasim.core.misc.ClassUtils; +import org.eqasim.core.simulation.EqasimConfigurator; +import org.eqasim.core.simulation.mode_choice.EqasimModeChoiceModule; +import org.matsim.contrib.drt.analysis.zonal.DrtZonalSystemParams; +import org.matsim.contrib.drt.optimizer.insertion.DrtInsertionSearchParams; +import org.matsim.contrib.drt.optimizer.insertion.extensive.ExtensiveInsertionSearchParams; +import org.matsim.contrib.drt.optimizer.rebalancing.RebalancingParams; +import org.matsim.contrib.drt.optimizer.rebalancing.plusOne.PlusOneRebalancingStrategyParams; +import org.matsim.contrib.drt.run.DrtConfigGroup; +import org.matsim.contrib.drt.run.DrtConfigs; +import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; +import org.matsim.contrib.dvrp.run.DvrpConfigGroup; +import org.matsim.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup; +import org.matsim.core.config.CommandLine; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.PlanCalcScoreConfigGroup; +import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.utils.misc.Time; + +import java.nio.file.Path; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class AdaptConfigForDrt { + + public static void adapt(Config config, Map vehiclesPathByDrtMode, Map operationalSchemes, Map drtUtilityEstimators, Map drtCostModels, String qsimEndtime, String modeAvailability) { + if(!config.getModules().containsKey(DvrpConfigGroup.GROUP_NAME)) { + config.addModule(new DvrpConfigGroup()); + } + if(!config.getModules().containsKey(MultiModeDrtConfigGroup.GROUP_NAME)) { + config.addModule(new MultiModeDrtConfigGroup()); + } + MultiModeDrtConfigGroup multiModeDrtConfigGroup = (MultiModeDrtConfigGroup) config.getModules().get(MultiModeDrtConfigGroup.GROUP_NAME); + + DiscreteModeChoiceConfigGroup dmcConfig = DiscreteModeChoiceConfigGroup.getOrCreate(config); + + // Add DRT to the available modes + if(modeAvailability != null) { + dmcConfig.setModeAvailability(modeAvailability); + } + + + // Add DRT to cached modes + Set cachedModes = new HashSet<>(dmcConfig.getCachedModes()); + cachedModes.addAll(vehiclesPathByDrtMode.keySet()); + dmcConfig.setCachedModes(cachedModes); + + Set tripConstraints = new HashSet<>(dmcConfig.getTripConstraints()); + tripConstraints.add(EqasimModeChoiceModule.DRT_WALK_CONSTRAINT); + dmcConfig.setTripConstraints(tripConstraints); + + for(String drtMode: vehiclesPathByDrtMode.keySet()) { + DrtConfigGroup drtConfigGroup = new DrtConfigGroup(); + drtConfigGroup.setMode(drtMode); + drtConfigGroup.setOperationalScheme(DrtConfigGroup.OperationalScheme.valueOf(operationalSchemes.get(drtMode))); + drtConfigGroup.setStopDuration(15.0); + drtConfigGroup.setMaxWaitTime(600); + drtConfigGroup.setMaxTravelTimeAlpha(1.5); + drtConfigGroup.setMaxTravelTimeBeta(300.0); + drtConfigGroup.setVehiclesFile(vehiclesPathByDrtMode.get(drtMode)); + + DrtInsertionSearchParams searchParams = new ExtensiveInsertionSearchParams(); + drtConfigGroup.addDrtInsertionSearchParams(searchParams); + + RebalancingParams rebalancingParams = new RebalancingParams(); + rebalancingParams.setInterval(1800); + rebalancingParams.addParameterSet(new PlusOneRebalancingStrategyParams()); + drtConfigGroup.addParameterSet(rebalancingParams); + + DrtZonalSystemParams drtZonalSystemParams = new DrtZonalSystemParams(); + drtZonalSystemParams.setZonesGeneration(DrtZonalSystemParams.ZoneGeneration.GridFromNetwork); + drtZonalSystemParams.setCellSize(500.0); + drtZonalSystemParams.setTargetLinkSelection(DrtZonalSystemParams.TargetLinkSelection.mostCentral); + drtConfigGroup.addParameterSet(drtZonalSystemParams); + + multiModeDrtConfigGroup.addDrtConfig(drtConfigGroup); + + // Set up choice model + EqasimConfigGroup eqasimConfig = EqasimConfigGroup.get(config); + eqasimConfig.setCostModel(drtMode, drtCostModels.get(drtMode)); + eqasimConfig.setEstimator(drtMode, drtUtilityEstimators.get(drtMode)); + + PlanCalcScoreConfigGroup.ModeParams modeParams = new PlanCalcScoreConfigGroup.ModeParams(drtMode); + config.planCalcScore().addModeParams(modeParams); + } + + DrtConfigs.adjustMultiModeDrtConfig(multiModeDrtConfigGroup, config.planCalcScore(), config.plansCalcRoute()); + + // Additional requirements + config.qsim().setStartTime(0.0); + config.qsim().setSimStarttimeInterpretation(QSimConfigGroup.StarttimeInterpretation.onlyUseStarttime); + config.qsim().setEndTime(Time.parseOptionalTime(qsimEndtime).seconds()); + config.qsim().setSimEndtimeInterpretation(QSimConfigGroup.EndtimeInterpretation.onlyUseEndtime); + + } + + private static Map> extractDrtInfo(String[] drtModeNames, Map values) { + Map> result = new HashMap<>(); + if(drtModeNames.length == 0) { + throw new IllegalStateException("No drt modes provided"); + } + for(String key: values.keySet()) { + String[] currentElements = values.get(key); + Map resultingMap; + + if(drtModeNames.length == currentElements.length) { + resultingMap = IntStream.range(0, drtModeNames.length).boxed().collect(Collectors.toMap(integer -> drtModeNames[integer], (Function) integer -> currentElements[integer])); + } else { + if(currentElements.length != 1) { + throw new IllegalStateException(String.format("When the number of provided drt mode names is not equal to the number of provided %s," + + " only one %s should be provided, it will be used for all the drt modes ", key, key)); + } + resultingMap = Arrays.stream(drtModeNames).collect(Collectors.toMap(mode -> mode, mode -> currentElements[0])); + } + result.put(key, resultingMap); + } + return result; + } + + public static void main(String[] args) throws CommandLine.ConfigurationException { + CommandLine cmd = new CommandLine.Builder(args) // + .requireOptions("input-config-path", "output-config-path", "vehicles-paths") + .allowOptions("mode-names") + .allowOptions("mode-availability") + .allowOptions("configurator-class") + .allowOptions("operational-schemes") + .allowOptions("cost-models", "estimators") + .allowOptions("qsim-endtime") + .build(); + + + String inputConfigPath = cmd.getOptionStrict("input-config-path"); + String outputConfigPath = cmd.getOptionStrict("output-config-path"); + String[] modeNames = Arrays.stream(cmd.getOption("mode-names").orElse("drt").split(",")).collect(Collectors.toSet()).toArray(String[]::new); + String[] vehiclesPath = cmd.getOptionStrict("vehicles-paths").split(","); + String qsimEndtime = cmd.getOption("qsim-endtime").orElse("30:00:00"); + String[] costModel = cmd.getOption("cost-models").orElse(EqasimModeChoiceModule.ZERO_COST_MODEL_NAME).split(","); + String[] estimator = cmd.getOption("estimators").orElse(EqasimModeChoiceModule.DRT_ESTIMATOR_NAME).split(","); + String[] operationalSchemes = cmd.getOption("operational-schemes").orElse(DrtConfigGroup.OperationalScheme.door2door.toString()).split(","); + + + Map toExtract = new HashMap<>(); + toExtract.put("vehicles-paths", Arrays.stream(vehiclesPath).map(p -> Path.of(outputConfigPath).getParent().toAbsolutePath().relativize(Path.of(p).toAbsolutePath()).toString()).toArray(String[]::new)); + toExtract.put("cost-models", costModel); + toExtract.put("estimators", estimator); + toExtract.put("operational-schemes", operationalSchemes); + + Map> info = extractDrtInfo(modeNames, toExtract); + + + EqasimConfigurator configurator; + if(cmd.hasOption("configurator-class")) { + configurator = ClassUtils.getInstanceOfClassExtendingOtherClass(cmd.getOptionStrict("configurator-class"), EqasimConfigurator.class); + } else { + configurator = new EqasimConfigurator(); + } + + Config config = ConfigUtils.loadConfig(inputConfigPath, configurator.getConfigGroups()); + + adapt(config, info.get("vehicles-paths"), info.get("operational-schemes"), info.get("estimators"), info.get("cost-models"), qsimEndtime, cmd.getOption("mode-availability").orElse(null)); + + cmd.applyConfiguration(config); + + ConfigUtils.writeConfig(config, outputConfigPath); + } +} \ No newline at end of file diff --git a/core/src/test/java/org/eqasim/TestSimulationPipeline.java b/core/src/test/java/org/eqasim/TestSimulationPipeline.java index 1eac60548..700d5f204 100644 --- a/core/src/test/java/org/eqasim/TestSimulationPipeline.java +++ b/core/src/test/java/org/eqasim/TestSimulationPipeline.java @@ -9,6 +9,8 @@ import org.eqasim.core.simulation.mode_choice.AbstractEqasimExtension; import org.eqasim.core.simulation.mode_choice.EqasimModeChoiceModule; import org.eqasim.core.simulation.mode_choice.parameters.ModeParameters; +import org.eqasim.core.simulation.modes.drt.utils.AdaptConfigForDrt; +import org.eqasim.core.simulation.modes.drt.utils.CreateDrtVehicles; import org.eqasim.core.tools.ExportNetworkToShapefile; import org.eqasim.core.tools.ExportTransitLinesToShapefile; import org.eqasim.core.tools.ExportTransitStopsToShapefile; @@ -27,9 +29,9 @@ import java.io.File; import java.io.IOException; +import java.net.MalformedURLException; import java.net.URL; -import java.util.HashSet; -import java.util.Set; +import java.util.*; public class TestSimulationPipeline { @@ -45,10 +47,11 @@ public void tearDown() throws IOException { FileUtils.deleteDirectory(new File("melun_test")); } - private void runMelunSimulation() { + private void runMelunSimulation(String configPath, String outputPath, Collection extraModes) { EqasimConfigurator eqasimConfigurator = new EqasimConfigurator(); - Config config = ConfigUtils.loadConfig("melun_test/input/config.xml", eqasimConfigurator.getConfigGroups()); - ((ControlerConfigGroup) config.getModules().get(ControlerConfigGroup.GROUP_NAME)).setOutputDirectory("melun_test/output"); + Config config = ConfigUtils.loadConfig(configPath, eqasimConfigurator.getConfigGroups()); + ((ControlerConfigGroup) config.getModules().get(ControlerConfigGroup.GROUP_NAME)).setOutputDirectory(outputPath); + eqasimConfigurator.addOptionalConfigGroups(config); Scenario scenario = ScenarioUtils.createScenario(config); eqasimConfigurator.configureScenario(scenario); @@ -75,6 +78,7 @@ protected void installEqasimExtension() { if(isCarPassenger) { modes.add("car_passenger"); } + modes.addAll(extraModes); return modes; }).asEagerSingleton(); } @@ -130,9 +134,35 @@ private void runShapefileExports() throws Exception { }); } + @Test + public void testDrt() throws MalformedURLException, CommandLine.ConfigurationException { + CreateDrtVehicles.main(new String[]{ + "--network-path", "melun_test/input/network.xml.gz", + "--output-vehicles-path", "melun_test/input/drt_vehicles_a.xml.gz", + "--vehicles-number", "50", + "--vehicle-id-prefix", "vehicle_drt_a_" + }); + + CreateDrtVehicles.main(new String[]{ + "--network-path", "melun_test/input/network.xml.gz", + "--output-vehicles-path", "melun_test/input/drt_vehicles_b.xml.gz", + "--vehicles-number", "50", + "--vehicle-id-prefix", "vehicle_drt_b_" + }); + + AdaptConfigForDrt.main(new String[] { + "--input-config-path", "melun_test/input/config.xml", + "--output-config-path", "melun_test/input/config_drt.xml", + "--mode-names", "drt_a,drt_b", + "--vehicles-paths", "melun_test/input/drt_vehicles_a.xml.gz,melun_test/input/drt_vehicles_b.xml.gz" + }); + + runMelunSimulation("melun_test/input/config_drt.xml", "melun_test/output_drt", List.of("drt_a", "drt_b")); + } + @Test public void testPipeline() throws Exception { - runMelunSimulation(); + runMelunSimulation("melun_test/input/config.xml", "melun_test/output", Collections.emptyList()); runAnalyses(); runShapefileExports(); } diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/RunCorsicaDrtSimulation.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/RunCorsicaDrtSimulation.java index 38a7d840d..69c99c01d 100644 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/RunCorsicaDrtSimulation.java +++ b/examples/src/main/java/org/eqasim/examples/corsica_drt/RunCorsicaDrtSimulation.java @@ -145,9 +145,6 @@ static public void main(String[] args) throws ConfigurationException { controller.addOverridingModule(new IDFModeChoiceModule(cmd)); { // Configure controller for DRT - controller.addOverridingModule(new DvrpModule()); - controller.addOverridingModule(new MultiModeDrtModule()); - controller.configureQSimComponents(components -> { DvrpQSimComponents.activateAllModes(multiModeDrtConfig).configure(components); From 40a0e360a9b4262edae66c1b95e3f6e15447b825 Mon Sep 17 00:00:00 2001 From: Tarek Chouaki Date: Sat, 16 Dec 2023 22:15:07 +0100 Subject: [PATCH 5/7] feat: Drt analysis --- .../analysis/EqasimAnalysisModule.java | 29 ++- .../drt/analysis/DrtAnalysisListener.java | 120 +++++++++++++ .../modes/drt/analysis/DrtAnalysisModule.java | 12 ++ .../drt/analysis/DrtPersonAnalysisFilter.java | 1 + .../dvrp_vehicles/VehicleActivityItem.java | 17 ++ .../VehicleAnalysisListener.java | 167 ++++++++++++++++++ .../dvrp_vehicles/VehicleAnalysisWriter.java | 93 ++++++++++ .../dvrp_vehicles/VehicleMovementItem.java | 19 ++ .../passengers/PassengerAnalysisListener.java | 113 ++++++++++++ .../passengers/PassengerAnalysisWriter.java | 59 +++++++ .../passengers/PassengerRideItem.java | 22 +++ .../analysis/run/RunDvrpVehicleAnalysis.java | 48 +++++ .../analysis/run/RunPassengerAnalysis.java | 52 ++++++ .../modes/drt/analysis/utils/LinkFinder.java | 27 +++ .../drt/analysis/utils/PassengerTracker.java | 54 ++++++ .../analysis/{ => utils}/VehicleRegistry.java | 2 +- 16 files changed, 833 insertions(+), 2 deletions(-) create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtAnalysisListener.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtAnalysisModule.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleActivityItem.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleAnalysisListener.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleAnalysisWriter.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleMovementItem.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/passengers/PassengerAnalysisListener.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/passengers/PassengerAnalysisWriter.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/passengers/PassengerRideItem.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/run/RunDvrpVehicleAnalysis.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/run/RunPassengerAnalysis.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/utils/LinkFinder.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/utils/PassengerTracker.java rename core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/{ => utils}/VehicleRegistry.java (92%) diff --git a/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java b/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java index 03af8c588..b66ffbc38 100644 --- a/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java +++ b/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java @@ -1,15 +1,21 @@ package org.eqasim.core.simulation.analysis; +import com.google.inject.Inject; +import com.google.inject.Provider; import org.eqasim.core.analysis.DefaultPersonAnalysisFilter; import org.eqasim.core.analysis.PersonAnalysisFilter; 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.components.config.EqasimConfigGroup; +import org.eqasim.core.simulation.modes.drt.analysis.DrtAnalysisListener; import org.eqasim.core.simulation.modes.drt.analysis.DrtPersonAnalysisFilter; -import org.eqasim.core.simulation.modes.drt.analysis.VehicleRegistry; +import org.eqasim.core.simulation.modes.drt.analysis.utils.VehicleRegistry; 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.controler.OutputDirectoryHierarchy; +import org.matsim.core.controler.listener.ControlerListener; import org.matsim.core.router.MainModeIdentifier; import org.matsim.pt.transitSchedule.api.TransitSchedule; @@ -23,6 +29,27 @@ public void install() { if(getConfig().getModules().containsKey(MultiModeDrtConfigGroup.GROUP_NAME)) { bind(VehicleRegistry.class).asEagerSingleton(); addEventHandlerBinding().to(VehicleRegistry.class); + //Using a static method as a provider causes it to be called even when the bind is not performed + //So to avoid the potential problems, we use the provider below + addControlerListenerBinding().toProvider(new Provider<>() { + + @Inject + EqasimConfigGroup config; + @Inject + MultiModeDrtConfigGroup drtConfig; + @Inject + OutputDirectoryHierarchy outputDirectory; + @Inject + Network network; + @Inject + VehicleRegistry vehicleRegistry; + + @Override + public ControlerListener get() { + return new DrtAnalysisListener(config, drtConfig, outputDirectory, network, vehicleRegistry); + } + }); + // Define filter for trip analysis bind(PersonAnalysisFilter.class).to(DrtPersonAnalysisFilter.class); } else { bind(DefaultPersonAnalysisFilter.class); diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtAnalysisListener.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtAnalysisListener.java new file mode 100644 index 000000000..b49131032 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtAnalysisListener.java @@ -0,0 +1,120 @@ +package org.eqasim.core.simulation.modes.drt.analysis; + +import com.google.inject.Singleton; +import org.eqasim.core.components.config.EqasimConfigGroup; +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; +import org.matsim.core.controler.events.IterationStartsEvent; +import org.matsim.core.controler.events.ShutdownEvent; +import org.matsim.core.controler.listener.IterationEndsListener; +import org.matsim.core.controler.listener.IterationStartsListener; +import org.matsim.core.controler.listener.ShutdownListener; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.util.stream.Collectors; + +@Singleton +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"; + + private final OutputDirectoryHierarchy outputDirectory; + + private final int analysisInterval; + private boolean isActive = false; + + private final PassengerAnalysisListener passengerAnalysisListener; + private final VehicleAnalysisListener vehicleAnalysisListener; + + 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.passengerAnalysisListener = new PassengerAnalysisListener( + drtConfig.getModalElements().stream().map(DrtConfigGroup::getMode).collect(Collectors.toSet()), linkFinder, + vehicleRegistry); + this.vehicleAnalysisListener = new VehicleAnalysisListener(linkFinder, vehicleRegistry); + } + + @Override + public void notifyIterationStarts(IterationStartsEvent event) { + if (analysisInterval > 0) { + isActive = event.getIteration() % analysisInterval == 0 || event.isLastIteration(); + } + + if (isActive) { + event.getServices().getEvents().addHandler(passengerAnalysisListener); + event.getServices().getEvents().addHandler(vehicleAnalysisListener); + } + } + + @Override + public void notifyIterationEnds(IterationEndsEvent event) { + try { + if (isActive) { + event.getServices().getEvents().removeHandler(passengerAnalysisListener); + + String path = outputDirectory.getIterationFilename(event.getIteration(), PASSENGER_RIDES_FILE_NAME); + new PassengerAnalysisWriter(passengerAnalysisListener).writeRides(new File(path)); + + event.getServices().getEvents().removeHandler(vehicleAnalysisListener); + + String movementsPath = outputDirectory.getIterationFilename(event.getIteration(), + VEHICLE_MOVEMENTS_FILE_NAME); + new VehicleAnalysisWriter(vehicleAnalysisListener).writeMovements(new File(movementsPath)); + + String activitiesPath = outputDirectory.getIterationFilename(event.getIteration(), + VEHICLE_ACTIVITIES_FILE_NAME); + new VehicleAnalysisWriter(vehicleAnalysisListener).writeActivities(new File(activitiesPath)); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + @Override + public void notifyShutdown(ShutdownEvent event) { + try { + File iterationPath = new File( + 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 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 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 exception) { + throw new RuntimeException(exception); + } + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtAnalysisModule.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtAnalysisModule.java new file mode 100644 index 000000000..2fad70889 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtAnalysisModule.java @@ -0,0 +1,12 @@ +package org.eqasim.core.simulation.modes.drt.analysis; + +import com.google.inject.Singleton; +import org.matsim.core.controler.AbstractModule; + +public class DrtAnalysisModule extends AbstractModule { + @Override + public void install() { + bind(DrtAnalysisListener.class).in(Singleton.class); + addControlerListenerBinding().to(DrtAnalysisListener.class); + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtPersonAnalysisFilter.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtPersonAnalysisFilter.java index c5079f0ed..55730bf34 100644 --- a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtPersonAnalysisFilter.java +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtPersonAnalysisFilter.java @@ -2,6 +2,7 @@ import com.google.inject.Inject; import org.eqasim.core.analysis.DefaultPersonAnalysisFilter; +import org.eqasim.core.simulation.modes.drt.analysis.utils.VehicleRegistry; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.population.Person; diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleActivityItem.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleActivityItem.java new file mode 100644 index 000000000..b5b06b651 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleActivityItem.java @@ -0,0 +1,17 @@ +package org.eqasim.core.simulation.modes.drt.analysis.dvrp_vehicles; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.vehicles.Vehicle; + +public class VehicleActivityItem { + public String mode; + + public Id vehicleId; + public Link link; + + public double startTime = Double.NaN; + public double endTime = Double.NaN; + + public String type; +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleAnalysisListener.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleAnalysisListener.java new file mode 100644 index 000000000..944d6ee94 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleAnalysisListener.java @@ -0,0 +1,167 @@ +package org.eqasim.core.simulation.modes.drt.analysis.dvrp_vehicles; + +import org.eqasim.core.simulation.modes.drt.analysis.utils.LinkFinder; +import org.eqasim.core.simulation.modes.drt.analysis.utils.PassengerTracker; +import org.eqasim.core.simulation.modes.drt.analysis.utils.VehicleRegistry; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.events.*; +import org.matsim.api.core.v01.events.handler.*; +import org.matsim.vehicles.Vehicle; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class VehicleAnalysisListener implements PersonDepartureEventHandler, PersonArrivalEventHandler, ActivityStartEventHandler, ActivityEndEventHandler, LinkEnterEventHandler, + PersonEntersVehicleEventHandler, PersonLeavesVehicleEventHandler { + private final LinkFinder linkFinder; + private final VehicleRegistry vehicleRegistry; + private final PassengerTracker passengers = new PassengerTracker(); + + private final List movements = new LinkedList<>(); + private final List activities = new LinkedList<>(); + + private final Map, VehicleMovementItem> currentMovements = new HashMap<>(); + private final Map, VehicleActivityItem> currentActivities = new HashMap<>(); + + public VehicleAnalysisListener(LinkFinder linkFinder, VehicleRegistry vehicleRegistry) { + this.linkFinder = linkFinder; + this.vehicleRegistry = vehicleRegistry; + } + + @Override + public void handleEvent(PersonDepartureEvent event) { + if (vehicleRegistry.isFleet(event.getPersonId())) { + String mode = vehicleRegistry.getMode(event.getPersonId()); + Id vehicleId = Id.createVehicleId(event.getPersonId()); + + VehicleMovementItem movement = new VehicleMovementItem(); + movements.add(movement); + + movement.mode = mode; + movement.vehicleId = vehicleId; + + movement.originLink = linkFinder.getLink(event.getLinkId()); + movement.departureTime = event.getTime(); + + currentMovements.put(vehicleId, movement); + } + } + + @Override + public void handleEvent(LinkEnterEvent event) { + if (vehicleRegistry.isFleet(event.getVehicleId())) { + VehicleMovementItem movement = currentMovements.get(event.getVehicleId()); + + if (movement == null) { + throw new IllegalStateException("Found link enter event without departure"); + } + + movement.distance += linkFinder.getDistance(event.getLinkId()); + } + } + + @Override + public void handleEvent(PersonEntersVehicleEvent event) { + if (!vehicleRegistry.isFleet(event.getPersonId())) { + if (vehicleRegistry.isFleet(event.getVehicleId())) { + passengers.addPassenger(event.getVehicleId(), event.getPersonId()); + } + } + } + + @Override + public void handleEvent(PersonLeavesVehicleEvent event) { + if (!vehicleRegistry.isFleet(event.getPersonId())) { + if (vehicleRegistry.isFleet(event.getVehicleId())) { + passengers.removePassenger(event.getVehicleId(), event.getPersonId()); + } + } + } + + @Override + public void handleEvent(PersonArrivalEvent event) { + if (vehicleRegistry.isFleet(event.getPersonId())) { + Id vehicleId = Id.createVehicleId(event.getPersonId()); + + VehicleMovementItem movement = currentMovements.remove(vehicleId); + + if (movement == null) { + throw new IllegalStateException("Found arrival without departure"); + } + + movement.destinationLink = linkFinder.getLink(event.getLinkId()); + movement.arrivalTime = event.getTime(); + + movement.numberOfPassengers = passengers.getNumberOfPassengers(vehicleId); + } + } + + @Override + public void handleEvent(ActivityStartEvent event) { + if (vehicleRegistry.isFleet(event.getPersonId())) { + String mode = vehicleRegistry.getMode(event.getPersonId()); + Id vehicleId = Id.createVehicleId(event.getPersonId()); + + VehicleActivityItem activity = new VehicleActivityItem(); + activities.add(activity); + + activity.mode = mode; + activity.vehicleId = vehicleId; + + activity.link = linkFinder.getLink(event.getLinkId()); + activity.type = event.getActType(); + + activity.startTime = event.getTime(); + + currentActivities.put(vehicleId, activity); + } + } + + @Override + public void handleEvent(ActivityEndEvent event) { + // Here we want to skip activity type 'BeforeVrpSchedule' + // Since the current version of the VehicleRegistry considers the vehicle to be part of the fleet only after the TaskStartedEvent + // It is safe to just check the vehicle against the fleet here. + if (vehicleRegistry.isFleet(event.getPersonId())) { + String mode = vehicleRegistry.getMode(event.getPersonId()); + Id vehicleId = Id.createVehicleId(event.getPersonId()); + + VehicleActivityItem activity = currentActivities.remove(vehicleId); + boolean isStarted = activity != null; + + if (!isStarted) { + activity = new VehicleActivityItem(); + activities.add(activity); + } + + activity.mode = mode; + activity.vehicleId = vehicleId; + + activity.link = linkFinder.getLink(event.getLinkId()); + activity.type = event.getActType(); + + activity.endTime = event.getTime(); + } + } + + @Override + public void reset(int iteration) { + passengers.clear(); + + currentActivities.clear(); + currentMovements.clear(); + + activities.clear(); + movements.clear(); + } + + public List getActivities() { + return activities; + } + + public List getMovements() { + return movements; + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleAnalysisWriter.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleAnalysisWriter.java new file mode 100644 index 000000000..41683a035 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleAnalysisWriter.java @@ -0,0 +1,93 @@ +package org.eqasim.core.simulation.modes.drt.analysis.dvrp_vehicles; + +import java.io.*; + +public class VehicleAnalysisWriter { + private final VehicleAnalysisListener listener; + + public VehicleAnalysisWriter(VehicleAnalysisListener listener) { + this.listener = listener; + } + + public void writeMovements(File path) throws IOException { + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path))); + + writer.write(String.join(";", new String[] { // + "operator_id", // + "vehicle_id", // + + "origin_link_id", // + "origin_x", // + "origin_y", // + + "destination_link_id", // + "destination_x", // + "destination_y", // + + "departure_time", // + "arrival_time", // + + "distance", // + "number_of_passengers" // + }) + "\n"); + + for (VehicleMovementItem movement : listener.getMovements()) { + writer.write(String.join(";", new String[] { // + String.valueOf(movement.mode), // + String.valueOf(movement.vehicleId), // + + String.valueOf(movement.originLink.getId()), // + String.valueOf(movement.originLink.getCoord().getX()), // + String.valueOf(movement.originLink.getCoord().getY()), // + + movement.destinationLink == null ? "null" : String.valueOf(movement.destinationLink.getId()), // + movement.destinationLink == null ? "NaN" : String.valueOf(movement.destinationLink.getCoord().getX()), // + movement.destinationLink == null ? "NaN" : String.valueOf(movement.destinationLink.getCoord().getY()), // + + String.valueOf(movement.departureTime), // + String.valueOf(movement.arrivalTime), // + + String.valueOf(movement.distance), // + String.valueOf(movement.numberOfPassengers) // + }) + "\n"); + } + + writer.close(); + } + + public void writeActivities(File path) throws IOException { + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path))); + + writer.write(String.join(";", new String[] { // + "operator_id", // + "vehicle_id", // + + "link_id", // + "x", // + "y", // + + "start_time", // + "end_time", // + + "type" // + }) + "\n"); + + for (VehicleActivityItem activity : listener.getActivities()) { + writer.write(String.join(";", new String[] { // + String.valueOf(activity.mode), // + String.valueOf(activity.vehicleId), // + + String.valueOf(activity.link.getId()), // + String.valueOf(activity.link.getCoord().getX()), // + String.valueOf(activity.link.getCoord().getY()), // + + String.valueOf(activity.startTime), // + String.valueOf(activity.endTime), // + + activity.type // + }) + "\n"); + } + + writer.close(); + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleMovementItem.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleMovementItem.java new file mode 100644 index 000000000..b79d72b3d --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/dvrp_vehicles/VehicleMovementItem.java @@ -0,0 +1,19 @@ +package org.eqasim.core.simulation.modes.drt.analysis.dvrp_vehicles; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.vehicles.Vehicle; + +public class VehicleMovementItem { + public String mode; + public Id vehicleId; + + public Link originLink; + public Link destinationLink; + + public double departureTime = Double.NaN; + public double arrivalTime = Double.NaN; + + public double distance = 0; + public int numberOfPassengers = 0; +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/passengers/PassengerAnalysisListener.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/passengers/PassengerAnalysisListener.java new file mode 100644 index 000000000..1cc0e0369 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/passengers/PassengerAnalysisListener.java @@ -0,0 +1,113 @@ +package org.eqasim.core.simulation.modes.drt.analysis.passengers; + +import org.eqasim.core.simulation.modes.drt.analysis.utils.LinkFinder; +import org.eqasim.core.simulation.modes.drt.analysis.utils.PassengerTracker; +import org.eqasim.core.simulation.modes.drt.analysis.utils.VehicleRegistry; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.events.*; +import org.matsim.api.core.v01.events.handler.*; +import org.matsim.api.core.v01.population.Person; + +import java.util.*; + +public class PassengerAnalysisListener implements PersonDepartureEventHandler, PersonArrivalEventHandler, + LinkEnterEventHandler, PersonEntersVehicleEventHandler, PersonLeavesVehicleEventHandler { + private final LinkFinder linkFinder; + private final VehicleRegistry vehicleRegistry; + private final Collection modes; + private final PassengerTracker passengers = new PassengerTracker(); + + private final List rides = new LinkedList<>(); + private final Map, PassengerRideItem> currentRides = new HashMap<>(); + + public PassengerAnalysisListener(Collection modes, LinkFinder linkFinder, VehicleRegistry vehicleRegistry) { + this.linkFinder = linkFinder; + this.modes = modes; + this.vehicleRegistry = vehicleRegistry; + } + + @Override + public void handleEvent(PersonDepartureEvent event) { + if (!vehicleRegistry.isFleet(event.getPersonId())) { + if (modes.contains(event.getLegMode())) { + PassengerRideItem ride = new PassengerRideItem(); + rides.add(ride); + + ride.personId = event.getPersonId(); + ride.mode = event.getLegMode(); + + ride.departureTime = event.getTime(); + ride.originLink = linkFinder.getLink(event.getLinkId()); + + currentRides.put(event.getPersonId(), ride); + } + } + } + + @Override + public void handleEvent(LinkEnterEvent event) { + if (vehicleRegistry.isFleet(event.getVehicleId())) { + double distance = linkFinder.getDistance(event.getLinkId()); + + for (Id passengerId : passengers.getPassengerIds(event.getVehicleId())) { + PassengerRideItem ride = currentRides.get(passengerId); + + if (ride == null) { + throw new IllegalStateException("Found vehicle enter link without departure"); + } + + ride.distance += distance; + } + } + } + + @Override + public void handleEvent(PersonEntersVehicleEvent event) { + if (!vehicleRegistry.isFleet(event.getPersonId())) { + if (vehicleRegistry.isFleet(event.getVehicleId())) { + PassengerRideItem ride = currentRides.get(event.getPersonId()); + + if (ride == null) { + throw new IllegalStateException("Found vehicle enter event without departure"); + } + + ride.vehicleId = event.getVehicleId(); + ride.waitingTime = event.getTime() - ride.departureTime; + + passengers.addPassenger(event.getVehicleId(), event.getPersonId()); + } + } + } + + @Override + public void handleEvent(PersonLeavesVehicleEvent event) { + if (!vehicleRegistry.isFleet(event.getPersonId())) { + if (vehicleRegistry.isFleet(event.getVehicleId())) { + passengers.removePassenger(event.getVehicleId(), event.getPersonId()); + } + } + } + + @Override + public void handleEvent(PersonArrivalEvent event) { + if (!vehicleRegistry.isFleet(event.getPersonId())) { + PassengerRideItem ride = currentRides.remove(event.getPersonId()); + + if (ride != null) { + ride.arrivalTime = event.getTime(); + ride.destinationLink = linkFinder.getLink(event.getLinkId()); + } + } + } + + @Override + public void reset(int iteration) { + passengers.clear(); + rides.clear(); + currentRides.clear(); + } + + public List getRides() { + return rides; + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/passengers/PassengerAnalysisWriter.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/passengers/PassengerAnalysisWriter.java new file mode 100644 index 000000000..60442089f --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/passengers/PassengerAnalysisWriter.java @@ -0,0 +1,59 @@ +package org.eqasim.core.simulation.modes.drt.analysis.passengers; + +import java.io.*; + +public class PassengerAnalysisWriter { + private final PassengerAnalysisListener listener; + + public PassengerAnalysisWriter(PassengerAnalysisListener listener) { + this.listener = listener; + } + + public void writeRides(File path) throws IOException { + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path))); + + writer.write(String.join(";", new String[] { // + "person_id", // + "operator_id", // + "vehicle_id", // + + "origin_link_id", // + "origin_x", // + "origin_y", // + + "destination_link_id", // + "destination_x", // + "destination_y", // + + "departure_time", // + "arrival_time", // + "waiting_time", // + + "distance" // + }) + "\n"); + + for (PassengerRideItem ride : listener.getRides()) { + writer.write(String.join(";", new String[] { // + String.valueOf(ride.personId), // + ride.mode == null ? "NaN" : String.valueOf(ride.mode), // + ride.vehicleId == null ? "NaN" : String.valueOf(ride.vehicleId), // + + ride.originLink == null ? "null" : String.valueOf(ride.originLink.getId()), // + ride.originLink == null ? "NaN" : String.valueOf(ride.originLink.getCoord().getX()), // + ride.originLink == null ? "NaN" : String.valueOf(ride.originLink.getCoord().getY()), // + + ride.destinationLink == null ? "null" : String.valueOf(ride.destinationLink.getId()), // + ride.destinationLink == null ? "NaN" : String.valueOf(ride.destinationLink.getCoord().getX()), // + ride.destinationLink == null ? "NaN" : String.valueOf(ride.destinationLink.getCoord().getY()), // + + String.valueOf(ride.departureTime), // + String.valueOf(ride.arrivalTime), // + String.valueOf(ride.waitingTime), // + + String.valueOf(ride.distance) // + }) + "\n"); + } + + writer.close(); + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/passengers/PassengerRideItem.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/passengers/PassengerRideItem.java new file mode 100644 index 000000000..81647d287 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/passengers/PassengerRideItem.java @@ -0,0 +1,22 @@ +package org.eqasim.core.simulation.modes.drt.analysis.passengers; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.population.Person; +import org.matsim.vehicles.Vehicle; + +public class PassengerRideItem { + public String mode; + + public Id personId; + public Id vehicleId; + + public Link originLink; + public Link destinationLink; + + public double departureTime = Double.NaN; + public double arrivalTime = Double.NaN; + public double waitingTime = Double.NaN; + + public double distance = 0.0; +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/run/RunDvrpVehicleAnalysis.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/run/RunDvrpVehicleAnalysis.java new file mode 100644 index 000000000..91dbf29cc --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/run/RunDvrpVehicleAnalysis.java @@ -0,0 +1,48 @@ +package org.eqasim.core.simulation.modes.drt.analysis.run; + +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.utils.LinkFinder; +import org.eqasim.core.simulation.modes.drt.analysis.utils.VehicleRegistry; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.api.experimental.events.EventsManager; +import org.matsim.core.config.CommandLine; +import org.matsim.core.config.CommandLine.ConfigurationException; +import org.matsim.core.events.EventsUtils; +import org.matsim.core.events.MatsimEventsReader; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.network.io.MatsimNetworkReader; + +import java.io.File; +import java.io.IOException; + +public class RunDvrpVehicleAnalysis { + static public void main(String[] args) throws ConfigurationException, IOException { + CommandLine cmd = new CommandLine.Builder(args) // + .requireOptions("events-path", "network-path", "movements-output-path", "activities-output-path") // + .build(); + + String eventsPath = cmd.getOptionStrict("events-path"); + String networkPath = cmd.getOptionStrict("network-path"); + String movementsOutputPath = cmd.getOptionStrict("movements-output-path"); + String activitiesOutputPath = cmd.getOptionStrict("activities-output-path"); + + Network network = NetworkUtils.createNetwork(); + new MatsimNetworkReader(network).readFile(networkPath); + + LinkFinder linkFinder = new LinkFinder(network); + VehicleRegistry vehicleRegistry = new VehicleRegistry(); + VehicleAnalysisListener listener = new VehicleAnalysisListener(linkFinder, vehicleRegistry); + + EventsManager eventsManager = EventsUtils.createEventsManager(); + eventsManager.addHandler(vehicleRegistry); + eventsManager.addHandler(listener); + + eventsManager.initProcessing(); + new MatsimEventsReader(eventsManager).readFile(eventsPath); + eventsManager.finishProcessing(); + + new VehicleAnalysisWriter(listener).writeMovements(new File(movementsOutputPath)); + new VehicleAnalysisWriter(listener).writeActivities(new File(activitiesOutputPath)); + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/run/RunPassengerAnalysis.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/run/RunPassengerAnalysis.java new file mode 100644 index 000000000..09cbf2679 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/run/RunPassengerAnalysis.java @@ -0,0 +1,52 @@ +package org.eqasim.core.simulation.modes.drt.analysis.run; + +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.core.api.experimental.events.EventsManager; +import org.matsim.core.config.CommandLine; +import org.matsim.core.config.CommandLine.ConfigurationException; +import org.matsim.core.events.EventsUtils; +import org.matsim.core.events.MatsimEventsReader; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.network.io.MatsimNetworkReader; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +public class RunPassengerAnalysis { + static public void main(String[] args) throws ConfigurationException, IOException { + CommandLine cmd = new CommandLine.Builder(args) // + .requireOptions("events-path", "network-path", "output-path", "modes") // + .build(); + + String eventsPath = cmd.getOptionStrict("events-path"); + String networkPath = cmd.getOptionStrict("network-path"); + String outputPath = cmd.getOptionStrict("output-path"); + + String rawModes = cmd.getOptionStrict("modes"); + Set modes = Arrays.asList(rawModes.split(",")).stream().map(String::trim).collect(Collectors.toSet()); + + Network network = NetworkUtils.createNetwork(); + new MatsimNetworkReader(network).readFile(networkPath); + + LinkFinder linkFinder = new LinkFinder(network); + VehicleRegistry vehicleRegistry = new VehicleRegistry(); + PassengerAnalysisListener listener = new PassengerAnalysisListener(modes, linkFinder, vehicleRegistry); + + EventsManager eventsManager = EventsUtils.createEventsManager(); + eventsManager.addHandler(vehicleRegistry); + eventsManager.addHandler(listener); + + eventsManager.initProcessing(); + new MatsimEventsReader(eventsManager).readFile(eventsPath); + eventsManager.finishProcessing(); + + new PassengerAnalysisWriter(listener).writeRides(new File(outputPath)); + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/utils/LinkFinder.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/utils/LinkFinder.java new file mode 100644 index 000000000..acf666d4b --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/utils/LinkFinder.java @@ -0,0 +1,27 @@ +package org.eqasim.core.simulation.modes.drt.analysis.utils; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; + +public class LinkFinder { + private final Network network; + + public LinkFinder(Network network) { + this.network = network; + } + + public Link getLink(Id linkId) { + Link link = network.getLinks().get(linkId); + + if (link == null) { + throw new IllegalStateException("Cannot find link: " + linkId); + } + + return link; + } + + public double getDistance(Id linkId) { + return getLink(linkId).getLength(); + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/utils/PassengerTracker.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/utils/PassengerTracker.java new file mode 100644 index 000000000..79b6841cb --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/utils/PassengerTracker.java @@ -0,0 +1,54 @@ +package org.eqasim.core.simulation.modes.drt.analysis.utils; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.population.Person; +import org.matsim.vehicles.Vehicle; + +import java.util.*; + +public class PassengerTracker { + private final Map, Set>> passengers = new HashMap<>(); + + private void ensurePassengers(Id vehicleId) { + if (!passengers.containsKey(vehicleId)) { + passengers.put(vehicleId, new HashSet<>()); + } + } + + public boolean hasPassenger(Id vehicleId, Id passengerId) { + ensurePassengers(vehicleId); + return passengers.get(vehicleId).contains(passengerId); + } + + public void addPassenger(Id vehicleId, Id passengerId) { + ensurePassengers(vehicleId); + + if (!passengers.get(vehicleId).add(passengerId)) { + throw new IllegalStateException(String.format("Passenger '%s' is already in vehicle '%s'", passengerId, vehicleId)); + } + } + + public void removePassenger(Id vehicleId, Id passengerId) { + ensurePassengers(vehicleId); + + if (!passengers.get(vehicleId).remove(passengerId)) { + throw new IllegalStateException(String.format("Passenger '%s' is not in vehicle '%s'", passengerId, vehicleId)); + } + } + + public int getNumberOfPassengers(Id vehicleId) { + ensurePassengers(vehicleId); + return passengers.get(vehicleId).size(); + } + + public Collection> getPassengerIds(Id vehicleId) { + ensurePassengers(vehicleId); + return passengers.get(vehicleId); + } + + public void clear() { + for (Set> passengerList : passengers.values()) { + passengerList.clear(); + } + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/VehicleRegistry.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/utils/VehicleRegistry.java similarity index 92% rename from core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/VehicleRegistry.java rename to core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/utils/VehicleRegistry.java index a3098b144..d9c61bb2c 100644 --- a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/VehicleRegistry.java +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/utils/VehicleRegistry.java @@ -1,4 +1,4 @@ -package org.eqasim.core.simulation.modes.drt.analysis; +package org.eqasim.core.simulation.modes.drt.analysis.utils; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.IdMap; From 59bdc22905d19f3a8d910a5c75aa0ce419feaa79 Mon Sep 17 00:00:00 2001 From: Tarek Chouaki Date: Mon, 15 Jan 2024 11:32:24 +0100 Subject: [PATCH 6/7] feat: DrtAnalysisModule is used properly now --- .../analysis/EqasimAnalysisModule.java | 37 +++---------------- .../modes/drt/analysis/DrtAnalysisModule.java | 17 ++++++++- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java b/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java index b66ffbc38..b63660316 100644 --- a/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java +++ b/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java @@ -1,57 +1,30 @@ package org.eqasim.core.simulation.analysis; -import com.google.inject.Inject; -import com.google.inject.Provider; import org.eqasim.core.analysis.DefaultPersonAnalysisFilter; import org.eqasim.core.analysis.PersonAnalysisFilter; 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.components.config.EqasimConfigGroup; -import org.eqasim.core.simulation.modes.drt.analysis.DrtAnalysisListener; -import org.eqasim.core.simulation.modes.drt.analysis.DrtPersonAnalysisFilter; -import org.eqasim.core.simulation.modes.drt.analysis.utils.VehicleRegistry; +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.controler.OutputDirectoryHierarchy; -import org.matsim.core.controler.listener.ControlerListener; 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); if(getConfig().getModules().containsKey(MultiModeDrtConfigGroup.GROUP_NAME)) { - bind(VehicleRegistry.class).asEagerSingleton(); - addEventHandlerBinding().to(VehicleRegistry.class); - //Using a static method as a provider causes it to be called even when the bind is not performed - //So to avoid the potential problems, we use the provider below - addControlerListenerBinding().toProvider(new Provider<>() { - - @Inject - EqasimConfigGroup config; - @Inject - MultiModeDrtConfigGroup drtConfig; - @Inject - OutputDirectoryHierarchy outputDirectory; - @Inject - Network network; - @Inject - VehicleRegistry vehicleRegistry; - - @Override - public ControlerListener get() { - return new DrtAnalysisListener(config, drtConfig, outputDirectory, network, vehicleRegistry); - } - }); - // Define filter for trip analysis - bind(PersonAnalysisFilter.class).to(DrtPersonAnalysisFilter.class); + 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); } diff --git a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtAnalysisModule.java b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtAnalysisModule.java index 2fad70889..9027c78c2 100644 --- a/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtAnalysisModule.java +++ b/core/src/main/java/org/eqasim/core/simulation/modes/drt/analysis/DrtAnalysisModule.java @@ -1,12 +1,27 @@ package org.eqasim.core.simulation.modes.drt.analysis; +import com.google.inject.Provides; import com.google.inject.Singleton; +import org.eqasim.core.analysis.PersonAnalysisFilter; +import org.eqasim.core.components.config.EqasimConfigGroup; +import org.eqasim.core.simulation.modes.drt.analysis.utils.VehicleRegistry; +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.controler.OutputDirectoryHierarchy; public class DrtAnalysisModule extends AbstractModule { @Override public void install() { - bind(DrtAnalysisListener.class).in(Singleton.class); addControlerListenerBinding().to(DrtAnalysisListener.class); + bind(VehicleRegistry.class).asEagerSingleton(); + addEventHandlerBinding().to(VehicleRegistry.class); + bind(PersonAnalysisFilter.class).to(DrtPersonAnalysisFilter.class); + } + + @Provides + @Singleton + public DrtAnalysisListener provideDrtAnalysisListener(EqasimConfigGroup eqasimConfig, MultiModeDrtConfigGroup drtConfig, OutputDirectoryHierarchy outputDirectoryHierarchy, Network network, VehicleRegistry vehicleRegistry) { + return new DrtAnalysisListener(eqasimConfig, drtConfig, outputDirectoryHierarchy, network, vehicleRegistry); } } From 0ca7cb82b21c04aea0a9d26d406b58a0ed0312cc Mon Sep 17 00:00:00 2001 From: Tarek Chouaki Date: Mon, 15 Jan 2024 11:34:05 +0100 Subject: [PATCH 7/7] refractor: removed redundant classes --- .../corsica_drt/CorsicaDrtModule.java | 25 +-- .../corsica_drt/RunCorsicaDrtSimulation.java | 6 +- .../analysis/DvrpAnalsisModule.java | 13 -- .../analysis/DvrpAnalysisListener.java | 124 ------------ .../passengers/PassengerAnalysisListener.java | 125 ------------- .../passengers/PassengerAnalysisWriter.java | 63 ------- .../passengers/PassengerRideItem.java | 22 --- .../analysis/run/RunPassengerAnalysis.java | 52 ------ .../analysis/run/RunVehicleAnalysis.java | 48 ----- .../analysis/utils/LinkFinder.java | 27 --- .../analysis/utils/PassengerTracker.java | 58 ------ .../analysis/utils/VehicleRegistry.java | 24 --- .../vehicles/VehicleActivityItem.java | 17 -- .../vehicles/VehicleAnalysisListener.java | 176 ------------------ .../vehicles/VehicleAnalysisWriter.java | 97 ---------- .../vehicles/VehicleMovementItem.java | 19 -- .../parameters/CorsicaDrtModeParameters.java | 61 ------ .../mode_choice/utilities/DrtPredictor.java | 58 ------ .../utilities/DrtUtilityEstimator.java | 59 ------ .../mode_choice/utilities/DrtVariables.java | 20 -- 20 files changed, 6 insertions(+), 1088 deletions(-) delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/DvrpAnalsisModule.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/DvrpAnalysisListener.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/passengers/PassengerAnalysisListener.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/passengers/PassengerAnalysisWriter.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/passengers/PassengerRideItem.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/run/RunPassengerAnalysis.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/run/RunVehicleAnalysis.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/utils/LinkFinder.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/utils/PassengerTracker.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/utils/VehicleRegistry.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleActivityItem.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleAnalysisListener.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleAnalysisWriter.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleMovementItem.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/parameters/CorsicaDrtModeParameters.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/utilities/DrtPredictor.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/utilities/DrtUtilityEstimator.java delete mode 100644 examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/utilities/DrtVariables.java diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/CorsicaDrtModule.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/CorsicaDrtModule.java index 1c9d277a3..88d06f8ee 100644 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/CorsicaDrtModule.java +++ b/examples/src/main/java/org/eqasim/examples/corsica_drt/CorsicaDrtModule.java @@ -8,15 +8,13 @@ import org.eqasim.core.simulation.mode_choice.AbstractEqasimExtension; import org.eqasim.core.simulation.mode_choice.ParameterDefinition; import org.eqasim.core.simulation.mode_choice.cost.CostModel; -import org.eqasim.core.simulation.mode_choice.parameters.ModeParameters; +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.eqasim.examples.corsica_drt.mode_choice.CorsicaDrtModeAvailability; import org.eqasim.examples.corsica_drt.mode_choice.cost.DrtCostModel; import org.eqasim.examples.corsica_drt.mode_choice.parameters.CorsicaDrtCostParameters; -import org.eqasim.examples.corsica_drt.mode_choice.parameters.CorsicaDrtModeParameters; -import org.eqasim.examples.corsica_drt.mode_choice.utilities.DrtPredictor; -import org.eqasim.examples.corsica_drt.mode_choice.utilities.DrtUtilityEstimator; import org.eqasim.ile_de_france.mode_choice.parameters.IDFCostParameters; -import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; import org.matsim.core.config.CommandLine; import com.google.inject.Provider; @@ -39,14 +37,12 @@ protected void installEqasimExtension() { // Configure choice alternative for DRT bindUtilityEstimator("drt").to(DrtUtilityEstimator.class); bindCostModel("drt").to(DrtCostModel.class); - bind(DrtPredictor.class); + bind(DrtPredictor.class).to(DefaultDrtPredictor.class); // Define filter for trip analysis bind(PersonAnalysisFilter.class).to(DrtPersonAnalysisFilter.class); // Override parameter bindings - bind(ModeParameters.class).to(CorsicaDrtModeParameters.class); - bind(IDFModeParameters.class).to(CorsicaDrtModeParameters.class); bind(IDFCostParameters.class).to(CorsicaDrtCostParameters.class); } @@ -69,19 +65,6 @@ public CorsicaDrtCostParameters provideCostParameters(EqasimConfigGroup config) return parameters; } - @Provides - @Singleton - public CorsicaDrtModeParameters provideModeParameters(EqasimConfigGroup config) { - CorsicaDrtModeParameters parameters = CorsicaDrtModeParameters.buildDefault(); - - if (config.getModeParametersPath() != null) { - ParameterDefinition.applyFile(new File(config.getModeParametersPath()), parameters); - } - - ParameterDefinition.applyCommandLine("mode-parameter", commandLine, parameters); - return parameters; - } - @Provides @Named("drt") public CostModel provideCarCostModel(Map> factory, EqasimConfigGroup config) { diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/RunCorsicaDrtSimulation.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/RunCorsicaDrtSimulation.java index 69c99c01d..4ae8e557a 100644 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/RunCorsicaDrtSimulation.java +++ b/examples/src/main/java/org/eqasim/examples/corsica_drt/RunCorsicaDrtSimulation.java @@ -9,7 +9,7 @@ import org.eqasim.core.components.transit.EqasimTransitQSimModule; import org.eqasim.core.simulation.analysis.EqasimAnalysisModule; import org.eqasim.core.simulation.mode_choice.EqasimModeChoiceModule; -import org.eqasim.examples.corsica_drt.analysis.DvrpAnalsisModule; +import org.eqasim.core.simulation.modes.drt.analysis.DrtAnalysisModule; import org.eqasim.examples.corsica_drt.mode_choice.CorsicaDrtModeAvailability; import org.eqasim.examples.corsica_drt.rejections.RejectionConstraint; import org.eqasim.examples.corsica_drt.rejections.RejectionModule; @@ -24,9 +24,7 @@ import org.matsim.contrib.drt.run.DrtConfigGroup.OperationalScheme; import org.matsim.contrib.drt.run.DrtConfigs; 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.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup; import org.matsim.core.config.CommandLine; @@ -156,7 +154,7 @@ static public void main(String[] args) throws ConfigurationException { { // Add overrides for Corsica + DRT controller.addOverridingModule(new CorsicaDrtModule(cmd)); controller.addOverridingModule(new RejectionModule(Arrays.asList("drt"))); - controller.addOverridingModule(new DvrpAnalsisModule()); + controller.addOverridingModule(new DrtAnalysisModule()); } controller.run(); diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/DvrpAnalsisModule.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/DvrpAnalsisModule.java deleted file mode 100644 index c594d27b2..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/DvrpAnalsisModule.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.eqasim.examples.corsica_drt.analysis; - -import org.matsim.core.controler.AbstractModule; - -import com.google.inject.Singleton; - -public class DvrpAnalsisModule extends AbstractModule { - @Override - public void install() { - bind(DvrpAnalysisListener.class).in(Singleton.class); - addControlerListenerBinding().to(DvrpAnalysisListener.class); - } -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/DvrpAnalysisListener.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/DvrpAnalysisListener.java deleted file mode 100644 index 438536607..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/DvrpAnalysisListener.java +++ /dev/null @@ -1,124 +0,0 @@ -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; - -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.matsim.api.core.v01.network.Network; -import org.matsim.contrib.drt.run.MultiModeDrtConfigGroup; -import org.matsim.core.controler.OutputDirectoryHierarchy; -import org.matsim.core.controler.events.IterationEndsEvent; -import org.matsim.core.controler.events.IterationStartsEvent; -import org.matsim.core.controler.events.ShutdownEvent; -import org.matsim.core.controler.listener.IterationEndsListener; -import org.matsim.core.controler.listener.IterationStartsListener; -import org.matsim.core.controler.listener.ShutdownListener; - -import com.google.inject.Inject; -import com.google.inject.Singleton; - -@Singleton -public class DvrpAnalysisListener 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"; - - private final OutputDirectoryHierarchy outputDirectory; - - private final int analysisInterval; - private boolean isActive = false; - - private final PassengerAnalysisListener passengerAnalysisListener; - private final VehicleAnalysisListener vehicleAnalysisListener; - - private final VehicleRegistry vehicleRegistry; - - @Inject - public DvrpAnalysisListener(EqasimConfigGroup config, MultiModeDrtConfigGroup drtConfig, - OutputDirectoryHierarchy outputDirectory, Network network) { - 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, - vehicleRegistry); - this.vehicleAnalysisListener = new VehicleAnalysisListener(linkFinder, vehicleRegistry); - } - - @Override - public void notifyIterationStarts(IterationStartsEvent event) { - if (analysisInterval > 0) { - isActive = event.getIteration() % analysisInterval == 0 || event.isLastIteration(); - } - - 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); - new PassengerAnalysisWriter(passengerAnalysisListener).writeRides(new File(path)); - - event.getServices().getEvents().removeHandler(vehicleAnalysisListener); - - String movementsPath = outputDirectory.getIterationFilename(event.getIteration(), - VEHICLE_MOVEMENTS_FILE_NAME); - new VehicleAnalysisWriter(vehicleAnalysisListener).writeMovements(new File(movementsPath)); - - String activitiesPath = outputDirectory.getIterationFilename(event.getIteration(), - VEHICLE_ACTIVITIES_FILE_NAME); - new VehicleAnalysisWriter(vehicleAnalysisListener).writeActivities(new File(activitiesPath)); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - @Override - public void notifyShutdown(ShutdownEvent event) { - try { - File iterationPath = new File( - 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) { - } - - 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) { - } - - 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) { - } - } -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/passengers/PassengerAnalysisListener.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/passengers/PassengerAnalysisListener.java deleted file mode 100644 index 26122c46c..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/passengers/PassengerAnalysisListener.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.eqasim.examples.corsica_drt.analysis.passengers; - -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.eqasim.examples.corsica_drt.analysis.utils.LinkFinder; -import org.eqasim.examples.corsica_drt.analysis.utils.PassengerTracker; -import org.eqasim.examples.corsica_drt.analysis.utils.VehicleRegistry; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.events.LinkEnterEvent; -import org.matsim.api.core.v01.events.PersonArrivalEvent; -import org.matsim.api.core.v01.events.PersonDepartureEvent; -import org.matsim.api.core.v01.events.PersonEntersVehicleEvent; -import org.matsim.api.core.v01.events.PersonLeavesVehicleEvent; -import org.matsim.api.core.v01.events.handler.LinkEnterEventHandler; -import org.matsim.api.core.v01.events.handler.PersonArrivalEventHandler; -import org.matsim.api.core.v01.events.handler.PersonDepartureEventHandler; -import org.matsim.api.core.v01.events.handler.PersonEntersVehicleEventHandler; -import org.matsim.api.core.v01.events.handler.PersonLeavesVehicleEventHandler; -import org.matsim.api.core.v01.population.Person; - -public class PassengerAnalysisListener implements PersonDepartureEventHandler, PersonArrivalEventHandler, - LinkEnterEventHandler, PersonEntersVehicleEventHandler, PersonLeavesVehicleEventHandler { - private final LinkFinder linkFinder; - private final VehicleRegistry vehicleRegistry; - private final Collection modes; - private final PassengerTracker passengers = new PassengerTracker(); - - private final List rides = new LinkedList<>(); - private final Map, PassengerRideItem> currentRides = new HashMap<>(); - - public PassengerAnalysisListener(Collection modes, LinkFinder linkFinder, VehicleRegistry vehicleRegistry) { - this.linkFinder = linkFinder; - this.modes = modes; - this.vehicleRegistry = vehicleRegistry; - } - - @Override - public void handleEvent(PersonDepartureEvent event) { - if (!vehicleRegistry.isFleet(event.getPersonId())) { - if (modes.contains(event.getLegMode())) { - PassengerRideItem ride = new PassengerRideItem(); - rides.add(ride); - - ride.personId = event.getPersonId(); - ride.mode = event.getLegMode(); - - ride.departureTime = event.getTime(); - ride.originLink = linkFinder.getLink(event.getLinkId()); - - currentRides.put(event.getPersonId(), ride); - } - } - } - - @Override - public void handleEvent(LinkEnterEvent event) { - if (vehicleRegistry.isFleet(event.getVehicleId())) { - double distance = linkFinder.getDistance(event.getLinkId()); - - for (Id passengerId : passengers.getPassengerIds(event.getVehicleId())) { - PassengerRideItem ride = currentRides.get(passengerId); - - if (ride == null) { - throw new IllegalStateException("Found vehicle enter link without departure"); - } - - ride.distance += distance; - } - } - } - - @Override - public void handleEvent(PersonEntersVehicleEvent event) { - if (!vehicleRegistry.isFleet(event.getPersonId())) { - if (vehicleRegistry.isFleet(event.getVehicleId())) { - PassengerRideItem ride = currentRides.get(event.getPersonId()); - - if (ride == null) { - throw new IllegalStateException("Found vehicle enter event without departure"); - } - - ride.vehicleId = event.getVehicleId(); - ride.waitingTime = event.getTime() - ride.departureTime; - - passengers.addPassenger(event.getVehicleId(), event.getPersonId()); - } - } - } - - @Override - public void handleEvent(PersonLeavesVehicleEvent event) { - if (!vehicleRegistry.isFleet(event.getPersonId())) { - if (vehicleRegistry.isFleet(event.getVehicleId())) { - passengers.removePassenger(event.getVehicleId(), event.getPersonId()); - } - } - } - - @Override - public void handleEvent(PersonArrivalEvent event) { - if (!vehicleRegistry.isFleet(event.getPersonId())) { - PassengerRideItem ride = currentRides.remove(event.getPersonId()); - - if (ride != null) { - ride.arrivalTime = event.getTime(); - ride.destinationLink = linkFinder.getLink(event.getLinkId()); - } - } - } - - @Override - public void reset(int iteration) { - passengers.clear(); - rides.clear(); - currentRides.clear(); - } - - public List getRides() { - return rides; - } -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/passengers/PassengerAnalysisWriter.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/passengers/PassengerAnalysisWriter.java deleted file mode 100644 index 3dc814657..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/passengers/PassengerAnalysisWriter.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.eqasim.examples.corsica_drt.analysis.passengers; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; - -public class PassengerAnalysisWriter { - private final PassengerAnalysisListener listener; - - public PassengerAnalysisWriter(PassengerAnalysisListener listener) { - this.listener = listener; - } - - public void writeRides(File path) throws IOException { - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path))); - - writer.write(String.join(";", new String[] { // - "person_id", // - "operator_id", // - "vehicle_id", // - - "origin_link_id", // - "origin_x", // - "origin_y", // - - "destination_link_id", // - "destination_x", // - "destination_y", // - - "departure_time", // - "arrival_time", // - "waiting_time", // - - "distance" // - }) + "\n"); - - for (PassengerRideItem ride : listener.getRides()) { - writer.write(String.join(";", new String[] { // - String.valueOf(ride.personId), // - ride.mode == null ? "NaN" : String.valueOf(ride.mode), // - ride.vehicleId == null ? "NaN" : String.valueOf(ride.vehicleId), // - - ride.originLink == null ? "null" : String.valueOf(ride.originLink.getId()), // - ride.originLink == null ? "NaN" : String.valueOf(ride.originLink.getCoord().getX()), // - ride.originLink == null ? "NaN" : String.valueOf(ride.originLink.getCoord().getY()), // - - ride.destinationLink == null ? "null" : String.valueOf(ride.destinationLink.getId()), // - ride.destinationLink == null ? "NaN" : String.valueOf(ride.destinationLink.getCoord().getX()), // - ride.destinationLink == null ? "NaN" : String.valueOf(ride.destinationLink.getCoord().getY()), // - - String.valueOf(ride.departureTime), // - String.valueOf(ride.arrivalTime), // - String.valueOf(ride.waitingTime), // - - String.valueOf(ride.distance) // - }) + "\n"); - } - - writer.close(); - } -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/passengers/PassengerRideItem.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/passengers/PassengerRideItem.java deleted file mode 100644 index 8da7877e4..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/passengers/PassengerRideItem.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.eqasim.examples.corsica_drt.analysis.passengers; - -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.network.Link; -import org.matsim.api.core.v01.population.Person; -import org.matsim.vehicles.Vehicle; - -public class PassengerRideItem { - public String mode; - - public Id personId; - public Id vehicleId; - - public Link originLink; - public Link destinationLink; - - public double departureTime = Double.NaN; - public double arrivalTime = Double.NaN; - public double waitingTime = Double.NaN; - - public double distance = 0.0; -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/run/RunPassengerAnalysis.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/run/RunPassengerAnalysis.java deleted file mode 100644 index a59bf302a..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/run/RunPassengerAnalysis.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.eqasim.examples.corsica_drt.analysis.run; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.Set; -import java.util.stream.Collectors; - -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.matsim.api.core.v01.network.Network; -import org.matsim.core.api.experimental.events.EventsManager; -import org.matsim.core.config.CommandLine; -import org.matsim.core.config.CommandLine.ConfigurationException; -import org.matsim.core.events.EventsUtils; -import org.matsim.core.events.MatsimEventsReader; -import org.matsim.core.network.NetworkUtils; -import org.matsim.core.network.io.MatsimNetworkReader; - -public class RunPassengerAnalysis { - static public void main(String[] args) throws ConfigurationException, IOException { - CommandLine cmd = new CommandLine.Builder(args) // - .requireOptions("events-path", "network-path", "output-path", "modes") // - .build(); - - String eventsPath = cmd.getOptionStrict("events-path"); - String networkPath = cmd.getOptionStrict("network-path"); - String outputPath = cmd.getOptionStrict("output-path"); - - String rawModes = cmd.getOptionStrict("modes"); - Set modes = Arrays.asList(rawModes.split(",")).stream().map(String::trim).collect(Collectors.toSet()); - - Network network = NetworkUtils.createNetwork(); - new MatsimNetworkReader(network).readFile(networkPath); - - LinkFinder linkFinder = new LinkFinder(network); - VehicleRegistry vehicleRegistry = new VehicleRegistry(); - PassengerAnalysisListener listener = new PassengerAnalysisListener(modes, linkFinder, vehicleRegistry); - - EventsManager eventsManager = EventsUtils.createEventsManager(); - eventsManager.addHandler(vehicleRegistry); - eventsManager.addHandler(listener); - - eventsManager.initProcessing(); - new MatsimEventsReader(eventsManager).readFile(eventsPath); - eventsManager.finishProcessing(); - - new PassengerAnalysisWriter(listener).writeRides(new File(outputPath)); - } -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/run/RunVehicleAnalysis.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/run/RunVehicleAnalysis.java deleted file mode 100644 index 5b1c1a43e..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/run/RunVehicleAnalysis.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.eqasim.examples.corsica_drt.analysis.run; - -import java.io.File; -import java.io.IOException; - -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.matsim.api.core.v01.network.Network; -import org.matsim.core.api.experimental.events.EventsManager; -import org.matsim.core.config.CommandLine; -import org.matsim.core.config.CommandLine.ConfigurationException; -import org.matsim.core.events.EventsUtils; -import org.matsim.core.events.MatsimEventsReader; -import org.matsim.core.network.NetworkUtils; -import org.matsim.core.network.io.MatsimNetworkReader; - -public class RunVehicleAnalysis { - static public void main(String[] args) throws ConfigurationException, IOException { - CommandLine cmd = new CommandLine.Builder(args) // - .requireOptions("events-path", "network-path", "movements-output-path", "activities-output-path") // - .build(); - - String eventsPath = cmd.getOptionStrict("events-path"); - String networkPath = cmd.getOptionStrict("network-path"); - String movementsOutputPath = cmd.getOptionStrict("movements-output-path"); - String activitiesOutputPath = cmd.getOptionStrict("activities-output-path"); - - Network network = NetworkUtils.createNetwork(); - new MatsimNetworkReader(network).readFile(networkPath); - - LinkFinder linkFinder = new LinkFinder(network); - VehicleRegistry vehicleRegistry = new VehicleRegistry(); - VehicleAnalysisListener listener = new VehicleAnalysisListener(linkFinder, vehicleRegistry); - - EventsManager eventsManager = EventsUtils.createEventsManager(); - eventsManager.addHandler(vehicleRegistry); - eventsManager.addHandler(listener); - - eventsManager.initProcessing(); - new MatsimEventsReader(eventsManager).readFile(eventsPath); - eventsManager.finishProcessing(); - - new VehicleAnalysisWriter(listener).writeMovements(new File(movementsOutputPath)); - new VehicleAnalysisWriter(listener).writeActivities(new File(activitiesOutputPath)); - } -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/utils/LinkFinder.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/utils/LinkFinder.java deleted file mode 100644 index e3cb3037a..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/utils/LinkFinder.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.eqasim.examples.corsica_drt.analysis.utils; - -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.network.Link; -import org.matsim.api.core.v01.network.Network; - -public class LinkFinder { - private final Network network; - - public LinkFinder(Network network) { - this.network = network; - } - - public Link getLink(Id linkId) { - Link link = network.getLinks().get(linkId); - - if (link == null) { - throw new IllegalStateException("Cannot find link: " + linkId); - } - - return link; - } - - public double getDistance(Id linkId) { - return getLink(linkId).getLength(); - } -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/utils/PassengerTracker.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/utils/PassengerTracker.java deleted file mode 100644 index 16c8eb8b7..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/utils/PassengerTracker.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.eqasim.examples.corsica_drt.analysis.utils; - -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.population.Person; -import org.matsim.vehicles.Vehicle; - -public class PassengerTracker { - private final Map, Set>> passengers = new HashMap<>(); - - private void ensurePassengers(Id vehicleId) { - if (!passengers.containsKey(vehicleId)) { - passengers.put(vehicleId, new HashSet<>()); - } - } - - public boolean hasPassenger(Id vehicleId, Id passengerId) { - ensurePassengers(vehicleId); - return passengers.get(vehicleId).contains(passengerId); - } - - public void addPassenger(Id vehicleId, Id passengerId) { - ensurePassengers(vehicleId); - - if (!passengers.get(vehicleId).add(passengerId)) { - throw new IllegalStateException(String.format("Passenger '%s' is already in vehicle '%s'", passengerId, vehicleId)); - } - } - - public void removePassenger(Id vehicleId, Id passengerId) { - ensurePassengers(vehicleId); - - if (!passengers.get(vehicleId).remove(passengerId)) { - throw new IllegalStateException(String.format("Passenger '%s' is not in vehicle '%s'", passengerId, vehicleId)); - } - } - - public int getNumberOfPassengers(Id vehicleId) { - ensurePassengers(vehicleId); - return passengers.get(vehicleId).size(); - } - - public Collection> getPassengerIds(Id vehicleId) { - ensurePassengers(vehicleId); - return passengers.get(vehicleId); - } - - public void clear() { - for (Set> passengerList : passengers.values()) { - passengerList.clear(); - } - } -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/utils/VehicleRegistry.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/utils/VehicleRegistry.java deleted file mode 100644 index 8a6833b8d..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/utils/VehicleRegistry.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.eqasim.examples.corsica_drt.analysis.utils; - -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.IdMap; -import org.matsim.contrib.dvrp.fleet.DvrpVehicle; -import org.matsim.contrib.dvrp.vrpagent.TaskStartedEvent; -import org.matsim.contrib.dvrp.vrpagent.TaskStartedEventHandler; - -public class VehicleRegistry implements TaskStartedEventHandler { - private final IdMap vehicleModes = new IdMap<>(DvrpVehicle.class); - - @Override - public void handleEvent(TaskStartedEvent event) { - vehicleModes.computeIfAbsent(event.getDvrpVehicleId(), id -> event.getDvrpMode()); - } - - public boolean isFleet(Id id) { - return vehicleModes.containsKey(Id.create(id, DvrpVehicle.class)); - } - - public String getMode(Id id) { - return vehicleModes.get(Id.create(id, DvrpVehicle.class)); - } -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleActivityItem.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleActivityItem.java deleted file mode 100644 index 02e0c0f63..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleActivityItem.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.eqasim.examples.corsica_drt.analysis.vehicles; - -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.network.Link; -import org.matsim.vehicles.Vehicle; - -public class VehicleActivityItem { - public String mode; - - public Id vehicleId; - public Link link; - - public double startTime = Double.NaN; - public double endTime = Double.NaN; - - public String type; -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleAnalysisListener.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleAnalysisListener.java deleted file mode 100644 index 463f0229e..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleAnalysisListener.java +++ /dev/null @@ -1,176 +0,0 @@ -package org.eqasim.examples.corsica_drt.analysis.vehicles; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import org.eqasim.examples.corsica_drt.analysis.utils.LinkFinder; -import org.eqasim.examples.corsica_drt.analysis.utils.PassengerTracker; -import org.eqasim.examples.corsica_drt.analysis.utils.VehicleRegistry; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.events.ActivityEndEvent; -import org.matsim.api.core.v01.events.ActivityStartEvent; -import org.matsim.api.core.v01.events.LinkEnterEvent; -import org.matsim.api.core.v01.events.PersonArrivalEvent; -import org.matsim.api.core.v01.events.PersonDepartureEvent; -import org.matsim.api.core.v01.events.PersonEntersVehicleEvent; -import org.matsim.api.core.v01.events.PersonLeavesVehicleEvent; -import org.matsim.api.core.v01.events.handler.ActivityEndEventHandler; -import org.matsim.api.core.v01.events.handler.ActivityStartEventHandler; -import org.matsim.api.core.v01.events.handler.LinkEnterEventHandler; -import org.matsim.api.core.v01.events.handler.PersonArrivalEventHandler; -import org.matsim.api.core.v01.events.handler.PersonDepartureEventHandler; -import org.matsim.api.core.v01.events.handler.PersonEntersVehicleEventHandler; -import org.matsim.api.core.v01.events.handler.PersonLeavesVehicleEventHandler; -import org.matsim.vehicles.Vehicle; - -public class VehicleAnalysisListener implements PersonDepartureEventHandler, PersonArrivalEventHandler, ActivityStartEventHandler, ActivityEndEventHandler, LinkEnterEventHandler, - PersonEntersVehicleEventHandler, PersonLeavesVehicleEventHandler { - private final LinkFinder linkFinder; - private final VehicleRegistry vehicleRegistry; - private final PassengerTracker passengers = new PassengerTracker(); - - private final List movements = new LinkedList<>(); - private final List activities = new LinkedList<>(); - - private final Map, VehicleMovementItem> currentMovements = new HashMap<>(); - private final Map, VehicleActivityItem> currentActivities = new HashMap<>(); - - public VehicleAnalysisListener(LinkFinder linkFinder, VehicleRegistry vehicleRegistry) { - this.linkFinder = linkFinder; - this.vehicleRegistry = vehicleRegistry; - } - - @Override - public void handleEvent(PersonDepartureEvent event) { - if (vehicleRegistry.isFleet(event.getPersonId())) { - String mode = vehicleRegistry.getMode(event.getPersonId()); - Id vehicleId = Id.createVehicleId(event.getPersonId()); - - VehicleMovementItem movement = new VehicleMovementItem(); - movements.add(movement); - - movement.mode = mode; - movement.vehicleId = vehicleId; - - movement.originLink = linkFinder.getLink(event.getLinkId()); - movement.departureTime = event.getTime(); - - currentMovements.put(vehicleId, movement); - } - } - - @Override - public void handleEvent(LinkEnterEvent event) { - if (vehicleRegistry.isFleet(event.getVehicleId())) { - VehicleMovementItem movement = currentMovements.get(event.getVehicleId()); - - if (movement == null) { - throw new IllegalStateException("Found link enter event without departure"); - } - - movement.distance += linkFinder.getDistance(event.getLinkId()); - } - } - - @Override - public void handleEvent(PersonEntersVehicleEvent event) { - if (!vehicleRegistry.isFleet(event.getPersonId())) { - if (vehicleRegistry.isFleet(event.getVehicleId())) { - passengers.addPassenger(event.getVehicleId(), event.getPersonId()); - } - } - } - - @Override - public void handleEvent(PersonLeavesVehicleEvent event) { - if (!vehicleRegistry.isFleet(event.getPersonId())) { - if (vehicleRegistry.isFleet(event.getVehicleId())) { - passengers.removePassenger(event.getVehicleId(), event.getPersonId()); - } - } - } - - @Override - public void handleEvent(PersonArrivalEvent event) { - if (vehicleRegistry.isFleet(event.getPersonId())) { - Id vehicleId = Id.createVehicleId(event.getPersonId()); - - VehicleMovementItem movement = currentMovements.remove(vehicleId); - - if (movement == null) { - throw new IllegalStateException("Found arrival without departure"); - } - - movement.destinationLink = linkFinder.getLink(event.getLinkId()); - movement.arrivalTime = event.getTime(); - - movement.numberOfPassengers = passengers.getNumberOfPassengers(vehicleId); - } - } - - @Override - public void handleEvent(ActivityStartEvent event) { - if (vehicleRegistry.isFleet(event.getPersonId())) { - String mode = vehicleRegistry.getMode(event.getPersonId()); - Id vehicleId = Id.createVehicleId(event.getPersonId()); - - VehicleActivityItem activity = new VehicleActivityItem(); - activities.add(activity); - - activity.mode = mode; - activity.vehicleId = vehicleId; - - activity.link = linkFinder.getLink(event.getLinkId()); - activity.type = event.getActType(); - - activity.startTime = event.getTime(); - - currentActivities.put(vehicleId, activity); - } - } - - @Override - public void handleEvent(ActivityEndEvent event) { - if (vehicleRegistry.isFleet(event.getPersonId())) { - String mode = vehicleRegistry.getMode(event.getPersonId()); - Id vehicleId = Id.createVehicleId(event.getPersonId()); - - VehicleActivityItem activity = currentActivities.remove(vehicleId); - boolean isStarted = activity != null; - - if (!isStarted) { - activity = new VehicleActivityItem(); - activities.add(activity); - } - - activity.mode = mode; - activity.vehicleId = vehicleId; - - activity.link = linkFinder.getLink(event.getLinkId()); - activity.type = event.getActType(); - - activity.endTime = event.getTime(); - } - } - - @Override - public void reset(int iteration) { - passengers.clear(); - - currentActivities.clear(); - currentMovements.clear(); - - activities.clear(); - movements.clear(); - } - - public List getActivities() { - return activities; - } - - public List getMovements() { - return movements; - } -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleAnalysisWriter.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleAnalysisWriter.java deleted file mode 100644 index 9abcae6ac..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleAnalysisWriter.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.eqasim.examples.corsica_drt.analysis.vehicles; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; - -public class VehicleAnalysisWriter { - private final VehicleAnalysisListener listener; - - public VehicleAnalysisWriter(VehicleAnalysisListener listener) { - this.listener = listener; - } - - public void writeMovements(File path) throws IOException { - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path))); - - writer.write(String.join(";", new String[] { // - "operator_id", // - "vehicle_id", // - - "origin_link_id", // - "origin_x", // - "origin_y", // - - "destination_link_id", // - "destination_x", // - "destination_y", // - - "departure_time", // - "arrival_time", // - - "distance", // - "number_of_passengers" // - }) + "\n"); - - for (VehicleMovementItem movement : listener.getMovements()) { - writer.write(String.join(";", new String[] { // - String.valueOf(movement.mode), // - String.valueOf(movement.vehicleId), // - - String.valueOf(movement.originLink.getId()), // - String.valueOf(movement.originLink.getCoord().getX()), // - String.valueOf(movement.originLink.getCoord().getY()), // - - movement.destinationLink == null ? "null" : String.valueOf(movement.destinationLink.getId()), // - movement.destinationLink == null ? "NaN" : String.valueOf(movement.destinationLink.getCoord().getX()), // - movement.destinationLink == null ? "NaN" : String.valueOf(movement.destinationLink.getCoord().getY()), // - - String.valueOf(movement.departureTime), // - String.valueOf(movement.arrivalTime), // - - String.valueOf(movement.distance), // - String.valueOf(movement.numberOfPassengers) // - }) + "\n"); - } - - writer.close(); - } - - public void writeActivities(File path) throws IOException { - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(path))); - - writer.write(String.join(";", new String[] { // - "operator_id", // - "vehicle_id", // - - "link_id", // - "x", // - "y", // - - "start_time", // - "end_time", // - - "type" // - }) + "\n"); - - for (VehicleActivityItem activity : listener.getActivities()) { - writer.write(String.join(";", new String[] { // - String.valueOf(activity.mode), // - String.valueOf(activity.vehicleId), // - - String.valueOf(activity.link.getId()), // - String.valueOf(activity.link.getCoord().getX()), // - String.valueOf(activity.link.getCoord().getY()), // - - String.valueOf(activity.startTime), // - String.valueOf(activity.endTime), // - - activity.type // - }) + "\n"); - } - - writer.close(); - } -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleMovementItem.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleMovementItem.java deleted file mode 100644 index b3c226659..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/analysis/vehicles/VehicleMovementItem.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.eqasim.examples.corsica_drt.analysis.vehicles; - -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.network.Link; -import org.matsim.vehicles.Vehicle; - -public class VehicleMovementItem { - public String mode; - public Id vehicleId; - - public Link originLink; - public Link destinationLink; - - public double departureTime = Double.NaN; - public double arrivalTime = Double.NaN; - - public double distance = 0; - public int numberOfPassengers = 0; -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/parameters/CorsicaDrtModeParameters.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/parameters/CorsicaDrtModeParameters.java deleted file mode 100644 index e9dbd24ee..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/parameters/CorsicaDrtModeParameters.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.eqasim.examples.corsica_drt.mode_choice.parameters; - -import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; - -public class CorsicaDrtModeParameters extends IDFModeParameters { - public class ParisDrtParameters { - 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 ParisDrtParameters drt = new ParisDrtParameters(); - - public static CorsicaDrtModeParameters buildDefault() { - // This is a copy & paste - - CorsicaDrtModeParameters parameters = new CorsicaDrtModeParameters(); - - // Cost - parameters.betaCost_u_MU = -0.206; - parameters.lambdaCostEuclideanDistance = -0.4; - parameters.referenceEuclideanDistance_km = 40.0; - - // Car - parameters.car.alpha_u = 1.35; - parameters.car.betaTravelTime_u_min = -0.06; - - parameters.car.additionalAccessEgressWalkTime_min = 4.0; - parameters.car.constantParkingSearchPenalty_min = 4.0; - - parameters.idfCar.betaInsideUrbanArea = -0.5; - parameters.idfCar.betaCrossingUrbanArea = -1.0; - - // PT - parameters.pt.alpha_u = 0.0; - parameters.pt.betaLineSwitch_u = -0.17; - parameters.pt.betaInVehicleTime_u_min = -0.017; - parameters.pt.betaWaitingTime_u_min = -0.0484; - parameters.pt.betaAccessEgressTime_u_min = -0.0804; - - // Bike - parameters.bike.alpha_u = -2.0; - parameters.bike.betaTravelTime_u_min = -0.05; - parameters.bike.betaAgeOver18_u_a = -0.0496; - - parameters.idfBike.betaInsideUrbanArea = 1.5; - - // Walk - parameters.walk.alpha_u = 1.43; - parameters.walk.betaTravelTime_u_min = -0.15; - - // DRT (adapted from public transport) - parameters.drt.alpha_u = 0.0; - parameters.drt.betaWaitingTime_u_min = -0.0484; - parameters.drt.betaTravelTime_u_min = -0.017; - parameters.drt.betaAccessEgressTime_u_min = -0.0804; - - return parameters; - } -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/utilities/DrtPredictor.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/utilities/DrtPredictor.java deleted file mode 100644 index 24a42799b..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/utilities/DrtPredictor.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.eqasim.examples.corsica_drt.mode_choice.utilities; - -import java.util.List; - -import org.eqasim.core.simulation.mode_choice.cost.CostModel; -import org.eqasim.core.simulation.mode_choice.utilities.predictors.CachedVariablePredictor; -import org.eqasim.core.simulation.mode_choice.utilities.predictors.PredictorUtils; -import org.matsim.api.core.v01.TransportMode; -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.contrib.drt.routing.DrtRoute; -import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; -import org.matsim.core.router.TripStructureUtils; - -import com.google.inject.Inject; -import com.google.inject.name.Named; - -public class DrtPredictor extends CachedVariablePredictor { - private CostModel costModel; - - @Inject - public DrtPredictor(@Named("drt") CostModel costModel) { - this.costModel = costModel; - } - - @Override - public DrtVariables predict(Person person, DiscreteModeChoiceTrip trip, List elements) { - double travelTime_min = 0.0; - double accessEgressTime_min = 0.0; - double cost_MU = 0.0; - double waitingTime_min = 0.0; - - for (Leg leg : TripStructureUtils.getLegs(elements)) { - switch (leg.getMode()) { - case TransportMode.walk: - accessEgressTime_min += leg.getTravelTime().seconds() / 60.0; - break; - case "drt": - DrtRoute route = (DrtRoute) leg.getRoute(); - - // We use worst case here - travelTime_min = route.getMaxTravelTime() / 60.0; - waitingTime_min = route.getMaxWaitTime() / 60.0; - - cost_MU = costModel.calculateCost_MU(person, trip, elements); - - break; - default: - throw new IllegalStateException("Encountered unknown mode in DrtPredictor: " + leg.getMode()); - } - } - - double euclideanDistance_km = PredictorUtils.calculateEuclideanDistance_km(trip); - - return new DrtVariables(travelTime_min, cost_MU, euclideanDistance_km, waitingTime_min, accessEgressTime_min); - } -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/utilities/DrtUtilityEstimator.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/utilities/DrtUtilityEstimator.java deleted file mode 100644 index 1a2b1bbd9..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/utilities/DrtUtilityEstimator.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.eqasim.examples.corsica_drt.mode_choice.utilities; - -import java.util.List; - -import org.eqasim.core.simulation.mode_choice.utilities.UtilityEstimator; -import org.eqasim.core.simulation.mode_choice.utilities.estimators.EstimatorUtils; -import org.eqasim.examples.corsica_drt.mode_choice.parameters.CorsicaDrtModeParameters; -import org.matsim.api.core.v01.population.Person; -import org.matsim.api.core.v01.population.PlanElement; -import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; - -import com.google.inject.Inject; - -public class DrtUtilityEstimator implements UtilityEstimator { - private final CorsicaDrtModeParameters parameters; - private final DrtPredictor predictor; - - @Inject - public DrtUtilityEstimator(CorsicaDrtModeParameters parameters, DrtPredictor predictor) { - this.parameters = parameters; - this.predictor = predictor; - } - - protected double estimateConstantUtility() { - return parameters.drt.alpha_u; - } - - protected double estimateTravelTimeUtility(DrtVariables variables) { - return parameters.drt.betaTravelTime_u_min * variables.travelTime_min; - } - - protected double estimateWaitingTimeUtility(DrtVariables variables) { - return parameters.drt.betaWaitingTime_u_min * variables.waitingTime_min; - } - - protected double estimateMonetaryCostUtility(DrtVariables variables) { - return parameters.betaCost_u_MU * EstimatorUtils.interaction(variables.euclideanDistance_km, - parameters.referenceEuclideanDistance_km, parameters.lambdaCostEuclideanDistance) * variables.cost_MU; - } - - protected double estimateAccessEgressTimeUtility(DrtVariables variables) { - return parameters.drt.betaAccessEgressTime_u_min * variables.accessEgressTime_min; - } - - @Override - public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { - DrtVariables variables = predictor.predict(person, trip, elements); - - double utility = 0.0; - - utility += estimateConstantUtility(); - utility += estimateTravelTimeUtility(variables); - utility += estimateWaitingTimeUtility(variables); - utility += estimateMonetaryCostUtility(variables); - utility += estimateAccessEgressTimeUtility(variables); - - return utility; - } -} diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/utilities/DrtVariables.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/utilities/DrtVariables.java deleted file mode 100644 index 34b322fae..000000000 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/mode_choice/utilities/DrtVariables.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.eqasim.examples.corsica_drt.mode_choice.utilities; - -import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; - -public class DrtVariables implements BaseVariables { - final public double travelTime_min; - final public double cost_MU; - final public double euclideanDistance_km; - final public double waitingTime_min; - final public double accessEgressTime_min; - - public DrtVariables(double travelTime_min, double cost_MU, double euclideanDistance_km, double waitingTime_min, - double accessEgressTime_min) { - this.travelTime_min = travelTime_min; - this.cost_MU = cost_MU; - this.euclideanDistance_km = euclideanDistance_km; - this.waitingTime_min = waitingTime_min; - this.accessEgressTime_min = accessEgressTime_min; - } -}