# Free Modules

In this section, the expression *free module* refers to a free module of finite rank over a ring of type `MPolyRing`

, `MPolyQuo`

, `MPolyLocalizedRing`

, or `MPolyQuoLocalizedRing`

. More concretely, given a ring $R$ of one of these types, the free $R$-modules considered are of type $R^p$, where we think of $R^p$ as a free module with a given basis, namely the basis of standard unit vectors. Accordingly, elements of free modules are represented by coordinate vectors, and homomorphisms between free modules by matrices.

By convention, vectors are row vectors, and matrices operate by multiplication on the right.

## Types

All OSCAR types for the modules considered here belong to the abstract type `ModuleFP{T}`

, where `T`

is the element type of the underlying ring. The free modules belong to the abstract subtype `AbstractFreeMod{T} <: ModuleFP{T}`

, they are modelled as objects of the concrete type `FreeMod{T} <: AbstractFreeMod{T}`

.

Canonical maps such us the canonical projection onto a quotient module arise in many constructions in commutative algebra. The `FreeMod`

type is designed so that it allows for the caching of such maps when executing functions. The `direct_sum`

function discussed in this section provides an example.

## Constructors

`free_module`

— Function```
free_module(R::MPolyRing, p::Int, name::String = "e"; cached::Bool = false)
free_module(R::MPolyQuo, p::Int, name::String = "e"; cached::Bool = false)
free_module(R::MPolyLocalizedRing, p::Int, name::String = "e"; cached::Bool = false)
free_module(R::MPolyQuoLocalizedRing, p::Int, name::String = "e"; cached::Bool = false)
```

Return the free $R$-module $R^p$, created with its basis of standard unit vectors.

The string `name`

specifies how the basis vectors are printed.

**Examples**

```
julia> R, (x, y, z) = PolynomialRing(QQ, ["x", "y", "z"]);
julia> FR = free_module(R, 2)
Free module of rank 2 over Multivariate Polynomial Ring in x, y, z over Rational Field
julia> x*FR[1]
x*e[1]
julia> P = ideal(R, [x, y, z]);
julia> U = complement_of_ideal(P);
julia> RL, _ = Localization(R, U);
julia> FRL = free_module(RL, 2, "f")
Free module of rank 2 over localization of Multivariate Polynomial Ring in x, y, z over Rational Field at the complement of ideal(x, y, z)
julia> RL(x)*FRL[1]
x//1*f[1]
julia> RQ, _ = quo(R, ideal(R, [2*x^2-y^3, 2*x^2-y^5]));
julia> FRQ = free_module(RQ, 2, "g")
Free module of rank 2 over Quotient of Multivariate Polynomial Ring in x, y, z over Rational Field by ideal(2*x^2 - y^3, 2*x^2 - y^5)
julia> RQ(x)*FRQ[1]
x*g[1]
julia> RQL, _ = Localization(RQ, U);
julia> FRQL = free_module(RQL, 2, "h")
Free module of rank 2 over Localization of Quotient of Multivariate Polynomial Ring in x, y, z over Rational Field by ideal(2*x^2 - y^3, 2*x^2 - y^5) at the multiplicative set complement of ideal(x, y, z)
julia> RQL(x)*FRQL[1]
x//1*h[1]
```

## Data Associated to Free Modules

If `F`

is a free `R`

-module, then

`base_ring(F)`

refers to`R`

,`basis(F)`

,`gens(F)`

to the basis vectors of`F`

,`rank(F)`

,`ngens(F)`

,`dim(F)`

to the number of these vectors, and`F[i]`

,`basis(F, i)`

,`gen(F, i)`

to the`i`

-th such vector.

###### Examples

```
julia> R, (x, y) = PolynomialRing(QQ, ["x", "y"]);
julia> F = free_module(R, 3);
julia> basis(F)
3-element Vector{FreeModElem{fmpq_mpoly}}:
e[1]
e[2]
e[3]
julia> rank(F)
3
```

## Elements of Free Modules

All OSCAR types for elements of the modules considered here belong to the abstract type `ModuleElemFP{T}`

, where `T`

is the element type of the underlying ring. The free modules belong to the abstract subtype `AbstractFreeModElem{T} <: ModuleFPElem{T}`

. They are modelled as objects of the concrete type `FreeModElem{T} <: AbstractFreeModElem{T}`

which implements an element $f$ of a free module $F$ as a sparse row, that is, as an object of type `SRow{T}`

. This object specifies the coordinates of $f$ with respect to the basis of standard unit vectors of $F$. To create an element, enter its coordinates as a sparse row or a vector:

`(F::FreeMod{T})(c::SRow{T}) where T`

`(F::FreeMod{T})(c::Vector{T}) where T`

Alternatively, directly write the element as a linear combination of basis vectors of $F$:

##### Examples

```
julia> R, (x, y) = PolynomialRing(QQ, ["x", "y"]);
julia> F = free_module(R, 3);
julia> f = F(sparse_row(R, [(1,x),(3,y)]))
x*e[1] + y*e[3]
julia> g = F([x, zero(R), y])
x*e[1] + y*e[3]
julia> h = x*F[1] + y*F[3]
x*e[1] + y*e[3]
julia> f == g == h
true
```

Given an element `f`

of a free module `F`

over a multivariate polynomial ring with element type `T`

,

`parent(f)`

refers to`F`

, and`coordinates(f)`

to the coordinate vector of`f`

, returned as an object of type`SRow{T}`

.

##### Examples

```
julia> R, (x, y) = PolynomialRing(QQ, ["x", "y"]);
julia> F = free_module(R, 3);
julia> f = x*F[1] + y*F[3]
x*e[1] + y*e[3]
julia> parent(f)
Free module of rank 3 over Multivariate Polynomial Ring in x, y over Rational Field
julia> coordinates(f)
Sparse row with positions [1, 3] and values fmpq_mpoly[x, y]
```

The zero element of a free module is obtained as follows:

`zero`

— Method`zero(F::AbstractFreeMod)`

Return the zero element of `F`

.

Whether a given element of a free module is zero can be tested as follows:

`iszero`

— Method`iszero(f::AbstractFreeModElem)`

Return `true`

if `f`

is zero, `false`

otherwise.

## Tests on Free Modules

`==`

— Method`==(F::FreeMod, G::FreeMod)`

Return `true`

if `F`

and `G`

are equal, `false`

otherwise.

Here, `F`

and `G`

are equal iff their base rings, ranks, and names for printing the basis elements are equal.

`iszero`

— Method`iszero(F::AbstractFreeMod)`

Return `true`

if `F`

is the zero module, `false`

otherwise.

## Homomorphisms from Free Modules

All OSCAR types for homomorphisms of the modules considered here belong to the abstract type `ModuleFPHom{T1, T2}`

, where `T1`

and `T2`

are the types of domain and codomain respectively. A homomorphism $F\rightarrow M$ from a free module $F$ is determined by specifying the images of the basis vectors of $F$ in $M$. For such homomorphisms, OSCAR provides the concrete type `FreeModuleHom{T1, T2} <: ModuleFPHom{T1, T2}`

as well as the following constructors:

`hom`

— Method`hom(F::FreeMod, M::ModuleFP{T}, V::Vector{<:ModuleFPElem{T}}) where T`

Given a vector `V`

of `rank(F)`

elements of `M`

, return the homomorphism `F`

$\to$ `M`

which sends the `i`

-th basis vector of `F`

to the `i`

-th entry of `V`

.

`hom(F::FreeMod, M::ModuleFP{T}, A::MatElem{T}) where T`

Given a matrix `A`

with `rank(F)`

rows and `ngens(M)`

columns, return the homomorphism `F`

$\to$ `M`

which sends the `i`

-th basis vector of `F`

to the linear combination $\sum_j A[i,j]*M[j]$ of the generators `M[j]`

of `M`

.

**Examples**

```
julia> R, (x, y, z) = PolynomialRing(QQ, ["x", "y", "z"])
(Multivariate Polynomial Ring in x, y, z over Rational Field, fmpq_mpoly[x, y, z])
julia> F = free_module(R, 3)
Free module of rank 3 over Multivariate Polynomial Ring in x, y, z over Rational Field
julia> G = free_module(R, 2)
Free module of rank 2 over Multivariate Polynomial Ring in x, y, z over Rational Field
julia> V = [y*G[1], x*G[1]+y*G[2], z*G[2]]
3-element Vector{FreeModElem{fmpq_mpoly}}:
y*e[1]
x*e[1] + y*e[2]
z*e[2]
julia> a = hom(F, G, V)
Map with following data
Domain:
=======
Free module of rank 3 over Multivariate Polynomial Ring in x, y, z over Rational Field
Codomain:
=========
Free module of rank 2 over Multivariate Polynomial Ring in x, y, z over Rational Field
julia> a(F[2])
x*e[1] + y*e[2]
julia> B = R[y 0; x y; 0 z]
[y 0]
[x y]
[0 z]
julia> b = hom(F, G, B)
Map with following data
Domain:
=======
Free module of rank 3 over Multivariate Polynomial Ring in x, y, z over Rational Field
Codomain:
=========
Free module of rank 2 over Multivariate Polynomial Ring in x, y, z over Rational Field
julia> a == b
true
```

Given a homomorphism of type `FreeModuleHom`

, a matrix representing it is recovered by the following function:

`matrix`

— Method`matrix(a::FreeModuleHom)`

Given a homomorphism `a : F → M`

of type `FreeModuleHom`

, return a matrix `A`

over `base_ring(M)`

with `rank(F)`

rows and `ngens(M)`

columns such that $a(F[i]) = \sum_j A[i,j]*M[j]$.

**Examples**

```
julia> R, (x, y, z) = PolynomialRing(QQ, ["x", "y", "z"])
(Multivariate Polynomial Ring in x, y, z over Rational Field, fmpq_mpoly[x, y, z])
julia> F = free_module(R, 3)
Free module of rank 3 over Multivariate Polynomial Ring in x, y, z over Rational Field
julia> G = free_module(R, 2)
Free module of rank 2 over Multivariate Polynomial Ring in x, y, z over Rational Field
julia> V = [y*G[1], x*G[1]+y*G[2], z*G[2]];
julia> a = hom(F, G, V);
julia> matrix(a)
[y 0]
[x y]
[0 z]
```

The domain and codomain of a homomorphism `a`

of type `FreeModuleHom`

can be recovered by entering `domain(a)`

and `codomain(a)`

, respectively.