1

我将我的知识库定义为:

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。

我知道必须通过限制回溯来完成。我尝试使用 cut 而不是运算符,但没有成功。有没有办法做到这一点?

4

1 回答 1

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

于 2017-10-17T23:01:00.307 回答