Spaces:
Running
Running
Akshay Agrawal
commited on
Commit
·
f56200e
1
Parent(s):
94e0f7b
optimization: qps
Browse files
optimization/04_quadratic_program.py
ADDED
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# /// script
|
2 |
+
# requires-python = ">=3.13"
|
3 |
+
# dependencies = [
|
4 |
+
# "cvxpy==1.6.0",
|
5 |
+
# "marimo",
|
6 |
+
# "numpy==2.2.2",
|
7 |
+
# ]
|
8 |
+
# ///
|
9 |
+
|
10 |
+
import marimo
|
11 |
+
|
12 |
+
__generated_with = "0.11.0"
|
13 |
+
app = marimo.App()
|
14 |
+
|
15 |
+
|
16 |
+
@app.cell(hide_code=True)
|
17 |
+
def _(mo):
|
18 |
+
mo.md(
|
19 |
+
r"""
|
20 |
+
# Quadratic program
|
21 |
+
|
22 |
+
A quadratic program is an optimization problem with a quadratic objective and
|
23 |
+
affine equality and inequality constraints. A common standard form is the
|
24 |
+
following:
|
25 |
+
|
26 |
+
\[
|
27 |
+
\begin{array}{ll}
|
28 |
+
\text{minimize} & (1/2)x^TPx + q^Tx\\
|
29 |
+
\text{subject to} & Gx \leq h \\
|
30 |
+
& Ax = b.
|
31 |
+
\end{array}
|
32 |
+
\]
|
33 |
+
|
34 |
+
Here $P \in \mathcal{S}^{n}_+$, $q \in \mathcal{R}^n$, $G \in \mathcal{R}^{m \times n}$, $h \in \mathcal{R}^m$, $A \in \mathcal{R}^{p \times n}$, and $b \in \mathcal{R}^p$ are problem data and $x \in \mathcal{R}^{n}$ is the optimization variable. The inequality constraint $Gx \leq h$ is elementwise.
|
35 |
+
|
36 |
+
**Why quadratic programming?** Quadratic programs are convex optimization problems that generalize both least-squares and linear programming.They can be solved efficiently and reliably, even in real-time.
|
37 |
+
|
38 |
+
**An example from finance.** A simple example of a quadratic program arises in finance. Suppose we have $n$ different stocks, an estimate $r \in \mathcal{R}^n$ of the expected return on each stock, and an estimate $\Sigma \in \mathcal{S}^{n}_+$ of the covariance of the returns. Then we solve the optimization problem
|
39 |
+
|
40 |
+
\[
|
41 |
+
\begin{array}{ll}
|
42 |
+
\text{minimize} & (1/2)x^T\Sigma x - r^Tx\\
|
43 |
+
\text{subject to} & x \geq 0 \\
|
44 |
+
& \mathbf{1}^Tx = 1,
|
45 |
+
\end{array}
|
46 |
+
\]
|
47 |
+
|
48 |
+
to find a nonnegative portfolio allocation $x \in \mathcal{R}^n_+$ that optimally balances expected return and variance of return.
|
49 |
+
|
50 |
+
When we solve a quadratic program, in addition to a solution $x^\star$, we obtain a dual solution $\lambda^\star$ corresponding to the inequality constraints. A positive entry $\lambda^\star_i$ indicates that the constraint $g_i^Tx \leq h_i$ holds with equality for $x^\star$ and suggests that changing $h_i$ would change the optimal value.
|
51 |
+
"""
|
52 |
+
)
|
53 |
+
return
|
54 |
+
|
55 |
+
|
56 |
+
@app.cell(hide_code=True)
|
57 |
+
def _(mo):
|
58 |
+
mo.md(
|
59 |
+
r"""
|
60 |
+
## Example
|
61 |
+
|
62 |
+
In this example, we use CVXPY to construct and solve a quadratic program.
|
63 |
+
"""
|
64 |
+
)
|
65 |
+
return
|
66 |
+
|
67 |
+
|
68 |
+
@app.cell
|
69 |
+
def _():
|
70 |
+
import cvxpy as cp
|
71 |
+
import numpy as np
|
72 |
+
return cp, np
|
73 |
+
|
74 |
+
|
75 |
+
@app.cell(hide_code=True)
|
76 |
+
def _(mo):
|
77 |
+
mo.md("""First we generate synthetic data.""")
|
78 |
+
return
|
79 |
+
|
80 |
+
|
81 |
+
@app.cell
|
82 |
+
def _(np):
|
83 |
+
m = 15
|
84 |
+
n = 10
|
85 |
+
p = 5
|
86 |
+
|
87 |
+
np.random.seed(1)
|
88 |
+
P = np.random.randn(n, n)
|
89 |
+
P = P.T @ P
|
90 |
+
q = np.random.randn(n)
|
91 |
+
G = np.random.randn(m, n)
|
92 |
+
h = G @ np.random.randn(n)
|
93 |
+
A = np.random.randn(p, n)
|
94 |
+
b = np.random.randn(p)
|
95 |
+
return A, G, P, b, h, m, n, p, q
|
96 |
+
|
97 |
+
|
98 |
+
@app.cell(hide_code=True)
|
99 |
+
def _(mo):
|
100 |
+
mo.md(r"""Next, we specify the problem. Notice that we use the `quad_form` function from CVXPY to create the quadratic form $x^TPx$.""")
|
101 |
+
return
|
102 |
+
|
103 |
+
|
104 |
+
@app.cell
|
105 |
+
def _(A, G, P, b, cp, h, n, q):
|
106 |
+
x = cp.Variable(n)
|
107 |
+
|
108 |
+
problem = cp.Problem(
|
109 |
+
cp.Minimize((1 / 2) * cp.quad_form(x, P) + q.T @ x),
|
110 |
+
[G @ x <= h, A @ x == b],
|
111 |
+
)
|
112 |
+
_ = problem.solve()
|
113 |
+
return problem, x
|
114 |
+
|
115 |
+
|
116 |
+
@app.cell(hide_code=True)
|
117 |
+
def _(mo, problem, x):
|
118 |
+
mo.md(
|
119 |
+
f"""
|
120 |
+
The optimal value is {problem.value:.04f}.
|
121 |
+
|
122 |
+
A solution $x$ is {mo.as_html(list(x.value))}
|
123 |
+
A dual solution is is {mo.as_html(list(problem.constraints[0].dual_value))}
|
124 |
+
"""
|
125 |
+
)
|
126 |
+
return
|
127 |
+
|
128 |
+
|
129 |
+
@app.cell
|
130 |
+
def _():
|
131 |
+
import marimo as mo
|
132 |
+
return (mo,)
|
133 |
+
|
134 |
+
|
135 |
+
if __name__ == "__main__":
|
136 |
+
app.run()
|