6

为了计算两个相同长度的列表之间的汉明距离,我使用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.

并且对于 A 和 B 都接地的查询hamm2/4仍然是正确的。foldl/5

那么,是否有充分的理由偏爱其中一个而不是另一个呢?还是有理由保持规则的顺序或改变它们?

我知道查询

hamm(a, B, 0, 1).

是假的,而

hamm2(a, B, 0, 1).

是真的,但我不能完全决定哪一个更有意义。. .

4

2 回答 2

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/4时正确地失败hamm2/4,反之亦然。所以两者都是半对半错,没有一个是坚定的。


可以做什么?

基于if_/3并由(=)/3@false 在此答案中提出,我为谓词实现了以下纯代码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.
于 2015-04-27T06:24:28.097 回答
-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.
于 2012-12-20T08:52:03.053 回答