ryansmcgee / seirsplus

Models of SEIRS epidemic dynamics with extensions, including network-structured populations, testing, contact tracing, and social distancing.
MIT License
660 stars 218 forks source link

'KeysView' object is returned instead of a list #1

Closed tomermilo closed 4 years ago

tomermilo commented 4 years ago

When running this: G_normal = custom_exponential_graph(baseGraph, scale=100)

I get the following error:

==================================================

TypeError Traceback (most recent call last) mtrand.pyx in mtrand.RandomState.choice()

TypeError: 'KeysView' object cannot be interpreted as an integer

During handling of the above exception, another exception occurred:

ValueError Traceback (most recent call last)

in 3 4 # Baseline normal interactions: ----> 5 G_normal = custom_exponential_graph(baseGraph, scale=100) 6 plot_degree_distn(G_normal, max_degree=40) ~\Anaconda3\envs\corona\lib\site-packages\seirsplus\models.py in custom_exponential_graph(base_graph, scale, min_num_edges, m, n) 1175 neighbors = graph[node].keys() 1176 quarantineEdgeNum = int( max(min(numpy.random.exponential(scale=scale, size=1), len(neighbors)), min_num_edges) ) -> 1177 quarantineKeepNeighbors = numpy.random.choice(neighbors, size=quarantineEdgeNum, replace=False) 1178 for neighbor in neighbors: 1179 if(neighbor not in quarantineKeepNeighbors): mtrand.pyx in mtrand.RandomState.choice() ValueError: 'a' must be 1-dimensional or an integer ========================================================== solved it by wrapping graph[node].keys() with list(): neighbors = graph[node].keys() -> neighbors = list(graph[node].keys()) Is it right?
kpelechrinis commented 4 years ago

I did the same and it solved this problem, but then I had a runtime error

RuntimeError: dictionary changed size during iteration

at the line 1177:

for neighbor in neighbors:

Any thoughts?

tomermilo commented 4 years ago

@kpelechrinis can you send your new custom_exponential_graph function?

kpelechrinis commented 4 years ago

@tomermilo actually the following version does not give any problem (essentially it is what you also mentioned I think) and I was able to run the example provided:

============================================== def custom_exponential_graph(base_graph=None, scale=100, min_num_edges=0, m=9, n=None):

Generate a random preferential attachment power law graph as a starting point.

# By the way this graph is constructed, it is expected to have 1 connected component.
# Every node is added along with m=8 edges, so the min degree is m=8.
if(base_graph):
    graph = base_graph.copy()
else:
    assert(n is not None), "Argument n (number of nodes) must be provided when no base graph is given."
    graph = networkx.barabasi_albert_graph(n=n, m=m)

# To get a graph with power-law-esque properties but without the fixed minimum degree,
# We modify the graph by probabilistically dropping some edges from each node. 
for node in graph:
    neighbors = list(graph[node].keys())
    quarantineEdgeNum = int( max(min(numpy.random.exponential(scale=scale, size=1), len(neighbors)), min_num_edges) )
    quarantineKeepNeighbors = numpy.random.choice(neighbors, size=quarantineEdgeNum, replace=False)
    for neighbor in neighbors:
        if(neighbor not in quarantineKeepNeighbors):
            graph.remove_edge(node, neighbor)

return graph
tomermilo commented 4 years ago

This is how I fixed it as well. Good luck

ryansmcgee commented 4 years ago

The change to list(dict.keys()) has been made throughout the package to make this keys lookup work in both Python 2 and 3. Thank you for flagging this issue.