| | """ |
| | Generate scale-free graph and output degree-distribution CSV file |
| | """ |
| |
|
| | import numpy as np |
| | import networkx as nx |
| | from collections import Counter |
| | import csv |
| | import sys |
| |
|
| |
|
| | def kronecker_generator(scale, edge_factor): |
| | """Kronecker graph generator |
| | Ported from octave code in https://graph500.org/?page_id=12#alg:generator |
| | """ |
| | N = 2 ** scale |
| | M = N * edge_factor |
| | A, B, C = (0.57, 0.19, 0.19) |
| | ijw = np.ones((3, M)) |
| |
|
| | ab = A + B |
| | c_norm = C / (1 - (A + B)) |
| | a_norm = A / (A + B) |
| |
|
| | for ib in range(scale): |
| | ii_bit = (np.random.rand(1, M) > ab).astype(int) |
| | ac = c_norm * ii_bit + a_norm * (1 - ii_bit) |
| | jj_bit = (np.random.rand(1, M) > ac).astype(int) |
| | ijw[:2, :] = ijw[:2, :] + 2 ** ib * np.vstack((ii_bit, jj_bit)) |
| |
|
| | ijw[2, :] = np.random.rand(1, M) |
| | ijw[:2, :] = ijw[:2, :] - 1 |
| | q = range(M) |
| | np.random.shuffle(q) |
| | ijw = ijw[:, q] |
| | edges = ijw[:2, :].astype(int).T |
| | _g = nx.DiGraph() |
| | _g.add_edges_from(edges) |
| | return _g |
| |
|
| |
|
| | def kronecker_generator_general(_n, _m): |
| | |
| | A, B, C = (0.57, 0.19, 0.19) |
| | ijw = np.ones((3, _m)) |
| | ab = A + B |
| | c_norm = C / (1 - (A + B)) |
| | a_norm = A / (A + B) |
| | tmp = _n |
| | while tmp > 0: |
| | tmp //= 2 |
| | ii_bit = (np.random.rand(1, _m) > ab).astype(int) |
| | ac = c_norm * ii_bit + a_norm * (1 - ii_bit) |
| | jj_bit = (np.random.rand(1, _m) > ac).astype(int) |
| | ijw[:2, :] = ijw[:2, :] + tmp * np.vstack((ii_bit, jj_bit)) |
| | ijw[2, :] = np.random.rand(1, _m) |
| | ijw[:2, :] = ijw[:2, :] - 1 |
| | q = range(_m) |
| | np.random.shuffle(q) |
| | ijw = ijw[:, q] |
| | edges = ijw[:2, :].astype(int).T |
| | _g = nx.DiGraph() |
| | _g.add_edges_from(edges) |
| | return _g |
| |
|
| |
|
| | def powerlaw_cluster_generator(_n, _edge_factor): |
| | edges = nx.barabasi_albert_graph(_n, _edge_factor, seed=0).edges() |
| |
|
| | |
| | di_edges = [(edges[i][0], edges[i][1]) if i % 2 == 0 else (edges[i][1], edges[i][0]) for i in range(len(edges))] |
| | _g = nx.DiGraph() |
| | _g.add_edges_from(di_edges) |
| | return _g |
| |
|
| |
|
| | if __name__ == "__main__": |
| | argv = sys.argv |
| | if len(argv) < 4: |
| | print("Usage: python3 %s [NumVertices] [EdgeFactor] [DegCSV]" % argv[0]) |
| | exit(1) |
| |
|
| | n = int(argv[1]) |
| | factor = int(argv[2]) |
| | g = powerlaw_cluster_generator(n, factor) |
| |
|
| | print("Number of vertices: %d" % g.number_of_nodes()) |
| | print("Number of edges: %d" % g.number_of_edges()) |
| |
|
| | in_deg = Counter(g.in_degree().values()) |
| | out_deg = Counter(g.out_degree().values()) |
| |
|
| | keys = set(sorted(list(in_deg.keys()) + list(out_deg.keys()))) |
| |
|
| | with open(argv[3], "w") as wf: |
| | writer = csv.writer(wf) |
| | writer.writerow(["Count", "In-degree", "Out-degree"]) |
| | for k in keys: |
| | |
| | writer.writerow([k, in_deg[k], out_deg[k]]) |
| |
|