Skip to content

Commit a974571

Browse files
authored
Merge pull request #264 from Bambade/qplayer
QPLayer: efficient differentiation of convex quadratic optimization
2 parents a5d11aa + cca81a0 commit a974571

File tree

76 files changed

+2147
-80
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+2147
-80
lines changed

.github/workflows/ci-linux-osx-win-conda.yml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,18 +123,29 @@ jobs:
123123
git submodule update --init
124124
mkdir build
125125
cd build
126-
cmake .. -G"Visual Studio 16 2019" -T "ClangCl" -DCMAKE_GENERATOR_PLATFORM=x64 -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX}/Library -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_SITELIB=${CONDA_PREFIX}/Lib/site-packages -DPYTHON_EXECUTABLE=${CONDA_PREFIX}/python.exe -DOpenMP_ROOT=$CONDA_PREFIX -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DLINK_PYTHON_INTERFACE_TO_OPENMP:BOOL=ON -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON
126+
cmake .. -G"Visual Studio 16 2019" -T "ClangCl" -DCMAKE_GENERATOR_PLATFORM=x64 -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX}/Library -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_SITELIB=${CONDA_PREFIX}/Lib/site-packages -DPYTHON_EXECUTABLE=${CONDA_PREFIX}/python.exe -DOpenMP_ROOT=$CONDA_PREFIX -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DLINK_PYTHON_INTERFACE_TO_OPENMP:BOOL=ON -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON
127127
128128
- name: Configure [Conda/Windows-latest]
129-
if: contains(matrix.os, 'windows-latest')
129+
if: contains(matrix.os, 'windows-latest') && contains(matrix.cxx_std, '20')
130130
shell: bash -l {0}
131131
run: |
132132
echo $(where ccache)
133133
ls C:\\Miniconda3\\envs\\proxsuite\\Library\\lib
134134
git submodule update --init
135135
mkdir build
136136
cd build
137-
cmake .. -G"Visual Studio 17 2022" -T "v143" -DCMAKE_GENERATOR_PLATFORM=x64 -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX}/Library -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_SITELIB=${CONDA_PREFIX}/Lib/site-packages -DPYTHON_EXECUTABLE=${CONDA_PREFIX}/python.exe -DOpenMP_ROOT=$CONDA_PREFIX -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DLINK_PYTHON_INTERFACE_TO_OPENMP:BOOL=ON -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON
137+
cmake .. -G"Visual Studio 17 2022" -T "ClangCl" -DCMAKE_GENERATOR_PLATFORM=x64 -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX}/Library -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_SITELIB=${CONDA_PREFIX}/Lib/site-packages -DPYTHON_EXECUTABLE=${CONDA_PREFIX}/python.exe -DOpenMP_ROOT=$CONDA_PREFIX -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DLINK_PYTHON_INTERFACE_TO_OPENMP:BOOL=ON -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON
138+
139+
- name: Configure [Conda/Windows-latest]
140+
if: contains(matrix.os, 'windows-latest') && contains(matrix.cxx_std, '17')
141+
shell: bash -l {0}
142+
run: |
143+
echo $(where ccache)
144+
ls C:\\Miniconda3\\envs\\proxsuite\\Library\\lib
145+
git submodule update --init
146+
mkdir build
147+
cd build
148+
cmake .. -G"Visual Studio 17 2022" -T "v143" -DCMAKE_GENERATOR_PLATFORM=x64 -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_INSTALL_PREFIX=${CONDA_PREFIX}/Library -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_CXX_STANDARD=${{ matrix.cxx_std }} -DBUILD_PYTHON_INTERFACE:BOOL=ON -DPYTHON_SITELIB=${CONDA_PREFIX}/Lib/site-packages -DPYTHON_EXECUTABLE=${CONDA_PREFIX}/python.exe -DOpenMP_ROOT=$CONDA_PREFIX -DBUILD_WITH_OPENMP_SUPPORT:BOOL=ON -DLINK_PYTHON_INTERFACE_TO_OPENMP:BOOL=ON -DBUILD_DOCUMENTATION:BOOL=ON -DINSTALL_DOCUMENTATION:BOOL=ON
138149
139150
- name: Build [Conda]
140151
shell: bash -l {0}

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ if(DEFINED CMAKE_CXX_STANDARD)
107107
else()
108108
set(CMAKE_CXX_STANDARD 17)
109109
endif()
110+
message(STATUS "[Proxsuite] Using C++ standard: ${CMAKE_CXX_STANDARD}")
110111

111112
# Handle Windows context
112113
if(MSVC)

README.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,21 @@ We are ready to integrate **ProxSuite** within other optimization ecosystems.
3333

3434
- dense, sparse, and matrix-free matrix factorization backends,
3535
- advanced warm-starting options (e.g., equality-constrained initial guess, warm-start or cold-start options from previous results),
36-
- dedicated features for handling more efficiently box constraints, linear programs, QP with diagonal Hessian, or with far more constraints than primal variables.
36+
37+
38+
with dedicated features for
39+
- handling more efficiently box constraints, linear programs, QP with diagonal Hessian, or with far more constraints than primal variables,
40+
- solving nonconvex QPs,
41+
- solving batches of QPs in parallel,
42+
- solving the closest feasible QP if the QP appears to be primal infeasible,
43+
- differentiating feasible and infeasible QPs.
3744

3845
**Proxsuite** is flexible:
3946

4047
- header only,
4148
- C++ 14/17/20 compliant,
4249
- Python and Julia bindings for easy code prototyping without sacrificing performance.
4350

44-
**Proxsuite** has a dedicated feature for solving batches of QPs.
45-
**Proxsuite** has a dedicated feature for solving nonconvex QPs.
46-
**Proxsuite** has a dedicated feature for solving the closest feasible QPs if they appear to be primal infeasible.
4751
**Proxsuite** is extensible.
4852
**Proxsuite** is reliable and extensively tested, showing the best performances on the hardest problems of the literature.
4953
**Proxsuite** is supported and tested on Windows, Mac OS X, Unix, and Linux.
@@ -123,7 +127,6 @@ where $x \in \mathbb{R}^n$ is the optimization variable. The objective function
123127
### Citing **ProxQP**
124128

125129
If you are using **ProxQP** for your work, we encourage you to [cite the related paper](https://hal.inria.fr/hal-03683733/file/Yet_another_QP_solver_for_robotics_and_beyond.pdf/).
126-
127130
### Numerical benchmarks
128131

129132
The numerical benchmarks of **ProxQP** against other commercial and open-source solvers are available [here](https://github.com/Simple-Robotics/proxqp_benchmark).
@@ -145,7 +148,24 @@ For hard problems from the [Maros Meszaros testset](http://www.cuter.rl.ac.uk/Pr
145148
The chart above reports the performance profiles of different solvers. It is classic for benchmarking solvers. Performance profiles correspond to the fraction of problems solved (on the y-axis) as a function of certain runtime (on the x-axis, measured in terms of a multiple of the runtime of the fastest solver for that problem). So the higher, the better. You can see that **ProxQP** solves the quickest over 60% of the problems (i.e., for $\tau=1$) and that for solving about 90% of the problems, it is at most 2 times slower than the fastest solvers solving these problems (i.e., for $\tau\approx2$).
146149

147150
*Note: All these results have been obtained with a 11th Gen Intel(R) Core(TM) i7-11850H @ 2.50GHz CPU.*
151+
## **QPLayer**
152+
153+
**QPLayer** enables to use a QP as a layer within standard learning architectures. More precisely, QPLayer differentiates over $\theta$ the primal and dual solutions of QP of the form
154+
155+
$$
156+
\begin{align}
157+
\min_{x} & ~\frac{1}{2}x^{T}H(\theta)x+g(\theta)^{T}x \\
158+
\text{s.t.} & ~A(\theta) x = b(\theta) \\
159+
& ~l(\theta) \leq C(\theta) x \leq u(\theta)
160+
\end{align}
161+
$$
162+
163+
where $x \in \mathbb{R}^n$ is the optimization variable. The objective function is defined by a positive semidefinite matrix $H(\theta) \in \mathcal{S}^n_+$ and a vector $g(\theta) \in \mathbb{R}^n$. The linear constraints are defined by the equality-contraint matrix $A(\theta) \in \mathbb{R}^{n_\text{eq} \times n}$ and the inequality-constraint matrix $C(\theta) \in \mathbb{R}^{n_\text{in} \times n}$ and the vectors $b \in \mathbb{R}^{n_\text{eq}}$, $l(\theta) \in \mathbb{R}^{n_\text{in}}$ and $u(\theta) \in \mathbb{R}^{n_\text{in}}$ so that $b_i \in \mathbb{R},~ \forall i = 1,...,n_\text{eq}$ and $l_i \in \mathbb{R} \cup \{ -\infty \}$ and $u_i \in \mathbb{R} \cup \{ +\infty \}, ~\forall i = 1,...,n_\text{in}$.
164+
165+
**QPLayer** is able to learn more structured architectures. For example, $\theta$ can consists only in learning some elements of $A$ while letting $b$ fixed (see e.g., the [example](https://github.com/Simple-Robotics/proxsuite/blob/main/examples/python/qplayer_sudoku.py) about how to include QPLayer into a learning pipeline). **QPLayer** can also differentiates over LPs. **QPLayer** allows for parallelized calculus over CPUs, and is interfaced with **PyTorch**.
166+
### Citing **QPLayer**
148167

168+
If you are using **QPLayer** for your work, we encourage you to [cite the related paper](https://inria.hal.science/hal-04133055/file/QPLayer_Preprint.pdf).
149169
## Installation procedure
150170

151171
Please follow the installation procedure [here](https://github.com/Simple-Robotics/proxsuite/blob/main/doc/5-installation.md).

benchmark/timings-parallel.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,10 @@ def generate_mixed_qp(n, n_eq, n_in, seed=1):
5858
proxsuite.proxqp.dense.solve_in_parallel(j, qps)
5959
timings[f"solve_parallel_{j}_threads"] = (perf_counter_ns() - tic) * 1e-6
6060

61+
62+
tic = perf_counter_ns()
63+
proxsuite.proxqp.dense.solve_in_parallel(qps=qps)
64+
timings[f"solve_parallel_heuristics_threads"] = (perf_counter_ns() - tic) * 1e-6
65+
6166
for k, v in timings.items():
6267
print(f"{k}: {v}ms")

bindings/python/CMakeLists.txt

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
if(UNIX)
22
set(PYTHON_COMPONENTS Development.Module)
33
endif()
4+
45
include(../../cmake-module/python.cmake)
56
include(../../cmake-module/python-helpers.cmake)
67

78
findpython(REQUIRED Development.Module)
8-
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/external/pybind11)
9-
add_subdirectory(external/pybind11
10-
${CMAKE_CURRENT_BINARY_DIR}/external/pybind11)
119

1210
if(IS_ABSOLUTE ${PYTHON_SITELIB})
1311
set(${PYWRAP}_INSTALL_DIR ${PYTHON_SITELIB}/${PROJECT_NAME})
@@ -16,6 +14,10 @@ else()
1614
${CMAKE_INSTALL_PREFIX}/${PYTHON_SITELIB}/${PROJECT_NAME})
1715
endif()
1816

17+
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/external/pybind11)
18+
add_subdirectory(external/pybind11
19+
${CMAKE_CURRENT_BINARY_DIR}/external/pybind11)
20+
1921
add_custom_target(python)
2022

2123
# Collect files
@@ -171,3 +173,15 @@ endif()
171173

172174
python_build_get_target(compile_pyc)
173175
add_dependencies(python ${compile_pyc})
176+
177+
set(PYTHON_FILES torch/__init__.py torch/qplayer.py torch/utils.py)
178+
179+
file(MAKE_DIRECTORY ${${PYWRAP}_INSTALL_DIR}/torch)
180+
181+
foreach(python ${PYTHON_FILES})
182+
python_build(${PROJECT_NAME} ${python})
183+
get_filename_component(pysubmodule ${python} PATH)
184+
get_filename_component(pyname ${python} NAME)
185+
set(MODULE_NAME ${PROJECT_NAME}/${pysubmodule})
186+
python_install_on_site(${MODULE_NAME} ${pyname})
187+
endforeach(python)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
try:
2+
import torch
3+
except ImportError:
4+
import warnings
5+
6+
warnings.warn(
7+
"PyTorch not found. Please install via pip or conda for example to use QPFunction."
8+
)
9+
del warnings

0 commit comments

Comments
 (0)