Negation in core.logic

662 views
Skip to first unread message

Stathis Sideris

unread,
Sep 19, 2012, 11:11:06 AM9/19/12
to clo...@googlegroups.com
Hello,

Is there a way to negate a goal in core.logic? I have written this goal below, and I would like to use it to query all the pairs of people who are *not* relatives according to my facts (for dating purposes of course :-D)

(defn relative [p1 p2]
  (conde
    [(parent p1 p2)]
    [(parent p2 p1)]
    [(sibling p1 p2)]
    [(cousin p1 p2)]
    [(nephew p1 p2)]
    [(uncle p1 p2)]))

Thanks,

Stathis

David Nolen

unread,
Sep 19, 2012, 12:41:59 PM9/19/12
to clo...@googlegroups.com
core.logic currently only supports Prolog's negation as failure. You can write a goal that looks like this:

(defn not [g]
  (fn [a]
    (if (nil? (g a))
      a)))

But you must be careful if you use this, all logic vars passed to the goal g must be ground. So it's not relational.

I have some leads based on recent Prolog research (CiaoProlog, and an interesting dissertation on the abstract interpretation of Prolog) for really handling negation in core.logic but I don't think I'll have time to deal with it any time soon. Again, more than willing and excited to collaborate with people who would like to see it done sooner.

David

Stathis Sideris

unread,
Sep 20, 2012, 4:54:30 AM9/20/12
to clo...@googlegroups.com
Thanks a lot David. As much as I'd like to contribute, I've only just started looking into logic programming.

Stathis

Alex Dowad

unread,
Aug 9, 2013, 5:19:20 PM8/9/13
to clo...@googlegroups.com
Sorry to post on an old thread, but just in case someone comes here from Google:

I'm just playing with core.logic, and I think I found a way to negate a goal... I don't know if this is advisable or not, but it seems to work:

(== 0 (count (run* [arg] (goal arg))))

David Nolen

unread,
Aug 9, 2013, 5:22:12 PM8/9/13
to clojure
I've since added an experimental Prolog style negation as failure constraint `nafc`.


--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups "Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email to clojure+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Norman Richards

unread,
Aug 9, 2013, 5:59:18 PM8/9/13
to clo...@googlegroups.com
On Fri, Aug 9, 2013 at 4:19 PM, Alex Dowad <alexin...@gmail.com> wrote:

(== 0 (count (run* [arg] (goal arg))))

What this is actually doing 

(run* [q] 
  ;;... some stuff



Norman Richards

unread,
Aug 9, 2013, 6:05:00 PM8/9/13
to clo...@googlegroups.com
Sorry - gmail spasm....  

What I was trying to say is that what I think your code is doing is running a Clojure expression once and unifying with 0.  It's equivalent to precomputing that outside of the run*:

(let [result (count (run* [arg] (goal arg))] 
  (run* [q]
     ;; whatever-else-you-were doing
     (== 0 result)))

Now, of course that expression could use some projected value or be embedded in a goal that gets tested multiple times, but chances are that the naive uses of that are probably not doing what you really want to do.

Alex

unread,
Aug 10, 2013, 1:31:09 AM8/10/13
to clo...@googlegroups.com
Hi, Norman Richards,

In the example, "arg" and "goal" were not literal but were meant to be replaced with something appropriate to whatever you are trying to do. Yes, unless you use a projected value, it is equivalent to precomputing it outside the run*. The point was that, although very hacky, there is a way to create a goal which succeeds if, and only if, another goal fails. Having said that, David Nolen's "nafc" constraint sounds much better and I am going to check it out right now.


--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@googlegroups.com
Note that posts from new members are moderated - please be patient with your first post.
To unsubscribe from this group, send email to
clojure+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to a topic in the Google Groups "Clojure" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/clojure/hz63yeQfiQE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to clojure+u...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages