20 #ifndef AStarLookupTable_h 21 #define AStarLookupTable_h 40 #define UNREACHABLE (std::numeric_limits<double>::max() / 1000.0) 65 template<
class E,
class V>
69 virtual double lowerBound(
const E* from,
const E* to,
double speed,
double speedFactor,
double fromEffort,
double toEffort)
const = 0;
76 template<
class E,
class V>
82 for (
int i = 0; i < size; i++) {
83 for (
int j = 0; j < size; j++) {
86 myTable[i].push_back(val);
91 double lowerBound(
const E* from,
const E* to,
double ,
double speedFactor,
double ,
double )
const {
92 return myTable[from->getNumericalID()][to->getNumericalID()] / speedFactor;
104 template<
class E,
class V>
108 myFirstNonInternal = -1;
109 std::map<std::string, int> numericID;
111 if (!e->isInternal()) {
112 if (myFirstNonInternal == -1) {
113 myFirstNonInternal = e->getNumericalID();
115 numericID[e->getID()] = e->getNumericalID() - myFirstNonInternal;
118 std::ifstream strm(filename.c_str());
120 throw ProcessError(
"Could not load landmark-lookup-table from '" + filename +
"'.");
122 std::ofstream* ostrm = 0;
123 if (!outfile.empty()) {
124 ostrm =
new std::ofstream(outfile.c_str());
125 if (!ostrm->good()) {
126 throw ProcessError(
"Could not open file '" + outfile +
"' for writing.");
130 int numLandMarks = 0;
131 while (std::getline(strm, line)) {
137 if (st.
size() == 1) {
138 const std::string lm = st.
get(0);
139 myLandmarks[lm] = numLandMarks++;
140 myFromLandmarkDists.push_back(std::vector<double>(0));
141 myToLandmarkDists.push_back(std::vector<double>(0));
143 (*ostrm) << lm <<
"\n";
146 assert(st.
size() == 4);
147 const std::string lm = st.
get(0);
148 const std::string edge = st.
get(1);
149 if (numericID[edge] != (
int)myFromLandmarkDists[myLandmarks[lm]].size()) {
150 WRITE_WARNING(
"Unknown or unordered edge '" + edge +
"' in landmark file.");
154 myFromLandmarkDists[myLandmarks[lm]].push_back(distFrom);
155 myToLandmarkDists[myLandmarks[lm]].push_back(distTo);
158 if (myLandmarks.empty()) {
159 WRITE_WARNING(
"No landmarks in '" + filename +
"', falling back to standard A*.");
165 for (
int i = 0; i < (int)myLandmarks.size(); ++i) {
166 if ((
int)myFromLandmarkDists[i].size() != (int)edges.size() - myFirstNonInternal) {
167 const std::string landmarkID = getLandmark(i);
168 const E* landmark = 0;
170 for (
typename std::vector<E*>::const_iterator it_e = edges.begin(); it_e != edges.end(); ++it_e) {
171 if ((*it_e)->getID() == landmarkID) {
176 WRITE_WARNING(
"Landmark '" + landmarkID +
"' does not exist in the network.");
180 const std::string missing = filename +
".missing";
181 WRITE_WARNING(
"Not all network edges were found in the lookup table '" + filename +
"' for landmark '" + landmarkID +
"'. Saving missing values to '" + missing +
"'.");
183 ostrm =
new std::ofstream(missing.c_str());
184 if (!ostrm->good()) {
185 throw ProcessError(
"Could not open file '" + missing +
"' for writing.");
189 throw ProcessError(
"Not all network edges were found in the lookup table '" + filename +
"' for landmark '" + landmarkID +
"'.");
191 std::vector<const E*> routeLM(1, landmark);
192 const double lmCost = router->
recomputeCosts(routeLM, defaultVehicle, 0);
193 std::vector<const E*> route;
195 if (maxNumThreads > 0) {
196 if (threadPool.
size() == 0) {
199 router->
compute(landmark, landmark, defaultVehicle, 0, route);
201 while ((
int)threadPool.
size() < maxNumThreads) {
202 new WorkerThread(threadPool, router->
clone(), defaultVehicle);
205 std::vector<RoutingTask*> currentTasks;
206 for (
int j = (
int)myFromLandmarkDists[i].size() + myFirstNonInternal; j < (int)edges.size(); ++j) {
207 const E* edge = edges[j];
208 if (landmark != edge) {
209 std::vector<const E*> routeE(1, edge);
210 const double sourceDestCost = lmCost + router->
recomputeCosts(routeE, defaultVehicle, 0);
212 if (edge->getPredecessors().size() > 0 && landmark->getSuccessors().size() > 0) {
213 currentTasks.push_back(
new RoutingTask(landmark, edge, sourceDestCost));
214 threadPool.
add(currentTasks.back());
217 if (landmark->getPredecessors().size() > 0 && edge->getSuccessors().size() > 0) {
218 currentTasks.push_back(
new RoutingTask(edge, landmark, sourceDestCost));
219 threadPool.
add(currentTasks.back());
225 for (
int j = (
int)myFromLandmarkDists[i].size() + myFirstNonInternal; j < (int)edges.size(); ++j) {
226 const E* edge = edges[j];
227 double distFrom = -1;
229 if (landmark == edge) {
233 if (edge->getPredecessors().size() > 0 && landmark->getSuccessors().size() > 0) {
234 distFrom = currentTasks[taskIndex]->getCost();
235 delete currentTasks[taskIndex++];
237 if (landmark->getPredecessors().size() > 0 && edge->getSuccessors().size() > 0) {
238 distTo = currentTasks[taskIndex]->getCost();
239 delete currentTasks[taskIndex++];
242 myFromLandmarkDists[i].push_back(distFrom);
243 myToLandmarkDists[i].push_back(distTo);
244 (*ostrm) << landmarkID <<
" " << edge->getID() <<
" " << distFrom <<
" " << distTo <<
"\n";
246 currentTasks.clear();
250 for (
int j = (
int)myFromLandmarkDists[i].size() + myFirstNonInternal; j < (int)edges.size(); ++j) {
251 const E* edge = edges[j];
252 double distFrom = -1;
254 if (landmark == edge) {
258 std::vector<const E*> routeE(1, edge);
259 const double sourceDestCost = lmCost + router->
recomputeCosts(routeE, defaultVehicle, 0);
261 if (edge->getPredecessors().size() > 0 && landmark->getSuccessors().size() > 0) {
262 if (router->
compute(landmark, edge, defaultVehicle, 0, route)) {
263 distFrom =
MAX2(0.0, router->
recomputeCosts(route, defaultVehicle, 0) - sourceDestCost);
268 if (landmark->getPredecessors().size() > 0 && edge->getSuccessors().size() > 0) {
269 if (router->
compute(edge, landmark, defaultVehicle, 0, route)) {
270 distTo =
MAX2(0.0, router->
recomputeCosts(route, defaultVehicle, 0) - sourceDestCost);
275 myFromLandmarkDists[i].push_back(distFrom);
276 myToLandmarkDists[i].push_back(distTo);
277 (*ostrm) << landmarkID <<
" " << edge->getID() <<
" " << distFrom <<
" " << distTo <<
"\n";
284 double lowerBound(
const E* from,
const E* to,
double speed,
double speedFactor,
double fromEffort,
double toEffort)
const {
285 double result = from->getDistanceTo(to) / speed;
286 #ifdef ASTAR_DEBUG_LOOKUPTABLE 287 if (from->getID() == ASTAR_DEBUG_LOOKUPTABLE_FROM) {
288 std::cout <<
" lowerBound to=" << to->getID() <<
" result1=" << result <<
"\n";
291 for (
int i = 0; i < (int)myLandmarks.size(); ++i) {
293 const double fl = myToLandmarkDists[i][from->getNumericalID() - myFirstNonInternal];
294 const double tl = myToLandmarkDists[i][to->getNumericalID() - myFirstNonInternal];
295 if (fl >= 0 && tl >= 0) {
296 const double bound = (fl - tl - toEffort) / speedFactor;
297 #ifdef ASTAR_DEBUG_LOOKUPTABLE 298 if (from->getID() == ASTAR_DEBUG_LOOKUPTABLE_FROM && result < bound) {
299 std::cout <<
" landmarkTo=" << getLandmark(i) <<
" result2=" << bound
300 <<
" fl=" << fl <<
" tl=" << tl <<
"\n";
303 result =
MAX2(result, bound);
305 const double lt = myFromLandmarkDists[i][to->getNumericalID() - myFirstNonInternal];
306 const double lf = myFromLandmarkDists[i][from->getNumericalID() - myFirstNonInternal];
307 if (lt >= 0 && lf >= 0) {
308 const double bound = (lt - lf - fromEffort) / speedFactor;
309 #ifdef ASTAR_DEBUG_LOOKUPTABLE 310 if (from->getID() == ASTAR_DEBUG_LOOKUPTABLE_FROM && result < bound) {
311 std::cout <<
" landmarkFrom=" << getLandmark(i) <<
" result3=" << bound
312 <<
" lt=" << lt <<
" lf=" << lf <<
"\n";
315 result =
MAX2(result, bound);
317 if ((tl >= 0 && fl < 0)
318 || (lf >= 0 && lt < 0)) {
320 #ifdef ASTAR_DEBUG_UNREACHABLE 321 std::cout <<
" unreachable: from=" << from->getID() <<
" to=" << to->getID() <<
" landmark=" << getLandmark(i) <<
" " 322 << ((tl >= 0 && fl < 0) ?
" (toLandmark)" :
" (fromLandmark)")
323 <<
" fl=" << fl <<
" tl=" << tl <<
" lt=" << lt <<
" lf=" << lf
349 virtual ~WorkerThread() {
352 double compute(
const E* src,
const E* dest,
const double costOff) {
354 if (myRouter->compute(src, dest, myVehicle, 0, myRoute)) {
355 result =
MAX2(0.0, myRouter->recomputeCosts(myRoute, myVehicle, 0) + costOff);
363 std::vector<const E*> myRoute;
368 RoutingTask(
const E* src,
const E* dest,
const double costOff)
369 : mySrc(src), myDest(dest), myCost(-costOff) {}
371 myCost = ((WorkerThread*)context)->compute(mySrc, myDest, myCost);
377 const E*
const mySrc;
378 const E*
const myDest;
382 RoutingTask& operator=(
const RoutingTask&);
391 for (std::map<std::string, int>::const_iterator it = myLandmarks.begin(); it != myLandmarks.end(); ++it) {
392 if (it->second == i) {
void waitAll(const bool deleteFinished=true)
waits for all tasks to be finished
bool consistent() const
whether the heuristic ist consistent (found nodes are always visited on the shortest path the first t...
bool consistent() const
whether the heuristic ist consistent (found nodes are always visited on the shortest path the first t...
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
#define WRITE_WARNING(msg)
virtual double lowerBound(const E *from, const E *to, double speed, double speedFactor, double fromEffort, double toEffort) const =0
provide a lower bound on the distance between from and to (excluding traveltime of both edges) ...
LandmarkLookupTable(const std::string &filename, const std::vector< E * > &edges, SUMOAbstractRouter< E, V > *router, const V *defaultVehicle, const std::string &outfile, const int maxNumThreads)
std::vector< std::vector< double > > myToLandmarkDists
FullLookupTable(const std::string &filename, const int size)
std::map< std::string, int > myLandmarks
virtual bool consistent() const =0
whether the heuristic ist consistent (found nodes are always visited on the shortest path the first t...
void add(Task *const t, int index=-1)
Gives a number to the given task and assigns it to the worker with the given index. If the index is negative, assign to the next (round robin) one.
std::string getLandmark(int i) const
virtual double recomputeCosts(const std::vector< const E * > &edges, const V *const v, SUMOTime msTime) const =0
int size() const
Returns the number of threads in the pool.
double lowerBound(const E *from, const E *to, double, double speedFactor, double, double) const
provide a lower bound on the distance between from and to (excluding traveltime of both edges) ...
A pool of worker threads which distributes the tasks and collects the results.
std::vector< std::vector< double > > myTable
std::string get(int pos) const
static double _2double(const E *const data)
converts a char-type array into the double value described by it
double lowerBound(const E *from, const E *to, double speed, double speedFactor, double fromEffort, double toEffort) const
provide a lower bound on the distance between from and to (excluding traveltime of both edges) ...
Abstract superclass of a task to be run with an index to keep track of pending tasks.
A thread repeatingly calculating incoming tasks.
Computes the shortest path through a network using the A* algorithm.
virtual SUMOAbstractRouter * clone()=0
std::vector< std::vector< double > > myFromLandmarkDists