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?
Related
For instance, say I have this program (only tested in swi-prolog):
:- use_module(library(clpfd)).
:- use_module(library(lists)).
% Sorted has the same elements as List and is also sorted
clpfd_sort(List, Sorted) :-
same_length(List, Sorted),
chain(Sorted, #=<),
permutation(List, Sorted).
Where could I find enough information on how clpfd works to know whether this is an efficient solution? It might be greedy to ask such a simple solution to be n lg(n) but for all I know it's 10^n.
I've looked at sources such as this and they all do a great job of explaining the magic of clpfd but none of them explain enough of how it's implemented for me to get an idea of which programs will run quickly and which will run slowly. clpfd apparently uses attributes to hook into unification? I don't know enough about attributes to know what that means for the complexity of the programs I write. Is there somewhere I could find out?
Example experiment:
:- use_module(library(clpfd)).
:- use_module(library(lists)).
call_time(G,T) :-
statistics(runtime,[T0|_]),
G,
statistics(runtime,[T1|_]),
T is T1 - T0.
% Sorted has the same elements as List and is also sorted
clpfd_sort(List):-
same_length(List, Sorted),
chain(Sorted, #=<),
permutation(List, Sorted).
item_goal(I,clpfd_sort(I)).
n_randoms_times(NumberOfExperiments,Random_Lists,Times) :-
numlist(1,NumberOfExperiments,Experiment_Sizes),
maplist(numlist(1),Experiment_Sizes,ExperimentLists),
maplist(random_permutation,ExperimentLists,Random_Lists),
maplist(item_goal,Random_Lists,Goals),
maplist(call_time,Goals,Times).
Test:
?- n_randoms_times(15,R,T),write(T).
[0,0,0,1,1,1,2,5,4,3,16,34,43,115,246]
So it looks like the time doubles as we add one to the size of the list ...
The best way to tackle with complexities of a Prolog or clpfd program is to avoid the actual mechanisms within and concentrate on concrete answers or sets of answers first. After all, if such an analysis already indicates a very large O, any further details are just futile, as is the case in your program.
Consider a list of n equal numbers. In this case, we will get n valid permutations. Thus worst-case complexity is at least O(n!). That seems to be bad enough to reconsider your approach.
The best in this case would be to develop a constraint that relates that list of integers to the actual list directly. If my memory does serve me well such has been implemented in the context of Prolog IV.
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.
Task is: Determine what numbers a,b,c is divider of N. For example: (a=2,b=3,c=4,n=2 Answer is a,c).
So, I wrote following code:
PREDICATES
a(integer,integer)
m(integer,integer,integer,integer)
CLAUSES
a(X,N):-
0 = X mod N,
write(X).
m(A,B,C,N):-
a(A,N).
m(A,B,C,N):-
a(B,N).
m(A,B,C,N):-
a(C,N).
GOAL
m(2,3,4,2).
but if Prolog found first solution (in my case a=2) then it stops and displays it. But, in my case answer will be a=2, c=4.
My question is "how Prolog can check all predicates"?
Prolog begins backtracking when a call fails. In certain situations, it may be necessary to initialize the performance of backtracking to find other solutions. Prolog has a special predicate fail, which calls unsuccessful finish, and, therefore, initializes refund.
So, I rewrote my code:
PREDICATES
a(integer,integer)
m(integer,integer,integer,integer)
CLAUSES
a(X,N):-
0 = X mod N,
write(X),nl.
m(A,B,C,N):-
a(A,N),fail.
m(A,B,C,N):-
a(B,N),fail.
m(A,B,C,N):-
a(C,N).
GOAL
m(2,3,4,2).
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.
. %
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.