-
Notifications
You must be signed in to change notification settings - Fork 83
/
osqp_.py
100 lines (88 loc) · 3.09 KB
/
osqp_.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2016-2018 Stephane Caron <stephane.caron@normalesup.org>
#
# This file is part of qpsolvers.
#
# qpsolvers is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# qpsolvers is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with qpsolvers. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
from numpy import hstack, inf, ndarray, ones
from osqp import OSQP
from scipy.sparse import csc_matrix, vstack
from warnings import warn
def conversion_warning(M):
return "Converted %s to scipy.sparse.csc.csc_matrix\n" \
"For best performance, build %s as a csc_matrix " \
"rather than as a numpy.ndarray\n" % (M, M)
def osqp_solve_qp(P, q, G=None, h=None, A=None, b=None, initvals=None):
"""
Solve a Quadratic Program defined as:
minimize
(1/2) * x.T * P * x + q.T * x
subject to
G * x <= h
A * x == b
using OSQP <https://github.com/oxfordcontrol/osqp>.
Parameters
----------
P : scipy.sparse.csc_matrix
Symmetric quadratic-cost matrix.
q : numpy.array
Quadratic cost vector.
G : scipy.sparse.csc_matrix
Linear inequality constraint matrix.
h : numpy.array
Linear inequality constraint vector.
A : scipy.sparse.csc_matrix, optional
Linear equality constraint matrix.
b : numpy.array, optional
Linear equality constraint vector.
initvals : numpy.array, optional
Warm-start guess vector.
Returns
-------
x : array, shape=(n,)
Solution to the QP, if found, otherwise ``None``.
Note
----
OSQP requires `P` to be symmetric, and won't check for errors otherwise.
Check out for this point if you e.g. `get nan values
<https://github.com/oxfordcontrol/osqp/issues/10>`_ in your solutions.
"""
l = -inf * ones(len(h))
if type(P) is ndarray:
warn(conversion_warning("P"))
P = csc_matrix(P)
if A is not None:
if A.ndim == 1:
A = A.reshape((1, A.shape[0]))
qp_A = vstack([G, A]).tocsc()
qp_l = hstack([l, b])
qp_u = hstack([h, b])
else: # no equality constraint
if type(G) is ndarray:
warn(conversion_warning("G"))
G = csc_matrix(G)
qp_A = G
qp_l = l
qp_u = h
osqp = OSQP()
osqp.setup(P=P, q=q, A=qp_A, l=qp_l, u=qp_u, verbose=False)
if initvals is not None:
osqp.warm_start(x=initvals)
res = osqp.solve()
if res.info.status_val != osqp.constant('OSQP_SOLVED'):
print("OSQP exited with status '%s'" % res.info.status)
return res.x