Matrix plugin with MLD overlay
This commit is contained in:
parent
b910ab9bcb
commit
517cb5f094
@ -1,3 +1,9 @@
|
|||||||
|
# 5.9.0
|
||||||
|
- Changes from 5.8
|
||||||
|
- Algorithm:
|
||||||
|
- Multi-Level Dijkstra:
|
||||||
|
- Plugins supported: `table`
|
||||||
|
|
||||||
# 5.8.0
|
# 5.8.0
|
||||||
- Changes from 5.7
|
- Changes from 5.7
|
||||||
- API:
|
- API:
|
||||||
|
@ -41,12 +41,6 @@ bool needsLoopForward(const PhantomNode &source_phantom, const PhantomNode &targ
|
|||||||
|
|
||||||
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &target_phantom);
|
||||||
|
|
||||||
void insertSourceInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
|
||||||
const PhantomNode &phantom_node);
|
|
||||||
|
|
||||||
void insertTargetInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
|
||||||
const PhantomNode &phantom_node);
|
|
||||||
|
|
||||||
template <typename Heap>
|
template <typename Heap>
|
||||||
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
|
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
|
||||||
{
|
{
|
||||||
@ -81,6 +75,40 @@ void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename ManyToManyQueryHeap>
|
||||||
|
void insertSourceInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
if (phantom_node.IsValidForwardSource())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.forward_segment_id.id,
|
||||||
|
-phantom_node.GetForwardWeightPlusOffset(),
|
||||||
|
{phantom_node.forward_segment_id.id, -phantom_node.GetForwardDuration()});
|
||||||
|
}
|
||||||
|
if (phantom_node.IsValidReverseSource())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.reverse_segment_id.id,
|
||||||
|
-phantom_node.GetReverseWeightPlusOffset(),
|
||||||
|
{phantom_node.reverse_segment_id.id, -phantom_node.GetReverseDuration()});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ManyToManyQueryHeap>
|
||||||
|
void insertTargetInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
if (phantom_node.IsValidForwardTarget())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.forward_segment_id.id,
|
||||||
|
phantom_node.GetForwardWeightPlusOffset(),
|
||||||
|
{phantom_node.forward_segment_id.id, phantom_node.GetForwardDuration()});
|
||||||
|
}
|
||||||
|
if (phantom_node.IsValidReverseTarget())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.reverse_segment_id.id,
|
||||||
|
phantom_node.GetReverseWeightPlusOffset(),
|
||||||
|
{phantom_node.reverse_segment_id.id, phantom_node.GetReverseDuration()});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename FacadeT>
|
template <typename FacadeT>
|
||||||
void annotatePath(const FacadeT &facade,
|
void annotatePath(const FacadeT &facade,
|
||||||
const PhantomNodes &phantom_node_pair,
|
const PhantomNodes &phantom_node_pair,
|
||||||
|
@ -78,6 +78,20 @@ struct MultiLayerDijkstraHeapData
|
|||||||
MultiLayerDijkstraHeapData(NodeID p, bool from) : parent(p), from_clique_arc(from) {}
|
MultiLayerDijkstraHeapData(NodeID p, bool from) : parent(p), from_clique_arc(from) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ManyToManyMultiLayerDijkstraHeapData : MultiLayerDijkstraHeapData
|
||||||
|
{
|
||||||
|
LevelID level;
|
||||||
|
EdgeWeight duration;
|
||||||
|
ManyToManyMultiLayerDijkstraHeapData(NodeID p, EdgeWeight duration)
|
||||||
|
: MultiLayerDijkstraHeapData(p), level(0), duration(duration)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
ManyToManyMultiLayerDijkstraHeapData(NodeID p, bool from, LevelID level, EdgeWeight duration)
|
||||||
|
: MultiLayerDijkstraHeapData(p, from), level(level), duration(duration)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
|
template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
|
||||||
{
|
{
|
||||||
using QueryHeap = util::QueryHeap<NodeID,
|
using QueryHeap = util::QueryHeap<NodeID,
|
||||||
@ -86,12 +100,23 @@ template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
|
|||||||
MultiLayerDijkstraHeapData,
|
MultiLayerDijkstraHeapData,
|
||||||
util::UnorderedMapStorage<NodeID, int>>;
|
util::UnorderedMapStorage<NodeID, int>>;
|
||||||
|
|
||||||
|
using ManyToManyQueryHeap = util::QueryHeap<NodeID,
|
||||||
|
NodeID,
|
||||||
|
EdgeWeight,
|
||||||
|
ManyToManyMultiLayerDijkstraHeapData,
|
||||||
|
util::UnorderedMapStorage<NodeID, int>>;
|
||||||
|
|
||||||
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
|
using SearchEngineHeapPtr = boost::thread_specific_ptr<QueryHeap>;
|
||||||
|
|
||||||
|
using ManyToManyHeapPtr = boost::thread_specific_ptr<ManyToManyQueryHeap>;
|
||||||
|
|
||||||
static SearchEngineHeapPtr forward_heap_1;
|
static SearchEngineHeapPtr forward_heap_1;
|
||||||
static SearchEngineHeapPtr reverse_heap_1;
|
static SearchEngineHeapPtr reverse_heap_1;
|
||||||
|
static ManyToManyHeapPtr many_to_many_heap;
|
||||||
|
|
||||||
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
void InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes);
|
||||||
|
|
||||||
|
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,11 +15,6 @@ namespace engine
|
|||||||
namespace routing_algorithms
|
namespace routing_algorithms
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace ch
|
|
||||||
{
|
|
||||||
|
|
||||||
using ManyToManyQueryHeap = SearchEngineData<Algorithm>::ManyToManyQueryHeap;
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
struct NodeBucket
|
struct NodeBucket
|
||||||
@ -32,16 +27,19 @@ struct NodeBucket
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME This should be replaced by an std::unordered_multimap, though this needs benchmarking
|
// FIXME This should be replaced by an std::unordered_multimap, though this needs benchmarking
|
||||||
using SearchSpaceWithBuckets = std::unordered_map<NodeID, std::vector<NodeBucket>>;
|
using SearchSpaceWithBuckets = std::unordered_map<NodeID, std::vector<NodeBucket>>;
|
||||||
|
|
||||||
|
namespace ch
|
||||||
|
{
|
||||||
template <bool DIRECTION>
|
template <bool DIRECTION>
|
||||||
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
const NodeID node,
|
const NodeID node,
|
||||||
const EdgeWeight weight,
|
const EdgeWeight weight,
|
||||||
const EdgeWeight duration,
|
const EdgeWeight duration,
|
||||||
ManyToManyQueryHeap &query_heap)
|
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap)
|
||||||
{
|
{
|
||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
{
|
{
|
||||||
@ -75,7 +73,7 @@ void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<Alg
|
|||||||
void forwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
void forwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
const unsigned row_idx,
|
const unsigned row_idx,
|
||||||
const unsigned number_of_targets,
|
const unsigned number_of_targets,
|
||||||
ManyToManyQueryHeap &query_heap,
|
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
|
||||||
const SearchSpaceWithBuckets &search_space_with_buckets,
|
const SearchSpaceWithBuckets &search_space_with_buckets,
|
||||||
std::vector<EdgeWeight> &weights_table,
|
std::vector<EdgeWeight> &weights_table,
|
||||||
std::vector<EdgeWeight> &durations_table)
|
std::vector<EdgeWeight> &durations_table)
|
||||||
@ -131,7 +129,7 @@ void forwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<Alg
|
|||||||
|
|
||||||
void backwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
void backwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
const unsigned column_idx,
|
const unsigned column_idx,
|
||||||
ManyToManyQueryHeap &query_heap,
|
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
|
||||||
SearchSpaceWithBuckets &search_space_with_buckets)
|
SearchSpaceWithBuckets &search_space_with_buckets)
|
||||||
{
|
{
|
||||||
const NodeID node = query_heap.DeleteMin();
|
const NodeID node = query_heap.DeleteMin();
|
||||||
@ -148,7 +146,6 @@ void backwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<Al
|
|||||||
|
|
||||||
relaxOutgoingEdges<REVERSE_DIRECTION>(facade, node, target_weight, target_duration, query_heap);
|
relaxOutgoingEdges<REVERSE_DIRECTION>(facade, node, target_weight, target_duration, query_heap);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<EdgeWeight>
|
std::vector<EdgeWeight>
|
||||||
manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
@ -247,6 +244,168 @@ manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
// TODO: generalize with CH version
|
// TODO: generalize with CH version
|
||||||
namespace mld
|
namespace mld
|
||||||
{
|
{
|
||||||
|
template <bool DIRECTION>
|
||||||
|
void relaxOutgoingEdges(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
|
const NodeID node,
|
||||||
|
const EdgeWeight weight,
|
||||||
|
const EdgeWeight duration,
|
||||||
|
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap)
|
||||||
|
{
|
||||||
|
const auto &partition = facade.GetMultiLevelPartition();
|
||||||
|
const auto &cells = facade.GetCellStorage();
|
||||||
|
|
||||||
|
const auto &node_data = query_heap.GetData(node);
|
||||||
|
const auto level =
|
||||||
|
std::max(node_data.level, partition.GetHighestDifferentLevel(node_data.parent, node));
|
||||||
|
|
||||||
|
if (level >= 1 && !node_data.from_clique_arc)
|
||||||
|
{
|
||||||
|
const auto &cell = cells.GetCell(level, partition.GetCell(level, node));
|
||||||
|
if (DIRECTION == FORWARD_DIRECTION)
|
||||||
|
{
|
||||||
|
// Shortcuts in forward direction
|
||||||
|
auto destination = cell.GetDestinationNodes().begin();
|
||||||
|
auto shortcut_durations = cell.GetOutDuration(node);
|
||||||
|
for (auto shortcut_weight : cell.GetOutWeight(node))
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(destination != cell.GetDestinationNodes().end());
|
||||||
|
BOOST_ASSERT(!shortcut_durations.empty());
|
||||||
|
const NodeID to = *destination;
|
||||||
|
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
|
||||||
|
{
|
||||||
|
const auto to_weight = weight + shortcut_weight;
|
||||||
|
const auto to_duration = duration + shortcut_durations.front();
|
||||||
|
if (!query_heap.WasInserted(to))
|
||||||
|
{
|
||||||
|
query_heap.Insert(to, to_weight, {node, true, level, to_duration});
|
||||||
|
}
|
||||||
|
else if (to_weight < query_heap.GetKey(to))
|
||||||
|
{
|
||||||
|
query_heap.GetData(to) = {node, true, level, to_duration};
|
||||||
|
query_heap.DecreaseKey(to, to_weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++destination;
|
||||||
|
shortcut_durations.advance_begin(1);
|
||||||
|
}
|
||||||
|
BOOST_ASSERT(shortcut_durations.empty());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Shortcuts in backward direction
|
||||||
|
auto source = cell.GetSourceNodes().begin();
|
||||||
|
auto shortcut_durations = cell.GetInDuration(node);
|
||||||
|
for (auto shortcut_weight : cell.GetInWeight(node))
|
||||||
|
{
|
||||||
|
BOOST_ASSERT(source != cell.GetSourceNodes().end());
|
||||||
|
BOOST_ASSERT(!shortcut_durations.empty());
|
||||||
|
const NodeID to = *source;
|
||||||
|
if (shortcut_weight != INVALID_EDGE_WEIGHT && node != to)
|
||||||
|
{
|
||||||
|
const auto to_weight = weight + shortcut_weight;
|
||||||
|
const auto to_duration = duration + shortcut_durations.front();
|
||||||
|
if (!query_heap.WasInserted(to))
|
||||||
|
{
|
||||||
|
query_heap.Insert(to, to_weight, {node, true, level, to_duration});
|
||||||
|
}
|
||||||
|
else if (to_weight < query_heap.GetKey(to))
|
||||||
|
{
|
||||||
|
query_heap.GetData(to) = {node, true, level, to_duration};
|
||||||
|
query_heap.DecreaseKey(to, to_weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++source;
|
||||||
|
shortcut_durations.advance_begin(1);
|
||||||
|
}
|
||||||
|
BOOST_ASSERT(shortcut_durations.empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto edge : facade.GetBorderEdgeRange(level, node))
|
||||||
|
{
|
||||||
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
|
if (DIRECTION == FORWARD_DIRECTION ? data.forward : data.backward)
|
||||||
|
{
|
||||||
|
const NodeID to = facade.GetTarget(edge);
|
||||||
|
const EdgeWeight edge_weight = data.weight;
|
||||||
|
const EdgeWeight edge_duration = data.duration;
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
|
const EdgeWeight to_weight = weight + edge_weight;
|
||||||
|
const EdgeWeight to_duration = duration + edge_duration;
|
||||||
|
|
||||||
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
|
if (!query_heap.WasInserted(to))
|
||||||
|
{
|
||||||
|
query_heap.Insert(to, to_weight, {node, false, level, to_duration});
|
||||||
|
}
|
||||||
|
// Found a shorter Path -> Update weight
|
||||||
|
else if (to_weight < query_heap.GetKey(to))
|
||||||
|
{
|
||||||
|
// new parent
|
||||||
|
query_heap.GetData(to) = {node, false, level, to_duration};
|
||||||
|
query_heap.DecreaseKey(to, to_weight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void forwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
|
const unsigned row_idx,
|
||||||
|
const unsigned number_of_targets,
|
||||||
|
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
|
||||||
|
const SearchSpaceWithBuckets &search_space_with_buckets,
|
||||||
|
std::vector<EdgeWeight> &weights_table,
|
||||||
|
std::vector<EdgeWeight> &durations_table)
|
||||||
|
{
|
||||||
|
const NodeID node = query_heap.DeleteMin();
|
||||||
|
const EdgeWeight source_weight = query_heap.GetKey(node);
|
||||||
|
const EdgeWeight source_duration = query_heap.GetData(node).duration;
|
||||||
|
|
||||||
|
// check if each encountered node has an entry
|
||||||
|
const auto bucket_iterator = search_space_with_buckets.find(node);
|
||||||
|
// iterate bucket if there exists one
|
||||||
|
if (bucket_iterator != search_space_with_buckets.end())
|
||||||
|
{
|
||||||
|
const std::vector<NodeBucket> &bucket_list = bucket_iterator->second;
|
||||||
|
for (const NodeBucket ¤t_bucket : bucket_list)
|
||||||
|
{
|
||||||
|
// get target id from bucket entry
|
||||||
|
const unsigned column_idx = current_bucket.target_id;
|
||||||
|
const EdgeWeight target_weight = current_bucket.weight;
|
||||||
|
const EdgeWeight target_duration = current_bucket.duration;
|
||||||
|
|
||||||
|
auto ¤t_weight = weights_table[row_idx * number_of_targets + column_idx];
|
||||||
|
auto ¤t_duration = durations_table[row_idx * number_of_targets + column_idx];
|
||||||
|
|
||||||
|
// check if new weight is better
|
||||||
|
const EdgeWeight new_weight = source_weight + target_weight;
|
||||||
|
if (new_weight >= 0 && new_weight < current_weight)
|
||||||
|
{
|
||||||
|
current_weight = new_weight;
|
||||||
|
current_duration = source_duration + target_duration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
relaxOutgoingEdges<FORWARD_DIRECTION>(facade, node, source_weight, source_duration, query_heap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void backwardRoutingStep(const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
|
const unsigned column_idx,
|
||||||
|
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
|
||||||
|
SearchSpaceWithBuckets &search_space_with_buckets)
|
||||||
|
{
|
||||||
|
const NodeID node = query_heap.DeleteMin();
|
||||||
|
const EdgeWeight target_weight = query_heap.GetKey(node);
|
||||||
|
const EdgeWeight target_duration = query_heap.GetData(node).duration;
|
||||||
|
|
||||||
|
// store settled nodes in search space bucket
|
||||||
|
search_space_with_buckets[node].emplace_back(column_idx, target_weight, target_duration);
|
||||||
|
|
||||||
|
relaxOutgoingEdges<REVERSE_DIRECTION>(facade, node, target_weight, target_duration, query_heap);
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<EdgeWeight>
|
std::vector<EdgeWeight>
|
||||||
manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
const datafacade::ContiguousInternalMemoryDataFacade<Algorithm> &facade,
|
||||||
@ -263,6 +422,79 @@ manyToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
std::vector<EdgeWeight> weights_table(number_of_entries, INVALID_EDGE_WEIGHT);
|
std::vector<EdgeWeight> weights_table(number_of_entries, INVALID_EDGE_WEIGHT);
|
||||||
std::vector<EdgeWeight> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION);
|
std::vector<EdgeWeight> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION);
|
||||||
|
|
||||||
|
engine_working_data.InitializeOrClearManyToManyThreadLocalStorage(facade.GetNumberOfNodes());
|
||||||
|
|
||||||
|
auto &query_heap = *(engine_working_data.many_to_many_heap);
|
||||||
|
|
||||||
|
SearchSpaceWithBuckets search_space_with_buckets;
|
||||||
|
|
||||||
|
unsigned column_idx = 0;
|
||||||
|
const auto search_target_phantom = [&](const PhantomNode &phantom) {
|
||||||
|
// clear heap and insert target nodes
|
||||||
|
query_heap.Clear();
|
||||||
|
insertTargetInHeap(query_heap, phantom);
|
||||||
|
|
||||||
|
// explore search space
|
||||||
|
while (!query_heap.Empty())
|
||||||
|
{
|
||||||
|
backwardRoutingStep(facade, column_idx, query_heap, search_space_with_buckets);
|
||||||
|
}
|
||||||
|
++column_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
// for each source do forward search
|
||||||
|
unsigned row_idx = 0;
|
||||||
|
const auto search_source_phantom = [&](const PhantomNode &phantom) {
|
||||||
|
// clear heap and insert source nodes
|
||||||
|
query_heap.Clear();
|
||||||
|
insertSourceInHeap(query_heap, phantom);
|
||||||
|
|
||||||
|
// explore search space
|
||||||
|
while (!query_heap.Empty())
|
||||||
|
{
|
||||||
|
forwardRoutingStep(facade,
|
||||||
|
row_idx,
|
||||||
|
number_of_targets,
|
||||||
|
query_heap,
|
||||||
|
search_space_with_buckets,
|
||||||
|
weights_table,
|
||||||
|
durations_table);
|
||||||
|
}
|
||||||
|
++row_idx;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (target_indices.empty())
|
||||||
|
{
|
||||||
|
for (const auto &phantom : phantom_nodes)
|
||||||
|
{
|
||||||
|
search_target_phantom(phantom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const auto index : target_indices)
|
||||||
|
{
|
||||||
|
const auto &phantom = phantom_nodes[index];
|
||||||
|
search_target_phantom(phantom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source_indices.empty())
|
||||||
|
{
|
||||||
|
for (const auto &phantom : phantom_nodes)
|
||||||
|
{
|
||||||
|
search_source_phantom(phantom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const auto index : source_indices)
|
||||||
|
{
|
||||||
|
const auto &phantom = phantom_nodes[index];
|
||||||
|
search_source_phantom(phantom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return durations_table;
|
return durations_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,40 +23,6 @@ bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &ta
|
|||||||
target_phantom.GetReverseWeightPlusOffset();
|
target_phantom.GetReverseWeightPlusOffset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertSourceInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
|
||||||
const PhantomNode &phantom_node)
|
|
||||||
{
|
|
||||||
if (phantom_node.IsValidForwardSource())
|
|
||||||
{
|
|
||||||
heap.Insert(phantom_node.forward_segment_id.id,
|
|
||||||
-phantom_node.GetForwardWeightPlusOffset(),
|
|
||||||
{phantom_node.forward_segment_id.id, -phantom_node.GetForwardDuration()});
|
|
||||||
}
|
|
||||||
if (phantom_node.IsValidReverseSource())
|
|
||||||
{
|
|
||||||
heap.Insert(phantom_node.reverse_segment_id.id,
|
|
||||||
-phantom_node.GetReverseWeightPlusOffset(),
|
|
||||||
{phantom_node.reverse_segment_id.id, -phantom_node.GetReverseDuration()});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void insertTargetInHeap(SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
|
||||||
const PhantomNode &phantom_node)
|
|
||||||
{
|
|
||||||
if (phantom_node.IsValidForwardTarget())
|
|
||||||
{
|
|
||||||
heap.Insert(phantom_node.forward_segment_id.id,
|
|
||||||
phantom_node.GetForwardWeightPlusOffset(),
|
|
||||||
{phantom_node.forward_segment_id.id, phantom_node.GetForwardDuration()});
|
|
||||||
}
|
|
||||||
if (phantom_node.IsValidReverseTarget())
|
|
||||||
{
|
|
||||||
heap.Insert(phantom_node.reverse_segment_id.id,
|
|
||||||
phantom_node.GetReverseWeightPlusOffset(),
|
|
||||||
{phantom_node.reverse_segment_id.id, phantom_node.GetReverseDuration()});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
@ -94,6 +94,7 @@ void SearchEngineData<CH>::InitializeOrClearManyToManyThreadLocalStorage(unsigne
|
|||||||
using MLD = routing_algorithms::mld::Algorithm;
|
using MLD = routing_algorithms::mld::Algorithm;
|
||||||
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::forward_heap_1;
|
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::forward_heap_1;
|
||||||
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::reverse_heap_1;
|
SearchEngineData<MLD>::SearchEngineHeapPtr SearchEngineData<MLD>::reverse_heap_1;
|
||||||
|
SearchEngineData<MLD>::ManyToManyHeapPtr SearchEngineData<MLD>::many_to_many_heap;
|
||||||
|
|
||||||
void SearchEngineData<MLD>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes)
|
void SearchEngineData<MLD>::InitializeOrClearFirstThreadLocalStorage(unsigned number_of_nodes)
|
||||||
{
|
{
|
||||||
@ -116,5 +117,16 @@ void SearchEngineData<MLD>::InitializeOrClearFirstThreadLocalStorage(unsigned nu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SearchEngineData<MLD>::InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes)
|
||||||
|
{
|
||||||
|
if (many_to_many_heap.get())
|
||||||
|
{
|
||||||
|
many_to_many_heap->Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
many_to_many_heap.reset(new ManyToManyQueryHeap(number_of_nodes));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ auto makeGraph(const MultiLevelPartition &mlp, const std::vector<MockEdge> &mock
|
|||||||
struct EdgeData
|
struct EdgeData
|
||||||
{
|
{
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
|
EdgeDuration duration;
|
||||||
bool forward;
|
bool forward;
|
||||||
bool backward;
|
bool backward;
|
||||||
};
|
};
|
||||||
@ -34,8 +35,8 @@ auto makeGraph(const MultiLevelPartition &mlp, const std::vector<MockEdge> &mock
|
|||||||
for (const auto &m : mock_edges)
|
for (const auto &m : mock_edges)
|
||||||
{
|
{
|
||||||
max_id = std::max<std::size_t>(max_id, std::max(m.start, m.target));
|
max_id = std::max<std::size_t>(max_id, std::max(m.start, m.target));
|
||||||
edges.push_back(Edge{m.start, m.target, m.weight, true, false});
|
edges.push_back(Edge{m.start, m.target, m.weight, 2 * m.weight, true, false});
|
||||||
edges.push_back(Edge{m.target, m.start, m.weight, false, true});
|
edges.push_back(Edge{m.target, m.start, m.weight, 2 * m.weight, false, true});
|
||||||
}
|
}
|
||||||
std::sort(edges.begin(), edges.end());
|
std::sort(edges.begin(), edges.end());
|
||||||
return partition::MultiLevelGraph<EdgeData, osrm::storage::Ownership::Container>(
|
return partition::MultiLevelGraph<EdgeData, osrm::storage::Ownership::Container>(
|
||||||
@ -253,6 +254,12 @@ BOOST_AUTO_TEST_CASE(four_levels_test)
|
|||||||
CHECK_EQUAL_RANGE(cell_2_1.GetInWeight(9), 0, INVALID_EDGE_WEIGHT);
|
CHECK_EQUAL_RANGE(cell_2_1.GetInWeight(9), 0, INVALID_EDGE_WEIGHT);
|
||||||
CHECK_EQUAL_RANGE(cell_2_1.GetInWeight(12), INVALID_EDGE_WEIGHT, 10);
|
CHECK_EQUAL_RANGE(cell_2_1.GetInWeight(12), INVALID_EDGE_WEIGHT, 10);
|
||||||
|
|
||||||
|
CHECK_EQUAL_RANGE(cell_2_1.GetOutDuration(9), 6, 0, INVALID_EDGE_WEIGHT);
|
||||||
|
CHECK_EQUAL_RANGE(cell_2_1.GetOutDuration(13), INVALID_EDGE_WEIGHT, INVALID_EDGE_WEIGHT, 20);
|
||||||
|
CHECK_EQUAL_RANGE(cell_2_1.GetInDuration(8), 6, INVALID_EDGE_WEIGHT);
|
||||||
|
CHECK_EQUAL_RANGE(cell_2_1.GetInDuration(9), 0, INVALID_EDGE_WEIGHT);
|
||||||
|
CHECK_EQUAL_RANGE(cell_2_1.GetInDuration(12), INVALID_EDGE_WEIGHT, 20);
|
||||||
|
|
||||||
CellStorage storage_rec(mlp, graph);
|
CellStorage storage_rec(mlp, graph);
|
||||||
customizer.Customize(graph, storage_rec);
|
customizer.Customize(graph, storage_rec);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user