Saltar al contenido
El bit perdido
Newsletter

Lección 8 de 11

Codificar códigos cíclicos: del polinomio generador a los CRC

Codifica con un polinomio generador, de forma sistemática o no, comprueba palabras con el polinomio de control y detecta errores con el resto de una división.

Borrador: pendiente de que lo revise el autor. Esta página no aparece en Google.

Al terminar sabrás:

  • Codificar un mensaje multiplicando por g(x)
  • Codificar de forma sistemática con el resto de x^(n-k) m(x) entre g(x)
  • Obtener h(x) y las matrices generatriz y de paridad de un cíclico
  • Calcular el síndrome como un resto y corregir un error en Hamming

Si sabes multiplicar matrices, resolver un sistema de ecuaciones lineales y operar con polinomios (sumar, multiplicar, dividir), puedes seguirlo. Lo demás (aritmética módulo 2, subespacios, cuerpos finitos) se explica sobre la marcha.

Ya sabes qué es un código cíclico: sus palabras son los múltiplos de un generador g(x)g(x), divisor de xn−1x^n - 1. Queda lo práctico: ¿cómo se codifica, se comprueba y se corrige? Todo se reduce a multiplicar y dividir polinomios. Y verás qué hay detrás de la palabra «CRC» de tantos archivos y protocolos de red.

Seguimos numerando desde 0: c=(c0,…,cn−1)↔c(x)=c0+⋯+cn−1xn−1c = (c_0, \dots, c_{n-1}) \leftrightarrow c(x) = c_0 + \dots + c_{n-1}x^{n-1}. Trabajamos con el Hamming cíclico [7,4,3][7,4,3] de la lección anterior, con g(x)=1+x+x3g(x) = 1 + x + x^3.

La idea

Hay dos maneras de pasar de 4 bits de mensaje a 7 de palabra.

  1. Multiplicar. Ves el mensaje como un polinomio m(x)m(x) de grado menor que 4 y calculas c(x)=m(x)g(x)c(x) = m(x)g(x). Es inmediato, pero el mensaje queda «mezclado» en la palabra.
  2. Dividir. Pones el mensaje en las últimas posiciones y rellenas las primeras con la redundancia justa para que el polinomio sea múltiplo de gg. La redundancia es el resto de una división, y el mensaje se lee al final de la palabra.

La segunda es la codificación sistemática, la misma idea que la forma [Ik∣P][I_k \mid P] de la lección 4, pero con polinomios. Ojo: aquí la redundancia va delante y el mensaje detrás, al revés que en la lección 4; es solo una convención. Es la idea de los CRC.

Codificación no sistemática

El código es C={ m(x)g(x) }C = \{\,m(x)g(x)\,\}. Para el mensaje m=(1,0,1,1)m = (1,0,1,1) tenemos m(x)=1+x2+x3m(x) = 1 + x^2 + x^3 y

c(x)=(1+x2+x3)(1+x+x3)=1+x+x2+x3+x4+x5+x6,c(x) = (1 + x^2 + x^3)(1 + x + x^3) = 1 + x + x^2 + x^3 + x^4 + x^5 + x^6,

es decir, c=(1,1,1,1,1,1,1)c = (1,1,1,1,1,1,1) (x3x^3 aparece tres veces y en módulo 2 queda una). El mensaje 10111011 no se ve por ninguna parte. Es lo mismo que calcular mGmG con la matriz generatriz cíclica, cuyas filas son g,xg,x2g,x3gg, xg, x^2g, x^3g:

G=(1101000011010000110100001101).G = \begin{pmatrix}1&1&0&1&0&0&0\\0&1&1&0&1&0&0\\0&0&1&1&0&1&0\\0&0&0&1&1&0&1\end{pmatrix}.

Multiplicar por m(x)m(x) es sumar las filas que indica mm: aquí m=(1,0,1,1)m = (1,0,1,1) suma las filas 1, 3 y 4.

Codificación sistemática

Queremos una palabra «redundancia + mensaje», con el mensaje en los kk últimos coeficientes. Receta:

  1. Calcula xn−km(x)x^{n-k}m(x): es colocar el mensaje en las kk últimas posiciones.
  2. Divide entre g(x)g(x) y quédate con el resto r(x)r(x), de grado menor que n−kn-k.
  3. La palabra es c(x)=xn−km(x)+r(x)c(x) = x^{n-k}m(x) + r(x) (en módulo 2, sumar es restar).

¿Por qué es múltiplo de gg? Si xn−km=q g+rx^{n-k}m = q\,g + r, entonces xn−km+r=q gx^{n-k}m + r = q\,g. Y como rr tiene grado menor que n−kn-k, solo toca las primeras posiciones y no estropea el mensaje.

Para m=(1,0,1,1)m = (1,0,1,1), con n−k=3n - k = 3:

  • x3m(x)=x3+x5+x6x^3m(x) = x^3 + x^5 + x^6.
  • Dividimos entre g=x3+x+1g = x^3 + x + 1: restamos x3gx^3 g (queda x4+x5x^4 + x^5), luego x2gx^2 g (queda x2+x3+x4x^2+x^3+x^4), luego x gx\,g (queda x+x3x + x^3) y por último gg (queda 11).
  • El resto es r(x)=1r(x) = 1.
  • Palabra: c(x)=1+x3+x5+x6c(x) = 1 + x^3 + x^5 + x^6, es decir, c=(1,0,0,1,0,1,1)c = (1,0,0,1,0,1,1).

Los 3 primeros símbolos, 100100, son la redundancia y los 4 últimos, 10111011, el mensaje. Comprobación: al dividir c(x)c(x) entre gg el resto es 0 (es la división del ejemplo «que sí» de la lección anterior).

El polinomio de control

El polinomio de control es h(x)=(xn−1)/g(x)h(x) = (x^n - 1)/g(x). Para nuestro código,

h(x)=1+x+x2+x4,g(x)h(x)=x7−1.h(x) = 1 + x + x^2 + x^4, \qquad g(x)h(x) = x^7 - 1.

Comprueba palabras: cc está en el código si y solo si c(x)h(x)≡0(modxn−1)c(x)h(x) \equiv 0 \pmod{x^n-1}. Si c=m gc = m\,g, entonces c h=m g h=m(xn−1)c\,h = m\,g\,h = m(x^n - 1), que vale 0 cuando xn=1x^n=1. Y al revés: si c h=Q (xn−1)=Q g hc\,h = Q\,(x^n-1) = Q\,g\,h, entonces c=Q gc = Q\,g.

También da la matriz de paridad. Escribe los coeficientes de hh al revés, de h4h_4 a h0h_0: 1,0,1,1,11,0,1,1,1. Las filas de HH son esa lista desplazada:

H=(101110001011100010111).H = \begin{pmatrix}1&0&1&1&1&0&0\\0&1&0&1&1&1&0\\0&0&1&0&1&1&1\end{pmatrix}.

¿Por qué? Cada entrada de GHTGH^T resulta ser un coeficiente de g(x)h(x)=x7+1g(x)h(x) = x^7+1 de grado entre 1 y 6, y todos ellos son 0. Así que GHT=0GH^T = 0. Cuidado: no es la HH del hilo, porque este código tiene las posiciones en otro orden (es equivalente, no igual).

El síndrome es un resto

Si recibes r(x)=c(x)+e(x)r(x) = c(x) + e(x), con cc palabra y ee el error, entonces el resto de dividir entre gg es

s(x)=r(x) mod g(x)=e(x) mod g(x),s(x) = r(x) \bmod g(x) = e(x) \bmod g(x),

porque cc es múltiplo de gg y su resto es 0. El síndrome es el resto de dividir entre gg y solo depende del error, igual que en la lección 6. Basta una división, que un circuito con registros de desplazamiento hace al vuelo.

Ojo: hay dos síndromes, el vector HrTHr^T de la lección 6 y este resto s(x)s(x). Son objetos distintos, pero guardan la misma información: dos palabras recibidas tienen el mismo HrTHr^T si y solo si tienen el mismo resto (en ambos casos, si y solo si su diferencia está en el código).

Un error en la posición ii es e(x)=xie(x) = x^i. Los restos de xix^i entre g=1+x+x3g = 1+x+x^3 son:

posición ii0123456
xi mod gx^i \bmod g11xxx2x^21+x1+xx+x2x+x^21+x+x21+x+x^21+x21+x^2

Los 7 restos son distintos y no nulos (son los 7 polinomios no nulos de grado menor que 3): el síndrome señala la posición del error.

CRC: detectar con el mismo truco

Los CRC (comprobación de redundancia cíclica) son, en esencia, la codificación sistemática de arriba, con un g(x)g(x) elegido para detectar y mensajes larguísimos. El emisor ve la trama como un polinomio, calcula el resto de dividir xdeg⁡gm(x)x^{\deg g}m(x) entre g(x)g(x) y lo añade como redundancia. (Se transmite primero el coeficiente de mayor grado, así que el resto, de grados bajos, va al final de la trama.) El receptor divide lo que le llega; si el resto no es cero, hay un error y el dato no se acepta: Ethernet descarta la trama y un descompresor ZIP avisa de que el archivo está dañado. Los estándares reales, como el CRC-32 de Ethernet y ZIP, añaden detalles (un valor inicial y un complemento final) que no cambian la idea. En el ejercicio 3 calculas un CRC a mano.

Una ráfaga de longitud ℓ\ell es un error cuyas posiciones dañadas caben en un tramo de ℓ\ell símbolos seguidos (no tienen por qué cambiar todos). Si el término independiente de gg es 1, se detecta toda ráfaga de longitud menor o igual que deg⁡g\deg g, sea cual sea la longitud del mensaje. La razón: esa ráfaga es xib(x)x^i b(x) con b≠0b \neq 0 y deg⁡b<deg⁡g\deg b < \deg g; como gg no tiene factor xx, para dividir a xibx^i b tendría que dividir a bb, y no puede. Sin esa condición falla: g=x3+x2g = x^3 + x^2 divide a la ráfaga x6+x5x^6 + x^5. Los generadores de códigos cíclicos y de CRC estándar la cumplen.

Ejemplo resuelto

Enviamos m=(1,0,1,1)m = (1,0,1,1) con el código sistemático y hay un error en la posición 4.

1. Palabra enviada. Como arriba, c=(1,0,0,1,0,1,1)c = (1,0,0,1,0,1,1).

2. Palabra recibida. El error cambia el coeficiente de x4x^4: r=(1,0,0,1,1,1,1)r = (1,0,0,1,1,1,1), es decir, r(x)=1+x3+x4+x5+x6r(x) = 1 + x^3 + x^4 + x^5 + x^6.

3. Síndrome. Divide r(x)r(x) entre g(x)=1+x+x3g(x) = 1 + x + x^3:

  • Resta x3g=x3+x4+x6x^3g = x^3 + x^4 + x^6: queda 1+x51 + x^5.
  • Resta x2g=x2+x3+x5x^2g = x^2 + x^3 + x^5: queda 1+x2+x31 + x^2 + x^3.
  • Resta gg: queda x+x2x + x^2.

El resto es s(x)=x+x2≠0s(x) = x + x^2 \neq 0: hay un error.

4. Posición. En la tabla, x+x2x + x^2 es el resto de x4x^4. Error en la posición 4.

5. Corrección. Cambia r4r_4: (1,0,0,1,0,1,1)(1,0,0,1,0,1,1), la palabra enviada. Sus 4 últimos símbolos dan el mensaje, 10111011.

Ejercicios

Ejercicio 1

Codifica de forma sistemática el mensaje m=(0,1,1,1)m = (0,1,1,1) con g(x)=1+x+x3g(x) = 1 + x + x^3.

Ver la solución

m(x)=x+x2+x3m(x) = x + x^2 + x^3, luego x3m(x)=x4+x5+x6x^3 m(x) = x^4 + x^5 + x^6. Divide entre gg:

  • Resta x3g=x3+x4+x6x^3g = x^3 + x^4 + x^6: queda x3+x5x^3 + x^5.
  • Resta x2g=x2+x3+x5x^2g = x^2 + x^3 + x^5: queda x2x^2.

El resto es r(x)=x2r(x) = x^2. La palabra es c(x)=x2+x4+x5+x6c(x) = x^2 + x^4 + x^5 + x^6, es decir, c=(0,0,1,0,1,1,1)c = (0,0,1,0,1,1,1): redundancia 001001 y mensaje 01110111.

Ejercicio 2

Con la matriz de paridad HH de esta lección (la del código g=1+x+x3g = 1+x+x^3), decide si 10111001011100 y 10111011011101 son palabras del código. Si alguna no lo es, di qué columna de HH aparece en el síndrome.

Ver la solución

Cada componente de HrTHr^T es el producto escalar de una fila de HH con rr, módulo 2. Las filas de HH tienen unos en {0,2,3,4}\{0,2,3,4\}, {1,3,4,5}\{1,3,4,5\} y {2,4,5,6}\{2,4,5,6\}.

Para r=1011100r = 1011100 (unos en 0,2,3,40,2,3,4) los solapes son {0,2,3,4}\{0,2,3,4\}, {3,4}\{3,4\} y {2,4}\{2,4\}, de tamaños 4, 2 y 2: todos pares. El síndrome es (0,0,0)T(0,0,0)^T, luego es palabra del código.

Para r=1011101r = 1011101 (unos en 0,2,3,4,60,2,3,4,6) los solapes tienen tamaños 4, 2 y 3. El síndrome es (0,0,1)T≠0(0,0,1)^T \neq 0, así que no es palabra. Es la última columna de HH, la de la posición 6: es la palabra anterior con un error ahí.

Ejercicio 3

Calcula a mano un CRC de 3 bits con g(x)=x3+x+1g(x) = x^3+x+1 para el mensaje de 8 bits 1101001111010011, escrito como se transmite (del coeficiente de mayor grado al de menor). Comprueba después que la trama completa da resto 0.

Ver la solución

El mensaje es m(x)=x7+x6+x4+x+1m(x) = x^7 + x^6 + x^4 + x + 1, y g=x3+x+1g = x^3 + x + 1 se escribe 10111011 (ojo: aquí los bits van de mayor a menor grado, como en los CRC; en el resto de la lección, gg era 11011101, de menor a mayor). Multiplicar por x3x^3 es añadir tres ceros: 1101001100011010011000. Divide: pon 10111011 bajo el primer 1, suma módulo 2 cifra a cifra (sin llevadas) y repite hasta que queden menos de 4 cifras.

11010011000
1011
 1100011000
 1011
  111011000
  1011
   10111000
   1011
       1000
       1011
        011

El resto es 011011, es decir, r(x)=x+1r(x) = x + 1: ese es el CRC. La trama enviada es 11010011 01111010011\,011.

El receptor divide 1101001101111010011011 entre 10111011: los pasos son los mismos, pero al final queda 10111011 en lugar de 10001000, y 1011+1011=01011 + 1011 = 0. Resto 0: trama aceptada. Si cambia un bit (una ráfaga de longitud 1), el resto deja de ser 0.

En resumen

  • No sistemática: c(x)=m(x)g(x)c(x) = m(x)g(x), o sea, mGmG con GG de filas g,xg,…g, xg, \dots
  • Sistemática: c(x)=xn−km(x)+r(x)c(x) = x^{n-k}m(x) + r(x), con rr el resto de dividir xn−kmx^{n-k}m entre gg. El mensaje se lee al final.
  • El polinomio de control h=(xn−1)/gh = (x^n-1)/g comprueba palabras (c h≡0c\,h \equiv 0) y da la matriz de paridad.
  • El síndrome es el resto de dividir entre gg; en Hamming cada resto xi mod gx^i \bmod g es distinto y señala la posición del error.
  • Los CRC usan este mecanismo para detectar errores en datos largos. Si g(0)=1g(0) = 1, detectan toda ráfaga de longitud hasta deg⁡g\deg g.

Siguiente lección: Códigos Reed-Solomon

Para profundizar