Cannot increment variable N by 1 using is/2 predicate - prolog

Cannot increment variable N by 1 using is/2 predicate. N is always 0 in the repeat loop. Why? How to increment it?
:- dynamic audible/1, flashes/1,tuned/1.
audible(false).
flashes(false).
tuned(false).
turn :-
N is 0 ,
repeat ,
(
incr(N,N1) ,
N1 =:= 5000 ,
audible(true) ,
flashes(true) -> retractall(tuned) ,
retractall(flashes) ,
retractall(audible) ,
assert( tuned(true) ) ,
assert( flashes(true) ) ,
assert( audible(true) )
) .
incr(X,X1) :- X1 is X+1 .

Because N is 0. Variables in Prolog are not assignables. Here's what happens if you trace your loop:
?- trace, turn.
Call: (7) turn ?
Call: (8) _G492 is 0 ?
Exit: (8) 0 is 0 ?
Call: (8) repeat ?
Exit: (8) repeat ?
Call: (8) incr(0, _G493) ?
Call: (9) _G495 is 0+1 ?
Exit: (9) 1 is 0+1 ?
Exit: (8) incr(0, 1) ?
Call: (8) 1=:=5000 ?
Fail: (8) 1=:=5000 ?
Redo: (8) repeat ?
Exit: (8) repeat ?
Call: (8) incr(0, _G493) ?
Call: (9) _G495 is 0+1 ?
Exit: (9) 1 is 0+1 ?
Exit: (8) incr(0, 1) ?
Call: (8) 1=:=5000 ?
Fail: (8) 1=:=5000 ?
Redo: (8) repeat ?
Exit: (8) repeat ?
Call: (8) incr(0, _G493) ?
Call: (9) _G495 is 0+1 ?
Exit: (9) 1 is 0+1 ?
Exit: (8) incr(0, 1) ?
Call: (8) 1=:=5000 ?
Fail: (8) 1=:=5000 ?
Redo: (8) repeat ?
See what's happening there? You're repeatedly asking if 1 is 5000, which fails, and then you try again. But the value of N and N1 will never change within the body of a predicate. Prolog does not have block-scoped variables like you're accustomed to. You need to make the body of the loop into a separate predicate and use recursion to accomplish what you're trying to do. It's going to look something like this:
turn :- loop(0).
loop(5000) :-
audible(true), ...
loop(N) :-
incr(N, N1),
loop(N1).
By the way, there's already a predicate succ/2 that does what you're trying to do with incr/2.

I haven't a clue what you're trying to accomplish here, but it would appear that you're trying to write procedural prolog code.
It doesn't work.
Prolog variables are write-once: having been unified with an object they cease to be variable. They become that object, until that unification is undone via backtracking.
You need to learn to think recursively and to use recursion loops to do what you want.
Your turn/0 predicate
turn :-
N is 0 ,
repeat ,
(
incr(N,N1) ,
N1 =:= 5000 ,
audible(true) ,
flashes(true) -> retractall(tuned) ,
retractall(flashes) ,
retractall(audible) ,
assert( tuned(true) ) ,
assert( flashes(true) ) ,
assert( audible(true) )
) .
does the following. It:
unifies N with 0,
increments N1 with N+1, making N1 = 1
fails if N1 is something other than 5000 (which it is).
On failure, the prolog engine starts backtracking...
backtracking through incr/2 undoes N1's binding, making it variable again.
backtracking into repeat/0, succeeds again.
At this point, you're back to where you started, with N bound to 0.
Wash, rinse, repeat.

Related

Difference between two Implementation of even and odd in Prolog

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.

Error when defining length in SWI Prolog

I have defined a procedure named length in a file named test.pl:
% Finds the length of a list.
length([], 0).
length([_ | Tail], N) :-
length(Tail, N1),
N is 1 + N1.
When the program is run using SWI-Prolog (prolog test.pl), the following error appears:
ERROR: /home/user/test.pl:2:
No permission to modify static procedure `length/2'
Defined at /usr/lib/swi-prolog/boot/init.pl:3496
ERROR: /home/user/test.pl:3:
No permission to modify static procedure `length/2'
Defined at /usr/lib/swi-prolog/boot/init.pl:3496
I tried changing the name of the procedure from length to mylength, and the error disappears. What does this error mean? Can I define a procedure named length? If not, why can't it be done?
length/2 isn't defined in Prolog, but it's instead part of the shallow interface over native (high efficient) lists implementation. You should use the directive redefine_system_predicate.
For instance, save in a file redef_length.pl
:- redefine_system_predicate(length(?,?)).
% Finds the length of a list.
length([], 0).
length([_ | Tail], N) :-
length(Tail, N1),
N is 1 + N1.
then consult it
?- [test/prolog/redef_length].
true.
?- trace.
true.
[trace] ?- length(A,B).
Call: (8) length(_1476, _1478) ? creep
Exit: (8) length([], 0) ? creep
A = [],
B = 0 ;
Redo: (8) length(_1476, _1478) ? creep
Call: (9) length(_1718, _1738) ? creep
Exit: (9) length([], 0) ? creep
Call: (9) _1478 is 1+0 ? creep
Exit: (9) 1 is 1+0 ? creep
Exit: (8) length([_1716], 1) ? creep
A = [_1716],
B = 1
That's right. length/2 is a built-in predicate: length(?List, ?Int) is True if Int represents the number of elements in List. So the name is already used.

Prolog recursion in sum of n natural numbers

I am having trouble to understand how value of Z is constantly changing. The specific step has been indicated in the stack trace output.
Here is the code I am using for finding sum of N natural numbers -
sum1(1,1).
sum1(N, Sum) :-
Next is N-1,
sum1(Next, Z),
Sum is Z + N.
Here is the stack trace -
?- sum1(3,_).
Call: (8) sum1(3, _2668) ? creep
Call: (9) _2860 is 3+ -1 ? creep
Exit: (9) 2 is 3+ -1 ? creep
Call: (9) sum1(2, _2862) ? creep
Call: (10) _2866 is 2+ -1 ? creep
Exit: (10) 1 is 2+ -1 ? creep
Call: (10) sum1(1, _2868) ? creep
Exit: (10) sum1(1, 1) ? creep
Call: (10) _2872 is 1+2 ? creep
Exit: (10) 3 is 1+2 ? creep
Exit: (9) sum1(2, 3) ? creep **%How is Z assigned value 3 ?**
Call: (9) _2668 is 3+3 ? creep
Exit: (9) 6 is 3+3 ? EOF: exit
Thanks in advance!
It is not "changing"; each proof of sum1 gets its own versions of N, Sum, Next and Z. This is why, in the stack trace, each gets a different generated name (i.e. _2860), so Prolog can tell them apart.
As to your specific question, 2 lines above the line you ask about, that particular Sum is _2872; so proving _2872 is 1+2 requires _2872 to be 3. And this Sum is matched to the previous call sum(1, _2868), where _2868 was that sum1's Z (as you can see from 2 lines above that).

Prolog if clause returns false

I am learning Prolog and I have a small question.
I'm working on an example which "builds" a tower.
So I define 3 blocks a, b and c.
The third block c lays on top of a and b -> so it is supported by a and b.
block(a).
block(b).
block(c).
%supported(BLOCK, BY1, BY2)
supported(c,a,b).
level(BLOCK, LEVEL) :-
supported(BLOCK, X, _)
-> (level(X, LEV1), LEVEL is LEV1 + 1)
; LEVEL is 0.
I also have a function to calculate the level of a block. The problem I have is the following:
?- level(X, 0).
false.
?- level(X, 1).
X = c.
Why is it returning false for the level 0 and how can i fix it?
I would like to have a method which returns me a and b for level 0.
consider that
?- level(a,0).
true.
it's evident that when BLOCK is free the supported(BLOCK, X, _) succeeds, forcing the rule on the unintended conjuntion level(X, LEV1), LEVEL is LEV1 + 1, that indeed fails.
To correct the behaviour, bind BLOCK:
level(BLOCK, LEVEL) :-
block(BLOCK),
(supported(BLOCK, X, _) -> level(X, LEV1), LEVEL is LEV1 + 1 ; LEVEL is 0).
One can debug this using trace. (added indentation):
[trace] ?- level(X, 0).
Call: (6) level(_G2697, 0) ? creep
Call: (7) supported(_G2697, _G2771, _G2772) ? creep
Exit: (7) supported(c, a, b) ? creep
Call: (7) level(a, _G2771) ? creep
Call: (8) supported(a, _G2771, _G2772) ? creep
Fail: (8) supported(a, _G2771, _G2772) ? creep
Redo: (7) level(a, _G2771) ? creep
Call: (8) _G2770 is 0 ? creep
Exit: (8) 0 is 0 ? creep
Exit: (7) level(a, 0) ? creep
Call: (7) 0 is 0+1 ? creep
Fail: (7) 0 is 0+1 ? creep
Fail: (6) level(_G2697, 0) ? creep
false.
So what happened?
First you call level(X,0). This predicate calls supported with supported(BLOCK,X,_). There is one answer that unifies: BLOCK=a, X=b and _=c. So that means the if-then-else statement uses the then-part.
In the then-part, it queries level/2 again with level(b,LEV1), now this call results in a call to support(b,LEV1,_). For this call, it can't resolve the call, because there is no support predicate with the first value b. So now we take the else-part. We unify LEV1 is 0, thus LEV1=0 and we return.
In the return part (in the then-part), level(b,0) is the result. Now we unify LEVEL is LEV1+1, LEVEL however was already grounded as 0 and 0+1 is 1. Thus it fails on the top level.
The resolution is probably to make supported finer, and define it as: support/2.
The program reads:
block(a).
block(b).
block(c).
%supported(BLOCK, BY1, BY2)
supported(c,b).
supported(c,a).
supported(b,a).
Now the level predicate reads:
level(B,L) :-
supported(B,C),
level(C,LC),
L is LC+1.
level(_,0).

prolog - why this strange trace

here is the prolog code (which i sort of follow).
len([],0).
len([_|T],N) :- len(T,X), N is X+1.
and here is the trace for it (im running linux, swi)
[trace] ?- len([d,f,w,c],X).
Call: (7) len([d, f, w, c], _G314) ?
Call: (8) len([f, w, c], _L182) ?
Call: (9) len([w, c], _L201) ?
Call: (10) len([c], _L220) ?
Call: (11) len([], _L239) ?
Exit: (11) len([], 0) ?
^ Call: (11) _L220 is 0+1 ?
^ Exit: (11) 1 is 0+1 ?
Exit: (10) len([c], 1) ?
^ Call: (10) _L201 is 1+1 ?
^ Exit: (10) 2 is 1+1 ?
Exit: (9) len([w, c], 2) ?
^ Call: (9) _L182 is 2+1 ?
^ Exit: (9) 3 is 2+1 ?
Exit: (8) len([f, w, c], 3) ?
^ Call: (8) _G314 is 3+1 ?
^ Exit: (8) 4 is 3+1 ?
Exit: (7) len([d, f, w, c], 4) ?
X = 4.
i know prolog runs down these 'trees' but im having trouble figuring out why the increment to the variable is only done when it is exiting - any explainations of the mechanics of this?
Many thanks!
The reason for this, is that N is X+1 is the last part to the predicate.
Think of it like this: to calculate N is X+1, we need to know the value of X, which is calculated by calling len(T,X). But the process of calculating X requires yet another call to len, all the way to the situation where you end up with an empty list.
It is at that point that the list length is known, namely 0. Thus that value is "returned". Only then 0 + 1 can calculated and "returned". And then 1 + 1. Etc.
Thinking of it another way, observe that for any two predicates a and b, a, b yields true iff both a and b are true. In Prolog, b will only be evaluated if it is known that a is true (otherwise there is no point in evaluating b, since the result is known to be false).
As a result, all additions are done after the recursive calls to len.

Resources