Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Arithmetic and clojure functions on core.logic lvars

Two related questions in one:

Can Clojure's core.logic module perform arithmetic, logical comparison, etc, like ordinary Prolog? I am envisioning something like the following:

(defrel points person n) 
(fact :bob 2)
(fact :charlie 3)
(run* [q] (fresh [x y] 
   (points :bob x) 
   (points :charlie y) 
   (< x y) 
   (== q (+ x y))))

=> (5)

In this example, neither the logical comparison (< x y) nor the attempted binding of q to (+ x y) works. I suppose that this is because I'm working with LVars, not integers at this point, and I can't make these comparisons because the symbols aren't yet bound. But it works in prolog:

points(bob, 2).
points(charlie, 3).
?- points(bob, X), points(charlie, Y), Result is X + Y.

=> Result = 5.

In a similar vein, can I somehow use Clojure functions (which return booleans or other "truthy" values) as logic predicates? In other words, to use functions to tell Minikanren which terms unify or not. Something along the lines of:

(defmagic startswithhi-o [v]
  (.startsWith v "hi"))
(defrel person n)
(fact person "bob")
(fact person "hillary")
(run* [q] 
   (fresh [n]
     (person n)
     (startswithhi-o n)
     (== q n)))

=> ("hillary")

If I try things like this I get errors also complaining that the LVars aren't bound. Is there a way to do this?

Lastly if anyone has read this far, I might as well ask: are there plans to incorporate probabilistic logic into core.logic, along the lines of:

http://dtai.cs.kuleuven.be/problog/ ?

I'm not holding my breath but it would be awesome!

like image 792
gilesc Avatar asked Oct 05 '11 23:10

gilesc


2 Answers

Non-relational arithmetic is possible via project.

(run 1 [q]
   (fresh [x y]
        (== x 1)
        (== y 2)
        (project [x y]
                 (== q (+ x y)))))
(3)

I believe the Prolog example given is also non-relational.

The second half of your question can also be solved via project, but you must be careful that you always input a ground value.

(defn startwith [x]
    (project [x]
         (== true (.startsWith x "hi"))))

PS: Hold your breath for Constraint Logic Programming to come to core.logic!

like image 124
Ambrose Avatar answered Nov 15 '22 01:11

Ambrose


I believe you have to "project" (nonrel/project) a logic variable to its binding before you can apply a function to it:

(defrel points person n) 
(fact points :bob 2)
(fact points :charlie 3)
(run* [q] 
  (exist [x y] 
    (points :bob x) 
    (points :charlie y) 
    (project [x y]
      (== true (< x y)) 
      (== q (+ x y)))))

Note that exist substitutes for fresh in the original snippet and the additional argument for the fact declarations.

like image 2
cderoove Avatar answered Nov 15 '22 02:11

cderoove