Пример 4
Кодирование Хаффмана наглядно показано на примере источника, заданного таблицей.
Вероятности и энтропия двух символов.
Решение. Немного упростим кодирование, отказавшись от наглядных переупорядочений знаков на втором шаге, т.к. в таком маленьком примере это можно сделать «в уме». В соответствии с первым шагом, расположим все знаки в порядке убывания их вероятностей (рисунок 1).
Рисунок 1 – Кодирование Хаффмана п = 4.
На втором шаге объединим символы «а» и «с», обладающие наименьшими вероятностями, в составной символ «ас». Далее объединим «е» с «ас» в составной символ «еас» с вероятностью 0.25. Теперь наименьшими вероятностями уже обладают символы «f» и «b». Объединив их, получим символ «fb». Следующая редукция дает составной символ «fbeac» с вероятностью 0,6. И, наконец, объединив все символы, получим составной символ «dfbeac», вероятность которого равна 1.
На третьем шаге будем идти справа налево, приписывая верхним компонентам объединений символ «0», а нижним «1». Полученные кодовые слова всех простых знаков с их длинами приведены в следующей таблице.
Кодирование кодом Хаффмана к рисунку 1.
Данный код обладает минимальной средней длиной кодового слова.
Средняя длина кодового слова определяется длинами всех слов ni, «взвешенными» с соответствующими вероятностями pi;
.
(1)
В рассмотренном выше примере
средняя длина кодового слова
бит близка к энтропии Н(Х)
= 2.25
бит. Важнейшей величиной, называемой
эффективностью кода или фактором сжатия,
является отношение средней длины к
энтропии. В нашем примере эффективность
кода равна
=
0.976.
Эффективность кода или фактор сжатия
.
(2)
Реализация декодера кода Хаффмана следует непосредственно из рисунка 1. На рисунке 2 представлено дерево, называемое кодовым деревом декодера.
Декодирование каждого нового слова начинается с исходного узла (корня) кодового дерева. Если мы принимаем «0», то идем по ребру, соответствующему нулю (по верхнему ребру). В нашем примере при этом мы достигаем оконечного узла d. Следовательно, был передан символ d и мы начинаем декодирование нового символа с, корня.
Рисунок 2 – Кодовая конструкция для D = 2 и п = 4.
Если мы принимаем «1», то идем по нижнему ребру и попадаем в узел, из которого выходят два ребра. Следующий принятый бит указывает, какое из этих двух ребер нужно выбрать. Мы продолжаем эту процедуру до тех нор, пока не достигнем оконечного узла. В этом случае мы принимаем решение о переданном символе и опять переходим к корню кодового дерева.
Лабораторная работа 2 Арифметическое кодирование и декодирование
При арифметическом кодировании мы исходим из того факта, что при нормализованном распределении сумма вероятностей символов (и соответствующих им относительных частот) источника всегда равна единице. Если относительные частоты символов неизвестны передатчику и приемнику:
они могут определяться, например, путем текущих статистических изменений передаваемой информации в фиксированные моменты времени;
приемник и передатчик совместно, исходя из относительных частот, устанавливают жесткие правила кодирования.
Особенностью арифметического кодирования является то, что для отображения последовательности символов в потоки натуральных чисел на интервале [0,1] используются относительные частоты.
Результатом такого отображения является сжатие символов (посимвольное сжатие) в соответствии с их вероятностями.
Пример. Рассмотрим арифметическое кодирование последовательности букв «GELEEESSER». Относительные частоты букв в этом потоке приведены в таблице1.
Таблица 1 – Буквы и их относительные частоты.
Процедура кодирования представлена на рисунке 1.
Первой букве «G», в соответствии с ее относительной частотой, соответствует интервал [0.7, 0.8[. Согласно алгоритму, каждая цепочка букв, начинающихся с G, всегда будет отображаться в число, принадлежащее этому интервалу. Таким образом, в рассматриваемом примере первая десятичная цифра после запятой уже определена.
Рисунок 1 – Арифметическое кодирование.
Кодирование последующих букв производится аналогично с тем важным отличием, что теперь делению каждый раз будет подвергаться интервал, выбранный на предыдущем шаге. Из рисунке 1 следует, что букве «Е» на втором шаге соответствует интервал [0.7, 0.75[.
Таблица 3, в которой алгоритм кодирования прослежен но шагам, показывает, что последовательность «GELEEESER» отображается в число 740387 (0 и запятая не нуждаются в отображении). Отметим, что:
Часто встречающимся буквам ставятся в соответствие большие интервалы. На их отображение затрачивается меньше десятичных цифр, чем на отображение редко встречающихся букв.
Длинные сообщения отображаются в «длинные» числа. Представление этих чисел в двоичной форме, необходимое для передачи сообщений, приводит к появлению кодовых слов большой длины.
Практическая реализация скользящие алгоритма арифметического кодирования требует высокой точности, которая ограничивается длиной кодовых слов. Для сокращения необходимой длины регистра, при реализации арифметического кодирования используется целочисленная арифметика с выдачей уже готовых промежуточных результатов.
Алгоритм представлен в таблице 2.
Таблица 2 – Алгоритм арифметического кодирования.
Механизм его действия раскрывается с помощью таблицы 3.
Таблица 3 – Арифметическое кодирование фразы «GELEEESSER».
В нашем примере для реализации кодирования достаточно регистра для хранения шести текущих десятичных цифр.
В соответствии с таблицей 2, на первом шаге происходит инициализация переменных LO и HI. Для первой кодируемой буквы «G» ширина интервала равна В = l'000'000. Нижняя и верхняя границы равны соответственно LO = 0 + l'000'000 x 0.7 = 700'000 и HI = 0+ l'000'000 x 0.8 – 1 = 799'999. Первая десятичная цифра уже определена и равна 7, а содержимое регистров LO и HI сдвигается на одну позицию влево. Заметим, что в регистре LO освободившееся место занимает 0, а в регистре HI - 9.
Для второй буквы «Е» ширина интервала равна В = l'000'000, поэтому, получаем LO = 0 + l'000'000 = 000'000 и HI = 0 + l'000'000 x 0.5 – 1 = 499'999. Кодирование последующих букв проводится аналогично. В завершении работы алгоритма выдается некоторое число из последнего интервала. Для этого мы округляем верхнюю границу интервала HI, отбрасывая младшие разряды до тех пор, пока это возможно. В результате получаем число с минимальным количеством цифр, принадлежащее последнему интервалу.
