def default_super_categories(cls, category, *args): """ Returns the default super categories of ``...`` INPUT: - ``category`` -- a category OUTPUT: a join category This implements the property that an induced subcategory is a subcategory. EXAMPLES: A subquotient of a monoid is a monoid, and a subquotient of semigroup:: sage: Monoids().Subquotients().super_categories() [Category of monoids, Category of subquotients of semigroups] TESTS:: sage: C = Monoids().Subquotients() sage: C.__class__.default_super_categories(C.base_category(), *C._args) Join of Category of monoids and Category of subquotients of semigroups """ return Category.join([category, super(RegressiveCovariantConstructionCategory, cls).default_super_categories(category, *args)])
def default_super_categories(cls, category, *args): """ Returns the default super categories of `F_{Cat}(A,B,C)` for `A,B,C` parents in `Cat`. INPUT: - ``cls`` -- the category class for the functor `F` - ``category`` -- a category `Cat` - ``*args`` -- further arguments for the functor OUTPUT: a (join) category The default implementation is to return the join of the categories of `F(A,B,C)` for `A,B,C` in turn in each of the super categories of ``category``. This is implemented as a class method, in order to be able to reconstruct the functorial category associated to each of the super categories of ``category``. EXAMPLES: Bialgebras are both algebras and coalgebras:: sage: Bialgebras(QQ).super_categories() [Category of algebras over Rational Field, Category of coalgebras over Rational Field] Hence tensor products of bialgebras are tensor products of algebras and tensor products of coalgebras:: sage: Bialgebras(QQ).TensorProducts().super_categories() [Category of tensor products of algebras over Rational Field, Category of tensor products of coalgebras over Rational Field] Here is how :meth:`default_super_categories` was called internally:: sage: sage.categories.tensor.TensorProductsCategory.default_super_categories(Bialgebras(QQ)) Join of Category of tensor products of algebras over Rational Field and Category of tensor products of coalgebras over Rational Field We now show a similar example, with the ``Algebra`` functor which takes a parameter `\QQ`:: sage: FiniteMonoids().super_categories() [Category of finite semigroups, Category of monoids] sage: FiniteMonoids().Algebras(QQ).super_categories() [Category of semigroup algebras over Rational Field] Note that neither the category of *finite* semigroup algebras nor that of monoid algebras appear in the result; this is because there is currently nothing specific implemented about them. Here is how :meth:`default_super_categories` was called internally:: sage: sage.categories.algebra_functor.AlgebrasCategory.default_super_categories(FiniteMonoids(), QQ) Category of monoid algebras over Rational Field """ return Category.join([ getattr(cat, cls._functor_category)(*args) for cat in category._super_categories ])
def __init__(self, cartan_type): """ Construct this Coxeter group as a Sage permutation group, by fetching the permutation representation of the generators from Chevie's database. TESTS:: sage: from sage.combinat.root_system.coxeter_group import CoxeterGroupAsPermutationGroup sage: W = CoxeterGroupAsPermutationGroup(CartanType(["H",3])) # optional - chevie sage: TestSuite(W).run() # optional - chevie """ assert cartan_type.is_finite() assert cartan_type.is_irreducible() self._semi_simple_rank = cartan_type.n from sage.interfaces.gap3 import gap3 gap3._start() gap3.load_package("chevie") self._gap_group = gap3('CoxeterGroup("%s",%s)'%(cartan_type.letter,cartan_type.n)) # Following #9032, x.N is an alias for x.numerical_approx in every Sage object ... N = self._gap_group.__getattr__("N").sage() generators = [str(x) for x in self._gap_group.generators] self._is_positive_root = [None] + [ True ] * N + [False]*N PermutationGroup_generic.__init__(self, gens = generators, category = Category.join([FinitePermutationGroups(), FiniteCoxeterGroups()]))
def __init__(self, sets, category, order=None, **kwargs): r""" See :class:`CartesianProductPoset` for details. TESTS:: sage: P = Poset((srange(3), lambda left, right: left <= right)) sage: C = cartesian_product((P, P), order='notexisting') Traceback (most recent call last): ... ValueError: No order 'notexisting' known. sage: C = cartesian_product((P, P), category=(Groups(),)) sage: C.category() Join of Category of groups and Category of posets """ if order is None: self._le_ = self.le_product elif isinstance(order, str): try: self._le_ = getattr(self, 'le_' + order) except AttributeError: raise ValueError("No order '%s' known." % (order,)) else: self._le_ = order from sage.categories.category import Category from sage.categories.posets import Posets if not isinstance(category, tuple): category = (category,) category = Category.join(category + (Posets(),)) super(CartesianProductPoset, self).__init__( sets, category, **kwargs)
def __init__(self, cartan_type): """ Construct this Coxeter group as a Sage permutation group, by fetching the permutation representation of the generators from Chevie's database. TESTS:: sage: from sage.combinat.root_system.coxeter_group import CoxeterGroupAsPermutationGroup sage: W = CoxeterGroupAsPermutationGroup(CartanType(["H",3])) # optional - chevie sage: TestSuite(W).run() # optional - chevie """ assert cartan_type.is_finite() assert cartan_type.is_irreducible() self._semi_simple_rank = cartan_type.n from sage.interfaces.gap3 import gap3 gap3._start() gap3.load_package("chevie") self._gap_group = gap3('CoxeterGroup("%s",%s)' % (cartan_type.letter, cartan_type.n)) # Following #9032, x.N is an alias for x.numerical_approx in every Sage object ... N = self._gap_group.__getattr__("N").sage() generators = [str(x) for x in self._gap_group.generators] self._is_positive_root = [None] + [True] * N + [False] * N PermutationGroup_generic.__init__(self, gens=generators, category=Category.join([ FinitePermutationGroups(), FiniteCoxeterGroups() ]))
def default_super_categories(cls, category, *args): """ Return the default super categories of `F_{Cat}(A,B,...)` for `A,B,...` parents in `Cat`. INPUT: - ``cls`` -- the category class for the functor `F` - ``category`` -- a category `Cat` - ``*args`` -- further arguments for the functor OUTPUT: A join category. This implements the property that an induced subcategory is a subcategory. EXAMPLES: A subquotient of a monoid is a monoid, and a subquotient of semigroup:: sage: Monoids().Subquotients().super_categories() [Category of monoids, Category of subquotients of semigroups] TESTS:: sage: C = Monoids().Subquotients() sage: C.__class__.default_super_categories(C.base_category(), *C._args) Category of unital subquotients of semigroups """ return Category.join([category, super(RegressiveCovariantConstructionCategory, cls).default_super_categories(category, *args)])
def __classcall_private__(cls, crystals, facade=True, keepkey=False, category=None): """ Normalization of arguments; see :class:`UniqueRepresentation`. TESTS: We check that direct sum of crystals have unique representation:: sage: B = crystals.Tableaux(['A',2], shape=[2,1]) sage: C = crystals.Letters(['A',2]) sage: D1 = crystals.DirectSum([B, C]) sage: D2 = crystals.DirectSum((B, C)) sage: D1 is D2 True sage: D3 = crystals.DirectSum([B, C, C]) sage: D4 = crystals.DirectSum([D1, C]) sage: D3 is D4 True """ if not isinstance(facade, bool) or not isinstance(keepkey, bool): raise TypeError # Normalize the facade-keepkey by giving keepkey dominance facade = not keepkey # We expand out direct sums of crystals ret = [] for x in Family(crystals): if isinstance(x, DirectSumOfCrystals): ret += list(x.crystals) else: ret.append(x) category = Category.meet([Category.join(c.categories()) for c in ret]) return super(DirectSumOfCrystals, cls).__classcall__(cls, Family(ret), facade=facade, keepkey=keepkey, category=category)
def __init__(self, sets, category, order=None, **kwargs): r""" See :class:`CartesianProductPoset` for details. TESTS:: sage: P = Poset((srange(3), lambda left, right: left <= right)) sage: C = cartesian_product((P, P), order='notexisting') Traceback (most recent call last): ... ValueError: No order 'notexisting' known. sage: C = cartesian_product((P, P), category=(Groups(),)) sage: C.category() Join of Category of groups and Category of posets """ if order is None: self._le_ = self.le_product elif isinstance(order, str): try: self._le_ = getattr(self, 'le_' + order) except AttributeError: raise ValueError("No order '%s' known." % (order, )) else: self._le_ = order from sage.categories.category import Category from sage.categories.posets import Posets if not isinstance(category, tuple): category = (category, ) category = Category.join(category + (Posets(), )) super(CartesianProductPoset, self).__init__(sets, category, **kwargs)
def default_super_categories(cls, category, *args): """ Returns the default super categories of `F_{Cat}(A,B,C)` for `A,B,C` parents in `Cat`. INPUT: - ``cls`` -- the category class for the functor `F` - ``category`` -- a category `Cat` - ``*args`` -- further arguments for the functor OUTPUT: a (join) category The default implementation is to return the join of the categories of `F(A,B,C)` for `A,B,C` in turn in each of the super categories of ``category``. This is implemented as a class method, in order to be able to reconstruct the functorial category associated to each of the super categories of ``category``. EXAMPLES: Bialgebras are both algebras and coalgebras:: sage: Bialgebras(QQ).super_categories() [Category of algebras over Rational Field, Category of coalgebras over Rational Field] Hence tensor products of bialgebras are tensor products of algebras and tensor products of coalgebras:: sage: Bialgebras(QQ).TensorProducts().super_categories() [Category of tensor products of algebras over Rational Field, Category of tensor products of coalgebras over Rational Field] Here is how :meth:`default_super_categories` was called internally:: sage: sage.categories.tensor.TensorProductsCategory.default_super_categories(Bialgebras(QQ)) Join of Category of tensor products of algebras over Rational Field and Category of tensor products of coalgebras over Rational Field We now show a similar example, with the ``Algebra`` functor which takes a parameter `\QQ`:: sage: FiniteMonoids().super_categories() [Category of finite semigroups, Category of monoids] sage: FiniteMonoids().Algebras(QQ).super_categories() [Category of semigroup algebras over Rational Field] Note that neither the category of *finite* semigroup algebras nor that of monoid algebras appear in the result; this is because there is currently nothing specific implemented about them. Here is how :meth:`default_super_categories` was called internally:: sage: sage.categories.algebra_functor.AlgebrasCategory.default_super_categories(FiniteMonoids(), QQ) Category of monoid algebras over Rational Field """ return Category.join([getattr(cat, cls._functor_category)(*args) for cat in category._super_categories])
def __init__(self, order, cache=None, category=None): """ Create with the command ``IntegerModRing(order)``. TESTS:: sage: FF = IntegerModRing(29) sage: TestSuite(FF).run() sage: F19 = IntegerModRing(19, category = Fields()) sage: TestSuite(F19).run() sage: F23 = IntegerModRing(23) sage: F23 in Fields() True sage: TestSuite(F23).run() sage: Z16 = IntegerModRing(16) sage: TestSuite(Z16).run() sage: R = Integers(100000) sage: TestSuite(R).run() # long time (17s on sage.math, 2011) """ order = ZZ(order) if order <= 0: raise ZeroDivisionError("order must be positive") self.__order = order self._pyx_order = integer_mod.NativeIntStruct(order) if category is None: from sage.categories.commutative_rings import CommutativeRings from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.category import Category category = Category.join( [CommutativeRings(), FiniteEnumeratedSets()]) # category = default_category # If the category is given then we trust that is it right. # Give the generator a 'name' to make quotients work. The # name 'x' is used because it's also used for the ring of # integers: see the __init__ method for IntegerRing_class in # sage/rings/integer_ring.pyx. quotient_ring.QuotientRing_generic.__init__(self, ZZ, ZZ.ideal(order), names=('x', ), category=category) # Calling ParentWithGens is not needed, the job is done in # the quotient ring initialisation. #ParentWithGens.__init__(self, self, category = category) # We want that the ring is its own base ring. self._base = self if cache is None: cache = order < 500 if cache: self._precompute_table() self._zero_element = integer_mod.IntegerMod(self, 0) self._one_element = integer_mod.IntegerMod(self, 1)
def __init__(self, A, gens=None): """ A subring of the endomorphism ring. INPUT: - ``A`` - an abelian variety - ``gens`` - (default: None); optional; if given should be a tuple of the generators as matrices EXAMPLES:: sage: J0(23).endomorphism_ring() Endomorphism ring of Abelian variety J0(23) of dimension 2 sage: sage.modular.abvar.homspace.EndomorphismSubring(J0(25)) Endomorphism ring of Abelian variety J0(25) of dimension 0 sage: E = J0(11).endomorphism_ring() sage: type(E) <class 'sage.modular.abvar.homspace.EndomorphismSubring_with_category'> sage: E.category() Join of Category of hom sets in Category of sets and Category of rings sage: E.homset_category() Category of modular abelian varieties over Rational Field sage: TestSuite(E).run(skip=["_test_elements"]) TESTS: The following tests against a problem on 32 bit machines that occured while working on trac ticket #9944:: sage: sage.modular.abvar.homspace.EndomorphismSubring(J1(12345)) Endomorphism ring of Abelian variety J1(12345) of dimension 5405473 """ self._J = A.ambient_variety() self._A = A # Initialise self with the correct category. # TODO: a category should be able to specify the appropriate # category for its endomorphism sets # We need to initialise it as a ring first homset_cat = A.category() cat = Category.join([homset_cat.hom_category(), Rings()]) Ring.__init__(self, A.base_ring()) Homspace.__init__(self, A, A, cat=homset_cat) self._refine_category_(Rings()) if gens is None: self._gens = None else: self._gens = tuple([self._get_matrix(g) for g in gens]) self._is_full_ring = gens is None
def __init__(self, A, gens=None): """ A subring of the endomorphism ring. INPUT: - ``A`` - an abelian variety - ``gens`` - (default: None); optional; if given should be a tuple of the generators as matrices EXAMPLES:: sage: J0(23).endomorphism_ring() Endomorphism ring of Abelian variety J0(23) of dimension 2 sage: sage.modular.abvar.homspace.EndomorphismSubring(J0(25)) Endomorphism ring of Abelian variety J0(25) of dimension 0 sage: E = J0(11).endomorphism_ring() sage: type(E) <class 'sage.modular.abvar.homspace.EndomorphismSubring_with_category'> sage: E.category() Join of Category of hom sets in Category of sets and Category of rings sage: E.homset_category() Category of modular abelian varieties over Rational Field sage: TestSuite(E).run(skip=["_test_elements"]) TESTS: The following tests against a problem on 32 bit machines that occured while working on trac ticket #9944:: sage: sage.modular.abvar.homspace.EndomorphismSubring(J1(12345)) Endomorphism ring of Abelian variety J1(12345) of dimension 5405473 """ self._J = A.ambient_variety() self._A = A # Initialise self with the correct category. # TODO: a category should be able to specify the appropriate # category for its endomorphism sets # We need to initialise it as a ring first homset_cat = A.category() cat = Category.join([homset_cat.hom_category(),Rings()]) Ring.__init__(self, A.base_ring()) Homspace.__init__(self, A, A, cat=homset_cat) self._refine_category_(Rings()) if gens is None: self._gens = None else: self._gens = tuple([ self._get_matrix(g) for g in gens ]) self._is_full_ring = gens is None
def default_super_categories(cls, category): """ Returns the default super categories of ``category.IsomorphicObjects()`` Mathematical meaning: if `A` is the image of `B` by an isomorphism in the category `C`, then `A` is both a subobject of `B` and a quotient of `B` in the category `C`. INPUT: - ``cls`` -- the class ``IsomorphicObjectsCategory`` - ``category`` -- a category `Cat` OUTPUT: a (join) category In practice, this returns ``category.Subobjects()`` and ``category.Quotients()``, joined together with the result of the method :meth:`RegressiveCovariantConstructionCategory.default_super_categories() <sage.categories.covariant_functorial_construction.RegressiveCovariantConstructionCategory.default_super_categories>` (that is the join of ``category`` and ``cat.IsomorphicObjects()`` for each ``cat`` in the super categories of ``category``). EXAMPLES: Consider ``category=Groups()``, which has ``cat=Monoids()`` as super category. Then, the image of a group `G'` by a group isomorphism is simultaneously a subgroup of `G`, a subquotient of `G`, a group by itself, and the image of `G` by a monoid isomorphism:: sage: Groups().IsomorphicObjects().super_categories() [Category of groups, Category of subquotients of monoids, Category of quotients of semigroups, Category of isomorphic objects of sets] Mind the last item above: there is indeed currently nothing implemented about isomorphic objects of monoids. This resulted from the following call:: sage: sage.categories.isomorphic_objects.IsomorphicObjectsCategory.default_super_categories(Groups()) Join of Category of groups and Category of subquotients of monoids and Category of quotients of semigroups and Category of isomorphic objects of sets """ return Category.join([ category.Subobjects(), category.Quotients(), super(IsomorphicObjectsCategory, cls).default_super_categories(category) ])
def super_categories(self): """ Returns the super categories of a construction category EXAMPLES:: sage: Sets().Subquotients().super_categories() [Category of sets] sage: Semigroups().Quotients().super_categories() [Category of subquotients of semigroups, Category of quotients of sets] """ return Category.join(self.extra_super_categories() + [self.__class__.default_super_categories(self.base_category(), *self._args)], as_list = True)
def __init__(self, order, cache=None, category=None): """ Create with the command ``IntegerModRing(order)``. TESTS:: sage: FF = IntegerModRing(29) sage: TestSuite(FF).run() sage: F19 = IntegerModRing(19, category = Fields()) sage: TestSuite(F19).run() sage: F23 = IntegerModRing(23) sage: F23 in Fields() True sage: TestSuite(F23).run() sage: Z16 = IntegerModRing(16) sage: TestSuite(Z16).run() sage: R = Integers(100000) sage: TestSuite(R).run() # long time (17s on sage.math, 2011) """ order = ZZ(order) if order <= 0: raise ZeroDivisionError("order must be positive") self.__order = order self._pyx_order = integer_mod.NativeIntStruct(order) if category is None: from sage.categories.commutative_rings import CommutativeRings from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.category import Category category = Category.join([CommutativeRings(), FiniteEnumeratedSets()]) # category = default_category # If the category is given then we trust that is it right. # Give the generator a 'name' to make quotients work. The # name 'x' is used because it's also used for the ring of # integers: see the __init__ method for IntegerRing_class in # sage/rings/integer_ring.pyx. quotient_ring.QuotientRing_generic.__init__(self, ZZ, ZZ.ideal(order), names=('x',), category=category) # Calling ParentWithGens is not needed, the job is done in # the quotient ring initialisation. #ParentWithGens.__init__(self, self, category = category) # We want that the ring is its own base ring. self._base = self if cache is None: cache = order < 500 if cache: self._precompute_table() self._zero_element = integer_mod.IntegerMod(self, 0) self._one_element = integer_mod.IntegerMod(self, 1)
def default_super_categories(cls, category): """ Returns the default super categories of ``category.IsomorphicObjects()`` Mathematical meaning: if `A` is the image of `B` by an isomorphism in the category `C`, then `A` is both a subobject of `B` and a quotient of `B` in the category `C`. INPUT: - ``cls`` -- the class ``IsomorphicObjectsCategory`` - ``category`` -- a category `Cat` OUTPUT: a (join) category In practice, this returns ``category.Subobjects()`` and ``category.Quotients()``, joined together with the result of the method :meth:`RegressiveCovariantConstructionCategory.default_super_categories() <sage.categories.covariant_functorial_construction.RegressiveCovariantConstructionCategory.default_super_categories>` (that is the join of ``category`` and ``cat.IsomorphicObjects()`` for each ``cat`` in the super categories of ``category``). EXAMPLES: Consider ``category=Groups()``, which has ``cat=Monoids()`` as super category. Then, the image of a group `G'` by a group isomorphism is simultaneously a subgroup of `G`, a subquotient of `G`, a group by itself, and the image of `G` by a monoid isomorphism:: sage: Groups().IsomorphicObjects().super_categories() [Category of groups, Category of subquotients of monoids, Category of quotients of semigroups, Category of isomorphic objects of sets] Mind the last item above: there is indeed currently nothing implemented about isomorphic objects of monoids. This resulted from the following call:: sage: sage.categories.isomorphic_objects.IsomorphicObjectsCategory.default_super_categories(Groups()) Join of Category of groups and Category of subquotients of monoids and Category of quotients of semigroups and Category of isomorphic objects of sets """ return Category.join([category.Subobjects(), category.Quotients(), super(IsomorphicObjectsCategory, cls).default_super_categories(category)])
def default_super_categories_yacop(cls, category, *args): """ TESTS:: sage: import yacop sage: # an earlier version of this hack broke the MRO for quasi symmetric functions: sage: QuasiSymmetricFunctions(GF(3)) Quasisymmetric functions over the Finite Field of size 3 """ sageresult = Category.join([ category, super(RegressiveCovariantConstructionCategory, cls).default_super_categories(category, *args) ]) ans = sageresult if isinstance(ans, sage.categories.category.JoinCategory): j = [ cat for cat in sageresult.super_categories() if not hasattr(cat, "yacop_no_default_inheritance") ] ans = Category.join(j) return ans
def _test_homsets_category(self, **options): r""" Run generic tests on this homsets category .. SEEALSO:: :class:`TestSuite`. EXAMPLES:: sage: Sets().Homsets()._test_homsets_category() """ # TODO: remove if unneeded #from sage.categories.objects import Objects #from sage.categories.sets_cat import Sets tester = self._tester(**options) tester.assert_(self.is_subcategory(Category.join(self.base_category().structure()).Homsets()))
def __init__(self, crystals, **options): """ TESTS:: sage: C = crystals.Letters(['A',2]) sage: B = crystals.DirectSum([C,C], keepkey=True) sage: B Direct sum of the crystals Family (The crystal of letters for type ['A', 2], The crystal of letters for type ['A', 2]) sage: B.cartan_type() ['A', 2] sage: from sage.combinat.crystals.direct_sum import DirectSumOfCrystals sage: isinstance(B, DirectSumOfCrystals) True """ if 'keepkey' in options: keepkey = options['keepkey'] else: keepkey = False # facade = options['facade'] if keepkey: facade = False else: facade = True category = Category.meet( [Category.join(crystal.categories()) for crystal in crystals]) Parent.__init__(self, category=category) DisjointUnionEnumeratedSets.__init__(self, crystals, keepkey=keepkey, facade=facade) self.rename("Direct sum of the crystals %s" % (crystals, )) self._keepkey = keepkey self.crystals = crystals if len(crystals) == 0: raise ValueError("The direct sum is empty") else: assert (crystal.cartan_type() == crystals[0].cartan_type() for crystal in crystals) self._cartan_type = crystals[0].cartan_type() if keepkey: self.module_generators = [ self(tuple([i, b])) for i in range(len(crystals)) for b in crystals[i].module_generators ] else: self.module_generators = sum( (list(B.module_generators) for B in crystals), [])
def _test_homsets_category(self, **options): r""" Run generic tests on this homsets category .. SEEALSO:: :class:`TestSuite`. EXAMPLES:: sage: Sets().Homsets()._test_homsets_category() """ # TODO: remove if unneeded #from sage.categories.objects import Objects #from sage.categories.sets_cat import Sets tester = self._tester(**options) tester.assertTrue(self.is_subcategory(Category.join(self.base_category().structure()).Homsets())) tester.assertTrue(self.is_subcategory(Homsets()))
def __classcall_private__(cls, crystals, facade=True, keepkey=False, category=None): """ Normalization of arguments; see :class:`UniqueRepresentation`. TESTS: We check that direct sum of crystals have unique representation:: sage: B = crystals.Tableaux(['A',2], shape=[2,1]) sage: C = crystals.Letters(['A',2]) sage: D1 = crystals.DirectSum([B, C]) sage: D2 = crystals.DirectSum((B, C)) sage: D1 is D2 True sage: D3 = crystals.DirectSum([B, C, C]) sage: D4 = crystals.DirectSum([D1, C]) sage: D3 is D4 True """ if not isinstance(facade, bool) or not isinstance(keepkey, bool): raise TypeError # Normalize the facade-keepkey by giving keepkey dominance if keepkey: facade = False else: facade = True # We expand out direct sums of crystals ret = [] for x in Family(crystals): if isinstance(x, DirectSumOfCrystals): ret += list(x.crystals) else: ret.append(x) category = Category.meet([Category.join(c.categories()) for c in ret]) return super(DirectSumOfCrystals, cls).__classcall__(cls, Family(ret), facade=facade, keepkey=keepkey, category=category)
def default_super_categories(cls, category): """ Return the default super categories of ``category.Homsets()`` INPUT: - ``cls`` -- the category class for the functor `F` - ``category`` -- a category `Cat` OUTPUT: a category .. TODO:: adapt everything below The default implementation is to return the join of the categories of `F(A,B,...)` for `A,B,...` in turn in each of the super categories of ``category``. This is implemented as a class method, in order to be able to reconstruct the functorial category associated to each of the super categories of ``category``. EXAMPLES:: sage: AdditiveMagmas().Homsets().super_categories() [Category of additive magmas] sage: AdditiveMagmas().AdditiveUnital().Homsets().super_categories() [Category of additive unital additive magmas] For now nothing specific is implemented for homsets of additive groups compared to homsets of monoids:: sage: from sage.categories.additive_groups import AdditiveGroups sage: AdditiveGroups().Homsets() Category of homsets of additive monoids Similarly for rings; so a ring homset is a homset of unital magmas and additive magmas:: sage: Rings().Homsets() Category of homsets of unital magmas and additive unital additive magmas """ return Category.join([getattr(cat, cls._functor_category)() for cat in category.full_super_categories()])
def super_categories(self): """ EXAMPLES:: sage: from sage.categories.magmatic_algebras import MagmaticAlgebras sage: MagmaticAlgebras(ZZ).super_categories() [Category of additive commutative additive associative additive unital distributive magmas and additive magmas, Category of modules over Integer Ring] sage: from sage.categories.additive_semigroups import AdditiveSemigroups sage: MagmaticAlgebras(ZZ).is_subcategory((AdditiveSemigroups() & Magmas()).Distributive()) True """ R = self.base_ring() # Note: The specifications impose `self` to be a subcategory # of the join of its super categories. Here the join is non # trivial, since some of the axioms of Modules (like the # commutativity of '+') are added to the left hand side. We # might want the infrastructure to take this join for us. return Category.join([(Magmas() & AdditiveMagmas()).Distributive(), Modules(R)], as_list=True)
def super_categories(self): """ EXAMPLES:: sage: from sage.categories.magmatic_algebras import MagmaticAlgebras sage: MagmaticAlgebras(ZZ).super_categories() [Category of additive commutative additive associative additive unital distributive magmas and additive magmas, Category of modules over Integer Ring] sage: from sage.categories.additive_semigroups import AdditiveSemigroups sage: MagmaticAlgebras(ZZ).is_subcategory((AdditiveSemigroups() & Magmas()).Distributive()) True """ R = self.base_ring() # Note: The specifications impose `self` to be a subcategory # of the join of its super categories. Here the join is non # trivial, since some of the axioms of Modules (like the # commutativity of '+') are added to the left hand side. We # might want the infrastructure to take this join for us. return Category.join([(Magmas() & AdditiveMagmas()).Distributive(), Modules(R)], as_list=True)
def default_super_categories(cls, category): """ Return the default super categories of ``category.Metric()``. Mathematical meaning: if `A` is a metric space in the category `C`, then `A` is also a topological space. INPUT: - ``cls`` -- the class ``MetricSpaces`` - ``category`` -- a category `Cat` OUTPUT: A (join) category In practice, this returns ``category.Metric()``, joined together with the result of the method :meth:`RegressiveCovariantConstructionCategory.default_super_categories() <sage.categories.covariant_functorial_construction.RegressiveCovariantConstructionCategory.default_super_categories>` (that is the join of ``category`` and ``cat.Metric()`` for each ``cat`` in the super categories of ``category``). EXAMPLES: Consider ``category=Groups()``. Then, a group `G` with a metric is simultaneously a topological group by itself, and a metric space:: sage: Groups().Metric().super_categories() [Category of topological groups, Category of metric spaces] This resulted from the following call:: sage: sage.categories.metric_spaces.MetricSpacesCategory.default_super_categories(Groups()) Join of Category of topological groups and Category of metric spaces """ return Category.join([ category.Topological(), super(MetricSpacesCategory, cls).default_super_categories(category) ])
def __init__(self, crystals, **options): """ TESTS:: sage: C = crystals.Letters(['A',2]) sage: B = crystals.DirectSum([C,C], keepkey=True) sage: B Direct sum of the crystals Family (The crystal of letters for type ['A', 2], The crystal of letters for type ['A', 2]) sage: B.cartan_type() ['A', 2] sage: from sage.combinat.crystals.direct_sum import DirectSumOfCrystals sage: isinstance(B, DirectSumOfCrystals) True """ if "keepkey" in options: keepkey = options["keepkey"] else: keepkey = False # facade = options['facade'] if keepkey: facade = False else: facade = True category = Category.meet([Category.join(crystal.categories()) for crystal in crystals]) Parent.__init__(self, category=category) DisjointUnionEnumeratedSets.__init__(self, crystals, keepkey=keepkey, facade=facade) self.rename("Direct sum of the crystals %s" % (crystals,)) self._keepkey = keepkey self.crystals = crystals if len(crystals) == 0: raise ValueError("The direct sum is empty") else: assert (crystal.cartan_type() == crystals[0].cartan_type() for crystal in crystals) self._cartan_type = crystals[0].cartan_type() if keepkey: self.module_generators = [ self(tuple([i, b])) for i in range(len(crystals)) for b in crystals[i].module_generators ] else: self.module_generators = sum((list(B.module_generators) for B in crystals), [])
def default_super_categories(cls, category, *args): r""" Return the default super categories of ``category.Graded()``. Mathematical meaning: every graded object (module, algebra, etc.) is a filtered object with the (implicit) filtration defined by `F_i = \bigoplus_{j \leq i} G_j`. INPUT: - ``cls`` -- the class ``GradedModulesCategory`` - ``category`` -- a category OUTPUT: a (join) category In practice, this returns ``category.Filtered()``, joined together with the result of the method :meth:`RegressiveCovariantConstructionCategory.default_super_categories() <sage.categories.covariant_functorial_construction.RegressiveCovariantConstructionCategory.default_super_categories>` (that is the join of ``category.Filtered()`` and ``cat`` for each ``cat`` in the super categories of ``category``). EXAMPLES: Consider ``category=Algebras()``, which has ``cat=Modules()`` as super category. Then, a grading of an algebra `G` is also a filtration of `G`:: sage: Algebras(QQ).Graded().super_categories() [Category of filtered algebras over Rational Field, Category of graded modules over Rational Field] This resulted from the following call:: sage: sage.categories.graded_modules.GradedModulesCategory.default_super_categories(Algebras(QQ)) Join of Category of filtered algebras over Rational Field and Category of graded modules over Rational Field """ cat = super(GradedModulesCategory, cls).default_super_categories(category, *args) return Category.join([category.Filtered(), cat])
def default_super_categories(cls, category, *args): r""" Return the default super categories of ``category.Graded()``. Mathematical meaning: every graded object (module, algebra, etc.) is a filtered object with the (implicit) filtration defined by `F_i = \bigoplus_{j \leq i} G_j`. INPUT: - ``cls`` -- the class ``GradedModulesCategory`` - ``category`` -- a category OUTPUT: a (join) category In practice, this returns ``category.Filtered()``, joined together with the result of the method :meth:`RegressiveCovariantConstructionCategory.default_super_categories() <sage.categories.covariant_functorial_construction.RegressiveCovariantConstructionCategory.default_super_categories>` (that is the join of ``category.Filtered()`` and ``cat`` for each ``cat`` in the super categories of ``category``). EXAMPLES: Consider ``category=Algebras()``, which has ``cat=Modules()`` as super category. Then, a grading of an algebra `G` is also a filtration of `G`:: sage: Algebras(QQ).Graded().super_categories() [Category of filtered algebras over Rational Field, Category of graded modules over Rational Field] This resulted from the following call:: sage: sage.categories.graded_modules.GradedModulesCategory.default_super_categories(Algebras(QQ)) Join of Category of filtered algebras over Rational Field and Category of graded modules over Rational Field """ cat = super(GradedModulesCategory, cls).default_super_categories(category, *args) return Category.join([category.Filtered(), cat])
def default_super_categories(cls, category): """ Return the default super categories of ``category.Metric()``. Mathematical meaning: if `A` is a metric space in the category `C`, then `A` is also a topological space. INPUT: - ``cls`` -- the class ``MetricSpaces`` - ``category`` -- a category `Cat` OUTPUT: A (join) category In practice, this returns ``category.Metric()``, joined together with the result of the method :meth:`RegressiveCovariantConstructionCategory.default_super_categories() <sage.categories.covariant_functorial_construction.RegressiveCovariantConstructionCategory.default_super_categories>` (that is the join of ``category`` and ``cat.Metric()`` for each ``cat`` in the super categories of ``category``). EXAMPLES: Consider ``category=Groups()``. Then, a group `G` with a metric is simultaneously a topological group by itself, and a metric space:: sage: Groups().Metric().super_categories() [Category of topological groups, Category of metric spaces] This resulted from the following call:: sage: sage.categories.metric_spaces.MetricSpacesCategory.default_super_categories(Groups()) Join of Category of topological groups and Category of metric spaces """ return Category.join([category.Topological(), super(MetricSpacesCategory, cls).default_super_categories(category)])
def __init__(self, abvar, field_of_definition=QQ): """ Initialize ``self``. TESTS:: sage: A = J0(11) sage: G = A.torsion_subgroup(2) sage: TestSuite(G).run() # long time """ from sage.categories.category import Category from sage.categories.fields import Fields from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.modules import Modules from .abvar import is_ModularAbelianVariety if field_of_definition not in Fields(): raise TypeError("field_of_definition must be a field") if not is_ModularAbelianVariety(abvar): raise TypeError("abvar must be a modular abelian variety") category = Category.join((Modules(ZZ), FiniteEnumeratedSets())) Module.__init__(self, ZZ, category=category) self.__abvar = abvar self.__field_of_definition = field_of_definition
def __init__(self, abvar, field_of_definition=QQ): """ Initialize ``self``. TESTS:: sage: A = J0(11) sage: G = A.torsion_subgroup(2) sage: TestSuite(G).run() # long time """ from sage.categories.category import Category from sage.categories.fields import Fields from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.modules import Modules from .abvar import is_ModularAbelianVariety if field_of_definition not in Fields(): raise TypeError("field_of_definition must be a field") if not is_ModularAbelianVariety(abvar): raise TypeError("abvar must be a modular abelian variety") category = Category.join((Modules(ZZ), FiniteEnumeratedSets())) Module.__init__(self, ZZ, category=category) self.__abvar = abvar self.__field_of_definition = field_of_definition
def __init__(self, cartan_type, prefix, finite=True): r""" EXAMPLES:: sage: from sage.combinat.root_system.fundamental_group import FundamentalGroupOfExtendedAffineWeylGroup sage: F = FundamentalGroupOfExtendedAffineWeylGroup(['A',3,1]) sage: F in Groups().Commutative().Finite() True sage: TestSuite(F).run() """ def leading_support(beta): r""" Given a dictionary with one key, return this key """ supp = beta.support() assert len(supp) == 1 return supp[0] self._cartan_type = cartan_type self._prefix = prefix special_node = cartan_type.special_node() self._special_nodes = cartan_type.special_nodes() # initialize dictionaries with the entries for the # distinguished special node # dictionary of inverse elements inverse_dict = {} inverse_dict[special_node] = special_node # dictionary for the action of special automorphisms by # permutations of the affine Dynkin nodes auto_dict = {} for i in cartan_type.index_set(): auto_dict[special_node, i] = i # dictionary for the finite Weyl component of the special automorphisms reduced_words_dict = {} reduced_words_dict[0] = tuple([]) if cartan_type.dual().is_untwisted_affine(): # this combines the computations for an untwisted affine # type and its affine dual cartan_type = cartan_type.dual() if cartan_type.is_untwisted_affine(): cartan_type_classical = cartan_type.classical() I = [i for i in cartan_type_classical.index_set()] Q = RootSystem(cartan_type_classical).root_lattice() alpha = Q.simple_roots() omega = RootSystem( cartan_type_classical).weight_lattice().fundamental_weights() W = Q.weyl_group(prefix="s") for i in self._special_nodes: if i == special_node: continue antidominant_weight, reduced_word = omega[ i].to_dominant_chamber(reduced_word=True, positive=False) reduced_words_dict[i] = tuple(reduced_word) w0i = W.from_reduced_word(reduced_word) idual = leading_support(-antidominant_weight) inverse_dict[i] = idual auto_dict[i, special_node] = i for j in I: if j == idual: auto_dict[i, j] = special_node else: auto_dict[i, j] = leading_support(w0i.action(alpha[j])) self._action = Family( self._special_nodes, lambda i: Family(cartan_type.index_set(), lambda j: auto_dict[i, j])) self._dual_node = Family(self._special_nodes, inverse_dict.__getitem__) self._reduced_words = Family(self._special_nodes, reduced_words_dict.__getitem__) if finite: cat = Category.join( (Groups().Commutative().Finite(), EnumeratedSets())) else: cat = Groups().Commutative().Infinite() Parent.__init__(self, category=cat)
def __init__(self, order, cache=None, category=None): """ Create with the command IntegerModRing(order) INPUT: - ``order`` - an integer 1 - ``category`` - a subcategory of ``CommutativeRings()`` (the default) (currently only available for subclasses) OUTPUT: - ``IntegerModRing`` - the ring of integers modulo N. EXAMPLES: First we compute with integers modulo `29`. :: sage: FF = IntegerModRing(29) sage: FF Ring of integers modulo 29 sage: FF.category() Join of Category of commutative rings and Category of subquotients of monoids and Category of quotients of semigroups and Category of finite enumerated sets sage: FF.is_field() True sage: FF.characteristic() 29 sage: FF.order() 29 sage: gens = FF.unit_gens() sage: a = gens[0] sage: a 2 sage: a.is_square() False sage: def pow(i): return a**i sage: [pow(i) for i in range(16)] [1, 2, 4, 8, 16, 3, 6, 12, 24, 19, 9, 18, 7, 14, 28, 27] sage: TestSuite(FF).run() We have seen above that an integer mod ring is, by default, not initialised as an object in the category of fields. However, one can force it to be. Moreover, testing containment in the category of fields my re-initialise the category of the integer mod ring:: sage: F19 = IntegerModRing(19, category = Fields()) sage: F19.category().is_subcategory(Fields()) True sage: F23 = IntegerModRing(23) sage: F23.category().is_subcategory(Fields()) False sage: F23 in Fields() True sage: F23.category().is_subcategory(Fields()) True sage: TestSuite(F19).run() sage: TestSuite(F23).run() Next we compute with the integers modulo `16`. :: sage: Z16 = IntegerModRing(16) sage: Z16.category() Join of Category of commutative rings and Category of subquotients of monoids and Category of quotients of semigroups and Category of finite enumerated sets sage: Z16.is_field() False sage: Z16.order() 16 sage: Z16.characteristic() 16 sage: gens = Z16.unit_gens() sage: gens [15, 5] sage: a = gens[0] sage: b = gens[1] sage: def powa(i): return a**i sage: def powb(i): return b**i sage: gp_exp = FF.unit_group_exponent() sage: gp_exp 28 sage: [powa(i) for i in range(15)] [1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1] sage: [powb(i) for i in range(15)] [1, 5, 9, 13, 1, 5, 9, 13, 1, 5, 9, 13, 1, 5, 9] sage: a.multiplicative_order() 2 sage: b.multiplicative_order() 4 sage: TestSuite(Z16).run() Saving and loading:: sage: R = Integers(100000) sage: TestSuite(R).run() # long time (17s on sage.math, 2011) Testing ideals and quotients:: sage: Z10 = Integers(10) sage: I = Z10.principal_ideal(0) sage: Z10.quotient(I) == Z10 True sage: I = Z10.principal_ideal(2) sage: Z10.quotient(I) == Z10 False sage: I.is_prime() True """ order = ZZ(order) if order <= 0: raise ZeroDivisionError, "order must be positive" self.__order = order self._pyx_order = integer_mod.NativeIntStruct(order) self.__unit_group_exponent = None self.__factored_order = None self.__factored_unit_order = None if category is None: from sage.categories.commutative_rings import CommutativeRings from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.category import Category category = Category.join( [CommutativeRings(), FiniteEnumeratedSets()]) # category = default_category # If the category is given then we trust that is it right. # Give the generator a 'name' to make quotients work. The # name 'x' is used because it's also used for the ring of # integers: see the __init__ method for IntegerRing_class in # sage/rings/integer_ring.pyx. quotient_ring.QuotientRing_generic.__init__(self, ZZ, ZZ.ideal(order), names=('x', ), category=category) # Calling ParentWithGens is not needed, the job is done in # the quotient ring initialisation. #ParentWithGens.__init__(self, self, category = category) # We want that the ring is its own base ring. self._base = self if cache is None: cache = order < 500 if cache: self._precompute_table() self._zero_element = integer_mod.IntegerMod(self, 0) self._one_element = integer_mod.IntegerMod(self, 1)
def __init_extra__(self): """ Declare the canonical coercion from ``self.base_ring()`` to ``self``, if there has been none before. EXAMPLES:: sage: A = AlgebrasWithBasis(QQ).example(); A An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field sage: coercion_model = sage.structure.element.get_coercion_model() sage: coercion_model.discover_coercion(QQ, A) (Generic morphism: From: Rational Field To: An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field, None) sage: A(1) # indirect doctest B[word: ] TESTS: Ensure that :trac:`28328` is fixed and that non-associative algebras are supported:: sage: class Foo(CombinatorialFreeModule): ....: def one(self): ....: return self.monomial(0) sage: from sage.categories.magmatic_algebras \ ....: import MagmaticAlgebras sage: C = MagmaticAlgebras(QQ).WithBasis().Unital() sage: F = Foo(QQ,(1,),category=C) sage: F(0) 0 sage: F(3) 3*B[0] """ # If self has an attribute _no_generic_basering_coercion # set to True, then this declaration is skipped. # This trick, introduced in #11900, is used in # sage.matrix.matrix_space.py and # sage.rings.polynomial.polynomial_ring. # It will hopefully be refactored into something more # conceptual later on. if getattr(self, '_no_generic_basering_coercion', False): return base_ring = self.base_ring() if base_ring is self: # There are rings that are their own base rings. No need to register that. return if self._is_coercion_cached(base_ring): # We will not use any generic stuff, since a (presumably) better conversion # has already been registered. return # Pick a homset for the morphism to live in... if self in Rings(): # The algebra is associative, and thus a ring. The # base ring is also a ring. Everything is OK. H = Hom(base_ring, self, Rings()) else: # If the algebra isn't associative, we would like to # use the category of unital magmatic algebras (which # are not necessarily associative) instead. But, # unfortunately, certain important rings like QQ # aren't in that category. As a result, we have to use # something weaker. cat = Magmas().Unital() cat = Category.join([cat, CommutativeAdditiveGroups()]) cat = cat.Distributive() H = Hom(base_ring, self, cat) # We need to register a coercion from the base ring to self. # # There is a generic method from_base_ring(), that just does # multiplication with the multiplicative unit. However, the # unit is constructed repeatedly, which is slow. # So, if the unit is available *now*, then we can create a # faster coercion map. # # This only applies for the generic from_base_ring() method. # If there is a specialised from_base_ring(), then it should # be used unconditionally. generic_from_base_ring = self.category( ).parent_class.from_base_ring if type(self).from_base_ring != generic_from_base_ring: # Custom from_base_ring() use_from_base_ring = True if isinstance(generic_from_base_ring, lazy_attribute): # If the category implements from_base_ring() as lazy # attribute, then we always use it. # This is for backwards compatibility, see Trac #25181 use_from_base_ring = True else: try: one = self.one() use_from_base_ring = False except (NotImplementedError, AttributeError, TypeError): # The unit is not available, yet. But there are cases # in which it will be available later. So, we use # the generic from_base_ring() after all. use_from_base_ring = True mor = None if use_from_base_ring: mor = SetMorphism(function=self.from_base_ring, parent=H) else: # We have the multiplicative unit, so implement the # coercion from the base ring as multiplying with that. # # But first we check that it actually works. If not, # then the generic implementation of from_base_ring() # would fail as well so we don't use it. try: if one._lmul_(base_ring.an_element()) is not None: # There are cases in which lmul returns None, # which means that it's not implemented. # One example: Hecke algebras. mor = SetMorphism(function=one._lmul_, parent=H) except (NotImplementedError, AttributeError, TypeError): pass if mor is not None: try: self.register_coercion(mor) except AssertionError: pass
def category_of(cls, category, *args): """ Return the homsets category of ``category``. This classmethod centralizes the construction of all homset categories. The ``cls`` and ``args`` arguments below are essentially unused. Their purpose is solely to let the code deviate as little as possible from the generic implementation of this method: :meth:`FunctorialConstructionCategory.category_of`. The reason for this deviation is that, unlike in the other functorial constructions which are covariant, we recurse only on *full* supercategories; then, we need a special treatment for the base case were a category neither defines the ``Homsets`` construction, nor inherits it from its full supercategories. INPUT: - ``cls`` -- :class:`HomsetsCategory` or a subclass thereof - ``category`` -- a category `Cat` - ``*args`` -- (unused) EXAMPLES: If ``category`` implements a ``Homsets`` class, then this class is used to build the homset category:: sage: from sage.categories.homsets import HomsetsCategory sage: H = HomsetsCategory.category_of(Modules(ZZ)); H Category of homsets of modules over Integer Ring sage: type(H) <class 'sage.categories.modules.Modules.Homsets_with_category'> Otherwise, if ``category`` has one or more full super categories, then the join of their respective homsets category is returned. In this example, the join consists of a single category:: sage: C = Modules(ZZ).WithBasis().FiniteDimensional() sage: C.full_super_categories() [Category of modules with basis over Integer Ring, Category of finite dimensional modules over Integer Ring] sage: H = HomsetsCategory.category_of(C); H Category of homsets of modules with basis over Integer Ring sage: type(H) <class 'sage.categories.modules_with_basis.ModulesWithBasis.Homsets_with_category'> As a last resort, a :class:`HomsetsOf` of the categories forming the structure of ``self`` is constructed:: sage: H = HomsetsCategory.category_of(Magmas()); H Category of homsets of magmas sage: type(H) <class 'sage.categories.homsets.HomsetsOf_with_category'> sage: HomsetsCategory.category_of(Rings()) Category of homsets of unital magmas and additive unital additive magmas """ functor_category = getattr(category.__class__, cls._functor_category) if isinstance(functor_category, type) and issubclass(functor_category, Category): return functor_category(category, *args) elif category.full_super_categories(): return cls.default_super_categories(category, *args) else: return HomsetsOf(Category.join(category.structure()))
def _coerce_map_from_base_ring(self): """ Return a suitable coercion map from the base ring of ``self``. TESTS:: sage: A = cartesian_product((QQ['z'],)); A The Cartesian product of (Univariate Polynomial Ring in z over Rational Field,) sage: A.base_ring() Rational Field sage: A._coerce_map_from_base_ring() Generic morphism: From: Rational Field To: The Cartesian product of (Univariate Polynomial Ring in z over Rational Field,) Check that :trac:`29312` is fixed:: sage: F.<x,y,z> = FreeAlgebra(QQ, implementation='letterplace') sage: F._coerce_map_from_base_ring() Generic morphism: From: Rational Field To: Free Associative Unital Algebra on 3 generators (x, y, z) over Rational Field """ base_ring = self.base_ring() # Pick a homset for the morphism to live in... if self in Rings(): # The algebra is associative, and thus a ring. The # base ring is also a ring. Everything is OK. H = Hom(base_ring, self, Rings()) else: # If the algebra isn't associative, we would like to # use the category of unital magmatic algebras (which # are not necessarily associative) instead. But, # unfortunately, certain important rings like QQ # aren't in that category. As a result, we have to use # something weaker. cat = Magmas().Unital() cat = Category.join([cat, CommutativeAdditiveGroups()]) cat = cat.Distributive() H = Hom(base_ring, self, cat) # We need to construct a coercion from the base ring to self. # # There is a generic method from_base_ring(), that just does # multiplication with the multiplicative unit. However, the # unit is constructed repeatedly, which is slow. # So, if the unit is available *now*, then we can create a # faster coercion map. # # This only applies for the generic from_base_ring() method. # If there is a specialised from_base_ring(), then it should # be used unconditionally. generic_from_base_ring = self.category( ).parent_class.from_base_ring from_base_ring = self.from_base_ring # bound method if from_base_ring.__func__ != generic_from_base_ring: # Custom from_base_ring() use_from_base_ring = True elif isinstance(generic_from_base_ring, lazy_attribute): # If the category implements from_base_ring() as lazy # attribute, then we always use it. # This is for backwards compatibility, see Trac #25181 use_from_base_ring = True else: try: one = self.one() use_from_base_ring = False except (NotImplementedError, AttributeError, TypeError): # The unit is not available, yet. But there are cases # in which it will be available later. So, we use # the generic from_base_ring() after all. use_from_base_ring = True mor = None if use_from_base_ring: mor = SetMorphism(function=from_base_ring, parent=H) else: # We have the multiplicative unit, so implement the # coercion from the base ring as multiplying with that. # # But first we check that it actually works. If not, # then the generic implementation of from_base_ring() # would fail as well so we don't use it. try: if one._lmul_(base_ring.an_element()) is not None: # There are cases in which lmul returns None, # which means that it's not implemented. # One example: Hecke algebras. mor = SetMorphism(function=one._lmul_, parent=H) except (NotImplementedError, AttributeError, TypeError): pass return mor
def __init__(self, cartan_type, prefix, finite=True): r""" EXAMPLES:: sage: from sage.combinat.root_system.fundamental_group import FundamentalGroupOfExtendedAffineWeylGroup sage: F = FundamentalGroupOfExtendedAffineWeylGroup(['A',3,1]) sage: F in Groups().Commutative().Finite() True sage: TestSuite(F).run() """ def leading_support(beta): r""" Given a dictionary with one key, return this key """ supp = beta.support() assert len(supp) == 1 return supp[0] self._cartan_type = cartan_type self._prefix = prefix special_node = cartan_type.special_node() self._special_nodes = cartan_type.special_nodes() # initialize dictionaries with the entries for the distinguished special node # dictionary of inverse elements inverse_dict = {} inverse_dict[special_node] = special_node # dictionary for the action of special automorphisms by permutations of the affine Dynkin nodes auto_dict = {} for i in cartan_type.index_set(): auto_dict[special_node,i] = i # dictionary for the finite Weyl component of the special automorphisms reduced_words_dict = {} reduced_words_dict[0] = tuple([]) if cartan_type.dual().is_untwisted_affine(): # this combines the computations for an untwisted affine type and its affine dual cartan_type = cartan_type.dual() if cartan_type.is_untwisted_affine(): cartan_type_classical = cartan_type.classical() I = [i for i in cartan_type_classical.index_set()] Q = RootSystem(cartan_type_classical).root_lattice() alpha = Q.simple_roots() omega = RootSystem(cartan_type_classical).weight_lattice().fundamental_weights() W = Q.weyl_group(prefix="s") for i in self._special_nodes: if i == special_node: continue antidominant_weight, reduced_word = omega[i].to_dominant_chamber(reduced_word=True, positive=False) reduced_words_dict[i] = tuple(reduced_word) w0i = W.from_reduced_word(reduced_word) idual = leading_support(-antidominant_weight) inverse_dict[i] = idual auto_dict[i,special_node] = i for j in I: if j == idual: auto_dict[i,j] = special_node else: auto_dict[i,j] = leading_support(w0i.action(alpha[j])) self._action = Family(self._special_nodes, lambda i: Family(cartan_type.index_set(), lambda j: auto_dict[i,j])) self._dual_node = Family(self._special_nodes, inverse_dict.__getitem__) self._reduced_words = Family(self._special_nodes, reduced_words_dict.__getitem__) if finite: cat = Category.join((Groups().Commutative().Finite(),EnumeratedSets())) else: cat = Groups().Commutative().Infinite() Parent.__init__(self, category = cat)
def __init__(self, order, cache=None, category=None): """ Create with the command IntegerModRing(order) INPUT: - ``order`` - an integer 1 - ``category`` - a subcategory of ``CommutativeRings()`` (the default) (currently only available for subclasses) OUTPUT: - ``IntegerModRing`` - the ring of integers modulo N. EXAMPLES: First we compute with integers modulo `29`. :: sage: FF = IntegerModRing(29) sage: FF Ring of integers modulo 29 sage: FF.category() Join of Category of commutative rings and Category of subquotients of monoids and Category of quotients of semigroups and Category of finite enumerated sets sage: FF.is_field() True sage: FF.characteristic() 29 sage: FF.order() 29 sage: gens = FF.unit_gens() sage: a = gens[0] sage: a 2 sage: a.is_square() False sage: def pow(i): return a**i sage: [pow(i) for i in range(16)] [1, 2, 4, 8, 16, 3, 6, 12, 24, 19, 9, 18, 7, 14, 28, 27] sage: TestSuite(FF).run() We have seen above that an integer mod ring is, by default, not initialised as an object in the category of fields. However, one can force it to be. Moreover, testing containment in the category of fields my re-initialise the category of the integer mod ring:: sage: F19 = IntegerModRing(19, category = Fields()) sage: F19.category().is_subcategory(Fields()) True sage: F23 = IntegerModRing(23) sage: F23.category().is_subcategory(Fields()) False sage: F23 in Fields() True sage: F23.category().is_subcategory(Fields()) True sage: TestSuite(F19).run() sage: TestSuite(F23).run() Next we compute with the integers modulo `16`. :: sage: Z16 = IntegerModRing(16) sage: Z16.category() Join of Category of commutative rings and Category of subquotients of monoids and Category of quotients of semigroups and Category of finite enumerated sets sage: Z16.is_field() False sage: Z16.order() 16 sage: Z16.characteristic() 16 sage: gens = Z16.unit_gens() sage: gens (15, 5) sage: a = gens[0] sage: b = gens[1] sage: def powa(i): return a**i sage: def powb(i): return b**i sage: gp_exp = FF.unit_group_exponent() sage: gp_exp 28 sage: [powa(i) for i in range(15)] [1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1] sage: [powb(i) for i in range(15)] [1, 5, 9, 13, 1, 5, 9, 13, 1, 5, 9, 13, 1, 5, 9] sage: a.multiplicative_order() 2 sage: b.multiplicative_order() 4 sage: TestSuite(Z16).run() Saving and loading:: sage: R = Integers(100000) sage: TestSuite(R).run() # long time (17s on sage.math, 2011) Testing ideals and quotients:: sage: Z10 = Integers(10) sage: I = Z10.principal_ideal(0) sage: Z10.quotient(I) == Z10 True sage: I = Z10.principal_ideal(2) sage: Z10.quotient(I) == Z10 False sage: I.is_prime() True """ order = ZZ(order) if order <= 0: raise ZeroDivisionError, "order must be positive" self.__order = order self._pyx_order = integer_mod.NativeIntStruct(order) self.__unit_group_exponent = None self.__factored_order = None self.__factored_unit_order = None if category is None: from sage.categories.commutative_rings import CommutativeRings from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.category import Category category = Category.join([CommutativeRings(), FiniteEnumeratedSets()]) # category = default_category # If the category is given then we trust that is it right. # Give the generator a 'name' to make quotients work. The # name 'x' is used because it's also used for the ring of # integers: see the __init__ method for IntegerRing_class in # sage/rings/integer_ring.pyx. quotient_ring.QuotientRing_generic.__init__(self, ZZ, ZZ.ideal(order), names=('x',), category=category) # Calling ParentWithGens is not needed, the job is done in # the quotient ring initialisation. #ParentWithGens.__init__(self, self, category = category) # We want that the ring is its own base ring. self._base = self if cache is None: cache = order < 500 if cache: self._precompute_table() self._zero_element = integer_mod.IntegerMod(self, 0) self._one_element = integer_mod.IntegerMod(self, 1)
def default_super_categories(cls, category): """ Return the default super categories of ``category.Homsets()``. INPUT: - ``cls`` -- the category class for the functor `F` - ``category`` -- a category `Cat` OUTPUT: a category As for the other functorial constructions, if ``category`` implements a nested ``Homsets`` class, this method is used in combination with ``category.Homsets().extra_super_categories()`` to compute the super categories of ``category.Homsets()``. EXAMPLES: If ``category`` has one or more full super categories, then the join of their respective homsets category is returned. In this example, this join consists of a single category:: sage: from sage.categories.homsets import HomsetsCategory sage: from sage.categories.additive_groups import AdditiveGroups sage: C = AdditiveGroups() sage: C.full_super_categories() [Category of additive inverse additive unital additive magmas, Category of additive monoids] sage: H = HomsetsCategory.default_super_categories(C); H Category of homsets of additive monoids sage: type(H) <class 'sage.categories.additive_monoids.AdditiveMonoids.Homsets_with_category'> and, given that nothing specific is currently implemented for homsets of additive groups, ``H`` is directly the category thereof:: sage: C.Homsets() Category of homsets of additive monoids Similarly for rings: a ring homset is just a homset of unital magmas and additive magmas:: sage: Rings().Homsets() Category of homsets of unital magmas and additive unital additive magmas Otherwise, if ``category`` implements a nested class ``Homsets``, this method returns the category of all homsets:: sage: AdditiveMagmas.Homsets <class 'sage.categories.additive_magmas.AdditiveMagmas.Homsets'> sage: HomsetsCategory.default_super_categories(AdditiveMagmas()) Category of homsets which gives one of the super categories of ``category.Homsets()``:: sage: AdditiveMagmas().Homsets().super_categories() [Category of additive magmas, Category of homsets] sage: AdditiveMagmas().AdditiveUnital().Homsets().super_categories() [Category of additive unital additive magmas, Category of homsets] the other coming from ``category.Homsets().extra_super_categories()``:: sage: AdditiveMagmas().Homsets().extra_super_categories() [Category of additive magmas] Finally, as a last resort, this method returns a stub category modelling the homsets of this category:: sage: hasattr(Posets, "Homsets") False sage: H = HomsetsCategory.default_super_categories(Posets()); H Category of homsets of posets sage: type(H) <class 'sage.categories.homsets.HomsetsOf_with_category'> sage: Posets().Homsets() Category of homsets of posets TESTS:: sage: Objects().Homsets().super_categories() [Category of homsets] sage: Sets().Homsets().super_categories() [Category of homsets] sage: (Magmas() & Posets()).Homsets().super_categories() [Category of homsets] """ if category.full_super_categories(): return Category.join([ getattr(cat, cls._functor_category)() for cat in category.full_super_categories() ]) else: functor_category = getattr(category.__class__, cls._functor_category) if isinstance(functor_category, type) and issubclass( functor_category, Category): return Homsets() else: return HomsetsOf(Category.join(category.structure()))
def default_super_categories(cls, category): """ Return the default super categories of ``category.Homsets()``. INPUT: - ``cls`` -- the category class for the functor `F` - ``category`` -- a category `Cat` OUTPUT: a category As for the other functorial constructions, if ``category`` implements a nested ``Homsets`` class, this method is used in combination with ``category.Homsets().extra_super_categories()`` to compute the super categories of ``category.Homsets()``. EXAMPLES: If ``category`` has one or more full super categories, then the join of their respective homsets category is returned. In this example, this join consists of a single category:: sage: from sage.categories.homsets import HomsetsCategory sage: from sage.categories.additive_groups import AdditiveGroups sage: C = AdditiveGroups() sage: C.full_super_categories() [Category of additive inverse additive unital additive magmas, Category of additive monoids] sage: H = HomsetsCategory.default_super_categories(C); H Category of homsets of additive monoids sage: type(H) <class 'sage.categories.additive_monoids.AdditiveMonoids.Homsets_with_category'> and, given that nothing specific is currently implemented for homsets of additive groups, ``H`` is directly the category thereof:: sage: C.Homsets() Category of homsets of additive monoids Similarly for rings: a ring homset is just a homset of unital magmas and additive magmas:: sage: Rings().Homsets() Category of homsets of unital magmas and additive unital additive magmas Otherwise, if ``category`` implements a nested class ``Homsets``, this method returns the category of all homsets:: sage: AdditiveMagmas.Homsets <class 'sage.categories.additive_magmas.AdditiveMagmas.Homsets'> sage: HomsetsCategory.default_super_categories(AdditiveMagmas()) Category of homsets which gives one of the super categories of ``category.Homsets()``:: sage: AdditiveMagmas().Homsets().super_categories() [Category of additive magmas, Category of homsets] sage: AdditiveMagmas().AdditiveUnital().Homsets().super_categories() [Category of additive unital additive magmas, Category of homsets] the other coming from ``category.Homsets().extra_super_categories()``:: sage: AdditiveMagmas().Homsets().extra_super_categories() [Category of additive magmas] Finally, as a last resort, this method returns a stub category modelling the homsets of this category:: sage: hasattr(Posets, "Homsets") False sage: H = HomsetsCategory.default_super_categories(Posets()); H Category of homsets of posets sage: type(H) <class 'sage.categories.homsets.HomsetsOf_with_category'> sage: Posets().Homsets() Category of homsets of posets TESTS:: sage: Objects().Homsets().super_categories() [Category of homsets] sage: Sets().Homsets().super_categories() [Category of homsets] sage: (Magmas() & Posets()).Homsets().super_categories() [Category of homsets] """ if category.full_super_categories(): return Category.join([getattr(cat, cls._functor_category)() for cat in category.full_super_categories()]) else: functor_category = getattr(category.__class__, cls._functor_category) if isinstance(functor_category, type) and issubclass(functor_category, Category): return Homsets() else: return HomsetsOf(Category.join(category.structure()))