COMPRESSION.RU:   О сервере  Анонсы  Статьи+исходники  Ссылки  RU.COMPRESS  Форум 
Книга "Методы сжатия данных":   Универсальные  Изображения  Видео 
Авторские проекты: Д.Ватолин  А.Ратушняк  М.Смирнов  В.Юкин  Е.Шелвин
А.Филинский  Д.Шкарин  С.Оснач  С.Воскобойников

Индекс

О сжатии словаря - [2]

26 сентября 2003 - Shelwien


From: Eugene D. Shelwien
  To: Dmitry Khmelev
Subj: О сжатии словаря
Date: Fri, 26 Sep 2003 23:41:23

> У меня тут появилась мысль о сжатии словаря, но я что-то не могу > сообразить, является ли это сжатие обратимым. ;)

Как меня недавно убедил Вадим Юкин, для настоящих фанатов компрессии это несущественно ;)


> Чтобы запрограммировать и проверить у меня нету необходимых 
> подпрограмм, так что может быть, Вам это будет легче.

Да ладно, лень - тоже хорошее оправдание ;) > Итак, пусть нам надо сжать N слов w[1], ..., w[N], причём они все > попарно не равны w[i]!=w[j] при i!=j. Предлагается сжимать это с > помощью преобразования Барроуза-Уилера, но с некоторой оговоркой.

У BWT есть одна маленькая проблема. По сравнению с современными реализациями PPM/CM, основанные на нем компрессоры дают существенно меньшее сжатие.

 
> Если мы просто вставим разделитель S между словами (т.е. будем
> преобразовывать текст T = w[1] S w[2] S ... S w[N] S), то группировка
> близких контекстов (концов слов) будет нарушаться символами из следующего
> лексикографически слова. Поэтому надо каким-то образом избавиться от этой
> зависимости. 

Н-да. Эту-то проблему я в своей заметке решил. В случае с BWT достаточно будет просто заменить его на ST(32) и дополнить слова до этой длины нулями. Или вообще сделать специализированный вариант ST, где сортировка отключается при достижении разделителя. Вопрос был, собственно, о другом - какие корреляции между какими частями слов надо учитывать.


> Избавление предлагается такое. Введём N различных
> символов-разделителей S[1], ..., S[N], которые будем вставлять между
> словами, причём все S[i] лексикографически предшествуют буквам основного
> алфавита (в котором записаны слова w[i]). Остаётся задать
> лексикографический порядок на S[i]. Самый примитивный способ:
> S[i]<S[j] тогда и только тогда, когда i<j. 

Ну, вместо символов я взял строки - это же ничего принципиально не меняет? В этом случае - просто разбил номер слова на тетрады и записал кодами 0..15.


> Более интересный способ:
> S[i]<S[j] тогда и только тогда, когда reverse(w[i])<reverse(w[j]), 
> (здесь reverse() означает инверсию слова, т.е. перестановку букв слова 
> в обратном порядке). В силу неравенства слов этот порядок 
> однозначно определён.

А здесь я перевернул файл (переставил символы в обратном порядке), заново отсортировал (как раз по твоему reverse()), добавил номера (записав "цифры" в обратном порядке), затем перевернул весь файл обратно.

Потом подумал, и изменил направление сравнения в сортировке - эффект тот же.

 
> А теперь --- трюк, в правильности которого я не уверен. Давайте рассмотрим
> преобразование Барроуза-Уилера текста
> 
>   T = w[1] S[1] w[2] S[2] ... S[N-1] w[N] S[N]
> 
> которое обозначим через BW(T). А теперь заменим в BW(T)
> все символы разделители S[1], ..., S[N] на один (например, на код 0).
> 
> Вопрос: верно ли, что при обращении преобразования Уилера из полученной
> строки получатся все исходные слова, может и в перепутанном порядке?

Обычным iBWT здесь не обойдешься (хотя я даже отломал на пробу проверки контрольных сумм из DC - но добился только Out of memory).

Но вообще такое вполне реально.

Хотя в данном случае это не имеет значения по другой причине.

 
> Если да - то вот оно решение. 

Это - решение задачи блокирования ложных контекстов для BWT.

К моей задаче, к сожалению, это имеет весьма отдаленное отношение ;)

 
> Правда, надо ещё проверить, насколько сильно получится сжать. 

См. ниже. > Интуиция подсказывает, что поскольку информации о > порядке слов мы не передаём > (что происходит в подходах, описанных на > странице http://compression.graphicon.ru/download/text.html),

Если речь о моей заметке, то проблем это не вызывает по причине умения ppmonstr'а работать с локальными изменениями статистики.

 
> то всё должно ужаться очень хорошо.

Смотрим:    
Transform Postcoder O1BFA Ash02-o4 Binder's DC Plain BWT 1172644 1231928 1191292 Direct delimiters + BWT 801452 717420 971242 Reverse delimiters + BWT 491444 496021 519844 Modified BWT 491444 496021 519844 Dictpack1 data + BWT 437193 463704 442987 ppmonstr ash02 slim16 epm8 Dictpack1 to compare 426005 426945 432240 429631

Так что предложенный подход, конечно, позволяет-таки получить с помощью BWT менее 1M на бергмансовском english.dic, что тоже полезно. Только вот мой фильтр работает лучше. Да и вообще некоторые полезные корреляции после BWT становится трудновато разглядеть.

"Modified BWT" выше - это полный аналог второго варианта с разделителями, только никакие символы в исходный файл не добавляются. Вместо этого, функция сравнения строк изменена так, чтобы имитировать тот же эффект.

Имхо интересно, что многосимвольные разделители оказалось возможным полностью и корректно удалить из BWT - первоначально они просто заменялись на код 0A и результат был на несколько килобайт больше.


> Прекрасно. Остаётся строго доказать этот факт и можно писать статью ;) Мне
> всё ещё не ясно, почему же восстановление (с точностью до
> перестановки слов) однозначно.

А ты видел вадимово объяснение (в BWT FAQ) принципа действия iBWT?

У нас есть последняя колонка таблицы. Мы ее сортируем, получаем первую - а также все диграммы, т.к. колонки соседние. Затем сортируем диграммы и т.п.

Далее, допустим, нам известно, что все разделители лексикографически предшествуют обычным символам. Что произойдет с вышеописанным процессом, если мы их все заменим в BWT единственным разделителем? А то, что поменяется только соответствие разделитель(в первой колонке) - символ (в последней), а не символ-символ. Т.о. от любого символа мы всегда сможем корректно перейти к следующему, нельзя лишь гарантировать, что с разделителя мы попадем именно на тот символ, который за ним следовал в оригинале, т.к. порядок разделителей в BWT утерян. Поэтому нельзя и применять к таким данным обычное BWT - возможны циклы etc. Однако с соответствием разделитель(в последней колонке)-символ также остается все в порядке, так что мы можем получить все слова (в произвольном порядке), перебрав все разделители.

Все программы/исходники, необходимые для проверки всего вышенаписанного, находятся здесь.