Using And clause in HEAD of a prolog statement - prolog

Every member of this club is either educated or rich or both.
I wanted to write a statement very similar to above in my PROLOG code. I wrote everything else.
edu(X);rich(X) :- member(X).
This is what I had written. But then PROLOG doesn't allow any operators in the clause head. I have spent 5 hours till now trying to do various things with this statement but unable to reach a solution that works. :(

See http://en.wikipedia.org/wiki/Horn_clause for am explanation of the form of logic Prolog is based on.
Given your statement, ("Every member of this club is either educated or rich or both."), the only things you can declare to be true are:
A person is educated if they are a member and not rich.
A person is rich if they are a member and not educated.
The following, for example, are not necessarily true:
A person who is rich and educated is a member.
A member who is rich is educated.
A member who is rich is not educated.

You can't combine multiple heads. If you want edu(X) and rich(X) to be true when member(X) is true, you have to define them separately ("every member of this club is educationed" and "every member of this club is rich"):
edu(X) :-
member(X).
rich(X) :-
member(X).
The tricky part is that your original statement is not well-formed. It says that some members may be rich but not educated or vice versa. This is problematic. For example, let's take the naive case that if a member isn't rich, he's educated, and the reverse:
edu(X) :-
member(X), \+ rich(X).
rich(X) :-
member(X), \+ edu(X).
Now, according to these rules, nobody is automatically rich and educated. So long as we define every member as at least one of the two, this is fine. However, consider these facts:
member(alice).
member(bob).
member(charlie).
member(dave).
rich(alice).
edu(bob).
rich(charlie).
edu(charlie).
In this case, rich(alice) works fine, because it's a fact. edu(alice) will result in no. The reverse is true for bob. With charlie, we've defined both as facts, so both are true. But what about dave? Both edu(dave) and rich(dave) refer back to the other, creating an infinite recursion. Without any further knowledge of what you're doing, the best we can do to resolve this is to default either edu(X) or rich(X) to true:
edu(X) :-
member(X).
rich(X) :-
member(X), \+ edu(X).
Now everyone is assumed to be educated unless we explicitly declare otherwise. You could do the same thing defaulting to rich if you preferred. Short of additional information, this is the best you can do.

As a side note: the idea of using disjunctions in heads of clauses has lead to disjunctive logic programming, see, e.g., "Foundations of Disjunctive Logic Programming" by Jorge Lobo, Jack Minker, Arcot Rajaseka. edu(X);rich(X) :- member(X). would be a valid disjunctive clause. A related topic, disjunctive Datalog, has been explored by Nicola Leone, Gerald Pfeifer and Wolfgang Faber in the DLV project: http://www.dbai.tuwien.ac.at/proj/dlv/

Maybe you want to write:
member(X) :- edu(X) ; rich(X)
If someone is educated, rich or both, is a member of the club.

Related

forall/2 predicate query doesn’t return results

I have the following facts.
loves(ami, paul).
loves(lucy, paul).
female(ami).
artist(ami).
female(lucy).
artist(lucy).
canadian(paul).
lovesCanadianArtists(Person) :- forall(canadian(X), loves(Person, X)).
When I execute the query in SWI-Prolog:
?- lovesCanadianArtists(X).
The answer is true, and I don't get results.
Someone told me that the issue is the predicate isLovedByArtists(Person) is not inversible or invertible. So, I should add a condition on Person variable because it is not bound by the forall\2 predicate. Like:
lovesCanadianArtists(Person) :- female(Person), forall(canadian(X), loves(Person, X)).
So, my questions are:
Is this predicate invertibility documented anywhere ? I can't find it.
For me, the explanation given is wrong, and but I am not sure whether I should get results with my first rule. What's the underlying issue here ?
What's the underlying issue here ?
"forall/2 does not change any variable bindings. [...] If your intent is to create variable bindings, the forall/2 control structure is inadequate." - https://www.swi-prolog.org/pldoc/man?section=forall2
Perhaps one of foreach, findall, bagof or setof will do what you want, although it's not clear from the plural 'artists' and singular 'Person' exactly what that is; e.g. for a list of all People who love at least one Canadian artist, which may have duplicates if you add more Canadian artists:
lovesCanadianArtists(People) :-
findall(Person, (canadian(X), loves(Person, X)), People).

Learning Prolog (cuts, lists, negation) push me in the right direction

I have the following base knowledge:
“NBA players over 30 years old that have won at least 3 NBA championships are superstars. NBA players below 30 are superstars only if they appear on the front cover of a videogame or if they have at least 5 million followers in Twitter.”
Define a unary predicate superstar that gives only one answer (true/false) to each query, when applied to a concrete person, e.g. superstar(pauGasol). The rules should only check a fact once (for instance, they should not check the age of the queried person twice). You can’t use the “;” operator.
You can use these data in your tests (4 of these 8 players are superstars, according to the previous definition):
age(kobeBryant,37).
championships(kobeBryant,5).
millionsFollowers(kobeBryant,9).
age(pauGasol,35).
championships(pauGasol,2).
videogameCover(pauGasol).
millionsFollowers(pauGasol,3).
age(marcGasol,31).
videogameCover(marcGasol).
millionsFollowers(marcGasol,1).
age(stephenCurry,28).
championships(stephenCurry,1).
videogameCover(stephenCurry).
millionsFollowers(stephenCurry,5).
age(klayThompson,26).
championships(klayThompson,1).
age(kevinDurant,27).
millionsFollowers(kevinDurant,13).
age(russellWestbrook,27).
videogameCover(russellWestbrook).
millionsFollowers(russellWestbrook,3).
age(dwayneWade,29).
championships(dwayneWade,3).
millionsFollowers(dwayneWade,4).
So what i did was this:
superstar(X):- age(X,Y), Y>=30, championships(X,Z), Z>=3,!.
superstar(X):- age(X,Y), Y=<30, videogameCover(X),!.
superstar(X):- millionsFollowers(X,Z), Z>=5.
We learned lists, cuts and negation last lesson.
Could someone push me in the right direction as to what should i use, so the age is only checked once, and if it's greater then 30 goes one way less then 30 goes other way, im new to prolog and programming in general.
I am not asking for a solution, I am asking for a push, hint.
When i will figure it out, I will post the solution my self hopefully.
The request to access only once a DB table normalizes the AND/OR search tree. You could introduce a service predicate to discriminate a pre-condition.
superstar(X) :- age(X,Y), age_check(X,Y).
now, using the cut, you can actually commit to a branch
age_check(X,Y) :- Y>=30, !, championships(X,Z), Z>=3.
% other 2 rules for age_check, actually not using Y
or, avoid the cut, but use a correct domain disjunction:
age_check(X,Y) :- Y>=30, championships(X,Z), Z>=3.
age_check(X,Y) :- Y<30, etc etc
...
in the end i did it like this:
superstar(A) :- age(A,B), B>=30, !, championships(A,C), C>=3.
superstar(A) :- videogameCover(A),!.
superstar(A) :- millionsFollowers(A,B), B>=5.
This is how the teacher wanted it to be, seems like that is way to complicated for something that can be done simpler:
trichampion(X) :- championships(X,Z), Z>=3.
socialmediastar(X) :- millionsFollowers(X,Z), Z>=5.
superstar(X) :- age(X,Y), Y>=30,!,trichampion(X).
superstar(X) :- videogameCover(X),!.
superstar(X) :- socialmediastar(X).

Can anyone correct my prolog answer for the given statement if it is wrong?

1.Whale has a backbone.
whale(X):-backbone(X).
2.Whale grows with their mother's milk.
whale(X):-grows(X,Y),milk(Y,mother).
OR
grows(X):-whale(X),drinks(X,mother's_milk).
It really depends how you want to organize your database. You could, for example, also say:
A vertebrate (has a backbone) is a whale, or a dog, or a snake.
vertebrate(whale).
vertebrate(god).
vertebrate(snake).
Is whale a vertebrate?
?- vertebrate(whale).
true.
Similarly,
A mammal (feeds on their mother's milk) is a whale, or a dog.
mammal(whale).
mammal(dog).
The message here is that since you need to actully provide the database in some form, and since "has spine" and "is vertebrate" are the same thing, you might as well explicitly list all mammals.
Or are you thinking of some use case where the argument to whale/1 is an object created by the program, and backbone needs to look at it in some specific way (look at the value of an attribute, for example) to succeed or fail?
Edit
Think about it like this:
Whale has a backbone
has(whale, backbone).
But then, you could write,
vertebrate(X) :-
has_backbone(X).
has_backbone(X) :-
has(X, backbone).
And at that point you should see why this is indeed not necessary. Just write:
vertebrate(whale). % :- has_backbone(whalte) :- has(whale, backbone).
And, in the same way:
Whale grows on their mother's milk
grows_on(whale, 'mother\'s milk').
has(X, 'mammary glands') :-
grows_on(X, 'mother\'s milk').
mammal(X) :-
has(X, 'mammary glands').
Identical to above, you end up with:
mammal(whale).
As Boris indicates, it depends upon how you want to organize your data. Specifically, upon what detailed level you want to define your facts. If you get down to lower level facts, you'd look at the definition for mammal, for instance (OED):
Mammal: a warm-blooded vertebrate animal of a class that is
distinguished by the possession of hair or fur, the secretion of milk
by females for the nourishment of the young, and (typically) the birth
of live young.
So here, assuming the conditions given in the above definition are not only necessary but sufficient, you could define mammal in detail as:
mammal(X) :-
vertebrate(X),
warm_blooded(X),
(has_fur(X) ; has_hair(X)),
feeds_by_milk(X),
gives_live_birth(X).
Which would then require that you define all of these kinds facts for whatever beasts/things you are wanting to query about. (And, yes, a whale has hair, although very little of it.) The statement:
Whale grows with their mother's milk.
Would be a fact, not based upon a rule, because there's no fundamental fact that such a rule would be derived from. The fact, using the terms I introduced above, would be:
feeds_by_milk(whale).
If you don't want to have all those detailed data, then you'd do as Boris showed which is establish your lowest level facts as mammal:
mammal(whale).
mammal(dog).
In Prolog, it's important to think carefully about how facts are defined and what they really mean, semantically. In your initial example, you have what appears to be a fact called milk that has two arguments. You have an example usage, milk(Y, mother), but it doesn't very directly express the fact that Y feeds on it's mother's milk. It introduces mother as an argument, but unnecessarily since it's not likely that you'd have also something like milk(Y, father). feeds_by_milk(Y) or even, feeds_on_mothers_milk(Y) is a better expression of the fact in this case. Likewise, whale(X) doesn't have clear semantics. What is X in this case? Do the whales have personal names, like whale(shamu)? Perhaps. The above discussion is dealing with whales categorically. That is, a whale, in this discussion, is an atomic entity, so would more likely be the argument in your facts, not one of the fact names. If you want to deal with them individually (e.g., answer the question, Is Shamu a whale?) then you would need a rule that identifies whale(X) using facts and rules which eventually lead to questions to the user such as, Is shamu warm blooded?, and then after answers to such questions are asserted, the query whale(shamu) run to see if it succeeds.

Is there a way to annotate the parameter and return value in Prolog?

parent(mel, joan).
parent(jane, betty).
parent(jane, tom).
parent(richard, adam).
parent(richard, rosa).
parent(joan, fran).
For example someone asks me to find all ancestors of a parent. I give him the code:
ancestor(P,C) :- parent(P, C).
ancestor(P,C) :- ancestor(P,P1), parent(P1, C).
But my friend still doesn't know how to use the predicate. Does he call it like
ancestor(richard, C) or ancestor(C, richard) ?
Is there a way to annotate that P is the parameter while C is the return value? And in a complex case, there will be predicates with different names, how should my user know which predicate is the final predicate he wants to use?
To help the human-readable meaning, you could add an extra predicate documenting the parameters as readable name/value pairs:
entry_ancestor_of(ancestor=P, descendent=C) :-
ancestor(P,C).
?- entry_ancestor_of(ancestor=richard, descendent=C).
C = adam .
Above, the suffix *ancestor_of* suggests param 1 is ancestor of param 2, so naming the predicate carefully can make it clearer.
Usually(convention), input parameters are the earlier parameters, and output parameters are later parameters, but where the predicate 'works both ways', ie. either could be input or output, this rule can't hold. This is the case for your predicate:
?- entry_ancestor_of(ancestor=X, descendent=adam).
X = richard .
Either parameter could be input or output, so there is no need to codify/explain them as such, although you might want to comment that it works both ways.
I would usually comment these 'flexible' predicates by putting an example of both of the above usages in a comment next to the predicate.
For entrypoint labelling, just do one or more of the following:
explicitly name the predicate as an entrypoint, as above
document using comments in the code which are the entrypoints
arrange the entrypoints in the same physical section with a comment
block saying that the predicates below are entrypoints.
Edit: Extra things re: coding guidelines / other answers.
In Coding guidelines for Prolog, section 3.8, it says 'For example, mother_of(A, B) is ambiguous;', so I gave bad advice on that.. perhaps acapelli's suggestion would be more useful on that.
In that document, also have a look at:
3.5 Choose sensible names for auxiliary predicates
3.8 Choose predicate names to help show the argument order
3.13 Decide whether predicate names should carry the types on which they operate
4.1 Begin every predicate (except perhaps auxiliary predicates) with an introductory comment in a well-defined format
The '?' system for identifying parameter types that will ness mentioned is on page 21.
a useful convention, sponsored for instance by Markus Triska, builds a predicate functor by joining the parameters 'names' - in a wide, applicable sense. Your example could be
parent_child(mel, joan).
...
ancestor_descendant(P, C) :- parent_child(P, C).
ancestor_descendant(A, D) :- ancestor_descendant(A, I), parent_child(I, D).
Also ISO-Prolog, and - for instance - SWI-Prolog library, attempt to follow this strategy.
For instance
atom_codes(Atom, Codes) :- ...
WRT to declare the type and status of arguments, some Prolog provide declarations - for instance Turbo Prolog, ECLiPSe, others... Sometime such declarations are required - usually to check correctness, often to speed up the computation.
SWI-Prolog offers 'just' structured comments, that IDE process automatically, and there has been a contribution aiming to exploit such declarations with runtime check.
Yes, with comments, and/or meaningful argument names,
% ancestor( ?Ancestor, ?Descendent).
ancestor(P,C) :- parent(P, C).
ancestor(P,C) :- ancestor(P,P1), parent(P1, C).
? means the argument can be used both as input (already set when the call is made), or for output (not yet set when the call is made).
The convention promoted in The Art of Prolog (I think) is that you place the name of the predicate after its first argument, to get at the intended argument ordering: P "is" ancestor C. Presumably "ancestor_of". But if you use that name, someone unfamiliar with that convention might read ancestor_of(P,C) as "ancestor of P is C", so it's a double-edged sword.

In Prolog (SWI), how to build a knowledge base of user supplied pairs and assert to be equal

I am very new to Prolog and trying to learn.
For my program, I would like to have the user provide pairs of strings which are "types of".
For example, user provides at command line the strings "john" and "man". These atoms would be made to be equal, i.e. john(man).
At next prompt, then user provides "man" and "tall", again program asserts these are valid, man(tall).
Then the user could query the program and ask "Is john tall?". Or in Prolog: john(tall) becomes true by transitive property.
I have been able to parse the strings from the user's input and assign them to variables Subject and Object.
I tried a clause (where Subject and Object are different strings):
attribute(Subject, Object) :-
assert(term_to_atom(_ , Subject),
term_to_atom(_ , Object)).
I want to assert the facts that Subject and Object are valid pair. If the user asserts it, then they belong to together. How do I force this equality of the pairs?
What's the best way to go about this?
Questions of this sort have been asked a lot recently (I guess your professors all share notes or something) so a browse through recent history might have been productive for you. This one comes to mind, for instance.
Your code is pretty wide of the mark. This is what you're trying to do:
attribute(Subject, Object) :-
Fact =.. [Object, Subject],
assertz(Fact).
Using it works like this:
?- attribute(man, tall).
true.
?- tall(X).
X = man.
So, here's what you should notice about this code:
We're using =../2, the "univ" operator, to build structures from lists. This is the only way to create a fact from some atoms.
I've swapped subject and object, because doing it the other way is almost certainly not what you want.
The predicate you want is assertz/1 or asserta/1, not assert/2. The a and z on the end just tells Prolog whether you want the fact at the beginning or end of the database.
Based on looking at your code, I think you have a lot of baggage you need to shed to become productive with Prolog.
Prolog predicates do not return values. So assert(term_to_atom(... wasn't even on the right track, because you seemed to think that term_to_atom would "return" a value and it would get substituted into the assert call like in a functional or imperative language. Prolog just plain works completely differently from that.
I'm not sure why you have an empty variable in your term_to_atom predicates. I think you did that to satisfy the predicate's arity, but this predicate is pretty useless unless you have one ground term and one variable.
There is an assert/2, but it doesn't do what you want. It should be clear why assert normally only takes one argument.
Prolog facts should look like property(subject...). It is not easy to construct facts and then query them, which is what you'd have to do using man(tall). What you want to say is that there is a property, being tall, and man satisfies it.
I would strongly recommend you back up and go through some basic Prolog tutorials at this point. If you try to press forward you're only going to get more lost.
Edit: In response to your comment, I'm not sure how general you want to go. In the basic case where you're dealing with a 4-item list with [is,a] in the middle, this is sufficient:
build_fact([Subject,is,a,Object], is_a(Subject, Object)).
If you want to isolate the first and last and create the fact, you have to use univ again:
build_fact([Subject|Rest], Fact) :-
append(PredicateAtoms, [Object], Rest),
atomic_list_concat(PredicateAtoms, '_', Predicate),
Fact =.. [Predicate, Subject, Object].
Not sure if you want to live with the articles ("a", "the") that will wind up on the end though:
?- build_fact([john,could,be,a,man], Fact).
Fact = could_be_a(john, man)
Don't do variable fact heads. Prolog works best when the set of term names is fixed. Instead, make a generic place for storing properties using predefined, static term name, e.g.:
is_a(john, man).
property(man, tall).
property(john, thin).
(think SQL tables in a normal form). Then you can use simple assertz/1 to update the database:
add_property(X, Y) :- assertz(property(X, Y)).

Resources