24#include <unordered_set>
40#ifdef AFBU_WRITE_QGIS_FILTERS
49#ifdef AFBU_DEBUG_LEVEL_2
50#define AFBU_DEBUG_LEVEL_1
53#ifdef AFBU_DEBUG_LEVEL_1
54#define AFBU_DEBUG_LEVEL_0
64template<
class E,
class N,
class V,
class M>
81template<
class E,
class N,
class V,
class M>
85 const double EPS = 0.009;
105 int numberOfLevels,
bool unbuildIsWarning,
107 const std::shared_ptr<const FlippedLookupTable> flippedLookup =
nullptr,
108 const bool havePermissions =
false,
const bool haveRestrictions =
false,
147 void init(
SUMOTime time,
const V*
const vehicle, std::vector<FlagInfo*>& flagInfos);
196 void putArcFlag(
ArcInfo* arcInfo,
const int sHARCLevel,
const bool isLeftOrLowerCell);
236 size_t numberOfBoundaryNodes);
250template<
class E,
class N,
class V,
class M>
252 if (myArcInfos.empty()) {
254 myArcInfos.push_back(
new ArcInfo(flippedEdge));
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;
263#ifdef AFBU_DEBUG_LEVEL_2
264 if (sHARCLevel != 0) {
268 computeArcFlags(msTime, sHARCLevel, vehicle);
270#ifdef AFBU_DEBUG_LEVEL_0
271 std::cout <<
"Copying arc flags from the arc infos... " << std::endl;
274 for (
const ArcInfo* arcInfo : myArcInfos) {
275 flagInfos[index++]->arcFlags = arcInfo->arcFlags;
278#ifdef AFBU_DEBUG_LEVEL_0
279 std::cout <<
"Arc flags copied from the arc infos. " << std::endl;
284template<
class E,
class N,
class V,
class M>
287 assert(myFlippedPartition);
288 const std::vector<const Cell*>& levelCells = myFlippedPartition->getCellsAtLevel(sHARCLevel2PartitionLevel(sHARCLevel));
289#ifdef AFBU_DEBUG_LEVEL_0
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;
296#ifdef AFBU_DEBUG_LEVEL_2
297 if (cell->getNumber() == 4) {
301 computeArcFlags(msTime, sHARCLevel, cell, vehicle);
303#ifdef AFBU_DEBUG_LEVEL_0
304 std::cout <<
"Cleaning up after computeArcFlags..." << std::endl;
306 for (
ArcInfo* arcInfo : myArcInfos) {
307 arcInfo->effortsToBoundaryNodes.clear();
308 arcInfo->touched =
false;
310#ifdef AFBU_DEBUG_LEVEL_0
311 std::cout <<
"Cleaned up." << std::endl;
313#ifdef AFBU_DEBUG_LEVEL_2
317 }
catch (
const std::invalid_argument& e) {
318 std::cerr <<
"Exception: " << e.what() << std::endl;
323template<
class E,
class N,
class V,
class M>
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;
336 initBoundaryEdges(boundaryEdges);
338#ifdef AFBU_DEBUG_LEVEL_0
343 assert(!boundaryEdge->isInternal());
344 ArcInfo* arcInfo = myArcInfos[boundaryEdge->getNumericalID()];
345 if (boundaryNode == boundaryEdge->getFromJunction()) {
350 std::vector<const FlippedEdge<E, N, V>*> into;
351#ifdef AFBU_DEBUG_LEVEL_2
352 std::vector<const FlippedEdge<E, N, V>*> into2;
354 if (myNode2EdgeRouter->computeNode2Edge(boundaryNode, boundaryEdge, vehicle, msTime, into)) {
355 double recomputedEffort = myNode2EdgeRouter->recomputeCostsNoLastEdge(into, vehicle, msTime);
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);
361 std::cout <<
"node2Edge router succeeded, effort: " << recomputedEffort <<
", effort incl. last edge: " << recomputedEffort2 << std::endl;
362 assert(recomputedEffort <= recomputedEffort2);
367#ifdef AFBU_DEBUG_LEVEL_2
368 std::cout <<
"UNREACHABLE!" << std::endl;
373#ifdef AFBU_DEBUG_LEVEL_0
375 std::cout <<
"Initial distance computation spent " +
elapsedMs2string(timeSpent) +
"." << std::endl;
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;
383 if (myCentralizedSPTree->computeCentralizedSPTree(msTime, cell, vehicle)) {
384 computeArcFlagsAux(msTime, sHARCLevel, cell, vehicle);
386#ifdef AFBU_DEBUG_LEVEL_0
387 std::cout <<
"Centralized shortest path tree algorithm finished." << std::endl;
391template<
class E,
class N,
class V,
class M>
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;
403 initBoundaryEdges(boundaryEdges);
404#ifdef AFBU_DEBUG_LEVEL_1
407 std::map<const FlippedEdge<E, N, V>*, std::vector<const FlippedEdge<E, N, V>*>> incomingEdgesOfOutgoingBoundaryEdges;
408 size_t numberOfBoundaryNodes = boundaryNodes.size();
410 incomingEdgesOfOutgoingBoundaryEdges[boundaryEdge] = std::vector<const FlippedEdge<E, N, V>*>(numberOfBoundaryNodes);
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;
421 assert(!boundaryEdge->isInternal());
422 ArcInfo* arcInfo = myArcInfos[boundaryEdge->getNumericalID()];
423 if (boundaryNode == boundaryEdge->getFromJunction()) {
425 (incomingEdgesOfOutgoingBoundaryEdges[boundaryEdge])[index] =
nullptr;
428 double effort = (myNode2EdgeRouter->edgeInfo(boundaryEdge))->effort;
430 = (myNode2EdgeRouter->edgeInfo(boundaryEdge))->prev ?
431 (myNode2EdgeRouter->edgeInfo(boundaryEdge))->prev->edge :
nullptr;
432 (incomingEdgesOfOutgoingBoundaryEdges[boundaryEdge])[index] = incomingEdge;
437#ifdef AFBU_DEBUG_LEVEL_0
439 std::cout <<
"Initial distance computation spent " +
elapsedMs2string(timeSpent) +
"." << std::endl;
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;
446#ifdef AFBU_DEBUG_LEVEL_0
449 if (myCentralizedSPTree->computeCentralizedSPTree(msTime, cell, vehicle, incomingEdgesOfOutgoingBoundaryEdges)) {
450#ifdef AFBU_DEBUG_LEVEL_0
452 std::cout <<
"Centralized SP tree computation spent " +
elapsedMs2string(timeSpent) +
"." << std::endl;
454 computeArcFlagsAux(msTime, sHARCLevel, cell, vehicle);
456#ifdef AFBU_DEBUG_LEVEL_0
457 std::cout <<
"Centralized shortest path tree algorithm finished." << std::endl;
461template<
class E,
class N,
class V,
class M>
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;
473 for (iter = first; iter != last; iter++) {
474 const std::vector<const FlippedEdge<E, N, V>*> incomingEdges = (*iter)->getIncoming();
476 if (supercellEdge->isInternal()) {
479 if (myNode2EdgeRouter->isProhibited(supercellEdge, vehicle,
STEPS2TIME(msTime))) {
482#ifdef AFBU_DEBUG_LEVEL_1
483 numberOfSupercellEdges++;
485 ArcInfo* supercellArcInfo = myArcInfos[supercellEdge->getNumericalID()];
487 arcInfosOnAShortestPath.insert(supercellArcInfo);
490#ifdef AFBU_DEBUG_LEVEL_1
491 std::cout <<
"Number of supercell edges: " << numberOfSupercellEdges << std::endl;
494#ifdef AFBU_DEBUG_LEVEL_1
495 std::cout <<
"Identifying shortest paths..." << std::endl;
497#ifdef AFBU_DEBUG_LEVEL_0
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)));
508 bool onShortestPath =
false;
510 for (index = 0; index < numberOfBoundaryNodes; index++) {
515 if (effort1ToBoundaryNode == std::numeric_limits<double>::max()) {
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;
525 assert(!follower.first->isInternal());
526 ArcInfo* followerInfo = myArcInfos[follower.first->getNumericalID()];
529 if (myNode2EdgeRouter->isProhibited(follower.first, vehicle, sTime)) {
530 myErrorMsgHandler->inform(
"Vehicle '" +
Named::getIDSecure(vehicle) +
"' is not allowed on source edge '" + followerInfo->
edge->getID() +
"'.");
540 if (effort2ToBoundaryNode == std::numeric_limits<double>::max()) {
546 myNode2EdgeRouter->updateViaEdgeCost(follower.second, vehicle,
547 sTime , edgeEffort, length);
549 if (effort1ToBoundaryNode + edgeEffort
550 <= effort2ToBoundaryNode
551 +
EPS && effort1ToBoundaryNode + edgeEffort >= effort2ToBoundaryNode -
EPS) {
552 onShortestPath =
true;
555 edgeEffort = oldEdgeEffort;
559 if (!onShortestPath) {
560 erasedEdges.insert(*iter2);
561 iter2 = arcInfosOnAShortestPath.erase(iter2);
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;
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;
581 ArcInfo* arcInfo = myArcInfos[edgeInsideCell->getNumericalID()];
582 if (myNode2EdgeRouter->isProhibited(edgeInsideCell, vehicle,
STEPS2TIME(msTime))) {
585 arcInfosOnAShortestPath.insert(arcInfo);
587 delete pEdgesInsideCell;
588#ifdef AFBU_DEBUG_LEVEL_0
589 std::cout <<
"Edges inside cell added." << std::endl;
591 std::cout <<
"Shortest path identification spent " +
elapsedMs2string(timeSpent) +
"." << std::endl;
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());
604 for (
const ArcInfo* erasedEdgeArcInfo : erasedEdges) {
605 erasedNodes.insert(erasedEdgeArcInfo->edge->getFromJunction());
606 erasedNodes.insert(erasedEdgeArcInfo->edge->getToJunction());
610 size_t numberOfNodesOnAShortestPath = nodesOnAShortestPath.size();
613 qgisFilterString += node->getID() + (k < numberOfNodesOnAShortestPath ?
", " :
"");
615 qgisFilterString +=
")";
616 std::ostringstream pathAndFileName;
617 pathAndFileName <<
"./filter_superset_nodes_cell_" << cell->getNumber() <<
"_supercell_" << supercell->getNumber() <<
".qqf";
619 file.open(pathAndFileName.str());
620 std::ostringstream content;
621 content <<
"<Query>" << qgisFilterString <<
"</Query>";
622 file << content.str();
626 qgisFilterString.clear();
627 qgisFilterString =
"id IN (";
629 size_t numberOfErasedNodes = erasedNodes.size();
632 qgisFilterString += node->getID() + (k < numberOfErasedNodes ?
", " :
"");
634 qgisFilterString +=
")";
635 pathAndFileName.str(
"");
636 pathAndFileName.clear();
637 pathAndFileName <<
"./filter_erased_nodes_cell_" << cell->getNumber() <<
"_supercell_" << supercell->getNumber() <<
".qqf";
639 file.open(pathAndFileName.str());
642 content <<
"<Query>" << qgisFilterString <<
"</Query>";
643 file << content.str();
647 for (
ArcInfo* arcInfo : arcInfosOnAShortestPath) {
648 putArcFlag(arcInfo, sHARCLevel, cell->isLeftOrLowerCell());
652template<
class E,
class N,
class V,
class M>
655 (arcInfo->
arcFlags)[sHARCLevel * 2 + (isLeftOrLowerCell ? 0 : 1)] = 1;
658template<
class E,
class N,
class V,
class M>
662 assert(!boundaryEdge->isInternal());
664 arcInfo = myArcInfos[boundaryEdge->getNumericalID()];
666 std::fill_n(std::back_inserter(arcInfo->
arcFlags),
667 myFlippedPartition->numberOfArcFlags(),
false);
673template<
class E,
class N,
class V,
class M>
675 const Cell* supercell,
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();
686 if (supercellEdge->isInternal()) {
689 if (boundaryEdges.count(supercellEdge)) {
693 supercellArcInfo = myArcInfos[supercellEdge->getNumericalID()];
694 if (supercellArcInfo->
arcFlags.empty()) {
695 std::fill_n(std::back_inserter(supercellArcInfo->
arcFlags),
696 myFlippedPartition->numberOfArcFlags(),
false);
700 numberOfBoundaryNodes, std::numeric_limits<double>::max());
std::string elapsedMs2string(long long int t)
convert ms to string for log output
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
Builds the flags for (multi-level) arc flag routing (Hilger et al.) in its multi-level variant (also ...
AFBuild(const std::vector< FlippedEdge< E, N, V > * > &flippedEdges, const KDTreePartition< FlippedEdge< E, N, V >, FlippedNode< E, N, V >, V > *const flippedPartition, int numberOfLevels, bool unbuildIsWarning, typename SUMOAbstractRouter< FlippedEdge< E, N, V >, V >::Operation flippedOperation, const std::shared_ptr< const FlippedLookupTable > flippedLookup=nullptr, const bool havePermissions=false, const bool haveRestrictions=false, const std::map< const FlippedEdge< E, N, V > *, RouterProhibition > *toProhibit=nullptr)
Constructor.
void initSupercellEdges(const Cell *supercell, const std::unordered_set< const FlippedEdge< E, N, V > * > &boundaryEdges, size_t numberOfBoundaryNodes)
Initialize the supercell edges.
void init(SUMOTime time, const V *const vehicle, std::vector< FlagInfo * > &flagInfos)
Initialize the arc flag build.
AFInfo< FlippedEdge< E, N, V > >::ArcInfo ArcInfo
std::vector< ArcInfo * > myArcInfos
The container of arc informations (for the centralized shortest path tree)
AFCentralizedSPTree< FlippedEdge< E, N, V >, FlippedNode< E, N, V >, V > * myCentralizedSPTree
A Dijkstra based centralized label-correcting algorithm.
SUMOAbstractRouter< FlippedEdge< E, N, V >, V >::Operation myFlippedOperation
The object's operation to perform on a backward graph with flipped edges.
MsgHandler *const myErrorMsgHandler
The handler for routing errors.
const std::shared_ptr< const FlippedLookupTable > myFlippedLookupTable
The lookup table for travel time heuristics.
const std::vector< FlippedEdge< E, N, V > * > & myFlippedEdges
The flipped edges.
SUMOAbstractRouter< FlippedEdge< E, N, V >, V >::Operation getFlippedOperation()
Returns the operation for a backward graph with flipped edges.
const int myNumberOfLevels
The number of levels.
AbstractLookupTable< FlippedEdge< E, N, V >, V > FlippedLookupTable
const std::map< const FlippedEdge< E, N, V > *, RouterProhibition > * myProhibited
The list of explicitly prohibited edges.
AFInfo< E >::FlagInfo FlagInfo
void computeArcFlagsAux(SUMOTime msTime, const int sHARCLevel, const Cell *cell, const V *const vehicle)
Helper method for computeArcFlags(), which computes the arc flags for a given cell.
void initBoundaryEdges(const std::unordered_set< const FlippedEdge< E, N, V > * > &boundaryEdges)
Initialize the boundary edges param[in] boundaryEdges The boundary edges.
int sHARCLevel2PartitionLevel(int sHARCLevel)
Converts a SHARC level number to a partition level number.
void setFlippedPartition(const KDTreePartition< FlippedEdge< E, N, V >, FlippedNode< E, N, V >, V > *flippedPartition)
Set the flipped partition param[in] flippedPartition The flipped partition.
const bool myHaveRestrictions
The boolean flag indicating whether edge restrictions need to be considered or not.
void putArcFlag(ArcInfo *arcInfo, const int sHARCLevel, const bool isLeftOrLowerCell)
Put the arc flag of the edge in arcInfo.
const KDTreePartition< FlippedEdge< E, N, V >, FlippedNode< E, N, V >, V > * myFlippedPartition
The partition for the backward graph with flipped edges.
KDTreePartition< FlippedEdge< E, N, V >, FlippedNode< E, N, V >, V >::Cell Cell
void computeArcFlagsNaive(SUMOTime msTime, const int sHARCLevel, const Cell *cell, const V *const vehicle)
Computes the arc flags for a given cell (naive version)
const std::shared_ptr< const FlippedLookupTable > getFlippedLookup()
Returns the lookup table for the backward graph with flipped edges.
void computeArcFlags(SUMOTime msTime, int sHARCLevel, const V *const vehicle)
Computes the arc flags for all cells at a given level.
const bool myHavePermissions
The boolean flag indicating whether edge permissions need to be considered or not.
const double EPS
Maximum difference of two path lengths considered to be equal.
int partitionLevel2SHARCLevel(int partitionLevel)
Converts a partition level number to a SHARC level number.
Node2EdgeRouter< FlippedEdge< E, N, V >, FlippedNode< E, N, V >, V, M > * myNode2EdgeRouter
The node-to-edge router (for a backward graph with flipped edges)
std::vector< bool > arcFlags
The arc flags.
std::vector< double > effortsToBoundaryNodes
The efforts to boundary nodes.
const E *const edge
The current edge.
static int sHARCLevel2PartitionLevel(int sHARCLevel, int numberOfPartitionLevels)
Converts a SHARC level number to a partition level number.
static int partitionLevel2SHARCLevel(int partitionLevel, int numberOfPartitionLevels)
Converts a partition level number to a SHARC level number.
The edge type representing backward edges with flipped nodes.
the node type representing nodes used for backward search
Partitions the router's network wrt a k-d tree subdivision scheme.
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
virtual void prohibit(const Prohibitions &toProhibit)
static long getCurrentMillis()
Returns the current time in milliseconds.
Prohibitions and their estimated end time.