def diameter(self) -> float: CP.print_none('Calculating Diameter') diam = nx.diameter(self.graph) self.stats['diameter'] = diam return diam
def k_hop_reach(self) -> np.array: """ Returns the average number of nodes reachable from any node in k-hops Two levels of aggregation: 1. _k_hop_reachability gives the absolute count of nodes reachable within a k-hops from a node 2. overall_k_hop_dict aggregates the sum of all absolute counts for all nodes Normalizing factor: n ** 2 (once for each step) Then convert to a cumulative distribution :return: """ CP.print_none('Calculating hop-plot') overall_k_hop_dict = Counter() for node in self.graph.nodes(): k_hop_dict = self._k_hop_reachability_counter(node) overall_k_hop_dict += Counter(k_hop_dict) k_hop_vec = np.array([ v for k, v in sorted(overall_k_hop_dict.items(), key=lambda x: x[0]) ]) k_hop_vec = k_hop_vec / (self.graph.order()**2) self.stats['k_hop_reach'] = np.cumsum(k_hop_vec) return self.stats['k_hop_reach']
def clustering_coefficients_by_degree(self) -> Dict[int, float]: """ Returns the average clustering coefficient by degree :return: """ CP.print_none('Calculating Clustering Coefficients and CC by degree') clustering_coeffs = nx.clustering(self.graph) self.stats['clustering_coeffs'] = clustering_coeffs clustering_by_degree = {} # clustering per degree # get the sums for node, cc in clustering_coeffs.items(): deg = self.graph.degree[node] if deg not in clustering_by_degree: clustering_by_degree[deg] = [] clustering_by_degree[deg].append(cc) avg_clustering_by_degree = { deg: np.mean(ccs) for deg, ccs in clustering_by_degree.items() } self.stats[ 'clustering_coefficients_by_degree'] = avg_clustering_by_degree return avg_clustering_by_degree
def degree_centrality(self) -> Dict[int, float]: """ Degree centrality """ CP.print_none('Calculating Degree Centrality') degree_centrality = nx.degree_centrality(self.graph) self.stats['degree_centrality'] = degree_centrality return degree_centrality
def closeness_centrality(self) -> Dict[int, float]: """ Closeness centrality """ CP.print_none('Calculating Closeness Centrality') closeness = nx.closeness_centrality(self.graph) self.stats['closeness_centrality'] = closeness return closeness
def update(self, new_input_graph: nx.Graph) -> None: """ Update the model to (a) update the input graph, (b) fit the parameters :return: """ CP.print_none('Updating graph') self.input_graph = new_input_graph self._fit() # re-fit the parameters return
def pagerank(self) -> Dict[int, float]: """ PageRank centrality """ CP.print_none('Calculating PageRank') pagerank = nx.pagerank_scipy(self.graph) pagerank = {int(k): v for k, v in pagerank.items()} self.stats['pagerank'] = pagerank return pagerank
def assortativity(self) -> float: """ Returns the assortativity of the network :return: """ CP.print_none('Calculating Degree Assortativity') assortativity = nx.degree_assortativity_coefficient(self.graph) self.stats['assortativity'] = assortativity return assortativity
def adj_eigenvalues(self): """ Returns the eigenvalues of the Adjacency matrix :return: """ CP.print_none('Calculating eigenvalues of Adjacency Matrix') adj_eigenvalues = nx.adjacency_spectrum(self.graph) self.stats['adj_eigenvalues'] = adj_eigenvalues return adj_eigenvalues
def component_size_distribution(self) -> List[Tuple[int, float]]: """ Returns the distribution of component sizes and fraction of nodes in each component, largest first :return: """ CP.print_none('Calculating Component Size Distribution') component_size_ratio_list = [ (len(c), len(c) / self.graph.order()) for c in sorted( nx.connected_components(self.graph), key=len, reverse=True) ] self.stats['component_size_distribution'] = component_size_ratio_list return component_size_ratio_list
def laplacian_eigenvalues(self) -> np.array: """ Returns eigenvalues of the Laplacian :return: """ CP.print_none('Calculating Laplacian Eigenvalues') if self.graph.order() == 0 or self.graph.size() == 0: CP.print_orange( f'Graph has {self.graph.order()} nodes and {self.graph.size()} edges!' ) laplacian_eigs = [] else: laplacian_eigs = nx.laplacian_spectrum(self.graph) self.stats['laplacian_eigenvalues'] = laplacian_eigs return laplacian_eigs
def degree_dist(self, normalized=True) -> Dict[int, float]: """ Returns the degrees counter - keys: degrees, values: #nodes with that degree :return: """ CP.print_none('Calculating Degree Distribution') degree_seq = sorted(deg for _, deg in self.graph.degree()) self.stats['degree_seq'] = degree_seq degree_counts = Counter(degree_seq) if normalized: for deg, count in degree_counts.items(): degree_counts[deg] /= self.graph.order() self.stats['degree_dist'] = dict(degree_counts) return dict(degree_counts)