R is a language and environment for statistical computing and graphics. It is a GNU project which is similar to the S language and environment which was developed at Bell Laboratories (formerly AT&T, now Lucent Technologies) by John Chambers and colleagues. R can be considered as a different implementation of S. There are some important differences, but much code written for S runs unaltered under R. For more information or to download R please visit the R website.
Installing the package takes a single command:
> install.packages("lpSolve", repos = "http://r-forge.r-project.org")Note that there is also an lpSolve package available on CRAN. The CRAN version of the package is based on lp_solve version 5.5.0.8 and does not include the API.
The > shown before each R command is the R prompt. Only the text after > must be entered.
Documentation is provided for each function in the lpSolve package using R's built-in help system. For example, the command
> ?add.constraintwill display the documentation for the add.constraint function.
The lpSolve package implements two general approaches to solving linear programs.
The first approach is provided by the functions lpSolve, lp, lp.transport and lp.assign. These functions allow a linear program (and transport and assignment problems) to be defined and solved using a single command. For example, the command
> result <- lpSolve(obj, A, b)solves the linear program
min: obj * x subject to: A %*% x <= b x >= 0and stores the results in an R list named result. The individual components of the result (e.g., the optimal value of the objective function, the decision variables, etc.) can be retrieved from this list. This approach is practical for small linear programs and dense linear programs.
Alternatively, the lpSolve package provides an API for building and solving linear programs that mimics the lp_solve C API. This approach allows much greater flexibility but also has a few caveats. The most important is that the lpSolve linear program model objects created by make.lp and read.lp are not actually R objects but external pointers to lp_solve 'lprec' structures. R does not know how to deal with these structures. In particular, R cannot duplicate them. Thus one must never assign an existing lpSolve linear program model object in R code.
Consider the following example. First we create an empty model x.
> x <- make.lp(2, 2)Then we assign x to y.
> y <- xNext we set some columns in x.
> set.column(x, 1, c(1, 2)) > set.column(x, 2, c(3, 4))And finally, take a look at y.
> y Model name: C1 C2 Minimize 0 0 R1 1 3 free 0 R2 2 4 free 0 Type Real Real upbo Inf Inf lowbo 0 0The changes we made in x appear in y as well. Although x and y are two distinct objects in R, they both refer to the same lp_solve 'lprec' structure.
The safest way to use the lpSolve API is inside an R function - do not return the lpSolve linear program model object. See the code for the functions lp and lp.transport for examples.
> lprec <- make.lp(0, 4) > set.objfn(lprec, c(1, 3, 6.24, 0.1)) > add.constraint(lprec, c(0, 78.26, 0, 2.9), ">=", 92.3) > add.constraint(lprec, c(0.24, 0, 11.31, 0), "<=", 14.8) > add.constraint(lprec, c(12.68, 0, 0.08, 0.9), ">=", 4) > set.bounds(lprec, lower = c(28.6, 18), columns = c(1, 4)) > set.bounds(lprec, upper = 48.98, columns = 4) > RowNames <- c("THISROW", "THATROW", "LASTROW") > ColNames <- c("COLONE", "COLTWO", "COLTHREE", "COLFOUR") > dimnames(lprec) <- list(RowNames, ColNames)Lets take a look at what we have done so far.
> lprec # or equivalently print(lprec) Model name: COLONE COLTWO COLTHREE COLFOUR Minimize 1 3 6.24 0.1 THISROW 0 78.26 0 2.9 >= 92.3 THATROW 0.24 0 11.31 0 <= 14.8 LASTROW 12.68 0 0.08 0.9 >= 4 Type Real Real Real Real upbo Inf Inf Inf 48.98 lowbo 28.6 0 0 18Now lets solve the model.
> solve(lprec) [1] 0 > get.objective(lprec) [1] 31.78276 > get.variables(lprec) [1] 28.60000 0.00000 0.00000 31.82759 > get.constraints(lprec) [1] 92.3000 6.8640 391.2928
Note that there are some commands that return an answer. For the accessor functions (generally named get.*) the output should be clear. For other functions (e.g., solve), the interpretation of the returned value is described in the documentation. Since solve is generic in R, use the command
> ?solve.lpExtPtrto view the appropriate documentation. The assignment functions (generally named set.*) also have a return value - often a logical value indicating whether the command was successful - that is returned invisibly. Invisible values can be assigned but are not echoed to the console. For example,
> status <- add.constraint(lprec, c(12.68, 0, 0.08, 0.9), ">=", 4) > status [1] TRUEindicates that the operation was successful. Invisible values can also be used in flow control.