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:
committed by
Patrick Niklaus
parent
bf6698f4cc
commit
57c6c6e51c
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user