【问题标题】:Backtracking in recursive predicates递归谓词中的回溯
【发布时间】:2014-12-03 07:15:58
【问题描述】:

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

[F0] isInteger(0).
[F1] isInteger(X):- isInteger(Y), X is Y+1.
  1. 查询的第一个结果是Integer(R),标记放在F0,会返回R=0

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

我了解以上内容。现在这是我的问题:

  1. 如果用户按下 ;再次,标记在哪里?搜索如何继续返回 R=2?我试图理解这本书第 78-79 页中的图像,但我不清楚。我发现的在线教程在存在递归的情况下不处理回溯。

我正在寻找任何解释存在递归的回溯的教程,希望有帮助我理解的堆栈内容图像。

提前谢谢你 苏珊娜

【问题讨论】:

    标签: prolog failure-slice


    【解决方案1】:

    使用图像理解回溯和递归适用于非常小的示例,但不适用于更大的程序。此外,通过单步执行程序,您很容易错过最有趣的属性。幸运的是,还有比这更好的概念。让我们以isInteger/1 为例。

    解决方案/答案集

    您的主要兴趣是确保您描述的内容是正确的。在这里,第二条规则是最有趣的。按照箭头:- 的方向阅读。也就是说,从右到左:如果Y 是一个整数,而X is Y+1 那么X 也是一个整数。

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

    终端属性

    下一个问题涉及谓词的终止属性。请注意,如果它必须产生无限多的答案,它就不能——事实上不得——终止。另一方面,像isInteger(1) 这样的地面查询要么有一个解决方案,要么没有解决方案。因此,对于这种情况,谓词终止是可取的。但是,您的定义不会在这里终止!

    失败切片

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

    ?- isInteger(1), isInteger(0) :- false。 是整数(X): - isInteger(Y), , X 是 Y+1

    只有极少部分负责不终止!剩下的部分甚至根本不看X 的值。因此,您的程序从不终止。不管你怎么称呼它。

    更多示例请参见

    【讨论】:

    • 感谢您的解释
    【解决方案2】:

    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
    

    “Next”(注意我们在缩进'____'处重新开始)

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

    非常好。

    我将向当地团队解释这一点。这是一个带有一些“原始符号”的整数枚举过程的说明。希望不言自明。

    【讨论】:

    • 你调用正确的程序不能用于枚举自然数。
    • @false 太棒了!显然我错了。我需要考虑更多。
    猜你喜欢
    • 2018-10-09
    • 1970-01-01
    • 2011-09-20
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 2016-09-27
    相关资源
    最近更新 更多