# Pyomo接口

Pyomo 是基于Python编程语言的开源优化建模语言， 它提供了丰富的优化相关功能，并已被许多研究人员用于解决复杂的实际应用问题，感兴趣的用户可以查看 谁在使用Pyomo? 了解更多信息。本章介绍了如何在 Pyomo环境下使用杉数求解器。

## 安装说明

### 使用conda安装

```conda install -c conda-forge pyomo
```

Pyomo也集成了一些可选的第三方Python包扩展其优化相关功能，可通过如下命令进行安装：

```conda install -c conda-forge pyomo.extras
```

### 使用pip安装

```pip install pyomo
```

## 使用示例

### 抽象模型

Pyomo主要提供了两种方式对其支持的各种问题类型进行建模，本部分将介绍使用抽象模型求解上述问题的方式。

``` 1# The code is adopted from:
2#
3# https://github.com/Pyomo/pyomo/blob/master/examples/pyomo/amplbook2/diet.py
4#
5# with some modification by developer of the Cardinal Optimizer
6
7from pyomo.core import *
8
9model = AbstractModel()
10
11model.NUTR = Set()
12model.FOOD = Set()
13
14model.cost  = Param(model.FOOD, within=NonNegativeReals)
15model.f_min = Param(model.FOOD, within=NonNegativeReals)
16
17model.f_max = Param(model.FOOD)
18model.n_min = Param(model.NUTR, within=NonNegativeReals)
19model.n_max = Param(model.NUTR)
20model.amt   = Param(model.NUTR, model.FOOD, within=NonNegativeReals)
21
23  return (model.f_min[i], model.f_max[i])
25
26def Objective_rule(model):
28model.totalcost = Objective(rule=Objective_rule, sense=minimize)
29
30def Diet_rule(model, i):
31  expr = 0
32
33  for j in model.FOOD:
34    expr = expr + model.amt[i, j] * model.Buy[j]
35
36  return (model.n_min[i], expr, model.n_max[i])
37model.Diet = Constraint(model.NUTR, rule=Diet_rule)
```

``` 1# The data is adopted from:
2#
3# https://github.com/Pyomo/pyomo/blob/master/examples/pyomo/amplbook2/diet.dat
4#
5# with some modification by developer of the Cardinal Optimizer
6
7data;
8
9set NUTR := A B1 B2 C ;
10set FOOD := BEEF CHK FISH HAM MCH MTL SPG TUR ;
11
12param:   cost  f_min  f_max :=
13  BEEF   3.19    0     100
14  CHK    2.59    0     100
15  FISH   2.29    0     100
16  HAM    2.89    0     100
17  MCH    1.89    0     100
18  MTL    1.99    0     100
19  SPG    1.99    0     100
20  TUR    2.49    0     100 ;
21
22param:   n_min  n_max :=
23   A      700   10000
24   C      700   10000
25   B1     700   10000
26   B2     700   10000 ;
27
28param amt (tr):
29           A    C   B1   B2 :=
30   BEEF   60   20   10   15
31   CHK     8    0   20   20
32   FISH    8   10   15   10
33   HAM    40   40   35   10
34   MCH    15   35   15   15
35   MTL    70   30   15   15
36   SPG    25   50   25   15
37   TUR    60   20   15   10 ;
```

```pyomo solve --solver=coptampl pydiet_abstract.py pydiet_abstract.dat
```

```[    0.00] Setting up Pyomo environment
[    0.00] Applying Pyomo preprocessing actions
[    0.00] Creating model
[    0.01] Applying solver
[    0.05] Processing results
Number of solutions: 1
Solution Information
Gap: None
Status: optimal
Function Value: 88.19999999999999
Solver results file: results.yml
[    0.05] Applying Pyomo postprocessing actions
[    0.05] Pyomo Finished
```

```# ==========================================================
# = Solver Results                                         =
# ==========================================================
# ----------------------------------------------------------
#   Problem Information
# ----------------------------------------------------------
Problem:
- Lower bound: -inf
Upper bound: inf
Number of objectives: 1
Number of constraints: 4
Number of variables: 8
Sense: unknown
# ----------------------------------------------------------
#   Solver Information
# ----------------------------------------------------------
Solver:
- Status: ok
Message: COPT-AMPL\x3a optimal solution; objective 88.2, iterations 1
Termination condition: optimal
Id: 0
Error rc: 0
Time: 0.03171110153198242
# ----------------------------------------------------------
#   Solution Information
# ----------------------------------------------------------
Solution:
- number of solutions: 1
number of solutions displayed: 1
- Gap: None
Status: optimal
Message: COPT-AMPL\x3a optimal solution; objective 88.2, iterations 1
Objective:
totalcost:
Value: 88.19999999999999
Variable:
Value: 46.666666666666664
Constraint: No values
```

### 具象模型

```  1# The code is adopted from:
2#
3# https://github.com/Pyomo/pyomo/blob/master/examples/pyomo/amplbook2/diet.py
4#
5# with some modification by developer of the Cardinal Optimizer
6
7from __future__ import print_function, division
8
9import pyomo.environ as pyo
10import pyomo.opt as pyopt
11
12from copt_pyomo import *
13
14# Nutrition set
15NUTR = ["A", "C", "B1", "B2"]
16# Food set
17FOOD = ["BEEF", "CHK", "FISH", "HAM", "MCH", "MTL", "SPG", "TUR"]
18
19# Price of foods
20cost = {"BEEF": 3.19, "CHK": 2.59, "FISH": 2.29, "HAM": 2.89, "MCH": 1.89,
21        "MTL":  1.99, "SPG": 1.99, "TUR":  2.49}
22# Nutrition of foods
23amt = {"BEEF": {"A": 60, "C": 20, "B1": 10, "B2": 15},
24       "CHK":  {"A": 8,  "C": 0,  "B1": 20, "B2": 20},
25       "FISH": {"A": 8,  "C": 10, "B1": 15, "B2": 10},
26       "HAM":  {"A": 40, "C": 40, "B1": 35, "B2": 10},
27       "MCH":  {"A": 15, "C": 35, "B1": 15, "B2": 15},
28       "MTL":  {"A": 70, "C": 30, "B1": 15, "B2": 15},
29       "SPG":  {"A": 25, "C": 50, "B1": 25, "B2": 15},
30       "TUR":  {"A": 60, "C": 20, "B1": 15, "B2": 10}}
31
32# The "diet problem" using ConcreteModel
33model = pyo.ConcreteModel()
34
35model.NUTR = pyo.Set(initialize=NUTR)
36model.FOOD = pyo.Set(initialize=FOOD)
37
38model.cost = pyo.Param(model.FOOD, initialize=cost)
39
40def amt_rule(model, i, j):
41  return amt[i][j]
42model.amt  = pyo.Param(model.FOOD, model.NUTR, initialize=amt_rule)
43
44model.f_min = pyo.Param(model.FOOD, default=0)
45model.f_max = pyo.Param(model.FOOD, default=100)
46
47model.n_min = pyo.Param(model.NUTR, default=700)
48model.n_max = pyo.Param(model.NUTR, default=10000)
49
51  return (model.f_min[i], model.f_max[i])
53
54def Objective_rule(model):
56model.totalcost = pyo.Objective(rule=Objective_rule, sense=pyo.minimize)
57
58def Diet_rule(model, j):
59  expr = 0
60
61  for i in model.FOOD:
62    expr = expr + model.amt[i, j] * model.buy[i]
63
64  return (model.n_min[j], expr, model.n_max[j])
65model.Diet = pyo.Constraint(model.NUTR, rule=Diet_rule)
66
67# Reduced costs of variables
68model.rc = pyo.Suffix(direction=pyo.Suffix.IMPORT)
69
70# Activities and duals of constraints
71model.slack = pyo.Suffix(direction=pyo.Suffix.IMPORT)
72model.dual = pyo.Suffix(direction=pyo.Suffix.IMPORT)
73
74# Use 'copt_direct' solver to solve the problem
75solver = pyopt.SolverFactory('copt_direct')
76
77# Use 'copt_persistent' solver to solve the problem
78# solver = pyopt.SolverFactory('copt_persistent')
79# solver.set_instance(model)
80
81results = solver.solve(model, tee=True)
82
83# Check result
84print("")
85if results.solver.status == pyopt.SolverStatus.ok and \
86   results.solver.termination_condition == pyopt.TerminationCondition.optimal:
87  print("Optimal solution found")
88else:
89  print("Something unexpected happened: ", str(results.solver))
90
91print("")
92print("Optimal objective value:")
93print("  totalcost: {0:6f}".format(pyo.value(model.totalcost)))
94
95print("")
96print("Variables solution:")
97for i in FOOD:
98  print("  buy[{0:4s}] = {1:9.6f} (rc: {2:9.6f})".format(i, \
101
102print("")
103print("Constraint solution:")
104for i in NUTR:
105  print("  diet[{0:2s}] = {1:12.6f} (dual: {2:9.6f})".format(i, \
106                                                      model.slack[model.Diet[i]], \
107                                                      model.dual[model.Diet[i]]))
```

```python pydiet_concrete.py
```

```Optimal solution found
Objective:
totalcost: 88.200000
Variables: