Unidad 3 · Códigos de bloque lineales · el subespacio, la tasa, la matriz generadora, la forma sistemática y las 16 palabras del (7,4)
Por un canal de bits pueden pasar palabras. Un código declara válidas sólo , que alcanzan justo para los mensajes de bits; las otras quedan prohibidas, y si llega una, hubo error. Toda la teoría de los códigos de bloque es elegir bien ese subconjunto. Un código lineal pide una sola cosa más: que el subconjunto sea un subespacio. Con eso alcanzan vectores para describirlo entero, y codificar pasa a ser un producto de un vector por una matriz.
Un código de bloque lineal sobre es un subespacio de dimensión de , el espacio de las -tuplas binarias. Sus elementos son las palabras de código. es la longitud de bloque, la cantidad de bits de información, y los que sobran son redundancia, o paridad. La tasa es la fracción del flujo que es información:
El ejemplo de toda la unidad es el Hamming : 16 palabras válidas entre 128, una de cada ocho, y . De cada siete bits que viajan, cuatro son del usuario. Es el mismo Hamming que cruza a no codificar en 5,85 dB.
De ser un subespacio salen dos propiedades que se usan todo el tiempo:
Sobre esas dos son la definición entera, no una consecuencia. Los únicos escalares son 0 y 1, así que multiplicar por un escalar no agrega ninguna exigencia; y la primera sale de la segunda, porque para cualquier . Un conjunto no vacío de vectores binarios es un código lineal si y sólo si es cerrado para la suma. El conjunto {0000, 1100, 1010, 0111} tiene cuatro palabras, , pero no es lineal: 1100 + 1010 = 0110 no está.
La segunda propiedad tiene un costado que rinde mucho más adelante. Sumarle una palabra fija a todas las palabras del código las devuelve a todas, sólo que en otro orden: el resultado está en el código por la suma cerrada, y dos palabras distintas no pueden ir a parar a la misma. El código se ve igual desde cualquiera de sus palabras, y por eso para analizar los errores alcanza con suponer que se transmitió la nula: es lo que hace que la distancia mínima se lea como un peso.
Un subespacio de dimensión tiene una base de vectores linealmente independientes, . Puestos como filas forman la matriz generadora , de . El mensaje se codifica como
Leído bit a bit: cada elige la fila , y la palabra es el XOR de las filas elegidas. Con eso la suma cerrada se ve en una línea: si y , entonces : la suma de dos palabras es la palabra de la suma de los mensajes.
Lo que cuesta. El codificador no guarda las palabras: guarda las entradas de . Para el del trabajo final es la diferencia entre una tabla de palabras, que no entra en ningún universo, y 60.945 bits. Ésa es la razón de pedir linealidad: no es una comodidad matemática, es lo que vuelve al código implementable.
Las filas tienen que ser independientes. Si una fila es suma de otras, dos mensajes distintos caen en la misma palabra. Con las filas del pero la cuarta cambiada por , el mensaje 1101 suma , la misma palabra que 0000. Los 16 mensajes dan sólo 8 palabras distintas, cada una dos veces, y el receptor no tiene forma de saber cuál de los dos se mandó.
La base no es única. Cualquier otra base del mismo subespacio da otra con el mismo código: cambia qué palabra le toca a cada mensaje, no el conjunto de palabras. Cuántas hay se cuenta eligiendo las filas en orden, cada una fuera del subespacio que generan las anteriores:
El tiene 20.160 matrices generadoras, y recorriendo todas las cuaternas de palabras no nulas e independientes salen exactamente ésas. Todas codifican el mismo conjunto de 16 palabras, y las capacidades de detectar y corregir dependen sólo del conjunto. Lo que decide cuál usar es la comodidad.
De todas esas matrices, hay una que se prefiere. está en forma sistemática cuando se escribe
con la identidad de y de . Desarrollando con esa forma, el mensaje sale intacto en las primeras posiciones y detrás vienen bits de paridad:
Cada bit de paridad es el XOR de los bits de mensaje que marca la columna de : una ecuación de paridad. Todo el diseño del código vive en . La ventaja es del receptor: si no hubo errores, lee el mensaje directamente, sin deshacer ninguna transformación. Y la matriz de paridad sale sin hacer cuentas, .
Es una sola. De las 20.160 del , la sistemática es exactamente una, y no por casualidad: si las primeras cuatro posiciones de tienen que repetir , la fila tiene que ser la única palabra del código que empieza con un 1 en la posición y ceros en las otras tres. No queda nada para elegir. La convención de poner el mensaje adelante sí es una elección, y en toda la unidad se usa ésta.
La del , con las posiciones de 0 a 6 de izquierda a derecha:
Leyendo las tres columnas de de arriba abajo salen las tres ecuaciones de paridad:
En hardware. El codificador del RTL del curso es exactamente eso. Los cuatro bits de mensaje pasan como cables a las posiciones 0 a 3 de la salida, y la paridad son tres asignaciones, una por columna de . El bit de cada bus es la posición : i_info[i] es y parity[j] es , que va a la posición .
assign parity[0] = i_info[0] ^ i_info[2] ^ i_info[3]; assign parity[1] = i_info[0] ^ i_info[1] ^ i_info[2]; assign parity[2] = i_info[1] ^ i_info[2] ^ i_info[3];
Cada columna de tiene tres unos, así que cada bit de paridad es un XOR de tres entradas, y el codificador entero es combinacional: cuatro cables y tres compuertas, sin un solo registro. Simulado sobre los 16 mensajes, entrega las mismas 16 palabras que .
Con u = 0000 no hay ninguna fila elegida y la palabra es la nula. Prendé y : se suman y , y sale 1001 011, con el mensaje adelante y la paridad atrás. Guardala, armá 0110 y mirá la suma: 1111 111, que es la palabra de 1111. Probá con las que quieras: no hay suma de dos palabras que se salga del código. Y prendé la otra base, la que cambia por : el mismo 1001 sale 1101 000, y las primeras cuatro posiciones ya no son el mensaje. De los 16 mensajes, 8 cambian de palabra, pero las palabras que aparecen en la grilla son las mismas 16. Cambió la correspondencia, no el código.
Los cuatro primeros bits son el mensaje; los tres últimos, la paridad. La columna es el peso, la cantidad de unos de la palabra:
| u | v | w | u | v | w |
|---|---|---|---|---|---|
| 0000 | 0000 000 | 0 | 0110 | 0110 100 | 3 |
| 1000 | 1000 110 | 3 | 0101 | 0101 110 | 4 |
| 0100 | 0100 011 | 3 | 0011 | 0011 010 | 3 |
| 0010 | 0010 111 | 4 | 1110 | 1110 010 | 4 |
| 0001 | 0001 101 | 3 | 1101 | 1101 000 | 3 |
| 1100 | 1100 101 | 4 | 1011 | 1011 100 | 4 |
| 1010 | 1010 001 | 3 | 0111 | 0111 001 | 4 |
| 1001 | 1001 011 | 4 | 1111 | 1111 111 | 7 |
Una es de peso 0, siete de peso 3, siete de peso 4 y una de peso 7. La más liviana que no es nula tiene tres unos, y eso, por la suma cerrada, es lo mismo que decir que dos palabras distintas difieren siempre en tres posiciones o más: es la distancia mínima del código, y lo que le permite corregir un error. Las cuatro filas de están en la tabla —son las palabras de 1000, 0100, 0010 y 0001— y las otras doce son sumas de ellas.
El apunte dice que toda de rango se lleva a con operaciones de fila y, si hace falta, permutando columnas. Ese «si hace falta» tiene un precio. Las operaciones de fila cambian la base y dejan el código igual; permutar columnas cambia el código.
El caso más chico: el {0000, 1100, 0011, 1111}. En todas sus palabras las posiciones 0 y 1 son iguales, así que ninguna empieza con 10 y el mensaje no puede ir intacto ahí. Escalonando sus filas, los pivotes caen en las columnas 0 y 2, no en 0 y 1. Intercambiando las posiciones 1 y 2 sale {0000, 1010, 0101, 1111}, que sí tiene . Es un código equivalente: los mismos pesos, las mismas distancias, la misma capacidad de corregir. Pero son otras palabras, y un decodificador escrito para uno no sirve para el otro sin deshacer la permutación.
El también tiene posiciones donde el mensaje no entra. De las 35 formas de elegir cuatro posiciones, 28 sirven para llevar el mensaje intacto y 7 no. Las siete que fallan son las que dejan afuera, exactamente, las tres posiciones de una palabra de peso 3. Esa palabra vale cero en las cuatro elegidas, igual que la nula, y si dos palabras distintas coinciden ahí, esas cuatro posiciones no pueden distinguir 16 mensajes. Por ejemplo, 0100 011 tiene sus unos en 1, 5 y 6: las posiciones 0, 2, 3 y 4 no alcanzan.