Make renumbering transparent to contraction
This commit is contained in:
parent
e011c60e12
commit
247f1c120f
@ -12,8 +12,7 @@ namespace contractor
|
|||||||
struct ContractorEdgeData
|
struct ContractorEdgeData
|
||||||
{
|
{
|
||||||
ContractorEdgeData()
|
ContractorEdgeData()
|
||||||
: weight(0), duration(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0),
|
: weight(0), duration(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0)
|
||||||
is_original_via_node_ID(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
ContractorEdgeData(EdgeWeight weight,
|
ContractorEdgeData(EdgeWeight weight,
|
||||||
@ -24,18 +23,17 @@ struct ContractorEdgeData
|
|||||||
bool forward,
|
bool forward,
|
||||||
bool backward)
|
bool backward)
|
||||||
: weight(weight), duration(duration), id(id),
|
: weight(weight), duration(duration), id(id),
|
||||||
originalEdges(std::min((1u << 28) - 1u, original_edges)), shortcut(shortcut),
|
originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut),
|
||||||
forward(forward), backward(backward), is_original_via_node_ID(false)
|
forward(forward), backward(backward)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
EdgeWeight duration;
|
EdgeWeight duration;
|
||||||
unsigned id;
|
unsigned id;
|
||||||
unsigned originalEdges : 28;
|
unsigned originalEdges : 29;
|
||||||
bool shortcut : 1;
|
bool shortcut : 1;
|
||||||
bool forward : 1;
|
bool forward : 1;
|
||||||
bool backward : 1;
|
bool backward : 1;
|
||||||
bool is_original_via_node_ID : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using ContractorGraph = util::DynamicGraph<ContractorEdgeData>;
|
using ContractorGraph = util::DynamicGraph<ContractorEdgeData>;
|
||||||
|
@ -101,10 +101,9 @@ class GraphContractor
|
|||||||
std::vector<float> node_levels_,
|
std::vector<float> node_levels_,
|
||||||
std::vector<EdgeWeight> node_weights_);
|
std::vector<EdgeWeight> node_weights_);
|
||||||
|
|
||||||
/* Flush all data from the contraction to disc and reorder stuff for better locality */
|
void RenumberGraph(ThreadDataContainer &thread_data_list,
|
||||||
void FlushDataAndRebuildContractorGraph(ThreadDataContainer &thread_data_list,
|
std::vector<RemainingNodeData> &remaining_nodes,
|
||||||
std::vector<RemainingNodeData> &remaining_nodes,
|
std::vector<float> &node_priorities);
|
||||||
std::vector<float> &node_priorities);
|
|
||||||
|
|
||||||
void Run(double core_factor = 1.0);
|
void Run(double core_factor = 1.0);
|
||||||
|
|
||||||
@ -130,22 +129,13 @@ class GraphContractor
|
|||||||
{
|
{
|
||||||
const NodeID target = graph.GetTarget(edge);
|
const NodeID target = graph.GetTarget(edge);
|
||||||
const ContractorGraph::EdgeData &data = graph.GetEdgeData(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];
|
||||||
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");
|
|
||||||
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
|
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
|
||||||
new_edge.data.weight = data.weight;
|
new_edge.data.weight = data.weight;
|
||||||
new_edge.data.duration = data.duration;
|
new_edge.data.duration = data.duration;
|
||||||
new_edge.data.shortcut = data.shortcut;
|
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
|
// tranlate the _node id_ of the shortcutted node
|
||||||
new_edge.data.turn_id = orig_node_id_from_new_node_id_map[data.id];
|
new_edge.data.turn_id = orig_node_id_from_new_node_id_map[data.id];
|
||||||
@ -286,17 +276,13 @@ class GraphContractor
|
|||||||
if (RUNSIMULATION)
|
if (RUNSIMULATION)
|
||||||
{
|
{
|
||||||
const int constexpr SIMULATION_SEARCH_SPACE_SIZE = 1000;
|
const int constexpr SIMULATION_SEARCH_SPACE_SIZE = 1000;
|
||||||
dijkstra.Run(number_of_targets,
|
dijkstra.Run(
|
||||||
SIMULATION_SEARCH_SPACE_SIZE,
|
number_of_targets, SIMULATION_SEARCH_SPACE_SIZE, max_weight, node, graph);
|
||||||
max_weight,
|
|
||||||
node,
|
|
||||||
graph);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const int constexpr FULL_SEARCH_SPACE_SIZE = 2000;
|
const int constexpr FULL_SEARCH_SPACE_SIZE = 2000;
|
||||||
dijkstra.Run(
|
dijkstra.Run(number_of_targets, FULL_SEARCH_SPACE_SIZE, max_weight, node, graph);
|
||||||
number_of_targets, FULL_SEARCH_SPACE_SIZE, max_weight, node, graph);
|
|
||||||
}
|
}
|
||||||
for (auto out_edge : graph.GetAdjacentEdgeRange(node))
|
for (auto out_edge : graph.GetAdjacentEdgeRange(node))
|
||||||
{
|
{
|
||||||
|
@ -13,21 +13,25 @@ GraphContractor::GraphContractor(ContractorGraph graph_)
|
|||||||
GraphContractor::GraphContractor(ContractorGraph graph_,
|
GraphContractor::GraphContractor(ContractorGraph graph_,
|
||||||
std::vector<float> node_levels_,
|
std::vector<float> node_levels_,
|
||||||
std::vector<EdgeWeight> node_weights_)
|
std::vector<EdgeWeight> node_weights_)
|
||||||
: graph(std::move(graph_)), node_levels(std::move(node_levels_)),
|
: graph(std::move(graph_)), orig_node_id_from_new_node_id_map(graph.GetNumberOfNodes()),
|
||||||
node_weights(std::move(node_weights_))
|
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 */
|
/* Reorder nodes for better locality during contraction */
|
||||||
void GraphContractor::FlushDataAndRebuildContractorGraph(
|
void GraphContractor::RenumberGraph(ThreadDataContainer &thread_data_list,
|
||||||
ThreadDataContainer &thread_data_list,
|
std::vector<RemainingNodeData> &remaining_nodes,
|
||||||
std::vector<RemainingNodeData> &remaining_nodes,
|
std::vector<float> &node_priorities)
|
||||||
std::vector<float> &node_priorities)
|
|
||||||
{
|
{
|
||||||
// Delete old heap data to free memory that we need for the coming operations
|
// Delete old heap data to free memory that we need for the coming operations
|
||||||
thread_data_list.data.clear();
|
thread_data_list.data.clear();
|
||||||
orig_node_id_from_new_node_id_map.resize(graph.GetNumberOfNodes(), SPECIAL_NODEID);
|
std::vector<NodeID> new_node_id_from_current_node_id(graph.GetNumberOfNodes(), SPECIAL_NODEID);
|
||||||
std::vector<NodeID> new_node_id_from_orig_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;
|
auto new_node_id = 0;
|
||||||
|
|
||||||
@ -35,35 +39,43 @@ void GraphContractor::FlushDataAndRebuildContractorGraph(
|
|||||||
for (auto &remaining : remaining_nodes)
|
for (auto &remaining : remaining_nodes)
|
||||||
{
|
{
|
||||||
auto id = new_node_id++;
|
auto id = new_node_id++;
|
||||||
new_node_id_from_orig_node_id[remaining.id] = id;
|
new_node_id_from_current_node_id[remaining.id] = id;
|
||||||
orig_node_id_from_new_node_id_map[id] = remaining.id;
|
orig_node_id_from_new_node_id_map[id] = to_orig[remaining.id];
|
||||||
remaining.id = id;
|
remaining.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Already contracted nodes get the high IDs
|
// Already contracted nodes get the high IDs
|
||||||
for (const auto orig_id : util::irange<std::size_t>(0, graph.GetNumberOfNodes()))
|
for (const auto current_id : util::irange<std::size_t>(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++;
|
auto id = new_node_id++;
|
||||||
new_node_id_from_orig_node_id[orig_id] = id;
|
new_node_id_from_current_node_id[current_id] = id;
|
||||||
orig_node_id_from_new_node_id_map[id] = orig_id;
|
orig_node_id_from_new_node_id_map[id] = to_orig[current_id];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(new_node_id == graph.GetNumberOfNodes());
|
BOOST_ASSERT(new_node_id == graph.GetNumberOfNodes());
|
||||||
|
|
||||||
util::inplacePermutation(
|
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(
|
util::inplacePermutation(
|
||||||
node_weights.begin(), node_weights.end(), new_node_id_from_orig_node_id);
|
node_weights.begin(), node_weights.end(), new_node_id_from_current_node_id);
|
||||||
graph.Renumber(new_node_id_from_orig_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<NodeID>(0, graph.GetNumberOfNodes()))
|
for (const auto node : util::irange<NodeID>(0, graph.GetNumberOfNodes()))
|
||||||
{
|
{
|
||||||
for (const auto edge : graph.GetAdjacentEdgeRange(node))
|
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);
|
util::Percent p(log, number_of_nodes);
|
||||||
|
|
||||||
unsigned current_level = 0;
|
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 &&
|
while (remaining_nodes.size() > 1 &&
|
||||||
number_of_contracted_nodes < static_cast<NodeID>(number_of_nodes * core_factor))
|
number_of_contracted_nodes < static_cast<NodeID>(number_of_nodes * core_factor))
|
||||||
{
|
{
|
||||||
if (!flushed_contractor && (number_of_contracted_nodes >
|
if (number_of_contracted_nodes > next_renumbering)
|
||||||
static_cast<NodeID>(number_of_nodes * 0.65 * core_factor)))
|
|
||||||
{
|
{
|
||||||
log << " [flush " << number_of_contracted_nodes << " nodes] ";
|
RenumberGraph(thread_data_list, remaining_nodes, node_priorities);
|
||||||
|
log << "[renumbered]";
|
||||||
FlushDataAndRebuildContractorGraph(thread_data_list, remaining_nodes, node_priorities);
|
// only one renumbering for now
|
||||||
|
next_renumbering = number_of_nodes;
|
||||||
flushed_contractor = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
@ -179,25 +189,11 @@ void GraphContractor::Run(double core_factor)
|
|||||||
tbb::parallel_for(
|
tbb::parallel_for(
|
||||||
tbb::blocked_range<NodeID>(
|
tbb::blocked_range<NodeID>(
|
||||||
begin_independent_nodes_idx, end_independent_nodes_idx, ContractGrainSize),
|
begin_independent_nodes_idx, end_independent_nodes_idx, ContractGrainSize),
|
||||||
[this, remaining_nodes, flushed_contractor, current_level](
|
[this, remaining_nodes, current_level](const tbb::blocked_range<NodeID> &range) {
|
||||||
const tbb::blocked_range<NodeID> &range) {
|
for (auto position = range.begin(), end = range.end(); position != end;
|
||||||
if (flushed_contractor)
|
++position)
|
||||||
{
|
{
|
||||||
for (auto position = range.begin(), end = range.end(); position != end;
|
node_levels[remaining_nodes[position].id] = current_level;
|
||||||
++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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -289,29 +285,13 @@ void GraphContractor::Run(double core_factor)
|
|||||||
|
|
||||||
if (remaining_nodes.size() > 2)
|
if (remaining_nodes.size() > 2)
|
||||||
{
|
{
|
||||||
if (flushed_contractor)
|
tbb::parallel_for(tbb::blocked_range<NodeID>(0, remaining_nodes.size(), InitGrainSize),
|
||||||
{
|
[this, &remaining_nodes](const tbb::blocked_range<NodeID> &range) {
|
||||||
tbb::parallel_for(tbb::blocked_range<NodeID>(0, remaining_nodes.size(), InitGrainSize),
|
for (auto x = range.begin(), end = range.end(); x != end; ++x)
|
||||||
[this, &remaining_nodes](const tbb::blocked_range<NodeID> &range) {
|
{
|
||||||
for (auto x = range.begin(), end = range.end(); x != end; ++x)
|
is_core_node[remaining_nodes[x].id] = true;
|
||||||
{
|
}
|
||||||
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<NodeID>(0, remaining_nodes.size(), InitGrainSize),
|
|
||||||
[this, &remaining_nodes](const tbb::blocked_range<NodeID> &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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -320,9 +300,14 @@ void GraphContractor::Run(double core_factor)
|
|||||||
is_core_node.clear();
|
is_core_node.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log << "\n";
|
||||||
|
|
||||||
util::Log() << "[core] " << remaining_nodes.size() << " nodes " << graph.GetNumberOfEdges()
|
util::Log() << "[core] " << remaining_nodes.size() << " nodes " << graph.GetNumberOfEdges()
|
||||||
<< " edges.";
|
<< " 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();
|
thread_data_list.data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user