Skip to content

feat(cypher): implement shortestPath execution with igraph/cugraph backends #1010

Closed

Description

@lmeyerov

Summary

This is the active direct Cypher shortestPath(...) execution lane.

Active implementation PR:

Current branch status on April 3, 2026

#1042 currently adds the narrow scalar shortest-path contract needed by the benchmark lane:

  • length(path)
  • path IS NULL
  • CASE path IS NULL WHEN true THEN -1 ELSE length(path) END
  • exact official comma-seeded interactive-complex-13 shape
  • bounded, reverse-direction, disconnected-null, endpoint/id-projection, staged WITH, zero-hop, cyclic/bounded duplicate-route, and multi-row shortestPath amplification around that scalar slice

Still intentionally unsupported on the branch:

  • allShortestPaths(...)
  • RETURN path
  • relationships(path) and other generic path-carrier forms

Focused validation so far

Local focused checks:

  • graphistry/tests/compute/gfql/cypher/test_parser.py -k shortest_path
  • result: 1 passed, 95 deselected
  • graphistry/tests/compute/gfql/cypher/test_lowering.py -k "shortest_path or allShortestPaths"
  • result: 40 passed, 660 deselected

Focused dgx-spark host-CPU checks:

  • parser: 1 passed, 95 deselected
  • lowering/execution: 40 passed, 660 deselected

What this branch found while implementing the lane

Two adjacent runtime fixes were needed in the row-binding path:

  • fixed-point edges must count as multihop in graphistry/compute/gfql/same_path/edge_semantics.py
  • multihop row bindings must preserve hop-labeled node frames into the next node filter in graphistry/compute/gfql/row/pipeline.py

Seven adjacent scalar/runtime hardening fixes were then needed during amplification:

  • shortest-path scalar rewrites now bind onto the endpoint alias hop property, and disconnected empty-row synthesis now carries alias-prefixed seed values so endpoint/id projections survive direct RETURN null-extension
  • disconnected shortest-path rows now also null-extend through staged scalar WITH ... RETURN ... chains in the supported local subset
  • unbounded shortestPath self-matches now produce valid zero-hop scalar results instead of null / -1
  • cyclic shortestPath scalar execution now dedupes equal-length revisits instead of erroring or diverging on multiroute graphs
  • bounded cyclic and self-loop shortestPath scalar outputs now dedupe identical shortest rows instead of returning duplicates
  • multi-row shortestPath pair queries now preserve row-specific endpoint hop values instead of collapsing to 0 / 1
  • multi-row disconnected shortestPath now null-extends per seed pair for direct, staged, bounded, and reverse-direction scalar forms

Recent test-only amplification on top locks:

  • multi-row path IS NULL ordering across direct, staged, bounded, and reverse-direction shortestPath queries

So this issue is well past parser recognition: the active branch is executing the shortest-path scalar contract end-to-end in focused tests and has gone through several real amplification passes that kept uncovering product bugs.

Benchmark target

Official query file:

  • /home/lmeyerov/Work/pyg-bench/third_party/ldbc_snb_interactive_v1_impls/cypher/queries/interactive-complex-13.cypher

Official query text:

MATCH
    (person1:Person {id: $person1Id}),
    (person2:Person {id: $person2Id}),
    path = shortestPath((person1)-[:KNOWS*]-(person2))
RETURN
    CASE path IS NULL
        WHEN true THEN -1
        ELSE length(path)
    END AS shortestPathLength

Activity

  1. lmeyerov commented on Apr 2, 2026

    @lmeyerov
    ContributorAuthor

    Benchmark rerun update from pyg-bench on refreshed current master 14dafaf6b951954d8de840f9236f3e874249ebac.

    Official SNB lane:

    • query: interactive-complex-1 / named-shortest-friends
    • artifact: /home/lmeyerov/Work/pyg-bench/results/runs/dgx-spark-snb-interactive-ic1-origin-master-14dafaf6b9-fresh-r2
    • command:
      uv run python scripts/run_dgx_spark_suite.py --suite snb-interactive --config configs/suites/snb-interactive-ic1-conformance-sf1.yaml --output-dir results/runs/dgx-spark-snb-interactive-ic1-origin-master-14dafaf6b9-fresh-r2 --graphistry-repo-path /tmp/pygraphistry-origin-master-14dafaf6b --host-uv

    Measured outcome on dgx-spark:

    • GFQL: partial via the benchmark-side bounded-shortest-path plus profile-history workaround
    • direct Cypher: primitive_gap under #1010
    • error:
      [unsupported-cypher-query] shortestPath() is not yet supported in the local Cypher compiler | field: match | value: 'shortestPath' | suggestion: Use a subset currently supported by the GFQL Cypher compiler.

    Timing from the same run:

    • setup_latency_ms = 301.229
    • query_latency_ms = 236.499
    • csv_load = 70.363 ms
    • derivation = 150.102 ms
    • graph_bind = 80.764 ms

    Two useful benchmark-side notes:

    • this lane now measures cleanly on the reduced core_fast fixture path, so it is no longer blocked by harness setup noise
    • the pinned official substitution used here yields zero result rows on the staged sf1 fixture, so this is primarily a support-classification checkpoint rather than a high-cardinality comparison run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions