如果我有以下知识库,如何在parent_of术语中添加一个剪切,以便如果X已经确定为父亲,prolog将不会尝试“检查”X是否也是母亲?
father_of(max,john).
father_of(max,james).
father_of(max,gabe).
mother_of(june,john).
mother_of(june,james).
parent_of(X,Y) :- father_of(X,Y).
parent_of(X,Y) :- mother_of(X,Y).
例如,我想:
parent_of(max,Y)为:Y = john,Y = james,Y = gabe
parent_of(june,Y)为:Y = john,Y = james
对于第一个,我不希望prolog甚至试图检查max是否是一个母亲,因为已经确定他是一个父亲。
我已经尝试了很多组合,包括:
parent_of(X,Y) :- father_of(X,Y),!. <-- fixes an X and Y and thus will list only Y=john
parent_of(X,Y) :- !,father_of(X,Y). <-- works for parent_of(max,Y) but not parent_of(jane)
这甚至可能吗?
答案 0 :(得分:1)
进行此类优化非常棘手。 Prolog在这些问题上的表现非常出色,没有任何优化。
但作为一般规则:您不能简单地将切入设置为程序,您需要提前执行各种测试。我怀疑这些测试比你打算删除的开销更容易。这是一次尝试。老实说,我的感觉并不是很好,因为你应该先学习纯粹的Prolog。
因此我们假设没有解决方案:?- father_of(P,_), mother_of(P,_).
parent_of(F, C) :- ( atom(F), \+ \+ father_of(F, _) -> ! ; true ), father_of(F, C). parent_of(M, C) :- mother_of(M, C).
这真的更好吗?也许,也许不是。
但无论如何,您已经理解了一个重点:聪明的优化需要进行广泛的测试。我相信上面是正确的,但我甚至不确定这会更快。毕竟,现在有两个father_of/2
的查找代替father_of/2
,一个mother_of/2
。天真的版本可能会更快......
答案 1 :(得分:0)
为此,一些Prolog系统提供了“软切”*->/2
:
parent_of(X,Y) :- father_of(X,Y) *-> true ; mother_of(X,Y).
一般情况下,对于If *-> Then ; Else
,如果条件If
成功,Then
被执行,则只返回If
和Then
的替代解决方案。只有在If
根本没有解决方案的情况下,才会执行Else
。
这要求您了解谓词的模式,即调用模式。在您的情况下,如果谓词parent_of
的模式为parent_of(++,?)
,则添加软剪辑就可以了(假设名称是唯一的或仅针对一种性别显示)。在parent_of(++,++)
的情况下,即使是常规切割也没关系,除非您的数据库中有重复的事实(对称性破坏是切割的一个用例)。但是,如果你还需要迎合parent_of(-,?)
,那么削减真的会削减解决方案。
一般情况下:只有当您确定切出的搜索树的分支不包含解决方案或仅包含您不感兴趣的对称解决方案时,才使用剪切。