mk: phase 7 piece A — fixed-point iteration in SLG tabling
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 48s

Replace the single-pass body run with table-2-slg-iter / table-3-slg-iter:
each iteration stores the current vals in cache and re-runs the body;
loop until vals length stops growing. The cache thus grows
monotonically until no new answers appear.

For simple cycles (single tabled relation) this is sound and
terminating — len comparison is O(1) and the cache only grows.

Limitation: mutually-recursive tabled relations have INDEPENDENT
iteration loops. Each runs to its own fixed point in isolation; the
two don't coordinate. True SLG uses a worklist that cross-fires
re-iteration when any subgoal's cache grows. Left as a future
refinement.

All 5 SLG tests still pass (Fibonacci unchanged, 3 cyclic-patho
cases unchanged).
This commit is contained in:
2026-05-09 14:12:36 +00:00
parent 1d7400a54a
commit 28bd8bb98c

View File

@@ -13,6 +13,23 @@
;; recursive calls are NOT discovered. Full SLG with fixed-point
;; iteration (re-running until no new answers) is left for follow-up.
(define
table-2-slg-iter
(fn
(rel-fn input output s key prev-vals)
(begin
(mk-tab-store! key prev-vals)
(let
((all-substs (stream-take -1 ((rel-fn input output) s))))
(let
((vals (map (fn (s2) (mk-walk* output s2)) all-substs)))
(cond
((= (len vals) (len prev-vals))
(begin
(mk-tab-store! key vals)
(mk-tab-replay-vals vals output s)))
(:else (table-2-slg-iter rel-fn input output s key vals))))))))
(define
table-2-slg
(fn
@@ -30,21 +47,29 @@
(let
((cached (mk-tab-lookup key)))
(cond
((= cached :in-progress) mzero)
((not (= cached :miss))
(mk-tab-replay-vals cached output s))
(:else
(begin
(mk-tab-store! key :in-progress)
(let
((all-substs (stream-take -1 ((rel-fn input output) s))))
(let
((vals (map (fn (s2) (mk-walk* output s2)) all-substs)))
(begin
(mk-tab-store! key vals)
(mk-tab-replay-vals vals output s))))))))))
(table-2-slg-iter rel-fn input output s key (list)))))))
(:else ((rel-fn input output) s))))))))
(define
table-3-slg-iter
(fn
(rel-fn i1 i2 output s key prev-vals)
(begin
(mk-tab-store! key prev-vals)
(let
((all-substs (stream-take -1 ((rel-fn i1 i2 output) s))))
(let
((vals (map (fn (s2) (mk-walk* output s2)) all-substs)))
(cond
((= (len vals) (len prev-vals))
(begin
(mk-tab-store! key vals)
(mk-tab-replay-vals vals output s)))
(:else (table-3-slg-iter rel-fn i1 i2 output s key vals))))))))
(define
table-3-slg
(fn
@@ -62,17 +87,8 @@
(let
((cached (mk-tab-lookup key)))
(cond
((= cached :in-progress) mzero)
((not (= cached :miss))
(mk-tab-replay-vals cached output s))
(:else
(begin
(mk-tab-store! key :in-progress)
(let
((all-substs (stream-take -1 ((rel-fn i1 i2 output) s))))
(let
((vals (map (fn (s2) (mk-walk* output s2)) all-substs)))
(begin
(mk-tab-store! key vals)
(mk-tab-replay-vals vals output s))))))))))
(table-3-slg-iter rel-fn i1 i2 output s key (list)))))))
(:else ((rel-fn i1 i2 output) s))))))))