Vamos aplicar o Branch and Bound ao Knapsack , espero que isso torne o conceito claro para você.
Temos itens, rotulados de a . é o valor do ésimo item e seu peso. Tentamos encaixá-los em uma mochila que pode conter até peso no total, e tentamos maximizar a soma dos valores do item que colocamos na mochila.1 n v i i w i Tn1nviiwiT
A abordagem comum de retorno é a nossa base. Primeiro colocamos no pacote e depois resolvemos o problema para os itens restantes com recursão. Em seguida, removemos a do pacote e resolvemos o problema para os itens restantes novamente e retornamos a melhor configuração que encontramos. n - 1 v 1 n - 1v1n−1v1n−1
Esse retorno é a parte 'Ramificação' de Ramificação e limite. Você ramifica (no caso da mochila) dois casos: 'item faz parte da solução' e 'item não faz parte da solução'. Você pode visualizar isso como uma árvore binária, onde o filho esquerdo é um caso e o filho direito é o outro caso. Essa árvore é a árvore de pesquisa (ou espaço de pesquisa ): sua profundidade é e, portanto, possui nós. O algoritmo, portanto, tem um tempo de execução exponencial no número de itens.i n O ( 2 N )iinO(2n)
Agora chegamos à parte 'Limite': tentamos encontrar critérios para que possamos dizer 'essa configuração nunca funciona, então é melhor não nos incomodarmos em computar isso'. Um exemplo desse critério é 'o peso dos itens que já colocamos na mochila excede ': se adicionamos, digamos, os primeiros itens à mochila e, portanto, ela já está cheia, não há não adianta tentar colocar os itens até na mochila também, mas também não adianta tentar ajustar qualquer subconjunto de até na mochila, pois ela já está cheia, então economizamos cerca de casos. Outro exemplo é 'n / 2 nTn/2n n / 2 + 1 n 2 n / 2n/2+1nn/2+1n2n/2mesmo se eu colocar todos os itens restantes, o valor dos itens que eu coloquei não excederá a melhor configuração que encontrei até agora '.
Esses critérios essencialmente cortam partes da árvore de pesquisa: em algum nó, você diz, por exemplo, 'a subárvore esquerda não me dará uma configuração melhor, porque X', então você esquece essa subárvore e não a explora. Uma subárvore de profundidade que você cortou dessa maneira economiza nós, que podem aumentar bastante a velocidade se você tiver sorte.O ( 2 d )dO(2d)
Observe que isso se chama ' Limite ' porque geralmente envolve algum tipo de limite inferior ou superior: para o critério ' mesmo que eu coloque todos os itens restantes, o valor dos itens que eu coloquei não excederá a melhor configuração Eu descobri até agora ', o valor da sua melhor configuração até agora é um limite inferior para a melhor configuração; portanto, qualquer coisa que nunca ultrapasse esse limite inferior está fadada ao fracasso.
Você pode tornar a parte 'Limite' a mais complexa possível. Por exemplo, problemas de programação inteira geralmente são resolvidos usando relaxações: você relaxa seu programa para um programa linear, que pode ser resolvido em tempo polinomial, e então pode jogar fora muitos casos de suas variáveis binárias que nunca funcionarão de qualquer maneira. Em seguida, você ramifica nas opções restantes.
Observe que Branch and Bound geralmente apenas aumentam a velocidade na prática, mas não na teoria: é difícil dizer exatamente quanto da árvore de pesquisa é cortada usando suas heurísticas. Isso é testemunhado pelo número de heurísticas diferentes usadas na prática em tais problemas. Se você não tiver sorte, a árvore de pesquisa restante permanece enorme, mesmo com muitos limites.