From bb71d9b28ac807951d8d1dc2eec085defa040145 Mon Sep 17 00:00:00 2001 From: Patrick Niklaus Date: Fri, 2 Feb 2018 12:08:39 +0000 Subject: [PATCH] Remove unused code in partitioner --- include/partitioner/annotated_partition.hpp | 136 ------- src/partitioner/annotated_partition.cpp | 387 -------------------- 2 files changed, 523 deletions(-) delete mode 100644 include/partitioner/annotated_partition.hpp delete mode 100644 src/partitioner/annotated_partition.cpp diff --git a/include/partitioner/annotated_partition.hpp b/include/partitioner/annotated_partition.hpp deleted file mode 100644 index c67541480..000000000 --- a/include/partitioner/annotated_partition.hpp +++ /dev/null @@ -1,136 +0,0 @@ -#ifndef OSRM_PARTITIONER_ANNOTATE_HPP_ -#define OSRM_PARTITIONER_ANNOTATE_HPP_ - -#include "partitioner/bisection_graph.hpp" -#include "util/typedefs.hpp" -#include -#include -#include - -namespace osrm -{ -namespace partitioner -{ - -// takes the result of a recursive bisection and turns it into an annotated partition for MLD. These -// annotated partitions provide a mapping from every node in the graph to a consecutively -// numbered cell in each level of the multi level partition. Instead of using the bisection directly -// (which can result in a unbalanced tree structure) -// -// _____o______ -// / \  -// o ____o____ -// / \ / \  -// a b o _o_ -// / \ / \  -// c d o o -// / \ / \  -// e f g h -// -// we build a balanced structure that will result in a multi-cut on any level. We transform this -// layout into: -// -// _____o__________ -// / | \  -// o | \  -// / \ | \  -// a b o _o_ -// / \ / \  -// c d o o -// / \ / \  -// e f g h -class AnnotatedPartition -{ - public: - // Used to generate an implicit tree representation - struct SizedID - { - BisectionID id; - std::size_t count; - - bool operator<(const SizedID &other) const { return id < other.id; }; - }; - - // Metrics that describe a single level - struct LevelMetrics - { - std::size_t border_nodes; - std::size_t border_arcs; - - // impresses imbalance, if not all nodes are in that cell anymore - std::size_t contained_nodes; - std::size_t number_of_cells; - - std::size_t max_border_nodes_per_cell; - std::size_t max_border_arcs_per_cell; - - std::size_t total_memory_cells; - std::vector cell_sizes; - - std::ostream &print(std::ostream &os) const - { - os << "[level]\n" - << "\t#border nodes: " << border_nodes << " #border arcs: " << border_arcs - << " #cells: " << number_of_cells << " #contained nodes: " << contained_nodes << "\n" - << "\tborder nodes: max: " << max_border_nodes_per_cell - << " avg : " << static_cast(border_nodes) / number_of_cells - << " border arcs: max: " << max_border_arcs_per_cell << " " - << " avg: " << static_cast(border_arcs) / number_of_cells << "\n" - << "\tmemory consumption: " << total_memory_cells / (1024.0 * 1024.0) << " MB." - << "\n"; - os << "\tcell sizes:"; - for (auto s : cell_sizes) - os << " " << s; - os << std::endl; - return os; - } - - std::ostream &logMachinereadable(std::ostream &os, - const std::string &identification, - std::size_t depth, - const bool print_header = false) const - { - if (print_header) - os << "[" << identification << "] # depth cells total_nodes border_nodes " - "max_border_nodes border_arcs max_border_arcs bytes " - "cell_sizes*\n"; - - os << "[" << identification << "] " << depth << " " << number_of_cells << " " - << contained_nodes << " " << border_nodes << " " << max_border_nodes_per_cell << " " - << border_arcs << " " << max_border_arcs_per_cell << " " << total_memory_cells; - - for (auto s : cell_sizes) - os << " " << s; - - os << "\n"; - return os; - } - }; - - AnnotatedPartition(const BisectionGraph &graph, const std::vector &bisection_ids); - - private: - // print distribution of level graph as it is - void PrintBisection(const std::vector &implicit_tree, - const BisectionGraph &graph, - const std::vector &bisection_ids) const; - - // find levels that offer good distribution of average cell sizes - void SearchLevels(const std::vector &implicit_tree, - const BisectionGraph &graph, - const std::vector &bisection_ids) const; - - // set cell_ids[i] == INFTY to exclude element - LevelMetrics AnalyseLevel(const BisectionGraph &graph, - const std::vector &cell_ids) const; - - std::vector - ComputeCellIDs(std::vector> &prefixes, - const BisectionGraph &graph, - const std::vector &bisection_ids) const; -}; - -} // namespace partitioner -} // namespace osrm - -#endif // OSRM_PARTITIONER_ANNOTATE_HPP_ diff --git a/src/partitioner/annotated_partition.cpp b/src/partitioner/annotated_partition.cpp deleted file mode 100644 index 468f7305f..000000000 --- a/src/partitioner/annotated_partition.cpp +++ /dev/null @@ -1,387 +0,0 @@ -#include "partitioner/annotated_partition.hpp" - -#include -#include // for CHAR_BIT -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util/timing_util.hpp" - -namespace osrm -{ -namespace partitioner -{ - -namespace -{ - -// the shift value needed to access the most significant bit of the bisection ID -const constexpr auto SHIFT_TO_MSB_BISECTION_ID = sizeof(BisectionID) * CHAR_BIT - 1; -// an invalid ID for a cell -const constexpr std::uint32_t INVALID_CELLID = std::numeric_limits::max(); - -auto masked(const BisectionID id, const std::int32_t level) -{ - // special treatment for negative level - if (level == -1) - return 0u; - - // 0.01.1 with 1 starting at the level+1_th most significant bit (level = 0 -> 01..1) - const auto cut_below_level = (1 << (SHIFT_TO_MSB_BISECTION_ID - level)) - 1; - const auto mask = std::numeric_limits::max() ^ cut_below_level; - return id & mask; -} - -// create a comparator for a given level -auto makeCompare(const std::uint32_t level) -{ - return [level](const AnnotatedPartition::SizedID lhs, const AnnotatedPartition::SizedID rhs) { - return masked(lhs.id, level) < masked(rhs.id, level); - }; -} - -// build a tree of cells from the IDs present: -auto leftChild(const BisectionID id_prefix, const std::int32_t /*level*/) { return id_prefix; } - -// given the prefix 10.... on level 1 (second level), the the right child would be -// 101.... on level 2 -auto rightChild(const BisectionID id_prefix, const std::int32_t level) -{ - return id_prefix | (1 << (SHIFT_TO_MSB_BISECTION_ID - (level + 1))); -} - -// get the range of all children -auto getChildrenRange(const std::vector &implicit_tree, - const BisectionID id_prefix, - const std::int32_t level) -{ - AnnotatedPartition::SizedID id = {id_prefix, 0}; - - // find all elements of the same prefix as id_prefi - auto range = - std::equal_range(implicit_tree.begin(), implicit_tree.end(), id, makeCompare(level)); - - // don't ever return our sentinel element as included - if (range.second == implicit_tree.end()) - --range.second; - - return range; -} - -auto getCellSize(const std::vector &implicit_tree, - const BisectionID id_prefix, - const std::uint32_t level) -{ - auto range = getChildrenRange(implicit_tree, id_prefix, level); - return range.second->count - range.first->count; -} - -bool hasChildren(const std::vector &implicit_tree, - const BisectionID id_prefix, - const std::uint32_t level) -{ - auto range = getChildrenRange(implicit_tree, id_prefix, level); - return std::distance(range.first, range.second) > 1; -} - -} // namespace - -AnnotatedPartition::AnnotatedPartition(const BisectionGraph &graph, - const std::vector &bisection_ids) -{ - // create a sorted vector of bisection ids that exist in the network - std::vector implicit_tree = [&]() { - std::map existing_ids; - - // insert an ID into the sized_id set or increase the count if the element should be already - // present in the set of known ids - const auto insert_or_augment = [&existing_ids](const BisectionID id) { - SizedID sized_id = {id, 1}; - auto maybe_existing_id = existing_ids.find(id); - if (maybe_existing_id == existing_ids.end()) - existing_ids[id] = sized_id; - else - maybe_existing_id->second.count++; - }; - std::for_each(bisection_ids.begin(), bisection_ids.end(), insert_or_augment); - - std::vector result; - result.resize(existing_ids.size() + 1); - std::transform(existing_ids.begin(), - existing_ids.end(), - result.begin(), - [](const auto &pair) { return pair.second; }); - - // sentinel - result.back() = {std::numeric_limits::max(), 0}; - - return result; - }(); - - // calculate a prefix sum over all sorted IDs, this allows to get the size of any partition in - // the array/level based on the prefix and lower bound on prefixes. - // e.g 00,01,10,11 allow to search for (0) (1) to find (00) and (10) as lower bounds. The - // difference in count is the size of all cells in the left part of the partition. - std::transform(implicit_tree.begin(), - implicit_tree.end(), - implicit_tree.begin(), - [sum = std::size_t{0}](SizedID id) mutable { - const auto new_sum = sum + id.count; - id.count = sum; - sum = new_sum; - return id; - }); - - PrintBisection(implicit_tree, graph, bisection_ids); - SearchLevels(implicit_tree, graph, bisection_ids); -} - -void AnnotatedPartition::PrintBisection(const std::vector &implicit_tree, - const BisectionGraph &graph, - const std::vector &bisection_ids) const -{ - // print some statistics on the bisection tree - std::queue id_queue; - id_queue.push(0); - - const auto add_child = [&id_queue, &implicit_tree](const BisectionID prefix, - const std::uint32_t level) { - const auto child_range = getChildrenRange(implicit_tree, prefix, level); - if (std::distance(child_range.first, child_range.second) > 1) - id_queue.push(prefix); - }; - - std::vector> current_level; - for (std::int32_t level = -1; !id_queue.empty(); ++level) - { - auto level_size = id_queue.size(); - current_level.clear(); - while (level_size--) - { - const auto prefix = id_queue.front(); - id_queue.pop(); - if (level == -1 || hasChildren(implicit_tree, prefix, level)) - { - current_level.push_back( - std::pair(leftChild(prefix, level), level + 1)); - current_level.push_back( - std::pair(rightChild(prefix, level), level + 1)); - } - add_child(leftChild(prefix, level), level); - add_child(rightChild(prefix, level), level); - } - if (!current_level.empty()) - { - const auto cell_ids = ComputeCellIDs(current_level, graph, bisection_ids); - const auto stats = AnalyseLevel(graph, cell_ids); - stats.logMachinereadable(std::cout, "bisection", level, level == -1); - } - } -} - -void AnnotatedPartition::SearchLevels(const std::vector &implicit_tree, - const BisectionGraph &graph, - const std::vector &bisection_ids) const -{ - std::vector> current_level; - - // start searching with level 0 at prefix 0 - current_level.push_back({static_cast(0), -1}); - std::int32_t level = -1; - - const auto print_level = [&]() { - if (current_level.empty()) - return; - - const auto cell_ids = ComputeCellIDs(current_level, graph, bisection_ids); - const auto stats = AnalyseLevel(graph, cell_ids); - stats.logMachinereadable(std::cout, "dfs-balanced", level, level == -1); - ++level; - }; - - std::size_t max_size = 0.5 * graph.NumberOfNodes(); - std::queue> id_queue; - while (!current_level.empty()) - { - std::size_t total_size = 0; - std::size_t count = 0; - for (auto element : current_level) - { - // don't relax final cells - if (element.second == -1 || hasChildren(implicit_tree, element.first, element.second)) - { - total_size += getCellSize( - implicit_tree, leftChild(element.first, element.second), element.second + 1); - id_queue.push(std::pair( - leftChild(element.first, element.second), element.second + 1)); - - total_size += getCellSize( - implicit_tree, rightChild(element.first, element.second), element.second + 1); - id_queue.push(std::pair( - rightChild(element.first, element.second), element.second + 1)); - count += 2; - } - } - auto avg_size = (total_size / static_cast(count)); - - current_level.clear(); - - const auto relax = [&id_queue, &implicit_tree, avg_size, ¤t_level]( - const std::pair &element) { - const auto size = getCellSize(implicit_tree, element.first, element.second); - if (!hasChildren(implicit_tree, element.first, element.second)) - { - current_level.push_back(element); - } - else - { - const auto left = leftChild(element.first, element.second); - const auto right = rightChild(element.first, element.second); - - const auto get_penalty = [avg_size](const auto size) { - return std::abs(size - avg_size); - }; - - if (get_penalty(size) < - 0.5 * (get_penalty(getCellSize(implicit_tree, left, element.second + 1)) + - get_penalty(getCellSize(implicit_tree, right, element.second + 1)))) - { - current_level.push_back(element); - } - else - { - id_queue.push(std::pair(left, element.second + 1)); - id_queue.push(std::pair(right, element.second + 1)); - } - } - }; - - while (!id_queue.empty()) - { - relax(id_queue.front()); - id_queue.pop(); - } - print_level(); - max_size *= 0.5; - } -} - -AnnotatedPartition::LevelMetrics -AnnotatedPartition::AnalyseLevel(const BisectionGraph &graph, - const std::vector &cell_ids) const -{ - std::unordered_map cell_sizes; - std::unordered_map border_nodes; - std::unordered_map border_arcs; - - // compute basic metrics of the level - std::size_t border_nodes_total = 0; - std::size_t border_arcs_total = 0; - std::size_t contained_nodes = 0; - - // only border nodes on the lowest level can be border nodes in general - for (const auto &node : graph.Nodes()) - { - const auto cell_id = cell_ids[node.original_id]; - if (cell_id == INVALID_CELLID) - continue; - - ++contained_nodes; - - const auto edge_range = graph.Edges(node); - const auto border_arcs_at_node = std::count_if( - edge_range.begin(), edge_range.end(), [&cell_id, &cell_ids, &graph](const auto &edge) { - const auto target_cell_id = cell_ids[graph.Node(edge.target).original_id]; - return target_cell_id != cell_id; - }); - - cell_sizes[cell_id]++; - border_arcs[cell_id] += border_arcs_at_node; - border_arcs_total += border_arcs_at_node; - if (border_arcs_at_node) - { - border_nodes[cell_id]++; - ++border_nodes_total; - } - } - - const auto by_size = [](const std::pair &lhs, - const std::pair &rhs) { - return lhs.second < rhs.second; - }; - const auto max_nodes = - border_nodes.empty() - ? 0 - : std::max_element(border_nodes.begin(), border_nodes.end(), by_size)->second; - const auto max_arcs = - border_arcs.empty() - ? 0 - : std::max_element(border_arcs.begin(), border_arcs.end(), by_size)->second; - - const auto squarded_size = [](const std::size_t accumulated, - const std::pair &element) { - return accumulated + element.second * element.second; - }; - - const auto memory = - 4 * std::accumulate(border_arcs.begin(), border_nodes.end(), std::size_t(0), squarded_size); - - std::vector cell_sizes_vec; - cell_sizes_vec.resize(cell_sizes.size()); - std::transform(cell_sizes.begin(), - cell_sizes.end(), - cell_sizes_vec.begin(), - [](const auto &pair) { return pair.second; }); - return {border_nodes_total, - border_arcs_total, - contained_nodes, - border_nodes.size(), - max_nodes, - max_arcs, - memory, - std::move(cell_sizes_vec)}; -} - -std::vector -AnnotatedPartition::ComputeCellIDs(std::vector> &prefixes, - const BisectionGraph &graph, - const std::vector &bisection_ids) const -{ - std::vector cell_ids(graph.NumberOfNodes(), INVALID_CELLID); - - std::sort(prefixes.begin(), prefixes.end(), [](const auto lhs, const auto rhs) { - return lhs.first < rhs.first; - }); - - for (const auto &node : graph.Nodes()) - { - // find the cell_id of node in the current levels - const auto id = bisection_ids[node.original_id]; - - const auto is_prefixed_by = [id](const auto &prefix) { - return masked(id, prefix.second) == prefix.first; - }; - - const auto prefix = std::lower_bound( - prefixes.begin(), prefixes.end(), id, [&](const auto prefix, const BisectionID id) { - return prefix.first < masked(id, prefix.second); - }); - - if (prefix == prefixes.end()) - continue; - - if (is_prefixed_by(*prefix)) - cell_ids[node.original_id] = std::distance(prefixes.begin(), prefix); - } - return cell_ids; -} - -} // namespace partitioner -} // namespace osrm