依靠规则顺序

时间:2012-12-20 07:11:45

标签: prolog meta-predicate

要计算两个相同长度的列表之间的汉明距离,我使用foldl(hamm, A, B, 0, R).定义hamm/4

hamm(A, A, V, V) :- !.
hamm(A, B, V0, V1) :- A \= B, V1 is V0 + 1.

第一条规则中的切入可防止不必要的回溯。然而,第二条规则的写法可能不同:

hamm2(A, A, V, V) :- !.
hamm2(_, _, V0, V1) :- V1 is V0 + 1.

hamm2/4foldl/5一起仍然是正确的,或者对于A和B都是基础的查询仍然是正确的。

那么有一个很好的理由选择一个而不是另一个吗?或者有理由按规定保留规则或切换它们吗?

我知道查询

hamm(a, B, 0, 1).

是假的,而

hamm2(a, B, 0, 1).

是真的,但我无法确定哪一个更有意义。 。

2 个答案:

答案 0 :(得分:2)

OP实现了两个累加器式谓词来计算汉明距离(hamm/4hamm2/4),但不确定哪一个更多感觉。

让我们读一下困惑OP的问题:“X是否有距离(a,X)为1?”。以下是Prolog给出的“答案”:

?- hamm(a,X,0,1). 
false.                          % wrong: should succeed conditionally
?- hamm2(a,X,0,1).              % wrong: should succeed, but not unconditionally
true.

从逻辑角度来看,两个实现都在上面的测试中行为不端。让我们为坚定性进行一些测试

?- hamm(a,X,0,1),X=a.           % right
false.
?- hamm(a,X,0,1),X=b.           % wrong: should succeed as distance(a,b) is 1
false.

?- hamm2(a,X,0,1),X=a.          % wrong: should fail as distance(a,a) is 0
X = a.
?- hamm2(a,X,0,1),X=b.          % right 
X = b.

请注意,在先前的查询中hamm/4hamm2/4错误成功时正确失败,反之亦然。 所以两个都是半正确/半错误,而都不是一个 坚定不移。

可以做些什么?

根据this answer中@false提供的if_/3(=)/3,我为谓词hamm3/4实现了以下纯代码:

:- use_module(library(clpfd)).

hamm3(A,B,V0,V) :-
   if_(A = B, V0 = V, V #= V0+1).

现在让我们使用hamm3/4重复上述查询:

?- hamm3(a,X,0,1). 
dif(X,a).
?- hamm3(a,X,0,1),X=a.
false.
?- hamm3(a,X,0,1),X=b.
X = b.

它有效!最后,让我们让最常见的查询查看hamm3/4的整个解决方案集:

?- hamm3(A,B,N0,N).
A = B,    N0 = N ;
dif(A,B), N0+1 #= N.

答案 1 :(得分:-1)

您已经发现了这些定义之间的差异:效率除外,您应该决定您的要求。您是否要接受数据结构中的变量?这种编程风格引入了一些高级Prolog功能(不完整的数据结构)。

无论如何,我认为第一种形式更准确(不太确定,我会说坚持4°论证

?- hamm(a, B, 0, 1).
false.

?- hamm(a, B, 0, 0).
B = a.

而hamm2是

?- hamm2(a, B, 0, 1).
true.

?- hamm2(a, B, 0, 0).
B = a.