\documentclass[12pt,fleqn,a4paper]{book}
% 
% Packages used:
%
\usepackage[koi8-r]{inputenc}
\usepackage[russian,english]{babel}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsfonts}
\usepackage{amsthm}
%
% Common customization:
%
\input defs
%
% The document
%
\begin{document}
\selectlanguage{russian}
%
% Lecture title
%
\lecture{3}{Иерархия по памяти}{М.  Плискин}
%
% The lecture
%
\begin{definition}
Для данной функции $f$,
$\DTIME(f(n))$ обозначает класс языков, принимаемых детерминированными
машинами Тьюринга, заканчивающими свою работу за время, 
не превосходящее $f(n)$, где $n$ --- длина входа\footnote{Вообще,
если не сказано иного, $n$ везде обозначает именно длину входа.}.
$\DSPACE(f(n))$ обозначает класс языков, принимаемых детерминированными
машинами Тьюринга, использующие не более $f(n)$ ячеек памяти
на рабочих лентах (входная \emph{readonly} лента --- не в счет).
Аналогично определяются и другие подобные этим классы, только буква $\mathbf{D}$
заменяется на другие\footnote{Неполный список сокращений:
$\mathbf{N}$ --- недетерминированный, $\mathbf{R}$ --- вероятностный
с ограниченной односторонней ошибкой, $\mathbf{B}$ --- вероятностный
с ограниченной двусторонней ошибкой, $\mathbf{BQ}$ --- квантовый с
ограниченной двусторонней ошибкой. Значение этих слов будет пояснено
позже.}. Если вместо функции $f$ указан класс функций (например, $O(n)$),
подразумевается объединение соответствующих классов:
$\DTIME(\mathcal{F})=\bigcup\limits_{f\in \mathcal{F}} \DTIME(f)$.
\end{definition}

\begin{definition}
Для любого вычислительного устройства $M$
обозначим $L(M)$ принимаемый им язык
(понятие \emph{принятия} строки
различно для разных типов вычислительных устройств).
\end{definition}

\section{Небольшое количество памяти, помогающее в вычислениях}
\begin{remark}
Отметим, что машина Тьюринга с лентой длины $O(1)$
есть конечный автомат.
%$\DSPACE(O(1))$ 
\end{remark}

\begin{theorem}
Покажем, что $\DSPACE(O(\log\log n))\neq\DSPACE(O(1)).$
\end{theorem}
\begin{proof}
Опишем язык $D$:
$$
D=\left\{\left.\overbrace{\underbrace{0\ldots00}_k}^{=0}\$
\overbrace{\underbrace{0\ldots01}_k}^{=1}\$\ldots\$
\overbrace{\underbrace{1\ldots11}_k}^{=2^k-1}\$\,\right|\,
k\in\mathbb{N}\right\}.
$$
Покажем, что данный язык не принадлежит классу $\DSPACE(O(1)).$
Для этого воспользуемся так называемой леммой о разрастании (pumping lemma),
доказательство которой можно найти в любой книге по теории формальных языков.

{
\small
\begin{lemma}
\leftskip 1cm
Для любого детерминированного конечного автомата $A$ существует
такое $n\in\mathbb{N}$, что каждая цепочка $w\in L(A)$
длины не менее $n$
представима в виде $w=\alpha\beta\gamma$, причем
$\alpha\beta^r\gamma\in L(A)$ для любого $r\in\mathbb{N}$.
\end{lemma}
}

Допустим, что наш язык $D$ принадлежит классу $\DSPACE(O(1))$, то
есть он распознается некоторым детерминированным конечным
автоматом. Тогда для него выполняется лемма о разрастании. Рассмотрим
строку длины не менее $n$ и попытаемся найти повторяющуюся подстроку $\beta$. 
Поскольку с ростом строки начальный блок из нулей должен расти,
строка $\beta$ должна начинаться с нуля (причем это нуль, стоящий до первой
единицы). По аналогичной причине 
она должна оканчиваться на единицу. Но тогда для любого $r\in\mathbb{N}$
строка $\alpha\beta^r\gamma$ начинается на одно и то же количество нулей,
что для достаточно больших $r$ противоречит $\alpha\beta^r\gamma\in L(A)$.
(Другое доказательство: количество символов $\$$ в каждом слове языка $D$
является степенью двойки, значит, по лемме о разрастании все они должны
входить в строку $\beta$, что противоречит тому, что расстояние между 
двумя символами $\$$ увеличивается с ростом длины строки.)
Таким образом, $D\notin\DSPACE(O(1))$.

%Отметим, что
%с ростом $k$ начальный блок нулей неизбежно захватит нашу
%подстроку целиком, то есть она должна состоять лишь из нулей.
%Аналогично финальный блок единиц также захватит нашу подстроку
%целиком, то есть она должна состоять лишь из единиц. Полученное
%противоречие показывает, что наш язык $D\notin\DSPACE(O(1)).$

Построим теперь машину Тьюринга, принимающую наш язык, используя
$O(\log\log n)$ ячеек памяти. Пусть на вход машине подана строка из нашего
языка, соответствующая некоторому натуральному $k.$ Машина будет в
этом случае работать в $k$ этапов. На $i$-м этапе задачей машины
будет проверить, что группы из $i$ последних битов
(счетчик $i$ занимает $O(\log k)=O(\log\log n)$ битов), взятых из
каждой из $2^k$ подстрок нашей строки, заключенных между знаками
$\$,$ образуют арифметическую прогрессию 
по модулю $2^i$ 
с разностью $1$. 
Например, для $i=1$ надо проверить, что последние биты в
каждой группе чередуются: $0,1,0,1,\ldots,0,1.$ Для $i=2$ надо
убедиться в том, что два последних бита образуют соответствующую
последовательность: $00,01,10,11,00,01,\ldots,11.$ 
%В итоге для строк
%из нашего языка проверка завершится успехом в тот момент, когда мы
%доберемся до знака $\$$, то есть вычислим таким образом то $k,$
%которому соответствует рассматриваемое слово. 
По окончании всех $k$ этапов следует проверить,
что $(k+1)$-й символ каждой группы --- действительно $\$$.
Очевидно, что для строк из $D$ все эти проверки пройдут.
Если же строка не
принадлежит $D$, то рано или поздно алгоритм обнаружит нарушение
структуры, и строка будет отвергнута.

Единственный момент, который не был рассмотрен до сих пор --- это
собственно организация процесса сравнения групп битов. Пусть у нас
есть группа битов $A,$ кодирующая некоторое число $s,$ и группа
битов $B,$ кодирующая число $t.$ Нам необходимо убедиться, что
$t=s+1.$ Для этого достаточно подсчитать длину
непрерывной последовательности единиц
в $A$, начинающейся с крайнего правого бита, 
и проверить, что в $B$ справа стоит точно такое же
количество нулей. Следующие цифры должны быть различны, а
оставшаяся часть должна совпадать. 
%Нетрудно заметить, что память
%нам необходима исключительно под хранение счетчика количества
%нулей.
Зная $i$ и $k$, нетрудно (при помощи счетчика, не превосходящего $k$)
добраться с нужной позиции $A$ до нужной позиции $B$, и наоборот
(вспомним, что $A$ и $B$ начинаются сразу за соседними символами $\$$
или, для самой первой группы битов, началом строки).
Очевидно, что размер нужного нам счетчика --- также $O(\log\log n)$.
%Объем этой памяти с учетом того, что длина анализируемой
%группы бит не превосходит $k=\log n,$ где $n$ --- длина слова,
%равен $\log k = \log\log n.$ Таким образом, наша машина требует
%для работы $O(\log\log n)$ памяти, что доказывает принадлежность
%нашего языка к классу $\DSPACE(\log\log n).$
\end{proof}

\section{Совсем маленькое количество памяти, не помогающее в вычислениях}

\begin{theorem}
$\forall\, \varepsilon>0\ \  
\DSPACE(O((\log\log n)^{1-\varepsilon}))=\DSPACE(O(1))$.
\end{theorem}

\begin{proof}
Рассмотрим машину, которая затрачивает не более\linebreak
$S(n)=O((\log\log n)^{1-\varepsilon})$ 
памяти на каждом входе длины $n$,
и покажем, что, начиная с некоторой
длины входа $N$ наша машина
использует одно и то же количество ячеек ленты
независимо от длины входа.

Для дальнейшего рассмотрения введем следующее определение:
\emph{псевдоконфигурацией} машины Тьюринга мы будем называть
конфигурацию, в которой вместо позиции считывающей головки на
\emph{входной} ленте хранится сам символ,
на который эта головка указывает.

Отметим сначала, что если алфавит машины Тьюринга есть множество
$\{0,1\},$ то общее количество псевдоконфигураций есть
$C(n)=O(S(n)2^{S(n)})$ (здесь первое $S(n)$ нужно для того, чтобы учесть
номер позиции на \emph{рабочей} ленте).
Рассмотрим теперь последовательность
псевдоконфигураций для состояния, характеризующегося некоторым
\emph{фиксированным} положением читающей головки на ленте. Ясно, что нас
интересуют лишь последовательности длины не более $C(n)$
(поскольку позиция головки на входной ленте
зафиксирована, более длинные
последовательности псевдоконфигураций
неизбежно ведут к зацикливанию, так как их количество --- это
количество разных \emph{конфигураций}). Таким образом,
общее число таких последовательностей можно оценить как
$$
C(n)^{C(n)}=
O\left(S(n)2^{S(n)}\right)^{O\left(S(n)2^{S(n)}\right)}=
O\left(S(n)2^{(S(n))^2\cdot2^{S(n)}}\right)=
$$
$$
=O(
n^{
(\log\log n)^{2-2\varepsilon}
\cdot
\log \log\log n
/
(\log n)^\varepsilon})=
o(n).
$$

Для всех $n$, больших некоторого $N\in\mathbb{N}$,
эта функция $<\frac{n}{2}$.
Мы утверждаем, что наша машина не использует более $S(N)$
ячеек ленты ни для какого входа длиннее $N$.

Пусть $x'$ --- самый короткий вход (из входов длины $>N$),
на котором используется более $S(N)$ памяти;
$n'$ --- его длина.
Заметим, что $x'$ можно представить в виде
$$
\begin{array}{ccccccccccc}
x'&=&\alpha &a&\beta &a&\gamma &a&\delta&\\
\mbox{(номера позиций:}&&
&\mbox{\scriptsize$i$}&
&\mbox{\scriptsize$j$}&
&\mbox{\scriptsize$k$}&
&\mbox{\scriptsize)},
\end{array}
$$
где позициям $i,j,k$ соответствует одна и та же последовательность
псевдоконфигураций (для каждой позиции рассматриваются псевдоконфигурации,
существующие в моменты, когда головка находится именно в этой позиции).
Такое представление возможно, так как есть $n'$ позиций входной ленты,
но менее $n'/2$ последовательностей псевдоконфигураций.
%Следовательно, найдутся три одинаковые последовательности, а
%значит и три одинаковых символа.

Покажем теперь, что каждая из псевдоконфигураций, встречающихся
при работе на строке $x'$, встречается также и при работе хотя
бы на одной из строка $\alpha a\gamma a\delta$ и $\alpha a\beta a\delta$ 
(это будет означать, что машина затрачивает на $x'$ столько же памяти,
сколько и на более короткой строке,
что противоречит предположению о минимальности $x'$).
Именно, соответствующая псевдоконфигурация должна встретиться
при работе на соответствующей строке (в момент чтения $\beta$ ---
при работе на $\alpha a\beta a\delta$, в момент чтения $\gamma$ ---
при работе на $\alpha a\gamma a\delta$).

Сравним работу машины на $\alpha a\gamma a\delta$ и на $x'$.
Соответствующие <<протоколы>> работы не будут отличаться до тех пор, пока
машина не сдвинется впервые правее $i$-й позиции входной ленты
(пусть до этого момента последовательность псевдоконфигураций
в $i$-й позиции --- $C_1,C_2,\ldots,C_t$).
Дальнейшее поведение машины на $x'$ нас не интересует до тех пор, пока она
не выйдет за пределы подстроки $a \beta a$.
Имеется два способа выйти: 
направо (правее $k$-й позиции) и налево.
Рассмотрим первый случай.

Заметим, что при работе на $x'$ последовательность
псевдоконфигураций в $k$-й позиции --- та же самая: $C_1,C_2,\ldots,C_t$.
Следовательно, машина впервые сдвинется правее $k$-й позиции в конфигурации
$C_t$. Ее дальнейшая работа не будет отличаться от 
дальнейшей работы на $\alpha a\gamma a \delta$,
%не будет отличаться от того, как машина 
%работала на $x'$, \emph{сдвинувшись правее позиции $k$}
%(пропустим часть <<протокола>> до этого момента --- она соответствует
%чтению $\beta$), 
поскольку псевдоконфигурации и считываемые 
символы на входной строке совпадают ---
и так до того момента, пока головка не сдвинется левее
соответствующей (в одном случае --- $i$-й, в другом --- $k$-й) позиции,
и$\;$т.$\;$д. (Случай, когда первый выход из $\beta$ ---
налево, аналогичен.)
%После этого момента <<протокол работы>> на более короткой строке снова
%совпадает с <<протоколом работы>> на первой части $x'$
%(тут мы снова выпустили часть второго <<протокола>>), и$\;$т.$\;$д.
%Пусть она дошла до первого
%вхождения символа $a.$ Тогда рано или поздно она дойдет до второго
%вхождения, а далее все совпадает с укороченной цепочкой.

Случай $\alpha a\beta a\delta$ также может быть рассмотрен аналогично.
%При этом ясно, что максимальное пространство тратится то же (так
%как работа исходной машины полностью моделируется). Таким образом,
%мы получили более короткую, чем $x',$ цепочку, на которой тратится
%больше $S(N)$ памяти. Противоречие с минимальностью длины $x'.$
\end{proof}

\section{Большее количество памяти, помогающее в вычислениях}

\begin{definition}
Для классов, определяемых с ограничением по памяти, 
мы будем рассматривать ограничения, являющиеся
\emph{<<space construc\-tible>>} функциями.
Функция $f$ является таковой, если существует детерминированная
машина Тьюринга,
вычисляющая (двоичное представление) $f(n)$
на входе $\underbrace{1\ldots1}_n$ и затрачивающая
на это память не более $f(n)$.
\end{definition}
\begin{remark}
Другие классы могут оказаться совершенно неестественными;
даже большая невычислимая добавка к ограничению на самом деле может
не добавить силы вычислениям.
\end{remark}

\begin{theorem}
$\DSPACE(S_1(n))\neq\DSPACE(S_2(n)),$ где $S_1(n)=o(S_2(n))$ и
$S_1(n)\ge\log n$ для всех $n>n_0.$
\end{theorem}

\begin{proof}
Рассмотрим следующий язык (обозначая $\langle M\rangle$ запись машины $M$ ---
т.е., по существу, ее функции перехода):
$$
\left\{x=\langle M\rangle 01^k \left|
\begin{aligned}
&k\in\mathbb{N}\cup\{0\}, \\
&\left|\langle M \rangle\right| < \frac1{10}S_2(|x|), \\
&\text{$M$ отвергает $x$ с памятью } \leq\frac1{10}S_2(|x|)
\end{aligned}
\right.\right\}.
$$
Этот язык мы можем распознать, используя $S_2(|x|)$ памяти.
Покажем, что его нельзя распознать, потратив только $S_1(|x|)$
памяти. Действительно, пусть существует машина $M_1,$ которая
производит такое распознавание. Тогда для некоторого $N$
и для всех $n>N$ справедливо
$S_1(n)<\frac1{10}S_2(n)$. Рассмотрим число $n$,
большее $N$ и большее $|\langle M_1\rangle|$.
Если строка $M_1$ принимает строку $\langle
M_1\rangle01^{n-|\langle M_1\rangle|-1}$,
то она по определению нашего языка ему не принадлежит,
а если отвергает, то принадлежит! 
\end{proof}

Можно доказать аналогичную теорему об иерархии по времени.
\begin{definition}
Для классов, определяемых с ограничением по времени, 
мы будем рассматривать ограничения, являющиеся
\emph{<<time construc\-tible>>} функциями.
Функция $f$ является таковой, если существует детерминированная
машина Тьюринга,
вычисляющая (двоичное представление) $f(n)$
на входе $\underbrace{1\ldots1}_n$ и затрачивающая
на это не более $f(n)$ шагов.
\end{definition}
\begin{theorem}\label{th:time}
$\DTIME(S_1(n))\neq\DTIME(S_2(n)),$ где
$$
\frac{S_1(n)\log S_2(n)}{S_2(n)}\to0
$$
и $S_1(n)\ge O(n)$ начиная с некоторого места.
\end{theorem}
\begin{exercise}
Докажите теорему~\ref{th:time}.
\qed
\end{exercise}

\end{document}
