-
Notifications
You must be signed in to change notification settings - Fork 123
Features
Sometimes it's useful to create a list of facts that you want to run queries over. Use defrel
and fact
.
(defrel man p)
(fact man 'Bob)
(fact man 'John)
(fact man 'Ricky)
(defrel woman p)
(fact woman 'Mary)
(fact woman 'Martha)
(fact woman 'Lucy)
(defrel likes p1 p2)
(fact likes 'Bob 'Mary)
(fact likes 'John 'Martha)
(fact likes 'Ricky 'Lucy)
(defrel fun p)
(fact fun 'Lucy)
(run* [q]
(fresh [x y]
(fun y)
(likes x y)
(== q [x y]))) ; ([Ricky Lucy])
It's important to index relationships so that the time to run queries doesn't grow linearly with the number of facts. You can create indexes for any element of the fact tuple. Note that this has implications for memory usage.
; Clojure 1.3.0
(defrel likes ^:index p1 ^:index p2)
; Clojure 1.2.0
(defrel likes ^{:index true} p1 ^{:index true} p2)
** A la carte unifier core.logic comes with a unifier that can be used much like core.unify:
(unifier '(?x ?y ?z) '(1 2 ?y)) ; (1 2 _.0)
The above is quite slow since we have to walk the data structure and replace the logic var symbols. It's more efficient to prep
the expressions before hand if you're going to be unifying the same expressions over and over again.
(let [[u w] (map prep ['(?x ?y) (1 2)])]
(unifier* u w))
core.logic as of version 0.5.4 supports tabling. Certain kinds of logic programs that would not terminate in Prolog will terminate in core.logic if you create a tabled goal.
(defne arco [x y]
([:a :b])
([:b :a])
([:b :d]))
(def patho
(tabled [x y]
(conde
[(arco x y)]
[(fresh [z]
(arco x z)
(patho z y))])))
;; (:b :a :d)
(run* [q] (patho :a q))
core.logic has Prolog-type Definite Clause Grammar syntax for parsing. Until core.logic gets support for environment trimming this feature should be considered for experimental use only.
(def-->e verb [v]
([[:v 'eats]] '[eats]))
(def-->e noun [n]
([[:n 'bat]] '[bat])
([[:n 'cat]] '[cat]))
(def-->e det [d]
([[:d 'the]] '[the])
([[:d 'a]] '[a]))
(def-->e noun-phrase [n]
([[:np d n]] (det d) (noun n)))
(def-->e verb-phrase [n]
([[:vp v np]] (verb v) (noun-phrase np)))
(def-->e sentence [s]
([[:s np vp]] (noun-phrase np) (verb-phrase vp)))
(run* [parse-tree]
(sentence parse-tree '[the bat eats a cat] []))
;; ([:s [:np [:d the] [:n bat]] [:vp [:v eats] [:np [:d a] [:n cat]]]])
core.logic has rapidly evolving support for different forms of constraint logic programming, CLP for short. core.logic is designed to be extensible to different constraint domains. Out of the box it supports disequality constraints over trees, known as CLP(Tree), and constraint over finite domains, know as CLP(FD).
CLP(Tree) is pretty simple and adds only one new operator !=
. Given two terms the use of the !=
operator will guarantee that the two terms will never unify, in some sense this is "opposite" of what is provided by the unification operator ==
.
The most straightforward use is to just check that something is not not equal to some other simple value.
(run* [q]
(!= q))