Source code for pocketpartition.core.kunz._vector
"""
KunzVector — the Kunz coordinate vector as an immutable tuple subclass.
"""
__all__ = ['KunzVector']
from ..numerical_semigroup import NumericalSemigroup
from ._coords import _compute_kunz_coords
[docs]
class KunzVector(tuple):
"""
The Kunz coordinate vector of a NumericalSemigroup, stored as an
immutable tuple of positive integers of length m-1.
Entry k (0-indexed) is w_{k+1} = min{ n in S : n ≡ k+1 (mod m) } / m,
where m is the multiplicity of S.
Because KunzVector subclasses tuple, it supports all standard tuple
operations. The originating semigroup is accessible via `.semigroup`.
"""
def __new__(cls, S: NumericalSemigroup):
coords = _compute_kunz_coords(S)
instance = super().__new__(cls, coords)
return instance
def __init__(self, S: NumericalSemigroup):
self._semigroup = S
# tuple.__init__ takes no arguments
super().__init__()
# --- semigroup pass-throughs ---
@property
def semigroup(self) -> NumericalSemigroup:
"""The NumericalSemigroup this vector was built from."""
return self._semigroup
@property
def multiplicity(self) -> int:
"""The multiplicity of the underlying semigroup (equals ``m``, the vector length plus one)."""
return self._semigroup.multiplicity()
@property
def genus(self) -> int:
"""The genus (number of gaps) of the underlying semigroup."""
return self._semigroup.genus
@property
def frobenius_number(self) -> int:
"""The Frobenius number (largest gap) of the underlying semigroup."""
return self._semigroup.frobenius_number
# --- coordinate access (1-indexed, matching residue notation) ---
[docs]
def coord(self, i: int) -> int:
"""
Return w_i (1-indexed). i must satisfy 1 <= i <= m-1.
"""
m = self.multiplicity
if not (1 <= i <= m - 1):
raise IndexError(f"Index {i} out of range for multiplicity {m}.")
return self[i - 1]
# --- display ---
def __repr__(self) -> str:
return (f"KunzVector(m={self.multiplicity}, "
f"coords={tuple(self)}, genus={self.genus})")