Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
237 views
in Technique[技术] by (71.8m points)

python - networkx DiGraph Attribute Error self._succ

Context: I'm trying to run another researcher's code - it describes a traffic model for the Bay Area road network, which is subject to seismic hazard. I'm new to Python and therefore would really appreciate some help debugging the following error.

Issue: When I try to run the code for the sample data provided with the file, following the instructions in the README, I get the following error.

DN0a226926:quick_traffic_model gitanjali$ python mahmodel_road_only.py
You are considering 2 ground-motion intensity maps.
You are considering 1743 different site locations.
You are considering 2 different damage maps (1 per ground-motion intensity map).
Traceback (most recent call last):
  File "mahmodel_road_only.py", line 288, in <module>
main()
  File "mahmodel_road_only.py", line 219, in main
  G = get_graph()
  File "mahmodel_road_only.py", line 157, in get_graph
  G = add_superdistrict_centroids(G)
  File "mahmodel_road_only.py", line 46, in add_superdistrict_centroids
  G.add_node(str(1000000 + i))
  File "/Library/Python/2.7/site-packages/networkx-2.0-py2.7.egg/networkx/classes/digraph.py", line 412, in add_node
if n not in self._succ:
  AttributeError: 'DiGraph' object has no attribute '_succ'

Debugging: Based on some other questions, it seems like this error stems from an issue with the networkx version (I'm using 2.0) or the Python version (I'm using 2.7.10). I went through the migration guide cited in other questions and found nothing that I needed to change in mahmodel_road_only.py. I also checked the digraph.py file and found that self._succ is defined. I also checked the definition of get_graph(), shown below, which calls networkx, but didn't see any obvious issues.

def get_graph():
  import networkx
  '''loads full mtc highway graph with dummy links and then adds a few 
  fake centroidal nodes for max flow and traffic assignment'''
G = networkx.read_gpickle("input/graphMTC_CentroidsLength3int.gpickle")
G = add_superdistrict_centroids(G)
assert not G.is_multigraph() # Directed! only one edge between nodes
G = networkx.freeze(G) #prevents edges or nodes to be added or deleted
return G

Question: How can I resolve this problem? Is it a matter of changing the Python or Networkx versions? If not, what next steps could you recommend for debugging?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I believe your problem is similar to that in AttributeError: 'DiGraph' object has no attribute '_node'

The issue there is that the graph being investigated was created in networkx 1.x and then pickled. The graph then has the attributes that a networkx 1.x object has. I believe this happened for you as well.

You've now opened it and you're applying tools from networkx 2.x to that graph. But those tools assume that it's a networkx 2.x DiGraph, with all the attributes expected in a 2.x DiGraph. In particular it expects _succ to be defined for a node, which a 1.x DiGraph does not have.

So here are two approaches that I believe will work:

Short term solution Remove networkx 2.x and replace with networkx 1.11.

This is not optimal because networkx 2.x is more powerful. Also code that has been written to work in both 2.x and 1.x (following the migration guide you mentioned) will be less efficient in 1.x (for example there will be places where the 1.x code is using lists and the 2.x code is using generators).

Long term solution Convert the 1.x graph into a 2.x graph (I can't test easily as I don't have 1.x on my computer at the moment - If anyone tries this, please leave a comment saying whether this works and whether your network was weighted):

#you need commands here to load the 1.x graph G
#
import networkx as nx   #networkx 2.0
H = nx.DiGraph() #if it's a DiGraph()
#H=nx.Graph() #if it's a typical networkx Graph().

H.add_nodes_from(G.nodes(data=True))
H.add_edges_from(G.edges(data=True))

The data=True is used to make sure that any edge/node weights are preserved. H is now a networkx 2.x DiGraph, with the edges and nodes having whatever attributes G had. The networkx 2.x commands should work on it.

Bonus longer term solution Contact the other researcher and warn him/her that the code example is now out of date.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...