From fd30e82836862d25775fc95b35db387e5b4fb465 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Sun, 28 Jun 2015 15:30:40 +0200 Subject: [PATCH] Add graph compressor unit tests --- CMakeLists.txt | 4 +- .../graph_compressor.cpp | 0 .../graph_compressor.hpp | 2 +- contractor/edge_based_graph_factory.cpp | 1 - contractor/edge_based_graph_factory.hpp | 2 - contractor/processing_chain.cpp | 2 +- data_structures/dynamic_graph.hpp | 4 +- data_structures/node_based_graph.hpp | 10 + unit_tests/algorithms/graph_compressor.cpp | 232 ++++++++++++++++++ 9 files changed, 249 insertions(+), 8 deletions(-) rename {contractor => algorithms}/graph_compressor.cpp (100%) rename {contractor => algorithms}/graph_compressor.hpp (98%) create mode 100644 unit_tests/algorithms/graph_compressor.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b1f627297..788d35470 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,7 @@ add_executable(osrm-extract ${ExtractorSources} $ $ $ $ $ $ $ $ $ $) @@ -77,7 +77,7 @@ file(GLOB AlgorithmGlob algorithms/*.cpp) file(GLOB HttpGlob server/http/*.cpp) file(GLOB LibOSRMGlob library/*.cpp) file(GLOB DataStructureTestsGlob unit_tests/data_structures/*.cpp data_structures/hilbert_value.cpp data_structures/compressed_edge_container.cpp) -file(GLOB AlgorithmTestsGlob unit_tests/algorithms/*.cpp) +file(GLOB AlgorithmTestsGlob unit_tests/algorithms/*.cpp algorithms/graph_compressor.cpp data_structures/compressed_edge_container.cpp data_structures/restriction_map.cpp) set( OSRMSources diff --git a/contractor/graph_compressor.cpp b/algorithms/graph_compressor.cpp similarity index 100% rename from contractor/graph_compressor.cpp rename to algorithms/graph_compressor.cpp diff --git a/contractor/graph_compressor.hpp b/algorithms/graph_compressor.hpp similarity index 98% rename from contractor/graph_compressor.hpp rename to algorithms/graph_compressor.hpp index 0e349423c..c1cca153e 100644 --- a/contractor/graph_compressor.hpp +++ b/algorithms/graph_compressor.hpp @@ -29,7 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" -#include "speed_profile.hpp" +#include "../contractor/speed_profile.hpp" #include "../data_structures/node_based_graph.hpp" #include diff --git a/contractor/edge_based_graph_factory.cpp b/contractor/edge_based_graph_factory.cpp index c5c31ac5b..110311df6 100644 --- a/contractor/edge_based_graph_factory.cpp +++ b/contractor/edge_based_graph_factory.cpp @@ -266,7 +266,6 @@ void EdgeBasedGraphFactory::RenumberEdges() BOOST_ASSERT(SPECIAL_NODEID != edge_data.edgeBasedNodeID); } } - m_number_of_edge_based_nodes = numbered_edges_count; } /// Creates the nodes in the edge expanded graph from edges in the node-based graph. diff --git a/contractor/edge_based_graph_factory.hpp b/contractor/edge_based_graph_factory.hpp index 20a3feda4..e4829737c 100644 --- a/contractor/edge_based_graph_factory.hpp +++ b/contractor/edge_based_graph_factory.hpp @@ -81,8 +81,6 @@ class EdgeBasedGraphFactory private: using EdgeData = NodeBasedDynamicGraph::EdgeData; - unsigned m_number_of_edge_based_nodes; - std::vector m_edge_based_node_list; DeallocatingVector m_edge_based_edge_list; diff --git a/contractor/processing_chain.cpp b/contractor/processing_chain.cpp index 4a6a12c5b..461d38afe 100644 --- a/contractor/processing_chain.cpp +++ b/contractor/processing_chain.cpp @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "processing_chain.hpp" #include "contractor.hpp" -#include "graph_compressor.hpp" +#include "../algorithms/graph_compressor.hpp" #include "../algorithms/crc32_processor.hpp" #include "../data_structures/compressed_edge_container.hpp" diff --git a/data_structures/dynamic_graph.hpp b/data_structures/dynamic_graph.hpp index b18204c61..f96eb1992 100644 --- a/data_structures/dynamic_graph.hpp +++ b/data_structures/dynamic_graph.hpp @@ -90,9 +90,11 @@ template class DynamicGraph */ template DynamicGraph(const NodeIterator nodes, const ContainerT &graph) { + // we need to cast here because DeallocatingVector does not have a valid const iterator + BOOST_ASSERT(std::is_sorted(const_cast(graph).begin(), const_cast(graph).end())); + number_of_nodes = nodes; number_of_edges = static_cast(graph.size()); - // node_array.reserve(number_of_nodes + 1); node_array.resize(number_of_nodes + 1); EdgeIterator edge = 0; EdgeIterator position = 0; diff --git a/data_structures/node_based_graph.hpp b/data_structures/node_based_graph.hpp index b69053a97..c44f92b53 100644 --- a/data_structures/node_based_graph.hpp +++ b/data_structures/node_based_graph.hpp @@ -46,6 +46,16 @@ struct NodeBasedEdgeData { } + NodeBasedEdgeData(int distance, unsigned edgeBasedNodeID, unsigned nameID, + bool isAccessRestricted, bool shortcut, bool forward, bool backward, + bool roundabout, bool ignore_in_grid, TravelMode travel_mode) + : distance(distance), edgeBasedNodeID(edgeBasedNodeID), + nameID(nameID), isAccessRestricted(isAccessRestricted), shortcut(shortcut), + forward(forward), backward(backward), roundabout(roundabout), ignore_in_grid(ignore_in_grid), + travel_mode(travel_mode) + { + } + int distance; unsigned edgeBasedNodeID; unsigned nameID; diff --git a/unit_tests/algorithms/graph_compressor.cpp b/unit_tests/algorithms/graph_compressor.cpp new file mode 100644 index 000000000..0b09752a6 --- /dev/null +++ b/unit_tests/algorithms/graph_compressor.cpp @@ -0,0 +1,232 @@ +#include "../../algorithms/graph_compressor.hpp" +#include "../../data_structures/compressed_edge_container.hpp" +#include "../../data_structures/restriction_map.hpp" +#include "../../data_structures/node_based_graph.hpp" +#include "../../contractor/speed_profile.hpp" +#include "../../typedefs.h" + +#include +#include + +#include + +BOOST_AUTO_TEST_SUITE(graph_compressor) + +void dumpGraph(const NodeBasedDynamicGraph& graph) +{ + for (auto i = 0u; i < graph.GetNumberOfNodes(); ++i) + { + std::cout << "## node " << i << " degree: " << graph.GetOutDegree(i) << std::endl; + for (auto e = graph.BeginEdges(i); e < graph.EndEdges(i); ++e) + { + const auto& data = graph.GetEdgeData(e); + auto target = graph.GetTarget(e); + if (data.forward && !data.backward) + std::cout << i << "->" << target << std::endl; + if (!data.forward && data.backward) + std::cout << i << "<-" << target << std::endl; + if (data.forward && data.backward) + std::cout << i << "--" << target << std::endl; + } + } +} + +BOOST_AUTO_TEST_CASE(long_road_test) +{ + // + // 0---1---2---3---4 + // + SpeedProfileProperties speed_profile; + GraphCompressor compressor(speed_profile); + + std::unordered_set barrier_nodes; + std::unordered_set traffic_lights; + RestrictionMap map; + CompressedEdgeContainer container; + + using InputEdge = NodeBasedDynamicGraph::InputEdge; + std::vector edges = { + // source, target, distance, edgeBasedNodeID, nameID, isAccessRestricted, shortcut, forward, backward, roundabout, ignore_in_grid, travel_mode + {0, 1, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {1, 0, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {1, 2, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {2, 1, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {2, 3, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {3, 2, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {3, 4, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {4, 3, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT} + }; + + BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[2].data)); + BOOST_ASSERT(edges[2].data.IsCompatibleTo(edges[4].data)); + BOOST_ASSERT(edges[4].data.IsCompatibleTo(edges[6].data)); + + NodeBasedDynamicGraph graph(5, edges); + compressor.Compress(barrier_nodes, traffic_lights, map, graph, container); + + BOOST_CHECK_EQUAL(graph.FindEdge(0, 1), SPECIAL_EDGEID); + BOOST_CHECK_EQUAL(graph.FindEdge(1, 2), SPECIAL_EDGEID); + BOOST_CHECK_EQUAL(graph.FindEdge(2, 3), SPECIAL_EDGEID); + BOOST_CHECK_EQUAL(graph.FindEdge(3, 4), SPECIAL_EDGEID); + BOOST_CHECK(graph.FindEdge(0, 4) != SPECIAL_EDGEID); +} + +BOOST_AUTO_TEST_CASE(loop_test) +{ + // + // 0---1---2 + // | | + // 5---4---3 + // + SpeedProfileProperties speed_profile; + GraphCompressor compressor(speed_profile); + + std::unordered_set barrier_nodes; + std::unordered_set traffic_lights; + RestrictionMap map; + CompressedEdgeContainer container; + + using InputEdge = NodeBasedDynamicGraph::InputEdge; + std::vector edges = { + // source, target, distance, edgeBasedNodeID, nameID, isAccessRestricted, shortcut, forward, backward, roundabout, ignore_in_grid, travel_mode + {0, 1, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {0, 5, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {1, 0, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {1, 2, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {2, 1, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {2, 3, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {3, 2, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {3, 4, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {4, 3, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {4, 5, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {5, 0, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {5, 4, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + }; + + BOOST_ASSERT(edges.size() == 12); + BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[1].data)); + BOOST_ASSERT(edges[1].data.IsCompatibleTo(edges[2].data)); + BOOST_ASSERT(edges[2].data.IsCompatibleTo(edges[3].data)); + BOOST_ASSERT(edges[3].data.IsCompatibleTo(edges[4].data)); + BOOST_ASSERT(edges[4].data.IsCompatibleTo(edges[5].data)); + BOOST_ASSERT(edges[5].data.IsCompatibleTo(edges[6].data)); + BOOST_ASSERT(edges[6].data.IsCompatibleTo(edges[7].data)); + BOOST_ASSERT(edges[7].data.IsCompatibleTo(edges[8].data)); + BOOST_ASSERT(edges[8].data.IsCompatibleTo(edges[9].data)); + BOOST_ASSERT(edges[9].data.IsCompatibleTo(edges[10].data)); + BOOST_ASSERT(edges[10].data.IsCompatibleTo(edges[11].data)); + + NodeBasedDynamicGraph graph(6, edges); + compressor.Compress(barrier_nodes, traffic_lights, map, graph, container); + + BOOST_CHECK_EQUAL(graph.FindEdge(5, 0), SPECIAL_EDGEID); + BOOST_CHECK_EQUAL(graph.FindEdge(0, 1), SPECIAL_EDGEID); + BOOST_CHECK_EQUAL(graph.FindEdge(1, 2), SPECIAL_EDGEID); + BOOST_CHECK_EQUAL(graph.FindEdge(2, 3), SPECIAL_EDGEID); + BOOST_CHECK(graph.FindEdge(5, 3) != SPECIAL_EDGEID); + BOOST_CHECK(graph.FindEdge(3, 4) != SPECIAL_EDGEID); + BOOST_CHECK(graph.FindEdge(4, 5) != SPECIAL_EDGEID); +} + +BOOST_AUTO_TEST_CASE(t_intersection) +{ + // + // 0---1---2 + // | + // 3 + // + SpeedProfileProperties speed_profile; + GraphCompressor compressor(speed_profile); + + std::unordered_set barrier_nodes; + std::unordered_set traffic_lights; + RestrictionMap map; + CompressedEdgeContainer container; + + using InputEdge = NodeBasedDynamicGraph::InputEdge; + std::vector edges = { + // source, target, distance, edgeBasedNodeID, nameID, isAccessRestricted, shortcut, forward, backward, roundabout, ignore_in_grid, travel_mode + {0, 1, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {1, 0, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {1, 2, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {1, 3, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {2, 1, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {3, 1, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + }; + + BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[1].data)); + BOOST_ASSERT(edges[1].data.IsCompatibleTo(edges[2].data)); + BOOST_ASSERT(edges[2].data.IsCompatibleTo(edges[3].data)); + BOOST_ASSERT(edges[3].data.IsCompatibleTo(edges[4].data)); + BOOST_ASSERT(edges[4].data.IsCompatibleTo(edges[5].data)); + + NodeBasedDynamicGraph graph(4, edges); + compressor.Compress(barrier_nodes, traffic_lights, map, graph, container); + + BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID); + BOOST_CHECK(graph.FindEdge(1, 2) != SPECIAL_EDGEID); + BOOST_CHECK(graph.FindEdge(1, 3) != SPECIAL_EDGEID); +} + +BOOST_AUTO_TEST_CASE(street_name_changes) +{ + // + // 0---1---2 + // + SpeedProfileProperties speed_profile; + GraphCompressor compressor(speed_profile); + + std::unordered_set barrier_nodes; + std::unordered_set traffic_lights; + RestrictionMap map; + CompressedEdgeContainer container; + + using InputEdge = NodeBasedDynamicGraph::InputEdge; + std::vector edges = { + // source, target, distance, edgeBasedNodeID, nameID, isAccessRestricted, shortcut, forward, backward, roundabout, ignore_in_grid, travel_mode + {0, 1, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {1, 0, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {1, 2, 1, SPECIAL_EDGEID, 1, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {2, 1, 1, SPECIAL_EDGEID, 1, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + }; + + BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[1].data)); + BOOST_ASSERT(edges[2].data.IsCompatibleTo(edges[3].data)); + + NodeBasedDynamicGraph graph(5, edges); + compressor.Compress(barrier_nodes, traffic_lights, map, graph, container); + + BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID); + BOOST_CHECK(graph.FindEdge(1, 2) != SPECIAL_EDGEID); +} + +BOOST_AUTO_TEST_CASE(direction_changes) +{ + // + // 0-->1---2 + // + SpeedProfileProperties speed_profile; + GraphCompressor compressor(speed_profile); + + std::unordered_set barrier_nodes; + std::unordered_set traffic_lights; + RestrictionMap map; + CompressedEdgeContainer container; + + using InputEdge = NodeBasedDynamicGraph::InputEdge; + std::vector edges = { + // source, target, distance, edgeBasedNodeID, nameID, isAccessRestricted, shortcut, forward, backward, roundabout, ignore_in_grid, travel_mode + {0, 1, 1, SPECIAL_EDGEID, 0, false, false, true, false, false, false, TRAVEL_MODE_DEFAULT}, + {1, 0, 1, SPECIAL_EDGEID, 0, false, false, false, true, false, false, TRAVEL_MODE_DEFAULT}, + {1, 2, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + {2, 1, 1, SPECIAL_EDGEID, 0, false, false, true, true, false, false, TRAVEL_MODE_DEFAULT}, + }; + + NodeBasedDynamicGraph graph(5, edges); + compressor.Compress(barrier_nodes, traffic_lights, map, graph, container); + + BOOST_CHECK(graph.FindEdge(0, 1) != SPECIAL_EDGEID); + BOOST_CHECK(graph.FindEdge(1, 2) != SPECIAL_EDGEID); +} + +BOOST_AUTO_TEST_SUITE_END()