Prolog Beginner: Trivial Example that I cannot get to work. - prolog

I have some prolog. The lessThanTen and example predicates work as expected however the exam predicate does not work.
lessThanTen(9).
lessThanTen(8).
lessThanTen(7).
lessThanTen(6).
lessThanTen(5).
lessThanTen(4).
lessThanTen(3).
lessThanTen(2).
lessThanTen(1).
lessThanTen(0).
% This should always return 5.
example(X) :-
X is 5.
% This should return all values that are less than ten.
exam(X) :-
X is lessThanTen(Y).
Here is the output:
% swipl
...
?- [addv1].
Warning: /.../addv1.pl:17:
Singleton variables: [Y]
% addv1 compiled 0.00 sec, 1,484 bytes
true.
?- lessThanTen(X).
X = 9 ;
X = 8 ;
X = 7 ;
...
?- example(X).
X = 5.
?- exam(X).
ERROR: is/2: Arithmetic: `lessThanTen/1' is not a function
?- exam(5).
ERROR: is/2: Arithmetic: `lessThanTen/1' is not a function
I am thinking that the warning I am getting is pretty key.

The is operator expects its right-hand argument - your lessThanTen(Y) - to be an arithmetic expression. It, of course, isn't.
Also, exam/1 just looks wrong: what's Y? The clause takes a single argument X.

lessThanTen(9).
lessThanTen(8).
lessThanTen(7).
lessThanTen(6).
lessThanTen(5).
lessThanTen(4).
lessThanTen(3).
lessThanTen(2).
lessThanTen(1).
lessThanTen(0).
example(X) :-
X is 5.
exam(X) :-
lessThanTen(X).

Related

Prolog: Multiplication(X,Y)

double(X, Y) :-
X is Y/2, Y is X*2.
I'm trying to execute this but its given error always
Arguments are not sufficiently instantiated
In:
[2] 4 is _1604/2
[1] double(4,_1662) at line 2
how can I get double of two variables.
You are trying to make a bidirectional procedure, where at least one of the parameters is instantiated.
You may use CLP(fd) like this:
double(X, Y):- Y #= X*2.
Note this will only work with integer values, so for example
?- double(2, Y).
Y = 4.
?- double(X, 4).
X = 2.
but
?- double(2.5, Y).
ERROR: Domain error: `clpfd_expression' expected, found `2.5'
ERROR: In:
ERROR: [14] throw(error(domain_error(clpfd_expression,2.5),_2162))
ERROR: [11] clpfd:parse_clpfd(2.5*2,_2200) at c:/swi/swi8/library/clp/clpfd.pl:7359
ERROR: [9] clpfd:clpfd_equal(_2236,2.5*2) at c:/swi/swi8/library/clp/clpfd.pl:2795
ERROR: [7] <user>
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
?- double(X, 5).
false.
or if you want to use is/2 then you should make sure that the right hand side of is/2 is bound to an number, for example like this:
double(X, Y) :-
( number(X)
-> Y is X*2
; number(Y)
-> X is Y/2
).
The procedure using CLP(fd) is clearly more powerful as it does not require the right hand arithmetic expression to be instantiated prior to issue the constraint, and thus allows queries like double(X,Y) to succeed (giving the remaining constraints upon querying).
You may also try CLP(r) which works over reals:
:- use_module(library(clpr)).
double(X, Y):- { Y=X*2 }.
sample runs:
?- double(2, Y).
Y = 4.
?- double(X, 4).
X = 2.
?- double(2.5, Y).
Y = 5.0.
?- double(X, 5).
X = 2.5.

Create successor numbers from natural numbers

I want to create successor Numbers from natural numbers in Prolog.
nat2s(0, s(0)).
nat2s(NaturalNumber, SNumber) :-
N is NaturalNumber - 1,
nat2s(N, s(SNumber)).
The output should be like this:
nat2s(3, X).
X = s(s(s(0))).
Actually it's an infinitive loop. I don't how to end the loop without only getting true as result.
I suggest a slightly different approach, namely the use of library(clpfd). First let's pick a more declarative name for the predicate. Since in your post the natural number and the number in s(X)-notation are the first and second argument respectively, let's call it nat_sx/2. Then the predicate can be defined like so:
:- use_module(library(clpfd)).
nat_sx(0,0).
nat_sx(N,s(X)) :-
N #> 0,
N0 #= N-1,
nat_sx(N0,X).
This yields the desired result in your post:
?- nat_sx(3,X).
X = s(s(s(0))) ? ;
no
To see why the use of clpfd is beneficial let's incorporate the suggested corrections from the comments into your code and compare both versions.
nat2s(0, 0).
nat2s(NaturalNumber, s(SNumber)) :-
NaturalNumber > 0,
N is NaturalNumber - 1,
nat2s(N, SNumber).
The above query works with this version as well:
?- nat2s(3,S).
S = s(s(s(0))) ? ;
no
However, it would be nice to be able to use the predicate in the other direction as well. So let's ask which natural number corresponds to s(s(0)):
?- nat_sx(N,s(s(0))).
N = 2 ? ;
no
?- nat2s(N,s(s(0))).
ERROR at clause 2 of user:nat2s/2 !!
INSTANTIATION ERROR- =:=/2: expected bound value
The reason for the instantiation error is the fact that is/2 expects a variable-free expression on the right side:
?- X is 3-1.
X = 2
?- 2 is X-1.
ERROR!!
INSTANTIATION ERROR- in arithmetic: expected bound value
?- 2 is 3-X.
ERROR!!
INSTANTIATION ERROR- in arithmetic: expected bound value
This is also the reason why the most general query of nat2s/2 has an instantiation error after the first solution...
?- nat2s(N,S).
N = S = 0 ? ;
ERROR at clause 2 of user:nat2s/2 !!
INSTANTIATION ERROR- =:=/2: expected bound value
... while nat_sx/2 keeps generating solutions:
?- nat_sx(N,S).
N = S = 0 ? ;
N = 1,
S = s(0) ? ;
N = 2,
S = s(s(0)) ? ;
...

Prolog ERROR: is/2: Arguments are not sufficiently instantiated

I'm new to Prolog. I wrote a very short program as follows:
plus(X,Y,R):- R is X+Y.
When I run it, I get the following problem:
?- plus(1,1,2).
true
?- plus(1,1,X).
X=2
?- plus(1,X,2).
ERROR: is/2: Arguments are not sufficiently instantiated
Why does the error happens? How can I modify the code to achieve the same goal?
Thank you all for helping me!!!
The reason that this is not working is that is/2 is (like) a function. Given X,Y it calculates X+Y and stores it to R (it instantiates R with X+Y). If R is provided and X or Y is a var (it is not yet instantiated) then how could it calculate X+Y, that's why the instantiation error.
To solve this you should use something more relational like module :CLPFD
:- use_module(library(clpfd)).
plus(X,Y,R):- R #= X+Y.
Some examples:
**?- [ask].
true.
?- plus(1,1,2).
true.
?- plus(1,1,X).
X = 2.
?- plus(1,X,2).
X = 1.
?- plus(X,Y,2).
X+Y#=2.
?- plus(X,Y,R).
X+Y#=R.**
You can see in the last case that is gives as an answer how X,Y and R are related.

Prolog: comparing predicate value with constant

I have some problems with prolog, specifically I can't compare a value of a predicate with a constant.
predicate(9).
compare(X,Y) :- X<Y.
Running the program:
?-compare(predicate(X),10).
Why doesn't it work? Thank you for your answers.
Predicates don't return values in the way that a function does.
This is C:
int nine() { return 9; }
int main() {
int x = nine(); /* x is now 9 */
}
This is Prolog:
% source
nine(9).
% from the top level
?- nine(X).
X = 9.
?- nine(X), X < 10.
X = 9.
?- nine(X), compare(C1, X, 10), compare(C2, 10, X).
X = 9,
C1 = (<),
C2 = (>).
Few things (trying not to use too much Prolog lingo):
What your predicate/1 and my nine/1 does is to unify its only argument with the integer 9. If the unification succeeds, the predicate succeeds, and now the argument is bound to 9. If the unification fails, the predicate fails.
?- nine(9).
true.
?- nine(nine).
false.
?- nine(X), nine(Y).
X = Y, Y = 9.
You will also notice that there is a standard predicate compare/3 that can be used for comparison of Prolog terms. Because predicates don't have a return value in the way that functions do, it uses an extra argument to report the result of the comparison. You could have instead tried something along the lines of:
% greater_than(X, Y) : true if X is greater than Y according
% to the standard order of terms
greater_than(X, Y) :- X #> Y.
But this is just defining an alias for #>/2, which is a predicate itself (but has been declared as an operator so that you can use it in infix notation).
?- #>(a, b).
false.
?- #>(b, a).
true.
Same goes for </2, which is a predicate for comparison of arithmetic expressions:
?- 2 + 4 =< 6.
true.
?- nine(X), X > 10 - X.
X = 9.
?- nine(X), X > 10.
false.
Like #Boris said before "Predicates don't return values in the way that a function does." Here you must try to instantiate the variables in the head of your rule.
If you are trying with you predicate compare/2 to find a number X greater than Y, and at the same time this number X should be a fact predicate/1, then add both conditions to the body of your rule or predicate compare/2
predicate(9).
compare(X,Y) :- predicate(X), X<Y.
Now if you consult:
?- compare(X,10).
The answer will be
X = 9
As you can see, 9 is smaller than 10, and at the same time 9 is a fact predicate/1. And that is the return value you are looking for.
Caution
Note that the operator >/2, requires that both sides are instantiated, so in this case you won't be able ask for the value Y in your predicate
?- compare(9, Y)
</2: Arguments are not sufficiently instantiated
Maybe and if it make sense, you can try to instantiate this variable to a fact predicate/1 too.
predicate(9).
predicate(10).
compare(X,Y) :- predicate(X), predicate(Y), X<Y.
?- compare(9,Y).
Y = 10

How to return two values from a basic predicate(?) in Prolog?

I just started going over Prolog about an hour ago and have already stumbled into a slight problem I am unsure about. I am writing a predicate (or function?) that takes a list and returns the min and max values. Right now, I am just looking at one of the special cases when the list has 1 item. For example, if you query minmax([5], X, Y). I want the predicate to return X=5 Y=5. I have this code:
minmax([X], X, X).
but it is returning X = Y, Y = 5. I know it is a true statement and trivial, but is there a way I can return X=5,Y=5 ???
It is returning what you think it is. X is 5 as is Y. The values are unified and so the interpreter shows the message X=Y, Y=5. You need to get out the Prolog textbook and read up on unification of terms.
You could just as easily say
foo(A,B) :- A = 5 , B is (A+A)/2 .
and query it:
?- foo(X,Y).
and get the same result. In the Prolog universe, there is only ever a single instance of the integer 5.
X=Y, Y=5 means that X and Y are now both equal to 5. It's just a different way of saying that; you really shouldn't care. If you print both values, you'll just get 5:
?- [user].
|: print_stuff :-
|: X = Y,
|: Y = 5,
|: write('X = '), writeln(X),
|: write('Y = '), writeln(Y).
|: % user://1 compiled 0.02 sec, 2 clauses
true.
?- print_stuff.
X = 5
Y = 5
true.

Resources