У меня есть следующая строка, которую я хотел бы кодировать Хаффманом и эффективно хранить в битовом массиве:
>>> print sequence
GTCAGGACAAGAAAGACAANTCCAATTNACATTATG|
Частоты символов в sequence
:
>>> print freqTuples
[(0.40540540540540543, 'A'), (0.1891891891891892, 'T'), (0.16216216216216217, 'C'), (0.16216216216216217, 'G'), (0.05405405405405406, 'N'), (0.02702702702702703, '|')]`
Я перевожу это в словарь кодов Хаффмана:
>>> print codeDict
{'A': '1', 'C': '010', 'G': '001', 'N': '0110', 'T': '000', '|': '0111'}
Затем я использовал пакет Python bitstring
для перевода строки, символ за символом, в экземпляр класса BitArray
, который я называю bitArray
, который содержит биты для каждого символа, закодированного с помощью соответствующего кода Хаффмана. :
>>> print bitArray.bin
0b001000010100100110101100111100110101101100000100101100000001101010100000010000010111
Вот битовый массив в байтах:
>>> print bitArray.tobytes()
!I\254\363[^D\260^Z\240Ap
Я должен использовать tobytes()
вместо bytes
, так как сгенерированный битовый массив не делится равномерно на 8-битные сегменты.
Когда я вычисляю эффективность хранения представления BitArray
(соотношение размеров массива битов и входной строки), я получаю худшую производительность, чем если бы я оставил входную строку без кодировки:
>>> sys.getsizeof(bitArray.tobytes()) / float(len(sequence))
1.2972972973
Правильно ли я измеряю эффективность хранения? (Если я кодирую более длинные входные строки, это соотношение улучшается, но кажется, что оно приближается к асимптотическому пределу около 0,28. Я хотел бы подтвердить, что это правильный способ измерения.)
Редактировать
Следующие два подхода дают разные ответы:
>>> print len(bitArray.tobytes()) / float(len(mergedSequence))
0.297297297297
>>> print bitArray.len / (8.*len(mergedSequence))
0.283783783784
Я не уверен, во что верить. Но в процессе записи данных в хранилище я думаю, что мне понадобится байтовое представление, что заставляет меня склоняться к выбору первого результата.