generate stats in annotation
This commit is contained in:
committed by
Patrick Niklaus
parent
739ad73ae9
commit
be41e8b321
@@ -0,0 +1,136 @@
|
||||
#ifndef OSRM_PARTITION_ANNOTATE_HPP_
|
||||
#define OSRM_PARTITION_ANNOTATE_HPP_
|
||||
|
||||
#include "partition/bisection_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
#include <cstdint>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace partition
|
||||
{
|
||||
|
||||
// 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<std::size_t> 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<double>(border_nodes) / number_of_cells
|
||||
<< " border arcs: max: " << max_border_arcs_per_cell << " "
|
||||
<< " avg: " << static_cast<double>(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<BisectionID> &bisection_ids);
|
||||
|
||||
private:
|
||||
// print distribution of level graph as it is
|
||||
void PrintBisection(const std::vector<SizedID> &implicit_tree,
|
||||
const BisectionGraph &graph,
|
||||
const std::vector<BisectionID> &bisection_ids) const;
|
||||
|
||||
// find levels that offer good distribution of average cell sizes
|
||||
void SearchLevels(const std::vector<SizedID> &implicit_tree,
|
||||
const BisectionGraph &graph,
|
||||
const std::vector<BisectionID> &bisection_ids) const;
|
||||
|
||||
// set cell_ids[i] == INFTY to exclude element
|
||||
LevelMetrics AnalyseLevel(const BisectionGraph &graph,
|
||||
const std::vector<std::uint32_t> &cell_ids) const;
|
||||
|
||||
std::vector<std::uint32_t>
|
||||
ComputeCellIDs(std::vector<std::pair<BisectionID, std::int32_t>> &prefixes,
|
||||
const BisectionGraph &graph,
|
||||
const std::vector<BisectionID> &bisection_ids) const;
|
||||
};
|
||||
|
||||
} // namespace partition
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_PARTITION_ANNOTATE_HPP_
|
||||
@@ -35,7 +35,7 @@ class InertialFlow
|
||||
SpatialOrder MakeSpatialOrder(double ratio, double slope) const;
|
||||
|
||||
// Makes n cuts with different spatial orders and returns the best.
|
||||
DinicMaxFlow::MinCut BestMinCut(std::size_t n, double ratio) const;
|
||||
DinicMaxFlow::MinCut BestMinCut(std::size_t n, double ratio, double balance) const;
|
||||
|
||||
// The subgraph to partition into two parts.
|
||||
const GraphView &view;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "partition/bisection_graph.hpp"
|
||||
#include "partition/graph_view.hpp"
|
||||
#include "partition/recursive_bisection_state.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
@@ -23,7 +24,7 @@ class RecursiveBisection
|
||||
const std::size_t num_optimizing_cuts,
|
||||
const std::size_t small_component_size);
|
||||
|
||||
const std::vector<RecursiveBisectionState::BisectionID> &BisectionIDs() const;
|
||||
const std::vector<BisectionID> &BisectionIDs() const;
|
||||
|
||||
private:
|
||||
BisectionGraph &bisection_graph;
|
||||
|
||||
@@ -20,7 +20,6 @@ class RecursiveBisectionState
|
||||
{
|
||||
public:
|
||||
// The ID in the partition array
|
||||
using BisectionID = std::uint32_t;
|
||||
using NodeIterator = BisectionGraph::ConstNodeIterator;
|
||||
|
||||
RecursiveBisectionState(BisectionGraph &bisection_graph);
|
||||
@@ -42,7 +41,11 @@ class RecursiveBisectionState
|
||||
|
||||
const std::vector<BisectionID> &BisectionIDs() const;
|
||||
|
||||
// return the depth encoded in the SCCs
|
||||
std::uint32_t SCCDepth() const;
|
||||
|
||||
private:
|
||||
std::uint32_t scc_levels;
|
||||
BisectionGraph &bisection_graph;
|
||||
std::vector<BisectionID> bisection_ids;
|
||||
};
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
#ifndef OSRM_PARTITION_RECURSIVE_BISECTION_STATS_HPP_
|
||||
#define OSRM_PARTITION_RECURSIVE_BISECTION_STATS_HPP_
|
||||
|
||||
#include "partition/bisection_graph.hpp"
|
||||
#include "partition/recursive_bisection_state.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace partition
|
||||
{
|
||||
// generates some statistics on a recursive bisection to describe its quality/parameters
|
||||
void printBisectionStats(std::vector<RecursiveBisectionState::BisectionID> const &bisection_ids,
|
||||
const BisectionGraph &graph);
|
||||
} // namespace partition
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_PARTITION_RECURSIVE_BISECTION_STATS_HPP_
|
||||
@@ -81,26 +81,21 @@ template <typename EdgeDataT> struct SortableEdgeWithData : SortableEdgeWithData
|
||||
|
||||
} // namespace static_graph_details
|
||||
|
||||
template <typename NodeT, typename EdgeT, bool UseSharedMemory = false> class FlexibleStaticGraph
|
||||
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
|
||||
{
|
||||
static_assert(traits::HasFirstEdgeMember<NodeT>::value,
|
||||
"Model for compatible Node type requires .first_edge member attribute");
|
||||
static_assert(traits::HasTargetMember<EdgeT>::value,
|
||||
"Model for compatible Node type requires .target member attribute");
|
||||
|
||||
public:
|
||||
using NodeIterator = static_graph_details::NodeIterator;
|
||||
using EdgeIterator = static_graph_details::EdgeIterator;
|
||||
using EdgeRange = range<EdgeIterator>;
|
||||
using NodeArrayEntry = NodeT;
|
||||
using EdgeArrayEntry = EdgeT;
|
||||
using NodeArrayEntry = static_graph_details::NodeArrayEntry;
|
||||
using EdgeArrayEntry = static_graph_details::EdgeArrayEntry<EdgeDataT>;
|
||||
|
||||
EdgeRange GetAdjacentEdgeRange(const NodeID node) const
|
||||
{
|
||||
return irange(BeginEdges(node), EndEdges(node));
|
||||
}
|
||||
|
||||
template <typename ContainerT> FlexibleStaticGraph(const int nodes, const ContainerT &graph)
|
||||
template <typename ContainerT> StaticGraph(const int nodes, const ContainerT &graph)
|
||||
{
|
||||
BOOST_ASSERT(std::is_sorted(const_cast<ContainerT &>(graph).begin(),
|
||||
const_cast<ContainerT &>(graph).end()));
|
||||
@@ -128,14 +123,15 @@ template <typename NodeT, typename EdgeT, bool UseSharedMemory = false> class Fl
|
||||
for (const auto i : irange(node_array[node].first_edge, e))
|
||||
{
|
||||
edge_array[i].target = graph[edge].target;
|
||||
CopyDataIfAvailable(edge_array[i], graph[edge], traits::HasDataMember<EdgeT>{});
|
||||
CopyDataIfAvailable(
|
||||
edge_array[i], graph[edge], traits::HasDataMember<EdgeArrayEntry>{});
|
||||
edge++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FlexibleStaticGraph(typename ShM<NodeT, UseSharedMemory>::vector &nodes,
|
||||
typename ShM<EdgeT, UseSharedMemory>::vector &edges)
|
||||
StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes,
|
||||
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector &edges)
|
||||
{
|
||||
number_of_nodes = static_cast<decltype(number_of_nodes)>(nodes.size() - 1);
|
||||
number_of_edges = static_cast<decltype(number_of_edges)>(edges.size());
|
||||
@@ -198,7 +194,7 @@ template <typename NodeT, typename EdgeT, bool UseSharedMemory = false> class Fl
|
||||
EdgeIterator
|
||||
FindSmallestEdge(const NodeIterator from, const NodeIterator to, FilterFunction &&filter) const
|
||||
{
|
||||
static_assert(traits::HasDataMember<EdgeT>::value,
|
||||
static_assert(traits::HasDataMember<EdgeArrayEntry>::value,
|
||||
"Filtering on .data not possible without .data member attribute");
|
||||
|
||||
EdgeIterator smallest_edge = SPECIAL_EDGEID;
|
||||
@@ -243,13 +239,13 @@ template <typename NodeT, typename EdgeT, bool UseSharedMemory = false> class Fl
|
||||
|
||||
private:
|
||||
template <typename OtherEdge>
|
||||
void CopyDataIfAvailable(EdgeT &into, const OtherEdge &from, std::true_type)
|
||||
void CopyDataIfAvailable(EdgeArrayEntry &into, const OtherEdge &from, std::true_type)
|
||||
{
|
||||
into.data = from.data;
|
||||
}
|
||||
|
||||
template <typename OtherEdge>
|
||||
void CopyDataIfAvailable(EdgeT &into, const OtherEdge &from, std::false_type)
|
||||
void CopyDataIfAvailable(EdgeArrayEntry &into, const OtherEdge &from, std::false_type)
|
||||
{
|
||||
// Graph has no .data member, never copy even if `from` has a .data member.
|
||||
(void)into;
|
||||
@@ -259,15 +255,11 @@ template <typename NodeT, typename EdgeT, bool UseSharedMemory = false> class Fl
|
||||
NodeIterator number_of_nodes;
|
||||
EdgeIterator number_of_edges;
|
||||
|
||||
typename ShM<NodeT, UseSharedMemory>::vector node_array;
|
||||
typename ShM<EdgeT, UseSharedMemory>::vector edge_array;
|
||||
typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array;
|
||||
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array;
|
||||
};
|
||||
|
||||
template <typename EdgeDataT, bool UseSharedMemory = false>
|
||||
using StaticGraph = FlexibleStaticGraph<static_graph_details::NodeArrayEntry,
|
||||
static_graph_details::EdgeArrayEntry<EdgeDataT>,
|
||||
UseSharedMemory>;
|
||||
}
|
||||
}
|
||||
} // namespace util
|
||||
} // namespace osrm
|
||||
|
||||
#endif // STATIC_GRAPH_HPP
|
||||
|
||||
@@ -61,6 +61,7 @@ using EdgeWeight = std::int32_t;
|
||||
using TurnPenalty = std::int16_t; // turn penalty in 100ms units
|
||||
|
||||
static const std::size_t INVALID_INDEX = std::numeric_limits<std::size_t>::max();
|
||||
using BisectionID = std::uint32_t;
|
||||
|
||||
using LaneID = std::uint8_t;
|
||||
static const LaneID INVALID_LANEID = std::numeric_limits<LaneID>::max();
|
||||
|
||||
Reference in New Issue
Block a user