Prolog Cut运算符

时间:2017-10-17 20:26:32

标签: prolog prolog-cut

我将我的知识库定义为:

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。

我知道必须通过限制回溯来完成。我尝试使用剪切而不是操作符,但无法成功。有没有办法实现这个目标?

1 个答案:

答案 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.如果找到错误的方法,它就不会继续搜索,它只会失败。试试吧!