Unidad 6 · Los códigos BCH · por qué 2t raíces consecutivas garantizan distancia 2t + 1: la H sobre GF(2ᵐ), la prueba por la Vandermonde, cuándo la distancia real es mayor, y por qué la familia no aguanta bloques largos
Un código BCH se diseña pidiendo raíces: potencias consecutivas de un elemento de orden . Nadie mira las palabras, y sin embargo la distancia mínima queda garantizada antes de escribir la primera. La garantía es la cota BCH, y su prueba entera cabe en un determinante.
Sea una palabra del código. Es múltiplo del generador, y el generador se anula en las raíces pedidas, así que también:
Son ecuaciones lineales en los bits , con coeficientes en . Escritas como :
La fila son las potencias de , y la columna son las potencias de : la posición del bloque. Hace el trabajo de una matriz de paridad —las palabras son exactamente su núcleo— pero no es una en el sentido de la Unidad 3: sus entradas no son bits y sus filas pueden ser dependientes. Si una raíz pedida es conjugada de otra, su fila sobra: la fila de es la de elevada al cuadrado, y una palabra binaria que anula una anula la otra.
Escribiendo cada entrada como su columna de bits sale una matriz binaria de filas, y su rango es . Medido sobre : el (15,7) da 16 filas binarias de rango 8, y el (15,5), 24 de rango 10. Quedándose sólo con las filas de exponente impar, como en el ejemplo 6.2 de Lin y Costello, son 8 de rango 8 y 12 de rango 10: en el (15,5) la fila de aporta 2 bits y no 4, porque su polinomio mínimo tiene grado 2.
Al número se lo llama distancia diseñada. La cota BCH, el teorema 1 de la unidad, dice que es un piso:
El enunciado no depende de ni de que sea primitivo, y vale más allá de la familia: todo código cíclico cuyo generador tenga entre sus raíces potencias consecutivas de un elemento de orden tiene . Por eso conviene mirar todas las raíces del generador y no sólo las pedidas: si la conjugación agregó otras, la tira consecutiva más larga puede ser más larga que .
Paso 1: alcanza con el peso. El código es lineal, así que su distancia mínima es el menor peso de una palabra no nula. Hay que probar que no existe ninguna palabra no nula de peso . Se supone que existe y se llega a un absurdo.
Paso 2: quedarse con sus columnas. Sea esa palabra, con sus componentes no nulas en las posiciones . En cada ecuación de la sección 01 sólo sobreviven esos términos:
Paso 3: un sistema cuadrado. Como , se pueden tomar sólo las primeras ecuaciones. Queda un sistema homogéneo de , con la matriz
El sistema es , y el vector de incógnitas no es nulo: sus componentes son, por definición, las no nulas de . Un sistema homogéneo con solución no trivial tiene determinante cero, así que .
Paso 4: sacar un factor por columna. La columna de es : de una fila a la siguiente el exponente crece en uno, y eso multiplica por . El determinante es lineal en cada columna:
Paso 5: es una Vandermonde. La matriz que quedó tiene en cada columna las potencias de un solo elemento, el nodo . Es una matriz de Vandermonde, y su determinante es el producto de las diferencias de los nodos. En restar es sumar:
Paso 6: los nodos son distintos. Las posiciones cumplen , y tiene orden exactamente : sus primeras potencias son distintas dos a dos. Ningún factor es cero, y en un cuerpo un producto de no nulos no es nulo. Los factores de columna tampoco: son potencias de .
Paso 7: el absurdo. Por los pasos 4 a 6, ; por el paso 3, . No hay palabra no nula de peso , y . Dicho en columnas: cualquier conjunto de o menos columnas de es linealmente independiente.
La fuerza del argumento está en un solo lugar: la consecutividad. Que los exponentes de las filas sean es lo que deja, en el paso 4, el mismo multiplicador de fila a fila dentro de cada columna, y eso es lo que arma la Vandermonde. Con filas salteadas la cuenta no sale, y el determinante sí puede anularse. En el (15,5), con las filas de y y las columnas 0 y 5:
porque . Recorridas todas las elecciones de columnas del (15,5), con las primeras filas y de 1 a 6, son 9948 submatrices y ninguna da cero. Con las filas y , 15 de los 105 pares de columnas dan cero. Con y , que también están salteadas, ninguno: son potencias consecutivas de , que tiene orden 15 igual que , y la prueba corre con en su lugar.
Y el límite del argumento está a la vista: de las ecuaciones usa sólo , y de las raíces del generador usa sólo una tira. Todo lo demás que dice se tira, y por eso la cota puede quedar floja.
Arranca sin columnas. Elegí dos o tres y mirá el determinante: después probá todas las del mismo tamaño. Prendé el interruptor, quedate con las filas de y , y buscá dos columnas que lo anulen; después cambiá a y . Al final pedí una palabra de peso : sus columnas suman cero, pero ninguna submatriz cuadrada de lo puede mostrar, porque no hay filas.
La cota es una desigualdad, y hay tres situaciones. Las tres se midieron recorriendo las palabras de cada código.
Igualdad. El (15,7) tiene y el (15,5), : exactamente . En los quince códigos BCH primitivos de sentido estricto de largo 15, 31 y 63 con , la distancia mínima es justo la tira más larga de raíces consecutivas más uno.
Desigualdad estricta por conjugación. La distancia supera la pedida, pero la cota la ve si se le da la tira entera. Sobre , pedir con son las raíces y , pero sus clases traen también y : el (31,21) tiene una tira de cuatro y , no 3. Pidiendo sale el (31,11), con una tira de diez y , no 9. Se detecta mirando las raíces del generador, contando la tira módulo .
Desigualdad estricta genuina. La distancia supera también a la tira más larga, y la cota no la ve de ninguna manera. Sobre con , tiene orden 23, porque . Pidiendo , las cuatro raíces caen en una sola clase de once exponentes:
El generador es y el código es un (23,12). La tira más larga es 1, 2, 3, 4: la cota garantiza 5. Recorridas las 4096 palabras, . Es el código de Golay: su generador es el recíproco de , el mismo código leído al revés. Ver estos casos pide cotas más finas, que combinan varias tiras de raíces en lugar de una sola: las de Hartmann y Tzeng y la de Roos son las más conocidas.
En los tres casos la garantía de diseño sigue en pie: el decodificador que se construye sobre las raíces corrige errores, sea cual fuere la distancia verdadera. Lo que corrige de más una distancia mayor, ese decodificador no lo aprovecha.
El teorema 3 de la unidad pone el límite de la familia: no existe una sucesión de códigos BCH primitivos con la tasa y la distancia relativa las dos acotadas lejos de cero cuando . Al alargar el bloque con la tasa fija, la fracción de errores corregibles, , se va a cero.
La idea detrás es el costo de cada error. Mientras las clases de los exponentes impares hasta son completas y distintas, cada error corregible cuesta exactamente bits de paridad: es el teorema 2, , con igualdad. Con la tasa fija hay bits para gastar, y si cada error costara alcanzarían para
Al crecer las clases empiezan a coincidir y algunos errores salen más baratos, pero no alcanza: el del denominador crece con el bloque. Medido sobre los BCH primitivos de sentido estricto, tomando para cada el de mayor con tasa al menos . La dimensión sale de contar las clases ciclotómicas de los exponentes 1 a , que no dependen del polinomio primitivo, y hasta coincide con la del generador construido. es la tira más larga más uno, y en todas las filas resultó igual a :
| m | código | t | d₀ | t/n | d₀/n | t·m/n |
|---|---|---|---|---|---|---|
| 5 | (31,16) | 3 | 7 | 0,097 | 0,226 | 0,48 |
| 6 | (63,36) | 5 | 11 | 0,079 | 0,175 | 0,48 |
| 7 | (127,64) | 10 | 21 | 0,079 | 0,165 | 0,55 |
| 8 | (255,131) | 18 | 37 | 0,071 | 0,145 | 0,56 |
| 10 | (1023,513) | 57 | 115 | 0,056 | 0,112 | 0,56 |
| 11 | (2047,1024) | 106 | 213 | 0,052 | 0,104 | 0,57 |
| 12 | (4095,2057) | 198 | 397 | 0,048 | 0,097 | 0,58 |
| 14 | (16383,8200) | 691 | 1383 | 0,042 | 0,084 | 0,59 |
| 16 | (65535,32771) | 2477 | 4955 | 0,038 | 0,076 | 0,61 |
La última columna es la paridad que haría falta si cada error costara bits, como fracción de . Con tasa la paridad real no pasa de 0,5, y la columna apenas la supera: de 0,48 a 0,61 mientras va de 5 a 16. Los errores salen algo más baratos que bits, pero no tanto como para compensar que crece. Por eso baja de 0,097 a 0,038. El largo 15 queda afuera: el (15,7) ya tiene tasa 0,467, y arriba de un medio sólo está el (15,11), de .
La comparación que importa es con lo que existe. La cota de Varshamov-Gilbert asegura que, con tasa , hay códigos binarios cuya distancia relativa tiende a 0,110, el que cumple . La distancia que garantiza la cota BCH la cruza hacia abajo entre y , y sigue bajando. Lo medido es la distancia garantizada. El teorema dice más: tampoco la distancia verdadera acompaña, y esa prueba es bastante más larga. El lugar de la familia son los bloques cortos y medianos con tasa alta, donde la garantía de distancia y la decodificación algebraica son difíciles de igualar.
Las submatrices del (15,5), recorridas todas, con armado desde la tabla de potencias de y el determinante por eliminación. Lo de los comentarios es la salida de correrlo.
from itertools import combinations
# GF(2^4) con p(X) = 1 + X + X^4: exp[i] es α^i como entero de 4 bits.
exp = [1]
for _ in range(14):
x = exp[-1] << 1
exp.append(x ^ 0b10011 if x & 0b10000 else x)
log = {v: i for i, v in enumerate(exp)}
def mul(a, b):
return 0 if a == 0 or b == 0 else exp[(log[a] + log[b]) % 15]
def inv(a):
return exp[-log[a] % 15]
def det(M):
"""Determinante sobre GF(2^4) por eliminación: la suma es XOR."""
M, d = [f[:] for f in M], 1
for c in range(len(M)):
p = next((i for i in range(c, len(M)) if M[i][c]), None)
if p is None:
return 0
M[c], M[p] = M[p], M[c]
d = mul(d, M[c][c])
for i in range(c + 1, len(M)):
f = mul(M[i][c], inv(M[c][c]))
M[i] = [a ^ mul(f, b) for a, b in zip(M[i], M[c])]
return d
def ceros(filas, n=15):
"""Cuántas elecciones de w = len(filas) columnas dan determinante cero."""
w, total, nulos = len(filas), 0, 0
for cols in combinations(range(n), w):
M = [[exp[(e * i) % 15] for i in cols] for e in filas]
total += 1
nulos += det(M) == 0
return nulos, total
# El (15,5): t = 3, las filas de H son β^1 ... β^6, con β = α.
for w in range(1, 7):
print(w, ceros(range(1, w + 1)))
print('{1,3}', ceros([1, 3]))
print('{1,4}', ceros([1, 4]))
# 1 (0, 15)
# 2 (0, 105)
# 3 (0, 455)
# 4 (0, 1365)
# 5 (0, 3003)
# 6 (0, 5005)
# {1,3} (0, 105)
# {1,4} (15, 105)
Las seis primeras líneas son la cota: submatrices, ninguna singular. El determinante se calcula entero, sin usar la fórmula de la Vandermonde: que nunca dé cero no está puesto por construcción. Las dos últimas son la sección 04: salteadas de a dos, las filas siguen siendo una tira de potencias de ; de a tres, ya no.