add comparison tool for graph classes
This commit is contained in:
parent
f2cdb97867
commit
c03aec364c
@ -332,6 +332,8 @@ if(WITH_TOOLS OR BUILD_TOOLS)
|
||||
target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES})
|
||||
add_executable(osrm-springclean tools/springclean.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:GITDESCRIPTION> $<TARGET_OBJECTS:EXCEPTION>)
|
||||
target_link_libraries(osrm-springclean ${Boost_LIBRARIES})
|
||||
add_executable(osrm-graph-compare tools/graph_compare.cpp $<TARGET_OBJECTS:FINGERPRINT> $<TARGET_OBJECTS:IMPORT> $<TARGET_OBJECTS:COORDINATE> $<TARGET_OBJECTS:LOGGER> $<TARGET_OBJECTS:RESTRICTION> $<TARGET_OBJECTS:EXCEPTION> $<TARGET_OBJECTS:MERCATOR>)
|
||||
target_link_libraries(osrm-graph-compare ${Boost_LIBRARIES} ${TBB_LIBRARIES})
|
||||
|
||||
install(TARGETS osrm-cli DESTINATION bin)
|
||||
install(TARGETS osrm-io-benchmark DESTINATION bin)
|
||||
|
@ -76,8 +76,8 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
// Constructs an empty graph with a given number of nodes.
|
||||
explicit DynamicGraph(NodeIterator nodes) : number_of_nodes(nodes), number_of_edges(0)
|
||||
{
|
||||
node_list.reserve(number_of_nodes);
|
||||
node_list.resize(number_of_nodes);
|
||||
node_array.reserve(number_of_nodes);
|
||||
node_array.resize(number_of_nodes);
|
||||
|
||||
edge_list.reserve(number_of_nodes * 1.1);
|
||||
edge_list.resize(number_of_nodes);
|
||||
@ -87,29 +87,29 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
{
|
||||
number_of_nodes = nodes;
|
||||
number_of_edges = static_cast<EdgeIterator>(graph.size());
|
||||
node_list.reserve(number_of_nodes + 1);
|
||||
node_list.resize(number_of_nodes + 1);
|
||||
// node_array.reserve(number_of_nodes + 1);
|
||||
node_array.resize(number_of_nodes + 1);
|
||||
EdgeIterator edge = 0;
|
||||
EdgeIterator position = 0;
|
||||
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||
{
|
||||
EdgeIterator lastEdge = edge;
|
||||
EdgeIterator last_edge = edge;
|
||||
while (edge < number_of_edges && graph[edge].source == node)
|
||||
{
|
||||
++edge;
|
||||
}
|
||||
node_list[node].firstEdge = position;
|
||||
node_list[node].edges = edge - lastEdge;
|
||||
position += node_list[node].edges;
|
||||
node_array[node].first_edge = position;
|
||||
node_array[node].edges = edge - last_edge;
|
||||
position += node_array[node].edges;
|
||||
}
|
||||
node_list.back().firstEdge = position;
|
||||
node_array.back().first_edge = position;
|
||||
edge_list.reserve(static_cast<std::size_t>(edge_list.size() * 1.1));
|
||||
edge_list.resize(position);
|
||||
edge = 0;
|
||||
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||
{
|
||||
for (const auto i : osrm::irange(node_list[node].firstEdge,
|
||||
node_list[node].firstEdge + node_list[node].edges))
|
||||
for (const auto i : osrm::irange(node_array[node].first_edge,
|
||||
node_array[node].first_edge + node_array[node].edges))
|
||||
{
|
||||
edge_list[i].target = graph[edge].target;
|
||||
edge_list[i].data = graph[edge].data;
|
||||
@ -124,7 +124,7 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
|
||||
unsigned GetNumberOfEdges() const { return number_of_edges; }
|
||||
|
||||
unsigned GetOutDegree(const NodeIterator n) const { return node_list[n].edges; }
|
||||
unsigned GetOutDegree(const NodeIterator n) const { return node_array[n].edges; }
|
||||
|
||||
unsigned GetDirectedOutDegree(const NodeIterator n) const
|
||||
{
|
||||
@ -149,12 +149,12 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
|
||||
EdgeIterator BeginEdges(const NodeIterator n) const
|
||||
{
|
||||
return EdgeIterator(node_list[n].firstEdge);
|
||||
return EdgeIterator(node_array[n].first_edge);
|
||||
}
|
||||
|
||||
EdgeIterator EndEdges(const NodeIterator n) const
|
||||
{
|
||||
return EdgeIterator(node_list[n].firstEdge + node_list[n].edges);
|
||||
return EdgeIterator(node_array[n].first_edge + node_array[n].edges);
|
||||
}
|
||||
|
||||
EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
|
||||
@ -164,7 +164,7 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
|
||||
NodeIterator InsertNode()
|
||||
{
|
||||
node_list.emplace_back(node_list.back());
|
||||
node_array.emplace_back(node_array.back());
|
||||
number_of_nodes += 1;
|
||||
|
||||
return number_of_nodes;
|
||||
@ -173,14 +173,14 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
// adds an edge. Invalidates edge iterators for the source node
|
||||
EdgeIterator InsertEdge(const NodeIterator from, const NodeIterator to, const EdgeDataT &data)
|
||||
{
|
||||
Node &node = node_list[from];
|
||||
EdgeIterator newFirstEdge = node.edges + node.firstEdge;
|
||||
Node &node = node_array[from];
|
||||
EdgeIterator newFirstEdge = node.edges + node.first_edge;
|
||||
if (newFirstEdge >= edge_list.size() || !isDummy(newFirstEdge))
|
||||
{
|
||||
if (node.firstEdge != 0 && isDummy(node.firstEdge - 1))
|
||||
if (node.first_edge != 0 && isDummy(node.first_edge - 1))
|
||||
{
|
||||
node.firstEdge--;
|
||||
edge_list[node.firstEdge] = edge_list[node.firstEdge + node.edges];
|
||||
node.first_edge--;
|
||||
edge_list[node.first_edge] = edge_list[node.first_edge + node.edges];
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -195,32 +195,32 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
edge_list.resize(edge_list.size() + newSize);
|
||||
for (const auto i : osrm::irange(0u, node.edges))
|
||||
{
|
||||
edge_list[newFirstEdge + i] = edge_list[node.firstEdge + i];
|
||||
makeDummy(node.firstEdge + i);
|
||||
edge_list[newFirstEdge + i] = edge_list[node.first_edge + i];
|
||||
makeDummy(node.first_edge + i);
|
||||
}
|
||||
for (const auto i : osrm::irange(node.edges + 1, newSize))
|
||||
{
|
||||
makeDummy(newFirstEdge + i);
|
||||
}
|
||||
node.firstEdge = newFirstEdge;
|
||||
node.first_edge = newFirstEdge;
|
||||
}
|
||||
}
|
||||
Edge &edge = edge_list[node.firstEdge + node.edges];
|
||||
Edge &edge = edge_list[node.first_edge + node.edges];
|
||||
edge.target = to;
|
||||
edge.data = data;
|
||||
++number_of_edges;
|
||||
++node.edges;
|
||||
return EdgeIterator(node.firstEdge + node.edges);
|
||||
return EdgeIterator(node.first_edge + node.edges);
|
||||
}
|
||||
|
||||
// removes an edge. Invalidates edge iterators for the source node
|
||||
void DeleteEdge(const NodeIterator source, const EdgeIterator e)
|
||||
{
|
||||
Node &node = node_list[source];
|
||||
Node &node = node_array[source];
|
||||
--number_of_edges;
|
||||
--node.edges;
|
||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != node.edges);
|
||||
const unsigned last = node.firstEdge + node.edges;
|
||||
const unsigned last = node.first_edge + node.edges;
|
||||
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != last);
|
||||
// swap with last edge
|
||||
edge_list[e] = edge_list[last];
|
||||
@ -245,7 +245,7 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
}
|
||||
|
||||
number_of_edges -= deleted;
|
||||
node_list[source].edges -= deleted;
|
||||
node_array[source].edges -= deleted;
|
||||
|
||||
return deleted;
|
||||
}
|
||||
@ -277,7 +277,7 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
struct Node
|
||||
{
|
||||
// index of the first edge
|
||||
EdgeIterator firstEdge;
|
||||
EdgeIterator first_edge;
|
||||
// amount of edges
|
||||
unsigned edges;
|
||||
};
|
||||
@ -291,7 +291,7 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
NodeIterator number_of_nodes;
|
||||
std::atomic_uint number_of_edges;
|
||||
|
||||
std::vector<Node> node_list;
|
||||
std::vector<Node> node_array;
|
||||
DeallocatingVector<Edge> edge_list;
|
||||
};
|
||||
|
||||
|
@ -91,7 +91,6 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
|
||||
StaticGraph(const int nodes, std::vector<InputEdge> &graph)
|
||||
{
|
||||
tbb::parallel_sort(graph.begin(), graph.end());
|
||||
number_of_nodes = nodes;
|
||||
number_of_edges = static_cast<EdgeIterator>(graph.size());
|
||||
node_array.resize(number_of_nodes + 1);
|
||||
@ -112,11 +111,10 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
for (const auto node : osrm::irange(0u, number_of_nodes))
|
||||
{
|
||||
EdgeIterator e = node_array[node + 1].first_edge;
|
||||
for (EdgeIterator i = node_array[node].first_edge; i != e; ++i)
|
||||
for (const auto i : osrm::irange(node_array[node].first_edge, e))
|
||||
{
|
||||
edge_array[i].target = graph[edge].target;
|
||||
edge_array[i].data = graph[edge].data;
|
||||
BOOST_ASSERT(edge_array[i].data.distance > 0);
|
||||
edge++;
|
||||
}
|
||||
}
|
||||
@ -143,7 +141,7 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
return NodeIterator(edge_array[e].target);
|
||||
}
|
||||
|
||||
inline EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; }
|
||||
EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; }
|
||||
|
||||
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_array[e].data; }
|
||||
|
||||
|
199
tools/graph_compare.cpp
Normal file
199
tools/graph_compare.cpp
Normal file
@ -0,0 +1,199 @@
|
||||
#include "../data_structures/dynamic_graph.hpp"
|
||||
#include "../data_structures/import_edge.hpp"
|
||||
#include "../data_structures/query_node.hpp"
|
||||
#include "../data_structures/restriction.hpp"
|
||||
#include "../data_structures/static_graph.hpp"
|
||||
#include "../util/fingerprint.hpp"
|
||||
#include "../util/graph_loader.hpp"
|
||||
#include "../util/integer_range.hpp"
|
||||
#include "../util/make_unique.hpp"
|
||||
#include "../util/osrm_exception.hpp"
|
||||
#include "../util/simple_logger.hpp"
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
struct TarjanEdgeData
|
||||
{
|
||||
TarjanEdgeData() : distance(INVALID_EDGE_WEIGHT), name_id(INVALID_NAMEID) {}
|
||||
TarjanEdgeData(unsigned distance, unsigned name_id) : distance(distance), name_id(name_id) {}
|
||||
unsigned distance;
|
||||
unsigned name_id;
|
||||
};
|
||||
|
||||
using StaticTestGraph = StaticGraph<TarjanEdgeData>;
|
||||
using DynamicTestGraph = StaticGraph<TarjanEdgeData>;
|
||||
using StaticEdge = StaticTestGraph::InputEdge;
|
||||
using DynamicEdge = DynamicTestGraph::InputEdge;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
std::vector<QueryNode> coordinate_list;
|
||||
std::vector<TurnRestriction> restriction_list;
|
||||
std::vector<NodeID> bollard_node_list;
|
||||
std::vector<NodeID> traffic_lights_list;
|
||||
|
||||
LogPolicy::GetInstance().Unmute();
|
||||
try
|
||||
{
|
||||
// enable logging
|
||||
if (argc < 3)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0]
|
||||
<< " <osrm> <osrm.restrictions>";
|
||||
return -1;
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << "Using restrictions from file: " << argv[2];
|
||||
std::ifstream restriction_ifstream(argv[2], std::ios::binary);
|
||||
const FingerPrint fingerprint_orig;
|
||||
FingerPrint fingerprint_loaded;
|
||||
restriction_ifstream.read(reinterpret_cast<char *>(&fingerprint_loaded),
|
||||
sizeof(FingerPrint));
|
||||
|
||||
// check fingerprint and warn if necessary
|
||||
if (!fingerprint_loaded.TestGraphUtil(fingerprint_orig))
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << argv[2] << " was prepared with a different build. "
|
||||
"Reprocess to get rid of this warning.";
|
||||
}
|
||||
|
||||
if (!restriction_ifstream.good())
|
||||
{
|
||||
throw osrm::exception("Could not access <osrm-restrictions> files");
|
||||
}
|
||||
uint32_t usable_restrictions = 0;
|
||||
restriction_ifstream.read(reinterpret_cast<char *>(&usable_restrictions), sizeof(uint32_t));
|
||||
restriction_list.resize(usable_restrictions);
|
||||
|
||||
// load restrictions
|
||||
if (usable_restrictions > 0)
|
||||
{
|
||||
restriction_ifstream.read(reinterpret_cast<char *>(&restriction_list[0]),
|
||||
usable_restrictions * sizeof(TurnRestriction));
|
||||
}
|
||||
restriction_ifstream.close();
|
||||
|
||||
std::ifstream input_stream(argv[1], std::ifstream::in | std::ifstream::binary);
|
||||
if (!input_stream.is_open())
|
||||
{
|
||||
throw osrm::exception("Cannot open osrm file");
|
||||
}
|
||||
|
||||
// load graph data
|
||||
std::vector<ImportEdge> edge_list;
|
||||
const NodeID number_of_nodes =
|
||||
readBinaryOSRMGraphFromStream(input_stream, edge_list, bollard_node_list,
|
||||
traffic_lights_list, &coordinate_list, restriction_list);
|
||||
input_stream.close();
|
||||
|
||||
BOOST_ASSERT_MSG(restriction_list.size() == usable_restrictions,
|
||||
"size of restriction_list changed");
|
||||
|
||||
SimpleLogger().Write() << restriction_list.size() << " restrictions, "
|
||||
<< bollard_node_list.size() << " bollard nodes, "
|
||||
<< traffic_lights_list.size() << " traffic lights";
|
||||
|
||||
traffic_lights_list.clear();
|
||||
traffic_lights_list.shrink_to_fit();
|
||||
|
||||
// Building an node-based graph
|
||||
std::vector<StaticEdge> static_graph_edge_list;
|
||||
std::vector<DynamicEdge> dynamic_graph_edge_list;
|
||||
for (const auto &input_edge : edge_list)
|
||||
{
|
||||
if (input_edge.source == input_edge.target)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (input_edge.forward)
|
||||
{
|
||||
static_graph_edge_list.emplace_back(input_edge.source, input_edge.target,
|
||||
(std::max)(input_edge.weight, 1),
|
||||
input_edge.name_id);
|
||||
dynamic_graph_edge_list.emplace_back(input_edge.source, input_edge.target,
|
||||
(std::max)(input_edge.weight, 1),
|
||||
input_edge.name_id);
|
||||
}
|
||||
if (input_edge.backward)
|
||||
{
|
||||
dynamic_graph_edge_list.emplace_back(input_edge.target, input_edge.source,
|
||||
(std::max)(input_edge.weight, 1),
|
||||
input_edge.name_id);
|
||||
static_graph_edge_list.emplace_back(input_edge.target, input_edge.source,
|
||||
(std::max)(input_edge.weight, 1),
|
||||
input_edge.name_id);
|
||||
}
|
||||
}
|
||||
edge_list.clear();
|
||||
edge_list.shrink_to_fit();
|
||||
BOOST_ASSERT_MSG(0 == edge_list.size() && 0 == edge_list.capacity(),
|
||||
"input edge vector not properly deallocated");
|
||||
|
||||
tbb::parallel_sort(static_graph_edge_list.begin(), static_graph_edge_list.end());
|
||||
tbb::parallel_sort(dynamic_graph_edge_list.begin(), dynamic_graph_edge_list.end());
|
||||
|
||||
auto static_graph =
|
||||
osrm::make_unique<StaticTestGraph>(number_of_nodes, static_graph_edge_list);
|
||||
auto dynamic_graph =
|
||||
osrm::make_unique<DynamicTestGraph>(number_of_nodes, dynamic_graph_edge_list);
|
||||
|
||||
SimpleLogger().Write() << "Starting static/dynamic graph comparison";
|
||||
|
||||
BOOST_ASSERT(static_graph->GetNumberOfNodes() == dynamic_graph->GetNumberOfNodes());
|
||||
BOOST_ASSERT(static_graph->GetNumberOfEdges() == dynamic_graph->GetNumberOfEdges());
|
||||
for (const auto node : osrm::irange(0u, static_graph->GetNumberOfNodes()))
|
||||
{
|
||||
const auto static_range = static_graph->GetAdjacentEdgeRange(node);
|
||||
const auto dynamic_range = dynamic_graph->GetAdjacentEdgeRange(node);
|
||||
SimpleLogger().Write() << "checking node " << node << "/"
|
||||
<< static_graph->GetNumberOfNodes();
|
||||
|
||||
BOOST_ASSERT(static_range.size() == dynamic_range.size());
|
||||
const auto static_begin = static_graph->BeginEdges(node);
|
||||
const auto dynamic_begin = dynamic_graph->BeginEdges(node);
|
||||
|
||||
// check raw interface
|
||||
for (int i = 0; i < static_range.size(); ++i)
|
||||
{
|
||||
const auto static_target = static_graph->GetTarget(static_begin + i);
|
||||
const auto dynamic_target = dynamic_graph->GetTarget(dynamic_begin + i);
|
||||
BOOST_ASSERT(static_target == dynamic_target);
|
||||
|
||||
const auto static_data = static_graph->GetEdgeData(static_begin + i);
|
||||
const auto dynamic_data = dynamic_graph->GetEdgeData(dynamic_begin + i);
|
||||
|
||||
BOOST_ASSERT(static_data.distance == dynamic_data.distance);
|
||||
BOOST_ASSERT(static_data.name_id == dynamic_data.name_id);
|
||||
}
|
||||
|
||||
// check range interface
|
||||
std::vector<EdgeID> static_target_ids, dynamic_target_ids;
|
||||
std::vector<TarjanEdgeData> static_edge_data, dynamic_edge_data;
|
||||
for (const auto static_id : static_range)
|
||||
{
|
||||
static_target_ids.push_back(static_graph->GetTarget(static_id));
|
||||
static_edge_data.push_back(static_graph->GetEdgeData(static_id));
|
||||
}
|
||||
for (const auto dynamic_id : dynamic_range)
|
||||
{
|
||||
dynamic_target_ids.push_back(dynamic_graph->GetTarget(dynamic_id));
|
||||
dynamic_edge_data.push_back(dynamic_graph->GetEdgeData(dynamic_id));
|
||||
}
|
||||
BOOST_ASSERT(static_target_ids.size() == dynamic_target_ids.size());
|
||||
BOOST_ASSERT(std::equal(std::begin(static_target_ids), std::end(static_target_ids),
|
||||
std::begin(dynamic_target_ids)));
|
||||
}
|
||||
|
||||
SimpleLogger().Write() << "Graph comparison finished successfully";
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << "[exception] " << e.what();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user