From eb692d80daf9510ea8d2b166ad3ee414d179a2e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Mon, 30 Sep 2024 13:50:07 +0200 Subject: [PATCH 01/81] activate epsilon by default --- .../mode_choice/epsilon/AdaptConfigForEpsilon.java | 10 +++++++--- .../eqasim/ile_de_france/scenario/RunAdaptConfig.java | 4 ++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/simulation/mode_choice/epsilon/AdaptConfigForEpsilon.java b/core/src/main/java/org/eqasim/core/simulation/mode_choice/epsilon/AdaptConfigForEpsilon.java index d379e3fb2..313d46cff 100644 --- a/core/src/main/java/org/eqasim/core/simulation/mode_choice/epsilon/AdaptConfigForEpsilon.java +++ b/core/src/main/java/org/eqasim/core/simulation/mode_choice/epsilon/AdaptConfigForEpsilon.java @@ -17,7 +17,13 @@ public static void main(String[] args) throws CommandLine.ConfigurationException Config config = ConfigUtils.loadConfig(commandLine.getOptionStrict("input-config-path"), new EqasimConfigGroup(), new DiscreteModeChoiceConfigGroup()); commandLine.applyConfiguration(config); - DiscreteModeChoiceConfigGroup discreteModeChoiceConfigGroup = (DiscreteModeChoiceConfigGroup) config.getModules().get(DiscreteModeChoiceConfigGroup.GROUP_NAME); + run(config); + + ConfigUtils.writeConfig(config, commandLine.getOptionStrict("output-config-path")); + } + + static public void run(Config config) { + DiscreteModeChoiceConfigGroup discreteModeChoiceConfigGroup = (DiscreteModeChoiceConfigGroup) config.getModules().get(DiscreteModeChoiceConfigGroup.GROUP_NAME); discreteModeChoiceConfigGroup.setSelector(SelectorModule.MAXIMUM); EqasimConfigGroup eqasimConfigGroup = (EqasimConfigGroup) config.getModules().get(EqasimConfigGroup.GROUP_NAME); @@ -29,7 +35,5 @@ public static void main(String[] args) throws CommandLine.ConfigurationException } eqasimConfigGroup.setEstimator(entry.getKey(), EpsilonModule.EPSILON_UTILITY_PREFIX + entry.getValue()); } - - ConfigUtils.writeConfig(config, commandLine.getOptionStrict("output-config-path")); } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index a171cbef6..0c36105be 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -2,6 +2,7 @@ import org.eqasim.core.components.config.ConfigAdapter; import org.eqasim.core.components.config.EqasimConfigGroup; +import org.eqasim.core.simulation.mode_choice.epsilon.AdaptConfigForEpsilon; import org.eqasim.ile_de_france.IDFConfigurator; import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; import org.matsim.api.core.v01.TransportMode; @@ -32,6 +33,9 @@ static public void adaptConfiguration(Config config, String prefix) { .get(DiscreteModeChoiceConfigGroup.GROUP_NAME); dmcConfig.setModeAvailability(IDFModeChoiceModule.MODE_AVAILABILITY_NAME); + + // Epsilon + AdaptConfigForEpsilon.run(config); // Calibration results for 5% From 6649152ba5fa224aad34de0e46e8ab1ec217d153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Mon, 30 Sep 2024 13:57:34 +0200 Subject: [PATCH 02/81] integrate transit routing parameters --- .../raptor/EqasimRaptorConfigGroup.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/components/raptor/EqasimRaptorConfigGroup.java b/core/src/main/java/org/eqasim/core/components/raptor/EqasimRaptorConfigGroup.java index d0ee550f9..c496a6007 100644 --- a/core/src/main/java/org/eqasim/core/components/raptor/EqasimRaptorConfigGroup.java +++ b/core/src/main/java/org/eqasim/core/components/raptor/EqasimRaptorConfigGroup.java @@ -10,26 +10,26 @@ public EqasimRaptorConfigGroup() { } @Parameter - public double travelTimeRail_u_h = -7.0; + public double travelTimeRail_u_h = -1.4278139352278472; @Parameter - public double travelTimeSubway_u_h = -7.0; + public double travelTimeSubway_u_h = -1.0; @Parameter - public double travelTimeBus_u_h = -7.0; + public double travelTimeBus_u_h = -2.835025304050246; @Parameter - public double travelTimeTram_u_h = -7.0; + public double travelTimeTram_u_h = -3.199594607188756; @Parameter - public double travelTimeOther_u_h = -7.0; + public double travelTimeOther_u_h = -2.835025304050246; @Parameter - public double perTransfer_u = -1.0; + public double perTransfer_u = -0.5441109013512305; @Parameter - public double waitTime_u_h = -6.0; + public double waitTime_u_h = -0.497984826174775; @Parameter - public double walkTime_u_h = -7.0; + public double walkTime_u_h = -3.8494071051697385; } From d4a55d9e412fd9131bfa9ac583649aac41c07807 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Mon, 30 Sep 2024 16:31:56 +0200 Subject: [PATCH 03/81] update crossing penalty --- .../components/traffic/CrossingPenalty.java | 7 +++ .../traffic/DefaultCrossingPenalty.java | 54 +++++++++++++++++++ .../traffic/EqasimLinkSpeedCalculator.java | 23 ++------ .../traffic/EqasimTrafficModule.java | 21 ++++++++ .../traffic/EqasimTrafficQSimModule.java | 5 +- .../scenario/preparation/AdjustFreespeed.java | 40 ++++++++++++++ .../core/simulation/EqasimConfigurator.java | 4 +- .../eqasim/core/simulation/vdf/VDFModule.java | 5 +- .../vdf/travel_time/VDFTravelTime.java | 40 +++++--------- .../test/java/org/eqasim/TestEmissions.java | 18 ++++--- .../scenario/RunAdaptConfig.java | 11 ++-- 11 files changed, 162 insertions(+), 66 deletions(-) create mode 100644 core/src/main/java/org/eqasim/core/components/traffic/CrossingPenalty.java create mode 100644 core/src/main/java/org/eqasim/core/components/traffic/DefaultCrossingPenalty.java create mode 100644 core/src/main/java/org/eqasim/core/components/traffic/EqasimTrafficModule.java create mode 100644 core/src/main/java/org/eqasim/core/scenario/preparation/AdjustFreespeed.java diff --git a/core/src/main/java/org/eqasim/core/components/traffic/CrossingPenalty.java b/core/src/main/java/org/eqasim/core/components/traffic/CrossingPenalty.java new file mode 100644 index 000000000..875716a91 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/components/traffic/CrossingPenalty.java @@ -0,0 +1,7 @@ +package org.eqasim.core.components.traffic; + +import org.matsim.api.core.v01.network.Link; + +public interface CrossingPenalty { + double calculateCrossingPenalty(Link link); +} diff --git a/core/src/main/java/org/eqasim/core/components/traffic/DefaultCrossingPenalty.java b/core/src/main/java/org/eqasim/core/components/traffic/DefaultCrossingPenalty.java new file mode 100644 index 000000000..412a143a6 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/components/traffic/DefaultCrossingPenalty.java @@ -0,0 +1,54 @@ +package org.eqasim.core.components.traffic; + +import org.matsim.api.core.v01.IdSet; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; + +public class DefaultCrossingPenalty implements CrossingPenalty { + static public final String MAJOR_CROSSING_ATTRIBUTE = "eqasim:majorCrossing"; + + private final IdSet penalizedLinkIds; + private final double crossingPenalty; + + DefaultCrossingPenalty(IdSet penalizedLinkIds, double crossingPenalty) { + this.penalizedLinkIds = penalizedLinkIds; + this.crossingPenalty = crossingPenalty; + } + + @Override + public double calculateCrossingPenalty(Link link) { + if (penalizedLinkIds.contains(link.getId())) { + return crossingPenalty; + } else { + return 0.0; + } + } + + static public DefaultCrossingPenalty build(Network network, double crossingPenalty) { + IdSet penalizedLinkIds = new IdSet<>(Link.class); + + for (Link link : network.getLinks().values()) { + if (link.getAllowedModes().contains(TransportMode.car)) { + if (link.getToNode().getInLinks().size() > 1) { // otherwise straight road or diverge + double maximumCapacity = Double.NEGATIVE_INFINITY; + boolean foundLower = false; + + for (Link inlink : link.getToNode().getInLinks().values()) { + if (inlink.getCapacity() > maximumCapacity) { + maximumCapacity = inlink.getCapacity(); + } + + foundLower |= inlink.getCapacity() < link.getCapacity(); + } + + if (link.getCapacity() == maximumCapacity && foundLower) { + penalizedLinkIds.add(link.getId()); + } + } + } + } + + return new DefaultCrossingPenalty(penalizedLinkIds, crossingPenalty); + } +} diff --git a/core/src/main/java/org/eqasim/core/components/traffic/EqasimLinkSpeedCalculator.java b/core/src/main/java/org/eqasim/core/components/traffic/EqasimLinkSpeedCalculator.java index 98345a6ae..98e56d789 100644 --- a/core/src/main/java/org/eqasim/core/components/traffic/EqasimLinkSpeedCalculator.java +++ b/core/src/main/java/org/eqasim/core/components/traffic/EqasimLinkSpeedCalculator.java @@ -5,30 +5,17 @@ import org.matsim.core.mobsim.qsim.qnetsimengine.linkspeedcalculator.LinkSpeedCalculator; public class EqasimLinkSpeedCalculator implements LinkSpeedCalculator { - final private double crossingPenalty; + private final CrossingPenalty crossingPenalty; - public EqasimLinkSpeedCalculator(double crossingPenalty) { + public EqasimLinkSpeedCalculator(CrossingPenalty crossingPenalty) { this.crossingPenalty = crossingPenalty; } @Override public double getMaximumVelocity(QVehicle vehicle, Link link, double time) { - boolean isMajor = true; - - for (Link other : link.getToNode().getInLinks().values()) { - if (other.getCapacity() >= link.getCapacity()) { - isMajor = false; - } - } - double maximumVelocity = Math.min(vehicle.getMaximumVelocity(), link.getFreespeed(time)); - - if (isMajor || link.getToNode().getInLinks().size() == 1) { - return maximumVelocity; - } else { - double travelTime = link.getLength() / maximumVelocity; - travelTime += crossingPenalty; - return link.getLength() / travelTime; - } + double travelTime = link.getLength() / maximumVelocity; + travelTime += crossingPenalty.calculateCrossingPenalty(link); + return link.getLength() / travelTime; } } diff --git a/core/src/main/java/org/eqasim/core/components/traffic/EqasimTrafficModule.java b/core/src/main/java/org/eqasim/core/components/traffic/EqasimTrafficModule.java new file mode 100644 index 000000000..8f8b2b98d --- /dev/null +++ b/core/src/main/java/org/eqasim/core/components/traffic/EqasimTrafficModule.java @@ -0,0 +1,21 @@ +package org.eqasim.core.components.traffic; + +import org.eqasim.core.components.config.EqasimConfigGroup; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.controler.AbstractModule; + +import com.google.inject.Provides; +import com.google.inject.Singleton; + +public class EqasimTrafficModule extends AbstractModule { + @Override + public void install() { + bind(CrossingPenalty.class).to(DefaultCrossingPenalty.class); + } + + @Provides + @Singleton + public DefaultCrossingPenalty provideDefaultCrossingPenalty(Network network, EqasimConfigGroup eqasimConfig) { + return DefaultCrossingPenalty.build(network, eqasimConfig.getCrossingPenalty()); + } +} diff --git a/core/src/main/java/org/eqasim/core/components/traffic/EqasimTrafficQSimModule.java b/core/src/main/java/org/eqasim/core/components/traffic/EqasimTrafficQSimModule.java index 752a75f6e..e102c8db6 100644 --- a/core/src/main/java/org/eqasim/core/components/traffic/EqasimTrafficQSimModule.java +++ b/core/src/main/java/org/eqasim/core/components/traffic/EqasimTrafficQSimModule.java @@ -1,6 +1,5 @@ package org.eqasim.core.components.traffic; -import org.eqasim.core.components.config.EqasimConfigGroup; import org.matsim.core.mobsim.qsim.AbstractQSimModule; import org.matsim.core.mobsim.qsim.qnetsimengine.linkspeedcalculator.LinkSpeedCalculator; @@ -15,7 +14,7 @@ protected void configureQSim() { @Provides @Singleton - public EqasimLinkSpeedCalculator provideBaselineLinkSpeedCalculator(EqasimConfigGroup eqasimConfig) { - return new EqasimLinkSpeedCalculator(eqasimConfig.getCrossingPenalty()); + public EqasimLinkSpeedCalculator provideBaselineLinkSpeedCalculator(CrossingPenalty crossigPenalty) { + return new EqasimLinkSpeedCalculator(crossigPenalty); } } diff --git a/core/src/main/java/org/eqasim/core/scenario/preparation/AdjustFreespeed.java b/core/src/main/java/org/eqasim/core/scenario/preparation/AdjustFreespeed.java new file mode 100644 index 000000000..e9a21bf6c --- /dev/null +++ b/core/src/main/java/org/eqasim/core/scenario/preparation/AdjustFreespeed.java @@ -0,0 +1,40 @@ +package org.eqasim.core.scenario.preparation; + +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.CommandLine; +import org.matsim.core.config.CommandLine.ConfigurationException; + +public class AdjustFreespeed { + static public final String INITIAL_FREESPEED = "eqasim:initialFreespeed"; + + static public void main(String[] args) throws ConfigurationException { + CommandLine commandLine = new CommandLine.Builder(args) // + .requireOptions("input-path", "output-path") // + .allowPrefixes("freespeed") // + .build(); + + + + } + + static public void run(Network network) { + + } + + static public void validate(Scenario scenario) { + boolean valid = false; + + for (Link link : scenario.getNetwork().getLinks().values()) { + if (link.getAttributes().getAttribute(INITIAL_FREESPEED) != null) { + valid = true; + break; + } + } + + if (!valid) { + throw new IllegalStateException("Did not find initial freespeed. Did you call AdjustFreespeed?"); + } + } +} 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 3f759caff..00c4d233e 100644 --- a/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java +++ b/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java @@ -7,6 +7,7 @@ import org.eqasim.core.components.config.EqasimConfigGroup; import org.eqasim.core.components.raptor.EqasimRaptorConfigGroup; import org.eqasim.core.components.raptor.EqasimRaptorModule; +import org.eqasim.core.components.traffic.EqasimTrafficModule; import org.eqasim.core.components.traffic.EqasimTrafficQSimModule; import org.eqasim.core.components.transit.EqasimTransitModule; import org.eqasim.core.components.transit.EqasimTransitQSimModule; @@ -79,7 +80,8 @@ public EqasimConfigurator() { new EqasimComponentsModule(), // new EpsilonModule(), // new EqasimRaptorModule(), - new EqasimModeChoiceModule()// + new EqasimModeChoiceModule(), // + new EqasimTrafficModule() // )); qsimModules.addAll(Arrays.asList( // diff --git a/core/src/main/java/org/eqasim/core/simulation/vdf/VDFModule.java b/core/src/main/java/org/eqasim/core/simulation/vdf/VDFModule.java index 53ba1918d..98bbf919b 100644 --- a/core/src/main/java/org/eqasim/core/simulation/vdf/VDFModule.java +++ b/core/src/main/java/org/eqasim/core/simulation/vdf/VDFModule.java @@ -6,6 +6,7 @@ import java.util.Optional; import org.eqasim.core.components.config.EqasimConfigGroup; +import org.eqasim.core.components.traffic.CrossingPenalty; import org.eqasim.core.scenario.cutter.extent.ScenarioExtent; import org.eqasim.core.scenario.cutter.extent.ShapeScenarioExtent; import org.eqasim.core.simulation.vdf.handlers.VDFHorizonHandler; @@ -69,10 +70,10 @@ public VDFScope provideVDFScope(VDFConfigGroup config) { @Provides @Singleton public VDFTravelTime provideVDFTravelTime(VDFConfigGroup config, VDFScope scope, Network network, - VolumeDelayFunction vdf, QSimConfigGroup qsimConfig, EqasimConfigGroup eqasimConfig) throws IOException { + VolumeDelayFunction vdf, QSimConfigGroup qsimConfig, EqasimConfigGroup eqasimConfig, CrossingPenalty crossingPenalty) throws IOException { ScenarioExtent updateExtent = config.getUpdateAreaShapefile() == null ? null : new ShapeScenarioExtent.Builder(new File(ConfigGroup.getInputFileURL(getConfig().getContext(), config.getUpdateAreaShapefile()).getPath()), Optional.empty(), Optional.empty()).build(); return new VDFTravelTime(scope, config.getMinimumSpeed(), config.getCapacityFactor(), - eqasimConfig.getSampleSize(), network, vdf, eqasimConfig.getCrossingPenalty(), updateExtent); + eqasimConfig.getSampleSize(), network, vdf, crossingPenalty, updateExtent); } @Provides diff --git a/core/src/main/java/org/eqasim/core/simulation/vdf/travel_time/VDFTravelTime.java b/core/src/main/java/org/eqasim/core/simulation/vdf/travel_time/VDFTravelTime.java index 994fe22ee..8df59c2a9 100644 --- a/core/src/main/java/org/eqasim/core/simulation/vdf/travel_time/VDFTravelTime.java +++ b/core/src/main/java/org/eqasim/core/simulation/vdf/travel_time/VDFTravelTime.java @@ -7,6 +7,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.eqasim.core.components.traffic.CrossingPenalty; import org.eqasim.core.scenario.cutter.extent.ScenarioExtent; import org.eqasim.core.simulation.vdf.VDFScope; import org.eqasim.core.simulation.vdf.travel_time.function.VolumeDelayFunction; @@ -24,23 +25,25 @@ public class VDFTravelTime implements TravelTime { private final double minimumSpeed; private final double capacityFactor; private final double samplingRate; - private final double crossingPenalty; private final Network network; private final VolumeDelayFunction vdf; private final ScenarioExtent updateAreaExtent; + private final CrossingPenalty crossingPenalty; + private final IdMap> travelTimes = new IdMap<>(Link.class); private final Logger logger = LogManager.getLogger(VDFTravelTime.class); public VDFTravelTime(VDFScope scope, double minimumSpeed, double capacityFactor, double samplingRate, - Network network, VolumeDelayFunction vdf, double crossingPenalty) { + Network network, VolumeDelayFunction vdf, CrossingPenalty crossingPenalty) { this(scope, minimumSpeed, capacityFactor, samplingRate, network, vdf, crossingPenalty, null); } public VDFTravelTime(VDFScope scope, double minimumSpeed, double capacityFactor, double samplingRate, - Network network, VolumeDelayFunction vdf, double crossingPenalty, ScenarioExtent updateAreaExtent) { + Network network, VolumeDelayFunction vdf, CrossingPenalty crossingPenalty, + ScenarioExtent updateAreaExtent) { this.scope = scope; this.network = network; this.vdf = vdf; @@ -53,8 +56,8 @@ public VDFTravelTime(VDFScope scope, double minimumSpeed, double capacityFactor, for (Link link : network.getLinks().values()) { double travelTime = Math.max(1.0, Math.min(link.getLength() / minimumSpeed, link.getLength() / link.getFreespeed())); - travelTimes.put(link.getId(), new ArrayList<>( - Collections.nCopies(scope.getIntervals(), considerCrossingPenalty(link, travelTime)))); + travelTimes.put(link.getId(), new ArrayList<>(Collections.nCopies(scope.getIntervals(), + travelTime + crossingPenalty.calculateCrossingPenalty(link)))); } } @@ -70,7 +73,7 @@ public void update(IdMap> counts) { public void update(IdMap> counts, boolean forceUpdateAllLinks) { String logMessage = "Updating VDFTravelTime "; - if(updateAreaExtent != null && !forceUpdateAllLinks) { + if (updateAreaExtent != null && !forceUpdateAllLinks) { logMessage += " using update extent ..."; } else { logMessage += " ..."; @@ -82,12 +85,13 @@ public void update(IdMap> counts, boolean forceUpdateAllLinks for (Map.Entry, List> entry : counts.entrySet()) { Link link = network.getLinks().get(entry.getKey()); - if(link == null) { + if (link == null) { continue; } - if(updateAreaExtent != null && !forceUpdateAllLinks) { - if(!updateAreaExtent.isInside(link.getFromNode().getCoord()) || !updateAreaExtent.isInside(link.getToNode().getCoord())) { + if (updateAreaExtent != null && !forceUpdateAllLinks) { + if (!updateAreaExtent.isInside(link.getFromNode().getCoord()) + || !updateAreaExtent.isInside(link.getToNode().getCoord())) { continue; } } @@ -105,7 +109,7 @@ public void update(IdMap> counts, boolean forceUpdateAllLinks double travelTime = Math.max(1.0, Math.min(link.getLength() / minimumSpeed, vdf.getTravelTime(time, flow, capacity, link))); - linkTravelTimes.set(i, considerCrossingPenalty(link, travelTime)); + linkTravelTimes.set(i, travelTime + crossingPenalty.calculateCrossingPenalty(link)); if (travelTime > link.getLength() / link.getFreespeed()) { nonFreespeedCount += 1; @@ -115,20 +119,4 @@ public void update(IdMap> counts, boolean forceUpdateAllLinks logger.info(String.format(" Done: %d/%d are slower than freespeed", nonFreespeedCount, totalCount)); } - - private double considerCrossingPenalty(Link link, double baseTravelTime) { - boolean isMajor = true; - - for (Link other : link.getToNode().getInLinks().values()) { - if (other.getCapacity() >= link.getCapacity()) { - isMajor = false; - } - } - - if (isMajor || link.getToNode().getInLinks().size() == 1) { - return baseTravelTime; - } else { - return baseTravelTime + crossingPenalty; - } - } } diff --git a/core/src/test/java/org/eqasim/TestEmissions.java b/core/src/test/java/org/eqasim/TestEmissions.java index bef761534..ab897f275 100644 --- a/core/src/test/java/org/eqasim/TestEmissions.java +++ b/core/src/test/java/org/eqasim/TestEmissions.java @@ -168,11 +168,11 @@ private void runModifyNetwork() { private void runMelunEmissions() throws CommandLine.ConfigurationException, IOException { Map counts = countLegs("melun_test/output/output_events.xml.gz"); - Assert.assertEquals(3297, (long) counts.get("car")); - Assert.assertEquals(1560, (long) counts.get("car_passenger")); - Assert.assertEquals(9348, (long) counts.get("walk")); - Assert.assertEquals(3412, (long) counts.getOrDefault("bike", 0L)); - Assert.assertEquals(2108, (long) counts.get("pt")); + Assert.assertEquals(2793, (long) counts.get("car")); + Assert.assertEquals(1559, (long) counts.get("car_passenger")); + Assert.assertEquals(11642, (long) counts.get("walk")); + Assert.assertEquals(2861, (long) counts.getOrDefault("bike", 0L)); + Assert.assertEquals(3347, (long) counts.get("pt")); RunComputeEmissionsEvents.main(new String[] { "--config-path", "melun_test/input/config.xml", "--hbefa-cold-avg", "sample_41_EFA_ColdStart_vehcat_2020average.csv", "--hbefa-hot-avg", @@ -180,7 +180,7 @@ private void runMelunEmissions() throws CommandLine.ConfigurationException, IOEx "sample_41_EFA_ColdStart_SubSegm_2020detailed.csv", "--hbefa-hot-detailed", "sample_41_EFA_HOT_SubSegm_2020detailed.csv", }); - assertEquals(355977, countLines(new File("melun_test/output/output_emissions_events.xml.gz"))); + assertEquals(334633, countLines(new File("melun_test/output/output_emissions_events.xml.gz"))); RunExportEmissionsNetwork.main(new String[] { "--config-path", "melun_test/input/config.xml", "--pollutants", "PM,CO,NOx,Unknown", "--time-bin-size", "3600" }); @@ -197,10 +197,12 @@ private void runMelunEmissions() throws CommandLine.ConfigurationException, IOEx & f.getAttribute("time").toString().equals("43200")).findFirst().orElse(null); assertNotNull(feature); - double expectedPm = 0.006847378350421; - double expectedCo = 0.456258730331835; + double expectedPm = 0.006288836075491; + double expectedCo = 0.263774681387141; double expectedNox = 0.477558671071797; double expectedUnknown = Double.NaN; + + assertEquals(expectedPm, feature.getAttribute("PM")); assertEquals(expectedCo, feature.getAttribute("CO")); diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index 0c36105be..96bc9010f 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -34,16 +34,11 @@ static public void adaptConfiguration(Config config, String prefix) { dmcConfig.setModeAvailability(IDFModeChoiceModule.MODE_AVAILABILITY_NAME); + // Major crossing penalty from calibration + eqasimConfig.setCrossingPenalty(4.2); + // Epsilon AdaptConfigForEpsilon.run(config); - - // Calibration results for 5% - - if (eqasimConfig.getSampleSize() == 0.05) { - // Adjust flow and storage capacity - config.qsim().setFlowCapFactor(0.045); - config.qsim().setStorageCapFactor(0.045); - } // Vehicles QSimConfigGroup qsimConfig = config.qsim(); From 8ef52520c1a005e41c3d23c471a81bd1f1a97132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Mon, 30 Sep 2024 22:36:27 +0200 Subject: [PATCH 04/81] update choice model --- .../mode_choice/IDFModeAvailability.java | 39 ++------ .../mode_choice/IDFModeChoiceModule.java | 32 +++++-- .../ile_de_france/mode_choice/SynpopTODO.java | 9 ++ .../costs/IDFMotorbikeCostModel.java | 27 ++++++ .../mode_choice/costs/IDFPtCostModel.java | 94 +++++++------------ .../parameters/IDFCostParameters.java | 4 +- .../parameters/IDFModeParameters.java | 80 ++++++++++------ .../estimators/IDFBikeUtilityEstimator.java | 51 ---------- .../estimators/IDFCarUtilityEstimator.java | 34 +++---- .../IDFMotorbikeUtilityEstimator.java | 56 +++++++++++ .../IDFPassengerUtilityEstimator.java | 49 ++++++++++ .../estimators/IDFPtUtilityEstimator.java | 54 +++++++++++ .../predictors/IDFMotorbikePredictor.java | 53 +++++++++++ .../predictors/IDFPassengerPredictor.java | 42 +++++++++ .../predictors/IDFPersonPredictor.java | 4 +- .../predictors/IDFPredictorUtils.java | 24 ++++- .../utilities/predictors/IDFPtPredictor.java | 53 +++++++++++ .../predictors/IDFSpatialPredictor.java | 23 ----- .../variables/IDFMotorbikeVariables.java | 18 ++++ .../variables/IDFPassengerVariables.java | 15 +++ .../variables/IDFPersonVariables.java | 4 +- .../utilities/variables/IDFPtVariables.java | 13 +++ .../variables/IDFSpatialVariables.java | 13 --- .../scenario/RunAdaptConfig.java | 4 +- 24 files changed, 553 insertions(+), 242 deletions(-) create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/SynpopTODO.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFMotorbikeCostModel.java delete mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBikeUtilityEstimator.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFMotorbikeUtilityEstimator.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPassengerUtilityEstimator.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFMotorbikePredictor.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPassengerPredictor.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java delete mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFSpatialPredictor.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFMotorbikeVariables.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPassengerVariables.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPtVariables.java delete mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFSpatialVariables.java diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java index b193c2bb6..cf77d84a1 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java @@ -4,11 +4,11 @@ import java.util.HashSet; import java.util.List; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPredictorUtils; import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.population.Person; import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; import org.matsim.contribs.discrete_mode_choice.model.mode_availability.ModeAvailability; -import org.matsim.core.population.PersonUtils; public class IDFModeAvailability implements ModeAvailability { @Override @@ -18,47 +18,28 @@ public Collection getAvailableModes(Person person, List elements) { + return costParameters.motorbikeCost_EUR_km * getInVehicleDistance_km(elements); + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java index 37ac35dce..4a5780809 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java @@ -4,100 +4,70 @@ import org.eqasim.core.simulation.mode_choice.cost.CostModel; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPersonPredictor; -import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFSpatialPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPtPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPersonVariables; -import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFSpatialVariables; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPtVariables; import org.matsim.api.core.v01.Coord; -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.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; import org.matsim.core.utils.geometry.CoordUtils; -import org.matsim.pt.routes.TransitPassengerRoute; -import org.matsim.pt.transitSchedule.api.TransitSchedule; import com.google.inject.Inject; public class IDFPtCostModel implements CostModel { private final IDFPersonPredictor personPredictor; - private final IDFSpatialPredictor spatialPredictor; - - // TODO: This should be hidden by some custom predictor - private final TransitSchedule transitSchedule; + private final IDFPtPredictor ptPredictor; @Inject - public IDFPtCostModel(IDFPersonPredictor personPredictor, IDFSpatialPredictor spatialPredictor, - TransitSchedule transitSchedule) { + public IDFPtCostModel(IDFPersonPredictor personPredictor, IDFPtPredictor ptPredictor) { this.personPredictor = personPredictor; - this.spatialPredictor = spatialPredictor; - this.transitSchedule = transitSchedule; - } - - private boolean isOnlyMetroOrBus(List elements) { - for (PlanElement element : elements) { - if (element instanceof Leg) { - Leg leg = (Leg) element; - - if (leg.getMode().equals(TransportMode.pt)) { - TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute(); - - String transportMode = transitSchedule.getTransitLines().get(route.getLineId()).getRoutes() - .get(route.getRouteId()).getTransportMode(); - - if (!transportMode.equals("bus") && !transportMode.equals("subway")) { - return false; - } - } - } - } - - return true; + this.ptPredictor = ptPredictor; } private final static Coord CENTER = new Coord(651726, 6862287); - private double calculateBasisDistance_km(DiscreteModeChoiceTrip trip) { - return 1e-3 * (CoordUtils.calcEuclideanDistance(CENTER, trip.getOriginActivity().getCoord()) - + CoordUtils.calcEuclideanDistance(CENTER, trip.getDestinationActivity().getCoord())); - } + private final static double regressionA = 0.098; + private final static double regressionB = 0.006; + private final static double regressionC = 0.006; + private final static double regressionD = -0.77; @Override public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List elements) { // I) If the person has a subscription, the price is zero! - IDFPersonVariables personVariables = personPredictor.predictVariables(person, trip, elements); if (personVariables.hasSubscription) { return 0.0; } - // II) If the trip is entirely inside of Paris, or it only consists of metro and - // bus, the price is 1.80 EUR - - IDFSpatialVariables spatialVariables = spatialPredictor.predictVariables(person, trip, elements); - boolean isWithinParis = spatialVariables.hasUrbanOrigin && spatialVariables.hasUrbanDestination; + // II) Special case: Within Paris or only metro and bus + IDFPtVariables ptVariables = ptPredictor.predictVariables(person, trip, elements); + boolean isWithinParis = false; - boolean isOnlyMetroOrBus = isOnlyMetroOrBus(elements); + if (true) { + throw new IllegalStateException("find out if this is in paris"); + } - if (isOnlyMetroOrBus || isWithinParis) { + if (ptVariables.hasOnlySubwayAndBus || isWithinParis) { return 1.8; } - /*- - * III) Otherwise, we calculate as follows: - * - * 1) Determine the Euclidean distance from the origin station to the center of Paris. - * 2) Determine the Euclidean distance from the destination station to the center of Paris. - * 3) Add up the two distances to arrive at the distance D as the basis for price calculation. - * 4) Calculate 0.25 EUR/km * D to arrive at a rough price estimate. - * - * This assumes that trips in Île-de-France usually must cross through Paris (and otherwise - * they would usually be a bus). And some brief experimentation with the route planner of - * RATP showed that the prices are roghly constructed by the total ride distance with - * a price per distance. TODO: A more detailed analysis would be good to have! - */ - - return 0.25 * calculateBasisDistance_km(trip); + // III) Otherwise, use regression by Abdelkader DIB + double directDistance_km = 1e-3 * CoordUtils.calcEuclideanDistance(trip.getOriginActivity().getCoord(), + trip.getDestinationActivity().getCoord()); + + double originCenterDistance_km = 1e-3 + * CoordUtils.calcEuclideanDistance(CENTER, trip.getOriginActivity().getCoord()); + + double destinationCenterDistance_km = 1e-3 + * CoordUtils.calcEuclideanDistance(CENTER, trip.getDestinationActivity().getCoord()); + + return Math.max(1.9, sigmoid(regressionA * directDistance_km + regressionB * originCenterDistance_km + + regressionC * destinationCenterDistance_km + regressionD)); + } + + private double sigmoid(double x) { + return 1.0 / (1.0 + Math.exp(x)); } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java index 4e2563840..bdf6b5e1a 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java @@ -4,11 +4,13 @@ public class IDFCostParameters implements ParameterDefinition { public double carCost_EUR_km = 0.0; + public double motorbikeCost_EUR_km = 0.0; public static IDFCostParameters buildDefault() { IDFCostParameters parameters = new IDFCostParameters(); - parameters.carCost_EUR_km = 0.15; + parameters.carCost_EUR_km = 0.2; + parameters.motorbikeCost_EUR_km = 0.1; return parameters; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java index e145acd47..fbab01232 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java @@ -4,52 +4,78 @@ public class IDFModeParameters extends ModeParameters { public class IDFCarParameters { - public double betaInsideUrbanArea; - public double betaCrossingUrbanArea; + public double betaInVehicleTravelTime_u_min; } - public class IDFBikeParameters { - public double betaInsideUrbanArea; + public final IDFCarParameters idfCar = new IDFCarParameters(); + + public class IDFPassengerParameters { + public double alpha_u; + public double betaInVehicleTravelTime_u_min; + public double betaDrivingPermit_u; } - public final IDFCarParameters idfCar = new IDFCarParameters(); - public final IDFBikeParameters idfBike = new IDFBikeParameters(); + public final IDFPassengerParameters idfPassenger = new IDFPassengerParameters(); + + public class IDFMotorbikeParameters { + public double alpha_u; + public double betaInVehicleTravelTime_u_min; + } + + public final IDFMotorbikeParameters idfMotorbike = new IDFMotorbikeParameters(); + + public class IDFPtParameters { + public double betaDrivingPermit_u; + public double onlyBus_u; + } + + public final IDFPtParameters idfPt = new IDFPtParameters(); + + public double betaAccessTime_u_min; public static IDFModeParameters buildDefault() { IDFModeParameters parameters = new IDFModeParameters(); + // Access + parameters.betaAccessTime_u_min = -0.0313; + // Cost - parameters.betaCost_u_MU = -0.206; - parameters.lambdaCostEuclideanDistance = -0.4; - parameters.referenceEuclideanDistance_km = 40.0; + parameters.betaCost_u_MU = -0.474; + parameters.lambdaCostEuclideanDistance = -0.274; + parameters.referenceEuclideanDistance_km = 4.4; // Car - parameters.car.alpha_u = 1.35; - parameters.car.betaTravelTime_u_min = -0.06; + parameters.car.alpha_u = -0.662; + parameters.car.betaTravelTime_u_min = -0.0262; + + parameters.idfCar.betaInVehicleTravelTime_u_min = -0.0262; + + // Car passenger + parameters.idfPassenger.alpha_u = -2.08; + parameters.idfPassenger.betaDrivingPermit_u = -1.17; + parameters.idfPassenger.betaInVehicleTravelTime_u_min = -0.0608; - parameters.car.additionalAccessEgressWalkTime_min = 4.0; - parameters.car.constantParkingSearchPenalty_min = 4.0; - - parameters.idfCar.betaInsideUrbanArea = -0.5; - parameters.idfCar.betaCrossingUrbanArea = -1.0; + // Motorbike + parameters.idfMotorbike.alpha_u = -2.2; + parameters.idfMotorbike.betaInVehicleTravelTime_u_min = -0.0321; // 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; + parameters.pt.betaLineSwitch_u = -0.452; + parameters.pt.betaInVehicleTime_u_min = -0.0201; + parameters.pt.betaWaitingTime_u_min = -0.0191; + parameters.pt.betaAccessEgressTime_u_min = parameters.betaAccessTime_u_min; + parameters.idfPt.betaDrivingPermit_u = -0.712; + parameters.idfPt.onlyBus_u = -1.42; + // 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; + parameters.bike.alpha_u = -3.42; + parameters.bike.betaTravelTime_u_min = -0.0824; // Walk - parameters.walk.alpha_u = 1.43; - parameters.walk.betaTravelTime_u_min = -0.15; + parameters.walk.alpha_u = 1.2; + parameters.walk.betaTravelTime_u_min = -0.158; return parameters; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBikeUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBikeUtilityEstimator.java deleted file mode 100644 index 4c77d18bc..000000000 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBikeUtilityEstimator.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.eqasim.ile_de_france.mode_choice.utilities.estimators; - -import java.util.List; - -import org.eqasim.core.simulation.mode_choice.utilities.estimators.BikeUtilityEstimator; -import org.eqasim.core.simulation.mode_choice.utilities.predictors.BikePredictor; -import org.eqasim.core.simulation.mode_choice.utilities.predictors.PersonPredictor; -import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; -import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFSpatialPredictor; -import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFSpatialVariables; -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 IDFBikeUtilityEstimator extends BikeUtilityEstimator { - private final IDFModeParameters parameters; - private final IDFSpatialPredictor spatialPredictor; - - @Inject - public IDFBikeUtilityEstimator(IDFModeParameters parameters, IDFSpatialPredictor spatialPredictor, - PersonPredictor personPredictor, BikePredictor bikePredictor) { - super(parameters, personPredictor, bikePredictor); - - this.parameters = parameters; - this.spatialPredictor = spatialPredictor; - } - - protected double estimateUrbanUtility(IDFSpatialVariables variables) { - double utility = 0.0; - - if (variables.hasUrbanOrigin && variables.hasUrbanDestination) { - utility += parameters.idfBike.betaInsideUrbanArea; - } - - return utility; - } - - @Override - public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { - IDFSpatialVariables variables = spatialPredictor.predictVariables(person, trip, elements); - - double utility = 0.0; - - utility += super.estimateUtility(person, trip, elements); - utility += estimateUrbanUtility(variables); - - return utility; - } -} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarUtilityEstimator.java index ca318a373..24e9f1b1f 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarUtilityEstimator.java @@ -4,9 +4,8 @@ import org.eqasim.core.simulation.mode_choice.utilities.estimators.CarUtilityEstimator; import org.eqasim.core.simulation.mode_choice.utilities.predictors.CarPredictor; +import org.eqasim.core.simulation.mode_choice.utilities.variables.CarVariables; import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; -import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFSpatialPredictor; -import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFSpatialVariables; 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; @@ -15,39 +14,30 @@ public class IDFCarUtilityEstimator extends CarUtilityEstimator { private final IDFModeParameters parameters; - private final IDFSpatialPredictor spatialPredictor; + private final CarPredictor predictor; @Inject - public IDFCarUtilityEstimator(IDFModeParameters parameters, IDFSpatialPredictor spatialPredictor, - CarPredictor carPredictor) { - super(parameters, carPredictor); + public IDFCarUtilityEstimator(IDFModeParameters parameters, CarPredictor predictor) { + super(parameters, predictor); this.parameters = parameters; - this.spatialPredictor = spatialPredictor; + this.predictor = predictor; } - protected double estimateUrbanUtility(IDFSpatialVariables variables) { - double utility = 0.0; - - if (variables.hasUrbanOrigin && variables.hasUrbanDestination) { - utility += parameters.idfCar.betaInsideUrbanArea; - } - - if (variables.hasUrbanOrigin || variables.hasUrbanDestination) { - utility += parameters.idfCar.betaCrossingUrbanArea; - } - - return utility; + protected double estimateAccessEgressTimeUtility(CarVariables variables) { + return parameters.betaAccessTime_u_min * variables.accessEgressTime_min; } @Override public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { - IDFSpatialVariables variables = spatialPredictor.predictVariables(person, trip, elements); + CarVariables variables = predictor.predictVariables(person, trip, elements); double utility = 0.0; - utility += super.estimateUtility(person, trip, elements); - utility += estimateUrbanUtility(variables); + utility += estimateConstantUtility(); + utility += estimateTravelTimeUtility(variables); + utility += estimateAccessEgressTimeUtility(variables); + utility += estimateMonetaryCostUtility(variables); return utility; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFMotorbikeUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFMotorbikeUtilityEstimator.java new file mode 100644 index 000000000..38f1942c6 --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFMotorbikeUtilityEstimator.java @@ -0,0 +1,56 @@ +package org.eqasim.ile_de_france.mode_choice.utilities.estimators; + +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.ile_de_france.mode_choice.parameters.IDFModeParameters; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFMotorbikePredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFMotorbikeVariables; +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 IDFMotorbikeUtilityEstimator implements UtilityEstimator { + private final IDFModeParameters parameters; + private final IDFMotorbikePredictor predictor; + + @Inject + public IDFMotorbikeUtilityEstimator(IDFModeParameters parameters, IDFMotorbikePredictor predictor) { + this.parameters = parameters; + this.predictor = predictor; + } + + protected double estimateConstantUtility() { + return parameters.idfMotorbike.alpha_u; + } + + protected double estimateTravelTimeUtility(IDFMotorbikeVariables variables) { + return parameters.idfMotorbike.betaInVehicleTravelTime_u_min * variables.travelTime_min; + } + + protected double estimateAccessEgressTimeUtility(IDFMotorbikeVariables variables) { + return parameters.betaAccessTime_u_min * variables.accessEgressTime_min; + } + + protected double estimateMonetaryCostUtility(IDFMotorbikeVariables variables) { + return parameters.betaCost_u_MU * EstimatorUtils.interaction(variables.euclideanDistance_km, + parameters.referenceEuclideanDistance_km, parameters.lambdaCostEuclideanDistance) * variables.cost_MU; + } + + @Override + public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { + IDFMotorbikeVariables variables = predictor.predictVariables(person, trip, elements); + + double utility = 0.0; + + utility += estimateConstantUtility(); + utility += estimateTravelTimeUtility(variables); + utility += estimateAccessEgressTimeUtility(variables); + utility += estimateMonetaryCostUtility(variables); + + return utility; + } +} \ No newline at end of file diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPassengerUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPassengerUtilityEstimator.java new file mode 100644 index 000000000..610829606 --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPassengerUtilityEstimator.java @@ -0,0 +1,49 @@ +package org.eqasim.ile_de_france.mode_choice.utilities.estimators; + +import java.util.List; + +import org.eqasim.core.simulation.mode_choice.utilities.UtilityEstimator; +import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPassengerPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPassengerVariables; +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 IDFPassengerUtilityEstimator implements UtilityEstimator { + private final IDFModeParameters parameters; + private final IDFPassengerPredictor predictor; + + @Inject + public IDFPassengerUtilityEstimator(IDFModeParameters parameters, IDFPassengerPredictor predictor) { + this.parameters = parameters; + this.predictor = predictor; + } + + protected double estimateConstantUtility() { + return parameters.idfPassenger.alpha_u; + } + + protected double estimateTravelTimeUtility(IDFPassengerVariables variables) { + return parameters.idfPassenger.betaInVehicleTravelTime_u_min * variables.travelTime_min; + } + + protected double estimateAccessEgressTimeUtility(IDFPassengerVariables variables) { + return parameters.betaAccessTime_u_min * variables.accessEgressTime_min; + } + + @Override + public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { + IDFPassengerVariables variables = predictor.predictVariables(person, trip, elements); + + double utility = 0.0; + + utility += estimateConstantUtility(); + utility += estimateTravelTimeUtility(variables); + utility += estimateAccessEgressTimeUtility(variables); + + return utility; + } +} \ No newline at end of file diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java new file mode 100644 index 000000000..e61ec0dcf --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java @@ -0,0 +1,54 @@ +package org.eqasim.ile_de_france.mode_choice.utilities.estimators; + +import java.util.List; + +import org.eqasim.core.simulation.mode_choice.utilities.estimators.PtUtilityEstimator; +import org.eqasim.core.simulation.mode_choice.utilities.predictors.PtPredictor; +import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPersonPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPtPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPersonVariables; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPtVariables; +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 IDFPtUtilityEstimator extends PtUtilityEstimator { + private final IDFModeParameters parameters; + private final IDFPersonPredictor personPredictor; + private final IDFPtPredictor idfPtPredictor; + + @Inject + public IDFPtUtilityEstimator(IDFModeParameters parameters, IDFPtPredictor idfPtPredictor, + IDFPersonPredictor personPredictor, PtPredictor ptPredictor) { + super(parameters, ptPredictor); + + this.personPredictor = personPredictor; + this.idfPtPredictor = idfPtPredictor; + this.parameters = parameters; + } + + protected double estimateDrivingPermitUtility(IDFPersonVariables variables) { + return variables.hasDrivingPermit ? parameters.idfPt.betaDrivingPermit_u : 0.0; + } + + protected double estimateOnlyBus(IDFPtVariables variables) { + return variables.isOnlyBus ? parameters.idfPt.onlyBus_u : 0.0; + } + + @Override + public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { + IDFPersonVariables personVariables = personPredictor.predictVariables(person, trip, elements); + IDFPtVariables ptVariables = idfPtPredictor.predictVariables(person, trip, elements); + + double utility = 0.0; + + utility += super.estimateUtility(person, trip, elements); + utility += estimateDrivingPermitUtility(personVariables); + utility += estimateOnlyBus(ptVariables); + + return utility; + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFMotorbikePredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFMotorbikePredictor.java new file mode 100644 index 000000000..43cf46fe8 --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFMotorbikePredictor.java @@ -0,0 +1,53 @@ +package org.eqasim.ile_de_france.mode_choice.utilities.predictors; + +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.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFMotorbikeVariables; +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.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; +import org.matsim.core.router.TripStructureUtils; + +import com.google.common.base.Verify; +import com.google.inject.Inject; +import com.google.inject.name.Named; + +public class IDFMotorbikePredictor extends CachedVariablePredictor { + private final CostModel costModel; + + @Inject + public IDFMotorbikePredictor(@Named(IDFModeChoiceModule.MOTORBIKE) CostModel costModel) { + this.costModel = costModel; + } + + @Override + public IDFMotorbikeVariables predict(Person person, DiscreteModeChoiceTrip trip, + List elements) { + double motorbikeTravelTime_min = 0.0; + double accessEgressTime_min = 0.0; + + boolean foundCar = false; + + for (Leg leg : TripStructureUtils.getLegs(elements)) { + if (leg.getMode().equals(IDFModeChoiceModule.MOTORBIKE)) { + Verify.verify(!foundCar); + motorbikeTravelTime_min += leg.getTravelTime().seconds() / 60.0; + } else if (leg.getMode().equals(TransportMode.walk)) { + accessEgressTime_min += leg.getTravelTime().seconds() / 60.0; + } else { + throw new IllegalStateException("Unexpected mode in motorbike chain: " + leg.getMode()); + } + } + + double cost_MU = costModel.calculateCost_MU(person, trip, elements); + double euclideanDistance_km = PredictorUtils.calculateEuclideanDistance_km(trip); + + return new IDFMotorbikeVariables(motorbikeTravelTime_min, cost_MU, euclideanDistance_km, accessEgressTime_min); + } +} \ No newline at end of file diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPassengerPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPassengerPredictor.java new file mode 100644 index 000000000..2fea60c66 --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPassengerPredictor.java @@ -0,0 +1,42 @@ +package org.eqasim.ile_de_france.mode_choice.utilities.predictors; + +import java.util.List; + +import org.eqasim.core.simulation.mode_choice.utilities.predictors.CachedVariablePredictor; +import org.eqasim.core.simulation.mode_choice.utilities.predictors.PredictorUtils; +import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPassengerVariables; +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.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; +import org.matsim.core.router.TripStructureUtils; + +import com.google.common.base.Verify; + +public class IDFPassengerPredictor extends CachedVariablePredictor { + @Override + public IDFPassengerVariables predict(Person person, DiscreteModeChoiceTrip trip, + List elements) { + double passengerTravelTime_min = 0.0; + double accessEgressTime_min = 0.0; + + boolean foundCar = false; + + for (Leg leg : TripStructureUtils.getLegs(elements)) { + if (leg.getMode().equals(IDFModeChoiceModule.PASSENGER)) { + Verify.verify(!foundCar); + passengerTravelTime_min += leg.getTravelTime().seconds() / 60.0; + } else if (leg.getMode().equals(TransportMode.walk)) { + accessEgressTime_min += leg.getTravelTime().seconds() / 60.0; + } else { + throw new IllegalStateException("Unexpected mode in passenger chain: " + leg.getMode()); + } + } + + double euclideanDistance_km = PredictorUtils.calculateEuclideanDistance_km(trip); + + return new IDFPassengerVariables(passengerTravelTime_min, euclideanDistance_km, accessEgressTime_min); + } +} \ No newline at end of file diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java index e4d5d5ca0..249b82371 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java @@ -7,12 +7,14 @@ 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 org.matsim.core.population.PersonUtils; public class IDFPersonPredictor extends CachedVariablePredictor { @Override protected IDFPersonVariables predict(Person person, DiscreteModeChoiceTrip trip, List elements) { boolean hasSubscription = IDFPredictorUtils.hasSubscription(person); - return new IDFPersonVariables(hasSubscription); + boolean hasDrivingPermit = !"no".equals(PersonUtils.getLicense(person)); + return new IDFPersonVariables(hasSubscription, hasDrivingPermit); } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java index 1672f3c16..b49d88e00 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java @@ -1,7 +1,7 @@ package org.eqasim.ile_de_france.mode_choice.utilities.predictors; -import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Person; +import org.matsim.core.population.PersonUtils; public class IDFPredictorUtils { static public boolean hasSubscription(Person person) { @@ -9,8 +9,24 @@ static public boolean hasSubscription(Person person) { return hasSubscription != null && hasSubscription; } - static public boolean isUrbanArea(Activity activity) { - Boolean isUrban = (Boolean) activity.getAttributes().getAttribute("isUrban"); - return isUrban != null && isUrban; + static public boolean isOutside(Person person) { + Boolean isOutside = (Boolean) person.getAttributes().getAttribute("outside"); + return isOutside != null && isOutside; + } + + static public boolean hasDrivingLicense(Person person) { + return !"no".equals(PersonUtils.getLicense(person)); + } + + static public boolean hasCarAvailability(Person person) { + return !"none".equals((String) person.getAttributes().getAttribute("carAvailability")); + } + + static public boolean hasBicycleAvailability(Person person) { + return !"none".equals((String) person.getAttributes().getAttribute("bicycleAvailability")); + } + + static public boolean hasMotorbikeAvailability(Person person) { + return !"none".equals((String) person.getAttributes().getAttribute("motorbikeAvailability")); } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java new file mode 100644 index 000000000..26014a3a0 --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java @@ -0,0 +1,53 @@ +package org.eqasim.ile_de_france.mode_choice.utilities.predictors; + +import java.util.List; + +import org.eqasim.core.simulation.mode_choice.utilities.predictors.CachedVariablePredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPtVariables; +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.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; +import org.matsim.pt.routes.TransitPassengerRoute; +import org.matsim.pt.transitSchedule.api.TransitLine; +import org.matsim.pt.transitSchedule.api.TransitRoute; +import org.matsim.pt.transitSchedule.api.TransitSchedule; + +import com.google.inject.Inject; + +public class IDFPtPredictor extends CachedVariablePredictor { + private final TransitSchedule schedule; + + @Inject + public IDFPtPredictor(TransitSchedule schedule) { + this.schedule = schedule; + } + + @Override + public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List elements) { + int busCount = 0; + int subwayCount = 0; + int otherCount = 0; + + for (PlanElement element : elements) { + if (element instanceof Leg leg) { + if (leg instanceof TransitPassengerRoute route) { + TransitLine transitLine = schedule.getTransitLines().get(route.getLineId()); + TransitRoute transitRoute = transitLine.getRoutes().get(route.getRouteId()); + String transportMode = transitRoute.getTransportMode(); + + if (transportMode.equals("bus")) { + busCount++; + } else if (transportMode.equals("subway")) { + subwayCount++; + } + } + } + } + + boolean isOnlyBus = busCount > 0 && subwayCount == 0 && otherCount == 0; + boolean hasOnlySubwayAndBus = (busCount > 0 || subwayCount > 0) && otherCount == 0; + + return new IDFPtVariables(isOnlyBus, hasOnlySubwayAndBus); + } +} \ No newline at end of file diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFSpatialPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFSpatialPredictor.java deleted file mode 100644 index dbafe6437..000000000 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFSpatialPredictor.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.eqasim.ile_de_france.mode_choice.utilities.predictors; - -import java.util.List; - -import org.eqasim.core.simulation.mode_choice.utilities.predictors.CachedVariablePredictor; -import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFSpatialVariables; -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.Singleton; - -@Singleton -public class IDFSpatialPredictor extends CachedVariablePredictor { - @Override - protected IDFSpatialVariables predict(Person person, DiscreteModeChoiceTrip trip, - List elements) { - boolean hasUrbanOrigin = IDFPredictorUtils.isUrbanArea(trip.getOriginActivity()); - boolean hasUrbanDestination = IDFPredictorUtils.isUrbanArea(trip.getDestinationActivity()); - - return new IDFSpatialVariables(hasUrbanOrigin, hasUrbanDestination); - } -} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFMotorbikeVariables.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFMotorbikeVariables.java new file mode 100644 index 000000000..31065c9ad --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFMotorbikeVariables.java @@ -0,0 +1,18 @@ +package org.eqasim.ile_de_france.mode_choice.utilities.variables; + +import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; + +public class IDFMotorbikeVariables implements BaseVariables { + final public double travelTime_min; + final public double cost_MU; + final public double euclideanDistance_km; + final public double accessEgressTime_min; + + public IDFMotorbikeVariables(double travelTime_min, double cost_MU, double euclideanDistance_km, + double accessEgressTime_min) { + this.travelTime_min = travelTime_min; + this.cost_MU = cost_MU; + this.euclideanDistance_km = euclideanDistance_km; + this.accessEgressTime_min = accessEgressTime_min; + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPassengerVariables.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPassengerVariables.java new file mode 100644 index 000000000..6701629a9 --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPassengerVariables.java @@ -0,0 +1,15 @@ +package org.eqasim.ile_de_france.mode_choice.utilities.variables; + +import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; + +public class IDFPassengerVariables implements BaseVariables { + final public double travelTime_min; + final public double euclideanDistance_km; + final public double accessEgressTime_min; + + public IDFPassengerVariables(double travelTime_min, double euclideanDistance_km, double accessEgressTime_min) { + this.travelTime_min = travelTime_min; + this.euclideanDistance_km = euclideanDistance_km; + this.accessEgressTime_min = accessEgressTime_min; + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPersonVariables.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPersonVariables.java index f3d821c52..9d668747d 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPersonVariables.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPersonVariables.java @@ -4,8 +4,10 @@ public class IDFPersonVariables implements BaseVariables { public final boolean hasSubscription; + public final boolean hasDrivingPermit; - public IDFPersonVariables(boolean hasSubscription) { + public IDFPersonVariables(boolean hasSubscription, boolean hasDrivingPermit) { this.hasSubscription = hasSubscription; + this.hasDrivingPermit = hasDrivingPermit; } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPtVariables.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPtVariables.java new file mode 100644 index 000000000..a8e8f705e --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPtVariables.java @@ -0,0 +1,13 @@ +package org.eqasim.ile_de_france.mode_choice.utilities.variables; + +import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; + +public class IDFPtVariables implements BaseVariables { + public final boolean isOnlyBus; + public final boolean hasOnlySubwayAndBus; + + public IDFPtVariables(boolean isOnlyBus, boolean hasOnlySubwayAndBus) { + this.isOnlyBus = isOnlyBus; + this.hasOnlySubwayAndBus = hasOnlySubwayAndBus; + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFSpatialVariables.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFSpatialVariables.java deleted file mode 100644 index 6edc67e88..000000000 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFSpatialVariables.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.eqasim.ile_de_france.mode_choice.utilities.variables; - -import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; - -public class IDFSpatialVariables implements BaseVariables { - public final boolean hasUrbanOrigin; - public final boolean hasUrbanDestination; - - public IDFSpatialVariables(boolean hasUrbanOrigin, boolean hasUrbanDestination) { - this.hasUrbanOrigin = hasUrbanOrigin; - this.hasUrbanDestination = hasUrbanDestination; - } -} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index 96bc9010f..42d573b33 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -27,7 +27,9 @@ static public void adaptConfiguration(Config config, String prefix) { eqasimConfig.setCostModel(TransportMode.pt, IDFModeChoiceModule.PT_COST_MODEL_NAME); eqasimConfig.setEstimator(TransportMode.car, IDFModeChoiceModule.CAR_ESTIMATOR_NAME); - eqasimConfig.setEstimator(TransportMode.bike, IDFModeChoiceModule.BIKE_ESTIMATOR_NAME); + eqasimConfig.setEstimator(IDFModeChoiceModule.BICYCLE, IDFModeChoiceModule.BICYCLE_ESTIMATOR_NAME); + eqasimConfig.setEstimator(IDFModeChoiceModule.MOTORBIKE, IDFModeChoiceModule.MOTORBIKE_ESTIMATOR_NAME); + eqasimConfig.setEstimator(IDFModeChoiceModule.PASSENGER, IDFModeChoiceModule.PASSENGER_ESTIMATOR_NAME); DiscreteModeChoiceConfigGroup dmcConfig = (DiscreteModeChoiceConfigGroup) config.getModules() .get(DiscreteModeChoiceConfigGroup.GROUP_NAME); From 748bac629d051ab48de2a76f824959c1ecb36393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 1 Oct 2024 14:53:00 +0200 Subject: [PATCH 05/81] prepare for testing --- .../spatial/ImputeSpatialAttribute.java | 22 +++++- .../spatial/RunImputeSpatialAttribute.java | 17 ++++- .../eqasim/ile_de_france/RunSimulation.java | 76 +++++++++++++++++++ .../mode_choice/IDFModeChoiceModule.java | 16 ++++ .../mode_choice/costs/IDFPtCostModel.java | 7 +- .../utilities/predictors/IDFPtPredictor.java | 26 ++++++- .../utilities/variables/IDFPtVariables.java | 4 +- .../scenario/RunAdaptConfig.java | 42 +++++++++- 8 files changed, 199 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/scenario/spatial/ImputeSpatialAttribute.java b/core/src/main/java/org/eqasim/core/scenario/spatial/ImputeSpatialAttribute.java index 3c948a4c9..d76d34b7f 100644 --- a/core/src/main/java/org/eqasim/core/scenario/spatial/ImputeSpatialAttribute.java +++ b/core/src/main/java/org/eqasim/core/scenario/spatial/ImputeSpatialAttribute.java @@ -13,6 +13,8 @@ import org.matsim.api.core.v01.population.Population; import org.matsim.core.router.TripStructureUtils; import org.matsim.core.router.TripStructureUtils.StageActivityHandling; +import org.matsim.pt.transitSchedule.api.TransitSchedule; +import org.matsim.pt.transitSchedule.api.TransitStopFacility; public class ImputeSpatialAttribute { private final Geometry geometry; @@ -30,7 +32,8 @@ public void run(Population population) throws InterruptedException { for (Person person : population.getPersons().values()) { for (Plan plan : person.getPlans()) { - for (Activity activity : TripStructureUtils.getActivities(plan, StageActivityHandling.ExcludeStageActivities)) { + for (Activity activity : TripStructureUtils.getActivities(plan, + StageActivityHandling.ExcludeStageActivities)) { Point point = factory .createPoint(new Coordinate(activity.getCoord().getX(), activity.getCoord().getY())); @@ -62,4 +65,21 @@ public void run(Network network) throws InterruptedException { progress.close(); } + + public void run(TransitSchedule schedule) throws InterruptedException { + ParallelProgress progress = new ParallelProgress("Imputing spatial schedule attributes ...", + schedule.getFacilities().size()); + + for (TransitStopFacility facility : schedule.getFacilities().values()) { + Point point = factory.createPoint(new Coordinate(facility.getCoord().getX(), facility.getCoord().getY())); + + if (geometry.covers(point)) { + facility.getAttributes().putAttribute(attribute, true); + } + + progress.update(); + } + + progress.close(); + } } diff --git a/core/src/main/java/org/eqasim/core/scenario/spatial/RunImputeSpatialAttribute.java b/core/src/main/java/org/eqasim/core/scenario/spatial/RunImputeSpatialAttribute.java index 08bce0d8e..b0fc697b4 100644 --- a/core/src/main/java/org/eqasim/core/scenario/spatial/RunImputeSpatialAttribute.java +++ b/core/src/main/java/org/eqasim/core/scenario/spatial/RunImputeSpatialAttribute.java @@ -18,13 +18,15 @@ import org.matsim.core.population.io.PopulationReader; import org.matsim.core.population.io.PopulationWriter; import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.pt.transitSchedule.api.TransitScheduleReader; +import org.matsim.pt.transitSchedule.api.TransitScheduleWriter; public class RunImputeSpatialAttribute { static public void main(String[] args) throws ConfigurationException, MalformedURLException, IOException, InterruptedException { CommandLine cmd = new CommandLine.Builder(args) // .allowOptions("input-population-path", "input-network-path", "output-population-path", - "output-network-path") // + "output-network-path", "input-schedule-path", "output-schedule-path") // .requireOptions("shape-path", "shape-attribute", "shape-value", "attribute") // .build(); @@ -36,6 +38,10 @@ static public void main(String[] args) throw new IllegalStateException("Both input and output path must be given for the network."); } + if (cmd.hasOption("input-schedule-path") ^ cmd.hasOption("output-schedule-path")) { + throw new IllegalStateException("Both input and output path must be given for the schedule."); + } + // Load shape String shapeAttribute = cmd.getOptionStrict("shape-attribute"); String shapeValue = cmd.getOptionStrict("shape-value"); @@ -68,5 +74,14 @@ static public void main(String[] args) algorithm.run(scenario.getPopulation()); new PopulationWriter(scenario.getPopulation()).write(cmd.getOptionStrict("output-population-path")); } + + // Load schedule + if (cmd.hasOption("input-schedule-path")) { + File populationPath = new File(cmd.getOptionStrict("input-schedule-path")); + new TransitScheduleReader(scenario).readFile(populationPath.toString()); + algorithm.run(scenario.getTransitSchedule()); + new TransitScheduleWriter(scenario.getTransitSchedule()) + .writeFile(cmd.getOptionStrict("output-schedule-path")); + } } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java index 4a5ce91bd..95c288a56 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java @@ -1,16 +1,39 @@ package org.eqasim.ile_de_france; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.eqasim.core.components.config.EqasimConfigGroup; import org.eqasim.core.scenario.validation.VehiclesValidator; import org.eqasim.core.simulation.analysis.EqasimAnalysisModule; import org.eqasim.core.simulation.mode_choice.EqasimModeChoiceModule; import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; +import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Plan; +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.CommandLine; import org.matsim.core.config.CommandLine.ConfigurationException; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.RoutingConfigGroup.AccessEgressType; +import org.matsim.core.config.groups.RoutingConfigGroup.TeleportedModeParams; +import org.matsim.core.config.groups.ScoringConfigGroup.ModeParams; import org.matsim.core.controler.Controler; +import org.matsim.core.router.TripStructureUtils; import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.vehicles.Vehicle; +import org.matsim.vehicles.VehicleType; +import org.matsim.vehicles.VehicleUtils; +import org.matsim.vehicles.Vehicles; +import org.matsim.vehicles.VehiclesFactory; public class RunSimulation { static public void main(String[] args) throws ConfigurationException { @@ -30,6 +53,59 @@ static public void main(String[] args) throws ConfigurationException { ScenarioUtils.loadScenario(scenario); configurator.adjustScenario(scenario); + /*-{ + // TODO: Make this static! > OK looks like everything is covered in pipeline + Vehicles vehicles = scenario.getVehicles(); + VehiclesFactory factory = vehicles.getFactory(); + + VehicleType vehicleType = vehicles.getVehicleTypes() + .get(Id.create("defaultVehicleType", VehicleType.class)); + + // ok should be done in pipeline + for (Person person : scenario.getPopulation().getPersons().values()) { + Map> personVehicles = new HashMap<>(); + + for (String mode : Arrays.asList("motorbike", "passenger")) { + Vehicle vehicle = factory.createVehicle(Id.createVehicleId(person.getId().toString() + ":" + mode), + vehicleType); + vehicles.addVehicle(vehicle); + + personVehicles.put(mode, vehicle.getId()); + } + + VehicleUtils.insertVehicleIdsIntoPersonAttributes(person, personVehicles); + } + + for (Person person : scenario.getPopulation().getPersons().values()) { + person.getAttributes().putAttribute("bicycleAvailability", + person.getAttributes().getAttribute("bikeAvailability")); // ok done in pipeline + person.getAttributes().putAttribute("motorbikeAvailability", + person.getAttributes().getAttribute("bikeAvailability")); // ok done in pipeline + + // ok mode changes in pipeline + for (Plan plan : person.getPlans()) { + for (Leg leg : TripStructureUtils.getLegs(plan)) { + if (leg.getMode().equals("bike")) { + leg.setMode("bicycle"); + TripStructureUtils.setRoutingMode(leg, "bicycle"); + } + } + } + } + + // OK done with pt2matsim + for (Link link : scenario.getNetwork().getLinks().values()) { + Set allowedModes = new HashSet<>(link.getAllowedModes()); + + if (allowedModes.contains("car")) { + allowedModes.add("passenger"); + allowedModes.add("motorbike"); + } + + link.setAllowedModes(allowedModes); + } + }*/ + Controler controller = new Controler(scenario); configurator.configureController(controller); controller.addOverridingModule(new EqasimAnalysisModule()); diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java index c8863f1b8..4cef140a4 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java @@ -3,10 +3,12 @@ import java.io.File; import java.io.IOException; import java.util.List; +import java.util.Map; import org.eqasim.core.components.config.EqasimConfigGroup; 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.mode_choice.tour_finder.ActivityTourFinderWithExcludedActivities; import org.eqasim.core.simulation.mode_choice.utilities.estimators.BikeUtilityEstimator; @@ -19,15 +21,20 @@ import org.eqasim.ile_de_france.mode_choice.utilities.estimators.IDFMotorbikeUtilityEstimator; import org.eqasim.ile_de_france.mode_choice.utilities.estimators.IDFPassengerUtilityEstimator; import org.eqasim.ile_de_france.mode_choice.utilities.estimators.IDFPtUtilityEstimator; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFMotorbikePredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPassengerPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPersonPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPtPredictor; import org.matsim.contribs.discrete_mode_choice.components.tour_finder.ActivityTourFinder; import org.matsim.contribs.discrete_mode_choice.modules.config.ActivityTourFinderConfigGroup; import org.matsim.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup; import org.matsim.core.config.CommandLine; import org.matsim.core.config.CommandLine.ConfigurationException; +import com.google.inject.Provider; import com.google.inject.Provides; import com.google.inject.Singleton; +import com.google.inject.name.Named; public class IDFModeChoiceModule extends AbstractEqasimExtension { private final CommandLine commandLine; @@ -61,6 +68,9 @@ protected void installEqasimExtension() { bindModeAvailability(MODE_AVAILABILITY_NAME).to(IDFModeAvailability.class); bind(IDFPersonPredictor.class); + bind(IDFMotorbikePredictor.class); + bind(IDFPassengerPredictor.class); + bind(IDFPtPredictor.class); bindCostModel(CAR_COST_MODEL_NAME).to(IDFCarCostModel.class); bindCostModel(MOTORBIKE_COST_MODEL_NAME).to(IDFMotorbikeCostModel.class); @@ -112,4 +122,10 @@ public ActivityTourFinderWithExcludedActivities provideActivityTourFinderWithExc return new ActivityTourFinderWithExcludedActivities(List.of("outside"), new ActivityTourFinder(config.getActivityTypes())); } + + @Provides + @Named("motorbike") + public CostModel providePtCostModel(Map> factory, EqasimConfigGroup config) { + return getCostModel(factory, config, "motorbike"); + } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java index 4a5780809..8c98f0510 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java @@ -43,13 +43,8 @@ public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List< // II) Special case: Within Paris or only metro and bus IDFPtVariables ptVariables = ptPredictor.predictVariables(person, trip, elements); - boolean isWithinParis = false; - if (true) { - throw new IllegalStateException("find out if this is in paris"); - } - - if (ptVariables.hasOnlySubwayAndBus || isWithinParis) { + if (ptVariables.hasOnlySubwayAndBus || ptVariables.isWithinParis) { return 1.8; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java index 26014a3a0..2f1508fed 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java @@ -12,10 +12,13 @@ import org.matsim.pt.transitSchedule.api.TransitLine; import org.matsim.pt.transitSchedule.api.TransitRoute; import org.matsim.pt.transitSchedule.api.TransitSchedule; +import org.matsim.pt.transitSchedule.api.TransitStopFacility; import com.google.inject.Inject; public class IDFPtPredictor extends CachedVariablePredictor { + static public final String PARIS_ATTRIBUTE = "isParis"; + private final TransitSchedule schedule; @Inject @@ -29,6 +32,9 @@ public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List 0 && subwayCount == 0 && otherCount == 0; boolean hasOnlySubwayAndBus = (busCount > 0 || subwayCount > 0) && otherCount == 0; - return new IDFPtVariables(isOnlyBus, hasOnlySubwayAndBus); + boolean isWithinParis = false; + + if (firstRoute != null) { + TransitStopFacility startFacility = schedule.getFacilities().get(firstRoute.getAccessStopId()); + TransitStopFacility endFacility = schedule.getFacilities().get(lastRoute.getEgressStopId()); + + Boolean startParis = (Boolean) startFacility.getAttributes().getAttribute(PARIS_ATTRIBUTE); + Boolean endParis = (Boolean) endFacility.getAttributes().getAttribute(PARIS_ATTRIBUTE); + + isWithinParis = startParis != null && endParis != null && startParis && endParis; + } + + return new IDFPtVariables(isOnlyBus, hasOnlySubwayAndBus, isWithinParis); } } \ No newline at end of file diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPtVariables.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPtVariables.java index a8e8f705e..461f1de3e 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPtVariables.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPtVariables.java @@ -5,9 +5,11 @@ public class IDFPtVariables implements BaseVariables { public final boolean isOnlyBus; public final boolean hasOnlySubwayAndBus; + public final boolean isWithinParis; - public IDFPtVariables(boolean isOnlyBus, boolean hasOnlySubwayAndBus) { + public IDFPtVariables(boolean isOnlyBus, boolean hasOnlySubwayAndBus, boolean isWithinParis) { this.isOnlyBus = isOnlyBus; this.hasOnlySubwayAndBus = hasOnlySubwayAndBus; + this.isWithinParis = isWithinParis; } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index 42d573b33..a37e2c5f8 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -1,16 +1,25 @@ package org.eqasim.ile_de_france.scenario; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + import org.eqasim.core.components.config.ConfigAdapter; import org.eqasim.core.components.config.EqasimConfigGroup; +import org.eqasim.core.simulation.mode_choice.EqasimModeChoiceModule; import org.eqasim.core.simulation.mode_choice.epsilon.AdaptConfigForEpsilon; import org.eqasim.ile_de_france.IDFConfigurator; import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; import org.matsim.api.core.v01.TransportMode; 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.CommandLine.ConfigurationException; import org.matsim.core.config.Config; import org.matsim.core.config.groups.QSimConfigGroup; import org.matsim.core.config.groups.QSimConfigGroup.VehiclesSource; +import org.matsim.core.config.groups.RoutingConfigGroup.AccessEgressType; +import org.matsim.core.config.groups.RoutingConfigGroup.TeleportedModeParams; +import org.matsim.core.config.groups.ScoringConfigGroup.ModeParams; import org.matsim.core.config.groups.VehiclesConfigGroup; public class RunAdaptConfig { @@ -20,22 +29,53 @@ static public void main(String[] args) throws ConfigurationException { } static public void adaptConfiguration(Config config, String prefix) { + // MATSim: routing + config.routing().setAccessEgressType(AccessEgressType.accessEgressModeToLink); + + Set networkModes = new HashSet<>(config.routing().getNetworkModes()); + networkModes.add("passenger"); + networkModes.add("motorbike"); + config.routing().setNetworkModes(networkModes); + + // MATSim: scoring + TeleportedModeParams bicycleRouteParams = new TeleportedModeParams(); + bicycleRouteParams.setMode("bicycle"); + bicycleRouteParams.setTeleportedModeSpeed(15.0 / 3.6); + bicycleRouteParams.setBeelineDistanceFactor(1.3); + config.routing().addTeleportedModeParams(bicycleRouteParams); + + for (String mode : Arrays.asList("motorbike", "bicycle", "passenger")) { + ModeParams modeScoringParams = new ModeParams(mode); + modeScoringParams.setMarginalUtilityOfTraveling(-1.0); + config.scoring().addModeParams(modeScoringParams); + } + // Adjust eqasim config EqasimConfigGroup eqasimConfig = EqasimConfigGroup.get(config); eqasimConfig.setCostModel(TransportMode.car, IDFModeChoiceModule.CAR_COST_MODEL_NAME); eqasimConfig.setCostModel(TransportMode.pt, IDFModeChoiceModule.PT_COST_MODEL_NAME); + eqasimConfig.setCostModel(IDFModeChoiceModule.MOTORBIKE, IDFModeChoiceModule.MOTORBIKE_COST_MODEL_NAME); eqasimConfig.setEstimator(TransportMode.car, IDFModeChoiceModule.CAR_ESTIMATOR_NAME); eqasimConfig.setEstimator(IDFModeChoiceModule.BICYCLE, IDFModeChoiceModule.BICYCLE_ESTIMATOR_NAME); eqasimConfig.setEstimator(IDFModeChoiceModule.MOTORBIKE, IDFModeChoiceModule.MOTORBIKE_ESTIMATOR_NAME); eqasimConfig.setEstimator(IDFModeChoiceModule.PASSENGER, IDFModeChoiceModule.PASSENGER_ESTIMATOR_NAME); - + eqasimConfig.removeEstimator(TransportMode.bike); + + // Discrete mode choice DiscreteModeChoiceConfigGroup dmcConfig = (DiscreteModeChoiceConfigGroup) config.getModules() .get(DiscreteModeChoiceConfigGroup.GROUP_NAME); dmcConfig.setModeAvailability(IDFModeChoiceModule.MODE_AVAILABILITY_NAME); + Set tripConstraints = new HashSet<>(dmcConfig.getTripConstraints()); + tripConstraints.remove(EqasimModeChoiceModule.PASSENGER_CONSTRAINT_NAME); + dmcConfig.setTripConstraints(tripConstraints); + + VehicleTourConstraintConfigGroup vehicleTourConstraint = dmcConfig.getVehicleTourConstraintConfig(); + vehicleTourConstraint.setRestrictedModes(Arrays.asList("car", "bicycle", "motorbike")); + // Major crossing penalty from calibration eqasimConfig.setCrossingPenalty(4.2); From 757ea13fdcb528631ca7e42efa7d0b2a63a0aec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 1 Oct 2024 15:43:51 +0200 Subject: [PATCH 06/81] add fix for population routing --- .../core/scenario/routing/RunPopulationRouting.java | 6 +++++- .../test/java/org/eqasim/TestSimulationPipeline.java | 12 ++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/scenario/routing/RunPopulationRouting.java b/core/src/main/java/org/eqasim/core/scenario/routing/RunPopulationRouting.java index f0c7b7f2e..2607b1ad7 100644 --- a/core/src/main/java/org/eqasim/core/scenario/routing/RunPopulationRouting.java +++ b/core/src/main/java/org/eqasim/core/scenario/routing/RunPopulationRouting.java @@ -9,8 +9,10 @@ import org.eqasim.core.simulation.mode_choice.AbstractEqasimExtension; import org.eqasim.core.simulation.termination.EqasimTerminationConfigGroup; import org.matsim.api.core.v01.Scenario; +import org.matsim.contribs.discrete_mode_choice.modules.DiscreteModeChoiceModule; import org.matsim.core.config.CommandLine; import org.matsim.core.config.CommandLine.ConfigurationException; +import org.matsim.core.controler.AbstractModule; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.population.io.PopulationWriter; @@ -59,7 +61,9 @@ static public void main(String[] args) throws ConfigurationException, Interrupte Injector injector = new InjectorBuilder(scenario) // .addOverridingModules(configurator.getModules().stream() - .filter(module -> !(module instanceof AbstractEqasimExtension)).toList()) // + .filter(module -> !(module instanceof AbstractEqasimExtension)) // + .filter(module -> !(module instanceof DiscreteModeChoiceModule)) // + .toList()) // .addOverridingModule(new PopulationRouterModule(numberOfThreads, batchSize, true, modes)) // .addOverridingModule(new TimeInterpretationModule()).build(); diff --git a/core/src/test/java/org/eqasim/TestSimulationPipeline.java b/core/src/test/java/org/eqasim/TestSimulationPipeline.java index c9e417f01..11856461a 100644 --- a/core/src/test/java/org/eqasim/TestSimulationPipeline.java +++ b/core/src/test/java/org/eqasim/TestSimulationPipeline.java @@ -15,6 +15,7 @@ import org.eqasim.core.analysis.run.RunTripAnalysis; import org.eqasim.core.scenario.cutter.RunScenarioCutter; import org.eqasim.core.scenario.cutter.RunScenarioCutterV2; +import org.eqasim.core.scenario.routing.RunPopulationRouting; import org.eqasim.core.simulation.EqasimConfigurator; import org.eqasim.core.simulation.analysis.EqasimAnalysisModule; import org.eqasim.core.simulation.mode_choice.AbstractEqasimExtension; @@ -407,6 +408,7 @@ public void runVdf() throws CommandLine.ConfigurationException, IOException, Int @Test public void testPipeline() throws Exception { runMelunSimulation("melun_test/input/config.xml", "melun_test/output"); + runPopulationRouting(); runStandaloneModeChoice(); runVdf(); runAnalyses(); @@ -414,8 +416,14 @@ public void testPipeline() throws Exception { runCutter(); runCutterV2(); } - - + + public void runPopulationRouting() throws CommandLine.ConfigurationException, IOException, InterruptedException { + RunPopulationRouting.main(new String[] { + "--config-path", "melun_test/input/config.xml", + "--output-path", "melun_test/output/routed_population.xml.gz" + }); + } + public void runStandaloneModeChoice() throws CommandLine.ConfigurationException, IOException, InterruptedException { RunStandaloneModeChoice.main(new String[] { "--config-path", "melun_test/input/config.xml", From 047bb4fcf28c8c2fbad84949316c5b8bfae3e66e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 2 Oct 2024 21:56:44 +0200 Subject: [PATCH 07/81] add modes for convergence --- .../org/eqasim/ile_de_france/scenario/RunAdaptConfig.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index a37e2c5f8..8cc060ff4 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -8,6 +8,7 @@ import org.eqasim.core.components.config.EqasimConfigGroup; import org.eqasim.core.simulation.mode_choice.EqasimModeChoiceModule; import org.eqasim.core.simulation.mode_choice.epsilon.AdaptConfigForEpsilon; +import org.eqasim.core.simulation.termination.EqasimTerminationConfigGroup; import org.eqasim.ile_de_france.IDFConfigurator; import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; import org.matsim.api.core.v01.TransportMode; @@ -88,5 +89,9 @@ static public void adaptConfiguration(Config config, String prefix) { VehiclesConfigGroup vehiclesConfig = config.vehicles(); vehiclesConfig.setVehiclesFile(prefix + "vehicles.xml.gz"); + + // Convergence + EqasimTerminationConfigGroup terminationConfig = EqasimTerminationConfigGroup.getOrCreate(config); + terminationConfig.setModes(Arrays.asList("car", "passenger", "motorbike", "pt", "bicycle", "walk")); } } From 1ef466df88a0697db632f1597a94b34f87ca2072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 3 Oct 2024 16:04:32 +0200 Subject: [PATCH 08/81] revert integration of motorbikes for no --- .../mode_choice/IDFModeAvailability.java | 5 -- .../mode_choice/IDFModeChoiceModule.java | 13 +---- .../costs/IDFMotorbikeCostModel.java | 27 --------- .../parameters/IDFModeParameters.java | 23 ++------ .../IDFMotorbikeUtilityEstimator.java | 56 ------------------- .../predictors/IDFMotorbikePredictor.java | 53 ------------------ .../predictors/IDFPredictorUtils.java | 4 -- .../scenario/RunAdaptConfig.java | 26 ++++----- 8 files changed, 19 insertions(+), 188 deletions(-) delete mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFMotorbikeCostModel.java delete mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFMotorbikeUtilityEstimator.java delete mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFMotorbikePredictor.java diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java index cf77d84a1..9a3a9bf71 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java @@ -25,11 +25,6 @@ public Collection getAvailableModes(Person person, List> factory, EqasimConfigGroup config) { diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFMotorbikeCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFMotorbikeCostModel.java deleted file mode 100644 index 2fcea5fff..000000000 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFMotorbikeCostModel.java +++ /dev/null @@ -1,27 +0,0 @@ -package org.eqasim.ile_de_france.mode_choice.costs; - -import java.util.List; - -import org.eqasim.core.simulation.mode_choice.cost.AbstractCostModel; -import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; -import org.eqasim.ile_de_france.mode_choice.parameters.IDFCostParameters; -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 IDFMotorbikeCostModel extends AbstractCostModel { - private final IDFCostParameters costParameters; - - @Inject - public IDFMotorbikeCostModel(IDFCostParameters costParameters) { - super(IDFModeChoiceModule.MOTORBIKE); - this.costParameters = costParameters; - } - - @Override - public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List elements) { - return costParameters.motorbikeCost_EUR_km * getInVehicleDistance_km(elements); - } -} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java index fbab01232..714920e0c 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java @@ -8,7 +8,7 @@ public class IDFCarParameters { } public final IDFCarParameters idfCar = new IDFCarParameters(); - + public class IDFPassengerParameters { public double alpha_u; public double betaInVehicleTravelTime_u_min; @@ -17,20 +17,13 @@ public class IDFPassengerParameters { public final IDFPassengerParameters idfPassenger = new IDFPassengerParameters(); - public class IDFMotorbikeParameters { - public double alpha_u; - public double betaInVehicleTravelTime_u_min; - } - - public final IDFMotorbikeParameters idfMotorbike = new IDFMotorbikeParameters(); - public class IDFPtParameters { public double betaDrivingPermit_u; public double onlyBus_u; } public final IDFPtParameters idfPt = new IDFPtParameters(); - + public double betaAccessTime_u_min; public static IDFModeParameters buildDefault() { @@ -38,7 +31,7 @@ public static IDFModeParameters buildDefault() { // Access parameters.betaAccessTime_u_min = -0.0313; - + // Cost parameters.betaCost_u_MU = -0.474; parameters.lambdaCostEuclideanDistance = -0.274; @@ -47,18 +40,14 @@ public static IDFModeParameters buildDefault() { // Car parameters.car.alpha_u = -0.662; parameters.car.betaTravelTime_u_min = -0.0262; - + parameters.idfCar.betaInVehicleTravelTime_u_min = -0.0262; - + // Car passenger parameters.idfPassenger.alpha_u = -2.08; parameters.idfPassenger.betaDrivingPermit_u = -1.17; parameters.idfPassenger.betaInVehicleTravelTime_u_min = -0.0608; - // Motorbike - parameters.idfMotorbike.alpha_u = -2.2; - parameters.idfMotorbike.betaInVehicleTravelTime_u_min = -0.0321; - // PT parameters.pt.alpha_u = 0.0; parameters.pt.betaLineSwitch_u = -0.452; @@ -68,7 +57,7 @@ public static IDFModeParameters buildDefault() { parameters.idfPt.betaDrivingPermit_u = -0.712; parameters.idfPt.onlyBus_u = -1.42; - + // Bike parameters.bike.alpha_u = -3.42; parameters.bike.betaTravelTime_u_min = -0.0824; diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFMotorbikeUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFMotorbikeUtilityEstimator.java deleted file mode 100644 index 38f1942c6..000000000 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFMotorbikeUtilityEstimator.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.eqasim.ile_de_france.mode_choice.utilities.estimators; - -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.ile_de_france.mode_choice.parameters.IDFModeParameters; -import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFMotorbikePredictor; -import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFMotorbikeVariables; -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 IDFMotorbikeUtilityEstimator implements UtilityEstimator { - private final IDFModeParameters parameters; - private final IDFMotorbikePredictor predictor; - - @Inject - public IDFMotorbikeUtilityEstimator(IDFModeParameters parameters, IDFMotorbikePredictor predictor) { - this.parameters = parameters; - this.predictor = predictor; - } - - protected double estimateConstantUtility() { - return parameters.idfMotorbike.alpha_u; - } - - protected double estimateTravelTimeUtility(IDFMotorbikeVariables variables) { - return parameters.idfMotorbike.betaInVehicleTravelTime_u_min * variables.travelTime_min; - } - - protected double estimateAccessEgressTimeUtility(IDFMotorbikeVariables variables) { - return parameters.betaAccessTime_u_min * variables.accessEgressTime_min; - } - - protected double estimateMonetaryCostUtility(IDFMotorbikeVariables variables) { - return parameters.betaCost_u_MU * EstimatorUtils.interaction(variables.euclideanDistance_km, - parameters.referenceEuclideanDistance_km, parameters.lambdaCostEuclideanDistance) * variables.cost_MU; - } - - @Override - public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { - IDFMotorbikeVariables variables = predictor.predictVariables(person, trip, elements); - - double utility = 0.0; - - utility += estimateConstantUtility(); - utility += estimateTravelTimeUtility(variables); - utility += estimateAccessEgressTimeUtility(variables); - utility += estimateMonetaryCostUtility(variables); - - return utility; - } -} \ No newline at end of file diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFMotorbikePredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFMotorbikePredictor.java deleted file mode 100644 index 43cf46fe8..000000000 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFMotorbikePredictor.java +++ /dev/null @@ -1,53 +0,0 @@ -package org.eqasim.ile_de_france.mode_choice.utilities.predictors; - -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.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; -import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFMotorbikeVariables; -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.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; -import org.matsim.core.router.TripStructureUtils; - -import com.google.common.base.Verify; -import com.google.inject.Inject; -import com.google.inject.name.Named; - -public class IDFMotorbikePredictor extends CachedVariablePredictor { - private final CostModel costModel; - - @Inject - public IDFMotorbikePredictor(@Named(IDFModeChoiceModule.MOTORBIKE) CostModel costModel) { - this.costModel = costModel; - } - - @Override - public IDFMotorbikeVariables predict(Person person, DiscreteModeChoiceTrip trip, - List elements) { - double motorbikeTravelTime_min = 0.0; - double accessEgressTime_min = 0.0; - - boolean foundCar = false; - - for (Leg leg : TripStructureUtils.getLegs(elements)) { - if (leg.getMode().equals(IDFModeChoiceModule.MOTORBIKE)) { - Verify.verify(!foundCar); - motorbikeTravelTime_min += leg.getTravelTime().seconds() / 60.0; - } else if (leg.getMode().equals(TransportMode.walk)) { - accessEgressTime_min += leg.getTravelTime().seconds() / 60.0; - } else { - throw new IllegalStateException("Unexpected mode in motorbike chain: " + leg.getMode()); - } - } - - double cost_MU = costModel.calculateCost_MU(person, trip, elements); - double euclideanDistance_km = PredictorUtils.calculateEuclideanDistance_km(trip); - - return new IDFMotorbikeVariables(motorbikeTravelTime_min, cost_MU, euclideanDistance_km, accessEgressTime_min); - } -} \ No newline at end of file diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java index b49d88e00..d8169e0ac 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java @@ -25,8 +25,4 @@ static public boolean hasCarAvailability(Person person) { static public boolean hasBicycleAvailability(Person person) { return !"none".equals((String) person.getAttributes().getAttribute("bicycleAvailability")); } - - static public boolean hasMotorbikeAvailability(Person person) { - return !"none".equals((String) person.getAttributes().getAttribute("motorbikeAvailability")); - } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index 8cc060ff4..f3d8beea3 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -32,64 +32,62 @@ static public void main(String[] args) throws ConfigurationException { static public void adaptConfiguration(Config config, String prefix) { // MATSim: routing config.routing().setAccessEgressType(AccessEgressType.accessEgressModeToLink); - + Set networkModes = new HashSet<>(config.routing().getNetworkModes()); networkModes.add("passenger"); networkModes.add("motorbike"); config.routing().setNetworkModes(networkModes); - + // MATSim: scoring TeleportedModeParams bicycleRouteParams = new TeleportedModeParams(); bicycleRouteParams.setMode("bicycle"); bicycleRouteParams.setTeleportedModeSpeed(15.0 / 3.6); bicycleRouteParams.setBeelineDistanceFactor(1.3); config.routing().addTeleportedModeParams(bicycleRouteParams); - + for (String mode : Arrays.asList("motorbike", "bicycle", "passenger")) { ModeParams modeScoringParams = new ModeParams(mode); modeScoringParams.setMarginalUtilityOfTraveling(-1.0); config.scoring().addModeParams(modeScoringParams); } - + // Adjust eqasim config EqasimConfigGroup eqasimConfig = EqasimConfigGroup.get(config); eqasimConfig.setCostModel(TransportMode.car, IDFModeChoiceModule.CAR_COST_MODEL_NAME); eqasimConfig.setCostModel(TransportMode.pt, IDFModeChoiceModule.PT_COST_MODEL_NAME); - eqasimConfig.setCostModel(IDFModeChoiceModule.MOTORBIKE, IDFModeChoiceModule.MOTORBIKE_COST_MODEL_NAME); eqasimConfig.setEstimator(TransportMode.car, IDFModeChoiceModule.CAR_ESTIMATOR_NAME); eqasimConfig.setEstimator(IDFModeChoiceModule.BICYCLE, IDFModeChoiceModule.BICYCLE_ESTIMATOR_NAME); - eqasimConfig.setEstimator(IDFModeChoiceModule.MOTORBIKE, IDFModeChoiceModule.MOTORBIKE_ESTIMATOR_NAME); eqasimConfig.setEstimator(IDFModeChoiceModule.PASSENGER, IDFModeChoiceModule.PASSENGER_ESTIMATOR_NAME); eqasimConfig.removeEstimator(TransportMode.bike); - + // Discrete mode choice DiscreteModeChoiceConfigGroup dmcConfig = (DiscreteModeChoiceConfigGroup) config.getModules() .get(DiscreteModeChoiceConfigGroup.GROUP_NAME); dmcConfig.setModeAvailability(IDFModeChoiceModule.MODE_AVAILABILITY_NAME); - + Set tripConstraints = new HashSet<>(dmcConfig.getTripConstraints()); tripConstraints.remove(EqasimModeChoiceModule.PASSENGER_CONSTRAINT_NAME); dmcConfig.setTripConstraints(tripConstraints); - + VehicleTourConstraintConfigGroup vehicleTourConstraint = dmcConfig.getVehicleTourConstraintConfig(); vehicleTourConstraint.setRestrictedModes(Arrays.asList("car", "bicycle", "motorbike")); - + // Major crossing penalty from calibration eqasimConfig.setCrossingPenalty(4.2); - + // Epsilon AdaptConfigForEpsilon.run(config); - + // Vehicles QSimConfigGroup qsimConfig = config.qsim(); qsimConfig.setVehiclesSource(VehiclesSource.fromVehiclesData); - + VehiclesConfigGroup vehiclesConfig = config.vehicles(); vehiclesConfig.setVehiclesFile(prefix + "vehicles.xml.gz"); - + // Convergence EqasimTerminationConfigGroup terminationConfig = EqasimTerminationConfigGroup.getOrCreate(config); terminationConfig.setModes(Arrays.asList("car", "passenger", "motorbike", "pt", "bicycle", "walk")); From 0c8e28841c9464d1e399704e553320ac7431c1c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 3 Oct 2024 16:09:13 +0200 Subject: [PATCH 09/81] further cleanup --- .../eqasim/ile_de_france/RunSimulation.java | 5 +---- .../mode_choice/IDFModeChoiceModule.java | 6 ------ .../ile_de_france/mode_choice/SynpopTODO.java | 9 --------- .../parameters/IDFCostParameters.java | 2 -- .../variables/IDFMotorbikeVariables.java | 18 ------------------ .../ile_de_france/scenario/RunAdaptConfig.java | 7 +++---- 6 files changed, 4 insertions(+), 43 deletions(-) delete mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/SynpopTODO.java delete mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFMotorbikeVariables.java diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java index 95c288a56..19c6d0cdb 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java @@ -65,7 +65,7 @@ static public void main(String[] args) throws ConfigurationException { for (Person person : scenario.getPopulation().getPersons().values()) { Map> personVehicles = new HashMap<>(); - for (String mode : Arrays.asList("motorbike", "passenger")) { + for (String mode : Arrays.asList("passenger")) { Vehicle vehicle = factory.createVehicle(Id.createVehicleId(person.getId().toString() + ":" + mode), vehicleType); vehicles.addVehicle(vehicle); @@ -79,8 +79,6 @@ static public void main(String[] args) throws ConfigurationException { for (Person person : scenario.getPopulation().getPersons().values()) { person.getAttributes().putAttribute("bicycleAvailability", person.getAttributes().getAttribute("bikeAvailability")); // ok done in pipeline - person.getAttributes().putAttribute("motorbikeAvailability", - person.getAttributes().getAttribute("bikeAvailability")); // ok done in pipeline // ok mode changes in pipeline for (Plan plan : person.getPlans()) { @@ -99,7 +97,6 @@ static public void main(String[] args) throws ConfigurationException { if (allowedModes.contains("car")) { allowedModes.add("passenger"); - allowedModes.add("motorbike"); } link.setAllowedModes(allowedModes); diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java index 9466443d5..65d6bd0d5 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java @@ -111,10 +111,4 @@ public ActivityTourFinderWithExcludedActivities provideActivityTourFinderWithExc return new ActivityTourFinderWithExcludedActivities(List.of("outside"), new ActivityTourFinder(config.getActivityTypes())); } - - @Provides - @Named("motorbike") - public CostModel providePtCostModel(Map> factory, EqasimConfigGroup config) { - return getCostModel(factory, config, "motorbike"); - } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/SynpopTODO.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/SynpopTODO.java deleted file mode 100644 index e9162ac47..000000000 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/SynpopTODO.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.eqasim.ile_de_france.mode_choice; - -public class SynpopTODO { - /*- - * - bicycleAvailability - * - motorbikeAvailability - * - attribute to indicate paris for stops / activities - */ -} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java index bdf6b5e1a..098ecb189 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java @@ -4,13 +4,11 @@ public class IDFCostParameters implements ParameterDefinition { public double carCost_EUR_km = 0.0; - public double motorbikeCost_EUR_km = 0.0; public static IDFCostParameters buildDefault() { IDFCostParameters parameters = new IDFCostParameters(); parameters.carCost_EUR_km = 0.2; - parameters.motorbikeCost_EUR_km = 0.1; return parameters; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFMotorbikeVariables.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFMotorbikeVariables.java deleted file mode 100644 index 31065c9ad..000000000 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFMotorbikeVariables.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.eqasim.ile_de_france.mode_choice.utilities.variables; - -import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; - -public class IDFMotorbikeVariables implements BaseVariables { - final public double travelTime_min; - final public double cost_MU; - final public double euclideanDistance_km; - final public double accessEgressTime_min; - - public IDFMotorbikeVariables(double travelTime_min, double cost_MU, double euclideanDistance_km, - double accessEgressTime_min) { - this.travelTime_min = travelTime_min; - this.cost_MU = cost_MU; - this.euclideanDistance_km = euclideanDistance_km; - this.accessEgressTime_min = accessEgressTime_min; - } -} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index f3d8beea3..03917f9fc 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -35,7 +35,6 @@ static public void adaptConfiguration(Config config, String prefix) { Set networkModes = new HashSet<>(config.routing().getNetworkModes()); networkModes.add("passenger"); - networkModes.add("motorbike"); config.routing().setNetworkModes(networkModes); // MATSim: scoring @@ -45,7 +44,7 @@ static public void adaptConfiguration(Config config, String prefix) { bicycleRouteParams.setBeelineDistanceFactor(1.3); config.routing().addTeleportedModeParams(bicycleRouteParams); - for (String mode : Arrays.asList("motorbike", "bicycle", "passenger")) { + for (String mode : Arrays.asList("bicycle", "passenger")) { ModeParams modeScoringParams = new ModeParams(mode); modeScoringParams.setMarginalUtilityOfTraveling(-1.0); config.scoring().addModeParams(modeScoringParams); @@ -73,7 +72,7 @@ static public void adaptConfiguration(Config config, String prefix) { dmcConfig.setTripConstraints(tripConstraints); VehicleTourConstraintConfigGroup vehicleTourConstraint = dmcConfig.getVehicleTourConstraintConfig(); - vehicleTourConstraint.setRestrictedModes(Arrays.asList("car", "bicycle", "motorbike")); + vehicleTourConstraint.setRestrictedModes(Arrays.asList("car", "bicycle")); // Major crossing penalty from calibration eqasimConfig.setCrossingPenalty(4.2); @@ -90,6 +89,6 @@ static public void adaptConfiguration(Config config, String prefix) { // Convergence EqasimTerminationConfigGroup terminationConfig = EqasimTerminationConfigGroup.getOrCreate(config); - terminationConfig.setModes(Arrays.asList("car", "passenger", "motorbike", "pt", "bicycle", "walk")); + terminationConfig.setModes(Arrays.asList("car", "passenger", "pt", "bicycle", "walk")); } } From 9f95c51d6448fbbcde9a6669778d4d484859e860 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 3 Oct 2024 16:26:17 +0200 Subject: [PATCH 10/81] fix --- .../java/org/eqasim/core/simulation/EqasimConfigurator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 00c4d233e..96402b2a3 100644 --- a/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java +++ b/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java @@ -70,7 +70,8 @@ public EqasimConfigurator() { new SwissRailRaptorConfigGroup(), // new EqasimConfigGroup(), // new DiscreteModeChoiceConfigGroup(), // - new EqasimRaptorConfigGroup() // + new EqasimRaptorConfigGroup(), // + new EqasimTerminationConfigGroup() )); modules.addAll(Arrays.asList( // From c1937f3da5292349352d57043b1c589855d611d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 3 Oct 2024 16:39:45 +0200 Subject: [PATCH 11/81] config --- .../java/org/eqasim/core/simulation/EqasimConfigurator.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 96402b2a3..00c4d233e 100644 --- a/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java +++ b/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java @@ -70,8 +70,7 @@ public EqasimConfigurator() { new SwissRailRaptorConfigGroup(), // new EqasimConfigGroup(), // new DiscreteModeChoiceConfigGroup(), // - new EqasimRaptorConfigGroup(), // - new EqasimTerminationConfigGroup() + new EqasimRaptorConfigGroup() // )); modules.addAll(Arrays.asList( // From 4d7f4c709efdb170fb8a14f0264a1d92a322df8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 3 Oct 2024 16:43:20 +0200 Subject: [PATCH 12/81] config --- .../java/org/eqasim/core/simulation/EqasimConfigurator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 00c4d233e..72a69cecd 100644 --- a/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java +++ b/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java @@ -70,7 +70,8 @@ public EqasimConfigurator() { new SwissRailRaptorConfigGroup(), // new EqasimConfigGroup(), // new DiscreteModeChoiceConfigGroup(), // - new EqasimRaptorConfigGroup() // + new EqasimRaptorConfigGroup(), // + new EqasimTerminationConfigGroup() // )); modules.addAll(Arrays.asList( // From 0938b218257a83dfd42e9d9e119239b1a8116654 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 3 Oct 2024 16:59:40 +0200 Subject: [PATCH 13/81] reconfigure termination --- .../org/eqasim/core/simulation/EqasimConfigurator.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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 72a69cecd..c27c228c2 100644 --- a/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java +++ b/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java @@ -71,7 +71,7 @@ public EqasimConfigurator() { new EqasimConfigGroup(), // new DiscreteModeChoiceConfigGroup(), // new EqasimRaptorConfigGroup(), // - new EqasimTerminationConfigGroup() // + new EqasimTerminationConfigGroup() // )); modules.addAll(Arrays.asList( // @@ -82,7 +82,9 @@ public EqasimConfigurator() { new EpsilonModule(), // new EqasimRaptorModule(), new EqasimModeChoiceModule(), // - new EqasimTrafficModule() // + new EqasimTrafficModule(), // + new EqasimTerminationModule(), // + new ModeShareModule() // )); qsimModules.addAll(Arrays.asList( // @@ -97,7 +99,6 @@ public EqasimConfigurator() { DvrpQSimComponents.activateAllModes((MultiModal) controller.getConfig().getModules().get(MultiModeDrtConfigGroup.GROUP_NAME)).configure(components))); this.registerOptionalConfigGroup(new DvrpConfigGroup(), Collections.singleton(new DvrpModule())); - this.registerOptionalConfigGroup(new EqasimTerminationConfigGroup(), List.of(new EqasimTerminationModule(), new ModeShareModule())); this.registerOptionalConfigGroup(new MultiModeFeederDrtConfigGroup(), List.of(new MultiModeFeederDrtModule(), new EqasimFeederDrtModeChoiceModule())); this.registerOptionalConfigGroup( new TransitWithAbstractAbstractAccessModuleConfigGroup(), From 9d5623fd4f0773a7397057d60f460c3e332d7362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 3 Oct 2024 17:06:03 +0200 Subject: [PATCH 14/81] revert termination configuration --- .../org/eqasim/core/simulation/EqasimConfigurator.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) 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 c27c228c2..a46a7590e 100644 --- a/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java +++ b/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java @@ -70,8 +70,7 @@ public EqasimConfigurator() { new SwissRailRaptorConfigGroup(), // new EqasimConfigGroup(), // new DiscreteModeChoiceConfigGroup(), // - new EqasimRaptorConfigGroup(), // - new EqasimTerminationConfigGroup() // + new EqasimRaptorConfigGroup() // )); modules.addAll(Arrays.asList( // @@ -81,10 +80,7 @@ public EqasimConfigurator() { new EqasimComponentsModule(), // new EpsilonModule(), // new EqasimRaptorModule(), - new EqasimModeChoiceModule(), // - new EqasimTrafficModule(), // - new EqasimTerminationModule(), // - new ModeShareModule() // + new EqasimModeChoiceModule() // )); qsimModules.addAll(Arrays.asList( // @@ -99,6 +95,7 @@ public EqasimConfigurator() { DvrpQSimComponents.activateAllModes((MultiModal) controller.getConfig().getModules().get(MultiModeDrtConfigGroup.GROUP_NAME)).configure(components))); this.registerOptionalConfigGroup(new DvrpConfigGroup(), Collections.singleton(new DvrpModule())); + this.registerOptionalConfigGroup(new EqasimTerminationConfigGroup(), List.of(new EqasimTerminationModule(), new ModeShareModule())); this.registerOptionalConfigGroup(new MultiModeFeederDrtConfigGroup(), List.of(new MultiModeFeederDrtModule(), new EqasimFeederDrtModeChoiceModule())); this.registerOptionalConfigGroup( new TransitWithAbstractAbstractAccessModuleConfigGroup(), From 18b39257492e00894449c5b19b748d8f7fa598a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 3 Oct 2024 17:11:49 +0200 Subject: [PATCH 15/81] rename passenger -> car_passenger --- .../mode_choice/IDFModeAvailability.java | 2 +- .../mode_choice/IDFModeChoiceModule.java | 16 ++++++--------- .../parameters/IDFModeParameters.java | 10 +++++----- ...a => IDFCarPassengerUtilityEstimator.java} | 20 +++++++++---------- ...tor.java => IDFCarPassengerPredictor.java} | 10 +++++----- ...les.java => IDFCarPassengerVariables.java} | 4 ++-- .../scenario/RunAdaptConfig.java | 4 ++-- 7 files changed, 31 insertions(+), 35 deletions(-) rename ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/{IDFPassengerUtilityEstimator.java => IDFCarPassengerUtilityEstimator.java} (62%) rename ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/{IDFPassengerPredictor.java => IDFCarPassengerPredictor.java} (78%) rename ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/{IDFPassengerVariables.java => IDFCarPassengerVariables.java} (69%) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java index 9a3a9bf71..1b1c9d451 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java @@ -18,7 +18,7 @@ public Collection getAvailableModes(Person person, List elements) { - IDFPassengerVariables variables = predictor.predictVariables(person, trip, elements); + IDFCarPassengerVariables variables = predictor.predictVariables(person, trip, elements); double utility = 0.0; diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPassengerPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFCarPassengerPredictor.java similarity index 78% rename from ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPassengerPredictor.java rename to ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFCarPassengerPredictor.java index 2fea60c66..5d3cd491c 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPassengerPredictor.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFCarPassengerPredictor.java @@ -5,7 +5,7 @@ import org.eqasim.core.simulation.mode_choice.utilities.predictors.CachedVariablePredictor; import org.eqasim.core.simulation.mode_choice.utilities.predictors.PredictorUtils; import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; -import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPassengerVariables; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFCarPassengerVariables; import org.matsim.api.core.v01.TransportMode; import org.matsim.api.core.v01.population.Leg; import org.matsim.api.core.v01.population.Person; @@ -15,9 +15,9 @@ import com.google.common.base.Verify; -public class IDFPassengerPredictor extends CachedVariablePredictor { +public class IDFCarPassengerPredictor extends CachedVariablePredictor { @Override - public IDFPassengerVariables predict(Person person, DiscreteModeChoiceTrip trip, + public IDFCarPassengerVariables predict(Person person, DiscreteModeChoiceTrip trip, List elements) { double passengerTravelTime_min = 0.0; double accessEgressTime_min = 0.0; @@ -25,7 +25,7 @@ public IDFPassengerVariables predict(Person person, DiscreteModeChoiceTrip trip, boolean foundCar = false; for (Leg leg : TripStructureUtils.getLegs(elements)) { - if (leg.getMode().equals(IDFModeChoiceModule.PASSENGER)) { + if (leg.getMode().equals(IDFModeChoiceModule.CAR_PASSENGER)) { Verify.verify(!foundCar); passengerTravelTime_min += leg.getTravelTime().seconds() / 60.0; } else if (leg.getMode().equals(TransportMode.walk)) { @@ -37,6 +37,6 @@ public IDFPassengerVariables predict(Person person, DiscreteModeChoiceTrip trip, double euclideanDistance_km = PredictorUtils.calculateEuclideanDistance_km(trip); - return new IDFPassengerVariables(passengerTravelTime_min, euclideanDistance_km, accessEgressTime_min); + return new IDFCarPassengerVariables(passengerTravelTime_min, euclideanDistance_km, accessEgressTime_min); } } \ No newline at end of file diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPassengerVariables.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFCarPassengerVariables.java similarity index 69% rename from ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPassengerVariables.java rename to ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFCarPassengerVariables.java index 6701629a9..21523bc33 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPassengerVariables.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFCarPassengerVariables.java @@ -2,12 +2,12 @@ import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; -public class IDFPassengerVariables implements BaseVariables { +public class IDFCarPassengerVariables implements BaseVariables { final public double travelTime_min; final public double euclideanDistance_km; final public double accessEgressTime_min; - public IDFPassengerVariables(double travelTime_min, double euclideanDistance_km, double accessEgressTime_min) { + public IDFCarPassengerVariables(double travelTime_min, double euclideanDistance_km, double accessEgressTime_min) { this.travelTime_min = travelTime_min; this.euclideanDistance_km = euclideanDistance_km; this.accessEgressTime_min = accessEgressTime_min; diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index 03917f9fc..e43cc079f 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -58,7 +58,7 @@ static public void adaptConfiguration(Config config, String prefix) { eqasimConfig.setEstimator(TransportMode.car, IDFModeChoiceModule.CAR_ESTIMATOR_NAME); eqasimConfig.setEstimator(IDFModeChoiceModule.BICYCLE, IDFModeChoiceModule.BICYCLE_ESTIMATOR_NAME); - eqasimConfig.setEstimator(IDFModeChoiceModule.PASSENGER, IDFModeChoiceModule.PASSENGER_ESTIMATOR_NAME); + eqasimConfig.setEstimator(IDFModeChoiceModule.CAR_PASSENGER, IDFModeChoiceModule.CAR_PASSENGER_ESTIMATOR_NAME); eqasimConfig.removeEstimator(TransportMode.bike); // Discrete mode choice @@ -89,6 +89,6 @@ static public void adaptConfiguration(Config config, String prefix) { // Convergence EqasimTerminationConfigGroup terminationConfig = EqasimTerminationConfigGroup.getOrCreate(config); - terminationConfig.setModes(Arrays.asList("car", "passenger", "pt", "bicycle", "walk")); + terminationConfig.setModes(Arrays.asList("car", "car_passenger", "pt", "bicycle", "walk")); } } From a85e04fd604f1c6e6784aa6dce930c8d6417b786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 3 Oct 2024 18:32:41 +0200 Subject: [PATCH 16/81] update configurator --- .../java/org/eqasim/core/simulation/EqasimConfigurator.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 a46a7590e..23a491d02 100644 --- a/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java +++ b/core/src/main/java/org/eqasim/core/simulation/EqasimConfigurator.java @@ -79,8 +79,9 @@ public EqasimConfigurator() { new DiscreteModeChoiceModule(), // new EqasimComponentsModule(), // new EpsilonModule(), // - new EqasimRaptorModule(), - new EqasimModeChoiceModule() // + new EqasimRaptorModule(), // + new EqasimModeChoiceModule(), // + new EqasimTrafficModule() // )); qsimModules.addAll(Arrays.asList( // From 7c895345f5e7629195c73b8125f7dedba9a3285b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 3 Oct 2024 18:39:54 +0200 Subject: [PATCH 17/81] update parameters without motorbike --- .../parameters/IDFModeParameters.java | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java index 8ebac229d..7b4bcb5b7 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java @@ -3,12 +3,6 @@ import org.eqasim.core.simulation.mode_choice.parameters.ModeParameters; public class IDFModeParameters extends ModeParameters { - public class IDFCarParameters { - public double betaInVehicleTravelTime_u_min; - } - - public final IDFCarParameters idfCar = new IDFCarParameters(); - public class IDFCarPassengerParameters { public double alpha_u; public double betaInVehicleTravelTime_u_min; @@ -30,40 +24,38 @@ public static IDFModeParameters buildDefault() { IDFModeParameters parameters = new IDFModeParameters(); // Access - parameters.betaAccessTime_u_min = -0.0313; + parameters.betaAccessTime_u_min = -0.0318; // Cost - parameters.betaCost_u_MU = -0.474; - parameters.lambdaCostEuclideanDistance = -0.274; + parameters.betaCost_u_MU = -0.425; + parameters.lambdaCostEuclideanDistance = -0.268; parameters.referenceEuclideanDistance_km = 4.4; // Car - parameters.car.alpha_u = -0.662; - parameters.car.betaTravelTime_u_min = -0.0262; - - parameters.idfCar.betaInVehicleTravelTime_u_min = -0.0262; + parameters.car.alpha_u = -0.613; + parameters.car.betaTravelTime_u_min = -0.0285; // Car passenger - parameters.idfCarPassenger.alpha_u = -2.08; - parameters.idfCarPassenger.betaDrivingPermit_u = -1.17; - parameters.idfCarPassenger.betaInVehicleTravelTime_u_min = -0.0608; + parameters.idfCarPassenger.alpha_u = -2.04; + parameters.idfCarPassenger.betaDrivingPermit_u = -1.16; + parameters.idfCarPassenger.betaInVehicleTravelTime_u_min = -0.0605; // PT parameters.pt.alpha_u = 0.0; - parameters.pt.betaLineSwitch_u = -0.452; - parameters.pt.betaInVehicleTime_u_min = -0.0201; - parameters.pt.betaWaitingTime_u_min = -0.0191; + parameters.pt.betaLineSwitch_u = -0.457; + parameters.pt.betaInVehicleTime_u_min = -0.0195; + parameters.pt.betaWaitingTime_u_min = -0.0195; parameters.pt.betaAccessEgressTime_u_min = parameters.betaAccessTime_u_min; - parameters.idfPt.betaDrivingPermit_u = -0.712; - parameters.idfPt.onlyBus_u = -1.42; + parameters.idfPt.betaDrivingPermit_u = -0.722; + parameters.idfPt.onlyBus_u = -1.43; // Bike - parameters.bike.alpha_u = -3.42; - parameters.bike.betaTravelTime_u_min = -0.0824; + parameters.bike.alpha_u = -3.39; + parameters.bike.betaTravelTime_u_min = -0.0823; // Walk - parameters.walk.alpha_u = 1.2; + parameters.walk.alpha_u = 1.24; parameters.walk.betaTravelTime_u_min = -0.158; return parameters; From 8296a1cfe626d99708a99e998c861dde666f702e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Mon, 7 Oct 2024 07:59:33 +0200 Subject: [PATCH 18/81] add parking costs --- .../spatial/ImputeSpatialAttribute.java | 4 ++ .../mode_choice/costs/IDFCarCostModel.java | 49 ++++++++++++++++++- .../parameters/IDFCostParameters.java | 2 + .../predictors/IDFPersonPredictor.java | 6 +-- .../predictors/IDFPredictorUtils.java | 5 ++ .../variables/IDFPersonVariables.java | 4 +- 6 files changed, 64 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/scenario/spatial/ImputeSpatialAttribute.java b/core/src/main/java/org/eqasim/core/scenario/spatial/ImputeSpatialAttribute.java index d76d34b7f..8069f8c56 100644 --- a/core/src/main/java/org/eqasim/core/scenario/spatial/ImputeSpatialAttribute.java +++ b/core/src/main/java/org/eqasim/core/scenario/spatial/ImputeSpatialAttribute.java @@ -39,6 +39,10 @@ public void run(Population population) throws InterruptedException { if (geometry.contains(point)) { activity.getAttributes().putAttribute(attribute, true); + + if (activity.getType().equals("home")) { + person.getAttributes().putAttribute(attribute, true); + } } } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java index 8a8a45263..ac5153ee8 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java @@ -4,23 +4,68 @@ import org.eqasim.core.simulation.mode_choice.cost.AbstractCostModel; import org.eqasim.ile_de_france.mode_choice.parameters.IDFCostParameters; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPersonPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPersonVariables; import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.PlanElement; import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; +import org.matsim.core.utils.timing.TimeInterpretation; +import org.matsim.core.utils.timing.TimeTracker; import com.google.inject.Inject; public class IDFCarCostModel extends AbstractCostModel { + private final TimeInterpretation timeInterpretation; private final IDFCostParameters costParameters; + private final IDFPersonPredictor personPredictor; @Inject - public IDFCarCostModel(IDFCostParameters costParameters) { + public IDFCarCostModel(IDFCostParameters costParameters, IDFPersonPredictor personPredictor, + TimeInterpretation timeInterpretation) { super("car"); + this.costParameters = costParameters; + this.personPredictor = personPredictor; + this.timeInterpretation = timeInterpretation; } @Override public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List elements) { - return costParameters.carCost_EUR_km * getInVehicleDistance_km(elements); + double parkingCost_EUR = calculateParkingCost_EUR(person, trip, elements); + return costParameters.carCost_EUR_km * getInVehicleDistance_km(elements) + parkingCost_EUR; + } + + private double calculateParkingCost_EUR(Person person, DiscreteModeChoiceTrip trip, + List elements) { + IDFPersonVariables personVariables = personPredictor.predictVariables(person, trip, elements); + + if (!personVariables.isParisResident && hasParisDestination(trip)) { + final double parkingDuration_min; + + Plan plan = person.getSelectedPlan(); + if (trip.getDestinationActivity() == plan.getPlanElements().get(plan.getPlanElements().size() - 1)) { + parkingDuration_min = 8.0 * 3600.0 / 60.0; + } else { + TimeTracker timeTracker = new TimeTracker(timeInterpretation); + + timeTracker.setTime(trip.getDepartureTime()); + timeTracker.addElements(elements); + + double activityStartTime = timeTracker.getTime().seconds(); + timeTracker.addActivity(trip.getDestinationActivity()); + + parkingDuration_min = (timeTracker.getTime().seconds() - activityStartTime) / 60.0; + } + + return Math.max(1.0, Math.ceil(parkingDuration_min / 60.0)) * costParameters.parisParkingCost_EUR_h; + } + + return 0.0; + } + + private boolean hasParisDestination(DiscreteModeChoiceTrip trip) { + Boolean isParis = (Boolean) trip.getDestinationActivity().getAttributes().getAttribute("isParis"); + return isParis != null && isParis; } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java index 098ecb189..73e7929e3 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java @@ -4,11 +4,13 @@ public class IDFCostParameters implements ParameterDefinition { public double carCost_EUR_km = 0.0; + public double parisParkingCost_EUR_h = 0.0; public static IDFCostParameters buildDefault() { IDFCostParameters parameters = new IDFCostParameters(); parameters.carCost_EUR_km = 0.2; + parameters.parisParkingCost_EUR_h = 3.0; return parameters; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java index 249b82371..afd31a462 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java @@ -7,14 +7,14 @@ 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 org.matsim.core.population.PersonUtils; public class IDFPersonPredictor extends CachedVariablePredictor { @Override protected IDFPersonVariables predict(Person person, DiscreteModeChoiceTrip trip, List elements) { boolean hasSubscription = IDFPredictorUtils.hasSubscription(person); - boolean hasDrivingPermit = !"no".equals(PersonUtils.getLicense(person)); - return new IDFPersonVariables(hasSubscription, hasDrivingPermit); + boolean hasDrivingPermit = IDFPredictorUtils.hasDrivingLicense(person); + boolean isParisResident = IDFPredictorUtils.isParisResident(person); + return new IDFPersonVariables(hasSubscription, hasDrivingPermit, isParisResident); } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java index d8169e0ac..cc6f62dfb 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java @@ -25,4 +25,9 @@ static public boolean hasCarAvailability(Person person) { static public boolean hasBicycleAvailability(Person person) { return !"none".equals((String) person.getAttributes().getAttribute("bicycleAvailability")); } + + static public boolean isParisResident(Person person) { + Boolean isResident = (Boolean) person.getAttributes().getAttribute("isParis"); + return isResident != null && isResident; + } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPersonVariables.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPersonVariables.java index 9d668747d..a46adf04d 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPersonVariables.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPersonVariables.java @@ -5,9 +5,11 @@ public class IDFPersonVariables implements BaseVariables { public final boolean hasSubscription; public final boolean hasDrivingPermit; + public final boolean isParisResident; - public IDFPersonVariables(boolean hasSubscription, boolean hasDrivingPermit) { + public IDFPersonVariables(boolean hasSubscription, boolean hasDrivingPermit, boolean isParisResident) { this.hasSubscription = hasSubscription; this.hasDrivingPermit = hasDrivingPermit; + this.isParisResident = isParisResident; } } From a666bbb7e636a97900fed55868e68b06ed7650eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Mon, 7 Oct 2024 18:10:09 +0200 Subject: [PATCH 19/81] update certain definitions in estimator --- .../estimators/IDFPtUtilityEstimator.java | 43 ++++++++++--- .../utilities/predictors/IDFPtPredictor.java | 61 ++++++++++++++++++- .../utilities/variables/IDFPtVariables.java | 18 +++++- 3 files changed, 112 insertions(+), 10 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java index e61ec0dcf..b79c8859b 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java @@ -2,8 +2,8 @@ import java.util.List; -import org.eqasim.core.simulation.mode_choice.utilities.estimators.PtUtilityEstimator; -import org.eqasim.core.simulation.mode_choice.utilities.predictors.PtPredictor; +import org.eqasim.core.simulation.mode_choice.utilities.UtilityEstimator; +import org.eqasim.core.simulation.mode_choice.utilities.estimators.EstimatorUtils; import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPersonPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPtPredictor; @@ -15,21 +15,44 @@ import com.google.inject.Inject; -public class IDFPtUtilityEstimator extends PtUtilityEstimator { +public class IDFPtUtilityEstimator implements UtilityEstimator { private final IDFModeParameters parameters; private final IDFPersonPredictor personPredictor; private final IDFPtPredictor idfPtPredictor; @Inject public IDFPtUtilityEstimator(IDFModeParameters parameters, IDFPtPredictor idfPtPredictor, - IDFPersonPredictor personPredictor, PtPredictor ptPredictor) { - super(parameters, ptPredictor); - + IDFPersonPredictor personPredictor) { this.personPredictor = personPredictor; this.idfPtPredictor = idfPtPredictor; this.parameters = parameters; } + protected double estimateConstantUtility() { + return parameters.pt.alpha_u; + } + + protected double estimateAccessEgressTimeUtility(IDFPtVariables variables) { + return parameters.pt.betaAccessEgressTime_u_min * variables.accessEgressTime_min; + } + + protected double estimateInVehicleTimeUtility(IDFPtVariables variables) { + return parameters.pt.betaInVehicleTime_u_min * variables.inVehicleTime_min; + } + + protected double estimateWaitingTimeUtility(IDFPtVariables variables) { + return parameters.pt.betaWaitingTime_u_min * variables.waitingTime_min; + } + + protected double estimateLineSwitchUtility(IDFPtVariables variables) { + return parameters.pt.betaLineSwitch_u * variables.numberOfLineSwitches; + } + + protected double estimateMonetaryCostUtility(IDFPtVariables variables) { + return parameters.betaCost_u_MU * EstimatorUtils.interaction(variables.euclideanDistance_km, + parameters.referenceEuclideanDistance_km, parameters.lambdaCostEuclideanDistance) * variables.cost_MU; + } + protected double estimateDrivingPermitUtility(IDFPersonVariables variables) { return variables.hasDrivingPermit ? parameters.idfPt.betaDrivingPermit_u : 0.0; } @@ -45,7 +68,13 @@ public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List { static public final String PARIS_ATTRIBUTE = "isParis"; private final TransitSchedule schedule; + private final CostModel costModel; @Inject - public IDFPtPredictor(TransitSchedule schedule) { + public IDFPtPredictor(TransitSchedule schedule, @Named("pt") CostModel costModel) { this.schedule = schedule; + this.costModel = costModel; + } + + protected CostModel getCostModel() { + return this.costModel; } @Override public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List elements) { + int numberOfVehicularTrips = 0; + boolean isFirstWaitingTime = false; // different from standard estimator + + // Track relevant variables (from standard estimator) + double inVehicleTime_min = 0.0; + double waitingTime_min = 0.0; + double accessEgressTime_min = 0.0; + + // Track IDF variables int busCount = 0; int subwayCount = 0; int otherCount = 0; @@ -37,6 +56,36 @@ public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List 0 && subwayCount == 0 && otherCount == 0; boolean hasOnlySubwayAndBus = (busCount > 0 || subwayCount > 0) && otherCount == 0; @@ -72,6 +128,7 @@ public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List Date: Mon, 7 Oct 2024 18:52:32 +0200 Subject: [PATCH 20/81] avoid circular dependency for predictor --- .../estimators/IDFPtUtilityEstimator.java | 14 ++++++++++---- .../utilities/predictors/IDFPtPredictor.java | 12 +++--------- .../utilities/variables/IDFPtVariables.java | 4 +--- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java index b79c8859b..39bdaee0f 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java @@ -2,6 +2,7 @@ import java.util.List; +import org.eqasim.core.simulation.mode_choice.cost.CostModel; import org.eqasim.core.simulation.mode_choice.utilities.UtilityEstimator; import org.eqasim.core.simulation.mode_choice.utilities.estimators.EstimatorUtils; import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; @@ -14,18 +15,21 @@ import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; import com.google.inject.Inject; +import com.google.inject.name.Named; public class IDFPtUtilityEstimator implements UtilityEstimator { private final IDFModeParameters parameters; private final IDFPersonPredictor personPredictor; private final IDFPtPredictor idfPtPredictor; + private final CostModel costModel; @Inject public IDFPtUtilityEstimator(IDFModeParameters parameters, IDFPtPredictor idfPtPredictor, - IDFPersonPredictor personPredictor) { + IDFPersonPredictor personPredictor, @Named("pt") CostModel costModel) { this.personPredictor = personPredictor; this.idfPtPredictor = idfPtPredictor; this.parameters = parameters; + this.costModel = costModel; } protected double estimateConstantUtility() { @@ -48,9 +52,9 @@ protected double estimateLineSwitchUtility(IDFPtVariables variables) { return parameters.pt.betaLineSwitch_u * variables.numberOfLineSwitches; } - protected double estimateMonetaryCostUtility(IDFPtVariables variables) { + protected double estimateMonetaryCostUtility(IDFPtVariables variables, double cost_EUR) { return parameters.betaCost_u_MU * EstimatorUtils.interaction(variables.euclideanDistance_km, - parameters.referenceEuclideanDistance_km, parameters.lambdaCostEuclideanDistance) * variables.cost_MU; + parameters.referenceEuclideanDistance_km, parameters.lambdaCostEuclideanDistance) * cost_EUR; } protected double estimateDrivingPermitUtility(IDFPersonVariables variables) { @@ -66,6 +70,8 @@ public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List { static public final String PARIS_ATTRIBUTE = "isParis"; private final TransitSchedule schedule; - private final CostModel costModel; @Inject - public IDFPtPredictor(TransitSchedule schedule, @Named("pt") CostModel costModel) { + public IDFPtPredictor(TransitSchedule schedule) { this.schedule = schedule; - this.costModel = costModel; } protected CostModel getCostModel() { - return this.costModel; + return null; } @Override @@ -108,9 +105,6 @@ public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List 0 && subwayCount == 0 && otherCount == 0; @@ -129,6 +123,6 @@ public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List Date: Mon, 7 Oct 2024 22:06:02 +0200 Subject: [PATCH 21/81] fix error in cost model --- .../mode_choice/utilities/predictors/IDFPtPredictor.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java index c34eb34fe..dce29ec6e 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java @@ -92,6 +92,8 @@ public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List Date: Tue, 8 Oct 2024 08:09:50 +0200 Subject: [PATCH 22/81] idf pt estimator was not enabled --- .../java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index dadc344f3..b382ea34a 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -56,6 +56,7 @@ static public void adaptConfiguration(Config config, String prefix) { eqasimConfig.setCostModel(TransportMode.pt, IDFModeChoiceModule.PT_COST_MODEL_NAME); eqasimConfig.setEstimator(TransportMode.car, IDFModeChoiceModule.CAR_ESTIMATOR_NAME); + eqasimConfig.setEstimator(TransportMode.pt, IDFModeChoiceModule.PT_ESTIMATOR_NAME); eqasimConfig.setEstimator(IDFModeChoiceModule.BICYCLE, IDFModeChoiceModule.BICYCLE_ESTIMATOR_NAME); eqasimConfig.setEstimator(IDFModeChoiceModule.CAR_PASSENGER, IDFModeChoiceModule.CAR_PASSENGER_ESTIMATOR_NAME); eqasimConfig.removeEstimator(TransportMode.bike); From a57fa7d5adb34b6f8c841e88596257fd3962dfec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 8 Oct 2024 10:56:57 +0200 Subject: [PATCH 23/81] fixes and forgot to add driving permit for car passenger --- .../components/traffic/EqasimTrafficQSimModule.java | 3 +-- .../estimators/IDFCarPassengerUtilityEstimator.java | 13 ++++++++++++- .../ile_de_france/scenario/RunAdaptConfig.java | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/components/traffic/EqasimTrafficQSimModule.java b/core/src/main/java/org/eqasim/core/components/traffic/EqasimTrafficQSimModule.java index e102c8db6..ce1b10c3e 100644 --- a/core/src/main/java/org/eqasim/core/components/traffic/EqasimTrafficQSimModule.java +++ b/core/src/main/java/org/eqasim/core/components/traffic/EqasimTrafficQSimModule.java @@ -1,7 +1,6 @@ package org.eqasim.core.components.traffic; import org.matsim.core.mobsim.qsim.AbstractQSimModule; -import org.matsim.core.mobsim.qsim.qnetsimengine.linkspeedcalculator.LinkSpeedCalculator; import com.google.inject.Provides; import com.google.inject.Singleton; @@ -9,7 +8,7 @@ public class EqasimTrafficQSimModule extends AbstractQSimModule { @Override protected void configureQSim() { - bind(LinkSpeedCalculator.class).to(EqasimLinkSpeedCalculator.class); + addLinkSpeedCalculator().to(EqasimLinkSpeedCalculator.class); } @Provides diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java index f7574f5de..b72d1600b 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java @@ -5,7 +5,9 @@ import org.eqasim.core.simulation.mode_choice.utilities.UtilityEstimator; import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFCarPassengerPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPersonPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFCarPassengerVariables; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPersonVariables; 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; @@ -15,11 +17,14 @@ public class IDFCarPassengerUtilityEstimator implements UtilityEstimator { private final IDFModeParameters parameters; private final IDFCarPassengerPredictor predictor; + private final IDFPersonPredictor personPredictor; @Inject - public IDFCarPassengerUtilityEstimator(IDFModeParameters parameters, IDFCarPassengerPredictor predictor) { + public IDFCarPassengerUtilityEstimator(IDFModeParameters parameters, IDFCarPassengerPredictor predictor, + IDFPersonPredictor personPredictor) { this.parameters = parameters; this.predictor = predictor; + this.personPredictor = personPredictor; } protected double estimateConstantUtility() { @@ -34,15 +39,21 @@ protected double estimateAccessEgressTimeUtility(IDFCarPassengerVariables variab return parameters.betaAccessTime_u_min * variables.accessEgressTime_min; } + protected double estimateDrivingPermit(IDFPersonVariables variables) { + return variables.hasDrivingPermit ? parameters.idfCarPassenger.betaDrivingPermit_u : 0.0; + } + @Override public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { IDFCarPassengerVariables variables = predictor.predictVariables(person, trip, elements); + IDFPersonVariables personVariables = personPredictor.predictVariables(person, trip, elements); double utility = 0.0; utility += estimateConstantUtility(); utility += estimateTravelTimeUtility(variables); utility += estimateAccessEgressTimeUtility(variables); + utility += estimateDrivingPermit(personVariables); return utility; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index b382ea34a..f6b50f7f5 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -66,6 +66,7 @@ static public void adaptConfiguration(Config config, String prefix) { .get(DiscreteModeChoiceConfigGroup.GROUP_NAME); dmcConfig.setModeAvailability(IDFModeChoiceModule.MODE_AVAILABILITY_NAME); + dmcConfig.setCachedModes(Arrays.asList("car", "bicycle", "pt", "walk", "car_passenger", "truck")); Set tripConstraints = new HashSet<>(dmcConfig.getTripConstraints()); tripConstraints.remove(EqasimModeChoiceModule.PASSENGER_CONSTRAINT_NAME); From c0645372957b594a7c291b504cd4c868d1a8c40a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 9 Oct 2024 11:37:21 +0200 Subject: [PATCH 24/81] update passenger availability and some other parameters --- .../mode_choice/IDFModeAvailability.java | 9 +++-- .../parameters/IDFModeParameters.java | 35 +++++++++---------- .../estimators/IDFPtUtilityEstimator.java | 2 +- .../scenario/RunAdaptConfig.java | 6 +++- 4 files changed, 29 insertions(+), 23 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java index 1b1c9d451..f743af0d1 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeAvailability.java @@ -18,11 +18,14 @@ public Collection getAvailableModes(Person person, List Date: Wed, 9 Oct 2024 17:29:34 +0200 Subject: [PATCH 25/81] fix bug in cost model --- .../ile_de_france/mode_choice/costs/IDFPtCostModel.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java index 8c98f0510..d2a65a370 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java @@ -31,6 +31,7 @@ public IDFPtCostModel(IDFPersonPredictor personPredictor, IDFPtPredictor ptPredi private final static double regressionB = 0.006; private final static double regressionC = 0.006; private final static double regressionD = -0.77; + private final static double basePrice = 5.5; @Override public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List elements) { @@ -45,7 +46,7 @@ public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List< IDFPtVariables ptVariables = ptPredictor.predictVariables(person, trip, elements); if (ptVariables.hasOnlySubwayAndBus || ptVariables.isWithinParis) { - return 1.8; + return 1.9; } // III) Otherwise, use regression by Abdelkader DIB @@ -58,7 +59,7 @@ public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List< double destinationCenterDistance_km = 1e-3 * CoordUtils.calcEuclideanDistance(CENTER, trip.getDestinationActivity().getCoord()); - return Math.max(1.9, sigmoid(regressionA * directDistance_km + regressionB * originCenterDistance_km + return Math.max(1.9, basePrice * sigmoid(regressionA * directDistance_km + regressionB * originCenterDistance_km + regressionC * destinationCenterDistance_km + regressionD)); } From a7e5984911ae9eba18c79d0495fba6e539dc5a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 10 Oct 2024 16:41:19 +0200 Subject: [PATCH 26/81] test in pt model --- .../utilities/predictors/IDFPtPredictor.java | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java index dce29ec6e..9f80e4597 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java @@ -11,6 +11,8 @@ 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 org.matsim.core.utils.timing.TimeInterpretation; +import org.matsim.core.utils.timing.TimeTracker; import org.matsim.pt.routes.TransitPassengerRoute; import org.matsim.pt.transitSchedule.api.TransitLine; import org.matsim.pt.transitSchedule.api.TransitRoute; @@ -23,10 +25,12 @@ public class IDFPtPredictor extends CachedVariablePredictor { static public final String PARIS_ATTRIBUTE = "isParis"; private final TransitSchedule schedule; + private final TimeInterpretation timeInterpretation; @Inject - public IDFPtPredictor(TransitSchedule schedule) { + public IDFPtPredictor(TransitSchedule schedule, TimeInterpretation timeInterpretation) { this.schedule = schedule; + this.timeInterpretation = timeInterpretation; } protected CostModel getCostModel() { @@ -36,7 +40,7 @@ protected CostModel getCostModel() { @Override public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List elements) { int numberOfVehicularTrips = 0; - boolean isFirstWaitingTime = false; // different from standard estimator + boolean isFirstTransitLeg = true; // Track relevant variables (from standard estimator) double inVehicleTime_min = 0.0; @@ -51,7 +55,13 @@ public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List= 0.0; - if (!isFirstWaitingTime) { - waitingTime_min += waitingTime / 60.0; - } else { - isFirstWaitingTime = false; + if (isFirstTransitLeg) { + // if departure is in the future, offset here + waitingTime += Math.max(0.0, leg.getDepartureTime().seconds() - elementStartTime); + isFirstTransitLeg = false; } + inVehicleTime_min += inVehicleTime / 60.0; + waitingTime_min += waitingTime / 60.0; + numberOfVehicularTrips++; break; default: From 64864b44f88e7f4ae0140340190864f88212cb9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 10 Oct 2024 18:51:49 +0200 Subject: [PATCH 27/81] update model --- .../parameters/IDFModeParameters.java | 34 +++++++++---------- .../utilities/predictors/IDFPtPredictor.java | 21 +----------- 2 files changed, 18 insertions(+), 37 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java index c84fe2e83..9829632e2 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java @@ -24,38 +24,38 @@ public static IDFModeParameters buildDefault() { IDFModeParameters parameters = new IDFModeParameters(); // Access - parameters.betaAccessTime_u_min = -0.0312; + parameters.betaAccessTime_u_min = -0.031239; // Cost - parameters.betaCost_u_MU = -0.311; - parameters.lambdaCostEuclideanDistance = -0.258; + parameters.betaCost_u_MU = -0.310998; + parameters.lambdaCostEuclideanDistance = -0.257501; parameters.referenceEuclideanDistance_km = 4.4; // Car - parameters.car.alpha_u = -0.201; - parameters.car.betaTravelTime_u_min = -0.0424; + parameters.car.alpha_u = -0.201465; + parameters.car.betaTravelTime_u_min = -0.042431; // Car passenger - parameters.idfCarPassenger.alpha_u = -1.71; - parameters.idfCarPassenger.betaDrivingPermit_u = -0.835; - parameters.idfCarPassenger.betaInVehicleTravelTime_u_min = -0.07; + parameters.idfCarPassenger.alpha_u = -1.713201; + parameters.idfCarPassenger.betaDrivingPermit_u = -0.835542; + parameters.idfCarPassenger.betaInVehicleTravelTime_u_min = -0.069976; // PT parameters.pt.alpha_u = 0.0; - parameters.pt.betaLineSwitch_u = -0.418; - parameters.pt.betaInVehicleTime_u_min = -0.0255; - parameters.pt.betaWaitingTime_u_min = -0.0218; + parameters.pt.betaLineSwitch_u = -0.417658; + parameters.pt.betaInVehicleTime_u_min = -0.025501; + parameters.pt.betaWaitingTime_u_min = -0.021801; - parameters.idfPt.betaDrivingPermit_u = -0.531; - parameters.idfPt.onlyBus_u = -1.42; + parameters.idfPt.betaDrivingPermit_u = -0.531426; + parameters.idfPt.onlyBus_u = -1.416309; // Bike - parameters.bike.alpha_u = -2.93; - parameters.bike.betaTravelTime_u_min = -0.0935; + parameters.bike.alpha_u = -2.927596 ; + parameters.bike.betaTravelTime_u_min = -0.093485; // Walk - parameters.walk.alpha_u = 1.69; - parameters.walk.betaTravelTime_u_min = -0.162; + parameters.walk.alpha_u = 1.685152; + parameters.walk.betaTravelTime_u_min = -0.162285; return parameters; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java index 9f80e4597..2287c16ad 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java @@ -11,8 +11,6 @@ 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 org.matsim.core.utils.timing.TimeInterpretation; -import org.matsim.core.utils.timing.TimeTracker; import org.matsim.pt.routes.TransitPassengerRoute; import org.matsim.pt.transitSchedule.api.TransitLine; import org.matsim.pt.transitSchedule.api.TransitRoute; @@ -25,12 +23,10 @@ public class IDFPtPredictor extends CachedVariablePredictor { static public final String PARIS_ATTRIBUTE = "isParis"; private final TransitSchedule schedule; - private final TimeInterpretation timeInterpretation; @Inject - public IDFPtPredictor(TransitSchedule schedule, TimeInterpretation timeInterpretation) { + public IDFPtPredictor(TransitSchedule schedule) { this.schedule = schedule; - this.timeInterpretation = timeInterpretation; } protected CostModel getCostModel() { @@ -40,7 +36,6 @@ protected CostModel getCostModel() { @Override public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List elements) { int numberOfVehicularTrips = 0; - boolean isFirstTransitLeg = true; // Track relevant variables (from standard estimator) double inVehicleTime_min = 0.0; @@ -55,13 +50,7 @@ public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List= 0.0; - - if (isFirstTransitLeg) { - // if departure is in the future, offset here - waitingTime += Math.max(0.0, leg.getDepartureTime().seconds() - elementStartTime); - isFirstTransitLeg = false; - } - inVehicleTime_min += inVehicleTime / 60.0; waitingTime_min += waitingTime / 60.0; From 361463ad610eb16d76dfc4d2081847c3a761fc9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Sat, 12 Oct 2024 10:31:45 +0200 Subject: [PATCH 28/81] add debugging output --- .../ile_de_france/mode_choice/costs/IDFCarCostModel.java | 1 + .../ile_de_france/mode_choice/costs/IDFPtCostModel.java | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java index ac5153ee8..8821859d4 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java @@ -33,6 +33,7 @@ public IDFCarCostModel(IDFCostParameters costParameters, IDFPersonPredictor pers @Override public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List elements) { double parkingCost_EUR = calculateParkingCost_EUR(person, trip, elements); + System.err.println("Car: " + parkingCost_EUR + " + " + costParameters.carCost_EUR_km * getInVehicleDistance_km(elements)); return costParameters.carCost_EUR_km * getInVehicleDistance_km(elements) + parkingCost_EUR; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java index d2a65a370..8f6fa44fc 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java @@ -39,6 +39,7 @@ public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List< IDFPersonVariables personVariables = personPredictor.predictVariables(person, trip, elements); if (personVariables.hasSubscription) { + System.err.println("PT Cost: Subscription"); return 0.0; } @@ -46,6 +47,7 @@ public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List< IDFPtVariables ptVariables = ptPredictor.predictVariables(person, trip, elements); if (ptVariables.hasOnlySubwayAndBus || ptVariables.isWithinParis) { + System.err.println("PT Cost: Single"); return 1.9; } @@ -59,6 +61,8 @@ public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List< double destinationCenterDistance_km = 1e-3 * CoordUtils.calcEuclideanDistance(CENTER, trip.getDestinationActivity().getCoord()); + System.err.println("PT Cost: IDF " + Math.max(1.9, basePrice * sigmoid(regressionA * directDistance_km + regressionB * originCenterDistance_km + + regressionC * destinationCenterDistance_km + regressionD))); return Math.max(1.9, basePrice * sigmoid(regressionA * directDistance_km + regressionB * originCenterDistance_km + regressionC * destinationCenterDistance_km + regressionD)); } From db67327c0c1d83fde388b64a4e3022104f38cab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Sat, 12 Oct 2024 10:53:18 +0200 Subject: [PATCH 29/81] revert debugging --- .../ile_de_france/mode_choice/costs/IDFCarCostModel.java | 1 - .../ile_de_france/mode_choice/costs/IDFPtCostModel.java | 4 ---- 2 files changed, 5 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java index 8821859d4..ac5153ee8 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java @@ -33,7 +33,6 @@ public IDFCarCostModel(IDFCostParameters costParameters, IDFPersonPredictor pers @Override public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List elements) { double parkingCost_EUR = calculateParkingCost_EUR(person, trip, elements); - System.err.println("Car: " + parkingCost_EUR + " + " + costParameters.carCost_EUR_km * getInVehicleDistance_km(elements)); return costParameters.carCost_EUR_km * getInVehicleDistance_km(elements) + parkingCost_EUR; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java index 8f6fa44fc..d2a65a370 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java @@ -39,7 +39,6 @@ public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List< IDFPersonVariables personVariables = personPredictor.predictVariables(person, trip, elements); if (personVariables.hasSubscription) { - System.err.println("PT Cost: Subscription"); return 0.0; } @@ -47,7 +46,6 @@ public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List< IDFPtVariables ptVariables = ptPredictor.predictVariables(person, trip, elements); if (ptVariables.hasOnlySubwayAndBus || ptVariables.isWithinParis) { - System.err.println("PT Cost: Single"); return 1.9; } @@ -61,8 +59,6 @@ public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List< double destinationCenterDistance_km = 1e-3 * CoordUtils.calcEuclideanDistance(CENTER, trip.getDestinationActivity().getCoord()); - System.err.println("PT Cost: IDF " + Math.max(1.9, basePrice * sigmoid(regressionA * directDistance_km + regressionB * originCenterDistance_km - + regressionC * destinationCenterDistance_km + regressionD))); return Math.max(1.9, basePrice * sigmoid(regressionA * directDistance_km + regressionB * originCenterDistance_km + regressionC * destinationCenterDistance_km + regressionD)); } From b59c19bd9b8982c5aac3c759ee4ed0a58f8b898b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Sat, 12 Oct 2024 23:20:34 +0200 Subject: [PATCH 30/81] formatting --- .../ile_de_france/mode_choice/parameters/IDFModeParameters.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java index 9829632e2..4e88aff2e 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java @@ -50,7 +50,7 @@ public static IDFModeParameters buildDefault() { parameters.idfPt.onlyBus_u = -1.416309; // Bike - parameters.bike.alpha_u = -2.927596 ; + parameters.bike.alpha_u = -2.927596; parameters.bike.betaTravelTime_u_min = -0.093485; // Walk From f08ae29bd1816f4d99c9cc413682747b75b0933a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Mon, 14 Oct 2024 09:07:21 +0200 Subject: [PATCH 31/81] rearranging some code --- .../estimators/IDFPtUtilityEstimator.java | 18 +++++++++--------- .../utilities/predictors/IDFPtPredictor.java | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java index 830866886..76633ad5c 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java @@ -40,23 +40,23 @@ protected double estimateAccessEgressTimeUtility(IDFPtVariables variables) { return parameters.betaAccessTime_u_min * variables.accessEgressTime_min; } - protected double estimateInVehicleTimeUtility(IDFPtVariables variables) { - return parameters.pt.betaInVehicleTime_u_min * variables.inVehicleTime_min; + protected double estimateLineSwitchUtility(IDFPtVariables variables) { + return parameters.pt.betaLineSwitch_u * variables.numberOfLineSwitches; } protected double estimateWaitingTimeUtility(IDFPtVariables variables) { return parameters.pt.betaWaitingTime_u_min * variables.waitingTime_min; } - protected double estimateLineSwitchUtility(IDFPtVariables variables) { - return parameters.pt.betaLineSwitch_u * variables.numberOfLineSwitches; - } - protected double estimateMonetaryCostUtility(IDFPtVariables variables, double cost_EUR) { return parameters.betaCost_u_MU * EstimatorUtils.interaction(variables.euclideanDistance_km, parameters.referenceEuclideanDistance_km, parameters.lambdaCostEuclideanDistance) * cost_EUR; } + protected double estimateInVehicleTimeUtility(IDFPtVariables variables) { + return parameters.pt.betaInVehicleTime_u_min * variables.inVehicleTime_min; + } + protected double estimateDrivingPermitUtility(IDFPersonVariables variables) { return variables.hasDrivingPermit ? parameters.idfPt.betaDrivingPermit_u : 0.0; } @@ -76,13 +76,13 @@ public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { - int numberOfVehicularTrips = 0; + int numberOfVehicularLegs = 0; // Track relevant variables (from standard estimator) double inVehicleTime_min = 0.0; @@ -71,7 +71,7 @@ public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List Date: Sun, 20 Oct 2024 18:48:56 +0200 Subject: [PATCH 32/81] fix bug for pt variables --- .../mode_choice/utilities/predictors/IDFPtPredictor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java index 11e12302a..5850fbfd6 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java @@ -76,8 +76,8 @@ public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List Date: Mon, 21 Oct 2024 02:50:46 +0200 Subject: [PATCH 33/81] add vdf --- .../core/simulation/vdf/VDFQSimModule.java | 14 +------------- .../eqasim/ile_de_france/RunSimulation.java | 19 ++++++++++++++++++- .../scenario/RunAdaptConfig.java | 4 ++-- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/simulation/vdf/VDFQSimModule.java b/core/src/main/java/org/eqasim/core/simulation/vdf/VDFQSimModule.java index 2b250b3d9..3c72bd4c8 100644 --- a/core/src/main/java/org/eqasim/core/simulation/vdf/VDFQSimModule.java +++ b/core/src/main/java/org/eqasim/core/simulation/vdf/VDFQSimModule.java @@ -2,12 +2,8 @@ import org.eqasim.core.simulation.vdf.travel_time.VDFLinkSpeedCalculator; import org.eqasim.core.simulation.vdf.travel_time.VDFTravelTime; -import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.population.Population; -import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.mobsim.qsim.AbstractQSimModule; -import org.matsim.core.mobsim.qsim.qnetsimengine.ConfigurableQNetworkFactory; -import org.matsim.core.mobsim.qsim.qnetsimengine.QNetworkFactory; import com.google.inject.Provides; import com.google.inject.Singleton; @@ -15,15 +11,7 @@ public class VDFQSimModule extends AbstractQSimModule { @Override protected void configureQSim() { - } - - @Provides - @Singleton - public QNetworkFactory provideQNetworkFactory(EventsManager events, Scenario scenario, - VDFLinkSpeedCalculator linkSpeedCalculator) { - ConfigurableQNetworkFactory networkFactory = new ConfigurableQNetworkFactory(events, scenario); - networkFactory.setLinkSpeedCalculator(linkSpeedCalculator); - return networkFactory; + addLinkSpeedCalculator().to(VDFLinkSpeedCalculator.class); } @Provides diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java index 19c6d0cdb..4b84a560f 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java @@ -10,6 +10,8 @@ import org.eqasim.core.scenario.validation.VehiclesValidator; import org.eqasim.core.simulation.analysis.EqasimAnalysisModule; import org.eqasim.core.simulation.mode_choice.EqasimModeChoiceModule; +import org.eqasim.core.simulation.vdf.VDFConfigGroup; +import org.eqasim.core.simulation.vdf.engine.VDFEngineConfigGroup; import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; @@ -39,11 +41,26 @@ public class RunSimulation { static public void main(String[] args) throws ConfigurationException { CommandLine cmd = new CommandLine.Builder(args) // .requireOptions("config-path") // - .allowPrefixes("mode-choice-parameter", "cost-parameter") // + .allowPrefixes("mode-choice-parameter", "cost-parameter", "use-vdf") // .build(); IDFConfigurator configurator = new IDFConfigurator(); Config config = ConfigUtils.loadConfig(cmd.getOptionStrict("config-path"), configurator.getConfigGroups()); + + if (cmd.getOption("use-vdf").map(Boolean::parseBoolean).orElse(false)) { + EqasimConfigGroup eqasimConfig = EqasimConfigGroup.get(config); + + VDFConfigGroup vdfConfig = new VDFConfigGroup(); + config.addModule(vdfConfig); + + vdfConfig.setCapacityFactor(eqasimConfig.getSampleSize()); + vdfConfig.setModes(Set.of("car", "car_passenger")); + + VDFEngineConfigGroup engineConfig = new VDFEngineConfigGroup(); + engineConfig.setModes(Set.of("car", "car_passenger")); + engineConfig.setGenerateNetworkEvents(false); + } + configurator.addOptionalConfigGroups(config); cmd.applyConfiguration(config); VehiclesValidator.validate(config); diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index dee7678ef..4ca204479 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -33,7 +33,7 @@ static public void adaptConfiguration(Config config, String prefix) { config.routing().setAccessEgressType(AccessEgressType.accessEgressModeToLink); Set networkModes = new HashSet<>(config.routing().getNetworkModes()); - networkModes.add("passenger"); + networkModes.add(IDFModeChoiceModule.CAR_PASSENGER); config.routing().setNetworkModes(networkModes); TeleportedModeParams bicycleRouteParams = new TeleportedModeParams(); @@ -70,7 +70,7 @@ static public void adaptConfiguration(Config config, String prefix) { .get(DiscreteModeChoiceConfigGroup.GROUP_NAME); dmcConfig.setModeAvailability(IDFModeChoiceModule.MODE_AVAILABILITY_NAME); - dmcConfig.setCachedModes(Arrays.asList("car", "bicycle", "pt", "walk", "car_passenger", "truck")); + dmcConfig.setCachedModes(Arrays.asList("car", "bicycle", "pt", "walk", IDFModeChoiceModule.CAR_PASSENGER, "truck")); Set tripConstraints = new HashSet<>(dmcConfig.getTripConstraints()); tripConstraints.remove(EqasimModeChoiceModule.PASSENGER_CONSTRAINT_NAME); From 3f1092a6a79da604892731a0c377950932e7ef8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Mon, 21 Oct 2024 12:03:30 +0200 Subject: [PATCH 34/81] fix vdf --- .../src/main/java/org/eqasim/ile_de_france/RunSimulation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java index 4b84a560f..8c7273e1e 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java @@ -59,7 +59,7 @@ static public void main(String[] args) throws ConfigurationException { VDFEngineConfigGroup engineConfig = new VDFEngineConfigGroup(); engineConfig.setModes(Set.of("car", "car_passenger")); engineConfig.setGenerateNetworkEvents(false); - } + config.addModule(engineConfig); } configurator.addOptionalConfigGroups(config); cmd.applyConfiguration(config); From ed09eea3a64e70eb83852c3043f529a0ac53cdc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Mon, 21 Oct 2024 12:12:58 +0200 Subject: [PATCH 35/81] update --- .../main/java/org/eqasim/ile_de_france/RunSimulation.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java index 8c7273e1e..d67fbe2d7 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java @@ -1,6 +1,7 @@ package org.eqasim.ile_de_france; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -37,6 +38,8 @@ import org.matsim.vehicles.Vehicles; import org.matsim.vehicles.VehiclesFactory; +import com.google.common.base.Verify; + public class RunSimulation { static public void main(String[] args) throws ConfigurationException { CommandLine cmd = new CommandLine.Builder(args) // @@ -59,7 +62,10 @@ static public void main(String[] args) throws ConfigurationException { VDFEngineConfigGroup engineConfig = new VDFEngineConfigGroup(); engineConfig.setModes(Set.of("car", "car_passenger")); engineConfig.setGenerateNetworkEvents(false); - config.addModule(engineConfig); } + config.addModule(engineConfig); + + config.qsim().setMainModes(Collections.emptySet()); + } configurator.addOptionalConfigGroups(config); cmd.applyConfiguration(config); From a930864974cf78d9c619ea126312d40923e6e8dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 23 Oct 2024 10:15:28 +0200 Subject: [PATCH 36/81] fix capacity factor --- .../src/main/java/org/eqasim/ile_de_france/RunSimulation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java index d67fbe2d7..ed0abbb14 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java @@ -56,7 +56,7 @@ static public void main(String[] args) throws ConfigurationException { VDFConfigGroup vdfConfig = new VDFConfigGroup(); config.addModule(vdfConfig); - vdfConfig.setCapacityFactor(eqasimConfig.getSampleSize()); + vdfConfig.setCapacityFactor(1.0); vdfConfig.setModes(Set.of("car", "car_passenger")); VDFEngineConfigGroup engineConfig = new VDFEngineConfigGroup(); From 30f0372cff8706da4c3c5fab6136ee7d24093a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Sat, 2 Nov 2024 22:21:51 +0100 Subject: [PATCH 37/81] fix --- .../src/main/java/org/eqasim/ile_de_france/RunSimulation.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java index aac11f284..8c3f4ebb6 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java @@ -41,9 +41,9 @@ static public void main(String[] args) throws ConfigurationException { engineConfig.setModes(Set.of("car", "car_passenger")); engineConfig.setGenerateNetworkEvents(false); config.addModule(engineConfig); - } - config.qsim().setMainModes(Collections.emptySet()); + config.qsim().setMainModes(Collections.emptySet()); + } } cmd.applyConfiguration(config); From 7dae6d907a370365973fd26c82cc0f0dfd435207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 14 Jan 2025 17:24:03 +0100 Subject: [PATCH 38/81] deactivate policies --- .../main/java/org/eqasim/ile_de_france/RunSimulation.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java index 90ca9de90..9ed3f794f 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java @@ -50,8 +50,8 @@ static public void main(String[] args) throws ConfigurationException { cmd.applyConfiguration(config); VehiclesValidator.validate(config); - PolicyExtension policies = new PolicyExtension(); - policies.adaptConfiguration(config); + // PolicyExtension policies = new PolicyExtension(); + // policies.adaptConfiguration(config); Scenario scenario = ScenarioUtils.createScenario(config); configurator.configureScenario(scenario); @@ -113,7 +113,7 @@ static public void main(String[] args) throws ConfigurationException { controller.addOverridingModule(new EqasimAnalysisModule()); controller.addOverridingModule(new EqasimModeChoiceModule()); controller.addOverridingModule(new IDFModeChoiceModule(cmd)); - controller.addOverridingModule(policies); + // controller.addOverridingModule(policies); controller.run(); } } \ No newline at end of file From b6d4119c9882a6fc2d29565ee44017b3e7a4d95a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Fri, 31 Jan 2025 14:29:09 +0100 Subject: [PATCH 39/81] add script to adjust capacity --- .gitignore | 1 + .../scenario/RunAdjustCapacity.java | 42 +++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustCapacity.java diff --git a/.gitignore b/.gitignore index b7baae4d3..f699e9f96 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ dependency-reduced-pom.xml *.iml *.idea simulation_output +.vscode diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustCapacity.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustCapacity.java new file mode 100644 index 000000000..ba167f5b2 --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustCapacity.java @@ -0,0 +1,42 @@ +package org.eqasim.ile_de_france.scenario; + +import java.io.File; +import java.io.IOException; +import java.util.Optional; + +import org.eqasim.core.scenario.cutter.extent.ScenarioExtent; +import org.eqasim.core.scenario.cutter.extent.ShapeScenarioExtent; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.config.CommandLine; +import org.matsim.core.config.CommandLine.ConfigurationException; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.network.io.NetworkWriter; + +public class RunAdjustCapacity { + static public void main(String[] args) throws ConfigurationException, InterruptedException, IOException { + CommandLine cmd = new CommandLine.Builder(args) // + .requireOptions("input-path", "output-path", "extent-path", "factor") // + .build(); + + String inputPath = cmd.getOptionStrict("input-path"); + String extentPath = cmd.getOptionStrict("extent-path"); + String outputPath = cmd.getOptionStrict("output-path"); + double factor = Double.parseDouble(cmd.getOptionStrict("factor")); + + ScenarioExtent extent = new ShapeScenarioExtent.Builder(new File(extentPath), Optional.empty(), + Optional.empty()).build(); + + Network network = NetworkUtils.createNetwork(); + new MatsimNetworkReader(network).readFile(cmd.getOptionStrict("input-path")); + + for (Link link : network.getLinks().values()) { + if (extent.isInside(link.getCoord())) { + link.setCapacity(link.getCapacity() * factor); + } + } + + new NetworkWriter(network).write(cmd.getOptionStrict("output-path")); + } +} From ba049421d819e992616c2a4e8eee72a0a329445f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Sat, 1 Feb 2025 16:28:49 +0100 Subject: [PATCH 40/81] add dummies for paris --- .../mode_choice/parameters/IDFModeParameters.java | 7 +++++++ .../IDFCarPassengerUtilityEstimator.java | 14 ++++++++++++++ .../estimators/IDFCarUtilityEstimator.java | 14 ++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java index 4e88aff2e..76e8b6fc5 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java @@ -3,6 +3,13 @@ import org.eqasim.core.simulation.mode_choice.parameters.ModeParameters; public class IDFModeParameters extends ModeParameters { + public class IDFParisParameters { + public double car_u; + public double carPassenger_u; + } + + public final IDFParisParameters idfParis = new IDFParisParameters(); + public class IDFCarPassengerParameters { public double alpha_u; public double betaInVehicleTravelTime_u_min; diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java index b72d1600b..f6804060b 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java @@ -8,6 +8,7 @@ import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPersonPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFCarPassengerVariables; import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPersonVariables; +import org.matsim.api.core.v01.population.Activity; 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; @@ -55,6 +56,19 @@ public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List Date: Tue, 11 Feb 2025 21:23:49 +0100 Subject: [PATCH 41/81] add dummy for bicycle inside Paris --- .../mode_choice/IDFModeChoiceModule.java | 3 +- .../parameters/IDFModeParameters.java | 1 + .../IDFBicycleUtilityEstimator.java | 52 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBicycleUtilityEstimator.java diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java index cede65462..6595314dd 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java @@ -14,6 +14,7 @@ import org.eqasim.ile_de_france.mode_choice.costs.IDFPtCostModel; import org.eqasim.ile_de_france.mode_choice.parameters.IDFCostParameters; import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; +import org.eqasim.ile_de_france.mode_choice.utilities.estimators.IDFBicycleUtilityEstimator; import org.eqasim.ile_de_france.mode_choice.utilities.estimators.IDFCarPassengerUtilityEstimator; import org.eqasim.ile_de_france.mode_choice.utilities.estimators.IDFCarUtilityEstimator; import org.eqasim.ile_de_france.mode_choice.utilities.estimators.IDFPtUtilityEstimator; @@ -63,7 +64,7 @@ protected void installEqasimExtension() { bindCostModel(PT_COST_MODEL_NAME).to(IDFPtCostModel.class); bindUtilityEstimator(CAR_ESTIMATOR_NAME).to(IDFCarUtilityEstimator.class); - bindUtilityEstimator(BICYCLE_ESTIMATOR_NAME).to(BikeUtilityEstimator.class); + bindUtilityEstimator(BICYCLE_ESTIMATOR_NAME).to(IDFBicycleUtilityEstimator.class); bindUtilityEstimator(CAR_PASSENGER_ESTIMATOR_NAME).to(IDFCarPassengerUtilityEstimator.class); bindUtilityEstimator(PT_ESTIMATOR_NAME).to(IDFPtUtilityEstimator.class); diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java index 76e8b6fc5..8ef324f15 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java @@ -6,6 +6,7 @@ public class IDFModeParameters extends ModeParameters { public class IDFParisParameters { public double car_u; public double carPassenger_u; + public double bicycle_u; } public final IDFParisParameters idfParis = new IDFParisParameters(); diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBicycleUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBicycleUtilityEstimator.java new file mode 100644 index 000000000..971a8d3ba --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBicycleUtilityEstimator.java @@ -0,0 +1,52 @@ +package org.eqasim.ile_de_france.mode_choice.utilities.estimators; + +import java.util.List; + +import org.eqasim.core.simulation.mode_choice.utilities.estimators.BikeUtilityEstimator; +import org.eqasim.core.simulation.mode_choice.utilities.predictors.BikePredictor; +import org.eqasim.core.simulation.mode_choice.utilities.predictors.PersonPredictor; +import org.eqasim.core.simulation.mode_choice.utilities.variables.CarVariables; +import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; +import org.matsim.api.core.v01.population.Activity; +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 IDFBicycleUtilityEstimator extends BikeUtilityEstimator { + private final IDFModeParameters parameters; + + @Inject + public IDFBicycleUtilityEstimator(IDFModeParameters parameters, PersonPredictor personPredictor, + BikePredictor predictor) { + super(parameters, personPredictor, predictor); + this.parameters = parameters; + } + + protected double estimateAccessEgressTimeUtility(CarVariables variables) { + return parameters.betaAccessTime_u_min * variables.accessEgressTime_min; + } + + @Override + public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { + double utility = 0.0; + + utility += super.estimateUtility(person, trip, elements); + + if (isParis(trip)) { + utility += parameters.idfParis.bicycle_u; + } + + return utility; + } + + static private boolean isParis(DiscreteModeChoiceTrip trip) { + return isParis(trip.getOriginActivity()) || isParis(trip.getDestinationActivity()); + } + + static private boolean isParis(Activity activity) { + Boolean isParis = (Boolean) activity.getAttributes().getAttribute("isParis"); + return isParis != null && isParis; + } +} From e113bb61d42f0d46486bfa201f9aaf41e4b14318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Sat, 1 Mar 2025 13:04:44 +0100 Subject: [PATCH 42/81] travel time correction for car passengers --- .../eqasim/ile_de_france/RunSimulation.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java index 0e90a107b..b56bfdce5 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java @@ -6,13 +6,22 @@ import org.eqasim.core.scenario.validation.VehiclesValidator; import org.eqasim.core.simulation.vdf.VDFConfigGroup; import org.eqasim.core.simulation.vdf.engine.VDFEngineConfigGroup; +import org.eqasim.core.simulation.vdf.travel_time.VDFTravelTime; import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.population.Person; import org.matsim.core.config.CommandLine; import org.matsim.core.config.CommandLine.ConfigurationException; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; +import org.matsim.core.router.util.TravelTime; import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.vehicles.Vehicle; + +import com.google.inject.Inject; +import com.google.inject.Provider; public class RunSimulation { static public void main(String[] args) throws ConfigurationException { @@ -52,6 +61,29 @@ static public void main(String[] args) throws ConfigurationException { Controler controller = new Controler(scenario); configurator.configureController(controller); + + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + addTravelTimeBinding("car_passenger").toProvider(new Provider<>() { + @Inject + VDFTravelTime delegate; + + @Override + public TravelTime get() { + return new TravelTime() { + @Override + public double getLinkTravelTime(Link link, double time, Person person, Vehicle vehicle) { + double travelTime = delegate.getLinkTravelTime(link, time, person, vehicle); + double linkTravelTime = Math.floor(travelTime); + return linkTravelTime + 1.0; + } + }; + } + }); + } + }); + controller.run(); } } \ No newline at end of file From ba75b719c1f3db4598164a8e91639b9202826d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Sat, 29 Mar 2025 17:20:01 +0100 Subject: [PATCH 43/81] possibility to change network speeds --- ...ustCapacity.java => RunAdjustNetwork.java} | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) rename ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/{RunAdjustCapacity.java => RunAdjustNetwork.java} (53%) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustCapacity.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java similarity index 53% rename from ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustCapacity.java rename to ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java index ba167f5b2..e58fd1d69 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustCapacity.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java @@ -14,29 +14,36 @@ import org.matsim.core.network.io.MatsimNetworkReader; import org.matsim.core.network.io.NetworkWriter; -public class RunAdjustCapacity { +public class RunAdjustNetwork { static public void main(String[] args) throws ConfigurationException, InterruptedException, IOException { CommandLine cmd = new CommandLine.Builder(args) // - .requireOptions("input-path", "output-path", "extent-path", "factor") // + .requireOptions("input-path", "output-path", "extent-path") // + .allowOptions("capacity-factor", "speed-factor", "extent-path") // .build(); String inputPath = cmd.getOptionStrict("input-path"); - String extentPath = cmd.getOptionStrict("extent-path"); String outputPath = cmd.getOptionStrict("output-path"); - double factor = Double.parseDouble(cmd.getOptionStrict("factor")); - ScenarioExtent extent = new ShapeScenarioExtent.Builder(new File(extentPath), Optional.empty(), - Optional.empty()).build(); + double capacityFactor = cmd.getOption("capacity-factor").map(Double::parseDouble).orElse(1.0); + double speedFactor = cmd.getOption("speed-factor").map(Double::parseDouble).orElse(1.0); + + ScenarioExtent extent = null; + if (cmd.hasOption("extent-path")) { + String extentPath = cmd.getOptionStrict("extent-path"); + extent = new ShapeScenarioExtent.Builder(new File(extentPath), Optional.empty(), + Optional.empty()).build(); + } Network network = NetworkUtils.createNetwork(); - new MatsimNetworkReader(network).readFile(cmd.getOptionStrict("input-path")); + new MatsimNetworkReader(network).readFile(inputPath); for (Link link : network.getLinks().values()) { - if (extent.isInside(link.getCoord())) { - link.setCapacity(link.getCapacity() * factor); + if (extent == null || extent.isInside(link.getCoord())) { + link.setCapacity(link.getCapacity() * capacityFactor); + link.setFreespeed(link.getFreespeed() * speedFactor); } } - new NetworkWriter(network).write(cmd.getOptionStrict("output-path")); + new NetworkWriter(network).write(outputPath); } } From df68f11362a21bd4eeb393defc122bc00de06117 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Sat, 29 Mar 2025 17:30:15 +0100 Subject: [PATCH 44/81] make extent optional --- .../org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java index e58fd1d69..e41331952 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java @@ -17,7 +17,7 @@ public class RunAdjustNetwork { static public void main(String[] args) throws ConfigurationException, InterruptedException, IOException { CommandLine cmd = new CommandLine.Builder(args) // - .requireOptions("input-path", "output-path", "extent-path") // + .requireOptions("input-path", "output-path") // .allowOptions("capacity-factor", "speed-factor", "extent-path") // .build(); From b264f391514b1fdfc8a14300fbf4b2278f17f04f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Sun, 6 Apr 2025 16:06:34 +0200 Subject: [PATCH 45/81] add passenger speed factor --- .../src/main/java/org/eqasim/ile_de_france/RunSimulation.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java index b56bfdce5..79ed9242a 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java @@ -28,6 +28,7 @@ static public void main(String[] args) throws ConfigurationException { CommandLine cmd = new CommandLine.Builder(args) // .requireOptions("config-path") // .allowPrefixes("mode-choice-parameter", "cost-parameter", "use-vdf", "use-vdf-engine") // + .allowOptions("passenger-speed-factor") // .build(); IDFConfigurator configurator = new IDFConfigurator(cmd); @@ -62,6 +63,8 @@ static public void main(String[] args) throws ConfigurationException { Controler controller = new Controler(scenario); configurator.configureController(controller); + double passengerSpeedFactor = cmd.getOption("passenger-speed-factor").map(Double::parseDouble).orElse(1.0); + controller.addOverridingModule(new AbstractModule() { @Override public void install() { @@ -75,6 +78,7 @@ public TravelTime get() { @Override public double getLinkTravelTime(Link link, double time, Person person, Vehicle vehicle) { double travelTime = delegate.getLinkTravelTime(link, time, person, vehicle); + travelTime *= passengerSpeedFactor; double linkTravelTime = Math.floor(travelTime); return linkTravelTime + 1.0; } From d2ddc46a347d776e60b6486fcbfff4377a5805db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Mon, 7 Apr 2025 14:35:38 +0200 Subject: [PATCH 46/81] fix psf --- .../src/main/java/org/eqasim/ile_de_france/RunSimulation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java index 79ed9242a..a3acc1649 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java @@ -78,7 +78,7 @@ public TravelTime get() { @Override public double getLinkTravelTime(Link link, double time, Person person, Vehicle vehicle) { double travelTime = delegate.getLinkTravelTime(link, time, person, vehicle); - travelTime *= passengerSpeedFactor; + travelTime /= passengerSpeedFactor; double linkTravelTime = Math.floor(travelTime); return linkTravelTime + 1.0; } From a9068ef8b11de4c3924627df1d1e1984520bf789 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 22 Jul 2025 12:11:37 +0200 Subject: [PATCH 47/81] update to latest values --- .../raptor/EqasimRaptorConfigGroup.java | 14 ++++---- .../eqasim/ile_de_france/IDFConfigurator.java | 14 ++++++++ .../mode_choice/costs/IDFCarCostModel.java | 6 ++-- .../parameters/IDFCostParameters.java | 6 ++-- .../parameters/IDFModeParameters.java | 36 +++++++++---------- .../scenario/RunAdaptConfig.java | 4 +-- 6 files changed, 47 insertions(+), 33 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/components/raptor/EqasimRaptorConfigGroup.java b/core/src/main/java/org/eqasim/core/components/raptor/EqasimRaptorConfigGroup.java index c496a6007..213eee283 100644 --- a/core/src/main/java/org/eqasim/core/components/raptor/EqasimRaptorConfigGroup.java +++ b/core/src/main/java/org/eqasim/core/components/raptor/EqasimRaptorConfigGroup.java @@ -10,26 +10,26 @@ public EqasimRaptorConfigGroup() { } @Parameter - public double travelTimeRail_u_h = -1.4278139352278472; + public double travelTimeRail_u_h = -0.08317394412379128; @Parameter public double travelTimeSubway_u_h = -1.0; @Parameter - public double travelTimeBus_u_h = -2.835025304050246; + public double travelTimeBus_u_h = -2.8470557962683523; @Parameter - public double travelTimeTram_u_h = -3.199594607188756; + public double travelTimeTram_u_h = -4.849609430935352; @Parameter - public double travelTimeOther_u_h = -2.835025304050246; + public double travelTimeOther_u_h = -2.8470557962683523; @Parameter - public double perTransfer_u = -0.5441109013512305; + public double perTransfer_u = -0.47539778048347203; @Parameter - public double waitTime_u_h = -0.497984826174775; + public double waitTime_u_h = -17.935075050105493; @Parameter - public double walkTime_u_h = -3.8494071051697385; + public double walkTime_u_h = -4.198783720934392; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java index 5fecd6ba5..686f07233 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java @@ -2,7 +2,9 @@ import org.eqasim.core.simulation.EqasimConfigurator; import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; +import org.matsim.api.core.v01.Scenario; import org.matsim.core.config.CommandLine; +import org.matsim.core.config.Config; public class IDFConfigurator extends EqasimConfigurator { public IDFConfigurator(CommandLine cmd) { @@ -10,4 +12,16 @@ public IDFConfigurator(CommandLine cmd) { registerModule(new IDFModeChoiceModule(cmd)); } + + public void configureScenario(Scenario scenario) { + super.configureScenario(scenario); + + Config config = scenario.getConfig(); + + config.routing().getTeleportedModeParams().get("walk").setBeelineDistanceFactor(1.3); + config.routing().getTeleportedModeParams().get("walk").setTeleportedModeSpeed(3.5 / 3.6); + + config.routing().getTeleportedModeParams().get("bicycle").setBeelineDistanceFactor(1.3); + config.routing().getTeleportedModeParams().get("bicycle").setTeleportedModeSpeed(9.1 / 3.6); + } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java index ac5153ee8..5e1a94aa9 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java @@ -32,11 +32,11 @@ public IDFCarCostModel(IDFCostParameters costParameters, IDFPersonPredictor pers @Override public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List elements) { - double parkingCost_EUR = calculateParkingCost_EUR(person, trip, elements); + double parkingCost_EUR = 0.0; // calculateParkingCost_EUR(person, trip, elements); return costParameters.carCost_EUR_km * getInVehicleDistance_km(elements) + parkingCost_EUR; } - private double calculateParkingCost_EUR(Person person, DiscreteModeChoiceTrip trip, + /*private double calculateParkingCost_EUR(Person person, DiscreteModeChoiceTrip trip, List elements) { IDFPersonVariables personVariables = personPredictor.predictVariables(person, trip, elements); @@ -67,5 +67,5 @@ private double calculateParkingCost_EUR(Person person, DiscreteModeChoiceTrip tr private boolean hasParisDestination(DiscreteModeChoiceTrip trip) { Boolean isParis = (Boolean) trip.getDestinationActivity().getAttributes().getAttribute("isParis"); return isParis != null && isParis; - } + }*/ } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java index 73e7929e3..eb36cab60 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFCostParameters.java @@ -4,13 +4,13 @@ public class IDFCostParameters implements ParameterDefinition { public double carCost_EUR_km = 0.0; - public double parisParkingCost_EUR_h = 0.0; + // public double parisParkingCost_EUR_h = 0.0; public static IDFCostParameters buildDefault() { IDFCostParameters parameters = new IDFCostParameters(); - parameters.carCost_EUR_km = 0.2; - parameters.parisParkingCost_EUR_h = 3.0; + parameters.carCost_EUR_km = 0.12; + // parameters.parisParkingCost_EUR_h = 3.0; return parameters; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java index 8ef324f15..292cb87f2 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java @@ -32,38 +32,38 @@ public static IDFModeParameters buildDefault() { IDFModeParameters parameters = new IDFModeParameters(); // Access - parameters.betaAccessTime_u_min = -0.031239; + parameters.betaAccessTime_u_min = -0.032127; // Cost - parameters.betaCost_u_MU = -0.310998; - parameters.lambdaCostEuclideanDistance = -0.257501; - parameters.referenceEuclideanDistance_km = 4.4; + parameters.betaCost_u_MU = -0.874321; + parameters.lambdaCostEuclideanDistance = -0.237512; + parameters.referenceEuclideanDistance_km = 4.42; // Car - parameters.car.alpha_u = -0.201465; - parameters.car.betaTravelTime_u_min = -0.042431; + parameters.car.alpha_u = -0.833961; + parameters.car.betaTravelTime_u_min = -0.047915; // Car passenger - parameters.idfCarPassenger.alpha_u = -1.713201; - parameters.idfCarPassenger.betaDrivingPermit_u = -0.835542; - parameters.idfCarPassenger.betaInVehicleTravelTime_u_min = -0.069976; + parameters.idfCarPassenger.alpha_u = -1.666851; + parameters.idfCarPassenger.betaDrivingPermit_u = -1.430039; + parameters.idfCarPassenger.betaInVehicleTravelTime_u_min = -0.102795; // PT parameters.pt.alpha_u = 0.0; - parameters.pt.betaLineSwitch_u = -0.417658; - parameters.pt.betaInVehicleTime_u_min = -0.025501; - parameters.pt.betaWaitingTime_u_min = -0.021801; + parameters.pt.betaLineSwitch_u = -0.324087; + parameters.pt.betaInVehicleTime_u_min = -0.025956; + parameters.pt.betaWaitingTime_u_min = -0.073963; - parameters.idfPt.betaDrivingPermit_u = -0.531426; - parameters.idfPt.onlyBus_u = -1.416309; + parameters.idfPt.betaDrivingPermit_u = -0.658996; + parameters.idfPt.onlyBus_u = -1.151128; // Bike - parameters.bike.alpha_u = -2.927596; - parameters.bike.betaTravelTime_u_min = -0.093485; + parameters.bike.alpha_u = -3.625289; + parameters.bike.betaTravelTime_u_min = -0.058303; // Walk - parameters.walk.alpha_u = 1.685152; - parameters.walk.betaTravelTime_u_min = -0.162285; + parameters.walk.alpha_u = 1.014904; + parameters.walk.betaTravelTime_u_min = -0.117956; return parameters; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index 1a155a3b6..1b5c87341 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -40,12 +40,12 @@ static public void adaptConfiguration(Config config, String prefix) { TeleportedModeParams bicycleRouteParams = new TeleportedModeParams(); bicycleRouteParams.setMode("bicycle"); - bicycleRouteParams.setTeleportedModeSpeed(15.0 / 3.6); + bicycleRouteParams.setTeleportedModeSpeed(9.1 / 3.6); bicycleRouteParams.setBeelineDistanceFactor(1.3); config.routing().addTeleportedModeParams(bicycleRouteParams); TeleportedModeParams walkRouteParams = config.routing().getTeleportedModeParams().get(TransportMode.walk); - walkRouteParams.setTeleportedModeSpeed(4.5 / 3.6); + walkRouteParams.setTeleportedModeSpeed(3.5 / 3.6); walkRouteParams.setBeelineDistanceFactor(1.3); // MATSim: scoring From 53b65968fec83768be9fcc0b3f1aa23878cd33c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 22 Jul 2025 17:19:22 +0200 Subject: [PATCH 48/81] update walk speed --- .../src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java | 2 +- .../java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java index 686f07233..65b8aa35d 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java @@ -19,7 +19,7 @@ public void configureScenario(Scenario scenario) { Config config = scenario.getConfig(); config.routing().getTeleportedModeParams().get("walk").setBeelineDistanceFactor(1.3); - config.routing().getTeleportedModeParams().get("walk").setTeleportedModeSpeed(3.5 / 3.6); + config.routing().getTeleportedModeParams().get("walk").setTeleportedModeSpeed(3.25 / 3.6); config.routing().getTeleportedModeParams().get("bicycle").setBeelineDistanceFactor(1.3); config.routing().getTeleportedModeParams().get("bicycle").setTeleportedModeSpeed(9.1 / 3.6); diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index 1b5c87341..03521414f 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -45,7 +45,7 @@ static public void adaptConfiguration(Config config, String prefix) { config.routing().addTeleportedModeParams(bicycleRouteParams); TeleportedModeParams walkRouteParams = config.routing().getTeleportedModeParams().get(TransportMode.walk); - walkRouteParams.setTeleportedModeSpeed(3.5 / 3.6); + walkRouteParams.setTeleportedModeSpeed(3.25 / 3.6); walkRouteParams.setBeelineDistanceFactor(1.3); // MATSim: scoring From 3b597e46b331aef263719bb659114e52f46aa032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 23 Jul 2025 09:08:32 +0200 Subject: [PATCH 49/81] allow setting capacities --- .../eqasim/ile_de_france/scenario/RunAdjustNetwork.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java index e41331952..f6030e647 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java @@ -18,7 +18,7 @@ public class RunAdjustNetwork { static public void main(String[] args) throws ConfigurationException, InterruptedException, IOException { CommandLine cmd = new CommandLine.Builder(args) // .requireOptions("input-path", "output-path") // - .allowOptions("capacity-factor", "speed-factor", "extent-path") // + .allowOptions("capacity-factor", "speed-factor", "extent-path", "capacity-value") // .build(); String inputPath = cmd.getOptionStrict("input-path"); @@ -27,6 +27,8 @@ static public void main(String[] args) throws ConfigurationException, Interrupte double capacityFactor = cmd.getOption("capacity-factor").map(Double::parseDouble).orElse(1.0); double speedFactor = cmd.getOption("speed-factor").map(Double::parseDouble).orElse(1.0); + Optional capacityValue = cmd.getOption("capacity-value").map(Double::parseDouble); + ScenarioExtent extent = null; if (cmd.hasOption("extent-path")) { String extentPath = cmd.getOptionStrict("extent-path"); @@ -39,6 +41,10 @@ static public void main(String[] args) throws ConfigurationException, Interrupte for (Link link : network.getLinks().values()) { if (extent == null || extent.isInside(link.getCoord())) { + if (capacityValue.isPresent()) { + link.setCapacity(capacityValue.get()); + } + link.setCapacity(link.getCapacity() * capacityFactor); link.setFreespeed(link.getFreespeed() * speedFactor); } From 0ccdce03b5c1d110220e66fb7aab05aa7c2d92df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 23 Jul 2025 09:28:33 +0200 Subject: [PATCH 50/81] fix for setting freespeed --- .../org/eqasim/core/scenario/freeflow/RunAdaptFreespeed.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/eqasim/core/scenario/freeflow/RunAdaptFreespeed.java b/core/src/main/java/org/eqasim/core/scenario/freeflow/RunAdaptFreespeed.java index 7a3b3f130..1ce498ead 100644 --- a/core/src/main/java/org/eqasim/core/scenario/freeflow/RunAdaptFreespeed.java +++ b/core/src/main/java/org/eqasim/core/scenario/freeflow/RunAdaptFreespeed.java @@ -18,7 +18,7 @@ public class RunAdaptFreespeed { static public void main(String[] args) throws ConfigurationException, JacksonException, DatabindException, IOException { CommandLine cmd = new CommandLine.Builder(args) // - .requireOptions("input-path", "output-path", "configuration-path") + .requireOptions("input-path", "output-path", "settings-path") .build(); String inputPath = cmd.getOptionStrict("input-path"); From b78a1dbe890ee55a1d4bdf676c5f1fe54c9fdf24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 23 Jul 2025 09:47:32 +0200 Subject: [PATCH 51/81] fix --- .../eqasim/core/scenario/freeflow/FreeflowConfigurator.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/scenario/freeflow/FreeflowConfigurator.java b/core/src/main/java/org/eqasim/core/scenario/freeflow/FreeflowConfigurator.java index d5e9c4907..87014231d 100644 --- a/core/src/main/java/org/eqasim/core/scenario/freeflow/FreeflowConfigurator.java +++ b/core/src/main/java/org/eqasim/core/scenario/freeflow/FreeflowConfigurator.java @@ -134,10 +134,11 @@ public void apply(Network network, FreeflowConfiguration configuration) { for (Link link : network.getLinks().values()) { LinkRecord record = records.get(link.getId()); - double travelTime = record.networkTravelTime * container.factors.get(link.getId()); + double travelTime = record.networkTravelTime * container.factors.getOrDefault(link.getId(), 1.0); link.setFreespeed(link.getLength() / travelTime); - link.getAttributes().putAttribute(AttributeCrossingPenalty.ATTRIBUTE, container.delays.get(link.getId())); + link.getAttributes().putAttribute(AttributeCrossingPenalty.ATTRIBUTE, + container.delays.getOrDefault(link.getId(), 0.0)); link.getAttributes().putAttribute("freeflow:linkType", record.linkType.toString()); link.getAttributes().putAttribute("freeflow:crossingType", record.crossingType.toString()); } From 7630f9a780ce2c0feab38a9e5973c40b2dc6ccdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 23 Jul 2025 10:09:51 +0200 Subject: [PATCH 52/81] adapt config --- .../org/eqasim/ile_de_france/IDFConfigurator.java | 12 ------------ .../ile_de_france/scenario/RunAdaptConfig.java | 12 +++++++----- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java index 65b8aa35d..dc3dbf728 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java @@ -12,16 +12,4 @@ public IDFConfigurator(CommandLine cmd) { registerModule(new IDFModeChoiceModule(cmd)); } - - public void configureScenario(Scenario scenario) { - super.configureScenario(scenario); - - Config config = scenario.getConfig(); - - config.routing().getTeleportedModeParams().get("walk").setBeelineDistanceFactor(1.3); - config.routing().getTeleportedModeParams().get("walk").setTeleportedModeSpeed(3.25 / 3.6); - - config.routing().getTeleportedModeParams().get("bicycle").setBeelineDistanceFactor(1.3); - config.routing().getTeleportedModeParams().get("bicycle").setTeleportedModeSpeed(9.1 / 3.6); - } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index 03521414f..6ebc91734 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -43,13 +43,13 @@ static public void adaptConfiguration(Config config, String prefix) { bicycleRouteParams.setTeleportedModeSpeed(9.1 / 3.6); bicycleRouteParams.setBeelineDistanceFactor(1.3); config.routing().addTeleportedModeParams(bicycleRouteParams); - + TeleportedModeParams walkRouteParams = config.routing().getTeleportedModeParams().get(TransportMode.walk); walkRouteParams.setTeleportedModeSpeed(3.25 / 3.6); walkRouteParams.setBeelineDistanceFactor(1.3); // MATSim: scoring - for (String mode : Arrays.asList("bicycle", "passenger")) { + for (String mode : Arrays.asList(IDFModeChoiceModule.BICYCLE, IDFModeChoiceModule.CAR_PASSENGER)) { ModeParams modeScoringParams = new ModeParams(mode); modeScoringParams.setMarginalUtilityOfTraveling(-1.0); config.scoring().addModeParams(modeScoringParams); @@ -72,14 +72,15 @@ static public void adaptConfiguration(Config config, String prefix) { .get(DiscreteModeChoiceConfigGroup.GROUP_NAME); dmcConfig.setModeAvailability(IDFModeChoiceModule.MODE_AVAILABILITY_NAME); - dmcConfig.setCachedModes(Arrays.asList("car", "bicycle", "pt", "walk", IDFModeChoiceModule.CAR_PASSENGER, "truck")); + dmcConfig.setCachedModes(Arrays.asList("car", IDFModeChoiceModule.BICYCLE, "pt", "walk", + IDFModeChoiceModule.CAR_PASSENGER, "truck")); Set tripConstraints = new HashSet<>(dmcConfig.getTripConstraints()); tripConstraints.remove(EqasimModeChoiceModule.PASSENGER_CONSTRAINT_NAME); dmcConfig.setTripConstraints(tripConstraints); VehicleTourConstraintConfigGroup vehicleTourConstraint = dmcConfig.getVehicleTourConstraintConfig(); - vehicleTourConstraint.setRestrictedModes(Arrays.asList("car", "bicycle")); + vehicleTourConstraint.setRestrictedModes(Arrays.asList("car", IDFModeChoiceModule.BICYCLE)); // Major crossing penalty from calibration eqasimConfig.setCrossingPenalty(4.2); @@ -96,6 +97,7 @@ static public void adaptConfiguration(Config config, String prefix) { // Convergence EqasimTerminationConfigGroup terminationConfig = EqasimTerminationConfigGroup.getOrCreate(config); - terminationConfig.setModes(Arrays.asList("car", "car_passenger", "pt", "bicycle", "walk")); + terminationConfig.setModes( + Arrays.asList("car", IDFModeChoiceModule.CAR_PASSENGER, "pt", IDFModeChoiceModule.BICYCLE, "walk")); } } From 5d8815d72ae9a1096e9d943cdf4f50c6b11b58e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 23 Jul 2025 15:46:18 +0200 Subject: [PATCH 53/81] update --- .../core/scenario/spatial/RunImputeSpatialAttribute.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/scenario/spatial/RunImputeSpatialAttribute.java b/core/src/main/java/org/eqasim/core/scenario/spatial/RunImputeSpatialAttribute.java index 0ff5c4b4c..f181e92c7 100644 --- a/core/src/main/java/org/eqasim/core/scenario/spatial/RunImputeSpatialAttribute.java +++ b/core/src/main/java/org/eqasim/core/scenario/spatial/RunImputeSpatialAttribute.java @@ -26,8 +26,9 @@ static public void main(String[] args) throws ConfigurationException, MalformedURLException, IOException, InterruptedException { CommandLine cmd = new CommandLine.Builder(args) // .allowOptions("input-population-path", "input-network-path", "output-population-path", - "output-network-path", "input-schedule-path", "output-schedule-path") // - .requireOptions("shape-path", "shape-attribute", "shape-value", "attribute", EqasimConfigurator.CONFIGURATOR) // + "output-network-path", "input-schedule-path", "output-schedule-path", + EqasimConfigurator.CONFIGURATOR) // + .requireOptions("shape-path", "shape-attribute", "shape-value", "attribute") // .build(); if (cmd.hasOption("input-population-path") ^ cmd.hasOption("output-population-path")) { From 99bfe1d66e82fddb2365f2ff57b3e31c5666f54f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 23 Jul 2025 16:24:25 +0200 Subject: [PATCH 54/81] fix pipeline bug --- .../eqasim/ile_de_france/RunSimulation.java | 47 ++++++++++--------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java index a3acc1649..186614670 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java @@ -65,28 +65,31 @@ static public void main(String[] args) throws ConfigurationException { double passengerSpeedFactor = cmd.getOption("passenger-speed-factor").map(Double::parseDouble).orElse(1.0); - controller.addOverridingModule(new AbstractModule() { - @Override - public void install() { - addTravelTimeBinding("car_passenger").toProvider(new Provider<>() { - @Inject - VDFTravelTime delegate; - - @Override - public TravelTime get() { - return new TravelTime() { - @Override - public double getLinkTravelTime(Link link, double time, Person person, Vehicle vehicle) { - double travelTime = delegate.getLinkTravelTime(link, time, person, vehicle); - travelTime /= passengerSpeedFactor; - double linkTravelTime = Math.floor(travelTime); - return linkTravelTime + 1.0; - } - }; - } - }); - } - }); + if (cmd.hasOption("use-vdf")) { + controller.addOverridingModule(new AbstractModule() { + @Override + public void install() { + addTravelTimeBinding("car_passenger").toProvider(new Provider<>() { + @Inject + VDFTravelTime delegate; + + @Override + public TravelTime get() { + return new TravelTime() { + @Override + public double getLinkTravelTime(Link link, double time, Person person, + Vehicle vehicle) { + double travelTime = delegate.getLinkTravelTime(link, time, person, vehicle); + travelTime /= passengerSpeedFactor; + double linkTravelTime = Math.floor(travelTime); + return linkTravelTime + 1.0; + } + }; + } + }); + } + }); + } controller.run(); } From 6529c585b41604165feb48d386c55eff64170535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Fri, 25 Jul 2025 11:37:04 +0200 Subject: [PATCH 55/81] provide config network --- .../scenario/RunAdjustNetwork.java | 8 +-- .../scenario/RunConfigureNetwork.java | 52 +++++++++++++++++++ 2 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunConfigureNetwork.java diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java index f6030e647..e41331952 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdjustNetwork.java @@ -18,7 +18,7 @@ public class RunAdjustNetwork { static public void main(String[] args) throws ConfigurationException, InterruptedException, IOException { CommandLine cmd = new CommandLine.Builder(args) // .requireOptions("input-path", "output-path") // - .allowOptions("capacity-factor", "speed-factor", "extent-path", "capacity-value") // + .allowOptions("capacity-factor", "speed-factor", "extent-path") // .build(); String inputPath = cmd.getOptionStrict("input-path"); @@ -27,8 +27,6 @@ static public void main(String[] args) throws ConfigurationException, Interrupte double capacityFactor = cmd.getOption("capacity-factor").map(Double::parseDouble).orElse(1.0); double speedFactor = cmd.getOption("speed-factor").map(Double::parseDouble).orElse(1.0); - Optional capacityValue = cmd.getOption("capacity-value").map(Double::parseDouble); - ScenarioExtent extent = null; if (cmd.hasOption("extent-path")) { String extentPath = cmd.getOptionStrict("extent-path"); @@ -41,10 +39,6 @@ static public void main(String[] args) throws ConfigurationException, Interrupte for (Link link : network.getLinks().values()) { if (extent == null || extent.isInside(link.getCoord())) { - if (capacityValue.isPresent()) { - link.setCapacity(capacityValue.get()); - } - link.setCapacity(link.getCapacity() * capacityFactor); link.setFreespeed(link.getFreespeed() * speedFactor); } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunConfigureNetwork.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunConfigureNetwork.java new file mode 100644 index 000000000..da4b770ec --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunConfigureNetwork.java @@ -0,0 +1,52 @@ +package org.eqasim.ile_de_france.scenario; + +import java.io.IOException; + +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.network.Node; +import org.matsim.core.config.CommandLine; +import org.matsim.core.config.CommandLine.ConfigurationException; +import org.matsim.core.network.NetworkUtils; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.network.io.NetworkWriter; + +public class RunConfigureNetwork { + static public void main(String[] args) throws ConfigurationException, InterruptedException, IOException { + CommandLine cmd = new CommandLine.Builder(args) // + .requireOptions("input-path", "output-path") // + .allowOptions("lane-capacity") // + .build(); + + String inputPath = cmd.getOptionStrict("input-path"); + String outputPath = cmd.getOptionStrict("output-path"); + + double laneCapacity = cmd.getOption("lane-capacity").map(Double::parseDouble).orElse(1800.0); + + Network network = NetworkUtils.createNetwork(); + new MatsimNetworkReader(network).readFile(inputPath); + + for (Link link : network.getLinks().values()) { + // by default, set capacity of all links to 1800 per lane + link.setCapacity(link.getNumberOfLanes() * laneCapacity); + } + + // now treat mergers / intersections + for (Node node : network.getNodes().values()) { + // calculate total capacity of the outgoing links + double outgoingLanes = node.getOutLinks().values().stream().mapToDouble(Link::getNumberOfLanes).sum(); + double outCapacity = laneCapacity * outgoingLanes; + + // calculate incoming lanes and distribute outgoing capacity over them + double incomingLanes = node.getInLinks().values().stream().mapToDouble(Link::getNumberOfLanes).sum(); + double inCapacityPerLane = Math.min(outCapacity / incomingLanes, laneCapacity); + + for (Link link : node.getInLinks().values()) { + // set incoming link capacity by distributing outgoing capacity + link.setCapacity(link.getNumberOfLanes() * inCapacityPerLane); + } + } + + new NetworkWriter(network).write(outputPath); + } +} From b8b719121b926275ebf73416ff528c91b1265ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Fri, 25 Jul 2025 16:33:36 +0200 Subject: [PATCH 56/81] update network configuration --- .../scenario/RunConfigureNetwork.java | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunConfigureNetwork.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunConfigureNetwork.java index da4b770ec..20da41f39 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunConfigureNetwork.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunConfigureNetwork.java @@ -15,35 +15,25 @@ public class RunConfigureNetwork { static public void main(String[] args) throws ConfigurationException, InterruptedException, IOException { CommandLine cmd = new CommandLine.Builder(args) // .requireOptions("input-path", "output-path") // - .allowOptions("lane-capacity") // + .allowOptions("node-capacity") // .build(); String inputPath = cmd.getOptionStrict("input-path"); String outputPath = cmd.getOptionStrict("output-path"); - double laneCapacity = cmd.getOption("lane-capacity").map(Double::parseDouble).orElse(1800.0); + double nodeCapacity = cmd.getOption("node-capacity").map(Double::parseDouble).orElse(1800.0); Network network = NetworkUtils.createNetwork(); new MatsimNetworkReader(network).readFile(inputPath); - for (Link link : network.getLinks().values()) { - // by default, set capacity of all links to 1800 per lane - link.setCapacity(link.getNumberOfLanes() * laneCapacity); - } - - // now treat mergers / intersections for (Node node : network.getNodes().values()) { - // calculate total capacity of the outgoing links - double outgoingLanes = node.getOutLinks().values().stream().mapToDouble(Link::getNumberOfLanes).sum(); - double outCapacity = laneCapacity * outgoingLanes; - - // calculate incoming lanes and distribute outgoing capacity over them - double incomingLanes = node.getInLinks().values().stream().mapToDouble(Link::getNumberOfLanes).sum(); - double inCapacityPerLane = Math.min(outCapacity / incomingLanes, laneCapacity); + // calculate incoming lanes and distribute node capacity over them + double incomingLaneCount = node.getInLinks().values().stream().mapToDouble(Link::getNumberOfLanes).sum(); + double laneCapacity = nodeCapacity / incomingLaneCount; for (Link link : node.getInLinks().values()) { // set incoming link capacity by distributing outgoing capacity - link.setCapacity(link.getNumberOfLanes() * inCapacityPerLane); + link.setCapacity(link.getNumberOfLanes() * laneCapacity); } } From 5ef3e3e0ca932387d68d69df16881f0641d15ff6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Fri, 25 Jul 2025 23:00:54 +0200 Subject: [PATCH 57/81] defaults --- .../main/java/org/eqasim/ile_de_france/RunSimulation.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java index 186614670..95fc31688 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunSimulation.java @@ -12,6 +12,7 @@ import org.matsim.api.core.v01.population.Person; import org.matsim.core.config.CommandLine; import org.matsim.core.config.CommandLine.ConfigurationException; +import org.matsim.core.config.groups.QSimConfigGroup.NodeTransition; import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.AbstractModule; @@ -42,6 +43,10 @@ static public void main(String[] args) throws ConfigurationException { vdfConfig.setCapacityFactor(1.0); vdfConfig.setModes(Set.of("car", "car_passenger")); + config.qsim().setFlowCapFactor(1e9); + config.qsim().setStorageCapFactor(1e9); + config.qsim().setStuckTime(3600.0); + if (cmd.getOption("use-vdf-engine").map(Boolean::parseBoolean).orElse(false)) { VDFEngineConfigGroup engineConfig = new VDFEngineConfigGroup(); engineConfig.setModes(Set.of("car", "car_passenger")); From 3f6d8b0c698f0dd2fb0f3abcc3610ff1182f7ce5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Mon, 11 Aug 2025 18:13:08 +0200 Subject: [PATCH 58/81] add new components --- .../AbstractCostModelWithPreviousTrips.java | 8 + .../cost/CostModelWithPreviousTrips.java | 13 ++ .../utilities/EqasimUtilityEstimator.java | 9 +- .../UtilityEstimatorWithPreviousTrips.java | 13 ++ .../estimators/CarUtilityEstimator.java | 15 +- ...hedVariablePredictorWithPreviousTrips.java | 29 ++++ .../utilities/predictors/CarPredictor.java | 15 +- .../VariablePredictorWithPreviousTrips.java | 14 ++ .../eqasim/ile_de_france/IDFConfigurator.java | 4 +- .../RunTemporaryModelModification.java | 150 ++++++++++++++++++ .../mode_choice/IDFModeChoiceModule.java | 5 +- .../mode_choice/costs/IDFCarCostModel.java | 116 ++++++++++---- .../parameters/IDFModeParameters.java | 63 +++++--- .../IDFBicycleUtilityEstimator.java | 14 -- .../IDFCarPassengerUtilityEstimator.java | 26 ++- .../estimators/IDFCarUtilityEstimator.java | 59 ++++--- .../estimators/IDFPtUtilityEstimator.java | 30 +++- .../predictors/IDFParkingPredictor.java | 36 +++++ .../predictors/IDFPersonPredictor.java | 7 +- .../predictors/IDFPredictorUtils.java | 23 ++- .../utilities/predictors/IDFPtPredictor.java | 46 +++--- .../predictors/IDFSpatialPredictor.java | 30 ++++ .../variables/IDFParkingVariables.java | 17 ++ .../variables/IDFPersonVariables.java | 9 +- .../variables/IDFSpatialVariables.java | 19 +++ .../parking/IDFParkingModule.java | 25 +++ .../parking/ParkingPressure.java | 29 ++++ .../ile_de_france/parking/ParkingTariff.java | 29 ++++ .../scenario/RunAdaptConfig.java | 2 +- .../eqasim/ile_de_france/TestCorisica.java | 26 +++ .../LosAngelesCarUtilityEstimator.java | 5 +- .../SanFranciscoCarUtilityEstimator.java | 5 +- .../SaoPauloCarUtilityEstimator.java | 5 +- .../estimators/ZurichCarUtilityEstimator.java | 5 +- 34 files changed, 744 insertions(+), 157 deletions(-) create mode 100644 core/src/main/java/org/eqasim/core/simulation/mode_choice/cost/AbstractCostModelWithPreviousTrips.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/mode_choice/cost/CostModelWithPreviousTrips.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/UtilityEstimatorWithPreviousTrips.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/predictors/CachedVariablePredictorWithPreviousTrips.java create mode 100644 core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/predictors/VariablePredictorWithPreviousTrips.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/RunTemporaryModelModification.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFParkingPredictor.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFSpatialPredictor.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFParkingVariables.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFSpatialVariables.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/IDFParkingModule.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/ParkingPressure.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/ParkingTariff.java diff --git a/core/src/main/java/org/eqasim/core/simulation/mode_choice/cost/AbstractCostModelWithPreviousTrips.java b/core/src/main/java/org/eqasim/core/simulation/mode_choice/cost/AbstractCostModelWithPreviousTrips.java new file mode 100644 index 000000000..c4b5d8ae7 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/mode_choice/cost/AbstractCostModelWithPreviousTrips.java @@ -0,0 +1,8 @@ +package org.eqasim.core.simulation.mode_choice.cost; + +public abstract class AbstractCostModelWithPreviousTrips extends AbstractCostModel + implements CostModelWithPreviousTrips { + protected AbstractCostModelWithPreviousTrips(String mode) { + super(mode); + } +} diff --git a/core/src/main/java/org/eqasim/core/simulation/mode_choice/cost/CostModelWithPreviousTrips.java b/core/src/main/java/org/eqasim/core/simulation/mode_choice/cost/CostModelWithPreviousTrips.java new file mode 100644 index 000000000..bdb5daec7 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/mode_choice/cost/CostModelWithPreviousTrips.java @@ -0,0 +1,13 @@ +package org.eqasim.core.simulation.mode_choice.cost; + +import java.util.List; + +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 org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate; + +public interface CostModelWithPreviousTrips extends CostModel { + double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List elements, + List previousTrips); +} diff --git a/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/EqasimUtilityEstimator.java b/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/EqasimUtilityEstimator.java index 56918edf2..daf860c96 100644 --- a/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/EqasimUtilityEstimator.java +++ b/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/EqasimUtilityEstimator.java @@ -37,7 +37,14 @@ protected double estimateTrip(Person person, String mode, DiscreteModeChoiceTrip if (estimator == null) { throw new IllegalStateException(String.format("No estimator registered for mode '%s'", mode)); } else { - double utility = estimator.estimateUtility(person, trip, elements); + double utility = 0.0; + + if (estimator instanceof UtilityEstimatorWithPreviousTrips withPreviousTrips) { + utility += withPreviousTrips.estimateUtility(person, trip, elements, previousTrips); + } else { + utility += estimator.estimateUtility(person, trip, elements); + } + utility += epsilonProvider.getEpsilon(person.getId(), trip.getIndex(), mode); utility -= utilityPenalty.calculatePenalty(mode, person, trip, elements); return utility; diff --git a/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/UtilityEstimatorWithPreviousTrips.java b/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/UtilityEstimatorWithPreviousTrips.java new file mode 100644 index 000000000..2b5d06163 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/UtilityEstimatorWithPreviousTrips.java @@ -0,0 +1,13 @@ +package org.eqasim.core.simulation.mode_choice.utilities; + +import java.util.List; + +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 org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate; + +public interface UtilityEstimatorWithPreviousTrips extends UtilityEstimator { + double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements, + List previousTrips); +} diff --git a/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/estimators/CarUtilityEstimator.java b/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/estimators/CarUtilityEstimator.java index b0628fa2f..55511f924 100644 --- a/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/estimators/CarUtilityEstimator.java +++ b/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/estimators/CarUtilityEstimator.java @@ -3,16 +3,17 @@ import java.util.List; 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.UtilityEstimatorWithPreviousTrips; import org.eqasim.core.simulation.mode_choice.utilities.predictors.CarPredictor; import org.eqasim.core.simulation.mode_choice.utilities.variables.CarVariables; 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 org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate; import com.google.inject.Inject; -public class CarUtilityEstimator implements UtilityEstimator { +public class CarUtilityEstimator implements UtilityEstimatorWithPreviousTrips { private final ModeParameters parameters; private final CarPredictor predictor; @@ -40,8 +41,9 @@ protected double estimateMonetaryCostUtility(CarVariables variables) { } @Override - public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { - CarVariables variables = predictor.predictVariables(person, trip, elements); + public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements, + List previousTrips) { + CarVariables variables = predictor.predictVariables(person, trip, elements, previousTrips); double utility = 0.0; @@ -52,4 +54,9 @@ public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { + throw new IllegalStateException("Need to provide previous trips"); + } } diff --git a/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/predictors/CachedVariablePredictorWithPreviousTrips.java b/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/predictors/CachedVariablePredictorWithPreviousTrips.java new file mode 100644 index 000000000..986aa92c6 --- /dev/null +++ b/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/predictors/CachedVariablePredictorWithPreviousTrips.java @@ -0,0 +1,29 @@ +package org.eqasim.core.simulation.mode_choice.utilities.predictors; + +import java.util.List; + +import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; +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 org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate; + +public abstract class CachedVariablePredictorWithPreviousTrips + implements VariablePredictorWithPreviousTrips { + private DiscreteModeChoiceTrip cacheKey = null; + private T cacheValue = null; + + @Override + public T predictVariables(Person person, DiscreteModeChoiceTrip trip, List elements, + List previousTrips) { + if (trip != cacheKey) { + cacheKey = trip; + cacheValue = predict(person, trip, elements, previousTrips); + } + + return cacheValue; + } + + protected abstract T predict(Person person, DiscreteModeChoiceTrip trip, List elements, + List previousTrips); +} diff --git a/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/predictors/CarPredictor.java b/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/predictors/CarPredictor.java index df6ce4600..063ebbb5b 100644 --- a/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/predictors/CarPredictor.java +++ b/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/predictors/CarPredictor.java @@ -3,6 +3,7 @@ import java.util.List; import org.eqasim.core.simulation.mode_choice.cost.CostModel; +import org.eqasim.core.simulation.mode_choice.cost.CostModelWithPreviousTrips; import org.eqasim.core.simulation.mode_choice.parameters.ModeParameters; import org.eqasim.core.simulation.mode_choice.utilities.variables.CarVariables; import org.matsim.api.core.v01.TransportMode; @@ -10,13 +11,14 @@ 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 org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate; import org.matsim.core.router.TripStructureUtils; import com.google.common.base.Verify; import com.google.inject.Inject; import com.google.inject.name.Named; -public class CarPredictor extends CachedVariablePredictor { +public class CarPredictor extends CachedVariablePredictorWithPreviousTrips { private final CostModel costModel; private final ModeParameters parameters; @@ -27,7 +29,8 @@ public CarPredictor(ModeParameters parameters, @Named("car") CostModel costModel } @Override - public CarVariables predict(Person person, DiscreteModeChoiceTrip trip, List elements) { + public CarVariables predict(Person person, DiscreteModeChoiceTrip trip, List elements, + List previousTrips) { double carTravelTime_min = parameters.car.constantParkingSearchPenalty_min; double accessEgressTime_min = parameters.car.additionalAccessEgressWalkTime_min; @@ -44,7 +47,13 @@ public CarVariables predict(Person person, DiscreteModeChoiceTrip trip, List { + T predictVariables(Person person, DiscreteModeChoiceTrip trip, List elements, + List previousTrips); +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java index dc3dbf728..dd870060a 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java @@ -2,14 +2,14 @@ import org.eqasim.core.simulation.EqasimConfigurator; import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; -import org.matsim.api.core.v01.Scenario; +import org.eqasim.ile_de_france.parking.IDFParkingModule; import org.matsim.core.config.CommandLine; -import org.matsim.core.config.Config; public class IDFConfigurator extends EqasimConfigurator { public IDFConfigurator(CommandLine cmd) { super(cmd); registerModule(new IDFModeChoiceModule(cmd)); + registerModule(new IDFParkingModule()); } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunTemporaryModelModification.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunTemporaryModelModification.java new file mode 100644 index 000000000..99563feca --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunTemporaryModelModification.java @@ -0,0 +1,150 @@ +package org.eqasim.ile_de_france; + +import java.io.File; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.eqasim.core.misc.ParallelProgress; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPredictorUtils; +import org.eqasim.ile_de_france.parking.ParkingPressure; +import org.eqasim.ile_de_france.parking.ParkingTariff; +import org.geotools.api.data.SimpleFeatureReader; +import org.geotools.api.feature.simple.SimpleFeature; +import org.geotools.geopkg.FeatureEntry; +import org.geotools.geopkg.GeoPackage; +import org.locationtech.jts.geom.Coordinate; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryFactory; +import org.locationtech.jts.geom.Point; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.population.Activity; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Plan; +import org.matsim.core.config.CommandLine; +import org.matsim.core.config.CommandLine.ConfigurationException; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.network.io.MatsimNetworkReader; +import org.matsim.core.network.io.NetworkWriter; +import org.matsim.core.population.io.PopulationReader; +import org.matsim.core.population.io.PopulationWriter; +import org.matsim.core.router.TripStructureUtils; +import org.matsim.core.router.TripStructureUtils.StageActivityHandling; +import org.matsim.core.scenario.ScenarioUtils; + +import com.google.common.base.Preconditions; + +public class RunTemporaryModelModification { + private final static Logger logger = LogManager.getLogger(RunTemporaryModelModification.class); + private final static GeometryFactory geometryFactory = new GeometryFactory(); + + static public void main(String[] args) throws ConfigurationException, IOException, InterruptedException { + CommandLine cmd = new CommandLine.Builder(args) // + .requireOptions("config-path", "data-path", "output-population-path", "output-network-path") // + .build(); + + IDFConfigurator configurator = new IDFConfigurator(cmd); + Config config = ConfigUtils.loadConfig(cmd.getOptionStrict("config-path")); + configurator.updateConfig(config); + cmd.applyConfiguration(config); + + logger.info("Reading zone information ..."); + List items = new LinkedList<>(); + try (GeoPackage gpkg = new GeoPackage(new File(cmd.getOptionStrict("data-path")))) { + FeatureEntry featureEntry = gpkg.feature("data"); + SimpleFeatureReader reader = gpkg.reader(featureEntry, null, null); + + while (reader.hasNext()) { + SimpleFeature feature = reader.next(); + + String municipalityId = (String) feature.getAttribute("municipality_id"); + Preconditions.checkNotNull(municipalityId); + + Double parkingPressure = (Double) feature.getAttribute("parking_pressure"); + Preconditions.checkNotNull(parkingPressure); + + Double parkingTariff = (Double) feature.getAttribute("parking_tariff"); + Preconditions.checkNotNull(parkingTariff); + + items.add(new Item(municipalityId, parkingPressure, parkingTariff, + (Geometry) feature.getDefaultGeometry())); + } + } + + Scenario scenario = ScenarioUtils.createScenario(config); + configurator.adjustScenario(scenario); + + new PopulationReader(scenario) + .readURL(config.plans().getInputFileURL(config.getContext())); + + new MatsimNetworkReader(scenario.getNetwork()).readURL(config.network().getInputFileURL(config.getContext())); + + ParallelProgress progress = new ParallelProgress("Processing population ...", + scenario.getPopulation().getPersons().size()); + progress.start(); + + for (Person person : scenario.getPopulation().getPersons().values()) { + for (Plan plan : person.getPlans()) { + Activity homeActivity = null; + + for (Activity activity : TripStructureUtils.getActivities(plan, + StageActivityHandling.ExcludeStageActivities)) { + if (homeActivity == null && activity.getType().equals("home")) { + homeActivity = activity; + } + + Coordinate coordinate = new Coordinate(activity.getCoord().getX(), activity.getCoord().getY()); + Point pointGeometry = geometryFactory.createPoint(coordinate); + + for (Item item : items) { + if (item.geometry.covers(pointGeometry)) { + activity.getAttributes().putAttribute(IDFPredictorUtils.ACTIVITY_MUNICIPALITY_ID, + item.municipalityId); + break; + } + } + } + + if (homeActivity != null) { + person.getAttributes().putAttribute(IDFPredictorUtils.RESIDENCE_MUNICIPALITY_ID, + homeActivity.getAttributes().getAttribute(IDFPredictorUtils.ACTIVITY_MUNICIPALITY_ID)); + } + } + + progress.update(); + } + + progress.close(); + + progress = new ParallelProgress("Processing network ...", + scenario.getNetwork().getLinks().size()); + progress.start(); + + for (Link link : scenario.getNetwork().getLinks().values()) { + Coordinate coordinate = new Coordinate(link.getCoord().getX(), link.getCoord().getY()); + Point pointGeometry = geometryFactory.createPoint(coordinate); + + for (Item item : items) { + if (item.geometry.covers(pointGeometry)) { + link.getAttributes().putAttribute(ParkingPressure.LINK_ATTRIBUTE, item.parkingPressure); + link.getAttributes().putAttribute(ParkingTariff.LINK_ATTRIBUTE, item.parkingTariff); + break; + } + } + + progress.update(); + } + + progress.close(); + + new PopulationWriter(scenario.getPopulation()).write(cmd.getOptionStrict("output-population-path")); + new NetworkWriter(scenario.getNetwork()).write(cmd.getOptionStrict("output-network-path")); + } + + private record Item(String municipalityId, double parkingPressure, double parkingTariff, Geometry geometry) { + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java index 6595314dd..36850856e 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/IDFModeChoiceModule.java @@ -9,7 +9,6 @@ import org.eqasim.core.simulation.mode_choice.ParameterDefinition; import org.eqasim.core.simulation.mode_choice.parameters.ModeParameters; import org.eqasim.core.simulation.mode_choice.tour_finder.ActivityTourFinderWithExcludedActivities; -import org.eqasim.core.simulation.mode_choice.utilities.estimators.BikeUtilityEstimator; import org.eqasim.ile_de_france.mode_choice.costs.IDFCarCostModel; import org.eqasim.ile_de_france.mode_choice.costs.IDFPtCostModel; import org.eqasim.ile_de_france.mode_choice.parameters.IDFCostParameters; @@ -19,8 +18,10 @@ import org.eqasim.ile_de_france.mode_choice.utilities.estimators.IDFCarUtilityEstimator; import org.eqasim.ile_de_france.mode_choice.utilities.estimators.IDFPtUtilityEstimator; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFCarPassengerPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFParkingPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPersonPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPtPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFSpatialPredictor; import org.matsim.contribs.discrete_mode_choice.components.tour_finder.ActivityTourFinder; import org.matsim.contribs.discrete_mode_choice.modules.config.ActivityTourFinderConfigGroup; import org.matsim.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup; @@ -59,6 +60,8 @@ protected void installEqasimExtension() { bind(IDFPersonPredictor.class); bind(IDFCarPassengerPredictor.class); bind(IDFPtPredictor.class); + bind(IDFSpatialPredictor.class); + bind(IDFParkingPredictor.class); bindCostModel(CAR_COST_MODEL_NAME).to(IDFCarCostModel.class); bindCostModel(PT_COST_MODEL_NAME).to(IDFPtCostModel.class); diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java index 5e1a94aa9..d50811ad4 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java @@ -3,69 +3,131 @@ import java.util.List; import org.eqasim.core.simulation.mode_choice.cost.AbstractCostModel; +import org.eqasim.core.simulation.mode_choice.cost.AbstractCostModelWithPreviousTrips; import org.eqasim.ile_de_france.mode_choice.parameters.IDFCostParameters; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFParkingPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPersonPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFSpatialPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFParkingVariables; import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPersonVariables; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFSpatialVariables; +import org.matsim.api.core.v01.population.Leg; import org.matsim.api.core.v01.population.Person; -import org.matsim.api.core.v01.population.Plan; import org.matsim.api.core.v01.population.PlanElement; import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; +import org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.DefaultRoutedTripCandidate; +import org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate; import org.matsim.core.utils.timing.TimeInterpretation; import org.matsim.core.utils.timing.TimeTracker; import com.google.inject.Inject; -public class IDFCarCostModel extends AbstractCostModel { +public class IDFCarCostModel extends AbstractCostModelWithPreviousTrips { private final TimeInterpretation timeInterpretation; private final IDFCostParameters costParameters; private final IDFPersonPredictor personPredictor; + private final IDFSpatialPredictor spatialPredictor; + private final IDFParkingPredictor parkingPredictor; @Inject public IDFCarCostModel(IDFCostParameters costParameters, IDFPersonPredictor personPredictor, + IDFSpatialPredictor spatialPredictor, IDFParkingPredictor parkingPredictor, TimeInterpretation timeInterpretation) { super("car"); this.costParameters = costParameters; this.personPredictor = personPredictor; + this.spatialPredictor = spatialPredictor; + this.parkingPredictor = parkingPredictor; this.timeInterpretation = timeInterpretation; } @Override - public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List elements) { - double parkingCost_EUR = 0.0; // calculateParkingCost_EUR(person, trip, elements); - return costParameters.carCost_EUR_km * getInVehicleDistance_km(elements) + parkingCost_EUR; + public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List elements, + List previousTrips) { + return costParameters.carCost_EUR_km * getInVehicleDistance_km(elements) + + calculateParkingCost_EUR(person, trip, elements, previousTrips); } - /*private double calculateParkingCost_EUR(Person person, DiscreteModeChoiceTrip trip, - List elements) { - IDFPersonVariables personVariables = personPredictor.predictVariables(person, trip, elements); + public double calculateParkingCost_EUR(Person person, DiscreteModeChoiceTrip trip, + List tripElements, List previousTrips) { + IDFSpatialVariables spatialVariables = spatialPredictor.predictVariables(person, trip, tripElements); + IDFParkingVariables parkingVariables = parkingPredictor.predictVariables(person, trip, tripElements); + IDFPersonVariables personVariables = personPredictor.predictVariables(person, trip, tripElements); + + // Origin parking costs + double originParkingCost_EUR = 0.0; + + boolean isOriginWork = trip.getOriginActivity().getType().equals("work"); + boolean isOriginResident = spatialVariables.originMunicipalityId + .equals(personVariables.residenceMunicipalityId); + + if (!isOriginWork && !isOriginResident) { + double originDuration = getOriginDuration(person, trip, previousTrips); + originParkingCost_EUR = Math.ceil(originDuration / 3600.0) + * parkingVariables.originParkingTariff_EUR_h; + } + + // Destination parking costs + double destinationParkingCost_EUR = 0.0; + + boolean isDestinationWork = trip.getDestinationActivity().getType().equals("work"); + boolean isDestinationResident = spatialVariables.destinationMunicipalityId + .equals(personVariables.residenceMunicipalityId); + + if (!isDestinationWork && !isDestinationResident) { + double destinationDuration = getDestinationDuration(person, trip, tripElements); + destinationParkingCost_EUR = Math.ceil(destinationDuration / 3600.0) + * parkingVariables.destinationParkingTariff_EUR_h; + } + + return originParkingCost_EUR + destinationParkingCost_EUR; + } - if (!personVariables.isParisResident && hasParisDestination(trip)) { - final double parkingDuration_min; + private final double FIRST_LAST_DURATION = 8.0 * 3600.0; - Plan plan = person.getSelectedPlan(); - if (trip.getDestinationActivity() == plan.getPlanElements().get(plan.getPlanElements().size() - 1)) { - parkingDuration_min = 8.0 * 3600.0 / 60.0; - } else { - TimeTracker timeTracker = new TimeTracker(timeInterpretation); + private double getOriginDuration(Person person, DiscreteModeChoiceTrip trip, List previousTrips) { + if (previousTrips.size() == 0) { + return FIRST_LAST_DURATION; + } else { + TimeTracker timeTracker = new TimeTracker(timeInterpretation); - timeTracker.setTime(trip.getDepartureTime()); - timeTracker.addElements(elements); + DefaultRoutedTripCandidate previousTrip = (DefaultRoutedTripCandidate) previousTrips + .get(previousTrips.size() - 1); + List precedingElements = previousTrip.getRoutedPlanElements(); - double activityStartTime = timeTracker.getTime().seconds(); - timeTracker.addActivity(trip.getDestinationActivity()); + double startTime = ((Leg) precedingElements.get(0)).getDepartureTime().seconds(); + timeTracker.setTime(startTime); + timeTracker.addElements(precedingElements); - parkingDuration_min = (timeTracker.getTime().seconds() - activityStartTime) / 60.0; - } + double arrivalTime = timeTracker.getTime().seconds(); + timeTracker.addActivity(trip.getOriginActivity()); + double departureTime = timeTracker.getTime().seconds(); - return Math.max(1.0, Math.ceil(parkingDuration_min / 60.0)) * costParameters.parisParkingCost_EUR_h; + return departureTime - arrivalTime; } + } - return 0.0; + private double getDestinationDuration(Person person, DiscreteModeChoiceTrip trip, + List tripElements) { + List planElements = person.getSelectedPlan().getPlanElements(); + if (planElements.get(planElements.size() - 1) == trip.getDestinationActivity()) { + return FIRST_LAST_DURATION; + } else { + TimeTracker timeTracker = new TimeTracker(timeInterpretation); + timeTracker.setTime(trip.getDepartureTime()); + timeTracker.addElements(tripElements); + + double arrivalTime = timeTracker.getTime().seconds(); + timeTracker.addActivity(trip.getDestinationActivity()); + double departureTime = timeTracker.getTime().seconds(); + + return departureTime - arrivalTime; + } } - private boolean hasParisDestination(DiscreteModeChoiceTrip trip) { - Boolean isParis = (Boolean) trip.getDestinationActivity().getAttributes().getAttribute("isParis"); - return isParis != null && isParis; - }*/ + @Override + public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List elements) { + throw new IllegalStateException("Use cost calculator with previous costs"); + } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java index 292cb87f2..aae97068f 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/parameters/IDFModeParameters.java @@ -3,13 +3,11 @@ import org.eqasim.core.simulation.mode_choice.parameters.ModeParameters; public class IDFModeParameters extends ModeParameters { - public class IDFParisParameters { - public double car_u; - public double carPassenger_u; - public double bicycle_u; + public class IDFCarParameters { + public double betaParkingPressure_u; } - public final IDFParisParameters idfParis = new IDFParisParameters(); + public final IDFCarParameters idfCar = new IDFCarParameters(); public class IDFCarPassengerParameters { public double alpha_u; @@ -21,49 +19,66 @@ public class IDFCarPassengerParameters { public class IDFPtParameters { public double betaDrivingPermit_u; - public double onlyBus_u; + public double betaOnlyBus_u; + public double betaCrossingParisBorder_u; } public final IDFPtParameters idfPt = new IDFPtParameters(); public double betaAccessTime_u_min; + public double referenceIncomePerCU_EUR; + public double lambdaCostIncome; + + public double betaRoadInsideParis_u; + public static IDFModeParameters buildDefault() { IDFModeParameters parameters = new IDFModeParameters(); // Access - parameters.betaAccessTime_u_min = -0.032127; + parameters.betaAccessTime_u_min = -0.021105; // Cost - parameters.betaCost_u_MU = -0.874321; - parameters.lambdaCostEuclideanDistance = -0.237512; - parameters.referenceEuclideanDistance_km = 4.42; + parameters.betaCost_u_MU = -0.169591; + + parameters.lambdaCostEuclideanDistance = 0.174056; + parameters.referenceEuclideanDistance_km = 4.329534430285437; + + parameters.lambdaCostIncome = -0.131802; + parameters.referenceIncomePerCU_EUR = 1842.3492427549477; // Car - parameters.car.alpha_u = -0.833961; - parameters.car.betaTravelTime_u_min = -0.047915; + parameters.car.alpha_u = 1.164972; + parameters.car.betaTravelTime_u_min = -0.042989; + + parameters.idfCar.betaParkingPressure_u = -1.274770; // Car passenger - parameters.idfCarPassenger.alpha_u = -1.666851; - parameters.idfCarPassenger.betaDrivingPermit_u = -1.430039; - parameters.idfCarPassenger.betaInVehicleTravelTime_u_min = -0.102795; + parameters.idfCarPassenger.alpha_u = -0.340312; + parameters.idfCarPassenger.betaDrivingPermit_u = -1.206877; + parameters.idfCarPassenger.betaInVehicleTravelTime_u_min = -0.070463; + + // Road + parameters.betaRoadInsideParis_u = -1.513682; // PT parameters.pt.alpha_u = 0.0; - parameters.pt.betaLineSwitch_u = -0.324087; - parameters.pt.betaInVehicleTime_u_min = -0.025956; - parameters.pt.betaWaitingTime_u_min = -0.073963; + parameters.pt.betaLineSwitch_u = -0.263965; + parameters.pt.betaInVehicleTime_u_min = -0.007223; + parameters.pt.betaWaitingTime_u_min = -0.034504; + + parameters.idfPt.betaDrivingPermit_u = -0.955961; + parameters.idfPt.betaOnlyBus_u = -0.748072; - parameters.idfPt.betaDrivingPermit_u = -0.658996; - parameters.idfPt.onlyBus_u = -1.151128; + parameters.idfPt.betaCrossingParisBorder_u = 0.934523; // Bike - parameters.bike.alpha_u = -3.625289; - parameters.bike.betaTravelTime_u_min = -0.058303; + parameters.bike.alpha_u = -2.283258; + parameters.bike.betaTravelTime_u_min = -0.050672; // Walk - parameters.walk.alpha_u = 1.014904; - parameters.walk.betaTravelTime_u_min = -0.117956; + parameters.walk.alpha_u = 2.369931; + parameters.walk.betaTravelTime_u_min = -0.114553; return parameters; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBicycleUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBicycleUtilityEstimator.java index 971a8d3ba..2fef934a3 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBicycleUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBicycleUtilityEstimator.java @@ -7,7 +7,6 @@ import org.eqasim.core.simulation.mode_choice.utilities.predictors.PersonPredictor; import org.eqasim.core.simulation.mode_choice.utilities.variables.CarVariables; import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; -import org.matsim.api.core.v01.population.Activity; 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; @@ -34,19 +33,6 @@ public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { IDFCarPassengerVariables variables = predictor.predictVariables(person, trip, elements); IDFPersonVariables personVariables = personPredictor.predictVariables(person, trip, elements); + IDFSpatialVariables spatialVariables = spatialPredictor.predictVariables(person, trip, elements); double utility = 0.0; @@ -55,20 +63,8 @@ public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { - CarVariables variables = predictor.predictVariables(person, trip, elements); + public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements, + List previousTrips) { + IDFPersonVariables personVariables = personPredictor.predictVariables(person, trip, elements); + IDFSpatialVariables spatialVariables = spatialPredictor.predictVariables(person, trip, elements); + IDFParkingVariables parkingVariables = parkingPredictor.predictVariables(person, trip, elements); + CarVariables variables = predictor.predictVariables(person, trip, elements, previousTrips); double utility = 0.0; utility += estimateConstantUtility(); utility += estimateTravelTimeUtility(variables); utility += estimateAccessEgressTimeUtility(variables); - utility += estimateMonetaryCostUtility(variables); - - if (isParis(trip)) { - utility += parameters.idfParis.car_u; - } + utility += estimateMonetaryCostUtility(variables, personVariables); + utility += estimateParkingPressureUtility(parkingVariables); + utility += estimateInsideParisUtility(spatialVariables); return utility; } - - static private boolean isParis(DiscreteModeChoiceTrip trip) { - return isParis(trip.getOriginActivity()) || isParis(trip.getDestinationActivity()); - } - - static private boolean isParis(Activity activity) { - Boolean isParis = (Boolean) activity.getAttributes().getAttribute("isParis"); - return isParis != null && isParis; - } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java index 76633ad5c..8c4d36314 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java @@ -8,8 +8,10 @@ import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPersonPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPtPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFSpatialPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPersonVariables; import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPtVariables; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFSpatialVariables; 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; @@ -21,13 +23,16 @@ public class IDFPtUtilityEstimator implements UtilityEstimator { private final IDFModeParameters parameters; private final IDFPersonPredictor personPredictor; private final IDFPtPredictor idfPtPredictor; + private final IDFSpatialPredictor spatialPredictor; private final CostModel costModel; @Inject public IDFPtUtilityEstimator(IDFModeParameters parameters, IDFPtPredictor idfPtPredictor, - IDFPersonPredictor personPredictor, @Named("pt") CostModel costModel) { + IDFPersonPredictor personPredictor, IDFSpatialPredictor spatialPredictor, + @Named("pt") CostModel costModel) { this.personPredictor = personPredictor; this.idfPtPredictor = idfPtPredictor; + this.spatialPredictor = spatialPredictor; this.parameters = parameters; this.costModel = costModel; } @@ -48,9 +53,13 @@ protected double estimateWaitingTimeUtility(IDFPtVariables variables) { return parameters.pt.betaWaitingTime_u_min * variables.waitingTime_min; } - protected double estimateMonetaryCostUtility(IDFPtVariables variables, double cost_EUR) { + protected double estimateMonetaryCostUtility(IDFPtVariables variables, IDFPersonVariables personVariables, + double cost_EUR) { return parameters.betaCost_u_MU * EstimatorUtils.interaction(variables.euclideanDistance_km, - parameters.referenceEuclideanDistance_km, parameters.lambdaCostEuclideanDistance) * cost_EUR; + parameters.referenceEuclideanDistance_km, parameters.lambdaCostEuclideanDistance) + * EstimatorUtils.interaction(personVariables.householdIncomePerCU_EUR, + parameters.referenceIncomePerCU_EUR, parameters.lambdaCostIncome) + * cost_EUR; } protected double estimateInVehicleTimeUtility(IDFPtVariables variables) { @@ -61,14 +70,19 @@ protected double estimateDrivingPermitUtility(IDFPersonVariables variables) { return variables.hasDrivingPermit ? parameters.idfPt.betaDrivingPermit_u : 0.0; } - protected double estimateOnlyBus(IDFPtVariables variables) { - return variables.isOnlyBus ? parameters.idfPt.onlyBus_u : 0.0; + protected double estimateOnlyBusUtility(IDFPtVariables variables) { + return variables.isOnlyBus ? parameters.idfPt.betaOnlyBus_u : 0.0; + } + + protected double estimateCrossingParisBoundaryUtility(IDFSpatialVariables variables) { + return variables.isCrossingParisBoundary ? parameters.idfPt.betaCrossingParisBorder_u : 0.0; } @Override public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { IDFPersonVariables personVariables = personPredictor.predictVariables(person, trip, elements); IDFPtVariables ptVariables = idfPtPredictor.predictVariables(person, trip, elements); + IDFSpatialVariables spatialVariables = spatialPredictor.predictVariables(person, trip, elements); double cost_EUR = costModel.calculateCost_MU(person, trip, elements); @@ -78,12 +92,14 @@ public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List { + private final ParkingPressure parkingPressure; + private final ParkingTariff parkingTariff; + + @Inject + public IDFParkingPredictor(ParkingPressure parkingPressure, ParkingTariff parkingTariff) { + this.parkingPressure = parkingPressure; + this.parkingTariff = parkingTariff; + } + + @Override + protected IDFParkingVariables predict(Person person, DiscreteModeChoiceTrip trip, + List elements) { + double originParkingTariff_EUR_h = parkingTariff.getParkingPressure(trip.getOriginActivity().getLinkId()); + double destinationParkingTariff_EUR_h = parkingTariff + .getParkingPressure(trip.getDestinationActivity().getLinkId()); + + return new IDFParkingVariables(parkingPressure.getParkingPressure( // + trip.getOriginActivity().getLinkId()), // + originParkingTariff_EUR_h, destinationParkingTariff_EUR_h); + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java index afd31a462..45c69f334 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java @@ -14,7 +14,10 @@ protected IDFPersonVariables predict(Person person, DiscreteModeChoiceTrip trip, List elements) { boolean hasSubscription = IDFPredictorUtils.hasSubscription(person); boolean hasDrivingPermit = IDFPredictorUtils.hasDrivingLicense(person); - boolean isParisResident = IDFPredictorUtils.isParisResident(person); - return new IDFPersonVariables(hasSubscription, hasDrivingPermit, isParisResident); + double householdIncomePerCU_EUR = IDFPredictorUtils.getHouseholdIncome(person); + String residenceMunicipalityId = IDFPredictorUtils.getMunicipalityId(person); + + return new IDFPersonVariables(hasSubscription, hasDrivingPermit, householdIncomePerCU_EUR, + residenceMunicipalityId); } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java index cc6f62dfb..1c7f67122 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java @@ -1,5 +1,6 @@ package org.eqasim.ile_de_france.mode_choice.utilities.predictors; +import org.matsim.api.core.v01.population.Activity; import org.matsim.api.core.v01.population.Person; import org.matsim.core.population.PersonUtils; @@ -25,9 +26,23 @@ static public boolean hasCarAvailability(Person person) { static public boolean hasBicycleAvailability(Person person) { return !"none".equals((String) person.getAttributes().getAttribute("bicycleAvailability")); } - - static public boolean isParisResident(Person person) { - Boolean isResident = (Boolean) person.getAttributes().getAttribute("isParis"); - return isResident != null && isResident; + + static public double getHouseholdIncome(Person person) { + Double householdIncome = (Double) person.getAttributes().getAttribute("householdIncome"); + return householdIncome; + } + + static public final String ACTIVITY_MUNICIPALITY_ID = "municipalityId"; + + static public String getMunicipalityId(Activity activity) { + String municipalityId = (String) activity.getAttributes().getAttribute(ACTIVITY_MUNICIPALITY_ID); + return municipalityId != null ? municipalityId : ""; + } + + static public final String RESIDENCE_MUNICIPALITY_ID = "residenceMunicipalityId"; + + static public String getMunicipalityId(Person person) { + String municipalityId = (String) person.getAttributes().getAttribute(RESIDENCE_MUNICIPALITY_ID); + return municipalityId != null ? municipalityId : ""; } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java index 5850fbfd6..fe532e3fb 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java @@ -53,30 +53,30 @@ public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List { + @Override + protected IDFSpatialVariables predict(Person person, DiscreteModeChoiceTrip trip, + List elements) { + String originMunicipalityId = IDFPredictorUtils.getMunicipalityId(trip.getOriginActivity()); + String destinationMunicipalityId = IDFPredictorUtils.getMunicipalityId(trip.getDestinationActivity()); + + boolean isOriginInsideParis = isInsideParis(originMunicipalityId); + boolean isDestinationInsideParis = isInsideParis(destinationMunicipalityId); + + return new IDFSpatialVariables( // + isOriginInsideParis && isDestinationInsideParis, // + isOriginInsideParis ^ isDestinationInsideParis, // + originMunicipalityId, destinationMunicipalityId); + } + + static private boolean isInsideParis(String municipalityId) { + return municipalityId.startsWith("75"); + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFParkingVariables.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFParkingVariables.java new file mode 100644 index 000000000..99f3b7300 --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFParkingVariables.java @@ -0,0 +1,17 @@ +package org.eqasim.ile_de_france.mode_choice.utilities.variables; + +import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; + +public class IDFParkingVariables implements BaseVariables { + public final double parkingPressure; + + public final double originParkingTariff_EUR_h; + public final double destinationParkingTariff_EUR_h; + + public IDFParkingVariables(double parkingPressure, double originParkingTariff_EUR_h, + double destinationParkingTariff_EUR_h) { + this.parkingPressure = parkingPressure; + this.originParkingTariff_EUR_h = originParkingTariff_EUR_h; + this.destinationParkingTariff_EUR_h = destinationParkingTariff_EUR_h; + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPersonVariables.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPersonVariables.java index a46adf04d..a6625c646 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPersonVariables.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPersonVariables.java @@ -5,11 +5,14 @@ public class IDFPersonVariables implements BaseVariables { public final boolean hasSubscription; public final boolean hasDrivingPermit; - public final boolean isParisResident; + public final double householdIncomePerCU_EUR; + public final String residenceMunicipalityId; - public IDFPersonVariables(boolean hasSubscription, boolean hasDrivingPermit, boolean isParisResident) { + public IDFPersonVariables(boolean hasSubscription, boolean hasDrivingPermit, double householdIncomePerCU_EUR, + String residenceMunicipalityId) { this.hasSubscription = hasSubscription; this.hasDrivingPermit = hasDrivingPermit; - this.isParisResident = isParisResident; + this.householdIncomePerCU_EUR = householdIncomePerCU_EUR; + this.residenceMunicipalityId = residenceMunicipalityId; } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFSpatialVariables.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFSpatialVariables.java new file mode 100644 index 000000000..4673d433a --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFSpatialVariables.java @@ -0,0 +1,19 @@ +package org.eqasim.ile_de_france.mode_choice.utilities.variables; + +import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; + +public class IDFSpatialVariables implements BaseVariables { + public final boolean isInsideParisBoundary; + public final boolean isCrossingParisBoundary; + + public final String originMunicipalityId; + public final String destinationMunicipalityId; + + public IDFSpatialVariables(boolean isInsideParisBoundary, boolean isCrossingParisBoundary, + String originMunicipalityId, String destinationMunicipalityId) { + this.isInsideParisBoundary = isInsideParisBoundary; + this.isCrossingParisBoundary = isCrossingParisBoundary; + this.originMunicipalityId = originMunicipalityId; + this.destinationMunicipalityId = destinationMunicipalityId; + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/IDFParkingModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/IDFParkingModule.java new file mode 100644 index 000000000..20676194e --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/IDFParkingModule.java @@ -0,0 +1,25 @@ +package org.eqasim.ile_de_france.parking; + +import org.matsim.api.core.v01.network.Network; +import org.matsim.core.controler.AbstractModule; + +import com.google.inject.Provides; +import com.google.inject.Singleton; + +public class IDFParkingModule extends AbstractModule { + @Override + public void install() { + } + + @Provides + @Singleton + ParkingPressure provideParkingPressure(Network network) { + return new ParkingPressure(network); + } + + @Provides + @Singleton + ParkingTariff provideParkingTariff(Network network) { + return new ParkingTariff(network); + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/ParkingPressure.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/ParkingPressure.java new file mode 100644 index 000000000..4b31b227f --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/ParkingPressure.java @@ -0,0 +1,29 @@ +package org.eqasim.ile_de_france.parking; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.IdMap; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; + +import com.google.inject.Singleton; + +@Singleton +public class ParkingPressure { + static public final String LINK_ATTRIBUTE = "parkingPressure"; + + private final IdMap values = new IdMap<>(Link.class); + + public ParkingPressure(Network network) { + for (Link link : network.getLinks().values()) { + Double value = (Double) link.getAttributes().getAttribute(LINK_ATTRIBUTE); + + if (value != null) { + values.put(link.getId(), value); + } + } + } + + public double getParkingPressure(Id link) { + return values.getOrDefault(link, 0.0); + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/ParkingTariff.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/ParkingTariff.java new file mode 100644 index 000000000..e5ccf4878 --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/ParkingTariff.java @@ -0,0 +1,29 @@ +package org.eqasim.ile_de_france.parking; + +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.IdMap; +import org.matsim.api.core.v01.network.Link; +import org.matsim.api.core.v01.network.Network; + +import com.google.inject.Singleton; + +@Singleton +public class ParkingTariff { + static public final String LINK_ATTRIBUTE = "parkingTariff_EUR_h"; + + private final IdMap values = new IdMap<>(Link.class); + + public ParkingTariff(Network network) { + for (Link link : network.getLinks().values()) { + Double value = (Double) link.getAttributes().getAttribute(LINK_ATTRIBUTE); + + if (value != null) { + values.put(link.getId(), value); + } + } + } + + public double getParkingPressure(Id link) { + return values.getOrDefault(link, 0.0); + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java index 6ebc91734..d2ff7afa9 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/scenario/RunAdaptConfig.java @@ -83,7 +83,7 @@ static public void adaptConfiguration(Config config, String prefix) { vehicleTourConstraint.setRestrictedModes(Arrays.asList("car", IDFModeChoiceModule.BICYCLE)); // Major crossing penalty from calibration - eqasimConfig.setCrossingPenalty(4.2); + eqasimConfig.setCrossingPenalty(0.0); // Epsilon AdaptConfigForEpsilon.run(config); 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 d61600183..b350ad7e0 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 @@ -9,22 +9,29 @@ import java.util.concurrent.ExecutionException; import org.apache.commons.io.FileUtils; +import org.eqasim.core.components.config.EqasimConfigGroup; import org.eqasim.core.scenario.RunInsertVehicles; import org.eqasim.core.scenario.cutter.RunScenarioCutter; import org.eqasim.core.standalone_mode_choice.RunStandaloneModeChoice; +import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.matsim.api.core.v01.Scenario; import org.matsim.api.core.v01.events.handler.PersonDepartureEventHandler; +import org.matsim.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup; 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.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.config.ConfigWriter; +import org.matsim.core.config.groups.RoutingConfigGroup; +import org.matsim.core.config.groups.ScoringConfigGroup; import org.matsim.core.config.groups.QSimConfigGroup.VehiclesSource; +import org.matsim.core.config.groups.RoutingConfigGroup.TeleportedModeParams; +import org.matsim.core.config.groups.ScoringConfigGroup.ModeParams; import org.matsim.core.events.EventsUtils; import org.matsim.core.events.MatsimEventsReader; import org.matsim.core.population.io.PopulationReader; @@ -49,6 +56,25 @@ private void adjustConfig() throws ConfigurationException { configurator.updateConfig(config); config.vehicles().setVehiclesFile("corsica_vehicles.xml.gz"); config.qsim().setVehiclesSource(VehiclesSource.fromVehiclesData); + + EqasimConfigGroup eqasimConfig = EqasimConfigGroup.get(config); + eqasimConfig.setEstimator("bike", IDFModeChoiceModule.BICYCLE_ESTIMATOR_NAME); + eqasimConfig.setEstimator("bicycle", IDFModeChoiceModule.BICYCLE_ESTIMATOR_NAME); + + DiscreteModeChoiceConfigGroup dmcConfig = DiscreteModeChoiceConfigGroup.getOrCreate(config); + dmcConfig.setModeAvailability(IDFModeChoiceModule.MODE_AVAILABILITY_NAME); + + RoutingConfigGroup routingConfig = config.routing(); + + TeleportedModeParams bicycleRoutingParams = new TeleportedModeParams("bicycle"); + bicycleRoutingParams.setBeelineDistanceFactor(1.3); + bicycleRoutingParams.setTeleportedModeSpeed(9.3 / 3.6); + routingConfig.addTeleportedModeParams(bicycleRoutingParams); + + ScoringConfigGroup scoringConfig = config.scoring(); + ModeParams bicycleScoringParams = new ModeParams("bicycle"); + scoringConfig.addModeParams(bicycleScoringParams); + new ConfigWriter(config).write("corsica_test/corsica_config.xml"); } diff --git a/los_angeles/src/main/java/org/eqasim/los_angeles/mode_choice/utilities/estimators/LosAngelesCarUtilityEstimator.java b/los_angeles/src/main/java/org/eqasim/los_angeles/mode_choice/utilities/estimators/LosAngelesCarUtilityEstimator.java index 5820f01a9..ebfb95684 100644 --- a/los_angeles/src/main/java/org/eqasim/los_angeles/mode_choice/utilities/estimators/LosAngelesCarUtilityEstimator.java +++ b/los_angeles/src/main/java/org/eqasim/los_angeles/mode_choice/utilities/estimators/LosAngelesCarUtilityEstimator.java @@ -13,6 +13,7 @@ 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 org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate; import com.google.inject.Inject; @@ -41,9 +42,9 @@ protected double estimateMonetaryCostUtility(CarVariables variables) { } @Override - public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { + public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements, List previousTrips) { LosAngelesPersonVariables variables = predictor.predictVariables(person, trip, elements); - CarVariables variables_car = carPredictor.predict(person, trip, elements); + CarVariables variables_car = carPredictor.predict(person, trip, elements, previousTrips); double utility = 0.0; diff --git a/san_francisco/src/main/java/org/eqasim/san_francisco/mode_choice/utilities/estimators/SanFranciscoCarUtilityEstimator.java b/san_francisco/src/main/java/org/eqasim/san_francisco/mode_choice/utilities/estimators/SanFranciscoCarUtilityEstimator.java index 186cff0ad..6b7f9cfab 100644 --- a/san_francisco/src/main/java/org/eqasim/san_francisco/mode_choice/utilities/estimators/SanFranciscoCarUtilityEstimator.java +++ b/san_francisco/src/main/java/org/eqasim/san_francisco/mode_choice/utilities/estimators/SanFranciscoCarUtilityEstimator.java @@ -13,6 +13,7 @@ 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 org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate; import com.google.inject.Inject; @@ -41,9 +42,9 @@ protected double estimateMonetaryCostUtility(CarVariables variables) { } @Override - public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { + public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements, List previousTrips) { SanFranciscoPersonVariables variables = predictor.predictVariables(person, trip, elements); - CarVariables variables_car = carPredictor.predict(person, trip, elements); + CarVariables variables_car = carPredictor.predict(person, trip, elements, previousTrips); double utility = 0.0; diff --git a/sao_paulo/src/main/java/org/eqasim/sao_paulo/mode_choice/utilities/estimators/SaoPauloCarUtilityEstimator.java b/sao_paulo/src/main/java/org/eqasim/sao_paulo/mode_choice/utilities/estimators/SaoPauloCarUtilityEstimator.java index 379f48979..1e7d52c9f 100644 --- a/sao_paulo/src/main/java/org/eqasim/sao_paulo/mode_choice/utilities/estimators/SaoPauloCarUtilityEstimator.java +++ b/sao_paulo/src/main/java/org/eqasim/sao_paulo/mode_choice/utilities/estimators/SaoPauloCarUtilityEstimator.java @@ -12,6 +12,7 @@ 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 org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate; import com.google.inject.Inject; @@ -34,9 +35,9 @@ protected double estimateRegionalUtility(SaoPauloPersonVariables variables) { } @Override - public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { + public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements, List previousTrips) { SaoPauloPersonVariables variables = predictor.predictVariables(person, trip, elements); - CarVariables variables_car = carPredictor.predict(person, trip, elements); + CarVariables variables_car = carPredictor.predict(person, trip, elements, previousTrips); double utility = 0.0; diff --git a/switzerland/src/main/java/org/eqasim/switzerland/zurich/mode_choice/utilities/estimators/ZurichCarUtilityEstimator.java b/switzerland/src/main/java/org/eqasim/switzerland/zurich/mode_choice/utilities/estimators/ZurichCarUtilityEstimator.java index 06e7a9bbe..fceb8ebd7 100644 --- a/switzerland/src/main/java/org/eqasim/switzerland/zurich/mode_choice/utilities/estimators/ZurichCarUtilityEstimator.java +++ b/switzerland/src/main/java/org/eqasim/switzerland/zurich/mode_choice/utilities/estimators/ZurichCarUtilityEstimator.java @@ -15,6 +15,7 @@ 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 org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate; import com.google.inject.Inject; @@ -62,8 +63,8 @@ protected double estimateCityUtility(ZurichTripVariables variables) { } @Override - public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements) { - CarVariables variables = predictor.predictVariables(person, trip, elements); + public double estimateUtility(Person person, DiscreteModeChoiceTrip trip, List elements, List previousTrips) { + CarVariables variables = predictor.predictVariables(person, trip, elements, previousTrips); ZurichPersonVariables personVariables = personPredictor.predictVariables(person, trip, elements); ZurichTripVariables tripVariables = tripPredictor.predictVariables(person, trip, elements); From 89472e33abab1f240030971cd9afe0cd6463208f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 12 Aug 2025 17:47:37 +0200 Subject: [PATCH 59/81] logging --- .../mode_choice/costs/IDFCarCostModel.java | 15 +++++++++++++-- .../IDFCarPassengerUtilityEstimator.java | 1 + .../estimators/IDFCarUtilityEstimator.java | 4 ++++ .../estimators/IDFPtUtilityEstimator.java | 10 +++++++--- .../predictors/IDFParkingPredictor.java | 19 ++++++++++++++----- .../ile_de_france/parking/ParkingTariff.java | 2 +- 6 files changed, 40 insertions(+), 11 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java index d50811ad4..a8b6a37e2 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java @@ -2,7 +2,6 @@ import java.util.List; -import org.eqasim.core.simulation.mode_choice.cost.AbstractCostModel; import org.eqasim.core.simulation.mode_choice.cost.AbstractCostModelWithPreviousTrips; import org.eqasim.ile_de_france.mode_choice.parameters.IDFCostParameters; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFParkingPredictor; @@ -45,8 +44,12 @@ public IDFCarCostModel(IDFCostParameters costParameters, IDFPersonPredictor pers @Override public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List elements, List previousTrips) { + double parkingCost_EUR = calculateParkingCost_EUR(person, trip, elements, previousTrips); + + System.err.println("carcost:parkingCost " + parkingCost_EUR); + return costParameters.carCost_EUR_km * getInVehicleDistance_km(elements) - + calculateParkingCost_EUR(person, trip, elements, previousTrips); + + parkingCost_EUR; } public double calculateParkingCost_EUR(Person person, DiscreteModeChoiceTrip trip, @@ -81,6 +84,14 @@ public double calculateParkingCost_EUR(Person person, DiscreteModeChoiceTrip tri * parkingVariables.destinationParkingTariff_EUR_h; } + if (originParkingCost_EUR > 0.0) { + System.err.println("carcost:origin " + originParkingCost_EUR); + } + + if (destinationParkingCost_EUR > 0.0) { + System.err.println("carcost:destination " + destinationParkingCost_EUR); + } + return originParkingCost_EUR + destinationParkingCost_EUR; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java index 1ba848963..7885673c4 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java @@ -48,6 +48,7 @@ protected double estimateDrivingPermit(IDFPersonVariables variables) { } protected double estimateInsideParisUtility(IDFSpatialVariables spatialVariables) { + System.err.println("carPassenger:insideParis " + spatialVariables.isInsideParisBoundary); return spatialVariables.isInsideParisBoundary ? parameters.betaRoadInsideParis_u : 0.0; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarUtilityEstimator.java index cc4360589..0960cad92 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarUtilityEstimator.java @@ -45,6 +45,8 @@ protected double estimateAccessEgressTimeUtility(CarVariables variables) { } protected double estimateMonetaryCostUtility(CarVariables carVariables, IDFPersonVariables personVariables) { + System.err.println("car:householdIncome " + personVariables.householdIncomePerCU_EUR); + double baseValue = super.estimateMonetaryCostUtility(carVariables); return baseValue * EstimatorUtils.interaction(personVariables.householdIncomePerCU_EUR, @@ -52,10 +54,12 @@ protected double estimateMonetaryCostUtility(CarVariables carVariables, IDFPerso } protected double estimateParkingPressureUtility(IDFParkingVariables parkingVariables) { + System.err.println("car:parkingPressure " + parkingVariables.parkingPressure); return parameters.idfCar.betaParkingPressure_u * parkingVariables.parkingPressure; } protected double estimateInsideParisUtility(IDFSpatialVariables spatialVariables) { + System.err.println("car:insideParis " + spatialVariables.isInsideParisBoundary); return spatialVariables.isInsideParisBoundary ? parameters.betaRoadInsideParis_u : 0.0; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java index 8c4d36314..9d96d51b5 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java @@ -55,10 +55,13 @@ protected double estimateWaitingTimeUtility(IDFPtVariables variables) { protected double estimateMonetaryCostUtility(IDFPtVariables variables, IDFPersonVariables personVariables, double cost_EUR) { - return parameters.betaCost_u_MU * EstimatorUtils.interaction(variables.euclideanDistance_km, - parameters.referenceEuclideanDistance_km, parameters.lambdaCostEuclideanDistance) + System.err.println("pt:householdIncome " + personVariables.householdIncomePerCU_EUR); + + return parameters.betaCost_u_MU * // + EstimatorUtils.interaction(variables.euclideanDistance_km, + parameters.referenceEuclideanDistance_km, parameters.lambdaCostEuclideanDistance) // * EstimatorUtils.interaction(personVariables.householdIncomePerCU_EUR, - parameters.referenceIncomePerCU_EUR, parameters.lambdaCostIncome) + parameters.referenceIncomePerCU_EUR, parameters.lambdaCostIncome) // * cost_EUR; } @@ -75,6 +78,7 @@ protected double estimateOnlyBusUtility(IDFPtVariables variables) { } protected double estimateCrossingParisBoundaryUtility(IDFSpatialVariables variables) { + System.err.println("pt:crossingParis " + variables.isCrossingParisBoundary); return variables.isCrossingParisBoundary ? parameters.idfPt.betaCrossingParisBorder_u : 0.0; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFParkingPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFParkingPredictor.java index 6faa5ebda..0e17f84fa 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFParkingPredictor.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFParkingPredictor.java @@ -25,12 +25,21 @@ public IDFParkingPredictor(ParkingPressure parkingPressure, ParkingTariff parkin @Override protected IDFParkingVariables predict(Person person, DiscreteModeChoiceTrip trip, List elements) { - double originParkingTariff_EUR_h = parkingTariff.getParkingPressure(trip.getOriginActivity().getLinkId()); + double originParkingPressure = parkingPressure.getParkingPressure( + trip.getOriginActivity().getLinkId()); + + double destinationParkingPressure = parkingPressure.getParkingPressure( + trip.getDestinationActivity().getLinkId()); + + double parkingPressure = originParkingPressure + destinationParkingPressure; + + double originParkingTariff_EUR_h = parkingTariff.getParkingTariff(trip.getOriginActivity().getLinkId()); double destinationParkingTariff_EUR_h = parkingTariff - .getParkingPressure(trip.getDestinationActivity().getLinkId()); + .getParkingTariff(trip.getDestinationActivity().getLinkId()); - return new IDFParkingVariables(parkingPressure.getParkingPressure( // - trip.getOriginActivity().getLinkId()), // - originParkingTariff_EUR_h, destinationParkingTariff_EUR_h); + return new IDFParkingVariables( // + parkingPressure, // + originParkingTariff_EUR_h, // + destinationParkingTariff_EUR_h); } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/ParkingTariff.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/ParkingTariff.java index e5ccf4878..3a03745d5 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/ParkingTariff.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/parking/ParkingTariff.java @@ -23,7 +23,7 @@ public ParkingTariff(Network network) { } } - public double getParkingPressure(Id link) { + public double getParkingTariff(Id link) { return values.getOrDefault(link, 0.0); } } From 46e6b3175ea038712f9393b26bc23ba06a4563f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 12 Aug 2025 18:06:27 +0200 Subject: [PATCH 60/81] switch to CU --- .../utilities/predictors/IDFPersonPredictor.java | 2 +- .../utilities/predictors/IDFPredictorUtils.java | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java index 45c69f334..b28a40a16 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPersonPredictor.java @@ -14,7 +14,7 @@ protected IDFPersonVariables predict(Person person, DiscreteModeChoiceTrip trip, List elements) { boolean hasSubscription = IDFPredictorUtils.hasSubscription(person); boolean hasDrivingPermit = IDFPredictorUtils.hasDrivingLicense(person); - double householdIncomePerCU_EUR = IDFPredictorUtils.getHouseholdIncome(person); + double householdIncomePerCU_EUR = IDFPredictorUtils.getHouseholdIncomePerCU(person); String residenceMunicipalityId = IDFPredictorUtils.getMunicipalityId(person); return new IDFPersonVariables(hasSubscription, hasDrivingPermit, householdIncomePerCU_EUR, diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java index 1c7f67122..b13cd3ac7 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java @@ -32,6 +32,15 @@ static public double getHouseholdIncome(Person person) { return householdIncome; } + static public int getConsumptionUnits(Person person) { + Integer consumptionUnits = (Integer) person.getAttributes().getAttribute("householdConsumptionUnits"); + return consumptionUnits; + } + + static public double getHouseholdIncomePerCU(Person person) { + return getHouseholdIncome(person) / getConsumptionUnits(person); + } + static public final String ACTIVITY_MUNICIPALITY_ID = "municipalityId"; static public String getMunicipalityId(Activity activity) { From 7730c17ff714ebd6236e9340943ceccc19abffa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 12 Aug 2025 18:40:51 +0200 Subject: [PATCH 61/81] cu are double --- .../mode_choice/utilities/predictors/IDFPredictorUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java index b13cd3ac7..9131c21e0 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPredictorUtils.java @@ -32,8 +32,8 @@ static public double getHouseholdIncome(Person person) { return householdIncome; } - static public int getConsumptionUnits(Person person) { - Integer consumptionUnits = (Integer) person.getAttributes().getAttribute("householdConsumptionUnits"); + static public double getConsumptionUnits(Person person) { + Double consumptionUnits = (Double) person.getAttributes().getAttribute("householdConsumptionUnits"); return consumptionUnits; } From 79a440adf22702c4885a541152ab51a403064398 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 12 Aug 2025 23:30:36 +0200 Subject: [PATCH 62/81] remove logging --- .../mode_choice/costs/IDFCarCostModel.java | 10 ---------- .../estimators/IDFCarPassengerUtilityEstimator.java | 1 - .../utilities/estimators/IDFCarUtilityEstimator.java | 4 ---- .../utilities/estimators/IDFPtUtilityEstimator.java | 3 --- 4 files changed, 18 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java index a8b6a37e2..213ba9912 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java @@ -46,8 +46,6 @@ public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List< List previousTrips) { double parkingCost_EUR = calculateParkingCost_EUR(person, trip, elements, previousTrips); - System.err.println("carcost:parkingCost " + parkingCost_EUR); - return costParameters.carCost_EUR_km * getInVehicleDistance_km(elements) + parkingCost_EUR; } @@ -84,14 +82,6 @@ public double calculateParkingCost_EUR(Person person, DiscreteModeChoiceTrip tri * parkingVariables.destinationParkingTariff_EUR_h; } - if (originParkingCost_EUR > 0.0) { - System.err.println("carcost:origin " + originParkingCost_EUR); - } - - if (destinationParkingCost_EUR > 0.0) { - System.err.println("carcost:destination " + destinationParkingCost_EUR); - } - return originParkingCost_EUR + destinationParkingCost_EUR; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java index 7885673c4..1ba848963 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarPassengerUtilityEstimator.java @@ -48,7 +48,6 @@ protected double estimateDrivingPermit(IDFPersonVariables variables) { } protected double estimateInsideParisUtility(IDFSpatialVariables spatialVariables) { - System.err.println("carPassenger:insideParis " + spatialVariables.isInsideParisBoundary); return spatialVariables.isInsideParisBoundary ? parameters.betaRoadInsideParis_u : 0.0; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarUtilityEstimator.java index 0960cad92..cc4360589 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFCarUtilityEstimator.java @@ -45,8 +45,6 @@ protected double estimateAccessEgressTimeUtility(CarVariables variables) { } protected double estimateMonetaryCostUtility(CarVariables carVariables, IDFPersonVariables personVariables) { - System.err.println("car:householdIncome " + personVariables.householdIncomePerCU_EUR); - double baseValue = super.estimateMonetaryCostUtility(carVariables); return baseValue * EstimatorUtils.interaction(personVariables.householdIncomePerCU_EUR, @@ -54,12 +52,10 @@ protected double estimateMonetaryCostUtility(CarVariables carVariables, IDFPerso } protected double estimateParkingPressureUtility(IDFParkingVariables parkingVariables) { - System.err.println("car:parkingPressure " + parkingVariables.parkingPressure); return parameters.idfCar.betaParkingPressure_u * parkingVariables.parkingPressure; } protected double estimateInsideParisUtility(IDFSpatialVariables spatialVariables) { - System.err.println("car:insideParis " + spatialVariables.isInsideParisBoundary); return spatialVariables.isInsideParisBoundary ? parameters.betaRoadInsideParis_u : 0.0; } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java index 9d96d51b5..a0dd57aac 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFPtUtilityEstimator.java @@ -55,8 +55,6 @@ protected double estimateWaitingTimeUtility(IDFPtVariables variables) { protected double estimateMonetaryCostUtility(IDFPtVariables variables, IDFPersonVariables personVariables, double cost_EUR) { - System.err.println("pt:householdIncome " + personVariables.householdIncomePerCU_EUR); - return parameters.betaCost_u_MU * // EstimatorUtils.interaction(variables.euclideanDistance_km, parameters.referenceEuclideanDistance_km, parameters.lambdaCostEuclideanDistance) // @@ -78,7 +76,6 @@ protected double estimateOnlyBusUtility(IDFPtVariables variables) { } protected double estimateCrossingParisBoundaryUtility(IDFSpatialVariables variables) { - System.err.println("pt:crossingParis " + variables.isCrossingParisBoundary); return variables.isCrossingParisBoundary ? parameters.idfPt.betaCrossingParisBorder_u : 0.0; } From 41ac126ad6422b9600143bd622aec4c33e46ece1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Fri, 22 Aug 2025 17:27:57 +0200 Subject: [PATCH 63/81] update --- .../mode_choice/costs/IDFPtCostModel.java | 19 +++++++++-- .../IDFBicycleUtilityEstimator.java | 8 ----- .../utilities/predictors/IDFPtPredictor.java | 33 ++++--------------- .../utilities/variables/IDFPtVariables.java | 8 ++--- 4 files changed, 25 insertions(+), 43 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java index d2a65a370..d43454674 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java @@ -5,8 +5,10 @@ import org.eqasim.core.simulation.mode_choice.cost.CostModel; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPersonPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPtPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFSpatialPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPersonVariables; import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFPtVariables; +import org.eqasim.ile_de_france.mode_choice.utilities.variables.IDFSpatialVariables; import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.PlanElement; @@ -16,13 +18,18 @@ import com.google.inject.Inject; public class IDFPtCostModel implements CostModel { + private static final double UNIT_PRICE = 1.8; + private final IDFPersonPredictor personPredictor; private final IDFPtPredictor ptPredictor; + private final IDFSpatialPredictor spatialPredictor; @Inject - public IDFPtCostModel(IDFPersonPredictor personPredictor, IDFPtPredictor ptPredictor) { + public IDFPtCostModel(IDFPersonPredictor personPredictor, IDFPtPredictor ptPredictor, + IDFSpatialPredictor spatialPredictor) { this.personPredictor = personPredictor; this.ptPredictor = ptPredictor; + this.spatialPredictor = spatialPredictor; } private final static Coord CENTER = new Coord(651726, 6862287); @@ -45,8 +52,14 @@ public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List< // II) Special case: Within Paris or only metro and bus IDFPtVariables ptVariables = ptPredictor.predictVariables(person, trip, elements); - if (ptVariables.hasOnlySubwayAndBus || ptVariables.isWithinParis) { - return 1.9; + if (ptVariables.isWithoutRail) { + return UNIT_PRICE; + } + + IDFSpatialVariables spatialVariables = spatialPredictor.predictVariables(person, trip, elements); + + if (spatialVariables.isInsideParisBoundary) { + return UNIT_PRICE; } // III) Otherwise, use regression by Abdelkader DIB diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBicycleUtilityEstimator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBicycleUtilityEstimator.java index 2fef934a3..806dc6d80 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBicycleUtilityEstimator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/estimators/IDFBicycleUtilityEstimator.java @@ -5,7 +5,6 @@ import org.eqasim.core.simulation.mode_choice.utilities.estimators.BikeUtilityEstimator; import org.eqasim.core.simulation.mode_choice.utilities.predictors.BikePredictor; import org.eqasim.core.simulation.mode_choice.utilities.predictors.PersonPredictor; -import org.eqasim.core.simulation.mode_choice.utilities.variables.CarVariables; import org.eqasim.ile_de_france.mode_choice.parameters.IDFModeParameters; import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.PlanElement; @@ -14,17 +13,10 @@ import com.google.inject.Inject; public class IDFBicycleUtilityEstimator extends BikeUtilityEstimator { - private final IDFModeParameters parameters; - @Inject public IDFBicycleUtilityEstimator(IDFModeParameters parameters, PersonPredictor personPredictor, BikePredictor predictor) { super(parameters, personPredictor, predictor); - this.parameters = parameters; - } - - protected double estimateAccessEgressTimeUtility(CarVariables variables) { - return parameters.betaAccessTime_u_min * variables.accessEgressTime_min; } @Override diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java index fe532e3fb..bc57aa7bf 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/predictors/IDFPtPredictor.java @@ -15,13 +15,10 @@ import org.matsim.pt.transitSchedule.api.TransitLine; import org.matsim.pt.transitSchedule.api.TransitRoute; import org.matsim.pt.transitSchedule.api.TransitSchedule; -import org.matsim.pt.transitSchedule.api.TransitStopFacility; import com.google.inject.Inject; public class IDFPtPredictor extends CachedVariablePredictor { - static public final String PARIS_ATTRIBUTE = "isParis"; - private final TransitSchedule schedule; @Inject @@ -46,9 +43,7 @@ public IDFPtVariables predict(Person person, DiscreteModeChoiceTrip trip, List 0 && subwayCount == 0 && otherCount == 0; - boolean hasOnlySubwayAndBus = (busCount > 0 || subwayCount > 0) && otherCount == 0; - - boolean isWithinParis = false; - - if (firstRoute != null) { - TransitStopFacility startFacility = schedule.getFacilities().get(firstRoute.getAccessStopId()); - TransitStopFacility endFacility = schedule.getFacilities().get(lastRoute.getEgressStopId()); - - Boolean startParis = (Boolean) startFacility.getAttributes().getAttribute(PARIS_ATTRIBUTE); - Boolean endParis = (Boolean) endFacility.getAttributes().getAttribute(PARIS_ATTRIBUTE); - - isWithinParis = startParis != null && endParis != null && startParis && endParis; - } + boolean isOnlyBus = busCount > 0 && subwayCount == 0 && railCount == 0 && otherCount == 0; + boolean isWithoutRail = railCount == 0; return new IDFPtVariables(inVehicleTime_min, waitingTime_min, accessEgressTime_min, numberOfLineSwitches, - euclideanDistance_km, isOnlyBus, hasOnlySubwayAndBus, isWithinParis); + euclideanDistance_km, isOnlyBus, isWithoutRail); } } \ No newline at end of file diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPtVariables.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPtVariables.java index 0a7ae3447..0154687c0 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPtVariables.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/utilities/variables/IDFPtVariables.java @@ -10,12 +10,11 @@ public class IDFPtVariables implements BaseVariables { public final double euclideanDistance_km; public final boolean isOnlyBus; - public final boolean hasOnlySubwayAndBus; - public final boolean isWithinParis; + public final boolean isWithoutRail; public IDFPtVariables(double inVehicleTime_min, double waitingTime_min, double accessEgressTime_min, int numberOfLineSwitches, double euclideanDistance_km, boolean isOnlyBus, - boolean hasOnlySubwayAndBus, boolean isWithinParis) { + boolean isWithoutRail) { this.inVehicleTime_min = inVehicleTime_min; this.waitingTime_min = waitingTime_min; this.accessEgressTime_min = accessEgressTime_min; @@ -23,7 +22,6 @@ public IDFPtVariables(double inVehicleTime_min, double waitingTime_min, double a this.euclideanDistance_km = euclideanDistance_km; this.isOnlyBus = isOnlyBus; - this.hasOnlySubwayAndBus = hasOnlySubwayAndBus; - this.isWithinParis = isWithinParis; + this.isWithoutRail = isWithoutRail; } } From 36bb338690db3efea941ed0dbb5e4003569fd471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Fri, 22 Aug 2025 17:28:45 +0200 Subject: [PATCH 64/81] update --- .../ile_de_france/mode_choice/costs/IDFPtCostModel.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java index d43454674..969b56156 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFPtCostModel.java @@ -72,8 +72,9 @@ public double calculateCost_MU(Person person, DiscreteModeChoiceTrip trip, List< double destinationCenterDistance_km = 1e-3 * CoordUtils.calcEuclideanDistance(CENTER, trip.getDestinationActivity().getCoord()); - return Math.max(1.9, basePrice * sigmoid(regressionA * directDistance_km + regressionB * originCenterDistance_km - + regressionC * destinationCenterDistance_km + regressionD)); + return Math.max(UNIT_PRICE, + basePrice * sigmoid(regressionA * directDistance_km + regressionB * originCenterDistance_km + + regressionC * destinationCenterDistance_km + regressionD)); } private double sigmoid(double x) { From d21dfd350dca348d964b87b069c802794e86948b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Fri, 12 Sep 2025 10:58:26 +0200 Subject: [PATCH 65/81] add functionality for choice model probe --- .../eqasim/ile_de_france/IDFConfigurator.java | 5 +++ .../probing/ProbeConfigGroup.java | 19 +++++++++ .../probing/ProbeNetworkRoutingModule.java | 37 +++++++++++++++++ .../probing/ProbeRoutingModule.java | 41 +++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeNetworkRoutingModule.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeRoutingModule.java diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java index dd870060a..e4467b68a 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java @@ -3,6 +3,8 @@ import org.eqasim.core.simulation.EqasimConfigurator; import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; import org.eqasim.ile_de_france.parking.IDFParkingModule; +import org.eqasim.ile_de_france.probing.ProbeConfigGroup; +import org.eqasim.ile_de_france.probing.ProbeRoutingModule; import org.matsim.core.config.CommandLine; public class IDFConfigurator extends EqasimConfigurator { @@ -11,5 +13,8 @@ public IDFConfigurator(CommandLine cmd) { registerModule(new IDFModeChoiceModule(cmd)); registerModule(new IDFParkingModule()); + + registerConfigGroup(new ProbeConfigGroup(), false); + registerModule(new ProbeRoutingModule()); } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java new file mode 100644 index 000000000..d6093a910 --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java @@ -0,0 +1,19 @@ +package org.eqasim.ile_de_france.probing; + +import org.matsim.core.config.Config; +import org.matsim.core.config.ReflectiveConfigGroup; + +public class ProbeConfigGroup extends ReflectiveConfigGroup { + static public final String NAME = "eqasim:probe"; + + @Parameter + public boolean useProbeTravelTimes = false; + + public ProbeConfigGroup() { + super(NAME); + } + + static public ProbeConfigGroup get(Config config) { + return (ProbeConfigGroup) config.getModules().get(NAME); + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeNetworkRoutingModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeNetworkRoutingModule.java new file mode 100644 index 000000000..d67269239 --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeNetworkRoutingModule.java @@ -0,0 +1,37 @@ +package org.eqasim.ile_de_france.probing; + +import java.util.List; + +import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.PlanElement; +import org.matsim.core.router.RoutingModule; +import org.matsim.core.router.RoutingRequest; + +public class ProbeNetworkRoutingModule implements RoutingModule { + private final RoutingModule delegate; + private final String mode; + private final String attribute; + + public ProbeNetworkRoutingModule(RoutingModule delegate, String mode) { + this.delegate = delegate; + this.mode = mode; + this.attribute = "probeTravelTime:" + mode; + } + + @Override + public List calcRoute(RoutingRequest request) { + double probeTravelTime = (Double) request.getPerson().getAttributes().getAttribute(attribute); + List elements = delegate.calcRoute(request); + + for (PlanElement element : elements) { + if (element instanceof Leg leg) { + if (leg.getMode().equals(mode)) { + leg.setTravelTime(probeTravelTime); + leg.getRoute().setTravelTime(probeTravelTime); + } + } + } + + return elements; + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeRoutingModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeRoutingModule.java new file mode 100644 index 000000000..1e521343b --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeRoutingModule.java @@ -0,0 +1,41 @@ +package org.eqasim.ile_de_france.probing; + +import java.util.Set; + +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.router.NetworkRoutingProvider; +import org.matsim.core.router.RoutingModule; + +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Provider; +import com.google.inject.name.Names; + +public class ProbeRoutingModule extends AbstractModule { + @Override + public void install() { + ProbeConfigGroup config = ProbeConfigGroup.get(getConfig()); + + if (config.useProbeTravelTimes) { + for (String mode : Set.of("car", "car_passenger")) { + // delegate + bind(Key.get(RoutingModule.class, Names.named("base_" + mode))) + .toProvider(new NetworkRoutingProvider(mode)); + + // override + addRoutingModuleBinding(mode).toProvider(new Provider<>() { + @Inject + Injector injector; + + @Override + public ProbeNetworkRoutingModule get() { + RoutingModule delegate = injector + .getInstance(Key.get(RoutingModule.class, Names.named("base_" + mode))); + return new ProbeNetworkRoutingModule(delegate, mode); + } + }); + } + } + } +} From 3f8322ac53131fb783ed6fa5e74f20c3414dcf6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 16 Sep 2025 14:58:19 +0200 Subject: [PATCH 66/81] add choice model output --- .../eqasim/ile_de_france/IDFConfigurator.java | 4 +- .../mode_choice/costs/IDFCarCostModel.java | 31 +++- .../probing/PredictionWriter.java | 140 ++++++++++++++++++ .../probing/ProbeConfigGroup.java | 3 + .../ile_de_france/probing/ProbeModule.java | 76 ++++++++++ .../probing/ProbeRoutingModule.java | 41 ----- 6 files changed, 249 insertions(+), 46 deletions(-) create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java delete mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeRoutingModule.java diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java index e4467b68a..9b5bdea53 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/IDFConfigurator.java @@ -4,7 +4,7 @@ import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; import org.eqasim.ile_de_france.parking.IDFParkingModule; import org.eqasim.ile_de_france.probing.ProbeConfigGroup; -import org.eqasim.ile_de_france.probing.ProbeRoutingModule; +import org.eqasim.ile_de_france.probing.ProbeModule; import org.matsim.core.config.CommandLine; public class IDFConfigurator extends EqasimConfigurator { @@ -15,6 +15,6 @@ public IDFConfigurator(CommandLine cmd) { registerModule(new IDFParkingModule()); registerConfigGroup(new ProbeConfigGroup(), false); - registerModule(new ProbeRoutingModule()); + registerModule(new ProbeModule()); } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java index 213ba9912..1fadba116 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java @@ -19,6 +19,7 @@ import org.matsim.core.utils.timing.TimeInterpretation; import org.matsim.core.utils.timing.TimeTracker; +import com.google.common.base.Preconditions; import com.google.inject.Inject; public class IDFCarCostModel extends AbstractCostModelWithPreviousTrips { @@ -86,9 +87,32 @@ public double calculateParkingCost_EUR(Person person, DiscreteModeChoiceTrip tri } private final double FIRST_LAST_DURATION = 8.0 * 3600.0; + static public final String IS_FIRST_TRIP = "isFirstTrip"; + static public final String IS_LAST_TRIP = "isLastTrip"; + + private boolean isFirstTrip(DiscreteModeChoiceTrip trip, List previousTrips) { + Boolean attribute = (Boolean) trip.getTripAttributes().getAttribute(IS_FIRST_TRIP); + + if (attribute == null) { + return previousTrips.size() == 0; + } else { + return attribute; + } + } + + private boolean isLastTrip(DiscreteModeChoiceTrip trip, Person person) { + Boolean attribute = (Boolean) trip.getTripAttributes().getAttribute(IS_LAST_TRIP); + + if (attribute == null) { + List planElements = person.getSelectedPlan().getPlanElements(); + return planElements.get(planElements.size() - 1) == trip.getDestinationActivity(); + } else { + return attribute; + } + } private double getOriginDuration(Person person, DiscreteModeChoiceTrip trip, List previousTrips) { - if (previousTrips.size() == 0) { + if (isFirstTrip(trip, previousTrips)) { return FIRST_LAST_DURATION; } else { TimeTracker timeTracker = new TimeTracker(timeInterpretation); @@ -105,14 +129,14 @@ private double getOriginDuration(Person person, DiscreteModeChoiceTrip trip, Lis timeTracker.addActivity(trip.getOriginActivity()); double departureTime = timeTracker.getTime().seconds(); + Preconditions.checkState(arrivalTime <= departureTime); return departureTime - arrivalTime; } } private double getDestinationDuration(Person person, DiscreteModeChoiceTrip trip, List tripElements) { - List planElements = person.getSelectedPlan().getPlanElements(); - if (planElements.get(planElements.size() - 1) == trip.getDestinationActivity()) { + if (isLastTrip(trip, person)) { return FIRST_LAST_DURATION; } else { TimeTracker timeTracker = new TimeTracker(timeInterpretation); @@ -123,6 +147,7 @@ private double getDestinationDuration(Person person, DiscreteModeChoiceTrip trip timeTracker.addActivity(trip.getDestinationActivity()); double departureTime = timeTracker.getTime().seconds(); + Preconditions.checkState(arrivalTime <= departureTime); return departureTime - arrivalTime; } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java new file mode 100644 index 000000000..57e262e2c --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java @@ -0,0 +1,140 @@ +package org.eqasim.ile_de_france.probing; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +import org.eqasim.core.simulation.mode_choice.utilities.predictors.VariablePredictor; +import org.eqasim.core.simulation.mode_choice.utilities.predictors.VariablePredictorWithPreviousTrips; +import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.PlanElement; +import org.matsim.api.core.v01.population.Population; +import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; +import org.matsim.contribs.discrete_mode_choice.replanning.TripListConverter; +import org.matsim.core.controler.events.StartupEvent; +import org.matsim.core.controler.listener.StartupListener; +import org.matsim.core.router.TripRouter; +import org.matsim.facilities.ActivityFacilities; +import org.matsim.facilities.FacilitiesUtils; +import org.matsim.facilities.Facility; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class PredictionWriter implements StartupListener { + private final Population population; + private final TripRouter tripRouter; + private final ActivityFacilities facilities; + private final File outputPath; + + private final Set modes = new HashSet<>(); + private final List> predictorEntries = new LinkedList<>(); + private final List> predictorEntriesWithPreviousTrips = new LinkedList<>(); + + public PredictionWriter(Population population, TripRouter tripRouter, ActivityFacilities facilities, + File outputPath) { + this.population = population; + this.tripRouter = tripRouter; + this.facilities = facilities; + this.outputPath = outputPath; + } + + public PredictionWriter addPredictor(String name, String mode, + VariablePredictor predictor) { + predictorEntries.add(new PredictorEntry<>(name, mode, predictor)); + modes.add(mode); + return this; + } + + public PredictionWriter addPredictor(String name, VariablePredictor predictor) { + predictorEntries.add(new PredictorEntry<>(name, null, predictor)); + return this; + } + + public PredictionWriter addPredictor(String name, String mode, + VariablePredictorWithPreviousTrips predictor) { + predictorEntriesWithPreviousTrips.add(new PredictorEntryWithPreviousTrip<>(name, mode, predictor)); + return this; + } + + public PredictionWriter addPredictor(String name, + VariablePredictorWithPreviousTrips predictor) { + predictorEntriesWithPreviousTrips.add(new PredictorEntryWithPreviousTrip<>(name, null, predictor)); + return this; + } + + @Override + public void notifyStartup(StartupEvent event) { + List result = new LinkedList<>(); + + for (Person person : population.getPersons().values()) { + DiscreteModeChoiceTrip trip = new TripListConverter().convert(person.getSelectedPlan()).get(0); + + Facility originFacility = FacilitiesUtils.toFacility(trip.getOriginActivity(), facilities); + Facility destinationFacility = FacilitiesUtils.toFacility(trip.getDestinationActivity(), facilities); + + List> predictions = new LinkedList<>(); + + for (String mode : modes) { + List tripElements = tripRouter.calcRoute(mode, originFacility, + destinationFacility, + trip.getDepartureTime(), person, trip.getTripAttributes()); + + for (var entry : predictorEntries) { + if (entry.mode.equals(mode)) { + predictions.add(new PredictionEntry<>(entry.name, entry.mode, + entry.predictor.predictVariables(person, trip, tripElements))); + } + } + + for (var entry : predictorEntriesWithPreviousTrips) { + if (entry.mode.equals(mode)) { + predictions.add(new PredictionEntry<>(entry.name, entry.mode, + entry.predictor.predictVariables(person, trip, tripElements, Collections.emptyList()))); + } + } + } + + for (var entry : predictorEntries) { + if (entry.mode == null) { + predictions.add(new PredictionEntry<>(entry.name, null, + entry.predictor.predictVariables(person, trip, null))); + } + } + + for (var entry : predictorEntriesWithPreviousTrips) { + if (entry.mode == null) { + predictions.add(new PredictionEntry<>(entry.name, null, + entry.predictor.predictVariables(person, trip, null, null))); + } + } + + result.add(new PersonEntry(person.getId().toString(), predictions)); + } + + try { + new ObjectMapper().writeValue(outputPath, result); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public record PredictorEntryWithPreviousTrip( + String name, String mode, VariablePredictorWithPreviousTrips predictor) { + } + + public record PredictorEntry( + String name, String mode, VariablePredictor predictor) { + } + + public record PredictionEntry( + String name, String mode, T variables) { + } + + public record PersonEntry(String personId, List> predictions) { + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java index d6093a910..ff7899a2e 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java @@ -9,6 +9,9 @@ public class ProbeConfigGroup extends ReflectiveConfigGroup { @Parameter public boolean useProbeTravelTimes = false; + @Parameter + public boolean writePredictions = false; + public ProbeConfigGroup() { super(NAME); } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java new file mode 100644 index 000000000..d47295bfd --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java @@ -0,0 +1,76 @@ +package org.eqasim.ile_de_france.probing; + +import java.io.File; +import java.util.Set; + +import org.eqasim.core.simulation.mode_choice.utilities.predictors.BikePredictor; +import org.eqasim.core.simulation.mode_choice.utilities.predictors.CarPredictor; +import org.eqasim.core.simulation.mode_choice.utilities.predictors.WalkPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFCarPassengerPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFParkingPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPersonPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPtPredictor; +import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFSpatialPredictor; +import org.matsim.api.core.v01.population.Population; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.router.NetworkRoutingProvider; +import org.matsim.core.router.RoutingModule; +import org.matsim.core.router.TripRouter; +import org.matsim.facilities.ActivityFacilities; + +import com.google.inject.Inject; +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Provider; +import com.google.inject.Provides; +import com.google.inject.Singleton; +import com.google.inject.name.Names; + +public class ProbeModule extends AbstractModule { + @Override + public void install() { + ProbeConfigGroup config = ProbeConfigGroup.get(getConfig()); + + if (config.useProbeTravelTimes) { + for (String mode : Set.of("car", "car_passenger")) { + // delegate + bind(Key.get(RoutingModule.class, Names.named("base_" + mode))) + .toProvider(new NetworkRoutingProvider(mode)); + + // override + addRoutingModuleBinding(mode).toProvider(new Provider<>() { + @Inject + Injector injector; + + @Override + public ProbeNetworkRoutingModule get() { + RoutingModule delegate = injector + .getInstance(Key.get(RoutingModule.class, Names.named("base_" + mode))); + return new ProbeNetworkRoutingModule(delegate, mode); + } + }); + } + } + } + + @Provides + @Singleton + PredictionWriter providePredictionWriter(Population population, ActivityFacilities facilities, + TripRouter tripRouter, OutputDirectoryHierarchy outputHierarchy, Injector injector) { + File outputPath = new File(outputHierarchy.getOutputFilename("predictions.json")); + PredictionWriter writer = new PredictionWriter(population, tripRouter, facilities, outputPath); + + writer.addPredictor("car", "car", injector.getInstance(CarPredictor.class)); + writer.addPredictor("pt", "pt", injector.getInstance(IDFPtPredictor.class)); + writer.addPredictor("car_passenger", "car_passenger", injector.getInstance(IDFCarPassengerPredictor.class)); + writer.addPredictor("bicycle", "bicycle", injector.getInstance(BikePredictor.class)); + writer.addPredictor("walk", "walk", injector.getInstance(WalkPredictor.class)); + + writer.addPredictor("person", injector.getInstance(IDFPersonPredictor.class)); + writer.addPredictor("spatial", injector.getInstance(IDFSpatialPredictor.class)); + writer.addPredictor("parking", injector.getInstance(IDFParkingPredictor.class)); + + return writer; + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeRoutingModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeRoutingModule.java deleted file mode 100644 index 1e521343b..000000000 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeRoutingModule.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.eqasim.ile_de_france.probing; - -import java.util.Set; - -import org.matsim.core.controler.AbstractModule; -import org.matsim.core.router.NetworkRoutingProvider; -import org.matsim.core.router.RoutingModule; - -import com.google.inject.Inject; -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.Provider; -import com.google.inject.name.Names; - -public class ProbeRoutingModule extends AbstractModule { - @Override - public void install() { - ProbeConfigGroup config = ProbeConfigGroup.get(getConfig()); - - if (config.useProbeTravelTimes) { - for (String mode : Set.of("car", "car_passenger")) { - // delegate - bind(Key.get(RoutingModule.class, Names.named("base_" + mode))) - .toProvider(new NetworkRoutingProvider(mode)); - - // override - addRoutingModuleBinding(mode).toProvider(new Provider<>() { - @Inject - Injector injector; - - @Override - public ProbeNetworkRoutingModule get() { - RoutingModule delegate = injector - .getInstance(Key.get(RoutingModule.class, Names.named("base_" + mode))); - return new ProbeNetworkRoutingModule(delegate, mode); - } - }); - } - } - } -} From 023a2a42e8f406da65eec29835537f819c0453cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 16 Sep 2025 15:02:40 +0200 Subject: [PATCH 67/81] enable writer --- .../java/org/eqasim/ile_de_france/probing/ProbeModule.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java index d47295bfd..0c9a54f35 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java @@ -52,6 +52,10 @@ public ProbeNetworkRoutingModule get() { }); } } + + if (config.writePredictions) { + addControlerListenerBinding().to(PredictionWriter.class); + } } @Provides From 3064214267aef272e31ea40f29cfabb51dbc27b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 16 Sep 2025 15:04:50 +0200 Subject: [PATCH 68/81] add progress --- .../ile_de_france/probing/PredictionWriter.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java index 57e262e2c..4b37b0082 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Set; +import org.eqasim.core.misc.ParallelProgress; import org.eqasim.core.simulation.mode_choice.utilities.predictors.VariablePredictor; import org.eqasim.core.simulation.mode_choice.utilities.predictors.VariablePredictorWithPreviousTrips; import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; @@ -71,6 +72,9 @@ public PredictionWriter addPredictor(String name, public void notifyStartup(StartupEvent event) { List result = new LinkedList<>(); + ParallelProgress progress = new ParallelProgress("Writing predictions ...", population.getPersons().size()); + progress.start(); + for (Person person : population.getPersons().values()) { DiscreteModeChoiceTrip trip = new TripListConverter().convert(person.getSelectedPlan()).get(0); @@ -114,6 +118,7 @@ public void notifyStartup(StartupEvent event) { } result.add(new PersonEntry(person.getId().toString(), predictions)); + progress.update(1); } try { @@ -121,6 +126,12 @@ public void notifyStartup(StartupEvent event) { } catch (IOException e) { throw new RuntimeException(e); } + + try { + progress.close(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } } public record PredictorEntryWithPreviousTrip( From 1d3bafc6605fa5238c776630b32433b9d703d3d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 16 Sep 2025 15:17:35 +0200 Subject: [PATCH 69/81] directly make use of parking duration in probe model --- .../mode_choice/costs/IDFCarCostModel.java | 37 +++++++------------ 1 file changed, 14 insertions(+), 23 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java index 1fadba116..168a508ca 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/mode_choice/costs/IDFCarCostModel.java @@ -87,32 +87,17 @@ public double calculateParkingCost_EUR(Person person, DiscreteModeChoiceTrip tri } private final double FIRST_LAST_DURATION = 8.0 * 3600.0; - static public final String IS_FIRST_TRIP = "isFirstTrip"; - static public final String IS_LAST_TRIP = "isLastTrip"; - private boolean isFirstTrip(DiscreteModeChoiceTrip trip, List previousTrips) { - Boolean attribute = (Boolean) trip.getTripAttributes().getAttribute(IS_FIRST_TRIP); + private final static String PRECEDING_PARKING_DURATION = "precedingParkingDuration"; + private final static String FOLLOWING_PARKING_DURATION = "followingParkingDuration"; - if (attribute == null) { - return previousTrips.size() == 0; - } else { - return attribute; - } - } - - private boolean isLastTrip(DiscreteModeChoiceTrip trip, Person person) { - Boolean attribute = (Boolean) trip.getTripAttributes().getAttribute(IS_LAST_TRIP); - - if (attribute == null) { - List planElements = person.getSelectedPlan().getPlanElements(); - return planElements.get(planElements.size() - 1) == trip.getDestinationActivity(); - } else { - return attribute; + private double getOriginDuration(Person person, DiscreteModeChoiceTrip trip, List previousTrips) { + Double precedingParkingDuration = (Double) trip.getTripAttributes().getAttribute(PRECEDING_PARKING_DURATION); + if (precedingParkingDuration != null) { + return precedingParkingDuration; } - } - private double getOriginDuration(Person person, DiscreteModeChoiceTrip trip, List previousTrips) { - if (isFirstTrip(trip, previousTrips)) { + if (previousTrips.size() == 0) { return FIRST_LAST_DURATION; } else { TimeTracker timeTracker = new TimeTracker(timeInterpretation); @@ -136,7 +121,13 @@ private double getOriginDuration(Person person, DiscreteModeChoiceTrip trip, Lis private double getDestinationDuration(Person person, DiscreteModeChoiceTrip trip, List tripElements) { - if (isLastTrip(trip, person)) { + Double followingParkingDuration = (Double) trip.getTripAttributes().getAttribute(FOLLOWING_PARKING_DURATION); + if (followingParkingDuration != null) { + return followingParkingDuration; + } + + List planElements = person.getSelectedPlan().getPlanElements(); + if (planElements.get(planElements.size() - 1) == trip.getDestinationActivity()) { return FIRST_LAST_DURATION; } else { TimeTracker timeTracker = new TimeTracker(timeInterpretation); From 7a911b859ac12bcfb292a5b1a95ed71cfddc37f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 16 Sep 2025 16:56:34 +0200 Subject: [PATCH 70/81] update probing --- .../probing/PredictionWriter.java | 7 ++-- .../probing/ProbeConfigGroup.java | 3 -- .../ile_de_france/probing/ProbeModule.java | 4 --- .../ile_de_france/probing/RunPrediction.java | 36 +++++++++++++++++++ 4 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/RunPrediction.java diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java index 4b37b0082..ca2c1ed7a 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java @@ -17,8 +17,6 @@ import org.matsim.api.core.v01.population.Population; import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; import org.matsim.contribs.discrete_mode_choice.replanning.TripListConverter; -import org.matsim.core.controler.events.StartupEvent; -import org.matsim.core.controler.listener.StartupListener; import org.matsim.core.router.TripRouter; import org.matsim.facilities.ActivityFacilities; import org.matsim.facilities.FacilitiesUtils; @@ -26,7 +24,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; -public class PredictionWriter implements StartupListener { +public class PredictionWriter { private final Population population; private final TripRouter tripRouter; private final ActivityFacilities facilities; @@ -68,8 +66,7 @@ public PredictionWriter addPredictor(String name, return this; } - @Override - public void notifyStartup(StartupEvent event) { + public void run() { List result = new LinkedList<>(); ParallelProgress progress = new ParallelProgress("Writing predictions ...", population.getPersons().size()); diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java index ff7899a2e..d6093a910 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java @@ -9,9 +9,6 @@ public class ProbeConfigGroup extends ReflectiveConfigGroup { @Parameter public boolean useProbeTravelTimes = false; - @Parameter - public boolean writePredictions = false; - public ProbeConfigGroup() { super(NAME); } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java index 0c9a54f35..d47295bfd 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java @@ -52,10 +52,6 @@ public ProbeNetworkRoutingModule get() { }); } } - - if (config.writePredictions) { - addControlerListenerBinding().to(PredictionWriter.class); - } } @Provides diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/RunPrediction.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/RunPrediction.java new file mode 100644 index 000000000..b8ccf283e --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/RunPrediction.java @@ -0,0 +1,36 @@ +package org.eqasim.ile_de_france.probing; + +import java.io.IOException; +import java.util.concurrent.ExecutionException; + +import org.eqasim.core.simulation.EqasimConfigurator; +import org.matsim.api.core.v01.Scenario; +import org.matsim.core.config.CommandLine; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.controler.Controler; +import org.matsim.core.scenario.ScenarioUtils; + +public class RunPrediction { + public static void main(String[] args) + throws CommandLine.ConfigurationException, InterruptedException, IOException, ExecutionException { + CommandLine cmd = new CommandLine.Builder(args) // + .requireOptions("config-path") // + .build(); + + // Loading the config + EqasimConfigurator configurator = EqasimConfigurator.getInstance(cmd); + + Config config = ConfigUtils.loadConfig(cmd.getOptionStrict("config-path")); + configurator.updateConfig(config); + cmd.applyConfiguration(config); + + Scenario scenario = ScenarioUtils.createScenario(config); + configurator.configureScenario(scenario); + ScenarioUtils.loadScenario(scenario); + configurator.adjustScenario(scenario); + + Controler controller = new Controler(scenario); + controller.getInjector().getInstance(PredictionWriter.class).run(); + } +} From c6932ac5ae0f4fb3bbbf539ff6bfc29a5fb20218 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 16 Sep 2025 17:08:15 +0200 Subject: [PATCH 71/81] update --- .../java/org/eqasim/ile_de_france/probing/RunPrediction.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/RunPrediction.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/RunPrediction.java index b8ccf283e..a0ccdef1e 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/RunPrediction.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/RunPrediction.java @@ -31,6 +31,7 @@ public static void main(String[] args) configurator.adjustScenario(scenario); Controler controller = new Controler(scenario); + configurator.configureController(controller); controller.getInjector().getInstance(PredictionWriter.class).run(); } } From 91c9cf423f0716e8cb1f8a24fbe4fa1ad79800a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 16 Sep 2025 17:25:00 +0200 Subject: [PATCH 72/81] fix dep time --- .../java/org/eqasim/ile_de_france/probing/PredictionWriter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java index ca2c1ed7a..fdc85cb5b 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java @@ -74,6 +74,7 @@ public void run() { for (Person person : population.getPersons().values()) { DiscreteModeChoiceTrip trip = new TripListConverter().convert(person.getSelectedPlan()).get(0); + trip.setDepartureTime(trip.getOriginActivity().getEndTime().seconds()); Facility originFacility = FacilitiesUtils.toFacility(trip.getOriginActivity(), facilities); Facility destinationFacility = FacilitiesUtils.toFacility(trip.getDestinationActivity(), facilities); From c5a3b89c9d2b2f021ebde0b6119858dd02157831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 16 Sep 2025 17:50:26 +0200 Subject: [PATCH 73/81] bugfix --- .../org/eqasim/ile_de_france/probing/PredictionWriter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java index fdc85cb5b..d7e4cd421 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java @@ -87,14 +87,14 @@ public void run() { trip.getDepartureTime(), person, trip.getTripAttributes()); for (var entry : predictorEntries) { - if (entry.mode.equals(mode)) { + if (mode.equals(entry.mode)) { predictions.add(new PredictionEntry<>(entry.name, entry.mode, entry.predictor.predictVariables(person, trip, tripElements))); } } for (var entry : predictorEntriesWithPreviousTrips) { - if (entry.mode.equals(mode)) { + if (mode.equals(entry.mode)) { predictions.add(new PredictionEntry<>(entry.name, entry.mode, entry.predictor.predictVariables(person, trip, tripElements, Collections.emptyList()))); } From c54cd3f89d9a7fb79a4dc5cf60630a56efa084ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 17 Sep 2025 13:47:20 +0200 Subject: [PATCH 74/81] bugfix --- .../java/org/eqasim/ile_de_france/probing/PredictionWriter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java index d7e4cd421..6f0c239b4 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java @@ -57,6 +57,7 @@ public PredictionWriter addPredictor(String name, Vari public PredictionWriter addPredictor(String name, String mode, VariablePredictorWithPreviousTrips predictor) { predictorEntriesWithPreviousTrips.add(new PredictorEntryWithPreviousTrip<>(name, mode, predictor)); + modes.add(mode); return this; } From e68ba21157c3f706d7b0e0522979f1339d00dcde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 17 Sep 2025 17:07:47 +0200 Subject: [PATCH 75/81] add costs and utilities --- .../probing/PredictionWriter.java | 43 ++++++++++++++++++- .../ile_de_france/probing/ProbeModule.java | 20 +++++++++ 2 files changed, 61 insertions(+), 2 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java index 6f0c239b4..86a33a810 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java @@ -3,12 +3,16 @@ import java.io.File; import java.io.IOException; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Set; import org.eqasim.core.misc.ParallelProgress; +import org.eqasim.core.simulation.mode_choice.cost.CostModel; +import org.eqasim.core.simulation.mode_choice.utilities.UtilityEstimator; import org.eqasim.core.simulation.mode_choice.utilities.predictors.VariablePredictor; import org.eqasim.core.simulation.mode_choice.utilities.predictors.VariablePredictorWithPreviousTrips; import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; @@ -33,6 +37,8 @@ public class PredictionWriter { private final Set modes = new HashSet<>(); private final List> predictorEntries = new LinkedList<>(); private final List> predictorEntriesWithPreviousTrips = new LinkedList<>(); + private final List estimatorEntries = new LinkedList<>(); + private final List costModelEntries = new LinkedList<>(); public PredictionWriter(Population population, TripRouter tripRouter, ActivityFacilities facilities, File outputPath) { @@ -67,6 +73,16 @@ public PredictionWriter addPredictor(String name, return this; } + public PredictionWriter addEstimator(String mode, UtilityEstimator estimator) { + estimatorEntries.add(new EstimatorEntry(mode, estimator)); + return this; + } + + public PredictionWriter addCostModel(String mode, CostModel model) { + costModelEntries.add(new CostModelEntry(mode, model)); + return this; + } + public void run() { List result = new LinkedList<>(); @@ -81,6 +97,8 @@ public void run() { Facility destinationFacility = FacilitiesUtils.toFacility(trip.getDestinationActivity(), facilities); List> predictions = new LinkedList<>(); + Map utilities = new HashMap<>(); + Map costs = new HashMap<>(); for (String mode : modes) { List tripElements = tripRouter.calcRoute(mode, originFacility, @@ -100,6 +118,18 @@ public void run() { entry.predictor.predictVariables(person, trip, tripElements, Collections.emptyList()))); } } + + for (var entry : estimatorEntries) { + if (mode.equals(entry.mode)) { + utilities.put(mode, entry.estimator.estimateUtility(person, trip, tripElements)); + } + } + + for (var entry : costModelEntries) { + if (mode.equals(entry.mode)) { + costs.put(mode, entry.model.calculateCost_MU(person, trip, tripElements)); + } + } } for (var entry : predictorEntries) { @@ -116,7 +146,7 @@ public void run() { } } - result.add(new PersonEntry(person.getId().toString(), predictions)); + result.add(new PersonEntry(person.getId().toString(), predictions, utilities, costs)); progress.update(1); } @@ -141,10 +171,19 @@ public record PredictorEntry( String name, String mode, VariablePredictor predictor) { } + public record EstimatorEntry( + String mode, UtilityEstimator estimator) { + } + + public record CostModelEntry( + String mode, CostModel model) { + } + public record PredictionEntry( String name, String mode, T variables) { } - public record PersonEntry(String personId, List> predictions) { + public record PersonEntry(String personId, List> predictions, Map utilities, + Map costs) { } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java index d47295bfd..ab76e5fde 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java @@ -3,9 +3,16 @@ import java.io.File; import java.util.Set; +import org.eqasim.core.simulation.mode_choice.utilities.estimators.WalkUtilityEstimator; import org.eqasim.core.simulation.mode_choice.utilities.predictors.BikePredictor; import org.eqasim.core.simulation.mode_choice.utilities.predictors.CarPredictor; import org.eqasim.core.simulation.mode_choice.utilities.predictors.WalkPredictor; +import org.eqasim.ile_de_france.mode_choice.costs.IDFCarCostModel; +import org.eqasim.ile_de_france.mode_choice.costs.IDFPtCostModel; +import org.eqasim.ile_de_france.mode_choice.utilities.estimators.IDFBicycleUtilityEstimator; +import org.eqasim.ile_de_france.mode_choice.utilities.estimators.IDFCarPassengerUtilityEstimator; +import org.eqasim.ile_de_france.mode_choice.utilities.estimators.IDFCarUtilityEstimator; +import org.eqasim.ile_de_france.mode_choice.utilities.estimators.IDFPtUtilityEstimator; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFCarPassengerPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFParkingPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPersonPredictor; @@ -61,16 +68,29 @@ PredictionWriter providePredictionWriter(Population population, ActivityFaciliti File outputPath = new File(outputHierarchy.getOutputFilename("predictions.json")); PredictionWriter writer = new PredictionWriter(population, tripRouter, facilities, outputPath); + // mode specific predictors writer.addPredictor("car", "car", injector.getInstance(CarPredictor.class)); writer.addPredictor("pt", "pt", injector.getInstance(IDFPtPredictor.class)); writer.addPredictor("car_passenger", "car_passenger", injector.getInstance(IDFCarPassengerPredictor.class)); writer.addPredictor("bicycle", "bicycle", injector.getInstance(BikePredictor.class)); writer.addPredictor("walk", "walk", injector.getInstance(WalkPredictor.class)); + // mode independent predictors writer.addPredictor("person", injector.getInstance(IDFPersonPredictor.class)); writer.addPredictor("spatial", injector.getInstance(IDFSpatialPredictor.class)); writer.addPredictor("parking", injector.getInstance(IDFParkingPredictor.class)); + // mode estimators + writer.addEstimator("car", injector.getInstance(IDFCarUtilityEstimator.class)); + writer.addEstimator("car_passenger", injector.getInstance(IDFCarPassengerUtilityEstimator.class)); + writer.addEstimator("pt", injector.getInstance(IDFPtUtilityEstimator.class)); + writer.addEstimator("bicycle", injector.getInstance(IDFBicycleUtilityEstimator.class)); + writer.addEstimator("walk", injector.getInstance(WalkUtilityEstimator.class)); + + // mode costs + writer.addCostModel("car", injector.getInstance(IDFCarCostModel.class)); + writer.addCostModel("pt", injector.getInstance(IDFPtCostModel.class)); + return writer; } } From b228340795e6c8b430b34f91d76d5421bf22f01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 17 Sep 2025 17:53:22 +0200 Subject: [PATCH 76/81] add availability --- .../probing/PredictionWriter.java | 23 +++++++++++++++++-- .../ile_de_france/probing/ProbeModule.java | 4 ++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java index 86a33a810..4fd07c464 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java @@ -20,6 +20,7 @@ import org.matsim.api.core.v01.population.PlanElement; import org.matsim.api.core.v01.population.Population; import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; +import org.matsim.contribs.discrete_mode_choice.model.mode_availability.ModeAvailability; import org.matsim.contribs.discrete_mode_choice.replanning.TripListConverter; import org.matsim.core.router.TripRouter; import org.matsim.facilities.ActivityFacilities; @@ -39,6 +40,7 @@ public class PredictionWriter { private final List> predictorEntriesWithPreviousTrips = new LinkedList<>(); private final List estimatorEntries = new LinkedList<>(); private final List costModelEntries = new LinkedList<>(); + private final List availabilityEntries = new LinkedList<>(); public PredictionWriter(Population population, TripRouter tripRouter, ActivityFacilities facilities, File outputPath) { @@ -75,11 +77,18 @@ public PredictionWriter addPredictor(String name, public PredictionWriter addEstimator(String mode, UtilityEstimator estimator) { estimatorEntries.add(new EstimatorEntry(mode, estimator)); + modes.add(mode); return this; } public PredictionWriter addCostModel(String mode, CostModel model) { costModelEntries.add(new CostModelEntry(mode, model)); + modes.add(mode); + return this; + } + + public PredictionWriter addAvailability(String name, ModeAvailability availability) { + availabilityEntries.add(new AvailabilityEntry(name, availability)); return this; } @@ -99,6 +108,7 @@ public void run() { List> predictions = new LinkedList<>(); Map utilities = new HashMap<>(); Map costs = new HashMap<>(); + Map> availabilities = new HashMap<>(); for (String mode : modes) { List tripElements = tripRouter.calcRoute(mode, originFacility, @@ -146,7 +156,12 @@ public void run() { } } - result.add(new PersonEntry(person.getId().toString(), predictions, utilities, costs)); + for (var entry : availabilityEntries) { + availabilities.put(entry.name, + new HashSet<>(entry.availability.getAvailableModes(person, Collections.singletonList(trip)))); + } + + result.add(new PersonEntry(person.getId().toString(), predictions, utilities, costs, availabilities)); progress.update(1); } @@ -179,11 +194,15 @@ public record CostModelEntry( String mode, CostModel model) { } + public record AvailabilityEntry( + String name, ModeAvailability availability) { + } + public record PredictionEntry( String name, String mode, T variables) { } public record PersonEntry(String personId, List> predictions, Map utilities, - Map costs) { + Map costs, Map> availabilities) { } } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java index ab76e5fde..9b59bf4c6 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java @@ -7,6 +7,7 @@ import org.eqasim.core.simulation.mode_choice.utilities.predictors.BikePredictor; import org.eqasim.core.simulation.mode_choice.utilities.predictors.CarPredictor; import org.eqasim.core.simulation.mode_choice.utilities.predictors.WalkPredictor; +import org.eqasim.ile_de_france.mode_choice.IDFModeAvailability; import org.eqasim.ile_de_france.mode_choice.costs.IDFCarCostModel; import org.eqasim.ile_de_france.mode_choice.costs.IDFPtCostModel; import org.eqasim.ile_de_france.mode_choice.utilities.estimators.IDFBicycleUtilityEstimator; @@ -91,6 +92,9 @@ PredictionWriter providePredictionWriter(Population population, ActivityFaciliti writer.addCostModel("car", injector.getInstance(IDFCarCostModel.class)); writer.addCostModel("pt", injector.getInstance(IDFPtCostModel.class)); + // availability + writer.addAvailability("standard", injector.getInstance(IDFModeAvailability.class)); + return writer; } } From d694c79e9cc5deefec67ba397b75f3d5e9b9ffbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 17 Sep 2025 17:56:58 +0200 Subject: [PATCH 77/81] fix --- .../org/eqasim/ile_de_france/probing/ProbeModule.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java index 9b59bf4c6..bee99c94e 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java @@ -82,17 +82,25 @@ PredictionWriter providePredictionWriter(Population population, ActivityFaciliti writer.addPredictor("parking", injector.getInstance(IDFParkingPredictor.class)); // mode estimators + bind(IDFCarUtilityEstimator.class); // explicit bindings are required writer.addEstimator("car", injector.getInstance(IDFCarUtilityEstimator.class)); + bind(IDFCarPassengerUtilityEstimator.class); // explicit bindings are required writer.addEstimator("car_passenger", injector.getInstance(IDFCarPassengerUtilityEstimator.class)); + bind(IDFPtUtilityEstimator.class); // explicit bindings are required writer.addEstimator("pt", injector.getInstance(IDFPtUtilityEstimator.class)); + bind(IDFBicycleUtilityEstimator.class); // explicit bindings are required writer.addEstimator("bicycle", injector.getInstance(IDFBicycleUtilityEstimator.class)); + bind(WalkUtilityEstimator.class); // explicit bindings are required writer.addEstimator("walk", injector.getInstance(WalkUtilityEstimator.class)); // mode costs + bind(IDFCarCostModel.class); // explicit bindings are required writer.addCostModel("car", injector.getInstance(IDFCarCostModel.class)); + bind(IDFPtCostModel.class); // explicit bindings are required writer.addCostModel("pt", injector.getInstance(IDFPtCostModel.class)); // availability + bind(IDFModeAvailability.class); // explicit bindings are required writer.addAvailability("standard", injector.getInstance(IDFModeAvailability.class)); return writer; From c5b3d7ff497c8c684f896736137d22a6fcb77947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 17 Sep 2025 18:31:52 +0200 Subject: [PATCH 78/81] update --- .../ile_de_france/probing/ProbeModule.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java index bee99c94e..f766d832b 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java @@ -59,6 +59,16 @@ public ProbeNetworkRoutingModule get() { } }); } + + // explicit bindings are required + bind(IDFCarUtilityEstimator.class); + bind(IDFCarPassengerUtilityEstimator.class); + bind(IDFPtUtilityEstimator.class); + bind(IDFBicycleUtilityEstimator.class); + bind(WalkUtilityEstimator.class); + bind(IDFCarCostModel.class); + bind(IDFPtCostModel.class); + bind(IDFModeAvailability.class); } } @@ -82,25 +92,17 @@ PredictionWriter providePredictionWriter(Population population, ActivityFaciliti writer.addPredictor("parking", injector.getInstance(IDFParkingPredictor.class)); // mode estimators - bind(IDFCarUtilityEstimator.class); // explicit bindings are required writer.addEstimator("car", injector.getInstance(IDFCarUtilityEstimator.class)); - bind(IDFCarPassengerUtilityEstimator.class); // explicit bindings are required writer.addEstimator("car_passenger", injector.getInstance(IDFCarPassengerUtilityEstimator.class)); - bind(IDFPtUtilityEstimator.class); // explicit bindings are required writer.addEstimator("pt", injector.getInstance(IDFPtUtilityEstimator.class)); - bind(IDFBicycleUtilityEstimator.class); // explicit bindings are required writer.addEstimator("bicycle", injector.getInstance(IDFBicycleUtilityEstimator.class)); - bind(WalkUtilityEstimator.class); // explicit bindings are required writer.addEstimator("walk", injector.getInstance(WalkUtilityEstimator.class)); // mode costs - bind(IDFCarCostModel.class); // explicit bindings are required writer.addCostModel("car", injector.getInstance(IDFCarCostModel.class)); - bind(IDFPtCostModel.class); // explicit bindings are required writer.addCostModel("pt", injector.getInstance(IDFPtCostModel.class)); // availability - bind(IDFModeAvailability.class); // explicit bindings are required writer.addAvailability("standard", injector.getInstance(IDFModeAvailability.class)); return writer; From ad0303c028780a2edd9a963f56a66850c4bcce3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 17 Sep 2025 18:39:13 +0200 Subject: [PATCH 79/81] update --- .../eqasim/ile_de_france/probing/PredictionWriter.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java index 4fd07c464..4c2c0a8b8 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java @@ -13,6 +13,7 @@ import org.eqasim.core.misc.ParallelProgress; import org.eqasim.core.simulation.mode_choice.cost.CostModel; import org.eqasim.core.simulation.mode_choice.utilities.UtilityEstimator; +import org.eqasim.core.simulation.mode_choice.utilities.UtilityEstimatorWithPreviousTrips; import org.eqasim.core.simulation.mode_choice.utilities.predictors.VariablePredictor; import org.eqasim.core.simulation.mode_choice.utilities.predictors.VariablePredictorWithPreviousTrips; import org.eqasim.core.simulation.mode_choice.utilities.variables.BaseVariables; @@ -131,7 +132,12 @@ public void run() { for (var entry : estimatorEntries) { if (mode.equals(entry.mode)) { - utilities.put(mode, entry.estimator.estimateUtility(person, trip, tripElements)); + if (entry.estimator instanceof UtilityEstimatorWithPreviousTrips) { + utilities.put(mode, ((UtilityEstimatorWithPreviousTrips) entry.estimator) + .estimateUtility(person, trip, tripElements, Collections.emptyList())); + } else { + utilities.put(mode, entry.estimator.estimateUtility(person, trip, tripElements)); + } } } From 2b504d706ede4dbec3d7b9fe5493f1ac3b7ca7cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Wed, 17 Sep 2025 18:45:24 +0200 Subject: [PATCH 80/81] update --- .../eqasim/ile_de_france/probing/PredictionWriter.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java index 4c2c0a8b8..95996fe7e 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/PredictionWriter.java @@ -12,6 +12,7 @@ import org.eqasim.core.misc.ParallelProgress; import org.eqasim.core.simulation.mode_choice.cost.CostModel; +import org.eqasim.core.simulation.mode_choice.cost.CostModelWithPreviousTrips; import org.eqasim.core.simulation.mode_choice.utilities.UtilityEstimator; import org.eqasim.core.simulation.mode_choice.utilities.UtilityEstimatorWithPreviousTrips; import org.eqasim.core.simulation.mode_choice.utilities.predictors.VariablePredictor; @@ -143,7 +144,12 @@ public void run() { for (var entry : costModelEntries) { if (mode.equals(entry.mode)) { - costs.put(mode, entry.model.calculateCost_MU(person, trip, tripElements)); + if (entry.model instanceof CostModelWithPreviousTrips) { + costs.put(mode, ((CostModelWithPreviousTrips) entry.model).calculateCost_MU(person, trip, + tripElements, Collections.emptyList())); + } else { + costs.put(mode, entry.model.calculateCost_MU(person, trip, tripElements)); + } } } } From 2530dcc18e5003b59900eaaf18941ee89433d756 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 18 Sep 2025 10:51:25 +0200 Subject: [PATCH 81/81] update --- .../probing/ProbeConfigGroup.java | 3 +++ .../probing/ProbeModeAvailability.java | 27 +++++++++++++++++++ .../ile_de_france/probing/ProbeModule.java | 5 ++++ 3 files changed, 35 insertions(+) create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModeAvailability.java diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java index d6093a910..ae3affa97 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeConfigGroup.java @@ -9,6 +9,9 @@ public class ProbeConfigGroup extends ReflectiveConfigGroup { @Parameter public boolean useProbeTravelTimes = false; + @Parameter + public boolean useProbeAvailability = false; + public ProbeConfigGroup() { super(NAME); } diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModeAvailability.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModeAvailability.java new file mode 100644 index 000000000..f034d5f9a --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModeAvailability.java @@ -0,0 +1,27 @@ +package org.eqasim.ile_de_france.probing; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.matsim.api.core.v01.population.Person; +import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; +import org.matsim.contribs.discrete_mode_choice.model.mode_availability.ModeAvailability; + +public class ProbeModeAvailability implements ModeAvailability { + static public final String ATTRIBUTE = "probe:modeAvailability"; + + @Override + public Collection getAvailableModes(Person person, List trips) { + String raw = (String) person.getAttributes().getAttribute(ATTRIBUTE); + + Set modes = new HashSet<>(); + + for (String mode : raw.split(",")) { + modes.add(mode.strip()); + } + + return modes; + } +} diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java index f766d832b..51f81c7d5 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/probing/ProbeModule.java @@ -20,6 +20,7 @@ import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFPtPredictor; import org.eqasim.ile_de_france.mode_choice.utilities.predictors.IDFSpatialPredictor; import org.matsim.api.core.v01.population.Population; +import org.matsim.contribs.discrete_mode_choice.model.mode_availability.ModeAvailability; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.router.NetworkRoutingProvider; @@ -70,6 +71,10 @@ public ProbeNetworkRoutingModule get() { bind(IDFPtCostModel.class); bind(IDFModeAvailability.class); } + + if (config.useProbeAvailability) { + bind(ModeAvailability.class).toInstance(new ProbeModeAvailability()); + } } @Provides