Сжатие двоичной матрицы - PullRequest
4 голосов
/ 19 мая 2011

Нас попросили найти способ максимально сжать квадратную двоичную матрицу и, если возможно, добавить биты избыточности для проверки и, возможно, исправления ошибок.

Внедрение избыточности легко реализовать вмое мнение.Сложная часть - это сжатие матрицы.Я думал об использовании длины прогона после преобразования матрицы в вектор, потому что будет больше нулей, чем единиц, но я достиг сжатия только в 40 бит (мы работаем с небольшими размерами), хотя я думал, что это будет лучше.

Кроме того, после длины прогона идея состояла в том, чтобы Хаффман кодировал матрицу, но для восстановления исходной информации необходимо отправить словарь.

Я хотел бы знать, как лучше всего сжать двоичную матрицу?

После прочтения некоторых комментариев да @ Адам, вы правы, матрица 14x14 должна быть сжата в 128 битах, поэтому, если я буду использовать только координаты (строки и столбцы) для каждого ненулевого элемента, все равно это будет 160 бит(поскольку их двадцать).Я не ищу точное решение, но полезную идею.

Ответы [ 4 ]

5 голосов
/ 19 мая 2011

Вы можете говорить о сжатии чего-либо, только если у вас есть дистрибутив и представление.Это вопрос словаря, который вы должны отправить: вам всегда нужен какой-то словарь протокола для распаковки чего-либо.Просто так получилось, что такие вещи, как .zip и .mpeg, уже имеют эти словари / кодеки.Даже такая простая вещь, как кодирование по Хаффману, является алгоритмом;на другой стороне канала связи (вы можете думать о сжатии как о связи), у другого человека уже есть немного кода (словарь) для выполнения схемы декомпрессии Хаффмана.

Таким образом, вы даже не можете начатьпоговорим о сжатии чего-либо, не думая сначала «какие матрицы я ожидаю увидеть?», «действительно ли данные случайны или есть порядок?», и если да, то «как я могу представить матрицы, чтобы воспользоваться преимуществами порядка вданные? ".

Вы не можете сжать некоторые матрицы, не увеличив размер других объектов (по крайней мере, на 1 бит).Это плохая новость, если все матрицы одинаково вероятны, и вы одинаково заботитесь обо всех них.

Дополнения:

Ответ на использование механизма разреженных матриц не обязательноправильный ответ.Например, матрица может быть представлена ​​в python как [[(r+c)%2 for c in range (cols)] for r in range(rows)] (шаблон шахматной доски), и разреженная матрица вообще не будет сжимать ее, но сложность матрицы по Колмогорову - это длина программы, описанная выше.

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

Сколько единиц составляет матрица в виде доли от ее размера и каков ее размер (NxN - что такое N)?

Кроме того, это неверное утверждение, и его не следует использовать в качестве причины для желательного кодирования по длине прогона (для которого все еще требуется программа);когда вы передаете данные по каналу, вы всегда можете добавить исправление ошибок в эти данные.«Данные» - это просто кусочек.Вы можете передавать как данные, так и любые необходимые словари по каналу.Механизм исправления ошибок совершенно не заботится о том, для чего предназначены передаваемые вами биты.

Приложение 2:

Существуют (14*14) choose 20 возможные схемы, которые, как я полагаю,выбираются случайным образом.Если бы это число было больше 128^2, то то, что вы пытаетесь сделать, было бы невозможно.К счастью log_2((14*14) choose 20) ~= 90bits < 128bits, так что это возможно.

Простое решение записать 20 чисел, таких как 32,2,67,175,52,...,168, не будет работать, потому что log_2(14*14)*20 ~= 153bits > 128bits.Это было бы эквивалентно кодированию по длине прогона.Мы хотим сделать что-то подобное, но у нас очень строгий бюджет и мы не можем позволить себе быть «расточительными» с битами.

Поскольку вы одинаково заботитесь о каждой возможности, ваша «словарь» / «программа» будет имитироватьгигантский справочный стол. Реализация Matlab с разреженной матрицей может работать, но она не гарантированно работает и поэтому не является правильным решением.

Если вы можете создать биекцию между диапазоном чисел [0,2^128) и подмножествами размера 20ты в порядке.Это соответствует перечислению способов спуска пирамиды в http://en.wikipedia.org/wiki/Binomial_coefficient до 20-го элемента строки 196. Это то же самое, что и перечисление всех «k-комбинаций».См. http://en.wikipedia.org/wiki/Combination#Enumerating_k-combinations

К счастью, я знаю, что Mathematica, Sage и другое программное обеспечение CAS, по-видимому, могут генерировать "5-е" или "12-е" или произвольно пронумерованное k-подмножество.Просматривая их документацию, мы сталкиваемся с функцией под названием «rank», например, http://www.sagemath.org/doc/reference/sage/combinat/subset.html

. Затем мы проводим дополнительный поиск и сталкиваемся с каким-то загадочным кодом Фортрана, таким как http://people.sc.fsu.edu/~jburkardt/m_src/subset/ksub_rank.m и http://people.sc.fsu.edu/~jburkardt/m_src/subset/ksub_unrank.m

Мы могли бы перепроектировать его, но он довольно плотный. Но теперь у нас достаточно информации для поиска k-subset rank unrank, что приводит нас к http://www.site.uottawa.ca/~lucia/courses/5165-09/GenCombObj.pdf - см. Раздел «Генерация k-подмножеств (из n-множества): лексикографическая Упорядочивание "и алгоритмы rank и unrank на следующих нескольких страницах.

Чтобы достичь точного теоретически оптимального сжатия, в случае равномерно случайного распределения 1 с, мы должны, таким образом, использовать эту технику, чтобы подвести наши матрицы к нашему выходному числу в диапазоне <<code>2^128. Так уж сложилось, что комбинации имеют естественный порядок, известный как ранжирование и расстановка комбинаций. Вы назначаете номер для каждой комбинации (рейтинг), и если вы знаете номер, вы автоматически знаете комбинацию (unranking). Поиск в Google k-subset rank unrank, вероятно, приведет к другим алгоритмам.

Таким образом, ваше решение будет выглядеть так:

serialize the matrix into a list
    e.g. [[0,0,1][0,1,1][1,0,0]] -> [0,0,1,0,1,1,1,0,0]
take the indices of the 1s:
    e.g. [0,0,1,0,1,1,1,0,0] -> [3,5,6,7]
          1 2 3 4 5 6 7 8 9      a k=4-subset of an n=9 set
take the rank
    e.g. compressed = rank([3,5,6,7], n=9)
         compressed==412 (or something, I made that up)
you're done!
    e.g. 412 -binary-> 110011100 (at most n=9bits, less than 2^n=2^9=512)
to uncompress, unrank it
3 голосов
/ 20 мая 2011

Я получу 128 бит в секунду, во-первых, вот как вы подгоните логическую матрицу 14x14 с ровно 20 ненулевыми значениями в 136 бит. Он основан на формате разреженной матрицы CSC.

У вас есть массив c с 14 4-битными счетчиками, которые сообщают вам, сколько ненулевых элементов в каждом столбце. У вас есть другой массив r с 20 4-битными индексами строк.

56 бит (с) + 80 бит (р) = 136 бит.

Давайте выжмем 8 бит из c: Вместо 4-битных счетчиков используйте 2-битные. c теперь 2 * 14 = 28 бит, но не может поддерживать более 3 ненулевых значений на столбец. Это оставляет нам 128-80-28 = 20 бит. Используйте это пространство для массива a4c с 5 4-битными элементами, которые "добавляют 4 к элементу c", заданным 4-битным элементом. Итак, если a4c={2,2,10,15, 15}, это означает c[2] += 4; c[2] += 4 (again); c[10] += 4;.

«Наиболее расточительное» распределение ненулевых значений - это такое, в котором для подсчета столбцов потребуется добавить -4 для поддержки 1 дополнительного ненулевого значения: 5 столбцов с 4 ненулевыми значениями в каждом. К счастью, у нас есть ровно 5 надстроек.

Общее пространство = 28 бит (с) + 20 бит (a4c) + 80 бит (r) = 128 бит.

3 голосов
/ 19 мая 2011

Ваш вклад является идеальным кандидатом на разреженную матрицу. Вы сказали, что используете Matlab, поэтому у вас уже есть хорошая разреженная матрица для вас.

spm = sparse(dense_matrix)

Реализация разреженной матрицы в Matlab использует сжатые разреженные столбцы, использование памяти которых составляет порядка 2*(# of nonzeros) + (# of columns), что должно быть довольно хорошо в вашем случае с 20 ненулевыми и 14 столбцами. Хранить 20 значений лучше, чем хранить 196 ...

Также помните, что все матрицы в Matlab собираются из двойных чисел. Тот факт, что ваша матрица может быть сохранена как 1-битное логическое значение, не означает, что Matlab не будет привязывать ее к 64-битному значению с плавающей запятой ... Если вам это нужно как логическое значение, вам придется сделать введите свой собственный C и используйте файлы .mex для взаимодействия с Matlab.

0 голосов
/ 19 мая 2011

Подумав об этом еще раз, если все ваши матрицы будут такими маленькими и все они будут двоичными, просто сохраните их как двоичный вектор (битовая маска). Если исходить из примера 14x14, для которого требуется 196 бит или 25 байтов (плюс n, m, если ваши размеры не постоянны). Этот же вектор в Matlab будет использовать 64 бита на элемент или 1568 байт. Хранение матрицы в виде битовой маски занимает столько же места, сколько 4 элемента исходной матрицы в Matlab, при степени сжатия 62x.

К сожалению, я не знаю, поддерживает ли Matlab битовые маски изначально или вам приходится прибегать к файлам .mex. Если вы попадаете в C ++, вы можете использовать STL vector<bool>, который реализует битовую маску для вас.

...