def test_hierarchical(self): # most of leiden is tested in unit / integration tests in graspologic-native. # All we're trying to test through these unit tests are the python conversions # prior to calling, so type and value validation and that we got a result edges = _create_edge_list() results = hierarchical_leiden(edges, random_seed=1234) total_nodes = len([item for item in results if item.level == 0]) partitions = HierarchicalCluster.final_hierarchical_clustering(results) self.assertEqual(total_nodes, len(partitions))
def test_isolate_nodes_in_nx_graph_are_not_returned(self): self.assertEqual( 10, len(self.graph.nodes), "the input graph contains all nodes including isolate", ) with pytest.warns(UserWarning, match="isolate"): partitions = leiden(self.graph) self.assert_isolate_not_in_result(partitions) with pytest.warns(UserWarning, match="isolate"): hierarchical_partitions = hierarchical_leiden(self.graph) self.assert_isolate_not_in_hierarchical_result(hierarchical_partitions)
def test_isolate_nodes_in_csr_matrix_are_not_returned(self): sparse_adj_matrix = nx.to_scipy_sparse_matrix(self.graph) self.assertEqual( 10, sparse_adj_matrix.shape[0], "the input csr contains all nodes including isolate", ) with pytest.warns(UserWarning, match="isolate"): partitions = leiden(sparse_adj_matrix) self.assert_isolate_not_in_result(partitions) with pytest.warns(UserWarning, match="isolate"): hierarchical_partitions = hierarchical_leiden(sparse_adj_matrix) self.assert_isolate_not_in_hierarchical_result(hierarchical_partitions)
def test_isolate_nodes_in_ndarray_are_not_returned(self): ndarray_adj_matrix = nx.to_numpy_array(self.graph) self.assertEqual( 10, ndarray_adj_matrix.shape[0], "the input array contains all nodes including isolate", ) with pytest.warns(UserWarning, match="isolate"): partitions = leiden(ndarray_adj_matrix) self.assert_isolate_not_in_result(partitions) with pytest.warns(UserWarning, match="isolate"): hierarchical_partitions = hierarchical_leiden(ndarray_adj_matrix) self.assert_isolate_not_in_hierarchical_result(hierarchical_partitions)
def test_correct_types(self): # both leiden and hierarchical_leiden require the same types and mostly the same value range restrictions good_args = { "starting_communities": { "1": 2 }, "extra_forced_iterations": 0, "resolution": 1.0, "randomness": 0.001, "use_modularity": True, "random_seed": None, "is_weighted": True, "weight_default": 1.0, "check_directed": True, } graph = nx.Graph() graph.add_edge("1", "2", weight=3.0) graph.add_edge("2", "3", weight=4.0) leiden(graph=graph, **good_args) with self.assertRaises(TypeError): args = good_args.copy() args["starting_communities"] = 123 leiden(graph=graph, **args) args = good_args.copy() args["starting_communities"] = None leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["extra_forced_iterations"] = 1234.003 leiden(graph=graph, **args) with self.assertRaises(ValueError): args = good_args.copy() args["extra_forced_iterations"] = -4003 leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["resolution"] = "leiden" leiden(graph=graph, **args) with self.assertRaises(ValueError): args = good_args.copy() args["resolution"] = 0 leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["randomness"] = "leiden" leiden(graph=graph, **args) with self.assertRaises(ValueError): args = good_args.copy() args["randomness"] = 0 leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["use_modularity"] = 1234 leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["trials"] = "hotdog" leiden(graph=graph, **args) with self.assertRaises(ValueError): args = good_args.copy() args["trials"] = 0 leiden(graph=graph, **args) args = good_args.copy() args["random_seed"] = 1234 leiden(graph=graph, **args) args["random_seed"] = None leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["random_seed"] = "leiden" leiden(graph=graph, **args) with self.assertRaises(ValueError): args = good_args.copy() args["random_seed"] = -1 leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["is_weighted"] = "leiden" leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["weight_default"] = "leiden" leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["check_directed"] = "leiden" leiden(graph=graph, **args) # one extra parameter hierarchical needs with self.assertRaises(TypeError): args = good_args.copy() args["max_cluster_size"] = "leiden" hierarchical_leiden(graph=graph, **args) with self.assertRaises(ValueError): args = good_args.copy() args["max_cluster_size"] = 0 hierarchical_leiden(graph=graph, **args) as_csr = nx.to_scipy_sparse_matrix(graph) partitions = leiden(graph=as_csr, **good_args) node_ids = partitions.keys() for node_id in node_ids: self.assertTrue( isinstance(node_id, (np.int32, np.intc)), f"{node_id} has {type(node_id)} should be an np.int32/np.intc", )
def test_correct_types(self): # both leiden and hierarchical_leiden require the same types and mostly the same value range restrictions good_args = { "starting_communities": {"1": 2}, "extra_forced_iterations": 0, "resolution": 1.0, "randomness": 0.001, "use_modularity": True, "random_seed": None, "is_weighted": True, "weight_default": 1.0, "check_directed": True, } graph = nx.Graph() graph.add_edge("1", "2", weight=3.0) graph.add_edge("2", "3", weight=4.0) leiden(graph=graph, **good_args) with self.assertRaises(TypeError): args = good_args.copy() args["starting_communities"] = 123 leiden(graph=graph, **args) args = good_args.copy() args["starting_communities"] = None leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["extra_forced_iterations"] = 1234.003 leiden(graph=graph, **args) with self.assertRaises(ValueError): args = good_args.copy() args["extra_forced_iterations"] = -4003 leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["resolution"] = "leiden" leiden(graph=graph, **args) with self.assertRaises(ValueError): args = good_args.copy() args["resolution"] = 0 leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["randomness"] = "leiden" leiden(graph=graph, **args) with self.assertRaises(ValueError): args = good_args.copy() args["randomness"] = 0 leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["use_modularity"] = 1234 leiden(graph=graph, **args) args = good_args.copy() args["random_seed"] = 1234 leiden(graph=graph, **args) args["random_seed"] = None leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["random_seed"] = "leiden" leiden(graph=graph, **args) with self.assertRaises(ValueError): args = good_args.copy() args["random_seed"] = -1 leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["is_weighted"] = "leiden" leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["weight_default"] = "leiden" leiden(graph=graph, **args) with self.assertRaises(TypeError): args = good_args.copy() args["check_directed"] = "leiden" leiden(graph=graph, **args) # one extra parameter hierarchical needs with self.assertRaises(TypeError): args = good_args.copy() args["max_cluster_size"] = "leiden" hierarchical_leiden(graph=graph, **args) with self.assertRaises(ValueError): args = good_args.copy() args["max_cluster_size"] = 0 hierarchical_leiden(graph=graph, **args)