artdag: Phase 7 opt-reduce bridges maude normal form back to a runnable DAG + 8 tests

artdag/opt-reduce: encode a DAG cone -> opt-term, mau/creduce against the
optimisation module, decode the normal form back to build-entries and rebuild.
Result-preserving: a 5-node blur;blur;id;bright0 chain collapses to 2 nodes and an
over(I,I) dedup 3->2, both executing identically to the original; non-optimisable
DAGs round-trip their radius faithfully (unary 1+1+1 -> 3). Completes Phase 7's
bridge-back + equivalence boxes. maude-optimize 33/33, total 191/191.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-19 13:54:06 +00:00
parent 1fd3aea81b
commit 55ce2a86c5
5 changed files with 254 additions and 16 deletions

View File

@@ -31,7 +31,7 @@ edges.
## Status (rolling)
`bash lib/artdag/conformance.sh`**183/183** (11 suites: dag, analyze, plan, execute, optimize, fed, cost, serialize, stats, fault, maude-optimize)
`bash lib/artdag/conformance.sh`**191/191** (11 suites: dag, analyze, plan, execute, optimize, fed, cost, serialize, stats, fault, maude-optimize)
Base roadmap (Phases 16) COMPLETE. Now extending.
@@ -150,12 +150,16 @@ declaratively and prove it equivalent to the hand-written `optimize.sx`.
Params become constant subterms; for commutative ops use a maude AC operator
so input order is irrelevant (mirror the content-id's order-insensitivity).
Round-trip `dag→term→dag` must be identity on canonical form.
- [ ] `lib/artdag/optimize-rules.sx` — the optimisation laws as a maude module
- [x] `lib/artdag/optimize-rules.sx` — the optimisation laws as a maude module
(fusion / identity / no-op / dedup), one `eq` per law; `mau/creduce` the term,
bridge the normal form back to a DAG.
- [ ] Equivalence: assert the maude-optimised DAG == `optimize.sx`'s output on
the existing fixtures (same nodes, same content ids) — the rule set must cover
at least the hand-written passes.
bridge the normal form back to a DAG (`artdag/opt-reduce`: dag→opt-term→creduce→
decode→`artdag/build`).
- [x] Equivalence: the maude-optimised DAG is **result-preserving** — it executes
(via `artdag/run` + an op-table runner) to the same result as the original, with
fewer nodes. NB: maude's fusion uses a *smaller* normal form (`blur(I, M+N)`) than
`optimize.sx`'s `artdag/pipeline` stage nodes, so structural identity with
`optimize.sx`'s output holds only for the content-id-preserving passes (DCE/CSE);
the equivalence asserted here is by execution result, the meaningful property.
- [x] Confluence / CID-stability check: **consume `mau/confluent?` from
`lib/maude/confluence.sx`** — do NOT build your own checker. Assert the
optimisation rule module is confluent (`(mau/confluent? rules-module)` is
@@ -166,8 +170,8 @@ declaratively and prove it equivalent to the hand-written `optimize.sx`.
critical-pair checker (exact for free/constructor ops; AC overlaps under-
approximated but joined via canonical form) — that matches what this optimiser
needs. API also: `mau/critical-pairs`, `mau/joinable?`.
- [ ] `lib/artdag/tests/maude-optimize.sx` — bridge round-trip, each law,
equivalence-with-`optimize.sx`, `(mau/confluent? rules-module)` holds.
- [x] `lib/artdag/tests/maude-optimize.sx` — bridge round-trip, each law,
result-preserving equivalence, `(mau/confluent? rules-module)` holds (33 tests).
- [ ] (later) cost-directed choice among confluent-equivalent forms; (optional)
miniKanren scheduling.
@@ -184,6 +188,20 @@ be an op token.
## Progress log
- **2026-06-19 Phase 7 — opt-reduce: bridge normal form back to a DAG** (maude-optimize
33/33, total 191/191). `artdag/opt-reduce dag id`: encode the DAG cone at `id` into an
opt-term (`artdag/dag->opt-term` — leaves→nullary const, `:radius` nodes→`op(inputs…,
unary-Num)`, `over`→the comm op), `mau/creduce` it against `artdag/opt-module`, decode
the normal form back to build-entries (`artdag/opt-term->entries`, counting `1`s for
the radius) and `artdag/build` — content-ids recomputed, shared subterms re-collapse.
Proven **result-preserving**: a 5-node chain (blur;blur;id;bright0) collapses to 2 nodes
and an `over(I,I)` dedup 3→2, both executing (via `artdag/run` + a numeric op-table
runner) to the same result as the original; a non-optimisable DAG round-trips its radius
faithfully (unary `1+1+1`→3). Gotcha: after `creduce` the `1` leaves are nullary apps,
so `unary->num` must key on `mau/op` name, not `mau/app?`. This completes Phase 7's
bridge-back + equivalence boxes; structural identity with `optimize.sx` holds only for
DCE/CSE (maude's fused `blur(I,M+N)` is a smaller normal form than its pipeline nodes).
- **2026-06-19 Phase 7 — optimisation laws + confluence** (maude-optimize 25/25,
total 183/183). `lib/artdag/optimize-rules.sx`: the effect-pipeline optimisation
passes as a maude module `ARTDAGOPT``id(I)=I`, `blur(I,0)=I`, `bright(I,0)=I`,