Mögliche Damerau-Levenshtein-Verbesserung?

9

Ich habe kürzlich den Damerau-Levenshtein-Distanzalgorithmus aus dem Pseudocode auf Wikipedia implementiert. Ich konnte keine Erklärung genau das finden , wie es funktioniert und der Pseudo - Code verwendet vollständig uninformativ Variablennamen wie DA, DB, i1, und j1das ließ ich meinen Kopf kratzen.

Hier ist meine Implementierung in Python: https://gist.github.com/badocelot/5327337

Die Python-Implementierung hat mir geholfen, durch das Programm zu gehen und herauszufinden, was passiert ist, und die Variablen in hilfreichere Namen umzubenennen. Ich war mit dem Wagner-Fischer-Ansatz zur Berechnung der Levenshtein-Entfernung so vertraut, dass ich einen Bezugsrahmen hatte.

Ich verstehe Damerau-Levenshtein folgendermaßen:

Die mysteriösen Variablen:

  • DA( last_rowin meinem Code) ist eine Art Karte, die die letzte Zeile enthält, in der jedes Element gesehen wurde. In meinem Code ist es ein aktuelles Python-Wörterbuch
  • DB( last_match_col) enthält die letzte Spalte, in der der Buchstabe bmit dem Buchstaben in ader aktuellen Zeile übereinstimmt
  • i1( last_matching_row) ist die Zeilennummer von DAfür den aktuellen Buchstaben inb
  • j1ist nur eine Kopie des Werts von DB/, last_match_colbevor er möglicherweise aktualisiert wird; In meinem Code habe ich gerade verschoben, wo last_match_coldiese Variable aktualisiert und entfernt wurde

Die Umsetzungskosten:

H[i1][j1] + (i-i1-1) + 1 + (j-j1-1)

berechnet die Kosten für das Austauschen des aktuellen Zeichens bgegen das letzte bbekannte Zeichen a(die letzte Übereinstimmung) und behandelt alle dazwischen liegenden Zeichen entweder als Hinzufügung oder als Löschung.

Kostenbestandteile:

  • H[i1][j1] Setzt die Grundkosten auf den Punkt in den Berechnungen vor der Umsetzung zurück, da das Auffinden einer Umsetzung frühere Arbeiten ungültig macht
  • (i-i1-1) ist der Abstand zwischen der aktuellen Zeile und der letzten Zeile, der mit dem aktuellen Zeichen übereinstimmt. Dies ist die Anzahl der Löschungen, die erforderlich wären
  • (j-j1-1) ist der Abstand zwischen der aktuellen Spalte und der letzten Spalte mit einer Übereinstimmung, dh die Anzahl der Hinzufügungen
  • Das Extra + 1sind nur die Kosten für die Umsetzung selbst

Wenn diese Analyse falsch ist, würde ich gerne wissen, wo ich falsch gelaufen bin. Wie gesagt, ich konnte keine detaillierte Erklärung finden, wie der Algorithmus online funktioniert.

Verbesserte Version?

Nachdem das heraus, aber es fiel mir auf, dass durch die Kosten für die Berechnung der beiden Ergänzungen und Streichungen zwischen Buchstaben schien fehlerhaft: eine Addition und eine Deletion zu einer Substitution entspricht, die dies nicht überprüft.

Wenn alles richtig ist, sollte die Lösung trivial sein: Die Kosten für die Buchstaben zwischen transponierten Buchstaben sollten die höheren der Hinzufügungen und Löschungen sein: Konvertieren Sie so viele in Substitutionen wie möglich und fügen Sie alle verbleibenden Ergänzungen oder Löschungen hinzu.

Die Kosten wären also:

H[i1][j1] + max((i-i1-1), (j-j1-1)) + 1

Hier ist mein Code für diese Version: https://gist.github.com/badocelot/5327427

Nach einigen einfachen Tests scheint dies richtig zu sein. Zum Beispiel gibt "abcdef" -> "abcfad" einen Bearbeitungsabstand von 2 an (transponieren Sie "d" und "f", ändern Sie "e" in "a"), während der ursprüngliche Algorithmus einen Abstand von 3 angibt (entweder die letzten drei) Buchstaben sind Substitutionen oder 1 Transposition + 1 Addition + 1 Deletion).

Jetzt kann ich nicht die erste Person sein, die daran gedacht hat. Warum bin ich nicht darauf gestoßen? Habe ich gerade nicht lange genug gesucht? Oder gibt es einen subtilen Fehler, der verhindert, dass dies tatsächlich funktioniert?

James Jensen
quelle
Ich habe beschlossen, einen Blog-Beitrag zu schreiben, in dem DL ausführlich erklärt wird: scarcitycomputing.blogspot.com/2013/04/…
James Jensen

Antworten:

3

Ich musste die Damerau-Levenshtein-Distanz auf Wikipedia nachschlagen, also vergib mir, wenn das falsch ist. Es sieht jedoch so aus, als ob nur benachbarte Buchstaben und keine beliebigen Buchstaben transponiert werden können. Ihr Beispiel "abcdef" -> "abcfad" mit der Transponierung von d und f funktioniert also nicht. Mir scheint, Sie haben die Definition des Algorithmus geändert und berechnen die Damerau-Levenshtein-Entfernung nicht mehr.

Steve
quelle
Hmm, ich verstehe was du meinst. DL ermöglicht Transpositionen entweder vor dem Hinzufügen oder nach dem Löschen. Wenn beides aufgetreten ist, handelt es sich nicht wirklich um eine benachbarte Umsetzung, sodass die Kosten in die Höhe schnellen und die Umsetzungskosten nicht als neue Kosten ausgewählt werden. Es sah so aus, als würde es beides handhaben, weil es sie durch einen Nebeneffekt der Kostenminimierung vermeidet.
James Jensen