Programmazione Greedy I codici di Huffman

Documenti analoghi
Algoritmi Greedy. Tecniche Algoritmiche: tecnica greedy (o golosa) Un esempio

carattere a b c d e f cod. var

Algoritmi e Strutture Dati Laboratorio 15/12/2008. Daniele Loiacono

Algoritmi e strutture dati. Codici di Huffman

Definizioni. Soluzione ottima: migliore soluzione possibile Soluzione ottima localmente: soluzione ottima in un dominio contiguo. Il paradigma greedy

Esercitazione 4 Algoritmi greedy

Alberi ed Alberi Binari

Lunghezza media. Teorema Codice D-ario prefisso per v.c. X soddisfa. L H D (X). Uguaglianza vale sse D l i. = p i. . p.1/27

Compressione Dati. Teorema codifica sorgente: Entropia fornisce un limite sia inferiore che superiore al numero di bit per simbolo sorgente.. p.

Alberi binari e alberi binari di ricerca

Alberi e alberi binari I Un albero è un caso particolare di grafo

Def. La lunghezza media L(C) di un codice C per una v.c. Obiettivo: Codice ottimo rispetto alla lunghezza media. Lunghezza media di un codice

RISOLUZIONE IN LOGICA PROPOSIZIONALE. Giovanna D Agostino Dipartimento di Matemaica e Informatica, Università di Udine

PROVETTE D ESAME. Algoritmi e Strutture Dati

15 Informazione e Predizione

Espressioni aritmetiche

Progettazione di Algoritmi

ALGORITMI CORSO DI STUDIO IN INFORMATICA (laurea triennale) UNIVERSITÀ DEGLI STUDI DI CATANIA ANNO ACCADEMICO 2014/15

TRIE (albero digitale di ricerca)

Introduzione alla codifica entropica

Sommario della lezione

23/10/2016. gli alberi. alcune definizioni. un esempio. LABORATORIO DI PROGRAMMAZIONE 2 Corso di laurea in matematica.

Linguaggi di Programmazione Corso C. Parte n.3 Linguaggi Liberi da Contesto e Linguaggi Contestuali. Nicola Fanizzi

Esercizi su alberi binari

Note per la Lezione 4 Ugo Vaccaro

Suffix Trees. Docente: Nicolò Cesa-Bianchi versione 21 settembre 2017

Linguaggi e Grammatiche Liberi da Contesto

Heap e code di priorità

Appunti Senza Pretese di Programmazione II: Costruzione di un Albero Bilanciato

Università degli Studi di L Aquila Facoltà di Scienze M.F.N. Corso di Laurea in Informatica. Modulo di Laboratorio di Algoritmi e Strutture Dati

La codifica di sorgente

Dati e Algoritmi I (Pietracaprina) Esercizi sugli Alberi

Problemi di ordinamento

Algoritmi e Strutture Dati

Alberi binari (radicati e ordinati) della radice Il padre del nodo 5 e del nodo 3

Esercizi di Algoritmi e Strutture Dati

LE STRUTTURE DATI DINAMICHE: GLI ALBERI. Cosimo Laneve

Informatica Generale Homework di Recupero 2016

Esercizi Capitolo 10 - Code con priorità e insiemi disgiunti

Alberi. Alberi: definizioni. Alberi Binari. Esercizi su alberi binari: metodi ricorsivi. Struttura dati per alberi generici. ASD-L - Luca Tesei

Esercizi Capitolo 10 - Code con priorità e insiemi disgiunti

Alberi. Gli alberi sono una generalizzazione delle liste che consente di modellare delle strutture gerarchiche come questa: Largo. Fosco.

GLI ALBERI BINARI DI RICERCA. Cosimo Laneve

In questa lezione. Heapsort. ordinamento con complessità, nel caso peggiore, O(nlogn) [CLRS01] cap. 6 da pag. 106 a pag. 114

Codifica dell informazione

Appunti sui Codici di Reed Muller. Giovanni Barbarino

Algoritmi e Strutture Dati

Progettazione di Algoritmi

Algoritmi e Strutture Dati. HeapSort

Introduzione ai grafi

Algoritmi e Strutture Dati

Alberi. Gli alberi sono una generalizzazione delle liste che consente di modellare delle strutture gerarchiche come questa: Largo. Fosco.

Laboratorio di Python

Sui Linguaggi Regolari: Teorema di Kleene - Pumping Lemm

Un esempio: l ADT Dizionario (mutabile) Definizione. Alberi binari di ricerca (BST = binary search tree) search(chiave k) -> elem

Teoria dell informazione

METODI DELLA RICERCA OPERATIVA

Alberi di copertura. Mauro Passacantando. Dipartimento di Informatica Largo B. Pontecorvo 3, Pisa

La codifica digitale

Programmazione Funzionale

Generazione di una mesh rettangolare

Possibile applicazione

2.3 Cammini ottimi. E. Amaldi Fondamenti di R.O. Politecnico di Milano 1

Esercitazioni di Algoritmi e Strutture Dati

CODIFICA DI CARATTERI

Appunti lezione Capitolo 14 Greedy

Grammatiche. Grammatiche libere da contesto Grammatiche regolari Potenza delle grammatiche libere e regolari Struttura di frase: Alberi di derivazione

1 Esercizio - caso particolare di ottimalità

Esercitazione 3. Heapsort

Algoritmi e Strutture Dati

Algoritmi e Strutture Dati

Informatica di Base 1 Linea 1

Alberi di ricerca. Alberi binari di ricerca. F. Damiani - Alg. & Lab. 04/05 (da C. Demetrescu et al - McGraw-Hill)

Un ripasso di aritmetica: Conversione dalla base 10 alla base 2

ITLCC 2006/10/6 19:09 page 7 #3

heap heap heap? max- e min-heap concetti ed applicazioni heap = catasta condizione di heap non è una struttura ordinata

Algoritmi e Strutture Dati

2.2 Alberi di supporto di costo ottimo

Lezione 4 Ugo Vaccaro

Lezione 5. Giuditta Franco. 19 Febbraio 2008

Laboratorio di Algoritmi e Strutture Dati. Aniello Murano. people.na.infn.it/~murano/ Murano Aniello - Lab. di ASD Terza Lezione

Alberi binari di ricerca

Dizionari Liste invertite e Trie

Il tipo astratto coda con priorità: specifiche sintattiche e semantiche. Realizzazioni.

Pumping lemma per i linguaggi Context-free

2) Codici univocamente decifrabili e codici a prefisso.

Algoritmi di Ricerca

liste ogni nodo ha un successore, tranne l ultimo della lista che ne ha zero; alberi binari ogni nodo ha zero, uno oppure due figli

Codifica di Huffman e Lempel-Ziv-Welch A L B E R T O B E L U S S I A N N O A C C A D E M I C O /

Alberi. Strutture dati: Alberi. Alberi: Alcuni concetti. Alberi: definizione ricorsiva. Alberi: Una prima realizzazione. Alberi: prima Realizzazione

I Tipi di Dato Astratto

Algoritmi e Principi dell'informatica Seconda Prova in Itinere - 14 Febbraio 2014

Concetti fondamentali

P (F E) = P (E) P (F E) = = 25

Introduzione alla programmazione

Teoria della Calcolabilità!

Rappresentazione delle frazioni proprie Aritmetica in binario Barbara Masucci

Informazione e sua rappresentazione: codifica

Foglio Elettronico Lezione 1

Informazione binaria: - codici binari, notazione binaria/ottale/esadecimale -

Transcript:

Programmazione Greedy I codici di Huffman Codifica dell informazione La rappresentazione ordinaria dell informazione prevede l impiego di un numero costante di bit; per esempio ad ogni carattere del codice ASCII è associata univocamente una stringa binaria di 8 bit. Relazioni di questo tipo prendono il nome di codici a lunghezza fissa. Supponiamo di avere un alfabeto A={a, b, c, d,e}, per poterne fornire una rappresentazione tramite codice a lunghezza fissa dobbiamo impiegare almeno 3 bit: a d b e c Prendiamo in esame una semplice stringa formata dai simboli dell alfabeto A, ad esempio aaabcde. La codifica complessiva della stringa richiede 2 bit (3 bit per ogni carattere). Ammettendo di considerare altre informazioni si può operare secondo una strategia diversa. Se si conoscono a priori le frequenze con cui i caratteri occorrono all interno di un file, allora conviene adottare un codice a lunghezza variabile il cui scopo è quello di assegnare meno bit in corrispendenza dei caratteri più frequenti e aumentare progressivamente il dispendio della memoria con il diminuire della frequenza. Tornando all esempio precedente relativo all alfabeto A e alla stringa aaabcde, una possibile codifica progressiva sarebbe: a (carattere più frequente) b d c e Adesso la codifica della stringa comporterebbe un costo sensibilmente minore: aaabcde (costo complessivo di bit) La cosa sembrerebbe funzionare perfettamente (più del 5% di risparmio), ma bisogna considerare anche la possibilità di recuperare l informazione compressa. Con questa scelta la decodifica è diventata un operazione indecidibile, con risultati disastrosi sul significato originale dei dati. A tal proposito basti considerare i primi 4 bit della codifica proposta: aaab (esatto) cd (sbagliato) cab (sbagliato) acb (sbagliato)...... Per questo motivo un codice a lunghezza variabile che possa essere felicemente impiegato nella compressione dei dati deve essere un codice prefisso. In un codice prefisso nessuna stringa di codifica

può essere il prefisso di una qualunque altra stringa di codifica, e questo elimina ogni ambiguita in fase di decodifica. Codici prefissi e alberi binari Una rappresentazione comoda per un codice variabile prefisso è quella che fa uso degli alberi binari. Tutti i caratteri dell alfabeto a cui appartiene il codice sono disposti come foglie dell albero e, dopo aver etichettato ogni arco dell albero indicando con il percorso verso il sottoalbero sinistro e con il percorso verso il sottoalbero destro, la codifica di un simbolo risulta come la stringa che etichetta il cammino dalla radice alla foglia che contiene quel simbolo. Esaminiamo il codice a lunghezza variabile presentato in precedenza per l alfabeto A: A C D E B Il codice non è prefisso perchè i caratteri non etichettano solo foglie, ma anche nodi intermedi (come nel caso di a e b). Inoltre un codice prefisso ottimo induce una rappresentazione completa, nella quale ogni nodo interno ha esattamente 2 figli, quindi, se A è l alfabeto di caratteri a cui appartiene il codice, allora l albero di codifica avrà A foglie e A - nodi interni. A questo proposito esaminiamo l albero del codice a lunghezza fissa presentato in precedenza: L albero non è completo; infatti il codice a lunghezza fissa non e un codice ottimo A B C D E In generale si può notare che, se T è un albero per un codice su un alfabeto A, f(x) è la frequenza relativa ad ogni carattere x di A e liv(x) è la profondità di x all interno di T, allora possiamo definire il costo dell albero T come: C ( T ) = x A f ( x) liv( x)

Algoritmo di Huffman Gli studi di Huffman forniscono un metodo algoritmico in grado di generare un codice prefisso ottimo per un file in cui compaiano n caratteri. I caratteri fanno parte di un alfabeto A ( A = n) e per ogni a di A è definita la frequenza di a, f(a), come il numero di occorenze di a all interno del file. L algoritmo di Huffman riceve in input l alfabeto da codificare e il vettore con le frequenze di ciascun carattere e costruisce l albero di codifica ottimo: albero_di_huffman (A, f[]) { n = A ; heap = costruisci_heap(a); for (n- volte) { x = estrai_minimo(heap); y = estrai_minimo(heap); z = nuovo_nodo(); figlio_sinistro[z] = x; figlio_destro[z] = y; f[z] = f[x]+f[y]; inserisci(heap, z); } } La costruzione dell albero è iterativa, vengono selezionati ogni volta i due elementi con frequenza minore, x e y, per essere fusi in unico albero. Il procedimento di fusione rende x e y figli di un nuovo elemento z la cui caratteristica è di ereditare la frequenza somma delle frequenze dei due elementi fusi. Nell implementazione in pseudocodice presentata in questo contesto l algoritmo organizza i simboli dell alfabeto A in una coda con priorità, secondo valori crescenti della frequenza. La coda è realizzata tramite un heap minimo. La complessità dell algoritmo è così quantificabile con semplici osservazioni: () la costruzione di un heap ha un costo O(n); (2) le operazioni di inserimento ed estrazione che avvengono all interno del for contribuiscono con O(log(n)); (3) il for viene ripetuto n volte; in definitiva il costo totale è pari a O(n log(n)). Correttezza dell algoritmo Per snellire la dimostrazione facciamo due osservazioni preliminari di cui si fornirà la prova in un secondo tempo: Osservazione : Se A è un alfabeto e x, y sono i due simboli di A con frequenza minore, allora esiste un codice prefisso ottimo per A il cui albero T presenta x e y come fratelli. Osservazione 2: Se T è un albero ottimo per l alfabeto A e x, y sono due caratteri che appaiono in T come foglie di uno stesso nodo z, allora, se f(z)= f(x)+f(y), l albero T = T-{x,y} è ancora un albero ottimo per l alfabeto A = A-{x,y}+{z}.

La dimostrazione è condotta per induzione sul numero n di caratteri che compongono l alfabeto da codificare. Base: se n=2, indipendentemente dalle frequenze di ciascun carattere, l algoritmo di Huffman costruisce uno dei due unici possibili alberi prefissi ottimi. Induzione: in presenza di n+ caratteri l algoritmo individua due simboli x e y con minor frequenza. Per l oss. possiamo stabilire che x e y sono figli di uno stesso nodo z; a questo punto l algoritmo lavora su z, riducendo di un simbolo l alfabeto e portandosi al livello n, dove l albero di codifica T è ottimo per ipotesi induttiva. Dato che il procedimento etichetta f[z] con f[x]+f[y] allora per l oss.2 se T è ottimo allora è ottimo anche l albero di livello n+ da cui T proviene. Concludiamo con la dimostrazione delle due osservazioni. (dimostrazione oss.) Supponiamo di avere un alfabeto A e due caratteri x,y A che hanno la minor frequenza tra tutti i simboli di A. Forniamo una prova costruttiva a partire da un albero T ottimo per A, dove x e y non sono fratelli. Mostriamo come sia possibile costruire un albero T, ancora ottimo per A, ma dove x e y siano fratelli. Individuiamo all interno di T le due foglie sorelle a e b che si trovino al livello più basso. Adesso scambiamo a con x e b con y e mostriamo che l albero T ottenuto è ancora una albero ottimo. Il ragionamento sarà condotto sullo scambio di a con x, ma in maniera del tutto simmetrica può essere esteso anche al caso di b e y. Lo spostamento di a e x ha provocato una variazione nel costo dell albero T, in particolare: C(T )=C(T)-f(x)liv(x)+f(x)liv(a)-f(a)liv(a)+f(a)liv(x) C(T )=C(T)+f(x)[liv(a)-liv(x)]-f(a)[liv(a)-liv(x)] C(T )=C(T)+[liv(a)-liv(x)][f(x)-f(a)] Considerando che per come abbiamo scelto a e x risulta: liv(x) liv(a) e f(a) f(x) Allora possiamo concludere che la variazione di costo fra T e T è minore o uguale a zero, il che implica che T è ancora un albero ottimo. (dimostrazione oss.2) Siano dati due alberi T e T, il primo ottimo per un alfabeto A e il secondo definito come T =T-{x,y}, dove x e y sono le due foglie di un nodo z in T. Posto f(z)=f(x)+f(y) vogliamo dimostrare che T è ottimo per l alfabeto A-{x,y} {z}. Mettiamo in relazione il costo di T e quello di T : C(T)=C(T )-f(z)liv(z)+f(x)liv(x)+f(y)liv(y) () Se poniamo liv(z)=l e consideriamo che x e y si trovano alla stessa altezza e sono figlie di z, allora possiamo scrivere liv(x)=liv(y)=l+; inoltre se notiamo che f(z)=f(x)+f(y), la () diventa: C(T)=C(T )-l(f(x)+f(y))+(l+)(f(x)+f(y)) C(T)=C(T )+f(x)+f(y) (2)

Adesso supponiamo che esista un albero T per l alfabeto A-{x,y} {z} tale che C(T )<C(T )(*). L esistenza di T genera un assurdo, se infatti a T aggiungiamo x e y, otteniamo un albero T per A tale che: C(T )=C(T )+f(x)+f(y) (3) Considerando in sequenza la (3), la (*) e la (2): C(T ) = C(T )+f(x)+f(y) < C(T )+f(x)+f(y) = C(T) C(T )<C(T) (4) L espressione (4) è un assurdo perchè abbiamo considerato per ipotesi che T era un albero ottimo per A, l assurdo deriva dall aver supposto che T non fosse ottimo per A-{x,y} {z}. Fabio Venditti, 999