Prolog not returning expected values - prolog

I'm trying to get comfortable with Prolog (SWI Prolog specifically).
I have this very simple listing:
animal(bear).
animal(mouse).
animal(bird).
Now whenever I ask for all atoms that fulfill (what is the correct expression?) the predicate
animal I always get only the first one.
?- animal(X).
X = bear .
Though all three atoms evaluate to 'true' for animal.
?- animal(mouse).
true.
?- animal(bird).
true.
What am I doing wrong? Is this behavior controllable via some setting?

There is nothing wrong in your code. Prolog is a reasoning machine. So it tries to find the first solution that will satisfy all the variables.
Once the solution is found it prints it out.
Now if you need additional solution there should be some combination that you should enter so that prolog will continue searching.
If I remember correctly it might be a semicolon...
Hope this helps

Related

What am I missing about equality and unification in Prolog?

I'm working through Clocksin and Mellish to try and finally go beyond just dabbling in Prolog. FWIW, I'm running SWI-Prolog:
SWI-Prolog version 7.2.3 for x86_64-linux
Anyway, I implemented a diff/2 predicate as part of exercise 1.4. The predicate is very simple:
diff(X,Y) :- X \== Y.
And it works when used in the sister_of predicate, like this:
sister_of(X,Y) :-
female(X),
diff(X,Y),
parents(X, Mum, Dad ),
parents(Y, Mum, Dad ).
in that, assuming the necessary additional facts, doing this:
?- sister_of(alice,alice).
returns false as expected. But here's the rub. If I do this instead:
?- sister_of(alice, Who).
(again, given the additional facts necessary)
I get
Who = edward ;
Who = alice;
false
Even though, as already shown, the sister_of predicate does not treat alice as her own sister.
On the other hand, if I use the SWI provided dif/2 predicate, then everything works the way I would naively expect.
Can anyone explain why this is happening this way, and why my diff implementation doesn't work the way I'm expecting, in the case where I ask for additional unifications from that query?
The entire source file I'm working with can be found here
Any help is much appreciated.
As you note, the problem stems from the interplay between equality (or rather, inequality) and unification. Observe that in your definition of sister_of, you first find a candidate value for X, then try to constrain Y to be different, but Y is still an uninstantiated logic variable and the check is always going to succeed, like diff(alice, Y) will. The following constraints, including the last one that gives a concrete value to Y, come too late.
In general, what you need to do is ensure that by the time you get to the inequality check all variables are instantiated. Negation is a non-logical feature of Prolog and therefore potentially dangerous, but checking whether two ground terms are not equal is safe.

natural_number(1) -> false. Problems with s/1 predicate

I'm using swi-prolog. I'm simply trying to follow the examples in the book "the art of prolog", but I'm not getting the correct results. I'm afraid this might be due to the s/1 predicate. I can't even find s/1 in the documentation for swipl, the only predicate that is similar is succ/2: http://www.swi-prolog.org/pldoc/man?predicate=succ/2 This can't be used the same way as s/1. I'd much prefer to have the s predicate.
This is the program for determining whether a number is a natural number:
natural_number(0).
natural_number(s(X)) :- natural_number(X).
However, natural_number(1) for example yields false. What's the problem here?

Prolog - resolution

I am doing resolution proof in formal logic using truth table and prolog program outcome of my experiments are different and I want to know why.
Here is the problem in plain english:
1. If someone looks into eyes of fighter, he is going to get angry.
2. If the fighter gets angry, he is going to punch.
If the fighter punched, did someone look into fighter's eyes?
'Fighter punched' is conclusion, and we know when conclusion is true the premise could be either false or true, therefore we can't answer the question.
However, following SWI prolog program returns true:
eyes:-angry.
angry:-punch.
punch.
?-eyes.
True
Also
aggregate_all(count, (eyes), Count)
1
Can somebody explain this?
Remember that :- in Prolog is supposed to look like an arrow — an arrow from right to left, like <==. (We do not actually use an arrow, so that users can freely define a custom operator and use it for their own purpose without interfering with regular Prolog code.)
Thus, all your arrows point in the wrong direction. You probably meant:
angry(true) :- eyes(true).
punch(true) :- angry(true).
I am introducing a Boolean argument for these predicates so that you can play with different parameters without worrying about (non)existence of any predicates.
For example, if you add to these clauses:
eyes(true).
Then you get:
?- punch(T).
T = true.
However, if you instead add:
eyes(false).
then you get:
?- punch(T).
false.
This shows that yes, someone must have looked the person in the eye.

Prolog Backtracking On Finding A Solution And Returning False

I'm taking a crack at Prolog (using SWI-Prolog) and everything works like I want it to, i.e., the logic is calculated correctly and it finds the right solutions but the whole backtracking thing is screwing with me.
Here's the code:
tall(X) :- skinny(X) ; eatless(X).
eatless(X) :- playsmore(X).
playsmore(X) :- hasxbox(X) ; hasplaystation(X).
skinny(a).
vegetarian(a).
hasxbox(b).
eatsburger(c).
hasplaystation(d).
list_all_tall :- forall(tall(Tall), writeln(Tall)).
Very basic stuff. Here's what I get as a result of my queries:
?- tall(a).
true ; % Note 1
false.
?- tall(b).
true ; % Note 2
false.
?- tall(c).
false.
?- tall(d).
true.
As you can see from Notes 1 and 2, it waits for me to hit ; to move on and then considers the first solution as null and eventually outputs false.
I can use cuts to control this behavior better but I also want the following commands to work properly:
?- tall(X).
X = a ;
X = b ;
X = d.
And:
?- list_all_tall.
a
b
d
true.
These two commands give the solution exactly the way I want. Its just the ones for Notes 1 and 2 that are driving me up the wall. Is there a way that I can keep the functionality as it is right now for tall(X). and list_all_tall., while fixing the functionality of tall(a). and tall(b). to my liking, i.e., the program should exit with a true. after I ask tall(a). or tall(b).
I'd appreciated it if instead of giving straight answers someone could actually explain how I could go about fixing it myself because maybe my way of thinking in Prolog is all bassackwards.
PS: No offense intended to tall, skinny, fat, burger eating, video game playing, vegetarian folks.
Just to supplement Daniel's well-explained answer (+1) for your specific case, consider:
tall(a).
Prolog will look at the first match, which is through:
tall(X) :- skinny(X) ; eatless(X).
This will succeed because skinny(a) will succeed. However, there's a disjunction ; leaving a choice point for Prolog that it hasn't explored yet. Because skinny(a) succeeds and the choice point is pending, you get true but prompted to seek more. Prolog then backtracks to the choice point and tries to satisfy eatless(a) but fails. Thus, you get:
?- tall(a).
true ; % because `skinny(a)` succeeded
false. % because `eatless(a)` failed
Taking another example:
tall(d).
Again, this matches the tall/1 predicate, but this time, skinny(d) fails and prolog moves right on (due to the disjunction) to eatless(d) which succeeds. However, there are no more choice points after that success, so you get:
?- tall(d).
true. % There were no choice points available after success
The best thing to do is not worry about it, because you're not always going to be able to prevent it.
Prolog doesn't ever know that there will be another answer. It just knows that there may be another answer. This is called a choice point. Whenever Prolog reaches an alternative, it creates a choice point and then follows the first option. If that option doesn't work out, it backs up to the most recent choice point and tries the next alternative. If it runs out of alternatives without finding an answer, you get no or false.
You can try to write your code so that you don't get a choice point if you know there are no more items. member/2, for instance, in some Prologs you get false after the last item and in others you do not. But it isn't a composition problem to have a dud choice point after all your solutions. Your user interface probably won't show users Prolog's prompts directly. You can use setof/3 and the other extralogical predicates to get all the solutions. The false won't "leak" out into the world. It's a little unnerving at first, but just trust it and don't worry too much about it.
It is possible to run the same predicate, tall/1 in this case, in different modes based on different instantiation patterns.
When you run ?- tall(a). you instantiate the argument (i.e., X=a) and you want to receive either true or false (and no choicepoints, indicated by ;).
In Prolog this mode is called semi-deterministic.
You can force your predicate to be semi-deterministic for this specific instantiation pattern in the following way:
tall(X):- (ground(X) -> once(tall0(X)) ; tall0(X)).
Here ground(X) succeeds just in case X is fully instantiated.
Fully instantiated means that it is not a variable nor is it a compound term containing a variable.
tall0(X) is your original predicate.
The second mode you want to use is ?- tall(X).
Here you expect all results to be given subsequently, using ;.
This mode is called non-deterministic in Prolog.
The complete code for your example is:
tall(X):- (ground(X) -> once(tall0(X)) ; tall0(X)).
tall0(X):- skinny(X) ; eatless(X).
eatless(X):- playsmore(X).
playsmore(X):- hasxbox(X) ; hasplaystation(X).
skinny(a).
hasxbox(b).
hasplaystation(d).
Now the single predicate tall/1 can be called in the two modes, producing the behavior you want. Semi-deterministic usage:
?- tall(a).
true.
Non-deterministic usage:
?- tall(X).
X = a ;
X = b ;
X = d.
Hope this helps!

Make Prolog return one solution and stop showing the query option

I'm new to prolog, and am experimenting with how to get it to stop querying after it finds one answer. I'm using this code:
member1(L,[L|_]).
member1(L,[_|RS]) :- member1(L,RS),!.
The result is:
| ?- member1(3,[3,2,3]).
true ? a
yes
I'm lost as to how I could get Prolog to stop printing "true ?" and just print "yes" instead. I've tried using if/else construct and the format function but it still prints "true ?". Any ideas?
You're cutting the wrong place. Cut after the base condition, which says, "once the base is met, don't backtrack any more":
member1(L,[L|_]) :- !.
member1(L,[_|RS]) :- member1(L,RS).
If-then does work for me, perhaps you implemented it different? (on swi-prolog)
member1(X,[Y|RS]) :-
( X = Y -> true
; member1(X,RS) -> true
; false
) .
Swi also has the predicate once/1.
edited to account for the error pointed out by false.
From the output you show, I assume you are using GNU Prolog. But, first just an important remark:
The cut you placed does not cut as you intend it! In fact, it does not even prevent that there is a single answer. Here is evidence for that:
| ?- member1(X,[1,2,3]).
X = 1 ? ;
X = 2
yes
So you still have two answers. As a rule of thumb: a cut after a recursive goal often does some unexpected things.
If you insist to have exactly the first answer, simply say once(member(X,[1,2,3])). The once/1 is effectively a cut, too, but quite in disguise. It is tamed to do exactly one thing. Yes, you can place also cuts into recursive rules, but for a beginner, better leave that to a later lesson.
Behind all this there is another point, which is less visible: The toplevel shell of GNU Prolog will ask you for further solutions if it sees an open alternative (jargon: choicepoint). So when GNU asks you for more, it knows that some part has yet to be explored, but there is no guarantee, that there is actually another answer:
?- member(1-X,[1-a,2-b,3-c]).
X = a ? ;
no
Here, the toplevel sees an open choicepoint and thus asks if you want to explore the query any further. Alas, this search is in vein...

Resources