General frame algorithm for solving discrete problems.
We have seen in case of the festivals example, that brute force approach is a probably very slow, but valid approach to find an optimal solution when the search space is discrete and finite. Some acceleration ideas have also been mentioned, some of which may could be applied in a more general manner. Let's focus on enumerating only the feasible solutions now.
Enumerating all of the solutions was simple for the festivals, travesing through all of the subsets of a set is a simple task to do. We would only need to count from 0 to \(2^n-1\) and interpret the numbers binary representation as a subset indicator. Many of those subsets are, however, infeasible, and things get a little bit more difficult, if we want to generate the feasible solutions only. Try to figure out an approach to do so by yourself, or just click the button below. Show solution
There are many ways to do this, but a simple approach would be to follow these steps:
We wither go to F1 or not.
A tree-style enumeration of the feasible solutions can be observed in the above approach:
Another way to look at the same tree is:
The approach described above can be generalized to any problems with discrete decisions:
In practice, the sets assigned to nodes are usually not generated and partitioned explicitely. Instead, the outcomes of the former decisions are kept, and at each node it is somehow checked, whether:
If we already have the above branching algorithm, it can easily be extended with a minimum search on the leafs.
Let us consider a simple shortest path problem: I am currently living in Győr, and my parents live in Nagykanizsa. Let us assume, that I want to drive home the shortest way possible, only using main roads (roads with 1 and 2 digit numbers), but no highways to avoid additional fees.
A simple way to split all of the feasible routes to subsets is to make a decision on the first part of my track, which can be either:
A children node is created for all of these 6 options, and for example, the fourth node represents all of the solutions that start with
This can be repeated for all of the nodes, until we reach Nagykanizsa. If the "partial route" of a node ends at Nagykanizsa, it must be a leaf node, as that route is the only feasible solution with no circle that has that beginning. The length of the route can be evaluated and used in the minimum search.
This approach, however, is not very efficient. Assume, that we have already found the following leaf node: "Győr - Veszprém - Csopak - Balatonederics - Keszthely - Fenékpuszta - Balatonszentgyörgy - Nagykanizsa" with 217 km. When we find this solution, there may be other uninvestigated nodes with partial routes, for example: "Győr - Komárom - Budapest - Szolnok". If we were to blindly follow the instructions above, we would create two children nodes (branch this solution set into two) for following the direction towards either Jászberény or Törökszentmiklós.
We can, however, observe, that the route until Szolnok is already 227 km long, that is longer than a feasible solution we have found so far. Thus, there is no meaning in finding solutions in this subtree (in the set assigned to this node), as they will definitely be worse than a solution formerly found, hence not optimal. So, we can prune this node (solution subset) from the search, and look for another one.
What we did essentially is to give a lower bound on all of the solutions in that subtree (in the set assigned to the node), and if it was worse than the best solution found so far, the subtree (solution subset) was pruned. This idea can be generalized to any problem class, if there is a way to provide a lower bound on a subset of solutions. A general, pseudo-code like structure of the Branch-and-Bound frame algorithm looks like this:
Note, that this is a frame algorithm, that can be used for a lot of problem classes, where the details have to be specified, e.g.:
For example, we used the length of the "already traveled path" as the lower bound, and made branches based on the next segment in the path.
The "tightness" of a bounding function can be the most important contributor to the efficiency of an algorithm. If the bound is not tight, i.e., the bound is far from the actual value of the best solution in \(P\), then pruning will only happen deeper in the tree, and a subtree is investigated unnecessarily. To understand this, let's go back to our pruned path, "Győr - Komárom - Budapest - Szolnok". The parent of this node was "Győr - Komárom - Budapest", and it has 7 siblings. The bound of the parent is 126 km, which is way below of the 217 km long solution we have found earlier, so all 8 children nodes are generated. If we look at the map, we can see intuitievely, that this is really a wrong direction to go, as Budapest is east from Gyor, while Nagykanizsa is to the south-west. What this means, that just by looking at the map, we know, that none of the solutions in this subtree (in the set assigned to "Győr - Komárom - Budapest") will be better than the one we have already found. Still we need to generate the children, and in some cases the grandchildren to prove it, as our bound is not tight enough.
Our previous bound did not include anything about the distance, that is still to be traveled from the end of the current path. However, it is not difficult to provide a lower bound for that either. Simply we should add the geographical distance between the end of the current path and Nagykanizsa. For the "Győr - Komárom - Budapest" node, this Budapest-Nagykanizsa distance is 190 km. Adding the two together: 126 + 190 = 316 km, which is still a valid lower bound, as any "ending" of that path will be longer than 190 km. 316 km is way over 227, so with this tigther bound we can prune the "Győr - Komárom - Budapest" node, and we will not have to spend time generating and evaluating its children, grandchildren.
It seems, that we always have to strive towards tighter and tighter bounds to keep the B&B tree as small as possible. Tighter bounds, however, often require more complex calculations. A slightly tigther bound may not prune enough nodes to make up for the additional time spent on calculating that complex bound at each node. Selecting the best performing bound is not a trivial task, and is often done on a statistical basis.