Создание дерева данных с помощью networkx в python

Я пытаюсь создать дерево, которое имеет 1111 узлов и организовано так, что узел 1 имеет 10 детей (от 2 до 11), узел 2 имеет 10 детей (от 12 до 21) и так далее... таким образом, чтобы каждый узел имел 10 детей с 1 узлов на корневом уровне, имеющий 10 дочерних узлов, каждый дочерний узел имеет 10 детей, и каждый из этих 100 узлов 10 дочерних узлов каждого это 1000 конечных узлов. Общее количество узлов 1111.

import networkx as nx
G = nx.Graph()
L1 = [1]
L2 = [x for x in range(2,12)]
L3 = [x for x in range(12,112)]
L4 = [x for x in range(112,1112)]

G.add_node(1)
G.add_nodes_from(L1)
G.add_nodes_from(L2)
G.add_nodes_from(L3)
G.add_nodes_from(L4)

теперь я хочу добавить ребра, используя G.add_edges_from([(x,y) for x in L1 for y in L2]) что нормально для первый уровень, но как это сделать для других уровней?

3 ответов


вы можете достичь желаемого результата "из коробки" в одной строке:

import networkx as nx

G = nx.balanced_tree(10,10)

вы можете обобщить создание графика на произвольную глубину и произвольное количество детей для каждого внутреннего узла.

если вы начинаете нумерацию уровней от 0 -- то есть корневой узел представляет Уровень 0 -- то каждый уровень содержит nуровень узлы.
n-количество дочерних элементов на каждом внутреннем узле.

вы можете определить индексы первого и последнего узла на каждом уровень.
Например, в вашем случае с n = 10 последними узлами для уровней 0, 1, 2, 3 являются
100 = 1,
100 + 101 = 11,
100 + 101 + 102 = 111,
100 + 101 + 102 + 103 = 1111.

чтобы найти индексы дочерних элементов для данного узла, вы берете индекс последнего узла на этот уровень и добавить смещение.
Если данный узел является первым (самым левым) узлом на этом уровне, смещение равно 0.
Если его последний узел на этом уровне смещение (nуровень - 1) * n.
Тогда (nуровень - 1) - количество узлов-предшественников на этом уровне.
В общем случае смещение рассчитывается как [количество узлов-предшественников на этом уровне] * n.

это понятие охватывается кодом как offset = ulim + i * n + 1.
Я добавил 1 чтобы иметь возможность цикл в следующем из 0 - (n-1) вместо с 1 - n.

import networkx as nx

n = 10  # the number of children for each node 
depth = 3 # number of levels, starting from 0

G = nx.Graph()
G.add_node(1) # initialize root

ulim = 0
for level in range(depth): # loop over each level
  nl = n**level # number of nodes on a given level
  llim = ulim + 1 # index of first node on a given level 
  ulim = ulim + nl # index of last node on a given level
  for i in range(nl): # loop over nodes (parents) on a given level
    parent = llim + i
    offset = ulim + i * n + 1 # index pointing to node just before first child
    for j in range(n): # loop over children for a given node (parent)
      child = offset + j
      G.add_node(child)
      G.add_edge(parent, child)

      # show the results
      print '{:d}-{:d}'.format(parent, child),
    print ''
  print '---------'

на depth = 3 и n = 3 это выход:

1-2 1-3 1-4 
---------
2-5 2-6 2-7 
3-8 3-9 3-10 
4-11 4-12 4-13 
---------
5-14 5-15 5-16 
6-17 6-18 6-19 
7-20 7-21 7-22 
8-23 8-24 8-25 
9-26 9-27 9-28 
10-29 10-30 10-31 
11-32 11-33 11-34 
12-35 12-36 12-37 
13-38 13-39 13-40 
---------

понял ответ

import networkx as nx
G = nx.Graph()
L1 = [1]
L2 = [x for x in range(2,12)]
L3 = [x for x in range(12,112)]
L4 = [x for x in range(112,1112)]


G.add_node(1)
G.add_nodes_from(L1)
G.add_nodes_from(L2)
G.add_nodes_from(L3)
G.add_nodes_from(L4)
G.add_edges_from([(x,y) for x in L1 for y in L2])
temp2 = []
temp = []
temp2.extend(L4)
temp.extend(L3)
for i in range(1,11,1):
    G.add_edges_from([x,temp.pop()] for x in L2)
    G.add_edges_from([y,temp2.pop()] for y in L3)

print G.nodes()
print G.edges()
print G.number_of_nodes()
print G.number_of_edges()
print G.neighbors(1)

try:
    diameter_of_myGraph =nx.shortest_path_length(G)
    #print diameter_of_myGraph
except nx.NetworkXNoPath:
    print 'No path'

try:
    avg_distance_of_myGraph =nx.average_shortest_path_length(G)
    print avg_distance_of_myGraph
except nx.NetworkXNoPath:
    print 'No path'