Initial Skeleton for Recursive Bisection via Inertial Flow
This commit is contained in:
committed by
Patrick Niklaus
parent
07221f5a48
commit
d56db500d3
@@ -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_
|
||||
@@ -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_
|
||||
@@ -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_
|
||||
@@ -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
|
||||
@@ -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_
|
||||
@@ -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_
|
||||
Reference in New Issue
Block a user