Почему коэффициент сжатия, использующий bzip2 для последовательности «a», такой скачкообразный?

15
library(ggplot2)

compress <- function(str) {
  length(memCompress(paste(rep("a", str), collapse=""), type="bzip2"))
  / nchar(paste(rep("a", str), collapse=""))
}

cr <- data.frame(i = 1:10000, r = sapply(1:10000, compress))

ggplot(cr[cr$i>=5000 & cr$i<=10000,], aes(x=i, y=r)) + geom_line()

введите описание изображения здесь

Степень сжатия начинается с 37 для «а» и достигает безубыточности при 39 «а» с (степень сжатия = 1). Диаграмма начинается довольно гладко и внезапно становится резкой для 98 "а" и оттуда через все более и более короткие интервалы.

Локальные минимумы и гладкие участки кажутся также довольно хаотичными и случайными Может кто-нибудь объяснить мне, почему bzip2 показывает это поведение в этом примере?

Раффаэль
источник

Ответы:

14

Предположим, что простой алгоритм сжатия представляет последовательность aпутем сохранения , то есть некоторый фиксированный заголовок, строка и количество повторений n . Это кодирование по длине прогона . Тогда длина сжатого текста была бы близка к в + Л.Г. п битов для некоторых констант через . , Соответствующий коэффициент сжатия будет + LG ( п )(header,"a",n)ana+lgna . Это примерно форма кривой, если смотреть с расстояния, если вы пренебрегаете локальными взлетами и падениями. Асимптотически, степень сжатия составляетΘ(lg(n)p/n)сp1(я не сработал, но я подозреваю, что есть другие факторы, которые делают размер выходного суперлинейного по длине строка ввода).a+lg(n)nΘ(lg(n)p/n)p1

lgnnana+1a+2ana+1na+2n

Поскольку степень сжатия слишком близка к обратной величине длины для визуального наблюдения, в моей реализации приведены данные для небольшой длины (это может зависеть от версии библиотеки bzip2, поскольку существует несколько способов сжатия некоторых входных данных. ). Первый столбец указывает количество aсимволов, второй столбец - длину сжатого вывода.

1–3       37
4–99      39
100–115   37
116–258   39
259–354   45
355       43
356       40
357–370   41
371–498   43
499–513   41
514–609   45
610       43
611       41
613–625   42
626–753   44
754–764   42
765       40
766–767   41
768       42
769–864   45
…

Bzip2 намного сложнее , чем простое кодирование длин серий. Он работает в несколько этапов, и первым шагом является этап кодирования по длине прогона , но с фиксированным ограничением размера. Первый шаг работает следующим образом: если байт повторяется по крайней мере 4 раза, то замените байты после 4-го байтом, указывающим количество повторений стертых байтов. Например, aaaaaaaпреобразуется в aaaa\d{3}(где \d{003}символ с байтовым значением 3); aaaaпреобразуется в aaaa\d{0}и т. д. Поскольку имеется только 256 различных байтовых значений, таким образом можно кодировать только последовательности, в которых байт повторяется до 259 раз; если их больше, начинается новая последовательность. Кроме того, эталонная реализация останавливается на счетчике повторов 252, который кодирует строку из 256 байтов.

an1n34n258aaaa\d{252}\d{252} это число повторений, я не проверял) сам повторяется и, следовательно, сжимается последующими шагами.

aaaa\374aan=258a

n=100a101aaaa\d{97}aaaaaan=101aA68n83

Мой анализ этого примера далеко не исчерпывающий. Чтобы понять другие эффекты, вам нужно изучить другие этапы преобразования: я в основном остановился после шага 1 из 9. Надеюсь, это даст вам представление о том, почему коэффициенты сжатия становятся немного изменчивыми и не изменяются монотонно. Если вы действительно хотите выяснить каждую деталь, я рекомендую взять существующую реализацию и наблюдать за ней с помощью отладчика.

По большей части такие мелкие вариации не являются главной целью при разработке алгоритма сжатия: во многих распространенных сценариях, таких как универсальные алгоритмы или алгоритмы сжатия мультимедиа, разница в несколько байтов не имеет значения. Сжатие пытается выжать каждый бит на локальном уровне и пытается преобразовать цепочки таким образом, чтобы выигрывать часто, редко проигрывая, а затем не сильно. Тем не менее существуют ситуации, например, специальные протоколы связи, предназначенные для связи с низкой пропускной способностью, где важен каждый бит. Другая ситуация, когда точная длина вывода имеет значение, - это когда сжатый текст зашифрован: когда злоумышленник может передать часть текста для сжатия и зашифрования, вариации длины зашифрованного текста могут раскрыть часть сжатого и зашифрованного текста для противник;ПРЕСТУПЛЕНИЕ эксплуатировать на HTTPS .

Жиль "ТАК - перестань быть злым"
источник