Refactor StaticGraph generation

This commit is contained in:
Patrick Niklaus 2017-03-07 03:09:18 +00:00 committed by Patrick Niklaus
parent 78a199e2fb
commit 58681fa7ea
2 changed files with 40 additions and 43 deletions

View File

@ -84,6 +84,17 @@ template <typename EdgeDataT> struct SortableEdgeWithData : SortableEdgeWithData
} }
}; };
template <typename EntryT, typename OtherEdge>
EntryT edgeToEntry(const OtherEdge &from, std::true_type)
{
return EntryT{from.target, from.data};
}
template <typename EntryT, typename OtherEdge>
EntryT edgeToEntry(const OtherEdge &from, std::false_type)
{
return EntryT{from.target};
}
} // namespace static_graph_details } // namespace static_graph_details
template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
@ -101,39 +112,12 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
return irange(BeginEdges(node), EndEdges(node)); return irange(BeginEdges(node), EndEdges(node));
} }
template <typename ContainerT> StaticGraph(const int nodes, const ContainerT &graph) template <typename ContainerT> StaticGraph(const int nodes, const ContainerT &edges)
{ {
BOOST_ASSERT(std::is_sorted(const_cast<ContainerT &>(graph).begin(), BOOST_ASSERT(std::is_sorted(const_cast<ContainerT &>(edges).begin(),
const_cast<ContainerT &>(graph).end())); const_cast<ContainerT &>(edges).end()));
number_of_nodes = nodes; InitializeFromSortedEdgeRange(nodes, edges.begin(), edges.end());
number_of_edges = static_cast<EdgeIterator>(graph.size());
node_array.resize(number_of_nodes + 1);
EdgeIterator edge = 0;
EdgeIterator position = 0;
for (const auto node : irange(0u, number_of_nodes + 1))
{
EdgeIterator last_edge = edge;
while (edge < number_of_edges && graph[edge].source == node)
{
++edge;
}
node_array[node].first_edge = position; //=edge
position += edge - last_edge; // remove
}
edge_array.resize(position); //(edge)
edge = 0;
for (const auto node : irange(0u, number_of_nodes))
{
EdgeIterator e = node_array[node + 1].first_edge;
for (const auto i : irange(node_array[node].first_edge, e))
{
edge_array[i].target = graph[edge].target;
CopyDataIfAvailable(
edge_array[i], graph[edge], traits::HasDataMember<EdgeArrayEntry>{});
edge++;
}
}
} }
StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes, StaticGraph(typename ShM<NodeArrayEntry, UseSharedMemory>::vector &nodes,
@ -245,22 +229,33 @@ template <typename EdgeDataT, bool UseSharedMemory = false> class StaticGraph
const NodeArrayEntry &GetNode(const NodeID nid) const { return node_array[nid]; } const NodeArrayEntry &GetNode(const NodeID nid) const { return node_array[nid]; }
const EdgeArrayEntry &GetEdge(const EdgeID eid) const { return edge_array[eid]; } const EdgeArrayEntry &GetEdge(const EdgeID eid) const { return edge_array[eid]; }
protected: protected:
template <typename OtherEdge> template <typename IterT>
void CopyDataIfAvailable(EdgeArrayEntry &into, const OtherEdge &from, std::true_type) void InitializeFromSortedEdgeRange(const unsigned nodes, IterT begin, IterT end)
{ {
into.data = from.data; number_of_nodes = nodes;
} number_of_edges = static_cast<EdgeIterator>(std::distance(begin, end));
node_array.reserve(number_of_nodes + 1);
template <typename OtherEdge> node_array.push_back(NodeArrayEntry{0u});
void CopyDataIfAvailable(EdgeArrayEntry &into, const OtherEdge &from, std::false_type) auto iter = begin;
{ for (auto node : util::irange(0u, nodes))
// Graph has no .data member, never copy even if `from` has a .data member. {
(void)into; iter =
(void)from; std::find_if(iter, end, [node](const auto &edge) { return edge.source != node; });
unsigned offset = std::distance(begin, iter);
node_array.push_back(NodeArrayEntry{offset});
}
BOOST_ASSERT(iter == end);
BOOST_ASSERT(node_array.size() == number_of_nodes + 1);
edge_array.resize(number_of_edges);
std::transform(begin, end, edge_array.begin(), [](const auto &from) {
return static_graph_details::edgeToEntry<EdgeArrayEntry>(
from, traits::HasDataMember<EdgeArrayEntry>{});
});
} }
private:
NodeIterator number_of_nodes; NodeIterator number_of_nodes;
EdgeIterator number_of_edges; EdgeIterator number_of_edges;

View File

@ -23,6 +23,8 @@ typedef TestStaticGraph::NodeArrayEntry TestNodeArrayEntry;
typedef TestStaticGraph::EdgeArrayEntry TestEdgeArrayEntry; typedef TestStaticGraph::EdgeArrayEntry TestEdgeArrayEntry;
typedef static_graph_details::SortableEdgeWithData<TestData> TestInputEdge; typedef static_graph_details::SortableEdgeWithData<TestData> TestInputEdge;
static_assert(traits::HasDataMember<TestInputEdge>::value, "TestInputEdge needs to have data");
constexpr unsigned TEST_NUM_NODES = 100; constexpr unsigned TEST_NUM_NODES = 100;
constexpr unsigned TEST_NUM_EDGES = 500; constexpr unsigned TEST_NUM_EDGES = 500;
// Chosen by a fair W20 dice roll (this value is completely arbitrary) // Chosen by a fair W20 dice roll (this value is completely arbitrary)