Prolog and sibling relationship? - prolog

I'm new to Prolog and having a bit of difficulty. I have:
man(ken).
man(tom).
woman(juli).
father(ken, tom).
father(ken, juli).
male(A) :- man(A).
brother(A,B) :- male(A), father(C,A), father(C,B), (A \= B).
I know the male/man is redundant, but it's part of the assignment. Anyway, when I try something like:
|?- brother(tom, juli).
I get "no" as the response. I'm sure I've made a stupid, simple mistake, but my lack of understanding is making it very hard to find. Can anyone see what my problem is?

When you enter:
|?- brother(tom, juli).
You'll see a response something like this (SWI Prolog):
true ? ;
no
| ?-
So it first responds with "true" (gives a match) and then, after you enter ; to show more solutions, it says "no" to indicate there are no further solutions. Some prolog interpreters may say "no" or "false" in this case, with the same meaning. This response from the prolog interpreters initially throws many a new prolog user.
You could, alternatively, press "enter" which just means you're done and don't want to see any further solutions:
true ?
yes
| ?-
Then you get "yes".

Related

Prolog singleton variables in rule head causes program to output booleans for all queries

I have this prolog program.
red(rose).
red(anthurium).
white(rose).
white(gardenia).
white(jasmine).
like(Y,X) :-
red(X),!,
fail
;
white(X).
And below is how it responds to different queries.
?- like(rose,gardenia).
true.
?- like(rose,P).
false.
?- like(Val,anthurium).
false.
?- like(rose,X).
false
The problem I now have is this:
When querying with a variable within the query (Eg: ?- like(rose,X).), Prolog usually responds by returning a value, (something like X=some_val). Why I don't get any value for those variables, but either true or false?
All helpful answers are highly appreciated. Thanks in advance.
Think about what Prolog is doing here:
like(rose,P) succeeds if red(P), so it grabs a possible substitution for P, namely rose or anthurium. Then it traverses the cut and then it fails. But "failing" means that the proof search down that path didn't bring any solution, there are no successful bindings to report (the only fail to get information out of a failing branch is to side-effect to a log file and read check it later). In fact, all bindings will be undone on backtracking. The second branch is white(X), but rose is not white, so we fail here, too.
You can also write:
like(_,X) :- \+ red(X).
like(_,X) :- white(X).
which is a bit more readable. One notices that when calling like(_,X), the goal enclosed by the negation-as-failure operator \+ is nonground. This is bad, and causes a floundering query (in other words, don't do that). I have written this little page on "floundering".

When does Prolog prompts 'yes' and when does it says 'true'

I wrote the following knowledge base in Prolog:
likes(yamini,chocolate).
likes(anuj,apple).
likes(yamini,book).
likes(john,book).
likes(john,france).
Now, when I consult the above file and try the following commands:
| ?- likes(anuj,apple).
(1 ms) yes
| ?- likes(yamini,chocolate).
true ? ;
no
I want to understand when does Prolog replies a 'yes' versus when does it replies 'true'.
That output depends on the toplevel you are using. It seems you are using GProlog. It will output yes when the query succeeds and there are no choice points left (no other possible solutions).
And it will answer true when the query succeeds but there are still other possible solutions to be checked.
This is an artefact of the toplevel (Prolog command line) implementation. Apparently you implementation says true when it could prove a goal and it is unsure whether there may be more solutions. If it is sure that there is only one solution, it says yes.
Here is what SWI-Prolog does:
?- likes(anuj,apple).
true.
Prolog could successfully prove the goal likes(anuj,apple) and it is also sure there are no other ways to prove it otherwise one would see something like this:
?- member(X,[1,2]).
X = 1 ;
X = 2.
where an X that makes the goal true has been found as 1 but there may be other solutions. And indeed there are, namely 2.
Back to our example:
?- likes(yamini,chocolate).
true.

Pattern-matching: query returns 'no' even when base case provided

I have a simple Prolog-program that I need some help debugging.
The point is to extend the program by pattern-matching to create a proof checker for propositional logic. The problem I have is that I get no when I expect yes and my 'fix' (providing a base case for valid_proof_aux) still gives me two solutions and I don't know why.
Not sure how to go about debugging Prolog yet, sorry.
%call:
valid_proof([p],p,[[1, p, premise]])
%src:
reverse_it([],Z,Z).
reverse_it([H|T],Z,Acc) :- reverse_it(T,Z,[H|Acc]).
valid_proof(Prems,Goal,Proof):-
last(Proof, [_, Goal, _]),
reverse_it(Proof, RevP, []),
valid_proof_aux(Prems, RevP) .
valid_proof_aux(Prems,
[[_,Prop,premise] | T]):-
memberchk(Prop,Prems),
valid_proof_aux(Prems,T).
%my 'fix'
valid_proof_aux(_, []) :- true .
You don't really show how to run the program and what exactly you get (you should edit your question with and add this), so this answer is a bit of a guess, but anyway:
You need the base case either way (as you observe yourself), valid_proof_aux/2 would fail when the list becomes empty [] and does not match [[...]|T] anymore.
?- [] = [_|_]. % try to unify an empty list with a non-empty list
false.
What you need to do to get rid of the choice point is to put the list argument as the first argument.
valid_proof_aux([], _).
valid_proof_aux([[_,Prop,premise]|T], Prems) :-
memberchk(Prop, Prems),
valid_proof_aux(T, Prems).
Note that you don't need the :- true., this is implicit. Also, avoid leaving any blanks on the two sides of the | in [Head|Tail].

False value returned in Prolog?

sitting(mary, james).
sitting(rosie, andrew).
sitting(kiera, tom).
issitting(X, Y) :- sitting(X, Y).
Hey guys, I basically want to check who the true or false values of who is sitting next to who,
When I type in the compiler
issitting(rosie, andrew).
A true value is returned, however, when I type
issitting(andrew, rosie).
A false value is returned (Which should be true because they are sitting next to each other). I don't want to add three extra lines of code should the user check for who is sitting next to each other (with all possible combinations).
How would you alter the rule to get Prolog to understand that if the user switches the names around, they're still true (NOT false).
I don't understand why it's giving me 'false' .
I'm stuck and this is the best I could get done so far :/
Thank you.
(I could just point out the problem, but then you would not learn anything. I assume you are using SWI, since you say that false is returned.)
?- issitting(andrew, rosie).
false.
Let me restate what your problem is: You are expecting that issitting(andrew, rosie) is true. But it is not. What would you do if you asked that question to a person? Probably you would ask why? Why isn't andrew sitting next to rosie? And, say, you did not understand the explanations, you might have asked another question:
Is andrew at least sitting next to anyone?
So this question is a generalization of the original question. In Prolog, we can do the very same thing with the help of variables like so:
?- issitting(andrew, Anyone).
false.
So now we know that andrew issitting next to nobody? Confused? Well, we can generalize the query once again:
Is there at least one person sitting next to anyone?
?- issitting(Person, Anyone).
Person = mary, Anyone = james
; Person = rosie, Anyone = andrew
; Person = kiera, Anyone = tom.
So there are some persons around. Effectively, the reason is that you have sitting/2 and another relation issitting/2. You need to generalize issitting/2 by adding the following rule:
issitting(X, Y) :- sitting(Y, X).
But the point was to show you a good general debugging strategy:
In case of unexpected failure, try to generalize your query (and your program).

SWI-Prolog How Prolog handles logical comparisons

I have written the following code in SWI-Prolog:
:- dynamic state_a/1 .
:- dynamic state_b/1 .
:- dynamic state_c/1 .
state_a([1,2,3,4,5,0]).
state_b([0]).
chop(LIST,HEAD,TAIL) :- LIST=[HEAD|TAIL].
move_ab :- !,state_a(X),
chop(X,Ha,Ba),
Ha>0,
state_b(Y),
chop(Y,Hb,Bb),!,
(Ha<Hb ; Hb =:= 0),
asserta(state_a(Ba)),asserta(state_b([Ha|Y])),
retract(state_a(X)), retract(state_b(Y));
write('Wrong Move.Choose Another').
There are 2 OR(;) in my code. When I ask move_ab in Prolog for the first time all the conditions before the second OR are true so i get the answer true from Prolog.
But the second time I ask move_ab in Prolog I get just the answer false.
I don't know how this can happen. Some of the conditions before the second OR are not true so Prolog should check the condition after the second OR and write me the message Wrong Move.Choose Another..
I tried using () to group the conditions but I still get the same message.
Any idea about what is going on? By the way I am a newb in Prolog, just started 2 days ago :)
The problem lies in the use of cut (!/0) before the conditions are properly tested. Cut removes choice points. Here it means that the choices are removed before you even test anything. So if the tests fail, everything fails !
BTW, manipulating the database is maybe not the best idea there. To represent states, you could use global variables as follows :
:- nb_setval(state_a, [1,2,3,4,5,0]).
:- nb_setval(state_b, [0]).
move_ab :-
nb_getval(state_a, [Ha|Ta]),
Ha > 0,
nb_getval(state_b, [Hb|Tb]),
(Ha < Hb ; Hb =:= 0),
nb_setval(state_a, Ta),
nb_setval(state_b, [Ha, Hb|Tb]),
!
;
write('Wrong Move.Choose Another').
A general advice given to beginners in prolog is to stay away from database manipulation if possible, as often problems are solvable without it. Here though it could be justified, but global variables will be faster and easier to manipulate.

Resources