Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2006-2024 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 std::string& id, const SUMOTime depart,
121 : const std::string& fromTaz, const std::string& toTaz,
122 : const std::string& vehicleType,
123 : const bool originIsEdge = false, const bool destinationIsEdge = false);
124 :
125 : /** @brief Helper function for flow and trip output writing the depart
126 : * and arrival attributes
127 : *
128 : * @param[in] dev The stream to write the generated vehicle trips to
129 : * @param[in] noVtype Whether vtype information shall not be written
130 : * @param[in] cell The OD cell containing the vtype
131 : */
132 : void writeDefaultAttrs(OutputDevice& dev, const bool noVtype,
133 : const ODCell* const cell);
134 :
135 : /** @brief Writes the vehicles stored in the matrix assigning the sources and sinks
136 : *
137 : * The cells stored in myContainer are sorted, first. Then, for each time
138 : * step to generate vehicles for, it is checked whether the topmost cell
139 : * is valid for this time step. If so, vehicles are generated from this
140 : * cell's description using "computeDeparts" and stored in an internal vector.
141 : * The pointer is moved and the check is repeated until the current cell
142 : * is not valid for the current time or no further cells exist.
143 : *
144 : * Then, for the current time step, the internal list of vehicles is sorted and
145 : * all vehicles that start within this time step are written.
146 : *
147 : * The left fraction of vehicles to insert is saved for each O/D-dependency
148 : * over time and the number of vehicles to generate is increased as soon
149 : * as this value is larger than 1, decrementing it.
150 : *
151 : * @param[in] begin The begin time to generate vehicles for
152 : * @param[in] end The end time to generate vehicles for
153 : * @param[in] dev The stream to write the generated vehicle trips to
154 : * @param[in] uniform Information whether departure times shallbe uniformly spread or random
155 : * @param[in] differSourceSink whether source and sink shall be different edges
156 : * @param[in] noVtype Whether vtype information shall not be written
157 : * @param[in] prefix A prefix for the vehicle names
158 : * @param[in] stepLog Whether processed time shall be written
159 : * @param[in] pedestrians Writes trips for pedestrians
160 : * @param[in] persontrips Writes trips for persontrips
161 : */
162 : void write(SUMOTime begin, const SUMOTime end,
163 : OutputDevice& dev, const bool uniform,
164 : const bool differSourceSink, const bool noVtype,
165 : const std::string& prefix, const bool stepLog,
166 : bool pedestrians, bool persontrips,
167 : const std::string& modes);
168 :
169 :
170 : /** @brief Writes the flows stored in the matrix
171 : *
172 : * @param[in] begin The begin time to generate vehicles for
173 : * @param[in] end The end time to generate vehicles for
174 : * @param[in] dev The stream to write the generated vehicle trips to
175 : * @param[in] noVtype Whether vtype information shall not be written
176 : * @param[in] prefix A prefix for the flow names
177 : * @param[in] asProbability Write probability to spawn per second instead of number of vehicles
178 : * @param[in] pedestrians Writes flows for pedestrians
179 : * @param[in] persontrips Writes flows for persontrips
180 : */
181 : void writeFlows(const SUMOTime begin, const SUMOTime end,
182 : OutputDevice& dev, const bool noVtype,
183 : const std::string& prefix,
184 : bool asProbability = false, bool pedestrians = false, bool persontrips = false,
185 : const std::string& modes = "");
186 :
187 :
188 : /** @brief Returns the number of loaded vehicles
189 : *
190 : * Returns the value of myNoLoaded
191 : *
192 : * @return The number of loaded vehicles
193 : */
194 : double getNumLoaded() const;
195 :
196 :
197 : /** @brief Returns the number of written vehicles
198 : *
199 : * Returns the value of myNoWritten
200 : *
201 : * @return The number of written vehicles
202 : */
203 : double getNumWritten() const;
204 :
205 :
206 : /** @brief Returns the number of discarded vehicles
207 : *
208 : * Returns the value of myNoDiscarded
209 : *
210 : * @return The number of discarded vehicles
211 : */
212 : double getNumDiscarded() const;
213 :
214 :
215 : /** @brief Splits the stored cells dividing them on the given time line
216 : * @todo Describe
217 : */
218 : void applyCurve(const Distribution_Points& ps);
219 :
220 :
221 : /** @brief read a VISUM-matrix with the O Format
222 : * @todo Describe
223 : */
224 : void readO(LineReader& lr, double scale,
225 : std::string vehType, bool matrixHasVehType);
226 :
227 : /** @brief read a VISUM-matrix with the V Format
228 : * @todo Describe
229 : */
230 : void readV(LineReader& lr, double scale,
231 : std::string vehType, bool matrixHasVehType);
232 :
233 : /** @brief read a matrix in one of several formats
234 : * @todo Describe
235 : */
236 : void loadMatrix(OptionsCont& oc);
237 :
238 : /** @brief read SUMO routes
239 : * @todo Describe
240 : */
241 : void loadRoutes(OptionsCont& oc, SUMOSAXHandler& handler);
242 :
243 : /** @brief split the given timeline
244 : * @todo Describe
245 : */
246 : Distribution_Points parseTimeLine(const std::vector<std::string>& def, bool timelineDayInHours);
247 :
248 : const std::vector<ODCell*>& getCells() {
249 : return myContainer;
250 : }
251 :
252 : void sortByBeginTime();
253 :
254 : SUMOTime getBegin() const {
255 118 : return myBegin;
256 : }
257 :
258 : SUMOTime getEnd() const {
259 59 : return myEnd;
260 : }
261 :
262 : void addTazRelWeight(const std::string intervalID, const std::string& from, const std::string& to,
263 : double val, double beg, double end);
264 :
265 : protected:
266 : /**
267 : * @struct ODVehicle
268 : * @brief An internal representation of a single vehicle
269 : */
270 : struct ODVehicle {
271 : /// @brief The id of the vehicle
272 : std::string id;
273 : /// @brief The departure time of the vehicle
274 : SUMOTime depart;
275 : /// @brief The cell of the ODMatrix which generated the vehicle
276 : ODCell* cell;
277 : /// @brief The edge the vehicles shall start at
278 : std::string from;
279 : /// @brief The edge the vehicles shall end at
280 : std::string to;
281 :
282 : };
283 :
284 :
285 : /** @brief Computes the vehicle departs stored in the given cell and saves them in "into"
286 : *
287 : * At first, the number of vehicles to insert is computed using the
288 : * integer value of the vehicleNumber information from the given cell.
289 : * In the case vehicleNumber has a fraction, an additional vehicle
290 : * may be added in the case a chosen random number is lower than this fraction.
291 : *
292 : * If uniform is true, the departure times of the generated vehicles
293 : * are spread uniformly, otherwise the departure time are chosen randomly from
294 : * the interval.
295 : *
296 : * The vehicle names are generated by putting the value of vehName after the
297 : * given prefix. The value of vehName is incremented with each generated vehicle.
298 : *
299 : * The number of left vehicles (the fraction if no additional vehicle was
300 : * generated) is returned.
301 : *
302 : * @param[in] cell The cell to use
303 : * @param[in,out] vehName An incremented index of the generated vehicle
304 : * @param[out] into The storage to put generated vehicles into
305 : * @param[in] uniform Information whether departure times shallbe uniformly spread or random
306 : * @param[in] differSourceSink whether source and sink shall be different edges
307 : * @param[in] prefix A prefix for the vehicle names
308 : * @return The number of left vehicles to insert
309 : */
310 : double computeDeparts(ODCell* cell,
311 : int& vehName, std::vector<ODVehicle>& into,
312 : const bool uniform, const bool differSourceSink,
313 : const std::string& prefix);
314 :
315 :
316 : /** @brief Splits the given cell dividing it on the given time line and
317 : * storing the results in the given container
318 : *
319 : * For the given cell, a list of clones is generated. The number of these
320 : * is equal to the number of "areas" within the given distribution
321 : * description (time line in this case) and each clone's vehicleNumber
322 : * is equal to the given cell's vehicle number multiplied with the area's
323 : * probability. The clones are stored in the given cell vector.
324 : *
325 : * @see Distribution_Points
326 : * @param[in] ps The time line to apply
327 : * @param[in] cell The cell to split
328 : * @param[out] newCells The storage to put generated cells into
329 : * @todo describe better!!!
330 : */
331 : void applyCurve(const Distribution_Points& ps, ODCell* cell,
332 : std::vector<ODCell*>& newCells);
333 :
334 :
335 : private:
336 : /** @used in the functions readV and readO
337 : * @todo Describe
338 : */
339 : std::string getNextNonCommentLine(LineReader& lr);
340 :
341 : /** @used in the functions readV and readO
342 : * @todo Describe
343 : */
344 : SUMOTime parseSingleTime(const std::string& time);
345 :
346 : /** @used in the functions readV and readO
347 : * @todo Describe
348 : */
349 : std::pair<SUMOTime, SUMOTime> readTime(LineReader& lr);
350 :
351 : /** @used in the functions readV and readO
352 : * @todo Describe
353 : */
354 : double readFactor(LineReader& lr, double scale);
355 :
356 :
357 : private:
358 : /// @brief The loaded cells
359 : std::vector<ODCell*> myContainer;
360 :
361 : /// @brief The loaded cells indexed by origin and destination
362 : std::map<const std::pair<const std::string, const std::string>, std::vector<ODCell*> > myShortCut;
363 :
364 : /// @brief The districts to retrieve sources/sinks from
365 : const ODDistrictCont& myDistricts;
366 :
367 : /// @brief The missing districts already warned about
368 : std::set<std::string> myMissingDistricts;
369 :
370 : /// @brief Number of loaded vehicles
371 : double myNumLoaded;
372 :
373 : /// @brief Number of written vehicles
374 : double myNumWritten;
375 :
376 : /// @brief Number of discarded vehicles
377 : double myNumDiscarded;
378 :
379 : /// @brief parsed time bounds
380 : SUMOTime myBegin, myEnd;
381 :
382 : /// @brief user-defined vType
383 : std::string myVType;
384 :
385 : /// @brief the scaling factor for traffic
386 : double myScale;
387 :
388 : /**
389 : * @class cell_by_begin_comparator
390 : * @brief Used for sorting the cells by the begin time they describe
391 : */
392 : class cell_by_begin_comparator {
393 : public:
394 : /// @brief constructor
395 : explicit cell_by_begin_comparator() { }
396 :
397 :
398 : /** @brief Comparing operator
399 : *
400 : * Compares two cells by the begin of the time they describe. The sort is stabilized
401 : * (with secondary sort keys being origin and destination) to get comparable results
402 : * with different platforms / compilers.
403 : *
404 : * @param[in] p1 First cell to compare
405 : * @param[in] p2 Second cell to compare
406 : * @return Whether the begin time of the first cell is lower than the one of the second
407 : */
408 124840 : int operator()(ODCell* p1, ODCell* p2) const {
409 124840 : if (p1->begin == p2->begin) {
410 66420 : if (p1->origin == p2->origin) {
411 25144 : return p1->destination < p2->destination;
412 : }
413 41276 : return p1->origin < p2->origin;
414 : }
415 58420 : return p1->begin < p2->begin;
416 : }
417 :
418 : };
419 :
420 :
421 : /**
422 : * @class descending_departure_comperator
423 : * @brief Used for sorting vehicles by their departure (latest first)
424 : *
425 : * A reverse operator to what may be expected is used in order to allow
426 : * prunning the sorted vector from its tail.
427 : */
428 : class descending_departure_comperator {
429 : public:
430 : /// @brief constructor
431 : descending_departure_comperator() { }
432 :
433 :
434 : /** @brief Comparing operator
435 : *
436 : * Compares two vehicles by their departure time
437 : *
438 : * @param[in] p1 First vehicle to compare
439 : * @param[in] p2 Second vehicle to compare
440 : * @return Whether the departure time of the first vehicle is larger than the one of the second
441 : */
442 : bool operator()(const ODVehicle& p1, const ODVehicle& p2) const {
443 170767 : if (p1.depart == p2.depart) {
444 7 : return p1.id > p2.id;
445 : }
446 170760 : return p1.depart > p2.depart;
447 : }
448 :
449 : };
450 :
451 : private:
452 : /** @brief invalid copy constructor */
453 : ODMatrix(const ODMatrix& s);
454 :
455 : /** @brief invalid assignment operator */
456 : ODMatrix& operator=(const ODMatrix& s) = delete;
457 :
458 : };
|