Эффективно определить "как отсортировано" список, например. Расстояние Левенштейн

Я делаю некоторые исследования алгоритмов ранжирования и хотел бы, учитывая отсортированный список и некоторую перестановку этого списка, вычислить некоторое расстояние между двумя перестановками. Для случая расстояния Левенштейна это соответствует вычислению расстояния между последовательностью и отсортированной копией этой последовательности. Существует также, например, "расстояние инверсии", алгоритм с линейным временем которого подробно описан здесь, над которым я работаю над внедрением.

Знает ли кто-нибудь о существующем внедрении python расстояния инверсии и/или оптимизации расстояния Левенштейна? Я вычисляю это на последовательности от 50 000 до 200 000 элементов, поэтому O (n ^ 2) слишком медленна, но O (n log (n)) или лучше должно быть достаточным.

Также будут оценены другие метрики для сходства подстановок.


Изменить для людей из будущего:

На основе ответа Раймонда Хеттингера; это не Левенштейн или расстояние от инверсии, а скорее "сопоставление гештальт-шаблонов": P

from difflib import SequenceMatcher
import random
ratings = [random.gauss(1200, 200) for i in range(100000)]
SequenceMatcher(None, ratings, sorted(ratings)).ratio()

работает на ~ 6 секунд на страшном рабочем столе.

Edit2: Если вы можете принудить свою последовательность к перестановке [1.. n], то вариация манхэттенской метрики чрезвычайно быстра и имеет некоторые интересные результаты.

manhattan = lambda l: sum(abs(a - i) for i, a in enumerate(l)) / (0.5 * len(l) ** 2)
rankings = list(range(100000))
random.shuffle(rankings)
manhattan(rankings) # ~ 0.6665, < 1 second

Нормализующий коэффициент технически является приближением; это правильно для даже размерных списков, но должно быть (0.5 * (len(l) ** 2 - 1)) для списков нечетного размера.

Edit3: Существует несколько других алгоритмов для проверки сходства списков! коэффициент рейтинга Кендалла Тау и Spearman коэффициент ранжирования. Реализации их доступны в библиотеке SciPy как scipy.stats.kendalltau и scipy.stats.rspearman и возвращают ранги вместе с ассоциированным p -величины.

Ответ 1

Расстояние Левенштейна - это алгоритм O (n ** 2), поэтому, если вы хотите идти быстрее, используйте альтернативный быстрый алгоритм в модуль difflib. Метод ratio вычисляет меру сходства между двумя последовательностями.

Если вам нужно придерживаться Levenshtein, в Python Cookbook есть рецепт Python: http://code.activestate.com/recipes/576874-levenshtein-distance/.

Другой Python script можно найти по адресу: http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#Python