lib/artdag/optimize-rules.sx — the effect-pipeline optimisation passes (identity elim, no-op/zero-radius elim, adjacent fusion, idempotent over dedup) as a maude module. Radius algebra is _+_ [assoc comm id: 0] (NOT Peano successor rules, which are non-confluent here); mau/confluent? certifies 0 non-joinable critical pairs, so the optimised pipeline's normal form / content id is rewrite-order stable. Consumes lib/maude/confluence.sx. maude-optimize 25/25, total 183/183. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
170 lines
4.3 KiB
Plaintext
170 lines
4.3 KiB
Plaintext
; Phase 7 — rule-based optimization via maude-on-sx.
|
|
; Bridge round-trip: dag->term->dag is the identity on canonical (content-id) form.
|
|
|
|
; ---- linear chain a -> b -> c (b carries params) ----
|
|
|
|
(define
|
|
mo-chain
|
|
(artdag/build
|
|
(list
|
|
(list "a" "in" (list) {:v 5})
|
|
(list "b" "blur" (list "a") {:radius 2})
|
|
(list "c" "blur" (list "b") {:radius 3}))))
|
|
(define mo-c-id (artdag/dag-id mo-chain "c"))
|
|
(define mo-chain-rt (artdag/mb-roundtrip mo-chain mo-c-id))
|
|
|
|
(artdag-test
|
|
"roundtrip: sink id preserved"
|
|
(artdag/member? mo-c-id (keys (artdag/dag-nodes mo-chain-rt)))
|
|
true)
|
|
|
|
(artdag-test
|
|
"roundtrip: node count preserved"
|
|
(artdag/node-count mo-chain-rt)
|
|
3)
|
|
|
|
(artdag-test
|
|
"roundtrip: sink op preserved"
|
|
(artdag/node-op (artdag/dag-get mo-chain-rt mo-c-id))
|
|
"blur")
|
|
|
|
(artdag-test
|
|
"roundtrip: sink params preserved"
|
|
(artdag/node-params (artdag/dag-get mo-chain-rt mo-c-id))
|
|
{:radius 3})
|
|
|
|
(artdag-test
|
|
"roundtrip: full reconstructed node equals original"
|
|
(= (artdag/dag-get mo-chain-rt mo-c-id) (artdag/dag-get mo-chain mo-c-id))
|
|
true)
|
|
|
|
; ---- term shape ----
|
|
|
|
(define mo-c-term (artdag/dag->term mo-chain mo-c-id))
|
|
|
|
(artdag-test "term: sink op is the maude operator" (mau/op mo-c-term) "blur")
|
|
|
|
(artdag-test
|
|
"term: params recovered from meta"
|
|
(artdag/term-params mo-c-term)
|
|
{:radius 3})
|
|
|
|
(artdag-test
|
|
"term: commutative flag recovered (false)"
|
|
(artdag/term-commutative mo-c-term)
|
|
false)
|
|
|
|
(artdag-test
|
|
"term->entries: one entry per node"
|
|
(len (artdag/term->entries mo-c-term))
|
|
3)
|
|
|
|
; ---- commutative node: order-insensitive id survives round-trip ----
|
|
|
|
(define
|
|
mo-comm
|
|
(artdag/build
|
|
(list
|
|
(list "x" "src" (list) {})
|
|
(list "y" "noise" (list) {})
|
|
(list "z" "over" (list "x" "y") {} true))))
|
|
(define mo-z-id (artdag/dag-id mo-comm "z"))
|
|
(define mo-comm-rt (artdag/mb-roundtrip mo-comm mo-z-id))
|
|
|
|
(artdag-test
|
|
"roundtrip comm: commutative id preserved"
|
|
(artdag/member? mo-z-id (keys (artdag/dag-nodes mo-comm-rt)))
|
|
true)
|
|
|
|
(artdag-test
|
|
"term comm: commutative flag recovered (true)"
|
|
(artdag/term-commutative (artdag/dag->term mo-comm mo-z-id))
|
|
true)
|
|
|
|
; ---- diamond: shared subgraph re-collapses to one node ----
|
|
|
|
(define
|
|
mo-diamond
|
|
(artdag/build
|
|
(list
|
|
(list "a" "src" (list) {})
|
|
(list "b" "blur" (list "a") {:radius 1})
|
|
(list "c" "bright" (list "a") {:gain 2})
|
|
(list "d" "over" (list "b" "c") {} true))))
|
|
(define mo-d-id (artdag/dag-id mo-diamond "d"))
|
|
(define mo-diamond-rt (artdag/mb-roundtrip mo-diamond mo-d-id))
|
|
|
|
(artdag-test
|
|
"roundtrip diamond: shared node not duplicated"
|
|
(artdag/node-count mo-diamond-rt)
|
|
4)
|
|
|
|
(artdag-test
|
|
"roundtrip diamond: sink id preserved"
|
|
(artdag/member? mo-d-id (keys (artdag/dag-nodes mo-diamond-rt)))
|
|
true)
|
|
|
|
(artdag-test
|
|
"roundtrip diamond: shared src id preserved"
|
|
(artdag/member?
|
|
(artdag/dag-id mo-diamond "a")
|
|
(keys (artdag/dag-nodes mo-diamond-rt)))
|
|
true)
|
|
|
|
; ---- optimisation laws as a confluent maude module (optimize-rules.sx) ----
|
|
; The optimised pipeline is the normal form; confluence => stable content id.
|
|
|
|
(artdag-test "opt module is confluent" (artdag/opt-confluent?) true)
|
|
|
|
(artdag-test
|
|
"opt module has no non-joinable critical pairs"
|
|
(len (artdag/opt-non-joinable))
|
|
0)
|
|
|
|
(artdag-test
|
|
"law: identity elimination"
|
|
(artdag/opt-normal-form "id(src)")
|
|
"src")
|
|
|
|
(artdag-test
|
|
"law: zero-radius blur is a no-op"
|
|
(artdag/opt-normal-form "blur(src, 0)")
|
|
"src")
|
|
|
|
(artdag-test
|
|
"law: zero-radius bright is a no-op"
|
|
(artdag/opt-normal-form "bright(src, 0)")
|
|
"src")
|
|
|
|
(artdag-test
|
|
"law: adjacent blur fusion adds radii"
|
|
(artdag/opt-normal-form "blur(blur(src, 1), 1)")
|
|
"blur(src, _+_(1, 1))")
|
|
|
|
(artdag-test
|
|
"fusion normal form is rewrite-order stable"
|
|
(artdag/opt-same-form?
|
|
"blur(blur(blur(src, 1), 1), 1)"
|
|
"blur(blur(src, 1 + 1), 1)")
|
|
true)
|
|
|
|
(artdag-test
|
|
"laws compose: id + no-op + fusion"
|
|
(artdag/opt-normal-form "bright(id(blur(blur(src, 1), 1)), 0)")
|
|
"blur(src, _+_(1, 1))")
|
|
|
|
(artdag-test
|
|
"law: idempotent over dedup (CSE)"
|
|
(artdag/opt-normal-form "over(blur(src, 1), blur(src, 1))")
|
|
"blur(src, 1)")
|
|
|
|
(artdag-test
|
|
"distinct over operands do not dedup"
|
|
(artdag/opt-same-form? "over(blur(src, 1), blur(src, 1 + 1))" "blur(src, 1)")
|
|
false)
|
|
|
|
(artdag-test
|
|
"distinct pipelines stay distinct"
|
|
(artdag/opt-same-form? "blur(src, 1)" "bright(src, 1)")
|
|
false)
|