Skip to content

Commit 20826a7

Browse files
authored
Merge pull request #28 from marimo-team/aka/optimization-dcp
optimization: dcp, sdp
2 parents f40980f + 28ec558 commit 20826a7

File tree

3 files changed

+220
-4
lines changed

3 files changed

+220
-4
lines changed
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
# Learn optimization
22

3-
🚧 _This collection is a work in progress. Check back later for new notebooks!_
4-
5-
This collection of marimo notebooks teaches you the basics of mathematical
3+
This collection of marimo notebooks teaches you the basics of convex
64
optimization.
75

86
After working through these notebooks, you'll understand how to create
97
and solve optimization problems using the Python library
108
[CVXPY](https://github.com/cvxpy/cvxpy), as well as how to apply what you've
119
learned to real-world problems such as portfolio allocation in finance,
12-
resource allocation, and more.
10+
control of vehicles, and more.
1311

1412
![SpaceX](https://www.debugmind.com/wp-content/uploads/2020/01/spacex-1.jpg)
1513

0 commit comments

Comments
 (0)