Prolog: Decrementing variable in argument - prolog

I am new to Prolog and was tasked with a Fibonnaci predicate fib( N, F) where N is the number in sequence, and F is the value. What I came up with does not work, but the solution I found seems identical to me... I cannot understand the difference.
My version:
/* MY VERSION, DOES NOT WORK */
fib( 0, 0).
fib( 1, 1).
fib(N,F) :-
N > 1,
fib(N-1,F1),
fib(N-2,F2),
plus(F1,F2,F).
The working version:
/* FOUND SOLUTION, DOES WORK */
fib( 0, 0).
fib( 1, 1).
fib(N,F) :-
N > 1,
N1 is N-1,
N2 is N-2,
fib(N1,F1),
fib(N2,F2),
plus(F1,F2,F).
Obviously the problem has something to do with me using "N-1" and "N-2" as arguments rather than assigning those values to new variables first. But I don't get it... because in other recursive Prolog codes, I have successfully done just that (decremented a variable right in the argument slot). Does this make sense?
Thanks!
Below is an example where the "N-1" did work.
line( N, _, _) :-
N =:= 0.
line( N, M, Char) :-
N > 0,
N mod M =\= 1,
write( Char), write( ' '),
line( N-1, M, Char).
line( N, M, Char) :-
N > 0,
N mod M =:= 1,
write( Char), write( '\n'),
line( N-1, M, Char).
square( N, Char) :-
N > 0,
line( N*N, N, Char).
A new version of fib/2 which also works!
/* NEW VERSION, CHANGED TRIVIAL CASES TO EVALUATE N */
fib( N, 0) :-
N =:= 0.
fib( N, 1).
N =:= 1.
fib(N,F) :-
N > 1,
fib(N-1,F1),
fib(N-2,F2),
plus(F1,F2,F).

In prolog,
1 - 2
Doesn't actually do any arithmetic (I know, right?), it creates a structure:
-(1, 2)
And is is a predicate that evaluates that structure:
is(X, -(1, 2))
Will unify X with -1.
Also apparently < and > (and those like it) are like is in that they evaluate expressions.
So that means that the difference between your fib predicate and your line predicate is that
fib(0, 0).
is using unification, ie, testing whether the terms themselves are equal:
foo(0).
?- foo(1 - 1).
false
Whereas a test like =:= tests for numerical equality:
foo(X) :- X =:= 0.
?- foo(1 - 1).
yes

I'd probably write the predicate somthing like the following.
fib/2 is the outer 'public' interface. N is the position in the sequence (zero-relative). F gets unified with the value of the Fibonacci sequence at that position.
fibonacci/5 is the inner 'core' that does the work.
The 1st argument is the counter
The 2nd argument is the limit
The 3rd/4th arguments are the sliding frame required to compute the next item in the sequence. It should be noted that there is not required for a Fibonacci sequence start start with { 1 , 1 }. Any two integers will do.
The 5th argument gets unified with the desired result.
Each clause in the core works as follows:
If N is 0, F is unified with '1'.
If N is 1, F is unified with '1'.
If the limit has been reached, we're done. Unify F with the sum of the preceding two elements in the sequence.
If counter is less than the limit, compute the next element in the sequence and recurse, sliding the oldest value out from the sliding window.
Here's the code:
fib( N , F ) :-
N >= 0 ,
fibonnaci( 0 , N , 1 , 1 , F ).
fibonacci( 0 , 0 , F , _ , F ).
fibonacci( 1 , 1 , _ , F , F ).
fibonacci( Limit , Limit , X , Y , F ) :-
F is X + Y
.
fibonacci( Current , Limit , X , Y , F ) :-
Current < Limit ,
Next is Current + 1 ,
Z is X + Y ,
fibonacci( Next , Limit , Y , Z , F )
.

Related

Cannot do simple Prolog

I have multiple recursions in Prolog but when i do similar recursion to pow in result block it says:
is/2: Arguments are not sufficiently instantiated.
pow(_,0,1):-!.
pow(X,N,XN):-
N>0,
N1 is N - 1,
pow(X, N1, XN1),
XN is XN1 * X.
result(_,0,_):-!.
result(X, N, Res):-
N2 is N - 1,
N1 is 2*N - 1,
pow(X, N1, Numer),
pow(-1, N2, One),
writeln('before'),
result(X, N2, RS1),
writeln('after'),
writeln('RS1: ' + RS1),
Res is RS1+One*(Numer/N1).
It's probably for the reason that because
result(_,0,_):-!.
is true for any 3rd (and 1st) argument where 2nd one is 0, so in
result(X, N2, RS1)
the RS1 variable cannot be computed when N2 is 0. (It's just like to ask a question to find x when 0 * x = 0 is given, for example.)
If you fix the value for RS1 when N2=0, e.g. using a conditional like this
(N2 =:= 0 -> RS1 is 1; result(X, N2, RS1)),
it will work.
A common pattern in Prolog is the use of helper predicates with an accumulator.
Xn is repeated multiplication. It's shorthand for 1 * X * X ..., repeated n times, correct? And that gives you the prolog predicate you need.
Try something like this:
% ---------------------------------------------------------
% pow/3 — Our public predicate to raise X to the Nth power,
% unifying the result with R
% ---------------------------------------------------------
pow( X , N , R ) :-
pow(X,N,1,R)
.
% --------------------------------------------------------------
% pow/4 — Our private helper predicate
%
% It also raised X to the Nth power, but uses an accumulator, T,
% in which to accumulate the result.
% --------------------------------------------------------------
pow( _ , 0 , R , R ) . % Once we hit the 0th power, we're done: just unify the accumulator with R.
pow( X , N , T , R ) :- % To evaluate X to the Nth power...
N > 0, % 0. For non-negative, integral values of N.
T1 is T * X, % 1. Multiple the accumulator by X
N1 is N-1, % 2. Decrement the power N by 1
pow(X,N1,T1,R) % 3. Recursively evaluate X to the N-1th power
. % Easy!

creating a list in prolog based on an other list

i am a begginer in prolog and i want to write a code that creates a list based on another list.I wrote this :
create([_],N,J,K,J):- N>K.
create([X|Xs],N,L,K,J):- X==N , N1 is N + 1 , create(Xs,N1,[-1|L],K,J).
create([X|Xs],N,L,K,J):-N1 is N + 1 , create([X|Xs],N1,[0|L],K,J).
K is the size of the output list.
N is a counter .
L is the output.
X is the input list.
?- create([1,2],1,[],5,N).
N = [0, 0, 0, 0, -1]
i would like to get a list with size equal to 5(K) filled with zeros except the positions that are specified in the input list on which the value will be -1(I didnt reverse it).
I think your code should be - note the list is built in the head, to avoid reversing)
create(_ ,N,K, []) :- N > K, !.
create([N|Xs],N,K,[-1|L]) :- !, N1 is N + 1, create(Xs,N1,K,L).
create( Xs ,N,K,[ 0|L]) :- N1 is N + 1, create(Xs,N1,K,L).
It requires the zeros positions sorted.
Otherwise, the more idiomatic - and cryptic -
create(Ps, N,K, L) :- findall(D, (
between(N,K,P),
( memberchk(P,Ps) -> D = -1 ; D = 0)), L).
will work regardless the ordering.

Finding the k'th occurence of a given element

I just started in Prolog and have the problem:
(a) Given a list L, an object X, and a positive integer K, it returns
the position of the K-th occurrence of X in L if X appears at least K
times in L otherwise 0.
The goal pos([a,b,c,b],b,2,Z) should succeed with the answer Z = 4.
So far I have:
pos1([],H,K,F).
pos1([H],H,1,F).
pos1([H|T],H,K,F):- NewK is K - 1, pos1(T,H,NewK,F), F is F + 1.
pos1([H|T],X,K,F):- pos1(T,X,K,F).
But I can't figure out why I'm getting:
ERROR: is/2: Arguments are not sufficiently instantiated
Any help would be much appreciated!
Use clpfd!
:- use_module(library(clpfd)).
We define pos/4 based on (#>)/2, (#=)/2, if_/3, dif/3, and (#<)/3:
pos(Xs,E,K,P) :-
K #> 0,
pos_aux(Xs,E,K,1,P).
pos_aux([X|Xs],E,K,P0,P) :-
P0+1 #= P1,
if_(dif(X,E),
pos_aux(Xs,E,K,P1,P),
if_(K #< 2,
P0 = P,
(K0+1 #= K,
pos_aux(Xs,E,K0,P1,P)))).
Sample query as given by the OP:
?- X = b, N = 2, pos([a,b,c,b],X,N,P).
X = b, N = 2, P = 4. % succeeds deterministically
How about the following more general query?
?- pos([a,b,c,b],X,N,P).
X = a, N = 1, P = 1
; X = b, N = 1, P = 2
; X = b, N = 2, P = 4 % (exactly like in above query)
; X = c, N = 1, P = 3
; false.
Let's take a high-level approach to it, trading the efficiency of the resulting code for the ease of development:
pos(L,X,K,P):-
numerate(L,X,LN,1), %// [A1,A2,A3...] -> [A1-1,A2-2,A3-3...], where Ai = X.
( drop1(K,LN,[X-P|_]) -> true ; P=0 ).
Now we just implement the two new predicates. drop1(K,L,L2) drops K-1 elements from L, so we're left with L2:
drop1(K,L2,L2):- K<2, !.
drop1(K,[_|T],L2):- K1 is K-1, drop1(K1,T,L2).
numerate(L,X,LN,I) adds an I-based index to each element of L, but keeps only Xs:
numerate([],_,[],_).
numerate([A|B],X,R,I):- I1 is I+1, ( A=X -> R=[A-I|C] ; R=C ), numerate(B,X,C,I1).
Testing:
5 ?- numerate([1,b,2,b],b,R,1).
R = [b-2, b-4].
6 ?- pos([1,b,2,b],b,2,P).
P = 4.
7 ?- pos([1,b,2,b],b,3,P).
P = 0.
I've corrected your code, without changing the logic, that seems already simple enough.
Just added a 'top level' handler, passing to actual worker pos1/4 and testing if worked, else returning 0 - a debatable way in Prolog, imo is better to allow to fail, I hope you will appreciate how adopting this (see comments) simplified your code...
pos(L,X,K,F):- pos1(L,X,K,F) -> true ; F=0.
% pos1([],H,K,F). useless: let it fail
% pos1([H],H,1,F). useless: already handled immediatly bottom
pos1([H|T],H,K,P):- K==1 -> P=1 ; NewK is K - 1, pos1(T,H,NewK,F), P is F + 1.
pos1([_|T],X,K,P):- pos1(T,X,K,F),P is F+1.
I hope you're allowed to use the if/then/else construct. Anyway, yields
7 ?- pos([a,b,c,b],b,2,Z).
Z = 4.
8 ?- pos([a,b,c,b],b,3,Z).
Z = 0.
Something like this. An outer predicate (this one enforces the specified constraints) that invokes an inner worker predicate:
kth( L , X , K , P ) :-
is_list( L ) , % constraint: L must be a list
nonvar(X) , % constriant: X must be an object
integer(K) , K > 0 % constraint: K must be a positive integer
kth( Ls , X , K , 1 , P ) % invoke the worker predicate with its accumulator seeded to 1
. % easy!
is_list/2 ensures you've got a list:
is_list(X) :- var(X) , !, fail .
is_list([]).
is_list([_|_]).
The predicate that does all the work is this one:
kth( [] , _ , _ , _ , 0 ) . % if we hit the end of the list, P is 0.
kth( [X|Ls] , X , K , K , K ) :- ! . % if we find the Kth desired element, succeed (and cut: we won't find another Kth element)
kth( [_|Ls] , X , K , N , P ) :- % otherwise
N < K , % - if we haven't got to K yet ...
N1 is N+1 , % - increment our accumulator , and
kth(Ls,X,K,N1,P) % - recurse down.
. % easy!
Though the notion of returning 0 instead of failure is Not the Prolog Way, if you ask me.

Beginner - add multiples of 3 and 5

I'm trying to find the sum of all positive multiples of 3 and 5 below 1000. After adding the portion that's supposed to remove the multiples of 3 from the sum of the multiples of 5, gprolog will keep spitting out "No" for the query ?- sigma(1000,N).
The problem apparently lies in sigma5, but I can't quite spot it:
sigma(Num, Result) :- sigma3(Num, 3, Result3),
sigma5(Num, 5, Result5),
Result is Result3 + Result5.
sigma3(Num, A, Result) :- A < Num,
Ax is A+3,
sigma3(Num, Ax, ResultX),
Result is ResultX + A.
sigma3(Num, A, Result) :- A >= Num,
Result is 0.
sigma5(Num, A, Result) :- A < Num,
mod3 is A mod 3,
0 \= mod3,
Ax is A+5,
sigma5(Num, Ax, ResultX),
Result is ResultX + A.
sigma5(Num, A, Result) :- A < Num,
mod3 is A mod 3,
0 == mod3,
Ax is A+5,
sigma5(Num, Ax, ResultX),
Result is ResultX.
sigma5(Num, A, Result) :- A >= Num,
Result is 0.
What's the problem with my code?
As integers are involved, consider using finite domain constraints. For example, with SWI-Prolog:
?- use_module(library(clpfd)).
true.
?- findall(N, (N mod 3 #= 0 #\/ N mod 5 #= 0, N in 0..999, indomain(N)), Ns),
sum(Ns, #=, Sum).
Ns = [0, 3, 5, 6, 9, 10, 12, 15, 18|...],
Sum = 233168.
Prolog has never been popular for it's arithmetic capabilities.
This is due to the need to represent 'term constructors' for symbolic processing, without undue evaluation, so when actual arithmetic is required we must explicitly allocate the 'space' (a variable) for the result, instead that 'passing down' an expression. This lead to rather verbose and unpleasant code.
But using some popular extension, like CLP(FD), available in GProlog as well as SWI-Prolog, we get much better results, not readily available in other languages: namely, a closure of the integer domain over the usual arithmetic operations. For instance, from the SWI-Prolog CLP(FD) library, a 'bidirectional' factorial
n_factorial(0, 1).
n_factorial(N, F) :- N #> 0, N1 #= N - 1, F #= N * F1, n_factorial(N1, F1).
?- n_factorial(X, 3628800).
X = 10 .
Anyway, here is a simple minded solution to the original problem, similar to what you attempted, but using an accumulator to compute result. This simple trick allows writing a tail recursive procedure, that turns out in better efficiency.
sigma(Num, Result) :-
sigma(1, Num, 0, Result).
sigma(N, M, Acc, Tot) :-
( N < M, !,
( (0 is N mod 3 ; 0 is N mod 5)
-> Sum is Acc + N
; Sum is Acc
),
N1 is N + 1,
sigma(N1, M, Sum, Tot)
; Tot is Acc
).
Test:
?- sigma(1000, X).
X = 233168 .
mod3 is A mod 3,
(as well all the other occurrences of mod3) should be Mod3 since it is a variable.
with that fix, the program runs correctly (at least for N=1000)
btw here is my solution (using higher-order predicates):
sum(S):-
findall(X,between(1,999,X),L), % create a list with all numbers between 1 and 999
include(div(3),L,L3), % get the numbers of list L which are divisible by 3
include(div(5),L,L5), % get the numbers of list L which are divisible by 5
append(L3,L5,LF), % merge the two lists
list_to_set(LF,SF), % eliminate double elements
sumlist(SF,S). % find the sum of the members of the list
div(N,M):-
0 is M mod N.
it's less efficient of course but the input is too small to make a noticeable difference
This all seems very complicated to me.
sum_of( L , S ) :-
L > 0 ,
sum_of( 0 , L , 0 , S )
.
sum_of( X , X , S , S ) . % if we hit the upper bound, we're done.
sum_of( X , L , T , S ) :- % if not, look at it.
X < L , % - backtracking once we succeeded.
add_mult35( X , T , T1 ) , % - add any multiple of 3 or 5 to the accumulator
X1 is X + 1 , % - next X
sum_of( X1 , L , T1 , S ) % - recurse
.
add_mult35( X , T , T ) :- % no-op if X is
X mod 3 =\= 0 , % - not a multiple of 3, and
X mod 5 =\= 0 , % - not a multiple of 5
!. %
add_mult35( X , T , T1 ) :- % otherwise,
T1 is T + X % increment the accumulator by X
.
This could be even more concise than it is.
Aside from my code probably being extraordinarily horrible (it's actually longer than my C solution, which is quite a feat on it's own),
ANSI C:
int sum_multiples_of_three_and_five( int lower_bound , int upper_bound )
{
int sum = 0 ;
for ( int i = lower_bound ; i <= upper_bound ; ++i )
{
if ( 0 == i % 3 || 0 == i % 5 )
{
sum += i ;
}
}
return sum ;
}

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