Reputation: 4233
I want to:
Take the following as an example:
Red robotic birds are only composed of buttons, cheese, and wire.
I want to express that a class of birds, birds that are red and robotic, have a property. This property is that they are composed only of buttons, cheese, and wire. There are no restrictions on the type of wire cheese or buttons. Also as a result, it should be deducible that there are no red robotic birds that are composed of paper. Also, these birds can be composed of a subset of the items buttons, cheese, and wire.
In clojure/core.logic.prelude, there are relations and facts using defrel
and fact
.
However, I can't come up with a combination to explain this fact.
Upvotes: 17
Views: 3218
Reputation: 18556
In Prolog there is no distinction between facts and goals as there are in miniKanren. I might address this in the future.
BTW, I'm not sure that this completely answers your question - it would be helpful to hear what types of queries you wish to run.
This is tested code (for Clojure 1.3.0-beta1) since I'm using the ^:index trick, this code will run fine in 1.2.0 if you swap it for ^{:index true}:
(ns clojure.core.logic.so
(:refer-clojure :exclude [==])
(:use [clojure.core.logic]))
(defrel property* ^:index p ^:index t)
(fact property* :bird :red-robotic-bird)
(fact property* :red :red-robotic-bird)
(fact property* :robotic :red-robotic-bird)
(fact property* :tasty :cake)
(fact property* :red-robotic-bird :macaw)
(defn property [p t]
(conde
[(property* p t)]
[(fresh [ps]
(property* ps t)
(property p ps))]))
(defrel composition* ^:index m ^:index t)
(fact composition* :buttons :red-robotic-bird)
(fact composition* :cheese :red-robotic-bird)
(fact composition* :wire :red-robotic-bird)
(fact composition* :flour :cake)
(defn composition [m t]
(fresh [p]
(composition* m p)
(conde
[(== p t)]
[(property p t)])))
Trying it out.
(comment
;; what is a macaw composed of?
(run* [q] (composition q :macaw))
;; (:wire :cheese :buttons)
;; what things include buttons in their composition?
(run* [q] (composition :buttons q))
;; (:red-robotic-bird :macaw)
;; does a macaw include flour in its composition?
(run* [q] (composition :flour :macaw))
;; ()
;; is a macaw a bird?
(run* [q] (property :bird :macaw))
;; (_.0)
;; is a cake a bird?
(run* [q] (property :bird :cake))
;; ()
;; what are the properties of a macaw?
(run* [q] (property q :macaw))
;; (:red-robotic-bird :robotic :bird :red)
)
Upvotes: 23
Reputation: 40658
Not entirely sure if this is what you need, but you can easily express that a class has a set of properties by creating a graph structure of facts (see the list of properties facts below and the rule for finding the properties within a set).
Then to express the composition of that set of properties you need another set of composition facts and rule that discovers any sub-properties of the class and as a result things it can be composed of.
I've given a code example below as well to help explain.
property(bird, red_robotic_bird).
property(red, red_robotic_bird).
property(robot, red_robotic_bird).
property(tasty, cake).
property(red_robotic_bird, macaw).
property(Property, Thing) :-
property(PropertySet, Thing),
property(Property, PropertySet).
composition(buttons, red_robotic_bird).
composition(cheese, red_robotic_bird).
composition(wire, red_robotic_bird).
composition(flour, cake).
composition(Material, Thing) :-
property(Property, Thing),
composition(Material, Property).
example queries
?- composition(Material, macaw).
Material = buttons ;
Material = cheese ;
Material = wire ;
no
?- composition(buttons, Thing).
Thing = red_robotic_bird ;
Thing = macaw ;
no
?- composition(flour, macaw).
no
?- property(bird, macaw).
yes
?- property(bird, cake).
no
property(Property, macaw).
Property = red_robotic_bird ;
Property = bird ;
Property = red ;
Property = robot ;
no
Prolog rules in brief.
Rules are essentially just facts (eg. animal(cat).
) that are conditional on other rules or facts being true. A rule is made up a head and a body (head :- body.
). A body is a logical proof most commonly expressed in conjunctive normal form (A /\ B /\ C). The and operator in prolog is ,
, the or operator is ;
(but its use is discouraged in rules), and the period (.
) denotes the end of a rule or fact.
Note that if a later rule or fact in the body fails then prolog will backtrack and ask for an alternative answer from a previous rule or fact and then try again. Consider the somewhat contrived example below.
share_same_colour(FruitA, FruitB) :- colour(Colour, FruitA), colour(Colour, FruitB).
If we execute the query share_same_colour(apple, strawberry).
then colour(Colour, apple).
might return Colour as being green. However, there no green strawberries, so prolog will backtrack and ask what other colours do apples come in. The next answer might be red, upon which the second colour statement would succeed and the whole rule be true.
Upvotes: 4