Move renumbering and edge deduplication in extractor

This commit is contained in:
Patrick Niklaus 2015-05-13 01:26:54 +02:00
parent a57fb4f1ab
commit 3065de63dd
11 changed files with 235 additions and 194 deletions

View File

@ -343,8 +343,14 @@ void EdgeBasedGraphFactory::CompressGeometry()
continue; continue;
} }
if ( // TODO: rename to IsCompatibleTo // this case can happen if two ways with different names overlap
fwd_edge_data1.IsEqualTo(fwd_edge_data2) && rev_edge_data1.IsEqualTo(rev_edge_data2)) 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 == BOOST_ASSERT(m_node_based_graph->GetEdgeData(forward_e1).nameID ==
m_node_based_graph->GetEdgeData(reverse_e1).nameID); m_node_based_graph->GetEdgeData(reverse_e1).nameID);

View File

@ -303,44 +303,38 @@ void Prepare::SetupScriptingEnvironment(
/** /**
\brief Build load restrictions from .restriction file \brief Build load restrictions from .restriction file
*/ */
void Prepare::LoadRestrictionMap(const std::unordered_map<NodeID, NodeID> &external_to_internal_node_map, std::shared_ptr<RestrictionMap> Prepare::LoadRestrictionMap()
RestrictionMap &restriction_map)
{ {
boost::filesystem::ifstream input_stream(config.restrictions_path, std::ios::in | std::ios::binary); boost::filesystem::ifstream input_stream(config.restrictions_path, std::ios::in | std::ios::binary);
std::vector<TurnRestriction> restriction_list; std::vector<TurnRestriction> restriction_list;
loadRestrictionsFromFile(input_stream, external_to_internal_node_map, restriction_list); loadRestrictionsFromFile(input_stream, restriction_list);
SimpleLogger().Write() << " - " << restriction_list.size() << " restrictions."; SimpleLogger().Write() << " - " << restriction_list.size() << " restrictions.";
restriction_map = RestrictionMap(restriction_list); return std::make_shared<RestrictionMap>(restriction_list);
} }
/** /**
\brief Build load node based graph from .osrm file and restrictions from .restrictions file \brief Load node based graph from .osrm file
*/ */
std::shared_ptr<NodeBasedDynamicGraph> std::shared_ptr<NodeBasedDynamicGraph>
Prepare::LoadNodeBasedGraph(std::vector<NodeID> &barrier_node_list, Prepare::LoadNodeBasedGraph(std::vector<NodeID> &barrier_node_list,
std::vector<NodeID> &traffic_light_list, std::vector<NodeID> &traffic_light_list,
RestrictionMap &restriction_map,
std::vector<QueryNode>& internal_to_external_node_map) std::vector<QueryNode>& internal_to_external_node_map)
{ {
std::vector<NodeBasedEdge> edge_list; std::vector<NodeBasedEdge> edge_list;
std::unordered_map<NodeID, NodeID> external_to_internal_node_map;
boost::filesystem::ifstream input_stream(config.osrm_input_path, std::ios::in | std::ios::binary); boost::filesystem::ifstream input_stream(config.osrm_input_path, std::ios::in | std::ios::binary);
NodeID number_of_node_based_nodes = loadNodesFromFile(input_stream, NodeID number_of_node_based_nodes = loadNodesFromFile(input_stream,
barrier_node_list, traffic_light_list, barrier_node_list, traffic_light_list,
internal_to_external_node_map, internal_to_external_node_map);
external_to_internal_node_map);
SimpleLogger().Write() << " - " << barrier_node_list.size() << " bollard nodes, " SimpleLogger().Write() << " - " << barrier_node_list.size() << " bollard nodes, "
<< traffic_light_list.size() << " traffic lights"; << traffic_light_list.size() << " traffic lights";
loadEdgesFromFile(input_stream, external_to_internal_node_map, edge_list); loadEdgesFromFile(input_stream, edge_list);
LoadRestrictionMap(external_to_internal_node_map, restriction_map);
if (edge_list.empty()) if (edge_list.empty())
{ {
@ -369,9 +363,9 @@ Prepare::BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_nod
auto barrier_node_list = osrm::make_unique<std::vector<NodeID>>(); auto barrier_node_list = osrm::make_unique<std::vector<NodeID>>();
auto traffic_light_list = osrm::make_unique<std::vector<NodeID>>(); auto traffic_light_list = osrm::make_unique<std::vector<NodeID>>();
auto restriction_map = std::make_shared<RestrictionMap>();
auto node_based_graph = LoadNodeBasedGraph(*barrier_node_list, *traffic_light_list, *restriction_map, internal_to_external_node_map); auto restriction_map = LoadRestrictionMap();
auto node_based_graph = LoadNodeBasedGraph(*barrier_node_list, *traffic_light_list, internal_to_external_node_map);
const std::size_t number_of_node_based_nodes = node_based_graph->GetNumberOfNodes(); const std::size_t number_of_node_based_nodes = node_based_graph->GetNumberOfNodes();

View File

@ -61,8 +61,7 @@ class Prepare
protected: protected:
void SetupScriptingEnvironment(lua_State *myLuaState, void SetupScriptingEnvironment(lua_State *myLuaState,
EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile); EdgeBasedGraphFactory::SpeedProfileProperties &speed_profile);
void LoadRestrictionMap(const std::unordered_map<NodeID, NodeID> &external_to_internal_node_map, std::shared_ptr<RestrictionMap> LoadRestrictionMap();
RestrictionMap &restriction_map);
unsigned CalculateEdgeChecksum(std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list); unsigned CalculateEdgeChecksum(std::unique_ptr<std::vector<EdgeBasedNode>> node_based_edge_list);
void ContractGraph(const std::size_t number_of_edge_based_nodes, void ContractGraph(const std::size_t number_of_edge_based_nodes,
DeallocatingVector<EdgeBasedEdge>& edge_based_edge_list, DeallocatingVector<EdgeBasedEdge>& edge_based_edge_list,
@ -72,7 +71,6 @@ class Prepare
std::unique_ptr<DeallocatingVector<QueryEdge>> contracted_edge_list); std::unique_ptr<DeallocatingVector<QueryEdge>> contracted_edge_list);
std::shared_ptr<NodeBasedDynamicGraph> LoadNodeBasedGraph(std::vector<NodeID> &barrier_node_list, std::shared_ptr<NodeBasedDynamicGraph> LoadNodeBasedGraph(std::vector<NodeID> &barrier_node_list,
std::vector<NodeID> &traffic_light_list, std::vector<NodeID> &traffic_light_list,
RestrictionMap &restriction_map,
std::vector<QueryNode>& internal_to_external_node_map); std::vector<QueryNode>& internal_to_external_node_map);
std::pair<std::size_t, std::size_t> std::pair<std::size_t, std::size_t>
BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map, BuildEdgeExpandedGraph(std::vector<QueryNode> &internal_to_external_node_map,

View File

@ -47,6 +47,13 @@ bool NodeBasedEdge::operator<(const NodeBasedEdge &other) const
return source < other.source; return source < other.source;
} }
NodeBasedEdge::NodeBasedEdge()
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), forward(false),
backward(false), roundabout(false), in_tiny_cc(false),
access_restricted(false), is_split(false), travel_mode(false)
{
}
NodeBasedEdge::NodeBasedEdge(NodeID source, NodeBasedEdge::NodeBasedEdge(NodeID source,
NodeID target, NodeID target,
NodeID name_id, NodeID name_id,

View File

@ -35,6 +35,7 @@ struct NodeBasedEdge
{ {
bool operator<(const NodeBasedEdge &e) const; bool operator<(const NodeBasedEdge &e) const;
NodeBasedEdge();
explicit NodeBasedEdge(NodeID source, explicit NodeBasedEdge(NodeID source,
NodeID target, NodeID target,
NodeID name_id, NodeID name_id,
@ -58,8 +59,6 @@ struct NodeBasedEdge
bool access_restricted : 1; bool access_restricted : 1;
bool is_split : 1; bool is_split : 1;
TravelMode travel_mode : 4; TravelMode travel_mode : 4;
NodeBasedEdge() = delete;
}; };
struct EdgeBasedEdge struct EdgeBasedEdge

View File

@ -64,7 +64,7 @@ struct NodeBasedEdgeData
backward = temp_flag; backward = temp_flag;
} }
bool IsEqualTo(const NodeBasedEdgeData &other) const bool IsCompatibleTo(const NodeBasedEdgeData &other) const
{ {
return (forward == other.forward) && (backward == other.backward) && return (forward == other.forward) && (backward == other.backward) &&
(nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) && (nameID == other.nameID) && (ignore_in_grid == other.ignore_in_grid) &&
@ -85,6 +85,7 @@ NodeBasedDynamicGraphFromImportEdges(int number_of_nodes, std::vector<NodeBasedE
NodeBasedDynamicGraph::InputEdge edge; NodeBasedDynamicGraph::InputEdge edge;
for (const NodeBasedEdge &import_edge : input_edge_list) for (const NodeBasedEdge &import_edge : input_edge_list)
{ {
BOOST_ASSERT(import_edge.forward || import_edge.backward);
if (import_edge.forward) if (import_edge.forward)
{ {
edge.source = import_edge.source; edge.source = import_edge.source;

View File

@ -79,10 +79,6 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
{ {
try try
{ {
PrepareRestrictions();
WriteRestrictions(restrictions_file_name);
std::ofstream file_out_stream; std::ofstream file_out_stream;
file_out_stream.open(output_file_name.c_str(), std::ios::binary); file_out_stream.open(output_file_name.c_str(), std::ios::binary);
file_out_stream.write((char *)&fingerprint, sizeof(FingerPrint)); file_out_stream.write((char *)&fingerprint, sizeof(FingerPrint));
@ -94,6 +90,9 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
file_out_stream.close(); file_out_stream.close();
PrepareRestrictions();
WriteRestrictions(restrictions_file_name);
WriteNames(name_file_name); WriteNames(name_file_name);
} }
catch (const std::exception &e) catch (const std::exception &e)
@ -151,6 +150,14 @@ void ExtractionContainers::PrepareNodes()
TIMER_STOP(erasing_dups); TIMER_STOP(erasing_dups);
std::cout << "ok, after " << TIMER_SEC(erasing_dups) << "s" << std::endl; std::cout << "ok, after " << TIMER_SEC(erasing_dups) << "s" << std::endl;
std::cout << "[extractor] Building node id map ... " << std::flush;
TIMER_START(id_map);
external_to_internal_node_id_map.reserve(used_node_id_list.size());
for (NodeID i = 0u; i < used_node_id_list.size(); ++i)
external_to_internal_node_id_map[used_node_id_list[i]] = i;
TIMER_STOP(id_map);
std::cout << "ok, after " << TIMER_SEC(id_map) << "s" << std::endl;
std::cout << "[extractor] Sorting all nodes ... " << std::flush; std::cout << "[extractor] Sorting all nodes ... " << std::flush;
TIMER_START(sorting_nodes); TIMER_START(sorting_nodes);
stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), ExternalMemoryNodeSTXXLCompare(), stxxl::sort(all_nodes_list.begin(), all_nodes_list.end(), ExternalMemoryNodeSTXXLCompare(),
@ -187,6 +194,12 @@ void ExtractionContainers::PrepareEdges()
} }
BOOST_ASSERT(edge_iterator->result.source == node_iterator->node_id); BOOST_ASSERT(edge_iterator->result.source == node_iterator->node_id);
// assign new node id
auto id_iter = external_to_internal_node_id_map.find(node_iterator->node_id);
BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end());
edge_iterator->result.source = id_iter->second;
edge_iterator->source_coordinate.lat = node_iterator->lat; edge_iterator->source_coordinate.lat = node_iterator->lat;
edge_iterator->source_coordinate.lon = node_iterator->lon; edge_iterator->source_coordinate.lon = node_iterator->lon;
++edge_iterator; ++edge_iterator;
@ -211,6 +224,10 @@ void ExtractionContainers::PrepareEdges()
{ {
if (edge_iterator->result.target < node_iterator->node_id) if (edge_iterator->result.target < node_iterator->node_id)
{ {
// mark edge as invalid
edge_iterator->result.source = SPECIAL_NODEID;
edge_iterator->result.target = SPECIAL_NODEID;
// FIXME we are skipping edges here: That means the data is broken! // FIXME we are skipping edges here: That means the data is broken!
++edge_iterator; ++edge_iterator;
continue; continue;
@ -246,12 +263,113 @@ void ExtractionContainers::PrepareEdges()
return -1.0; return -1.0;
}(edge_iterator->weight_data); }(edge_iterator->weight_data);
edge_iterator->result.weight = std::max(1, (int)std::floor(weight + .5)); auto& edge = edge_iterator->result;
edge.weight = std::max(1, (int)std::floor(weight + .5));
// assign new node id
auto id_iter = external_to_internal_node_id_map.find(node_iterator->node_id);
BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end());
edge.target = id_iter->second;
// if source id > target id -> swap
if (edge.source > edge.target)
{
std::swap(edge.source, edge.target);
// std::swap does not work with bit-fields
bool temp = edge.forward;
edge.forward = edge.backward;
edge.backward = temp;
}
}
else
{
// mark edge as invalid
edge_iterator->result.source = SPECIAL_NODEID;
edge_iterator->result.target = SPECIAL_NODEID;
// FIXME we should print a warning here.
} }
++edge_iterator; ++edge_iterator;
} }
TIMER_STOP(compute_weights); TIMER_STOP(compute_weights);
std::cout << "ok, after " << TIMER_SEC(compute_weights) << "s" << std::endl; std::cout << "ok, after " << TIMER_SEC(compute_weights) << "s" << std::endl;
// Sort edges by start.
std::cout << "[extractor] Sorting edges by renumbered start ... " << std::flush;
TIMER_START(sort_edges_by_renumbered_start);
stxxl::sort(all_edges_list.begin(), all_edges_list.end(), CmpEdgeByStartThenTargetID(), stxxl_memory);
TIMER_STOP(sort_edges_by_renumbered_start);
std::cout << "ok, after " << TIMER_SEC(sort_edges_by_renumbered_start) << "s" << std::endl;
BOOST_ASSERT(all_edges_list.size() > 0);
for (unsigned i = 1; i < all_edges_list.size();)
{
// only invalid edges left
if (all_edges_list[i].result.source == SPECIAL_NODEID)
{
break;
}
unsigned start_idx = i;
NodeID source = all_edges_list[i].result.source;
NodeID target = all_edges_list[i].result.target;
int min_forward_weight = std::numeric_limits<int>::max();
int min_backward_weight = std::numeric_limits<int>::max();
unsigned min_forward_idx = std::numeric_limits<unsigned>::max();
unsigned min_backward_idx = std::numeric_limits<unsigned>::max();
while (all_edges_list[i].result.source == source &&
all_edges_list[i].result.target == target)
{
if (all_edges_list[i].result.forward && all_edges_list[i].result.weight < min_forward_weight)
{
min_forward_idx = i;
}
if (all_edges_list[i].result.backward && all_edges_list[i].result.weight < min_backward_weight)
{
min_backward_idx = i;
}
// this also increments the outer loop counter!
i++;
}
BOOST_ASSERT(min_forward_idx == std::numeric_limits<unsigned>::max() || min_forward_idx < i);
BOOST_ASSERT(min_backward_idx == std::numeric_limits<unsigned>::max() || min_backward_idx < i);
// reset direction for both edges
if (min_forward_idx != std::numeric_limits<unsigned>::max())
{
all_edges_list[min_forward_idx].result.forward = false;
all_edges_list[min_forward_idx].result.backward = false;
}
if (min_backward_idx != std::numeric_limits<unsigned>::max())
{
all_edges_list[min_backward_idx].result.forward = false;
all_edges_list[min_backward_idx].result.backward = false;
}
// set directions that were chosen as min
// note that this needs to come after the ifs above, since
// the minimal forward and backward edge can be the same
if (min_forward_idx != std::numeric_limits<unsigned>::max())
all_edges_list[min_forward_idx].result.forward = true;
if (min_backward_idx != std::numeric_limits<unsigned>::max())
all_edges_list[min_backward_idx].result.backward = true;
// invalidate all unused edges
for (unsigned j = start_idx; j < i; j++)
{
if (j == min_forward_idx || j == min_backward_idx)
{
continue;
}
all_edges_list[j].result.source = SPECIAL_NODEID;
all_edges_list[j].result.target = SPECIAL_NODEID;
}
}
} }
void ExtractionContainers::WriteEdges(std::ofstream& file_out_stream) const void ExtractionContainers::WriteEdges(std::ofstream& file_out_stream) const
@ -266,11 +384,13 @@ void ExtractionContainers::WriteEdges(std::ofstream& file_out_stream) const
for (const auto& edge : all_edges_list) for (const auto& edge : all_edges_list)
{ {
if (edge.result.weight > 0) if (edge.result.source == SPECIAL_NODEID || edge.result.target == SPECIAL_NODEID)
{ {
file_out_stream.write((char*) &edge.result, sizeof(NodeBasedEdge)); continue;
number_of_used_edges++;
} }
file_out_stream.write((char*) &edge.result, sizeof(NodeBasedEdge));
number_of_used_edges++;
} }
TIMER_STOP(write_edges); TIMER_STOP(write_edges);
std::cout << "ok, after " << TIMER_SEC(write_edges) << "s" << std::endl; std::cout << "ok, after " << TIMER_SEC(write_edges) << "s" << std::endl;
@ -339,6 +459,7 @@ void ExtractionContainers::WriteRestrictions(const std::string& path) const
for (const auto &restriction_container : restrictions_list) for (const auto &restriction_container : restrictions_list)
{ {
if (SPECIAL_NODEID != restriction_container.restriction.from.node && if (SPECIAL_NODEID != restriction_container.restriction.from.node &&
SPECIAL_NODEID != restriction_container.restriction.via.node &&
SPECIAL_NODEID != restriction_container.restriction.to.node) SPECIAL_NODEID != restriction_container.restriction.to.node)
{ {
restrictions_out_stream.write((char *)&(restriction_container.restriction), restrictions_out_stream.write((char *)&(restriction_container.restriction),
@ -362,7 +483,7 @@ void ExtractionContainers::PrepareRestrictions()
std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl; std::cout << "ok, after " << TIMER_SEC(sort_ways) << "s" << std::endl;
std::cout << "[extractor] Sorting " << restrictions_list.size() std::cout << "[extractor] Sorting " << restrictions_list.size()
<< " restrictions. by from... " << std::flush; << " restriction. by from... " << std::flush;
TIMER_START(sort_restrictions); TIMER_START(sort_restrictions);
stxxl::sort(restrictions_list.begin(), restrictions_list.end(), stxxl::sort(restrictions_list.begin(), restrictions_list.end(),
CmpRestrictionContainerByFrom(), stxxl_memory); CmpRestrictionContainerByFrom(), stxxl_memory);
@ -385,23 +506,42 @@ void ExtractionContainers::PrepareRestrictions()
if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.from.way) if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.from.way)
{ {
SimpleLogger().Write(LogLevel::logDEBUG) << "Restriction references invalid way: " << restrictions_iterator->restriction.from.way;
restrictions_iterator->restriction.from.node = SPECIAL_NODEID;
++restrictions_iterator; ++restrictions_iterator;
continue; continue;
} }
BOOST_ASSERT(way_start_and_end_iterator->way_id == BOOST_ASSERT(way_start_and_end_iterator->way_id ==
restrictions_iterator->restriction.from.way); restrictions_iterator->restriction.from.way);
// we do not remap the via id yet, since we will need it for the to node as well
const NodeID via_node_id = restrictions_iterator->restriction.via.node; const NodeID via_node_id = restrictions_iterator->restriction.via.node;
// check if via is actually valid, if not invalidate
auto via_id_iter = external_to_internal_node_id_map.find(via_node_id);
if(via_id_iter == external_to_internal_node_id_map.end())
{
SimpleLogger().Write(LogLevel::logDEBUG) << "Restriction references invalid node: " << restrictions_iterator->restriction.via.node;
restrictions_iterator->restriction.via.node = SPECIAL_NODEID;
++restrictions_iterator;
continue;
}
if (way_start_and_end_iterator->first_segment_source_id == via_node_id) if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
{ {
restrictions_iterator->restriction.from.node = // assign new from node id
way_start_and_end_iterator->first_segment_target_id; auto id_iter = external_to_internal_node_id_map.find(
way_start_and_end_iterator->first_segment_target_id);
BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end());
restrictions_iterator->restriction.from.node = id_iter->second;
} }
else if (way_start_and_end_iterator->last_segment_target_id == via_node_id) else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
{ {
restrictions_iterator->restriction.from.node = // assign new from node id
way_start_and_end_iterator->last_segment_source_id; auto id_iter = external_to_internal_node_id_map.find(
way_start_and_end_iterator->last_segment_source_id);
BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end());
restrictions_iterator->restriction.from.node = id_iter->second;
} }
++restrictions_iterator; ++restrictions_iterator;
} }
@ -428,8 +568,16 @@ void ExtractionContainers::PrepareRestrictions()
++way_start_and_end_iterator; ++way_start_and_end_iterator;
continue; continue;
} }
if (restrictions_iterator->restriction.from.node == SPECIAL_NODEID ||
restrictions_iterator->restriction.via.node == SPECIAL_NODEID)
{
++restrictions_iterator;
continue;
}
if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.to.way) if (way_start_and_end_iterator->way_id > restrictions_iterator->restriction.to.way)
{ {
SimpleLogger().Write(LogLevel::logDEBUG) << "Restriction references invalid way: " << restrictions_iterator->restriction.to.way;
restrictions_iterator->restriction.to.way = SPECIAL_NODEID;
++restrictions_iterator; ++restrictions_iterator;
continue; continue;
} }
@ -437,15 +585,24 @@ void ExtractionContainers::PrepareRestrictions()
restrictions_iterator->restriction.to.way); restrictions_iterator->restriction.to.way);
const NodeID via_node_id = restrictions_iterator->restriction.via.node; const NodeID via_node_id = restrictions_iterator->restriction.via.node;
// assign new via node id
auto via_id_iter = external_to_internal_node_id_map.find(via_node_id);
BOOST_ASSERT(via_id_iter != external_to_internal_node_id_map.end());
restrictions_iterator->restriction.via.node = via_id_iter->second;
if (way_start_and_end_iterator->first_segment_source_id == via_node_id) if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
{ {
restrictions_iterator->restriction.to.node = auto to_id_iter = external_to_internal_node_id_map.find(
way_start_and_end_iterator->first_segment_target_id; way_start_and_end_iterator->first_segment_target_id);
BOOST_ASSERT(to_id_iter != external_to_internal_node_id_map.end());
restrictions_iterator->restriction.to.node = to_id_iter->second;
} }
else if (way_start_and_end_iterator->last_segment_target_id == via_node_id) else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
{ {
restrictions_iterator->restriction.to.node = auto to_id_iter = external_to_internal_node_id_map.find(
way_start_and_end_iterator->last_segment_source_id; way_start_and_end_iterator->last_segment_source_id);
BOOST_ASSERT(to_id_iter != external_to_internal_node_id_map.end());
restrictions_iterator->restriction.to.node = to_id_iter->second;
} }
++restrictions_iterator; ++restrictions_iterator;
} }

View File

@ -35,6 +35,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "../util/fingerprint.hpp" #include "../util/fingerprint.hpp"
#include <stxxl/vector> #include <stxxl/vector>
#include <unordered_map>
/** /**
* Uses external memory containers from stxxl to store all the data that * Uses external memory containers from stxxl to store all the data that
@ -73,6 +74,7 @@ class ExtractionContainers
STXXLStringVector name_list; STXXLStringVector name_list;
STXXLRestrictionsVector restrictions_list; STXXLRestrictionsVector restrictions_list;
STXXLWayIDStartEndVector way_start_end_id_list; STXXLWayIDStartEndVector way_start_end_id_list;
std::unordered_map<NodeID, NodeID> external_to_internal_node_id_map;
const FingerPrint fingerprint; const FingerPrint fingerprint;
ExtractionContainers(); ExtractionContainers();

View File

@ -105,6 +105,20 @@ struct InternalExtractorEdge
} }
}; };
struct CmpEdgeByStartThenTargetID
{
using value_type = InternalExtractorEdge;
bool operator()(const InternalExtractorEdge &lhs, const InternalExtractorEdge &rhs) const
{
return (lhs.result.source < rhs.result.source) ||
((lhs.result.source == rhs.result.source) &&
(lhs.result.target < rhs.result.target));
}
value_type max_value() { return InternalExtractorEdge::max_value(); }
value_type min_value() { return InternalExtractorEdge::min_value(); }
};
struct CmpEdgeByStartID struct CmpEdgeByStartID
{ {
using value_type = InternalExtractorEdge; using value_type = InternalExtractorEdge;

View File

@ -76,22 +76,19 @@ void DeleteFileIfExists(const std::string &file_name)
} }
} }
void LoadRestrictions(const char* path, void LoadRestrictions(const char* path, std::vector<TurnRestriction>& restriction_list)
std::unique_ptr<std::unordered_map<NodeID, NodeID>> ext_to_int_id_map,
std::vector<TurnRestriction>& restriction_list)
{ {
std::ifstream input_stream(path, std::ios::binary); std::ifstream input_stream(path, std::ios::binary);
if (!input_stream.is_open()) if (!input_stream.is_open())
{ {
throw osrm::exception("Cannot open restriction file"); throw osrm::exception("Cannot open restriction file");
} }
loadRestrictionsFromFile(input_stream, *ext_to_int_id_map, restriction_list); loadRestrictionsFromFile(input_stream, restriction_list);
} }
std::size_t LoadGraph(const char* path, std::size_t LoadGraph(const char* path,
std::vector<QueryNode>& coordinate_list, std::vector<QueryNode>& coordinate_list,
std::vector<NodeID>& barrier_node_list, std::vector<NodeID>& barrier_node_list,
std::unordered_map<NodeID, NodeID>& ext_to_int_id_map,
std::vector<TarjanEdge>& graph_edge_list) std::vector<TarjanEdge>& graph_edge_list)
{ {
std::ifstream input_stream(path, std::ifstream::in | std::ifstream::binary); std::ifstream input_stream(path, std::ifstream::in | std::ifstream::binary);
@ -106,10 +103,9 @@ std::size_t LoadGraph(const char* path,
auto number_of_nodes = loadNodesFromFile(input_stream, barrier_node_list, auto number_of_nodes = loadNodesFromFile(input_stream, barrier_node_list,
traffic_light_node_list, traffic_light_node_list,
coordinate_list, coordinate_list);
ext_to_int_id_map);
loadEdgesFromFile(input_stream, ext_to_int_id_map, edge_list); loadEdgesFromFile(input_stream, edge_list);
traffic_light_node_list.clear(); traffic_light_node_list.clear();
traffic_light_node_list.shrink_to_fit(); traffic_light_node_list.shrink_to_fit();
@ -142,7 +138,6 @@ int main(int argc, char *argv[])
std::vector<QueryNode> coordinate_list; std::vector<QueryNode> coordinate_list;
std::vector<TurnRestriction> restriction_list; std::vector<TurnRestriction> restriction_list;
std::vector<NodeID> barrier_node_list; std::vector<NodeID> barrier_node_list;
auto ext_to_int_id_map = osrm::make_unique<std::unordered_map<NodeID, NodeID>>();
LogPolicy::GetInstance().Unmute(); LogPolicy::GetInstance().Unmute();
try try
@ -158,8 +153,8 @@ int main(int argc, char *argv[])
SimpleLogger().Write() << "Using restrictions from file: " << argv[2]; SimpleLogger().Write() << "Using restrictions from file: " << argv[2];
std::vector<TarjanEdge> graph_edge_list; std::vector<TarjanEdge> graph_edge_list;
auto number_of_nodes = LoadGraph(argv[1], coordinate_list, barrier_node_list, *ext_to_int_id_map, graph_edge_list); auto number_of_nodes = LoadGraph(argv[1], coordinate_list, barrier_node_list, graph_edge_list);
LoadRestrictions(argv[2], std::move(ext_to_int_id_map), restriction_list); LoadRestrictions(argv[2], restriction_list);
tbb::parallel_sort(graph_edge_list.begin(), graph_edge_list.end()); tbb::parallel_sort(graph_edge_list.begin(), graph_edge_list.end());
const auto graph = std::make_shared<TarjanGraph>(number_of_nodes, graph_edge_list); const auto graph = std::make_shared<TarjanGraph>(number_of_nodes, graph_edge_list);

View File

@ -58,7 +58,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* we need to renumber it to the new internal id. * we need to renumber it to the new internal id.
*/ */
unsigned loadRestrictionsFromFile(std::istream& input_stream, unsigned loadRestrictionsFromFile(std::istream& input_stream,
const std::unordered_map<NodeID, NodeID>& ext_to_int_id_map,
std::vector<TurnRestriction>& restriction_list) std::vector<TurnRestriction>& restriction_list)
{ {
const FingerPrint fingerprint_orig; const FingerPrint fingerprint_orig;
@ -79,38 +78,6 @@ unsigned loadRestrictionsFromFile(std::istream& input_stream,
number_of_usable_restrictions * sizeof(TurnRestriction)); number_of_usable_restrictions * sizeof(TurnRestriction));
} }
// renumber ids referenced in restrictions
for (TurnRestriction &current_restriction : restriction_list)
{
auto internal_id_iter = ext_to_int_id_map.find(current_restriction.from.node);
if (internal_id_iter == ext_to_int_id_map.end())
{
SimpleLogger().Write(logDEBUG) << "Unmapped from node " << current_restriction.from.node
<< " of restriction";
continue;
}
current_restriction.from.node = internal_id_iter->second;
internal_id_iter = ext_to_int_id_map.find(current_restriction.via.node);
if (internal_id_iter == ext_to_int_id_map.end())
{
SimpleLogger().Write(logDEBUG) << "Unmapped via node " << current_restriction.via.node
<< " of restriction";
continue;
}
current_restriction.via.node = internal_id_iter->second;
internal_id_iter = ext_to_int_id_map.find(current_restriction.to.node);
if (internal_id_iter == ext_to_int_id_map.end())
{
SimpleLogger().Write(logDEBUG) << "Unmapped to node " << current_restriction.to.node
<< " of restriction";
continue;
}
current_restriction.to.node = internal_id_iter->second;
}
return number_of_usable_restrictions; return number_of_usable_restrictions;
} }
@ -119,14 +86,12 @@ unsigned loadRestrictionsFromFile(std::istream& input_stream,
* Reads the beginning of an .osrm file and produces: * Reads the beginning of an .osrm file and produces:
* - list of barrier nodes * - list of barrier nodes
* - list of traffic lights * - list of traffic lights
* - index to original node id map * - nodes indexed by their internal (non-osm) id
* - original node id to index map
*/ */
NodeID loadNodesFromFile(std::istream &input_stream, NodeID loadNodesFromFile(std::istream &input_stream,
std::vector<NodeID> &barrier_node_list, std::vector<NodeID> &barrier_node_list,
std::vector<NodeID> &traffic_light_node_list, std::vector<NodeID> &traffic_light_node_list,
std::vector<QueryNode> &int_to_ext_node_id_map, std::vector<QueryNode> &node_array)
std::unordered_map<NodeID, NodeID> &ext_to_int_id_map)
{ {
const FingerPrint fingerprint_orig; const FingerPrint fingerprint_orig;
FingerPrint fingerprint_loaded; FingerPrint fingerprint_loaded;
@ -146,9 +111,7 @@ NodeID loadNodesFromFile(std::istream &input_stream,
for (NodeID i = 0; i < n; ++i) for (NodeID i = 0; i < n; ++i)
{ {
input_stream.read(reinterpret_cast<char *>(&current_node), sizeof(ExternalMemoryNode)); input_stream.read(reinterpret_cast<char *>(&current_node), sizeof(ExternalMemoryNode));
int_to_ext_node_id_map.emplace_back(current_node.lat, current_node.lon, node_array.emplace_back(current_node.lat, current_node.lon, current_node.node_id);
current_node.node_id);
ext_to_int_id_map.emplace(current_node.node_id, i);
if (current_node.barrier) if (current_node.barrier)
{ {
barrier_node_list.emplace_back(i); barrier_node_list.emplace_back(i);
@ -167,122 +130,27 @@ NodeID loadNodesFromFile(std::istream &input_stream,
} }
/** /**
* Reads a .osrm file and produces the edges. Edges reference nodes in the old * Reads a .osrm file and produces the edges.
* OSM based format, we need to renumber it here.
*/ */
NodeID loadEdgesFromFile(std::istream &input_stream, NodeID loadEdgesFromFile(std::istream &input_stream,
const std::unordered_map<NodeID, NodeID> &ext_to_int_id_map,
std::vector<NodeBasedEdge> &edge_list) std::vector<NodeBasedEdge> &edge_list)
{ {
EdgeID m; EdgeID m;
input_stream.read(reinterpret_cast<char *>(&m), sizeof(unsigned)); input_stream.read(reinterpret_cast<char *>(&m), sizeof(unsigned));
edge_list.reserve(m); edge_list.resize(m);
SimpleLogger().Write() << " and " << m << " edges "; SimpleLogger().Write() << " and " << m << " edges ";
NodeBasedEdge edge(0, 0, 0, 0, false, false, false, false, false, TRAVEL_MODE_INACCESSIBLE, false); input_stream.read((char *) edge_list.data(), m * sizeof(NodeBasedEdge));
for (EdgeID i = 0; i < m; ++i)
#ifndef NDEBUG
for (const auto& edge : edge_list)
{ {
input_stream.read(reinterpret_cast<char *>(&edge), sizeof(NodeBasedEdge));
BOOST_ASSERT_MSG(edge.weight > 0, "loaded null weight"); BOOST_ASSERT_MSG(edge.weight > 0, "loaded null weight");
BOOST_ASSERT_MSG(edge.forward || edge.backward, "loaded null weight"); BOOST_ASSERT_MSG(edge.forward || edge.backward, "loaded invalid direction");
BOOST_ASSERT_MSG(edge.travel_mode != TRAVEL_MODE_INACCESSIBLE, "loaded null weight"); BOOST_ASSERT_MSG(edge.travel_mode != TRAVEL_MODE_INACCESSIBLE, "loaded non-accessible");
// translate the external NodeIDs to internal IDs
auto internal_id_iter = ext_to_int_id_map.find(edge.source);
if (ext_to_int_id_map.find(edge.source) == ext_to_int_id_map.end())
{
#ifndef NDEBUG
SimpleLogger().Write(logWARNING) << " unresolved source NodeID: " << edge.source;
#endif
continue;
}
edge.source = internal_id_iter->second;
internal_id_iter = ext_to_int_id_map.find(edge.target);
if (ext_to_int_id_map.find(edge.target) == ext_to_int_id_map.end())
{
#ifndef NDEBUG
SimpleLogger().Write(logWARNING) << "unresolved target NodeID : " << edge.target;
#endif
continue;
}
edge.target = internal_id_iter->second;
BOOST_ASSERT_MSG(edge.source != SPECIAL_NODEID && edge.target != SPECIAL_NODEID,
"nonexisting source or target");
if (edge.source > edge.target)
{
std::swap(edge.source, edge.target);
// std::swap does not work with bit-fields
bool temp = edge.forward;
edge.forward = edge.backward;
edge.backward = temp;
}
edge_list.push_back(edge);
} }
#endif
tbb::parallel_sort(edge_list.begin(), edge_list.end());
// Removes multi-edges between nodes
for (unsigned i = 1; i < edge_list.size(); ++i)
{
if ((edge_list[i - 1].target == edge_list[i].target) &&
(edge_list[i - 1].source == edge_list[i].source))
{
const bool edge_flags_equivalent = (edge_list[i - 1].forward == edge_list[i].forward) &&
(edge_list[i - 1].backward == edge_list[i].backward);
const bool edge_flags_are_superset1 =
(edge_list[i - 1].forward && edge_list[i - 1].backward) &&
(edge_list[i].forward != edge_list[i].backward);
const bool edge_flags_are_superset_2 =
(edge_list[i].forward && edge_list[i].backward) &&
(edge_list[i - 1].forward != edge_list[i - 1].backward);
if (edge_flags_equivalent)
{
edge_list[i].weight = std::min(edge_list[i - 1].weight, edge_list[i].weight);
edge_list[i - 1].source = SPECIAL_NODEID;
}
else if (edge_flags_are_superset1)
{
if (edge_list[i - 1].weight <= edge_list[i].weight)
{
// edge i-1 is smaller and goes in both directions. Throw away the other edge
edge_list[i].source = SPECIAL_NODEID;
}
else
{
// edge i-1 is open in both directions, but edge i is smaller in one direction.
// Close edge i-1 in this direction
edge_list[i - 1].forward = !edge_list[i].forward;
edge_list[i - 1].backward = !edge_list[i].backward;
}
}
else if (edge_flags_are_superset_2)
{
if (edge_list[i - 1].weight <= edge_list[i].weight)
{
// edge i-1 is smaller for one direction. edge i is open in both. close edge i
// in the other direction
edge_list[i].forward = !edge_list[i - 1].forward;
edge_list[i].backward = !edge_list[i - 1].backward;
}
else
{
// edge i is smaller and goes in both direction. Throw away edge i-1
edge_list[i - 1].source = SPECIAL_NODEID;
}
}
}
}
const auto new_end_iter =
std::remove_if(edge_list.begin(), edge_list.end(), [](const NodeBasedEdge &edge)
{
return edge.source == SPECIAL_NODEID || edge.target == SPECIAL_NODEID;
});
edge_list.erase(new_end_iter, edge_list.end()); // remove excess candidates.
edge_list.shrink_to_fit();
SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges"; SimpleLogger().Write() << "Graph loaded ok and has " << edge_list.size() << " edges";
return m; return m;