Ветви и границы ( BB , B&B или BnB ) — это метод решения задач оптимизации путем разбиения их на более мелкие подзадачи и использования ограничивающей функции для устранения подзадач, которые не могут содержать оптимальное решение. Это парадигма разработки алгоритмов для дискретных и комбинаторных задач оптимизации, а также математической оптимизации . Алгоритм ветвей и границ состоит из систематического перечисления возможных решений с помощью поиска в пространстве состояний : набор возможных решений рассматривается как образующий корневое дерево с полным набором в корне. Алгоритм исследует ветви этого дерева, которые представляют подмножества множества решений. Перед перечислением возможных решений ветви ветвь проверяется на соответствие верхней и нижней оценочным границам оптимального решения и отбрасывается, если она не может дать лучшее решение, чем лучшее, найденное алгоритмом на данный момент.
Алгоритм зависит от эффективной оценки нижних и верхних границ регионов/ветвей пространства поиска. Если границы недоступны, алгоритм вырождается в исчерпывающий поиск.
Метод был впервые предложен Эйлсой Лэнд и Элисон Дойг во время проведения исследований в Лондонской школе экономики, спонсируемых British Petroleum, в 1960 году для дискретного программирования , [1] [2] и стал наиболее часто используемым инструментом для решения NP-трудных задач оптимизации. [3] Название «ветви и границы» впервые появилось в работе Литтла и др. по задаче коммивояжера . [4] [5]
Целью алгоритма ветвей и границ является поиск значения x , которое максимизирует или минимизирует значение действительной функции f ( x ) , называемой целевой функцией, среди некоторого множества S допустимых или потенциальных решений . Множество S называется пространством поиска или допустимой областью . Остальная часть этого раздела предполагает, что минимизация f ( x ) желательна; это предположение не теряет общности , поскольку можно найти максимальное значение f ( x ) путем нахождения минимума g ( x ) = − f ( x ) . Алгоритм B&B работает в соответствии с двумя принципами:
Превращение этих принципов в конкретный алгоритм для определенной задачи оптимизации требует некоторой структуры данных , которая представляет наборы возможных решений. Такое представление называется экземпляром задачи . Обозначим набор возможных решений экземпляра I как S I . Представление экземпляра должно содержать три операции:
Используя эти операции, алгоритм B&B выполняет рекурсивный поиск сверху вниз по дереву экземпляров , сформированных операцией ветвления. При посещении экземпляра I он проверяет, равен ли bound( I ) текущей верхней границе или больше ее; если это так, I можно безопасно исключить из поиска, и рекурсия останавливается. Этот шаг обрезки обычно реализуется путем поддержания глобальной переменной, которая записывает минимальную верхнюю границу, наблюдаемую среди всех рассмотренных до сих пор экземпляров.
Ниже приведен скелет универсального алгоритма ветвей и границ для минимизации произвольной целевой функции f . [3] Чтобы получить фактический алгоритм из этого, требуется ограничивающая функция bound , которая вычисляет нижние границы f на узлах дерева поиска, а также правило ветвления, специфичное для проблемы. Таким образом, универсальный алгоритм, представленный здесь, является функцией высшего порядка .
Можно использовать несколько различных структур данных очереди . Эта реализация на основе очереди FIFO дает поиск в ширину . Стек (очередь LIFO) даст алгоритм поиска в глубину . Алгоритм поиска наилучшего первого ветвления и границ может быть получен с помощью приоритетной очереди , которая сортирует узлы по их нижней границе. [3] Примерами алгоритмов поиска наилучшего первого наилучшего с этой предпосылкой являются алгоритм Дейкстры и его потомок поиск A* . Вариант поиска в глубину рекомендуется, когда нет хорошей эвристики для получения начального решения, потому что он быстро дает полные решения и, следовательно, верхние границы. [7]
Реализация вышеизложенного на псевдокоде, похожем на C++ , выглядит следующим образом:
// C++-подобная реализация ветвей и границ,// предполагая, что целевая функция f должна быть минимизированаКомбинаторное решение branch_and_bound_solve ( Комбинаторная задача , ObjectiveFunction объективная_функция /*f*/ , Ограничивающая функция нижняя_граничная_функция /*ограниченная*/ ) { // Шаг 1 выше. double problem_upper_bound = std :: numeric_limits < double >:: infinity ; // = B Комбинаторное решение эвристическое_решение = эвристическое_решение ( задача ); // x_h problem_upper_bound = objective_function ( heuristic_solution ); // B = f(x_h) Комбинаторное решение current_optimum = эвристическое_решение ; // Шаг 2 выше очередь < CandidateSolutionTree > candidate_queue ; // инициализация очереди, специфичная для проблемы candidate_queue = populate_candidates ( проблема ); while ( ! candidate_queue . empty ()) { // Шаг 3 выше // Шаг 3.1 узел CandidateSolutionTree = candidate_queue . pop (); // "узел" представляет N выше если ( узел . представляет_единственный_кандидат ()) { // Шаг 3.2 если ( целевая_функция ( узел.кандидат ( ) ) < верхняя_граница_проблемы ) { current_optimum = узел . candidate (); верхняя_граница_проблемы = целевая_функция ( текущий_оптимум ); } // в противном случае узел является единственным кандидатом, который не является оптимальным } else { // Шаг 3.3: узел представляет ветвь возможных решений // "child_branch" представляет N_i выше для ( auto && child_branch : node . candidate_nodes ) { если ( нижняя_граница_функция ( дочерняя_ветвь ) <= проблема_верхняя_граница ) { candidate_queue.enqueue ( child_branch ) ; // Шаг 3.3.2 } // в противном случае bound(N_i) > B, поэтому мы обрезаем ветвь; шаг 3.3.1 } } } вернуть текущий_оптимум ; }
В приведенном выше псевдокоде функции heuristic_solve
и , populate_candidates
вызываемые как подпрограммы, должны быть предоставлены как применимые к проблеме. Функции f ( objective_function
) и bound ( lower_bound_function
) рассматриваются как объекты функций , как они написаны, и могут соответствовать лямбда-выражениям , указателям функций и другим типам вызываемых объектов в языке программирования C++.
Когда — вектор , алгоритмы ветвей и границ можно объединить с интервальным анализом [8] и методами контракторов , чтобы обеспечить гарантированное нахождение глобального минимума. [9] [10]
Этот подход используется для ряда NP-трудных задач:
Ветви и границы также могут быть основой различных эвристик . Например, может возникнуть желание прекратить ветвление, когда разрыв между верхней и нижней границами становится меньше определенного порога. Это используется, когда решение «достаточно хорошо для практических целей» и может значительно сократить требуемые вычисления. Этот тип решения особенно применим, когда используемая функция стоимости является шумной или является результатом статистических оценок и, таким образом, не известна точно, а скорее известна только как находящаяся в диапазоне значений с определенной вероятностью . [ требуется цитата ]
Нау и др. представляют обобщение метода ветвей и границ, которое также включает в себя алгоритмы поиска A* , B* и альфа-бета . [16]
Для решения этой проблемы можно использовать метод ветвей и границ.
Максимизируйте с этими ограничениями
и являются целыми числами.
Первый шаг — ослабить целочисленное ограничение. У нас есть две крайние точки для первого уравнения, которые образуют линию: и . Мы можем образовать вторую линию с векторными точками и .
Третья точка — . Это область выпуклой оболочки , поэтому решение лежит в одной из вершин области. Мы можем найти пересечение, используя сокращение строк, которое равно , или со значением 276,667. Мы проверяем другие конечные точки, проводя линию по области, и обнаруживаем, что это максимум по действительным числам.
Мы выбираем переменную с максимальной дробной частью, в этом случае она становится параметром для метода ветвей и границ. Мы переходим к и получаем 276 @ . Мы достигли целочисленного решения, поэтому переходим к другой ветви . Мы получаем 275,75 @ . У нас есть десятичное решение, поэтому переходим к и находим 274,571 @ . Мы пробуем другую ветвь , но допустимых решений нет. Следовательно, максимум равен 276 с и .