set.seed(1)
n <- 5
M <- matrix(rnorm(n * n), n, n)
M <- (M + t(M)) / 2 # a symmetric --- but indefinite --- target matrix
round(eigen(M, only.values = TRUE)$values, 3) # note the negative eigenvalues[1] 1.768 0.907 0.562 -0.851 -1.705
Install and license MOSEK — a commercial-grade conic solver that is free for academic use — and route any CVXR problem to it by changing a single word. You will also see what MOSEK’s detailed solver log looks like on a small semidefinite program.
Every example in this book is solved with the open-source solvers that ship with CVXR — Clarabel, OSQP, SCS, HiGHS — and for the overwhelming majority of problems they are excellent. But commercial solvers can pull ahead on large or numerically hard problems, especially semidefinite and second-order-cone programs, and they tend to report richer diagnostics. MOSEK is a standout: a mature interior-point solver that is free for students and academic researchers.
The good news is that switching solvers changes nothing about your model. You write the problem exactly as before; you only name a different solver at solve time.
MOSEK is commercial software, but academic access is free and the setup is quick:
Get a license. Request a free personal academic license (or a 30-day commercial trial). Save the license file to ~/mosek/mosek.lic — the default location MOSEK searches — or point the MOSEKLM_LICENSE_FILE environment variable at it.
Install the Rmosek interface. Rmosek is distributed by MOSEK, not from CRAN, and is built against your local MOSEK installation:
install.packages("Rmosek", repos = "https://download.mosek.com/stable/rmosek/")
library(Rmosek)
mosek_attachbuilder() # locate the MOSEK Optimization Suite
install.rmosek() # build and install the interfaceThe official, platform-by-platform guide is at docs.mosek.com.
Check it works:
library(Rmosek)
mosek_version()Once Rmosek loads and the license is found, CVXR will discover MOSEK automatically.
Selecting MOSEK is a one-word change to psolve():
psolve(prob, solver = "MOSEK")That is the whole API. Variables, constraints, the objective, and dual-variable recovery are all identical to every other solver — the solver name is the only thing that changes.
Here is a small semidefinite program, the kind of problem where a commercial conic solver earns its keep. Given a symmetric (but indefinite) matrix \(M\), we look for the positive-semidefinite matrix \(X\) closest to it in Frobenius norm:
\[ \underset{X \succeq 0}{\text{minimize}}\ \ \|X - M\|_F^2 . \]
The constraint \(X \succeq 0\) (“\(X\) is PSD”) is declared right on the variable:
set.seed(1)
n <- 5
M <- matrix(rnorm(n * n), n, n)
M <- (M + t(M)) / 2 # a symmetric --- but indefinite --- target matrix
round(eigen(M, only.values = TRUE)$values, 3) # note the negative eigenvalues[1] 1.768 0.907 0.562 -0.851 -1.705
The target has negative eigenvalues, so it is not itself PSD. We solve for the closest matrix that is, and turn on verbose = TRUE to watch MOSEK work:
X <- Variable(c(n, n), PSD = TRUE) # symmetric PSD matrix variable
prob <- Problem(Minimize(sum_squares(X - M))) # nearest PSD matrix, Frobenius norm
psolve(prob, solver = "MOSEK", verbose = TRUE)The solve above is marked eval: false so the book builds without MOSEK installed. The output below is the genuine result of running it with MOSEK 11.1.2.
With verbose = TRUE, CVXR reports the compilation and the solve summary — note that the chosen solver is MOSEK, and that compile time and solver time are tracked separately (Chapter 8):
────────────────────────────── CVXR v1.9.1 ──────────────────────────────
ℹ Problem: 1 variable, 0 constraints (DCP)
ℹ Compilation: "MOSEK" via CVXR::Dcp2Cone -> CVXR::CvxAttr2Constr ->
CVXR::ConeMatrixStuffing -> CVXR::Mosek_Solver
ℹ Compile time: 0.21s
─────────────────────────── Numerical solver ────────────────────────────
──────────────────────────────── Summary ────────────────────────────────
✔ Status: optimal
✔ Optimal value: 3.6305
ℹ Compile time: 0.21s
ℹ Solver time: 0.019s
MOSEK also keeps its own detailed log of the solve — the problem type, the interior-point iteration table, and a final optimizer summary. A future CVXR release will stream this log inline whenever you pass verbose = TRUE (as CVXPY does); here is what MOSEK reports for this SDP:
Problem
Name :
Objective sense : minimize
Type : CONIC (conic optimization problem)
Constraints : 0
Affine conic cons. : 2 (42 rows)
Scalar variables : 16
Matrix variables : 1 (scalarized: 1)
Integer variables : 0
Optimizer - threads : 16
Optimizer - solved problem : the primal
Optimizer - Constraints : 26
Optimizer - Cones : 1
Optimizer - Scalar variables : 28 conic : 27
Optimizer - Semi-definite variables: 1 scalarized : 15
Factor - nonzeros before factor : 351 after factor: 351
Factor - dense dim. : 0 flops : 7.88e+03
ITE PFEAS DFEAS GFEAS PRSTATUS POBJ DOBJ MU TIME
0 1.6e+00 1.0e+00 2.0e+00 0.00e+00 0.000000000e+00 -1.000000000e+00 1.0e+00 0.00
1 4.1e-01 2.5e-01 5.8e-01 -3.80e-01 1.089704904e+00 1.312151618e+00 2.5e-01 0.00
2 5.9e-02 3.6e-02 1.1e-02 5.00e-01 3.386613408e+00 3.242645938e+00 3.6e-02 0.00
3 7.4e-03 4.6e-03 5.1e-04 9.41e-01 3.608929356e+00 3.590619106e+00 4.6e-03 0.00
4 1.0e-03 6.4e-04 3.3e-05 1.01e+00 3.627235469e+00 3.624865947e+00 6.4e-04 0.00
5 3.2e-05 2.0e-05 2.3e-07 1.00e+00 3.630317873e+00 3.630261513e+00 2.0e-05 0.00
6 4.0e-06 2.5e-06 1.1e-08 1.00e+00 3.630469253e+00 3.630462235e+00 2.5e-06 0.00
7 4.0e-07 2.5e-07 3.7e-10 1.00e+00 3.630493170e+00 3.630492590e+00 2.5e-07 0.00
8 1.2e-08 7.5e-09 2.0e-12 1.00e+00 3.630495992e+00 3.630495975e+00 7.5e-09 0.00
Optimizer terminated. Time: 0.00
Interior-point solution summary
Problem status : PRIMAL_AND_DUAL_FEASIBLE
Solution status : OPTIMAL
Primal. obj: 3.6304959921e+00 nrm: 4e+00 Viol. var: 0e+00 barvar: 0e+00
Dual. obj: 3.6304959749e+00 nrm: 2e+00 Viol. var: 2e-11 barvar: 1e-24
Optimizer summary
Optimizer - time: 0.00
Interior-point - iterations : 8 time: 0.00
Simplex - iterations : 0 time: 0.00
Mixed integer - relaxations: 0 time: 0.00
Read the iteration table top to bottom: MOSEK drives the primal/dual feasibility residuals (PFEAS, DFEAS) and the duality gap (MU) down toward zero, the primal and dual objectives (POBJ, DOBJ) squeeze together, and after eight interior-point iterations they meet at the optimal value 3.6305 — exactly the number in CVXR’s summary. The solution \(X^\star\) is the original matrix with its negative eigenvalues clipped to zero, which is the classic closed form for this problem; CVXR and MOSEK recover it numerically without you having to know that.
Rmosek from MOSEK’s repo, and CVXR finds it automatically.psolve(prob, solver = "MOSEK") — with no change to the model.verbose = TRUE reports CVXR’s compile/solve summary; MOSEK additionally produces a detailed interior-point log of its own.For the full list of solvers CVXR can drive — open-source and commercial — and their capabilities, see the CVXR solver documentation.