Skip to content

Commit

Permalink
remove support for Subpopulation (was never configurable)
Browse files Browse the repository at this point in the history
  • Loading branch information
jfbischoff committed Oct 13, 2023
1 parent 310d8a7 commit 62d1c20
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 364 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -39,15 +41,49 @@ public Map<String, String> getComments() {
Map<String, String> 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;
Expand All @@ -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)
Expand All @@ -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<? extends ConfigGroup> 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<String, String> getComments() {
Map<String,String> 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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,11 @@ public class TimeAllocationMutator implements Provider<PlanStrategy> {
@Inject private GlobalConfigGroup globalConfigGroup;
@Inject private TimeAllocationMutatorConfigGroup timeAllocationMutatorConfigGroup;
@Inject private PlansConfigGroup plansConfigGroup;
@Inject private Provider<org.matsim.core.router.TripRouter> 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;
}
Expand Down
Loading

0 comments on commit 62d1c20

Please sign in to comment.