Articulo de referencia

Codificación adaptativa de Huffman

La codificación Huffman adaptativa (también llamada codificación Huffman dinámica ) es una técnica de codificación adaptativa basada en la codificación Huffman . Permite constru...

La codificación Huffman adaptativa (también llamada codificación Huffman dinámica ) es una técnica de codificación adaptativa basada en la codificación Huffman . Permite construir el código a medida que se transmiten los símbolos, sin tener conocimiento inicial de la distribución de la fuente, lo que permite una codificación en una sola pasada y la adaptación a las condiciones cambiantes de los datos. [ 1 ]

La ventaja del procedimiento de una sola pasada es que la fuente se puede codificar en tiempo real, aunque se vuelve más sensible a los errores de transmisión, ya que una sola pérdida arruina todo el código, lo que requiere la detección y corrección de errores .

Algoritmos

Existen varias implementaciones de este método, las más destacadas son FGK ( Faller - Gallager - Knuth ) y el algoritmo de Vitter .

Algoritmo FGK

Se trata de una técnica de codificación en línea basada en la codificación de Huffman. Al no requerir conocimiento previo de las frecuencias de ocurrencia, permite ajustar dinámicamente el árbol de Huffman a medida que se transmiten los datos. En un árbol de Huffman FGK, se utiliza un nodo externo especial, denominado nodo 0 , para identificar un nuevo carácter. Es decir, cada vez que se encuentran nuevos datos, se genera la ruta al nodo 0 seguida de los datos. Para un carácter que ya ha llegado, simplemente se genera la ruta de los datos en el árbol de Huffman actual. Lo más importante es que debemos ajustar el árbol de Huffman FGK si es necesario y, finalmente, actualizar la frecuencia de los nodos relacionados. A medida que aumenta la frecuencia de un dato, la propiedad de hermanos del árbol de Huffman puede romperse. El ajuste se activa por este motivo y se logra mediante intercambios consecutivos de nodos, subárboles o ambos. El nodo de datos se intercambia con el nodo de mayor orden con la misma frecuencia en el árbol de Huffman (o con el subárbol con raíz en el nodo de mayor orden). Todos los nodos ancestros del nodo también deben procesarse de la misma manera.

Dado que el algoritmo FGK presenta algunos inconvenientes en lo que respecta al intercambio de nodos o subárboles, Vitter propuso otro algoritmo para mejorarlo.

Algoritmo de Vitter

Algunos términos y limitaciones importantes  :

  • Numeración implícita  : Significa que los nodos se numeran en orden ascendente por nivel y de izquierda a derecha. Es decir, los nodos del nivel inferior tendrán un número implícito menor que los nodos del nivel superior, y los nodos del mismo nivel se numeran en orden ascendente de izquierda a derecha. En otras palabras, al construir el árbol de Huffman, al fusionar dos nodos en un nodo padre, se asigna el nodo con el valor más bajo como hijo izquierdo y el nodo con el valor más alto como hijo derecho.
  • Invariante  : Para cada peso w, todas las hojas de peso w preceden a todos los nodos internos que tengan peso w. En otras palabras, cuando construimos el árbol de Huffman, si varios nodos tenían el mismo valor, priorizamos la fusión de las hojas sobre los nodos internos.
  • Bloques  : Los nodos del mismo peso y del mismo tipo (es decir, nodos hoja o nodos internos) forman un bloque.
  • Líder  : Nodo con el número más alto en un bloque.

Los bloques están interconectados en orden creciente de sus pesos.

Un bloque hoja siempre precede a un bloque interno del mismo peso, manteniendo así la invariante.

NYT (Not Yet Transferred) es un nodo especial que se utiliza para representar símbolos que "aún no se han transferido" .

Slide_And_Increment(nodo hoja) comienza el deslizamiento. P es un nodo hoja.
Slide_And_Increment(nodo hoja) paso deslizante 2. Como P es un nodo hoja, se desliza delante de los siguientes nodos de bloque de igual peso.
Slide_And_Increment(nodo hoja) paso deslizante 3. Aquí aumentamos el peso actual en 1.
Slide_And_Increment(nodo hoja) paso deslizante 4. El método llega a su fin. P es el nuevo padre.
Slide_And_Increment(nodo interno) comienza el deslizamiento. P es un nodo interno.
Slide_And_Increment(nodo interno) paso deslizante 2. El nodo P se desliza delante del siguiente bloque de nodos de hojas, con peso wt+1.
Slide_And_Increment(nodo interno) paso deslizante 3. Ahora aumentamos el peso a 9. Por lo tanto, se mantiene el invariante ya que el nodo actual es un nodo interno y debería aparecer delante de los nodos hoja de igual peso, ya que hemos aumentado el peso.
Slide_And_Increment(nodo interno) paso deslizante 4. Ahora la 'P' apunta al padre anterior (como en el caso del nodo interno según el algoritmo).
El algoritmo para agregar un símbolo es hoja_a_incrementar := NULL p := puntero al nodo hoja que contiene el siguiente símbolo si (p es NYT) entonces Extiende p añadiendo dos hijos El hijo izquierdo se convierte en el nuevo NYT y el hijo derecho es el nuevo símbolo del nodo hoja. p := padre del nuevo símbolo nodo hoja hoja_a_incrementar := Hijo derecho de p demás Intercambia p con el líder de su bloque. si (el nuevo p es hermano del NYT) entonces hoja_a_incrementar := p p := padre de p mientras (p ≠ NULL) hacer Deslizar_y_incrementar(p) Si (leaf_to_increment != NULL) entonces Slide_And_Increment(leaf_to_increment)
La función Slide_And_Increment(p) es previous_p := padre de psi (p es un nodo interno) entonces Desliza p en el árbol más arriba que los nodos de las hojas de peso wt + 1 aumentar el peso de p en 1 p := previous_p de lo contrario Desliza p en el árbol más arriba que los nodos internos de peso wt aumentar el peso de p en 1 p := nuevo padre de p .

El codificador y el decodificador comienzan únicamente con el nodo raíz, que es el que tiene el número máximo. Al principio, se trata de nuestro nodo inicial NYT.

Cuando transmitimos un símbolo del NYT, tenemos que transmitir primero el código del nodo del NYT y luego su código genérico.

Para cada símbolo que ya se encuentra en el árbol, solo tenemos que transmitir el código correspondiente a su nodo hoja.

Ejemplo

La codificación "abb" da como resultado 01100001 001100010 11.

Paso 1:

Comience con un árbol vacío.

Para "a" transmitir su código binario.

Paso 2:

NYT genera dos nodos hijos: 254 y 255, ambos con peso 0. Aumenta el peso para la raíz y el nodo 255. El código para "a", asociado con el nodo 255, es 1.

Para "b" transmitir 0 (para el nodo NYT) y luego su código binario.

Paso 3:

NYT genera dos nodos hijos: 252 para NYT y 253 para el nodo hoja, ambos con peso 0. Aumenta los pesos de 253, 254 y la raíz. Para mantener la invariante de Vitter de que todas las hojas de peso w preceden (en la numeración implícita) a todos los nodos internos de peso w, la rama que comienza con el nodo 254 debe intercambiarse (en términos de símbolos y pesos, pero no de orden numérico) con el nodo 255. El código para "b" es 11.

Para la segunda "b" transmitir 11.

Para facilitar la explicación, este paso no sigue exactamente el algoritmo de Vitter, [ 2 ] pero los efectos son equivalentes.

Paso 4:

Vaya al nodo hoja 253. Observe que tenemos dos bloques con peso 1. Los nodos 253 y 254 son un bloque (que consta de hojas), el nodo 255 es otro bloque (que consta de nodos internos). Para el nodo 253, el número más grande en su bloque es 254, así que intercambie los pesos y símbolos de los nodos 253 y 254. Ahora el nodo 254 y la rama que comienza desde el nodo 255 satisfacen la condición SlideAndIncrement [ 2 ] y por lo tanto deben intercambiarse. Finalmente, aumente el peso de los nodos 255 y 256.

El código futuro para "b" es 1, y para "a" es ahora 01, lo que refleja su frecuencia.

Referencias

  1. Ze-Nian Li; Mark S. Drew; Jiangchuan Liu (9 de abril de 2014). Fundamentos de multimedia . Springer Science & Business Media. ISBN 978-3-319-05290-8.
  2. 1 2 "Codificación Huffman adaptativa" . Cs.duke.edu . Recuperado el 26 de febrero de 2012 .
  • Artículo original de Vitter: JS Vitter, " Diseño y análisis de códigos Huffman dinámicos ", Journal of the ACM, 34(4), octubre de 1987, pp. 825–845.
  • JS Vitter, "ALGORITMO 673 Codificación dinámica de Huffman", ACM Transactions on Mathematical Software, 15(2), junio de 1989, pp. 158–167. También aparece en Collected Algorithms of ACM.
  • Donald E. Knuth, "Codificación dinámica de Huffman", Journal of Algorithm, 6(2), 1985, pp 163–180.