Move graph compression code outside of EBGF
This commit is contained in:
parent
9958937fd1
commit
7345dc6861
@ -41,20 +41,20 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <limits>
|
||||
|
||||
EdgeBasedGraphFactory::EdgeBasedGraphFactory(std::shared_ptr<NodeBasedDynamicGraph> node_based_graph,
|
||||
std::shared_ptr<RestrictionMap> restriction_map,
|
||||
std::unique_ptr<std::vector<NodeID>> barrier_node_list,
|
||||
std::unique_ptr<std::vector<NodeID>> traffic_light_node_list,
|
||||
const std::vector<QueryNode> &node_info_list,
|
||||
const SpeedProfileProperties &speed_profile)
|
||||
: speed_profile(speed_profile),
|
||||
m_number_of_edge_based_nodes(std::numeric_limits<unsigned>::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<NodeID>& barrier_nodes,
|
||||
const std::unordered_set<NodeID>& traffic_lights,
|
||||
std::shared_ptr<const RestrictionMap> restriction_map,
|
||||
const std::vector<QueryNode> &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<EdgeBasedEdge> &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;
|
||||
}
|
||||
|
@ -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<NodeBasedDynamicGraph> node_based_graph,
|
||||
std::shared_ptr<RestrictionMap> restricion_map,
|
||||
std::unique_ptr<std::vector<NodeID>> barrier_node_list,
|
||||
std::unique_ptr<std::vector<NodeID>> traffic_light_node_list,
|
||||
const GeometryCompressor& geometry_compressor,
|
||||
const std::unordered_set<NodeID>& barrier_nodes,
|
||||
const std::unordered_set<NodeID>& traffic_lights,
|
||||
std::shared_ptr<const RestrictionMap> restriction_map,
|
||||
const std::vector<QueryNode> &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<EdgeBasedEdge> &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<QueryNode>& m_node_info_list;
|
||||
std::shared_ptr<NodeBasedDynamicGraph> m_node_based_graph;
|
||||
std::shared_ptr<RestrictionMap> m_restriction_map;
|
||||
std::shared_ptr<RestrictionMap const> m_restriction_map;
|
||||
|
||||
std::unordered_set<NodeID> m_barrier_nodes;
|
||||
std::unordered_set<NodeID> m_traffic_lights;
|
||||
const std::unordered_set<NodeID>& m_barrier_nodes;
|
||||
const std::unordered_set<NodeID>& 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<OriginalEdgeData> &original_edge_data_vector) const;
|
||||
|
||||
NodeID max_id;
|
||||
std::size_t removed_node_count;
|
||||
|
||||
};
|
||||
|
||||
#endif /* EDGE_BASED_GRAPH_FACTORY_HPP_ */
|
||||
|
187
contractor/graph_compressor.cpp
Normal file
187
contractor/graph_compressor.cpp
Normal file
@ -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<NodeID>& barrier_nodes,
|
||||
const std::unordered_set<NodeID>& 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;
|
||||
}
|
62
contractor/graph_compressor.hpp
Normal file
62
contractor/graph_compressor.hpp
Normal file
@ -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 <memory>
|
||||
#include <unordered_set>
|
||||
|
||||
class GeometryCompressor;
|
||||
class RestrictionMap;
|
||||
|
||||
class GraphCompressor
|
||||
{
|
||||
using EdgeData = NodeBasedDynamicGraph::EdgeData;
|
||||
|
||||
public:
|
||||
GraphCompressor(const SpeedProfileProperties& speed_profile);
|
||||
|
||||
void Compress(const std::unordered_set<NodeID>& barrier_nodes,
|
||||
const std::unordered_set<NodeID>& 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
|
@ -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<std::vector<EdgeBasedNod
|
||||
Also initializes speed profile.
|
||||
*/
|
||||
void Prepare::SetupScriptingEnvironment(
|
||||
lua_State *lua_state, EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile)
|
||||
lua_State *lua_state, SpeedProfileProperties &speed_profile)
|
||||
{
|
||||
// open utility libraries string library;
|
||||
luaL_openlibs(lua_state);
|
||||
@ -319,21 +321,32 @@ std::shared_ptr<RestrictionMap> Prepare::LoadRestrictionMap()
|
||||
\brief Load node based graph from .osrm file
|
||||
*/
|
||||
std::shared_ptr<NodeBasedDynamicGraph>
|
||||
Prepare::LoadNodeBasedGraph(std::vector<NodeID> &barrier_node_list,
|
||||
std::vector<NodeID> &traffic_light_list,
|
||||
Prepare::LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
|
||||
std::unordered_set<NodeID> &traffic_lights,
|
||||
std::vector<QueryNode>& internal_to_external_node_map)
|
||||
{
|
||||
std::vector<NodeBasedEdge> edge_list;
|
||||
|
||||
boost::filesystem::ifstream input_stream(config.osrm_input_path, std::ios::in | std::ios::binary);
|
||||
|
||||
std::vector<NodeID> barrier_list;
|
||||
std::vector<NodeID> 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<QueryNode> &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<std::vector<NodeID>>();
|
||||
auto traffic_light_list = osrm::make_unique<std::vector<NodeID>>();
|
||||
std::unordered_set<NodeID> barrier_nodes;
|
||||
std::unordered_set<NodeID> 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<RestrictionMap const>(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<unsigned>::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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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<RestrictionMap> LoadRestrictionMap();
|
||||
SpeedProfileProperties &speed_profile);
|
||||
unsigned CalculateEdgeChecksum(std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list);
|
||||
void ContractGraph(const std::size_t number_of_edge_based_nodes,
|
||||
DeallocatingVector<EdgeBasedEdge>& edge_based_edge_list,
|
||||
@ -68,9 +68,11 @@ class Prepare
|
||||
std::size_t WriteContractedGraph(unsigned number_of_edge_based_nodes,
|
||||
std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list,
|
||||
std::unique_ptr<DeallocatingVector<QueryEdge>> contracted_edge_list);
|
||||
std::shared_ptr<NodeBasedDynamicGraph> LoadNodeBasedGraph(std::vector<NodeID> &barrier_node_list,
|
||||
std::vector<NodeID> &traffic_light_list,
|
||||
std::vector<QueryNode>& internal_to_external_node_map);
|
||||
std::shared_ptr<RestrictionMap> LoadRestrictionMap();
|
||||
std::shared_ptr<NodeBasedDynamicGraph>
|
||||
LoadNodeBasedGraph(std::unordered_set<NodeID> &barrier_nodes,
|
||||
std::unordered_set<NodeID> &traffic_lights,
|
||||
std::vector<QueryNode>& internal_to_external_node_map);
|
||||
std::pair<std::size_t, std::size_t>
|
||||
BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,
|
||||
std::vector<EdgeBasedNode> &node_based_edge_list,
|
||||
|
16
contractor/speed_profile.hpp
Normal file
16
contractor/speed_profile.hpp
Normal file
@ -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
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user