Using CPLEX in R: Installing cplexAPI in Windows 10

I have a very large mixed integer problem to solve.   COIN‘s solver accessed through Rsymphony did a decent job, but had trouble finding feasible solutions.  I had been told that the IBM cplex  solver was the best on the market for mixed integer programming.

Installing cplex is a relatively easy task.  The difficulties began when I tried to install a link from R.  Either cplexAPI or Rcplex.  You can search and see that there is very little helpful information in the usual places.  I reached out to the developers and Jonathan of cplexAPI responded with very helpful troubleshooting and instructions.

We (honestly, all Jonathan) determined that the following sequence should correctly install cplexAPI.  First, read the directions.

After downloading, unpack the .tar.gz file someplace.  I am going to unpack mine on the desktop.

Open the newly created folder cplexAPI and you will find a directory labeled src.  Open the Makevars.win file within that folder.  I have Notepad++ installed, so I right click Makevars.win and open withNotepad++.  The instructions note that you will need to find each of these directories and type them in.  They may (and probably will if you are using any other version).

PKG_CPPFLAGS=-g -D_R_=1 -DUSE_R=1 -I"C:/Program Files/IBM/ILOG/CPLEX_Studio127/cplex/include"
PKG_LIBS=-L"C:/Program Files/IBM/ILOG/CPLEX_Studio127/cplex/bin/x64_win64" -lm -lcplex1270

After saving you will need to repackage cplexAPI.  Head over to the command line (remember I unpacked my tar.gz file on my desktop) and use the command:

R CMD build --no-build-vignettes --no-manual  --md5     C:\Users\{your name here}\Desktop\cplexAPI

This will repackage the folder, avoiding the md5 error you can find while searching for solutions.  After a successful repackage you can then install the package at the command line.

R CMD INSTALL --build --no-multiarch .\cplexAPI_1.3.3.tar.gz

At this point, you may have errors.  The key you are looking for is this output:

packaged installation of 'cplexAPI' as cplexAPI_1.3.3.zip
DONE (cplexAPI)

Now try it out.  Here is an example from Gabriel Gelius-Dietrich’s cplexAPI – Quick Start.

> library(cplexAPI)

env prob chgProbNameCPLEX(env, prob, "sample")
[1] 0
nc nr obj rhs sense lb ub cn rn beg cnt ind val copyLpwNamesCPLEX(env, prob, nc, nr, CPX_MAX, obj, rhs, sense,
+ beg, cnt, ind, val, lb, ub, NULL, cn, rn)
[1] 0
lpoptCPLEX(env, prob)
[1] 0
solutionCPLEX(env, prob)
$lpstat
[1] 1
$objval
[1] 13
$x
[1] 2 0 1
$pi
[1] 1 0 1
$slack
[1] 0 1 0
$dj
[1] 0 -3 0

I am looking forward to using cplexAPI for a larger problem!

For more R posts visit:http://www.R-bloggers.com

http://www.R-bloggers.com

Subset and Fill via an Index

I had a very large (70,000+ columns) problem that I needed to reduce. A function took two matrices and transformed them into a single vector the length as the two inputs. I needed to reduce the inputs and then map the output back to the original position of the corresponding column. This entry may seem obvious to veteran R users and I am mainly writing this to provide a reference to myself. Here is a visual example of what I needed.

time <- c(1, 1, 2, 2, 3, 3)
money <- c(2, 2, 4, 4, 6, 6)
ownership <- c(1, 0, 1, 0, 1, 0)
mat <- rbind(time, money, ownership)
print(mat)
##           [,1] [,2] [,3] [,4] [,5] [,6]
## time         1    1    2    2    3    3
## money        2    2    4    4    6    6
## ownership    1    0    1    0    1    0
dat <- c(1, 0, 2, 0, 3, 0)  
obj <- matrix(dat,nrow=1)
print(obj)
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    0    2    0    3    0
f <- function(mat,obj){
  #generic function with output of the same number of columns as obj
}
soln <- f(mat, obj)

where soln is a 1×6 matrix.

The size of my problem made the function f extremely slow and unreliable. I needed a way to reduce the inputs and then map the output appropriately to a results matrix.

The matrices mat and obj reduce to:

time <- c(1, 2, 3)
money <- c(2, 4, 6)
ownership <- c(1, 1, 1)
mat <- rbind(time, money, ownership) 
print(mat)
##           [,1] [,2] [,3]
## time         1    2    3
## money        2    4    6
## ownership    1    1    1
dat <- c(1, 2, 3)  
obj <- matrix(dat,nrow=1)
print(obj)
##      [,1] [,2] [,3]
## [1,]    1    2    3
soln <- f(mat, obj)

with the soln being a 1×3 matrix. For example:

soln=               [,1]     [,2]      [,3]     
           [1,] 4.151969 5.759826  5.537563 

where the decision to exclude a column from mat is based on the value in ownership[]=0 and the same for obj. The added difficulty, is that I need to be able to assign the output in soln to the mapped to the corresponding original position in a larger SOLN matrix. In this case columns 1,3,5. Ownership is randomly assigned, so there will be no pattern other than the zeros described above.

time <- c(1, 1, 2, 2, 3, 3)
money <- c(2, 2, 4, 4, 6, 6)
ownership <- c(1, 0, 1, 0, 1, 0)
mat <- rbind(time, money, ownership)
print(mat)
##           [,1] [,2] [,3] [,4] [,5] [,6]
## time         1    1    2    2    3    3
## money        2    2    4    4    6    6
## ownership    1    0    1    0    1    0
dat <- c(1, 0, 2, 0, 3, 0)  
obj <- matrix(dat,nrow=1)
print(obj)
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]    1    0    2    0    3    0
obj2 <- obj[, as.logical(ownership), drop = FALSE]
print(obj2)
##      [,1] [,2] [,3]
## [1,]    1    2    3
mat2 <- mat[, as.logical(ownership)]
print(mat2)
##           [,1] [,2] [,3]
## time         1    2    3
## money        2    4    6
## ownership    1    1    1

evaluates to

soln <- f(mat, obj)

with the soln being a 1×3 matrix. For example:

soln=               [,1]     [,2]      [,3]     
           [1,] 4.151969 5.759826  5.537563 

I need to create a result space:

SOLN <- matrix(data=NA,nrow=1,ncol=6)
print(SOLN)
##      [,1] [,2] [,3] [,4] [,5] [,6]
## [1,]   NA   NA   NA   NA   NA   NA

Then map the results from soln to columns 1, 3, & 5.

SOLN[, as.logical(ownership)] <- soln
print(SOLN)
##          [,1] [,2]     [,3] [,4]     [,5] [,6]
## [1,] 4.151969   NA 5.759826   NA 5.537563   NA

A much more elegant solution than the for loops I was trying to write!

For more R posts visit:http://www.R-bloggers.com