Trasformata di Burrows-Wheeler
# Trasformata di Burrows-Wheeler

La trasformata di Burrows-Wheeler (abbreviata con BWT) è un algoritmo usato nei programmi di compressione dati come bzip2. È stata inventata da Michael Burrows e David Wheeler.

Quando una stringa di caratteri viene sottoposta alla BWT, nessuno di questi cambia di valore perché la trasformazione permuta soltanto l'ordine dei caratteri. Se la stringa originale contiene molte ripetizioni di certe sottostringhe, allora nella stringa trasformata troveremo diversi punti in cui lo stesso carattere si ripete tante volte. Ciò è utile per la compressione perché diventa facile comprimere una stringa in cui compaiono lunghe sequenze di caratteri tutti uguali.

Per esempio, la stringa:

verrebbe trasformata nella seguente:

## La trasformata

La trasformata è fatta ordinando tutte le rotazioni del testo e poi prendendo soltanto l'ultima colonna. Per esempio, il testo "^BANANA@" viene trasformato in "BNN^AA@A" attraverso questi passi (i caratteri rossi ^ e @ indicano rispettivamente il puntatore di inizio stringa, e quello di fine stringa o 'EOF'):

Trasformata :

| Input | Tutte le rotazioni | Linee in ordine lessicografico | Si prende l'ultima colonna | Output |
| - | - | - | - | - |
| ^BANANA@ | ^BANANA@ @^BANANA A@^BANAN NA@^BANA ANA@^BAN NANA@^BA ANANA@^B BANANA@^ | ANANA@^B ANA@^BAN A@^BANAN BANANA@^ NANA@^BA NA@^BANA ^BANANA@ @^BANANA | ANANA@^B ANA@^BAN A@^BANAN BANANA@^ NANA@^BA NA@^BANA ^BANANA@ @^BANANA | BNN^AA@A |

Il seguente pseudocodice mostra un metodo, inefficiente, per calcolare la BWT e la sua inversa. Assume che la stringa di input s contenga un carattere speciale 'EOF' che è sempre l'ultimo carattere e che non appare mai nel testo, e che quindi è ignorato durante l'ordinamento.

## La trasformata inversa

La cosa più interessante della BWT non è che questa genera un output più facilmente comprimibile dell'originale, anche perché ciò si potrebbe ottenere mettendo semplicemente in ordine alfabetico i caratteri, ma è la sua reversibilità: il documento originale si ricostruisce a partire dai soli caratteri dell'ultima colonna.

L'inversa può essere compresa in questo modo. Prendi la tabella finale dell'algoritmo BWT ed elimina tutto a parte l'ultima colonna. Data soltanto quest'informazione puoi facilmente ricostruire la prima colonna. L'ultima colonna ti dice quali sono tutti i caratteri del testo, basta metterli in ordine per ottenere la prima colonna. Adesso la prima e l'ultima colonna sono note e insieme ti danno tutte le coppie di caratteri successivi nel documento, dove le coppie danno, ciclicamente, sempre prima l'ultimo e poi il primo carattere della coppia nel documento originale. Ordinando la lista delle coppie ottieni la prima e la seconda colonna. Continuando in questo modo puoi ricostruire l'intera lista, quindi, la riga con il carattere 'EOF' alla fine è il testo originale. La trasformata inversa dell'esempio sopra viene fatta così:

Trasformata inversa :

| Input ||||
| - | - | - | - |
| BNN^AA@A ||||
| Aggiungi | Ordina | Aggiungi | Ordina |
| B N N ^ A A @ A | A A A B N N ^ @ | BA NA NA ^B AN AN @^ A@ | AN AN A@ BA NA NA ^B @^ |
| Aggiungi | Ordina | Aggiungi | Ordina |
| BAN NAN NA@ ^BA ANA ANA @^B A@^ | ANA ANA A@^ BAN NAN NA@ ^BA @^B | BANA NANA NA@^ ^BAN ANAN ANA@ @^BA A@^B | ANAN ANA@ A@^B BANA NANA NA@^ ^BAN @^BA |
| Aggiungi | Ordina | Aggiungi | Ordina |
| BANAN NANA@ NA@^B ^BANA ANANA ANA@^ @^BAN A@^BA | ANANA ANA@^ A@^BA BANAN NANA@ NA@^B ^BANA @^BAN | BANANA NANA@^ NA@^BA ^BANAN ANANA@ ANA@^B @^BANA A@^BAN | ANANA@ ANA@^B A@^BAN BANANA NANA@^ NA@^BA ^BANAN @^BANA |
| Aggiungi | Ordina | Aggiungi | Ordina |
| BANANA@ NANA@^B NA@^BAN ^BANANA ANANA@^ ANA@^BA @^BANAN A@^BANA | ANANA@^ ANA@^BA A@^BANA BANANA@ NANA@^B NA@^BAN ^BANANA @^BANAN | BANANA@^ NANA@^BA NA@^BANA ^BANANA@ ANANA@^B ANA@^BAN @^BANANA A@^BANAN | ANANA@^B ANA@^BAN A@^BANAN BANANA@^ NANA@^BA NA@^BANA ^BANANA@ @^BANANA |
| Output ||||
| ^BANANA@ ||||

Certe ottimizzazioni possono far sì che questi algoritmi vengano eseguiti in maniera più efficiente senza cambiare il risultato; non c'è nessuna necessità di tenere l'intera tabella in memoria, tanto meno su disco e non è necessario ripetere i continui ordinamenti dell'esempio. Ogni riga della tabella è rappresentata in memoria con un semplice puntatore al carattere d'inizio della stessa.

## Implementazione d'esempio

Nota: Scritta in C

implementazione in Perl:

