Prolog Successor Arithmetic - prolog

I have a knowledge base with the following:
numeral(0).
numeral(s(X)) :- numeral(X).
numeral(X+Y) :- numeral(X), numeral(Y).
add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
add2(W+X,Y+Z,R) :- add(W,X,A),add(Y,Z,T),add2(A,T,R).
add2(X+Y,Z,R) :- add(X,Y,A),add2(A,Z,R).
add2(X,Y+Z,R) :- add(Y,Z,A),add2(X,A,R).
add2(X,Y,R) :- add(X,Y,R).
which evaluates correctly queries such as:
?- add2(s(0)+s(s(0)), s(s(0)), Z).
Z = s(s(s(s(s(0)))))
?- add2(0, s(0)+s(s(0)), Z).
Z = s(s(s(0)))
?- add2(s(s(0)), s(0)+s(s(0)), Z).
Z = s(s(s(s(s(0)))))
However the following query is evaluated to:
?- add2(s(0)+s(0), s(0+s(s(0))), Z).
Z = s(s(s(0+s(s(0))))) .
But the required output is:
?- add2(s(0)+s(0), s(0+s(s(0))), Z).
Z = s(s(s(s(s(0)))))
I know the issue is with the line:
add2(W+X,Y+Z,R) :- add(W,X,A),add(Y,Z,T),add2(A,T,R).
But i just can't figure it out. Any help would be appreciated!

I think you make the problem more complex by handling the cases with an add2/3 predicate. You first need to resolve the structure of the first two arguments to something of the shape s(s(...s(0)...)).
In order to do this, we can make an resolve/2 function that looks for (+)/2 terms and recursively works with add/3:
resolve(0,0).
resolve(s(X),s(Y)) :-
resolve(X,Y).
resolve(X+Y,Z) :-
resolve(X,RX),
resolve(Y,RY),
add(RX,RY,Z).
So now for a grammar:
E -> 0
E -> s(E)
E -> E + E
resolve/2 will convert this to a grammar with:
E -> 0
E -> s(E)
For example:
?- resolve(s(0)+s(0),X).
X = s(s(0)).
?- resolve(s(0+s(s(0))),X).
X = s(s(s(0))).
And now our add2/3 predicate will first resolve/2 the operands, and then add these together:
add2(A,B,C) :-
resolve(A,RA),
resolve(B,RB),
add(RA,RB,C).
The sample queries you then write resolve to:
?- add2(s(0)+s(s(0)), s(s(0)), Z).
Z = s(s(s(s(s(0))))).
?- add2(0, s(0)+s(s(0)), Z).
Z = s(s(s(0))).
?- add2(s(s(0)), s(0)+s(s(0)), Z).
Z = s(s(s(s(s(0))))).
?- add2(s(0)+s(0), s(0+s(s(0))), Z).
Z = s(s(s(s(s(0))))).

Related

How to implement the factorial sequence in successor arithmetics for all argument modes?

The following Prolog program defines a predicate fact/2 for computing the factorial of an integer in successor arithmetics:
fact(0, s(0)).
fact(s(X), Y) :-
fact(X, Z),
prod(s(X), Z, Y).
prod(0, _, 0).
prod(s(U), V, W) :-
sum(V, X, W),
prod(V, U, X).
sum(0, Y, Y).
sum(s(X), Y, s(Z)) :-
sum(X, Y, Z).
It works with queries in this argument mode:
?- fact(s(0), s(0)).
true
; false.
It also works with queries in this argument mode:
?- fact(s(0), Y).
Y = s(0)
; false.
It also works with queries in this argument mode:
?- fact(X, Y).
X = 0, Y = s(0)
; X = Y, Y = s(0)
; X = Y, Y = s(s(0))
; X = s(s(s(0))), Y = s(s(s(s(s(s(0))))))
; …
But it exhausts resources with queries in this argument mode:
?- fact(X, s(0)).
X = 0
; X = s(0)
;
Stack limit (0.2Gb) exceeded
Stack sizes: local: 4Kb, global: 0.2Gb, trail: 0Kb
Stack depth: 2,503,730, last-call: 100%, Choice points: 13
In:
[2,503,730] sum('<garbage_collected>', _1328, _1330)
[38] prod('<garbage_collected>', <compound s/1>, '<garbage_collected>')
[33] fact('<garbage_collected>', <compound s/1>)
[32] fact('<garbage_collected>', <compound s/1>)
[31] swish_trace:swish_call('<garbage_collected>')
How to implement the factorial sequence in successor arithmetics for all argument modes?
The first question must be why? A failure-slice helps to understand the problem:
fact(0, s(0)) :- false.
fact(s(X), Y) :- fact(X, Z), false, prod(s(X), Z, Y).
This fragment alone terminates only if the first argument is given. If it is not, then there is no way to prevent non-termination, as Y is not restricted in any way in the visible part. So we have to change that part. A simple way is to observe that the second argument continually increases. In fact it grows quite fast, but for the sake of termination, one is enough:
fact2(N, F) :-
fact2(N, F, F).
fact2(0, s(0), _).
fact2(s(X), Y, s(B)) :- fact2(X, Z, B), prod(s(X), Z, Y).
And, should I add, this can be even proved.
fact2(A,B)terminates_if b(A);b(B).
% optimal. loops found: [fact2(s(_),s(_))]. NTI took 0ms,73i,73i
But, there is a caveat...
If only F is known, the program will now require temporally space proprotional to |F|! That is not an exclamation point but a factorial sign...
I think you can use cut to avoid backtracking when the second argument is a ground term.
fact(0, s(0)).
fact(s(X), Y) :-
fact(X, Z),
prod(s(X), Z, W),
(ground(Y) ->
!,
Y = W
; Y = W).
prod(0, _, 0).
prod(s(U), V, W) :- sum(V, X, W), prod(V, U, X).
sum(0, Y, Y).
sum(s(X), Y, s(Z)) :- sum(X, Y, Z).
Examples:
?- fact(N, 0).
false.
?- fact(N, s(s(s(0)))).
false.
?- fact(X, s(0)).
X = 0
; X = s(0)
; false.
?- fact(s(s(s(0))), s(s(s(s(s(s(0))))))).
true
; false.
?- fact(s(s(s(0))), s(s(s(s(s(0)))))).
; false.
?- fact(s(s(s(0))), Y).
Y = s(s(s(s(s(s(0))))))
; false.
?- fact(X, Y).
X = 0, Y = s(0)
; X = Y, Y = s(0)
; X = Y, Y = s(s(0))
; …
?- fact(s(s(X)), s(s(Y))).
X = Y, Y = 0
; X = s(0), Y = s(s(s(s(0))))
; …

Prolog membership predicate without dif or when

The following prolog logic
memberd(X, [X|_T]).
memberd(X, [Y| T]) :- dif(X,Y), memberd(X, T).
will produce
?- memberd(a, [a, b, a]).
true
?- memberd(X, [a, b, a]).
X = a ;
X = b ;
false.
?- memberd(X, [a, b, a, c, a, d, b]).
X = a ;
X = b ;
X = c ;
X = d ;
false.
is there prolog logic that can be used to produce the same result without using when() or dif() function or anything from a loaded prolog library. Just using pure logic?
To answer your question literally, just use:
?- setof(t, member(X, [a,b,a]), _).
X = a
; X = b.
However, some answers will be suboptimal:
?- setof(t,member(a,[a,X]),_).
true
; X = a. % redundant
... whereas memberd/2 answers in perfection:
?- memberd(a,[a,X]).
true
; false.
In fact, if you use library(reif) with
memberd(E, [X|Xs]) :-
if_(E = X, true, memberd(E, Xs) ).
you get the best answer possible:
?- memberd(a,[a,X]).
true.

Prolog predecessor math

I have an add2 predicate which resolves like this where s(0) is the successor of 0 i.e 1
?- add2(s(0)+s(s(0)), s(s(0)), Z).
Z = s(s(s(s(s(0)))))
?- add2(0, s(0)+s(s(0)), Z).
Z = s(s(s(0)))
?- add2(s(s(0)), s(0)+s(s(0)), Z).
Z = s(s(s(s(s(0)))))
etc..
I'm trying to do add in a predecessor predicate which will work like so
?- add2(p(s(0)), s(s(0)), Z).
Z = s(s(0))
?- add2(0, s(p(0)), Z).
Z = 0
?- add2(p(0)+s(s(0)),s(s(0)),Z).
Z = s(s(s(0)))
?- add2(p(0), p(0)+s(p(0)), Z).
Z = p(p(0))
I can't seem to find a way to do this. My code is below.
numeral(0).
numeral(s(X)) :- numeral(X).
numeral(X+Y) :- numeral(X), numeral(Y).
numeral(p(X)) :- numeral(X).
add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
add(p(X),Y,p(Z)) :- add(X,Y,Z).
resolve(0,0).
resolve(s(X),s(Y)) :-
resolve(X,Y).
resolve(p(X),p(Y)) :-
resolve(X,Y).
resolve(X+Y,Z) :-
resolve(X,RX),
resolve(Y,RY),
add(RX,RY,Z).
add2(A,B,C) :-
resolve(A,RA),
resolve(B,RB),
add(RA,RB,C).
In general, adding with successor arithmetic means handling successor terms, which have the shape 0 or s(X) where X is also a successor term. This is addressed completely by this part of your code:
add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
Now you have to make a decision; you can either handle the predecessors and the addition terms here, in add/3, or you can wrap this predicate in another one that will handle them. You appear to have chosen to wrap add/3 with add2/3. In that case, you will definitely need to create a reducing term, such as you've built here with resolve/2, and I agree with your implementation of part of it:
resolve(0,0).
resolve(s(X),s(Y)) :-
resolve(X,Y).
resolve(X+Y,Z) :-
resolve(X,RX),
resolve(Y,RY),
add(RX,RY,Z).
This is all good. What you're missing now is a way to handle p(X) terms. The right way to do this is to notice that you already have a way of deducting by one, by using add/3 with s(0):
resolve(p(X), R) :-
resolve(X, X1),
add(s(0), R, X1).
In other words, instead of computing X using X = Y - 1, we are computing X using X + 1 = Y.
Provided your inputs are never negative, your add2/3 predicate will now work.

Logic Programming with Prolog

Logic Programming with Prolog:
Consider the program:
f(X) :- !, X = a.
f(X) :- !, X = b.
f(X) :- X = c.
What does P return for the queries f(a) , f(b) and f(c) respectively?
Consider the program:
f(X) :- X = a, !.
f(X) :- X= b, !.
f(X) :- X = c.
What does P return for the queries f(a) , f(b) and f(c) respectively?
What does P return for the queries f(a) , f(b) and f(c) respectively?
f(X) :- !, X = a.
f(X) :- !, X = b.
f(X) :- X = c.
?- f(a).
true.
?- f(b).
false.
?- f(c).
false.
f(X) :- X = a, !.
f(X) :- X = b, !.
f(X) :- X = c.
?- f(a).
true.
?- f(b).
true.
?- f(c).
true.

Assert higher-order clause in Prolog

This works:
assert(p(X) :- q(X)).
This does not work:
P = p,Q = q, assert(P(X) :- Q(X)).
How can I make the latter work?
You need to make the terms first; you can use the "univ" operator, =.. for this:
?- P = p, Q = q, Head =.. [P, X], Body =.. [Q, X], assertz((Head :- Body)).
P = p,
Q = q,
Head = p(X),
Body = q(X).
?- listing(p/1).
:- dynamic p/1.
p(A) :-
q(A).
You need the second pair of parentheses in most implementations, apparently. You will need them anyway if you had for example a conjunction in the body.
?- assertz(a :- b).
true.
?- assertz(a :- b, c).
ERROR: assertz/2: Uninstantiated argument expected, found c (2-nd argument)
?- assertz((a :- b, c)).
true.

Resources