Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/router/AFBuilder.h
169678 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-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 AFBuilder.h
15
/// @author Ruediger Ebendt
16
/// @date 01.11.2023
17
///
18
// Arc flags builder for the arc flag router
19
/****************************************************************************/
20
#pragma once
21
#include <config.h>
22
#include <vector>
23
// uncomment to disable assert()
24
// #define NDEBUG
25
#include <cassert>
26
27
#include "AFBuild.h"
28
#include "FlippedEdge.h"
29
30
//#define AFBL_DEBUG_LEVEL_0
31
//#define AFBL_DEBUG_LEVEL_1
32
//#define AFBL_DEBUG_LEVEL_2
33
34
#ifdef AFBL_DEBUG_LEVEL_2
35
#define AFBL_DEBUG_LEVEL_1
36
#endif
37
38
#ifdef AFBL_DEBUG_LEVEL_1
39
#define AFBL_DEBUG_LEVEL_0
40
#endif
41
42
// ===========================================================================
43
// class definitions
44
// ===========================================================================
45
/**
46
* @class AFBuilder
47
* @brief Builds arc flags for shortest path search with the arc flag router
48
*/
49
50
template<class E, class N, class V, class M>
51
class AFBuilder {
52
public:
53
typedef typename AFInfo<E>::FlagInfo FlagInfo;
54
typedef AbstractLookupTable<FlippedEdge<E, N, V>, V> FlippedLookupTable;
55
56
/** @brief Constructor
57
* @param[in] numberOfLevels The number of levels
58
* @param[in] edges The container with all edges of the network
59
* @param[in] unbuildIsWarning The flag indicating whether network unbuilds should issue warnings or errors
60
* @param[in] flippedOperation The operation for a backward graph with flipped edges
61
* @param[in] flippedLookup The lookup table for a backward graph with flipped edges
62
* @param[in] havePermissions The flag indicating whether edges have permissions which must be respected
63
* @param[in] haveRestrictions The flag indicating whether edges have restrictions which must be respected
64
* @param[in] toProhibit The list of explicitly prohibited edges
65
*/
66
AFBuilder(int numberOfLevels, const std::vector<E*>& edges, bool unbuildIsWarning,
67
typename SUMOAbstractRouter<FlippedEdge<E, N, V>, V>::Operation flippedOperation,
68
const std::shared_ptr<const FlippedLookupTable> flippedLookup = nullptr,
69
const bool havePermissions = false, const bool haveRestrictions = false,
70
const std::map<const FlippedEdge<E, N, V>*, double>* toProhibit = nullptr) :
71
myEdges(edges),
72
myNumberOfLevels(numberOfLevels),
73
myNumberOfArcFlags(2 * (myNumberOfLevels - 1)),
74
#ifdef AFBL_DEBUG_LEVEL_0
75
myArcFlagsFileName("arcflags.csv"),
76
#endif
77
myAmClean(true) {
78
for (const E* const edge : edges) {
79
myFlagInfos.push_back(new FlagInfo(edge));
80
}
81
// build the backward graph with flipped edges / nodes in advance
82
#ifdef AFBL_DEBUG_LEVEL_0
83
std::cout << "Building flipped edges (" << edges.size() << " edges) / nodes..." << std::endl;
84
#endif
85
for (const E* const edge : edges) {
86
myFlippedEdges.push_back(edge->getFlippedRoutingEdge());
87
}
88
for (FlippedEdge<E, N, V>* flippedEdge : myFlippedEdges) {
89
flippedEdge->init();
90
}
91
#ifdef AFBL_DEBUG_LEVEL_0
92
std::cout << "Flipped edges / nodes are ready." << std::endl;
93
#endif
94
myFlippedPartition = new KDTreePartition<FlippedEdge<E, N, V>, FlippedNode<E, N, V>, V>(myNumberOfLevels,
95
myFlippedEdges, havePermissions, haveRestrictions);
96
#ifdef AFBL_DEBUG_LEVEL_0
97
std::cout << "Instantiating arc flag build..." << std::endl;
98
#endif
99
myArcFlagBuild = new AFBuild<E, N, V, M>(myFlippedEdges, myFlippedPartition, numberOfLevels, unbuildIsWarning,
100
flippedOperation, flippedLookup, havePermissions, haveRestrictions, toProhibit);
101
102
#ifdef AFBL_DEBUG_LEVEL_0
103
std::cout << "Arc flag build is instantiated (but still uninitialized)." << std::endl;
104
#endif
105
} // end of constructor
106
107
/// @brief Destructor
108
~AFBuilder();
109
110
/// @brief Returns the arc flag build
111
AFBuild<E, N, V, M>* getArcFlagBuild() {
112
return myArcFlagBuild;
113
}
114
/// @brief Returns the edges
115
const std::vector<E*>& getEdges() {
116
return myEdges;
117
}
118
/// @brief Resets the builder
119
void reset();
120
/** @brief Build the arc flag information for the arc flag router
121
* @param[in] msTime The start time of the routes in milliseconds
122
* @param[in] The vehicle
123
* @return The vector with the arc flag information
124
*/
125
std::vector<FlagInfo*>& build(SUMOTime msTime, const V* const vehicle);
126
/** @brief Converts a SHARC level number to a partition level number
127
* @param[in] sHARCLevel The SHARC level
128
* @return The partition level number
129
*/
130
int sHARCLevel2PartitionLevel(int sHARCLevel) {
131
return AFRouter<E, N, V, M>::sHARCLevel2PartitionLevel(sHARCLevel, myNumberOfLevels);
132
}
133
134
protected:
135
#ifdef AFBL_DEBUG_LEVEL_0
136
/** @brief Loads already precomputed arc flags from a CSV file (for testing purposes)
137
* @param[in] fileName The name of the CSV file
138
*/
139
void loadFlagsFromCsv(const std::string fileName);
140
/** @brief Saves computed arc flags to a CSV file (for testing purposes)
141
* @param[in] fileName The name of the CSV file
142
*/
143
void saveFlagsToCsv(const std::string fileName);
144
/** @brief Returns true iff a file with the given name exists
145
* @param[in] name The name of the file to test for existence
146
* @return true iff a file with the given name exists
147
*/
148
bool fileExists(const std::string& name) {
149
std::ifstream f(name.c_str());
150
return f.good();
151
}
152
#endif
153
/// @brief The edges
154
const std::vector<E*>& myEdges;
155
/// @brief The flipped (backward) edges
156
std::vector<FlippedEdge<E, N, V>*> myFlippedEdges;
157
/// @brief The k-d tree partition of the backward graph with flipped edges
158
KDTreePartition<FlippedEdge<E, N, V>, FlippedNode<E, N, V>, V>* myFlippedPartition;
159
/// @brief The flag informations
160
std::vector<FlagInfo*> myFlagInfos;
161
/// @brief The arc flag build
162
AFBuild<E, N, V, M>* myArcFlagBuild;
163
/// @brief The number of levels of the k-d tree partition of the network
164
int myNumberOfLevels;
165
/// @brief The number of arc flags per each edge
166
int myNumberOfArcFlags;
167
#ifdef AFBL_DEBUG_LEVEL_0
168
/// @brief The name of the arc flags file.
169
// @note This is a CSV file for convenience/testing purposes
170
const std::string myArcFlagsFileName;
171
#endif
172
bool myAmClean;
173
};
174
175
// ===========================================================================
176
// method definitions
177
// ===========================================================================
178
179
template<class E, class N, class V, class M>
180
AFBuilder<E, N, V, M>::~AFBuilder() {
181
delete myArcFlagBuild;
182
delete myFlippedPartition;
183
for (FlagInfo* flagInfo : myFlagInfos) {
184
delete flagInfo;
185
}
186
}
187
188
template<class E, class N, class V, class M>
189
void AFBuilder<E, N, V, M>::reset() {
190
for (FlagInfo* flagInfo : myFlagInfos) {
191
flagInfo->reset();
192
}
193
myAmClean = true;
194
}
195
196
template<class E, class N, class V, class M>
197
std::vector<typename AFInfo<E>::FlagInfo*>& AFBuilder<E, N, V, M>::build(SUMOTime msTime, const V* const vehicle) {
198
if (!myAmClean) {
199
reset();
200
}
201
assert(myFlippedPartition);
202
if (myFlippedPartition->isClean()) {
203
myFlippedPartition->init(vehicle);
204
myArcFlagBuild->setFlippedPartition(myFlippedPartition);
205
} else {
206
myFlippedPartition->reset(vehicle);
207
}
208
assert(myArcFlagBuild);
209
#ifdef AFBL_DEBUG_LEVEL_0
210
bool fileExists = this->fileExists(myArcFlagsFileName);
211
if (fileExists && myAmClean) {
212
std::cout << "Loading arc flags from file " << myArcFlagsFileName << std::endl;
213
loadFlagsFromCsv(myArcFlagsFileName);
214
std::cout << "Arc flags loaded." << std::endl;
215
} else {
216
#endif
217
myArcFlagBuild->init(msTime, vehicle, myFlagInfos);
218
#ifdef AFBL_DEBUG_LEVEL_0
219
}
220
#endif
221
delete myFlippedPartition;
222
myFlippedPartition = nullptr;
223
224
#ifdef AFBL_DEBUG_LEVEL_0
225
if (!fileExists) {
226
std::cout << "Saving arc flags..." << std::endl;
227
// save flag vectors in a CSV file (one column, flag vectors in the order of edges)
228
saveFlagsToCsv(myArcFlagsFileName);
229
std::cout << "Arc flags have been saved." << std::endl;
230
}
231
#endif
232
myAmClean = false;
233
return myFlagInfos;
234
}
235
236
#ifdef AFBL_DEBUG_LEVEL_0
237
template<class E, class N, class V, class M>
238
void AFBuilder<E, N, V, M>::saveFlagsToCsv(const std::string fileName) {
239
std::ofstream csvFile(fileName);
240
for (FlagInfo* flagInfo : myFlagInfos) {
241
if ((flagInfo->arcFlags).empty()) {
242
// default flag is false / zero
243
std::fill_n(std::back_inserter(flagInfo->arcFlags),
244
myNumberOfArcFlags, false);
245
}
246
for (bool flag : flagInfo->arcFlags) {
247
csvFile << flag;
248
}
249
csvFile << std::endl;
250
}
251
csvFile.close();
252
}
253
254
template<class E, class N, class V, class M>
255
void AFBuilder<E, N, V, M>::loadFlagsFromCsv(const std::string fileName) {
256
assert(myAmClean);
257
std::string fileNameCopy = fileName;
258
std::ifstream csvFile(fileNameCopy);
259
std::string result;
260
if (!csvFile.is_open()) {
261
result = fileNameCopy.insert(0, "Could not open CSV file ");
262
throw std::runtime_error(result);
263
}
264
for (FlagInfo* flagInfo : myFlagInfos) {
265
(flagInfo->arcFlags).clear();
266
std::fill_n(std::back_inserter(flagInfo->arcFlags),
267
myNumberOfArcFlags, false);
268
std::string line;
269
if (std::getline(csvFile, line)) {
270
if (line.empty()) {
271
continue;
272
}
273
std::stringstream stringStream(line);
274
std::string flagAsString(1, '\0');
275
int pos = 0;
276
while (stringStream.read(&flagAsString[0], 1)) {
277
(flagInfo->arcFlags)[pos++] = (!flagAsString.compare("0") ? 0 : 1);
278
}
279
} else {
280
result = fileNameCopy.insert(0, "CSV file ");
281
throw std::runtime_error(result.append(" has not enough lines - wrong or corrupted file?"));
282
}
283
}
284
myAmClean = false;
285
csvFile.close();
286
}
287
#endif
288
289