2017-10-17 74 views
1

我定義我的知識基礎爲:Prolog的切割操作

edge(mammal,isa,animal). 
edge(human,isa,mammal). 
edge(simba,isa,human). 

edge(animal,swim,bybirth). 
edge(human,swim,mustlearn). 

path(X,Y) :- edge(X,isa,Y). 
path(X,Y) :- edge(X,isa,Z), path(Z,Y). 

swim(X,Y) :- edge(X,swim,Y). 
swim(X,Y) :- path(X,Z), swim(Z,Y). 

現在,用上面的知識基礎,我用下面的:

?- swim(simba,bybirth). 
?- swim(simba,mustlearn). 

而對於這兩個疑問,序言返回true 。我希望Prolog先檢查本地游泳場所,然後以分級方式查看直接父級,等等。當我們知道Simba「mustlearn」游泳時,它應該停止搜索,並且不應再往下看。因此,它應該爲第一個查詢返回false,爲第二個查詢返回true。

我知道它必須通過限制回溯來完成。我嘗試使用剪切而不是運營商,但不能成功。有沒有辦法做到這一點?

回答

1

我試過了,也遇到了問題。我想這可能工作:

swim(X,Y) :- once((edge(X,swim,Y); path(X,Z), swim(Z,Y))). 

它不工作,因爲如果Y已經被實例化的方式,第一步將無法統一,它會嘗試第二借道human中間去。所以即使查詢只產生一個結果,它也可能被愚弄爲產生swim(simba, bybirth)。解決的辦法是逼的Prolog承諾的另一個變量綁定,然後檢查的承諾後綁定:

swim(X,Y) :- 
    once((edge(X,swim,Method); path(X,Z), swim(Z,Method))), 
    Method = Y. 

這告訴Prolog的,只有一種方式來獲得這種方法,使發現的方法,然後它必須是Y.如果你發現錯誤的方法,它不會繼續搜索,它會失敗。嘗試一下!