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 : /****************************************************************************/