Merge pull request #1440 from Project-OSRM/feature/check_graph_implementations

fix incorrect SCC generation
This commit is contained in:
Dennis Luxen 2015-04-17 09:50:46 +02:00
commit d4065774ce
9 changed files with 422 additions and 105 deletions

View File

@ -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)

View File

@ -95,18 +95,18 @@ template <typename GraphT> 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<TarjanStackFrame> recursion_stack;
// true = stuff before, false = stuff after call
std::stack<NodeID> tarjan_stack;
std::vector<TarjanNode> tarjan_node_list(m_node_based_graph->GetNumberOfNodes());
std::vector<TarjanNode> 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<bool> processing_node_before_recursion(m_node_based_graph->GetNumberOfNodes(),
true);
for (const NodeID node : osrm::irange(0u, last_node))
std::vector<bool> processing_node_before_recursion(max_node_id, true);
for (const NodeID node : osrm::irange(0u, max_node_id))
{
if (SPECIAL_NODEID == components_index[node])
{

View File

@ -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;
}

View File

@ -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 <boost/assert.hpp>
#include <cstdint>
#include <algorithm>
#include <limits>
#include <vector>
#include <atomic>
#include <limits>
#include <tuple>
#include <vector>
template <typename EdgeDataT> class DynamicGraph
{
@ -76,8 +78,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 +89,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 +126,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 +151,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 +166,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 +175,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 +197,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 +247,7 @@ template <typename EdgeDataT> class DynamicGraph
}
number_of_edges -= deleted;
node_list[source].edges -= deleted;
node_array[source].edges -= deleted;
return deleted;
}
@ -260,7 +262,46 @@ template <typename EdgeDataT> 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 <typename EdgeDataT> class DynamicGraph
struct Node
{
// index of the first edge
EdgeIterator firstEdge;
EdgeIterator first_edge;
// amount of edges
unsigned edges;
};
@ -291,7 +332,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;
};

View File

@ -35,8 +35,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/assert.hpp>
#include <tbb/parallel_sort.h>
#include <algorithm>
#include <limits>
#include <utility>
@ -91,7 +89,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 +109,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 +139,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; }
@ -159,6 +155,19 @@ template <typename EdgeDataT, bool UseSharedMemory = false> 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;

View File

@ -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<TarjanEdge> graph_edge_list;
// DeallocatingVector<TarjanEdge> 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<TarjanGraph>(number_of_nodes, graph_edge_list);
edge_list.clear();
edge_list.shrink_to_fit();
const auto graph = std::make_shared<TarjanGraph>(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<TarjanSCC<TarjanGraph>>(graph, restriction_map, bollard_node_list);
auto tarjan = osrm::make_unique<TarjanSCC<TarjanGraph>>(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(

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 (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<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;
}

View File

@ -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 <boost/test/unit_test.hpp>
#include <boost/test/test_case_template.hpp>
#include <boost/mpl/list.hpp>
#include <random>
#include <unordered_map>
BOOST_AUTO_TEST_SUITE(dynamic_graph)
struct TestData
{
EdgeID id;
};
typedef DynamicGraph<TestData> TestDynamicGraph;
typedef TestDynamicGraph::InputEdge TestInputEdge;
BOOST_AUTO_TEST_CASE(find_test)
{
/*
* (0) -1-> (1)
* ^ ^
* 2 5
* | |
* (3) -3-> (4)
* <-4-
*/
std::vector<TestInputEdge> 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()

View File

@ -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<TestData> 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 <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomArrayEntryFixture
@ -94,8 +85,7 @@ template <unsigned NUM_NODES, unsigned NUM_EDGES> struct RandomArrayEntryFixture
for (unsigned i = 0; i < NUM_EDGES; i++)
{
edges.emplace_back(
TestEdgeArrayEntry{static_cast<unsigned>(node_udist(g)),
TestData{i, false, static_cast<unsigned>(lengths_udist(g))}});
TestEdgeArrayEntry{static_cast<unsigned>(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<TestEdge> &edges)
{
std::vector<TestInputEdge> 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<TestInputEdge> 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()