<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=217.66.157.35&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=217.66.157.35&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/217.66.157.35"/>
		<updated>2026-05-12T15:27:00Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%BE%D0%BD%D0%BE%D1%82%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BE%D0%B4_%D0%93%D1%80%D0%B5%D1%8F&amp;diff=58038</id>
		<title>Монотонный код Грея</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%BE%D0%BD%D0%BE%D1%82%D0%BE%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BA%D0%BE%D0%B4_%D0%93%D1%80%D0%B5%D1%8F&amp;diff=58038"/>
				<updated>2016-12-19T18:39:49Z</updated>
		
		<summary type="html">&lt;p&gt;217.66.157.35: /* Псевдокод */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Монотонный код Грея''' (англ. ''Monotonic Gray Code'') {{---}} способ построения кода Грея, при котором &amp;lt;tex&amp;gt;\forall i &amp;lt; j&amp;lt;/tex&amp;gt; &amp;lt;tex&amp;gt;\nexists g_i, g_j&amp;lt;/tex&amp;gt;, что &amp;lt;tex&amp;gt;g_i&amp;lt;/tex&amp;gt; содержит на &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; или больше единиц, чем &amp;lt;tex&amp;gt;g_j&amp;lt;/tex&amp;gt;.&lt;br /&gt;
}}&lt;br /&gt;
Монотонный код Грея преимущественно используется в теории связанных сетей, например для минимизации ожидания линейным массивом процессоров.&amp;lt;ref&amp;gt;[http://www.sciencedirect.com/science/article/pii/0097316595900918 C. D Savage and P. Winkler (1995). &amp;quot;Monotone Gray codes and the middle levels problem&amp;quot;page 7]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Алгоритм построения == &lt;br /&gt;
&lt;br /&gt;
Для начала определим такое понятие, как ''вес'' двоичного кода, им будет являтся количество &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; в данном двоичном коде. Очевидно, что нельзя построить [[:Коды_Грея|код Грея]] в котором бы вес всегда возрастал.&lt;br /&gt;
Неплохим решением этой проблемы будет обход всех кодов со смежными с данным весами.&lt;br /&gt;
&lt;br /&gt;
Мы можем формализовать модель монотонных кодов Грея рассматривая разбиение гиперкуба &amp;lt;tex&amp;gt;Q_n = (V_n, E_n)&amp;lt;/tex&amp;gt;, вершины в котором являются двоичными кодами, на уровни с одинаковым весом вершин.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
V_n(i) = \{ v \mid v \text{ has weight } i \}&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
для &amp;lt;tex&amp;gt;0 \leqslant i \leqslant n&amp;lt;/tex&amp;gt;. Для всех уровней выполняется соотношение &amp;lt;tex&amp;gt;|V_n(i)| = C_n^i&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;tex&amp;gt;Q_n(i)&amp;lt;/tex&amp;gt; подграф &amp;lt;tex&amp;gt;Q_n&amp;lt;/tex&amp;gt;, который является объединением двух смежных уровней, т. е. &amp;lt;tex&amp;gt;V_n(i) \cup V_n(i+1)&amp;lt;/tex&amp;gt;, и пусть &amp;lt;tex&amp;gt;E_n(i)&amp;lt;/tex&amp;gt; множество граней &amp;lt;tex&amp;gt;Q_n(i)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Тогда монотонным кодом Грея будет являтся [[:Гамильтоновы_графы#.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|Гамильтонов путь]] в &amp;lt;tex&amp;gt;Q_n&amp;lt;/tex&amp;gt;, при котором любое множество вершин &amp;lt;tex&amp;gt;\delta_1 , \delta_2&amp;lt;/tex&amp;gt; такие, что &amp;lt;tex&amp;gt;\forall i, j : i \leqslant j&amp;lt;/tex&amp;gt;, то &amp;lt;tex&amp;gt;\delta_1 \in E_n(i)&amp;lt;/tex&amp;gt; идет перед &amp;lt;tex&amp;gt;\delta_2 \in E_n(j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ниже на катринке Гамильтонов путь в гиперкубе &amp;lt;tex&amp;gt;Q_4&amp;lt;/tex&amp;gt; для &amp;lt;tex&amp;gt;n = 4&amp;lt;/tex&amp;gt;, построенный по алгоритму Саважа-Винклера (англ. ''Savage-Winkler'').&amp;lt;ref&amp;gt;[http://www.sciencedirect.com/science/article/pii/0097316595900918 C. D Savage and P. Winkler (1995). &amp;quot;Monotone Gray codes and the middle levels problem&amp;quot;page 14]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Monotonic_Gray_Code_Graph.png|center|4-ичный монотонный код Грея]]&lt;br /&gt;
&lt;br /&gt;
Элегантная идея построения &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ичного монотонного кода Грея состоит в том, чтобы рекурсивно строить подпути &amp;lt;tex&amp;gt;P_{n,j}&amp;lt;/tex&amp;gt; длинны &amp;lt;tex&amp;gt;2C_n^j&amp;lt;/tex&amp;gt; включающих вершины &amp;lt;tex&amp;gt;E_n(j)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Определим &amp;lt;tex&amp;gt;P_{1,0} = (0, 1)&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;P_{n,j} = \emptyset&amp;lt;/tex&amp;gt;, когда &amp;lt;tex&amp;gt;j &amp;lt; 0&amp;lt;/tex&amp;gt; или &amp;lt;tex&amp;gt;j \geqslant n&amp;lt;/tex&amp;gt; и &lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
P_{n+1,j} = 1P^{\pi_n}_{n,j-1}, 0P_{n,j}&lt;br /&gt;
&amp;lt;/tex&amp;gt;. То есть &amp;lt;tex&amp;gt;P_{n+1, j}&amp;lt;/tex&amp;gt; это объединение множеств &amp;lt;tex&amp;gt;P^{\pi_n}_{n,j-1}&amp;lt;/tex&amp;gt; с приписанной в начале &amp;lt;tex&amp;gt;1&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;P_{n,j}&amp;lt;/tex&amp;gt; с приписанным в начале &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;tex&amp;gt;\pi_n&amp;lt;/tex&amp;gt; это определенная перестановка элементов множества к которому она применена, а &amp;lt;tex&amp;gt;P^{\pi}&amp;lt;/tex&amp;gt; это путь &amp;lt;tex&amp;gt;P&amp;lt;/tex&amp;gt; к котрому была применена пересатновка  &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt;.&lt;br /&gt;
Существует два варианта построить монотонный код грея по путям &amp;lt;tex&amp;gt;P_{n, j}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Назовем их &amp;lt;tex&amp;gt;G_n^{(1)}&amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt;G_n^{(2)}&amp;lt;/tex&amp;gt;. Будем строить их таким образом: &lt;br /&gt;
&amp;lt;tex&amp;gt;&lt;br /&gt;
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&lt;br /&gt;
&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Выбор перестановки &amp;lt;tex&amp;gt;\pi_n&amp;lt;/tex&amp;gt; обусловлен тем, чтобы получившиеся коды соответсвовали требованиям кода Грея и поэтому эта перестановка равна &amp;lt;tex&amp;gt;\pi_n = E^{-1}(\pi_{n-1}^2)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Чтобы лучше разобратся в том, как сторится этот код и работает перестановка &amp;lt;tex&amp;gt;\pi&amp;lt;/tex&amp;gt; следует рассмотреть таблицу ниже.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|class=&amp;quot;wikitable&amp;quot; align=&amp;quot;center&amp;quot; style=&amp;quot;color: blue; background-color:#ffffcc;&amp;quot; cellpadding=&amp;quot;10&amp;quot;&lt;br /&gt;
|+ Подпути алгоритма Саважа-Винклера&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; style=&amp;quot;width:3em;&amp;quot;| &amp;lt;math&amp;gt;P_{n,j}&amp;lt;/math&amp;gt; &lt;br /&gt;
! scope=&amp;quot;col&amp;quot; | &amp;lt;tex&amp;gt;j = 0&amp;lt;/tex&amp;gt;&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; | &amp;lt;tex&amp;gt;j = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; | &amp;lt;tex&amp;gt;j = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; | &amp;lt;tex&amp;gt;j = 3&amp;lt;/tex&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | &amp;lt;tex&amp;gt;n = 1&amp;lt;/tex&amp;gt;&lt;br /&gt;
| &amp;lt;tex&amp;gt;0, 1&amp;lt;/tex&amp;gt; || || ||&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | &amp;lt;tex&amp;gt;n = 2&amp;lt;/tex&amp;gt;&lt;br /&gt;
| &amp;lt;tex&amp;gt;00, 01&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;10, 11&amp;lt;/tex&amp;gt; || ||&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | &amp;lt;tex&amp;gt;n = 3&amp;lt;/tex&amp;gt;&lt;br /&gt;
| &amp;lt;tex&amp;gt;000, 001&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;100, 110, 010, 011&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;101, 111&amp;lt;/tex&amp;gt; ||&lt;br /&gt;
|-&lt;br /&gt;
! scope=&amp;quot;row&amp;quot; | &amp;lt;tex&amp;gt;n = 4&amp;lt;/tex&amp;gt;&lt;br /&gt;
| &amp;lt;tex&amp;gt;0000, 0001&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;1000, 1100, 0100, 0110, 0010, 0011&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;1010, 1011, 1001, 1101, 0101, 0111&amp;lt;/tex&amp;gt; || &amp;lt;tex&amp;gt;1110, 1111&amp;lt;/tex&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Монотонный код Грея может быть эффективно сгенерирован по этому алгоритму за время &amp;lt;tex&amp;gt;O(n)&amp;lt;/tex&amp;gt;. Легче всего написать этот алгоритм используя генератор.&lt;br /&gt;
&lt;br /&gt;
=== Псевдокод ===&lt;br /&gt;
Перед тем как писать псевдокод необходимо объяснить что такое &amp;lt;code&amp;gt;'''yield'''&amp;lt;/code&amp;gt; и что понимать под выражениями типа &amp;lt;code&amp;gt;(0,)&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;(1,)&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;'''yield'''&amp;lt;/code&amp;gt; {{---}} аналог &amp;lt;code&amp;gt;'''return'''&amp;lt;/code&amp;gt; только для функций-генераторов. То есть генераторы это тоже итерируемые объекты, но прочитать их можно лишь один раз. Это связано с тем, что они не хранят значения в памяти, а генерируют их на лету. &lt;br /&gt;
&lt;br /&gt;
С конструкциями типа &amp;lt;code&amp;gt;(0,)&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;(1,)&amp;lt;/code&amp;gt; все проще. Используя ее совместно с &amp;lt;code&amp;gt;'''yield'''&amp;lt;/code&amp;gt; мы можем в изменять наш генерируемый объект. Например, &amp;lt;code&amp;gt;'''yield''' (0,)&amp;lt;/code&amp;gt; допишет к генерируемому объекту (в нашем случае кортежу (англ. ''tuple'')) &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; в начало. &lt;br /&gt;
{| border=&amp;quot;0&amp;quot; &lt;br /&gt;
|align=&amp;quot;left&amp;quot; colspan=&amp;quot;4&amp;quot;|&lt;br /&gt;
Вспомогательная функция для генерации перестановки, циклически сдвигает битовый вектор направо &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; раз. &lt;br /&gt;
Принимает и возвращает кортеж. Кортеж аналог списка, но в кортеже нельзя менять элементы, можно только добавлять.&lt;br /&gt;
&amp;lt;code&amp;gt;[i:]&amp;lt;/code&amp;gt; {{---}} возвращает подсписок, начиная с индекса &amp;lt;tex&amp;gt;i&amp;lt;/tex&amp;gt; (аналогично &amp;lt;code&amp;gt;[:i]&amp;lt;/code&amp;gt;), а отрицательный знак позволяет индексироваться с конца (полагая, что -1 — последний элемент списка).&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''function''' rotateRight(x: '''int[n]'''): '''int[n]'''&lt;br /&gt;
    '''return''' x[-n:] + x[:-n]&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Рекурсивная генерация &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt;-ой перестановки. &lt;br /&gt;
Возвращает перестановку в виде кортежа. &lt;br /&gt;
Если &amp;lt;tex&amp;gt;n&amp;lt;/tex&amp;gt; становится меньше &amp;lt;tex&amp;gt;2&amp;lt;/tex&amp;gt; дописывает в начало кортежа &amp;lt;tex&amp;gt;0&amp;lt;/tex&amp;gt; и возвращает его.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''function''' pi('''int''' n): '''int[n]'''&lt;br /&gt;
    '''if''' n &amp;lt;= 1&lt;br /&gt;
        '''return''' (0,)&lt;br /&gt;
    x = pi(n - 1) + (n - 1,)&lt;br /&gt;
    '''return''' rotateRight('''tuple'''(x[k] '''for''' k '''in''' x), 1)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Рекурсивная генерация пути &amp;lt;tex&amp;gt;P_{n, j}&amp;lt;/tex&amp;gt;. &lt;br /&gt;
Принимает &amp;lt;tex&amp;gt;n, j&amp;lt;/tex&amp;gt;, а так же дополнительный параметр определяющий надо-ли переворачивать кортеж.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
 '''function''' p('''int''' n, '''int''' j, '''bool''' reverse = ''false''): '''list&amp;lt;int[n]&amp;gt;'''&lt;br /&gt;
    '''if''' n == 1 and j == 0&lt;br /&gt;
        '''if''' '''not''' reverse&lt;br /&gt;
            '''yield''' (0,)&lt;br /&gt;
            '''yield''' (1,)&lt;br /&gt;
        '''else'''&lt;br /&gt;
            '''yield''' (1,)&lt;br /&gt;
            '''yield''' (0,)&lt;br /&gt;
    '''else if''' j &amp;gt;= 0 '''and''' j &amp;lt; n&lt;br /&gt;
        perm = pi(n - 1)&lt;br /&gt;
        '''if''' '''not''' reverse&lt;br /&gt;
            '''for''' x '''in''' p(n - 1, j - 1)&lt;br /&gt;
                '''yield''' (1,) + '''tuple'''(x[k] '''for''' k '''in''' perm)&lt;br /&gt;
            '''for''' x '''in''' p(n - 1, j)&lt;br /&gt;
                '''yield''' (0,) + x&lt;br /&gt;
        '''else'''&lt;br /&gt;
            '''for''' x '''in''' p(n - 1, j, reverse=''true'')&lt;br /&gt;
                '''yield''' (0,) + x&lt;br /&gt;
            '''for''' x '''in''' p(n - 1, j - 1, reverse=''true'')&lt;br /&gt;
                '''yield''' (1,) + '''tuple'''(x[k] '''for''' k '''in''' perm)&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
Генерация монотонного кода Грея при помощи уже написанного генератора &amp;lt;tex&amp;gt;p&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&amp;lt;code&amp;gt; &lt;br /&gt;
 '''function''' monotonic('''int''' n): '''list&amp;lt;int[n]&amp;gt;'''&lt;br /&gt;
    '''for''' i '''in''' range(n)&lt;br /&gt;
        '''for''' x '''in''' (p(n, i) '''if''' i % 2 == 0 '''else''' p(n, i, reverse=True))&lt;br /&gt;
            '''yield''' x&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Визуализация работы алгоритма===&lt;br /&gt;
Для &amp;lt;tex&amp;gt;n = 5&amp;lt;/tex&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
[[Файл:Monotonic_Gray_Code_Ex1.png|center|Визуализация работы алгоритма для 5-ичного кода]]&lt;br /&gt;
&lt;br /&gt;
Для &amp;lt;tex&amp;gt;n = 6&amp;lt;/tex&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Файл:Monotonic_Gray_Code_Ex2.png|center|Визуализация работы алгоритма для 6-ичного кода]]&lt;br /&gt;
&lt;br /&gt;
==См. Также==&lt;br /&gt;
&lt;br /&gt;
*[[:Коды_Грея|Коды Грея]]&lt;br /&gt;
&lt;br /&gt;
*[[:Коды_антигрея|Коды антигрея]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Gray_code Wikipedia {{---}} Gray code]&lt;br /&gt;
&lt;br /&gt;
* [http://ru.wikipedia.org/wiki/код_Грея Википедия {{---}} Код Грея]&lt;br /&gt;
&lt;br /&gt;
* [http://www.jucs.org/jucs_13_11/the_gray_code/jucs_13_11_1573_1597_doran.pdf Robert W. Doran The Gray Code, Journal of Universal Computer Science, vol. 13, no. 11 (2007).]&lt;br /&gt;
&lt;br /&gt;
*[http://sciyoshi.com/2010/12/gray-codes Alternative Combinatorial Gray Codes]&lt;br /&gt;
&lt;br /&gt;
[[Категория: Дискретная математика и алгоритмы]]&lt;br /&gt;
[[Категория: Комбинаторика]]&lt;/div&gt;</summary>
		<author><name>217.66.157.35</name></author>	</entry>

	</feed>