1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6

# теория · шаг 3 из 6

Покрытие множеств: жадность без оптимума, но с гарантией

Коротко

Покрытие множеств - выбрать как можно меньше множеств, чтобы накрыть все элементы. Задача NP-трудна, точной жадности нет: естественный критерий «брать множество, накрывающее больше всего НЕНАКРЫТОГО» даёт не оптимум, а ответ не хуже оптимума примерно в ln n раз (точнее - в H(n) = 1 + 1/2 + ... + 1/n раз), и лучшего отношения не даёт ни один полиномиальный алгоритм - при условии, что P ≠ NP. Так появляется третий режим работы с жадностью: не «доказать оптимальность» и не «отвергнуть», а доказать гарантию. Вершинное покрытие показывает это с неожиданной стороны: «жадность по степени» КОНСТАНТНОЙ гарантии не имеет (только логарифмическую), а грубый приём «берём ОБА конца непокрытого ребра» даёт гарантию 2 - при том что на конкретных данных может отвечать хуже.

Если ты знаешь, что такое c-приближённый алгоритм, помнишь оценки ln n и 2 и понимаешь, почему алгоритм с гарантией может проиграть алгоритму без неё, листай до «Теперь сам».

Как думаешь, когда жадность всё-таки берут

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

Задача NP-трудна - точного быстрого алгоритма нет ни у кого. Отвергнуть жадность? Тогда чем решать? Вопрос: что можно УТВЕРЖДАТЬ про ответ жадного алгоритма, если оптимум недостижим?

На что это похоже

Оценка ремонта. Точную стоимость заранее не знает никто, и честный подрядчик говорит не «будет столько», а «не дороже чем в полтора раза против сметы». Это не отказ от ответа, а ответ другого типа - с ГАРАНТИЕЙ сверху. Приближённые алгоритмы устроены ровно так: ответ не точный, но отклонение ограничено доказанной величиной.

Механизм: жадность с гарантией

ПОКРЫТИЕ МНОЖЕСТВ
дано: универсум U из n элементов и семейство множеств S₁...S_m
найти: наименьшее число множеств, объединение которых равно U

ЖАДНЫЙ КРИТЕРИЙ: брать множество, накрывающее больше всего ещё НЕНАКРЫТЫХ элементов
цена: Θ(сумма размеров множеств) при аккуратной реализации
гарантия: ответ <= H(n) · оптимум,  где H(n) = 1 + 1/2 + ... + 1/n ≈ ln n
ЧТО ЗНАЧИТ c-ПРИБЛИЖЁННЫЙ АЛГОРИТМ

    для ЛЮБОГО входа:  ответ_алгоритма <= c · оптимум
    (для задач на минимум; для максимума - ответ >= оптимум / c)

c - граница ХУДШЕГО случая, а не типичная ошибка:
алгоритм с гарантией 2 на реальных данных обычно ошибается на проценты
ВЕРШИННОЕ ПОКРЫТИЕ: накрыть все рёбра минимальным числом вершин

приём 1: брать вершину наибольшей СТЕПЕНИ
    КОНСТАНТНОЙ гарантии нет: это частный случай покрытия множеств,
    то есть порядка ln n - хуже двойки
приём 2: пока есть непокрытые рёбра, брать любое из них
    и класть в ответ ОБА его конца
    гарантия 2: взятые рёбра не имеют общих вершин, значит в любом покрытии
    есть хотя бы по одной вершине из каждого - оптимум не меньше числа рёбер,
    а мы взяли ровно вдвое больше

Правило

Если задача NP-трудна, у жадности третий исход: не оптимум и не отказ, а ДОКАЗАННАЯ ГАРАНТИЯ. Алгоритм называют c-приближённым, если для любого входа его ответ не хуже оптимума в c раз; c - граница худшего случая. Жадность для покрытия множеств (брать множество с наибольшим числом ненакрытых элементов) даёт H(n) ≈ ln n, и при P ≠ NP лучшего отношения не добьётся ни один полиномиальный алгоритм - то есть жадность здесь не «пока лучшее, что придумали», а предел возможного. Для вершинного покрытия гарантию 2 даёт не жадность по степени (у неё гарантия лишь логарифмическая - это частный случай покрытия множеств), а приём «взять оба конца произвольного ребра». Важно: алгоритм с гарантией может на конкретных данных ответить ХУЖЕ алгоритма без гарантии - гарантия говорит про худший случай, а не про этот вход.

Разбор: жадность промахивается на трёх множествах

универсум: {1, 2, 3, 4, 5, 6}
множества:  A = {1, 2, 3, 4}
            B = {1, 2, 5}
            C = {3, 4, 6}
ЖАДНОСТЬ
шаг 1: A накрывает 4 элемента, B - 3, C - 3  → берём A
       ненакрыто: {5, 6}
шаг 2: B накрывает из них {5} - один; C накрывает {6} - один → берём B
       ненакрыто: {6}
шаг 3: берём C
ответ: 3 множества

ОПТИМУМ
B ∪ C = {1,2,5} ∪ {3,4,6} = {1,2,3,4,5,6} = U
ответ: 2 множества

Жадность взяла самое крупное множество - и именно оно оказалось лишним. Контрпример, как обычно, крошечный: три множества и шесть элементов.

Это и есть устройство плохого случая в общем виде: подбираются множества так, чтобы «самое жирное» множество каждый раз немного перекрывало нужные, и на каждом шаге жадность теряла чуть-чуть. Если продолжать конструкцию, потери накапливаются логарифмически - отсюда и оценка ln n, и она достигается, то есть не завышена.

Разбор: алгоритм с гарантией 2 проиграл алгоритму с худшей гарантией

Теперь тот поучительный случай, ради которого стоит мерить, а не рассуждать. Граф: центр 0 соединён с 1, 2, 3, и ещё есть рёбра 1-4, 2-5, 3-6.

рёбра: 0-1, 0-2, 0-3, 1-4, 2-5, 3-6      (7 вершин, 6 рёбер)

ОПТИМУМ (перебором):            {1, 2, 3}             → 3 вершины
ЖАДНОСТЬ ПО СТЕПЕНИ:            {0, 1, 2, 3}          → 4 вершины
«ОБА КОНЦА РЕБРА»:              {0, 1, 2, 5, 3, 6}    → 6 вершин

Смотри, что получилось. Алгоритм с доказанной гарантией 2 дал 6 - ровно вдвое хуже оптимума, то есть уткнулся в свою границу. Алгоритм с гарантией ХУЖЕ - логарифмической - дал 4, то есть точнее. И это не парадокс, а ровно то, что означает слово «гарантия»: она ограничивает худший случай для ВСЕХ входов, а на отдельном входе алгоритм с худшей гарантией может оказаться точнее.

Практический вывод из этого замера: лучшая гарантия - не повод выбирать алгоритм вслепую. Если данные известны и их можно прогнать, выбирают ЗАМЕРОМ; гарантия нужна там, где данные приходят любые и нужна уверенность в худшем случае. А лучший практический рецепт - запустить оба и взять лучший ответ: гарантия худшего случая от этого не портится.

Что ломается без этого

Первое: читать «гарантия 2» как «ошибается вдвое»: это граница сверху для худшего случая, а типичная ошибка обычно проценты. Второе: выбирать алгоритм по одной лишь гарантии, не замеряя на своих данных - как в разборе выше, где алгоритм с гарантией 2 проиграл алгоритму с логарифмической. Третье: считать, что жадность для покрытия множеств «пока не улучшили»: её ln n неулучшаем при P ≠ NP, то есть искать принципиально лучший полиномиальный алгоритм бессмысленно. Четвёртое: доказывать гарантию на примерах: «на сотне тестов не хуже чем на 10%» - это не гарантия, а наблюдение; гарантия - неравенство, доказанное для любого входа. Пятое: применять приём «оба конца ребра» к ВЗВЕШЕННОМУ вершинному покрытию: там он гарантии не даёт, нужен другой алгоритм - через линейное программированиеРазбирается в разделе 22, глава «ЛП-округление и прямо-двойственный метод»: Округление по порогу: взвешенное вершинное покрытие. Шестое: путать вершинное покрытие с покрытием множеств: формулировки похожи, гарантии разные (2 против ln n), и вершинное покрытие - частный случай покрытия множеств, но с лучшей оценкой.

Зачем это в работе

Покрытие множеств - это та задача, в которую превращается половина практических вопросов «выбрать минимальный набор, который закрывает всё». Минимальный набор тестов, покрывающих все ветки кода. Минимальный набор серверов, с которых видны все подсети. Минимальный набор правил фильтрации, закрывающих все известные атаки. Минимальный набор складов, обслуживающих все регионы. Во всех этих случаях точный ответ недостижим, а жадность даёт результат за минуты - и, что важно, можно сказать заказчику, насколько он может быть хуже идеала. Вторая половина урока - про профессиональную честность формулировок: «мы берём жадный алгоритм, он не хуже оптимума в ln n раз, на наших данных совпал с точным на выборке из тысячи задач» - это полный ответ. «Мы написали оптимальный алгоритм» - неполный и, скорее всего, неверный.

Теперь сам

Универсум {1, 2, 3, 4, 5}, множества S₁ = {1, 2, 3}, S₂ = {1, 4}, S₃ = {2, 5}, S₄ = {3, 4, 5}. Что даст жадность и каков оптимум?

Ответ.

ЖАДНОСТЬ
шаг 1: размеры 3, 2, 2, 3. Самое крупное - S₁ (или S₄; возьмём S₁)
       накрыто {1,2,3}, ненакрыто {4,5}
шаг 2: S₂ даёт {4} - один; S₃ даёт {5} - один; S₄ даёт {4,5} - ДВА → берём S₄
       накрыто всё
ответ: 2 множества (S₁ и S₄)

ОПТИМУМ: двух множеств достаточно (S₁ и S₄) - значит 2, меньше одного множества
         не бывает (ни одно не покрывает все пять элементов)

Здесь жадность попала в оптимум, и это нормальный, самый частый исход: плохие случаи надо конструировать специально. На этих данных, кстати, и «неправильный» критерий «самое большое множество по ОБЩЕМУ размеру» дал бы те же два множества (S₁ и S₄ - самые крупные, вместе они покрывают всё), так что различие критериев этот пример не показывает.

А вот пример, где они расходятся:

универсум {1..7}
S₁ = {1,3,6}   S₂ = {1,2,4,5,7}   S₃ = {1,3,4,7}   S₄ = {1,2,5,7}

по ОБЩЕМУ размеру: S₂ (5 элементов), затем S₃ (4), затем S₁ - три множества
по НЕНАКРЫТЫМ:     S₂ (5 новых), затем S₁ даёт {3,6} - два новых, остальные
                   по одному → два множества, и это оптимум

Разница в том, что «общий размер» не замечает перекрытий: S₃ большое, но три его элемента уже накрыты. Правильный критерий считает именно ПРИБАВКУ.

Главное

Если задача NP-трудна, у жадности третий исход - доказанная ГАРАНТИЯ. Алгоритм c-приближён, если для любого входа его ответ не хуже оптимума в c раз; c - граница худшего случая, не типичная ошибка. Покрытие множеств: жадность «больше всего НЕНАКРЫТЫХ элементов» даёт H(n) ≈ ln n, оценка достигается, и её главный член ln n неулучшаем при P ≠ NP. Контрпример к оптимальности крошечный: A={1,2,3,4}, B={1,2,5}, C={3,4,6} - жадность берёт 3 множества, оптимум 2. Вершинное покрытие: гарантию 2 даёт приём «оба конца НЕПОКРЫТОГО ребра» (взятые рёбра попарно независимы, значит оптимум не меньше их числа), а у жадности по степени гарантия лишь логарифмическая - вершинное покрытие есть частный случай покрытия множеств. Замер показывает, что гарантия не равна качеству: на звезде с отростками алгоритм с гарантией 2 дал 6, жадность по степени 4, оптимум 3. Выбор между ними - по замеру на своих данных, а гарантия нужна там, где вход может быть любым.

Комментарии

Пока нет комментариев. Будь первым!

Оставить комментарий

Комментарий появится после проверки. Email не публикуется. Войти, чтобы не вводить имя каждый раз.