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 81f84e13492..58477477f23 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 @@ -1,560 +1,561 @@ -/* *********************************************************************** * - * project: org.matsim.* - * * - * *********************************************************************** * - * * - * copyright : (C) 2013 by the members listed in the COPYING, * - * LICENSE and WARRANTY file. * - * email : info at matsim dot org * - * * - * *********************************************************************** * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * See also COPYING, LICENSE and WARRANTY file * - * * - * *********************************************************************** */ - -/** - * - */ -package org.matsim.contrib.decongestion; - -import org.junit.Assert; -import org.junit.Rule; -import org.junit.Test; -import org.matsim.analysis.ScoreStatsControlerListener.ScoreItem; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.Scenario; -import org.matsim.contrib.decongestion.DecongestionConfigGroup.DecongestionApproach; -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; -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.controler.OutputDirectoryHierarchy; -import org.matsim.core.scenario.ScenarioUtils; -import org.matsim.testcases.MatsimTestUtils; - -/** - * - * - * @author ikaddoura - * - */ -public class DecongestionPricingTestIT { - - @Rule - public MatsimTestUtils testUtils = new MatsimTestUtils(); - - /** - * Kp = 0.0123 - * - */ - @Test - public final void test0a() { - - System.out.println(testUtils.getPackageInputDirectory()); - - final String configFile = testUtils.getPackageInputDirectory() + "/config0.xml"; - - Config config = ConfigUtils.loadConfig(configFile); - - String outputDirectory = testUtils.getOutputDirectory() + "/"; - config.controller().setOutputDirectory(outputDirectory); - - final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); - decongestionSettings.setWriteOutputIteration(1); - decongestionSettings.setKp(0.0123); - decongestionSettings.setKd(0.0); - decongestionSettings.setKi(0.0); - decongestionSettings.setMsa(false); - 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); - - DecongestionInfo info = new DecongestionInfo(); - - // congestion toll computation - controler.addOverridingModule(new AbstractModule() { - @Override - public void install() { - - this.bind(DecongestionInfo.class).toInstance(info); - - this.bind(DecongestionTollSetting.class).to(DecongestionTollingPID.class); - this.bind(IntervalBasedTolling.class).to(IntervalBasedTollingAll.class); - - this.bind(IntervalBasedTollingAll.class).asEagerSingleton(); - this.bind(DelayAnalysis.class).asEagerSingleton(); - this.bind(PersonVehicleTracker.class).asEagerSingleton(); - - this.addEventHandlerBinding().to(IntervalBasedTollingAll.class); - this.addEventHandlerBinding().to(DelayAnalysis.class); - this.addEventHandlerBinding().to(PersonVehicleTracker.class); - - this.addControlerListenerBinding().to(DecongestionControlerListener.class); - - } - }); - - // toll-adjusted routing - - final TollTimeDistanceTravelDisutilityFactory travelDisutilityFactory = new TollTimeDistanceTravelDisutilityFactory(); - - controler.addOverridingModule(new AbstractModule(){ - @Override - public void install() { - this.bindCarTravelDisutilityFactory().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); - - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt0, MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 150.5, tt1, MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt2, MatsimTestUtils.EPSILON); - - final int index = config.controller().getLastIteration() - config.controller().getFirstIteration(); - double avgScore = controler.getScoreStats().getScoreHistory().get( ScoreItem.executed ).get(index); - Assert.assertEquals("Wrong average executed score. The tolls seem to have changed.", -33.940316666666666, avgScore, MatsimTestUtils.EPSILON); - - System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().toString()); - System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2avgDelay().toString()); - - Assert.assertEquals("Wrong average delay (capacity is set in a way that one of the two agents has to wait 101 sec. Thus the average is 50.5", 50.5, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2avgDelay().get(84), MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong toll.", 50.5 * 0.0123, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().get(84), MatsimTestUtils.EPSILON); - - } - - /** - * Kp = 0.0123, other syntax - * - */ - @Test - public final void test0amodified() { - - System.out.println(testUtils.getPackageInputDirectory()); - - final String configFile = testUtils.getPackageInputDirectory() + "/config0.xml"; - - Config config = ConfigUtils.loadConfig(configFile); - - String outputDirectory = testUtils.getOutputDirectory() + "/"; - config.controller().setOutputDirectory(outputDirectory); - - final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); - decongestionSettings.setWriteOutputIteration(1); - decongestionSettings.setKp(0.0123); - decongestionSettings.setKd(0.0); - decongestionSettings.setKi(0.0); - decongestionSettings.setMsa(false); - 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)); - - // toll-adjusted routing - - final TollTimeDistanceTravelDisutilityFactory travelDisutilityFactory = new TollTimeDistanceTravelDisutilityFactory(); - - controler.addOverridingModule(new AbstractModule(){ - @Override - public void install() { - this.bindCarTravelDisutilityFactory().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); - - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt0, MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 150.5, tt1, MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt2, MatsimTestUtils.EPSILON); - - final int index = config.controller().getLastIteration() - config.controller().getFirstIteration(); - double avgScore = controler.getScoreStats().getScoreHistory().get( ScoreItem.executed ).get(index); - Assert.assertEquals("Wrong average executed score. The tolls seem to have changed.", -33.940316666666666, avgScore, MatsimTestUtils.EPSILON); - } - - /** - * Kp = 2 - * - */ - @Test - public final void test0b() { - - System.out.println(testUtils.getPackageInputDirectory()); - - final String configFile = testUtils.getPackageInputDirectory() + "/config0.xml"; - - Config config = ConfigUtils.loadConfig(configFile); - - String outputDirectory = testUtils.getOutputDirectory() + "/"; - config.controller().setOutputDirectory(outputDirectory); - - final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); - decongestionSettings.setWriteOutputIteration(1); - decongestionSettings.setKp(2.0); - decongestionSettings.setKd(0.0); - decongestionSettings.setKi(0.0); - decongestionSettings.setMsa(false); - 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); - - DecongestionInfo info = new DecongestionInfo(); - - // congestion toll computation - controler.addOverridingModule(new AbstractModule() { - @Override - public void install() { - - this.bind(DecongestionInfo.class).toInstance(info); - - this.bind(DecongestionTollSetting.class).to(DecongestionTollingPID.class); - this.bind(IntervalBasedTolling.class).to(IntervalBasedTollingAll.class); - - this.bind(IntervalBasedTollingAll.class).asEagerSingleton(); - this.bind(DelayAnalysis.class).asEagerSingleton(); - this.bind(PersonVehicleTracker.class).asEagerSingleton(); - - this.addEventHandlerBinding().to(IntervalBasedTollingAll.class); - this.addEventHandlerBinding().to(DelayAnalysis.class); - this.addEventHandlerBinding().to(PersonVehicleTracker.class); - - this.addControlerListenerBinding().to(DecongestionControlerListener.class); - - } - }); - - // toll-adjusted routing - - final TollTimeDistanceTravelDisutilityFactory travelDisutilityFactory = new TollTimeDistanceTravelDisutilityFactory(); - - controler.addOverridingModule(new AbstractModule(){ - @Override - public void install() { - this.bindCarTravelDisutilityFactory().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); - - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt0, MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 150.5, tt1, MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt2, MatsimTestUtils.EPSILON); - - final int index = config.controller().getLastIteration() - config.controller().getFirstIteration(); - double avgScore = controler.getScoreStats().getScoreHistory().get( ScoreItem.executed ).get(index); - Assert.assertEquals("Wrong average executed score. The tolls seem to have changed.", -134.31916666666666, avgScore, MatsimTestUtils.EPSILON); - - System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().toString()); - System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2avgDelay().toString()); - - Assert.assertEquals("Wrong average delay (capacity is set in a way that one of the two agents has to wait 101 sec. Thus the average is 50.5", 50.5, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2avgDelay().get(84), MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong toll.", 50.5 * 2, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().get(84), MatsimTestUtils.EPSILON); - } - - /** - * Kp = 2 - * - */ - @Test - public final void test0bmodified() { - - System.out.println(testUtils.getPackageInputDirectory()); - - final String configFile = testUtils.getPackageInputDirectory() + "/config0.xml"; - - Config config = ConfigUtils.loadConfig(configFile); - - String outputDirectory = testUtils.getOutputDirectory() + "/"; - config.controller().setOutputDirectory(outputDirectory); - - final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); - decongestionSettings.setWriteOutputIteration(1); - decongestionSettings.setKp(2.0); - decongestionSettings.setKd(0.0); - decongestionSettings.setKi(0.0); - decongestionSettings.setMsa(false); - 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)); - - // toll-adjusted routing - - final TollTimeDistanceTravelDisutilityFactory travelDisutilityFactory = new TollTimeDistanceTravelDisutilityFactory(); - - controler.addOverridingModule(new AbstractModule(){ - @Override - public void install() { - this.bindCarTravelDisutilityFactory().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); - - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt0, MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 150.5, tt1, MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt2, MatsimTestUtils.EPSILON); - - final int index = config.controller().getLastIteration() - config.controller().getFirstIteration(); - double avgScore = controler.getScoreStats().getScoreHistory().get( ScoreItem.executed ).get(index); - Assert.assertEquals("Wrong average executed score. The tolls seem to have changed.", -134.31916666666666, avgScore, MatsimTestUtils.EPSILON); - } - - /** - * Kp = 0 / no tolling - * - */ - @Test - public final void test0c() { - - System.out.println(testUtils.getPackageInputDirectory()); - - final String configFile = testUtils.getPackageInputDirectory() + "/config0.xml"; - - Config config = ConfigUtils.loadConfig(configFile); - - String outputDirectory = testUtils.getOutputDirectory() + "/"; - config.controller().setOutputDirectory(outputDirectory); - - final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); - decongestionSettings.setWriteOutputIteration(1); - decongestionSettings.setKp(0.0); - decongestionSettings.setKd(0.0); - decongestionSettings.setKi(0.0); - decongestionSettings.setMsa(false); - 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); - - DecongestionInfo info = new DecongestionInfo(); - - // congestion toll computation - controler.addOverridingModule(new AbstractModule() { - @Override - public void install() { - - this.bind(DecongestionInfo.class).toInstance(info); - - this.bind(DelayAnalysis.class).asEagerSingleton(); - this.addEventHandlerBinding().to(DelayAnalysis.class); - - this.addControlerListenerBinding().to(DecongestionControlerListener.class); - - } - }); - - // toll-adjusted routing - - final TollTimeDistanceTravelDisutilityFactory travelDisutilityFactory = new TollTimeDistanceTravelDisutilityFactory(); - - controler.addOverridingModule(new AbstractModule(){ - @Override - public void install() { - this.bindCarTravelDisutilityFactory().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); - - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt0, MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 150.5, tt1, MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt2, MatsimTestUtils.EPSILON); - - final int index = config.controller().getLastIteration() - config.controller().getFirstIteration(); - double avgScore = controler.getScoreStats().getScoreHistory().get( ScoreItem.executed ).get(index); - Assert.assertEquals("Wrong average executed score. The tolls seem to have changed.", -33.31916666666666, avgScore, MatsimTestUtils.EPSILON); - - System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().toString()); - System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2avgDelay().toString()); - - Assert.assertEquals("Wrong average delay (capacity is set in a way that one of the two agents has to wait 101 sec. Thus the average is 50.5", 50.5, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2avgDelay().get(84), MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong toll.", null, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().get(84)); - - } - - /** - * Tests the PID controller - * - */ - @Test - public final void test1() { - - System.out.println(testUtils.getPackageInputDirectory()); - - final String configFile = testUtils.getPackageInputDirectory() + "/config.xml"; - Config config = ConfigUtils.loadConfig(configFile); - - String outputDirectory = testUtils.getOutputDirectory() + "/"; - config.controller().setOutputDirectory(outputDirectory); - - final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); - decongestionSettings.setWriteOutputIteration(1); - decongestionSettings.setFractionOfIterationsToEndPriceAdjustment(1.0); - decongestionSettings.setFractionOfIterationsToStartPriceAdjustment(0.0); - decongestionSettings.setDecongestionApproach(DecongestionApproach.PID); - config.addModule(decongestionSettings); - - final Scenario scenario = ScenarioUtils.loadScenario(config); - Controler controler = new Controler(scenario); - - DecongestionInfo info = new DecongestionInfo(); - - // decongestion pricing - controler.addOverridingModule(new AbstractModule() { - @Override - public void install() { - - this.bind(DecongestionInfo.class).toInstance(info); - - this.bind(DecongestionTollSetting.class).to(DecongestionTollingPID.class); - this.bind(IntervalBasedTolling.class).to(IntervalBasedTollingAll.class); - - this.bind(IntervalBasedTollingAll.class).asEagerSingleton(); - this.bind(DelayAnalysis.class).asEagerSingleton(); - this.bind(PersonVehicleTracker.class).asEagerSingleton(); - - this.addEventHandlerBinding().to(IntervalBasedTollingAll.class); - this.addEventHandlerBinding().to(DelayAnalysis.class); - this.addEventHandlerBinding().to(PersonVehicleTracker.class); - - this.addControlerListenerBinding().to(DecongestionControlerListener.class); - } - }); - - 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) ; - Assert.assertEquals("Wrong average executed score. The run output seems to have changed.", -11749.431349675931, avgScore, MatsimTestUtils.EPSILON); - - System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().toString()); - Assert.assertEquals("Wrong toll in time bin 61.", 12.600000000000009, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().get(61), MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong toll in time bin 73.", 16.665000000000006, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().get(73), MatsimTestUtils.EPSILON); - } - - /** - * Tests the BangBang controller - * - */ - @Test - public final void test2() { - - System.out.println(testUtils.getPackageInputDirectory()); - - final String configFile = testUtils.getPackageInputDirectory() + "/config.xml"; - Config config = ConfigUtils.loadConfig(configFile); - - String outputDirectory = testUtils.getOutputDirectory() + "/"; - config.controller().setOutputDirectory(outputDirectory); - - final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); - decongestionSettings.setWriteOutputIteration(1); - decongestionSettings.setFractionOfIterationsToEndPriceAdjustment(1.0); - decongestionSettings.setFractionOfIterationsToStartPriceAdjustment(0.0); - config.addModule(decongestionSettings); - - DecongestionInfo info = new DecongestionInfo(); - - final Scenario scenario = ScenarioUtils.loadScenario(config); - Controler controler = new Controler(scenario); - - // decongestion pricing - controler.addOverridingModule(new AbstractModule() { - @Override - public void install() { - - this.bind(DecongestionInfo.class).toInstance(info); - - this.bind(DecongestionTollSetting.class).to(DecongestionTollingBangBang.class); - this.bind(IntervalBasedTolling.class).to(IntervalBasedTollingAll.class); - - this.bind(IntervalBasedTollingAll.class).asEagerSingleton(); - this.bind(DelayAnalysis.class).asEagerSingleton(); - this.bind(PersonVehicleTracker.class).asEagerSingleton(); - - this.addEventHandlerBinding().to(IntervalBasedTollingAll.class); - this.addEventHandlerBinding().to(DelayAnalysis.class); - this.addEventHandlerBinding().to(PersonVehicleTracker.class); - - this.addControlerListenerBinding().to(DecongestionControlerListener.class); - - } - }); - - 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 ) ; - Assert.assertEquals("Wrong average executed score. The run output seems to have changed.", -54.97929444444, avgScore, MatsimTestUtils.EPSILON); - - System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().toString()); - Assert.assertEquals("Wrong toll in time bin 61.", 13., info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().get(61), MatsimTestUtils.EPSILON); - Assert.assertEquals("Wrong toll in time bin 73.", 13., info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().get(73), MatsimTestUtils.EPSILON); - } - -} +/* *********************************************************************** * + * project: org.matsim.* + * * + * *********************************************************************** * + * * + * copyright : (C) 2013 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +/** + * + */ +package org.matsim.contrib.decongestion; + +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.matsim.analysis.ScoreStatsControlerListener.ScoreItem; +import org.matsim.api.core.v01.Id; +import org.matsim.api.core.v01.Scenario; +import org.matsim.contrib.decongestion.DecongestionConfigGroup.DecongestionApproach; +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; +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.controler.OutputDirectoryHierarchy; +import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.testcases.MatsimTestUtils; + +/** + * + * + * @author ikaddoura + * + */ +public class DecongestionPricingTestIT { + + @Rule + public MatsimTestUtils testUtils = new MatsimTestUtils(); + + /** + * Kp = 0.0123 + * + */ + @Test + public final void test0a() { + + System.out.println(testUtils.getPackageInputDirectory()); + + final String configFile = testUtils.getPackageInputDirectory() + "/config0.xml"; + + Config config = ConfigUtils.loadConfig(configFile); + + String outputDirectory = testUtils.getOutputDirectory() + "/"; + config.controller().setOutputDirectory(outputDirectory); + + final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); + decongestionSettings.setWriteOutputIteration(1); + decongestionSettings.setKp(0.0123); + decongestionSettings.setKd(0.0); + decongestionSettings.setKi(0.0); + decongestionSettings.setMsa(false); + 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); + + DecongestionInfo info = new DecongestionInfo(); + + // congestion toll computation + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + + this.bind(DecongestionInfo.class).toInstance(info); + + this.bind(DecongestionTollSetting.class).to(DecongestionTollingPID.class); + this.bind(IntervalBasedTolling.class).to(IntervalBasedTollingAll.class); + + this.bind(IntervalBasedTollingAll.class).asEagerSingleton(); + this.bind(DelayAnalysis.class).asEagerSingleton(); + this.bind(PersonVehicleTracker.class).asEagerSingleton(); + + this.addEventHandlerBinding().to(IntervalBasedTollingAll.class); + this.addEventHandlerBinding().to(DelayAnalysis.class); + this.addEventHandlerBinding().to(PersonVehicleTracker.class); + + this.addControlerListenerBinding().to(DecongestionControlerListener.class); + + } + }); + + // toll-adjusted routing + + final TollTimeDistanceTravelDisutilityFactory travelDisutilityFactory = new TollTimeDistanceTravelDisutilityFactory(); + + controler.addOverridingModule(new AbstractModule(){ + @Override + public void install() { + this.bindCarTravelDisutilityFactory().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); + + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt0, MatsimTestUtils.EPSILON); + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 150.5, tt1, MatsimTestUtils.EPSILON); + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt2, MatsimTestUtils.EPSILON); + + final int index = config.controller().getLastIteration() - config.controller().getFirstIteration(); + double avgScore = controler.getScoreStats().getScoreHistory().get( ScoreItem.executed ).get(index); + Assert.assertEquals("Wrong average executed score. The tolls seem to have changed.", -33.940316666666666, avgScore, MatsimTestUtils.EPSILON); + + System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().toString()); + System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2avgDelay().toString()); + + Assert.assertEquals("Wrong average delay (capacity is set in a way that one of the two agents has to wait 101 sec. Thus the average is 50.5", 50.5, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2avgDelay().get(84), MatsimTestUtils.EPSILON); + Assert.assertEquals("Wrong toll.", 50.5 * 0.0123, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().get(84), MatsimTestUtils.EPSILON); + + } + + /** + * Kp = 0.0123, other syntax + * + */ + @Test + public final void test0amodified() { + + System.out.println(testUtils.getPackageInputDirectory()); + + final String configFile = testUtils.getPackageInputDirectory() + "/config0.xml"; + + Config config = ConfigUtils.loadConfig(configFile); + + String outputDirectory = testUtils.getOutputDirectory() + "/"; + config.controller().setOutputDirectory(outputDirectory); + + final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); + decongestionSettings.setWriteOutputIteration(1); + decongestionSettings.setKp(0.0123); + decongestionSettings.setKd(0.0); + decongestionSettings.setKi(0.0); + decongestionSettings.setMsa(false); + 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)); + + // toll-adjusted routing + + final TollTimeDistanceTravelDisutilityFactory travelDisutilityFactory = new TollTimeDistanceTravelDisutilityFactory(); + + controler.addOverridingModule(new AbstractModule(){ + @Override + public void install() { + this.bindCarTravelDisutilityFactory().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); + + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt0, MatsimTestUtils.EPSILON); + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 150.5, tt1, MatsimTestUtils.EPSILON); + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt2, MatsimTestUtils.EPSILON); + + final int index = config.controller().getLastIteration() - config.controller().getFirstIteration(); + double avgScore = controler.getScoreStats().getScoreHistory().get( ScoreItem.executed ).get(index); + Assert.assertEquals("Wrong average executed score. The tolls seem to have changed.", -33.940316666666666, avgScore, MatsimTestUtils.EPSILON); + } + + /** + * Kp = 2 + * + */ + @Test + public final void test0b() { + + System.out.println(testUtils.getPackageInputDirectory()); + + final String configFile = testUtils.getPackageInputDirectory() + "/config0.xml"; + + Config config = ConfigUtils.loadConfig(configFile); + + String outputDirectory = testUtils.getOutputDirectory() + "/"; + config.controller().setOutputDirectory(outputDirectory); + + final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); + decongestionSettings.setWriteOutputIteration(1); + decongestionSettings.setKp(2.0); + decongestionSettings.setKd(0.0); + decongestionSettings.setKi(0.0); + decongestionSettings.setMsa(false); + 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); + + DecongestionInfo info = new DecongestionInfo(); + + // congestion toll computation + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + + this.bind(DecongestionInfo.class).toInstance(info); + + this.bind(DecongestionTollSetting.class).to(DecongestionTollingPID.class); + this.bind(IntervalBasedTolling.class).to(IntervalBasedTollingAll.class); + + this.bind(IntervalBasedTollingAll.class).asEagerSingleton(); + this.bind(DelayAnalysis.class).asEagerSingleton(); + this.bind(PersonVehicleTracker.class).asEagerSingleton(); + + this.addEventHandlerBinding().to(IntervalBasedTollingAll.class); + this.addEventHandlerBinding().to(DelayAnalysis.class); + this.addEventHandlerBinding().to(PersonVehicleTracker.class); + + this.addControlerListenerBinding().to(DecongestionControlerListener.class); + + } + }); + + // toll-adjusted routing + + final TollTimeDistanceTravelDisutilityFactory travelDisutilityFactory = new TollTimeDistanceTravelDisutilityFactory(); + + controler.addOverridingModule(new AbstractModule(){ + @Override + public void install() { + this.bindCarTravelDisutilityFactory().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); + + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt0, MatsimTestUtils.EPSILON); + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 150.5, tt1, MatsimTestUtils.EPSILON); + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt2, MatsimTestUtils.EPSILON); + + final int index = config.controller().getLastIteration() - config.controller().getFirstIteration(); + double avgScore = controler.getScoreStats().getScoreHistory().get( ScoreItem.executed ).get(index); + Assert.assertEquals("Wrong average executed score. The tolls seem to have changed.", -134.31916666666666, avgScore, MatsimTestUtils.EPSILON); + + System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().toString()); + System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2avgDelay().toString()); + + Assert.assertEquals("Wrong average delay (capacity is set in a way that one of the two agents has to wait 101 sec. Thus the average is 50.5", 50.5, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2avgDelay().get(84), MatsimTestUtils.EPSILON); + Assert.assertEquals("Wrong toll.", 50.5 * 2, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().get(84), MatsimTestUtils.EPSILON); + } + + /** + * Kp = 2 + * + */ + @Test + public final void test0bmodified() { + + System.out.println(testUtils.getPackageInputDirectory()); + + final String configFile = testUtils.getPackageInputDirectory() + "/config0.xml"; + + Config config = ConfigUtils.loadConfig(configFile); + + String outputDirectory = testUtils.getOutputDirectory() + "/"; + config.controller().setOutputDirectory(outputDirectory); + + final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); + decongestionSettings.setWriteOutputIteration(1); + decongestionSettings.setKp(2.0); + decongestionSettings.setKd(0.0); + decongestionSettings.setKi(0.0); + decongestionSettings.setMsa(false); + 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)); + + // toll-adjusted routing + + final TollTimeDistanceTravelDisutilityFactory travelDisutilityFactory = new TollTimeDistanceTravelDisutilityFactory(); + + controler.addOverridingModule(new AbstractModule(){ + @Override + public void install() { + this.bindCarTravelDisutilityFactory().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); + + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt0, MatsimTestUtils.EPSILON); + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 150.5, tt1, MatsimTestUtils.EPSILON); + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt2, MatsimTestUtils.EPSILON); + + final int index = config.controller().getLastIteration() - config.controller().getFirstIteration(); + double avgScore = controler.getScoreStats().getScoreHistory().get( ScoreItem.executed ).get(index); + Assert.assertEquals("Wrong average executed score. The tolls seem to have changed.", -134.31916666666666, avgScore, MatsimTestUtils.EPSILON); + } + + /** + * Kp = 0 / no tolling + * + */ + @Test + public final void test0c() { + + System.out.println(testUtils.getPackageInputDirectory()); + + final String configFile = testUtils.getPackageInputDirectory() + "/config0.xml"; + + Config config = ConfigUtils.loadConfig(configFile); + + String outputDirectory = testUtils.getOutputDirectory() + "/"; + config.controller().setOutputDirectory(outputDirectory); + + final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); + decongestionSettings.setWriteOutputIteration(1); + decongestionSettings.setKp(0.0); + decongestionSettings.setKd(0.0); + decongestionSettings.setKi(0.0); + decongestionSettings.setMsa(false); + 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); + + DecongestionInfo info = new DecongestionInfo(); + + // congestion toll computation + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + + this.bind(DecongestionInfo.class).toInstance(info); + + this.bind(DelayAnalysis.class).asEagerSingleton(); + this.addEventHandlerBinding().to(DelayAnalysis.class); + + this.addControlerListenerBinding().to(DecongestionControlerListener.class); + + } + }); + + // toll-adjusted routing + + final TollTimeDistanceTravelDisutilityFactory travelDisutilityFactory = new TollTimeDistanceTravelDisutilityFactory(); + + controler.addOverridingModule(new AbstractModule(){ + @Override + public void install() { + this.bindCarTravelDisutilityFactory().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); + + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt0, MatsimTestUtils.EPSILON); + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 150.5, tt1, MatsimTestUtils.EPSILON); + Assert.assertEquals("Wrong travel time. The run output seems to have changed.", 100.0, tt2, MatsimTestUtils.EPSILON); + + final int index = config.controller().getLastIteration() - config.controller().getFirstIteration(); + double avgScore = controler.getScoreStats().getScoreHistory().get( ScoreItem.executed ).get(index); + Assert.assertEquals("Wrong average executed score. The tolls seem to have changed.", -33.31916666666666, avgScore, MatsimTestUtils.EPSILON); + + System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().toString()); + System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2avgDelay().toString()); + + Assert.assertEquals("Wrong average delay (capacity is set in a way that one of the two agents has to wait 101 sec. Thus the average is 50.5", 50.5, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2avgDelay().get(84), MatsimTestUtils.EPSILON); + Assert.assertNull("Wrong toll.", info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().get(84)); + + } + + /** + * Tests the PID controller + * + */ + @Test + public final void test1() { + + System.out.println(testUtils.getPackageInputDirectory()); + + final String configFile = testUtils.getPackageInputDirectory() + "/config.xml"; + Config config = ConfigUtils.loadConfig(configFile); + + String outputDirectory = testUtils.getOutputDirectory() + "/"; + config.controller().setOutputDirectory(outputDirectory); + + final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); + decongestionSettings.setWriteOutputIteration(1); + decongestionSettings.setFractionOfIterationsToEndPriceAdjustment(1.0); + decongestionSettings.setFractionOfIterationsToStartPriceAdjustment(0.0); + decongestionSettings.setDecongestionApproach(DecongestionApproach.PID); + config.addModule(decongestionSettings); + + final Scenario scenario = ScenarioUtils.loadScenario(config); + Controler controler = new Controler(scenario); + + DecongestionInfo info = new DecongestionInfo(); + + // decongestion pricing + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + + this.bind(DecongestionInfo.class).toInstance(info); + + this.bind(DecongestionTollSetting.class).to(DecongestionTollingPID.class); + this.bind(IntervalBasedTolling.class).to(IntervalBasedTollingAll.class); + + this.bind(IntervalBasedTollingAll.class).asEagerSingleton(); + this.bind(DelayAnalysis.class).asEagerSingleton(); + this.bind(PersonVehicleTracker.class).asEagerSingleton(); + + this.addEventHandlerBinding().to(IntervalBasedTollingAll.class); + this.addEventHandlerBinding().to(DelayAnalysis.class); + this.addEventHandlerBinding().to(PersonVehicleTracker.class); + + this.addControlerListenerBinding().to(DecongestionControlerListener.class); + } + }); + + 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) ; + Assert.assertEquals("Wrong average executed score. The run output seems to have changed.", -12036.177448472225, avgScore, MatsimTestUtils.EPSILON); + + System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().toString()); + Assert.assertEquals("Wrong toll in time bin 61.", 9.197000000000003, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().get(61), MatsimTestUtils.EPSILON); + Assert.assertEquals("Wrong toll in time bin 73.", 12.963999999999984, info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().get(73), MatsimTestUtils.EPSILON); + } + + /** + * Tests the BangBang controller + * + */ + @Test + public final void test2() { + + System.out.println(testUtils.getPackageInputDirectory()); + + final String configFile = testUtils.getPackageInputDirectory() + "/config.xml"; + Config config = ConfigUtils.loadConfig(configFile); + + String outputDirectory = testUtils.getOutputDirectory() + "/"; + config.controller().setOutputDirectory(outputDirectory); + + final DecongestionConfigGroup decongestionSettings = new DecongestionConfigGroup(); + decongestionSettings.setWriteOutputIteration(1); + decongestionSettings.setFractionOfIterationsToEndPriceAdjustment(1.0); + decongestionSettings.setFractionOfIterationsToStartPriceAdjustment(0.0); + config.addModule(decongestionSettings); + + DecongestionInfo info = new DecongestionInfo(); + + final Scenario scenario = ScenarioUtils.loadScenario(config); + Controler controler = new Controler(scenario); + + // decongestion pricing + controler.addOverridingModule(new AbstractModule() { + @Override + public void install() { + + this.bind(DecongestionInfo.class).toInstance(info); + + this.bind(DecongestionTollSetting.class).to(DecongestionTollingBangBang.class); + this.bind(IntervalBasedTolling.class).to(IntervalBasedTollingAll.class); + + this.bind(IntervalBasedTollingAll.class).asEagerSingleton(); + this.bind(DelayAnalysis.class).asEagerSingleton(); + this.bind(PersonVehicleTracker.class).asEagerSingleton(); + + this.addEventHandlerBinding().to(IntervalBasedTollingAll.class); + this.addEventHandlerBinding().to(DelayAnalysis.class); + this.addEventHandlerBinding().to(PersonVehicleTracker.class); + + this.addControlerListenerBinding().to(DecongestionControlerListener.class); + + } + }); + + 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 ) ; + Assert.assertEquals("Wrong average executed score. The run output seems to have changed.", -55.215645833333184, avgScore, MatsimTestUtils.EPSILON); + + System.out.println(info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().toString()); + Assert.assertEquals("Wrong toll in time bin 61.", 13., info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().get(61), MatsimTestUtils.EPSILON); + Assert.assertEquals("Wrong toll in time bin 73.", 13., info.getlinkInfos().get(Id.createLinkId("link12")).getTime2toll().get(73), MatsimTestUtils.EPSILON); + } + +} diff --git a/contribs/discrete_mode_choice/src/test/java/org/matsim/contrib/discrete_mode_choice/examples/TestSiouxFalls.java b/contribs/discrete_mode_choice/src/test/java/org/matsim/contrib/discrete_mode_choice/examples/TestSiouxFalls.java index 567d5fb1fe4..59e3cf6d1a4 100644 --- a/contribs/discrete_mode_choice/src/test/java/org/matsim/contrib/discrete_mode_choice/examples/TestSiouxFalls.java +++ b/contribs/discrete_mode_choice/src/test/java/org/matsim/contrib/discrete_mode_choice/examples/TestSiouxFalls.java @@ -56,14 +56,14 @@ public void install() { controller.run(); - assertEquals(44196, (int) listener.counts.get("pt")); + + System.out.println((int) listener.counts.get("pt")); + System.out.println((int) listener.counts.get("car")); + System.out.println(listener.counts.get("walk")); + + assertEquals(44195, (int) listener.counts.get("pt")); assertEquals(132316, (int) listener.counts.get("car")); - assertEquals(82140, (int) listener.counts.get("walk")); -// assertEquals(42520, (int) listener.counts.get("pt")); -// assertEquals(132100, (int) listener.counts.get("car")); -// assertEquals(79106, (int) listener.counts.get("walk")); - // ...setConstrainedModes(...) (inside configureAsSubtourModeChoiceReplacement(...)) used to ignore its arguments because of a typo. - // This is now corrected, but results are no longer backwards compatible. kai, jan'23 + assertEquals(82139, (int) listener.counts.get("walk")); } diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT/runChessboard/output_events.xml.gz b/contribs/freight/test/input/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT/runChessboard/output_events.xml.gz index cd5ffc78e82..8057a55fbcc 100644 Binary files a/contribs/freight/test/input/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT/runChessboard/output_events.xml.gz and b/contribs/freight/test/input/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT/runChessboard/output_events.xml.gz differ diff --git a/contribs/freight/test/input/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT/runChessboard/output_plans.xml.gz b/contribs/freight/test/input/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT/runChessboard/output_plans.xml.gz index f2c6b3d4e47..3ca1e52a85a 100644 Binary files a/contribs/freight/test/input/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT/runChessboard/output_plans.xml.gz and b/contribs/freight/test/input/org/matsim/freight/carriers/usecases/chessboard/RunChessboardIT/runChessboard/output_plans.xml.gz differ diff --git a/contribs/pseudosimulation/src/test/java/org/matsim/contrib/pseudosimulation/RunPSimTest.java b/contribs/pseudosimulation/src/test/java/org/matsim/contrib/pseudosimulation/RunPSimTest.java index 08c4ca3cba5..2a82fc13096 100644 --- a/contribs/pseudosimulation/src/test/java/org/matsim/contrib/pseudosimulation/RunPSimTest.java +++ b/contribs/pseudosimulation/src/test/java/org/matsim/contrib/pseudosimulation/RunPSimTest.java @@ -1,10 +1,6 @@ package org.matsim.contrib.pseudosimulation; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.Assert; @@ -29,15 +25,18 @@ import org.matsim.core.replanning.strategies.DefaultPlanStrategiesModule; import org.matsim.core.utils.io.IOUtils; import org.matsim.examples.ExamplesUtils; -import org.matsim.pt.config.TransitConfigGroup.TransitRoutingAlgorithmType; import org.matsim.testcases.MatsimTestUtils; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; + @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class RunPSimTest { @Rule public MatsimTestUtils utils = new MatsimTestUtils(); - private Logger logger = LogManager.getLogger(RunPSimTest.class ); + private final Logger logger = LogManager.getLogger(RunPSimTest.class ); private final Config config = ConfigUtils.loadConfig(IOUtils.extendUrl(ExamplesUtils.getTestScenarioURL("pt-tutorial" ),"0.config.xml" ) ); @@ -57,10 +56,7 @@ public void testA() { //identify selector strategies Field[] selectors = DefaultPlanStrategiesModule.DefaultSelector.class.getDeclaredFields(); List selectorNames = new ArrayList<>(); -// for (Field selector : selectors) { -// selectorNames.add(selector.toString()); -// logger.warn( selector.toString() ); -// } + // yyyyyy does not work as designed selectorNames.add( DefaultPlanStrategiesModule.DefaultSelector.ChangeExpBeta ); selectorNames.add( DefaultPlanStrategiesModule.DefaultSelector.BestScore ); @@ -107,7 +103,8 @@ public void install() { Population popActual = PopulationUtils.createPopulation( config ); PopulationUtils.readPopulation( popActual, outDir + "/output_plans.xml.gz" ); new PopulationComparison().compare( popExpected, popActual ) ; - Assert.assertEquals("RunPsim score changed.", 138.88788052033888, psimScore, MatsimTestUtils.EPSILON); + Assert.assertEquals("RunPsim score changed.", 138.86084460860525, psimScore, MatsimTestUtils.EPSILON); + } /** @@ -130,8 +127,9 @@ public void testB() { controler.run(); double qsimScore = execScoreTracker.executedScore; - logger.info("Default controller score was " + qsimScore ); - Assert.assertEquals("Default controller score changed.", 131.85545404187428, qsimScore, MatsimTestUtils.EPSILON); + logger.info("Default controler score was " + qsimScore ); +// Assert.assertEquals("Default controler score changed.", 131.84309487251033d, qsimScore, MatsimTestUtils.EPSILON); + Assert.assertEquals("Default controler score changed.", 131.8303325803256, qsimScore, MatsimTestUtils.EPSILON); } class ExecScoreTracker implements ShutdownListener { diff --git a/contribs/shared_mobility/src/test/java/org/matsim/contrib/shared_mobility/RunIT.java b/contribs/shared_mobility/src/test/java/org/matsim/contrib/shared_mobility/RunIT.java index 975e64b1a88..4afd46b468d 100644 --- a/contribs/shared_mobility/src/test/java/org/matsim/contrib/shared_mobility/RunIT.java +++ b/contribs/shared_mobility/src/test/java/org/matsim/contrib/shared_mobility/RunIT.java @@ -157,18 +157,18 @@ public final void test() throws UncheckedIOException, ConfigurationException, UR OutputData data = countLegs(controller.getControlerIO().getOutputPath() + "/output_events.xml.gz"); - Assert.assertEquals(82689, (long) data.counts.get("car")); - Assert.assertEquals(29890, (long) data.counts.get("walk")); - Assert.assertEquals(30, (long) data.counts.get("bike")); - Assert.assertEquals(19115, (long) data.counts.get("pt")); + Assert.assertEquals(82629, (long) data.counts.get("car")); + Assert.assertEquals(29739, (long) data.counts.get("walk")); + Assert.assertEquals(31, (long) data.counts.get("bike")); + Assert.assertEquals(19029, (long) data.counts.get("pt")); Assert.assertEquals(21, (long) data.pickupCounts.get("wheels")); Assert.assertEquals(2, (long) data.pickupCounts.get("mobility")); - Assert.assertEquals(9, (long) data.pickupCounts.get("velib")); + Assert.assertEquals(10, (long) data.pickupCounts.get("velib")); Assert.assertEquals(21, (long) data.dropoffCounts.get("wheels")); Assert.assertEquals(0, (long) data.dropoffCounts.getOrDefault("mobility", 0L)); - Assert.assertEquals(9, (long) data.dropoffCounts.get("velib")); + Assert.assertEquals(10, (long) data.dropoffCounts.get("velib")); Assert.assertEquals(0, (long) data.failedPickupCounts.getOrDefault("wheels",0L)); Assert.assertEquals(0, (long) data.failedPickupCounts.getOrDefault("mobility",0L)); diff --git a/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystems/10.events.xml.gz b/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystems/10.events.xml.gz index c7ef25fe7c6..3493cb13c84 100644 Binary files a/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystems/10.events.xml.gz and b/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystems/10.events.xml.gz differ diff --git a/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystems/10.plans.xml.gz b/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystems/10.plans.xml.gz index 9b71cf15cb5..2b90066faf5 100644 Binary files a/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystems/10.plans.xml.gz and b/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystems/10.plans.xml.gz differ diff --git a/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystemsWTryEndTimeThenDuration/10.events.xml.gz b/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystemsWTryEndTimeThenDuration/10.events.xml.gz index e2ea8e8111c..3493cb13c84 100644 Binary files a/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystemsWTryEndTimeThenDuration/10.events.xml.gz and b/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystemsWTryEndTimeThenDuration/10.events.xml.gz differ diff --git a/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystemsWTryEndTimeThenDuration/10.plans.xml.gz b/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystemsWTryEndTimeThenDuration/10.plans.xml.gz index d66ff6e80af..d8733aca4db 100644 Binary files a/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystemsWTryEndTimeThenDuration/10.plans.xml.gz and b/contribs/signals/src/test/resources/test/input/org/matsim/contrib/signals/integration/SignalSystemsIT/testSignalSystemsWTryEndTimeThenDuration/10.plans.xml.gz differ diff --git a/matsim/src/main/java/org/matsim/core/config/groups/TimeAllocationMutatorConfigGroup.java b/matsim/src/main/java/org/matsim/core/config/groups/TimeAllocationMutatorConfigGroup.java index f9e7d9b2718..1a4b33e942e 100644 --- a/matsim/src/main/java/org/matsim/core/config/groups/TimeAllocationMutatorConfigGroup.java +++ b/matsim/src/main/java/org/matsim/core/config/groups/TimeAllocationMutatorConfigGroup.java @@ -25,11 +25,13 @@ import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.ReflectiveConfigGroup; +import org.matsim.core.utils.misc.Time; public final class TimeAllocationMutatorConfigGroup extends ReflectiveConfigGroup { public static final String GROUP_NAME = "timeAllocationMutator"; + public TimeAllocationMutatorConfigGroup() { super(GROUP_NAME); } @@ -39,15 +41,49 @@ public Map getComments() { Map comments = super.getComments(); comments.put(MUTATION_RANGE, "Default:1800.0; Defines how many seconds a time mutation can maximally shift a time."); comments.put(MUTATION_AFFECTS_DURATION, "Default:true; Defines whether time mutation changes an activity's duration."); - comments.put(USE_INDIVIDUAL_SETTINGS_FOR_SUBPOPULATIONS, "false; Use individual settings for each subpopulation. " - + "If enabled but no settings are found, regular settings are uses as fallback."); + comments.put(LATEST_ACTIVITY_END_TIME,"Latest Activity End Time. Default = 24:00:00"); + comments.put(MUTATION_RANGE_STEP,"Mutation Range Step, default = 1 second"); + comments.put(MUTATE_AROUND_INITIAL_END_TIME_ONLY,"Mutates times only around the initially defined end times."); return comments; } // --- + private static final String LATEST_ACTIVITY_END_TIME = "latestActivityEndTime"; + private static final String MUTATE_AROUND_INITIAL_END_TIME_ONLY = "mutateAroundInitialEndTimeOnly"; + private static final String MUTATION_RANGE_STEP = "mutationRangeStep"; private static final String MUTATION_RANGE = "mutationRange"; private double mutationRange = 1800.0; + private double latestActivityEndTime = 24*3600.0; + private boolean mutateAroundInitialEndTimeOnly = false; + private double mutationRangeStep = 1.0; + + @StringGetter(MUTATION_RANGE_STEP) + public double getMutationRangeStep() { + return mutationRangeStep; + } + @StringSetter(MUTATION_RANGE_STEP) + public void setMutationRangeStep(double mutationRangeStep) { + this.mutationRangeStep = mutationRangeStep; + } + @StringGetter(LATEST_ACTIVITY_END_TIME) + public double getLatestActivityEndTime() { + return latestActivityEndTime; + } + @StringSetter(LATEST_ACTIVITY_END_TIME) + public void setLatestActivityEndTime(String latestActivityEndTime) { + this.latestActivityEndTime = Time.parseTime(latestActivityEndTime); + } + + @StringGetter(MUTATE_AROUND_INITIAL_END_TIME_ONLY) + public boolean isMutateAroundInitialEndTimeOnly() { + return mutateAroundInitialEndTimeOnly; + } + @StringSetter(MUTATE_AROUND_INITIAL_END_TIME_ONLY) + public void setMutateAroundInitialEndTimeOnly(boolean mutateAroundInitialEndTimeOnly) { + this.mutateAroundInitialEndTimeOnly = mutateAroundInitialEndTimeOnly; + } + @StringGetter(MUTATION_RANGE) public double getMutationRange() { return this.mutationRange; @@ -71,112 +107,4 @@ public void setAffectingDuration(boolean affectingDuration) { } // --- - - private static final String USE_INDIVIDUAL_SETTINGS_FOR_SUBPOPULATIONS = "useIndividualSettingsForSubpopulations"; - private boolean useIndividualSettingsForSubpopulations = false; -// @StringGetter(USE_INDIVIDUAL_SETTINGS_FOR_SUBPOPULATIONS) // I am disabling the xml usage for the time being, see comment below. kai, may'19 - public boolean isUseIndividualSettingsForSubpopulations() { - // yyyy is it really so plausible to have this? If we continue in this direction, we will eventually have the PTV behaviorally homogeneous - // groups. I would find it more natural to have behavior that depends continuously on person type, and then use Java in order to define that - // behaviour. Rather than to overload the config mechanism. kai, may'19 - return this.useIndividualSettingsForSubpopulations; - } -// @StringSetter(USE_INDIVIDUAL_SETTINGS_FOR_SUBPOPULATIONS) // I am disabling the xml usage for the time being, see comments. kai, may'19 - public void setUseIndividualSettingsForSubpopulations(boolean useIndividualSettingsForSubpopulations) { - // yyyy see comment under isUseIndividualSettingsForSubpopulations. kai, may'10 - this.useIndividualSettingsForSubpopulations = useIndividualSettingsForSubpopulations; - } - - // --- - - public TimeAllocationMutatorSubpopulationSettings getTimeAllocationMutatorSubpopulationSettings(String subpopulation) { - - if (subpopulation == null) return null; - - Collection configGroups = this.getParameterSets(TimeAllocationMutatorSubpopulationSettings.SET_NAME); - for (ConfigGroup group : configGroups) { - if (group instanceof TimeAllocationMutatorSubpopulationSettings) { - TimeAllocationMutatorSubpopulationSettings subpopulationSettings = (TimeAllocationMutatorSubpopulationSettings) group; - if (subpopulation.equals(subpopulationSettings.subpopulation)) return subpopulationSettings; - } - } - - return null; - } - - @Override - public ConfigGroup createParameterSet(final String type) { - switch (type) { - case TimeAllocationMutatorSubpopulationSettings.SET_NAME: - return new TimeAllocationMutatorSubpopulationSettings(); - default: - throw new IllegalArgumentException("unknown set type '" + type + "'"); - } - } - - @Override - public void addParameterSet(final ConfigGroup set) { - switch (set.getName()) { - case TimeAllocationMutatorSubpopulationSettings.SET_NAME: - super.addParameterSet(set); - break; - default: - throw new IllegalArgumentException( set.getName() ); - } - } - - public static class TimeAllocationMutatorSubpopulationSettings extends ReflectiveConfigGroup { - - public static final String SET_NAME = "subpopulationSettings"; - private static final String MUTATION_RANGE = "mutationRange"; - private static final String MUTATION_AFFECTS_DURATION = "mutationAffectsDuration"; - private static final String SUBPOPULATION = "subpopulation"; - - private double mutationRange = 1800.0; - private boolean affectingDuration = true; - private String subpopulation = null; - - public TimeAllocationMutatorSubpopulationSettings() { - super(SET_NAME); - } - - @Override - public final Map getComments() { - Map comments = super.getComments(); - comments.put(MUTATION_RANGE, "Default:1800.0; Defines how many seconds a time mutation can maximally shift a time."); - comments.put(MUTATION_AFFECTS_DURATION, "Default:true; Defines whether time mutation changes an activity's duration."); - comments.put(SUBPOPULATION, "Subpopulation to which the values from this parameter set are applied."); - return comments; - } - - @StringGetter(MUTATION_RANGE) - public double getMutationRange() { - return this.mutationRange; - } - - @StringSetter(MUTATION_RANGE) - public void setMutationRange(final double val) { - this.mutationRange = val; - } - - @StringGetter(MUTATION_AFFECTS_DURATION) - public boolean isAffectingDuration() { - return affectingDuration; - } - - @StringSetter(MUTATION_AFFECTS_DURATION) - public void setAffectingDuration(boolean affectingDuration) { - this.affectingDuration = affectingDuration; - } - - @StringSetter(SUBPOPULATION) - public void setSubpopulation(final String subpopulation) { - this.subpopulation = subpopulation; - } - - @StringGetter(SUBPOPULATION) - public String getSubpopulation() { - return this.subpopulation; - } - } } diff --git a/matsim/src/main/java/org/matsim/core/population/algorithms/MutateActivityTimeAllocation.java b/matsim/src/main/java/org/matsim/core/population/algorithms/MutateActivityTimeAllocation.java new file mode 100644 index 00000000000..e658570f8ea --- /dev/null +++ b/matsim/src/main/java/org/matsim/core/population/algorithms/MutateActivityTimeAllocation.java @@ -0,0 +1,122 @@ +/* *********************************************************************** * + * project: org.matsim.* + * PlanMutateTimeAllocation.java + * * + * *********************************************************************** * + * * + * copyright : (C) 2007, 2008 by the members listed in the COPYING, * + * LICENSE and WARRANTY file. * + * email : info at matsim dot org * + * * + * *********************************************************************** * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * See also COPYING, LICENSE and WARRANTY file * + * * + * *********************************************************************** */ + +package org.matsim.core.population.algorithms; + +import java.util.Random; + +import org.matsim.api.core.v01.population.Activity; +import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.Plan; +import org.matsim.api.core.v01.population.PlanElement; +import org.matsim.core.router.TripStructureUtils; +import org.matsim.core.router.TripStructureUtils.StageActivityHandling; + +/** + * Mutates the duration of activities randomly within a specified range. + * + * @author knagel, jbischoff + */ +public final class MutateActivityTimeAllocation implements PlanAlgorithm { + + + public static final String INITIAL_END_TIME_ATTRIBUTE = "initialEndTime"; + private final double mutationRange; + private final Random random; + private final boolean affectingDuration; + private final double latestActivityEndTime; + private final boolean mutateAroundInitialEndTimeOnly; + private final double mutationRangeStep; + + + public MutateActivityTimeAllocation(final double mutationRange, boolean affectingDuration, final Random random, double latestActivityEndTime, boolean mutateAroundInitialEndTimeOnly, double mutationRangeStep) { + this.mutationRange = mutationRange; + this.affectingDuration = affectingDuration; + this.random = random; + this.latestActivityEndTime = latestActivityEndTime; + this.mutateAroundInitialEndTimeOnly = mutateAroundInitialEndTimeOnly; + this.mutationRangeStep = Math.max(1.0,mutationRangeStep); + + } + + @Override + public void run(final Plan plan) { + for ( Activity act : TripStructureUtils.getActivities( plan , StageActivityHandling.ExcludeStageActivities ) ) { + if (act.getEndTime().isDefined()) { + double endTime = act.getEndTime().seconds(); + if (mutateAroundInitialEndTimeOnly){ + Object initialEndtime = act.getAttributes().getAttribute(INITIAL_END_TIME_ATTRIBUTE); + if (initialEndtime!=null) { + endTime = (double) initialEndtime; + } else { + act.getAttributes().putAttribute(INITIAL_END_TIME_ATTRIBUTE,endTime); + } + } + double newEndTime = Math.min(mutateTime(endTime, mutationRange),this.latestActivityEndTime); + act.setEndTime(newEndTime); + act.setStartTimeUndefined(); + } + else if ( affectingDuration ) { + if ( act.getMaximumDuration().isDefined()) { + act.setMaximumDuration(mutateTime(act.getMaximumDuration().seconds(), mutationRange)); + } + } + } + setLegDepartureTimes(plan); + + } + + private void setLegDepartureTimes(Plan plan) { + //setting leg departure times can only be an estimate and might be useful for certain dynamic modes. + //In general, it is best to trigger a reroute after mutating time. + double now = 0; + for (PlanElement planElement : plan.getPlanElements()){ + if (planElement instanceof Activity activity){ + if (activity.getEndTime().isDefined()){ + now = activity.getEndTime().seconds(); + } + else if (activity.getMaximumDuration().isDefined()){ + now = now + activity.getMaximumDuration().seconds(); + } + } else if (planElement instanceof Leg leg){ + if (leg.getDepartureTime().isDefined()) { + leg.setDepartureTime(now); + if (leg.getTravelTime().isDefined()) { + now = now + leg.getTravelTime().seconds(); + } + } + } + } + } + + private double mutateTime(final double time, double mutationRange) { + double t = time; + int mutationRangeBins = (int) Math.ceil( mutationRange/mutationRangeStep); + t = t - mutationRange + (2*this.random.nextInt(mutationRangeBins)*mutationRangeStep) ; + if (t < 0) { + t = 0; + } + // note that this also affects duration + return t; + } + + + +} diff --git a/matsim/src/main/java/org/matsim/core/population/algorithms/PlanMutateTimeAllocation.java b/matsim/src/main/java/org/matsim/core/population/algorithms/PlanMutateTimeAllocation.java deleted file mode 100644 index b078ed95700..00000000000 --- a/matsim/src/main/java/org/matsim/core/population/algorithms/PlanMutateTimeAllocation.java +++ /dev/null @@ -1,142 +0,0 @@ -/* *********************************************************************** * - * project: org.matsim.* - * PlanMutateTimeAllocation.java - * * - * *********************************************************************** * - * * - * copyright : (C) 2007, 2008 by the members listed in the COPYING, * - * LICENSE and WARRANTY file. * - * email : info at matsim dot org * - * * - * *********************************************************************** * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * See also COPYING, LICENSE and WARRANTY file * - * * - * *********************************************************************** */ - -package org.matsim.core.population.algorithms; - -import java.util.List; -import java.util.Random; - -import org.matsim.api.core.v01.population.Activity; -import org.matsim.api.core.v01.population.Leg; -import org.matsim.api.core.v01.population.Plan; -import org.matsim.api.core.v01.population.PlanElement; -import org.matsim.core.utils.misc.OptionalTime; - -/** - * Mutates the duration of activities randomly within a specified range. - * For the first act, the end-time is mutated. For the last act, duration and end-time are set to UNDEFINED. - * For all other acts, the duration is mutated, and the end-time is updated accordingly. - * If an activity has no duration set (UNDEFINED_TIME), a random time between 0 and 24h will be chosen. - * Departure and arrival times of legs are updated according to the activity durations, but the - * leg travel time is not modified (e.g. updated according to new expected departure time). - * - * @author mrieser - */ -public final class PlanMutateTimeAllocation implements PlanAlgorithm { - - private final double mutationRange; - private final Random random; - - public PlanMutateTimeAllocation(final double mutationRange, final Random random) { - this.mutationRange = mutationRange; - this.random = random; - } - - @Override - public void run(final Plan plan) { - mutatePlan(plan); - } - - private void mutatePlan(final Plan plan) { - - List planElements = plan.getPlanElements(); - int max = planElements.size(); - - double now = 0; - - // apply mutation to all activities except the last home activity - for (int i = 0; i < max; i++) { - - PlanElement pe = planElements.get(i); - - if (pe instanceof Activity) { - Activity act = (Activity) pe; - - // handle first activity - if (i == 0) { - // set start to midnight - act.setStartTime(now); - // mutate the end time of the first activity - act.setEndTime(mutateTime(act.getEndTime())); - // calculate resulting duration - act.setMaximumDuration(act.getEndTime().seconds() - act.getStartTime().seconds()); - // move now pointer - now += act.getEndTime().seconds(); - - // handle middle activities - } else if (i < (max - 1)) { - - // assume that there will be no delay between arrival time and activity start time - act.setStartTime(now); - if (act.getMaximumDuration().isDefined()) { - // mutate the durations of all 'middle' activities - act.setMaximumDuration(mutateTime(act.getMaximumDuration())); - now += act.getMaximumDuration().seconds(); - // set end time accordingly - act.setEndTime(now); - } else { - double newEndTime = mutateTime(act.getEndTime()); - if (newEndTime < now) { - newEndTime = now; - } - act.setEndTime(newEndTime); - now = newEndTime; - } - // handle last activity - } else { - - // assume that there will be no delay between arrival time and activity start time - act.setStartTime(now); - // invalidate duration and end time because the plan will be interpreted 24 hour wrap-around - act.setMaximumDurationUndefined(); - act.setEndTimeUndefined(); - - } - - } else if (pe instanceof Leg) { - - Leg leg = (Leg) pe; - - // assume that there will be no delay between end time of previous activity and departure time - leg.setDepartureTime(now); - // let duration untouched. if defined add it to now - if (leg.getTravelTime().isDefined()) { - now += leg.getTravelTime().seconds(); - } - final double arrTime = now; - // set planned arrival time accordingly - leg.setTravelTime( arrTime - leg.getDepartureTime().seconds()); - - } - } - } - - private double mutateTime(final OptionalTime time) { - if (time.isDefined()) { - double t = time.seconds() + (int)((this.random.nextDouble() * 2.0 - 1.0) * this.mutationRange); - if (t < 0) t = 0; - if (t > 24*3600) t = 24*3600; - return t; - } else { - return this.random.nextInt(24*3600); - } - } - -} diff --git a/matsim/src/main/java/org/matsim/core/population/algorithms/PlanMutateTimeAllocationSimplified.java b/matsim/src/main/java/org/matsim/core/population/algorithms/PlanMutateTimeAllocationSimplified.java deleted file mode 100644 index 7e4434a9f94..00000000000 --- a/matsim/src/main/java/org/matsim/core/population/algorithms/PlanMutateTimeAllocationSimplified.java +++ /dev/null @@ -1,96 +0,0 @@ -/* *********************************************************************** * - * project: org.matsim.* - * PlanMutateTimeAllocation.java - * * - * *********************************************************************** * - * * - * copyright : (C) 2007, 2008 by the members listed in the COPYING, * - * LICENSE and WARRANTY file. * - * email : info at matsim dot org * - * * - * *********************************************************************** * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * See also COPYING, LICENSE and WARRANTY file * - * * - * *********************************************************************** */ - -package org.matsim.core.population.algorithms; - -import java.util.Random; - -import org.matsim.api.core.v01.population.Activity; -import org.matsim.api.core.v01.population.Plan; -import org.matsim.core.router.TripStructureUtils; -import org.matsim.core.router.TripStructureUtils.StageActivityHandling; - -/** - * Mutates the duration of activities randomly within a specified range. - *
- * Other than the "full" version, this version just mutates activity end time and activity duration if they are defined, - * without thinking any further. If this produces invalid plans, they will eventually be removed through the selection - * process. kai, jun'12 - * - * @author knagel - */ -public final class PlanMutateTimeAllocationSimplified implements PlanAlgorithm { - - private final StageActivityHandling stageActivityHandling; - private final double mutationRange; - private final Random random; - private final boolean affectingDuration; - - /** - * Initializes an instance mutating all activities in a plan - * @param mutationRange - * @param affectingDuration - * @param random - */ - public PlanMutateTimeAllocationSimplified(final double mutationRange, boolean affectingDuration, final Random random) { - this( StageActivityHandling.StagesAsNormalActivities , mutationRange , affectingDuration, random ); - } - /** - * Initializes an instance mutating all non-stage activities in a plan - * @param mutationRange - * @param affectingDuration - * @param random - */ - public PlanMutateTimeAllocationSimplified(final StageActivityHandling stageActivityHandling, final double mutationRange, boolean affectingDuration, final Random random) { - this.stageActivityHandling = stageActivityHandling; - this.mutationRange = mutationRange; - this.affectingDuration = affectingDuration; - this.random = random; - } - - @Override - public void run(final Plan plan) { - for ( Activity act : TripStructureUtils.getActivities( plan , stageActivityHandling ) ) { - // this is deliberately simplistic. Cleanup up of the time information should be done somewhere else. - if (act.getEndTime().isDefined()) { - act.setEndTime(mutateTime(act.getEndTime().seconds())); - } - if ( affectingDuration ) { - if ( act.getMaximumDuration().isDefined()) { - act.setMaximumDuration(mutateTime(act.getMaximumDuration().seconds())); - } - } - } - // the legs are not doing anything. kai, jun'12 - } - - private double mutateTime(final double time) { - double t = time; - t = t + (int)((this.random.nextDouble() * 2.0 - 1.0) * this.mutationRange); - - if (t < 0) { - t = 0; - } - // note that this also affects duration - - return t; - } - -} diff --git a/matsim/src/main/java/org/matsim/core/population/algorithms/TripPlanMutateTimeAllocation.java b/matsim/src/main/java/org/matsim/core/population/algorithms/TripPlanMutateTimeAllocation.java index b9e5ed82d7d..05940f1c8bd 100644 --- a/matsim/src/main/java/org/matsim/core/population/algorithms/TripPlanMutateTimeAllocation.java +++ b/matsim/src/main/java/org/matsim/core/population/algorithms/TripPlanMutateTimeAllocation.java @@ -69,12 +69,11 @@ public TripPlanMutateTimeAllocation(final double mutationRange, final boolean af this.mutationRange = mutationRange; this.affectingDuration = affectingDuration; this.random = random; -// this.subpopulationAttribute = subpopulationAttribute; this.subpopulationMutationRanges = subpopulationMutationRanges; this.subpopulationAffectingDuration = subpopulationAffectingDuration; this.latestEndTime = latestEndTime; } - + @Override public void run(final Plan plan) { mutatePlan(plan); @@ -89,12 +88,11 @@ private void mutatePlan(final Plan plan) { final String subpopulation = this.getSubpopulation(plan); final boolean affectingDuration = this.isAffectingDuration(subpopulation); final double mutationRange = this.getMutationRange(subpopulation); - + // apply mutation to all activities except the last home activity for (PlanElement pe : plan.getPlanElements()) { - if (pe instanceof Activity) { - Activity act = (Activity)pe; + if (pe instanceof Activity act) { // handle first activity if (isFirst) { @@ -124,7 +122,7 @@ private void mutatePlan(final Plan plan) { } now += act.getMaximumDuration().seconds(); // (may feel a bit disturbing since it was not mutated but it is just using the "old" value which is perfectly ok. kai, jan'14) - + // set end time accordingly act.setEndTime(now); } else { @@ -191,30 +189,28 @@ private double mutateTime(final OptionalTime time, final double mutationRange) { public void setUseActivityDurations(final boolean useActivityDurations) { this.useActivityDurations = useActivityDurations; } - - private final String getSubpopulation(final Plan plan) { -// if (this.subpopulationAttribute == null) return null; + + private String getSubpopulation(final Plan plan) { if (plan.getPerson() == null) return null; -// return (String) PopulationUtils.getPersonAttribute(plan.getPerson(), this.subpopulationAttribute); return PopulationUtils.getSubpopulation( plan.getPerson() ); } - - private final boolean isAffectingDuration(final String subpopulation) { + + private boolean isAffectingDuration(final String subpopulation) { if (subpopulation != null) { Boolean isAffectingDuration = this.subpopulationAffectingDuration.get(subpopulation); if (isAffectingDuration != null) return isAffectingDuration.booleanValue(); } - + // fallback solution: no subpopulation attribute was found return this.affectingDuration; } - - private final double getMutationRange(final String subpopulation) { + + private double getMutationRange(final String subpopulation) { if (subpopulation != null) { Double mutationRange = this.subpopulationMutationRanges.get(subpopulation); if (mutationRange != null) return mutationRange.doubleValue(); } - + // fallback solution: no subpopulation attribute was found return this.mutationRange; } diff --git a/matsim/src/main/java/org/matsim/core/replanning/modules/TripTimeAllocationMutator.java b/matsim/src/main/java/org/matsim/core/replanning/modules/TripTimeAllocationMutator.java deleted file mode 100644 index a30266f7821..00000000000 --- a/matsim/src/main/java/org/matsim/core/replanning/modules/TripTimeAllocationMutator.java +++ /dev/null @@ -1,89 +0,0 @@ -/* *********************************************************************** * - * project: org.matsim.* - * TransitTimeAllocationMutator.java - * * - * *********************************************************************** * - * * - * copyright : (C) 2009 by the members listed in the COPYING, * - * LICENSE and WARRANTY file. * - * email : info at matsim dot org * - * * - * *********************************************************************** * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * See also COPYING, LICENSE and WARRANTY file * - * * - * *********************************************************************** */ - -package org.matsim.core.replanning.modules; - -import com.google.inject.Inject; -import org.matsim.core.config.Config; -import org.matsim.core.config.groups.PlansConfigGroup; -import org.matsim.core.config.groups.PlansConfigGroup.ActivityDurationInterpretation; -import org.matsim.core.gbl.MatsimRandom; -import org.matsim.core.population.algorithms.PlanAlgorithm; -import org.matsim.core.population.algorithms.TripPlanMutateTimeAllocation; -import org.matsim.core.router.TripRouter; - -import jakarta.inject.Provider; - -/** - * Copy/Paste of TimeAllocationMutator, that calls TransitPlanMutateTimeAllocation instead - * of PlanMutateTimeAllocation. - * - * @author mrieser - */ -public class TripTimeAllocationMutator extends AbstractMultithreadedModule { - - private final Provider tripRouterProvider; - - public final static String CONFIG_GROUP = "TimeAllocationMutator"; - public final static String CONFIG_MUTATION_RANGE = "mutationRange"; - - private double mutationRange = 1800.0; - private boolean useActivityDurations = true; - private final boolean affectingDuration; - - /** - * Creates a new TimeAllocationMutator with a mutation range as defined in - * the configuration (module "TimeAllocationMutator", param "mutationRange"). - */ - public TripTimeAllocationMutator(Config config, Provider tripRouterProvider) { - super(config.global()); - this.tripRouterProvider = tripRouterProvider; - this.mutationRange = config.timeAllocationMutator().getMutationRange() ; - this.affectingDuration = config.timeAllocationMutator().isAffectingDuration() ; - PlansConfigGroup.ActivityDurationInterpretation actDurInterpr = ( config.plans().getActivityDurationInterpretation() ) ; - if ( actDurInterpr == PlansConfigGroup.ActivityDurationInterpretation.minOfDurationAndEndTime ) { - useActivityDurations = true ; - } else if ( actDurInterpr == PlansConfigGroup.ActivityDurationInterpretation.endTimeOnly ) { - useActivityDurations = false ; - } else if ( actDurInterpr == PlansConfigGroup.ActivityDurationInterpretation.tryEndTimeThenDuration ) { - throw new UnsupportedOperationException( "need to clarify the correct setting here. Probably not a big deal, but not done yet. kai, aug'10") ; - } else { - throw new IllegalStateException( "beahvior not defined for this configuration setting") ; - } - } - - public TripTimeAllocationMutator(Config config, Provider tripRouterProvider, final double mutationRange, boolean affectingDuration) { - super(config.global()); - this.tripRouterProvider = tripRouterProvider; - this.mutationRange = mutationRange; - this.affectingDuration = affectingDuration; - } - - @Override - public PlanAlgorithm getPlanAlgoInstance() { - TripPlanMutateTimeAllocation pmta = - new TripPlanMutateTimeAllocation( - this.mutationRange, - affectingDuration, MatsimRandom.getLocalInstance()); - pmta.setUseActivityDurations(this.useActivityDurations); - return pmta; - } - -} diff --git a/matsim/src/main/java/org/matsim/core/replanning/strategies/TimeAllocationMutator.java b/matsim/src/main/java/org/matsim/core/replanning/strategies/TimeAllocationMutator.java index 0d7ab5c75c6..c1fbe50e538 100644 --- a/matsim/src/main/java/org/matsim/core/replanning/strategies/TimeAllocationMutator.java +++ b/matsim/src/main/java/org/matsim/core/replanning/strategies/TimeAllocationMutator.java @@ -35,14 +35,11 @@ public class TimeAllocationMutator implements Provider { @Inject private GlobalConfigGroup globalConfigGroup; @Inject private TimeAllocationMutatorConfigGroup timeAllocationMutatorConfigGroup; @Inject private PlansConfigGroup plansConfigGroup; - @Inject private Provider tripRouterProvider; - @Inject private Population population; @Override public PlanStrategy get() { PlanStrategyImpl strategy = new PlanStrategyImpl(new RandomPlanSelector()); - TimeAllocationMutatorModule tam = new TimeAllocationMutatorModule(this.tripRouterProvider, - this.plansConfigGroup, this.timeAllocationMutatorConfigGroup, this.globalConfigGroup, population); + TimeAllocationMutatorModule tam = new TimeAllocationMutatorModule( this.timeAllocationMutatorConfigGroup, this.globalConfigGroup); strategy.addStrategyModule(tam); return strategy; } diff --git a/matsim/src/main/java/org/matsim/core/replanning/strategies/TimeAllocationMutatorModule.java b/matsim/src/main/java/org/matsim/core/replanning/strategies/TimeAllocationMutatorModule.java index 2486e8dbf77..485089a53ee 100644 --- a/matsim/src/main/java/org/matsim/core/replanning/strategies/TimeAllocationMutatorModule.java +++ b/matsim/src/main/java/org/matsim/core/replanning/strategies/TimeAllocationMutatorModule.java @@ -22,121 +22,45 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.matsim.api.core.v01.population.Population; import org.matsim.api.core.v01.replanning.PlanStrategyModule; -import org.matsim.core.config.Config; -import org.matsim.core.config.ConfigGroup; import org.matsim.core.config.groups.GlobalConfigGroup; -import org.matsim.core.config.groups.PlansConfigGroup; import org.matsim.core.config.groups.TimeAllocationMutatorConfigGroup; -import org.matsim.core.config.groups.TimeAllocationMutatorConfigGroup.TimeAllocationMutatorSubpopulationSettings; import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.population.algorithms.PlanAlgorithm; -import org.matsim.core.population.algorithms.PlanMutateTimeAllocationSimplified; -import org.matsim.core.population.algorithms.TripPlanMutateTimeAllocation; +import org.matsim.core.population.algorithms.MutateActivityTimeAllocation; import org.matsim.core.replanning.modules.AbstractMultithreadedModule; -import org.matsim.core.router.TripRouter; -import org.matsim.core.router.TripStructureUtils.StageActivityHandling; - -import jakarta.inject.Provider; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; /** - * Wraps the {@link org.matsim.core.population.algorithms.PlanMutateTimeAllocation}- + * Wraps the {@link org.matsim.core.population.algorithms.TripPlanMutateTimeAllocation}- * PlanAlgorithm into a {@link PlanStrategyModule} so it can be used for plans * replanning. Supports multiple threads. * * @author mrieser - * @see org.matsim.core.population.algorithms.PlanMutateTimeAllocation + * @see org.matsim.core.population.algorithms.TripPlanMutateTimeAllocation */ class TimeAllocationMutatorModule extends AbstractMultithreadedModule{ - private static boolean ACTIVITY_DURATION_WARNING_SHOWN = false; private static final Logger log = LogManager.getLogger( TimeAllocationMutatorModule.class ); - private final double mutationRange; private final boolean affectingDuration; -// private final String subpopulationAttribute; - private final Map subpopulationMutationRanges; - private final Map subpopulationAffectingDuration; - private final PlansConfigGroup.ActivityDurationInterpretation activityDurationInterpretation; - - /** - * Creates a new TimeAllocationMutator with a mutation range as defined in - * the configuration (module "TimeAllocationMutator", param "mutationRange"). - */ - @Deprecated - TimeAllocationMutatorModule( Config config, Provider tripRouterProvider, final double mutationRange, boolean affectingDuration ) { - super(config.global()); - this.affectingDuration = affectingDuration; - this.mutationRange = mutationRange; - this.activityDurationInterpretation = (config.plans().getActivityDurationInterpretation()); -// this.subpopulationAttribute = null; - this.subpopulationMutationRanges = null; - this.subpopulationAffectingDuration = null; - log.warn("deprecated constructor was used - individual time allocation mutator settings for subpopulations is not supported!"); - } + private final TimeAllocationMutatorConfigGroup timeAllocationMutatorConfigGroup; - TimeAllocationMutatorModule( Provider tripRouterProvider, PlansConfigGroup plansConfigGroup, TimeAllocationMutatorConfigGroup timeAllocationMutatorConfigGroup, GlobalConfigGroup globalConfigGroup ) { - this(tripRouterProvider, plansConfigGroup, timeAllocationMutatorConfigGroup, globalConfigGroup, null); - } - TimeAllocationMutatorModule( Provider tripRouterProvider, PlansConfigGroup plansConfigGroup, TimeAllocationMutatorConfigGroup timeAllocationMutatorConfigGroup, GlobalConfigGroup globalConfigGroup, - final Population population ) { + TimeAllocationMutatorModule( TimeAllocationMutatorConfigGroup timeAllocationMutatorConfigGroup, GlobalConfigGroup globalConfigGroup) { super(globalConfigGroup); - this.activityDurationInterpretation = plansConfigGroup.getActivityDurationInterpretation(); this.mutationRange = timeAllocationMutatorConfigGroup.getMutationRange(); this.affectingDuration = timeAllocationMutatorConfigGroup.isAffectingDuration(); + this.timeAllocationMutatorConfigGroup = timeAllocationMutatorConfigGroup; - // in case we have subpopulations and individual settings for them - if ( -// plansConfigGroup.getSubpopulationAttributeName() != null && - timeAllocationMutatorConfigGroup.isUseIndividualSettingsForSubpopulations() && population != null) { -// this.subpopulationAttribute = plansConfigGroup.getSubpopulationAttributeName(); - this.subpopulationMutationRanges = new HashMap<>(); - this.subpopulationAffectingDuration = new HashMap<>(); - - Collection settings = timeAllocationMutatorConfigGroup.getParameterSets(TimeAllocationMutatorSubpopulationSettings.SET_NAME); - for (ConfigGroup group : settings) { - TimeAllocationMutatorSubpopulationSettings subpopulationSettings = (TimeAllocationMutatorSubpopulationSettings) group; - String subpopulation = subpopulationSettings.getSubpopulation(); - this.subpopulationMutationRanges.put(subpopulation, subpopulationSettings.getMutationRange()); - this.subpopulationAffectingDuration.put(subpopulation, subpopulationSettings.isAffectingDuration()); - log.info("Found individual time mutator settings for subpopulation: " + subpopulation); - } - } else { -// this.subpopulationAttribute = null; - this.subpopulationMutationRanges = null; - this.subpopulationAffectingDuration = null; - } } @Override public PlanAlgorithm getPlanAlgoInstance() { - PlanAlgorithm pmta; - switch (this.activityDurationInterpretation) { - case minOfDurationAndEndTime: - pmta = new TripPlanMutateTimeAllocation(this.mutationRange, this.affectingDuration, MatsimRandom.getLocalInstance(), - this.subpopulationMutationRanges, this.subpopulationAffectingDuration); - break; - default: - if(this.affectingDuration) { - if (!ACTIVITY_DURATION_WARNING_SHOWN) { - log.warn("Please be aware that durations of activities now can mutate freely and possibly become negative." + - "This might be a problem if you have \n" + - "a) short activities that are only provided with duration and not with endtime AND\n" + - "b) agents with only one or two initial plans.\n" + - "This can have impact on scoring and maybe even on qsim execution. It is recommended to set affectingDuration=false for such set up."); - ACTIVITY_DURATION_WARNING_SHOWN = true; - } - } - pmta = new PlanMutateTimeAllocationSimplified( - // TODO: is StageActivityHandling.ExcludeStageActivities right here? - StageActivityHandling.ExcludeStageActivities, this.mutationRange, this.affectingDuration, MatsimRandom.getLocalInstance()); - } + PlanAlgorithm pmta = new MutateActivityTimeAllocation + (this.mutationRange, this.affectingDuration, MatsimRandom.getLocalInstance(), + timeAllocationMutatorConfigGroup.getLatestActivityEndTime(), timeAllocationMutatorConfigGroup.isMutateAroundInitialEndTimeOnly(), + timeAllocationMutatorConfigGroup.getMutationRangeStep()); return pmta; } } diff --git a/matsim/src/main/java/org/matsim/core/replanning/strategies/TimeAllocationMutatorReRoute.java b/matsim/src/main/java/org/matsim/core/replanning/strategies/TimeAllocationMutatorReRoute.java index 009e9e0199c..f430d0d3004 100644 --- a/matsim/src/main/java/org/matsim/core/replanning/strategies/TimeAllocationMutatorReRoute.java +++ b/matsim/src/main/java/org/matsim/core/replanning/strategies/TimeAllocationMutatorReRoute.java @@ -43,13 +43,12 @@ public class TimeAllocationMutatorReRoute implements Provider { @Inject private TimeAllocationMutatorConfigGroup timeAllocationMutatorConfigGroup; @Inject private PlansConfigGroup plansConfigGroup; @Inject private ActivityFacilities activityFacilities; - @Inject private Population population; @Inject private TimeInterpretation timeInterpretation; @Override public PlanStrategy get() { final PlanStrategyImpl strategy = new PlanStrategyImpl(new RandomPlanSelector()); - strategy.addStrategyModule(new TimeAllocationMutatorModule(this.tripRouterProvider, this.plansConfigGroup, this.timeAllocationMutatorConfigGroup, this.globalConfigGroup, this.population) ); + strategy.addStrategyModule(new TimeAllocationMutatorModule(this.timeAllocationMutatorConfigGroup, this.globalConfigGroup) ); strategy.addStrategyModule(new ReRoute(this.activityFacilities, this.tripRouterProvider, this.globalConfigGroup, this.timeInterpretation)); return strategy; } diff --git a/matsim/src/test/java/org/matsim/core/replanning/strategies/DeterministicMultithreadedReplanningIT.java b/matsim/src/test/java/org/matsim/core/replanning/strategies/DeterministicMultithreadedReplanningIT.java index be3a2df553f..122f9acc428 100644 --- a/matsim/src/test/java/org/matsim/core/replanning/strategies/DeterministicMultithreadedReplanningIT.java +++ b/matsim/src/test/java/org/matsim/core/replanning/strategies/DeterministicMultithreadedReplanningIT.java @@ -78,7 +78,7 @@ public void testTimeAllocationMutator() { config.controller().setOutputDirectory(testUtils.getOutputDirectory() + "/run1/"); TestControler controler = new TestControler(config, strategyManager); PlanStrategyImpl strategy = new PlanStrategyImpl(new RandomPlanSelector()); - strategy.addStrategyModule(new TimeAllocationMutatorModule(TripRouterFactoryBuilderWithDefaults.createDefaultTripRouterFactoryImpl(controler.getScenario() ), config.plans(), config.timeAllocationMutator(), config.global()) ); + strategy.addStrategyModule(new TimeAllocationMutatorModule( config.timeAllocationMutator(), config.global()) ); strategyManager.addStrategy( strategy, null, 1.0 ); controler.run(); } @@ -88,7 +88,7 @@ public void testTimeAllocationMutator() { config.controller().setOutputDirectory(testUtils.getOutputDirectory() + "/run2/"); TestControler controler = new TestControler(config, strategyManager); PlanStrategyImpl strategy = new PlanStrategyImpl(new RandomPlanSelector()); - strategy.addStrategyModule(new TimeAllocationMutatorModule(TripRouterFactoryBuilderWithDefaults.createDefaultTripRouterFactoryImpl(controler.getScenario() ), config.plans(), config.timeAllocationMutator(), config.global()) ); + strategy.addStrategyModule(new TimeAllocationMutatorModule(config.timeAllocationMutator(), config.global()) ); strategyManager.addStrategy( strategy, null, 1.0 ); controler.run(); } @@ -129,7 +129,7 @@ public void testReRouteTimeAllocationMutator() { config.controller().setOutputDirectory(testUtils.getOutputDirectory() + "/run1/"); TestControler controler = new TestControler(config, strategyManager); strategy.addStrategyModule(new ReRoute(controler.getScenario(), TripRouterFactoryBuilderWithDefaults.createDefaultTripRouterFactoryImpl(controler.getScenario()), TimeInterpretation.create(config))); // finish strategy configuration - strategy.addStrategyModule(new TimeAllocationMutatorModule(TripRouterFactoryBuilderWithDefaults.createDefaultTripRouterFactoryImpl(controler.getScenario() ), config.plans(), config.timeAllocationMutator(), config.global()) ); + strategy.addStrategyModule(new TimeAllocationMutatorModule( config.timeAllocationMutator(), config.global()) ); controler.run(); } { @@ -142,7 +142,7 @@ public void testReRouteTimeAllocationMutator() { config.controller().setOutputDirectory(testUtils.getOutputDirectory() + "/run2/"); TestControler controler2 = new TestControler(config, strategyManager2); strategy2.addStrategyModule(new ReRoute(controler2.getScenario(), TripRouterFactoryBuilderWithDefaults.createDefaultTripRouterFactoryImpl(controler2.getScenario()), TimeInterpretation.create(config))); // finish strategy configuration - strategy2.addStrategyModule(new TimeAllocationMutatorModule(TripRouterFactoryBuilderWithDefaults.createDefaultTripRouterFactoryImpl(controler2.getScenario() ), config.plans(), config.timeAllocationMutator(), config.global()) ); + strategy2.addStrategyModule(new TimeAllocationMutatorModule(config.timeAllocationMutator(), config.global()) ); controler2.run(); } @@ -275,7 +275,7 @@ public void testReRoute() { private static class TestControler { Controler controler ; - private StrategyManager manager; + private final StrategyManager manager; public TestControler(final Config config, final StrategyManager manager) { this( ScenarioUtils.loadScenario( config ) , manager ); diff --git a/matsim/src/test/java/org/matsim/core/replanning/strategies/TimeAllocationMutatorModuleTest.java b/matsim/src/test/java/org/matsim/core/replanning/strategies/TimeAllocationMutatorModuleTest.java index 54ff79db0e3..00e5fa6b164 100644 --- a/matsim/src/test/java/org/matsim/core/replanning/strategies/TimeAllocationMutatorModuleTest.java +++ b/matsim/src/test/java/org/matsim/core/replanning/strategies/TimeAllocationMutatorModuleTest.java @@ -22,40 +22,31 @@ import static org.junit.Assert.assertTrue; -import jakarta.inject.Provider; - +import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.matsim.api.core.v01.Coord; 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.Link; import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.network.Node; -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.Config; -import org.matsim.core.config.ConfigUtils; -import org.matsim.core.config.groups.TimeAllocationMutatorConfigGroup.TimeAllocationMutatorSubpopulationSettings; +import org.matsim.api.core.v01.population.*; import org.matsim.core.gbl.MatsimRandom; import org.matsim.core.network.NetworkUtils; import org.matsim.core.population.PersonUtils; import org.matsim.core.population.PopulationUtils; import org.matsim.core.population.algorithms.PlanAlgorithm; -import org.matsim.core.population.algorithms.PlanMutateTimeAllocation; -import org.matsim.core.population.algorithms.PlanMutateTimeAllocationSimplified; -import org.matsim.core.population.algorithms.TripPlanMutateTimeAllocation; -import org.matsim.core.router.TripRouter; -import org.matsim.core.router.TripStructureUtils.StageActivityHandling; -import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.population.algorithms.MutateActivityTimeAllocation; import org.matsim.core.utils.misc.Time; +import org.matsim.pt.PtConstants; import org.matsim.testcases.MatsimTestUtils; +import java.util.Random; + /** * Tests the functionality of {@link TimeAllocationMutatorModule}, mainly that the - * correct mutation range is handed over to the underlying {@link PlanMutateTimeAllocation}. + * correct mutation range is handed over to the underlying {@link MutateActivityTimeAllocation}. * * @author mrieser */ @@ -65,141 +56,11 @@ public class TimeAllocationMutatorModuleTest { public MatsimTestUtils utils = new MatsimTestUtils(); - /** - * Tests that the mutation range given in the constructor is respected. - * - * @author mrieser - */ - @Test public void testMutationRangeParam() { - boolean affectingDuration = true ; - - runMutationRangeTest(new TripPlanMutateTimeAllocation(750, affectingDuration, MatsimRandom.getLocalInstance()), 750); - runMutationRangeTest(new TripPlanMutateTimeAllocation(7200, affectingDuration, MatsimRandom.getLocalInstance()), 7200); - } - @Test public void testSimplifiedMutation() { boolean affectingDuration = true ; - runSimplifiedMutationRangeTest(new PlanMutateTimeAllocationSimplified(StageActivityHandling.ExcludeStageActivities, 750, affectingDuration, MatsimRandom.getLocalInstance()), 750); - runSimplifiedMutationRangeTest(new PlanMutateTimeAllocationSimplified(StageActivityHandling.ExcludeStageActivities, 7200, affectingDuration, MatsimRandom.getLocalInstance()), 7200); - } - - @Test public void testSubpopulations() { - - String cbSubpopulation = "cb"; - String freightSubpopulation = "freight"; - - Config config = ConfigUtils.createConfig(); -// config.plans().setSubpopulationAttributeName("subpopulation"); - config.timeAllocationMutator().setUseIndividualSettingsForSubpopulations(true); - config.timeAllocationMutator().setMutationRange(1800.0); - - TimeAllocationMutatorSubpopulationSettings cbSettings = (TimeAllocationMutatorSubpopulationSettings) config.timeAllocationMutator().createParameterSet(TimeAllocationMutatorSubpopulationSettings.SET_NAME); - cbSettings.setSubpopulation(cbSubpopulation); - cbSettings.setAffectingDuration(false); - cbSettings.setMutationRange(100.0); - config.timeAllocationMutator().addParameterSet(cbSettings); - - TimeAllocationMutatorSubpopulationSettings freightSettings = (TimeAllocationMutatorSubpopulationSettings) config.timeAllocationMutator().createParameterSet(TimeAllocationMutatorSubpopulationSettings.SET_NAME); - freightSettings.setSubpopulation(freightSubpopulation); - freightSettings.setAffectingDuration(true); - freightSettings.setMutationRange(7200.0); - config.timeAllocationMutator().addParameterSet(freightSettings); - - Provider tripRouterProvider = null; - - TimeAllocationMutatorModule mutator = new TimeAllocationMutatorModule(tripRouterProvider, config.plans(), config.timeAllocationMutator(), config.global()); - - Scenario scenario = ScenarioUtils.createScenario(config); - - TimeAllocationMutatorModule cbMutator = new TimeAllocationMutatorModule(tripRouterProvider, config.plans(), config.timeAllocationMutator(), config.global(), scenario.getPopulation()); -// assertEquals(false, cbMutator.affectingDuration); -// assertEquals(100.0, cbMutator.mutationRange); -// -// TimeAllocationMutator freightMutator = new TimeAllocationMutator(tripRouterProvider, config.plans(), config.timeAllocationMutator(), config.global(), scenario.getPopulation()); -// assertEquals(true, freightMutator.affectingDuration); -// assertEquals(7200.0, freightMutator.mutationRange); - } - - /** - * Internal helper method to run the real test, but with different setups. - * Basically, it creates one plan and calls the given TimeAllocationMutator - * several times with this plans, each time measuring how much the activity - * durations have changed and thus ensuring, the differences are within the - * expected range. - * - * @param tripPlanMutateTimeAllocation A preset TimeAllocationMutator to be used for the tests. - * @param expectedMutationRange The expected range for mutation. - */ - private static void runMutationRangeTest( final PlanAlgorithm tripPlanMutateTimeAllocation, final int expectedMutationRange ) { - // setup network - Network network = NetworkUtils.createNetwork(); - network.setCapacityPeriod(Time.parseTime("01:00:00")); - Node node1 = NetworkUtils.createAndAddNode(network, Id.create("1", Node.class), new Coord((double) 0, (double) 0)); - Node node2 = NetworkUtils.createAndAddNode(network, Id.create("2", Node.class), new Coord((double) 100, (double) 0)); - Node node3 = NetworkUtils.createAndAddNode(network, Id.create("3", Node.class), new Coord((double) 200, (double) 0)); - Node node4 = NetworkUtils.createAndAddNode(network, Id.create("4", Node.class), new Coord((double) 300, (double) 0)); - final Node fromNode = node1; - final Node toNode = node2; - Link link1 = NetworkUtils.createAndAddLink(network,Id.create("0", Link.class), fromNode, toNode, (double) 100, (double) 5, (double) 100, (double) 1 ); - final Node fromNode1 = node2; - final Node toNode1 = node3; - NetworkUtils.createAndAddLink(network,Id.create("1", Link.class), fromNode1, toNode1, (double) 100, (double) 5, (double) 100, (double) 1 ); - final Node fromNode2 = node3; - final Node toNode2 = node4; - NetworkUtils.createAndAddLink(network,Id.create("2", Link.class), fromNode2, toNode2, (double) 100, (double) 5, (double) 100, (double) 1 ); - - // setup person - Plan plan; - Activity act1, act2; - try { - /* The chosen times for the activity durations are such that it is likely - * for the random mutation to reach midnight (either at 00:00:00 or at 24:00:00). - */ - Person person = PopulationUtils.getFactory().createPerson(Id.create("1", Person.class)); - plan = PersonUtils.createAndAddPlan(person, true); - act1 = PopulationUtils.createAndAddActivityFromLinkId(plan, "h", link1.getId()); - act1.setEndTime(4*3600); - PopulationUtils.createAndAddLeg( plan, TransportMode.car ); - act2 = PopulationUtils.createAndAddActivityFromLinkId(plan, "w", link1.getId()); - act2.setMaximumDuration(14*3600); - PopulationUtils.createAndAddLeg( plan, TransportMode.car ); - PopulationUtils.createAndAddActivityFromLinkId(plan, "h", link1.getId()); - } catch (Exception e) { - throw new RuntimeException(e); - } - - // run test - double act1Dur = act1.getEndTime().seconds(); - double minDiff1 = Double.POSITIVE_INFINITY; - double maxDiff1 = Double.NEGATIVE_INFINITY; - double act2Dur = act2.getMaximumDuration().seconds(); - double minDiff2 = Double.POSITIVE_INFINITY; - double maxDiff2 = Double.NEGATIVE_INFINITY; - for (int i = 0; i < 150; i++) { - tripPlanMutateTimeAllocation.run(plan); - // test duration of act1 - double diff = act1Dur - act1.getMaximumDuration().seconds(); - if (diff > maxDiff1) maxDiff1 = diff; - if (diff < minDiff1) minDiff1 = diff; - act1Dur = act1.getMaximumDuration().seconds(); - assertTrue("activity duration cannot be smaller than 0, is " + act1Dur, act1Dur >= 0.0); - // test duration of act2 - diff = act2Dur - act2.getMaximumDuration().seconds(); - if (diff > maxDiff2) maxDiff2 = diff; - if (diff < minDiff2) minDiff2 = diff; - act2Dur = act2.getMaximumDuration().seconds(); - assertTrue("activity duration cannot be smaller than 0, is " + act2Dur, act2Dur >= 0.0); - } - assertTrue("mutation range differences wrong (act1).", minDiff1 <= maxDiff1); - assertTrue("mutation range differences wrong (act2).", minDiff2 <= maxDiff2); - - /* The following asserts are dependent on random numbers. - * But I would still expect that we get up to at least 95% of the limit... */ - assertValueInRange("mutation range out of range (maxDiff1).", maxDiff1, expectedMutationRange*0.95, expectedMutationRange); - assertValueInRange("mutation range out of range (minDiff1).", minDiff1, -expectedMutationRange, -expectedMutationRange*0.95); - assertValueInRange("mutation range out of range (maxDiff2).", maxDiff1, expectedMutationRange*0.95, expectedMutationRange); - assertValueInRange("mutation range out of range (minDiff2).", minDiff2, -expectedMutationRange, -expectedMutationRange*0.95); + runSimplifiedMutationRangeTest(new MutateActivityTimeAllocation( 750, affectingDuration, MatsimRandom.getLocalInstance(),24*3600,false,1), 750); + runSimplifiedMutationRangeTest(new MutateActivityTimeAllocation( 7200, affectingDuration, MatsimRandom.getLocalInstance(),24*3600,false,1), 7200); } /** @@ -216,19 +77,19 @@ private void runSimplifiedMutationRangeTest(final PlanAlgorithm tripPlanMutateTi // setup network Network network = NetworkUtils.createNetwork(); network.setCapacityPeriod(Time.parseTime("01:00:00")); - Node node1 = NetworkUtils.createAndAddNode(network, Id.create("1", Node.class), new Coord((double) 0, (double) 0)); - Node node2 = NetworkUtils.createAndAddNode(network, Id.create("2", Node.class), new Coord((double) 100, (double) 0)); - Node node3 = NetworkUtils.createAndAddNode(network, Id.create("3", Node.class), new Coord((double) 200, (double) 0)); - Node node4 = NetworkUtils.createAndAddNode(network, Id.create("4", Node.class), new Coord((double) 300, (double) 0)); + Node node1 = NetworkUtils.createAndAddNode(network, Id.create("1", Node.class), new Coord(0, 0)); + Node node2 = NetworkUtils.createAndAddNode(network, Id.create("2", Node.class), new Coord(100, 0)); + Node node3 = NetworkUtils.createAndAddNode(network, Id.create("3", Node.class), new Coord(200, 0)); + Node node4 = NetworkUtils.createAndAddNode(network, Id.create("4", Node.class), new Coord(300, 0)); final Node fromNode = node1; final Node toNode = node2; - Link link1 = NetworkUtils.createAndAddLink(network,Id.create("0", Link.class), fromNode, toNode, (double) 100, (double) 5, (double) 100, (double) 1 ); + Link link1 = NetworkUtils.createAndAddLink(network,Id.create("0", Link.class), fromNode, toNode, 100, 5, 100, 1); final Node fromNode1 = node2; final Node toNode1 = node3; - NetworkUtils.createAndAddLink(network,Id.create("1", Link.class), fromNode1, toNode1, (double) 100, (double) 5, (double) 100, (double) 1 ); + NetworkUtils.createAndAddLink(network,Id.create("1", Link.class), fromNode1, toNode1, 100, 5, 100, 1); final Node fromNode2 = node3; final Node toNode2 = node4; - NetworkUtils.createAndAddLink(network,Id.create("2", Link.class), fromNode2, toNode2, (double) 100, (double) 5, (double) 100, (double) 1 ); + NetworkUtils.createAndAddLink(network,Id.create("2", Link.class), fromNode2, toNode2, 100, 5, 100, 1); // setup person Plan plan; @@ -286,4 +147,134 @@ private void runSimplifiedMutationRangeTest(final PlanAlgorithm tripPlanMutateTi private static void assertValueInRange(final String message, final double actual, final double lowerLimit, final double upperLimit) { assertTrue(message + " actual: " + actual + ", range: " + lowerLimit + "..." + upperLimit, (lowerLimit <= actual) && (actual <= upperLimit)); } + + + @Test + public void testRun() { + // setup population with one person + Person person = PopulationUtils.getFactory().createPerson(Id.create(1, Person.class)); + Plan plan = PersonUtils.createAndAddPlan(person, true); + Activity act = PopulationUtils.createAndAddActivityFromCoord(plan, "home", new Coord(0, 0)); + act.setEndTime(8.0 * 3600); + PopulationUtils.createAndAddLeg( plan, TransportMode.transit_walk ); + Activity ptAct1 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, new Coord(0, 100)); + ptAct1.setMaximumDuration(0); + PopulationUtils.createAndAddLeg( plan, TransportMode.pt ); + Activity ptAct2 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, new Coord(0, 100)); + ptAct2.setMaximumDuration(0); + PopulationUtils.createAndAddLeg( plan, TransportMode.transit_walk ); + act = PopulationUtils.createAndAddActivityFromCoord(plan, "work", new Coord(0, 500)); + act.setEndTime(16*3600); + PopulationUtils.createAndAddLeg( plan, TransportMode.transit_walk ); + Activity ptAct3 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, new Coord(0, 100)); + ptAct3.setMaximumDuration(0); + PopulationUtils.createAndAddLeg( plan, TransportMode.pt ); + Activity ptAct4 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, new Coord(0, 100)); + ptAct4.setMaximumDuration(0); + PopulationUtils.createAndAddLeg( plan, TransportMode.transit_walk ); + PopulationUtils.createAndAddActivityFromCoord(plan, "work", new Coord(0, 500)); + boolean affectingDuration = true ; + + MutateActivityTimeAllocation mutator = + new MutateActivityTimeAllocation( + 3600., + affectingDuration, new Random(2011),24*3600,false,1); + mutator.run(plan); + + Assert.assertEquals(0.0, ptAct1.getMaximumDuration().seconds(), 1e-8); + Assert.assertEquals(0.0, ptAct2.getMaximumDuration().seconds(), 1e-8); + Assert.assertEquals(0.0, ptAct3.getMaximumDuration().seconds(), 1e-8); + Assert.assertEquals(0.0, ptAct4.getMaximumDuration().seconds(), 1e-8); + } + + @Test + public void testRunLatestEndTime() { + // setup population with one person + Person person = PopulationUtils.getFactory().createPerson(Id.create(1, Person.class)); + Plan plan = PersonUtils.createAndAddPlan(person, true); + Activity act = PopulationUtils.createAndAddActivityFromCoord(plan, "home", new Coord(0, 0)); + act.setEndTime(8.0 * 3600); + PopulationUtils.createAndAddLeg(plan, TransportMode.transit_walk); + Activity ptAct1 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, + new Coord(0, 100)); + ptAct1.setMaximumDuration(0); + PopulationUtils.createAndAddLeg(plan, TransportMode.pt); + Activity ptAct2 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, + new Coord(0, 100)); + ptAct2.setMaximumDuration(0); + PopulationUtils.createAndAddLeg(plan, TransportMode.transit_walk); + act = PopulationUtils.createAndAddActivityFromCoord(plan, "work", new Coord(0, 500)); + act.setEndTime(38 * 3600); + PopulationUtils.createAndAddLeg(plan, TransportMode.transit_walk); + Activity ptAct3 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, + new Coord(0, 100)); + ptAct3.setMaximumDuration(0); + PopulationUtils.createAndAddLeg(plan, TransportMode.pt); + Activity ptAct4 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, + new Coord(0, 100)); + ptAct4.setMaximumDuration(0); + PopulationUtils.createAndAddLeg(plan, TransportMode.transit_walk); + PopulationUtils.createAndAddActivityFromCoord(plan, "work", new Coord(0, 500)); + + boolean affectingDuration = true; + final double latestEndTime = 30. * 3600; + + MutateActivityTimeAllocation mutator = + new MutateActivityTimeAllocation( + 3600., + affectingDuration, new Random(2011),latestEndTime,false,1); + + mutator.run(plan); + + Assert.assertEquals(0.0, ptAct1.getMaximumDuration().seconds(), 1e-8); + Assert.assertEquals(0.0, ptAct2.getMaximumDuration().seconds(), 1e-8); + Assert.assertEquals(0.0, ptAct3.getMaximumDuration().seconds(), 1e-8); + Assert.assertEquals(0.0, ptAct4.getMaximumDuration().seconds(), 1e-8); + + // check whether activity times are equal or less than latestEndTime + for (PlanElement pe : plan.getPlanElements()) { + if (pe instanceof Activity activity) { + if (activity.getStartTime().isDefined()) { + Assert.assertTrue(activity.getStartTime().seconds() <= latestEndTime); + } + if (activity.getEndTime().isDefined()) { + Assert.assertTrue(activity.getEndTime().seconds() <= latestEndTime); + } + } + } + } + @Test + public void testLegTimesAreSetCorrectly() { + // setup population with one person + Person person = PopulationUtils.getFactory().createPerson(Id.create(1, Person.class)); + Plan plan = PersonUtils.createAndAddPlan(person, true); + Activity act = PopulationUtils.createAndAddActivityFromCoord(plan, "home", new Coord(0, 0)); + act.setEndTime(8.0 * 3600); + Leg leg1 = PopulationUtils.createAndAddLeg( plan, TransportMode.walk ); + leg1.setDepartureTime(8.0*3600); + leg1.setTravelTime(1800.); + Activity act2 = PopulationUtils.createAndAddActivityFromCoord(plan, "work", new Coord(0, 500)); + act2.setMaximumDuration(8*3600); + Leg leg2 = PopulationUtils.createAndAddLeg( plan, TransportMode.walk ); + leg2.setDepartureTime(16.5*3600); + leg2.setTravelTime(1800.0); + PopulationUtils.createAndAddActivityFromCoord(plan, "work", new Coord(0, 500)); + boolean affectingDuration = true ; + + MutateActivityTimeAllocation mutator = + new MutateActivityTimeAllocation( + 3600., + affectingDuration, new Random(2011),24*3600,false,1); + mutator.run(plan); + + double firstActEndTime = act.getEndTime().seconds(); + double secondActDuration = act2.getMaximumDuration().seconds(); + Assert.assertEquals(firstActEndTime,leg1.getDepartureTime().seconds(), MatsimTestUtils.EPSILON); + Assert.assertEquals(firstActEndTime+secondActDuration+leg1.getTravelTime().seconds(),leg2.getDepartureTime().seconds(), MatsimTestUtils.EPSILON); + + + + } + + } diff --git a/matsim/src/test/java/org/matsim/population/algorithms/TripPlanMutateTimeAllocationTest.java b/matsim/src/test/java/org/matsim/population/algorithms/TripPlanMutateTimeAllocationTest.java deleted file mode 100644 index 4961b6887c0..00000000000 --- a/matsim/src/test/java/org/matsim/population/algorithms/TripPlanMutateTimeAllocationTest.java +++ /dev/null @@ -1,134 +0,0 @@ -/* *********************************************************************** * - * project: org.matsim.* - * * - * *********************************************************************** * - * * - * copyright : (C) 2011 by the members listed in the COPYING, * - * LICENSE and WARRANTY file. * - * email : info at matsim dot org * - * * - * *********************************************************************** * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * See also COPYING, LICENSE and WARRANTY file * - * * - * *********************************************************************** */ - -package org.matsim.population.algorithms; - -import java.util.Random; - -import org.junit.Assert; -import org.junit.Test; -import org.matsim.api.core.v01.Coord; -import org.matsim.api.core.v01.Id; -import org.matsim.api.core.v01.TransportMode; -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.api.core.v01.population.PlanElement; -import org.matsim.core.population.PersonUtils; -import org.matsim.core.population.PopulationUtils; -import org.matsim.core.population.algorithms.TripPlanMutateTimeAllocation; -import org.matsim.pt.PtConstants; - -/** - * @author mrieser - */ -public class TripPlanMutateTimeAllocationTest { - - @Test - public void testRun() { - // setup population with one person - Person person = (Person) PopulationUtils.getFactory().createPerson(Id.create(1, Person.class)); - Plan plan = PersonUtils.createAndAddPlan(person, true); - Activity act = PopulationUtils.createAndAddActivityFromCoord(plan, "home", new Coord((double) 0, (double) 0)); - act.setEndTime(8.0 * 3600); - PopulationUtils.createAndAddLeg( plan, TransportMode.transit_walk ); - Activity ptAct1 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, new Coord((double) 0, (double) 100)); - ptAct1.setMaximumDuration(0); - PopulationUtils.createAndAddLeg( plan, TransportMode.pt ); - Activity ptAct2 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, new Coord((double) 0, (double) 100)); - ptAct2.setMaximumDuration(0); - PopulationUtils.createAndAddLeg( plan, TransportMode.transit_walk ); - act = PopulationUtils.createAndAddActivityFromCoord(plan, "work", new Coord((double) 0, (double) 500)); - act.setEndTime(16*3600); - PopulationUtils.createAndAddLeg( plan, TransportMode.transit_walk ); - Activity ptAct3 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, new Coord((double) 0, (double) 100)); - ptAct3.setMaximumDuration(0); - PopulationUtils.createAndAddLeg( plan, TransportMode.pt ); - Activity ptAct4 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, new Coord((double) 0, (double) 100)); - ptAct4.setMaximumDuration(0); - PopulationUtils.createAndAddLeg( plan, TransportMode.transit_walk ); - PopulationUtils.createAndAddActivityFromCoord(plan, "work", new Coord((double) 0, (double) 500)); - boolean affectingDuration = true ; - - TripPlanMutateTimeAllocation mutator = - new TripPlanMutateTimeAllocation( - 3600., - affectingDuration, new Random(2011)); - mutator.run(plan); - - Assert.assertEquals(0.0, ptAct1.getMaximumDuration().seconds(), 1e-8); - Assert.assertEquals(0.0, ptAct2.getMaximumDuration().seconds(), 1e-8); - Assert.assertEquals(0.0, ptAct3.getMaximumDuration().seconds(), 1e-8); - Assert.assertEquals(0.0, ptAct4.getMaximumDuration().seconds(), 1e-8); - } - - @Test - public void testRunLatestEndTime() { - // setup population with one person - Person person = (Person) PopulationUtils.getFactory().createPerson(Id.create(1, Person.class)); - Plan plan = PersonUtils.createAndAddPlan(person, true); - Activity act = PopulationUtils.createAndAddActivityFromCoord(plan, "home", new Coord((double) 0, (double) 0)); - act.setEndTime(8.0 * 3600); - PopulationUtils.createAndAddLeg(plan, TransportMode.transit_walk); - Activity ptAct1 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, - new Coord((double) 0, (double) 100)); - ptAct1.setMaximumDuration(0); - PopulationUtils.createAndAddLeg(plan, TransportMode.pt); - Activity ptAct2 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, - new Coord((double) 0, (double) 100)); - ptAct2.setMaximumDuration(0); - PopulationUtils.createAndAddLeg(plan, TransportMode.transit_walk); - act = PopulationUtils.createAndAddActivityFromCoord(plan, "work", new Coord((double) 0, (double) 500)); - act.setEndTime(38 * 3600); - PopulationUtils.createAndAddLeg(plan, TransportMode.transit_walk); - Activity ptAct3 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, - new Coord((double) 0, (double) 100)); - ptAct3.setMaximumDuration(0); - PopulationUtils.createAndAddLeg(plan, TransportMode.pt); - Activity ptAct4 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, - new Coord((double) 0, (double) 100)); - ptAct4.setMaximumDuration(0); - PopulationUtils.createAndAddLeg(plan, TransportMode.transit_walk); - PopulationUtils.createAndAddActivityFromCoord(plan, "work", new Coord((double) 0, (double) 500)); - - boolean affectingDuration = true; - final double latestEndTime = 30. * 3600; - - TripPlanMutateTimeAllocation mutator = new TripPlanMutateTimeAllocation(3600., affectingDuration, - new Random(2011), null, null, latestEndTime); - mutator.run(plan); - - Assert.assertEquals(0.0, ptAct1.getMaximumDuration().seconds(), 1e-8); - Assert.assertEquals(0.0, ptAct2.getMaximumDuration().seconds(), 1e-8); - Assert.assertEquals(0.0, ptAct3.getMaximumDuration().seconds(), 1e-8); - Assert.assertEquals(0.0, ptAct4.getMaximumDuration().seconds(), 1e-8); - - // check whether activity times are equal or less than latestEndTime - for (PlanElement pe : plan.getPlanElements()) { - if (pe instanceof Activity activity) { - if (activity.getStartTime().isDefined()) { - Assert.assertTrue(activity.getStartTime().seconds() <= latestEndTime); - } - if (activity.getEndTime().isDefined()) { - Assert.assertTrue(activity.getEndTime().seconds() <= latestEndTime); - } - } - } - } -}