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 822763c7683..7e4b9caa3af 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; @@ -56,9 +92,9 @@ public double getMutationRange() { public void setMutationRange(final double val) { this.mutationRange = val; } - + // --- - + private static final String MUTATION_AFFECTS_DURATION = "mutationAffectsDuration"; private boolean affectingDuration = true; @StringGetter(MUTATION_AFFECTS_DURATION) @@ -69,114 +105,6 @@ public boolean isAffectingDuration() { public void setAffectingDuration(boolean affectingDuration) { this.affectingDuration = 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/PlanMutateTimeAllocationSimplified.java b/matsim/src/main/java/org/matsim/core/population/algorithms/PlanMutateTimeAllocationSimplified.java index bc98010b74c..405aba45d2c 100644 --- a/matsim/src/main/java/org/matsim/core/population/algorithms/PlanMutateTimeAllocationSimplified.java +++ b/matsim/src/main/java/org/matsim/core/population/algorithms/PlanMutateTimeAllocationSimplified.java @@ -20,10 +20,14 @@ package org.matsim.core.population.algorithms; +import java.util.Map; 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.population.PopulationUtils; import org.matsim.core.router.TripStructureUtils; import org.matsim.core.router.TripStructureUtils.StageActivityHandling; @@ -38,48 +42,84 @@ */ public final class PlanMutateTimeAllocationSimplified 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; + - /** - * Initializes an instance mutating all non-stage activities in a plan - * @param mutationRange - * @param affectingDuration - * @param random - */ - public PlanMutateTimeAllocationSimplified(final double mutationRange, boolean affectingDuration, final Random random) { + public PlanMutateTimeAllocationSimplified(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 ) ) { - // 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())); + 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); + double shift = endTime -newEndTime; + act.setEndTime(newEndTime); + if (act.getStartTime().isDefined()){ + act.setStartTime(act.getStartTime().seconds()-shift); + } } - if ( affectingDuration ) { + else if ( affectingDuration ) { if ( act.getMaximumDuration().isDefined()) { - act.setMaximumDuration(Math.max(1.0,mutateTime(act.getMaximumDuration().seconds()))); + act.setMaximumDuration(mutateTime(act.getMaximumDuration().seconds(), mutationRange)); } } } - // the legs are not doing anything. kai, jun'12 + setLegDepartureTimes(plan); + } - private double mutateTime(final double time) { - double t = time; - t = t + (int)((this.random.nextDouble() * 2.0 - 1.0) * this.mutationRange); + private void setLegDepartureTimes(Plan plan) { + Activity previousActivity = null; + for (PlanElement planElement : plan.getPlanElements()){ + if (planElement instanceof Activity activity){ + previousActivity = activity; + } else if (planElement instanceof Leg leg){ + if (previousActivity.getEndTime().isDefined()){ + leg.setDepartureTime(previousActivity.getEndTime().seconds()); + } else { + // previous activity has only a duration. + // Estimates about departure time would be very vague, thus they are not set. + leg.setDepartureTimeUndefined(); + } + } + } + } + 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/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 9e56b9117d4..70cae3d1e8e 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 @@ -29,7 +29,6 @@ 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; @@ -54,81 +53,27 @@ */ 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 Map subpopulationMutationRanges; - private final Map subpopulationAffectingDuration; - private final PlansConfigGroup.ActivityDurationInterpretation activityDurationInterpretation; + private final TimeAllocationMutatorConfigGroup timeAllocationMutatorConfigGroup; - /** - * 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.subpopulationMutationRanges = null; - this.subpopulationAffectingDuration = null; - log.warn("deprecated constructor was used - individual time allocation mutator settings for subpopulations is not supported!"); - } - 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 ( - timeAllocationMutatorConfigGroup.isUseIndividualSettingsForSubpopulations() && population != null) { - 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.subpopulationMutationRanges = null; - this.subpopulationAffectingDuration = null; - } } @Override public PlanAlgorithm getPlanAlgoInstance() { - PlanAlgorithm pmta; - if (Objects.requireNonNull(this.activityDurationInterpretation) == PlansConfigGroup.ActivityDurationInterpretation.minOfDurationAndEndTime) { - pmta = new TripPlanMutateTimeAllocation(this.mutationRange, this.affectingDuration, MatsimRandom.getLocalInstance(), - this.subpopulationMutationRanges, this.subpopulationAffectingDuration); - } else { - 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(this.mutationRange, this.affectingDuration, MatsimRandom.getLocalInstance()); - } + PlanAlgorithm pmta = new PlanMutateTimeAllocationSimplified + (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 809249f84d7..ab1c2e72e72 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.controler().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.controler().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.controler().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.controler().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 a93fa7f5506..a447d5b2a90 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 @@ -38,23 +38,20 @@ 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.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.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.utils.misc.Time; import org.matsim.testcases.MatsimTestUtils; /** * Tests the functionality of {@link TimeAllocationMutatorModule}, mainly that the - * correct mutation range is handed over to the underlying {@link TripPlanMutateTimeAllocation}. + * correct mutation range is handed over to the underlying {@link PlanMutateTimeAllocationSimplified}. * * @author mrieser */ @@ -64,141 +61,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( 750, affectingDuration, MatsimRandom.getLocalInstance()), 750); - runSimplifiedMutationRangeTest(new PlanMutateTimeAllocationSimplified( 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(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, 100, 5, 100, 1); - final Node fromNode1 = node2; - final Node toNode1 = node3; - 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, 100, 5, 100, 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 PlanMutateTimeAllocationSimplified( 750, affectingDuration, MatsimRandom.getLocalInstance(),24*3600,false,1), 750); + runSimplifiedMutationRangeTest(new PlanMutateTimeAllocationSimplified( 7200, affectingDuration, MatsimRandom.getLocalInstance(),24*3600,false,1), 7200); } /** diff --git a/matsim/src/test/java/org/matsim/population/algorithms/TripPlanMutateTimeAllocationTest.java b/matsim/src/test/java/org/matsim/population/algorithms/TripPlanMutateTimeAllocationTest.java index 4961b6887c0..9e60c754881 100644 --- a/matsim/src/test/java/org/matsim/population/algorithms/TripPlanMutateTimeAllocationTest.java +++ b/matsim/src/test/java/org/matsim/population/algorithms/TripPlanMutateTimeAllocationTest.java @@ -19,8 +19,6 @@ package org.matsim.population.algorithms; -import java.util.Random; - import org.junit.Assert; import org.junit.Test; import org.matsim.api.core.v01.Coord; @@ -32,9 +30,11 @@ 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.core.population.algorithms.PlanMutateTimeAllocationSimplified; import org.matsim.pt.PtConstants; +import java.util.Random; + /** * @author mrieser */ @@ -43,33 +43,33 @@ public class TripPlanMutateTimeAllocationTest { @Test public void testRun() { // setup population with one person - Person person = (Person) PopulationUtils.getFactory().createPerson(Id.create(1, Person.class)); + 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)); + 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((double) 0, (double) 100)); + 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((double) 0, (double) 100)); + 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((double) 0, (double) 500)); + 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((double) 0, (double) 100)); + 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((double) 0, (double) 100)); + 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((double) 0, (double) 500)); + PopulationUtils.createAndAddActivityFromCoord(plan, "work", new Coord(0, 500)); boolean affectingDuration = true ; - TripPlanMutateTimeAllocation mutator = - new TripPlanMutateTimeAllocation( + PlanMutateTimeAllocationSimplified mutator = + new PlanMutateTimeAllocationSimplified( 3600., - affectingDuration, new Random(2011)); + affectingDuration, new Random(2011),24*3600,false,1); mutator.run(plan); Assert.assertEquals(0.0, ptAct1.getMaximumDuration().seconds(), 1e-8); @@ -81,37 +81,40 @@ public void testRun() { @Test public void testRunLatestEndTime() { // setup population with one person - Person person = (Person) PopulationUtils.getFactory().createPerson(Id.create(1, Person.class)); + 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)); + 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((double) 0, (double) 100)); + new Coord(0, 100)); ptAct1.setMaximumDuration(0); PopulationUtils.createAndAddLeg(plan, TransportMode.pt); Activity ptAct2 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, - new Coord((double) 0, (double) 100)); + new Coord(0, 100)); ptAct2.setMaximumDuration(0); PopulationUtils.createAndAddLeg(plan, TransportMode.transit_walk); - act = PopulationUtils.createAndAddActivityFromCoord(plan, "work", new Coord((double) 0, (double) 500)); + 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((double) 0, (double) 100)); + new Coord(0, 100)); ptAct3.setMaximumDuration(0); PopulationUtils.createAndAddLeg(plan, TransportMode.pt); Activity ptAct4 = PopulationUtils.createAndAddActivityFromCoord(plan, PtConstants.TRANSIT_ACTIVITY_TYPE, - new Coord((double) 0, (double) 100)); + new Coord(0, 100)); ptAct4.setMaximumDuration(0); PopulationUtils.createAndAddLeg(plan, TransportMode.transit_walk); - PopulationUtils.createAndAddActivityFromCoord(plan, "work", new Coord((double) 0, (double) 500)); + PopulationUtils.createAndAddActivityFromCoord(plan, "work", new Coord(0, 500)); boolean affectingDuration = true; final double latestEndTime = 30. * 3600; - TripPlanMutateTimeAllocation mutator = new TripPlanMutateTimeAllocation(3600., affectingDuration, - new Random(2011), null, null, latestEndTime); + PlanMutateTimeAllocationSimplified mutator = + new PlanMutateTimeAllocationSimplified( + 3600., + affectingDuration, new Random(2011),latestEndTime,false,1); + mutator.run(plan); Assert.assertEquals(0.0, ptAct1.getMaximumDuration().seconds(), 1e-8);