Pyomo AbstractModel 和 Python 字典
Pyomo AbstractModel and Python Dictionaries
我是 Pyomo 的新手,我从一些小例子开始,通过理解和测试它们。现在我想使用 Python 字典重写一个更复杂的示例我想重写的示例来自 Pyomo Gallery:
https://nbviewer.jupyter.org/github/Pyomo/PyomoGallery/blob/master/diet/DietProblem.ipynb
作为如何使用 Python 词典与 pyomo 的示例,我采用了以下内容:
https://pyomo.readthedocs.io/en/stable/working_abstractmodels/data/raw_dicts.html
自从我开始的两天以来,我一直在围绕移动索引盘旋字典,并希望我的重新实现能够工作,但我只是不知道正确的方法是什么。为什么当前的方法不起作用。有时我改变了一些关于字典结构的东西并收到了不同的错误消息,然后我继续下一个并且(解决它,或者只是改变它)并且旧的再次弹出。
我只是提供我目前的状态,非常感谢您的帮助。一个可行的解决方案可能会帮助我理解如何使用 Python 字典对数据建模。
from __future__ import division
import pyomo.environ as pyo
from pyomo.opt import SolverFactory
from math import inf
food_keys = ['Cheeseburger', 'Ham Sandwich', 'Hamburger', 'Fish Sandwich', 'Chicken Sandwich', 'Fries', 'Sausage Biscuit', 'Lowfat Milk', 'Orange Juice']
cost_vol_keys = ['c', 'V']
cost_vol = [[1.84, 4.0], [2.19, 7.5], [1.84, 3.5], [1.44, 5.0], [2.29, 7.3], [.77, 2.6], [1.29, 4.1], [.60, 8.0], [.72, 12.0]]
F = {food_keys[i]:
{cost_vol_keys[j]:
cost_vol[i][j]
for j in range(len(cost_vol_keys))}
for i in range(len(food_keys))}
nutrition_keys = ['Cal', 'Carbo Protein', 'VitA', 'VitC', 'Calc', 'Iron']
nutrition_req_keys = ['Nmin', 'Nmax']
nutrition_req = [
[2000, None],
[ 350, 375],
[ 55, None],
[ 100, None],
[ 100, None],
[ 100, None],
[ 100, None]
]
N = {nutrition_keys[i]:
{nutrition_req_keys[j]:
nutrition_req[i][j]
for j in range(len(nutrition_req_keys))}
for i in range(len(nutrition_keys))}
Vmax = 75.0
nutrition = [
[510, 34, 28, 15, 6, 30, 20],
[370, 35, 24, 15, 10, 20, 20],
[500, 42, 25, 6, 2, 25, 20],
[370, 38, 14, 2, 0, 15, 10],
[400, 42, 31, 8, 15, 15, 8],
[220, 26, 3, 0, 15, 0, 2],
[345, 27, 15, 4, 0, 20, 15],
[110, 12, 9, 10, 4, 30, 0],
[ 80, 20, 1, 2, 120, 2, 2]
]
a = {(food_keys[i], nutrition_keys[j]): nutrition[i][j]
for j in range(len(nutrition_keys))
for i in range(len(food_keys))}
data = {None: {
'F': {None: F},
'N': {None: N},
'a': a,
'Vmax': {None: Vmax},
}}
model = pyo.AbstractModel()
solver = 'gurobi'
solver_io = 'python'
stream_solver = False # True prints solver output to screen
keepfiles = False # True prints intermediate file names (.nl,.sol,...)
opt = SolverFactory(solver, solver_io = solver_io)
opt.options['outlev'] = 1 # tell gurobi to be verbose with output
opt.options['solnsens'] = 1
opt.options['bestbound'] = 1
# Foods
model.F = pyo.Set()
# Nutrients
model.N = pyo.Set()
# Cost of each food
model.c = pyo.Param(model.F, within = pyo.PositiveReals)
# Amount of nutrient in each food
model.a = pyo.Param(model.F, model.N, within = pyo.NonNegativeReals)
# Lower and upper bound on each nutrient
model.Nmin = pyo.Param(model.N, within = pyo.NonNegativeReals, default = 0.0)
model.Nmax = pyo.Param(model.N, within = pyo.NonNegativeReals, default = inf)
# Volume per serving of food
model.V = pyo.Param(model.F, within = pyo.PositiveReals)
# Maximum volume of food consumed
model.Vmax = pyo.Param(within = pyo.PositiveReals)
# Number of servings consumed of each food
model.x = pyo.Var(model.F, within = pyo.NonNegativeIntegers)
# Minimize the cost of food that is consumed
def cost_rule(model):
return sum(model.c[i] * model.x[i] for i in model.F)
model.cost = pyo.Objective(rule = cost_rule)
# Limit nutrient consumption for each nutrient
def nutrient_rule(model, j):
value = sum(model.a[i, j] * model.x[i] for i in model.F)
return pyo.inequality(model.Nmin[j], value, model.Nmax[j])
model.nutrient_limit = pyo.Constraint(model.N, rule = nutrient_rule)
# Limit the volume of food consumed
def volume_rule(model):
return sum(model.V[i] * model.x[i] for i in model.F) <= model.Vmax
model.volume = pyo.Constraint(rule = volume_rule)
model_instance = model.create_instance(data)
model_instance.pprint()
results = opt.solve(model_instance, keepfiles = keepfiles, tee = stream_solver)
你 运行 遇到了问题,因为你要求 pyomo 阅读你的字典 就好像 它们是一个 .dat 文件,就像你引用的例子一样。它不能那样做。它可以读取具有由同一键集索引的多个项目的多列 .dat 文件,但(据我所知)不能从 python 字典中执行相同的操作。所以你有几个选择...
分解你的字典,并有 个人 的成本,价值等。这应该是一个微不足道的修复,然后更新你的 data
型号。
只需像您引用的示例那样将您的数据填充到一个单独的 .dat 文件中,就可以了
换档 ConcreteModel()
并忘记保持模型和数据分离。 Python 非常擅长整理文件和数据表,所以我几乎总是选择让 python 整理,然后根据创建的词典制作 ConcreteModel()
。在不更改任何词典的情况下,您可以这样做:
model = pyo.ConcreteModel('chow time')
# Foods
model.F = pyo.Set(initialize=F.keys())
# Nutrients
model.N = pyo.Set(initialize=N.keys())
# Cost of each food
model.c = pyo.Param(model.F, within = pyo.PositiveReals, initialize = {k:v['c'] for k,v in F.items()})
# Volume per serving of food
model.V = pyo.Param(model.F, within = pyo.PositiveReals, initialize = {k:v['V'] for k,v in F.items()})
我是 Pyomo 的新手,我从一些小例子开始,通过理解和测试它们。现在我想使用 Python 字典重写一个更复杂的示例我想重写的示例来自 Pyomo Gallery:
https://nbviewer.jupyter.org/github/Pyomo/PyomoGallery/blob/master/diet/DietProblem.ipynb
作为如何使用 Python 词典与 pyomo 的示例,我采用了以下内容:
https://pyomo.readthedocs.io/en/stable/working_abstractmodels/data/raw_dicts.html
自从我开始的两天以来,我一直在围绕移动索引盘旋字典,并希望我的重新实现能够工作,但我只是不知道正确的方法是什么。为什么当前的方法不起作用。有时我改变了一些关于字典结构的东西并收到了不同的错误消息,然后我继续下一个并且(解决它,或者只是改变它)并且旧的再次弹出。
我只是提供我目前的状态,非常感谢您的帮助。一个可行的解决方案可能会帮助我理解如何使用 Python 字典对数据建模。
from __future__ import division
import pyomo.environ as pyo
from pyomo.opt import SolverFactory
from math import inf
food_keys = ['Cheeseburger', 'Ham Sandwich', 'Hamburger', 'Fish Sandwich', 'Chicken Sandwich', 'Fries', 'Sausage Biscuit', 'Lowfat Milk', 'Orange Juice']
cost_vol_keys = ['c', 'V']
cost_vol = [[1.84, 4.0], [2.19, 7.5], [1.84, 3.5], [1.44, 5.0], [2.29, 7.3], [.77, 2.6], [1.29, 4.1], [.60, 8.0], [.72, 12.0]]
F = {food_keys[i]:
{cost_vol_keys[j]:
cost_vol[i][j]
for j in range(len(cost_vol_keys))}
for i in range(len(food_keys))}
nutrition_keys = ['Cal', 'Carbo Protein', 'VitA', 'VitC', 'Calc', 'Iron']
nutrition_req_keys = ['Nmin', 'Nmax']
nutrition_req = [
[2000, None],
[ 350, 375],
[ 55, None],
[ 100, None],
[ 100, None],
[ 100, None],
[ 100, None]
]
N = {nutrition_keys[i]:
{nutrition_req_keys[j]:
nutrition_req[i][j]
for j in range(len(nutrition_req_keys))}
for i in range(len(nutrition_keys))}
Vmax = 75.0
nutrition = [
[510, 34, 28, 15, 6, 30, 20],
[370, 35, 24, 15, 10, 20, 20],
[500, 42, 25, 6, 2, 25, 20],
[370, 38, 14, 2, 0, 15, 10],
[400, 42, 31, 8, 15, 15, 8],
[220, 26, 3, 0, 15, 0, 2],
[345, 27, 15, 4, 0, 20, 15],
[110, 12, 9, 10, 4, 30, 0],
[ 80, 20, 1, 2, 120, 2, 2]
]
a = {(food_keys[i], nutrition_keys[j]): nutrition[i][j]
for j in range(len(nutrition_keys))
for i in range(len(food_keys))}
data = {None: {
'F': {None: F},
'N': {None: N},
'a': a,
'Vmax': {None: Vmax},
}}
model = pyo.AbstractModel()
solver = 'gurobi'
solver_io = 'python'
stream_solver = False # True prints solver output to screen
keepfiles = False # True prints intermediate file names (.nl,.sol,...)
opt = SolverFactory(solver, solver_io = solver_io)
opt.options['outlev'] = 1 # tell gurobi to be verbose with output
opt.options['solnsens'] = 1
opt.options['bestbound'] = 1
# Foods
model.F = pyo.Set()
# Nutrients
model.N = pyo.Set()
# Cost of each food
model.c = pyo.Param(model.F, within = pyo.PositiveReals)
# Amount of nutrient in each food
model.a = pyo.Param(model.F, model.N, within = pyo.NonNegativeReals)
# Lower and upper bound on each nutrient
model.Nmin = pyo.Param(model.N, within = pyo.NonNegativeReals, default = 0.0)
model.Nmax = pyo.Param(model.N, within = pyo.NonNegativeReals, default = inf)
# Volume per serving of food
model.V = pyo.Param(model.F, within = pyo.PositiveReals)
# Maximum volume of food consumed
model.Vmax = pyo.Param(within = pyo.PositiveReals)
# Number of servings consumed of each food
model.x = pyo.Var(model.F, within = pyo.NonNegativeIntegers)
# Minimize the cost of food that is consumed
def cost_rule(model):
return sum(model.c[i] * model.x[i] for i in model.F)
model.cost = pyo.Objective(rule = cost_rule)
# Limit nutrient consumption for each nutrient
def nutrient_rule(model, j):
value = sum(model.a[i, j] * model.x[i] for i in model.F)
return pyo.inequality(model.Nmin[j], value, model.Nmax[j])
model.nutrient_limit = pyo.Constraint(model.N, rule = nutrient_rule)
# Limit the volume of food consumed
def volume_rule(model):
return sum(model.V[i] * model.x[i] for i in model.F) <= model.Vmax
model.volume = pyo.Constraint(rule = volume_rule)
model_instance = model.create_instance(data)
model_instance.pprint()
results = opt.solve(model_instance, keepfiles = keepfiles, tee = stream_solver)
你 运行 遇到了问题,因为你要求 pyomo 阅读你的字典 就好像 它们是一个 .dat 文件,就像你引用的例子一样。它不能那样做。它可以读取具有由同一键集索引的多个项目的多列 .dat 文件,但(据我所知)不能从 python 字典中执行相同的操作。所以你有几个选择...
分解你的字典,并有 个人 的成本,价值等。这应该是一个微不足道的修复,然后更新你的
data
型号。只需像您引用的示例那样将您的数据填充到一个单独的 .dat 文件中,就可以了
换档
ConcreteModel()
并忘记保持模型和数据分离。 Python 非常擅长整理文件和数据表,所以我几乎总是选择让 python 整理,然后根据创建的词典制作ConcreteModel()
。在不更改任何词典的情况下,您可以这样做:
model = pyo.ConcreteModel('chow time')
# Foods
model.F = pyo.Set(initialize=F.keys())
# Nutrients
model.N = pyo.Set(initialize=N.keys())
# Cost of each food
model.c = pyo.Param(model.F, within = pyo.PositiveReals, initialize = {k:v['c'] for k,v in F.items()})
# Volume per serving of food
model.V = pyo.Param(model.F, within = pyo.PositiveReals, initialize = {k:v['V'] for k,v in F.items()})