feat(algo): descriptor-template GDS layer — GDS_LEIDEN, GDS_LOUVAIN, GDS_PPR - #56
Conversation
Louvain community detection via the icebug bridge: projected graph -> InMemGraph CSR -> Arrow UInt64 arrays (system pool, see previous commit) -> zero-copy NetworKit::GraphR -> PLM -> community assignments streamed back through the GDS result pipeline. Coexists with the hand-rolled LOUVAIN under the GDS_ prefix, same as GDS_PAGE_RANK. Test asserts community structure (two 4-cliques joined by a bridge edge), not raw IDs, since PLM is parallel and nondeterministic. Co-Authored-By: Claude Fable 5 <[email protected]>
|
Rebased over #47's merge (the gated source list and registration both conflicted — resolved as the union). 75/75 locally with node2vec and Louvain together. |
c76a58f to
3f4d6cf
Compare
|
Much of gds_xxx.cpp seems to be boilerplate. Is it possible to use some templates/reflection/codgen mechanism to automate it? Or we're looking at 100+ PRs. Also |
Random walk with restart from caller-supplied source nodes:
CALL GDS_PPR('G', [rowid, ...]) — teleportation is uniform over the
sources (NetworKit::PageRank::forSources, memory-efficient: no n-sized
personalization vector), so scores measure standing relative to the
anchors rather than globally. Consumes the shared zero-copy CSR bridge.
Optional params dampingFactor/tolerance as GDS_PAGE_RANK. Sources
validated non-empty and non-negative at bind, range-checked against the
projected node count at run time.
Tests: star anchored at a leaf (asymmetric distribution vs the plain
PageRank tie), and a two-clique trust-closure case — anchored in one
clique, mass stays with the anchor's community (0.17-0.29 vs 0.03-0.07
across the bridge) — plus empty-list and out-of-range error cases.
Co-Authored-By: Claude Fable 5 <[email protected]>
Per review: the per-algorithm boilerplate is gone. GDSPerNodeScalarAlgo (gds_algo_template.h) supplies bind, the shared zero-copy CSR bridge, GraphR construction, and vertex-compute streaming for the whole per-node-scalar equivalence class; an algorithm is now a descriptor — name, output column, optional params, extra-positional-arg policy (NoExtraArgs / SourceListArg), and the NetworKit invocation. GDS_PAGE_RANK, GDS_LOUVAIN, and GDS_PPR are rewritten as descriptors (unchanged CALL surfaces, unchanged test expectations). GDS_LEIDEN is the first new algorithm to ride the template: ParallelLeidenView with gamma/iterations optional params, ~100 lines including both param structs. Per-node-vector outputs (GDS_NODE2VEC) stay bespoke until a second member of that class motivates the template. Co-Authored-By: Claude Fable 5 <[email protected]>
|
Both addressed in d9ece89 (+d90630c). Boilerplate: descriptor templates per algorithm shape — the per-node-scalar template now serves PAGE_RANK, LOUVAIN, LEIDEN, and PPR; a new algorithm in this class is a ~30–100 line descriptor. Leiden: GDS_LEIDEN via ParallelLeidenView with gamma/iterations params, first rider on the template. PPR came along as the extra-args policy's proof (sources = teleportation anchors — the trust primitive from the Discord thread). 78/78. |
Reworked per review — both points:
1. Boilerplate → descriptor templates.
gds_algo_template.hintroducesGDSPerNodeScalarAlgo<DESC>: one class template per algorithm shape (per-node-scalar is the largest equivalence class — centrality, community detection). The template owns bind, the shared zero-copy CSR bridge,GraphRconstruction, and result streaming; an algorithm is now a descriptor — name, output column, optional params, an extra-positional-args policy (NoExtraArgs/SourceListArg), and the NetworKit invocation. The 100+ algorithms become ~30–100 line descriptor files, not PRs full of copied plumbing.GDS_PAGE_RANKis refactored onto it in this PR (CALL surface and test expectations unchanged). Per-node-vector outputs (GDS_NODE2VEC) stay bespoke until a second member of that class motivates the template.2. Leiden first.
GDS_LEIDENviaParallelLeidenView(gamma + iterations optional params) — ~100 lines including both param structs, the first new algorithm to ride the template.GDS_LOUVAINstays (a ~55-line descriptor now) since the two are useful to compare, but the Leiden file carries the "prefer this" note.Bonus:
GDS_PPR—CALL GDS_PPR('G', [rowid, ...])viaPageRank::forSources, theSourceListArgpolicy's first user. Its test is worth a look: two 4-cliques joined by a bridge, anchored in one clique — trust mass stays with the anchor's community (0.17–0.29 vs 0.03–0.07 across the bridge). That's the confidence primitive from the Discord trust/viewpoint discussion, as a query.Suite: 78/78 locally (all existing GDS test expectations unchanged by the refactor).
🤖 Generated with Claude Code