|
""" |
|
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]]) |
|
|