prolog - ERROR: Arguments are not sufficiently instantiated - prolog

I'm fairly new to prolog and need to check if the points makes a triangle isosceles but i got this error. ERROR: Arguments are not sufficiently instantiated. I'm not sure what I did wrong.
distance seems to work fine but the problem is with the isosceles.
/*Is the triangle isosceles?*/
isosceles(point2d(X1,Y1), point2d(X2,Y2), point2d(X3,Y3)):-
distance( point2d(X1,Y1), point2d(X2,Y2), D ) =:= distance( point2d(X2,Y2), point2d(X3,Y3), D );
distance( point2d(X2,Y2), point2d(X3,Y3), D ) =:= distance( point2d(X1,Y1), point2d(X3,Y3), D );
distance( point2d(X1,Y1), point2d(X3,Y3), D ) =:= distance( point2d(X1,Y1), point2d(X2,Y2), D ).
distance(point2d(X1,Y1), point2d(X2,Y2), D):-
D is sqrt((X2 - X1)^2 + (Y2 - Y1)^2).
?- isosceles(point2d(0,0), point2d(2,4), point2d(5,0)).
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [11] distance(point2d(0,0),point2d(2,4),_10064)=:=distance(point2d(2,4),point2d(5,0),_10084)
ERROR: [10] isosceles(point2d(0,0),point2d(2,4),point2d(5,0)) at /home/checkman123/prolog-geometry/threepoints.pl:25
ERROR: [9] <user>
EDIT: so I think i got it working? by using , instead. I still wants to know why =:= doesnt work tho.

This is what David is saying, after factorizing the repeated calculations:
iso(point2d(X1,Y1), point2d(X2,Y2), point2d(X3,Y3)):-
distance( point2d(X1,Y1), point2d(X2,Y2), D12 ),
distance( point2d(X2,Y2), point2d(X3,Y3), D23 ),
distance( point2d(X1,Y1), point2d(X3,Y3), D13 ),
(D12 =:= D13; D23 =:= D13; D13 =:= D12).

Related

Efficient Fibonacci in Prolog

I am trying to implement a Fibonacci predicate that can be efficiently used with CLP.
:- module(fibonacci, [fibonacci/2]).
fibonacci(N, F) :-
( var(N) ; integer(N) ),
( var(F) ; integer(F) ),
( var(F) ->
( integer(N) ->
fib_1(N, F), !
; fib_3(0, N, F)
)
; ( integer(N) ->
fib_1(N, F0), F0 = F, !
; fib_2(0, F, N0), N0 = N, !
)
).
fib_3(I, J, F) :-
( I = J, fib_1(I, F) ) ;
( I1 is I + 1, fib_3(I1, J, F) ).
fib_2(I, F, J) :-
fib_1(I, F0),
( F = F0 ->
J = I, !
; ( F0 > F -> !, fail
; I1 is I + 1,
fib_2(I1, F, J)
)
).
fib_1(0, 0).
fib_1(1, 1).
fib_1(2, 1).
fib_1(N, F) :-
var(F),
N > 2,
( N mod 2 =:= 0 ->
N0 is div(N, 2),
N1 is N0 + 1,
fib_1(N0, F0),
fib_1(N1, F1),
F is F0 * (2 * F1 - F0)
; N0 is div(N + 1, 2),
N1 is N0 - 1,
fib_1(N0, F0),
fib_1(N1, F1),
F is F0 * F0 + F1 * F1
).
This is not the prettiest code, but it does what I want it to do.
?- fibonacci(A, 10).
false.
?- fibonacci(A, 13).
A = 7.
?- fibonacci(12, A).
A = 144.
?- fibonacci(12, 144).
true.
?- fibonacci(12, 145).
false.
?- fibonacci(A, B).
A = B, B = 0 ;
A = B, B = 1 ;
A = 2,
B = 1 ;
A = 3,
B = 2 ;
A = 4,
B = 3 ;
A = B, B = 5 .
What's the magic potion that is missing for this query to work:
fibonacci(_, B), B #< 1000
Is it rectifiable at all, or is CLP a completely different beast altogether, and every predicate that is CLP-compatible needs to understand more than just integers and vars?
You should avoid using ! within an algorithm that uses clp(FD) as they don't mix well. Also if-then-else may backfire too. I'd also keep an eye on using var/1 within an algorithm that uses clp.
Here goes a solution that uses clp(FD) and accumulators to avoid double recursion:
fibonacci(0, 0).
fibonacci(1, 1).
fibonacci(N, F):-
N #> 1,
zcompare(C, 2, N),
fibonacci(C, 2, N, 0, 1, F).
fibonacci(=, N, N, F1, F2, F):-
F #= F1+F2.
fibonacci(<, N0, N, F1, F2, F):-
N1 #= N0+1,
F3 #= F1+F2,
F #> F3,
zcompare(C, N1, N),
fibonacci(C, N1, N, F2, F3, F).
Also for the test you should issue the constraint over the expected number before calling fibonacci/2. So instead of fibonacci(_, B), B #< 1000. use B #< 1000, fibonacci(_, B).
sample runs:
?- fibonacci(10, F).
F = 55.
?- B #< 1000, fibonacci(_, B).
B = 0 ;
B = 1 ;
B = 1 ;
B = 2 ;
B = 3 ;
B = 5 ;
B = 8 ;
B = 13 ;
B = 21 ;
B = 34 ;
B = 55 ;
B = 89 ;
B = 144 ;
B = 233 ;
B = 377 ;
B = 610 ;
B = 987 ;
false.

Prolog tells me a procedure is undefined when it appears to be defined

I'm new to Prolog and I'm having trouble figuring out why it's telling me procedures are undefined when I query them, when they appear to be defined. This code was given to me by my instructor and I'm not allowed to change it, so it must be a problem with the way I'm compiling it or something related to that. I'm using the SWI-Prolog IDE.
I have 2 .pl files:
print-maze.pl:
printMaze() :- boundary(XMAX,YMAX), \+printMaze( p(-1,YMAX), XMAX ).
printMaze( p( _, Y ), _ ) :- Y < -1, fail.
printMaze( p( X, Y ), XMAX ) :- Y >= -1, X > XMAX,
nl,
NewY is Y - 1,
printMaze( p(-1,NewY), XMAX ).
printMaze( p( X, Y ), XMAX ) :- Y >= -1, X =< XMAX,
printSpot( X, Y ),
NewX is X + 1,
printMaze( p(NewX,Y), XMAX ).
printSpot( X, Y ) :- (
( X is -1, Y is -1 );
( boundary( X, _ ), Y is -1 );
( boundary( _, Y ), X is -1 );
boundary( X, Y )
),
!, write( '+' ).
printSpot( X, Y ) :- ( boundary( X, _ ); X = -1 ),
!, N is Y mod 10, write( N ).
printSpot( X, Y ) :- ( boundary( _, Y ); Y = -1 ),
!, N is X mod 10, write( N ).
printSpot( X, Y ) :- goal( X, Y ), !, write( '*' ).
printSpot( X, Y ) :- wall( X, Y ), !, write( '-' ).
printSpot( _, _ ) :- write( ' ' ).
and test0.pl:
goal( 2, 2 ).
boundary( 3, 3 ).
wall( 0, 1 ).
wall( 0, 2 ).
wall( 2, 0 ).
wall( 2, 1 ).
% 0,0
% 2,2
:- load_files( 'print-maze.pl' ).
After clicking Compile and then Make in the editor while I have both files open,
when I do the query:
?- goal(2,2).
I get the error:
ERROR: Undefined procedure: goal/2 (DWIM could not correct goal)
and when I do the query:
?- printMaze().
I get the error:
ERROR: Undefined procedure: boundary/2
ERROR: In:
ERROR: [9] boundary(_7002,_7004)
ERROR: [8] printMaze at c:/users/jproc/documents/prolog/print-maze.pl:7
ERROR: [7] <user>
goal/2 and boundary/2 appear to be defined in test0.pl, so what gives?
I figured out that the issue was I needed to go to File and Consult ... and select test0.pl. After that, the queries gave their expected results.

Arguments are not sufficiently instantiated with prolog clpfd

I am working with CLPFD and I cannot seem to get rid of the error:
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [16] throw(error(instantiation_error,_9234))
ERROR: [12] clpfd:drep_to_domain(_9270..15,_9266) at /usr/lib/swi-prolog/library/clp/clpfd.pl:3652
ERROR: [11] clpfd:clpfd_in(_9302,_9308..15) at /usr/lib/swi-prolog/library/clp/clpfd.pl:1608
ERROR: [10] computeShapeBelow([[circle|...],6|...],[[diamond|...],_9370|...])
Below is my program and it is clear to me that Dim1 and Dim2 which come from nth0/3 are causing Prolog to throw this error. How can I work around this? I cannot find a way to apply the solutions I have seen here on StackOverflow with CLPFD
:- use_module(library(clpfd)).
computeShapeBelow(Shape1,Shape2) :-
nth0(2,Shape1,Location1),
nth0(2,Shape2,Location2),
nth0(1,Shape1,Dim1),
nth0(1,Shape2,Dim2),
nth0(0,Location1,Xcord1),
nth0(0,Location2,Xcord2),
nth0(1,Location1,Ycord1),
nth0(1,Location2,Ycord2),
XlowerLimit1 #= Dim1,
XupperLimit1 #= 20-Dim1,
YlowerLimit1 #= Dim1,
YupperLimit1 #= 15-Dim1,
XlowerLimit2 #= Dim2,
XupperLimit2 #= 20-Dim2,
YlowerLimit2 #= Dim2,
YupperLimit2 #= 15-Dim2,
Ycord1 in YlowerLimit1..YupperLimit1,
Ycord2 in YlowerLimit2..YupperLimit2,
Xcord1 in XlowerLimit1..XupperLimit1,
Xcord2 in XlowerLimit2..XupperLimit2,
Ycord2 #> Ycord1+Dim2+Dim1,
labeling([min(Xcord1),
min(Ycord2),
max(Xcord2),
max(Ycord2)],
[Xcord1,Ycord1,Xcord2,Ycord2]).
Edit
listing(computeShapeBelow) produces the following.
computeShapeBelow(A, B) :-
nth0(2, A, C),
nth0(2, B, D),
nth0(1, A, E),
nth0(1, B, J),
nth0(0, C, Q),
nth0(0, D, R),
nth0(1, C, O),
nth0(1, D, P),
( integer(E)
-> F=E
; clpfd:clpfd_equal(F, E)
),
( integer(E)
-> G is 20-E
; clpfd:clpfd_equal(G, 20-E)
),
( integer(E)
-> H=E
; clpfd:clpfd_equal(H, E)
),
( integer(E)
-> I is 15-E
; clpfd:clpfd_equal(I, 15-E)
),
( integer(J)
-> K=J
; clpfd:clpfd_equal(K, J)
),
( integer(J)
-> L is 20-J
; clpfd:clpfd_equal(L, 20-J)
),
( integer(J)
-> M=J
; clpfd:clpfd_equal(M, J)
),
( integer(J)
-> N is 15-J
; clpfd:clpfd_equal(N, 15-J)
),
clpfd:clpfd_in(O, H..I),
clpfd:clpfd_in(P, M..N),
clpfd:clpfd_in(Q, F..G),
clpfd:clpfd_in(R, K..L),
( integer(P)
-> ( integer(O),
integer(J),
integer(E)
-> P>=O+J+E+1
; S=P,
clpfd:clpfd_geq(S, O+J+E+1)
)
; integer(O),
integer(J),
integer(E)
-> S is O+J+E+1,
clpfd:clpfd_geq(P, S)
; clpfd:clpfd_geq(P, O+J+E+1)
).
The reason for this error is your using variables as domain boundaries in (in)/2.
As a minimal example that shows the problem, consider:
?- Var in X..Y.
ERROR: Arguments are not sufficiently instantiated
For (in)/2, the domain must be ground. It is not admissible to use only partially instantiated domains.
A possible workaround for this concrete issue is using arithmetic constraints like (#>)/2 etc. instead of (in)/2. For example:
my_in(Var, Lower, Upper) :-
Lower #=< Var, Var #=< Upper.
If you use this predicate instead of (in)/2 in your code, your issue disappears. I leave figuring out how to use the predicate as a small challenge.
However, other issues will then surface. I think they should be discussed separately, in a new question.

Prolog findall - Arguments are not sufficiently instantiated

location(T1,R,C) :-
T0 is T1 - 1,
RN is R - 1,
RS is R + 1,
CW is C - 1,
CE is C + 1,
(
((action(T0,eat);action(T0,clockWise);action(T0,counterClockWise)), location(T0,R,C));
((action(T0,attack);action(T0,forward)), bump(T1), location(T0,R,C));
((action(T0,attack);action(T0,forward)), dir(T0,north), not(bump(T1)), location(T0,RS,C));
((action(T0,attack);action(T0,forward)), dir(T0,south), not(bump(T1)), location(T0,RN,C));
((action(T0,attack);action(T0,forward)), dir(T0,west), not(bump(T1)), location(T0,R,CE));
((action(T0,attack);action(T0,forward)), dir(T0,east), not(bump(T1)), location(T0,R,CW))
).
peek_location( [T0, R, C], [R_n, C_n]) :-
RN is R - 1,
RS is R + 1,
CW is C - 1,
CE is C + 1,
(
((action(T0,eat);action(T0,clockWise);action(T0,counterClockWise)), R_n is R, C_n is C);
((action(T0,attack);action(T0,forward)), dir(T0,north), R_n is RS, C_n is C);
((action(T0,attack);action(T0,forward)), dir(T0,south), R_n is RN, C_n is C);
((action(T0,attack);action(T0,forward)), dir(T0,west), R_n is R, C_n is CE);
((action(T0,attack);action(T0,forward)), dir(T0,east), R_n is R, C_n is CW)
).
dir(T1,north) :-
T0 is T1 - 1,
(
((action(T0,eat);action(T0,attack);action(T0,forward)), dir(T0,north) );
(action(T0,clockWise) , dir(T0,west));
(action(T0,counterClockWise), dir(T0,east))
).
dir(T1,east) :-
T0 is T1 - 1,
(
((action(T0,eat);action(T0,attack);action(T0,forward)), dir(T0,east));
(action(T0,clockWise) , dir(T0,north));
(action(T0,counterClockWise), dir(T0,south))
).
dir(T1,south) :-
T0 is T1 - 1,
(
((action(T0,eat);action(T0,attack);action(T0,forward)), dir(T0,south));
(action(T0,clockWise) , dir(T0,east));
(action(T0,counterClockWise), dir(T0,west))
).
dir(T1,west) :-
T0 is T1 - 1,
(
((action(T0,eat);action(T0,attack);action(T0,forward)), dir(T0,west) );
(action(T0,clockWise) , dir(T0,south));
(action(T0,counterClockWise), dir(T0,north))
).
findWhenBumped(BumpedTimeList) :- findall(T_prime ,(bump(T), T_prime is T -1),BumpedTimeList).
test(X,List):- findall(X,X,List).
/* Wall variables related */
isWall(T,R,C):-
isWall(R,C).
isWall(X,Y):- % change in Q1
(X =:= 0;
Y =:= 0);
(
findWhenBumped(BumpedTimeList),
findall( [T, R, C], ( location(T, R, C), member(T, BumpedTimeList) ), BumpedPosList),
maplist(peek_location, BumpedPosList, WallPosList ),
member([X,Y],WallPosList)
).
isClear(T,R,C) :- % change in Q1
hasNotEnemy(T,R,C),
hasNotPit(T,R,C),
not(isWall(R,C)).
bump(-1).
hasNotEnemy(T,X,Y). % change in Q2
hasNotPit(-1,X,Y). % change in Q2
hasPit(-1,X,Y). % change in Q3
hasEnemy(-1,X,Y). % change in Q3
hasDeadEnemy(-1,X,Y). % change in Q3
hasFood(-1,X,Y). % change in Q4
hasNotFood(T,X,Y). % change in Q4
isWall(-1,-1).
isWall(-1,-1,-1).
location(1,1,1).
dir(1,east).
Line below fails,
findall( [T, R, C], ( location(T, R, C), member(T, BumpedTimeList) ), BumpedPosList)
What I want to do is to find time instances where bump() is true and find the corresponding location() for that time instance. When I delete the location definition at top and only have the facts, it works. I am completely new to Prolog so please be as specific as you can.
Thanks all in advance.

Prolog test is always true var(sum) error

I am trying to compile a SWI-Prolog program but keep getting test is always true, var (sum) error on line 7. I cant figure out what this means. Can someone please help? This is a program I am hoping will eventually solve Latin squares. Thank you.
:- use_module(library(clpfd)).
magic_counter(Count) :-
findall(a, magic_1(_Soln), As),
length(As, Count).
magic_1(Soln) :-
Row1 = [W1, W2, W3],
Row2 = [X1, X2, X3],
Row3 = [Y1, Y2, Y3],
Row1 ins 1..3,
Row2 ins 1..3,
Row3 ins 1..3,
Sum #= 6,
all_different(Row1),
all_different(Row2),
all_different(Row3),
all_different([W1,X1,Y1]),
all_different([W2,X2,Y2]),
all_different([W3,X3,Y3]),
W1 + W2 + W3 #= Sum,
X1 + X2 + X3 #= Sum,
Y1 + Y2 + Y3 #= Sum,
W1 + X1 + Y1 #= Sum,
W2 + X2 + Y2 #= Sum,
W3 + X3 + Y3 #= Sum,
append(Row1,Row2,Row12),
append(Row12,Row3,Soln),
labeling([], Soln).
It's a warning, not an error.
I posted some time again a request on SWI-Prolog mailing list for this problem, since some existing code begun to raise this warning after a refinement to messages. Here is the answer from Jan.
I think you can ignore the warning, or disable it, but this seems not advisable.
If a row consists of three integers between 1 and 3, and these integers must be distinct, then the sum of such a row must be 6 (by definition). Stating that the sum of such a row equals 6 is therefore an idle constraint. The same reasoning applies to the 'columns' for which you assert similar disjointness constraints.
Edit: Even though the above reasoning is correct, this is not the origin of the warning. Carlo is right on this, it simply depends on the way in which the constraint library rewrites the constraints.
test1:-
L = [X],
L ins 1..2,
Y #= 2,
X #= Y.
test2:-
L = [X],
L ins 1..2,
X #= 2.
test1/0 gives the warning, test2/0 does not. Still, I find it difficult to see why the warning is given in the first place, i.e. what the rational behind it is. For example, here is the expansion of test1/0 (notice my comments):
:- use_module(library(clpfd)).
test1:-
A=[D],
A ins 1..2,
(
integer(B)
->
(
var(2)
->
2 is B
;
true
->
B=:=2
;
C is B,
clpfd:clpfd_equal(C, 2)
)
;
true
->
(
var(B) % This does not throw a warning.
->
B is 2
;
C is 2,
clpfd:clpfd_equal(B, C)
)
;
clpfd:clpfd_equal(B, 2)
),
(
integer(D)
->
(
var(B) % This throws a "Test is always true" warning.
->
B is D
;
integer(B)
->
D=:=B
;
E is D,
clpfd:clpfd_equal(E, B)
)
;
integer(B)
->
(
var(D)
->
D is B
;
E is B,
clpfd:clpfd_equal(D, E)
)
;
clpfd:clpfd_equal(D, B)
).

Resources