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,
class M>
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#ifdef AFRO_DEBUG_LEVEL_1
427 int numberOfFollowers = 0;
428 int numberOfAvoidedFollowers = 0;
429 int numberOfEmptyFlagVectors = 0;
432 const double speed = vehicle ==
nullptr ?
myMaxSpeed :
MIN2(vehicle->getMaxSpeed(),
myMaxSpeed * vehicle->getChosenSpeedFactor());
438 const E*
const minEdge = minimumInfo->edge;
443#ifdef AFRO_DEBUG_LEVEL_1
444 std::cout <<
"Found to, to->getID(): " << to->getID() << std::endl;
445 std::cout << static_cast<double>(numberOfFollowers - numberOfAvoidedFollowers) /
static_cast<double>(num_visited)
446 <<
" followers considered (out of " <<
static_cast<double>(numberOfFollowers) /
static_cast<double>(num_visited) <<
") on average." << std::endl;
447 std::cout << static_cast<double>(numberOfFollowers - numberOfAvoidedFollowers)
448 <<
" followers considered (out of " <<
static_cast<double>(numberOfFollowers) <<
")." << std::endl;
449 std::cout << numberOfEmptyFlagVectors <<
" out of " << numberOfFollowers <<
" flag vectors of followers were unassigned (i.e., empty)." << std::endl;
450 std::cout <<
"num_visited: " << num_visited << std::endl;
456 this->
myFound.push_back(minimumInfo);
457 minimumInfo->visited =
true;
459 const double effortDelta = this->
getEffort(minEdge, vehicle, minimumInfo->leaveTime);
460 const double leaveTime = minimumInfo->leaveTime + this->
getTravelTime(minEdge, vehicle, minimumInfo->leaveTime, effortDelta);
464 double heuristic_remaining = 0.;
465 double heuristicEffort = minimumInfo->effort + effortDelta + heuristic_remaining;
467 for (
const std::pair<const E*, const E*>& follower : minEdge->getViaSuccessors(vClass)) {
468 auto& followerInfo = this->
myEdgeInfos[follower.first->getNumericalID()];
469 const FlagInfo* followerFlagInfo = (*myFlagInfos)[follower.first->getNumericalID()];
471 if (followerInfo.prohibited || this->isProhibited(follower.first, vehicle)) {
474#ifdef AFRO_DEBUG_LEVEL_1
476 if (followerFlagInfo->
arcFlags.empty()) {
477 numberOfEmptyFlagVectors++;
480#ifdef AFRO_DEBUG_LEVEL_2
485#ifdef AFRO_DEBUG_LEVEL_2
489#ifdef AFRO_DEBUG_LEVEL_1
490 numberOfAvoidedFollowers++;
499 heuristic_remaining =
500 (
myLookupTable ==
nullptr ? minEdge->getDistanceTo(to) / speed :
501 myLookupTable->lowerBound(minEdge, to, speed, vehicle->getChosenSpeedFactor(),
502 minEdge->getMinimumTravelTime(
nullptr), to->getMinimumTravelTime(
nullptr)));
506 heuristicEffort += heuristic_remaining;
509 double effort = minimumInfo->effort + effortDelta;
510 double time = leaveTime;
512 const double oldEffort = followerInfo.effort;
513 if ((!followerInfo.visited || mayRevisit) && effort < oldEffort) {
514 followerInfo.effort = effort;
517 followerInfo.heuristicEffort =
MAX2(
MIN2(heuristicEffort, followerInfo.heuristicEffort), effort);
518 followerInfo.leaveTime = time;
519 followerInfo.prev = minimumInfo;
520 if (oldEffort == std::numeric_limits<double>::max()) {
524 auto fi = std::find(this->
myFrontierList.begin(), this->myFrontierList.end(), &followerInfo);
537#ifdef AFRO_DEBUG_LEVEL_1
538 std::cout <<
"Queue ran empty, no solution." << std::endl;
539 std::cout << static_cast<double>(numberOfFollowers - numberOfAvoidedFollowers) /
static_cast<double>(num_visited)
540 <<
" followers considered (out of " <<
static_cast<double>(numberOfFollowers) /
static_cast<double>(num_visited) <<
") on average." << std::endl;
541 std::cout << static_cast<double>(numberOfFollowers - numberOfAvoidedFollowers)
542 <<
" followers considered (out of " <<
static_cast<double>(numberOfFollowers) <<
")." << std::endl;
543 std::cout << numberOfEmptyFlagVectors <<
" out of " << numberOfFollowers <<
" flag vectors of followers were unassigned (i.e., empty)." << std::endl;
544 std::cout <<
"num_visited: " << num_visited << std::endl;
563 throw std::runtime_error(
"Bulk mode is not supported by the arc flag router.");
594#ifdef AFRO_DEBUG_LEVEL_2
596 long long int myFlagContextStartTime;
597 long long int myFlagContextTimeSum;
612template<
class E,
class N,
class V,
class M>
616 throw std::runtime_error(
"flag infos not initialized, call compute() at least once before calling flags().");
618 return ((*myFlagInfos)[edge->getNumericalID()])->arcFlags;
621template<
class E,
class N,
class V,
class M>
624 myTargetEdgeCellLevel0 =
nullptr;
625 for (
auto& edgeInfo : this->myFrontierList) {
628 this->myFrontierList.clear();
629 for (
auto& edgeInfo : this->myFound) {
632 this->myFound.clear();
635 auto& fromInfo = this->myEdgeInfos[edgeID];
636 fromInfo.heuristicEffort = 0.;
637 fromInfo.effort = 0.;
639 fromInfo.prev =
nullptr;
640 this->myFrontierList.push_back(&fromInfo);
644template<
class E,
class N,
class V,
class M>
646 assert(settledEdge !=
nullptr && targetEdge !=
nullptr);
648 for (sHARCLevel = 0; sHARCLevel < myPartition->getNumberOfLevels() - 1; sHARCLevel++) {
649 int partitionLevel = sHARCLevel2PartitionLevel(sHARCLevel, myPartition->getNumberOfLevels());
650 const std::vector<const Cell*>& levelCells = myPartition->getCellsAtLevel(partitionLevel);
651 typename std::vector<const Cell*>::const_iterator first = levelCells.begin();
652 typename std::vector<const Cell*>::const_iterator last = levelCells.end();
653 typename std::vector<const Cell*>::const_iterator iter;
654 const Cell* settledEdgeCell =
nullptr;
655 const Cell* targetEdgeCell =
nullptr;
657 for (iter = first; iter != last; iter++) {
659 if (!settledEdgeCell && (*iter)->
contains(settledEdge->getFromJunction())) {
660 settledEdgeCell = *iter;
662 if (!targetEdgeCell && (*iter)->
contains(targetEdge->getFromJunction())) {
663 targetEdgeCell = *iter;
665 if (settledEdgeCell && targetEdgeCell) {
669 assert(settledEdgeCell && targetEdgeCell);
672 settledEdgeCell == targetEdgeCell);
676 throw std::runtime_error(
"flagContext: relevant level could not be determined.");
679template<
class E,
class N,
class V,
class M>
681 assert(settledEdge !=
nullptr && targetEdge !=
nullptr);
683 const Cell* settledEdgeCell =
nullptr;
684 const Cell* targetEdgeCell =
nullptr;
685 if (myLastSettledEdgeCell
686 && myLastSettledEdgeCell->contains(settledEdge->getFromJunction())) {
690 return myLastFlagContext;
692 int numberOfPartitionLevels = myPartition->getNumberOfLevels();
693 if (numberOfPartitionLevels <= 4) {
694 int partitionLevel = sHARCLevel2PartitionLevel(sHARCLevel, myPartition->getNumberOfLevels());
695 const std::vector<const Cell*>& levelCells = myPartition->getCellsAtLevel(partitionLevel);
696 typename std::vector<const Cell*>::const_iterator first = levelCells.begin();
697 typename std::vector<const Cell*>::const_iterator last = levelCells.end();
698 typename std::vector<const Cell*>::const_iterator iter;
700 for (iter = first; iter != last; iter++) {
703 && (*iter)->
contains(settledEdge->getFromJunction())) {
704 settledEdgeCell = *iter;
706 if (!targetEdgeCell && myTargetEdgeCellLevel0) {
707 targetEdgeCell = myTargetEdgeCellLevel0;
708 }
else if (!targetEdgeCell
709 && (*iter)->
contains(targetEdge->getFromJunction())) {
710 myTargetEdgeCellLevel0 = *iter;
711 targetEdgeCell = myTargetEdgeCellLevel0;
713 if (settledEdgeCell && targetEdgeCell) {
714 assert(myTargetEdgeCellLevel0);
719 settledEdgeCell = myPartition->searchNode(settledEdge->getFromJunction());
720 if (!targetEdgeCell && myTargetEdgeCellLevel0) {
722 targetEdgeCell = myTargetEdgeCellLevel0;
723 }
else if (!targetEdgeCell) {
724 myTargetEdgeCellLevel0 = myPartition->searchNode(targetEdge->getFromJunction());
725 targetEdgeCell = myTargetEdgeCellLevel0;
728 assert(settledEdgeCell && targetEdgeCell);
734 myLastSettledEdgeCell = settledEdgeCell;
735 std::tuple<int, int, bool> flagContext = std::make_tuple(sHARCLevel, targetEdgeCell->
isLeftOrLowerCell() ? 0 : 1,
736 settledEdgeCell == targetEdgeCell);
737 myLastFlagContext = flagContext;
741template<
class E,
class N,
class V,
class M>
748template<
class E,
class N,
class V,
class M>
750 myQueryVisits += visits;
755template<
class E,
class N,
class V,
class M>
757 if (myNumQueries > 0) {
758 WRITE_MESSAGE(myType +
" answered " +
toString(myNumQueries) +
" queries and explored " +
toString((
double)myQueryVisits / (
double)myNumQueries) +
" edges on average.");
760#ifdef AFRO_DEBUG_LEVEL_2
766template<
class E,
class N,
class V,
class M>
771 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.
long long int myQueryTimeSum
SUMOTime myValidUntil
The validity duration of the current flag infos (exclusive)
static int sHARCLevel2PartitionLevel(int sHARCLevel, int numberOfPartitionLevels)
Converts a SHARC level number to a partition 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.
const std::string myType
The type of this router.
virtual ~AFRouter()
Destructor.
std::vector< bool > & flags(const E *edge)
Returns the arc flags of the passed edge.
const Cell * myLastSettledEdgeCell
The cell of the last settled edge.
long long int myQueryVisits
Counters for performance logging.
KDTreePartition< E, N, V >::Cell Cell
const SUMOTime myWeightPeriod
The validity duration of one weight interval.
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.
AbstractLookupTable< FlippedEdge< E, N, V >, V > FlippedLookupTable
void endQuery(int visits)
Stop timer for query time sum.
std::tuple< int, int, bool > flagContextNaive(const E *settledEdge, const E *targetEdge)
Kept for runtime comparisons.
virtual void setBulkMode(const bool mode)
Bulk mode is not supported.
std::vector< FlagInfo * > * myFlagInfos
Edge infos containing the associated edge and its arc flags.
void reportStatistics()
Report query time statistics.
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...
AFInfo< E >::FlagInfo FlagInfo
virtual void reset(const V *const vehicle)
Trigger arc flags rebuild.
static int partitionLevel2SHARCLevel(int partitionLevel, int numberOfPartitionLevels)
Converts a partition level number to a SHARC level number.
const KDTreePartition< E, N, V > * myPartition
The partition.
void resetStatistics()
Reset query time statistics.
EdgeInfoComparator myComparator
The comparator for edge information.
void startQuery()
Start timer for query time sum.
const Cell * myTargetEdgeCellLevel0
The cell of the target edge at SHARC level 0.
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...
AbstractLookupTable< E, V > LookupTable
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 > flagContext(const E *settledEdge, const E *targetEdge)
Returns the flag context for a route query from given settled edge to the target edge.
long long int myQueryStartTime
The time spent querying in milliseconds.
const std::shared_ptr< const LookupTable > myLookupTable
The lookup table for travel time heuristics.
AFBuilder< E, N, V, M > * myBuilder
The builder.
long long int myNumQueries
std::tuple< int, int, bool > myLastFlagContext
The last flag context.
const SUMOAbstractRouter< E, V >::EdgeInfo * edgeInfo(const E *const edge) const
Returns the edge information for the passed edge.
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
virtual SUMOAbstractRouter< E, V > * clone()
Cloning method.
double myMaxSpeed
The maximum speed in the network.
SUMOAbstractRouter< E, V >::EdgeInfo * edgeInfo(const E *const edge)
Returns the edge information for the passed edge.
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.