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