Implement InducedSubgraphView - #43
Conversation
|
Remaining items to implement are:
Something to note is that I had to make the I think we should save the base GraphView class, which |
|
I'm looking at the |
|
Or do it on the first request to access the degrees |
Sounds good. I'll start working on adding that behavior. |
| originalGraph.get().forInNeighborsOf(v, [&](node u, edgeweight ew) { | ||
| if (!hasNode(u) || u == v) | ||
| return; | ||
| ++inducedDegree[u]; |
There was a problem hiding this comment.
This keeps m from double-counting, but makes the public in-degree wrong for directed self-loops. Fixing this likely needs separate edge-count delta logic on removal too, since networkit/cpp/graph/InducedSubgraphView.cpp:119 currently subtract out-degree plus cached in-degree.
There was a problem hiding this comment.
I'm a bit confused -- I thought a directed self-loop from v to v would contribute +1 to both inDegree[v] and outDegree[v]. That contribution happens in the above loop, where we iterate over out-neighbors.
|
performance: Full edge traversal of a small view scans the entire base graph. n Also as an integration test, please run the abm14 graph and see if any runtime regressed due to the |
|
Details on the virtual vs templated. Only one problematic instance was found in the review. The nuance is that C++ templates are only “polymorphic” through the operations they call inside the instantiated base template. For example, Graph::forNodes is a template, so if code has: const Graph &g = view; it instantiates/runs Graph::forNodes, not InducedSubgraphView::forNodes. The branch partially mitigates that by changing many internal checks from exists[v] to virtual hasNode(v), so those base-template paths become correct but potentially slow. |
|
Closing to defer until the refactor (#69) is implemented. |
Reattempt of #43 on the concept rework: instead of subclassing the old virtual Graph, InducedSubgraphView is a header-only template over any GraphLike base graph -- GraphR, GraphW, CoarsenedGraphView, or another induced view -- and keeps the base node ids. Membership is edited in batches (addNodes/removeNodes). The induced degrees, the edge count and the self-loop count are maintained incrementally while the batch is applied, which keeps every GraphLike primitive O(1). Neighborhoods are never materialized: each range filters the base adjacency on the fly, so the footprint is one presence flag plus one or two degree counters per base node. frontier() and realize(compact) carry over from the old attempt. Supporting changes live in the previous commits: the erased handle's own outNeighbors/inNeighbors and the payload-safe hasEdge/weight in the ops layer.
Implementation for issue #39