Bitácora · FEC · Concepto

Los códigos BCH

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 Xn+1, 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 t se quieren corregir, se piden 2t 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.

01 · La definición

Sea β un elemento de orden n de GF(2m), y l0 un entero no negativo. El código BCH binario de longitud n y distancia diseñada d0=2t+1 es el código cíclico generado por el polinomio binario de menor grado que tiene por raíces a las 2t potencias consecutivas

βl0,βl0+1,…,βl0+2t−1

Un polinomio con coeficientes en GF(2) que se anula en βj se anula también en todos sus conjugados, así que es múltiplo del polinomio mínimo φj de βj. Para que g(X) se anule en las 2t 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:

g(X)=MCM{φl0(X),φl0+1(X),…,φl0+2t−1(X)}

El mínimo común múltiplo y no el producto, porque las 2t potencias caen casi siempre en menos de 2t 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 n, toda potencia de β es raíz de Xn+1; sus polinomios mínimos dividen a Xn+1, y su mínimo común múltiplo también. Y un divisor de Xn+1 genera un código cíclico de largo n.

La definición se lee también al revés, como prueba de pertenencia: un polinomio binario v(X) de grado menor que n es palabra si y sólo si

v(βj)=0para j=l0,…,l0+2t−1

Si se anula en las 2t 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 l0=1, y primitivo si n=2m−1, o sea si β es un elemento primitivo; entonces se escribe β=α. Casi todos los BCH de uso práctico son las dos cosas.

02 · Los dos cuerpos

La construcción usa dos cuerpos con papeles distintos, y confundirlos es la fuente de error más frecuente de la unidad.

GF(2), el cuerpo base, es donde viven los coeficientes de g(X) y los bits de las palabras. El código es binario: por el canal pasan ceros y unos. GF(2m), el cuerpo de extensión, es donde viven las raíces de g(X). 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 g(X), 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 GF(2m). El codificador de un BCH es un codificador cíclico común; el decodificador es un procesador aritmético entero.

03 · El diseño, en cuatro pasos

Paso 1: el cuerpo. Se fija la longitud n y se busca el menor m tal que n divida a 2m−1. Se toma β=α(2m−1)/n, que tiene orden n.

Paso 2: las raíces. Se fija t y se escriben las 2t 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 g(X), y el código es un (n,n−degg).

La dimensión k 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.

04 · Los cuatro ejemplos

El (15,7). En GF(24) con p(X)=1+X+X4, primitivo de sentido estricto con t=2. Las raíces pedidas son α, α2, α3 y α4. Las clases módulo 15 son C1={1,2,4,8} y C3={3,6,9,12}: tres de las cuatro pedidas están en C1 y la otra en C3. Entran dos polinomios mínimos:

g(X)=φ1(X)φ3(X)=(1+X+X4)(1+X+X2+X3+X4)=1+X4+X6+X7+X8

De grado 8: un (15,7). Se pidieron cuatro raíces y g(X) tiene ocho: las cuatro pedidas más α6, α8, α9 y α12, 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 t=3 se piden α a α6. A las dos clases anteriores se suma C5={5,10}, cuyo polinomio mínimo, 1+X+X2, tiene grado 2:

g(X)=φ1(X)φ3(X)φ5(X)=1+X+X2+X4+X5+X8+X10

De grado 10: un (15,5), con dmin=7 y distribución de pesos A0=1,A7=15,A8=15,A15=1. 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 26−1=63 y a ningún 2m−1 menor, así que se trabaja en GF(26) con p(X)=1+X+X6, y se toma β=α3, de orden 21. Con t=2 las raíces pedidas son β, β2, β3, β4, o sea α3, α6, α9, α12. Módulo 63, las clases son {3,6,12,24,48,33} y {9,18,36}: dos polinomios mínimos, de grados 6 y 3,

φβ(X)=1+X+X2+X4+X6,φβ3(X)=1+X2+X3 g(X)=1+X+X4+X5+X7+X8+X9

De grado 9: un (21,12), y g(X) divide a X21+1. Enumeradas sus 4096 palabras, dmin=5. 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 GF(28) con p(X)=1+X2+X3+X4+X8, con t=2. Las cuatro raíces α a α4 se reparten en dos clases de ocho elementos cada una, y el generador tiene grado 16:

g(X)=1+X+X5+X6+X8+X9+X10+X11+X13+X14+X16

Un (255,239) de tasa 0,937, que corrige dos errores por bloque de 255 bits con dieciséis de redundancia. Su g(X) 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 t=1 primitivo y de sentido estricto, g(X)=φ1, 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í.

Construcción Las raíces de g(X) en el anillo de exponentes — elegí el cuerpo, la capacidad y el primer exponente. Cada punto es una potencia de α; el trazo de afuera es la tira más larga de exponentes consecutivos entre las raíces, que da vuelta por el cero si hace falta.
código — raíces — tira — garantiza — n − k — mt —

Las clases que entraron
    g(X)

    —

    Arranca en el Hamming (15,11): dos raíces pedidas, dos agregadas, una tira de dos. Subí t de a uno en largo 15 y mirá cuánto crece n−k en cada paso. Después pasá a largo 31 con t=1 y corré l0 a 2: pedís un error y mirá la tira. Volvé a l0=1 y subí t hasta 4. Y probá l0=0 en largo 15 con t=2, mirando las dos últimas lecturas.

    05 · La elección de l₀ y la tira más larga

    Nada obliga a tomar l0=1. En largo 31, sobre GF(25) con p(X)=1+X2+X5, con t=1 y l0=1 las raíces pedidas son α y α2, de la misma clase: g(X)=φ1 y el código es el Hamming (31,26). Con t=1 y l0=2 se piden α2 y α3, que están en clases distintas:

    g(X)=φ1(X)φ3(X)=1+X3+X5+X6+X8+X9+X10

    Un (31,21): cinco bits más de redundancia para corregir un solo error, que parece un mal negocio. No lo es. Ese g(X) es idéntico al de l0=1 con t=2, porque la clase de α2 trajo a α y a α4 sin que nadie los pidiera, y entre las raíces quedan cuatro potencias consecutivas, de α a α4. Enumeradas sus 221 palabras, dmin=5: el código diseñado para corregir uno corrige dos.

    La regla que sale de ahí: obtenido g(X), se busca la tira más larga de exponentes consecutivos entre todas sus raíces, no sólo la que se pidió. Si mide δ−1, la cota BCH vale con esa tira y el código tiene dmin≥δ: esa es la distancia diseñada efectiva. La tira puede dar la vuelta por el cero, porque los exponentes se leen módulo n.

    l0=1 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.

    06 · El catálogo

    Al subir t con el largo fijo, k baja a saltos, y varios t seguidos pueden dar el mismo g(X). Por ejemplo, en largo 31 t=4 y t=5 dan el mismo (31,11): con t=4 se piden α a α8, la clase C5 trae a α9 y a α10, y la tira llega a 10. Pedir t=5 no agrega ninguna raíz.

    Un código, entonces, tiene un rango de t que lo producen, y el catálogo lo lista con el mayor: el que su tira de raíces de verdad garantiza. Los t menores del rango dan el mismo código con una distancia diseñada menor. Enumeradas sus 2048 palabras, el (31,11) tiene dmin=11, la que corresponde a t=5. La tabla recorre t en los BCH primitivos de sentido estricto de largo 15, 31 y 63; la columna «desde» es el menor t que ya da el código, cuando no coincide con el mayor.

    códigotdesden − kmt
    (15,11)1—44
    (15,7)2—88
    (15,5)3—1012
    (15,1)741428
    (31,26)1—55
    (31,21)2—1010
    (31,16)3—1515
    (31,11)542025
    (31,6)762535
    (31,1)1583075
    (63,57)1—66
    (63,51)2—1212
    (63,45)3—1818
    (63,39)4—2424
    (63,36)5—2730
    (63,30)6—3336
    (63,24)7—3942
    (63,18)1084560
    (63,16)11—4766
    (63,10)13125378
    (63,7)15145690
    (63,1)311662186

    Calculada armando g(X) para cada t, y verificado en cada fila que el mayor t es la mitad de la tira más larga del código. Las filas (n,1) son la repetición: g(X) tiene por raíces todas las potencias de α menos α0=1, y la tira llega a n−1. En largo 255 las ocho primeras filas, del (255,247) al (255,191), van con t de 1 a 8 y cumplen n−k=mt=8t; la primera que se despega es el (255,187), con t=9: 68 contra 72.

    El catálogo no depende del polinomio primitivo elegido: las clases son conjuntos de exponentes módulo n, y k sale de cuántos exponentes cubren. El primitivo cambia los coeficientes de g(X), no su grado.

    07 · La redundancia: n − k ≤ mt

    Un BCH binario primitivo de sentido estricto con capacidad diseñada t cumple

    n−k≤mt

    Es un resultado de Mann, y la prueba entra en tres pasos.

    Paso 1: los pares sobran. β2i=(βi)2 es conjugada de βi, así que está en su clase y comparte su polinomio mínimo. De las 2t potencias pedidas, las de exponente par no agregan nada.

    Paso 2: quedan t impares. Los exponentes 1,3,…,2t−1 aportan a lo sumo t polinomios mínimos distintos.

    Paso 3: cada uno pesa a lo sumo m. La clase de i se cierra en a lo sumo m duplicaciones, porque 2mi≡i módulo 2m−1. El grado del MCM es a lo sumo la suma de los grados: mt.

    Vale con igualdad mientras las clases de los impares son todas de tamaño m y distintas entre sí, y se despega por dos motivos que la prueba deja a la vista. Medido en el primer t donde se despega cada largo:

    largoprimer código con n − k < mtn − kmtpor qué
    15(15,5), t = 31012clase corta: C₅ = {5, 10}
    31(31,11), t = 52025coincidencia: 9 está en C₅
    63(63,36), t = 52730clase corta: C₉ = {9, 18, 36}
    255(255,187), t = 96872clase 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: C5={5,9,10,18,20}, y el impar 9 no aporta nada nuevo. Para t chico la cota es exacta, y es la forma rápida de estimar la redundancia: en largo 255, ocho bits por error corregido.

    08 · Lo que la construcción no da

    La cota pide l0=1. La prueba de n−k≤mt usa que los pares pedidos sean dobles de impares pedidos. Con l0=0 entra además la raíz α0=1, cuya clase es C0={0} y cuyo polinomio mínimo es 1+X. En largo 15 con t=2 se piden α0 a α3, entran C0, C1 y C3, y

    g(X)=(1+X)(1+X4+X6+X7+X8)=1+X+X4+X5+X6+X9

    de grado 9, uno más que mt=8. Es el (15,6): las palabras de peso par del (15,7). La tira va de α0 a α4, mide 5 y garantiza dmin≥6, 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 k 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 t/n tiende a cero. Las dos cosas, con su prueba, están en la cota BCH.

    09 · La cuenta en Python

    El diseño entero, sin librerías: la tabla de potencias de α, la clase de un exponente, el polinomio mínimo como producto de (X+βj) 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 i como coeficiente de Xi, y el primitivo con su término Xm 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 l0=2. El último es el (31,11) pedido con t=4: la tira de 10 dice que corrige cinco.

    Para tener a mano

    1. BCH de largo n y distancia diseñada d0=2t+1: el cíclico de g(X) = MCM de los polinomios mínimos de βl0,…,βl0+2t−1, con β de orden n.
    2. MCM y no producto: cada clase conjugada entra una vez. Las raíces de g(X) son las pedidas más todas sus conjugadas.
    3. Coeficientes y bits en GF(2); raíces y síndromes en GF(2m). Codificar es binario; decodificar no.
    4. Diseño: el menor m con n que divida a 2m−1, β=α(2m−1)/n, las 2t potencias, sus clases, el producto. k sale, no se elige.
    5. (15,7) = 1+X4+X6+X7+X8, dmin=5. (15,5) = 1+X+X2+X4+X5+X8+X10, dmin=7. (21,12) con β=α3, dmin=5. (255,239) de grado 16 y once coeficientes.
    6. Con t=1, primitivo y estricto, el BCH es el Hamming.
    7. La distancia la garantiza la tira más larga de exponentes consecutivos entre todas las raíces, no la pedida: l0=2 y t=1 en largo 31 dan el (31,21), que corrige dos.
    8. El catálogo lista cada código con el mayor t que lo produce: (31,11) con t=5, aunque sale desde 4; (63,18) con 10, aunque sale desde 8.
    9. n−k≤mt con l0=1, igual mientras las clases de los impares sean de tamaño m y distintas. Con l0=0 puede pasarse: el (15,6) pide 9 contra 8.
    ← Anterior Siguiente → Inicio
    Relacionados Las clases conjugadas y los polinomios mínimos La cota BCH El polinomio generador Los códigos de Hamming Los síndromes y el polinomio localizador Pedir t puede darte más Las potencias de α recorren todo, o no