Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/od/ODMatrix.h
169666 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2006-2025 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
return myBegin;
253
}
254
255
SUMOTime getEnd() const {
256
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
int operator()(ODCell* p1, ODCell* p2) const {
406
if (p1->begin == p2->begin) {
407
if (p1->origin == p2->origin) {
408
return p1->destination < p2->destination;
409
}
410
return p1->origin < p2->origin;
411
}
412
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
if (p1.depart == p2.depart) {
441
return p1.id > p2.id;
442
}
443
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
};
456
457