Add edge-based graph loading in MLD facade

This commit is contained in:
Michael Krasnyk
2017-03-06 23:00:11 +01:00
committed by Patrick Niklaus
parent 53b0417e36
commit f42136637d
15 changed files with 406 additions and 178 deletions
@@ -22,33 +22,33 @@ std::vector<ContractorEdge> adaptToContractorInput(InputEdgeContainer input_edge
{
#ifndef NDEBUG
const unsigned int constexpr DAY_IN_DECI_SECONDS = 24 * 60 * 60 * 10;
if (static_cast<unsigned int>(std::max(input_edge.weight, 1)) > DAY_IN_DECI_SECONDS)
if (static_cast<unsigned int>(std::max(input_edge.data.weight, 1)) > DAY_IN_DECI_SECONDS)
{
util::Log(logWARNING) << "Edge weight large -> "
<< static_cast<unsigned int>(std::max(input_edge.weight, 1))
<< static_cast<unsigned int>(std::max(input_edge.data.weight, 1))
<< " : " << static_cast<unsigned int>(input_edge.source) << " -> "
<< static_cast<unsigned int>(input_edge.target);
}
#endif
edges.emplace_back(input_edge.source,
input_edge.target,
std::max(input_edge.weight, 1),
input_edge.duration,
std::max(input_edge.data.weight, 1),
input_edge.data.duration,
1,
input_edge.edge_id,
input_edge.data.edge_id,
false,
input_edge.forward ? true : false,
input_edge.backward ? true : false);
input_edge.data.forward ? true : false,
input_edge.data.backward ? true : false);
edges.emplace_back(input_edge.target,
input_edge.source,
std::max(input_edge.weight, 1),
input_edge.duration,
std::max(input_edge.data.weight, 1),
input_edge.data.duration,
1,
input_edge.edge_id,
input_edge.data.edge_id,
false,
input_edge.backward ? true : false,
input_edge.forward ? true : false);
input_edge.data.backward ? true : false,
input_edge.data.forward ? true : false);
}
// FIXME not sure if we need this
edges.shrink_to_fit();
@@ -2,6 +2,7 @@
#define OSRM_ENGINE_DATAFACADE_ALGORITHM_DATAFACADE_HPP
#include "contractor/query_edge.hpp"
#include "extractor/edge_based_edge.hpp"
#include "engine/algorithm.hpp"
#include "partition/cell_storage.hpp"
@@ -66,6 +67,25 @@ template <> class AlgorithmDataFacade<algorithm::CoreCH>
template <> class AlgorithmDataFacade<algorithm::MLD>
{
public:
using EdgeData = extractor::EdgeBasedEdge::EdgeData;
// search graph access
virtual unsigned GetNumberOfNodes() const = 0;
virtual unsigned GetNumberOfEdges() const = 0;
virtual unsigned GetOutDegree(const NodeID n) const = 0;
virtual NodeID GetTarget(const EdgeID e) const = 0;
virtual const EdgeData &GetEdgeData(const EdgeID e) const = 0;
virtual EdgeID BeginEdges(const NodeID n) const = 0;
virtual EdgeID EndEdges(const NodeID n) const = 0;
virtual EdgeRange GetAdjacentEdgeRange(const NodeID node) const = 0;
virtual const partition::MultiLevelPartitionView &GetMultiLevelPartition() const = 0;
virtual const partition::CellStorageView &GetCellStorage() const = 0;
@@ -1200,12 +1200,67 @@ class ContiguousInternalMemoryDataFacade<algorithm::MLD>
: public ContiguousInternalMemoryDataFacadeBase,
public ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>
{
private:
using QueryGraph = util::StaticGraph<EdgeData, true>;
using GraphNode = QueryGraph::NodeArrayEntry;
using GraphEdge = QueryGraph::EdgeArrayEntry;
std::unique_ptr<QueryGraph> m_query_graph;
void InitializeGraphPointer(storage::DataLayout &data_layout, char *memory_block)
{
auto graph_nodes_ptr = data_layout.GetBlockPtr<GraphNode>(
memory_block, storage::DataLayout::MLD_GRAPH_NODE_LIST);
auto graph_edges_ptr = data_layout.GetBlockPtr<GraphEdge>(
memory_block, storage::DataLayout::MLD_GRAPH_EDGE_LIST);
util::ShM<GraphNode, true>::vector node_list(
graph_nodes_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_NODE_LIST]);
util::ShM<GraphEdge, true>::vector edge_list(
graph_edges_ptr, data_layout.num_entries[storage::DataLayout::MLD_GRAPH_EDGE_LIST]);
m_query_graph.reset(new QueryGraph(node_list, edge_list));
}
public:
ContiguousInternalMemoryDataFacade(std::shared_ptr<ContiguousBlockAllocator> allocator)
: ContiguousInternalMemoryDataFacadeBase(allocator),
ContiguousInternalMemoryAlgorithmDataFacade<algorithm::MLD>(allocator)
{
InitializeInternalPointers(allocator->GetLayout(), allocator->GetMemory());
}
void InitializeInternalPointers(storage::DataLayout &data_layout, char *memory_block)
{
InitializeGraphPointer(data_layout, memory_block);
}
// search graph access
unsigned GetNumberOfNodes() const override final { return m_query_graph->GetNumberOfNodes(); }
unsigned GetNumberOfEdges() const override final { return m_query_graph->GetNumberOfEdges(); }
unsigned GetOutDegree(const NodeID n) const override final
{
return m_query_graph->GetOutDegree(n);
}
NodeID GetTarget(const EdgeID e) const override final { return m_query_graph->GetTarget(e); }
EdgeData &GetEdgeData(const EdgeID e) const override final
{
return m_query_graph->GetEdgeData(e);
}
EdgeID BeginEdges(const NodeID n) const override final { return m_query_graph->BeginEdges(n); }
EdgeID EndEdges(const NodeID n) const override final { return m_query_graph->EndEdges(n); }
EdgeRange GetAdjacentEdgeRange(const NodeID node) const override final
{
return m_query_graph->GetAdjacentEdgeRange(node);
}
};
}
+29 -15
View File
@@ -29,11 +29,29 @@ struct EdgeBasedEdge
NodeID source;
NodeID target;
NodeID edge_id;
EdgeWeight weight;
EdgeWeight duration : 30;
std::uint32_t forward : 1;
std::uint32_t backward : 1;
struct EdgeData
{
EdgeData() : edge_id(0), weight(0), duration(0), forward(false), backward(false) {}
EdgeData(const NodeID edge_id,
const EdgeWeight weight,
const EdgeWeight duration,
const bool forward,
const bool backward)
: edge_id(edge_id), weight(weight), duration(duration), forward(forward),
backward(backward)
{
}
NodeID edge_id;
EdgeWeight weight;
EdgeWeight duration : 30;
std::uint32_t forward : 1;
std::uint32_t backward : 1;
auto is_unidirectional() const { return !forward || !backward; }
} data;
};
static_assert(sizeof(extractor::EdgeBasedEdge) == 20,
"Size of extractor::EdgeBasedEdge type is "
@@ -42,10 +60,7 @@ static_assert(sizeof(extractor::EdgeBasedEdge) == 20,
// Impl.
inline EdgeBasedEdge::EdgeBasedEdge()
: source(0), target(0), edge_id(0), weight(0), duration(0), forward(false), backward(false)
{
}
inline EdgeBasedEdge::EdgeBasedEdge() : source(0), target(0) {}
inline EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
const NodeID target,
@@ -54,19 +69,18 @@ inline EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
const EdgeWeight duration,
const bool forward,
const bool backward)
: source(source), target(target), edge_id(edge_id), weight(weight), duration(duration),
forward(forward), backward(backward)
: source(source), target(target), data{edge_id, weight, duration, forward, backward}
{
}
inline bool EdgeBasedEdge::operator<(const EdgeBasedEdge &other) const
{
const auto unidirectional = (!forward || !backward);
const auto other_is_unidirectional = (!other.forward || !other.backward);
const auto unidirectional = data.is_unidirectional();
const auto other_is_unidirectional = other.data.is_unidirectional();
// if all items are the same, we want to keep bidirectional edges. due to the `<` operator,
// preferring 0 (false) over 1 (true), we need to compare the inverse of `bidirectional`
return std::tie(source, target, weight, unidirectional) <
std::tie(other.source, other.target, other.weight, other_is_unidirectional);
return std::tie(source, target, data.weight, unidirectional) <
std::tie(other.source, other.target, other.data.weight, other_is_unidirectional);
}
} // ns extractor
} // ns osrm
+102 -102
View File
@@ -19,7 +19,7 @@ namespace osrm
namespace partition
{
struct EdgeBasedGraphEdgeData : extractor::EdgeBasedEdge
struct EdgeBasedGraphEdgeData : extractor::EdgeBasedEdge::EdgeData
{
// We need to write out the full edge based graph again.
@@ -38,6 +38,107 @@ struct EdgeBasedGraphEdge : EdgeBasedGraph::InputEdge
using Base::Base;
};
// Bidirectional (s,t) to (s,t) and (t,s)
std::vector<extractor::EdgeBasedEdge>
SplitBidirectionalEdges(const std::vector<extractor::EdgeBasedEdge> &edges)
{
std::vector<extractor::EdgeBasedEdge> directed;
directed.reserve(edges.size() * 2);
for (const auto &edge : edges)
{
directed.emplace_back(edge.source,
edge.target,
edge.data.edge_id,
std::max(edge.data.weight, 1),
edge.data.duration,
edge.data.forward,
edge.data.backward);
directed.emplace_back(edge.target,
edge.source,
edge.data.edge_id,
std::max(edge.data.weight, 1),
edge.data.duration,
edge.data.backward,
edge.data.forward);
}
return directed;
}
std::vector<EdgeBasedGraphEdge>
PrepareEdgesForUsageInGraph(std::vector<extractor::EdgeBasedEdge> edges)
{
std::sort(begin(edges), end(edges));
std::vector<EdgeBasedGraphEdge> graph_edges;
graph_edges.reserve(edges.size());
for (NodeID i = 0; i < edges.size();)
{
const NodeID source = edges[i].source;
const NodeID target = edges[i].target;
// remove eigenloops
if (source == target)
{
++i;
continue;
}
EdgeBasedGraphEdge forward_edge;
EdgeBasedGraphEdge reverse_edge;
forward_edge.source = reverse_edge.source = source;
forward_edge.target = reverse_edge.target = target;
forward_edge.data.edge_id = reverse_edge.data.edge_id = edges[i].data.edge_id;
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION_INT_30;
forward_edge.data.forward = reverse_edge.data.backward = true;
forward_edge.data.backward = reverse_edge.data.forward = false;
// 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;
graph_edges.push_back(forward_edge);
}
}
else
{ // insert seperate edges
if (((int)forward_edge.data.weight) != INVALID_EDGE_WEIGHT)
{
graph_edges.push_back(forward_edge);
}
if ((int)reverse_edge.data.weight != INVALID_EDGE_WEIGHT)
{
graph_edges.push_back(reverse_edge);
}
}
}
return graph_edges;
}
struct EdgeBasedGraphReader
{
EdgeBasedGraphReader(storage::io::FileReader &reader)
@@ -74,107 +175,6 @@ struct EdgeBasedGraphReader
}
private:
// Bidirectional (s,t) to (s,t) and (t,s)
std::vector<extractor::EdgeBasedEdge>
SplitBidirectionalEdges(const std::vector<extractor::EdgeBasedEdge> &edges)
{
std::vector<extractor::EdgeBasedEdge> directed;
directed.reserve(edges.size() * 2);
for (const auto &edge : edges)
{
directed.emplace_back(edge.source,
edge.target,
edge.edge_id,
std::max(edge.weight, 1),
edge.duration,
edge.forward,
edge.backward);
directed.emplace_back(edge.target,
edge.source,
edge.edge_id,
std::max(edge.weight, 1),
edge.duration,
edge.backward,
edge.forward);
}
return directed;
}
std::vector<EdgeBasedGraphEdge>
PrepareEdgesForUsageInGraph(std::vector<extractor::EdgeBasedEdge> edges)
{
std::sort(begin(edges), end(edges));
std::vector<EdgeBasedGraphEdge> graph_edges;
graph_edges.reserve(edges.size());
for (NodeID i = 0; i < edges.size();)
{
const NodeID source = edges[i].source;
const NodeID target = edges[i].target;
// remove eigenloops
if (source == target)
{
++i;
continue;
}
EdgeBasedGraphEdge forward_edge;
EdgeBasedGraphEdge reverse_edge;
forward_edge.source = reverse_edge.source = source;
forward_edge.target = reverse_edge.target = target;
forward_edge.data.edge_id = reverse_edge.data.edge_id = edges[i].edge_id;
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION_INT_30;
forward_edge.data.forward = reverse_edge.data.backward = true;
forward_edge.data.backward = reverse_edge.data.forward = false;
// remove parallel edges
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
{
if (edges[i].forward)
{
forward_edge.data.weight = std::min(edges[i].weight, forward_edge.data.weight);
forward_edge.data.duration =
std::min(edges[i].duration, forward_edge.data.duration);
}
if (edges[i].backward)
{
reverse_edge.data.weight = std::min(edges[i].weight, reverse_edge.data.weight);
reverse_edge.data.duration =
std::min(edges[i].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;
graph_edges.push_back(forward_edge);
}
}
else
{ // insert seperate edges
if (((int)forward_edge.data.weight) != INVALID_EDGE_WEIGHT)
{
graph_edges.push_back(forward_edge);
}
if ((int)reverse_edge.data.weight != INVALID_EDGE_WEIGHT)
{
graph_edges.push_back(reverse_edge);
}
}
}
return graph_edges;
}
std::vector<extractor::EdgeBasedEdge> edges;
std::size_t num_nodes;
};
+5 -1
View File
@@ -64,7 +64,9 @@ const constexpr char *block_id_to_name[] = {"NAME_CHAR_DATA",
"MLD_CELL_SOURCE_BOUNDARY",
"MLD_CELL_DESTINATION_BOUNDARY",
"MLD_CELLS",
"MLD_CELL_LEVEL_OFFSETS"};
"MLD_CELL_LEVEL_OFFSETS",
"MLD_GRAPH_NODE_LIST",
"MLD_GRAPH_EDGE_LIST"};
struct DataLayout
{
@@ -117,6 +119,8 @@ struct DataLayout
MLD_CELL_DESTINATION_BOUNDARY,
MLD_CELLS,
MLD_CELL_LEVEL_OFFSETS,
MLD_GRAPH_NODE_LIST,
MLD_GRAPH_EDGE_LIST,
NUM_BLOCKS
};
+1
View File
@@ -71,6 +71,7 @@ struct StorageConfig final
boost::filesystem::path turn_lane_description_path;
boost::filesystem::path mld_partition_path;
boost::filesystem::path mld_storage_path;
boost::filesystem::path edge_based_graph_path;
};
}
}
@@ -106,6 +106,18 @@ template <typename DataT> class SharedMemoryWrapper
return m_ptr[index];
}
const DataT &front() const {
BOOST_ASSERT_MSG(m_size > 0, "invalid size");
return m_ptr[0];
}
const DataT &back() const {
BOOST_ASSERT_MSG(m_size > 0, "invalid size");
return m_ptr[m_size - 1];
}
auto data() const { return m_ptr; }
template <typename T>
friend void swap(SharedMemoryWrapper<T> &, SharedMemoryWrapper<T> &) noexcept;
};
+4 -1
View File
@@ -134,8 +134,11 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes,
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector &edges)
{
BOOST_ASSERT(!nodes.empty());
number_of_nodes = static_cast<decltype(number_of_nodes)>(nodes.size() - 1);
number_of_edges = static_cast<decltype(number_of_edges)>(edges.size());
number_of_edges = static_cast<decltype(number_of_edges)>(nodes.back().first_edge);
BOOST_ASSERT(number_of_edges <= edges.size());
using std::swap;
swap(node_array, nodes);