ECS 110: Data Structures and Programming
Discussion Section Notes -- Week 9
Ted Krovetz (tdkrovetz@ucdavis.edu)

BRANCH & BOUND
==============

This week we will examine branch and bound techniques to reduce the state
space tree of an exhaustive search.


1. BRANCH AND BOUND
-------------------

1.1 Motivation

There exist many real-life, practical problems for which no efficient
algorithm is known, but whose intrinsic difficulty no one has yet managed
to prove. Many of these problems reduce to "try every possible
configuration and select the result which best fits the problem." The
travelling salesperson problem is an example of this type. Essentially, to
solve the TSP, one must try all possible orderings of the cities to visit
and keep track of the one which costs the least. Unfortunately, a small
sample of cities (15) can quickly yield a number of possible solutions
which is very large (15! = 1.3e12).


1.3 Search Tree

Using either breadth-first or depth-first search, all the possible paths
of a graph can be represented as a tree. Each leaf of the tree represents
a completed path, while each node represents a partial tour, which has
associated with it a fixed cost to get from the start node, and a sub-tree
of possible completions to the path. (demonstration given in class).

1.4 Pruning the Sample Space

One solution to the size of the search tree is not to search the entire
sample space. For example, you could follow a greedy strategy, picking the
possible edges with least cost until a TSP tour has been selected. This is
a very fast approach which generally yields a good solution. Good, but not
optimal. To get an optimal solution you must consider all possible
permutations. With the proper heuristics, you can usually prune the search
space to a much more manageable size. For instance, using the quick greedy
strategy, we can establish a bound on our solution. While considering
other possible tours, any tour which would produce a cost greater that
that of the quick greedy method can be thrown out.

As an example consider the following distance matrix

 0  3  8 10  1
 3  0  3  1  2
 8  3  0  2  4
10  1  2  0  3
 1  2  4  3  0

Using the greedy strategy on the graph gives a quick bound of 14
(demonstrated in section). With this information, we can nip many paths
before wasting time exploring them (demonstrated in section). For
instance, any path beginning with (1,4,5) will be greater than 13 and
therefore no better than our previously found bound. No need to continue
on that search path.

If we are smart about the way we generate a search tree for the possible
solutions, and we keep information about the best solution found so far,
and we make clever guesses about how much further we need to go to
complete our tour, then at each node there will be a lot of information to
help judge whether the current path is likely to be optimal. In fact, all
branch-and-bound really is applying some heuristic to possible paths to
determine whether continuing on that path is prudent. The heuristic is
entirely up to the programmer. Some heuristics could be quite accurate but
rather expensive, while others could be quick and dirty. Which solves a
problem faster can only be discovered through experimentation.


1.5 An algorithm

Given a function, c, which maps a partial solution to an estimate of the
best total cost to complete the solution; and given that c is less than or
equal to the actual total cost, at each level of our search we can rank
the promise of following a particular edge. Also, if we keep track of the
best solution found, we never need to consider partial solutions whose
estimated cost is greater than the best found. So, some pseudo-code.

int U = INFINITY; // (Upperbound) Haven't found any solutions yet
priority_queue pq;

E = initial state;
while (1) {
  for each child X of E {
    if c(X) < U then
      pq.enqueue(X, c(X));
      if (X = leaf)
        U = min(U,cost(X))
  }
  do {
    if (pq.empty()) {
      cout << "Answer = U"
      exit();
    }
    E = pq.delete();  // Kill all nodes >= U
  } while (E >= U)
}

A branch-and-bound solution can be applied to any problem that can be
represented using a search tree and a cost function which can estimate the
cost of a partial solution. Other examples include n-queens, knapsack,
15-puzzle. Time permitting, we will discuss some other problems.


1.6 TSP Branch and Bound Example

[The following is extracted from "Algorithmics: Theory and Practice, G.
Brassard and P. Bratley, Prentice-Hall, 1988"]

Like backtracking, branch-and-bound is a technique for exploring an
implicit directed graph. Again, this graph is usually acyclic or even a
tree. This time, we are looking for the optimal solution to some problem.
At each node we calculate a bound on the possible values of any solutions
that might happen to be farther on in the graph. If the bound shows that
any such solutions must necessarily be worst than the best solution found
so far, then we do not need to go on exploring this part of the graph.

In the simplest version, calculation of these bounds is combined with a
breadth-first of depth-first search, and serves only, as we have just
explained, to prune certain branches of a tree or to close certain paths
in a graph. More often, however, the calculated bound is used not only to
close off certain paths, but also to choose which of the open paths looks
the most promising, so that it can be explored first.

In general terms we may say that a depth-first search finishes exploring
nodes in the inverse order of their creation, using a stack to hold those
nodes that have been generated but not yet explored fully; a breadth-first
search finishes exploring nodes in the order of their creation, using this
time a queue to hold those that have been generated but not yet explored.
Branch-and-bound uses auxiliary computations to decide at each instant
which node should be explored next, and a priority list to hold those
nodes that have been generated but not yet explored.

We return to the travelling salesperson problem.

Let G be the complete graph on five points with the following distance matrix:

 0 14  4 10 20
14  0  7  8  7
 4  5  0  7 16
11  7  9  0  2
18  7 17  4  0

We are looking for the shortest tour starting from node 1 that passes
exactly once through each other node before returning to node 1.

The nodes in the implicit graph correspond to partially specified paths.
For instance, node (1,4,3) corresponds to two complete tours:
(1,4,3,2,5,1) and (1,4,3,5,2,1). The successors of a given node correspond
to paths in which one additional node has been specified. At each node we
calculate a lower bound on the length of the corresponding complete tours.

To calculate this bound, suppose that half the distance between two points
i and j is counted at the moment we leave i, and the the other half when
we arrive at j. For instance, leaving node 1 costs us at least 2, namely
the lowest of the values 14/2, 4/2, 10/2, and 20/2. Similarly, visiting
node 2 costs us at least 5 (at least 4/2 when we arrive and at least 7/2
when we leave). Returning to node 1 costs at least 2, the minimum of 14/2,
4/2, 11/2 and 18/2. To obtain a bound on the length of a path, it suffices
to add elements of this kind. For instance, a complete tour must include a
departure from node 1, a visit to each of the nodes 2,3,4, and 5 (not
necessarily in this order) and a return to 1. Its length is therefore at
least
  2 + 6 + 4 + 3 + 3 + 2 = 20

Notice that this calculation does not imply the existence of a solution
that costs only 20.

In Figure 6.6.5 (a tree to be drawn in section) the root of the tree
specifies that the starting point for our tour is node 1. Obviously, this
arbitrary choice of a starting point does not alter the length of the
shortest tour. We have just calculated the lower bound shown for this
node. (This bound on the root of the implicit tree serves no purpose in
the algorithm; it was computed here for the sake of illustration.) Our
search begins by generating (as though for a breadth-first search) the
four possible successors of the root, namely, nodes (1,2), (1,3), (1,4)
and (1,5). The bound for node (1,2), for example, is calculated as
follows. A tour that begins with (1,2) must include

- The trip 1-2: 14 (formally , leaving 1 for 2 and arriving at 2 from 1: 7 + 7)
- A departure from 2 toward 3,4, or 5: minimum 7/2
- A visit to 3 that neither comes from 1 nor leaves for 2: minimum 11/2
- A similar visit to 4: minimum 3
- A similar visit to 5: minimum 3
- A return to 1 from 3,4, or 5: minimum 2.

The length of such a tour is therefore at least 31. The other bounds are
calculated similarly.

Next, the most promising node seems to be (1,3), whose bound is 24. The
three children (1,3,2), (1,3,4), and (1,3,5) of this node are therefore
generated. To give just one example, we calculate the bound for node
(1,3,2) as follows:

- The trip 1-3-2: 9
- A departure from 2 toward 4 or 5: minimum 7/2
- A visit to 4 that comes from neither 1 nor 3
  and that leaves for neither 2 nor 3: minimum 3
- A similar visit to 5: minimum 3
- A return to 1 from 4 or 5: minimum 11/2,

which gives a total length of at least 24.

The most promising node is now (1,3,2). Its two children (1,3,2,4) and
(1,3,2,5) are generated. This time, as node (1,3,2,4), for instance,
corresponds to exactly one complete tour (1,3,2,4,5,1), we do not need to
calculate a lower bound since we can calculate immediately its length 37.

We find that the length of the tour (1,3,2,5,4,1) is 31. If we are only
concerned to find one optimal solution, we do not need to continue
exploration of the nodes (1,2), (1,5), and (1,3,5), which cannot possibly
lead to a better solution. Even the node (1,3,4) is pointless. (Why?)
There remains only node (1,4) to explore. The only child to offer
interesting possibilities is (1,4,5). After looing at the two complete
tours (1,4,5,2,3,1) and (1,4,5,3,2,1), we find that the tour (1,4,5,2,3,1)
of length 30 is optimal. This example demonstrates that although at one
point (1,3) was the most promising node, the optimal solution does not
come from there.

To obtain our answer, we have looked at merely 15 of the 41 nodes that are
present in a complete (state space) tree.

The need to keep a list of nodes that have been generated but not yet
completely explored, situated at all levels of the tree and preferably
sorted in order of the corresponding bounds, makes branch-and-bound quite
hard to program. The heap is an ideal data structure for holding this
list. Unlike depth-first search and its related techniques, no elegant
recursive formulation of branch-an-bound is available to the programmer.
Nevertheless, the technique is sufficiently powerful that it is often used
in practical applications.

It is next to impossible to give any idea how well the technique will
perform on a given problem using a given bound. There is always a
compromise to be made concerning the quality of the bound to be
calculated: with a better bound we look at less nodes, but on the other
hand, we shall most likely spend more time at each one calculating the
corresponding bound. In the worst case it may turn out that even an
excellent bound does not allow us to cut any branches off the tree, and
all the extra work we have done is wasted.
