Определим язык [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), \dots[/math]
Далее будем обозначать [math]\underbrace{a^{a^{\cdot^{\cdot^{a}}}}}_n[/math]
как [math]^{n}a[/math].
Рассмотрим язык [math]SAT[/math]. Логично предположить, что как в [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], удовлетворяющий следующим условиям:
- [math]A \in P[/math] (что влечёт за собой[math]SAT \cap A \in NP[/math]);
- [math]SAT \cap A \not\in P[/math];
- [math]SAT \nleqslant 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]q_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]SAT(x) \ne L(f_i(x))[/math], то [math]f(n) = f(n-1)+1[/math], иначе [math]f(n) = f(n-1)[/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) = b3(b1(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].
Теорема доказана.