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
@@ -2,7 +2,7 @@
|
||||
#include "extractor/edge_based_edge.hpp"
|
||||
#include "extractor/guidance/turn_analysis.hpp"
|
||||
#include "extractor/guidance/turn_lane_handler.hpp"
|
||||
#include "extractor/node_based_graph_to_edge_based_graph_mapping_writer.hpp"
|
||||
#include "extractor/io.hpp"
|
||||
#include "extractor/scripting_environment.hpp"
|
||||
#include "extractor/suffix_table.hpp"
|
||||
|
||||
@@ -94,8 +94,7 @@ void EdgeBasedGraphFactory::GetEdgeBasedNodeWeights(std::vector<EdgeWeight> &out
|
||||
|
||||
EdgeID EdgeBasedGraphFactory::GetHighestEdgeID() { return m_max_edge_id; }
|
||||
|
||||
boost::optional<EdgeBasedGraphFactory::Mapping>
|
||||
EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID node_v)
|
||||
NBGToEBG EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID node_v)
|
||||
{
|
||||
// merge edges together into one EdgeBasedNode
|
||||
BOOST_ASSERT(node_u != SPECIAL_NODEID);
|
||||
@@ -113,10 +112,7 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID nod
|
||||
|
||||
const EdgeData &reverse_data = m_node_based_graph->GetEdgeData(edge_id_2);
|
||||
|
||||
if (forward_data.edge_id == SPECIAL_NODEID && reverse_data.edge_id == SPECIAL_NODEID)
|
||||
{
|
||||
return boost::none;
|
||||
}
|
||||
BOOST_ASSERT(forward_data.edge_id != SPECIAL_NODEID || reverse_data.edge_id != SPECIAL_NODEID);
|
||||
|
||||
if (forward_data.edge_id != SPECIAL_NODEID && reverse_data.edge_id == SPECIAL_NODEID)
|
||||
m_edge_based_node_weights[forward_data.edge_id] = INVALID_EDGE_WEIGHT;
|
||||
@@ -176,7 +172,7 @@ EdgeBasedGraphFactory::InsertEdgeBasedNode(const NodeID node_u, const NodeID nod
|
||||
|
||||
BOOST_ASSERT(current_edge_source_coordinate_id == node_v);
|
||||
|
||||
return Mapping{node_u, node_v, forward_data.edge_id, reverse_data.edge_id};
|
||||
return NBGToEBG{node_u, node_v, forward_data.edge_id, reverse_data.edge_id};
|
||||
}
|
||||
|
||||
void EdgeBasedGraphFactory::FlushVectorToStream(
|
||||
@@ -207,7 +203,10 @@ void EdgeBasedGraphFactory::Run(ScriptingEnvironment &scripting_environment,
|
||||
|
||||
TIMER_START(generate_nodes);
|
||||
m_edge_based_node_weights.reserve(m_max_edge_id + 1);
|
||||
GenerateEdgeExpandedNodes(cnbg_ebg_mapping_path);
|
||||
{
|
||||
auto mapping = GenerateEdgeExpandedNodes();
|
||||
io::write(cnbg_ebg_mapping_path, mapping);
|
||||
}
|
||||
TIMER_STOP(generate_nodes);
|
||||
|
||||
TIMER_START(generate_edges);
|
||||
@@ -259,12 +258,9 @@ unsigned EdgeBasedGraphFactory::RenumberEdges()
|
||||
}
|
||||
|
||||
/// Creates the nodes in the edge expanded graph from edges in the node-based graph.
|
||||
void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes(const std::string &cnbg_ebg_mapping_path)
|
||||
std::vector<NBGToEBG> EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
|
||||
{
|
||||
// Optional writer, for writing out a mapping. Neither default ctor not boost::optional work
|
||||
// with the underlying FileWriter, so hack around that limitation with a unique_ptr.
|
||||
std::unique_ptr<NodeBasedGraphToEdgeBasedGraphMappingWriter> writer;
|
||||
writer = std::make_unique<NodeBasedGraphToEdgeBasedGraphMappingWriter>(cnbg_ebg_mapping_path);
|
||||
std::vector<NBGToEBG> mapping;
|
||||
|
||||
util::Log() << "Generating edge expanded nodes ... ";
|
||||
{
|
||||
@@ -295,21 +291,14 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes(const std::string &cnbg_eb
|
||||
|
||||
BOOST_ASSERT(node_u < node_v);
|
||||
|
||||
boost::optional<Mapping> mapping;
|
||||
|
||||
// if we found a non-forward edge reverse and try again
|
||||
if (edge_data.edge_id == SPECIAL_NODEID)
|
||||
{
|
||||
mapping = InsertEdgeBasedNode(node_v, node_u);
|
||||
mapping.push_back(InsertEdgeBasedNode(node_v, node_u));
|
||||
}
|
||||
else
|
||||
{
|
||||
mapping = InsertEdgeBasedNode(node_u, node_v);
|
||||
}
|
||||
|
||||
if (mapping)
|
||||
{
|
||||
writer->WriteMapping(mapping->u, mapping->v, mapping->head, mapping->tail);
|
||||
mapping.push_back(InsertEdgeBasedNode(node_u, node_v));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -319,6 +308,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes(const std::string &cnbg_eb
|
||||
BOOST_ASSERT(m_max_edge_id + 1 == m_edge_based_node_weights.size());
|
||||
|
||||
util::Log() << "Generated " << m_edge_based_node_list.size() << " nodes in edge-expanded graph";
|
||||
|
||||
return mapping;
|
||||
}
|
||||
|
||||
/// Actually it also generates OriginalEdgeData and serializes them...
|
||||
|
||||
@@ -42,6 +42,7 @@ Partition cellsToPartition(const std::vector<CellBisection> &cells,
|
||||
[&partition, cell_id](const auto node_id) { partition[node_id] = cell_id; });
|
||||
cell_id++;
|
||||
}
|
||||
BOOST_ASSERT(std::find(partition.begin(), partition.end(), INVALID_CELL_ID) == partition.end());
|
||||
|
||||
return partition;
|
||||
}
|
||||
@@ -126,9 +127,10 @@ bisectionToPartition(const std::vector<BisectionID> &node_to_bisection_id,
|
||||
std::vector<Partition> partitions(max_cell_sizes.size());
|
||||
std::vector<std::uint32_t> num_cells(max_cell_sizes.size());
|
||||
|
||||
auto level_idx = max_cell_sizes.size() - 1;
|
||||
int level_idx = max_cell_sizes.size() - 1;
|
||||
for (auto max_cell_size : boost::adaptors::reverse(max_cell_sizes))
|
||||
{
|
||||
BOOST_ASSERT(level_idx >= 0);
|
||||
partitionLevel(node_to_bisection_id, max_cell_size, permutation, cells);
|
||||
|
||||
partitions[level_idx] = cellsToPartition(cells, permutation);
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
#include "partition/edge_based_graph_reader.hpp"
|
||||
#include "partition/io.hpp"
|
||||
#include "partition/multi_level_partition.hpp"
|
||||
#include "partition/node_based_graph_to_edge_based_graph_mapping_reader.hpp"
|
||||
#include "partition/recursive_bisection.hpp"
|
||||
#include "partition/remove_unconnected.hpp"
|
||||
|
||||
#include "extractor/io.hpp"
|
||||
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/geojson_debug_logger.hpp"
|
||||
@@ -123,7 +125,8 @@ int Partitioner::Run(const PartitionConfig &config)
|
||||
// Then loads the edge based graph tanslates the partition and modifies it.
|
||||
// For details see #3205
|
||||
|
||||
auto mapping = LoadNodeBasedGraphToEdgeBasedGraphMapping(config.cnbg_ebg_mapping_path.string());
|
||||
std::vector<extractor::NBGToEBG> mapping;
|
||||
extractor::io::read(config.cnbg_ebg_mapping_path.string(), mapping);
|
||||
util::Log() << "Loaded node based graph to edge based graph mapping";
|
||||
|
||||
auto edge_based_graph = LoadEdgeBasedGraph(config.edge_based_graph_path.string());
|
||||
@@ -137,61 +140,22 @@ int Partitioner::Run(const PartitionConfig &config)
|
||||
const auto &node_based_partition_ids = recursive_bisection.BisectionIDs();
|
||||
|
||||
// Partition ids, keyed by edge based graph nodes
|
||||
std::vector<NodeID> edge_based_partition_ids(edge_based_graph->GetNumberOfNodes());
|
||||
std::vector<NodeID> edge_based_partition_ids(edge_based_graph->GetNumberOfNodes(),
|
||||
SPECIAL_NODEID);
|
||||
|
||||
// Extract edge based border nodes, based on node based partition and mapping.
|
||||
for (const auto node : util::irange(0u, edge_based_graph->GetNumberOfNodes()))
|
||||
// Only resolve all easy cases in the first pass
|
||||
for (const auto &entry : mapping)
|
||||
{
|
||||
const auto node_based_nodes = mapping.Lookup(node);
|
||||
const auto u = entry.u;
|
||||
const auto v = entry.v;
|
||||
const auto forward_node = entry.forward_ebg_node;
|
||||
const auto backward_node = entry.backward_ebg_node;
|
||||
|
||||
const auto u = node_based_nodes.u;
|
||||
const auto v = node_based_nodes.v;
|
||||
|
||||
if (node_based_partition_ids[u] == node_based_partition_ids[v])
|
||||
{
|
||||
// Can use partition_ids[u/v] as partition for edge based graph `node_id`
|
||||
edge_based_partition_ids[node] = node_based_partition_ids[u];
|
||||
|
||||
auto edges = edge_based_graph->GetAdjacentEdgeRange(node);
|
||||
if (edges.size() == 1)
|
||||
{ // Check the edge case with one adjacent edge-based backward edge
|
||||
auto edge = edges.front();
|
||||
auto other = edge_based_graph->GetTarget(edge);
|
||||
auto &data = edge_based_graph->GetEdgeData(edge);
|
||||
auto other_node_based_nodes = mapping.Lookup(other);
|
||||
if (data.backward &&
|
||||
node_based_partition_ids[other_node_based_nodes.u] !=
|
||||
node_based_partition_ids[u])
|
||||
{ // use id of other node if the edge [other_u, other_v] -> [u,v] is a single edge
|
||||
// and nodes other_[u,v] are in different node-based partitions
|
||||
edge_based_partition_ids[node] =
|
||||
node_based_partition_ids[other_node_based_nodes.u];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Border nodes u,v - need to be resolved.
|
||||
// FIXME: just pick one side for now. See #3205.
|
||||
|
||||
bool use_u = false;
|
||||
for (auto edge : edge_based_graph->GetAdjacentEdgeRange(node))
|
||||
{
|
||||
auto other = edge_based_graph->GetTarget(edge);
|
||||
auto &data = edge_based_graph->GetEdgeData(edge);
|
||||
auto other_node_based_nodes = mapping.Lookup(other);
|
||||
|
||||
if (data.backward)
|
||||
{ // can use id of u if [other_u, other_v] -> [u,v] is in the same partition as u
|
||||
BOOST_ASSERT(u == other_node_based_nodes.v);
|
||||
use_u |= node_based_partition_ids[u] ==
|
||||
node_based_partition_ids[other_node_based_nodes.u];
|
||||
}
|
||||
}
|
||||
|
||||
// Use partition that introduce less cross cell connections
|
||||
edge_based_partition_ids[node] = node_based_partition_ids[use_u ? u : v];
|
||||
}
|
||||
// This heuristic strategy seems to work best, even beating chosing the minimum
|
||||
// border edge bisection ID
|
||||
edge_based_partition_ids[forward_node] = node_based_partition_ids[u];
|
||||
if (backward_node != SPECIAL_NODEID)
|
||||
edge_based_partition_ids[backward_node] = node_based_partition_ids[v];
|
||||
}
|
||||
|
||||
std::vector<Partition> partitions;
|
||||
@@ -203,6 +167,9 @@ int Partitioner::Run(const PartitionConfig &config)
|
||||
config.minimum_cell_size * 32 * 16,
|
||||
config.minimum_cell_size * 32 * 16 * 32});
|
||||
|
||||
auto num_unconnected = removeUnconnectedBoundaryNodes(*edge_based_graph, partitions);
|
||||
util::Log() << "Fixed " << num_unconnected << " unconnected nodes";
|
||||
|
||||
util::Log() << "Edge-based-graph annotation:";
|
||||
for (std::size_t level = 0; level < level_to_num_cells.size(); ++level)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user