Search code examples
pythongraphnetworkxadjacency-matrix

Trouble creating adjacency matrix using networkx


In the answer to this question there is code that creates all trees with a certain number of nodes.

The problem is that I tried to create the corresponding adjacency matrix using a built-in function in networkx nx.to_numpy_array but for some reason it's not working, the code is next:

#Function created by warped

import itertools
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt 

def make_all_trees(nodes):
    # generate all pairwise combinations of nodes
    edges =  [a for a in itertools.product(range(nodes), range(nodes))]

    # use sets to lose..
    # ..symmetric edges: (0,1), (1,0) => keep only (0,1) 
    edges = list(set([tuple(set(e)) for e in edges]))
    # ..and self-loops: (0,0)
    edges = [e for e in edges if len(e)>1]

    trees = []
    # generate all graphs that have nodes-1 edges
    for o in itertools.combinations(edges, nodes-1):
        #make sure that all nodes are in the edgelist:
        flattened = [item for sublist in o for item in sublist]

        if len(set(flattened)) == nodes:
            G = nx.Graph()
            G.add_edges_from(o)
            # make sure all nodes are connected
            if len(list(nx.connected_components(G)))==1:
                trees.append(G)

    return trees

#This is what I added it to create the corresponding adjacency matrix

trees = make_all_trees(3) #This create all the graph trees with 3 nodes, so it creates 3 trees

adjaux = []
for i in trees:
    adjaux.append(nx.to_numpy_array(i))

print(np.array(adjaux))

#Draws the graph
for p, tree in enumerate(trees):
    plt.subplot(4,4, p+1)
    nx.draw_networkx(tree)
plt.show()


The output is the following

enter image description here

#Adjacency matrix created 

adjaux = [[[0. 1. 0.]   [[0. 1. 1.]     [[0. 1. 0.] 
           [1. 0. 1.]    [1. 0. 0.]      [1. 0. 1.]
           [0. 1. 0.]]   [1. 0. 0.]]     [0. 1. 0.]]]


As you can see, although all the trees graph are correct and the first two adjacency matrix are correct, the last one is incorrect, the output should be:

adjaux = [[[0. 1. 0.]   [[0. 1. 1.]     [[0. 0. 1.] 
           [1. 0. 1.]    [1. 0. 0.]      [0. 0. 1.]
           [0. 1. 0.]]   [1. 0. 0.]]     [1. 1. 0.]]]

I tried re-creating the code step by step, but I can't see what and why it's not working, all seems to be fine, so any help will be appreciated, thank you!


Solution

  • documentation of nx.to_numpy_array:

    [...] nodelist (list, optional) – The rows and columns are ordered according to the nodes in nodelist. If nodelist is None, then the ordering is produced by G.nodes(). [...]

    Checking the order for your graphs:

    trees = make_all_trees(3)
    for tree in trees:
        print(tree.nodes())
    
    #output:
    [0, 1, 2] # first tree
    [0, 1, 2] # second tree
    [1, 2, 0] # third tree, node order is changed
    

    So, the adjacency matrix is correct in all cases (the graphs are displayed correctly, so edges must be recorded correctly), but the order is messed up. You need to explicitly specify the order of nodes in the nodelist argument:

    adjaux=[]
    for tree in trees:
        adjaux.append(nx.to_numpy_array(tree, nodelist=sorted(tree.nodes())))
    
    for a in adjaux:
        print('-'*10)
        print(a)
    
    ----------
    [[0. 1. 0.]
     [1. 0. 1.]
     [0. 1. 0.]]
    ----------
    [[0. 1. 1.]
     [1. 0. 0.]
     [1. 0. 0.]]
    ----------
    [[0. 0. 1.]
     [0. 0. 1.]
     [1. 1. 0.]]