\newpage
\pagestyle{empty}
\topmargin 6in
\begin{latexonly}
\hfill\line(1,0){400}
\end{latexonly}
\section{AP\'ENDICE X: Compresores de fuentes}
\begin{latexonly}
\line(1,0){400}
\newpage
\end{latexonly}
\topmargin 0in

\pagestyle{fancy}
\hspace{0.5in}En un manual donde se buscan altos rendimientos quiz\'a no sea descabellado dedicar
un cap\'\i tulo entero a la compresi\'on de datos. Esto es ?`queremos eficiencia computacional? Luego tendremos que intentar
minimizar el tama\~{n}o de lo que nuestra computadora tenga que procesar, para que pueda terminar el 
trabajo en el menor tiempo posible y con menor probabilidad de errores.

Con {\em eficiencia computacional}, t\'ermino ampliamente utilizando en nuestros d\'\i as, quiero referirme 
al concepto de poder obtener una respuesta {\bf r\'apida}, {\bf fiable} y {\bf segura} de nuestro sistema, ya sea en el \'ambito de procesador, memoria
o red.

En unos a\~{n}os, los que vivimos, en los que la aparici\'on de formatos de audio/v\'\i deo/imagen comprimidos ha puesto en jaque
a las discogr\'aficas y organizaciones {\em preocupadas} por los derechos de autor, no puede obviarse la
necesidad de la inmensa mayor\'\i a de usuarios para poder obtener el
m\'aximo partido a las unidades de almacenaje de que disponen.

Todo esto quiz\'as vaya en detrimento de la calidad: por todos es conocida la inmensa {\bf cantidad}
de temas que podremos tostar en un disco compacto, en formato comprimido. La equivalencia a nuestra discoteca en formatos no comprimidos
puede darnos tranquilamente tama\~{n}os 15, 20, 50 veces superiores. Ahora la variable es la calidad que queramos
preservar en nuestra compresi\'on ({\em bitrate}).

?`Para qu\'e puede servirnos intentar comprender el funcionamiento de las aplicaciones de compresi\'on? B\'asicamente
nos haremos una idea de nuestras carencias en el campo matem\'atico,
pero a\'un as\'\i\ conseguiremos comprender algo 
mejor que ante un buen rendimiento siempre se esconden
complicados\footnote{esta complejidad no es siempre directamente proporcional a la eficiencia del proceso total.}
 m\'etodos para poder acceder m\'as r\'apidamente a un enorme conjunto
 de datos. Como en nuestro mundo, m\'as o menos real que el de
 nuestras computadoras, las b\'usquedas y dem\'as tratamientos de informaci\'on ser\'an tanto m\'as r\'apidas
cuanto menores sean los vol\'umenes a tratar.

Este documento no pretende ser un manual de usuario, as\'\i\ que para poder poner en pr\'actica los procesos
de compresi\'on el lector deber\'a dirigirse a los {\em man} propios del sistema operativo. Esta es una 
pr\'actica que no deberemos obviar puesto que esta documentaci\'on generalmente est\'a desarrollada por los propios autores, as\'\i\ que
?`qu\'e mejor forma de conocer todos los par\'ametros?

Volviendo pues a nuestro relato sobre algor\'\i tmica de compresi\'on de fuentes, quiz\'a sea ahora el momento
de aclarar una idea que puede habernos dejado con la duda, tras los p\'arrafos anteriores, sobre si comprimir
significa perder informaci\'on (o calidad, seg\'un la naturaleza de la fuente que se trate).\\
Evidentemente: !`NO! Perder informaci\'on muchas veces ser\'\i a imperdonable y terminar\'\i a por inutilizar
cualquier resto de los datos originales. Este es un aspecto que se ha cuidado mucho puesto que poder
{\em inflar} y {\em desinflar}\footnote{m\'as tarde el lector entender\'a mejor la utilizaci\'on de estos t\'erminos.}
los datos no tiene que traducirse nunca en una p\'erdida del fin que dar\'\i amos a los datos originales.
A estos algoritmos sin p\'erdidas se los conoce internacionalmente como {\em lossless} y podemos tomar
ejemplos del formato de imagen GIF o del de audio Monkey (este \'ultimo ya se empieza a instaurar en estudios profesionales de grabaci\'on).

?`Queda poco claro? Ve\'amoslo pues desde otra perspectiva, y volviendo a las nociones dadas al comienzo: ?`qu\'e nos interesa al
disparar un archivo multimedia? Evidentemente que se oiga, que se visualice o ambas cosas a la vez.
Si aplicamos una compresi\'on y no podemos gozar de sus funcionalidades primarias, desecharemos el fichero.
La compresi\'on pues deber\'a mantener la imagen sobre nuestra pantalla (y/o el audio) pero ?`necesariamente a la misma
calidad que la funte? A menudo los formatos de v\'\i deo poseen altas resoluciones, altas definiciones de color y 
lo mismo con el audio, de elevadas frecuencias de muestreo (en los estudios se trabaja a 96KHz/24bit cuando un CD
ha de grabarse a 44.1KHz/16bit). No necesitamos gozar de estas extremas calidades para reconocer nuestra m\'usica, es m\'as,
numerosos y serios estudiosos se dieron cuenta ya hace muchos a\~{n}os que el o\'\i do humano percibe el audio como un todo,
desechando notables cantidades de las componentes en frecuencia: tenemos en cuenta el total de frecuencias que lo componen, no
sus componentes por separado. Todos estos estudios han desarrollado la base algor\'\i tmica
para la mayor parte de compresores de audio, tarea especialmente fruct\'\i fera en los laboratorios \htmladdnormallink{Fraunhofer ISS-A}{http://www.iis.fraunhofer.de/}, en Alemania.

El mundo del v\'\i deo ya se inici\'o, con los hermanos Lumi\`ere, con una forma de compresi\'on:
los {\em frames} por segundo. El mundo en que vivimos no se mueve a 24 im\'agenes por segundo en Europa, y ni tan
siquiera a 30 en pa\'\i ses como Jap\'on o EUA. Capturar ciertas im\'agenes en el tiempo y reproducirlas sucesivamente
solo es una forma m\'as que el ingenio humano ha desarrollado para poder apoderarse del medio que lo envuelve para
poder disponer de \'el a su conveniencia. El autoenga\~{n}o parece pertenecer a nuestra naturaleza.

De todas formas cada frame a veces contiene demasiada informaci\'on, o almenos demasiada informaci\'on NO necesaria para poder reconocer el film.
La cantidad de informaci\'on que se deseche, como hemos indicado, la decidiremos nosotros a partir
del ratio de compresi\'on que nos interese. Aqu\'\i\ pues presentamos el concepto de {\bf bitrate}: la cantidad de informaci\'on
por segundo que queremos mantener del fichero original. Qu\'e informaci\'on en concreto ser\'a mantenida es algo
que decide el algoritmo del compresor.

El concepto atemporal de bitrate es lo que llamamos {\bf ratio de compresi\'on}. Tomar no toda la informaci\'on 
reducir\'a el tama\~{n}o as\'\i\ que el ratio es la relaci\'on entre el tama\~{n}o original y el que nos da la compresi\'on.
Puede darse en porcentajes o en decimal, esto no es importante.

Para los ficheros de datos (binarios, de texto,...) utilizaremos el concepto de ratio, el bitrate solo tiene
sentido para los ficheros que deben reproducirse en el tiempo, por definici\'on.

Otro t\'ermino de gran importancia en el campo de la Teor\'\i a de la Informaci\'on es la {\bf entrop\'\i a}, que es la magnitud que mide la informaci\'on contenida en un flujo 
de datos, es decir, lo que nos aporta sobre un dato o hecho concreto. Estamos comprimiendo datos e intentando que ocupen el menor
tama\~{n}o posible, no obstante este procedimiento no puede extrapolarse hasta el l\'\i mite (?`un bit?) puesto que no nos ser\'\i a 
posible recuperar la informaci\'on original. Todo ello est\'a
perfectamente documentado y definido matem\'aticamente
\htmladdnormallink{en la Parte II de los apuntes}{http://alumnes.eup.udl.es/~b4767512/tic_compressors/entropia.ps}
de la asignatura de TIC\footnote{\htmladdnormallink{Teor\'\i a de la Informaci\'on}{http://enciclopedia.us.es/wiki.phtml?title=Teor\%EDa+de+la+informaci\%F3n} y la Codificaci\'on.} que este a\~{n}o 2002-03 he cursado en la Escuela Universitaria Polit\'ecnica de Lleida.

Llegados a este punto el lector podr\'a comprender todo el significado de {\bf compresi\'on de fuentes: operaciones que se realizan sobre la informaci\'on de una fuente con el objetivo de eliminar la redundancia de informaci\'on}.
\vspace{0.5in}

\hspace{0.5in}El presente cap\'\i tulo lo dedico a personajes como \htmladdnormallink{Jean-loup Gailly}{http://gailly.net/}
y a \htmladdnormallink{Mark Adler}{http://www.alumni.caltech.edu/~madler/}, desarrolladores de las
herramientas de compresi\'on {\em gzip} e {\em zlib} y a los que admiro enormemente por
sus interesantes trabajos en campos como la astrof\'\i sica, astronom\'\i a, seguridad
de sistemas (inform\'aticos), tratamiento de im\'agenes fractales y, evidentemente, de compresi\'on de fuentes.

Tambi\'en desde aqu\'\i\ aprovecho para felicitar a \htmladdnormallink{Julian Seward}{http://sources.redhat.com/bzip2/} por su trabajo con el compresor {\em bzip2}, mi preferido. 

Para terminar con las dedicatorias me he reservado el nombre quiz\'as
m\'as relevante de esta disciplina cient\'\i fica: \htmladdnormallink{Claude E.Shannon}{http://enciclopedia.us.es/wiki.phtml?title=Claude+E.+Shannon},
padre de la ciencia de la Teor\'\i a de la Informaci\'on tras su art\'\i culo publicado en el {\em Bell System Technical Journal} en 1948, titulado {\em Una teor\'\i a matem\'atica de la comunicaci\'on}.

Sin olvidarnos de la gran masa de estudiosos que m\'as o menos an\'onimamente aportan ideas sobre nuevas
tecnolog\'\i as (la base del gzip data del 1977) y estrategias para generar nuevos procedimientos de compresi\'on. Entre ellos
destaco a mi actual profesor de \htmladdnormallink{TIC}{http://alumnes.eup.udl.es/~tic/} , \htmladdnormallink{Ramiro Moreno Chiral}{http://www.criptored.upm.es/miembros/miembro_046.htm}, dedicado a tiempo completo a la encriptaci\'on 
con curvas el\'\i pticas e hiperel\'\i pticas.
\vspace{0.5in}

\hspace{0.5in}En este ap\'endice el lector podr\'a conocer los
principales compresores. Asimismo se dar\'an algunas nociones de algor\'\i tmica para 
comprender que tras las reducciones de tama\~{n}o no se esconden m\'as
que m\'etodos matem\'aticos, a veces algo complicados.

Evidentemente pueden ampliarse horizontes en este tema, aunque al no ser el prop\'osito de
este documento se deja en numerosos enlaces y las referencias correspondientes.

\subsection*{Algoritmo de Huffman}
\hspace{0.5in}Cerca de los a\~{n}os 50s el Profesor Huffman decidi\'o ingeniar un algoritmo que calculara la manera
m\'as eficiente para representar datos, minimizando la cantidad de memoria requerida para almacenar esta informaci\'on.
Es una idea simple pero sin una soluci\'on trivial.

Las ideas que lograron desarrollar la estrategia de resoluci\'on para este problema esconden aspectos de la vida pr\'actica.
No obstante, y para no perder al lector, recordamos ciertos aspectos pr\'acticos (valga la redundancia) sobre c\'omo tratan la informaci\'on nuestras
computadoras, a\'un de silicio.

Por todos es conocido que la unidad m\'\i nima de informaci\'on es el bit, que puede adoptar dos valores, represantados
generalmente en l\'ogica binaria por {\tt 1} y {\tt 0}. Los caracteres de texto se codificaban con bytes (y a\'un se hace), que no son m\'as que sucesiones de 8 bits (codificaci\'on ASCII).
Estos 8 bits permiten 256 combinaciones as\'\i\ que podemos codificar 256 caracteres. La idea pues surgi\'o al percatarse que no todos 
aparecen con la misma frecuencia, algo subordinado al idioma, evidentemente.

Se pens\'o que las vocales, por ejemplo, aparecen un mayor n\'umero de veces que letras como la 'j' o la 'z'. No obstante no podemos
olvidarnos de nunguna codificaci\'on puesto que nadie nos asegura que no van a aparecer. Pero si hici\'eramos que la 'e' se codificara
con 7 bits y la 'j' o la 'z' con 9 bits podr\'\i amos obtener un texto final m\'as corto. En este principio de probabilidad se basa precisamente
el c\'odigo Morse, donde la 'e' se codifica con el s\'\i mbolo m\'as corto '.' y la 'q' con el m\'as largo '\_ \_ . \_'.

As\'\i\ pues este algoritmo trata de encontrar las probabilidades para todos los caracteres, y codificar en funci\'on de ellas.
Cada idioma tiene las suyas y aunque para el ingl\'es ya se han hecho numerosos estudios tomando ingentes cantidades de documentos, para el
castellano a\'un no los existen con suficiente madurez.

Pero hemos acertado si pensamos que una retah\'\i la de bits ser\'a no decodificable si aplic\'asemos el anterior razonamiento, puesto
que si no tomamos una longitud igual para todos los caracteres no sabremos cuando termina uno y empieza el otro. Para solucionar este
aspecto se pens\'o en construir {\bf \'arboles binarios}.

Para dar una idea gr\'afica de lo que representa esta soluci\'on tan {\em natural} podemos imaginaros un m\'ovil.
No tanto en forma de tel\'efono celular sino en algo que Alexander Calder, un artista americano, sabe contruir muy bien.
Como podemos ver en la foto, Alexander construye m\'oviles preferentemente con colores rojos y negros, aqu\'\i\ se incluye uno de sus
trabajos de m\'as envergadura (se encuentra en la {\em American National Gallery}). Nos interesa ver que estas estructuras penden de un punto
situado en la mitad de una asta, su balanceo est\'a calculado en funci\'on del aire de la sala. De cada asta cuelgan dos elementos:
otra asta y un peso. En las astas inferiores siempre encontramos pesos. La programaci\'on de un \'arbol de Huffman es id\'entica a
la estructura de un m\'ovil, solo que nos servir\'a para almacenar datos. La terminaci\'on de un asta se representar\'a con un {\tt 0}
o un {\tt 1} y los pesos con caracteres. Deberemos recorrer el \'arbol
y encontrando los terminales de astas ({\tt 0}'s y {\tt 1}'s) iremos
conociendo la codificaci\'on de cada car\'acter.

\begin{latexonly}
\ifpdf
        \begin{figure}[htbp]
        \includegraphics[bb = 10 200 0 0, scale=1]{./pics/movil_huffman.png}
        \vspace{2.7in}
        \caption{openMosixview: Aplicaci\'on principal}
        \end{figure}
\else
\end{latexonly}
        \begin{figure}
        \centering
        \includegraphics{pics/movil_huffman}
        \caption{Compresi\'on de fuentes: S\'\i mil del \'arbol de Huffman}
        \end{figure}

\begin{latexonly}
\fi
\end{latexonly}

Para construir un \'arbol perfectamente balanceado tendremos que echar
mano al procedimiento previo a la generaci\'on de los \'arboles: como se
ha indicado anteriormente deberemos conocer las frecuencias de aparici\'on de cada car\'acter. El peso de cada asta (el car\'acter)
ser\'a proporcional a su frecuencia de aparici\'on.

Como todos los algoritmos que valen la pena, el de Huffman tambi\'en han pasado por diferentes revisiones y versiones. La m\'as destacada 
quiz\'as sea la que se conoce como {\em Algoritmo adaptativo de Huffman} que tiene en cuenta una reordenaci\'on de los caracteres
en el s\'\i\ de esta estructura. ?`Por qu\'e?
Puede darse que en un documento empecemos con una masiva aparici\'on de ciertos caracteres que luego no
aparezcan m\'as. Esto obviamente degenerar\'\i a el \'arbol y con esta {\em adaptavilidad} se consigue un reflejo m\'as fiel
de lo que son las frecuencias de aparcici\'on en todo el documento.

Tenemos interesante documentaci\'on al respecto, destacando:
\begin{itemize}
        \item \htmladdnormallink{{\em Codificaci\'on Huffman Din\'amico}}{http://alumnes.eup.udl.es/~b4767512/tic_compressors/huffAdapt_oscar.ps} de Oscar Nu\~{n}o.

        \item \htmladdnormallink{{\em Introducci\'on a los c\'odigos de huffman}}{http://alumnes.eup.udl.es/~b4767512/tic_compressors/huffman_cah.ps} del seminario de matem\'aticas de la facultad de Lleida.

        \item \htmladdnormallink{{\em Transparencias sobre Teor\'\i a de la Informaci\'on}}{http://alumnes.eup.udl.es/~b4767512/tic_compressors/huffman_transpas.ps} del Ramiro Moreno proponen una visi\'on amena de los conceptos expuestos.
        
        \item \htmladdnormallink{{\em C\'odigos de Huffman}}{http://alumnes.eup.udl.es/~b4767512/tic_compressors/huffman_fuentes.ps} del Ramiro Moreno nos detalla el aspecto matem\'atico del tema.
\end{itemize}

En los documentos a los que haremos referencia podremos observar el procedimiento de construcci\'on de estas estructuras.
\vspace{0.5in}

\hspace{0.5in}A continuaci\'on detallaremos los algoritmos de los
compresores m\'as utilizados {\em\bf gzip}, el LZ77, y {\em\bf bzip2},
la transformada de Burrows-Wheeler. La p\'agina oficial del primer compresor es \htmladdnormallink{{\tt http://www.gzip.org/}}{http://www.gzip.org/}.
El texto que aqu\'\i\ se incluye pertenece b\'asicamente a las ideas que los propios
autores del compresor han escrito en \htmladdnormallink{{\tt http://www.gzip.org/algorithm.txt}}{http://www.gzip.org/algorithm.txt}
para dar las nociones generales sobre el funcionamiento del mismo.

Sus desarrolladores, Adler y Gailly, han implementado tambi\'en una librer\'\i a de prop\'osito general para
comprimir datos, llamada {\em zlib}. Su p\'agina, especificaciones y fuentes est\'an referenciados
en este mismo documento, en las Referencias.
%----------------------------------------------------------
\subsection*{Algoritmo de compresi\'on de {\em gzip}: funci\'on {\tt deflate()}}
\hspace{0.5in}El algoritmo de compresi\'on usado en {\em gzip} (y tambi\'en en {\em zip} y {\em zlib})
es una variaci\'on del LZ77 (Lempel-Ziv 1977). \'Este busca cadenas
(entendi\'endose como tal una secuencia de bytes)
repetidas en los datos de entrada. La segunda ocurrencia de una cadena
se reemplaza por un puntero a la cadena previamente marcada como
patr\'on, en forma de par de datos: distancia y longitud. Las
distancias entre cadenas y sus respectivos punteros estan limitadas a
32K bytes, y las longitudes a 258 bytes. Cuando una cadena no se
repite en ning\'un otro sitio durante los 32K anteriores donde
podr\'ia apuntarse, se emite una cadena de {\em bytes literales} que se corresponden
 con los datos de entrada.

A su vez los literales y las longitudes se comprimen con un \'arbol de Huffman
y las distancias con otro tipo de \'arbol. Estos \'arboles de
compresi\'on se guardan de forma compacta al principio de cada
bloque. Los bloques pueden tener cualquier tama\~{n}o (excepto en los
casos en que los datos comprimidos deban permanecer en memoria). Un
bloque es terminado cuando la funci\'on {\tt deflate()} determina que
ser\'a m\'as \'util empezar con uno nuevo para renovar los \'arboles.

Las cadenas duplicadas se encuentran en una tabla de hash. Todas las
entradas de longitud 3 se insertan en esta tabla. Para los siguiente 3 bytes se utilizan \'\i ndices hash.
Si la sucesi\'on de
hash para este \'\i ndice no est\'a vac\'\i o, todas las cadenas de la
sucesi\'on ser\'an comparadas con la cadena actual, y se
seleccionar\'a la de mayor longitud.

Las sucesiones de hash (retah\'\i la de punteros a cadenas de bytes) se buscan empezando con la cadena (de bytes) m\'as
reciente, a favor de las distancias cortas, hecho que trae ventajas para
la codificaci\'on Huffman. La sucesi\'on hash est\'a enlazada con
enlace simple (es decir, s\'olo en una direcci\'on). No hay eliminaciones en las sucesiones hash, el
algoritmo simplemente descarta coincidencias demasiado antiguas.

Para conseguir el peor caso posible deber\'\i amos suponer que tenemos 
sucesiones hash muy largas, truncadas arbitrariamente y en una cierta
longitud, determinada por una opci\'on del algoritmo (par\'ametro
{\tt level} en {\tt deflateInit}). Esta situaci\'on puede producirse
debido a que {\tt deflate()} no
siempre encuentra la coincidencia m\'as larga, aunque generalmente
encuentra una coincidencia con longitud suficiente.

deflate() tambi\'en diferencia la selecci\'on de coincidencias
con un mecanismo de evaluaci\'on. Tras encontrar una coincidencia de
longitud N, deflate() buscar\'a una coincidencia de mayor longitud en
el siguiente byte de entrada, ya que cuanto mayor sea la longitud de la cadena duplicada mayor ser\'a el ratio de compresi\'on que podr\'a obtenerse.
Si se encuentra una coincidencia m\'as larga, la anterior se modifica a una logitud de 1 (como si fuera un
byte literal simple) y el mecanismo de evaluaci\'on empieza de
nuevo. De otra forma la coincidencia original se mantiene y la
siguiente b\'usqueda (de coincidencias) se limita a N pasos siguientes.

El mecanismo de evaluaci\'on est\'a sujeto a un par\'ametro de la
rutina. Si la actual coincidencia es suficientemente larga, deflate()
reducir\'a la b\'usqueda de una coincidencia m\'as larga, acelerando
el total del proceso. Si el ratio de compresi\'on es m\'as importante
que la velocidad, deflate() completar\'a una segunda b\'usqueda
uniforma si la primera coincidencia es suficientemente larga\footnote{buscar 2 veces evidentemente retrasar\'a el proceso, pero como hemos se\~{n}alado ahora lo importante ser\'\i a el ratio.}.

El mecanismo de evaluaci\'on no est\'a pensado para los modos de mayor
compresi\'on (par\'ametro a {\tt level} de 1 a 3). Para estos modos de
compresi\'on r\'apida, las nuevas cadenas se insertan en la tabla hash
s\'olo cuando no hay coincidencia, o cuando la coincidencia no es lo
bastante larga. Esto degrada el ratio de compresi\'on pero ahorra
tiempo puesto que pueden producirse cortas inserciones en peque\~{n}as b\'usquedas.
%----------------------------------------------------------
\subsection*{Algoritmo de decompresi\'on de {\em gzip}: funci\'on {\tt inflate()}}
\subsubsection*{Introducci\'on}
\hspace{0.5in}La pregunta es, dado un \'arbol de Huffman, ?`c\'omo
decodificarlo lo m\'as r\'apido posible? Un aspecto importante
es que los c\'odigos cortos son m\'as comunes que los
largos, pero hay que poner atenci\'on para decodificar r\'apidamente
los cortos y dejar los largos para luego, ya que
necesitar\'an mayores tiempos de decodificaci\'on.

{\tt inflate()} configura un primer nivel de tabla que cubre un menor
n\'umero de bits de la entrada que la longitud del c\'odigo m\'as
largo. Obtiene algunos bits del flujo y actualiza la tabla. En la tabla
podremos ver si el siguiente c\'odigo es mayor o menos en tama\~{n}o (y cu\'anto),
si se da el caso de ser menor que el anterior nos dar\'a el valor, en caso contrario
apuntar\'a al siguiente nivel de la tabla para el cual la funci\'on inflate()
coger\'a m\'as bits e intentar\'a decodificar un c\'odigo m\'as largo.

El n\'umero de bits que se tratar\'an en la primera pasada es una estimaci\'on
de eficiencia entre el tiempo que se cree que tardar\'a a decodificar y el tiempo
para construir la tabla. Si la construcci\'on de la tabla no ocupa
mucho tiempo (y teniendo memoria {\em infinita}) se tendr\'\i a un solo
nivel en la tabla para cubrir todas las v\'\i as del c\'odigo de mayor tama\~{n}o.

inflate() env\'\i a \'arboles regularmente; no obstante es posible configurar, para un primer nivel
de tabla m\'as peque\~{n}o, que una aplicaci\'on tenga s\'olo un \'arbol para todos
los datos. Para inflate(), que tiene 286 posibles c\'odigos para el \'arbol de longitudes o literales,
el tama\~{n}o de la primera tabla es de nueve bits. Adem\'as la distancia entre
\'arboles tiene 30 posibles valores, y el tama\~{n}o de la primera tabla es de seis bits.
Ha de notarse que para cada uno de los casos, la tabla termina con un bit m\'as que
la longitud media de un c\'odigo, en el caso de estudio pertinente. 
Esto es, la longitud del c\'odigo corto puede llegar a ser un poco mayor de 8 bits
para 286 s\'\i mbolos y un poco menor de 5 bits para 30 s\'\i mbolos.
Esto puede ser interesante para ver si optimizando el primer nivel de tabla para otras
aplicaciones nos da unos valores dentro de un bit o dos en el c\'odigo
de menor tama\~{n}o.

\subsubsection*{M\'as detalles en las operaciones de b\'usqueda de tabla inflate}
\hspace{0.5in}Ahora queremos saber si este ama\~{n}ado y oscuro \'arbol
inflate() se comporta correctamente. Estamos en lo correcto si pensamos que no es un
\'arbol de Huffman. Una tabla de b\'usqueda para el primero es simple, o sea, nueve bits de un s\'\i mbolo
de Huffman. El s\'\i mbolo puede ser tan corto como un bit o tan largo como 15. Si un s\'\i mbolo
en particular es m\'as corto de nueve bits, luego la traducci\'on de este s\'\i mbolo es duplicada
en todas las entradas que empiecen con estos bits de s\'\i m bolo.
Pongamos un ejemplo, si el s\'\i mbolo es de cuatro bits luego es duplicado 32 (4x9) veces
en una tabla de nueve bits. Si el s\'\i mbolo es de longitud nueve solo aparecer\'a una vez.

Si el s\'\i mbolo es mayor de nueve bits esta entrada en la tabla apuntar\'a a otra
tabla similar para los bits sobrantes. De nuevo, la duplicaci\'on de entrada es necesaria.
La idea es que la mayor parte del tiempo el s\'\i mbolo sea
corto y que s\'olo sea referenciado en una tabla. Esta es la idea de trasfondo para
una primera compresi\'on de los datos. Para los s\'\i mbolos largos con menor frecuencia
de aparcici\'on nos serviremos de dos b\'usquedas. Si tenemos un m\'etodo de compresi\'on con
s\'\i mbolos realmente largos ser\'\i a aconsejable servirnos de varios niveles de b\'usquedas.
Para inflate(), con 2 niveles es suficiente.

Queda claro pues que una entrada cualquiera de la tabla puede apuntar a otra tabla (en el caso de nueve bits en el anterior caso,
por ejemplo) o contener la traducci\'on del s\'\i mbolo y el n\'umero de bits a tratar. Luego 
empezaremos con el siguiente bit a tratar.

?`Por qu\'e no s\'olo  hacemos una tabla de b\'usquedas para cuantos bits tenga el s\'\i mbolo m\'as largo?
La raz\'on es que si hici\'eramos esto terminar\'\i amos utilizando m\'as tiempo rellenando
con entradas de s\'\i mbolos duplicados que en la decodificaci\'on.
Almenos para la salida de deflate() que genera nuevos \'arboles distintos cada 10Kbytes.

Podemos imaginar que rellenando en una entrada de tabla de $2^{15}$ para un c\'odigo de 15 bits puede
ser demasiado largo si s\'olo decodificamos algunos centenares de s'\i mbolos diferentes.
En el otro extremo podemos hacer nuevas tablas para cada bit en el c\'odigo.
De hecho, esto es esencialmente un \'arbol de Huffman. pero utiliza demasiado tiempo
al recorrer el \'arbol mientras decodificamos, a\'un con s\'\i mbolos cortos.

El n\'umero de bits para la primera tabla de b\'usqueda es una negociaci\'on entre el tiempo a 
llenar la tabla y el tiempo gastado buscando el segundo nivel (y siguientes) en la tabla.

Esto puede ser un ejemplo.

{\em El c\'odigo que ser\'a decodificado con 10 s\'\i mbolos de 1 a 6 bits de longitud:}

A: 0\\
B: 10\\
C: 1100\\
D: 11010\\
E: 11011\\
F: 11100\\
G: 11101\\
H: 11110\\
I: 111110\\
J: 111111\\

{\em La primera tabla ser\'a de 3 bits de longitud ($2^{3}$=8 entradas):}

000: A,1\\
001: A,1\\
010: A,1\\
011: A,1\\
100: B,2\\
101: B,2\\
110: -$>$ table X (trata 3 bits)\\
111: -$>$ table Y (trata 3 bits)\\

Cada entrada es consecuente con los bits a decodificar y al n\'umero de ellos, i.e.
la cantidad de bits a tratar. O tambi\'en puede darse que los puntos de entrada 
referenc\'\i en a otra tabla con el n\'umero de bits a tratar impl\'\i citos en el tama\~{n}o
de la tabla.

Refiri\'endonos al caso anterior, la tabla X tiene 2 bits de longitud ya que el 
c\'odigo m\'as largo empieza con 110 tiene cinco bits de longitud:

00: C,1\\
01: C,1\\
10: D,2\\
11: E,2\\

La tabla Y tiene 3 bits de longitud puesto que el c\'odigo mayor empieza
con 111 tiene seis bits de longitud.

000: F,2\\
001: F,2\\
010: G,2\\
011: G,2\\
100: H,2\\
101: H,2\\
110: I,3\\
111: J,3\\

\hspace{0.5in}As\'\i\ pues lo que tenemos aqu\'\i\ son 3 tablas con un total de 20 entradas que
tienen que ser constru\'\i das. Esto puede ser comparado con las 64 entradas para una 
sola tabla. O comparado con las 16 entradas para un \'arbol de Huffman (seis entradas de tabla de 2 y una de 4)
da una media de 1.25 b\'usquedas por s\'\i mbolo. Esto puede ser comparado con una b\'usqueda por la tabla simple, o 1.66
b\'usquedas por s\'\i mbolo para el \'arbol de Huffman.

El formato de los ficheros comprimidos {\em gzip} est\'a especificado en las RF (Request For Comments) 1951 y 1952.
Sus enlaces est\'an en las Referencias, m\'as abajo.
%---------------
\subsection*{Paralelizaci\'on del algoritmo LZ77}
\hspace{0.5in}Ya hemos visto la variaci\'on del algoritmo LZ77 que utiliza {\em gzip} para codificar y decodificar fuentes.
Hemos aprendido que todo el procedimiento puede comprenderse si se entienden tanto el LZ77 como las estructuras
de \'arbol de Huffman. No obstante, y debido a la naturaleza de este manual, podr\'\i amos hacernos la pregunta
de si es posible paralelizar este algoritmo para obtener mayor eficiencia en sistemas paralelos, como los clusters.

Y como no, la respuesta vuelve a ser afirmativa. El principio de paralelizaci\'on se basa en comprender bien la estructura de un
fichero comprimido, con extensi\'on {\bf .gz}. Estos archivos estan formados por multibloques (ya vistos). Esta estructura
permitir\'\i a concatenar varios archivos {\em gzipados}, el resultado de la decodificaci\'on ser\'\i a un fichero mayor
que ambos que los contendr\'\i a a los dos. Consecuentemente la idea b\'asica para la paralelizaci\'on de este algoritmo es:
\begin{itemize}
        \item cortar el fichero original en varias partes
        \item aplicar el LZ77 a cada parte, cada una en un procesador diferente
        \item concatenar los resultados de cada parte
\end{itemize}

Podemos verlo m\'as claramente en la siguiente figura.
\begin{latexonly}
\ifpdf
        \begin{figure}[htbp]
        \includegraphics[bb = -75 160 0 0, scale=1]{./pics/pgzip_scheme.png}
        \vspace{2in}
        \caption{Compresi\'on de fuentes: Paralelizaci\'on de {\em gzip}}
        \end{figure}
\else
\end{latexonly}
        \begin{figure}
        \centering
        \includegraphics{pics/pgzip_scheme}
        \caption{Compresi\'on de fuentes: Paralelizaci\'on de {\em gzip}}
        \end{figure}

\begin{latexonly}
\fi
\end{latexonly}

Ahora el par\'ametro m\'as importante del algoritmo ser\'a el tama\~{n}o del corte, que no puede ser ni muy grande ni muy peque\~{n}o.
Generalmente se coge un valor mayor que el n\'umero de procesadores de que disponemos.

Ser\'\i a interesante conocer el n\'umero (N) que diera el n\'umero de hilos ({\em threads}) que podremos ejecutar de forma
paralela. Si tuvieramos esta informaci\'on conseguir\'\i amos la mayor eficiencia del algoritmo, puesto que pasar\'\i amos
el mismo n\'umero como cantidad de partes a dividir el fichero y consecuentemente la ejecuci\'on terminar\'\i a antes.
Pero normalmente no conocemos este par\'ametro del sistema y cortar un fichero que ya de por s\'\i\ acaree altos costes
computacionales podr\'\i a traducirse en una mayor coste en el tiempo. Algo que evidentemente no perseguimos.

Hay estudios hechos sobre la influencia del tama\~{n}o del corte en relaci\'on con la duraci\'on computacional del proceso.
Un grupo de investigaci\'on franc\'es que dedic\'o sus esfuerzos a analizar estas modificaciones en el algoritmo, all\'a por el a\~{n}o 1999.
Llegaron a interesantes resultados que podemos consultar en su web, apuntada en las Referencias.

Podemos ver algunas figuras comparativas donde se ejecut\'o el
algoritmo en computadoras SMP con 2 y 4 procesadores.

\begin{latexonly}
\ifpdf
\else
\hspace{0.5in}Tambi\'en se hicieron pruebas con diferentes tama\~{n}os de bloque,
tomando valores de 2, 4, 8 y 22 MB. Podemos ver los diferentes resultados:
%\end{latexonly}
% Imagen para el documento PS sobre diferntes tamaņos de bloque
        \begin{figure}
        \centering
        \scalebox{0.5}[.3]{\includegraphics{./pics/pgzip_graph4MB}}
        \scalebox{0.5}[.3]{\includegraphics{./pics/pgzip_graph22MB}}
        \caption{Compresi\'on de fuentes: Eficiencias seg\'un el
        tama\~{n}o del corte en {\em gzip} paralelo}
        \end{figure}
%\begin{latexonly}
\fi
\end{latexonly}

%imagen para el HTML
\begin{htmlonly}
\ifpdf
        \begin{figure}[htbp]
        \includegraphics[bb = 10 170 0 0, scale=1]{./pics/pgzip_graph_allMB.png}
        \vspace{2.5in}
        \caption{Compresi\'on de fuentes: Eficiencias seg\'un el
        tama\~{n}o del corte en {\em gzip} paralelo}
        \end{figure}
%\else
\fi
\end{htmlonly}
%-----
\begin{latexonly}
\ifpdf
        % Salto de pagina para PDF
        \newpage
\else
\fi
\end{latexonly}
%-------
\begin{latexonly}
\ifpdf
        \begin{figure}[htbp]
        \includegraphics[bb = 30 400 0 0, scale=0.9]{./pics/pgzip_2cpu.png}
        \vspace{4.7in}
        \caption{Compresi\'on de fuentes: Eficiencias de {\em gzip}
        paralelo en un sistema SMP bi y quadri procesador}     
        \includegraphics[bb = 30 400 0 0, scale=0.9]{./pics/pgzip_4cpu.png}
        \end{figure}
\else
\end{latexonly}
        \pagestyle{empty}
        \begin{figure}
        \centering
        \includegraphics[595,390][0,0]{./pics/pgzip_2cpu}
\begin{latexonly}
        \vspace{5.5in}
\end{latexonly}
\begin{latexonly}
        \caption{Compresi\'on de fuentes: Eficiencias de {\em gzip}
        paralelo en un sistema SMP bi y quadri procesador}
        \includegraphics[595,390][0,0]{./pics/pgzip_4cpu}
\end{latexonly}
        \vspace{5.5in}
        \end{figure}
\begin{latexonly}
\fi
\end{latexonly}
\newpage
\begin{latexonly}
\ifpdf
\hspace{0.5in}Tambi\'en se hicieron pruebas con diferentes tama\~{n}os de bloque,
tomando valores de 2, 4, 8 y 22 MB. Podemos ver los diferentes resultados:
        \begin{figure}[htbp]
        \includegraphics[bb = 0 600 0 0, scale=0.3]{./pics/pgzip_graph2MB.png}
        \includegraphics[bb = -800 600 0 0, scale=0.3]{./pics/pgzip_graph4MB.png}
        \end{figure}
        \begin{figure}[htbp]
        \includegraphics[bb = 0 1100 0 0, scale=0.3]{./pics/pgzip_graph8MB.png}
        \includegraphics[bb = -800 1100 0 0, scale=0.3]{./pics/pgzip_graph22MB.png}
        \vspace{4.5in}
        \caption{66Compresi\'on de fuentes: Eficiencias seg\'un el tama\~{n}o del corte en {\em gzip} paralelo}
        \end{figure}
\else
\fi
\end{latexonly}


%----------------------------------------------------------
\newpage
\subsection*{El algoritmo Burrows-Wheeler de ordenaci\'on de bloques}
\hspace{0.5in}Podemos encontrar una interesante implementaci\'on de un compresor
basado en la ordenaci\'on de bloques del algoritmo de Burrows-Wheeler en 
\ifpdf
\htmladdnormallink{http://www.cs.man.ac.uk/arch/\\people/j-seward/bzip-0.21.tar.gz}{http://www.cs.man.ac.uk/arch/people/j-seward/bzip-0.21.tar.gz}
\else
\htmladdnormallink{http://www.cs.man.ac.uk/arch/people/j-seward/bzip-0.21.tar.gz}{http://www.cs.man.ac.uk/arch/people/j-seward/bzip-0.21.tar.gz}
\fi

El algoritmo Burrows-Wheeler de compresi\'on por ordenaci\'on de bloques est\'a descrito en {\em A Block-sorting Lossless Data Compression Algorithm} de M. Burrows y
D.J. Wheeler, con fecha el 10 de mayo de 1994. Podemos encontrar una copia de este documento en formato PS en el sitio FTP
del {\em Digital on the Systems Research Center (SRC)},
\ifpdf
\htmladdnormallink{ftp://ftp.digital.com/pub/DEC/\\SRC/research-reports/SRC-124.ps.Z}{ftp://ftp.digital.com/pub/DEC/SRC/research-reports/SRC-124.ps.Z}
\else
\htmladdnormallink{ftp://ftp.digital.com/pub/DEC/SRC/research-reports/SRC-124.ps.Z}{ftp://ftp.digital.com/pub/DEC/SRC/research-reports/SRC-124.ps.Z}
\fi

El m\'etodo fue descubierto originalmente por uno de los autores (Wheeler) sobre 1983, pero no publicado hasta entonces.

El m\'etodo descrito en el documento original es realmente una
composici\'on de tres algoritmos diferentes:
\begin{itemize}
  \item el motor principal para la {\bf ordenaci\'on} de bloques (un
preprocesador expansivo sin p\'erdidas bastante ligero)

  \item el {\bf codificador} {\em move-to-front} (un codificador simple y r\'apido byte a byte, localmente adaptativo)

  \item y un {\bf codificador estad\'\i stico} que eventualmente se encarga de
una recompresi\'on.
\end{itemize}

\hspace{0.5in}De estos tres m\'etodos s\'olo veremos los dos primeros en este
documento puesto que constituyen el coraz\'on del algoritmo. Estos 2 algoritmos combinados conforman una transformaci\'on sin p\'erdidas ({\em lossless}) completamente reversible 
que, aplicando rotaciones a la primera distribuci\'on de s\'\i mbolos,
intenta hacer los datos m\'as comprensibles para poder aplicar
m\'etodos sencillos y consecuentemente m\'as r\'apidos.

Resumiendo el comportamiento del algoritmo podr\'\i amos decir que se encarga de transformar las deficiencias en las altas probabilidades de los 
bloques de los datos entrantes (haciendolas m\'as exactas) en deficiencias en en las estad\'\i sticas de bajo orden.\\
Este efecto es lo que podemos apreciar en el historigrama resultante de los s\'\i mbolos de datos.
\vspace{0.5in}

\hspace{0.5in}El {\bf preprocesador de ordenaci\'on de bloques} opera puramente en base a bloques. Una forma de entender esta idea es pensar en un bloque de entrada
ordenado como un arreglo (tabla unidimensional) circular donde, para cada s\'\i mbolo se utilizan sus siguientes (s\'\i mbolos) para usarlos como un
predictor. Este predictor es usado para agrupar los s\'\i mbolos junto
a vecinos similares y es realizado (conceptualmente) como un proceso
de dos fases.
\begin{itemize}
  \item La primera fase dispone todos los desplazamientos c\'\i clicos de los bloques de entrada cuyos tama\~{n}os son generalmente una potencia de 2.
Cabe destacar que la cadena originaria est\'a siempre intacta en alguna fila de la matriz resultante. Si la longitud del bloque es N, luego deber\'an existir
N rotaciones de la cadena original (hacia la izquierda). Estas rotaciones son tratadas como las filas de una matriz de s\'\i mbolos de dimensiones NxN.

  \item La segunda fase consiste en ordenar esta matriz
  conceptual. Esta fase da como resultado unas filas en un orden
  basado en algunos de sus primeros s\'\i mbolos. Si hay alguna cadena repetida diversas veces en el bloque de entrada, la fase de ordenaci\'on dispondr\'a todas estas rotaciones que tienen una parte
de esta cadena como el inicio de la fila com\'un  a cualquier otra. El s\'\i mbolo precedente en esta cadena repetida se encuentra en la \'ultima columna
de la matriz ordenada.
\end{itemize}

Estos m\'etodos dan cortas r\'afagas de pocos caracteres (y distintos) en la \'ultima columna de la matriz. La \'ultima columna 
es la que resulta como salida para la segunda fase. Existe un n\'umero
entero con sufucientes bits para contener el valor del tama\~{n}o de la cadena de entrada (i.e. $log_{2}$(n)). El n\'umero es utilizado para anotar la posici\'on de la fila dentro
de la cual el algoritmo de ordenaci\'on puso el bloque de entrada original.
Este entero siempre resulta en expansi\'on de los datos, pero es necesario para ser capaces de descomprimir correctamente la cadena. La cantidad absoluta
de {\em overhead} incrementa com el logaritmo del tama\~{n}o del bloque de entrada, por consiguiente el porcentaje de los datos de salida representan
despreciables respecto la cantidad de bloques usables.

\hspace{0.5in}Las caracter\'\i sticas del proceso de transformaci\'on hace que la salida est\'e ordenada de una forma tal que es altamente usable para posteriores 
manipulaciones. El mejor ejemplo (que tambi\'en podemos ver en el documento original)  es la codificaci\'on {\em move-to-front}.
Este codificador codifica un s\'\i mbolo como un n\'umero de distintos s\'\i mbolos vistos desde la \'ultima ocurrencia del s\'\i mbolo. B\'asicamente esto
significa el codificador da a su salida el \'\i ndice de un s\'\i mbolo de la entrada en una pila LIFO din\'amica y luego actualiza la pila moviendo el  s\'\i mbolo
al {\em top} de dicha pila. Esto es f\'acil y eficiente de implementar y responde a una adaptaci\'on local r\'apida. As\'\i\ como algunos pocos s\'\i mbolos comunes
gobernar\'an localmente la entrada del codificador, estos s\'\i mbolos se mantendr\'an en el {\em top} de la pila mientras que la salida principalmente
consistir\'a en n\'umeros bajos. Esto hace, a los m\'etodos de compresi\'on estad\'\i stica de primer orden, altamente susceptibles de ser impementados
f\'acil y eficientemente.

La matriz transformada que se describe requiere enormes cantidades de
espacio de almacenaje, y puede no darnos el resultado correcto en
algoritmos como el descrito aqu\'\i\ (puesto que hay diversas formas
de implementarlo).
Sin embargo el m\'etodo puede ser realizado muy eficientemente con sufijos y m\'etodos de ordenaci\'on {\em quick sort}. La transformaci\'on junto a eventuales compresiones
es extremadamente r\'apida y consigue altos ratios de compresi\'on en una mayor parte de datos de entrada. Cuando todo est\'a bien implementado
la velocidad del proceso alcanza \'ordenes propias de m\'etodos como LZ y ratios de compresi\'on cercanos a los codificadores de modelaje de Markov (llamados {\em state-of-the-art} debido a sus prestaciones).
El motor tambi\'en responde bien a incrementos en los tama\~{n}os de bloques: cuanto mayores sean los bloques en la entrada, m\'as espacio necesitaremos para los  
patrones que se generan. Esto da como resultado, en la mayor parte la compresiones, ratios \'optimos para tama\~{n}os de bloque de 1MB.

La {\bf decompresi\'on es b\'asicamente el proceso de compresi\'on
invertido}. No obstante, para proceder inversamente, ser\'an
necesarios m\'as recursos computacionales.
Esta l\'ogica que utilizaremos en el proceso implica reflexionar entorno al orden de la primera y \'ultima columna de la matriz de codificaci\'on.
El documento original contiene m\'as informaci\'on sobre por qu\'e este m\'etodo funciona y cē'omo implementarlo.

\hspace{0.5in}Para terminar con esta transformada de Burrows-Wheeler
se muestra un peque\~{n}o ejemplo pr\'actico. El bloque original que ser\'a comprimido ser\'a 
la cadena {\tt good, jolly good} debido a que tiene un tama\~{n}o exacto de 16 caracteres y presenta redundancias.\\
En la primera tabla podemos ver las rotaciones c\'\i clicas de la cadena de entrada. En la segunda podemos ver la matriz, tras ser ordenada. Cabe notar que
la \'ultima columna ha estado situada en la sexta fila.

\begin{verbatim}
       0 1 2 3 4 5 6 7 8 9 A B C D E F        0 1 2 3 4 5 6 7 8 9 A B C D E F
       -------------------------------        -------------------------------
  0 | g o o d ,   j o l l y   g o o d    0 |   g o o d g o o d ,   j o l l y
  1 | o o d ,   j o l l y   g o o d g    1 |   j o l l y   g o o d g o o d ,
  2 | o d ,   j o l l y   g o o d g o    2 | ,   j o l l y   g o o d g o o d
  3 | d ,   j o l l y   g o o d g o o    3 | d ,   j o l l y   g o o d g o o
  4 | ,   j o l l y   g o o d g o o d    4 | d g o o d ,   j o l l y   g o o
  5 |   j o l l y   g o o d g o o d ,    5 | g o o d ,   j o l l y   g o o d
  6 | j o l l y   g o o d g o o d ,      6 | g o o d g o o d ,   j o l l y
  7 | o l l y   g o o d g o o d ,   j    7 | j o l l y   g o o d g o o d ,
  8 | l l y   g o o d g o o d ,   j o    8 | l l y   g o o d g o o d ,   j o
  9 | l y   g o o d g o o d ,   j o l    9 | l y   g o o d g o o d ,   j o l
  A | y   g o o d g o o d ,   j o l l    A | o d ,   j o l l y   g o o d g o
  B |   g o o d g o o d ,   j o l l y    B | o d g o o d ,   j o l l y   g o
  C | g o o d g o o d ,   j o l l y      C | o l l y   g o o d g o o d ,   j
  D | o o d g o o d ,   j o l l y   g    D | o o d ,   j o l l y   g o o d g
  E | o d g o o d ,   j o l l y   g o    E | o o d g o o d ,   j o l l y   g
  F | d g o o d ,   j o l l y   g o o    F | y   g o o d g o o d ,   j o l l
\end{verbatim}
\hspace{1in} 1. Matriz de entrada\hspace{1.5in}2. Matriz tras la ordenaci\'on

\hspace{0.5in}La tercera tabla muestra la salida para este bloque de entrada. El entero indexador ha estado
empaquetado aunque 4 bits sean suficientes para este caso ($log_{2}$16
= 4). 

\begin{verbatim}
                      "y,dood  oloojggl",5}
\end{verbatim}
\hspace{1in}3. La salida tras la ordenaci\'on de bloques

La cuarta y quinta tabla muestran la cadena transformada tras la codificaci\'on {\em move-to-front}.

\begin{verbatim}
                      121,45,102,114,0,1,36,0,
                      1,113,1,0,112,110,0,3,5
\end{verbatim}
\hspace{1in}4. Tras {\em move-to-front-coding}

\begin{verbatim}
                      79,2D,66,72,0,1,24,0,
                      1,71,1,0,70,6E,0,3,5
\end{verbatim}
\hspace{1in}5. En hexadecimal

La sexta tabla muestra la distribuci\'on estad\'\i stica de los caracteres en la cadena de salida. Podemos ver la desproporcionada cantidad de ceros y unos, a\'un
con un patr\'on corto como el que hemos tomado. Esta es la salida que dar\'\i a un codificador estad\'\i stico simple. Se comprime bastante bien, tanto
la distribuci\'on como los caracteres de los bloques de la entrada aun siendo los bloques de entrada dispares.

\begin{verbatim}
                      00: 4;  01: 3;  03: 1;  05: 1;
                      24: 1;  2D: 1;  66: 1;  6E: 1;
                      70: 1;  71: 1;  72: 1;  79: 1
\end{verbatim}
\hspace{1in}6. Las estad\'\i sticas
%----------------------------------------------------------
\subsection*{Eficiencia comparativa entre algoritmos de compresi\'on}
\hspace{0.5in}Llegados a este punto nos damos cuenta que la compresi\'on de fuentes ha dado frutos desde hace muchos a\~{n}os
y que, lejos de sabernos capaces de dominar todos los m\'etodos matem\'aticos descubiertos, existe gran cantidad de desarrolladores analizando
nuevos procedimientos que puedan dar cabida a nuevas t\'ecnicas de compresi\'on.

En esta \'ultima secci\'on veremos tablas comparativas entre diferentes compresores, ser\'a algo meramente indicativo y nada fiable
de cara a dar pie a la elecci\'on de uno u otro compresor.

La eficiencia de cada algoritmo depende en gran medida de la naturaleza de los datos de entrada y de las estructuras internas de que se sirve. Veremos como se comportan ante datos tan dispares
como im\'agenes, textos, documentos XML, datos geof\'\i sicos y algo sin lo cual ni yo mismo estar\'\i a escribiendo esto ni Vd., estimado lector, ley\'endolo: el ADN del {\em homo sapiens}.
Como tributo a mi profesor me he tomado la libertad de a\~{n}adir tambi\'en pruebas sobre ficheros musicales (en formato MIDI), y concretamente
he comprimmido el fichero {\em dvorak.wav} que se corresponde con el cuarto movimiento ({\em allegro con fuoco}) de la novena sinfon\'\i a de este autor checo.

\subsubsection*{Metodolog\'\i a}
\hspace{0.5in}La eficiencia se ha medido en t\'erminos de ratios de compresi\'on y tiempos de decompresi\'on. Analizaremos algunos de los algoritmos explicados 
en este art\'\i culo y otros que tambi\'en existen. Estos son:
\begin{itemize}
        \item algoritmo LZ77 utilizado por {\em gzip}

        \item transformada de Burrows-Wheeler por {\em bzip2}
        
        \item LZW por {\em compress}

        \item algoritmo adaptativo de Huffman por {\em compact}

        \item algoritmo de aritm\'etica adaptativa por {\em arith}

        \item {\em ppm} y {\em ppm*} que se basan en la predicci\'on de probabilidadesde unos caracteres basada en el n\'umero de caracteres
que lo preceden.\\Son computacionalmente muy pesados.

        \item {\em sequitar}
\end{itemize}

\subsubsection*{Tabla de resultados}
\hspace{0.5in}Puesto que ya se ha concretado suficiente en los algoritmos m\'as utilizados y puesto que el lector deber\'\i a ser capaz por s\'\i\ mismo
de interpretar las tablas, se exponen los resultados obtenidos sin m\'as comentarios que estos.
\begin{table}
\begin{center}
\begin{tabular}{ | l | c | c | c | c | c | c | c | c |} \hline
                & gzip          & bzip2         & compress              & compact                       & arith         & ppm           & ppm*  & sequitar   \\ \hline
Texto 1         & 7.55          & 10.13         & 6.44                  & 2.61                          & 2.61          & 11.3          & 9.6   & 8.18 \\ \hline
Texto 2         & 2.09          & 1.93          & 1.39                  & 1.11                          & 1.11          & 4.25          & 1.87  & 1.79 \\ \hline
Texto 3         & 9.1           & 12.24         & 7                     & 2.66                          & 2.68          & 13.4          & 11.6  & 9.17 \\ \hline
homosapiens-ch8.dna & 3.31      & 3.54          & 3.55                  & 3.62                          & 3.91          & 4.02          & 3.16  & 3.47 \\ \hline
Documento XML   & 9.05          & 13.26         & 4.18                  & 1.43                          & 1.44          & 12.16         & 5.53  & 4.02 \\ \hline
Datos geof\'\i sicos & 1.49     & 3.87          & 2.43                  & 1.65                          & 1.66          & 5.97          & 3.96  & 3.08 \\ \hline
MIDI            & 3.92          & 3.91          & 2                     & 1.53                          & 1.53          & 9.3           & 4     & 3  \\ \hline
Objecto         & 35.29         & 26.92         & 3.32                  & 1.33                          & 1.34          & 30.25         & 4.66  & 1.94 \\ \hline
Imagen          & 9.09          & 10.31         & 8.25                  & 4.81                          & 6.58          & 19.09         & 9.374 & 8.22 \\ \hline
\end{tabular}
\caption{Compresi\'on de fuentes: Comparativa de ratios}
\end{center}
\end{table}
%----------------------------------------------------------
\subsection*{Referencias}
\begin{itemize}
        \item Ziv J., Lempel A., {\em A Universal Algorithm for Sequential Data
Compression}, IEEE Transactions on Information Theory, Vol. 23, No. 3,

        \item Algoritmo de Huffman explicado por un sobrino del autor\\
\htmladdnormallink{{\tt http://home.columbus.rr.com/kenhuffman/david/algorithm.html}}{http://home.columbus.rr.com/kenhuffman/david/algorithm.html}

        \item Formato de los ficheros comprimidos {\em gzip} en\\
\htmladdnormallink{{\tt ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html}}{ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html}\\
\htmladdnormallink{{\tt http://www.gzip.org/format.txt}}{http://www.gzip.org/format.txt}

        \item Para ampliar conocimientos sobre el algoritmo de {\em deflate()}\\
\htmladdnormallink{{\tt http://www.gzip.org/zlib/feldspar.html}}{http://www.gzip.org/zlib/feldspar.html}

        \item Paralelizaci\'on de {\em gzip}\\
\htmladdnormallink{{\tt http://www-id.imag.fr/Logiciels/ath1/athavista/Compression.html}}{http://www-id.imag.fr/Logiciels/ath1/athavista/Compression.html}

        \item P\'agina principal de {\em zlib} en\\
\htmladdnormallink{{\tt http://www.gzip.org/zlib/}}{http://www.gzip.org/zlib/}

        \item Manual de {\em zlib} en\\
\htmladdnormallink{{\tt http://www.gzip.org/zlib/manual.html}}{http://www.gzip.org/zlib/manual.html}

        \item Interesante art\'\i culo sobre la compresi\'on con la
        transformada de Burrows-Wheeler (utilizada por {\em bzip2}) \\
\htmladdnormallink{{\tt http://www.dogma.net/markn/articles/bwt/bwt.htm}}{http://www.dogma.net/markn/articles/bwt/bwt.htm}

        \item Sobre el compressor PPM\\
\htmladdnormallink{{\tt http://datacompression.info/PPM.shtml}}{http://datacompression.info/PPM.shtml}

        \item Comparativa sobre diferentes compresores {\em lossless}\\
\htmladdnormallink{{\tt http://www.geocities.com/SiliconValley/Bay/1995/binaries18.html}}{http://www.geocities.com/SiliconValley/Bay/1995/binaries18.html}

        \item Gu\'\i a muy completa para la codificaci\'on de im\'agenes, con ejemplos y transparencias\\
\htmladdnormallink{{\tt http://web.umr.edu/~ersoy/docs/comp/pres/}}{http://web.umr.edu/~ersoy/docs/comp/pres/}

        \item Gu\'\i a muy completa para la codificaci\'on de audio y video con algoritmos {\em lossless}\\
\htmladdnormallink{{\tt http://www.cs.sfu.ca/undergrad/CourseMaterials/CMPT365/material/notes/\\Chap4/Chap4.html}}{http://www.cs.sfu.ca/undergrad/CourseMaterials/CMPT365/material/notes/Chap4/Chap4.html}

        \item Data-compression.com, parece quedar claro ;)\\
\htmladdnormallink{{\tt http://www.data-compression.com/}}{http://www.data-compression.com/}

        \item {\em Las leyes de la criptograf\'\i a} seg\'un Neal R.Wagner, profesor en la Universidad de Texas (USA)\\
\htmladdnormallink{{\tt http://www.cs.utsa.edu/~wagner/laws/}}{http://www.cs.utsa.edu/~wagner/laws/}

        \item \htmladdnormallink{HoaX\_69}{http://www.free2code.net/members/user_profiles.php?id=5} es un estudiante de ingenier\'\i a inform\'atica ha desarrollado varios tutoriales de algunos de los algoritmos de que hemos hablado.\\
El de Huffman en \htmladdnormallink{{\tt http://www.free2code.net/tutorials/other/huffman}}{http://www.free2code.net/tutorials/other/huffman}\\
El LZ77 en \htmladdnormallink{{\tt http://www.free2code.net/tutorials/other/LZ77}}{http://www.free2code.net/tutorials/other/LZ77}\\
El RLE en \htmladdnormallink{{\tt http://www.free2code.net/tutorials/other/RLE}}{http://www.free2code.net/tutorials/other/RLE}

        \item P\'agina oficial del compressor {\em lossless} de audio Monkey\\
\htmladdnormallink{{\tt http://www.monkeysaudio.com/}}{http://www.monkeysaudio.com/}

        \item P\'agina oficial del compressor gratuito de audio Vorbis\\
\htmladdnormallink{{\tt http://www.vorbis.com/}}{http://www.vorbis.com/}

        \item Curiosidades sobre la familia Huffman\\
\htmladdnormallink{{\tt http://www.huffmancoding.com}}{http://www.huffmancoding.com}

        \item M\'as referencias sobre compresi\'on de datos\\
\htmladdnormallink{{\tt http://www.ics.uci.edu/~dan/pubs/DC-references.html}}{http://www.ics.uci.edu/~dan/pubs/DC-references.html}

\end{itemize}
