diff --git a/CMakeLists.txt b/CMakeLists.txt index 9770a0227..503171a59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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_link_libraries(osrm-springclean ${Boost_LIBRARIES}) + add_executable(osrm-graph-compare tools/graph_compare.cpp $ $ $ $ $ $ $) + target_link_libraries(osrm-graph-compare ${Boost_LIBRARIES} ${TBB_LIBRARIES}) install(TARGETS osrm-cli DESTINATION bin) install(TARGETS osrm-io-benchmark DESTINATION bin) diff --git a/algorithms/tiny_components.hpp b/algorithms/tiny_components.hpp index f3ca3c412..8eb61a912 100644 --- a/algorithms/tiny_components.hpp +++ b/algorithms/tiny_components.hpp @@ -95,18 +95,18 @@ template class TarjanSCC void run() { TIMER_START(SCC_RUN); + const NodeID max_node_id = m_node_based_graph->GetNumberOfNodes(); + // The following is a hack to distinguish between stuff that happens // before the recursive call and stuff that happens after std::stack recursion_stack; // true = stuff before, false = stuff after call std::stack tarjan_stack; - std::vector tarjan_node_list(m_node_based_graph->GetNumberOfNodes()); + std::vector tarjan_node_list(max_node_id); unsigned component_index = 0, size_of_current_component = 0; unsigned index = 0; - const NodeID last_node = m_node_based_graph->GetNumberOfNodes(); - std::vector processing_node_before_recursion(m_node_based_graph->GetNumberOfNodes(), - true); - for (const NodeID node : osrm::irange(0u, last_node)) + std::vector processing_node_before_recursion(max_node_id, true); + for (const NodeID node : osrm::irange(0u, max_node_id)) { if (SPECIAL_NODEID == components_index[node]) { diff --git a/contractor/edge_based_graph_factory.cpp b/contractor/edge_based_graph_factory.cpp index c4dc81a5b..268bb9f8d 100644 --- a/contractor/edge_based_graph_factory.cpp +++ b/contractor/edge_based_graph_factory.cpp @@ -93,15 +93,8 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, // find reverse edge id and const EdgeID edge_id_2 = m_node_based_graph->FindEdge(node_v, node_u); - -#ifndef NDEBUG - if (edge_id_2 == m_node_based_graph->EndEdges(node_v)) - { - SimpleLogger().Write(logWARNING) << "Did not find edge (" << node_v << "," << node_u << ")"; - } -#endif BOOST_ASSERT(edge_id_2 != SPECIAL_EDGEID); - BOOST_ASSERT(edge_id_2 < m_node_based_graph->EndEdges(node_v)); + const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(edge_id_2); if (forward_data.edgeBasedNodeID == SPECIAL_NODEID && @@ -315,7 +308,6 @@ void EdgeBasedGraphFactory::CompressGeometry() BOOST_ASSERT(node_u != node_v); const EdgeID forward_e1 = m_node_based_graph->FindEdge(node_u, node_v); - BOOST_ASSERT(m_node_based_graph->EndEdges(node_u) != forward_e1); BOOST_ASSERT(SPECIAL_EDGEID != forward_e1); BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(forward_e1)); const EdgeID reverse_e1 = m_node_based_graph->FindEdge(node_w, node_v); @@ -325,9 +317,7 @@ void EdgeBasedGraphFactory::CompressGeometry() const EdgeData &fwd_edge_data1 = m_node_based_graph->GetEdgeData(forward_e1); const EdgeData &rev_edge_data1 = m_node_based_graph->GetEdgeData(reverse_e1); - if ((m_node_based_graph->FindEdge(node_u, node_w) != - m_node_based_graph->EndEdges(node_u)) || - (m_node_based_graph->FindEdge(node_w, node_u) != m_node_based_graph->EndEdges(node_w))) + if (m_node_based_graph->FindEdgeInEitherDirection(node_u, node_w) != SPECIAL_EDGEID) { continue; } diff --git a/data_structures/dynamic_graph.hpp b/data_structures/dynamic_graph.hpp index 3a8f520c6..43e6c3aca 100644 --- a/data_structures/dynamic_graph.hpp +++ b/data_structures/dynamic_graph.hpp @@ -30,15 +30,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "deallocating_vector.hpp" #include "../util/integer_range.hpp" +#include "../typedefs.h" #include #include #include -#include -#include #include +#include +#include +#include template class DynamicGraph { @@ -76,8 +78,8 @@ template 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 +89,29 @@ template class DynamicGraph { number_of_nodes = nodes; number_of_edges = static_cast(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(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 +126,7 @@ template 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 +151,12 @@ template 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 +166,7 @@ template 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 +175,14 @@ template 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 +197,32 @@ template 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::max() != node.edges); - const unsigned last = node.firstEdge + node.edges; + const unsigned last = node.first_edge + node.edges; BOOST_ASSERT(std::numeric_limits::max() != last); // swap with last edge edge_list[e] = edge_list[last]; @@ -245,7 +247,7 @@ template class DynamicGraph } number_of_edges -= deleted; - node_list[source].edges -= deleted; + node_array[source].edges -= deleted; return deleted; } @@ -260,7 +262,46 @@ template class DynamicGraph return i; } } - return EndEdges(from); + return SPECIAL_EDGEID; + } + + // searches for a specific edge + EdgeIterator FindSmallestEdge(const NodeIterator from, const NodeIterator to) const + { + EdgeIterator smallest_edge = SPECIAL_EDGEID; + EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT; + for (auto edge : GetAdjacentEdgeRange(from)) + { + const NodeID target = GetTarget(edge); + const EdgeWeight weight = GetEdgeData(edge).distance; + if (target == to && weight < smallest_weight) + { + smallest_edge = edge; + smallest_weight = weight; + } + } + return smallest_edge; + } + + EdgeIterator FindEdgeInEitherDirection(const NodeIterator from, const NodeIterator to) const + { + EdgeIterator tmp = FindEdge(from, to); + return (SPECIAL_NODEID != tmp ? tmp : FindEdge(to, from)); + } + + EdgeIterator + FindEdgeIndicateIfReverse(const NodeIterator from, const NodeIterator to, bool &result) const + { + EdgeIterator current_iterator = FindEdge(from, to); + if (SPECIAL_NODEID == current_iterator) + { + current_iterator = FindEdge(to, from); + if (SPECIAL_NODEID != current_iterator) + { + result = true; + } + } + return current_iterator; } protected: @@ -277,7 +318,7 @@ template class DynamicGraph struct Node { // index of the first edge - EdgeIterator firstEdge; + EdgeIterator first_edge; // amount of edges unsigned edges; }; @@ -291,7 +332,7 @@ template class DynamicGraph NodeIterator number_of_nodes; std::atomic_uint number_of_edges; - std::vector node_list; + std::vector node_array; DeallocatingVector edge_list; }; diff --git a/data_structures/static_graph.hpp b/data_structures/static_graph.hpp index 2a5f6481e..7434b56de 100644 --- a/data_structures/static_graph.hpp +++ b/data_structures/static_graph.hpp @@ -35,8 +35,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#include - #include #include #include @@ -91,7 +89,6 @@ template class StaticGraph StaticGraph(const int nodes, std::vector &graph) { - tbb::parallel_sort(graph.begin(), graph.end()); number_of_nodes = nodes; number_of_edges = static_cast(graph.size()); node_array.resize(number_of_nodes + 1); @@ -112,11 +109,10 @@ template 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 +139,7 @@ template 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; } @@ -159,6 +155,19 @@ template class StaticGraph // searches for a specific edge EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const + { + for (const auto i : osrm::irange(BeginEdges(from), EndEdges(from))) + { + if (to == edge_array[i].target) + { + return i; + } + } + return SPECIAL_EDGEID; + } + + // searches for a specific edge + EdgeIterator FindSmallestEdge(const NodeIterator from, const NodeIterator to) const { EdgeIterator smallest_edge = SPECIAL_EDGEID; EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT; diff --git a/tools/components.cpp b/tools/components.cpp index 85cfd88bd..7ac64f8d9 100644 --- a/tools/components.cpp +++ b/tools/components.cpp @@ -27,8 +27,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../typedefs.h" #include "../algorithms/tiny_components.hpp" -#include "../data_structures/static_graph.hpp" #include "../data_structures/coordinate_calculation.hpp" +#include "../data_structures/dynamic_graph.hpp" +#include "../data_structures/static_graph.hpp" #include "../util/fingerprint.hpp" #include "../util/graph_loader.hpp" #include "../util/make_unique.hpp" @@ -148,6 +149,7 @@ int main(int argc, char *argv[]) // Building an node-based graph std::vector graph_edge_list; +// DeallocatingVector graph_edge_list; for (const auto &input_edge : edge_list) { if (input_edge.source == input_edge.target) @@ -172,15 +174,16 @@ int main(int argc, char *argv[]) "input edge vector not properly deallocated"); tbb::parallel_sort(graph_edge_list.begin(), graph_edge_list.end()); - auto graph = std::make_shared(number_of_nodes, graph_edge_list); - edge_list.clear(); - edge_list.shrink_to_fit(); + const auto graph = std::make_shared(number_of_nodes, graph_edge_list); + graph_edge_list.clear(); + graph_edge_list.shrink_to_fit(); SimpleLogger().Write() << "Starting SCC graph traversal"; RestrictionMap restriction_map(restriction_list); - auto tarjan = - osrm::make_unique>(graph, restriction_map, bollard_node_list); + auto tarjan = osrm::make_unique>(graph, + restriction_map, + bollard_node_list); tarjan->run(); SimpleLogger().Write() << "identified: " << tarjan->get_number_of_components() << " many components"; @@ -235,7 +238,7 @@ int main(int argc, char *argv[]) { const TarjanGraph::NodeIterator target = graph->GetTarget(current_edge); - if (source < target || graph->EndEdges(target) == graph->FindEdge(target, source)) + if (source < target || SPECIAL_EDGEID == graph->FindEdge(target, source)) { total_network_length += 100 * coordinate_calculation::euclidean_distance( diff --git a/tools/graph_compare.cpp b/tools/graph_compare.cpp new file mode 100644 index 000000000..8adc06e78 --- /dev/null +++ b/tools/graph_compare.cpp @@ -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 +#include + +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; +using DynamicTestGraph = StaticGraph; +using StaticEdge = StaticTestGraph::InputEdge; +using DynamicEdge = DynamicTestGraph::InputEdge; + +int main(int argc, char *argv[]) +{ + std::vector coordinate_list; + std::vector restriction_list; + std::vector bollard_node_list; + std::vector traffic_lights_list; + + LogPolicy::GetInstance().Unmute(); + try + { + // enable logging + if (argc < 3) + { + SimpleLogger().Write(logWARNING) << "usage:\n" << argv[0] + << " "; + 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(&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 files"); + } + uint32_t usable_restrictions = 0; + restriction_ifstream.read(reinterpret_cast(&usable_restrictions), sizeof(uint32_t)); + restriction_list.resize(usable_restrictions); + + // load restrictions + if (usable_restrictions > 0) + { + restriction_ifstream.read(reinterpret_cast(&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 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 static_graph_edge_list; + std::vector 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(number_of_nodes, static_graph_edge_list); + auto dynamic_graph = + osrm::make_unique(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 (const auto i : osrm::irange(0u, static_range.size())) + { + 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 static_target_ids, dynamic_target_ids; + std::vector 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; +} diff --git a/unit_tests/data_structures/dynamic_graph.cpp b/unit_tests/data_structures/dynamic_graph.cpp new file mode 100644 index 000000000..27dc7dc68 --- /dev/null +++ b/unit_tests/data_structures/dynamic_graph.cpp @@ -0,0 +1,96 @@ +/* + +Copyright (c) 2014, Project OSRM contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. +Redistributions in binary form must reproduce the above copyright notice, this +list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "../../data_structures/dynamic_graph.hpp" +#include "../../util/make_unique.hpp" +#include "../../typedefs.h" + +#include +#include +#include + +#include +#include + +BOOST_AUTO_TEST_SUITE(dynamic_graph) + +struct TestData +{ + EdgeID id; +}; + +typedef DynamicGraph TestDynamicGraph; +typedef TestDynamicGraph::InputEdge TestInputEdge; + +BOOST_AUTO_TEST_CASE(find_test) +{ + /* + * (0) -1-> (1) + * ^ ^ + * 2 5 + * | | + * (3) -3-> (4) + * <-4- + */ + std::vector input_edges = { + TestInputEdge{0, 1, TestData{1}}, + TestInputEdge{3, 0, TestData{2}}, + TestInputEdge{3, 4, TestData{3}}, + TestInputEdge{4, 3, TestData{4}}, + TestInputEdge{3, 0, TestData{5}} + }; + TestDynamicGraph simple_graph(5, input_edges); + + auto eit = simple_graph.FindEdge(0, 1); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1); + + eit = simple_graph.FindEdge(1, 0); + BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID); + + eit = simple_graph.FindEdgeInEitherDirection(1, 0); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1); + + bool reverse = false; + eit = simple_graph.FindEdgeIndicateIfReverse(1, 0, reverse); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1); + BOOST_CHECK(reverse); + + eit = simple_graph.FindEdge(3, 1); + BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID); + eit = simple_graph.FindEdge(0, 4); + BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID); + + eit = simple_graph.FindEdge(3, 4); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 3); + eit = simple_graph.FindEdgeInEitherDirection(3, 4); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 3); + + eit = simple_graph.FindEdge(3, 0); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 2); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/unit_tests/data_structures/static_graph.cpp b/unit_tests/data_structures/static_graph.cpp index 4b68b254d..ed303b791 100644 --- a/unit_tests/data_structures/static_graph.cpp +++ b/unit_tests/data_structures/static_graph.cpp @@ -40,15 +40,6 @@ BOOST_AUTO_TEST_SUITE(static_graph) struct TestData { EdgeID id; - bool shortcut; - unsigned distance; -}; - -struct TestEdge -{ - unsigned source; - unsigned target; - unsigned distance; }; typedef StaticGraph TestStaticGraph; @@ -58,7 +49,7 @@ typedef TestStaticGraph::InputEdge TestInputEdge; constexpr unsigned TEST_NUM_NODES = 100; constexpr unsigned TEST_NUM_EDGES = 500; -// Choosen by a fair W20 dice roll (this value is completely arbitrary) +// Chosen by a fair W20 dice roll (this value is completely arbitrary) constexpr unsigned RANDOM_SEED = 15; template struct RandomArrayEntryFixture @@ -94,8 +85,7 @@ template struct RandomArrayEntryFixture for (unsigned i = 0; i < NUM_EDGES; i++) { edges.emplace_back( - TestEdgeArrayEntry{static_cast(node_udist(g)), - TestData{i, false, static_cast(lengths_udist(g))}}); + TestEdgeArrayEntry{static_cast(node_udist(g)), TestData{i}}); } for (unsigned i = 0; i < NUM_NODES; i++) @@ -128,49 +118,37 @@ BOOST_FIXTURE_TEST_CASE(array_test, TestRandomArrayEntryFixture) } } -TestStaticGraph GraphFromEdgeList(const std::vector &edges) -{ - std::vector input_edges; - unsigned i = 0; - unsigned num_nodes = 0; - for (const auto &e : edges) - { - input_edges.push_back(TestInputEdge{e.source, e.target, TestData{i++, false, e.distance}}); - - num_nodes = std::max(num_nodes, std::max(e.source, e.target)); - } - - return TestStaticGraph(num_nodes, input_edges); -} - BOOST_AUTO_TEST_CASE(find_test) { /* * (0) -1-> (1) * ^ ^ - * 2 1 + * 2 5 * | | - * (3) -4-> (4) - * <-3- + * (3) -3-> (4) + * <-4- */ - TestStaticGraph simple_graph = GraphFromEdgeList({TestEdge{0, 1, 1}, - TestEdge{3, 0, 2}, - TestEdge{3, 4, 4}, - TestEdge{4, 3, 3}, - TestEdge{3, 0, 1}}); + std::vector input_edges = { + TestInputEdge{0, 1, TestData{1}}, + TestInputEdge{3, 0, TestData{2}}, + TestInputEdge{3, 4, TestData{3}}, + TestInputEdge{4, 3, TestData{4}}, + TestInputEdge{3, 0, TestData{5}} + }; + TestStaticGraph simple_graph(5, input_edges); auto eit = simple_graph.FindEdge(0, 1); - BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 0); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1); eit = simple_graph.FindEdge(1, 0); BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID); eit = simple_graph.FindEdgeInEitherDirection(1, 0); - BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 0); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1); bool reverse = false; eit = simple_graph.FindEdgeIndicateIfReverse(1, 0, reverse); - BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 0); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 1); BOOST_CHECK(reverse); eit = simple_graph.FindEdge(3, 1); @@ -179,13 +157,12 @@ BOOST_AUTO_TEST_CASE(find_test) BOOST_CHECK_EQUAL(eit, SPECIAL_EDGEID); eit = simple_graph.FindEdge(3, 4); - BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 2); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 3); eit = simple_graph.FindEdgeInEitherDirection(3, 4); - // I think this is wrong behaviour! Should be 3. - BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 2); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 3); eit = simple_graph.FindEdge(3, 0); - BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 4); + BOOST_CHECK_EQUAL(simple_graph.GetEdgeData(eit).id, 2); } BOOST_AUTO_TEST_SUITE_END()