i have two implementation of Prolog , the Function is to decide if the given number is odd or even
the first one works correctly
even1(0).
even1(X) :- X>0 ,X1 is X-1, odd1(X1).
odd1(1).
odd1(X) :- X>1 , X1 is X-1, even1(X1).
even1(2) returns true
but the second one doesnt work correctly
even2(0).
even2(X) :- X>0 , odd2(X-1).
odd2(1).
odd2(X) :- X>1 , even2(X-1).
even2(2) returns false
can anyone explain to me whats is the difference between the two of them ?
Prolog is a relational language, not a functional language. Thus, when you call odd2(X-1), the predicate argument, X-1, is not evaluated as an expression but interpreted as a compound term:
?- functor(X-1, Name, Arity).
Name = (-),
Arity = 2.
You can check what happens when Prolog proves a query by using your system trace functionality:
?- trace.
true.
[trace] ?- even2(2).
Call: (8) even2(2) ? creep
Call: (9) 2>0 ? creep
Exit: (9) 2>0 ? creep
Call: (9) odd2(2-1) ? creep
Call: (10) 2-1>0 ? creep
Exit: (10) 2-1>0 ? creep
Call: (10) even2(2-1-1) ? creep
Call: (11) 2-1-1>0 ? creep
Fail: (11) 2-1-1>0 ? creep
Fail: (10) even2(2-1-1) ? creep
Fail: (9) odd2(2-1) ? creep
Fail: (8) even2(2) ? creep
false.
Note that the expression 2-1-1 evaluates to zero but, being a compound term, the call even2(2-1-1) doesn't unify with your base case for the predicate, even2(0):
?- even2(2-1-1) = even2(0).
false.
?- 2-1-1 = 0.
false.
Therefore, Prolog tries the second clause and the call eventually fails the X>0 check. Note that >/2, by being an arithmetic comparison predicate, it does evaluate its arguments prior to the actual comparison.
Related
I made a pretty basic predicate to explain my problem, so don't mind it's uselessness. I want the predicate to fail if an empty list is passed as the B argument,
predicate(_,[],_) :- fail.
predicate(A,B,C) :-
write(A),
writeln(B),
C = true.
But when I enter this query:
?- predicate(test,[],X).
Instead of returning false(since it's supposed to fail), it execute the predicate and the output is:
test[]
X = true.
Why won't the predicate fail even if B is an empty list?
In fact, the first clause fails for the query ?- predicate(test,[],X).. However, when the first clause fails, the second clause is trigged and produces the observed output. To check that, you can use predicate trace/0:
?- trace, predicate(test,[],X).
Call: (11) predicate(test, [], _26304) ? creep % <= try first clause
Call: (12) fail ? creep
Fail: (12) fail ? creep
Redo: (11) predicate(test, [], _26304) ? creep % <= try second clause
Call: (12) write(test) ? creep
test
Exit: (12) write(test) ? creep
Call: (12) writeln([]) ? creep
[]
Exit: (12) writeln([]) ? creep
Call: (12) _26304=true ? creep
Exit: (12) true=true ? creep
Exit: (11) predicate(test, [], true) ? creep
X = true.
If you want that predicate/3 fails when called with []as second argument, then you can define that predicate as follows:
predicate(A, B, C) :-
B \= [], % this condition forces failure when B is the empty list
write(A),
writeln(B),
C = true.
Examples:
[trace] ?- predicate(test,[],X).
Call: (10) predicate(test, [], _28066) ? creep
Call: (11) []\=[] ? creep
Fail: (11) []\=[] ? creep
Fail: (10) predicate(test, [], _28066) ? creep
false.
[trace] ?- nodebug.
true.
?- predicate(test,[],X).
false.
?- predicate(test,[a],X).
test[a]
X = true.
predicates
nondeterm s(integer,integer)
nondeterm p(integer,integer,integer)
clauses
s(V,R) :-
p(0,V,R).
%,write(R),nl.
p(R,0,R).
p(Inc,V,R) :-
I2=Inc+V,
N1=V-1,
p(I2,N1,R).
goal
s(9,O).
gives an arithmetic overflow,,,why??
In Prolog mathematical expressions are not done with assignment, e.g. =. Prolog does not use assignment like many common programming languages, Prolog uses unification. If you want to do math expressions in Prolog and unify the result with a variable then you need to use the is/2 operator
I2 is Inc+V
N1 is V-1
You also need a guard statement to keep the second clause from being executed if the second parameter is 0.
s(V,O) :-
p(0,V,O).
p(R,0,R).
p(Inc,V,R) :-
V \= 0,
I2 is Inc+V,
N1 is V-1,
p(I2,N1,R).
Now your query returns
?- s(9,O).
O = 45 ;
false.
Complementing Guy's answer, it is instructive to run your query in the Prolog tracer as it clearly shows that, because you used unification (=/2) instead of arithmetic expression evaluation (is/2), your query build an increasingly bigger compound term at each recursive call until the global stack space is exhausted:
[trace] ?- s(9,O).
Call: (8) s(9, _3176) ? creep
Call: (9) p(0, 9, _3176) ? creep
Call: (10) _3396=0+9 ? creep
Exit: (10) 0+9=0+9 ? creep
Call: (10) _3402=9-1 ? creep
Exit: (10) 9-1=9-1 ? creep
Call: (10) p(0+9, 9-1, _3176) ? creep
Call: (11) _3408=0+9+(9-1) ? creep
Exit: (11) 0+9+(9-1)=0+9+(9-1) ? creep
Call: (11) _3414=9-1-1 ? creep
Exit: (11) 9-1-1=9-1-1 ? creep
Call: (11) p(0+9+(9-1), 9-1-1, _3176) ? creep
Call: (12) _3420=0+9+(9-1)+(9-1-1) ? creep
Exit: (12) 0+9+(9-1)+(9-1-1)=0+9+(9-1)+(9-1-1) ? creep
Call: (12) _3426=9-1-1-1 ?
...
Here is my knowledge base:
numeral(0).
numeral(succ(X)) :- numeral(X).
Here is my query:
numeral(X).
Here is what SWI Prolog returns in trace mode:
[trace] ?- numeral(X).
Call: (8) numeral(_3806) ? creep
Exit: (8) numeral(0) ? creep
X = 0 ;
Redo: (8) numeral(_3806) ? creep
Call: (9) numeral(_4006) ? creep
Exit: (9) numeral(0) ? creep
Exit: (8) numeral(succ(0)) ? creep
X = succ(0) ;
Redo: (9) numeral(_4006) ? creep
Call: (10) numeral(_4010) ? creep
Exit: (10) numeral(0) ? creep
Exit: (9) numeral(succ(0)) ? creep
Exit: (8) numeral(succ(succ(0))) ? creep
X = succ(succ(0))
I understand how it finds X=0 answer, I do not fully grasp how it obtains: X = succ(succ(0)). I understand that this is correct answer, but I am not sure how Prologs searched for it.
Here is my thinking:
When it prints Call: (9) numeral(_4006) ? creep it tries this rule: numeral(succ(X)) :- numeral(X). And in particular it probably substitutes _4006 = succ(X)
then it checks that it only holds when numeral(X) holds, which Prolog checks against numeral(0), so result is _4006 = succ(0).
Now if we ask for anther solution it again comes back to numeral(_4006), but what does it guess when is calls numeral(_4010). What is branching process here?
Is there way to get more details?
P.S. This is taken from the following link
Prolog searches trough bactracking. There are two ways Prolog can aim to satisfy an numeral(X) call:
with numeral(0) in which case it unifies X with 0; and
with numeral(succ(Y)) :- numeral(Y) in which case it unifies X with succ(Y) and makes a recursive call.
I here used Y since this also creates confusion: the variables in a clause are locally scoped in the sense that an X in a clause, is not the same variable as an X in a call.
Now in case Prolog backtracks and aims to satisfy the predicate with the clause, then this means that X = succ(Y) with Y a variable, but it needs to make an extra call with numeral(Y) as specified in the body.
Again there are two choices:
with numeral(0) in which case it unifies Y with 0; and
with numeral(succ(Z)) :- numeral(Z) in which case it unifies Y with succ(Z) and makes a recursive call.
In case we go for the first one, Y is set to 0, and thus X = succ(Y) hence X = succ(0). In the latter case X = succ(Y), and Y = succ(Z), and we again make a recursive call.
Now in case we again use the first line for numeral(0), this thus means that Z is unified with 0, hence Z = 0, hence Y = succ(0), hence X = succ(succ(0)).
Suppose, I have a prolog predicate such as:
name(music,[jazz,blues,classical]).
and what I want is to check membership of say jazz and return me true if in music?
So far, I did this:
ismember(X,Y):-imember(X,name(Y,Z)),write(Z).
imember(X,[_|Tail]):-imember(X,Tail).
imember(X,[X|_]).
But it isn't working.
?- ismember(jazz,music).
false.
And it isn't writing the write(Z) part.
In the visible part of the following fragment there is an error. Not only does your program fail, also the following generalization fails:
:- op(950, fy, *).
*(_).
ismember(X,Y):-
imember(_/*X*/,name(_/*Y*/,Z)).
imember(X,[_|Tail]):-
* imember(X,Tail).
imember(X,[_/*X*/|_]).
?- ismember(X, Y).
The generalization has been obtained by replacing some variables by _, and by removing one goal with *. It generalizes as much as possible. That is, any further generalization would make the goal succeed. And there is this nice property that holds in (pure, monotonic) Prolog:
If a generalization fails (for a specific query), then also the original program fails (for that same query).
That's the nice property that somehow establishes causality between a generalized fragment and the original program. If you want to remove the error, something in the generalized program has to be changed. Or conversely: If you make changes that still permit to get the generalization, then you have not fixed the error.
With this in mind,when searching for such a fragment, there is no need to "understand" the actual program. It suffices to guess and generalize mindlessly as long as this is possible.
Now, if we look at that generalization note that
the arguments of ismember/2 are completely ignored!
The problem is that the name(Y,Z) that you pass in imember/2 predicate isn't a list. You could simply write:
ismember(X,Y):-name(Y,Z),imember(X,Z),write(Z).
imember(X,[_|Tail]):-imember(X,Tail).
imember(X,[X|_]).
Example:
?- ismember(jazz,music).
[jazz,blues,classical]
true.
the ismember/2 predicate second parameter is a list , and you are not passing a list
here is a trace
[trace] ?- ismember(jazz,music).
Call: (8) ismember(jazz, music) ? creep
Call: (9) imember(jazz, name(music, _6828)) ? creep
Fail: (9) imember(jazz, name(music, _6828)) ? creep
Fail: (8) ismember(jazz, music) ? creep
false.
#coder answer is a correct way
or you can simply use the member/2 predicate as follows:
first define your list in the database:
music([jazz,blues,classical]).
now we have our music types list , next we write the rule
ismusicmember(X) :- music(L) , member(X,L),write(L).
music(L) to assign the variable L to our music list
member(X,L) the member/2 predicate check whether X is in the list or not
and running a query
?- ismusicmember(jazz).
[jazz,blues,classical]
true .
a trace:
[trace] ?- ismusicmember(jazz).
Call: (8) ismusicmember(jazz) ? creep
Call: (9) music(_7376) ? creep
Exit: (9) music([jazz, blues, classical]) ? creep
Call: (9) lists:member(jazz, [jazz, blues, classical]) ? creep
Exit: (9) lists:member(jazz, [jazz, blues, classical]) ? creep
Call: (9) write([jazz, blues, classical]) ? creep
[jazz,blues,classical]
Exit: (9) write([jazz, blues, classical]) ? creep
Exit: (8) ismusicmember(jazz) ? creep
true .
I am writing a program in Prolog that represents the rules of a card game. However, I am running into an infinite loop with the following code.
succ(seven_of_hearts,eight_of_hearts).
succ(eight_of_hearts,nine_of_hearts).
succ(nine_of_hearts,ten_of_hearts).
succ(ten_of_hearts,jack_of_hearts).
succ(jack_of_hearts,queen_of_hearts).
succ(queen_of_hearts,king_of_hearts).
succ(king_of_hearts,ace_of_hearts).
succ(X,Y) :-
succ(X,Z),
succ(Z,Y),
!.
beats(X,Y) :-
succ(Y,X).
Basically, my attempt with these few lines is to set up a system for determining if one card beats another according to the succ (or succession) relationships I have established. So the query I am running is beats(X,Y), where X and Y and atoms corresponding to cards. This query terminates successfully if it is true. For example, if I query beats(jack_of_hearts,seven_of_hearts), it returns true and terminates.
However, the query enters an infinite loop if it is false. For example, when I query beats(seven_of_hearts,jack_of_hearts). I traced the query and found that due to the recursive nature of the last succ statement, the query follows the chain of succ statements all the way down to the seven_of_hearts, or all the way up to the ace_of_hearts, and then continuously tries to evaluate succ(seven_of_hearts,X) or succ(ace_of_hearts,X) instead of returning false.
I have two questions: using this current structure, how could I prevent this? Or, if that's not possible, what is an alternative structure I could use to accomplish my goal?
EDIT:
Here is a screenshot of my trace for one of the failing queries:
Call: (267) beats(seven_of_hearts, jack_of_hearts) ? creep
Call: (268) succ(jack_of_hearts, seven_of_hearts) ? creep
Call: (269) succ(jack_of_hearts, _G7104) ? creep
Exit: (269) succ(jack_of_hearts, queen_of_hearts) ? creep
Call: (269) succ(queen_of_hearts, seven_of_hearts) ? creep
Call: (270) succ(queen_of_hearts, _G7104) ? creep
Exit: (270) succ(queen_of_hearts, king_of_hearts) ? creep
Call: (270) succ(king_of_hearts, seven_of_hearts) ? creep
Call: (271) succ(king_of_hearts, _G7104) ? creep
Exit: (271) succ(king_of_hearts, ace_of_hearts) ? creep
Call: (271) succ(ace_of_hearts, seven_of_hearts) ? creep
Call: (272) false ? creep
Fail: (272) false ? creep
Redo: (271) succ(ace_of_hearts, seven_of_hearts) ? creep
Call: (272) succ(ace_of_hearts, _G7104) ? creep
Call: (273) false ? creep
Fail: (273) false ? creep
Redo: (272) succ(ace_of_hearts, _G7104) ? creep
Call: (273) succ(ace_of_hearts, _G7104) ? creep
Call: (274) false ? creep
Fail: (274) false ? creep
Redo: (273) succ(ace_of_hearts, _G7104) ? creep
Call: (274) succ(ace_of_hearts, _G7104) ? creep
Call: (275) false ? creep
Your predicate obviously keeps calling itself: succ(X, Y) :- succ(Y, X), .... A simple solution is not to use the same name for your predicate as you do your facts. Get rid of your succ/2 predicate (leaving the facts) in favor of:
successor(X, Y) :- succ(X, Y).
successor(X, Y) :- succ(X, Z), succ(Z, Y).
beats(X, Y) :- successor(Y, X).