Free modules¶
-
class
sage.combinat.free_module.
CartesianProductWithFlattening
(flatten)¶ Bases:
object
A class for Cartesian product constructor, with partial flattening
-
sage.combinat.free_module.
CombinatorialFreeModule
¶ 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() 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), ....: 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), ('latex_bracket', False), ('latex_prefix', None), ('latex_scalar_mult', 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)
-
sage.combinat.free_module.
CombinatorialFreeModule_CartesianProduct
¶ 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.__custom_name = "F" sage: G = CombinatorialFreeModule(ZZ, [4,6]); G.__custom_name = "G" sage: H = CombinatorialFreeModule(ZZ, [4,7]); H.__custom_name = "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
-
sage.combinat.free_module.
CombinatorialFreeModule_Tensor
¶ 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.__custom_name = "F" sage: G = CombinatorialFreeModule(ZZ, [3,4]); G.__custom_name = "G" sage: T = tensor([F, G]); T F # G sage: T.category() Category of finite dimensional tensor products of 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 <... 'tuple'> 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