Skip to content

Commit

Permalink
Pull request #169: Additems
Browse files Browse the repository at this point in the history
Merge in HYP/hypernetx from additems to develop

* commit '9222850657767bde88a0846dfe4c8f8cd2288a39':
  Minor cleanup
  added import for deepcopy
  updated copy in PropertyStore to deep copy misc_properties
  updated construct from stores to return inplace or deep copy
  restricting todataframe to only return on objects actually in the hypergraph
  • Loading branch information
bonicim committed May 1, 2024
2 parents c519d05 + 9222850 commit be63722
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 55 deletions.
14 changes: 7 additions & 7 deletions hypernetx/classes/hyp_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,6 @@ def __init__(self, incidence_store, level, property_store=None):
elif level == 2:
self._items = self._incidence_store

# self._properties = PropertyStore()
### if no properties and level 0 or 1,
### create property store that
### returns weight 1 on every call for a weight
### and empty properties otherwise.

@property
def items(self):
return set(self._items)
Expand All @@ -79,6 +73,10 @@ def incidence_store(self):
def property_store(self):
return self._property_store

@property
def default_weight(self):
return self._property_store._default_weight

@property
def to_dataframe(self):
"""
Expand All @@ -90,7 +88,9 @@ def to_dataframe(self):
out: pd.DataFrame
"""
# Create a properties dataframe of non-user-defined items with default values

df = self.properties.copy(deep=True)

### deep copy dictionaries in the misc_properties column
temp = [deepcopy(d) for d in df.misc_properties.values]
df.misc_properties = temp
Expand All @@ -104,7 +104,7 @@ def to_dataframe(self):
)

# Combine user-defined and non-user-defined properties into one dataframe
return pd.concat([df, non_user_defined_properties])
return pd.concat([df, non_user_defined_properties]).loc[list(self.items)]

@property ### will remove this later
def dataframe(self):
Expand Down
86 changes: 43 additions & 43 deletions hypernetx/classes/hypergraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -631,21 +631,16 @@ def clone(self, name=None):
-------
: Hypergraph
"""
df = self.incidences.to_dataframe
eps = PropertyStore(self.edges.to_dataframe)
nps = PropertyStore(self.nodes.to_dataframe)
return self._construct_hyp_from_stores(df, edge_ps=eps, node_ps=nps, name=name)
return self._construct_hyp_from_stores(
self.incidences.to_dataframe, name=f"{self.name}_clone"
)

def __eq__(self, other):
if type(other) is type(self):
return (
all(n in self.nodes for n in other.nodes)
and all(e in self.edges for e in other.edges)
and self.incidence_dict == other.incidence_dict
)
return self.incidences.items == other.incidences.items
return False

def rename(self, edges=None, nodes=None, name=None):
def rename(self, edges=None, nodes=None, name=None, inplace=True):
"""
_summary_
Expand Down Expand Up @@ -675,7 +670,9 @@ def rename(self, edges=None, nodes=None, name=None):
df = df.rename(index=nodes, level=1)
eps = PropertyStore(edf)
nps = PropertyStore(ndf)
return self._construct_hyp_from_stores(df, edge_ps=eps, node_ps=nps, name=name)
return self._construct_hyp_from_stores(
df, edge_ps=eps, node_ps=nps, name=name, inplace=inplace
)

def get_cell_properties(self, edge_uid, node_uid, prop_name=None):
"""Get cell properties on a specified edge and node
Expand Down Expand Up @@ -1123,23 +1120,32 @@ def bipartite(self, keep_data=False, directed=False):
return B

def _construct_hyp_from_stores(
self, incidence_df, edge_ps=None, node_ps=None, name=None
self, incidence_df, edge_ps=None, node_ps=None, name=None, inplace=False
):

h = Hypergraph()
if inplace:
h = self
name = self.name
else:
h = Hypergraph()

incidence_store = IncidenceStore(
pd.DataFrame(incidence_df.index.tolist(), columns=["edges", "nodes"])
)
incidence_ps = PropertyStore(incidence_df)
incidence_ps = PropertyStore(
incidence_df, default_weight=self.incidences.default_weight
)
h._E = HypergraphView(incidence_store, 2, incidence_ps)

if edge_ps is None:
edge_ps = self.edges.property_store.copy()
edge_ps = PropertyStore(
self.edges.to_dataframe, default_weight=self.edges.default_weight
)
h._edges = HypergraphView(incidence_store, 0, edge_ps)

if node_ps is None:
node_ps = self.nodes.property_store.copy()
node_ps = PropertyStore(
self.nodes.to_dataframe, default_weight=self.nodes.default_weight
)
h._nodes = HypergraphView(incidence_store, 1, node_ps)

h._set_default_state()
Expand Down Expand Up @@ -1586,7 +1592,7 @@ def restrict_to_edges(self, edges, name=None):
keys = list(set(self._state_dict["labels"]["edges"]).difference(edges))
return self._remove(keys, level=0, name=name, inplace=False)

def add_edge(self, uid, **attr):
def add_edge(self, uid, inplace=True, **attr):
"""
Add a single edge with attributes to edge properties.
Does not add an incidence to the hypergraph.
Expand All @@ -1601,22 +1607,22 @@ def add_edge(self, uid, **attr):
-------
Hypergraph
"""
return self._add_items_from([(uid, attr)], 0)
return self._add_items_from([(uid, attr)], 0, inplace=inplace)

def add_edges_from(self, edges):
def add_edges_from(self, edges, inplace=True):
"""Edges must be a list of uids and/or tuples
of the form (uid,data) where data is dictionary"""
newedges = self._process_items(edges)
return self._add_items_from(newedges, 0)
return self._add_items_from(newedges, 0, inplace=inplace)

def add_node(self, uid, **attr):
return self._add_items_from([(uid, attr)], 1)
def add_node(self, uid, inplace=True, **attr):
return self._add_items_from([(uid, attr)], 1, inplace=inplace)

def add_nodes_from(self, nodes):
def add_nodes_from(self, nodes, inplace=True):
"""Nodes must be a list of uids and/or tuples
of the form (uid,data) where data is dictionary"""
newnodes = self._process_items(nodes)
return self._add_items_from(newnodes, 1)
return self._add_items_from(newnodes, 1, inplace=inplace)

def _process_items(self, items):
new_items = list()
Expand All @@ -1627,7 +1633,7 @@ def _process_items(self, items):
new_items.append(item)
return new_items

def add_nodes_to_edges(self, edge_dict):
def add_nodes_to_edges(self, edge_dict, inplace=True):
"""
Parameters
----------
Expand All @@ -1648,12 +1654,12 @@ def add_nodes_to_edges(self, edge_dict):
else:
for nd in nodes:
items.append(((ed, nd), {}))
return self._add_items_from(items, 2)
return self._add_items_from(items, 2, inplace=inplace)

def add_incidence(self, edge_id, node_id, **attr):
return self._add_items_from([((edge_id, node_id), attr)], 2)
def add_incidence(self, edge_id, node_id, inplace=True, **attr):
return self._add_items_from([((edge_id, node_id), attr)], 2, inplace=inplace)

def add_incidences_from(self, incidences):
def add_incidences_from(self, incidences, inplace=True):
"""
Adds incidences to Hypergraph
Expand All @@ -1675,9 +1681,9 @@ def add_incidences_from(self, incidences):
newincidences.append((pr, {}))
else:
newincidences.append(((pr[0], pr[1]), pr[2]))
return self._add_items_from(newincidences, 2)
return self._add_items_from(newincidences, 2, inplace=inplace)

def _add_items_from(self, items, level):
def _add_items_from(self, items, level, inplace=True):
"""Items must be a list of tuples
of the form (uid,data) where data is dictionary"""
df = self.incidences._property_store
Expand All @@ -1689,7 +1695,7 @@ def _add_items_from(self, items, level):
data = item[1]
hv.set_properties(uid, data)
return self._construct_hyp_from_stores(
df.properties, edge_ps=ep, node_ps=ndp, name=self.name
df.properties, edge_ps=ep, node_ps=ndp, name=self.name, inplace=inplace
)

#### This should follow behavior of restrictions
Expand Down Expand Up @@ -1752,7 +1758,7 @@ def _remove(
ep = self.edges.property_store
ndp = self.nodes.property_store
else:
df = self.incidences.properties.copy(deep=True)
df = self.incidences.to_dataframe
ep = self.edges.property_store.copy(deep=True)
ndp = self.nodes.property_store.copy(deep=True)
if level in [0, 1]:
Expand All @@ -1761,15 +1767,9 @@ def _remove(
hv._data = hv._data.drop(labels=uid_list, errors="ignore")
else:
df = df.drop(labels=uid_list, errors="ignore")
if inplace:
self = self._construct_hyp_from_stores(
df, edge_ps=ep, node_ps=ndp, name=self.name
)
return self
else:
return self._construct_hyp_from_stores(
df, edge_ps=ep, node_ps=ndp, name=name
)
return self._construct_hyp_from_stores(
df, edge_ps=ep, node_ps=ndp, name=self.name, inplace=inplace
)

def toplexes(self, return_hyp=False, name=None):
"""
Expand Down
12 changes: 7 additions & 5 deletions hypernetx/classes/property_store.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Any
from collections.abc import Hashable
from pandas import DataFrame
from copy import deepcopy


UID = "uid"
Expand Down Expand Up @@ -41,8 +42,7 @@ def __init__(self, data=None, default_weight=1):
<edge2uid> | <node1uid> | 1.0 | {} | <property value> | ...
| <node3uid> | 1.0 | {} | <property value> | ...
default_weight: int
default_weight: int | float
optional parameter that holds the specified default weight of the weight property
"""
# If no dataframe is provided, create an empty dataframe
Expand All @@ -52,7 +52,7 @@ def __init__(self, data=None, default_weight=1):
else:
self._data: DataFrame = data

self._default_weight: int = default_weight
self._default_weight: int | float = default_weight
self._columns = self._data.columns.tolist()

@property
Expand Down Expand Up @@ -255,8 +255,10 @@ def __contains__(self, uid) -> bool:

def copy(self, deep=False):
data = self._data.copy(deep=deep)
w = self._default_weight
return PropertyStore(data, default_weight=w)
if deep:
temp = [deepcopy(d) for d in data.misc_properties.values]
data["misc_properties"] = temp
return PropertyStore(data, default_weight=self._default_weight)


def flatten(my_dict):
Expand Down

0 comments on commit be63722

Please sign in to comment.