Коды антигрея — различия между версиями
(→Псевдокод) |
м (rollbackEdits.php mass rollback) |
||
(не показано 27 промежуточных версий 9 участников) | |||
Строка 1: | Строка 1: | ||
− | |||
− | |||
{{Определение | {{Определение | ||
|definition= | |definition= | ||
− | '''Код антигрея (Anti-Gray Code | + | '''Код антигрея''' (англ. ''Anti-Gray Code'') {{---}} такое упорядочивание <tex>k</tex>-ичных векторов, что [[расстояние Хэмминга]] между двумя соседними векторами максимально. |
}} | }} | ||
− | + | Код антигрея может использоваться для обнаружения неисправностей в устройстве при переходе в соседнее состояние. Часто используется в приборах, устанавливающихся на улице. Такое кодирование позволяет вовремя выявить поломку или какое-то загрязнение и своевременно устранить неисправность. | |
− | |||
== Двоичный код антигрея == | == Двоичный код антигрея == | ||
{{Определение | {{Определение | ||
|definition= | |definition= | ||
− | '''Двоичный код антигрея''' {{---}} такое упорядочивание двоичных векторов длины <tex>n</tex>, что соседние отличаются не менее, чем в <tex>n-1</tex> битах. | + | '''Двоичный код антигрея''' (англ. ''Binary Anti-Gray Code'') {{---}} такое упорядочивание двоичных векторов длины <tex>n</tex>, что соседние отличаются не менее, чем в <tex>n-1</tex> битах. |
}} | }} | ||
− | + | Заметим: упорядочивание векторов такое, что соседние отличаются во всех битах, возможно только для <tex>n = 1</tex>. Это объясняется тем, что для двоичного вектора существует ровно один вектор, отличающийся во всех битах, а в последовательности, где <tex>n > 1</tex>, таких векторов должно быть два. | |
− | |||
=== Пример === | === Пример === | ||
Строка 40: | Строка 36: | ||
=== Алгоритм генерации === | === Алгоритм генерации === | ||
− | Возьмем двоичный зеркальный [[Коды Грея | код Грея]] размером <tex>n</tex>. Тогда для первых <tex>2^{n-1}</tex> двоичных | + | Возьмем двоичный зеркальный [[Коды Грея | код Грея]] размером <tex>n</tex>. Тогда для первых <tex>2^{n-1}</tex> двоичных векторов будем: |
− | |||
− | |||
+ | # Печатать двоичный вектор | ||
# Печатать его инверсию | # Печатать его инверсию | ||
− | Утверждается, что с помощью данного алгоритма мы | + | Утверждается, что с помощью данного алгоритма мы напечатаем двоичный код антигрея. |
=== Псевдокод === | === Псевдокод === | ||
− | + | '''function''' genBinAntiGray(n: '''int'''): | |
− | genBinAntiGray(n) | + | '''for''' i = 1 '''to''' 2 ** (n - 1) |
− | for i = 1 to 2 | ||
v = getMirrorGray(i, n) | v = getMirrorGray(i, n) | ||
print(v) | print(v) | ||
Строка 59: | Строка 53: | ||
=== Доказательство корректности алгоритма === | === Доказательство корректности алгоритма === | ||
− | + | Обозначим за <tex>G_i</tex> — <tex>i</tex>-ый вектор в зеркальном коде Грея, <tex>\overline G_i</tex> — его инверсию. | |
+ | Тогда вектора будут располагаться в таком порядке: | ||
+ | :<tex>\dots</tex> <br> | ||
+ | :<tex>G_i</tex> <br> | ||
+ | :<tex>\overline G_i</tex> <br> | ||
+ | :<tex>G_{i+1}</tex> <br> | ||
+ | :<tex>\overline G_{i+1}</tex> <br> | ||
+ | :<tex>G_{i+2}</tex> <br> | ||
+ | :<tex>\dots</tex> | ||
+ | <tex>G_i</tex> и <tex>\overline G_i</tex> отличаются во всех битах. <br> | ||
+ | Если <tex>G_i</tex> и <tex>G_{i+1}</tex> отличаются в <tex>k</tex>-ом бите, то инверсия <tex>G_i</tex> совпадает с <tex>G_{i+1}</tex> только в <tex>k</tex>-ом бите. То есть <tex>\overline G_i</tex> и <tex>G_{i+1}</tex> отличаются во всех позициях, кроме <tex>k</tex>-ой. | ||
== Троичный код антигрея == | == Троичный код антигрея == | ||
{{Определение | {{Определение | ||
|definition= | |definition= | ||
− | '''Троичный код антигрея''' {{---}} такое упорядочивание троичных | + | '''Троичный код антигрея''' (англ. ''Ternary Anti-Gray Code'') {{---}} такое упорядочивание троичных векторов, что соседние отличаются во всех разрядах. |
}} | }} | ||
+ | В отличие от двоичного кода антигрея, здесь мы не сталкиваемся с проблемой однозначности "соседа" и можем привести такой код, соседние элементы которого будут отличаться во всех разрядах. | ||
− | + | === Алгоритм генерации === | |
+ | |||
+ | Упорядочим все троичные вектора лексикографически. Тогда для первых <tex>3^{n-1}</tex> векторов будем выводить сначала сам этот вектор, потом <tex>2</tex> его поразрядных циклических сдвига (каждый отдельный бит увеличиваем на <tex>1</tex>). | ||
+ | <br>Например, если мы имеем вектор <tex>021</tex>, то вы выведем: <tex>021</tex>, <tex>102</tex>, <tex>210</tex>. | ||
+ | |||
+ | Утверждается, что выполняя эти действия мы получим троичный код антигрея. | ||
+ | |||
+ | === Псевдокод === | ||
+ | <code> | ||
+ | '''function''' genTernAntiGray(n: '''int'''): | ||
+ | '''for''' v = <000..0> '''to''' <022..2> <span style="color:Green">// троичные вектора длины <tex>n</tex> </span> | ||
+ | '''for''' i = 0 '''to''' 2 | ||
+ | print(v) | ||
+ | digitCircleShift(v) | ||
+ | </code> | ||
+ | Заметим, что данный алгоритм можно обобщить на случай <tex>k</tex>-ичного кода антигрея. | ||
− | === | + | === Примеры работы алгоритма === |
{| class="wikitable" | {| class="wikitable" | ||
− | ! n = 1 | + | !colspan="2" align="center"| n = 1 |
− | + | !colspan="2" align="center"| n = 2 | |
− | + | !colspan="3" align="center"| n = 3 | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|- | |- | ||
− | | || | + | !align="center"|Первые <tex>3^{n-1}</tex><br>векторов |
+ | !align="center"|Коды антигрея | ||
+ | !align="center"|Первые <tex>3^{n-1}</tex><br>векторов | ||
+ | !align="center"|Коды антигрея | ||
+ | !align="center"|Первые <tex>3^{n-1}</tex><br>векторов | ||
+ | !colspan="2" align="center"|Коды антигрея | ||
|- | |- | ||
− | | || | + | | '''0''' || '''0''' || '''00''' || '''00''' || '''000''' || '''000''' || 200 |
|- | |- | ||
− | | || | + | | || 1 || '''01''' || 11 || '''001''' || 111 || '''012''' |
|- | |- | ||
− | | || | + | | || 2 || '''02''' || 22 || '''002''' || 222 || 120 |
|- | |- | ||
− | | || || 010 | + | | || || || '''01''' || '''010''' || '''001''' || 201 |
|- | |- | ||
− | | || || | + | | || || || 12 || '''011''' || 112 || '''020''' |
|- | |- | ||
− | | || || | + | | || || || 20 || '''012''' || 220 || 101 |
|- | |- | ||
− | | || || | + | | || || || '''02''' || '''020''' || '''002''' || 212 |
|- | |- | ||
− | | || || | + | | || || || 10 || '''021''' || 110 || '''021''' |
|- | |- | ||
− | | || || | + | | || || || 21 || '''022''' || 221 || 102 |
|- | |- | ||
− | | || || | + | | || || || || || '''010''' || 210 |
|- | |- | ||
− | | || || | + | | || || || || || 121 || '''022''' |
|- | |- | ||
− | | || || | + | | || || || || || 202 || 100 |
|- | |- | ||
− | | || || | + | | || || || || || '''011''' || 211 |
|- | |- | ||
− | | || || | + | | || || || || || 122 || |
− | | | ||
− | | || || | ||
− | | | ||
− | | | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
|} | |} | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
=== Доказательство корректности алгоритма === | === Доказательство корректности алгоритма === | ||
− | + | Обозначим <tex>i</tex>-ый троичный вектор как <tex>G_i^0</tex>, его первый и второй циклический сдвиги как <tex>G_i^1</tex> и <tex>G_i^2</tex> соответственно. Получаем вектора в следующем порядке: | |
+ | :<tex>\dots</tex> <br> | ||
+ | :<tex>G_i^0</tex> <br> | ||
+ | :<tex>G_i^1</tex> <br> | ||
+ | :<tex>G_i^2</tex> <br> | ||
+ | :<tex>G_{i+1}^0</tex> <br> | ||
+ | :<tex>\dots</tex> | ||
+ | <tex >G_i^0</tex> и <tex>G_i^1</tex>, равно как <tex>G_i^1</tex> и <tex>G_i^2</tex>, отличаются во всех битах. <br> | ||
+ | Если говорить о векторах как о троичных числах, то <tex>G_{i+1}^0</tex> получено из <tex>G_i^0</tex> прибавлением единицы, это значит, что у <tex>G_{i+1}^0</tex> несколько разрядов справа на единицу больше (по модулю <tex>3</tex>), чем у <tex>G_i^0</tex> (по правилам сложения в столбик). С другой стороны <tex>G_{i}^2</tex> получено из <tex>G_{i}^0</tex> двумя циклическими сдвигами вперёд, что равносильно одному циклическому сдвигу назад. Таким образом, в числе <tex>G_{i+1}^0</tex> некоторые биты такие же, как в <tex>G_{i}^0</tex>, остальные на единицу больше; в числе <tex>G_{i}^2</tex> все биты на один меньше по сравнению с <tex>G_{i}^0</tex>, значит <tex>G_{i}^2</tex> и <tex>G_{i+1}^0</tex> различны во всех битах. | ||
+ | Подобные рассуждения можно провести для любого <tex>k</tex>-ичного кода антигрея, где <tex>k \geqslant 3</tex>. | ||
== См. также == | == См. также == | ||
Строка 156: | Строка 151: | ||
*[[Цепные коды]] | *[[Цепные коды]] | ||
− | == Источники == | + | == Источники информации == |
+ | |||
+ | *[http://en.wikipedia.org/wiki/Gray_code Wikipedia {{---}} Gray code] | ||
+ | |||
+ | [[Категория: Дискретная математика и алгоритмы]] | ||
− | + | [[Категория: Комбинаторика]] |
Текущая версия на 19:03, 4 сентября 2022
Определение: |
Код антигрея (англ. Anti-Gray Code) — такое упорядочивание расстояние Хэмминга между двумя соседними векторами максимально. | -ичных векторов, что
Код антигрея может использоваться для обнаружения неисправностей в устройстве при переходе в соседнее состояние. Часто используется в приборах, устанавливающихся на улице. Такое кодирование позволяет вовремя выявить поломку или какое-то загрязнение и своевременно устранить неисправность.
Содержание
Двоичный код антигрея
Определение: |
Двоичный код антигрея (англ. Binary 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)
Доказательство корректности алгоритма
Обозначим за
— -ый вектор в зеркальном коде Грея, — его инверсию. Тогда вектора будут располагаться в таком порядке:
Если и отличаются в -ом бите, то инверсия совпадает с только в -ом бите. То есть и отличаются во всех позициях, кроме -ой.
Троичный код антигрея
Определение: |
Троичный код антигрея (англ. Ternary Anti-Gray Code) — такое упорядочивание троичных векторов, что соседние отличаются во всех разрядах. |
В отличие от двоичного кода антигрея, здесь мы не сталкиваемся с проблемой однозначности "соседа" и можем привести такой код, соседние элементы которого будут отличаться во всех разрядах.
Алгоритм генерации
Упорядочим все троичные вектора лексикографически. Тогда для первых
Например, если мы имеем вектор , то вы выведем: , , .
Утверждается, что выполняя эти действия мы получим троичный код антигрея.
Псевдокод
function genTernAntiGray(n: int):
for v = <000..0> to <022..2> // троичные вектора длины
for i = 0 to 2
print(v)
digitCircleShift(v)
Заметим, что данный алгоритм можно обобщить на случай
-ичного кода антигрея.Примеры работы алгоритма
n = 1 | n = 2 | n = 3 | ||||
---|---|---|---|---|---|---|
Первые векторов |
Коды антигрея | Первые векторов |
Коды антигрея | Первые векторов |
Коды антигрея | |
0 | 0 | 00 | 00 | 000 | 000 | 200 |
1 | 01 | 11 | 001 | 111 | 012 | |
2 | 02 | 22 | 002 | 222 | 120 | |
01 | 010 | 001 | 201 | |||
12 | 011 | 112 | 020 | |||
20 | 012 | 220 | 101 | |||
02 | 020 | 002 | 212 | |||
10 | 021 | 110 | 021 | |||
21 | 022 | 221 | 102 | |||
010 | 210 | |||||
121 | 022 | |||||
202 | 100 | |||||
011 | 211 | |||||
122 |
Доказательство корректности алгоритма
Обозначим
-ый троичный вектор как , его первый и второй циклический сдвиги как и соответственно. Получаем вектора в следующем порядке:
Если говорить о векторах как о троичных числах, то получено из прибавлением единицы, это значит, что у несколько разрядов справа на единицу больше (по модулю ), чем у (по правилам сложения в столбик). С другой стороны получено из двумя циклическими сдвигами вперёд, что равносильно одному циклическому сдвигу назад. Таким образом, в числе некоторые биты такие же, как в , остальные на единицу больше; в числе все биты на один меньше по сравнению с , значит и различны во всех битах.
Подобные рассуждения можно провести для любого -ичного кода антигрея, где .