17

I used excel solver to solve an optimization problem, and I am trying to replicate it in R.

I found many packages like optim, ROI etc., but it seems all of them only take a vector as the object to optimize and allow the variables to take any continuous value. In my case, I have a constraint matrix that also needs to be satisfied and my variables can only take binary values.

Here is problem I want to solve:

A-D are machines, 1-3 are tasks and the number in the first matrix is the value generated by using X machine to do Y task. The constraints are: A-D can do and only can do one task (cannot split); each task can be worked and only be worked by one machine.

Here is the code I am using:

par = rep(c(0,1),6)

mat <- matrix(c(9,10,11,4,5,10,1,3,5,7,5,4), nrow = 3)

fr <- function(x) {  
  y= matrix(x,nrow = 4)
  sum(mat %*% y)
}

a = optim(par, fr)

Some questions: How can I optimize maximum, seems this function default optimize minimum? How can I add constraints into it? How can I limit to binary variables?

Yoki
  • 863
  • 4
  • 14
  • 26
  • A matrix is a misshapen vector; reshape it and you're good to go (assuming you understand how to code up optimization of a vector). `xmat = matrix(1:4,ncol=2); x = c(xmat)` – Frank May 13 '15 at 22:06
  • Thanks Frank! I tried that and it worked. But I have some follow up question. I am indeed don't know how to code up optimization for a vector. – Yoki May 13 '15 at 22:13
  • 2
    simply add a "-" minus sign to sum funtion, optim will maximize. – forecaster May 13 '15 at 22:15

1 Answers1

17

You need to construct a vector for the objective function and a constraint matrix, finally solving with one of the R LP solvers:

library(lpSolve)
costs <- matrix(c(9, 10, 11, 4, 5, 10, 1, 3, 5, 7, 5, 4), nrow=3)
nr <- nrow(costs)
nc <- ncol(costs)
columns <- t(sapply(1:nc, function(x) rep(c(0, 1, 0), c(nr*(x-1), nr, nr*(nc-x)))))
rows <- t(sapply(1:nr, function(x) rep(rep(c(0, 1, 0), c(x-1, 1, nr-x)), nc)))
mod <- lp("max", as.vector(costs), rbind(columns, rows), "<=", rep(1, nr+nc), binary.vec=rep(TRUE, nr*nc))

Now you can grab the solution and the objective function:

mod$objval
# [1] 27
matrix(mod$solution, nrow=nr)
#      [,1] [,2] [,3] [,4]
# [1,]    0    0    0    1
# [2,]    1    0    0    0
# [3,]    0    1    0    0

Note that functions like optim are not well suited for this problem both because they don't consider matrices of constraints and also because they cannot limit to binary variable values.

josliber
  • 43,891
  • 12
  • 98
  • 133
  • Hi, can you please explain how this whole thing works? Especially why `columns` and `rows` have to be repetitive. – riders994 Aug 10 '15 at 18:42
  • @riders994 Basically `rbind(columns, rows)` returns the constraint matrix for the linear program, `rep(1, nr+nc)` is the right-hand side, and `as.vector(costs)` is the objective function. I used `rep` and other R functions to construct the constraint matrix for this particular linear programming problem. If you had a different problem you would probably use different code to get that matrix. You can read up on `rep` from its help page: `?rep`. – josliber Aug 10 '15 at 19:42
  • @josliber Would you be able to guide on a similar problem . It will really be helpful. https://stackoverflow.com/q/72238988/8019264 – MysticRenge May 14 '22 at 13:29