Hm, can anyone explain this?
(run* [q]
(fresh [a b]
(== q (list a b))
(fd/in a b (fd/interval 1 3))
(fd/< a b)
(nafc membero 2 q)))
;=> ((1 2) (2 3) (1 3))
The negation as failure constraint is supposed to ensure that 2 is not a member of the list q
, so I expected to get only the solution (1 3)
...It works if I replace the constraint with (nafc == a 2) (nafc == b 2)
or (!= a 2) (!= b 2)
but that gets cumbersome if the length of the list collection is long or even unknown...
Well, I think this is a bug so I've reported it: http://dev.clojure.org/jira/browse/LOGIC-172
Hm, it seems the problem only occurs stuff unified by clojure.core.logic.fd
relations...
@tsdh it's not an issue with fd, but it's because a
and b
are not ground. nafc
works only on grounded terms
So the following does what you expected:
(run* [q]
(fresh [a b]
(== q (list a b))
(fd/in a b (fd/interval 1 3))
(fd/< a b)
(== a 1)
(== b 2)
(l/nafc l/membero 2 q)))
;=> ()
while the following doesn't:
(run* [q]
(fresh [a b]
(== q (list a b))
(fd/in a b (fd/interval 1 3))
(fd/< a b)
(== a 1)
(l/nafc l/membero 2 q)
(== b 2)))
;=> ((1 2))
in the second example, b
is not ground for the nafc
a smaller example:
(run* [q]
(membero q [1 2])
(nafc membero 2 q))
;=> (1 2)
One way to accomplish what you were trying:
(run* [q]
(fresh [a b]
(== q (list a b))
(fd/in a b (fd/interval 1 3))
(fd/< a b)
(everyg #(!= 2 %) q)))
;=> ((1 3))
And if you have an arbitrary number of vars:
(let [vars (map lvar (range 4))]
(run* [q]
(== q vars)
(everyg #(fd/in % (fd/interval 1 6)) vars)
(everyg #(apply fd/< %) (partition 2 1 vars))
(everyg #(!= 2 %) q)))
;=> ((1 3 4 5) (3 4 5 6) (1 4 5 6) (1 3 5 6) (1 3 4 6))
@nberger: But the nafc
docs say that if the vars aren't ground, the evaluation of the constraint will be deferred.
...which I read as "it should work also for fresh vars where the actual check is deferred until the point where all vars are ground."
I think your smaller example is wrong. q
takes the values 1 and 2, and of course (membero 2 1)
and (membero 2 2)
fail.
Probably you meant this:
(run* [q]
(== q [1 2])
(nafc membero 2 q))
;=> ()
which actually gives the right answer.Yes, sorry, my example was wrong, so nafc is doing fine in that case. And reading again, I agree, deferred evaluation should do what you said
Well, we'll see if someone with more knowledge on the implementation comments on the JIRA issue.
yep :simple_smile: