forecaster
forecaster

Reputation: 1159

Linear programming in R using lpsolve

I'm trying to solve a linear programming problem in R using lpsolve package.

Here is the problem:

enter image description here

Here is the sample in R for reproducible example:

    library("lpSolve")
a <- matrix(c(1,2,5,
              1/2,1,3,
              1/5,1/3,1),nrow=3,byrow=T)

#
f.obj <- c(1,0,0,0)

f.con <- matrix (c(
  1,1,-a[1,2],0, #Contraint 1 for a12
  1,-1,a[1,2],0, #Contraint 2 for a12
  1,1,0,-a[1,3], #Contraint 1 for a13
  1,-1,0,a[1,3], #Contraint 2 for a13
  1,0,1,-a[2,3], #Contraint 1 for a23
  1,0,-1,a[2,3], #Contraint 2 for a23
  0,1,1,1, #Contraint 3
  0,1,0,0, #Constraint 4
  0,0,1,0, #Constraint 4
  0,0,0,1 #Constraint 4

  ), nrow=10, byrow=TRUE)

f.dir <- c(rep("<=",6), "=",rep(">",3))

f.rhs <- c(rep(1,6),1,rep(0,3))

g <- lp ("max", f.obj, f.con, f.dir, f.rhs)
g$solution

I'm able to solve this manually for a small problem, what if I had a 7 X 7 or a n x n matrix a. How would I specify the constraint 1 and 2, especially I'm struggling to define the constraint as it relates to a[i,j]?

a = matrix( 
  c(1,4,9,6,6,5,5,
    1/4,1,7,5,5,3,4,
    1/9,1/7,1,1/5,1/5,1/7,1/5,
    1/6,1/5,5,1,1,1/3,1/3,
    1/6,1/5,5,1,1,1/3,1/3,
    1/5,1/3,7,3,3,1,2,
    1/5,1/4,5,3,3,1/2,1
  ),nrow = 7,byrow =T)

the solution to the above matrix is 0.986 0.501 0.160 0.043 0.060 0.060 0.1 0.075 Any help would be greatly appreciated.

Upvotes: 3

Views: 1336

Answers (2)

G. Grothendieck
G. Grothendieck

Reputation: 269586

Have updated to incorporate revised constraint 4 and have made some minor code improvements.

Assuming the constraint matrix in the question is correct, this uses combn to iterate over all i < j setting the appropriate elements. Note that x[1] is the value of i and x[2] is the value of j in f. make_cons returns the constraint matrix in the same order as shown in the question but the rbind line in make_cons could be simplified to rbind(cons1, cons2, cons3, cons4) if it were OK to use such order.

make_cons <- function(a) {
   n <- nrow(a)
   f <- function(x) replace(numeric(n), x, c(1, -a[x[1], x[2]]))
   cons1 <- cbind(1, t(combn(1:n, 2, f)))
   cons2 <- cbind(1, -cons1[, -1])
   cons3 <- c(0, rep(1, n))
   cons4 <- cbind(0, diag(n))
   rbind(t(matrix(rbind(t(cons1), t(cons2)), ncol(cons1))), cons3, cons4)
}

# test

# a and f.con from question

a <- matrix(c(1, 0.5, 0.2, 2, 1, 0.333333333333333, 5, 3, 1), 3)
f.con <- matrix(c(1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, -1, 1, -1, 0, 0, 
  1, 1, 0, 0, -2, 2, 0, 0, 1, -1, 1, 0, 1, 0, 0, 0, -5, 5, -3, 
  3, 1, 0, 0, 1), 10)

all.equal(f.con, make_cons(a), check.attributes = FALSE)
## [1] TRUE

Upvotes: 3

Cettt
Cettt

Reputation: 11981

here is one possibility which uses for loops.

As I mentioned in the commenst, I think that you got condition (4) wrong. Here is my suggestion. My idea is to first set up a matrix for constraints (4), then for constraint (3) and then add constraints (2) and (1) in a loop. Note that, in the beginning, I do not consider the column corresponding to \mu. I will add this column in the end.

n<- nrow(a)
f.cons<- diag(n)
f.cons<- rbind(f.cons, rep(1,n))

This sets up a matrix corresponding to constraints (4) (first n rows) and constraint (3). Now I add rows to this matrix, using loops and the command rbind.

for(i in 1:(n-1)){
  for(j in (i+1): n){
   x<- rep(0, n)
   x[i]<- 1  #x corresponds to (1)
   x[j]<- -a[i,j]
   y<- -x #y corresponds to (2)
   f.cons<- rbind(f.cons, rbind(x, y))
}

}

So far, I have ignored the first column, which corresponds to \mu. I add it with these two simple lines:

 f.cons<- cbind(rep(1, nrow(f.cons)), f.cons)
 f.cons[1:(n+1), 1]=0

Note that in my matrix f.cond the first n+1 lines correspond to constraints (3) and (4)!

Upvotes: 1

Related Questions