Integer partition is a classic problem in enumeration. It often appears in an introduction to recursion/dynamic programming. For example, the coin exchange problem, where we are given a target sum , and a set of denominations, one can ask (1) is it possible to get the sum using the set of denominations; (2) how many ways are there to get the sum; (3) the smallest number of bills one need to get the sum; (4) enumerate all the ways to get the sum etc.
Here is another interesting application of integer partition (from “Understanding and using linear programming“): column generation. It is a preprocess step for linear programming problems. Consider the problem of cutting paper rolls. Suppose we have a list of orders of rolls with various width and number , where each order is specified by a pair , which means rolls of width (cm). We are going to cut these rolls from several large rolls of width . Clearly, it can happen that some material might be wasted: for example, suppose the large roll has width . We can cut a roll of width 6 and a a roll of width 3, then the remaining roll of width 1 is wasted. One natural optimization problem here is to minimize the total number of large rolls we use to fulfill the orders. This problem can be solved by linear programming (approximately). Integer partition is used to form the linear programming problem.
To formulate the linear program, we enumerate all possible ways to cut the large roll of width into rolls of various widths from . For example, , , etc. each cut must obey the natural constraint, which means that their sum of widths cannot exceed the overall width , and at the same time they should be maximal in the sense that the remaining, for example, is smaller than the minimum . For each a feasible cut plan of the large roll, we introduce a variable , which denotes that number of large rolls that will be cut according to this specification. So the optimization problem is , where the summation is overall possible cut plans .
The following example is from the book: suppose the large roll has width m, the list of orders are:
- 97 rolls of width 135cm
- 610 rolls of width 108cm
- 395 rolls of width 93cm
- 211 rolls of width 42cm
The possible cut plans are:
There are totally 12 possible cut plans, so the linear program will have 12 variables, each denotes the number of large rolls that will be cut according to plan Pi. Naturally, the constraint would be formed according the number of each type of rolls required in the order.
The code to compute all possible cutting plans:
integerpartition :: [Int] -> Int -> [[Int]]
integerpartition _ 0 = [[]]
integerpartition [] _ = []
integerpartition [w] x = [replicate (x `div` w) w]
integerpartition weights@(maxelem:remain) x
| maxelem > x = integerpartition remain x
| otherwise = [maxelem:c | c <- integerpartition weights (x - maxelem)] ++ integerpartition remain x
Naturally, we should also have the constraint that each should be integer. Once we get an optimal solution by solving the linear program, one possible solution is to round up each to an integer.