Exemplo n.º 1
0
    def CoxeterGroupAbsoluteOrderPoset(W, use_reduced_words=True):
        r"""
        Return the poset of elements of a Coxeter group with respect
        to absolute order.

        INPUT:

        - ``W`` -- a Coxeter group
        - ``use_reduced_words`` -- boolean (default: ``True``); if
          ``True``, then the elements are labeled by their lexicographically
          minimal reduced word

        EXAMPLES::

            sage: W = CoxeterGroup(['B', 3])
            sage: Posets.CoxeterGroupAbsoluteOrderPoset(W)
            Finite poset containing 48 elements

            sage: W = WeylGroup(['B', 2], prefix='s')
            sage: Posets.CoxeterGroupAbsoluteOrderPoset(W, False)
            Finite poset containing 8 elements
        """
        if use_reduced_words:
            element_labels = {s: tuple(s.reduced_word()) for s in W}
            return Poset({s: s.absolute_covers() for s in W}, element_labels)
        return Poset({s: s.absolute_covers() for s in W})
Exemplo n.º 2
0
    def arithmetic_independence_poset(self):
        """
        Compute the poset of (arithmetic) independent sets of the associated central toric arrangement.
        This is defined in [Len17b, Definition 5], [Mar18, Definitions 2.1 and 2.2], [DD18, Section 7].
        Notice that it is not the same as the independence poset of the underlying matroid.
        """
        # TODO: implement for Q != 0
        if self._Q.ncols() > 0:
            raise NotImplementedError

        A = self._A.transpose()
        data = {}

        # compute Smith normal forms of all submatrices
        for S_labeled in self.independent_sets():
            S = tuple(sorted(self._groundset_to_index[e] for e in S_labeled))
            D, U, V = A[S, :].smith_form()  # D == U*A[S,:]*V
            diagonal = [D[i, i] if i < D.ncols() else 0 for i in range(len(S))]
            data[tuple(S)] = (diagonal, U)

        # generate all elements of the poset
        elements = {
            S: list(
                vector(ZZ, x) for x in itertools.product(
                    *(range(max(data[tuple(S)][0][i], 1))
                      for i in range(len(S)))))
            for S in data.keys()
        }

        for l in elements.values():
            for v in l:
                v.set_immutable()

        all_elements = list((tuple(self._E[i] for i in S), x)
                            for (S, l) in elements.items() for x in l)
        cover_relations = []

        for (S, l) in elements.items():
            diagonal_S, U_S = data[S]
            S_labeled = tuple(self._E[i] for i in S)

            for s in S:
                i = S.index(s)  # index where the element s appears in S
                T = tuple(t for t in S if t != s)
                T_labeled = tuple(self._E[i] for i in T)

                diagonal_T, U_T = data[T]

                for x in l:
                    y = U_S**(-1) * x
                    z = U_T * vector(ZZ, y[:i].list() + y[i + 1:].list())
                    w = vector(ZZ,
                               (a % diagonal_T[j] if diagonal_T[j] > 0 else 0
                                for j, a in enumerate(z)))
                    w.set_immutable()

                    cover_relations.append(((T_labeled, w), (S_labeled, x)))

        return Poset(data=(all_elements, cover_relations),
                     cover_relations=True)
Exemplo n.º 3
0
    def SymmetricGroupWeakOrderPoset(n, labels="permutations"):
        """
        The poset of permutations with respect to weak order.

        EXAMPLES::

            sage: Posets.SymmetricGroupWeakOrderPoset(4)
            Finite poset containing 24 elements
        """
        if n < 10 and labels == "permutations":
            element_labels = dict([[s, "".join(map(str, s))]
                                   for s in Permutations(n)])
        if n < 10 and labels == "reduced_words":
            element_labels = dict(
                [[s, "".join(map(str, s.reduced_word_lexmin()))]
                 for s in Permutations(n)])

        def weak_covers(s):
            r"""
            Nested function for computing the covers of elements in the
            poset of weak order for the symmetric group.
            """
            return [
                v for v in s.bruhat_succ()
                if s.length() + (s.inverse() * v).length() == v.length()
            ]

        return Poset(dict([[s, weak_covers(s)] for s in Permutations(n)]),
                     element_labels)
Exemplo n.º 4
0
    def AntichainPoset(n):
        """
        Returns an antichain (a poset with no comparable elements)
        containing `n` elements.

        EXAMPLES::

            sage: A = Posets.AntichainPoset(6); A
            Finite poset containing 6 elements
            sage: for i in range(5):
            ...       for j in range(5):
            ...           if A.covers(A(i),A(j)):
            ...              print "TEST FAILED"

        TESTS:

        Check that #8422 is solved::

            sage: Posets.AntichainPoset(0)
            Finite poset containing 0 elements
            sage: C = Posets.AntichainPoset(1); C
            Finite poset containing 1 elements
            sage: C.cover_relations()
            []
            sage: C = Posets.AntichainPoset(2); C
            Finite poset containing 2 elements
            sage: C.cover_relations()
            []
        """
        return Poset((range(n), []))
Exemplo n.º 5
0
        def factorization_poset(self):
            """
            Returns the poset on self, where `u < w` if either u is
            the left symbol of w, or there exists a compatible
            factorization `w = u v` where v is in the quiver.

            The elements at level 1 are the elements of the quiver

            EXAMPLES::

                sage: import sage_semigroups.monoids.catalog as semigroups
                sage: M = PiMonoid(["A",3])
                sage: P = M.factorization_poset(); P
                Finite poset containing 24 elements

            The minimal elements are the idempotents of M::

                sage: sorted([x.element for x in P.minimal_elements()]) == sorted(M.idempotents())
                True

            The elements at level 1 index the quiver of M::

                sage: sorted([x.element for x in P.level_sets()[1]]) == sorted(M.quiver_elements())
                True
            """
            quiver = self.quiver_elements()
            edges = [ [u,uv] for (uv,l) in self.compatible_factorisations_strong().iteritems() for (u,v) in l if v in quiver ] + [ [ u.symbol("left"), u ] for u in self.non_idempotents() ]
            from sage.combinat.posets.posets import Poset
            return Poset((self, edges), cover_relations = False)
Exemplo n.º 6
0
    def random_element(self):
        r"""
        Return a uniformly random element of ``self``.

        ALGORITHM:

        This uses the
        :meth:`~sage.combinat.posets.posets.FinitePoset.random_order_ideal`
        method and the natural bijection with plane partitions.

        EXAMPLES::

            sage: P = PlanePartitions((4,3,5))
            sage: P.random_element()
            Plane partition [[4, 3, 3], [4, 0, 0], [2, 0, 0], [0, 0, 0]]
        """
        def leq(thing1, thing2):
            return all(thing1[i] <= thing2[i] for i in range(len(thing1)))
        elem = [(i,j,k) for i in range(self._box[0]) for j in range(self._box[1])
                for k in range(self._box[2])]
        myposet = Poset((elem, leq))
        R = myposet.random_order_ideal()
        Z = [[0 for i in range(self._box[1])] for j in range(self._box[0])]
        for C in R:
            Z[C[0]][C[1]] += 1
        return self.element_class(self, Z, check=False)
Exemplo n.º 7
0
    def matroid(self):
        r"""
        Returns the underlying matroid.

        Given a covector oriented matroid, the *underlying matroid* is the
        (flat) matroid whose collection of flats is given by the set of
        zeroes of all signed vectors.

        *Note* that matroids as defined through flats are not defined in sage
        version 9.2 and therefore it must be translated to another one of the
        definitions.

        Instead, we order our flats by inclusion; giving us a rank function and
        use the rank function definition of matroid.

        EXAMPLES::

            sage: from oriented_matroids import OrientedMatroid
            sage: C = [ [1,1,1], [1,1,0],[1,1,-1],[1,0,-1],[1,-1,-1],[0,-1,-1],
            ....: [-1,-1,-1],[0,1,1],[-1,1,1],[-1,0,1],[-1,-1,1],[-1,-1,0],
            ....: [0,0,0]]
            sage: M = OrientedMatroid(C, key='covector')
            sage: M.matroid()
            Matroid of rank 2 on 3 elements


        """
        from sage.matroids.constructor import Matroid
        from sage.combinat.posets.posets import Poset
        flats = list(set([frozenset(X.zeroes()) for X in self.elements()]))
        inc = lambda a,b: a.issubset(b)
        rf = Poset((flats, inc)).rank_function()
        return Matroid(groundset=self.groundset(), rank_function=rf)
Exemplo n.º 8
0
        def bruhat_poset(self, facade=False):
            """
            Return the Bruhat poset of ``self``.

            .. SEEALSO::

                :meth:`bhz_poset`, :meth:`shard_poset`, :meth:`weak_poset`

            EXAMPLES::

                sage: W = WeylGroup(["A", 2])
                sage: P = W.bruhat_poset()
                sage: P
                Finite poset containing 6 elements
                sage: P.show()

            Here are some typical operations on this poset::

                sage: W = WeylGroup(["A", 3])
                sage: P = W.bruhat_poset()
                sage: u = W.from_reduced_word([3,1])
                sage: v = W.from_reduced_word([3,2,1,2,3])
                sage: P(u) <= P(v)
                True
                sage: len(P.interval(P(u), P(v)))
                10
                sage: P.is_join_semilattice()
                False

            By default, the elements of `P` are aware that they belong
            to `P`::

                sage: P.an_element().parent()
                Finite poset containing 24 elements

            If instead one wants the elements to be plain elements of
            the Coxeter group, one can use the ``facade`` option::

                sage: P = W.bruhat_poset(facade = True)
                sage: P.an_element().parent()
                Weyl Group of type ['A', 3] (as a matrix group acting on the ambient space)

            .. SEEALSO:: :func:`Poset` for more on posets and facade posets.

            TESTS::

                sage: [len(WeylGroup(["A", n]).bruhat_poset().cover_relations()) for n in [1,2,3]]
                [1, 8, 58]

            .. todo::

                - Use the symmetric group in the examples (for nicer
                  output), and print the edges for a stronger test.
                - The constructed poset should be lazy, in order to
                  handle large / infinite Coxeter groups.
            """
            from sage.combinat.posets.posets import Poset
            covers = tuple([u, v] for v in self
                           for u in v.bruhat_lower_covers())
            return Poset((self, covers), cover_relations=True, facade=facade)
Exemplo n.º 9
0
    def __init__(self, dag):
        r"""
        Creates an object representing the class of all linear extensions
        of the directed acyclic graph \code{dag}.

        EXAMPLES::

            sage: from sage.graphs.linearextensions import LinearExtensions
            sage: D = DiGraph({ 0:[1,2], 1:[3], 2:[3,4] })
            sage: l = LinearExtensions(D)
            doctest:...: DeprecationWarning: LinearExtensions is deprecated; use FinitePoset.linear_extensions or DiGraph.topological_sort_generator instead
            See https://trac.sagemath.org/25864 for details.

            sage: l == loads(dumps(l))
            True

        TESTS::

            sage: list(LinearExtensions(DiGraph({ })))
            [[]]

            sage: LinearExtensions(DiGraph({ 0:[1], 1:[0] }))
            Traceback (most recent call last):
            ...
            ValueError: The graph is not directed acyclic

        """
        from sage.combinat.posets.posets import Poset
        self._dag = Poset(dag)  # this returns a copy
Exemplo n.º 10
0
def LatticePoset(data, *args, **options):
    r"""
    Construct a lattice from various forms of input data.

    INPUT:

    - ``data``, ``*args``, ``**options`` -- data and options that will
      be passed down to :func:`Poset` to construct a poset that is
      also a lattice.

    OUTPUT:

        FiniteLatticePoset -- an instance of :class:`FiniteLatticePoset`

    .. seealso:: :class:`Posets`, :class:`FiniteLatticePosets`, :func:`JoinSemiLattice`, :func:`MeetSemiLattice`

    EXAMPLES:

    Using data that defines a poset::

        sage: LatticePoset([[1,2],[3],[3]])
        Finite lattice containing 4 elements

        sage: LatticePoset([[1,2],[3],[3]], cover_relations = True)
        Finite lattice containing 4 elements

    Using a previously constructed poset::

        sage: P = Poset([[1,2],[3],[3]])
        sage: L = LatticePoset(P); L
        Finite lattice containing 4 elements
        sage: type(L)
        <class 'sage.combinat.posets.lattices.FiniteLatticePoset_with_category'>

    If the data is not a lattice, then an error is raised::

        sage: elms = [1,2,3,4,5,6,7]
        sage: rels = [[1,2],[3,4],[4,5],[2,5]]
        sage: LatticePoset((elms, rels))
        Traceback (most recent call last):
        ...
        ValueError: Not a lattice.

    Creating a facade lattice::

        sage: L = LatticePoset([[1,2],[3],[3]], facade = True)
        sage: L.category()
        Join of Category of finite lattice posets and Category of finite enumerated sets and Category of facade sets
        sage: parent(L[0])
        Integer Ring
        sage: TestSuite(L).run(skip = ['_test_an_element']) # is_parent_of is not yet implemented

    """
    if isinstance(data,FiniteLatticePoset) and len(args) == 0 and len(options) == 0:
        return data
    P = Poset(data, *args, **options)
    if not P.is_lattice():
        raise ValueError("Not a lattice.")

    return FiniteLatticePoset(P, category = FiniteLatticePosets(), facade = P._is_facade)
Exemplo n.º 11
0
def shard_poset(n):
    """
    Return the shard intersection order on permutations of size `n`.

    This is defined on the set of permutations. To every permutation,
    one can attach a pre-order, using the descending runs and their
    relative positions.

    The shard intersection order is given by the implication (or refinement)
    order on the set of pre-orders defined from all permutations.

    This can also be seen in a geometrical way. Every pre-order defines
    a cone in a vector space of dimension `n`. The shard poset is given by
    the inclusion of these cones.

    .. SEEALSO::

        :func:`shard_preorder_graph`

    EXAMPLES::

        sage: P = posets.ShardPoset(4); P  # indirect doctest
        Finite poset containing 24 elements
        sage: P.chain_polynomial()
        34*q^4 + 90*q^3 + 79*q^2 + 24*q + 1
        sage: P.characteristic_polynomial()
        q^3 - 11*q^2 + 23*q - 13
        sage: P.zeta_polynomial()
        17/3*q^3 - 6*q^2 + 4/3*q
        sage: P.is_selfdual()
        False
    """
    import operator
    Sn = [ShardPosetElement(s) for s in Permutations(n)]
    return Poset([Sn, operator.le], cover_relations=False, facade=True)
Exemplo n.º 12
0
        def bhz_poset(self):
            r"""
            Return the Bergeron-Hohlweg-Zabrocki partial order on the Coxeter
            group.

            This is a partial order on the elements of a finite
            Coxeter group `W`, which is distinct from the Bruhat
            order, the weak order and the shard intersection order. It
            was defined in [BHZ05]_.

            This partial order is not a lattice, as there is no unique
            maximal element. It can be succintly defined as follows.

            Let `u` and `v` be two elements of the Coxeter group `W`. Let
            `S(u)` be the support of `u`. Then `u \leq v` if and only
            if `v_{S(u)} = u` (here `v = v^I v_I` denotes the usual
            parabolic decomposition with respect to the standard parabolic
            subgroup `W_I`).

            .. SEEALSO::

                :meth:`bruhat_poset`, :meth:`shard_poset`, :meth:`weak_poset`

            EXAMPLES::

                sage: W = CoxeterGroup(['A',3], base_ring=ZZ)
                sage: P = W.bhz_poset(); P
                Finite poset containing 24 elements
                sage: P.relations_number()
                103
                sage: P.chain_polynomial()
                34*q^4 + 90*q^3 + 79*q^2 + 24*q + 1
                sage: len(P.maximal_elements())
                13

            REFERENCE:

            .. [BHZ05] \N. Bergeron, C. Hohlweg, and M. Zabrocki, *Posets
               related to the Connectivity Set of Coxeter Groups*.
               :arxiv:`math/0509271v3`
            """
            from sage.graphs.digraph import DiGraph
            from sage.combinat.posets.posets import Poset

            def covered_by(ux, vy):
                u, iu, Su = ux
                v, iv, Sv = vy
                if len(Sv) != len(Su) + 1:
                    return False
                if not all(u in Sv for u in Su):
                    return False
                return all((v * iu).has_descent(x, positive=True) for x in Su)

            vertices = [(u, u.inverse(),
                         tuple(set(u.reduced_word_reverse_iterator())))
                        for u in self]
            dg = DiGraph([vertices, covered_by])
            dg.relabel(lambda x: x[0])
            return Poset(dg, cover_relations=True)
Exemplo n.º 13
0
    def StandardExample(n, facade=None):
        r"""
        Return the partially ordered set on ``2n`` elements with
        dimension ``n``.

        Let `P` be the poset on `\{0, 1, 2, \ldots, 2n-1\}` whose defining
        relations are that `i < j` for every `0 \leq i < n \leq j < 2n`
        except when `i + n = j`. The poset `P` is the so-called
        *standard example* of a poset with dimension `n`.

        INPUT:

        - ``n`` -- an integer `\ge 2`, dimension of the constructed poset
        - ``facade`` (boolean) -- whether to make the returned poset a
          facade poset (see :mod:`sage.categories.facade_sets`); the
          default behaviour is the same as the default behaviour of
          the :func:`~sage.combinat.posets.posets.Poset` constructor

        OUTPUT:

        The standard example of a poset of dimension `n`.

        EXAMPLES::

            sage: A = Posets.StandardExample(3); A
            Finite poset containing 6 elements
            sage: A.dimension()
            3

        REFERENCES:

        .. [Rosen] K. Rosen *Handbook of Discrete and Combinatorial
           Mathematics* (1999), Chapman and Hall.

        .. [Garg] V. Garg *Introduction to Lattice Theory with Computer
           Science Applications* (2015), Wiley.

        TESTS::

            sage: A = Posets.StandardExample(10); A
            Finite poset containing 20 elements
            sage: len(A.cover_relations())
            90

            sage: P = Posets.StandardExample(5, facade=False)
            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))
        return Poset((range(2 * n), [[i, j + n] for i in range(n)
                                     for j in range(n) if i != j]),
                     facade=facade)
Exemplo n.º 14
0
    def UpDownPoset(n, m=1):
        r"""
        Return the up-down poset on `n` elements where every `(m+1)`
        step is down and the rest are up.

        The case where `m=1` is sometimes referred to as the zig-zag poset
        or the fence.

        INPUT:
    
        - ``n`` - nonnegative integer, number of elements in the poset
        - ``m`` - nonnegative integer (default 1), how frequently down
          steps occur

        OUTPUT:

        The partially ordered set on `\{ 0, 1, \ldots, n-1 \}`
        where `i` covers `i+1` if `m` divides `i+1`, and `i+1` covers `i`
        otherwise.

        EXAMPLES::

            sage: P = Posets.UpDownPoset(7, 2); P
            Finite poset containing 7 elements
            sage: sorted(P.cover_relations())
            [[0, 1], [1, 2], [3, 2], [3, 4], [4, 5], [6, 5]]

        Fibonacci numbers as the number of antichains of a poset::

            sage: [len(Posets.UpDownPoset(n).antichains().list()) for n in range(0, 6)]
            [1, 2, 3, 5, 8, 13]

        TESTS::

            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))
        try:
            m = Integer(m)
        except TypeError:
            raise TypeError(
                "parameter m must be an integer, not {0}".format(m))
        if m < 1:
            raise ValueError("parameter m must be positive, not {0}".format(m))

        covers = [[i, i + 1] if (i + 1) % (m + 1) else [i + 1, i]
                  for i in range(n - 1)]
        return Poset((range(n), covers), cover_relations=True)
Exemplo n.º 15
0
    def heap(self, **kargs):
        r"""
        Create the heap poset of ``self``.

        The heap of an FC element `w` is a labeled poset that can be defined
        from any reduced word of `w`. Different reduced words yield isomorphic
        labeled posets, so the heap is well defined.

        Heaps are very useful for visualizing and studying FC elements; see, for
        example, [Ste1996]_ and [GX2020]_.

        INPUT:

        - ``self`` -- list, a reduced word `w=s_0... s_{k-1}` of an FC element

        - ``one_index`` -- boolean (default: False). Setting the value to True
          will change the underlying set of the poset to `\{1, 2, \dots, n\}`

        - ``display_labeling`` -- boolean (default: False). Setting the value to
          True will display the label `s_i` for each element `i` of the poset

        OUTPUT: A labeled poset where the underlying set is `\{0,1,...,k-1\}`
        and where each element `i` carries `s_i` as its label. The partial order
        `\prec` on the poset is defined by declaring `i\prec j` if `i<j` and
        `m(s_i,s_j)\neq 2`.

        EXAMPLES::

            sage: FC = CoxeterGroup(['A', 5]).fully_commutative_elements()
            sage: FC([1, 4, 3, 5, 2, 4]).heap().cover_relations()
            [[1, 2], [1, 3], [2, 5], [2, 4], [3, 5], [0, 4]]
            sage: FC([1, 4, 3, 5, 4, 2]).heap(one_index=True).cover_relations()
            [[2, 3], [2, 4], [3, 6], [3, 5], [4, 6], [1, 5]]
        """
        m = self.parent().coxeter_group().coxeter_matrix()

        one_index = kargs.get('one_index', False)
        display_labeling = kargs.get('display_labeling', False)
        # elements of the poset:
        elements = list(range(1,
                              len(self) +
                              1)) if one_index else list(range(len(self)))

        # get the label of each poset element:
        def letter(index):
            return self[index - 1] if one_index else self[index]

        # specify the partial order:
        relations = [(i, j) for [i, j] in itertools.product(elements, repeat=2)
                     if i < j and m[letter(i), letter(j)] != 2]
        p = Poset((elements, relations))

        if not display_labeling:
            return p
        else:
            return p.relabel(lambda i: (i, letter(i)))
Exemplo n.º 16
0
def LocFreeSheaf(stalk_dict = {}, res_dict = {}, base_ring = ZZ, domain_poset = None):
    '''
      Construct a finite locally free sheaf of modules on a poset, given 
      certain input. Checks are performed to check if the given input indeed
      defines a sheaf. 
      
      INPUT:
      
      - ``stalk_dict`` -- (default: ``{}``); a dictionary where the keys are the points in the poset
          and the values are the ranks of the corresponding stalks.
      
      - ``res_dict`` -- (default: ``{}``); a dictionary where the keys are cover-relations of the poset
         (as tuples) and the values are the matrices of the corresponding restriction maps.
         Instead of a matrix, the input ``0`` is accepted and interpreted as the zero map 
         and the input ``1`` is accepted and interpreted as the identity matrix. 
         
      - ``base_ring`` -- (default: ``ZZ``); the ring over which the sheaf of modules is defined. 
          Can be any commutative ring, but to be able to calculate sheaf cohomology, one should 
          use rings that can be used as base ring for a ``ChainComplex``. Fields or `\mathbb{Z}` work fine. 
      
      - ``domain_poset`` -- (default: ``None``); the finite poset on which the sheaf is defined. 
          If the domain_poset is None, a domain poset will be build from the data in the stalk-
          and restriction dictionaries.  
      
      OUTPUT:
      
      An instance of  :class:`LocallyFreeSheafFinitePoset`.
      
    '''
    
    # Build a poset from the data in the stalk dict and the res dict
    build_poset_dict = dict()
    for key in stalk_dict:
        build_poset_dict[key] = []
    for relation in res_dict:
        build_poset_dict[relation[0]].append(relation[1])
    try:
        built_poset = Poset(build_poset_dict)
    except:
        raise ValueError("Data does not determine a sheaf on a poset.")
    
    # If a domain poset was provided, check if it matches the poset structure 
    # obtained from the stalk and res dictionaries. 
    if domain_poset is not None:
        if not domain_poset.is_isomorphic(built_poset):
            raise ValueError("Data does not determine a sheaf on the given poset.")
    else:
        domain_poset = built_poset
    
    # Build the sheaf and check if it is indeed a valid sheaf. 
    sheaf = LocallyFreeSheafFinitePoset(stalk_dict, res_dict, base_ring, domain_poset)
    if not sheaf._sheaf_data_valid():
        raise ValueError("The sheaf data is not valid")
    
    return sheaf
Exemplo n.º 17
0
    def SSTPoset(s, f=None):
        """
        The poset on semistandard tableaux of shape ``s`` and largest
        entry ``f`` that is ordered by componentwise comparison of the
        entries.

        INPUT:

        - ``s`` - shape of the tableaux

        - ``f`` - maximum fill number.  This is an optional
          argument.  If no maximal number is given, it will use
          the number of cells in the shape.

        NOTE: This is a basic implementation and most certainly
        not the most efficient.

        EXAMPLES::

            sage: Posets.SSTPoset([2,1])
            Finite poset containing 8 elements

            sage: Posets.SSTPoset([2,1],4)
            Finite poset containing 20 elements

            sage: Posets.SSTPoset([2,1],2).cover_relations()
            [[[[1, 1], [2]], [[1, 2], [2]]]]

            sage: Posets.SSTPoset([3,2]).bottom()  # long time (6s on sage.math, 2012)
            [[1, 1, 1], [2, 2]]

            sage: Posets.SSTPoset([3,2],4).maximal_elements()
            [[[3, 3, 4], [4, 4]]]
        """
        from sage.combinat.tableau import SemistandardTableaux

        def tableaux_is_less_than(a, b):
            atstring = []
            btstring = []
            for i in a:
                atstring += i
            for i in b:
                btstring += i
            for i in range(len(atstring)):
                if atstring[i] > btstring[i]:
                    return False
            return True

        if f is None:
            f = 0
            for i in s:
                f += i
        E = SemistandardTableaux(s, max_entry=f)
        return Poset((E, tableaux_is_less_than))
Exemplo n.º 18
0
    def to_poset(self, root_to_leaf=False):
        r"""
        Return the poset obtained by interpreting the tree as a hasse
        diagram. The default orientation is from leaves to root but you can
        pass ``root_to_leaf=True`` to obtain the inverse orientation.

        INPUT:

        - ``root_to_leaf`` -- boolean, true if the poset orientation should
          be from root to leaves. It is false by default.

        EXAMPLES::

            sage: t = OrderedTree([])
            sage: t.to_poset()
            Finite poset containing 1 elements
            sage: p = OrderedTree([[[]],[],[]]).to_poset()
            sage: p.cover_relations()
            [[0, 4], [1, 4], [2, 3], [3, 4]]
            sage: p = OrderedTree([[[]],[],[]]).to_poset(root_to_leaf=True)
            sage: p.cover_relations()
            [[0, 2], [0, 3], [0, 4], [4, 1]]

        If the tree is labelled, we use its labelling to label the poset.
        Otherwise, we use the poset canonical labelling::

            sage: t = OrderedTree([[[]],[],[]]).canonical_labelling()
            sage: t
            1[2[3[]], 4[], 5[]]
            sage: t.to_poset().cover_relations()
            [[5, 1], [4, 1], [3, 2], [2, 1]]
        """
        if self in LabelledOrderedTrees():
            relabel = False
        else:
            self = self.canonical_labelling()
            relabel = True
        relations = []
        elements = [self.label()]
        roots = [self]
        while len(roots) != 0:
            node = roots.pop()
            for child in node:
                elements.append(child.label())
                relations.append((node.label(),
                                  child.label()) if root_to_leaf else (
                                      child.label(), node.label()))
                roots.append(child)
        from sage.combinat.posets.posets import Poset
        p = Poset([elements, relations])
        if relabel:
            p = p.canonical_label()
        return p
Exemplo n.º 19
0
    def SymmetricGroupBruhatOrderPoset(n):
        """
        The poset of permutations with respect to Bruhat order.

        EXAMPLES::

            sage: Posets.SymmetricGroupBruhatOrderPoset(4)
            Finite poset containing 24 elements
        """
        if n < 10:
            element_labels = dict([[s,"".join(map(str,s))] for s in Permutations(n)])
        return Poset(dict([[s,s.bruhat_succ()]
                for s in Permutations(n)]),element_labels)
Exemplo n.º 20
0
    def octants(self):
        assert self._degrees.is_finite()
        from sage.combinat.posets.posets import Poset

        def pocom(a, b):
            t1, e1, s1 = a
            t2, e2, s2 = b
            if (t1 in (t2, 0)) and (e1 in (e2, 0)) and (s1 in (s2, 0)):
                return True
            return False

        X = Poset(([(sgn(t), sgn(e), sgn(s)) for (t, e, s) in self._degrees], pocom))
        return [list(u) for u in X.maximal_elements()]
Exemplo n.º 21
0
 def restrict_to(self, open_set):
     """
       Construct the restriction sheaf of ``self`` to ``open_set``. 
     """
     
     # Check whether the given set is indeed upwards closed
     if any(r[1] not in open_set for r in filter(lambda x: x[0] in open_set, self._domain_poset.relations())):
         raise ValueError("The given set is not upward closed.")
         
     s_dict = dict(filter(lambda (key, value): key in open_set, self._stalk_dict.items()))
     r_dict = dict(filter(lambda (key, value): key[0] in open_set, self._res_dict.items()))
     poset_dict = {x:self._domain_poset.order_filter([x])[1:] for x in s_dict}
     return LocallyFreeSheafFinitePoset(s_dict, r_dict, self._base_ring, Poset(poset_dict))
Exemplo n.º 22
0
    def circuits(self):
        """
        Return the circuits.

        Given a vector oriented matroid, the set of circuits is the set
        `Min(V)` which denotes the set of inclusion-minimal (nonempty) signed
        subsets.
        """
        from sage.combinat.posets.posets import Poset
        from oriented_matroids import OrientedMatroid
        # remove 0
        vecs = [v for v in self.vectors() if not v.is_zero()]
        P = Poset([vecs, lambda x, y: x.is_restriction_of(y)])
        return P.minimal_elements()
Exemplo n.º 23
0
    def SymmetricGroupWeakOrderPoset(n, labels="permutations", side="right"):
        r"""
        The poset of permutations of `\{ 1, 2, \ldots, n \}` with respect
        to the weak order (also known as the permutohedron order, cf.
        :meth:`~sage.combinat.permutation.Permutation.permutohedron_lequal`).

        The optional variable ``labels`` (default: ``"permutations"``)
        determines the labelling of the elements if `n < 10`. The optional
        variable ``side`` (default: ``"right"``) determines whether the
        right or the left permutohedron order is to be used.

        EXAMPLES::

            sage: Posets.SymmetricGroupWeakOrderPoset(4)
            Finite poset containing 24 elements
        """
        if n < 10 and labels == "permutations":
            element_labels = dict([[s, "".join(map(str, s))]
                                   for s in Permutations(n)])
        if n < 10 and labels == "reduced_words":
            element_labels = dict(
                [[s, "".join(map(str, s.reduced_word_lexmin()))]
                 for s in Permutations(n)])
        if side == "left":

            def weak_covers(s):
                r"""
                Nested function for computing the covers of elements in the
                poset of left weak order for the symmetric group.
                """
                return [
                    v for v in s.bruhat_succ() if s.length() +
                    (s.inverse().right_action_product(v)).length() ==
                    v.length()
                ]
        else:

            def weak_covers(s):
                r"""
                Nested function for computing the covers of elements in the
                poset of right weak order for the symmetric group.
                """
                return [
                    v for v in s.bruhat_succ() if s.length() +
                    (s.inverse().left_action_product(v)).length() ==
                    v.length()
                ]

        return Poset(dict([[s, weak_covers(s)] for s in Permutations(n)]),
                     element_labels)
Exemplo n.º 24
0
    def SymmetricGroupBruhatIntervalPoset(start, end):
        """
        The poset of permutations with respect to Bruhat order.

        INPUT:

        - ``start`` - list permutation

        - ``end`` - list permutation (same n, of course)

        .. note::

           Must have ``start`` <= ``end``.

        EXAMPLES:

        Any interval is rank symmetric if and only if it avoids these
        permutations::

            sage: P1 = Posets.SymmetricGroupBruhatIntervalPoset([1,2,3,4], [3,4,1,2])
            sage: P2 = Posets.SymmetricGroupBruhatIntervalPoset([1,2,3,4], [4,2,3,1])
            sage: ranks1 = [P1.rank(v) for v in P1]
            sage: ranks2 = [P2.rank(v) for v in P2]
            sage: [ranks1.count(i) for i in uniq(ranks1)]
            [1, 3, 5, 4, 1]
            sage: [ranks2.count(i) for i in uniq(ranks2)]
            [1, 3, 5, 6, 4, 1]

        """
        start = Permutation(start)
        end = Permutation(end)
        if len(start) != len(end):
            raise TypeError("Start (%s) and end (%s) must have same length." %
                            (start, end))
        if not start.bruhat_lequal(end):
            raise TypeError(
                "Must have start (%s) <= end (%s) in Bruhat order." %
                (start, end))
        unseen = [start]
        nodes = {}
        while len(unseen) > 0:
            perm = unseen.pop(0)
            nodes[perm] = [
                succ_perm for succ_perm in perm.bruhat_succ()
                if succ_perm.bruhat_lequal(end)
            ]
            for succ_perm in nodes[perm]:
                if succ_perm not in nodes:
                    unseen.append(succ_perm)
        return Poset(nodes)
Exemplo n.º 25
0
    def AntichainPoset(n, facade=None):
        """
        Return an antichain (a poset with no comparable elements)
        containing `n` elements.

        INPUT:

        - ``n`` (an integer) -- number of elements
        - ``facade`` (boolean) -- whether to make the returned poset a
          facade poset (see :mod:`sage.categories.facade_sets`); the
          default behaviour is the same as the default behaviour of
          the :func:`~sage.combinat.posets.posets.Poset` constructor

        EXAMPLES::

            sage: A = Posets.AntichainPoset(6); A
            Finite poset containing 6 elements

        TESTS::

            sage: for i in range(5):
            ....:     for j in range(5):
            ....:         if A.covers(A(i),A(j)):
            ....:             print("TEST FAILED")

        TESTS:

        Check that :trac:`8422` is solved::

            sage: Posets.AntichainPoset(0)
            Finite poset containing 0 elements
            sage: C = Posets.AntichainPoset(1); C
            Finite poset containing 1 elements
            sage: C.cover_relations()
            []
            sage: C = Posets.AntichainPoset(2); C
            Finite poset containing 2 elements
            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))
        return Poset((range(n), []), facade=facade)
Exemplo n.º 26
0
    def DiamondPoset(n, facade=False):
        """
        Returns the lattice of rank two containing ``n`` elements.

        EXAMPLES::

            sage: Posets.DiamondPoset(7)
            Finite lattice containing 7 elements
        """
        c = [[n - 1] for x in range(n)]
        c[0] = [x for x in range(1, n - 1)]
        c[n - 1] = []
        if n > 2:
            return LatticePoset(c, facade=facade)
        else:
            return Poset(c, facade=facade)
Exemplo n.º 27
0
    def _is_valid_ribbon(self, ribbon):
        r"""
        Return ``True`` if a ribbon has at most one anchor, no vertex has two
        or more anchors, and every hanging poset is d-complete.

        INPUT:

        - ``ribbon`` -- a list of elements that form a ribbon in your poset

        TESTS::

            sage: P = posets.RibbonPoset(5, [2])
            sage: P._is_valid_ribbon([0,1,2,3,4])
            True
            sage: P._is_valid_ribbon([2])
            False
            sage: P._is_valid_ribbon([2,3,4])
            True
            sage: P._is_valid_ribbon([2,3])
            True
        """
        ribbon = [self._element_to_vertex(x) for x in ribbon]
        G = self._hasse_diagram
        G_un = G.to_undirected().copy(immutable=False)
        R = G.subgraph(ribbon)
        num_anchors = 0

        for r in ribbon:
            anchor_neighbors = set(G.neighbors_out(r)).difference(
                set(R.neighbors_out(r)))
            if len(anchor_neighbors) == 1:
                num_anchors += 1
            elif len(anchor_neighbors) > 1:
                return False

            for lc in G.neighbors_in(r):
                if lc in ribbon:
                    continue

                G_un.delete_edge(lc, r)
                P = Poset(
                    G.subgraph(G_un.connected_component_containing_vertex(lc)))
                if P.top() != lc or not P.is_d_complete():
                    return False
                G_un.add_edge(lc, r)

        return True
Exemplo n.º 28
0
def MeetSemilattice(data, *args, **options):
    r"""
    Construct a meet semi-lattice from various forms of input data.

    INPUT:

    - ``data``, ``*args``, ``**options`` -- data and options that will
      be passed down to :func:`Poset` to construct a poset that is
      also a meet semilattice.

    .. seealso:: :func:`Poset`, :func:`JoinSemilattice`, :func:`LatticePoset`

    EXAMPLES:

    Using data that defines a poset::

          sage: MeetSemilattice([[1,2],[3],[3]])
          Finite meet-semilattice containing 4 elements

          sage: MeetSemilattice([[1,2],[3],[3]], cover_relations = True)
          Finite meet-semilattice containing 4 elements

    Using a previously constructed poset::

          sage: P = Poset([[1,2],[3],[3]])
          sage: L = MeetSemilattice(P); L
          Finite meet-semilattice containing 4 elements
          sage: type(L)
          <class 'sage.combinat.posets.lattices.FiniteMeetSemilattice_with_category'>

    If the data is not a lattice, then an error is raised::

          sage: elms = [1,2,3,4,5,6,7]
          sage: rels = [[1,2],[3,4],[4,5],[2,5]]
          sage: MeetSemilattice((elms, rels))
          Traceback (most recent call last):
          ...
          ValueError: Not a meet semilattice.
    """
    if isinstance(
            data,
            FiniteMeetSemilattice) and len(args) == 0 and len(options) == 0:
        return data
    P = Poset(data, *args, **options)
    if not P.is_meet_semilattice():
        raise ValueError, "Not a meet semilattice."
    return FiniteMeetSemilattice(P)
Exemplo n.º 29
0
def _dualizing_sheaf(poset, degree, base_ring, rank):
    p = degree * -1
    chains = sorted(filter(lambda chain: len(chain) == p + 1, poset.chains()))
    singleton = Poset({0: []}, {})
    sheaf = LocallyFreeSheafFinitePoset({0: rank}, {},
                                        base_ring=base_ring,
                                        domain_poset=singleton)
    result = None
    hom = Hom(singleton, poset)
    for c in chains:
        inclusion = hom(lambda point: {0: c[-1]}[point])
        to_add = sheaf.pushforward(inclusion)
        if result is None:
            result = to_add
        else:
            result = result + to_add
    return result
Exemplo n.º 30
0
        def tope_poset(self, base_tope, facade=False):
            r"""
            Returns the tope poset.

            The tope poset is the poset `(\mathcal{T}, B)` where `\mathcal{T}`
            is the set of topes and `B` is a distinguished tope called the
            *base tope*. The order is given by inclusion of separation sets
            from the base tope: `X \leq Y` if and only if
            `S(B, X) \subseteq S(B, Y)`.
            """
            from sage.combinat.posets.posets import Poset
            els = self.topes()
            rels = [(X, Y) for X in els for Y in els
                    if base_tope.separation_set(X).issubset(
                        base_tope.separation_set(Y))]

            return Poset((els, rels), cover_relations=False, facade=facade)