2012-12-20 16 views
6

obliczyć odległość Hamminga pomiędzy dwoma listami o tej samej długości, używam foldl(hamm, A, B, 0, R). z tej definicji hamm/4:Powołując się na zamówienie reguły

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

Cięcia w pierwszej regule zapobiega niepotrzebnemu Backtracking. Druga reguła, jednak mogło być napisane inaczej:

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

i hamm2/4 nadal będą poprawne razem z foldl/5 lub zapytań, gdzie A i B są szlifowane.

Czy istnieje naprawdę dobry powód, aby preferować ten jeden nad drugim? Czy istnieje powód, aby zachować zasady w tej kolejności lub je zmienić?

wiem, że zapytanie

hamm(a, B, 0, 1). 

jest fałszywa, a

hamm2(a, B, 0, 1). 

to prawda, ale nie mogę się zdecydować, który z nich dość większy sens. . .

Odpowiedz

-1

Już zauważyłeś różnice między tymi definicjami: skuteczność oddzielnie, powinieneś zdecydować o swoich wymaganiach. Czy zaakceptujesz zmienne w strukturach danych? Taki styl programowania wprowadza niektóre zaawansowane funkcje Prolog (niepełne struktury danych).

Zresztą, myślę, że pierwsza forma jest bardziej dokładne (nie do końca pewny, powiedziałbym niezłomną 4 ° argumentu)

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

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

podczas hamm2 jest

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

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

Można argumentować, na 'hamm2 (A, B, 0, 1)', tak, B nie jest tak samo jak A, więc te dwa elementy powinny dodać do dystansu Hamminga ... ale jak już powiedziałem, nie mogę również zdecydować, kiedy to ma sens. –

2

PO zaimplementował dwie predykaty w stylu akumulatorów do obliczania odległości Hamminga (hamm/4 i hamm2/4), ale nie był pewien, który z nich ma sens.

Przeczytajmy zapytanie, które zaintrygowało OP: "Czy istnieje X, że odległość (a, X) wynosi 1?". Oto „odpowiedź” Prolog daje:

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

z logicznego punktu widzenia, oba implementacje źle się zachowywać w powyższym teście. Zróbmy kilka testów dla niezłomności:

?- 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. 

Należy zauważyć, że w poprzednich zapytaniach hamm/4 słusznie nie kiedy hamm2/4 błędnie udało, i vice versa. Tak zarówno są pół-prawo/pół-źle, a ani jeden jest niezłomny.


Co można zrobić?

podstawie if_/3 i (=)/3 przedstawionego przez @false w this answer, I wdrożone następujące czystego kodu dla orzecznika hamm3/4:

:- use_module(library(clpfd)). 

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

Teraz powtórzmy powyżej zapytań za pomocą 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. 

To działa! Wreszcie niech zadać najbardziej ogólne zapytaniezobaczyć cały zestaw rozwiązań z hamm3/4:

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