问题
I was wondering is there a way to obtain all the different trees using Networkx? It's a known fact that the number of trees with n
nodes is n^(n-2)
(using Cayley's Formula) so if there is 3 nodes, then it has 3 tree graphs, if it has 4 nodes then it has 16 trees and so on. What I want is to code all the trees using the prufer sequence, I know that Networkx has a function to create random trees, but there is a chance I can get duplicates, all I can think of is use Numpy so I can find all the unique elements in a list, here is my code:
import numpy as np
import networkx as nx
n = 3 #Number of nodes
aux = []
prufer = []
for i in range(10):
aux.append(nx.random_tree(n))
for j in aux:
prufer.append(nx.to_prufer_sequence(j))
arr = np.array(prufer)
newarr = np.unique(arr, axis = 0)
The problem here it's that I generated 10 random trees, but in the end I only want 3 but when I want to find all the trees using 4 nodes I don't want to generate 50 if I'm only going to use 16. Is there a way I can do this more efficiently? Thank you!
回答1:
This might be a bit bruteforcy, and there might be built-in functionality or a more elegant approach that I am missing, but it certainly is better than randomly generating the trees: You can use itertools to generate pairwise combinations and filter out duplicates and self-pointing loops:
import itertools
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
testcases:
len(make_all_trees(3)): 3
len(make_all_trees(4)): 16
len(make_all_trees(5)): 125
all 4 node trees:
trees = make_all_trees(4)
for p, tree in enumerate(trees):
plt.subplot(4,4,p+1)
nx.draw_networkx(tree)
plt.show()
来源:https://stackoverflow.com/questions/62116491/how-can-i-get-all-the-tree-graphs-given-a-certain-numbers-of-nodes-networkx