我目前正在研究 Learn Prolog Now 示例,对于一个练习,如果我对一条规则进行微小更改,我的 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)
再次尝试(最后一条规则的第一个目标),从而循环。但我看不出另一条规则有什么更好的地方。