Overview

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

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.

Solving a MathProg model

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] 0

status 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.126

glpsol_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.

Separate data files

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"))

LP and MPS files

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 MPS

The 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.

Monitoring and limiting a run

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] FALSE

This 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.

Use from other packages

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.

Relation to other packages

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.