Skip to content

Commit

Permalink
Implementation of a Simplex Trie for Better Performance
Browse files Browse the repository at this point in the history
  • Loading branch information
ffl096 committed Feb 9, 2024
1 parent 5f18280 commit 5a1a11a
Show file tree
Hide file tree
Showing 11 changed files with 1,080 additions and 427 deletions.
1 change: 1 addition & 0 deletions test/classes/test_combinatorial_complex.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ def test_remove_nodes(self):
frozenset({6}): {"weight": 1},
}
}

example.remove_nodes(HyperEdge([3]))
assert example._complex_set.hyperedge_dict == {
0: {frozenset({4}): {"weight": 1}, frozenset({6}): {"weight": 1}}
Expand Down
16 changes: 5 additions & 11 deletions test/classes/test_reportviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -578,12 +578,9 @@ class TestReportViews_SimplexView:

def test_getitem(self):
"""Test __getitem__ method of the SimplexView."""
assert self.simplex_view.__getitem__((1, 2)) == {
"is_maximal": True,
"membership": set(),
}
assert self.simplex_view[(1, 2)] == {}
with pytest.raises(KeyError):
self.simplex_view.__getitem__([5])
_ = self.simplex_view[(5,)]

def test_str(self):
"""Test __str__ method of the SimplexView."""
Expand Down Expand Up @@ -612,15 +609,12 @@ def test_repr(self):

def test_getitem(self):
"""Test __getitem__ method of the NodeView."""
assert self.node_view.__getitem__(Simplex([1])) == {
"is_maximal": False,
"membership": {frozenset({1, 2})},
}
assert self.node_view[Simplex([1])] == {}
with pytest.raises(KeyError):
self.node_view.__getitem__([1, 2])
_ = self.node_view[(1, 2)]

# test for nodes of ColoredHyperGraph.
assert self.node_view_1.__getitem__([1]) == {"weight": 1}
assert self.node_view_1[(1,)] == {"weight": 1}


class TestReportViews_PathView:
Expand Down
131 changes: 131 additions & 0 deletions test/classes/test_simplex_trie.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
"""Tests for the `simplex_trie` module."""

import pytest

from toponetx.classes.simplex_trie import SimplexTrie


class TestSimplexTrie:
"""Tests for the `SimplexTree` class."""

def test_insert(self) -> None:
"""Test that the internal data structures of the simplex trie are correct after insertion."""
trie = SimplexTrie()
trie.insert((1, 2, 3))

assert trie.shape == [3, 3, 1]

assert set(trie.root.children.keys()) == {1, 2, 3}
assert set(trie.root.children[1].children.keys()) == {2, 3}
assert set(trie.root.children[1].children[2].children.keys()) == {3}
assert set(trie.root.children[2].children.keys()) == {3}

# the label list should contain the nodes of each depth according to their label
label_to_simplex = {
1: {1: [(1,)], 2: [(2,)], 3: [(3,)]},
2: {2: [(1, 2)], 3: [(1, 3), (2, 3)]},
3: {3: [(1, 2, 3)]},
}

assert len(trie.label_lists) == len(label_to_simplex)
for depth, label_list in trie.label_lists.items():
assert depth in label_to_simplex
assert len(label_list) == len(label_to_simplex[depth])
for label, nodes in label_list.items():
assert len(nodes) == len(label_to_simplex[depth][label])
for node, expected in zip(nodes, label_to_simplex[depth][label]):
assert node.simplex.elements == expected

def test_iter(self) -> None:
"""Test the iteration of the trie."""
trie = SimplexTrie()
trie.insert((1, 2, 3))
trie.insert((2, 3, 4))
trie.insert((0, 1))

# We guarantee a specific ordering of the simplices when iterating. Hence, we explicitly compare lists here.
assert list(map(lambda node: node.simplex.elements, trie)) == [
(0,),
(1,),
(2,),
(3,),
(4,),
(0, 1),
(1, 2),
(1, 3),
(2, 3),
(2, 4),
(3, 4),
(1, 2, 3),
(2, 3, 4),
]

def test_cofaces(self) -> None:
"""Test the cofaces method."""
trie = SimplexTrie()
trie.insert((1, 2, 3))
trie.insert((1, 2, 4))

# no ordering is guaranteed for the cofaces method
assert set(map(lambda node: node.simplex.elements, trie.cofaces((1,)))) == {
(1,),
(1, 2),
(1, 3),
(1, 4),
(1, 2, 3),
(1, 2, 4),
}
assert set(map(lambda node: node.simplex.elements, trie.cofaces((2,)))) == {
(2,),
(1, 2),
(2, 3),
(2, 4),
(1, 2, 3),
(1, 2, 4),
}

def test_is_maximal(self) -> None:
"""Test the `is_maximal` method."""
trie = SimplexTrie()
trie.insert((1, 2, 3))
trie.insert((1, 2, 4))

assert trie.is_maximal((1, 2, 3))
assert trie.is_maximal((1, 2, 4))
assert not trie.is_maximal((1, 2))
assert not trie.is_maximal((1, 3))
assert not trie.is_maximal((1, 4))
assert not trie.is_maximal((2, 3))

with pytest.raises(ValueError):
trie.is_maximal((5,))

def test_skeleton(self) -> None:
"""Test the skeleton method."""
trie = SimplexTrie()
trie.insert((1, 2, 3))
trie.insert((1, 2, 4))

# no ordering is guaranteed for the skeleton method
assert set(map(lambda node: node.simplex.elements, trie.skeleton(0))) == {
(1,),
(2,),
(3,),
(4,),
}
assert set(map(lambda node: node.simplex.elements, trie.skeleton(1))) == {
(1, 2),
(1, 3),
(1, 4),
(2, 3),
(2, 4),
}
assert set(map(lambda node: node.simplex.elements, trie.skeleton(2))) == {
(1, 2, 3),
(1, 2, 4),
}

with pytest.raises(ValueError):
_ = next(trie.skeleton(-1))
with pytest.raises(ValueError):
_ = next(trie.skeleton(3))
Loading

0 comments on commit 5a1a11a

Please sign in to comment.