Spaces:
Running
Running
Akshay Agrawal
commited on
Commit
·
28ec558
1
Parent(s):
f40980f
dcp, sdp
Browse files- optimization/06_convex_optimization.py +90 -0
- optimization/07_sdp.py +128 -0
- optimization/README.md +2 -4
optimization/06_convex_optimization.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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.2"
|
| 13 |
+
app = marimo.App()
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
@app.cell(hide_code=True)
|
| 17 |
+
def _(mo):
|
| 18 |
+
mo.md(
|
| 19 |
+
r"""
|
| 20 |
+
# Convex optimization
|
| 21 |
+
|
| 22 |
+
In the previous tutorials, we learned about least squares, linear programming,
|
| 23 |
+
and quadratic programming, and saw applications of each. We also learned that these problem
|
| 24 |
+
classes can be solved efficiently and reliably using CVXPY. That's because these problem classes are a special
|
| 25 |
+
case of a more general class of tractable problems, called **convex optimization problems.**
|
| 26 |
+
|
| 27 |
+
A convex optimization problem is an optimization problem that minimizes a convex
|
| 28 |
+
function, subject to affine equality constraints and convex inequality
|
| 29 |
+
constraints ($f_i(x)\leq 0$, where $f_i$ is a convex function).
|
| 30 |
+
|
| 31 |
+
**CVXPY.** CVXPY lets you specify and solve any convex optimization problem,
|
| 32 |
+
abstracting away the more specific problem classes. You start with CVXPY's **atomic functions**, like `cp.exp`, `cp.log`, and `cp.square`, and compose them to build more complex convex functions. As long as the functions are composed in the right way — as long as they are "DCP-compliant" — your resulting problem will be convex and solvable by CVXPY.
|
| 33 |
+
"""
|
| 34 |
+
)
|
| 35 |
+
return
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
@app.cell(hide_code=True)
|
| 39 |
+
def _(mo):
|
| 40 |
+
mo.md(
|
| 41 |
+
r"""
|
| 42 |
+
**🛑 Stop!** Before proceeding, read the CVXPY docs to learn about atomic functions and the DCP ruleset:
|
| 43 |
+
|
| 44 |
+
https://www.cvxpy.org/tutorial/index.html
|
| 45 |
+
"""
|
| 46 |
+
)
|
| 47 |
+
return
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
@app.cell(hide_code=True)
|
| 51 |
+
def _(mo):
|
| 52 |
+
mo.md(r"""**Is my problem DCP-compliant?** Below is a sample CVXPY problem. It is DCP-compliant. Try typing in other problems and seeing if they are DCP-compliant. If you know your problem is convex, there exists a way to express it in a DCP-compliant way.""")
|
| 53 |
+
return
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
@app.cell
|
| 57 |
+
def _(mo):
|
| 58 |
+
import cvxpy as cp
|
| 59 |
+
import numpy as np
|
| 60 |
+
|
| 61 |
+
x = cp.Variable(3)
|
| 62 |
+
P_sqrt = np.random.randn(3, 3)
|
| 63 |
+
|
| 64 |
+
objective = cp.log(np.random.randn(3) @ x) - cp.sum_squares(P_sqrt @ x)
|
| 65 |
+
constraints = [x >= 0, cp.sum(x) == 1]
|
| 66 |
+
problem = cp.Problem(cp.Maximize(objective), constraints)
|
| 67 |
+
mo.md(f"Is my problem DCP? `{problem.is_dcp()}`")
|
| 68 |
+
return P_sqrt, constraints, cp, np, objective, problem, x
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
@app.cell
|
| 72 |
+
def _(problem):
|
| 73 |
+
problem.solve()
|
| 74 |
+
return
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
@app.cell
|
| 78 |
+
def _(x):
|
| 79 |
+
x.value
|
| 80 |
+
return
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
@app.cell
|
| 84 |
+
def _():
|
| 85 |
+
import marimo as mo
|
| 86 |
+
return (mo,)
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
if __name__ == "__main__":
|
| 90 |
+
app.run()
|
optimization/07_sdp.py
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# /// script
|
| 2 |
+
# requires-python = ">=3.13"
|
| 3 |
+
# dependencies = [
|
| 4 |
+
# "cvxpy==1.6.0",
|
| 5 |
+
# "marimo",
|
| 6 |
+
# "numpy==2.2.2",
|
| 7 |
+
# "wigglystuff==0.1.9",
|
| 8 |
+
# ]
|
| 9 |
+
# ///
|
| 10 |
+
|
| 11 |
+
import marimo
|
| 12 |
+
|
| 13 |
+
__generated_with = "0.11.2"
|
| 14 |
+
app = marimo.App()
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
@app.cell(hide_code=True)
|
| 18 |
+
def _(mo):
|
| 19 |
+
mo.md(r"""# Semidefinite program""")
|
| 20 |
+
return
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
@app.cell(hide_code=True)
|
| 24 |
+
def _(mo):
|
| 25 |
+
mo.md(
|
| 26 |
+
r"""
|
| 27 |
+
_This notebook introduces an advanced topic._ A semidefinite program (SDP) is an optimization problem of the form
|
| 28 |
+
|
| 29 |
+
\[
|
| 30 |
+
\begin{array}{ll}
|
| 31 |
+
\text{minimize} & \mathbf{tr}(CX) \\
|
| 32 |
+
\text{subject to} & \mathbf{tr}(A_iX) = b_i, \quad i=1,\ldots,p \\
|
| 33 |
+
& X \succeq 0,
|
| 34 |
+
\end{array}
|
| 35 |
+
\]
|
| 36 |
+
|
| 37 |
+
where $\mathbf{tr}$ is the trace function, $X \in \mathcal{S}^{n}$ is the optimization variable and $C, A_1, \ldots, A_p \in \mathcal{S}^{n}$, and $b_1, \ldots, b_p \in \mathcal{R}$ are problem data, and $X \succeq 0$ is a matrix inequality. Here $\mathcal{S}^{n}$ denotes the set of $n$-by-$n$ symmetric matrices.
|
| 38 |
+
|
| 39 |
+
**Example.** An example of an SDP is to complete a covariance matrix $\tilde \Sigma \in \mathcal{S}^{n}_+$ with missing entries $M \subset \{1,\ldots,n\} \times \{1,\ldots,n\}$:
|
| 40 |
+
|
| 41 |
+
\[
|
| 42 |
+
\begin{array}{ll}
|
| 43 |
+
\text{minimize} & 0 \\
|
| 44 |
+
\text{subject to} & \Sigma_{ij} = \tilde \Sigma_{ij}, \quad (i,j) \notin M \\
|
| 45 |
+
& \Sigma \succeq 0,
|
| 46 |
+
\end{array}
|
| 47 |
+
\]
|
| 48 |
+
"""
|
| 49 |
+
)
|
| 50 |
+
return
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
@app.cell(hide_code=True)
|
| 54 |
+
def _(mo):
|
| 55 |
+
mo.md(
|
| 56 |
+
r"""
|
| 57 |
+
## Example
|
| 58 |
+
|
| 59 |
+
In the following code, we show how to specify and solve an SDP with CVXPY.
|
| 60 |
+
"""
|
| 61 |
+
)
|
| 62 |
+
return
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
@app.cell
|
| 66 |
+
def _():
|
| 67 |
+
import cvxpy as cp
|
| 68 |
+
import numpy as np
|
| 69 |
+
return cp, np
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
@app.cell
|
| 73 |
+
def _(np):
|
| 74 |
+
# Generate a random SDP.
|
| 75 |
+
n = 3
|
| 76 |
+
p = 3
|
| 77 |
+
np.random.seed(1)
|
| 78 |
+
C = np.random.randn(n, n)
|
| 79 |
+
A = []
|
| 80 |
+
b = []
|
| 81 |
+
for i in range(p):
|
| 82 |
+
A.append(np.random.randn(n, n))
|
| 83 |
+
b.append(np.random.randn())
|
| 84 |
+
return A, C, b, i, n, p
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
@app.cell
|
| 88 |
+
def _(A, C, b, cp, n, p):
|
| 89 |
+
# Create a symmetric matrix variable.
|
| 90 |
+
X = cp.Variable((n, n), symmetric=True)
|
| 91 |
+
|
| 92 |
+
# The operator >> denotes matrix inequality, with X >> 0 constraining X
|
| 93 |
+
# to be positive semidefinite
|
| 94 |
+
constraints = [X >> 0]
|
| 95 |
+
constraints += [cp.trace(A[i] @ X) == b[i] for i in range(p)]
|
| 96 |
+
prob = cp.Problem(cp.Minimize(cp.trace(C @ X)), constraints)
|
| 97 |
+
_ = prob.solve()
|
| 98 |
+
return X, constraints, prob
|
| 99 |
+
|
| 100 |
+
|
| 101 |
+
@app.cell
|
| 102 |
+
def _(X, mo, prob, wigglystuff):
|
| 103 |
+
mo.md(
|
| 104 |
+
f"""
|
| 105 |
+
The optimal value is {prob.value:0.4f}.
|
| 106 |
+
|
| 107 |
+
A solution for $X$ is (rounded to the nearest decimal) is:
|
| 108 |
+
|
| 109 |
+
{mo.ui.anywidget(wigglystuff.Matrix(X.value)).center()}
|
| 110 |
+
"""
|
| 111 |
+
)
|
| 112 |
+
return
|
| 113 |
+
|
| 114 |
+
|
| 115 |
+
@app.cell
|
| 116 |
+
def _():
|
| 117 |
+
import wigglystuff
|
| 118 |
+
return (wigglystuff,)
|
| 119 |
+
|
| 120 |
+
|
| 121 |
+
@app.cell
|
| 122 |
+
def _():
|
| 123 |
+
import marimo as mo
|
| 124 |
+
return (mo,)
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
if __name__ == "__main__":
|
| 128 |
+
app.run()
|
optimization/README.md
CHANGED
|
@@ -1,15 +1,13 @@
|
|
| 1 |
# Learn optimization
|
| 2 |
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
This collection of marimo notebooks teaches you the basics of mathematical
|
| 6 |
optimization.
|
| 7 |
|
| 8 |
After working through these notebooks, you'll understand how to create
|
| 9 |
and solve optimization problems using the Python library
|
| 10 |
[CVXPY](https://github.com/cvxpy/cvxpy), as well as how to apply what you've
|
| 11 |
learned to real-world problems such as portfolio allocation in finance,
|
| 12 |
-
|
| 13 |
|
| 14 |

|
| 15 |
|
|
|
|
| 1 |
# Learn optimization
|
| 2 |
|
| 3 |
+
This collection of marimo notebooks teaches you the basics of convex
|
|
|
|
|
|
|
| 4 |
optimization.
|
| 5 |
|
| 6 |
After working through these notebooks, you'll understand how to create
|
| 7 |
and solve optimization problems using the Python library
|
| 8 |
[CVXPY](https://github.com/cvxpy/cvxpy), as well as how to apply what you've
|
| 9 |
learned to real-world problems such as portfolio allocation in finance,
|
| 10 |
+
control of vehicles, and more.
|
| 11 |
|
| 12 |

|
| 13 |
|