Modules With Basis#
AUTHORS:
Nicolas M. Thiery (2008-2014): initial revision, axiomatization
Jason Bandlow and Florent Hivert (2010): Triangular Morphisms
Christian Stump (2010): github issue #9648 module_morphism’s to a wider class of codomains
- class sage.categories.modules_with_basis.ModulesWithBasis(base_category)#
Bases:
CategoryWithAxiom_over_base_ring
The category of modules with a distinguished basis.
The elements are represented by expanding them in the distinguished basis. The morphisms are not required to respect the distinguished basis.
EXAMPLES:
sage: ModulesWithBasis(ZZ) Category of modules with basis over Integer Ring sage: ModulesWithBasis(ZZ).super_categories() [Category of modules over Integer Ring]
If the base ring is actually a field, this constructs instead the category of vector spaces with basis:
sage: ModulesWithBasis(QQ) Category of vector spaces with basis over Rational Field sage: ModulesWithBasis(QQ).super_categories() [Category of modules with basis over Rational Field, Category of vector spaces over Rational Field]
Let \(X\) and \(Y\) be two modules with basis. We can build \(Hom(X,Y)\):
sage: X = CombinatorialFreeModule(QQ, [1,2]); X.__custom_name = "X" # optional - sage.modules sage: Y = CombinatorialFreeModule(QQ, [3,4]); Y.__custom_name = "Y" # optional - sage.modules sage: H = Hom(X, Y); H # optional - sage.modules Set of Morphisms from X to Y in Category of finite dimensional vector spaces with basis over Rational Field
The simplest morphism is the zero map:
sage: H.zero() # todo: move this test into module once we have an example # optional - sage.modules Generic morphism: From: X To: Y
which we can apply to elements of \(X\):
sage: x = X.monomial(1) + 3 * X.monomial(2) # optional - sage.modules sage: H.zero()(x) # optional - sage.modules 0
EXAMPLES:
We now construct a more interesting morphism by extending a function by linearity:
sage: phi = H(on_basis=lambda i: Y.monomial(i + 2)); phi # optional - sage.modules Generic morphism: From: X To: Y sage: phi(x) # optional - sage.modules B[3] + 3*B[4]
We can retrieve the function acting on indices of the basis:
sage: f = phi.on_basis() # optional - sage.modules sage: f(1), f(2) # optional - sage.modules (B[3], B[4])
\(Hom(X,Y)\) has a natural module structure (except for the zero, the operations are not yet implemented though). However since the dimension is not necessarily finite, it is not a module with basis; but see
FiniteDimensionalModulesWithBasis
andGradedModulesWithBasis
:sage: H in ModulesWithBasis(QQ), H in Modules(QQ) # optional - sage.modules (False, True)
Some more playing around with categories and higher order homsets:
sage: H.category() # optional - sage.modules Category of homsets of modules with basis over Rational Field sage: Hom(H, H).category() # optional - sage.modules Category of endsets of homsets of modules with basis over Rational Field
Todo
End(X)
is an algebra.Note
This category currently requires an implementation of an element method
support
. Once github issue #18066 is merged, an implementation of anitems
method will be required.- class CartesianProducts(category, *args)#
Bases:
CartesianProductsCategory
The category of modules with basis constructed by Cartesian products of modules with basis.
- class ParentMethods#
Bases:
object
- extra_super_categories()#
EXAMPLES:
sage: ModulesWithBasis(QQ).CartesianProducts().extra_super_categories() [Category of vector spaces with basis over Rational Field] sage: ModulesWithBasis(QQ).CartesianProducts().super_categories() [Category of Cartesian products of modules with basis over Rational Field, Category of vector spaces with basis over Rational Field, Category of Cartesian products of vector spaces over Rational Field]
- class DualObjects(category, *args)#
Bases:
DualObjectsCategory
- extra_super_categories()#
EXAMPLES:
sage: ModulesWithBasis(ZZ).DualObjects().extra_super_categories() [Category of modules over Integer Ring] sage: ModulesWithBasis(QQ).DualObjects().super_categories() [Category of duals of vector spaces over Rational Field, Category of duals of modules with basis over Rational Field]
- class ElementMethods#
Bases:
object
- coefficient(m)#
Return the coefficient of
m
inself
and raise an error ifm
is not in the basis indexing set.INPUT:
m
– a basis index of the parent ofself
OUTPUT:
The
B[m]
-coordinate ofself
with respect to the basisB
. Here,B
denotes the given basis of the parent ofself
.EXAMPLES:
sage: s = CombinatorialFreeModule(QQ, Partitions()) # optional - sage.combinat sage.modules sage: z = s([4]) - 2*s([2,1]) + s([1,1,1]) + s([1]) # optional - sage.combinat sage.modules sage: z.coefficient([4]) # optional - sage.combinat sage.modules 1 sage: z.coefficient([2,1]) # optional - sage.combinat sage.modules -2 sage: z.coefficient(Partition([2,1])) # optional - sage.combinat sage.modules -2 sage: z.coefficient([1,2]) # optional - sage.combinat sage.modules Traceback (most recent call last): ... AssertionError: [1, 2] should be an element of Partitions sage: z.coefficient(Composition([2,1])) # optional - sage.combinat sage.modules Traceback (most recent call last): ... AssertionError: [2, 1] should be an element of Partitions
Test that
coefficient
also works for those parents that do not have anelement_class
:sage: H = pAdicWeightSpace(3) # optional - sage.modules sage.rings.padics sage: F = CombinatorialFreeModule(QQ, H) # optional - sage.modules sage.rings.padics sage: hasattr(H, "element_class") # optional - sage.modules sage.rings.padics False sage: h = H.an_element() # optional - sage.modules sage.rings.padics sage: (2*F.monomial(h)).coefficient(h) # optional - sage.modules sage.rings.padics 2
- coefficients(sort=True)#
Return a list of the (non-zero) coefficients appearing on the basis elements in
self
(in an arbitrary order).INPUT:
sort
– (default:True
) to sort the coefficients based upon the default ordering of the indexing set
See also
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules sage: B = F.basis() # optional - sage.modules sage: f = B['a'] - 3*B['c'] # optional - sage.modules sage: f.coefficients() # optional - sage.modules [1, -3] sage: f = B['c'] - 3*B['a'] # optional - sage.modules sage: f.coefficients() # optional - sage.modules [-3, 1]
sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # optional - sage.combinat sage.modules sage: z.coefficients() # optional - sage.combinat sage.modules [1, 1, 1, 1]
- is_zero()#
Return
True
if and only ifself == 0
.EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules sage: B = F.basis() # optional - sage.modules sage: f = B['a'] - 3*B['c'] # optional - sage.modules sage: f.is_zero() # optional - sage.modules False sage: F.zero().is_zero() # optional - sage.modules True
sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: s([2,1]).is_zero() # optional - sage.combinat sage.modules False sage: s(0).is_zero() # optional - sage.combinat sage.modules True sage: (s([2,1]) - s([2,1])).is_zero() # optional - sage.combinat sage.modules True
- leading_coefficient(*args, **kwds)#
Return the leading coefficient of
self
.This is the coefficient of the term whose corresponding basis element is maximal. Note that this may not be the term which actually appears first when
self
is printed.If the default term ordering is not what is desired, a comparison key,
key(x,y)
, can be provided.EXAMPLES:
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) # optional - sage.modules sage: x.leading_coefficient() # optional - sage.modules 1 sage: def key(x): return -x # optional - sage.modules sage: x.leading_coefficient(key=key) # optional - sage.modules 3 sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules sage: f.leading_coefficient() # optional - sage.combinat sage.modules -5
- leading_item(*args, **kwds)#
Return the pair
(k, c)
where\[c \cdot (\mbox{the basis element indexed by } k)\]is the leading term of
self
.Here ‘leading term’ means that the corresponding basis element is maximal. Note that this may not be the term which actually appears first when
self
is printed.If the default term ordering is not what is desired, a comparison function,
key(x)
, can be provided.EXAMPLES:
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules sage: x = 3*X.monomial(1) + 2*X.monomial(2) + 4*X.monomial(3) # optional - sage.modules sage: x.leading_item() # optional - sage.modules (3, 4) sage: def key(x): return -x # optional - sage.modules sage: x.leading_item(key=key) # optional - sage.modules (1, 3) sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules sage: f.leading_item() # optional - sage.combinat sage.modules ([3], -5)
- leading_monomial(*args, **kwds)#
Return the leading monomial of
self
.This is the monomial whose corresponding basis element is maximal. Note that this may not be the term which actually appears first when
self
is printed.If the default term ordering is not what is desired, a comparison key,
key(x)
, can be provided.EXAMPLES:
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) # optional - sage.modules sage: x.leading_monomial() # optional - sage.modules B[3] sage: def key(x): return -x # optional - sage.modules sage: x.leading_monomial(key=key) # optional - sage.modules B[1] sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules sage: f.leading_monomial() # optional - sage.combinat sage.modules s[3]
- leading_support(*args, **kwds)#
Return the maximal element of the support of
self
.Note that this may not be the term which actually appears first when
self
is printed.If the default ordering of the basis elements is not what is desired, a comparison key,
key(x)
, can be provided.EXAMPLES:
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]) # optional - sage.modules sage: X.rename("X"); x = X.basis() # optional - sage.modules sage: x = 3*X.monomial(1) + 2*X.monomial(2) + 4*X.monomial(3) # optional - sage.modules sage: x.leading_support() # optional - sage.modules 3 sage: def key(x): return -x # optional - sage.modules sage: x.leading_support(key=key) # optional - sage.modules 1 sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules sage: f.leading_support() # optional - sage.combinat sage.modules [3]
- leading_term(*args, **kwds)#
Return the leading term of
self
.This is the term whose corresponding basis element is maximal. Note that this may not be the term which actually appears first when
self
is printed.If the default term ordering is not what is desired, a comparison key,
key(x)
, can be provided.EXAMPLES:
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) # optional - sage.modules sage: x.leading_term() # optional - sage.modules B[3] sage: def key(x): return -x # optional - sage.modules sage: x.leading_term(key=key) # optional - sage.modules 3*B[1] sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules sage: f.leading_term() # optional - sage.combinat sage.modules -5*s[3]
- length()#
Return the number of basis elements whose coefficients in
self
are nonzero.EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules sage: B = F.basis() # optional - sage.modules sage: f = B['a'] - 3*B['c'] # optional - sage.modules sage: f.length() # optional - sage.modules 2
sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # optional - sage.combinat sage.modules sage: z.length() # optional - sage.combinat sage.modules 4
- map_coefficients(f)#
Mapping a function on coefficients.
INPUT:
f
– an endofunction on the coefficient ring of the free module
Return a new element of
self.parent()
obtained by applying the functionf
to all of the coefficients ofself
.EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules sage: B = F.basis() # optional - sage.modules sage: f = B['a'] - 3*B['c'] # optional - sage.modules sage: f.map_coefficients(lambda x: x + 5) # optional - sage.modules 6*B['a'] + 2*B['c']
Killed coefficients are handled properly:
sage: f.map_coefficients(lambda x: 0) # optional - sage.modules 0 sage: list(f.map_coefficients(lambda x: 0)) # optional - sage.modules []
sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: a = s([2,1]) + 2*s([3,2]) # optional - sage.combinat sage.modules sage: a.map_coefficients(lambda x: x * 2) # optional - sage.combinat sage.modules 2*s[2, 1] + 4*s[3, 2]
- map_item(f)#
Mapping a function on items.
INPUT:
f
– a function mapping pairs(index, coeff)
to other such pairs
Return a new element of
self.parent()
obtained by applying the function \(f\) to all items(index, coeff)
ofself
.EXAMPLES:
sage: B = CombinatorialFreeModule(ZZ, [-1, 0, 1]) # optional - sage.modules sage: x = B.an_element(); x # optional - sage.modules 2*B[-1] + 2*B[0] + 3*B[1] sage: x.map_item(lambda i, c: (-i, 2*c)) # optional - sage.modules 6*B[-1] + 4*B[0] + 4*B[1]
f
needs not be injective:sage: x.map_item(lambda i, c: (1, 2*c)) # optional - sage.modules 14*B[1] sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: f = lambda m, c: (m.conjugate(), 2 * c) # optional - sage.combinat sage.modules sage: a = s([2,1]) + s([1,1,1]) # optional - sage.combinat sage.modules sage: a.map_item(f) # optional - sage.combinat sage.modules 2*s[2, 1] + 2*s[3]
- map_support(f)#
Mapping a function on the support.
INPUT:
f
– an endofunction on the indices of the free module
Return a new element of
self.parent()
obtained by applying the functionf
to all of the objects indexing the basis elements.EXAMPLES:
sage: B = CombinatorialFreeModule(ZZ, [-1, 0, 1]) # optional - sage.modules sage: x = B.an_element(); x # optional - sage.modules 2*B[-1] + 2*B[0] + 3*B[1] sage: x.map_support(lambda i: -i) # optional - sage.modules 3*B[-1] + 2*B[0] + 2*B[1]
f
needs not be injective:sage: x.map_support(lambda i: 1) # optional - sage.modules 7*B[1] sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: a = s([2,1]) + 2*s([3,2]) # optional - sage.combinat sage.modules sage: a.map_support(lambda x: x.conjugate()) # optional - sage.combinat sage.modules s[2, 1] + 2*s[2, 2, 1]
- map_support_skip_none(f)#
Mapping a function on the support.
INPUT:
f
– an endofunction on the indices of the free module
Returns a new element of
self.parent()
obtained by applying the function \(f\) to all of the objects indexing the basis elements.EXAMPLES:
sage: B = CombinatorialFreeModule(ZZ, [-1, 0, 1]) # optional - sage.modules sage: x = B.an_element(); x # optional - sage.modules 2*B[-1] + 2*B[0] + 3*B[1] sage: x.map_support_skip_none(lambda i: -i if i else None) # optional - sage.modules 3*B[-1] + 2*B[1]
f
needs not be injective:sage: x.map_support_skip_none(lambda i: 1 if i else None) # optional - sage.modules 5*B[1]
- monomial_coefficients(copy=True)#
Return a dictionary whose keys are indices of basis elements in the support of
self
and whose values are the corresponding coefficients.INPUT:
copy
– (default:True
) ifself
is internally represented by a dictionaryd
, then make a copy ofd
; ifFalse
, then this can cause undesired behavior by mutatingd
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules sage: B = F.basis() # optional - sage.modules sage: f = B['a'] + 3*B['c'] # optional - sage.modules sage: d = f.monomial_coefficients() # optional - sage.modules sage: d['a'] # optional - sage.modules 1 sage: d['c'] # optional - sage.modules 3
- monomials()#
Return a list of the monomials of
self
(in an arbitrary order).The monomials of an element \(a\) are defined to be the basis elements whose corresponding coefficients of \(a\) are non-zero.
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules sage: B = F.basis() # optional - sage.modules sage: f = B['a'] + 2*B['c'] # optional - sage.modules sage: f.monomials() # optional - sage.modules [B['a'], B['c']] sage: (F.zero()).monomials() # optional - sage.modules []
- support()#
Return an iterable of the objects indexing the basis of
self.parent()
whose corresponding coefficients ofself
are non-zero.This method returns these objects in an arbitrary order.
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules sage: B = F.basis() # optional - sage.modules sage: f = B['a'] - 3*B['c'] # optional - sage.modules sage: sorted(f.support()) # optional - sage.modules ['a', 'c']
sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: z = s([4]) + s([2,1]) + s([1,1,1]) + s([1]) # optional - sage.combinat sage.modules sage: sorted(z.support()) # optional - sage.combinat sage.modules [[1], [1, 1, 1], [2, 1], [4]]
- support_of_term()#
Return the support of
self
, whereself
is a monomial (possibly with coefficient).EXAMPLES:
sage: X = CombinatorialFreeModule(QQ, [1,2,3,4]); X.rename("X") # optional - sage.modules sage: X.monomial(2).support_of_term() # optional - sage.modules 2 sage: X.term(3, 2).support_of_term() # optional - sage.modules 3
An exception is raised if
self
has more than one term:sage: (X.monomial(2) + X.monomial(3)).support_of_term() # optional - sage.modules Traceback (most recent call last): ... ValueError: B[2] + B[3] is not a single term
- tensor(*elements)#
Return the tensor product of its arguments, as an element of the tensor product of the parents of those elements.
EXAMPLES:
sage: C = AlgebrasWithBasis(QQ) sage: A = C.example() # optional - sage.combinat sage.modules sage: a, b, c = A.algebra_generators() # optional - sage.combinat sage.modules sage: a.tensor(b, c) # optional - sage.combinat sage.modules B[word: a] # B[word: b] # B[word: c]
FIXME: is this a policy that we want to enforce on all parents?
- terms()#
Return a list of the (non-zero) terms of
self
(in an arbitrary order).See also
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) # optional - sage.modules sage: B = F.basis() # optional - sage.modules sage: f = B['a'] + 2*B['c'] # optional - sage.modules sage: f.terms() # optional - sage.modules [B['a'], 2*B['c']]
- trailing_coefficient(*args, **kwds)#
Return the trailing coefficient of
self
.This is the coefficient of the monomial whose corresponding basis element is minimal. Note that this may not be the term which actually appears last when
self
is printed.If the default term ordering is not what is desired, a comparison key
key(x)
, can be provided.EXAMPLES:
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) # optional - sage.modules sage: x.trailing_coefficient() # optional - sage.modules 3 sage: def key(x): return -x # optional - sage.modules sage: x.trailing_coefficient(key=key) # optional - sage.modules 1 sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules sage: f.trailing_coefficient() # optional - sage.combinat sage.modules 2
- trailing_item(*args, **kwds)#
Return the pair
(c, k)
wherec*self.parent().monomial(k)
is the trailing term ofself
.This is the monomial whose corresponding basis element is minimal. Note that this may not be the term which actually appears last when
self
is printed.If the default term ordering is not what is desired, a comparison key
key(x)
, can be provided.EXAMPLES:
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) # optional - sage.modules sage: x.trailing_item() # optional - sage.modules (1, 3) sage: def key(x): return -x # optional - sage.modules sage: x.trailing_item(key=key) # optional - sage.modules (3, 1) sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules sage: f.trailing_item() # optional - sage.combinat sage.modules ([1], 2)
- trailing_monomial(*args, **kwds)#
Return the trailing monomial of
self
.This is the monomial whose corresponding basis element is minimal. Note that this may not be the term which actually appears last when
self
is printed.If the default term ordering is not what is desired, a comparison key
key(x)
, can be provided.EXAMPLES:
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) # optional - sage.modules sage: x.trailing_monomial() # optional - sage.modules B[1] sage: def key(x): return -x # optional - sage.modules sage: x.trailing_monomial(key=key) # optional - sage.modules B[3] sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules sage: f.trailing_monomial() # optional - sage.combinat sage.modules s[1]
- trailing_support(*args, **kwds)#
Return the minimal element of the support of
self
. Note that this may not be the term which actually appears last whenself
is printed.If the default ordering of the basis elements is not what is desired, a comparison key,
key(x)
, can be provided.EXAMPLES:
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules sage: x = 3*X.monomial(1) + 2*X.monomial(2) + 4*X.monomial(3) # optional - sage.modules sage: x.trailing_support() # optional - sage.modules 1 sage: def key(x): return -x # optional - sage.modules sage: x.trailing_support(key=key) # optional - sage.modules 3 sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules sage: f.trailing_support() # optional - sage.combinat sage.modules [1]
- trailing_term(*args, **kwds)#
Return the trailing term of
self
.This is the term whose corresponding basis element is minimal. Note that this may not be the term which actually appears last when
self
is printed.If the default term ordering is not what is desired, a comparison key
key(x)
, can be provided.EXAMPLES:
sage: X = CombinatorialFreeModule(QQ, [1, 2, 3]); X.rename("X") # optional - sage.modules sage: x = 3*X.monomial(1) + 2*X.monomial(2) + X.monomial(3) # optional - sage.modules sage: x.trailing_term() # optional - sage.modules 3*B[1] sage: def key(x): return -x # optional - sage.modules sage: x.trailing_term(key=key) # optional - sage.modules B[3] sage: s = SymmetricFunctions(QQ).schur() # optional - sage.combinat sage.modules sage: f = 2*s[1] + 3*s[2,1] - 5*s[3] # optional - sage.combinat sage.modules sage: f.trailing_term() # optional - sage.combinat sage.modules 2*s[1]
- Filtered#
alias of
FilteredModulesWithBasis
- FiniteDimensional#
alias of
FiniteDimensionalModulesWithBasis
- Graded#
alias of
GradedModulesWithBasis
- class Homsets(category, *args)#
Bases:
HomsetsCategory
- class ParentMethods#
Bases:
object
- class MorphismMethods#
Bases:
object
- on_basis()#
Return the action of this morphism on basis elements.
OUTPUT:
a function from the indices of the basis of the domain to the codomain
EXAMPLES:
sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename("X") # optional - sage.modules sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename("Y") # optional - sage.modules sage: H = Hom(X, Y) # optional - sage.modules sage: x = X.basis() # optional - sage.modules sage: f = H(lambda x: Y.zero()).on_basis() # optional - sage.modules sage: f(2) # optional - sage.modules 0 sage: f = lambda i: Y.monomial(i) + 2*Y.monomial(i+1) # optional - sage.modules sage: g = H(on_basis=f).on_basis() # optional - sage.modules sage: g(2) # optional - sage.modules B[2] + 2*B[3] sage: g == f # optional - sage.modules True
- class ParentMethods#
Bases:
object
- basis()#
Return the basis of
self
.EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # optional - sage.modules sage: F.basis() # optional - sage.modules Finite family {'a': B['a'], 'b': B['b'], 'c': B['c']}
sage: QS3 = SymmetricGroupAlgebra(QQ, 3) # optional - sage.group sage.modules sage: list(QS3.basis()) # optional - sage.group sage.modules [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
- cardinality()#
Return the cardinality of
self
.EXAMPLES:
sage: S = SymmetricGroupAlgebra(QQ, 4) # optional - sage.groups sage.modules sage: S.cardinality() # optional - sage.groups sage.modules +Infinity sage: S = SymmetricGroupAlgebra(GF(2), 4) # not tested -- MRO bug trac #15475 # optional - sage.groups sage.rings.finite_rings sage.modules sage: S.cardinality() # not tested -- MRO bug trac #15475 # optional - sage.groups sage.rings.finite_rings sage.modules 16777216 sage: S.cardinality().factor() # not tested -- MRO bug trac #15475 # optional - sage.groups sage.rings.finite_rings sage.modules 2^24 sage: E.<x,y> = ExteriorAlgebra(QQ) # optional - sage.combinat sage.modules sage: E.cardinality() # optional - sage.combinat sage.modules +Infinity sage: E.<x,y> = ExteriorAlgebra(GF(3)) # optional - sage.combinat sage.rings.finite_rings sage.modules sage: E.cardinality() # optional - sage.combinat sage.rings.finite_rings sage.modules 81 sage: s = SymmetricFunctions(GF(2)).s() # optional - sage.combinat sage.rings.finite_rings sage.modules sage: s.cardinality() # optional - sage.combinat sage.rings.finite_rings sage.modules +Infinity
- dimension()#
Return the dimension of
self
.EXAMPLES:
sage: A.<x,y> = algebras.DifferentialWeyl(QQ) # optional - sage.combinat sage.modules sage: A.dimension() # optional - sage.combinat sage.modules +Infinity
- echelon_form(elements, row_reduced=False, order=None)#
Return a basis in echelon form of the subspace spanned by a finite set of elements.
INPUT:
elements
– a list or finite iterable of elements ofself
row_reduced
– (default:False
) whether to compute the basis for the row reduced echelon formorder
– (optional) either something that can be converted into a tuple or a key function
OUTPUT:
A list of elements of
self
whose expressions as vectors form a matrix in echelon form. Ifbase_ring
is specified, then the calculation is achieved in this base ring.EXAMPLES:
sage: R.<x,y> = QQ[] sage: C = CombinatorialFreeModule(R, ZZ, prefix='z') # optional - sage.modules sage: z = C.basis() # optional - sage.modules sage: C.echelon_form([z[0] - z[1], 2*z[1] - 2*z[2], z[0] - z[2]]) # optional - sage.modules [z[0] - z[2], z[1] - z[2]]
- is_finite()#
Return whether
self
is finite.This is true if and only if
self.basis().keys()
andself.base_ring()
are both finite.EXAMPLES:
sage: GroupAlgebra(SymmetricGroup(2), IntegerModRing(10)).is_finite() # optional - sage.groups sage.modules True sage: GroupAlgebra(SymmetricGroup(2)).is_finite() # optional - sage.groups sage.modules False sage: GroupAlgebra(AbelianGroup(1), IntegerModRing(10)).is_finite() # optional - sage.groups sage.modules False
- module_morphism(on_basis=None, matrix=None, function=None, diagonal=None, triangular=None, unitriangular=False, **keywords)#
Construct a module morphism from
self
tocodomain
.Let
self
be a module \(X\) with a basis indexed by \(I\). This constructs a morphism \(f: X \to Y\) by linearity from a map \(I \to Y\) which is to be its restriction to the basis \((x_i)_{i \in I}\) of \(X\). Some variants are possible too.INPUT:
self
– a parent \(X\) inModulesWithBasis(R)
with basis \(x=(x_i)_{i\in I}\).
Exactly one of the four following options must be specified in order to define the morphism:
on_basis
– a function \(f\) from \(I\) to \(Y\)diagonal
– a function \(d\) from \(I\) to \(R\)function
– a function \(f\) from \(X\) to \(Y\)matrix
– a matrix of size \(\dim Y \times \dim X\) (if the keywordside
is set to'left'
) or \(\dim Y \times \dim X\) (if this keyword is'right'
)
Further options include:
codomain
– the codomain \(Y\) of the morphism (default:f.codomain()
if it’s defined; otherwise it must be specified)category
– a category orNone
(default:None
)zero
– the zero of the codomain (default:codomain.zero()
); can be used (with care) to define affine maps. Only meaningful withon_basis
.position
– a non-negative integer specifying which positional argument is used as the input of the function \(f\) (default: 0); this is currently only used withon_basis
.triangular
– (default:None
)"upper"
or"lower"
orNone
:"upper"
- if theleading_support()
of the image of the basis vector \(x_i\) is \(i\), or"lower"
- if thetrailing_support()
of the image of the basis vector \(x_i\) is \(i\).
unitriangular
– (default:False
) a boolean. Only meaningful for a triangular morphism. As a shorthand, one may useunitriangular="lower"
fortriangular="lower", unitriangular=True
.side
– “left” or “right” (default: “left”) Only meaningful for a morphism built from a matrix.
EXAMPLES:
With the
on_basis
option, this returns a function \(g\) obtained by extending \(f\) by linearity on theposition
-th positional argument. For example, forposition == 1
and a ternary function \(f\), one has:\[g\left( a,\ \sum_i \lambda_i x_i,\ c \right) = \sum_i \lambda_i f(a, i, c).\]sage: X = CombinatorialFreeModule(QQ, [1,2,3]); X.rename("X") # optional - sage.modules sage: Y = CombinatorialFreeModule(QQ, [1,2,3,4]); Y.rename("Y") # optional - sage.modules sage: def f(i): ....: return Y.monomial(i) + 2*Y.monomial(i+1) sage: phi = X.module_morphism(f, codomain=Y) # optional - sage.modules sage: x = X.basis(); y = Y.basis() # optional - sage.modules sage: phi(x[1] + x[3]) # optional - sage.modules B[1] + 2*B[2] + B[3] + 2*B[4] sage: phi # optional - sage.modules Generic morphism: From: X To: Y
By default, the category is the first of
Modules(R).WithBasis().FiniteDimensional()
,Modules(R).WithBasis()
,Modules(R)
, andCommutativeAdditiveMonoids()
that contains both the domain and the codomain:sage: phi.category_for() # optional - sage.modules Category of finite dimensional vector spaces with basis over Rational Field
With the
zero
argument, one can define affine morphisms:sage: def f(i): ....: return Y.monomial(i) + 2*Y.monomial(i+1) sage: phi = X.module_morphism(f, codomain=Y, zero=10*y[1]) # optional - sage.modules sage: phi(x[1] + x[3]) # optional - sage.modules 11*B[1] + 2*B[2] + B[3] + 2*B[4]
In this special case, the default category is
Sets()
:sage: phi.category_for() # optional - sage.modules Category of sets
One can construct morphisms with the base ring as codomain:
sage: X = CombinatorialFreeModule(ZZ, [1, -1]) # optional - sage.modules sage: phi = X.module_morphism(on_basis=lambda i: i, codomain=ZZ) # optional - sage.modules sage: phi(2 * X.monomial(1) + 3 * X.monomial(-1)) # optional - sage.modules -1 sage: phi.category_for() # optional - sage.modules Category of commutative additive semigroups sage: phi.category_for() # todo: not implemented (ZZ is currently not in Modules(ZZ)) # optional - sage.modules Category of modules over Integer Ring
Or more generally any ring admitting a coercion map from the base ring:
sage: phi = X.module_morphism(on_basis=lambda i: i, codomain=RR) # optional - sage.modules sage: phi(2 * X.monomial(1) + 3 * X.monomial(-1)) # optional - sage.modules -1.00000000000000 sage: phi.category_for() # optional - sage.modules Category of commutative additive semigroups sage: phi.category_for() # todo: not implemented (RR is currently not in Modules(ZZ)) # optional - sage.modules Category of modules over Integer Ring sage: phi = X.module_morphism(on_basis=lambda i: i, codomain=Zmod(4)) # optional - sage.modules sage: phi(2 * X.monomial(1) + 3 * X.monomial(-1)) # optional - sage.modules 3 sage: phi = Y.module_morphism(on_basis=lambda i: i, codomain=Zmod(4)) # optional - sage.modules Traceback (most recent call last): ... ValueError: codomain(=Ring of integers modulo 4) should be a module over the base ring of the domain(=Y)
On can also define module morphisms between free modules over different base rings; here we implement the natural map from \(X = \RR^2\) to \(Y = \CC\):
sage: X = CombinatorialFreeModule(RR, ['x', 'y']) # optional - sage.modules sage: Y = CombinatorialFreeModule(CC, ['z']) # optional - sage.modules sage: x = X.monomial('x') # optional - sage.modules sage: y = X.monomial('y') # optional - sage.modules sage: z = Y.monomial('z') # optional - sage.modules sage: def on_basis(a): # optional - sage.modules ....: if a == 'x': ....: return CC(1) * z ....: elif a == 'y': ....: return CC(I) * z sage: phi = X.module_morphism(on_basis=on_basis, codomain=Y) # optional - sage.modules sage: v = 3 * x + 2 * y; v # optional - sage.modules 3.00000000000000*B['x'] + 2.00000000000000*B['y'] sage: phi(v) # optional - sage.modules (3.00000000000000+2.00000000000000*I)*B['z'] sage: phi.category_for() # optional - sage.modules Category of commutative additive semigroups sage: phi.category_for() # todo: not implemented (CC is currently not in Modules(RR)!) # optional - sage.modules Category of vector spaces over Real Field with 53 bits of precision sage: Y = CombinatorialFreeModule(CC['q'], ['z']) # optional - sage.modules sage: z = Y.monomial('z') # optional - sage.modules sage: phi = X.module_morphism(on_basis=on_basis, codomain=Y) # optional - sage.modules sage: phi(v) # optional - sage.modules (3.00000000000000+2.00000000000000*I)*B['z']
Of course, there should be a coercion between the respective base rings of the domain and the codomain for this to be meaningful:
sage: Y = CombinatorialFreeModule(QQ, ['z']) # optional - sage.modules sage: phi = X.module_morphism(on_basis=on_basis, codomain=Y) # optional - sage.modules Traceback (most recent call last): ... ValueError: codomain(=Free module generated by {'z'} over Rational Field) should be a module over the base ring of the domain(=Free module generated by {'x', 'y'} over Real Field with 53 bits of precision) sage: Y = CombinatorialFreeModule(RR['q'], ['z']) # optional - sage.modules sage: phi = Y.module_morphism(on_basis=on_basis, codomain=X) # optional - sage.modules Traceback (most recent call last): ... ValueError: codomain(=Free module generated by {'x', 'y'} over Real Field with 53 bits of precision) should be a module over the base ring of the domain(=Free module generated by {'z'} over Univariate Polynomial Ring in q over Real Field with 53 bits of precision)
With the
diagonal=d
argument, this constructs the module morphism \(g\) such that\[`g(x_i) = d(i) y_i`.\]This assumes that the respective bases \(x\) and \(y\) of \(X\) and \(Y\) have the same index set \(I\):
sage: X = CombinatorialFreeModule(ZZ, [1, 2, 3]); X.rename("X") # optional - sage.modules sage: from sage.arith.misc import factorial # optional - sage.modules sage: phi = X.module_morphism(diagonal=factorial, codomain=X) # optional - sage.modules sage: x = X.basis() # optional - sage.modules sage: phi(x[1]), phi(x[2]), phi(x[3]) # optional - sage.modules (B[1], 2*B[2], 6*B[3])
See also:
sage.modules.with_basis.morphism.DiagonalModuleMorphism
.With the
matrix=m
argument, this constructs the module morphism whose matrix in the distinguished basis of \(X\) and \(Y\) is \(m\):sage: X = CombinatorialFreeModule(ZZ, [1,2,3]); X.rename("X") # optional - sage.modules sage: x = X.basis() # optional - sage.modules sage: Y = CombinatorialFreeModule(ZZ, [3,4]); Y.rename("Y") # optional - sage.modules sage: y = Y.basis() # optional - sage.modules sage: m = matrix([[0,1,2], [3,5,0]]) # optional - sage.modules sage: phi = X.module_morphism(matrix=m, codomain=Y) # optional - sage.modules sage: phi(x[1]) # optional - sage.modules 3*B[4] sage: phi(x[2]) # optional - sage.modules B[3] + 5*B[4]
See also:
sage.modules.with_basis.morphism.ModuleMorphismFromMatrix
.With
triangular="upper"
, the constructed module morphism is assumed to be upper triangular; that is its matrix in the distinguished basis of \(X\) and \(Y\) would be upper triangular with invertible elements on its diagonal. This is used to compute preimages and to invert the morphism:sage: I = list(range(1, 200)) sage: X = CombinatorialFreeModule(QQ, I); X.rename("X"); x = X.basis() # optional - sage.modules sage: Y = CombinatorialFreeModule(QQ, I); Y.rename("Y"); y = Y.basis() # optional - sage.modules sage: f = Y.sum_of_monomials * divisors # optional - sage.modules sage: phi = X.module_morphism(f, triangular="upper", codomain=Y) # optional - sage.modules sage: phi(x[2]) # optional - sage.modules B[1] + B[2] sage: phi(x[6]) # optional - sage.modules B[1] + B[2] + B[3] + B[6] sage: phi(x[30]) # optional - sage.modules B[1] + B[2] + B[3] + B[5] + B[6] + B[10] + B[15] + B[30] sage: phi.preimage(y[2]) # optional - sage.modules -B[1] + B[2] sage: phi.preimage(y[6]) # optional - sage.modules B[1] - B[2] - B[3] + B[6] sage: phi.preimage(y[30]) # optional - sage.modules -B[1] + B[2] + B[3] + B[5] - B[6] - B[10] - B[15] + B[30] sage: (phi^-1)(y[30]) # optional - sage.modules -B[1] + B[2] + B[3] + B[5] - B[6] - B[10] - B[15] + B[30]
Since github issue #8678, one can also define a triangular morphism from a function:
sage: X = CombinatorialFreeModule(QQ, [0,1,2,3,4]); x = X.basis() # optional - sage.modules sage: from sage.modules.with_basis.morphism import TriangularModuleMorphismFromFunction # optional - sage.modules sage: def f(x): return x + X.term(0, sum(x.coefficients())) # optional - sage.modules sage: phi = X.module_morphism(function=f, codomain=X, # optional - sage.modules ....: triangular="upper") sage: phi(x[2] + 3*x[4]) # optional - sage.modules 4*B[0] + B[2] + 3*B[4] sage: phi.preimage(_) # optional - sage.modules B[2] + 3*B[4]
For details and further optional arguments, see
sage.modules.with_basis.morphism.TriangularModuleMorphism
.Warning
As a temporary measure, until multivariate morphisms are implemented, the constructed morphism is in
Hom(codomain, domain, category)
. This is only correct for unary functions.Todo
Should codomain be
self
by default in the diagonal, triangular, and matrix cases?Support for diagonal morphisms between modules not sharing the same index set
- monomial(i)#
Return the basis element indexed by
i
.INPUT:
i
– an element of the index set
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # optional - sage.modules sage: F.monomial('a') # optional - sage.modules B['a']
F.monomial
is in fact (almost) a map:sage: F.monomial # optional - sage.modules Term map from {'a', 'b', 'c'} to Free module generated by {'a', 'b', 'c'} over Rational Field
- monomial_or_zero_if_none(i)#
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # optional - sage.modules sage: F.monomial_or_zero_if_none('a') # optional - sage.modules B['a'] sage: F.monomial_or_zero_if_none(None) # optional - sage.modules 0
- quotient_module(submodule, check=True, already_echelonized=False, category=None)#
Construct the quotient module
self
/submodule
.INPUT:
submodule
– a submodule with basis ofself
, or something that can be turned into one viaself.submodule(submodule)
check
,already_echelonized
– passed down toModulesWithBasis.ParentMethods.submodule()
Warning
At this point, this only supports quotients by free submodules admitting a basis in unitriangular echelon form. In this case, the quotient is also a free module, with a basis consisting of the retract of a subset of the basis of
self
.EXAMPLES:
sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x") # optional - sage.modules sage: x = X.basis() # optional - sage.modules sage: Y = X.quotient_module([x[0] - x[1], x[1] - x[2]], # optional - sage.modules ....: already_echelonized=True) sage: Y.print_options(prefix='y'); Y # optional - sage.modules Free module generated by {2} over Rational Field sage: y = Y.basis() # optional - sage.modules sage: y[2] # optional - sage.modules y[2] sage: y[2].lift() # optional - sage.modules x[2] sage: Y.retract(x[0] + 2*x[1]) # optional - sage.modules 3*y[2] sage: R.<a,b> = QQ[] sage: C = CombinatorialFreeModule(R, range(3), prefix='x') # optional - sage.modules sage: x = C.basis() # optional - sage.modules sage: gens = [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]] # optional - sage.modules sage: Y = C.quotient_module(gens) # optional - sage.modules
See also
Modules.WithBasis.ParentMethods.submodule()
- random_element(n=2)#
Return a ‘random’ element of
self
.INPUT:
n
– integer (default: 2); number of summands
ALGORITHM:
Return a sum of
n
terms, each of which is formed by multiplying a random element of the base ring by a random element of the group.EXAMPLES:
sage: x = DihedralGroup(6).algebra(QQ).random_element() # optional - sage.groups sage.modules sage: x.parent() is DihedralGroup(6).algebra(QQ) # optional - sage.groups sage.modules True
Note, this result can depend on the PRNG state in libgap in a way that depends on which packages are loaded, so we must re-seed GAP to ensure a consistent result for this example:
sage: libgap.set_seed(0) # optional - sage.libs.gap 0 sage: m = SU(2, 13).algebra(QQ).random_element(1) # optional - sage.groups sage.modules sage: m.parent() is SU(2, 13).algebra(QQ) # optional - sage.groups sage.modules True sage: p = CombinatorialFreeModule(ZZ, Partitions(4)).random_element() # optional - sage.combinat sage.modules sage: p.parent() is CombinatorialFreeModule(ZZ, Partitions(4)) # optional - sage.combinat sage.modules True
- submodule(gens, check=True, already_echelonized=False, unitriangular=False, support_order=None, category=None, *args, **opts)#
The submodule spanned by a finite set of elements.
INPUT:
gens
– a list or family of elements ofself
check
– (default:True
) whether to verify that theelements of
gens
are inself
already_echelonized
– (default:False
) whetherthe elements of
gens
are already in (not necessarily reduced) echelon form
unitriangular
– (default:False
) whether the lift morphism is unitriangularsupport_order
– (optional) either something that can be converted into a tuple or a key functioncategory
– (optional) the category of the submodule
If
already_echelonized
isFalse
, then the generators are put in reduced echelon form usingechelonize()
, and reindexed by \(0,1,...\).Warning
At this point, this method only works for finite dimensional submodules and if matrices can be echelonized over the base ring.
If in addition
unitriangular
isTrue
, then the generators are made such that the coefficients of the pivots are 1, so that lifting map is unitriangular.The basis of the submodule uses the same index set as the generators, and the lifting map sends \(y_i\) to \(gens[i]\).
See also
ModulesWithBasis.FiniteDimensional.ParentMethods.quotient_module()
EXAMPLES:
We construct a submodule of the free \(\QQ\)-module generated by \(x_0, x_1, x_2\). The submodule is spanned by \(y_0 = x_0 - x_1\) and \(y_1 - x_1 - x_2\), and its basis elements are indexed by \(0\) and \(1\):
sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x") # optional - sage.modules sage: x = X.basis() # optional - sage.modules sage: gens = [x[0] - x[1], x[1] - x[2]]; gens # optional - sage.modules [x[0] - x[1], x[1] - x[2]] sage: Y = X.submodule(gens, already_echelonized=True) # optional - sage.modules sage: Y.print_options(prefix='y'); Y # optional - sage.modules Free module generated by {0, 1} over Rational Field sage: y = Y.basis() # optional - sage.modules sage: y[1] # optional - sage.modules y[1] sage: y[1].lift() # optional - sage.modules x[1] - x[2] sage: Y.retract(x[0] - x[2]) # optional - sage.modules y[0] + y[1] sage: Y.retract(x[0]) # optional - sage.modules Traceback (most recent call last): ... ValueError: x[0] is not in the image
By using a family to specify a basis of the submodule, we obtain a submodule whose index set coincides with the index set of the family:
sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x") # optional - sage.modules sage: x = X.basis() # optional - sage.modules sage: gens = Family({1: x[0] - x[1], 3: x[1] - x[2]}); gens # optional - sage.modules Finite family {1: x[0] - x[1], 3: x[1] - x[2]} sage: Y = X.submodule(gens, already_echelonized=True) # optional - sage.modules sage: Y.print_options(prefix='y'); Y # optional - sage.modules Free module generated by {1, 3} over Rational Field sage: y = Y.basis() # optional - sage.modules sage: y[1] # optional - sage.modules y[1] sage: y[1].lift() # optional - sage.modules x[0] - x[1] sage: y[3].lift() # optional - sage.modules x[1] - x[2] sage: Y.retract(x[0] - x[2]) # optional - sage.modules y[1] + y[3] sage: Y.retract(x[0]) # optional - sage.modules Traceback (most recent call last): ... ValueError: x[0] is not in the image
It is not necessary that the generators of the submodule form a basis (an explicit basis will be computed):
sage: X = CombinatorialFreeModule(QQ, range(3), prefix="x") # optional - sage.modules sage: x = X.basis() # optional - sage.modules sage: gens = [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]]; gens # optional - sage.modules [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]] sage: Y = X.submodule(gens, already_echelonized=False) # optional - sage.modules sage: Y.print_options(prefix='y') # optional - sage.modules sage: Y # optional - sage.modules Free module generated by {0, 1} over Rational Field sage: [b.lift() for b in Y.basis()] # optional - sage.modules [x[0] - x[2], x[1] - x[2]]
We now implement by hand the center of the algebra of the symmetric group \(S_3\):
sage: S3 = SymmetricGroup(3) # optional - sage.groups sage.modules sage: S3A = S3.algebra(QQ) # optional - sage.groups sage.modules sage: basis = S3A.annihilator_basis(S3A.algebra_generators(), # optional - sage.groups sage.modules ....: S3A.bracket) sage: basis # optional - sage.groups sage.modules ((), (1,2,3) + (1,3,2), (2,3) + (1,2) + (1,3)) sage: center = S3A.submodule(basis, # optional - sage.groups sage.modules ....: category=AlgebrasWithBasis(QQ).Subobjects(), ....: already_echelonized=True) sage: center # optional - sage.groups sage.modules Free module generated by {0, 1, 2} over Rational Field sage: center in Algebras # optional - sage.groups sage.modules True sage: center.print_options(prefix='c') # optional - sage.groups sage.modules sage: c = center.basis() # optional - sage.groups sage.modules sage: c[1].lift() # optional - sage.groups sage.modules (1,2,3) + (1,3,2) sage: c[0]^2 # optional - sage.groups sage.modules c[0] sage: e = 1/6 * (c[0]+c[1]+c[2]) # optional - sage.groups sage.modules sage: e.is_idempotent() # optional - sage.groups sage.modules True
Of course, this center is best constructed using:
sage: center = S3A.center() # optional - sage.groups sage.modules
We can also automatically construct a basis such that the lift morphism is (lower) unitriangular:
sage: R.<a,b> = QQ[] sage: C = CombinatorialFreeModule(R, range(3), prefix='x') # optional - sage.modules sage: x = C.basis() # optional - sage.modules sage: gens = [x[0] - x[1], 2*x[1] - 2*x[2], x[0] - x[2]] # optional - sage.modules sage: Y = C.submodule(gens, unitriangular=True) # optional - sage.modules sage: Y.lift.matrix() # optional - sage.modules [ 1 0] [ 0 1] [-1 -1]
We now construct a (finite-dimensional) submodule of an infinite dimensional free module:
sage: C = CombinatorialFreeModule(QQ, ZZ, prefix='z') # optional - sage.modules sage: z = C.basis() # optional - sage.modules sage: gens = [z[0] - z[1], 2*z[1] - 2*z[2], z[0] - z[2]] # optional - sage.modules sage: Y = C.submodule(gens) # optional - sage.modules sage: [Y.lift(b) for b in Y.basis()] # optional - sage.modules [z[0] - z[2], z[1] - z[2]]
- sum_of_monomials()#
Return the sum of the basis elements with indices in
indices
.INPUT:
indices
– an list (or iterable) of indices of basis elements
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) # optional - sage.modules sage: F.sum_of_monomials(['a', 'b']) # optional - sage.modules B['a'] + B['b'] sage: F.sum_of_monomials(['a', 'b', 'a']) # optional - sage.modules 2*B['a'] + B['b']
F.sum_of_monomials
is in fact (almost) a map:sage: F.sum_of_monomials # optional - sage.modules A map to Free module generated by {'a', 'b', 'c'} over Rational Field
- sum_of_terms(terms)#
Construct a sum of terms of
self
.INPUT:
terms
– a list (or iterable) of pairs(index, coeff)
OUTPUT:
Sum of
coeff * B[index]
over all(index, coeff)
interms
, whereB
is the basis ofself
.EXAMPLES:
sage: m = matrix([[0,1], [1,1]]) # optional - sage.modules sage: J.<a,b,c> = JordanAlgebra(m) # optional - sage.combinat sage.modules sage: J.sum_of_terms([(0, 2), (2, -3)]) # optional - sage.combinat sage.modules 2 + (0, -3)
- tensor(*parents, **kwargs)#
Return the tensor product of the parents.
EXAMPLES:
sage: C = AlgebrasWithBasis(QQ) sage: A = C.example(); A.rename("A") # optional - sage.combinat sage.modules sage: A.tensor(A, A) # optional - sage.combinat sage.modules A # A # A sage: A.rename(None) # optional - sage.combinat sage.modules
- term(index, coeff=None)#
Construct a term in
self
.INPUT:
index
– the index of a basis elementcoeff
– an element of the coefficient ring (default: one)
OUTPUT:
coeff * B[index]
, whereB
is the basis ofself
.EXAMPLES:
sage: m = matrix([[0,1], [1,1]]) # optional - sage.modules sage: J.<a,b,c> = JordanAlgebra(m) # optional - sage.combinat sage.modules sage: J.term(1, -2) # optional - sage.combinat sage.modules 0 + (-2, 0)
Design: should this do coercion on the coefficient ring?
- Super#
alias of
SuperModulesWithBasis
- class TensorProducts(category, *args)#
Bases:
TensorProductsCategory
The category of modules with basis constructed by tensor product of modules with basis.
- class ElementMethods#
Bases:
object
Implements operations on elements of tensor products of modules with basis.
- apply_multilinear_morphism(f, codomain=None)#
Return the result of applying the morphism induced by
f
toself
.INPUT:
f
– a multilinear morphism from the component modules of the parent tensor product to any modulecodomain
– the codomain off
(optional)
By the universal property of the tensor product,
f
induces a linear morphism from \(self.parent()\) to the target module. Returns the result of applying that morphism toself
.The codomain is used for optimizations purposes only. If it’s not provided, it’s recovered by calling
f
on the zero input.EXAMPLES:
We start with simple (admittedly not so interesting) examples, with two modules \(A\) and \(B\):
sage: A = CombinatorialFreeModule(ZZ, [1,2], prefix="A") # optional - sage.modules sage: A.rename("A") # optional - sage.modules sage: B = CombinatorialFreeModule(ZZ, [3,4], prefix="B") # optional - sage.modules sage: B.rename("B") # optional - sage.modules
and \(f\) the bilinear morphism \((a,b) \mapsto b \otimes a\) from \(A \times B\) to \(B \otimes A\):
sage: def f(a,b): ....: return tensor([b,a])
Now, calling applying \(f\) on \(a \otimes b\) returns the same as \(f(a,b)\):
sage: a = A.monomial(1) + 2 * A.monomial(2); a # optional - sage.modules A[1] + 2*A[2] sage: b = B.monomial(3) - 2 * B.monomial(4); b # optional - sage.modules B[3] - 2*B[4] sage: f(a, b) # optional - sage.modules B[3] # A[1] + 2*B[3] # A[2] - 2*B[4] # A[1] - 4*B[4] # A[2] sage: tensor([a, b]).apply_multilinear_morphism(f) # optional - sage.modules B[3] # A[1] + 2*B[3] # A[2] - 2*B[4] # A[1] - 4*B[4] # A[2]
\(f\) may be a bilinear morphism to any module over the base ring of \(A\) and \(B\). Here the codomain is \(\ZZ\):
sage: def f(a, b): ....: return sum(a.coefficients(), 0) * sum(b.coefficients(), 0) sage: f(a, b) # optional - sage.modules -3 sage: tensor([a, b]).apply_multilinear_morphism(f) # optional - sage.modules -3
Mind the \(0\) in the sums above; otherwise \(f\) would not return \(0\) in \(\ZZ\):
sage: def f(a,b): ....: return sum(a.coefficients()) * sum(b.coefficients()) sage: type(f(A.zero(), B.zero())) # optional - sage.modules <... 'int'>
Which would be wrong and break this method:
sage: tensor([a, b]).apply_multilinear_morphism(f) # optional - sage.modules Traceback (most recent call last): ... AttributeError: 'int' object has no attribute 'parent'
Here we consider an example where the codomain is a module with basis with a different base ring:
sage: C = CombinatorialFreeModule(QQ, [(1,3),(2,4)], prefix="C") # optional - sage.modules sage: C.rename("C") # optional - sage.modules sage: def f(a, b): ....: return C.sum_of_terms([((1,3), QQ(a[1]*b[3])), ....: ((2,4), QQ(a[2]*b[4]))]) sage: f(a,b) # optional - sage.modules C[(1, 3)] - 4*C[(2, 4)] sage: tensor([a, b]).apply_multilinear_morphism(f) # optional - sage.modules C[(1, 3)] - 4*C[(2, 4)] We conclude with a real life application, where we check that the antipode of the Hopf algebra of Symmetric functions on the Schur basis satisfies its defining formula:: sage: Sym = SymmetricFunctions(QQ) # optional - sage.combinat sage.modules sage: s = Sym.schur() # optional - sage.combinat sage.modules sage: def f(a, b): return a * b.antipode() # optional - sage.combinat sage.modules sage: x = 4 * s.an_element(); x # optional - sage.combinat sage.modules 8*s[] + 8*s[1] + 12*s[2] sage: x.coproduct().apply_multilinear_morphism(f) # optional - sage.combinat sage.modules 8*s[] sage: x.coproduct().apply_multilinear_morphism(f) == x.counit() # optional - sage.combinat sage.modules True
We recover the constant term of \(x\), as desired.
Todo
Extract a method to linearize a multilinear morphism, and delegate the work there.
- class ParentMethods#
Bases:
object
Implements operations on tensor products of modules with basis.
- extra_super_categories()#
EXAMPLES:
sage: ModulesWithBasis(QQ).TensorProducts().extra_super_categories() [Category of vector spaces with basis over Rational Field] sage: ModulesWithBasis(QQ).TensorProducts().super_categories() [Category of tensor products of modules with basis over Rational Field, Category of vector spaces with basis over Rational Field, Category of tensor products of vector spaces over Rational Field]
- is_abelian()#
Return whether this category is abelian.
This is the case if and only if the base ring is a field.
EXAMPLES:
sage: ModulesWithBasis(QQ).is_abelian() True sage: ModulesWithBasis(ZZ).is_abelian() False