1

我是逻辑编程和 Prolog 的新手。下面的 Prolog 程序定义了一个谓词add/3,用于将第一个参数与第二个参数相乘,从而得到第三个参数,基于方程x + y = z等价于 ( x - 1) + y = ( z - 1) :

add(0, Y, Y) :-
  number(Y).
add(X, Y, Z) :-
  number(X),
  number(Z),
  succ(U, X),
  succ(V, Z),
  add(U, Y, V).

但是这个查询,应该解决方程 1 + 0 = z,不返回预期的结果 ( 1):

?- add(1, 0, Z).
   false.

如何解决这个递归加法?

4

1 回答 1

1

您得到的原因是因为调用false的第二个子句仅对地号变量成功,但您在未实例化的情况下调用它。不能用作发电机。add/3number(Z)Znumber/1

删除该目标反过来会给您带来另一个错误,现在succ(V, Z)您最终调用它时使用了两个未实例化的变量,并且该谓词要求至少实例化它的一个参数。

您可以将目标与递归调用交换,add/3以便V在调用之前实例化succ/2。由于succ/2已经检查了它的参数,我将删除对X数字的检查。

add(0, Y, Y) :-
  number(Y).
add(X, Y, Z) :- 
  succ(U, X),
  add(U, Y, V),
  succ(V, Z).

这个过程现在应该适用于模式 +,+,?。它不适用于其他模式。您可能需要检查CLP(fd)


为了使其在三个参数中最多使用 1 个未绑定变量,您可以在两个不同的路径上拆分递归步骤,以确保第一次调用succ/2具有 1 个绑定变量,而第二次调用succ/2具有至少 1 个绑定变量。

add(0, Y, Y) :-
  number(Y).
add(X, Y, Z) :-
  (var(Z) -> L1-R1/L2-R2 = U-X/V-Z; L2-R2/L1-R1 = U-X/V-Z),
  succ(L1, R1),
  add(U, Y, V),
  succ(L2, R2).

它本质上选择了一个可以用 Prolog 算术评估的方程。

于 2021-07-30T18:34:08.573 回答