Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 58s
`table-2` wraps a 2-arg (input, output) relation. On a ground input walk, looks up the (string-encoded) cache key; on miss, runs the relation, drains the answer stream, extracts walk*-output values from each subst, stores them, and replays. On hit, replays the cached values directly — no recomputation. Cache lifetime: a single global mk-tab-cache (mutated via set!). mk-tab-clear! resets between independent queries. Canonical demo: tabled fib(25) = 75025 in ~5 seconds; the same naive fib-o times out at 60s. Memoization collapses the exponential redundant recomputation in the binary recursion. Limitations (deferred to future SLG work): cyclic recursive calls with the same ground key still diverge — naive memoization populates the cache only AFTER computation completes, so a recursive call inside its own computation can't see the in-progress entry. The brief's "tabled patho on cyclic graphs" use case requires producer/consumer scheduling and is left for a future iteration. 12 new tests, fib(0..20) + ground-term predicate + cache-replay verification. 638/638 cumulative.
61 lines
1.6 KiB
Plaintext
61 lines
1.6 KiB
Plaintext
;; lib/minikanren/tests/tabling.sx — Phase 7 piece A: naive memoization.
|
|
|
|
;; --- Fibonacci canary: tabled vs naive --
|
|
|
|
(define
|
|
tab-fib-o
|
|
(table-2
|
|
"fib"
|
|
(fn
|
|
(n result)
|
|
(conde
|
|
((== n 0) (== result 0))
|
|
((== n 1) (== result 1))
|
|
((fresh (n-1 n-2 r-1 r-2) (lto-i 1 n) (minuso-i n 1 n-1) (minuso-i n 2 n-2) (tab-fib-o n-1 r-1) (tab-fib-o n-2 r-2) (pluso-i r-1 r-2 result)))))))
|
|
|
|
(mk-tab-clear!)
|
|
|
|
(mk-test "tab-fib-zero" (run* q (tab-fib-o 0 q)) (list 0))
|
|
(mk-tab-clear!)
|
|
(mk-test "tab-fib-one" (run* q (tab-fib-o 1 q)) (list 1))
|
|
(mk-tab-clear!)
|
|
(mk-test "tab-fib-two" (run* q (tab-fib-o 2 q)) (list 1))
|
|
(mk-tab-clear!)
|
|
(mk-test "tab-fib-five" (run* q (tab-fib-o 5 q)) (list 5))
|
|
(mk-tab-clear!)
|
|
(mk-test "tab-fib-ten" (run* q (tab-fib-o 10 q)) (list 55))
|
|
(mk-tab-clear!)
|
|
(mk-test
|
|
"tab-fib-twenty"
|
|
(run* q (tab-fib-o 20 q))
|
|
(list 6765))
|
|
|
|
;; --- ground-term predicate ---
|
|
|
|
(mk-test "tab-ground-term-num" (mk-tab-ground-term? 5) true)
|
|
(mk-test "tab-ground-term-str" (mk-tab-ground-term? "hi") true)
|
|
(mk-test
|
|
"tab-ground-term-list"
|
|
(mk-tab-ground-term? (list 1 2 3))
|
|
true)
|
|
(mk-test "tab-ground-term-var" (mk-tab-ground-term? (mk-var "x")) false)
|
|
(mk-test
|
|
"tab-ground-term-nested"
|
|
(mk-tab-ground-term?
|
|
(list 1 (list 2 (mk-var "y")) 3))
|
|
false)
|
|
|
|
;; --- caching reduces work — count cache hits via repeated query ---
|
|
|
|
(mk-test
|
|
"tab-cache-replay"
|
|
(begin
|
|
(mk-tab-clear!)
|
|
(let
|
|
((first (run* q (tab-fib-o 10 q)))
|
|
(second (run* q (tab-fib-o 10 q))))
|
|
(and (= first (list 55)) (= second (list 55)))))
|
|
true)
|
|
|
|
(mk-tests-run!)
|