def test_bad_weights(self, dim, graph): """Test if function raises a ``ValueError`` when a vector of node weights input to ``node_select`` is not of the same dimension as the input graph.""" s = [0, 1] w = np.ones(dim - 1) with pytest.raises(ValueError, match="Number of node weights must match number of nodes"): clique.swap(s, graph, node_select=w)
def test_swap_weight_tie(self, dim, monkeypatch): """Test if function performs correct swap operation using randomness to break ties during degree-based node selection. The input graph is a complete graph with the ``(dim - 1, dim - 3)`` and ``(dim - 2, dim - 4)`` edges removed. The starting clique is the first ``dim - 2`` nodes. This results in two candidate swap pairs: ``(dim - 1, dim - 3)`` and ``(dim - 2, dim - 4)``. This test gives the every node the same weight, so we expect that either pair should be selected randomly with equal probability. This test monkeypatches the ``np.random.choice`` call to guarantee that one of the nodes is picked during one run of ``swap`` and the another node is picked during the next run. """ graph = nx.complete_graph(dim) graph.remove_edge(dim - 1, dim - 3) graph.remove_edge(dim - 2, dim - 4) s = list(range(dim - 2)) weights = [1 for _ in range(dim)] patch_random_choice_1 = functools.partial(patch_random_choice, element=0) patch_random_choice_2 = functools.partial(patch_random_choice, element=1) with monkeypatch.context() as m: m.setattr(np.random, "choice", patch_random_choice_1) c1 = clique.swap(s, graph, node_select=weights) with monkeypatch.context() as m: m.setattr(np.random, "choice", patch_random_choice_2) c2 = clique.swap(s, graph, node_select=weights) assert c1 != c2
def test_bad_node_select(self, dim): """Tests if function raises a ``ValueError`` when input an invalid ``node_select`` argument""" graph = nx.barbell_graph(dim, 0) s = [0] with pytest.raises(ValueError, match="Node selection method not recognized"): clique.swap(s, graph, node_select="")
def test_swap_degree_tie(self, dim, monkeypatch): """Test if function performs correct swap operation using randomness to break ties during degree-based node selection. Input graph is a fully connected graph. Additionally, a connection between node ``0`` and ``dim - 1`` is removed as well as a connection between node ``0`` and ``dim - 2``. A clique of the first ``dim - 2`` nodes is then input. In this case, C1 consists of nodes ``dim - 1`` and ``dim - 2``. As they have the same degree, they should be selected randomly with equal probability. This function monkeypatches the ``np.random.choice`` call to guarantee that one of the nodes is picked during one run of ``swap`` and the other node is picked during the next run. """ graph = nx.complete_graph(dim) graph.remove_edge(0, dim - 1) graph.remove_edge(0, dim - 2) s = set(range(dim - 2)) patch_random_choice_1 = functools.partial(patch_random_choice, element=0) patch_random_choice_2 = functools.partial(patch_random_choice, element=1) with monkeypatch.context() as m: m.setattr(np.random, "choice", patch_random_choice_1) c1 = clique.swap(s, graph, node_select="degree") with monkeypatch.context() as m: m.setattr(np.random, "choice", patch_random_choice_2) c2 = clique.swap(s, graph, node_select="degree") assert c1 != c2
def test_swap(self, dim): """Test if function performs correct swap operation. Input is a complete graph with a connection between node ``0`` and ``dim - 1`` removed. An input clique of the first ``dim - 1`` nodes is then input, with the result being a different clique with the first node removed and the ``dim`` node added.""" graph = nx.complete_graph(dim) graph.remove_edge(0, dim - 1) s = list(range(dim - 1)) assert set(clique.swap(s, graph)) == set(range(1, dim))
def test_swap_weight(self, dim): """Test if function performs correct swap operation when weight-based node selection is used. The input graph is a complete graph with the ``(dim - 1, dim - 3)`` and ``(dim - 2, dim - 4)`` edges removed. The starting clique is the first ``dim - 2`` nodes. This results in two candidate swap pairs: ``(dim - 1, dim - 3)`` and ``(dim - 2, dim - 4)``. Since node ``dim - 1`` has the largest weight, we expect to swap that in by removing node ``dim - 3``.""" graph = nx.complete_graph(dim) graph.remove_edge(dim - 1, dim - 3) graph.remove_edge(dim - 2, dim - 4) s = list(range(dim - 2)) weights = list(range(dim)) result = set(clique.swap(s, graph, node_select=weights)) expected = set(range(dim - 3)) | {dim - 1} assert result == expected
def test_swap_degree(self, dim): """Test if function performs correct swap operation when degree-based node selection is used. Input graph is a lollipop graph, consisting of a fully connected graph with a single additional node connected to just one of the nodes in the graph. Additionally, a connection between node ``0`` and ``dim - 1`` is removed as well as a connection between node ``0`` and ``dim - 2``. A clique of the first ``dim - 2`` nodes is then input. In this case, C1 consists of nodes ``dim - 1`` and ``dim - 2``. However, node ``dim - 1`` has greater degree due to the extra node in the lollipop graph. This test confirms that the resultant swap is performed correctly.""" graph = nx.lollipop_graph(dim, 1) graph.remove_edge(0, dim - 1) graph.remove_edge(0, dim - 2) s = list(range(dim - 2)) result = set(clique.swap(s, graph, node_select="degree")) expected = set(range(1, dim - 2)) | {dim - 1} assert result == expected
def test_input_valid_subgraph(self, dim): """Tests if function raises a ``ValueError`` when input is not a clique""" with pytest.raises(ValueError, match="Input is not a valid subgraph"): clique.swap([0, dim], nx.empty_graph(dim))