MATSIM
TripPlanMutateTimeAllocation.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * TransitPlanMutateTimeAllocation.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2009 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 
21 package org.matsim.core.population.algorithms;
22 
23 import java.util.Map;
24 import java.util.Random;
25 
33 
41 public final class TripPlanMutateTimeAllocation implements PlanAlgorithm {
42 
43  public static final double DEFAULT_LATEST_END_TIME = 24. * 3600;
44 
45  private final double mutationRange;
46  private final Random random;
47  private boolean useActivityDurations = true;
48  private final boolean affectingDuration;
49 // private final String subpopulationAttribute;
50  private final Map<String, Double> subpopulationMutationRanges;
51  private final Map<String, Boolean> subpopulationAffectingDuration;
52  private final double latestEndTime;
53 
54  public TripPlanMutateTimeAllocation(final double mutationRange,
55  final boolean affectingDuration, final Random random) {
56  this(mutationRange, affectingDuration, random, null, null );
57  }
58 
59  public TripPlanMutateTimeAllocation(final double mutationRange, final boolean affectingDuration,
60  final Random random, final Map<String, Double> subpopulationMutationRanges,
61  final Map<String, Boolean> subpopulationAffectingDuration) {
64  }
65 
66  public TripPlanMutateTimeAllocation(final double mutationRange, final boolean affectingDuration,
67  final Random random, final Map<String, Double> subpopulationMutationRanges,
68  final Map<String, Boolean> subpopulationAffectingDuration, final double latestEndTime) {
69  this.mutationRange = mutationRange;
70  this.affectingDuration = affectingDuration;
71  this.random = random;
72  this.subpopulationMutationRanges = subpopulationMutationRanges;
73  this.subpopulationAffectingDuration = subpopulationAffectingDuration;
74  this.latestEndTime = latestEndTime;
75  }
76 
77  @Override
78  public void run(final Plan plan) {
79  mutatePlan(plan);
80  }
81 
82  private void mutatePlan(final Plan plan) {
83 
84  double now = 0;
85  boolean isFirst = true;
86  Activity lastAct = (Activity) plan.getPlanElements().listIterator(plan.getPlanElements().size()).previous();
87 
88  final String subpopulation = this.getSubpopulation(plan);
89  final boolean affectingDuration = this.isAffectingDuration(subpopulation);
90  final double mutationRange = this.getMutationRange(subpopulation);
91 
92  // apply mutation to all activities except the last home activity
93  for (PlanElement pe : plan.getPlanElements()) {
94 
95  if (pe instanceof Activity act) {
96 
97  // handle first activity
98  if (isFirst) {
99  isFirst = false;
100  // set start to midnight
101  act.setStartTime(now);
102  // mutate the end time of the first activity
103  act.setEndTime(mutateTime(act.getEndTime(), mutationRange));
104  // calculate resulting duration
105  if (affectingDuration) {
106  act.setMaximumDuration(act.getEndTime().seconds() - act.getStartTime().seconds());
107  }
108  // move now pointer
109  now += act.getEndTime().seconds();
110 
111  // handle middle activities
112  } else if (act != lastAct) {
113 
114  // assume that there will be no delay between arrival time and activity start time
115  act.setStartTime(now);
116  if (!StageActivityTypeIdentifier.isStageActivity(act.getType())) {
117  if (this.useActivityDurations) {
118  if (act.getMaximumDuration().isDefined()) {
119  // mutate the durations of all 'middle' activities
120  if (affectingDuration) {
121  act.setMaximumDuration(mutateTime(act.getMaximumDuration(), mutationRange));
122  }
123  now += act.getMaximumDuration().seconds();
124  // (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)
125 
126  // set end time accordingly
127  act.setEndTime(now);
128  } else {
129  double newEndTime = mutateTime(act.getEndTime(), mutationRange);
130  if (newEndTime < now) {
131  newEndTime = now;
132  }
133  act.setEndTime(newEndTime);
134  now = newEndTime;
135  }
136  }
137  else {
138  if (act.getEndTime().isUndefined()) {
139  throw new IllegalStateException("Can not mutate activity end time because it is not set for Person: " + plan.getPerson().getId());
140  }
141  double newEndTime = mutateTime(act.getEndTime(), mutationRange);
142  if (newEndTime < now) {
143  newEndTime = now;
144  }
145  act.setEndTime(newEndTime);
146  now = newEndTime;
147  }
148  }
149  // handle last activity
150  } else {
151 
152  // assume that there will be no delay between arrival time and activity start time
153  act.setStartTime(now);
154  // invalidate duration and end time because the plan will be interpreted
155  // this.latestEndTime hour wrap-around
156  act.setMaximumDurationUndefined();
157  act.setEndTimeUndefined();
158  }
159 
160  } else {
161  Leg leg = (Leg) pe;
162 
163  // assume that there will be no delay between end time of previous activity and departure time
164  leg.setDepartureTime(now);
165  // let duration untouched. if defined add it to now
166  if (leg.getTravelTime().isDefined()) {
167  now += leg.getTravelTime().seconds();
168  }
169  final double arrTime = now;
170  // set planned arrival time accordingly
171  leg.setTravelTime( arrTime - leg.getDepartureTime().seconds());
172  }
173  }
174  }
175 
176  private double mutateTime(final OptionalTime time, final double mutationRange) {
177  if (time.isDefined()) {
178  double t = time.seconds() + (int)((this.random.nextDouble() * 2.0 - 1.0) * mutationRange);
179  if (t < 0)
180  t = 0;
181  if (t > this.latestEndTime)
182  t = this.latestEndTime;
183  return t;
184  } else {
185  return this.random.nextInt((int) this.latestEndTime);
186  }
187  }
188 
189  public void setUseActivityDurations(final boolean useActivityDurations) {
190  this.useActivityDurations = useActivityDurations;
191  }
192 
193  private String getSubpopulation(final Plan plan) {
194  if (plan.getPerson() == null) return null;
195  return PopulationUtils.getSubpopulation( plan.getPerson() );
196  }
197 
198  private boolean isAffectingDuration(final String subpopulation) {
199  if (subpopulation != null) {
200  Boolean isAffectingDuration = this.subpopulationAffectingDuration.get(subpopulation);
201  if (isAffectingDuration != null) return isAffectingDuration.booleanValue();
202  }
203 
204  // fallback solution: no subpopulation attribute was found
205  return this.affectingDuration;
206  }
207 
208  private double getMutationRange(final String subpopulation) {
209  if (subpopulation != null) {
210  Double mutationRange = this.subpopulationMutationRanges.get(subpopulation);
211  if (mutationRange != null) return mutationRange.doubleValue();
212  }
213 
214  // fallback solution: no subpopulation attribute was found
215  return this.mutationRange;
216  }
217 }
void setDepartureTime(final double seconds)
static final boolean isStageActivity(final String activityType)
static String getSubpopulation(HasPlansAndId<?, ?> person)
TripPlanMutateTimeAllocation(final double mutationRange, final boolean affectingDuration, final Random random, final Map< String, Double > subpopulationMutationRanges, final Map< String, Boolean > subpopulationAffectingDuration)
List< PlanElement > getPlanElements()
void setTravelTime(final double seconds)
double mutateTime(final OptionalTime time, final double mutationRange)
TripPlanMutateTimeAllocation(final double mutationRange, final boolean affectingDuration, final Random random, final Map< String, Double > subpopulationMutationRanges, final Map< String, Boolean > subpopulationAffectingDuration, final double latestEndTime)
TripPlanMutateTimeAllocation(final double mutationRange, final boolean affectingDuration, final Random random)