The tupledict class

The final important preliminary we would like to discuss is the tupledict class. This is a custom sub-class of the Python dict class that allows you to efficiently work with subsets of Gurobi variable objects. To be more specific, you can use the sum and prod methods on a tupledict object to easily and concisely build linear expressions. The keys for a tupledict are stored as a tuplelist, so the same select syntax can be used to choose subsets of entries. Specifically, by associating a tuple with each Gurobi variable, you can efficiently create expressions that contain a subset of matching variables. For example, using the sum method on a tupledict object, you could easily build an expression that captures the sum over all Gurobi variables for which the first field of the corresponding tuple is equal to 3 (using x.sum(3, '*')).

While you can directly build your own tupledict, the Gurobi interface provides an addVars method that adds one Gurobi decision variable to the model for each tuple in the input argument(s) and returns the result as a tupledict. Let us give a simple example. We'll begin by constructing a list of tuples, and then we'll create a set of Gurobi variables that are indexed using this list:

gurobi> l = list([(1, 2), (1, 3), (2, 3), (2, 4)])
gurobi> d = model.addVars(l, name="d")
gurobi> model.update()
The addVars method will create variables d(1,2), d(1,3), d(2,3), and d(2,4). Note that the name argument is used to name the resulting variables, but it only gives the prefix for the name - the names are subscripted by the tuple keys (so the variables would be named d[1,2], d[1,3], etc.). The final call to update synchronizes certain internal data structures; this detail can be safely ignored for now.

You can then use this tupledict to build linear expressions. For example, you could do:

gurobi> sum(, '*'))
The select method returns a list of Gurobi variables where the first field of the associated tuple is 1. The Python sum statement then creates a linear expression that captures the sum of these variables. In this case, that expression would be d(1,2) + d(1,3). Similarly, sum('*', 3)) would give d(1,3) + d(2,3). As with a tuplelist, you use a '*' string to indicate that any value is acceptable in that position in the tuple.

The tupledict class includes a method that simplifies the above. Rather than sum('*', 3)), you can use d.sum('*', 3) instead.

The tupledict class also includes a prod method, for cases where you need to build a linear expression with coefficients that aren't all 1.0. Coefficients are provided through a dict argument. They are indexed using the same tuples as the tupledict. For example, given a dict named coeff with two entries: coeff(1,2) = 5 and coeff(2,3) = 7, a call to would give the expression 5 d(1,2) + 7 d(2,3). You can also include a filter, so, 2, '*') would give just 7 d(2,3).

Note that tupledict is a sub-class of dict, so you can use the standard dict methods to access or modify a tupledict:

gurobi> print(d[1,3])
<gurobi.Var d[1,3]>
gurobi> d[3, 4] = 0.3
gurobi> print(d[3, 4])
gurobi> print(d.values())
dict_values([<gurobi.Var d[1,2]>, 0.3, <gurobi.Var d[1,3]>, <gurobi.Var d[2,3]>, <gurobi.Var d[2,4]>])
In our upcoming network flow example, once we've built a tupledict that contains a variable for each valid commodity-source-destination combination on the network (we'll call it flows), we can create a linear expression that captures the total flow on all arcs that empty into a specific destination city as follows:

gurobi> inbound = flows.sum('*', '*', 'New York')

We now present an example that illustrates the use of all of the concepts discussed so far.