Beispiel #1
0
    def __classcall_private__(cls, basis, ambient=None, unitriangular=False, category=None, *args, **opts):
        r"""
        Normalize the input.

        TESTS::

            sage: from sage.modules.with_basis.subquotient import SubmoduleWithBasis
            sage: X = CombinatorialFreeModule(QQ, range(3)); x = X.basis()
            sage: Y1 = SubmoduleWithBasis((x[0]-x[1], x[1]-x[2]), X)
            sage: Y2 = SubmoduleWithBasis([x[0]-x[1], x[1]-x[2]], X)
            sage: Y1 is Y2
            True
        """
        basis = Family(basis)
        if ambient is None:
            ambient = basis.an_element().parent()
        default_category = ModulesWithBasis(ambient.category().base_ring()).Subobjects()
        category = default_category.or_subcategory(category, join=True)
        return super(SubmoduleWithBasis, cls).__classcall__(cls, basis, ambient, unitriangular, category, *args, **opts)
Beispiel #2
0
    def basis(self):
        r"""
        Return the basis of ``self``.

        EXAMPLES::

            sage: O = lie_algebras.OnsagerAlgebra(QQ)
            sage: O.basis()
            Lazy family (Onsager monomial(i))_{i in
             Disjoint union of Family (Integer Ring, Positive integers)}
        """
        from sage.rings.all import ZZ
        from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets
        from sage.sets.positive_integers import PositiveIntegers
        I = DisjointUnionEnumeratedSets([ZZ, PositiveIntegers()],
                                        keepkey=True,
                                        facade=True)
        return Family(I, self.monomial, name='Onsager monomial')
Beispiel #3
0
    def fundamental_weights(self):
        """
        Return the fundamental weights for ``self``.

        This is the dual basis to the basis of simple roots.

        The base ring must be a field.

        EXAMPLES::

            sage: W = CoxeterGroup(['A',3], implementation='reflection')
            sage: W.fundamental_weights()
            Finite family {1: (3/2, 1, 1/2), 2: (1, 2, 1), 3: (1/2, 1, 3/2)}
        """
        simple_weights = self.bilinear_form().inverse()
        I = self.index_set()
        D = {i: simple_weights[k] for k, i in enumerate(I)}
        return Family(I, D.__getitem__)
Beispiel #4
0
    def algebra_generators(self):
        r"""
        Return the generators of this algebra.

        EXAMPLES::

            sage: C = CombinatorialFreeModule(QQ, ['a','b','c'])
            sage: TA = TensorAlgebra(C)
            sage: TA.algebra_generators()
            Finite family {'a': B['a'], 'b': B['b'], 'c': B['c']}
            sage: m = SymmetricFunctions(QQ).m()
            sage: Tm = TensorAlgebra(m)
            sage: Tm.algebra_generators()
            Lazy family (generator(i))_{i in Partitions}
        """
        return Family(self._indices.indices(),
                      lambda i: self.monomial(self._indices.gen(i)),
                      name='generator')
        def _part_generators(self, positive=False):
            r"""
            Return the Lie algebra generators for the positive or
            negative half of ``self``.

            .. NOTE::

                If the positive/negative generators correspond to the
                generators with (negative) simple roots, then this method
                will find them. If they do not, then this method *must*
                be overwritten. One should also overwrite this method in
                object classes when there is a better method to obtain them.
                Furthermore, this assumes that :meth:`lie_algebra_generators`
                is a finite set.

            INPUT:

            - ``positive`` -- boolean (default: ``False``); if ``True``
              then return positive part generators, otherwise the return
              the negative part generators

            OUTPUT:

            A :func:`~sage.sets.family.Family` whose keys are the
            index set of ``self``.

            EXAMPLES::

                sage: L = LieAlgebra(QQ, cartan_type=['E',6])
                sage: list(L._part_generators(False))
                [E[-alpha[1]], E[-alpha[2]], E[-alpha[3]],
                 E[-alpha[4]], E[-alpha[5]], E[-alpha[6]]]
            """
            I = self._cartan_type.index_set()
            P = self._cartan_type.root_system().root_lattice()
            ali = P.simple_roots().inverse_family()
            if positive:
                d = {ali[g.degree()]: g for g in self.lie_algebra_generators()
                     if self._part(g) > 0}
            if not positive:
                d = {ali[-g.degree()]: g for g in self.lie_algebra_generators()
                     if self._part(g) < 0}
            from sage.sets.family import Family
            return Family(I, d.__getitem__)
Beispiel #6
0
    def _positive_roots_reflections(self):
        """
        Return a family whose keys are the positive roots
        and values are the reflections.

        EXAMPLES::

            sage: W = CoxeterGroup(['A', 2])
            sage: F = W._positive_roots_reflections()
            sage: F.keys()
            [(1, 0), (1, 1), (0, 1)]
            sage: list(F)
            [
            [-1  1]  [ 0 -1]  [ 1  0]
            [ 0  1], [-1  0], [ 1 -1]
            ]
        """
        if not self.is_finite():
            raise NotImplementedError('not available for infinite groups')

        word = self.long_element(as_word=True)
        N = len(word)

        from sage.modules.free_module import FreeModule
        simple_roots = FreeModule(self.base_ring(), self.ngens()).gens()

        refls = self.simple_reflections()
        resu = []
        d = {}
        for i in range(1, N + 1):
            segment = word[:i]
            last = segment.pop()
            ref = refls[last]
            rt = simple_roots[last - 1]
            while segment:
                last = segment.pop()
                cr = refls[last]
                ref = cr * ref * cr
                rt = refls[last] * rt
            rt.set_immutable()
            resu += [rt]
            d[rt] = ref
        from sage.sets.family import Family
        return Family(resu, lambda rt: d[rt])
Beispiel #7
0
    def reflections(self):
        """
        Return the reflections of ``self``.

        The reflections of a Coxeter group `W` are the conjugates of
        the simple reflections. They are in bijection with the positive
        roots, for given a positive root, we may have the reflection in
        the hyperplane orthogonal to it. This method returns a family
        indexed by the positive roots taking values in the reflections.
        This requires ``self`` to be a finite Weyl group.

        .. NOTE::

            Prior to :trac:`20027`, the reflections were the keys
            of the family and the values were the positive roots.

        EXAMPLES::

            sage: W = WeylGroup("B2", prefix="s")
            sage: refdict = W.reflections(); refdict
            Finite family {(1, -1): s1, (0, 1): s2, (1, 1): s2*s1*s2, (1, 0): s1*s2*s1}
            sage: [r+refdict[r].action(r) for r in refdict.keys()]
            [(0, 0), (0, 0), (0, 0), (0, 0)]

            sage: W = WeylGroup(['A',2,1], prefix="s")
            sage: W.reflections()
            Lazy family (real root to reflection(i))_{i in
                        Positive real roots of type ['A', 2, 1]}

        TESTS::

            sage: CM = CartanMatrix([[2,-6],[-1,2]])
            sage: W = WeylGroup(CM, prefix='s')
            sage: W.reflections()
            Traceback (most recent call last):
            ...
            NotImplementedError: only implemented for finite and affine Cartan types
        """
        prr = self.domain().positive_real_roots()
        def to_elt(alp):
            ref = self.domain().reflection(alp)
            m = Matrix([ref(x).to_vector() for x in self.domain().basis()])
            return self(m.transpose())
        return Family(prr, to_elt, name="real root to reflection")
Beispiel #8
0
    def cells(self):
        """
        Return the cells of ``self``.

        EXAMPLES::

            sage: from sage.categories.cw_complexes import CWComplexes
            sage: X = CWComplexes().example()
            sage: C = X.cells()
            sage: sorted((d, C[d]) for d in C.keys())
            [(0, (0-cell v,)),
             (1, (0-cell e1, 0-cell e2)),
             (2, (2-cell f,))]
        """
        d = {0: (self.element_class(self, 0, 'v'), )}
        d[1] = tuple(
            [self.element_class(self, 0, 'e' + str(e)) for e in self._edges])
        d[2] = (self.an_element(), )
        return Family(d)
Beispiel #9
0
        def semigroup_generators(self):
            """
            Return the generators of ``self`` as a semigroup.

            The generators of a monoid `M` as a semigroup are the generators
            of `M` as a monoid and the unit.

            EXAMPLES::

                sage: M = Monoids().free([1,2,3])
                sage: M.semigroup_generators()
                Family (1, F[1], F[2], F[3])
            """
            G = self.monoid_generators()
            from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
            if G not in FiniteEnumeratedSets():
                raise NotImplementedError("currently only implemented for finitely generated monoids")
            from sage.sets.family import Family
            return Family((self.one(),) + tuple(G))
Beispiel #10
0
    def distinguished_reflections(self):
        """
        Return the reflections of ``self``.

        EXAMPLES::

            sage: W = WeylGroup(['B',2], implementation="permutation")
            sage: W.distinguished_reflections()
            Finite family {1: (1,5)(2,4)(6,8), 2: (1,3)(2,6)(5,7),
                           3: (2,8)(3,7)(4,6), 4: (1,7)(3,5)(4,8)}
        """
        Q = self._cartan_type.root_system().root_lattice()
        pos_roots = list(Q.positive_roots())
        Phi = pos_roots + [-x for x in pos_roots]
        def build_elt(index):
            r = pos_roots[index]
            perm = [Phi.index(x.reflection(r))+1 for x in Phi]
            return self.element_class(perm, self, check=False)
        return Family(self.reflection_index_set(), lambda i: build_elt(i-1))
Beispiel #11
0
    def algebra_generators(self):
        """
        Return the algebra generators of ``self``.
        """
        M = self._indices._sets[1] # The monomials
        wt = M.one() # The identity of the monomials
        P = self._indices._sets[2] # The idemponents

        I = ['s%i'%i for i in range(1, self._d)]  # The transpositions
        I += ['x%i'%i for i in range(1, self._d+1)] # The beads
        I += list(tuple(x) for x in P) # For the idempotents
        d = {}
        for i in range(1,self._d):
            d['s%i'%i] = self.sum_of_monomials( ((i,), wt, x) for x in P )
            d['x%i'%i] = self.sum_of_monomials( ((), M.gen(i-1), x) for x in P )
        d['x%i'%self._d] = self.sum_of_monomials( ((), M.gen(self._d-1), x) for x in P )
        for x in P:
            d[tuple(x)] = self.monomial( ((), wt, x) )
        return Family(I, lambda x: d[x], name="generator map")
Beispiel #12
0
    def lie_algebra_generators(self, str_keys=False):
        r"""
        Return the Chevalley Lie algebra generators of ``self``.

        INPUT:

        - ``str_keys`` -- (default: ``False``) set to ``True`` to have the
          indices indexed by strings instead of simple (co)roots

        EXAMPLES::

            sage: L = LieAlgebra(QQ, cartan_type=['A', 1])
            sage: L.lie_algebra_generators()
            Finite family {alpha[1]: E[alpha[1]], -alpha[1]: E[-alpha[1]], alphacheck[1]: h1}
            sage: L.lie_algebra_generators(True)
            Finite family {'e1': E[alpha[1]], 'f1': E[-alpha[1]], 'h1': h1}
        """
        index_set = self._cartan_type.index_set()
        alpha = self._Q.simple_roots()
        alphacheck = self._Q.simple_coroots()
        B = self.basis()
        ret = {}

        if str_keys:
            for i in index_set:
                al = alpha[i]
                ret['e{}'.format(i)] = B[al]
                ret['f{}'.format(i)] = B[-al]
                ret['h{}'.format(i)] = B[alphacheck[i]]
            keys = (['e{}'.format(i) for i in index_set]
                    + ['f{}'.format(i) for i in index_set]
                    + ['h{}'.format(i) for i in index_set])
        else:
            for i in index_set:
                al = alpha[i]
                ret[al] = B[al]
                ret[-al] = B[-al]
                ret[alphacheck[i]] = B[alphacheck[i]]
            keys = ([alpha[i] for i in index_set]
                    + [-alpha[i] for i in index_set]
                    + [alphacheck[i] for i in index_set])

        return Family(keys, ret.__getitem__)
Beispiel #13
0
        def group_generators(self):
            """
            Return group generators for ``self``.

            This default implementation calls :meth:`gens`, for
            backward compatibility.

            EXAMPLES::

                sage: A = AlternatingGroup(4)
                sage: A.group_generators()
                Family ((2,3,4), (1,2,3))
            """
            from sage.sets.family import Family
            try:
                return Family(self.gens())
            except AttributeError:
                raise NotImplementedError(
                    "no generators are implemented for this group")
Beispiel #14
0
    def basis(self):
        """
        Return a basis of ``self``.

        EXAMPLES::

            sage: d = lie_algebras.VirasoroAlgebra(QQ)
            sage: B = d.basis(); B
            Lazy family (basis map(i))_{i in Disjoint union of
                                        Family ({'c'}, Integer Ring)}
            sage: B['c']
            c
            sage: B[3]
            d[3]
            sage: B[-15]
            d[-15]
        """
        I = DisjointUnionEnumeratedSets([Set(['c']), ZZ])
        return Family(I, self.monomial, name='basis map')
Beispiel #15
0
    def basis(self):
        """
        Return a basis of ``self``.

        The basis returned begins with the unity of `R` and continues with
        the standard basis of `M`.

        EXAMPLES::

            sage: m = matrix([[0,1],[1,1]])
            sage: J = JordanAlgebra(m)
            sage: J.basis()
            Family (1 + (0, 0), 0 + (1, 0), 0 + (0, 1))
        """
        R = self.base_ring()
        ret = (self.element_class(self, R.one(), self._M.zero()), )
        ret += tuple(
            self.element_class(self, R.zero(), x) for x in self._M.basis())
        return Family(ret)
Beispiel #16
0
    def basis(self):
        r"""
        Return a basis of ``self``.

        EXAMPLES:

        A basis of a subalgebra::

            sage: sc = {('a','b'): {'c': 1}, ('a','c'): {'d': 1}}
            sage: L.<a,b,c,d> = LieAlgebra(QQ, sc)
            sage: L.subalgebra([a + b, c + d]).basis()
            Family (a + b, c, d)

        A basis of an ideal::

            sage: sc = {('x','y'): {'z': 1}, ('x','z'): {'w': 1}}
            sage: L.<x,y,z,w> = LieAlgebra(QQ, sc)
            sage: L.ideal([x + y + z + w]).basis()
            Family (w, x + y, z)
        """

        L = self.ambient()
        B = [self._to_m(X) for X in L.basis()]

        m = L.module()
        sm = m.submodule([self._to_m(X) for X in self.gens()])
        d = 0

        while sm.dimension() > d:
            d = sm.dimension()
            SB = sm.basis()
            if not self._is_ideal:
                B = SB

            brackets = [self._to_m(L.bracket(self._from_m(v), self._from_m(w)))
                        for v in B for w in SB]
            sm = m.submodule(sm.basis() + brackets)

        basis = [self.element_class(self, self._from_m(v))
                 for v in sm.echelonized_basis()]
        sortkey = lambda X: self.lift(X).leading_support(key=self._order)
        return Family(sorted(basis, key=sortkey))
Beispiel #17
0
        def simple_reflections(self):
            r"""
            Return the simple reflections `(s_i)_{i\in I}` of ``self`` as
            a family indexed by :meth:`index_set`.

            .. SEEALSO::

                - :meth:`simple_reflection`
                - :meth:`index_set`

            EXAMPLES:

            For the symmetric group, we recognize the simple transpositions::

                sage: W = SymmetricGroup(4); W
                Symmetric group of order 4! as a permutation group
                sage: s = W.simple_reflections()
                sage: s
                Finite family {1: (1,2), 2: (2,3), 3: (3,4)}
                sage: s[1]
                (1,2)
                sage: s[2]
                (2,3)
                sage: s[3]
                (3,4)

            Here are the simple reflections for a colored symmetric
            group and a reflection group::

                sage: W = ColoredPermutations(1,3)
                sage: W.simple_reflections()
                Finite family {1: [[0, 0, 0], [2, 1, 3]], 2: [[0, 0, 0], [1, 3, 2]]}

                sage: W = ReflectionGroup((1,1,3), index_set=['a','b']) # optional - gap3
                sage: W.simple_reflections()                            # optional - gap3
                Finite family {'a': (1,4)(2,3)(5,6), 'b': (1,3)(2,5)(4,6)}

            This default implementation uses :meth:`.index_set` and
            :meth:`.simple_reflection`.
            """
            from sage.sets.family import Family
            return Family(self.index_set(), self.simple_reflection)
Beispiel #18
0
    def __init__(self, modules, **options):
        CombinatorialFreeModule.Tensor.__init__(self, modules, **options)
        # with sage 5.7.beta4 the basis has the wrong category
        if False:
            try:
                from sage.sets.family import Family

                cc = list(self.basis().keys()).cc  # the CartesianProduct
                self._indices = Family(cc, lambda u: tuple(u))

                def contains(self, x):
                    return x in cc

                import types

                self._indices._contains_ = types.MethodType(contains, self.indices())
                self.basis.clear_cache()
            except AttributeError:
                pass
        self._fix_basis_tests()
Beispiel #19
0
    def basis(self):
        """
        Return a basis of ``self``.

        EXAMPLES::

            sage: W.<x,y> = DifferentialWeylAlgebra(QQ)
            sage: B = W.basis()
            sage: it = iter(B)
            sage: [it.next() for i in range(20)]
            [1, x, y, dx, dy, x^2, x*y, x*dx, x*dy, y^2, y*dx, y*dy,
             dx^2, dx*dy, dy^2, x^3, x^2*y, x^2*dx, x^2*dy, x*y^2]
        """
        n = self._n
        I = IntegerListsLex(NonNegativeIntegers(), length=n * 2)
        one = self.base_ring().one()
        f = lambda x: self.element_class(self, {
            (tuple(x[:n]), tuple(x[n:])): one
        })
        return Family(I, f, name="basis map")
Beispiel #20
0
    def alpha(self):
        r"""
        Returns the family `(\alpha_i)_{i\in I}` of the simple roots,
        with the extra feature that, for simple irreducible root
        systems, `\alpha_0` yields the opposite of the highest root.

        EXAMPLES::
        
            sage: alpha = RootSystem(["A",2]).root_lattice().alpha()
            sage: alpha[1]
            alpha[1]
            sage: alpha[0]
            -alpha[1] - alpha[2]

        """
        if self.root_system.is_finite() and self.root_system.is_irreducible():
            return Family(self.index_set(), self.simple_root, \
                          hidden_keys = [0], hidden_function = lambda i: - self.highest_root())
        else:
            return self.simple_roots()
Beispiel #21
0
    def basis(self):
        """
        Return a basis of ``self``.

        EXAMPLES::

            sage: from sage.geometry.linear_expression import LinearExpressionModule
            sage: L = LinearExpressionModule(QQ, ('x', 'y', 'z'))
            sage: list(L.basis())
            [x + 0*y + 0*z + 0,
             0*x + y + 0*z + 0,
             0*x + 0*y + z + 0,
             0*x + 0*y + 0*z + 1]
        """
        from sage.sets.family import Family
        gens = self.gens()
        d = {i: g for i, g in enumerate(gens)}
        d['b'] = self.element_class(self, self.ambient_module().zero(),
                                    self.base_ring().one())
        return Family(list(range(len(gens))) + ['b'], lambda i: d[i])
Beispiel #22
0
    def algebra_generators(self):
        r"""
        Return the generators of this algebra.

        These are the rooted trees with just one vertex.

        EXAMPLES::

            sage: A = algebras.FreePreLie(ZZ, 'fgh'); A
            Free PreLie algebra on 3 generators ['f', 'g', 'h']
             over Integer Ring
            sage: list(A.algebra_generators())
            [B[f[]], B[g[]], B[h[]]]

            sage: A = algebras.FreePreLie(QQ, ['x1','x2'])
            sage: list(A.algebra_generators())
            [B[x1[]], B[x2[]]]
        """
        Trees = self.basis().keys()
        return Family(self._alphabet, lambda a: self.monomial(Trees([], a)))
Beispiel #23
0
            def algebra_generators(self):
                r"""
                Return generators of this group algebra (as an algebra).

                EXAMPLES::

                    sage: GroupAlgebras(QQ).example(AlternatingGroup(10)).algebra_generators()
                    Finite family {(1,2,3,4,5,6,7,8,9): B[(1,2,3,4,5,6,7,8,9)], (8,9,10): B[(8,9,10)]}

                .. NOTE::

                    This function is overloaded for SymmetricGroupAlgebras
                    to return Permutations and not Elements of the
                    symmetric group::

                        sage: GroupAlgebras(QQ).example(SymmetricGroup(10)).algebra_generators()
                        [[2, 1, 3, 4, 5, 6, 7, 8, 9, 10], [2, 3, 4, 5, 6, 7, 8, 9, 10, 1]]
                """
                from sage.sets.family import Family
                return Family(self.group().gens(), self.term)
    def gens(self):
        """
        Return a family of generators of ``self``.

        OUTPUT:

        - a :class:`~sage.sets.family.Family`, indexed by the positive
          integers, whose `n`-th element is ``self.gen(n)``.

        EXAMPLES::

            sage: from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField
            sage: F = AlgebraicClosureFiniteField(GF(5), 'z')
            sage: g = F.gens(); g
            Lazy family (...(i))_{i in Positive integers}
            sage: g[3]
            z3
        """
        from sage.sets.family import Family
        from sage.sets.positive_integers import PositiveIntegers
        return Family(PositiveIntegers(), self.gen)
Beispiel #25
0
    def example(self):
        """
        EXAMPLES::

            sage: M = Semigroups().SetsWithAction().example()
            sage: TestSuite(M).run(skip = ["_test_pickling"])

        """
        from sage.monoids.representations import SetWithAction
        from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
        from sage.sets.finite_set_maps import FiniteSetMaps
        from sage.combinat.automatic_monoid import AutomaticMonoid
        from sage.sets.family import Family
        from sage.combinat.j_trivial_monoids import SubFiniteMonoidsOfFunctions

        Z = IntegerModRing(10)
        ambient = FiniteSetMaps(Z)
        S = AutomaticMonoid(Family({2: ambient(lambda x: 2*x), 3: ambient(lambda x: 3*x) }), category=SubFiniteMonoidsOfFunctions())
        M = SetWithAction(S, Z, action = lambda f,m: f(m))
        M.rename("Representation of the monoid generated by <2,3> acting on Z/10 Z by multiplication")
        return M
Beispiel #26
0
    def algebra_generators(self):
        r"""
        Return the algebra generators of ``self``.

        EXAMPLES::

            sage: AW = algebras.AskeyWilson(QQ)
            sage: G = AW.algebra_generators()
            sage: G['A']
            A
            sage: G['a']
            a
            sage: list(G)
            [A, B, C, a, b, g]
        """
        A = self.variable_names()
        def build_monomial(g):
            exp = [0] * 6
            exp[A.index(g)] = 1
            return self.monomial(self._indices(exp))
        return Family(A, build_monomial)
Beispiel #27
0
    def algebra_generators(self):
        """
        Return the algebra generators of ``self``.

        EXAMPLES::

            sage: Y = algebras.YokonumaHecke(5, 3)
            sage: dict(Y.algebra_generators())
            {'g1': g[1], 'g2': g[2], 't1': t1, 't2': t2, 't3': t3}
        """
        one = self._Pn.one()
        zero = [0] * self._n
        d = {}
        for i in range(self._n):
            r = list(zero)  # Make a copy
            r[i] = 1
            d['t%s' % (i + 1)] = self.monomial((tuple(r), one))
        G = self._Pn.group_generators()
        for i in range(1, self._n):
            d['g%s' % i] = self.monomial((tuple(zero), G[i]))
        return Family(sorted(d), lambda i: d[i])
Beispiel #28
0
    def basis(self):
        """
        Return the basis of ``self``.

        EXAMPLES::

            sage: L = lie_algebras.Heisenberg(QQ, oo)
            sage: L.basis()
            Lazy family (basis map(i))_{i in Disjoint union of Family ({'z'},
             The Cartesian product of (Positive integers, {'p', 'q'}))}
            sage: L.basis()['z']
            z
            sage: L.basis()[(12, 'p')]
            p12
        """
        S = cartesian_product([PositiveIntegers(), ['p','q']])
        I = DisjointUnionEnumeratedSets([Set(['z']), S])
        def basis_elt(x):
            if isinstance(x, str):
                return self.monomial(x)
            return self.monomial(x[1] + str(x[0]))
        return Family(I, basis_elt, name="basis map")
Beispiel #29
0
def IntegerListsNN(**kwds):
    """
    Lists of nonnegative integers with constraints.

    This function returns the union of ``IntegerListsLex(n, **kwds)``
    where `n` ranges over all nonnegative integers.

    EXAMPLES::

        sage: from sage.combinat.integer_lists.nn import IntegerListsNN
        sage: L = IntegerListsNN(max_length=3, max_slope=-1)
        sage: L
        Disjoint union of Lazy family (<lambda>(i))_{i in Non negative integer semiring}
        sage: it = iter(L)
        sage: for _ in range(20):
        ....:     print(next(it))
        []
        [1]
        [2]
        [3]
        [2, 1]
        [4]
        [3, 1]
        [5]
        [4, 1]
        [3, 2]
        [6]
        [5, 1]
        [4, 2]
        [3, 2, 1]
        [7]
        [6, 1]
        [5, 2]
        [4, 3]
        [4, 2, 1]
        [8]
    """
    return DisjointUnionEnumeratedSets(
        Family(NN, lambda i: IntegerListsLex(i, **kwds)))
Beispiel #30
0
    def __init__(self, poset):
        self.poset = poset
        support = poset.list()
        ambient_monoid = FiniteSetMaps(support, action="right")

        def genij(ij):
            (i, j) = ij
            return ambient_monoid.from_dict(
                {k: i if k == j else k
                 for k in support})

        index = map(tuple,
                    poset.cover_relations())  # index elems must be hashable
        self.pi = Family(index, genij)
        category = Monoids().JTrivial().Finite() & Monoids().Transformation(
        ).Subobjects()
        AutomaticMonoid.__init__(self,
                                 self.pi,
                                 ambient_monoid,
                                 one=ambient_monoid.one(),
                                 mul=operator.mul,
                                 category=category)
Beispiel #31
0
    def basis(self):
        """
        Return a basis of ``self``.

        EXAMPLES::

            sage: W.<x,y> = DifferentialWeylAlgebra(QQ)
            sage: B = W.basis()
            sage: it = iter(B)
            sage: [next(it) for i in range(20)]
            [1, x, y, dx, dy, x^2, x*y, x*dx, x*dy, y^2, y*dx, y*dy,
             dx^2, dx*dy, dy^2, x^3, x^2*y, x^2*dx, x^2*dy, x*y^2]
        """
        n = self._n
        # TODO in #17927: use IntegerVectors(length=2*n)
        from sage.combinat.integer_list import IntegerListsNN
        I = IntegerListsNN(length=n * 2)
        one = self.base_ring().one()
        f = lambda x: self.element_class(self, {
            (tuple(x[:n]), tuple(x[n:])): one
        })
        return Family(I, f, name="basis map")
    def __init__(self, monoid, generators=None):
        r"""
        EXAMPLES::

            sage: from sage_semigroups.monoids.karnofsky_rhodes_expansion import KarnofskyRhodesExpansion
            sage: from sage_semigroups.monoids.free_left_regular_band import FreeLeftRegularBand
            sage: F = FreeLeftRegularBand(2); F
            Free left regular band generated by ('a', 'b')
            sage: K = KarnofskyRhodesExpansion(F); K
            Karnofsky-Rhodes expansion of Free left regular band generated by ('a', 'b')
            sage: TestSuite(K).run()

        """
        self._underlying_monoid = monoid
        if generators is None:
            generators = monoid.semigroup_generators()
        self._words = Words(generators)
        self._underlying_monoid_generators = Family(generators)
        Parent.__init__(self, category=Monoids().Finite().FinitelyGenerated())
        self._representatives = {self._canonicalize(self.one()): self.one()}

        # TODO: do we really want to do this?!
        # force the generation of all the elements
        self.list()
class KarnofskyRhodesExpansion(UniqueRepresentation, Parent):
    def __init__(self, monoid, generators=None):
        r"""
        EXAMPLES::

            sage: from sage_semigroups.monoids.karnofsky_rhodes_expansion import KarnofskyRhodesExpansion
            sage: from sage_semigroups.monoids.free_left_regular_band import FreeLeftRegularBand
            sage: F = FreeLeftRegularBand(2); F
            Free left regular band generated by ('a', 'b')
            sage: K = KarnofskyRhodesExpansion(F); K
            Karnofsky-Rhodes expansion of Free left regular band generated by ('a', 'b')
            sage: TestSuite(K).run()

        """
        self._underlying_monoid = monoid
        if generators is None:
            generators = monoid.semigroup_generators()
        self._words = Words(generators)
        self._underlying_monoid_generators = Family(generators)
        Parent.__init__(self, category=Monoids().Finite().FinitelyGenerated())
        self._representatives = {self._canonicalize(self.one()): self.one()}

        # TODO: do we really want to do this?!
        # force the generation of all the elements
        self.list()

    def succ_generators(self, side="twosided"):
        def fcn(x):
            pgens = []
            if side == "right"  or side == "twosided":
                pgens += [self(x.value * g.value) for g in self.semigroup_generators()]
            if side == "left" or side == "twosided":
                pgens += [self(g.value * x.value) for g in self.semigroup_generators()]
            gens = []
            for gen in pgens:
                mT = self._canonicalize(gen)
                if mT not in self._representatives:
                    gens.append(gen)
                    self._representatives[mT] = gen
                elif self._representatives[mT] == gen:
                    gens.append(gen)
            return gens
        return fcn

    def _repr_(self):
        return "Karnofsky-Rhodes expansion of %s"%(self._underlying_monoid,)

    @cached_method
    def one(self):
        return self(self._words())

    def _canonicalize(self,x):
        m = self.projection(x)
        T = self.path_transition_edges(x)
        return (m,T)

    def representative(self, x):
        return self._representatives[self._canonicalize(x)]

    def product(self, x, y):
        return self.representative(self(x.value * y.value))
        return self.representative(self.representative(x).value * self.representative(y).value)

    def semigroup_generators(self):
        return Family([self(self._words((i,))) for i in self._underlying_monoid_generators])

    def an_element(self):
        return self.one()

    @lazy_attribute
    def _underlying_monoid_cayley_graph(self):
        return self._underlying_monoid.cayley_graph(side="right",
                generators=self._underlying_monoid_generators)

    @lazy_attribute
    def _transition_edges(self):
        G = self._underlying_monoid_cayley_graph
        d = {}
        for (i,C) in enumerate(G.strongly_connected_components()):
            for v in C:
                d[v] = i
        transition_edges = Set([(a,b,l) for (a,b,l) in G.edges() if d[a] != d[b]])
        return transition_edges

    def projection(self, w):
        return self._underlying_monoid.prod(w.value)

    @lazy_attribute
    def _transition_dictionary(self):
        t = {}
        for (u,v,l) in self._underlying_monoid_cayley_graph.edge_iterator():
            t[u, l] = v
        return t

    def _read_path(self, w):
        t = self._transition_dictionary
        i = self._underlying_monoid_generators.inverse_family()
        v = self._underlying_monoid.one()
        path = []
        for a in w.value:
            w = t[v,i[a]]
            path.append((v,w,i[a]))
            v = w
        return path

    def path_transition_edges(self, w):
        tedges = self._transition_edges
        output = []
        for (a,b,l) in self._read_path(w):
            if (a,b,l) in tedges:
                output.append((a,b,l))
        return Set(output)

    def are_equivalent(self, u, v):
        assert u in self
        assert v in self
        return self.projection(u) == self.projection(v) and \
                    self.path_transition_edges(u) == self.path_transition_edges(v)

    def __iter__(self):
        from sage.combinat.backtrack import TransitiveIdeal
        return TransitiveIdeal(self.succ_generators(side = "right"), [self.one()]).__iter__()

    class Element (ElementWrapper):
        wrapped_class = FiniteWord_class
        __lt__ = ElementWrapper._lt_by_value

        def _eq_(self, other):
            return self.parent().are_equivalent(self, other)
Beispiel #34
0
    def __init__(self, *args):
        r"""
        The constructor either acts as a copy constructor for a finite surface, or you can pass two options:
        polygons and identifications.
        
        INPUT:

        - ``polygons`` - a family of polygons (might be a list, a dictionnary
          label -> polygon or more generally a Family)

        - ``identifications`` - the identification of the edges. A list of pairs
          ((p0,e0),(p1,e1)).
        """
        if len(args)==2:
            polygons=args[0]
            identifications=args[1]

            self._polygons = Family(polygons)

            if self._polygons.cardinality() == 0:
                raise ValueError("there should be at least one polygon")

            self._field = self._polygons.an_element().parent().field()

            n = 0
            for p in self._polygons:
                if p.parent().field() != self._field:
                    raise ValueError("the field must be the same for all polygons")
                n += 1
                if n > 10:  # the number of polygons may be infinite...
                    break

            if isinstance(identifications, (list,dict)):
                edge_identifications = {}
                if isinstance(identifications, dict):
                    it = identifications.iteritems()
                else:
                    it = iter(identifications)
                for e0,e1 in it:
                    edge_identifications[e0] = e1
                    # Check that e0 makes sense. 
                    assert e0[1]>=0 and e0[1]<self._polygons[e0[0]].num_edges()
                    # Check that e1 makes sense. 
                    assert e1[1]>=0 and e1[1]<self._polygons[e1[0]].num_edges()
                    
                    if e1 in edge_identifications:
                        assert edge_identifications[e1] == e0
                    else:
                        edge_identifications[e1] = e0
            else:
                edge_identifications = identifications

            self._edge_identifications = edge_identifications
        elif len(args)==1:
            # Copy constructor for finite surface.
            s = args[0]
            if not s.is_finite():
                raise ValueError("Can only copy finite surface.")
            polygons = {}
            edge_identifications = {}
            for label,polygon in s.label_polygon_iterator():
                polygons[label]=polygon
                for edge in xrange(polygon.num_edges()):
                    edge_identifications[(label,edge)]=s.opposite_edge(label,edge)
            self._field = s.base_ring()
            self._polygons=Family(polygons)
            self._edge_identifications = edge_identifications
        else:
            raise ValueError("Can only be called with one or two arguments.")
Beispiel #35
0
class Surface_polygons_and_gluings(Surface):
    r"""
    Similarity surface build from a list of polygons and gluings.
    """
    def __init__(self, *args):
        r"""
        The constructor either acts as a copy constructor for a finite surface, or you can pass two options:
        polygons and identifications.
        
        INPUT:

        - ``polygons`` - a family of polygons (might be a list, a dictionnary
          label -> polygon or more generally a Family)

        - ``identifications`` - the identification of the edges. A list of pairs
          ((p0,e0),(p1,e1)).
        """
        if len(args)==2:
            polygons=args[0]
            identifications=args[1]

            self._polygons = Family(polygons)

            if self._polygons.cardinality() == 0:
                raise ValueError("there should be at least one polygon")

            self._field = self._polygons.an_element().parent().field()

            n = 0
            for p in self._polygons:
                if p.parent().field() != self._field:
                    raise ValueError("the field must be the same for all polygons")
                n += 1
                if n > 10:  # the number of polygons may be infinite...
                    break

            if isinstance(identifications, (list,dict)):
                edge_identifications = {}
                if isinstance(identifications, dict):
                    it = identifications.iteritems()
                else:
                    it = iter(identifications)
                for e0,e1 in it:
                    edge_identifications[e0] = e1
                    # Check that e0 makes sense. 
                    assert e0[1]>=0 and e0[1]<self._polygons[e0[0]].num_edges()
                    # Check that e1 makes sense. 
                    assert e1[1]>=0 and e1[1]<self._polygons[e1[0]].num_edges()
                    
                    if e1 in edge_identifications:
                        assert edge_identifications[e1] == e0
                    else:
                        edge_identifications[e1] = e0
            else:
                edge_identifications = identifications

            self._edge_identifications = edge_identifications
        elif len(args)==1:
            # Copy constructor for finite surface.
            s = args[0]
            if not s.is_finite():
                raise ValueError("Can only copy finite surface.")
            polygons = {}
            edge_identifications = {}
            for label,polygon in s.label_polygon_iterator():
                polygons[label]=polygon
                for edge in xrange(polygon.num_edges()):
                    edge_identifications[(label,edge)]=s.opposite_edge(label,edge)
            self._field = s.base_ring()
            self._polygons=Family(polygons)
            self._edge_identifications = edge_identifications
        else:
            raise ValueError("Can only be called with one or two arguments.")
        
        # display everything by default
        # I don't think we should be doing this by default whenever we create
        # a surface. -Pat
        #adj = []
        #todo = [self.base_label()]
        #labs = set(self.polygon_labels())
        #labs.remove(self.base_label())
        #while todo:
        #    p1 = todo.pop()
        #    for e1 in range(self.polygon(p1).num_edges()):
        #        p2,e2 = self.opposite_edge(p1,e1)
        #        if p2 in labs:
        #            labs.remove(p2)
        #            adj.append((p1,e1))
        #self._plot_options = {'adjacencies': adj}

    def is_finite(self):
        r"""
        Return whether or not the surface is finite.
        """
        from sage.rings.infinity import Infinity
        return self._polygons.cardinality() != Infinity
    
    def base_ring(self):
        return self._field

    def polygon_labels(self):
        from sage.combinat.words.alphabet import build_alphabet
        return build_alphabet(self._polygons.keys())

    def base_label(self):
        return self.polygon_labels().an_element()

    def polygon(self, lab):
        r"""
        Return the polygon with label ``lab``.
        """
        return self._polygons[lab]

    def opposite_edge(self, p, e):
        if (p,e) not in self._edge_identifications:
            e = e % self._polygons[p].num_edges()
            if (p,e) not in self._edge_identifications:
                raise ValueError("The pair"+str((p,e))+" is not a valid edge identifier.")
        return self._edge_identifications[(p,e)]
Beispiel #36
0
    def __classcall_private__(cls, generators, ambient=None, one=None, mul=operator.mul, category=None):
        """
        Parse and straighten the arguments; figure out the category.

        TESTS::

            sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
            sage: R = IntegerModRing(9)
            sage: M = AutomaticSemigroup((), one=R.one())
            sage: M.ambient() == R
            True
            sage: AutomaticSemigroup((0,)).category()
            Join of Category of finitely generated semigroups and Category of subquotients of semigroups and Category of commutative magmas and Category of subobjects of sets
            sage: AutomaticSemigroup((0,), one=1).category()
            Join of Category of subquotients of monoids and
            Category of commutative monoids and
            Category of finitely generated semigroups and
            Category of subobjects of sets
            sage: AutomaticSemigroup((0,), one=0).category()
            Join of Category of commutative monoids and
            Category of finitely generated semigroups and
            Category of subquotients of semigroups and
            Category of subobjects of sets
            sage: AutomaticSemigroup((0,), mul=operator.add).category()
            Join of Category of semigroups and Category of subobjects of sets
            sage: AutomaticSemigroup((0,), one=0, mul=operator.add).category()
            Join of Category of monoids and Category of subobjects of sets

            sage: S5 = SymmetricGroup(5)
            sage: AutomaticSemigroup([S5((1,2))]).category()
            Join of Category of finite groups and
            Category of subquotients of monoids and
            Category of finite finitely generated semigroups and
            Category of subquotients of finite sets and
            Category of subobjects of sets

        .. TODO::

            One would want a subsemigroup of a group to be
            automatically a subgroup (in ``Groups().Subobjects()``).
        """
        generators = Family(generators)
        if ambient is None:
            # Try to guess the ambient semigroup from the generators or the unit
            if generators.cardinality() > 0:
                ambient = generators.first().parent()
            elif one is not None:
                ambient = one.parent()
            else:
                raise ValueError(
                    "AutomaticSemigroup requires at least one generator or `one` to determine the ambient space"
                )
        elif ambient not in Sets:
            raise ValueError("ambient (=%s) should be a set" % ambient)

        # if mul is not operator.mul  and category.is_subcategory(Monoids().Subobjects())  error

        if one is None and category is not None:
            if category.is_subcategory(Monoids().Subobjects()):
                one = ambient.one()
            elif category.is_subcategory(Monoids()):
                raise ValueError("For a monoid which is just a subsemigroup, the unit should be specified")

        # Try to determine the most specific category
        # This logic should be in the categories
        if mul is operator.mul:
            default_category = Semigroups().FinitelyGenerated()
            if one is not None and one == ambient.one():
                default_category = default_category.Unital()
            if ambient in Semigroups().Commutative():
                default_category = default_category.Commutative()
            if ambient in Groups().Finite():
                default_category = default_category & Groups()
        else:
            default_category = Sets()

        if ambient in Sets().Finite():
            default_category = default_category.Finite()

        default_category = default_category.Subobjects() & Semigroups()
        if one is not None:
            default_category = default_category.Unital()
            cls = AutomaticMonoid

        if category is None:
            category = default_category
        else:
            category = default_category & category
        return super(AutomaticSemigroup, cls).__classcall__(
            cls, generators, ambient=ambient, one=one, mul=mul, category=category
        )