def sphere(): n_samples = 2000 n = 3 edges_percent = 0.2 X = np.ndarray(shape=(n_samples, n)) for i in range(n_samples): x = np.random.multivariate_normal(np.zeros(n), np.eye(n)) X[i] = x / np.linalg.norm(x) plot_sphere(X, 'sphere') inner_prods = X @ X.T dists = np.arccos(np.clip(inner_prods, -1, 1)) print('Finished computing distances') dists_vec = dists[np.triu_indices(n_samples, 1)] n_edges = int((edges_percent * 0.5 * n_samples * (n_samples - 1)) / 100) neigh_threshold = np.partition(dists_vec, n_edges)[n_edges] print('Number of edges: {}, neigh threshold: {}'.format( n_edges, neigh_threshold)) graph = nx.Graph() graph.add_edges_from(np.argwhere(dists < neigh_threshold)) graph.remove_edges_from(graph.selfloop_edges()) graph = ricciCurvature(graph, alpha=0.99, method='OTD') graph = formanCurvature(graph) o_curvatures, f_curvatures = get_edge_curvatures(graph) plot_curvatures(o_curvatures, 'sphere_ollivier') plot_curvatures(f_curvatures, 'sphere_forman')
def grid(): g = nx.grid_graph([5, 5, 5], periodic=True) g = ricciCurvature(g, alpha=0.99, method='OTD') g = formanCurvature(g) o_curvs, f_curvs = get_edge_curvatures(g) plot_curvatures(o_curvs, 'o_grid') plot_curvatures(f_curvs, 'f_grid') print(o_curvs, f_curvs)
def full_graph(): graph = nx.complete_graph(10) graph = ricciCurvature(graph, alpha=0.5, method='ATD') graph = formanCurvature(graph) o_curvatures, f_curvatures = get_edge_curvatures(graph) plot_curvatures(o_curvatures, 'full_ollivier') plot_curvatures(f_curvatures, 'full_forman')
def regular_sphere(toy=False): if toy: # yapf: disable X = [ [0, 0, 1], # north pole [1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], # equator [0, 0, -1], # south pole ] # yapf: enable else: # Algorithm from https://www.cmu.edu/biolphys/deserno/pdf/sphere_equi.pdf n_samples = 100 a = 4 * np.pi / n_samples d = np.sqrt(a) m_nu = int(np.pi / d) d_nu = np.pi / m_nu d_phi = a / d_nu X = [] for m in range(m_nu): nu = np.pi * (m + 0.5) / m_nu m_phi = int(2 * np.pi * np.sin(nu) / d_phi) for n in range(m_phi): phi = 2 * np.pi * n / m_phi x = np.array([ np.sin(nu) * np.cos(phi), np.sin(nu) * np.sin(phi), np.cos(nu) ]) X.append(x) print('Number of points: ', len(X)) # plot it to make sure it looks 'regular' X = np.array(X) plot_sphere(X, 'regular_sphere') # compute distances inner_prods = X @ X.T dists = np.arccos(np.clip(inner_prods, -1, 1)) print('Finished computing distances') # search for the smallest distance which gives a single connected component # graph = search_smallest_dist_for_connected_graph(dists) # even better: use the largest-smallest connecting distance graph = largest_smallest_connecting_distance(dists) # degree distribution; should be small plot_degree_distribution(graph, 'regular_sphere') # curvature graph = ricciCurvature(graph, alpha=0.99, method='OTD') graph = formanCurvature(graph) o_curvatures, f_curvatures = get_edge_curvatures(graph) if toy: print(o_curvatures, f_curvatures) else: plot_curvatures(o_curvatures, 'regular_sphere_ollivier') plot_curvatures(f_curvatures, 'regular_sphere_forman')
def small_sphere(): # This yields positive curvatures, as expected, so the conclusion is that # the other ones working with the sphere yield a lot of 0 curvatures because # of the dense sampling which makes the neighbourhood of each node to look # flat. g = nx.Graph() g.add_edges_from([(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 5), (2, 4), (2, 5), (3, 4), (3, 5), (4, 5)]) g = ricciCurvature(g, alpha=0.5, method='OTD') g = formanCurvature(g) o_curvs, f_curvs = get_edge_curvatures(g) print(o_curvs, f_curvs)
def erdos_renyi(): n = 1000 p = 0.01 g = nx.Graph() for i in range(n): for j in range(i + 1, n): if np.random.rand() < p: g.add_edge(i, j) print('Number of edges: ', g.number_of_edges()) print('Number of connected components: ', nx.number_connected_components(g)) g = ricciCurvature(g, alpha=0.5, method='OTD') g = formanCurvature(g) o_curvs, f_curvs = get_edge_curvatures(g) plot_curvatures(o_curvs, 'o_gnp') plot_curvatures(f_curvs, 'f_gnp')
def balanced_tree(): branching = 3 depth = 5 g = nx.balanced_tree(branching, depth) print('Number of edges: ', g.number_of_edges()) g = ricciCurvature(g, alpha=0.99, method='OTD') g = formanCurvature(g) o_curvatures, f_curvatures = get_edge_curvatures(g) plot_curvatures(o_curvatures, 'balanced_tree_ollivier') plot_curvatures(f_curvatures, 'balanced_tree_forman') # this shows that the positively curved edges are on the last layer for limit in range(1, depth + 1): curvatures = [] for u, v in nx.bfs_edges(g, 0, depth_limit=limit): curvatures.append(g[u][v]['ricciCurvature']) plot_curvatures(np.array(curvatures), '{}_balanced'.format(limit))
def tree(): graph = nx.Graph() graph.add_edge(0, 1) for i in range(2, 2000): j = i - np.random.geometric(0.01) while j < 0: j = j + i graph.add_edge(i, j) nx.nx_pydot.write_dot(graph, 'output/random_tree.dot') graph = ricciCurvature(graph, alpha=0.99, method='OTD') graph = formanCurvature(graph) o_curvatures, f_curvatures = get_edge_curvatures(graph) plot_curvatures(o_curvatures, 'tree_ollivier') plot_curvatures(f_curvatures, 'tree_forman') # skip the last layer curvatures = [] for _, v, attrs in graph.edges(data=True): if graph.degree[v] > 1: curvatures.append(attrs['ricciCurvature']) plot_curvatures(curvatures, 'tree_no_leaves_ollivier')
def hypercube(): g = nx.hypercube_graph(5) g = ricciCurvature(g, alpha=0.5, method='OTD') g = formanCurvature(g) o_curvs, f_curvs = get_edge_curvatures(g) print(o_curvs, f_curvs)
def cycle(): g = nx.cycle_graph(10) g = ricciCurvature(g, alpha=0.5, method='OTD') g = formanCurvature(g) o_curvatures, f_curvatures = get_edge_curvatures(g) print(o_curvatures, f_curvatures)
import networkx as nx from GraphRicciCurvature.FormanRicci import formanCurvature from GraphRicciCurvature.OllivierRicci import ricciCurvature from GraphRicciCurvature.RicciFlow import compute_ricciFlow # Import an example NetworkX karate club graph G = nx.karate_club_graph() # Compute the Ollivier-Ricci curvature of the given graph G G = ricciCurvature(G, alpha=0.5, weight=None, verbose=False) print("Karate Club Graph: The Ollivier-Ricci curvature of edge (0,1) is %f" % G[0][1]["ricciCurvature"]) # Compute the Forman-Ricci curvature of the given graph G G = formanCurvature(G, verbose=False) print("Karate Club Graph: The Forman-Ricci curvature of edge (0,1) is %f" % G[0][1]["formanCurvature"]) #----------------------------------- # Construct a directed graph example Gd = nx.DiGraph() Gd.add_edges_from([(1, 2), (2, 3), (3, 4), (2, 4), (4, 2)]) # Compute the Ollivier-Ricci curvature of the given directed graph Gd Gd = ricciCurvature(Gd) for n1, n2 in Gd.edges(): print("Directed Graph: The Ollivier-Ricci curvature of edge(%d,%d) id %f" % (n1, n2, Gd[n1][n2]["ricciCurvature"])) # Compute the Forman-Ricci curvature of the given directed graph Gd