feat(gfql): add built-in standard graph algorithms - #2006
Open
lmeyerov wants to merge 9 commits into
Open
Conversation
… engine
Adds `graphistry/compute/algorithms/`: five graph kernels written once against
the dataframe API so they run on pandas and cudf from a single implementation,
plus `compute_std()` to bind results onto a Plottable.
These exist because no backend implements the LDBC Graphalytics semantics.
cuGraph has no label propagation and no maximal independent set — confirmed
across cugraph, nx-cugraph and pylibcugraph's 79 algorithms. igraph's label
propagation is randomized rather than deterministic. Both backends' PageRank
converges to a tolerance while LDBC fixes the iteration count.
Named `std` in the standard-library sense: no optional third-party dependency,
runs on whichever engine holds the frames. Deliberately NOT named after the
benchmark that motivated it — "Graphalytics" is LDBC's benchmark name, and
putting it in a shipped public API would imply an endorsement and conformance
audit we do not have. Conformance belongs in docs and tests, not identifiers.
Two details that are easy to get wrong:
* The kernels need dense int32 ids 0..V-1 — that is what makes frontier
expansion a positional gather instead of a hash join. compute_std renumbers
and maps back, as compute_cugraph does for cuGraph's own renumbering.
* WCC and CDLP results ARE vertex ids: the label is the minimum member id. So
the values, not just the row order, map back to the caller's id space.
Monotone renumbering makes dense and original labels denote the same vertex,
but a user comparing a label to their own node ids needs the original.
Validated against independent references rather than self-consistency: networkx
for WCC, Dijkstra for SSSP (bitwise exact — integer weights in [1,255] keep every
distance exactly representable in float32), a naive Python LDBC implementation
for CDLP, a hand-written power iteration for PageRank, and independence plus
maximality invariants for MIS. The validators are themselves negative-tested
against corrupted results, since a validator that always passes makes an
unchecked number look checked. 27 tests.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YXm45Nzm1BgWs6iR2exufT
…ries
Wires the std backend into the Cypher CALL registry, so the engine-agnostic
kernels are reachable from a query rather than only from Python:
CALL graphistry.std.wcc.write()
CALL graphistry.std.cdlp.write({params: {iterations: 10}})
CALL graphistry.std.pagerank.write({out_col: 'pr'})
This matters because these are the only implementations of two of the five
algorithms: cuGraph has no label propagation and no maximal independent set
(checked across cugraph, nx-cugraph and pylibcugraph's 79 algorithms), and
igraph's label propagation is randomized rather than LDBC-deterministic.
Five touch points, all of which the compiler needs and none of which are
inferable from the resolver alone:
* `"std"` in the backend allowlist and in `_BACKEND`
* a resolver branch validating against `algorithms.registry.STD_COMPUTE_ALGS`
* an executor branch calling `compute_std`
* `compute_std` in the call safelist (`gfql/call/validation.py`) -- without it
the resolver succeeds and execution is refused
* a `std` branch in `_source_value_columns`, which otherwise asserts cugraph
That last one is worth stating: the output column is the REGISTRY's name for the
algorithm, not the algorithm name. `wcc` writes `component`, `sssp` writes
`distance`. Only cuGraph and igraph have the property that column == algorithm.
Verified the query surface does not change the answer: `CALL graphistry.std.wcc`
equals the direct kernel, and labels come back in the caller's id space, since a
WCC label IS a vertex id.
Unrelated pre-existing failures in test_lowering.py (7 cudf-parametrized cases)
are unchanged: 7 failed / 1566 passed both with and without this change.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YXm45Nzm1BgWs6iR2exufT
lmeyerov
marked this pull request as ready for review
August 21, 2026 05:03
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
CALL graphistry.std.*PageRank compatibility
graphistry.std.pageranknow accepts the current cuGraph PageRank signature and defaults:The std implementation also keeps Graphistry extras: dataframe-engine portability (pandas on CPU or cuDF on GPU),
weight, chunk sizing,stopping="fixed_iterations", legacyiterations/dampingaliases, and optionalconverged_col. Vector inputs accept original-ID maps, record lists, and dataframe forms.danglingis accepted for signature compatibility and intentionally ignored, matching cuGraph's public contract.This is a portable GFQL/std fallback, not a replacement for native backends on performance. Native
graphistry.cugraph.*and igraph integrations remain the preferred fast path when installed.Correctness boundaries
fail_on_nonconvergence=Falsereturns convergence statussourceis an original node ID; unknown or incompatible IDs fail clearlyMatched PageRank performance
Guarded same-dataset measurements on directed, unweighted cit-Patents (3,774,768 vertices / 16,518,947 edges), with graph preparation excluded and three timed repetitions:
tol=1e-8tol=1e-8tol=1e-8Retained top-10 vertex IDs match in every comparison. Maximum retained-rank deltas are below
1e-10for the aligned GPU profiles; igraph PRPACK does not expose a matching tolerance control. Full artifacts and reproducibility details are in graphistry/pyg-bench#193.Validation
./bin/lint.sh./bin/typecheck.sh(337 source files)./bin/check_docs_latex_unicode.shgit diff --checkNo Docker, GPU, dataset, or benchmark workload was run locally. All performance work ran on dgx-spark through the shared perf lock and
safe_run.sh, with cgroup/RMM limits, host-memory floor, watchdog, and hard timeouts.Closes #1975