Differences

This shows you the differences between two versions of the page.

Link to this comparison view

sd-ca:teme:teme-04 [2015/04/29 13:26]
cosmin.boaca
sd-ca:teme:teme-04 [2015/05/26 09:25] (current)
alexandru.farcasanu [Tema 4]
Line 1: Line 1:
-===== Tema 4 =====+====== Tema 4 ======
  
-**Responsabili:** +Termen de predare: ​**Luni,  25 Mai 2015, ora 23:55**
  
-  ​*[[cosmin.boaca1994@gmail.com| Cosmin Boacă]] +Deadline hard: **Joi, 28 Mai, ora 23:55**
-  ​*[[ciprianfarcasanu@gmail.com| Alex Fărcășanu]]+
  
-<hidden>+<note important> 
 +**1 Mai** Adaugat precizare legata de reprezentantul unui nod. Actualizat arhiva de teste. ​
  
-==== Obiective ====+**23 Mai** Modificare deadline: 25 Mai. 
 + 
 +**24 Mai** Update script testare: limita de timp a fost marita la 100 de secunde. 
 +</​note>​ 
 +===== Obiective ​=====
  
 În urma realizării acestei teme, studentul va fi capabil: În urma realizării acestei teme, studentul va fi capabil:
Line 15: Line 19:
   * să folosească algoritmii de compresie pentru reprezentarea compactă a imaginilor în format bitmap   * să folosească algoritmii de compresie pentru reprezentarea compactă a imaginilor în format bitmap
  
-==== Cunoştinţe necesare ====+===== Cunoştinţe necesare ​=====
  
 Pentru a putea rezolva această temă, studentul trebuie să fie familiar cu următoarele noţiuni: Pentru a putea rezolva această temă, studentul trebuie să fie familiar cu următoarele noţiuni:
Line 22: Line 26:
   * codificarea Huffman - o documentaţie accesibilă poate fi găsită [[sd-ca:​teme:​doc-tema04|aici]].   * codificarea Huffman - o documentaţie accesibilă poate fi găsită [[sd-ca:​teme:​doc-tema04|aici]].
  
-==== Cerinţă ====+===== Cerinţă ​=====
  
-=== Enunt ===+==== Enunt ====
  
 Sarcina voastră este să implementaţi un program care să comprime / decomprime un fişier arbitrar, aplicând algoritmul Huffman. [[sd-ca:​teme:​doc-tema04|Aici]] este descris, pe scurt, algoritmul şi aveţi şi un exemplu pentru compresia unui şir de caractere (fişier text). Algoritmul funcţionează pentru orice tip de fişier (nu neapărat text): se consideră fişierul ca un şir de octeţi. Sarcina voastră este să implementaţi un program care să comprime / decomprime un fişier arbitrar, aplicând algoritmul Huffman. [[sd-ca:​teme:​doc-tema04|Aici]] este descris, pe scurt, algoritmul şi aveţi şi un exemplu pentru compresia unui şir de caractere (fişier text). Algoritmul funcţionează pentru orice tip de fişier (nu neapărat text): se consideră fişierul ca un şir de octeţi.
  
-=== Executabil ===+==== Executabil ​====
  
 Programul vostru va trebui să primească la intrare numele unui fişier şi o serie de opţiuni, în felul următor: Programul vostru va trebui să primească la intrare numele unui fişier şi o serie de opţiuni, în felul următor:
Line 48: Line 52:
 Astfel, daca numele fişierului este ''​poza.bmp'',​ fişierul comprimat se va numi ''​poza.bmp.cmp'',​ iar fişierul decomprimat ''​decompressed_poza.bmp''​ Astfel, daca numele fişierului este ''​poza.bmp'',​ fişierul comprimat se va numi ''​poza.bmp.cmp'',​ iar fişierul decomprimat ''​decompressed_poza.bmp''​
  
-=== Compresie ===+==== Compresie ​====
  
 Se va considera şirul de octeti din fişier ca pe un şir de simboluri. Acestui şir de simboluri va trebui să-i aplicaţi o codificare Huffman, (a se vedea documentaţia pusă la dispoziţie) asociind fiecărui simbol o probabilitate de apariţie egală cu frecvenţa simbolului în fişier (deci va trebui să parcurgeţi la început întregul fişier pentru a determina aceste probabilităţi). Pentru reprezentarea cozii prioritare din care veţi extrage nodurile cu costul cel mai mic, veţi folosi o structură de heap. Pentru heap, veţi avea nevoie de o funcţie care compară două noduri între ele, şi veţi folosi următoarele reguli (presupunem ca prioritatea este maximă în vârful cozii): Se va considera şirul de octeti din fişier ca pe un şir de simboluri. Acestui şir de simboluri va trebui să-i aplicaţi o codificare Huffman, (a se vedea documentaţia pusă la dispoziţie) asociind fiecărui simbol o probabilitate de apariţie egală cu frecvenţa simbolului în fişier (deci va trebui să parcurgeţi la început întregul fişier pentru a determina aceste probabilităţi). Pentru reprezentarea cozii prioritare din care veţi extrage nodurile cu costul cel mai mic, veţi folosi o structură de heap. Pentru heap, veţi avea nevoie de o funcţie care compară două noduri între ele, şi veţi folosi următoarele reguli (presupunem ca prioritatea este maximă în vârful cozii):
   * dacă probabilitate(Nod1) < probabilitate(Nod2),​ atunci Nod1 > Nod2 (ordinea se inversează),​ şi viceversa.   * dacă probabilitate(Nod1) < probabilitate(Nod2),​ atunci Nod1 > Nod2 (ordinea se inversează),​ şi viceversa.
   * dacă probabilitate(Nod1) = probabilitate(Nod2),​ atunci ne uităm la înălţimea nodului în arbore, şi dacă înălţime(Nod1) < înălţime(Nod2),​ atunci Nod1 > Nod2 (ordinea se inversează),​ şi viceversa.   * dacă probabilitate(Nod1) = probabilitate(Nod2),​ atunci ne uităm la înălţimea nodului în arbore, şi dacă înălţime(Nod1) < înălţime(Nod2),​ atunci Nod1 > Nod2 (ordinea se inversează),​ şi viceversa.
-  * dacă probabilitate(Nod1) = probabilitate(Nod2),​ şi înălţime(Nod1) = înălţime(Nod2),​ atunci Nod1 Nod2.+  * dacă probabilitate(Nod1) = probabilitate(Nod2),​ şi înălţime(Nod1) = înălţime(Nod2),​ atunci ​ne uitam la reprezentantii nodurilor (vezi definitie mai jos). Daca reprezentant(Nod1) < reprezentant(Nod2) atunci Nod1 > Nod2 (ordinea se inversează),​ si viceversa.
  
-Practic, aceste reguli specifică ordinea în care se vor scoate elementele din coadă: se preferă cele cu probabilitate mică, iar dacă sunt mai multe cu aceeaşi probabilitate,​ le vom lua pe cele de pe nivelurile cele mai mici, pentru a păstra echilibrat arborele ​Huffman.+Practic, aceste reguli specifică ordinea în care se vor scoate elementele din coadă: se preferă cele cu probabilitate mică, iar dacă sunt mai multe cu aceeaşi probabilitate,​ le vom lua pe cele de pe nivelurile cele mai mici, pentru a păstra echilibrat arborele. Daca si inaltimile sunt egale, luam in considerare reprezentantul. Astfel vom avem un mod unic de a scoate elementele din coada prioritara.
  
-=== Serializare ===+**Reprezentantul** unui nod se defineste in felul urmator: 
 +   * daca nodul este frunza, reprezentantul este caracterul(octetul) asociat frunzei respective (In exemplul de [[sd-ca:​teme:​doc-tema04|aici]] reprezentantii tuturor frunzelor sunt '​a',​ '​n',​ ' ', '​r',​ '​e',​ '​m'​). 
 +   * altfel, reprezentant(Nod) = minim {reprezentant(Nod_stanga),​ reprezentant(Nod_dreapta)} unde Nod_stanga si Nod_dreapta sunt fii nodului Nod. 
 + 
 +==== Serializare ​====
  
 Arborele Huffman construit va fi necesar şi in pasul de decompresie,​ astfel că este nevoie sa fie salvat in fişier. Reprezentarea arborelui în fişier trebuie să fie cel de vector de structuri de forma: Arborele Huffman construit va fi necesar şi in pasul de decompresie,​ astfel că este nevoie sa fie salvat in fişier. Reprezentarea arborelui în fişier trebuie să fie cel de vector de structuri de forma:
Line 77: Line 85:
   * ''​value''​ reprezintă valorea simbolului (valoarea octetului) din frunza arborelui;   * ''​value''​ reprezintă valorea simbolului (valoarea octetului) din frunza arborelui;
   * ''​childData''​ reprezintă informaţii despre descendenţi,​ în cazul nodurilor neterminale;​ leftChild şi rightChild reprezintă indecşi în vectorul de structuri (indexarea porneşte de la 0), şi indică structurile ce codifică descendenţii stâng, respectiv drept, ai nodului. Trebuie remarcat faptul că într-un arbore Huffman, un nod fie este terminal, fie are exact doi descendenţi,​ deci cele două câmpuri vor fi valide simultan. De asemenea, structura de pe poziţia 0 din vector va fi rădăcina arborelui Huffman.   * ''​childData''​ reprezintă informaţii despre descendenţi,​ în cazul nodurilor neterminale;​ leftChild şi rightChild reprezintă indecşi în vectorul de structuri (indexarea porneşte de la 0), şi indică structurile ce codifică descendenţii stâng, respectiv drept, ai nodului. Trebuie remarcat faptul că într-un arbore Huffman, un nod fie este terminal, fie are exact doi descendenţi,​ deci cele două câmpuri vor fi valide simultan. De asemenea, structura de pe poziţia 0 din vector va fi rădăcina arborelui Huffman.
 +
 +<note tip>
 +Observam ca reprezentantul unui nod nu este salvat in fisier deoarece nu mai avem nevoie de el. Acesta a fost folosit pentru a garanta o secventa unica de extragere a nodurilor din coada prioritara.
 +</​note>​
  
 După ce este scris arborele Huffman se scrie şi dimensiunea fişierului de intrare ca un element de tip întreg fara semn(necesar la decomprimare pentru a şti câte simboluri trebuie decodificate). Urmează simbolurile scrise codificat în ordinea în care au fost citite din fişierul original. În urma aplicării arborelui Huffman asupra simbolurilor,​ se obţine un şir de biţi. După ce este scris arborele Huffman se scrie şi dimensiunea fişierului de intrare ca un element de tip întreg fara semn(necesar la decomprimare pentru a şti câte simboluri trebuie decodificate). Urmează simbolurile scrise codificat în ordinea în care au fost citite din fişierul original. În urma aplicării arborelui Huffman asupra simbolurilor,​ se obţine un şir de biţi.
Line 95: Line 107:
   * 10010111<​sub>​(2)</​sub>​ = 151<​sub>​(10)</​sub>​   * 10010111<​sub>​(2)</​sub>​ = 151<​sub>​(10)</​sub>​
   * 10111110<​sub>​(2)</​sub>​ = 190<​sub>​(10)</​sub>​   * 10111110<​sub>​(2)</​sub>​ = 190<​sub>​(10)</​sub>​
-  * **00**010001<​sub>​(2)</​sub>​ = 17<​sub>​(10)</​sub>​. **Atentie:​** in cazul in care numarul total de biti nu este multiplu de 8, se vor adauga biti de **0** ca padding.+  * **00**010001<​sub>​(2)</​sub>​ = 17<​sub>​(10)</​sub>​. ​
  
-TODO: atentionare - folosire doar unsigned vars.+<note warning>
  
-=== Format fisier comprimat ===+**Atentie:​** in cazul in care numarul total de biti nu este multiplu de 8, se vor adauga biti de **0** ca padding. 
 + 
 +Pentru operaţiile pe biţi folosiţi **DOAR variabile unsigned**. 
 + 
 +Recomandarea noastră este să folosiţi tipurile de date **uint8_t** / **uint16_t** / **uint32_t** după caz. 
 + 
 +</​note>​ 
 + 
 +==== Format fisier comprimat ​====
  
 Conform celor spuse mai sus, formatul unui fisier comprimat trebuie sa arate astfel (in aceasta ordine): Conform celor spuse mai sus, formatul unui fisier comprimat trebuie sa arate astfel (in aceasta ordine):
Line 105: Line 125:
 ^Camp|**K**| **V** | **N** | **L**| ^Camp|**K**| **V** | **N** | **L**|
 ^Semnificatie|numarul de noduri din arbore| arborele serializat | dimensiunea fisierului original | fisier comprimat| ^Semnificatie|numarul de noduri din arbore| arborele serializat | dimensiunea fisierului original | fisier comprimat|
-^Tip/​Dimensiune | 1 * uint16_t | K * HuffmanSerializedNode | 1 * uint32_t | sir de biti de lungime variabila ​|+^Tip/​Dimensiune | 1 * uint16_t | K * HuffmanSerializedNode | 1 * uint32_t | sir de biti ce reprezinta fisierul comprimat ​|
  
-==== Testare ====+===== Testare ​=====
  
 Testarea temei se va face folosind [[https://​vmchecker.cs.pub.ro/​ui/#​SD|vmchecker]]. Testarea temei se va face folosind [[https://​vmchecker.cs.pub.ro/​ui/#​SD|vmchecker]].
Line 118: Line 138:
  
 Puteţi descărca checker-ul pentru testare locală sub linux de [[http://​ocw.cs.pub.ro/​courses/​_media/​sd-ca/​teme/​checker.zip|aici]]. Puteţi descărca checker-ul pentru testare locală sub linux de [[http://​ocw.cs.pub.ro/​courses/​_media/​sd-ca/​teme/​checker.zip|aici]].
 +
 +<​note>​
 +Folositi flag-ul de optimizare -O2 la compilare.
 +</​note>​
  
  
-==== Alte precizari ====+===== Alte precizari ====
 +  * Atunci cand se construieste un nod nou, nodul cel mai prioritar din coada va deveni fiul **stang** al noului nod. 
 +  * Serializarea arborelui se va face printr-o parcurgere in **preordine**.
   * Se recomanda ca atat citirea cat si scrierea sa se realizeze cu functiile fread si fwrite. ​   * Se recomanda ca atat citirea cat si scrierea sa se realizeze cu functiile fread si fwrite. ​
   * Se recomanda folosirea tipurile de date uint8_t, uint16_t si uint32_t in cazul citirii si scrierii din fisiere. ​   * Se recomanda folosirea tipurile de date uint8_t, uint16_t si uint32_t in cazul citirii si scrierii din fisiere. ​
Line 130: Line 156:
     * Puteți folosi funcționalități ale C++, cu excepția claselor care implementeaza direct funcționalitatea cerută (cum ar fi priority_queue din STL).     * Puteți folosi funcționalități ale C++, cu excepția claselor care implementeaza direct funcționalitatea cerută (cum ar fi priority_queue din STL).
  
-</​hidden>​ 
sd-ca/teme/teme-04.1430303166.txt.gz · Last modified: 2015/04/29 13:26 by cosmin.boaca
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0