2013-03-13 85 views
1

我对使用某些规则查询期间会发生什么感到困惑。 以下是我笔记中的示例代码。困惑于查询和回溯

link(fortran, algol60). 
link(algol60,cpl). 
link(cpl, bcpl). 
link(bcpl, c). 
link(c, cplusplus). 
link(algol60, simula67). 
link(simula67, cplusplus). 
link(simula67, smalltalk80). 

path(L,M) :- %first path 
    link(L,M). %first link 

path(L,M) :- %second path 
    link(L,X), %second link 
    path(X,M). %third path 



| ?- path(X,bcpl). 

当我们询问,我们将调用第一路径和X将被启动,以CPL,因为链路(CPL,BCPL)是在我们的数据库匹配的第一件事。所以现在L = cpl和M = bcpl。 X = cpl? ; 然后我们继续按下;

接下来会发生什么?我们称之为第一路还是第二路?如果我们失败了一条规则会发生什么,我们从第一条路开始?

+0

您可以实际使用的示踪剂自己回答你的问题。在尝试输入相同的目标之前,尝试输入:?? - trace.',您将看到所有调用,失败和重做。 – 2013-03-13 13:01:05

+0

我试图按照这个,但我迷路了,因为我不确定第三条路径是第一条路径还是第二条路径。 – Instinct 2013-03-13 13:07:31

+0

如果您正在使用SWI-Prolog,则行首的数字将告诉您是否要进入新的“框架”,即谓词的新调用。无论如何,你所说的“第三条路径”是谓词'路径'的新调用,它有两个子句。你的“第一”和“第二条路径”是谓词定义,而第三条“路径”实际上是一个子目标。这是一个根本的区别,它可以被我现在能想到的所有编程语言共享。 – 2013-03-13 13:10:54

回答

1

;您需要下一个解决方案。正如你已经知道的,Prolog中的替代方法用多个子句表达。

是真实的,一个抽象解释,自上而下,从左到右,不会尝试既不是第一个或第二路/ 2,但会尽量先看看有没有另一个link(X,bcpl)。因为编制索引,SWI-Prolog不会尝试调用其中任何一个(它知道没有其他链接/ 2适当),而是会回溯并尝试下一个路径/ 2(第二个规则)。

这里有一个(部分)跟踪:当你看到Redo时,表示它选择了下一个替代可用。括号之间的数字是调用级别,但可以看到的是,对于一些实现细节,证明没有从1开始

?- leash(-all), trace, path(X,bcpl). 
    Call: (7) path(_G2093, bcpl) 
    Call: (8) link(_G2093, bcpl) 
    Exit: (8) link(cpl, bcpl) 
    Exit: (7) path(cpl, bcpl) 
X = cpl ; 
    Redo: (7) path(_G2093, bcpl) 
    Call: (8) link(_G2093, _G2262) 
    Exit: (8) link(fortran, algol60) 
    Call: (8) path(algol60, bcpl) 
    Call: (9) link(algol60, bcpl) 
    Fail: (9) link(algol60, bcpl) 
    Redo: (8) path(algol60, bcpl) 
    Call: (9) link(algol60, _G2262) 
    Exit: (9) link(algol60, cpl) 
    Call: (9) path(cpl, bcpl) 
    Call: (10) link(cpl, bcpl) 
    Exit: (10) link(cpl, bcpl) 
    Exit: (9) path(cpl, bcpl) 
    Exit: (8) path(algol60, bcpl) 
    Exit: (7) path(fortran, bcpl) 
X = fortran ; 
    Redo: (9) path(cpl, bcpl) 
... 
    Fail: (8) path(cplusplus, bcpl) 
    Redo: (8) link(_G2093, _G2262) 
    Exit: (8) link(simula67, smalltalk80) 
    Call: (8) path(smalltalk80, bcpl) 
    Call: (9) link(smalltalk80, bcpl) 
    Fail: (9) link(smalltalk80, bcpl) 
    Redo: (8) path(smalltalk80, bcpl) 
    Call: (9) link(smalltalk80, _G2262) 
    Fail: (9) link(smalltalk80, _G2262) 
    Fail: (8) path(smalltalk80, bcpl) 
    Fail: (7) path(_G2093, bcpl) 
false. 
+0

所以从你说的话,在链接(cpl,bcpl)的初始匹配之后,prolog将尝试寻找其他链接(X,bcpl)。但由于没有,它会失败,并继续前进到第二条路径, 重做:(7)路径(_G2093,bcpl) 这是正确的吗? – Instinct 2013-03-13 13:22:58

+0

是的,我认为是。尝试路径(X,Y)以查看替代链接/ 2扫描。 – CapelliC 2013-03-13 13:40:44