Upload
jorge-luis-gomez-vargas
View
33
Download
0
Embed Size (px)
Citation preview
Capıtulo 4
Otros Sistemas de Codificacion
En general, los codigos de Huffman no son adecuados cuando el tamano
del alfabeto fuente es pequeno y la probabilidad maxima grande, pues la
longitud media puede distar bastante de la entropıa. Cuando esto ocurre,
hemos visto que cabe la posibilidad de codificar grupos de sımbolos en lugar
de generar una palabra-codigo para cada sımbolo del alfabeto. Sin embargo,
en la practica esta posibilidad presenta un grave inconveniente. Si queremos
determinar la palabra-codigo que corresponde a una cadena concreta de longi-
tud k, el algoritmo extendido de Huffman exige encontrar las palabras-codigo
de todas las cadenas de longitud k. En este tema estudiamos el codigo arit-
metico, que no presenta este inconveniente, y algunas tecnicas de diccionario.
4.1. El codigo aritmetico
En la codificacion aritmetica, se genera una unica etiqueta o marca para la
sucesion que se desea codificar. Esta etiqueta es cierto numero del intervalo
(0, 1] y en su determinacion juegan un papel fundamental las frecuencias
acumuladas de los sımbolos del alfabeto. El uso de estas frecuencias para
determinar un codigo ya aparece en el trabajo de Shannon de 1948. Pero
el codigo aritmetico fue creado independientemente en 1976 por Pasco y
Rissanen.
43
44 CAPITULO 4. OTROS SISTEMAS DE CODIFICACION
El procedimiento para generar la marca de la sucesion consiste en ir re-
duciendo la longitud del intervalo que contiene dicha marca a medida que se
van recibiendo los elementos de la sucesion.
Para simplificar el desarrollo teorico, supondremos que el alfabeto fuente
es S = {1, 2, 3, ..., n}. Si el conjunto de probabilidades es P = {p1, .., pn}, las
frecuencias acumuladas vienen dadas por
F (k) =k∑
i=1
pi, y F (0) = 0,
de modo que los intervalos [F (i − 1), F (i)), con i = 1, .., n, constituyen una
particion del intervalo [0, 1). Asignamos el sımbolo i con el intervalo [F (i −1), F (i)). Se comienza con el intervalo [0, 1). Seguidamente se divide este en
subintervalos de la forma [F (i−1), F (i)), i = 1, 2, ..., n. Si el primer elemento
recibido es i, consideramos ahora el nuevo intervalo [F (i − 1), F (i)). Este
intervalo se divide en n subintervalos con longitudes proporcionales a las de
los de la primera division. Por tanto, tienen la forma
[F (i− 1) + rF (j − 1), F (i− 1) + rF (j)), j = 1, 2, .., n,
donde r = F (i) − F (i − 1), es decir, r es la longitud del intervalo actual
[F (i − 1), F (i)). Si el segundo elemento recibido es j, entonces el intervalo
que contiene la marca es [F (i−1)+rF (j−1), F (i−1)+rF (j)). Continuando
de esta forma se determina una sucesion decreciente de intervalos encajados y
el proceso termina cuando encontramos el intervalo que corresponde al ultimo
elemento recibido. La marca de la sucesion a codificar es cualquier elemento
de este intervalo final (suele tomarse el punto medio).
Para facilitar la comprension del algoritmo de codificacion, vamos a con-
siderar un ejemplo sencillo
Ejemplo 4.1.1. Supongamos que el alfabeto fuente es S = {1, 2, 3} con las
probabilidades P = {0.8, 0.04, 0.16} y se desea codificar la sucesion 1 3 2.
4.1. EL CODIGO ARITMETICO 45
Empezamos elaborando una tabla con las frecuencias acumuladas y los
subintervalos de (0, 1] de la forma [F (i− 1), F (i)), donde i = 1, 2, 3:
sımbolos F(i) subintervalos
1 0.8 [0,0.8)
2 0.84 [0.8,0.84)
3 1 [0.84,1)
Denotamos por ([ak, bk))k la sucesion de intervalos que contienen la marca de
la sucesion a codificar. Empezamos con [a0, b0) = [0, 1). El primer elemento
de la sucesion es 1, por tanto, el siguiente intervalo es
a1 = a0 + (b0 − a0) · F (0) = 0 + (1− 0) · 0 = 0
b1 = a0 + (b0 − a0) · F (1) = 0 + (1− 0) · 0.8 = 0.8.
A continuacion se determina el intervalo [a2, b2) usando el hecho de que el
siguiente elemento en la sucesion es 3:
a2 = a1 + (b1 − a1) · F (2) = 0 + (0.8− 0) · 0.84 = 0.672
b2 = a1 + (b1 − a1) · F (3) = 0 + (0.8− 0) · 1 = 0.8.
Notese que cada intervalo esta contenido en el anterior. Finalmente, deter-
minamos el intervalo [a3, b3), sabiendo que el tercer sımbolo es 2:
a3 = a2 + (b2 − a2) · F (1) = 0.672 + (0.8− 0.672) · 0.8 = 0.7744
b3 = a2 + (b2 − a2) · F (2) = 0.672 + (0.8− 0.672) · 0.84 = 0.77952.
La marca de la sucesion es el punto medio de este ultimo intervalo: m =
0.77696.
A la vista de las ideas anteriores, es facil determinar un algoritmo para
generar la marca:
1. Inicializar a0 = 0, b0 = 1.
2. Al recibir cada sımbolo del mensaje fuente, determinar el intervalo
[F (i− 1), F (i)) que le corresponde
46 CAPITULO 4. OTROS SISTEMAS DE CODIFICACION
3. Actualizar ak y bk:{
ak = ak−1 + (bk−1 − ak−1)F (i− 1)
bk = ak−1 + (bk−1 − ak−1)F (i).(4.1)
4. Continuar hasta codificar la sucesion entera.
Para probar que el codigo aritmetico es instantaneo, necesitamos la sigu-
iente expresion explıcita de la marca.
Denotemos por x la cadena x1, .., xk formada por sımbolos fuente y por
P (x) la probabilidad del mensaje x. Recordemos que la probabilidad de
recibir un sımbolo fuente es independiente de los anteriormente recibidos.
Si Sk el conjunto de todas las cadenas en S de longitud k, consideramos en
Sk el orden lexicografico y definimos
F (x1, .., xn) =∑y<x
P (y).
Entonces se verifica:
(1) La marca que corresponde al mensaje fuente x = x1x2...xk es
m(x) =∑y<x
P (y) + (1/2)P (x).
(2) Los extremos del intervalo marca vienen dados por
ak = F (ant(x1, .., xk)), bk = F (x1, ...xk),
donde ant(x1, .., xk) denota la cadena inmediatamente anterior a x1x2...xk.
Vamos a probar (2) por induccion sobre k:
i) Si se recibe el mensaje i, hemos visto que su intervalo identificador es
[F (i− 1), F (i)), por lo que (2) es cierta para k = 1.
ii) Supongamos que (2) es cierto para k y consideremos un mensaje fuente
x1x2...xki de longitud k+1. Por el algoritmo de generacion del intervalo marca
ak+1 = ak + (bk − ak) · F (i− 1), bk+1 = ak + (bk − ak) · F (i), (4.2)
4.2. GENERACION DE UN CODIGO BINARIO 47
donde [ak, bk) es el intervalo correspondiente al mensaje x1x2...xk. Vamos a
probar solo la igualdad
bk+1 = F (x1, .., xk, i),
puesto que la otra se prueba de manera similar. Por la hipotesis de induccion,
tenemos
bk = F (x1, .., xk), y ak = F (ant(x1, .., xk)). (4.3)
Teniendo en cuenta que
F (i) =∑j≤i
P (j) y 1− F (i) =∑j>i
P (j)
las relaciones (4.2) y (4.3) permiten obtener
bk+1 = ak(1−F (i))+bkF (i) =∑
y<ant(x1..xk)
∑j>i
P (y)P (j)+∑
y≤x1..xk
∑j≤i
P (y)P (j).
Finalmente, basta observar que, en el segundo miembro, las sumas de la
derecha son exactamente las sumas de las probabilidades de las cadenas de
la forma y1..ykj con y1..yk anterior o igual a x1..xk y j ≤ i, mientras que
las sumas de la izquierda son las sumas de las probabilidades de las cadenas
y1..ykj con y1..yk anterior a ant(x1, .., xk) y j > i, lo que constituye el total
de las sumas que determinan la frecuencia acumulada F (x1, .., xk).
4.2. Generacion de un codigo binario
Acabmos de ver como se genera la marca para cada mensaje, pero ahora
deseamos determinar un codigo binario para representar de una forma efi-
ciente y unica cualquier mensaje. La marca m es un numero del intervalo
[0, 1) y una forma de conseguir un codigo binario para este numero coonsiste
en considerar su representacion binaria, truncada adecuadamente.
Para ello, denotamos por `(x) el numero natural
dlog(1/P (x)
)+ 1e,
48 CAPITULO 4. OTROS SISTEMAS DE CODIFICACION
donde dae denota el menor numero entero que es mayor o igual que a y x es
una cadena finita en S cualquiera (recordemos que log denota el logaritmo
en base 2). La palabra-codigo que asignaremos al mensaje x sera la formada
por los `(x) primeros dıgitos de la representacion binaria de la marca m(x) y
denotamos por m(x)`(x) el numero real que resulta al truncar el desarrollo bi-
nario de m(x). Hemos visto que a mensajes fuente diferentes les corresponde
marcas diferentes; sin embargo, con los desarrollos truncados puede no ocur-
rir lo mismo. Es decir, tenemos que probar que al truncar las marcas de dos
mensajes diferentes se obtienen dos cadenas binarias distintas. Como los in-
tervalos identificadores son disjuntos, bastara probar que m(x)`(x) pertenece
al intervalo [F (ant(x)), F (x)). A la vista de las relaciones obvias
{0 ≤ m(x)−m(x)`(x) < 1
2`(x)
m(x)`(x) < F (x),(4.4)
solo necesitamos mostrar que F (ant(x)) ≤ m(x)`(x). Con este objetivo, notese
que1
2`(x)=
1
2d(1/P (x))+1e ≤1
2log(1/P (x))+1=
P (x)
2. (4.5)
Por otra parte, sabemos que
m(x)− F (ant(x)) =P (x)
2. (4.6)
De (4.5) y (4.6) se sigue
m(x)− F (ant(x)) ≥ 1
2`(x). (4.7)
Esta desigualdad junto con (4.4) permiten obtener
m(x)`(x) − F (ant(x)) ≥ 0,
lo que concluye la prueba de que m(x)`(x) pertenece al intervalo [F (ant(x)), F (x)).
Terminamos esta seccion probando que el codigo aritmetico es instan-
taneo, es decir, que una palabra-codigo no puede ser el comienzo de otra.
Hemos comprobado que al truncar la marca m(x) de la forma establecida
4.3. ALGORITMO DE DECODIFICACION 49
no nos salimos del intervalo identificativo. No obstante, vamos a ver que, de
hecho, se verifica que todo el intervalo [m(x)`(x),m(x)`(x) + 2−`(x)) esta in-
cluido en [F (ant(x)), F (x)). Como la relacion F (ant(x)) ≤ m(x)`(x) ya se ha
obtenido, basta probar la desigualdad
m(x)`(x) + 2−`(x)) ≤ F (x). (4.8)
Y (4.8) se obtiene como sigue
F (x)−m(x)`(x) ≥ F (x)−m(x) =P (x)
2≥ 2−`(x).
4.3. Algoritmo de decodificacion
Abordamos ahora el problema de la decodificacion de la marca de un men-
saje. Veremos que el proceso consiste en ir siguiendo los pasos de que consta
el proceso de generacion de la marca. Nuevamente, consideramos primero el
ejemplo anterior. Habiamos obtenido la marca m = 0.77696 y recordemos
que los intervalos que se van determinando durante el proceso de generacion
de m forman una sucesion decreciente de intervalos
[ak, bk) ⊂ [ak−1, bk−1) ⊂ · · · ⊂ [a1, b1) ⊂ [a0, b0) = [0, 1).
Iniciamos el proceso de decodificacion con [a0, b0) = [0, 1) y ponemos r =
b0 − a0. En la tabla de frecuencias acumuladas encontramos i ∈ {1, ..., n} de
modo que
F (i− 1) ≤ m− a0
r< F (i),
dado que la marca m se tomo en [a0+rF (i−1), a0+rF (i)) = [F (i−1), F (i)),
al recibir el primer elemento del mensaje fuente. En nuestro ejemplo, se tiene
m− a0
r= m = 0.77696.
Como m ∈ [0, 0.8) = [F (0), F (1)), se sigue que i = 1, lo que significa que el
primer elemento del mensaje es 1. Ahora se procede a actualizar
50 CAPITULO 4. OTROS SISTEMAS DE CODIFICACION
1) el intervalo
{a1 = a0 + rF (0) = 0
b1 = a0 + rF (1) = 0.8,
2) r = b1 − a1 = 0.8.
Como la marca pertenece al intervalo [a1 + rF (i− 1), a1 + rF (i)), para cierto
i ∈ {1, ..., n}, igual que en el primer paso buscamos en la tabla de frecuencias
acumuladas i de modo que
F (i− 1) ≤ m− a1
r< F (i).
Dado quem− a1
r=
0.77696− 0
0.8= 0.97,
deducimos que i = 3 y hemos encontrado el segundo elemento del mensaje.
El proceso de decodificacion continua de esta forma hasta que decodificamos
el ultimo sımbolo del mensaje. Hay dos formas de saber cuando se ha decod-
ificado el mensaje entero. a) El decodificador conoce la longitud del mensaje
fuente y b) se establce un sımbolo que marque el fin de la transmision.
Terminamos esta seccion estableciendo el algoritmo de decodificacion que
resulta obvio a la vista del ejemplo que hemos desarrollado:
1. Inicializar a0 = 0, b0 = 1.
2. Para cada k, encontrar
s =m− ak−1
bk−1 − ak−1
.
3. Encontrar i ≤ n de modo que
F (i− 1) ≤ s < F (i).
4. Actualizar ak y bk:{
ak = ak−1 + (bk−1 − ak−1)F (i− 1)
bk = ak−1 + (bk−1 − ak−1)F (i).(4.9)
5. Continuar hasta codificar la sucesion entera.
4.4. LONGITUD MEDIA DEL CODIGO ARITMETICO 51
4.4. Longitud media del codigo aritmetico
Nos ocupamos ahora de averiguar hasta que punto es eficiente el codigo
aritmetico. Notemos, en primer lugar, que la longitud media de las palabras
que codifican los mensajes fuente de longitud k viene dada por
L =∑
P (x) · `(x),
donde la suma se extiende a todas las cadenas de longitud k formadas por
sımbolos del alfabeto fuente S. Teniendo en cuenta la definicion de `(x),
resulta
L =∑
P (x)(dlog(1/P (x))e+ 1
) ≤∑
P (x)(log(1/P (x)) + 2
)=
= H(Sk) + 2∑
P (x) = H(Sk) + 2.
Por otra parte, se tiene la desigualdad H(Sk) ≤ L, ya que el codigo aritmetico
es instantaneo. Por tanto, se verifica
H(Sk) ≤ L ≤ H(Sk) + 2. (4.10)
Si denotamos por `S la longitud media por sımbolo fuente, entonces L = k`S
y (4.10) adopta la forma
H(Sk)
k≤ `S ≤ H(Sk)
k+
2
k. (4.11)
Finalmente, recordando que en el tema anterior hemos visto que H(Sk) =
kH(S), puede escribirse la relacion anterior en la forma
H(S) ≤ `S ≤ H(S) +2
k,
lo que prueba que podemos conseguir que `S este tan proxima a la entropıa
como se quiera sin mas que tomar k convenientemente grande.
52 CAPITULO 4. OTROS SISTEMAS DE CODIFICACION
4.5. Generacion del codigo aritmetico con es-
calado
Hemos visto que la marca se genera mediante el algoritmo
{an+1 = an + (bn − an)F (i− 1)
bn+1 = an + (bn − an)F (i).(4.12)
En las aplicaciones surge un importante problema en relacion con el codigo
aritmetico. A medida que n aumenta, los extremos del intervalo [an, bn) se
aproximan y puede ocurrir que la maquina no pueda distinguirlos. En este
apartado vamos a desarrollar un metodo que resuelve este problema y que
consiste en ir reescalando los intervalos que se van obteniendo.
El algoritmo se desarrolla con normalidad hasta encontrar el primer in-
tervalo [an, bn) que verifique una de las tres condiciones siguientes:
(a) [an, bn) ⊂ [0, 0.5).
(b) [an, bn) ⊂ [0.5, 1).
(c) [an, bn) ⊂ [0.25, 0.75) y 5 ∈ [an, bn).
Para simplificar, consideraremos por el momento solo las dos primeras posi-
bilidades. Supongamos que el intervalo [an, bn) es el primero que verifica (a)
o (b). Si esta contenido en [0, 0.5), tambien lo estan los intervalos siguientes.
Por tanto, la marca del mensaje que estamos codificando pertenece a [0, 0.5)
y el dıgito mas significativo de la representacion binaria de la marca es 0 (ten-
gase en cuenta que 0.5 = 0.12). Si, por el contrario, [an, bn) esta contenido en
la mitad superior, el dıgito mas significativo de la marca sera 1. Es decir, en
el momento que encontramos que un intervalo determinado por el algoritmo
anterior esta contenido en [0, 0.5) o [0.5, 1), el signo mas significativo de la
representacion binaria de la marca esta completamente determinado: es un 0
en el caso (a) y un 1 en el (b). Este hecho puede trnasmitirse o almacenarse
sin necesidad de esperar a codificar el resto del mensaje. Para evitar el prob-
lema de la reduccion progresiva del intervalo, tras transmitir el primer dıgito,
procedemos a reescalar el intervalo actual [an, bn). Para ello, consideramos las
4.5. GENERACION DEL CODIGO ARITMETICO CON ESCALADO 53
funciones
f1 : x ∈ [0, 0.5) → 2x ∈ [0, 1),
f2 : x ∈ [0.5, 1) → 2(x− 0.5) ∈ [0, 1),
y se continua el algoritmo con el nuevo intervalo [an, bn) = [fi(an), fi(bn)),
con i igual a 1 o 2 segun estemos en el caso (a) o (b). Es decir, para encontrar
el siguiente bit mas significativo de la marca, debemos escoger i de forma que{
an+1 = an + (bn − an)F (i− 1)
bn+1 = an + (bn − an)F (i).(4.13)
Si no hubiesemos reescalado, el algoritmo continua con el siguiente inter-
valo dado por (4.12). Para fijar ideas, supongamos que estamos en el caso
[an, bn) ⊂ [0, 0.5).Si multiplicamos los dos miembros de (4.12) por 2, resulta{
2an+1 = an + (bn − an)F (i− 1)
2bn+1 = an + (bn − an)F (i),(4.14)
lo que prueba que, con escalado o sin el, el valor de i es el mismo.
Imaginemos que por segunda vez el intervalo actual esta en una de las
situaciones (a) o (b). El dıgito mas significativo de los puntos de dicho interva-
lo esta entonces determinado y es, a su vez, el segundo dıgito mas significativo
de la marca (recuerdese que el intervalo se ha duplicado una vez). Por tanto,
podemos almacenar o transmitir este dıgito y continuar con el algoritmo, tras
reescalar el intervalo actual por segunda vez. La codificacion termina cuando
se ha considerado el ultimo sımbolo del mensaje fuente.
Pasamos ahora a considerar la posibilidad de que el intervalo actual
[an, bn) este contenido en [0.25, 0.75). Si este es el caso, duplicamos dicho
intervalo usando la aplicacion
f3 : x ∈ [0.25, 0.75) → 2(x− 0.25) ∈ [0, 1).
El codificador toma nota de que ha aplicado la funcion f3 y continua el
algoritmo con el nuevo intervalo [an, bn) = [f3(an), f3(bn)). Si se da el caso
54 CAPITULO 4. OTROS SISTEMAS DE CODIFICACION
de que, tras aplicar k veces f3, el nuevo intervalo obtenido por aplicacion
del algoritmo resulta estar contenido en [0.5, 1), puede demostrarse que los
siguientes k +1 dıgitos del desarrollo binario de la marca son necesariamente
1 seguido de k ceros. Si, por el contrario, despues de k aplicaciones de f3,
encontramos un intervalo contenido en [0, 0.5), entonces los k + 1 siguientes
dıgitos son 0 seguido de k unos. Estos dıgitos pueden ser ya transmitidos (o
almacenados) antes de continuar con el proceso de codificacion.
Para justificar las afirmaciones anteriores, vamos a considerar el caso mas
simple siguiente. Supongamos que se ha iniciado el algoritmo de codificacion
y, por primera vez, encontramos un intervalo [an, bn) que esta en alguna
de las situaciones (a), (b) o (c). Concretamente, asumimos que [an, bn) ⊂[0.25, 0.75). Entonces procedemos a reescalar el intervalo
an = 2(an − 0.25), bn = 2(bn − 0.25) (4.15)
y seguidamente, tras recibir el siguiente sımbolo, procedemos a determinar
el siguiente intervalo
{an+1 = an + (bn − an)F (i− 1)
bn+1 = an + (bn − an)F (i),(4.16)
Puede ocurrir que este intervalo este contenido en [0, 0.5), en [0.5, 1) o ni una
cosa ni la otra. Estamos interesados en el caso de que se de alguna de las dos
primeras.
a) [an+1, bn+1) ⊂ [0.5, 1). En este momento del proceso de codificacion,
segun hemos dicho mas arriba, los dos primero dıgitos del desarrollo binario
de la marca serıan 10. Para probar que esto es ası, denotemos por [asn+1, b
sn+1)
el intervalo que que se obtendrıa al aplicar el algoritmo de codificacion con
el intervalo [an, bn), es decir, sin aplicar f3. Sustituyendo los valores de an y
bn, dados por (4.15) en (4.16), obtenemos
{an+1 = 2(an − 0.25) + 2(bn − an)F (i− 1)
bn+1 = 2(an − 0.25) + 2(bn − an)F (i),
4.5. GENERACION DEL CODIGO ARITMETICO CON ESCALADO 55
Notese que an+1 = 2(asn+1 − 0.25) y bn+1 = 2(bs
n+1 − 0.25) y, teniendo en
cuenta que [an+1, bn+1) ⊂ [0.5, 1), se sigue que
asn+1 = 0.25 +
an+1
2≥ 0.25 +
0.5
2= 0.5
y
bsn+1 = 0.25 +
bn+1
2≤ 0.25 +
1
2= 0.75.
Esto muestra que [asn+1, b
sn+1) ⊂ [0.5, 0.75), por lo que la marca tiene como
primeras dos cifras significativas 10, ya que
0.25 = 0.012); 0.5 = 0.12), 0.75 = 0.112).
b) [an+1, bn+1) ⊂ [0, 0.5). Procediendo de igual forma, se probarıa que
[asn+1, b
sn+1) ⊂ [0.25, 0.5), por lo que la marca comenzarıa por 01.
Ejemplo 4.5.1. Sea S = {1, 2, 3, 4} el alfabeto fuente y P = {0.3, 0.15, 0.25, 0.3}el conjunto de probabilidades. Usar el algoritmo con reescalado para codificar
el mensaje 3 2 1 2.
En primer lugar, elaboramos la tabla con las frecuencias acumuladas y
los subintervalos que corresponden a cada sımbolo fuente
sımbolos F(i) intervalos
1 0.3 [0, 0.3)
2 0.45 [0.3, 0.45)
3 0.7 [0.45, 0.7)
4 1 [0.7, 1)
Se inicia el algoritmo de codificacion con a0 = 0 y b0 = 1. Se recibe el sımbolo
3 al que corresponde el intervalo [a1, b1) = [0.45, 0.7). Como esta contenido
en [0.25, 0.75), aplicamos la funcion f3 para obtener los nuevos valores de a1
y b1:
a1 = 2(0.45− 0.25) = 0.4, b1 = 2(0.7− 0.25) = 0.9
56 CAPITULO 4. OTROS SISTEMAS DE CODIFICACION
y ponemos el contador en 1. Al no estar el nuevo intervalo [0.4, 0.9) en ninguna
de las situaciones (a), (b) 0 (c), prosegimos con la codificacion del siguiente
sımbolo, 2. {a2 = 0.4 + (0.9− 0.4)0.3 = 0.55
b2 = 0.4 + (0.9− 0.4)0.45 = 0.625
El intervalo [a2, b2) esta contenido en la mitad superior del intervalo unidad,
por tanto, transmitimos 10, ponemos el contador en cero y aplicamos f2 para
reescalar el intervalo [a2, b2):
a2 = 2(0.55− 0.5) = 0.1, b2 = 2(0.625− 0.5) = 0.250.
El nuevo intervalo esta contenido en [0, 0.5). Entonces transmitimos 0 y apli-
camos f1 para reescalar el intervalo actual
a2 = 2 · 0.1 = 0.2, b2 = 2 · 0.250 = 0.5.
De nuevo transmitimos 0 y reescalamos con la funcion f1
a2 = 2 · 0.2 = 0.4; b2 = 2 · 0.5 = 1.
Nuevamente, el intervalo no esta en ninguna de las tres condiciones que pre-
cisan reescalado y, por tanto, damos entrada al siguiente sımbolo, 1. Actual-
izamos el intervalo{
a3 = 0.4 + (1− 0.4)0 = 0.4
b3 = 0.4 + (1− 0.4)0.3 = 0.58.
Como [a3, b3) esta contenido en [0.25, 0.75), ponemos el contador en 1 y
reescalamos por medio de f3
a3 = 2(0.4− 0.25) = 0.3, b3 = 2(0.58− 0.25) = 0.66.
Ponemos el contador en 2 y reescalamos con f3
a3 = 2(0.3− 0.25) = 0.1, b3 = 2(0.66− 0.25) = 0.82.
4.6. EL ALGORITMO DE CODIFICACION CON ARITMETICA ENTERA57
No se necesita reescalar, damos entrada al ultimo sımbolo, 2, y actualizamos
el intervalo:
{a4 = 0.1 + (0.82− 0.1) · 0.3 = 0.316
b4 = 0.1 + (0.82− 0.1) · 0.45 = 0.4240.
El intervalo [a4, b4) esta contenido en la mitad inferior del intervalo unidad y
el contador esta en 2, transmitimos 0 1 1. Hasta el momento se ha transmitido
la cadena 1 0 0 0 0 1 1.
4.6. El algoritmo de codificacion con aritmeti-
ca entera
Resuelto el problema de la reduccion progresiva del intervalo [an, bn),
a la hora de la aplicacion practica del codigo aritmetico, queda aun una
importante dificultad por resolver: encontrar el desarrollo binario de la marca
obtenida. En este apartado vamos a considerar una forma de implementar el
algoritmo de codificacion usando aritmetica entera.
En primer lugar, debemos decidir el valor del parametro m que representa
la longitud de las cadenas binarias que manipularemos. Por el momento,
supondremos que ha sido determinado su valor. Denotamos por ni el numero
de veces que aparece el sımbolo i en una sucesion de longitud N (suponemos
que el alfabeto fuente es S = {1, 2, .., s}). La sucesion de frcuencias absolutas
acumuladas se denota por (Nk)s0, por tanto, se tiene
Nk = n1 + n2 + · · ·+ nk, (k ≥ 1) y N0 = 0.
La frecuencia relativa acumulada F (i) viene dada por F (i) = Ni/N . Las
expresiones (??) del algoritmo de codificacion se sustituyen por
{an+1 = an + b (bn−an+1)Ni−1
Nc
bn+1 = an + b (bn−an+1)Ni
Nc − 1,
(4.17)
58 CAPITULO 4. OTROS SISTEMAS DE CODIFICACION
donde i es el sımbolo que se acaba de recibir y bxc denota la parte entera de
x. Los puntos 0, 0.5 y 1 del intervalo [0, 1) se ponen en correspondencia con
cadenas binarias de longitud m del modo siguiente
0 ←→ 0 · · · (m) · · · 0
0.5 ←→ 1 0 · · · (m− 1) · · · 01 ←→ 1 · · · (m) · · · 1.
Una vez establecida las notaciones que necesitamos, para simplificar la ex-
plicacion, vamos a desarrollar el metodo sobre un ejemplo concreto. Con-
sideramos el mismo ejemplo del apartado anterior. Suponemos que, en una
cadena de longitud 60, las frecuencias absolutas con que aparecen los sımbolos
S = {1, 2, 3, 4} son las indicadas en la tabla siguiente.
sımbolos frecuencias Ni
1 18 18
2 9 27
3 15 42
4 18 60
Debemos escoger m de modo que 2m supere a 4N . En nuestro caso, 4N = 240.
Por tanto, podemos escoger m = 8, pues 28 = 256. Supongamos que el
mensaje a codificar es 3 2 1 2.
Comenzamos con a0 = 000000002) = 0 y b0 = 111111112) = 255. Recibi-
mos el primer sımbolo , 3, y determinamos a1 y b1 mediante las expresiones
(4.17): {a1 = 0 + b256·27
60c = 115 = 011100112)
b1 = 0 + b256·4260
c − 1 = 178 = 101100102).
Vemos que el primer bit de a1 es diferente del de b1, pero el segundo bit es
mayor en a1 que en b1 (en el algoritmo con escalado, esto supondrıa que de-
berıamos aplicar la funcion f3). En la implementacion con aritmetica entera,
eliminamos el primer bit de ambos, el segundo se complementa y se anade
4.6. EL ALGORITMO DE CODIFICACION CON ARITMETICA ENTERA59
a la derecha un nuevo dıgito para completar los 8. a1 lleva un 0 y 1 un 1,
obteniendose
a1 = 011001102) = 102, b1 = 111001012) = 229.
Para llevar la cuenta del numero de veces que hacemos esta operacion, creamos
un contador al que damos el valor 1. Vemos que ahora el primer bit de a1
y b1 es diferente, pero el segundo de a1 no es mayor que el de b1. Entonces
proseguimos con la codificacion y consideramos el sımbolo siguiente, 2.{
a2 = 102 + b128·1860
c = 140 = 100011002)
b2 = 102 + b128·2760
c − 1 = 158 = 100111102).
Ahora el bit inicial es el mismo para a1 y para b1. Transmitimos (o almacen-
amos) un 1, eliminamos el primer bit y se anade a la derecha un 0 a a2 y un
1 a b2, resultando
a2 = 000110002), b2 = 001111012).
Ahora bien, como el contador marca 1, transmitimos despues del 1 un 0 y
ponemos el contador en cero. Hasta ahora, la palabra-codigo tiene la forma
1 0. Prosiguiendo con el metodo, como el primer bit de a1 y b1 es el mismo,
0, transmitimos 0 y anadimos a la derecha un 0 y un 1, respectivamente
a2 = 001100002), b2 = 011110112).
Nuevamente, el primer ´bit coincide, por lo que transmitimos el 0 y, tras
anadir por la derecha un 0 y un 1, obtenemos
a2 = 011000002) = 96,
b2 = 111101112) = 247.
Como los primeros bits son diferentes, pero los segundos iguales, proseguimos
con la codificacion recibiendo ahora el sımbolo 1.{
a3 = 96 + b152·060c = 96 = 011000002)
b3 = 96 + b152·1860
c − 1 = 140 = 100011002).
60 CAPITULO 4. OTROS SISTEMAS DE CODIFICACION
Ahora el primer bit es diferente, pero el segundo es mayor en a3 que en b3.
Ponemos el contador en 1, se elimina el primer bit de ambos extremos, se
complementa el segundo y se anade por la derecha un 0 y un 1, respectiva-
mente
a3 = 010000002), b3 = 100110012).
Otra vez se da la situacion anterior. Por tanto, ponemos el contador en 2,
eliminamos el primer bit, se complementa el segundo y se anade un 0 y un
1, respectivamente, por la derecha
a3 = 000000002) = 0,
b3 = 101100112) = 179.
A la vista de los dos primeros bits, proseguimos la codificacion con el sımbolo
final, 2 {a4 = 0 + b180·18
60c = 96 = 001101102)
b4 = 0 + b180·2760
c − 1 = 140 = 0101000002).
0 es el bit inicial de ambos, por tanto, se transmite 0 seguido de 1 1, ya que
el contador marca 2. Se pone a cero el contador, se elimina el primer bit y se
anade por la derecha un 0 y un 1 a cada uno
a4 = 011011002), b4 = 101000012).
Una vez que se ha codificado el ultimo sımbolo, se anade a la cadena ya
transmitida, 1 0 0 0 0 1 1, el codigo de a4. En definitiva, el mensaje codificado
es
1 0 0 0 0 1 1 0 1 1 0 1 1 0 0.
4.7. Decodificacion con aritmetica entera
El algoritmo de decodificacion sigue los mismos pasos que el de codifi-
cacion. A tıtulo de ejemplo, consideramos la cadena binaria, 1 0 0 0 0 1 1 0 1 1 0 1 1 0 0,
4.7. DECODIFICACION CON ARITMETICA ENTERA 61
obtenida en el apartado anterior al codificar el mensaje 3 2 1 2. Adoptamos
la misma longitud de palabra m = 8.
La decodificacion comienza tomando como marca los primeros 8 dıgitos
de la cadena codificada, es decir, s = 100001102) = 134 e inicializando el
intervalo
a = 000000002) = 0, b = 111111112) = 255.
Seguidamente, calculamos
⌊(s− a + 1) ·N − 1
b− a + 1
⌋= 31.
En la tabla de frecuencias acumuladas encontramos
27 = N2 ≤ 31 < N3 = 42,
por lo que decodificamos el primer sımbolo como 3. A continuacion actual-
izamos el intervalo
a = 0 +⌊
256·2760
⌋= 115 = 011100112)
b = 0 +⌊
256·4260
⌋− 1 = 178 = 101100102).
Vemos que el primer dıgito de a y b es diferente y el segundo es mayor en a
que en b. Entonces eliminamos el primer bit de a, b y s, complementamos el
segundo y se anade (por la derecha) un bit: un 0 para a, un 1 para b, mientras
que se incorpora a s el siguiente bit en la cadena codificada, en nuestro caso,
1. Se obtienen los valores
a = 011001102), b = 111001012), s = 100011012).
Ahora el primer bit es diferente, pero el segundo no es mayor en a que en b.
Obtenemos los valores decimales de a, b y s
a = 102, b = 229, s = 141
y calculamos ⌊(s− a + 1) ·N − 1
b− a + 1
⌋= 18.
62 CAPITULO 4. OTROS SISTEMAS DE CODIFICACION
En la tabla de frecuencias encontramos
18 = N1 ≤ 18 < N2 = 27,
lo que nos permite decodificar el segunso sımbolo como 2. Ahora actualizamos
los valores de a y b
a = 102 +⌊
128·1860
⌋= 140 = 100011002)
b = 102 +⌊
128·2760
⌋− 1 = 158 = 100111102).
El primer bit de a y b es identico, entonces lo eliminamos y anadimos a la
derecha de a y b un 0 y un 1, respectivamente. De igual forma, se elimina
el primer bit de s y se anade por la derecha el siguiente bit en la cadena
codificada, es decir, 1. Los nuevos valores son
a = 000110002), b = 001111012), s = 000110112).
De nuevo, el primer dıgito de a es identico al de b, entonces procedemos de
igual forma y obtenemos los nuevos valores
a = 001100002), b = 011110112), s = 001101102).
Nuevamente, son iguales y, repitiendo el proceso, obtenemos
a = 011000002) = 96
b = 111101112) = 247
s = 011011012) = 109.
En este momento a y b tienen el primer bit diferente y el segundo no es mayor
en a que en b; por tanto, proseguimos la decodificacion calculando
⌊(s− a + 1) ·N − 1
b− a + 1
⌋= 5.
Como
0 = N0 ≤ 5 < N1 = 18,
4.8. CODIFICACION ARITMETICA CON MATLAB 63
decodificamos el tercer sımbolo como 1 y actualizamos el intervalo
a = 96 +⌊
152·060
⌋= 96 = 011000002)
b = 96 +⌊
152cdot1860
⌋− 1 = 140 = 100011002).
a y b tienen diferente el primer bit, pero el segundo es mayor en a, entonces
eliminamos el primer bit en a, b y s, complementamos el segundo bit y anadi-
mos un bit a la derecha: a se completa con un 0, b con un 1 y s con el siguiente
bit en la cadena codificada, 1. Por tanto, tenemos los nuevos valores
a = 010000002), b = 100110012), s = 010110112).
Se da la situacion anterior otra vez, por lo que procedemos como antes y
obtenemos
a = 000000002) = 0
b = 101100112) = 179
s = 001101102) = 54.
Para decodificar el siguiente sımbolo, calculamos
⌊(s− a + 1) ·N − 1
b− a + 1
⌋= 18.
Dado que
18 = N1 ≤ 18 < N2 = 27,
podemos decodificar el cuarto y ultimo sımbolo como 2. Por lo general, la
longitud del mensaje fuente se transmite junto con el mensaje codificado, por
lo que el decodificador sabe cuando ha decodificado el ultimo sımbolo.
4.8. Codificacion aritmetica con Matlab
Matlab dispone de las dos funciones siguientes para codificar y decodificar
un codigo aritmetico: arithenco y arithdeco. Si el conjunto de sımbolos
fuente es S = {1, 2, 3, ..., n}, denotamos por F = {N1, ..., Nn} el conjunto
64 CAPITULO 4. OTROS SISTEMAS DE CODIFICACION
de las frecuencias absolutas, es decir, Nk es el numero de veces que aparece
el sımbolo k en un mensaje de longitud N =∑
k Nk. Si men es el mensaje
a codificar (una matriz fila con elementos de S), el mensaje codificado se
obtiene como se indica en el ejemplo.
Ejemplo 4.8.1. Sea S = {1, 2, 3} el conjunto de sımbolos fuente, F =
{10, 20, 70} el conjunto de frecuencias y men = [3321312] el mensaje a codi-
ficar.
Puede obtenerse el mensaje codificado con el programa
>> F = [10, 20, 70];
>> men = [3 3 2 1 3 1 2];
>> decomen = arithenco(men,F)
ans : 1 0 0 0 1 1 1 1 0 1 0 0 0 1 0 0 0 1 1 0 0.
Finalmente, para decodificar basta poner
>> arithdeco(codmen,F,length(men))
4.9. Tecnicas de diccionario
En numerosas ocasiones se da el caso de que la fuente produce determi-
nados grupos de letras con mayor frecuencia y, al contrario, otras combina-
ciones no se dan o son muy raras. Este es el caso cuando se trata con textos o
comandos de algun lenguaje de programacion, por ejemplo, LaTex. Esta car-
acterıstica puede explotarse para conseguir una mayor compresion. Lo usual
es elaborar una lista o diccionario con las combinaciones mas frecuentes de
letras del alfabeto fuente y las palabras-codigo correspondientes.
El diccionario puede ser estatico o dinamico. Cuando se tiene un buen
conocimiento a priori de la fuente en cuestion, se utiliza un diccionario es-
tatico. Por ejemplo, si se desea comprimir los datos de los estudiantes de una
universidad, hay palabras como estudiante, nombre, creditos, etc que seran
muy frecuentes. Por el contrario, si no se dispone de ese conocimiento previo
4.10. DICCIONARIOS ESTATICOS 65
de la fuente, tendremos que adquirirlo, de algun modo, en el momento de
la codificacion. Esta es la idea clave para la elaboracion de un diccionario
dinamico.
4.10. Diccionarios estaticos
Una de las formas mas comunes de crear un diccionario estatico es la
siguiente. El diccionario consta de todas las letras del alfabeto fuente junto
con las cadenas de 2 sımbolos (llamadas digrams) necesarias para completar
el tamano escogido para este.
Ejemplo 4.10.1. Supongamos que se desea crear un diccionario de tamano
256 para codificar los caracteres ASCII. Las primeras 95 entradas del dic-
cionario seran los 95 caracteres ASCII y las restantes 161 entradas seran las
parejas de caracteres mas frecuentes.
4.11. Diccionarios dinamicos
La mayorıa de las tecnicas de compresion de datos que se basan en dic-
cionarios dinamicos tienen su raız en los trabajos de J. Ziv y A. Lempel de
1977 y 1978. Estos trabajos proporcionan dos modos diferentes de constru-
ir diccionarios dinamicos y, de hecho, a partir de cada una de ellas se han
originado diversas variaciones de la idea original. A continuacion vamos a
describir como se elabora el diccionario en una variacion del metodo LZ78
debida a T. Welch, que recibe el nombre de algoritmo LZW.
El diccionario debe ser creado tanto por el codificador como por el decod-
ificador. Se inicia el metodo con un diccionario que contiene como entradas
todas las letras del alfabeto fuente. Para facilitar la explicacion, supongamos
que el alfabeto fuente es S = {a, b, c, v, &} y que deseamos codificar el men-
saje vbaab&vbaab&. Inicialmente, el diccionario tiene la forma
66 CAPITULO 4. OTROS SISTEMAS DE CODIFICACION
ındice entrada
1 &
2 b
3 a
4 c
5 v
El primer sımbolo que se recibe es v, que esta en el diccionario. Se procede
a concatenarlo con el siguiente y resulta la cadena vb. Como no pertenece a
la lista, se codifica v con el ındice que le corresponde en el diccionario (5) y
se anade a este la cadena vb como sexta entrada. Proseguimos con la cod-
ificacion considerando la letra que sigue a la que acabamos de codificar, es
decir, b. Como esta en el diccionario, se concatena con el siguiente sımbolo
y resulta la cadena ba. Como no pertenece al diccionario, codificamos b con
su ındice correspondiente (2) y se anade a la lista ba como septima entrada.
Continuamos de esta forma con la codificacion y supongamos que se ha lle-
gado hasta la segunda v ( concretamente, acabamos de anadir al diccionario
la cadena &v). En este momento, este tiene la forma siguiente:
ındice entrada
1 &
2 b
3 a
4 c
5 v
6 vb
7 ba
8 aa
9 ab
10 b&
11 & v
Llegados a este punto, procederıamos a codificar & con su ındice (1), para
4.12. CODIGOS DE TUNSTALL 67
continuar con la codificacion de v. Como v esta en el diccionario, se concatena
v con el siguiente sımbolo, lo que produce la cadena vb. Como esta en el
diccionario, se concatena con la siguiente letra del mensaje y resulta vba. Al
no estar en la lista, la anadimos como la entrada numero 12, codificamos vb
con su ındice (6) y se continua el proceso. La porcion del mensaje que hemos
codificado adopta la forma: 5233216.
Por su parte, la decodificacion consiste en ir reproduciendo los pasos que
hemos ido dando durante la codificacion (recordemos que el diccionario ini-
cial es el mismo en los dos procesos). El mensaje a decodificar comienza por
5 y vemos que esta en el diccionario y se corresponde con la letra v. Entonces
el decodificador decide que la primera letra del mensaje es v y pasa a consid-
erar el siguiente numero que es 2. Le corresponde la entrada b, de modo que
el decodificador ya conoce las dos primeras letras del mensaje: vb. Concate-
nendo con la anterior, obtiene vb. Como el decodificador debe ir formando
el diccionario de manera analoga a como lo hace el codificador, anade a su
diccionario la cadena vb como sexta entrada y pasa a considerar el siguiente
numero (3). Le corresponde la entrada a que esta en el diccionario. Entonces
la concatena con la letra que se acaba de decodificar, b, y resulta ba. La anade
a la lista como entrada numero 7 y decodifica 3 como a.
4.12. Codigos de Tunstall
Terminamos el capıtulo estudiando un codigo usado en la compresion de
datos que presenta la particularidad de que las palabras-codigo son de igual
longitud. Su principal ventaja radica en el hecho de que los errores en las
palabras-codigo no se propagan, lo que sı ocurre en el codigo de Huffman.
Logicamente, el codigo de Tunstall trata de maximizar el numero medio de
sımbolos fuente representados por cada palabra-codigo. Para facilitar su com-
prension vamos a considerar, en primer lugar, un ejemplo.
Ejemplo 4.12.1. Sea S = {a, b, c} el alfabeto fuente y P = {0.6, 0.3, 0.1}
68 CAPITULO 4. OTROS SISTEMAS DE CODIFICACION
el conjunto de probabilidades. Construir el codigo de Tunstall con palabras-
codigo de longitud 3.
El primer paso consiste en seleccionar la letra del alfabeto fuente con
mayor probabilidad. En nuestro caso, es la letra a. Seguidamente, se considera
el conjunto formado por las cadenas de longitud 2 de la forma a−, junto con
las de longitud 1 distintas de a. La tabla muestra cada una de estas cadenas
junto con la probabilidad que les corresponde.
cadenas probabilidades
b 0.3
c 0.1
aa 0.36
ab 0.18
ac 0.06
Ahora se selecciona la cadena con mayor probabilidad de la tabla anterior.
Se trata de la palabra aa cuya probabilidad es 0.36. Creamos un segundo
conjunto de cadenas eliminando en el anterior la cadena aa y anadiendo
todas las palabras de longitud 3 de la forma aa−:
{b, c, ab, ac, aaa, aab, aac}.
El conjunto resultante tiene 7 elementos por lo que puede codificarse (en
binario) con palabras-codigo de longitud 3.
Para abordar un caso generico, supongamos que el alfabeto fuente S tiene
n sımbolos y deseamos determinar el codigo de Tunstall con palabras-codigo
de longitud L. El numero maximo de palabras-codigo es igual a 2L. Inicial-
mente, la tabla tiene la forma
cadenas probabilidades
a1 p1
a2 p2
... ...
an pn
4.13. PRACTICAS DE PROGRAMACION 69
Por tanto, tenemos n cadenas. En el primer paso anadimos n cadenas de
longitud 2 y eliminamos una de longitud 1. Es decir, tras el primer paso la
tabla contiene n+(n−1) cadenas. Notese que en cada paso ocurre lo mismo:
se anaden n−1 nuevas cadenas. Luego, despues de aplicar k veces el proceso,
tendremos una tabla provisional con n+k·(n−1) cadenas. El metodo termina
cuando k verifica las desigualdades
n + k · (n− 1) ≤ 2L y n + (k + 1) · (n− 1) > 2L.
4.13. Practicas de Programacion
1. Elaborar un programa de Matlab para codificar y decodificar un men-
saje de longitud arbitraria:
a) con el codigo aritmetico y aritmetica entera
b) con un codigo de Tunstall
c) con un diccionario estatico
d) con un diccionario dinamico (algoritmo LZW)