import matplotlib.pyplot as plt import networkx as nx import pandas as pd nn_total_levels = 0 def nn(cluster_no, node_name): if not nn_total_levels: return str(cluster_no) + '-' + node_name return str(cluster_no % nn_total_levels) + '-' + node_name def lvl(node_name): return int(node_name.split('-')[0]) def join_nodes(g, a, b, target_degree = 6): if not (g.degree[a] == target_degree or g.degree[b] == target_degree): g.add_edge(a, b) def start_file(p): index = ['i', 'N', 'E', 'S', 'D', 'D_avg', 'T', 'C'] open(p, 'w').write(','.join(index) + '\n') def write_file(p, data): index = ['i', 'N', 'E', 'S', 'D', 'D_avg', 'T', 'C'] open(p, 'a').write(','.join([str(data[i]) for i in index]) + '\n') def build_cluster(n): g = nx.Graph() nodes = ['ls', 'lu', 'ld', 'm', 'rd', 'ru', 'rs'] edges = [('ls', 'lu'), ('ls', 'ld'), ('ld', 'lu'), ('rs', 'ru'), ('rs', 'rd'), ('rd', 'ru'), ('lu', 'm'), ('ld', 'm'), ('ru', 'm'), ('rd', 'm')] g.add_nodes_from([nn(n, x) for x in nodes]) g.add_edges_from([tuple(nn(n, y) for y in x) for x in edges]) return g def build_network(n): throw_dist = 4 g = build_cluster(0) global nn_total_levels nn_total_levels = n for i in range(1, n): c = build_cluster(i) g = nx.union(g, c) for i in range(n): if n >= 2: if i % 2: join_nodes(g, nn(i, 'lu'), nn(i-1, 'lu'), 4) join_nodes(g, nn(i, 'rd'), nn(i-1, 'rd'), 4) else: join_nodes(g, nn(i, 'ld'), nn(i-1, 'ld'), 4) join_nodes(g, nn(i, 'ru'), nn(i-1, 'ru'), 4) g.add_edge(nn(i, 'ls'), nn(i-1, 'rs')) g.add_edge(nn(i, 'rs'), nn(i-1, 'ls')) if n > 1 * throw_dist: g.add_edge(nn(i, 'rs'), nn(i-(1*throw_dist), 'ls')) g.add_edge(nn(i, 'ls'), nn(i-(1*throw_dist), 'rs')) if n > 2 * throw_dist: a = nn(i, 'lu') b = nn(i-(2*throw_dist), 'lu') join_nodes(g, a, b) if n > 3 * throw_dist: a = nn(i, 'ld') b = nn(i-(3*throw_dist), 'ld') join_nodes(g, a, b) if n > 4 * throw_dist: a = nn(i, 'ru') b = nn(i-(4*throw_dist), 'ru') join_nodes(g, a, b) if n > 5 * throw_dist: a = nn(i, 'rd') b = nn(i-(5*throw_dist), 'rd') join_nodes(g, a, b) if n > 7 * throw_dist: a = nn(i, 'm') b = nn(i-(7*throw_dist), 'm') join_nodes(g, a, b) return g def analyze(G: nx.Graph) -> dict: N = G.number_of_nodes() E = G.number_of_edges() degs = G.degree() s_vals = [s[1] for s in degs] S = max(s_vals) D = nx.diameter(G) D_average = nx.average_shortest_path_length(G) Q = N*D_average/E C = N*D*S return { 'N': N, 'E': E, 'S': S, 'D': D, 'D_avg': round(D_average, 4), 'T': round(Q, 4), 'C': C, } def visualize(g): def draw_edges_between(a, b, lvl_min = 0, lvl_max = False, color = 'black', width = 1.0, debug = False, direct = False): edgelist = [e for e in g.edges() if all([True if (a in i) or (b in i) else False for i in e])] if debug: print(edgelist) if lvl_max.__class__ == bool: if debug: print("Running 1 branch") edgelist = [(pa, pb) for pa, pb in edgelist if not (abs(lvl(pa) - lvl(pb)) < lvl_min or nn_total_levels - abs(lvl(pa) - lvl(pb)) < lvl_min)] ''' for p in edgelist: if abs(lvl(pa) - lvl(pb)) < lvl_min: edgelist.remove((pa, pb)) ''' else: if debug: print(f"Running 2 branch on {edgelist}") edgelist = [(pa, pb) for pa, pb in edgelist if not ((abs(lvl(pa) - lvl(pb)) < lvl_min or nn_total_levels - abs(lvl(pa) - lvl(pb)) < lvl_min) or (abs(lvl(pa) - lvl(pb)) > lvl_max and nn_total_levels - abs(lvl(pa) - lvl(pb)) > lvl_max))] ''' for pa, pb in edgelist: if debug: print(f"Processing ({pa}, {pb})") if abs(lvl(pa) - lvl(pb)) < lvl_min or abs(lvl(pa) - lvl(pb)) > lvl_max: edgelist.remove((pa, pb)) if debug: print(f'Discarding {pa} <-> {pb} (lvl(pa) == {lvl(pa)}, lvl(pb) == {lvl(pb)})') elif debug: print(f'Leaving {pa} <-> {pb} (lvl(pa) == {lvl(pa)}, lvl(pb) == {lvl(pb)})') for pa, pb in edgelist: if debug: print(f"Processing ({pa}, {pb})") if abs(lvl(pa) - lvl(pb)) < lvl_min or abs(lvl(pa) - lvl(pb)) > lvl_max: edgelist.remove((pa, pb)) if debug: print(f'Discarding {pa} <-> {pb} (lvl(pa) == {lvl(pa)}, lvl(pb) == {lvl(pb)})') elif debug: print(f'Leaving {pa} <-> {pb} (lvl(pa) == {lvl(pa)}, lvl(pb) == {lvl(pb)})') ''' if debug: print(edgelist) if direct: nx.draw_networkx_edges(g, exp_pos, edgelist = edgelist, width = width, edge_color = color) else: nx.draw_networkx_edges(g, exp_pos, edgelist = edgelist, connectionstyle='arc3,rad=0.2', arrows=True, width = width, edge_color = color) pos = { 'ls': (-2, 0), 'lu': (-1, 1), 'ld': (-1, -1), 'm' : (0, 0), 'ru': (1, 1), 'rd': (1, -1), 'rs': (2, 0) } exp_pos = {} for i in range(nn_total_levels): for j, v in pos.items(): exp_pos[nn(i, j)] = (v[0], v[1] * 0.65 + 3 * i) nx.draw_networkx_nodes(g, exp_pos, node_size = 600) nx.draw_networkx_labels(g, exp_pos, font_size = 8) #nx.draw_networkx_edges(g, exp_pos, edgelist = [e for e in g.edges() if all([True if ('ls' in i) or ('rs' in i) else False for i in e])], connectionstyle='arc3,rad=0.2', arrows=True) # cluster draw_edges_between('', '', lvl_max = 0, color = '#888888', width = 0.5, direct = True) # S => 4 draw_edges_between('ls', 'rs', lvl_max = 1, color = '#33AAAA', width = 2) draw_edges_between('lu', 'lu', lvl_max = 1, color = '#AAAA33', width = 1) draw_edges_between('ru', 'ru', lvl_max = 1, color = '#AAAA33', width = 1) draw_edges_between('ld', 'ld', lvl_max = 1, color = '#AAAA33', width = 1) draw_edges_between('rd', 'rd', lvl_max = 1, color = '#AAAA33', width = 1) # S => 6 draw_edges_between('lu', 'lu', lvl_min = 2, color = '#FF0000', width = 1.5) draw_edges_between('ld', 'ld', lvl_min = 2, color = '#FFFF00', width = 1.5) draw_edges_between('ru', 'ru', lvl_min = 2, color = '#00FF00', width = 1.5) draw_edges_between('rd', 'rd', lvl_min = 2, color = '#00FFFF', width = 1.5) draw_edges_between('ls', 'ls', lvl_min = 2, color = '#0000FF', width = 1.5) draw_edges_between('rs', 'rs', lvl_min = 2, color = '#FF00FF', width = 1.5) draw_edges_between('m' , 'm' , lvl_min = 2, color = '#000000', width = 1.5) plt.show() def main(): i = 0 start_file('data.csv') d = None while True: i += 1 g = build_network(i) r = analyze(g) r.update({"i": i}) ''' if d.__class__ == None.__class__: d = pd.DataFrame(r, index = ['i', 'N', 'E', 'S', 'D', 'D_avg', 'T', 'C']) else: d.add(r) ''' print(r) write_file('data.csv', r) if g.number_of_nodes() > 1000: break #print(r) #nx.draw(g, with_labels = True) #plt.show() #d.to_csv('data.csv') def test(): g = build_network(15) print(analyze(g)) print([i for i, v in g.degree if v > 6]) print(g.adj['14-ld']) nx.draw(g, with_labels = True) plt.show() def test2(): g = build_network(144) print(analyze(g)) print(set([v for i, v in g.degree()])) def test3(): g = build_network(3) #print(g.adj['0-ls']) visualize(g) if __name__=="__main__": test3()