示例#1
0
        class Algebras(AlgebrasCategory):
            extra_super_categories = raw_getattr(Groups.Finite.Algebras,
                                                 "extra_super_categories")

            class ParentMethods:
                __init_extra__ = raw_getattr(
                    Groups.Finite.Algebras.ParentMethods, "__init_extra__")
示例#2
0
文件: magmas.py 项目: timgates42/sage
        def __init_extra__(self):
            """
                sage: S = Semigroups().example("free")
                sage: S('a') * S('b') # indirect doctest
                'ab'
                sage: S('a').__class__._mul_ == S('a').__class__._mul_parent
                True

            """
            # This should instead register the multiplication to the coercion model
            # But this is not yet implemented in the coercion model
            #
            # Trac ticket #11900: The following used to test whether
            # self.product != self.product_from_element_class_mul. But
            # that is, of course, a bug. Namely otherwise, if the parent
            # has an optimized `product` then its elements will *always* use
            # a slow generic `_mul_`.
            #
            # So, in addition, it should be tested whether the element class exists
            # *and* has a custom _mul_, because in this case it must not be overridden.

            if (self.product.__func__ ==
                    self.product_from_element_class_mul.__func__):
                return
            if not (hasattr(self, "element_class")
                    and hasattr(self.element_class, "_mul_parent")):
                return

            E = self.element_class
            E_mul_func = raw_getattr(E, '_mul_')
            if not isinstance(E_mul_func, AbstractMethod):
                C = self.category().element_class
                try:
                    C_mul_func = raw_getattr(C, '_mul_')
                except AttributeError:  # Doesn't have _mul_
                    return

                if isinstance(C_mul_func, AbstractMethod):
                    return

                if E_mul_func is C_mul_func:
                    # self.product is custom, thus, we rely on it
                    E._mul_ = E._mul_parent
            else:  # E._mul_ has so far been abstract
                E._mul_ = E._mul_parent
示例#3
0
文件: magmas.py 项目: sagemath/sage
        def __init_extra__(self):
            """
                sage: S = Semigroups().example("free")
                sage: S('a') * S('b') # indirect doctest
                'ab'
                sage: S('a').__class__._mul_ == S('a').__class__._mul_parent
                True

            """
            # This should instead register the multiplication to the coercion model
            # But this is not yet implemented in the coercion model
            #
            # Trac ticket #11900: The following used to test whether
            # self.product != self.product_from_element_class_mul. But
            # that is, of course, a bug. Namely otherwise, if the parent
            # has an optimized `product` then its elements will *always* use
            # a slow generic `_mul_`.
            #
            # So, in addition, it should be tested whether the element class exists
            # *and* has a custom _mul_, because in this case it must not be overridden.

            if (self.product.__func__ == self.product_from_element_class_mul.__func__):
                return
            if not (hasattr(self, "element_class") and hasattr(self.element_class, "_mul_parent")):
                return

            E = self.element_class
            E_mul_func = raw_getattr(E, '_mul_')
            if not isinstance(E_mul_func, AbstractMethod):
                C = self.category().element_class
                try:
                    C_mul_func = raw_getattr(C, '_mul_')
                except AttributeError:  # Doesn't have _mul_
                    return

                if isinstance(C_mul_func, AbstractMethod):
                    return

                if E_mul_func is C_mul_func:
                    # self.product is custom, thus, we rely on it
                    E._mul_ = E._mul_parent
            else: # E._mul_ has so far been abstract
                E._mul_ = E._mul_parent
示例#4
0
class AutomaticMonoid(AutomaticSemigroup):
    def one(self):
        """
        Return the unit of ``self``.

        EXAMPLES::

            sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
            sage: R = IntegerModRing(21)
            sage: M = R.submonoid(())
            sage: M.one()
            1
            sage: M.one().parent() is M
            True
        """
        return self._one

    # This method takes the monoid generators and adds the unit
    semigroup_generators = raw_getattr(Monoids.ParentMethods,
                                       "semigroup_generators")

    def monoid_generators(self):
        """
        Return the family of monoid generators of ``self``.

        EXAMPLES::

            sage: from sage.monoids.automatic_semigroup import AutomaticSemigroup
            sage: R = IntegerModRing(28)
            sage: M = R.submonoid(Family({1: R(3), 2: R(5)}))
            sage: M.monoid_generators()
            Finite family {1: 3, 2: 5}

        Note that the monoid generators do not include the unit,
        unlike the semigroup generators::

            sage: M.semigroup_generators()
            Family (1, 3, 5)
        """
        return self._generators

    gens = monoid_generators
示例#5
0
    class Algebras(AlgebrasCategory):
        """
        EXAMPLES::

        Oops, the pretty printing is broken (the `s` is not removed properly)

            sage: Semigroups().SetsWithAction().Algebras(QQ)
            Category of sets endowed with an action of a semigrou algebras over Rational Field
            sage: Semigroups().SetsWithAction().Algebras(QQ)   # todo: not implemented
            Category of sets endowed with an action of a semigrou algebras over Rational Field
        """

        # see the warning in sage.categories.set_with_action_functor.SetsWithActionCategory._algebras_extra_super_categories
        extra_super_categories = raw_getattr(SetsWithActionCategory, "_algebras_extra_super_categories")

        class ParentMethods:

            def semigroup(self):
                """
                EXAMPLES::

                    sage: M = Semigroups().SetsWithAction().example().algebra(QQ)
                    sage: S = M.semigroup()
                """
                return self.basis().keys().semigroup()

            def action(self, s, x):
                """
                Return the action of ``s`` on ``x``.

                It is obtained by extending by linearity the action of
                ``s`` on the basis.

                INPUT:
                - ``x`` -- an element of ``self``
                - ``s`` -- an element of the semigroup acting on ``self``

                EXAMPLES::

                    sage: M = Semigroups().SetsWithAction().example().algebra(QQ); M
                    Free module generated by Representation of the monoid generated by <2,3> acting on Z/10 Z by multiplication over Rational Field
                    sage: S = M.semigroup()
                    sage: f2, f3 = S.semigroup_generators()
                    sage: x = M.an_element(); x
                    2*B[0] + 2*B[1] + 3*B[2]
                    sage: M.action(f2, x)
                    2*B[0] + 2*B[2] + 3*B[4]
                """
                action = self.basis().keys().action
                return x.map_support_skip_none(functools.partial(action, s))

            @cached_method
            def side(self):
                """
                Returns on which side the action occurs

                EXAMPLES::

                    sage: M = Semigroups().Finite().example()
                    sage: M.regular_representation(side='left').side()
                    'left'
                    sage: M.regular_representation(side='right').side()
                    'right'
                    sage: M.regular_representation(side="left").side.__module__
                    'sage.categories.sets_with_action'
                """
                return self.basis().keys().side()

            def character_of(self, s):
                """
                Return the trace of `s` as a linear morphism acting on ``self``

                INPUT:
                - `s` -- an element of the semigroup acting on ``self``

                EXAMPLES::

                    sage: S = AperiodicMonoids().Finite().example(3); S
                    The finite H-trivial monoid of order preserving maps on {1, .., 3}
                    sage: A = S.lr_regular_class_module(1, side="left")
                    sage: pi = S.monoid_generators()
                    sage: pi
                    Finite family {1: 113, 2: 122, -2: 133, -1: 223}
                    sage: A.character_of(S.one())
                    3
                    sage: A.character_of(pi[1])
                    1

                .. seealso: :meth:`Semigroups.SetsWithAction.ParentMethods.nr_fixed_points`
                """
                return self.basis().keys().nr_fixed_points(s)


            ########################################################################
            # EXPERIMENTAL, MOSTLY FOR H-TRIVIAL AND PROBABLY NOW USELESS
            ########################################################################

            def annihilator_with_apex(self, J):
                """
                INPUT:

                 - ``J`` -- the index of a regular J-class

                Let `A` be the set of all the elements of the
                semigroup which are not below `J` in `J`-order. This
                returns `Ann(self, A)`.
                """
                S = self.semigroup()
                P = S.j_poset_on_regular_classes()
                A = set(P).difference(P.principal_order_filter(J))
                # It is sufficient to take the generators of the highest J-classes in A
                A = P.order_ideal_generators(A)
                A = [x for I in A for x in S.regular_j_class_semigroup_generators(I)]
                return self.annihilator_of_subsemigroup(A)

            @cached_method
            def annihilator_module_with_apex(self, J):
                """
                INPUT:

                 - ``J`` -- the index of a regular J-class

                This attempts to construct a submodule of `self` with
                apex `J`. To this hand, this constructs the
                annihilator with apex `J` (see
                :meth:`annihilator_with_apex`), and checks whether it
                is indeed a submodule, and that its apex is `J`.

                If not, `None` is returned.

                EXAMPLES::

                    sage: M = Semigroups().SetsWithAction().example().algebra(QQ); M
                    Free module generated by Representation of the monoid generated by <2,3> acting on Z/10 Z by multiplication over Rational Field
                    sage: S = M.semigroup()

                This semigroup has two regular `J`-classes, with that
                indexed by `1` being smaller than that indexed by `0`
                (no luck in the random indexing chosen by Sage)::

                    sage: S.j_poset_on_regular_classes().cover_relations()
                    [[1, 0]]

                To those `J`-classes correspond two submodules of M::

                    sage: M.annihilator_module_with_apex(0)
                    Vector space of degree 10 and dimension 5 over Rational Field
                    Basis matrix:
                    [ 1  0  0  0  0 -1  0  0  0  0]
                    [ 0  1  0  0  0  0 -1  0  0  0]
                    [ 0  0  1  0  0  0  0 -1  0  0]
                    [ 0  0  0  1  0  0  0  0 -1  0]
                    [ 0  0  0  0  1  0  0  0  0 -1]

                    sage: M.annihilator_module_with_apex(1)
                    Vector space of degree 10 and dimension 10 over Rational Field
                    Basis matrix:
                    [1 0 0 0 0 0 0 0 0 0]
                    [0 1 0 0 0 0 0 0 0 0]
                    [0 0 1 0 0 0 0 0 0 0]
                    [0 0 0 1 0 0 0 0 0 0]
                    [0 0 0 0 1 0 0 0 0 0]
                    [0 0 0 0 0 1 0 0 0 0]
                    [0 0 0 0 0 0 1 0 0 0]
                    [0 0 0 0 0 0 0 1 0 0]
                    [0 0 0 0 0 0 0 0 1 0]
                    [0 0 0 0 0 0 0 0 0 1]

                    sage: M.annihilator_module_with_apex(0).apex()
                    0
                    sage: M.annihilator_module_with_apex(1).apex()
                    1

                We conclude with a case where the construction
                fails. Consider the right class module of the BiHecke
                Monoid of type A_3, indexed by `2314 = s_2 s_1`:

                    sage: W = SymmetricGroup(4)
                    sage: S = BiHeckeMonoid(W); S
                    bi-Hecke monoid of Symmetric group of order 4! as a permutation group
                    sage: w = W([2,3,1,4])
                    sage: R = S.lr_regular_class_module(w, side='right')
                    sage: list(f(W.one()) for f in R.basis().keys())
                    [(2,3), (1,2,3), ()]

                In this case, the construction fails::

                    sage: R.annihilator_module_with_apex(W([2,1,3,4]))   # long time
                    sage: R.annihilator_module_with_apex(W([1,3,2,4]))   # long time

                Indeed, the annihilator subspaces (which are
                respectively the kernels of pi_2 and pi_1) are not
                submodules::

                    sage: R.annihilator_with_apex(W([2,1,3,4]))
                    Vector space of degree 3 and dimension 2 over Rational Field
                    Basis matrix:
                    [ 1 -1  0]
                    [ 0  0  1]
                    sage: R.annihilator_with_apex(W([1,3,2,4]))
                    Vector space of degree 3 and dimension 2 over Rational Field
                    Basis matrix:
                    [ 1  0 -1]
                    [ 0  1  0]

                Could the map J -> R.annihilator_module_with_apexAnn(J)
                be extended to a morphism of posets from the poset of
                regular J-classes?

                Then, the pair of maps:

                J \mapsto self.annihilator_module_with_apex(J)

                and

                A \mapsto A.apex()

                should give a Galois connection.

                """
                S = self.semigroup()
                AnnJ = self.annihilator_with_apex(J)
                # If the apex of AnnJ is not J
                if all(self.action(s, self.from_vector(x)).is_zero()
                       for x in AnnJ.basis()
                       for s in S.regular_j_class_semigroup_generators(J)):
                    return None
                # If AnnJ is a submodule
                if any(self.action(s, self.from_vector(x)).to_vector() not in AnnJ
                       for x in AnnJ.basis()
                       for s in S.semigroup_generators()):
                    return None
                # Problem: make sure that the subspace AnnJ is private to self
                assert not hasattr(AnnJ, 'apex')
                AnnJ.apex = ConstantFunction(J)
                return AnnJ

            @cached_method
            def composition_series(self):
                """
                The (multiplicity-free) composition series of this module.

                This returns the set of (index of) `J`-classes `J`
                such that `J` is the apex of some submodule of ``self``.

                (conjectural: in fact only those such that there is an
                annihilator module with apex `J`)

                EXAMPLES::

                    sage: M = Semigroups().SetsWithAction().example().algebra(QQ); M
                    Free module generated by Representation of the monoid generated by <2,3> acting on Z/10 Z by multiplication over Rational Field
                    sage: M.composition_series()
                    {0, 1}
                """
                S = self.semigroup()
                R = self.basis().keys()
                try:
                    I = R.apex()
                    Js = [J for J in S.j_poset_on_regular_classes().principal_order_filter(I)]
                except AttributeError:
                    Js = S.regular_j_classes_keys()
                from sage.sets.set import Set
                return Set(J for J in Js if self.annihilator_module_with_apex(J) is not None)

            @cached_method
            def composition_series_poset(self):
                """
                The composition series of this module, endowed with `J`-order.

                EXAMPLES::

                    sage: M = Semigroups().SetsWithAction().example().algebra(QQ); M
                    Free module generated by Representation of the monoid generated by <2,3> acting on Z/10 Z by multiplication over Rational Field
                    sage: M.composition_series_poset()
                    Finite poset containing 2 elements
                    sage: M.composition_series_poset().cover_relations()
                    [[1, 0]]
                """
                S = self.semigroup()
                P = S.j_poset_on_regular_classes()
                return P.subposet(list(self.composition_series()))

            def annihilator_poset(self):
                """
                This computes all annihilator submodules with apex of
                ``self`` (see :meth:`self.annihilator_module_with_apex`)
                and order them for inclusion.

                EXAMPLES::

                    sage: M = Semigroups().SetsWithAction().example().algebra(QQ); M
                    Free module generated by Representation of the monoid generated by <2,3> acting on Z/10 Z by multiplication over Rational Field
                    sage: M.annihilator_poset()
                    Finite poset containing 2 elements
                    sage: M.annihilator_poset().cover_relations()
                    [[Vector space of degree 10 and dimension 5 over Rational Field
                      Basis matrix:
                      [ 1  0  0  0  0 -1  0  0  0  0]
                      [ 0  1  0  0  0  0 -1  0  0  0]
                      [ 0  0  1  0  0  0  0 -1  0  0]
                      [ 0  0  0  1  0  0  0  0 -1  0]
                      [ 0  0  0  0  1  0  0  0  0 -1],
                      Vector space of degree 10 and dimension 10 over Rational Field
                      Basis matrix:
                      [1 0 0 0 0 0 0 0 0 0]
                      [0 1 0 0 0 0 0 0 0 0]
                      [0 0 1 0 0 0 0 0 0 0]
                      [0 0 0 1 0 0 0 0 0 0]
                      [0 0 0 0 1 0 0 0 0 0]
                      [0 0 0 0 0 1 0 0 0 0]
                      [0 0 0 0 0 0 1 0 0 0]
                      [0 0 0 0 0 0 0 1 0 0]
                      [0 0 0 0 0 0 0 0 1 0]
                      [0 0 0 0 0 0 0 0 0 1]]]
                """
                from sage.combinat.posets.posets import Poset
                return Poset([[self.annihilator_with_apex(J) for J in self.composition_series()],
                              lambda M, N: M.is_subspace(N)])

            @cached_method
            def test_composition_series_poset(self):
                """
                Sanity checks for a for regular left/right class

                EXAMPLES::

                    sage: M = Semigroups().SetsWithAction().example().algebra(QQ); M
                    Free module generated by Representation of the monoid generated by <2,3> acting on Z/10 Z by multiplication over Rational Field
                    sage: M.test_composition_series_poset()
                """
                S = self.semigroup()
                R = self.basis().keys()
                composition_series_poset = self.composition_series_poset()
                assert composition_series_poset.is_meet_semilattice()
                #annihilator_poset = self.annihilator_poset()
                #annihilator_poset_dual = annihilator_poset.dual()
                #f = lambda J: annihilator_poset_dual(self.annihilator_with_apex(J))
                #assert composition_series_poset.is_poset_isomorphism(f, annihilator_poset_dual)

                # Dimension checks
                for J in self.composition_series():
                    assert self.annihilator_with_apex(J).dimension() == S.lr_regular_class(J, side=R.side()).cardinality()

                assert self.dimension() == sum(S.simple_module_dimension(J) for J in self.composition_series())

                # That can't work with the current definition of annihilator_module_with_apex.
                # j_poset = S.j_poset_on_regular_classes()
                # f = lambda J: composition_series_poset(self.annihilator_module_with_apex(J).apex())
                # assert j_poset.is_poset_morphism(f, composition_series_poset)

                return

                assert composition_series_poset.is_lattice()
                from sage.combinat.posets.lattices import LatticePoset
                composition_lattice = LatticePoset(composition_series_poset)
                # annihilator_poset = LatticePoset(annihilator_poset)

                # Check that self.annihilator_module_with_apex is a
                # lattice morphism from the composition poset to the
                # lattice of submodules of self. This is similar to
                # the above isomorphism test with the
                # annihilator_poset, except that we enforce that the
                # meet on submodules is given by intersection.

                f = lambda J: self.annihilator_module_with_apex(J)
                L = composition_lattice
                for J1 in self.composition_series():
                    for J2 in self.composition_series():
                        assert f(J1).intersection(f(J2)) == f( L.join(L(J1), L(J2)) )
        class ParentMethods:
            r"""
            TESTS:

            Ideally, these tests should be just after the declaration of the
            associated attributes. But doing this way, Sage will not consider
            them as a doctest.

            We check that Cartesian products of finite enumerated sets
            inherit various methods from `Sets.CartesianProducts`
            and not from :class:`EnumeratedSets.Finite`::

                sage: C = cartesian_product([Partitions(10), Permutations(20)])
                sage: C in EnumeratedSets().Finite()
                True

                sage: C.random_element.__module__
                'sage.categories.sets_cat'

                sage: C.cardinality.__module__
                'sage.categories.sets_cat'

                sage: C.__iter__.__module__
                'sage.categories.sets_cat'
            """
            random_element = raw_getattr(Sets.CartesianProducts.ParentMethods, "random_element")
            cardinality = raw_getattr(Sets.CartesianProducts.ParentMethods, "cardinality")
            __iter__ = raw_getattr(Sets.CartesianProducts.ParentMethods, "__iter__")

            def last(self):
                r"""
                Return the last element

                EXAMPLES::

                    sage: C = cartesian_product([Zmod(42), Partitions(10), IntegerRange(5)])
                    sage: C.last()
                    (41, [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 4)
                """
                return self._cartesian_product_of_elements(
                        tuple(c.last() for c in self.cartesian_factors()))

            def rank(self, x):
                r"""
                Return the rank of an element of this Cartesian product.

                The *rank* of ``x`` is its position in the
                enumeration. It is an integer between ``0`` and
                ``n-1`` where ``n`` is the cardinality of this set.

                .. SEEALSO::

                    - :meth:`EnumeratedSets.ParentMethods.rank`
                    - :meth:`unrank`

                EXAMPLES::

                    sage: C = cartesian_product([GF(2), GF(11), GF(7)])
                    sage: C.rank(C((1,2,5)))
                    96
                    sage: C.rank(C((0,0,0)))
                    0

                    sage: for c in C: print(C.rank(c))
                    0
                    1
                    2
                    3
                    4
                    5
                    ...
                    150
                    151
                    152
                    153

                    sage: F1 = FiniteEnumeratedSet('abcdefgh')
                    sage: F2 = IntegerRange(250)
                    sage: F3 = Partitions(20)
                    sage: C = cartesian_product([F1, F2, F3])
                    sage: c = C(('a', 86, [7,5,4,4]))
                    sage: C.rank(c)
                    54213
                    sage: C.unrank(54213)
                    ('a', 86, [7, 5, 4, 4])
                """
                from builtins import zip
                from sage.rings.integer_ring import ZZ
                x = self(x)
                b = ZZ.one()
                rank = ZZ.zero()
                for f, c in zip(reversed(x.cartesian_factors()),
                                reversed(self.cartesian_factors())):
                    rank += b * c.rank(f)
                    b *= c.cardinality()
                return rank

            def unrank(self, i):
                r"""
                Return the ``i``-th element of this Cartesian product.

                INPUT:

                - ``i`` -- integer between ``0`` and ``n-1`` where
                  ``n`` is the cardinality of this set.

                .. SEEALSO::

                    - :meth:`EnumeratedSets.ParentMethods.unrank`
                    - :meth:`rank`

                EXAMPLES::

                    sage: C = cartesian_product([GF(3), GF(11), GF(7), GF(5)])
                    sage: c = C.unrank(123); c
                    (0, 3, 3, 3)
                    sage: C.rank(c)
                    123

                    sage: c = C.unrank(857); c
                    (2, 2, 3, 2)
                    sage: C.rank(c)
                    857

                    sage: C.unrank(2500)
                    Traceback (most recent call last):
                    ...
                    IndexError: index i (=2) is greater than the cardinality
                """
                from sage.rings.integer_ring import ZZ
                i = ZZ(i)
                if i < 0:
                    raise IndexError("i (={}) must be a non-negative integer")
                elt = []
                for c in reversed(self.cartesian_factors()):
                    card = c.cardinality()
                    elt.insert(0, c.unrank(i % card))
                    i //= card
                if i:
                    raise IndexError("index i (={}) is greater than the cardinality".format(i))
                return self._cartesian_product_of_elements(elt)
 class Algebras(AlgebrasCategory):
     # see the warning in sage.categories.set_with_action_functor.SetsWithActionCategory._algebras_extra_super_categories
     extra_super_categories = raw_getattr(
         SetsWithActionCategory, "_algebras_extra_super_categories")
示例#8
0
 class ParentMethods:
     __init_extra__ = raw_getattr(
         Groups.Finite.Algebras.ParentMethods, "__init_extra__")
示例#9
0
 class ParentMethods:
     group = raw_getattr(Groups.Algebras.ParentMethods, "group")
示例#10
0
def trace_method(obj, meth, **kwds):
    r"""
    Trace the doings of a given method.
    It prints method entry with arguments,
    access to members and other methods during method execution
    as well as method exit with return value.

    INPUT:

    - ``obj`` -- the object containing the method.

    - ``meth`` -- the name of the method to be traced.

    - ``prefix`` -- (default: ``"  "``)
      string to prepend to each printed output.

    - ``reads`` -- (default: ``True``)
      whether to trace read access as well.
      

    EXAMPLES::

        sage: class Foo(object):
        ....:     def f(self, arg=None):
        ....:         self.y = self.g(self.x)
        ....:         if arg: return arg*arg
        ....:     def g(self, arg):
        ....:         return arg + 1
        ....:
        sage: foo = Foo()
        sage: foo.x = 3
        sage: from sage.doctest.fixtures import trace_method
        sage: trace_method(foo, "f")
        sage: foo.f()
        enter f()
          read x = 3
          call g(3) -> 4
          write y = 4
        exit f -> None
        sage: foo.f(3)
        enter f(3)
          read x = 3
          call g(3) -> 4
          write y = 4
        exit f -> 9
        9
    """
    from sage.cpython.getattr import raw_getattr
    f = raw_getattr(obj, meth)
    t = AttributeAccessTracerProxy(obj, **kwds)

    @wraps(f)
    def g(*args, **kwds):
        arglst = [reproducible_repr(arg) for arg in args]
        arglst.extend("{}={}".format(k, reproducible_repr(v))
                      for k, v in sorted(kwds.items()))
        print("enter {}({})".format(meth, ", ".join(arglst)))
        res = f(t, *args, **kwds)
        print("exit {} -> {}".format(meth, reproducible_repr(res)))
        return res

    setattr(obj, meth, g)