diff --git a/include/customizer/cell_customizer.hpp b/include/customizer/cell_customizer.hpp index 01e65e582..df5499579 100644 --- a/include/customizer/cell_customizer.hpp +++ b/include/customizer/cell_customizer.hpp @@ -22,6 +22,7 @@ class CellCustomizer { bool from_clique; EdgeDuration duration; + EdgeDistance distance; }; public: @@ -60,7 +61,7 @@ class CellCustomizer } } heap.Clear(); - heap.Insert(source, 0, {false, 0}); + heap.Insert(source, 0, {false, 0, 0}); // explore search space while (!heap.Empty() && !destinations_set.empty()) @@ -68,8 +69,18 @@ class CellCustomizer const NodeID node = heap.DeleteMin(); const EdgeWeight weight = heap.GetKey(node); const EdgeDuration duration = heap.GetData(node).duration; + const EdgeDistance distance = heap.GetData(node).distance; - RelaxNode(graph, cells, allowed_nodes, metric, heap, level, node, weight, duration); + RelaxNode(graph, + cells, + allowed_nodes, + metric, + heap, + level, + node, + weight, + duration, + distance); destinations_set.erase(node); } @@ -77,21 +88,27 @@ class CellCustomizer // fill a map of destination nodes to placeholder pointers auto weights = cell.GetOutWeight(source); auto durations = cell.GetOutDuration(source); + auto distances = cell.GetOutDistance(source); for (auto &destination : destinations) { BOOST_ASSERT(!weights.empty()); BOOST_ASSERT(!durations.empty()); + BOOST_ASSERT(!distances.empty()); const bool inserted = heap.WasInserted(destination); weights.front() = inserted ? heap.GetKey(destination) : INVALID_EDGE_WEIGHT; durations.front() = inserted ? heap.GetData(destination).duration : MAXIMAL_EDGE_DURATION; + distances.front() = + inserted ? heap.GetData(destination).distance : INVALID_EDGE_DISTANCE; weights.advance_begin(1); durations.advance_begin(1); + distances.advance_begin(1); } BOOST_ASSERT(weights.empty()); BOOST_ASSERT(durations.empty()); + BOOST_ASSERT(distances.empty()); } } @@ -128,7 +145,8 @@ class CellCustomizer LevelID level, NodeID node, EdgeWeight weight, - EdgeDuration duration) const + EdgeDuration duration, + EdgeDistance distance) const { auto first_level = level == 1; BOOST_ASSERT(heap.WasInserted(node)); @@ -149,6 +167,7 @@ class CellCustomizer auto subcell = cells.GetCell(metric, level - 1, subcell_id); auto subcell_destination = subcell.GetDestinationNodes().begin(); auto subcell_duration = subcell.GetOutDuration(node).begin(); + auto subcell_distance = subcell.GetOutDistance(node).begin(); for (auto subcell_weight : subcell.GetOutWeight(node)) { if (subcell_weight != INVALID_EDGE_WEIGHT) @@ -161,20 +180,24 @@ class CellCustomizer const EdgeWeight to_weight = weight + subcell_weight; const EdgeDuration to_duration = duration + *subcell_duration; + const EdgeDistance to_distance = distance + *subcell_distance; if (!heap.WasInserted(to)) { - heap.Insert(to, to_weight, {true, to_duration}); + heap.Insert(to, to_weight, {true, to_duration, to_distance}); } - else if (std::tie(to_weight, to_duration) < - std::tie(heap.GetKey(to), heap.GetData(to).duration)) + else if (std::tie(to_weight, to_duration, to_distance) < + std::tie(heap.GetKey(to), + heap.GetData(to).duration, + heap.GetData(to).distance)) { heap.DecreaseKey(to, to_weight); - heap.GetData(to) = {true, to_duration}; + heap.GetData(to) = {true, to_duration, to_distance}; } } ++subcell_destination; ++subcell_duration; + ++subcell_distance; } } } @@ -195,15 +218,18 @@ class CellCustomizer { const EdgeWeight to_weight = weight + data.weight; const EdgeDuration to_duration = duration + data.duration; + const EdgeDistance to_distance = distance + data.distance; if (!heap.WasInserted(to)) { - heap.Insert(to, to_weight, {false, duration + data.duration}); + heap.Insert( + to, to_weight, {false, duration + data.duration, distance + data.distance}); } - else if (std::tie(to_weight, to_duration) < - std::tie(heap.GetKey(to), heap.GetData(to).duration)) + else if (std::tie(to_weight, to_duration, to_distance) < + std::tie( + heap.GetKey(to), heap.GetData(to).duration, heap.GetData(to).distance)) { heap.DecreaseKey(to, to_weight); - heap.GetData(to) = {false, to_duration}; + heap.GetData(to) = {false, to_duration, to_distance}; } } } diff --git a/include/customizer/cell_metric.hpp b/include/customizer/cell_metric.hpp index 530a18559..7674174fe 100644 --- a/include/customizer/cell_metric.hpp +++ b/include/customizer/cell_metric.hpp @@ -20,6 +20,7 @@ template struct CellMetricImpl Vector weights; Vector durations; + Vector distances; }; } diff --git a/include/customizer/edge_based_graph.hpp b/include/customizer/edge_based_graph.hpp index 8414c5942..39240b743 100644 --- a/include/customizer/edge_based_graph.hpp +++ b/include/customizer/edge_based_graph.hpp @@ -83,11 +83,13 @@ class MultiLevelGraph : public partitioner::MultiLevelGraph node_to_edge_offset_, Vector node_weights_, Vector node_durations_, + Vector node_distances_, Vector is_forward_edge_, Vector is_backward_edge_) : SuperT(std::move(node_array_), std::move(edge_array_), std::move(node_to_edge_offset_)), node_weights(std::move(node_weights_)), node_durations(std::move(node_durations_)), - is_forward_edge(is_forward_edge_), is_backward_edge(is_backward_edge_) + node_distances(std::move(node_distances_)), is_forward_edge(is_forward_edge_), + is_backward_edge(is_backward_edge_) { } @@ -95,6 +97,8 @@ class MultiLevelGraph : public partitioner::MultiLevelGraph node_weights; Vector node_durations; + Vector node_distances; Vector is_forward_edge; Vector is_backward_edge; }; diff --git a/include/engine/datafacade/algorithm_datafacade.hpp b/include/engine/datafacade/algorithm_datafacade.hpp index ef910d4ac..a83a5340c 100644 --- a/include/engine/datafacade/algorithm_datafacade.hpp +++ b/include/engine/datafacade/algorithm_datafacade.hpp @@ -78,6 +78,8 @@ template <> class AlgorithmDataFacade virtual EdgeWeight GetNodeDuration(const NodeID node) const = 0; // TODO: to be removed + virtual EdgeDistance GetNodeDistance(const NodeID node) const = 0; + virtual bool IsForwardEdge(EdgeID edge) const = 0; virtual bool IsBackwardEdge(EdgeID edge) const = 0; diff --git a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp index 6befce6d0..936d40f99 100644 --- a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp +++ b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp @@ -697,6 +697,11 @@ template <> class ContiguousInternalMemoryAlgorithmDataFacade : public Algo return query_graph.GetNodeDuration(node); } + EdgeDistance GetNodeDistance(const NodeID node) const override final + { + return query_graph.GetNodeDistance(node); + } + bool IsForwardEdge(const NodeID node) const override final { return query_graph.IsForwardEdge(node); diff --git a/include/partitioner/cell_storage.hpp b/include/partitioner/cell_storage.hpp index b3ad7d7bc..271f804d9 100644 --- a/include/partitioner/cell_storage.hpp +++ b/include/partitioner/cell_storage.hpp @@ -75,16 +75,19 @@ template class CellStorageImpl // Implementation of the cell view. We need a template parameter here // because we need to derive a read-only and read-write view from this. - template class CellImpl + template + class CellImpl { private: using WeightPtrT = WeightValueT *; using DurationPtrT = DurationValueT *; + using DistancePtrT = DistanceValueT *; BoundarySize num_source_nodes; BoundarySize num_destination_nodes; WeightPtrT const weights; DurationPtrT const durations; + DistancePtrT const distances; const NodeID *const source_boundary; const NodeID *const destination_boundary; @@ -165,6 +168,14 @@ template class CellStorageImpl auto GetInDuration(NodeID node) const { return GetInRange(durations, node); } + auto GetOutDistance(NodeID node) const + { + return GetOutRange(distances, node); + } // Might be symmetric and may be able to get away with simply having GetDistance and not + // have both GetInDistance and GetOutDistance + + auto GetInDistance(NodeID node) const { return GetInRange(distances, node); } + auto GetSourceNodes() const { return boost::make_iterator_range(source_boundary, source_boundary + num_source_nodes); @@ -179,17 +190,20 @@ template class CellStorageImpl CellImpl(const CellData &data, WeightPtrT const all_weights, DurationPtrT const all_durations, + DistancePtrT const all_distances, const NodeID *const all_sources, const NodeID *const all_destinations) : num_source_nodes{data.num_source_nodes}, num_destination_nodes{data.num_destination_nodes}, weights{all_weights + data.value_offset}, durations{all_durations + data.value_offset}, + distances{all_distances + data.value_offset}, source_boundary{all_sources + data.source_boundary_offset}, destination_boundary{all_destinations + data.destination_boundary_offset} { BOOST_ASSERT(all_weights != nullptr); BOOST_ASSERT(all_durations != nullptr); + BOOST_ASSERT(all_durations != nullptr); BOOST_ASSERT(num_source_nodes == 0 || all_sources != nullptr); BOOST_ASSERT(num_destination_nodes == 0 || all_destinations != nullptr); } @@ -201,7 +215,8 @@ template class CellStorageImpl const NodeID *const all_destinations) : num_source_nodes{data.num_source_nodes}, num_destination_nodes{data.num_destination_nodes}, weights{nullptr}, - durations{nullptr}, source_boundary{all_sources + data.source_boundary_offset}, + durations{nullptr}, distances{nullptr}, + source_boundary{all_sources + data.source_boundary_offset}, destination_boundary{all_destinations + data.destination_boundary_offset} { BOOST_ASSERT(num_source_nodes == 0 || all_sources != nullptr); @@ -212,8 +227,8 @@ template class CellStorageImpl std::size_t LevelIDToIndex(LevelID level) const { return level - 1; } public: - using Cell = CellImpl; - using ConstCell = CellImpl; + using Cell = CellImpl; + using ConstCell = CellImpl; CellStorageImpl() {} @@ -388,6 +403,7 @@ template class CellStorageImpl return ConstCell{cells[cell_index], metric.weights.data(), metric.durations.data(), + metric.distances.data(), source_boundary.empty() ? nullptr : source_boundary.data(), destination_boundary.empty() ? nullptr : destination_boundary.data()}; } @@ -415,6 +431,7 @@ template class CellStorageImpl return Cell{cells[cell_index], metric.weights.data(), metric.durations.data(), + metric.distances.data(), source_boundary.data(), destination_boundary.data()}; } diff --git a/include/storage/view_factory.hpp b/include/storage/view_factory.hpp index f6c8e2137..b04e3026e 100644 --- a/include/storage/view_factory.hpp +++ b/include/storage/view_factory.hpp @@ -294,11 +294,14 @@ inline auto make_filtered_cell_metric_view(const SharedDataIndex &index, auto prefix = name + "/exclude/" + std::to_string(exclude_index); auto weights_block_id = prefix + "/weights"; auto durations_block_id = prefix + "/durations"; + auto distances_block_id = prefix + "/distances"; auto weights = make_vector_view(index, weights_block_id); auto durations = make_vector_view(index, durations_block_id); + auto distances = make_vector_view(index, distances_block_id); - return customizer::CellMetricView{std::move(weights), std::move(durations)}; + return customizer::CellMetricView{ + std::move(weights), std::move(durations), std::move(distances)}; } inline auto make_cell_metric_view(const SharedDataIndex &index, const std::string &name) @@ -311,12 +314,14 @@ inline auto make_cell_metric_view(const SharedDataIndex &index, const std::strin { auto weights_block_id = prefix + "/weights"; auto durations_block_id = prefix + "/durations"; + auto distances_block_id = prefix + "/distances"; auto weights = make_vector_view(index, weights_block_id); auto durations = make_vector_view(index, durations_block_id); + auto distances = make_vector_view(index, distances_block_id); - cell_metric_excludes.push_back( - customizer::CellMetricView{std::move(weights), std::move(durations)}); + cell_metric_excludes.push_back(customizer::CellMetricView{ + std::move(weights), std::move(durations), std::move(distances)}); } return cell_metric_excludes; @@ -332,6 +337,7 @@ inline auto make_multi_level_graph_view(const SharedDataIndex &index, const std: index, name + "/node_to_edge_offset"); auto node_weights = make_vector_view(index, name + "/node_weights"); auto node_durations = make_vector_view(index, name + "/node_durations"); + auto node_distances = make_vector_view(index, name + "/node_distances"); auto is_forward_edge = make_vector_view(index, name + "/is_forward_edge"); auto is_backward_edge = make_vector_view(index, name + "/is_backward_edge"); @@ -340,6 +346,7 @@ inline auto make_multi_level_graph_view(const SharedDataIndex &index, const std: std::move(node_to_offset), std::move(node_weights), std::move(node_durations), + std::move(node_distances), std::move(is_forward_edge), std::move(is_backward_edge)); } diff --git a/src/engine/routing_algorithms/many_to_many_mld.cpp b/src/engine/routing_algorithms/many_to_many_mld.cpp index d13c11b2b..a31a7b38e 100644 --- a/src/engine/routing_algorithms/many_to_many_mld.cpp +++ b/src/engine/routing_algorithms/many_to_many_mld.cpp @@ -41,7 +41,7 @@ void relaxOutgoingEdges(const DataFacade &facade, const NodeID node, const EdgeWeight weight, const EdgeDuration duration, - const EdgeDistance /* distance TODO use this */, + const EdgeDistance distance, typename SearchEngineData::ManyToManyQueryHeap &query_heap, Args... args) { @@ -66,65 +66,77 @@ void relaxOutgoingEdges(const DataFacade &facade, { // Shortcuts in forward direction auto destination = cell.GetDestinationNodes().begin(); auto shortcut_durations = cell.GetOutDuration(node); + auto shortcut_distances = cell.GetOutDistance(node); for (auto shortcut_weight : cell.GetOutWeight(node)) { BOOST_ASSERT(destination != cell.GetDestinationNodes().end()); BOOST_ASSERT(!shortcut_durations.empty()); + BOOST_ASSERT(!shortcut_distances.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(); + const auto to_distance = distance + shortcut_distances.front(); if (!query_heap.WasInserted(to)) { - query_heap.Insert(to, to_weight, {node, true, to_duration, 0}); + query_heap.Insert(to, to_weight, {node, true, to_duration, to_distance}); } - else if (std::tie(to_weight, to_duration, node) < + else if (std::tie(to_weight, to_duration, to_distance, node) < std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration, + query_heap.GetData(to).distance, query_heap.GetData(to).parent)) { - query_heap.GetData(to) = {node, true, to_duration, 0}; + query_heap.GetData(to) = {node, true, to_duration, to_distance}; query_heap.DecreaseKey(to, to_weight); } } ++destination; shortcut_durations.advance_begin(1); + shortcut_distances.advance_begin(1); } BOOST_ASSERT(shortcut_durations.empty()); + BOOST_ASSERT(shortcut_distances.empty()); } else { // Shortcuts in backward direction auto source = cell.GetSourceNodes().begin(); auto shortcut_durations = cell.GetInDuration(node); + auto shortcut_distances = cell.GetInDistance(node); for (auto shortcut_weight : cell.GetInWeight(node)) { BOOST_ASSERT(source != cell.GetSourceNodes().end()); BOOST_ASSERT(!shortcut_durations.empty()); + BOOST_ASSERT(!shortcut_distances.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(); + const auto to_distance = distance + shortcut_distances.front(); if (!query_heap.WasInserted(to)) { - query_heap.Insert(to, to_weight, {node, true, to_duration, 0}); + query_heap.Insert(to, to_weight, {node, true, to_duration, to_distance}); } else if (std::tie(to_weight, to_duration, node) < std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration, + query_heap.GetData(to).distance, query_heap.GetData(to).parent)) { - query_heap.GetData(to) = {node, true, to_duration, 0}; + query_heap.GetData(to) = {node, true, to_duration, to_distance}; query_heap.DecreaseKey(to, to_weight); } } ++source; shortcut_durations.advance_begin(1); + shortcut_distances.advance_begin(1); } BOOST_ASSERT(shortcut_durations.empty()); + BOOST_ASSERT(shortcut_distances.empty()); } } @@ -144,6 +156,7 @@ void relaxOutgoingEdges(const DataFacade &facade, const auto node_id = DIRECTION == FORWARD_DIRECTION ? node : facade.GetTarget(edge); const auto node_weight = facade.GetNodeWeight(node_id); const auto node_duration = facade.GetNodeDuration(node_id); + const auto node_distance = facade.GetNodeDistance(node_id); const auto turn_weight = node_weight + facade.GetWeightPenaltyForEdgeID(turn_id); const auto turn_duration = node_duration + facade.GetDurationPenaltyForEdgeID(turn_id); @@ -154,15 +167,16 @@ void relaxOutgoingEdges(const DataFacade &facade, // New Node discovered -> Add to Heap + Node Info Storage if (!query_heap.WasInserted(to)) { - query_heap.Insert(to, to_weight, {node, false, to_duration, 0}); + query_heap.Insert(to, to_weight, {node, false, to_duration, int(node_distance)}); } // Found a shorter Path -> Update weight and set new parent - else if (std::tie(to_weight, to_duration, node) < + else if (std::tie(to_weight, to_duration, node_distance, node) < std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration, + query_heap.GetData(to).distance, query_heap.GetData(to).parent)) { - query_heap.GetData(to) = {node, false, to_duration, 0}; + query_heap.GetData(to) = {node, false, to_duration, node_distance}; query_heap.DecreaseKey(to, to_weight); } } @@ -511,6 +525,7 @@ void forwardRoutingStep(const DataFacade &facade, const std::vector &search_space_with_buckets, std::vector &weights_table, std::vector &durations_table, + std::vector &distances_table, std::vector &middle_nodes_table, const PhantomNode &phantom_node) { @@ -530,6 +545,7 @@ void forwardRoutingStep(const DataFacade &facade, const auto column_idx = current_bucket.column_index; const auto target_weight = current_bucket.weight; const auto target_duration = current_bucket.duration; + const auto target_distance = current_bucket.distance; // Get the value location in the results tables: // * row-major direct (row_idx, column_idx) index for forward direction @@ -539,16 +555,20 @@ void forwardRoutingStep(const DataFacade &facade, : row_idx + column_idx * number_of_sources; auto ¤t_weight = weights_table[location]; auto ¤t_duration = durations_table[location]; + auto ¤t_distance = distances_table[location]; // Check if new weight is better auto new_weight = source_weight + target_weight; auto new_duration = source_duration + target_duration; + auto new_distance = source_distance + target_distance; if (new_weight >= 0 && - std::tie(new_weight, new_duration) < std::tie(current_weight, current_duration)) + std::tie(new_weight, new_duration, new_distance) < + std::tie(current_weight, current_duration, current_distance)) { current_weight = new_weight; current_duration = new_duration; + current_distance = new_distance; middle_nodes_table[location] = node; } } @@ -573,7 +593,7 @@ void backwardRoutingStep(const DataFacade &facade, // Store settled nodes in search space bucket search_space_with_buckets.emplace_back( - node, parent, from_clique_arc, column_idx, target_weight, target_duration); + node, parent, from_clique_arc, column_idx, target_weight, target_duration, target_distance); const auto &partition = facade.GetMultiLevelPartition(); const auto maximal_level = partition.GetNumberOfLevels() - 1; @@ -815,7 +835,7 @@ manyToManySearch(SearchEngineData &engine_working_data, std::vector weights_table(number_of_entries, INVALID_EDGE_WEIGHT); std::vector durations_table(number_of_entries, MAXIMAL_EDGE_DURATION); - std::vector distances_table; + std::vector distances_table(number_of_entries, INVALID_EDGE_DISTANCE); std::vector middle_nodes_table(number_of_entries, SPECIAL_NODEID); std::vector search_space_with_buckets; @@ -874,6 +894,7 @@ manyToManySearch(SearchEngineData &engine_working_data, search_space_with_buckets, weights_table, durations_table, + distances_table, middle_nodes_table, source_phantom); }