Skip to content

Commit

Permalink
Simplified upper bound condition for MLD routing
Browse files Browse the repository at this point in the history
  • Loading branch information
oxidase committed Mar 14, 2017
1 parent 5dc6b7f commit f8cb6ba
Showing 1 changed file with 31 additions and 59 deletions.
90 changes: 31 additions & 59 deletions include/engine/routing_algorithms/routing_base_mld.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,32 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
SearchEngineData::MultiLayerDijkstraHeap &reverse_heap,
const std::pair<LevelID, CellID> &parent_cell,
NodeID &middle_node,
EdgeWeight &path_upper_bound,
EdgeWeight &forward_upper_bound,
EdgeWeight &reverse_upper_bound)
EdgeWeight &path_upper_bound)
{
const auto node = forward_heap.DeleteMin();
const auto weight = forward_heap.GetKey(node);

auto update_upper_bounds = [&](NodeID to, EdgeWeight forward_weight, EdgeWeight edge_weight) {
// Upper bound for the path source -> target with
// weight(source -> node) = forward_weight, weight(node -> to) = edge_weight and
// weight(to -> target) ≤ reverse_weight is forward_weight + edge_weight + reverse_weight
// More tighter upper bound requires additional condition reverse_heap.WasRemoved(to)
// with weight(to -> target) = reverse_weight and all weights ≥ 0
if (reverse_heap.WasInserted(to))
// Upper bound for the path source -> target with
// weight(source -> node) = weight weight(to -> target) ≤ reverse_weight
// is weight + reverse_weight
// More tighter upper bound requires additional condition reverse_heap.WasRemoved(to)
// with weight(to -> target) = reverse_weight and all weights ≥ 0
if (reverse_heap.WasInserted(node))

This comment has been minimized.

Copy link
@TheMarex

TheMarex Mar 15, 2017

Member

Needs to be WasRemoved(node)

This comment has been minimized.

Copy link
@oxidase

oxidase Mar 15, 2017

Author Contributor

WasRemoved(node) will make upper bound stronger, but will break code in the path annotation for source and target nodes on one edge. I would keep here reverse_heap.WasInserted(node) to have similar behavior to CH in this case

{
auto reverse_weight = reverse_heap.GetKey(node);
auto path_weight = weight + reverse_weight;
if (path_weight >= 0 && path_weight < path_upper_bound)
{
auto reverse_weight = reverse_heap.GetKey(to);
auto path_weight = forward_weight + edge_weight + reverse_weight;
if (path_weight >= 0 && path_weight < path_upper_bound)
{
middle_node = to;
path_upper_bound = path_weight;
forward_upper_bound = forward_weight + edge_weight;
reverse_upper_bound = reverse_weight + edge_weight;
}
middle_node = node;
path_upper_bound = path_weight;
}
};
}

if (weight > path_upper_bound)
{
forward_heap.DeleteAll();
return;
}

const auto &node_data = forward_heap.GetData(node);
const auto level = node_data.level;
Expand All @@ -61,9 +61,6 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
(node_data.parent == node || // is the first point of the path
node_data.edge_id != SPECIAL_EDGEID); // or an overlay entreé point

// Edge case: single node path
update_upper_bounds(node, weight, 0);

if (check_overlay_edges)
{
if (DIRECTION == FORWARD_DIRECTION)
Expand All @@ -81,13 +78,11 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
if (!forward_heap.WasInserted(to))
{
forward_heap.Insert(to, to_weight, {node, level});
update_upper_bounds(to, weight, shortcut_weight);
}
else if (to_weight < forward_heap.GetKey(to))
{
forward_heap.GetData(to) = {node, level};
forward_heap.DecreaseKey(to, to_weight);
update_upper_bounds(to, weight, shortcut_weight);
}
}
++destination;
Expand All @@ -108,13 +103,11 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
if (!forward_heap.WasInserted(to))
{
forward_heap.Insert(to, to_weight, {node, level});
update_upper_bounds(to, weight, shortcut_weight);
}
else if (to_weight < forward_heap.GetKey(to))
{
forward_heap.GetData(to) = {node, level};
forward_heap.DecreaseKey(to, to_weight);
update_upper_bounds(to, weight, shortcut_weight);
}
}
++source;
Expand Down Expand Up @@ -144,13 +137,11 @@ void routingStep(const datafacade::ContiguousInternalMemoryDataFacade<algorithm:
if (!forward_heap.WasInserted(to))
{
forward_heap.Insert(to, to_weight, {node, to_level, edge});
update_upper_bounds(to, weight, edge_data.weight);
}
else if (to_weight < forward_heap.GetKey(to))
{
forward_heap.GetData(to) = {node, to_level, edge};
forward_heap.DecreaseKey(to, to_weight);
update_upper_bounds(to, weight, edge_data.weight);
}
}
}
Expand All @@ -164,44 +155,25 @@ auto search(const datafacade::ContiguousInternalMemoryDataFacade<algorithm::MLD>
SearchEngineData::MultiLayerDijkstraHeap &reverse_heap,
const std::pair<LevelID, CellID> &parent_cell)
{
BOOST_ASSERT(!forward_heap.Empty() && forward_heap.MinKey() < INVALID_EDGE_WEIGHT);
BOOST_ASSERT(!reverse_heap.Empty() && reverse_heap.MinKey() < INVALID_EDGE_WEIGHT);

// run two-Target Dijkstra routing step.
NodeID middle = SPECIAL_NODEID;
EdgeWeight weight = INVALID_EDGE_WEIGHT;
EdgeWeight forward_search_radius = INVALID_EDGE_WEIGHT;
EdgeWeight reverse_search_radius = INVALID_EDGE_WEIGHT;
bool progress;
do
while ((forward_heap.Size() + reverse_heap.Size() > 0))

This comment has been minimized.

Copy link
@TheMarex

TheMarex Mar 15, 2017

Member

while(forward_heap.Size() + reverse_heap.Size() > 0 && forward_heap.MinKey() + reverse_heap.MinKey() < upper_bound)

This comment has been minimized.

Copy link
@oxidase

oxidase Mar 15, 2017

Author Contributor

Condition forward_heap.MinKey() + reverse_heap.MinKey() < upper_bound will not work for the multi-layer case, because MinKey() values in heaps can be for different levels at one time. Here is the refined figure with a 1D graph after 5 iterations, where the forward heap is still on the level 1, but the reverse heap is already on the level 2
mld

The middle node is node and settled in both forward and reverse heaps (WasInserted(node) && WasRemoved(node) is true for both heaps), upper_bound is forward_heap.GetKey(node) + reverse_heap.GetKey(node) will be less than forward_heap.MinKey() + reverse_heap.MinKey(), so iterations should stop, but source->node->target is not the shortest path. The correct shortest path is shown with the blue line.
The "pessimistic" stopping condition forward_heap.MinKey() < upper_bound && reverse_heap.MinKey() < upper_bound is correct in this case.

I have another idea, how to tackle the problem: use different heaps for different levels, and do iterations over levels
0, 1, ... , highest_different_level - 1, and than do a bidirectional Dijkstra search on highest_different_level with the correct stopping criteria forward_heap.MinKey() + reverse_heap.MinKey() < upper_bound

{
progress = false;
if (!forward_heap.Empty() && (forward_heap.MinKey() < forward_search_radius))
if (!forward_heap.Empty())
{
progress = true;
routingStep<FORWARD_DIRECTION>(facade,
partition,
cells,
forward_heap,
reverse_heap,
parent_cell,
middle,
weight,
forward_search_radius,
reverse_search_radius);
routingStep<FORWARD_DIRECTION>(
facade, partition, cells, forward_heap, reverse_heap, parent_cell, middle, weight);
}
if (!reverse_heap.Empty() && (reverse_heap.MinKey() < reverse_search_radius))
if (!reverse_heap.Empty())
{
progress = true;
routingStep<REVERSE_DIRECTION>(facade,
partition,
cells,
reverse_heap,
forward_heap,
parent_cell,
middle,
weight,
reverse_search_radius,
forward_search_radius);
routingStep<REVERSE_DIRECTION>(
facade, partition, cells, reverse_heap, forward_heap, parent_cell, middle, weight);
}
} while (progress);
};

// No path found for both target nodes?
if (weight == INVALID_EDGE_WEIGHT || SPECIAL_NODEID == middle)
Expand Down

0 comments on commit f8cb6ba

Please sign in to comment.