Core.logic, dynamically generated goals

94 views
Skip to first unread message

Alex Robbins

unread,
May 19, 2012, 2:12:06 PM5/19/12
to clo...@googlegroups.com
I'm just getting started with logic programming, and it is entirely
possible I'm just approaching this incorrectly.

Is it possible to use dynamically generated goals in run* ?

For example,

(defrel grade person course g)
(fact grade 'Bob 'Algebra 'B)
(fact grade 'Bob 'Art 'C)
(fact grade 'John 'Algebra 'A)
(fact grade 'John 'Art 'A)
(fact grade 'Ricky 'Algebra 'D)
(fact grade 'Ricky 'Art 'A)

(def knowledge
{:course 'Algebra :g 'B})

(defn generate-goals [knowledge]
(map
(fn [{:keys [course g]}] (list 'grade 'person course g))
knowledge))

I want to do something like this (but valid clojure):
(run* [person]
~@(generate-goals knowledge))

It should give me back a list of people who match my current
knowledge. If I have more knowledge about the person, it will generate
more conditions, less knowledge fewer conditions. However, since run*
and run are macros, I can't apply them to a list. I can't splice in
because I'm not in a quotes list. Any ideas?

Thanks!

David Nolen

unread,
May 19, 2012, 3:02:12 PM5/19/12
to clo...@googlegroups.com
I don't think you need to generate goals for something as straightforward as this:

(defrel grade person course g)
(fact grade 'Bob 'Algebra 'B)
(fact grade 'Bob 'Art 'C)
(fact grade 'John 'Algebra 'A)
(fact grade 'John 'Art 'A)
(fact grade 'Ricky 'Algebra 'D)
(fact grade 'Ricky 'Art 'A)

(defn matches [{:keys [course g]}]
  (run* [q]
    (fresh [p]
      (grade p course g)
      (== q [p course g]))))

(matches {:course 'Algebra :g 'B})


--
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

Alex Robbins

unread,
May 19, 2012, 3:07:47 PM5/19/12
to clo...@googlegroups.com
Hmm, I didn't explain it very well. What if I had more knowledge?
Maybe I knew two grades sometimes. That could cut down on the list of
possible students (assuming there are more than the three in my
example).

How could I write a function that worked for both of these cases?
(matches [{:course 'Algebra :g 'B}])
(matches [{:course 'Algebra :g 'B} {:course 'Art :g 'C}])

Jason Jackson

unread,
May 19, 2012, 3:11:53 PM5/19/12
to clo...@googlegroups.com
Are you trying to see if a person meets multiple requirements? Here's how:



(defrel grade person course g)
(fact grade 'Bob 'Algebra 'B) 
(fact grade 'Bob 'Art 'C) 
(fact grade 'John 'Algebra 'A) 
(fact grade 'John 'Art 'A) 
(fact grade 'Ricky 'Algebra 'D) 
(fact grade 'Ricky 'Art 'A)

(defn meets-requirements [person [k & nowledge]]
  (if-let [{:keys [course g]} k]
    (all
     (grade person course g)
     (meets-requirements person nowledge))
    succeed))


#_ (run* [person]
     (meets-requirements
      person
      [{:course 'Algebra :g 'B}
       {:course 'Art :g 'C}]))
>> 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 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

Alex Robbins

unread,
May 19, 2012, 3:15:47 PM5/19/12
to clo...@googlegroups.com
Oh, so instead of trying to unroll my requirements into a bunch of
conditions, just make a single condition function that checks through
the list. That helps a lot!

Thanks!
Alex
>> >> 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 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 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

Brian Marick

unread,
May 20, 2012, 6:44:58 PM5/20/12
to clo...@googlegroups.com

On May 19, 2012, at 1:12 PM, Alex Robbins wrote:

> Is it possible to use dynamically generated goals in run* ?

You might want to think macros. I have written macros that tweak `run` bodies for various purposes:


`(~@runner [~qvar]
(l/fresh [~(gensyms :procedure) ~(gensyms :animal)]
(procedure-applies-to-animal-o ~(gensyms :procedure)
~(gensyms :animal))
(l/== ~(gensyms :procedure) ~procedure)
(l/== ~(gensyms :animal) ~animal)
~setter))]


-----
Brian Marick, Artisanal Labrador
Now working at http://path11.com
Contract programming in Ruby and Clojure
Occasional consulting on Agile


Alex Robbins

unread,
May 22, 2012, 9:55:42 AM5/22/12
to clo...@googlegroups.com
Good to think about. Thanks Brian.
Reply all
Reply to author
Forward
0 new messages