Поиск с углублением
Поиск с углублением (англ. depth-limited search, итеративное углубление, iterative deepening depth-first search, IDDFS) — это стратегия обхода графа или дерева решений в информатике и теории алгоритмов, которая сочетает в себе преимущества поиска в глубину (DFS) и поиска в ширину (BFS). Основная идея заключается в последовательном выполнении поиска в глубину с возрастающим ограничением на максимальную глубину (лимитом), пока не будет найдена целевая вершина (узел) или не будет исчерпано всё пространство состояний. Алгоритм гарантирует нахождение кратчайшего пути (оптимального по числу рёбер) в невзвешенных графах, при этом используя значительно меньше памяти, чем поиск в ширину.
История и развитие
Концепция поиска с углублением возникла как ответ на ограничения классических методов поиска. Поиск в глубину (DFS) прост в реализации и требует памяти порядка O(d), где d — максимальная глубина, но не гарантирует нахождения кратчайшего пути и может зацикливаться в бесконечных графах. Поиск в ширину (BFS) гарантирует оптимальность, но требует памяти O(b^d), где b — коэффициент ветвления, что делает его неприменимым для задач с большим пространством состояний (например, в шахматах или планировании).
В 1970-х годах, с развитием искусственного интеллекта и теории игр, исследователи начали искать компромиссные решения. Одним из первых формальных описаний алгоритма итеративного углубления считается работа Ричарда Корфа (Richard Korf) 1985 года «Depth-First Iterative-Deepening: An Optimal Admissible Tree Search», где он доказал его оптимальность и эффективность для деревьев. Впоследствии алгоритм стал стандартным инструментом в задачах поиска путей, решения головоломок (например, «15-пятнашек» или «Кубика Рубика») и в игровых программах.
Алгоритм работы
Основная процедура
Поиск с углублением реализуется как последовательность вызовов поиска в глубину с ограничением (DLS). На каждом шаге алгоритм задаёт лимит глубины L (начиная с 0 или 1) и запускает DFS, который не углубляется дальше L. Если цель найдена, алгоритм завершается. Если нет — лимит увеличивается на 1, и процесс повторяется.
Псевдокод (упрощённый): ``` function IDDFS(root, goal): for depth = 0 to ∞: result = DLS(root, goal, depth) if result != failure: return result
function DLS(node, goal, depth): if depth == 0 and node == goal: return node if depth > 0: for each child in expand(node): result = DLS(child, goal, depth - 1) if result != failure: return result return failure ```
Особенности реализации
- Отсутствие запоминания посещённых узлов: в классической версии IDDFS не хранит информацию о посещённых узлах между итерациями, что экономит память, но может приводить к повторным вычислениям.
- Ограничение глубины: лимит L предотвращает бесконечное углубление в графах с циклами. Для графов с циклами требуется дополнительная проверка на повторное посещение узла в рамках одной итерации (например, с помощью хранения пути).
- Условие завершения: алгоритм завершается, когда либо найдена цель, либо при очередном увеличении лимита не было найдено ни одного нового узла (что свидетельствует о полном обходе).
Характеристики и сложность
Временная сложность
Временная сложность IDDFS в худшем случае составляет O(b^d), где b — коэффициент ветвления (среднее число потомков узла), d — глубина оптимального решения. Это кажется неэффективным из-за повторных обходов, однако на практике повторные вычисления незначительны: для дерева с b > 1 суммарное число узлов, обработанных за все итерации, составляет примерно b^d * (b/(b-1)). Например, при b=2 и d=10 IDDFS обработает примерно вдвое больше узлов, чем BFS, но при b=10 — всего на 11% больше. Таким образом, асимптотическая сложность совпадает с BFS.
Пространственная сложность
Пространственная сложность IDDFS составляет O(d) — линейная по глубине. Это главное преимущество перед BFS (O(b^d)). Алгоритм хранит только текущий путь от корня до обрабатываемого узла, что позволяет решать задачи с огромным пространством состояний (например, в планировании маршрутов или в играх).
Оптимальность
IDDFS является оптимальным для невзвешенных графов (деревьев), если стоимость пути измеряется числом рёбер. Он гарантированно находит кратчайший путь, так как последовательно увеличивает лимит глубины, и первое найденное решение будет иметь минимальную глубину.
Полнота
Алгоритм полон для конечных графов и для бесконечных деревьев с конечным коэффициентом ветвления. В графах с циклами полнота достигается за счёт ограничения глубины и проверки повторений в рамках одной итерации.
Применение
Искусственный интеллект и игры
- Головоломки: IDDFS широко используется для решения задач, где пространство состояний велико, но глубина решения невелика. Примеры: «Ханойская башня», «15-пятнашки», «Кубик Рубика». В 1990-х годах с помощью IDDFS были найдены оптимальные решения для многих состояний кубика Рубика (до 20 ходов).
- Игровые программы: в шахматах и шашках IDDFS применяется в алгоритмах минимакса с альфа-бета-отсечением для поиска на фиксированную глубину. Итеративное углубление позволяет программе использовать оставшееся время: если время истекло, возвращается результат последнего завершённого поиска.
Поиск путей в графах
- Навигация: в задачах поиска пути в лабиринтах или на картах IDDFS может быть эффективной альтернативой A*, если требуется минимальное использование памяти.
- Планирование: в робототехнике и планировании действий IDDFS применяется для поиска последовательностей операций, особенно когда пространство состояний неограниченно.
Компиляторы и анализ программ
- Символическое выполнение: IDDFS используется для обхода деревьев выполнения программ при поиске ошибок или уязвимостей, где глубина стека вызовов может быть большой, но ограничена.
Сравнение с другими алгоритмами
Поиск в ширину (BFS)
- Память: BFS требует O(b^d) памяти, IDDFS — O(d). Для задач с b=10 и d=10 BFS потребует хранения ~10^10 узлов, что невозможно на обычных компьютерах, тогда как IDDFS обходится сотнями узлов.
- Скорость: IDDFS обычно медленнее BFS на 10-30% из-за повторных обходов, но в задачах с ограниченной памятью он является единственным практичным выбором.
Поиск в глубину (DFS)
- Оптимальность: DFS не гарантирует нахождения кратчайшего пути, IDDFS — гарантирует.
- Полнота: DFS может зацикливаться в бесконечных графах, IDDFS — нет (при правильной реализации с ограничением глубины).
A* и эвристические алгоритмы
- Эвристики: IDDFS не использует эвристические функции, поэтому в задачах с известной эвристикой A или IDA (итеративное углубление A) могут быть быстрее. IDA является гибридом IDDFS и A*, где лимит задаётся не глубиной, а стоимостью пути (f-стоимостью).
Ограничения и критика
- Повторные вычисления: основной недостаток IDDFS — многократный пересчёт одних и тех же узлов на разных итерациях. Для деревьев с большим коэффициентом ветвления это приводит к незначительному замедлению, но для графов с малым b (например, b=2) накладные расходы могут составлять до 100%.
- Неприменимость к взвешенным графам: классический IDDFS не учитывает стоимость рёбер, поэтому для взвешенных графов (например, карт с расстояниями) он не гарантирует оптимальности. В таких случаях используются алгоритмы вроде IDA* или поиска с углублением по стоимости (DLS с весами).
- Зависимость от глубины: алгоритм плохо подходит для задач, где глубина решения неизвестна или очень велика (например, тысячи шагов). В таких случаях предпочтительнее эвристические методы.
Примеры использования
Решение головоломки «15-пятнашек»
Для классической головоломки «15-пятнашек» (4x4) пространство состояний содержит около 10^13 узлов. IDDFS позволяет найти оптимальное решение (минимальное число ходов) для большинства конфигураций за разумное время (от секунд до минут), используя память порядка нескольких килобайт. Например, для случайной конфигурации с глубиной решения 50 ходов IDDFS обработает около 10^7 узлов, что выполнимо на современном компьютере.
Поиск в шахматах
В шахматных программах (например, Stockfish, Deep Blue) итеративное углубление является стандартом. Программа начинает поиск на глубину 1, затем 2, 3 и т.д., пока не истечёт отведённое время. Это позволяет:
- Использовать результаты предыдущих итераций для упорядочивания ходов (таблицы транспозиции).
- Гарантировать, что при прерывании будет доступно хотя бы какое-то решение.
- Адаптироваться к ограничениям по времени в реальных партиях.
Интересные факты
- Алгоритм IDDFS иногда называют «поиском с итеративным углублением» (iterative deepening search, IDS). В русскоязычной литературе встречаются термины «итеративное углубление» и «поиск с ограничением глубины».
- В 1990-х годах IDDFS использовался в проекте Deep Blue (компания IBM) для поиска в шахматах, хотя основным алгоритмом был альфа-бета-поиск с итеративным углублением.
- Для задач с непрерывным пространством состояний (например, в робототехнике) существуют модификации IDDFS, работающие с вещественными числами.
Источники
- Корф, Р. (1985). «Depth-First Iterative-Deepening: An Optimal Admissible Tree Search». Artificial Intelligence, 27(1), 97-109.
- Рассел, С., Норвиг, П. (2010). «Искусственный интеллект: современный подход» (3-е изд.). — М.: Вильямс. — Глава 3.
- Кнут, Д. (1997). «Искусство программирования» (Том 1). — М.: Вильямс. — Раздел 2.3.4.
- Седжвик, Р. (2002). «Фундаментальные алгоритмы на C++». — М.: ДиаСофт. — Глава 5.
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →