Московский государственный университет имени М.В.Ломоносова
Опубликован: 15.03.2007 | Доступ: свободный | Студентов: 616 / 27 | Оценка: 5.00 / 4.50 | Длительность: 19:30:00
Специальности: Программист
Дополнительный материал 1:

Решения задач

< Лекция 14 || Дополнительный материал 1: 12345678910
Аннотация: Приводятся решения задач или неформальные указания, пользуясь которыми заинтересованный читатель может восстановить строгое решение самостоятельно.
Ключевые слова: ПО, алфавит, множество состояний, управляющее устройство, функция переходов, пустой символ, завершение работы, четность, бит, метка, определение, сложение, доказательство, алгоритм, натуральное число, список, символ алфавита, цикла, длина, слово, место, окрестность, информация, машина Тьюринга, неравенство, очередь, копирование, вычитание, значение, указатель, переменные состояния, умножение, деление, целый, массив, базис, булева функция, базисные функции, дизъюнктивная нормальная форма, конъюнкция, дизъюнкция, произвольное, вершины графа, путь, путь в графе, глубина схемы, индукция, отрицание, вычисление, дерево, запись, матрица смежности, ребро, булева переменная, тождество, вершина, длина пути, объединение, двоичное представление, равенство, функция, основание, перестановка, граф, подформула, значение формулы, рекуррентного соотношения, polys, предикат, разрешимость, переменная, КНФ, корректность, эйлеровый путь, Связный граф, Замкнутый путь, связность, полином, правильный ответ, NP, инцидентность, Паросочетание, множество вершин, компонента связности, Ориентированный граф, Клик, дополнительным графом, множества, группа, Раскраска, restriction, прямоугольник, контур, число классов, первообразный корень, кратность, Произведение, класс, запрос, индекс, игра, операторы, подгруппа, композиция, матрица, единичный вектор, базисными векторами, вектор, собственное число, подмножество, прямой, рациональное число, коэффициенты, аппроксимация, транзитивность, множитель, иррациональное число, регистр, собственный вектор, вероятность, диффузия, представление, PPP, пункт, рекурсивные вычисления, точность, двоичное слово, выражение, эквивалентное свойство, квадрат нормы вектора, однородность, пространство, вес, расстояние, минимум

Из раздела 1

1.1 Неформально описать такую машину легко. Она переносит символы по одному слева направо и справа налево, пока не обнаруживает, что достигнута середина слова, после чего останавливается.

Дадим теперь формальное описание этой машины.

Внешний алфавит: \calA =\{0,\,1\}. Алфавит \calS =\{\emptycell, 0, 1, *, 0', 1'\}, помимо символов внешнего алфавита и пустого символа \emptycell, включает три вспомогательных метки, указывающих на положение символов, которые переносятся.

Множество состояний управляющего устройства

\calQ=\{q_0,q_f,r_0,r_1,l_0,l_1, l_{0'}, l_{1'}\}.
Буквы r и l указывают на направление переноса символа, индексы при этих буквах — на переносимый символ.

Теперь зададим функцию переходов. Для всех пар, на которых функция переходов не определена приводимыми ниже правилами, ее значения можно выбирать произвольно.

Начало работы:

\begin{align*} &(q_0,0)\mapsto(r_0,*,+1),&&(q_0,1)\mapsto(r_1,*,+1),\\ &(q_0,\emptycell)\mapsto(q_0,\emptycell,-1). \end{align*}
Первая строка означает, что машина поставила метку в первой позиции и понесла вправо символ, который в ней стоял. Вторая строка означает, что на пустом слове машина сразу останавливается.

Перенос вправо:

\begin{align*} &(r_0,0)\mapsto(r_0,0,+1),&&(r_1,0)\mapsto(r_1,0,+1),\\ &(r_0,1)\mapsto(r_0,1,+1),&&(r_1,1)\mapsto(r_1,1,+1). \end{align*}
Машина двигается вправо, пока не достигнет конца слова или метки.

Перемена направления движения справа налево состоит из двух действий: снять метку (если это не пустой символ)

(r_0,0')\mapsto(l_{0'},0,-1),&&(r_1,0')\mapsto(l_{1'},0,-1),\\ &(r_0,1')\mapsto(l_{0'},1,-1),&&(r_1,1')\mapsto(l_{1'},1,-1),\\ &(r_0,\emptycell)\mapsto(l_{0'},\emptycell,-1),&&(r_1,\emptycell)\mapsto(l_{1'},\emptycell,-1)

и поставить ее на левого соседа

(l_{0'},0)\mapsto(l_{0},0',-1),&&(l_{1'},0)\mapsto(l_{0},1',-1),\\ &(l_{0'},1)\mapsto(l_{1},0',-1),&&(l_{1'},1)\mapsto(l_{1},1',-1).

Перенос влево:

\begin{align*} &(l_{0},0)\mapsto(l_{0},0,-1),&&(l_{1},0)\mapsto(l_{0},0,-1),\\ &(l_{0},1)\mapsto(l_{1},1,-1),&&(l_{1},1)\mapsto(l_{1},1,-1). \end{align*}

Перемена движения слева направо:

\begin{align*} &(l_{0},*)\mapsto(q_{0},0,+1),&&(l_{1},*)\mapsto(q_{0},1,+1). \end{align*}

Завершение работы зависит от четности длины слова: при четной длине остановка происходит при начале движения вправо

(q_{0},0')\mapsto(q_{f},0,-1),&&(q_{0},1')\mapsto(q_{f},1,-1),

а при нечетной длине — при начале движения влево

&(l_{0'},*)\mapsto(q_{f},0,-1),&&(l_{1'},*)\mapsto(q_{f},1,-1),\\ &(q_f,0)\mapsto(q_f,0,-1),&& (q_f,1)\mapsto(q_f,1,-1).

1.2 Неформально делается следующее: ко второму слагаемому поочередно добавляются разряды первого, добавленный разряд стирается. Добавление одного разряда происходит за время, не превышающее удвоенной длины второго слагаемого, так что общее время работы машины квадратично зависит от длины входа.

Дадим теперь формальное описание такой машины.

Внешний алфавит: \calA =\{0,1,{+}\}. Алфавит \calS =\{\emptycell, 0, 1, {+}, 0', 1', {+}' \}, помимо символов внешнего алфавита и пустого символа \emptycell, включает три вспомогательных метки.

Множество состояний управляющего устройства

\calQ=\{q_0,q_f,q_p,r_0,r_1,l_0,l_1, d\}.
Буквы r и l указывают на направление переноса символа, индексы при этих буквах — на переносимый символ (влево машина носит бит переноса в следующий разряд, а вправо — добавляемый бит), в состоянии d машина осуществляет стирание обработанного разряда.

Теперь зададим функцию переходов. Как и в задаче 1.1, для не упомянутых ниже пар функция переходов определена произвольно.

Начало и конец работы:

\begin{align*} &(q_0,0)\mapsto(q_0,0',+1),&&(q_0,1)\mapsto(q_p,1',+1),&& (q_0,{+})\mapsto(d,0,-1),\\ &(q_p,0)\mapsto(q_p,0,+1),&&(q_p,1)\mapsto(q_p,1,+1),&& (q_p,{+})\mapsto(d,0,-1),\\ &(q_p,0')\mapsto(q_f,0,+1),&&(q_p,1')\mapsto(q_f,1,+1),&&\\ &(q_f,0)\mapsto(q_f,0,-1),&& (q_f,1)\mapsto(q_f,1,-1). && \end{align*}
Самый левый символ первого слагаемого помечается, чтобы не пропустить конец работы. Далее машина движется вправо в состоянии q_p. Если найден знак {+}, то происходит переход к началу добавления очередного слагаемого. Если найдена метка, то она стирается, а машина останавливается. При этом на ленте остается результат сложения (считаем, что сумма может начинаться нулями).

Определение очередного бита, который нужно добавлять ко второму слагаемому, перенос его вправо и переход в режим сложения:

\begin{align*} &(d,0)\mapsto(r_0,{+},+1),&&(d,1)\mapsto(r_1,{+},+1),\\ &(d,0')\mapsto(r_0,{+}',+1),&&(d,1')\mapsto(r_1,{+}',+1),\\ &(r_0,0)\mapsto(r_0,0,+1),&&(r_1,0)\mapsto(r_1,0,+1),\\ &(r_0,1)\mapsto(r_0,1,+1),&&(r_1,1)\mapsto(r_1,1,+1),\\ &(r_0,\emptycell)\mapsto(l_{0'},\emptycell,-1),&&(r_1,\emptycell)\mapsto(l_{1'},\emptycell,-1),\\ &(r_0,0')\mapsto(l_{0'},0,-1),&&(r_1,0')\mapsto(l_{1'},0,-1),\\ &(r_0,1')\mapsto(l_{0'},1,-1),&&(r_1,1')\mapsto(l_{1'},1,-1),\\ &(l_{0'},0)\mapsto(l_{0},0',-1),&&(l_{1'},0)\mapsto(l_{0},1',-1),\\ &(l_{0'},1)\mapsto(l_{0},1',-1),&&(l_{1'},1)\mapsto(l_{1},0',-1). \end{align*}

Сложение, пока не достигнут знак {+}

\begin{align*} &(l_0,0)\mapsto(l_{0},0,-1),&&(l_1,0)\mapsto(l_{0},1,-1),\\ &(l_0,1)\mapsto(l_{0},1,-1),&&(l_1,1)\mapsto(l_ {1},0,-1),\\ &(l_0,{+})\mapsto(d,0,-1),&&(l_1,{+})\mapsto(d,1,-1),\\ &(l_0,{+}')\mapsto(q_p,0,-1),&&(l_1,{+}')\mapsto(q_p,1,-1). \end{align*}
Последняя строчка применяется в конце, когда левее знака {+}' уже ничего нет. Поэтому машина начинает двигаться вправо, чтобы стереть оставшуюся метку.

1.3 Доказательство от противного. Предположим, что такой алгоритм есть, т.е. существует машина A, которая на входе ([М],x) дает ответ "да", если машина М останавливается на входе x, в противном случае дает ответ "нет" (через [М] обозначено описание машины М ). Тогда есть и такая машина A', которая на входе X моделирует работу A на входе (X,X). Затем, если ответ машины A — "да", то A' начинает двигать головку вправо и не останавливается, а если ответ A — "нет", то A' останавливается.

Остановится ли A' на входе [A']? Если остановится, то A дает ответ "да" на входе ([A'],[A']). Тогда, по определению машины A', на входе [A'] она не остановится. Итак, A' на входе [A'] не останавливается. Но тогда A дает ответ "нет" на входе ([A'],[A']). Но это означает, что A' на входе [A'] останавливается. Пришли к противоречию.

1.4 Во-первых, заметим, что есть алгоритм, который выписывает одну за другой те МТ, которые останавливаются, будучи запущенными на пустой ленте. Этот алгоритм перебирает все пары ([M],n) ( [M] — описание машины M, nнатуральное число) и для каждой пары моделирует работу M на пустом входе в течение n тактов. Если за это время происходит остановка, то M включается в список, если не была включена в него ранее.

Если бы существовал еще и такой алгоритм, который выписывает одну за другой машины, не останавливающиеся на пустом входе, то можно было бы построить и алгоритм, проверяющий, останавливается ли МТ A на пустом входе: запускаем оба алгоритма перечисления и ждем, когда описание A появится в одном или в другом списке.

Но тогда существовал бы и алгоритм, решающий проблему остановки: по машине M и входу x легко строится машина, которая сначала записывает x на ленту, а затем моделирует работу M. Так что из предыдущей задачи заключаем, что нет алгоритма, перечисляющего машины, не останавливающиеся на пустом слове.

1.5 Ограничимся указанием. Для любой вычислимой функции b(n) при достаточно больших n среди машин с n символами алфавита и n состояниями, останавливающихся на пустом входе, можно найти и такую, которая вычисляет nb(n), а затем вычитает из этого числа по единице, пока не дойдет до нуля.

1.6 Пусть имеется двухленточная МТ M_2, работающая за время T(n)\geq n на входах длины n. Опишем неформально машину M_1 с единственной лентой, моделирующую работу M_2. Алфавит этой машины достаточно велик, чтобы кодировать в одной ячейке содержимое ячеек с тем же номером на лентах M_2 и информацию о положении головок (на каких лентах головки находятся над ячейкой с тем же номером). Управляющее устройство M_1 позволяет запоминать содержимое ячеек, над которыми находятся головки M_2, и состояние управляющего устройства M_2.

Машина M_1 работает циклами, каждый из которых имитирует один такт работы M_2. В начале каждого цикла головка M_1 находится над самой левой ячейкой.

Цикл состоит из двух последовательных проходов по записанному слову. Вначале M_1 движется вправо и собирает информацию о состояниях в ячейках M_2, над которыми находятся головки. При обратном проходе справа налево M_1 выполняет действия, имитирующие такт работы M_2. На каждое такое действие требуется O(1) тактов.

Цикл выполняется за O(S) тактов работы M_1, где Sдлина используемой части ленты. Так как T(n)\geq n, то S\leq\max\{n,T(n)\}=T(n). Поэтому M_1 работает за время O(ST(n))\double=O(T^2(n)).

1.7 Приведем еще более неформальное, чем в предыдущей задаче, описание алгоритма. Алфавит моделирующей машины выберем достаточно большим, чтобы кодировать в одной ячейке содержимое ячеек на всех лентах, информацию о положении головок (на каких лентах головки находятся над данной ячейкой) и дополнительные метки, которые потребуются в процессе работы.

Опишем алгоритм A, который решает такую задачу: на одной из лент записано слово (t,w), на второй головка находится в конце используемой части ленты, нужно промоделировать работу трехленточной машины за период времени t (записанный двоичным словом), если вначале состояние лент определено словом w.

Запишем на свободное место на второй ленте число t/2, после чего скопируем туда же (t/2) -окрестности каждой из головок на всех трех лентах исходной машины и переместим головку в конец слова w (в конец используемой части первой ленты). К полученному на второй ленте слову применим рекурсивно алгоритм A, по завершении его работы скопируем на первую ленту результат моделирования, скопируем на вторую ленту (t/2) -окрестности головок во вновь полученном состоянии, отвечающем состоянию трехленточной машины после t/2 тактов работы, опять переместим головку в конец используемой части первой ленты. Еще раз рекурсивно применим A к слову на второй ленте, по завершении его работы скопируем результат моделирования на первую ленту.

Для корректного описания алгоритма нужно еще задать его работу на слове (1,w). В этом случае просто применяем алгоритм, аналогичный описанному в предыдущей задаче.

Операцию копирования с ленты на ленту можно осуществить за линейное от длины копируемого слова время. Поэтому для времени \widetilde T(t,s) работы в наихудшем случае алгоритма A, моделирующего работу трехленточной машины за время t на словах длины s, получаем оценку:

\widetilde T(t,s)\leq 2\widetilde  T(\frac{t}{2}, t)+O(t)+O(s). ( *)
Из (*) сразу следует, что при некоторой константе C_1 и t>1
\widetilde T(t,2t)\leq C_1t(\log t+1).
Поэтому
\widetilde T(t,s)=O(t\log t)+O(t)+O(s).

Заметим, что получить слово (t,w) из слова w можно за время |w|\log t, если t известно.

Алгоритм моделирования трехленточной машины на двухленточной использует алгоритм A следующим образом. Промоделируем работу машины из начального состояния за 1 такт, затем работу за 2 такта из достигнутого состояния и т.д. Оценим время работы этого алгоритма. Пусть исходная трехленточная машина работает на словах длины n за время T(n)\geq n. Тогда время T'(n) работы моделирующей машины будет оцениваться как

\begin{align*} T'(n)\leq\sum_{k=0}^{\lceil\log T(n)\rceil}\widetilde T(2^k,n+2^k)\leq \sum_{k=0}^{\lceil\log T(n)\rceil}O(n+2^k)+O(k2^k)+O(2^k)\leq\\ \leq \sum_{k=0}^{\lceil\log T(n)\rceil}O(T(n)) =O(T(n)\log T(n)). \end{align*}

1.8 Информация в машине Тьюринга переносится головкой управляющего устройства. Более точно эта мысль формулируется так. Рассмотрим последовательность \{Q_j(x,k)\} состояний управляющего устройства МТ в моменты переходов головки между k -й и (k+1) -й ячейками при работе МТ на входе x (рассматриваем переходы в обе стороны). Работа машины Тьюринга справа от k -й ячейки полностью определяется последовательностью \{Q_j(x,k)\}.

Теперь запишем нижнюю оценку на время работы МТ, копирующей входное слово. Она основана на том, что каждый переход головки требует отдельного такта работы МТ. Введем параметры \eps и \tau_k, значения которых определим позже. Для слова w через \tau_k(w) обозначим число переходов головки между k -й и (k+1) -й ячейками при работе МТ на входе w. Будем искать такое слово w, что \tau_k(w)>\tau_k при k\geq n/2.

Поскольку МТ копирует начальный кусок длины k справа от k -й ячейки, последовательности \{Q_j(vu,k)\} при фиксированном u должны быть различны для различных k -буквенных слов v. Коротких (длины не больше \tau ) последовательностей состояний управляющего устройства не больше, чем \slashfrac{|\calQ|^{\tau+1}}{(|\calQ|-1)}, где \calQмножество состояний управляющего устройства. Для любого (n-k) -буквенного слова u при

\frac{|\calQ|^{\tau+1}}{|\calQ|-1}\leq 2|\calQ|^\tau\leq\eps|\calA|^k, ( *)
где \calA — внешний алфавит, неравенство \tau_k(vu)>\tau выполнено по крайней мере для доли 1-\eps от всех k -буквенных слов v. Это означает, что для доли 1-|\calA|^{n-k}\eps от всех k -буквенных слов v неравенство \tau_k(vu)>\tau выполняется для всех u. Поэтому при
|\calA|^{n-k}\eps<\frac{1}{n} ( **)
найдется слово w такое, что \tau_k(w)>\tau_k при k\geq n/2.

Если \eps=(n|\calA|^{n/2})^{-1}, то (**) выполняется при k\geq n/2. Если при этом еще и \tau_k=\lfloor \slashfrac{(\log(\eps/2)+\frac{2}{3}n\log|\calA|)}{\log|\calQ|} \rfloor, то (*) выполняется при k\geq 2n/3. При таком выборе параметров \tau_k=\Omega(n) при k\geq 2n/3. Оценим время работы МТ на слове w таком, что \tau_k(w)>\tau_k при k\double\geq 2n/3 (мы уже доказали, что такое слово есть)

T(n)\geq\sum_{k=\lceil 2n/3\rceil}^{n} \tau_k=\frac{n}{3}\cdot\Omega(n)= \Omega(n^2).

Для оценки минимального времени работы T'(n) можно считать, что МТ вначале дописывает за T_1(n) тактов последовательность из одних 0 длины n, затем за O(n) шагов проверяет, состоит ли исходное слово из одних 0, после чего прекращает работу, если это так, а в противном случае работает любым правильным способом. Ясно, что T'(n)=T_1(n)+O(n). В свою очередь, T_1(n)=O(n\log n). Действительно, если бы машина во внутренней памяти могла хранить числа, то копирование слова из нулей не создало бы проблемы (надо было бы подсчитать длину слова и потом написать столько же нулей). Но этого сделать нельзя. Зато машина Тьюринга может хранить число в двоичной записи в окрестности своей головки (мы можем расширить алфавит и считать, что на ленте есть место для дополнительных пометок рядом с буквами слова из нулей и единиц). При этом прибавление единицы к такому счетчику, вычитание единицы и сдвиг счетчика по ленте (его ведь надо возить с собой) требуют времени порядка длины счетчика, т.е. O(\log n), так что всего мы укладываемся в O(n\log n) тактов.

Замечание. Можно показать, что T'(n)=\Omega(n\log n). Читателю предлагается самостоятельно понять, как нужно модифицировать изложенную выше нижнюю оценку времени работы в худшем случае.

< Лекция 14 || Дополнительный материал 1: 12345678910