Merge pull request #5894 from xlaussel/avoid_samelookup_in_heap_map
Avoid samelookup in heap map
This commit is contained in:
commit
eb1d399f3b
@ -24,11 +24,10 @@ namespace ch
|
|||||||
// Stalling
|
// Stalling
|
||||||
template <bool DIRECTION, typename HeapT>
|
template <bool DIRECTION, typename HeapT>
|
||||||
bool stallAtNode(const DataFacade<Algorithm> &facade,
|
bool stallAtNode(const DataFacade<Algorithm> &facade,
|
||||||
const NodeID node,
|
const typename HeapT::HeapNode &heapNode,
|
||||||
const EdgeWeight weight,
|
|
||||||
const HeapT &query_heap)
|
const HeapT &query_heap)
|
||||||
{
|
{
|
||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
for (auto edge : facade.GetAdjacentEdgeRange(heapNode.node))
|
||||||
{
|
{
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
if (DIRECTION == REVERSE_DIRECTION ? data.forward : data.backward)
|
if (DIRECTION == REVERSE_DIRECTION ? data.forward : data.backward)
|
||||||
@ -36,9 +35,10 @@ bool stallAtNode(const DataFacade<Algorithm> &facade,
|
|||||||
const NodeID to = facade.GetTarget(edge);
|
const NodeID to = facade.GetTarget(edge);
|
||||||
const EdgeWeight edge_weight = data.weight;
|
const EdgeWeight edge_weight = data.weight;
|
||||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
if (query_heap.WasInserted(to))
|
const auto toHeapNode = query_heap.GetHeapNodeIfWasInserted(to);
|
||||||
|
if (toHeapNode)
|
||||||
{
|
{
|
||||||
if (query_heap.GetKey(to) + edge_weight < weight)
|
if (toHeapNode->weight + edge_weight < heapNode.weight)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -50,11 +50,10 @@ bool stallAtNode(const DataFacade<Algorithm> &facade,
|
|||||||
|
|
||||||
template <bool DIRECTION>
|
template <bool DIRECTION>
|
||||||
void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
||||||
const NodeID node,
|
const SearchEngineData<Algorithm>::QueryHeap::HeapNode &heapNode,
|
||||||
const EdgeWeight weight,
|
|
||||||
SearchEngineData<Algorithm>::QueryHeap &heap)
|
SearchEngineData<Algorithm>::QueryHeap &heap)
|
||||||
{
|
{
|
||||||
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
for (const auto edge : facade.GetAdjacentEdgeRange(heapNode.node))
|
||||||
{
|
{
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
|
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
|
||||||
@ -63,19 +62,21 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
|||||||
const EdgeWeight edge_weight = data.weight;
|
const EdgeWeight edge_weight = data.weight;
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
const EdgeWeight to_weight = weight + edge_weight;
|
const EdgeWeight to_weight = heapNode.weight + edge_weight;
|
||||||
|
|
||||||
|
const auto toHeapNode = heap.GetHeapNodeIfWasInserted(to);
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if (!heap.WasInserted(to))
|
if (!toHeapNode)
|
||||||
{
|
{
|
||||||
heap.Insert(to, to_weight, node);
|
heap.Insert(to, to_weight, heapNode.node);
|
||||||
}
|
}
|
||||||
// Found a shorter Path -> Update weight
|
// Found a shorter Path -> Update weight
|
||||||
else if (to_weight < heap.GetKey(to))
|
else if (to_weight < toHeapNode->weight)
|
||||||
{
|
{
|
||||||
// new parent
|
// new parent
|
||||||
heap.GetData(to).parent = node;
|
toHeapNode->data.parent = heapNode.node;
|
||||||
heap.DecreaseKey(to, to_weight);
|
toHeapNode->weight = to_weight;
|
||||||
|
heap.DecreaseKey(*toHeapNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,35 +123,35 @@ void routingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const bool force_loop_forward,
|
const bool force_loop_forward,
|
||||||
const bool force_loop_reverse)
|
const bool force_loop_reverse)
|
||||||
{
|
{
|
||||||
const NodeID node = forward_heap.DeleteMin();
|
auto heapNode = forward_heap.DeleteMinGetHeapNode();
|
||||||
const EdgeWeight weight = forward_heap.GetKey(node);
|
const auto reverseHeapNode = reverse_heap.GetHeapNodeIfWasInserted(heapNode.node);
|
||||||
|
|
||||||
if (reverse_heap.WasInserted(node))
|
if (reverseHeapNode)
|
||||||
{
|
{
|
||||||
const EdgeWeight new_weight = reverse_heap.GetKey(node) + weight;
|
const EdgeWeight new_weight = reverseHeapNode->weight + heapNode.weight;
|
||||||
if (new_weight < upper_bound)
|
if (new_weight < upper_bound)
|
||||||
{
|
{
|
||||||
// if loops are forced, they are so at the source
|
// if loops are forced, they are so at the source
|
||||||
if ((force_loop_forward && forward_heap.GetData(node).parent == node) ||
|
if ((force_loop_forward && heapNode.data.parent == heapNode.node) ||
|
||||||
(force_loop_reverse && reverse_heap.GetData(node).parent == node) ||
|
(force_loop_reverse && reverseHeapNode->data.parent == heapNode.node) ||
|
||||||
// in this case we are looking at a bi-directional way where the source
|
// in this case we are looking at a bi-directional way where the source
|
||||||
// and target phantom are on the same edge based node
|
// and target phantom are on the same edge based node
|
||||||
new_weight < 0)
|
new_weight < 0)
|
||||||
{
|
{
|
||||||
// check whether there is a loop present at the node
|
// check whether there is a loop present at the node
|
||||||
for (const auto edge : facade.GetAdjacentEdgeRange(node))
|
for (const auto edge : facade.GetAdjacentEdgeRange(heapNode.node))
|
||||||
{
|
{
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
|
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
|
||||||
{
|
{
|
||||||
const NodeID to = facade.GetTarget(edge);
|
const NodeID to = facade.GetTarget(edge);
|
||||||
if (to == node)
|
if (to == heapNode.node)
|
||||||
{
|
{
|
||||||
const EdgeWeight edge_weight = data.weight;
|
const EdgeWeight edge_weight = data.weight;
|
||||||
const EdgeWeight loop_weight = new_weight + edge_weight;
|
const EdgeWeight loop_weight = new_weight + edge_weight;
|
||||||
if (loop_weight >= 0 && loop_weight < upper_bound)
|
if (loop_weight >= 0 && loop_weight < upper_bound)
|
||||||
{
|
{
|
||||||
middle_node_id = node;
|
middle_node_id = heapNode.node;
|
||||||
upper_bound = loop_weight;
|
upper_bound = loop_weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,7 +162,7 @@ void routingStep(const DataFacade<Algorithm> &facade,
|
|||||||
{
|
{
|
||||||
BOOST_ASSERT(new_weight >= 0);
|
BOOST_ASSERT(new_weight >= 0);
|
||||||
|
|
||||||
middle_node_id = node;
|
middle_node_id = heapNode.node;
|
||||||
upper_bound = new_weight;
|
upper_bound = new_weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,19 +171,19 @@ void routingStep(const DataFacade<Algorithm> &facade,
|
|||||||
// make sure we don't terminate too early if we initialize the weight
|
// make sure we don't terminate too early if we initialize the weight
|
||||||
// for the nodes in the forward heap with the forward/reverse offset
|
// for the nodes in the forward heap with the forward/reverse offset
|
||||||
BOOST_ASSERT(min_edge_offset <= 0);
|
BOOST_ASSERT(min_edge_offset <= 0);
|
||||||
if (weight + min_edge_offset > upper_bound)
|
if (heapNode.weight + min_edge_offset > upper_bound)
|
||||||
{
|
{
|
||||||
forward_heap.DeleteAll();
|
forward_heap.DeleteAll();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stalling
|
// Stalling
|
||||||
if (STALLING && stallAtNode<DIRECTION>(facade, node, weight, forward_heap))
|
if (STALLING && stallAtNode<DIRECTION>(facade, heapNode, forward_heap))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
relaxOutgoingEdges<DIRECTION>(facade, node, weight, forward_heap);
|
relaxOutgoingEdges<DIRECTION>(facade, heapNode, forward_heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool UseDuration>
|
template <bool UseDuration>
|
||||||
|
@ -228,40 +228,42 @@ retrievePackedPathFromHeap(const SearchEngineData<Algorithm>::QueryHeap &forward
|
|||||||
template <bool DIRECTION, typename Algorithm, typename... Args>
|
template <bool DIRECTION, typename Algorithm, typename... Args>
|
||||||
void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
||||||
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
typename SearchEngineData<Algorithm>::QueryHeap &forward_heap,
|
||||||
const NodeID node,
|
const typename SearchEngineData<Algorithm>::QueryHeap::HeapNode &heapNode,
|
||||||
const EdgeWeight weight,
|
|
||||||
Args... args)
|
Args... args)
|
||||||
{
|
{
|
||||||
const auto &partition = facade.GetMultiLevelPartition();
|
const auto &partition = facade.GetMultiLevelPartition();
|
||||||
const auto &cells = facade.GetCellStorage();
|
const auto &cells = facade.GetCellStorage();
|
||||||
const auto &metric = facade.GetCellMetric();
|
const auto &metric = facade.GetCellMetric();
|
||||||
|
|
||||||
const auto level = getNodeQueryLevel(partition, node, args...);
|
const auto level = getNodeQueryLevel(partition, heapNode.node, args...);
|
||||||
|
|
||||||
if (level >= 1 && !forward_heap.GetData(node).from_clique_arc)
|
if (level >= 1 && !heapNode.data.from_clique_arc)
|
||||||
{
|
{
|
||||||
if (DIRECTION == FORWARD_DIRECTION)
|
if (DIRECTION == FORWARD_DIRECTION)
|
||||||
{
|
{
|
||||||
// Shortcuts in forward direction
|
// Shortcuts in forward direction
|
||||||
const auto &cell = cells.GetCell(metric, level, partition.GetCell(level, node));
|
const auto &cell =
|
||||||
|
cells.GetCell(metric, level, partition.GetCell(level, heapNode.node));
|
||||||
auto destination = cell.GetDestinationNodes().begin();
|
auto destination = cell.GetDestinationNodes().begin();
|
||||||
for (auto shortcut_weight : cell.GetOutWeight(node))
|
for (auto shortcut_weight : cell.GetOutWeight(heapNode.node))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(destination != cell.GetDestinationNodes().end());
|
BOOST_ASSERT(destination != cell.GetDestinationNodes().end());
|
||||||
const NodeID to = *destination;
|
const NodeID to = *destination;
|
||||||
|
|
||||||
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
|
if (shortcut_weight != INVALID_EDGE_WEIGHT && heapNode.node != to)
|
||||||
{
|
{
|
||||||
const EdgeWeight to_weight = weight + shortcut_weight;
|
const EdgeWeight to_weight = heapNode.weight + shortcut_weight;
|
||||||
BOOST_ASSERT(to_weight >= weight);
|
BOOST_ASSERT(to_weight >= heapNode.weight);
|
||||||
if (!forward_heap.WasInserted(to))
|
const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
|
||||||
|
if (!toHeapNode)
|
||||||
{
|
{
|
||||||
forward_heap.Insert(to, to_weight, {node, true});
|
forward_heap.Insert(to, to_weight, {heapNode.node, true});
|
||||||
}
|
}
|
||||||
else if (to_weight < forward_heap.GetKey(to))
|
else if (to_weight < toHeapNode->weight)
|
||||||
{
|
{
|
||||||
forward_heap.GetData(to) = {node, true};
|
toHeapNode->data = {heapNode.node, true};
|
||||||
forward_heap.DecreaseKey(to, to_weight);
|
toHeapNode->weight = to_weight;
|
||||||
|
forward_heap.DecreaseKey(*toHeapNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++destination;
|
++destination;
|
||||||
@ -270,25 +272,28 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Shortcuts in backward direction
|
// Shortcuts in backward direction
|
||||||
const auto &cell = cells.GetCell(metric, level, partition.GetCell(level, node));
|
const auto &cell =
|
||||||
|
cells.GetCell(metric, level, partition.GetCell(level, heapNode.node));
|
||||||
auto source = cell.GetSourceNodes().begin();
|
auto source = cell.GetSourceNodes().begin();
|
||||||
for (auto shortcut_weight : cell.GetInWeight(node))
|
for (auto shortcut_weight : cell.GetInWeight(heapNode.node))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(source != cell.GetSourceNodes().end());
|
BOOST_ASSERT(source != cell.GetSourceNodes().end());
|
||||||
const NodeID to = *source;
|
const NodeID to = *source;
|
||||||
|
|
||||||
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
|
if (shortcut_weight != INVALID_EDGE_WEIGHT && heapNode.node != to)
|
||||||
{
|
{
|
||||||
const EdgeWeight to_weight = weight + shortcut_weight;
|
const EdgeWeight to_weight = heapNode.weight + shortcut_weight;
|
||||||
BOOST_ASSERT(to_weight >= weight);
|
BOOST_ASSERT(to_weight >= heapNode.weight);
|
||||||
if (!forward_heap.WasInserted(to))
|
const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
|
||||||
|
if (!toHeapNode)
|
||||||
{
|
{
|
||||||
forward_heap.Insert(to, to_weight, {node, true});
|
forward_heap.Insert(to, to_weight, {heapNode.node, true});
|
||||||
}
|
}
|
||||||
else if (to_weight < forward_heap.GetKey(to))
|
else if (to_weight < toHeapNode->weight)
|
||||||
{
|
{
|
||||||
forward_heap.GetData(to) = {node, true};
|
toHeapNode->data = {heapNode.node, true};
|
||||||
forward_heap.DecreaseKey(to, to_weight);
|
toHeapNode->weight = to_weight;
|
||||||
|
forward_heap.DecreaseKey(*toHeapNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++source;
|
++source;
|
||||||
@ -297,7 +302,7 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Boundary edges
|
// Boundary edges
|
||||||
for (const auto edge : facade.GetBorderEdgeRange(level, node))
|
for (const auto edge : facade.GetBorderEdgeRange(level, heapNode.node))
|
||||||
{
|
{
|
||||||
const auto &edge_data = facade.GetEdgeData(edge);
|
const auto &edge_data = facade.GetEdgeData(edge);
|
||||||
|
|
||||||
@ -310,21 +315,23 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
|||||||
checkParentCellRestriction(partition.GetCell(level + 1, to), args...))
|
checkParentCellRestriction(partition.GetCell(level + 1, to), args...))
|
||||||
{
|
{
|
||||||
const auto node_weight =
|
const auto node_weight =
|
||||||
facade.GetNodeWeight(DIRECTION == FORWARD_DIRECTION ? node : to);
|
facade.GetNodeWeight(DIRECTION == FORWARD_DIRECTION ? heapNode.node : to);
|
||||||
const auto turn_penalty = facade.GetWeightPenaltyForEdgeID(edge_data.turn_id);
|
const auto turn_penalty = facade.GetWeightPenaltyForEdgeID(edge_data.turn_id);
|
||||||
|
|
||||||
// TODO: BOOST_ASSERT(edge_data.weight == node_weight + turn_penalty);
|
// TODO: BOOST_ASSERT(edge_data.weight == node_weight + turn_penalty);
|
||||||
|
|
||||||
const EdgeWeight to_weight = weight + node_weight + turn_penalty;
|
const EdgeWeight to_weight = heapNode.weight + node_weight + turn_penalty;
|
||||||
|
|
||||||
if (!forward_heap.WasInserted(to))
|
const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
|
||||||
|
if (!toHeapNode)
|
||||||
{
|
{
|
||||||
forward_heap.Insert(to, to_weight, {node, false});
|
forward_heap.Insert(to, to_weight, {heapNode.node, false});
|
||||||
}
|
}
|
||||||
else if (to_weight < forward_heap.GetKey(to))
|
else if (to_weight < toHeapNode->weight)
|
||||||
{
|
{
|
||||||
forward_heap.GetData(to) = {node, false};
|
toHeapNode->data = {heapNode.node, false};
|
||||||
forward_heap.DecreaseKey(to, to_weight);
|
toHeapNode->weight = to_weight;
|
||||||
|
forward_heap.DecreaseKey(*toHeapNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -341,34 +348,35 @@ void routingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const bool force_loop_reverse,
|
const bool force_loop_reverse,
|
||||||
Args... args)
|
Args... args)
|
||||||
{
|
{
|
||||||
const auto node = forward_heap.DeleteMin();
|
const auto heapNode = forward_heap.DeleteMinGetHeapNode();
|
||||||
const auto weight = forward_heap.GetKey(node);
|
const auto weight = heapNode.weight;
|
||||||
|
|
||||||
BOOST_ASSERT(!facade.ExcludeNode(node));
|
BOOST_ASSERT(!facade.ExcludeNode(heapNode.node));
|
||||||
|
|
||||||
// Upper bound for the path source -> target with
|
// Upper bound for the path source -> target with
|
||||||
// weight(source -> node) = weight weight(to -> target) ≤ reverse_weight
|
// weight(source -> node) = weight weight(to -> target) ≤ reverse_weight
|
||||||
// is weight + reverse_weight
|
// is weight + reverse_weight
|
||||||
// More tighter upper bound requires additional condition reverse_heap.WasRemoved(to)
|
// More tighter upper bound requires additional condition reverse_heap.WasRemoved(to)
|
||||||
// with weight(to -> target) = reverse_weight and all weights ≥ 0
|
// with weight(to -> target) = reverse_weight and all weights ≥ 0
|
||||||
if (reverse_heap.WasInserted(node))
|
const auto reverseHeapNode = reverse_heap.GetHeapNodeIfWasInserted(heapNode.node);
|
||||||
|
if (reverseHeapNode)
|
||||||
{
|
{
|
||||||
auto reverse_weight = reverse_heap.GetKey(node);
|
auto reverse_weight = reverseHeapNode->weight;
|
||||||
auto path_weight = weight + reverse_weight;
|
auto path_weight = weight + reverse_weight;
|
||||||
|
|
||||||
// MLD uses loops forcing only to prune single node paths in forward and/or
|
// MLD uses loops forcing only to prune single node paths in forward and/or
|
||||||
// backward direction (there is no need to force loops in MLD but in CH)
|
// backward direction (there is no need to force loops in MLD but in CH)
|
||||||
if (!(force_loop_forward && forward_heap.GetData(node).parent == node) &&
|
if (!(force_loop_forward && heapNode.data.parent == heapNode.node) &&
|
||||||
!(force_loop_reverse && reverse_heap.GetData(node).parent == node) &&
|
!(force_loop_reverse && reverseHeapNode->data.parent == heapNode.node) &&
|
||||||
(path_weight >= 0) && (path_weight < path_upper_bound))
|
(path_weight >= 0) && (path_weight < path_upper_bound))
|
||||||
{
|
{
|
||||||
middle_node = node;
|
middle_node = heapNode.node;
|
||||||
path_upper_bound = path_weight;
|
path_upper_bound = path_weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relax outgoing edges from node
|
// Relax outgoing edges from node
|
||||||
relaxOutgoingEdges<DIRECTION>(facade, forward_heap, node, weight, args...);
|
relaxOutgoingEdges<DIRECTION>(facade, forward_heap, heapNode, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// With (s, middle, t) we trace back the paths middle -> s and middle -> t.
|
// With (s, middle, t) we trace back the paths middle -> s and middle -> t.
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
#include <boost/heap/d_ary_heap.hpp>
|
#include <boost/heap/d_ary_heap.hpp>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@ -194,10 +195,26 @@ template <typename NodeID,
|
|||||||
typename IndexStorage = ArrayStorage<NodeID, NodeID>>
|
typename IndexStorage = ArrayStorage<NodeID, NodeID>>
|
||||||
class QueryHeap
|
class QueryHeap
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
using HeapData = std::pair<Weight, Key>;
|
||||||
|
using HeapContainer = boost::heap::d_ary_heap<HeapData,
|
||||||
|
boost::heap::arity<4>,
|
||||||
|
boost::heap::mutable_<true>,
|
||||||
|
boost::heap::compare<std::greater<HeapData>>>;
|
||||||
|
using HeapHandle = typename HeapContainer::handle_type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using WeightType = Weight;
|
using WeightType = Weight;
|
||||||
using DataType = Data;
|
using DataType = Data;
|
||||||
|
|
||||||
|
struct HeapNode
|
||||||
|
{
|
||||||
|
HeapHandle handle;
|
||||||
|
NodeID node;
|
||||||
|
Weight weight;
|
||||||
|
Data data;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename... StorageArgs> explicit QueryHeap(StorageArgs... args) : node_index(args...)
|
template <typename... StorageArgs> explicit QueryHeap(StorageArgs... args) : node_index(args...)
|
||||||
{
|
{
|
||||||
Clear();
|
Clear();
|
||||||
@ -230,6 +247,13 @@ class QueryHeap
|
|||||||
return inserted_nodes[index].data;
|
return inserted_nodes[index].data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HeapNode &getHeapNode(NodeID node)
|
||||||
|
{
|
||||||
|
const auto index = node_index.peek_index(node);
|
||||||
|
BOOST_ASSERT((int)index >= 0 && (int)index < (int)inserted_nodes.size());
|
||||||
|
return inserted_nodes[index];
|
||||||
|
}
|
||||||
|
|
||||||
Data const &GetData(NodeID node) const
|
Data const &GetData(NodeID node) const
|
||||||
{
|
{
|
||||||
const auto index = node_index.peek_index(node);
|
const auto index = node_index.peek_index(node);
|
||||||
@ -269,6 +293,28 @@ class QueryHeap
|
|||||||
return inserted_nodes[index].node == node;
|
return inserted_nodes[index].node == node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::optional<HeapNode &> GetHeapNodeIfWasInserted(const NodeID node)
|
||||||
|
{
|
||||||
|
const auto index = node_index.peek_index(node);
|
||||||
|
if (index >= static_cast<decltype(index)>(inserted_nodes.size()) ||
|
||||||
|
inserted_nodes[index].node != node)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return inserted_nodes[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<const HeapNode &> GetHeapNodeIfWasInserted(const NodeID node) const
|
||||||
|
{
|
||||||
|
const auto index = node_index.peek_index(node);
|
||||||
|
if (index >= static_cast<decltype(index)>(inserted_nodes.size()) ||
|
||||||
|
inserted_nodes[index].node != node)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return inserted_nodes[index];
|
||||||
|
}
|
||||||
|
|
||||||
NodeID Min() const
|
NodeID Min() const
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!heap.empty());
|
BOOST_ASSERT(!heap.empty());
|
||||||
@ -290,6 +336,15 @@ class QueryHeap
|
|||||||
return inserted_nodes[removedIndex].node;
|
return inserted_nodes[removedIndex].node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HeapNode &DeleteMinGetHeapNode()
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(!heap.empty());
|
||||||
|
const Key removedIndex = heap.top().second;
|
||||||
|
heap.pop();
|
||||||
|
inserted_nodes[removedIndex].handle = heap.s_handle_from_iterator(heap.end());
|
||||||
|
return inserted_nodes[removedIndex];
|
||||||
|
}
|
||||||
|
|
||||||
void DeleteAll()
|
void DeleteAll()
|
||||||
{
|
{
|
||||||
auto const none_handle = heap.s_handle_from_iterator(heap.end());
|
auto const none_handle = heap.s_handle_from_iterator(heap.end());
|
||||||
@ -308,22 +363,13 @@ class QueryHeap
|
|||||||
heap.increase(reference.handle, std::make_pair(weight, index));
|
heap.increase(reference.handle, std::make_pair(weight, index));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
void DecreaseKey(const HeapNode &heapNode)
|
||||||
using HeapData = std::pair<Weight, Key>;
|
|
||||||
using HeapContainer = boost::heap::d_ary_heap<HeapData,
|
|
||||||
boost::heap::arity<4>,
|
|
||||||
boost::heap::mutable_<true>,
|
|
||||||
boost::heap::compare<std::greater<HeapData>>>;
|
|
||||||
using HeapHandle = typename HeapContainer::handle_type;
|
|
||||||
|
|
||||||
struct HeapNode
|
|
||||||
{
|
{
|
||||||
HeapHandle handle;
|
BOOST_ASSERT(!WasRemoved(heapNode.node));
|
||||||
NodeID node;
|
heap.increase(heapNode.handle, std::make_pair(heapNode.weight, (*heapNode.handle).second));
|
||||||
Weight weight;
|
}
|
||||||
Data data;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
private:
|
||||||
std::vector<HeapNode> inserted_nodes;
|
std::vector<HeapNode> inserted_nodes;
|
||||||
HeapContainer heap;
|
HeapContainer heap;
|
||||||
IndexStorage node_index;
|
IndexStorage node_index;
|
||||||
|
@ -32,16 +32,18 @@ void relaxNode(ContractorHeap &heap,
|
|||||||
}
|
}
|
||||||
const EdgeWeight to_weight = node_weight + data.weight;
|
const EdgeWeight to_weight = node_weight + data.weight;
|
||||||
|
|
||||||
|
const auto toHeapNode = heap.GetHeapNodeIfWasInserted(to);
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if (!heap.WasInserted(to))
|
if (!toHeapNode)
|
||||||
{
|
{
|
||||||
heap.Insert(to, to_weight, ContractorHeapData{current_hop, false});
|
heap.Insert(to, to_weight, ContractorHeapData{current_hop, false});
|
||||||
}
|
}
|
||||||
// Found a shorter Path -> Update weight
|
// Found a shorter Path -> Update weight
|
||||||
else if (to_weight < heap.GetKey(to))
|
else if (to_weight < toHeapNode->weight)
|
||||||
{
|
{
|
||||||
heap.DecreaseKey(to, to_weight);
|
toHeapNode->weight = to_weight;
|
||||||
heap.GetData(to).hop = current_hop;
|
heap.DecreaseKey(*toHeapNode);
|
||||||
|
toHeapNode->data.hop = current_hop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,11 +62,12 @@ void alternativeRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
QueryHeap &forward_heap = DIRECTION == FORWARD_DIRECTION ? heap1 : heap2;
|
QueryHeap &forward_heap = DIRECTION == FORWARD_DIRECTION ? heap1 : heap2;
|
||||||
QueryHeap &reverse_heap = DIRECTION == FORWARD_DIRECTION ? heap2 : heap1;
|
QueryHeap &reverse_heap = DIRECTION == FORWARD_DIRECTION ? heap2 : heap1;
|
||||||
|
|
||||||
const NodeID node = forward_heap.DeleteMin();
|
// Take a copy (no ref &) of the extracted node because otherwise could be modified later if
|
||||||
const EdgeWeight weight = forward_heap.GetKey(node);
|
// toHeapNode is the same
|
||||||
|
const auto heapNode = forward_heap.DeleteMinGetHeapNode();
|
||||||
|
|
||||||
const auto scaled_weight =
|
const auto scaled_weight =
|
||||||
static_cast<EdgeWeight>((weight + min_edge_offset) / (1. + VIAPATH_EPSILON));
|
static_cast<EdgeWeight>((heapNode.weight + min_edge_offset) / (1. + VIAPATH_EPSILON));
|
||||||
if ((INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_weight) &&
|
if ((INVALID_EDGE_WEIGHT != *upper_bound_to_shortest_path_weight) &&
|
||||||
(scaled_weight > *upper_bound_to_shortest_path_weight))
|
(scaled_weight > *upper_bound_to_shortest_path_weight))
|
||||||
{
|
{
|
||||||
@ -74,35 +75,36 @@ void alternativeRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
search_space.emplace_back(forward_heap.GetData(node).parent, node);
|
search_space.emplace_back(heapNode.data.parent, heapNode.node);
|
||||||
|
|
||||||
if (reverse_heap.WasInserted(node))
|
const auto reverseHeapNode = reverse_heap.GetHeapNodeIfWasInserted(heapNode.node);
|
||||||
|
if (reverseHeapNode)
|
||||||
{
|
{
|
||||||
search_space_intersection.emplace_back(node);
|
search_space_intersection.emplace_back(heapNode.node);
|
||||||
const EdgeWeight new_weight = reverse_heap.GetKey(node) + weight;
|
const EdgeWeight new_weight = reverseHeapNode->weight + heapNode.weight;
|
||||||
if (new_weight < *upper_bound_to_shortest_path_weight)
|
if (new_weight < *upper_bound_to_shortest_path_weight)
|
||||||
{
|
{
|
||||||
if (new_weight >= 0)
|
if (new_weight >= 0)
|
||||||
{
|
{
|
||||||
*middle_node = node;
|
*middle_node = heapNode.node;
|
||||||
*upper_bound_to_shortest_path_weight = new_weight;
|
*upper_bound_to_shortest_path_weight = new_weight;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check whether there is a loop present at the node
|
// check whether there is a loop present at the node
|
||||||
const auto loop_weight = std::get<0>(getLoopWeight<false>(facade, node));
|
const auto loop_weight = std::get<0>(getLoopWeight<false>(facade, heapNode.node));
|
||||||
const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
|
const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
|
||||||
if (loop_weight != INVALID_EDGE_WEIGHT &&
|
if (loop_weight != INVALID_EDGE_WEIGHT &&
|
||||||
new_weight_with_loop <= *upper_bound_to_shortest_path_weight)
|
new_weight_with_loop <= *upper_bound_to_shortest_path_weight)
|
||||||
{
|
{
|
||||||
*middle_node = node;
|
*middle_node = heapNode.node;
|
||||||
*upper_bound_to_shortest_path_weight = loop_weight;
|
*upper_bound_to_shortest_path_weight = loop_weight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
for (auto edge : facade.GetAdjacentEdgeRange(heapNode.node))
|
||||||
{
|
{
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
|
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
|
||||||
@ -111,20 +113,22 @@ void alternativeRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const EdgeWeight edge_weight = data.weight;
|
const EdgeWeight edge_weight = data.weight;
|
||||||
|
|
||||||
BOOST_ASSERT(edge_weight > 0);
|
BOOST_ASSERT(edge_weight > 0);
|
||||||
const EdgeWeight to_weight = weight + edge_weight;
|
const EdgeWeight to_weight = heapNode.weight + edge_weight;
|
||||||
|
|
||||||
|
const auto toHeapNode = forward_heap.GetHeapNodeIfWasInserted(to);
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if (!forward_heap.WasInserted(to))
|
if (!toHeapNode)
|
||||||
{
|
{
|
||||||
forward_heap.Insert(to, to_weight, node);
|
forward_heap.Insert(to, to_weight, heapNode.node);
|
||||||
}
|
}
|
||||||
// Found a shorter Path -> Update weight
|
// Found a shorter Path -> Update weight
|
||||||
else if (to_weight < forward_heap.GetKey(to))
|
else if (to_weight < toHeapNode->weight)
|
||||||
{
|
{
|
||||||
// new parent
|
// new parent
|
||||||
forward_heap.GetData(to).parent = node;
|
toHeapNode->data.parent = heapNode.node;
|
||||||
// decreased weight
|
// decreased weight
|
||||||
forward_heap.DecreaseKey(to, to_weight);
|
toHeapNode->weight = to_weight;
|
||||||
|
forward_heap.DecreaseKey(*toHeapNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,20 +45,18 @@ inline bool addLoopWeight(const DataFacade<ch::Algorithm> &facade,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool DIRECTION>
|
template <bool DIRECTION>
|
||||||
void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
void relaxOutgoingEdges(
|
||||||
const NodeID node,
|
const DataFacade<Algorithm> &facade,
|
||||||
const EdgeWeight weight,
|
const typename SearchEngineData<Algorithm>::ManyToManyQueryHeap::HeapNode &heapNode,
|
||||||
const EdgeDuration duration,
|
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
|
||||||
const EdgeDistance distance,
|
const PhantomNode &)
|
||||||
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
|
|
||||||
const PhantomNode &)
|
|
||||||
{
|
{
|
||||||
if (stallAtNode<DIRECTION>(facade, node, weight, query_heap))
|
if (stallAtNode<DIRECTION>(facade, heapNode, query_heap))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
for (auto edge : facade.GetAdjacentEdgeRange(heapNode.node))
|
||||||
{
|
{
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
|
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
|
||||||
@ -70,21 +68,23 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
|||||||
const auto edge_distance = data.distance;
|
const auto edge_distance = data.distance;
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
const auto to_weight = weight + edge_weight;
|
const auto to_weight = heapNode.weight + edge_weight;
|
||||||
const auto to_duration = duration + edge_duration;
|
const auto to_duration = heapNode.data.duration + edge_duration;
|
||||||
const auto to_distance = distance + edge_distance;
|
const auto to_distance = heapNode.data.distance + edge_distance;
|
||||||
|
|
||||||
|
const auto toHeapNode = query_heap.GetHeapNodeIfWasInserted(to);
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if (!query_heap.WasInserted(to))
|
if (!toHeapNode)
|
||||||
{
|
{
|
||||||
query_heap.Insert(to, to_weight, {node, to_duration, to_distance});
|
query_heap.Insert(to, to_weight, {heapNode.node, to_duration, to_distance});
|
||||||
}
|
}
|
||||||
// Found a shorter Path -> Update weight and set new parent
|
// Found a shorter Path -> Update weight and set new parent
|
||||||
else if (std::tie(to_weight, to_duration) <
|
else if (std::tie(to_weight, to_duration) <
|
||||||
std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration))
|
std::tie(toHeapNode->weight, toHeapNode->data.duration))
|
||||||
{
|
{
|
||||||
query_heap.GetData(to) = {node, to_duration, to_distance};
|
toHeapNode->data = {heapNode.node, to_duration, to_distance};
|
||||||
query_heap.DecreaseKey(to, to_weight);
|
toHeapNode->weight = to_weight;
|
||||||
|
query_heap.DecreaseKey(*toHeapNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,15 +101,14 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
std::vector<NodeID> &middle_nodes_table,
|
std::vector<NodeID> &middle_nodes_table,
|
||||||
const PhantomNode &phantom_node)
|
const PhantomNode &phantom_node)
|
||||||
{
|
{
|
||||||
const auto node = query_heap.DeleteMin();
|
// Take a copy of the extracted node because otherwise could be modified later if toHeapNode is
|
||||||
const auto source_weight = query_heap.GetKey(node);
|
// the same
|
||||||
const auto source_duration = query_heap.GetData(node).duration;
|
const auto heapNode = query_heap.DeleteMinGetHeapNode();
|
||||||
const auto source_distance = query_heap.GetData(node).distance;
|
|
||||||
|
|
||||||
// Check if each encountered node has an entry
|
// Check if each encountered node has an entry
|
||||||
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
|
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
|
||||||
search_space_with_buckets.end(),
|
search_space_with_buckets.end(),
|
||||||
node,
|
heapNode.node,
|
||||||
NodeBucket::Compare());
|
NodeBucket::Compare());
|
||||||
for (const auto ¤t_bucket : boost::make_iterator_range(bucket_list))
|
for (const auto ¤t_bucket : boost::make_iterator_range(bucket_list))
|
||||||
{
|
{
|
||||||
@ -129,18 +128,18 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
: distances_table[row_index * number_of_targets + column_index];
|
: distances_table[row_index * number_of_targets + column_index];
|
||||||
|
|
||||||
// Check if new weight is better
|
// Check if new weight is better
|
||||||
auto new_weight = source_weight + target_weight;
|
auto new_weight = heapNode.weight + target_weight;
|
||||||
auto new_duration = source_duration + target_duration;
|
auto new_duration = heapNode.data.duration + target_duration;
|
||||||
auto new_distance = source_distance + target_distance;
|
auto new_distance = heapNode.data.distance + target_distance;
|
||||||
|
|
||||||
if (new_weight < 0)
|
if (new_weight < 0)
|
||||||
{
|
{
|
||||||
if (addLoopWeight(facade, node, new_weight, new_duration, new_distance))
|
if (addLoopWeight(facade, heapNode.node, new_weight, new_duration, new_distance))
|
||||||
{
|
{
|
||||||
current_weight = std::min(current_weight, new_weight);
|
current_weight = std::min(current_weight, new_weight);
|
||||||
current_duration = std::min(current_duration, new_duration);
|
current_duration = std::min(current_duration, new_duration);
|
||||||
current_distance = std::min(current_distance, new_distance);
|
current_distance = std::min(current_distance, new_distance);
|
||||||
middle_nodes_table[row_index * number_of_targets + column_index] = node;
|
middle_nodes_table[row_index * number_of_targets + column_index] = heapNode.node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (std::tie(new_weight, new_duration) < std::tie(current_weight, current_duration))
|
else if (std::tie(new_weight, new_duration) < std::tie(current_weight, current_duration))
|
||||||
@ -148,12 +147,11 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
current_weight = new_weight;
|
current_weight = new_weight;
|
||||||
current_duration = new_duration;
|
current_duration = new_duration;
|
||||||
current_distance = new_distance;
|
current_distance = new_distance;
|
||||||
middle_nodes_table[row_index * number_of_targets + column_index] = node;
|
middle_nodes_table[row_index * number_of_targets + column_index] = heapNode.node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
relaxOutgoingEdges<FORWARD_DIRECTION>(
|
relaxOutgoingEdges<FORWARD_DIRECTION>(facade, heapNode, query_heap, phantom_node);
|
||||||
facade, node, source_weight, source_duration, source_distance, query_heap, phantom_node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void backwardRoutingStep(const DataFacade<Algorithm> &facade,
|
void backwardRoutingStep(const DataFacade<Algorithm> &facade,
|
||||||
@ -162,18 +160,19 @@ void backwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
std::vector<NodeBucket> &search_space_with_buckets,
|
std::vector<NodeBucket> &search_space_with_buckets,
|
||||||
const PhantomNode &phantom_node)
|
const PhantomNode &phantom_node)
|
||||||
{
|
{
|
||||||
const auto node = query_heap.DeleteMin();
|
// Take a copy (no ref &) of the extracted node because otherwise could be modified later if
|
||||||
const auto target_weight = query_heap.GetKey(node);
|
// toHeapNode is the same
|
||||||
const auto target_duration = query_heap.GetData(node).duration;
|
const auto heapNode = query_heap.DeleteMinGetHeapNode();
|
||||||
const auto target_distance = query_heap.GetData(node).distance;
|
|
||||||
const auto parent = query_heap.GetData(node).parent;
|
|
||||||
|
|
||||||
// Store settled nodes in search space bucket
|
// Store settled nodes in search space bucket
|
||||||
search_space_with_buckets.emplace_back(
|
search_space_with_buckets.emplace_back(heapNode.node,
|
||||||
node, parent, column_index, target_weight, target_duration, target_distance);
|
heapNode.data.parent,
|
||||||
|
column_index,
|
||||||
|
heapNode.weight,
|
||||||
|
heapNode.data.duration,
|
||||||
|
heapNode.data.distance);
|
||||||
|
|
||||||
relaxOutgoingEdges<REVERSE_DIRECTION>(
|
relaxOutgoingEdges<REVERSE_DIRECTION>(facade, heapNode, query_heap, phantom_node);
|
||||||
facade, node, target_weight, target_duration, target_distance, query_heap, phantom_node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ch
|
} // namespace ch
|
||||||
|
@ -71,38 +71,38 @@ void relaxBorderEdges(const DataFacade<mld::Algorithm> &facade,
|
|||||||
const auto to_distance = distance + node_distance;
|
const auto to_distance = distance + node_distance;
|
||||||
|
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if (!query_heap.WasInserted(to))
|
const auto toHeapNode = query_heap.GetHeapNodeIfWasInserted(to);
|
||||||
|
if (!toHeapNode)
|
||||||
{
|
{
|
||||||
query_heap.Insert(to, to_weight, {node, false, to_duration, to_distance});
|
query_heap.Insert(to, to_weight, {node, false, to_duration, to_distance});
|
||||||
}
|
}
|
||||||
// Found a shorter Path -> Update weight and set new parent
|
// Found a shorter Path -> Update weight and set new parent
|
||||||
else if (std::tie(to_weight, to_duration, to_distance, node) <
|
else if (std::tie(to_weight, to_duration, to_distance, node) <
|
||||||
std::tie(query_heap.GetKey(to),
|
std::tie(toHeapNode->weight,
|
||||||
query_heap.GetData(to).duration,
|
toHeapNode->data.duration,
|
||||||
query_heap.GetData(to).distance,
|
toHeapNode->data.distance,
|
||||||
query_heap.GetData(to).parent))
|
toHeapNode->data.parent))
|
||||||
{
|
{
|
||||||
query_heap.GetData(to) = {node, false, to_duration, to_distance};
|
toHeapNode->data = {node, false, to_duration, to_distance};
|
||||||
query_heap.DecreaseKey(to, to_weight);
|
toHeapNode->weight = to_weight;
|
||||||
|
query_heap.DecreaseKey(*toHeapNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool DIRECTION, typename... Args>
|
template <bool DIRECTION, typename... Args>
|
||||||
void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
|
void relaxOutgoingEdges(
|
||||||
const NodeID node,
|
const DataFacade<mld::Algorithm> &facade,
|
||||||
const EdgeWeight weight,
|
const typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap::HeapNode &heapNode,
|
||||||
const EdgeDuration duration,
|
typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &query_heap,
|
||||||
const EdgeDistance distance,
|
Args... args)
|
||||||
typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &query_heap,
|
|
||||||
Args... args)
|
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(!facade.ExcludeNode(node));
|
BOOST_ASSERT(!facade.ExcludeNode(heapNode.node));
|
||||||
|
|
||||||
const auto &partition = facade.GetMultiLevelPartition();
|
const auto &partition = facade.GetMultiLevelPartition();
|
||||||
|
|
||||||
const auto level = getNodeQueryLevel(partition, node, args...);
|
const auto level = getNodeQueryLevel(partition, heapNode.node, args...);
|
||||||
|
|
||||||
// Break outgoing edges relaxation if node at the restricted level
|
// Break outgoing edges relaxation if node at the restricted level
|
||||||
if (level == INVALID_LEVEL_ID)
|
if (level == INVALID_LEVEL_ID)
|
||||||
@ -110,40 +110,42 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
|
|||||||
|
|
||||||
const auto &cells = facade.GetCellStorage();
|
const auto &cells = facade.GetCellStorage();
|
||||||
const auto &metric = facade.GetCellMetric();
|
const auto &metric = facade.GetCellMetric();
|
||||||
const auto &node_data = query_heap.GetData(node);
|
|
||||||
|
|
||||||
if (level >= 1 && !node_data.from_clique_arc)
|
if (level >= 1 && !heapNode.data.from_clique_arc)
|
||||||
{
|
{
|
||||||
const auto &cell = cells.GetCell(metric, level, partition.GetCell(level, node));
|
const auto &cell = cells.GetCell(metric, level, partition.GetCell(level, heapNode.node));
|
||||||
if (DIRECTION == FORWARD_DIRECTION)
|
if (DIRECTION == FORWARD_DIRECTION)
|
||||||
{ // Shortcuts in forward direction
|
{ // Shortcuts in forward direction
|
||||||
auto destination = cell.GetDestinationNodes().begin();
|
auto destination = cell.GetDestinationNodes().begin();
|
||||||
auto shortcut_durations = cell.GetOutDuration(node);
|
auto shortcut_durations = cell.GetOutDuration(heapNode.node);
|
||||||
auto shortcut_distances = cell.GetOutDistance(node);
|
auto shortcut_distances = cell.GetOutDistance(heapNode.node);
|
||||||
for (auto shortcut_weight : cell.GetOutWeight(node))
|
for (auto shortcut_weight : cell.GetOutWeight(heapNode.node))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(destination != cell.GetDestinationNodes().end());
|
BOOST_ASSERT(destination != cell.GetDestinationNodes().end());
|
||||||
BOOST_ASSERT(!shortcut_durations.empty());
|
BOOST_ASSERT(!shortcut_durations.empty());
|
||||||
BOOST_ASSERT(!shortcut_distances.empty());
|
BOOST_ASSERT(!shortcut_distances.empty());
|
||||||
const NodeID to = *destination;
|
const NodeID to = *destination;
|
||||||
|
|
||||||
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
|
if (shortcut_weight != INVALID_EDGE_WEIGHT && heapNode.node != to)
|
||||||
{
|
{
|
||||||
const auto to_weight = weight + shortcut_weight;
|
const auto to_weight = heapNode.weight + shortcut_weight;
|
||||||
const auto to_duration = duration + shortcut_durations.front();
|
const auto to_duration = heapNode.data.duration + shortcut_durations.front();
|
||||||
const auto to_distance = distance + shortcut_distances.front();
|
const auto to_distance = heapNode.data.distance + shortcut_distances.front();
|
||||||
if (!query_heap.WasInserted(to))
|
const auto toHeapNode = query_heap.GetHeapNodeIfWasInserted(to);
|
||||||
|
if (!toHeapNode)
|
||||||
{
|
{
|
||||||
query_heap.Insert(to, to_weight, {node, true, to_duration, to_distance});
|
query_heap.Insert(
|
||||||
|
to, to_weight, {heapNode.node, true, to_duration, to_distance});
|
||||||
}
|
}
|
||||||
else if (std::tie(to_weight, to_duration, to_distance, node) <
|
else if (std::tie(to_weight, to_duration, to_distance, heapNode.node) <
|
||||||
std::tie(query_heap.GetKey(to),
|
std::tie(toHeapNode->weight,
|
||||||
query_heap.GetData(to).duration,
|
toHeapNode->data.duration,
|
||||||
query_heap.GetData(to).distance,
|
toHeapNode->data.distance,
|
||||||
query_heap.GetData(to).parent))
|
toHeapNode->data.parent))
|
||||||
{
|
{
|
||||||
query_heap.GetData(to) = {node, true, to_duration, to_distance};
|
toHeapNode->data = {heapNode.node, true, to_duration, to_distance};
|
||||||
query_heap.DecreaseKey(to, to_weight);
|
toHeapNode->weight = to_weight;
|
||||||
|
query_heap.DecreaseKey(*toHeapNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++destination;
|
++destination;
|
||||||
@ -156,32 +158,35 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
|
|||||||
else
|
else
|
||||||
{ // Shortcuts in backward direction
|
{ // Shortcuts in backward direction
|
||||||
auto source = cell.GetSourceNodes().begin();
|
auto source = cell.GetSourceNodes().begin();
|
||||||
auto shortcut_durations = cell.GetInDuration(node);
|
auto shortcut_durations = cell.GetInDuration(heapNode.node);
|
||||||
auto shortcut_distances = cell.GetInDistance(node);
|
auto shortcut_distances = cell.GetInDistance(heapNode.node);
|
||||||
for (auto shortcut_weight : cell.GetInWeight(node))
|
for (auto shortcut_weight : cell.GetInWeight(heapNode.node))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(source != cell.GetSourceNodes().end());
|
BOOST_ASSERT(source != cell.GetSourceNodes().end());
|
||||||
BOOST_ASSERT(!shortcut_durations.empty());
|
BOOST_ASSERT(!shortcut_durations.empty());
|
||||||
BOOST_ASSERT(!shortcut_distances.empty());
|
BOOST_ASSERT(!shortcut_distances.empty());
|
||||||
const NodeID to = *source;
|
const NodeID to = *source;
|
||||||
|
|
||||||
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
|
if (shortcut_weight != INVALID_EDGE_WEIGHT && heapNode.node != to)
|
||||||
{
|
{
|
||||||
const auto to_weight = weight + shortcut_weight;
|
const auto to_weight = heapNode.weight + shortcut_weight;
|
||||||
const auto to_duration = duration + shortcut_durations.front();
|
const auto to_duration = heapNode.data.duration + shortcut_durations.front();
|
||||||
const auto to_distance = distance + shortcut_distances.front();
|
const auto to_distance = heapNode.data.distance + shortcut_distances.front();
|
||||||
if (!query_heap.WasInserted(to))
|
const auto toHeapNode = query_heap.GetHeapNodeIfWasInserted(to);
|
||||||
|
if (!toHeapNode)
|
||||||
{
|
{
|
||||||
query_heap.Insert(to, to_weight, {node, true, to_duration, to_distance});
|
query_heap.Insert(
|
||||||
|
to, to_weight, {heapNode.node, true, to_duration, to_distance});
|
||||||
}
|
}
|
||||||
else if (std::tie(to_weight, to_duration, to_distance, node) <
|
else if (std::tie(to_weight, to_duration, to_distance, heapNode.node) <
|
||||||
std::tie(query_heap.GetKey(to),
|
std::tie(toHeapNode->weight,
|
||||||
query_heap.GetData(to).duration,
|
toHeapNode->data.duration,
|
||||||
query_heap.GetData(to).distance,
|
toHeapNode->data.distance,
|
||||||
query_heap.GetData(to).parent))
|
toHeapNode->data.parent))
|
||||||
{
|
{
|
||||||
query_heap.GetData(to) = {node, true, to_duration, to_distance};
|
toHeapNode->data = {heapNode.node, true, to_duration, to_distance};
|
||||||
query_heap.DecreaseKey(to, to_weight);
|
toHeapNode->weight = to_weight;
|
||||||
|
query_heap.DecreaseKey(*toHeapNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
++source;
|
++source;
|
||||||
@ -193,7 +198,13 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
relaxBorderEdges<DIRECTION>(facade, node, weight, duration, distance, query_heap, level);
|
relaxBorderEdges<DIRECTION>(facade,
|
||||||
|
heapNode.node,
|
||||||
|
heapNode.weight,
|
||||||
|
heapNode.data.duration,
|
||||||
|
heapNode.data.distance,
|
||||||
|
query_heap,
|
||||||
|
level);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -368,25 +379,17 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
|
|
||||||
while (!query_heap.Empty() && !target_nodes_index.empty())
|
while (!query_heap.Empty() && !target_nodes_index.empty())
|
||||||
{
|
{
|
||||||
// Extract node from the heap
|
// Extract node from the heap. Take a copy (no ref) because otherwise can be modified later
|
||||||
const auto node = query_heap.DeleteMin();
|
// if toHeapNode is the same
|
||||||
const auto weight = query_heap.GetKey(node);
|
const auto heapNode = query_heap.DeleteMinGetHeapNode();
|
||||||
const auto duration = query_heap.GetData(node).duration;
|
|
||||||
const auto distance = query_heap.GetData(node).distance;
|
|
||||||
|
|
||||||
// Update values
|
// Update values
|
||||||
update_values(node, weight, duration, distance);
|
update_values(
|
||||||
|
heapNode.node, heapNode.weight, heapNode.data.duration, heapNode.data.distance);
|
||||||
|
|
||||||
// Relax outgoing edges
|
// Relax outgoing edges
|
||||||
relaxOutgoingEdges<DIRECTION>(facade,
|
relaxOutgoingEdges<DIRECTION>(
|
||||||
node,
|
facade, heapNode, query_heap, phantom_nodes, phantom_index, phantom_indices);
|
||||||
weight,
|
|
||||||
duration,
|
|
||||||
distance,
|
|
||||||
query_heap,
|
|
||||||
phantom_nodes,
|
|
||||||
phantom_index,
|
|
||||||
phantom_indices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_pair(durations, distances_table);
|
return std::make_pair(durations, distances_table);
|
||||||
@ -408,15 +411,14 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
std::vector<NodeID> &middle_nodes_table,
|
std::vector<NodeID> &middle_nodes_table,
|
||||||
const PhantomNode &phantom_node)
|
const PhantomNode &phantom_node)
|
||||||
{
|
{
|
||||||
const auto node = query_heap.DeleteMin();
|
// Take a copy of the extracted node because otherwise could be modified later if toHeapNode is
|
||||||
const auto source_weight = query_heap.GetKey(node);
|
// the same
|
||||||
const auto source_duration = query_heap.GetData(node).duration;
|
const auto heapNode = query_heap.DeleteMinGetHeapNode();
|
||||||
const auto source_distance = query_heap.GetData(node).distance;
|
|
||||||
|
|
||||||
// Check if each encountered node has an entry
|
// Check if each encountered node has an entry
|
||||||
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
|
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
|
||||||
search_space_with_buckets.end(),
|
search_space_with_buckets.end(),
|
||||||
node,
|
heapNode.node,
|
||||||
NodeBucket::Compare());
|
NodeBucket::Compare());
|
||||||
for (const auto ¤t_bucket : boost::make_iterator_range(bucket_list))
|
for (const auto ¤t_bucket : boost::make_iterator_range(bucket_list))
|
||||||
{
|
{
|
||||||
@ -439,9 +441,9 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
auto ¤t_distance = distances_table.empty() ? nulldistance : distances_table[location];
|
auto ¤t_distance = distances_table.empty() ? nulldistance : distances_table[location];
|
||||||
|
|
||||||
// Check if new weight is better
|
// Check if new weight is better
|
||||||
auto new_weight = source_weight + target_weight;
|
auto new_weight = heapNode.weight + target_weight;
|
||||||
auto new_duration = source_duration + target_duration;
|
auto new_duration = heapNode.data.duration + target_duration;
|
||||||
auto new_distance = source_distance + target_distance;
|
auto new_distance = heapNode.data.distance + target_distance;
|
||||||
|
|
||||||
if (new_weight >= 0 && std::tie(new_weight, new_duration, new_distance) <
|
if (new_weight >= 0 && std::tie(new_weight, new_duration, new_distance) <
|
||||||
std::tie(current_weight, current_duration, current_distance))
|
std::tie(current_weight, current_duration, current_distance))
|
||||||
@ -449,12 +451,11 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
current_weight = new_weight;
|
current_weight = new_weight;
|
||||||
current_duration = new_duration;
|
current_duration = new_duration;
|
||||||
current_distance = new_distance;
|
current_distance = new_distance;
|
||||||
middle_nodes_table[location] = node;
|
middle_nodes_table[location] = heapNode.node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
relaxOutgoingEdges<DIRECTION>(
|
relaxOutgoingEdges<DIRECTION>(facade, heapNode, query_heap, phantom_node);
|
||||||
facade, node, source_weight, source_duration, source_distance, query_heap, phantom_node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool DIRECTION>
|
template <bool DIRECTION>
|
||||||
@ -464,28 +465,23 @@ void backwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
std::vector<NodeBucket> &search_space_with_buckets,
|
std::vector<NodeBucket> &search_space_with_buckets,
|
||||||
const PhantomNode &phantom_node)
|
const PhantomNode &phantom_node)
|
||||||
{
|
{
|
||||||
const auto node = query_heap.DeleteMin();
|
// Take a copy of the extracted node because otherwise could be modified later if toHeapNode is
|
||||||
const auto target_weight = query_heap.GetKey(node);
|
// the same
|
||||||
const auto target_duration = query_heap.GetData(node).duration;
|
const auto heapNode = query_heap.DeleteMinGetHeapNode();
|
||||||
const auto target_distance = query_heap.GetData(node).distance;
|
|
||||||
const auto parent = query_heap.GetData(node).parent;
|
|
||||||
const auto from_clique_arc = query_heap.GetData(node).from_clique_arc;
|
|
||||||
|
|
||||||
// Store settled nodes in search space bucket
|
// Store settled nodes in search space bucket
|
||||||
search_space_with_buckets.emplace_back(
|
search_space_with_buckets.emplace_back(heapNode.node,
|
||||||
node, parent, from_clique_arc, column_idx, target_weight, target_duration, target_distance);
|
heapNode.data.parent,
|
||||||
|
heapNode.data.from_clique_arc,
|
||||||
|
column_idx,
|
||||||
|
heapNode.weight,
|
||||||
|
heapNode.data.duration,
|
||||||
|
heapNode.data.distance);
|
||||||
|
|
||||||
const auto &partition = facade.GetMultiLevelPartition();
|
const auto &partition = facade.GetMultiLevelPartition();
|
||||||
const auto maximal_level = partition.GetNumberOfLevels() - 1;
|
const auto maximal_level = partition.GetNumberOfLevels() - 1;
|
||||||
|
|
||||||
relaxOutgoingEdges<!DIRECTION>(facade,
|
relaxOutgoingEdges<!DIRECTION>(facade, heapNode, query_heap, phantom_node, maximal_level);
|
||||||
node,
|
|
||||||
target_weight,
|
|
||||||
target_duration,
|
|
||||||
target_distance,
|
|
||||||
query_heap,
|
|
||||||
phantom_node,
|
|
||||||
maximal_level);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool DIRECTION>
|
template <bool DIRECTION>
|
||||||
|
Loading…
Reference in New Issue
Block a user