glpsol is the stand-alone solver of the GNU Linear
Programming Kit (GLPK). It reads a model, solves it and writes the
solution to a file. It is the reference implementation of
MathProg (GMPL), the modelling language of GLPK, and it
also reads CPLEX LP and MPS files.
The solver is normally obtained by installing GLPK. This package builds and installs the executable as part of the R package, so that
install.packages("glpsol")is sufficient on Windows and macOS, where the CRAN binary contains
its own copy of GLPK. On Linux the package is installed from source and
requires the GLPK development files (libglpk-dev or
glpk-devel); see the README. In either case the executable
does not need to be on the PATH:
glpsol_path()
#> [1] "C:/Users/admin/AppData/Local/Temp/RtmpsRBS6G/temp_libpath69e84f2b3bc6/glpsol/bin/x64/glpsol.exe"
glpk_version()
#> [1] "5.0"glpk_version() returns the version of the GLPK library
against which the package was built.
glpsol_run() accepts the arguments of the
glpsol command line. The package includes the
transportation example distributed with GLPK:
mod <- system.file("models", "transp.mod", package = "glpsol")
out <- tempfile("glpsol-")
dir.create(out)
sol <- file.path(out, "transp.sol")
res <- glpsol_run(c("-m", mod, "-o", sol), echo = FALSE)
res$status
#> [1] 0status is the exit status of the process: 0
indicates that glpsol ran to completion. It does not
indicate whether the model was feasible; that information is in the
log:
tail(res$log, 4)
#> [1] "OPTIMAL LP SOLUTION FOUND"
#> [2] "Time used: 0.0 secs"
#> [3] "Memory used: 0.1 Mb (126664 bytes)"
#> [4] "Writing basic solution to 'C:\\Users\\admin\\AppData\\Local\\Temp\\RtmpgFe6bw\\glpsol-c31872b05022/transp.sol'..."The solution is written to the file given with -o. Its
Status line states the outcome:
writeLines(head(readLines(sol), 12))
#> Problem: transp
#> Rows: 6
#> Columns: 6
#> Non-zeros: 18
#> Status: OPTIMAL
#> Objective: cost = 153.675 (MINimum)
#>
#> No. Row name St Activity Lower bound Upper bound Marginal
#> ------ ------------ -- ------------- ------------- ------------- -------------
#> 1 cost B 153.675
#> 2 supply[Seattle]
#> NU 350 350 < eps
grep("^Status", readLines(sol), value = TRUE)
#> [1] "Status: OPTIMAL"This printable format is intended for inspection rather than parsing.
To load the solution into R, request the plain-text format with
-w and the problem file with --wglp in the
same run. The first contains the values by index, the second the row and
column names:
txt <- file.path(out, "transp.txt")
glp <- file.path(out, "transp.glp")
glpsol_run(c("-m", mod, "-w", txt, "--wglp", glp), echo = FALSE)
s <- glpsol_read_solution(txt, names = glp)
s
#> <glpsol_solution> basic, optimal
#> problem: transp
#> objective: 153.675
#> rows: 6
#> cols: 6
s$cols[, c("name", "status", "primal", "dual")]
#> name status primal dual
#> 1 x[Seattle,New-York] basic 50 0.000
#> 2 x[Seattle,Chicago] basic 300 0.000
#> 3 x[Seattle,Topeka] lower 0 0.036
#> 4 x[San-Diego,New-York] basic 275 0.000
#> 5 x[San-Diego,Chicago] lower 0 0.009
#> 6 x[San-Diego,Topeka] basic 275 0.000
s$rows[, c("name", "primal", "dual")]
#> name primal dual
#> 1 cost 153.675 0.000
#> 2 supply[Seattle] 350.000 0.000
#> 3 supply[San-Diego] 550.000 0.000
#> 4 demand[New-York] 325.000 0.225
#> 5 demand[Chicago] 300.000 0.153
#> 6 demand[Topeka] 275.000 0.126glpsol_read_solution() reads the three kinds of solution
that glpsol can write (basic, interior-point and integer)
and reports the kind in kind. A model can also produce its
own output with the MathProg printf and table
statements. The most commonly used options are:
| Option | Effect |
|---|---|
-o file |
write the solution in printable format |
-w file |
write the solution in plain-text format |
-y file |
write MathProg printf/display output to a
file |
--wlp file, --wfreemps file
|
write the generated problem in CPLEX LP or free MPS format |
--check |
translate and generate the model without solving it |
--tmlim n |
limit the search to n seconds |
glpsol_run("--help") lists the complete set.
A MathProg model and its data are frequently kept in separate files;
the -d option names the data file. The example above
contains its own data; section, so a single file suffices.
With a separate data file the call is
glpsol_run(c("-m", "model.mod", "-d", "model.dat", "-o", "model.sol"))The same executable reads the two common exchange formats, so a problem written by another tool can be solved in the same way:
glpsol_run(c("--lp", "model.lp", "-o", "model.sol")) # CPLEX LP
glpsol_run(c("--freemps", "model.mps", "-o", "model.sol")) # free MPS
glpsol_run(c("--mps", "model.mps", "-o", "model.sol")) # fixed MPSThe LP method is selected with --simplex (the default)
or --interior. A model with integer variables is solved by
branch-and-cut; --nomip relaxes the integrality constraints
and solves the LP instead.
With echo = TRUE the log is written to the console as it
is produced, which is useful for large models that run for a long
time:
glpsol_run(c("-m", "big.mod"), echo = TRUE)In this mode the output is not captured and log is
empty; use echo = FALSE, as in the examples above, to
retain it.
timeout terminates the process after the given number of
seconds:
res <- glpsol_run(c("-m", mod), echo = FALSE, timeout = 60)
res$timed_out
#> [1] FALSEThis differs from the --tmlim option of GLPK, which
limits the search phase only. timeout applies to the whole
run, including model translation and output, and is available on all
platforms. A run terminated in this way returns
timed_out = TRUE and status = 124 instead of
raising an error.
glpsol_path() is the intended integration point. A
package that generates MathProg can pass the path to
system2() and keep its own calling convention. The
dependency can be made optional as follows:
find_glpsol <- function() {
if (requireNamespace("glpsol", quietly = TRUE)) {
hit <- tryCatch(glpsol::glpsol_path(), error = function(e) NULL)
if (!is.null(hit)) return(hit)
}
Sys.which("glpsol") # fall back to an installed copy
}This is the lookup used by multimod and energyRt: the bundled
executable is consulted after any explicitly configured path and before
copies found on the PATH, because its version is known.
glpkAPI, the
R binding to the GLPK C API, was archived from CRAN in March 2026. This
package fills the resulting gap at the command-line level:
install.packages() provides the solver,
glpsol_run() executes it in a separate process, and
glpsol_read_solution() reads the result. It does not
provide an interface to the C API.
Two alternatives remain for that purpose. Rglpk is on CRAN and
solves a matrix-level LP in-process with Rglpk_solve_LP();
it reads a single MathProg file but not separate data files. glpkAPI
itself can still be installed from the CRAN
archive against a system GLPK installation and provides the full
API, including named rows and columns, sensitivity analysis and
callbacks.