# Operations on Modules

## Subquotients Related to Homomorphisms

### Kernel

`kernel`

— Method`kernel(a::ModuleFPHom)`

Return the kernel of `a`

as an object of type `SubquoModule`

.

Additionally, if `K`

denotes this object, return the inclusion map `K`

$\to$ `domain(a)`

.

**Examples**

```
julia> R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]);
julia> F = free_module(R, 3);
julia> G = free_module(R, 2);
julia> W = R[y 0; x y; 0 z]
[y 0]
[x y]
[0 z]
julia> a = hom(F, G, W);
julia> K, incl = kernel(a);
julia> K
Submodule with 1 generator
1 -> x*z*e[1] - y*z*e[2] + y^2*e[3]
represented as subquotient with no relations.
julia> incl
Map with following data
Domain:
=======
Submodule with 1 generator
1 -> x*z*e[1] - y*z*e[2] + y^2*e[3]
represented as subquotient with no relations.
Codomain:
=========
Free module of rank 3 over Multivariate polynomial ring in 3 variables over QQ
```

```
julia> R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]);
julia> F = free_module(R, 1);
julia> A = R[x; y]
[x]
[y]
julia> B = R[x^2; y^3; z^4]
[x^2]
[y^3]
[z^4]
julia> M = SubquoModule(F, A, B)
Subquotient of Submodule with 2 generators
1 -> x*e[1]
2 -> y*e[1]
by Submodule with 3 generators
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1]
julia> N = M;
julia> V = [y^2*N[1], x*N[2]]
2-element Vector{SubquoModuleElem{QQMPolyRingElem}}:
x*y^2*e[1]
x*y*e[1]
julia> a = hom(M, N, V);
julia> K, incl = kernel(a);
julia> K
Subquotient of Submodule with 3 generators
1 -> (-x + y^2)*e[1]
2 -> x*y*e[1]
3 -> -x*y*e[1]
by Submodule with 3 generators
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1]
julia> incl
Map with following data
Domain:
=======
Subquotient of Submodule with 3 generators
1 -> (-x + y^2)*e[1]
2 -> x*y*e[1]
3 -> -x*y*e[1]
by Submodule with 3 generators
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1]
Codomain:
=========
Subquotient of Submodule with 2 generators
1 -> x*e[1]
2 -> y*e[1]
by Submodule with 3 generators
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1]
```

```
julia> Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]);
julia> F = graded_free_module(Rg, 1);
julia> A = Rg[x; y];
julia> B = Rg[x^2; y^3; z^4];
julia> M = SubquoModule(F, A, B)
Graded subquotient of submodule of F generated by
1 -> x*e[1]
2 -> y*e[1]
by submodule of F generated by
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1]
julia> N = M;
julia> V = [y^2*N[1], x^2*N[2]];
julia> a = hom(M, N, V)
M -> M
x*e[1] -> x*y^2*e[1]
y*e[1] -> x^2*y*e[1]
Graded module homomorphism of degree [2]
julia> kernel(a)
(Graded subquotient of submodule of F generated by
1 -> y*e[1]
2 -> -x*y*e[1]
by submodule of F generated by
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1], Graded subquotient of submodule of F generated by
1 -> y*e[1]
2 -> -x*y*e[1]
by submodule of F generated by
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1] -> M
y*e[1] -> y*e[1]
-x*y*e[1] -> -x*y*e[1]
Homogeneous module homomorphism)
```

### Image

`image`

— Method`image(a::ModuleFPHom)`

Return the image of `a`

as an object of type `SubquoModule`

.

Additionally, if `I`

denotes this object, return the inclusion map `I`

$\to$ `codomain(a)`

.

**Examples**

```
julia> R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]);
julia> F = free_module(R, 3);
julia> G = free_module(R, 2);
julia> W = R[y 0; x y; 0 z]
[y 0]
[x y]
[0 z]
julia> a = hom(F, G, W);
julia> I, incl = image(a);
julia> I
Submodule with 3 generators
1 -> y*e[1]
2 -> x*e[1] + y*e[2]
3 -> z*e[2]
represented as subquotient with no relations.
julia> incl
Map with following data
Domain:
=======
Submodule with 3 generators
1 -> y*e[1]
2 -> x*e[1] + y*e[2]
3 -> z*e[2]
represented as subquotient with no relations.
Codomain:
=========
Free module of rank 2 over Multivariate polynomial ring in 3 variables over QQ
```

```
julia> R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]);
julia> F = free_module(R, 1);
julia> A = R[x; y]
[x]
[y]
julia> B = R[x^2; y^3; z^4]
[x^2]
[y^3]
[z^4]
julia> M = SubquoModule(F, A, B)
Subquotient of Submodule with 2 generators
1 -> x*e[1]
2 -> y*e[1]
by Submodule with 3 generators
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1]
julia> N = M;
julia> V = [y^2*N[1], x*N[2]]
2-element Vector{SubquoModuleElem{QQMPolyRingElem}}:
x*y^2*e[1]
x*y*e[1]
julia> a = hom(M, N, V);
julia> I, incl = image(a);
julia> I
Subquotient of Submodule with 2 generators
1 -> x*y^2*e[1]
2 -> x*y*e[1]
by Submodule with 3 generators
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1]
julia> incl
Map with following data
Domain:
=======
Subquotient of Submodule with 2 generators
1 -> x*y^2*e[1]
2 -> x*y*e[1]
by Submodule with 3 generators
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1]
Codomain:
=========
Subquotient of Submodule with 2 generators
1 -> x*e[1]
2 -> y*e[1]
by Submodule with 3 generators
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1]
```

```
julia> Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]);
julia> F = graded_free_module(Rg, 1);
julia> A = Rg[x; y];
julia> B = Rg[x^2; y^3; z^4];
julia> M = SubquoModule(F, A, B)
Graded subquotient of submodule of F generated by
1 -> x*e[1]
2 -> y*e[1]
by submodule of F generated by
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1]
julia> N = M;
julia> V = [y^2*N[1], x^2*N[2]];
julia> a = hom(M, N, V)
M -> M
x*e[1] -> x*y^2*e[1]
y*e[1] -> x^2*y*e[1]
Graded module homomorphism of degree [2]
julia> image(a)
(Graded subquotient of submodule of F generated by
1 -> x*y^2*e[1]
2 -> x^2*y*e[1]
by submodule of F generated by
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1], Graded subquotient of submodule of F generated by
1 -> x*y^2*e[1]
2 -> x^2*y*e[1]
by submodule of F generated by
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1] -> M
x*y^2*e[1] -> x*y^2*e[1]
x^2*y*e[1] -> x^2*y*e[1]
Homogeneous module homomorphism)
```

### Cokernel

`cokernel`

— Method`cokernel(a::ModuleFPHom)`

Return the cokernel of `a`

as an object of type `SubquoModule`

.

**Examples**

```
julia> R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]);
julia> F = free_module(R, 3);
julia> G = free_module(R, 2);
julia> W = R[y 0; x y; 0 z]
[y 0]
[x y]
[0 z]
julia> a = hom(F, G, W);
julia> cokernel(a)
Subquotient of Submodule with 2 generators
1 -> e[1]
2 -> e[2]
by Submodule with 3 generators
1 -> y*e[1]
2 -> x*e[1] + y*e[2]
3 -> z*e[2]
```

```
julia> R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]);
julia> F = free_module(R, 1);
julia> A = R[x; y]
[x]
[y]
julia> B = R[x^2; y^3; z^4]
[x^2]
[y^3]
[z^4]
julia> M = SubquoModule(F, A, B)
Subquotient of Submodule with 2 generators
1 -> x*e[1]
2 -> y*e[1]
by Submodule with 3 generators
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1]
julia> N = M;
julia> V = [y^2*N[1], x*N[2]]
2-element Vector{SubquoModuleElem{QQMPolyRingElem}}:
x*y^2*e[1]
x*y*e[1]
julia> a = hom(M, N, V);
julia> cokernel(a)
Subquotient of Submodule with 2 generators
1 -> x*e[1]
2 -> y*e[1]
by Submodule with 5 generators
1 -> x^2*e[1]
2 -> y^3*e[1]
3 -> z^4*e[1]
4 -> x*y^2*e[1]
5 -> x*y*e[1]
```

```
julia> Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]);
julia> F = graded_free_module(Rg, 3);
julia> G = graded_free_module(Rg, 2);
julia> W = Rg[y 0; x y; 0 z]
[y 0]
[x y]
[0 z]
julia> a = hom(F, G, W)
F -> G
e[1] -> y*e[1]
e[2] -> x*e[1] + y*e[2]
e[3] -> z*e[2]
Graded module homomorphism of degree [1]
julia> M = cokernel(a)
Graded subquotient of submodule of G generated by
1 -> e[1]
2 -> e[2]
by submodule of G generated by
1 -> y*e[1]
2 -> x*e[1] + y*e[2]
3 -> z*e[2]
```

`cokernel(F::FreeMod{R}, A::MatElem{R}) where R`

Return the cokernel of `A`

as an object of type `SubquoModule`

with ambient free module `F`

.

**Examples**

```
julia> R, (x,y,z) = polynomial_ring(QQ, ["x", "y", "z"]);
julia> F = free_module(R, 2)
Free module of rank 2 over Multivariate polynomial ring in 3 variables over QQ
julia> A = R[x y; 2*x^2 3*y^2]
[ x y]
[2*x^2 3*y^2]
julia> M = cokernel(F, A)
Subquotient of Submodule with 2 generators
1 -> e[1]
2 -> e[2]
by Submodule with 2 generators
1 -> x*e[1] + y*e[2]
2 -> 2*x^2*e[1] + 3*y^2*e[2]
julia> ambient_free_module(M) === F
true
```

```
julia> Rg, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]);
julia> F = graded_free_module(Rg, [8,8])
Graded free module Rg^2([-8]) of rank 2 over Rg
julia> A = Rg[x y; 2*x^2 3*y^2]
[ x y]
[2*x^2 3*y^2]
julia> M = cokernel(F, A)
Graded subquotient of submodule of F generated by
1 -> e[1]
2 -> e[2]
by submodule of F generated by
1 -> x*e[1] + y*e[2]
2 -> 2*x^2*e[1] + 3*y^2*e[2]
julia> ambient_free_module(M) === F
true
julia> degrees_of_generators(M)
2-element Vector{FinGenAbGroupElem}:
[8]
[8]
```

## Direct Sums and Products

`direct_sum`

— Method`direct_sum(M::ModuleFP{T}...; task::Symbol = :sum) where T`

Given modules $M_1\dots M_n$, say, return the direct sum $\bigoplus_{i=1}^n M_i$.

Additionally, return

- a vector containing the canonical injections $M_i\to\bigoplus_{i=1}^n M_i$ if
`task = :sum`

(default), - a vector containing the canonical projections $\bigoplus_{i=1}^n M_i\to M_i$ if
`task = :prod`

, - two vectors containing the canonical injections and projections, respectively, if
`task = :both`

, - none of the above maps if
`task = :none`

.

`direct_product`

— Method`direct_product(M::ModuleFP{T}...; task::Symbol = :prod) where T`

Given modules $M_1\dots M_n$, say, return the direct product $\prod_{i=1}^n M_i$.

Additionally, return

- a vector containing the canonical projections $\prod_{i=1}^n M_i\to M_i$ if
`task = :prod`

(default), - a vector containing the canonical injections $M_i\to\prod_{i=1}^n M_i$ if
`task = :sum`

, - two vectors containing the canonical projections and injections, respectively, if
`task = :both`

, - none of the above maps if
`task = :none`

.

## Truncation

`truncate`

— Function`truncate(I::ModuleFP, g::FinGenAbGroupElem, task::Symbol=:with_morphism)`

Given a finitely presented graded module `M`

over a $\mathbb Z$-graded multivariate polynomial ring with positive weights, return the truncation of `M`

at degree `g`

.

Put more precisely, return the truncation as an object of type `SubquoModule`

. Additionally, if `N`

denotes this object,

- return the inclusion map
`N`

$\to$`M`

if`task = :with_morphism`

(default), - return and cache the inclusion map
`N`

$\to$`M`

if`task = :cache_morphism`

, - do none of the above if
`task = :none`

.

If `task = :only_morphism`

, return only the inclusion map. truncate(M::ModuleFP, d::Int, task::Symbol = :with_morphism)

Given a module `M`

as above, and given an integer `d`

, convert `d`

into an element `g`

of the grading group of `base_ring(I)`

and proceed as above.

**Examples**

```
julia> R, (x, y, z) = graded_polynomial_ring(QQ, ["x", "y", "z"]);
julia> F = graded_free_module(R, 1)
Graded free module R^1([0]) of rank 1 over R
julia> V = [x*F[1]; y^4*F[1]; z^5*F[1]];
julia> M, _ = quo(F, V);
julia> M[1]
e[1]
julia> MT = truncate(M, 3);
julia> MT[1]
Graded subquotient of submodule of F generated by
1 -> z^3*e[1]
2 -> y*z^2*e[1]
3 -> y^2*z*e[1]
4 -> y^3*e[1]
5 -> x*z^2*e[1]
6 -> x*y*z*e[1]
7 -> x*y^2*e[1]
8 -> x^2*z*e[1]
9 -> x^2*y*e[1]
10 -> x^3*e[1]
by submodule of F generated by
1 -> x*e[1]
2 -> y^4*e[1]
3 -> z^5*e[1]
```

## Twists

In the graded case, we have:

`twist`

— Method`twist(M::ModuleFP{T}, g::FinGenAbGroupElem) where {T<:MPolyDecRingElem}`

Return the twisted module `M(g)`

.

`twist(M::ModuleFP{T}, W::Vector{<:IntegerUnion}) where {T<:MPolyDecRingElem}`

Given a module `M`

over a $\mathbb Z^m$-graded polynomial ring and a vector `W`

of $m$ integers, convert `W`

into an element `g`

of the grading group of the ring and proceed as above.

`twist(M::ModuleFP{T}, d::IntegerUnion) where {T<:MPolyDecRingElem}`

Given a module `M`

over a $\mathbb Z$-graded polynomial ring and an integer `d`

, convert `d`

into an element `g`

of the grading group of the ring and proceed as above.

**Examples**

```
julia> R, (x, y) = graded_polynomial_ring(QQ, ["x", "y"]);
julia> I = ideal(R, [zero(R)])
Ideal generated by
0
julia> M = quotient_ring_as_module(I)
Graded submodule of R^1
1 -> e[1]
represented as subquotient with no relations
julia> degree(gen(M, 1))
[0]
julia> N = twist(M, 2)
Graded submodule of R^1
1 -> e[1]
represented as subquotient with no relations
julia> degree(gen(N, 1))
[-2]
```