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
+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_