int Contractor::Run() { if (config.core_factor > 1.0 || config.core_factor < 0) { throw util::exception("Core factor must be between 0.0 to 1.0 (inclusive)" + SOURCE_REF); } if (config.use_cached_priority) { util::Log(logWARNING) << "Using cached priorities is deprecated and they will be ignored."; } TIMER_START(preparing); util::Log() << "Reading node weights."; std::vector<EdgeWeight> node_weights; { storage::io::FileReader reader(config.GetPath(".osrm.enw"), storage::io::FileReader::VerifyFingerprint); storage::serialization::read(reader, node_weights); } util::Log() << "Done reading node weights."; util::Log() << "Loading edge-expanded graph representation"; std::vector<extractor::EdgeBasedEdge> edge_based_edge_list; updater::Updater updater(config.updater_config); EdgeID max_edge_id = updater.LoadAndUpdateEdgeExpandedGraph(edge_based_edge_list, node_weights); // Contracting the edge-expanded graph TIMER_START(contraction); std::vector<std::vector<bool>> node_filters; { extractor::EdgeBasedNodeDataContainer node_data; extractor::files::readNodeData(config.GetPath(".osrm.ebg_nodes"), node_data); extractor::ProfileProperties properties; extractor::files::readProfileProperties(config.GetPath(".osrm.properties"), properties); node_filters = util::excludeFlagsToNodeFilter(max_edge_id + 1, node_data, properties); } RangebasedCRC32 crc32_calculator; const unsigned checksum = crc32_calculator(edge_based_edge_list); QueryGraph query_graph; std::vector<std::vector<bool>> edge_filters; std::vector<std::vector<bool>> cores; std::tie(query_graph, edge_filters, cores) = contractExcludableGraph(toContractorGraph(max_edge_id + 1, std::move(edge_based_edge_list)), std::move(node_weights), std::move(node_filters), config.core_factor); TIMER_STOP(contraction); util::Log() << "Contracted graph has " << query_graph.GetNumberOfEdges() << " edges."; util::Log() << "Contraction took " << TIMER_SEC(contraction) << " sec"; files::writeGraph(config.GetPath(".osrm.hsgr"), checksum, query_graph, edge_filters); files::writeCoreMarker(config.GetPath(".osrm.core"), cores); TIMER_STOP(preparing); util::Log() << "Preprocessing : " << TIMER_SEC(preparing) << " seconds"; util::Log() << "finished preprocessing"; return 0; }
std::size_t Contractor::WriteContractedGraph(unsigned max_node_id, const util::DeallocatingVector<QueryEdge> &contracted_edge_list) { // Sorting contracted edges in a way that the static query graph can read some in in-place. tbb::parallel_sort(contracted_edge_list.begin(), contracted_edge_list.end()); const unsigned contracted_edge_count = contracted_edge_list.size(); util::SimpleLogger().Write() << "Serializing compacted graph of " << contracted_edge_count << " edges"; const util::FingerPrint fingerprint = util::FingerPrint::GetValid(); boost::filesystem::ofstream hsgr_output_stream(config.graph_output_path, std::ios::binary); hsgr_output_stream.write((char *)&fingerprint, sizeof(util::FingerPrint)); const NodeID max_used_node_id = [&contracted_edge_list] { NodeID tmp_max = 0; for (const QueryEdge &edge : contracted_edge_list) { BOOST_ASSERT(SPECIAL_NODEID != edge.source); BOOST_ASSERT(SPECIAL_NODEID != edge.target); tmp_max = std::max(tmp_max, edge.source); tmp_max = std::max(tmp_max, edge.target); } return tmp_max; }(); util::SimpleLogger().Write(logDEBUG) << "input graph has " << (max_node_id + 1) << " nodes"; util::SimpleLogger().Write(logDEBUG) << "contracted graph has " << (max_used_node_id + 1) << " nodes"; std::vector<util::StaticGraph<EdgeData>::NodeArrayEntry> node_array; // make sure we have at least one sentinel node_array.resize(max_node_id + 2); util::SimpleLogger().Write() << "Building node array"; util::StaticGraph<EdgeData>::EdgeIterator edge = 0; util::StaticGraph<EdgeData>::EdgeIterator position = 0; util::StaticGraph<EdgeData>::EdgeIterator last_edge; // initializing 'first_edge'-field of nodes: for (const auto node : util::irange(0u, max_used_node_id + 1)) { last_edge = edge; while ((edge < contracted_edge_count) && (contracted_edge_list[edge].source == node)) { ++edge; } node_array[node].first_edge = position; //=edge position += edge - last_edge; // remove } for (const auto sentinel_counter : util::irange<unsigned>(max_used_node_id + 1, node_array.size())) { // sentinel element, guarded against underflow node_array[sentinel_counter].first_edge = contracted_edge_count; } util::SimpleLogger().Write() << "Serializing node array"; RangebasedCRC32 crc32_calculator; const unsigned edges_crc32 = crc32_calculator(contracted_edge_list); util::SimpleLogger().Write() << "Writing CRC32: " << edges_crc32; const unsigned node_array_size = node_array.size(); // serialize crc32, aka checksum hsgr_output_stream.write((char *)&edges_crc32, sizeof(unsigned)); // serialize number of nodes hsgr_output_stream.write((char *)&node_array_size, sizeof(unsigned)); // serialize number of edges hsgr_output_stream.write((char *)&contracted_edge_count, sizeof(unsigned)); // serialize all nodes if (node_array_size > 0) { hsgr_output_stream.write((char *)&node_array[0], sizeof(util::StaticGraph<EdgeData>::NodeArrayEntry) * node_array_size); } // serialize all edges util::SimpleLogger().Write() << "Building edge array"; std::size_t number_of_used_edges = 0; util::StaticGraph<EdgeData>::EdgeArrayEntry current_edge; for (const auto edge : util::irange<std::size_t>(0UL, contracted_edge_list.size())) { // some self-loops are required for oneway handling. Need to assertthat we only keep these // (TODO) // no eigen loops // BOOST_ASSERT(contracted_edge_list[edge].source != contracted_edge_list[edge].target || // node_represents_oneway[contracted_edge_list[edge].source]); current_edge.target = contracted_edge_list[edge].target; current_edge.data = contracted_edge_list[edge].data; // every target needs to be valid BOOST_ASSERT(current_edge.target <= max_used_node_id); #ifndef NDEBUG if (current_edge.data.distance <= 0) { util::SimpleLogger().Write(logWARNING) << "Edge: " << edge << ",source: " << contracted_edge_list[edge].source << ", target: " << contracted_edge_list[edge].target << ", dist: " << current_edge.data.distance; util::SimpleLogger().Write(logWARNING) << "Failed at adjacency list of node " << contracted_edge_list[edge].source << "/" << node_array.size() - 1; return 1; } #endif hsgr_output_stream.write((char *)¤t_edge, sizeof(util::StaticGraph<EdgeData>::EdgeArrayEntry)); ++number_of_used_edges; } return number_of_used_edges; }