Optimise Flow Algorithm/Datastructures in use
This commit is contained in:
committed by
Patrick Niklaus
parent
dd60ae31ae
commit
786be6f570
@@ -2,16 +2,16 @@
|
||||
#define OSRM_BISECTION_GRAPH_HPP_
|
||||
|
||||
#include "util/coordinate.hpp"
|
||||
#include "util/static_graph.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
#include "partition/partition_graph.hpp"
|
||||
|
||||
#include "extractor/edge_based_edge.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
namespace osrm
|
||||
@@ -23,77 +23,77 @@ namespace partition
|
||||
// The coordinate will be used in the partitioning step.
|
||||
struct BisectionNode
|
||||
{
|
||||
// StaticGraph Node requirement (see static graph traits): .first_edge
|
||||
std::size_t first_edge;
|
||||
BisectionNode(util::Coordinate coordinate_ = {util::FloatLongitude{0}, util::FloatLatitude{0}},
|
||||
const NodeID original_id_ = SPECIAL_NODEID)
|
||||
: coordinate(std::move(coordinate_)), original_id(original_id_)
|
||||
{
|
||||
}
|
||||
|
||||
// the coordinate the node is located at
|
||||
util::Coordinate coordinate;
|
||||
|
||||
// the node id to access the bisection result
|
||||
NodeID original_id;
|
||||
};
|
||||
|
||||
// Graph edge and data for Max-Flow Min-Cut augmentation.
|
||||
struct BisectionEdge
|
||||
{
|
||||
BisectionEdge(const NodeID target_ = SPECIAL_NODEID) : target(target_) {}
|
||||
// StaticGraph Edge requirement (see static graph traits): .target, .data
|
||||
NodeID target;
|
||||
|
||||
// TODO: add data for augmentation here. In case we want to keep it completely external, the
|
||||
// static graph can be modified to no longer require a .data member by SFINAE-ing out features
|
||||
// based on the available compile time traits.
|
||||
std::int32_t data;
|
||||
};
|
||||
|
||||
// The graph layout we use as a basis for partitioning.
|
||||
using BisectionGraph = util::FlexibleStaticGraph<BisectionNode, BisectionEdge>;
|
||||
using RemappableGraphNode = NodeEntryWrapper<BisectionNode>;
|
||||
using BisectionInputEdge = GraphConstructionWrapper<BisectionEdge>;
|
||||
using BisectionGraph = RemappableGraph<RemappableGraphNode, BisectionEdge>;
|
||||
|
||||
template <typename RandomIt> void sortBySourceThenTarget(RandomIt first, RandomIt last)
|
||||
inline BisectionGraph makeBisectionGraph(const std::vector<util::Coordinate> &coordinates,
|
||||
const std::vector<BisectionInputEdge> &edges)
|
||||
{
|
||||
std::sort(first, last, [](const auto &lhs, const auto &rhs) {
|
||||
return std::tie(lhs.source, lhs.target) < std::tie(rhs.source, rhs.target);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename InputEdge>
|
||||
std::vector<BisectionNode> computeNodes(const std::vector<util::Coordinate> &coordinates,
|
||||
const std::vector<InputEdge> &edges)
|
||||
{
|
||||
std::vector<BisectionNode> result;
|
||||
result.reserve(coordinates.size() + 1 /*sentinel*/);
|
||||
std::vector<BisectionGraph::NodeT> result_nodes;
|
||||
result_nodes.reserve(coordinates.size());
|
||||
std::vector<BisectionGraph::EdgeT> result_edges;
|
||||
result_edges.reserve(edges.size());
|
||||
|
||||
// find the end of edges that belong to node_id
|
||||
const auto advance_edge_itr = [&edges](const std::size_t node_id, auto edge_itr) {
|
||||
const auto advance_edge_itr = [&edges, &result_edges](const std::size_t node_id,
|
||||
auto edge_itr) {
|
||||
while (edge_itr != edges.end() && edge_itr->source == node_id)
|
||||
{
|
||||
result_edges.push_back(edge_itr->Reduce());
|
||||
++edge_itr;
|
||||
}
|
||||
return edge_itr;
|
||||
};
|
||||
|
||||
// create a bisection node, requires the ID of the node as well as the lower bound to its edges
|
||||
const auto make_bisection_node = [&edges, &coordinates](const std::size_t node_id,
|
||||
const auto edge_itr) -> BisectionNode {
|
||||
return {static_cast<std::size_t>(std::distance(edges.begin(), edge_itr)),
|
||||
coordinates[node_id]};
|
||||
const auto edge_itr) {
|
||||
std::size_t range_begin = std::distance(edges.begin(), edge_itr);
|
||||
return BisectionGraph::NodeT(range_begin, range_begin, coordinates[node_id], node_id);
|
||||
};
|
||||
|
||||
auto edge_itr = edges.begin();
|
||||
for (std::size_t node_id = 0; node_id < coordinates.size(); ++node_id)
|
||||
{
|
||||
result.emplace_back(make_bisection_node(node_id,edge_itr));
|
||||
edge_itr = advance_edge_itr(node_id,edge_itr);
|
||||
result_nodes.emplace_back(make_bisection_node(node_id, edge_itr));
|
||||
edge_itr = advance_edge_itr(node_id, edge_itr);
|
||||
result_nodes.back().edges_end = std::distance(edges.begin(), edge_itr);
|
||||
}
|
||||
|
||||
auto null_island = util::Coordinate(util::FloatLongitude{0.0}, util::FloatLatitude{0.0});
|
||||
auto sentinel = BisectionNode{edges.size(), std::move(null_island)};
|
||||
|
||||
result.emplace_back(std::move(sentinel));
|
||||
|
||||
return result;
|
||||
return BisectionGraph(std::move(result_nodes), std::move(result_edges));
|
||||
}
|
||||
|
||||
template <typename InputEdge>
|
||||
std::vector<BisectionEdge> adaptToBisectionEdge(std::vector<InputEdge> edges)
|
||||
std::vector<BisectionInputEdge> adaptToBisectionEdge(std::vector<InputEdge> edges)
|
||||
{
|
||||
std::vector<BisectionEdge> result(edges.size());
|
||||
std::vector<BisectionInputEdge> result;
|
||||
result.reserve(edges.size());
|
||||
|
||||
std::transform(begin(edges), end(edges), begin(result), [](const auto &edge) {
|
||||
return BisectionEdge{edge.target, 1};
|
||||
std::transform(begin(edges), end(edges), std::back_inserter(result), [](const auto &edge) {
|
||||
return BisectionInputEdge{edge.source, edge.target};
|
||||
});
|
||||
|
||||
return result;
|
||||
|
||||
@@ -31,36 +31,42 @@ namespace partition
|
||||
class DinicMaxFlow
|
||||
{
|
||||
public:
|
||||
using PartitionResult = struct
|
||||
using Level = std::uint32_t;
|
||||
using MinCut = struct
|
||||
{
|
||||
std::size_t num_nodes_source;
|
||||
std::size_t num_edges;
|
||||
std::vector<bool> flags;
|
||||
};
|
||||
using SourceSinkNodes = std::set<NodeID>;
|
||||
using LevelGraph = std::unordered_map<NodeID, std::uint32_t>;
|
||||
using FlowEdges = std::unordered_set<std::pair<NodeID, NodeID>>;
|
||||
using SourceSinkNodes = std::unordered_set<NodeID>;
|
||||
using LevelGraph = std::vector<Level>;
|
||||
using FlowEdges = std::vector<std::set<NodeID>>;
|
||||
|
||||
PartitionResult operator()(const GraphView &view,
|
||||
const SourceSinkNodes &sink_nodes,
|
||||
const SourceSinkNodes &source_nodes) const;
|
||||
MinCut operator()(const GraphView &view,
|
||||
const SourceSinkNodes &sink_nodes,
|
||||
const SourceSinkNodes &source_nodes) const;
|
||||
|
||||
private:
|
||||
LevelGraph ComputeLevelGraph(const GraphView &view,
|
||||
const std::vector<NodeID> &border_source_nodes,
|
||||
const SourceSinkNodes &source_nodes,
|
||||
const SourceSinkNodes &sink_nodes,
|
||||
const FlowEdges &flow) const;
|
||||
|
||||
void AugmentFlow(FlowEdges &flow,
|
||||
const GraphView &view,
|
||||
const SourceSinkNodes &source_nodes,
|
||||
const SourceSinkNodes &sink_nodes,
|
||||
const LevelGraph &levels) const;
|
||||
std::uint32_t BlockingFlow(FlowEdges &flow,
|
||||
LevelGraph &levels,
|
||||
const GraphView &view,
|
||||
const SourceSinkNodes &source_nodes,
|
||||
const std::vector<NodeID> &border_sink_nodes) const;
|
||||
|
||||
bool findPath(const NodeID from,
|
||||
std::vector<NodeID> &path,
|
||||
const GraphView &view,
|
||||
const LevelGraph &levels,
|
||||
const FlowEdges &flow,
|
||||
const SourceSinkNodes &sink_nodes) const;
|
||||
std::vector<NodeID> GetAugmentingPath(LevelGraph &levels,
|
||||
const NodeID from,
|
||||
const GraphView &view,
|
||||
const FlowEdges &flow,
|
||||
const SourceSinkNodes &sink_nodes) const;
|
||||
|
||||
// Builds an actual cut result from a level graph
|
||||
MinCut MakeCut(const GraphView &view, const LevelGraph &levels) const;
|
||||
};
|
||||
|
||||
} // namespace partition
|
||||
|
||||
@@ -8,88 +8,50 @@
|
||||
#include <boost/iterator/iterator_facade.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace partition
|
||||
{
|
||||
|
||||
// Predicate for EdgeIDs checking their partition ids for equality.
|
||||
// Used in filter iterator below to discard edges in different partitions.
|
||||
struct HasSamePartitionID
|
||||
{
|
||||
HasSamePartitionID(const RecursiveBisectionState::BisectionID bisection_id,
|
||||
const BisectionGraph &bisection_graph,
|
||||
const RecursiveBisectionState &recursive_bisection_state);
|
||||
|
||||
bool operator()(const EdgeID eid) const;
|
||||
|
||||
private:
|
||||
const RecursiveBisectionState::BisectionID bisection_id;
|
||||
const BisectionGraph &bisection_graph;
|
||||
const RecursiveBisectionState &recursive_bisection_state;
|
||||
};
|
||||
|
||||
// Random Access Iterator on top of contiguous integral EdgeIDs
|
||||
class EdgeIDIterator : public boost::iterator_facade<EdgeIDIterator,
|
||||
EdgeID const,
|
||||
boost::random_access_traversal_tag>
|
||||
{
|
||||
public:
|
||||
EdgeIDIterator() : position(SPECIAL_EDGEID) {}
|
||||
explicit EdgeIDIterator(EdgeID position_) : position(position_) {}
|
||||
|
||||
private:
|
||||
friend class boost::iterator_core_access;
|
||||
|
||||
// Implements the facade's core operations required for random access iterators:
|
||||
// http://www.boost.org/doc/libs/1_63_0/libs/iterator/doc/iterator_facade.html#core-operations
|
||||
|
||||
void increment() { ++position; }
|
||||
void decrement() { --position; }
|
||||
void advance(difference_type offset) { position += offset; }
|
||||
bool equal(const EdgeIDIterator &other) const { return position == other.position; }
|
||||
reference dereference() const { return position; }
|
||||
difference_type distance_to(const EdgeIDIterator &other) const
|
||||
{
|
||||
return static_cast<difference_type>(other.position - position);
|
||||
}
|
||||
|
||||
value_type position;
|
||||
};
|
||||
|
||||
// Non-owning immutable sub-graph view into a base graph.
|
||||
// The part of the graph to select is determined by the recursive bisection state.
|
||||
class GraphView
|
||||
{
|
||||
public:
|
||||
using EdgeIterator = boost::filter_iterator<HasSamePartitionID, EdgeIDIterator>;
|
||||
|
||||
GraphView(const BisectionGraph &graph,
|
||||
const RecursiveBisectionState &bisection_state,
|
||||
const RecursiveBisectionState::IDIterator begin,
|
||||
const RecursiveBisectionState::IDIterator end);
|
||||
const BisectionGraph::ConstNodeIterator begin,
|
||||
const BisectionGraph::ConstNodeIterator end);
|
||||
|
||||
GraphView(const BisectionGraph &graph);
|
||||
|
||||
// Number of nodes _in this sub-graph.
|
||||
std::size_t NumberOfNodes() const;
|
||||
|
||||
RecursiveBisectionState::IDIterator Begin() const;
|
||||
RecursiveBisectionState::IDIterator End() const;
|
||||
|
||||
EdgeIterator EdgeBegin(const NodeID nid) const;
|
||||
EdgeIterator EdgeEnd(const NodeID nid) const;
|
||||
|
||||
NodeID GetTarget(const EdgeID eid) const;
|
||||
BisectionGraph::ConstNodeIterator Begin() const;
|
||||
BisectionGraph::ConstNodeIterator End() const;
|
||||
|
||||
const BisectionNode &GetNode(const NodeID nid) const;
|
||||
const BisectionEdge &GetEdge(const EdgeID eid) const;
|
||||
|
||||
NodeID GetID(const BisectionGraph::NodeT &node) const;
|
||||
|
||||
inline auto Edges(const NodeID nid) const { return bisection_graph.Edges(*(begin + nid)); }
|
||||
inline auto BeginEdges(const NodeID nid) const
|
||||
{
|
||||
return bisection_graph.BeginEdges(*(begin + nid));
|
||||
}
|
||||
inline auto EndEdges(const NodeID nid) const
|
||||
{
|
||||
return bisection_graph.EndEdges(*(begin + nid));
|
||||
}
|
||||
|
||||
private:
|
||||
const BisectionGraph &bisection_graph;
|
||||
const RecursiveBisectionState &bisection_state;
|
||||
|
||||
const RecursiveBisectionState::IDIterator begin;
|
||||
const RecursiveBisectionState::IDIterator end;
|
||||
const BisectionGraph::ConstNodeIterator begin;
|
||||
const BisectionGraph::ConstNodeIterator end;
|
||||
};
|
||||
|
||||
} // namespace partition
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef OSRM_PARTITION_INERTIAL_FLOW_HPP_
|
||||
#define OSRM_PARTITION_INERTIAL_FLOW_HPP_
|
||||
|
||||
#include "partition/dinic_max_flow.hpp"
|
||||
#include "partition/graph_view.hpp"
|
||||
|
||||
#include <unordered_set>
|
||||
@@ -16,7 +17,9 @@ class InertialFlow
|
||||
public:
|
||||
InertialFlow(const GraphView &view);
|
||||
|
||||
std::vector<bool> ComputePartition(const double balance, const double source_sink_rate);
|
||||
DinicMaxFlow::MinCut ComputePartition(const std::size_t num_slopes,
|
||||
const double balance,
|
||||
const double source_sink_rate);
|
||||
|
||||
private:
|
||||
// Spatially ordered sources and sink ids.
|
||||
@@ -32,7 +35,7 @@ class InertialFlow
|
||||
SpatialOrder MakeSpatialOrder(double ratio, double slope) const;
|
||||
|
||||
// Makes n cuts with different spatial orders and returns the best.
|
||||
MinCut bestMinCut(std::size_t n, double ratio) const;
|
||||
DinicMaxFlow::MinCut BestMinCut(std::size_t n, double ratio) const;
|
||||
|
||||
// The subgraph to partition into two parts.
|
||||
const GraphView &view;
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
#ifndef OSRM_PARTITION_GRAPH_HPP_
|
||||
#define OSRM_PARTITION_GRAPH_HPP_
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
#include "util/typedefs.hpp"
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace partition
|
||||
{
|
||||
|
||||
// wrapper for nodes to augment with a tag storing first edge id
|
||||
template <typename Base> class NodeEntryWrapper : public Base
|
||||
{
|
||||
public:
|
||||
template <typename... Args>
|
||||
NodeEntryWrapper(std::size_t edges_begin_, std::size_t edges_end_, Args &&... args)
|
||||
: Base(std::forward<Args>(args)...), edges_begin(edges_begin_), edges_end(edges_end_)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t edges_begin;
|
||||
std::size_t edges_end;
|
||||
};
|
||||
|
||||
template <typename Base> class GraphConstructionWrapper : public Base
|
||||
{
|
||||
public:
|
||||
template <typename... Args>
|
||||
GraphConstructionWrapper(const NodeID source_, Args &&... args)
|
||||
: Base(std::forward<Args>(args)...), source(source_)
|
||||
{
|
||||
}
|
||||
|
||||
NodeID source;
|
||||
|
||||
Base Reduce() const { return *this; }
|
||||
};
|
||||
|
||||
template <typename RandomIt> void groupEdgesBySource(RandomIt first, RandomIt last)
|
||||
{
|
||||
std::sort(
|
||||
first, last, [](const auto &lhs, const auto &rhs) { return lhs.source < rhs.source; });
|
||||
}
|
||||
|
||||
template <typename NodeEntryT, typename EdgeEntryT> class RemappableGraph
|
||||
{
|
||||
public:
|
||||
using NodeT = NodeEntryT;
|
||||
using EdgeT = EdgeEntryT;
|
||||
|
||||
using NodeIterator = typename std::vector<NodeT>::iterator;
|
||||
using ConstNodeIterator = typename std::vector<NodeT>::const_iterator;
|
||||
using EdgeIterator = typename std::vector<EdgeT>::iterator;
|
||||
using ConstEdgeIterator = typename std::vector<EdgeT>::const_iterator;
|
||||
|
||||
// Constructs an empty graph with a given number of nodes.
|
||||
explicit RemappableGraph(std::vector<NodeT> nodes_, std::vector<EdgeT> edges_)
|
||||
: nodes(std::move(nodes_)), edges(std::move(edges_))
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NumberOfNodes() const { return nodes.size(); }
|
||||
|
||||
auto &Node(const NodeID nid) { return nodes[nid]; }
|
||||
auto &Node(const NodeID nid) const { return nodes[nid]; }
|
||||
|
||||
auto &Edge(const EdgeID eid) { return edges[eid]; }
|
||||
auto &Edge(const EdgeID eid) const { return edges[eid]; }
|
||||
|
||||
auto Edges(const NodeID nid)
|
||||
{
|
||||
return boost::make_iterator_range(edges.begin() + nodes[nid].edges_begin,
|
||||
edges.begin() + nodes[nid].edges_end);
|
||||
}
|
||||
|
||||
auto Edges(const NodeID nid) const
|
||||
{
|
||||
return boost::make_iterator_range(edges.begin() + nodes[nid].edges_begin,
|
||||
edges.begin() + nodes[nid].edges_end);
|
||||
}
|
||||
|
||||
auto Edges(const NodeT &node)
|
||||
{
|
||||
return boost::make_iterator_range(edges.begin() + node.edges_begin,
|
||||
edges.begin() + node.edges_end);
|
||||
}
|
||||
|
||||
auto Edges(const NodeT &node) const
|
||||
{
|
||||
return boost::make_iterator_range(edges.begin() + node.edges_begin,
|
||||
edges.begin() + node.edges_end);
|
||||
}
|
||||
|
||||
auto BeginEdges(const NodeID nid) const { return edges.begin() + nodes[nid].edges_begin; }
|
||||
auto EndEdges(const NodeID nid) const { return edges.begin() + nodes[nid].edges_end; }
|
||||
|
||||
auto BeginEdges(const NodeT &node) const { return edges.begin() + node.edges_begin; }
|
||||
auto EndEdges(const NodeT &node) const { return edges.begin() + node.edges_end; }
|
||||
auto BeginEdges(const NodeT &node) { return edges.begin() + node.edges_begin; }
|
||||
auto EndEdges(const NodeT &node) { return edges.begin() + node.edges_end; }
|
||||
|
||||
// iterate over all nodes
|
||||
auto Nodes() { return boost::make_iterator_range(nodes.begin(), nodes.end()); }
|
||||
auto Nodes() const { return boost::make_iterator_range(nodes.begin(), nodes.end()); }
|
||||
|
||||
NodeIterator Begin() { return nodes.begin(); }
|
||||
NodeIterator End() { return nodes.end(); }
|
||||
ConstNodeIterator CBegin() const { return nodes.cbegin(); }
|
||||
ConstNodeIterator CEnd() const { return nodes.cend(); }
|
||||
|
||||
// removes the edges from the graph that return true for the filter, returns new end
|
||||
template <typename FilterT> auto RemoveEdges(NodeT &node, FilterT filter)
|
||||
{
|
||||
BOOST_ASSERT(&node >= &nodes[0] && &node <= &nodes.back());
|
||||
// required since we are not on std++17 yet, otherwise we are missing an argument_type
|
||||
const auto negate_filter = [&](const EdgeT &edge) { return !filter(edge); };
|
||||
const auto center = std::stable_partition(BeginEdges(node), EndEdges(node), negate_filter);
|
||||
const auto remaining_edges = std::distance(BeginEdges(node), center);
|
||||
node.edges_end = node.edges_begin + remaining_edges;
|
||||
return center;
|
||||
};
|
||||
|
||||
protected:
|
||||
std::vector<NodeT> nodes;
|
||||
std::vector<EdgeT> edges;
|
||||
};
|
||||
|
||||
} // namespace partition
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_PARTITION_GRAPH_HPP_
|
||||
@@ -2,9 +2,11 @@
|
||||
#define OSRM_PARTITION_RECURSIVE_BISECTION_HPP_
|
||||
|
||||
#include "partition/bisection_graph.hpp"
|
||||
#include "partition/graph_view.hpp"
|
||||
#include "partition/recursive_bisection_state.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
@@ -17,11 +19,15 @@ class RecursiveBisection
|
||||
RecursiveBisection(std::size_t maximum_cell_size,
|
||||
double balance,
|
||||
double boundary_factor,
|
||||
const BisectionGraph &bisection_graph);
|
||||
BisectionGraph &bisection_graph);
|
||||
|
||||
private:
|
||||
const BisectionGraph &bisection_graph;
|
||||
BisectionGraph &bisection_graph;
|
||||
RecursiveBisectionState internal_state;
|
||||
|
||||
// on larger graphs, SCCs give perfect cuts (think Amerika vs Europe)
|
||||
// This function performs an initial pre-partitioning using these sccs.
|
||||
std::vector<GraphView> FakeFirstPartitionWithSCC(const std::size_t small_component_size);
|
||||
};
|
||||
|
||||
} // namespace partition
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define OSRM_PARTITION_RECURSIVE_BISECTION_STATE_HPP_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include "partition/bisection_graph.hpp"
|
||||
@@ -62,26 +63,22 @@ class RecursiveBisectionState
|
||||
public:
|
||||
// The ID in the partition array
|
||||
using BisectionID = std::uint32_t;
|
||||
using IDIterator = std::vector<NodeID>::const_iterator;
|
||||
using NodeIterator = BisectionGraph::ConstNodeIterator;
|
||||
|
||||
RecursiveBisectionState(const BisectionGraph &bisection_graph);
|
||||
RecursiveBisectionState(BisectionGraph &bisection_graph);
|
||||
~RecursiveBisectionState();
|
||||
|
||||
BisectionID GetBisectionID(const NodeID nid) const;
|
||||
BisectionID GetBisectionID(const NodeID node) const;
|
||||
|
||||
// Bisects the node id array's sub-range based on the partition mask.
|
||||
// Returns: partition point of the bisection: iterator to the second group's first element.
|
||||
IDIterator ApplyBisection(const IDIterator begin,
|
||||
const IDIterator end,
|
||||
const std::vector<bool> &partition);
|
||||
|
||||
const IDIterator Begin() const;
|
||||
const IDIterator End() const;
|
||||
NodeIterator ApplyBisection(NodeIterator begin,
|
||||
const NodeIterator end,
|
||||
const std::size_t depth,
|
||||
const std::vector<bool> &partition);
|
||||
|
||||
private:
|
||||
const BisectionGraph &bisection_graph;
|
||||
|
||||
std::vector<NodeID> id_array;
|
||||
BisectionGraph &bisection_graph;
|
||||
std::vector<BisectionID> bisection_ids;
|
||||
};
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ void reorderFirstLast(RandomIt first, RandomIt last, std::size_t n, Comparator c
|
||||
{
|
||||
BOOST_ASSERT_MSG(n <= (last - first) / std::size_t{2}, "overlapping subranges not allowed");
|
||||
|
||||
if (n == 0 or (last - first < 2))
|
||||
if (n == 0 || (last - first < 2))
|
||||
return;
|
||||
|
||||
// Reorder first n: guarantees that the predicate holds for the first elements.
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef OSRM_PARTITION_TARJAN_GRAPH_WRAPPER_HPP_
|
||||
#define OSRM_PARTITION_TARJAN_GRAPH_WRAPPER_HPP_
|
||||
|
||||
#include "partition/bisection_graph.hpp"
|
||||
#include "util/integer_range.hpp"
|
||||
#include "util/typedefs.hpp"
|
||||
|
||||
namespace osrm
|
||||
{
|
||||
namespace partition
|
||||
{
|
||||
|
||||
class TarjanGraphWrapper
|
||||
{
|
||||
public:
|
||||
TarjanGraphWrapper(const BisectionGraph &bisection_graph);
|
||||
|
||||
std::size_t GetNumberOfNodes() const;
|
||||
util::range<EdgeID> GetAdjacentEdgeRange(const NodeID nid) const;
|
||||
NodeID GetTarget(const EdgeID eid) const;
|
||||
|
||||
protected:
|
||||
const BisectionGraph &bisection_graph;
|
||||
};
|
||||
|
||||
} // namespace partition
|
||||
} // namespace osrm
|
||||
|
||||
#endif // OSRM_PARTITION_TARJAN_GRAPH_WRAPPER_HPP_
|
||||
Reference in New Issue
Block a user