Gurobi / modeling-examples

Gurobi modeling examples
https://gurobi.github.io/modeling-examples/
Apache License 2.0
613 stars 269 forks source link

traveling_salesman "Model Code": RuntimeError: dictionary changed size during iteration #23

Closed Bookervsky closed 4 months ago

Bookervsky commented 4 months ago

In tsp.ipynb, when excuting the "Model Code" part, you may get a RuntimeError: dictionary changed size during iteration error on

for i, j in vars.keys():
    vars[j, i] = vars[i, j]  # edge in opposite direction

This is because in the "Data computation" part, when creating variable dist, the following code

dist = {(c1, c2): distance(c1, c2) for c1, c2 in combinations(capitals, 2)}

creates a n(n-1)/2 length dictionary, which means variable dist only contains distance[i,j] and does not contain distance[j,i], for example ,it only contains dist[('Montgomery', 'Phoenix')] but does not contain dist[('Phoenix',Montgomery')] This leads to further problem when creating and initializing decision variables for gurobi model:

m = gp.Model()

# Variables: is city 'i' adjacent to city 'j' on the tour?
vars = m.addVars(dist.keys(), obj=dist, vtype=GRB.BINARY, name='x')

# Symmetric direction: Copy the object
for i, j in vars.keys():
    vars[j, i] = vars[i, j]  # edge in opposite direction

As stated above, distance[j,i] does not exist, so vars[j, i] does not exist neither. For example, decision variable vars[('Montgomery', 'Phoenix')] exist but vars[('Phoenix',Montgomery')] does not exist, which makes vars[j, i] = vars[i, j] a RuntimeError.

So to fix this , the code dist = {(c1, c2): distance(c1, c2) for c1, c2 in combinations(capitals, 2)} should be changed to dist = {(c1, c2): distance(c1, c2) for c1, c2 in permutations(capitals, 2)} And of course you need to import itertools.combinations before using it.

@yurchisin

venaturum commented 4 months ago

Thanks again for reporting!

In gurobipy v11 there were some deliberate changes made to how gurobipy.tupledict works.

It looks like these changes are not compatible with this code.