Skip to content
swannodette edited this page Aug 2, 2012 · 29 revisions

Simple in memory database

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))

CLP(FD)

CLP(Tree) (Disequality)

Tabling

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))

Definite Clause Grammars (Experimental)

core.logic has Prolog-type DCG syntax for parsing:

(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]]]])