OPは、ハミング距離(hamm/4
およびhamm2/4
)を計算するために2つのアキュムレータスタイルの述語を実装しましたが、どちらがより理にかなっているのかわかりませんでした。
OPを困惑させたクエリを読んでみましょう:「distance(a、X)が1になるようなXはありますか?」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
、その逆も同様であることに注意してください。したがって、どちらも半分正しい/半分間違っており、どちらも不動ではありません。
何ができる?
この回答の@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.