Skip to main content

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:

  • SolMapLayer differentiates losses that depend on the optimal decision $\hat z^\star$.
  • ValueFuncLayer differentiates 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

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


Download files

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

Source Distribution

diffapqp-0.1.0.tar.gz (44.5 kB view details)

Uploaded Source

Built Distribution

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

diffapqp-0.1.0-py3-none-any.whl (37.3 kB view details)

Uploaded Python 3

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

Hashes for diffapqp-0.1.0.tar.gz
Algorithm Hash digest
SHA256 fa7d90d67fbb5c06bd7157326c0bfa8ca0e694228ce3992a2a7d9191cec92848
MD5 db1edb87e282fecc6733fe8dbbb03122
BLAKE2b-256 94f192e1fd72644d07b5d196ed62595b182be925c60a6f4c9b94f68d5f8116ac

See more details on using hashes here.

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

Hashes for diffapqp-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 84643041b4d63a5d31d06026a16ec2b0ef443c133a24925e2aff92d63ad7baea
MD5 ebb56a1ad1ca9c95aa1aa2a56af09161
BLAKE2b-256 61c3c4c51f2d60e81cf69f54f2754963bfb143225259f7bb946658891461408f

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