From 3491e78b191e6b555088b22d40952097371f401a Mon Sep 17 00:00:00 2001 From: Frederic Chapoton Date: Fri, 30 Aug 2013 18:37:45 +0000 Subject: [PATCH] imported patch trac_9280_nomodule.patch --- src/sage/categories/algebras_with_basis.py | 5 +- .../examples/graded_algebras_with_basis.py | 308 ++++++++++++++++++ .../examples/hopf_algebras_with_basis.py | 2 +- .../categories/graded_algebras_with_basis.py | 106 +++++- 4 files changed, 418 insertions(+), 3 deletions(-) create mode 100644 src/sage/categories/examples/graded_algebras_with_basis.py diff --git a/src/sage/categories/algebras_with_basis.py b/src/sage/categories/algebras_with_basis.py index ccd813a6fcd..99d5a188cd7 100644 --- a/src/sage/categories/algebras_with_basis.py +++ b/src/sage/categories/algebras_with_basis.py @@ -109,7 +109,10 @@ def super_categories(self): def example(self, alphabet = ('a','b','c')): """ - Returns an example of algebra with basis:: + Returns an example of algebra with basis as per + :meth:`Category.example `. + + :: sage: AlgebrasWithBasis(QQ).example() An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field diff --git a/src/sage/categories/examples/graded_algebras_with_basis.py b/src/sage/categories/examples/graded_algebras_with_basis.py new file mode 100644 index 00000000000..19d38e5adca --- /dev/null +++ b/src/sage/categories/examples/graded_algebras_with_basis.py @@ -0,0 +1,308 @@ +r""" +Examples of graded algebras with basis +""" +#***************************************************************************** +# Copyright (C) 2010 John H. Palmieri +# +# Distributed under the terms of the GNU General Public License (GPL) +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from sage.misc.cachefunc import cached_method +from sage.categories.all import GradedAlgebrasWithBasis +from sage.combinat.integer_vector_weighted import WeightedIntegerVectors +from sage.combinat.free_module import CombinatorialFreeModule + +class GradedPolynomialAlgebra(CombinatorialFreeModule): + r""" + This class illustrates an implementation of a graded algebra + with basis: a polynomial algebra on several generators of varying + degrees. + + INPUT: + + - ``R`` - base ring + + - ``generators`` - list of strings defining the polynomial + generators (optional, default ``("a", "b", "c")``) + + - ``degrees`` - a positive integer or a list of positive integers + (optional, default ``1``). If it is a list of positive + integers, then it must be of the same length as ``generators``, + and its `i`-th entry specifies the degree of the `i`-th + generator. If it is an integer `d`, then every generator is + given degree `d`. + + .. note:: + + This is not a very full-featured implementation of a + polynomial algebra; you can add and multiply elements and + compute their degrees, but not much else. For real + calculations, use Sage's ``PolynomialRing`` construction. + + The implementation involves the following: + + - *A data type for the algebra.* In this case, the algebra is a free module + with a basis consisting of monomials in the generators. So it is + constructed as a :class:`CombinatorialFreeModule + `. + This means that it inherits all of the functionality associated with + such objects, including operations such as addition of elements. + + - *Objects indexing the basis elements.* A basis of the algebra consists of + monomials in the generators, so each monomial can be represented as + a vector of non-negative integers corresponding to the exponents of the + generators. Luckily, such vectors can be generated by the function + ``WeightedIntegerVectors``, so we use these to index the basis elements. + + :: + + sage: A = GradedAlgebrasWithBasis(QQ).example(); A + An example of a graded algebra with basis: the polynomial algebra on generators ('a', 'b', 'c') of degrees (1, 1, 1) over Rational Field + sage: A.basis().keys() + Integer vectors weighted by [1, 1, 1] + + Since ``WeightedIntegerVectors`` is a graded enumerated set, this algebra + inherits methods that allow us to extract the elements in the basis that + are of degree `2` as well as homogeneous components:: + + sage: A.basis().keys().category() + Join of Category of infinite enumerated sets and Category of sets with grading + sage: A.basis(degree=2).list() + [c^{2}, bc, ac, b^{2}, ab, a^{2}] + sage: A.homogeneous_component(degree=2) # todo: what this should return? + Free module generated by Integer vectors of 2 weighted by [1, 1, 1] over Rational Field + + - *Generators of the algebra.* The method :meth:`algebra_generators` must + return a set of elements that generator the algebra:: + + sage: A.algebra_generators() + Family (a, b, c) + + - *Identity element.* Since the identity element is an element of the basis + (the monomial whose exponents are all zero), we define the method + :meth:`one_on_basis` to return the zero vector, since that is the object + that indexes the basis element corresponding to the identity element. + The method :meth:`one` uses :meth:`one_on_basis` to compute the identity + element:: + + sage: A.one_basis() + (0, 0, 0) + sage: A.one() + 1 + + - *Methods describing the algebra structure*. For dealing with basis + elements, the following methods need to be specified: + + - :meth:`product_on_basis` -- describing how the compute the product of + two basis elements; + - :meth:`degree_on_basis` -- describing how to compute the degree of + an element of the basis; + - :meth:`_repr_term` (optional) -- controls how a basis element will be + displayed on the screen. + + These methods form the building blocks for other automatically-defined + methods. For instance, the method :meth:`product`, which computes the + product of two arbitrary elements of the algebra, is constructed from + :meth:`product_on_basis` by extending it linearly. + + :: + + sage: A.product_on_basis((1,0,1), (0,0,2)) + ac^{3} + sage: (a,b,c) = A.algebra_generators() + sage: a * (1-b)^2 * c + ac - 2*abc + ab^{2}c + + The method :meth:`degree` uses :meth:`degree_on_basis` to compute the + degree for an arbitrary linear combination of basis elements. Similarly, + the method :meth:`is_homogeneous` will also use :meth:`degree_on_basis`. + + sage: A.degree_on_basis((1,0,1)) + 2 + sage: (a + 3*b - c).degree() + 1 + sage: (3*a).is_homogeneous() + True + sage: (a^3 - b^2).is_homogeneous() + False + sage: ((a + c)^2).is_homogeneous() + True + + The method :meth:`_repr_term` controls how a basis element will be + displayed on the screen, which automatically produces the print + representation for arbitrary elements of the algebra. + + sage: A._repr_term((1,0,1)) + 'ac' + + """ + def __init__(self, base_ring, generators=("a", "b", "c"), degrees=1): + """ + EXAMPLES:: + + sage: A = GradedAlgebrasWithBasis(QQ).example(); A + An example of a graded algebra with basis: the polynomial algebra on generators ('a', 'b', 'c') of degrees (1, 1, 1) over Rational Field + sage: A = GradedAlgebrasWithBasis(QQ).example(generators=("x", "y"), degrees=(2, 3)); A + An example of a graded algebra with basis: the polynomial algebra on generators ('x', 'y') of degrees (2, 3) over Rational Field + sage: TestSuite(A).run() + """ + from sage.rings.all import Integer + self._generators = generators + try: + Integer(degrees) + if degrees <= 0: + raise ValueError, "Degrees must be positive integers" + degrees = [degrees] * len(generators) + except TypeError: + # assume degrees is a list or tuple already. + if len(degrees) != len(generators): + raise ValueError, "List of generators and degrees must have the same length" + try: + for d in degrees: + assert Integer(d) > 0 + except (TypeError, AssertionError): + raise ValueError, "Degrees must be positive integers" + self._degrees = tuple(degrees) + CombinatorialFreeModule.__init__(self, base_ring, + WeightedIntegerVectors(self._degrees), + category = GradedAlgebrasWithBasis(base_ring)) + + # FIXME: this is currently required, because the implementation of ``basis`` + # in CombinatorialFreeModule overrides that of GradedAlgebrasWithBasis + basis = GradedAlgebrasWithBasis.ParentMethods.__dict__['basis'] + + @cached_method + def one_basis(self): + """ + Returns the integer vector '(0,...,0`), which indexes the one + of this algebra, as per + :meth:`AlgebrasWithBasis.ParentMethods.one_basis` + + EXAMPLES:: + + sage: A = GradedAlgebrasWithBasis(QQ).example() + sage: A.one_basis() + (0, 0, 0) + sage: A.one() + 1 + """ + # return self.basis().keys().subset(0).first() # This is generic + return tuple(self.basis().keys().subset(0).first()) + + def product_on_basis(self, t1, t2): + r""" + Product of basis elements, as per + :meth:`AlgebrasWithBasis.ParentMethods.product_on_basis` + + INPUT: + + - ``t1``, ``t2`` - tuples determining monomials (as the + exponents of the generators) in this algebra + + OUTPUT: the product of the two corresponding monomials, as an + element of ``self``. + + EXAMPLES:: + + sage: A = GradedAlgebrasWithBasis(QQ).example() + sage: A.product_on_basis((1,0,1), (0,0,2)) + ac^{3} + sage: (a,b,c) = A.algebra_generators() + sage: a * (1-b)^2 * c + ac - 2*abc + ab^{2}c + """ + return self.monomial(t1.__class__([a+b for a,b in zip(t1, t2)])) + + def degree_on_basis(self, t): + """ + The degree of the element determined by the tuple ``t`` in + this graded polynomial algebra. + + INPUT: + + - ``t`` -- the index of an element of the basis of this algebra, + i.e. an exponent vector of a monomial, written as a tuple + + Output: an integer, the degree of the corresponding monomial + + EXAMPLES:: + + sage: A = GradedAlgebrasWithBasis(QQ).example(generators=("x", "y"), degrees=(2, 3)) + sage: A.degree_on_basis((1,1)) # x^1 y^1 + 5 + sage: A.degree_on_basis((0,3)) + 9 + sage: type(A.degree_on_basis((0,3))) + + """ + return self.basis().keys().grading(t) + + @cached_method + def algebra_generators(self): + r""" + Returns the generators of this algebra, as per :meth:`Algebras.ParentMethods.algebra_generators`. + + EXAMPLES:: + + sage: A = GradedAlgebrasWithBasis(QQ).example(); A + An example of a graded algebra with basis: the polynomial algebra on generators ('a', 'b', 'c') of degrees (1, 1, 1) over Rational Field + sage: A.algebra_generators() + Family (a, b, c) + """ + from sage.sets.family import Family + L = len(self._generators) + return Family([self.monomial((0,) * i + (1,) + (0,) * (L-i-1)) for i in range(L)]) + + + # The following makes A[n] the same as A.homogeneous_components(n). + # While an homogeneous_components + # method should be implemented for any graded object, whether + # __getitem__ should be defined and whether it should be the same + # as homogeneous_components (or return something else, e.g., an + # element of the algebra as in the case of + # SymmetricFunctions(QQ).schur()), should be decided on a + # case-by-case basis. + __getitem__ = GradedAlgebrasWithBasis.ParentMethods.__dict__['homogeneous_component'] + + def _repr_(self): + """ + Print representation + + EXAMPLES:: + + sage: GradedAlgebrasWithBasis(QQ).example() # indirect doctest + An example of a graded algebra with basis: the polynomial algebra on generators ('a', 'b', 'c') of degrees (1, 1, 1) over Rational Field + """ + return "An example of a graded algebra with basis: the polynomial algebra on generators %s of degrees %s over %s"%(self._generators, self._degrees, self.base_ring()) + + + def _repr_term(self, t): + """ + Print representation for the basis element represented by the + tuple ``t``. This governs the behavior of the print + representation of all elements of the algebra. + + EXAMPLES:: + + sage: A = GradedAlgebrasWithBasis(QQ).example(generators=("B", "H", "d")) + sage: A._repr_term((0,1,2)) + 'Hd^{2}' + sage: A._repr_term((2,3,1)) + 'B^{2}H^{3}d' + """ + if len(t) == 0: + return "0" + if max(t) == 0: + return "1" + s = "" + for e,g in zip(t, self._generators): + if e != 0: + if e != 1: + s += "%s^{%s}" % (g,e) + else: + s += "%s" % g + s = s.strip() + return s + +Example = GradedPolynomialAlgebra diff --git a/src/sage/categories/examples/hopf_algebras_with_basis.py b/src/sage/categories/examples/hopf_algebras_with_basis.py index a2c4a355de6..d06a3777cea 100644 --- a/src/sage/categories/examples/hopf_algebras_with_basis.py +++ b/src/sage/categories/examples/hopf_algebras_with_basis.py @@ -1,5 +1,5 @@ r""" -Examples of algebras with basis +Examples of Hopf algebras with basis """ #***************************************************************************** # Copyright (C) 2008-2009 Nicolas M. Thiery diff --git a/src/sage/categories/graded_algebras_with_basis.py b/src/sage/categories/graded_algebras_with_basis.py index ffc4eb6b3db..886ebf98578 100644 --- a/src/sage/categories/graded_algebras_with_basis.py +++ b/src/sage/categories/graded_algebras_with_basis.py @@ -39,8 +39,112 @@ def super_categories(self): R = self.base_ring() return [GradedModulesWithBasis(R),GradedAlgebras(R), AlgebrasWithBasis(R)] + def example(self, generators = ('a','b','c'), degrees = 1): + """ + Returns an example of a graded algebra with basis as per + :meth:`Category.example `. + + EXAMPLES:: + + sage: GradedAlgebrasWithBasis(QQ).example() + An example of a graded algebra with basis: the polynomial algebra on generators ('a', 'b', 'c') of degrees (1, 1, 1) over Rational Field + + Another set of generators, and their degrees, can be specified + as optional arguments:: + + sage: GradedAlgebrasWithBasis(QQ).example(generators=("x", "z"), degrees=(3, 10)) + An example of a graded algebra with basis: the polynomial algebra on generators ('x', 'z') of degrees (3, 10) over Rational Field + """ + from sage.categories.examples.graded_algebras_with_basis import Example + return Example(self.base_ring(), generators, degrees) + class ParentMethods: - pass + + # TODO: which syntax do we prefer? + # A.basis(degree = 3) + # A.basis().subset(degree=3) + + # This is related to the following design question: + # If F = (f_i)_{i\in I} is a family, should ``F.subset(degree = 3)`` + # be the elements of F of degree 3 or those whose index is of degree 3? + + def basis(self, degree=None): + """ + Returns the basis for (an homogeneous component of) this graded algebra + + INPUT: + + - `degree` -- non negative integer or ``None``, optional (default: ``None``) + + If `degree` is None, returns a basis of the algebra. + Otherwise, returns the basis of the homogeneous component of degree + `degree`. + + EXAMPLES:: + + sage: A = GradedAlgebrasWithBasis(QQ).example(generators=("x", "y"), degrees=(2, 3)) + sage: A.basis(4) + Lazy family (Term map from Integer vectors weighted by [2, 3] to An example of a graded algebra with basis: the polynomial algebra on generators ('x', 'y') of degrees (2, 3) over Rational Field(i))_{i in Integer vectors of 4 weighted by [2, 3]} + sage: A.basis(4) # todo: not implemented (output) + Family (x^{2},) + sage: A.basis(6) # todo: not implemented (output) + Family (y^{2}, x^{3}) + sage: A.basis(-10) # todo: not implemented (output) + Family () + + Without arguments, the full basis is returned:: + + sage: A.basis() + Lazy family (Term map from Integer vectors weighted by [2, 3] to An example of a graded algebra with basis: the polynomial algebra on generators ('x', 'y') of degrees (2, 3) over Rational Field(i))_{i in Integer vectors weighted by [2, 3]} + """ + from sage.sets.family import Family + if degree is None: + return Family(self._basis_keys, self.monomial) + else: + return Family(self._basis_keys.subset(size=degree), self.monomial) + + @cached_method + def homogeneous_component(self, degree): + """ + Returns the degree `degree` homogeneous component of this graded algebra. + + EXAMPLES:: + + sage: A = GradedAlgebrasWithBasis(QQ).example(generators=("x", "y"), degrees=(2, 3)) + sage: A.homogeneous_component(1) + Free module generated by Integer vectors of 1 weighted by [2, 3] over Rational Field + sage: A.homogeneous_component(6) # todo: not implemented (output) + Free module generated by (y^{2}, x^{3}) over Rational Field + + As a shorthand, graded algebras may allow to access their + homogeneous components using square brackets; but this is + not systematically enforced:: + + sage: A[9] + Free module generated by Integer vectors of 9 weighted by [2, 3] over Rational Field + + TODO: + + - How do we want homogeneous components to be printed out? + + - If `A` and `B` are two graded algebras over the same index + set and ground ring, should ``A.homogeneous_component(3)`` + and `B.homogeneous_component(3)`` coincide? Or should they + instead be respectively aware that they are subsets of `A` + and `B`? + """ + from sage.combinat.free_module import CombinatorialFreeModule + M = CombinatorialFreeModule(self.base_ring(), + self.basis().keys().subset(size=degree), + element_class=self.Element) + #M._name = "Free module generated by %s"%(tuple(self.monomial(a) for a in basis),) + return M + + # TODO: degree_on_basis should be an abstract method; write doc and doctests + # from sage.misc.abstract_method import abstract_method + #@abstract_method + #def degree_on_basis(self): + # pass class ElementMethods: def is_homogeneous(self):