Replace flush in contract with in-place renumbering
This commit is contained in:
parent
26c909b64b
commit
e011c60e12
@ -163,13 +163,6 @@ class GraphContractor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
graph = ContractorGraph{};
|
graph = ContractorGraph{};
|
||||||
orig_node_id_from_new_node_id_map.clear();
|
|
||||||
orig_node_id_from_new_node_id_map.shrink_to_fit();
|
|
||||||
|
|
||||||
BOOST_ASSERT(0 == orig_node_id_from_new_node_id_map.capacity());
|
|
||||||
|
|
||||||
edges.append(external_edge_list.begin(), external_edge_list.end());
|
|
||||||
external_edge_list.clear();
|
|
||||||
|
|
||||||
// sort and remove duplicates
|
// sort and remove duplicates
|
||||||
tbb::parallel_sort(edges.begin(), edges.end());
|
tbb::parallel_sort(edges.begin(), edges.end());
|
||||||
@ -408,7 +401,6 @@ class GraphContractor
|
|||||||
bool Bias(const NodeID a, const NodeID b) const;
|
bool Bias(const NodeID a, const NodeID b) const;
|
||||||
|
|
||||||
ContractorGraph graph;
|
ContractorGraph graph;
|
||||||
ExternalVector<QueryEdge> external_edge_list;
|
|
||||||
std::vector<NodeID> orig_node_id_from_new_node_id_map;
|
std::vector<NodeID> orig_node_id_from_new_node_id_map;
|
||||||
std::vector<float> node_levels;
|
std::vector<float> node_levels;
|
||||||
|
|
||||||
|
@ -351,17 +351,25 @@ template <typename EdgeDataT> class DynamicGraph
|
|||||||
edge_list[edge].target = old_to_new_node[edge_list[edge].target];
|
edge_list[edge].target = old_to_new_node[edge_list[edge].target];
|
||||||
old_to_new_edge[edge] = new_edge_index++;
|
old_to_new_edge[edge] = new_edge_index++;
|
||||||
}
|
}
|
||||||
// and all adjacent empty edges
|
node_array[node].first_edge = new_first_edge;
|
||||||
for (auto edge = EndEdges(node); edge < number_of_edges && isDummy(edge); edge++)
|
}
|
||||||
|
auto number_of_valid_edges = new_edge_index;
|
||||||
|
|
||||||
|
// move all dummy edges to the end of the renumbered range
|
||||||
|
for (auto edge : util::irange<NodeID>(0, edge_list.size()))
|
||||||
|
{
|
||||||
|
if (old_to_new_edge[edge] == SPECIAL_EDGEID)
|
||||||
{
|
{
|
||||||
|
BOOST_ASSERT(isDummy(edge));
|
||||||
old_to_new_edge[edge] = new_edge_index++;
|
old_to_new_edge[edge] = new_edge_index++;
|
||||||
}
|
}
|
||||||
node_array[node].first_edge = new_first_edge;
|
|
||||||
}
|
}
|
||||||
BOOST_ASSERT(std::find(old_to_new_edge.begin(), old_to_new_edge.end(), SPECIAL_EDGEID) ==
|
BOOST_ASSERT(std::find(old_to_new_edge.begin(), old_to_new_edge.end(), SPECIAL_EDGEID) ==
|
||||||
old_to_new_edge.end());
|
old_to_new_edge.end());
|
||||||
|
|
||||||
util::inplacePermutation(edge_list.begin(), edge_list.end(), old_to_new_edge);
|
util::inplacePermutation(edge_list.begin(), edge_list.end(), old_to_new_edge);
|
||||||
|
// Remove useless dummy nodes at the end
|
||||||
|
edge_list.resize(number_of_valid_edges);
|
||||||
|
number_of_edges = number_of_valid_edges;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -18,84 +18,54 @@ GraphContractor::GraphContractor(ContractorGraph graph_,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Flush all data from the contraction to disc and reorder stuff for better locality */
|
/* Reorder nodes for better locality */
|
||||||
void GraphContractor::FlushDataAndRebuildContractorGraph(
|
void GraphContractor::FlushDataAndRebuildContractorGraph(
|
||||||
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)
|
||||||
{
|
{
|
||||||
util::DeallocatingVector<ContractorEdge> new_edge_set; // this one is not explicitely
|
|
||||||
// cleared since it goes out of
|
|
||||||
// scope anywa
|
|
||||||
// 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();
|
||||||
// Create new priority array
|
orig_node_id_from_new_node_id_map.resize(graph.GetNumberOfNodes(), SPECIAL_NODEID);
|
||||||
std::vector<float> new_node_priority(remaining_nodes.size());
|
std::vector<NodeID> new_node_id_from_orig_node_id(graph.GetNumberOfNodes(), SPECIAL_NODEID);
|
||||||
std::vector<EdgeWeight> new_node_weights(remaining_nodes.size());
|
|
||||||
// this map gives the old IDs from the new ones, necessary to get a consistent graph
|
auto new_node_id = 0;
|
||||||
// at the end of contraction
|
|
||||||
orig_node_id_from_new_node_id_map.resize(remaining_nodes.size());
|
// All remaining nodes get the low IDs
|
||||||
// this map gives the new IDs from the old ones, necessary to remap targets from the
|
for (auto &remaining : remaining_nodes)
|
||||||
// remaining graph
|
|
||||||
const auto number_of_nodes = graph.GetNumberOfNodes();
|
|
||||||
std::vector<NodeID> new_node_id_from_orig_id_map(number_of_nodes, SPECIAL_NODEID);
|
|
||||||
for (const auto new_node_id : util::irange<std::size_t>(0UL, remaining_nodes.size()))
|
|
||||||
{
|
{
|
||||||
auto &node = remaining_nodes[new_node_id];
|
auto id = new_node_id++;
|
||||||
BOOST_ASSERT(node_priorities.size() > node.id);
|
new_node_id_from_orig_node_id[remaining.id] = id;
|
||||||
new_node_priority[new_node_id] = node_priorities[node.id];
|
orig_node_id_from_new_node_id_map[id] = remaining.id;
|
||||||
BOOST_ASSERT(node_weights.size() > node.id);
|
remaining.id = id;
|
||||||
new_node_weights[new_node_id] = node_weights[node.id];
|
|
||||||
}
|
}
|
||||||
// build forward and backward renumbering map and remap ids in remaining_nodes
|
|
||||||
for (const auto new_node_id : util::irange<std::size_t>(0UL, remaining_nodes.size()))
|
// Already contracted nodes get the high IDs
|
||||||
|
for (const auto orig_id : util::irange<std::size_t>(0, graph.GetNumberOfNodes()))
|
||||||
{
|
{
|
||||||
auto &node = remaining_nodes[new_node_id];
|
if (new_node_id_from_orig_node_id[orig_id] == SPECIAL_NODEID)
|
||||||
// create renumbering maps in both directions
|
|
||||||
orig_node_id_from_new_node_id_map[new_node_id] = node.id;
|
|
||||||
new_node_id_from_orig_id_map[node.id] = new_node_id;
|
|
||||||
node.id = new_node_id;
|
|
||||||
}
|
|
||||||
// walk over all nodes
|
|
||||||
for (const auto source : util::irange<NodeID>(0UL, graph.GetNumberOfNodes()))
|
|
||||||
{
|
|
||||||
for (auto current_edge : graph.GetAdjacentEdgeRange(source))
|
|
||||||
{
|
{
|
||||||
ContractorGraph::EdgeData &data = graph.GetEdgeData(current_edge);
|
auto id = new_node_id++;
|
||||||
const NodeID target = graph.GetTarget(current_edge);
|
new_node_id_from_orig_node_id[orig_id] = id;
|
||||||
if (SPECIAL_NODEID == new_node_id_from_orig_id_map[source])
|
orig_node_id_from_new_node_id_map[id] = orig_id;
|
||||||
{
|
}
|
||||||
external_edge_list.push_back({source, target, data});
|
}
|
||||||
}
|
BOOST_ASSERT(new_node_id == graph.GetNumberOfNodes());
|
||||||
else
|
|
||||||
{
|
util::inplacePermutation(
|
||||||
// node is not yet contracted.
|
node_priorities.begin(), node_priorities.end(), new_node_id_from_orig_node_id);
|
||||||
// add (renumbered) outgoing edges to new util::DynamicGraph.
|
util::inplacePermutation(
|
||||||
ContractorEdge new_edge = {new_node_id_from_orig_id_map[source],
|
node_weights.begin(), node_weights.end(), new_node_id_from_orig_node_id);
|
||||||
new_node_id_from_orig_id_map[target],
|
graph.Renumber(new_node_id_from_orig_node_id);
|
||||||
data};
|
|
||||||
new_edge.data.is_original_via_node_ID = true;
|
// Mark all existing edges to reference old via IDs
|
||||||
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_node_id_from_orig_id_map[source],
|
for (const auto node : util::irange<NodeID>(0, graph.GetNumberOfNodes()))
|
||||||
"new source id not resolveable");
|
{
|
||||||
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_node_id_from_orig_id_map[target],
|
for (const auto edge : graph.GetAdjacentEdgeRange(node))
|
||||||
"new target id not resolveable");
|
{
|
||||||
new_edge_set.push_back(new_edge);
|
graph.GetEdgeData(edge).is_original_via_node_ID = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Replace old priorities array by new one
|
|
||||||
node_priorities.swap(new_node_priority);
|
|
||||||
// Delete old node_priorities vector
|
|
||||||
node_weights.swap(new_node_weights);
|
|
||||||
// old Graph is removed
|
|
||||||
graph = ContractorGraph{};
|
|
||||||
// create new graph
|
|
||||||
tbb::parallel_sort(new_edge_set.begin(), new_edge_set.end());
|
|
||||||
graph = ContractorGraph{static_cast<NodeID>(remaining_nodes.size()), new_edge_set};
|
|
||||||
new_edge_set.clear();
|
|
||||||
// INFO: MAKE SURE THIS IS THE LAST OPERATION OF THE FLUSH!
|
|
||||||
// reinitialize heaps and ThreadData objects with appropriate size
|
|
||||||
thread_data_list.number_of_nodes = graph.GetNumberOfNodes();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphContractor::Run(double core_factor)
|
void GraphContractor::Run(double core_factor)
|
||||||
|
Loading…
Reference in New Issue
Block a user