From 247f1c120f535d964389a64fd91968ead9dae9e7 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sat, 19 Aug 2017 10:37:24 +0000 Subject: [PATCH] Make renumbering transparent to contraction --- include/contractor/contractor_graph.hpp | 10 +- include/contractor/graph_contractor.hpp | 32 ++---- src/contractor/graph_contractor.cpp | 123 +++++++++++------------- 3 files changed, 67 insertions(+), 98 deletions(-) diff --git a/include/contractor/contractor_graph.hpp b/include/contractor/contractor_graph.hpp index e50f29f97..3424568a6 100644 --- a/include/contractor/contractor_graph.hpp +++ b/include/contractor/contractor_graph.hpp @@ -12,8 +12,7 @@ namespace contractor struct ContractorEdgeData { ContractorEdgeData() - : weight(0), duration(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0), - is_original_via_node_ID(false) + : weight(0), duration(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0) { } ContractorEdgeData(EdgeWeight weight, @@ -24,18 +23,17 @@ struct ContractorEdgeData bool forward, bool backward) : weight(weight), duration(duration), id(id), - originalEdges(std::min((1u << 28) - 1u, original_edges)), shortcut(shortcut), - forward(forward), backward(backward), is_original_via_node_ID(false) + originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut), + forward(forward), backward(backward) { } EdgeWeight weight; EdgeWeight duration; unsigned id; - unsigned originalEdges : 28; + unsigned originalEdges : 29; bool shortcut : 1; bool forward : 1; bool backward : 1; - bool is_original_via_node_ID : 1; }; using ContractorGraph = util::DynamicGraph; diff --git a/include/contractor/graph_contractor.hpp b/include/contractor/graph_contractor.hpp index 5b1359457..f43dbfaa7 100644 --- a/include/contractor/graph_contractor.hpp +++ b/include/contractor/graph_contractor.hpp @@ -101,10 +101,9 @@ class GraphContractor std::vector node_levels_, std::vector node_weights_); - /* Flush all data from the contraction to disc and reorder stuff for better locality */ - void FlushDataAndRebuildContractorGraph(ThreadDataContainer &thread_data_list, - std::vector &remaining_nodes, - std::vector &node_priorities); + void RenumberGraph(ThreadDataContainer &thread_data_list, + std::vector &remaining_nodes, + std::vector &node_priorities); void Run(double core_factor = 1.0); @@ -130,22 +129,13 @@ class GraphContractor { const NodeID target = graph.GetTarget(edge); const ContractorGraph::EdgeData &data = graph.GetEdgeData(edge); - if (!orig_node_id_from_new_node_id_map.empty()) - { - new_edge.source = orig_node_id_from_new_node_id_map[node]; - new_edge.target = orig_node_id_from_new_node_id_map[target]; - } - else - { - new_edge.source = node; - new_edge.target = target; - } - BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.source, "Source id invalid"); + new_edge.source = orig_node_id_from_new_node_id_map[node]; + new_edge.target = orig_node_id_from_new_node_id_map[target]; BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid"); new_edge.data.weight = data.weight; new_edge.data.duration = data.duration; new_edge.data.shortcut = data.shortcut; - if (!data.is_original_via_node_ID && !orig_node_id_from_new_node_id_map.empty()) + if (data.shortcut) { // tranlate the _node id_ of the shortcutted node new_edge.data.turn_id = orig_node_id_from_new_node_id_map[data.id]; @@ -286,17 +276,13 @@ class GraphContractor if (RUNSIMULATION) { const int constexpr SIMULATION_SEARCH_SPACE_SIZE = 1000; - dijkstra.Run(number_of_targets, - SIMULATION_SEARCH_SPACE_SIZE, - max_weight, - node, - graph); + dijkstra.Run( + number_of_targets, SIMULATION_SEARCH_SPACE_SIZE, max_weight, node, graph); } else { const int constexpr FULL_SEARCH_SPACE_SIZE = 2000; - dijkstra.Run( - number_of_targets, FULL_SEARCH_SPACE_SIZE, max_weight, node, graph); + dijkstra.Run(number_of_targets, FULL_SEARCH_SPACE_SIZE, max_weight, node, graph); } for (auto out_edge : graph.GetAdjacentEdgeRange(node)) { diff --git a/src/contractor/graph_contractor.cpp b/src/contractor/graph_contractor.cpp index 6d5495f74..3ec2293f7 100644 --- a/src/contractor/graph_contractor.cpp +++ b/src/contractor/graph_contractor.cpp @@ -13,21 +13,25 @@ GraphContractor::GraphContractor(ContractorGraph graph_) GraphContractor::GraphContractor(ContractorGraph graph_, std::vector node_levels_, std::vector node_weights_) - : graph(std::move(graph_)), node_levels(std::move(node_levels_)), - node_weights(std::move(node_weights_)) + : graph(std::move(graph_)), orig_node_id_from_new_node_id_map(graph.GetNumberOfNodes()), + node_levels(std::move(node_levels_)), node_weights(std::move(node_weights_)) { + // Fill the map with an identiy mapping + std::iota( + orig_node_id_from_new_node_id_map.begin(), orig_node_id_from_new_node_id_map.end(), 0); } -/* Reorder nodes for better locality */ -void GraphContractor::FlushDataAndRebuildContractorGraph( - ThreadDataContainer &thread_data_list, - std::vector &remaining_nodes, - std::vector &node_priorities) +/* Reorder nodes for better locality during contraction */ +void GraphContractor::RenumberGraph(ThreadDataContainer &thread_data_list, + std::vector &remaining_nodes, + std::vector &node_priorities) { // Delete old heap data to free memory that we need for the coming operations thread_data_list.data.clear(); - orig_node_id_from_new_node_id_map.resize(graph.GetNumberOfNodes(), SPECIAL_NODEID); - std::vector new_node_id_from_orig_node_id(graph.GetNumberOfNodes(), SPECIAL_NODEID); + std::vector new_node_id_from_current_node_id(graph.GetNumberOfNodes(), SPECIAL_NODEID); + + // we need to make a copy here because we are going to modify it + auto to_orig = orig_node_id_from_new_node_id_map; auto new_node_id = 0; @@ -35,35 +39,43 @@ void GraphContractor::FlushDataAndRebuildContractorGraph( for (auto &remaining : remaining_nodes) { auto id = new_node_id++; - new_node_id_from_orig_node_id[remaining.id] = id; - orig_node_id_from_new_node_id_map[id] = remaining.id; + new_node_id_from_current_node_id[remaining.id] = id; + orig_node_id_from_new_node_id_map[id] = to_orig[remaining.id]; remaining.id = id; } // Already contracted nodes get the high IDs - for (const auto orig_id : util::irange(0, graph.GetNumberOfNodes())) + for (const auto current_id : util::irange(0, graph.GetNumberOfNodes())) { - if (new_node_id_from_orig_node_id[orig_id] == SPECIAL_NODEID) + if (new_node_id_from_current_node_id[current_id] == SPECIAL_NODEID) { auto id = new_node_id++; - new_node_id_from_orig_node_id[orig_id] = id; - orig_node_id_from_new_node_id_map[id] = orig_id; + new_node_id_from_current_node_id[current_id] = id; + orig_node_id_from_new_node_id_map[id] = to_orig[current_id]; } } BOOST_ASSERT(new_node_id == graph.GetNumberOfNodes()); util::inplacePermutation( - node_priorities.begin(), node_priorities.end(), new_node_id_from_orig_node_id); + node_priorities.begin(), node_priorities.end(), new_node_id_from_current_node_id); util::inplacePermutation( - node_weights.begin(), node_weights.end(), new_node_id_from_orig_node_id); - graph.Renumber(new_node_id_from_orig_node_id); + node_weights.begin(), node_weights.end(), new_node_id_from_current_node_id); + util::inplacePermutation( + node_levels.begin(), node_levels.end(), new_node_id_from_current_node_id); + util::inplacePermutation( + is_core_node.begin(), is_core_node.end(), new_node_id_from_current_node_id); + graph.Renumber(new_node_id_from_current_node_id); - // Mark all existing edges to reference old via IDs + // Renumber all shortcut node IDs for (const auto node : util::irange(0, graph.GetNumberOfNodes())) { for (const auto edge : graph.GetAdjacentEdgeRange(node)) { - graph.GetEdgeData(edge).is_original_via_node_ID = true; + auto &data = graph.GetEdgeData(edge); + if (data.shortcut) + { + data.id = new_node_id_from_current_node_id[data.id]; + } } } } @@ -136,18 +148,16 @@ void GraphContractor::Run(double core_factor) util::Percent p(log, number_of_nodes); unsigned current_level = 0; - bool flushed_contractor = false; + std::size_t next_renumbering = number_of_nodes * 0.65 * core_factor; while (remaining_nodes.size() > 1 && number_of_contracted_nodes < static_cast(number_of_nodes * core_factor)) { - if (!flushed_contractor && (number_of_contracted_nodes > - static_cast(number_of_nodes * 0.65 * core_factor))) + if (number_of_contracted_nodes > next_renumbering) { - log << " [flush " << number_of_contracted_nodes << " nodes] "; - - FlushDataAndRebuildContractorGraph(thread_data_list, remaining_nodes, node_priorities); - - flushed_contractor = true; + RenumberGraph(thread_data_list, remaining_nodes, node_priorities); + log << "[renumbered]"; + // only one renumbering for now + next_renumbering = number_of_nodes; } tbb::parallel_for( @@ -179,25 +189,11 @@ void GraphContractor::Run(double core_factor) tbb::parallel_for( tbb::blocked_range( begin_independent_nodes_idx, end_independent_nodes_idx, ContractGrainSize), - [this, remaining_nodes, flushed_contractor, current_level]( - const tbb::blocked_range &range) { - if (flushed_contractor) + [this, remaining_nodes, current_level](const tbb::blocked_range &range) { + for (auto position = range.begin(), end = range.end(); position != end; + ++position) { - for (auto position = range.begin(), end = range.end(); position != end; - ++position) - { - const NodeID x = remaining_nodes[position].id; - node_levels[orig_node_id_from_new_node_id_map[x]] = current_level; - } - } - else - { - for (auto position = range.begin(), end = range.end(); position != end; - ++position) - { - const NodeID x = remaining_nodes[position].id; - node_levels[x] = current_level; - } + node_levels[remaining_nodes[position].id] = current_level; } }); } @@ -289,29 +285,13 @@ void GraphContractor::Run(double core_factor) if (remaining_nodes.size() > 2) { - if (flushed_contractor) - { - tbb::parallel_for(tbb::blocked_range(0, remaining_nodes.size(), InitGrainSize), - [this, &remaining_nodes](const tbb::blocked_range &range) { - for (auto x = range.begin(), end = range.end(); x != end; ++x) - { - const auto orig_id = remaining_nodes[x].id; - is_core_node[orig_node_id_from_new_node_id_map[orig_id]] = - true; - } - }); - } - else - { - tbb::parallel_for(tbb::blocked_range(0, remaining_nodes.size(), InitGrainSize), - [this, &remaining_nodes](const tbb::blocked_range &range) { - for (auto x = range.begin(), end = range.end(); x != end; ++x) - { - const auto orig_id = remaining_nodes[x].id; - is_core_node[orig_id] = true; - } - }); - } + tbb::parallel_for(tbb::blocked_range(0, remaining_nodes.size(), InitGrainSize), + [this, &remaining_nodes](const tbb::blocked_range &range) { + for (auto x = range.begin(), end = range.end(); x != end; ++x) + { + is_core_node[remaining_nodes[x].id] = true; + } + }); } else { @@ -320,9 +300,14 @@ void GraphContractor::Run(double core_factor) is_core_node.clear(); } + log << "\n"; + util::Log() << "[core] " << remaining_nodes.size() << " nodes " << graph.GetNumberOfEdges() << " edges."; + util::inplacePermutation(node_levels.begin(), node_levels.end(), orig_node_id_from_new_node_id_map); + util::inplacePermutation(is_core_node.begin(), is_core_node.end(), orig_node_id_from_new_node_id_map); + thread_data_list.data.clear(); }