Would appreciate any help on how this code should be changed with regards to the deprecation of defrel and facts and the move to pldb?
Here's the code:
(defrel parent x y)
(facts parent ’[[dave kaylen]
[frank dave]])
(defn grandparent
[x y]
(fresh [z]
(parent x z)
(parent z y)))
;; In the REPL
user> (run* [q]
(fresh [x y]
(grandparent x y)
(== q [x y])))
;; Result
([frank kaylen])
(ns your.ns.here
(:require [clojure.core.logic.pldb :as pldb]
[clojure.core.logic :refer :all]))
(pldb/db-rel parent p1 p2)
(def facts
(pldb/db
[parent 'dave 'kaylen]
[parent 'frank 'dave]))
(defn grandparent
[x y]
(fresh [z]
(parent x z)
(parent z y)))
(pldb/with-db facts
(doall (run* [q]
(fresh [x y]
(grandparent x y)
(== q [x y])))))
=> ([frank kaylen])
See the pldb tests from core.logic source for more examples
Related
I'm a beginner with logic programming.
I'm trying to implement a sorting relation like this:
(sorto [3 2 1][1 2 3]) -> #s
I'am using clojure and core.logic:
I don't understand why this can not terminate in most cases.
Any idea would be helpful, thank you.
(require '[clojure.core.logic :refer :all]
'[clojure.core.logic.fd :as fd])
First I define several little helpers:
A simple count relation: (counto [a b] 2) -> #s
(defne counto [list n]
([() 0])
([[fl . rl] _]
(fresh [nnxt]
(fd/- n 1 nnxt)
(counto rl nnxt))))
reduce and every? relational equivalents:
(defne reduceo [rel acc x y]
([_ _ () _] (== acc y))
([_ _ [fx . rx] _]
(fresh [nacc]
(rel acc fx nacc)
(reduceo rel nacc rx y))))
(defne everyo [g list]
([_ ()])
([_ [fl . rl]]
(g fl)
(everyo g rl)))
min relation: (mino 1 2 1) -> #s
(defn mino [x y z]
(conde
[(fd/<= x y) (== x z)]
[(fd/> x y) (== y z)]))
relation between a list and its minimum element: (mino* [1 2 3 0] 0) -> #s
(defne mino* [xs y]
([[fxs . rxs] _]
(reduceo mino fxs rxs y)))
The main relation: (sorto [2 3 1 4] [1 2 3 4]) -> #s
(defne sorto [x y]
([() ()])
([[fx . rx] [fy . ry]]
(fresh [x* c]
(counto rx c)
(counto ry c)
(mino* x fy)
(rembero fy x x*)
(sorto x* ry))))
The below runs doesn't terminate, I would like to understand why.
(run* [q]
(sorto q [1 2]))
; does not terminate
(run* [q]
(sorto [2 1] q))
; does not terminate
(run* [a b]
(everyo #(fd/in % (fd/interval 10)) a)
(everyo #(fd/in % (fd/interval 10)) b)
(sorto a b))
;neither
The high level answer is because conjunction are tried in order. Reordering them may sometimes make a program to terminate -- however in the general case there may not exist a "good" order.
Have a look at Chapter 5 in https://scholarworks.iu.edu/dspace/bitstream/handle/2022/8777/Byrd_indiana_0093A_10344.pdf
in clojure I'm using the following function to initialize a 2d vector:
(defn vec2d [x y init]
(vec (map
#(vec (map init (range x))) (range y))))
usage:
(def grid (vec2d 40 30 (fn [] "x")))
Since I'm new to the language, I ask myself if this is the most straight-forward way to do so. Has anyone an idea to optimize this?
Under the assumption that you'll always want to initialize the entries of the vector to a constant, here's how I'd do this:
(defn vec2d
"Return an x by y vector with all entries equal to val."
[x y val]
(vec (repeat y (vec (repeat x val)))))
if you want to be able to initialize according to the coordinate, you could do this
(defn vec2d [sx sy f]
(mapv (fn[x](mapv (fn[y] (f x y)) (range sx))) (range sy)))
This allows you to have a constant value if you do
(vec2d 4 3 (constantly 2))
;; [[2 2 2 2] [2 2 2 2] [2 2 2 2]]
or initialize according to the coordinates, say:
(vec2d 4 3 (fn[x y] (+ x y)))
(vec2d 4 3 +) ;; or more concisely
;;[[0 1 2 3] [1 2 3 4] [2 3 4 5]]
Use mapv and you're set
(defn vec2d [x y init]
(mapv #(mapv init (range x)) (range y)))
If you want the coordinates for initialization:
(defn vec2d [x y init]
(mapv (fn [y] (mapv #(init % y) (range x))) (range y))
A nested for it's also very readable for boards generation if you just want all cells:
(defn vec2d [cols rows init]
(for [x (range rows) y (range cols)]
(init x y)))
Or if you don't mind seqs:
(defn vec2d [cols rows init]
(for [x (range rows)]
(for [y (range cols)]
(init x y))))
Using a threading macro:
(defn vec-2d [r c v] (->> (repeat c v) vec (repeat r) vec))
There's an example in the book (P252), it's about the &env in macro, I just don't understand how to get the result{x 1, y 2}
(defmacro spy-env []
(let [ks (keys &env)]
`(prn (zipmap '~ks [~#ks]))))
(let [x 1 y 2]
(spy-env)
(+ x y))
; {x 1, y 2}
;= 3
I tried in the REPL like this:
user=> (defmacro spy-env [] (let [ks (keys &env)] `(prn ~#(keys &env))))
#'user/spy-env
user=> (let [x 1 y 2] (spy-env))
2 1
It's wried.
Expanding the macro would be a great way for you to see how it works, but unfortunately macroexpand-1 doesn't convey the right bindings for &env. This example:
(let [x 1 y 2] (spy-env))
Actually expands out to:
(let [x 1 y 2] (prn (zipmap '(x y) [x y])))
Do you get it? Within the first sequence, x and y are not evaluated, but within the second, they are. So it zips the symbols to whatever they evaluate to. Within that let block, (zipmap '(x y) [x y]) evaluates to {x 1 y 2}.
a) If you try the code of the book it does output the right value
user=> (defmacro spy-env []
#_=> (let [ks (keys &env)]
#_=> `(prn (zipmap '~ks [~#ks]))))
#'user/spy-env
user=> (let [x 1 y 2] (spy-env))
{x 1, y 2}
nil
user=> (let [x 1 y 2]
#_=> (spy-env)
#_=> (+ x y))
{x 1, y 2}
3
b) now your code is different
initial code :
`(prn (zipmap '~ks [~#ks]))
vs
`(prn ~#(keys &env))
with actually #(keys &env) being equal to #ks
What is the advantage of using fd/distinct in cases where the elements will be in a finite domain instead of distincto?
The following all return ([0 1] [1 0]).
;;; With distincto
(run* [q]
(fresh [x y]
(fd/in x y (fd/interval 1))
(distincto [x y])
(== q [x y])))
;;; With fd/distinct
(run* [q]
(fresh [x y]
(fd/in x y (fd/interval 1))
(fd/distinct [x y])
(== q [x y])))
;;; Without fd at all.
(let [interval [0 1]]
(run* [q]
(fresh [x y]
(membero x interval)
(membero y interval)
(distincto [x y])
(== q [x y]))))
Notably, although it appears you may use distincto in any place where you may use fd/distinct (but not the other way around), the same cannot be said for membero and fd/in.
fd/distinct is much more highly optimized than distincto which must receive any kind of value. fd/distinct under the hood deals with efficient representations of constrained variables all at once using sets, distincto uses the disequality operator != in a pretty simple manner.
I've used clojure for a while but just starting out with core.logic.
Given a domain like 1 2 3 4 I want to get a vector of two vectors back like ([[1 2] [3 4]]).
Note: This is just a simplified version of what I'm really trying to do. :) See: https://github.com/adamhoward/lineup
I found this definition for not-membero on the web:
(defne not-membero [x l]
([_ []])
([_ [?y . ?r]]
(!= x ?y)
(not-membero x ?r)))
And I'm trying to use it like this:
(run 1 [q]
(fresh [w x
y z]
(== q [[w x]
[y z]])
(infd w x y z (domain 1 2 3 4))
(everyg distinctfd [[w x] [y z]])
(everyg #(not-membero % [y z]) [w x])))
Running this in Emacs gives me an Evaluation aborted. message.
When I try switching out membero for not-membero I get back ([[1 2] [1 2]]) which makes sense to me. Every element in the first vector [w x] is a member of the second vector [y z].
But, when I call run 2 I get back ([[1 2] [1 2]] [[1 2] [1 3]]). I don't understand how [[1 2] [1 3]] can be correct for the rules above. Am I not understanding everyg correctly? Any guidance (including rtfmanual, rtfbook, rtfdissertation) will be appreciated.
Thanks.
Edit: May have solved this.
Still not sure about the strange results from membero but instead of the not-membero goal I found that I could do this:
(everyg #(distinctfd (conj [y z] %)) [w x])
Each element of [w x] conj'd to [y z] contains all distinct values. This may be less efficient than not-membero so I'm still open to any help.
Your example seems to be doing the same as this:
(run* [q]
(fresh [w x y z]
(fd/in w x y z (fd/domain 1 2 3 4))
(== q [[w x] [y z]])
(fd/distinct [w x y z])))
But seeing the soccer problem...
(ns test
(:refer-clojure :exclude [==])
(:use clojure.core.logic)
(require [clojure.core.logic.fd :as fd]))
(defn game [g] (fresh [a b c d e] (== g [a b c d e])))
(def players (range 1 11))
(defne not-membero [x l]
([_ []])
([_ [?y . ?r]]
(!= x ?y)
(not-membero x ?r)))
(defne plays [player games]
([_ []])
([_ [?f ?s . ?r]]
(membero player ?f) ; if you play this game
(not-membero player ?s) ; do not play next game
(plays player ?r))
([_ [?f ?s . ?r]]
(membero player ?s)
(not-membero player ?f)
(plays player ?r)))
(defne goalies [games]
([[[_ _ _ _ ?a]
[_ _ _ _ ?b]
[_ _ _ _ ?c]
[_ _ _ _ ?d]]]
(fd/in ?a ?b ?c ?d (apply fd/domain players))
(not-membero 1 [?a ?b ?c ?d]) ; star player != goalie
(fd/distinct [?a ?b ?c ?d]))) ; not goalie twice
(defn -main [& args]
(run 1 [q]
(fresh [a b c d]
(game a)
(game b)
(game c)
(game d)
(== q [a b c d])
(goalies q)
(everyg #(plays % q) players))))