Skip to content

Commit

Permalink
First Implementation of a Simplex Trie
Browse files Browse the repository at this point in the history
  • Loading branch information
ffl096 committed Aug 18, 2023
1 parent c5cc0cb commit e07d86b
Show file tree
Hide file tree
Showing 10 changed files with 958 additions and 422 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 @@ -398,6 +398,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
127 changes: 127 additions & 0 deletions test/classes/test_simplex_trie.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import pytest

from toponetx.classes.simplex_trie import SimplexTrie


class TestSimplexTrie:
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 e07d86b

Please sign in to comment.