Как нормализовать расстояние Левенштейна для максимальной длины выравнивания, а не длины строки?

Проблема: В нескольких R-пакетах реализованы реализаторы расстояний Levenshtein для вычисления сходства двух строк, например. http://finzi.psych.upenn.edu/R/library/RecordLinkage/html/strcmp.html. Вычисленные расчеты могут быть легко нормализованы для длины строки, например. разделив расстояние Левенштейна на длину самой длинной струны или разделив ее на среднее из длин двух строк. Однако для некоторых применений в лингвистике (например, диалектометрия и исследование восприимчивого многоязычия) рекомендуется, чтобы исходное расстояние Левенштейна было нормировано на длину самого длинного наименее затратного выравнивания (Heeringa, 2004: 130-132). Это имеет тенденцию производить дистанционные меры, которые имеют больший смысл с точки зрения восприятия-лингвистики.

Пример: Немецкая строка "tsYklUs" (Zyklus = цикл) может быть преобразована в свой шведский цикл "sYkEl" (cyckel = (bi)) в выравнивании с 7 слотами с двумя вставками (I) и двумя подстановками (S) для общего стоимость преобразования 4. Нормализованное расстояние Левенштейна: 4/7

(А)

t--s--Y--k--l--U--s
---s--Y--k--E--l---
===================
I-----------S--S--I = 4

Также можно преобразовать строки в 8-слотовое выравнивание с 3 вставками (I) и 1 удалением (D), а также для общей стоимости выравнивания 4. Нормализованное расстояние Левенштейна: 4/8

(В)

t--s--Y--k-----l--U--S
---s--Y--k--E--l------
======================
I-----------D-----I--I = 4

Последнее выравнивание имеет больше смысла лингвистически, потому что оно выравнивает [l] -фонемы друг с другом, а не с гласными [E] и [U].

Вопрос: Кто-нибудь знает о какой-либо функции R, которая позволила бы мне нормализовать расстояния Левенштейна для самого длинного выравнивания наименьшей стоимости, а не для длины строки? Спасибо за ваш вклад!

Справка: W.J. Heeringa (2004), Измерение различий произношения на диалекте с использованием расстояния Левенштейна. Кандидатская диссертация, Университет Гронингена. http://www.let.rug.nl/~heeringa/dialectology/thesis/

Изменить - Решение: Я думаю, что понял решение. Функция adist может возвращать выравнивание и, по-умолчанию, является самым длинным недорогим выравниванием. Чтобы взять пример выше, здесь выравнивание, связанное с sykel с tsyklus:

> attr(adist("sykel", "tsyklus", counts = TRUE), "trafos")
     [,1]      
[1,] "IMMMDMII"

Для вычисления нормированных по длине расстояний, как рекомендовано Heeringa (2004), мы можем написать скромную функцию:

normLev.fnc <- function(a, b) {
  drop(adist(a, b) / nchar(attr(adist(a, b, counts = TRUE), "trafos")))
}

В приведенном выше примере это возвращает

> normLev.fnc("sykel", "tsyklus")
[1] 0.5

Эта функция также возвращает правильные нормированные расстояния для примеров Heeringa (2004: 131):

> normLev.fnc("bine", "bEi")
[1] 0.6
> normLev.fnc("kaninçen", "konEin")
[1] 0.5555556
> normLev.fnc("kenEeri", "kenArje")
[1] 0.5

Чтобы сравнить несколько пар строк:

> L1 <- c("bine", "kaninçen", "kenEeri")
> L2 <- c("bEi",  "konEin", "kenArje")
> diag(normLev.fnc(L1, L2))
[1] 0.6000000 0.5555556 0.5000000

Ответ 1

В случае, если какие-либо лингвисты наткнутся на этот пост, я хотел бы указать, что алгоритмы, предоставленные пакетом RecordLinkage, необязательно оптимальны для сравнения строк, отличных от ASCII, например:

> levenshteinSim("väg", "way")
[1] -0.3333333
> levenshteinDist("väg", "way")
[1] 4
> levenshteinDist("väg", "wäy")
[1] 2
> levenshteinDist("väg", "wüy")
[1] 3