Prolog 递归谓词中的回溯

Prolog 递归谓词中的回溯,prolog,failure-slice,Prolog,Failure Slice,假设我们有以下谓词(这是来自的一个示例): 查询的第一个结果是integer(R),标记被放置在F0,并将返回R=0 如果用户按,标记放置在F1,我们移动到子目标(isInteger(Y),它满足于F0)和R=1 我理解上述情况。下面是我的问题: 如果用户按下;再说一遍,标记在哪里?搜索如何继续返回R=2?我试图理解书中78-79页的图像,但我不清楚。我发现的在线教程在存在递归的情况下不处理回溯 我正在寻找任何教程,解释在递归存在的回溯,希望与堆栈内容的图像,帮助我理解 先谢谢你 Suzanne

假设我们有以下谓词(这是来自的一个示例):

  • 查询的第一个结果是integer(R),标记被放置在F0,并将返回R=0

  • 如果用户按,标记放置在F1,我们移动到子目标(isInteger(Y),它满足于F0)和R=1

  • 我理解上述情况。下面是我的问题:

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

    先谢谢你
    Suzanne

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

    一套解决方案/答案 你的主要兴趣是确保你描述的东西是正确的。在这里,第二条规则最有趣。按照箭头的方向阅读它
    :-
    。也就是说,从右到左:假设
    Y
    是一个整数,
    X是Y+1
    那么
    X
    也是一个整数

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

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

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

    ?- isInteger(1), false isInteger(0) :- false. isInteger(X) :- isInteger(Y), false, X is Y+1. ?-isInteger(1),假 isInteger(0):-false。 isInteger(X):- isInteger(Y),假, X是Y+1。 只有很小的一部分负责不终止!剩下的部分甚至根本不看
    X
    的值。因此,您的程序永远不会终止。不管你怎么称呼它

    有关更多示例,请参阅。

    在控制台中跟踪此操作:

    使用
    ?-isInteger(I)
    枚举整数

    “下一个”

    >X=\u G5328,Y=\u G5926
    __达到0
    
    “下一步”(请注意,我们在缩进“\uu”处重新启动)

    \uuux=\ug5926,Y=\ug391
    ____达到0
    __
    “下一步”(请注意,我们在缩进“\uuuuuuuuuuuuuuuu”处重新启动)

    \uuuuuuux=\ug391,Y=\ug3260
    ______达到0
    ____
    非常好

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


    谢谢您的解释。您调用的正确程序不能用于枚举自然数。@错误,非常好!显然我错了。我需要更多地考虑这个问题。 ?- isInteger(1), false isInteger(0) :- false. isInteger(X) :- isInteger(Y), false, X is Y+1.
    % 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).
    
    > 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
    
    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