Skip to content

Explain inverse#762

Merged
frankmcsherry merged 3 commits into
TimelyDataflow:master-nextfrom
frankmcsherry:explain-inverse
Jun 17, 2026
Merged

Explain inverse#762
frankmcsherry merged 3 commits into
TimelyDataflow:master-nextfrom
frankmcsherry:explain-inverse

Conversation

@frankmcsherry

Copy link
Copy Markdown
Member

After #760 (Value/ADT data model), the explain rewrite covered the relational subset but panic!'d on FlatMap — so the new ADT expressiveness wasn't explainable, breaking
the writable ⟹ explainable invariant. This closes that gap, minimally and additively (no rewrite of the working relational rules, no envelope change).

  • decouple: re-ground with the universal-backstop flatmap test (the proof-of-concept).
  • explain(value): emit_lookup_flatmap — a real reverse rule replacing the panic. FlatMap is same-depth (it doesn't touch iteration time) and its list rides as one opaque
    value, so it slots into the existing flat envelope. The (output → input) pair table is built by running the op forward on the input side; the one wrinkle — a plain
    flatmap drops the source and the key isn't unique — is handled by re-keying the input by itself before exploding (the source rides through in the join key), then
    re-projecting to (k, pos, elem); a chain_in ≤ chain_out filter keeps it sound in iterating scopes. No new primitive.
  • explain(value): confirmed Collect reverses via the existing non-min keyed path ("demand all members") — no new rule.

Verified: flatmap and collect programs explain end-to-end (demand regenerates the queried output), and the full suite — including the heavy --ignored relational sweeps —
stays green.

Deferred (not needed for the invariant): the full (PRESERVED/RESIDUAL/REFORM) inverse-interface unification + opaque-value envelope (which would also delete the
Term-arity shape pass) — an independent cleanup for later.

🤖 Generated with Claude Code

frankmcsherry and others added 3 commits June 16, 2026 16:15
Re-land the proof-of-concept (removed from TimelyDataflow#760 as PR-scoped) on the follow-up
branch where it belongs: the universal backstop reverses `flatmap` — the op the
live rewrite still panics on — via the existing Dataflow primitives (forward
pair table, join on the output, REFORM the whole input). Grounds the inverse
work before the real rule + wiring.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…egression

Replace the `panic!` on `LinearOp::FlatMap` in the reverse walk with a real
rule, `emit_lookup_flatmap`. FlatMap is same-depth (it doesn't touch iteration
time) and its list rides as one opaque value, so no envelope change is needed:
build the (output -> input) pair table by running the op forward on the input
side, join the demand on the packed output, and recover the whole input (the
`None`-inverse endpoint). The one wrinkle — a plain flatmap drops the source
row and the key isn't unique — is handled by re-keying the input by itself
before exploding (the source rides through in the join key) and re-projecting
to (k, pos, elem) after; a chain_in <= chain_out filter keeps it sound in
iterating scopes. No new primitive; uses the existing project/flatmap/join.

With this, `writable => explainable` is restored for flatmap programs.
Verified: a flatmap sufficiency test passes, and the full suite — incl. the
heavy --ignored relational sweeps — stays green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collect (NEST) is a Reducer, so the reverse walk already routes it through the
non-min keyed lookup ("demand all same-key inputs") — which is exactly the
demand for a collected list (all its members). A sufficiency test over a
`| collect` program confirms the existing path handles a List-valued reducer
output; no new rule needed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@frankmcsherry frankmcsherry marked this pull request as ready for review June 17, 2026 01:30
@frankmcsherry frankmcsherry merged commit 75256dd into TimelyDataflow:master-next Jun 17, 2026
6 checks passed
@frankmcsherry frankmcsherry deleted the explain-inverse branch June 17, 2026 01:30
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.

1 participant