Free modules

class sage.combinat.free_module.CartesianProductWithFlattening(flatten)[source]

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)[source]

Bases: UniqueRepresentation, Module, IndexedGenerators

Class for free modules with a named basis.

INPUT:

  • R – base ring

  • basis_keys – list; tuple, family, set, etc. defining the indexing set for the basis of this module

  • element_class – the class of which elements of this module should be instances (default: None, in which case the elements are instances of IndexedFreeModuleElement)

  • category – the category in which this module lies (optional, default None, in which case use the “category of modules with basis” over the base ring R); this should be a subcategory of ModulesWithBasis

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
>>> from sage.all import *
>>> F = CombinatorialFreeModule(QQ, ['a','b','c'])
>>> 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']}
>>> from sage.all import *
>>> e = F.basis()
>>> 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']
>>> from sage.all import *
>>> [x for x in e]
[B['a'], B['b'], B['c']]
>>> [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']
>>> from sage.all import *
>>> e['a']
B['a']
>>> Integer(2)*e['a']
2*B['a']
>>> e['a'] + Integer(3)*e['b']
B['a'] + 3*B['b']

Some uses of sage.categories.commutative_additive_semigroups.CommutativeAdditiveSemigroups.ParentMethods.summation() and sum():

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]
>>> from sage.all import *
>>> F = CombinatorialFreeModule(QQ, [Integer(1),Integer(2),Integer(3),Integer(4)])
>>> F.summation(F.monomial(Integer(1)), F.monomial(Integer(3)))
B[1] + B[3]

>>> F = CombinatorialFreeModule(QQ, [Integer(1),Integer(2),Integer(3),Integer(4)])
>>> F.sum(F.monomial(i) for i in [Integer(1),Integer(2),Integer(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
>>> from sage.all import *
>>> F1 = CombinatorialFreeModule(QQ, (Integer(1),Integer(2),Integer(3),Integer(4)))
>>> 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 a UniqueRepresentation. 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
>>> from sage.all import *
>>> F1 = CombinatorialFreeModule(QQ, (Integer(1),Integer(2),Integer(3),Integer(4)))
>>> F1 is F
True
>>> F1 = CombinatorialFreeModule(QQ, [Integer(4),Integer(3),Integer(2),Integer(1)])
>>> F1 == F
False
>>> F2 = CombinatorialFreeModule(QQ, [Integer(1),Integer(2),Integer(3),Integer(4)], prefix='F')
>>> 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
>>> from sage.all import *
>>> F2.print_options(prefix='x')
>>> F2.prefix()
'x'
>>> F3 = CombinatorialFreeModule(QQ, [Integer(1),Integer(2),Integer(3),Integer(4)], prefix='F')
>>> F3 is F2   # F3 was defined just like F2
True
>>> F3.prefix()
'x'
>>> F4 = CombinatorialFreeModule(QQ, [Integer(1),Integer(2),Integer(3),Integer(4)], prefix='F', bracket=True)
>>> F4 == F2   # F4 was NOT defined just like F2
False
>>> F4.prefix()
'F'

>>> 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
>>> from sage.all import *
>>> 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
>>> from sage.all import *
>>> CombinatorialFreeModule(QQ, [Integer(1),Integer(2),Integer(3),Integer(4)]).category()
Category of finite dimensional vector spaces with basis over Rational Field
>>> CombinatorialFreeModule(QQ, Partitions(Integer(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 and sage.categories.examples.hopf_algebras_with_basis for illustrations of the use of the category keyword, and see sage.combinat.root_system.weight_space.WeightSpace for an example of the use of element_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)
>>> from sage.all import *
>>> F = CombinatorialFreeModule(QQ, ['a','b'], prefix='x')
>>> original_print_options = F.print_options()
>>> 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)]

>>> e = F.basis()
>>> e['a'] - Integer(3) * e['b']
x['a'] - 3*x['b']

>>> F.print_options(prefix='x', scalar_mult=' ', bracket='{')
>>> e['a'] - Integer(3) * e['b']
x{'a'} - 3 x{'b'}
>>> latex(e['a'] - Integer(3) * e['b'])
x_{a} - 3 x_{b}

>>> F.print_options(latex_prefix='y')
>>> latex(e['a'] - Integer(3) * e['b'])
y_{a} - 3  y_{b}

>>> F.print_options(sorting_reverse=True)
>>> e['a'] - Integer(3) * e['b']
-3 x{'b'} + x{'a'}
>>> F.print_options(**original_print_options) # reset print options

>>> F = CombinatorialFreeModule(QQ, [(Integer(1),Integer(2)), (Integer(3),Integer(4))])
>>> e = F.basis()
>>> e[(Integer(1),Integer(2))] - Integer(3) * e[(Integer(3),Integer(4))]
B[(1, 2)] - 3*B[(3, 4)]

>>> F.print_options(bracket=['_{', '}'])
>>> e[(Integer(1),Integer(2))] - Integer(3) * e[(Integer(3),Integer(4))]
B_{(1, 2)} - 3*B_{(3, 4)}

>>> F.print_options(prefix='', bracket=False)
>>> e[(Integer(1),Integer(2))] - Integer(3) * e[(Integer(3),Integer(4))]
(1, 2) - 3*(3, 4)
CartesianProduct[source]

alias of CombinatorialFreeModule_CartesianProduct

Element[source]

alias of IndexedFreeModuleElement

Tensor[source]

alias of CombinatorialFreeModule_Tensor

change_ring(R)[source]

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

sage: T = F.tensor(F); T
Free module generated by {'a', 'b', 'c'} over Integer Ring
 # Free module generated by {'a', 'b', 'c'} over Integer Ring
sage: T.change_ring(QQ)
Free module generated by {'a', 'b', 'c'} over Rational Field
 # Free module generated by {'a', 'b', 'c'} over Rational Field

sage: G = CombinatorialFreeModule(ZZ, ['x','y']); G
Free module generated by {'x', 'y'} over Integer Ring
sage: T = F.cartesian_product(G); T
Free module generated by {'a', 'b', 'c'} over Integer Ring
 (+) Free module generated by {'x', 'y'} over Integer Ring
sage: T.change_ring(QQ)
Free module generated by {'a', 'b', 'c'} over Rational Field
 (+) Free module generated by {'x', 'y'} over Rational Field
>>> from sage.all import *
>>> F = CombinatorialFreeModule(ZZ, ['a','b','c']); F
Free module generated by {'a', 'b', 'c'} over Integer Ring
>>> F_QQ = F.change_ring(QQ); F_QQ
Free module generated by {'a', 'b', 'c'} over Rational Field
>>> F_QQ.change_ring(ZZ) == F
True

>>> T = F.tensor(F); T
Free module generated by {'a', 'b', 'c'} over Integer Ring
 # Free module generated by {'a', 'b', 'c'} over Integer Ring
>>> T.change_ring(QQ)
Free module generated by {'a', 'b', 'c'} over Rational Field
 # Free module generated by {'a', 'b', 'c'} over Rational Field

>>> G = CombinatorialFreeModule(ZZ, ['x','y']); G
Free module generated by {'x', 'y'} over Integer Ring
>>> T = F.cartesian_product(G); T
Free module generated by {'a', 'b', 'c'} over Integer Ring
 (+) Free module generated by {'x', 'y'} over Integer Ring
>>> T.change_ring(QQ)
Free module generated by {'a', 'b', 'c'} over Rational Field
 (+) Free module generated by {'x', 'y'} over Rational Field
construction()[source]

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)
>>> from sage.all import *
>>> F = CombinatorialFreeModule(QQ, ['a','b','c'], category=AlgebrasWithBasis(QQ))
>>> F.construction()
(VectorFunctor, Rational Field)
dimension()[source]

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
>>> from sage.all import *
>>> F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
>>> F.dimension()
3
>>> F.basis().cardinality()
3
>>> F.basis().keys().cardinality()
3

Rank is available as a synonym:

sage: F.rank()
3
>>> from sage.all import *
>>> F.rank()
3

sage: s = SymmetricFunctions(QQ).schur()                                    # needs sage.combinat
sage: s.dimension()                                                         # needs sage.combinat
+Infinity
>>> from sage.all import *
>>> s = SymmetricFunctions(QQ).schur()                                    # needs sage.combinat
>>> s.dimension()                                                         # needs sage.combinat
+Infinity
element_class()[source]

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_ in Magmas.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 sage.all import *
>>> # needs sage.combinat
>>> 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
>>> A.element_class.mro()
[<class 'sage.categories.examples.algebras_with_basis.FreeAlgebra_with_category.element_class'>,
 <class 'sage.modules.with_basis.indexed_element.IndexedFreeModuleElement'>,
 ...]
>>> a,b,c = A.algebra_generators()
>>> a * b
B[word: ab]
from_vector(vector, order=None, coerce=True)[source]

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
>>> from sage.all import *
>>> # needs sage.combinat
>>> QS3 = SymmetricGroupAlgebra(QQ, Integer(3))
>>> b = QS3.from_vector(vector((Integer(2), Integer(0), Integer(0), Integer(0), Integer(0), Integer(4)))); b
2*[1, 2, 3] + 4*[3, 2, 1]
>>> a = Integer(2)*QS3([Integer(1),Integer(2),Integer(3)]) + Integer(4)*QS3([Integer(3),Integer(2),Integer(1)])
>>> a == b
True
get_order()[source]

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]]
>>> from sage.all import *
>>> QS2 = SymmetricGroupAlgebra(QQ,Integer(2))                                     # needs sage.combinat
>>> QS2.get_order()  # note: order changed on 2009-03-13                  # needs sage.combinat
[[2, 1], [1, 2]]
get_order_key()[source]

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']
>>> from sage.all import *
>>> A = FiniteDimensionalAlgebrasWithBasis(QQ).example()
>>> A.set_order(['x', 'y', 'a', 'b'])
>>> Akey = A.get_order_key()
>>> sorted(A.basis().keys(), key=Akey)
['x', 'y', 'a', 'b']
>>> A.set_order(list(reversed(A.basis().keys())))
>>> Akey = A.get_order_key()
>>> sorted(A.basis().keys(), key=Akey)
['b', 'a', 'y', 'x']
is_exact()[source]

Return True if elements of self have exact representations, which is true of self if and only if it is true of self.basis().keys() and self.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
>>> from sage.all import *
>>> GroupAlgebra(GL(Integer(3), GF(Integer(7)))).is_exact()                                 # needs sage.groups sage.rings.finite_rings
True
>>> GroupAlgebra(GL(Integer(3), GF(Integer(7))), RR).is_exact()                             # needs sage.groups sage.rings.finite_rings
False
>>> GroupAlgebra(GL(Integer(3), pAdicRing(Integer(7)))).is_exact()  # not implemented, needs sage.groups sage.rings.padics
False
linear_combination(iter_of_elements_coeff, factor_on_left=True)[source]

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) with element in self and coeff in self.base_ring()

  • factor_on_left – (optional) if True, the coefficients are multiplied from the left if False, 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]
>>> from sage.all import *
>>> F = CombinatorialFreeModule(QQ, [Integer(1),Integer(2)])
>>> f = F.an_element(); f
2*B[1] + 2*B[2]
>>> F.linear_combination( (f,i) for i in range(Integer(5)) )
20*B[1] + 20*B[2]
monomial()[source]

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']
>>> from sage.all import *
>>> F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
>>> 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
>>> from sage.all import *
>>> F.monomial
Term map from {'a', 'b', 'c'} to Free module generated by {'a', 'b', 'c'} over Rational Field
rank()[source]

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
>>> from sage.all import *
>>> F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
>>> F.dimension()
3
>>> F.basis().cardinality()
3
>>> F.basis().keys().cardinality()
3

Rank is available as a synonym:

sage: F.rank()
3
>>> from sage.all import *
>>> F.rank()
3

sage: s = SymmetricFunctions(QQ).schur()                                    # needs sage.combinat
sage: s.dimension()                                                         # needs sage.combinat
+Infinity
>>> from sage.all import *
>>> s = SymmetricFunctions(QQ).schur()                                    # needs sage.combinat
>>> s.dimension()                                                         # needs sage.combinat
+Infinity
set_order(order)[source]

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]]
>>> from sage.all import *
>>> # needs sage.combinat
>>> QS2 = SymmetricGroupAlgebra(QQ,Integer(2))
>>> b = list(QS2.basis().keys())
>>> b.reverse()
>>> QS2.set_order(b)
>>> QS2.get_order()
[[2, 1], [1, 2]]
sum(iter_of_elements)[source]

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 of self

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]
>>> from sage.all import *
>>> F = CombinatorialFreeModule(QQ,[Integer(1),Integer(2)])
>>> f = F.an_element(); f
2*B[1] + 2*B[2]
>>> F.sum( f for _ in range(Integer(5)) )
10*B[1] + 10*B[2]
sum_of_terms(terms, distinct=False)[source]

Construct a sum of terms of self.

INPUT:

  • terms – list (or iterable) of pairs (index, coeff)

  • distinct – boolean (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']
>>> from sage.all import *
>>> F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
>>> F.sum_of_terms([('a',Integer(2)), ('c',Integer(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']
>>> from sage.all import *
>>> F.sum_of_terms([('a',Integer(2)), ('c',Integer(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']
>>> from sage.all import *
>>> F.sum_of_terms([('a',Integer(2)), ('a',Integer(3))], distinct = True)
3*B['a']

Extreme case:

sage: F.sum_of_terms([])
0
>>> from sage.all import *
>>> F.sum_of_terms([])
0
term(index, coeff=None)[source]

Construct a term in self.

INPUT:

  • index – the index of a basis element

  • coeff – 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']
>>> from sage.all import *
>>> F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
>>> F.term('a',Integer(3))
3*B['a']
>>> F.term('a')
B['a']

Design: should this do coercion on the coefficient ring?

zero()[source]

EXAMPLES:

sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
sage: F.zero()
0
>>> from sage.all import *
>>> F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'])
>>> F.zero()
0
class sage.combinat.free_module.CombinatorialFreeModule_CartesianProduct(modules, **options)[source]

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})}
>>> from sage.all import *
>>> F = CombinatorialFreeModule(ZZ, [Integer(4),Integer(5)]); F.rename('F')
>>> G = CombinatorialFreeModule(ZZ, [Integer(4),Integer(6)]); G.rename('G')
>>> H = CombinatorialFreeModule(ZZ, [Integer(4),Integer(7)]); H.rename('H')
>>> S = cartesian_product([F, G])
>>> S
F (+) G
>>> 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)]]
>>> from sage.all import *
>>> 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
>>> from sage.all import *
>>> f =   F.monomial(Integer(4)) + Integer(2)*F.monomial(Integer(5))
>>> g = Integer(2)*G.monomial(Integer(4)) +   G.monomial(Integer(6))
>>> h =   H.monomial(Integer(4)) +   H.monomial(Integer(7))
>>> cartesian_product([f, g])
B[(0, 4)] + 2*B[(0, 5)] + 2*B[(1, 4)] + B[(1, 6)]
>>> 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)]
>>> 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
>>> from sage.all import *
>>> S = cartesian_product([cartesian_product([F, G]), H])  # todo: not implemented
F (+) G (+) H
class Element[source]

Bases: IndexedFreeModuleElement

cartesian_embedding(i)[source]

Return the natural embedding morphism of the i-th Cartesian factor (summand) of self into self.

INPUT:

  • i – 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
>>> from sage.all import *
>>> F = CombinatorialFreeModule(ZZ, [Integer(4),Integer(5)]); F.rename('F')
>>> G = CombinatorialFreeModule(ZZ, [Integer(4),Integer(6)]); G.rename('G')
>>> S = cartesian_product([F, G])
>>> phi = S.cartesian_embedding(Integer(0))
>>> phi(F.monomial(Integer(4)) + Integer(2) * F.monomial(Integer(5)))
B[(0, 4)] + 2*B[(0, 5)]
>>> phi(F.monomial(Integer(4)) + Integer(2) * F.monomial(Integer(6))).parent() == S
True
cartesian_factors()[source]

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)
>>> from sage.all import *
>>> F = CombinatorialFreeModule(ZZ, [Integer(4),Integer(5)]); F.rename('F')
>>> G = CombinatorialFreeModule(ZZ, [Integer(4),Integer(6)]); G.rename('G')
>>> S = cartesian_product([F, G])
>>> S.cartesian_factors()
(F, G)
cartesian_projection(i)[source]

Return the natural projection onto the \(i\)-th Cartesian factor (summand) of self.

INPUT:

  • i – 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
>>> from sage.all import *
>>> F = CombinatorialFreeModule(ZZ, [Integer(4),Integer(5)]); F.rename('F')
>>> G = CombinatorialFreeModule(ZZ, [Integer(4),Integer(6)]); G.rename('G')
>>> S = cartesian_product([F, G])
>>> x = S.monomial((Integer(0),Integer(4))) + Integer(2) * S.monomial((Integer(0),Integer(5))) + Integer(3) * S.monomial((Integer(1),Integer(6)))
>>> S.cartesian_projection(Integer(0))(x)
B[4] + 2*B[5]
>>> S.cartesian_projection(Integer(1))(x)
3*B[6]
>>> S.cartesian_projection(Integer(0))(x).parent() == F
True
>>> S.cartesian_projection(Integer(1))(x).parent() == G
True
summand_embedding(i)[source]

Return the natural embedding morphism of the i-th Cartesian factor (summand) of self into self.

INPUT:

  • i – 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
>>> from sage.all import *
>>> F = CombinatorialFreeModule(ZZ, [Integer(4),Integer(5)]); F.rename('F')
>>> G = CombinatorialFreeModule(ZZ, [Integer(4),Integer(6)]); G.rename('G')
>>> S = cartesian_product([F, G])
>>> phi = S.cartesian_embedding(Integer(0))
>>> phi(F.monomial(Integer(4)) + Integer(2) * F.monomial(Integer(5)))
B[(0, 4)] + 2*B[(0, 5)]
>>> phi(F.monomial(Integer(4)) + Integer(2) * F.monomial(Integer(6))).parent() == S
True
summand_projection(i)[source]

Return the natural projection onto the \(i\)-th Cartesian factor (summand) of self.

INPUT:

  • i – 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
>>> from sage.all import *
>>> F = CombinatorialFreeModule(ZZ, [Integer(4),Integer(5)]); F.rename('F')
>>> G = CombinatorialFreeModule(ZZ, [Integer(4),Integer(6)]); G.rename('G')
>>> S = cartesian_product([F, G])
>>> x = S.monomial((Integer(0),Integer(4))) + Integer(2) * S.monomial((Integer(0),Integer(5))) + Integer(3) * S.monomial((Integer(1),Integer(6)))
>>> S.cartesian_projection(Integer(0))(x)
B[4] + 2*B[5]
>>> S.cartesian_projection(Integer(1))(x)
3*B[6]
>>> S.cartesian_projection(Integer(0))(x).parent() == F
True
>>> S.cartesian_projection(Integer(1))(x).parent() == G
True
class sage.combinat.free_module.CombinatorialFreeModule_Tensor(modules, **options)[source]

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, ]
>>> from sage.all import *
>>> F = CombinatorialFreeModule(ZZ, [Integer(1),Integer(2)]); F.rename('F')
>>> G = CombinatorialFreeModule(ZZ, [Integer(3),Integer(4)]); G.rename('G')
>>> T = tensor([F, G]); T
F # G

>>> T.category()
Category of tensor products of
 finite dimensional modules with basis over Integer Ring

>>> 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
>>> from sage.all import *
>>> 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)]
>>> from sage.all import *
>>> 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}
>>> 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]]
>>> from sage.all import *
>>> T.basis().cardinality()
4
>>> 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
>>> from sage.all import *
>>> H = CombinatorialFreeModule(ZZ, [Integer(5),Integer(6)]); H.rename('H')
>>> tensor([F, tensor([G, H])])
F # G # H
>>> tensor([tensor([F, G]), H])
F # G # H
>>> 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]
>>> from sage.all import *
>>> f =   F.monomial(Integer(1)) + Integer(2) * F.monomial(Integer(2))
>>> g = Integer(2)*G.monomial(Integer(3)) +     G.monomial(Integer(4))
>>> h =   H.monomial(Integer(5)) +     H.monomial(Integer(6))
>>> 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
>>> from sage.all import *
>>> tensor([f, tensor([g, h])]) == tensor([f, g, h])
True
>>> 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
>>> from sage.all import *
>>> t = tensor([f, g, h])
>>> t.parent()
F # G # H
tensor_constructor(modules)[source]

INPUT:

  • modules – 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]
>>> from sage.all import *
>>> F = CombinatorialFreeModule(ZZ, [Integer(1),Integer(2)]); F.rename('F')
>>> G = CombinatorialFreeModule(ZZ, [Integer(3),Integer(4)]); G.rename('G')
>>> H = CombinatorialFreeModule(ZZ, [Integer(5),Integer(6)]); H.rename('H')

>>> f =   F.monomial(Integer(1)) + Integer(2)*F.monomial(Integer(2))
>>> g = Integer(2)*G.monomial(Integer(3)) +   G.monomial(Integer(4))
>>> h =   H.monomial(Integer(5)) +   H.monomial(Integer(6))
>>> FG = tensor([F, G])
>>> phi_fg = FG.tensor_constructor((F, G))
>>> phi_fg(f, g)
2*B[1] # B[3] + B[1] # B[4] + 4*B[2] # B[3] + 2*B[2] # B[4]

>>> FGH = tensor([F, G, H])
>>> phi_fgh = FGH.tensor_constructor((F, G, H))
>>> 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]

>>> phi_fg_h = FGH.tensor_constructor((FG, H))
>>> 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()[source]

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)
>>> from sage.all import *
>>> F = CombinatorialFreeModule(ZZ, [Integer(1),Integer(2)])
>>> F.rename('F')
>>> G = CombinatorialFreeModule(ZZ, [Integer(3),Integer(4)])
>>> G.rename('G')
>>> T = tensor([F, G]); T
F # G
>>> T.tensor_factors()
(F, G)