【发布时间】:2019-03-04 14:56:37
【问题描述】:
我目前正在研究 Learn Prolog Now 示例,对于一个 exercise,如果我对一条规则进行了微小的更改,我的 KB 就会用完本地堆栈。这是知识库:
byCar(auckland,hamilton).
byCar(hamilton,raglan).
byCar(valmont,saarbruecken).
byCar(valmont,metz).
byTrain(metz,frankfurt).
byTrain(saarbruecken,frankfurt).
byTrain(metz,paris).
byTrain(saarbruecken,paris).
byPlane(frankfurt,bangkok).
byPlane(frankfurt,singapore).
byPlane(paris,losAngeles).
byPlane(bangkok,auckland).
byPlane(singapore,auckland).
byPlane(losAngeles,auckland).
travel(X,Y) :- byCar(X,Y).
travel(X,Y) :- byTrain(X,Y).
travel(X,Y) :- byPlane(X,Y).
及相关规则:
travel(X,Y) :- travel(X,Z), travel(Z,Y).
这是有问题的查询,它用完了堆栈:
?- travel(valmont,losAngeles).
但是如果我将规则更改为
travel(X,Y) :- travel(Z,Y), travel(X,Z).
然后就可以了。
如果我跟踪查询,我很快就会像这样卡住:
Redo: (17) travel(raglan, _6896) ? creep
Call: (18) byPlane(raglan, _6896) ? creep
Fail: (18) byPlane(raglan, _6896) ? creep
Redo: (17) travel(raglan, _6896) ? creep
Call: (18) travel(raglan, _6896) ? creep
Call: (19) byCar(raglan, _6896) ? creep
Fail: (19) byCar(raglan, _6896) ? creep
Redo: (18) travel(raglan, _6896) ? creep
Call: (19) byTrain(raglan, _6896) ? creep
Fail: (19) byTrain(raglan, _6896) ? creep
Redo: (18) travel(raglan, _6896) ? creep
Call: (19) byPlane(raglan, _6896) ? creep
Fail: (19) byPlane(raglan, _6896) ? creep
Redo: (18) travel(raglan, _6896) ? creep
...
但我不明白为什么。它不应该只是理解 raglan 是一个终端站,因此它必须再回溯一层吗?
谢谢!
编辑:我使用 SWI Prolog
编辑:我在一步步解决后发现了问题。
在插肩的情况下,任何地方都没有规则。因此,在尝试byPlane, byTrain, byCar 之后,它再次尝试travel(raglan, X)(最后一条规则的第一个目标),从而循环。
但我看不出另一条规则有什么更好的地方。
【问题讨论】:
标签: prolog backtracking failure-slice non-termination