Skip to content

Commit

Permalink
Non recursive add simplex (#247)
Browse files Browse the repository at this point in the history
* FIX: rewrote add_simplices_from to make it non-recursive. tests: fixed some

* fix: some tests

* fix: test

* fix: put the docstring back in

* non-recursive add_simplex

* fix: remove supfaces of edge #85

* style: ran black

* nich request

* fix: id and review comment

* refactor: added helper function to add simplices without checks, for clarity and to avoid redundancy

* fix: changed tests to check sets to satistfy different python versions

* fix: boundary_matrix test - thanks Marco

* fix: more tests

* fix: more tests

* tests: skip random doctests

* fix: infinite loop. tests: reinstated warning tests

* run isort and black

* remove unnecessary import

Co-authored-by: Nicholas Landry <[email protected]>
  • Loading branch information
maximelucas and nwlandry authored Dec 9, 2022
1 parent 7457018 commit 9f32d2c
Show file tree
Hide file tree
Showing 6 changed files with 367 additions and 168 deletions.
1 change: 0 additions & 1 deletion tests/classes/test_hypergraph.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import pickle
import tempfile
from warnings import warn

import pytest

Expand Down
203 changes: 122 additions & 81 deletions tests/classes/test_simplicialcomplex.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pytest
from warnings import warn

import pytest

import xgi
from xgi.exception import XGIError

Expand Down Expand Up @@ -38,18 +39,19 @@ def test_add_simplex():
S = xgi.SimplicialComplex()
S.add_simplex([1, 2, 3])

edge_dict = {
0: frozenset({1, 2, 3}),
1: frozenset({1, 2}),
2: frozenset({1, 3}),
3: frozenset({2, 3}),
}
edges = [
frozenset({1, 2, 3}),
frozenset({2, 3}),
frozenset({1, 2}),
frozenset({1, 3}),
]

assert S.num_nodes == 3
assert S._edge == edge_dict
assert list(S.edges) == list(range(4))
assert set(S.edges.members()) == set(edges)

S.add_simplex([2, 1])
assert S._edge == edge_dict
assert set(S.edges.members()) == set(edges)

# check uid
S2 = xgi.SimplicialComplex()
Expand Down Expand Up @@ -84,28 +86,22 @@ def test_add_simplices_from_iterable_of_members():
]
S = xgi.SimplicialComplex()
S.add_simplices_from(edges)
assert S.edges.members() == simplices1
assert set(S.edges.members()) == set(simplices1)

S1 = xgi.SimplicialComplex(edges)
with pytest.raises(XGIError):
xgi.SimplicialComplex(S1.edges)

edges = {frozenset([0, 1]), frozenset([1, 2]), frozenset([1, 2, 4])}
simplices2 = [
frozenset({0, 1}),
frozenset({1, 2, 4}),
frozenset({1, 2}),
frozenset({1, 4}),
frozenset({2, 4}),
]

S = xgi.SimplicialComplex()
S.add_simplices_from(edges)
assert S.edges.members() == simplices2
assert set(S.edges.members()) == set(simplices1)

edges = [[0, 1], {1, 2}, (1, 2, 4)]
S = xgi.SimplicialComplex()
S.add_simplices_from(edges)
assert S.edges.members() == simplices1
assert set(S.edges.members()) == set(simplices1)

edges = [{"foo", "bar"}, {"bar", "baz"}, {"foo", "bar", "baz"}]
simplices3 = [
Expand Down Expand Up @@ -137,40 +133,62 @@ def test_add_simplices_from_iterable_of_members():

def test_add_simplices_from_format2():
edges = [({0, 1}, 0), ({1, 2}, 1), ({1, 2, 4}, 2)]
simplices1 = [
frozenset({0, 1}),
frozenset({1, 2}),
frozenset({1, 2, 4}),
frozenset({1, 4}),
frozenset({2, 4}),
]
simplices1 = {
0: frozenset({0, 1}),
1: frozenset({1, 2}),
2: frozenset({1, 2, 4}),
3: frozenset({2, 4}),
4: frozenset({1, 4}),
}
H = xgi.SimplicialComplex()
H.add_simplices_from(edges)
assert list(H.edges) == list(range(6))
assert H.edges.members(dtype=dict) == simplices1
assert list(H.edges) == list(range(5))
assert H._edge == simplices1

edges = [({0, 1}, "a"), ({1, 2}, "b"), ({1, 2, 4}, "foo")]
simplices = {
"a": frozenset({0, 1}),
"b": frozenset({1, 2}),
"foo": frozenset({1, 2, 4}),
0: frozenset({2, 4}),
1: frozenset({1, 4}),
}
H = xgi.SimplicialComplex()
H.add_simplices_from(edges)
assert list(H.edges) == list(range(6))
assert H.edges.members(dtype=dict) == {e[1]: e[0] for e in edges}
assert list(H.edges) == ["a", "b", "foo", 0, 1]
assert H._edge == simplices

edges = [({0, 1}, "a"), ({1, 2}, "b"), ({2, 3, 4}, 100)]
simplices = [
frozenset({0, 1}),
frozenset({1, 2}),
frozenset({2, 3, 4}),
frozenset({2, 3}),
frozenset({2, 4}),
frozenset({3, 4}),
]
H = xgi.SimplicialComplex()
H.add_simplices_from(edges)
assert list(H.edges) == [e[1] for e in edges]
assert H.edges.members(dtype=dict) == {e[1]: e[0] for e in simplices1}
assert list(H.edges) == ["a", "b", 100, 101, 102, 103]
assert set(H.edges.members()) == set(simplices)

# check counter
H.add_edge([1, 9, 2])
assert H.edges.members(101) == {1, 9, 2}
H.add_simplex([1, 9, 2])
assert next(H._edge_uid) == 107

H1 = xgi.SimplicialComplex([{1, 2}, {2, 3, 4}])
with pytest.warns(
UserWarning, match="uid 0 already exists, cannot add edge {1, 3}."
UserWarning, match="uid 0 already exists, cannot add simplex {1, 3}."
):
H1.add_edges_from([({1, 3}, 0)])
assert H1._edge == {0: {1, 2}, 1: {2, 3, 4}}
H1.add_simplices_from([({1, 3}, 0)])
simplices = [
frozenset({1, 2}),
frozenset({2, 3, 4}),
frozenset({2, 3}),
frozenset({2, 4}),
frozenset({3, 4}),
]
assert set(H1.edges.members()) == set(simplices)


def test_add_simplices_from_format3():
Expand All @@ -179,25 +197,25 @@ def test_add_simplices_from_format3():
({1, 2}, {"age": 30}),
({1, 2, 4}, {"color": "blue", "age": 40}),
]
simplices1 = [
frozenset({0, 1}),
frozenset({1, 2}),
frozenset({1, 2, 4}),
frozenset({1, 4}),
frozenset({2, 4}),
]
simplices1 = {
0: frozenset({0, 1}),
1: frozenset({1, 2}),
2: frozenset({1, 2, 4}),
3: frozenset({2, 4}),
4: frozenset({1, 4}),
}
H = xgi.SimplicialComplex()
H.add_simplices_from(edges)
assert list(H.edges) == list(range(5))
assert H.edges.members() == simplices1
assert H._edge == simplices1
assert H.edges[0] == edges[0][1]
assert H.edges[1] == edges[1][1]
assert H.edges[2] == edges[2][1]
assert H.edges[3] == dict()
assert H.edges[4] == dict()
# check counter
H.add_simplex([1, 9, 2])
assert H.edges.members(5) == {1, 9, 2}
assert next(H._edge_uid) == 8


def test_add_simplices_from_format4():
Expand All @@ -206,26 +224,26 @@ def test_add_simplices_from_format4():
({1, 2}, "two", {"age": 30}),
({1, 2, 4}, "three", {"color": "blue", "age": 40}),
]
simplices1 = [
frozenset({0, 1}),
frozenset({1, 2}),
frozenset({1, 2, 4}),
frozenset({1, 4}),
frozenset({2, 4}),
]
simplices1 = {
"one": frozenset({0, 1}),
"two": frozenset({1, 2}),
"three": frozenset({1, 2, 4}),
0: frozenset({2, 4}),
1: frozenset({1, 4}),
}

H = xgi.SimplicialComplex()
H.add_simplices_from(edges)
assert list(H.edges) == ["one", "two", "three", 0, 1]
assert H.edges.members() == simplices1
assert H._edge == simplices1
assert H.edges["one"] == edges[0][2]
assert H.edges["two"] == edges[1][2]
assert H.edges["three"] == edges[2][2]
assert H.edges[0] == dict()
assert H.edges[1] == dict()
# check counter
H.add_simplex([1, 9, 2])
assert H.edges.members(2) == {1, 9, 2}
assert next(H._edge_uid) == 5

H1 = xgi.SimplicialComplex([{1, 2}, {2, 3, 4}])
with pytest.warns(
Expand All @@ -237,19 +255,20 @@ def test_add_simplices_from_format4():

def test_add_edges_from_dict():
edges = {"one": [0, 1], "two": [1, 2], 2: [1, 2, 4]}
simplices1 = [
frozenset({0, 1}),
frozenset({1, 2}),
frozenset({1, 2, 4}),
frozenset({1, 4}),
frozenset({2, 4}),
]
simplices1 = {
"one": frozenset({0, 1}),
"two": frozenset({1, 2}),
2: frozenset({1, 2, 4}),
3: frozenset({2, 4}),
4: frozenset({1, 4}),
}

H = xgi.SimplicialComplex()
H.add_simplices_from(edges)
assert list(H.edges) == ["one", "two", 2, 3, 4]
assert H.edges.members() == simplices1
assert H._edge == simplices1
# check counter
H.add_edge([1, 9, 2])
H.add_simplex([1, 9, 2])
assert H.edges.members(5) == {1, 9, 2}

H1 = xgi.SimplicialComplex([{1, 2}, {2, 3, 4}])
Expand Down Expand Up @@ -281,12 +300,14 @@ def test_add_simplices_from(edgelist5):
simplex = ((1, 2, 3), {"color": "red"})
S3.add_simplices_from([simplex], max_order=2)

assert S3.edges.members(dtype=dict) == {
0: frozenset({1, 2, 3}),
1: frozenset({1, 2}),
2: frozenset({1, 3}),
3: frozenset({2, 3}),
}
simplices = [
frozenset({1, 2, 3}),
frozenset({2, 3}),
frozenset({1, 2}),
frozenset({1, 3}),
]

assert set(S3.edges.members()) == set(simplices)

assert S3.edges[0] == {"color": "red"}
assert S3.edges[1] == {}
Expand Down Expand Up @@ -420,14 +441,34 @@ def test_remove_simplex_id(edgelist6):
S.add_simplices_from(edgelist6)

# remove simplex and others it belongs to
S.remove_simplex_id(6) # simplex {2, 3}
edge_dict = {
0: frozenset({0, 1, 2}),
1: frozenset({0, 1}),
2: frozenset({0, 2}),
3: frozenset({1, 2}),
5: frozenset({1, 3}),
8: frozenset({2, 4}),
9: frozenset({3, 4}),
}
assert S._edge == edge_dict
id = list(S._edge.values()).index(frozenset({2, 3}))
S.remove_simplex_id(id) # simplex {2, 3}
edges = [
frozenset({0, 1, 2}),
frozenset({0, 1}),
frozenset({2, 4}),
frozenset({1, 2}),
frozenset({3, 4}),
frozenset({0, 2}),
frozenset({1, 3}),
]
assert set(S.edges.members()) == set(edges)


def test_remove_simplex_ids_from(edgelist6):
S = xgi.SimplicialComplex()
S.add_simplices_from(edgelist6)

# remove simplex and others it belongs to
id1 = list(S._edge.values()).index(frozenset({2, 3}))
id2 = list(S._edge.values()).index(frozenset({0, 1, 2}))
S.remove_simplex_ids_from([id1, id2])
edges = [
frozenset({0, 1}),
frozenset({2, 4}),
frozenset({1, 2}),
frozenset({3, 4}),
frozenset({0, 2}),
frozenset({1, 3}),
]
assert set(S.edges.members()) == set(edges)
4 changes: 3 additions & 1 deletion tests/generators/test_classic.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ def test_flag_complex():
G1 = nx.complete_graph(4)
S4 = xgi.flag_complex(G1)
S5 = xgi.flag_complex(G1, ps=[1])
assert S4.edges.members() == S5.edges.members()
assert S4.num_nodes == S5.num_nodes
assert S4.num_edges == S5.num_edges
assert set(S4.edges.members()) == set(S5.edges.members())


def test_ring_lattice():
Expand Down
Loading

0 comments on commit 9f32d2c

Please sign in to comment.