Я отошел от среды, последнюю версию можно найти по адресу: https://www.avoggu.com/posts/an-efficient-algorithm-for-hamming-(74)-decoding-matlab-implementation/
Пристегнитесь. Мы собираемся исследовать коды Хэмминга (7, 4) и эффективно реализовать их в Matlab / Octave.
Когда данные передаются по каналу, ошибки часто возникают из-за шума и других причин. Для учета потерь к фактическим данным добавляются и передаются избыточные данные. Эти данные могут использоваться для обнаружения и до некоторой степени исправления ошибок. Это известно как канальное кодирование, и коды Хэмминга являются примером.
Коды Хэмминга (7, 4) кодируют 4 бита данных в 7-битные блоки. Дополнительные 3 бита - это избыточные биты четности, о которых мы говорили.
Например, рассмотрим 4 бита данных: d1 d2 d3 d4
. При этом биты четности рассчитываются как
p1 = d2 + d3 + d4 p2 = d1 + d3 + d4 p3 = d1 + d2 + d4
Все это объединено и закодировано как
p1 p2 p3 d1 d2 d3 d4
На стороне получателя снова создаются биты четности, которые проверяются с полученными битами для обнаружения и исправления ошибок.
Предположим, произошла только 1 ошибка, а значение бита было изменено. Если перевернуть d1, это вызовет разногласия в p2 и p3. И так далее.
Также обратите внимание, что ошибки могут возникать и в битах четности. Если только p1 не согласен, ошибка произошла в p1.
Конечно, это не сработает, если будет более одной ошибки. Но если ваш канал дает 2 ошибки на каждые 7 бит, вам все равно обречено. Типичные вероятности ошибок имеют порядок 10^-6
.
Хорошо. Приступим к реализации. Вы могли заметить, что кодирование можно представить как умножение матриц.
data = [d1 d2 d3 d4] |0 1 1 1 0 0 0| encoded_data = [d1 d2 d3 d4] * |1 0 1 0 1 0 0| |1 1 0 0 0 1 0| |1 1 1 0 0 0 1|
Первым элементом результирующей матрицы будет d1*0 + d2*1 + d3*1 + d4*1
. Превосходно! Это именно то, что мы хотели для бита четности p1.
Последние четыре бита будут самими битами данных.
Такая матрица называется generator matrix
. Мы сгенерировали коды Хэмминга, умножив наши данные на матрицу генератора.
Обратное - decoder matrix
. На стороне получателя мы используем его, чтобы определить, где произошла ошибка. Вот матрица декодера для кодов Хэмминга (7, 4).
|1 0 0 0 1 1 1| |0 1 0 1 0 1 1| * [p1 p2 p3 d1 d2 d3 d4] |0 0 1 1 1 0 1|
Умножив наш 7-битный код на эту матрицу, у нас останутся 3 бита, которые сообщают нам, произошла ли и где произошла ошибка.
Изучите, что делает матрица декодера. Первый элемент будет
p1 + d2 + d3 + d4
. Это равно 2 * (d2 + d3 + d4)
. Поскольку это двоичный файл, у нас останется 0
. Но если где-то произошла ошибка, сумма будет 1
.
Вот как будет выглядеть результирующая матрица для ошибок в разных положениях.
No errors -> [0 0 0] Error in p1 -> [1 0 0] Error in p2 -> [0 1 0] Error in p3 -> [0 0 1] Error in d1 -> [0 1 1] Error in d2 -> [1 0 1] Error in d3 -> [1 1 0] Error in d4 -> [1 1 1]
Теперь, когда мы знаем, где ошибка, при декодировании просто переворачивается бит ошибки и удаляются биты четности.
Кодировка в Matlab (полный код в конце)
function [output_vector] = sevenFourHammingEncode(input_vector) output_vector = []; number_of_windows = length(input_vector) / 4; % assumes length to be multiple of four four_bit_windows = reshape(input_vector, 4, number_of_windows)'; % p1 p2 p3 d1 d2 d3 d4 generator_matrix = [ 0 1 1 1 0 0 0 ; 1 0 1 0 1 0 0 ; 1 1 0 0 0 1 0 ; 1 1 1 0 0 0 1 ; ]; output_vector = mod(four_bit_windows * generator_matrix, 2); output_vector = reshape(output_vector', numel(output_vector), 1)'; end
Расшифровка
Извините за отсутствие комментариев. Когда я писал это, я не осознавал их важности. А теперь не помню, что он делает. Попробуйте представить код как матричные операции на бумаге, и вы поймете. Если да, напишите мне, и я добавлю его сюда. Спасибо :)
function [output_vector] = sevenFourHammingDecode(input_vector) output_vector = []; number_of_windows = numel(input_vector) / 7; seven_bit_windows = reshape(input_vector, 7, number_of_windows)'; % p1 p2 p3 d1 d2 d3 d4 decoder_matrix = [ 1 0 0 0 1 1 1 ; 0 1 0 1 0 1 1 ; 0 0 1 1 1 0 1 ; ]; % [ 1 0 0 ; 0 1 0 ; 0 0 1; 0 1 1 ; 1 0 1 ; 1 1 0 ; 1 1 1; ] % [4, 2, 1, 3, 5, 6, 7] result_vector = mod(decoder_matrix * seven_bit_windows', 2)'; result_vector = result_vector * [4 ; 2 ; 1]; % summing all elements result_vector(result_vector == 4) = 9; result_vector(result_vector == 1) = 11; result_vector(result_vector == 3) = 12; result_vector = mod(result_vector, 8); seven_bit_windows = [ones(size(seven_bit_windows, 1), 1) seven_bit_windows]; % adding 1 column at start result_vector = [(0:8:rows(result_vector)*8-1)' result_vector]; result_vector = result_vector * [1 ; 1]; % summing row and column padded_data = reshape(seven_bit_windows', numel(seven_bit_windows), 1)'; padded_data(result_vector' + 1) = not(padded_data(result_vector' + 1)); padded_data = reshape(padded_data, 8, numel(padded_data) / 8)'; padded_data = padded_data(:, 5:end); output_vector = reshape(padded_data', numel(padded_data), 1)'; end
При декодировании используются только матричные операции, и поэтому оно намного быстрее, чем при использовании for loop
. На порядки быстрее.
Вот сценарий для сравнения производительности кодировок (3, 1), (5, 1) и Хэмминга (7, 4).
Вот и все. Раздел комментариев, если вам нужна помощь.
Aravind