mk: graph reachability via patho — classic miniKanren
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
Defines a small graph as a fact list, edgeo for fact lookup, and patho
that recursively constructs paths. Direct-edge clause yields (x y);
otherwise traverse one edge to z, recurse for z->y, prepend x.
Enumerates all paths between two nodes, including alternates through
shortcut edges:
(run* q (patho :a :d q))
-> ((:a :b :c :d) (:a :c :d)) ; both routes
6 new tests, 316/316 cumulative.
This commit is contained in:
70
lib/minikanren/tests/graph.sx
Normal file
70
lib/minikanren/tests/graph.sx
Normal file
@@ -0,0 +1,70 @@
|
||||
;; 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!)
|
||||
@@ -173,6 +173,11 @@ _(none yet)_
|
||||
|
||||
_Newest first._
|
||||
|
||||
- **2026-05-08** — **Graph reachability via patho**: classic miniKanren
|
||||
graph search. `edgeo` looks up edges in a fact list via `membero`; `patho`
|
||||
recursively builds paths via direct-edge OR (one edge + recurse + cons).
|
||||
Enumerates all paths between two nodes, including alternates through
|
||||
shortcuts. 6 new tests, 316/316 cumulative.
|
||||
- **2026-05-08** — **everyo / someo (predicate-style relations)**:
|
||||
`(everyo rel l)` — every element of l satisfies rel; `(someo rel l)` —
|
||||
some element does. Both compose with intarith for numeric tests:
|
||||
|
||||
Reference in New Issue
Block a user