• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

peekxc / splex / 9978389681

17 Jul 2024 05:02PM UTC coverage: 84.772% (-0.2%) from 84.929%
9978389681

push

github

peekxc
v0.3.2

20 of 22 new or added lines in 5 files covered. (90.91%)

17 existing lines in 4 files now uncovered.

835 of 985 relevant lines covered (84.77%)

2.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.48
/src/splex/SetComplex.py
1
import numpy as np
3✔
2
from .meta import * 
3✔
3
from .generics import *
3✔
4
from .Simplex import *
3✔
5
from .complex_abcs import Complex
3✔
6
from sortedcontainers import SortedSet # SortedSet is a vaid Sequence! 
3✔
7

8
class SetComplex(Complex, ComplexLike):
3✔
9
  """ Abstract Simplicial Complex"""
10

11
  def __init__(self, simplices: Iterable[SimplexConvertible] = None):
3✔
12
    """ Set Complex """
13
    self.data = SortedSet([], key=lambda s: (len(s), tuple(s), s)) # for now, just use the lex/dim/face order 
3✔
14
    self.n_simplices = tuple()
3✔
15
    if simplices is not None: 
3✔
16
      self.update(simplices)
3✔
17
  
18
  ## --- Collection requirements --- 
19
  def __iter__(self) -> Iterator[Simplex]:
3✔
20
    """Constructs an iterator of _Simplex_ objects."""
21
    return iter(self.data)
3✔
22
  
23
  def __len__(self, p: Optional[int] = None) -> int:
3✔
24
    """Returns the number of (p)-simplices in the complex.
25
    
26
    Parameters: 
27
      p: optional dimension to restrict too. By default, all simplices are counted. 
28

29
    Returns: 
30
      the number of (p)-simplices in the simplex. 
31
    """
32
    return len(self.data)
3✔
33

34
  def __contains__(self, item: Collection[int]):
3✔
35
    """Simplex membership check."""
36
    return self.data.__contains__(Simplex(item))
3✔
37

38
  ## --- Sequence requirements ---
39
  def __getitem__(self, index: Union[int, slice]):
3✔
40
    """Simplex accessor function."""
41
    return self.data[index]
×
42

43
  # MutableSequence 
44
  # __getitem__, __setitem__, __delitem__, __len__, insert, append, reverse, extend, pop, remove, and __iadd__
45

46
  # MutableSet 
47
  # __contains__, __iter__, __len__, add, discard, clear, pop, remove, __ior__, __iand__, __ixor__, and __isub__
48

49
  ## --- Generics support --- 
50
  def dim(self) -> int:
3✔
51
    """Returns the maximal dimension of any simplex in the complex."""
52
    return len(self.n_simplices) - 1
3✔
53

54
  def faces(self, p: Optional[int] = None, **kwargs) -> Iterator[Simplex]:
3✔
55
    """Enumerates the (p)-faces of the complex."""
56
    if p is None:
3✔
UNCOV
57
      yield from iter(self)
×
58
    else: 
59
      assert isinstance(p, Number)
3✔
60
      yield from filter(lambda s: len(s) == p + 1, iter(self))
3✔
61

62
  def card(self, p: int = None) -> tuple:
3✔
63
    """Cardinality of the complex.
64
    
65
    If p is supplied, returns the number of p-simplices in the complex. Otherwise, a tuple 
66
    whose index p represents the number of p-simplices in the complex. 
67
    """
68
    if p is None: 
3✔
69
      return self.n_simplices
3✔
70
    else: 
71
      assert isinstance(p, int), "Invalid p"
3✔
72
      return 0 if p < 0 or p >= len(self.n_simplices) else self.n_simplices[p]
3✔
73

74
  # --- Additional support functions ---
75
  def cofaces(self, item: Collection[int]) -> Iterator[Simplex]:
3✔
76
    """Enumerates the cofaces of a give simplex."""
77
    s = Simplex(item)
3✔
78
    yield from filter(lambda t: t >= s, iter(self))
3✔
79

80
  def update(self, simplices: Iterable[SimplexConvertible]):
3✔
81
    """Updates the complex by unioning with the given iterable of simplices."""
82
    for s in simplices:
3✔
83
      self.add(s)
3✔
84

85
  def add(self, item: SimplexConvertible) -> None:
3✔
86
    """Adds a simplex to the complex.
87
    
88
    Note that adding a simplex by definition with add all of its faces to the complex as well.
89
    """
90
    s = Simplex(item)                                               # cast to Simplex for comparability
3✔
91
    ns = np.zeros(max(dim(s)+1, dim(self)+1), dtype=np.uint64)      # array to update num. simplices
3✔
92
    ns[:len(self.n_simplices)] = self.n_simplices
3✔
93
    for face in faces(s):
3✔
94
      if face not in self.data:
3✔
95
        self.data.add(face)
3✔
96
        ns[dim(face)] += 1
3✔
97
    self.n_simplices = tuple(ns)
3✔
98
        # if len(face) > len(self.n_simplices):
99
        #   # self.n_simplices = tuple(list(self.n_simplices) + [1])
100
        # else:
101
        #   t = self.n_simplices
102
          # self.n_simplices = tuple(t[i]+1 if i == (len(face)-1) else t[i] for i in range(len(t)))
103
        
104
  def remove(self, item: SimplexConvertible):
3✔
105
    """Removes a simplex from the complex.
106
    
107
    Note that removing a simplex by definition with remove all of its cofaces from the complex as well.
108

109
    This function raises an exception if the supplied simplex is not found. For non-throwing version, see discard.
110
    """
111
    if not self.__contains__(item):
3✔
112
      raise ValueError(f"Simplex {str(Simplex(item))} does not exist in the complex.")
×
113
    self.data.difference_update(set(self.cofaces(item)))
3✔
114
    self._update_n_simplices()
3✔
115

116
  def discard(self, item: SimplexConvertible):
3✔
117
    """Removes a simplex from the complex.
118
    
119
    Note that removing a simplex by definition with remove all of its cofaces from the complex as well.
120
    """
121
    self.data.difference_update(set(self.cofaces(item)))
3✔
122
    self._update_n_simplices()
3✔
123
  
124
  def _update_n_simplices(self) -> None:
3✔
125
    """ Bulk update to shape """
126
    from collections import Counter
3✔
127
    cc = Counter([len(s)-1 for s in self.data])
3✔
128
    self.n_simplices = tuple(dict(sorted(cc.items())).values())
3✔
129

130
  def __repr__(self):
3✔
131
    if len(self) == 0:
×
132
      return "<  Empty set complex >"
×
133
    return f"Set Complex with {card(self)} {tuple(range(0,dim(self)+1))}-simplices"
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc