Reputation: 10322
What's the fasted way in networkx
to get the crossing edges between two disjoint node sets?
Is there some ready-made function to use?
The way I am using now:
import networkx as nx
from itertools import product
A = set(range(50))
B = set(range(50, 100))
g = nx.complete_graph(100)
cross_edges = [(n1, n2)
for n1, n2 in product(A, B)
if n1 in g.adj and n2 in g.adj[n1]]
Upvotes: 3
Views: 4041
Reputation: 1026
You can use the edge_boundary function in Networkx.
The edge boundary of a set S with respect to a set T is the set of edges (u, v) such that u is in S and v is in T.
This is also called a cut-set, the set of edges that have one endpoint in each subset of the partition.
Upvotes: 8
Reputation: 5228
This is an old thread but here is the solution I'm working with.
def edges_cross(graph, nodes1, nodes2):
"""
Finds edges between two sets of disjoint nodes.
Running time is O(len(nodes1) * len(nodes2))
Args:
graph (nx.Graph): an undirected graph
nodes1 (set): set of nodes disjoint from nodes2
nodes2 (set): set of nodes disjoint from nodes1.
"""
return {(u, v) for u in nodes1
for v in nodes2.intersection(graph.adj[u])}
If n=len(nodes1)
and m=len(nodes2)
then this algorithm will run in O(nm)
because there are n iterations of the outer loop. Each inner loop calls nodes2.intersection
will runs in O(m)
time as long as graph.adj[u]
is a set (it is actually a dict, but this will operate on its keys which quack like a set). See python docs for more details about set intersection running time.
I also have a function for edges inside of a set of nodes which runs in O(n^2)
by a similar argument, but it contains a few tricks to reduce the constant factor as well.
def edges_inside(graph, nodes):
"""
Finds edges within a set of nodes
Running time is O(len(nodes) ** 2)
Args:
graph (nx.Graph): an undirected graph
nodes1 (set): a set of nodes
"""
result = set([])
upper = nodes.copy()
graph_adj = graph.adj
for u in nodes:
for v in upper.intersection(graph_adj[u]):
result.add((u, v))
upper.remove(u)
return result
Upvotes: 0
Reputation: 5448
It depends on assumptions about the graph.
If graph is dense than your approach is optimal since set of result edges is almost the same as product(A,B)
. Than it is goot to iterate through all possible edges (product(A,B)
) and check is it an edge.
If graph is sparse than it would be faster to iterate through existing edges and check for edges between A and B. Something like:
Bs = set(B) # 'in' operator is faster for sets
result = []
for n1 in A: # Iterate through first set
for n2 in g.adj[n1]: # Than through edges connected to a node
if n2 in Bs: # Check is it edge between A and B
result.append(n1, n2)
Possible optimization is to set A to be smaller of two input sets.
Upvotes: 0