qoco 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,58 @@
1
+ # Taken from osqp-python
2
+
3
+ name: Build Wheels
4
+
5
+ on:
6
+ # Triggers the workflow on push or pull request events
7
+ push:
8
+ branches:
9
+ - "*"
10
+ - "*/*"
11
+ - "**"
12
+ pull_request:
13
+ branches: [main]
14
+
15
+ jobs:
16
+ build_sdist:
17
+ name: Build source
18
+ runs-on: ubuntu-latest
19
+ strategy:
20
+ fail-fast: false
21
+ steps:
22
+ - uses: actions/checkout@master
23
+ with:
24
+ submodules: "recursive"
25
+
26
+ - name: Build source and wheel
27
+ run: |
28
+ python -m pip install build
29
+ python -m build --outdir=wheelhouse
30
+
31
+ - name: Upload sdist and wheel to github
32
+ uses: actions/upload-artifact@v4
33
+ with:
34
+ name: wheels-sdist
35
+ path: wheelhouse/*
36
+ if-no-files-found: error
37
+
38
+ build_wheels:
39
+ name: Building wheels on ${{ matrix.os }}
40
+ runs-on: ${{ matrix.os }}
41
+ strategy:
42
+ fail-fast: false
43
+ matrix:
44
+ os: [ubuntu-latest, macos-13, macos-latest]
45
+
46
+ steps:
47
+ - uses: actions/checkout@v4
48
+ with:
49
+ fetch-depth: 0
50
+ submodules: true
51
+
52
+ - uses: pypa/cibuildwheel@v2.21
53
+
54
+ - name: Upload wheels
55
+ uses: actions/upload-artifact@v4
56
+ with:
57
+ name: cibw-wheels-${{ matrix.os }}
58
+ path: wheelhouse/*.whl
@@ -0,0 +1,51 @@
1
+ # This is a basic workflow to help you get started with Actions
2
+
3
+ name: Unit Tests
4
+
5
+ # Controls when the workflow will run
6
+ on:
7
+ # Triggers the workflow on push or pull request events
8
+ push:
9
+ branches:
10
+ - "*"
11
+ - "*/*"
12
+ - "**"
13
+ pull_request:
14
+ branches: [main]
15
+
16
+ # Allows you to run this workflow manually from the Actions tab
17
+ workflow_dispatch:
18
+
19
+ # A workflow run is made up of one or more jobs that can run sequentially or in parallel
20
+ jobs:
21
+ # This workflow contains a single job called "build"
22
+ build:
23
+ # The type of runner that the job will run on
24
+ runs-on: ubuntu-latest
25
+
26
+ strategy:
27
+ # Set fail-fast to false to ensure that feedback is delivered for all matrix combinations. Consider changing this to true when your workflow is stable.
28
+ fail-fast: false
29
+
30
+ matrix:
31
+ os: [ubuntu-latest]
32
+
33
+ # Steps represent a sequence of tasks that will be executed as part of the job
34
+ steps:
35
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
36
+ - uses: actions/checkout@v4
37
+ - uses: actions/setup-python@v5
38
+ with:
39
+ python-version: "3.11"
40
+
41
+ - name: Install dependencies
42
+ run: >
43
+ pip install "pybind11[global]" pytest pytest-xdist cvxpy
44
+
45
+ - name: Install qoco
46
+ run: >
47
+ pip install .
48
+
49
+ - name: Run Pytest
50
+ run: >
51
+ pytest -n 12
qoco-0.1.0/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.egg-info/
2
+ build/
3
+ .vscode/
4
+ __pycache__/
5
+ qoco_custom*/
@@ -0,0 +1,33 @@
1
+ cmake_minimum_required(VERSION 3.15)
2
+ project(extension)
3
+
4
+ set(CMAKE_CXX_STANDARD 11)
5
+
6
+ set(QOCO_BUILD_TYPE "Release")
7
+
8
+ # Detect operating system.
9
+ message(STATUS "We are on a ${CMAKE_SYSTEM_NAME} system")
10
+ if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
11
+ add_compile_definitions(IS_LINUX)
12
+ elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
13
+ add_compile_definitions(IS_MACOS)
14
+ endif()
15
+
16
+ find_package(pybind11 REQUIRED)
17
+
18
+ message(STATUS "Fetching/configuring QOCO")
19
+ list(APPEND CMAKE_MESSAGE_INDENT " ")
20
+ include(FetchContent)
21
+ FetchContent_Declare(
22
+ qoco
23
+ GIT_REPOSITORY https://github.com/qoco-org/qoco.git
24
+ GIT_TAG 5abc44574b62e5a28cdae8e97ea70ecacf1f954c
25
+ )
26
+
27
+ list(POP_BACK CMAKE_MESSAGE_INDENT)
28
+ FetchContent_MakeAvailable(qoco)
29
+
30
+ pybind11_add_module(qoco_ext src/bindings.cpp)
31
+ target_include_directories(qoco_ext INTERFACE ${qoco_SOURCE_DIR}/include)
32
+ target_link_libraries(qoco_ext PUBLIC pybind11::module qocostatic)
33
+ install(TARGETS qoco_ext DESTINATION . COMPONENT python)
qoco-0.1.0/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2024, Govind Chari
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
qoco-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,47 @@
1
+ Metadata-Version: 2.1
2
+ Name: qoco
3
+ Version: 0.1.0
4
+ Summary: QOCO: Quadratic Objective Conic Optimizer
5
+ Author-Email: "Govind M. Chari" <govindchari1@gmail.com>
6
+ Project-URL: Homepage, https://github.com/qoco-org/qoco
7
+ Project-URL: Issues, https://github.com/qoco-org/qoco/issues
8
+ Requires-Python: >=3.8
9
+ Requires-Dist: jinja2
10
+ Requires-Dist: numpy>=1.7
11
+ Requires-Dist: qdldl
12
+ Requires-Dist: scipy>=0.13.2
13
+ Requires-Dist: setuptools
14
+ Description-Content-Type: text/markdown
15
+
16
+ # QOCO Python
17
+ <p align="center">
18
+ <img src="https://github.com/user-attachments/assets/7bd44fa7-d198-4739-bb79-a5c15e04a8de" alt="drawing" width="500"/>
19
+ </p>
20
+
21
+ <p align="center">
22
+ <a href="https://opensource.org/licenses/BSD-3-Clause"><img src="https://img.shields.io/badge/License-BSD_3--Clause-blue.svg" alt="License" /></a>
23
+ <a href=https://github.com/qoco-org/qoco-python/actions/workflows/unit_tests.yml/badge.svg"><img src="https://github.com/qoco-org/qoco-python/actions/workflows/unit_tests.yml/badge.svg"/></a>
24
+ </p>
25
+
26
+ This repository contains the python wrapper for [QOCO](https://github.com/qoco-org/qoco) and the code generator QOCOGEN.
27
+
28
+ QOCOGEN is a code generator which takes in an second-order cone program problem family and generates a customized C solver (called qoco_custom) for the specified problem family which implements the same algorithm as QOCO. This customized solver is library-free, only uses static memory allocation, and can be a few times faster than QOCO.
29
+
30
+ ## Bug reports
31
+
32
+ File any issues or bug reports using the [issue tracker](https://github.com/qoco-org/qoco-python/issues).
33
+
34
+ ## Citing
35
+ ```
36
+ @misc{chari2025qoco,
37
+ author = {Chari, Govind M. and Acikmese, Behcet},
38
+ title = {QOCO},
39
+ year = {2025},
40
+ publisher = {GitHub},
41
+ journal = {GitHub repository},
42
+ howpublished = {\url{https://github.com/qoco-org/qoco}},
43
+ }
44
+ ```
45
+
46
+ ## License
47
+ QOCO is licensed under the BSD-3-Clause license.
qoco-0.1.0/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # QOCO Python
2
+ <p align="center">
3
+ <img src="https://github.com/user-attachments/assets/7bd44fa7-d198-4739-bb79-a5c15e04a8de" alt="drawing" width="500"/>
4
+ </p>
5
+
6
+ <p align="center">
7
+ <a href="https://opensource.org/licenses/BSD-3-Clause"><img src="https://img.shields.io/badge/License-BSD_3--Clause-blue.svg" alt="License" /></a>
8
+ <a href=https://github.com/qoco-org/qoco-python/actions/workflows/unit_tests.yml/badge.svg"><img src="https://github.com/qoco-org/qoco-python/actions/workflows/unit_tests.yml/badge.svg"/></a>
9
+ </p>
10
+
11
+ This repository contains the python wrapper for [QOCO](https://github.com/qoco-org/qoco) and the code generator QOCOGEN.
12
+
13
+ QOCOGEN is a code generator which takes in an second-order cone program problem family and generates a customized C solver (called qoco_custom) for the specified problem family which implements the same algorithm as QOCO. This customized solver is library-free, only uses static memory allocation, and can be a few times faster than QOCO.
14
+
15
+ ## Bug reports
16
+
17
+ File any issues or bug reports using the [issue tracker](https://github.com/qoco-org/qoco-python/issues).
18
+
19
+ ## Citing
20
+ ```
21
+ @misc{chari2025qoco,
22
+ author = {Chari, Govind M. and Acikmese, Behcet},
23
+ title = {QOCO},
24
+ year = {2025},
25
+ publisher = {GitHub},
26
+ journal = {GitHub repository},
27
+ howpublished = {\url{https://github.com/qoco-org/qoco}},
28
+ }
29
+ ```
30
+
31
+ ## License
32
+ QOCO is licensed under the BSD-3-Clause license.
@@ -0,0 +1,20 @@
1
+ [build-system]
2
+ requires = ["scikit-build-core", "pybind11"]
3
+ build-backend = "scikit_build_core.build"
4
+
5
+ [project]
6
+ name = "qoco"
7
+ version = "0.1.0"
8
+ description = "QOCO: Quadratic Objective Conic Optimizer"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ authors = [{ name = "Govind M. Chari", email = "govindchari1@gmail.com" }]
12
+ dependencies = ["jinja2", "numpy>=1.7", "qdldl", "scipy>=0.13.2", "setuptools"]
13
+
14
+ [tool.scikit-build]
15
+ install.components = ["python"]
16
+ wheel.install-dir = "qoco"
17
+
18
+ [project.urls]
19
+ Homepage = "https://github.com/qoco-org/qoco"
20
+ Issues = "https://github.com/qoco-org/qoco/issues"
@@ -0,0 +1,7 @@
1
+ pybind11
2
+ numpy>=1.7
3
+ # Exclude scipy 1.12 because the random sparse array function started returning
4
+ # the transpose of the original, breaking the unit tests. This was fixed in 1.13.0.
5
+ # ref: https://github.com/scipy/scipy/issues/20027
6
+ scipy>=0.13.2,!=1.12.0
7
+ qdldl
@@ -0,0 +1,313 @@
1
+ /* Copyright (c) 2024, Govind M. Chari <govindchari1@gmail.com> */
2
+ /* This source code is licensed under the BSD 3-Clause License */
3
+
4
+ #include <pybind11/pybind11.h>
5
+ #include <pybind11/numpy.h>
6
+ #include "qoco.h"
7
+
8
+ namespace py = pybind11;
9
+ using namespace pybind11::literals;
10
+
11
+ class CSC
12
+ {
13
+ public:
14
+ CSC(py::object A);
15
+ ~CSC();
16
+ QOCOCscMatrix *getcsc() const;
17
+ py::array_t<QOCOFloat> _x;
18
+ py::array_t<QOCOInt> _i;
19
+ py::array_t<QOCOInt> _p;
20
+ QOCOInt m;
21
+ QOCOInt n;
22
+ QOCOInt nnz;
23
+
24
+ private:
25
+ QOCOCscMatrix *_csc;
26
+ };
27
+
28
+ CSC::CSC(py::object A)
29
+ {
30
+ py::object spa = py::module::import("scipy.sparse");
31
+
32
+ if (A == py::none())
33
+ {
34
+ this->m = 0;
35
+ this->n = 0;
36
+ this->nnz = 0;
37
+ this->_csc = nullptr;
38
+ }
39
+
40
+ else
41
+ {
42
+ py::tuple dim = A.attr("shape");
43
+
44
+ int m = dim[0].cast<int>();
45
+ int n = dim[1].cast<int>();
46
+
47
+ if (!spa.attr("isspmatrix_csc")(A))
48
+ {
49
+ A = spa.attr("csc_matrix")(A);
50
+ }
51
+
52
+ this->_p = A.attr("indptr").cast<py::array_t<QOCOInt, py::array::c_style>>();
53
+ this->_i = A.attr("indices").cast<py::array_t<QOCOInt, py::array::c_style>>();
54
+ this->_x = A.attr("data").cast<py::array_t<QOCOFloat, py::array::c_style>>();
55
+
56
+ this->_csc = new QOCOCscMatrix();
57
+ this->_csc->m = m;
58
+ this->_csc->n = n;
59
+ this->_csc->x = (QOCOFloat *)this->_x.data();
60
+ this->_csc->i = (QOCOInt *)this->_i.data();
61
+ this->_csc->p = (QOCOInt *)this->_p.data();
62
+ this->_csc->nnz = A.attr("nnz").cast<int>();
63
+
64
+ this->m = this->_csc->m;
65
+ this->n = this->_csc->n;
66
+ this->nnz = this->_csc->nnz;
67
+ }
68
+ }
69
+
70
+ QOCOCscMatrix *CSC::getcsc() const
71
+ {
72
+ return this->_csc;
73
+ }
74
+
75
+ CSC::~CSC()
76
+ {
77
+ if (this->_csc)
78
+ delete this->_csc;
79
+ }
80
+
81
+ class PyQOCOSolution
82
+ {
83
+ public:
84
+ PyQOCOSolution(QOCOSolution &, QOCOInt, QOCOInt, QOCOInt);
85
+ py::array_t<QOCOFloat> get_x();
86
+ py::array_t<QOCOFloat> get_s();
87
+ py::array_t<QOCOFloat> get_y();
88
+ py::array_t<QOCOFloat> get_z();
89
+ QOCOSolution &_solution;
90
+
91
+ private:
92
+ QOCOInt _n;
93
+ QOCOInt _m;
94
+ QOCOInt _p;
95
+ };
96
+
97
+ PyQOCOSolution::PyQOCOSolution(QOCOSolution &solution, QOCOInt n, QOCOInt m, QOCOInt p) : _n(n), _m(m), _p(p), _solution(solution)
98
+ {
99
+ }
100
+
101
+ py::array_t<QOCOFloat> PyQOCOSolution::get_x()
102
+ {
103
+ return py::array_t<QOCOFloat>(
104
+ {this->_n},
105
+ {sizeof(QOCOFloat)},
106
+ this->_solution.x);
107
+ }
108
+
109
+ py::array_t<QOCOFloat> PyQOCOSolution::get_s()
110
+ {
111
+ return py::array_t<QOCOFloat>(
112
+ {this->_m},
113
+ {sizeof(QOCOFloat)},
114
+ this->_solution.s);
115
+ }
116
+
117
+ py::array_t<QOCOFloat> PyQOCOSolution::get_y()
118
+ {
119
+ return py::array_t<QOCOFloat>(
120
+ {this->_p},
121
+ {sizeof(QOCOFloat)},
122
+ this->_solution.y);
123
+ }
124
+
125
+ py::array_t<QOCOFloat> PyQOCOSolution::get_z()
126
+ {
127
+ return py::array_t<QOCOFloat>(
128
+ {this->_m},
129
+ {sizeof(QOCOFloat)},
130
+ this->_solution.z);
131
+ }
132
+
133
+ class PyQOCOSolver
134
+ {
135
+ public:
136
+ PyQOCOSolver(QOCOInt, QOCOInt, QOCOInt, const CSC &, const py::array_t<QOCOFloat>, const CSC &, const py::array_t<QOCOFloat>, const CSC &, const py::array_t<QOCOFloat>, QOCOInt, QOCOInt, const py::array_t<QOCOInt>, QOCOSettings *);
137
+ ~PyQOCOSolver();
138
+
139
+ QOCOSettings *get_settings();
140
+ PyQOCOSolution &get_solution();
141
+
142
+ QOCOInt update_settings(const QOCOSettings &);
143
+ // QOCOInt update_vector_data(py::object, py::object, py::object);
144
+ // QOCOInt update_matrix_data(py::object, py::object, py::object);
145
+
146
+ QOCOInt solve();
147
+
148
+ private:
149
+ QOCOInt n;
150
+ QOCOInt m;
151
+ QOCOInt p;
152
+
153
+ const CSC &_P;
154
+ py::array_t<QOCOFloat> _c;
155
+
156
+ const CSC &_A;
157
+ py::array_t<QOCOFloat> _b;
158
+
159
+ const CSC &_G;
160
+ py::array_t<QOCOFloat> _h;
161
+
162
+ QOCOInt l;
163
+ QOCOInt nsoc;
164
+ py::array_t<QOCOInt> _q;
165
+
166
+ QOCOSolver *_solver;
167
+ };
168
+
169
+ PyQOCOSolver::PyQOCOSolver(QOCOInt n, QOCOInt m, QOCOInt p, const CSC &P, const py::array_t<QOCOFloat> c, const CSC &A, const py::array_t<QOCOFloat> b, const CSC &G, const py::array_t<QOCOFloat> h, QOCOInt l, QOCOInt nsoc, const py::array_t<QOCOInt> q, QOCOSettings *settings) : n(n), m(m), p(p), _P(P), _c(c), _A(A), _b(b), _G(G), _h(h), l(l), nsoc(nsoc), _q(q)
170
+ {
171
+ this->_solver = new QOCOSolver();
172
+
173
+ py::tuple dim = this->_b.attr("shape");
174
+ QOCOFloat *bptr;
175
+ if (dim[0].cast<int>() == 0)
176
+ {
177
+ bptr = (QOCOFloat *)nullptr;
178
+ }
179
+ else
180
+ {
181
+ bptr = (QOCOFloat *)this->_b.data();
182
+ }
183
+
184
+ dim = this->_h.attr("shape");
185
+ QOCOFloat *hptr;
186
+ if (dim[0].cast<int>() == 0)
187
+ {
188
+ hptr = nullptr;
189
+ }
190
+ else
191
+ {
192
+ hptr = (QOCOFloat *)this->_h.data();
193
+ }
194
+
195
+ dim = this->_q.attr("shape");
196
+ QOCOInt *qptr;
197
+ if (dim[0].cast<int>() == 0)
198
+ {
199
+ qptr = nullptr;
200
+ }
201
+ else
202
+ {
203
+ qptr = (QOCOInt *)this->_q.data();
204
+ }
205
+
206
+ QOCOInt status = qoco_setup(this->_solver, n, m, p, this->_P.getcsc(), (QOCOFloat *)this->_c.data(), this->_A.getcsc(), bptr, this->_G.getcsc(), hptr, l, nsoc, qptr, settings);
207
+
208
+ if (status)
209
+ {
210
+ std::string message = "Setup Error (Error Code " + std::to_string(status) + ")";
211
+ throw py::value_error(message);
212
+ }
213
+ }
214
+
215
+ PyQOCOSolver::~PyQOCOSolver()
216
+ {
217
+ qoco_cleanup(this->_solver);
218
+ }
219
+
220
+ QOCOSettings *PyQOCOSolver::get_settings()
221
+ {
222
+ return this->_solver->settings;
223
+ }
224
+
225
+ PyQOCOSolution &PyQOCOSolver::get_solution()
226
+ {
227
+ PyQOCOSolution *solution = new PyQOCOSolution(*this->_solver->sol, this->n, this->m, this->p);
228
+ return *solution;
229
+ }
230
+
231
+ QOCOInt PyQOCOSolver::solve()
232
+ {
233
+ py::gil_scoped_release release;
234
+ QOCOInt status = qoco_solve(this->_solver);
235
+ py::gil_scoped_acquire acquire;
236
+ return status;
237
+ }
238
+
239
+ QOCOInt PyQOCOSolver::update_settings(const QOCOSettings &new_settings)
240
+ {
241
+ return qoco_update_settings(this->_solver, &new_settings);
242
+ }
243
+
244
+ PYBIND11_MODULE(qoco_ext, m)
245
+ {
246
+ // Enums.
247
+ py::enum_<qoco_solve_status>(m, "qoco_solve_status", py::module_local())
248
+ .value("QOCO_UNSOLVED", QOCO_UNSOLVED)
249
+ .value("QOCO_SOLVED", QOCO_SOLVED)
250
+ .value("QOCO_SOLVED_INACCURATE", QOCO_SOLVED_INACCURATE)
251
+ .value("QOCO_MAX_ITER", QOCO_MAX_ITER)
252
+ .value("QOCO_NUMERICAL_ERROR", QOCO_NUMERICAL_ERROR)
253
+ .export_values();
254
+
255
+ // CSC.
256
+ py::class_<CSC>(m, "CSC", py::module_local())
257
+ .def(py::init<py::object>())
258
+ .def_readonly("m", &CSC::m)
259
+ .def_readonly("n", &CSC::n)
260
+ .def_readonly("x", &CSC::_x)
261
+ .def_readonly("i", &CSC::_i)
262
+ .def_readonly("p", &CSC::_p)
263
+ .def_readonly("nnz", &CSC::nnz);
264
+
265
+ // Settings.
266
+ py::class_<QOCOSettings>(m, "QOCOSettings", py::module_local())
267
+ .def(py::init([]()
268
+ { return new QOCOSettings(); }))
269
+ .def_readwrite("max_iters", &QOCOSettings::max_iters)
270
+ .def_readwrite("bisect_iters", &QOCOSettings::bisect_iters)
271
+ .def_readwrite("ruiz_iters", &QOCOSettings::ruiz_iters)
272
+ .def_readwrite("iter_ref_iters", &QOCOSettings::iter_ref_iters)
273
+ .def_readwrite("abstol", &QOCOSettings::abstol)
274
+ .def_readwrite("reltol", &QOCOSettings::reltol)
275
+ .def_readwrite("abstol_inacc", &QOCOSettings::abstol_inacc)
276
+ .def_readwrite("reltol_inacc", &QOCOSettings::reltol_inacc)
277
+ .def_readwrite("kkt_static_reg", &QOCOSettings::kkt_static_reg)
278
+ .def_readwrite("kkt_dynamic_reg", &QOCOSettings::kkt_dynamic_reg)
279
+ .def_readwrite("verbose", &QOCOSettings::verbose);
280
+
281
+ m.def("set_default_settings", &set_default_settings);
282
+
283
+ // Solution.
284
+ py::class_<PyQOCOSolution>(m, "QOCOSolution", py::module_local())
285
+ .def_property_readonly("x", &PyQOCOSolution::get_x)
286
+ .def_property_readonly("s", &PyQOCOSolution::get_s)
287
+ .def_property_readonly("y", &PyQOCOSolution::get_y)
288
+ .def_property_readonly("z", &PyQOCOSolution::get_z)
289
+ .def_property_readonly("iters", [](const PyQOCOSolution &sol)
290
+ { return sol._solution.iters; })
291
+ .def_property_readonly("setup_time_sec", [](const PyQOCOSolution &sol)
292
+ { return sol._solution.setup_time_sec; })
293
+ .def_property_readonly("solve_time_sec", [](const PyQOCOSolution &sol)
294
+ { return sol._solution.solve_time_sec; })
295
+ .def_property_readonly("obj", [](const PyQOCOSolution &sol)
296
+ { return sol._solution.obj; })
297
+ .def_property_readonly("pres", [](const PyQOCOSolution &sol)
298
+ { return sol._solution.pres; })
299
+ .def_property_readonly("dres", [](const PyQOCOSolution &sol)
300
+ { return sol._solution.dres; })
301
+ .def_property_readonly("gap", [](const PyQOCOSolution &sol)
302
+ { return sol._solution.gap; })
303
+ .def_property_readonly("status", [](const PyQOCOSolution &sol)
304
+ { return sol._solution.status; });
305
+
306
+ // Solver.
307
+ py::class_<PyQOCOSolver>(m, "QOCOSolver", py::module_local())
308
+ .def(py::init<QOCOInt, QOCOInt, QOCOInt, const CSC &, const py::array_t<QOCOFloat>, const CSC &, const py::array_t<QOCOFloat>, const CSC &, const py::array_t<QOCOFloat>, QOCOInt, QOCOInt, const py::array_t<QOCOInt>, QOCOSettings *>(), "n"_a, "m"_a, "p"_a, "P"_a, "c"_a.noconvert(), "A"_a, "b"_a.noconvert(), "G"_a, "h"_a.noconvert(), "l"_a, "nsoc"_a, "q"_a.noconvert(), "settings"_a)
309
+ .def_property_readonly("solution", &PyQOCOSolver::get_solution, py::return_value_policy::reference)
310
+ .def("update_settings", &PyQOCOSolver::update_settings)
311
+ .def("solve", &PyQOCOSolver::solve)
312
+ .def("get_settings", &PyQOCOSolver::get_settings, py::return_value_policy::reference);
313
+ }
@@ -0,0 +1 @@
1
+ from qoco.interface import QOCO