Free modules of finite rank#
The class FiniteRankFreeModule
implements free modules of finite rank
over a commutative ring.
A free module of finite rank over a commutative ring \(R\) is a module \(M\) over \(R\) that admits a finite basis, i.e. a finite family of linearly independent generators. Since \(R\) is commutative, it has the invariant basis number property, so that the rank of the free module \(M\) is defined uniquely, as the cardinality of any basis of \(M\).
No distinguished basis of \(M\) is assumed. On the contrary, many bases can be introduced on the free module along with change-of-basis rules (as module automorphisms). Each module element has then various representations over the various bases.
Note
The class FiniteRankFreeModule
does not inherit from
class FreeModule_generic
nor from class
CombinatorialFreeModule
, since
both classes deal with modules with a distinguished basis (see
details below). Accordingly, the class
FiniteRankFreeModule
inherits directly from the generic class
Parent
with the category set to
Modules
(and not to
ModulesWithBasis
).
Todo
implement submodules
create a FreeModules category (cf. the TODO statement in the documentation of
Modules
: Implement a ``FreeModules(R)`` category, when so prompted by a concrete use case)
AUTHORS:
Eric Gourgoulhon, Michal Bejger (2014-2015): initial version
Travis Scrimshaw (2016): category set to
Modules(ring).FiniteDimensional()
(trac ticket #20770)Michael Jung (2019): improve treatment of the zero element
Eric Gourgoulhon (2021): unicode symbols for tensor and exterior products
Matthias Koeppe (2022):
FiniteRankFreeModule_abstract
, symmetric powers
REFERENCES:
EXAMPLES:
Let us define a free module of rank 2 over \(\ZZ\):
sage: M = FiniteRankFreeModule(ZZ, 2, name='M') ; M
Rank-2 free module M over the Integer Ring
sage: M.category()
Category of finite dimensional modules over Integer Ring
We introduce a first basis on M
:
sage: e = M.basis('e') ; e
Basis (e_0,e_1) on the Rank-2 free module M over the Integer Ring
The elements of the basis are of course module elements:
sage: e[0]
Element e_0 of the Rank-2 free module M over the Integer Ring
sage: e[1]
Element e_1 of the Rank-2 free module M over the Integer Ring
sage: e[0].parent()
Rank-2 free module M over the Integer Ring
We define a module element by its components w.r.t. basis e
:
sage: u = M([2,-3], basis=e, name='u')
sage: u.display(e)
u = 2 e_0 - 3 e_1
Module elements can be also be created by arithmetic expressions:
sage: v = -2*u + 4*e[0] ; v
Element of the Rank-2 free module M over the Integer Ring
sage: v.display(e)
6 e_1
sage: u == 2*e[0] - 3*e[1]
True
We define a second basis on M
from a family of linearly independent
elements:
sage: f = M.basis('f', from_family=(e[0]-e[1], -2*e[0]+3*e[1])) ; f
Basis (f_0,f_1) on the Rank-2 free module M over the Integer Ring
sage: f[0].display(e)
f_0 = e_0 - e_1
sage: f[1].display(e)
f_1 = -2 e_0 + 3 e_1
We may of course express the elements of basis e
in terms of basis f
:
sage: e[0].display(f)
e_0 = 3 f_0 + f_1
sage: e[1].display(f)
e_1 = 2 f_0 + f_1
as well as any module element:
sage: u.display(f)
u = -f_1
sage: v.display(f)
12 f_0 + 6 f_1
The two bases are related by a module automorphism:
sage: a = M.change_of_basis(e,f) ; a
Automorphism of the Rank-2 free module M over the Integer Ring
sage: a.parent()
General linear group of the Rank-2 free module M over the Integer Ring
sage: a.matrix(e)
[ 1 -2]
[-1 3]
Let us check that basis f
is indeed the image of basis e
by a
:
sage: f[0] == a(e[0])
True
sage: f[1] == a(e[1])
True
The reverse change of basis is of course the inverse automorphism:
sage: M.change_of_basis(f,e) == a^(-1)
True
We introduce a new module element via its components w.r.t. basis f
:
sage: v = M([2,4], basis=f, name='v')
sage: v.display(f)
v = 2 f_0 + 4 f_1
The sum of the two module elements u
and v
can be performed even if
they have been defined on different bases, thanks to the known relation
between the two bases:
sage: s = u + v ; s
Element u+v of the Rank-2 free module M over the Integer Ring
We can display the result in either basis:
sage: s.display(e)
u+v = -4 e_0 + 7 e_1
sage: s.display(f)
u+v = 2 f_0 + 3 f_1
Tensor products of elements are implemented:
sage: t = u*v ; t
Type-(2,0) tensor u⊗v on the Rank-2 free module M over the Integer Ring
sage: t.parent()
Free module of type-(2,0) tensors on the
Rank-2 free module M over the Integer Ring
sage: t.display(e)
u⊗v = -12 e_0⊗e_0 + 20 e_0⊗e_1 + 18 e_1⊗e_0 - 30 e_1⊗e_1
sage: t.display(f)
u⊗v = -2 f_1⊗f_0 - 4 f_1⊗f_1
We can access to tensor components w.r.t. to a given basis via the square bracket operator:
sage: t[e,0,1]
20
sage: t[f,1,0]
-2
sage: u[e,0]
2
sage: u[e,:]
[2, -3]
sage: u[f,:]
[0, -1]
The parent of the automorphism a
is the group \(\mathrm{GL}(M)\), but
a
can also be considered as a tensor of type \((1,1)\) on M
:
sage: a.parent()
General linear group of the Rank-2 free module M over the Integer Ring
sage: a.tensor_type()
(1, 1)
sage: a.display(e)
e_0⊗e^0 - 2 e_0⊗e^1 - e_1⊗e^0 + 3 e_1⊗e^1
sage: a.display(f)
f_0⊗f^0 - 2 f_0⊗f^1 - f_1⊗f^0 + 3 f_1⊗f^1
As such, we can form its tensor product with t
, yielding a tensor of
type \((3,1)\):
sage: t*a
Type-(3,1) tensor on the Rank-2 free module M over the Integer Ring
sage: (t*a).display(e)
-12 e_0⊗e_0⊗e_0⊗e^0 + 24 e_0⊗e_0⊗e_0⊗e^1 + 12 e_0⊗e_0⊗e_1⊗e^0
- 36 e_0⊗e_0⊗e_1⊗e^1 + 20 e_0⊗e_1⊗e_0⊗e^0 - 40 e_0⊗e_1⊗e_0⊗e^1
- 20 e_0⊗e_1⊗e_1⊗e^0 + 60 e_0⊗e_1⊗e_1⊗e^1 + 18 e_1⊗e_0⊗e_0⊗e^0
- 36 e_1⊗e_0⊗e_0⊗e^1 - 18 e_1⊗e_0⊗e_1⊗e^0 + 54 e_1⊗e_0⊗e_1⊗e^1
- 30 e_1⊗e_1⊗e_0⊗e^0 + 60 e_1⊗e_1⊗e_0⊗e^1 + 30 e_1⊗e_1⊗e_1⊗e^0
- 90 e_1⊗e_1⊗e_1⊗e^1
The parent of \(t\otimes a\) is itself a free module of finite rank over \(\ZZ\):
sage: T = (t*a).parent() ; T
Free module of type-(3,1) tensors on the Rank-2 free module M over the
Integer Ring
sage: T.base_ring()
Integer Ring
sage: T.rank()
16
Differences between FiniteRankFreeModule
and FreeModule
(or VectorSpace
)
To illustrate the differences, let us create two free modules of rank 3 over
\(\ZZ\), one with FiniteRankFreeModule
and the other one with
FreeModule
:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') ; M
Rank-3 free module M over the Integer Ring
sage: N = FreeModule(ZZ, 3) ; N
Ambient free module of rank 3 over the principal ideal domain Integer Ring
The main difference is that FreeModule
returns a free module with a
distinguished basis, while FiniteRankFreeModule
does not:
sage: N.basis()
[
(1, 0, 0),
(0, 1, 0),
(0, 0, 1)
]
sage: M.bases()
[]
sage: M.print_bases()
No basis has been defined on the Rank-3 free module M over the Integer Ring
This is also revealed by the category of each module:
sage: M.category()
Category of finite dimensional modules over Integer Ring
sage: N.category()
Category of finite dimensional modules with basis over
(euclidean domains and infinite enumerated sets and metric spaces)
In other words, the module created by FreeModule
is actually \(\ZZ^3\),
while, in the absence of any distinguished basis, no canonical isomorphism
relates the module created by FiniteRankFreeModule
to \(\ZZ^3\):
sage: N is ZZ^3
True
sage: M is ZZ^3
False
sage: M == ZZ^3
False
Because it is \(\ZZ^3\), N
is unique, while there may be various modules
of the same rank over the same ring created by FiniteRankFreeModule
;
they are then distinguished by their names (actually by the complete
sequence of arguments of FiniteRankFreeModule
):
sage: N1 = FreeModule(ZZ, 3) ; N1
Ambient free module of rank 3 over the principal ideal domain Integer Ring
sage: N1 is N # FreeModule(ZZ, 3) is unique
True
sage: M1 = FiniteRankFreeModule(ZZ, 3, name='M_1') ; M1
Rank-3 free module M_1 over the Integer Ring
sage: M1 is M # M1 and M are different rank-3 modules over ZZ
False
sage: M1b = FiniteRankFreeModule(ZZ, 3, name='M_1') ; M1b
Rank-3 free module M_1 over the Integer Ring
sage: M1b is M1 # because M1b and M1 have the same name
True
As illustrated above, various bases can be introduced on the module created by
FiniteRankFreeModule
:
sage: e = M.basis('e') ; e
Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring
sage: f = M.basis('f', from_family=(-e[0], e[1]-e[2], -2*e[1]+3*e[2])) ; f
Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring
sage: M.bases()
[Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring,
Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring]
Each element of a basis is accessible via its index:
sage: e[0]
Element e_0 of the Rank-3 free module M over the Integer Ring
sage: e[0].parent()
Rank-3 free module M over the Integer Ring
sage: f[1]
Element f_1 of the Rank-3 free module M over the Integer Ring
sage: f[1].parent()
Rank-3 free module M over the Integer Ring
while on module N
, the element of the (unique) basis is accessible
directly from the module symbol:
sage: N.0
(1, 0, 0)
sage: N.1
(0, 1, 0)
sage: N.0.parent()
Ambient free module of rank 3 over the principal ideal domain Integer Ring
The arithmetic of elements is similar; the difference lies in the display:
a basis has to be specified for elements of M
, while elements of N
are
displayed directly as elements of \(\ZZ^3\):
sage: u = 2*e[0] - 3*e[2] ; u
Element of the Rank-3 free module M over the Integer Ring
sage: u.display(e)
2 e_0 - 3 e_2
sage: u.display(f)
-2 f_0 - 6 f_1 - 3 f_2
sage: u[e,:]
[2, 0, -3]
sage: u[f,:]
[-2, -6, -3]
sage: v = 2*N.0 - 3*N.2 ; v
(2, 0, -3)
For the case of M
, in order to avoid to specify the basis if the user is
always working with the same basis (e.g. only one basis has been defined),
the concept of default basis has been introduced:
sage: M.default_basis()
Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring
sage: M.print_bases()
Bases defined on the Rank-3 free module M over the Integer Ring:
- (e_0,e_1,e_2) (default basis)
- (f_0,f_1,f_2)
This is different from the distinguished basis of N
: it simply means that
the mention of the basis can be omitted in function arguments:
sage: u.display() # equivalent to u.display(e)
2 e_0 - 3 e_2
sage: u[:] # equivalent to u[e,:]
[2, 0, -3]
At any time, the default basis can be changed:
sage: M.set_default_basis(f)
sage: u.display()
-2 f_0 - 6 f_1 - 3 f_2
Another difference between FiniteRankFreeModule
and FreeModule
is that
for the former the range of indices can be specified (by default, it starts
from 0):
sage: M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1) ; M
Rank-3 free module M over the Integer Ring
sage: e = M.basis('e') ; e # compare with (e_0,e_1,e_2) above
Basis (e_1,e_2,e_3) on the Rank-3 free module M over the Integer Ring
sage: e[1], e[2], e[3]
(Element e_1 of the Rank-3 free module M over the Integer Ring,
Element e_2 of the Rank-3 free module M over the Integer Ring,
Element e_3 of the Rank-3 free module M over the Integer Ring)
All the above holds for VectorSpace
instead of FreeModule
: the object
created by VectorSpace
is actually a Cartesian power of the base field:
sage: V = VectorSpace(QQ,3) ; V
Vector space of dimension 3 over Rational Field
sage: V.category()
Category of finite dimensional vector spaces with basis
over (number fields and quotient fields and metric spaces)
sage: V is QQ^3
True
sage: V.basis()
[
(1, 0, 0),
(0, 1, 0),
(0, 0, 1)
]
To create a vector space without any distinguished basis, one has to use
FiniteRankFreeModule
:
sage: V = FiniteRankFreeModule(QQ, 3, name='V') ; V
3-dimensional vector space V over the Rational Field
sage: V.category()
Category of finite dimensional vector spaces over Rational Field
sage: V.bases()
[]
sage: V.print_bases()
No basis has been defined on the 3-dimensional vector space V over the
Rational Field
The class FiniteRankFreeModule
has been created for the needs
of the SageManifolds project, where
free modules do not have any distinguished basis. Too kinds of free modules
occur in the context of differentiable manifolds (see
here for more
details):
the tangent vector space at any point of the manifold (cf.
TangentSpace
);the set of vector fields on a parallelizable open subset \(U\) of the manifold, which is a free module over the algebra of scalar fields on \(U\) (cf.
VectorFieldFreeModule
).
For instance, without any specific coordinate choice, no basis can be distinguished in a tangent space.
On the other side, the modules created by FreeModule
have much more
algebraic functionalities than those created by FiniteRankFreeModule
. In
particular, submodules have not been implemented yet in
FiniteRankFreeModule
. Moreover, modules resulting from FreeModule
are tailored to the specific kind of their base ring:
free module over a commutative ring that is not an integral domain (\(\ZZ/6\ZZ\)):
sage: R = IntegerModRing(6) ; R Ring of integers modulo 6 sage: FreeModule(R, 3) Ambient free module of rank 3 over Ring of integers modulo 6 sage: type(FreeModule(R, 3)) <class 'sage.modules.free_module.FreeModule_ambient_with_category'>
free module over an integral domain that is not principal (\(\ZZ[X]\)):
sage: R.<X> = ZZ[] ; R Univariate Polynomial Ring in X over Integer Ring sage: FreeModule(R, 3) Ambient free module of rank 3 over the integral domain Univariate Polynomial Ring in X over Integer Ring sage: type(FreeModule(R, 3)) <class 'sage.modules.free_module.FreeModule_ambient_domain_with_category'>
free module over a principal ideal domain (\(\ZZ\)):
sage: R = ZZ ; R Integer Ring sage: FreeModule(R,3) Ambient free module of rank 3 over the principal ideal domain Integer Ring sage: type(FreeModule(R, 3)) <class 'sage.modules.free_module.FreeModule_ambient_pid_with_category'>
On the contrary, all objects constructed with FiniteRankFreeModule
belong
to the same class:
sage: R = IntegerModRing(6)
sage: type(FiniteRankFreeModule(R, 3))
<class 'sage.tensor.modules.finite_rank_free_module.FiniteRankFreeModule_with_category'>
sage: R.<X> = ZZ[]
sage: type(FiniteRankFreeModule(R, 3))
<class 'sage.tensor.modules.finite_rank_free_module.FiniteRankFreeModule_with_category'>
sage: R = ZZ
sage: type(FiniteRankFreeModule(R, 3))
<class 'sage.tensor.modules.finite_rank_free_module.FiniteRankFreeModule_with_category'>
Differences between FiniteRankFreeModule
and
CombinatorialFreeModule
An alternative to construct free modules in Sage is
CombinatorialFreeModule
.
However, as FreeModule
, it leads to a module with a distinguished basis:
sage: N = CombinatorialFreeModule(ZZ, [1,2,3]) ; N
Free module generated by {1, 2, 3} over Integer Ring
sage: N.category()
Category of finite dimensional modules with basis over Integer Ring
The distinguished basis is returned by the method basis()
:
sage: b = N.basis() ; b
Finite family {1: B[1], 2: B[2], 3: B[3]}
sage: b[1]
B[1]
sage: b[1].parent()
Free module generated by {1, 2, 3} over Integer Ring
For the free module M
created above with FiniteRankFreeModule
, the
method basis
has at least one argument: the symbol string that
specifies which basis is required:
sage: e = M.basis('e') ; e
Basis (e_1,e_2,e_3) on the Rank-3 free module M over the Integer Ring
sage: e[1]
Element e_1 of the Rank-3 free module M over the Integer Ring
sage: e[1].parent()
Rank-3 free module M over the Integer Ring
The arithmetic of elements is similar:
sage: u = 2*e[1] - 5*e[3] ; u
Element of the Rank-3 free module M over the Integer Ring
sage: v = 2*b[1] - 5*b[3] ; v
2*B[1] - 5*B[3]
One notices that elements of N
are displayed directly in terms of their
expansions on the distinguished basis. For elements of M
, one has to use
the method
display()
in order to specify the basis:
sage: u.display(e)
2 e_1 - 5 e_3
The components on the basis are returned by the square bracket operator for
M
and by the method coefficient
for N
:
sage: [u[e,i] for i in {1,2,3}]
[2, 0, -5]
sage: u[e,:] # a shortcut for the above
[2, 0, -5]
sage: [v.coefficient(i) for i in {1,2,3}]
[2, 0, -5]
- class sage.tensor.modules.finite_rank_free_module.FiniteRankDualFreeModule(fmodule, name=None, latex_name=None)#
Bases:
sage.tensor.modules.finite_rank_free_module.FiniteRankFreeModule_abstract
Dual of a free module of finite rank over a commutative ring.
Given a free module \(M\) of finite rank over a commutative ring \(R\), the dual of \(M\) is the set \(M^*\) of all linear forms on \(M\), i.e., linear maps
\[M \longrightarrow R\]This is a Sage parent class, whose element class is
FreeModuleAltForm
.INPUT:
fmodule
– free module \(M\) of finite rank, as an instance ofFiniteRankFreeModule
name
– (default:None
) string; name given to \(M^*\)latex_name
– (default:None
) string; LaTeX symbol to denote \(M^*\)
EXAMPLES:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: A = M.dual(); A Dual of the Rank-3 free module M over the Integer Ring
A
is a module (actually a free module) over \(\ZZ\):sage: A.category() Category of finite dimensional modules over Integer Ring sage: A in Modules(ZZ) True sage: A.rank() 3 sage: A.base_ring() Integer Ring sage: A.base_module() Rank-3 free module M over the Integer Ring
A
is a parent object, whose elements are linear forms, represented by instances of the classFreeModuleAltForm
:sage: a = A.an_element() ; a Linear form on the Rank-3 free module M over the Integer Ring sage: a.display() # expansion with respect to M's default basis (e) e^0 sage: from sage.tensor.modules.free_module_alt_form import FreeModuleAltForm sage: isinstance(a, FreeModuleAltForm) True sage: a in A True sage: A.is_parent_of(a) True
Elements can be constructed from
A
. In particular, 0 yields the zero element ofA
:sage: A(0) Linear form zero on the Rank-3 free module M over the Integer Ring sage: A(0) is A.zero() True
while non-zero elements are constructed by providing their components in a given basis:
sage: e Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring sage: comp = [0,3,-1] sage: a = A(comp, basis=e, name='a') ; a Linear form a on the Rank-3 free module M over the Integer Ring sage: a.display(e) a = 3 e^1 - e^2
An alternative is to construct the alternating form from an empty list of components and to set the nonzero components afterwards:
sage: a = A([], name='a') sage: a.set_comp(e)[0] = 3 sage: a.set_comp(e)[1] = -1 sage: a.set_comp(e)[2] = 4 sage: a.display(e) a = 3 e^0 - e^1 + 4 e^2
The dual is unique:
sage: A is M.dual() True
The exterior power \(\Lambda^1(M^*)\) is nothing but \(M^*\):
sage: M.dual_exterior_power(1) is M.dual() True
It also coincides with the module of type-\((0,1)\) tensors:
sage: M.dual_exterior_power(1) is M.tensor_module(0,1) True
- Element#
alias of
sage.tensor.modules.free_module_alt_form.FreeModuleAltForm
- base_module()#
Return the free module on which
self
is constructed.OUTPUT:
instance of
FiniteRankFreeModule
representing the free module on which the dual is defined.
EXAMPLES:
sage: M = FiniteRankFreeModule(ZZ, 5, name='M') sage: A = M.dual() sage: A.base_module() Rank-5 free module M over the Integer Ring sage: A.base_module() is M True
- construction()#
Return the functorial construction of
self
.This implementation just returns
None
, as no functorial construction is implemented.
- tensor_type()#
Return the tensor type of
self
.EXAMPLES:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: M.dual().tensor_type() (0, 1)
- zero()#
Return the zero of
self
.EXAMPLES:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: A = M.dual() sage: A.zero() Linear form zero on the Rank-3 free module M over the Integer Ring sage: A(0) is A.zero() True
- class sage.tensor.modules.finite_rank_free_module.FiniteRankFreeModule(ring, rank, name=None, latex_name=None, start_index=0, output_formatter=None, category=None, ambient=None)#
Bases:
sage.tensor.modules.finite_rank_free_module.FiniteRankFreeModule_abstract
Free module of finite rank over a commutative ring.
A free module of finite rank over a commutative ring \(R\) is a module \(M\) over \(R\) that admits a finite basis, i.e. a finite family of linearly independent generators. Since \(R\) is commutative, it has the invariant basis number property, so that the rank of the free module \(M\) is defined uniquely, as the cardinality of any basis of \(M\).
No distinguished basis of \(M\) is assumed. On the contrary, many bases can be introduced on the free module along with change-of-basis rules (as module automorphisms). Each module element has then various representations over the various bases.
Note
The class
FiniteRankFreeModule
does not inherit from classFreeModule_generic
nor from classCombinatorialFreeModule
, since both classes deal with modules with a distinguished basis (see details above). Moreover, following the recommendation exposed in trac ticket #16427 the classFiniteRankFreeModule
inherits directly fromParent
(with the category set toModules
) and not from the Cython classModule
.The class
FiniteRankFreeModule
is a Sage parent class, the corresponding element class beingFiniteRankFreeModuleElement
.INPUT:
ring
– commutative ring \(R\) over which the free module is constructedrank
– positive integer; rank of the free modulename
– (default:None
) string; name given to the free modulelatex_name
– (default:None
) string; LaTeX symbol to denote the freemodule; if none is provided, it is set toname
start_index
– (default: 0) integer; lower bound of the range of indices in bases defined on the free moduleoutput_formatter
– (default:None
) function or unbound method called to format the output of the tensor components;output_formatter
must take 1 or 2 arguments: the first argument must be an element of the ring \(R\) and the second one, if any, some format specification
EXAMPLES:
Free module of rank 3 over \(\ZZ\):
sage: FiniteRankFreeModule._clear_cache_() # for doctests only sage: M = FiniteRankFreeModule(ZZ, 3) ; M Rank-3 free module over the Integer Ring sage: M = FiniteRankFreeModule(ZZ, 3, name='M') ; M # declaration with a name Rank-3 free module M over the Integer Ring sage: M.category() Category of finite dimensional modules over Integer Ring sage: M.base_ring() Integer Ring sage: M.rank() 3
If the base ring is a field, the free module is in the category of vector spaces:
sage: V = FiniteRankFreeModule(QQ, 3, name='V') ; V 3-dimensional vector space V over the Rational Field sage: V.category() Category of finite dimensional vector spaces over Rational Field
The LaTeX output is adjusted via the parameter
latex_name
:sage: latex(M) # the default is the symbol provided in the string ``name`` M sage: M = FiniteRankFreeModule(ZZ, 3, name='M', latex_name=r'\mathcal{M}') sage: latex(M) \mathcal{M}
The free module M has no distinguished basis:
sage: M in ModulesWithBasis(ZZ) False sage: M in Modules(ZZ) True
In particular, no basis is initialized at the module construction:
sage: M.print_bases() No basis has been defined on the Rank-3 free module M over the Integer Ring sage: M.bases() []
Bases have to be introduced by means of the method
basis()
, the first defined basis being considered as the default basis, meaning it can be skipped in function arguments required a basis (this can be changed by means of the methodset_default_basis()
):sage: e = M.basis('e') ; e Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring sage: M.default_basis() Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring
A second basis can be created from a family of linearly independent elements expressed in terms of basis
e
:sage: f = M.basis('f', from_family=(-e[0], e[1]+e[2], 2*e[1]+3*e[2])) sage: f Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring sage: M.print_bases() Bases defined on the Rank-3 free module M over the Integer Ring: - (e_0,e_1,e_2) (default basis) - (f_0,f_1,f_2) sage: M.bases() [Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring, Basis (f_0,f_1,f_2) on the Rank-3 free module M over the Integer Ring]
M is a parent object, whose elements are instances of
FiniteRankFreeModuleElement
(actually a dynamically generated subclass of it):sage: v = M.an_element() ; v Element of the Rank-3 free module M over the Integer Ring sage: from sage.tensor.modules.free_module_element import FiniteRankFreeModuleElement sage: isinstance(v, FiniteRankFreeModuleElement) True sage: v in M True sage: M.is_parent_of(v) True sage: v.display() # expansion w.r.t. the default basis (e) e_0 + e_1 + e_2 sage: v.display(f) -f_0 + f_1
The test suite of the category of modules is passed:
sage: TestSuite(M).run()
Constructing an element of
M
from (the integer) 0 yields the zero element ofM
:sage: M(0) Element zero of the Rank-3 free module M over the Integer Ring sage: M(0) is M.zero() True
Non-zero elements are constructed by providing their components in a given basis:
sage: v = M([-1,0,3]) ; v # components in the default basis (e) Element of the Rank-3 free module M over the Integer Ring sage: v.display() # expansion w.r.t. the default basis (e) -e_0 + 3 e_2 sage: v.display(f) f_0 - 6 f_1 + 3 f_2 sage: v = M([-1,0,3], basis=f) ; v # components in a specific basis Element of the Rank-3 free module M over the Integer Ring sage: v.display(f) -f_0 + 3 f_2 sage: v.display() e_0 + 6 e_1 + 9 e_2 sage: v = M([-1,0,3], basis=f, name='v') ; v Element v of the Rank-3 free module M over the Integer Ring sage: v.display(f) v = -f_0 + 3 f_2 sage: v.display() v = e_0 + 6 e_1 + 9 e_2
An alternative is to construct the element from an empty list of componentsand to set the nonzero components afterwards:
sage: v = M([], name='v') sage: v[e,0] = -1 sage: v[e,2] = 3 sage: v.display(e) v = -e_0 + 3 e_2
Indices on the free module, such as indices labelling the element of a basis, are provided by the generator method
irange()
. By default, they range from 0 to the module’s rank minus one:sage: list(M.irange()) [0, 1, 2]
This can be changed via the parameter
start_index
in the module construction:sage: M1 = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1) sage: list(M1.irange()) [1, 2, 3]
The parameter
output_formatter
in the constructor of the free module is used to set the output format of tensor components:sage: N = FiniteRankFreeModule(QQ, 3, output_formatter=Rational.numerical_approx) sage: e = N.basis('e') sage: v = N([1/3, 0, -2], basis=e) sage: v[e,:] [0.333333333333333, 0.000000000000000, -2.00000000000000] sage: v.display(e) # default format (53 bits of precision) 0.333333333333333 e_0 - 2.00000000000000 e_2 sage: v.display(e, format_spec=10) # 10 bits of precision 0.33 e_0 - 2.0 e_2
- Element#
alias of
sage.tensor.modules.free_module_element.FiniteRankFreeModuleElement
- alternating_contravariant_tensor(degree, name=None, latex_name=None)#
Construct an alternating contravariant tensor on the free module.
INPUT:
degree
– degree of the alternating contravariant tensor (i.e. its tensor rank)name
– (default:None
) string; name given to the alternating contravariant tensorlatex_name
– (default:None
) string; LaTeX symbol to denote the alternating contravariant tensor; if none is provided, the LaTeX symbol is set toname
OUTPUT:
instance of
AlternatingContrTensor
EXAMPLES:
Alternating contravariant tensor on a rank-3 module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: a = M.alternating_contravariant_tensor(2, 'a') ; a Alternating contravariant tensor a of degree 2 on the Rank-3 free module M over the Integer Ring
The nonzero components in a given basis have to be set in a second step, thereby fully specifying the alternating form:
sage: e = M.basis('e') ; e Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring sage: a.set_comp(e)[0,1] = 2 sage: a.set_comp(e)[1,2] = -3 sage: a.display(e) a = 2 e_0∧e_1 - 3 e_1∧e_2
An alternating contravariant tensor of degree 1 is simply an element of the module:
sage: a = M.alternating_contravariant_tensor(1, 'a') ; a Element a of the Rank-3 free module M over the Integer Ring
See
AlternatingContrTensor
for more documentation.
- alternating_form(degree, name=None, latex_name=None)#
Construct an alternating form on the free module.
INPUT:
degree
– the degree of the alternating form (i.e. its tensor rank)name
– (default:None
) string; name given to the alternating formlatex_name
– (default:None
) string; LaTeX symbol to denote the alternating form; if none is provided, the LaTeX symbol is set toname
OUTPUT:
instance of
FreeModuleAltForm
EXAMPLES:
Alternating forms on a rank-3 module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: a = M.alternating_form(2, 'a') ; a Alternating form a of degree 2 on the Rank-3 free module M over the Integer Ring
The nonzero components in a given basis have to be set in a second step, thereby fully specifying the alternating form:
sage: e = M.basis('e') ; e Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring sage: a.set_comp(e)[0,1] = 2 sage: a.set_comp(e)[1,2] = -3 sage: a.display(e) a = 2 e^0∧e^1 - 3 e^1∧e^2
An alternating form of degree 1 is a linear form:
sage: a = M.alternating_form(1, 'a') ; a Linear form a on the Rank-3 free module M over the Integer Ring
To construct such a form, it is preferable to call the method
linear_form()
instead:sage: a = M.linear_form('a') ; a Linear form a on the Rank-3 free module M over the Integer Ring
See
FreeModuleAltForm
for more documentation.
- automorphism(matrix=None, basis=None, name=None, latex_name=None)#
Construct a module automorphism of
self
.Denoting
self
by \(M\), an automorphism ofself
is an element of the general linear group \(\mathrm{GL}(M)\).INPUT:
matrix
– (default:None
) matrix of size rank(M)*rank(M) representing the automorphism with respect tobasis
; this entry can actually be any material from which a matrix of elements ofself
base ring can be constructed; the columns ofmatrix
must be the components w.r.t.basis
of the images of the elements ofbasis
. Ifmatrix
isNone
, the automorphism has to be initialized afterwards by methodset_comp()
or via the operator [].basis
– (default:None
) basis ofself
defining the matrix representation; ifNone
the default basis ofself
is assumed.name
– (default:None
) string; name given to the automorphismlatex_name
– (default:None
) string; LaTeX symbol to denote the automorphism; if none is provided, the LaTeX symbol is set toname
OUTPUT:
instance of
FreeModuleAutomorphism
EXAMPLES:
Automorphism of a rank-2 free \(\ZZ\)-module:
sage: M = FiniteRankFreeModule(ZZ, 2, name='M') sage: e = M.basis('e') sage: a = M.automorphism(matrix=[[1,2],[1,3]], basis=e, name='a') ; a Automorphism a of the Rank-2 free module M over the Integer Ring sage: a.parent() General linear group of the Rank-2 free module M over the Integer Ring sage: a.matrix(e) [1 2] [1 3]
An automorphism is a tensor of type (1,1):
sage: a.tensor_type() (1, 1) sage: a.display(e) a = e_0⊗e^0 + 2 e_0⊗e^1 + e_1⊗e^0 + 3 e_1⊗e^1
The automorphism components can be specified in a second step, as components of a type-\((1,1)\) tensor:
sage: a1 = M.automorphism(name='a') sage: a1[e,:] = [[1,2],[1,3]] sage: a1.matrix(e) [1 2] [1 3] sage: a1 == a True
Component by component specification:
sage: a2 = M.automorphism(name='a') sage: a2[0,0] = 1 # component set in the module's default basis (e) sage: a2[0,1] = 2 sage: a2[1,0] = 1 sage: a2[1,1] = 3 sage: a2.matrix(e) [1 2] [1 3] sage: a2 == a True
See
FreeModuleAutomorphism
for more documentation.
- base_module()#
Return the free module on which
self
is constructed, namelyself
itself.EXAMPLES:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: M.base_module() is M True
- bases()#
Return the list of bases that have been defined on the free module
self
.Use the method
print_bases()
to get a formatted output with more information.OUTPUT:
list of instances of class
FreeModuleBasis
EXAMPLES:
Bases on a rank-3 free module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M_3', start_index=1) sage: M.bases() [] sage: e = M.basis('e') sage: M.bases() [Basis (e_1,e_2,e_3) on the Rank-3 free module M_3 over the Integer Ring] sage: f = M.basis('f') sage: M.bases() [Basis (e_1,e_2,e_3) on the Rank-3 free module M_3 over the Integer Ring, Basis (f_1,f_2,f_3) on the Rank-3 free module M_3 over the Integer Ring]
- basis(symbol, latex_symbol=None, from_family=None, indices=None, latex_indices=None, symbol_dual=None, latex_symbol_dual=None)#
Define or return a basis of the free module
self
.Let \(M\) denotes the free module
self
and \(n\) its rank.The basis can be defined from a set of \(n\) linearly independent elements of \(M\) by means of the argument
from_family
. Iffrom_family
is not specified, the basis is created from scratch and, at this stage, is unrelated to bases that could have been defined previously on \(M\). It can be related afterwards by means of the methodset_change_of_basis()
.If the basis specified by the given symbol already exists, it is simply returned, whatever the value of the arguments
latex_symbol
orfrom_family
.Note that another way to construct a basis of
self
is to use the methodnew_basis()
on an existing basis, with the automorphism relating the two bases as an argument.INPUT:
symbol
– either a string, to be used as a common base for the symbols of the elements of the basis, or a list/tuple of strings, representing the individual symbols of the elements of the basislatex_symbol
– (default:None
) either a string, to be used as a common base for the LaTeX symbols of the elements of the basis, or a list/tuple of strings, representing the individual LaTeX symbols of the elements of the basis; ifNone
,symbol
is used in place oflatex_symbol
from_family
– (default:None
) tuple or list of \(n\) linearly independent elements of the free moduleself
(\(n\) being the rank ofself
)indices
– (default:None
; used only ifsymbol
is a single string) list/tuple of strings representing the indices labelling the elements of the basis; ifNone
, the indices will be generated as integers within the range declared onself
latex_indices
– (default:None
) list/tuple of strings representing the indices for the LaTeX symbols of the elements of the basis; ifNone
,indices
is used insteadsymbol_dual
– (default:None
) same assymbol
but for the dual basis; ifNone
,symbol
must be a string and is used for the common base of the symbols of the elements of the dual basislatex_symbol_dual
– (default:None
) same aslatex_symbol
but for the dual basis
OUTPUT:
instance of
FreeModuleBasis
representing a basis onself
EXAMPLES:
Bases on a rank-3 free module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') ; e Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring sage: e[0] Element e_0 of the Rank-3 free module M over the Integer Ring sage: latex(e) \left(e_{0},e_{1},e_{2}\right)
The LaTeX symbol can be set explicitly:
sage: eps = M.basis('eps', latex_symbol=r'\epsilon') ; eps Basis (eps_0,eps_1,eps_2) on the Rank-3 free module M over the Integer Ring sage: latex(eps) \left(\epsilon_{0},\epsilon_{1},\epsilon_{2}\right)
The indices can be customized:
sage: f = M.basis('f', indices=('x', 'y', 'z')); f Basis (f_x,f_y,f_z) on the Rank-3 free module M over the Integer Ring sage: latex(f[1]) f_{y}
By providing a list or a tuple for the argument
symbol
, one can have a different symbol for each element of the basis; it is then mandatory to specify some symbols for the dual basis:sage: g = M.basis(('a', 'b', 'c'), symbol_dual=('A', 'B', 'C')); g Basis (a,b,c) on the Rank-3 free module M over the Integer Ring sage: g.dual_basis() Dual basis (A,B,C) on the Rank-3 free module M over the Integer Ring
If the provided symbol and indices are that of an already defined basis, the latter is returned (no new basis is created):
sage: M.basis('e') is e True sage: M.basis('eps') is eps True sage: M.basis('e', indices=['x', 'y', 'z']) is e False sage: M.basis('e', indices=['x', 'y', 'z']) is \ ....: M.basis('e', indices=['x', 'y', 'z']) True
The individual elements of the basis are labelled according the parameter
start_index
provided at the free module construction:sage: M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1) sage: e = M.basis('e') ; e Basis (e_1,e_2,e_3) on the Rank-3 free module M over the Integer Ring sage: e[1] Element e_1 of the Rank-3 free module M over the Integer Ring
Construction of a basis from a spanning family of linearly independent module elements:
sage: f1 = -e[2] sage: f2 = 4*e[1] + 3*e[3] sage: f3 = 7*e[1] + 5*e[3] sage: f = M.basis('f', from_family=(f1,f2,f3)) sage: f[1].display() f_1 = -e_2 sage: f[2].display() f_2 = 4 e_1 + 3 e_3 sage: f[3].display() f_3 = 7 e_1 + 5 e_3
The change-of-basis automorphisms have been registered:
sage: M.change_of_basis(e,f).matrix(e) [ 0 4 7] [-1 0 0] [ 0 3 5] sage: M.change_of_basis(f,e).matrix(e) [ 0 -1 0] [-5 0 7] [ 3 0 -4] sage: M.change_of_basis(f,e) == M.change_of_basis(e,f).inverse() True
Check of the change-of-basis e –> f:
sage: a = M.change_of_basis(e,f) ; a Automorphism of the Rank-3 free module M over the Integer Ring sage: all( f[i] == a(e[i]) for i in M.irange() ) True
Providing a family of module elements that are not linearly independent raise an error:
sage: g = M.basis('g', from_family=(f1, f2, f1+f2)) Traceback (most recent call last): ... ValueError: the provided module elements are not linearly independent
For more documentation on bases see
FreeModuleBasis
.
- change_of_basis(basis1, basis2)#
Return a module automorphism linking two bases defined on the free module
self
.If the automorphism has not been recorded yet (in the internal dictionary
self._basis_changes
), it is computed by transitivity, i.e. by performing products of recorded changes of basis.INPUT:
basis1
– a basis ofself
, denoted \((e_i)\) belowbasis2
– a basis ofself
, denoted \((f_i)\) below
OUTPUT:
instance of
FreeModuleAutomorphism
describing the automorphism \(P\) that relates the basis \((e_i)\) to the basis \((f_i)\) according to \(f_i = P(e_i)\)
EXAMPLES:
Changes of basis on a rank-2 free module:
sage: FiniteRankFreeModule._clear_cache_() # for doctests only sage: M = FiniteRankFreeModule(ZZ, 2, name='M', start_index=1) sage: e = M.basis('e') sage: f = M.basis('f', from_family=(e[1]+2*e[2], e[1]+3*e[2])) sage: P = M.change_of_basis(e,f) ; P Automorphism of the Rank-2 free module M over the Integer Ring sage: P.matrix(e) [1 1] [2 3]
Note that the columns of this matrix contain the components of the elements of basis
f
w.r.t. to basise
:sage: f[1].display(e) f_1 = e_1 + 2 e_2 sage: f[2].display(e) f_2 = e_1 + 3 e_2
The change of basis is cached:
sage: P is M.change_of_basis(e,f) True
Check of the change-of-basis automorphism:
sage: f[1] == P(e[1]) True sage: f[2] == P(e[2]) True
Check of the reverse change of basis:
sage: M.change_of_basis(f,e) == P^(-1) True
We have of course:
sage: M.change_of_basis(e,e) Identity map of the Rank-2 free module M over the Integer Ring sage: M.change_of_basis(e,e) is M.identity_map() True
Let us introduce a third basis on
M
:sage: h = M.basis('h', from_family=(3*e[1]+4*e[2], 5*e[1]+7*e[2]))
The change of basis
e
–>h
has been recorded directly from the definition ofh
:sage: Q = M.change_of_basis(e,h) ; Q.matrix(e) [3 5] [4 7]
The change of basis
f
–>h
is computed by transitivity, i.e. from the changes of basisf
–>e
ande
–>h
:sage: R = M.change_of_basis(f,h) ; R Automorphism of the Rank-2 free module M over the Integer Ring sage: R.matrix(e) [-1 2] [-2 3] sage: R.matrix(f) [ 5 8] [-2 -3]
Let us check that
R
is indeed the change of basisf
–>h
:sage: h[1] == R(f[1]) True sage: h[2] == R(f[2]) True
A related check is:
sage: R == Q*P^(-1) True
- construction()#
The construction functor and base ring for self.
EXAMPLES:
sage: FiniteRankFreeModule._clear_cache_() # for doctests only sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: M.construction() (VectorFunctor, Integer Ring) sage: N = FiniteRankFreeModule(ZZ, 3, name='N', start_index=17) sage: N.construction() (VectorFunctor, Integer Ring)
- default_basis()#
Return the default basis of the free module
self
.The default basis is simply a basis whose name can be skipped in methods requiring a basis as an argument. By default, it is the first basis introduced on the module. It can be changed by the method
set_default_basis()
.OUTPUT:
instance of
FreeModuleBasis
EXAMPLES:
At the module construction, no default basis is assumed:
sage: M = FiniteRankFreeModule(ZZ, 2, name='M', start_index=1) sage: M.default_basis() No default basis has been defined on the Rank-2 free module M over the Integer Ring
The first defined basis becomes the default one:
sage: e = M.basis('e') ; e Basis (e_1,e_2) on the Rank-2 free module M over the Integer Ring sage: M.default_basis() Basis (e_1,e_2) on the Rank-2 free module M over the Integer Ring sage: f = M.basis('f') ; f Basis (f_1,f_2) on the Rank-2 free module M over the Integer Ring sage: M.default_basis() Basis (e_1,e_2) on the Rank-2 free module M over the Integer Ring
- dual()#
Return the dual module of
self
.EXAMPLES:
Dual of a free module over \(\ZZ\):
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: M.dual() Dual of the Rank-3 free module M over the Integer Ring sage: latex(M.dual()) M^*
The dual is a free module of the same rank as M:
sage: from sage.tensor.modules.finite_rank_free_module import FiniteRankFreeModule_abstract sage: isinstance(M.dual(), FiniteRankFreeModule_abstract) True sage: M.dual().rank() 3
It is formed by alternating forms of degree 1, i.e. linear forms:
sage: M.dual() is M.dual_exterior_power(1) True sage: M.dual().an_element() Linear form on the Rank-3 free module M over the Integer Ring sage: a = M.linear_form() sage: a in M.dual() True
The elements of a dual basis belong of course to the dual module:
sage: e = M.basis('e') sage: e.dual_basis()[0] in M.dual() True
- dual_exterior_power(p)#
Return the \(p\)-th exterior power of the dual of
self
.If \(M\) stands for the free module
self
, the p-th exterior power of the dual of \(M\) is the set \(\Lambda^p(M^*)\) of all alternating forms of degree \(p\) on \(M\), i.e. of all multilinear maps\[\underbrace{M\times\cdots\times M}_{p\ \; \mbox{times}} \longrightarrow R\]that vanish whenever any of two of their arguments are equal. \(\Lambda^p(M^*)\) is a free module of rank \(\binom{n}{p}\) over the same ring as \(M\), where \(n\) is the rank of \(M\).
INPUT:
p
– non-negative integer
OUTPUT:
for \(p=0\), the base ring \(R\)
for \(p=1\), instance of
FiniteRankDualFreeModule
representing the dual \(M^*\)for \(p\geq 1\), instance of
ExtPowerDualFreeModule
representing the free module \(\Lambda^p(M^*)\)
EXAMPLES:
Exterior powers of the dual of a free \(\ZZ\)-module of rank 3:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: M.dual_exterior_power(0) # return the base ring Integer Ring sage: M.dual_exterior_power(1) # return the dual module Dual of the Rank-3 free module M over the Integer Ring sage: M.dual_exterior_power(1) is M.dual() True sage: M.dual_exterior_power(2) 2nd exterior power of the dual of the Rank-3 free module M over the Integer Ring sage: M.dual_exterior_power(2).an_element() Alternating form of degree 2 on the Rank-3 free module M over the Integer Ring sage: M.dual_exterior_power(2).an_element().display() e^0∧e^1 sage: M.dual_exterior_power(3) 3rd exterior power of the dual of the Rank-3 free module M over the Integer Ring sage: M.dual_exterior_power(3).an_element() Alternating form of degree 3 on the Rank-3 free module M over the Integer Ring sage: M.dual_exterior_power(3).an_element().display() e^0∧e^1∧e^2
See
ExtPowerDualFreeModule
for more documentation.
- dual_symmetric_power(p)#
Return the \(p\)-th symmetric power of the dual of
self
.EXAMPLES:
Symmetric powers of the dual of a free \(\ZZ\)-module of rank 3:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: M.dual_symmetric_power(0) Free module of type-(0,0) tensors on the Rank-3 free module M over the Integer Ring sage: M.dual_symmetric_power(1) # return the dual module Dual of the Rank-3 free module M over the Integer Ring sage: M.dual_symmetric_power(2) Free module of fully symmetric type-(0,2) tensors on the Rank-3 free module M over the Integer Ring sage: M.dual_symmetric_power(2).an_element() Symmetric bilinear form on the Rank-3 free module M over the Integer Ring sage: M.dual_symmetric_power(2).an_element().display() e^0⊗e^0 sage: M.dual_symmetric_power(3) Free module of fully symmetric type-(0,3) tensors on the Rank-3 free module M over the Integer Ring sage: M.dual_symmetric_power(3).an_element() Type-(0,3) tensor on the Rank-3 free module M over the Integer Ring sage: M.dual_symmetric_power(3).an_element().display() e^0⊗e^0⊗e^0
- endomorphism(matrix_rep, basis=None, name=None, latex_name=None)#
Construct an endomorphism of the free module
self
.The returned object is a module morphism \(\phi: M \rightarrow M\), where \(M\) is
self
.INPUT:
matrix_rep
– matrix of size rank(M)*rank(M) representing the endomorphism with respect tobasis
; this entry can actually be any material from which a matrix of elements ofself
base ring can be constructed; the columns ofmatrix_rep
must be the components w.r.t.basis
of the images of the elements ofbasis
.basis
– (default:None
) basis ofself
defining the matrix representation; if None the default basis ofself
is assumed.name
– (default:None
) string; name given to the endomorphismlatex_name
– (default:None
) string; LaTeX symbol to denote the endomorphism; if none is provided,name
will be used.
OUTPUT:
the endomorphism \(\phi: M \rightarrow M\) corresponding to the given specifications, as an instance of
FiniteRankFreeModuleMorphism
EXAMPLES:
Construction of an endomorphism with minimal data (module’s default basis and no name):
sage: M = FiniteRankFreeModule(ZZ, 2, name='M') sage: e = M.basis('e') sage: phi = M.endomorphism([[1,-2], [-3,4]]) ; phi Generic endomorphism of Rank-2 free module M over the Integer Ring sage: phi.matrix() # matrix w.r.t the default basis [ 1 -2] [-3 4]
Construction with full list of arguments (matrix given a basis different from the default one):
sage: a = M.automorphism() ; a[0,1], a[1,0] = 1, -1 sage: ep = e.new_basis(a, 'ep', latex_symbol="e'") sage: phi = M.endomorphism([[1,-2], [-3,4]], basis=ep, name='phi', ....: latex_name=r'\phi') sage: phi Generic endomorphism of Rank-2 free module M over the Integer Ring sage: phi.matrix(ep) # the input matrix [ 1 -2] [-3 4] sage: phi.matrix() # matrix w.r.t the default basis [4 3] [2 1]
See
FiniteRankFreeModuleMorphism
for more documentation.
- exterior_power(p)#
Return the \(p\)-th exterior power of
self
.If \(M\) stands for the free module
self
, the p-th exterior power of \(M\) is the set \(\Lambda^p(M)\) of all alternating contravariant tensors of rank \(p\), i.e. of all multilinear maps\[\underbrace{M^*\times\cdots\times M^*}_{p\ \; \mbox{times}} \longrightarrow R\]that vanish whenever any of two of their arguments are equal. \(\Lambda^p(M)\) is a free module of rank \(\binom{n}{p}\) over the same ring as \(M\), where \(n\) is the rank of \(M\).
INPUT:
p
– non-negative integer
OUTPUT:
for \(p=0\), the base ring \(R\)
for \(p=1\), the free module \(M\), since \(\Lambda^1(M)=M\)
for \(p\geq 2\), instance of
ExtPowerFreeModule
representing the free module \(\Lambda^p(M)\)
EXAMPLES:
Exterior powers of a free \(\ZZ\)-module of rank 3:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: M.exterior_power(0) # return the base ring Integer Ring sage: M.exterior_power(1) # return the module itself Rank-3 free module M over the Integer Ring sage: M.exterior_power(1) is M True sage: M.exterior_power(2) 2nd exterior power of the Rank-3 free module M over the Integer Ring sage: M.exterior_power(2).an_element() Alternating contravariant tensor of degree 2 on the Rank-3 free module M over the Integer Ring sage: M.exterior_power(2).an_element().display() e_0∧e_1 sage: M.exterior_power(3) 3rd exterior power of the Rank-3 free module M over the Integer Ring sage: M.exterior_power(3).an_element() Alternating contravariant tensor of degree 3 on the Rank-3 free module M over the Integer Ring sage: M.exterior_power(3).an_element().display() e_0∧e_1∧e_2
See
ExtPowerFreeModule
for more documentation.
- general_linear_group()#
Return the general linear group of
self
.If
self
is the free module \(M\), the general linear group is the group \(\mathrm{GL}(M)\) of automorphisms of \(M\).OUTPUT:
instance of class
FreeModuleLinearGroup
representing \(\mathrm{GL}(M)\)
EXAMPLES:
The general linear group of a rank-3 free module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: GL = M.general_linear_group() ; GL General linear group of the Rank-3 free module M over the Integer Ring sage: GL.category() Category of groups sage: type(GL) <class 'sage.tensor.modules.free_module_linear_group.FreeModuleLinearGroup_with_category'>
There is a unique instance of the general linear group:
sage: M.general_linear_group() is GL True
The group identity element:
sage: GL.one() Identity map of the Rank-3 free module M over the Integer Ring sage: GL.one().matrix(e) [1 0 0] [0 1 0] [0 0 1]
An element:
sage: GL.an_element() Automorphism of the Rank-3 free module M over the Integer Ring sage: GL.an_element().matrix(e) [ 1 0 0] [ 0 -1 0] [ 0 0 1]
See
FreeModuleLinearGroup
for more documentation.
- hom(codomain, matrix_rep, bases=None, name=None, latex_name=None)#
Homomorphism from
self
to a free module.Define a module homomorphism
\[\phi:\ M \longrightarrow N,\]where \(M\) is
self
and \(N\) is a free module of finite rank over the same ring \(R\) asself
.Note
This method is a redefinition of
sage.structure.parent.Parent.hom()
because the latter assumes thatself
has some privileged generators, while an instance ofFiniteRankFreeModule
has no privileged basis.INPUT:
codomain
– the target module \(N\)matrix_rep
– matrix of size rank(N)*rank(M) representing the homomorphism with respect to the pair of bases defined bybases
; this entry can actually be any material from which a matrix of elements of \(R\) can be constructed; the columns ofmatrix_rep
must be the components w.r.t.basis_N
of the images of the elements ofbasis_M
.bases
– (default:None
) pair(basis_M, basis_N)
defining the matrix representation,basis_M
being a basis ofself
andbasis_N
a basis of module \(N\) ; if None the pair formed by the default bases of each module is assumed.name
– (default:None
) string; name given to the homomorphismlatex_name
– (default:None
) string; LaTeX symbol to denote the homomorphism; if None,name
will be used.
OUTPUT:
the homomorphism \(\phi: M \rightarrow N\) corresponding to the given specifications, as an instance of
FiniteRankFreeModuleMorphism
EXAMPLES:
Homomorphism between two free modules over \(\ZZ\):
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: N = FiniteRankFreeModule(ZZ, 2, name='N') sage: e = M.basis('e') sage: f = N.basis('f') sage: phi = M.hom(N, [[-1,2,0], [5,1,2]]) ; phi Generic morphism: From: Rank-3 free module M over the Integer Ring To: Rank-2 free module N over the Integer Ring
Homomorphism defined by a matrix w.r.t. bases that are not the default ones:
sage: ep = M.basis('ep', latex_symbol=r"e'") sage: fp = N.basis('fp', latex_symbol=r"f'") sage: phi = M.hom(N, [[3,2,1], [1,2,3]], bases=(ep, fp)) ; phi Generic morphism: From: Rank-3 free module M over the Integer Ring To: Rank-2 free module N over the Integer Ring
Call with all arguments specified:
sage: phi = M.hom(N, [[3,2,1], [1,2,3]], bases=(ep, fp), ....: name='phi', latex_name=r'\phi')
The parent:
sage: phi.parent() is Hom(M,N) True
See class
FiniteRankFreeModuleMorphism
for more documentation.
- identity_map(name='Id', latex_name=None)#
Return the identity map of the free module
self
.INPUT:
name
– (string; default: ‘Id’) name given to the identity identity maplatex_name
– (string; default:None
) LaTeX symbol to denote the identity map; if none is provided, the LaTeX symbol is set to ‘mathrm{Id}’ ifname
is ‘Id’ and toname
otherwise
OUTPUT:
the identity map of
self
as an instance ofFreeModuleAutomorphism
EXAMPLES:
Identity map of a rank-3 \(\ZZ\)-module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: Id = M.identity_map() ; Id Identity map of the Rank-3 free module M over the Integer Ring sage: Id.parent() General linear group of the Rank-3 free module M over the Integer Ring sage: Id.matrix(e) [1 0 0] [0 1 0] [0 0 1]
The default LaTeX symbol:
sage: latex(Id) \mathrm{Id}
It can be changed by means of the method
set_name()
:sage: Id.set_name(latex_name=r'\mathrm{1}_M') sage: latex(Id) \mathrm{1}_M
The identity map is actually the identity element of GL(M):
sage: Id is M.general_linear_group().one() True
It is also a tensor of type-\((1,1)\) on M:
sage: Id.tensor_type() (1, 1) sage: Id.comp(e) Kronecker delta of size 3x3 sage: Id[:] [1 0 0] [0 1 0] [0 0 1]
Example with a LaTeX symbol different from the default one and set at the creation of the object:
sage: N = FiniteRankFreeModule(ZZ, 3, name='N') sage: f = N.basis('f') sage: Id = N.identity_map(name='Id_N', latex_name=r'\mathrm{Id}_N') sage: Id Identity map of the Rank-3 free module N over the Integer Ring sage: latex(Id) \mathrm{Id}_N
- irange(start=None)#
Single index generator, labelling the elements of a basis of
self
.INPUT:
start
– (default:None
) integer; initial value of the index; if none is provided,self._sindex
is assumed
OUTPUT:
an iterable index, starting from
start
and ending atself._sindex + self.rank() - 1
EXAMPLES:
Index range on a rank-3 module:
sage: M = FiniteRankFreeModule(ZZ, 3) sage: list(M.irange()) [0, 1, 2] sage: list(M.irange(start=1)) [1, 2]
The default starting value corresponds to the parameter
start_index
provided at the module construction (the default value being 0):sage: M1 = FiniteRankFreeModule(ZZ, 3, start_index=1) sage: list(M1.irange()) [1, 2, 3] sage: M2 = FiniteRankFreeModule(ZZ, 3, start_index=-4) sage: list(M2.irange()) [-4, -3, -2]
- linear_form(name=None, latex_name=None)#
Construct a linear form on the free module
self
.A linear form on a free module \(M\) over a ring \(R\) is a map \(M \rightarrow R\) that is linear. It can be viewed as a tensor of type \((0,1)\) on \(M\).
INPUT:
name
– (default:None
) string; name given to the linear formlatex_name
– (default:None
) string; LaTeX symbol to denote the linear form; if none is provided, the LaTeX symbol is set toname
OUTPUT:
instance of
FreeModuleAltForm
EXAMPLES:
Linear form on a rank-3 free module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: a = M.linear_form('A') ; a Linear form A on the Rank-3 free module M over the Integer Ring sage: a[:] = [2,-1,3] # components w.r.t. the module's default basis (e) sage: a.display() A = 2 e^0 - e^1 + 3 e^2
A linear form maps module elements to ring elements:
sage: v = M([1,1,1]) sage: a(v) 4
Test of linearity:
sage: u = M([-5,-2,7]) sage: a(3*u - 4*v) == 3*a(u) - 4*a(v) True
See
FreeModuleAltForm
for more documentation.
- print_bases()#
Display the bases that have been defined on the free module
self
.Use the method
bases()
to get the raw list of bases.EXAMPLES:
Bases on a rank-4 free module:
sage: M = FiniteRankFreeModule(ZZ, 4, name='M', start_index=1) sage: M.print_bases() No basis has been defined on the Rank-4 free module M over the Integer Ring sage: e = M.basis('e') sage: M.print_bases() Bases defined on the Rank-4 free module M over the Integer Ring: - (e_1,e_2,e_3,e_4) (default basis) sage: f = M.basis('f') sage: M.print_bases() Bases defined on the Rank-4 free module M over the Integer Ring: - (e_1,e_2,e_3,e_4) (default basis) - (f_1,f_2,f_3,f_4) sage: M.set_default_basis(f) sage: M.print_bases() Bases defined on the Rank-4 free module M over the Integer Ring: - (e_1,e_2,e_3,e_4) - (f_1,f_2,f_3,f_4) (default basis)
- set_change_of_basis(basis1, basis2, change_of_basis, compute_inverse=True)#
Relates two bases by an automorphism of
self
.This updates the internal dictionary
self._basis_changes
.INPUT:
basis1
– basis 1, denoted \((e_i)\) belowbasis2
– basis 2, denoted \((f_i)\) belowchange_of_basis
– instance of classFreeModuleAutomorphism
describing the automorphism \(P\) that relates the basis \((e_i)\) to the basis \((f_i)\) according to \(f_i = P(e_i)\)compute_inverse
(default:True
) – if set toTrue
, the inverse automorphism is computed and the change from basis \((f_i)\) to \((e_i)\) is set to it in the internal dictionaryself._basis_changes
EXAMPLES:
Defining a change of basis on a rank-2 free module:
sage: M = FiniteRankFreeModule(QQ, 2, name='M') sage: e = M.basis('e') sage: f = M.basis('f') sage: a = M.automorphism() sage: a[:] = [[1, 2], [-1, 3]] sage: M.set_change_of_basis(e, f, a)
The change of basis and its inverse have been recorded:
sage: M.change_of_basis(e,f).matrix(e) [ 1 2] [-1 3] sage: M.change_of_basis(f,e).matrix(e) [ 3/5 -2/5] [ 1/5 1/5]
and are effective:
sage: f[0].display(e) f_0 = e_0 - e_1 sage: e[0].display(f) e_0 = 3/5 f_0 + 1/5 f_1
- set_default_basis(basis)#
Sets the default basis of
self
.The default basis is simply a basis whose name can be skipped in methods requiring a basis as an argument. By default, it is the first basis introduced on the module.
INPUT:
basis
– instance ofFreeModuleBasis
representing a basis onself
EXAMPLES:
Changing the default basis on a rank-3 free module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M', start_index=1) sage: e = M.basis('e') ; e Basis (e_1,e_2,e_3) on the Rank-3 free module M over the Integer Ring sage: f = M.basis('f') ; f Basis (f_1,f_2,f_3) on the Rank-3 free module M over the Integer Ring sage: M.default_basis() Basis (e_1,e_2,e_3) on the Rank-3 free module M over the Integer Ring sage: M.set_default_basis(f) sage: M.default_basis() Basis (f_1,f_2,f_3) on the Rank-3 free module M over the Integer Ring
- sym_bilinear_form(name=None, latex_name=None)#
Construct a symmetric bilinear form on the free module
self
.INPUT:
name
– (default:None
) string; name given to the symmetric bilinear formlatex_name
– (default:None
) string; LaTeX symbol to denote the symmetric bilinear form; if none is provided, the LaTeX symbol is set toname
OUTPUT:
instance of
FreeModuleTensor
of tensor type \((0,2)\) and symmetric
EXAMPLES:
Symmetric bilinear form on a rank-3 free module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: a = M.sym_bilinear_form('A') ; a Symmetric bilinear form A on the Rank-3 free module M over the Integer Ring
A symmetric bilinear form is a type-\((0,2)\) tensor that is symmetric:
sage: a.parent() Free module of type-(0,2) tensors on the Rank-3 free module M over the Integer Ring sage: a.tensor_type() (0, 2) sage: a.tensor_rank() 2 sage: a.symmetries() symmetry: (0, 1); no antisymmetry
Components with respect to a given basis:
sage: e = M.basis('e') sage: a[0,0], a[0,1], a[0,2] = 1, 2, 3 sage: a[1,1], a[1,2] = 4, 5 sage: a[2,2] = 6
Only independent components have been set; the other ones are deduced by symmetry:
sage: a[1,0], a[2,0], a[2,1] (2, 3, 5) sage: a[:] [1 2 3] [2 4 5] [3 5 6]
A symmetric bilinear form acts on pairs of module elements:
sage: u = M([2,-1,3]) ; v = M([-2,4,1]) sage: a(u,v) 61 sage: a(v,u) == a(u,v) True
The sum of two symmetric bilinear forms is another symmetric bilinear form:
sage: b = M.sym_bilinear_form('B') sage: b[0,0], b[0,1], b[1,2] = -2, 1, -3 sage: s = a + b ; s Symmetric bilinear form A+B on the Rank-3 free module M over the Integer Ring sage: a[:], b[:], s[:] ( [1 2 3] [-2 1 0] [-1 3 3] [2 4 5] [ 1 0 -3] [ 3 4 2] [3 5 6], [ 0 -3 0], [ 3 2 6] )
Adding a symmetric bilinear from with a non-symmetric one results in a generic type-\((0,2)\) tensor:
sage: c = M.tensor((0,2), name='C') sage: c[0,1] = 4 sage: s = a + c ; s Type-(0,2) tensor A+C on the Rank-3 free module M over the Integer Ring sage: s.symmetries() no symmetry; no antisymmetry sage: s[:] [1 6 3] [2 4 5] [3 5 6]
See
FreeModuleTensor
for more documentation.
- symmetric_power(p)#
Return the \(p\)-th symmetric power of
self
.EXAMPLES:
Symmetric powers of a free \(\ZZ\)-module of rank 3:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') sage: M.symmetric_power(0) Free module of type-(0,0) tensors on the Rank-3 free module M over the Integer Ring sage: M.symmetric_power(1) # return the module itself Rank-3 free module M over the Integer Ring sage: M.symmetric_power(1) is M True sage: M.symmetric_power(2) Free module of fully symmetric type-(2,0) tensors on the Rank-3 free module M over the Integer Ring sage: M.symmetric_power(2).an_element() Type-(2,0) tensor on the Rank-3 free module M over the Integer Ring sage: M.symmetric_power(2).an_element().display() e_0⊗e_0 sage: M.symmetric_power(3) Free module of fully symmetric type-(3,0) tensors on the Rank-3 free module M over the Integer Ring sage: M.symmetric_power(3).an_element() Type-(3,0) tensor on the Rank-3 free module M over the Integer Ring sage: M.symmetric_power(3).an_element().display() e_0⊗e_0⊗e_0
- tensor(*args, **kwds)#
Construct a tensor on the free module
self
or a tensor product with other modules.If
args
consist of other parents, just delegate totensor_product()
.Otherwise, construct a tensor from the following input.
INPUT:
tensor_type
– pair(k, l)
withk
being the contravariant rank andl
the covariant rankname
– (default:None
) string; name given to the tensorlatex_name
– (default:None
) string; LaTeX symbol to denote the tensor; if none is provided, the LaTeX symbol is set toname
sym
– (default:None
) a symmetry or an iterable of symmetries among the tensor arguments: each symmetry is described by a tuple containing the positions of the involved arguments, with the conventionposition = 0
for the first argument. For instance:sym = (0,1)
for a symmetry between the 1st and 2nd argumentssym = [(0,2), (1,3,4)]
for a symmetry between the 1st and 3rd arguments and a symmetry between the 2nd, 4th and 5th arguments.
antisym
– (default:None
) antisymmetry or iterable of antisymmetries among the arguments, with the same convention as forsym
OUTPUT:
instance of
FreeModuleTensor
representing the tensor defined onself
with the provided characteristics
EXAMPLES:
Tensors on a rank-3 free module:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: t = M.tensor((1,0), name='t') ; t Element t of the Rank-3 free module M over the Integer Ring sage: t = M.tensor((0,1), name='t') ; t Linear form t on the Rank-3 free module M over the Integer Ring sage: t = M.tensor((1,1), name='t') ; t Type-(1,1) tensor t on the Rank-3 free module M over the Integer Ring sage: t = M.tensor((0,2), name='t', sym=(0,1)) ; t Symmetric bilinear form t on the Rank-3 free module M over the Integer Ring sage: t = M.tensor((0,2), name='t', antisym=(0,1)) ; t Alternating form t of degree 2 on the Rank-3 free module M over the Integer Ring sage: t = M.tensor((1,2), name='t') ; t Type-(1,2) tensor t on the Rank-3 free module M over the Integer Ring
See
FreeModuleTensor
for more examples and documentation.
- tensor_from_comp(tensor_type, comp, name=None, latex_name=None)#
Construct a tensor on
self
from a set of components.The tensor symmetries are deduced from those of the components.
INPUT:
tensor_type
– pair(k, l)
withk
being the contravariant rank andl
the covariant rankcomp
– instance ofComponents
representing the tensor components in a given basisname
– (default:None
) string; name given to the tensorlatex_name
– (default:None
) string; LaTeX symbol to denote the tensor; if none is provided, the LaTeX symbol is set toname
OUTPUT:
instance of
FreeModuleTensor
representing the tensor defined onself
with the provided characteristics.
EXAMPLES:
Construction of a tensor of rank 1:
sage: from sage.tensor.modules.comp import Components, CompWithSym, CompFullySym, CompFullyAntiSym sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: e = M.basis('e') ; e Basis (e_0,e_1,e_2) on the Rank-3 free module M over the Integer Ring sage: c = Components(ZZ, e, 1) sage: c[:] [0, 0, 0] sage: c[:] = [-1,4,2] sage: t = M.tensor_from_comp((1,0), c) sage: t Element of the Rank-3 free module M over the Integer Ring sage: t.display(e) -e_0 + 4 e_1 + 2 e_2 sage: t = M.tensor_from_comp((0,1), c) ; t Linear form on the Rank-3 free module M over the Integer Ring sage: t.display(e) -e^0 + 4 e^1 + 2 e^2
Construction of a tensor of rank 2:
sage: c = CompFullySym(ZZ, e, 2) sage: c[0,0], c[1,2] = 4, 5 sage: t = M.tensor_from_comp((0,2), c) ; t Symmetric bilinear form on the Rank-3 free module M over the Integer Ring sage: t.symmetries() symmetry: (0, 1); no antisymmetry sage: t.display(e) 4 e^0⊗e^0 + 5 e^1⊗e^2 + 5 e^2⊗e^1 sage: c = CompFullyAntiSym(ZZ, e, 2) sage: c[0,1], c[1,2] = 4, 5 sage: t = M.tensor_from_comp((0,2), c) ; t Alternating form of degree 2 on the Rank-3 free module M over the Integer Ring sage: t.display(e) 4 e^0∧e^1 + 5 e^1∧e^2
- tensor_module(k, l, sym, antisym)#
Return the free module of all tensors of type \((k, l)\) defined on
self
.INPUT:
k
– non-negative integer; the contravariant rank, the tensor type being \((k, l)\)l
– non-negative integer; the covariant rank, the tensor type being \((k, l)\)sym
– (default:None
) a symmetry or a list of symmetries among the tensor arguments: each symmetry is described by a tuple containing the positions of the involved arguments, with the conventionposition = 0
for the first argument. For instance:sym = (0,1)
for a symmetry between the 1st and 2nd argumentssym = [(0,2), (1,3,4)]
for a symmetry between the 1st and 3rd arguments and a symmetry between the 2nd, 4th and 5th arguments.
antisym
– (default:None
) antisymmetry or list of antisymmetries among the arguments, with the same convention as forsym
OUTPUT:
instance of
TensorFreeModule
representing the free module \(T^{(k,l)}(M)\) of type-\((k,l)\) tensors on the free moduleself
EXAMPLES:
Tensor modules over a free module over \(\ZZ\):
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: T = M.tensor_module(1,2) ; T Free module of type-(1,2) tensors on the Rank-3 free module M over the Integer Ring sage: T.an_element() Type-(1,2) tensor on the Rank-3 free module M over the Integer Ring
Tensor modules are unique:
sage: M.tensor_module(1,2) is T True
The module of type-\((1,0)\) tensors is the base module itself:
sage: M.tensor_module(1,0) is M True
while the module of type-\((0,1)\) tensors is the dual of the base module:
sage: M.tensor_module(0, 1) is M.dual() True
By using the arguments
sym
andantisym
, submodules of a full tensor module can be constructed:sage: T = M.tensor_module(4, 4, sym=((0, 1)), antisym=((4, 5))); T Free module of type-(4,4) tensors on the Rank-3 free module M over the Integer Ring, with symmetry on the index positions (0, 1), with antisymmetry on the index positions (4, 5) sage: T._name 'T^{2,3}(M)⊗T^{6,7}(M*)⊗Sym^{0,1}(M)⊗ASym^{4,5}(M*)' sage: latex(T) T^{\{2,3\}}(M) \otimes T^{\{6,7\}}(M^*) \otimes \mathrm{Sym}^{\{0,1\}}(M) \otimes \mathrm{ASym}^{\{4,5\}}(M^*)
See
TensorFreeModule
andTensorFreeSubmodule_sym
for more documentation.
- tensor_type()#
Return the tensor type of
self
, the pair \((1, 0)\).EXAMPLES:
sage: M = FiniteRankFreeModule(ZZ, 3) sage: M.tensor_type() (1, 0)
- class sage.tensor.modules.finite_rank_free_module.FiniteRankFreeModule_abstract(ring, rank, name=None, latex_name=None, category=None, ambient=None)#
Bases:
sage.structure.unique_representation.UniqueRepresentation
,sage.structure.parent.Parent
Abstract base class for free modules of finite rank over a commutative ring.
- ambient()#
Return the ambient module associated to this module.
EXAMPLES:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: M.ambient_module() is M True sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: Sym0123x45M = M.tensor_module(6, 0, sym=((0, 1, 2, 3), (4, 5))) sage: T60M = M.tensor_module(6, 0) sage: Sym0123x45M.ambient_module() is T60M True
- ambient_module()#
Return the ambient module associated to this module.
EXAMPLES:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: M.ambient_module() is M True sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: Sym0123x45M = M.tensor_module(6, 0, sym=((0, 1, 2, 3), (4, 5))) sage: T60M = M.tensor_module(6, 0) sage: Sym0123x45M.ambient_module() is T60M True
- is_submodule(other)#
Return
True
ifself
is a submodule ofother
.EXAMPLES:
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: N = FiniteRankFreeModule(ZZ, 4, name='N') sage: M.is_submodule(M) True sage: M.is_submodule(N) False
- isomorphism_with_fixed_basis(basis=None, codomain=None)#
Construct the canonical isomorphism from the free module
self
to a free module in whichbasis
ofself
is mapped to the distinguished basis ofcodomain
.INPUT:
basis
– (default:None
) the basis ofself
which should be mapped to the distinguished basis oncodomain
; ifNone
, the default basis is assumed.codomain
– (default:None
) the codomain of the isomorphism represented by a free module within the categoryModulesWithBasis
with the same rank and base ring asself
; ifNone
a free module represented byCombinatorialFreeModule
is constructed
OUTPUT:
a module morphism represented by
ModuleMorphismFromFunction
EXAMPLES:
sage: V = FiniteRankFreeModule(QQ, 3, start_index=1); V 3-dimensional vector space over the Rational Field sage: basis = e = V.basis("e"); basis Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the Rational Field sage: phi_e = V.isomorphism_with_fixed_basis(basis); phi_e Generic morphism: From: 3-dimensional vector space over the Rational Field To: Free module generated by {1, 2, 3} over Rational Field sage: phi_e.codomain().category() Category of finite dimensional vector spaces with basis over Rational Field sage: phi_e(e[1] + 2 * e[2]) e[1] + 2*e[2] sage: abc = V.basis(['a', 'b', 'c'], symbol_dual=['d', 'e', 'f']); abc Basis (a,b,c) on the 3-dimensional vector space over the Rational Field sage: phi_abc = V.isomorphism_with_fixed_basis(abc); phi_abc Generic morphism: From: 3-dimensional vector space over the Rational Field To: Free module generated by {1, 2, 3} over Rational Field sage: phi_abc(abc[1] + 2 * abc[2]) B[1] + 2*B[2]
Providing a codomain:
sage: W = CombinatorialFreeModule(QQ, ['a', 'b', 'c']) sage: phi_eW = V.isomorphism_with_fixed_basis(basis, codomain=W); phi_eW Generic morphism: From: 3-dimensional vector space over the Rational Field To: Free module generated by {'a', 'b', 'c'} over Rational Field sage: phi_eW(e[1] + 2 * e[2]) B['a'] + 2*B['b']
Providing a
Module_free_ambient
as the codomain:sage: W = QQ^3 sage: phi_eW = V.isomorphism_with_fixed_basis(basis, codomain=W); phi_eW Generic morphism: From: 3-dimensional vector space over the Rational Field To: Vector space of dimension 3 over Rational Field sage: phi_eW(e[1] + 2 * e[2]) (1, 2, 0)
Sending (1,1)-tensors to matrices:
sage: T11 = V.tensor_module(1, 1); T11 Free module of type-(1,1) tensors on the 3-dimensional vector space over the Rational Field sage: e_T11 = T11.basis("e"); e_T11 Standard basis on the Free module of type-(1,1) tensors on the 3-dimensional vector space over the Rational Field induced by Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the Rational Field sage: W = MatrixSpace(QQ, 3) sage: phi_e_T11 = T11.isomorphism_with_fixed_basis(e_T11, codomain=W); phi_e_T11 Generic morphism: From: Free module of type-(1,1) tensors on the 3-dimensional vector space over the Rational Field To: Full MatrixSpace of 3 by 3 dense matrices over Rational Field sage: t = T11.an_element(); t.display() 1/2 e_1⊗e^1 sage: phi_e_T11(t) [1/2 0 0] [ 0 0 0] [ 0 0 0]
Sending symmetric bilinear forms to matrices (note that they are currently elements of \(T^{(0,2)}(M)\), not the symmetric power of \(M\)):
sage: T02 = V.tensor_module(0, 2); T02 Free module of type-(0,2) tensors on the 3-dimensional vector space over the Rational Field sage: e_T02 = T02.basis("e"); e_T02 Standard basis on the Free module of type-(0,2) tensors on the 3-dimensional vector space over the Rational Field induced by Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the Rational Field sage: W = MatrixSpace(QQ, 3) sage: phi_e_T02 = T02.isomorphism_with_fixed_basis(e_T02, codomain=W); phi_e_T02 Generic morphism: From: Free module of type-(0,2) tensors on the 3-dimensional vector space over the Rational Field To: Full MatrixSpace of 3 by 3 dense matrices over Rational Field sage: a = V.sym_bilinear_form() sage: a[1,1], a[1,2], a[1,3] = 1, 2, 3 sage: a[2,2], a[2,3] = 4, 5 sage: a[3,3] = 6 sage: a.display() e^1⊗e^1 + 2 e^1⊗e^2 + 3 e^1⊗e^3 + 2 e^2⊗e^1 + 4 e^2⊗e^2 + 5 e^2⊗e^3 + 3 e^3⊗e^1 + 5 e^3⊗e^2 + 6 e^3⊗e^3 sage: phi_e_T02(a) [1 2 3] [2 4 5] [3 5 6]
Same but explicitly in the subspace of symmetric bilinear forms:
sage: Sym2Vdual = V.dual_symmetric_power(2); Sym2Vdual Free module of fully symmetric type-(0,2) tensors on the 3-dimensional vector space over the Rational Field sage: Sym2Vdual.is_submodule(T02) True sage: Sym2Vdual.rank() 6 sage: e_Sym2Vdual = Sym2Vdual.basis("e"); e_Sym2Vdual Standard basis on the Free module of fully symmetric type-(0,2) tensors on the 3-dimensional vector space over the Rational Field induced by Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the Rational Field sage: W_basis = [phi_e_T02(b) for b in e_Sym2Vdual]; W_basis [ [1 0 0] [0 1 0] [0 0 1] [0 0 0] [0 0 0] [0 0 0] [0 0 0] [1 0 0] [0 0 0] [0 1 0] [0 0 1] [0 0 0] [0 0 0], [0 0 0], [1 0 0], [0 0 0], [0 1 0], [0 0 1] ] sage: W = MatrixSpace(QQ, 3).submodule(W_basis); W Free module generated by {0, 1, 2, 3, 4, 5} over Rational Field sage: phi_e_Sym2Vdual = Sym2Vdual.isomorphism_with_fixed_basis(e_Sym2Vdual, codomain=W); phi_e_Sym2Vdual Generic morphism: From: Free module of fully symmetric type-(0,2) tensors on the 3-dimensional vector space over the Rational Field To: Free module generated by {0, 1, 2, 3, 4, 5} over Rational Field
Sending tensors to elements of the tensor square of
CombinatorialFreeModule
:sage: T20 = V.tensor_module(2, 0); T20 Free module of type-(2,0) tensors on the 3-dimensional vector space over the Rational Field sage: e_T20 = T02.basis("e"); e_T20 Standard basis on the Free module of type-(0,2) tensors on the 3-dimensional vector space over the Rational Field induced by Basis (e_1,e_2,e_3) on the 3-dimensional vector space over the Rational Field sage: W = CombinatorialFreeModule(QQ, [1, 2, 3]).tensor_square(); W Free module generated by {1, 2, 3} over Rational Field # Free module generated by {1, 2, 3} over Rational Field sage: phi_e_T20 = T20.isomorphism_with_fixed_basis(e_T20, codomain=W); phi_e_T20 Generic morphism: From: Free module of type-(2,0) tensors on the 3-dimensional vector space over the Rational Field To: Free module generated by {1, 2, 3} over Rational Field # Free module generated by {1, 2, 3} over Rational Field sage: t = T20.an_element(); t.display() 1/2 e_1⊗e_1 sage: phi_e_T20(t) 1/2*B[1] # B[1]
- rank()#
Return the rank of the free module
self
.Since the ring over which
self
is built is assumed to be commutative (and hence has the invariant basis number property), the rank is defined uniquely, as the cardinality of any basis ofself
.EXAMPLES:
Rank of free modules over \(\ZZ\):
sage: M = FiniteRankFreeModule(ZZ, 3) sage: M.rank() 3 sage: M.tensor_module(0,1).rank() 3 sage: M.tensor_module(0,2).rank() 9 sage: M.tensor_module(1,0).rank() 3 sage: M.tensor_module(1,1).rank() 9 sage: M.tensor_module(1,2).rank() 27 sage: M.tensor_module(2,2).rank() 81
- tensor(*args, **kwds)#
Return the tensor product of
self
andothers
.This method is invoked when
TensorProductFunctor
is applied to parents.It just delegates to
tensor_product()
.EXAMPLES:
sage: M = FiniteRankFreeModule(QQ, 2); M 2-dimensional vector space over the Rational Field sage: M20 = M.tensor_module(2, 0); M20 Free module of type-(2,0) tensors on the 2-dimensional vector space over the Rational Field sage: tensor([M20, M20]) Free module of type-(4,0) tensors on the 2-dimensional vector space over the Rational Field
- tensor_power(n)#
Return the
n
-fold tensor product ofself
.EXAMPLES:
sage: M = FiniteRankFreeModule(QQ, 2) sage: M.tensor_power(3) Free module of type-(3,0) tensors on the 2-dimensional vector space over the Rational Field sage: M.tensor_module(1,2).tensor_power(3) Free module of type-(3,6) tensors on the 2-dimensional vector space over the Rational Field
- tensor_product(*others)#
Return the tensor product of
self
andothers
.EXAMPLES:
sage: M = FiniteRankFreeModule(QQ, 2) sage: M.tensor_product(M) Free module of type-(2,0) tensors on the 2-dimensional vector space over the Rational Field sage: M.tensor_product(M.dual()) Free module of type-(1,1) tensors on the 2-dimensional vector space over the Rational Field sage: M.dual().tensor_product(M, M.dual()) Free module of type-(1,2) tensors on the 2-dimensional vector space over the Rational Field sage: M.tensor_product(M.tensor_module(1,2)) Free module of type-(2,2) tensors on the 2-dimensional vector space over the Rational Field sage: M.tensor_module(1,2).tensor_product(M) Free module of type-(2,2) tensors on the 2-dimensional vector space over the Rational Field sage: M.tensor_module(1,1).tensor_product(M.tensor_module(1,2)) Free module of type-(2,3) tensors on the 2-dimensional vector space over the Rational Field sage: Sym2M = M.tensor_module(2, 0, sym=range(2)); Sym2M Free module of fully symmetric type-(2,0) tensors on the 2-dimensional vector space over the Rational Field sage: Sym01x23M = Sym2M.tensor_product(Sym2M); Sym01x23M Free module of type-(4,0) tensors on the 2-dimensional vector space over the Rational Field, with symmetry on the index positions (0, 1), with symmetry on the index positions (2, 3) sage: Sym01x23M._index_maps ((0, 1), (2, 3)) sage: N = M.tensor_module(3, 3, sym=[1, 2], antisym=[3, 4]); N Free module of type-(3,3) tensors on the 2-dimensional vector space over the Rational Field, with symmetry on the index positions (1, 2), with antisymmetry on the index positions (3, 4) sage: NxN = N.tensor_product(N); NxN Free module of type-(6,6) tensors on the 2-dimensional vector space over the Rational Field, with symmetry on the index positions (1, 2), with symmetry on the index positions (4, 5), with antisymmetry on the index positions (6, 7), with antisymmetry on the index positions (9, 10) sage: NxN._index_maps ((0, 1, 2, 6, 7, 8), (3, 4, 5, 9, 10, 11))
- zero()#
Return the zero element of
self
.EXAMPLES:
Zero elements of free modules over \(\ZZ\):
sage: M = FiniteRankFreeModule(ZZ, 3, name='M') sage: M.zero() Element zero of the Rank-3 free module M over the Integer Ring sage: M.zero().parent() is M True sage: M.zero() is M(0) True sage: T = M.tensor_module(1,1) sage: T.zero() Type-(1,1) tensor zero on the Rank-3 free module M over the Integer Ring sage: T.zero().parent() is T True sage: T.zero() is T(0) True
Components of the zero element with respect to some basis:
sage: e = M.basis('e') sage: M.zero()[e,:] [0, 0, 0] sage: all(M.zero()[e,i] == M.base_ring().zero() for i in M.irange()) True sage: T.zero()[e,:] [0 0 0] [0 0 0] [0 0 0] sage: M.tensor_module(1,2).zero()[e,:] [[[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0], [0, 0, 0]]]