diff --git a/.gitignore b/.gitignore index fbaf40d11fa..1ee2944de32 100644 --- a/.gitignore +++ b/.gitignore @@ -21,5 +21,5 @@ doc/source/examples/* # Generated when 'python setup_egg.py' networkx.egg-info/ -Networkx.sublime-project -Networkx.sublime-workspace +*.sublime-project +*.sublime-workspace diff --git a/networkx/classes/function.py b/networkx/classes/function.py index 321d8be59a9..9f035b9848f 100644 --- a/networkx/classes/function.py +++ b/networkx/classes/function.py @@ -18,7 +18,7 @@ 'freeze','is_frozen','subgraph','create_empty_copy', 'set_node_attributes','get_node_attributes', 'set_edge_attributes','get_edge_attributes', - 'all_neighbors','non_neighbors'] + 'all_neighbors','non_neighbors', 'non_edges'] def nodes(G): """Return a copy of the graph nodes in a list.""" @@ -425,3 +425,28 @@ def non_neighbors(graph, node): """ nbors = set(neighbors(graph, node)) | set([node]) return (nnode for nnode in graph if nnode not in nbors) + +def non_edges(graph): + """Returns the non-existent edges in the graph. + + Parameters + ---------- + graph : NetworkX graph. + Graph to find non-existent edges. + + Returns + ------- + non_edges : iterator + Iterator of edges that are not in the graph. + """ + if graph.is_directed(): + for u in graph.nodes_iter(): + for v in non_neighbors(graph, u): + yield (u, v) + else: + S = set() + for u in graph.nodes_iter(): + for v in non_neighbors(graph, u): + if (u, v) not in S: + yield (u, v) + S.add((v, u)) diff --git a/networkx/classes/tests/test_function.py b/networkx/classes/tests/test_function.py index 2c121787772..f813908ac20 100644 --- a/networkx/classes/tests/test_function.py +++ b/networkx/classes/tests/test_function.py @@ -188,3 +188,29 @@ def test_non_neighbors(self): graph.add_nodes_from(range(10)) nbors = list(nx.non_neighbors(graph, 0)) assert_equal(len(nbors), 9) + + def test_non_edges(self): + # All possible edges exist + graph = nx.complete_graph(5) + nedges = list(nx.non_edges(graph)) + assert len(nedges) == 0 + + graph = nx.path_graph(4) + expected = [(0, 2), (0, 3), (1, 3)] + nedges = list(nx.non_edges(graph)) + for (u, v) in expected: + assert (u, v) in nedges or (v, u) in nedges + + graph = nx.star_graph(4) + expected = [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)] + nedges = list(nx.non_edges(graph)) + for (u, v) in expected: + assert (u, v) in nedges or (v, u) in nedges + + # Directed graphs + graph = nx.DiGraph() + graph.add_edges_from([(0, 2), (2, 0), (2, 1)]) + expected = [(0, 1), (1, 0), (1, 2)] + nedges = list(nx.non_edges(graph)) + for e in expected: + assert e in nedges