Search code examples
pythongraphnetworkx

What is the simplest way for generating all possible connected and non-connected undirected graphs containing N edges using NetworkX?


What is the simplest way for generating all possible connected and non-connected undirected graphs containing N edges using NetworkX?

I need to generate all possible connected and non-connected undirected graphs containing 6 edges using NetworkX. So I was hoping to write a function that works for other numbers of edges as well.

I have tried to use the built in generator functions in networkX functions to come up with a solution. None of the generator functions does what I need, but, maybe a combination of multiple generators could create the solution I was looking for.

My current code sample is using a single generator and visualizes the outputs in pyplot:

import networkx as nx
import matplotlib.pyplot as plt
N = 6

# Generate graphs with 6 edges [Need to help with this step]
all_graphs = list(nx.nonisomorphic_trees(N))

# Compute the Weisfeiler-Lehman hash for each graph
for i,graph in enumerate(all_graphs):
    # Compute the hash using the Weisfeiler-Lehman algorithm
    wl_hash = nx.weisfeiler_lehman_graph_hash(graph)
    
    plt.figure(i)
    nx.draw(graph)
    # Print the graph and its hash
    print("hash: ", wl_hash)

Any help is appreciated.


Solution

  • The below method uses recursion to compute all possible connected and non-connected undirected graphs containing N edges using NetworkX. The global variable graph_list contains all possible combinations after running the code. The below code does not discriminate between identical graph topologies that have been created form different node-edge combinations.

    import networkx as nx
    import matplotlib.pyplot as plt
    from copy import deepcopy
    
    N = 4
    graph_list = {}
    def build_graph(graph, N, edges, nodes):
        if edges == 0:
            graph_list.append(graph)
            return
        elif edges == N:
            nodes.append(0)
            nodes.append(1)
            cur_graph = deepcopy(graph)
            cur_graph.add_edge(nodes[0], nodes[1])
            build_graph(cur_graph, N, edges-1, nodes)
        else:
            nr_nodes = len(nodes)
    
            # add an edge from an existing node to a new node
            for node in range(nr_nodes):
                cur_nodes = nodes + [nr_nodes]
                cur_graph = deepcopy(graph)
                cur_graph.add_edge(node, nr_nodes)
                build_graph(cur_graph, N, edges-1, cur_nodes)
                
            # add an edge between two existing nodes that are not yet connected
            for i in range(nr_nodes):
                for j in range(nr_nodes):
                    if i != j and not graph.has_edge(i, j):
                        cur_graph = deepcopy(graph)
                        cur_graph.add_edge(i, j)
                        build_graph(cur_graph, N, edges-1, cur_nodes)
                        
            # add independent edge
            cur_nodes = nodes + [nr_nodes, nr_nodes +1]
            cur_graph = deepcopy(graph)
            cur_graph.add_edge(nr_nodes, nr_nodes+1)
            build_graph(cur_graph, N, edges-1, cur_nodes)
    
    build_graph(nx.Graph(), N, N, [])