From 857130acb010befd6b47e432a8225a7f98219672 Mon Sep 17 00:00:00 2001 From: Mark Bonicillo Date: Mon, 15 Apr 2024 14:53:08 -0700 Subject: [PATCH] Fix bugs in _add_item; add tests for add_edge --- hypernetx/classes/hypergraph.py | 13 ++++-- hypernetx/classes/tests/test_hypergraph.py | 54 ++++++++++++++++------ 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/hypernetx/classes/hypergraph.py b/hypernetx/classes/hypergraph.py index 4d931b3d..5555a328 100644 --- a/hypernetx/classes/hypergraph.py +++ b/hypernetx/classes/hypergraph.py @@ -2,6 +2,7 @@ # All rights reserved. from __future__ import annotations +import random import warnings warnings.filterwarnings("default", category=DeprecationWarning) @@ -1216,7 +1217,7 @@ def add_incidences_from(self, incidences, inplace=True): def _add_item(self, uid, level=2, data=None, inplace=True): data = data or {} - self._add_items_from([(uid, data)], level=level, inplace=inplace) + return self._add_items_from([(uid, data)], level=level, inplace=inplace) def _add_items_from(self, items, level=2, inplace=True): """Items must be a list of uids and/or tuples @@ -1243,10 +1244,12 @@ def _add_items_from(self, items, level=2, inplace=True): df.properties, edge_ps=ep, node_ps=np, name=self.name ) return self - else: - return self._construct_hyp_from_stores( - df.properties, edge_ps=ep, node_ps=np, name=name - ) + return self._construct_hyp_from_stores( + df.properties, + edge_ps=ep, + node_ps=np, + name=f"{self.name}-{random.randint(1, 100)}", + ) #### This should follow behavior of restrictions def remove_edges(self, keys, name=None, inplace=True): diff --git a/hypernetx/classes/tests/test_hypergraph.py b/hypernetx/classes/tests/test_hypergraph.py index 12425953..851d660f 100644 --- a/hypernetx/classes/tests/test_hypergraph.py +++ b/hypernetx/classes/tests/test_hypergraph.py @@ -69,20 +69,46 @@ def test_hypergraph_from_bipartite(sbsd_hypergraph): assert len(HB.nodes) == 8 -@pytest.mark.skip("Deprecated method; will support in later release") -def test_add_node_to_edge(sbs): - H = Hypergraph(sbs.edgedict) - assert H.shape == (7, 6) - node = "B" - edge = "P" - H.add_node_to_edge(node, edge) - assert H.shape == (8, 6) - # add edge with nodes already in hypergraph - H.add_edge({"Z": ["A", "B"]}) - assert H.shape == (8, 7) - # add edge not in hypergraph with nodes not in hypergraph - H.add_edge({"Y": ["M", "N"]}) - assert H.shape == (10, 8) +def test_add_edge_inplace(sbs): + h = Hypergraph(sbs.edgedict) + assert h.shape == (7, 6) + + # add a new edge in place; i.e. the current hypergraph should be mutated + new_edge = "X" + h.add_edge(new_edge) + + # the Hypergraph should not increase its number of edges and incidences because the current behavior of adding + # an edge does not connect two or more nodes. + # In other words, adding an edge with no nodes + assert h.shape == (7, 6) + assert new_edge not in h.edges.elements + + # the new edge has no user-defined property data, so it should not be listed in the PropertyStore + assert new_edge not in h.edges.properties + + # However, the new_edge will be listed in the complete list of all user and non-user-define properties for all edges + assert new_edge in h.edges.to_dataframe.index.tolist() + + assert new_edge in h.edges.to_dataframe.index.tolist() + + +def test_add_edge_not_inplace(sbs): + h = Hypergraph(sbs.edgedict) + assert h.shape == (7, 6) + + # add a new edge not in place; the current hypergraph should be diffrent from the new hypergraph + # created from add_edge + new_edge = "X" + new_hg = h.add_edge(new_edge, inplace=False) + + assert new_hg.shape == (7, 6) + assert new_edge not in new_hg.edges.elements + + assert new_edge not in new_hg.edges.properties + assert new_edge in new_hg.edges.to_dataframe.index.tolist() + + # verify that the new edge is not in the old HyperGraph + assert new_edge not in h.edges.to_dataframe.index.tolist() def test_remove_edges(sbs):