Tematy projektów Algorytmy Kompresji Danych (2006) Projekt nr 1 Temat: Kompresor plików w formacie.dbf Opracować algorytm kompresji plików w formacie.dbf. W algorytmie należy wykorzystać znajomość struktury pliku.dbf. Algorytm powinien każdorazowo analizować nagłówek pliku.dbf, a następnie uzależnić sposób kompresji od struktury pliku (propozycje): kompresję można przeprowadzać kolumnami (a nie wierszami), sposób kodowania kolumny uzależnić od typu pola (np. pola tekstowe LZSS (+ arytmetyczne), pola logiczne kodowanie arytmetyczne lub wprost binarne, itp.), kolejność kolumn można zmienić tak, aby zgrupować kolumny tego samego typu, opłacalne może okazać się (dla niektórych typów pól: data, liczbowe, logiczne) kodowanie różnic pomiędzy kolejnymi polami (np. dla dat: dni od poprzedniej daty) zamiast kodowania wartości pola wprost; algorytm może wypróbować oba sposoby i wybierać każdorazowo lepszy. Po dekompresji plik.dbf nie musi być identyczny z plikiem sprzed kompresji, wystarczy aby plik ten zawierał dokładnie takie same dane (kolejność wierszy i rekordów, zawartość rekordów, nazwy pól, itp.) jak przed kompresją. Projekt nr 2 Temat: Kompresja pliku w formacie.dbf z zachowaniem dostępu swobodnego do rekordów Opracować algorytm kompresji plików w formacie.dbf, przy czym po skompresowaniu pliku powinna być możliwość dekodowania dowolnego rekordu bez konieczności dekodowania innych rekordów oraz dodawania, usuwania, modyfikacji rekordów. Proponowane rozwiązanie: każdy rekord musi być zakodowany niezależnie od pozostałych oprócz zakodowanych rekordów skompresowane dane winny zawierać, wspólny dla wszystkich rekordów, opis ich charakterystyki (np. słownik dla pól tekstowych) na podstawie którego poszczególne rekordy kodowane są niezależnie, ponieważ rekordy będą miały różne długości, konieczne będzie utworzenie indeksu (tablicy offsetów początków poszczególnych rekordów w pliku)
operacja modyfikacji rekordu może zmienić jego rozmiar (w postaci skompresowanej) w takim przypadku należy umieścić go na końcu pliku, a jego poprzednią lokalizację oznaczyć jako puste miejsce (lub umieścić w wystarczająco dużym pustym miejscu pozostałym po innym rekordzie) zatem należy przechowywać również indeks/listę pustych miejsc, w sposób podobny, jak wyżej, realizujemy usunięcie rekordu, aby skompresowany plik nie zawierał zbyt wiele pustego miejsca, należy zaimplementować operację przebudowy skompresowanego pliku, która polegać będzie na usunięciu pustych miejsc; taka przebudowa powinna być wykonywana na żądanie oraz ewentualnie w sytuacji, gdy puste miejsca zajmują ponad (np.) 10% skompresowanego pliku, aby algorytm efektywnie kompresował nowo dodawane rekordy i aby usunięte rekordy nie zajmowały miejsca w danych wspólnych dla wszystkich rekordów konieczna jest okresowa aktualizacja tych danych można ją przeprowadzać co n dodanych rekordów oraz łącznie z przebudową pliku. Projekt nr 3 Temat: Kompresja pliku w formacie.ini z zachowaniem dostępu swobodnego do sekcji i kluczy Liczba osób: 1 Temat analogiczny do Kompresja pliku w formacie.dbf z zachowaniem dostępu swobodnego do rekordów (Projekt 3), ale dla plików.ini systemu Windows. Projekt nr 4 Temat: Klasa skompresowanego string-a Liczba osób: 1 lub 2 Opracować klasę packedstring funkcjonalnie odpowiadającą klasie string z biblioteki standardowej języka C++, ale potrafiącą wewnętrznie przechowywać łańcuch w postaci skompresowanej. Klasa packedstring przeznaczona jest do zastosowania tam, gdzie prawie wszystkie operacje na łańcuchach to operacja przypisania i operacje we/wy realizowane na całym łańcuchu oraz dopisywanie na końcu łańcucha innego łańcucha lub pojedynczego znaku. Można przyjąć, że typowy rozmiar łańcucha jest odpowiednio duży (kilkaset znaków). Uwagi: rozwiązanie można zrealizować w oparciu o kodowanie słownikowe LZSS (ewentualnie LZSS + koder arytmetyczny ze stałym modelem) przy dopisaniu, na końcu łańcucha, nowego znaku lub łańcucha, kompresja będzie efektywniejsza, jeżeli cofniemy się do początku ostatnio zakodowanej frazy i spróbujemy czy teraz nie znajdzie się dłuższa fraza (można również koniec łańcucha kodować z pewnym opóźnieniem), poniżej pewnej granicznej długości łańcucha kompresja jest nieefektywna, więc klasa packedstring winna krótkie łańcuchy przechowywać nie skompresowane,
klasa powinna obsługiwać również pozostałe typowe operacje na łańcuchach (w tym np. swobodne indeksowanie znaków łańcucha, metodę c_str(), itp.) niektóre takie operacje wymagać będą przejścia na nie skompresowaną reprezentację łańcucha i pozostawienia łańcucha w takiej postaci (np. spakowany_napis[20]= a ); klasa powinna mieć metodę wymuszenia wewnętrznej reprezentacji skompresowanej lub nie. Projekt nr 5 Temat: Klasa C++ reprezentująca archiwum ZIP Standard formatu ZIP dopuszcza dwa algorytmy kompresji, które są implementowane za pomocą poznanych bibliotek: zlib oraz libbzip2 (patrz pierwsze laboratorium). Tematem projektu jest wykorzystanie obu tych bibliotek do stworzenia klasy języka C++ reprezentującej archiwum ZIP. Klasa powinna udostępniać min. następujące metody: Create utworzenie pustego archiwum, Open otwarcie archiwum, Close zamknięcie archiwum, ListContents zwrócenie listy plików (do listy), GetHeader zwrócenie nagłówka konkretnego pliku z archiwum, AddFile dodanie pliku do archiwum z kompresją (tu się ustala parametry kompresji), AddFileRaw dodanie do archiwum pliku skompresowanego (przydaje się kiedy trzeba przenosić plik z archiwum do archiwum np. przy wyrzucaniu niektórych plików, bądź zastępowaniu nową wersją), GetFile dekompresja pliku z archiwum, GetFileRaw zwrócenie z archiwum pliku skompresowanego. Klasa powinna także umożliwiać podpięcie przez użytkownika własnego paska postępu (np. poprzez odziedziczenie po jakiejś klasie bazowej) i własnej obsługi błędów. Projekt nr 6 Temat: Klasa C++ reprezentująca automat przechowujący leksykon Źródła automatu reprezentującego leksykon są dostępne na stronie http://www-zo. iinf.polsl.gliwice.pl/ sdeor/pub/cd00abs.htm. Należy te źródła przerobić na C++ i dodać funkcjonalność zapisu automatu na dysk w postaci jeszcze bardziej skompresowanej (możliwy jest stopień kompresji 2:1 a nawet trochę więcej). Do kompresji należy wykorzystać RangeCoder. Automat przechowywany jest wewnętrznie w postaci tablicy. Tablica ta zawiera w kolejnych komórkach krawędzie. Kilka (od 1 do kilkudziesięciu) kolejnych krawędzi opisuje jeden węzeł. Każdy węzeł kończy się krawędzią, która ma ustawiony bit (znacznik końca węzła). Kilka pomysłów jak jeszcze można kompresować ten automat:
znaczniki końca węzła są ustawione w większości krawędzi na 0, a tylko w tych kończących węzeł na 1, znaczniki terminalności rzadziej są ustawione na 0 niż na 1, krawędzie w węźle ułożone są w porządku alfabetycznym (w wersji podstawowej automatu), tj. kontekstem symbolu może być poprzedni symbol, adresy zawsze wskazują na niższe pozycje w tablicy, adres jest potencjalnie liczbą z zakresu [0, 2 22 1], więc należy go efektywnie kodować. Uwaga: krawędź na pozycji 0 w automacie ma specjalne znaczenie wskazuje węzeł startowy. Projekt nr 7 Temat: Porównanie kilku implementacji kodowania arytmetycznego Liczba osób: 1 lub 2* Przeprowadzić porównanie kilku publicznie dostępnych implementacji algorytmu kodowania arytmetycznego, porównywane implementacje ocenić pod względem: uzyskiwanych współczynników kompresji: dla rzeczywistych danych (np. korpusu Calgary) i prostego modelu danych (np. adaptacyjnego probabilistycznego modelu 1 rzędu, własnego lub gotowego); należy porównać wyniki pomiędzy różnymi implementacjami oraz porównać je z efektywnością idealnego kodera arytmetycznego (mierzoną dla użytego modelu danych tak, jak na ćwiczeniu 2), (*) oraz dla danych wygenerowanych przez kilka samodzielnie zaimplementowanych modeli źródeł o znanych entropiach, prędkości kodowania i dekodowania (w miarę możliwości prędkości wyznaczyć dla kodowania, a nie kodowania i modelowania; można to zrealizować mierząc czasy (a) modelowania i kodowania oraz (b) tylko modelowania), łatwości użycia i jakości dokumentacji. Badania przeprowadzić dla następujących implementacji: Range Coder (http://www.compressconsult.com/rangecoder/), Koder MNW (http://www.cs.mu.oz.au/ alistair/arith coder/), Koder FastAC Sayooda (http://www.cipr.rpi.edu/ said/fastac.html), (*) Koder CACM (ftp://ftp.cpsc.ucalgary.ca/pub/projects/ar.cod/cacm-87.shar), (*) MQ Coder (koder binarny z wbudowanym modelem, dostępny wraz z implementacjami algorytmów JBIG2, JPEG2000, np.: www.ece.uvic.ca/ mdadams/ jasper/). Projekt nr 8 Temat: Porównanie algorytmów LZSS i LZW w zastosowaniu do kompresji dysku Liczba osób: 1 Przeprowadzić porównanie algorytmów LZSS i LZW (lub odmiany LZW-AP tj. takiej, w której po zakodowaniu nowej frazy, do słownika wstawiamy nie tylko
poprzednią frazę z dopisanym pierwszym znakiem nowej, ale też frazy zbudowane z poprzedniej frazy i wszystkich prefiksów nowej). Algorytmy testujemy w zastosowaniu do kompresji dysku (tj. tak, aby zachowana była możliwość częściowo swobodnego odczytu zakodowanych danych), co realizujemy następująco: skompresowane dane zapisujemy w klastrach o rozmiarze np. 4KB każdy, przy czym każdy klaster może zostać odkodowany niezależnie od pozostałych dla nas oznacza to, iż każdorazowo gdy rozmiar zakodowanych danych osiąga granicę klastra reinicjalizujemy słownik i kolejne dane kodujemy niezależnie od poprzednich, aby dostęp był faktycznie swobodny, do zakodowanych danych powinniśmy dołączyć mapę/indeks z informacją jakim offsetom nieskompresowanego pliku odpowiadają początki kolejnych klastrów. Algorytmy należy porównać pod względem uzyskiwanych współczynników kompresji dla plików korpusu Calgary, porównania należy przeprowadzić dla kilku rozmiarów klastra (np. 0.5, 1, 4 i 16KB). Projekt nr 9 Temat: Algorytm kompresji oparty na transformacie Burrowsa Wheelera Zaimplementować algorytm kompresji oparty na transformacie Burrowsa Wheelera. Algorytm powinien składać się z następujących etapów: transformata Burrowsa Wheelera dowolna implementacja algorytmu sortowania, może być nawet qsort z języka C; trzeba tylko pamiętać aby nie przechowywać całej macierzy a tylko indeksy pozycji startowych, transformata MTF w zupełności wystarcza tu naiwna implementacja, tj. utrzymujemy posortowaną tablicę i wyszukujemy symbol zawsze od początku, po czym przesuwamy go w tej tablicy na początek, RangeCoder sposób modelowania można wybrać dowolny: jeden z omówionych na wykładzie bądź dowolny własny. Otrzymany algorytm przetestować dla korpusu Calgary i porównać uzyskiwane współczynniki kompresji a także czas przynajmniej z bzip2 oraz gzip. Projekt nr 10 Temat: Algorytm kompresji różnicowej Opracować i zaimplementować algorytm kompresji różnicowej oparty na algorytmie LZSS. Problem przesuwania okna w starej wersji pliku można rozwiązać na kilka sposobów: założyć, że najdłuższe znalezione dopasowania dla bieżącej pozycji w plikach starym i nowym wyznaczają punkt synchronizacji, wyszukiwać w całym starym pliku wtedy trzeba odpowiednio zmodyfikować zapis dopasowania, aby były obsługiwane duże wartości.
Pierwszy symbol trójek/par z algorytmu LZSS powinien mieć tu 3 wartości: brak dopasowania, dopasowanie w nowym pliku, dopasowanie w starym pliku. Opisy dopasowania w starym i nowym pliku mogą być kodowane w osobnych kontekstach dla poprawy współczynnika kompresji. Przetestować program na kolejnych wersjach kilku (może być 2) dużych plików. Porównać współczynniki kompresji z osiąganymi przez algorytmy uniwersalne. Projekt nr 11 Temat: Kompresja plików XML Opracować i zaimplementować algorytm kompresji plików XML oparty na preprocesingu. Należy wykorzystać omówione na wykładzie przykłady redundancji w tych plikach. Przetestować program na kilku plikach XML i porównać go z innymi znanymi algorytmami specjalizowanymi oraz z algorytmami uniwersalnymi.