I was trying to implement a relation similar to (map + list1 list2) -> list3
My code is:
(require '[clojure.core.logic :as l])
(require '[clojure.core.logic.fd :as fd])
(defn zip+o [x y z]
(l/conde
[(l/== () x) (l/== () y) (l/== () z)]
[(l/fresh [fx rx fy ry fz rz]
(l/conso fx rx x)
(l/conso fy ry y)
(l/conso fz rz z)
(fd/in fx fy fz (fd/interval 10))
(fd/+ fx fy fz)
(zip+o rx ry rz))]))
(def expected-solutions
#{{:x [0 0] :y [1 1]}
{:x [0 1] :y [1 0]}
{:x [1 1] :y [0 0]}
{:x [1 0] :y [0 1]}})
(l/run* [q]
(l/fresh [x y]
(l/== q {:x x :y y})
(zip+o x y [1 1])))
;=> ({:x (1 0), :y (0 1)}
; {:x (0 0), :y (1 1)})
I've manage to get the expected behavior (I think...) by removing the call to onceo in clojure.core.logic/enforce-constraints
(defn enforce-constraints [x]
(all
(force-ans x)
(fn [a]
(let [constrained (enforceable-constrained a)]
(verify-all-bound a constrained)
((force-ans constrained) a) ;; <--- Here
#_((onceo (force-ans constrained)) a)))))
Sadly it breaks one test...
FAIL in (test-simplefd-in-last) (tests.clj:1797)
expected: (= (run* [q] (fresh [x y z p0 p1] (== q [x y]) (fd/+ x y 9) (fd/* x 2 p0) (fd/* y 4 p1) (fd/+ p0 p1 24) (fd/in x y z (fd/interval 0 9)))) (quote ([6 3])))
actual: (not (= ([6 3] [6 3] [6 3] [6 3] [6 3] [6 3] [6 3] [6 3] [6 3] [6 3]) ([6 3])))
I hope it will at least help you to find the real problem.