def hyperbolic_graph(N, deg, dia, dim, domain): '''The Hyperbolic Generator distributes points in hyperbolic space and adds edges between points with a probability depending on their distance. The resulting graphs have a power-law degree distribution, small diameter and high clustering coefficient. For a temperature of 0, the model resembles a unit-disk model in hyperbolic space. Parameters of the graph: N = Num of nodes k = Average degree gamma = Target exponent in Power Law Distribution Args: n (int or iterable) – Number of nodes or iterable of nodes dia (float) – Distance threshold value dim (int, optional): Dimension of the graph domain (str, optional): Domain of the graph Returns: Object: Best graph, beast average degree and best diameter. ''' import networkit as nk tolerance = 0.5 curr_deg_error = float('inf') count = 0 strt_time = time() while curr_deg_error > tolerance: G_Nk = nk.generators.HyperbolicGenerator(n = N,k = deg,gamma = 3.5).generate() G = graph_util.convertNkToNx(G_Nk) lcc,_ = graph_util.get_nk_lcc_undirected(G) curr_avg_deg = np.mean(list(dict(nx.degree(lcc)).values())) curr_deg_error = abs(curr_avg_deg - deg) count += 1 if count == 1000: break best_G = lcc best_avg_deg = curr_avg_deg best_diam = nx.algorithms.diameter(lcc) end_time = time() print('Graph_Name: Hyperbolic Graph') print('Num_Nodes: ', nx.number_of_nodes(best_G), ' Avg_Deg : ', best_avg_deg, ' Diameter: ', best_diam) print('TIME: ', end_time - strt_time) return best_G, best_avg_deg, best_diam
def watts_strogatz_graph(N, deg, dia, dim, domain): '''Return a Watts-Strogatz small-world graph. First create a ring over n nodes. Then each node in the ring is connected with its k nearest neighbors (k-1 neighbors if k is odd). Then shortcuts are created by replacing some edges as follows: for each edge u-v in the underlying "n-ring with k nearest neighbors" with probability p replace it with a new edge u-w with uniformly random choice of existing node w. Parameters of the graph: n (int) – The number of nodes k (int) – Each node is joined with its k nearest neighbors in a ring topology. p (float) – The probability of rewiring each edge Average Degree is solely decided by k Diameter depends on the value of p Args: n (int or iterable) – Number of nodes or iterable of nodes dia (float) – Distance threshold value dim (int, optional): Dimension of the graph domain (str, optional): Domain of the graph Returns: Object: Best graph, beast average degree and best diameter. ''' strt_time = time() p = 0.2 G = nx.watts_strogatz_graph(n=N, k=deg, p=p) lcc, _ = graph_util.get_nk_lcc_undirected(G) best_G = lcc best_diam = nx.algorithms.diameter(best_G) best_avg_deg = np.mean(list(dict(nx.degree(best_G)).values())) end_time = time() print('Graph_Name: Watts_Strogatz_Graph') print('Num_Nodes: ', nx.number_of_nodes(best_G), ' Avg_Deg : ', best_avg_deg, ' Diameter: ', best_diam) print('TIME: ', end_time - strt_time) return best_G, best_avg_deg, best_diam
def r_mat_graph(N, deg, dia, dim, domain): """Generates static R-MAT graphs. R-MAT (recursive matrix) graphs are random graphs with n=2^scale nodes and m=n*edgeFactor edges. More details at http://www.graph500.org or in the original paper: Deepayan Chakrabarti, Yiping Zhan, Christos Faloutsos: R-MAT: A Recursive Model for Graph Mining. Args: n (int or iterable) – Number of nodes or iterable of nodes dia (float) – Distance threshold value dim (int, optional): Dimension of the graph domain (str, optional): Domain of the graph Returns: Object: Best graph, beast average degree and best diameter. """ import networkit as nk tolerance = 0.5 curr_deg_error = float('inf') count = 0 strt_time = time() scale = np.log2(N) while curr_deg_error > tolerance: G_Nk = nk.generators.RmatGenerator(scale=scale,edgeFactor=deg/2, a=0.25,b=0.25,c=0.25,d=0.25).generate() G = graph_util.convertNkToNx(G_Nk) lcc,_ = graph_util.get_nk_lcc_undirected(G) curr_avg_deg = np.mean(list(dict(nx.degree(lcc)).values())) curr_deg_error = abs(curr_avg_deg - deg) count += 1 if count == 1000: break if count == 1000: raise("MAX TRIES EXCEEDED, TRY AGAIN") best_G = lcc best_avg_deg = curr_avg_deg best_diam = nx.algorithms.diameter(lcc) end_time = time() print('Graph_Name: RMAT') print('Num_Nodes: ', nx.number_of_nodes(best_G), ' Avg_Deg : ', best_avg_deg, ' Diameter: ', best_diam) print('TIME: ', end_time - strt_time) return best_G, best_avg_deg, best_diam
def stochastic_block_model(N, deg, dia, dim, domain): '''Returns a stochastic block model graph. This model partitions the nodes in blocks of arbitrary sizes, and places edges between pairs of nodes independently, with a probability that depends on the blocks. :param N: Number of Nodes :param p: Element (r,s) gives the density of edges going from the nodes of group r to nodes of group s. p must match the number of groups (len(sizes) == len(p)), and it must be symmetric if the graph is undirected. Formula for p: Through Empirical Studies - p = 0.001 * Deg gives perfect result for Num_of_Nodes = 1024 But if N >1024: scaler = N/1024 : then p = (0.001*deg)/scaler And if N < 1024 : Scaler = 1024/N : then p = (0.001*deg)*scaler and if N == 1024: p = (0.001*deg) Args: n (int or iterable) – Number of nodes or iterable of nodes dia (float) – Distance threshold value dim (int, optional): Dimension of the graph domain (str, optional): Domain of the graph Returns: Object: Best graph, beast average degree and best diameter. ''' tolerance = 0.5 curr_deg_error = float('inf') count = 0 p_default = 0.001 * deg N_default = 1024 if N_default > N: p_scaler = N_default/N p = p_default * p_scaler elif N_default < N: p_scaler = N / N_default p = p_default / p_scaler else: p = p_default strt_time = time() while curr_deg_error > tolerance: G = nx.generators.stochastic_block_model([N],[[p]]) lcc,_ = graph_util.get_nk_lcc_undirected(G) curr_avg_deg = np.mean(list(dict(nx.degree(G)).values())) curr_deg_error = abs(curr_avg_deg - deg) count += 1 if count == 1000: break best_G = lcc best_avg_deg = curr_avg_deg best_diam = nx.algorithms.diameter(lcc) end_time = time() print('Graph_Name: Stochastic Block Model') print('Num_Nodes: ', nx.number_of_nodes(best_G), ' Avg_Deg : ', best_avg_deg, ' Diameter: ', best_diam) print('TIME: ', end_time - strt_time) return best_G, best_avg_deg, best_diam
def powerlaw_cluster_graph(N, deg, dia, dim, domain): '''Holme and Kim algorithm for growing graphs with powerlaw degree distribution and approximate average clustering. The average clustering has a hard time getting above a certain cutoff that depends on ``m``. This cutoff is often quite low. The transitivity (fraction of triangles to possible triangles) seems to decrease with network size. It is essentially the Barabási–Albert (BA) growth model with an extra step that each random edge is followed by a chance of making an edge to one of its neighbors too (and thus a triangle). This algorithm improves on BA in the sense that it enables a higher average clustering to be attained if desired. It seems possible to have a disconnected graph with this algorithm since the initial ``m`` nodes may not be all linked to a new node on the first iteration like the BA model. Parameters of the graph: n (int) – the number of nodes m (int) – the number of random edges to add for each new node p (float,) – Probability of adding a triangle after adding a random edge Formula for m: (m^2)- (Nm)/2 + avg_deg * (N/2) = 0 => From this equation we need to find m : p : Does not vary the average degree or diameter so much. : Higher value of p may cause average degree to overshoot intended average_deg so we give the control of average degree to parameter m: by setting a lower value of p: 0.1 Args: n (int or iterable) – Number of nodes or iterable of nodes dia (float) – Distance threshold value dim (int, optional): Dimension of the graph domain (str, optional): Domain of the graph Returns: Object: Best graph, beast average degree and best diameter. ''' ## Calculating thof nodes: 10\nNumber of edges: 16\nAverage degree: 3.2000' strt_time = time() m = int(round((N - np.sqrt(N ** 2 - 4 * deg * N)) / 4)) p = 0.2 ## G at center: G = nx.powerlaw_cluster_graph(n=N, m=m, p=p) lcc, _ = graph_util.get_nk_lcc_undirected(G) best_G = lcc best_diam = nx.algorithms.diameter(best_G) best_avg_deg = np.mean(list(dict(nx.degree(best_G)).values())) end_time = time() print('Graph_Name: powerlaw_cluster_graph') print('Num_Nodes: ', nx.number_of_nodes(best_G), ' Avg_Deg : ', best_avg_deg, ' Diameter: ', best_diam) print('TIME: ', end_time - strt_time) return best_G, best_avg_deg, best_diam
def duplication_divergence_graph(N, deg, dia, dim, domain): '''Returns an undirected graph using the duplication-divergence model. A graph of ``n`` nodes is created by duplicating the initial nodes and retaining edges incident to the original nodes with a retention probability ``p``. Parameters of the graph: n (int) – The desired number of nodes in the graph. p (float) – The probability for retaining the edge of the replicated node. Args: n (int or iterable) – Number of nodes or iterable of nodes dia (float) – Distance threshold value dim (int, optional): Dimension of the graph domain (str, optional): Domain of the graph Returns: Object: Best graph, beast average degree and best diameter. ''' strt_time = time() tolerance = 0.5 if deg == 4: lower_lim = 0.3 upper_lim = 0.4 bands = 10 elif deg == 6: lower_lim = 0.4 upper_lim = 0.6 bands = 15 elif deg == 8: lower_lim = 0.46 upper_lim = 0.60 bands = 15 elif deg == 10: lower_lim = 0.50 upper_lim = 0.65 bands = 15 elif deg == 12: lower_lim = 0.55 upper_lim = 0.68 bands = 15 flag = False curr_avg_deg_error = float('inf') while curr_avg_deg_error > tolerance: p_space = np.linspace(lower_lim, upper_lim, bands) avg_deg_err_list = [] p_gap = p_space[1] - p_space[0] for p_val in p_space: G = nx.duplication_divergence_graph(n=N, p=p_val) lcc, _ = graph_util.get_nk_lcc_undirected(G) curr_avg_deg = np.mean(list(dict(nx.degree(lcc)).values())) curr_avg_deg_error = abs(deg - curr_avg_deg) avg_deg_err_list.append((lcc, curr_avg_deg_error, p_val, curr_avg_deg)) if deg - curr_avg_deg < 0: break if curr_avg_deg_error <= tolerance: best_G = lcc best_avg_deg = curr_avg_deg best_diam = nx.algorithms.diameter(best_G) flag = True break if flag == True: break sorted_avg_err = sorted(avg_deg_err_list, key=lambda x: x[1]) curr_avg_deg_error = sorted_avg_err[0][1] if sorted_avg_err[0][1] <= tolerance: best_G = sorted_avg_err[0][0] best_avg_deg = sorted_avg_err[0][3] best_diam = nx.algorithms.diameter(best_G) break else: lower_lim = sorted_avg_err[0][2] - p_gap upper_lim = sorted_avg_err[0][2] + p_gap end_time = time() print('Graph_Name: duplication divergence graph') print('Num_Nodes: ', nx.number_of_nodes(best_G), ' Avg_Deg : ', best_avg_deg, ' Diameter: ', best_diam) print('TIME: ', end_time - strt_time) return best_G, best_avg_deg, best_diam