add comparison tool for graph classes

This commit is contained in:
Dennis Luxen 2015-04-16 11:25:43 +02:00
parent f2cdb97867
commit c03aec364c
4 changed files with 233 additions and 34 deletions

View File

@ -332,6 +332,8 @@ if(WITH_TOOLS OR BUILD_TOOLS)
target_link_libraries(osrm-check-hsgr ${Boost_LIBRARIES}) 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>) 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}) 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-cli DESTINATION bin)
install(TARGETS osrm-io-benchmark DESTINATION bin) install(TARGETS osrm-io-benchmark DESTINATION bin)

View File

@ -76,8 +76,8 @@ template <typename EdgeDataT> class DynamicGraph
// Constructs an empty graph with a given number of nodes. // Constructs an empty graph with a given number of nodes.
explicit DynamicGraph(NodeIterator nodes) : number_of_nodes(nodes), number_of_edges(0) explicit DynamicGraph(NodeIterator nodes) : number_of_nodes(nodes), number_of_edges(0)
{ {
node_list.reserve(number_of_nodes); node_array.reserve(number_of_nodes);
node_list.resize(number_of_nodes); node_array.resize(number_of_nodes);
edge_list.reserve(number_of_nodes * 1.1); edge_list.reserve(number_of_nodes * 1.1);
edge_list.resize(number_of_nodes); edge_list.resize(number_of_nodes);
@ -87,29 +87,29 @@ template <typename EdgeDataT> class DynamicGraph
{ {
number_of_nodes = nodes; number_of_nodes = nodes;
number_of_edges = static_cast<EdgeIterator>(graph.size()); number_of_edges = static_cast<EdgeIterator>(graph.size());
node_list.reserve(number_of_nodes + 1); // node_array.reserve(number_of_nodes + 1);
node_list.resize(number_of_nodes + 1); node_array.resize(number_of_nodes + 1);
EdgeIterator edge = 0; EdgeIterator edge = 0;
EdgeIterator position = 0; EdgeIterator position = 0;
for (const auto node : osrm::irange(0u, number_of_nodes)) 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) while (edge < number_of_edges && graph[edge].source == node)
{ {
++edge; ++edge;
} }
node_list[node].firstEdge = position; node_array[node].first_edge = position;
node_list[node].edges = edge - lastEdge; node_array[node].edges = edge - last_edge;
position += node_list[node].edges; 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.reserve(static_cast<std::size_t>(edge_list.size() * 1.1));
edge_list.resize(position); edge_list.resize(position);
edge = 0; edge = 0;
for (const auto node : osrm::irange(0u, number_of_nodes)) for (const auto node : osrm::irange(0u, number_of_nodes))
{ {
for (const auto i : osrm::irange(node_list[node].firstEdge, for (const auto i : osrm::irange(node_array[node].first_edge,
node_list[node].firstEdge + node_list[node].edges)) node_array[node].first_edge + node_array[node].edges))
{ {
edge_list[i].target = graph[edge].target; edge_list[i].target = graph[edge].target;
edge_list[i].data = graph[edge].data; edge_list[i].data = graph[edge].data;
@ -124,7 +124,7 @@ template <typename EdgeDataT> class DynamicGraph
unsigned GetNumberOfEdges() const { return number_of_edges; } 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 unsigned GetDirectedOutDegree(const NodeIterator n) const
{ {
@ -149,12 +149,12 @@ template <typename EdgeDataT> class DynamicGraph
EdgeIterator BeginEdges(const NodeIterator n) const 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 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 EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
@ -164,7 +164,7 @@ template <typename EdgeDataT> class DynamicGraph
NodeIterator InsertNode() NodeIterator InsertNode()
{ {
node_list.emplace_back(node_list.back()); node_array.emplace_back(node_array.back());
number_of_nodes += 1; number_of_nodes += 1;
return number_of_nodes; return number_of_nodes;
@ -173,14 +173,14 @@ template <typename EdgeDataT> class DynamicGraph
// adds an edge. Invalidates edge iterators for the source node // adds an edge. Invalidates edge iterators for the source node
EdgeIterator InsertEdge(const NodeIterator from, const NodeIterator to, const EdgeDataT &data) EdgeIterator InsertEdge(const NodeIterator from, const NodeIterator to, const EdgeDataT &data)
{ {
Node &node = node_list[from]; Node &node = node_array[from];
EdgeIterator newFirstEdge = node.edges + node.firstEdge; EdgeIterator newFirstEdge = node.edges + node.first_edge;
if (newFirstEdge >= edge_list.size() || !isDummy(newFirstEdge)) 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--; node.first_edge--;
edge_list[node.firstEdge] = edge_list[node.firstEdge + node.edges]; edge_list[node.first_edge] = edge_list[node.first_edge + node.edges];
} }
else else
{ {
@ -195,32 +195,32 @@ template <typename EdgeDataT> class DynamicGraph
edge_list.resize(edge_list.size() + newSize); edge_list.resize(edge_list.size() + newSize);
for (const auto i : osrm::irange(0u, node.edges)) for (const auto i : osrm::irange(0u, node.edges))
{ {
edge_list[newFirstEdge + i] = edge_list[node.firstEdge + i]; edge_list[newFirstEdge + i] = edge_list[node.first_edge + i];
makeDummy(node.firstEdge + i); makeDummy(node.first_edge + i);
} }
for (const auto i : osrm::irange(node.edges + 1, newSize)) for (const auto i : osrm::irange(node.edges + 1, newSize))
{ {
makeDummy(newFirstEdge + i); 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.target = to;
edge.data = data; edge.data = data;
++number_of_edges; ++number_of_edges;
++node.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 // removes an edge. Invalidates edge iterators for the source node
void DeleteEdge(const NodeIterator source, const EdgeIterator e) void DeleteEdge(const NodeIterator source, const EdgeIterator e)
{ {
Node &node = node_list[source]; Node &node = node_array[source];
--number_of_edges; --number_of_edges;
--node.edges; --node.edges;
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != 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); BOOST_ASSERT(std::numeric_limits<unsigned>::max() != last);
// swap with last edge // swap with last edge
edge_list[e] = edge_list[last]; edge_list[e] = edge_list[last];
@ -245,7 +245,7 @@ template <typename EdgeDataT> class DynamicGraph
} }
number_of_edges -= deleted; number_of_edges -= deleted;
node_list[source].edges -= deleted; node_array[source].edges -= deleted;
return deleted; return deleted;
} }
@ -277,7 +277,7 @@ template <typename EdgeDataT> class DynamicGraph
struct Node struct Node
{ {
// index of the first edge // index of the first edge
EdgeIterator firstEdge; EdgeIterator first_edge;
// amount of edges // amount of edges
unsigned edges; unsigned edges;
}; };
@ -291,7 +291,7 @@ template <typename EdgeDataT> class DynamicGraph
NodeIterator number_of_nodes; NodeIterator number_of_nodes;
std::atomic_uint number_of_edges; std::atomic_uint number_of_edges;
std::vector<Node> node_list; std::vector<Node> node_array;
DeallocatingVector<Edge> edge_list; DeallocatingVector<Edge> edge_list;
}; };

View File

@ -91,7 +91,6 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
StaticGraph(const int nodes, std::vector<InputEdge> &graph) StaticGraph(const int nodes, std::vector<InputEdge> &graph)
{ {
tbb::parallel_sort(graph.begin(), graph.end());
number_of_nodes = nodes; number_of_nodes = nodes;
number_of_edges = static_cast<EdgeIterator>(graph.size()); number_of_edges = static_cast<EdgeIterator>(graph.size());
node_array.resize(number_of_nodes + 1); 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)) for (const auto node : osrm::irange(0u, number_of_nodes))
{ {
EdgeIterator e = node_array[node + 1].first_edge; 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].target = graph[edge].target;
edge_array[i].data = graph[edge].data; edge_array[i].data = graph[edge].data;
BOOST_ASSERT(edge_array[i].data.distance > 0);
edge++; edge++;
} }
} }
@ -143,7 +141,7 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
return NodeIterator(edge_array[e].target); 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; } const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_array[e].data; }

199
tools/graph_compare.cpp Normal file
View 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;
}