Recursion Prolog二进制加法

Recursion Prolog二进制加法,recursion,binary,prolog,failure-slice,Recursion,Binary,Prolog,Failure Slice,我需要在prolog中实现二进制加法,其中二进制数表示如下: 0: bot 1 : o(bot) 2 -> 10: z(o(bot)) 3 -> 11: o(o(bot)) 10 -> 1010: z(o(z(o(bot)))) 我写了这样一篇文章: add(X,bot,X):-!. add(bot,X,X):-!. add(z(X),z(Y),Res):- add(X,Y,D), Res = z(D). add(z(X),o(Y),Res):- add(X,Y,D

我需要在prolog中实现二进制加法,其中二进制数表示如下:

0:  bot
1 : o(bot)
2 -> 10:  z(o(bot))
3 -> 11:  o(o(bot))
10 -> 1010:  z(o(z(o(bot))))
我写了这样一篇文章:

add(X,bot,X):-!.
add(bot,X,X):-!.

add(z(X),z(Y),Res):- add(X,Y,D), Res = z(D).
add(z(X),o(Y),Res):- add(X,Y,D), Res = o(D).
add(o(X),z(Y),Res):- add(X,Y,D), Res = o(D).
add(o(X),o(Y),Res):-addc(X,Y,D), Res = z(D).

addc(X,bot,Res):-add(X,o(bot),Res),!.
addc(bot,X,Res):-add(X,o(bot),Res),!.
addc(z(X),z(Y),Res):- add(X,Y,D),Res = o(D).
addc(z(X),o(Y),Res):-addc(X,Y,D),Res = z(D).
addc(o(X),z(Y),Res):-addc(X,Y,D),Res = z(D).
addc(o(X),o(Y),Res):-addc(X,Y,D),Res = o(D).
当前两个参数是具体的时,它起作用:

?-add(o(o(bot)),z(o(o(bot))),D).
D = o(z(z(o(bot))))
当前两个参数之一是变量时,它将进入无限递归:

?-add(o(o(bot)),X,z(o(o(bot)))).
Stack limit (0.2Gb) exceeded
  Stack sizes: local: 0.1Gb, global: 34.9Mb, trail: 11.6Mb
  Stack depth: 1,524,958, last-call: 50%, Choice points: 762,476
  Possible non-terminating recursion:
    [1,524,958] add(bot, <compound s/1>, _1496)
    [1,524,957] add(bot, <compound s/1>, <compound z/1>)
?-添加(o(o(bot)),X,z(o(o(bot)))。
超出堆栈限制(0.2Gb)
堆栈大小:本地:0.1Gb,全局:34.9Mb,跟踪:11.6Mb
堆栈深度:1524958,上次调用:50%,选择点数:762476
可能的非终止递归:
[1524958]添加(机器人,1496)
[1524957]添加(bot,)
对于任何一个非具体的参数,我如何才能使它起作用呢?

(使用
bot
来处理其他被认为是
zero
null
0
有点奇怪。晶格不是我们主要关心的问题。)

首先,我们试图理解为什么程序没有终止。这可能相当棘手,尤其是在存在
的情况下
是Prolog的不纯元素之一。它们在一定程度上是需要的,但在这里,它们只是有害的,因为它们阻碍了我们的推理。因此,与其使用前两个cutful子句,不如使用

接下来的两次削减也是如此。请注意,这两个子句现在是不相交的。在此之后,我们有一个纯单调的程序,因此我们可以应用各种推理技术。在这种情况下,a正是我们所需要的。为了更好地理解不终止的原因,我将在程序中添加goals
false
,因为我们可以利用一个很好的属性:如果新程序不终止,那么旧程序也不会终止。通过这种方式,我们可以将问题缩小到原始程序的一小部分。经过几次尝试,我得出了以下失败片段:

add(bot,X,X) :- false. add(X,bot,X) :- false, dif(X,bot). add(z(X),z(Y),Res) :- false, add(X,Y,D), Res = z(D). add(z(X),o(Y),Res) :- false, add(X,Y,D), Res = o(D). add(o(X),z(Y),Res) :- false, add(X,Y,D), Res = o(D). add(o(X),o(Y),Res) :- addc(X,Y,D), false, Res = z(D). addc(bot,X,Res) :- add(X,o(bot),Res), false. addc(X,bot,Res) :- dif(X, bot), add(X,o(bot),Res), false. addc(z(X),z(Y),Res) :- false, add(X,Y,D), Res = o(D). addc(z(X),o(Y),Res) :- false, addc(X,Y,D), Res = z(D). addc(o(X),z(Y),Res) :- false, addc(X,Y,D), Res = z(D). addc(o(X),o(Y),Res) :- addc(X,Y,D), false, Res = o(D). ?- add(o(o(bot)),X,z(o(o(bot)))). 还提供了有利的终止条件:

% NTI summary:  Complete result is optimal.
add(A,B,C)terminates_if b(A),b(B);b(C).
    % optimal. loops found: [add(z(_),z(_),z(_)),add(o(bot),o(o(_)),z(z(_))),add(o(o(_)),o(bot),z(z(_)))]. NTI took    8ms,72i,30i
addc(A,B,C)terminates_if b(A),b(B);b(C).
    % optimal. loops found: [addc(z(z(_)),z(z(_)),o(z(_))),addc(bot,o(_),z(_)),addc(o(_),bot,z(_))]. NTI took    4ms,96i,96i
因此,
add/3
在给出前两个参数或最后一个参数时终止。所以你不需要第一个参数。相反,即使是更一般的查询也会终止:

?- add(X,Y,z(o(o(bot)))).
     X = bot, Y = z(o(o(bot)))
   ; X = z(o(o(bot))), Y = bot
   ; X = z(bot), Y = z(o(o(bot)))
   ; X = z(o(o(bot))), Y = z(bot)
   ; X = z(z(bot)), Y = z(o(o(bot)))
   ; X = z(z(o(bot))), Y = z(o(bot))
   ; X = z(z(z(bot))), Y = z(o(o(bot)))
   ; X = z(z(o(bot))), Y = z(o(z(bot)))
   ; X = z(o(bot)), Y = z(z(o(bot)))
   ; X = z(o(o(bot))), Y = z(z(bot))
   ; X = z(o(z(bot))), Y = z(z(o(bot)))
   ; X = z(o(o(bot))), Y = z(z(z(bot)))
   ; X = o(bot), Y = o(z(o(bot)))
   ; X = o(z(o(bot))), Y = o(bot)
   ; X = o(z(bot)), Y = o(z(o(bot)))
   ; X = o(z(o(bot))), Y = o(z(bot))
   ; X = o(z(z(bot))), Y = o(z(o(bot)))
   ; X = o(z(o(bot))), Y = o(z(z(bot)))
   ; X = Y, Y = o(o(bot))
   ; X = o(o(bot)), Y = o(o(z(bot)))
   ; X = o(o(z(bot))), Y = o(o(bot))
   ; X = Y, Y = o(o(z(bot)))
   ; false.

1更好的是,使用库的
reif
if/3
进行和 使这些条款尽可能确定

add(A, B, C) :- if_(A = bot, B = C, ( B = bot, A = C ) ).

消息
[1524957]add(bot,)
不能来自您的程序,因为没有
s/1
。只有
z/1
o/1
s。
?- add(X,Y,z(o(o(bot)))).
     X = bot, Y = z(o(o(bot)))
   ; X = z(o(o(bot))), Y = bot
   ; X = z(bot), Y = z(o(o(bot)))
   ; X = z(o(o(bot))), Y = z(bot)
   ; X = z(z(bot)), Y = z(o(o(bot)))
   ; X = z(z(o(bot))), Y = z(o(bot))
   ; X = z(z(z(bot))), Y = z(o(o(bot)))
   ; X = z(z(o(bot))), Y = z(o(z(bot)))
   ; X = z(o(bot)), Y = z(z(o(bot)))
   ; X = z(o(o(bot))), Y = z(z(bot))
   ; X = z(o(z(bot))), Y = z(z(o(bot)))
   ; X = z(o(o(bot))), Y = z(z(z(bot)))
   ; X = o(bot), Y = o(z(o(bot)))
   ; X = o(z(o(bot))), Y = o(bot)
   ; X = o(z(bot)), Y = o(z(o(bot)))
   ; X = o(z(o(bot))), Y = o(z(bot))
   ; X = o(z(z(bot))), Y = o(z(o(bot)))
   ; X = o(z(o(bot))), Y = o(z(z(bot)))
   ; X = Y, Y = o(o(bot))
   ; X = o(o(bot)), Y = o(o(z(bot)))
   ; X = o(o(z(bot))), Y = o(o(bot))
   ; X = Y, Y = o(o(z(bot)))
   ; false.
add(A, B, C) :- if_(A = bot, B = C, ( B = bot, A = C ) ).