osrm-backend/include/util/static_graph.hpp

214 lines
6.3 KiB
C++
Raw Normal View History

#ifndef STATIC_GRAPH_HPP
#define STATIC_GRAPH_HPP
2016-05-27 15:05:04 -04:00
#include "util/integer_range.hpp"
2016-01-02 11:13:44 -05:00
#include "util/percent.hpp"
#include "util/shared_memory_vector_wrapper.hpp"
#include "util/typedefs.hpp"
2014-05-23 08:32:28 -04:00
#include <boost/assert.hpp>
#include <algorithm>
2014-05-05 11:19:47 -04:00
#include <limits>
#include <utility>
#include <vector>
2016-01-05 10:51:13 -05:00
namespace osrm
{
namespace util
{
2014-05-05 11:19:47 -04:00
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
{
public:
using NodeIterator = NodeID;
using EdgeIterator = NodeID;
using EdgeData = EdgeDataT;
2016-01-05 10:51:13 -05:00
using EdgeRange = range<EdgeIterator>;
2014-08-05 11:19:09 -04:00
2014-05-05 11:19:47 -04:00
class InputEdge
{
public:
NodeIterator source;
NodeIterator target;
EdgeDataT data;
2015-01-27 11:44:46 -05:00
template <typename... Ts>
InputEdge(NodeIterator source, NodeIterator target, Ts &&... data)
: source(source), target(target), data(std::forward<Ts>(data)...)
{
}
2014-05-05 11:19:47 -04:00
bool operator<(const InputEdge &right) const
{
if (source != right.source)
{
return source < right.source;
2013-09-18 11:49:49 -04:00
}
return target < right.target;
}
};
2014-05-05 11:19:47 -04:00
struct NodeArrayEntry
{
// index of the first edge
EdgeIterator first_edge;
};
2014-05-05 11:19:47 -04:00
struct EdgeArrayEntry
{
NodeID target;
EdgeDataT data;
};
EdgeRange GetAdjacentEdgeRange(const NodeID node) const
{
2016-01-05 10:51:13 -05:00
return irange(BeginEdges(node), EndEdges(node));
}
2016-01-05 06:04:04 -05:00
template <typename ContainerT> StaticGraph(const int nodes, const ContainerT &graph)
2014-05-05 11:19:47 -04:00
{
2016-01-05 06:04:04 -05:00
BOOST_ASSERT(std::is_sorted(const_cast<ContainerT &>(graph).begin(),
const_cast<ContainerT &>(graph).end()));
2014-05-05 11:19:47 -04:00
number_of_nodes = nodes;
2015-01-02 11:43:46 -05:00
number_of_edges = static_cast<EdgeIterator>(graph.size());
2014-05-05 11:19:47 -04:00
node_array.resize(number_of_nodes + 1);
EdgeIterator edge = 0;
EdgeIterator position = 0;
2016-01-05 10:51:13 -05:00
for (const auto node : irange(0u, number_of_nodes + 1))
2014-05-05 11:19:47 -04:00
{
EdgeIterator last_edge = edge;
2014-05-05 11:19:47 -04:00
while (edge < number_of_edges && graph[edge].source == node)
{
++edge;
}
node_array[node].first_edge = position; //=edge
position += edge - last_edge; // remove
}
2014-05-05 11:19:47 -04:00
edge_array.resize(position); //(edge)
edge = 0;
2016-01-05 10:51:13 -05:00
for (const auto node : irange(0u, number_of_nodes))
2014-05-05 11:19:47 -04:00
{
EdgeIterator e = node_array[node + 1].first_edge;
2016-01-05 10:51:13 -05:00
for (const auto i : irange(node_array[node].first_edge, e))
2014-05-05 11:19:47 -04:00
{
edge_array[i].target = graph[edge].target;
edge_array[i].data = graph[edge].data;
edge++;
}
}
}
2014-05-05 11:19:47 -04:00
StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes,
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector &edges)
{
2014-10-17 07:03:49 -04:00
number_of_nodes = static_cast<decltype(number_of_nodes)>(nodes.size() - 1);
number_of_edges = static_cast<decltype(number_of_edges)>(edges.size());
using std::swap;
swap(node_array, nodes);
swap(edge_array, edges);
}
2014-06-24 18:20:58 -04:00
unsigned GetNumberOfNodes() const { return number_of_nodes; }
2014-05-05 11:19:47 -04:00
unsigned GetNumberOfEdges() const { return number_of_edges; }
2014-06-24 18:20:58 -04:00
unsigned GetOutDegree(const NodeIterator n) const { return EndEdges(n) - BeginEdges(n); }
inline NodeIterator GetTarget(const EdgeIterator e) const
2014-05-05 11:19:47 -04:00
{
return NodeIterator(edge_array[e].target);
}
2015-04-16 05:25:43 -04:00
EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_array[e].data; }
2011-04-15 12:39:44 -04:00
2014-05-05 11:19:47 -04:00
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_array[e].data; }
2014-05-05 11:19:47 -04:00
EdgeIterator BeginEdges(const NodeIterator n) const
{
return EdgeIterator(node_array.at(n).first_edge);
}
2014-05-05 11:19:47 -04:00
EdgeIterator EndEdges(const NodeIterator n) const
{
return EdgeIterator(node_array.at(n + 1).first_edge);
}
2014-05-05 11:19:47 -04:00
// searches for a specific edge
EdgeIterator FindEdge(const NodeIterator from, const NodeIterator to) const
{
2016-01-05 10:51:13 -05:00
for (const auto i : irange(BeginEdges(from), EndEdges(from)))
{
if (to == edge_array[i].target)
{
return i;
}
}
return SPECIAL_EDGEID;
}
/**
* Finds the edge with the smallest `.distance` going from `from` to `to`
* @param from the source node ID
* @param to the target node ID
* @param filter a functor that returns a `bool` that determines whether an edge should be
* tested or not.
* Takes `EdgeData` as a parameter.
* @return the ID of the smallest edge if any were found that satisfied *filter*, or
* `SPECIAL_EDGEID` if no
* matching edge is found.
*/
template <typename FilterFunction>
2016-09-30 08:33:43 -04:00
EdgeIterator
FindSmallestEdge(const NodeIterator from, const NodeIterator to, FilterFunction &&filter) const
2014-05-05 11:19:47 -04:00
{
EdgeIterator smallest_edge = SPECIAL_EDGEID;
EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT;
for (auto edge : GetAdjacentEdgeRange(from))
2014-05-05 11:19:47 -04:00
{
const NodeID target = GetTarget(edge);
2016-09-30 08:33:43 -04:00
const auto &data = GetEdgeData(edge);
if (target == to && data.distance < smallest_weight &&
std::forward<FilterFunction>(filter)(data))
2014-05-05 11:19:47 -04:00
{
smallest_edge = edge;
smallest_weight = data.distance;
}
}
2014-05-05 11:19:47 -04:00
return smallest_edge;
}
2014-05-05 11:19:47 -04:00
EdgeIterator FindEdgeInEitherDirection(const NodeIterator from, const NodeIterator to) const
{
EdgeIterator tmp = FindEdge(from, to);
return (SPECIAL_NODEID != tmp ? tmp : FindEdge(to, from));
2011-07-21 10:30:36 -04:00
}
2014-05-05 11:19:47 -04:00
EdgeIterator
FindEdgeIndicateIfReverse(const NodeIterator from, const NodeIterator to, bool &result) const
{
EdgeIterator current_iterator = FindEdge(from, to);
if (SPECIAL_NODEID == current_iterator)
{
current_iterator = FindEdge(to, from);
if (SPECIAL_NODEID != current_iterator)
{
2011-07-18 11:50:08 -04:00
result = true;
2013-09-18 11:49:49 -04:00
}
2011-07-18 11:50:08 -04:00
}
2014-05-05 11:19:47 -04:00
return current_iterator;
2011-07-18 11:50:08 -04:00
}
2014-05-05 11:19:47 -04:00
private:
NodeIterator number_of_nodes;
EdgeIterator number_of_edges;
2014-05-05 11:19:47 -04:00
typename ShM<NodeArrayEntry, UseSharedMemory>::vector node_array;
typename ShM<EdgeArrayEntry, UseSharedMemory>::vector edge_array;
};
2016-01-05 10:51:13 -05:00
}
}
#endif // STATIC_GRAPH_HPP