Редактирование: Монотонный код Грея

Перейти к: навигация, поиск

Внимание! Вы не авторизовались на сайте. Ваш IP-адрес будет публично видимым, если вы будете вносить любые правки. Если вы войдёте или создадите учётную запись, правки вместо этого будут связаны с вашим именем пользователя, а также у вас появятся другие преимущества.

Правка может быть отменена. Пожалуйста, просмотрите сравнение версий, чтобы убедиться, что это именно те изменения, которые вас интересуют, и нажмите «Записать страницу», чтобы изменения вступили в силу.
Текущая версия Ваш текст
Строка 1: Строка 1:
 
{{Определение
 
{{Определение
 
|definition =
 
|definition =
'''Монотонный код Грея''' (англ. ''Monotonic Gray Code'') {{---}} способ построения кода Грея, при котором <tex>\forall i < j</tex> <tex>\nexists 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> содержит на 2 или больше единиц, чем <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 \mid v \text{ has weight } i \}
+
V_n(i) = \{ v \in V_n : v \text{ has weight } i \}
 
</tex>
 
</tex>
  
для <tex>0 \leqslant i \leqslant n</tex>. Для всех уровней выполняется соотношение <tex>|V_n(i)| = C_n^i</tex>.
+
для <tex>0 \leq i \leq n</tex>. Для всех уровней выполняется соотношение <tex>|V_n(i)| = \binom{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>.
Тогда монотонным кодом Грея будет являтся [[:Гамильтоновы_графы#.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_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_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'').
  
[[Файл:Monotonic_Gray_Code_Graph.png|center|4-ичный монотонный код Грея]]
+
[[Файл:Monotonic_Gray_Code_Graph.png|center|4-ичный монотооный код Грея]]
  
Элегантная идея построения <tex>n</tex>-ичного монотонного кода Грея состоит в том, чтобы рекурсивно строить подпути <tex>P_{n,j}</tex> длинны <tex>2C_n^j</tex> включающих вершины <tex>E_n(j)</tex>.
+
Элегантная идея построения <tex>n</tex>-ичного монотонного кода Грея состоит в том, чтобы рекурсивно строить подпути <tex>P_{n,j}</tex> длинны <tex>2 \binom{n}{j}</tex> включающих вершины <tex>E_n(j)</tex>.
  
Определим <tex>P_{1,0} = (0, 1)</tex> и <tex>P_{n,j} = \emptyset</tex>, когда <tex>j < 0</tex> или <tex>j \geqslant n</tex> и  
+
Определим <tex>P_{1,0} = (0, 1)</tex> и <tex>P_{n,j} = \emptyset</tex>, когда <tex>j < 0</tex> или <tex>j \geq n</tex> и  
 
<tex>
 
<tex>
 
P_{n+1,j} = 1P^{\pi_n}_{n,j-1}, 0P_{n,j}
 
P_{n+1,j} = 1P^{\pi_n}_{n,j-1}, 0P_{n,j}
</tex>. То есть <tex>P_{n+1, j}</tex> это объединение множеств <tex>P^{\pi_n}_{n,j-1}</tex> с приписанной в начале <tex>1</tex> и <tex>P_{n,j}</tex> с приписанным в начале <tex>0</tex>.
+
</tex>.
  
 
Здесь <tex>\pi_n</tex> это определенная перестановка элементов множества к которому она применена, а <tex>P^{\pi}</tex> это путь <tex>P</tex> к котрому была применена пересатновка  <tex>\pi</tex>.
 
Здесь <tex>\pi_n</tex> это определенная перестановка элементов множества к которому она применена, а <tex>P^{\pi}</tex> это путь <tex>P</tex> к котрому была применена пересатновка  <tex>\pi</tex>.
Существует два варианта построить монотонный код грея по путям <tex>P_{n, j}</tex>.  
+
Существует два варианта построить моготонный код грея по путям <tex>P_{n, j}</tex>.  
  
 
Назовем их <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 \ldots \text{, } G_n^{(2)} = P_{n,0}^R P_{n,1} P_{n,2}^R P_{n,3} \ldots
+
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
 
</tex>
 
</tex>
  
Строка 70: Строка 70:
 
</center>
 
</center>
  
Монотонный код Грея может быть эффективно сгенерирован по этому алгоритму за время <tex>O(n)</tex>. Легче всего написать этот алгоритм используя генератор.
+
Монотонный код Грея может быть эффективно сгенерирован по этому алгоритму за время <tex>O(n)</tex>. Легче всего написать этот алгоритм используя сопрограмму.
  
 
=== Псевдокод ===
 
=== Псевдокод ===
Перед тем как писать псевдокод необходимо объяснить что такое <code>'''yield'''</code> и что понимать под выражениями типа <code>(0,)</code> или <code>(1,)</code>.
 
 
<code>'''yield'''</code> {{---}} аналог <code>'''return'''</code> только для функций-генераторов. То есть генераторы это тоже итерируемые объекты, но прочитать их можно лишь один раз. Это связано с тем, что они не хранят значения в памяти, а генерируют их на лету.
 
 
С конструкциями типа <code>(0,)</code> или <code>(1,)</code> все проще. Используя ее совместно с <code>'''yield'''</code> мы можем изменять наш генерируемый объект. Например, <code>'''yield''' (0,)</code> допишет к генерируемому объекту (в нашем случае кортежу (англ. ''tuple'')) <tex>0</tex> в начало.
 
 
{| border="0"  
 
{| border="0"  
 
|align="left" colspan="4"|
 
|align="left" colspan="4"|
Вспомогательная функция для генерации перестановки, циклически сдвигает битовый вектор направо <tex>n</tex> раз.
 
Принимает и возвращает кортеж. Кортеж аналог списка, но в кортеже нельзя менять элементы, можно только добавлять.
 
<code>[i:]</code> {{---}} возвращает подсписок, начиная с индекса <tex>i</tex> (аналогично <code>[:i]</code>), а отрицательный знак позволяет индексироваться с конца (полагая, что -1 — последний элемент списка).
 
 
<code>
 
<code>
'''function''' rotateRight(x: '''int[n]'''): '''int[n]'''
+
<font color = brown>rotate_right</font>(x, n):
 
     '''return''' x[-n:] + x[:-n]
 
     '''return''' x[-n:] + x[:-n]
</code>
+
<font color = brown>pi</font>(n):
Рекурсивная генерация <tex>n</tex>-ой перестановки.
+
     '''if''' n <= 1:
Возвращает перестановку в виде кортежа.
 
Если <tex>n</tex> становится меньше <tex>2</tex> дописывает в начало кортежа <tex>0</tex> и возвращает его.
 
<code>
 
'''function''' pi('''int''' n): '''int[n]'''
 
     '''if''' n <= 1
 
 
         '''return''' (0,)
 
         '''return''' (0,)
 
     x = pi(n - 1) + (n - 1,)
 
     x = pi(n - 1) + (n - 1,)
     '''return''' rotateRight('''tuple'''(x[k] '''for''' k '''in''' x), 1)
+
     '''return''' rotate_right('''tuple'''(x[k] '''for''' k '''in''' x), 1)
</code>
+
<font color = brown>p</font>(n, j, reverse=False):
Рекурсивная генерация пути <tex>P_{n, j}</tex>.
+
     if n == 1 and j == 0:
Принимает <tex>n, j</tex>, а так же дополнительный параметр определяющий надо-ли переворачивать кортеж.
+
         '''if''' '''not''' reverse:
<code>
 
'''function''' p('''int''' n, '''int''' j, '''bool''' reverse = ''false''): '''list<int[n]>'''
 
     '''if''' n == 1 and j == 0
 
         '''if''' '''not''' reverse
 
 
             '''yield''' (0,)
 
             '''yield''' (0,)
 
             '''yield''' (1,)
 
             '''yield''' (1,)
         '''else'''
+
         '''else''':
 
             '''yield''' (1,)
 
             '''yield''' (1,)
 
             '''yield''' (0,)
 
             '''yield''' (0,)
     '''else if''' j >= 0 '''and''' j < n
+
     '''elif''' j >= 0 '''and''' j < n:
 
         perm = pi(n - 1)
 
         perm = pi(n - 1)
         '''if''' '''not''' reverse
+
         '''if''' '''not''' reverse:
             '''for''' x '''in''' p(n - 1, j - 1)
+
             '''for''' x '''in''' p(n - 1, j - 1):
 
                 '''yield''' (1,) + '''tuple'''(x[k] '''for''' k '''in''' perm)
 
                 '''yield''' (1,) + '''tuple'''(x[k] '''for''' k '''in''' perm)
             '''for''' x '''in''' p(n - 1, j)
+
             '''for''' x '''in''' p(n - 1, j):
 
                 '''yield''' (0,) + x
 
                 '''yield''' (0,) + x
         '''else'''
+
         '''else''':
             '''for''' x '''in''' p(n - 1, j, reverse=''true'')
+
             '''for''' x '''in''' p(n - 1, j, reverse=True):
 
                 '''yield''' (0,) + x
 
                 '''yield''' (0,) + x
             '''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)  
</code>
+
<font color = brown>monotonic</font>(n):
Генерация монотонного кода Грея при помощи уже написанного генератора <tex>p</tex>.
+
     '''for''' i '''in''' range(n):
<code>
+
         '''for''' x '''in''' (p(n, i) '''if''' i % 2 == 0 '''else''' p(n, i, reverse=True)):
'''function''' monotonic('''int''' n): '''list<int[n]>'''
 
     '''for''' i '''in''' range(n)
 
         '''for''' x '''in''' (p(n, i) '''if''' i % 2 == 0 '''else''' p(n, i, reverse=''true''))
 
 
             '''yield''' x
 
             '''yield''' x
 
</code>
 
</code>
Строка 161: Строка 141:
 
[[Категория: Дискретная математика и алгоритмы]]
 
[[Категория: Дискретная математика и алгоритмы]]
 
[[Категория: Комбинаторика]]
 
[[Категория: Комбинаторика]]
[[Категория: Комбинаторные объекты ]]
+
[[Категория: Коды Грея]]
 +
[[Категория: Комбинаторные объекты]]

Пожалуйста, учтите, что любой ваш вклад в проект «Викиконспекты» может быть отредактирован или удалён другими участниками. Если вы не хотите, чтобы кто-либо изменял ваши тексты, не помещайте их сюда.
Вы также подтверждаете, что являетесь автором вносимых дополнений, или скопировали их из источника, допускающего свободное распространение и изменение своего содержимого (см. Викиконспекты:Авторские права). НЕ РАЗМЕЩАЙТЕ БЕЗ РАЗРЕШЕНИЯ ОХРАНЯЕМЫЕ АВТОРСКИМ ПРАВОМ МАТЕРИАЛЫ!

Чтобы изменить эту страницу, пожалуйста, ответьте на приведённый ниже вопрос (подробнее):

Отменить | Справка по редактированию (в новом окне)

Шаблоны, используемые на этой странице: