internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: networkx/networkx

Issue:
minimum_node_cut gives a wrong result if there is an edge between source and target nodes in an directed Graph
For the simple graph generated by the following code: 

```
G = nx.Graph()
G.add_nodes_from([0,1,2,3,4])
G.add_edges_from([(0,1),(0,2),(1,3),(3,4),(2,3)], weight = 1)
print nx.algorithms.connectivity.minimum_node_cut(G,1,0)
```

The output is `set([2])`.

While clearly, even with removing node 2 there would still be a path between 0 and 1 which is directly between them. I believe the proper output should be an empty set indicating there is no possible node cut.



Discussion:

Resolving patch:
diff --git a/networkx/algorithms/connectivity/cuts.py b/networkx/algorithms/connectivity/cuts.py
--- a/networkx/algorithms/connectivity/cuts.py
+++ b/networkx/algorithms/connectivity/cuts.py
@@ -285,7 +285,8 @@ def minimum_st_node_cut(G, s, t, flow_func=None, auxiliary=None, residual=None):
     mapping = H.graph.get('mapping', None)
     if mapping is None:
         raise nx.NetworkXError('Invalid auxiliary digraph.')
-
+    if G.has_edge(s, t) or G.has_edge(t, s):
+        return []
     kwargs = dict(flow_func=flow_func, residual=residual, auxiliary=H)
 
     # The edge cut in the auxiliary digraph corresponds to the node cut in the


Test patch:
diff --git a/networkx/algorithms/connectivity/tests/test_cuts.py b/networkx/algorithms/connectivity/tests/test_cuts.py
--- a/networkx/algorithms/connectivity/tests/test_cuts.py
+++ b/networkx/algorithms/connectivity/tests/test_cuts.py
@@ -238,6 +238,13 @@ def tests_min_cut_complete_directed():
         for flow_func in flow_funcs:
             assert_equal(4, len(interface_func(G, flow_func=flow_func)))
 
+def tests_minimum_st_node_cut():
+    G = nx.Graph()
+    G.add_nodes_from([0, 1, 2, 3, 7, 8, 11, 12])
+    G.add_edges_from([(7, 11), (1, 11), (1, 12), (12, 8), (0, 1)])
+    nodelist = minimum_st_node_cut(G, 7, 11)
+    assert(nodelist == [])
+
 def test_invalid_auxiliary():
     G = nx.complete_graph(5)
     assert_raises(nx.NetworkXError, minimum_st_node_cut, G, 0, 3,
Repository: networkx/networkx

Issue:
Fix location of graphviz_layout in draw_graphviz
Lost in a rename/rearrange? Added a basic smoke-test that just calls the function with a graph to verify names are valid.



Discussion:
Ugh -- you are correct... it was an oversight on the rename/relocation process.
Unfortunately it is more tricky than your fix covers because graphviz_layout is supplied by both the nx_pydot and nx_agraph modules.  So the "nx_pydot" text you added will only work if they have pydot installed. If they only have pygraphviz then you will need to put nx_agraph there.  Maybe it's best to try one and when it fails go to the other...

Maybe @Michael-E-Rose or @jfinkels (or others) could put together some tests of the graphviz_layout function in nx_pylab.py (and non-test code in the function itself). Anybody looking for some coding fun?

We need to make sure the function works in each installation case: 1) pydot and no pygraphviz, 2) pygraphviz and no pydot, 3) both, 4) neither.

This function just does

``` python
    pos = nx.drawing.graphviz_layout(G, prog)
    draw(G, pos, **kwargs)
```

Can we just avoid the complexity of all of the possible graphviz installations and simply remove it?

Removing it sounds good to me. :)


Resolving patch:
diff --git a/networkx/drawing/nx_pylab.py b/networkx/drawing/nx_pylab.py
--- a/networkx/drawing/nx_pylab.py
+++ b/networkx/drawing/nx_pylab.py
@@ -1,3 +1,11 @@
+#    Copyright (C) 2004-2016 by
+#    Aric Hagberg <hagberg@lanl.gov>
+#    Dan Schult <dschult@colgate.edu>
+#    Pieter Swart <swart@lanl.gov>
+#    All rights reserved.
+#    BSD license.
+#
+# Author: Aric Hagberg (hagberg@lanl.gov)
 """
 **********
 Matplotlib
@@ -13,14 +21,6 @@
 pygraphviz:     http://pygraphviz.github.io/
 
 """
-# Author: Aric Hagberg (hagberg@lanl.gov)
-
-#    Copyright (C) 2004-2016 by
-#    Aric Hagberg <hagberg@lanl.gov>
-#    Dan Schult <dschult@colgate.edu>
-#    Pieter Swart <swart@lanl.gov>
-#    All rights reserved.
-#    BSD license.
 import networkx as nx
 from networkx.drawing.layout import shell_layout,\
     circular_layout,spectral_layout,spring_layout,random_layout
@@ -35,8 +35,7 @@
            'draw_random',
            'draw_spectral',
            'draw_spring',
-           'draw_shell',
-           'draw_graphviz']
+           'draw_shell']
 
 
 def draw(G, pos=None, ax=None, hold=None, **kwds):
@@ -966,24 +965,6 @@ def draw_shell(G, **kwargs):
     draw(G, shell_layout(G, nlist=nlist), **kwargs)
 
 
-def draw_graphviz(G, prog="neato", **kwargs):
-    """Draw networkx graph with graphviz layout.
-
-    Parameters
-    ----------
-    G : graph
-       A networkx graph
-
-    prog : string, optional
-      Name of Graphviz layout program
-
-    kwargs : optional keywords
-       See networkx.draw_networkx() for a description of optional keywords.
-    """
-    pos = nx.drawing.graphviz_layout(G, prog)
-    draw(G, pos, **kwargs)
-
-
 def draw_nx(G, pos, **kwds):
     """For backward compatibility; use draw or draw_networkx."""
     draw(G, pos, **kwds)


Test patch:
Repository: networkx/networkx

Issue:
spring layout breaks with single node graph
This corner case (drawing 1 node) breaks spring layout and shouldn't

``` python
import networkx as nx  
G=nx.Graph()  
G.add_node("spam")  
nx.draw_networkx(G, node_size = 2000, node_color = "white", pos=nx.spring_layout(G))
```

http://stackoverflow.com/questions/36612991/how-to-draw-graph-having-single-node-in-networkx



Discussion:

Resolving patch:
diff --git a/networkx/drawing/layout.py b/networkx/drawing/layout.py
--- a/networkx/drawing/layout.py
+++ b/networkx/drawing/layout.py
@@ -290,7 +290,7 @@ def fruchterman_reingold_layout(G,dim=2,k=None,
     if len(G) == 0:
         return {}
     if len(G) == 1:
-        return {G.nodes()[0]: center}
+        return {next(G.nodes()): center}
 
     try:
         # Sparse matrix


Test patch:
Repository: networkx/networkx

Issue:
Namespace collision on nx.generators
It looks like nx.generators is no longer the modules in the folder networkx/generators.  Instead it is the contents of networkx/algorithms/community/generators.py

Can we rename that file to avoid namespace collisions on the word generators?
Maybe it should be moved to the generators directory and called `community_graphs.py`?



Discussion:
Either way is fine with me.  


Resolving patch:
diff --git a/networkx/algorithms/community/__init__.py b/networkx/algorithms/community/__init__.py
--- a/networkx/algorithms/community/__init__.py
+++ b/networkx/algorithms/community/__init__.py
@@ -1,6 +1,6 @@
 from networkx.algorithms.community.asyn_lpa import *
 from networkx.algorithms.community.centrality import *
-from networkx.algorithms.community.generators import *
+from networkx.algorithms.community.community_generators import *
 from networkx.algorithms.community.kclique import *
 from networkx.algorithms.community.kernighan_lin import *
 from networkx.algorithms.community.quality import *
diff --git a/networkx/algorithms/community/generators.py b/networkx/algorithms/community/community_generators.py
similarity index 100%
rename from networkx/algorithms/community/generators.py
rename to networkx/algorithms/community/community_generators.py


Test patch:
Repository: networkx/networkx

Issue:
compose() erases some MultiGraph edges
If a user wants to compose two multigraphs, it is very likely that they want to use all of the edges present in both. In MultiGraphs, edges which share the same (source, target) pair are not the same. Currently, edges which share the same (source, target, key) tuple are treated the same: as keys are assigned in insertion order by default, rather than having anything to do with the data, the end user just sees that an arbitrary few of their edges have gone missing.

``` python
import networkx as nx

a, b = nx.MultiGraph(), nx.MultiGraph()
a.add_path([1,2])
b.add_path([1,2])

nx.compose(a,b).number_of_edges() == a.number_of_edges() + b.number_of_edges()
>>> False
```

The documentation states that the edge sets are unioned. If this edge set is hashed by (source, target) pair, then the function cannot be advertised as applicable to MultiGraphs, because it collapses all multiedges. If the edge set is hashed by (source, target, key), as it is currently, then there is unexpected and possibly arbitrary behaviour which is not well documented. The edge set should be hashed by a UUID for MultiGraphs (i.e. all edges are distinct), in order to reflect how these classes are actually going to be used.



Discussion:
I can imagine users being confused by this if they use MultiGraphs without setting keys (which many don't).  On the other hand, changing it as you suggest could be confusing to users who do pay attention to the edge keys. At the very least a note should be included in the docs.

Perhaps there should be an argument to describe how to treat the edge keys.


Resolving patch:
diff --git a/networkx/algorithms/operators/binary.py b/networkx/algorithms/operators/binary.py
--- a/networkx/algorithms/operators/binary.py
+++ b/networkx/algorithms/operators/binary.py
@@ -316,6 +316,10 @@ def compose(G, H, name=None):
     -----
     It is recommended that G and H be either both directed or both undirected.
     Attributes from H take precedent over attributes from G.
+
+    For MultiGraphs, the edges are identified by incident nodes AND edge-key.
+    This can cause surprises (i.e., edge `(1, 2)` may or may not be the same
+    in two graphs) if you use MultiGraph without keeping track of edge keys.
     """
     if not G.is_multigraph() == H.is_multigraph():
         raise nx.NetworkXError('G and H must both be graphs or multigraphs.')


Test patch:
Repository: networkx/networkx

Issue:
relabel_nodes adds a graph attribute when copy=True
I would have expected the following to work:

```
import networkx as nx
graph_a = nx.DiGraph()
graph_b = nx.relabel_nodes(graph_a, {}, copy=True)
print "graph_a.graph", graph_a.graph
print "graph_b.graph", graph_b.graph
assert graph_a.graph == graph_b.graph
```

However, it does not since [_relabel_copy attempts to copy a non-existent graph attribute, 'name'](https://github.com/networkx/networkx/blob/1675a824d6cdb17c3144ef46ff52a0c2b53a11d1/networkx/relabel.py#L150).

I would have expected relabel_nodes to only change the node labels, while maintaining all graph/node/edge attributes.



Discussion:

Resolving patch:
diff --git a/networkx/readwrite/gml.py b/networkx/readwrite/gml.py
--- a/networkx/readwrite/gml.py
+++ b/networkx/readwrite/gml.py
@@ -435,10 +435,6 @@ def pop_attr(dct, category, attr, i):
 
     if label != 'id':
         G = nx.relabel_nodes(G, mapping)
-        if 'name' in graph:
-            G.graph['name'] = graph['name']
-        else:
-            del G.graph['name']
     return G
 
 
diff --git a/networkx/relabel.py b/networkx/relabel.py
--- a/networkx/relabel.py
+++ b/networkx/relabel.py
@@ -147,7 +147,8 @@ def _relabel_inplace(G, mapping):
 
 def _relabel_copy(G, mapping):
     H = G.__class__()
-    H.name = "(%s)" % G.name
+    if G.name:
+        H.name = "(%s)" % G.name
     if G.is_multigraph():
         H.add_edges_from( (mapping.get(n1, n1),mapping.get(n2, n2),k,d.copy())
                           for (n1,n2,k,d) in G.edges(keys=True, data=True))


Test patch:
diff --git a/networkx/tests/test_relabel.py b/networkx/tests/test_relabel.py
--- a/networkx/tests/test_relabel.py
+++ b/networkx/tests/test_relabel.py
@@ -150,6 +150,17 @@ def test_relabel_nodes_missing(self):
         mapping={0:'aardvark'}
         G=relabel_nodes(G,mapping,copy=False)
 
+    def test_relabel_copy_name(self):
+        G=Graph()
+        H = relabel_nodes(G, {}, copy=True)
+        assert_equal(H.graph, G.graph)
+        H = relabel_nodes(G, {}, copy=False)
+        assert_equal(H.graph, G.graph)
+        G.name = "first"
+        H = relabel_nodes(G, {}, copy=True)
+        assert_equal(H.graph, G.graph)
+        H = relabel_nodes(G, {}, copy=False)
+        assert_equal(H.graph, G.graph)
 
     def test_relabel_toposort(self):
         K5=nx.complete_graph(4)
Repository: networkx/networkx

Issue:
maximal matching documentation
networkx.algorithms.matching.maximal_matching is documented as 

"Find a maximal cardinality matching in the graph."

If it is just "maximal matching", then the use of 'cardinality' seems confusing.
Since the algorithm is not "maximum cardinality" matching.

For example, given a graph 'c'--'a'--'b'--'d' 
the method might return {('a', 'b')} as a maximal matching, which is not a maximum cardinality matching {('a', 'c'),('b', 'd')}.

```
import networkx as nx
g=nx.Graph()
g.add_edge('b','a')
g.add_edge('c','a')
g.add_edge('b','d')
print(nx.maximal_matching(g))
```

(The above test depends on the order of edges, which is not deterministic. If you get two edges as a result, you might restart python console and rerun the code.)

Could you remove 'cardinality' from the document?



Discussion:
You are right, that is confusing.  Thanks for pointing this out.  


Resolving patch:
diff --git a/networkx/algorithms/matching.py b/networkx/algorithms/matching.py
--- a/networkx/algorithms/matching.py
+++ b/networkx/algorithms/matching.py
@@ -21,10 +21,10 @@
 
 
 def maximal_matching(G):
-    r"""Find a maximal cardinality matching in the graph.
+    r"""Find a maximal matching in the graph.
 
     A matching is a subset of edges in which no node occurs more than once.
-    The cardinality of a matching is the number of matched edges.
+    A maximal matching cannot add more edges and still be a matching.
 
     Parameters
     ----------
@@ -152,8 +152,9 @@ def max_weight_matching(G, maxcardinality=False, weight='weight'):
     """Compute a maximum-weighted matching of G.
 
     A matching is a subset of edges in which no node occurs more than once.
-    The cardinality of a matching is the number of matched edges.
     The weight of a matching is the sum of the weights of its edges.
+    A maximal matching cannot add more edges and still be a matching.
+    The cardinality of a matching is the number of matched edges.
 
     Parameters
     ----------
diff --git a/networkx/algorithms/operators/product.py b/networkx/algorithms/operators/product.py
--- a/networkx/algorithms/operators/product.py
+++ b/networkx/algorithms/operators/product.py
@@ -131,7 +131,7 @@ def tensor_product(G, H):
     r"""Return the tensor product of G and H.
 
     The tensor product P of the graphs G and H has a node set that
-    is the Cartesian product of the node sets, :math:`V(P)=V(G) \times V(H)`.
+    is the tensor product of the node sets, :math:`V(P)=V(G) \times V(H)`.
     P has an edge ((u,v),(x,y)) if and only if (u,x) is an edge in G
     and (v,y) is an edge in H.
 


Test patch:
Repository: networkx/networkx

Issue:
Travis with Python3.6 miniconda fails
Fails with a gdal conflict error.
Can a conda expert help us figure out how to fix this?


```
UnsatisfiableError: The following specifications were found to be in conflict:

  - gdal -> libnetcdf 4.3.2 -> curl 7.38.0 -> openssl 1.0.1*
  - gdal -> numpy 1.9* -> python 2.7*
  - python 3.6*

Use "conda info <package>" to see the dependencies for each package.
CondaEnvironmentNotFoundError: Could not find environment: test-environment .
You can list all discoverable environments with `conda info --envs`.
```


Discussion:

Resolving patch:
diff --git a/networkx/algorithms/centrality/subgraph_alg.py b/networkx/algorithms/centrality/subgraph_alg.py
--- a/networkx/algorithms/centrality/subgraph_alg.py
+++ b/networkx/algorithms/centrality/subgraph_alg.py
@@ -67,10 +67,10 @@ def subgraph_centrality_exp(G):
 
     Examples
     --------
-    (from [1]_)
+    (Example from [1]_)
     >>> G = nx.Graph([(1,2),(1,5),(1,8),(2,3),(2,8),(3,4),(3,6),(4,5),(4,7),(5,6),(6,7),(7,8)])
     >>> sc = nx.subgraph_centrality_exp(G)
-    >>> print(['%s %0.2f'%(node,sc[node]) for node in sc])
+    >>> print(['%s %0.2f'%(node,sc[node]) for node in sorted(sc)])
     ['1 3.90', '2 3.90', '3 3.64', '4 3.71', '5 3.64', '6 3.71', '7 3.64', '8 3.90']
     """
     # alternative implementation that calculates the matrix exponential
@@ -130,9 +130,10 @@ def subgraph_centrality(G):
 
     Examples
     --------
+    (Example from [1]_)
     >>> G = nx.Graph([(1,2),(1,5),(1,8),(2,3),(2,8),(3,4),(3,6),(4,5),(4,7),(5,6),(6,7),(7,8)])
     >>> sc = nx.subgraph_centrality(G)
-    >>> print(['%s %0.2f'%(node,sc[node]) for node in sc])
+    >>> print(['%s %0.2f'%(node,sc[node]) for node in sorted(sc)])
     ['1 3.90', '2 3.90', '3 3.64', '4 3.71', '5 3.64', '6 3.71', '7 3.64', '8 3.90']
 
     References


Test patch:
Repository: networkx/networkx

Issue:
nx.power does not preserve zero-degree nodes
```shell
>>> G = nx.Graph()
>>> G.add_nodes_from([0, 1, 2])
>>> G.add_edge(0, 1)
>>> G2 = nx.power(G, 2)
>>> G.nodes()
[0, 1, 2]
>>> G2.nodes()
[0, 1]
```

Here `nx.power` fails to preserve the zero-degree node 2 in `G2`. This happens for all graphs in all such scenarios.

It is easy to see the problem: [the implementation](https://github.com/networkx/networkx/blob/master/networkx/algorithms/operators/product.py#L415-L434) adds nodes only as a byproduct of adding edges, and never actually initializes the result to contain all original nodes. A simple fix would be to change [this line](https://github.com/networkx/networkx/blob/master/networkx/algorithms/operators/product.py#L415) to `H = G.copy()` or `H = nx.Graph(); H.add_nodes_from(G.nodes())`. I can make a quick PR if this fix makes sense.


Discussion:

Resolving patch:
diff --git a/networkx/algorithms/operators/product.py b/networkx/algorithms/operators/product.py
--- a/networkx/algorithms/operators/product.py
+++ b/networkx/algorithms/operators/product.py
@@ -413,6 +413,7 @@ def power(G, k):
     if k <= 0:
         raise ValueError('k must be a positive integer')
     H = nx.Graph()
+    H.add_nodes_from(G)
     # update BFS code to ignore self loops.
     for n in G:
         seen = {}                  # level (number of hops) when seen in BFS


Test patch:
Repository: networkx/networkx

Issue:
adding attr dict to non-existent edge causes graph inconsistency
G.edge[node1][node2] = {"test":"test}

where G is of type networkx.classes.graph.Graph

will add an edge from node1 to node2, but node1 will not be in node2's neighbor list (G.neighbors(node2). This can lead to an inconsistent graph with an edge leading to a non-existent node.

(tested on networkx 1.11)



Discussion:
The method for adding edge to a graph is `G.add_edge(u, v)`. Modifying the underlying data structure dictionaries directly will certainly cause inconsistencies, but there's not much we can do about that (that's a feature of Python). So I guess all we can say in this situation is "don't do that". Is there some change to the code or documentation that you are requesting here?

I'll be honest, I didn't realize `G.edge[node1][node2] = {"test":"test}` wasn't a supported way of doing it.  I suppose some way of warning users not to use it would be best.

Perhaps a note in the [Edge Attributes](https://networkx.readthedocs.io/en/latest/tutorial/tutorial.html#edge-attributes) section of the tutorial and the class-level documentation for the `Graph` class to only read from `Graph.edge`, not write to it?


Resolving patch:
diff --git a/networkx/classes/graph.py b/networkx/classes/graph.py
--- a/networkx/classes/graph.py
+++ b/networkx/classes/graph.py
@@ -141,6 +141,10 @@ class Graph(object):
     >>> G[1][2]['weight'] = 4.7
     >>> G.edge[1][2]['weight'] = 4
 
+    Warning: assigning to `G.edge[u]` or `G.edge[u][v]` will almost certainly 
+    corrupt the graph data structure. Use 3 sets of brackets as shown above.
+    (4 for multigraphs: `MG.edge[u][v][key][name] = value`)
+
     **Shortcuts:**
 
     Many common graph features allow python syntax to speed reporting.


Test patch:
Repository: networkx/networkx

Issue:
Reading GML files
Reading the `polblogs.gml` file [downloaded here ](http://www-personal.umich.edu/~mejn/netdata/) using NetworkX's `read_gml` function throws `NetworkXError: edge is duplicated`. 

This was not the case previously. I'm running both `Python 2.7` and `Python 3.6`; the same error is thrown using both kernels. My NetworkX version is 1.11.




Discussion:
It looks like the code has changed significantly since your previous experience.   I didn't look into the details yet. A workaround for this error is to add "multigraph 1" to the header of the file to reflect that it has multiple edges
```
graph [
  directed 1
  multigraph 1
  node [
    id 1
...
```
The previous version of read_gml figured out whether the input file was a graph or multigraph by inspecting all of the edges.
At minimum this needs some documentation.

Resolving patch:
diff --git a/networkx/readwrite/gml.py b/networkx/readwrite/gml.py
--- a/networkx/readwrite/gml.py
+++ b/networkx/readwrite/gml.py
@@ -423,7 +423,9 @@ def pop_attr(dct, category, attr, i):
                 G.add_edge(source, target, **edge)
             else:
                 raise nx.NetworkXError(
-                    'edge #%d (%r%s%r) is duplicated' %
+                    """edge #%d (%r%s%r) is duplicated
+
+Hint:  If this is a multigraph, add "multigraph 1" to the header of the file.""" %
                     (i, source, '->' if directed else '--', target))
         else:
             key = edge.pop('key', None)


Test patch:
Repository: networkx/networkx

Issue:
Node contraction documentation should provide an example with multigraphs
Node or edge contraction is really a multigraph operation. For example, identifying the two endpoints of the path graph on three vertices yields a graph with two nodes and two parallel edges joining them. This should be at least an example in the documentation, and probably a unit test too.



Discussion:

Resolving patch:
diff --git a/networkx/algorithms/minors.py b/networkx/algorithms/minors.py
--- a/networkx/algorithms/minors.py
+++ b/networkx/algorithms/minors.py
@@ -309,13 +309,17 @@ def contracted_nodes(G, u, v, self_loops=True):
     Contracting two nonadjacent nodes of the cycle graph on four nodes `C_4`
     yields the path graph (ignoring parallel edges)::
 
-        >>> import networkx as nx
         >>> G = nx.cycle_graph(4)
         >>> M = nx.contracted_nodes(G, 1, 3)
         >>> P3 = nx.path_graph(3)
         >>> nx.is_isomorphic(M, P3)
         True
 
+        >>> G = nx.MultiGraph(P3)
+        >>> M = nx.contracted_nodes(G, 0, 2)
+        >>> M.edges
+        MultiEdgeView([(0, 1, 0), (0, 1, 1)])
+
     See also
     --------
     contracted_edge


Test patch:
diff --git a/networkx/algorithms/tests/test_minors.py b/networkx/algorithms/tests/test_minors.py
--- a/networkx/algorithms/tests/test_minors.py
+++ b/networkx/algorithms/tests/test_minors.py
@@ -222,6 +222,15 @@ def test_directed_node_contraction(self):
         expected.add_edge(0, 0)
         assert_true(nx.is_isomorphic(actual, expected))
 
+    def test_create_multigraph(self):
+        """Tests that using a MultiGraph creates multiple edges."""
+        G = nx.path_graph(3, create_using=nx.MultiGraph())
+        actual = nx.contracted_nodes(G, 0, 2)
+        expected = nx.MultiDiGraph()
+        expected.add_edge(0, 1)
+        expected.add_edge(0, 1)
+        assert_edges_equal(actual.edges, expected.edges)
+
     def test_node_attributes(self):
         """Tests that node contraction preserves node attributes."""
         G = nx.cycle_graph(4)
@@ -234,7 +243,8 @@ def test_node_attributes(self):
         expected = nx.complete_graph(3)
         expected = nx.relabel_nodes(expected, {1: 2, 2: 3})
         expected.add_edge(0, 0)
-        expected.node[0].update(dict(foo='bar', contraction={1: dict(baz='xyzzy')}))
+        cdict = {1: {'baz': 'xyzzy'}}
+        expected.node[0].update(dict(foo='bar', contraction=cdict))
         assert_true(nx.is_isomorphic(actual, expected))
         assert_equal(actual.node, expected.node)