osrm-backend/include/partitioner/partition_graph.hpp
2024-05-06 09:14:46 +02:00

160 lines
5.5 KiB
C++

#ifndef OSRM_PARTITIONER_GRAPH_HPP_
#define OSRM_PARTITIONER_GRAPH_HPP_
#include <algorithm>
#include <cstddef>
#include <functional>
#include <iterator>
#include <vector>
#include "util/typedefs.hpp"
#include <boost/range/iterator_range.hpp>
namespace osrm::partitioner
{
// forward declaration to allow finding friends
template <typename NodeEntryT, typename EdgeEntryT> class RemappableGraph;
// 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_)
{
}
private:
// only to be modified by the graph itself
std::size_t edges_begin;
std::size_t edges_end;
// give the graph access to the node data wrapper
template <typename NodeEntryT, typename EdgeEntryT> friend class RemappableGraph;
};
using RemappableGraphNode = NodeEntryWrapper<struct zero_base_class>;
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; }
EdgeID BeginEdgeID(const NodeID nid) const { return nodes[nid].edges_begin; }
EdgeID EndEdgeID(const NodeID nid) const { return nodes[nid].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()); }
NodeID GetID(const NodeT &node) const
{
BOOST_ASSERT(&node >= nodes.data() && &node <= &nodes.back());
return (&node - nodes.data());
}
EdgeID GetID(const EdgeT &edge) const
{
BOOST_ASSERT(&edge >= edges.data() && &edge <= &edges.back());
return (&edge - edges.data());
}
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.data() && &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 osrm::partitioner
#endif // OSRM_PARTITIONER_GRAPH_HPP_