From 7345dc686108aa59dff534a8d3023b324ef01868 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Wed, 24 Jun 2015 01:55:30 +0200 Subject: [PATCH] Move graph compression code outside of EBGF --- contractor/edge_based_graph_factory.cpp | 233 ++---------------------- contractor/edge_based_graph_factory.hpp | 37 +--- contractor/graph_compressor.cpp | 187 +++++++++++++++++++ contractor/graph_compressor.hpp | 62 +++++++ contractor/processing_chain.cpp | 56 +++--- contractor/processing_chain.hpp | 12 +- contractor/speed_profile.hpp | 16 ++ data_structures/restriction_map.hpp | 2 +- 8 files changed, 335 insertions(+), 270 deletions(-) create mode 100644 contractor/graph_compressor.cpp create mode 100644 contractor/graph_compressor.hpp create mode 100644 contractor/speed_profile.hpp diff --git a/contractor/edge_based_graph_factory.cpp b/contractor/edge_based_graph_factory.cpp index dbd73a73c..f4fb4467b 100644 --- a/contractor/edge_based_graph_factory.cpp +++ b/contractor/edge_based_graph_factory.cpp @@ -41,20 +41,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include EdgeBasedGraphFactory::EdgeBasedGraphFactory(std::shared_ptr node_based_graph, - std::shared_ptr restriction_map, - std::unique_ptr> barrier_node_list, - std::unique_ptr> traffic_light_node_list, - const std::vector &node_info_list, - const SpeedProfileProperties &speed_profile) - : speed_profile(speed_profile), - m_number_of_edge_based_nodes(std::numeric_limits::max()), - m_node_info_list(node_info_list), - m_node_based_graph(std::move(node_based_graph)), - m_restriction_map(std::move(restriction_map)), max_id(0), removed_node_count(0) + const GeometryCompressor& geometry_compressor, + const std::unordered_set& barrier_nodes, + const std::unordered_set& traffic_lights, + std::shared_ptr restriction_map, + const std::vector &node_info_list, + const SpeedProfileProperties &speed_profile) + : m_node_info_list(node_info_list), + m_node_based_graph(node_based_graph), + m_restriction_map(restriction_map), + m_barrier_nodes(barrier_nodes), + m_traffic_lights(traffic_lights), + m_geometry_compressor(geometry_compressor), + speed_profile(speed_profile) { - // insert into unordered sets for fast lookup - m_barrier_nodes.insert(barrier_node_list->begin(), barrier_node_list->end()); - m_traffic_lights.insert(traffic_light_node_list->begin(), traffic_light_node_list->end()); } void EdgeBasedGraphFactory::GetEdgeBasedEdges(DeallocatingVector &output_edge_list) @@ -146,15 +146,6 @@ void EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, NodeID current_edge_source_coordinate_id = node_u; - if (SPECIAL_NODEID != forward_data.edgeBasedNodeID) - { - max_id = std::max(forward_data.edgeBasedNodeID, max_id); - } - if (SPECIAL_NODEID != reverse_data.edgeBasedNodeID) - { - max_id = std::max(reverse_data.edgeBasedNodeID, max_id); - } - // traverse arrays from start and end respectively for (const auto i : osrm::irange(0u, geometry_size)) { @@ -231,13 +222,8 @@ void EdgeBasedGraphFactory::FlushVectorToStream( } void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename, - const std::string &geometry_filename, lua_State *lua_state) { - TIMER_START(geometry); - CompressGeometry(); - TIMER_STOP(geometry); - TIMER_START(renumber); RenumberEdges(); TIMER_STOP(renumber); @@ -250,189 +236,12 @@ void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename, GenerateEdgeExpandedEdges(original_edge_data_filename, lua_state); TIMER_STOP(generate_edges); - m_geometry_compressor.SerializeInternalVector(geometry_filename); - SimpleLogger().Write() << "Timing statistics for edge-expanded graph:"; - SimpleLogger().Write() << "Geometry compression: " << TIMER_SEC(geometry) << "s"; SimpleLogger().Write() << "Renumbering edges: " << TIMER_SEC(renumber) << "s"; SimpleLogger().Write() << "Generating nodes: " << TIMER_SEC(generate_nodes) << "s"; SimpleLogger().Write() << "Generating edges: " << TIMER_SEC(generate_edges) << "s"; } -void EdgeBasedGraphFactory::CompressGeometry() -{ - SimpleLogger().Write() << "Removing graph geometry while preserving topology"; - - const unsigned original_number_of_nodes = m_node_based_graph->GetNumberOfNodes(); - const unsigned original_number_of_edges = m_node_based_graph->GetNumberOfEdges(); - - Percent progress(original_number_of_nodes); - - for (const NodeID node_v : osrm::irange(0u, original_number_of_nodes)) - { - progress.printStatus(node_v); - - // only contract degree 2 vertices - if (2 != m_node_based_graph->GetOutDegree(node_v)) - { - continue; - } - - // don't contract barrier node - if (m_barrier_nodes.end() != m_barrier_nodes.find(node_v)) - { - continue; - } - - // check if v is a via node for a turn restriction, i.e. a 'directed' barrier node - if (m_restriction_map->IsViaNode(node_v)) - { - continue; - } - - /* - * reverse_e2 forward_e2 - * u <---------- v -----------> w - * ----------> <----------- - * forward_e1 reverse_e1 - * - * Will be compressed to: - * - * reverse_e1 - * u <---------- w - * ----------> - * forward_e1 - * - * If the edges are compatible. - * - */ - - const bool reverse_edge_order = - !(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(node_v)).forward); - const EdgeID forward_e2 = m_node_based_graph->BeginEdges(node_v) + reverse_edge_order; - BOOST_ASSERT(SPECIAL_EDGEID != forward_e2); - BOOST_ASSERT(forward_e2 >= m_node_based_graph->BeginEdges(node_v) && - forward_e2 < m_node_based_graph->EndEdges(node_v)); - const EdgeID reverse_e2 = m_node_based_graph->BeginEdges(node_v) + 1 - reverse_edge_order; - BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2); - BOOST_ASSERT(reverse_e2 >= m_node_based_graph->BeginEdges(node_v) && - reverse_e2 < m_node_based_graph->EndEdges(node_v)); - - const EdgeData &fwd_edge_data2 = m_node_based_graph->GetEdgeData(forward_e2); - const EdgeData &rev_edge_data2 = m_node_based_graph->GetEdgeData(reverse_e2); - - const NodeID node_w = m_node_based_graph->GetTarget(forward_e2); - BOOST_ASSERT(SPECIAL_NODEID != node_w); - BOOST_ASSERT(node_v != node_w); - const NodeID node_u = m_node_based_graph->GetTarget(reverse_e2); - BOOST_ASSERT(SPECIAL_NODEID != node_u); - BOOST_ASSERT(node_u != node_v); - - const EdgeID forward_e1 = m_node_based_graph->FindEdge(node_u, node_v); - 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); - BOOST_ASSERT(SPECIAL_EDGEID != reverse_e1); - BOOST_ASSERT(node_v == m_node_based_graph->GetTarget(reverse_e1)); - - 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->FindEdgeInEitherDirection(node_u, node_w) != SPECIAL_EDGEID) - { - continue; - } - - // this case can happen if two ways with different names overlap - if (fwd_edge_data1.nameID != rev_edge_data1.nameID || - fwd_edge_data2.nameID != rev_edge_data2.nameID) - { - continue; - } - - if (fwd_edge_data1.IsCompatibleTo(fwd_edge_data2) && rev_edge_data1.IsCompatibleTo(rev_edge_data2)) - { - BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID == - m_node_based_graph->GetEdgeData(reverse_e1).nameID); - BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e2).nameID == - m_node_based_graph->GetEdgeData(reverse_e2).nameID); - - // Get distances before graph is modified - const int forward_weight1 = m_node_based_graph->GetEdgeData(forward_e1).distance; - const int forward_weight2 = m_node_based_graph->GetEdgeData(forward_e2).distance; - - BOOST_ASSERT(0 != forward_weight1); - BOOST_ASSERT(0 != forward_weight2); - - const int reverse_weight1 = m_node_based_graph->GetEdgeData(reverse_e1).distance; - const int reverse_weight2 = m_node_based_graph->GetEdgeData(reverse_e2).distance; - - BOOST_ASSERT(0 != reverse_weight1); - BOOST_ASSERT(0 != reverse_weight2); - - const bool has_node_penalty = m_traffic_lights.find(node_v) != m_traffic_lights.end(); - - // add weight of e2's to e1 - m_node_based_graph->GetEdgeData(forward_e1).distance += fwd_edge_data2.distance; - m_node_based_graph->GetEdgeData(reverse_e1).distance += rev_edge_data2.distance; - if (has_node_penalty) - { - m_node_based_graph->GetEdgeData(forward_e1).distance += - speed_profile.traffic_signal_penalty; - m_node_based_graph->GetEdgeData(reverse_e1).distance += - speed_profile.traffic_signal_penalty; - } - - // extend e1's to targets of e2's - m_node_based_graph->SetTarget(forward_e1, node_w); - m_node_based_graph->SetTarget(reverse_e1, node_u); - - // remove e2's (if bidir, otherwise only one) - m_node_based_graph->DeleteEdge(node_v, forward_e2); - m_node_based_graph->DeleteEdge(node_v, reverse_e2); - - // update any involved turn restrictions - m_restriction_map->FixupStartingTurnRestriction(node_u, node_v, node_w); - m_restriction_map->FixupArrivingTurnRestriction(node_u, node_v, node_w, - *m_node_based_graph); - - m_restriction_map->FixupStartingTurnRestriction(node_w, node_v, node_u); - m_restriction_map->FixupArrivingTurnRestriction(node_w, node_v, node_u, - *m_node_based_graph); - - // store compressed geometry in container - m_geometry_compressor.CompressEdge( - forward_e1, forward_e2, node_v, node_w, - forward_weight1 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0), - forward_weight2); - m_geometry_compressor.CompressEdge( - reverse_e1, reverse_e2, node_v, node_u, reverse_weight1, - reverse_weight2 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0)); - ++removed_node_count; - - - } - } - SimpleLogger().Write() << "removed " << removed_node_count << " nodes"; - m_geometry_compressor.PrintStatistics(); - - unsigned new_node_count = 0; - unsigned new_edge_count = 0; - - for (const auto i : osrm::irange(0u, m_node_based_graph->GetNumberOfNodes())) - { - if (m_node_based_graph->GetOutDegree(i) > 0) - { - ++new_node_count; - new_edge_count += (m_node_based_graph->EndEdges(i) - m_node_based_graph->BeginEdges(i)); - } - } - SimpleLogger().Write() << "new nodes: " << new_node_count << ", edges " << new_edge_count; - SimpleLogger().Write() << "Node compression ratio: " - << new_node_count / (double)original_number_of_nodes; - SimpleLogger().Write() << "Edge compression ratio: " - << new_edge_count / (double)original_number_of_edges; -} /// Renumbers all _forward_ edges and sets the edgeBasedNodeID. /// A specific numbering is not important. Any unique ID will do. @@ -462,9 +271,7 @@ void EdgeBasedGraphFactory::RenumberEdges() m_number_of_edge_based_nodes = numbered_edges_count; } -/** - * Creates the nodes in the edge expanded graph from edges in the node-based graph. - */ +/// Creates the nodes in the edge expanded graph from edges in the node-based graph. void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes() { SimpleLogger().Write() << "Identifying components of the (compressed) road network"; @@ -476,10 +283,10 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes() component_explorer.run(); SimpleLogger().Write() << "identified: " - << component_explorer.get_number_of_components() - removed_node_count + << component_explorer.get_number_of_components() << " (compressed) components"; SimpleLogger().Write() << "identified " - << component_explorer.get_size_one_count() - removed_node_count + << component_explorer.get_size_one_count() << " (compressed) SCCs of size 1"; SimpleLogger().Write() << "generating edge-expanded nodes"; @@ -543,9 +350,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes() << " nodes in edge-expanded graph"; } -/** - * Actually it also generates OriginalEdgeData and serializes them... - */ +/// Actually it also generates OriginalEdgeData and serializes them... void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( const std::string &original_edge_data_filename, lua_State *lua_state) { @@ -790,7 +595,3 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID node_u, return TurnInstructionsClass::GetTurnDirectionOfInstruction(angle); } -unsigned EdgeBasedGraphFactory::GetNumberOfEdgeBasedNodes() const -{ - return m_number_of_edge_based_nodes; -} diff --git a/contractor/edge_based_graph_factory.hpp b/contractor/edge_based_graph_factory.hpp index a5274396f..8e0ea2608 100644 --- a/contractor/edge_based_graph_factory.hpp +++ b/contractor/edge_based_graph_factory.hpp @@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef EDGE_BASED_GRAPH_FACTORY_HPP_ #define EDGE_BASED_GRAPH_FACTORY_HPP_ +#include "speed_profile.hpp" #include "geometry_compressor.hpp" #include "../typedefs.h" #include "../data_structures/deallocating_vector.hpp" @@ -57,17 +58,16 @@ class EdgeBasedGraphFactory EdgeBasedGraphFactory() = delete; EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete; - struct SpeedProfileProperties; explicit EdgeBasedGraphFactory(std::shared_ptr node_based_graph, - std::shared_ptr restricion_map, - std::unique_ptr> barrier_node_list, - std::unique_ptr> traffic_light_node_list, + const GeometryCompressor& geometry_compressor, + const std::unordered_set& barrier_nodes, + const std::unordered_set& traffic_lights, + std::shared_ptr restriction_map, const std::vector &node_info_list, const SpeedProfileProperties &speed_profile); void Run(const std::string &original_edge_data_filename, - const std::string &geometry_filename, lua_State *lua_state); void GetEdgeBasedEdges(DeallocatingVector &edges); @@ -78,20 +78,6 @@ class EdgeBasedGraphFactory int GetTurnPenalty(double angle, lua_State *lua_state) const; - unsigned GetNumberOfEdgeBasedNodes() const; - - struct SpeedProfileProperties - { - SpeedProfileProperties() - : traffic_signal_penalty(0), u_turn_penalty(0), has_turn_penalty_function(false) - { - } - - int traffic_signal_penalty; - int u_turn_penalty; - bool has_turn_penalty_function; - } speed_profile; - private: using EdgeData = NodeBasedDynamicGraph::EdgeData; @@ -102,13 +88,13 @@ class EdgeBasedGraphFactory const std::vector& m_node_info_list; std::shared_ptr m_node_based_graph; - std::shared_ptr m_restriction_map; + std::shared_ptr m_restriction_map; - std::unordered_set m_barrier_nodes; - std::unordered_set m_traffic_lights; + const std::unordered_set& m_barrier_nodes; + const std::unordered_set& m_traffic_lights; + const GeometryCompressor& m_geometry_compressor; - - GeometryCompressor m_geometry_compressor; + SpeedProfileProperties speed_profile; void CompressGeometry(); void RenumberEdges(); @@ -121,9 +107,6 @@ class EdgeBasedGraphFactory void FlushVectorToStream(std::ofstream &edge_data_file, std::vector &original_edge_data_vector) const; - NodeID max_id; - std::size_t removed_node_count; - }; #endif /* EDGE_BASED_GRAPH_FACTORY_HPP_ */ diff --git a/contractor/graph_compressor.cpp b/contractor/graph_compressor.cpp new file mode 100644 index 000000000..79fcbb937 --- /dev/null +++ b/contractor/graph_compressor.cpp @@ -0,0 +1,187 @@ +#include "graph_compressor.hpp" + +#include "geometry_compressor.hpp" +#include "../data_structures/dynamic_graph.hpp" +#include "../data_structures/node_based_graph.hpp" +#include "../data_structures/restriction_map.hpp" +#include "../data_structures/percent.hpp" + +GraphCompressor::GraphCompressor(const SpeedProfileProperties& speed_profile) + : speed_profile(speed_profile) +{ +} + + +void GraphCompressor::Compress(const std::unordered_set& barrier_nodes, + const std::unordered_set& traffic_lights, + RestrictionMap& restriction_map, + NodeBasedDynamicGraph& graph, + GeometryCompressor& geometry_compressor) +{ + const unsigned original_number_of_nodes = graph.GetNumberOfNodes(); + const unsigned original_number_of_edges = graph.GetNumberOfEdges(); + + Percent progress(original_number_of_nodes); + + for (const NodeID node_v : osrm::irange(0u, original_number_of_nodes)) + { + progress.printStatus(node_v); + + // only contract degree 2 vertices + if (2 != graph.GetOutDegree(node_v)) + { + continue; + } + + // don't contract barrier node + if (barrier_nodes.end() != barrier_nodes.find(node_v)) + { + continue; + } + + // check if v is a via node for a turn restriction, i.e. a 'directed' barrier node + if (restriction_map.IsViaNode(node_v)) + { + continue; + } + + // reverse_e2 forward_e2 + // u <---------- v -----------> w + // ----------> <----------- + // forward_e1 reverse_e1 + // + // Will be compressed to: + // + // reverse_e1 + // u <---------- w + // ----------> + // forward_e1 + // + // If the edges are compatible. + + const bool reverse_edge_order = + !(graph.GetEdgeData(graph.BeginEdges(node_v)).forward); + const EdgeID forward_e2 = graph.BeginEdges(node_v) + reverse_edge_order; + BOOST_ASSERT(SPECIAL_EDGEID != forward_e2); + BOOST_ASSERT(forward_e2 >= graph.BeginEdges(node_v) && + forward_e2 < graph.EndEdges(node_v)); + const EdgeID reverse_e2 = graph.BeginEdges(node_v) + 1 - reverse_edge_order; + BOOST_ASSERT(SPECIAL_EDGEID != reverse_e2); + BOOST_ASSERT(reverse_e2 >= graph.BeginEdges(node_v) && + reverse_e2 < graph.EndEdges(node_v)); + + const EdgeData &fwd_edge_data2 = graph.GetEdgeData(forward_e2); + const EdgeData &rev_edge_data2 = graph.GetEdgeData(reverse_e2); + + const NodeID node_w = graph.GetTarget(forward_e2); + BOOST_ASSERT(SPECIAL_NODEID != node_w); + BOOST_ASSERT(node_v != node_w); + const NodeID node_u = graph.GetTarget(reverse_e2); + BOOST_ASSERT(SPECIAL_NODEID != node_u); + BOOST_ASSERT(node_u != node_v); + + const EdgeID forward_e1 = graph.FindEdge(node_u, node_v); + BOOST_ASSERT(SPECIAL_EDGEID != forward_e1); + BOOST_ASSERT(node_v == graph.GetTarget(forward_e1)); + const EdgeID reverse_e1 = graph.FindEdge(node_w, node_v); + BOOST_ASSERT(SPECIAL_EDGEID != reverse_e1); + BOOST_ASSERT(node_v == graph.GetTarget(reverse_e1)); + + const EdgeData &fwd_edge_data1 = graph.GetEdgeData(forward_e1); + const EdgeData &rev_edge_data1 = graph.GetEdgeData(reverse_e1); + + if (graph.FindEdgeInEitherDirection(node_u, node_w) != SPECIAL_EDGEID) + { + continue; + } + + // this case can happen if two ways with different names overlap + if (fwd_edge_data1.nameID != rev_edge_data1.nameID || + fwd_edge_data2.nameID != rev_edge_data2.nameID) + { + continue; + } + + if (fwd_edge_data1.IsCompatibleTo(fwd_edge_data2) && rev_edge_data1.IsCompatibleTo(rev_edge_data2)) + { + BOOST_ASSERT(graph.GetEdgeData(forward_e1).nameID == + graph.GetEdgeData(reverse_e1).nameID); + BOOST_ASSERT(graph.GetEdgeData(forward_e2).nameID == + graph.GetEdgeData(reverse_e2).nameID); + + // Get distances before graph is modified + const int forward_weight1 = graph.GetEdgeData(forward_e1).distance; + const int forward_weight2 = graph.GetEdgeData(forward_e2).distance; + + BOOST_ASSERT(0 != forward_weight1); + BOOST_ASSERT(0 != forward_weight2); + + const int reverse_weight1 = graph.GetEdgeData(reverse_e1).distance; + const int reverse_weight2 = graph.GetEdgeData(reverse_e2).distance; + + BOOST_ASSERT(0 != reverse_weight1); + BOOST_ASSERT(0 != reverse_weight2); + + const bool has_node_penalty = traffic_lights.find(node_v) != traffic_lights.end(); + + // add weight of e2's to e1 + graph.GetEdgeData(forward_e1).distance += fwd_edge_data2.distance; + graph.GetEdgeData(reverse_e1).distance += rev_edge_data2.distance; + if (has_node_penalty) + { + graph.GetEdgeData(forward_e1).distance += + speed_profile.traffic_signal_penalty; + graph.GetEdgeData(reverse_e1).distance += + speed_profile.traffic_signal_penalty; + } + + // extend e1's to targets of e2's + graph.SetTarget(forward_e1, node_w); + graph.SetTarget(reverse_e1, node_u); + + // remove e2's (if bidir, otherwise only one) + graph.DeleteEdge(node_v, forward_e2); + graph.DeleteEdge(node_v, reverse_e2); + + // update any involved turn restrictions + restriction_map.FixupStartingTurnRestriction(node_u, node_v, node_w); + restriction_map.FixupArrivingTurnRestriction(node_u, node_v, node_w, graph); + + restriction_map.FixupStartingTurnRestriction(node_w, node_v, node_u); + restriction_map.FixupArrivingTurnRestriction(node_w, node_v, node_u, graph); + + // store compressed geometry in container + geometry_compressor.CompressEdge( + forward_e1, forward_e2, node_v, node_w, + forward_weight1 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0), + forward_weight2); + geometry_compressor.CompressEdge( + reverse_e1, reverse_e2, node_v, node_u, reverse_weight1, + reverse_weight2 + (has_node_penalty ? speed_profile.traffic_signal_penalty : 0)); + } + } + + PrintStatistics(original_number_of_nodes, original_number_of_edges, graph); +} + +void GraphCompressor::PrintStatistics(unsigned original_number_of_nodes, + unsigned original_number_of_edges, + const NodeBasedDynamicGraph& graph) const +{ + + unsigned new_node_count = 0; + unsigned new_edge_count = 0; + + for (const auto i : osrm::irange(0u, graph.GetNumberOfNodes())) + { + if (graph.GetOutDegree(i) > 0) + { + ++new_node_count; + new_edge_count += (graph.EndEdges(i) - graph.BeginEdges(i)); + } + } + SimpleLogger().Write() << "Node compression ratio: " + << new_node_count / (double)original_number_of_nodes; + SimpleLogger().Write() << "Edge compression ratio: " + << new_edge_count / (double)original_number_of_edges; +} diff --git a/contractor/graph_compressor.hpp b/contractor/graph_compressor.hpp new file mode 100644 index 000000000..17b3c29a7 --- /dev/null +++ b/contractor/graph_compressor.hpp @@ -0,0 +1,62 @@ +/* + +Copyright (c) 2014, Project OSRM, Dennis Luxen, others +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. + +*/ +#ifndef GEOMETRY_COMPRESSOR_HPP +#define GEOMETRY_COMPRESSOR_HPP + +#include "../typedefs.h" + +#include "speed_profile.hpp" +#include "../data_structures/node_based_graph.hpp" + +#include +#include + +class GeometryCompressor; +class RestrictionMap; + +class GraphCompressor +{ + using EdgeData = NodeBasedDynamicGraph::EdgeData; + +public: + GraphCompressor(const SpeedProfileProperties& speed_profile); + + void Compress(const std::unordered_set& barrier_nodes, + const std::unordered_set& traffic_lights, + RestrictionMap& restriction_map, + NodeBasedDynamicGraph& graph, + GeometryCompressor& geometry_compressor); +private: + + void PrintStatistics(unsigned original_number_of_nodes, + unsigned original_number_of_edges, + const NodeBasedDynamicGraph& graph) const; + + SpeedProfileProperties speed_profile; +}; + +#endif diff --git a/contractor/processing_chain.cpp b/contractor/processing_chain.cpp index a76bc657f..207381864 100644 --- a/contractor/processing_chain.cpp +++ b/contractor/processing_chain.cpp @@ -28,6 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "processing_chain.hpp" #include "contractor.hpp" +#include "geometry_compressor.hpp" +#include "graph_compressor.hpp" #include "../algorithms/crc32_processor.hpp" #include "../data_structures/deallocating_vector.hpp" @@ -263,7 +265,7 @@ unsigned Prepare::CalculateEdgeChecksum(std::unique_ptr Prepare::LoadRestrictionMap() \brief Load node based graph from .osrm file */ std::shared_ptr -Prepare::LoadNodeBasedGraph(std::vector &barrier_node_list, - std::vector &traffic_light_list, +Prepare::LoadNodeBasedGraph(std::unordered_set &barrier_nodes, + std::unordered_set &traffic_lights, std::vector& internal_to_external_node_map) { std::vector edge_list; boost::filesystem::ifstream input_stream(config.osrm_input_path, std::ios::in | std::ios::binary); + std::vector barrier_list; + std::vector traffic_light_list; NodeID number_of_node_based_nodes = loadNodesFromFile(input_stream, - barrier_node_list, traffic_light_list, + barrier_list, traffic_light_list, internal_to_external_node_map); - SimpleLogger().Write() << " - " << barrier_node_list.size() << " bollard nodes, " + SimpleLogger().Write() << " - " << barrier_list.size() << " bollard nodes, " << traffic_light_list.size() << " traffic lights"; + // insert into unordered sets for fast lookup + barrier_nodes.insert(barrier_list.begin(), barrier_list.end()); + traffic_lights.insert(traffic_light_list.begin(), traffic_light_list.end()); + + barrier_list.clear(); + barrier_list.shrink_to_fit(); + traffic_light_list.clear(); + traffic_light_list.shrink_to_fit(); + loadEdgesFromFile(input_stream, edge_list); if (edge_list.empty()) @@ -357,37 +370,38 @@ Prepare::BuildEdgeExpandedGraph(std::vector &internal_to_external_nod lua_State *lua_state = luaL_newstate(); luabind::open(lua_state); - EdgeBasedGraphFactory::SpeedProfileProperties speed_profile; - + SpeedProfileProperties speed_profile; SetupScriptingEnvironment(lua_state, speed_profile); - auto barrier_node_list = osrm::make_unique>(); - auto traffic_light_list = osrm::make_unique>(); + std::unordered_set barrier_nodes; + std::unordered_set traffic_lights; auto restriction_map = LoadRestrictionMap(); - auto node_based_graph = LoadNodeBasedGraph(*barrier_node_list, *traffic_light_list, internal_to_external_node_map); + auto node_based_graph = LoadNodeBasedGraph(barrier_nodes, traffic_lights, internal_to_external_node_map); - const std::size_t number_of_node_based_nodes = node_based_graph->GetNumberOfNodes(); + + GeometryCompressor geometry_compressor; + GraphCompressor graph_compressor(speed_profile); + graph_compressor.Compress(barrier_nodes, traffic_lights, *restriction_map, *node_based_graph, geometry_compressor); EdgeBasedGraphFactory edge_based_graph_factory(node_based_graph, - restriction_map, - std::move(barrier_node_list), - std::move(traffic_light_list), + geometry_compressor, + barrier_nodes, + traffic_lights, + std::const_pointer_cast(restriction_map), internal_to_external_node_map, speed_profile); - edge_based_graph_factory.Run(config.edge_output_path, config.geometry_output_path, lua_state); + geometry_compressor.SerializeInternalVector(config.geometry_output_path); + + edge_based_graph_factory.Run(config.edge_output_path, lua_state); lua_close(lua_state); - const std::size_t number_of_edge_based_nodes = - edge_based_graph_factory.GetNumberOfEdgeBasedNodes(); - - BOOST_ASSERT(number_of_edge_based_nodes != std::numeric_limits::max()); - edge_based_graph_factory.GetEdgeBasedEdges(edge_based_edge_list); edge_based_graph_factory.GetEdgeBasedNodes(node_based_edge_list); - return std::make_pair(number_of_node_based_nodes, number_of_edge_based_nodes); + const std::size_t number_of_node_based_nodes = node_based_graph->GetNumberOfNodes(); + return std::make_pair(number_of_node_based_nodes, node_based_edge_list.size()); } /** diff --git a/contractor/processing_chain.hpp b/contractor/processing_chain.hpp index 281768166..a46b963ec 100644 --- a/contractor/processing_chain.hpp +++ b/contractor/processing_chain.hpp @@ -33,6 +33,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "../data_structures/query_edge.hpp" #include "../data_structures/static_graph.hpp" +struct SpeedProfileProperties; struct EdgeBasedNode; struct lua_State; @@ -59,8 +60,7 @@ class Prepare protected: void SetupScriptingEnvironment(lua_State *myLuaState, - EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile); - std::shared_ptr LoadRestrictionMap(); + SpeedProfileProperties &speed_profile); unsigned CalculateEdgeChecksum(std::unique_ptr> node_based_edge_list); void ContractGraph(const std::size_t number_of_edge_based_nodes, DeallocatingVector& edge_based_edge_list, @@ -68,9 +68,11 @@ class Prepare std::size_t WriteContractedGraph(unsigned number_of_edge_based_nodes, std::unique_ptr> node_based_edge_list, std::unique_ptr> contracted_edge_list); - std::shared_ptr LoadNodeBasedGraph(std::vector &barrier_node_list, - std::vector &traffic_light_list, - std::vector& internal_to_external_node_map); + std::shared_ptr LoadRestrictionMap(); + std::shared_ptr + LoadNodeBasedGraph(std::unordered_set &barrier_nodes, + std::unordered_set &traffic_lights, + std::vector& internal_to_external_node_map); std::pair BuildEdgeExpandedGraph(std::vector &internal_to_external_node_map, std::vector &node_based_edge_list, diff --git a/contractor/speed_profile.hpp b/contractor/speed_profile.hpp new file mode 100644 index 000000000..534ccce34 --- /dev/null +++ b/contractor/speed_profile.hpp @@ -0,0 +1,16 @@ +#ifndef SPEED_PROFILE_PROPERTIES_HPP +#define SPEED_PROFILE_PROPERTIES_HPP + +struct SpeedProfileProperties +{ + SpeedProfileProperties() + : traffic_signal_penalty(0), u_turn_penalty(0), has_turn_penalty_function(false) + { + } + + int traffic_signal_penalty; + int u_turn_penalty; + bool has_turn_penalty_function; +}; + +#endif diff --git a/data_structures/restriction_map.hpp b/data_structures/restriction_map.hpp index 98b360c25..dbca35651 100644 --- a/data_structures/restriction_map.hpp +++ b/data_structures/restriction_map.hpp @@ -156,7 +156,7 @@ class RestrictionMap bool CheckIfTurnIsRestricted(const NodeID node_u, const NodeID node_v, const NodeID node_w) const; - std::size_t size() { return m_count; } + std::size_t size() const { return m_count; } private: // check of node is the start of any restriction