我正在学习通过Gurobi python构建优化模型,但是在寻找定义决策变量和约束的pythonic方法时遇到了一些问题:
假设我有这些设置:
time={morning, afternoon, evening};
interval={early,late};
food={burger, banana, apple, orange};
我的决策变量是二进制进餐[时间,间隔,食物]。但是,我只有如下定义的一组可能的选项,不能枚举我的集合中的所有元素:
time interval food number value
morning early banana 2 500
morning early apple 3 600
afternoon early burger 1 800
evening late orane 2 400
所以我的eat变量只能是以下内容:
eat[morning,early,banana]
eat[morning,early,apple]
eat[afternoon,early,burger]
eat[evening,late,orange]
我做不到:
eat = m.addVars(time, interval, food, name = "Eat", vtype=GRB.BINARY)
我可以做类似的事情:
eat = {}
for row in input.to_dict('records'):
key = (row['time'], row['interval'],row['food'])
eat[key] = m.addVar(name = "Eat", vtype=GRB.BINARY)
但是我仍然很难定义我的目标,那就是数量和价值相乘并进食,我正在寻找一种更一致,更优雅的方法:
obj = quicksum(number[i,j,k]*value[i, j, k] * eat[i, j, k] for i in time
for j in interval for k in food)
上面将列举所有错误的内容,而我尝试了如下操作:
obj = quicksum(number[key]*value[key] * eat[key] \
for key in eat)
将其限制为仅在字典中定义的组合,但是当我不得不像下面这样分隔字典的元素时,我就在约束中苦苦挣扎:
m.addConstrs(quicksum(eat[i,j,k] for k in food)==1 for i in time for j in interval)
或类似的
m.addConstrs(quicksum(eat[morning,j,banana] ==1) for j in interval)
很长的问题很抱歉。来自优化/ Python专家的任何帮助都将非常有用。
答案 0 :(得分:3)
它可以帮助您利用Gurobi Python API必须存储的变量tupledict。它具有一些方便的方法,使您可以轻松地对变量求和,乘法或切片。我在下面提供了一个完整的示例。
from gurobipy import GRB, Model
import numpy as np
tuples = [('morning', 'early', 'banana'),('morning', 'early', 'apple'),
('afternoon', 'early', 'burger'), ('evening', 'late', 'orane')]
numbers, values = [2, 3, 1, 2], [500, 600, 800, 400]
m = Model('SO52451928')
eat = m.addVars(tuples, name='eat', vtype=GRB.BINARY)
coeffs = np.array(numbers) * np.array(values) # Can be made with regular lists as well
coeffs = dict(zip(tuples, coeffs))
obj = eat.prod(coeffs)
m.setObjective(obj)
# This structure holds the unique combinations of (time, interval) that
# appear in the data. They are necessary, because they form the set over which
# our constraints are defined
time_intervals = set(zip(*zip(*tuples)[:2]))
constrs = m.addConstrs((
eat.sum(i, j, '*') == 1 for i, j in time_intervals), name='one_food')
m.write(m.ModelName+'.lp')
m.optimize()
if m.SolCount > 0:
print(zip(m.getAttr(
'VarName', m.getVars()), m.getAttr('x', m.getVars())))
我希望这会有所帮助!