Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2010-2024 German Aerospace Center (DLR) and others.
4 : // activitygen module
5 : // Copyright 2010 TUM (Technische Universitaet Muenchen, http://www.tum.de/)
6 : // This program and the accompanying materials are made available under the
7 : // terms of the Eclipse Public License 2.0 which is available at
8 : // https://www.eclipse.org/legal/epl-2.0/
9 : // This Source Code may also be made available under the following Secondary
10 : // Licenses when the conditions for such availability set forth in the Eclipse
11 : // Public License 2.0 are satisfied: GNU General Public License, version 2
12 : // or later which is available at
13 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
14 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
15 : /****************************************************************************/
16 : /// @file AGActivities.cpp
17 : /// @author Piotr Woznica
18 : /// @author Daniel Krajzewicz
19 : /// @author Walter Bamberger
20 : /// @author Michael Behrisch
21 : /// @date July 2010
22 : ///
23 : // Main class that manages activities taken in account and generates the
24 : // inhabitants' trip list.
25 : /****************************************************************************/
26 : #include <config.h>
27 :
28 : #include <sstream>
29 : #include <utils/common/RandHelper.h>
30 : #include <activitygen/city/AGTime.h>
31 : #include "AGWorkAndSchool.h"
32 : #include "AGFreeTime.h"
33 : #include "AGActivities.h"
34 :
35 : #define REBUILD_ITERATION_LIMIT 2
36 :
37 :
38 : // ===========================================================================
39 : // method definitions
40 : // ===========================================================================
41 : void
42 0 : AGActivities::addTrip(AGTrip t, std::list<AGTrip>* tripSet) {
43 : tripSet->push_back(t);
44 0 : }
45 :
46 : void
47 4516 : AGActivities::addTrips(std::list<AGTrip> t, std::list<AGTrip>* tripSet) {
48 : std::list<AGTrip>::iterator it;
49 8184 : for (it = t.begin(); it != t.end(); ++it) {
50 : tripSet->push_back(*it);
51 : }
52 4516 : }
53 :
54 : void
55 9 : AGActivities::generateActivityTrips() {
56 : int numbErr;
57 : /**
58 : * trips due to public transportation
59 : */
60 : numbErr = 0;
61 : std::list<AGBusLine>::iterator itBL;
62 20 : for (itBL = myCity->busLines.begin(); itBL != myCity->busLines.end(); ++itBL) {
63 11 : if (! generateBusTraffic(*itBL)) {
64 0 : ++numbErr;
65 : }
66 : }
67 9 : if (numbErr != 0) {
68 0 : std::cerr << "ERROR: " << numbErr << " bus lines couldn't been completely generated ( " << (float)numbErr * 100.0 / (float)myCity->busLines.size() << "% )..." << std::endl;
69 : } else {
70 : std::cout << "no problem during bus line trip generation..." << std::endl;
71 : }
72 :
73 : std::cout << "after public transportation: " << trips.size() << std::endl;
74 : /**
75 : * trips due to activities in the city
76 : * @NOTICE: includes people working in work positions out of the city
77 : */
78 : numbErr = 0;
79 : std::list<AGHousehold>::iterator itHH;
80 1514 : for (itHH = myCity->households.begin(); itHH != myCity->households.end(); ++itHH) {
81 1506 : if (! generateTrips(*itHH)) {
82 0 : ++numbErr;
83 : }
84 : }
85 8 : if (numbErr != 0) {
86 0 : std::cout << "WARNING: " << numbErr << " ( " << (float)numbErr * 100.0 / (float)myCity->households.size() << "% ) households' trips haven't been generated: would probably need more iterations for rebuilding..." << std::endl;
87 : } else {
88 : std::cout << "no problem during households' trips generation..." << std::endl;
89 : }
90 :
91 : std::cout << "after household activities: " << trips.size() << std::endl;
92 : /**
93 : * trips due to incoming and outgoing traffic
94 : * @WARNING: the outgoing traffic is already done: households in which someone works on a work position that is out of the city.
95 : */
96 8 : if (! generateInOutTraffic()) {
97 : std::cerr << "ERROR while generating in/Out traffic..." << std::endl;
98 : } else {
99 : std::cout << "no problem during in/out traffic generation..." << std::endl;
100 : }
101 :
102 : std::cout << "after incoming/outgoing traffic: " << trips.size() << std::endl;
103 : /**
104 : * random traffic trips
105 : * @NOTICE: this includes uniform and proportional random traffic
106 : */
107 8 : if (! generateRandomTraffic()) {
108 : std::cerr << "ERROR while generating random traffic..." << std::endl;
109 : } else {
110 : std::cout << "no problem during random traffic generation..." << std::endl;
111 : }
112 :
113 : std::cout << "after random traffic: " << trips.size() << std::endl;
114 8 : }
115 :
116 : bool
117 1506 : AGActivities::generateTrips(AGHousehold& hh) {
118 : int iteration = 0;
119 : bool generated = false;
120 : std::list<AGTrip> temporaTrips;
121 3011 : while (!generated && iteration < REBUILD_ITERATION_LIMIT) {
122 1506 : if (!temporaTrips.empty()) {
123 : temporaTrips.clear();
124 : }
125 : // Work and school activities
126 1506 : AGWorkAndSchool ws(&hh, &(myCity->statData), &temporaTrips);
127 1506 : generated = ws.generateTrips();
128 1506 : if (!generated) {
129 0 : hh.regenerate();
130 0 : ++iteration;
131 0 : continue;
132 : }
133 1506 : addTrips(ws.getPartialActivityTrips(), &temporaTrips);
134 :
135 : // free time activities
136 1506 : AGFreeTime ft(&hh, &(myCity->statData), &temporaTrips, nbrDays);
137 1506 : generated = ft.generateTrips();
138 1505 : if (!generated) {
139 0 : hh.regenerate();
140 0 : ++iteration;
141 : continue;
142 : }
143 1505 : addTrips(ft.getPartialActivityTrips(), &temporaTrips);
144 : //cout << "after this hh: " << temporaTrips.size() << " we have: " << trips.size() << endl;
145 : //trips of all activities generated:
146 3011 : addTrips(temporaTrips, &trips);
147 1506 : }
148 1505 : return generated;
149 : }
150 :
151 : bool
152 11 : AGActivities::generateBusTraffic(AGBusLine bl) {
153 : std::list<AGBus>::iterator itB;
154 : std::list<AGPosition>::iterator itS;
155 : /**
156 : * Buses in the first direction
157 : */
158 516 : for (itB = bl.buses.begin(); itB != bl.buses.end(); ++itB) {
159 505 : if (bl.stations.size() < 1) {
160 0 : return false;
161 : }
162 1010 : AGTrip t(bl.stations.front(), bl.stations.back(), *itB, itB->getDeparture());
163 4491 : for (itS = bl.stations.begin(); itS != bl.stations.end(); ++itS) {
164 7467 : if (*itS == t.getDep() || *itS == t.getArr()) {
165 1010 : continue;
166 : }
167 2976 : t.addLayOver(*itS);
168 : }
169 505 : trips.push_back(t);
170 505 : }
171 : /**
172 : * Buses in the return direction
173 : */
174 : //verify that buses return back to the beginning
175 11 : if (bl.revStations.empty()) {
176 : return true; //in this case, no return way: everything is ok.
177 : }
178 516 : for (itB = bl.revBuses.begin(); itB != bl.revBuses.end(); ++itB) {
179 505 : if (bl.revStations.size() < 1) {
180 0 : return false;
181 : }
182 1010 : AGTrip t(bl.revStations.front(), bl.revStations.back(), *itB, itB->getDeparture());
183 4491 : for (itS = bl.revStations.begin(); itS != bl.revStations.end(); ++itS) {
184 7467 : if (*itS == t.getDep() || *itS == t.getArr()) {
185 1010 : continue;
186 : }
187 2976 : t.addLayOver(*itS);
188 : }
189 505 : trips.push_back(t);
190 505 : }
191 : return true;
192 : }
193 :
194 : bool
195 8 : AGActivities::generateInOutTraffic() {
196 : /**
197 : * outgoing traffic already done by generateTrips():
198 : * people who work out of the city.
199 : * Here are people from outside the city coming to work.
200 : */
201 8 : if (myCity->peopleIncoming.empty()) {
202 : return true;
203 : }
204 3 : if (myCity->cityGates.empty()) {
205 : return false;
206 : }
207 : int num = 1;
208 : std::list<AGAdult>::iterator itA;
209 :
210 402 : for (itA = myCity->peopleIncoming.begin(); itA != myCity->peopleIncoming.end(); ++itA) {
211 400 : int posi = myCity->statData.getRandomCityGateByIncoming();
212 800 : std::string nom(generateName(num, "carIn"));
213 800 : AGTrip wayTrip(myCity->cityGates[posi], itA->getWorkPosition().getPosition(), nom, itA->getWorkPosition().getOpening());
214 : //now we put the estimated time of entrance in the city.
215 400 : wayTrip.setDepTime(wayTrip.estimateDepTime(wayTrip.getTime(), myCity->statData.speedTimePerKm));
216 800 : AGTrip retTrip(itA->getWorkPosition().getPosition(), myCity->cityGates[posi], nom, itA->getWorkPosition().getClosing());
217 400 : trips.push_back(wayTrip);
218 : trips.push_back(retTrip);
219 400 : ++num;
220 400 : }
221 : return true;
222 : }
223 :
224 : std::string
225 1925 : AGActivities::generateName(int i, std::string prefix) {
226 1925 : std::ostringstream os;
227 1925 : os << i;
228 3850 : return prefix + os.str();
229 1925 : }
230 :
231 : bool
232 8 : AGActivities::generateRandomTraffic() {
233 : //total number of trips during the whole simulation
234 : int totalTrips = 0, ttOneDayTrips = 0, ttDailyTrips = 0;
235 : std::list<AGTrip>::iterator it;
236 3404 : for (it = trips.begin(); it != trips.end(); ++it) {
237 3396 : if (it->isDaily()) {
238 2744 : ++ttDailyTrips;
239 : } else {
240 652 : ++ttOneDayTrips;
241 : }
242 : }
243 8 : totalTrips = ttOneDayTrips + ttDailyTrips * nbrDays;
244 : //TESTS
245 : std::cout << "Before Random traffic generation (days are still entire):" << std::endl;
246 8 : std::cout << "- Total number of trips: " << totalTrips << std::endl;
247 8 : std::cout << "- Total daily trips: " << ttDailyTrips << std::endl;
248 8 : std::cout << "- Total one-day trips: " << ttOneDayTrips << std::endl;
249 : //END OF TESTS
250 :
251 : //random uniform distribution:
252 8 : int nbrRandUni = (int)((float)totalTrips * myCity->statData.uniformRandomTrafficRate / (1.0f - myCity->statData.uniformRandomTrafficRate));
253 : //TESTS
254 8 : std::cout << "added uniform random trips: " << nbrRandUni << std::endl;
255 : //END OF TESTS
256 1533 : for (int i = 0; i < nbrRandUni; ++i) {
257 1525 : AGPosition dep(myCity->getRandomStreet());
258 1525 : AGPosition arr(myCity->getRandomStreet());
259 1525 : AGTime depTime(RandHelper::rand(nbrDays * 86400));
260 1525 : AGTrip rdtr(dep, arr, generateName(i, "randUni"), depTime.getTime() % 86400, depTime.getDay() + 1);
261 1525 : rdtr.setType("random");
262 1525 : trips.push_back(rdtr);
263 1525 : }
264 :
265 : //random proportional distribution:
266 : //float proportionalPercentage = 0.05f;
267 : //TODO generate a proportionally distributed random traffic
268 :
269 8 : return true;
270 : }
271 :
272 :
273 : /****************************************************************************/
|