1   package tutorial.programming.example08DemandGeneration;
2   
3   import java.util.ArrayList;
4   import java.util.List;
5   import java.util.Map;
6   import java.util.TreeMap;
7   
8   import org.matsim.api.core.v01.Coord;
9   import org.matsim.api.core.v01.Scenario;
10  import org.matsim.api.core.v01.TransportMode;
11  import org.matsim.api.core.v01.population.Activity;
12  import org.matsim.api.core.v01.population.Leg;
13  import org.matsim.api.core.v01.population.Person;
14  import org.matsim.api.core.v01.population.Plan;
15  import org.matsim.api.core.v01.population.Population;
16  import org.matsim.api.core.v01.population.PopulationFactory;
17  import org.matsim.core.config.ConfigUtils;
18  import org.matsim.core.population.PopulationWriter;
19  import org.matsim.core.scenario.ScenarioUtils;
20  
21  public class ZPopulationGenerator {
22  
23  	public static void main(String args[]) {
24  
25  		/*
26  		 * Create population from sample input data.  
27  		 */
28  		Scenario scenario = createPopulationFromCensusFile("./input/input_sample_zurich.txt");
29  
30  		/*
31  		 * Write population to file.
32  		 */
33  		PopulationWriter populationWriter = new PopulationWriter(scenario.getPopulation(), scenario.getNetwork());
34  		populationWriter.write("./input/population.xml");
35  
36  	}
37  
38  	private static Scenario createPopulationFromCensusFile(String censusFile)	{
39  
40  		Scenario scenario = ScenarioUtils.createScenario(ConfigUtils.createConfig());
41  
42  		/*
43  		 * Use Parser to read the census sample file.
44  		 */
45  		List<ZCensusEntry> censusEntries = new ZCensusParser().readFile(censusFile);
46  
47  		/*
48  		 * Get Population and PopulationFactory objects.
49  		 * The Population contains all created Agents and their plans,
50  		 * the PopulationFactory should be used to create Plans,
51  		 * Activities, Legs and so on.
52  		 */
53  		Population population = scenario.getPopulation();
54  		PopulationFactory populationFactory = population.getFactory();
55  
56  
57  		/*
58  		 * The census file contains one line per trip, meaning a typical person
59  		 * is represented by multiple lines / trips. Therefore in a first step
60  		 * we have to sort the trips based on the person who executes them.
61  		 */
62  
63  		/*
64  		 * Create a Map with the PersonIds as key and a list of CensusEntry as values.
65  		 */
66  		Map<Integer, List<ZCensusEntry>> personEntryMapping = new TreeMap<Integer, List<ZCensusEntry>>();
67  		for (ZCensusEntry censusEntry : censusEntries) {
68  			/*
69  			 * If the Map already contains an entry for the current person
70  			 * the list will not be null.
71  			 */
72  			List<ZCensusEntry> entries = personEntryMapping.get(censusEntry.id_person);
73  
74  			/*
75  			 * If no mapping exists -> create a new one
76  			 */
77  			if (entries == null) {
78  				entries = new ArrayList<ZCensusEntry>();
79  				personEntryMapping.put(censusEntry.id_person, entries);
80  			}
81  
82  			/*
83  			 *  Add currently processed entry to the list
84  			 */
85  			entries.add(censusEntry);
86  		}
87  
88  		/*
89  		 * Now create a plan for each person - iterate over all entries in the map.
90  		 */
91  		for (List<ZCensusEntry> personEntries : personEntryMapping.values()) {
92  			/*
93  			 * Get the first entry from the list - it will never be null.
94  			 */
95  			ZCensusEntry entry = personEntries.get(0);
96  
97  			/*
98  			 * Get id of the person from the censusEntry.
99  			 */
100 			int id_person = entry.id_person;
101 
102 			/*
103 			 * Create new person and add it to the population.
104 			 * Use scenario.createId(String id) to create the Person's Id.
105 			 */
106 			Person person = populationFactory.createPerson(scenario.createId(String.valueOf(id_person)));
107 			population.addPerson(person);
108 
109 
110 			/*
111 			 *  Create new plan and add it to the person.
112 			 */
113 			Plan plan = populationFactory.createPlan();
114 			person.addPlan(plan);
115 
116 			/*
117 			 * Every Agent has at least one activity which is being at home.
118 			 * - set the activity type to "home"
119 			 * - set the start time to 0.0
120 			 * - add the Activity to the plan.
121 			 */	
122 			Coord homeCoord =  scenario.createCoord(entry.h_x, entry.h_y);
123 			Activity homeActivity = populationFactory.createActivityFromCoord("home", homeCoord);
124 			homeActivity.setStartTime(0.0);
125 			plan.addActivity(homeActivity);
126 
127 			/*
128 			 * Create objects that are needed when creating the other
129 			 * Activities and Legs of the Plan.
130 			 * 
131 			 * Mind that we have to set a start and end time for each Activity
132 			 * (except the last one - it will last until the end of the simulated
133 			 * period). The end time of an Activity equals the departure time of
134 			 * the next Trip. We set the end time of an Activity when we process
135 			 * the next Trip by using a point to the last previously created
136 			 * Activity (initially this is the Home Activity). 
137 			 */
138 
139 			Coord endCoord = null;
140 			String transportMode = null;
141 			Leg leg = null;
142 			Activity activity = null;
143 			Activity previousActivity = homeActivity;
144 
145 			/*
146 			 *  Create person's Trips and add them to the Plan.
147 			 */
148 			for (ZCensusEntry personEntry : personEntries) {
149 				endCoord = scenario.createCoord(personEntry.d_x, personEntry.d_y);
150 				transportMode = getTransportMode(personEntry.tripmode);
151 				String activityType = getActivityType(personEntry.trippurpose);
152 
153 				/*
154 				 * Create a new Leg using the PopulationFactory and set its parameters.
155 				 * Mind that MATSim uses seconds as time unit whereas the census uses minutes.
156 				 */
157 				leg = populationFactory.createLeg(transportMode);
158 				leg.setDepartureTime(personEntry.starttime * 60);
159 				leg.setTravelTime(personEntry.tripduration * 60);
160 				previousActivity.setEndTime(personEntry.starttime * 60);
161 
162 				/*
163 				 * Create a new Activity using the Population Factory and set its parameters.
164 				 */
165 				activity = populationFactory.createActivityFromCoord(activityType, endCoord);
166 				activity.setStartTime(personEntry.starttime * 60 + personEntry.tripduration * 60);
167 
168 				/*
169 				 * Add the Leg and the Activity to the plan.
170 				 */
171 				plan.addLeg(leg);
172 				plan.addActivity(activity);
173 
174 				/*
175 				 * Do not forget to update the pointer to the previousActivity.
176 				 */
177 				previousActivity = activity;
178 			}
179 
180 			/*
181 			 * ... and finally: If the last Activity takes place at the Home Coordinates
182 			 * we assume that the Agent is performing a "home" Activity.
183 			 */
184 			if (activity.getCoord().equals(homeCoord)) {
185 				activity.setType("home");
186 			}
187 		}
188 		return scenario;
189 
190 	}
191 
192 	/*
193 	 * Helper methods that convert the entries from the census file.
194 	 */
195 
196 	private static String getTransportMode(int mode) {
197 		switch (mode) {
198 		case 1: return TransportMode.walk;
199 		case 2: return TransportMode.bike;
200 		case 3: return TransportMode.car;
201 		case 4: return TransportMode.pt;
202 		case 5: return "undefined";
203 
204 		default: return "undefined";
205 		}
206 	}
207 
208 	private static String getActivityType(int activityType) {
209 		switch (activityType) {
210 		case 1: return "work";
211 		case 2: return "education";
212 		case 3: return "shop";
213 		case 4: return "leisure";
214 		case 5: return "other";
215 
216 		default: return "undefined";
217 		}
218 	}
219 
220 }