Calculating whether number is prime in Prolog - prolog

I am trying to calculate if the input is a prime number but something goes wrong... here's my code:
primeNumber(X):-
prime_prime(A, 1).
prime_prime(A, B):-
R is A mod B,
R =:= 1,
R =:= A.
prime_prime(X, B):-
B < A,
Next is B + 1,
prime_prime(A, Next).
It gives me false every time. Anyone got any clues or idea on what I am doing wrong?

See http://www.swi-prolog.org/pldoc/man?function=mod/2:
+IntExpr1 mod +IntExpr2
Modulo, defined as Result = IntExpr1 - (IntExpr1 div IntExpr2) × IntExpr2, where div is floored division.
So R should be 0. mod has only one result.
A working solution would be:
primeNumber(A) :-
A > 1, % Negative numbers, 0 and 1 are not prime.
prime_prime(A, 2). % Begin iteration:
prime_prime(A, B) :- % Test if A divides by B without remainder
B >= A % The limit was reached?
-> true % Then it's prime.
; 0 is A mod B % B divides A without a remainder?
-> false % Then it's not prime.
; succ(B, C), % Otherwise: C is B + 1
prime_prime(A, C). % Test if C divides A.
By the way, primeNumber/1 (a predicate named primeNumber, with one argument) is a totally separate predicate from primeNumber/2 (same name, two arguments). A "subfunction" that only gets an extra argument for the start value, is usually given the same name. So instead of prime_prime you should just use primeNumber, though in Prolog you normally don't use camelCase.
Using the optimization that Sergei Lodyagin proposed in the comments:
primeNumber(A) :-
A > 1, % Negative numbers, 0 and 1 are not prime.
sqrt(A, L), % A prime factor of A is =< the square root of A.
prime_prime(A, 2, L). % Begin iteration:
prime_prime(A, B, L) :- % Test if A divides by B without remainder
B >= L % The limit was reached?
-> true % Then it's prime.
; 0 is A mod B % B divides A without a remainder?
-> false % Then it's not prime.
; succ(B, C), % Otherwise: C is B + 1
prime_prime(A, C, L). % Test if C divides A.
And if you use the predefined predicate between(+Low, +High, ?Value):
primeNumber(A) :-
L is floor(sqrt(A)),
\+ (between(2, L, X),
0 is A mod X).
And to reduce the number of iterations even further, you only need to test for odd modules:
primeNumber(2).
primeNumber(A) :-
A > 2,
\+ 0 is A mod 2,
L is floor(sqrt(A) / 2),
\+ (between(1, L, X),
0 is A mod (1 + 2*X)).

Kay already provided a working modification of the broken program. I'll provide a simple analysis of what's broken.
When solving a problem in Prolog, it's good to be able to write out logically what it is you want first. In this case, it appears that you want to declare that:
A number, A, is prime if, for each number B < A, the value of A mod B is non-zero.
There are probably a couple of ways to render this directly into Prolog, of which Kay shows one.
However, the way your original rules are written, they say:
A number, A, is prime if:
(Rule 1) The value of A mod B, for a given value of B, is 1 and is also A.
OR (Rule 2) B < A and Rule 1 is satisfied with A and B+1.
As you can see, the rules as defined have a few issues:
The rules don't match the logical definition of prime described in terms of the modulo relationship between the original number and all the numbers less than itself.
The first rule expects an impossible mathematical condition when A is not equal to 1 (remember, the comma [,] in Prolog is a conjunction)
The rules are initiated with starting divisor of 1, which is probably bad since 1 divides everything and is likely to become an exception to any rules that work
EDIT
Getting back to the first definition of a prime using the modulo operator, we can translate that into Prolog as follows:
is_prime(N) :- % N is prime if...
N > 1, % N > 1, and
non_divisible_from(N, 2). % N is non-divisible by everything from 2 to N-1
non_divisible_from(N, D) :- % N is non-divisible by D through N-1 if...
N =< D. % D >= N
% --OR--
non_divisible_from(N, D) :- % N is non-divisible from D to N-1 if...
N > D, % N > D, and
N mod D =\= 0, % N is non-divisible by D, and
D1 is D + 1, % N is non-divisible by D+1 to N-1
non_divisible_from(N, D1).
This logic is basically the same as Kay's except he's using a Prolog if-then-else construct.

Related

Sum of random digits in Prolog

The scenario is to mimic rolling 3 six-sided die in Prolog while trying to obey the recursive nature of prolog. This is easily done with the Fibonacci series
n_factorial(N, F) :-
N #> 0,
F #= N*F1,
N1 #= N-1,
n_factorial(N1, F1).
I'm having difficulty translating this to the dice paradigm, where we add a random number to the sum.
# N = number of dice, S = number of sides, R = result
roll_dice(N, S, R) :-
N1 #> 0,
R = random_between(1, S, R1),
N1 #= N-1,
roll_dice(N1, S, R1).
throws an error but neglects the sum anyway. I would normally use += in other languages.
A few things not quite right there:
R = random_between(1, S, R1) stores that structure in R, it does not generate random numbers.
R1 is used for "the random number you get for rolling one die" and "the sum of all the random numbers from rolling all the remaining dice" and it is unlikely those will be the same value, and when they isn't the same, that will fail.
There is no code to do the summing. (The equivalent of the Factorial video using F #= N * F1)
No recursive base case (the first line of the factorial from the video is not shown in your question, it is n_factorial(0, 1).). When N dice remaining gets down to 0, there is nothing to handle that case.
Here is one implementation:
:- use_module(library(clpfd)).
roll_dice(0, _, 0).
roll_dice(NDice, Sides, Sum) :-
NDice #> 0,
random_between(1, Sides, Roll),
Sum #= Roll + RunningTotal,
NDiceLeft #= NDice - 1,
roll_dice(NDiceLeft, Sides, RunningTotal).
while trying to obey the recursive nature of Prolog.
I guess that's important to understand; this can be done with less bolierplate and fewer temporary variables to name, e.g.:
roll_dice(NDice, Sides, Sum) :-
length(Rolls, NDice),
maplist(random(1, Sides), Rolls),
sum_list(Rolls, Sum).
which makes a list Rolls the right size to hold all the rolls, fills them in using maplist to apply random on each of them, and sums that list for the answer.
I'd do something along the lines of:
roll(N,S,R) :- positive_int(N), positive_int(S), roller(N,S,0,R) .
positive_int(N) :- integer(N), N > 0 .
roller(0,_,R,R) .
roller(N,S,T,R) :-
T1 is 1+random(S),
N1 is N-1,
roller(N1,S,T1,R)
.

prolog list of all divisors of a number

I want to find all the divisors of a natural number.and output a list.
now my code looks like this:
divisors(0,[]).
divisors(N,[N1|P]):-
N1=N,
RES is (N mod N1),
N1 is N-1,
RES==0,
divisors(N,P).
divisors(N,[N1|P]):-
N1=N,
RES is (N mod N1),
N1 is N-1,
RES\=0,!, fail.
but it doesn't work. tell me, what am I doing wrong?
I've seen what can be done via findall, but I want to do it differently.The idea is as follows. Subtract one from the number (whose divisors we are looking for) each time and if the original number is divided by a new number, then write it to the head of the list.
(I just realized..That I don 't remember N anywhere ..since with recursive calls, it will already be different. I'm completely confused..)
(I just realized..That I don 't remember N anywhere ..since with recursive calls, it will already be different. I'm completely confused..)
That's right, there is no concept of nested scope in Prolog. Instead, we pass everything we need further down among the predicate's arguments, possibly using additional arguments.
Minimal edit to fix your code:
divisors(N,L):- divisors(N,N,L).
divisors(N,0,[]):- !.
divisors(N,N1,[N1|P]):- % use N1
%N1=N,
RES is (N mod N1),
N2 is N1-1,
RES==0,
divisors(N,N2,P).
divisors(N,N1,P):- % skip N1
%N1=N,
RES is (N mod N1),
N2 is N1-1,
RES\=0, %!, fail
divisors(N,N2,P). % same P
The result list L is instantiated in the top-down fashion.
Examples:
49 ?- divisors(12,L).
L = [12, 6, 4, 3, 2, 1].
50 ?- divisors(37,L).
L = [37, 1].
The brute force way of finding all the divisors of a natural number would be something like this:
divisors( 0 , [] ) . % zero is a special case
divisors( N , Ds ) :- % otherwise, the general case applies
integer(N), % - N must be an integer, and
N > 0, % - N must be positive (and greater than 0)
divisors(1,N,Ds) % - invoke our helper predicate to try all possible divisors from 1–N inclusive
. % - Easy!
divisors( D , N , [D|Ds] ) :- % case 1: D is a divisor of N
D < N , % - D must be less than N, and
0 =:= N mod D, % - D must be an integer divisor of N,
!, % - eliminate the choice point
D1 is D+1, % - increment D
divisors(D1,N,Ds) % - recurse down, with D prepended to the result list
. %
divisors( D , N , Ds ) :- % case 2: D is not a divisor of N
D < N , % - D must be less than N, and
0 =\= N mod D, % - D must not be an integer divisor of N
!, % - eliminate the choice point
D1 is D+1, % - increment D
divisors(D1,N,Ds) . % - recurse down, discarding the current D
divisors( N , N , [N] ) % case 3: every number is its own divisor.
. %

calculate the s-number for a natural number using Prolog [duplicate]

This question already has answers here:
Convert peano number s(N) to integer in Prolog
(3 answers)
Closed 2 years ago.
I am a total novice to Prolog and still am getting used to its logic.
I have a task to create functions that turn a natural number into an "S-number" and vice versa.
So Number 0 would be 0.
Number 1 would be s(0).
Number 2 would be s(s(0)).
And so on.
nat(0).
nat(s(0)):- nat(X).
The function for finding a natural number for a given S-number I already have:
s2nat(0, 0) :- !.
s2nat(s(S),Number) :- s2nat(S,NewNumber), Number is NewNumber + 1.
So ?- s2nat(s(s(s(0))), X) would give X=3 as an output.
Now I need to write a function that does the opposite: returns an S-number for a given natural number.
And here I am stuck. I don't quite understand how to write a condition so that Prolog understands that I need s(S) to be returned. The condition Number is NewNumber + 1 doesn't work anymore to go back and get to a "0".
Do you have any advice?
In the recursive step, you can check if Number > 0, and peform recursion with Number-1:
snat(0, 0).
snat(s(S), Number) :-
Number > 0,
Number1 is Number-1,
s2nat(S, Number1).
We can make the predicate multidirection, for example by using the clpfd library:
:- use_module(library(clpfd)).
snat(0, 0).
snat(s(X), N) :-
N #> 0,
N1 #= N-1,
snat(X, N1).
This predicate can thus calculate the Peano representation of a number, calculate the number the Peano representation represents, validate if the given Peano number is indeed the given number, and enumerate over all possible Peano representations and their corresponding number:
?- snat(X, 4).
X = s(s(s(s(0)))) ;
false.
?- snat(s(s(0)), N).
N = 2.
?- snat(s(s(0)), 2).
true.
?- snat(s(s(0)), 4).
false.
?- snat(X, N).
X = N, N = 0 ;
X = s(0),
N = 1 ;
X = s(s(0)),
N = 2 ;
X = s(s(s(0))),
N = 3 ;
X = s(s(s(s(0)))),
N = 4

Primality test predicate isPrime/1 in Prolog

I am trying to understand solutions of exercises in order to prepare my logic programming exam and somehow I could not understand the logic of the code below.
Explanations in the question:
n is a prime number n > 1 and 1 < m < n
n/m has a non-zero remainder.
Here is the code:
isPrime(X) :- help(X,X).
help(X,Y) :-
Y > 2,
LOW is Y-1,
Z is X mod LOW,
Z > 0,
help(X,LOW).
help(X,2).
Could someone please explain the code for me.
This code is attempting to determine if X is a prime number, by doing the following:
let Y = X initially
1. Check to see if the number (Y) is greater than 2.
2. Assign a new variable (LOW) one-less than the starting number (Y-1)
3. If X mod LOW is greater than zero, then recurse with LOW as the new Y
Repeat this until X mod LOW is greater than zero and your mod is 1 (Y=2), then if I'm reading this (and remembering the formula) correctly, you should have X as a prime.
If at some point X mod LOW equals zero, then X is a non-prime.
Example: X=6 (non-prime)
Y=6, LOW=5, Z = 6 mod 5 = 1 --> help(6,5)
Y=5, LOW=4, Z = 6 mod 4 = 2 --> help(6,4)
Y=4, LOW=3 Z = 6 mod 3 = 0 --> non prime because it's divisible by 3 in this case
Example: X=5 (prime)
Y=5, LOW=4, Z= 5 mod 4 = 1 --> help(5,4)
Y=4, LOW=3, Z= 5 mod 3 = 2 --> help(5,3)
Y=3, LOW=2 Z= 5 mod 2 = 3 --> help(5,2)
Y=2, --> once you get to this point, X is prime, because LOW=1,
and any number mod 1 is greater than zero, and you can't "X mod 0".
Make sense? It's effectively iterating over numbers less than X to see if it divides equally (mod = 0).
OK. The definition of a prime number :
An integer n is prime if the following holds true:
N is greater than 1, and
N is divisible only by itself and 1.
Since every integer is (A) divisible by itself, and (B) divisible by 1, there is no real need to check that these conditions hold true. The real constraint that must be checked is this:
For a number n to be prime, the following constraints must be satisfied:
n must be greater than 1, and
No m must exist in the domain 1 > m < n such that n is divisible by m
Your help/2 predicate enforces that second constraint, by seeding its second argument with the test value, and decrementing it, looking for an m that divides n.
An easier way might be to write the test in a declarative manner and let Prolog figure it out for you:
is_prime(2). % 2 is prime by definition.
is_prime(N) :- % otherwise, N is prime if,
N > 2 , % - N is greater than 2, and
0 =\= N mod 2 % - and N is odd (no real need to check even numbers, eh?
not_divisible(3,N) % - and N is not divisible any other odd number in the range 3 -- (N-1)
.
not_divisible(N,N) . % if we've counted up to N, we're good.
not_divisible(M,N) :- % otherwise...
M < N , % - if M is less than N, and
0 =:= N mod M % - and N is not divisible by M, then
M1 is M-1 , % - decrement M, and
not_divisible(M1,N) % - recurse down on the newly decremented M
. %

ERROR: Undefined procedure: (+)/2

I'm new in SWI-Prolog and I want to check prime function in Prolog.
prime(N) :-
N > 1,
M is N - 1,
check(N, M).
check(_, 1).
check(N, M) :-
M > 1,
R is N - M * N / M,
R > 0,
P is M - 1,
check(N, P).
but when I ask 2 + 2 or another operator like (*)/2, (/)/2,... in Prolog it says: undefined procedure: (+)/2.
I think it is for see or tell. I reassign see(user) and tell(user) but this error occurs again.
why?
In SWI prolog 6.0.2 division as you used it returns floating point number. So prime(13) for example will fail, as remainder is 0. Integer division uses operator //. But check prolog SWI functions rem and mod.
Also you would like to have a cut after first definition of check, otherwise prolog will explore the second definition, which will return false. Cut ensures that after it checked all natural numbers smaller than N, it stops with success.
Here is the corrected code which behaves as desired in SWI Prolog 6.0.2.
prime(N) :-
N > 1,
M is N - 1,
check(N, M).
check(_, 1) :- !.
check(N, M) :-
M > 1,
R is N mod M,
R > 0,
P is M - 1,
check(N, P).
About your error, check this out:
?- 2+2.
ERROR: Undefined procedure: (+)/2
?- X is 2+2.
X = 4
You're supposed to use is in Prolog to force the evaluation of arithmetic expressions. Try typing "help(is)." at SWI-Prolog's prompt.
But your algorithm is massively inefficient, on two accounts. First, you check the candidate number for divisibility by all its preceding numbers, while only those not greater than its square root are enough (if a*b=n and a >= sqrt(n) then b =< sqrt(n)).
Then, you test in reversed order. Multiples of smaller factors are much more frequent than of larger ones, so the testing will get cut off much much earlier when done in ascending order, making the overall program run much much faster. Lastly, no need to test by any even number except 2:
prime(2).
prime(N) :- N > 1,
N mod 2 > 0, % is odd
M is floor(sqrt(N+1)), % round-off paranoia
check(N, M, 3).
check(N, M, F) :- F>M.
check(N, M, F) :- F=<M,
N mod F > 0,
F1 is F + 2, % test by odds only
check(N, M, F1).
primesFromTo(F,T,X):-
between(F,T,X), prime(X).
You are mentioning see and tell: These are very old-fashioned built-in predicates. Better avoid them. Use [file] to load a file, and make to reload it.
For a better implementation of testing primes, see this answer.

Resources