Монотонный код Грея — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
Строка 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 \in V_n : v \text{ has weight } i \}
+
V_n(i) = \{ v \mid V_n : v \text{ has weight } i \}
 
</tex>
 
</tex>
  
для <tex>0 \leq i \leq n</tex>. Для всех уровней выполняется соотношение <tex>|V_n(i)| = \binom{n}{i}</tex>.
+
для <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>\delta_1 \in E_n(i)</tex> идет перед <tex>\delta_2 \in E_n(j)</tex>, то <tex>i \leq j</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 \cdots \text{, } G_n^{(2)} = P_{n,0}^R P_{n,1} P_{n,2}^R P_{n,3} \cdots
+
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 = brown>rotate_right</font>(x, n):
+
rotateRight(x, n):<font color=green> // Вспомогательная функция для генерации перестановки, циклически сдвигает битовый вектор направо <tex>n</tex> раз. Принимает и возвращает котреж (англ. ''tuple'').</font>
 
     '''return''' x[-n:] + x[:-n]
 
     '''return''' x[-n:] + x[:-n]
<font color = brown>pi</font>(n):
+
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 = brown>p</font>(n, j, reverse=False):
+
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 = brown>monotonic</font>(n):
+
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) — способ построения кода Грея, при котором gi,gj, что gi содержит на 2 или больше единиц, чем gj.

Монотонный код Грея преимущественно используется в теории связанных сетей, например для минимизации ожидания линейным массивом процессоров.[1]

Алгоритм построения

Для начала определим такое понятие, как вес двоичного кода, им будет являтся количество 1 в данном двоичном коде. Очевидно, что нельзя построить код Грея в котором бы вес всегда возрастал. Неплохим решением этой проблемы будет обход всех кодов со смежными с данным весами.

Мы можем формализовать модель монотонных кодов Грея рассматривая разбиение гиперкуба Qn=(Vn,En), вершины в котором являются двоичными кодами, на уровни с одинаковым весом вершин.

Vn(i)={vVn:v has weight i}

для 0in. Для всех уровней выполняется соотношение |Vn(i)|=Cin.

Пусть Qn(i) подграф Qn, который является обединением двух смежных уровней, т. е. Vn(i)Vn(i+1), и пусть En(i) множество граней Qn(i). Тогда монотонным кодом Грея будет являтся Гамильтонов путь в Qn, при котором любое множество вершин δ1,δ2 такие, что i,j:ij, то δ1En(i) идет перед δ2En(j).

Ниже на катринке Гамильтонов путь в гиперкубе Q4 для n=4, построенный по алгоритму Саважа-Винклера (англ. Savage-Winkler).[2]

4-ичный монотооный код Грея

Элегантная идея построения n-ичного монотонного кода Грея состоит в том, чтобы рекурсивно строить подпути Pn,j длинны 2 \binom{n}{j} включающих вершины E_n(j).

Определим P_{1,0} = (0, 1) и P_{n,j} = \emptyset, когда j \lt 0 или j \geq n и P_{n+1,j} = 1P^{\pi_n}_{n,j-1}, 0P_{n,j} .

Здесь \pi_n это определенная перестановка элементов множества к которому она применена, а P^{\pi} это путь P к котрому была применена пересатновка \pi. Существует два варианта построить моготонный код грея по путям P_{n, j}.

Назовем их G_n^{(1)} и G_n^{(2)}. Будем строить их таким образом: 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

Выбор перестановки \pi_n обусловлен тем, чтобы получившиеся коды соответсвовали требованиям кода Грея и поэтому эта перестановка равна \pi_n = E^{-1}(\pi_{n-1}^2).

Чтобы лучше разобратся в том, как сторится этот код и работает перестановка \pi следует рассмотреть таблицу ниже.

Подпути алгоритма Саважа-Винклера
P_{n,j} j = 0 j = 1 j = 2 j = 3
n = 1 0, 1
n = 2 00, 01 10, 11
n = 3 000, 001 100, 110, 010, 011 101, 111
n = 4 0000, 0001 1000, 1100, 0100, 0110, 0010, 0011 1010, 1011, 1001, 1101, 0101, 0111 1110, 1111

Монотонный код Грея может быть эффективно сгенерирован по этому алгоритму за время O(n). Легче всего написать этот алгоритм используя сопрограмму.

Псевдокод

rotateRight(x, n): // Вспомогательная функция для генерации перестановки, циклически сдвигает битовый вектор направо [math]n[/math] раз. Принимает и возвращает котреж (англ. tuple).
   return x[-n:] + x[:-n]
pi(n): // Рекурсивная генерация [math]n[/math]-ой перестановки. Возвращает перестановку в виде кортежа. Если n становится меньше [math]2[/math] дописывает в начало кортежа [math]0[/math] и возвращает его.
   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): // Рекурсивная генерация пути [math]P_{n, j}[/math]. Принимает [math]n, j[/math], а так же дополнительный параметр определяющий надо-ли переворачивать кортеж.
   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

Визуализация работы алгоритма

Для n = 5

Визуализация работы алгоритма для 5-ичного кода

Для n = 6

Визуализация работы алгоритма для 6-ичного кода

См. Также

Примечания

Источники информации