通过 Gurobi Python 添加变量和约束的有效方法,无需枚举所有元素
Efficient way to add variables and constraints through Gurobi Python without enumerating through all elements
我正在学习通过 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[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)
但我仍然无法定义我的 objective,它是乘以数字和价值,然后吃,我正在寻找一种更一致、更优雅的方式:
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)
抱歉,问题很长。 optimization/python 专家的任何帮助都会很棒。
它可能会帮助您利用 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())))
希望对您有所帮助!
我正在学习通过 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[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)
但我仍然无法定义我的 objective,它是乘以数字和价值,然后吃,我正在寻找一种更一致、更优雅的方式:
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)
抱歉,问题很长。 optimization/python 专家的任何帮助都会很棒。
它可能会帮助您利用 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())))
希望对您有所帮助!