
- •Предисловие
- •Введение
- •Алгоритмы и их сложность
- •Примеры задач и алгоритмов
- •Задачи на графах: «Коммивояжер», «Кратчайшие пути», «Остовные деревья»
- •Приближенные алгоритмы: «Составление расписаний»
- •«Сортировка слиянием»
- •«Быстрая сортировка»
- •Формально об алгоритмах. Несложно о сложности
- •«RAM»: машины с произвольным доступом
- •Сложность в худшем случае
- •Сложность в среднем
- •Полиномиальные алгоритмы
- •Полиномиальность и эффективность
- •Аппроксимация с гарантированной точностью
- •Алгоритмы с оценками точности
- •Жадные алгоритмы для «Покрытия множеств»
- •Приближенные алгоритмы для «Вершинного покрытия»
- •Жадный алгоритм для «Рюкзака»
- •Алгоритм Кристофидеса
- •Аппроксимация с заданной точностью
- •«Рюкзак»: динамическое программирование
- •Полностью полиномиальная приближенная схема для «Рюкзака»
- •Вероятностный анализ детерминированных алгоритмов
- •Сложность и полиномиальность в среднем
- •Задача упаковки
- •Выполнимость КНФ
- •Точность алгоритма для почти всех входов
- •«Рюкзак»: полиномиальность в среднем
- •Вероятностные алгоритмы и их анализ
- •Вероятностная проверка тождеств
- •Максимальное по включению независимое множество в графе
- •Протокол византийского соглашения
- •Вероятностное округление
- •Максимальный разрез в графе
- •Методы дерандомизации
- •Метод условных вероятностей
- •Метод малых вероятностных пространств
- •Полиномиальная проверка простоты
- •Основы теории сложности вычислений
- •Сложность вычислений
- •Машины Тьюринга и вычислимость
- •Сводимость по Куку
- •Недетерминированные алгоритмы
- •Сводимость по Карпу
- •Вероятностные вычисления
- •Вероятностно проверяемые доказательства
- •Схемы и схемная сложность
- •Коммуникационная сложность
- •Диаграмма классов сложности
- •Приложения
- •Введение в Python
- •Глоссарий
- •Предметный указатель
- •Список алгоритмов

128 |
Глава 3. ВЕРОЯТНОСТНЫЙ АНАЛИЗ ДЕТЕРМИНИРОВАННЫХ АЛГОРИТМОВ |
∑ |
|
|
∑ |
n |
|
|
|
∑ |
n |
|
|
|
|
n |
n |
|
n |
n |
|
|
|
n |
n |
|
|
|
|
E jXnj = k=0 (k) Pk |
= 1 + k=1 (k) Pk |
1 + n + k=2 (k) Pk < |
|
|
|
|
|||||||
|
|
|
|
∑ |
|
mp2 |
|
|
∑ |
k ln n mp2(k 1) |
|
|
|
|
|
|
|
k |
e |
(k 1) |
1 + n + e |
= |
|
|
|||
|
|
|
< 1 + n + n |
|
|
|
|
|
|||||
|
|
|
|
k=2 |
|
|
|
|
k=2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
= 1 + n + n e |
(k 1)(ln n mp2) |
: |
|
|
|
|
|
|
|
|
|
|
|
|
k=2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
n |
|
|
|
|
|
|
|
|
|
|
|
|
|
∑ |
|
|
При условии mp2 |
|
ln n в последней сумме каждый член не превосходит 1. Это и означает, что E[X ] = |
|||||||||||
O(n2). |
|
|
|
|
|
|
|
|
|
|
n |
|
Некоторые экспериментальные результаты поведения алгоритма 28 «Упаковка-ДинПрог» на случайных данных, можно увидеть на рисунке 3.2.
В заключение отметим, что из полученных результатов вытекает не только полиномиальный в среднем алгоритм для задачи 15 «Packing», но и полиномиальный в среднем алгоритм для более трудной задачи подсчета числа целых точек в многограннике, заданном ограничениями (3.1).
3.3Выполнимость КНФ
Раздел основан на работе [Iwa89].

3.3. ВЫПОЛНИМОСТЬ КНФ |
129 |
|||||||||||||||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

130 |
|
|
|
|
|
|
|
|
|
Глава 3. ВЕРОЯТНОСТНЫЙ АНАЛИЗ ДЕТЕРМИНИРОВАННЫХ АЛГОРИТМОВ |
||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Рис. 3.3: Карта-памятка раздела 3.2.0
Задача 16. «Выполнимость/SAT»². Дано булевское выражение, являющееся конъюнктивной нормаль-
ной формой (КНФ):
m
CNF = Ci; |
(3.3) |
i=1 |
|
где Ci — элементарные дизъюнкции вида
1 |
_ |
k |
; |
(3.4) |
xj1 |
: : : _ xjk |
²В англоязычной литературе — Sa sfiability или просто SAT.

3.3. ВЫПОЛНИМОСТЬ КНФ |
131 |
1 k n, j 2 f0; 1g, x1 = x и x0 = (:x).
Существует ли (булевский) набор переменных xj, обращающий эту форму в 1 (т. е. в «Истину»)?
Задаче 16 «SAT» выпала честь быть первой задачей, для которой была установлена NP-полнота (cм. раздел 6.2). И хотя NP-полнота задачи, по сути, определяет «переборность» любого алгоритма для ее решения³, одни виды перебора могут быть перспективнее других.
Итак, как можно организовать решение этой задачи?
Самым простым решением будет перебор всех входных наборов x = fx1; : : : ; xng, пока CNF (x) не станет равна единице. Однако в худшем случае, например, если CNF невыполнима, надо перебрать 2n наборов x.
Для некоторых формул этот перебор можно сократить, если обеспечить подсчет размера множества невыполнимых наборов — jX0j, где X0 = fx : CNF (x) = 0g. CNF невыполнима тогда и только тогда, когда jX0j = 2n.
Остается вопрос: как подсчитать jX0j более эффективно, нежели перебором x? Введем (или напомним) несколько обозначений.
Определение 3.3.1. Литерал — каждое вхождение переменной xi (или ее отрицания) в скобку. Например, для (x1 _ x2) ^ (x1 _ x3) литералами будут x1; x2; x1; x3.
Для некоторого подмножества из k скобок S = fCj1 ; : : : ; Cjk g мы обозначим через LitS все литералы S, т. е. все литералы lit 2 fxi; xig, входящие в S.
Рассмотрим некоторую КНФ (обозначим ее CNF (x)). На каких наборах она равна нулю? Очевидно, если CNF (x) = 0, то одна или несколько скобок-дизъюнкций Cj(x) = 0.
³Разумеется, при гипотезе P ≠ NP

132 |
Глава 3. ВЕРОЯТНОСТНЫЙ АНАЛИЗ ДЕТЕРМИНИРОВАННЫХ АЛГОРИТМОВ |
Возьмем некоторое подмножество S = fCj1 ; : : : ; Cjk g из k скобок и зададимся вопросом: когда все скобки в S будут равны нулю? Обозначим это утверждение предикатом ZS(x) = 1 и раскроем определение:
|
|
|
|
|
|
|
|
|
|
k |
|
k |
|
|
|
ZS(x) |
= |
Cji |
= |
|
lit |
= |
lit: |
|
|
i=1 |
|
i=1 |
lit2Cji |
|
lit2LitS |
|
|
|
|
|
|
т. е. ZS зависит только от множества литералов LitS и не зависит от распределения литералов по отдельным скобкам. А для множества S возможны два варианта. Множество S может быть:
зависимое — 9i: литералы xi 2 LitS и xi 2 LitS. В этом случае ZS 0, т. е. jx : ZS(x) = 1j = 0 — нет выполняющих ZS наборов.
независимое — i: xi 2 LitS и xi 2 LitS. Тогда есть выполняющие ZS наборы x, причем каждая переменная из LitS может входить либо в положительной степени и иметь значение «0», либо в отрицательной степени и иметь значение «1». т. е. если x3 2 LitS, то x3 = 1, а если x7 2 LitS, то x7 = 0. Для остальных переменных, не входящих в LitS, значение может быть любым. Поэтому jx : ZS(x) = 1j = 2n LitSj.
Итак, если 9x : CNF (x) = 0, то существует некоторое независимое S. Для подсчета размера множества обнуляющих наборов jX0j построим все независимые множества и просуммируем для каждого независимого множества S число «обнуляющих» наборов 2n LitSj.

3.3. ВЫПОЛНИМОСТЬ КНФ |
133 |
Рис. 3.4: «Обнуляющие» наборы для трехскобочной КНФ
Разумеется, напрямую суммировать нельзя, т.к. «обнуляющие» наборы различных множеств пересекаются. Например, рассмотрим трехскобочную (скобки C1; C2; C3) КНФ, у которой все наборы скобок fC1g, fC2g, fC3g, fC1; C2g, fC1; C3g, fC2; C3g, fC1; C2; C3g являются независимыми. Тогда множество «обнуляющих» наборов fx : ZfC1g = 1g включает в себя множество fx : ZfC1;C2g = 1g, которое включает

134 Глава 3. ВЕРОЯТНОСТНЫЙ АНАЛИЗ ДЕТЕРМИНИРОВАННЫХ АЛГОРИТМОВ
в себя, в свою очередь, множество fx : ZfC1;C2;C3g = 1g.
Как раз для подсчета мощности объединения пересекающихся множеств и применяется комбинаторная формула включений-исключений , утверждающая, что для конечных множеств A1; : : : ; An мощность их объединения можно подсчитать по формуле
|
Ai |
|
= |
∑ |
jAij |
∑ |
∑ |
|
|
n |
|
n |
jAi \ Ajj + |
jAi \ Aj \ Akj ( 1)n 1 jA1 \ \ Anj : |
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
i=1 |
|
|
|
i=1 |
|
i;j : i<j |
i;j;k : i<j<k |
В нашем случае Ai обозначает множество наборов, для которых i-я скобка Ci равна нулю, поэтому
jX0j = j [mi=1 Aij:
Далее удобно разбить все независимые множества на «k-слои» Nk: независимые множества с k скобками, и организовать суммирование включений-исключений по этим слоям:
∑ |
∑ |
m |
|
jX0j = ( 1)k 1 |
2n LitSj: |
k=1 |
S2Nk |
Осталось понять, как построить все независимые множества скобок. Оказалось, их также удобно строить «послойно», получая Nk+1 из Nk попыткой «добавить» каждую скобку Cj к каждому множеству из Nk следующим образом, и оставляя только независимые множества, т.е. те множества, в которых ни один литерал не встречается со своим отрицанием.
Вариант: «формула включения-исключения», в англоязычной литературе — «inclusion-exclusion principle» или «sieve principle».

3.3. ВЫПОЛНИМОСТЬ КНФ |
135 |
Стартуем же мы с пустого множества N0.
Заметим, что непосредственно для подсчета jX0j нет необходимости хранить все независимые множества, достаточно хранить текущее Nk (и вычисляемое Nk+1), и суммировать оценку jX0j по формуле включений-исключений одновременно с построением Nk+1.
Таким образом, мы получаем алгоритм 29.
Лемма 7. Сложность алгоритма 29 в наихудшем случае:
O(m2n max jNkj):
k
Доказательство. Действительно:
•цикл по «слоям» — O(m);
•цикл по скобкам — O(m);
•цикл по независимым множествам из k скобок — O(Nk).
•цикл по литералам в скобке (проверка независимости множества S = Cj + t) внесет множитель
O(n);
Общая трудоемкость — O(m2n maxk jNkj).
Видно, что, как и в случае с другими алгоритмами динамического программирования, время работы алгоритма определяется размером множества частичных решений (в данном случае Nk). В частности, оно может быть экспоненциальным.

136 |
Глава 3. ВЕРОЯТНОСТНЫЙ АНАЛИЗ ДЕТЕРМИНИРОВАННЫХ АЛГОРИТМОВ |
Алгоритм 29 Динамическое программирование для «SAT»
def sat_counting(cnf):
size = 0 #счетчик выполняющих КНФ наборов n = cnf.num_vars()
N = {cnf.empty_clauses_set(): SetOfLiterals([])} for k, dummy in enumerate(cnf): # цикл по слоям
S = {} # новый слой независимых множеств for j, C in enumerate(cnf): # цикл по скобкам for t in N: # цикл по независимым множествам
if j not in t: # если скобки там нет s = t + j # добавляем её
if s not in S: #в слое S нет такого? lit = copy(N[t]) # «наследуем» t for x in C:
ok = -x not in lit if not ok:
break # x несовместен lit.add(x)
if ok and len(lit) > len(N[t]):
S[s] = lit # да, s — независимое size += 2**(n - len(lit)) * (-1)**k
N = S return size
CNF = (x2 _ x3 _ x1) ^ (x3 _ x2) ^ (x1 _ x3) ^ (x1 _ x2 _ x4)
k |
size |
N |
|
|
|
0 |
0 |
fg: fg |
1 |
12 |
fC0g: fx2; x3;x1g, fC3g: fx1; x2; x4g, fC1g: fx3;x2g, fC2g: fx1;x3g |
2 |
11 |
fC2; C3g: fx1; x2; x4;x3g |
3 |
11 |
|
|
|
|
end |
11 |
|
|
|
|
|
|
11 < 24 ! . |
CNF = (x3 _ x2) ^ (x1 _ x3) ^ (x3 _ x1) ^ (x2 _ x3)
k |
size |
N |
|
|
|
0 |
0 |
fg: fg |
1 |
8 |
fC0g: fx3;x2g, fC3g: fx2; x3g, fC1g: fx1;x3g, fC2g: fx3;x1g |
28
3 |
8 |
end |
8 |
8 = 23 ! .
3.3. ВЫПОЛНИМОСТЬ КНФ |
137 |
Упражнение 3.3.1. Какие входные данные для алгоритма 29 заставят его работать экспоненциально долго?
С другой стороны, на многих входах этот алгоритм работает эффективно.
Упражнение 3.3.2. На каких входных данных этот алгоритм будет работать O(m)?
Для оценки практичности алгоритма попробуем ввести некоторое вероятностное распределение входных данных и оценить сложность алгоритма в среднем.
Теорема 10. Пусть для каждой скобки вероятность появления каждой из n переменных (или ее отрицания) равна p, причем
np2 ln m:
Тогда алгоритм 29 является полиномиальным в среднем.
Доказательство. Для доказательства достаточно будет оценить сверху математическое ожидание jNkj. Пусть Sk — некоторое множество скобок, jSkj = k.
Вероятность того, что внутри одной скобки xi «не встретится» с :xi равна 1 p2. Вероятность p~i(Sk), что xi избежит встречи с :xi в каждой из k скобок Sk равна
p~i(Sk) = (1 p2)k:
Обозначим через pi(Sk) вероятность, что в Sk нет одновременно xi и :xi.
Эта вероятность pi(Sk), очевидно не больше вероятности p~i(Sk), ибо в последнем случае разрешается xi встретиться с :xi, если они будут в разных скобках (поскольку мы оцениваем дополнения событий, то дополнение к более узкому событию и дает верхнюю оценку), поэтому
pi(Sk) (1 p2)k:

138 Глава 3. ВЕРОЯТНОСТНЫЙ АНАЛИЗ ДЕТЕРМИНИРОВАННЫХ АЛГОРИТМОВ
Теперь оценим вероятность того, что Sk — независимое множество, обозначив ее через P (Sk):
∏n
P (Sk) = pi(Sk) (1 p2)kn:
i=1
Видно, что эта вероятность зависит только от размера множества Sk, поэтому дальше будем обозначать ее через P (k).
Теперь можно оценить математическое ожидание maxk jNkj:
|
|
|
∑ |
|
|
∑ |
|
|
|
|
|
|
|
|
m |
m |
|
m |
m |
|
|
|
|
|
max |
N |
|
P (k) |
|
(1 p2)kn |
|
|
|||
E |
k j |
|
kj k=1 (k ) |
|
k=1 (k ) |
|
∑ |
||||
|
|
|
|
|
|
|
|
∑ |
|
∑ |
|
|
|
|
|
|
|
|
|
m |
|
m |
m |
|
|
|
|
|
|
|
|
|
mk expf np2kg expfk(ln m |
np2)g 1 = m: |
|
|
|
|
|
|
|
|
|
k=1 |
|
k=1 |
k=1 |
Упражнение 3.3.3. Докажите, что
|
|
|
|
∑ |
|
|
|
|
|
|
m |
m |
|
|
max |
N |
kj |
|
P (k): |
|
E |
k j |
|
k=1 (k ) |
|