I am learning to build optimization models through Gurobi python and I am having some issues finding the pythonic way of defining decision variables and constraints:
Assuming I have these sets:
time={morning, afternoon, evening};
interval={early,late};
food={burger, banana, apple, orange};
and my decision variable is binary eat[time,interval,food]. However I only have a defined set of possible options as below and cannot enumerate all elements of my sets:
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
so my eat variables can only be the following:
eat[morning,early,banana]
eat[morning,early,apple]
eat[afternoon,early,burger]
eat[evening,late,orange]
and I cannot do:
eat = m.addVars(time, interval, food, name = "Eat", vtype=GRB.BINARY)
I can do something like:
eat = {}
for row in input.to_dict('records'):
key = (row['time'], row['interval'],row['food'])
eat[key] = m.addVar(name = "Eat", vtype=GRB.BINARY)
But I still have trouble defining my objective which is multiplying number and value and eat and I am looking for a more consistent, elegant way:
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)
The above will enumerate all which is wrong and I tried something like this:
obj = quicksum(number[key]*value[key] * eat[key] \
for key in eat)
which limits it to only defined combinations in the dictionary but then I am struggling with constraints when I have to separate elements of dictionary like below:
m.addConstrs(quicksum(eat[i,j,k] for k in food)==1 for i in time for j in interval)
or something like
m.addConstrs(quicksum(eat[morning,j,banana] ==1) for j in interval)
Sorry for the long questions. Any help from optimization/python experts would be great.
It may help you to make use of the tupledict structure the Gurobi Python API has to store the variables. It has some convenient methods which allow you to sum, multiply or slice variables easily. I provide a complete example below.
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())))
I hope this helps!
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加