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).
Related
How do I hide a module or a whole package from tracing.
I have this query, and I want to step through it, but
I am not interested in what CLP(X) does, only at what point something fails in my query.
?- X in 0..5, X in 7..8.
fail.
?- dif(A, 1), A = 1.
fail.
If I run this query in SWI-Prolog it shows me every nifty
detail of the module CLP(X), not only some inlining
related to the constraints but also everything else from CLP(X):
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.2)
?- trace.
true.
[trace] ?- X in 0..5, X in 7..8.
Call: (9) clpfd:clpfd_in(_2662, 0..5) ? creep
Call: (10) clpfd:fd_variable(_2662) ? creep
Call: (11) var(_2662) ? creep
Exit: (11) var(_2662) ? creep
Call: (11) true ? creep
Exit: (11) true ? creep
[trace] ?- dif(A, 1), A=1.
Call: (9) dif:dif(_3044, 1) ? creep
Exit: (9) dif:dif(_3410{dif = ...}, 1) ? creep
Call: (9) _3410{dif = ...}=1 ? creep
Is there a way to suppress the internals of CLP(X). For
example if I use another Prolog system, I don't see any
internals of the CLP(X) (Preview):
Jekejeke Prolog 3, Development Environment 1.3.6
?- trace.
Yes
?- X in 0..5, X in 7..8.
0 Call X in 0..5 ?
0 Exit X in 0..5 ?
0 Call X in 7..8 ?
0 Fail X in 7..8 ?
No
?- neq(A, 1), A = 1.
0 Call neq(A, 1) ?
0 Exit neq(A, 1) ?
0 Call A = 1 ?
0 Fail A = 1 ?
No
Is there an elegant way to disable a module/package, but nevertheless see top-level calls/exits from the module/packge?
There are various ways to control the debugging process in SWI-Prolog, see http://www.swi-prolog.org/pldoc/man?section=debugging. In this can you can use the skip option, which will "skip to exit port of this call or wake port". The option is activated by pressing s during the trace intead of Enter.
In this case skipping over all calls results in a trace which is very similar to your Jekejeke example (although a bit less nicely formatted):
?- use_module(library(clpfd)).
true.
?- trace.
true.
[trace] ?- X in 0..5, X in 7..8.
Call: (9) clpfd:clpfd_in(_7788, 0..5) ? skip
Exit: (9) clpfd:clpfd_in(_8226{clpfd = ...}, 0..5) ? creep
Call: (9) integer(_8226{clpfd = ...}) ? skip
Fail: (9) integer(_8226{clpfd = ...}) ? creep
Call: (9) clpfd:clpfd_in(_8226{clpfd = ...}, 7..8) ? skip
Fail: (9) clpfd:clpfd_in(_8226{clpfd = ...}, 7..8) ? creep
false.
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)).
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.
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.
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.