Pyomo - 选择域值的子集以创建最优集
Pyomo - Selecting a subset of domain values to create an optimal set
我有一系列项目,我想从中 select 项目的最佳子集,它根据条件最大化成本。物品清单如下:
items = {
0: { 'user': 1, 'cost': 100 },
1: { 'user': 1, 'cost': 150 },
2: { 'user': 2, 'cost': 200 },
3: { 'user': 2, 'cost': 100 },
4: { 'user': 3, 'cost': 150 }
}
约束是,每个用户只能select编辑一个项目。因此,上述场景的最佳解决方案将包含项目 1、2 和 4。
我已经尝试了以下代码来解决这个问题(没有限制,因为我还没有走到那一步)
from pyomo.environ import (ConcreteModel, Objective, Var, Boolean, maximize, Constraint, Set, value)
from pyomo.opt.base import SolverFactory
items = {
0: { 'user': 1, 'cost': 100 },
1: { 'user': 1, 'cost': 150 },
2: { 'user': 2, 'cost': 200 },
3: { 'user': 2, 'cost': 100 },
4: { 'user': 3, 'cost': 150 }
}
item_selection = model = ConcreteModel()
model.selected_items = Set(initialize=[0], domain=items.keys())
model.obj = Objective(expr = sum(items[i]['cost'] for i in model.selected_items), sense=maximize)
solver = 'glpk'
solver_exe = '/opt/homebrew/Cellar/glpk/5.0/bin/glpsol'
opt = SolverFactory(solver, executable=solver_exe)
solution = opt.solve(item_selection)
solution.write()
以上代码输出结果如下
WARNING: Constant objective detected, replacing with a placeholder to prevent
solver failure.
WARNING: Empty constraint block written in LP format - solver may error
# ==========================================================
# = Solver Results =
# ==========================================================
# ----------------------------------------------------------
# Problem Information
# ----------------------------------------------------------
Problem:
- Name: unknown
Lower bound: 100.0
Upper bound: 100.0
Number of objectives: 1
Number of constraints: 1
Number of variables: 1
Number of nonzeros: 1
Sense: maximize
# ----------------------------------------------------------
# Solver Information
# ----------------------------------------------------------
Solver:
- Status: ok
Termination condition: optimal
Statistics:
Branch and bound:
Number of bounded subproblems: 0
Number of created subproblems: 0
Error rc: 0
Time: 0.032784223556518555
# ----------------------------------------------------------
# Solution Information
# ----------------------------------------------------------
Solution:
- number of solutions: 0
number of solutions displayed: 0
因为在我的代码示例中,集合 selected_items 是一个包含所有项目 ID 域的列表,我希望 selected_items = [1,2,4](一旦约束是也适用)。
当我运行
item_selection.obj()
我只是得到
100.0
作为输出。这是项目 ID“0”的成本(我已经用它初始化了集合)。所以求解器不会向集合中添加任何其他 ID。
我是 pyomo 的新手,所以任何建议都会有所帮助。谢谢
经过一番研究,我能够解决问题。
import pyomo.environ as pe
import pyomo.opt as po
solver = po.SolverFactory('glpk')
items = {
0: { 'user': 1, 'cost': 100 },
1: { 'user': 1, 'cost': 150 },
2: { 'user': 2, 'cost': 200 },
3: { 'user': 2, 'cost': 100 },
4: { 'user': 3, 'cost': 150 },
}
# Get a list of unique users from the items dict
users = list(set([items[i]['user'] for i in items.keys()]))
# Create dictionaries to initialise model parameters and variables
item_user_init = dict([(item_id, item['user']) for item_id, item in items.items()])
item_cost_init = dict([(item_id, item['cost']) for item_id, item in items.items()])
selected_users_init = dict([(item_id, 0) for item_id in items.keys()])
model = pe.ConcreteModel()
# Indexed set for all the item keys
model.item_keys = pe.Set(initialize=items.keys())
# Model Parameters and
model.user = pe.Param(model.item_keys, initialize=item_user_init)
model.cost = pe.Param(model.item_keys, initialize=item_cost_init)
# For each item id, assign a value of 0 in the beginning. For selected items, this value will change to 1
model.selected_users = pe.Var(model.item_keys, domain=pe.Binary, initialize=selected_users_init)
# Objective Function - to maximise sum of costs for selected items
model.obj = pe.Objective(sense=pe.maximize, expr = sum(model.cost[i]*model.selected_users[i] for i in model.item_keys))
# Constraint Function - to limit maximum one item per user
def user_constraint(model, user):
return sum(model.selected_users[i] for i in model.item_keys if items[i]['user'] == user) <= 1
model.user_constraint = pe.Constraint(users, expr=user_constraint)
result = solver.solve(model)
print('Selected Item IDs: {}'.format([i for i in model.item_keys if pe.value(model.selected_users[i]) > 0]))
print('Total Cost: {}'.format(pe.value(model.obj)))
以上代码产生了预期的输出,如下所示:
Selected Item IDs: [1, 2, 4]
Total Cost: 500.0
由于我对 pyomo 还是个新手,如有任何提高代码质量的建议,我们将不胜感激。
我有一系列项目,我想从中 select 项目的最佳子集,它根据条件最大化成本。物品清单如下:
items = {
0: { 'user': 1, 'cost': 100 },
1: { 'user': 1, 'cost': 150 },
2: { 'user': 2, 'cost': 200 },
3: { 'user': 2, 'cost': 100 },
4: { 'user': 3, 'cost': 150 }
}
约束是,每个用户只能select编辑一个项目。因此,上述场景的最佳解决方案将包含项目 1、2 和 4。
我已经尝试了以下代码来解决这个问题(没有限制,因为我还没有走到那一步)
from pyomo.environ import (ConcreteModel, Objective, Var, Boolean, maximize, Constraint, Set, value)
from pyomo.opt.base import SolverFactory
items = {
0: { 'user': 1, 'cost': 100 },
1: { 'user': 1, 'cost': 150 },
2: { 'user': 2, 'cost': 200 },
3: { 'user': 2, 'cost': 100 },
4: { 'user': 3, 'cost': 150 }
}
item_selection = model = ConcreteModel()
model.selected_items = Set(initialize=[0], domain=items.keys())
model.obj = Objective(expr = sum(items[i]['cost'] for i in model.selected_items), sense=maximize)
solver = 'glpk'
solver_exe = '/opt/homebrew/Cellar/glpk/5.0/bin/glpsol'
opt = SolverFactory(solver, executable=solver_exe)
solution = opt.solve(item_selection)
solution.write()
以上代码输出结果如下
WARNING: Constant objective detected, replacing with a placeholder to prevent
solver failure.
WARNING: Empty constraint block written in LP format - solver may error
# ==========================================================
# = Solver Results =
# ==========================================================
# ----------------------------------------------------------
# Problem Information
# ----------------------------------------------------------
Problem:
- Name: unknown
Lower bound: 100.0
Upper bound: 100.0
Number of objectives: 1
Number of constraints: 1
Number of variables: 1
Number of nonzeros: 1
Sense: maximize
# ----------------------------------------------------------
# Solver Information
# ----------------------------------------------------------
Solver:
- Status: ok
Termination condition: optimal
Statistics:
Branch and bound:
Number of bounded subproblems: 0
Number of created subproblems: 0
Error rc: 0
Time: 0.032784223556518555
# ----------------------------------------------------------
# Solution Information
# ----------------------------------------------------------
Solution:
- number of solutions: 0
number of solutions displayed: 0
因为在我的代码示例中,集合 selected_items 是一个包含所有项目 ID 域的列表,我希望 selected_items = [1,2,4](一旦约束是也适用)。
当我运行
item_selection.obj()
我只是得到
100.0
作为输出。这是项目 ID“0”的成本(我已经用它初始化了集合)。所以求解器不会向集合中添加任何其他 ID。
我是 pyomo 的新手,所以任何建议都会有所帮助。谢谢
经过一番研究,我能够解决问题。
import pyomo.environ as pe
import pyomo.opt as po
solver = po.SolverFactory('glpk')
items = {
0: { 'user': 1, 'cost': 100 },
1: { 'user': 1, 'cost': 150 },
2: { 'user': 2, 'cost': 200 },
3: { 'user': 2, 'cost': 100 },
4: { 'user': 3, 'cost': 150 },
}
# Get a list of unique users from the items dict
users = list(set([items[i]['user'] for i in items.keys()]))
# Create dictionaries to initialise model parameters and variables
item_user_init = dict([(item_id, item['user']) for item_id, item in items.items()])
item_cost_init = dict([(item_id, item['cost']) for item_id, item in items.items()])
selected_users_init = dict([(item_id, 0) for item_id in items.keys()])
model = pe.ConcreteModel()
# Indexed set for all the item keys
model.item_keys = pe.Set(initialize=items.keys())
# Model Parameters and
model.user = pe.Param(model.item_keys, initialize=item_user_init)
model.cost = pe.Param(model.item_keys, initialize=item_cost_init)
# For each item id, assign a value of 0 in the beginning. For selected items, this value will change to 1
model.selected_users = pe.Var(model.item_keys, domain=pe.Binary, initialize=selected_users_init)
# Objective Function - to maximise sum of costs for selected items
model.obj = pe.Objective(sense=pe.maximize, expr = sum(model.cost[i]*model.selected_users[i] for i in model.item_keys))
# Constraint Function - to limit maximum one item per user
def user_constraint(model, user):
return sum(model.selected_users[i] for i in model.item_keys if items[i]['user'] == user) <= 1
model.user_constraint = pe.Constraint(users, expr=user_constraint)
result = solver.solve(model)
print('Selected Item IDs: {}'.format([i for i in model.item_keys if pe.value(model.selected_users[i]) > 0]))
print('Total Cost: {}'.format(pe.value(model.obj)))
以上代码产生了预期的输出,如下所示:
Selected Item IDs: [1, 2, 4]
Total Cost: 500.0
由于我对 pyomo 还是个新手,如有任何提高代码质量的建议,我们将不胜感激。