MATSIM
CreateDemand.java
Go to the documentation of this file.
1 package tutorial.programming.demandGenerationWithFacilities;
2 
3 import org.apache.log4j.Logger;
4 import org.matsim.api.core.v01.Coord;
5 import org.matsim.api.core.v01.Id;
12 import org.matsim.core.utils.collections.QuadTree;
15 
16 import java.io.BufferedReader;
17 import java.io.FileReader;
18 import java.io.IOException;
19 import java.util.*;
20 
21 
22 class CreateDemand {
23  private Scenario scenario;
24 
25  // We need another population, the PUS population
26  private Scenario scenarioPUS;
27 
28  private static final String pusTripsFile = "examples/tutorial/programming/demandGenerationWithFacilities/travelsurvey_trips.txt";
29  private static final String pusPersonsFile = "examples/tutorial/programming/demandGenerationWithFacilities/travelsurvey_persons.txt";
30 
31  private ObjectAttributes personHomeAndWorkLocations;
32  private Random random = new Random(3838494);
33 
34  private List<Id> pusWorkers = new Vector<>();
35  private List<Id> pusNonWorkers = new Vector<>();
36 
37  private QuadTree<ActivityFacility> shopFacilitiesTree;
38  private QuadTree<ActivityFacility> leisureFacilitiesTree;
39  private QuadTree<ActivityFacility> educationFacilitiesTree;
40 
41  private final static Logger log = Logger.getLogger(CreateDemand.class);
42 
43 
44  public void run(Scenario scenario, ObjectAttributes personHomeAndWorkLocations) {
45  this.scenario = scenario;
47  this.personHomeAndWorkLocations = personHomeAndWorkLocations;
48  this.init();
49  this.createPUSPersons();
50  this.createPUSPlans();
51  this.assignPUSPlansToMATSimPopulation();
52  }
53 
54  private void init() {
55  /*
56  * Build quad trees for assigning home and work locations
57  */
58  this.shopFacilitiesTree = CreatePopulation.createActivitiesTree("shop", this.scenario);
59  this.leisureFacilitiesTree = CreatePopulation.createActivitiesTree("leisure", this.scenario);
60  this.educationFacilitiesTree = CreatePopulation.createActivitiesTree("education", this.scenario);
61  }
62 
63  private void createPUSPersons() {
64  /*
65  * For convenience and code readability store population and population factory in a local variable
66  */
67  Population population = this.scenarioPUS.getPopulation();
68  PopulationFactory populationFactory = population.getFactory();
69 
70  /*
71  * Read the PUS file
72  */
73  try {
74  BufferedReader bufferedReader = new BufferedReader(new FileReader(pusPersonsFile));
75  bufferedReader.readLine(); //skip header
76 
77  int index_personId = 0;
78 
79  String line;
80  while ((line = bufferedReader.readLine()) != null) {
81  String parts[] = line.split("\t");
82  /*
83  * Create a person and add it to the population
84  */
85  System.out.println(Arrays.asList(parts));
86  System.out.println(parts[index_personId]);
87  Person person = populationFactory.createPerson(Id.create(parts[index_personId].trim(), Person.class));
88  population.addPerson(person);
89 
90  /*
91  * Create a day plan and add it to the person
92  */
93  Plan plan = populationFactory.createPlan();
94  person.addPlan(plan);
95  person.setSelectedPlan(plan);
96  }
97  bufferedReader.close();
98  } // end try
99  catch (IOException e) {
100  e.printStackTrace();
101  }
102  }
103 
104  /*
105  * [[ 4 ]]
106  */
107  private void createPUSPlans() {
108  /*
109  * For convenience and code readability store population and population factory in a local variable
110  */
111  Population population = this.scenarioPUS.getPopulation();
112  PopulationFactory populationFactory = population.getFactory();
113 
114  /*
115  * Read the PUS trips file
116  */
117  try {
118  BufferedReader bufferedReader = new BufferedReader(new FileReader(pusTripsFile));
119  bufferedReader.readLine(); //skip header
120 
121  int index_personId = 0;
122  int index_xCoordOrigin = 2;
123  int index_yCoordOrigin = 3;
124  int index_xCoordDestination = 4;
125  int index_yCoordDestination = 5;
126  int index_activityDuration = 6;
127  int index_mode = 7;
128  int index_activityType = 8;
129 
130  Id<Person> previousPerson = null;
131  boolean worker = false;
132 
133  String line;
134  while ((line = bufferedReader.readLine()) != null) {
135  String parts[] = line.split("\t");
136 
137  Id<Person> personId = Id.create(parts[index_personId], Person.class);
138  Person person = population.getPersons().get(personId);
139 
140  Plan plan = person.getSelectedPlan();
141  /*
142  * If a new person is read add a home activity (first origin activity)
143  * Otherwise add a leg and an activity (destination activity)
144  */
145  if (!personId.equals(previousPerson)) {
146  Coord coordOrigin = new Coord(Double.parseDouble(parts[index_xCoordOrigin]), Double.parseDouble(parts[index_yCoordOrigin]));
147 
148  Activity activity =
149  populationFactory.createActivityFromCoord("home", coordOrigin);
150 
151  plan.addActivity(activity);
152 
153  // define if previous person is a worker or not
154  if (previousPerson != null) {
155  if (worker) {
156  this.pusWorkers.add(previousPerson);
157  }
158  else {
159  this.pusNonWorkers.add(previousPerson);
160  }
161  }
162  worker = false;
163  }
164  else {
165  /*
166  * Add a leg from previous location to this location with the given mode
167  */
168  String mode = parts[index_mode];
169  plan.addLeg(populationFactory.createLeg(mode));
170 
171  /*
172  * Add activity given its type.
173  */
174  Coord coordDestination = new Coord(Double.parseDouble(parts[index_xCoordDestination]), Double.parseDouble(parts[index_yCoordDestination]));
175 
176  String activityType = parts[index_activityType].trim();
177  if (activityType.startsWith("w")) worker = true;
178 
179  Activity activity =
180  populationFactory.createActivityFromCoord(activityType, coordDestination);
181 
182  Double duration = Double.parseDouble(parts[index_activityDuration]);
183  plan.addActivity(activity);
184  }
185  previousPerson = personId;
186  }
187  log.info("Number of workers: " + this.pusWorkers.size());
188  log.info("Number of non-workers: " + this.pusNonWorkers.size());
189  bufferedReader.close();
190  } // end try
191  catch (IOException e) {
192  e.printStackTrace();
193  }
194  PopulationWriter populationWriter = new PopulationWriter(this.scenarioPUS.getPopulation(), this.scenario.getNetwork());
195  populationWriter.write("./output/PUSplans.xml.gz");
196  }
197 
198  /*
199  * [[ 5 ]]
200  */
201  private void assignPUSPlansToMATSimPopulation() {
202  /* Iterate through MATSim population and randomly assign a plan from the PUS population.
203  * Adapt the activity locations and the activity end times.
204  */
205  for (Person person : this.scenario.getPopulation().getPersons().values()) {
206  if ((Boolean) person.getCustomAttributes().get(PersonUtils.EMPLOYED)) {
207  Collections.shuffle(this.pusWorkers, this.random);
208  Person pusPerson = this.scenarioPUS.getPopulation().getPersons().get(this.pusWorkers.get(0));
209  Plan plan = this.adaptAndCopyPlan(person, pusPerson.getSelectedPlan(), true);
210  person.addPlan(plan);
211  }
212  else {
213  Collections.shuffle(this.pusNonWorkers, this.random);
214  Person pusPerson = this.scenarioPUS.getPopulation().getPersons().get(this.pusNonWorkers.get(0));
215  Plan plan = this.adaptAndCopyPlan(person, pusPerson.getSelectedPlan(), false);
216  person.addPlan(plan);
217  }
218  }
219  }
220 
221  private Plan adaptAndCopyPlan(Person person, Plan plan, boolean worker) {
222  Plan newPlan = PopulationUtils.createPlan();
223  PopulationUtils.copyFromTo(plan, newPlan);
224  /*
225  * Go through plan and adapt locations and times
226  */
227  int counter = 0;
228  double time = 0.0;
229  Activity previousActivity = null;
230  String firstType = "";
231  for (PlanElement pe : newPlan.getPlanElements()) {
232  if (pe instanceof Activity) {
233  Activity activity = (Activity)pe;
234  ActivityFacility facility;
235 
236  if (activity.getType().startsWith("h")) {
237  facility = (ActivityFacility)this.personHomeAndWorkLocations.getAttribute(person.getId().toString(), "home");
238  } else if (activity.getType().startsWith("w")) {
239  facility = (ActivityFacility)this.personHomeAndWorkLocations.getAttribute(person.getId().toString(), "work");
240  } else {
241  facility = this.getRandomLocation(activity, previousActivity.getCoord());
242  }
243  if (facility == null) {
244  throw new RuntimeException();
245  }
246 
247  if (counter == 0) {
248  time = 8.0 * 3600.0 + this.randomizeTimes();
249  int suffix = (int)(time / 3600.0);
250  activity.setType("h" + suffix);
251  firstType = activity.getType();
252  activity.setEndTime(time);
253  }
254  else if (counter == newPlan.getPlanElements().size() -1) {
255  activity.setType(firstType);
256  }
257  else {
258  double activityDuration = 8 * 3600;
259 
260  time += activityDuration + this.randomizeTimes();
261  String dur = String.valueOf((int)(activityDuration / 3600.0));
262  if (dur.equals("0")) dur = "0.5";
263  activity.setType(activity.getType().substring(0, 1) + dur);
264  activity.setEndTime(time);
265  }
266  activity.setFacilityId(facility.getId());
267  activity.setLinkId(facility.getLinkId());
268  activity.setCoord(facility.getCoord());
269 
270 
271  previousActivity = activity;
272  }
273  else {
274  Leg leg = (Leg)pe;
275  leg.setDepartureTime(time);
276  }
277  counter++;
278  }
279  return newPlan;
280  }
281 
282  private ActivityFacility getRandomLocation(Activity activity, Coord coordPreviousActivity) {
283  double xCoordCenter = coordPreviousActivity.getX();
284  double yCoordCenter = coordPreviousActivity.getY();
285  ArrayList<ActivityFacility> facilities = new ArrayList<>();
286 
287  if (activity.getType().startsWith("s")) {
288  double radius = 8000.0;
289  while (facilities.size() == 0) {
290  facilities = (ArrayList<ActivityFacility>) this.shopFacilitiesTree.getDisk(xCoordCenter, yCoordCenter, radius);
291  radius *= 2.0;
292  }
293  }
294  else if (activity.getType().startsWith("l")) {
295  double radius = 8000.0;
296  while (facilities.size() == 0) {
297  facilities = (ArrayList<ActivityFacility>) this.leisureFacilitiesTree.getDisk(xCoordCenter, yCoordCenter, radius);
298  radius *= 2.0;
299  }
300  }
301  else {
302  double radius = 8000.0;
303  while (facilities.size() == 0) {
304  facilities = (ArrayList<ActivityFacility>) this.educationFacilitiesTree.getDisk(xCoordCenter, yCoordCenter, radius);
305  radius *= 2.0;
306  }
307  }
308  int randomIndex = (int)(random.nextFloat() * (facilities.size()));
309  return facilities.get(randomIndex);
310  }
311 
312  private double randomizeTimes() {
313  final double sigma = 1.0;
314  return random.nextGaussian() * sigma * 3600.0;
315  }
316 
317  public Scenario getScenario() {
318  return scenario;
319  }
320 
321 
322 }
abstract List< PlanElement > getPlanElements()
static void copyFromTo(final Plan in, Plan out)
abstract void addLeg(final Leg leg)
void setDepartureTime(final double seconds)
Map< Id< Person >,?extends Person > getPersons()
abstract void addActivity(final Activity act)
static Config createConfig(final String filename)
Activity createActivityFromCoord(String actType, Coord coord)
Object getAttribute(final String objectId, final String attribute)
void setFacilityId(final Id< ActivityFacility > id)
static Scenario createScenario(final Config config)
void setEndTime(final double seconds)