Search code examples
rlinear-programminglpsolve

How should i set up linear model in R using lpSolve() library


How should i set up the linear model using lpSolve library in R? I have the following code but realized I dont know how to add the constraint

enter image description here

library(lpSolveAPI)
library(lpSolve)

### create a new lpSolve linear program model object

(lps.model <- make.lp(nrow=4, ncol=4))

# set decision variable as real
set.type(lps.model, columns = 1, type="real")
set.type(lps.model, columns = 2, type="real")
set.type(lps.model, columns = 3, type="real")
set.type(lps.model, columns = 4, type="real")
#see what typoes are defined for each variables
get.type(lps.model)

#give model a name
name.lp(lps.model, name="The ACC Basketball")

# set columns value
set.column(lps.model, 1, c(210,100,175,80))
set.column(lps.model, 2, c(90,70,105,65))
set.column(lps.model, 3, c(180,130,140,105))
set.column(lps.model, 4, c(160,200,170,120))

# set objective function
lp.control(lps.model, sense="min")
set.objfn(lps.model, obj=c(1,1,1,1))

#set constraints
add.constraint(lps.model, c(1,1,1,1), "<=", 1)

# set columns names
ColNames <- c("Raleigh", "Atlanta", "Durham", "Clemson")
RowNames <- c("A", "B", "C", "D")

# view models
lps.model

I am stuck on how should i define my constraint so that it become binary where the objective is find the minimun mileage travel, but each team must perform a game at each location.


Solution

  • This is a typical assignment problem. The lpSolve documentation describes how a specific model for assignment problems is already implemented:

    This is a particular integer programming problem. All the decision variables are assumed to be integers; each row has the constraint that its entries must add up to 1 (so that there is one 1 and the remaining entries are 0) and each column has the same constraint. This is assumed to be a minimization problem."

    Observe that that is exactly the model you have. How you can use it:

    > library(lpSolve)
    
    > # Matrix of costs: the ij-th element is the cost of 
    > # assigning source i to destination j.
    > cost.mat <- matrix(c(
    +   210, 90, 180, 160, 
    +   100, 70, 130, 200, 
    +   175, 105, 140, 170, 
    +   80, 65, 105, 120
    + ), nrow=4, byrow=TRUE)
    
    > # Character vector, length 1, containing either 
    > # "min" (the default) or "max"
    > direction = "min"
    
    > # IP model:
    > result <- lp.assign(cost.mat, direction)
    
    > result
    Success: the objective function is 450 
    
    > result$solution
         [,1] [,2] [,3] [,4]
    [1,]    0    0    0    1
    [2,]    0    1    0    0
    [3,]    0    0    1    0
    [4,]    1    0    0    0
    

    Edit: a more general approach in which you'd just use the lp method and model the constraints manually can also be achieved. If you think of the simplex tableau and realize that every decision variable has its own column, then you can model that:

    > library(lpSolve)
    
    > # Numeric vector of coefficients of objective function
    > objective.in <- c(
    +   210, 90, 180, 160, 
    +   100, 70, 130, 200, 
    +   175, 105, 140, 170, 
    +   80, 65, 105, 120
    + )
    
    > # Character vector, length 1, containing either 
    > # "min" (the default) or "max"
    > direction = "min"
    
    # This is the representation of the constraints, where the sum of columns (1,0,0,0,... sequence) is one set of constraints and the sum of the rows (1,1,1,1,...) is the other set of constraints.
    > const.mat <- matrix(c(
    +   1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,
    +   0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,
    +   0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,
    +   0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
    +   1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,
    +   0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,
    +   0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,
    +   0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1
    + ), nrow=8, byrow = TRUE)
    
    > const.mat
         [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16]
    [1,]    1    0    0    0    1    0    0    0    1     0     0     0     1     0     0     0
    [2,]    0    1    0    0    0    1    0    0    0     1     0     0     0     1     0     0
    [3,]    0    0    1    0    0    0    1    0    0     0     1     0     0     0     1     0
    [4,]    0    0    0    1    0    0    0    1    0     0     0     1     0     0     0     1
    [5,]    1    1    1    1    0    0    0    0    0     0     0     0     0     0     0     0
    [6,]    0    0    0    0    1    1    1    1    0     0     0     0     0     0     0     0
    [7,]    0    0    0    0    0    0    0    0    1     1     1     1     0     0     0     0
    [8,]    0    0    0    0    0    0    0    0    0     0     0     0     1     1     1     1
    
    > # Vector of character strings giving the direction 
    > # of the constraint: each value should be one of 
    > # "<," "<=," "=," "==," ">," or ">=".
    > # (In each pair the two values are identical.)
    > const.dir <- c(
    +   "=",
    +   "=",
    +   "=",
    +   "=",
    +   "=",
    +   "=",
    +   "=",
    +   "="
    + )
    
    > # Vector of numeric values for the right-hand sides of the constraints.
    > const.rhs <- c(1,1,1,1,1,1,1,1)
    
    # This is the vector of binary variables. Obviously all decision variables, and since one decision variable corresponds to one coefficient in the objective function, it is just the length of the coefficient vector.
    > # Numeric vector giving the indices of variables 
    > # that are required to be binary.
    > binary.vec <- seq(1, length(objective.in))
    
    > result <-
    +   lp(direction,
    +      objective.in,
    +      const.mat,
    +      const.dir,
    +      const.rhs,
    +      binary.vec = binary.vec)
    
    
    # The results are the same, as expected.
    > result
    Success: the objective function is 450 
    
    > result$solution
     [1] 0 0 0 1 0 1 0 0 0 0 1 0 1 0 0 0