我建议你不要遵循JuhoÖstman提出的路径并保持纯洁 - 否则,为什么要在第一个例子中使用Prolog?如果你坚持逻辑范式太宽大,你会得到一些令人不快的结果。在这种情况下,Juho的谓词绝对不同于你的,我会告诉你为什么。正如larsmans所说,首先,放弃无用的edu_le(A,B) :- edu_less(A,B).
规则。你会得到你原来的谓词的少冗余版本:
edu_le1(A, A).
edu_le1(A, B) :- edu_less(A, C), edu_le1(C, B).
它只是表现为edu_le
,意思是:给定一个任意的查询,它产生完全一样的答案,除了重复(edu_le1
具有以下)。你可能只是对它感到满意,但它仍然有一些你可能不喜欢的冗余答案;例如,SWI下:
?- edu_le1(hs, hs)
true ;
false.
现在你可以说你不喜欢它,因为它仍然具有冗余false
,但如果你使用的Juho的谓词代替(没有无用的规则):
edu_le2(A, A) :- !.
edu_le2(A, B) :- edu_less(A, C), edu_le2(C, B).
你消除它是真的没用的最终false
:
?- edu_le2(hs, hs)
true.
?-
,但你失去不止于此:你输了,作为垫的话,产生的所有次的可能性当一个变量没有实例化Ê解决方案:
?- edu_le1(hs, B) %same, with more copies, for edu_le
B = hs ;
B = college ;
B = masters ;
B = phd ;
false.
?- edu_le2(hs, B)
B = hs. %bad!
?-
换句话说,后者谓词不是相当于前者:edu_le
和edu_le1
具有类型edu_le(?A, ?B)
,而代替edu_le2
具有类型edu_le2(+A, +B)
(参见[1]的含义)。请确保:edu_le2
不太有用,因为它的功能较少,因此可以在较少的上下文中重复使用。这是因为edu_le2
中的剪切是一种红色剪切,即剪切,它改变了引入谓词的含义。鉴于您了解两者之间的差异,您可能会满意它。这完全取决于你想用它做什么。
如果你想获得最好的两个世界,你需要在edu_le1
中引入一个适当的绿色切割,当A和B被完全实例化时,降低冗余度。在此目的下,您必须检查A和B在切割前是否被实例化为相同的术语。你不能用=
来做,因为=
不检查,但统一。正确的操作是==
:
edu_le3(A, B) :- (A == B -> ! ; true), A = B.
edu_le3(A, B) :- edu_less(A, C), edu_le3(C, B).
注意的是,在第一条规则的附加切口才能处于激活A
和B
碰巧是同一个术语。现在的发型是一种合适的绿色切,谓语也工作在最一般的情况下,你原来一个:
?- edu_le3(A, A).
true.
?- edu_le3(A, B). %note that A and B are not the same term
A = B ;
A = hs,
B = college ;
A = hs,
B = masters ;
A = hs,
B = phd ;
A = college,
B = masters ;
A = college,
B = phd ;
A = masters,
B = phd ;
false.
?-
与Prolog的通过所有的解决方案回溯。
我不认为有一种方法可以消除最后的false
而不会对edu_lt
引入太强的依赖性。这是因为我们必须保持开放的可能性,以便在后来决定用更多的基础事实来丰富它时再探索另一个edu_lt
。所以,在我看来,这是最好的你可以拥有。
[1] SWI Prolog的参考手册,第4.1节。
AHHHHHHHH(像圣洁啊)。谢谢。感谢上帝,我不是纯粹主义者吧? – Matt 2010-10-18 04:35:02