rconstraintslpsolve

LpSolve R conditional constraint


I am trying to answer the following ILP where the objective is to maximize the type of patients operated, while only 2 different types can be operated at most.

max 310x1 + 400x2 + 500x3 + 500x4 + 650x5 + 800x6 + 850x7
subject to
1.8x1 + 2.8x2 + 3.0x3 + 3.6x4 + 3.8x5 + 4.6x6 + 5.0x7 <= 25
250x1 + 300x2 + 500x3 + 400x4 + 550x5 + 800x6 + 750x7 >= 4000 
xj <= dj
d1 + d2 + d3 + d4 + d5 + d6 + d7 <= 2
xj >= 0 and integer

to write this in R package lpSolve I have the following code:

# Set coefficients of the objective function
f.obj <- c(310, 400, 500, 500, 650, 800, 850, 0, 0, 0, 0, 0, 0, 0)

# Set matrix corresponding to coefficients of constraints by rows
f.con <- matrix(c(1.8, 2.8, 3, 3.6, 3.8, 4.6, 5, 0, 0, 0, 0, 0, 0, 0,
                  250, 300, 500, 400, 550, 800, 750, 0, 0, 0, 0, 0, 0, 0,
                  0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
                  1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0,
                  0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0,
                  0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0,
                  0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0,
                  0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0,
                  0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0,
                  0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1), nrow = 10, byrow = TRUE)

# Set unequality/equality signs
f.dir <- c("<=",
           "<=",
           "<=",
           "<=",
           "<=",
           "<=",
           "<=",
           "<=",
           "<=",
           "<=")

# Set right hand side coefficients
f.rhs <- c(25, 4000, 2,0, 0, 0, 0, 0, 0,0)

# Final value (z)
lp("max", f.obj, f.con, f.dir, f.rhs, int.vec = 1:7, binary.vec = 8:14)

# Variables final values
lp("max", f.obj, f.con, f.dir, f.rhs, int.vec = 1:7, binary.vec = 8:14)$solution

However, the x will not go above 1 now because d is binary.

Does anyone know how I can properly write these constraints?


Solution

  • You have 7 different patient types, x1 to x7, x's are integers. You can select at most 2 x's to be nonzero. You can do this by adding binary variables b1 to b7 for each x, and two constraints for each x.

    x >= -U + U*b
    x <= U*b
    

    where U is some upper bound for the max x value.

    library(lpSolve)
    
    # Set coefficients of the objective function
    f.obj <- c(310, 400, 500, 500, 650, 800, 850, 0, 0, 0, 0, 0, 0, 0, 0)
    
    U=999
    
    # Set matrix corresponding to coefficients of constraints by rows
    f.con <- matrix(c(1.8, 2.8, 3, 3.6, 3.8, 4.6, 5, 0, 0, 0, 0, 0, 0, 0, 0,
                      250, 300, 500, 400, 550, 800, 750, 0, 0, 0, 0, 0, 0, 0, 0,
                      0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0,
                      1, 0, 0, 0, 0, 0, 0, -U, 0, 0, 0, 0, 0, 0, U,
                      1, 0, 0, 0, 0, 0, 0, -U, 0, 0, 0, 0, 0, 0, 0,
                      0, 1, 0, 0, 0, 0, 0, 0, -U, 0, 0, 0, 0, 0, U,
                      0, 1, 0, 0, 0, 0, 0, 0, -U, 0, 0, 0, 0, 0, 0,
                      0, 0, 1, 0, 0, 0, 0, 0, 0, -U, 0, 0, 0, 0, U,
                      0, 0, 1, 0, 0, 0, 0, 0, 0, -U, 0, 0, 0, 0, 0,
                      0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -U, 0, 0, 0, U,
                      0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -U, 0, 0, 0, 0,
                      0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -U, 0, 0, U,
                      0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -U, 0, 0, 0,
                      0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -U, 0, U,
                      0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -U, 0, 0,
                      0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -U, U,
                      0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -U, 0), nrow = 17, byrow = TRUE)
    
    # Set unequality/equality signs
    f.dir <- c("<=","<=","<=",rep(c(">=","<="),7))
    
    # Set right hand side coefficients
    f.rhs <- c(25, 4000, 2, rep(0,14))
    
    # Final value (z)
    res=lp("max", f.obj, f.con, f.dir, f.rhs, int.vec = 1:7, binary.vec = 8:14)
    

    The results

    > res$objval
    [1] 4260
    
    > res$solution
     [1] 11.000000  0.000000  0.000000  0.000000  0.000000  0.000000  1.000000  1.000000  0.000000  0.000000
    [11]  0.000000  0.000000  0.000000  1.000000  0.998999
    

    so the first and seventh patient types were selected, 11 of x1, 1 of x7. We can check the constraints

    > sum(c(1.8, 2.8, 3, 3.6, 3.8, 4.6, 5)*c(11,0,0,0,0,0,1))
    [1] 24.8
    > sum(c(250, 300, 500, 400, 550, 800, 750)*c(11,0,0,0,0,0,1))
    [1] 3500