Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Two small R packages of mine have gone to CRAN. coinclp binds the COIN-OR Clp linear programming solver and was accepted on 15 September 2026; ROI.plugin.coinclp registers it with the R Optimization Infrastructure and is in the submission queue behind it. Between them they put back something R lost at the end of 2021, and this post is a short account of what that was, what the new packages do, and — because it would be dishonest to leave it out — when you should reach for a different solver altogether.
Where this comes from
Clp is one of the original COIN-OR codes. COIN-OR started inside IBM Research in 2000 as an open-source home for operations research software, and Clp — John Forrest’s simplex code, with a barrier method alongside — has been its linear programming workhorse ever since. It is mature, free under the Eclipse Public License, and good at the thing simplex codes are for: solving a model, changing it a little, and solving it again from the basis you already have.
R had a binding to it for a decade. Gabriel Gelius-Dietrich’s clpAPI, written at Heinrich Heine University Düsseldorf for the sybil metabolic-modelling toolkit, was on CRAN from 2011. In 2017 Benoit Thieurmel built ROI.plugin.clp on top of it, so that anyone using ROI could pick Clp with one argument. Then clpAPI’s CRAN checks started failing, nobody fixed them, and it was archived on 30 November 2021. ROI.plugin.clp had done nothing wrong, but it depended on an archived package, so it followed six weeks later.
I had been using clpAPI in my own models since 2018 and noticed the way everyone does: a fresh R install, a script that would not load. The particular annoyance is that on Windows the Clp library is already on the machine — Rtools has shipped it since version 4.3 — so the only thing missing was a few hundred lines of C++ to get at it.
What coinclp does
The bindings are written from scratch against the current Clp callable library, with registered entry points and external pointers that clean up after themselves, and they build on R 4.5 and 4.6. There are three ways in.
The first is one call. Give it an objective, a constraint matrix, directions and a right-hand side, and get back the solution, the objective, the shadow prices and the reduced costs together:
library(coinclp)
A <- rbind(material = c(120, 210),
labour = c(110, 30),
capacity = c( 1, 1))
fit <- clp_solve(c(143, 60), A, "<=", c(15000, 4000, 75), max = TRUE)
fit$objval # 6315.625
fit$solution # 21.875 53.125
fit$duals # 0.0000 1.0375 28.8750
The constraint matrix can be an ordinary dense matrix, a Matrix sparse matrix, a slam triplet matrix or plain i/j/v triplets. A sparse matrix goes to Clp as sparse: the package passes only the non-zero entries, and never expands the matrix into a full grid of mostly zeros first, which for a large model is the difference between fitting in memory and not.
The second is the whole callable library: build a model, keep it, change bounds or coefficients, hand back the basis and re-solve. That is what Clp is for, and it is where the one-call interfaces of most R solver packages let you down — a parametric study or a column-generation loop that rebuilds the model each iteration throws away exactly the information that makes simplex fast. In the vignette a tightened re-solve from a saved basis takes zero iterations.
The third is for old code. Every function clpAPI exported — initProbCLP(), loadProblemCLP(), solveInitialCLP() and the rest — is reproduced with the same names and arguments, so a script written against clpAPI needs only a new library() line. None of clpAPI’s code is reused; the layer is an independent implementation of its interface.
ROI.plugin.coinclp is the ROI side. The solver is called "coinclp" rather than "clp", because ROI takes the name from the package, and unlike the 2017 plugin it returns duals, reduced costs and row activities alongside the primal solution:
library(ROI) library(ROI.plugin.coinclp) res <- ROI_solve(op, solver = "coinclp") solution(res, "dual")
When not to use it
Clp is not the fastest open-source LP solver any more, and I would rather say so than have you find out. The obvious comparison is HiGHS, from Julian Hall’s group at Edinburgh, which is now the default LP solver in SciPy and in MATLAB. On Hans Mittelmann’s LPopt benchmark as of September 2026, HiGHS solves 54 of the 65 test problems within the time limit and Clp solves 40, and HiGHS is about twice as fast on the scaled geometric mean. The commercial codes are further ahead again: COPT solves all 65 and is roughly 27 times faster than Clp on the same measure.
The benchmark also shows why the honest answer is “it depends on the model”. On a handful of instances Clp is the quicker of the two — Linf_520c takes Clp 36 seconds and HiGHS 872, and Clp solves datt256 where HiGHS times out — but on more of them the reverse holds, sometimes by a wide margin. If you have one large LP to solve once, try highs or ROI.plugin.highs first; with ROI the switch is one argument, so trying both costs nothing.
And Clp solves linear programs only. If your variables are integer you need a MIP solver: HiGHS again, or Rglpk, lpSolve or COIN-OR’s own Rsymphony. The ROI plugin will refuse an integer problem rather than quietly relax it, and clp_solve() has no notion of integer variables at all.
Where Clp still earns its place is the kind of work it was built for: models that are solved many times with small changes, where a warm start from the previous basis matters more than raw speed on a cold solve; anything that already speaks Clp’s API, which is more code than you might think; and Windows machines, where it is the one LP solver you get for free with Rtools and no further installation.
Installing it
On Windows, install.packages("coinclp") is the whole job — from source with Rtools installed until CRAN’s Windows binaries appear, which usually takes a few days. Elsewhere Clp is a system library and has to be there first: coinor-libclp-dev on Debian and Ubuntu, coin-or-Clp-devel on Fedora, brew install clp on macOS, coin-or-clp from conda-forge. Until the ROI plugin clears the CRAN queue it installs from GitHub:
install.packages("coinclp")
remotes::install_github("SamLovick/ROI.plugin.coinclp")
Source, issues and the vignette are at github.com/SamLovick/coinclp and github.com/SamLovick/ROI.plugin.coinclp. Both packages are under the Eclipse Public License, matching COIN-OR. If you were a clpAPI user and something in the compatibility layer does not behave as it used to, an issue with the script that broke would be very welcome.
The post coinclp: the COIN-OR Clp linear programming solver is back on CRAN appeared first on Sam Lovick Consulting.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
