Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
eclipse
GitHub Repository: eclipse/sumo
Path: blob/main/src/utils/router/AFBuild.h
193905 views
1
/****************************************************************************/
2
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3
// Copyright (C) 2001-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 AFBuild.h
15
/// @author Ruediger Ebendt
16
/// @date 01.12.2023
17
///
18
// Class for building the arc flags for (multi-level) arc flag routing
19
/****************************************************************************/
20
#pragma once
21
#include <config.h>
22
#include <memory>
23
#include <vector>
24
#include <unordered_set>
25
#include <math.h>
26
#include <cmath>
27
#include <limits>
28
#include <stdexcept>
29
#include <string>
30
#include <cinttypes>
31
#include <utility>
32
#include <utils/common/SUMOTime.h>
33
#include <utils/common/SUMOVehicleClass.h>
34
#include "KDTreePartition.h"
35
#include "Node2EdgeRouter.h"
36
#include "FlippedEdge.h"
37
#include "AFCentralizedSPTree.h"
38
39
//#define AFBU_WRITE_QGIS_FILTERS
40
#ifdef AFBU_WRITE_QGIS_FILTERS
41
#include <fstream>
42
#include <sstream>
43
#endif
44
45
//#define AFBU_DEBUG_LEVEL_0
46
//#define AFBU_DEBUG_LEVEL_1
47
//#define AFBU_DEBUG_LEVEL_2
48
49
#ifdef AFBU_DEBUG_LEVEL_2
50
#define AFBU_DEBUG_LEVEL_1
51
#endif
52
53
#ifdef AFBU_DEBUG_LEVEL_1
54
#define AFBU_DEBUG_LEVEL_0
55
#endif
56
57
// uncomment to disable assert()
58
// #define NDEBUG
59
#include <cassert>
60
61
// ===========================================================================
62
// class declarations
63
// ===========================================================================
64
template<class E, class N, class V, class M>
65
class AFRouter;
66
67
// ===========================================================================
68
// class definitions
69
// ===========================================================================
70
71
/**
72
* @class AFBuild
73
* @brief Builds the flags for (multi-level) arc flag routing (Hilger et al.) in its multi-level variant
74
* (also called "stripped SHARC" by Delling et al.)
75
*
76
* The template parameters are:
77
* @param E The edge class to use (MSEdge/ROEdge )
78
* @param N The node class to use (MSJunction/RONode)
79
* @param V The vehicle class to use (MSVehicle/ROVehicle)
80
*/
81
template<class E, class N, class V, class M>
82
class AFBuild {
83
public:
84
/// @brief Maximum difference of two path lengths considered to be equal
85
const double EPS = 0.009;
86
typedef typename KDTreePartition<FlippedEdge<E, N, V>, FlippedNode<E, N, V>, V>::Cell Cell;
87
typedef typename AFInfo<FlippedEdge<E, N, V>>::ArcInfo ArcInfo;
88
typedef typename AFInfo<E>::FlagInfo FlagInfo;
89
typedef AbstractLookupTable<FlippedEdge<E, N, V>, V> FlippedLookupTable;
90
91
/** @brief Constructor
92
* @param[in] flippedEdges The flipped (aka reversed / backward) edges
93
* @param[in] flippedPartition The k-d tree partition of the backward graph with flipped edges
94
* @param[in] numberOfLevels The number of levels
95
* @param[in] unbuildIsWarning The flag indicating whether network unbuilds should issue warnings or errors
96
* @param[in] flippedOperation The operation for a backward graph with flipped edges
97
* @param[in] flippedLookup The lookup table for a backward graph with flipped edges
98
* @param[in] havePermissions The boolean flag indicating whether edge permissions need to be considered or not
99
* @param[in] haveRestrictions The boolean flag indicating whether edge restrictions need to be considered or not
100
* @param[in] toProhibit The list of explicitly prohibited edges
101
*/
102
AFBuild(
103
const std::vector<FlippedEdge<E, N, V>*>& flippedEdges,
104
const KDTreePartition<FlippedEdge<E, N, V>, FlippedNode<E, N, V>, V>* const flippedPartition,
105
int numberOfLevels, bool unbuildIsWarning,
106
typename SUMOAbstractRouter<FlippedEdge<E, N, V>, V>::Operation flippedOperation,
107
const std::shared_ptr<const FlippedLookupTable> flippedLookup = nullptr,
108
const bool havePermissions = false, const bool haveRestrictions = false,
109
const std::map<const FlippedEdge<E, N, V>*, RouterProhibition>* toProhibit = nullptr) :
110
myFlippedEdges(flippedEdges),
111
myFlippedPartition(flippedPartition),
112
myNumberOfLevels(numberOfLevels),
113
myErrorMsgHandler(unbuildIsWarning ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()),
114
myFlippedOperation(flippedOperation),
115
myFlippedLookupTable(flippedLookup),
116
myHavePermissions(havePermissions),
117
myHaveRestrictions(haveRestrictions),
118
myProhibited(toProhibit),
119
myNode2EdgeRouter(new Node2EdgeRouter<FlippedEdge<E, N, V>, FlippedNode<E, N, V>, V, M>(myFlippedEdges,
120
unbuildIsWarning, myFlippedOperation, myFlippedLookupTable, myHavePermissions, myHaveRestrictions)) {
121
myCentralizedSPTree = new AFCentralizedSPTree<FlippedEdge<E, N, V>, FlippedNode<E, N, V>, V>(myFlippedEdges,
122
myArcInfos, unbuildIsWarning, myNode2EdgeRouter, myHavePermissions, myHaveRestrictions);
123
if (toProhibit) {
124
myNode2EdgeRouter->prohibit(*toProhibit);
125
}
126
}
127
128
/// @brief Destructor
129
~AFBuild() {
130
delete myCentralizedSPTree;
131
delete myNode2EdgeRouter;
132
}
133
134
/// @brief Returns the operation for a backward graph with flipped edges
135
typename SUMOAbstractRouter<FlippedEdge<E, N, V>, V>::Operation getFlippedOperation() {
136
return myFlippedOperation;
137
}
138
/// @brief Returns the lookup table for the backward graph with flipped edges
139
const std::shared_ptr<const FlippedLookupTable> getFlippedLookup() {
140
return myFlippedLookupTable;
141
}
142
/** @brief Initialize the arc flag build
143
* @param[in] msTime The start time of the routes in milliseconds
144
* @param[in] vehicle The vehicle
145
* @param[in] flagInfos The arc flag informations
146
*/
147
void init(SUMOTime time, const V* const vehicle, std::vector<FlagInfo*>& flagInfos);
148
/** @brief Set the flipped partition
149
* param[in] flippedPartition The flipped partition
150
*/
151
void setFlippedPartition(const KDTreePartition<FlippedEdge<E, N, V>, FlippedNode<E, N, V>, V>* flippedPartition) {
152
myFlippedPartition = flippedPartition;
153
}
154
/** @brief Converts a partition level number to a SHARC level number
155
* @param[in] partitionLevel The partition level
156
* @return The SHARC level number corresponding to the given partition level number
157
*/
158
int partitionLevel2SHARCLevel(int partitionLevel) {
159
return AFRouter<E, N, V, M>::partitionLevel2SHARCLevel(partitionLevel, myNumberOfLevels);
160
}
161
/** @brief Converts a SHARC level number to a partition level number
162
* @param[in] sHARCLevel The SHARC level
163
* @return The partition level number corresponding to the given SHARC level number
164
*/
165
int sHARCLevel2PartitionLevel(int sHARCLevel) {
166
return AFRouter<E, N, V, M>::sHARCLevel2PartitionLevel(sHARCLevel, myNumberOfLevels);
167
}
168
169
protected:
170
/** @brief Computes the arc flags for all cells at a given level
171
* @param[in] msTime The start time of the routes in milliseconds
172
* @param[in] sHARCLevel The SHARC level
173
* @param[in] vehicle The vehicle
174
*/
175
void computeArcFlags(SUMOTime msTime, int sHARCLevel, const V* const vehicle);
176
/** @brief Computes the arc flags for a given cell
177
* @param[in] msTime The start time of the routes in milliseconds
178
* @param sHARCLevel The SHARC level
179
* @param[in] cell The cell
180
* @param[in] vehicle The vehicle
181
*/
182
void computeArcFlags(SUMOTime msTime, const int sHARCLevel, const Cell* cell, const V* const vehicle);
183
/** @brief Computes the arc flags for a given cell (naive version)
184
* @param[in] msTime The start time of the routes in milliseconds
185
* @param sHARCLevel The SHARC level
186
* @param[in] cell The cell
187
* @param[in] vehicle The vehicle
188
*/
189
void computeArcFlagsNaive(SUMOTime msTime, const int sHARCLevel, const Cell* cell, const V* const vehicle);
190
/** @brief Put the arc flag of the edge in arcInfo
191
* @note wrt the passed SHARC level, and the boolean flag indicating whether the respective cell is a left or lower one or not
192
* @param[in] arcInfo The arc information
193
* @param[in] sHARCLevel The SHARC level
194
* @param[in] isLeftOrLowerCell The boolean flag indicating whether the respective cell is a left or lower one or not
195
*/
196
void putArcFlag(ArcInfo* arcInfo, const int sHARCLevel, const bool isLeftOrLowerCell);
197
/// @brief The flipped edges
198
const std::vector<FlippedEdge<E, N, V>*>& myFlippedEdges;
199
/// @brief The partition for the backward graph with flipped edges
200
const KDTreePartition<FlippedEdge<E, N, V>, FlippedNode<E, N, V>, V>* myFlippedPartition;
201
/// @brief The number of levels
202
const int myNumberOfLevels;
203
/// @brief The handler for routing errors
204
MsgHandler* const myErrorMsgHandler;
205
/// @brief The object's operation to perform on a backward graph with flipped edges
206
typename SUMOAbstractRouter<FlippedEdge<E, N, V>, V>::Operation myFlippedOperation;
207
/// @brief The lookup table for travel time heuristics
208
const std::shared_ptr<const FlippedLookupTable> myFlippedLookupTable;
209
/// @brief The boolean flag indicating whether edge permissions need to be considered or not
210
const bool myHavePermissions;
211
/// @brief The boolean flag indicating whether edge restrictions need to be considered or not
212
const bool myHaveRestrictions;
213
/// @brief The list of explicitly prohibited edges
214
const std::map<const FlippedEdge<E, N, V>*, RouterProhibition>* myProhibited;
215
/// @brief The node-to-edge router (for a backward graph with flipped edges)
216
Node2EdgeRouter<FlippedEdge<E, N, V>, FlippedNode<E, N, V>, V, M>* myNode2EdgeRouter;
217
/// @brief A Dijkstra based centralized label-correcting algorithm
218
// @note Builds shortest path trees for all boundary nodes at once
219
// @note It operates on a backward graph with flipped edges
220
AFCentralizedSPTree<FlippedEdge<E, N, V>, FlippedNode<E, N, V>, V>* myCentralizedSPTree;
221
/// @brief The container of arc informations (for the centralized shortest path tree)
222
std::vector<ArcInfo*> myArcInfos;
223
224
private:
225
/** @brief Initialize the boundary edges
226
* param[in] boundaryEdges The boundary edges
227
*/
228
void initBoundaryEdges(const std::unordered_set<const FlippedEdge<E, N, V>*>& boundaryEdges);
229
/** @brief Initialize the supercell edges
230
* @param[in] supercell The supercell
231
* @param[in] boundaryEdges The boundary edges
232
* @param[in] numberOfBoundaryNodes The number of boundary nodes
233
*/
234
void initSupercellEdges(const Cell* supercell,
235
const std::unordered_set<const FlippedEdge<E, N, V>*>& boundaryEdges,
236
size_t numberOfBoundaryNodes);
237
/** @brief Helper method for computeArcFlags(), which computes the arc flags for a given cell
238
* @param[in] msTime The start time of the routes in milliseconds
239
* @param[in] sHARCLevel The SHARC level
240
* @param[in] cell The cell
241
* @param[in] vehicle The vehicle
242
*/
243
void computeArcFlagsAux(SUMOTime msTime, const int sHARCLevel, const Cell* cell, const V* const vehicle);
244
}; // end of class AFBuild declaration
245
246
// ===========================================================================
247
// method definitions
248
// ===========================================================================
249
250
template<class E, class N, class V, class M>
251
void AFBuild<E, N, V, M>::init(SUMOTime msTime, const V* const vehicle, std::vector<FlagInfo*>& flagInfos) {
252
if (myArcInfos.empty()) {
253
for (const FlippedEdge<E, N, V>* const flippedEdge : myFlippedEdges) {
254
myArcInfos.push_back(new ArcInfo(flippedEdge));
255
}
256
}
257
int sHARCLevel;
258
for (sHARCLevel = 0; sHARCLevel < myNumberOfLevels - 1; sHARCLevel++) {
259
#ifdef AFBU_DEBUG_LEVEL_0
260
std::cout << "Starting computation of flags of level " << sHARCLevel << " (levels run from 0 to "
261
<< myNumberOfLevels - 2 << ")." << std::endl;
262
#endif
263
#ifdef AFBU_DEBUG_LEVEL_2
264
if (sHARCLevel != 0) {
265
continue;
266
}
267
#endif
268
computeArcFlags(msTime, sHARCLevel, vehicle);
269
}
270
#ifdef AFBU_DEBUG_LEVEL_0
271
std::cout << "Copying arc flags from the arc infos... " << std::endl;
272
#endif
273
int index = 0;
274
for (const ArcInfo* arcInfo : myArcInfos) {
275
flagInfos[index++]->arcFlags = arcInfo->arcFlags;
276
delete arcInfo;
277
}
278
#ifdef AFBU_DEBUG_LEVEL_0
279
std::cout << "Arc flags copied from the arc infos. " << std::endl;
280
#endif
281
myArcInfos.clear();
282
}
283
284
template<class E, class N, class V, class M>
285
void AFBuild<E, N, V, M>::computeArcFlags(SUMOTime msTime, const int sHARCLevel, const V* const vehicle) {
286
try {
287
assert(myFlippedPartition);
288
const std::vector<const Cell*>& levelCells = myFlippedPartition->getCellsAtLevel(sHARCLevel2PartitionLevel(sHARCLevel));
289
#ifdef AFBU_DEBUG_LEVEL_0
290
int i = 0;
291
#endif
292
for (const Cell* cell : levelCells) {
293
#ifdef AFBU_DEBUG_LEVEL_0
294
std::cout << "Starting to compute core flags of the " << i++ << "th cell..." << std::endl;
295
#endif
296
#ifdef AFBU_DEBUG_LEVEL_2
297
if (cell->getNumber() == 4) {
298
#endif
299
// kept to make comparisons possible
300
//computeArcFlagsNaive(msTime, sHARCLevel, cell, vehicle);
301
computeArcFlags(msTime, sHARCLevel, cell, vehicle);
302
// clean up (all except the computed flags, of course)
303
#ifdef AFBU_DEBUG_LEVEL_0
304
std::cout << "Cleaning up after computeArcFlags..." << std::endl;
305
#endif
306
for (ArcInfo* arcInfo : myArcInfos) {
307
arcInfo->effortsToBoundaryNodes.clear();
308
arcInfo->touched = false;
309
}
310
#ifdef AFBU_DEBUG_LEVEL_0
311
std::cout << "Cleaned up." << std::endl;
312
#endif
313
#ifdef AFBU_DEBUG_LEVEL_2
314
}
315
#endif
316
}
317
} catch (const std::invalid_argument& e) {
318
std::cerr << "Exception: " << e.what() << std::endl;
319
exit(-1);
320
}
321
}
322
323
template<class E, class N, class V, class M>
324
void AFBuild<E, N, V, M>::computeArcFlagsNaive(SUMOTime msTime, const int sHARCLevel, const Cell* cell, const V* const vehicle) {
325
const Cell* supercell = cell->getSupercell();
326
const std::unordered_set<const FlippedEdge<E, N, V>*>& boundaryEdges = cell->getOutgoingBoundaryEdges();
327
const std::vector<const FlippedNode<E, N, V>*>& boundaryNodes = cell->getBoundaryFromNodes();
328
#ifdef AFBU_DEBUG_LEVEL_1
329
std::cout << "Number of boundary edges: " << boundaryEdges.size() << std::endl;
330
std::cout << "Number of boundary nodes: " << boundaryNodes.size() << std::endl;
331
std::cout << "Cell number: " << cell->getNumber() << std::endl;
332
std::cout << "Supercell number: " << supercell->getNumber() << std::endl;
333
#endif
334
//
335
// initialization of arc flag vectors
336
initBoundaryEdges(boundaryEdges);
337
338
#ifdef AFBU_DEBUG_LEVEL_0
339
long long int startTime = SysUtils::getCurrentMillis();
340
#endif
341
for (const FlippedNode<E, N, V>* boundaryNode : boundaryNodes) {
342
for (const FlippedEdge<E, N, V>* boundaryEdge : boundaryEdges) {
343
assert(!boundaryEdge->isInternal());
344
ArcInfo* arcInfo = myArcInfos[boundaryEdge->getNumericalID()];
345
if (boundaryNode == boundaryEdge->getFromJunction()) {
346
arcInfo->effortsToBoundaryNodes.push_back(0.);
347
continue;
348
}
349
// compute effort
350
std::vector<const FlippedEdge<E, N, V>*> into;
351
#ifdef AFBU_DEBUG_LEVEL_2
352
std::vector<const FlippedEdge<E, N, V>*> into2;
353
#endif
354
if (myNode2EdgeRouter->computeNode2Edge(boundaryNode, boundaryEdge, vehicle, msTime, into)) {
355
double recomputedEffort = myNode2EdgeRouter->recomputeCostsNoLastEdge(into, vehicle, msTime);
356
arcInfo->effortsToBoundaryNodes.push_back(recomputedEffort);
357
#ifdef AFBU_DEBUG_LEVEL_2
358
if (!into.empty() && myNode2EdgeRouter->compute(into[0], boundaryEdge, vehicle, msTime, into2)) {
359
double recomputedEffort2 = myNode2EdgeRouter->recomputeCosts(into2, vehicle, msTime);
360
361
std::cout << "node2Edge router succeeded, effort: " << recomputedEffort << ", effort incl. last edge: " << recomputedEffort2 << std::endl;
362
assert(recomputedEffort <= recomputedEffort2);
363
}
364
#endif
365
} else {
366
arcInfo->effortsToBoundaryNodes.push_back(UNREACHABLE);
367
#ifdef AFBU_DEBUG_LEVEL_2
368
std::cout << "UNREACHABLE!" << std::endl;
369
#endif
370
}
371
}
372
}
373
#ifdef AFBU_DEBUG_LEVEL_0
374
long long int timeSpent = SysUtils::getCurrentMillis() - startTime;
375
std::cout << "Initial distance computation spent " + elapsedMs2string(timeSpent) + "." << std::endl;
376
#endif
377
378
// initialize all supercell edges' labels, arc flag vectors for the centralized shortest path tree algorithm / arc flag build
379
initSupercellEdges(supercell, boundaryEdges, boundaryNodes.size());
380
#ifdef AFBU_DEBUG_LEVEL_0
381
std::cout << "Initialization of all supercell edges' labels and arc flag vectors done. Starting the centralized shortest path tree algorithm..." << std::endl;
382
#endif
383
if (myCentralizedSPTree->computeCentralizedSPTree(msTime, cell, vehicle)) {
384
computeArcFlagsAux(msTime, sHARCLevel, cell, vehicle);
385
}
386
#ifdef AFBU_DEBUG_LEVEL_0
387
std::cout << "Centralized shortest path tree algorithm finished." << std::endl;
388
#endif
389
}
390
391
template<class E, class N, class V, class M>
392
void AFBuild<E, N, V, M>::computeArcFlags(SUMOTime msTime, const int sHARCLevel, const Cell* cell, const V* const vehicle) {
393
const Cell* supercell = cell->getSupercell();
394
const std::unordered_set<const FlippedEdge<E, N, V>*>& boundaryEdges = cell->getOutgoingBoundaryEdges();
395
const std::vector<const FlippedNode<E, N, V>*>& boundaryNodes = cell->getBoundaryFromNodes();
396
#ifdef AFBU_DEBUG_LEVEL_1
397
std::cout << "Number of boundary edges: " << boundaryEdges.size() << std::endl;
398
std::cout << "Number of boundary nodes: " << boundaryNodes.size() << std::endl;
399
std::cout << "Cell number: " << cell->getNumber() << std::endl;
400
std::cout << "Supercell number: " << supercell->getNumber() << std::endl;
401
#endif
402
// initialization of arc flag vectors
403
initBoundaryEdges(boundaryEdges);
404
#ifdef AFBU_DEBUG_LEVEL_1
405
long long int startTime = SysUtils::getCurrentMillis();
406
#endif
407
std::map<const FlippedEdge<E, N, V>*, std::vector<const FlippedEdge<E, N, V>*>> incomingEdgesOfOutgoingBoundaryEdges;
408
size_t numberOfBoundaryNodes = boundaryNodes.size();
409
for (const FlippedEdge<E, N, V>* boundaryEdge : boundaryEdges) {
410
incomingEdgesOfOutgoingBoundaryEdges[boundaryEdge] = std::vector<const FlippedEdge<E, N, V>*>(numberOfBoundaryNodes);
411
}
412
int index = 0; // boundary node index
413
for (const FlippedNode<E, N, V>* boundaryNode : boundaryNodes) {
414
myNode2EdgeRouter->reset(vehicle);
415
if (myNode2EdgeRouter->computeNode2Edges(boundaryNode, boundaryEdges, vehicle, msTime)) {
416
#ifdef AFBU_DEBUG_LEVEL_2
417
std::cout << "Node-to-edge router succeeded." << std::endl;
418
#endif
419
}
420
for (const FlippedEdge<E, N, V>* boundaryEdge : boundaryEdges) {
421
assert(!boundaryEdge->isInternal());
422
ArcInfo* arcInfo = myArcInfos[boundaryEdge->getNumericalID()];
423
if (boundaryNode == boundaryEdge->getFromJunction()) {
424
arcInfo->effortsToBoundaryNodes.push_back(0.);
425
(incomingEdgesOfOutgoingBoundaryEdges[boundaryEdge])[index] = nullptr;
426
continue;
427
}
428
double effort = (myNode2EdgeRouter->edgeInfo(boundaryEdge))->effort;
429
const FlippedEdge<E, N, V>* incomingEdge
430
= (myNode2EdgeRouter->edgeInfo(boundaryEdge))->prev ?
431
(myNode2EdgeRouter->edgeInfo(boundaryEdge))->prev->edge : nullptr;
432
(incomingEdgesOfOutgoingBoundaryEdges[boundaryEdge])[index] = incomingEdge;
433
arcInfo->effortsToBoundaryNodes.push_back(effort == std::numeric_limits<double>::max() ? UNREACHABLE : effort);
434
}
435
index++;
436
} // end for boundary nodes
437
#ifdef AFBU_DEBUG_LEVEL_0
438
long long int timeSpent = SysUtils::getCurrentMillis() - startTime;
439
std::cout << "Initial distance computation spent " + elapsedMs2string(timeSpent) + "." << std::endl;
440
#endif
441
// initialize all supercell edges' labels and arc flag vectors for the centralized shortest path DAG algorithm / arc flag build
442
initSupercellEdges(supercell, boundaryEdges, boundaryNodes.size());
443
#ifdef AFBU_DEBUG_LEVEL_0
444
std::cout << "Initialization of all supercell edges' labels and arc flag vectors done. Starting the centralized shortest path tree algorithm..." << std::endl;
445
#endif
446
#ifdef AFBU_DEBUG_LEVEL_0
447
startTime = SysUtils::getCurrentMillis();
448
#endif
449
if (myCentralizedSPTree->computeCentralizedSPTree(msTime, cell, vehicle, incomingEdgesOfOutgoingBoundaryEdges)) {
450
#ifdef AFBU_DEBUG_LEVEL_0
451
timeSpent = SysUtils::getCurrentMillis() - startTime;
452
std::cout << "Centralized SP tree computation spent " + elapsedMs2string(timeSpent) + "." << std::endl;
453
#endif
454
computeArcFlagsAux(msTime, sHARCLevel, cell, vehicle);
455
}
456
#ifdef AFBU_DEBUG_LEVEL_0
457
std::cout << "Centralized shortest path tree algorithm finished." << std::endl;
458
#endif
459
}
460
461
template<class E, class N, class V, class M>
462
void AFBuild<E, N, V, M>::computeArcFlagsAux(SUMOTime msTime, const int sHARCLevel, const Cell* cell, const V* const vehicle) {
463
const Cell* supercell = cell->getSupercell();
464
std::pair<typename std::vector<const FlippedNode<E, N, V>*>::const_iterator,
465
typename std::vector<const FlippedNode<E, N, V>*>::const_iterator> supercellNodeIterators = supercell->nodeIterators();
466
typename std::vector<const FlippedNode<E, N, V>*>::const_iterator first = supercellNodeIterators.first;
467
typename std::vector<const FlippedNode<E, N, V>*>::const_iterator last = supercellNodeIterators.second;
468
typename std::vector<const FlippedNode<E, N, V>*>::const_iterator iter;
469
std::unordered_set<ArcInfo*> arcInfosOnAShortestPath;
470
#ifdef AFBU_DEBUG_LEVEL_1
471
int numberOfSupercellEdges = 0;
472
#endif
473
for (iter = first; iter != last; iter++) {
474
const std::vector<const FlippedEdge<E, N, V>*> incomingEdges = (*iter)->getIncoming();
475
for (const FlippedEdge<E, N, V>* supercellEdge : incomingEdges) {
476
if (supercellEdge->isInternal()) {
477
continue;
478
}
479
if (myNode2EdgeRouter->isProhibited(supercellEdge, vehicle, STEPS2TIME(msTime))) {
480
continue;
481
}
482
#ifdef AFBU_DEBUG_LEVEL_1
483
numberOfSupercellEdges++;
484
#endif
485
ArcInfo* supercellArcInfo = myArcInfos[supercellEdge->getNumericalID()];
486
// start by initializing to set of all supercell edge arc infos
487
arcInfosOnAShortestPath.insert(supercellArcInfo);
488
}
489
}
490
#ifdef AFBU_DEBUG_LEVEL_1
491
std::cout << "Number of supercell edges: " << numberOfSupercellEdges << std::endl;
492
#endif
493
const SUMOVehicleClass vClass = vehicle == 0 ? SVC_IGNORING : vehicle->getVClass();
494
#ifdef AFBU_DEBUG_LEVEL_1
495
std::cout << "Identifying shortest paths..." << std::endl;
496
#endif
497
#ifdef AFBU_DEBUG_LEVEL_0
498
long long int startTime = SysUtils::getCurrentMillis();
499
#endif
500
std::unordered_set<ArcInfo*> erasedEdges;
501
for (auto iter2 = arcInfosOnAShortestPath.begin(); iter2 != arcInfosOnAShortestPath.end();) {
502
const ArcInfo* arcInfo = *iter2;
503
assert(!arcInfo->edge->isInternal());
504
assert(myNode2EdgeRouter);
505
assert(!myNode2EdgeRouter->isProhibited(arcInfo->edge, vehicle, STEPS2TIME(msTime)));
506
size_t numberOfBoundaryNodes = arcInfo->effortsToBoundaryNodes.size();
507
size_t index;
508
bool onShortestPath = false;
509
// attempt to prove that the edge is on a shortest path for at least one boundary node
510
for (index = 0; index < numberOfBoundaryNodes; index++) {
511
double effort1ToBoundaryNode = arcInfo->effortsToBoundaryNodes[index];
512
if (effort1ToBoundaryNode == UNREACHABLE) {
513
continue;
514
}
515
if (effort1ToBoundaryNode == std::numeric_limits<double>::max()) {
516
continue;
517
}
518
double sTime = STEPS2TIME(msTime);
519
double edgeEffort = myNode2EdgeRouter->getEffort(arcInfo->edge, vehicle, sTime);
520
sTime += myNode2EdgeRouter->getTravelTime(arcInfo->edge, vehicle, sTime, edgeEffort);
521
double oldEdgeEffort = edgeEffort;
522
double oldSTime = sTime;
523
524
for (const std::pair<const FlippedEdge<E, N, V>*, const FlippedEdge<E, N, V>*>& follower : arcInfo->edge->getViaSuccessors(vClass)) {
525
assert(!follower.first->isInternal());
526
ArcInfo* followerInfo = myArcInfos[follower.first->getNumericalID()];
527
528
// check whether it can be used
529
if (myNode2EdgeRouter->isProhibited(follower.first, vehicle, sTime)) {
530
myErrorMsgHandler->inform("Vehicle '" + Named::getIDSecure(vehicle) + "' is not allowed on source edge '" + followerInfo->edge->getID() + "'.");
531
continue;
532
}
533
if (followerInfo->effortsToBoundaryNodes.empty()) {
534
continue;
535
}
536
double effort2ToBoundaryNode = followerInfo->effortsToBoundaryNodes[index];
537
if (effort2ToBoundaryNode == UNREACHABLE) {
538
continue;
539
}
540
if (effort2ToBoundaryNode == std::numeric_limits<double>::max()) {
541
continue;
542
}
543
544
// add via efforts to current follower to edge effort
545
double length = 0.; // dummy length for call of updateViaEdgeCost
546
myNode2EdgeRouter->updateViaEdgeCost(follower.second, vehicle,
547
sTime /* has been updated to the time where the edge has been traversed */, edgeEffort, length);
548
// test whether edge is on a shortest path to a boundary node
549
if (effort1ToBoundaryNode + edgeEffort /* edge effort incl. via efforts to current follower of edge */
550
<= effort2ToBoundaryNode /* efforts incl. via efforts to current follower o. e. */
551
+ EPS && effort1ToBoundaryNode + edgeEffort >= effort2ToBoundaryNode - EPS) {
552
onShortestPath = true;
553
break; // a shortest path to one boundary node suffices
554
}
555
edgeEffort = oldEdgeEffort;
556
sTime = oldSTime;
557
} // end of loop over outgoing edges
558
} // loop over indexes
559
if (!onShortestPath) {
560
erasedEdges.insert(*iter2);
561
iter2 = arcInfosOnAShortestPath.erase(iter2); // not on a shortest path, remove it
562
} else {
563
++iter2;
564
}
565
} // loop over edge infos
566
567
#ifdef AFBU_DEBUG_LEVEL_0
568
std::cout << "Edges clearly not on a shortest path have been removed. Number of edges on a shortest path is now: "
569
<< arcInfosOnAShortestPath.size() << std::endl;
570
#endif
571
572
// set arc flags (for level sHARCLevel) for all edges completely inside the cell
573
// (done since these edges all have a to-node inside the cell, i.e. we have to set the own-cell flag for them).
574
std::unordered_set<const FlippedEdge<E, N, V>*>* pEdgesInsideCell = cell->edgeSet(vehicle);
575
std::unordered_set<const FlippedEdge<E, N, V>*> edgesInsideCell = *pEdgesInsideCell;
576
#ifdef AFBU_DEBUG_LEVEL_0
577
std::cout << "Adding all edges completely inside the cell to set of edges on a shortest path, cell no:"
578
<< cell->getNumber() << std::endl;
579
#endif
580
for (const FlippedEdge<E, N, V>* edgeInsideCell : edgesInsideCell) {
581
ArcInfo* arcInfo = myArcInfos[edgeInsideCell->getNumericalID()];
582
if (myNode2EdgeRouter->isProhibited(edgeInsideCell, vehicle, STEPS2TIME(msTime))) {
583
continue;
584
}
585
arcInfosOnAShortestPath.insert(arcInfo);
586
}
587
delete pEdgesInsideCell;
588
#ifdef AFBU_DEBUG_LEVEL_0
589
std::cout << "Edges inside cell added." << std::endl;
590
long long int timeSpent = SysUtils::getCurrentMillis() - startTime;
591
std::cout << "Shortest path identification spent " + elapsedMs2string(timeSpent) + "." << std::endl;
592
#endif
593
594
#ifdef AFBU_WRITE_QGIS_FILTERS
595
std::string qgisFilterString = "id IN (";
596
std::unordered_set<const FlippedNode<E, N, V>*> nodesOnAShortestPath;
597
std::unordered_set<const FlippedNode<E, N, V>*> erasedNodes;
598
for (const ArcInfo* arcInfo : arcInfosOnAShortestPath) {
599
assert(!(myNode2EdgeRouter->edgeInfo(arcInfo->edge))->prohibited
600
&& !myNode2EdgeRouter->isProhibited(arcInfo->edge, vehicle));
601
nodesOnAShortestPath.insert(arcInfo->edge->getFromJunction());
602
nodesOnAShortestPath.insert(arcInfo->edge->getToJunction());
603
}
604
for (const ArcInfo* erasedEdgeArcInfo : erasedEdges) {
605
erasedNodes.insert(erasedEdgeArcInfo->edge->getFromJunction());
606
erasedNodes.insert(erasedEdgeArcInfo->edge->getToJunction());
607
}
608
size_t k = 0;
609
// go through the relevant nodes of the supercell
610
size_t numberOfNodesOnAShortestPath = nodesOnAShortestPath.size();
611
for (const FlippedNode<E, N, V>* node : nodesOnAShortestPath) {
612
k++;
613
qgisFilterString += node->getID() + (k < numberOfNodesOnAShortestPath ? ", " : "");
614
}
615
qgisFilterString += ")";
616
std::ostringstream pathAndFileName;
617
pathAndFileName << "./filter_superset_nodes_cell_" << cell->getNumber() << "_supercell_" << supercell->getNumber() << ".qqf";
618
std::ofstream file;
619
file.open(pathAndFileName.str());
620
std::ostringstream content;
621
content << "<Query>" << qgisFilterString << "</Query>";
622
file << content.str();
623
file.close();
624
// erased nodes
625
k = 0;
626
qgisFilterString.clear();
627
qgisFilterString = "id IN (";
628
// go through the erased nodes of the supercell
629
size_t numberOfErasedNodes = erasedNodes.size();
630
for (const FlippedNode<E, N, V>* node : erasedNodes) {
631
k++;
632
qgisFilterString += node->getID() + (k < numberOfErasedNodes ? ", " : "");
633
}
634
qgisFilterString += ")";
635
pathAndFileName.str("");
636
pathAndFileName.clear();
637
pathAndFileName << "./filter_erased_nodes_cell_" << cell->getNumber() << "_supercell_" << supercell->getNumber() << ".qqf";
638
file.clear();
639
file.open(pathAndFileName.str());
640
content.str("");
641
content.clear();
642
content << "<Query>" << qgisFilterString << "</Query>";
643
file << content.str();
644
file.close();
645
#endif
646
// put arc flags for level 'sHARCLevel' for all supercell edges which are on a shortest path
647
for (ArcInfo* arcInfo : arcInfosOnAShortestPath) {
648
putArcFlag(arcInfo, sHARCLevel, cell->isLeftOrLowerCell());
649
}
650
}
651
652
template<class E, class N, class V, class M>
653
void AFBuild<E, N, V, M>::putArcFlag(ArcInfo* arcInfo, const int sHARCLevel, const bool isLeftOrLowerCell) {
654
assert(arcInfo);
655
(arcInfo->arcFlags)[sHARCLevel * 2 + (isLeftOrLowerCell ? 0 : 1)] = 1;
656
}
657
658
template<class E, class N, class V, class M>
659
void AFBuild<E, N, V, M>::initBoundaryEdges(const std::unordered_set<const FlippedEdge<E, N, V>*>& boundaryEdges) {
660
// initialization of arc flag vectors
661
for (const FlippedEdge<E, N, V>* boundaryEdge : boundaryEdges) {
662
assert(!boundaryEdge->isInternal());
663
ArcInfo* arcInfo;
664
arcInfo = myArcInfos[boundaryEdge->getNumericalID()];
665
if (arcInfo->arcFlags.empty()) {
666
std::fill_n(std::back_inserter(arcInfo->arcFlags),
667
myFlippedPartition->numberOfArcFlags(), false);
668
}
669
arcInfo->effortsToBoundaryNodes.clear();
670
}
671
}
672
673
template<class E, class N, class V, class M>
674
void AFBuild<E, N, V, M>::initSupercellEdges(
675
const Cell* supercell,
676
const std::unordered_set<const FlippedEdge<E, N, V>*>& boundaryEdges,
677
size_t numberOfBoundaryNodes) {
678
std::pair<typename std::vector<const FlippedNode<E, N, V>*>::const_iterator,
679
typename std::vector<const FlippedNode<E, N, V>*>::const_iterator> supercellNodeIterators = supercell->nodeIterators();
680
typename std::vector<const FlippedNode<E, N, V>*>::const_iterator first = supercellNodeIterators.first;
681
typename std::vector<const FlippedNode<E, N, V>*>::const_iterator last = supercellNodeIterators.second;
682
typename std::vector<const FlippedNode<E, N, V>*>::const_iterator iter;
683
for (iter = first; iter != last; iter++) {
684
const std::vector<const FlippedEdge<E, N, V>*> incomingEdges = (*iter)->getIncoming();
685
for (const FlippedEdge<E, N, V>* supercellEdge : incomingEdges) {
686
if (supercellEdge->isInternal()) {
687
continue;
688
}
689
if (boundaryEdges.count(supercellEdge)) {
690
continue;
691
}
692
ArcInfo* supercellArcInfo;
693
supercellArcInfo = myArcInfos[supercellEdge->getNumericalID()];
694
if (supercellArcInfo->arcFlags.empty()) {
695
std::fill_n(std::back_inserter(supercellArcInfo->arcFlags),
696
myFlippedPartition->numberOfArcFlags(), false);
697
}
698
supercellArcInfo->effortsToBoundaryNodes.clear();
699
std::fill_n(std::back_inserter(supercellArcInfo->effortsToBoundaryNodes),
700
numberOfBoundaryNodes, std::numeric_limits<double>::max());
701
}
702
}
703
}
704
705