Remove all boundary nodes and use simple u-v-stragtegy to pick id

This commit removes all occurences of unconnected boundary nodes
and switches to the simple heuristic of picking U for the forward
and V for the backward node. This performs better than several
fancy heuristics.
This commit is contained in:
Patrick Niklaus
2017-03-15 14:30:12 +00:00
committed by Patrick Niklaus
parent bf6698f4cc
commit 57c6c6e51c
11 changed files with 319 additions and 236 deletions
+4 -11
View File
@@ -10,10 +10,12 @@
#include "extractor/guidance/turn_analysis.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/nbg_to_ebg.hpp"
#include "extractor/original_edge_data.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/query_node.hpp"
#include "extractor/restriction_map.hpp"
#include "util/deallocating_vector.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
@@ -35,7 +37,6 @@
#include <vector>
#include <boost/filesystem/fstream.hpp>
#include <boost/optional.hpp>
namespace osrm
{
@@ -144,7 +145,7 @@ class EdgeBasedGraphFactory
unsigned RenumberEdges();
void GenerateEdgeExpandedNodes(const std::string &nbg_ebg_mapping_path);
std::vector<NBGToEBG> GenerateEdgeExpandedNodes();
void GenerateEdgeExpandedEdges(ScriptingEnvironment &scripting_environment,
const std::string &original_edge_data_filename,
@@ -153,15 +154,7 @@ class EdgeBasedGraphFactory
const std::string &turn_duration_penalties_filename,
const std::string &turn_penalties_index_filename);
// Mapping betweenn the node based graph u,v nodes and the edge based graph head,tail edge ids.
// Required in the osrm-partition tool to translate from a nbg partition to a ebg partition.
struct Mapping
{
NodeID u, v;
EdgeID head, tail;
};
boost::optional<Mapping> InsertEdgeBasedNode(const NodeID u, const NodeID v);
NBGToEBG InsertEdgeBasedNode(const NodeID u, const NodeID v);
void FlushVectorToStream(storage::io::FileWriter &edge_data_file,
std::vector<OriginalEdgeData> &original_edge_data_vector) const;
+22 -4
View File
@@ -2,6 +2,7 @@
#define OSRM_EXTRACTOR_IO_HPP
#include "extractor/datasources.hpp"
#include "extractor/nbg_to_ebg.hpp"
#include "extractor/segment_data_container.hpp"
#include "storage/io.hpp"
@@ -15,7 +16,23 @@ namespace extractor
namespace io
{
void read(const boost::filesystem::path &path, Datasources &sources)
inline void read(const boost::filesystem::path &path, std::vector<NBGToEBG> &mapping)
{
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader{path, fingerprint};
reader.DeserializeVector(mapping);
}
inline void write(const boost::filesystem::path &path, const std::vector<NBGToEBG> &mapping)
{
const auto fingerprint = storage::io::FileWriter::GenerateFingerprint;
storage::io::FileWriter reader{path, fingerprint};
reader.SerializeVector(mapping);
}
inline void read(const boost::filesystem::path &path, Datasources &sources)
{
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
storage::io::FileReader reader{path, fingerprint};
@@ -23,7 +40,7 @@ void read(const boost::filesystem::path &path, Datasources &sources)
reader.ReadInto(sources);
}
void write(const boost::filesystem::path &path, Datasources &sources)
inline void write(const boost::filesystem::path &path, Datasources &sources)
{
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
storage::io::FileWriter writer{path, fingerprint};
@@ -31,7 +48,8 @@ void write(const boost::filesystem::path &path, Datasources &sources)
writer.WriteFrom(sources);
}
template <> void read(const boost::filesystem::path &path, SegmentDataContainer &segment_data)
template <>
inline void read(const boost::filesystem::path &path, SegmentDataContainer &segment_data)
{
const auto fingerprint = storage::io::FileReader::HasNoFingerprint;
storage::io::FileReader reader{path, fingerprint};
@@ -57,7 +75,7 @@ template <> void read(const boost::filesystem::path &path, SegmentDataContainer
}
template <>
void write(const boost::filesystem::path &path, const SegmentDataContainer &segment_data)
inline void write(const boost::filesystem::path &path, const SegmentDataContainer &segment_data)
{
const auto fingerprint = storage::io::FileWriter::HasNoFingerprint;
storage::io::FileWriter writer{path, fingerprint};
+21
View File
@@ -0,0 +1,21 @@
#ifndef OSRM_EXTRACTOR_NBG_TO_EBG_HPP
#define OSRM_EXTRACTOR_NBG_TO_EBG_HPP
#include "util/typedefs.hpp"
namespace osrm
{
namespace extractor
{
// Mapping betweenn the node based graph u,v nodes and the edge based graph head,tail edge ids.
// Required in the osrm-partition tool to translate from a nbg partition to a ebg partition.
struct NBGToEBG
{
NodeID u, v;
NodeID forward_ebg_node, backward_ebg_node;
};
}
}
#endif
@@ -1,63 +0,0 @@
#ifndef NODE_BASED_GRAPH_TO_EDGE_BASED_GRAPH_MAPPING_WRITER_HPP
#define NODE_BASED_GRAPH_TO_EDGE_BASED_GRAPH_MAPPING_WRITER_HPP
#include "storage/io.hpp"
#include "util/log.hpp"
#include "util/typedefs.hpp"
#include <boost/assert.hpp>
#include <cstddef>
#include <string>
namespace osrm
{
namespace extractor
{
// Writes: | Fingerprint | #mappings | u v fwd_node bkw_node | u v fwd_node bkw_node | ..
// - uint64: number of mappings (u, v, fwd_node bkw_node) chunks
// - NodeID u, NodeID v, EdgeID fwd_node, EdgeID bkw_node
struct NodeBasedGraphToEdgeBasedGraphMappingWriter
{
NodeBasedGraphToEdgeBasedGraphMappingWriter(const std::string &path)
: writer{path, storage::io::FileWriter::GenerateFingerprint}, num_written{0}
{
const std::uint64_t dummy{0}; // filled in later
writer.WriteElementCount64(dummy);
}
void WriteMapping(NodeID u, NodeID v, EdgeID fwd_ebg_node, EdgeID bkw_ebg_node)
{
BOOST_ASSERT(u != SPECIAL_NODEID);
BOOST_ASSERT(v != SPECIAL_NODEID);
BOOST_ASSERT(fwd_ebg_node != SPECIAL_EDGEID || bkw_ebg_node != SPECIAL_EDGEID);
writer.WriteOne(u);
writer.WriteOne(v);
writer.WriteOne(fwd_ebg_node);
writer.WriteOne(bkw_ebg_node);
num_written += 1;
}
~NodeBasedGraphToEdgeBasedGraphMappingWriter()
{
if (num_written != 0)
{
writer.SkipToBeginning();
writer.WriteOne(num_written);
}
}
private:
storage::io::FileWriter writer;
std::uint64_t num_written;
};
} // ns extractor
} // ns osrm
#endif // NODE_BASED_GRAPH_TO_EDGE_BASED_GRAPH_MAPPING_WRITER_HPP
+2
View File
@@ -240,6 +240,8 @@ template <bool UseShareMemory> class CellStorageImpl
if (!is_source_node && !is_destination_node)
{
number_of_unconneced++;
util::Log(logWARNING) << "Found unconnected boundary node " << node << "("
<< cell_id << ") on level " << (int)level;
level_destination_boundary.emplace_back(cell_id, node);
}
}
@@ -1,80 +0,0 @@
#ifndef OSRM_NODE_BASED_GRAPH_TO_EDGE_BASED_GRAPH_MAPPING_READER_HPP
#define OSRM_NODE_BASED_GRAPH_TO_EDGE_BASED_GRAPH_MAPPING_READER_HPP
#include "storage/io.hpp"
#include "util/typedefs.hpp"
#include <cstddef>
#include <iterator>
#include <unordered_map>
#include <vector>
#include <boost/assert.hpp>
namespace osrm
{
namespace partition
{
struct NodeBasedGraphToEdgeBasedGraphMapping
{
NodeBasedGraphToEdgeBasedGraphMapping(storage::io::FileReader &reader)
{
// Reads: | Fingerprint | #mappings | u v fwd_node bkw_node | u v fwd_node bkw_node | ..
// - uint64: number of mappings (u, v, fwd_node, bkw_node) chunks
// - NodeID u, NodeID v, EdgeID fwd_node, EdgeID bkw_node
//
// Gets written in NodeBasedGraphToEdgeBasedGraphMappingWriter
const auto num_mappings = reader.ReadElementCount64();
edge_based_node_to_node_based_nodes.reserve(num_mappings * 2);
for (std::uint64_t i{0}; i < num_mappings; ++i)
{
const auto u = reader.ReadOne<NodeID>(); // node based graph `from` node
const auto v = reader.ReadOne<NodeID>(); // node based graph `to` node
const auto fwd_ebg_node = reader.ReadOne<EdgeID>(); // edge based graph forward node
const auto bkw_ebg_node = reader.ReadOne<EdgeID>(); // edge based graph backward node
edge_based_node_to_node_based_nodes.insert({fwd_ebg_node, {u, v}});
edge_based_node_to_node_based_nodes.insert({bkw_ebg_node, {v, u}});
}
}
struct NodeBasedNodes
{
NodeID u, v;
};
NodeBasedNodes Lookup(EdgeID edge_based_node) const
{
auto it = edge_based_node_to_node_based_nodes.find(edge_based_node);
if (it != end(edge_based_node_to_node_based_nodes))
return it->second;
BOOST_ASSERT_MSG(false, "unable to fine edge based node, graph <-> mapping out of sync");
return NodeBasedNodes{SPECIAL_NODEID, SPECIAL_NODEID};
}
private:
std::unordered_map<EdgeID, NodeBasedNodes> edge_based_node_to_node_based_nodes;
};
inline NodeBasedGraphToEdgeBasedGraphMapping
LoadNodeBasedGraphToEdgeBasedGraphMapping(const std::string &path)
{
const auto fingerprint = storage::io::FileReader::VerifyFingerprint;
storage::io::FileReader reader(path, fingerprint);
NodeBasedGraphToEdgeBasedGraphMapping mapping{reader};
return mapping;
}
} // ns partition
} // ns osrm
#endif
+115
View File
@@ -0,0 +1,115 @@
#ifndef OSRM_PARTITION_REMOVE_UNCONNECTED_HPP
#define OSRM_PARTITION_REMOVE_UNCONNECTED_HPP
#include "util/log.hpp"
#include "util/typedefs.hpp"
#include <boost/assert.hpp>
#include <algorithm>
#include <vector>
namespace osrm
{
namespace partition
{
using Partition = std::vector<CellID>;
template <typename GraphT>
std::size_t removeUnconnectedBoundaryNodes(const GraphT &edge_based_graph,
std::vector<Partition> &partitions)
{
auto num_unconnected = 0;
auto could_not_fix = 0;
for (int level_index = partitions.size() - 1; level_index >= 0; level_index--)
{
struct Witness
{
NodeID id;
std::size_t induced_border_edges;
};
std::vector<Witness> witnesses;
for (NodeID node = 0; node < edge_based_graph.GetNumberOfNodes(); ++node)
{
witnesses.clear();
bool is_source = false;
bool is_target = false;
const auto cell_id = partitions[level_index][node];
for (auto edge : edge_based_graph.GetAdjacentEdgeRange(node))
{
const auto data = edge_based_graph.GetEdgeData(edge);
const auto target = edge_based_graph.GetTarget(edge);
const auto target_cell_id = partitions[level_index][target];
if (target_cell_id == cell_id)
{
is_source |= data.forward;
is_target |= data.backward;
}
else
{
witnesses.push_back({target, 0});
}
}
const auto unconnected = witnesses.size() > 0 && !is_source && !is_target;
if (unconnected)
{
num_unconnected++;
if (level_index < static_cast<int>(partitions.size() - 1))
{
auto new_end = std::remove_if(
witnesses.begin(), witnesses.end(), [&](const auto &witness) {
return partitions[level_index + 1][node] !=
partitions[level_index + 1][witness.id];
});
witnesses.resize(new_end - witnesses.begin());
}
if (witnesses.size() == 0)
{
could_not_fix++;
continue;
}
for (auto &witness : witnesses)
{
for (auto edge : edge_based_graph.GetAdjacentEdgeRange(node))
{
auto target = edge_based_graph.GetTarget(edge);
for (auto sublevel_index = level_index; sublevel_index >= 0;
--sublevel_index)
{
if (partitions[sublevel_index][target] !=
partitions[sublevel_index][witness.id])
witness.induced_border_edges++;
}
}
}
auto best_witness = std::min_element(
witnesses.begin(), witnesses.end(), [](const auto &lhs, const auto &rhs) {
return lhs.induced_border_edges < rhs.induced_border_edges;
});
BOOST_ASSERT(best_witness != witnesses.end());
// assign `node` to same subcells as `best_witness`
for (auto sublevel_index = level_index; sublevel_index >= 0; --sublevel_index)
{
partitions[sublevel_index][node] = partitions[sublevel_index][best_witness->id];
}
}
}
}
if (could_not_fix > 0)
util::Log(logWARNING) << "Could not fix " << could_not_fix << " unconnected boundary nodes";
return num_unconnected;
}
}
}
#endif