From c97d77b703474d2044a6613ca37994b3795f7dbf Mon Sep 17 00:00:00 2001 From: Kai Nagel Date: Wed, 10 Jan 2024 21:50:32 +0100 Subject: [PATCH] build use case that tests the full infrastructure (existing tests also passed when toll-sensitive router was removed) --- contribs/decongestion/pom.xml | 10 +- .../decongestion/DecongestionModule.java | 60 ++++--- .../TollTimeDistanceTravelDisutility.java | 2 +- .../run/DecongestionRunExample.java | 3 +- .../run/DecongestionRunExampleFromConfig.java | 9 +- .../DecongestionPricingTestIT.java | 163 +++++++++++++++--- 6 files changed, 182 insertions(+), 65 deletions(-) diff --git a/contribs/decongestion/pom.xml b/contribs/decongestion/pom.xml index f95fa91552d..42c6ad098c0 100644 --- a/contribs/decongestion/pom.xml +++ b/contribs/decongestion/pom.xml @@ -4,7 +4,15 @@ contrib 16.0-SNAPSHOT - 4.0.0 + + + org.matsim.contrib + otfvis + ${parent.version} + test + + + 4.0.0 org.matsim.contrib decongestion decongestion diff --git a/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/DecongestionModule.java b/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/DecongestionModule.java index a6afea61fd6..b8129dd901c 100644 --- a/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/DecongestionModule.java +++ b/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/DecongestionModule.java @@ -19,12 +19,15 @@ package org.matsim.contrib.decongestion; -import org.matsim.api.core.v01.Scenario; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import org.matsim.api.core.v01.TransportMode; import org.matsim.contrib.decongestion.data.DecongestionInfo; import org.matsim.contrib.decongestion.handler.DelayAnalysis; import org.matsim.contrib.decongestion.handler.IntervalBasedTolling; import org.matsim.contrib.decongestion.handler.IntervalBasedTollingAll; import org.matsim.contrib.decongestion.handler.PersonVehicleTracker; +import org.matsim.contrib.decongestion.routing.TollTimeDistanceTravelDisutilityFactory; import org.matsim.contrib.decongestion.tollSetting.DecongestionTollSetting; import org.matsim.contrib.decongestion.tollSetting.DecongestionTollingBangBang; import org.matsim.contrib.decongestion.tollSetting.DecongestionTollingPID; @@ -37,51 +40,46 @@ public class DecongestionModule extends AbstractModule { - private final DecongestionConfigGroup decongestionConfigGroup; - - public DecongestionModule(Scenario scenario) { - this.decongestionConfigGroup = (DecongestionConfigGroup) scenario.getConfig().getModules().get(DecongestionConfigGroup.GROUP_NAME); - } + @Inject private DecongestionConfigGroup decongestionConfigGroup; @Override public void install() { if (decongestionConfigGroup.isEnableDecongestionPricing()) { - switch( decongestionConfigGroup.getDecongestionApproach() ) { - case BangBang: - this.bind(DecongestionTollingBangBang.class).asEagerSingleton(); - this.bind(DecongestionTollSetting.class).to(DecongestionTollingBangBang.class); - break; - case PID: - this.bind(DecongestionTollingPID.class).asEagerSingleton(); - this.bind(DecongestionTollSetting.class).to(DecongestionTollingPID.class); - this.addEventHandlerBinding().to(DecongestionTollingPID.class); - break; - case P_MC: - this.bind(DecongestionTollingP_MCP.class).asEagerSingleton(); - this.bind(DecongestionTollSetting.class).to(DecongestionTollingP_MCP.class); - this.addEventHandlerBinding().to(DecongestionTollingP_MCP.class); - break; - default: - throw new RuntimeException("not implemented") ; + switch( decongestionConfigGroup.getDecongestionApproach() ){ + case BangBang -> { + this.bind( DecongestionTollingBangBang.class ).in( Singleton.class ); + this.bind( DecongestionTollSetting.class ).to( DecongestionTollingBangBang.class ); + } + case PID -> { + this.bind( DecongestionTollingPID.class ).in( Singleton.class ); + this.bind( DecongestionTollSetting.class ).to( DecongestionTollingPID.class ); + this.addEventHandlerBinding().to( DecongestionTollingPID.class ); + } + case P_MC -> { + this.bind( DecongestionTollingP_MCP.class ).in( Singleton.class ); + this.bind( DecongestionTollSetting.class ).to( DecongestionTollingP_MCP.class ); + this.addEventHandlerBinding().to( DecongestionTollingP_MCP.class ); + } + default -> throw new RuntimeException( "not implemented" ); } } else { // no pricing } - this.bind(DecongestionInfo.class).asEagerSingleton(); + addTravelDisutilityFactoryBinding( TransportMode.car ).to( TollTimeDistanceTravelDisutilityFactory.class ); + + this.bind(DecongestionInfo.class).in( Singleton.class ); - this.bind(IntervalBasedTollingAll.class).asEagerSingleton(); - this.bind(IntervalBasedTolling.class).to(IntervalBasedTollingAll.class); - this.addEventHandlerBinding().to(IntervalBasedTollingAll.class); + this.bind(IntervalBasedTolling.class).to(IntervalBasedTollingAll.class).in( Singleton.class ); + this.addEventHandlerBinding().to(IntervalBasedTolling.class); - this.bind(DelayAnalysis.class).asEagerSingleton(); - this.addEventHandlerBinding().to(DelayAnalysis.class); + this.addEventHandlerBinding().to(DelayAnalysis.class).in( Singleton.class ); - this.addEventHandlerBinding().to(PersonVehicleTracker.class).asEagerSingleton(); + this.addEventHandlerBinding().to(PersonVehicleTracker.class).in( Singleton.class ); - this.addControlerListenerBinding().to(DecongestionControlerListener.class); + this.addControlerListenerBinding().to(DecongestionControlerListener.class).in( Singleton.class ); } } diff --git a/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/routing/TollTimeDistanceTravelDisutility.java b/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/routing/TollTimeDistanceTravelDisutility.java index f4036b3e1a0..1ad6ad0f479 100644 --- a/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/routing/TollTimeDistanceTravelDisutility.java +++ b/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/routing/TollTimeDistanceTravelDisutility.java @@ -39,7 +39,7 @@ * * @author ikaddoura */ -public final class TollTimeDistanceTravelDisutility implements TravelDisutility { +final class TollTimeDistanceTravelDisutility implements TravelDisutility { private static final Logger log = LogManager.getLogger(TollTimeDistanceTravelDisutility.class); private final TravelDisutility delegate; diff --git a/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/run/DecongestionRunExample.java b/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/run/DecongestionRunExample.java index 09fecc0f0e5..28ea4b3cfa5 100644 --- a/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/run/DecongestionRunExample.java +++ b/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/run/DecongestionRunExample.java @@ -39,7 +39,6 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; -import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.scenario.ScenarioUtils; /** @@ -108,7 +107,7 @@ private void run() { Controler controler = new Controler(scenario); // congestion toll computation - controler.addOverridingModule(new DecongestionModule(scenario) ); + controler.addOverridingModule(new DecongestionModule() ); // toll-adjusted routing controler.addOverridingModule(new AbstractModule(){ diff --git a/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/run/DecongestionRunExampleFromConfig.java b/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/run/DecongestionRunExampleFromConfig.java index 407c71c08ee..7bfe040d503 100644 --- a/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/run/DecongestionRunExampleFromConfig.java +++ b/contribs/decongestion/src/main/java/org/matsim/contrib/decongestion/run/DecongestionRunExampleFromConfig.java @@ -37,7 +37,6 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; -import org.matsim.core.controler.OutputDirectoryHierarchy; import org.matsim.core.scenario.ScenarioUtils; /** @@ -72,22 +71,18 @@ private void run() { Config config = ConfigUtils.loadConfig(configFile, new DecongestionConfigGroup() ); final Scenario scenario = ScenarioUtils.loadScenario(config); - Controler controler = new Controler(scenario); - // ############################################################# + Controler controler = new Controler(scenario); // congestion toll computation - - controler.addOverridingModule(new DecongestionModule(scenario) ); + controler.addOverridingModule(new DecongestionModule() ); // toll-adjusted routing - controler.addOverridingModule(new AbstractModule(){ @Override public void install() { addTravelDisutilityFactoryBinding( TransportMode.car ).toInstance( new TollTimeDistanceTravelDisutilityFactory() ); // yyyy try if this could add the class instead of the instance. possibly as singleton. kai, jan'24 - } }); diff --git a/contribs/decongestion/src/test/java/org/matsim/contrib/decongestion/DecongestionPricingTestIT.java b/contribs/decongestion/src/test/java/org/matsim/contrib/decongestion/DecongestionPricingTestIT.java index 71f839a4070..ee68e87271b 100644 --- a/contribs/decongestion/src/test/java/org/matsim/contrib/decongestion/DecongestionPricingTestIT.java +++ b/contribs/decongestion/src/test/java/org/matsim/contrib/decongestion/DecongestionPricingTestIT.java @@ -28,8 +28,12 @@ import org.matsim.analysis.ScoreStatsControlerListener.ScoreItem; import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.TransportMode; +import org.matsim.api.core.v01.network.Network; +import org.matsim.api.core.v01.population.Population; import org.matsim.contrib.decongestion.DecongestionConfigGroup.DecongestionApproach; import org.matsim.contrib.decongestion.data.DecongestionInfo; +import org.matsim.contrib.decongestion.data.LinkInfo; import org.matsim.contrib.decongestion.handler.DelayAnalysis; import org.matsim.contrib.decongestion.handler.IntervalBasedTolling; import org.matsim.contrib.decongestion.handler.IntervalBasedTollingAll; @@ -43,9 +47,14 @@ import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.Controler; import org.matsim.core.controler.OutputDirectoryHierarchy; +import org.matsim.core.router.util.TravelTime; import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.io.IOUtils; +import org.matsim.examples.ExamplesUtils; import org.matsim.testcases.MatsimTestUtils; +import java.net.URL; + /** * * @@ -114,16 +123,13 @@ public void install() { // toll-adjusted routing - final TollTimeDistanceTravelDisutilityFactory travelDisutilityFactory = new TollTimeDistanceTravelDisutilityFactory(); - controler.addOverridingModule(new AbstractModule(){ @Override public void install() { - this.bindCarTravelDisutilityFactory().toInstance( travelDisutilityFactory ); + addTravelDisutilityFactoryBinding( TransportMode.car ).toInstance( new TollTimeDistanceTravelDisutilityFactory() ); } }); - controler.getConfig().controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); controler.run(); double tt0 = controler.getLinkTravelTimes().getLinkTravelTime(scenario.getNetwork().getLinks().get(Id.createLinkId("link12")), 6 * 3600 + 50. * 60, null, null); @@ -155,14 +161,14 @@ final void test0amodified() { System.out.println(testUtils.getPackageInputDirectory()); - final String configFile = testUtils.getPackageInputDirectory() + "/config0.xml"; + // --- - Config config = ConfigUtils.loadConfig(configFile); + Config config = ConfigUtils.loadConfig( testUtils.getPackageInputDirectory() + "/config0.xml" ); - String outputDirectory = testUtils.getOutputDirectory() + "/"; - config.controller().setOutputDirectory(outputDirectory); + config.controller().setOutputDirectory( testUtils.getOutputDirectory() ); + + final DecongestionConfigGroup decongestionSettings = ConfigUtils.addOrGetModule( config, DecongestionConfigGroup.class ); - final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); decongestionSettings.setWriteOutputIteration(1); decongestionSettings.setKp(0.0123); decongestionSettings.setKd(0.0); @@ -171,28 +177,31 @@ final void test0amodified() { decongestionSettings.setTollBlendFactor(1.0); decongestionSettings.setFractionOfIterationsToEndPriceAdjustment(1.0); decongestionSettings.setFractionOfIterationsToStartPriceAdjustment(0.0); - config.addModule(decongestionSettings); + + // --- final Scenario scenario = ScenarioUtils.loadScenario(config); + + // --- + Controler controler = new Controler(scenario); // congestion toll computation - controler.addOverridingModule(new DecongestionModule(scenario)); + controler.addOverridingModule(new DecongestionModule() ); // toll-adjusted routing - final TollTimeDistanceTravelDisutilityFactory travelDisutilityFactory = new TollTimeDistanceTravelDisutilityFactory(); - controler.addOverridingModule(new AbstractModule(){ @Override public void install() { - this.bindCarTravelDisutilityFactory().toInstance( travelDisutilityFactory ); + addTravelDisutilityFactoryBinding( TransportMode.car ).toInstance( new TollTimeDistanceTravelDisutilityFactory() ); } }); - controler.getConfig().controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); controler.run(); + // --- + double tt0 = controler.getLinkTravelTimes().getLinkTravelTime(scenario.getNetwork().getLinks().get(Id.createLinkId("link12")), 6 * 3600 + 50. * 60, null, null); double tt1 = controler.getLinkTravelTimes().getLinkTravelTime(scenario.getNetwork().getLinks().get(Id.createLinkId("link12")), 7 * 3600 + 63, null, null); double tt2 = controler.getLinkTravelTimes().getLinkTravelTime(scenario.getNetwork().getLinks().get(Id.createLinkId("link12")), 7 * 3600 + 15. * 60, null, null); @@ -206,6 +215,114 @@ public void install() { Assertions.assertEquals(-33.940316666666666, avgScore, MatsimTestUtils.EPSILON, "Wrong average executed score. The tolls seem to have changed."); } + /** + * Kp = 0.0123, other syntax, kn + * + */ + @Test + final void test0amodifiedKn() { + + URL configUrl = IOUtils.extendUrl( ExamplesUtils.getTestScenarioURL( "equil" ), "config.xml" ); + + Config config = ConfigUtils.loadConfig( configUrl ); + config.controller().setOutputDirectory( testUtils.getOutputDirectory() ); + + config.plans().setInputFile( "plans2000.xml.gz" ); + // (in my first attempts, the default plans file had too few agents. after my later changes, it may no longer be necessary to use this file here. kai, jan'23) + + config.controller().setLastIteration( 20 ); + // (need some iterations for the decongestion to unfold. 20 may be more than really needed. kai, jan'23) + + final DecongestionConfigGroup decongestionSettings = ConfigUtils.addOrGetModule( config, DecongestionConfigGroup.class ); + + decongestionSettings.setWriteOutputIteration(1); +// decongestionSettings.setKp(0.0123); + decongestionSettings.setKp(0.123); + decongestionSettings.setKd(0.0); + decongestionSettings.setKi(0.0); + decongestionSettings.setMsa(false); + decongestionSettings.setTollBlendFactor(1.0); + decongestionSettings.setFractionOfIterationsToEndPriceAdjustment(1.0); + decongestionSettings.setFractionOfIterationsToStartPriceAdjustment(0.0); + + // === + + final Scenario scenario = ScenarioUtils.loadScenario(config); + + Network network = scenario.getNetwork(); + + // make middle link faster + network.getLinks().get( Id.createLinkId( "6" )).setFreespeed( 100. ); + + // make alternative wider + network.getLinks().get( Id.createLinkId( "14" ) ).setCapacity( 100000. ); + + // increase some other capacities: + network.getLinks().get( Id.createLinkId( "5" ) ).setCapacity( 100000. ); + network.getLinks().get( Id.createLinkId( "6" ) ).setCapacity( 100000. ); + + // remove all other alternatives: + network.removeLink( Id.createLinkId( "11" ) ); + network.removeLink( Id.createLinkId( "12" ) ); + network.removeLink( Id.createLinkId( "13" ) ); + network.removeLink( Id.createLinkId( "16" ) ); + network.removeLink( Id.createLinkId( "17" ) ); + network.removeLink( Id.createLinkId( "18" ) ); + network.removeLink( Id.createLinkId( "19" ) ); + + network.removeLink( Id.createLinkId( "2" ) ); + network.removeLink( Id.createLinkId( "3" ) ); + network.removeLink( Id.createLinkId( "4" ) ); + network.removeLink( Id.createLinkId( "7" ) ); + network.removeLink( Id.createLinkId( "8" ) ); + network.removeLink( Id.createLinkId( "9" ) ); + network.removeLink( Id.createLinkId( "10" ) ); + + // --- + + Population population = scenario.getPopulation(); + + // remove 3/4 of the population to reduce computation time: + for ( int ii=500; ii<2000; ii++ ){ + population.removePerson( Id.createPersonId( ii ) ); + } + + + // --- + + Controler controler = new Controler(scenario); + + controler.addOverridingModule(new DecongestionModule() ); + +// controler.addOverridingModule( new OTFVisLiveModule() ); + + controler.run(); + + // === + + DecongestionInfo info = controler.getInjector().getInstance( DecongestionInfo.class ); + + final LinkInfo linkInfo = info.getlinkInfos().get( Id.createLinkId( "15" ) ); + if ( linkInfo!= null ){ + System.out.println( linkInfo.getTime2toll().toString() ); + } + + final TravelTime linkTravelTimes = controler.getLinkTravelTimes(); + double tt0a = linkTravelTimes.getLinkTravelTime(scenario.getNetwork().getLinks().get(Id.createLinkId("15" ) ), 6 * 3600-1 , null, null ); + double tt0b = linkTravelTimes.getLinkTravelTime(scenario.getNetwork().getLinks().get(Id.createLinkId("15" ) ), 6 * 3600 , null, null ); + double tt0c = linkTravelTimes.getLinkTravelTime(scenario.getNetwork().getLinks().get(Id.createLinkId("15" ) ), 6 * 3600+15*60 , null, null ); + double tt1 = linkTravelTimes.getLinkTravelTime(scenario.getNetwork().getLinks().get(Id.createLinkId("14" ) ), 6 * 3600, null, null ); + + System.err.println( tt0a + " " + tt0b + " " + tt0c ); + System.err.println( tt1 ); + + Assertions.assertEquals(179.985, tt0a, MatsimTestUtils.EPSILON, "Wrong travel time. The run output seems to have changed."); + Assertions.assertEquals(344.04, tt0b, MatsimTestUtils.EPSILON, "Wrong travel time. The run output seems to have changed."); + Assertions.assertEquals(179.985, tt0c, MatsimTestUtils.EPSILON, "Wrong travel time. The run output seems to have changed."); + Assertions.assertEquals(180.0, tt1, MatsimTestUtils.EPSILON, "Wrong travel time. The run output seems to have changed."); + + } + /** * Kp = 2 * @@ -268,13 +385,15 @@ public void install() { controler.addOverridingModule(new AbstractModule(){ @Override public void install() { - this.bindCarTravelDisutilityFactory().toInstance( travelDisutilityFactory ); + addTravelDisutilityFactoryBinding( TransportMode.car ).toInstance( travelDisutilityFactory ); } }); controler.getConfig().controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); controler.run(); + // === + double tt0 = controler.getLinkTravelTimes().getLinkTravelTime(scenario.getNetwork().getLinks().get(Id.createLinkId("link12")), 6 * 3600 + 50. * 60, null, null); double tt1 = controler.getLinkTravelTimes().getLinkTravelTime(scenario.getNetwork().getLinks().get(Id.createLinkId("link12")), 7 * 3600 + 63, null, null); double tt2 = controler.getLinkTravelTimes().getLinkTravelTime(scenario.getNetwork().getLinks().get(Id.createLinkId("link12")), 7 * 3600 + 15. * 60, null, null); @@ -325,7 +444,7 @@ final void test0bmodified() { Controler controler = new Controler(scenario); // congestion toll computation - controler.addOverridingModule(new DecongestionModule(scenario)); + controler.addOverridingModule(new DecongestionModule() ); // toll-adjusted routing @@ -334,7 +453,7 @@ final void test0bmodified() { controler.addOverridingModule(new AbstractModule(){ @Override public void install() { - this.bindCarTravelDisutilityFactory().toInstance( travelDisutilityFactory ); + addTravelDisutilityFactoryBinding( TransportMode.car ).toInstance( travelDisutilityFactory ); } }); @@ -505,11 +624,9 @@ final void test2() { System.out.println(testUtils.getPackageInputDirectory()); - final String configFile = testUtils.getPackageInputDirectory() + "/config.xml"; - Config config = ConfigUtils.loadConfig(configFile); + Config config = ConfigUtils.loadConfig( testUtils.getPackageInputDirectory() + "/config.xml" ); - String outputDirectory = testUtils.getOutputDirectory() + "/"; - config.controller().setOutputDirectory(outputDirectory); + config.controller().setOutputDirectory( testUtils.getOutputDirectory() ); final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); decongestionSettings.setWriteOutputIteration(1); @@ -545,9 +662,9 @@ public void install() { } }); - controler.getConfig().controller().setOverwriteFileSetting(OutputDirectoryHierarchy.OverwriteFileSetting.deleteDirectoryIfExists); controler.run(); + // --- final int index = config.controller().getLastIteration() - config.controller().getFirstIteration(); double avgScore = controler.getScoreStats().getScoreHistory().get( ScoreItem.executed ).get( index ) ;