from collections import Counter import community from features_infra.feature_calculators import NodeFeatureCalculator, FeatureMeta class LouvainCalculator(NodeFeatureCalculator): def is_relevant(self): # relevant only for undirected graphs return not self._gnx.is_directed() def _calculate(self, include: set): partition = community.best_partition(self._gnx) com_size_dict = Counter(partition.values()) self._features = { node: com_size_dict[partition[node]] for node in self._gnx } feature_entry = { "louvain": FeatureMeta(LouvainCalculator, {"lov"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(LouvainCalculator, is_max_connected=True)
from features_infra.feature_calculators import NodeFeatureCalculator, FeatureMeta class GeneralCalculator(NodeFeatureCalculator): def is_relevant(self): return True def _calculate(self, include: set): if self._gnx.is_directed(): self._features = { node: (out_deg, in_deg) for (node, out_deg), (_, in_deg) in zip( self._gnx.out_degree(), self._gnx.in_degree()) } else: self._features = {node: deg for node, deg in self._gnx.degree()} feature_entry = { "general": FeatureMeta(GeneralCalculator, {"gen"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(GeneralCalculator, is_max_connected=True)
import networkx as nx from features_infra.feature_calculators import NodeFeatureCalculator, FeatureMeta class SquareClusteringCoefficientCalculator(NodeFeatureCalculator): def __init__(self, *args, **kwargs): super(SquareClusteringCoefficientCalculator, self).__init__(*args, **kwargs) def _calculate(self, include: set): self._features = nx.algorithms.cluster.square_clustering(self._gnx) def is_relevant(self): return True feature_entry = { "square_clustering_coefficient": FeatureMeta(SquareClusteringCoefficientCalculator, {"square_clustering"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(SquareClusteringCoefficientCalculator, is_max_connected=True)
denominator = sum((dist / avg_out[m]) * (self._alpha**(-m)) for m, dist in out_dist.items()) if 0 != denominator: numerator = sum((dist / avg_in[m]) * (self._alpha**(-m)) for m, dist in in_dist.items()) self._features[node] = numerator / denominator @staticmethod def _calculate_average_per_dist(num_nodes, count_dist): # rearrange the details in "count_dist" to be with unique distance in the array "all_dist_count" all_dist_count = {} for counter in count_dist.values(): for dist, occurrences in counter.items(): all_dist_count[dist] = all_dist_count.get(dist, 0) + occurrences # calculating for each distance the average return { dist: float(count) / num_nodes for dist, count in all_dist_count.items() } feature_entry = { "attractor_basin": FeatureMeta(AttractorBasinCalculator, {"ab"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(AttractorBasinCalculator, is_max_connected=True)
class EccentricityCalculator(NodeFeatureCalculator): def _calculate(self, include: set): dists = { src: neighbors for src, neighbors in nx.all_pairs_shortest_path_length(self._gnx) } self._features = { node: max(neighbors.values()) for node, neighbors in dists.items() } def _calculate_dep(self, include: set): # Not using eccentricity to handle disconnected graphs. (If a graph has more than 1 connected components, # the eccentricty will raise an exception) self._features = { node: nx.eccentricity(self._gnx, node) for node in self._gnx } def is_relevant(self): return True feature_entry = { "eccentricity": FeatureMeta(EccentricityCalculator, {"ecc"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(EccentricityCalculator, is_max_connected=True)
def test_all(): for cls in FEATURE_CLASSES: test_specific_feature(cls, is_max_connected=True)
import networkx as nx from graph_measures.features_infra.feature_calculators import NodeFeatureCalculator, FeatureMeta class BetweennessCentralityCalculator(NodeFeatureCalculator): def __init__(self, *args, normalized=False, **kwargs): super(BetweennessCentralityCalculator, self).__init__(*args, **kwargs) self._is_normalized = normalized def _calculate(self, include: set, is_regression=False): self._features = nx.betweenness_centrality( self._gnx, normalized=self._is_normalized) def is_relevant(self): return True feature_entry = { "betweenness_centrality": FeatureMeta(BetweennessCentralityCalculator, {"betweenness"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(BetweennessCentralityCalculator, is_max_connected=True)
import networkx as nx from features_infra.feature_calculators import NodeFeatureCalculator, FeatureMeta class EigenvectorCentralityCalculator(NodeFeatureCalculator): def __init__(self, *args, max_iter=1000, **kwargs): super(EigenvectorCentralityCalculator, self).__init__(*args, **kwargs) self._max_iter = max_iter def _calculate(self, include: set): self._features = nx.eigenvector_centrality(self._gnx, max_iter=self._max_iter) def is_relevant(self): return True feature_entry = { "eigenvector_centrality": FeatureMeta(EigenvectorCentralityCalculator, {"eigenvector"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(EigenvectorCentralityCalculator, is_max_connected=True)
import networkx as nx from features_infra.feature_calculators import NodeFeatureCalculator, FeatureMeta class AllPairsShortestPathLengthCalculator(NodeFeatureCalculator): def __init__(self, *args, **kwargs): super(AllPairsShortestPathLengthCalculator, self).__init__(*args, **kwargs) def _calculate(self, include: set): self._features = nx.algorithms.shortest_paths.unweighted.all_pairs_shortest_path_length( self._gnx) def is_relevant(self): return True feature_entry = { "all_pairs_shortest_path_length": FeatureMeta(AllPairsShortestPathLengthCalculator, {"all_pairs_shortest_path_length"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(AllPairsShortestPathLengthCalculator, is_max_connected=True)
class FiedlerVectorCalculator(NodeFeatureCalculator): def _calculate_dep(self, include: set): # Working on every connected component by itself self._features = dict(zip(self._gnx, alg_connectivity.fiedler_vector(self._gnx))) def _calculate(self, include: set): self._features = {} for connected_component in nx.connected_components(self._gnx): graph = self._gnx.subgraph(connected_component) if len(graph) < 2: self._features.update(zip(graph.nodes(), [0.] * len(graph))) else: self._features.update(zip(graph.nodes(), map(float, alg_connectivity.fiedler_vector(graph)))) def is_relevant(self): # Fiedler vector also works only on connected undirected graphs # so if gnx is not connected we shall expect an exception: networkx.exception.NetworkXError # return (not self._gnx.is_directed()) and (nx.is_connected(self._gnx.to_undirected())) return not self._gnx.is_directed() feature_entry = { "fiedler_vector": FeatureMeta(FiedlerVectorCalculator, {"fv"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(FiedlerVectorCalculator, is_max_connected=True)
feature_node_entry = { "motif3": FeatureMeta(nth_nodes_motif(3), {"m3"}), "motif4": FeatureMeta(nth_nodes_motif(4), {"m4"}), } feature_edge_entry = { "motif3_edge": FeatureMeta(nth_edges_motif(3), {"me3"}), "motif4_edge": FeatureMeta(nth_edges_motif(4), {"me4"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature # Previous version contained a bug while counting twice sub-groups with double edges # test_specific_feature(nth_edges_motif(3), is_max_connected=True) test_specific_feature(nth_edges_motif(4), is_max_connected=True) # def _calculate_motif_dictionaries(self): # motifs_edges_dict = {} # motifs_vertices_dict = {} # motif_edges = list(permutations(range(self._level), 2)) # # motif_file = pandas.read_csv(self._motif_path(), delimiter="\t") # if not self._gnx.is_directed(): # motifs_vertices_dict = {BitArray(length=3, int=int(y)).bin: int(x) for i, (x, y) in motif_file.iterrows()} # else: # num_edges = len(motif_edges) # for _, (x, y) in motif_file.iterrows(): # bin_repr = BitArray(length=num_edges, int=int(y)) # motifs_vertices_dict[bin_repr.bin] = int(x) # motifs_edges_dict[bin_repr.bin] = [edge_type for bit, edge_type in zip(bin_repr, motif_edges) if bit]
import networkx as nx from features_infra.feature_calculators import NodeFeatureCalculator, FeatureMeta class KCoreCalculator(NodeFeatureCalculator): def is_relevant(self): return True def _calculate(self, include: set): loopless_gnx = self._gnx.copy() loopless_gnx.remove_edges_from(nx.selfloop_edges(loopless_gnx)) self._features = nx.core_number(loopless_gnx) feature_entry = { "k_core": FeatureMeta(KCoreCalculator, {"kc"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(KCoreCalculator, is_max_connected=True)
import networkx as nx from features_infra.feature_calculators import NodeFeatureCalculator, FeatureMeta class PageRankCalculator(NodeFeatureCalculator): def __init__(self, *args, alpha=0.9, **kwargs): super(PageRankCalculator, self).__init__(*args, **kwargs) self._alpha = alpha def is_relevant(self): # Undirected graphs will be converted to a directed # graph with two directed edges for each undirected edge. return True def _calculate(self, include: set): self._features = nx.pagerank(self._gnx, alpha=self._alpha) feature_entry = { "page_rank": FeatureMeta(PageRankCalculator, {"pr"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(PageRankCalculator, is_max_connected=True)
import networkx as nx from features_infra.feature_calculators import NodeFeatureCalculator, FeatureMeta class PageRankCalculator(NodeFeatureCalculator): def __init__(self, *args, alpha=0.9, **kwargs): super(PageRankCalculator, self).__init__(*args, **kwargs) self._alpha = alpha def is_relevant(self): # Undirected graphs will be converted to a directed # graph with two directed edges for each undirected edge. return True def _calculate(self, include: set): self._features = nx.pagerank(self._gnx, alpha=self._alpha) feature_entry = { "page_rank": FeatureMeta(PageRankCalculator, {"pr"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(PageRankCalculator)
import networkx as nx from features_infra.feature_calculators import NodeFeatureCalculator, FeatureMeta class AverageNeighborDegreeCalculator(NodeFeatureCalculator): def is_relevant(self): return True def _calculate(self, include: set): self._features = nx.average_neighbor_degree(self._gnx) feature_entry = { "average_neighbor_degree": FeatureMeta(AverageNeighborDegreeCalculator, {"avg_nd"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(AverageNeighborDegreeCalculator, is_max_connected=True)
d = r return laplacian, y, tol, r, d @staticmethod def _initialize_vars_from_laplacian_matrix1(g): # creating laplacian matrix w = g + g.T d = np.diag(sum(w)) l = d - w _id = np.sum(g, 0) od = np.sum(g, 1) # initialize_vars b = np.subtract((np.array([od])).T, (np.array([_id])).T) tol = 0.001 n = np.size(g, 1) y = np.random.rand(n, 1) y = np.subtract(y, (1 / n) * sum(y)) k = np.dot(l, y) r = np.subtract(b, k) d = r return l, y, tol, r, d feature_entry = { "hierarchy_energy": FeatureMeta(HierarchyEnergyCalculator, {"hierarchy"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(HierarchyEnergyCalculator, is_max_connected=True)
# Fast and numerically precise: variance = np.average((values - average)**2, weights=weights) return average, np.sqrt(variance) def _calculate(self, include: set, is_regression=False): for node in self._gnx: # calculate BFS distances distances = nx.single_source_shortest_path_length(self._gnx, node) # distances.pop(node) # if not distances: # self._features[node] = [0., 0.] # continue node_dist = Counter(distances.values()) dists, weights = zip(*node_dist.items()) # This was in the previous version # instead of the above commented fix adjusted_dists = np.asarray([x + 1 for x in dists]) weights = np.asarray(weights) self._features[node] = list( self.weighted_avg_and_std(adjusted_dists, weights)) feature_entry = { "bfs_moments": FeatureMeta(BfsMomentsCalculator, {"bfs"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(BfsMomentsCalculator, is_max_connected=True)
import networkx as nx from features_infra.feature_calculators import NodeFeatureCalculator, FeatureMeta class LoadCentralityCalculator(NodeFeatureCalculator): def is_relevant(self): return True def _calculate(self, include: set): self._features = nx.load_centrality(self._gnx) feature_entry = { "load_centrality": FeatureMeta(LoadCentralityCalculator, {"load_c"}), } if __name__ == "__main__": from measure_tests.specific_feature_test import test_specific_feature test_specific_feature(LoadCentralityCalculator, is_max_connected=True)