From abb1bd7031434c26d9f4557007ca09623d993274 Mon Sep 17 00:00:00 2001 From: Brenda Praggastis <39808911+brendapraggastis@users.noreply.github.com> Date: Sun, 23 Jul 2023 13:59:38 -0700 Subject: [PATCH 1/3] debugged hypergraph.remove method as per hyp-338 --- hypernetx/classes/hypergraph.py | 11 +++++++---- hypernetx/classes/tests/conftest.py | 14 ++++++++++++++ hypernetx/classes/tests/test_hypergraph.py | 12 ++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/hypernetx/classes/hypergraph.py b/hypernetx/classes/hypergraph.py index 930785bd..a4945300 100644 --- a/hypernetx/classes/hypergraph.py +++ b/hypernetx/classes/hypergraph.py @@ -1529,20 +1529,23 @@ def remove(self, keys, level=None, name=None): rdfprop = self.properties.copy() rdf = self.dataframe.copy() if not isinstance(keys, (list, tuple, set)): - keys = list(keys) + nkeys = list() + nkeys.append(keys) + else: + nkeys = keys if level == 0: - kdx = set(keys).intersection(set(self._state_dict["labels"]["edges"])) + kdx = set(nkeys).intersection(set(self._state_dict["labels"]["edges"])) for k in kdx: rdfprop = rdfprop.drop((0, k)) rdf = rdf.loc[~rdf[self._edge_col].isin(kdx)] elif level == 1: - kdx = set(keys).intersection(set(self._state_dict["labels"]["nodes"])) + kdx = set(nkeys).intersection(set(self._state_dict["labels"]["nodes"])) for k in kdx: rdfprop = rdfprop.drop((1, k)) rdf = rdf.loc[~rdf[self._node_col].isin(kdx)] else: rdfprop = rdfprop.reset_index() - kdx = set(keys).intersection(rdfprop.id.unique()) + kdx = set(nkeys).intersection(rdfprop.id.unique()) rdfprop = rdfprop.set_index("id") rdfprop = rdfprop.drop(index=kdx) rdf = rdf.loc[~rdf[self._edge_col].isin(kdx)] diff --git a/hypernetx/classes/tests/conftest.py b/hypernetx/classes/tests/conftest.py index 2f5e7519..e9b69de4 100644 --- a/hypernetx/classes/tests/conftest.py +++ b/hypernetx/classes/tests/conftest.py @@ -75,6 +75,15 @@ def __init__(self): self.edgedict = {AB: {A, B}, BC: {B, C}, ACD: {A, C, D}} self.hypergraph = Hypergraph(self.edgedict, name="TriLoop") +class TriLoop2: + """Triloop example with redundant node and edge""" + + def __init__(self): + A, B, C, D, E = "A", "B", "C", "D", "E" + AB, BC, ACD, ACD2 = "AB", "BC", "ACD", "ACD2" + self.edgedict = {AB: {A, B}, BC: {B, C}, ACD: {A, C, D, E}, ACD2: {A, C, D, E}} + self.hypergraph = Hypergraph(self.edgedict, name="TriLoop2") + class SBSDupes: def __init__(self): @@ -156,6 +165,11 @@ def triloop(): return TriLoop() +@pytest.fixture +def triloop2(): + return TriLoop2() + + @pytest.fixture def sbs_hypergraph(sbs): return Hypergraph(sbs.edgedict, name="sbsh") diff --git a/hypernetx/classes/tests/test_hypergraph.py b/hypernetx/classes/tests/test_hypergraph.py index 4f5ef0f3..5834e705 100644 --- a/hypernetx/classes/tests/test_hypergraph.py +++ b/hypernetx/classes/tests/test_hypergraph.py @@ -88,6 +88,18 @@ def test_remove_edges(sbs): H = H.remove_edges("O") assert H.shape == (6, 4) +def test_remove_edges(triloop2): + H = triloop2.hypergraph + k = "ACD2" + newH = H.remove(k) + assert newH.shape == (5,3) + newH = H.remove_nodes('E') + assert newH.shape == (4,4) + newH = H.remove_edges('ACD') + assert newH.shape == (5,3) + newH = H.remove(['ACD','E']) + assert newH.shape == (4,3) + def test_remove_nodes(): a, b, c, d = "a", "b", "c", "d" From 99067faa3224b05dfa59cd3fb827eb45229bb551 Mon Sep 17 00:00:00 2001 From: Brenda Praggastis <39808911+brendapraggastis@users.noreply.github.com> Date: Tue, 25 Jul 2023 10:09:50 -0700 Subject: [PATCH 2/3] updated hotfix in response to comments --- hypernetx/classes/hypergraph.py | 23 +++++++++++++--------- hypernetx/classes/tests/test_hypergraph.py | 9 ++++++--- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/hypernetx/classes/hypergraph.py b/hypernetx/classes/hypergraph.py index a4945300..0b923f20 100644 --- a/hypernetx/classes/hypergraph.py +++ b/hypernetx/classes/hypergraph.py @@ -6,7 +6,7 @@ import warnings from collections import defaultdict from collections.abc import Sequence, Iterable -from typing import Optional, Any, TypeVar, Union, Mapping +from typing import Optional, Any, TypeVar, Union, Mapping, Hashable import networkx as nx import numpy as np @@ -1513,13 +1513,15 @@ def remove(self, keys, level=None, name=None): Parameters ---------- - keys : list | tuple | set - node and/or edge id to restrict to + keys : list | tuple | set | Hashable + node and/or edge id(s) to restrict to level : None, optional Enter 0 to remove edges with ids in keys. Enter 1 to remove nodes with ids in keys. If None then all objects in nodes and edges with the id will be removed. + name : str, optional + Name of new hypergraph Returns ------- @@ -1528,28 +1530,30 @@ def remove(self, keys, level=None, name=None): """ rdfprop = self.properties.copy() rdf = self.dataframe.copy() - if not isinstance(keys, (list, tuple, set)): + if isinstance(keys, (list, tuple, set)): + nkeys = keys + elif isinstance(keys, Hashable): nkeys = list() nkeys.append(keys) else: - nkeys = keys + raise TypeError("`keys` parameter must be list | tuple | set | Hashable") if level == 0: kdx = set(nkeys).intersection(set(self._state_dict["labels"]["edges"])) for k in kdx: rdfprop = rdfprop.drop((0, k)) - rdf = rdf.loc[~rdf[self._edge_col].isin(kdx)] + rdf = rdf.loc[~(rdf[self._edge_col].isin(kdx))] elif level == 1: kdx = set(nkeys).intersection(set(self._state_dict["labels"]["nodes"])) for k in kdx: rdfprop = rdfprop.drop((1, k)) - rdf = rdf.loc[~rdf[self._node_col].isin(kdx)] + rdf = rdf.loc[~(rdf[self._node_col].isin(kdx))] else: rdfprop = rdfprop.reset_index() kdx = set(nkeys).intersection(rdfprop.id.unique()) rdfprop = rdfprop.set_index("id") rdfprop = rdfprop.drop(index=kdx) - rdf = rdf.loc[~rdf[self._edge_col].isin(kdx)] - rdf = rdf.loc[~rdf[self._node_col].isin(kdx)] + rdf = rdf.loc[~(rdf[self._edge_col].isin(kdx))] + rdf = rdf.loc[~(rdf[self._node_col].isin(kdx))] return Hypergraph( setsystem=rdf, @@ -1559,6 +1563,7 @@ def remove(self, keys, level=None, name=None): misc_cell_properties_col=self.edges._misc_cell_props_col, properties=rdfprop, misc_properties_col=self.edges._misc_props_col, + name=name ) def toplexes(self, name=None): diff --git a/hypernetx/classes/tests/test_hypergraph.py b/hypernetx/classes/tests/test_hypergraph.py index 5834e705..0462a3e8 100644 --- a/hypernetx/classes/tests/test_hypergraph.py +++ b/hypernetx/classes/tests/test_hypergraph.py @@ -88,17 +88,20 @@ def test_remove_edges(sbs): H = H.remove_edges("O") assert H.shape == (6, 4) -def test_remove_edges(triloop2): +def test_remove(triloop2): H = triloop2.hypergraph k = "ACD2" + assert H.shape == (5,4) newH = H.remove(k) assert newH.shape == (5,3) - newH = H.remove_nodes('E') + newH = H.remove('E',level=1) assert newH.shape == (4,4) - newH = H.remove_edges('ACD') + newH = H.remove('ACD',level=0) assert newH.shape == (5,3) newH = H.remove(['ACD','E']) assert newH.shape == (4,3) + with pytest.raises(TypeError): + H.remove({'ACD':'edge'}) def test_remove_nodes(): From 11d34b0ee266f8d94af2f665a97ad32ba3a558b4 Mon Sep 17 00:00:00 2001 From: Mark Bonicillo Date: Tue, 25 Jul 2023 14:40:47 -0700 Subject: [PATCH 3/3] =?UTF-8?q?bump:=20version=202.0.2=20=E2=86=92=202.0.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cz.toml | 2 +- docs/source/conf.py | 2 +- hypernetx/__init__.py | 2 +- setup.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.cz.toml b/.cz.toml index 0df7b5af..b8265df3 100644 --- a/.cz.toml +++ b/.cz.toml @@ -1,6 +1,6 @@ [tool.commitizen] name = "cz_conventional_commits" -version = "2.0.2" +version = "2.0.3" version_files = [ "setup.py", "docs/source/conf.py", diff --git a/docs/source/conf.py b/docs/source/conf.py index 6bd25ed2..433c2b18 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -19,7 +19,7 @@ import os -__version__ = "2.0.2" +__version__ = "2.0.3" # If extensions (or modules to document with autodoc) are in another directory, diff --git a/hypernetx/__init__.py b/hypernetx/__init__.py index 562a3666..21723aaa 100644 --- a/hypernetx/__init__.py +++ b/hypernetx/__init__.py @@ -11,4 +11,4 @@ from hypernetx.utils import * from hypernetx.utils.toys import * -__version__ = "2.0.2" +__version__ = "2.0.3" diff --git a/setup.py b/setup.py index 86e048c4..edea8c23 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ from setuptools import setup -__version__ = "2.0.2" +__version__ = "2.0.3" setup(version=__version__)