简体   繁体   English

Prolog 二进制加法

[英]Prolog binary addition

I need to implement binary addition in prolog, where binary numbers are represented as follows:我需要在prolog中实现二进制加法,其中二进制数表示如下:

0:  bot
1 : o(bot)
2 -> 10:  z(o(bot))
3 -> 11:  o(o(bot))
10 -> 1010:  z(o(z(o(bot))))

I've written this:我写过这个:

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

It works when the first 2 arguments are concrete:当前两个参数是具体的时,它起作用:

?-add(o(o(bot)),z(o(o(bot))),D).
D = o(z(z(o(bot))))

When one of the first 2 arguments is a variable, it goes into an infinite recursion:当前两个参数之一是变量时,它进入无限递归:

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

How can i make this work for any one non-concrete argument?我怎样才能使这项工作适用于任何一个非具体的论点?

(Using bot for what is otherwise considered zero , null or 0 is a bit odd. Lattices are not our major concern here.) (使用bot否则被认为是zeronull0有点奇怪。格子不是我们在这里的主要关注点。)

First, we try to understand why the program does not terminate.首先,我们试图理解为什么程序不会终止。 This can be quite tricky, in particular in presence of the !这可能非常棘手,尤其是在! which is one of Prolog's impure elements.这是Prolog的不纯元素之一。 They are needed to a certain degree, but here in this case, they are harmful only, as they are hindering our reasoning.它们在一定程度上是需要的,但在这种情况下,它们只是有害的,因为它们阻碍了我们的推理。 So instead of the first two cutful clauses, write 1所以不要写前两个cutful子句,而是写1

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

and similarly for the next two cuts.接下来的两次剪辑也是如此。 Note that those two clauses are now disjoint.请注意,这两个子句现在是不相交的。 After this we have a pure monotonic program and thus we can apply various reasoning techniques.在此之后,我们有一个纯单调程序,因此我们可以应用各种推理技术。 In this case, a is just what we need.在这种情况下, 正是我们所需要的。 To better understand the reason for non-termination, I will add goals false into the program, for there is a nice property we can exploit: If the new program does not terminate, then also the old one will not terminate.为了更好地理解不终止的原因,我将在程序中添加目标false ,因为我们可以利用一个很好的特性:如果新程序不终止,那么旧程序也不会终止。 In this manner we can narrow down the problem to a smaller part of the original program.通过这种方式,我们可以将问题缩小到原始程序的一小部分。 After a couple of tries, I came up with the following failure-slice:经过几次尝试,我想出了以下失败片段:

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

Out of the ~2^23 possible failure slices, this appears to be a minimal one.在 ~2^23 个可能的故障切片中,这似乎是最小的一个。 That is, any further false makes the program terminate.也就是说,任何进一步的false都会使程序终止。

Let's look at it: Everywhere Res is either ignored or just passed further on.让我们看看它:Everywhere Res要么被忽略,要么被进一步传递。 Therefore the third argument has no influence on termination whatsoever.因此,第三个参数对终止没有任何影响。 But you can put all those Res = equations just after the :- .但是您可以将所有这些Res =方程放在:- That's the earliest possible place.那是最早的地方。

add(bot,X,X).
add(X,bot,X):- dif(X,bot).
add(z(X),z(Y), z(D)) :- add(X,Y,D).
add(z(X),o(Y), o(D)) :- add(X,Y,D).
add(o(X),z(Y), o(D)) :- add(X,Y,D).
add(o(X),o(Y), z(D)) :- addc(X,Y,D).

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

Also cTI gives favorable termination conditions: cTI还给出了有利的终止条件:

% 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

So add/3 terminates either if the first two, or the last argument are given.因此,如果给出前两个参数或最后一个参数,则add/3终止。 So you do not need the first argument.所以你不需要第一个参数。 In stead, even the more general query terminates:相反,即使是更一般的查询也会终止:

?- 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 And even better, use if_/3 of library reif for SICStus and SWI to keep those clauses as determinate as possible. 1 更好的是,对SICStusSWI使用库reif if_/3以保持这些子句尽可能确定。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM