Add variables using multiple values from dictionary
AnsweredI am new to Gurobi and have been looking into the Netflow example for Python, trying to adapt it for my data.
I have converted all my inputdata from an multidimensional array into a dictionary using multidict, giving them keys corresponding to the variable type:
order,departure,arrival,amount = gp.multidict({ data}), or let's say k: i, j, d.
I am now trying to make the decision variables for the model with indices for the order, departure and arrival, so x[k,i,j]. And the value from the amount, d, should be the corresponding coefficient for the objective.
I tried this using gp.addVars(order, departure, arrival, obj=amount, name= "x"). However this gives variables with all possible k, i, j combinations. Instead, to benefit from sparsity in a larger dataset, I would like to only generate decision variables of valid combinations of k,i,j which are in the dictionary.
The example defines multiple (tuple)lists and dictionaries and then generates the variables. However would it also be possible to generate the decision variables as desired, using only the one dictionary?

Hi,
If I understand correctly, you want one variable for each element of \( \texttt{order} \)? If so, you can create an intermediate data structure that contains every \( \texttt{order, departure, arrival} \) tuple:
indices = list(zip(order, departure.values(), arrival.values()))
x = m.addVars(indices, obj=amount.values(), name="x")However, since the \( \texttt{order} \) keys should be unique and you can intuit the \( \texttt{departure} \) and \( \texttt{arrival} \) values from these keys, you can probably make your model work just by indexing these variables with the \( \texttt{order} \) tuplelist:
x = m.addVars(order, obj=amount.values(), name="x")
If I misunderstood your question, please post a small example that shows what you are trying to achieve.
Thanks,
Eli
1 
Thanks for your reply! Yes I would like a variable for each \(\texttt{order}\), but with three indexes corresponding to the order, departure and arrival values.
Hopefully this example clarifies my intention:
exampledata = np.array([[1,1,3,1],
[2,3,2,2],
[3,2,1,4],
[4,1,3,1]])
#in variables: [k,i,j,d]
order,departure,arrival,amount=gp.multidict({row[0]:row[1:].tolist() for row in exampledata})Wile the first value of each element, \(\texttt{k}\) is unique, I do need the information for \(\texttt{i,j}\) in the decision variables so from that I would like to generate the decision variables:
x[k,i,j]: x[1,1,3], x[2,3,2], x[3,2,1], x[4,1,3]
Your suggestion for an intermediate list \(\texttt{indices}\) provides for that. Although my main question was if this would be possible with only the dictionary keys and without the need for an intermediate list?
Unfortunately the \(\texttt{obj=custdemand.values()}\) does not seem to take the correct values. For each \(\texttt{k,i,j}\) combination, it should take the corresponding \(\texttt{d }\) so:
x[1,1,3]>1, x[2,3,2]>2, x[3,2,1]>4, x[4,1,3]>1
I know I can make an additional dictionary with \(\texttt{k,i,j}\) as key and \(\texttt{d }\) as value, but if there is a way to use my existing formulations that would be great to know!
0 
Hi,
There isn't a way to do this without manipulating the existing data. Ultimately, you need to pass Gurobi a list of tuples that represent the sparse variable indices, but the data isn't currently structured this way.
I'm not sure I understand what you mean when you say the \( \texttt{obj=custdemand.values()} \) are not taking the correct values (do you mean \( \texttt{amount.values()} \)?). When Gurobi sets the objective terms for the newly created variables, each element of in the \( \texttt{indices} \) list will be matched with the corresponding element of the \( \texttt{amount.values()} \) list. For example, this code:
import numpy as np
import gurobipy as gp
exampledata = np.array([[1,1,3,1], [2,3,2,2], [3,2,1,4], [4,1,3,1]])
order, departure, arrival, amount = gp.multidict({row[0]: row[1:].tolist() for row in exampledata})
indices = list(zip(order, departure.values(), arrival.values()))
m = gp.Model()
x = m.addVars(indices, obj=amount.values(), name="x")produces the following objective:
Minimize
x[1,1,3] + 2 x[2,3,2] + 4 x[3,2,1] + x[4,1,3]This seems to be what you want, and it avoids the need to create a dictionary to map each \( \texttt{(k, i, j)} \) tuple to \( \texttt{d} \).
Thanks,
Eli
1 
Thanks again! I got it to work. Unbeknownst to me, when I used the SetObjective command to maximize the objective function, the coefficients were reset to zero's. That's solved now.
0
Please sign in to leave a comment.
Comments
4 comments