Prolog findall - Arguments are not sufficiently instantiated - prolog

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.

Related

Prolog finding target number in a list by applying operations (+,-,/,*)

The task is to find if there exists at least one combination of numbers from given list and operators to obtain target number. No usemodule allowed
numbers([3,4,1,2], 7) → true. (cause 4 + 3 = 7)
numbers([1,7,7,3], 24) → true. (cause (7 - 3) * (7 - 1) = 24)
Tried member if target is already in the list. But lost further
Building upon https://professor-fish.blogspot.com/2009/11/countdown-with-prolog.html
solve_countdown(Ns, SumWanted, TsUniq) :-
findall(T, (
any_comb(Ns, Sub),
num_combs(Sub, T),
SumWanted is T
), Ts),
sort(Ts, TsUniq).
any_comb(_, []).
any_comb([H|T], [E|Comb]) :-
select(E, [H|T], Lst0),
any_comb(Lst0, Comb).
num_combs([N], N).
num_combs(As, T) :-
split_list_in_2(As, As1, As2),
num_combs(As1, T1),
num_combs(As2, T2),
% Break symmetry, since 5+2 is same as 2+5
( T1 #=< T2,
( T = T1 + T2
; T1 > 1, T = T1 * T2
)
; T = T1 - T2
; T = T1 / T2
),
R is T,
integer(R),
R #> 0.
split_list_in_2([H1, H2|T], [H1|Start], Remainder) :-
split_list_in_2_(T, H2, Start, Remainder).
split_list_in_2_(L, H2, [], [H2|L]).
split_list_in_2_([H|T], H2, [H2|Start], Remainder) :-
split_list_in_2_(T, H, Start, Remainder).
Result in swi-prolog:
?- time(solve_countdown([1,7,7,3], 24, Ts)).
% 10,996 inferences, 0.002 CPU in 0.002 seconds (99% CPU, 5236642 Lips)
Ts = [3*(1+7), (7-1)*(7-3)].
select/3 code is here.
Squeezing the lemon. I get a slightly faster version.
The logic replicates this paper:
https://www.cs.nott.ac.uk/~pszgmh/countdown.pdf
But adds forward checking:
% solve(+Integer, -Term, +Integer, +List, -List)
solve(1, N, N, P, Q) :- !, select(N, P, Q).
solve(K, G, N, P, Q) :-
J is K-1,
between(1, J, I),
L is K-I,
solve2(I, E, A, P, H),
forward(E, A, F, B, G, N),
solve(L, F, B, H, Q).
forward(E, A, F, B, E+F, N) :- N > A, B is N-A, A =< B.
forward(E, A, F, B, E-F, N) :- A > N, B is A-N.
forward(E, A, F, B, E*F, N) :- N mod A =:= 0, B is N div A, A =< B, A =\= 1.
forward(E, A, F, B, E/F, N) :- A mod N =:= 0, B is A div N, B =\= 1.
% solve2(+Integer, -Term, -Integer, +List, -List)
solve2(1, N, N, P, Q) :- !, select(N, P, Q).
solve2(K, G, N, P, Q) :-
J is K-1,
between(1, J, I),
L is K-I,
solve2(I, E, A, P, H),
solve2(L, F, B, H, Q),
combine(E, A, F, B, G, N).
combine(E, A, F, B, E+F, N) :- A =< B, N is A+B.
combine(E, A, F, B, E-F, N) :- A > B, N is A-B.
combine(E, A, F, B, E*F, N) :- A =< B, A =\= 1, N is A*B.
combine(E, A, F, B, E/F, N) :- B =\= 1, A mod B =:= 0, N is A div B.
Example run with SWI-Prolog 9.1.4:
% time((between(1,6,N), solve(N, E, 999, [1,3,5,10,25,50], _), fail; true)).
% % 2,618,953 inferences, 0.234 CPU in 0.242 seconds (97% CPU, 11174199 Lips)
% true.

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.

Calculating Cousin Relationship in Prolog

I am trying to calculate cousin relationship in the format P'th cousin Qth removed. For example, In this picture below,
Thomas and Zack are cousins twice removed.
Thomas and Nikolay are second cousins once removed
Thomas and Saul are third cousins zero'th removed
So far I have a code like this that, finds the cousins:
ancestor(X,Z):-parent(X,Z).
ancestor(X,Z):-parent(X,Y), ancestor(Y,Z).
cousins(Child1, Child2) :-
ancestor(Y1,Child1),
ancestor(Y1,Child2),
Child1 \= Child2.
My logic is as long as Child1 and Child2 shares a common ancestor they are cousins.
The issue I am having is in trying to find out whether they are first cousins, or second cousins, or third cousins etc and whether they are once removed, twice removed, or thrice removed.
Any suggestion or hints on how I could solve this problem would be greatly helpful.
Thanks!
I think I got this right.
You will need the CLP(FD) library to make this work.
Simply write :- use_module(library(clpfd)). at the beginning of your program.
cousins_nth_removed/4
The first two arguments are atoms representing the persons' names. The third argument (in [1,sup)) represents the first/second/third/... cousins relationship, while the fourth argument (in [0,sup)) represents the zeroth/once/twice/... removed relationship
cousins_nth_removed(C1, C2, 1, 0) :- % First cousins, zeroth removed
dif(C1, C2),
dif(P1, P2), % They have different parents
parent_child(P1, C1),
parent_child(P2, C2),
parent_child(GP, P1), % Their parents have the same parent GP
parent_child(GP, P2).
cousins_nth_removed(C1, C2, N, 0) :- % Nth cousins, zeroth removed
N #> 1,
dif(C1, C2),
children_removed_ancestor(C1, C2, R, R), % They are both R generations away from
dif(P1, P2), % their oldest common ancestor
parent_child(P1, C1),
parent_child(P2, C2),
M #= N - 1, % Their parents are N-1th cousins
cousins_nth_removed(P1, P2, M, 0). % zeroth removed
cousins_nth_removed(C1, C2, N, R) :- % Nth cousins, Rth removed
R #> 0,
dif(C1, C2),
children_removed_ancestor(C1, C2, R1, R2), % R is the difference of the distances
R #= abs(R2 - R1), % between each cousin and their oldest
S #= R - 1, % common ancestor
( R1 #= R2, % R = 0 -> Zeroth removed, second rule
cousins_nth_removed(C1, C2, N, 0)
; R1 #> R2, % C1 is younger than C2
parent_child(P1, C1), % -> C2 is Nth cousin R-1th removed
cousins_nth_removed(P1, C2, N, S) % with the parent of C1
; R1 #< R2, % C2 is younger than C1
parent_child(P2, C2), % -> C1 is Nth cousin R-1th removed
cousins_nth_removed(C1, P2, N, S) % with the parent of C2
).
children_removed_ancestor/4
The name isn't ideal, but this predicate is basically used to retrieve the generation gaps of two persons to their oldest common ancestor.
children_removed_ancestor(C1, C2, R1, R2) :-
child_removed_oldest_ancestor(C1, R1, A),
child_removed_oldest_ancestor(C2, R2, A).
child_removed_oldest_ancestor/3
This predicate retrieves the generation gap between a person and their oldest ancestor.
child_removed_oldest_ancestor(C, 0, C) :- % The ancestor of all
\+ parent_child(_, C). % They have no parent
child_removed_oldest_ancestor(C, N, A) :-
N #> 0,
parent_child(P, C),
M #= N - 1,
child_removed_oldest_ancestor(P, M, A).
Some queries
?- cousins_nth_removed(thomas, zack, N, R). % Your example
N = 1,
R = 2 ;
false.
?- cousins_nth_removed(thomas, nikolay, N, R). % Your example
N = 2,
R = 1 ;
false.
?- cousins_nth_removed(thomas, saul, N, R). % Your example
N = 3,
R = 0 ;
false.
?- cousins_nth_removed(thomas, C, N, R). % All cousins of thomas
C = farah,
N = 1,
R = 0 ;
C = ping,
N = 2,
R = 0 ;
C = william,
N = 3,
R = 0 ;
C = saul,
N = 3,
R = 0 ;
C = sean,
N = R, R = 1 ;
C = steven,
N = R, R = 1 ;
C = zack,
N = 1,
R = 2 ;
C = kyle,
N = 2,
R = 1 ;
C = nikolay,
N = 2,
R = 1 ;
C = wei,
N = 2,
R = 1 ;
false.
?- cousins_nth_removed(C1, C2, 3, 0). % All third cousins zeroth removed
C1 = ping,
C2 = william ;
C1 = ping,
C2 = saul ;
C1 = farah,
C2 = william ;
C1 = farah,
C2 = saul ;
C1 = ignat,
C2 = william ;
C1 = ignat,
C2 = saul ;
C1 = thomas,
C2 = william ;
C1 = thomas,
C2 = saul ;
C1 = william,
C2 = ping ;
C1 = william,
C2 = farah ;
C1 = william,
C2 = ignat ;
C1 = william,
C2 = thomas ;
C1 = saul,
C2 = ping ;
C1 = saul,
C2 = farah ;
C1 = saul,
C2 = ignat ;
C1 = saul,
C2 = thomas ;
false.
Overall program
:- use_module(library(clpfd)).
parent_child(leila,min).
parent_child(leila,seema).
parent_child(min,ali).
parent_child(min,jesse).
parent_child(min,john).
parent_child(ali,sean).
parent_child(ali,steven).
parent_child(sean,ping).
parent_child(jesse,dallas).
parent_child(jesse,mustafa).
parent_child(dallas,farah).
parent_child(mustafa,ignat).
parent_child(mustafa,thomas).
parent_child(seema,zack).
parent_child(zack,kyle).
parent_child(zack,nikolay).
parent_child(zack,wei).
parent_child(kyle,william).
parent_child(nikolay,saul).
cousins_nth_removed(C1, C2, 1, 0) :-
dif(C1, C2),
dif(P1, P2),
parent_child(P1, C1),
parent_child(P2, C2),
parent_child(GP, P1),
parent_child(GP, P2).
cousins_nth_removed(C1, C2, N, 0) :-
N #> 1,
dif(C1, C2),
children_removed_ancestor(C1, C2, R, R),
dif(P1, P2),
parent_child(P1, C1),
parent_child(P2, C2),
M #= N - 1,
cousins_nth_removed(P1, P2, M, 0).
cousins_nth_removed(C1, C2, N, R) :-
R #> 0,
dif(C1, C2),
children_removed_ancestor(C1, C2, R1, R2),
R #= abs(R2 - R1),
S #= R - 1,
( R1 #= R2,
cousins_nth_removed(C1, C2, N, 0)
; R1 #> R2,
parent_child(P1, C1),
cousins_nth_removed(P1, C2, N, S)
; R1 #< R2,
parent_child(P2, C2),
cousins_nth_removed(C1, P2, N, S)
).
children_removed_ancestor(C1, C2, R1, R2) :-
child_removed_oldest_ancestor(C1, R1, A),
child_removed_oldest_ancestor(C2, R2, A).
child_removed_oldest_ancestor(C, 0, C) :-
\+ parent_child(_, C).
child_removed_oldest_ancestor(C, N, A) :-
N #> 0,
parent_child(P, C),
M #= N - 1,
child_removed_oldest_ancestor(P, M, A).
I now hate genealogical trees.

prolog compare paragraph

triangle_area(triangle(point(X1,Y1),point(X2,Y2),H),S):-
M1 is ((X1 - X2)*(X1 - X2)),
N1 is ((Y1 - Y2)*(Y1 - Y2)),
O1 is (M1 + N1),
R1 is (sqrt(O1)),
S is (H*R1).
compare_tri(triangle(point(X1,Y1),point(X2,Y2),H1), triangle(point(X3,Y3),point(X4,Y4),H2)):-
triangle_area(triangle(point(X1,Y1), point(X2,Y2), H1), S1),
triangle_area(triangle(point(X3,Y3), point(X4,Y4), H2), S2),
( (S1 < S2) -> (S1 is 2), (S2 is 1)
; (S2 is 1), (S1 is 2)),
write('Triangle '),
write(S1),
write(' is bigger than Triangle'),
write(S2),
write('.').
compare_tri(triangle(point(0,0),point(2,0),4),triangle(point(0,0),point(3,0),3).
I expected 'Triangle 2 is bigger than Triangle 1.'
But it's didn't work.
It just tell me like this.
ERROR: Syntax error: Operator expected
ERROR: compare_tri(triangle(point(0,0),point(2,0),4),triangle(point(0,0),point(3,0),3)
ERROR: ** here **
ERROR: .
What is the problem?
The first problem is that you miss a close parenthesis on the query.
?- compare_tri(triangle(point(0,0),point(2,0),4),triangle(point(0,0),point(3,0),3)).
The second one is that you as assigning to S1 and S2, that are already bound to the area. Here is a correction:
compare_tri(triangle(point(X1,Y1),point(X2,Y2),H1),triangle(point(X3,Y3),point(X4,Y4),H2)):-
triangle_area(triangle(point(X1,Y1),point(X2,Y2),H1),S1),
triangle_area(triangle(point(X3,Y3),point(X4,Y4),H2),S2),
( (S1<S2) -> (T1,T2) = (2,1) ; (T1,T2) = (1,2) ),
write('Triangle '),
write(T1),
write(' is bigger than Triangle'),
write(T2),
write('.').
If you break things up into smaller discrete pieces, it gets easier to understand, as well as to test and debug things and identify problems, something like this:
triangle_area( triangle(P1,P2,H) , S ) :-
distance(P1,P2,B) ,
A is B*H/2.0
.
distance(point(X1,Y1),point(X2,Y2),L) :-
Dx is X2-X1 ,
Dy is Y2-Y1 ,
Dx2 is Dx*Dx ,
Dy2 is Dy*Dy ,
L is sqrt(Dx2+Dy2)
.
compare_tri( T1, T2 ) :-
triangle_area(T1, Area1),
triangle_area(T2, Area2),
compare(Op,Area1,Area2) ,
log_results( Op, T1, T2 )
.
log_results( '>',T1,T2 ) :-
write(T1),
write(' is larger than '),
write(T2),
nl
.
log_results( '<',T1,T2 ) :-
write(T2),
write(' is larger than '),
write(T1),
nl
.
log_results( '=',T1,T2 ) :-
write(T1),
write(' is the same size as '),
write(T2),
nl
.

Rule to calculate power of a number when the exponent is Negative in Prolog?

I have a power function pow that attempts to calculate the value of B to the power of E. So far I handle the cases-
1. exponent is 0
2. exponent is non-zero
pow(B,0,1).
pow(B,E,Result):- E2 is E - 1,
pow(B,E2,Result2),
Result is B*Result2.
How can I add another case where the power function can handle negative exponents?
First, one should consider how to define 00. Formally speaking it is indeterminate. It could be zero or it could be 1. As Wolfram's Mathworld says in its article on powers and in its article on zero:
00 (zero to the zeroth power) itself is undefined. The lack of a well-defined meaning for this quantity follows from the mutually contradictory facts that a0 is always 1, so 00 should equal 1, but 0a is always 0 (for a > 0), so 0a should equal 0. The choice of definition for 00 is usually defined to be indeterminate, although defining 00 = 1 allows some formulas to be expressed simply (Knuth 1992; Knuth 1997, p. 57).
So you should first choose how to define the special case of 00: Is it 0? Is it 1? Is it undefined?
I choose to look at it as being undefined.
That being said, you can look at a positive exponent as indicated repeated multiplication (e.g. 103 is 10*10*10, or 1,000), and you can look at a negative exponent as indicating repeated division (e.g, 10-3 is (((1/10)/10)/10), or 0.001). My inclination, partly because I like the symmetry of this approach and partly to avoid the cuts (since a cut is often a signal that you've not defined the solution properly), would be something like this:
% -----------------------------
% The external/public predicate
% -----------------------------
pow( 0 , 0 , _ ) :- ! , fail .
pow( X , N , R ) :-
pow( X , N , 1 , R )
.
% -----------------------------------
% the tail-recursive worker predicate
% -----------------------------------
pow( _ , 0 , R , R ).
pow( X , N , T , R ) :-
N > 0 ,
T1 is T * X ,
N1 is N-1 ,
pow( X , N1 , T1 , R )
.
pow( _ , 0 , R , R ) :-
N < 0 ,
T1 is T / X ,
N1 is N+1 ,
pow( X , N1 , T1 , R )
.
The other approach, as others have noted, is to define a positive exponent as indicating repeated multiplication, and a negative exponent as indicating the reciprocal of the positive exponent, so 103 is 10*10*10 or 1,000, and 10-3 is 1/(103), or 1/1,000 or 0.001. To use this definition, I'd again avoid the cuts and do something like this:
% -----------------------------
% the external/public predicate
% -----------------------------
pow( 0 , 0 , _ ) :- % 0^0 is indeterminate. Is it 1? Is it 0? Could be either.
! ,
fail
.
pow( X , N , R ) :-
N > 0 ,
pow( X , N , 1 , R )
.
pow( X , N , R ) :-
N < 0 ,
N1 = - N ,
pow( X , N1 , 1 , R1 ) ,
R is 1 / R1
.
% -----------------------------------
% The tail-recursive worker predicate
% -----------------------------------
pow( _ , 0 , R , R ).
pow( X , N , T , R ) :-
N > 0 ,
T1 is T * X ,
N1 is N-1 ,
pow( X , N1 , T1 , R )
.
Don't forget that a^(2b) = (a^b)^2 and x^2 = x*x. It is ok to call a tail-recursive working predicate with accumulator, in a non-tail fashion, from a top-level "UI" predicate. That way you don't have to implement working predicate for negative powers but rather reuse the one for positive power, and alter its result in the top-level predicate (I see this has already been suggested):
pow(B, E, R):- E<0 -> ... ; E=:=0 -> ... ; E>0 -> ... .
To start, your second clause is non tail recursive (you can read about the subject here). It means that eventually, you will run out of call stack memory when running it.
A good thing would be to use an accumulator to make it tail recursive. You can achieve that as follows :
% we add an accumulator to poW/3, making it pow/4.
pow(B, E, Result) :- pow(B, E, 1, Result).
% when we hit 0, our accumulator holds B^E so we unify it with result.
pow(_, 0, Accu, Accu) :- !.
% at each step, we multiply our accumulator by B
pow(B, E, Accu, Result) :-
NewE is E - 1,
NewAccu is Accu * B,
pow(B, NewE, NewAccu, Result).
Then, you can simply handle the negative case by adding this clause on top of the others (it simply tells prolog that a negative power is the inverse of the positive one) :
pow(B, E, Result) :-
E < 0,
PositiveE is - E,
pow(B, PositiveE, 1, R),
!,
Result is 1 / R.
Note that you can do it directly with your code :
pow(B, E, Result) :-
E < 0,
PositiveE is - E,
pow(B, PositiveE, R),
!,
Result is 1 / R.
Plus, we now introduced a very red cut (see here for the meaning of red cut if necessary). So it'd be better to turn into a green cut with this modification :
pow(B, E, Result) :-
E < 0,
PositiveE is - E,
pow(B, PositiveE, 1, R),
!,
Result is 1 / R.
% we add an accumulator to poW/3, making it pow/4.
pow(B, E, Result) :-
E >= 0, %************* HERE *****************
pow(B, E, 1, Result).
% when we hit 0, our accumulator holds B^E so we unify it with result.
pow(_, 0, Accu, Accu) :- !.
% at each step, we multiply our accumulator by B
pow(B, E, Accu, Result) :-
NewE is E - 1,
NewAccu is Accu * B,
pow(B, NewE, NewAccu, Result).

Resources