Initial Skeleton for Recursive Bisection via Inertial Flow

This commit is contained in:
Moritz Kobitzsch
2017-01-23 11:50:03 +01:00
committed by Patrick Niklaus
parent 07221f5a48
commit d56db500d3
18 changed files with 868 additions and 48 deletions
@@ -59,7 +59,6 @@ class ContiguousInternalMemoryDataFacade : public BaseDataFacade
using GraphNode = QueryGraph::NodeArrayEntry;
using GraphEdge = QueryGraph::EdgeArrayEntry;
using IndexBlock = util::RangeTable<16, true>::BlockT;
using InputEdge = QueryGraph::InputEdge;
using RTreeLeaf = super::RTreeLeaf;
using SharedRTree =
util::StaticRTree<RTreeLeaf, util::ShM<util::Coordinate, true>::vector, true>;
+99
View File
@@ -0,0 +1,99 @@
#ifndef OSRM_BISECTION_GRAPH_HPP_
#define OSRM_BISECTION_GRAPH_HPP_
#include "util/coordinate.hpp"
#include "util/static_graph.hpp"
#include "util/typedefs.hpp"
#include "extractor/edge_based_edge.hpp"
#include <cstddef>
#include <tuple>
namespace osrm
{
namespace partition
{
// Required for usage in static graph
struct BisectionNode
{
std::size_t first_edge;
util::Coordinate cordinate;
};
// The edge is used within a partition
struct BisectionEdge
{
NodeID target;
std::int32_t data; // will be one, but we have the space...
};
// workaround of how static graph assumes edges to be formatted :(
using BisectionGraph = util::FlexibleStaticGraph<BisectionNode, BisectionEdge>;
template <typename InputEdge> std::vector<InputEdge> groupBySource(std::vector<InputEdge> edges)
{
std::sort(edges.begin(), edges.end(), [](const auto &lhs, const auto &rhs) {
return std::tie(lhs.source, lhs.target) < std::tie(rhs.source, rhs.target);
});
return edges;
}
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);
// stateful transform, counting node ids and moving the edge itr forward
const auto coordinate_to_bisection_node =
[ edge_itr = edges.begin(), node_id = 0u, &edges ](
const util::Coordinate coordinate) mutable->BisectionNode
{
const auto edges_of_node = edge_itr;
// count all edges with this source
while (edge_itr != edges.end() && edge_itr->source == node_id)
++edge_itr;
// go to the next node
++node_id;
return {static_cast<std::size_t>(std::distance(edges.begin(), edges_of_node)), coordinate};
};
std::transform(coordinates.begin(),
coordinates.end(),
std::back_inserter(result),
coordinate_to_bisection_node);
// sentinel element
result.push_back(
{edges.size(), util::Coordinate(util::FloatLongitude{0.0}, util::FloatLatitude{0.0})});
return result;
}
template <typename InputEdge>
std::vector<BisectionEdge> adaptToBisectionEdge(std::vector<InputEdge> edges)
{
std::vector<BisectionEdge> result;
result.reserve(edges.size());
std::transform(edges.begin(),
edges.end(),
std::back_inserter(result),
[](const auto &edge) -> BisectionEdge {
return {edge.target, 1};
});
return result;
}
} // namespace partition
} // namespace osrm
#endif // OSRM_BISECTION_GRAPH_HPP_
+76
View File
@@ -0,0 +1,76 @@
#ifndef OSRM_PARTITION_GRAPHVIEW_HPP_
#define OSRM_PARTITION_GRAPHVIEW_HPP_
#include "partition/bisection_graph.hpp"
#include "partition/recursive_bisection_state.hpp"
#include <boost/iterator/filter_iterator.hpp>
#include <boost/iterator/iterator_facade.hpp>
namespace osrm
{
namespace partition
{
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;
};
// a wrapper around the EdgeIDs returned by the static graph to make them iterable
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;
void increment() { position++; }
bool equal(const EdgeIDIterator &other) const { return position == other.position; }
const EdgeID &dereference() const { return position; }
EdgeID position;
};
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);
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;
private:
const BisectionGraph &bisection_graph;
const RecursiveBisectionState &bisection_state;
const RecursiveBisectionState::IDIterator begin;
const RecursiveBisectionState::IDIterator end;
};
} // namespace partition
} // namespace osrm
#endif // OSRM_PARTITION_GRAPHVIEW_HPP_
+25
View File
@@ -0,0 +1,25 @@
#ifndef OSRM_PARTITION_INERTIAL_FLOW_HPP_
#define OSRM_PARTITION_INERTIAL_FLOW_HPP_
#include "partition/graph_view.hpp"
#include <vector>
namespace osrm
{
namespace partition
{
class InertialFlow
{
public:
InertialFlow(const GraphView &view);
std::vector<bool> ComputePartition(const double balance, const double source_sink_rate);
private:
const GraphView &view;
};
} // namespace partition
} // namespace osrm
#endif // OSRM_PARTITION_INERTIAL_FLOW_HPP_
+47
View File
@@ -0,0 +1,47 @@
#ifndef PARTITIONER_CONFIG_HPP
#define PARTITIONER_CONFIG_HPP
#include <boost/filesystem/path.hpp>
#include <array>
#include <string>
namespace osrm
{
namespace partition
{
struct PartitionConfig
{
PartitionConfig() noexcept : requested_num_threads(0) {}
void UseDefaults()
{
std::string basepath = base_path.string();
const std::string ext = ".osrm";
const auto pos = basepath.find(ext);
if (pos != std::string::npos)
{
basepath.replace(pos, ext.size(), "");
}
else
{
// unknown extension
}
edge_based_graph_path = basepath + ".osrm.ebg";
partition_path = basepath + ".osrm.partition";
}
// might be changed to the node based graph at some point
boost::filesystem::path base_path;
boost::filesystem::path edge_based_graph_path;
boost::filesystem::path partition_path;
unsigned requested_num_threads;
};
}
}
#endif // PARTITIONER_CONFIG_HPP
+21
View File
@@ -0,0 +1,21 @@
#ifndef OSRM_PARTITION_PARTITIONER_HPP_
#define OSRM_PARTITION_PARTITIONER_HPP_
#include "partition/partition_config.hpp"
namespace osrm
{
namespace partition
{
// tool access to the recursive partitioner
class Partitioner
{
public:
int Run(const PartitionConfig &config);
};
} // namespace partition
} // namespace osrm
#endif // OSRM_PARTITION_PARTITIONER_HPP_
+30
View File
@@ -0,0 +1,30 @@
#ifndef OSRM_PARTITION_RECURSIVE_BISECTION_HPP_
#define OSRM_PARTITION_RECURSIVE_BISECTION_HPP_
#include "partition/bisection_graph.hpp"
#include "partition/recursive_bisection_state.hpp"
#include <cstddef>
namespace osrm
{
namespace partition
{
class RecursiveBisection
{
public:
RecursiveBisection(std::size_t maximum_cell_size,
double balance,
double boundary_factor,
const BisectionGraph &bisection_graph);
private:
const BisectionGraph &bisection_graph;
RecursiveBisectionState internal_state;
};
} // namespace partition
} // namespace osrm
#endif // OSRM_PARTITION_RECURSIVE_BISECTION_HPP_
@@ -0,0 +1,74 @@
#ifndef OSRM_PARTITION_RECURSIVE_BISECTION_STATE_HPP_
#define OSRM_PARTITION_RECURSIVE_BISECTION_STATE_HPP_
#include <cstddef>
#include <vector>
#include "partition/bisection_graph.hpp"
#include "util/typedefs.hpp"
namespace osrm
{
namespace partition
{
// The recursive state describes the relation between our global graph and the recursive state in a
// recursive bisection.
// 
// We describe the state with the use of two arrays:
// 
// The id-arrays keeps nodes in order, based on their partitioning. Initially, it contains all nodes
// in sorted order:
// 
// ids: [0,1,2,3,4,5,6,7,8,9]
// 
// When partitioned (for this example we use even : odd), the arrays is re-ordered to group all
// elements within a single cell of the partition:
// 
// ids: [0,2,4,6,8,1,3,5,7,9]
//
// This can be performed recursively by interpreting the arrays [0,2,4,6,8] and [1,3,5,7,9] as new
// input.
//
// The partitioning array describes all results of the partitioning in form of `left` or `right`.
// It is a sequence of bits for every id that describes if it is moved to the `front` or `back`
// during the split of the ID array. In the example, we would get the result
// 
// bisection-ids: [0,1,0,1,0,1,0,1,0,1]
// 
// Further partitioning [0,2,4,6,8] into [0,4,8], [2,6] and [1,3,5,7,9] into [1,3,9] and [5,7]
// the result would be:
// 
// bisection-ids: [00,10,01,10,00,11,01,11,00,10]
class RecursiveBisectionState
{
public:
// the ID in the partition arr
using BisectionID = std::uint32_t;
using IDIterator = std::vector<NodeID>::const_iterator;
RecursiveBisectionState(const BisectionGraph &bisection_graph);
~RecursiveBisectionState();
BisectionID GetBisectionID(const NodeID nid) const;
// returns the center of the bisection
IDIterator ApplyBisection(const IDIterator begin,
const IDIterator end,
const std::vector<bool> &partition);
const IDIterator Begin() const;
const IDIterator End() const;
private:
const BisectionGraph &bisection_graph;
std::vector<NodeID> id_array;
std::vector<BisectionID> bisection_ids;
};
} // namespace partition
} // namespace osrm
#endif // OSRM_PARTITION_RECURSIVE_BISECTION_STATE_HPP_
+63 -45
View File
@@ -18,54 +18,64 @@ namespace osrm
namespace util
{
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
namespace static_graph_details
{
using NodeIterator = NodeID;
using EdgeIterator = NodeID;
struct NodeArrayEntry
{
// index of the first edge
EdgeIterator first_edge;
};
template <typename EdgeDataT> struct EdgeArrayEntry
{
NodeID target;
EdgeDataT data;
};
template <typename EdgeDataT> class SortableEdgeWithData
{
public:
using NodeIterator = NodeID;
using EdgeIterator = NodeID;
using EdgeData = EdgeDataT;
NodeIterator source;
NodeIterator target;
EdgeDataT data;
template <typename... Ts>
SortableEdgeWithData(NodeIterator source, NodeIterator target, Ts &&... data)
: source(source), target(target), data(std::forward<Ts>(data)...)
{
}
bool operator<(const SortableEdgeWithData &right) const
{
if (source != right.source)
{
return source < right.source;
}
return target < right.target;
}
};
} // namespace static_graph_details
template <typename NodeT, typename EdgeT, bool UseSharedMemory = false> class FlexibleStaticGraph
{
public:
using NodeIterator = static_graph_details::NodeIterator;
using EdgeIterator = static_graph_details::EdgeIterator;
using EdgeData = decltype(EdgeT::data);
using EdgeRange = range<EdgeIterator>;
class InputEdge
{
public:
NodeIterator source;
NodeIterator target;
EdgeDataT data;
template <typename... Ts>
InputEdge(NodeIterator source, NodeIterator target, Ts &&... data)
: source(source), target(target), data(std::forward<Ts>(data)...)
{
}
bool operator<(const InputEdge &right) const
{
if (source != right.source)
{
return source < right.source;
}
return target < right.target;
}
};
struct NodeArrayEntry
{
// index of the first edge
EdgeIterator first_edge;
};
struct EdgeArrayEntry
{
NodeID target;
EdgeDataT data;
};
using NodeArrayEntry = NodeT;
using EdgeArrayEntry = EdgeT;
EdgeRange GetAdjacentEdgeRange(const NodeID node) const
{
return irange(BeginEdges(node), EndEdges(node));
}
template <typename ContainerT> StaticGraph(const int nodes, const ContainerT &graph)
template <typename ContainerT> FlexibleStaticGraph(const int nodes, const ContainerT &graph)
{
BOOST_ASSERT(std::is_sorted(const_cast<ContainerT &>(graph).begin(),
const_cast<ContainerT &>(graph).end()));
@@ -99,8 +109,8 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
}
}
StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes,
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector &edges)
FlexibleStaticGraph(typename ShM<NodeT, UseSharedMemory>::vector &nodes,
typename ShM<EdgeT, 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());
@@ -121,9 +131,9 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
return NodeIterator(edge_array[e].target);
}
EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; }
auto &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; }
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_array[e].data; }
const auto &GetEdgeData(const EdgeIterator e) const { return edge_array[e].data; }
EdgeIterator BeginEdges(const NodeIterator n) const
{
@@ -200,13 +210,21 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
return current_iterator;
}
const NodeArrayEntry& GetNode(const NodeID nid) const { return node_array[nid]; }
const EdgeArrayEntry& GetEdge(const EdgeID eid) const { return edge_array[eid]; }
private:
NodeIterator number_of_nodes;
EdgeIterator number_of_edges;
typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array;
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array;
typename ShM<NodeT, UseSharedMemory>::vector node_array;
typename ShM<EdgeT, UseSharedMemory>::vector edge_array;
};
template <typename EdgeDataT, bool UseSharedMemory = false>
using StaticGraph = FlexibleStaticGraph<static_graph_details::NodeArrayEntry,
static_graph_details::EdgeArrayEntry<EdgeDataT>,
UseSharedMemory>;
}
}