Saya memiliki file yang berisi nomor biner yang dipesan dari hingga :
0000000000
0000000001
0000000010
0000000011
0000000100
...
1111111111
7z tidak mengkompres file ini dengan sangat efisien (untuk n = 20, 22 MB dikompresi hingga 300 kB).
Apakah ada algoritma yang dapat mengenali struktur data yang sangat sederhana dan mengkompres file ke beberapa byte? Saya juga ingin tahu apa bidang CS atau teori informasi yang mempelajari algoritma pintar tersebut. "AI" akan terlalu luas, harap sarankan kata kunci yang lebih konkret.
Gagasan simetri harus memainkan peran mendasar dalam kompresi data, tetapi kueri pencarian "simetri dalam kompresi data" dan "teori grup dalam kompresi data" secara mengejutkan mengembalikan hampir tidak ada yang relevan.
information-theory
data-compression
DSblizzard
sumber
sumber
Jawaban:
Ini tampaknya menjadi kasus penggunaan yang jelas untuk kompresi delta . Jika diketahui apriori, ini sepele: simpan angka pertama kata demi kata, dan untuk setiap angka berikutnya simpan hanya perbedaan dengan yang sebelumnya. Dalam kasus Anda, ini akan memberin
Ini kemudian dapat dengan pengkodean run-length sederhana disimpan dalam ruang , karena hanya ada O ( 1 ) kelompok (yaitu, dua) dari delta yang berbeda.O(n) O(1)
Jika tidak diketahui, hal yang paling sederhana adalah pencarian brute force untuk ukuran kata yang mewakili representasi delta / run-length tersingkat. Mungkin hanya pencarian ini untuk dipilih secara acak, √n Potongan berukuran N , untuk mengamortisasi overhead temuannsambil mempertahankan keandalan yang baik.N−−√ n
Tidak seperti proposal DW "all or nothing", kompresi delta dengan enkode run-length sebenarnya dapat memberikan rasio kompresi yang masuk akal untuk beberapa jenis konten dunia nyata yang sederhana, seperti audio resolusi rendah. (Dengan demikian cocok untuk kompresi audio berkualitas rendah, latensi rendah, dan daya rendah.)
sumber
Tentu, tentu saja ada algoritma. Ini algoritma saya:
Pertama, periksa apakah file tersebut berisi angka biner yang terurut dari hingga 2 n - 1 , untuk beberapa n . Jika demikian, tulis 0 bit diikuti oleh n satu bit diikuti oleh 0 bit.0 2n- 1 n n
Jika tidak, tulis 1 bit, lalu tulis 7z-kompresi file.
Ini sangat efisien untuk file dari struktur tertentu.
Intinya adalah: tidak ada makan siang gratis dalam kompresi data. Anda mungkin dapat membangun algoritma kompresi yang memampatkan satu jenis file dengan baik, dengan mengorbankan lebih banyak orang. Tetapi, jika Anda mengetahui sesuatu tentang sifat file yang akan Anda kompres, Anda dapat mengoptimalkan algoritme untuk jenis file tertentu.
Area ini adalah "kompresi data". Lihat tag kompresi data kami , dan baca buku teks tentang kompresi data.
sumber
Apa pun yang menggunakan BWT (Burrows-Wheeler transform) harus dapat mengompres dengan cukup baik.
Tes Python cepat saya:
(Angka di sini adalah 'first_compressor second_compressor time_taken bytes_out')
(BWT diambil dari sini )
Ini masih 'bukan hanya beberapa byte', tetapi masih jauh lebih baik daripada hanya gzip saja. BWT + bz2 turun ke 237 byte dari 1114111 untuk input 16-bit, misalnya.
Sayangnya, BWT terlalu lambat dan haus akan memori untuk banyak aplikasi. Terutama mengingat ini adalah implementasi naif dalam Python - pada mesin saya, saya kehabisan RAM sebelum 2 ** 20.
Dengan Pypy saya dapat menjalankan input 2 ** 20 penuh, dan memampatkannya menjadi 2611 byte dengan BWT diikuti oleh bz2. Tetapi mengambil lebih dari 3 menit dan memuncak pada lebih dari 4GB RAM yang digunakan ...
Sayangnya, pendekatan ini masih O (2 ^ n) ruang output, akan muncul - setidaknya dari kurva-pas 1..20.
sumber
eval
dengan melakukan:for first in (bwt_c, nothing, lzma, zlib, gzip, bz2):
danfOut = first.compress(inputData)
.4 times block size
memori (mis ~ ~ 4MB untuk ini) dan pada kecepatan>10 MB/s
(saya penulis perpustakaan bwt / algoritma kompresi) yang cukup dapat digunakan untuk banyak aplikasi. Perhatikan bahwa bahkan gzip menghasilkan hasil kompresi yang sangat baik. Terima kasih telah berbagi Saya tidak mengetahui adanya penelitian tentang penggunaan bwt dua kali.Pengkodean PNG melakukan apa yang Anda inginkan. Ini bekerja pada data kehidupan nyata juga, bukan hanya data yang sangat terorganisir.
Dalam PNG, setiap baris dikodekan dengan filter, yang 4 ditentukan. Salah satunya adalah "menyandikan piksel ini sebagai perbedaan antara nilainya dan nilai piksel yang di atasnya." Setelah pemfilteran, data kemudian di-zip menggunakan DEFLATE.
Penyaringan ini adalah contoh spesifik dari Delta Encoding yang disebutkan oleh leftaroundabout dalam jawabannya, kecuali alih-alih menindaklanjutinya dengan Run Length Encoding Anda menindaklanjutinya dengan algoritma DEFLATE yang lebih kuat. Ini mencapai tujuan yang sama, hanya DEFLATE akan menangani berbagai input yang lebih besar sambil tetap memberikan rasio kompresi yang diinginkan.
Alat lain yang sering digunakan dalam data ilmiah di mana filter + DEFLATE tidak cukup efektif adalah pengkodean BERAS. Dalam RICE, Anda mengambil satu blok nilai dan mengeluarkan semua bit paling signifikan terlebih dahulu, lalu semua bit paling signifikan ke-2, sampai ke bit paling tidak signifikan. Anda kemudian mengompres hasilnya. Untuk data Anda yang tidak akan seefektif pemfilteran gaya PNG (karena data Anda sempurna untuk pemfilteran PNG), tetapi untuk banyak data ilmiah cenderung menghasilkan hasil yang baik. Dalam banyak data ilmiah, kita melihat bit yang paling signifikan cenderung berubah perlahan, sedangkan yang paling signifikan hampir acak. Ini menggoda data yang sangat mudah diprediksi dari data yang sangat entropis.
sumber
Algoritma praktis apa pun yang mencari struktur tertentu akan dibatasi hanya pada struktur yang dikodekan secara keras. Anda dapat menambal 7z untuk mengenali urutan spesifik ini, tetapi seberapa sering struktur spesifik ini akan terjadi dalam kehidupan nyata? Tidak sering cukup untuk menjamin waktu yang diperlukan untuk memeriksa input untuk input ini.
Selain kepraktisan, orang dapat menganggap kompresor sempurna sebagai algoritma yang mencoba untuk membangun program terpendek yang menghasilkan output yang diberikan. Tidak perlu dikatakan, tidak ada cara praktis untuk melakukan ini. Bahkan jika Anda mencoba enumerasi brute-force dari semua program yang mungkin dan memeriksa apakah mereka menghasilkan output yang diinginkan ( bukan ide yang sepenuhnya gila ), Anda akan mengalami masalah Menghentikan , yang berarti bahwa Anda harus membatalkan uji coba berjalan setelah sejumlah tertentu langkah-langkah eksekusi, sebelum Anda tahu apakah program ini pasti tidak dapat menghasilkan output yang diinginkan.
Pohon pencarian untuk pendekatan brute force tumbuh secara eksponensial dengan panjang program dan tidak praktis untuk semua kecuali program yang paling sederhana (sekitar 5-7 instruksi panjang).
sumber
Rasio kompresi sepenuhnya tergantung pada dekompresor yang ditargetkan. Jika decompressor tidak dapat mendekode angka 4 byte berurutan lebih kompak dari 4 byte per angka maka Anda SOL.
Ada berbagai hal yang memungkinkan pengkodean angka berurutan. Misalnya penyandian diferensial. Anda mengambil n byte pada suatu waktu dan kemudian mengambil perbedaan atau xor bit dan kemudian kompres hasilnya. Ini menambahkan 4 opsi di sini untuk mencoba setiap hitungan byte: identitas
a'[i] = a[i]
; perbedaana'[i] = a[i-1]-a[i]
; membalikkan perbedaana'[i] = a[i]-a[i-1]
; dan xora'[i] = a[i]^a[i-1]
. Itu berarti menambahkan 2 bit untuk memilih metode dan jumlah byte untuk 3 dari 4 opsi.Namun tidak semua data merupakan urutan catatan dengan panjang tetap. Pengkodean diferensial tidak masuk akal untuk itu (kecuali kompresor dapat secara empiris membuktikan bahwa ia bekerja untuk sedikit data).
sumber