2014-11-28 06:13:18 -05:00
|
|
|
#ifndef DYNAMICGRAPH_HPP
|
|
|
|
#define DYNAMICGRAPH_HPP
|
2010-07-09 05:05:40 -04:00
|
|
|
|
2016-01-02 11:13:44 -05:00
|
|
|
#include "util/deallocating_vector.hpp"
|
|
|
|
#include "util/integer_range.hpp"
|
2017-05-19 18:28:01 -04:00
|
|
|
#include "util/permutation.hpp"
|
2016-01-02 11:13:44 -05:00
|
|
|
#include "util/typedefs.hpp"
|
2013-06-24 17:02:28 -04:00
|
|
|
|
2017-04-04 19:54:30 -04:00
|
|
|
#include "storage/io_fwd.hpp"
|
|
|
|
|
2013-06-26 09:50:06 -04:00
|
|
|
#include <boost/assert.hpp>
|
2014-05-07 08:44:18 -04:00
|
|
|
|
|
|
|
#include <cstdint>
|
2013-06-24 17:02:28 -04:00
|
|
|
|
2010-07-09 05:05:40 -04:00
|
|
|
#include <algorithm>
|
2015-04-16 08:30:52 -04:00
|
|
|
#include <atomic>
|
2010-09-13 10:16:07 -04:00
|
|
|
#include <limits>
|
2015-04-16 08:30:52 -04:00
|
|
|
#include <tuple>
|
2013-06-24 17:02:28 -04:00
|
|
|
#include <vector>
|
2012-11-15 07:39:23 -05:00
|
|
|
|
2016-01-05 10:51:13 -05:00
|
|
|
namespace osrm
|
|
|
|
{
|
|
|
|
namespace util
|
|
|
|
{
|
2017-04-02 13:15:20 -04:00
|
|
|
template <typename EdgeDataT> class DynamicGraph;
|
|
|
|
|
|
|
|
namespace serialization
|
|
|
|
{
|
|
|
|
template <typename EdgeDataT, bool UseSharedMemory>
|
|
|
|
void read(storage::io::FileReader &reader, DynamicGraph<EdgeDataT> &graph);
|
|
|
|
|
|
|
|
template <typename EdgeDataT, bool UseSharedMemory>
|
2017-04-04 19:01:00 -04:00
|
|
|
void write(storage::io::FileWriter &writer, const DynamicGraph<EdgeDataT> &graph);
|
2017-04-02 13:15:20 -04:00
|
|
|
}
|
2016-01-05 10:51:13 -05:00
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
template <typename EdgeDataT> class DynamicGraph
|
|
|
|
{
|
|
|
|
public:
|
2014-08-19 07:01:38 -04:00
|
|
|
using EdgeData = EdgeDataT;
|
2016-06-11 11:23:29 -04:00
|
|
|
using NodeIterator = std::uint32_t;
|
|
|
|
using EdgeIterator = std::uint32_t;
|
2016-01-05 10:51:13 -05:00
|
|
|
using EdgeRange = range<EdgeIterator>;
|
2014-05-07 12:39:16 -04:00
|
|
|
|
|
|
|
class InputEdge
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
NodeIterator source;
|
|
|
|
NodeIterator target;
|
|
|
|
EdgeDataT data;
|
2014-07-14 11:35:26 -04:00
|
|
|
|
2015-01-27 11:44:46 -05:00
|
|
|
InputEdge()
|
|
|
|
: source(std::numeric_limits<NodeIterator>::max()),
|
|
|
|
target(std::numeric_limits<NodeIterator>::max())
|
|
|
|
{
|
|
|
|
}
|
2014-07-15 05:50:08 -04:00
|
|
|
|
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-07-14 11:35:26 -04:00
|
|
|
|
2015-02-19 13:15:16 -05:00
|
|
|
bool operator<(const InputEdge &rhs) const
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
2015-02-19 13:15:16 -05:00
|
|
|
return std::tie(source, target) < std::tie(rhs.source, rhs.target);
|
2011-10-10 12:56:01 -04:00
|
|
|
}
|
2014-05-07 12:39:16 -04:00
|
|
|
};
|
|
|
|
|
2017-08-18 18:31:04 -04:00
|
|
|
DynamicGraph() : DynamicGraph(0) {}
|
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
// Constructs an empty graph with a given number of nodes.
|
2014-10-17 08:19:33 -04:00
|
|
|
explicit DynamicGraph(NodeIterator nodes) : number_of_nodes(nodes), number_of_edges(0)
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
2015-04-16 05:25:43 -04:00
|
|
|
node_array.reserve(number_of_nodes);
|
|
|
|
node_array.resize(number_of_nodes);
|
2014-05-07 12:39:16 -04:00
|
|
|
|
2014-07-02 10:58:19 -04:00
|
|
|
edge_list.reserve(number_of_nodes * 1.1);
|
|
|
|
edge_list.resize(number_of_nodes);
|
2014-05-07 12:39:16 -04:00
|
|
|
}
|
|
|
|
|
2015-05-04 12:43:16 -04:00
|
|
|
/**
|
|
|
|
* Constructs a DynamicGraph from a list of edges sorted by source node id.
|
|
|
|
*/
|
2014-10-17 08:19:33 -04:00
|
|
|
template <class ContainerT> DynamicGraph(const NodeIterator nodes, const ContainerT &graph)
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
2015-06-28 09:30:40 -04:00
|
|
|
// we need to cast here because DeallocatingVector does not have a valid const iterator
|
2016-01-05 06:04:04 -05:00
|
|
|
BOOST_ASSERT(std::is_sorted(const_cast<ContainerT &>(graph).begin(),
|
|
|
|
const_cast<ContainerT &>(graph).end()));
|
2015-06-28 09:30:40 -04:00
|
|
|
|
2014-07-02 09:27:09 -04:00
|
|
|
number_of_nodes = nodes;
|
2015-02-10 05:35:58 -05:00
|
|
|
number_of_edges = static_cast<EdgeIterator>(graph.size());
|
2015-04-16 05:25:43 -04:00
|
|
|
node_array.resize(number_of_nodes + 1);
|
2014-05-07 12:39:16 -04:00
|
|
|
EdgeIterator edge = 0;
|
|
|
|
EdgeIterator position = 0;
|
2016-01-05 10:51:13 -05:00
|
|
|
for (const auto node : irange(0u, number_of_nodes))
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
2015-04-16 05:25:43 -04:00
|
|
|
EdgeIterator last_edge = edge;
|
2014-07-02 09:27:09 -04:00
|
|
|
while (edge < number_of_edges && graph[edge].source == node)
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
|
|
|
++edge;
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|
2015-04-16 05:25:43 -04:00
|
|
|
node_array[node].first_edge = position;
|
|
|
|
node_array[node].edges = edge - last_edge;
|
|
|
|
position += node_array[node].edges;
|
2014-05-07 12:39:16 -04:00
|
|
|
}
|
2015-04-16 05:25:43 -04:00
|
|
|
node_array.back().first_edge = position;
|
2014-10-28 10:13:26 -04:00
|
|
|
edge_list.reserve(static_cast<std::size_t>(edge_list.size() * 1.1));
|
2014-07-02 10:58:19 -04:00
|
|
|
edge_list.resize(position);
|
2014-05-07 12:39:16 -04:00
|
|
|
edge = 0;
|
2016-01-05 10:51:13 -05:00
|
|
|
for (const auto node : irange(0u, number_of_nodes))
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
2016-01-05 10:51:13 -05:00
|
|
|
for (const auto i : irange(node_array[node].first_edge,
|
2016-01-07 19:31:57 -05:00
|
|
|
node_array[node].first_edge + node_array[node].edges))
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
2014-07-02 10:58:19 -04:00
|
|
|
edge_list[i].target = graph[edge].target;
|
2015-09-10 06:21:36 -04:00
|
|
|
BOOST_ASSERT(edge_list[i].target < number_of_nodes);
|
2014-07-02 10:58:19 -04:00
|
|
|
edge_list[i].data = graph[edge].data;
|
2014-05-07 12:39:16 -04:00
|
|
|
++edge;
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|
|
|
|
}
|
2014-05-07 12:39:16 -04:00
|
|
|
}
|
2010-09-13 10:16:07 -04:00
|
|
|
|
2017-08-22 15:53:44 -04:00
|
|
|
DynamicGraph(const DynamicGraph &other)
|
|
|
|
{
|
|
|
|
number_of_nodes = other.number_of_nodes;
|
|
|
|
// atomics can't be moved this is why we need an own constructor
|
|
|
|
number_of_edges = static_cast<std::uint32_t>(other.number_of_edges);
|
|
|
|
|
|
|
|
node_array = other.node_array;
|
|
|
|
edge_list = other.edge_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
DynamicGraph&operator=(const DynamicGraph &other)
|
|
|
|
{
|
|
|
|
auto copy_other = other;
|
|
|
|
*this = std::move(other);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2017-05-19 18:28:01 -04:00
|
|
|
DynamicGraph(DynamicGraph &&other)
|
|
|
|
{
|
|
|
|
number_of_nodes = other.number_of_nodes;
|
|
|
|
// atomics can't be moved this is why we need an own constructor
|
|
|
|
number_of_edges = static_cast<std::uint32_t>(other.number_of_edges);
|
|
|
|
|
|
|
|
node_array = std::move(other.node_array);
|
|
|
|
edge_list = std::move(other.edge_list);
|
|
|
|
}
|
|
|
|
|
|
|
|
DynamicGraph &operator=(DynamicGraph &&other)
|
|
|
|
{
|
|
|
|
number_of_nodes = other.number_of_nodes;
|
|
|
|
// atomics can't be moved this is why we need an own constructor
|
|
|
|
number_of_edges = static_cast<std::uint32_t>(other.number_of_edges);
|
|
|
|
|
|
|
|
node_array = std::move(other.node_array);
|
|
|
|
edge_list = std::move(other.edge_list);
|
|
|
|
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2014-07-02 09:27:09 -04:00
|
|
|
unsigned GetNumberOfNodes() const { return number_of_nodes; }
|
2010-09-13 10:16:07 -04:00
|
|
|
|
2014-07-02 09:27:09 -04:00
|
|
|
unsigned GetNumberOfEdges() const { return number_of_edges; }
|
2010-09-13 10:16:07 -04:00
|
|
|
|
2015-04-16 05:25:43 -04:00
|
|
|
unsigned GetOutDegree(const NodeIterator n) const { return node_array[n].edges; }
|
2010-09-13 10:16:07 -04:00
|
|
|
|
2014-05-20 09:40:14 -04:00
|
|
|
unsigned GetDirectedOutDegree(const NodeIterator n) const
|
|
|
|
{
|
|
|
|
unsigned degree = 0;
|
2016-01-05 10:51:13 -05:00
|
|
|
for (const auto edge : irange(BeginEdges(n), EndEdges(n)))
|
2014-05-20 09:40:14 -04:00
|
|
|
{
|
2015-06-28 18:42:22 -04:00
|
|
|
if (!GetEdgeData(edge).reversed)
|
2014-05-20 09:40:14 -04:00
|
|
|
{
|
|
|
|
++degree;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return degree;
|
|
|
|
}
|
|
|
|
|
2014-07-02 10:58:19 -04:00
|
|
|
NodeIterator GetTarget(const EdgeIterator e) const { return NodeIterator(edge_list[e].target); }
|
2010-09-13 10:16:07 -04:00
|
|
|
|
2014-07-02 10:58:19 -04:00
|
|
|
void SetTarget(const EdgeIterator e, const NodeIterator n) { edge_list[e].target = n; }
|
2013-12-12 18:32:12 -05:00
|
|
|
|
2014-07-02 10:58:19 -04:00
|
|
|
EdgeDataT &GetEdgeData(const EdgeIterator e) { return edge_list[e].data; }
|
2010-09-13 10:16:07 -04:00
|
|
|
|
2014-07-02 10:58:19 -04:00
|
|
|
const EdgeDataT &GetEdgeData(const EdgeIterator e) const { return edge_list[e].data; }
|
2010-09-13 10:16:07 -04:00
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
EdgeIterator BeginEdges(const NodeIterator n) const
|
|
|
|
{
|
2015-04-16 05:25:43 -04:00
|
|
|
return EdgeIterator(node_array[n].first_edge);
|
2014-05-07 12:39:16 -04:00
|
|
|
}
|
2010-09-13 10:16:07 -04:00
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
EdgeIterator EndEdges(const NodeIterator n) const
|
|
|
|
{
|
2015-04-16 05:25:43 -04:00
|
|
|
return EdgeIterator(node_array[n].first_edge + node_array[n].edges);
|
2014-05-07 12:39:16 -04:00
|
|
|
}
|
2010-09-13 10:16:07 -04:00
|
|
|
|
2014-05-19 07:00:27 -04:00
|
|
|
EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
|
2014-05-13 10:56:30 -04:00
|
|
|
{
|
2016-01-05 10:51:13 -05:00
|
|
|
return irange(BeginEdges(node), EndEdges(node));
|
2014-05-13 10:56:30 -04:00
|
|
|
}
|
|
|
|
|
2014-07-02 09:27:09 -04:00
|
|
|
NodeIterator InsertNode()
|
|
|
|
{
|
2015-04-16 05:25:43 -04:00
|
|
|
node_array.emplace_back(node_array.back());
|
2014-07-02 10:58:19 -04:00
|
|
|
number_of_nodes += 1;
|
2014-07-02 09:27:09 -04:00
|
|
|
|
|
|
|
return number_of_nodes;
|
|
|
|
}
|
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
// adds an edge. Invalidates edge iterators for the source node
|
|
|
|
EdgeIterator InsertEdge(const NodeIterator from, const NodeIterator to, const EdgeDataT &data)
|
|
|
|
{
|
2015-04-16 05:25:43 -04:00
|
|
|
Node &node = node_array[from];
|
2017-01-11 10:49:44 -05:00
|
|
|
EdgeIterator one_beyond_last_of_node = node.edges + node.first_edge;
|
|
|
|
// if we can't write at the end of this nodes edges
|
|
|
|
// that is: the end is the end of the edge_list,
|
|
|
|
// or the beginning of the next nodes edges
|
|
|
|
if (one_beyond_last_of_node == edge_list.size() || !isDummy(one_beyond_last_of_node))
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
2017-01-11 10:49:44 -05:00
|
|
|
// can we write before this nodes edges?
|
2015-04-16 05:25:43 -04:00
|
|
|
if (node.first_edge != 0 && isDummy(node.first_edge - 1))
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
2015-04-16 05:25:43 -04:00
|
|
|
node.first_edge--;
|
|
|
|
edge_list[node.first_edge] = edge_list[node.first_edge + node.edges];
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|
2014-05-07 12:39:16 -04:00
|
|
|
else
|
|
|
|
{
|
2017-01-11 10:49:44 -05:00
|
|
|
// we have to move this nodes edges to the end of the edge_list
|
2014-07-02 10:58:19 -04:00
|
|
|
EdgeIterator newFirstEdge = (EdgeIterator)edge_list.size();
|
2014-05-07 12:39:16 -04:00
|
|
|
unsigned newSize = node.edges * 1.1 + 2;
|
2014-07-02 10:58:19 -04:00
|
|
|
EdgeIterator requiredCapacity = newSize + edge_list.size();
|
|
|
|
EdgeIterator oldCapacity = edge_list.capacity();
|
2017-01-11 10:49:44 -05:00
|
|
|
// make sure there is enough space at the end
|
2014-05-07 12:39:16 -04:00
|
|
|
if (requiredCapacity >= oldCapacity)
|
|
|
|
{
|
2014-07-02 10:58:19 -04:00
|
|
|
edge_list.reserve(requiredCapacity * 1.1);
|
2010-09-13 10:16:07 -04:00
|
|
|
}
|
2014-07-02 10:58:19 -04:00
|
|
|
edge_list.resize(edge_list.size() + newSize);
|
2017-01-11 10:49:44 -05:00
|
|
|
// move the edges over and invalidate the old ones
|
2016-01-05 10:51:13 -05:00
|
|
|
for (const auto i : irange(0u, node.edges))
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
2015-04-16 05:25:43 -04:00
|
|
|
edge_list[newFirstEdge + i] = edge_list[node.first_edge + i];
|
|
|
|
makeDummy(node.first_edge + i);
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|
2017-01-11 10:49:44 -05:00
|
|
|
// invalidate until the end of edge_list
|
2016-01-05 10:51:13 -05:00
|
|
|
for (const auto i : irange(node.edges + 1, newSize))
|
2014-07-02 10:58:19 -04:00
|
|
|
{
|
2014-05-07 12:39:16 -04:00
|
|
|
makeDummy(newFirstEdge + i);
|
2014-07-02 10:58:19 -04:00
|
|
|
}
|
2015-04-16 05:25:43 -04:00
|
|
|
node.first_edge = newFirstEdge;
|
2010-07-09 05:05:40 -04:00
|
|
|
}
|
|
|
|
}
|
2017-01-11 10:49:44 -05:00
|
|
|
// get the position for the edge that is to be inserted
|
|
|
|
// and write it
|
2015-04-16 05:25:43 -04:00
|
|
|
Edge &edge = edge_list[node.first_edge + node.edges];
|
2014-05-07 12:39:16 -04:00
|
|
|
edge.target = to;
|
|
|
|
edge.data = data;
|
2014-07-02 09:27:09 -04:00
|
|
|
++number_of_edges;
|
2014-05-07 12:39:16 -04:00
|
|
|
++node.edges;
|
2015-04-16 05:25:43 -04:00
|
|
|
return EdgeIterator(node.first_edge + node.edges);
|
2014-05-07 12:39:16 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// removes an edge. Invalidates edge iterators for the source node
|
|
|
|
void DeleteEdge(const NodeIterator source, const EdgeIterator e)
|
|
|
|
{
|
2015-04-16 05:25:43 -04:00
|
|
|
Node &node = node_array[source];
|
2014-07-02 09:27:09 -04:00
|
|
|
--number_of_edges;
|
2014-05-07 12:39:16 -04:00
|
|
|
--node.edges;
|
|
|
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != node.edges);
|
2015-04-16 05:25:43 -04:00
|
|
|
const unsigned last = node.first_edge + node.edges;
|
2014-05-07 12:39:16 -04:00
|
|
|
BOOST_ASSERT(std::numeric_limits<unsigned>::max() != last);
|
|
|
|
// swap with last edge
|
2014-07-02 10:58:19 -04:00
|
|
|
edge_list[e] = edge_list[last];
|
2014-05-07 12:39:16 -04:00
|
|
|
makeDummy(last);
|
|
|
|
}
|
|
|
|
|
|
|
|
// removes all edges (source,target)
|
|
|
|
int32_t DeleteEdgesTo(const NodeIterator source, const NodeIterator target)
|
|
|
|
{
|
|
|
|
int32_t deleted = 0;
|
|
|
|
for (EdgeIterator i = BeginEdges(source), iend = EndEdges(source); i < iend - deleted; ++i)
|
|
|
|
{
|
2014-07-02 10:58:19 -04:00
|
|
|
if (edge_list[i].target == target)
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
|
|
|
do
|
|
|
|
{
|
|
|
|
deleted++;
|
2014-07-02 10:58:19 -04:00
|
|
|
edge_list[i] = edge_list[iend - deleted];
|
2014-05-07 12:39:16 -04:00
|
|
|
makeDummy(iend - deleted);
|
2014-07-02 10:58:19 -04:00
|
|
|
} while (i < iend - deleted && edge_list[i].target == target);
|
2014-05-07 12:39:16 -04:00
|
|
|
}
|
2010-09-13 10:16:07 -04:00
|
|
|
}
|
2010-07-09 05:05:40 -04:00
|
|
|
|
2014-07-02 09:27:09 -04:00
|
|
|
number_of_edges -= deleted;
|
2015-04-16 05:25:43 -04:00
|
|
|
node_array[source].edges -= deleted;
|
2014-05-07 12:39:16 -04:00
|
|
|
|
|
|
|
return deleted;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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)))
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
2014-07-02 10:58:19 -04:00
|
|
|
if (to == edge_list[i].target)
|
2014-05-07 12:39:16 -04:00
|
|
|
{
|
|
|
|
return i;
|
|
|
|
}
|
2010-09-13 10:16:07 -04:00
|
|
|
}
|
2015-04-16 18:20:37 -04:00
|
|
|
return SPECIAL_EDGEID;
|
2014-05-07 12:39:16 -04:00
|
|
|
}
|
|
|
|
|
2015-04-16 10:12:08 -04:00
|
|
|
// searches for a specific edge
|
|
|
|
EdgeIterator FindSmallestEdge(const NodeIterator from, const NodeIterator to) const
|
|
|
|
{
|
|
|
|
EdgeIterator smallest_edge = SPECIAL_EDGEID;
|
|
|
|
EdgeWeight smallest_weight = INVALID_EDGE_WEIGHT;
|
|
|
|
for (auto edge : GetAdjacentEdgeRange(from))
|
|
|
|
{
|
|
|
|
const NodeID target = GetTarget(edge);
|
|
|
|
const EdgeWeight weight = GetEdgeData(edge).distance;
|
|
|
|
if (target == to && weight < smallest_weight)
|
|
|
|
{
|
|
|
|
smallest_edge = edge;
|
|
|
|
smallest_weight = weight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return smallest_edge;
|
|
|
|
}
|
|
|
|
|
2015-04-16 18:22:51 -04:00
|
|
|
EdgeIterator FindEdgeInEitherDirection(const NodeIterator from, const NodeIterator to) const
|
|
|
|
{
|
|
|
|
EdgeIterator tmp = FindEdge(from, to);
|
|
|
|
return (SPECIAL_NODEID != tmp ? tmp : FindEdge(to, from));
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return current_iterator;
|
|
|
|
}
|
|
|
|
|
2017-05-19 18:28:01 -04:00
|
|
|
void Renumber(const std::vector<NodeID> &old_to_new_node)
|
|
|
|
{
|
|
|
|
// permutate everything but the sentinel
|
|
|
|
util::inplacePermutation(node_array.begin(), std::prev(node_array.end()), old_to_new_node);
|
|
|
|
|
|
|
|
// Build up edge permutation
|
|
|
|
auto new_edge_index = 0;
|
|
|
|
std::vector<EdgeID> old_to_new_edge(edge_list.size(), SPECIAL_EDGEID);
|
|
|
|
for (auto node : util::irange<NodeID>(0, number_of_nodes))
|
|
|
|
{
|
|
|
|
auto new_first_edge = new_edge_index;
|
|
|
|
// move all filled edges
|
|
|
|
for (auto edge : GetAdjacentEdgeRange(node))
|
|
|
|
{
|
|
|
|
edge_list[edge].target = old_to_new_node[edge_list[edge].target];
|
|
|
|
old_to_new_edge[edge] = new_edge_index++;
|
|
|
|
}
|
2017-08-18 19:52:36 -04:00
|
|
|
node_array[node].first_edge = new_first_edge;
|
|
|
|
}
|
|
|
|
auto number_of_valid_edges = new_edge_index;
|
|
|
|
|
|
|
|
// move all dummy edges to the end of the renumbered range
|
|
|
|
for (auto edge : util::irange<NodeID>(0, edge_list.size()))
|
|
|
|
{
|
|
|
|
if (old_to_new_edge[edge] == SPECIAL_EDGEID)
|
2017-05-19 18:28:01 -04:00
|
|
|
{
|
2017-08-18 19:52:36 -04:00
|
|
|
BOOST_ASSERT(isDummy(edge));
|
2017-05-19 18:28:01 -04:00
|
|
|
old_to_new_edge[edge] = new_edge_index++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOOST_ASSERT(std::find(old_to_new_edge.begin(), old_to_new_edge.end(), SPECIAL_EDGEID) ==
|
|
|
|
old_to_new_edge.end());
|
|
|
|
util::inplacePermutation(edge_list.begin(), edge_list.end(), old_to_new_edge);
|
2017-08-18 19:52:36 -04:00
|
|
|
// Remove useless dummy nodes at the end
|
|
|
|
edge_list.resize(number_of_valid_edges);
|
|
|
|
number_of_edges = number_of_valid_edges;
|
2017-05-19 18:28:01 -04:00
|
|
|
}
|
|
|
|
|
2014-05-07 12:39:16 -04:00
|
|
|
protected:
|
|
|
|
bool isDummy(const EdgeIterator edge) const
|
|
|
|
{
|
2014-07-02 10:58:19 -04:00
|
|
|
return edge_list[edge].target == (std::numeric_limits<NodeIterator>::max)();
|
2014-05-07 12:39:16 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void makeDummy(const EdgeIterator edge)
|
|
|
|
{
|
2014-07-02 10:58:19 -04:00
|
|
|
edge_list[edge].target = (std::numeric_limits<NodeIterator>::max)();
|
2014-05-07 12:39:16 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
struct Node
|
|
|
|
{
|
|
|
|
// index of the first edge
|
2015-04-16 05:25:43 -04:00
|
|
|
EdgeIterator first_edge;
|
2014-05-07 12:39:16 -04:00
|
|
|
// amount of edges
|
|
|
|
unsigned edges;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Edge
|
|
|
|
{
|
|
|
|
NodeIterator target;
|
|
|
|
EdgeDataT data;
|
|
|
|
};
|
|
|
|
|
2014-07-02 09:27:09 -04:00
|
|
|
NodeIterator number_of_nodes;
|
|
|
|
std::atomic_uint number_of_edges;
|
2014-05-07 12:39:16 -04:00
|
|
|
|
2015-04-16 05:25:43 -04:00
|
|
|
std::vector<Node> node_array;
|
2014-07-02 10:58:19 -04:00
|
|
|
DeallocatingVector<Edge> edge_list;
|
2010-07-09 05:05:40 -04:00
|
|
|
};
|
2016-01-05 10:51:13 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-28 06:13:18 -05:00
|
|
|
#endif // DYNAMICGRAPH_HPP
|