要计算两个相同长度的列表之间的汉明距离,我使用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/4
与foldl/5
一起仍然是正确的,或者对于A和B都是基础的查询仍然是正确的。
那么有一个很好的理由选择一个而不是另一个吗?或者有理由按规定保留规则或切换它们吗?
我知道查询
hamm(a, B, 0, 1).
是假的,而
hamm2(a, B, 0, 1).
是真的,但我无法确定哪一个更有意义。 。
答案 0 :(得分:2)
OP实现了两个累加器式谓词来计算汉明距离(hamm/4
和hamm2/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
错误成功时正确失败,反之亦然。
所以两个都是半正确/半错误,而都不是一个
坚定不移。
可以做些什么?
根据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.