Skip to content

Commit 2bb4d0f

Browse files
committed
Merge pull request #75 from valhalla/kk_shorter
take the shortest path even if its basically a crap shoot
2 parents fcab774 + 1a61734 commit 2bb4d0f

File tree

3 files changed

+49
-21
lines changed

3 files changed

+49
-21
lines changed

src/thor/pathalgorithm.cc

+37-15
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ namespace thor {
5656
PathAlgorithm::PathAlgorithm()
5757
: edgelabel_index_(0),
5858
adjacencylist_(nullptr),
59-
edgestatus_(nullptr) {
59+
edgestatus_(nullptr),
60+
best_destination_{kInvalidLabel, std::numeric_limits<float>::max()}{
6061
edgelabels_.reserve(kInitialEdgeLabelCount);
6162
}
6263

@@ -70,6 +71,7 @@ void PathAlgorithm::Clear() {
7071
// Set the edge label index back to 0
7172
edgelabel_index_ = 0;
7273
edgelabels_.clear();
74+
best_destination_ = std::make_pair(kInvalidLabel, std::numeric_limits<float>::max());
7375

7476
// Clear elements from the adjacency list
7577
if(adjacencylist_ != nullptr) {
@@ -123,7 +125,7 @@ std::vector<GraphId> PathAlgorithm::GetBestPath(const PathLocation& origin,
123125

124126
// Initialize the origin and destination locations
125127
SetOrigin(graphreader, origin, costing, loop_edge);
126-
SetDestination(dest);
128+
SetDestination(graphreader, dest, costing);
127129

128130
// Counts of transitions to upper levels (TEST - TODO better design!)
129131
uint32_t upto1count = 0;
@@ -146,6 +148,10 @@ std::vector<GraphId> PathAlgorithm::GetBestPath(const PathLocation& origin,
146148
// error codes and return the appropriate one here
147149
next_label_index = adjacencylist_->Remove(edgelabels_);
148150
if (next_label_index == kInvalidLabel) {
151+
// If we had a destination but we were waiting on other possible ones
152+
if(best_destination_.first != kInvalidLabel)
153+
return FormPath(best_destination_.first, graphreader, loop_edge);
154+
// We didn't find any destination edge
149155
LOG_ERROR("Route failed after iterations = " + std::to_string(edgelabel_index_));
150156
throw std::runtime_error("No path could be found for input");
151157
}
@@ -156,8 +162,8 @@ std::vector<GraphId> PathAlgorithm::GetBestPath(const PathLocation& origin,
156162
edgestatus_->Set(nextlabel.edgeid(), kPermanent);
157163

158164
// Check for completion. Form path and return if complete.
159-
if (IsComplete(nextlabel)) {
160-
return FormPath(next_label_index, graphreader, loop_edge);
165+
if (IsComplete(next_label_index)) {
166+
return FormPath(best_destination_.first, graphreader, loop_edge);
161167
}
162168

163169
// TODO - do we need to terminate fruitless searches?
@@ -283,7 +289,7 @@ std::vector<GraphId> PathAlgorithm::GetBestPath(const PathLocation& origin,
283289
}
284290

285291
// Add an edge at the origin to the adjacency list
286-
void PathAlgorithm::SetOrigin(baldr::GraphReader& graphreader,
292+
void PathAlgorithm::SetOrigin(GraphReader& graphreader,
287293
const PathLocation& origin, const std::shared_ptr<DynamicCost>& costing, const GraphId& loop_edge_id) {
288294
// Get sort heuristic based on distance from origin to destination
289295
float dist = astarheuristic_.GetDistance(origin.vertex());
@@ -328,21 +334,37 @@ void PathAlgorithm::SetOrigin(baldr::GraphReader& graphreader,
328334
}
329335

330336
// Add a destination edge
331-
void PathAlgorithm::SetDestination(const PathLocation& dest) {
332-
// TODO - add partial distances
337+
void PathAlgorithm::SetDestination(GraphReader& graphreader, const PathLocation& dest, const std::shared_ptr<DynamicCost>& costing) {
338+
// For each edge
333339
for (const auto& edge : dest.edges()) {
334-
destinations_[edge.id] = edge.dist;
340+
// Keep the id and the cost to traverse the partial distance
341+
const GraphTile* tile = graphreader.GetGraphTile(edge.id);
342+
destinations_[edge.id] = costing->Get(tile->directededge(edge.id)) * edge.dist;
335343
}
336344
}
337345

338346
// Test is the shortest path has been found.
339-
bool PathAlgorithm::IsComplete(const EdgeLabel& edge_label) {
340-
// TODO - if destination is along an edge and the edge allows
341-
// travel in both directions we need to make sure both directions
342-
// are found or some further cost is encountered to rule out the
343-
// other direction
344-
const auto& p = destinations_.find(edge_label.edgeid());
345-
return p != destinations_.end();
347+
bool PathAlgorithm::IsComplete(const uint32_t edge_label_index) {
348+
//grab the label
349+
const EdgeLabel& edge_label = edgelabels_[edge_label_index];
350+
//if we've already found a destination and the search's current edge is more costly to get to, we are done
351+
if(best_destination_.first != kInvalidLabel && edge_label.truecost() > best_destination_.second)
352+
return true;
353+
//check if its a destination
354+
auto p = destinations_.find(edge_label.edgeid());
355+
//it is indeed one of the possible destination edges
356+
if(p != destinations_.end()) {
357+
//if we didnt have another destination yet or this one is better
358+
auto cost = edge_label.truecost() + p->second;
359+
if(best_destination_.first == kInvalidLabel || cost < best_destination_.second){
360+
best_destination_.first = edge_label_index;
361+
best_destination_.second = cost;
362+
}
363+
destinations_.erase(p);
364+
//if we've found all of the destinations we are done looking
365+
return destinations_.size() == 0;
366+
}
367+
return false;
346368
}
347369

348370
// Form the path from the adjacency list.

src/thor/trippathbuilder.cc

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ TripPath TripPathBuilder::Build(GraphReader& graphreader,
119119
// If the path was only one edge we have a special case
120120
if(pathedges.size() == 1) {
121121
if(end_pct < start_pct)
122-
throw std::runtime_error("Generated reverse trivial path, this is a bug and we are working on it");
122+
throw std::runtime_error("Generated reverse trivial path, report this bug!");
123123
const auto tile = graphreader.GetGraphTile(pathedges.front());
124124
const auto edge = tile->directededge(pathedges.front());
125125

valhalla/thor/pathalgorithm.h

+11-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <vector>
55
#include <map>
66
#include <unordered_map>
7+
#include <utility>
78

89
#include <valhalla/baldr/graphid.h>
910
#include <valhalla/baldr/graphreader.h>
@@ -64,9 +65,12 @@ class PathAlgorithm {
6465
// to search to find an entry that is already in the adjacency list
6566
std::unordered_map<baldr::GraphId, uint32_t> adjlistedges_;
6667

67-
// Destinations
68+
// Destinations, id and cost
6869
std::unordered_map<baldr::GraphId, float> destinations_;
6970

71+
// Destination that was last found with its true cost + partial cost
72+
std::pair<uint32_t, float> best_destination_;
73+
7074
/**
7175
* Initialize
7276
*/
@@ -82,14 +86,16 @@ class PathAlgorithm {
8286
/**
8387
* Set the destination edge(s).
8488
*/
85-
void SetDestination(const baldr::PathLocation& dest);
89+
void SetDestination(baldr::GraphReader& graphreader, const baldr::PathLocation& dest,
90+
const std::shared_ptr<DynamicCost>& costing);
8691

8792
/**
88-
* Test if the shortest path is found.
93+
* Return a valid edge id if we've found the destination edge
8994
*
90-
* @param edge_label edgelabel to be tested for destination
95+
* @param edge_label_index edge label to be tested for destination
96+
* @return bool true if we've found the destination
9197
*/
92-
bool IsComplete(const EdgeLabel& edge_label);
98+
bool IsComplete(const uint32_t edge_label_index);
9399

94100
/**
95101
* Form the path from the adjacency list.

0 commit comments

Comments
 (0)