How to write number classifiers in prolog? - prolog

Playing with Prolog for the first time and while I thought I knew what it basically is good for, I find it hard to get anything done in it. So, I tried to find the easiest possible task and even fail to accomplish that.
I think it is due to me not knowing how prolog data types (numbers) are supposed to work or they have special syntax.
So, my first attempt to classify even numbers was:
even(0).
even(X) :- even(X-2).
Result: stack overflow for the query: even(2).
So I thought well if this is not it, then maybe it is:
even(0).
even(X+2) :- even(X).
Result of even(2): false.
So my simple question is: How to write such simple things in prolog? Is it all not working because i use numbers?

Why not do it the normal way:
is_even(X) :-
X /\ 0x1 =:= 0.
If you want to enumerate non-negative even numbers upon backtracking when the argument is not bound, this is a different thing altogether. It is probably easy to just say:
even(X) :-
between(0, infinite, X),
is_even(X).
You can use the second definition like this:
?- even(X).
X = 0 ;
X = 2 ;
X = 4 ;
X = 6 . % and so on
There are some differences between is_even/1 and even/1:
is_even/1 will work for any integer, positive or negative
is_even/1 will, surprisingly enough, work for expressions that evaluate to integers, too, for example, X = 3, ..., is_even(X + 1). This is because =:= accepts an arithmetic expression on either side.
even/1 uses between/3, so the domain of X and error conditions are the same as for the third argument of between/3.
As a consequence, even/1 does not work with negative integers or arithmetic expressions.
But wait, there's more!
Apparently, between(0, infinite, X) is not something you can do in almost any Prolog apart from SWI. So, instead, you can use another predicate that will enumerate positive integers (list lengths):
even_f(X) :-
length(_, X),
is_even(X).
(Thank you to #false for this)

Use is/2 to force the arithmetic evaluation. On their own, Prolog terms are just structural symbolic entities, X-2 is a compound term of arity 2, -(X,2):
3 ?- write_canonical( X-2 ).
-(_,2)
true.
But is is for arithmetic expressions:
4 ?- Z is 5-2.
Z = 3.
Your definition should thus be
even(X):- X=:=0 -> true
; X > 0 -> Y is X-2, even(Y).
The drawback of such definition is that it can't be called in a generative fashion, like even(X) to get all the evens generated one after the other.
It is only good for checking a given number. For simplicity, it ignores the negative numbers and always fails for them.

Related

Why does Prolog does not backtrack on comparison?

I would expect that the following should always be true if a comparison backtrack, right? unless it goes into an infinite loop!
?- Y=2 , random:random(1,3,X), X =\= Y.
Y = 2,
X = 1.
?- Y=2 , random:random(1,3,X), X =\= Y.
false.
but I got false!
In general, my question is why doesn't comparison backtrack?
Thanks for all the answers. My confusion seemed to come primarily from my expectation of random keep generating new-random numbers, so I confused that comparison was not backtracking, instead, the reason was that random does its thing only once and fails afterwards.
I was unaware of semi-determinate nature of some predicates.
But now I can be on a lookout ;) for cases like this. thanks again.
In your example, there is nothing to backtrack.
All predicates you are using in these examples ((=)/2, random/3 and (=\=)/2) are semi-deterministic: This means that they either fail, or succeed exactly once.
In other words, they can all succeed at most once.
Therefore, if at least one of these predicates fails, then the query fails.
To generate a succession of pseudo-random numbers on backtracking, use for example repeat/0.
Warning: random/3 is an impure predicate: It may yield different solutions even though the query is exactly the same. It may lead to failure on one invocation, and to success on another. This complicates testing and reasoning about your code considerably.
Prolog works with what are called Horn-clauses. This means that each term individually, for example Y=2, is a separate goal in a question to be answered. The result will be yes or no for each goal, and if all goals answer yes, the question is answered with yes.
What your code asks is as follows:
%Is Y equal to 2 or can it be made equal?
%Yes, Y is a variable and can be assigned the numerical atom 2
Y=2 ,
%Give me a random number between 1 and 3.
%Is X equal to the random number or can it be made equal?
%Yes, X is a variable and can be assigned the outcome atom of random:random
random:random(1,3,X),
%is the term contained within X NOT equivalent to Y?
X =\= Y.
You can check out existing comparison predicates in for example the SWI documentation or on Learn Prolog Now!.
Depending on your implementation you can use trace and write to output the actual atoms in the variables, allowing you to explore how your program actually works.
?- trace, (Y=2 , random:random(1,3,X), write(X),nl, X =\= Y). %SWI-Prolog
SWI-prolog online editor
Infinite recursion looks like p(P) :- p(P).. It has a call to the question it is supposed to solve inside the answer itself, meaning to solve for p(P) it will check p(P), which never ends.
Backtracking only happens when Prolog has choicepoints. Choicepoints are points where in the decision tree, there are MULTIPLE POSSIBLE WAYS to satisfy the question Prolog is currently processing. Prolog works from top to bottom, then left to right.
Think of a cars salesman who gets asked "which car is the best for me?". He has more than one possible car to sell you, so he'll start showing you different cars that meet your criteria. The car needs to have a transport capacity of a volume over 400 liters? All cars that don't satisfy this condition are not presented as a solution.
Prolog does a depth-first search, meaning it goes down to the first answer it finds, then checks whether there's other ways to answer it. If there is no result, the answer is no. If there is at least one solution, the answer is yes and you get all possible answers for your question. This way you only get results that satisfy a whole chain of goals you've set.
I think this will help.
% Generate random value from Min to Max(with backtrack)
rand_backtrack(Min,Max,RandVal):-
create_list(Min,Max,List),
randomize_list(List,Randomized),
length(Randomized,Len),
% Choose one Variable from Randomized (From first element to last).
% When backtrack occured, next element is chosen.
between(1,Len,Idx),
nth1(Idx,Randomized,RandVal).
% create integer order list
% [Min,Min+1,Min+2,....,Max]
create_list(Max,Max,[Max]):-!.
create_list(Min,Max,[Min|Rest]):-
Min1 is Min+1,
create_list(Min1,Max,Rest).
% shuffle List.
% result always changes.
% ex.randomize_list([1,2,3,4,5,6],R) R=[4,2,6,1,3,5]
%
randomize_list([Val],[Val]):-!.
randomize_list(List,[RandVal|RestRandomized]):-
length(List,Len),
random(1,Len,RandIdx),
nth1(RandIdx,List,RandVal),
select(RandVal, List, Rest),
!,
randomize_list(Rest,RestRandomized).
?- rand_backtrack(3,19,A).
A = 6 ;
A = 4 ;
A = 8 ;
A = 13 ;
A = 15 ;
A = 16 ;
A = 9 ;
A = 18 ;
A = 7 ;
A = 3 ;
A = 12 ;
A = 10 ;
A = 17 ;
A = 11 ;
A = 14 ;
A = 5 ;
A = 19.

relational prolog and bit mask manipulations

I am trying my hand at relational prolog. Part of my program needs to deal with bitmasks. It however seems that prolog code handles bit makes, such as to set a bit or clear a bit doesn't work relationally -- i.e. it only works in setting a bit, but not in the other direction, identifying what bit is set.
For example:
setbit(X, N, V) :-
N1 #= 1<< N,
V #= X \/ N1.
this code only work in one direction, where X and N are given and V is calculated. If one provides V and N, then X is not derived, but rather its left as an uninstantiated expression.
Does this mean that calculating with bit maps and masks is out of scope of relational prolog.
?- setbit(0,1,X).
X = 2.
?- setbit(X, 1, 2).
2#=X\/2.
the latter doesn't bind X to 0.
thank you,
Daniel
Edit: based on the comments below, the following code works very well:
setbit(X, N, V) :-
X in 0..1,
label([X]),
N1 #= 1<< N,
V #= X \/ N1.
clearbit(X, N, V) :-
X in 0..1,
label([X]),
current_prolog_flag(max_tagged_integer, MTI),
N1 #= MTI /\ \(1<<N),
% N1 #= 0xffffffffffffff /\ \(1<<N),
V #= X /\ N1
Note, the current_prolog_flag -- it retrieves the maximum integer fitting into one word on the current machine architecture -- on 64 bit its 54 bits, the rest of the bits are used for housekeeping.
From a given solution, you cannot conclude that it is the only solution. That is, from
?- setbit(0,1,X).
X = 2.
you cannot conclude that
?- setbit(X, 1, 2).
has X = 0 as the only solution. In fact, there is another solution, namely
?- setbit(2, 1, 2).
true.
Ideally, all constraints would maintain domain-consistency. In this ideal world we would have:
?- setbit(X, 1, 2).
X in 0\/2, % idealiter
2#=X\/2.
instead of
?- setbit(X, 1, 2).
2#=X\/2. % realiter
But first of all, let us realize that both answers are correct! The second answer says precisely the same as the ideal one. However, finding a concrete solution may be more costly in the second case. In particular, since the following query has an answer:
?- setbit(X, 1, 2), X #> 2.
X in 3..sup,
2#=X\/2. % inconsistency
This answer reads like the notice of winning a lottery ticket you never heard of:
Yes, congratulation! There is a solution, provided all this fine print, this X in 3..sup, 2#=/2 has a solution, otherwise it does not have any solution. So don't complain, we told you so.
That is, an answer may very well contain exactly zero solutions. To be absolutely sure about a solution, you have to eliminate all constraints. The easiest way to do so, is using labeling/2. However, labeling/2 is defined only for finite domains (that's where the FD in CLPFD stems from). But in this case X is not constrained to a finite domain - would that be the case, we would have an extra constraint like X in 0..2.
The degree of consistency in clpfd-systems heavily depends on the actual use cases. After all, full consistency is undecidable. So there will always be cases where we would expect a more precise outcome. It is rather a question of tradeoffs for both run- and development time. Should you have convincing use cases contact the system developer.
In this particular case, you are probably better off using modulo arithmetics and addition.
I am not great at clpfd, but I think the problem here is that you haven't given X a finite domain or asked for its values to be enumerated. This works:
?- setbit(X, 1, 2), X in 0..1, label([X]).
X = 0 ;
false.
The second expression there, X in 0..1 says you want X to be zero or one, and the third says, "give me the values X can obtain."

How can I write a rule that finds a number using integer/1?

I am writing a rule that is looking for a particular integer. I assumed I can write something like this
find_number(X):-
integer(X),
X > 1, X < 5.
Then expect the result of a query to integer(X) to result in X=2, X=3, X=4, false. Instead, I just get a false result. The only way I found to write this rule is to use numlist/3 like so
find_number(X):-
numlist(2, 4, NumList),
member(X, NumList).
Can anyone explain why this is?
Your reasoning would be perfectly valid iff integer/1 were an actual relation that satisfies basic logical properties.
For example, in classical logic, a unary predicate P satisfies the following property:
If P(σ(T)) is satisfiable for any substitution σ and term T, then P(T) is also satisfiable.
This seems completely obvious and of course holds also for all pure predicates in Prolog.
The problem is that integer/1 is not a pure relation.
In particular, we have for example:
?- integer(3).
true.
Yet the following more general query fails:
?- integer(X).
false.
Is there any integer? No.
Believe it or not, that's how integer/1 actually works.
Clearly, something seems not quite right for such predicates, and so there are better alternatives in all widely used modern Prolog systems. I strongly recommend you use such alternatives instead, to get the most out of Prolog.
For the case of integers, I recommend you check out CLP(FD) constraints (clpfd).
For example, in GNU Prolog, your code could look like this:
good_number(X) :-
X #> 1,
X #< 5.
With the following queries and answers:
| ?- good_number(X).
X = _#2(2..4)
| ?- good_number(X), fd_labeling([X]).
X = 2 ? ;
X = 3 ? ;
X = 4
This works exactly as we expect a relation to work! I have taken the liberty to change the name such that it makes sense also in more specific cases, where there is nothing left to "find":
| ?- good_number(3).
yes
Depending on your Prolog system, you may have to import a library to use such more declarative features. See also logical-purity for more information.
You get only false because integer/1 tests if the input is an integer and if it is it succeeds else if it is not an integer or if it is a variable that is not instantiated as in your case, then it fails.
You could use between/2 built in predicate:
find_number(X):-between(2,4,X).
This will return:
?- find_number(X).
X = 2 ;
X = 3 ;
X = 4.

Prolog and limitations of backtracking

This is probably the most trivial implementation of a function that returns the length of a list in Prolog
count([], 0).
count([_|B], T) :- count(B, U), T is U + 1.
one thing about Prolog that I still cannot wrap my head around is the flexibility of using variables as parameters.
So for example I can run count([a, b, c], 3). and get true. I can also run count([a, b], X). and get an answer X = 2.. Oddly (at least for me) is that I can also run count(X, 3). and get at least one result, which looks something like X = [_G4337877, _G4337880, _G4337883] ; before the interpreter disappears into an infinite loop. I can even run something truly "flexible" like count(X, A). and get X = [], A = 0 ; X = [_G4369400], A = 1., which is obviously incomplete but somehow really nice.
Therefore my multifaceted question. Can I somehow explain to Prolog not to look beyond first result when executing count(X, 3).? Can I somehow make Prolog generate any number of solutions for count(X, A).? Is there a limitation of what kind of solutions I can generate? What is it about this specific predicate, that prevents me from generating all solutions for all possible kinds of queries?
This is probably the most trivial implementation
Depends from viewpoint: consider
count(L,C) :- length(L,C).
Shorter and functional. And this one also works for your use case.
edit
library CLP(FD) allows for
:- use_module(library(clpfd)).
count([], 0).
count([_|B], T) :- U #>= 0, T #= U + 1, count(B, U).
?- count(X,3).
X = [_G2327, _G2498, _G2669] ;
false.
(further) answering to comments
It was clearly sarcasm
No, sorry for giving this impression. It was an attempt to give you a synthetic answer to your question. Every details of the implementation of length/2 - indeed much longer than your code - have been carefully weighted to give us a general and efficient building block.
There must be some general concept
I would call (full) Prolog such general concept. From the very start, Prolog requires us to solve computational tasks describing relations among predicate arguments. Once we have described our relations, we can query our 'knowledge database', and Prolog attempts to enumerate all answers, in a specific order.
High level concepts like unification and depth first search (backtracking) are keys in this model.
Now, I think you're looking for second order constructs like var/1, that allow us to reason about our predicates. Such constructs cannot be written in (pure) Prolog, and a growing school of thinking requires to avoid them, because are rather difficult to use. So I posted an alternative using CLP(FD), that effectively shields us in some situation. In this question specific context, it actually give us a simple and elegant solution.
I am not trying to re-implement length
Well, I'm aware of this, but since count/2 aliases length/2, why not study the reference model ? ( see source on SWI-Prolog site )
The answer you get for the query count(X,3) is actually not odd at all. You are asking which lists have a length of 3. And you get a list with 3 elements. The infinite loop appears because the variables B and U in the first goal of your recursive rule are unbound. You don't have anything before that goal that could fail. So it is always possible to follow the recursion. In the version of CapelliC you have 2 goals in the second rule before the recursion that fail if the second argument is smaller than 1. Maybe it becomes clearer if you consider this slightly altered version:
:- use_module(library(clpfd)).
count([], 0).
count([_|B], T) :-
T #> 0,
U #= T - 1,
count(B, U).
Your query
?- count(X,3).
will not match the first rule but the second one and continue recursively until the second argument is 0. At that point the first rule will match and yield the result:
X = [_A,_B,_C] ?
The head of the second rule will also match but its first goal will fail because T=0:
X = [_A,_B,_C] ? ;
no
In your above version however Prolog will try the recursive goal of the second rule because of the unbound variables B and U and hence loop infinitely.

Can between/3 not be recursive?

I've seen the Prolog Prologue definition of between/3:
between(Lower, Upper, Lower) :-
Lower =< Upper.
between(Lower1, Upper, X) :-
Lower1 < Upper,
Lower2 is Lower1 + 1,
between(Lower2, Upper, X).
I don't understand why it requires recursion. A logical definition of between could be:
between(Lower, Upper, Something):-
Lower =< Upper,
Lower =< Something,
Something =< Upper.
I tried that on gprolog and it works, but only for simple queries:
| ?- between(0,5,1).
yes
For queries with variables I get:
| ?- between(0,5,X).
uncaught exception: error(instantiation_error, (=<)/2)
I don't really understand why.
I kind of figure Prolog needs some sort of reference number to unify variables against, but why the cryptic error on (=<)/2?
The error is not that cryptic, once you know what general purpose arithmetic in Prolog does. In short, it is simply there to do non-logical, "calculate this and give me the answer" kind of arithmetic. Comparisons (so all the </2, =</2, =:=/2, etc) require that you have arithmetic expressions on both sides; is/2 assumes that it has an arithmetic expression on the left side and a free variable on the right. So, you can do stuff like:
?- X is 3^1.3.
X = 4.171167510947728.
?- 1 =:= sin(pi/2).
true.
If you actually read the GNU-Prolog manual carefully enough, you should find, at the beginning of the relevant section, the following two sentences:
An arithmetic expression is a Prolog term built from numbers, variables, and functors (or operators) that represent arithmetic functions. When an expression is evaluated each variable must be bound to a non-variable expression.
(Emphasis mine)
Predicates like between/3, plus/3, or succ/2 are examples of special purpose integer arithmetic. They have their uses. However, most of the uses for doing actual integer math have been superseded by CLPFD. For GNU-Prolog, you should consult the documentation, but for a short example, to emulate between/3, you could say:
?- fd_domain(X, 0, 2), fd_labeling(X).
X = 0 ? ;
X = 1 ? ;
X = 2
yes
You should notice that this is definitely not recursive (to answer the question in the title). Of course, we are all aware that at some level, there is recursion or iteration involved, in order to get these answers.

Resources