Source code for pocketpartition.core.genus
__all__ = ['WithGenus', 'WithMaxGenus']
from collections import deque
from ..core.numerical_semigroup import NumericalSemigroup
def bfs_to_depth(root, depth):
"""
Yield every node in a rooted tree that sits at exactly ``depth`` levels
below ``root``.
The tree is traversed breadth-first so that nodes at shallower depths are
visited before nodes at deeper ones, although only nodes at the target
depth are actually yielded.
Parameters
----------
root : NumericalSemigroup
The root of the semigroup tree (typically ``NumericalSemigroup({1})``).
depth : int
The target depth. Nodes at ``depth == 0`` means only ``root`` is
yielded. Negative values produce no output.
Yields
------
NumericalSemigroup
Each numerical semigroup at exactly ``depth`` levels from ``root``.
"""
if depth < 0:
return
queue = deque([(root, 0)])
while queue:
node, current_depth = queue.popleft()
if current_depth == depth:
yield node
elif current_depth < depth:
for child in node.get_children():
queue.append((child, current_depth + 1))
def bfs_up_to_depth(root, depth):
"""
Yield every node in a rooted tree that is at most ``depth`` levels below
``root``, including ``root`` itself.
The tree is traversed breadth-first, so nodes are yielded in non-decreasing
order of depth.
Parameters
----------
root : NumericalSemigroup
The root of the semigroup tree (typically ``NumericalSemigroup({1})``).
depth : int
The maximum depth to explore. Negative values produce no output.
Yields
------
NumericalSemigroup
Each numerical semigroup at depth ``0, 1, ..., depth`` from ``root``.
"""
if depth < 0:
return
queue = deque([(root, 0)])
while queue:
node, current_depth = queue.popleft()
yield node
if current_depth < depth:
for child in node.get_children():
queue.append((child, current_depth + 1))
[docs]
def WithGenus(g):
"""
Yield all numerical semigroups of genus exactly ``g``.
This is a thin wrapper around :func:`bfs_to_depth` rooted at the semigroup
``N`` (generated by ``{1}``), which is the unique semigroup of genus 0 and
the root of the semigroup tree.
Parameters
----------
g : int
The target genus. Must be non-negative; negative values produce no
output.
Yields
------
NumericalSemigroup
Each numerical semigroup whose genus equals ``g``.
Examples
--------
>>> from pocketpartition import WithGenus
>>> semigroups = list(WithGenus(3))
>>> len(semigroups)
4
>>> all(S.genus == 3 for S in semigroups)
True
"""
yield from bfs_to_depth(NumericalSemigroup(generators={1}), g)
[docs]
def WithMaxGenus(g):
"""
Yield all numerical semigroups of genus at most ``g``.
This is a thin wrapper around :func:`bfs_up_to_depth` rooted at the
semigroup ``N`` (generated by ``{1}``), which is the unique semigroup of
genus 0 and the root of the semigroup tree.
Parameters
----------
g : int
The maximum genus to include. Must be non-negative; negative values
produce no output.
Yields
------
NumericalSemigroup
Each numerical semigroup whose genus is in ``{0, 1, ..., g}``.
Examples
--------
>>> from pocketpartition import WithMaxGenus
>>> semigroups = list(WithMaxGenus(2))
>>> all(S.genus <= 2 for S in semigroups)
True
>>> {S.genus for S in semigroups} == {0, 1, 2}
True
"""
yield from bfs_up_to_depth(NumericalSemigroup(generators={1}), g)