Циклические коды

(краткий пересказ)

Что это такое

Циклические коды относятся к линейным кодам. Специфические свойства данного вида кодов помогают как при кодировании/декодировании, так и при аппаратной реализации этих процессов.

Одно из определений циклического кода

Определение
Линейный код называют циклическим, если для любого кодового слова  [xnx0x1...xn-1] циклическая перестановка символов [x0x1...xn-1xn] также дает кодовое слово.

Процедура построения таких кодов гораздо более управляемая. Однако, нам потребуется перейти от векторного описания кодов к полиномиальному. Последовательность символов основного алфавита (0'ки и 1'ки в простейшем случае), составляющие сообщения и кодовые слова мы будем интерпретировать как коэффициенты полиномов. Например, считая, что коэффициенты записаны в порядке возрастания степени, сообщение [1010] запишем в виде многочлена 1 + x2 . Кодирование сообщения в более "длинное" кодовое слово будет проводится умножением этого многочлена на другой, что дает в результате многочлен более высокой степени.

Рассмотрим операции с многочленами подробнее.

Полиномиальная арифметика

Рассмотрим многочлены с коэффициентами из поля Z2. Сложение, умножение и деление полиномов проводится как обычно.

Для тех, кто это подзабыл, приведем пример на деление.

 

Пример  1

Найти (1 + x + x2 + x5)/(1 + x2).

 

            x^3 +  x  +  1
          -----------------------------
x^2 +  1  | x^5 + x^2 +  x  +  1
		x^5 + x^3
          -----------------------------
                  x^3 + x^2 +  x  +  1
                  x^3 +  x 
                  ---------------------
                        x^2 +  1   
                        x^2 +  1
                        --------
                               0
(В арифметике поля Z2 x + x = 0 , т.к. в более подробной записи x + x = (1 + 1)*x = 0*x = 0). Таким образом, 1 + x2 делит 1 + x + x2 + x5 нацело и результат есть 1 + x + x3.

Напомним также модульную арифметику многочленов. Многочлены называются сравнимыми по модулю многочлена p(x), если их разность делится на p(x) нацело. Поэтому для получения f(x)(mod p(x)) вам нужно просто разделить f(x) на p(x) и взять остаток от деления. Заметим, что если степень   f(x) меньше степени p(x), то результатом будет просто f(x)

Пример 2

Нати 1 + x2 + x5 (mod 1 + x2).
            x^3 +  x  +  1
          -----------------------------
x^2 +  1  | x^5 + x^2 +  1
		x^5 + x^3
          -----------------------------
                  x^3 + x^2 +  1
                  x^3 +  x 
                  ---------------------
                        x^2 +  x  +  1   
                        x^2 +  1
                        ---------------
                               x
Итак, 1 + x2 + x5 (mod 1 + x2) = x.

Замечательным свойством полиномиального представления кодов является возможность осуществить циклический сдвиг на одну позицию вправо простым умножением кодового многочлена степени n-1 на многочлен "x" и нахождения остатка от деления на  xn + 1.

Пример 3

Осуществить единичный правый циклический сдвиг кодового слова [1011], используя полиномиальную интерпретацию.

Вектору [1011] соответствует полином 1 + x2 + x3. Умножим его на x, что дает get x + x3 + x4. Далее, найдем остаток от деления на  xn + 1, т.е. x + x3 + x4 (mod xn + 1) = x + x3 + x4 (mod x4 + 1).

             1
          -----------------------------
x^4 +  1  | x^4 + x^3 +  x
		x^4 +  1
          -----------------------------
                  x^3 +  x  +  1
Результат 1 + x + x3. Многочлен 1 + x + x3 соответствует вектору [1101], который получается из [1011] правым циклическим сдвигом на одну позицию.

Порождающий многочлен

    Процедура кодирования в полиномиальной интерпретации сводится к умножению многочлена-сообщения на подходящий многочлен, называемый порождающим многочленом данного кода. Теоретическое обоснование опустим, приведем лишь формулировку соответствующей теоремы [3].

Tеорема

Многочлен g(x) является порождающим многочленом линейного циклического кода длины  n тогда и только тогда, когда g(x) делит 1 + xn.

    Из теоремы следует, что для получения  порождающего многочлена g(x) нам необходимо разложить на множители xn + 1 и выделить многочлен такой степени, которая соответствует длине кодового слова. Длина кодового слова n и длина сообщения  k связаны соотношением, k = n - deg(g(x)), где deg(g(x)) обозначает степень g(x).

Пример 4

    Найти порождающий многочлен (ПМ) линейного циклического кода длины   n = 15, который осуществляет кодирование сообщений длины k = 7. Затем кодировать сообщение [0110110].

    Если нам нужен ПМ для кода длины 15 при длине сообщения 7, то нужно найти делитель x15 + 1 степени 15 - 7 = 8.

Многочлен x15 + 1 разлагается на множители (как? - вот в чем вопрос)

x15 + 1 = (1 + x)(1 + x + x2)(1 + x + x2 + x3 + x4)(1 + x + x4)(1 + x3 + x4),
поэтому можно взять g(x) = (1 + x + x2 + x3 + x4)(1 + x + x4) = 1 + x4 + x6 + x7 + x8. Используя этот многочлен как ПМ мы строим код с минимальным расстоянием 5, который исправляет 2 ошибки. Найдя ПМ, мы можем кодировать сообщение [0110110]. В полиномиальной интерпретации вектору [0110110] соответствует x + x2 + x4 + x5. Умножим его на ПМ g(x).
(x + x2 + x4 + x5)(1 + x4 + x6 + x7 + x8) =
x + x2 + x4 + x6 + x7 + x8 + x9 + x13

Соответствующее кодовое слово[011010111100010]. Итак, сообщение [0110110] кодировано в слово [011010111100010].

Алгоритм декодирования

Процедура декодирования циклического кода следующая [3].

  1. Найти синдромный многочлен s(x) = r(x)(mod g(x)), где r(x) полученное слово.
  2. Для каждого i >= 0, вычислять si(x) = xis(x)(mod g(x)) до тех пор, пока не будет найден, sj такой, что для него (вес)wt(sj) <= t, где t -- максимальное число ошибок, исправляемых кодом. Таким образом полином ошибки есть e(x) = xn-jsj(x) (mod (1 + xn))

Пример 4 (прод.)

Декодировать полученное слово [011010111010010], которое было отправлено после кодирования кодом из первой части примера 4. Соответствующий вектору [011010111010010] многочлен
x + x2 + x4 + x6 + x7 + x8 + x10 + x13
Найдем многочлен-синдром, (напомню, что g(x) = 1 + x4 + x6 + x7 + x8).
x + x2 + x4 + x6 + x7 + x8 + x10 + x13 (mod 1 + x4 + x6 + x7 + x8) =
x2 + x6 + x8

Для кодового слова синдром, как известно, равен 0. В данном случае это не так, посланное слово было искажено помехой. В соответствии с описанной процедурой декодирования будем вычислять si(x) = xi(x2 + x6 + x8)(mod g(x)) для последовательных возрастающих значений i пока не найдем многочлен степени меньшей или равной двум (число ошибок t = 2 ).

s1 = xs(x)(mod g(x)) = (x3 + x7 + x9)(mod g(x)) = x3 + x4 + x5 + x6 + x7

s2 = x2s(x)(mod g(x)) = (x4 + x8 + x10)(mod g(x)) = 1 + x + x2 + x5

s3 = x3s(x)(mod g(x)) = (x5 + x9 + x11)(mod g(x)) = x + x2 + x3 + x6

s4 = x4s(x)(mod g(x)) = (x6 + x10 + x12)(mod g(x)) = x2 + x3 + x4 + x7

s5 = x5s(x)(mod g(x)) = (x7 + x11 + x13)(mod g(x)) = 1 + x3 + x5 + x6 + x7

s6 = x6s(x)(mod g(x)) = (x8 + x12 + x14)(mod g(x)) = x + 1

x + 1 имеет вес 2, поэтому для нахождения многочлена ошибок вычисляем e(x) = x15-6s6(x)(mod (1 + xn)) = x9(x + 1)(mod (1 + xn)) = x10 + x9.

Итак, если отправленное кодовое слово имеет не более двух ошибок, то оно было таким

(x + x2 + x4 + x6 + x7 + x8 + x10 + x13) + (x10 + x9) =

x + x2 + x4 + x6 + x7 + x8 + x9 + x13

Этот многочлен соответствует вектору [011010111100010]. Чтобы восстановить само сообщение нам надо разделить кодовое слово на ПМ g(x) и получить 

x + x2 + x4 + x5,  

значит сообщение было [0110110].

Немного подробнее

IV. Размерность, порождающая и проверочная матрицы

    Сейчас мы рассмотрим, как идеи, которые первоначально обсуждались применительно к линейным кодам, будут интерпретироваться при полиномиальном описании циклических кодов.

Теорема: Если ПМ g(x) кода C имеет степень n-k тогда C является (n,k)-циклическим кодом. Если g(x) = a0 + a1x + a2x2 + ... + an-k xn-k , то порождающая матрица кода C  k x n матрица вида:

[cyclic form of generator matrix]

Док-во: Векторы g(x), xg(x), x2g(x), ..., xk-1g(x) линейно -независимы. IВ противном случае существует нетривиальный набор коэффициентов {bi} такой, что

b0g(x) + b1xg(x) + b2 x2 g(x) + ... + bk-1 xk-1 g(x) = 0,
(b0 + b1x + b2x2 + ... + bk-1 xk-1) g(x) = 0.

Но степень этого произведения k - 1 + n - k = n - 1 < n, поэтому оно не может быть тождественно = 0 mod (xn - 1), кроме как при всех bi = 0.

Пусть c(x) из C, тогда c(x) = b(x) g(x) и можно заключить, что b(x) имеет степень <= k - 1 (иначе произведение будет иметь степень > n - 1 и придется приводить к остатку по mod (xn - 1),  b'(x), удовлетворяющему этому ограничению на степень ). Таким образом, c(x) может быть представлено линейной комбинацией функций вида xi g(x).

Система {xi g(x) }, 0 <= i <= k - 1 является базисом   C, а, следовательно, размерность кода k.

    Получив полиномиальную интерпретацию циклического кода C, мы рассмотрим соответствующую интерпретацию дуального к C  кода Cperp . Покажем, что дуальный циклическому коду C код Cperp также циклический.

Рассмотрим многочлен h(x) = (xn - 1)/g(x), где g(x) ПМ кода C. Если  deg(g(x)) = n - k, то deg(h(x)) = k и он также нормированный, поэтому h(x) порождает циклический код C' размерности  n - k. Пусть c1(x) = a1(x)g(x) из C и c2(x) = a2(x)h(x) из C'. Тогда

c1(x) c2(x) = a1(x)g(x)a2(x)h(x) = a1(x)a2(x)f(x) = 0 (mod f(x)),

где f(x) = xn - 1. Поэтому, используя умножение многочленов по модулю mod f(x), произведение любого кодового многочлена из C и любого многочлена из C' будет давать 0. Означает ли это, что C' -- дуальный к C код? К сожалению нет, поскольку построенный изоморфизм не сохраняет скалярное произведение, т.е. скалярное произведение векторов не соответствует нулевому произведению многочленов. Однако, коды C' и C тесно связаны - они эквивалентны.

Рассмотрим два вектора:

a = (a0 a1 ... an-1) из C
и
b = (b0 b1 ... bn-1) из C',

и их произведение (вернее, соответствующих многочленов)

[a(x) b(x) = sum from {i=0} to {n-1} c_i x^i (mod x^n - 1)]

для каких-то ci из F. Свободный член произведения

c0 = a0 b0 + a1bn-1 + a2 bn-2 + ... + an-1 b1,

т.к    xn = 1 (mod f(x)). Теперь c0 можно записать как скалярное произведение

c0 = a b'

где b' вектор, полученный из b циклическим сдвигом координат b на одну позицию влево и изменением порядка записи координат (т.е. (b0 bn-1 bn-2 ... b1)). Заметим, что умножение многочлена  [sum from {i=0} to {n-1} ci xi] на xn-t приводит к тому, что ct становится свободным членом, а значит  ct -- свободный член a(x)(xn-t b(x)). Поэтому,

ct = a b'

где b' теперь вектор, связанный с xn-t b(x). По отношению к b(x), b' это вектор, полученный циклическим сдвигом b на t+1 позиций влево с последующим изменением порядка координат на противоположный.

Примет: Пусть n = 3, и вектора a = (a0 a1 a2) и b = (b0 b1 b2). Перемножая их по  mod x3 - 1, получим

a(x)b(x) = (a0 + a1x + a2 x2)(b0 + b1x + b2 x2)
= (a0 b0 + a1b2 + a2 b1) + (a0 b1 + a1 b0 + a2 b2)x + (a0 b2 + a1 b1 + a2 b0)x2.

Коэффициент при x2 будет a(b2 b1 b0). Этот вектор b' получен из b сдвигом на 3 ( = 2 + 1) позиции влево (это ставит все координаты на старые места) и изменением порядка координат с последней на первую.  b-вектор в коэффициенте при x получается из b сдвигом на 2 ( = 1 + 1) позиции влево, что дает (b2 b0 b1) и изменением порядка следования  (b1 b0 b2).

    Теперь поскольку a(x)b(x) = 0 mod (xn - 1), коэффициенты при всех степенях x должны равняться 0. Вышеприведенное рассуждение приводит к заключению, что ac = 0 (т.е., векторы a и c ортогональны) для c полученного любой циклической перестановкой (сдвигом) вектора, координаты которого имеют противоположный порядок следования, чем у b. Поскольку h(x) порождает код C', {h(x), xh(x), ..., xn-k-1h(x) } это базис для C' и G' = [h(x), xh(x), ..., xn-k-1h(x)]t -- порождающая матрица для C'. Теперь G' порождает код C' той же размерности n - k, что и C . Более того, взяв в качестве b(x) сам h(x), мы видим, что обратнопереставленный любой вектор из C' ортогонален любому вектору из C. Это означает, что переставив в обратном порядке колонки  G', мы получим матрицу H, которая порождает код  Cperp , а значит является проверочной для C.

 

Пример: Предположим, что мы хотим построить порождающую матрицу для (7,4)- бинарного циклического кода. Поскольку g(x) = 1 + x + x3 делит f(x) = x7 - 1, то g(x) порождает (7,4) - циклический код C. h(x) = f(x)/g(x) = 1 + x + x2 + x4 порождает (7,3)-циклический код C'. Порождающая матрица для C 

[G = matrix { 1101000, 0110100, 0011010, 0001101}]

Порождающая матрица для  C' 

[G' = matrix { 1110100, 0111010, 0011101}]

Перепишем колонки G' в обратном порядке, получим  порождающую матрицу для Cperp (она же проверочная для исходного кода)

[H = matrix { 0010111, 0101110, 1011100}]

Нетрудно проверить, что  GHT = 0.

Поскольку C' и Cperp могут быть получены простой перестановкой координат всех векторов - это эквивалентные коды. Повторим ранее данное определение,

Определение : Пусть h(x) = a0 + a1 x + ... + ak xk многочлен степени k (ak#0). Определим   обратный многочлен hR (x) для h(x) формулой

[h_R (x) = sum from {i=0} to k a_{k-i} x^i]

Заметим, что hR(x) = xk h(1/x), где k = deg h(x). Суммируя все вышесказанное, получим следующее.

Tеорема: Пусть g(x) -- нормированный делитель f(x) = xn - 1 степени n-k, и, следовательно, ПМ для циклического (n,k)-кода C. Пусть h(x) = f(x)/g(x). Тогда hR(x) -- обратный многочлен к h(x), есть ПМ кода Cperp .

 

V. Синдромы и охота на ошибки

    Прежде всего рассмотрим альтернативный вид [R, Ik] порождающей матрицы циклического кода (систематический). Пусть g(x) ПМ кода. Разделим xn-k+i на g(x) для 0 <= i <= k-1. Это дает

xn-k+i = qi(x)g(x) + ri(x)

где deg(ri(x)) < deg (g(x)) = n-k или ri(x) = 0. Then

xn-k+i - ri(x) = qi(x)g(x) in C

система k линейно независящих кодовых слов, матрица, по строкам которой записаны эти слова, есть порождающая матрица требуемого вида.

Пример: Рассмотрим бинарный (7,4)-циклический код, порожденный g(x) = 1 + x + x3. Алгоритм деления дает:

x3 = (1)(x3 + x + 1) + (1+ x)
x4 = (x)(x3 + x + 1) + (x + x2)
x5 = (x2 + 1)(x3 + x + 1) + (1 + x + x2)
x6 = (x3 + x + 1)(x3 + x + 1) + (1 + x2).

Порождающая матрица

                    1 1 0 1 0 0 0                                         1 1 0
                    0 1 1 0 1 0 0                                         0 1 1
             G =    1 1 1 0 0 1 0    =  [R I4]            где   R  =      1 1 1
                    1 0 1 0 0 0 1                                         1 0 1   .
Заметим, что строки R как раз остатки от деления.

Соответствующая проверочная матрица это H = [In-k -Rt]. Разделение матрицы подобным образом  предоставляет возможность удобной полиномиальной интерпретации синдрома вектора.

Tеорема: Пусть r(x) и s(x) есть соответствующие полиномиальные представления для вектора r и его синдрома s = Hrt. Тогда s(x) -- остаток от деления r(x) на g(x).

Док-во: Пусть r(x) = a0 + a1 x + ... + an-1 xn-1. Заметим, что столбцы i, 0 <= i <= n-k-1, матрицы H соответствуют xi a столбцы j, n-k <= j <= n-1, соответствуют rj-n+k(x), так что

[s(x) = r(x) - h(x) g(x)]

где h(x) = an-k q0(x) + ... + an-1 qk-1(x). Таким образом r(x) = h(x)g(x) + s(x). Поскольку deg ri(x) <= n-k-1, то deg s(x) <= n-k-1. В силу единственности промежуточного частного и остатка при делении многочленов, мы можем заключить, что s(x) это остаток при делении r(x) на g(x).

Таким образом синдром вектора можно получить делением многочленов. Более того, синдром вектора и его циклического сдвига тесно связаны. Предположим, что

r(x) = q(x)g(x) + s(x),

где deg(s(x)) самое большее n-k-1. По вышеприведенной теореме s(x) синдром r(x). Теперь

xr(x) = xq(x)g(x) + xs(x).

Если степень xs(x) не более n-k-1, то снова это синдром xr(x). В противном случае, синдром xr(x) остаток от деления xs(x) на g(x). В этом случае, положим

[s(x) = s'(x) + s_{n-k-1} x^{n-k-1}]

Пусть ПМ

[g(x) = g'(x) +  x^{n-k}]

Тогда

[x s(x) = s_{n-k-1} g(x) + (x s'(x) -s_{n-k-1} g'(x) )]

где deg (xs'(x) - sn-k-1 g'(x)) <= n - k - 1. Теперь в силу единственности остатка и предыдущей теоремы, мы видим, что синдром xs(x) есть xs(x) - sn-k-1 g(x). Приходим к выводу:

Tеорема: Пусть C циклический (n,k)-код над F с ПМ g(x), и пусть r(x) имеет синдромный многочлен s(x) = s0 + s1 x + ... + sm xm. Тогда синдромный многочлен xr(x) есть

  1. xs(x) если deg s(x) < n-k-1, и
  2. xs(x) - sn-k-1 g(x), если deg s(x) = n-k-1.
Пример: Рассмотрим код предыдущего примера с ПМ g(x) = 1 + x + x3. Используя записанную там порождающую матрицу, мы можем получить проверочную матрицу,
                                              1 0 0 1 0 1 1
                       H = [I3  -Rt]  =       0 1 0 1 1 1 0    .
                                              0 0 1 0 1 1 1
Получили вектор r = (1011011). Синдром r равен Hrt = (001)t = s. Многочлен

r(x) = 1 + x2 + x3 + x5 + x6.

Если разделить r(x) на g(x), то получим

r(x) = (x3 + x2 + x + 1)g(x) + x2.

Остаток, как и следовало ожидать, равен  s.

А теперь найдем остаток циклического сдвига r. Положим w = (1101101), что соответствует многочлену xr(x). Hwt = (110)t. В полиномиальной интерпретации этот синдром получается так. Поскольку deg s(x) = 2 = n-k-1, синдром xr(x) есть

xs(x) - 1g(x) = x3 - (x3 + x + 1) = 1 + x.

    Предыдущее расмотрение дает нам интересный метод декодирования некоторых видов ошибок в циклических кодах. Эту технику иногда называют охотой(капканы) на ошибки ( error trapping).

    Предположим, что C это (n,k)-код с минимальным расстоянием d = 2t + 1, и проверочной матрицей H = [In-k A]. Пусть c кодовое слово и e вектор ошибки веса не более t. Если получено r = c + e , то синдром r равен

s = H rt = H (c + e)t = H et.

    Пусть e* = (st, 0), где 0 это k-вектор из 0'ей. Тогда H e*t = s, т.е. e* и e имеют один и тот же синдром, значит в одном смежном классе C. Теперь пусть wt(s) <= t. Тогда wt(e*)<= t и значит e = e* , поскольку смежный класс содержит не более одного вектора веса меньше или равного t.

       Следовательно, в этом случае ошибка известна и равна e = (st,0).

    Алгоритм декодирования

  1. Вычислим синдром s0(x) of r(x) по алгоритму деления.
  2. Положим i = 0.
  3. Если wt(si(x)) <= t, тогда установим e(x) = xn-i(si,0), и декодируем to r(x) - e(x).
  4. Положим i = i + 1.
  5. Если i = n then stop; ошибка не исправляется.
  6. Если deg si-1(x) < n-k-1, тогда set si(x) = xsi-1(x); иначе si(x) = xsi-1(x) - g(x).
  7. Go to (3).
Пример: g(x) = 1 + x2 + x3 генерирует бинарный (7,4)-циклический код с минимальным расстоянием 3 (и следовательно 1-ошибку исправляет). Рассмотрим кодовое слово 1 + x + x5 = (1 + x + x2) g(x), пусть после передачи многочлен r(x) = 1 + x + x5 + x6 был получен. Декодируем его. Разделим r(x) на g(x) для нахождения синдрома,

r(x) = (x3 + 1)g(x) + (x + x2),

так s(x) = x + x2.Так как вес s(x)  > 1 (= t), вычислим синдром s1(x)  xr(x). Так как of s(x) = 2 = n - k - 1, умножаем s(x) на x и делим на g(x), что дает  s1(x) = 1. Поскольку вес 1, мы получили маску ошибки

e(x) = x7-1(s1,0) = x6(1000000) = x6.

Так как  n = 7 все ошибки веса 1 имеют циклический сдвиг на шесть 0's и 6 > k = 4, исправляются все единичные ошибки..

Пример: g(x) = 1 + x4 + x6 + x7 + x8 порождает бинарный (15,7)-циклический код. Если минимальное расстояние 5(так), то t = 2. Некоторые (по меньшей мере) веса 2 маски ошибок могут содержать сдвиги не менее  7 0й и могут бытьотловлены. Если мы получили

r = (1100 1110 1100 010)

считаем,

r(x) = (x + x2 + x4 + x5)g(x) + (1 + x2 + x5 + x7).

Вычисляем синдромы si(x) для xi r(x) пока wt(si(x)) <= 2.

 

                               i              si(x)

                               0             10100101
                               1             11011001
                               2             11100111
                               3             11111000
                               4             01111100
                               5             00111110
                               6             00011111
                               7             10000100
Итак, ошибка

e = x15-7(s7,0) = x8(100001000000000) = (0000 0000 1000 010),

и мы исправляем  r(x) на r - e = (1100 1110 0100 000).

 



Hosted by uCoz