How can you determine in prolog that two numbers are relatively primes? Does anyone know if there is a function for this or you have to write it? I searched for it in the documentation, but haven't found anything useful.
As #mbratch mentioned in comments, there is a standard gcd (greatest common divisor) function.
Relatively prime numbers has gcd equal to 1.
So the code of relatively_prime can be very simple:
relatively_prime(X, Y) :-
gcd(X, Y) =:= 1.
Related
I have written the following prolog code to find all the prime factors of a number.
find_factors(0).
find_factors(N):- N>0, isPrime(N), write(N),nl, S is N-1, find_factors(S).
where the predicate isPrime(N) checks whether a number is prime or not and returns true or false accordingly.
However with my logic, I always get false as output. Where is the problem?? I am very new to prolog programming, so I am struggling a little bit.
If further clarifications needed, drop a comment below.
I think, you should not start with prime factorization to learn Prolog, because your code does not suggest you have a clear idea of that problem. I have a hard time interpreting the intention/idea behind your code.
I recommend to start learning prolog by picking a problem that you already understand.
Then maybe start thinking about how a suitable predicate for your solution should look like.
In the case of prime factorization, it could be maybe
prime_factors(N, List), which is supposed to be provable if N is a number and List is the list of all of its prime factors.
Or it could be
prime_factor(N, F), which is supposed to be provable if N is a number and F is one of its prime factors.
In other words: what questions do you want to ask the prolog system?
I am very new to Prolog and I am trying to do a simple recursive example.
My KB is:
natural(0).
natural(n) :- natural(n - 1).
Then my query is:
natural(1).
and the answer is false.
From what I read, numbers in Prolog are constants like 'book' and this might be
causing the problem, but I am not sure how to fix it.
Any help would be much appreciated. Thank you!
You should do it like that:
natural(0).
natural(N) :- M is N - 1, natural(M).
Prolog is not an imperative language and natural is not a function.
What happens here is I'm unifying M with N - 1 and then look if M is natural.
So, translating to imperative, is is for assignment.
Also keep in mind that variable must start with uppercase, lowercase is for 'constants'.
In SWI-Prolog,
nat(N) :- between(0, infinite, N).
works for both testing and generating natural numbers.
I was working on a Prolog problem consisting in counting the number of elements of a list:
count([], 0).
count([H|T], N) :-
count(T, X),
N is X+1,
N > 0.
I can understand why it's written like that but I don't understand why we can't replace N is X+1 by X is N-1 ?
Thanks a lot!
Your question is very legitimate, +1.
The reason for this seemingly arbitrary choice is that (is)/2 is a comparatively low-level predicate and only works in very specific cases that can only be understood procedurally, not declaratively. Therefore, (is)/2 is extremely hard to understand for beginners and should better be avoided because it destroys many relational properties we want to enjoy when using Prolog.
The declarative solution is to use constraints, where you can do exactly what you say. For relations over integers, simply replace (is)/2 by (#=)/2 to enjoy the relational properties you intuitively expect.
For example, using GNU Prolog:
count([], 0).
count([_|Ls], N) :-
count(Ls, X),
X #= N - 1,
N #> 0.
In other systems like SICStus Prolog and SWI, you currently still need to use library(clpfd) for this. In addition, I highly recommend a more declarative name for this relation, making clear which argument denotes what:
:- use_module(library(clpfd)).
list_length([], 0).
list_length([_|Ls], N) :-
list_length(Ls, X),
X #= N - 1,
N #> 0.
Sample queries:
?- list_length([_,_,_], N).
N = 3.
?- list_length(Ls, 2).
Ls = [_G602, _G605] .
I leave improving the termination properties of this predicate as an easy exercise.
I'm new to prolog and every single bit of code I write turns into an infinite loop.
I'm specifically trying to see if X is in the range from 0 to K - 1.
range(X,X).
range(X,K) :- K0 is K - 1, range(X,K0).
My idea behind the code is that I decrement K until K0 equals X, then the base case will kick in. I'm getting an infinite loop though, so something with the way I'm thinking is wrong.
Welcome to the wondrous world of Prolog! It seems you tried to leapfrog several steps when learning Prolog, and (not very surprisingly) failed.
Ideally, you take a book like Art of Prolog and start with family relations. Then extend towards natural numbers using successor-arithmetics, and only then go to (is)/2. Today, (that is, since about 1996) there is even a better way than using (is)/2 which is library(clpfd) as found in SICStus or SWI.
So let's see how your program would have been, using successor-arithmetics. Maybe less_than_or_equal/2 would be a better name:
less_than_or_equal(N,N).
less_than_or_equal(N,s(M)) :-
less_than_or_equal(N,M).
?- less_than_or_equal(N,s(s(0))).
N = s(s(0))
; N = s(0)
; N = 0.
It works right out of the box! No looping whatsoever. So what went wrong?
Successor arithmetics relies on the natural numbers. But you used integers which contain also these negative numbers. With negative numbers, numbers are no longer well ordered (well founded, or Noetherian), and you directly experienced that consequence. So stick with the natural numbers! They are all natural, and do not contain any artificial negative ingredients. Whoever said "God made the integers, all else is the work of man." must have been wrong.
But now back to your program. Why does it not terminate? After all, you found an answer, so it is not completely wrong. Is it not? You tried to reapply the notions of control flow you learned in command oriented languages to Prolog. Well, Prolog has two relatively independent control flows, and many more surprising things like real variables (TM) that appear at runtime that have no direct counterpart in Java or C#. So this mapping did not work. I got a little bit suspicious when you called the fact a "base case". You probably meant that it is a "termination condition". But it is not.
So how can we easily understand termination in Prolog? The best is to use a failure-slice. The idea is that we will try to make your program as small as possible by inserting false goals into your program. At any place. Certain of the resulting programs will still not terminate. And those are most interesting, since they are a reason for non-termination of the original program! They are immediately, causally connected to your problem. And they are much better for they are shorter. Which means less time to read. Here are some attempts, I will strike through the parts that are no longer relevant.
range(X,X).
range(X,K) :-
K0 is K - 1, false,
range(X,K0).
Nah, above doesn't loop, so it cannot tell us anything. Let's try again:
range(X,X) :- false.
range(X,K) :-
K0 is K - 1,
range(X,K0), false.
This one loops for range(X,1) already. In fact, it is the minimal failure slice. With a bit of experience you will learn to see those with no effort.
We have to change something in the visible part to make this terminate. For example, you might add K > 0 or do what #Shevliaskovic suggested.
I believe the simplest way to do this is:
range(X,X).
range(X,K) :- X>0, X<K-1.
and here are my results:
6 ?- range(4,4).
true .
7 ?- range(5,8).
true.
8 ?- range(5,4).
false.
The simple way, as has been pointed out, if you just want to validate that X lies within a specified domain would be to just check the condition:
range(X,K) :- X >= 0 , X < K .
Otherwise, if you want your range/2 to be generative, would be to use the built-in between/3:
range(X,K) :- integer(K) , K1 is K-1 , between(0,K1,X).
If your prolog doesn't have a between/3, it's a pretty simple implementation:
%
% the classic `between/3` wants the inclusive lower and upper bounds
% to be bound. So we'll make the test once and use a helper predicate.
%
between(Lo,Hi,N) :-
integer(Lo),
integer(Hi),
_between(Lo,Hi,N)
.
_between(Lo,Hi,Lo) :- % unify the lower bound with the result
Lo =< Hi % - if we haven't yet exceeded the inclusive upper bound.
. %
_between(Lo,Hi,N) :- % otherwise...
Lo < Hi , % - if the lower bound is less than the inclusive upper bound
L1 is Lo+1 , % - increment the lower bound
_between(L1,Hi,N) % - and recurse down.
. %
I'm sure this is rather basic, though I couldn't find it on here by searching.
I'm learning prolog and found an example with rules: (representing adjacency)
adj(1, 2). adj(2, 1).
adj(1, 3). adj(3, 1).
adj(3, 4). adj(4, 3).
Now, this struck me as a little wasteful, since we know that adjacency is a reciprocal relationship, it should be enough to define only one of each pair, and then define:
adj(X, Y) :-
adj(Y, X), !.
I understand why this simplistic attempt doesn't work; it falls into an infinite loop if X and Y aren't adjacent. But, I haven't quite figured out how to modify this to work in all cases.
you should introduce an alternative name and code your logic using that. For instance
adj(1, 2).
adj(1, 3).
adj(3, 4).
is_adj(X,Y) :- adj(X,Y) ; adj(Y,X).