Расстояние Хэмминга и мутации

Чтобы сравнить две последовательности равной длины буква в букву, считают расстояние Хэмминга — число несовпадений.

Расстояние Хэмминга между двумя строками равной длины — количество позиций, в которых их символы различаются.

Когда два гена почти одинаковы, но один накопил мутации, расстояние Хэмминга прямо считает число точечных замен между ними. Это простейшая мера «непохожести» и основа приближённого поиска. Условие — строки одной длины (только замены, без вставок и удалений; для них нужно выравнивание).

Считаем расстояние Хэмминга

def hamming(a, b):
    if len(a) != len(b):
        raise ValueError('Строки должны быть равной длины')
    return sum(1 for x, y in zip(a, b) if x != y)

s1 = 'GAGCCTACTAACGGGAT'
s2 = 'CATCGTAATGACGGCCT'
print('Расстояние Хэмминга:', hamming(s1, s2))

Вывод:

Расстояние Хэмминга: 7

Семь позиций различаются — значит, между этими последовательностями как минимум 7 точечных мутаций. zip идёт по парам букв, генератор считает несовпадения.

Биологический смысл

Расстояние Хэмминга = число точечных замен (substitutions). Если разделить его на длину, получим долю различий — грубую оценку эволюционного расстояния: чем больше мутаций накопилось, тем дальше разошлись последовательности. Это используется при построении деревьев (раздел про филогенетику). Но Хэмминг не видит вставок/удалений — для них нужно выравнивание.

GAGCCTACTAACGGGAT
несовпадения помечены столбцами ниже
CATCGTAATGACGGCCT
(несовпадений: 7)

Приближённый поиск мотива

В реальной ДНК сайт связывания не идеален — он встречается с парой ошибок. Поэтому ищут мотив с допуском: все позиции, где расстояние Хэмминга до мотива не больше d.

def hamming(a, b):
    return sum(1 for x, y in zip(a, b) if x != y)

def find_approx(seq, motif, max_d):
    k = len(motif)
    hits = []
    for i in range(len(seq) - k + 1):
        if hamming(seq[i:i+k], motif) <= max_d:
            hits.append(i)
    return hits

seq = 'ATGACGATGTTG'
print('ATG с d=0:', find_approx(seq, 'ATG', 0))
print('ATG с d=1:', find_approx(seq, 'ATG', 1))

Вывод:

ATG с d=0: [0, 6]
ATG с d=1: [0, 3, 6, 9]

При d=0 находим точные ATG (позиции 0 и 6). При d=1 добавляются позиции, отличающиеся одной буквой (3 и 9). Так ищут вырожденные сайты и моделируют мутации.

Как работает под капотом: Хэмминг против Левенштейна

Хэмминг прост, но жёсток: требует равной длины и считает только замены. Если одна последовательность получила вставку, все буквы после неё «съезжают», и Хэмминг покажет огромное расстояние, хотя биологически отличие — одна вставка. Расстояние Левенштейна (редактирования) учитывает вставки и удаления, а его обобщение — выравнивание — главная тема следующего раздела. Правило: одинаковая длина и только замены — Хэмминг; возможны сдвиги — выравнивание.

У приближённого поиска есть и оборотная сторона, о которой стоит помнить, — сложность. Наш вариант проверяет каждое окно за O(k) и проходит всю строку, давая O(n·k). Для одного мотива в гене это пустяк. Но в задачах вроде поиска всех вариантов сайта связывания транскрипционного фактора по всему геному человека с допуском в 2–3 ошибки наивный перебор уже ощутимо тяжёл, и применяют умные приёмы: бьют мотив на куски (если ошибок не больше d, хотя бы один из d+1 кусков совпадёт точно — это «принцип ящиков») и сначала ищут точные куски быстрым индексом, а уже вокруг них проверяют полный мотив. Эта идея «фильтр плюс проверка» — та же, что лежит в основе BLAST, к которому мы придём в разделе про выравнивание. Так простое расстояние Хэмминга оказывается отправной точкой для серьёзных эвристик поиска.

Частые ошибки

  • Применять Хэмминг к строкам разной длины. zip молча обрежет по короткой — добавьте проверку длины.
  • Считать Хэмминг при наличии вставок. Он завысит различие; нужно выравнивание.
  • Забыть границу поиска. В приближённом поиске range(len-k+1), иначе выйдете за конец.

Итог

  • Расстояние Хэмминга — число различающихся позиций у строк равной длины (число замен).
  • Доля различий грубо оценивает эволюционное расстояние.
  • Приближённый поиск мотива принимает позиции с Хэммингом не больше порога d.
  • Хэмминг не видит вставок/удалений — для них нужно выравнивание (следующий раздел).
Проверьте себя
1. Что измеряет расстояние Хэмминга?
AДлину последовательности
BЧисло позиций, где символы двух строк равной длины различаются
CЧисло вставок и удалений
DGC-состав
2. Почему расстояние Хэмминга нельзя применять при вставке в одной из последовательностей?
AОно станет нулём
BПосле вставки буквы съезжают, и Хэмминг завысит различие, хотя отличие мало
CХэмминг требует регулярных выражений
DВставки не бывают в ДНК
3. Что делает приближённый поиск мотива с порогом d?
AИщет только точные вхождения
BНаходит позиции, где расстояние Хэмминга до мотива не больше d
CИгнорирует мотив
DСчитает GC-состав