diff --git a/cdlib/algorithms/crisp_partition.py b/cdlib/algorithms/crisp_partition.py index 7b1d42f..86ab152 100644 --- a/cdlib/algorithms/crisp_partition.py +++ b/cdlib/algorithms/crisp_partition.py @@ -364,7 +364,7 @@ def gdmp2(g_original: object, min_threshold: float = 0.75) -> NodeClustering: ) -def spinglass(g_original: object, spins: int = 25) -> NodeClustering: +def spinglass(g_original: object, spins: int = 25, weights: object = None) -> NodeClustering: """ Spinglass relies on an analogy between a very popular statistical mechanic model called Potts spin glass, and the community structure. It applies the simulated annealing optimization technique on this model to optimize the modularity. @@ -375,11 +375,12 @@ def spinglass(g_original: object, spins: int = 25) -> NodeClustering: ========== ======== ======== Undirected Directed Weighted ========== ======== ======== - Yes No No + Yes No Yes ========== ======== ======== :param g_original: a networkx/igraph object :param spins: the number of spins to use. This is the upper limit for the number of communities. It is not a problem to supply a (reasonably) big number here, in which case some spin states will be unpopulated. + :param weights: list of double, or edge attribute Weights of edges. Can be either an iterable or an edge attribute. Default None :return: NodeClustering object :Example: @@ -399,18 +400,18 @@ def spinglass(g_original: object, spins: int = 25) -> NodeClustering: ) g = convert_graph_formats(g_original, ig.Graph) - coms = g.community_spinglass(spins=spins) + coms = g.community_spinglass(spins=spins, weights=weights) communities = [] for c in coms: communities.append([g.vs[x]["name"] for x in c]) return NodeClustering( - communities, g_original, "Spinglass", method_parameters={"": ""} + communities, g_original, "Spinglass", method_parameters={"spins": spins, "weights": weights} ) -def eigenvector(g_original: object) -> NodeClustering: +def eigenvector(g_original: object, weights: object = None) -> NodeClustering: """ Newman's leading eigenvector method for detecting community structure based on modularity. This is the proper internal of the recursive, divisive algorithm: each split is done by maximizing the modularity regarding the original network. @@ -421,10 +422,11 @@ def eigenvector(g_original: object) -> NodeClustering: ========== ======== ======== Undirected Directed Weighted ========== ======== ======== - Yes No No + Yes No Yes ========== ======== ======== :param g_original: a networkx/igraph object + :param weights: list of double, or edge attribute Weights of edges. Can be either an iterable or an edge attribute. Default None :return: NodeClustering object :Example: @@ -445,12 +447,12 @@ def eigenvector(g_original: object) -> NodeClustering: ) g = convert_graph_formats(g_original, ig.Graph) - coms = g.community_leading_eigenvector() + coms = g.community_leading_eigenvector(weights=weights) communities = [g.vs[x]["name"] for x in coms] return NodeClustering( - communities, g_original, "Eigenvector", method_parameters={"": ""} + communities, g_original, "Eigenvector", method_parameters={"weights": weights} ) @@ -606,9 +608,9 @@ def leiden( ========== ======== ======== :param g_original: a networkx/igraph object - :param initial_membership: list of int Initial membership for the partition. If :obj:`None` then defaults to a singleton partition. Deafault None - :param weights: list of double, or edge attribute Weights of edges. Can be either an iterable or an edge attribute. Deafault None - :param resolution_parameter: double >0 A parameter value controlling the coarseness of the clustering. Higher resolutions lead to more communities, while lower resolutions lead to fewer communities. Deafault 1 + :param initial_membership: list of int Initial membership for the partition. If :obj:`None` then defaults to a singleton partition. Default None + :param weights: list of double, or edge attribute Weights of edges. Can be either an iterable or an edge attribute. Default None + :param resolution_parameter: double >0 A parameter value controlling the coarseness of the clustering. Higher resolutions lead to more communities, while lower resolutions lead to fewer communities. Default 1 :return: NodeClustering object :Example: @@ -690,8 +692,8 @@ def rb_pots( :param g_original: a networkx/igraph object - :param initial_membership: list of int Initial membership for the partition. If :obj:`None` then defaults to a singleton partition. Deafault None - :param weights: list of double, or edge attribute Weights of edges. Can be either an iterable or an edge attribute. Deafault None + :param initial_membership: list of int Initial membership for the partition. If :obj:`None` then defaults to a singleton partition. Default None + :param weights: list of double, or edge attribute Weights of edges. Can be either an iterable or an edge attribute. Default None :param resolution_parameter: double >0 A parameter value controlling the coarseness of the clustering. Higher resolutions lead to more communities, while lower resolutions lead to fewer communities. Default 1 :return: NodeClustering object @@ -770,10 +772,10 @@ def rber_pots( :param g_original: a networkx/igraph object - :param initial_membership: list of int Initial membership for the partition. If :obj:`None` then defaults to a singleton partition. Deafault None - :param weights: list of double, or edge attribute Weights of edges. Can be either an iterable or an edge attribute. Deafault None - :param node_sizes: list of int, or vertex attribute Sizes of nodes are necessary to know the size of communities in aggregate graphs. Usually this is set to 1 for all nodes, but in specific cases this could be changed. Deafault None - :param resolution_parameter: double >0 A parameter value controlling the coarseness of the clustering. Higher resolutions lead to more communities, while lower resolutions lead to fewer communities. Deafault 1 + :param initial_membership: list of int Initial membership for the partition. If :obj:`None` then defaults to a singleton partition. Default None + :param weights: list of double, or edge attribute Weights of edges. Can be either an iterable or an edge attribute. Default None + :param node_sizes: list of int, or vertex attribute Sizes of nodes are necessary to know the size of communities in aggregate graphs. Usually this is set to 1 for all nodes, but in specific cases this could be changed. Default None + :param resolution_parameter: double >0 A parameter value controlling the coarseness of the clustering. Higher resolutions lead to more communities, while lower resolutions lead to fewer communities. Default 1 :return: NodeClustering object :Example: @@ -865,10 +867,10 @@ def cpm( :param g_original: a networkx/igraph object - :param initial_membership: list of int Initial membership for the partition. If :obj:`None` then defaults to a singleton partition. Deafault None - :param weights: list of double, or edge attribute Weights of edges. Can be either an iterable or an edge attribute. Deafault None - :param node_sizes: list of int, or vertex attribute Sizes of nodes are necessary to know the size of communities in aggregate graphs. Usually this is set to 1 for all nodes, but in specific cases this could be changed. Deafault None - :param resolution_parameter: double >0 A parameter value controlling the coarseness of the clustering. Higher resolutions lead to more communities, while lower resolutions lead to fewer communities. Deafault 1 + :param initial_membership: list of int Initial membership for the partition. If :obj:`None` then defaults to a singleton partition. Default None + :param weights: list of double, or edge attribute Weights of edges. Can be either an iterable or an edge attribute. Default None + :param node_sizes: list of int, or vertex attribute Sizes of nodes are necessary to know the size of communities in aggregate graphs. Usually this is set to 1 for all nodes, but in specific cases this could be changed. Default None + :param resolution_parameter: double >0 A parameter value controlling the coarseness of the clustering. Higher resolutions lead to more communities, while lower resolutions lead to fewer communities. Default 1 :return: NodeClustering object :Example: @@ -948,8 +950,8 @@ def significance_communities( :param g_original: a networkx/igraph object - :param initial_membership: list of int Initial membership for the partition. If :obj:`None` then defaults to a singleton partition. Deafault None - :param node_sizes: list of int, or vertex attribute Sizes of nodes are necessary to know the size of communities in aggregate graphs. Usually this is set to 1 for all nodes, but in specific cases this could be changed. Deafault None + :param initial_membership: list of int Initial membership for the partition. If :obj:`None` then defaults to a singleton partition. Default None + :param node_sizes: list of int, or vertex attribute Sizes of nodes are necessary to know the size of communities in aggregate graphs. Usually this is set to 1 for all nodes, but in specific cases this could be changed. Default None :return: NodeClustering object :Example: @@ -1029,9 +1031,9 @@ def surprise_communities( ========== ======== ======== :param g_original: a networkx/igraph object - :param initial_membership: list of int Initial membership for the partition. If :obj:`None` then defaults to a singleton partition. Deafault None - :param weights: list of double, or edge attribute Weights of edges. Can be either an iterable or an edge attribute. Deafault None - :param node_sizes: list of int, or vertex attribute Sizes of nodes are necessary to know the size of communities in aggregate graphs. Usually this is set to 1 for all nodes, but in specific cases this could be changed. Deafault None + :param initial_membership: list of int Initial membership for the partition. If :obj:`None` then defaults to a singleton partition. Default None + :param weights: list of double, or edge attribute Weights of edges. Can be either an iterable or an edge attribute. Default None + :param node_sizes: list of int, or vertex attribute Sizes of nodes are necessary to know the size of communities in aggregate graphs. Usually this is set to 1 for all nodes, but in specific cases this could be changed. Default None :return: NodeClustering object :Example: @@ -1098,7 +1100,7 @@ def greedy_modularity(g_original: object, weight: list = None) -> NodeClustering ========== ======== ======== :param g_original: a networkx/igraph object - :param weight: list of double, or edge attribute Weights of edges. Can be either an iterable or an edge attribute. Deafault None + :param weight: list of double, or edge attribute Weights of edges. Can be either an iterable or an edge attribute. Default None :return: NodeClustering object :Example: diff --git a/cdlib/algorithms/overlapping_partition.py b/cdlib/algorithms/overlapping_partition.py index 3b98cf2..aaa7850 100644 --- a/cdlib/algorithms/overlapping_partition.py +++ b/cdlib/algorithms/overlapping_partition.py @@ -161,7 +161,7 @@ def ego_networks(g_original: object, level: int = 1) -> NodeClustering: ========== ======== ======== :param g_original: a networkx/igraph object - :param level: extrac communities with all neighbors of distance<=level from a node. Deafault 1 + :param level: extrac communities with all neighbors of distance<=level from a node. Default 1 :return: NodeClustering object diff --git a/cdlib/test/test_community_discovery_models.py b/cdlib/test/test_community_discovery_models.py index 9c19cda..b02f632 100644 --- a/cdlib/test/test_community_discovery_models.py +++ b/cdlib/test/test_community_discovery_models.py @@ -436,6 +436,17 @@ def test_spinglass(self): self.assertEqual(type(com.communities[0]), list) self.assertEqual(type(com.communities[0][0]), str) + nx.set_edge_attributes(g, values=2, name="weight") + weight_list = [g[u][v]["weight"] for u, v in g.edges()] + for com in ( + algorithms.spinglass(g, weights="weight"), + algorithms.spinglass(g, weights=weight_list), + ): + self.assertEqual(type(com.communities), list) + if len(com.communities) > 0: + self.assertEqual(type(com.communities[0]), list) + self.assertEqual(type(com.communities[0][0]), str) + def test_walktrap(self): if ig is not None: g = get_string_graph() @@ -454,6 +465,17 @@ def test_eigenvector(self): self.assertEqual(type(com.communities[0]), list) self.assertEqual(type(com.communities[0][0]), str) + nx.set_edge_attributes(g, values=2, name="weight") + weight_list = [g[u][v]["weight"] for u, v in g.edges()] + for com in ( + algorithms.eigenvector(g, weights="weight"), + algorithms.eigenvector(g, weights=weight_list), + ): + self.assertEqual(type(com.communities), list) + if len(com.communities) > 0: + self.assertEqual(type(com.communities[0]), list) + self.assertEqual(type(com.communities[0][0]), str) + def test_Congo(self): g = get_string_graph() coms = algorithms.congo(g, number_communities=3, height=2)