Refactor StaticGraph generation
This commit is contained in:
parent
78a199e2fb
commit
58681fa7ea
@ -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;
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user