Skip to main content

Code generation with CVXPY

Project description

CVXPYgen

PyPI version Python License CI

CVXPYgen takes a parametrized CVXPY convex optimization problem and generates a custom C solver tailored to that problem family. The generated code provides interfaces in C/C++ (for embedded applications) and Python/CVXPY (for prototyping and desktop applications).

Problems need to be modeled according to disciplined parametrized programming (DPP). For more details, see our slides and manuscript. If you use this code, please cite

@article{schaller2022embedded,
  title={Embedded code generation with CVXPY},
  author={Schaller, Maximilian and Banjac, Goran and Diamond, Steven and Agrawal, Akshay and Stellato, Bartolomeo and Boyd, Stephen},
  journal={IEEE Control Systems Letters},
  volume={6},
  pages={2653--2658},
  year={2022},
  publisher={IEEE}
}

Install

pip install cvxpygen

The CLARABEL solver requires Rust and Eigen. Example notebooks require marimo and matplotlib.

Quick start: Nonnegative least squares

import cvxpy as cp
from cvxpygen import cpg

# define CVXPY problem
m, n = 3, 2
A = cp.Parameter((m, n), name='A')
b = cp.Parameter(m, name='b')
x = cp.Variable(n, name='x')
problem = cp.Problem(cp.Minimize(cp.sum_squares(A @ x - b)), [x >= 0])

# generate code
cpg.generate_code(problem, code_dir='nonneg_ls')

Important: Set name= on variables and parameters. You'll identify them with these names after code generation. An extended version of this example is available under quick_start.py. An HTML summary of the generated code is written to nonneg_ls/README.html, with instructions for using the generated code.

C interface

Here is how to compile the auto-generated example nonneg_ls/c/src/cpg_example.c (requires CMake). Parameters and variables are stored as Fortran-order (column-major) flat arrays in C.

Unix:

cd nonneg_ls/c/build
cmake ..
cmake --build . --target cpg_example
./cpg_example

Windows:

cd nonneg_ls\c\build
cmake ..
cmake --build . --target cpg_example --config release
Release\cpg_example
CVXPY interface Here is how to register the Python module as a custom method for CVXPY.
from nonneg_ls.cpg_solver import cpg_solve
problem.register_solve('CPG', cpg_solve)

b.value = ...
problem.solve(method='CPG', updated_params=['b'])

solution = x.value

You may pass updated_params to tell the solver which parameters changed (omit it to update all).

generate_code options

Argument Type Default Description
code_dir str 'cpg_code' Output directory
solver str 'OSQP' for QPs
'QOCOGEN' for SOCPs
Solver backend
solver_opts dict {} Options forwarded to the solver
enable_settings list[str] [] Solver settings to keep tuneable at runtime
prefix str '' Symbol prefix for multi-problem codegen
gradient bool False Enable gradient computation (QPs only)
wrapper bool True Compile Python wrapper

Examples

Domain Marimo notebook
Actuator allocation actuator.py
Approximate dynamic programming adp.py
Model predictive control mpc.py
Portfolio construction portfolio.py
Resource allocation resource.py
Energy management energy.py
Network flow optimization network.py
Tuning PV system power.py
Learning alpha alpha.py

Run any marimo notebook as:

marimo edit actuator.py

Differentiable QPs

CVXPYgen supports differentiating through quadratic programs, with an interface to CVXPYlayers (>= 1.2.0):

cpg.generate_code(problem, code_dir='nonneg_ls_diff', gradient=True)

from nonneg_ls_diff.cpg_solver import forward, backward
from cvxpylayers.torch import CvxpyLayer
from cvxpylayers.interfaces import SolverInterface

layer = CvxpyLayer(problem, parameters=[A, b], variables=[x],
                   solver=SolverInterface.from_codegen(forward, backward))

As long as the problem is a QP, also conic solvers such as QOCOGEN or CLARABEL are supported. For more details, see our manuscript on differentiable QPs and examples/paper_grad for examples from the manuscript. Also see the example notebooks power.py and alpha.py. If you use this feature, please cite

@article{schaller2025code,
  title={Code generation for solving and differentiating through convex optimization problems},
  author={Schaller, Maximilian and Boyd, Stephen},
  journal={Optimization and Engineering},
  pages={1--25},
  year={2025},
  publisher={Springer}
}

Explicit solutions for QPs

For QPs whose parameters are all vectors (no matrix parameters), the solution is a piecewise affine function of the parameters. CVXPYgen integrates with PDAQP to precompute this map offline and generates code for instant evaluation online. Advantages of such an explicit solver can include transparency, interpretability, reliability, and speed. The number of inequality constraints (and non-differentiable atoms such as cp.norm1) should be small, since the number of affine pieces typically grows exponentially with those.

Important: Limit parameters with standard CVXPY constraints to keep the number of affine pieces tractable. For example, specify l <= p, p <= u where p is a CVXPY parameter and l and u are arrays:

prob = cp.Problem(obj, constr + [l <= p, p <= u])
cpg.generate_code(prob, code_dir='code_explicit', solver='explicit')

To enable the computation of dual variables, set solver_opts={'dual': True}. Control complexity via 'max_floats' (number of floating point numbers in the explicit solution, default 1e6) and 'max_regions' (maximum number of affine pieces, default 500) in solver_opts. Store the explicit solution in half precision (instead of single precision) by setting 'fp16': True in solver_opts.

For more details, see our slides and manuscript on explicit solutions for QPs. For practical examples, see power.py and alpha.py. If you use this feature, please cite

@article{schaller2025automatic,
  title={Automatic generation of explicit quadratic programming solvers},
  author={Schaller, Maximilian and Arnstr{\"o}m, Daniel and Bemporad, Alberto and Boyd, Stephen},
  journal={arXiv preprint arXiv:2506.11513},
  year={2025}
}

CVXPYgen 1.0 supports gradient=True along with solver='explicit'.

Tests

pip install pytest
cd tests
pytest

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cvxpygen-1.0.0.tar.gz (630.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cvxpygen-1.0.0-py3-none-any.whl (774.3 kB view details)

Uploaded Python 3

File details

Details for the file cvxpygen-1.0.0.tar.gz.

File metadata

  • Download URL: cvxpygen-1.0.0.tar.gz
  • Upload date:
  • Size: 630.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for cvxpygen-1.0.0.tar.gz
Algorithm Hash digest
SHA256 9cfe31c4c6cfbd5cab492beb6773f223b310b6cb79dd479938d580238c9433f5
MD5 9ee69122a7d46a78004e7d51484b298a
BLAKE2b-256 f2c9bda6870f790955e4569bc64a41d30f538b9daae6f13ce8bdc09a383bedda

See more details on using hashes here.

File details

Details for the file cvxpygen-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: cvxpygen-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 774.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for cvxpygen-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 facffac0f3816ddbee281ad1f3592be0c8c0fb318a7de4405c71d989665129f2
MD5 39d68f5a4cb468c2e56c8148eb3fd500
BLAKE2b-256 58a4566571718f79ca352530bd757fc3c1898b0462fdf93ccc0b33d07eba444f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page