O objetivo desta técnica de projeto de algoritmos é ser capaz de melhorar (não assintoticamente) um algoritmo de backtracking em relação a tempo e para problemas de otimização. Por ser de otimização, as soluções para uma instância podem ser classificadas em: factíveis sse ela não viola nenhuma das restrições do problema; e ótimas sse são factíveis e também de melhor qualidade em relação à função objetivo. Em linhas gerais, a ideia será a de explorar a árvore do espaço de busca de maneira a podar o máximo de nós. Para isso, um algoritmo de branch-and-bound precisa manter a seguinte informação:
Melhor solução: o custo da melhor solução observada até então;
Potencial de um nó: para cada nó, precisamos de uma forma de determinar o quão boa a solução obtida a partir dali pode se tornar;
Observe que o potencial de um nó não representa necessariamente que existirá uma solução a partir daquele nó que tem o custo do potencial – apenas significa que não tem como obter melhor solução do que aquilo a partir dali. Outra observação é que a noção do que é melhor ou pior depende de ser um problema de maximização ou minimização: para minimização o potencial é um limite inferior, para maximização o potencial é um limite superior.
Com isso, um algoritmo de branch-and-bound pode podar um nó de um espaço de busca sempre que:
O nó representar uma solução não factível;
O nó representa um ponto onde nenhuma escolha pode ser feita, isto é, a solução candidata está completa;
O potencial de um nó não é melhor do que a melhor solução observada até então.
Para que essa estratégia tenha vantagens em relação ao bactracking, precisamos então sempre manter os nós ativos da árvore de busca a todo momento para então sempre escolher expandir o nó de melhor potencial (best first). Nós ativos são aqueles nós folha que ainda não foram podados.
BRANCH-AND-BOUND(b)1.seja S∗←NIL uma soluc¸a˜o oˊtima inicialmente nula2.seja N←{∅} o conjunto de noˊs ativos (soluc¸o˜es parciais)3.enquanto N=∅4.seja S∈N a soluc¸a˜o com o melhor potencial b(S)5.para cada item viaˊvel i a partir de S6.S′←S∪{i}⟨⟨novo noˊ⟩⟩7.se S′ na˜o puder ser expandida (soluc¸a˜o completa)8.se S∗=NIL ou b(S′) for melhor do que b(S∗)9.S∗←S′10.remova de N todo noˊS′′tal que b(S′′)eˊ pior do que b(S*)11.sena˜o11.N←N∪{S′}13.return S∗
Limite superior para o custo de soluções parciais: o potencial máximo de ganho a partir da escolha de alguns itens. Considerando v′ e w′ como sendo o que se tem de custo e benefício em um dado momento: ub=v′+(W−w′)(vi+1/wi+1), isto é, o benefício que já temos mais o máximo de custo benefício para cada unidade de peso restante da mochila.
MOCHILA-BRANCH-AND-BOUND(S,v′,w′,i)⟨⟨ assumir w,v,W como entradas do problema⟩⟩1.se soluc¸a˜o atual eˊ inviaˊvel, retorne a soluc¸a˜o indicando pior potencial possıˊvel 2.se todos os itens foram considerados, retorne a soluc¸a˜o 3.gere duas soluc¸o˜es parciais: (1) adiciona item iaˋ soluc¸a˜o; (2) na˜o adiciona iaˋ soluc¸a˜o 4.determine os custos e benefıˊcios parciais (v′/w′) e os limites superiores (ub) de cada soluc¸a˜o gerada5.seja (A) o noˊ (soluc¸a˜o gerada) com maior potencial6.seja (B) o noˊ (soluc¸a˜o gerada) com menor potencial7.chame recursivo MOCHILA-BRANCH-AND-BOUND com o noˊ (A)8.se o limite superior de (B) for ≤ aˋ soluc¸a˜o de (A)9.retorne soluc¸a˜o de (A) como melhor10.sena˜o11.chame recursivo MOCHILA-BRANCH-AND-BOUND com o noˊ (B)11.retorne melhor entre as soluc¸o˜es de (A) e (B)
O problema da alocação recebe como entrada um conjunto de trabalhadores w1,w2,⋅⋅⋅,wn, um conjunto de tarefas t1,t2,⋅⋅⋅,tn e um custo cij para cada alocação wi→tj . Uma tarefa só pode ser atribuída a um único trabalhador e vice versa. O objetivo é encontrar o conjunto de n alocações que minimize a soma dos custos. Vamos representar uma instância do problema como uma matriz n×n onde linhas representam os trabalhadores e colunas representam as tarefas. Por exemplo: