Here we have the usual minikanren fair search operators
and then modified "depth first" variants
This allows mk programming where you can select which kind search subprograms should use
(define-syntax conj+ (syntax-rules () ((_ g) (Zzz g)) ((_ g0 g ...) (conj (Zzz g0) (conj+ g ...))))) (define-syntax disj+ (syntax-rules () ((_ g) (Zzz g)) ((_ g0 g ...) (disj (Zzz g0) (disj+ g ...))))) (define-syntax conde (syntax-rules () ((_ (g0 g ...) ...) (disj+ (conj+ g0 g ...) ...)))) ;; depth first search versions of the same (define-syntax conj+/dfs (syntax-rules () ((_ g) g) ((_ g0 g ...) (conj/dfs g0 (conj+/dfs g ...))))) (define-syntax disj+/dfs (syntax-rules () ((_ g) g) ((_ g0 g ...) (disj/dfs g0 (disj+/dfs g ...))))) (define-syntax conde/dfs (syntax-rules () ((_ (g0 g ...) ...) (disj+/dfs (conj+ g0 g ...) ...))))
The difference is simply that we don't "delay" using Zzz in the DFS version.
How can we represent a map in minikanren? A list of the regions and then as association list explaining what each region is next to.
becomes
(define nodes '(quebec northwest-territories ontario british-columbia manitoba alberta saskatchewan yukon nunavut newfoundland-and-labrador new-brunswick nova-scotia prince-edward-island)) (define edges '((quebec ontario) (quebec new-brunswick) (quebec newfoundland-and-labrador) (northwest-territories yukon) (northwest-territories british-columbia) (northwest-territories alberta) (northwest-territories saskatchewan) (northwest-territories nunavut) (ontario manitoba) (british-columbia yukon) (british-columbia alberta) (manitoba saskatchewan) (manitoba nunavut) (alberta saskatchewan) (new-brunswick nova-scotia)))
Here is the minikanren code for coloring in these maps!
The function "graph-good-ordering" (omitted from this slide) is what does the map reduction in order to figure out how to arrange the minikanren program so that it only uses local backtracking. That is just a pure scheme function with no minikanren or unification involved.
(define (coloro x) (membero x '(red green blue yellow))) (define (different-colors table) (lambda (constraint) (fresh (x y x-color y-color) (== constraint `(,x ,y)) (assoco x table x-color) (assoco y table y-color) (=/= x-color y-color)))) (define (my-mapo p l i) ;; This has to be done in a depth first search! ;; (display (make-list i '-)) (newline) (conde/dfs ((== l '())) ((fresh/dfs (car cdr) (== l `(,car . ,cdr)) (p car) (my-mapo p cdr (+ i 1)))))) (define (color states edges colors) ;; This is a simple constrained generate and test solver ;; The interesting part was the graph reduction preprocessing ;; stage. (fresh (table) ;; make a list to hold the color of each state (make-assoc-tableo states colors table) ;; make sure each color is different to neighbours (mapo (different-colors table) edges) ;; brute force search for a valid coloring (my-mapo coloro colors 0))) (define (do-australia) (let ((nodes (graph-good-ordering australia:nodes australia:edges))) (run^ 1 (lambda (q) (color nodes australia:edges q))))) (define (do-canada) (let ((nodes (graph-good-ordering canada:nodes canada:edges))) (run^ 1 (lambda (q) (color nodes canada:edges q))))) (define (do-america) (let ((nodes (graph-good-ordering america:nodes america:edges))) (run^ 1 (lambda (q) (color nodes america:edges q)))))
Using DFS to solve these map coloring problems give a huge speedup!