Монотонный код Грея — различия между версиями
Gpevnev (обсуждение | вклад) |
Gpevnev (обсуждение | вклад) |
||
Строка 3: | Строка 3: | ||
'''Монотонный код Грея''' (англ. ''Monotonic Gray Code'') {{---}} способ построения кода Грея, при котором <tex>\nexists</tex> <tex>g_i, g_j</tex>, что <tex>g_i</tex> содержит на <tex>2</tex> или больше единиц, чем <tex>g_j</tex>. | '''Монотонный код Грея''' (англ. ''Monotonic Gray Code'') {{---}} способ построения кода Грея, при котором <tex>\nexists</tex> <tex>g_i, g_j</tex>, что <tex>g_i</tex> содержит на <tex>2</tex> или больше единиц, чем <tex>g_j</tex>. | ||
}} | }} | ||
− | Монотонный код Грея преимущественно используется в теории связанных сетей, например для минимизации ожидания линейным массивом процессоров. | + | Монотонный код Грея преимущественно используется в теории связанных сетей, например для минимизации ожидания линейным массивом процессоров.<ref>[http://www.sciencedirect.com/science/article/pii/0097316595900918 C. D Savage and P. Winkler (1995). "Monotone Gray codes and the middle levels problem"page 7]</ref> |
== Алгоритм построения == | == Алгоритм построения == | ||
− | Для начала определим такое понятие, как ''вес'' двоичного кода, им будет являтся количество <tex>1</tex> в данном двоичном коде. Очевидно, что нельзя построить код Грея в котором бы вес всегда возрастал. | + | Для начала определим такое понятие, как ''вес'' двоичного кода, им будет являтся количество <tex>1</tex> в данном двоичном коде. Очевидно, что нельзя построить [[:Коды_Грея|код Грея]] в котором бы вес всегда возрастал. |
Неплохим решением этой проблемы будет обход всех кодов со смежными с данным весами. | Неплохим решением этой проблемы будет обход всех кодов со смежными с данным весами. | ||
Строка 13: | Строка 13: | ||
<tex> | <tex> | ||
− | V_n(i) = \{ v \ | + | V_n(i) = \{ v \mid V_n : v \text{ has weight } i \} |
</tex> | </tex> | ||
− | для <tex>0 \ | + | для <tex>0 \leqslant i \leqslant n</tex>. Для всех уровней выполняется соотношение <tex>|V_n(i)| = C_n^i</tex>. |
Пусть <tex>Q_n(i)</tex> подграф <tex>Q_n</tex>, который является обединением двух смежных уровней, т. е. <tex>V_n(i) \cup V_n(i+1)</tex>, и пусть <tex>E_n(i)</tex> множество граней <tex>Q_n(i)</tex>. | Пусть <tex>Q_n(i)</tex> подграф <tex>Q_n</tex>, который является обединением двух смежных уровней, т. е. <tex>V_n(i) \cup V_n(i+1)</tex>, и пусть <tex>E_n(i)</tex> множество граней <tex>Q_n(i)</tex>. | ||
− | Тогда монотонным кодом Грея будет являтся Гамильтонов путь в <tex>Q_n</tex>, при котором | + | Тогда монотонным кодом Грея будет являтся [[:Гамильтоновы_графы|Гамильтонов путь]] в <tex>Q_n</tex>, при котором любое множество вершин <tex>\delta_1 , \delta_2</tex> такие, что <tex>\forall i, j : i \leqslant j</tex>, то <tex>\delta_1 \in E_n(i)</tex> идет перед <tex>\delta_2 \in E_n(j)</tex>. |
− | Ниже на катринке Гамильтонов путь в гиперкубе <tex>Q_4</tex> для <tex>n = 4</tex>, построенный по алгоритму Саважа-Винклера(англ. ''Savage-Winkler''). | + | Ниже на катринке Гамильтонов путь в гиперкубе <tex>Q_4</tex> для <tex>n = 4</tex>, построенный по алгоритму Саважа-Винклера (англ. ''Savage-Winkler'').<ref>[http://www.sciencedirect.com/science/article/pii/0097316595900918 C. D Savage and P. Winkler (1995). "Monotone Gray codes and the middle levels problem"page 14]</ref> |
[[Файл:Monotonic_Gray_Code_Graph.png|center|4-ичный монотооный код Грея]] | [[Файл:Monotonic_Gray_Code_Graph.png|center|4-ичный монотооный код Грея]] | ||
Строка 37: | Строка 37: | ||
Назовем их <tex>G_n^{(1)}</tex> и <tex>G_n^{(2)}</tex>. Будем строить их таким образом: | Назовем их <tex>G_n^{(1)}</tex> и <tex>G_n^{(2)}</tex>. Будем строить их таким образом: | ||
<tex> | <tex> | ||
− | G_n^{(1)} = P_{n,0} P_{n,1}^R P_{n,2} P_{n,3}^R \ | + | G_n^{(1)} = P_{n,0} P_{n,1}^R P_{n,2} P_{n,3}^R \ldots \text{, } G_n^{(2)} = P_{n,0}^R P_{n,1} P_{n,2}^R P_{n,3} \ldots |
</tex> | </tex> | ||
Строка 76: | Строка 76: | ||
|align="left" colspan="4"| | |align="left" colspan="4"| | ||
<code> | <code> | ||
− | <font color = | + | rotateRight(x, n):<font color=green> // Вспомогательная функция для генерации перестановки, циклически сдвигает битовый вектор направо <tex>n</tex> раз. Принимает и возвращает котреж (англ. ''tuple'').</font> |
'''return''' x[-n:] + x[:-n] | '''return''' x[-n:] + x[:-n] | ||
− | <font color = | + | pi(n):<font color=green> // Рекурсивная генерация <tex>n</tex>-ой перестановки. Возвращает перестановку в виде кортежа. Если n становится меньше <tex>2</tex> дописывает в начало кортежа <tex>0</tex> и возвращает его.</font> |
'''if''' n <= 1: | '''if''' n <= 1: | ||
'''return''' (0,) | '''return''' (0,) | ||
x = pi(n - 1) + (n - 1,) | x = pi(n - 1) + (n - 1,) | ||
'''return''' rotate_right('''tuple'''(x[k] '''for''' k '''in''' x), 1) | '''return''' rotate_right('''tuple'''(x[k] '''for''' k '''in''' x), 1) | ||
− | <font color = | + | p(n, j, reverse = ''false''):<font color=green> // Рекурсивная генерация пути <tex>P_{n, j}</tex>. Принимает <tex>n, j</tex>, а так же дополнительный параметр определяющий надо-ли переворачивать кортеж.</font> |
if n == 1 and j == 0: | if n == 1 and j == 0: | ||
'''if''' '''not''' reverse: | '''if''' '''not''' reverse: | ||
Строка 103: | Строка 103: | ||
'''for''' x '''in''' p(n - 1, j - 1, reverse=True): | '''for''' x '''in''' p(n - 1, j - 1, reverse=True): | ||
'''yield''' (1,) + '''tuple'''(x[k] '''for''' k '''in''' perm) | '''yield''' (1,) + '''tuple'''(x[k] '''for''' k '''in''' perm) | ||
− | <font color = | + | monotonic(n):<font color=green> // Генерация монотонного кода Грея при помощи уже написанной сопрограммы p.</font> |
'''for''' i '''in''' range(n): | '''for''' i '''in''' range(n): | ||
'''for''' x '''in''' (p(n, i) '''if''' i % 2 == 0 '''else''' p(n, i, reverse=True)): | '''for''' x '''in''' (p(n, i) '''if''' i % 2 == 0 '''else''' p(n, i, reverse=True)): |
Версия 19:01, 6 декабря 2016
Определение: |
Монотонный код Грея (англ. Monotonic Gray Code) — способ построения кода Грея, при котором | , что содержит на или больше единиц, чем .
Монотонный код Грея преимущественно используется в теории связанных сетей, например для минимизации ожидания линейным массивом процессоров.[1]
Содержание
Алгоритм построения
Для начала определим такое понятие, как вес двоичного кода, им будет являтся количество код Грея в котором бы вес всегда возрастал. Неплохим решением этой проблемы будет обход всех кодов со смежными с данным весами.
в данном двоичном коде. Очевидно, что нельзя построитьМы можем формализовать модель монотонных кодов Грея рассматривая разбиение гиперкуба
, вершины в котором являются двоичными кодами, на уровни с одинаковым весом вершин.
для
. Для всех уровней выполняется соотношение .Пусть Гамильтонов путь в , при котором любое множество вершин такие, что , то идет перед .
подграф , который является обединением двух смежных уровней, т. е. , и пусть множество граней . Тогда монотонным кодом Грея будет являтсяНиже на катринке Гамильтонов путь в гиперкубе [2]
для , построенный по алгоритму Саважа-Винклера (англ. Savage-Winkler).Элегантная идея построения
-ичного монотонного кода Грея состоит в том, чтобы рекурсивно строить подпути длинны включающих вершины .Определим
и , когда или и .Здесь
это определенная перестановка элементов множества к которому она применена, а это путь к котрому была применена пересатновка . Существует два варианта построить моготонный код грея по путям .Назовем их
и . Будем строить их таким образом:Выбор перестановки
обусловлен тем, чтобы получившиеся коды соответсвовали требованиям кода Грея и поэтому эта перестановка равна .Чтобы лучше разобратся в том, как сторится этот код и работает перестановка
следует рассмотреть таблицу ниже.Монотонный код Грея может быть эффективно сгенерирован по этому алгоритму за время
. Легче всего написать этот алгоритм используя сопрограмму.Псевдокод
rotateRight(x, n): // Вспомогательная функция для генерации перестановки, циклически сдвигает битовый вектор направораз. Принимает и возвращает котреж (англ. tuple). return x[-n:] + x[:-n] pi(n): // Рекурсивная генерация -ой перестановки. Возвращает перестановку в виде кортежа. Если n становится меньше дописывает в начало кортежа и возвращает его. if n <= 1: return (0,) x = pi(n - 1) + (n - 1,) return rotate_right(tuple(x[k] for k in x), 1) p(n, j, reverse = false): // Рекурсивная генерация пути . Принимает , а так же дополнительный параметр определяющий надо-ли переворачивать кортеж. if n == 1 and j == 0: if not reverse: yield (0,) yield (1,) else: yield (1,) yield (0,) elif j >= 0 and j < n: perm = pi(n - 1) if not reverse: for x in p(n - 1, j - 1): yield (1,) + tuple(x[k] for k in perm) for x in p(n - 1, j): yield (0,) + x else: for x in p(n - 1, j, reverse=True): yield (0,) + x for x in p(n - 1, j - 1, reverse=True): yield (1,) + tuple(x[k] for k in perm) monotonic(n): // Генерация монотонного кода Грея при помощи уже написанной сопрограммы p. for i in range(n): for x in (p(n, i) if i % 2 == 0 else p(n, i, reverse=True)): yield x
|
Визуализация работы алгоритма
Для
Для