Bitácora · FEC · Concepto

La distribución de pesos de los códigos BCH

Unidad 6 · Los códigos BCH · cuántas palabras hay de cada peso: el dual del (31,21) y MacWilliams, la binomial para los códigos largos, y la probabilidad de error no detectado con sus dos cotas

Un código BCH garantiza su distancia diseñada y no dice nada más. Pero usado como detector, un código falla cuando el canal escribe justo otra palabra, y cuántas veces pasa eso depende de cuántas palabras hay de cada peso. La distribución de pesos de un BCH cualquiera no se conoce en forma cerrada. Hay dos caminos parciales: contarla desde el dual, cuando el dual es chico, y aproximarla con una binomial, cuando el código es largo. De ella sale la probabilidad de error no detectado, que tiene dos cotas.

01 · La definición

La distribución de pesos de un código (n,k) es la lista A0,A1,…,An, donde Ai cuenta las palabras de peso i. Se la guarda en un polinomio, el enumerador de pesos:

A(z)=∑i=0nAizi,A0=1,A(1)=2k

En un código lineal, el menor i>0 con Ai≠0 es la distancia mínima. La cota BCH asegura que A1=⋯=A2t=0, y de los demás coeficientes no dice nada.

Para qué sirven. Sobre el canal binario simétrico con probabilidad de transición p, se transmite v y llega r=v+e. Si el patrón de error e es una palabra no nula, r es otra palabra, el síndrome da cero y el error pasa sin que nadie lo vea. Y sólo así: si e no es palabra, el síndrome no es cero. Un patrón de peso i tiene probabilidad pi(1−p)n−i, y hay Ai palabras de ese peso:

Pu(E)=∑i=1nAipi(1−p)n−i

Es la probabilidad de error no detectado. Con p chico manda el primer término, Adminpdmin, y con p=1/2 todos los patrones pesan lo mismo y queda Pu(E)=(2k−1)/2n: una palabra no nula cualquiera, sobre todos los vectores.

02 · El dual del (31,21), paso a paso

El (31,21) es el BCH de largo 31 que corrige dos errores. Sobre GF(25), con P(x)=1+x2+x5, las cuatro raíces α,α2,α3,α4 caen en dos clases conjugadas, la de α y la de α3, y el generador es el producto de sus dos polinomios mínimos:

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

con φ1=1+X2+X5 y φ3=1+X2+X3+X4+X5. El código tiene 221=2 097 152 palabras. Su dual es un (31,10): tiene 1024. Un BCH de tasa alta tiene un dual chico, y ésa es la asimetría que se aprovecha.

Paso 1: el polinomio de paridad. Como g(X) divide a X31+1, el cociente h(X)=(X31+1)/g(X) es el polinomio de paridad, de grado k=21:

h(X)=1+X3+X5+X8+X11+X12+X13+X14+X16+X18+X20+X21

Paso 2: el dual lo genera el recíproco. El dual de un cíclico es cíclico, y su generador es h∗(X)=Xkh(X−1), el mismo polinomio leído al revés (está en el polinomio generador):

h∗(X)=1+X+X3+X5+X7+X8+X9+X10+X13+X16+X18+X21

Paso 3: contar. Las palabras del dual son los u(X)h∗(X) con u(X) de grado menor que 10. Recorridas las 1024, los pesos que aparecen son cuatro:

B(z)=1+310z12+527z16+186z20

Paso 4: la forma cerrada. Para los BCH primitivos de sentido estricto con t=2 y m impar, el dual tiene siempre esos tres pesos no nulos, alrededor de 2m−1, y se sabe cuántas palabras hay de cada uno. Con m=5:

peso icon m = 5palabras Bᵢcon m = 5
0011
2m−1 − 2(m−1)/212(2m−2 + 2(m−3)/2)(2m − 1)(8 + 2)·31 = 310
2m−116(2m−1 + 1)(2m − 1)17·31 = 527
2m−1 + 2(m−1)/220(2m−2 − 2(m−3)/2)(2m − 1)(8 − 2)·31 = 186

El recuento palabra por palabra y la fórmula dan lo mismo, y los cuatro números suman 1024=210. Para m par y para t=3 también hay tablas cerradas; para un BCH cualquiera, no.

03 · Del dual al código: MacWilliams

La identidad de MacWilliams pasa del enumerador del dual al del código:

A(z)=2−(n−k)(1+z)nB(1−z1+z)

con k la dimensión del código, así que el factor de adelante es uno sobre la cantidad de palabras del dual: acá, 2−10. Se comprueba en z=1: B(0)=B0=1 y queda A(1)=2−10·231=221, las palabras del (31,21).

Coeficiente a coeficiente: cada palabra del dual de peso i aporta (1−z)i(1+z)n−i, y el coeficiente de zj en ese producto es el polinomio de Krawtchouk

Aj=2−(n−k)∑iBiKj(i) Kj(i)=∑l=0j(−1)l(il)(n−ij−l)

Con un dual de cuatro pesos, cada Aj es una suma de cuatro términos dividida por 1024. Hechas las 32 sumas:

A(z)=1+186z5+806z6+2635z7+7905z8+⋯+301 971z15+301 971z16+⋯+186z26+z31

La lista entera está en la tabla de la sección 04. Enumeradas una por una las 2 097 152 palabras del (31,21), la distribución sale idéntica, coeficiente por coeficiente.

Se lee así. El menor peso no nulo es 5: la distancia mínima real es la diseñada, 2t+1. La lista es simétrica, A31−i=Ai, porque la palabra de todos unos está en el código: α0=1 no es raíz de g(X), así que X+1 no lo divide, y (X31+1)/(X+1)=1+X+⋯+X30 es múltiplo suyo. Sumarle esa palabra a otra de peso i da una de peso 31−i. Por eso al hueco de los pesos 1 a 4 le corresponde otro, del 27 al 30.

Y el hueco sale de una cancelación. En j=3, por ejemplo, los cuatro términos son

A3=4495−15 190+7905+27901024=0

El primero, el de la palabra nula del dual, es K3(0)=(313); los otros tres, los de las 1023 palabras restantes, lo anulan exacto. En el widget de abajo se ve, peso por peso, qué hace cada término.

04 · Contra la binomial

El segundo camino es una aproximación. Para un BCH primitivo de largo n=2m−1 con n−k=mt bits de paridad, y m suficientemente grande,

Ai≃{00<i≤2t(1+λ0n−1/10)(ni)2−(n−k)i>2t

con λ0 acotado por una constante, de modo que el factor de corrección tiende a 1 cuando el código se alarga. De los (ni) vectores de peso i, al código le toca la fracción 2−(n−k) que le corresponde por su tamaño: salvo en los pesos bajos, un BCH largo reparte sus palabras como si las hubieran elegido al azar. La estructura algebraica se ve en el hueco, y en nada más.

La binomial no sale de la nada: es el primer término de MacWilliams. La palabra nula del dual tiene B0=1 y Kj(0)=(nj), así que aporta exactamente (nj)2−(n−k). Lo demás es la corrección que traen las otras palabras del dual. La aproximación dice que en un BCH largo esa corrección es chica, salvo donde borra los pesos bajos. En el (31,21), con la mitad de la lista, porque la otra mitad es su espejo:

i31 − iAᵢbinomialrazón
03110,001—
13000,0300
22900,4540
32804,3900
427030,7280
526186165,9291,121
625806719,0241,121
7242 6352 567,9441,026
8237 9057 703,8331,026
92218 91019 687,5730,961
102141 60243 312,6610,961
112085 56082 687,8081,035
1219142 600137 813,0131,035
1318195 300201 419,0190,970
1417251 100258 967,3100,970
1516301 971293 496,2841,029

La binomial es (31i)2−10, y la razón, Ai sobre ella. Del peso 5 al 26 la razón queda entre 0,961 y 1,121, y la peor está en el borde del hueco. Adentro del hueco, la binomial pone 35,6 palabras entre los pesos 1 y 4 —30,7 de peso 4— y el código no tiene ninguna. En un código más corto la aproximación ajusta peor: en el (15,7), con

A(z)=1+18z5+30z6+15z7+15z8+30z9+18z10+z15

Ahí la razón va de 0,597, en los pesos 7 y 8, a 1,534, en el 5, el 6, el 9 y el 10.

Recuento Del dual al código, peso por peso — elegí un peso j: se hacen los cuatro términos de MacWilliams y su barra queda en el gráfico. La línea cortada es la binomial, que es el primer término solo.
Los cuatro términos: Bᵢ · Kⱼ(i)
peso del dual iBᵢKⱼ(i)Bᵢ · Kⱼ(i)
El (31,21), en escala logarítmica
Aⱼ visitadobinomial C(31, j) · 2⁻¹⁰
suma — Aⱼ = suma / 1024 — binomial — razón — pesos vistos —

Arranca en el peso 15, el del medio, donde la barra y la binomial casi se tocan y el primer término se lleva el 97 % de la suma. Bajá hacia el 5 y mirá cómo crecen los otros tres. Después pasá al 4: el primer término sigue ahí, y los otros tres lo anulan.

05 · La probabilidad de error no detectado

Con la aproximación de la sección 04 en la fórmula de Pu(E), los pesos de 1 a 2t no aportan y la redundancia sale como factor:

Pu(E)≃(1+λ0n−1/10)2−(n−k)∑i=2t+1n(ni)pi(1−p)n−i

La suma es la probabilidad de que ocurran más de 2t errores, y no pasa de uno. De ahí la cota general:

Pu(E)≲2−(n−k)

La probabilidad de dejar pasar un error queda acotada por la redundancia, sea cual sea el canal. Es la probabilidad de que un vector elegido al azar caiga en el código: 2k/2n. Para el (255,239) vale 2−16≈1,53·10−5.

Con p chico es muy pesimista. En el (31,21), con la distribución exacta de la sección 03 y p=10−2,

Pu(E)=1,497·10−8contra2−10=9,77·10−4

65 230 veces menos: 4,8 órdenes de magnitud. Recién en p=1/2, con un canal que no transporta nada, las dos coinciden: (221−1)/231=2−10(1−2−21).

06 · La cota exponencial

La suma de la sección 05 es la cola de una binomial, y la cola se acota con la desigualdad de Chernoff. Con ε=(2t+1)/n y p<ε,

∑i=nεn(ni)pi(1−p)n−i≤2−nE(ε,p) E(ε,p)=H(p)+(ε−p)H′(p)−H(ε)

con H(x)=−xlog2x−(1−x)log2(1−x) la entropía binaria y H′(x)=log2(1−x)/x. Desarmado, el exponente es

E(ε,p)=εlog2εp+(1−ε)log21−ε1−p

que es positivo siempre que ε≠p, y crece a medida que p se aleja de ε hacia abajo. Juntando con la sección 05:

Pu(E)≲2−nE(ε,p)2−(n−k)

que decae exponencialmente en el largo además de en la redundancia. En el (31,21), ε=5/31≈0,161. Las dos cotas contra la cuenta exacta:

pexactaexponencialexponencial / exacta2⁻¹⁰ / exacta
10⁻⁴1,856·10⁻¹⁸8,642·10⁻¹⁸4,665,3·10¹⁴
10⁻³1,820·10⁻¹³8,442·10⁻¹³4,645,4·10⁹
10⁻²1,497·10⁻⁸6,672·10⁻⁸4,466,5·10⁴
0,051,952·10⁻⁵7,135·10⁻⁵3,6650,0
0,12,085·10⁻⁴5,598·10⁻⁴2,684,68
0,155,359·10⁻⁴9,618·10⁻⁴1,791,82

La general es plana y la exponencial sigue la pendiente: con p chico, 2−nE va como pnε=p5, igual que el término 186p5 que manda en la exacta, y queda a un factor 4,5 arriba. Al acercarse a ε las dos cotas se juntan. Las dos llevan ≲ porque se tiró el factor (1+λ0n−1/10); en el (31,21) la exponencial queda arriba de la exacta en todo 10−5<p<ε, por un factor de al menos 1,62.

Simulación La probabilidad de error no detectado y sus dos cotas — mové p y leé las tres curvas en ese punto. Antes de sumar el (15,7), apostá.
(31,21), exacta cota general 2⁻⁽ⁿ⁻ᵏ⁾ cota exponencial, p < ε
Con p = 10⁻³, ¿cuál deja pasar más errores por palabra?
exacta — cota general — exponencial — general / exacta — (15,7) — (31,21) / (15,7) —

Arranca en p=1/2, donde la exacta y la cota general son la misma cosa. Bajá p y mirá cuánto se abre la distancia, y dónde aparece la exponencial. Apostá antes de ver el (15,7), y después recorré su curva de punta a punta.

07 · Dos bits de paridad: cuatro veces arriba, diez abajo

El (15,7) es el BCH de largo 15 que corrige dos errores: ocho bits de paridad, dos menos que el (31,21), y la misma distancia mínima, 5. En la zona plana su cota general es 2−8 contra 2−10, y la curva exacta lo sigue: en p=1/2 el (15,7) deja pasar 3,97 veces más que el (31,21), que es 22 salvo por el −1 de 2k−1.

Pero el orden se invierte. Las dos curvas exactas se cruzan en p≈0,186, y debajo de ahí el (31,21), con más redundancia, deja pasar más: en p=10−3, 1,820·10−13 contra 1,785·10−14, 10,2 veces más por palabra. Con p chico manda A5p5, y el (31,21) tiene 186 palabras de peso 5 donde el (15,7) tiene 18: una palabra más larga ofrece más maneras de que cinco errores formen otra palabra. La redundancia fija el techo; el piso lo fijan la distancia mínima y cuántas palabras hay a esa distancia. La cota general no ve ninguna de las dos.

08 · Lo que la cota general no promete

El ≲ no es un adorno. Pu(E)≤2−(n−k) sale de suponer la binomial, y un código que se aparta mucho de ella puede pasarla. El (15,5) de g(X)=1+X5+X10, un cíclico que no es BCH, repite tres veces un bloque de cinco bits: A(z)=1+5z3+10z6+10z9+5z12+z15. Barriendo p de 10−5 en 10−5 hasta 1/2, su Pu(E) pasa a 2−10 por un factor de hasta 2,91, en p≈0,207.

Los dos BCH de la sección 07 no la pasan en ningún punto de ese barrido: el máximo de Pu(E)·2n−k está en p=1/2 y vale 1−2−k. Para saberlo de un código hay que tener su distribución, y ése es todo el punto: la cota BCH no la da, el dual la da sólo cuando es chico, y la binomial la adivina sólo cuando el código es largo. Lo que pasa con un error más que t, cuando el código corrige en vez de detectar, también lo deciden las palabras de peso mínimo: está en pasado t, la cuenta la hacen las palabras livianas.

09 · La cuenta en Python

El camino entero para el (31,21), con enteros como polinomios binarios: el bit i es el coeficiente de Xi. Divide para sacar h(X), lo invierte, recorre el dual, aplica MacWilliams con los polinomios de Krawtchouk y evalúa Pu(E). Lo de los comentarios es la salida de correrlo.

from math import comb

def mul(a, b):
    """Producto de polinomios binarios guardados como enteros (bit i = X^i)."""
    r = 0
    while b:
        if b & 1:
            r ^= a
        a, b = a << 1, b >> 1
    return r

def div(a, b):
    q = 0
    while a.bit_length() >= b.bit_length():
        s = a.bit_length() - b.bit_length()
        q, a = q | 1 << s, a ^ b << s
    return q, a

n, k = 31, 21
g = 0b11101101001                         # 1 + X³ + X⁵ + X⁶ + X⁸ + X⁹ + X¹⁰
h, resto = div(1 << n | 1, g)             # h(X) = (X³¹ + 1) / g(X)
hr = int(f'{h:0{k + 1}b}'[::-1], 2)       # h*(X) = X²¹ h(1/X)

B = [0] * (n + 1)                         # el dual: los 1024 múltiplos de h*(X)
for u in range(1 << (n - k)):
    B[bin(mul(u, hr)).count('1')] += 1
print(resto, {i: b for i, b in enumerate(B) if b})
# 0 {0: 1, 12: 310, 16: 527, 20: 186}

def K(j, i):                              # Krawtchouk: el coeficiente de z^j
    return sum((-1) ** l * comb(i, l) * comb(n - i, j - l) for l in range(j + 1))

S = [sum(B[i] * K(j, i) for i in range(n + 1)) for j in range(n + 1)]
A = [s // 2 ** (n - k) for s in S]
print(A[:9], sum(A) == 2 ** k, all(s % 2 ** (n - k) == 0 for s in S))
# [1, 0, 0, 0, 0, 186, 806, 2635, 7905] True True

Pu = lambda p: sum(A[i] * p ** i * (1 - p) ** (n - i) for i in range(1, n + 1))
print(f'{Pu(1e-2):.4e} {2.0 ** -(n - k):.4e} {Pu(0.5) * 2 ** (n - k):.7f}')
# 1.4971e-08 9.7656e-04 0.9999995

El 0 del primer renglón es el resto de la división: g(X) divide a X31+1. El segundo True dice que las 32 sumas son múltiplos exactos de 1024, así que la división entera no redondea nada. El 0.9999995 del final es 1−2−21.

Para tener a mano

  1. Pu(E)=∑i≥1Aipi(1−p)n−i: el error pasa si y sólo si es una palabra no nula. La distribución de un BCH cualquiera no se conoce en forma cerrada.
  2. Dual chico, MacWilliams: A(z)=2−(n−k)(1+z)nB((1−z)/(1+z)), con 2n−k las palabras del dual. El dual de un cíclico lo genera Xkh(X−1).
  3. (31,21): B(z)=1+310z12+527z16+186z20, y A(z)=1+186z5+806z6+⋯+z31, simétrica porque la palabra de todos unos es del código.
  4. La binomial (ni)2−(n−k) es el término de la palabra nula del dual. En el (31,21) ajusta entre 0,961 y 1,121 del peso 5 al 26; en el (15,7), entre 0,597 y 1,534.
  5. Cota general: Pu≲2−(n−k), alcanzada en p=1/2. Exponencial, para p<ε=(2t+1)/n: Pu≲2−nE(ε,p)2−(n−k).
  6. (31,21) en p=10−2: 1,497·10−8, 4,8 órdenes debajo de 2−10; la exponencial, a un factor 4,46.
  7. (15,7) contra (31,21): dos bits de paridad menos valen un factor 22 en la zona plana (3,97 en p=1/2), pero debajo de p≈0,186 el (31,21) deja pasar más: 10,2 veces en 10−3, por 186 palabras de peso 5 contra 18.
  8. La cota general no es un teorema para todo código: el (15,5) de 1+X5+X10 la pasa por 2,91.
← Anterior Siguiente → Inicio
Relacionados Los códigos BCH La cota BCH La matriz de paridad y el código dual La distancia mínima El polinomio generador Pasado t, la cuenta la hacen las palabras livianas La ráfaga que más se escapa