50#define UNREACHABLE (std::numeric_limits<double>::max() / 1000.0)
51#define AFRO_WRITE_QGIS_FILTERS
58#ifdef AFRO_DEBUG_LEVEL_3
59#define AFRO_DEBUG_LEVEL_2
62#ifdef AFRO_DEBUG_LEVEL_2
63#define AFRO_DEBUG_LEVEL_1
66#ifdef AFRO_DEBUG_LEVEL_1
67#define AFRO_DEBUG_LEVEL_0
90template<
class E,
class N,
class V>
104 return &(this->
myEdgeInfos[edge->getNumericalID()]);
113 return &(this->
myEdgeInfos[edge->getNumericalID()]);
132 return edgeInfo1->
edge->getNumericalID() > edgeInfo2->
edge->getNumericalID();
152 bool unbuildIsWarning,
154 SUMOTime weightPeriod,
const std::shared_ptr<const LookupTable> lookup =
nullptr,
155 const std::shared_ptr<const FlippedLookupTable> flippedLookup =
nullptr,
156 const bool havePermissions =
false,
const bool haveRestrictions =
false) :
157 SUMOAbstractRouter<E, V>(
"arcFlagRouter", unbuildIsWarning, operation, nullptr, havePermissions, haveRestrictions),
165 flippedOperation, flippedLookup, havePermissions, haveRestrictions)),
171#ifdef AFRO_DEBUG_LEVEL_2
172 myFlagContextStartTime(0),
173 myFlagContextTimeSum(0),
177 for (
const E*
const edge : edges) {
196 const std::vector<E*>& edges,
198 bool unbuildIsWarning,
201 SUMOTime weightPeriod,
const std::shared_ptr<const LookupTable> lookup =
nullptr,
202 const std::shared_ptr<const FlippedLookupTable> flippedLookup =
nullptr,
203 const bool havePermissions =
false,
const bool haveRestrictions =
false) :
204 SUMOAbstractRouter<E, V>(
"arcFlagRouter", unbuildIsWarning, operation, nullptr, havePermissions, haveRestrictions),
212 flippedOperation, flippedLookup, havePermissions, haveRestrictions)),
218#ifdef AFRO_DEBUG_LEVEL_2
219 myFlagContextStartTime(0),
220 myFlagContextTimeSum(0),
224 for (
const auto&
edgeInfo : edgeInfos) {
243 std::vector<FlagInfo*>* flagInfos,
244 const std::shared_ptr<const LookupTable> lookup =
nullptr,
245 const bool havePermissions =
false,
const bool haveRestrictions =
false) :
246 SUMOAbstractRouter<E, V>(
"arcFlagRouterClone", unbuildIsWarning, operation, nullptr, havePermissions, haveRestrictions),
254 myType(
"arcFlagRouterClone"),
259#ifdef AFRO_DEBUG_LEVEL_2
260 myFlagContextStartTime(0),
261 myFlagContextTimeSum(0),
265 for (
const auto&
edgeInfo : edgeInfos) {
289 this->myOperation,
myBuilder->getArcFlagBuild()->getFlippedOperation(),
291 this->myHavePermissions, this->myHaveRestrictions);
302 if (partitionLevel <= 0) {
303 throw std::invalid_argument(
"partitionLevel2SHARCLevel: given partition level is zero (0) or below. This does not correspond to a valid SHARC level. Partition levels valid for conversion to SHARC levels go from one to number of partition levels minus one.");
306 if (partitionLevel > numberOfPartitionLevels - 1) {
307 throw std::invalid_argument(
"partitionLevel2SHARCLevel: given partition level exceeds the number of partition levels minus one. Most likely you did not start the partition level numbering at zero (0), which is required here.");
309 return (numberOfPartitionLevels - 1) - partitionLevel;
318 int numberOfSHARCLevels = numberOfPartitionLevels - 1;
319 if (sHARCLevel < 0) {
320 throw std::invalid_argument(
"sHARCLevel2PartitionLevel: given SHARC level is negative.");
324 if (sHARCLevel > numberOfSHARCLevels - 1) {
325 throw std::invalid_argument(
"sHARCLevel2PartitionLevel: given SHARC level exceeds the number of SHARC levels minus one. Most likely you did not start the SHARC level numbering at zero (0), which is required here.");
327 return numberOfSHARCLevels - sHARCLevel;
337 return flagInfo->
arcFlags.empty() ? true :
347 std::vector<bool>&
flags(
const E* edge);
352 virtual void reset(
const V*
const vehicle) {
357#ifdef AFRO_DEBUG_LEVEL_0
358 long long int firstCallStart = 0;
359 long long int firstCallTime = 0;
361 std::cout <<
"Calling arc flag router for the first time during current weight period (arc flags build). This might take a while... " << std::endl;
364#ifdef AFRO_DEBUG_LEVEL_0
366 std::cout <<
"Time spent for arc flags build: " <<
elapsedMs2string(firstCallTime) << std::endl;
379 std::tuple<int, int, bool>
flagContext(
const E* settledEdge,
const E* targetEdge);
381 std::tuple<int, int, bool>
flagContextNaive(
const E* settledEdge,
const E* targetEdge);
391 bool compute(
const E* from,
const E* to,
const V*
const vehicle,
392 SUMOTime msTime, std::vector<const E*>& into,
bool silent =
false) {
393 assert(from !=
nullptr && to !=
nullptr);
395 if (this->
myEdgeInfos[from->getNumericalID()].prohibited || this->isProhibited(from, vehicle)) {
401 if (this->
myEdgeInfos[to->getNumericalID()].prohibited || this->isProhibited(to, vehicle)) {
422 this->
init(from->getNumericalID(), msTime);
426 int numberOfFollowers = 0;
427 int numberOfAvoidedFollowers = 0;
428 int numberOfEmptyFlagVectors = 0;
430 const double speed = vehicle ==
nullptr ?
myMaxSpeed :
MIN2(vehicle->getMaxSpeed(),
myMaxSpeed * vehicle->getChosenSpeedFactor());
436 const E*
const minEdge = minimumInfo->edge;
441#ifdef AFRO_DEBUG_LEVEL_1
442 std::cout <<
"Found to, to->getID(): " << to->getID() << std::endl;
443 std::cout << static_cast<double>(numberOfFollowers - numberOfAvoidedFollowers) /
static_cast<double>(num_visited)
444 <<
" followers considered (out of " <<
static_cast<double>(numberOfFollowers) /
static_cast<double>(num_visited) <<
") on average." << std::endl;
445 std::cout << static_cast<double>(numberOfFollowers - numberOfAvoidedFollowers)
446 <<
" followers considered (out of " <<
static_cast<double>(numberOfFollowers) <<
")." << std::endl;
447 std::cout << numberOfEmptyFlagVectors <<
" out of " << numberOfFollowers <<
" flag vectors of followers were unassigned (i.e., empty)." << std::endl;
448 std::cout <<
"num_visited: " << num_visited << std::endl;
454 this->
myFound.push_back(minimumInfo);
455 minimumInfo->visited =
true;
457 const double effortDelta = this->
getEffort(minEdge, vehicle, minimumInfo->leaveTime);
458 const double leaveTime = minimumInfo->leaveTime + this->
getTravelTime(minEdge, vehicle, minimumInfo->leaveTime, effortDelta);
462 double heuristic_remaining = 0.;
463 double heuristicEffort = minimumInfo->effort + effortDelta + heuristic_remaining;
465 for (
const std::pair<const E*, const E*>& follower : minEdge->getViaSuccessors(vClass)) {
466 auto& followerInfo = this->
myEdgeInfos[follower.first->getNumericalID()];
467 const FlagInfo* followerFlagInfo = (*myFlagInfos)[follower.first->getNumericalID()];
469 if (followerInfo.prohibited || this->isProhibited(follower.first, vehicle)) {
473 if (followerFlagInfo->
arcFlags.empty()) {
474 numberOfEmptyFlagVectors++;
476#ifdef AFRO_DEBUG_LEVEL_2
481#ifdef AFRO_DEBUG_LEVEL_2
485 numberOfAvoidedFollowers++;
493 heuristic_remaining =
494 (
myLookupTable ==
nullptr ? minEdge->getDistanceTo(to) / speed :
495 myLookupTable->lowerBound(minEdge, to, speed, vehicle->getChosenSpeedFactor(),
496 minEdge->getMinimumTravelTime(
nullptr), to->getMinimumTravelTime(
nullptr)));
500 heuristicEffort += heuristic_remaining;
503 double effort = minimumInfo->effort + effortDelta;
504 double time = leaveTime;
506 const double oldEffort = followerInfo.effort;
507 if ((!followerInfo.visited || mayRevisit) && effort < oldEffort) {
508 followerInfo.effort = effort;
511 followerInfo.heuristicEffort =
MAX2(
MIN2(heuristicEffort, followerInfo.heuristicEffort), effort);
512 followerInfo.leaveTime = time;
513 followerInfo.prev = minimumInfo;
514 if (oldEffort == std::numeric_limits<double>::max()) {
518 auto fi = std::find(this->
myFrontierList.begin(), this->myFrontierList.end(), &followerInfo);
531#ifdef AFRO_DEBUG_LEVEL_1
532 std::cout <<
"Queue ran empty, no solution." << std::endl;
533 std::cout << static_cast<double>(numberOfFollowers - numberOfAvoidedFollowers) /
static_cast<double>(num_visited)
534 <<
" followers considered (out of " <<
static_cast<double>(numberOfFollowers) /
static_cast<double>(num_visited) <<
") on average." << std::endl;
535 std::cout << static_cast<double>(numberOfFollowers - numberOfAvoidedFollowers)
536 <<
" followers considered (out of " <<
static_cast<double>(numberOfFollowers) <<
")." << std::endl;
537 std::cout << numberOfEmptyFlagVectors <<
" out of " << numberOfFollowers <<
" flag vectors of followers were unassigned (i.e., empty)." << std::endl;
538 std::cout <<
"num_visited: " << num_visited << std::endl;
557 throw std::runtime_error(
"Bulk mode is not supported by the arc flag router.");
588#ifdef AFRO_DEBUG_LEVEL_2
590 long long int myFlagContextStartTime;
591 long long int myFlagContextTimeSum;
606template<
class E,
class N,
class V>
610 throw std::runtime_error(
"flag infos not initialized, call compute() at least once before calling flags().");
612 return ((*myFlagInfos)[edge->getNumericalID()])->arcFlags;
615template<
class E,
class N,
class V>
618 myTargetEdgeCellLevel0 =
nullptr;
619 for (
auto& edgeInfo : this->myFrontierList) {
622 this->myFrontierList.clear();
623 for (
auto& edgeInfo : this->myFound) {
626 this->myFound.clear();
629 auto& fromInfo = this->myEdgeInfos[edgeID];
630 fromInfo.heuristicEffort = 0.;
631 fromInfo.effort = 0.;
633 fromInfo.prev =
nullptr;
634 this->myFrontierList.push_back(&fromInfo);
638template<
class E,
class N,
class V>
640 assert(settledEdge !=
nullptr && targetEdge !=
nullptr);
642 for (sHARCLevel = 0; sHARCLevel < myPartition->getNumberOfLevels() - 1; sHARCLevel++) {
643 int partitionLevel = sHARCLevel2PartitionLevel(sHARCLevel, myPartition->getNumberOfLevels());
644 const std::vector<const Cell*>& levelCells = myPartition->getCellsAtLevel(partitionLevel);
645 typename std::vector<const Cell*>::const_iterator first = levelCells.begin();
646 typename std::vector<const Cell*>::const_iterator last = levelCells.end();
647 typename std::vector<const Cell*>::const_iterator iter;
648 const Cell* settledEdgeCell =
nullptr;
649 const Cell* targetEdgeCell =
nullptr;
651 for (iter = first; iter != last; iter++) {
653 if (!settledEdgeCell && (*iter)->
contains(settledEdge->getFromJunction())) {
654 settledEdgeCell = *iter;
656 if (!targetEdgeCell && (*iter)->
contains(targetEdge->getFromJunction())) {
657 targetEdgeCell = *iter;
659 if (settledEdgeCell && targetEdgeCell) {
663 assert(settledEdgeCell && targetEdgeCell);
666 settledEdgeCell == targetEdgeCell);
670 throw std::runtime_error(
"flagContext: relevant level could not be determined.");
673template<
class E,
class N,
class V>
675 assert(settledEdge !=
nullptr && targetEdge !=
nullptr);
677 const Cell* settledEdgeCell =
nullptr;
678 const Cell* targetEdgeCell =
nullptr;
679 if (myLastSettledEdgeCell
680 && myLastSettledEdgeCell->contains(settledEdge->getFromJunction())) {
684 return myLastFlagContext;
686 int numberOfPartitionLevels = myPartition->getNumberOfLevels();
687 if (numberOfPartitionLevels <= 4) {
688 int partitionLevel = sHARCLevel2PartitionLevel(sHARCLevel, myPartition->getNumberOfLevels());
689 const std::vector<const Cell*>& levelCells = myPartition->getCellsAtLevel(partitionLevel);
690 typename std::vector<const Cell*>::const_iterator first = levelCells.begin();
691 typename std::vector<const Cell*>::const_iterator last = levelCells.end();
692 typename std::vector<const Cell*>::const_iterator iter;
694 for (iter = first; iter != last; iter++) {
697 && (*iter)->
contains(settledEdge->getFromJunction())) {
698 settledEdgeCell = *iter;
700 if (!targetEdgeCell && myTargetEdgeCellLevel0) {
701 targetEdgeCell = myTargetEdgeCellLevel0;
702 }
else if (!targetEdgeCell
703 && (*iter)->
contains(targetEdge->getFromJunction())) {
704 myTargetEdgeCellLevel0 = *iter;
705 targetEdgeCell = myTargetEdgeCellLevel0;
707 if (settledEdgeCell && targetEdgeCell) {
708 assert(myTargetEdgeCellLevel0);
713 settledEdgeCell = myPartition->searchNode(settledEdge->getFromJunction());
714 if (!targetEdgeCell && myTargetEdgeCellLevel0) {
716 targetEdgeCell = myTargetEdgeCellLevel0;
717 }
else if (!targetEdgeCell) {
718 myTargetEdgeCellLevel0 = myPartition->searchNode(targetEdge->getFromJunction());
719 targetEdgeCell = myTargetEdgeCellLevel0;
722 assert(settledEdgeCell && targetEdgeCell);
728 myLastSettledEdgeCell = settledEdgeCell;
729 std::tuple<int, int, bool> flagContext = std::make_tuple(sHARCLevel, targetEdgeCell->
isLeftOrLowerCell() ? 0 : 1,
730 settledEdgeCell == targetEdgeCell);
731 myLastFlagContext = flagContext;
735template<
class E,
class N,
class V>
742template<
class E,
class N,
class V>
744 myQueryVisits += visits;
749template<
class E,
class N,
class V>
751 if (myNumQueries > 0) {
752 WRITE_MESSAGE(myType +
" answered " +
toString(myNumQueries) +
" queries and explored " +
toString((
double)myQueryVisits / (
double)myNumQueries) +
" edges on average.");
754#ifdef AFRO_DEBUG_LEVEL_2
760template<
class E,
class N,
class V>
765 myQueryStartTime = 0;
#define WRITE_MESSAGE(msg)
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
#define UNUSED_PARAMETER(x)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Builds arc flags for shortest path search with the arc flag router.
std::vector< bool > arcFlags
The arc flags.
bool operator()(const typename SUMOAbstractRouter< E, V >::EdgeInfo *edgeInfo1, const typename SUMOAbstractRouter< E, V >::EdgeInfo *edgeInfo2) const
Comparing method.
virtual SUMOAbstractRouter< E, V > * clone()
Cloning method.
bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)
Builds the route between the given edges using the minimum travel time param[in] from The from-/start...
SUMOTime myValidUntil
The validity duration of the current flag infos (exclusive)
void reportStatistics()
Report query time statistics.
long long int myQueryStartTime
The time spent querying in milliseconds.
void endQuery(int visits)
Stop timer for query time sum.
virtual void setBulkMode(const bool mode)
Bulk mode is not supported.
virtual void reset(const V *const vehicle)
Trigger arc flags rebuild.
EdgeInfoComparator myComparator
The comparator for edge information.
static bool flag(const FlagInfo *flagInfo, const std::tuple< int, int, bool > flagContext)
Returns the arc flag of the edge in flagInfo wrt flagContext.
std::tuple< int, int, bool > flagContextNaive(const E *settledEdge, const E *targetEdge)
Kept for runtime comparisons.
static int sHARCLevel2PartitionLevel(int sHARCLevel, int numberOfPartitionLevels)
Converts a SHARC level number to a partition level number.
long long int myNumQueries
const std::shared_ptr< const LookupTable > myLookupTable
The lookup table for travel time heuristics.
AbstractLookupTable< E, V > LookupTable
virtual ~AFRouter()
Destructor.
const std::string myType
The type of this router.
const Cell * myTargetEdgeCellLevel0
The cell of the target edge at SHARC level 0.
long long int myQueryVisits
Counters for performance logging.
static int partitionLevel2SHARCLevel(int partitionLevel, int numberOfPartitionLevels)
Converts a partition level number to a SHARC level number.
AFRouter(const std::vector< typename SUMOAbstractRouter< E, V >::EdgeInfo > &edgeInfos, const KDTreePartition< E, N, V > *partition, bool unbuildIsWarning, typename SUMOAbstractRouter< E, V >::Operation operation, std::vector< FlagInfo * > *flagInfos, const std::shared_ptr< const LookupTable > lookup=nullptr, const bool havePermissions=false, const bool haveRestrictions=false)
Special cloning constructor, only for time-independent instances which never rebuild arc infos.
SUMOAbstractRouter< E, V >::EdgeInfo * edgeInfo(const E *const edge)
Returns the edge information for the passed edge.
std::tuple< int, int, bool > myLastFlagContext
The last flag context.
void resetStatistics()
Reset query time statistics.
std::vector< FlagInfo * > * myFlagInfos
Edge infos containing the associated edge and its arc flags.
const SUMOAbstractRouter< E, V >::EdgeInfo * edgeInfo(const E *const edge) const
Returns the edge information for the passed edge.
std::vector< bool > & flags(const E *edge)
Returns the arc flags of the passed edge.
KDTreePartition< E, N, V >::Cell Cell
std::tuple< int, int, bool > flagContext(const E *settledEdge, const E *targetEdge)
Returns the flag context for a route query from given settled edge to the target edge.
AFInfo< E >::FlagInfo FlagInfo
long long int myQueryTimeSum
AFRouter(const std::vector< E * > &edges, const KDTreePartition< E, N, V > *partition, bool unbuildIsWarning, typename SUMOAbstractRouter< E, V >::Operation operation, typename SUMOAbstractRouter< FlippedEdge< E, N, V >, V >::Operation flippedOperation, SUMOTime weightPeriod, const std::shared_ptr< const LookupTable > lookup=nullptr, const std::shared_ptr< const FlippedLookupTable > flippedLookup=nullptr, const bool havePermissions=false, const bool haveRestrictions=false)
Constructor.
const KDTreePartition< E, N, V > * myPartition
The partition.
double myMaxSpeed
The maximum speed in the network.
void startQuery()
Start timer for query time sum.
const Cell * myLastSettledEdgeCell
The cell of the last settled edge.
AFBuilder< E, N, V > * myBuilder
The builder.
AFRouter(const std::vector< typename SUMOAbstractRouter< E, V >::EdgeInfo > &edgeInfos, const std::vector< E * > &edges, const KDTreePartition< E, N, V > *partition, bool unbuildIsWarning, typename SUMOAbstractRouter< E, V >::Operation operation, typename SUMOAbstractRouter< FlippedEdge< E, N, V >, V >::Operation flippedOperation, SUMOTime weightPeriod, const std::shared_ptr< const LookupTable > lookup=nullptr, const std::shared_ptr< const FlippedLookupTable > flippedLookup=nullptr, const bool havePermissions=false, const bool haveRestrictions=false)
"Normal" cloning constructor for uninitialized or time-dependent instances
void init(const int edgeID, const SUMOTime msTime)
Initialize the arc flag router param[in] edgeID The edge id(entifier) param[in] msTime The start time...
const SUMOTime myWeightPeriod
The validity duration of one weight interval.
AbstractLookupTable< FlippedEdge< E, N, V >, V > FlippedLookupTable
The edge type representing backward edges with flipped nodes.
Represents an element of the node partition (i.e. a node set)
bool contains(const N *node) const
Tests whether the given node belongs to the cell.
const Cell * getSupercell() const
Returns the supercell.
bool isLeftOrLowerCell() const
Returns the boolean flag indicating whether this cell is a left or lower cell or not.
Partitions the router's network wrt a k-d tree subdivision scheme.
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
void informf(const std::string &format, T value, Targs... Fargs)
adds a new formatted message
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
const E *const edge
The current edge.
double heuristicEffort
Estimated effort to reach the edge (effort + lower bound on remaining effort)
MsgHandler *const myErrorMsgHandler
the handler for routing errors
const bool myHavePermissions
whether edge permissions need to be considered
std::vector< typename SUMOAbstractRouter< E, V >::EdgeInfo > myEdgeInfos
The container of edge information.
double(* Operation)(const E *const, const V *const, double)
Type of the function that is used to retrieve the edge effort.
Operation myOperation
The object's operation to perform.
double getTravelTime(const E *const e, const V *const v, const double t, const double effort) const
double getEffort(const E *const e, const V *const v, double t) const
void updateViaEdgeCost(const E *viaEdge, const V *const v, double &time, double &effort, double &length) const
bool myAmClean
whether we are already initialized
const bool myHaveRestrictions
whether edge restrictions need to be considered
void buildPathFrom(const typename SUMOAbstractRouter< E, V >::EdgeInfo *rbegin, std::vector< const E * > &edges)
Builds the path from marked edges.
void endQuery(int visits)
std::vector< typename SUMOAbstractRouter< E, V >::EdgeInfo * > myFrontierList
A container for reusage of the min edge heap.
std::vector< typename SUMOAbstractRouter< E, V >::EdgeInfo * > myFound
list of visited Edges (for resetting)
static long getCurrentMillis()
Returns the current time in milliseconds.