Convex Optimization in R Using CVXR
A Hands-On Tutorial
A hands-on tutorial on disciplined convex optimization in R with CVXR, prepared for useR! 2026 (Warsaw).
Preface
Welcome to Convex Optimization in R Using CVXR, a hands-on tutorial prepared for useR! 2026 in Warsaw.
Convex optimization sits underneath a remarkable share of modern statistics and machine learning — least squares and ridge regression, the lasso and elastic net, robust and quantile regression, support vector machines, portfolio optimization, maximum-entropy modeling, and much more. CVXR lets you write these problems in R in natural mathematical notation and have them solved to global optimality, without hand-deriving a solver or matching your problem to a canned routine.
This tutorial accompanies CVXR 1.9.1, a ground-up rewrite built on R’s S7 object system that brings R to parity with Python’s CVXPY.
Who this is for
We assume intermediate R (data frames, functions, basic matrix algebra) and a little linear algebra and probability. No optimization background is required. The early chapters start gently — if you have never solved an optimization problem in your life, you are in the right place. Later chapters reach material that will interest experienced optimizers too; exercises marked with a star (⭐) are there for you.
How to use this book
This is a hands-on book. You are meant to run the code, not just read it.
- Open the accompanying project (see Getting the materials below) and work through each chapter’s
.qmdby executing the code chunks as you read. You do not need to type anything — click Run (or pressCtrl/Cmd+Enter) and watch what happens. - Each hands-on chapter ends with exercises. Try them, then click to reveal the solution:
Solutions look like this — the code and its output are right here, hidden until you want them.
Getting the materials
All the materials — chapter sources, data, and the setup_check.R script below — live in one Git repository: github.com/bnaras/cvxr_tutorial. Get a copy in whichever way suits you:
- RStudio (recommended): File → New Project → Version Control → Git, paste
https://github.com/bnaras/cvxr_tutorial.gitas the repository URL, and click Create Project — RStudio opens the project for you. (If you quit RStudio and come back later, reopen it via thecvxr-tutorial-2026.Rprojfile.) - Positron: open the Command Palette (
Ctrl/Cmd+Shift+P), run Git: Clone, paste the same URL, and open the cloned folder. - Terminal:
git clone https://github.com/bnaras/cvxr_tutorial.git, then open the folder in your editor. - No Git? Use the green Code → Download ZIP button on the repository page and unzip it.
We recommend RStudio for the tutorial: it bundles Quarto and needs no extra setup, so your time goes to optimization rather than tooling. Positron and other-editor users are of course welcome — you already know your environment. Whichever you use, make your first step, the moment the project is open, the setup check in Installation below: it tells you exactly which packages you need and which you already have.
You will also need Quarto (≥ 1.4) to render the book or preview chapters. RStudio bundles Quarto, so there is nothing extra to install there. Positron and plain-terminal users should install the Quarto CLI once from the link above. You can still run individual code chunks without rendering anything — Quarto is only required when you render a whole chapter or the full book (quarto render).
Two small things before you start. When you open a chapter such as 01-intro.qmd, edit it in Source mode, not Visual mode: the visual editor can silently rewrite a file’s options (for instance, adding a word-wrap setting to the header), which you don’t want in the shared materials. And we recommend rendering the book once, ahead of the session, with quarto render (or, in RStudio, the Render button, available any time a .qmd file is open): this caches every chunk’s results via Quarto’s freeze, so nothing has to recompute live during the tutorial, and it confirms your whole setup — packages and solvers — in one shot.
Installation
Everything in this tutorial runs on CRAN packages only. Your first step, once the project is open, is to run the included setup_check.R — it tells you what you need before you install anything:
source("setup_check.R") # or: Rscript setup_check.RFor every package it prints a table of what you have, your installed version, the minimum needed, and the version the tutorial was built with — so if anything misbehaves later, you can tell at a glance whether a version difference is to blame. It also checks your R version (R ≥ 4.3.0) and runs a tiny solve on each solver, reporting PASS/WARN/FAIL.
Then install whatever it flags. It is all on CRAN — the solvers and a handful of helper packages (for plots, data, and comparisons against familiar R routines):
# Solvers (CVXR auto-pulls clarabel, osqp, scs, highs)
install.packages(c("CVXR", "scip", "Uno", "sparsediff"))
# Helpers used by the examples
install.packages(c("ggplot2", "RColorBrewer", "tidyr", "nnls",
"glmnet", "png", "bench"))CVXR automatically brings in the four open-source solvers it uses — clarabel, osqp, scs, and highs. The scip/Uno/sparsediff trio powers two hands-on chapters near the end — mixed-integer second-order-cone programming with scip (11 Mixed-Integer Programming) and nonlinear programming with Uno + sparsediff (14 Beyond Convex: Nonlinear Programming). If you ever can’t install one of those three, you can still do every other chapter with just CVXR plus the helpers.
A note on solvers
We deliberately restrict ourselves to solvers available on CRAN. CVXR also interfaces with commercial solvers (MOSEK, Gurobi, CPLEX, Xpress) and several others, but none are needed here. Wherever a chapter names a solver explicitly, it is one of the CRAN ones above.
Further reading
Every topic here is expanded, with many more worked examples, at the CVXR website cvxr.rbind.io. The package is described in Fu et al. (2020). The standard reference for the subject is Boyd and Vandenberghe (2004).
Acknowledgments
CVXR builds on the work of the CVXPY team and the broader disciplined-convex- programming community. The examples here draw on the CVXR documentation, to whose many contributors we are grateful.