6. The notion of module

This notebook is part of the Introduction to manifolds in SageMath by Andrzej Chrzeszczyk (Jan Kochanowski University of Kielce, Poland).

In [1]:
version()
Out[1]:
'SageMath version 9.6, Release Date: 2022-05-15'

If F is a field, a set V is called a vector space over F if there is an operation of addition $\ (x,y) → x+y\ \ $ from V×V to V, and a scalar multiplication operation $\ \ (α,x) → αx\ \ $ from F×V to V, such that the following properties are satisfied.
(i) (u+v) + w = u + (v+w) for all u, v, w ∈ V,
(ii) u+v=v+u for all u, v ∈ V,
(iii) There exists an element 0 ∈ V such that 0+v=v+0 for all v ∈ V,
(iv) For each v ∈ V there exists u ∈ V such that v+u=0,
(v) 1v=v for all v ∈ V,
(vi) $(\alpha\beta)v=\alpha(\beta v)$ for all $\alpha,\beta\in F$ and v∈V,
(vii) $(\alpha+\beta)v=\alpha v+\beta v$ for all $\alpha,\beta\in F$ and v∈V,
(viii) $\alpha(u+v)=\alpha u+\alpha v$ for all $\alpha\in F$ and $u$∈V.

The formal definition of the module M over the ring R is exactly as above (with V replaced by M and F replaced by R) but we relax the requirement that F be a field, and instead allow an arbitrary ring R (with unity). We shall restrict ourselves to the commutative rings R.

A free module of finite rank over a commutative ring R is a module $M$ over R that admits a finite basis, that is a finite family $\{e_1,\ldots,e_k\}$, which spans $M$, i.e., for every $v\in M$, $\ v=\sum_{i=1}^k a_ie_i$ for some $ a_i\in$ R, and $e_i$ are linearly independent i.e., $\sum_{i=1}^k a_ie_i=0$ implies that all $a_i$ are zero.

Since R is commutative, it has the invariant basis number property, so that the rank (dimension) of the free module M is defined uniquely, as the cardinality of any basis of $M$.

General remark on free modules in SageMath

Basic motivation for introducing free modules into consideration in SageMath Manifolds is the fact that the sets of vector fields and tensor fields on a parallelizable open subset U of the manifold, are free modules over the ring of scalar fields on U.

Some frequently used commands from SageMath FiniteRankFreeModule:

an_element              endomorphism             sym_bilinear_form        
automorphism            hom                      tensor
bases                   irange                   tensor_from_comp
basis                   linear_form              tensor_module
change_of_basis         rank                     alternating_form                  
default_basis           set_change_of_basis      dual_exterior_power
dual                    set_default_basis        exterior_power

In our examples we will use mainly the SageMath symbolic ring SR.


Example 6.1

FiniteRankFreeModule in SageMath:

Symbolic ring SR is considered as a field:

In [2]:
SR.is_field()                            # Symbolic ring is a field
Out[2]:
True

so the finite rank free modules over SR are in fact vector spaces:

In [3]:
V = FiniteRankFreeModule(SR,4,name='V')  # rank 4 free module V over SR
#V?  --detailed explanations concerning FiniteRankFreeModule
V                                        # information on V
Out[3]:
4-dimensional vector space V over the Symbolic Ring

Defining V as a finite rank free module over a field we obtain a vector space without predefined basis.

In [4]:
V.bases()                       # check that V has no predefined  basis
Out[4]:
[]

Later we shall see that without any specific coordinate choice, no basis can be distinguished in a tangent space. This is one more motivation for using modules in SageMath Manifolds.


Let us check that defining vector space with VectorSpace command, we introduce a predefined basis.

In [5]:
W = VectorSpace(SR,4); W
Out[5]:
Vector space of dimension 4 over Symbolic Ring
In [6]:
W.basis()
Out[6]:
[
(1, 0, 0, 0),
(0, 1, 0, 0),
(0, 0, 1, 0),
(0, 0, 0, 1)
]

In SageMath the VectorSpace of rank 4 over R is in fact R^4 -the Cartesian power of R.

In [7]:
W == SR^4
Out[7]:
True

but an analogous FiniteRankFreeModule is not:

In [8]:
V == SR^4
Out[8]:
False


Example 6.2

To define a vector in SageMath Manifolds we need some basis.

In [9]:
%display latex
M = FiniteRankFreeModule(SR, 4, name='M')  # module M
e = M.basis('e')                           # basis of M
# e?  -detailed explanations concerning bases
# range(1,5)=[1,2,3,4]  --coefficients of the linear combination
u = M(range(1,5),name='u');u.disp()        # show vector
Out[9]:
\(\displaystyle u = e_{0} + 2 e_{1} + 3 e_{2} + 4 e_{3}\)

Vectors can be defined also as linear combinations of the basis.

In [10]:
al = srange(1,5)         # a more flexible version of range
                         # linear combination of basis:
w = sum([al[k]*e[k] for k in range(4)])
w.disp()                   # show w
Out[10]:
\(\displaystyle e_{0} + 2 e_{1} + 3 e_{2} + 4 e_{3}\)
In [11]:
# a more general linear combination of a basis 
# \alpha+[Tab] gives the Greek letter alpha
al = var('α',n=4)         # α_i, i=1,2,3,4
                          # linear combination of basis:
w = sum([al[k]*e[k] for k in range(4)])
w.disp()                  # show w
Out[11]:
\(\displaystyle α_{0} e_{0} + α_{1} e_{1} + α_{2} e_{2} + α_{3} e_{3}\)


Linear transformations in finite rank free module


By the linearity of the map $\Phi:M\to N$ between two modules over $R$ we mean the condition

$$ \Phi (av + bw ) = a\Phi (v) + b\Phi (w ),\quad\text{for}\quad v,w\in M,\quad a,b\in R.$$


Automorphism


Automorphism of the module M is a bijective linear transformation M $\to$ M.

An automorphism allows for example for defining a new basis.
If more than one bases are defined, the first one is the default one.


Example 6.3

Let us define a module with two bases and an automorphism defining the change of basis.

In [12]:
%display latex
M = FiniteRankFreeModule(SR, 4, name='M')   # 4-dim module over SR
a = M.automorphism()                        # automorphism of M
# a? --detailed explanations concerning module automorphism
e = M.basis('e')                            # define default basis
f = M.basis('f')                            # define second basis
# diagonal matrix with diagonal (4,3,2,1)   
a[e,:]=diagonal_matrix(4, srange(4,0,-1));  # matrix of automorphism
M.set_change_of_basis(e, f, a)              # define change of basis
u = M(range(1,5),name='u')                  # define vector
# displaying the vector in non-default basis needs 
# the basis name as an argument
u.disp(),'________',u.disp(f)               # vector u in bases e and f
Out[12]:
\(\displaystyle \left(u = e_{0} + 2 e_{1} + 3 e_{2} + 4 e_{3}, \verb|________|, u = \frac{1}{4} f_{0} + \frac{2}{3} f_{1} + \frac{3}{2} f_{2} + 4 f_{3}\right)\)
In [13]:
M.default_basis()                           # default basis
Out[13]:
\(\displaystyle \left(e_{0},e_{1},e_{2},e_{3}\right)\)

Matrix of the automorphism:

In [14]:
a.matrix()                                  # matrix of automorphism a
Out[14]:
\(\displaystyle \left(\begin{array}{rrrr} 4 & 0 & 0 & 0 \\ 0 & 3 & 0 & 0 \\ 0 & 0 & 2 & 0 \\ 0 & 0 & 0 & 1 \end{array}\right)\)


Example 6.4

The new basis can be also defined component by component.

In [15]:
%display latex
M=FiniteRankFreeModule(SR,4,name='M')      # 4-dim module over SR
e = M.basis('e')                           # basis e
f = M.basis('f', from_family=              # new basis f contains lin.comb.
            (4*e[0],3*e[1],2*e[2],e[3]))   # of elements of e
u = M(range(1,5),name='u');                # vector u
u.disp(),'______',u.disp(f)                # u in bases e and f
Out[15]:
\(\displaystyle \left(u = e_{0} + 2 e_{1} + 3 e_{2} + 4 e_{3}, \verb|______|, u = \frac{1}{4} f_{0} + \frac{2}{3} f_{1} + \frac{3}{2} f_{2} + 4 f_{3}\right)\)

Matrix of the change of basis e $\to$ f:

In [16]:
M.change_of_basis(e,f).matrix(e)           # matrix of change of basis e->f
Out[16]:
\(\displaystyle \left(\begin{array}{rrrr} 4 & 0 & 0 & 0 \\ 0 & 3 & 0 & 0 \\ 0 & 0 & 2 & 0 \\ 0 & 0 & 0 & 1 \end{array}\right)\)

Matrix of the change of basis f $\to$ e:

In [17]:
M.change_of_basis(f,e).matrix(e)           # matrix of change of basis f->e
Out[17]:
\(\displaystyle \left(\begin{array}{rrrr} \frac{1}{4} & 0 & 0 & 0 \\ 0 & \frac{1}{3} & 0 & 0 \\ 0 & 0 & \frac{1}{2} & 0 \\ 0 & 0 & 0 & 1 \end{array}\right)\)


Endomorphism


Endomorphism of the module M is a general linear transformation M $\to$ M.


Example 6.5

Define an endomorphism using arbitrarily chosen matrix.

In [18]:
M = FiniteRankFreeModule(SR,4,name='M')    # 4-dim module over SR
e = M.basis('e')                           # basis e
ma = matrix(4,4,range(16))                 # matrix of endomorphism                                           
phi = M.endomorphism(ma, basis=e,          # define an endomorphism
        name='phi',latex_name=r'\Phi')     # Phi
u = M(range(1,5),name='u');                # vector u
phi(u).disp()                              # Phi(u)
Out[18]:
\(\displaystyle \Phi\left(u\right) = 20 e_{0} + 60 e_{1} + 100 e_{2} + 140 e_{3}\)


Using general symbolic matrices


Example 6.6

To obtain general $N\times N$ matrices with elements $a_{ij}$ we can use for example the following definition:

In [19]:
aa = [[var('a'+str(i)+str(j))                # 4x4 symbolic matrix is
       for j in range(4)]                    # defined by list of lists
        for i in range(4)]
In [20]:
aa                                         # list of lists (list of rows)
Out[20]:
\(\displaystyle \left[\left[a_{00}, a_{01}, a_{02}, a_{03}\right], \left[a_{10}, a_{11}, a_{12}, a_{13}\right], \left[a_{20}, a_{21}, a_{22}, a_{23}\right], \left[a_{30}, a_{31}, a_{32}, a_{33}\right]\right]\)

General endomorphism of a 4-dimensional module:

In [21]:
M = FiniteRankFreeModule(SR,4,name='M')    # 4-dim module M over SR 
e = M.basis('e')                           # basis of M
phi = M.endomorphism(aa, basis=e,          # define an endomorphism
    name='phi',latex_name=r'\Phi')         # using matrix
for k in range(4):                         # show the values Phi(e_i)
    show(phi(e[k]).disp()) 
# coefficients of phi(e_k) are taken from 
# the k-th column of phi matrix 
\(\displaystyle \Phi\left(e_{0}\right) = a_{00} e_{0} + a_{10} e_{1} + a_{20} e_{2} + a_{30} e_{3}\)
\(\displaystyle \Phi\left(e_{1}\right) = a_{01} e_{0} + a_{11} e_{1} + a_{21} e_{2} + a_{31} e_{3}\)
\(\displaystyle \Phi\left(e_{2}\right) = a_{02} e_{0} + a_{12} e_{1} + a_{22} e_{2} + a_{32} e_{3}\)
\(\displaystyle \Phi\left(e_{3}\right) = a_{03} e_{0} + a_{13} e_{1} + a_{23} e_{2} + a_{33} e_{3}\)
In [22]:
%display latex                             # matrix of endomorphism
phi.matrix()
Out[22]:
\(\displaystyle \left(\begin{array}{rrrr} a_{00} & a_{01} & a_{02} & a_{03} \\ a_{10} & a_{11} & a_{12} & a_{13} \\ a_{20} & a_{21} & a_{22} & a_{23} \\ a_{30} & a_{31} & a_{32} & a_{33} \end{array}\right)\)


Homomorphisms of modules


The general linear maps between modules M, N are homomorphisms.

A bijective homomorphism is called isomorphism.


Example 6.7

Define two modules and a homomorphism between them.

In [23]:
M = FiniteRankFreeModule(SR,4,name='M')  # 4-dim module M over SR
N = FiniteRankFreeModule(SR,2,name='N')  # 2-dim module over SR
e = M.basis('e')                         # basis of M
f = N.basis('f')                         # basis of N
ma = matrix(2,4,lambda i,j:i+j)          # matrix a_ij=i+j
phi = M.hom(N,ma); phi                   # define homomorphism
                                         # with matrix ma
Out[23]:
\(\displaystyle \mbox{Generic morphism: From: 4-dimensional vector space M over the Symbolic Ring To: 2-dimensional vector space N over the Symbolic Ring}\)
In [24]:
# mathematical object of which "phi" is an element
phi.parent()
Out[24]:
\(\displaystyle \mathrm{Hom}\left(M,N\right)\)

Let us check the additivity property using general vectors V, W.

In [25]:
v = var('v',n=4)  #(v0,v1,v2,v3)           # components of vector V
w = var('w',n=4)  #(w0,w1,w2,w3)           # components of vector W
V = M(list(v))                             # vector V
W = M(list(w))                             # vector W
phi(V+W) == phi(V) + phi(W)                # check the additivity
Out[25]:
\(\displaystyle \mathrm{True}\)


The value of the homomorphism phi on the vector V in the basis of N:

In [26]:
phi(V).disp()                            # phi(V)
Out[26]:
\(\displaystyle \left( v_{1} + 2 \, v_{2} + 3 \, v_{3} \right) f_{0} + \left( v_{0} + 2 \, v_{1} + 3 \, v_{2} + 4 \, v_{3} \right) f_{1}\)

The matrix of the homomorphism phi:

In [27]:
phi.matrix()                             # matrix of homomorphism
Out[27]:
\(\displaystyle \left(\begin{array}{rrrr} 0 & 1 & 2 & 3 \\ 1 & 2 & 3 & 4 \end{array}\right)\)


Linear forms on modules. Dual module


By a linear form or a linear functional on a module $\ M\ $ over $R$ we mean the map $f:M\to R$ such that

$$ f (av + bw ) = af(v) + bf(w ),\quad\text{for}\quad v,w\in M,\quad a,b\in R.$$


The dual module $M^*$ is the module of linear forms on a module $M$.


Example 6.8

The module of all linear functionals or linear forms on M in SageMath Manifold is M.dual():

In [28]:
M = FiniteRankFreeModule(SR,4,name='M')  # 4-dim module over SR
Mstar = M.dual(); Mstar
# Since SR is a field, M is a vector space
Out[28]:
\(\displaystyle M^*\)


Dual basis


SageMath dual.basis allows to define a dual basis to a given basis $\ \{e_i\}_{i=1}^n$, i.e., the set of linear functionals $\ \{e^i\}_{i=1}^n\ $ such that $\quad e^i(e_j)=\delta^i_j.$


Example 6.9

Define dual basis in SageMath Manifolds.

In [29]:
# continuation
e = M.basis('e');                       # basis of M
ep = e.dual_basis(); ep                    # dual basis
Out[29]:
\(\displaystyle \left(e^{0},e^{1},e^{2},e^{3}\right)\)

Let us check that $\quad e^i(e_j)=\delta^i_j$:

In [30]:
%display latex
matrix(4,4,lambda i,j:ep[i](e[j]))      # matrix  e^i(e_j)
Out[30]:
\(\displaystyle \left(\begin{array}{rrrr} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{array}\right)\)


Linear forms on a module M are linear combinations of elements of the dual basis.


Example 6.10

Define a linear form in SageMath Manifolds.

In [31]:
# continuation
a = M.linear_form('a')                    # linear form a on M               
a[:] = 1,2,3,4                            # define components of a
a.disp()                                  # show a
Out[31]:
\(\displaystyle a = e^{0} + 2 e^{1} + 3 e^{2} + 4 e^{3}\)

Linear forms are elements of the dual module $M^*$.

In [32]:
# mathematical object of which "a" is an element
print(a.parent())
Dual of the 4-dimensional vector space M over the Symbolic Ring
In [33]:
Mstar = M.dual()
a.parent() == Mstar                 # check if parent of a is M dual
Out[33]:
\(\displaystyle \mathrm{True}\)

What's next?

Take a look at the notebook Smooth functions and pullbacks.