我将我的知识库定义为:
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).
对于这两个查询,Prolog返回true。我希望Prolog首先在本地检查属性游泳,然后查看直接父级,依此类推。一旦我们知道辛巴“必须”游泳,它应该停止搜索,不应该再看了。因此,对于第一个查询,它应该返回false,对于第二个查询,它应该返回true。
我知道必须通过限制回溯来完成。我尝试使用剪切而不是操作符,但无法成功。有没有办法实现这个目标?
答案 0 :(得分:0)
我尝试了它并遇到了一个问题。我认为这可能有用:
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.如果找到错误的方法,它就不会继续搜索,它只会失败。试试吧!