anonymous variables - prolog - a few queries - prolog

Can you help me understand the engine of answering the next queries?
?- _ = _.
?- _ = 1.
?- A = _, B = _, C = A + B + 1.
And some extra query (not related to anonymous variables):
?- B = A + 1, A = C, C = B - 1.
I know the answers to above queries, but I want to understand how prolog find those answers :)
Thanks!

_ is called the _anonymous variable. Each occurrence of _ is a different variable. You can observe it easily by using the standard write_canonical/1 built-in predicate. For example:
| ?- write_canonical(_ = _).
=(_279,_280)
yes
A variable can be unified with any term, including other variable, as you observe in your queries. Note that the standard =/2 built-in predicate performs unification, not equality or arithmetic expression evaluation. Unification takes two terms and succeeds if the two terms are the same or can be made the same by unifying any variables in the terms. For example:
| ?- A + 1 = 2 + B.
A = 2
B = 1
(1 ms) yes
A query such as:
| ?- write_canonical(B = A + 1), nl, B = A + 1, write_canonical(B).
=(_279,+(_280,1))
+(_280,1)
B = A+1
yes
unifies the variable B with the compound term +(A,1). _279 and _280 are the internal variable representation for, respectively, B and A. Different Prolog systems print these internal representation differently. For example, using SWI-Prolog:
?- write_canonical(B = A + 1), nl, B = A + 1, write_canonical(B).
=(_,+(_,1))
+(_,1)
B = A+1.
Regarding your extra query, B = A + 1, A = C, C = B - 1, it creates cyclic terms. Consider the simpler query:
| ?- X = f(X).
The result and consequent variable binding report by the Prolog top-level depends on a specific Prolog system handles cyclic terms. For example, in GNU Prolog you will get:
| ?- X = f(X).
cannot display cyclic term for X
yes
while SICStus Prolog reports:
| ?- X = f(X).
X = f(f(f(f(f(f(f(f(f(f(...)))))))))) ?
Cyclic terms are useful for some applications, e.g. coinductive logic programming. But the handling of cyclic terms is not standardized and varies among Prolog systems. The ISO Prolog standard provides a built-in predicate, unify_with_occurs_check/2, that checks if unification will create a cyclic term, preventing it. For example:
| ?- unify_with_occurs_check(X, f(X)).
no
| ?- unify_with_occurs_check(X, Y).
Y = X
(1 ms) yes

Related

using call(G) vs using G without call/1

Many prolog guides use the following definition of negation as failure.
% negation as failure
negation(G) :- call(G), !, fail.
negation(_).
Question: is it necessary to wrap G in call/1?
In the following definition, G is written without wrapping it with a call/1, and it seems to work.
% negation as failure
negation2(G) :- G, !, fail.
negation2(_).
Testing with swi-prolog (swish):
?- negation2(true)
false
?- negation2(false)
true
I also tested it with a short prolog program.
Question 2: Are there scenarios when we must write call(G) and not simply G?
First of all, these examples are about programs that go beyond first order logic, for you now permit variables to be in the place of goals. Inevitably, this transition will lead to some quirks on its way.
The common way to resolve this in ISO (and also in many systems that are not ISO like SWI) is to define an exact moment where first-order terms are converted into a goal or body of a clause (7.6.2). In this moment, a variable G_0 that occurs in the place of a goal is wrapped into call(G_0).
Thus, to answer Q1: No, it is not necessary to wrap that variable in your definition of negation/1, since the term-to-body conversion is happening here at the time of the preparation for execution of this Prolog text.
So essentially there will never be a variable that is called directly. Instead, call/1 is used always.
Your question 2 thus boils down to: What is the difference between a non-variable term as a goal and that term just wrapped with call/1?
Terms that cannot be converted to a goal/body.
?- false, call(1).
false.
?- false, 1.
error(type_error(callable,(false,1)),(',')/2).
?- G_0 = ( false, call(1)), G_0.
false.
?- G_0 = ( false, 1), G_0.
error(type_error(callable,(false,1)),(',')/2).
Control constructs cut and if-then-else no longer cut.
?- ( !, false ; true ).
false.
?- ( call(!), false ; true ).
true.
?- ( A = 1 -> B = 2 ; C = 3 ).
A = 1, B = 2.
?- ( ( A = 1 -> B = 2 ) ; C = 3 ).
A = 1, B = 2.
?- ( call(( A = 1 -> B = 2 )) ; C = 3 ).
A = 1, B = 2
; C = 3.
Note that in SWI, the toplevel has its own extra error checking which sometimes shows. With an extra indirection this can be circumvented. Here is such a case:
?- false, unknown.
false. % result in Scryer etc
?- false, unknown.
ERROR: Unknown procedure: unknown/0 (DWIM could not correct goal)
% SWI result only
?- G_0 = ( false, unknown ), G_0.
false. % same result everywhere

Prolog power of 2 recursion

Need help creating a recursive clause is a rule: X is a power of 2 only if there is a Y such that when adding Y to Y the result is
X, and Y is a power of 2. in prolog
We are going to define this predicate recursively. The followings are the fact and rule for detecting whether a numeral
is a power of 2 or not:
• The base clause is a fact: 1 is a power of 2 (because 1=20);
• The recursive clause is a rule: X is a power of 2 only if there is a Y such that when adding Y to Y the result is
X, and Y is a power of 2.
For example, the following shows how the queries should be performed:
| ?- powerOf2(succ(succ(succ(succ(0))))).
true ?
yes
| ?- powerOf2(succ(succ(succ(0)))).
no
The first query shows that 4 is a power of 2; while the second shows that 3 is not.
can not use the built-in is/2 predicate to perform arithmetic
To make it easier to represent natural numbers in Peano notation, you can use the following predicate:
nat(0, 0).
nat(N, s(P)) :-
succ(M, N),
nat(M, P).
Examples:
?- nat(3, P).
P = s(s(s(0))) ;
false.
?- nat(5, P).
P = s(s(s(s(s(0))))) ;
false.
To get the double of a Peano number, use the predicate:
double(0, 0).
double(s(A), s(s(B))) :-
double(A, B).
Examples:
?- nat(1, P), double(P, D).
P = s(0),
D = s(s(0)) ;
false.
?- nat(3, P), double(P, D).
P = s(s(s(0))),
D = s(s(s(s(s(s(0)))))) ;
false.
To check whether a Peano number is a power of two, use the predicate:
power_of_two(s(0)).
power_of_two(s(s(N))) :-
double(M, s(s(N))),
power_of_two(M).
Example:
?- between(1,9,N), nat(N,P), power_of_two(P).
N = 1,
P = s(0) ;
N = 2,
P = s(s(0)) ;
N = 4,
P = s(s(s(s(0)))) ;
N = 8,
P = s(s(s(s(s(s(s(s(0)))))))) ;
false.
Need help creating a recursive clause
The recursive clause will be:
power_of_two(1).
power_of_two(X) :-
X > 1,
Y is X / 2,
power_of_two(Y).
A base case which handles 1 being a power of two. And a case which handles when X is greater than one, Y is half X and recursively checks that Y is a power of two.
can not use the built-in is/2 predicate to perform arithmetic
You can't, but I can for the sake of illustrating the recursive clause you asked about. I'm assuming that since it tells you to use "succ(succ(succ(succ(0))))" you already have met that and have some code for adding/subtracting/dividing which you can reuse to replace Y is X / 2.

Get index of a Term's argument in Prolog

I need to get the index of a term's argument in Prolog. Predicate arg/3 seems to do the opposite of what I need:
arg(Index, Term, Value).
arg/3 fails if Index is a variable, so it's not possible to get the index of a given value and term. You guys know any other way to achieve this (I can't use external libraries)?
An example of the expected behaviour would be:
?- arg_(Index, regs(a,b,c), c).
Index = 3
Not all Prolog implementations seem to behave like SWI-Prolog does when the index is a variable. Its behavior might be an extension to the standard.
Here is what GNU Prolog 1.4.5 does:
| ?- arg(Index,s(a,b,c,d),V).
uncaught exception: error(instantiation_error,arg/3)
| ?- arg(Index,regs(a,b,c),c).
uncaught exception: error(instantiation_error,arg/3)
So you'll have to backtrack over the valid indices yourself. You can use functor/3 to find out how many arguments there are:
| ?- Term = regs(a,b,c), functor(Term, _Functor, Arity).
Arity = 3
Term = regs(a,b,c)
yes
And many Prologs (including GNU Prolog) have a between/3 predicate for enumerating integers in a range:
| ?- between(1, 4, N).
N = 1 ? ;
N = 2 ? ;
N = 3 ? ;
N = 4
(1 ms) yes
So overall you can do:
| ?- Term = regs(a,b,c), functor(Term, _Functor, Arity), between(1, Arity, Index), arg(Index, Term, Value).
Arity = 3
Index = 1
Term = regs(a,b,c)
Value = a ? ;
Arity = 3
Index = 2
Term = regs(a,b,c)
Value = b ? ;
Arity = 3
Index = 3
Term = regs(a,b,c)
Value = c
yes

What is the difference between is and =?

I have entered these statements into the prolog interpreter and am confused by the results. Shouldn't they return the same thing; true?
1 ?- 7 = 5 + 2.
false.
2 ?- 7 is 5 + 2.
true.
No, because =/2 does not mean assign in Prolog, but rather unify. And the unification algorithm does not know anything at all about arithmetic, just structure. So you can do some interesting things with arithmetic expressions in Prolog that are quite difficult to pull off in other languages:
?- X = 5 + 2.
X = 5+2.
It looks like nothing happened there, but what actually happened is X was given the value "5 + 2" as a structure. Put another way:
?- A + B = 5 + 2.
A = 5,
B = 2.
Or even:
?- X = 5 + 2, X =.. [Op|_].
X = 5+2,
Op = (+).
That last one might make more sense with the whole list though:
?- X = 5 + 2, X =.. Y.
X = 5+2,
Y = [+, 5, 2].
This is an effect of the remarkable "univ" operator, =../2, which is able to convert between Lisp-like lists and Prolog syntax, enabling you to do interesting construction and decomposition of structures in a generic fashion.
Now, is/2, on the other hand, does know about arithmetic. It unifies its left argument with the result of arithmetic simplification of its right. Do note that it only works in one direction:
?- 7 is 5 + 2.
true.
?- 5 + 2 is 7.
false.
You could say that =/2 is interested in structure and is/2 is interested in numeric equality. But it does mean that it's unusually easy to teach Prolog algebra:
simplify(X * Y + X * Z, X * (Y + Z)). % distributive property
simplify(X, X).
?- simplify(A * 3 + A * 4, Q).
Q = A* (3+4)
Now, this isn't perfect (note that we got 3+4 and not 7) and it's still a lot of work to make it really smart:
?- simplify(3 * A + 4 * A, Q).
Q = 3*A+4*A.
But that's a problem for another day.
Nutshell:
=/2 triggers unification
is/2 triggers arithmetic evaluation

Relational operators use in prolog for variables

I am writing the following code and is giving perfect results.
edge(s,a,300).
edge(s,d,20).
edge(a,d,400).
edge(a,b,1500).
edge(b,c,9).
edge(b,e,200).
edge(c,d,2000).
edge(c,g,12).
edge(d,e,3).
edge(e,f,400).
edge(f,g,800).
connected(X,Y,D) :- edge(X,Y,D) ; edge(Y,X,D).
path(A,B,D,Path) :-
travel(A,B,D,[A],Q),
reverse(Q,Path).
travel(A,B,D,P,[B|P]) :-
connected(A,B,D).
travel(A,B,D,Visited,Path) :-
connected(A,X,D1),
X \== B,
\+member(X,Visited),
D2 is D - D1,
travel(X,B,D2,[X|Visited],Path).
Here if I query like
| ?- path(s,e,23,P).
P = [s,d,e] ? ;
no
| ?-
I do get the correct response.
But no I wish to get the results for a D<50, say.
How to do?
Arithmetic expressions are kind of a special case in Prolog, and not expected to work with unbound arguments, so you cannot simply ask for path(s,e,D,P), D < 50, because the is-clause needs all its right-hand side arguments instantiated.
You can use the finite domain (FD) constraint extensions for Prolog (e.g. in GNU Prolog): just change your is to the FD-equivalent #=, and ask:
/Users/stolz/test.pl compiled, 27 lines read - 3180 bytes written, 8 ms
| ?- fd_domain(D,0,50), path(s,e,D,P).
D = 23
P = [s,d,e] ? ;
no
You should let Prolog compute the distance D as well as the Path:
travel(A,B,D,Visited,Path) :-
connected(A,X,D1),
X \== B,
\+member(X,Visited),
travel(X,B,D2,[X|Visited],Path),
D is D2 + D1.
Then you can query it
?- path(Start, Stop, D, P), D < 50.
and will get (on backtracking) all paths with D < 50.
?- path(s,e,X,P),X<50.
X = 23,
P = [s, d, e] ;
false.
Although I think finite domain constraints are the best to use here, you can achieve what you want with a minor modification to your code.
In the first clause of travel/5 instead of unifying input argument D with the third argument of connected/3, you can use a fresh variable and then check to see whether your current distance (D) is larger or equal to this new variable.
travel(A,B,D,P,[B|P]) :-
connected(A,B,TD),
D >= TD.

Resources