Python에서 Quadratic programming 혹은 convex optimization을 위한 solver로 OSQP, CVXPY 등이 있지만 저는 가장 robust하다고 하는 CVXOPT package를 사용하고 있습니다.

Quadratic programming

| Notation | Meaning | Shape |
|---|---|---|
| $n$ | number of elements of the solution vector | $()$ |
| $m$ | number of inequality constraints | $()$ |
| $p$ | number of equality constraints | $()$ |
| $x$ | solution vector | $(n, 1)$ |
| $P$ | quadratic coefficient matrix (positive semidefinite) | $(n, n)$ |
| $q$ | linear coefficient vector | $(n, 1)$ |
| $G$ | Inequality constraint coefficient matrix | $(m, n)$ |
| $h$ | Inequality constraint constant vector | $(m, 1)$ |
| $A$ | Equality constraint coefficient matrix | $(p, n)$ |
| $b$ | Equality constraint constant vector | $(p, 1)$ |
\(\text{minimize }
\begin{aligned}
\frac{1}{2}
\begin{pmatrix}
x_1 & \cdots & x_n \\
\end{pmatrix}
\begin{pmatrix}
P_{11} & \cdots & P_{1n}\\
\vdots & \ddots & \vdots\\
P_{n1} & \cdots & P_{nn}\\
\end{pmatrix}
\begin{pmatrix}
x_1 \\
\vdots \\
x_n \\
\end{pmatrix} +
\begin{pmatrix}
q_1 & \cdots & q_n \\
\end{pmatrix}
\begin{pmatrix}
x_1 \\
\vdots \\
x_n \\
\end{pmatrix}
\end{aligned}
\\
\text{subject to }
\begin{pmatrix}
G_{11} & \cdots & G_{1n}\\
\vdots & \ddots & \vdots\\
G_{m1} & \cdots & G_{mn}\\
\end{pmatrix}
\begin{pmatrix}
x_1 \\
\vdots \\
x_n \\
\end{pmatrix} \preceq
\begin{pmatrix}
h_1 \\
\vdots \\
h_m \\
\end{pmatrix}
\\ \quad \quad \quad \quad \
\begin{pmatrix}
A_{11} & \cdots & A_{1n}\\
\vdots & \ddots & \vdots\\
A_{p1} & \cdots & A_{pn}\\
\end{pmatrix}
\begin{pmatrix}
x_1 \\
\vdots \\
x_n \\
\end{pmatrix} =
\begin{pmatrix}
b_1 \\
\vdots \\
b_p \\
\end{pmatrix}\)
Quadratic program를 풀기 위해서 먼저 해야할 일은 문제를 quadratic form으로 변형시키는 것입니다. 구체적으론 위의 식의 $P, q, G, h, A, b$ 를 구하는 일이죠.
물론, 제약조건 여부에 따라 $G, h, A, b$ 를 사용하지 않고 $P, q$ 만 가지고 있어도 됩니다.
Data는 double type(np.float64 or np.double)의 cvxopt.matrix() 형태로 입력해야 합니다.
간단한 linear regression 예제를 통해 사용방법을 알아봅시다!
\[min \ \frac{1}{2}|| S'w - y ||^2 \\ s.t. \sum_t w_t = 1 \\ \quad \ \ \ \forall_t w_t \geq 0\]위 식을 풀어보면 아래와 같이 표현할 수 있습니다.
\[min \ \frac{1}{2} w'(SS')w + (-Sy)'w \\ s.t. -Iw \leq \mathbf{0} \\ \quad \ \ \ \mathbf{1}w = 1\]1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import numpy as np
from cvxopt import matrix, solvers
n = 15
T = 60
S = np.random.rand(n, T)
y = np.random.rand(T)
P = matrix(S @ S.T)
q = matrix(-S @ y)
G = matrix(-1 * np.identity(n))
h = matrix(np.zeros(n))
A = matrix(np.ones(n).reshape(1, n))
b = matrix(1.0)
solvers.options['show_progress'] = False # verbose=False
sol = solvers.qp(P, q, G, h, A, b)
w = sol['x']
[ 2.71e-06]
[ 1.23e-01]
[ 7.77e-02]
[ 2.19e-02]
[ 7.99e-02]
[ 1.66e-01]
[ 8.54e-09]
[ 1.77e-08]
[ 1.62e-09]
[ 1.04e-01]
[ 5.16e-09]
[ 1.03e-01]
[ 9.16e-02]
[ 1.60e-09]
[ 2.33e-01]