File size: 3,006 Bytes
28ec558
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8646a4e
 
 
 
 
 
28ec558
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# /// script
# requires-python = ">=3.13"
# dependencies = [
#     "cvxpy==1.6.0",
#     "marimo",
#     "numpy==2.2.2",
#     "wigglystuff==0.1.9",
# ]
# ///

import marimo

__generated_with = "0.11.2"
app = marimo.App()


@app.cell
def _():
    import marimo as mo
    return (mo,)


@app.cell(hide_code=True)
def _(mo):
    mo.md(r"""# Semidefinite program""")
    return


@app.cell(hide_code=True)
def _(mo):
    mo.md(
        r"""
        _This notebook introduces an advanced topic._ A semidefinite program (SDP) is an optimization problem of the form

        \[
            \begin{array}{ll}
            \text{minimize}   & \mathbf{tr}(CX) \\
            \text{subject to} & \mathbf{tr}(A_iX) = b_i, \quad i=1,\ldots,p \\
                              & X \succeq 0,
            \end{array}
        \]

        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.

        **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\}$:

        \[
            \begin{array}{ll}
            \text{minimize}   & 0 \\
            \text{subject to} & \Sigma_{ij} = \tilde \Sigma_{ij}, \quad (i,j) \notin M \\
                              & \Sigma \succeq 0,
            \end{array}
        \]
        """
    )
    return


@app.cell(hide_code=True)
def _(mo):
    mo.md(
        r"""
        ## Example

        In the following code, we show how to specify and solve an SDP with CVXPY.
        """
    )
    return


@app.cell
def _():
    import cvxpy as cp
    import numpy as np
    return cp, np


@app.cell
def _(np):
    # Generate a random SDP.
    n = 3
    p = 3
    np.random.seed(1)
    C = np.random.randn(n, n)
    A = []
    b = []
    for i in range(p):
        A.append(np.random.randn(n, n))
        b.append(np.random.randn())
    return A, C, b, i, n, p


@app.cell
def _(A, C, b, cp, n, p):
    # Create a symmetric matrix variable.
    X = cp.Variable((n, n), symmetric=True)

    # The operator >> denotes matrix inequality, with X >> 0 constraining X
    # to be positive semidefinite
    constraints = [X >> 0]
    constraints += [cp.trace(A[i] @ X) == b[i] for i in range(p)]
    prob = cp.Problem(cp.Minimize(cp.trace(C @ X)), constraints)
    _ = prob.solve()
    return X, constraints, prob


@app.cell
def _(X, mo, prob, wigglystuff):
    mo.md(
        f"""
        The optimal value is {prob.value:0.4f}.

        A solution for $X$ is (rounded to the nearest decimal) is: 
        
        {mo.ui.anywidget(wigglystuff.Matrix(X.value)).center()}
        """
    )
    return


@app.cell
def _():
    import wigglystuff
    return (wigglystuff,)


if __name__ == "__main__":
    app.run()