Refactor contractor to pass in graph directly
This commit is contained in:
parent
acb7916996
commit
26c909b64b
@ -95,10 +95,9 @@ class GraphContractor
|
||||
};
|
||||
|
||||
public:
|
||||
GraphContractor(int nodes, std::vector<ContractorEdge> input_edge_list);
|
||||
GraphContractor(ContractorGraph graph);
|
||||
|
||||
GraphContractor(int nodes,
|
||||
std::vector<ContractorEdge> edges,
|
||||
GraphContractor(ContractorGraph graph,
|
||||
std::vector<float> node_levels_,
|
||||
std::vector<EdgeWeight> node_weights_);
|
||||
|
||||
@ -119,18 +118,18 @@ class GraphContractor
|
||||
|
||||
util::UnbufferedLog log;
|
||||
log << "Getting edges of minimized graph ";
|
||||
util::Percent p(log, contractor_graph->GetNumberOfNodes());
|
||||
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
|
||||
if (contractor_graph->GetNumberOfNodes())
|
||||
util::Percent p(log, graph.GetNumberOfNodes());
|
||||
const NodeID number_of_nodes = graph.GetNumberOfNodes();
|
||||
if (graph.GetNumberOfNodes())
|
||||
{
|
||||
Edge new_edge;
|
||||
for (const auto node : util::irange(0u, number_of_nodes))
|
||||
{
|
||||
p.PrintStatus(node);
|
||||
for (auto edge : contractor_graph->GetAdjacentEdgeRange(node))
|
||||
for (auto edge : graph.GetAdjacentEdgeRange(node))
|
||||
{
|
||||
const NodeID target = contractor_graph->GetTarget(edge);
|
||||
const ContractorGraph::EdgeData &data = contractor_graph->GetEdgeData(edge);
|
||||
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];
|
||||
@ -163,7 +162,7 @@ class GraphContractor
|
||||
}
|
||||
}
|
||||
}
|
||||
contractor_graph.reset();
|
||||
graph = ContractorGraph{};
|
||||
orig_node_id_from_new_node_id_map.clear();
|
||||
orig_node_id_from_new_node_id_map.shrink_to_fit();
|
||||
|
||||
@ -198,10 +197,10 @@ class GraphContractor
|
||||
constexpr bool REVERSE_DIRECTION_ENABLED = true;
|
||||
constexpr bool REVERSE_DIRECTION_DISABLED = false;
|
||||
|
||||
for (auto in_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
||||
for (auto in_edge : graph.GetAdjacentEdgeRange(node))
|
||||
{
|
||||
const ContractorEdgeData &in_data = contractor_graph->GetEdgeData(in_edge);
|
||||
const NodeID source = contractor_graph->GetTarget(in_edge);
|
||||
const ContractorEdgeData &in_data = graph.GetEdgeData(in_edge);
|
||||
const NodeID source = graph.GetTarget(in_edge);
|
||||
if (source == node)
|
||||
continue;
|
||||
|
||||
@ -221,14 +220,14 @@ class GraphContractor
|
||||
EdgeWeight max_weight = 0;
|
||||
unsigned number_of_targets = 0;
|
||||
|
||||
for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
||||
for (auto out_edge : graph.GetAdjacentEdgeRange(node))
|
||||
{
|
||||
const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge);
|
||||
const ContractorEdgeData &out_data = graph.GetEdgeData(out_edge);
|
||||
if (!out_data.forward)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const NodeID target = contractor_graph->GetTarget(out_edge);
|
||||
const NodeID target = graph.GetTarget(out_edge);
|
||||
if (node == target)
|
||||
{
|
||||
continue;
|
||||
@ -298,22 +297,22 @@ class GraphContractor
|
||||
SIMULATION_SEARCH_SPACE_SIZE,
|
||||
max_weight,
|
||||
node,
|
||||
*contractor_graph);
|
||||
graph);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int constexpr FULL_SEARCH_SPACE_SIZE = 2000;
|
||||
dijkstra.Run(
|
||||
number_of_targets, FULL_SEARCH_SPACE_SIZE, max_weight, node, *contractor_graph);
|
||||
number_of_targets, FULL_SEARCH_SPACE_SIZE, max_weight, node, graph);
|
||||
}
|
||||
for (auto out_edge : contractor_graph->GetAdjacentEdgeRange(node))
|
||||
for (auto out_edge : graph.GetAdjacentEdgeRange(node))
|
||||
{
|
||||
const ContractorEdgeData &out_data = contractor_graph->GetEdgeData(out_edge);
|
||||
const ContractorEdgeData &out_data = graph.GetEdgeData(out_edge);
|
||||
if (!out_data.forward)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const NodeID target = contractor_graph->GetTarget(out_edge);
|
||||
const NodeID target = graph.GetTarget(out_edge);
|
||||
if (target == node)
|
||||
continue;
|
||||
|
||||
@ -408,7 +407,7 @@ class GraphContractor
|
||||
// This bias function takes up 22 assembly instructions in total on X86
|
||||
bool Bias(const NodeID a, const NodeID b) const;
|
||||
|
||||
std::shared_ptr<ContractorGraph> contractor_graph;
|
||||
ContractorGraph graph;
|
||||
ExternalVector<QueryEdge> external_edge_list;
|
||||
std::vector<NodeID> orig_node_id_from_new_node_id_map;
|
||||
std::vector<float> node_levels;
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "contractor/contractor_graph.hpp"
|
||||
#include "util/log.hpp"
|
||||
|
||||
#include <tbb/parallel_sort.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
@ -13,15 +15,14 @@ namespace contractor
|
||||
|
||||
// Make sure to move in the input edge list!
|
||||
template <typename InputEdgeContainer>
|
||||
std::vector<ContractorEdge> adaptToContractorInput(InputEdgeContainer input_edge_list)
|
||||
ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer input_edge_list)
|
||||
{
|
||||
std::vector<ContractorEdge> edges;
|
||||
edges.reserve(input_edge_list.size() * 2);
|
||||
|
||||
for (const auto &input_edge : input_edge_list)
|
||||
{
|
||||
if (input_edge.data.weight == INVALID_EDGE_WEIGHT)
|
||||
continue;
|
||||
BOOST_ASSERT(input_edge.data.weight < INVALID_EDGE_WEIGHT);
|
||||
|
||||
#ifndef NDEBUG
|
||||
const unsigned int constexpr DAY_IN_DECI_SECONDS = 24 * 60 * 60 * 10;
|
||||
@ -52,10 +53,74 @@ std::vector<ContractorEdge> adaptToContractorInput(InputEdgeContainer input_edge
|
||||
false,
|
||||
input_edge.data.backward ? true : false,
|
||||
input_edge.data.forward ? true : false);
|
||||
};
|
||||
tbb::parallel_sort(edges.begin(), edges.end());
|
||||
|
||||
NodeID edge = 0;
|
||||
for (NodeID i = 0; i < edges.size();)
|
||||
{
|
||||
const NodeID source = edges[i].source;
|
||||
const NodeID target = edges[i].target;
|
||||
const NodeID id = edges[i].data.id;
|
||||
// remove eigenloops
|
||||
if (source == target)
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
ContractorEdge forward_edge;
|
||||
ContractorEdge reverse_edge;
|
||||
forward_edge.source = reverse_edge.source = source;
|
||||
forward_edge.target = reverse_edge.target = target;
|
||||
forward_edge.data.forward = reverse_edge.data.backward = true;
|
||||
forward_edge.data.backward = reverse_edge.data.forward = false;
|
||||
forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
|
||||
forward_edge.data.id = reverse_edge.data.id = id;
|
||||
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
|
||||
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
|
||||
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION;
|
||||
// remove parallel edges
|
||||
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
|
||||
{
|
||||
if (edges[i].data.forward)
|
||||
{
|
||||
forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight);
|
||||
forward_edge.data.duration =
|
||||
std::min(edges[i].data.duration, forward_edge.data.duration);
|
||||
}
|
||||
if (edges[i].data.backward)
|
||||
{
|
||||
reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight);
|
||||
reverse_edge.data.duration =
|
||||
std::min(edges[i].data.duration, reverse_edge.data.duration);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
// merge edges (s,t) and (t,s) into bidirectional edge
|
||||
if (forward_edge.data.weight == reverse_edge.data.weight)
|
||||
{
|
||||
if ((int)forward_edge.data.weight != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
forward_edge.data.backward = true;
|
||||
edges[edge++] = forward_edge;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // insert seperate edges
|
||||
if (((int)forward_edge.data.weight) != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
edges[edge++] = forward_edge;
|
||||
}
|
||||
if ((int)reverse_edge.data.weight != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
edges[edge++] = reverse_edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIXME not sure if we need this
|
||||
edges.shrink_to_fit();
|
||||
return edges;
|
||||
util::Log() << "merged " << edges.size() - edge << " edges out of " << edges.size();
|
||||
edges.resize(edge);
|
||||
|
||||
return ContractorGraph{number_of_nodes, edges};
|
||||
}
|
||||
|
||||
} // namespace contractor
|
||||
|
@ -66,6 +66,8 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
}
|
||||
};
|
||||
|
||||
DynamicGraph() : DynamicGraph(0) {}
|
||||
|
||||
// Constructs an empty graph with a given number of nodes.
|
||||
explicit DynamicGraph(NodeIterator nodes) : number_of_nodes(nodes), number_of_edges(0)
|
||||
{
|
||||
|
@ -72,8 +72,7 @@ int Contractor::Run()
|
||||
|
||||
util::DeallocatingVector<QueryEdge> contracted_edge_list;
|
||||
{ // own scope to not keep the contractor around
|
||||
GraphContractor graph_contractor(max_edge_id + 1,
|
||||
adaptToContractorInput(std::move(edge_based_edge_list)),
|
||||
GraphContractor graph_contractor(toContractorGraph(max_edge_id+1, std::move(edge_based_edge_list)),
|
||||
std::move(node_levels),
|
||||
std::move(node_weights));
|
||||
graph_contractor.Run(config.core_factor);
|
||||
|
@ -5,87 +5,17 @@ namespace osrm
|
||||
namespace contractor
|
||||
{
|
||||
|
||||
GraphContractor::GraphContractor(int nodes, std::vector<ContractorEdge> input_edge_list)
|
||||
: GraphContractor(nodes, std::move(input_edge_list), {}, {})
|
||||
GraphContractor::GraphContractor(ContractorGraph graph_)
|
||||
: GraphContractor(std::move(graph_), {}, {})
|
||||
{
|
||||
}
|
||||
|
||||
GraphContractor::GraphContractor(int nodes,
|
||||
std::vector<ContractorEdge> edges,
|
||||
GraphContractor::GraphContractor(ContractorGraph graph_,
|
||||
std::vector<float> node_levels_,
|
||||
std::vector<EdgeWeight> node_weights_)
|
||||
: node_levels(std::move(node_levels_)), node_weights(std::move(node_weights_))
|
||||
: graph(std::move(graph_)), node_levels(std::move(node_levels_)),
|
||||
node_weights(std::move(node_weights_))
|
||||
{
|
||||
tbb::parallel_sort(edges.begin(), edges.end());
|
||||
NodeID edge = 0;
|
||||
for (NodeID i = 0; i < edges.size();)
|
||||
{
|
||||
const NodeID source = edges[i].source;
|
||||
const NodeID target = edges[i].target;
|
||||
const NodeID id = edges[i].data.id;
|
||||
// remove eigenloops
|
||||
if (source == target)
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
ContractorEdge forward_edge;
|
||||
ContractorEdge reverse_edge;
|
||||
forward_edge.source = reverse_edge.source = source;
|
||||
forward_edge.target = reverse_edge.target = target;
|
||||
forward_edge.data.forward = reverse_edge.data.backward = true;
|
||||
forward_edge.data.backward = reverse_edge.data.forward = false;
|
||||
forward_edge.data.shortcut = reverse_edge.data.shortcut = false;
|
||||
forward_edge.data.id = reverse_edge.data.id = id;
|
||||
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
|
||||
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
|
||||
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION;
|
||||
// remove parallel edges
|
||||
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
|
||||
{
|
||||
if (edges[i].data.forward)
|
||||
{
|
||||
forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight);
|
||||
forward_edge.data.duration =
|
||||
std::min(edges[i].data.duration, forward_edge.data.duration);
|
||||
}
|
||||
if (edges[i].data.backward)
|
||||
{
|
||||
reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight);
|
||||
reverse_edge.data.duration =
|
||||
std::min(edges[i].data.duration, reverse_edge.data.duration);
|
||||
}
|
||||
++i;
|
||||
}
|
||||
// merge edges (s,t) and (t,s) into bidirectional edge
|
||||
if (forward_edge.data.weight == reverse_edge.data.weight)
|
||||
{
|
||||
if ((int)forward_edge.data.weight != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
forward_edge.data.backward = true;
|
||||
edges[edge++] = forward_edge;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // insert seperate edges
|
||||
if (((int)forward_edge.data.weight) != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
edges[edge++] = forward_edge;
|
||||
}
|
||||
if ((int)reverse_edge.data.weight != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
edges[edge++] = reverse_edge;
|
||||
}
|
||||
}
|
||||
}
|
||||
util::Log() << "merged " << edges.size() - edge << " edges out of " << edges.size();
|
||||
edges.resize(edge);
|
||||
contractor_graph = std::make_shared<ContractorGraph>(nodes, edges);
|
||||
edges.clear();
|
||||
edges.shrink_to_fit();
|
||||
|
||||
BOOST_ASSERT(0 == edges.capacity());
|
||||
util::Log() << "contractor finished initalization";
|
||||
}
|
||||
|
||||
/* Flush all data from the contraction to disc and reorder stuff for better locality */
|
||||
@ -107,7 +37,7 @@ void GraphContractor::FlushDataAndRebuildContractorGraph(
|
||||
orig_node_id_from_new_node_id_map.resize(remaining_nodes.size());
|
||||
// this map gives the new IDs from the old ones, necessary to remap targets from the
|
||||
// remaining graph
|
||||
const auto number_of_nodes = contractor_graph->GetNumberOfNodes();
|
||||
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()))
|
||||
{
|
||||
@ -127,12 +57,12 @@ void GraphContractor::FlushDataAndRebuildContractorGraph(
|
||||
node.id = new_node_id;
|
||||
}
|
||||
// walk over all nodes
|
||||
for (const auto source : util::irange<NodeID>(0UL, contractor_graph->GetNumberOfNodes()))
|
||||
for (const auto source : util::irange<NodeID>(0UL, graph.GetNumberOfNodes()))
|
||||
{
|
||||
for (auto current_edge : contractor_graph->GetAdjacentEdgeRange(source))
|
||||
for (auto current_edge : graph.GetAdjacentEdgeRange(source))
|
||||
{
|
||||
ContractorGraph::EdgeData &data = contractor_graph->GetEdgeData(current_edge);
|
||||
const NodeID target = contractor_graph->GetTarget(current_edge);
|
||||
ContractorGraph::EdgeData &data = graph.GetEdgeData(current_edge);
|
||||
const NodeID target = graph.GetTarget(current_edge);
|
||||
if (SPECIAL_NODEID == new_node_id_from_orig_id_map[source])
|
||||
{
|
||||
external_edge_list.push_back({source, target, data});
|
||||
@ -158,14 +88,14 @@ void GraphContractor::FlushDataAndRebuildContractorGraph(
|
||||
// Delete old node_priorities vector
|
||||
node_weights.swap(new_node_weights);
|
||||
// old Graph is removed
|
||||
contractor_graph.reset();
|
||||
graph = ContractorGraph{};
|
||||
// create new graph
|
||||
tbb::parallel_sort(new_edge_set.begin(), new_edge_set.end());
|
||||
contractor_graph = std::make_shared<ContractorGraph>(remaining_nodes.size(), new_edge_set);
|
||||
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 = contractor_graph->GetNumberOfNodes();
|
||||
thread_data_list.number_of_nodes = graph.GetNumberOfNodes();
|
||||
}
|
||||
|
||||
void GraphContractor::Run(double core_factor)
|
||||
@ -181,7 +111,7 @@ void GraphContractor::Run(double core_factor)
|
||||
const constexpr size_t NeighboursGrainSize = 1;
|
||||
const constexpr size_t DeleteGrainSize = 1;
|
||||
|
||||
const NodeID number_of_nodes = contractor_graph->GetNumberOfNodes();
|
||||
const NodeID number_of_nodes = graph.GetNumberOfNodes();
|
||||
|
||||
ThreadDataContainer thread_data_list(number_of_nodes);
|
||||
|
||||
@ -340,11 +270,10 @@ void GraphContractor::Run(double core_factor)
|
||||
{
|
||||
for (const ContractorEdge &edge : data->inserted_edges)
|
||||
{
|
||||
const EdgeID current_edge_ID = contractor_graph->FindEdge(edge.source, edge.target);
|
||||
const EdgeID current_edge_ID = graph.FindEdge(edge.source, edge.target);
|
||||
if (current_edge_ID != SPECIAL_EDGEID)
|
||||
{
|
||||
ContractorGraph::EdgeData ¤t_data =
|
||||
contractor_graph->GetEdgeData(current_edge_ID);
|
||||
ContractorGraph::EdgeData ¤t_data = graph.GetEdgeData(current_edge_ID);
|
||||
if (current_data.shortcut && edge.data.forward == current_data.forward &&
|
||||
edge.data.backward == current_data.backward)
|
||||
{
|
||||
@ -357,7 +286,7 @@ void GraphContractor::Run(double core_factor)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
contractor_graph->InsertEdge(edge.source, edge.target, edge.data);
|
||||
graph.InsertEdge(edge.source, edge.target, edge.data);
|
||||
}
|
||||
data->inserted_edges.clear();
|
||||
}
|
||||
@ -421,8 +350,8 @@ void GraphContractor::Run(double core_factor)
|
||||
is_core_node.clear();
|
||||
}
|
||||
|
||||
util::Log() << "[core] " << remaining_nodes.size() << " nodes "
|
||||
<< contractor_graph->GetNumberOfEdges() << " edges.";
|
||||
util::Log() << "[core] " << remaining_nodes.size() << " nodes " << graph.GetNumberOfEdges()
|
||||
<< " edges.";
|
||||
|
||||
thread_data_list.data.clear();
|
||||
}
|
||||
@ -465,9 +394,9 @@ void GraphContractor::DeleteIncomingEdges(ContractorThreadData *data, const Node
|
||||
neighbours.clear();
|
||||
|
||||
// find all neighbours
|
||||
for (auto e : contractor_graph->GetAdjacentEdgeRange(node))
|
||||
for (auto e : graph.GetAdjacentEdgeRange(node))
|
||||
{
|
||||
const NodeID u = contractor_graph->GetTarget(e);
|
||||
const NodeID u = graph.GetTarget(e);
|
||||
if (u != node)
|
||||
{
|
||||
neighbours.push_back(u);
|
||||
@ -479,7 +408,7 @@ void GraphContractor::DeleteIncomingEdges(ContractorThreadData *data, const Node
|
||||
|
||||
for (const auto i : util::irange<std::size_t>(0, neighbours.size()))
|
||||
{
|
||||
contractor_graph->DeleteEdgesTo(neighbours[i], node);
|
||||
graph.DeleteEdgesTo(neighbours[i], node);
|
||||
}
|
||||
}
|
||||
|
||||
@ -492,9 +421,9 @@ bool GraphContractor::UpdateNodeNeighbours(std::vector<float> &priorities,
|
||||
neighbours.clear();
|
||||
|
||||
// find all neighbours
|
||||
for (auto e : contractor_graph->GetAdjacentEdgeRange(node))
|
||||
for (auto e : graph.GetAdjacentEdgeRange(node))
|
||||
{
|
||||
const NodeID u = contractor_graph->GetTarget(e);
|
||||
const NodeID u = graph.GetTarget(e);
|
||||
if (u == node)
|
||||
{
|
||||
continue;
|
||||
@ -523,9 +452,9 @@ bool GraphContractor::IsNodeIndependent(const std::vector<float> &priorities,
|
||||
std::vector<NodeID> &neighbours = data->neighbours;
|
||||
neighbours.clear();
|
||||
|
||||
for (auto e : contractor_graph->GetAdjacentEdgeRange(node))
|
||||
for (auto e : graph.GetAdjacentEdgeRange(node))
|
||||
{
|
||||
const NodeID target = contractor_graph->GetTarget(e);
|
||||
const NodeID target = graph.GetTarget(e);
|
||||
if (node == target)
|
||||
{
|
||||
continue;
|
||||
@ -552,9 +481,9 @@ bool GraphContractor::IsNodeIndependent(const std::vector<float> &priorities,
|
||||
// examine all neighbours that are at most 2 hops away
|
||||
for (const NodeID u : neighbours)
|
||||
{
|
||||
for (auto e : contractor_graph->GetAdjacentEdgeRange(u))
|
||||
for (auto e : graph.GetAdjacentEdgeRange(u))
|
||||
{
|
||||
const NodeID target = contractor_graph->GetTarget(e);
|
||||
const NodeID target = graph.GetTarget(e);
|
||||
if (node == target)
|
||||
{
|
||||
continue;
|
||||
|
Loading…
Reference in New Issue
Block a user