;; lib/minikanren/tests/tabling-slg.sx — Phase 7 piece A: SLG-style tabling.

;; --- table-2-slg with Fibonacci (sanity: same answer as naive table-2) ---

(mk-tab-clear!)
(define
  slg-fib-o
  (table-2-slg
    "slg-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) (slg-fib-o n-1 r-1) (slg-fib-o n-2 r-2) (pluso-i r-1 r-2 result)))))))

(mk-tab-clear!)
(mk-test "slg-fib-five" (run* q (slg-fib-o 5 q)) (list 5))
(mk-tab-clear!)
(mk-test "slg-fib-ten" (run* q (slg-fib-o 10 q)) (list 55))

;; --- table-3-slg with cyclic-graph patho ---

(define slg-cyc-edges (list (list :a :b) (list :b :a) (list :b :c)))
(define slg-cyc-edgeo (fn (x y) (membero (list x y) slg-cyc-edges)))

(mk-tab-clear!)
(define
  tab-patho
  (table-3-slg
    "patho"
    (fn
      (x y path)
      (conde
        ((slg-cyc-edgeo x y) (== path (list x y)))
        ((fresh (z mid) (slg-cyc-edgeo x z) (tab-patho z y mid) (conso x mid path)))))))

(mk-tab-clear!)
(mk-test
  "slg-cyclic-direct"
  (run* q (tab-patho :a :b q))
  (list (list :a :b)))

(mk-tab-clear!)
(mk-test
  "slg-cyclic-multi-hop"
  (run* q (tab-patho :a :c q))
  (list (list :a :b :c)))

(mk-tab-clear!)
(mk-test
  "slg-cyclic-self-loop-finite"
  (run* q (tab-patho :a :a q))
  (list (list :a :b :a)))

(mk-tests-run!)
