Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 57s
Squash merge of 76 commits from loops/minikanren. Adds lib/minikanren/ — a complete miniKanren-on-SX implementation built on top of lib/guest/match.sx, validating the lib-guest unify-and-match kit as intended. Modules (20 .sx files, ~1700 LOC): unify, stream, goals, fresh, conde, condu, conda, run, relations, peano, intarith, project, nafc, matche, fd, queens, defrel, clpfd, tabling Phases 1–5 fully done (core miniKanren API, all classic relations, matche, conda, project, nafc). Phase 6 — native CLP(FD): domain primitives, fd-in / fd-eq / fd-neq / fd-lt / fd-lte / fd-plus / fd-times / fd-distinct / fd-label, with constraint reactivation iterating to fixed point. N-queens via FD: 4-queens 2 solutions, 5-queens 10 solutions (vs naive timeout past N=4). Phase 7 — naive ground-arg tabling: table-1 / table-2 / table-3. Fibonacci canary: tab-fib(25) = 75025 in seconds, naive fib(25) times out at 60s. Ackermann via table-3: A(3,3) = 61. 71 test files, 644+ tests passing across the suite. Producer/consumer SLG (cyclic patho, mutual recursion) deferred — research-grade work. The lib-guest validation experiment is conclusive: lib/minikanren/ unify.sx adds ~50 lines of local logic (custom cfg, deep walk*, fresh counter) over lib/guest/match.sx's ~100-line kit. The kit earns its keep ~3× by line count.
71 lines
1.7 KiB
Plaintext
71 lines
1.7 KiB
Plaintext
;; lib/minikanren/tests/graph.sx — directed-graph reachability via patho.
|
|
|
|
(define
|
|
test-edges
|
|
(list (list :a :b) (list :b :c) (list :c :d) (list :a :c) (list :d :e)))
|
|
|
|
(define edgeo (fn (from to) (membero (list from to) test-edges)))
|
|
|
|
(define
|
|
patho
|
|
(fn
|
|
(x y path)
|
|
(conde
|
|
((edgeo x y) (== path (list x y)))
|
|
((fresh (z mid-path) (edgeo x z) (patho z y mid-path) (conso x mid-path path))))))
|
|
|
|
;; --- direct edges ---
|
|
|
|
(mk-test "patho-direct" (run* q (patho :a :b q)) (list (list :a :b)))
|
|
|
|
(mk-test "patho-no-direct-edge" (run* q (patho :e :a q)) (list))
|
|
|
|
;; --- indirect ---
|
|
|
|
(mk-test
|
|
"patho-multi-hop"
|
|
(let
|
|
((paths (run* q (patho :a :d q))))
|
|
(and
|
|
(= (len paths) 2)
|
|
(and
|
|
(some (fn (p) (= p (list :a :b :c :d))) paths)
|
|
(some (fn (p) (= p (list :a :c :d))) paths))))
|
|
true)
|
|
|
|
(mk-test
|
|
"patho-to-leaf"
|
|
(let
|
|
((paths (run* q (patho :a :e q))))
|
|
(and
|
|
(= (len paths) 2)
|
|
(and
|
|
(some (fn (p) (= p (list :a :b :c :d :e))) paths)
|
|
(some (fn (p) (= p (list :a :c :d :e))) paths))))
|
|
true)
|
|
|
|
;; --- enumeration with multiplicity ---
|
|
;; Each path contributes one tuple, so reachable nodes can repeat. Here
|
|
;; targets are: b (1 path), c (2 paths), d (2 paths), e (2 paths) = 7.
|
|
|
|
(mk-test
|
|
"patho-enumerate-from-a-with-multiplicity"
|
|
(let
|
|
((targets (run* q (fresh (path) (patho :a q path)))))
|
|
(and
|
|
(= (len targets) 7)
|
|
(and
|
|
(some (fn (t) (= t :b)) targets)
|
|
(and
|
|
(some (fn (t) (= t :c)) targets)
|
|
(and
|
|
(some (fn (t) (= t :d)) targets)
|
|
(some (fn (t) (= t :e)) targets))))))
|
|
true)
|
|
|
|
;; --- unreachable target ---
|
|
|
|
(mk-test "patho-unreachable" (run* q (patho :a :z q)) (list))
|
|
|
|
(mk-tests-run!)
|