kunz¶
pocketpartition.core.kunz¶
Kunz coordinate machinery for numerical semigroups.
Sub-modules¶
_coords : _compute_kunz_coords, kunz_tuple _vector : KunzVector _fourier : FourierKunzVector _distance : kunz_distance _polyhedron : KunzPolyhedron
All public names are re-exported from this package so that existing imports
of the form from pocketpartition.core.kunz import ... continue to work
without modification.
- pocketpartition.core.kunz.kunz_tuple(S)[source]¶
Return the Kunz coordinate tuple of a numerical semigroup.
For a semigroup S with multiplicity m, the Kunz tuple is the vector
(w_1, ..., w_{m-1})wherew_i = min{ n in S : n ≡ i (mod m) } / m.- Parameters:
S (NumericalSemigroup)
- Return type:
- Returns:
tuple of int – Length
m - 1, all entries positive.
Examples
>>> from pocketpartition import NumericalSemigroup >>> from pocketpartition.core.kunz import kunz_tuple >>> S = NumericalSemigroup(generators=[3, 4, 5]) >>> kunz_tuple(S) (1, 1)
- class pocketpartition.core.kunz.KunzVector(S)[source]¶
Bases:
tupleThe 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.
- property semigroup: NumericalSemigroup¶
The NumericalSemigroup this vector was built from.
- class pocketpartition.core.kunz.FourierKunzVector(source)[source]¶
Bases:
objectThe normalized Kunz function viewed as a step function on the circle S^1.
Starting from a KunzVector v = (w_1, …, w_{m-1}) we build:
f : S^1 → [0, 1] f(i/m) = w_i / max_j(w_j) for i = 1, …, m-1 f(0) = 0 (convention: 0 residue class maps to 0)
The domain is discretised as {0, 1/m, 2/m, …, (m-1)/m} ⊂ [0,1) and f is extended to all of [0,1) as a right-continuous step function (piecewise-constant on each interval [i/m, (i+1)/m)).
- Parameters:
source (KunzVector | NumericalSemigroup) – Either a KunzVector or a NumericalSemigroup (converted automatically).
- property kunz_vector: KunzVector¶
- fourier_coefficient(n)[source]¶
Compute the n-th Fourier coefficient of f.
Because f is piecewise-constant on each half-open interval
[i/m, (i+1)/m), the integral\[c_n = \int_0^1 f(x)\, e^{-2\pi i n x}\, dx\]reduces exactly to a finite sum. Integrating
f(i/m) * e^{-2πinx}over[i/m, (i+1)/m)gives(1/m) * f(i/m) * e^{-2πi n (i/m)}, so:\[c_n = \frac{1}{m} \sum_{i=0}^{m-1} f\!\left(\frac{i}{m}\right) e^{-2\pi i n i/m}\]This is the standard DFT of the grid values, scaled by
1/m.- Parameters:
n (int) – Fourier mode index.
- Return type:
- Returns:
complex – The n-th Fourier coefficient c_n.
- fourier_coefficients(n_max)[source]¶
Compute Fourier coefficients c_n for n = -n_max, …, n_max.
Uses numpy’s FFT when available (O(m log m)), otherwise falls back to the per-coefficient DFT loop (O(m * n_max)).
- partial_sum(x, n_max)[source]¶
Evaluate the Fourier partial sum \(S_{n_{\max}}(x) = \sum_{|n| \le n_{\max}} c_n e^{2\pi i n x}\).
Useful for visualising how well the Fourier series reconstructs f.
- Parameters:
x (float) – Point in [0, 1).
n_max (int) – Number of modes on each side.
- Return type:
- Returns:
float – Real part of the partial sum (imaginary part is ~0 for real f).
- distance(other, norm='L2')[source]¶
Compute the distance between this FourierKunzVector and another.
Both functions are evaluated on a common grid of size lcm(m_self, m_other), which is the finest grid on which both step functions are simultaneously constant.
- Parameters:
other (FourierKunzVector)
norm ({“L1”, “L2”, “Linf”}) – Which norm to use:
"L1"— \(\int_0^1 |f(x) - g(x)| \, dx\)"L2"— \(\left(\int_0^1 |f(x) - g(x)|^2 \, dx\right)^{1/2}\) (default)"Linf"— \(\sup_{x \in [0,1)} |f(x) - g(x)|\)
- Return type:
- Returns:
float – The distance ≥ 0.
- Raises:
ValueError – If
normis not one of the supported values.TypeError – If
otheris not a FourierKunzVector, or ifnormis not a string.
- pocketpartition.core.kunz.kunz_distance(S, T, norm='L2')[source]¶
Compute the distance between two numerical semigroups (or already-built Kunz / FourierKunz vectors) using their normalised Kunz step functions.
- Parameters:
S, T (NumericalSemigroup | KunzVector | FourierKunzVector) – The two objects to compare. NumericalSemigroup and KunzVector inputs are automatically converted to FourierKunzVector.
norm ({“L1”, “L2”, “Linf”}) – Which norm to use (default
"L2"):"L1"— sum of absolute differences (normalised by grid size)"L2"— root-mean-square differences (default)"Linf"— maximum absolute difference
- Returns:
float – d(f_S, f_T) ≥ 0, where equality holds iff the two normalised Kunz step functions are identical.
- Return type:
Examples
>>> from pocketpartition import NumericalSemigroup, kunz_distance >>> S = NumericalSemigroup(generators=[3, 4, 5]) >>> T = NumericalSemigroup(generators=[3, 5]) >>> kunz_distance(S, T) # L2 (default) 0.816... >>> kunz_distance(S, T, norm="L1") 0.666... >>> kunz_distance(S, T, norm="Linf") 1.0...
- class pocketpartition.core.kunz.KunzPolyhedron(m)[source]¶
Bases:
objectThe Kunz polyhedron for a given multiplicity m.
The Kunz polyhedron
P(m)is the rational polyhedral cone inR^{m-1}defined by the inequalities:c_i + c_j >= c_{i+j}for all1 <= i <= j <= m-1withi+j < mc_i + c_j + 1 >= c_{i+j-m}for all1 <= i <= j <= m-1withi+j > m
Every numerical semigroup of multiplicity m corresponds to an integer lattice point inside
P(m), and conversely every such lattice point with all positive coordinates determines a numerical semigroup.- Parameters:
m (int) – The multiplicity. Must be a positive integer.
- corner¶
The
mequally-spaced points(0, 1/m, 2/m, ..., (m-1)/m), representing the origin corner of the polyhedron in the normalised coordinate chart.
Examples
>>> from pocketpartition.core.kunz import KunzPolyhedron, kunz_tuple >>> from pocketpartition import NumericalSemigroup >>> kp = KunzPolyhedron(3) >>> S = NumericalSemigroup(generators=[3, 4, 5]) >>> kp.is_point(kunz_tuple(S)) True
- is_point(p)[source]¶
Check whether a coordinate vector lies inside the Kunz polyhedron.
- Parameters:
p (tuple of int or float) – A vector of length
m - 1. Entryp[k]represents the coordinatec_{k+1}(1-indexed residuek+1modm).- Return type:
- Returns:
bool –
Trueifpsatisfies all Kunz polyhedron inequalities,Falseotherwise.
Notes
The inequalities checked are, for all
1 <= i <= j <= m-1:i + j < m→c_i + c_j >= c_{i+j}i + j > m→c_i + c_j + 1 >= c_{i+j-m}i + j == m→ always satisfied for non-negative coordinates
- Raises:
ValueError – If
pdoes not have lengthm - 1.
Examples
>>> kp = KunzPolyhedron(3) >>> kp.is_point((1, 1)) # Kunz tuple of <3, 4, 5> True >>> kp.is_point((-1, 1)) # negative coordinate False