Монотонный код Грея — различия между версиями
Gpevnev (обсуждение | вклад) |
Gpevnev (обсуждение | вклад) |
||
| Строка 19: | Строка 19: | ||
Пусть <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>\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>. | + | Тогда монотонным кодом Грея будет являтся [[:Гамильтоновы_графы#.D0.9E.D1.81.D0.BD.D0.BE.D0.B2.D0.BD.D1.8B.D0.B5_.D0.BE.D0.BF.D1.80.D0.B5.D0.B4.D0.B5.D0.BB.D0.B5.D0.BD.D0.B8.D1.8F|Гамильтонов путь]] в <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'').<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> | Ниже на катринке Гамильтонов путь в гиперкубе <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> | ||
Версия 16:52, 18 декабря 2016
| Определение: |
| Монотонный код Грея (англ. Monotonic Gray Code) — способ построения кода Грея, при котором , что содержит на или больше единиц, чем . |
Монотонный код Грея преимущественно используется в теории связанных сетей, например для минимизации ожидания линейным массивом процессоров.[1]
Содержание
Алгоритм построения
Для начала определим такое понятие, как вес двоичного кода, им будет являтся количество в данном двоичном коде. Очевидно, что нельзя построить код Грея в котором бы вес всегда возрастал. Неплохим решением этой проблемы будет обход всех кодов со смежными с данным весами.
Мы можем формализовать модель монотонных кодов Грея рассматривая разбиение гиперкуба , вершины в котором являются двоичными кодами, на уровни с одинаковым весом вершин.
для . Для всех уровней выполняется соотношение .
Пусть подграф , который является объединением двух смежных уровней, т. е. , и пусть множество граней . Тогда монотонным кодом Грея будет являтся Гамильтонов путь в , при котором любое множество вершин такие, что , то идет перед .
Ниже на катринке Гамильтонов путь в гиперкубе для , построенный по алгоритму Саважа-Винклера (англ. Savage-Winkler).[2]
Элегантная идея построения -ичного монотонного кода Грея состоит в том, чтобы рекурсивно строить подпути длинны включающих вершины .
Определим и , когда или и . То есть это объединение множеств с приписанной в начале 1 и с приписанным в начале нулем.
Здесь это определенная перестановка элементов множества к которому она применена, а это путь к котрому была применена пересатновка . Существует два варианта построить монотонный код грея по путям .
Назовем их и . Будем строить их таким образом:
Выбор перестановки обусловлен тем, чтобы получившиеся коды соответсвовали требованиям кода Грея и поэтому эта перестановка равна .
Чтобы лучше разобратся в том, как сторится этот код и работает перестановка следует рассмотреть таблицу ниже.
Монотонный код Грея может быть эффективно сгенерирован по этому алгоритму за время . Легче всего написать этот алгоритм используя генератор.
Псевдокод
Перед тем как писать псевдокод необходимо объяснить что такое yield и что понимать под выражениями типа (0,) или (1,).
yield - аналог return только для функций-генераторов. То есть генераторы это тоже итерируемые объекты, но прочитать их можно лишь один раз. Это связано с тем, что они не хранят значения в памяти, а генерируют их на лету.
С конструкциями типа (0,) или (1,) все проще. Используя ее совместно с yield мы можем в изменять наш генерируемый объект. Например, yield (0,) допишет к генерируемому объекту (в нашем случае кортежу (англ. tuple)) в начало.
rotateRight(x, n): return x[-n:] + x[:-n]
pi(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):
for i in range(n):
for x in (p(n, i) if i % 2 == 0 else p(n, i, reverse=True)):
yield x
|
Визуализация работы алгоритма
Для
Для


