Skip to content

Instantly share code, notes, and snippets.

@jmgimeno
Created January 1, 2012 19:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jmgimeno/1548120 to your computer and use it in GitHub Desktop.
Save jmgimeno/1548120 to your computer and use it in GitHub Desktop.
SAT in clojure.core.logic
;Code from http://peteriserins.com/2011/12/23/sat-in-clojure-core-logic.html
(defn and-rewrite [expr]
`(conde
(~(goalify (second expr))
~(goalify (second (rest expr))))))
(defn or-rewrite [expr]
`(conde
(~(goalify (second expr)))
(~(goalify (second (rest expr))))))
(defn demorgan [subexpr]
(if (and (seq? subexpr)
(= 'not (first subexpr)))
(second subexpr)
(cons 'not (list subexpr))))
(defn not-rewrite [expr]
(let [expr (second expr)]
(cond
(symbol? expr)
`(== ~expr false)
(= 'not (first expr))
(goalify (second expr))
(= 'and (first expr))
(goalify (cons 'or (map demorgan (rest expr))))
(= 'or (first expr))
(goalify (cons 'and (map demorgan (rest expr)))))))
(defn goalify [expr]
"Turns boolean expressions into core.logic goals"
(cond
(symbol? expr)
`(== ~expr true)
(= 'and (first expr))
(and-rewrite expr)
(= 'or (first expr))
(or-rewrite expr)
(= 'not (first expr))
(not-rewrite expr)))
(defmacro sat [vars expr]
"SAT"
`(run* [q#]
(fresh ~vars
~(goalify expr)
(== q# ~vars))))
;Usage
(sat (and p (not p)))
;=> ()
(sat [p q] (not (and (or (not p) q)
q)))
;=> ([_.0 false] [true false])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment