Skip to content

Make custom schedulers compose with the term/proof encoding#944

Draft
oflatt-claude wants to merge 1 commit into
egraphs-good:mainfrom
oflatt-claude:term-encoding-scheduler-maintenance
Draft

Make custom schedulers compose with the term/proof encoding#944
oflatt-claude wants to merge 1 commit into
egraphs-good:mainfrom
oflatt-claude:term-encoding-scheduler-maintenance

Conversation

@oflatt-claude

Copy link
Copy Markdown
Contributor

Problem

Custom schedulers — e.g. egglog-experimental's backoff scheduler — drive a ruleset through EGraph::step_rules_with_scheduler. Under the term/proof encoding, the e-graph's invariants (canonical representatives, congruence closure, deferred deletion) are maintained by generated maintenance rulesets rather than the backend union-find, and those rulesets must be run to fixpoint between steps. step_rules_with_scheduler never ran them, so a scheduled step queried stale, un-canonicalized view tables — schedulers and term/proof mode did not compose.

Approach

Record the maintenance schedule in the program itself via a new internal command (internal-rebuild-schedule <schedule>), emitted once by the term-encoding pass. step_rules and step_rules_with_scheduler then run that schedule to fixpoint after each step. Runs are no longer wrapped with an inline rebuild in the desugared schedule; non-run commands keep their existing per-command rebuild.

Because the schedule travels with the desugared program (as data), the desugared output stays self-contained — it still runs correctly when replayed on a plain e-graph without term encoding (the desugar test mode), which is why the schedule is carried in the program rather than gated on a runtime flag.

Only the user's ruleset is scheduled; maintenance always runs unscheduled. The command is named internal-rebuild-schedule to signal it is not for direct use.

Tests

  • term encoding + scheduler runs maintenance (single step)
  • proof mode + scheduler preserves proofs (extract + check a derived equality's proof)
  • real backoff algorithm (ported from egglog-experimental) reaches the same saturated e-graph as an unscheduled run on an AC-rewrite benchmark, asserting it actually bans
  • a fractional (partial-selection) scheduler reaches the same result — residual matches held across rebuilds are re-applied idempotently (sound, since term-encoding terms are immutable)
  • choose_all saturation-equivalence

Full .egg suite (744, across term-encoding / proofs / proof-testing / desugar modes) and lib tests pass; make nits clean.

Follow-up

The per-command rebuild for non-run commands is still injected into the desugared program. Moving it to a lazy rebuild-before-observe runtime model (mutations mark the e-graph dirty; maintenance runs only before check/extract/print/queries) would remove that injection too. An eager "rebuild after each mutating command" does not work: a single user set on a :merge function desugars into multiple commands that must rebuild as a unit, and the flat desugared list has lost those boundaries — so this needs the lazy model, left as follow-up.

🤖 Generated with Claude Code

Custom schedulers such as egglog-experimental's backoff scheduler drive
a ruleset through `step_rules_with_scheduler`, but that path never ran
the term-encoding maintenance rulesets (rebuilding, congruence, path
compression, deferred deletion). Scheduled steps therefore queried
stale, un-canonicalized view tables under term/proof encoding.

Record the maintenance schedule in the program via a new internal
`(internal-rebuild-schedule ...)` command and run it to fixpoint inside
`step_rules` and `step_rules_with_scheduler` after each step. Because the
schedule travels with the desugared program, the desugared output stays
self-contained and runnable without term encoding. Only the user's
ruleset is scheduled; maintenance always runs unscheduled.

Add tests for term encoding + scheduler, proof mode, the real backoff
algorithm (saturation-equivalence on a benchmark), and a fractional
scheduler (residual-match soundness).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

2 participants