Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor poset examples for better code coverage #35466

Merged
merged 1 commit into from
Apr 13, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 73 additions & 127 deletions src/sage/combinat/posets/poset_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,51 @@
from sage.categories.finite_lattice_posets import FiniteLatticePosets
from sage.graphs.digraph import DiGraph
from sage.rings.integer import Integer
from sage.sets.non_negative_integers import NonNegativeIntegers


def check_int(n, minimum=0):
"""
Check that ``n`` is an integer at least equal to ``minimum``.

This is a boilerplate function ensuring input safety.

INPUT:

- ``n`` -- anything

- ``minimum`` -- an optional integer (default: 0)

EXAMPLES::

sage: from sage.combinat.posets.poset_examples import check_int
sage: check_int(6, 3)
6
sage: check_int(6)
6

sage: check_int(-1)
Traceback (most recent call last):
...
ValueError: number of elements must be a non-negative integer, not -1

sage: check_int(1, 3)
Traceback (most recent call last):
...
ValueError: number of elements must be an integer at least 3, not 1

sage: check_int('junk')
Traceback (most recent call last):
...
ValueError: number of elements must be a non-negative integer, not junk
"""
if minimum == 0:
msg = "a non-negative integer"
else:
msg = f"an integer at least {minimum}"
if n not in NonNegativeIntegers() or n < minimum:
raise ValueError("number of elements must be " + msg + f", not {n}")
return Integer(n)


class Posets(metaclass=ClasscallMetaclass):
Expand Down Expand Up @@ -155,12 +200,7 @@ def __classcall__(cls, n=None):
"""
if n is None:
return sage.categories.posets.Posets()
try:
n = Integer(n)
except TypeError:
raise TypeError("number of elements must be an integer, not {0}".format(n))
if n < 0:
raise ValueError("number of elements must be non-negative, not {0}".format(n))
n = check_int(n)
return FinitePosets_n(n)

@staticmethod
Expand Down Expand Up @@ -203,12 +243,7 @@ def BooleanLattice(n, facade=None, use_subsets=False):
sage: list(posets.BooleanLattice(1, use_subsets=True))
[{}, {1}]
"""
try:
n = Integer(n)
except TypeError:
raise TypeError("number of elements must be an integer, not {0}".format(n))
if n < 0:
raise ValueError("number of elements must be non-negative, not {0}".format(n))
n = check_int(n)
if n == 0:
if use_subsets:
from sage.sets.set import Set
Expand Down Expand Up @@ -282,12 +317,7 @@ def ChainPoset(n, facade=None):
sage: C.cover_relations()
[[0, 1]]
"""
try:
n = Integer(n)
except TypeError:
raise TypeError("number of elements must be an integer, not {0}".format(n))
if n < 0:
raise ValueError("number of elements must be non-negative, not {0}".format(n))
n = check_int(n)
D = DiGraph([range(n), [[x, x + 1] for x in range(n - 1)]],
format='vertices_and_edges')
return FiniteLatticePoset(hasse_diagram=D,
Expand Down Expand Up @@ -335,12 +365,7 @@ def AntichainPoset(n, facade=None):
sage: C.cover_relations()
[]
"""
try:
n = Integer(n)
except TypeError:
raise TypeError("number of elements must be an integer, not {0}".format(n))
if n < 0:
raise ValueError("number of elements must be non-negative, not {0}".format(n))
n = check_int(n)
return Poset((range(n), []), facade=facade)

@staticmethod
Expand Down Expand Up @@ -398,12 +423,7 @@ def DiamondPoset(n, facade=None):
sage: posets.DiamondPoset(7)
Finite lattice containing 7 elements
"""
try:
n = Integer(n)
except TypeError:
raise TypeError("number of elements must be an integer, not {0}".format(n))
if n <= 2:
raise ValueError("n must be an integer at least 3")
n = check_int(n, 3)
c = [[n - 1] for x in range(n)]
c[0] = [x for x in range(1, n - 1)]
c[n - 1] = []
Expand Down Expand Up @@ -435,12 +455,7 @@ def Crown(n, facade=None):
sage: posets.Crown(3)
Finite poset containing 6 elements
"""
try:
n = Integer(n)
except TypeError:
raise TypeError("number of elements must be an integer, not {0}".format(n))
if n < 2:
raise ValueError("n must be an integer at least 2")
n = check_int(n, 2)
D = {i: [i + n, i + n + 1] for i in range(n - 1)}
D[n - 1] = [n, n + n - 1]
return FinitePoset(hasse_diagram=DiGraph(D), category=FinitePosets(),
Expand Down Expand Up @@ -478,12 +493,7 @@ def DivisorLattice(n, facade=None):
Finite lattice containing 1 elements with distinguished linear extension
"""
from sage.arith.misc import divisors, is_prime
try:
n = Integer(n)
except TypeError:
raise TypeError("number of elements must be an integer, not {0}".format(n))
if n <= 0:
raise ValueError("n must be a positive integer")
n = check_int(n, 1)
Div_n = divisors(n)
hasse = DiGraph([Div_n, lambda a, b: b % a == 0 and is_prime(b // a)])
return FiniteLatticePoset(hasse, elements=Div_n, facade=facade,
Expand Down Expand Up @@ -623,9 +633,7 @@ def IntegerPartitionsDominanceOrder(n):
[[4, 2], [5, 1]],
[[5, 1], [6]]]
"""
from sage.rings.semirings.non_negative_integer_semiring import NN
if n not in NN:
raise ValueError('n must be an integer')
n = check_int(n)
from sage.combinat.partition import Partitions, Partition
return LatticePoset((Partitions(n), Partition.dominates)).dual()

Expand Down Expand Up @@ -663,14 +671,7 @@ def PowerPoset(n):
0
"""
# Todo: Make this faster.

try:
n = Integer(n)
except TypeError:
raise TypeError("parameter n must be an integer, not {0}".format(n))
if n < 0:
raise ValueError("parameter n must be non-negative, not {0}".format(n))

n = check_int(n)
all_pos_n = set()
Pn = list(Posets(n))
for P in Pn:
Expand Down Expand Up @@ -759,16 +760,6 @@ def RandomPoset(n, p):

TESTS::

sage: posets.RandomPoset('junk', 0.5)
Traceback (most recent call last):
...
TypeError: number of elements must be an integer, not junk

sage: posets.RandomPoset(-6, 0.5)
Traceback (most recent call last):
...
ValueError: number of elements must be non-negative, not -6

sage: posets.RandomPoset(6, 'garbage')
Traceback (most recent call last):
...
Expand All @@ -783,13 +774,7 @@ def RandomPoset(n, p):
Finite poset containing 0 elements
"""
from sage.misc.prandom import random

try:
n = Integer(n)
except (TypeError, ValueError):
raise TypeError("number of elements must be an integer, not {0}".format(n))
if n < 0:
raise ValueError("number of elements must be non-negative, not {0}".format(n))
n = check_int(n)
try:
p = float(p)
except (TypeError, ValueError):
Expand Down Expand Up @@ -856,16 +841,6 @@ def RandomLattice(n, p, properties=None):

TESTS::

sage: posets.RandomLattice('junk', 0.5)
Traceback (most recent call last):
...
TypeError: number of elements must be an integer, not junk

sage: posets.RandomLattice(-6, 0.5)
Traceback (most recent call last):
...
ValueError: number of elements must be non-negative, not -6

sage: posets.RandomLattice(6, 'garbage')
Traceback (most recent call last):
...
Expand All @@ -885,13 +860,7 @@ def RandomLattice(n, p, properties=None):
Finite lattice containing 0 elements
"""
from copy import copy

try:
n = Integer(n)
except TypeError:
raise TypeError("number of elements must be an integer, not {0}".format(n))
if n < 0:
raise ValueError("number of elements must be non-negative, not {0}".format(n))
n = check_int(n)
try:
p = float(p)
except Exception:
Expand Down Expand Up @@ -973,10 +942,8 @@ def SetPartitions(n):
sage: posets.SetPartitions(4)
Finite lattice containing 15 elements
"""
from sage.rings.semirings.non_negative_integer_semiring import NN
if n not in NN:
raise ValueError('n must be an integer')
from sage.combinat.set_partition import SetPartitions
n = check_int(n)
S = SetPartitions(n)

def covers(x):
Expand Down Expand Up @@ -1083,12 +1050,7 @@ def StandardExample(n, facade=None):
sage: P(4) < P(3), P(4) > P(3)
(False, False)
"""
try:
n = Integer(n)
except TypeError:
raise TypeError("dimension must be an integer, not {0}".format(n))
if n < 2:
raise ValueError("dimension must be at least 2, not {0}".format(n))
n = check_int(n, 2)
return Poset((range(2*n), [[i, j+n] for i in range(n)
for j in range(n) if i != j]),
facade=facade)
Expand Down Expand Up @@ -1244,17 +1206,20 @@ def TetrahedralPoset(n, *colors, **labels):
sage: tet = posets.TetrahedralPoset(3, 'green','yellow','blue','orange')
sage: ji.is_isomorphic(tet)
True

TESTS::

sage: posets.TetrahedralPoset(4,'scarlet')
Traceback (most recent call last):
...
ValueError: color input must be among: 'green', 'red', 'yellow',
'orange', 'silver', and 'blue'
"""
n = check_int(n, 2)
n = n - 1
try:
n = Integer(n)
except TypeError:
raise TypeError("n must be an integer")
if n < 2:
raise ValueError("n must be greater than 2")
for c in colors:
if c not in ('green', 'red', 'yellow', 'orange', 'silver', 'blue'):
raise ValueError("color input must be from the following: 'green', 'red', 'yellow', 'orange', 'silver', and 'blue'")
raise ValueError("color input must be among: 'green', 'red', 'yellow', 'orange', 'silver', and 'blue'")
elem = [(i, j, k) for i in range(n)
for j in range(n - i) for k in range(n - i - j)]
rels = []
Expand Down Expand Up @@ -1421,12 +1386,7 @@ def UpDownPoset(n, m=1):
sage: P = posets.UpDownPoset(0); P
Finite poset containing 0 elements
"""
try:
n = Integer(n)
except TypeError:
raise TypeError("number of elements must be an integer, not {0}".format(n))
if n < 0:
raise ValueError("number of elements must be non-negative, not {0}".format(n))
n = check_int(n)
try:
m = Integer(m)
except TypeError:
Expand Down Expand Up @@ -1581,12 +1541,7 @@ def YoungFibonacci(n):
from sage.categories.finite_posets import FinitePosets
from sage.combinat.words.word import Word

try:
n = Integer(n)
except TypeError:
raise TypeError("number of elements must be an integer, not {0}".format(n))
if n < 0:
raise ValueError("number of elements must be non-negative, not {0}".format(n))
n = check_int(n)

if n == 0:
return MeetSemilattice({'': []})
Expand Down Expand Up @@ -1632,12 +1587,7 @@ def DoubleTailedDiamond(n):
sage: P.cover_relations()
[[1, 2], [2, 3], [2, 4], [3, 5], [4, 5], [5, 6]]
"""
try:
n = Integer(n)
except TypeError:
raise TypeError("number of elements must be an integer, not {}".format(n))
if n <= 0:
raise ValueError("number of elements must be nonnegative, not {}".format(n))
n = check_int(n, 1)

edges = [(i, i+1) for i in range(1, n)]
edges.extend([(n, n+1), (n, n+2), (n+1, n+3), (n+2, n+3)])
Expand Down Expand Up @@ -1680,12 +1630,7 @@ def PermutationPattern(n):
sage: posets.PermutationPattern(2)
Finite poset containing 3 elements
"""
try:
n = Integer(n)
except TypeError:
raise TypeError("number of elements must be an integer, not {}".format(n))
if n <= 0:
raise ValueError("number of elements must be nonnegative, not {}".format(n))
n = check_int(n, 1)
elem = []
for i in range(1, n + 1):
elem += Permutations(i)
Expand Down Expand Up @@ -1841,6 +1786,7 @@ def RibbonPoset(n, descents):
sage: sorted(R.cover_relations())
[[0, 1], [2, 1], [3, 2], [3, 4]]
"""
n = check_int(n)
return Mobile(DiGraph([list(range(n)),
[(i + 1, i) if i in descents else (i, i + 1)
for i in range(n - 1)]]))
Expand Down