I'm new to prolog an I try to implement a function that gives me a list of primes in an specific range (from A to B). Here is my code:
%ending recursion
prime_list(A,A,[A]) :- is_prime(A).
prime_list(A,A,[]) :- not(is_prime(A)).
% if A is prime:
prime_list(A,B,[H|T]) :-
N1 is A+1, H is A, is_prime(A), prime_list(N1,B,T).
% if A is not prime:
prime_list(A,B,[H|T]) :-
N1 is A+1, not(is_prime(A)), prime_list(N1,B,[H|T]).
as long as B is smaler then 9 it works. So for example
prime_list(1,8,X).
gives me
X = [2, 3, 5, 7]
but for B bigger than 8 Prolog doesn't terminate and seems to be stuck in an endless loop. Can someone explain me why my approach is not working?
I'm pretty sure that my "is_prime" -function works, because I've tested it with many values. But to be on the safe side, I'll put it here too:
is_prime_help(X,I) :-
(not(I is 1), 0 is mod(X,I));
(not(I is 1), N1 is I-1, is_prime_help(X, N1)).
is_prime(X) :- not(X is 1), N1 is X-1, not(is_prime_help(X,N1)).
In the last clause, you should replace both [H|T] by just T. Otherwise, this assumes that at least a prime must come after. So what you would hope to be the last recursive call looks like prime_list(9,9,[H|T]) and the two first clauses never match and it never ends...
Here is my code.
equals2(X,Y,N,I):- X is Y,I is N+1; I is N.
elemNum(X,[],0).
elemNum(X,[Y|Ys],N) :- elemNum(X,Ys,N1),equals2(X,Y,N1,I),N is I.
lemNum first argument is element from array, second is array. It counts the number of elements in array.
Then in console
| ?- elemNum(1,[1,2,3,1,1],N),N<2.
N = 1 ?
yes
I am sure than my function elemNum works just fine. How its possible that in console this assertion returns 1?
Thanks for help
Non sure to understand what do you want ... but I suppose that you want count the number of element in the list (second argument of elemNum/3) that are equals to the first argument.
If so, you should modify equals2/4 as follows
equals2(X,Y,N,I):- X is Y,I is N+1; X \== Y, I is N.
or better (IMHO) split it in 2 different clauses
equals2(X,X,N,I):- I is N+1.
equals2(X,Y,N,N):- X \== Y.
With your equal2/4, the second or case (I is N) is executed (in backtracking) even when X is equal to Y so elemNum(1,[1,2,3,1,1],N) unifiy N with 3, 2, 2 again, 1, 2, 1, 1 again and 0.
Regarding elemNum/3, works but you can semplify it (avoiding a warning) as
elemNum(_,[],0).
elemNum(X,[Y|Ys],I) :- elemNum(X,Ys,N1), equals2(X,Y,N1,I).
or you can rewrite it, avoiding the use of equals2/4 as
elemNum(_, [], 0).
elemNum(X, [X | Ys], I) :- elemNum(X, Ys, I0), I is I0+1.
elemNum(X, [Y | Ys], I) :- X \== Y, elemNum(X, Ys, I).
I was just introduced to Prolog and am trying to write a predicate that finds the Max value of a list of integers. I need to write one that compares from the beginning and the other that compares from the end. So far, I have:
max2([],R).
max2([X|Xs], R):- X > R, max2(Xs, X).
max2([X|Xs], R):- X <= R, max2(Xs, R).
I realize that R hasn't been initiated yet, so it's unable to make the comparison. Do i need 3 arguments in order to complete this?
my_max([], R, R). %end
my_max([X|Xs], WK, R):- X > WK, my_max(Xs, X, R). %WK is Carry about
my_max([X|Xs], WK, R):- X =< WK, my_max(Xs, WK, R).
my_max([X|Xs], R):- my_max(Xs, X, R). %start
other way
%max of list
max_l([X],X) :- !, true.
%max_l([X],X). %unuse cut
%max_l([X],X):- false.
max_l([X|Xs], M):- max_l(Xs, M), M >= X.
max_l([X|Xs], X):- max_l(Xs, M), X > M.
Ignoring the homework constraints about starting from the beginning or the end, the proper way to implement a predicate that gets the numeric maximum is as follows:
list_max([P|T], O) :- list_max(T, P, O).
list_max([], P, P).
list_max([H|T], P, O) :-
( H > P
-> list_max(T, H, O)
; list_max(T, P, O)).
A very simple approach (which starts from the beginning) is the following:
maxlist([],0).
maxlist([Head|Tail],Max) :-
maxlist(Tail,TailMax),
Head > TailMax,
Max is Head.
maxlist([Head|Tail],Max) :-
maxlist(Tail,TailMax),
Head =< TailMax,
Max is TailMax.
As you said, you must have the variables instantiated if you want to evaluate an arithmetic expression. To solve this, first you have to make the recursive call, and then you compare.
Hope it helps!
As an alternative to BLUEPIXY' answer, SWI-Prolog has a builtin predicate, max_list/2, that does the search for you. You could also consider a slower method, IMO useful to gain familiarity with more builtins and nondeterminism (and then backtracking):
slow_max(L, Max) :-
select(Max, L, Rest), \+ (member(E, Rest), E > Max).
yields
2 ?- slow_max([1,2,3,4,5,6,10,7,8],X).
X = 10 ;
false.
3 ?- slow_max([1,2,10,3,4,5,6,10,7,8],X).
X = 10 ;
X = 10 ;
false.
edit
Note you don't strictly need three arguments, but just to have properly instantiated variables to carry out the comparison. Then you can 'reverse' the flow of values:
max2([R], R).
max2([X|Xs], R):- max2(Xs, T), (X > T -> R = X ; R = T).
again, this is slower than the three arguments loops, suggested in other answers, because it will defeat 'tail recursion optimization'. Also, it does just find one of the maxima:
2 ?- max2([1,2,3,10,5,10,6],X).
X = 10 ;
false.
Here's how to do it with lambda expressions and meta-predicate foldl/4, and, optionally, clpfd:
:- use_module([library(lambda),library(apply),library(clpfd)]).
numbers_max([Z|Zs],Max) :- foldl(\X^S^M^(M is max(X,S)),Zs,Z,Max).
fdvars_max( [Z|Zs],Max) :- foldl(\X^S^M^(M #= max(X,S)),Zs,Z,Max).
Let's run some queries!
?- numbers_max([1,4,2,3],M). % integers: all are distinct
M = 4. % succeeds deterministically
?- fdvars_max( [1,4,2,3],M).
M = 4. % succeeds deterministically
?- numbers_max([1,4,2,3,4],M). % integers: M occurs twice
M = 4. % succeeds deterministically
?- fdvars_max( [1,4,2,3,4],M).
M = 4. % succeeds deterministically
What if the list is empty?
?- numbers_max([],M).
false.
?- fdvars_max( [],M).
false.
At last, some queries showing differences between numbers_max/2 and fdvars_max/2:
?- numbers_max([1,2,3,10.0],M). % ints + float
M = 10.0.
?- fdvars_max( [1,2,3,10.0],M). % ints + float
ERROR: Domain error: `clpfd_expression' expected, found `10.0'
?- numbers_max([A,B,C],M). % more general use
ERROR: is/2: Arguments are not sufficiently instantiated
?- fdvars_max( [A,B,C],M).
M#>=_X, M#>=C, M#=max(C,_X), _X#>=A, _X#>=B, _X#=max(B,A). % residual goals
list_max([L|Ls], Max) :- foldl(num_num_max, Ls, L, Max).
num_num_max(X, Y, Max) :- Max is max(X, Y).
%Query will be
?-list_max([4,12,5,3,8,90,10,11],Max).
Max=90
Right now I was working with recursion in Prolog, so if it is useful for someone I will leave 'my two cents' solving it in the two ways that I have thought:
% Start
start :- max_trad([2, 4, 6, 0, 5], MaxNumber1),
max_tail([2, 4, 6, 0, 5], 0, MaxNumber2),
show_results(MaxNumber1, MaxNumber2).
% Traditional Recursion (Method 1)
max_trad([Head|Tail], Max) :- max_trad(Tail, Value), Head > Value, Max is Head.
max_trad([Head|Tail], Max) :- max_trad(Tail, Value), Head =< Value, Max is Value.
max_trad([], 0).
% Tail Recursion (Method 2)
max_tail([], PartialMax, PartialMax).
max_tail([Head|Tail], PartialMax, FinalMax) :- Head > PartialMax, max_tail(Tail, Head, FinalMax).
max_tail([_|Tail], PartialMax, FinalMax) :- max_tail(Tail, PartialMax, FinalMax).
% Show both of the results
show_results(MaxNumber1, MaxNumber2) :-
write("The max value (obtained with traditional recursion) is: "), writeln(MaxNumber1),
write("The max value (obtained with tail recursion) is: "), writeln(MaxNumber2).
The output of the above code is:
Both methods are similar, the difference is that in the second an auxiliary variable is used in the recursion to pass values forward, while in the first method, although we have one less variable, we are filling the Stack with instructions to be executed later, so if it were an exaggeratedly large list, the second method is appropriate.
maximum_no([],Max):-
write("Maximum No From the List is:: ",Max).
maximum_no([H|T],Max):-
H>Max,
N = H,
maximum_no(T,N).
maximum_no(L,Max):-
maximum_no(L,Max).
The maximum number in a list in Prolog ?
max([],A):-print(A),!.
max([Head | Tail] , A):-A =< Head ,A1 is Head , max(Tail,A1) ; max(Tail,A).
max(L,M):-
member(M,L),
findall(X,(member(X,L),X>M),NL),
length(NL,0).
I am trying to calculate the Fibonacci series using the following function:
fib(0,A,_,A).
fib(N,A,B,F) :-
N1 is N-1, Sum is A+B, fib(N1, B, Sum, F).
fib(N, F) :- fib(N, 0, 1, F).
This is intended to works like this:
| ?- fib(20,Result).
Result = 6765 ?
But when I try this, it complains:
| ?- fib(What,6765).
uncaught exception: error(instantiation_error,(is)/2)
Does anyone understand why this is happening?
In the second clause:
fib(N,A,B,F) :-
N1 is N-1, Sum is A+B, fib(N1, B, Sum, F).
N is a variable to be decremented, and in your call to:
fib(What, 6765).
The variable is not yet defined, so you get the instantiation error on N1 is N - 1.
In swipl I do even get the error:
?- fib(W, 6765).
ERROR: fib/4: Arguments are not sufficiently instantiated
Now that you know it's an error, do you mind to know if it's actually possible to answer your query?
How do you would approach the problem? Your function it's ok, isn't it? Exactly, because it's a function, and not a relation, you get the error.
It's a bit complicate to solve it, but CLP can do !
See this fascinating example from CLP(FD) documentation (cited here)
:- use_module(library(clpfd)).
n_factorial(0, 1).
n_factorial(N, F) :-
N #> 0, N1 #= N - 1, F #= N * F1,
n_factorial(N1, F1).
We need something like this, but for fibonacci.
See how easy it is:
:- [library(clpfd)].
fib(0,A,_,A).
fib(N,A,B,F) :-
N #> 0,
N1 #= N-1,
Sum #= A+B,
fib(N1, B, Sum, F).
fib(N, F) :- fib(N, 0, 1, F).
i.e. replace is/2 by #=/2 and we get
?- fib(20,Result).
Result = 6765 .
?- fib(X,6765).
X = 20 ;
^C
note, after the first response the program loops!
Do you a see a way to correct it? Or another question could be worth...
A more clear and more natural predicate definition may be:
//The two base steps
fib1(0,0).
fib1(1,1).
//the recursive step
fib1(N,F) :-
N >= 0, M is N-2, O is N-1, fib1(M,A), fib1(O,B), F is A+B.
It is also a definition with only one predicate: fib/2