Коды антигрея
| Определение: |
| Код антигрея (англ. Anti-Gray Code) — такое упорядочивание -ичных векторов, что расстояние Хэмминга между двумя соседними векторами максимально. |
Код антигрея может использоваться для обнаружения неисправностей в устройстве при переходе в соседнее состояние. Часто используется в приборах, устанавливающихся на улице. Такое кодирование позволяет вовремя выявить поломку или какое-то загрязнение и своевременно устранить неисправность.
Содержание
Двоичный код антигрея
| Определение: |
| Двоичный код антигрея — такое упорядочивание двоичных векторов длины , что соседние отличаются не менее, чем в битах. |
Заметим: упорядочивание векторов такое, что соседние отличаются во всех битах, возможно только для . Это объясняется тем, что для двоичного вектора существует ровно один вектор, отличающийся во всех битах, а в последовательности, где , таких векторов должно быть два.
Пример
| n = 1 | n = 2 | n = 3 |
|---|---|---|
| 0 | 00 | 000 |
| 1 | 11 | 111 |
| 01 | 001 | |
| 10 | 110 | |
| 011 | ||
| 100 | ||
| 010 | ||
| 101 |
Алгоритм генерации
Возьмем двоичный зеркальный код Грея размером . Тогда для первых двоичных векторов будем:
- Печатать двоичный вектор
- Печатать его инверсию
Утверждается, что с помощью данного алгоритма мы напечатаем двоичный код антигрея.
Псевдокод
function genBinAntiGray(n: int)
for i = 1 to 2**(n-1)
v = getMirrorGray(i, n)
print(v)
inverseBits(v)
print(v)
Доказательство корректности алгоритма
Обозначим за — -ый вектор в зеркальном коде Грея, — его инверсию.
Тогда вектора будут располагаться в таком порядке:
- ...
-
-
-
-
-
- ...
и отличаются во всех битах.
Если и отличаются в -ом бите, то инверсия совпадает с только в -ом бите. То есть и отличаются во всех позициях, кроме -ой.
Троичный код антигрея
| Определение: |
| Троичный код антигрея — такое упорядочивание троичных векторов, что соседние отличаются во всех разрядах. |
В отличие от двоичного кода антигрея, здесь мы не сталкиваемся с проблемой однозначности "соседа" и можем привести такой код, соседние элементы которого будут отличаться во всех разрядах.
Пример
| n = 1 | n = 2 | n = 3 | ||
|---|---|---|---|---|
| 0 | 00 | 000 | 010 | 020 |
| 1 | 11 | 111 | 121 | 101 |
| 2 | 22 | 222 | 202 | 212 |
| 01 | 001 | 011 | 021 | |
| 12 | 112 | 122 | 102 | |
| 20 | 220 | 200 | 210 | |
| 02 | 002 | 012 | 022 | |
| 10 | 110 | 120 | 100 | |
| 21 | 221 | 201 | 211 | |
Алгоритм генерации
Упорядочим все троичные вектора лексикографически. Тогда для первых векторов будем выводить сначала сам этот вектор, потом 2 его поразрядных циклических сдвига.
Например, если мы имеем вектор , то вы выведем: , , .
Утверждается, что выполняя эти действия мы получим троичный код антигрея.
Псевдокод
function genTernAntiGray(n: int)
for v = <000..0> to <022..2>
digitCircleShift(v)
while(v[0] != 0)
print(v)
digitCircleShift(v)
Заметим, что данный алгоритм можно обобщить на случай -ичного кода антигрея.
Доказательство корректности алгоритма
Обозначим -ый троичный вектор как , его первый и второй циклический сдвиги как и соответственно. Получаем вектора в следующем порядке:
- ...
-
-
-
-
- ...
и , равно как и , отличаются во всех битах.
Если говорить о векторах как о троичных числах, то получено из прибавлением единицы, это значит, что у несколько разрядов справа на единицу больше (по модулю ), чем у (по правилам сложения в столбик). С другой стороны получено из двумя циклическими сдвигами вперёд, что равносильно одному циклическому сдвигу назад. Таким образом, в числе некоторые биты такие же, как в , остальные на единицу больше; в числе все биты на один меньше по сравнению с , значит и различны во всех битах.
Подобные рассуждения можно провести для любого -ичного кода антигрея, где .