Skip to content

fix(plugins): run igraph and cuGraph on Polars-bound graphs (#2025) - #2172

Open
lmeyerov wants to merge 2 commits into
masterfrom
fix/polars-graph-algorithms-2025
Open

lmeyerov wants to merge 2 commits into
masterfrom
fix/polars-graph-algorithms-2025

Conversation

@lmeyerov

Copy link
Copy Markdown
Contributor

Closes #2025. Groundwork for #1966: the same bridge is applied to the layouts in a stacked PR.

Problem

At master 599c405a, freshly reproduced on dgx-spark (polars 1.35.2, igraph 1.0.0, cuDF/cuGraph 26.02):

method eager Polars lazy Polars
compute_igraph, layout_igraph AttributeError: 'Int64' object has no attribute 'name' LazyFrame is not subscriptable / has no len()
compute_cugraph, layout_cugraph ValueError: Unsupported edge data type LazyFrame is not subscriptable

GFQL call() already runs these analytics off-engine under Polars and returns Polars frames, as documented in "Analytics under Polars" in engines.rst. Direct method calls bypassed that bridge.

Change

  • graphistry/Engine.py: graph_frames_to_engine, now shared with the GFQL call executor, and bridge_polars_graph(compute_engine). For a Polars-bound graph, eager or lazy:
    • no engine argument, auto or polars: run on the compute engine and return eager Polars;
    • polars-gpu: run on cuDF and return Polars;
    • explicit pandas or cudf: honored, and that engine's frames are returned.
    • Non-Polars graphs pass through untouched.
    • Node id, source, destination and edge id dtypes are restored after the round trip, but only when the cast is exact, so 0.5 is never silently turned into 0.
  • PlotterBase: igraph methods bridge through pandas; cuGraph methods go Polars to cuDF via Arrow.
  • Docs: the engines.rst "Analytics under Polars" section now covers direct method calls; compute_igraph docstring; CHANGELOG.

Validation (dgx-spark)

  • New tests: 26 pass, including the decorator contract and plugin parity against pandas-bound results. The cuGraph cases run with TEST_CUGRAPH=1 --gpus all.
  • Regression on plugins, layouts, engine helpers and GFQL call/off-engine tests: master has 3 failures and 644 passes; the branch has the same 3 failures and 657 passes. The 3 cuGraph failures (test_edges_named, test_minimal_attributed_edges, test_all_calls) are pre-existing in this image.
  • Full graphistry/tests/compute without a GPU: identical failure sets on master and branch.
  • ruff, mypy on the changed lines, comment-density and type-hygiene guards: clean.

Cost (#2032 context, no algorithm change)

compute_igraph('pagerank'), interleaved, medians of 5 runs, 4 CPUs:

graph pandas total Polars total Polars-in convert to_igraph solver join-back Polars-out convert
100k nodes / 1M edges 1247 ms 1260 ms 5 ms 297 ms 124 ms 802 ms 1 ms
1M nodes / 10M edges 17943 ms 18084 ms 10 ms 5471 ms 3419 ms 8693 ms 5 ms

The bridge adds well under 0.1% of runtime, and the Polars totals fall within the pandas run ranges. As #2032 reports, the solver accounts for only 10 to 19% of the time; join-back and igraph conversion dominate.

Merge note: master requires an approving review, and self-approval is impossible, so landing this as the author needs gh pr merge --admin, which means no human review.

🤖 Generated with Claude Code

compute_igraph/layout_igraph and compute_cugraph/layout_cugraph crashed on
graphs bound to polars frames (AttributeError on eager, "LazyFrame is not
subscriptable" on lazy, "Unsupported edge data type" for cuGraph). GFQL
call() already bridged these analytics under Polars; direct method calls
bypassed it.

- Engine.py: graph_frames_to_engine (shared with the GFQL call executor) and
  bridge_polars_graph(compute_engine): Polars-bound graphs (eager or lazy)
  run on pandas or cuDF and return eager Polars frames; explicit
  engine='pandas'/'cudf' is honored; non-Polars graphs pass through
  untouched. Identifier dtypes are restored only when the cast is exact.
- PlotterBase: igraph methods bridge through pandas, cuGraph methods
  through cuDF (Arrow).
- Tests: decorator contract (engine forms, positional engine, lazy,
  passthrough, dtype restore and its exactness guard) and plugin parity
  against pandas-bound results, cuGraph gated on TEST_CUGRAPH.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
The new tests need polars, which only test-polars installs, and the igraph
parity cases need igraph, which that lane lacked; without it they would
skip in every lane. Adding igraph leaves the existing lane results
unchanged (same pass/fail sets on dgx with and without igraph).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01DBp5x7mfdDARNTXhRoJATw

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

compute_cugraph / compute_igraph reject polars-bound graphs (LazyFrame and DataFrame)

1 participant