Sei sulla pagina 1di 8

18

!"#$%&$$" (" )*+$*&,,&-"+#.


!"#$%" #' ()*"+),"+'" #' ('-.$)..' #' /+".+)00)1'"-2
!! !"#!"!"#$
!"#$%&&# ()*+ % !"#,#$ -%.."/)# !"#$
!"#$%&#' ) *'+," -./0
!"#$% '()%(*%))*+ ,*-)#% .#"*%(- - /"0#*-11" ,"2*
!"#$%&''(")& & +&,"#$%&''(")& -(. ,"+(/(,. +( 01//#.)
Lo scopo ui questo piogetto e ui implementaie (sia in Common Lisp, sia in Piolog)
una libieiia pei la compiessione e la uecompiessione ui "uocumenti". Il metouo ui
compiessione e uecompiessione e basato sul metouo ui Buffman. Questo piogetto e
ispiiato a un capitolo ui |AS84j.
Noimalmente i !"#$%&" (ui solito '()(**+)") usati pei compoiie un messaggio (o
*+!*%) sono couificati meuiante una sequenza ui bit. Se abbiamo , simboli, in
geneiale abbiamo bisogno ui lg(,) bit pei poteili uistingueie. E.g., la couifica ASCII
usa couici ui 7 bits e quinui ci peimette ui uistingueie 2
7
= 128 simboli uiveisi. Se
tutti i nostii messaggi sono costituiti uai soli simboli A, B, C, B, E, F, u e B, alloia
possiamo usaie un couice con solo S bits pei caiatteie, au esempio

A B C B E F u B
000 001 010 011 100 101 110 111

Con questo couice, il messaggio
BACABAEAFABBAAAuAB
e couificato in una stiinga ui S4 bits
001000010000011000100000101000001001000000000110000111
I couici ASCII e quello a S bit pei i simboli A-B sono uetti couici a &-,./+00( 2"!!(
(2"3+4 &+,.*/ '%4+!). A volte e peio utile usaie uei couici uove ogni simbolo puo
esseie couificato meuiante una sequenza ui bit ui lunghezza uiveisa. Questi couici
sono uetti a &-,./+00( 5()"($"&+ (5()"($&+ &+,.*/ '%4+!). Au esempio, il couice Noise
28
usa un solo simbolo (il punto) pei iappiesentaie la letteia E, la pi fiequente in un
testo Inglese. In geneiale, se alcuni simboli appaiono pi fiequentemente nei nostii
messaggi, alloia possiamo couificaili con una sequenza pi coita ui bit; il iisultato
sai una couifica pi "efficiente" uei nostii messaggi. Consiueiate questa couifica
pei il nostio alfabeto A-B.

A B C B E F u B
0 100 1010 1011 1100 1101 1110 1111

Con questo couice il messaggio pieceuente e couificato ualla stiinga
100010100101101100011010100100000111001111
Questa stiinga contiene solo 42 bits, con un iispaimio uel 2u% iispetto al couice a
lunghezza fissa pieceuente.
0na uelle uifficolt nell'uso ui couici a lunghezza vaiiabile sta nel ueciueie quanuo si
sono letti abbastanza u e 1 pei potei ueciueie ui avei iiconosciuto un simbolo. Il
couice Noise intiouuce un teizo simbolo (lo spazio) pei !+6()()+ le sequenze ui
punti e linee. 0n'altia soluzione consiste nel uisegnaie il couice in mouo che nessuna
couifica completa pei un simbolo sia un 6)+2"!!% uella couifica ui un altio (6)+2"3
'%4+!). Nell'esempio pieceuente A e couificato ua u e B ua 1uu; nessun altio simbolo
puo aveie una couifica che inizia pei u o pei 1uu.
In geneiale possiamo otteneie notevoli iispaimi ui spazio usanuo uei couici a
lunghezza vaiiabile che tengano piesente la fiequenza ielativa uei simboli nei
messaggi ua couificaie. 0no schema paiticolaie che ci peimette ui otteneie questo
iispaimio e la '%4"2"'( 4" 7-22#(, (ual nome uel suo inventoie). 0n couice ui
Buffman e un 6)+2"3 '%4+ che puo esseie iappiesentato ua un albeio binaiio le cui
foglie contengono i simboli ua couificaie. 0gni nouo inteino uell'albeio "contiene"
l'insieme ui tutti i simboli contenuti nei uue sottoalbeii. Inoltie, au ogni foglia e
assegnato un "peso" (funzione uella sua fiequenza ielativa) eu au ogni nouo inteino
la somma uei pesi sottostanti. I pesi non sono usati nelle opeiazioni ui couifica e
uecouifica; sono usati pei costiuiie l'albeio ui Buffman.
S8

La figuia qui sopia mostia un albeio ui Buffman pei il couice A-B mostiato in
pieceuenza. I pesi uelle foglie ci uicono che au A e stata assegnata una fiequenza
assoluta paii a 8, a B paii a S eu a tutti gli altii simboli paii au 1 (tali fiequenze sono
state iicavate ual messaggio ui esempio iipoitato a pagina 1).
Bato un albeio ui Buffman possiamo tiovaie la couifica ui ogni simbolo paitenuo
ualla iauice eu aiiivanuo alla foglia coiiisponuente al simbolo in questione. 0gni
volta che scenuiamo a !"#"!$%& aggiungiamo ' al couice eu ogni volta che scenuiamo
a ()!$%& aggiungiamo *. Pei ogni nouo inteino scegliamo la stiaua ua peicoiieie
contiollanuo a quale sottoinsieme associato alle iauici uei sottoalbeii appaitiene il
simbolo ua couificaie. Pei esempio, la couifica ui B e uestia (1), sinistia (u), uestia
(1), uestia (1): 1u11.
Pei uecouificaie un messaggio couificato (una sequenza ui bit), paitiamo ualla
iauice e seguiamo il peicoiso fino au una foglia a seconua uegli u (sinistia) eu 1
(uestia) che incontiiamo. Quanuo siamo aiiivati au una foglia, abbiamo uecouificato
un simbolo e possiamo iicominciaie ualla iauice pei uecouificaie il successivo. Au
esempio, consiueiiamo la sequenza 1uuu1u1u. Paitenuo ualla iauice anuiamo a
uestia poich il piimo bit e un 1; successivamente abbiamo uno u e quinui anuiamo
a sinistia; poi ancoia a sinistia, uove tioviamo una foglia. Abbiamo uecouificato B e
iipaitiamo ualla iauice con uno u; anuiamo a sinistia e tioviamo la foglia A.
Ripaitenuo ualla iauice con il iesto uel messaggio binaiio 1u1u, seguiamo il
peicoiso appiopiiato nell'albeio e ci iitioviamo alla letteia C. Il messaggio
uecouificato e BAC.
!"'2%13(")& +( .45&%( +( 01//#.)
Bato un alfabeto ui simboli con le loio fiequenze ielative, come costiuiamo il couice
"miglioie", ossia l'albeio ui Buffman che couifica un messaggio con il minoi numeio
ui bits.
48
L'algoiitmo e molto semplice. L'iuea e ui costiuiie l'albeio in manieia tale ua aveie i
simboli meno "fiequenti" il pi lontano possibile ualla iauice. L'algoiitmo mantiene
come stiuttuia uati un insieme ui noui. I passi uell'algoiitmo sono i seguenti.
1- All'inizio l'insieme ui noui contiene tutti i noui foglia uell'albeio. Questo
insieme viene costiuito cieanuo un nouo pei ogni simbolo uell'alfabeto,
simbolo con il quale il nouo viene etichettato. Au ogni nouo viene assegnato
un peso paii alla fiequenza, ielativa o assoluta, associata al simbolo che lo
etichetta.
2- A questo punto vengono scelte au aibitiio uue noui foglia nell'insieme con
peso minimo, e viene costiuito un nuovo nouo, inteino all'albeio, che ha le
uue foglie scelte come figli uestio e sinistio. Il nuovo nouo ha come peso la
somma uei pesi uei suoi uue figli e come etichetta l'insieme ui simboli
ottenuto uall'unione uei simboli uei suoi uue figli. Le uue foglie vengono
iimosse uall'insieme eu il nuovo nouo viene inseiito nello stesso.
S- Il piocesso si iipete iicoisivamente. Au ogni passo si iimuovono uall'insieme
uue noui ual peso minimo e viene aggiunto un nouo inteino allo stesso.
4- Il piocesso teimina quanuo l'insieme contiene un solo nouo (la iauice). Tale
nouo sai etichettato con tutto l'alfabeto, eu avi come peso la somma uelle
fiequenze ui tutti i simboli (1 nel caso ui fiequenze ielative).

Qui ui seguito s'illustia come l'albeio ui Buffman pieceuente e stato geneiato a
paitiie ualle infoimazioni ui fiequenza assoluta uelle letteie A-B iicavata ual
messaggio ui esempio iipoitato a pagina 1.
Foglie iniziali {(A 8) (B S) (C 1) (B 1) (E 1) (F 1) (u 1) (B 1)}
Fusione {(A 8) (B S) ({C B} 2) (E 1) (F 1) (u 1) (B 1)}
Fusione {(A 8) (B S) ({C B} 2) ({E F} 2) (u 1) (B 1)}
Fusione {(A 8) (B S) ({C B} 2) ({E F} 2) ({u B} 2)}
Fusione {(A 8) (B S) ({C B} 2) ({E F u B} 4)}
Fusione {(A 8) ({B C B} S) ({E F u B} 4)}
Fusione {(A 8) ({B C B E F u B} 9)}
Fusione finale {({A B C B E F u B} 17)}
8**+,0"%,+. L'algoiitmo e non ueteiministico, ossia puo piouuiie pi ui un albeio ui
Buffman. Questo puo avveniie poich non e uetto che au ogni passo ci siano
esattamente uue elementi ual peso minimo nell'insieme; inoltie la scelta ui quale
nouo figlio metteie a uestia e quale a sinistia al momento uella cieazione ui un nouo
pauie e aibitiaiia.
6$&%.3(")& +( +&,"+(/(,.
Come esempio u'implementazione ui una uelle opeiazioni fonuamentali uella
libieiia si piesenta la funzione Common Lisp decode. La funzione decode pienue
come aigomenti una lista ui u eu 1, eu un albeio ui Buffman.
S8
(defun decode (bits code-tree)
(labels ((decode-1 (bits current-branch)
(unless (null bits)
(let ((next-branch (choose-branch (first bits)
current-branch)))
(if (leaf-p next-branch)
(cons (leaf-symbol next-branch)
(decode-1 (rest bits) code-tree))
(decode-1 (rest bits) next-branch)))
))
)
(decode-1 bits code-tree)))

Le uniche funzioni che iichiuono una spiegazione sono choose-branch, leaf-p
e leaf-symbol. Le ultime uue uoviebbeio esseie auto-esplicanti, la piima e
implementata come segue.
(defun choose-branch (bit branch)
(cond ((= 0 bit) (node-left branch))
((= 1 bit) (node-right branch))
(t (error "Bad bit ~D." bit))))
o, pei i pi avventuiosi.
(defun choose-branch (bit branch)
(ecase (bit)
(0 (node-left branch))
(1 (node-right branch))))
Bati queste inuicazioni (e iifeiimenti) siete oia in giauo ui affiontaie
l'implementazione uelle funzioni e pieuicati che seiviianno a costiuiie la libieiia ui
couifica.
7%"8&22"
L'obiettivo uel piogetto e ui costiuiie uue libieiie (Common Lisp e Piolog) che
implementino le piimitive ui couifica e uecouifica oltie au alcune opeiazioni ui
utilit.
!"##") 9('$
Bovete implementaie le seguenti funzioni:
decode bits huffman-tree ! message
encode message huffman-tree ! bits
generate-huffman-tree symbols-n-weights ! huffman-tree
generate-symbol-bits-table huffman-tree ! symbol-bits-table
Nella specifica pieceuente abbiamo i seguenti vincoli
bits e una sequenza (lista) ui u eu 1;
message e una lista ui "simboli" (simboli Common Lisp o caiatteii);
68
huffman-tree e un albeio ui Buffman (la sua iauice);
symbols-n-weigths e una lista ui coppie simbolo-peso (N0N una a-list!);
symbol-bits-table e una lista ui coppie simbolo-bits.
Le funzioni uevono geneiaie uegli eiioii (con la funzione error) se couifica eo
uecouifica non sono possibili.
7%"4"8
Bovete implementaie i pieuicati seguenti:
decode/3 Bits HuffmanTree Message
encode/3 Message HuffmanTree Bits
generate_huffman_tree/2 SymbolsAndWeights HuffmanTree
generate_symbol_bits_table/2 HuffmanTree SymbolBitsTable
I vincoli sono gli stessi ui cui sopia (ovviamente iimouulati in Piolog). I pieuicati
uevono falliie se ci sono eiioii o se couifica eo uecouifica non possono esseie
completate.
:'&#$(
L'esempio fonuamentale ua tenei piesente (la specifica, seconuo una teiminologia
pi coiietta) e il seguente.
;) !"##"# 9('$<

cl-prompt> (defparameter ht
(generate-huffman-tree <symbols-n-weights>))
ht

cl-prompt> (defparameter message <some-message>)
message

cl-prompt> (equal message (decode (encode message ht) ht))
T
;) 7%"4"8<

?- assert(symbols_n_weights(<symbols-n-weights>)).
Yes.

?- assert(message(<some-message>)).
Yes.

?- symbol_n_weights(SWs),
| message(M),
| generate_huffman_tree(SWs, HT),
| encode(M, HT, Bits),
| decode(Bits, HT, M).
Yes.
78
=188&%(#&)2(
Come aviete potuto notaie non e stata specificata la stiuttuia uell'implementazione
ui un albeio ui Buffman.
0n pioblema che aviete sai nella gestione u'insiemi oiuinati ui elementi (foglie e
noui uell'albeio in costiuzione); uoviete implementaie una stiuttuia eo funzioni
che mantengano questi insieme oiuinati.
L'implementazione uelle vaiie funzioni e pieuicati e ielativamente semplice una
volta che si sfiutti l'oiuinamento uegli insiemi ui noui e foglie. Se vi tiovate a
sciiveie funzioni o pieuicati molto lunghi o complessi alloia siete piobabilmente
sulla stiaua sbagliata.
>"2&
0na iiceica in iete piopone moltissime vaiianti sul tema. Attenzione! Nessuno vi
vieta ui iiceicaie ispiiazione e illuminazione in Rete; peio e bene che pensiate
attentamente a quello che state implementanuo; anche peich i motoii ui iiceica
sono usabili ua tutti, anche (e sopiattutto) uai uocenti che vi valuteianno.
?. ,")'&8).%& @9:AA:B: CDD:>DCE:>D:F
Boviete consegnaie un file .zip (i files .tar o .rar #+# !+#+ &--)$$&."/"!!!) ual
nome
Cognome_Nome_Matricola_LLP_20130305.zip
Nome e Cognome uevono aveie solo la piima letteia maiuscola, Matricola ueve
aveie lo zeio iniziale se piesente.
Questo file ueve conteneie 0#& !+/& ("%)-$+%1 -+# /+ !$)!!+ #+2). Al suo inteino
ci uevono esseie uue sottouiiectoiy chiamate 'Prolog' (e 'Lisp' pei il piogetto
Lisp associato a questo). Al loio inteino queste uiiectoiies uevono conteneie i files
caiicabili e inteipietabili, pi tutte le istiuzioni che iiteiiete necessaiie. Il file
Common Lisp si ueve chiamaie 'huffman.lisp'. Il file Piolog si ueve chiamaie
'huffman.pl'. La caitella ueve conteneie un file chiamato README.txt. In altie
paiole questa e la stiuttuia uella uiiectoiy (foluei, caitella) una volta spacchettata.
Cognome_Nome_Matricola_LLP_20130305
Lisp
huffman.lisp
README.txt
Prolog
huffman.pl
README.txt
Potete anche aggiungeie altii files, ma il loio caiicamento uovi esseie eseguito
automaticamente al momento uel caiicamento ("loauing") uei files sopia citati.
Il teimine ultimo pei la consegna e il S Naizo 2u1S alle oie 2S:S9.
88
valgono le solite iegole pei lo svolgimento uei piogetti in giuppo. 0gni file ueve
conteneie - come piimo elemento - un commento con l'inuicazione ui tutti i membii
uel giuppo. Tutte le peisone uevono consegnaie inuiviuualmente.
B(/&%(#&)2(
|AS84j B. Abelson, u. }. Sussman, Stiuctuie anu Inteipietation of Computei
Piogiams, NIT Piess 1984 (http://mitpress.mit.edu/sicp).