Prolog 困惑于查询和回溯
我对使用一些规则进行查询时会发生什么感到有点困惑。 下面是我笔记中的示例代码Prolog 困惑于查询和回溯,prolog,Prolog,我对使用一些规则进行查询时会发生什么感到有点困惑。 下面是我笔记中的示例代码 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 lin
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,因为link(cpl,bcpl)是数据库中匹配的第一个东西。现在L=cpl,M=bcpl。
X=cpl;
然后我们继续施压
接下来会发生什么?我们叫第一条路还是第二条路?如果我们没有通过规则,我们会从第一条路径开始吗?按
代码>您需要下一个解决方案。正如您已经知道的,Prolog中的备选方案用多个子句表示
诚然,从上到下、从左到右的抽象解释不会尝试第一条路径或第二条路径/2,而是首先尝试查看是否存在另一个链接(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.
按代码>您需要下一个解决方案。正如您已经知道的,Prolog中的备选方案用多个子句表示
诚然,从上到下、从左到右的抽象解释不会尝试第一条路径或第二条路径/2,而是首先尝试查看是否存在另一个链接(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.
实际上,您可以使用跟踪程序自己回答您的问题。尝试键入:?-trace.
在尝试相同的目标之前,在提示符处键入,您将看到所有调用、失败和重做-s。我已尝试遵循此操作,但我迷路了,因为我不确定第三个路径调用的是第一个路径还是第二个路径。如果您使用的是SWI Prolog,行首的数字将告诉您是否进入一个新的“框架”,即谓词的新调用。无论如何,您所调用的“第三条路径”是对谓词path
的新调用,它有两个子句。您的“第一条”和“第二条路径”是谓词定义,而第三条“路径”实际上是一个子目标。这是一个基本的区别,我现在能想到的所有编程语言都有这个区别。实际上,你可以自己使用跟踪程序来回答你的问题。尝试键入:?-trace.
在尝试相同的目标之前,在提示符处键入,您将看到所有调用、失败和重做-s。我已尝试遵循此操作,但我迷路了,因为我不确定第三个路径调用的是第一个路径还是第二个路径。如果您使用的是SWI Prolog,行首的数字将告诉您是否进入一个新的“框架”,即谓词的新调用。无论如何,您所调用的“第三条路径”是对谓词path
的新调用,它有两个子句。您的“第一条”和“第二条路径”是谓词定义,而第三条“路径”实际上是一个子目标。这是一个基本的区别,我现在能想到的所有编程语言都有这个区别。因此,从您所说的,在link(cpl,bcpl)的初始匹配之后,prolog将尝试寻找其他link(X,bcpl)。但由于没有,它将失败并转到第二条路径,重做:(7)路径(_G2093,bcpl)是否正确?是的,我认为正确。尝试路径(X,Y)以查看替代链接/2扫描。因此,根据您所说的,在链接(cpl,bcpl)的初始匹配之后,prolog将尝试查找其他链接(X,bcpl)。但由于没有,它将失败并转到第二条路径,重做:(7)路径(_G2093,bcpl)是否正确?是的,我认为正确。尝试路径(X,Y)以查看备选链接/2扫描。