Prolog beginner, member/2 builtin predicate - prolog

I have this:
someuserdef(a,[b,c,d]).
When I try
?- someuserdef(a,L),member(b,L).
I don't get a true or false answer but the list
L=[b,c,d] ;
false.
How do I get just a true or false answer?

You're asking Prolog to give you a value of L that matches both rules. If it can tell that there's only one answer, it will return yes - otherwise it will give you the first answer, return no, and prompt you before checking for any more answers.
When you're providing variables (capital letters) to Prolog queries, it will return matches - it's when you ask it to check rules (with no variables) e.g. someuserdef(b, [b, c, d]) that it will return yes or no to indicate whether your assertion is true or false.

Related

How to create predicate that is true if gets different values

I would like to ask how to create predicate that returns true if gets different values.
I have this database:
fruit(apple).
fruit(peach).
fruit(banana).
fruit(orange).
fruit(mandarine).
fruit(plum).
I need predicate threeFruits/3 that takes three fruits and says if they are different i.e.
threeFruits(apple,peach,banana). -> true
threeFruits(apple,apple,banana). -> false .. etc.
The code I have so far is not correct:
threeFruits(X,Y,Z):- fruit(X),fruit(Y),fruit(Z).
I tried also unification, but it can tell me only if they are same, but not working for different.
threeFruits(fruit(X),fruit(X),fruit(X)).
Thank you in advance for any hint.
Assuming the X, Y, Z are really atoms for which fruit/1 is valid, you can test whether they pairwise "do not unify" by using the negation of =/2 (i.e. the negation of unification)
threeFruits(X,Y,Z) :-
assertion(fruit(X)),
assertion(fruit(Y)),
assertion(fruit(Z)),
X\=Y,Y\=Z,X\=Z.
Alternatively, you can use the negation of ==/2 to check whether they pairwise "are not the same":
threeFruits(X,Y,Z) :-
assertion(fruit(X)),
assertion(fruit(Y)),
assertion(fruit(Z)),
X\==Y,Y\==Z,X\==Z.

Prolog: Assign value to Variable in Predicate

With the following rules:
test('John', ebola).
test('John', covid).
test('Maria', covid).
How can I create a predicate that would tell me if John or Maria took (both) the Ebola and Covid tests?
I want to do something similar to this (I know it's wrong, just the idea):
tests(Persona, Ebola, Covid) :-
Ebola = test(Persona, ebola),
Covid = test(Persona, covid).
Prolog is relational not functional. test(X, Y) either holds or fails and doesn't return a value like what you thought. Here's what you should have written:
tests(Persona) :-
test(Persona, ebola),
test(Persona, covid).
You can query tests('John') which is true since both test/2 calls succeeds. The query tests('Maria') fails because test('Maria', ebola) fails.
Does it answer your question ?

Learn Prolog now: Why answering true to the first query of exercise 1.5?

I have just started learning Prolog, and I'm wondering about the first question of this exercise.
%% Suppose we are working with the following knowledge base:
wizard(ron).
hasWand(harry).
quidditchPlayer(harry).
wizard(X) :- hasBroom(X), hasWand(X).
hasBroom(X) :- quidditchPlayer(X).
How does Prolog respond to the following queries?
wizard(ron). -> true
witch(ron). -> undefined procedure
wizard(hermione). -> false
witch(hermione). -> undefined procedure
wizard(harry). -> true
wizard(Y). -> Y = ron ; Y = harry.
witch(Y). -> undefined procedure
Using swipl on Ubuntu, importing the knowledge base for this exercise, first of course trying to decipher what Prolog will returns, and finally checking by myself.
Ok pretty boring stuff until now, I have seen a few answer to these exercises over Github (here, here and there), and I don't understand the answer to the first one: %% 1. wizard(ron). -> true.
First of all the interpreter is complaining about the two definition of what is a wizard:
Warning: /tmp/prolog/ex15.pl:4:
Clauses of wizard/1 are not together in the source-file
Earlier definition at /tmp/prolog/ex15.pl:1
Current predicate: quidditchPlayer/1
Use :- discontiguous wizard/1. to suppress this message
Secondly, when querying I obtain:
?- wizard(ron).
true ;
false.
The way I get it, first Prolog returns the first fact from the knowledge base, then apply the rule head and find out that ron has neither a broom nor a wand.
All this leading to my question: what subtlety have I missed that makes others writing true as an answer to this query?
what subtlety have I missed that makes others writing true as an answer to this query?
`?- wizard(ron).`
true;
false
You have the clause (fact) wizard(ron). in your KB.
To make the things clearer you can write the fact also as the rule clause:
wizard(ron) :- true.
As you can see this is pretty redundant notation but useful in some cases as the general fact representation.
So your query can be interpreted as follows:
Is there an wizard called ron?
Since you have the fact wizard(ron) :- true.
Prolog will first unify the goal and the head.
In your case unify is trivial comparison because no variables are in the goal and the head.
Then Prolog tries to prove body. The body is builtin predicate true, so you quickly get the answer - true.
Then pressing ';' you initiate the search for the alternative solution.
Since no (more) solutions exist for the query wizard(ron), Prolog writes false.
The dot operator designates the clause end. So you wrongly typed dots in your examples:
-> operator means if-then-else relation. It can be used within clause body.
For example you can write std_member/2 as if_member/2
std_member(X, [ X | _ ]).
std_member(X, [ _ | Xs ]) :-
std_member(X, [ _ | Xs).
if_member(X, [ Y | Xs ]) :-
X = Y -> true;
if_member( X, Xs ).

Prolog programm returns yes instead of value

I got the following event: item(C,X,G,P), (where C is a number for the product,X it's name,G it's price,P it's cost).
When i use the command item(n3001,_,_,P) directly on the prolog console i get as answer
G = 1.25 X = 100 but when i write the equation p3(C)-: item(C,_,_,P). then i consult the text i get as answer yes.
My question clarified is how come the one time i get the value of P which i want and the other time i get whether it's true or false?
There are no return values in Prolog and p3/1 does not constitute a function but a relation. Your definition
p3(C) :-
item(C,_,_,P).
reads: If item(C,_,_,P) succeeds then p3(C) succeeds as well. For the sake of argument, let's assume that your code includes the following fact:
item(n3001,100,1.25,1).
If you query
?- p3(n3001).
Prolog unifies C in the head of your rule with n3001 and then tries your goal item(C,_,_,P) which succeeds. Hence the rule succeeds and Prolog tells you:
?- p3(n3001).
yes
If you want to know the price corresponding to n3001 you have to to define a rule where P appears in the head of the rule as well, e.g.:
p3(C,P) :-
item(C,_,_,P).
If you query that you'll get to see the value of P corresponding to n3001:
?- p3(n3001,P).
P = 1
If you query item/4 directly P appears in the arguments and therefore you get to see a substitution for it that satisfies your query:
?- item(n3001,_,_,P).
P = 1

Prolog ~ Resolution involving the negation of some other statement?

I have the following code, where I define is_max as the negation of is_below.
rank(mary,1).
rank(juan,2).
rank(john,3).
rank(jane,4).
is_below(X) :- rank(X,A), rank(Y,B), A<B .
is_max(X) :- not(is_below(X)) .
is_below is true if X is below someone in terms of rank. Therefore the person with the highest/max rank is someone for whom is_below is false (accordingly, is_max is defined).
When I query
is_max(jane) .
This is true (the above is false for mary, juan, and john)
However, when I query
is_max(X) .
This is false. I was expecting it to return jane. My logic seems to be fine, so I am not sure why I don't get jane. Any insight would be really appreciated!
Prolog has negation as failure. Think of it as 'not provable'.
is_max(X) would be true if is_below(X) would always be false. is_below(X) is true for X=mary, so is_below(X) is provable, and is_max(X) is false.
Because of this it's better to use notation \+ instead of not, to remind yourself that it's not true not.
A possible way to fix your code is to explicitly instantiate X:
is_max(X) :- rank(X,_), \+ is_below(X).

Resources