Skip to content

GFQL Polars: native hop-gated aliases for forward/reverse min_hops > 1 #1748

Description

@lmeyerov

Current scope (reconciled against master 599c405a234bff2402e4f76041cac6e169f6f7c8): implement native Polars execution of forward/reverse variable-length patterns with min_hops > 1 and a node alias. These shapes currently raise NotImplementedError before returning an ungated result. The original silent-wrong severity is resolved; native support remains open, as the existing comments specify. Preserve named/unnamed boundary tests and the supported pandas/cuDF escape hatch.

Earlier reproductions and measurements below are historical; they do not describe current Polars service.

Historical report

Summary

On the polars chain engine, a forward or reverse variable-length pattern with min_hops > 1 returns nodes whose hop distance is outside the requested window. No error is raised — the answer is silently wrong.

Undirected *2..3 correctly declines with a NotImplementedError. Only fwd/rev silently mis-answer.

Repro

import pandas as pd, polars as pl, graphistry
e = pd.DataFrame({"s": ["p0","p1","p2","p1"], "d": ["p1","p2","p4","p0"]})
q = "MATCH (a {id:'p0'})-[*2..3]->(b) RETURN b"

graphistry.edges(e, "s", "d").gfql(q, engine="pandas")
# -> p2, p4                      (correct: distances 2 and 3)

graphistry.edges(pl.from_pandas(e), "s", "d").gfql(q, engine="polars")
# -> p0, p1, p2, p4              (WRONG: p0 is distance 0, p1 is distance 1)

Cause

The polars chain gates a node alias by hop distance only when the auto hop-label column is present. For min_hops > 1 the label is deliberately not requested (those labels come from pandas' layered backward walk, which is not ported), so the alias ends up ungated and every reachable node passes.

Undirected happens to escape because it declines the whole shape earlier.

Scope — measured, not inferred

4-engine differential sweep against pandas as oracle, 144 cases (4 hand graphs + 12 random graphs x 9 patterns), run on dgx-spark under safe_run.sh, RAPIDS 26.02 image.

build pandas cudf polars polars-gpu
master c355660a 144/144 144/144 79 ok / 49 wrong / 16 NIE 79 / 49 / 16
master + #1746 + #1747 144/144 144/144 114 ok / 14 wrong / 16 NIE 114 / 14 / 16

Set-diff of the mismatch sets: 0 regressions, 70 of 98 fixed. All 28 residual mismatches (14 per polars engine) are this one shape, -[*2..3]->.

So this bug is pre-existing on master and is not introduced by the #1741 stack — that stack removes 71% of the silent-wrong surface and leaves exactly this hole.

Fix direction

Either port the layered backward walk that produces min_hops > 1 labels, or — cheaper and strictly better than today — decline (NIE) the fwd/rev min_hops > 1 + node-alias shape the same way undirected already does, so a wrong answer becomes an honest error.

Related: #1741, #1746, #1747.

Activity

  1. lmeyerov commented on Jul 20, 2026

    @lmeyerov
    ContributorAuthor

    Handled in #1747 by honest decline (not silent-wrong). Rather than leave this shape returning wrong rows, #1747 now declines fwd/rev min_hops>1 + node-alias with a NotImplementedError pointing here (adapted from the retired #1742 decline pattern). Differential vs pandas: 30/30 named shapes NIE, 30/30 unnamed run and match pandas, 0 silent-wrong, 0 over-decline; 4-engine sweep now 112 agree / 0 disagree / 32 NIE (was 114/14/16). This issue stays open for the full fix — porting pandas' layered backward walk so min_hops>1 aliases are hop-gated and run natively — but the silent-wrong severity is resolved.

  2. lmeyerov commented on Aug 13, 2026

    @lmeyerov
    ContributorAuthor

    The silent window violation is GONE at the #1873 stack head: polars raises the shape-specific NIE this issue proposed ("min_hops>1 ... not yet hop-gated") instead of returning {p0,p1,p2,p4}; pandas answers {p2,p4} correctly. Remaining work is the native implementation behind the decline.

  3. lmeyerov commented on Aug 18, 2026

    @lmeyerov
    ContributorAuthor

    Verified resolved on master e6625ed28 (post correctness-stack merge) — recommending close after review.

    Repro: MATCH (a {id:'p0'})-[*2..3]->(b) RETURN b.id on the issue's chain fixture. Hand-computed hop window from p0: {p2, p4} (p0/p1 are outside min_hops=2).

    pandas: b.id = [p2, p4]      (exact)
    cudf:   b.id = [p2, p4]      (exact)
    polars: typed NotImplementedError citing this issue:
      "polars chain engine: a node alias after a forward/reverse variable-length edge with
       min_hops>1 is not yet hop-gated (would tag nodes outside the hop window — issue #1748);
       use engine='pandas' or engine='cudf'"
    

    The silent-wrong (polars returning p0/p1 outside the hop window) is gone — polars now takes the issue's own proposed "decline with typed NIE" direction, with a working pandas/cuDF escape hatch. Fine to close as resolved-by-decline, or keep open only if the native polars hop-gated implementation should be tracked here rather than in a new feature issue.

  4. lmeyerov commented on Aug 18, 2026

    @lmeyerov
    ContributorAuthor

    Audit vs master e6625ed28: the SILENT-WRONG half is resolved — pandas/cuDF return exactly the correct window and polars declines with a typed NIE citing this issue. Keeping this OPEN, reframed as the tracker for the remaining FEATURE: native polars service of forward/reverse varlen with min_hops>1 (the typed decline's escape hatch). Note #1903's polars NIEs also cite this issue as the gating tracker.

  5. changed the title [-]polars chain: forward/reverse varlen with min_hops>1 returns nodes outside the hop window (silent wrong)[/-] [+]GFQL Polars: native hop-gated aliases for forward/reverse min_hops > 1[/+] on Oct 9, 2026
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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions