5.4.5. Python 的SDP建模与优化

在本节中,我们将使用 MindOptPython API 来建模以及求解 半定规划问题示例 中的问题。

5.4.5.1. SDP示例1

首先,需要引入 Python 包:

26from mindoptpy import *

第一步:创建优化模型:

先建立一空的 MindOpt 模型。

31    # Step 1. Create a model.
32    model = Model()

第二步:SDP模型输入

通过 Model.addPsdVar(),新增维度为 \(3\times3\) 的半正定矩阵变量 \(\mathbf{X}\)

36        # Add a PSD matrix variable.
37        X = model.addPsdVar(dim=3, name="X")

输入目标函数的系数矩阵 \(\mathbf{C}\)。 并且通过 Model.setObjective() 的第一个参数,设置模型的目标函数, 以及通过第二个参数,设定优化方向为最大化。

40        C = np.array([[-3, 0, 1], [0, -2, 0], [1, 0, -3]])
41        objective = C * X
42        model.setObjective(objective, MDO.MAXIMIZE)

接着,我们输入约束系数矩阵 \(\mathbf{A}\),以及通过 Model.addConstr(),新增模型的约束。

44        # Input the constraint.
45        A = np.array([[3, 0, 1], [0, 4, 0], [1, 0, 5]])
46        model.addConstr(A * X == 1, "c0")

第三步:求解SDP模型

模型输入后,我们便可以通过调用 Model.optimize() 求解问题。

49        model.optimize()

接下来我们可以取得最优的的目标函数值。

52            # Display objective.
53            print("Objective: " + str(objective.getValue()))

最后,我们呈现 \(\mathbf{X}\) 半正定矩阵变量的数值解。

55            # Display the solution.
56            print("X = ")
57            print(X.PsdX)

第四步:释放模型对应的资源

68        # Step 4. Free the model.
69        model.dispose()

文件链接 mdo_sdo_ex1.py 提供了完整源代码:

 1"""
 2/**
 3 *  Description
 4 *  -----------
 5 *
 6 *  Semidefinite optimization (row-wise input).
 7 *
 8 *  Formulation
 9 *  -----------
10 *
11 *  Maximize
12 *  obj: 
13 *    tr(C X)
14 *  Subject To
15 *    c0 : tr(A X) = 1
16 *  Bounds
17 *    X is p.s.d.
18 *
19 *  Matrix
20 *    C = [ -3  0  1 ]  A = [ 3 0 1 ]
21 *        [  0 -2  0 ]      [ 0 4 0 ]
22 *        [  1  0 -3 ]      [ 1 0 5 ]
23 *  End
24 */
25 """
26from mindoptpy import *
27import numpy as np
28
29if __name__ == "__main__":
30
31    # Step 1. Create a model.
32    model = Model()
33
34    try:
35        # Step 2. Input model.
36        # Add a PSD matrix variable.
37        X = model.addPsdVar(dim=3, name="X")
38
39        # Set objective.
40        C = np.array([[-3, 0, 1], [0, -2, 0], [1, 0, -3]])
41        objective = C * X
42        model.setObjective(objective, MDO.MAXIMIZE)
43
44        # Input the constraint.
45        A = np.array([[3, 0, 1], [0, 4, 0], [1, 0, 5]])
46        model.addConstr(A * X == 1, "c0")
47
48        # Step 3. Solve the problem and display the result.
49        model.optimize()
50
51        if model.status == MDO.OPTIMAL:
52            # Display objective.
53            print("Objective: " + str(objective.getValue()))
54        
55            # Display the solution.
56            print("X = ")
57            print(X.PsdX)
58        else:
59            print("No feasible solution.")
60    except MdoError as e:
61        print("Received Mindopt exception.")
62        print(" - Code          : {}".format(e.errno))
63        print(" - Reason        : {}".format(e.message))
64    except Exception as e:
65        print("Received exception.")
66        print(" - Reason        : {}".format(e))
67    finally:
68        # Step 4. Free the model.
69        model.dispose()

5.4.5.2. SDP示例2

首先,需要引入 Python 包:

32from mindoptpy import *

第一步:创建MindOpt模型

先建立一空的 MindOpt 模型。

38    # Step 1. Create a model.
39    model = Model()

第二步:SDP模型输入

通过 Model.addVar(),新增两个非负变量 \(x_0\)\(x_1\)

43        # Add nonnegative scalar variables.
44        x0 = model.addVar(lb=0.0, name="x0")
45        x1 = model.addVar(lb=0.0, name="x1")

通过 Model.addPsdVar(),新增两个维度分别为 \(2\times 2\)\(3\times 3\) 的 两个半正定矩阵变量 \(\mathbf{X}_0\)\(\mathbf{X}_1\)

47        # Add PSD matrix variables.
48        X0 = model.addPsdVar(dim = 2, name = "X0")
49        X1 = model.addPsdVar(dim = 3, name = "X1")

输入目标函数的系数矩阵 \(\mathbf{C}_0\)\(\mathbf{C}_1\)。 并且通过 Model.setObjective() 的第一个参数,设置模型的目标函数, 以及通过第二个参数,设定优化方向为最大化。

51        # Set objective
52        C0 = np.array([[2, 1], [1, 2]])
53        C1 = np.array([[3, 0, 1], [0, 2, 0], [1, 0, 3]])
54        objective = C0 * X0 + C1 * X1
55        model.setObjective(objective, MDO.MAXIMIZE)

接着,我们输入第一个约束的系数矩阵 \(\mathbf{A}_{00}\),并且通过 Model.addConstr(),新增第一个约束。

57        # Input the first constraint.
58        A00 = np.array([[3, 1], [1, 3]])
59        model.addConstr(A00 * X0 + x0 == 1, "c0")

接着,我们输入第二个约束的系数矩阵 \(\mathbf{A}_{11}\),并且通过 Model.addConstr(),新增第一个约束。

61        # Input the second constraint.
62        A11 = np.array([[3, 0, 1], [0, 4, 0], [1, 0, 5]])
63        model.addConstr(A11 * X1 + x1 == 2, "c1")

第三步:求解SDP模型

模型输入后,我们便可以通过调用 Model.optimize() 求解问题。

66        model.optimize()

接下来我们可以取得最优的的目标函数值。

69            # Display objective.
70            print("Objective: " + str(objective.getValue()))

最后,我们呈现所有变量的数值解。

72            # Display the solution.
73            print("x0 = " + " {0:7.6f}".format(x0.X))
74            print("x1 = " + " {0:7.6f}".format(x1.X))
75            print("X0 = ")
76            print(X0.PsdX)
77            print("X1 = ")
78            print(X1.PsdX)

第四步:释放模型对应的资源

89        # Step 4. Free the model.
90        model.dispose()

文件链接 mdo_sdo_ex2.py 提供了完整源代码:

 1"""
 2/**
 3 *  Description
 4 *  -----------
 5 *
 6 *  Semidefinite optimization (row-wise input).
 7 *
 8 *  Formulation
 9 *  -----------
10 *
11 *  Maximize
12 *  obj: 
13 *   tr(C0 X0)   + tr(C1 X1)    + 0 x0 + 0 x1
14 *  Subject To
15 *   c0 : tr(A00 X0)                + 1 x0        = 1
16 *   c1 :              tr(A11 X1)          + 1 x1 = 2
17 *  Bounds
18 *    0 <= x0
19 *    0 <= x1
20 *    X0,X1 are p.s.d.
21 *
22 *  Matrix
23 *    C0 =  [ 2 1 ]   A00 = [ 3 1 ]
24 *          [ 1 2 ]         [ 1 3 ]
25 *
26 *    C1 = [ 3 0 1 ]  A11 = [ 3 0 1 ]
27 *         [ 0 2 0 ]        [ 0 4 0 ]
28 *         [ 1 0 3 ]        [ 1 0 5 ]
29 *  End
30 */
31 """
32from mindoptpy import *
33import numpy as np
34
35
36if __name__ == "__main__":
37
38    # Step 1. Create a model.
39    model = Model()
40
41    try:
42        # Step 2. Input model.
43        # Add nonnegative scalar variables.
44        x0 = model.addVar(lb=0.0, name="x0")
45        x1 = model.addVar(lb=0.0, name="x1")
46        
47        # Add PSD matrix variables.
48        X0 = model.addPsdVar(dim = 2, name = "X0")
49        X1 = model.addPsdVar(dim = 3, name = "X1")
50        
51        # Set objective
52        C0 = np.array([[2, 1], [1, 2]])
53        C1 = np.array([[3, 0, 1], [0, 2, 0], [1, 0, 3]])
54        objective = C0 * X0 + C1 * X1
55        model.setObjective(objective, MDO.MAXIMIZE)
56        
57        # Input the first constraint.
58        A00 = np.array([[3, 1], [1, 3]])
59        model.addConstr(A00 * X0 + x0 == 1, "c0")
60        
61        # Input the second constraint.
62        A11 = np.array([[3, 0, 1], [0, 4, 0], [1, 0, 5]])
63        model.addConstr(A11 * X1 + x1 == 2, "c1")
64        
65        # Step 3. Solve the problem and display the result.
66        model.optimize()
67          
68        if model.status == MDO.OPTIMAL:
69            # Display objective.
70            print("Objective: " + str(objective.getValue()))
71
72            # Display the solution.
73            print("x0 = " + " {0:7.6f}".format(x0.X))
74            print("x1 = " + " {0:7.6f}".format(x1.X))
75            print("X0 = ")
76            print(X0.PsdX)
77            print("X1 = ")
78            print(X1.PsdX)
79        else:
80            print("No feasible solution.")
81    except MdoError as e:
82        print("Received Mindopt exception.")
83        print(" - Code          : {}".format(e.errno))
84        print(" - Reason        : {}".format(e.message))
85    except Exception as e:
86        print("Received exception.")
87        print(" - Reason        : {}".format(e))
88    finally:
89        # Step 4. Free the model.
90        model.dispose()