Теорема Ладнера — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
(Утверждение 2)
(<math>...</math> -> <tex>...</tex>)
Строка 1: Строка 1:
 
'''Теорема Ладнера''' (Ladner's Theorem) утверждает,
 
'''Теорема Ладнера''' (Ladner's Theorem) утверждает,
что если [[P]] не совпадает с [[NP]], то существует язык <math>L</math>,
+
что если [[P]] не совпадает с [[NP]], то существует язык <tex>L</tex>,
принадлежащий <math>NP</math>, но не являющийся полиномиальным и [[NP-полнота|NP-полным]].
+
принадлежащий <tex>NP</tex>, но не являющийся полиномиальным и [[NP-полнота|NP-полным]].
  
 
==Иллюстрация==
 
==Иллюстрация==
  
Определим язык <math>A</math> как множество таких формул <math>\alpha</math>,
+
Определим язык <tex>A</tex> как множество таких формул <tex>\alpha</tex>,
что <math>\left\lfloor \frac{1}{2}\log_{10}^*|\alpha|\right\rfloor</math> чётно.
+
что <tex>\left\lfloor \frac{1}{2}\log_{10}^*|\alpha|\right\rfloor</tex> чётно.
Иными словами, <math>A</math> — это язык формул с длинами, лежащими в промежутках  
+
Иными словами, <tex>A</tex> — это язык формул с длинами, лежащими в промежутках  
 
<math>\left[1,10^{10}\right),
 
<math>\left[1,10^{10}\right),
 
\left[\underbrace{10^{10^{\cdot^{\cdot^{10}}}}}_4,
 
\left[\underbrace{10^{10^{\cdot^{\cdot^{10}}}}}_4,
\underbrace{10^{10^{\cdot^{\cdot^{10}}}}}_6\right), \dots</math>
+
\underbrace{10^{10^{\cdot^{\cdot^{10}}}}}_6\right), \ldots</math>
Далее будем обозначать <math>\underbrace{a^{a^{\cdot^{\cdot^{a}}}}}_n</math>
+
Далее будем обозначать <tex>\underbrace{a^{a^{\cdot^{\cdot^{a}}}}}_n</tex>
как <math>^{n}a</math>.
+
как <tex>^{n}a</tex>.
  
Рассмотрим язык [[SAT]] всех удовлетворимых формул. Логично предположить, что как в <math>A</math>,
+
Рассмотрим язык [[SAT]] всех удовлетворимых формул. Логично предположить, что как в <tex>A</tex>,
так и в <math>\bar{A}</math> лежит бесконечное множество элементов из <math>SAT</math>,
+
так и в <tex>\bar{A}</tex> лежит бесконечное множество элементов из <tex>SAT</tex>,
не распознаваемых за полиномиальное время, поэтому <math>SAT \cap A \not\in P</math>.
+
не распознаваемых за полиномиальное время, поэтому <tex>SAT \cap A \not\in P</tex>.
Из <math>A \in P</math> и <math>SAT \in NP</math> следует, что <math>SAT \cap A \in NP</math>.
+
Из <tex>A \in P</tex> и <tex>SAT \in NP</tex> следует, что <tex>SAT \cap A \in NP</tex>.
  
Осталось показать, что <math>SAT \cap A</math> не является NP-полным. Пусть
+
Осталось показать, что <tex>SAT \cap A</tex> не является NP-полным. Пусть
это не так. Тогда из NP-полноты следует, что существует полиномиальная функция <math>f</math>,
+
это не так. Тогда из NP-полноты следует, что существует полиномиальная функция <tex>f</tex>,
[[Сведение по Карпу|сводящая по Карпу]] <math>SAT</math> к <math>SAT \cap A</math>.  
+
[[Сведение по Карпу|сводящая по Карпу]] <tex>SAT</tex> к <tex>SAT \cap A</tex>.  
  
Возьмём формулу <math>\varphi</math> длиной <math>^{2k+1}10</math>.  
+
Возьмём формулу <tex>\varphi</tex> длиной <tex>^{2k+1}10</tex>.  
Она не лежит в <math>A</math> и, следовательно, в <math>SAT \cap A</math>.
+
Она не лежит в <tex>A</tex> и, следовательно, в <tex>SAT \cap A</tex>.
Функция <math>f</math> не может перевести <math>\varphi</math> в промежуток
+
Функция <tex>f</tex> не может перевести <tex>\varphi</tex> в промежуток
<math>\left[^{2k+2}10, ^{2k+4}10\right)</math> или дальше, так как размер
+
<tex>\left[^{2k+2}10, ^{2k+4}10\right)</tex> или дальше, так как размер
 
выхода полиномиальной функции не может быть экспоненциально больше длины
 
выхода полиномиальной функции не может быть экспоненциально больше длины
входа. Значит, <math>\varphi</math> отображается в меньший промежуток, но
+
входа. Значит, <tex>\varphi</tex> отображается в меньший промежуток, но
 
в этом случае размер выхода экспоненциально меньше длины входа.  Добавляя
 
в этом случае размер выхода экспоненциально меньше длины входа.  Добавляя
к этому то, что проверку на принадлежность <math>f(\varphi)</math>  
+
к этому то, что проверку на принадлежность <tex>f(\varphi)</tex> к
<math>SAT \cap A</math> можно осуществить за <math>O(2^{poly})</math>
+
<tex>SAT \cap A</tex> можно осуществить за <tex>O(2^{poly})</tex>
(это следует из её принадлежности классу <math>NP</math>), получаем программу,
+
(это следует из её принадлежности классу <tex>NP</tex>), получаем программу,
разрешающую <math>\varphi</math> за полином. Утверждение о том, что все формулы
+
разрешающую <tex>\varphi</tex> за полином. Утверждение о том, что все формулы
<math>\varphi</math> длиной <math>^{2k+1}10</math> принадлежат классу
+
<tex>\varphi</tex> длиной <tex>^{2k+1}10</tex> принадлежат классу
<math>P</math>, скорее всего не верно, и, следовательно, язык  
+
<tex>P</tex>, скорее всего не верно, и, следовательно, язык  
<math>SAT \cap A</math> не является NP-полным.
+
<tex>SAT \cap A</tex> не является NP-полным.
  
 
Заметим, что это объяснение не является доказательством!
 
Заметим, что это объяснение не является доказательством!
  
 
==Доказательство==
 
==Доказательство==
Будем искать язык <math>A</math>, удовлетворяющий следующим условиям:
+
Будем искать язык <tex>A</tex>, удовлетворяющий следующим условиям:
#<math>A \in P</math> (что влечёт за собой<math>SAT \cap A \in NP</math>);
+
#<tex>A \in P</tex> (что влечёт за собой<tex>SAT \cap A \in NP</tex>);
#<math>SAT \cap A \not\in P</math>;
+
#<tex>SAT \cap A \not\in P</tex>;
#<math>SAT \nleqslant SAT \cap A</math>.
+
#<tex>SAT \not \leq SAT \cap A</tex>.
  
Если такой язык существует, то <math>L = SAT \cap A</math> является искомым примером множества
+
Если такой язык существует, то <tex>L = SAT \cap A</tex> является искомым примером множества
из <math>NP \setminus (P \cup NPC)</math>.
+
из <tex>NP \setminus (P \cup NPC)</tex>.
  
 
===Утверждение 1===
 
===Утверждение 1===
Можно перечислить (возможно, с повторениями) все языки из <math>P</math>.
+
Можно перечислить (возможно, с повторениями) все языки из <tex>P</tex>.
  
 
Действительно, рассмотрим последовательность всех программ, упорядоченных по длине:
 
Действительно, рассмотрим последовательность всех программ, упорядоченных по длине:
<math> \tilde{p_0}, \tilde{p_1}, \ldots, \tilde{p_n}, \ldots</math>
+
<tex> \tilde{p_0}, \tilde{p_1}, \ldots, \tilde{p_n}, \ldots</tex>
Обозначим за <math>p_i</math> программу, запускающую <math>\tilde{p_i}</math>
+
Обозначим за <tex>p_i</tex> программу, запускающую <tex>\tilde{p_i}</tex>
с таймером <math>in^i</math>. Тогда среди <math>{p_i}</math> встречаются
+
с таймером <tex>in^i</tex>. Тогда среди <tex>{p_i}</tex> встречаются
только программы из <math>P</math>, и для каждой полиномиальной программы
+
только программы из <tex>P</tex>, и для каждой полиномиальной программы
<math>\tilde{p_i}</math>, работающей за полином <math>g_i(n)</math>, существует
+
<tex>\tilde{p_i}</tex>, работающей за полином <tex>g_i(n)</tex>, существует
номер <math>j</math> такой, что <math>jn^j > g_i(n)</math> для всех натуральных <math>n</math>
+
номер <tex>j</tex> такой, что <tex>jn^j > g_i(n)</tex> для всех натуральных <tex>n</tex>
и <math>\tilde{p_j}</math> делает то же самое, что и <math>\tilde{p_i}</math>.
+
и <tex>\tilde{p_j}</tex> делает то же самое, что и <tex>\tilde{p_i}</tex>.
Таким образом, <math>p_j</math> распознает тот же язык, что и <math>\tilde{p_i}</math>.
+
Таким образом, <tex>p_j</tex> распознает тот же язык, что и <tex>\tilde{p_i}</tex>.
  
 
===Утверждение 2===
 
===Утверждение 2===
Можно перечислить все функции из <math>\tilde{P}</math>.
+
Можно перечислить все функции из <tex>\tilde{P}</tex>.
  
Аналогично предыдущему доказательству, сначала построим последовательность <math>\tilde{f_i}</math>, а затем, добавив таймер <math>in^i</math>, получим последовательность <math>f_i</math>.
+
Аналогично предыдущему доказательству, сначала построим последовательность <tex>\tilde{f_i}</tex>, а затем, добавив таймер <tex>in^i</tex>, получим последовательность <tex>f_i</tex>.
  
===Описание способа построения <math>A</math>===
+
===Описание способа построения <tex>A</tex>===
Упорядочим все слова по возрастанию длины. Разобьем всё <math>\Sigma^{*}</math> на множества
+
Упорядочим все слова по возрастанию длины. Разобьем всё <tex>\Sigma^{*}</tex> на множества
<math>A_i</math> так, что <math>\forall i<j, \forall \alpha \in A_i, \beta \in A_j: |\alpha| < |\beta|</math>
+
<tex>A_i</tex> так, что <tex>\forall i<j, \forall \alpha \in A_i, \beta \in A_j: |\alpha| < |\beta|</tex>
(то есть разбиение происходит по длинам, причем <math>A_i</math> идут «подряд»),
+
(то есть разбиение происходит по длинам, причем <tex>A_i</tex> идут «подряд»),
<math>SAT \cap \bigcup_{i=0}^{k} A_{2i}</math> отличается от <math>L(p_k)</math> элементом
+
<tex>SAT \cap \bigcup_{i=0}^{k} A_{2i}</tex> отличается от <tex>L(p_k)</tex> элементом
из <math>\bigcup_{i=0}^{2k} A_i</math> и для любого <math>k</math> существует <math>\alpha \in \bigcup_{i=0}^{2k+1} A_i</math>,
+
из <tex>\bigcup_{i=0}^{2k} A_i</tex> и для любого <tex>k</tex> существует <tex>\alpha \in \bigcup_{i=0}^{2k+1} A_i</tex>,
для которого выполняются условия <math>f_k(\alpha) \in \bigcup_{i=0}^{2k+1} A_i</math> и  
+
для которого выполняются условия <tex>f_k(\alpha) \in \bigcup_{i=0}^{2k+1} A_i</tex> и  
<math>[\alpha \in SAT] \ne [f_k(\alpha) \in SAT \cap \bigcup_{i=0}^{k} A_{2i}]</math>.
+
<tex>[\alpha \in SAT] \ne [f_k(\alpha) \in SAT \cap \bigcup_{i=0}^{k} A_{2i}]</tex>.
  
 
<!--Куда-то сюда неплохо было бы добавить картинку-->
 
<!--Куда-то сюда неплохо было бы добавить картинку-->
  
Если мы сможем построить такие <math>A_i</math>, то язык <math>L = SAT \cap \bigcup_{i=0}^{\infty} A_{2i}</math>
+
Если мы сможем построить такие <tex>A_i</tex>, то язык <tex>L = SAT \cap \bigcup_{i=0}^{\infty} A_{2i}</tex>
 
будет отличаться от любого полиномиального языка, и ни одна полиномиальная функция не будет сводить
 
будет отличаться от любого полиномиального языка, и ни одна полиномиальная функция не будет сводить
<math>SAT</math> к <math>L</math>.
+
<tex>SAT</tex> к <tex>L</tex>.
  
Попытаемся построить такую полиномиальную функцию <math>f</math>, что  
+
Попытаемся построить такую полиномиальную функцию <tex>f</tex>, что  
<math>A_i = \left\{x \mid f(|x|) = i\right\}</math>. Тогда  
+
<tex>A_i = \left\{x \mid f(|x|) = i\right\}</tex>. Тогда  
 
<math>A=\left\{x \mid f(|x|) \, \vdots \, 2 \right\}</math> и  
 
<math>A=\left\{x \mid f(|x|) \, \vdots \, 2 \right\}</math> и  
 
<math>L=SAT \cap A = \left\{\varphi \mid \varphi \in SAT \and f(|\varphi|)\, \vdots \, 2\right\}</math>
 
<math>L=SAT \cap A = \left\{\varphi \mid \varphi \in SAT \and f(|\varphi|)\, \vdots \, 2\right\}</math>
  
===Построение <math>f</math>===
+
===Построение <tex>f</tex>===
Зададим <math>f(0) = f(1) = 0</math>. Затем рекурсивно определим <math>f(n)</math>. Для этого рассмотрим три случая:
+
Зададим <tex>f(0) = f(1) = 0</tex>. Затем рекурсивно определим <tex>f(n)</tex>. Для этого рассмотрим три случая:
*<math>(\log_2 n) ^ {f(n-1)} \ge n</math>:
+
*<tex>(\log_2 n) ^ {f(n-1)} \ge n</tex>:
*:<math>f(n) = f(n-1)</math>;
+
*:<tex>f(n) = f(n-1)</tex>;
*<math>f(n-1)=2i</math>:
+
*<tex>f(n-1)=2i</tex>:
*:если существует <math>x</math> такой, что <math>|x| < \log_2 n</math> и <math>p_i(x) \ne L(x)</math>, то <math>f(n) = f(n-1)+1</math>, иначе <math>f(n) = f(n-1)</math>;
+
*:если существует <tex>x</tex> такой, что <tex>|x| < \log_2 n</tex> и <tex>p_i(x) \ne L(x)</tex>, то <tex>f(n) = f(n-1)+1</tex>, иначе <tex>f(n) = f(n-1)</tex>;
*<math>f(n-1)=2i+1</math>:
+
*<tex>f(n-1)=2i+1</tex>:
*:если существует <math>x</math> такой, что <math>|x| < \log_2 n</math>,<math>|f_i(x)| < \log_2 n</math> и <math>SAT(x) \ne L(f_i(x))</math>, то <math>f(n) = f(n-1)+1</math>, иначе <math>f(n) = f(n-1)</math>.
+
*:если существует <tex>x</tex> такой, что <tex>|x| < \log_2 n</tex>,<tex>|f_i(x)| < \log_2 n</tex> и <tex>SAT(x) \ne L(f_i(x))</tex>, то <tex>f(n) = f(n-1)+1</tex>, иначе <tex>f(n) = f(n-1)</tex>.
  
Заметим, что вызовы <math>L(\alpha)</math> делаются для <math>\alpha</math>, для которых <math>f</math> уже построена.
+
Заметим, что вызовы <tex>L(\alpha)</tex> делаются для <tex>\alpha</tex>, для которых <tex>f</tex> уже построена.
  
Первый случай позволяет сказать, что <math>f(n)</math> ограничена <math>O\left(\log_{\log_2 n} n\right) = O(\log_2 n)</math>.
+
Первый случай позволяет сказать, что <tex>f(n)</tex> ограничена <tex>O\left(\log_{\log_2 n} n\right) = O(\log_2 n)</tex>.
Второй «ответственен» за множества <math>A_i</math> для чётных <math>i</math>, третий — для нечетных.
+
Второй «ответственен» за множества <tex>A_i</tex> для чётных <tex>i</tex>, третий — для нечетных.
Логарифм в условии <math>|x| < \log_2 n</math> необходим для полиномиальности <math>f(n)</math>.
+
Логарифм в условии <tex>|x| < \log_2 n</tex> необходим для полиномиальности <tex>f(n)</tex>.
  
===Полиномиальность <math>f</math>===
+
===Полиномиальность <tex>f</tex>===
Покажем, что <math>f \in \tilde{P}</math>. Для упрощения будем считать, что алфавит <math>\Sigma=\{0,1\}</math>.
+
Покажем, что <tex>f \in \tilde{P}</tex>. Для упрощения будем считать, что алфавит <tex>\Sigma=\{0,1\}</tex>.
  
<math>T(n) = T(n-1) + a(n)(b_1(n) + b_2(n) + b_3(n) + b_4(n)) + c_1(n) + c2_2(n)</math>, где:
+
<tex>T(n) = T(n-1) + a(n)(b_1(n) + b_2(n) + b_3(n) + b_4(n)) + c_1(n) + c2_2(n)</tex>, где:
*<math>T(n-1)</math> идёт на вычисление <math>f(n-1)</math>;
+
*<tex>T(n-1)</tex> идёт на вычисление <tex>f(n-1)</tex>;
*<math>a(n)</math> — время перебора всех слов <math>x</math> таких, что <math>|x| < \log_2 n</math>;
+
*<tex>a(n)</tex> — время перебора всех слов <tex>x</tex> таких, что <tex>|x| < \log_2 n</tex>;
*<math>b_1(n)</math> — время работы <math>p_i(x)</math>;
+
*<tex>b_1(n)</tex> — время работы <tex>p_i(x)</tex>;
*<math>b_2(n)</math> — время работы <math>SAT(x)</math>;
+
*<tex>b_2(n)</tex> — время работы <tex>SAT(x)</tex>;
*<math>b_3(n)</math> — время работы <math>L(x)</math>;
+
*<tex>b_3(n)</tex> — время работы <tex>L(x)</tex>;
*<math>b_4(n)</math> — время работы <math>L(f_i(x))</math>;
+
*<tex>b_4(n)</tex> — время работы <tex>L(f_i(x))</tex>;
*<math>c_1(n)</math> — время, необходимое для построения программы <math>p_i</math>;
+
*<tex>c_1(n)</tex> — время, необходимое для построения программы <tex>p_i</tex>;
*<math>c_2(n)</math> — время, необходимое для построения функции <math>f_i</math>.
+
*<tex>c_2(n)</tex> — время, необходимое для построения функции <tex>f_i</tex>.
  
<math>a(n) = O\left(2^{\log_2 n}\right) = O(n)</math>, таким образом <math>a(n) \in \tilde{P}</math>.
+
<tex>a(n) = O\left(2^{\log_2 n}\right) = O(n)</tex>, таким образом <tex>a(n) \in \tilde{P}</tex>.
  
<math>b_1(n) = O\left(i(\log_2 n)^i\right) = O\left(f(n-1)(\log_2 n)^{f(n-1)}\right) = O\left(f(n-1)n\right) = O(n^2) \in \tilde{P}</math>
+
<tex>b_1(n) = O\left(i(\log_2 n)^i\right) = O\left(f(n-1)(\log_2 n)^{f(n-1)}\right) = O\left(f(n-1)n\right) = O(n^2) \in \tilde{P}</tex>
  
<math>b_2(n) = O \left( 2^{\log_2 n} \log_2 n\right) = O\left(n \log_2 n\right) = O\left(n^2\right) \in \tilde{P}</math>
+
<tex>b_2(n) = O \left( 2^{\log_2 n} \log_2 n\right) = O\left(n \log_2 n\right) = O\left(n^2\right) \in \tilde{P}</tex>
  
<math>b_3(n) = O \left(2^{\log_2 n} \log_2 n + \log_2 n\right) = O \left(n \log_2 n\right) = O\left(n^2\right) \in \tilde{P}</math>
+
<tex>b_3(n) = O \left(2^{\log_2 n} \log_2 n + \log_2 n\right) = O \left(n \log_2 n\right) = O\left(n^2\right) \in \tilde{P}</tex>
  
<math>b_4(n) = b_3(b_1(n)) = O\left(n^4\right) \in \tilde{P}</math>
+
<tex>b_4(n) = b_3(b_1(n)) = O\left(n^4\right) \in \tilde{P}</tex>
  
Чтобы построить программу <math>p_i</math> достаточно построить <math>\tilde{p_i}</math>.  
+
Чтобы построить программу <tex>p_i</tex> достаточно построить <tex>\tilde{p_i}</tex>.  
Из того, что все <math>\tilde{p_i}</math> упорядочены по длине, следует, что длина
+
Из того, что все <tex>\tilde{p_i}</tex> упорядочены по длине, следует, что длина
<math>\tilde{p_i}</math> не превосходит <math>ci</math> (константа зависит от языка описания программы).
+
<tex>\tilde{p_i}</tex> не превосходит <tex>ci</tex> (константа зависит от языка описания программы).
Поэтому для построения i-ой программы достаточно перебрать все <math>2^{ci+1}-1</math> слов с длиной не больше <math>ci</math>
+
Поэтому для построения i-ой программы достаточно перебрать все <tex>2^{ci+1}-1</tex> слов с длиной не больше <tex>ci</tex>
и вывести i-ое, являющееся программой. Такой способ требует <math>O(2^{ci}i) = O(2^{\log_2 n} \log_2 n) = O(n^2)</math> времени.
+
и вывести i-ое, являющееся программой. Такой способ требует <tex>O(2^{ci}i) = O(2^{\log_2 n} \log_2 n) = O(n^2)</tex> времени.
Аналогично можно построить и <math>f_i</math>. Из этого следует, что <math>c_1(n)</math> и <math>c_2(n)</math> тоже полиномиальны.
+
Аналогично можно построить и <tex>f_i</tex>. Из этого следует, что <tex>c_1(n)</tex> и <tex>c_2(n)</tex> тоже полиномиальны.
  
Получаем, что <math>T(n) = T(n-1) + poly</math>. Значит, <math>T(n) \le n \cdot poly </math>.  
+
Получаем, что <tex>T(n) = T(n-1) + poly</tex>. Значит, <tex>T(n) \le n \cdot poly </tex>.  
Поэтому <math>T(n) \in \tilde{P}</math> и <math>A \in P</math>.
+
Поэтому <tex>T(n) \in \tilde{P}</tex> и <tex>A \in P</tex>.
  
Таким образом, <math>f</math> полиномиальна и <math>A \in P</math>.
+
Таким образом, <tex>f</tex> полиномиальна и <tex>A \in P</tex>.
  
===Доказательство выполнения свойств <math>A</math>===
+
===Доказательство выполнения свойств <tex>A</tex>===
Предположим, что <math>\lim_{n \to \infty}f(n) = 2i</math>. Это значит, что фунция «застряла» в ветке «иначе» случая два,
+
Предположим, что <tex>\lim_{n \to \infty}f(n) = 2i</tex>. Это значит, что фунция «застряла» в ветке «иначе» случая два,
но из этого следует, что <math>SAT</math> не отличается от <math>L(p_i)</math>. Это
+
но из этого следует, что <tex>SAT</tex> не отличается от <tex>L(p_i)</tex>. Это
влечёт за собой принадлежность <math>SAT</math> к <math>P</math>, что противоречит предположению <math>P \ne NP</math>.
+
влечёт за собой принадлежность <tex>SAT</tex> к <tex>P</tex>, что противоречит предположению <tex>P \ne NP</tex>.
  
Аналогично, в случае, если <math>\lim_{n \to \infty}f(n) = 2i+1</math>. Тогда функция «застряла» в ветке «иначе» случая три.
+
Аналогично, в случае, если <tex>\lim_{n \to \infty}f(n) = 2i+1</tex>. Тогда функция «застряла» в ветке «иначе» случая три.
Следствием этого является то, что <math>SAT</math> функцией <math>p_i</math> сводится к конечному множеству, что тоже
+
Следствием этого является то, что <tex>SAT</tex> функцией <tex>p_i</tex> сводится к конечному множеству, что тоже
противоречит предположению <math>P \ne NP</math>.
+
противоречит предположению <tex>P \ne NP</tex>.
  
Получается, что <math>\lim_{n \to \infty}f(n) = +\infty</math>, но по построению если <math>f</math> неограниченно растет,
+
Получается, что <tex>\lim_{n \to \infty}f(n) = +\infty</tex>, но по построению если <tex>f</tex> неограниченно растет,
то <math>L</math> не совпадает ни с каким языком <math>L(p_i)</math> и ни одна функция <math>f_i</math> не сводит
+
то <tex>L</tex> не совпадает ни с каким языком <tex>L(p_i)</tex> и ни одна функция <tex>f_i</tex> не сводит
<math>SAT</math> к <math>L</math>.  Следовательно, выполняются все три требуемых свойста, и <math>L</math> является примером
+
<tex>SAT</tex> к <tex>L</tex>.  Следовательно, выполняются все три требуемых свойста, и <tex>L</tex> является примером
языка из <math>NP\setminus(P \cup NPC)</math>.
+
языка из <tex>NP\setminus(P \cup NPC)</tex>.
  
 
Теорема доказана.
 
Теорема доказана.

Версия 11:22, 13 марта 2010

Теорема Ладнера (Ladner's Theorem) утверждает, что если P не совпадает с NP, то существует язык [math]L[/math], принадлежащий [math]NP[/math], но не являющийся полиномиальным и NP-полным.

Иллюстрация

Определим язык [math]A[/math] как множество таких формул [math]\alpha[/math], что [math]\left\lfloor \frac{1}{2}\log_{10}^*|\alpha|\right\rfloor[/math] чётно. Иными словами, [math]A[/math] — это язык формул с длинами, лежащими в промежутках [math]\left[1,10^{10}\right), \left[\underbrace{10^{10^{\cdot^{\cdot^{10}}}}}_4, \underbrace{10^{10^{\cdot^{\cdot^{10}}}}}_6\right), \ldots[/math] Далее будем обозначать [math]\underbrace{a^{a^{\cdot^{\cdot^{a}}}}}_n[/math] как [math]^{n}a[/math].

Рассмотрим язык SAT всех удовлетворимых формул. Логично предположить, что как в [math]A[/math], так и в [math]\bar{A}[/math] лежит бесконечное множество элементов из [math]SAT[/math], не распознаваемых за полиномиальное время, поэтому [math]SAT \cap A \not\in P[/math]. Из [math]A \in P[/math] и [math]SAT \in NP[/math] следует, что [math]SAT \cap A \in NP[/math].

Осталось показать, что [math]SAT \cap A[/math] не является NP-полным. Пусть это не так. Тогда из NP-полноты следует, что существует полиномиальная функция [math]f[/math], сводящая по Карпу [math]SAT[/math] к [math]SAT \cap A[/math].

Возьмём формулу [math]\varphi[/math] длиной [math]^{2k+1}10[/math]. Она не лежит в [math]A[/math] и, следовательно, в [math]SAT \cap A[/math]. Функция [math]f[/math] не может перевести [math]\varphi[/math] в промежуток [math]\left[^{2k+2}10, ^{2k+4}10\right)[/math] или дальше, так как размер выхода полиномиальной функции не может быть экспоненциально больше длины входа. Значит, [math]\varphi[/math] отображается в меньший промежуток, но в этом случае размер выхода экспоненциально меньше длины входа. Добавляя к этому то, что проверку на принадлежность [math]f(\varphi)[/math] к [math]SAT \cap A[/math] можно осуществить за [math]O(2^{poly})[/math] (это следует из её принадлежности классу [math]NP[/math]), получаем программу, разрешающую [math]\varphi[/math] за полином. Утверждение о том, что все формулы [math]\varphi[/math] длиной [math]^{2k+1}10[/math] принадлежат классу [math]P[/math], скорее всего не верно, и, следовательно, язык [math]SAT \cap A[/math] не является NP-полным.

Заметим, что это объяснение не является доказательством!

Доказательство

Будем искать язык [math]A[/math], удовлетворяющий следующим условиям:

  1. [math]A \in P[/math] (что влечёт за собой[math]SAT \cap A \in NP[/math]);
  2. [math]SAT \cap A \not\in P[/math];
  3. [math]SAT \not \leq SAT \cap A[/math].

Если такой язык существует, то [math]L = SAT \cap A[/math] является искомым примером множества из [math]NP \setminus (P \cup NPC)[/math].

Утверждение 1

Можно перечислить (возможно, с повторениями) все языки из [math]P[/math].

Действительно, рассмотрим последовательность всех программ, упорядоченных по длине: [math] \tilde{p_0}, \tilde{p_1}, \ldots, \tilde{p_n}, \ldots[/math] Обозначим за [math]p_i[/math] программу, запускающую [math]\tilde{p_i}[/math] с таймером [math]in^i[/math]. Тогда среди [math]{p_i}[/math] встречаются только программы из [math]P[/math], и для каждой полиномиальной программы [math]\tilde{p_i}[/math], работающей за полином [math]g_i(n)[/math], существует номер [math]j[/math] такой, что [math]jn^j \gt g_i(n)[/math] для всех натуральных [math]n[/math] и [math]\tilde{p_j}[/math] делает то же самое, что и [math]\tilde{p_i}[/math]. Таким образом, [math]p_j[/math] распознает тот же язык, что и [math]\tilde{p_i}[/math].

Утверждение 2

Можно перечислить все функции из [math]\tilde{P}[/math].

Аналогично предыдущему доказательству, сначала построим последовательность [math]\tilde{f_i}[/math], а затем, добавив таймер [math]in^i[/math], получим последовательность [math]f_i[/math].

Описание способа построения [math]A[/math]

Упорядочим все слова по возрастанию длины. Разобьем всё [math]\Sigma^{*}[/math] на множества [math]A_i[/math] так, что [math]\forall i\lt j, \forall \alpha \in A_i, \beta \in A_j: |\alpha| \lt |\beta|[/math] (то есть разбиение происходит по длинам, причем [math]A_i[/math] идут «подряд»), [math]SAT \cap \bigcup_{i=0}^{k} A_{2i}[/math] отличается от [math]L(p_k)[/math] элементом из [math]\bigcup_{i=0}^{2k} A_i[/math] и для любого [math]k[/math] существует [math]\alpha \in \bigcup_{i=0}^{2k+1} A_i[/math], для которого выполняются условия [math]f_k(\alpha) \in \bigcup_{i=0}^{2k+1} A_i[/math] и [math][\alpha \in SAT] \ne [f_k(\alpha) \in SAT \cap \bigcup_{i=0}^{k} A_{2i}][/math].


Если мы сможем построить такие [math]A_i[/math], то язык [math]L = SAT \cap \bigcup_{i=0}^{\infty} A_{2i}[/math] будет отличаться от любого полиномиального языка, и ни одна полиномиальная функция не будет сводить [math]SAT[/math] к [math]L[/math].

Попытаемся построить такую полиномиальную функцию [math]f[/math], что [math]A_i = \left\{x \mid f(|x|) = i\right\}[/math]. Тогда [math]A=\left\{x \mid f(|x|) \, \vdots \, 2 \right\}[/math] и [math]L=SAT \cap A = \left\{\varphi \mid \varphi \in SAT \and f(|\varphi|)\, \vdots \, 2\right\}[/math]

Построение [math]f[/math]

Зададим [math]f(0) = f(1) = 0[/math]. Затем рекурсивно определим [math]f(n)[/math]. Для этого рассмотрим три случая:

  • [math](\log_2 n) ^ {f(n-1)} \ge n[/math]:
    [math]f(n) = f(n-1)[/math];
  • [math]f(n-1)=2i[/math]:
    если существует [math]x[/math] такой, что [math]|x| \lt \log_2 n[/math] и [math]p_i(x) \ne L(x)[/math], то [math]f(n) = f(n-1)+1[/math], иначе [math]f(n) = f(n-1)[/math];
  • [math]f(n-1)=2i+1[/math]:
    если существует [math]x[/math] такой, что [math]|x| \lt \log_2 n[/math],[math]|f_i(x)| \lt \log_2 n[/math] и [math]SAT(x) \ne L(f_i(x))[/math], то [math]f(n) = f(n-1)+1[/math], иначе [math]f(n) = f(n-1)[/math].

Заметим, что вызовы [math]L(\alpha)[/math] делаются для [math]\alpha[/math], для которых [math]f[/math] уже построена.

Первый случай позволяет сказать, что [math]f(n)[/math] ограничена [math]O\left(\log_{\log_2 n} n\right) = O(\log_2 n)[/math]. Второй «ответственен» за множества [math]A_i[/math] для чётных [math]i[/math], третий — для нечетных. Логарифм в условии [math]|x| \lt \log_2 n[/math] необходим для полиномиальности [math]f(n)[/math].

Полиномиальность [math]f[/math]

Покажем, что [math]f \in \tilde{P}[/math]. Для упрощения будем считать, что алфавит [math]\Sigma=\{0,1\}[/math].

[math]T(n) = T(n-1) + a(n)(b_1(n) + b_2(n) + b_3(n) + b_4(n)) + c_1(n) + c2_2(n)[/math], где:

  • [math]T(n-1)[/math] идёт на вычисление [math]f(n-1)[/math];
  • [math]a(n)[/math] — время перебора всех слов [math]x[/math] таких, что [math]|x| \lt \log_2 n[/math];
  • [math]b_1(n)[/math] — время работы [math]p_i(x)[/math];
  • [math]b_2(n)[/math] — время работы [math]SAT(x)[/math];
  • [math]b_3(n)[/math] — время работы [math]L(x)[/math];
  • [math]b_4(n)[/math] — время работы [math]L(f_i(x))[/math];
  • [math]c_1(n)[/math] — время, необходимое для построения программы [math]p_i[/math];
  • [math]c_2(n)[/math] — время, необходимое для построения функции [math]f_i[/math].

[math]a(n) = O\left(2^{\log_2 n}\right) = O(n)[/math], таким образом [math]a(n) \in \tilde{P}[/math].

[math]b_1(n) = O\left(i(\log_2 n)^i\right) = O\left(f(n-1)(\log_2 n)^{f(n-1)}\right) = O\left(f(n-1)n\right) = O(n^2) \in \tilde{P}[/math]

[math]b_2(n) = O \left( 2^{\log_2 n} \log_2 n\right) = O\left(n \log_2 n\right) = O\left(n^2\right) \in \tilde{P}[/math]

[math]b_3(n) = O \left(2^{\log_2 n} \log_2 n + \log_2 n\right) = O \left(n \log_2 n\right) = O\left(n^2\right) \in \tilde{P}[/math]

[math]b_4(n) = b_3(b_1(n)) = O\left(n^4\right) \in \tilde{P}[/math]

Чтобы построить программу [math]p_i[/math] достаточно построить [math]\tilde{p_i}[/math]. Из того, что все [math]\tilde{p_i}[/math] упорядочены по длине, следует, что длина [math]\tilde{p_i}[/math] не превосходит [math]ci[/math] (константа зависит от языка описания программы). Поэтому для построения i-ой программы достаточно перебрать все [math]2^{ci+1}-1[/math] слов с длиной не больше [math]ci[/math] и вывести i-ое, являющееся программой. Такой способ требует [math]O(2^{ci}i) = O(2^{\log_2 n} \log_2 n) = O(n^2)[/math] времени. Аналогично можно построить и [math]f_i[/math]. Из этого следует, что [math]c_1(n)[/math] и [math]c_2(n)[/math] тоже полиномиальны.

Получаем, что [math]T(n) = T(n-1) + poly[/math]. Значит, [math]T(n) \le n \cdot poly [/math]. Поэтому [math]T(n) \in \tilde{P}[/math] и [math]A \in P[/math].

Таким образом, [math]f[/math] полиномиальна и [math]A \in P[/math].

Доказательство выполнения свойств [math]A[/math]

Предположим, что [math]\lim_{n \to \infty}f(n) = 2i[/math]. Это значит, что фунция «застряла» в ветке «иначе» случая два, но из этого следует, что [math]SAT[/math] не отличается от [math]L(p_i)[/math]. Это влечёт за собой принадлежность [math]SAT[/math] к [math]P[/math], что противоречит предположению [math]P \ne NP[/math].

Аналогично, в случае, если [math]\lim_{n \to \infty}f(n) = 2i+1[/math]. Тогда функция «застряла» в ветке «иначе» случая три. Следствием этого является то, что [math]SAT[/math] функцией [math]p_i[/math] сводится к конечному множеству, что тоже противоречит предположению [math]P \ne NP[/math].

Получается, что [math]\lim_{n \to \infty}f(n) = +\infty[/math], но по построению если [math]f[/math] неограниченно растет, то [math]L[/math] не совпадает ни с каким языком [math]L(p_i)[/math] и ни одна функция [math]f_i[/math] не сводит [math]SAT[/math] к [math]L[/math]. Следовательно, выполняются все три требуемых свойста, и [math]L[/math] является примером языка из [math]NP\setminus(P \cup NPC)[/math].

Теорема доказана.