Why can't I assert the following rule in SWI-Prolog? - prolog

I'm trying to define a rule to convert natural numbers to integers as follows:
?- assert(nat_to_int(0, 0)).
true.
?- assert(nat_to_int(s(X), Y):- nat_to_int(X, Z), Y is Z + 1).
ERROR: Uninstantiated argument expected, found _5706 is _5712+1 (2-nd argument)
ERROR: In:
ERROR: [8] assert((nat_to_int(...,_5772):-nat_to_int(_5776,_5778)),_5782 is _5788+1)
ERROR: [7] <user>
I understand that Z has to be instantiated before it can be used in the expression Y is Z + 1. However, I don't understand why it wouldn't be instantiated. Doesn't nat(X, Z) instantiate Z?
I think the problem is that X itself might not be instantiated. Hence, it wouldn't be able to figure out what Z should be. How do I fix this problem?

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.

Arguments are not sufficiently instantiated in clause/2

i'm trying to write a simple meta-interpreter for the unification in prolog, this is what i got so far
unify(A,B):-var(A),A=B.
unify(A,B):-nonvar(A),var(B),B=A.
unify(A,B):-compound(A),compound(B),A=..[F|ArgsA],B=..[F|ArgsB],unify_args(ArgsA,ArgsB).
unify_args([A|TA],[B|TB]):-unify(A,B),unify_args(TA,TB).
unify_args([],[]).
meta(true).
meta((A,B)):- meta(A),meta(B).
meta(C):-clause(H,B), unify(H,C), meta(B).
the problem that i'm getting is that when i try to unify two variables e.g
meta((A,B)).
i get the correct result
A = B, B = true .
but when i try to unify anything else for example
meta((a,a)).
or even a compund i get the following error:
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [12] clause(_4306,_4308)
ERROR: [11] meta(a) at path_redacted/unify1.pl:22
ERROR: [10] meta((a,a)) at path_redacted/unify1.pl:21
ERROR: [9] <user>
i can't understand why clause/2 would need instantiated argouments in this particular case, or maybe i'm missing something else?
Thank you for any help
As Will Ness pointed out in a comment, clause/2 requires the Head to be instantiated.
As written, your meta-interpreter tries to enumerate all clauses of all predicates in the program to find ones that unify with the goal term C. You will have to restrict this to only enumerating clauses that match C. One way to do this would be to call clause(C, Body) directly. I guess you want to avoid this, since this would cheat by doing the unification for you.
The other way is to copy C's functor, but not its arguments. You can use this copy to look up clauses for the predicate of interest, but you will still be able to do the unification yourself.
Here is how you can do such a "skeleton" copy:
?- C = f(x, y), functor(C, Functor, Arity), functor(Skeleton, Functor, Arity).
C = f(x, y),
Functor = f,
Arity = 2,
Skeleton = f(_70, _72).
In the context of your meta-interpreter, something like this gets you closer to what you want:
meta(Goal) :-
functor(Goal, Functor, Arity),
functor(Head, Functor, Arity),
clause(Head, Body),
unify(Head, Goal),
meta(Body).
For example, using this example program:
f(x).
g(y).
fg(X, Y) :-
f(X),
g(Y).
We get:
?- meta(fg(X, Y)).
X = x,
Y = y ;
ERROR: No permission to access private_procedure `true/0'
ERROR: In:
ERROR: [12] clause(true,_2750)
...
The solution is found correctly, but backtracking for further answers tries to access a clause for true. This is not allowed by SWI-Prolog. You will have to be more careful about making the clauses of the meta-interpreter mutually exclusive. You will probably need to place cuts.

Call a rule in Prolog

I'm trying to solve Knight Tour problem.
I want to call a rule to evaluate possible movements, but I can't do that my rule returns the next position in the variable that I send.
move(X,Y):-
X is X+1,
Y is Y-2.
move(X,Y):-
X is X+2,
Y is Y-1.
In the console I send move(2,2) for example and I hope that returns 3,0 and 4,1 but returns false.
In addition to the answer provided by #coder (+s(0)), I would suggest the use of library(clpfd), a pair representation for the coordinates and a name that reflects which argument is what, e.g. from_to/2. Then your predicate could look something like this:
:- use_module(library(clpfd)).
from_to(X-Y,X1-Y1):-
X1 #= X+1,
Y1 #= Y-2.
from_to(X-Y,X1-Y1):-
X1 #= X+2,
Y1 #= Y-1.
Using clpfd makes it possible to use the predicate both ways, e.g.: I'm at position 3-4, where can I move to?
?- from_to(3-4,T).
T = 4-2 ? ;
T = 5-3
Or: I'm at position 3-4, where could I have come from?
?- from_to(F,3-4).
F = 2-6 ? ;
F = 1-5
The latter case doesn't work if you define your predicate using is/2, since in that case the expression on the right side is expected to be instantiated:
?- X is 3+4.
X = 7
?- 7 is X+4.
ERROR!!
INSTANTIATION ERROR- in arithmetic: expected bound value
?- 7 is 3+X.
ERROR!!
INSTANTIATION ERROR- in arithmetic: expected bound value
You need to use new variables and add new parameters like:
move(X, Y, New_X, New_Y):-
New_X is X+1,
New_Y is Y-2.
That's because when you call move(2,2) X and Y are instantiated to the value 2 and they can't change, so you could pass two new uninstantiated variables which will be returned instantiated.
For example now if you call: move(2,2,X,Y)
X,Y will be instantiated (when predicate returns/succeeds) and the predicate will return you the right values in X,Y .

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 Beginner: Trivial Example that I cannot get to work.

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).

Resources