def compute_user_pagerank(network, user, directed_networks, weighted): if len(network.es) == 0: return 1 options = igraph.ARPACKOptions() options.mxiter = 100000 # Igraph 0.7 has a bad bug! It does not give pagerank of a specific user. It # only returns pagerank of first user in the graph, no matter what the # vertices argument is. So we get a list of all pageranks, then query in the # list with the index of node with name user user_index = network.vs.find(user).index if weighted: # if weights are requested, we should use the original weights rather than their inverse # (in contrast to closeness). In case of pagerank, large edge weights are good for the # incoming node. They give it more credit. weights = network.es['weight'] else: weights = None user_pagerank = network.pagerank(directed=directed_networks, damping=0.85, weights=weights, implementation="prpack", arpack_options=options)[user_index] if user_pagerank > 1: sys.stderr.write('Error: Pagerank of user %s is greater than one: %f' % (user, user_pagerank)) # Igraph returns tiny non-zero values for page ranks that should be really zero. # manually zero them out. if user_pagerank < pow(10, -15): user_pagerank = 0 return utils.round_to_sigfigs(user_pagerank, NUM_SIGFIGS)
def compute_user_pagerank(network, user, directed_networks, weighted): if len(network.es) == 0: return 1 options = igraph.ARPACKOptions() options.mxiter = 100000 # Igraph 0.7 has a bad bug! It does not give pagerank of a specific user. It # only returns pagerank of first user in the graph, no matter what the # vertices argument is. So we get a list of all pageranks, then query in the # list with the index of node with name user user_index = network.vs.find(user).index if weighted: # if weights are requested, we should use the original weights rather than their inverse # (in contrast to closeness). In case of pagerank, large edge weights are good for the # incoming node. They give it more credit. weights = network.es['weight'] else: weights = None user_pagerank = network.pagerank(directed=directed_networks, damping=0.85, weights=weights, implementation = "prpack", arpack_options = options)[user_index] if user_pagerank > 1: sys.stderr.write('Error: Pagerank of user %s is greater than one: %f' % (user, user_pagerank)) # Igraph returns tiny non-zero values for page ranks that should be really zero. # manually zero them out. if user_pagerank < pow(10, -15): user_pagerank = 0 return utils.round_to_sigfigs(user_pagerank, NUM_SIGFIGS)
def compute_network_weighted_average_path_length(network, directed_networks): if len(network.es) == 0: return 0 # weights are requested, we should use the inverse of weights, since higher weights # means more interactions between two users weights = [1.0 / w for w in network.es['weight']] if directed_networks: shortest_paths = network.shortest_paths(source=network.vs, target=network.vs, weights=weights, mode=igraph.OUT) else: shortest_paths = network.shortest_paths(source=network.vs, target=network.vs, weights=weights, mode=igraph.ALL) # iterate over all shortest paths and add them up # assign the largest path length to unconnected nodes max_path_length = -1 for i in shortest_paths: for path_length in i: if path_length != float('Inf') and path_length > max_path_length: max_path_length = path_length num_pairs = 0 sum_path_lengths = 0 for i in shortest_paths: for path_length in i: sum_path_lengths += min(path_length, max_path_length) num_pairs += 1 average_path_length = sum_path_lengths / num_pairs return utils.round_to_sigfigs(average_path_length, NUM_SIGFIGS)
def compute_network_weighted_average_path_length(network, directed_networks): if len(network.es) == 0: return 0 # weights are requested, we should use the inverse of weights, since higher weights # means more interactions between two users weights = [1.0/w for w in network.es['weight']] if directed_networks: shortest_paths = network.shortest_paths(source = network.vs, target = network.vs, weights = weights, mode = igraph.OUT) else: shortest_paths = network.shortest_paths(source = network.vs, target = network.vs, weights = weights, mode = igraph.ALL) # iterate over all shortest paths and add them up # assign the largest path length to unconnected nodes max_path_length = -1 for i in shortest_paths: for path_length in i: if path_length != float('Inf') and path_length > max_path_length: max_path_length = path_length num_pairs = 0 sum_path_lengths = 0 for i in shortest_paths: for path_length in i: sum_path_lengths += min(path_length, max_path_length) num_pairs += 1 average_path_length = sum_path_lengths / num_pairs return utils.round_to_sigfigs(average_path_length, NUM_SIGFIGS)
def compute_user_closeness_centrality(network, user, mode, weighted): if weighted: # if weights are requested, we should use the inverse of weights, since higher weights # means more interactions between two users weights = [1.0 / w for w in network.es['weight']] else: weights = None user_closeness_centrality = network.closeness(vertices=user, mode=mode, weights=weights) return utils.round_to_sigfigs(user_closeness_centrality, NUM_SIGFIGS)
def compute_user_closeness_centrality(network, user, mode, weighted): if weighted: # if weights are requested, we should use the inverse of weights, since higher weights # means more interactions between two users weights = [1.0/w for w in network.es['weight']] else: weights = None user_closeness_centrality = network.closeness(vertices = user, mode = mode, weights = weights) return utils.round_to_sigfigs(user_closeness_centrality, NUM_SIGFIGS)
def compute_laplacian_centrality(network, vertex): # find mapping from vertex to sum of edge weights vertex_weights = collections.defaultdict(float) for edge in network.es: source = edge["source"] target = edge["target"] weight = edge["weight"] vertex_weights[source] += weight vertex_weights[target] += weight neighbors = network.neighbors(vertex, mode="all") result = (vertex_weights[vertex]**2 + vertex_weights[vertex] + 2 * sum(vertex_weights[i] for i in neighbors)) return utils.round_to_sigfigs(result, NUM_SIGFIGS)
def compute_laplacian_centrality(network, vertex): # find mapping from vertex to sum of edge weights vertex_weights = collections.defaultdict(float) for edge in network.es: source = edge["source"] target = edge["target"] weight = edge["weight"] vertex_weights[source] += weight vertex_weights[target] += weight neighbors = network.neighbors(vertex, mode="all") result = (vertex_weights[vertex]**2 + vertex_weights[vertex] + 2 * sum(vertex_weights[i] for i in neighbors) ) return utils.round_to_sigfigs(result, NUM_SIGFIGS)
def compute_network_weighted_density(network, directed_networks): if len(network.es) == 0: return 0 num_vertices = len(network.vs) num_max_edges = num_vertices * (num_vertices - 1) sum_edge_weights = 0 for edge_weight in network.es['weight']: sum_edge_weights += edge_weight if directed_networks: density = (sum_edge_weights / num_max_edges) else: density = (2.0 * sum_edge_weights / num_max_edges) return utils.round_to_sigfigs(density, NUM_SIGFIGS)
def compute_user_betweenness_centrality(network, user, directed_networks, weighted): if len(network.es) == 0: return 1 if weighted: # if weights are requested, we should use the inverse of weights, since higher weights # means more interactions between two users so the path length should be smaller weights = [1.0/w for w in network.es['weight']] else: weights = None user_betweenness = network.betweenness(vertices = user, directed = directed_networks, weights = weights, nobigint = False) return utils.round_to_sigfigs(user_betweenness, NUM_SIGFIGS)
def compute_user_satoshi_pagerank(network, user, weighted): if len(network.es) == 0: return 1 if 'satoshi' not in network.vs["name"]: return 0 # increase the pagerank computation max number of iterations. sometimes arpack does not # converge. options = igraph.ARPACKOptions() options.mxiter = 100000 # Igraph 0.7 has a bad bug! It does not give pagerank of a specific user. It # only returns pagerank of first user in the graph, no matter what the # vertices argument is. So we get a list of all pageranks, then query in the # list with the index of node with name user user_index = network.vs.find(user).index if weighted: # if weights are requested, we should use the original weights rather than their inverse # (in contrast to closeness). In case of pagerank, large edge weights are good for the # incoming node. They give it more credit. weights = network.es['weight'] else: weights = None # Vertices should be the active user whose page rank we want to compute. directed # should be true so that directed paths are considered. damping is the probability # that we reset the random walk on Satoshi at each step. reset_vertices should only # contain Satoshi, since we are interested in flow from Satoshi. weights should be # the 'weight' attribute so that weights are used in page rank computation. user_satoshi_pagerank = network.personalized_pagerank( directed=True, damping=0.85, reset_vertices='satoshi', weights=weights, implementation="prpack", arpack_options=options)[user_index] if user_satoshi_pagerank > 1: sys.stderr.write( 'Error: Satoshi pagerank of user %s is greater than one: %f' % (user, user_satoshi_pagerank)) # Igraph returns tiny non-zero values for page ranks that should be really zero. # manually zero them out. if user_satoshi_pagerank < pow(10, -15): user_satoshi_pagerank = 0 return utils.round_to_sigfigs(user_satoshi_pagerank, NUM_SIGFIGS)
def compute_user_betweenness_centrality(network, user, directed_networks, weighted): if len(network.es) == 0: return 1 if weighted: # if weights are requested, we should use the inverse of weights, since higher weights # means more interactions between two users so the path length should be smaller weights = [1.0 / w for w in network.es['weight']] else: weights = None user_betweenness = network.betweenness(vertices=user, directed=directed_networks, weights=weights, nobigint=False) return utils.round_to_sigfigs(user_betweenness, NUM_SIGFIGS)
def compute_user_satoshi_pagerank(network, user, weighted): if len(network.es) == 0: return 1 if 'satoshi' not in network.vs["name"]: return 0 # increase the pagerank computation max number of iterations. sometimes arpack does not # converge. options = igraph.ARPACKOptions() options.mxiter = 100000 # Igraph 0.7 has a bad bug! It does not give pagerank of a specific user. It # only returns pagerank of first user in the graph, no matter what the # vertices argument is. So we get a list of all pageranks, then query in the # list with the index of node with name user user_index = network.vs.find(user).index if weighted: # if weights are requested, we should use the original weights rather than their inverse # (in contrast to closeness). In case of pagerank, large edge weights are good for the # incoming node. They give it more credit. weights = network.es['weight'] else: weights = None # Vertices should be the active user whose page rank we want to compute. directed # should be true so that directed paths are considered. damping is the probability # that we reset the random walk on Satoshi at each step. reset_vertices should only # contain Satoshi, since we are interested in flow from Satoshi. weights should be # the 'weight' attribute so that weights are used in page rank computation. user_satoshi_pagerank = network.personalized_pagerank( directed=True, damping=0.85, reset_vertices='satoshi', weights=weights, implementation = "prpack", arpack_options = options)[user_index] if user_satoshi_pagerank > 1: sys.stderr.write('Error: Satoshi pagerank of user %s is greater than one: %f' % (user, user_satoshi_pagerank)) # Igraph returns tiny non-zero values for page ranks that should be really zero. # manually zero them out. if user_satoshi_pagerank < pow(10, -15): user_satoshi_pagerank = 0 return utils.round_to_sigfigs(user_satoshi_pagerank, NUM_SIGFIGS)
def compute_user_clustering_coefficient(network, user): user_clustering_coefficient = network.transitivity_local_undirected( vertices=user, mode="zero") return utils.round_to_sigfigs(user_clustering_coefficient, NUM_SIGFIGS)
def compute_network_average_degree(network): average_degree = network.degree_distribution().mean return utils.round_to_sigfigs(average_degree, NUM_SIGFIGS)
def compute_network_clustering_coefficient(network): clustering_coefficient = network.transitivity_undirected(mode="zero") return utils.round_to_sigfigs(clustering_coefficient, NUM_SIGFIGS)
def compute_network_average_path_length(network, directed_networks): average_path_length = network.average_path_length(directed = directed_networks, unconn = True) return utils.round_to_sigfigs(average_path_length, NUM_SIGFIGS)
def compute_network_unweighted_average_path_length(network, directed_networks): average_path_length = network.average_path_length( directed=directed_networks, unconn=False) return utils.round_to_sigfigs(average_path_length, NUM_SIGFIGS)
def compute_network_unweighted_density(network): return utils.round_to_sigfigs(network.density(loops=True), NUM_SIGFIGS)
def compute_user_clustering_coefficient(network, user): user_clustering_coefficient = network.transitivity_local_undirected( vertices = user, mode = "zero") return utils.round_to_sigfigs(user_clustering_coefficient, NUM_SIGFIGS)