Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2006-2026 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file ODMatrix.h
15 : /// @author Daniel Krajzewicz
16 : /// @author Michael Behrisch
17 : /// @author Yun-Pang Floetteroed
18 : /// @date 05. Apr. 2006
19 : ///
20 : // An O/D (origin/destination) matrix
21 : /****************************************************************************/
22 : #pragma once
23 : #include <config.h>
24 :
25 : #include <iostream>
26 : #include <sstream>
27 : #include <fstream>
28 : #include <vector>
29 : #include <cstdlib>
30 : #include <ctime>
31 : #include <algorithm>
32 : #include <set>
33 : #include <string>
34 : #include <utils/common/SUMOTime.h>
35 : #include "ODCell.h"
36 : #include "ODDistrictCont.h"
37 : #include <utils/distribution/Distribution_Points.h>
38 : #include <utils/importio/LineReader.h>
39 : #include <utils/common/SUMOTime.h>
40 : #include <utils/xml/SAXWeightsHandler.h>
41 :
42 : // ===========================================================================
43 : // class declarations
44 : // ===========================================================================
45 : class OptionsCont;
46 : class OutputDevice;
47 : class SUMOSAXHandler;
48 :
49 :
50 : // ===========================================================================
51 : // class definitions
52 : // ===========================================================================
53 : /**
54 : * @class ODMatrix
55 : * @brief An O/D (origin/destination) matrix
56 : *
57 : * This class is the internal representation of a loaded O/D-matrix. Beside
58 : * being the storage for ODCells, the matrix also contains information about
59 : * the numbers of loaded, discarded, and written vehicles.
60 : *
61 : * The matrix has a reference to the container of districts stored. This allows
62 : * to validate added cell descriptions in means that using existing origins/
63 : * destinations only is assured.
64 : *
65 : * In addition of being a storage, the matrix is also responsible for writing
66 : * the results and contains methods for splitting the entries over time.
67 : */
68 : class ODMatrix : public SAXWeightsHandler::EdgeFloatTimeLineRetriever {
69 :
70 : public:
71 : /** @brief Constructor
72 : *
73 : * @param[in] dc The district container to obtain referenced districts from
74 : */
75 : ODMatrix(const ODDistrictCont& dc, double scale);
76 :
77 :
78 : /// Destructor
79 : ~ODMatrix();
80 :
81 :
82 : /** @brief Builds a single cell from the given values, verifying them
83 : *
84 : * At first, the number of loaded vehicles (myNoLoaded) is incremented
85 : * by vehicleNumber.
86 : *
87 : * It is checked whether both the origin and the destination exist within
88 : * the assigned district container (myDistricts). If one of them is missing,
89 : * an error is generated, if both, a warning, because in the later case
90 : * the described flow may lay completely beside the processed area. In both
91 : * cases the given number of vehicles (vehicleNumber) is added to myNoDiscarded.
92 : *
93 : * If the origin/destination districts are known, a cell is built using the
94 : * given values. This cell is added to the list of known cells (myContainer).
95 : *
96 : * @param[in] vehicleNumber The number of vehicles to store within the cell
97 : * @param[in] beginEnd The begin and the end of the interval the cell is valid for
98 : * @param[in] origin The origin district to use for the cell's flows
99 : * @param[in] destination The destination district to use for the cell's flows
100 : * @param[in] vehicleType The vehicle type to use for the cell's flows
101 : * @return whether the cell could be added
102 : */
103 : bool add(double vehicleNumber, const std::pair<SUMOTime, SUMOTime>& beginEnd,
104 : const std::string& origin, const std::string& destination,
105 : const std::string& vehicleType,
106 : const bool originIsEdge = false, const bool destinationIsEdge = false,
107 : bool noScaling = false);
108 :
109 : /** @brief Adds a single vehicle with departure time
110 : *
111 : * If there is no existing ODCell for the given parameters one is generated
112 : * using add(...)
113 : *
114 : * @param[in] id The id of the vehicle
115 : * @param[in] depart The departure time of the vehicle
116 : * @param[in] od The origin and destination district to use for the cell's flows
117 : * @param[in] vehicleType The vehicle type to use for the cell's flows
118 : * @return whether the vehicle could be added
119 : */
120 : bool add(const SUMOVehicleParameter& veh, bool originIsEdge = false, bool destinationIsEdgeconst = false);
121 :
122 : /** @brief Helper function for flow and trip output writing the depart
123 : * and arrival attributes
124 : *
125 : * @param[in] dev The stream to write the generated vehicle trips to
126 : * @param[in] noVtype Whether vtype information shall not be written
127 : * @param[in] cell The OD cell containing the vtype
128 : */
129 : void writeDefaultAttrs(OutputDevice& dev, const bool noVtype,
130 : const ODCell* const cell);
131 :
132 : /** @brief Writes the vehicles stored in the matrix assigning the sources and sinks
133 : *
134 : * The cells stored in myContainer are sorted, first. Then, for each time
135 : * step to generate vehicles for, it is checked whether the topmost cell
136 : * is valid for this time step. If so, vehicles are generated from this
137 : * cell's description using "computeDeparts" and stored in an internal vector.
138 : * The pointer is moved and the check is repeated until the current cell
139 : * is not valid for the current time or no further cells exist.
140 : *
141 : * Then, for the current time step, the internal list of vehicles is sorted and
142 : * all vehicles that start within this time step are written.
143 : *
144 : * The left fraction of vehicles to insert is saved for each O/D-dependency
145 : * over time and the number of vehicles to generate is increased as soon
146 : * as this value is larger than 1, decrementing it.
147 : *
148 : * @param[in] begin The begin time to generate vehicles for
149 : * @param[in] end The end time to generate vehicles for
150 : * @param[in] dev The stream to write the generated vehicle trips to
151 : * @param[in] uniform Information whether departure times shallbe uniformly spread or random
152 : * @param[in] differSourceSink whether source and sink shall be different edges
153 : * @param[in] noVtype Whether vtype information shall not be written
154 : * @param[in] prefix A prefix for the vehicle names
155 : * @param[in] stepLog Whether processed time shall be written
156 : * @param[in] pedestrians Writes trips for pedestrians
157 : * @param[in] persontrips Writes trips for persontrips
158 : */
159 : void write(SUMOTime begin, const SUMOTime end,
160 : OutputDevice& dev, const bool uniform,
161 : const bool differSourceSink, const bool noVtype,
162 : const std::string& prefix, const bool stepLog,
163 : bool pedestrians, bool persontrips,
164 : const std::string& modes);
165 :
166 :
167 : /** @brief Writes the flows stored in the matrix
168 : *
169 : * @param[in] begin The begin time to generate vehicles for
170 : * @param[in] end The end time to generate vehicles for
171 : * @param[in] dev The stream to write the generated vehicle trips to
172 : * @param[in] noVtype Whether vtype information shall not be written
173 : * @param[in] prefix A prefix for the flow names
174 : * @param[in] asProbability Write probability to spawn per second instead of number of vehicles
175 : * @param[in] pedestrians Writes flows for pedestrians
176 : * @param[in] persontrips Writes flows for persontrips
177 : */
178 : void writeFlows(const SUMOTime begin, const SUMOTime end,
179 : OutputDevice& dev, const bool noVtype,
180 : const std::string& prefix,
181 : bool asProbability = false,
182 : bool asPoisson = false,
183 : bool pedestrians = false, bool persontrips = false,
184 : const std::string& modes = "");
185 :
186 :
187 : /** @brief Returns the number of loaded vehicles
188 : *
189 : * Returns the value of myNoLoaded
190 : *
191 : * @return The number of loaded vehicles
192 : */
193 : double getNumLoaded() const;
194 :
195 :
196 : /** @brief Returns the number of written vehicles
197 : *
198 : * Returns the value of myNoWritten
199 : *
200 : * @return The number of written vehicles
201 : */
202 : double getNumWritten() const;
203 :
204 :
205 : /** @brief Returns the number of discarded vehicles
206 : *
207 : * Returns the value of myNoDiscarded
208 : *
209 : * @return The number of discarded vehicles
210 : */
211 : double getNumDiscarded() const;
212 :
213 :
214 : /** @brief Splits the stored cells dividing them on the given time line
215 : * @todo Describe
216 : */
217 : void applyCurve(const Distribution_Points& ps);
218 :
219 :
220 : /** @brief read a VISUM-matrix with the O Format
221 : * @todo Describe
222 : */
223 : void readO(LineReader& lr, double scale,
224 : std::string vehType, bool matrixHasVehType);
225 :
226 : /** @brief read a VISUM-matrix with the V Format
227 : * @todo Describe
228 : */
229 : void readV(LineReader& lr, double scale,
230 : std::string vehType, bool matrixHasVehType);
231 :
232 : /** @brief read a matrix in one of several formats
233 : * @todo Describe
234 : */
235 : void loadMatrix(OptionsCont& oc);
236 :
237 : /** @brief read SUMO routes
238 : * @todo Describe
239 : */
240 : void loadRoutes(OptionsCont& oc, SUMOSAXHandler& handler);
241 :
242 : /** @brief split the given timeline
243 : * @todo Describe
244 : */
245 : Distribution_Points parseTimeLine(const std::vector<std::string>& def, bool timelineDayInHours);
246 :
247 : const std::vector<ODCell*>& getCells() {
248 : return myContainer;
249 : }
250 :
251 : void sortByBeginTime();
252 :
253 : SUMOTime getBegin() const {
254 142 : return myBegin;
255 : }
256 :
257 : SUMOTime getEnd() const {
258 71 : return myEnd;
259 : }
260 :
261 : void addTazRelWeight(const std::string intervalID, const std::string& from, const std::string& to,
262 : double val, double beg, double end);
263 :
264 : protected:
265 : /**
266 : * @struct ODVehicle
267 : * @brief An internal representation of a single vehicle
268 : */
269 : struct ODVehicle {
270 : /// @brief The id of the vehicle
271 : std::string id;
272 : /// @brief The departure time of the vehicle
273 : SUMOTime depart;
274 : /// @brief The cell of the ODMatrix which generated the vehicle
275 : ODCell* cell;
276 : /// @brief The edge the vehicles shall start at
277 : std::string from;
278 : /// @brief The edge the vehicles shall end at
279 : std::string to;
280 :
281 : };
282 :
283 :
284 : /** @brief Computes the vehicle departs stored in the given cell and saves them in "into"
285 : *
286 : * At first, the number of vehicles to insert is computed using the
287 : * integer value of the vehicleNumber information from the given cell.
288 : * In the case vehicleNumber has a fraction, an additional vehicle
289 : * may be added in the case a chosen random number is lower than this fraction.
290 : *
291 : * If uniform is true, the departure times of the generated vehicles
292 : * are spread uniformly, otherwise the departure time are chosen randomly from
293 : * the interval.
294 : *
295 : * The vehicle names are generated by putting the value of vehName after the
296 : * given prefix. The value of vehName is incremented with each generated vehicle.
297 : *
298 : * The number of left vehicles (the fraction if no additional vehicle was
299 : * generated) is returned.
300 : *
301 : * @param[in] cell The cell to use
302 : * @param[in,out] vehName An incremented index of the generated vehicle
303 : * @param[out] into The storage to put generated vehicles into
304 : * @param[in] uniform Information whether departure times shallbe uniformly spread or random
305 : * @param[in] differSourceSink whether source and sink shall be different edges
306 : * @param[in] prefix A prefix for the vehicle names
307 : * @return The number of left vehicles to insert
308 : */
309 : double computeDeparts(ODCell* cell,
310 : int& vehName, std::vector<ODVehicle>& into,
311 : const bool uniform, const bool differSourceSink,
312 : const std::string& prefix);
313 :
314 :
315 : /** @brief Splits the given cell dividing it on the given time line and
316 : * storing the results in the given container
317 : *
318 : * For the given cell, a list of clones is generated. The number of these
319 : * is equal to the number of "areas" within the given distribution
320 : * description (time line in this case) and each clone's vehicleNumber
321 : * is equal to the given cell's vehicle number multiplied with the area's
322 : * probability. The clones are stored in the given cell vector.
323 : *
324 : * @see Distribution_Points
325 : * @param[in] ps The time line to apply
326 : * @param[in] cell The cell to split
327 : * @param[out] newCells The storage to put generated cells into
328 : * @todo describe better!!!
329 : */
330 : void applyCurve(const Distribution_Points& ps, ODCell* cell,
331 : std::vector<ODCell*>& newCells);
332 :
333 :
334 : private:
335 : /** @used in the functions readV and readO
336 : * @todo Describe
337 : */
338 : std::string getNextNonCommentLine(LineReader& lr);
339 :
340 : /** @used in the functions readV and readO
341 : * @todo Describe
342 : */
343 : SUMOTime parseSingleTime(const std::string& time);
344 :
345 : /** @used in the functions readV and readO
346 : * @todo Describe
347 : */
348 : std::pair<SUMOTime, SUMOTime> readTime(LineReader& lr);
349 :
350 : /** @used in the functions readV and readO
351 : * @todo Describe
352 : */
353 : double readFactor(LineReader& lr, double scale);
354 :
355 :
356 : private:
357 : /// @brief The loaded cells
358 : std::vector<ODCell*> myContainer;
359 :
360 : /// @brief The loaded cells indexed by origin and destination
361 : std::map<const std::pair<const std::string, const std::string>, std::vector<ODCell*> > myShortCut;
362 :
363 : /// @brief The districts to retrieve sources/sinks from
364 : const ODDistrictCont& myDistricts;
365 :
366 : /// @brief The missing districts already warned about
367 : std::set<std::string> myMissingDistricts;
368 :
369 : /// @brief Number of loaded vehicles
370 : double myNumLoaded;
371 :
372 : /// @brief Number of written vehicles
373 : double myNumWritten;
374 :
375 : /// @brief Number of discarded vehicles
376 : double myNumDiscarded;
377 :
378 : /// @brief parsed time bounds
379 : SUMOTime myBegin, myEnd;
380 :
381 : /// @brief user-defined vType
382 : std::string myVType;
383 :
384 : /// @brief the scaling factor for traffic
385 : double myScale;
386 :
387 : /**
388 : * @class cell_by_begin_comparator
389 : * @brief Used for sorting the cells by the begin time they describe
390 : */
391 : class cell_by_begin_comparator {
392 : public:
393 : /// @brief constructor
394 : explicit cell_by_begin_comparator() { }
395 :
396 :
397 : /** @brief Comparing operator
398 : *
399 : * Compares two cells by the begin of the time they describe. The sort is stabilized
400 : * (with secondary sort keys being origin and destination) to get comparable results
401 : * with different platforms / compilers.
402 : *
403 : * @param[in] p1 First cell to compare
404 : * @param[in] p2 Second cell to compare
405 : * @return Whether the begin time of the first cell is lower than the one of the second
406 : */
407 124840 : int operator()(ODCell* p1, ODCell* p2) const {
408 124840 : if (p1->begin == p2->begin) {
409 66420 : if (p1->origin == p2->origin) {
410 25144 : return p1->destination < p2->destination;
411 : }
412 41276 : return p1->origin < p2->origin;
413 : }
414 58420 : return p1->begin < p2->begin;
415 : }
416 :
417 : };
418 :
419 :
420 : /**
421 : * @class descending_departure_comperator
422 : * @brief Used for sorting vehicles by their departure (latest first)
423 : *
424 : * A reverse operator to what may be expected is used in order to allow
425 : * prunning the sorted vector from its tail.
426 : */
427 : class descending_departure_comperator {
428 : public:
429 : /// @brief constructor
430 : descending_departure_comperator() { }
431 :
432 :
433 : /** @brief Comparing operator
434 : *
435 : * Compares two vehicles by their departure time
436 : *
437 : * @param[in] p1 First vehicle to compare
438 : * @param[in] p2 Second vehicle to compare
439 : * @return Whether the departure time of the first vehicle is larger than the one of the second
440 : */
441 : bool operator()(const ODVehicle& p1, const ODVehicle& p2) const {
442 170767 : if (p1.depart == p2.depart) {
443 7 : return p1.id > p2.id;
444 : }
445 170760 : return p1.depart > p2.depart;
446 : }
447 :
448 : };
449 :
450 : private:
451 : /** @brief invalid copy constructor */
452 : ODMatrix(const ODMatrix& s);
453 :
454 : /** @brief invalid assignment operator */
455 : ODMatrix& operator=(const ODMatrix& s) = delete;
456 :
457 : };
|