Skip to main content

A Python implementation of the CVQP solver for CVaR-constrained quadratic programs

Project description

CVQP

PyPI version License

CVQP is a Python library with fast, scalable methods for solving large-scale CVaR-constrained quadratic programs and Euclidean projection onto CVaR constraints (or equivalent sum-of-k-largest constraints). These methods handle problems where standard solvers are prohibitively slow or fail. For details, see our paper.

Installation

From PyPI:

pip install cvqp

From source:

git clone https://github.com/cvxgrp/cvqp.git
cd cvqp
poetry install
poetry run pip install -e .

Usage

Solve a CVaR-constrained quadratic program

CVQP solves problems of the form

$$ \begin{array}{ll} \text{minimize} & \frac{1}{2}x^TPx + q^Tx \ \text{subject to} & \phi_\beta(Ax) \leq \kappa \ & l \leq Bx \leq u, \end{array} $$

where $\phi_\beta$ is the Conditional Value-at-Risk (CVaR) at level $\beta$.

import numpy as np
from cvqp import solve_cvqp

# Problem data
np.random.seed(42)
n, m = 10, 100
P = np.eye(n) * 0.1                    # Quadratic cost matrix
q = np.ones(n) * -0.1                  # Linear cost vector
A = np.random.randn(m, n) * 0.2 + 0.1  # CVaR constraint matrix
B = np.eye(n)                          # Box constraint matrix
l = -np.ones(n)                        # Lower bounds
u = np.ones(n)                         # Upper bounds
beta = 0.9                             # CVaR confidence level
kappa = 0.1                            # CVaR limit

results = solve_cvqp(P=P, q=q, A=A, B=B, l=l, u=u,
                     beta=beta, kappa=kappa, verbose=True)

print(f"Optimal value: {results.value:.6f}")
print(f"Solution: {results.x}")

Project onto a CVaR constraint

Project a vector $v$ onto the feasible set defined by a CVaR constraint:

$$ \begin{array}{ll} \text{minimize} & |v - x|2^2 \ \text{subject to} & \phi\beta(x) \leq \kappa. \end{array} $$

from cvqp import proj_cvar
import numpy as np

# Create a vector representing scenario losses
v = np.array([4.0, 1.0, 6.0, 2.0, 5.0, 3.0, 7.0])
beta = 0.8  # Confidence level (80%)
kappa = 4.5  # CVaR threshold

x = proj_cvar(v, beta, kappa)

# Compute CVaR at confidence level beta
def cvar(losses, beta):
    sorted_losses = sorted(losses, reverse=True)
    k = int((1 - beta) * len(losses))
    return sum(sorted_losses[:k]) / k

print(f"Original losses: {v}")
print(f"Projected losses: {x}")
print(f"Original CVaR: {cvar(v, beta):.2f}")
print(f"Projected CVaR: {cvar(x, beta):.2f}")

Project onto a sum-of-k-largest constraint

CVaR constraints are equivalent to sum-of-k-largest constraints. For a vector $x \in \mathbf{R}^m$, the CVaR constraint $\phi_\beta(x) \leq \kappa$ is equivalent to $f_k(x) \leq d$ where $f_k(x) = \sum_{i=1}^k x_{[i]}$ (sum of k largest components), $k = (1-\beta)m$, and $d = \kappa k$. The projection problem becomes

$$ \begin{array}{ll} \text{minimize} & |v - x|_2^2 \ \text{subject to} & f_k(x) \leq d. \end{array} $$

from cvqp import proj_sum_largest
import numpy as np

# Create a vector to project
v = np.array([6.0, 2.0, 5.0, 4.0, 1.0])
k = 2  # Number of largest elements to constrain
d = 7.0  # Upper bound on sum

x = proj_sum_largest(v, k, d)

print(f"Original vector: {v}")
print(f"Projected vector: {x}")
print(f"Sum of {k} largest: {sum(sorted(x, reverse=True)[:k]):.2f}")

Benchmarks

See benchmarks/ for benchmark results against MOSEK and Clarabel on a suite of large-scale problems.

Citation

If you use CVQP in your research, please cite:

@misc{cvqp2025,
  title={An Operator Splitting Method for Large-Scale {CVaR}-Constrained Quadratic Programs},
  author={Luxenberg, Eric and P\'erez-Pi\~neiro, David and Diamond, Steven and Boyd, Stephen},
  year={2025},
  eprint={2504.10814},
  archivePrefix={arXiv},
  primaryClass={math.OC},
  url={https://arxiv.org/abs/2504.10814}
}

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

cvqp-0.2.0.tar.gz (16.3 kB view details)

Uploaded Source

Built Distribution

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

cvqp-0.2.0-py3-none-any.whl (17.4 kB view details)

Uploaded Python 3

File details

Details for the file cvqp-0.2.0.tar.gz.

File metadata

  • Download URL: cvqp-0.2.0.tar.gz
  • Upload date:
  • Size: 16.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.0.1 CPython/3.13.1 Darwin/24.4.0

File hashes

Hashes for cvqp-0.2.0.tar.gz
Algorithm Hash digest
SHA256 2b7f7f72856ad1ade7d8f9a08026d20ff96198198d9077e9a894d9a922690fed
MD5 7ea53f370260c47ac3bb182af78e86ac
BLAKE2b-256 054db4b2670684b48be94ea23d73d4d5d96a222c98ab844778c487dedfe51074

See more details on using hashes here.

File details

Details for the file cvqp-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: cvqp-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 17.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.0.1 CPython/3.13.1 Darwin/24.4.0

File hashes

Hashes for cvqp-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c565243489e9d07428bebb933f5c0e9126ef533e8fe6f352352c734b368f56bc
MD5 937c53dd01081bcda60adc6c3c4a4a5d
BLAKE2b-256 4beb074879b78b802c8e75b9926cfa5f113f64b5a375dacac7a5f85a3aa1576c

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