An R interface to COIN-OR Clp, the simplex and interior point linear programming solver of the COIN-OR project.
coinclp replaces the clpAPI package,
which was archived from CRAN on 2021-11-30 and took ROI.plugin.clp
with it in January 2022. The bindings here are written from scratch
against the current Clp callable library, use registered
.Call entry points and external pointers with finalizers,
and build on R 4.5 and R 4.6. A compatibility layer reproduces clpAPI’s
exported functions so existing code runs unchanged.
Clp is not bundled; install the library first.
| Platform | Command |
|---|---|
| Windows | nothing to do: Rtools 4.3 and later ship Clp |
| Debian / Ubuntu | sudo apt-get install coinor-libclp-dev |
| Fedora / RHEL | sudo dnf install coin-or-Clp-devel |
| macOS | brew install clp |
| conda-forge | conda install coin-or-clp |
Then:
# install.packages("remotes")
remotes::install_github("SamLovick/coinclp")If Clp sits somewhere pkg-config does not look:
R CMD INSTALL coinclp \
--configure-args='--with-clp-include=/opt/clp/include/coin --with-clp-lib=/opt/clp/lib'library(coinclp)
# maximise 143x + 60y subject to
# 120x + 210y <= 15000
# 110x + 30y <= 4000
# x + y <= 75
A <- rbind(c(120, 210), c(110, 30), c(1, 1))
res <- clp_solve(c(143, 60), A, "<=", c(15000, 4000, 75), max = TRUE)
res$objval # 6315.625
res$solution # 21.875 53.125
res$duals # 0.000 1.0375 28.875constraints accepts a dense matrix, a sparse
Matrix object, a slam::simple_triplet_matrix,
or a list of i/j/v triplets.
Ranged constraints are written with row_lower and
row_upper instead of dir/rhs.
The full callable library is available for building a model once and re-solving it as it changes, which is where Clp earns its keep:
model <- clp_model()
clp_load_problem(model, ncols = 2, nrows = 3,
start = c(0L, 3L, 6L),
index = c(0L, 1L, 2L, 0L, 1L, 2L),
value = c(120, 110, 1, 210, 30, 1),
obj = c(-143, -60),
rowub = c(15000, 4000, 75))
clp_initial_solve(model)
clp_objective_value(model) # -6315.625
basis <- clp_status_array(model) # keep the optimal basis
clp_set_row_upper(model, c(15000, 4000, 70))
clp_copyin_status(model, basis) # warm start
clp_dual_simplex(model) # re-solves in 0 iterations
clp_free(model)Also bound: presolve options (clp_options() and the
clp_options_* setters), barrier and idiot crash entry
points, row and column names, MPS input and output, model snapshots,
infeasibility and unboundedness rays, and every tolerance and limit Clp
exposes.
Row and column positions in the clp_* bindings are
0-based, matching the Clp documentation. clp_solve(),
clp_matrix() and the name accessors use ordinary 1-based R
positions.
Every function clpAPI exported is here with the same name and
arguments, so older scripts need only a new library()
line:
lp <- initProbCLP()
setLogLevelCLP(lp, 0)
loadProblemCLP(lp, 2, 3, c(0, 3, 6), c(0, 1, 2, 0, 1, 2),
c(120, 110, 1, 210, 30, 1),
lb = c(0, 0), ub = c(1e30, 1e30), obj_coef = c(143, 60),
rlb = rep(-1e30, 3), rub = c(15000, 4000, 75))
setObjDirCLP(lp, -1)
solveInitialCLP(lp)
getObjValCLP(lp) # 6315.625
delProbCLP(lp)The clpPtr S4 class, its accessors and the
status_codeCLP() / return_codeCLP() helpers
behave as before. New code should prefer the clp_*
interface.
Clp 1.16 or later works. A few entry points were added to the C API
after the 1.17 series (Clp_writeMps,
Clp_modifyCoefficient, Clp_setRowName,
Clp_setColumnName); configure detects them by
link test, and clp_features() reports what the current
build has. Where Clp_writeMps is missing — including the
Clp 1.17.0 that Rtools ships — clp_write_mps() falls back
to an MPS writer implemented in R.
The package is released under the Eclipse Public License, matching COIN-OR. Clp itself is a separate work under EPL 2.0 and is not distributed here.
Prior art: the clpAPI package by Gabriel Gelius-Dietrich (GPL-3)
defined the *CLP function names that the compatibility
layer reproduces; none of its code is used here.