Learning-augmented optimization: differentiable APQP/APLP layers on CVXPY and PyTorch.
Project description
DiffAPQP
DiffAPQP connects continuous affine-parametric quadratic and linear programs written in CVXPY to PyTorch. It provides differentiable layers for two common learning targets:
SolMapLayerdifferentiates losses that depend on the optimal decision $\hat z^\star$.ValueFuncLayerdifferentiates losses that depend on the optimal objective value $\alpha(\hat y)$.
Write the optimization model naturally in CVXPY and pass the original
cvxpy.Problem to either layer. DiffAPQP validates and canonicalizes compatible
problems internally, so no manual standard-form construction is required.
The package is developed by Dr. Wangkun Xu from Imperial College London, partially funded by EPSRC under Grant EP/Y025946/1.
- More details can be found in the documentation.
- Please also refer to our preprint paper: Structured Differentiable Optimization for Efficient Decision-focused Learning in Power Systems and
- power system application repository: diffapqp-power-system.
Highlights
- Native CVXPY modeling: parameter and variable names become the keys of the layer's input and output dictionaries.
- Batched execution: independent parameter instances can be solved concurrently.
- Flexible forward solvers: CVXPY-compatible QP and conic backends can be used independently of the backward method.
- Repeated-solve acceleration: solver warm starts and in-place data updates are available where the backend and CVXPY interface support them.
- Specialized differentiation: solution-map losses use full- or reduced-KKT adjoints, while value-function losses use a direct value derivative without solving an adjoint system.
Installation
Install the core package from PyPI:
python -m pip install diffapqp
This installs CVXPY and its standard dependencies, which normally provide Clarabel, OSQP, and SCS. Optional solver packages can be installed with:
python -m pip install "diffapqp[gurobi]" # Gurobi; a licence is required
python -m pip install "diffapqp[proxqp]" # PROXQP
DiffAPQP's explicit sample-indexed warm starts and in-place solver-data updates for OSQP, SCS, QPALM, and PROXQP require the pinned custom CVXPY fork:
python -m pip install \
"cvxpy @ git+https://github.com/xuwkk/cvxpy.git@v1.9.0-lapso.7"
python -m pip install diffapqp
The custom fork requires Python 3.11 or later. The core DiffAPQP package supports Python 3.9 or later. Install PyTorch separately first when a particular CUDA build is required.
See the installation guide for editable installs, compatibility imports, and additional solver backends.
Quick Start
The following example defines a parameterized QP, solves two instances as a batch, and differentiates a loss through the optimal decisions:
import cvxpy as cp
import torch
from diffapqp import SolMapLayer
z = cp.Variable(2, name="z")
q = cp.Parameter(2, name="q")
problem = cp.Problem(
cp.Minimize(0.5 * cp.sum_squares(z) + q @ z),
[z >= 0, z <= 10],
)
layer = SolMapLayer(problem, max_n_cores=1)
q_batch = torch.tensor(
[[-1.0, -2.0], [0.5, -1.5]],
dtype=torch.double,
requires_grad=True,
)
primal_dict, *_ = layer(
{"q": q_batch},
solver="OSQP",
reduced_kkt=True,
)
loss = primal_dict["z"].square().mean()
loss.backward()
print(primal_dict["z"])
print(q_batch.grad)
The leading tensor dimension is the batch dimension. Input keys must match the
names of CVXPY parameters, and primal_dict restores the names and shapes of
the original CVXPY variables.
Choose a Layer
| Training loss depends on | Layer | Differentiable output | Backward method |
|---|---|---|---|
| Optimal decisions $\hat z^\star$ | SolMapLayer |
Named variables in primal_dict |
Full- or reduced-KKT adjoint |
| Optimal value $\alpha(\hat y)$ | ValueFuncLayer |
value_batch |
Direct value-function derivative |
Supported Problem Class
DiffAPQP targets continuous affine-parametric QPs and LPs whose canonical form is
$$ \begin{aligned} \underset{\tilde z}{\operatorname{minimize}}\quad & \frac{1}{2}\tilde z^\top P\tilde z
- q(\hat y)^\top\tilde z + c(\hat y) \ \text{subject to}\quad & A\tilde z = b(\hat y), \ & G\tilde z \le h(\hat y). \end{aligned} $$
The matrices $P$, $A$, and $G$ are constant, while $q$, $c$, $b$, and $h$ may depend affinely on the parameter vector $\hat y$. Linear programs are the special case $P=0$.
The original CVXPY problem must:
- be continuous, DCP compliant, and reducible through CVXPY's QP canonicalization;
- satisfy CVXPY's DPP rules when parameterized;
- assign explicit names to all parameters and decision variables.
Parameterized quadratic or constraint matrices, nonlinear constraints, and integer or Boolean decisions are outside the current layer contract. The problem setup explains the accepted model and internal canonicalization in detail.
Warm Start and Update
With the custom CVXPY fork, repeated solves can associate warm-start iterates with stable sample identifiers and reuse a solver workspace for each batch slot:
primal_dict, *_ = layer(
param_dict,
idx_list=sample_ids,
solver="OSQP",
warm_start=True,
update=True,
)
The first call initializes the relevant state; later calls reuse it. Warm start and update are distinct mechanisms, and their exact behavior is solver dependent. See Efficient Forward Pass for the lifecycle and Solvers for backend coverage and default arguments.
Documentation
- Documentation home
- Installation
- Solvers and default arguments
- API overview
- Theory overview
- Solution-map layer
- Value-function layer
Tutorials, Tests, and Benchmarks
- Tutorials provide runnable examples of both differentiable layers.
- Tests cover canonicalization, forward solves, gradients, and package compatibility.
- Benchmarks compare runtime, gradient agreement, CPU usage, and memory usage.
Development
git clone https://github.com/xuwkk/diffapqp.git
cd diffapqp
python -m pip install -e ".[dev,docs]"
python -m pytest
python -m mkdocs build --strict
Install the custom CVXPY fork before the editable package when developing or testing sample-indexed warm-start/update behavior.
License
DiffAPQP is released under the Apache License 2.0.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file diffapqp-0.1.0.tar.gz.
File metadata
- Download URL: diffapqp-0.1.0.tar.gz
- Upload date:
- Size: 44.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa7d90d67fbb5c06bd7157326c0bfa8ca0e694228ce3992a2a7d9191cec92848
|
|
| MD5 |
db1edb87e282fecc6733fe8dbbb03122
|
|
| BLAKE2b-256 |
94f192e1fd72644d07b5d196ed62595b182be925c60a6f4c9b94f68d5f8116ac
|
File details
Details for the file diffapqp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: diffapqp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 37.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.18
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
84643041b4d63a5d31d06026a16ec2b0ef443c133a24925e2aff92d63ad7baea
|
|
| MD5 |
ebb56a1ad1ca9c95aa1aa2a56af09161
|
|
| BLAKE2b-256 |
61c3c4c51f2d60e81cf69f54f2754963bfb143225259f7bb946658891461408f
|