I'm trying to create a sort of residual network from a given network, for that I'm first creating the reverse edges that doesn't exist in the graph, but I keep getting the message
RuntimeError: dictionary changed size during iteration
First I was obviously iterating over an object that was being modified during the loop:
def Gf(Graph): #residual graph
for u in Graph:
for v in Graph[u]:
if u in Graph[v]:
pass
else:
Graph[v][u]=0 #create the edge with capacity 0
return Graph
Where the graph Graph is an object of the form (I'm new to python so I don't know if this is the best way to do it)
defaultdict(lambda: defaultdict(lambda:0))
with values Graph[u][v] set to capacity of the edge u,v.
So I created a copy of Graph and tried to iterate over that object
def Gf(Graph): #residual graph
Graph_Copy=Graph.copy()
for u in Graph_Copy:
for v in Graph_Copy[u]:
if u in Graph_Copy[v]:
pass
else:
Graph[v][u]=0
return Graph
But that didn't work. I tried some other ways (create a deepcopy; create an empty object Graph_Copy, iterate over Graph and then set adequate values to Graph_Copy) but no luck so far. What I'm doing wrong?
Honestly, I don't know exactly what is causing your exception. What I do know, however, is that it is a bad idea to use nested dictionaries to represent graphs. They are harder to iterate over, as you have discovered, and have more overhead. Instead, you should use a nested list.
If I understand your current data structure correctly, it can be represented as followed:
graph = {
u0: {v0: 0, v1: 0, ... },
u1: {v0: 0, v1: 0, ... },
...
} # the curly brackets denote dictionaries
The better representation would be:
graph = [
[0, 0, 0, ...],
[0, 0, 0, ...],
...
] # the brackets denote lists
This is the default way to encode the distance matrix ( http://en.wikipedia.org/wiki/Distance_matrix ) representation of a graph. If you have coded in other languages like C/C++, then this is the equivalent of a 2-dimensional array.
Assuming that u
& v
are labels for your graph vertices, they can be represented as numerical values, ie 0 for the 1st node, 1 for the 2nd, and so on. Accessing the value of the edge uv
would be as simple as doing graph[u][v]
.
Now, let's assume that you have changed your code so that the graph G which has N vertices is represented as a nested list/2D array of size NxN, your function can be rewritten as followed:
def gf(g): # python style guideline recommends lower case variable & function names
vertices_count = len(g) # get the size of the original graph
gf = [] # initialize the new redidual graph
for u in range(vertices_count):
gf.append([0]*vertices_count) # initialize the edges
for v in range(vertices_count):
if g[u][v] > 0:
# do something here if the value of edge u-v is more than zero, e.g. gf[u][v] = some formula
else:
# do something here if the value of edge u-v is zero,, e.g. gf[u][v] = 0
return gf
The error is because you're using defaultdict
. So what can look like a read-only operation, eg, Graph[u]
, can actually add a key and change the dictionary size.
EDIT: Removed suggestion to use copy
or deepcopy
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.