5.6. Pyomo 的建模与优化

Pyomo 是基于 Python 开发的第三方开源建模语言,它支持对线性规划、混合整数规划、非线性规划等问题建模和分析,并调用其他商用或开源的求解器进行求解。

目前,MindOpt 支持在 Windows/Linux/OSX 系统中,通过 Pyomo 建立 线性规划模型 并调用 MindOpt 来求解。关于 Pyomo 的详细内容,请参考 Pyomo 官方文档

在本节中,我们将介绍如何使用 Pyomo API 来建立 线性规划问题示例 中的优化问题,并调用 MindOpt 求解。

5.6.1. 安装 Pyomo

用户首先必须安装 MindOpt。关于 MindOpt 的安装与配置请参考 单机版 MindOpt 安装MindOpt 安装后,用户可以通过以下 pip 的命令方式来安装 Pyomo:

pip install pyomo

关于 Pyomo 的详细安装方式,请参考 Pyomo Installation

5.6.2. 调用 Pyomo 接口文件

MindOpt 的 Pyomo 接口文件( mindopt_pyomo.py )定义了 Pyomo 调用 MindOpt 所需的相关接口。此接口文件继承自 Pyomo 的 DirectSolver 类别,实现代码则在安装包中:

<MDOHOME>\<VERSION>\<PLATFORM>\lib\pyomo\mindopt_pyomo.py

用户首先将该接口文件移到当前使用目录中,并在 Python 代码中导入该文件:

30from mindopt_pyomo import MindoDirect

接着,我们调用 Pyomo API 来建立 线性规划问题示例 中的优化问题。关于 Pyomo API 的详细说明,请参考 Pyomo 官方文档

41    # Define variables and constraints.
42    variable_names = ['x0', 'x1', 'x2', 'x3']
43    var_lb = {'x0':0, 'x1':0, 'x2':0, 'x3':0}
44    var_ub = {'x0':10, 'x1':None, 'x2':None, 'x3':None}
45    objective_coeff = {'x0': 1, 'x1': 1, 'x2': 1, 'x3': 1}
46    constraint_names = ['c0', 'c1']
47    constraint_bound = {'c0': 1, 'c1': 1}
48    constraint_coeff = {('x0', 'c0'): 1, ('x1', 'c0'): 1, ('x2', 'c0'): 2, ('x3', 'c0'): 3,
49                        ('x0', 'c1'): 1, ('x1', 'c1'): -1, ('x2', 'c1'): 0, ('x3', 'c1'): 6}
50
51    # Create model.
52    model = ConcreteModel(name="ex1")
53
54    # Build decision variables.
55    model.Set = Set(initialize=variable_names)
56    model.Variable = Var(model.Set, within=NonNegativeReals, bounds=fb)
57
58    # Objective.
59    model.obj = Objective(expr=sum(objective_coeff[var_name] * model.Variable[var_name] for var_name in variable_names), sense=minimize)
60
61    # Constraints.
62    model.dual = Suffix(direction=Suffix.IMPORT)
63    model.cons1 = Constraint(expr = ConstraintsRule(model, 'c0') >= constraint_bound['c0'])
64    model.cons2 = Constraint(expr = ConstraintsRule(model, 'c1') == constraint_bound['c1'])

求解前,我们指定使用 MindOpt 求解器,并对求解的相关参数进行设置(求解器参数数请查阅 可选输入参数):

69    # Solve problem by MindOpt solver.
70    opt = SolverFactory("mindo_direct")
71    
72    # Set options.
73    opt.options['Method'] = -1
74    opt.options['IPM/PrimalTolerance'] = 1e-10

最后,调用 Pyomo 的求解函数 solve() 进行求解,并获取相关的结果:

79    # Solve.
80    results = opt.solve(model)
81
82    # Summary of result.
83    results.write()
84
85    if (results.solver.status == SolverStatus.ok) and (results.solver.termination_condition == TerminationCondition.optimal):
86        print("The solution is optimal and feasible.")
87        model.Variable.display()
88        model.dual.display()
89        model.obj.display()
90    elif (results.solver.termination_condition == TerminationCondition.infeasible):
91        print("The model is infeasible.")
92        print("Solver Status: ",  results.solver.status)
93    else:
94        print("Something else is wrong.")
95        print("Solver Status: ",  results.solver.status)

5.6.3. 建模示例: mdo_pyomo_lo_ex1

mdo_pyomo_lo_ex1.py 中提供了完整代码:

 1"""
 2/**
 3 *  Description
 4 *  -----------
 5 *
 6 *  Linear optimization.
 7 *
 8 *  Formulation
 9 *  -----------
10 *
11 *  Minimize
12 *    obj: 1 x0 + 1 x1 + 1 x2 + 1 x3
13 *  Subject To
14 *   c1 : 1 x0 + 1 x1 + 2 x2 + 3 x3 >= 1
15 *   c2 : 1 x0 - 1 x2        + 6 x3 == 1
16 *  Bounds
17 *    0 <= x0 <= 10
18 *    0 <= x1
19 *    0 <= x2
20 *    0 <= x3
21 *  End
22 */
23"""
24
25from pyomo.environ import *
26from pyomo.core.base.util import Initializer
27from pyomo.opt import SolverFactory
28from pyomo.opt import SolverStatus, TerminationCondition
29
30from mindopt_pyomo import MindoDirect
31from mindoptpy import *
32
33def ConstraintsRule(model, p):
34    return sum(constraint_coeff[i, p] * model.Variable[i] for i in variable_names)
35
36def fb(model, i):
37    return (var_lb[i], var_ub[i])
38
39if __name__ == '__main__':
40
41    # Define variables and constraints.
42    variable_names = ['x0', 'x1', 'x2', 'x3']
43    var_lb = {'x0':0, 'x1':0, 'x2':0, 'x3':0}
44    var_ub = {'x0':10, 'x1':None, 'x2':None, 'x3':None}
45    objective_coeff = {'x0': 1, 'x1': 1, 'x2': 1, 'x3': 1}
46    constraint_names = ['c0', 'c1']
47    constraint_bound = {'c0': 1, 'c1': 1}
48    constraint_coeff = {('x0', 'c0'): 1, ('x1', 'c0'): 1, ('x2', 'c0'): 2, ('x3', 'c0'): 3,
49                        ('x0', 'c1'): 1, ('x1', 'c1'): -1, ('x2', 'c1'): 0, ('x3', 'c1'): 6}
50
51    # Create model.
52    model = ConcreteModel(name="ex1")
53
54    # Build decision variables.
55    model.Set = Set(initialize=variable_names)
56    model.Variable = Var(model.Set, within=NonNegativeReals, bounds=fb)
57
58    # Objective.
59    model.obj = Objective(expr=sum(objective_coeff[var_name] * model.Variable[var_name] for var_name in variable_names), sense=minimize)
60
61    # Constraints.
62    model.dual = Suffix(direction=Suffix.IMPORT)
63    model.cons1 = Constraint(expr = ConstraintsRule(model, 'c0') >= constraint_bound['c0'])
64    model.cons2 = Constraint(expr = ConstraintsRule(model, 'c1') == constraint_bound['c1'])
65
66    # Print formulation of model.
67    model.pprint()
68
69    # Solve problem by MindOpt solver.
70    opt = SolverFactory("mindo_direct")
71    
72    # Set options.
73    opt.options['Method'] = -1
74    opt.options['IPM/PrimalTolerance'] = 1e-10
75    
76    # Solve.
77    results = opt.solve(model)
78
79    # Summary of result.
80    results.write()
81
82    if (results.solver.status == SolverStatus.ok) and (results.solver.termination_condition == TerminationCondition.optimal):
83        print("The solution is optimal and feasible.")
84        model.Variable.display()
85        model.dual.display()
86        model.obj.display()
87    elif (results.solver.termination_condition == TerminationCondition.infeasible):
88        print("The model is infeasible.")
89        print("Solver Status: ",  results.solver.status)
90    else:
91        print("Something else is wrong.")
92        print("Solver Status: ",  results.solver.status)

其他 Pyomo 的示例请参考 Pyomo Gallery