[R] Binary optimization problem in R

Hans W Borchers hwborchers at googlemail.com
Wed Sep 21 15:12:48 CEST 2011


Michael Haenlein <haenlein <at> escpeurope.eu> writes:

> Dear all,
> 
> I would like to solve a problem similar to a multiple knapsack problem and
> am looking for a function in R that can help me.
> 
> Specifically, my situation is as follows: I have a list of n items which I
> would like to allocate to m groups with fixed size. Each item has a certain
> profit value and this profit depends on the type of group the item is in.
> My problem is to allocate the items into groups so the overall profit is
> maximized while respecting the fixed size of each group.
> 
> Take the following example with 20 items (n=5) and 5 groups (m=5):
> 
> set.seed(1)
> profits <- matrix(runif(100), nrow=20)
> size<-c(2,3,4,5,6)
> 
> The matrix "profits" describes the profit of each item when it is allocated
> to a certain group. For example, when item 1 is allocated to group 1 it
> generates a profit of 0.26550866. However, when item 1 is allocated to group
> 2 it generates a profit of 0.93470523. The matrix "size" describes the size
> of each group. So group 1 can contain 2 items, group 2 3 items, group 4 4
> items, etc.
> 
> I think this is probably something that could be done with constrOptim() but
> I'm not exactly sure how.

The task you describe is an integer optimization problem and can most likely
not be solved with a numeric optimization routine like constrOptim().

In the example above, the solution I get is a maximal profit of 16.31194
with these allocations:
    group 1:   4, 18
          2:   1,  9, 15
          3:   3,  6, 11, 12
          4:   8, 10, 16, 17, 20
          5:   2,  5,  7, 13, 14, 19

(mis)using the mixed-integer package 'lpSolve' in the following way
(with 100 binary variables):

    library("lpSolve")

    obj <- -c(profits)                  # we will look for a minimum
    dir <- rep("==", 25)                # discrete equality constraints
    rhs <- c(c(2,3,4,5,6), rep(1, 20))

    # Assign 2, 3, 4, 5, 6 items to groups 1--5 resp.
    mat <- matrix(0, 25, 100); mat[1,  1: 20] <- 1; mat[2, 21: 40] <- 1
    mat[3, 41: 60] <- 1;       mat[4, 61: 80] <- 1; mat[5, 81:100] <- 1
    # Assign each item to only one group
    for (i in 1:20) {
        mat[i+5, c(i, i+20, i+40, i+60, i+80)] <- 1
    }

    sol <- lp("min", obj, mat, dir, rhs, all.bin=TRUE)

    # RESULT
    -sol$objval                 # 16.31194
    # ALLOCATIONS
    which(sol$solution==1) - rep(seq(0, 80, 20), 2:6)
    # 4 18  1  9 15  3  6 11 12  8 10 16 17 20  2  5  7 13 14 19

In case you have thousands of items and many groups, packages like 'lpSolve',
'Rglpk', or 'Rsymphony' will not be able to handle the task and you might be
forced to look for tools outside the R realm.

Hans Werner



More information about the R-help mailing list