• ## sage/categories/category.py

# HG changeset patch
# User F. Chapoton <chapoton@math.univ-lyon1.fr>
# Date 1277423971 25200
# Node ID d78f4b69a715771879ec5b21ca00874e33deba90
# Parent  d0943a747f6dd975386c499f666609c9b1e3d8c5
#11688: an example of a graded module with basis

This patch aims at an improvement of graded modules with basis.

Done:

* Make an example of graded module with basis (using partitions)
diff --git a/sage/categories/category.py b/sage/categories/category.py
 a class Category(UniqueRepresentation, Sag full featured version is available elsewhere in Sage, and should be used insted. Technical note: by default FooBar(...).example() is Technical note: by default FooBar(...).example() is constructed by looking up sage.categories.examples.foo_bar.Example and calling it as Example(category = FooBar). Extra positional or named parameters are also passed down. Categories are welcome to override this. sage.categories.examples.foo_bar.Example and calling it as Example(). Extra positional or named parameters are also passed down. For a category over base ring, the base ring is further passed down as an optional argument. Categories are welcome to override this default implementation. EXAMPLES:: class Category(UniqueRepresentation, Sag cls = module.Example except AttributeError: return NotImplemented # Add the base ring as optional argument if this is a category over base ring # This really should be in Category_over_base_ring.example, # but that would mean duplicating the documentation above. from category_types import Category_over_base_ring if isinstance(self, Category_over_base_ring): # Huh, smelly Run Time Type Checking, isn't it? if "base_ring" not in keywords: keywords["base_ring"]=self.base_ring() return cls(*args, **keywords)
diff --git a/sage/categories/examples/graded_modules_with_basis.py b/sage/categories/examples/graded_modules_with_basis.py
new file mode 100644
 - r""" Examples of graded modules with basis """ #***************************************************************************** #  Copyright (C) 2013 Frederic Chapoton # #  Distributed under the terms of the GNU General Public License (GPL) #                  http://www.gnu.org/licenses/ #***************************************************************************** from sage.categories.graded_modules_with_basis import GradedModulesWithBasis from sage.combinat.free_module import CombinatorialFreeModule from sage.combinat.partition import Partitions class GradedPartitionModule(CombinatorialFreeModule): r""" This class illustrates an implementation of a graded module with basis: the free module over partitions. INPUT: - R - base ring The implementation involves the following: - A choice of how to represent elements.  In this case, the basis elements are partitions. The algebra is constructed as a :class:CombinatorialFreeModule  on the set of partitions, so it inherits all of the methods for such objects, and has operations like addition already defined. :: sage: A = GradedModulesWithBasis(QQ).example() - A basis function - this module is graded by the non-negative integers, so there is a function defined in this module, creatively called :func:basis, which takes an integer d as input and returns a family of partitions representing a basis for the algebra in degree d. :: sage: A.basis(2) Lazy family (Term map from Partitions to An example of a graded module with basis: the free module on partitions over Rational Field(i))_{i in Partitions of the integer 2} sage: A.basis(6)[Partition([3,2,1])] P[3, 2, 1] - If the algebra is called A, then its basis function is stored as A.basis.  Thus the function can be used to find a basis for the degree d piece: essentially, just call A.basis(d).  More precisely, call x for each x in A.basis(d). :: sage: [m for m in A.basis(4)] [P[4], P[3, 1], P[2, 2], P[2, 1, 1], P[1, 1, 1, 1]] - For dealing with basis elements: :meth:degree_on_basis, and :meth:_repr_term. The first of these defines the degree of any monomial, and then the :meth:degree  method for elements -- see the next item -- uses it to compute the degree for a linear combination of monomials.  The last of these determines the print representation for monomials, which automatically produces the print representation for general elements. :: sage: A.degree_on_basis(Partition([4,3])) 7 sage: A._repr_term(Partition([4,3])) 'P[4, 3]' - There is a class for elements, which inherits from :class:CombinatorialFreeModuleElement .  An element is determined by a dictionary whose keys are partitions and whose corresponding values are the coefficients.  The class implements two things: an :meth:is_homogeneous  method and a :meth:degree  method. :: sage: p = A.monomial(Partition([3,2,1])); p P[3, 2, 1] sage: p.is_homogeneous() True sage: p.degree() 6 """ def __init__(self, base_ring): """ EXAMPLES:: sage: A = GradedModulesWithBasis(QQ).example(); A An example of a graded module with basis: the free module on partitions over Rational Field sage: TestSuite(A).run() """ CombinatorialFreeModule.__init__(self, base_ring, Partitions(), category=GradedModulesWithBasis(base_ring)) # FIXME: this is currently required, because the implementation of basis # in CombinatorialFreeModule overrides that of GradedModulesWithBasis basis = GradedModulesWithBasis.ParentMethods.__dict__['basis'] # This could be a default implementation def degree_on_basis(self, t): """ The degree of the element determined by the partition t in this graded module. INPUT: - t -- the index of an element of the basis of this module, i.e. a partition OUTPUT: an integer, the degree of the corresponding basis element EXAMPLES:: sage: A = GradedModulesWithBasis(QQ).example() sage: A.degree_on_basis(Partition((2,1))) 3 sage: A.degree_on_basis(Partition((4,2,1,1,1,1))) 10 sage: type(A.degree_on_basis(Partition((1,1)))) """ return t.size() def _repr_(self): """ Print representation EXAMPLES:: sage: GradedModulesWithBasis(QQ).example()  # indirect doctest An example of a graded module with basis: the free module on partitions over Rational Field """ return "An example of a graded module with basis: the free module on partitions over %s" % self.base_ring() def _repr_term(self, t): """ Print representation for the basis element represented by the partition t. This governs the behavior of the print representation of all elements of the algebra. EXAMPLES:: sage: A = GradedModulesWithBasis(QQ).example() sage: A._repr_term(Partition((4,2,1))) 'P[4, 2, 1]' """ return 'P' + t._repr_() Example = GradedPartitionModule
diff --git a/sage/categories/graded_modules_with_basis.py b/sage/categories/graded_modules_with_basis.py
 a from category_types import Category_over from sage.categories.all import GradedModules, ModulesWithBasis from sage.misc.cachefunc import cached_method class GradedModulesWithBasis(Category_over_base_ring): """ The category of graded modules with a distinguished basis class GradedModulesWithBasis(Category_ov return [GradedModules(R), ModulesWithBasis(R)] 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, d=None): """ Returns the basis for (an homogeneous component of) this graded module INPUT: - d -- non negative integer or None, optional (default: None) If d is None, returns a basis of the module. Otherwise, returns the basis of the homogeneous component of degree d. EXAMPLES:: sage: A = GradedModulesWithBasis(ZZ).example() sage: A.basis(4) Lazy family (Term map from Partitions to An example of a graded module with basis: the free module on partitions over Integer Ring(i))_{i in Partitions of the integer 4} Without arguments, the full basis is returned:: sage: A.basis() Lazy family (Term map from Partitions to An example of a graded module with basis: the free module on partitions over Integer Ring(i))_{i in Partitions} sage: A.basis() Lazy family (Term map from Partitions to An example of a graded module with basis: the free module on partitions over Integer Ring(i))_{i in Partitions} """ from sage.sets.family import Family if d is None: return Family(self._basis_keys, self.monomial) else: return Family(self._basis_keys.subset(size=d), self.monomial) class ElementMethods: pass def is_homogeneous(self): """ Return whether this element is homogeneous. EXAMPLES:: sage: A = GradedModulesWithBasis(ZZ).example() sage: x=A(Partition((3,2,1))) sage: y=A(Partition((4,4,1))) sage: z=A(Partition((2,2,2))) sage: (3*x).is_homogeneous() True sage: (x - y).is_homogeneous() False sage: (x+2*z).is_homogeneous() True """ degree_on_basis = self.parent().degree_on_basis degree = None for m in self.support(): if degree is None: degree = degree_on_basis(m) else: if degree != degree_on_basis(m): return False return True def degree(self): """ The degree of this element in the graded module. .. note:: This raises an error if the element is not homogeneous. Another implementation option would be to return the maximum of the degrees of the homogeneous summands. EXAMPLES:: sage: A = GradedModulesWithBasis(ZZ).example() sage: x = A(Partition((3,2,1))) sage: y = A(Partition((4,4,1))) sage: z = A(Partition((2,2,2))) sage: x.degree() 6 sage: (x + 2*z).degree() 6 sage: (y - x).degree() Traceback (most recent call last): ... ValueError: Element is not homogeneous. """ if not self.support(): raise ValueError("The zero element does not have a well-defined degree.") if self.is_homogeneous(): return self.parent().degree_on_basis(self.leading_support()) else: raise ValueError("Element is not homogeneous.") def homogeneous_component(self, n): """ Return the homogeneous component of degree n of this element. EXAMPLES:: sage: A = GradedModulesWithBasis(ZZ).example() sage: x = A.an_element(); x 2*P[] + 2*P[1] + 3*P[2] sage: x.homogeneous_component(-1) 0 sage: x.homogeneous_component(0) 2*P[] sage: x.homogeneous_component(1) 2*P[1] sage: x.homogeneous_component(2) 3*P[2] sage: x.homogeneous_component(3) 0 TESTS: Check that this really return A.zero() and not a plain 0:: sage: x.homogeneous_component(3).parent() is A True """ degree_on_basis = self.parent().degree_on_basis return self.parent().sum_of_terms((i, c) for (i, c) in self if degree_on_basis(i) == n) def truncate(self, n): """ Return the sum of the homogeneous components of degree < n of this element EXAMPLES:: sage: A = GradedModulesWithBasis(ZZ).example() sage: x = A.an_element(); x 2*P[] + 2*P[1] + 3*P[2] sage: x.truncate(0) 0 sage: x.truncate(1) 2*P[] sage: x.truncate(2) 2*P[] + 2*P[1] sage: x.truncate(3) 2*P[] + 2*P[1] + 3*P[2] TESTS: Check that this really return A.zero() and not a plain 0:: sage: x.truncate(0).parent() is A True """ degree_on_basis = self.parent().degree_on_basis return self.parent().sum_of_terms((i, c) for (i, c) in self if degree_on_basis(i) < n)