回溯递归谓词

时间:2013-01-02 00:48:23

标签: prolog failure-slice

假设我们有以下谓词(这是来自Programming in Prolog的示例):

[F0] isInteger(0).
[F1] isInteger(X):- isInteger(Y), X is Y+1.
  1. 查询的第一个结果isInteger(R),标记位于F0,将返回R = 0

  2. 如果用户按下; ,标记放在F1,我们移动到subgoal(isInteger(Y),满意F0)和R = 1.

  3. 我理解上面的内容。现在我的问题是:

    1. 如果用户按下;再次,标记在哪里?搜索如何继续返回R = 2?我试图理解本书第78-79页中的图像,但我不清楚。我发现的在线教程不会在递归的情况下处理回溯。
    2. 我正在寻找任何解释存在递归的回溯的教程,希望能够帮助我理解堆栈内容的图像。

      提前谢谢你 苏珊

2 个答案:

答案 0 :(得分:8)

通过使用图像来理解回溯和递归适用于非常小的示例,但它不能扩展到更大的程序。此外,通过单步执行程序,您很容易错过最有趣的属性。幸运的是,有更好的概念。我们举个例子isInteger/1

解决方案/答案集

您的主要兴趣是确保您描述正确的事情。在这里,第二条规则最有趣。按箭头:-的方向阅读。也就是说,从右到左:提供Y是整数,X is Y+1X也是整数。

然后,您可以估计在这种情况下无限的解决方案集。

终止属性

下一个问题涉及谓词的终止属性。注意,它不能 - 实际上必须不 - 终止,如果它必须产生无限多的答案。另一方面,像isInteger(1)这样的地面查询有一个或没有解决方案。因此,期望谓词终止于这种情况。但是,您的定义不会在此处终止!

故障片

为了更好地理解这一点,我将使用failure-slice。也就是说,我会在您的计划中插入 false 目标。如果生成的程序片段没有终止,则原始程序片段不会终止。

?- isInteger(1), false

isInteger(0) :- false.
isInteger(X) :-
   isInteger(Y), false,
   X is Y+1.

只有很小一部分负责不终止!其余部分甚至根本没有查看X的值。因此,您的程序将终止 never 。不管你怎么称呼它。

有关更多示例,请参阅

答案 1 :(得分:0)

swish控制台中跟踪此内容:

% Handover to indenting predicate

isInteger(X) :- isInteger(X,0).

% As isInteger(), with printouts

isInteger(0,I) :- ws(I), format('0 reached\n').
isInteger(X,I) :- wrout('>', X,Y,I), ID is I+1, isInteger(Y,ID), wrout('<', X,Y,I), X is Y+1, wsucc(I).

% Writing out

wrout(C,X,Y,I) :-ws(I),format('~a X=',C),write(X),format(',Y='),write(Y),format('\n').

% Writing "success"

wsucc(I) :- ws(I),format('success\n').

% Indenting by 2*N underscores

ws(0).
ws(N) :- N>0, format('__'), ND is N-1, ws(ND).

通过? - isInteger(2).检查2是否为整数(但不要为此调用Next或将发生永不停止的搜索!)

> X=2,Y=_G5707
__0 reached
< X=2,Y=0
__> X=_G5707,Y=_G6473
____0 reached
__< X=_G5707,Y=0
__success
< X=2,Y=1
success
true

使用?- isInteger(I)

枚举整数
0 reached
I = 0

“下一步”

> X=_G5328,Y=_G5926
__0 reached
< X=_G5328,Y=0
success
I = 1

“下一步”(请注意我们在缩进'__'处重新启动)

__> X=_G5926,Y=_G391
____0 reached
__< X=_G289,Y=0
__success
< X=_G257,Y=1
success
I = 2

“下一步”(请注意我们在缩进'____'处重新启动)

____> X=_G391,Y=_G3260
______0 reached
____< X=_G391,Y=0
____success
__< X=_G289,Y=1
__success
< X=_G257,Y=2
success
I = 3

非常好。

我将向当地团队解释。下面是整数枚举过程的示意图,其中包含一些“原始符号”。希望不言自明。

integer enumeration backtracking illustration