Merge pull request #1440 from Project-OSRM/feature/check_graph_implementations
fix incorrect SCC generation
This commit is contained in:
commit
d4065774ce
@ -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)
|
||||
|
@ -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])
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
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 (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;
|
||||
}
|
96
unit_tests/data_structures/dynamic_graph.cpp
Normal file
96
unit_tests/data_structures/dynamic_graph.cpp
Normal 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()
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user