Unidad 6 · Los códigos BCH · se piden raíces y sale el código: la definición, los dos cuerpos, el diseño en cuatro pasos, los cuatro ejemplos, la tira más larga, el catálogo y cuánta redundancia cuesta cada error
La Unidad 5 arma todos los códigos cíclicos de un largo factorizando , pero no dice cuál corrige más: la distancia se conoce recién al enumerar. Los códigos BCH dan vuelta el orden. Se fija cuántos errores se quieren corregir, se piden raíces consecutivas en un cuerpo de extensión, y el polinomio generador sale de esas raíces con la garantía puesta. Los publicaron Hocquenghem en 1959 y Bose y Ray-Chaudhuri en 1960.
Sea un elemento de orden de , y un entero no negativo. El código BCH binario de longitud y distancia diseñada es el código cíclico generado por el polinomio binario de menor grado que tiene por raíces a las potencias consecutivas
Un polinomio con coeficientes en que se anula en se anula también en todos sus conjugados, así que es múltiplo del polinomio mínimo de . Para que se anule en las potencias tiene que ser múltiplo de cada uno de sus polinomios mínimos, y para que tenga el menor grado tiene que ser exactamente el mínimo común múltiplo:
El mínimo común múltiplo y no el producto, porque las potencias caen casi siempre en menos de clases conjugadas, y dos potencias de la misma clase comparten polinomio mínimo: cada uno entra una sola vez.
El código es cíclico de verdad. Como tiene orden , toda potencia de es raíz de ; sus polinomios mínimos dividen a , y su mínimo común múltiplo también. Y un divisor de genera un código cíclico de largo .
La definición se lee también al revés, como prueba de pertenencia: un polinomio binario de grado menor que es palabra si y sólo si
Si se anula en las potencias, se anula en sus conjugadas, es múltiplo de cada polinomio mínimo y por lo tanto de su MCM. Es la lectura que usa el decodificador: evaluar lo recibido en esas raíces da los síndromes.
Dos nombres. El código es de sentido estricto si , y primitivo si , o sea si es un elemento primitivo; entonces se escribe . Casi todos los BCH de uso práctico son las dos cosas.
La construcción usa dos cuerpos con papeles distintos, y confundirlos es la fuente de error más frecuente de la unidad.
, el cuerpo base, es donde viven los coeficientes de y los bits de las palabras. El código es binario: por el canal pasan ceros y unos. , el cuerpo de extensión, es donde viven las raíces de . Ningún elemento suyo aparece jamás en el canal.
De ahí una asimetría. Para codificar alcanza con el cuerpo base: es dividir polinomios binarios por , con el mismo registro de desplazamiento de cualquier cíclico, y el cuerpo de extensión no interviene. Para decodificar hace falta el de extensión, porque los síndromes son lo recibido evaluado en raíces que son elementos de . El codificador de un BCH es un codificador cíclico común; el decodificador es un procesador aritmético entero.
Paso 1: el cuerpo. Se fija la longitud y se busca el menor tal que divida a . Se toma , que tiene orden .
Paso 2: las raíces. Se fija y se escriben las potencias consecutivas de .
Paso 3: las clases. Se reparten esas potencias en clases conjugadas y se anota el polinomio mínimo de cada clase, sin repetir.
Paso 4: el producto. Se multiplican los polinomios mínimos distintos. El resultado es , y el código es un .
La dimensión no se elige: sale. Se especifican el largo y la capacidad, y la tasa queda determinada por cuántas clases hicieron falta para cubrir las raíces pedidas.
El (15,7). En con , primitivo de sentido estricto con . Las raíces pedidas son , , y . Las clases módulo 15 son y : tres de las cuatro pedidas están en y la otra en . Entran dos polinomios mínimos:
De grado 8: un (15,7). Se pidieron cuatro raíces y tiene ocho: las cuatro pedidas más , , y , que entraron por estar en las mismas clases. Enumeradas sus 128 palabras, la distancia mínima es 5: la diseñada, justa.
El (15,5). Con se piden a . A las dos clases anteriores se suma , cuyo polinomio mínimo, , tiene grado 2:
De grado 10: un (15,5), con y distribución de pesos . Es el código de referencia de toda la decodificación, y el del ejercicio resuelto de la unidad.
El (21,12), no primitivo. 21 divide a y a ningún menor, así que se trabaja en con , y se toma , de orden 21. Con las raíces pedidas son , , , , o sea , , , . Módulo 63, las clases son y : dos polinomios mínimos, de grados 6 y 3,
De grado 9: un (21,12), y divide a . Enumeradas sus 4096 palabras, . Los no primitivos agregan largos al catálogo, a cambio de trabajar en un cuerpo más grande que el que el largo pediría.
El (255,239). En con , con . Las cuatro raíces a se reparten en dos clases de ocho elementos cada una, y el generador tiene grado 16:
Un (255,239) de tasa 0,937, que corrige dos errores por bloque de 255 bits con dieciséis de redundancia. Su tiene once coeficientes no nulos, y eso es lo que cuesta su codificador en compuertas.
Y el caso más chico ya era conocido. Con primitivo y de sentido estricto, , el polinomio primitivo mismo: el BCH es el código de Hamming de ese largo, el (15,11) o el (31,26). En el widget se arranca de ahí.
Arranca en el Hamming (15,11): dos raíces pedidas, dos agregadas, una tira de dos. Subí de a uno en largo 15 y mirá cuánto crece en cada paso. Después pasá a largo 31 con y corré a 2: pedís un error y mirá la tira. Volvé a y subí hasta 4. Y probá en largo 15 con , mirando las dos últimas lecturas.
Nada obliga a tomar . En largo 31, sobre con , con y las raíces pedidas son y , de la misma clase: y el código es el Hamming (31,26). Con y se piden y , que están en clases distintas:
Un (31,21): cinco bits más de redundancia para corregir un solo error, que parece un mal negocio. No lo es. Ese es idéntico al de con , porque la clase de trajo a y a sin que nadie los pidiera, y entre las raíces quedan cuatro potencias consecutivas, de a . Enumeradas sus palabras, : el código diseñado para corregir uno corrige dos.
La regla que sale de ahí: obtenido , se busca la tira más larga de exponentes consecutivos entre todas sus raíces, no sólo la que se pidió. Si mide , la cota BCH vale con esa tira y el código tiene : esa es la distancia diseñada efectiva. La tira puede dar la vuelta por el cero, porque los exponentes se leen módulo .
es la elección habitual porque, para una misma capacidad, tiende a dar el generador de menor grado: los pares de la tira pedida caen en las clases de los impares. Pero no siempre es la óptima, y mirar el conjunto entero de raíces es parte del diseño. Cuántas veces la tira resulta más larga que la pedida, y en qué códigos, es lo que mide el ensayo Pedir t puede darte más.
Al subir con el largo fijo, baja a saltos, y varios seguidos pueden dar el mismo . Por ejemplo, en largo 31 y dan el mismo (31,11): con se piden a , la clase trae a y a , y la tira llega a 10. Pedir no agrega ninguna raíz.
Un código, entonces, tiene un rango de que lo producen, y el catálogo lo lista con el mayor: el que su tira de raíces de verdad garantiza. Los menores del rango dan el mismo código con una distancia diseñada menor. Enumeradas sus 2048 palabras, el (31,11) tiene , la que corresponde a . La tabla recorre en los BCH primitivos de sentido estricto de largo 15, 31 y 63; la columna «desde» es el menor que ya da el código, cuando no coincide con el mayor.
| código | t | desde | n − k | mt |
|---|---|---|---|---|
| (15,11) | 1 | — | 4 | 4 |
| (15,7) | 2 | — | 8 | 8 |
| (15,5) | 3 | — | 10 | 12 |
| (15,1) | 7 | 4 | 14 | 28 |
| (31,26) | 1 | — | 5 | 5 |
| (31,21) | 2 | — | 10 | 10 |
| (31,16) | 3 | — | 15 | 15 |
| (31,11) | 5 | 4 | 20 | 25 |
| (31,6) | 7 | 6 | 25 | 35 |
| (31,1) | 15 | 8 | 30 | 75 |
| (63,57) | 1 | — | 6 | 6 |
| (63,51) | 2 | — | 12 | 12 |
| (63,45) | 3 | — | 18 | 18 |
| (63,39) | 4 | — | 24 | 24 |
| (63,36) | 5 | — | 27 | 30 |
| (63,30) | 6 | — | 33 | 36 |
| (63,24) | 7 | — | 39 | 42 |
| (63,18) | 10 | 8 | 45 | 60 |
| (63,16) | 11 | — | 47 | 66 |
| (63,10) | 13 | 12 | 53 | 78 |
| (63,7) | 15 | 14 | 56 | 90 |
| (63,1) | 31 | 16 | 62 | 186 |
Calculada armando para cada , y verificado en cada fila que el mayor es la mitad de la tira más larga del código. Las filas son la repetición: tiene por raíces todas las potencias de menos , y la tira llega a . En largo 255 las ocho primeras filas, del (255,247) al (255,191), van con de 1 a 8 y cumplen ; la primera que se despega es el (255,187), con : 68 contra 72.
El catálogo no depende del polinomio primitivo elegido: las clases son conjuntos de exponentes módulo , y sale de cuántos exponentes cubren. El primitivo cambia los coeficientes de , no su grado.
Un BCH binario primitivo de sentido estricto con capacidad diseñada cumple
Es un resultado de Mann, y la prueba entra en tres pasos.
Paso 1: los pares sobran. es conjugada de , así que está en su clase y comparte su polinomio mínimo. De las potencias pedidas, las de exponente par no agregan nada.
Paso 2: quedan impares. Los exponentes aportan a lo sumo polinomios mínimos distintos.
Paso 3: cada uno pesa a lo sumo . La clase de se cierra en a lo sumo duplicaciones, porque módulo . El grado del MCM es a lo sumo la suma de los grados: .
Vale con igualdad mientras las clases de los impares son todas de tamaño y distintas entre sí, y se despega por dos motivos que la prueba deja a la vista. Medido en el primer donde se despega cada largo:
| largo | primer código con n − k < mt | n − k | mt | por qué |
|---|---|---|---|---|
| 15 | (15,5), t = 3 | 10 | 12 | clase corta: C₅ = {5, 10} |
| 31 | (31,11), t = 5 | 20 | 25 | coincidencia: 9 está en C₅ |
| 63 | (63,36), t = 5 | 27 | 30 | clase corta: C₉ = {9, 18, 36} |
| 255 | (255,187), t = 9 | 68 | 72 | clase corta: C₁₇, de cuatro |
En largo 31 no hay clases cortas, porque 31 es primo y todas las clases no nulas tienen cinco elementos. Ahí el despegue llega sólo por coincidencia: , y el impar 9 no aporta nada nuevo. Para chico la cota es exacta, y es la forma rápida de estimar la redundancia: en largo 255, ocho bits por error corregido.
La cota pide . La prueba de usa que los pares pedidos sean dobles de impares pedidos. Con entra además la raíz , cuya clase es y cuyo polinomio mínimo es . En largo 15 con se piden a , entran , y , y
de grado 9, uno más que . Es el (15,6): las palabras de peso par del (15,7). La tira va de a , mide 5 y garantiza , y enumeradas sus 64 palabras la distancia es exactamente 6. Un bit más de redundancia compró un punto de distancia: el código detecta un error más, pero sigue corrigiendo dos.
La dimensión no se elige. Entre dos filas del catálogo no hay nada. En largo 31 no existe un BCH primitivo de sentido estricto con entre 16 y 11: si el (31,16) no alcanza, el siguiente cuesta cinco bits más de redundancia.
La tira es una cota inferior. Hay códigos BCH cuya distancia excede a la tira más larga de sus raíces, y verlo pide cotas más finas. Y al alargar el bloque con la tasa fija, la fracción de errores corregibles tiende a cero. Las dos cosas, con su prueba, están en la cota BCH.
El diseño entero, sin librerías: la tabla de potencias de , la clase de un exponente, el polinomio mínimo como producto de sobre la clase —con la comprobación de que sale binario—, el MCM y la tira más larga. Los polinomios binarios van como enteros, con el bit como coeficiente de , y el primitivo con su término incluido. Lo de los comentarios es la salida de correrlo.
def tablas(m, p):
"""exp y log de GF(2^m); p es el primitivo con el bit m incluido."""
N, exp, log, x = 2 ** m - 1, [], {}, 1
for i in range(N):
exp.append(x); log[x] = i
x <<= 1
if x >> m: x ^= p
return exp, log
def clase(i, n):
c, j = [], i % n
while j not in c:
c.append(j); j = 2 * j % n
return c
def minimo(m, p, paso, c):
"""phi(X) = prod (X + beta^j) sobre la clase; sale con coeficientes 0 y 1."""
exp, log = tablas(m, p)
N = 2 ** m - 1
mul = lambda a, b: 0 if a == 0 or b == 0 else exp[(log[a] + log[b]) % N]
phi = [1]
for j in c:
r = exp[j * paso % N]
phi = [(phi[i - 1] if i else 0) ^ (mul(phi[i], r) if i < len(phi) else 0)
for i in range(len(phi) + 1)]
assert set(phi) <= {0, 1}
return sum(b << i for i, b in enumerate(phi))
def mul2(a, b):
r = 0
while b:
if b & 1: r ^= a
a, b = a << 1, b >> 1
return r
def bch(m, p, n, t, l0=1):
paso, raices, g = (2 ** m - 1) // n, set(), 1
for j in range(l0, l0 + 2 * t):
if j % n not in raices:
c = clase(j, n)
raices |= set(c)
g = mul2(g, minimo(m, p, paso, c))
return g, raices
def tira(raices, n):
"""La tira más larga de exponentes consecutivos (módulo n)."""
if len(raices) == n: return n
return max(next(l for l in range(n) if (r + l) % n not in raices)
for r in raices if (r - 1) % n not in raices)
def texto(g):
return ' + '.join('1' if i == 0 else 'X' if i == 1 else f'X^{i}'
for i in range(g.bit_length()) if g >> i & 1)
casos = [(4, 0b10011, 15, 2, 1), (4, 0b10011, 15, 3, 1),
(6, 0b1000011, 21, 2, 1), (5, 0b100101, 31, 1, 2),
(5, 0b100101, 31, 4, 1)]
for m, p, n, t, l0 in casos:
g, R = bch(m, p, n, t, l0)
L = tira(R, n)
print(f'({n},{n - g.bit_length() + 1}) t={t} l0={l0} tira {L}: d >= {L + 1}')
print(' g =', texto(g))
# (15,7) t=2 l0=1 tira 4: d >= 5
# g = 1 + X^4 + X^6 + X^7 + X^8
# (15,5) t=3 l0=1 tira 6: d >= 7
# g = 1 + X + X^2 + X^4 + X^5 + X^8 + X^10
# (21,12) t=2 l0=1 tira 4: d >= 5
# g = 1 + X + X^4 + X^5 + X^7 + X^8 + X^9
# (31,21) t=1 l0=2 tira 4: d >= 5
# g = 1 + X^3 + X^5 + X^6 + X^8 + X^9 + X^10
# (31,11) t=4 l0=1 tira 10: d >= 11
# g = 1 + X^2 + X^4 + X^6 + X^7 + X^9 + X^10 + X^13 + X^17 + X^18 + X^20
Los cuatro primeros casos son los ejemplos de la sección 04 y el de . El último es el (31,11) pedido con : la tira de 10 dice que corrige cinco.