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

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.

Related

Which way to store facts, apple vs exists(apple) is more idiomatic?

I am trying to develop a "simplest" prolog program.
Method 1
Conceptually, the program creates a set of facts which are stored in the database, to be queried later.
% simple facts
apple.
banana.
orange.
cherry.
The database can be queried as expected.
?- apple.
true
?- mango.
procedure `mango' does not exist
Method 2
Most textbooks which teach prolog would start such a "simplest" program using predicates, something like:
% simple facts
exists(apple).
exists(banana).
exists(orange).
exists(cherry).
The queries would then change in nature to testing whether the predicate can be satisfied, eg:
?- exists(apple).
true
?- exists(mango).
false
Question:
Is Method 1 an incorrect use of prolog? If so, why?
In my understanding, prolog is testing whether queries can be shown to be true, and to do this the database is searched. My doubt is raised by the error "procedure `mango' does not exist".
I think you are focusing on a distinction between "facts" and "predicates" which does not really exist; apple. is apple(). a predicate with no body and no arguments. The following shape:
name(argument1, argument2) :-
n2(arg3),
n3(arg4).
says that "name holds for the given arguments if n2 and n3 hold for their arguments", i.e. name only holds in certain conditions. Take the conditions away and you get:
name(argument1, argument2).
Now there are no conditions where it can fail, so it says "name holds for the given arguments". It always holds, it's like an unchanging fact, but "fact" is not a different kind of thing in Prolog, it's still a term with a functor and arity which can be called, it's just that the body of code to check is effectively true and nothing else.
Take the arguments away and you get:
name.
"name holds". It's similar to name()., no arguments.
The way Prolog is implemented, these are close to functions, procedures, subroutines in other languages - they are not the same, but Prolog looks through your code for one with a matching name (functor) and matching number of arguments (similar to method overload resolution in other languages), and calls it with the given arguments and sees whether it holds or not. If it cannot find a matching name and number of arguments, you get the "procedure does not exist" error.
In typical Prolog usage, the style name(argument1, argument2) is used so that "name" tries to describe a logical relation between the arguments, and the arguments are the data being related. e.g. length(List, Quantity) tries to explain that List is related to Quantity through the relation of length.
With method 2 you can extend it to:
exists(apple).
exists(crabapple).
exists(concrete).
food(apple).
food(crabapple).
food(snozzcumber).
edible(apple).
edible(snozzcumber).
and then ask for all things which exist, all foods, all edible things, or combinations like foods which are fictional and edible, things which exist but are inedible, etc. With method 1 you can say that apple holds, but you can't easily use it as data, can't easily query for all things which exist, can't easily change the code to describe that apple exists and is edible. With method 2 you can ask ?- exists(X). and have Prolog fill in X and tell you that apple exists. You can't easily do that with method 1.
If you put the data in place of the name (functor) that's like storing food by using an empty text file named 'apple.txt' and an empty text file named 'banana.txt' and so on, instead of putting them in a single file exists.txt. It's not a syntax or logical error to do this, if there is a reason you want to do it like that then you can, so it's hard to call it strictly "incorrect". Also like using a SQL database and making a table 'apple' and a table 'banana' and so on, instead of putting them in a table 'fruit'. Like having a bookshelf with a book named 'apple' and a book named 'banana' and so on, instead of one book named 'Fruits of the World'. You can do that, it's not incorrect to name a book "apple", but it's not a good way to use books to store lists of fruit.
If you specifically want something for codegolf where shortness trumps all other concerns then yes, fine. But it is going against the grain, against the normal use, it limits what you can do and it's not how Prolog was built to be used. It's also hard to describe something with fewer characters as "simpler" if it means a weird, limited, non-standard way of doing things.
The predicate exists/1 exists, the predicate apple/0 exists, the predicate mango/0 does not exist.
The query exists(apple). successfully reports true ("succeeds" in the Prolog vernacular), the query exists(mango). successfully reports false ("fails" to be proven, in the vernacular), the query apple. successfully reports true and the query mango. fails to execute because the predicate mango/0 does not exist.
So we can say that apple "exists", mango does not "exist", apple/0 exists, but mango/0 does not exist.
However, (in SWI Prolog),
11 ?- mango.
ERROR: toplevel: Undefined procedure: mango/0 (DWIM could not correct goal)
12 ?- [user].
:- dynamic(mango/0).
|: ^Z
true.
13 ?- mango.
false.
So you can work with your 1st method too, if you declare all the predicates of interest as dynamic.

Prolog array in rules and operation

I have a little problem with define facts and search in array in Prolog. I dont know, how add to rule my array and result of it.
Ok, need some like this:
% John is allergic to fish and milk.
isAllergic(john, [fish, milk]).
% food shark has allergen fish and john cant eat it and drink milk
allergen(shark, fish).
allergen(milk, milk).
%I need list of food, what person (john) can eat.
foodForPerson(F,C):- isAllergic(F, X), allergen(X,C).
And then I call FoodForPerson(john,X), but result is false. I think, that problem is in array.
Result should be X=milk, X=shark.
You are missing a member/2 call to get an element out of an array:
foodForPerson(F,C) :-
isAllergic(F, Xs),
members(X,Xs),
allergen(X,C).
Although a better way to represent this is using facts, instead of lists, thus:
isAllergic(john, fish).
isAllergic(john, milk).
In that case your proposed predicate would have worked. And furthermore it's easy to assert and retract single facts. Or combine different libariries how each know something about John.
Edit
In case you wish to use a list for allergen as well, you can make use of member twice:
isAllergic(john, [fish, milk]).
allergen(sharkWitHPotato, [fish, potato]).
foodForPerson(F,X) :-
isAllergic(F, As),
allergen(X,Cs),
member(A,As),
member(A,Cs).
Note that in your comment, you swapped the arguments of allergen I guess?
But this can result in listing the same tuple john,sharkWitHPotato multiple times.

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

Using And clause in HEAD of a prolog statement

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.

Resources