示例#1
0
def test_finite_poset(P):
    """
    Test several functions on a given finite poset.

    The function contains tests of different kinds, for example

    - Numerical properties jump number, dimension etc. can't be a bigger
      in a subposet with one element less.
    - "Dual tests", for example the dual of meet-semilattice must be a join-semilattice.
    - Random tries: for example if the dimension of a poset is `k`, then it can't be the
      intersection of `k-1` random linear extensions.

    EXAMPLES::

        sage: from sage.tests.finite_poset import test_finite_poset
        sage: P = posets.RandomPoset(10, 0.15)
        sage: test_finite_poset(P) is None  # Long time
        True
    """
    from sage.combinat.posets.posets import Poset
    from sage.combinat.subset import Subsets
    from sage.misc.prandom import shuffle

    from sage.misc.misc import attrcall

    e = P.random_element()
    P_one_less = P.subposet([x for x in P if x != e])

    # Cardinality
    if len(P) != P.cardinality():
        raise ValueError("error 1 in cardinality")
    if P.cardinality() - 1 != P_one_less.cardinality():
        raise ValueError("error 5 in cardinality")

    # Height
    h1 = P.height()
    h2, chain = P.height(certificate=True)
    if h1 != h2:
        raise ValueError("error 1 in height")
    if h1 != len(chain):
        raise ValueError("error 2 in height")
    if not P.is_chain_of_poset(chain):
        raise ValueError("error 3 in height")
    if len(P.random_maximal_chain()) > h1:
        raise ValueError("error 4 in height")
    if h1 - P_one_less.height() not in [0, 1]:
        raise ValueError("error 5 in height")

    # Width
    w1 = P.width()
    w2, antichain = P.width(certificate=True)
    if w1 != w2:
        raise ValueError("error 1 in width")
    if w1 != len(antichain):
        raise ValueError("error 2 in width")
    if not P.is_antichain_of_poset(antichain):
        raise ValueError("error 3 in width")
    if len(P.random_maximal_antichain()) > w1:
        raise ValueError("error 4 in width")
    if w1 - P_one_less.width() not in [0, 1]:
        raise ValueError("error 5 in width")

    # Dimension
    dim1 = P.dimension()
    dim2, linexts = P.dimension(certificate=True)
    if dim1 != dim2:
        raise ValueError("error 1 in dimension")
    if dim1 != len(linexts):
        raise ValueError("error 2 in dimension")
    P_ = Poset((P.list(), lambda a, b: all(
        linext.index(a) < linext.index(b) for linext in linexts)))
    if P_ != Poset(P.hasse_diagram()):
        raise ValueError("error 3 in dimension")
    x = [P.random_linear_extension() for _ in range(dim1 - 1)]
    P_ = Poset(
        (P.list(),
         lambda a, b: all(linext.index(a) < linext.index(b) for linext in x)))
    if P_ == Poset(P.hasse_diagram()):
        raise ValueError("error 4 in dimension")
    if dim1 - P_one_less.dimension() < 0:
        raise ValueError("error 5 in dimension")

    # Jump number
    j1 = P.jump_number()
    j2, linext = P.jump_number(certificate=True)
    if j1 != j2:
        raise ValueError("error 1 in jump number")
    if P.linear_extension(linext).jump_count() != j1:
        raise ValueError("error 2 in jump number")
    if not P.is_linear_extension(linext):
        raise ValueError("error 3 in jump number")
    if P.linear_extension(P.random_linear_extension()).jump_count() < j1:
        raise ValueError("error 4 in jump number")
    if j1 - P_one_less.jump_number() not in [0, 1]:
        raise ValueError("error 5 in jump number")

    P_dual = P.dual()
    selfdual_properties = [
        'chain', 'bounded', 'connected', 'graded', 'ranked', 'series_parallel',
        'slender', 'lattice'
    ]
    for prop in selfdual_properties:
        f = attrcall('is_' + prop)
        if f(P) != f(P_dual):
            raise ValueError("error in self-dual property %s" % prop)
    if P.is_graded():
        if P.is_bounded():
            if P.is_eulerian() != P_dual.is_eulerian():
                raise ValueError("error in self-dual property eulerian")
            if P.is_eulerian():
                P_ = P.star_product(P)
                if not P_.is_eulerian():
                    raise ("error in star product / eulerian")
        chain1 = P.random_maximal_chain()
        if len(chain1) != h1:
            raise ValueError("error in is_graded")
        if not P.is_ranked():
            raise ValueError("error in is_ranked / is_graded")

    if P.is_meet_semilattice() != P_dual.is_join_semilattice():
        raise ValueError("error in meet/join semilattice")

    if set(P.minimal_elements()) != set(P_dual.maximal_elements()):
        raise ValueError("error in min/max elements")
    if P.top() != P_dual.bottom():
        raise ValueError("error in top/bottom element")

    parts = P.connected_components()
    P_ = Poset()
    for part in parts:
        P_ = P_.disjoint_union(part)
    if not P.is_isomorphic(P_):
        raise ValueError("error in connected components / disjoint union")
    parts = P.ordinal_summands()
    P_ = Poset()
    for part in parts:
        P_ = P_.ordinal_sum(part)
    if not P.is_isomorphic(P_):
        raise ValueError("error in ordinal summands / ordinal sum")

    P_ = P.with_bounds().without_bounds()
    if not P.is_isomorphic(P_):
        raise ValueError("error in with bounds / without bounds")

    P_ = P.completion_by_cuts().irreducibles_poset()
    if not P.has_isomorphic_subposet(P_):
        raise ValueError("error in completion by cuts / irreducibles poset")

    P_ = P.subposet(Subsets(P).random_element())
    if not P_.is_induced_subposet(P):
        raise ValueError("error in subposet / is induced subposet")

    if not P.is_linear_extension(P.random_linear_extension()):
        raise ValueError("error in is linear extension")

    x = list(P)
    shuffle(x)
    if not P.is_linear_extension(P.sorted(x)):
        raise ValueError("error in sorted")

    dil = P.dilworth_decomposition()
    chain = dil[randint(0, len(dil) - 1)]
    if not P.is_chain_of_poset(chain):
        raise ValueError("error in Dilworth decomposition")
    lev = P.level_sets()
    level = lev[randint(0, len(lev) - 1)]
    if not P.is_antichain_of_poset(level):
        raise ValueError("error in level sets")

    # certificate=True must return a pair
    bool_with_cert = [
        'eulerian', 'greedy', 'join_semilattice', 'jump_critical',
        'meet_semilattice', 'slender'
    ]
    for p in bool_with_cert:
        try:  # some properties are not always defined for all posets
            res1 = attrcall('is_' + p)(P)
        except ValueError:
            continue
        res2 = attrcall('is_' + p, certificate=True)(P)
        if type(res2) != type((1, 2)) or len(res2) != 2:
            raise ValueError(
                "certificate-option does not return a pair in %s" % p)
        if res1 != res2[0]:
            raise ValueError("certificate-option changes result in %s" % p)