Free modules#
- class sage.combinat.free_module.CartesianProductWithFlattening(flatten)#
Bases:
object
A class for Cartesian product constructor, with partial flattening
- class sage.combinat.free_module.CombinatorialFreeModule(R, basis_keys=None, element_class=None, category=None, prefix=None, names=None, **kwds)#
Bases:
UniqueRepresentation
,Module
,IndexedGenerators
Class for free modules with a named basis
INPUT:
R
- base ringbasis_keys
- list, tuple, family, set, etc. defining the indexing set for the basis of this moduleelement_class
- the class of which elements of this module should be instances (optional, default None, in which case the elements are instances ofIndexedFreeModuleElement
)category
- the category in which this module lies (optional, default None, in which case use the “category of modules with basis” over the base ringR
); this should be a subcategory ofModulesWithBasis
For the options controlling the printing of elements, see
IndexedGenerators
.Note
These print options may also be accessed and modified using the
print_options()
method, after the module has been defined.EXAMPLES:
We construct a free module whose basis is indexed by the letters a, b, c:
sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) sage: F Free module generated by {'a', 'b', 'c'} over Rational Field
Its basis is a family, indexed by a, b, c:
sage: e = F.basis() sage: e Finite family {'a': B['a'], 'b': B['b'], 'c': B['c']}
sage: [x for x in e] [B['a'], B['b'], B['c']] sage: [k for k in e.keys()] ['a', 'b', 'c']
Let us construct some elements, and compute with them:
sage: e['a'] B['a'] sage: 2*e['a'] 2*B['a'] sage: e['a'] + 3*e['b'] B['a'] + 3*B['b']
Some uses of
sage.categories.commutative_additive_semigroups.CommutativeAdditiveSemigroups.ParentMethods.summation()
andsum()
:sage: F = CombinatorialFreeModule(QQ, [1,2,3,4]) sage: F.summation(F.monomial(1), F.monomial(3)) B[1] + B[3] sage: F = CombinatorialFreeModule(QQ, [1,2,3,4]) sage: F.sum(F.monomial(i) for i in [1,2,3]) B[1] + B[2] + B[3]
Note that free modules with a given basis and parameters are unique:
sage: F1 = CombinatorialFreeModule(QQ, (1,2,3,4)) sage: F1 is F True
The identity of the constructed free module depends on the order of the basis and on the other parameters, like the prefix. Note that
CombinatorialFreeModule
is aUniqueRepresentation
. Hence, two combinatorial free modules evaluate equal if and only if they are identical:sage: F1 = CombinatorialFreeModule(QQ, (1,2,3,4)) sage: F1 is F True sage: F1 = CombinatorialFreeModule(QQ, [4,3,2,1]) sage: F1 == F False sage: F2 = CombinatorialFreeModule(QQ, [1,2,3,4], prefix='F') sage: F2 == F False
Because of this, if you create a free module with certain parameters and then modify its prefix or other print options, this affects all modules which were defined using the same parameters.
sage: F2.print_options(prefix='x') sage: F2.prefix() 'x' sage: F3 = CombinatorialFreeModule(QQ, [1,2,3,4], prefix='F') sage: F3 is F2 # F3 was defined just like F2 True sage: F3.prefix() 'x' sage: F4 = CombinatorialFreeModule(QQ, [1,2,3,4], prefix='F', bracket=True) sage: F4 == F2 # F4 was NOT defined just like F2 False sage: F4.prefix() 'F' sage: F2.print_options(prefix='F') #reset for following doctests
The constructed module is in the category of modules with basis over the base ring:
sage: CombinatorialFreeModule(QQ, Partitions()).category() # needs sage.combinat Category of vector spaces with basis over Rational Field
If furthermore the index set is finite (i.e. in the category
Sets().Finite()
), then the module is declared as being finite dimensional:sage: CombinatorialFreeModule(QQ, [1,2,3,4]).category() Category of finite dimensional vector spaces with basis over Rational Field sage: CombinatorialFreeModule(QQ, Partitions(3), # needs sage.combinat ....: category=Algebras(QQ).WithBasis()).category() Category of finite dimensional algebras with basis over Rational Field
See
sage.categories.examples.algebras_with_basis
andsage.categories.examples.hopf_algebras_with_basis
for illustrations of the use of thecategory
keyword, and seesage.combinat.root_system.weight_space.WeightSpace
for an example of the use ofelement_class
.Customizing print and LaTeX representations of elements:
sage: F = CombinatorialFreeModule(QQ, ['a','b'], prefix='x') sage: original_print_options = F.print_options() sage: sorted(original_print_options.items()) [('bracket', None), ('iterate_key', False), ('latex_bracket', False), ('latex_names', None), ('latex_prefix', None), ('latex_scalar_mult', None), ('names', None), ('prefix', 'x'), ('scalar_mult', '*'), ('sorting_key', <function ...<lambda> at ...>), ('sorting_reverse', False), ('string_quotes', True), ('tensor_symbol', None)] sage: e = F.basis() sage: e['a'] - 3 * e['b'] x['a'] - 3*x['b'] sage: F.print_options(prefix='x', scalar_mult=' ', bracket='{') sage: e['a'] - 3 * e['b'] x{'a'} - 3 x{'b'} sage: latex(e['a'] - 3 * e['b']) x_{a} - 3 x_{b} sage: F.print_options(latex_prefix='y') sage: latex(e['a'] - 3 * e['b']) y_{a} - 3 y_{b} sage: F.print_options(sorting_reverse=True) sage: e['a'] - 3 * e['b'] -3 x{'b'} + x{'a'} sage: F.print_options(**original_print_options) # reset print options sage: F = CombinatorialFreeModule(QQ, [(1,2), (3,4)]) sage: e = F.basis() sage: e[(1,2)] - 3 * e[(3,4)] B[(1, 2)] - 3*B[(3, 4)] sage: F.print_options(bracket=['_{', '}']) sage: e[(1,2)] - 3 * e[(3,4)] B_{(1, 2)} - 3*B_{(3, 4)} sage: F.print_options(prefix='', bracket=False) sage: e[(1,2)] - 3 * e[(3,4)] (1, 2) - 3*(3, 4)
- CartesianProduct#
- Element#
alias of
IndexedFreeModuleElement
- Tensor#
alias of
CombinatorialFreeModule_Tensor
- change_ring(R)#
Return the base change of
self
to \(R\).EXAMPLES:
sage: F = CombinatorialFreeModule(ZZ, ['a','b','c']); F Free module generated by {'a', 'b', 'c'} over Integer Ring sage: F_QQ = F.change_ring(QQ); F_QQ Free module generated by {'a', 'b', 'c'} over Rational Field sage: F_QQ.change_ring(ZZ) == F True
- construction()#
The construction functor and base ring for self.
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a','b','c'], category=AlgebrasWithBasis(QQ)) sage: F.construction() (VectorFunctor, Rational Field)
- dimension()#
Return the dimension of the free module (which is given by the number of elements in the basis).
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) sage: F.dimension() 3 sage: F.basis().cardinality() 3 sage: F.basis().keys().cardinality() 3
Rank is available as a synonym:
sage: F.rank() 3
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage: s.dimension() # needs sage.combinat +Infinity
- element_class()#
The (default) class for the elements of this parent
Overrides
Parent.element_class()
to force the construction of Python class. This is currently needed to inherit really all the features from categories, and in particular the initialization of_mul_
inMagmas.ParentMethods.__init_extra__()
.EXAMPLES:
sage: # needs sage.combinat sage: A = Algebras(QQ).WithBasis().example(); A An example of an algebra with basis: the free algebra on the generators ('a', 'b', 'c') over Rational Field sage: A.element_class.mro() [<class 'sage.categories.examples.algebras_with_basis.FreeAlgebra_with_category.element_class'>, <class 'sage.modules.with_basis.indexed_element.IndexedFreeModuleElement'>, ...] sage: a,b,c = A.algebra_generators() sage: a * b B[word: ab]
- from_vector(vector, order=None, coerce=True)#
Build an element of
self
from a (sparse) vector.See also
get_order()
,CombinatorialFreeModule.Element._vector_()
EXAMPLES:
sage: # needs sage.combinat sage: QS3 = SymmetricGroupAlgebra(QQ, 3) sage: b = QS3.from_vector(vector((2, 0, 0, 0, 0, 4))); b 2*[1, 2, 3] + 4*[3, 2, 1] sage: a = 2*QS3([1,2,3]) + 4*QS3([3,2,1]) sage: a == b True
- get_order()#
Return the order of the elements in the basis.
EXAMPLES:
sage: QS2 = SymmetricGroupAlgebra(QQ,2) # needs sage.combinat sage: QS2.get_order() # note: order changed on 2009-03-13 # needs sage.combinat [[2, 1], [1, 2]]
- get_order_key()#
Return a comparison key on the basis indices that is compatible with the current term order.
EXAMPLES:
sage: A = FiniteDimensionalAlgebrasWithBasis(QQ).example() sage: A.set_order(['x', 'y', 'a', 'b']) sage: Akey = A.get_order_key() sage: sorted(A.basis().keys(), key=Akey) ['x', 'y', 'a', 'b'] sage: A.set_order(list(reversed(A.basis().keys()))) sage: Akey = A.get_order_key() sage: sorted(A.basis().keys(), key=Akey) ['b', 'a', 'y', 'x']
- is_exact()#
Return
True
if elements ofself
have exact representations, which is true ofself
if and only if it is true ofself.basis().keys()
andself.base_ring()
.EXAMPLES:
sage: GroupAlgebra(GL(3, GF(7))).is_exact() # needs sage.groups sage.rings.finite_rings True sage: GroupAlgebra(GL(3, GF(7)), RR).is_exact() # needs sage.groups sage.rings.finite_rings False sage: GroupAlgebra(GL(3, pAdicRing(7))).is_exact() # not implemented, needs sage.groups sage.rings.padics False
- linear_combination(iter_of_elements_coeff, factor_on_left=True)#
Return the linear combination \(\lambda_1 v_1 + \cdots + \lambda_k v_k\) (resp. the linear combination \(v_1 \lambda_1 + \cdots + v_k \lambda_k\)) where
iter_of_elements_coeff
iterates through the sequence \(((v_1, \lambda_1), ..., (v_k, \lambda_k))\).INPUT:
iter_of_elements_coeff
– iterator of pairs(element, coeff)
withelement
inself
andcoeff
inself.base_ring()
factor_on_left
– (optional) ifTrue
, the coefficients are multiplied from the left ifFalse
, the coefficients are multiplied from the right
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, [1,2]) sage: f = F.an_element(); f 2*B[1] + 2*B[2] sage: F.linear_combination( (f,i) for i in range(5) ) 20*B[1] + 20*B[2]
- monomial()#
Return the basis element indexed by
i
.INPUT:
i
– an element of the index set
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) sage: F.monomial('a') B['a']
F.monomial
is in fact (almost) a map:sage: F.monomial Term map from {'a', 'b', 'c'} to Free module generated by {'a', 'b', 'c'} over Rational Field
- rank()#
Return the dimension of the free module (which is given by the number of elements in the basis).
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) sage: F.dimension() 3 sage: F.basis().cardinality() 3 sage: F.basis().keys().cardinality() 3
Rank is available as a synonym:
sage: F.rank() 3
sage: s = SymmetricFunctions(QQ).schur() # needs sage.combinat sage: s.dimension() # needs sage.combinat +Infinity
- set_order(order)#
Set the order of the elements of the basis.
If
set_order()
has not been called, then the ordering is the one used in the generation of the elements of self’s associated enumerated set.Warning
Many cached methods depend on this order, in particular for constructing subspaces and quotients. Changing the order after some computations have been cached does not invalidate the cache, and is likely to introduce inconsistencies.
EXAMPLES:
sage: # needs sage.combinat sage: QS2 = SymmetricGroupAlgebra(QQ,2) sage: b = list(QS2.basis().keys()) sage: b.reverse() sage: QS2.set_order(b) sage: QS2.get_order() [[2, 1], [1, 2]]
- sum(iter_of_elements)#
Return the sum of all elements in
iter_of_elements
.Overrides method inherited from commutative additive monoid as it is much faster on dicts directly.
INPUT:
iter_of_elements
– iterator of elements ofself
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ,[1,2]) sage: f = F.an_element(); f 2*B[1] + 2*B[2] sage: F.sum( f for _ in range(5) ) 10*B[1] + 10*B[2]
- sum_of_terms(terms, distinct=False)#
Construct a sum of terms of
self
.INPUT:
terms
– a list (or iterable) of pairs(index, coeff)
distinct
– (default:False
) whether the indices are guaranteed to be distinct
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) sage: F.sum_of_terms([('a',2), ('c',3)]) 2*B['a'] + 3*B['c']
If
distinct
is True, then the construction is optimized:sage: F.sum_of_terms([('a',2), ('c',3)], distinct = True) 2*B['a'] + 3*B['c']
Warning
Use
distinct=True
only if you are sure that the indices are indeed distinct:sage: F.sum_of_terms([('a',2), ('a',3)], distinct = True) 3*B['a']
Extreme case:
sage: F.sum_of_terms([]) 0
- 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)
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) sage: F.term('a',3) 3*B['a'] sage: F.term('a') B['a']
Design: should this do coercion on the coefficient ring?
- zero()#
EXAMPLES:
sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) sage: F.zero() 0
- class sage.combinat.free_module.CombinatorialFreeModule_CartesianProduct(modules, **options)#
Bases:
CombinatorialFreeModule
An implementation of Cartesian products of modules with basis
EXAMPLES:
We construct two free modules, assign them short names, and construct their Cartesian product:
sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") sage: H = CombinatorialFreeModule(ZZ, [4,7]); H.rename("H") sage: S = cartesian_product([F, G]) sage: S F (+) G sage: S.basis() Lazy family (Term map from Disjoint union of Family ({4, 5}, {4, 6}) to F (+) G(i))_{i in Disjoint union of Family ({4, 5}, {4, 6})}
Note that the indices of the basis elements of F and G intersect non trivially. This is handled by forcing the union to be disjoint:
sage: list(S.basis()) [B[(0, 4)], B[(0, 5)], B[(1, 4)], B[(1, 6)]]
We now compute the Cartesian product of elements of free modules:
sage: f = F.monomial(4) + 2*F.monomial(5) sage: g = 2*G.monomial(4) + G.monomial(6) sage: h = H.monomial(4) + H.monomial(7) sage: cartesian_product([f, g]) B[(0, 4)] + 2*B[(0, 5)] + 2*B[(1, 4)] + B[(1, 6)] sage: cartesian_product([f, g, h]) B[(0, 4)] + 2*B[(0, 5)] + 2*B[(1, 4)] + B[(1, 6)] + B[(2, 4)] + B[(2, 7)] sage: cartesian_product([f, g, h]).parent() F (+) G (+) H
TODO: choose an appropriate semantic for Cartesian products of Cartesian products (associativity?):
sage: S = cartesian_product([cartesian_product([F, G]), H]) # todo: not implemented F (+) G (+) H
- class Element#
Bases:
IndexedFreeModuleElement
- cartesian_embedding(i)#
Return the natural embedding morphism of the
i
-th Cartesian factor (summand) ofself
intoself
.INPUT:
i
– an integer
EXAMPLES:
sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") sage: S = cartesian_product([F, G]) sage: phi = S.cartesian_embedding(0) sage: phi(F.monomial(4) + 2 * F.monomial(5)) B[(0, 4)] + 2*B[(0, 5)] sage: phi(F.monomial(4) + 2 * F.monomial(6)).parent() == S True
- cartesian_factors()#
Return the factors of the Cartesian product.
EXAMPLES:
sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") sage: S = cartesian_product([F, G]) sage: S.cartesian_factors() (F, G)
- cartesian_projection(i)#
Return the natural projection onto the \(i\)-th Cartesian factor (summand) of
self
.INPUT:
i
– an integer
EXAMPLES:
sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") sage: S = cartesian_product([F, G]) sage: x = S.monomial((0,4)) + 2 * S.monomial((0,5)) + 3 * S.monomial((1,6)) sage: S.cartesian_projection(0)(x) B[4] + 2*B[5] sage: S.cartesian_projection(1)(x) 3*B[6] sage: S.cartesian_projection(0)(x).parent() == F True sage: S.cartesian_projection(1)(x).parent() == G True
- summand_embedding(i)#
Return the natural embedding morphism of the
i
-th Cartesian factor (summand) ofself
intoself
.INPUT:
i
– an integer
EXAMPLES:
sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") sage: S = cartesian_product([F, G]) sage: phi = S.cartesian_embedding(0) sage: phi(F.monomial(4) + 2 * F.monomial(5)) B[(0, 4)] + 2*B[(0, 5)] sage: phi(F.monomial(4) + 2 * F.monomial(6)).parent() == S True
- summand_projection(i)#
Return the natural projection onto the \(i\)-th Cartesian factor (summand) of
self
.INPUT:
i
– an integer
EXAMPLES:
sage: F = CombinatorialFreeModule(ZZ, [4,5]); F.rename("F") sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.rename("G") sage: S = cartesian_product([F, G]) sage: x = S.monomial((0,4)) + 2 * S.monomial((0,5)) + 3 * S.monomial((1,6)) sage: S.cartesian_projection(0)(x) B[4] + 2*B[5] sage: S.cartesian_projection(1)(x) 3*B[6] sage: S.cartesian_projection(0)(x).parent() == F True sage: S.cartesian_projection(1)(x).parent() == G True
- class sage.combinat.free_module.CombinatorialFreeModule_Tensor(modules, **options)#
Bases:
CombinatorialFreeModule
Tensor Product of Free Modules
EXAMPLES:
We construct two free modules, assign them short names, and construct their tensor product:
sage: F = CombinatorialFreeModule(ZZ, [1,2]); F.rename("F") sage: G = CombinatorialFreeModule(ZZ, [3,4]); G.rename("G") sage: T = tensor([F, G]); T F # G sage: T.category() Category of tensor products of finite dimensional modules with basis over Integer Ring sage: T.construction() # todo: not implemented [tensor, ]
T is a free module, with same base ring as F and G:
sage: T.base_ring() Integer Ring
The basis of T is indexed by tuples of basis indices of F and G:
sage: T.basis().keys() Image of Cartesian product of {1, 2}, {3, 4} by The map <class 'tuple'> from Cartesian product of {1, 2}, {3, 4} sage: T.basis().keys().list() [(1, 3), (1, 4), (2, 3), (2, 4)]
FIXME: Should elements of a CartesianProduct be tuples (making them hashable)?
Here are the basis elements themselves:
sage: T.basis().cardinality() 4 sage: list(T.basis()) [B[1] # B[3], B[1] # B[4], B[2] # B[3], B[2] # B[4]]
The tensor product is associative and flattens sub tensor products:
sage: H = CombinatorialFreeModule(ZZ, [5,6]); H.rename("H") sage: tensor([F, tensor([G, H])]) F # G # H sage: tensor([tensor([F, G]), H]) F # G # H sage: tensor([F, G, H]) F # G # H
We now compute the tensor product of elements of free modules:
sage: f = F.monomial(1) + 2 * F.monomial(2) sage: g = 2*G.monomial(3) + G.monomial(4) sage: h = H.monomial(5) + H.monomial(6) sage: tensor([f, g]) 2*B[1] # B[3] + B[1] # B[4] + 4*B[2] # B[3] + 2*B[2] # B[4]
Again, the tensor product is associative on elements:
sage: tensor([f, tensor([g, h])]) == tensor([f, g, h]) True sage: tensor([tensor([f, g]), h]) == tensor([f, g, h]) True
Note further that the tensor product spaces need not preexist:
sage: t = tensor([f, g, h]) sage: t.parent() F # G # H
- tensor_constructor(modules)#
INPUT:
modules
– a tuple \((F_1,\dots,F_n)\) of free modules whose tensor product is self
Returns the canonical multilinear morphism from \(F_1 \times \dots \times F_n\) to \(F_1 \otimes \dots \otimes F_n\)
EXAMPLES:
sage: F = CombinatorialFreeModule(ZZ, [1,2]); F.rename("F") sage: G = CombinatorialFreeModule(ZZ, [3,4]); G.rename("G") sage: H = CombinatorialFreeModule(ZZ, [5,6]); H.rename("H") sage: f = F.monomial(1) + 2*F.monomial(2) sage: g = 2*G.monomial(3) + G.monomial(4) sage: h = H.monomial(5) + H.monomial(6) sage: FG = tensor([F, G]) sage: phi_fg = FG.tensor_constructor((F, G)) sage: phi_fg(f, g) 2*B[1] # B[3] + B[1] # B[4] + 4*B[2] # B[3] + 2*B[2] # B[4] sage: FGH = tensor([F, G, H]) sage: phi_fgh = FGH.tensor_constructor((F, G, H)) sage: phi_fgh(f, g, h) 2*B[1] # B[3] # B[5] + 2*B[1] # B[3] # B[6] + B[1] # B[4] # B[5] + B[1] # B[4] # B[6] + 4*B[2] # B[3] # B[5] + 4*B[2] # B[3] # B[6] + 2*B[2] # B[4] # B[5] + 2*B[2] # B[4] # B[6] sage: phi_fg_h = FGH.tensor_constructor((FG, H)) sage: phi_fg_h(phi_fg(f, g), h) 2*B[1] # B[3] # B[5] + 2*B[1] # B[3] # B[6] + B[1] # B[4] # B[5] + B[1] # B[4] # B[6] + 4*B[2] # B[3] # B[5] + 4*B[2] # B[3] # B[6] + 2*B[2] # B[4] # B[5] + 2*B[2] # B[4] # B[6]
- tensor_factors()#
Return the tensor factors of this tensor product.
EXAMPLES:
sage: F = CombinatorialFreeModule(ZZ, [1,2]) sage: F.rename("F") sage: G = CombinatorialFreeModule(ZZ, [3,4]) sage: G.rename("G") sage: T = tensor([F, G]); T F # G sage: T.tensor_factors() (F, G)