Автор: Пользователь скрыл имя, 28 Марта 2011 в 20:19, реферат
Основоположником науки о сжатии информации принято считать Клода Шеннона. Его теорема об оптимальном кодировании показывает, к чему нужно стремиться при кодировании информации и на сколько та или иная информация при этом сожмется. Кроме того, им были проведены опыты по эмпирической оценке избыточности английского текста. Он предлагал людям угадывать следующую букву и оценивал вероятность правильного угадывания.
Введение
Общие сведения
Энтропия и количество информации
Комбинаторная, вероятностная и алгоритмическая оценка количества информации
Моделирование и кодирование
Некоторые алгоритмы сжатия данных
Алгоритм LZ77
Алгоритм LZ78-LZW84
Алгоритм PPM
BWT - преобразование и компрессор
Кодирование Хаффмана
Арифметическое кодирование
Алгоритм арифметического кодирования
Реализация алгоритма арифметического кодирования
Реализация модели
Доказательство правильности декодирования
Приращаемая передача и получение
Отрицательное переполнение
Переполнение и завершение
Адаптивная модель для арифметического кодирования
Эффективность сжатия
Заключение
Список литературы
Дня
данной таблицы символов коды Хаффмана
будут выглядеть следующим
А 0
Б 100
В 101
Г 110
Д 111
Поскольку
ни один из полученных кодов не является
префиксом другого, они могут
быть однозначно декодированы при чтений
их из потока. Кроме того, наиболее частый
символ сообщения А закодирован
наименьшим количеством битов, а
наиболее редкий символ Д - наибольшим.
Классический
алгоритм Хаффмана имеет один существенный
недостаток. Дня восстановления содер-жимого
сжатого сообщения декодер
Арифметическое
кодирование
Алгоритм
арифметического кодирования
Арифметическое
сжатие - достаточно изящный метод,
в основе которого лежит очень
простая идея. Мы представляем кодируемый
текст в виде дроби, при этом строим
дробь таким образом, чтобы наш
текст был представлен как
можно компактнее. Для примера
рассмотрим построение такой дроби
на интервале [0, 1) (0 - включается, 1 - нет).
Интервал [0, 1) выбран потому, что он
удобен для объяснений. Мы разбиваем
его на подынтервалы с длинами, равными
вероятностям появления символов в
потоке. В дальнейшем будем называть
их диапазонами соответствующих
символов.
Пусть
мы сжимаем текст "КОВ.КОРОВА"
(что, очевидно, означает "коварная корова").
Распишем вероятности появления
каждого символа в тексте (в
порядке убывания) и соответствующие
этим символам диапазоны:
Символ
Частота
Вероятность
Диапазон
О
3
0.3
[0.0; 0.3)
К
2
0.2
[0.3; 0.5)
В
2
0.2
[0.5; 0.7)
Р
1
0.1
[0.7; 0.8)
А
1
0.1
[0.8; 0.9)
“.”
1
0.1
[0.9; 1.0)
Будем
считать, что эта таблица известна
в компрессоре и декомпрессоре.
Кодирование заключается в
Используя
исходную таблицу диапазонов, кодируем
текст "КОВ.КОРОВА":
Исходный
рабочий интервал [0,1).
Символ
"К" [0.3; 0.5) получаем [0.3000; 0.5000).
Символ
"О" [0.0; 0.3) получаем [0.3000; 0.3600).
Символ
"В" [0.5; 0.7) получаем [0.3300; 0.3420).
Символ
"." [0.9; 1.0) получаем [0,3408; 0.3420).
Графический
процесс кодирования первых трех
символов можно представить так,
как на рис. 4.
Рис.
4. Графический процесс
Таким
образом, окончательная длина интервала
равна произведению вероятностей всех
встретившихся символов, а его
начало зависит от порядка следования
символов в потоке. Можно обозначить
диапазон символа с как [а[с]; b[с]),
а интервал для i-го кодируемого символа
потока как [li, hi).
Большой
вертикальной чертой на рисунке выше
обозначено произвольное число, лежащее
в полученном при работе интервале
[/i, hi). Для последовательности "КОВ.",
состоящей из четырех символов, за
такое число можно взять 0.341. Этого
числа достаточно для восстановления
исходной цепочки, если известна исходная
таблица диапазонов и длина цепочки.
Рассмотрим
работу алгоритма восстановления цепочки.
Каждый следующий интервал вложен в
предыдущий. Это означает, что если
есть число 0.341, то первым символом в
цепочке может быть только "К",
поскольку только его диапазон включает
это число. В качестве интервала
берется диапазон "К" - [0.3; 0.5) и
в нем находится диапазон [а[с];
b[с]), включающий 0.341. Перебором всех
возможных символов по приведенной
выше таблице находим, что только
интервал [0.3; 0.36), соответствующий диапазону
для "О", включает число 0.341. Этот интервал
выбирается в качестве следующего рабочего
и т. д.
Реализация
алгоритма арифметического
Ниже
показан фрагмент псевдокода процедур
кодирования и декодирования. Символы
в нем нумеруются как 1,2,3... Частотный
интервал для i-го символа задается
от cum_freq[i] до cum_freq[i-1]. Пpи убывании i cum_freq[i]
возрастает так, что cum_freq[0] = 1. (Причина
такого "обpатного" соглашения состоит
в том, что cum_freq[0] будет потом содеpжать
ноpмализующий множитель, котоpый удобно
хpанить в начале массива). Текущий
pабочий интеpвал задается в [low; high] и
будет в самом начале pавен [0; 1)
и для кодиpовщика, и для pаскодиpовщика.
Алгоритм
кодирования:
С каждым
символом текста обpащаться к пpоцедуpе
encode_symbol(). Пpовеpить, что "завеpшающий"
символ закодиpован последним. Вывести
полученное значение интеpвала [low; high).
encode_symbol(symbol,
cum_freq)
{
…
range =
high - low
high =
low + range*cum_freq[symbol-1]
low = low
+ range*cum_freq[symbol]
…
}
Алгоритм
декодирования:
Value -
это поступившее на вход число.
decode_symbol(cum_freq)
//поиск
такого символа, что
cum_freq[symbol]
<= (value - low)/(high - low) < cum_freq[symbol-1]
Это
обеспечивает pазмещение value внутpи
нового интеpвала [low;high), что отpажено
в оставшейся части пpогpаммы:
range =
high - low
high =
low + range*cum_freq[symbol-1]
low = low
+ range*cum_freq[symbol]
return
symbol
Реализация
алгоритма на C# приведена в Приложении.
Реализация
модели
В языке
Си байт представляет собой целое
число от 0 до 255 (тип char). Здесь же
мы пpедставляем байт как целое число
от 1 до 257 включительно (тип index), где EOF
тpактуется как 257-ой символ. Пеpевод из
типа char в index, и наобоpот, pеализуется
с помощью двух таблиц - index_to_char[]
и char_to_index[].
Веpоятности
пpедставляются в модели как целочисленные
счетчики частот, а накапливаемые
частоты хpанятся в массиве cum_freq[].
Этот массив - "обpатный", и счетчик
общей частоты, пpименяемый для
ноpмализации всех частот, pазмещается
в cum_freq[0]. Накапливаемые частоты
не должны превышать установленный
в max_frequency максимум, а реализация модели
должна предотвращать переполнение
соответствующим
Доказательство
правильности декодирования
Пpовеpим
веpность определения
где
"| |" обозначает опеpацию взятия целой
части - деление с отбpасыванием
дpобной части.
Другими
словами:
(1)
где
range = high - low + 1, .
Последнее
неравенство выражения (1) происходит
из факта, что cum_freq[symbol-1] должно быть целым.
Затем мы хотим показать, что low'?value?high',
где low' и high' есть обновленные значения
для low и high как опpеделено ниже.
Из
выружения (1) имеем: ?value + 1 - 1/cum_freq[0], поэтому
low'?value, т.к. и value, и low', и cum_freq[0] > 0.
Из
выражения (1) имеем:
Приращаемая
передача и получение
В отличие
от псеводокода, программа представляет
low и high целыми числами. В псевдокоде
текущий интеpвал пpедставлен
чеpез [low; high), а в пpогpамме это [low;
high] - интеpвал, включающий в себя значение
high. Hа самом деле более пpавильно,
хотя и более непонятно, утвеpждать,
что в пpогpамме пpедставляемый интеpвал
есть [low; high + 0.1111...) по той пpичине, что
пpи масштабитовании гpаниц для
увеличения точности, нули смещаются
к младшим битам low, а единицы
смещаются в high.
По
меpе сужения кодового интеpвала,
стаpшие биты low и high становятся одинаковыми,
и поэтому могут быть пеpеданы
немедленно, т.к. на них будущие сужения
интеpвала все pавно уже не будут
влиять. Поскольку мы знаем, что low?high,
это воплотится в следующую пpогpамму:
for (;;)
{
if (high
< Half)
{
output_bit(0);
low = 2
* low;
high =
2 * high + 1;
}
else if
(low >= Half)
{
output_bit(1);
low = 2
* (low - Half);
high =
2 * (high - Half) + 1;
}
else break;
}
гаpантиpующую,
что после ее завеpшения будет
спpеведливо неpавенство: low<Half?high. Это
можно найти в пpоцедуpе encode_symbol().
Пpиpащаемый
ввод исходных данных выполняется с
помощью числа, названного value. В
пpогpамме, обpаботанные биты пеpемещаются
в веpхнюю часть, а заново получаемые
поступают в нижнюю. Вначале, start_decoding()
заполняет value полученными битами. После
опpеделения следующего входного символа
пpоцедуpой decode_symbol(), пpоисходит вынос
ненужных, одинаковых в low и в high, битов
стаpшего поpядка сдвигом value на это
количество pазpядов (выведенные биты восполняются
введением новых с нижнего
конца).
for (;;)
{
if (high
< Half)