Let $$R$$ be a connected graded algebra. A finitely presented module over $$R$$ is a module isomorphic to the cokernel of an $$R$$-linear homomorphism $$f: F_1 \to F_0$$ of finitely generated free modules: the generators of $$F_0$$ correspond to the generators of the module, and the generators of $$F_1$$ correspond to its relations, via the map $$f$$.

This module class takes as input a set of generators and relations and uses them to construct a presentation, using the class FreeGradedModuleMorphism. It also allows such a morphism as input.

This package was designed with homological algebra in mind, and its API focuses on maps rather than objects. A good example of this is the kernel function sage.modules.fp_graded.morphism.FPModuleMorphism.kernel_inclusion(), which computes the kernel of a homomorphism $$f: M\to N$$. Its return value is not an instance of the module class, but rather an injective homomorphism $$i: K\to M$$ with the property that $$\operatorname{im}(i) = \ker(f)$$.

Note

Some methods here require in addition that $$R$$ be an algebra over a field or a PID and that Sage has a description of a basis for $$R$$.

AUTHORS:

• Robert R. Bruner, Michael J. Catanzaro (2012): Initial version.

• Sverre Lunoee–Nielsen and Koen van Woerden (2019-11-29): Updated the original software to Sage version 8.9.

• Sverre Lunoee–Nielsen (2020-07-01): Refactored the code and added new documentation and tests.

A finitely presented module over a connected graded algebra.

INPUT:

One of the following:

• arg0 – a morphism such that the module is the cokernel, or a free graded module, in which case the output is the same module, viewed as finitely presented

Otherwise:

• arg0 – the graded connected algebra over which the module is defined; this algebra must be equipped with a graded basis

• generator_degrees – tuple of integer degrees

• relations – tuple of relations; a relation is a tuple of coefficients $$(c_1, \ldots, c_n)$$, ordered so that they correspond to the module generators, that is, such a tuple corresponds to the relation

$c_1 g_1 + \ldots + c_n g_n = 0$

if the generators are $$(g_1, \ldots, g_n)$$

EXAMPLES:

sage: E.<x,y> = ExteriorAlgebra(QQ)
sage: M = FPModule(E, [0, 1], [[x, 1]])
sage: a, b = M.generators()
sage: x*a + b == 0
True
sage: (x*a + b).normalize()
0

sage: A3 = SteenrodAlgebra(2, profile=(4,3,2,1))
sage: M = FPModule(A3, [0, 1], [[Sq(2), Sq(1)]])
sage: M.generators()
(g[0], g[1])
sage: M.relations()
(Sq(2)*g[0] + Sq(1)*g[1],)
sage: M.is_trivial()
False

sage: Z = FPModule(A3, [])
sage: Z.generators()
()
sage: Z.relations()
()
sage: Z.is_trivial()
True

sage: F = FreeGradedModule(E, [0, 1])
sage: one = Hom(F, F).identity()
sage: Z = FPModule(one)
sage: Z.is_trivial()
True

Free graded left module on 2 generators over The exterior algebra of rank 2 over Rational Field
Element
an_element(n=None)

An element of this module.

This function chooses deterministically an element, i.e. the output depends only on the module and its input n.

INPUT:

• n – (optional) the degree of the element to construct

OUTPUT:

A module element of the given degree.

EXAMPLES:

sage: A2 = SteenrodAlgebra(2, profile=(3,2,1))
sage: M = FPModule(A2, [0,2,4], [[0, Sq(5), Sq(3)], [Sq(7), 0, Sq(2)*Sq(1)]])

sage: [M.an_element(i) for i in range(10)]
[g[0],
Sq(1)*g[0],
Sq(2)*g[0] + g[2],
Sq(0,1)*g[0] + Sq(1)*g[2],
Sq(1,1)*g[0] + Sq(2)*g[2] + g[4],
Sq(2,1)*g[0] + Sq(0,1)*g[2] + Sq(1)*g[4],
Sq(0,2)*g[0] + Sq(1,1)*g[2] + Sq(2)*g[4],
Sq(0,0,1)*g[0] + Sq(2,1)*g[2] + Sq(0,1)*g[4],
Sq(1,0,1)*g[0] + Sq(6)*g[2] + Sq(1,1)*g[4],
Sq(2,0,1)*g[0] + Sq(4,1)*g[2] + Sq(2,1)*g[4]]
basis_elements(n, verbose=False)

Return a basis for the free module of degree n module elements.

Note

Suppose self is a module over the graded algebra $$A$$ with base ring $$R$$. This returns a basis as a free module over $$R$$.

INPUT:

• n – an integer

• verbose – (default: False) a boolean to control if log messages should be emitted

OUTPUT:

A list of homogeneous module elements of degree n which is a basis for the free module of all degree n module elements.

EXAMPLES:

sage: A2 = SteenrodAlgebra(2, profile=(3,2,1))
sage: M.<m0,m2> = FPModule(A2, [0,2], [[Sq(4), Sq(2)], [0, Sq(6)]])

sage: M.basis_elements(4)
(Sq(1,1)*m0, Sq(4)*m0)

sage: M.basis_elements(5)
(Sq(2,1)*m0, Sq(5)*m0, Sq(0,1)*m2)

sage: M.basis_elements(25)
()

sage: M.basis_elements(0)
(m0,)

sage: M.basis_elements(2)
(Sq(2)*m0, m2)
change_ring(algebra)

Change the base ring of self.

INPUT:

• algebra – a connected graded algebra

OUTPUT:

The finitely presented module over algebra defined with the exact same number of generators of the same degrees and relations as self.

EXAMPLES:

sage: A = SteenrodAlgebra(2)
sage: A2 = SteenrodAlgebra(2, profile=(3,2,1))

sage: M = FPModule(A, [0,1], [[Sq(2), Sq(1)]])
sage: N = M.change_ring(A2); N
Finitely presented left module on 2 generators and 1 relation over
sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1]

Changing back yields the original module:

sage: N.change_ring(A) is M
True
connectivity()

The connectivity of self.

Since a finitely presented module over a connected algebra is in particular bounded below, the connectivity is an integer when the module is non-trivial, and $$+\infty$$ when the module is trivial.

EXAMPLES:

sage: A = SteenrodAlgebra(2)

sage: M = FPModule(A, [0,2,4], [[0, Sq(5), Sq(3)], [Sq(7), 0, Sq(2)*Sq(1)]])
sage: M.connectivity()
0

sage: G = FPModule(A, [0,2], [[1,0]])
sage: G.connectivity()
2
defining_homomorphism()

Return the homomorphism defining self.

self is a finitely presented module defined as the cokernel of a map $$j: F_0 o F_1$$ of free modules, and this returns that map.

EXAMPLES:

sage: E.<x,y> = ExteriorAlgebra(QQ)
sage: M = FPModule(E, [0, 1], [[x, 1]])
sage: M.defining_homomorphism()
Module morphism:
From: Free graded left module on 1 generator over The exterior algebra of rank 2 over Rational Field
To:   Free graded left module on 2 generators over The exterior algebra of rank 2 over Rational Field
Defn: g[1] |--> x*g[0] + g[1]
element_from_coordinates(coordinates, n)

Return the module element in degree n having the given coordinates with respect to the basis returned by basis_elements().

This function is inverse to sage.modules.fp_graded.element.FPElement.vector_presentation().

INPUT:

• coordinates – a vector of coordinates

• n – the degree of the element to construct

OUTPUT:

A module element of degree n having the given coordinates with respect to the basis returned by basis_elements().

EXAMPLES:

sage: A = SteenrodAlgebra(2)
sage: M = FPModule(A, [0], [[Sq(4)], [Sq(7)], [Sq(4)*Sq(9)]])

sage: M.vector_presentation(12).dimension()
3
sage: x = M.element_from_coordinates((0,1,0), 12); x
Sq(0,4)*g[0]

Applying the inverse function brings us back to the coordinate form:

sage: x.vector_presentation()
(0, 1, 0)
gen(index)

Return the module generator with the given index.

EXAMPLES:

sage: A4 = SteenrodAlgebra(2, profile=(4,3,2,1))

sage: M = FPModule(A4, [0,2,3])
sage: M.generator(0)
g[0]

sage: N = FPModule(A4, [0, 1], [[Sq(2), Sq(1)]], names='h')
sage: N.generator(1)
h[1]
generator(index)

Return the module generator with the given index.

EXAMPLES:

sage: A4 = SteenrodAlgebra(2, profile=(4,3,2,1))

sage: M = FPModule(A4, [0,2,3])
sage: M.generator(0)
g[0]

sage: N = FPModule(A4, [0, 1], [[Sq(2), Sq(1)]], names='h')
sage: N.generator(1)
h[1]
generator_degrees()

Return the degrees of the generators for self.

EXAMPLES:

sage: A4 = SteenrodAlgebra(2, profile=(4,3,2,1))
sage: N = FPModule(A4, [0, 1], [[Sq(2), Sq(1)]])

sage: N.generator_degrees()
(0, 1)
generators()

Return the generators of self.

EXAMPLES:

sage: A4 = SteenrodAlgebra(2, profile=(4,3,2,1))

sage: M = FPModule(A4, [0,0,2,3])
sage: M.generators()
(g[0, 0], g[0, 1], g[2, 0], g[3, 0])

sage: N = FPModule(A4, [0, 1], [[Sq(2), Sq(1)]], names='h')
sage: N.generators()
(h[0], h[1])

sage: Z = FPModule(A4, [])
sage: Z.generators()
()
gens()

Return the generators of self.

EXAMPLES:

sage: A4 = SteenrodAlgebra(2, profile=(4,3,2,1))

sage: M = FPModule(A4, [0,0,2,3])
sage: M.generators()
(g[0, 0], g[0, 1], g[2, 0], g[3, 0])

sage: N = FPModule(A4, [0, 1], [[Sq(2), Sq(1)]], names='h')
sage: N.generators()
(h[0], h[1])

sage: Z = FPModule(A4, [])
sage: Z.generators()
()
has_relations()

Return True if no relations are defined, and False otherwise.

Note

This module is free if this function returns False, but a free module can have (redundant) relations.

EXAMPLES:

sage: A2 = SteenrodAlgebra(2, profile=(3,2,1))

sage: F = FPModule(A2, [1,2])
sage: F.has_relations()
False

sage: M = FPModule(A2, [1,2], [[Sq(2), Sq(1)]])
sage: M.has_relations()
True

A free module constructed with a redundant generator and relation:

sage: N = FPModule(A2, [0, 0], [[0, 1]])
sage: N.has_relations()
True
sage: # Computing a minimal presentation reveals an
....: # isomorphic module with no relations.
sage: N_min = N.minimal_presentation().domain()
sage: N_min.has_relations()
False
is_trivial()

Return True if self is isomorphic to the trivial module and False otherwise.

EXAMPLES:

sage: A = SteenrodAlgebra(2)
sage: A2 = SteenrodAlgebra(2, profile=(3,2,1))

sage: M = FPModule(A2, [])
sage: M.is_trivial()
True

sage: N = FPModule(A, [1,2])
sage: N.is_trivial()
False

sage: P = FPModule(A, [1,2], [[1,0], [0,1]])
sage: P.is_trivial()
True
minimal_presentation(top_dim=None, verbose=False)

Return a minimal presentation of self.

OUTPUT:

An isomorphism $$M \to S$$, where $$M$$ has minimal presentation and $$S$$ is self.

EXAMPLES:

sage: A2 = SteenrodAlgebra(2, profile=(3,2,1))

sage: M = FPModule(A2, [0,1], [[Sq(2),Sq(1)],[0,Sq(2)],[Sq(3),0]])
sage: i = M.minimal_presentation()
sage: M_min = i.domain()

i is an isomorphism between M_min and M:

sage: i.codomain() is M
True
sage: i.is_injective()
True
sage: i.is_surjective()
True

There are more relations in M than in M_min:

sage: M.relations()
(Sq(2)*g[0] + Sq(1)*g[1], Sq(2)*g[1], Sq(3)*g[0])
sage: M_min.relations()
(Sq(2)*g[0] + Sq(1)*g[1], Sq(2)*g[1])
monomial()

Return the basis element indexed by i.

INPUT:

• i – an element of the index set

EXAMPLES:

sage: M = FPModule(SteenrodAlgebra(2), [0,1], [[Sq(4), Sq(3)]])
sage: M.monomial(0)
g[0]
sage: M.monomial(1)
g[1]
relation(index)

Return the module relation of the given index.

EXAMPLES:

sage: A4 = SteenrodAlgebra(2, profile=(4,3,2,1))
sage: N = FPModule(A4, [0, 1], [[Sq(2), Sq(1)]])
sage: N.relation(0)
Sq(2)*g[0] + Sq(1)*g[1]
relations()

Return the relations of self.

EXAMPLES:

sage: A4 = SteenrodAlgebra(2, profile=(4,3,2,1))

sage: M = FPModule(A4, [0,2,3])
sage: M.relations()
()

sage: N = FPModule(A4, [0, 1], [[Sq(2), Sq(1)]])
sage: N.relations()
(Sq(2)*g[0] + Sq(1)*g[1],)

sage: Z = FPModule(A4, [])
sage: Z.relations()
()
resolution(k, top_dim=None, verbose=False)

Return a free resolution of this module of length k.

INPUT:

• k – an non-negative integer

• top_dim – stop the computation at this degree (optional, default None, but required if the algebra is not finite-dimensional)

• verbose – (default: False) a boolean to control if log messages should be emitted

OUTPUT:

A list of homomorphisms $$[\epsilon, f_1, \ldots, f_k]$$ such that

$f_i: F_i \to F_{i-1} \text{ for } 1 < i \leq k, \qquad \epsilon: F_0 \to M,$

where each $$F_i$$ is a finitely generated free module, and the sequence

$F_k \xrightarrow{\mathit{f_k}} F_{k-1} \xrightarrow{\mathit{f_{k-1}}} \ldots \rightarrow F_0 \xrightarrow{\epsilon} M \rightarrow 0$

is exact. Note that the 0th element in this list is the map $$\epsilon$$, and the rest of the maps are between free modules.

EXAMPLES:

sage: E.<x,y> = ExteriorAlgebra(QQ)
sage: M = FPModule(E, [0], [[x], [y]])
sage: res = M.resolution(3); res
[Module morphism:
From: Free graded left module on 1 generator over The exterior algebra of rank 2 over Rational Field
To:   Finitely presented left module on 1 generator and 2 relations over The exterior algebra of rank 2 over Rational Field
Defn: g[0] |--> g[0],
Module morphism:
From: Free graded left module on 2 generators over The exterior algebra of rank 2 over Rational Field
To:   Free graded left module on 1 generator over The exterior algebra of rank 2 over Rational Field
Defn: g[1, 0] |--> x*g[0]
g[1, 1] |--> y*g[0],
Module morphism:
From: Free graded left module on 3 generators over The exterior algebra of rank 2 over Rational Field
To:   Free graded left module on 2 generators over The exterior algebra of rank 2 over Rational Field
Defn: g[2, 0] |--> x*g[1, 0]
g[2, 1] |--> y*g[1, 0] + x*g[1, 1]
g[2, 2] |--> y*g[1, 1],
Module morphism:
From: Free graded left module on 4 generators over The exterior algebra of rank 2 over Rational Field
To:   Free graded left module on 3 generators over The exterior algebra of rank 2 over Rational Field
Defn: g[3, 0] |--> x*g[2, 0]
g[3, 1] |--> y*g[2, 0] + x*g[2, 1]
g[3, 2] |--> y*g[2, 1] + x*g[2, 2]
g[3, 3] |--> y*g[2, 2]]
sage: all((res[i] * res[i+1]).is_zero() for i in range(len(res)-1))
True

sage: e = SymmetricFunctions(QQ).e()
sage: M = FPModule(e, [0], [[e[2]+e[1,1]], [e[1,1]]])
sage: res = M.resolution(3, top_dim=10)
sage: all((res[i] * res[i+1]).is_zero() for i in range(2))
True
sage: res[-1].domain().is_trivial()
True
sage: M = FPModule(e, [0,2], [[e[2]+e[1,1], 0], [e[2,1], e[1]], [0, e[1,1]]])
sage: res = M.resolution(3, top_dim=10)
sage: all((res[i] * res[i+1]).is_zero() for i in range(2))
True
sage: res[-1].domain().is_trivial()
True

sage: A2 = SteenrodAlgebra(2, profile=(3,2,1))
sage: M = FPModule(A2, [0,1], [[Sq(2), Sq(1)]])
sage: M.resolution(0)
[Module morphism:
From: Free graded left module on 2 generators over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1]
To:   Finitely presented left module on 2 generators and 1 relation over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1]
Defn: g[0] |--> g[0]
g[1] |--> g[1]]
sage: res = M.resolution(4, verbose=True)
Computing f_1 (1/4)
Computing f_2 (2/4)
Computing using the profile:
(2, 1)
Resolving the kernel in the range of dimensions [2, 8]: 2 3 4 5 6 7 8.
Computing f_3 (3/4)
Computing using the profile:
(2, 1)
Resolving the kernel in the range of dimensions [8, 14]: 8 9 10 11 12 13 14.
Computing f_4 (4/4)
Computing using the profile:
(2, 1)
Resolving the kernel in the range of dimensions [9, 16]: 9 10 11 12 13 14 15 16.
sage: len(res)
5
sage: res
[Module morphism:
From: Free graded left module on 2 generators over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1]
To:   Finitely presented left module on 2 generators and 1 relation over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1]
Defn: g[0] |--> g[0]
g[1] |--> g[1],
Module morphism:
From: Free graded left module on 1 generator over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1]
To:   Free graded left module on 2 generators over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1]
Defn: g[2] |--> Sq(2)*g[0] + Sq(1)*g[1],
Module morphism:
From: Free graded left module on 1 generator over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1]
To:   Free graded left module on 1 generator over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1]
Defn: g[8] |--> Sq(3,1)*g[2],
Module morphism:
From: Free graded left module on 2 generators over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1]
To:   Free graded left module on 1 generator over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1]
Defn: g[9] |--> Sq(1)*g[8]
g[10] |--> Sq(2)*g[8],
Module morphism:
From: Free graded left module on 2 generators over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1]
To:   Free graded left module on 2 generators over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1]
Defn: g[10] |--> Sq(1)*g[9]
g[12] |--> Sq(0,1)*g[9] + Sq(2)*g[10]]
sage: for i in range(len(res)-1):
....:     assert (res[i] * res[i+1]).is_zero(), 'the result is not a complex'

We construct $$\GF{3}$$ as a $$\ZZ$$-module (with trivial grading concentrated in degree 0) and compute its resolution:

sage: E = ExteriorAlgebra(ZZ, 0)
sage: M = FPModule(E, [0], [[3]])
sage: res = M.resolution(3)
sage: res
[Module morphism:
From: Free graded left module on 1 generator over The exterior algebra of rank 0 over Integer Ring
To:   Finitely presented left module on 1 generator and 1 relation over The exterior algebra of rank 0 over Integer Ring
Defn: g[0] |--> g[0],
Module endomorphism of Free graded left module on 1 generator over The exterior algebra of rank 0 over Integer Ring
Defn: g[0] |--> 3*g[0],
Module morphism:
From: Free graded left module on 0 generators over The exterior algebra of rank 0 over Integer Ring
To:   Free graded left module on 1 generator over The exterior algebra of rank 0 over Integer Ring,
Module endomorphism of Free graded left module on 0 generators over The exterior algebra of rank 0 over Integer Ring]
submodule_inclusion(spanning_elements)

Return the inclusion morphism of the submodule of self spanned by the given elements.

INPUT:

• spanning_elements – an iterable of elements

OUTPUT:

The inclusion of the submodule into this module.

Because a submodule of a finitely presented module need not be finitely presented, this method will only work if the underlying algebra is finite-dimensional. Indeed, the current implementation only works if the algebra has a top_class method, which gets used in sage.modules.fp_graded.morphism._resolve_kernel().

EXAMPLES:

sage: A2 = SteenrodAlgebra(2, profile=(3,2,1))

sage: M = FPModule(A2, [0,1], [[Sq(2),Sq(1)]])
sage: i = M.submodule_inclusion([M.generator(0)])
sage: i.codomain() is M
True
sage: i.is_injective()
True
sage: i.domain().generator_degrees()
(0,)
sage: i.domain().relations()
(Sq(3)*g[0],)
suspension(t)

Return the suspension of self by degree t.

INPUT:

• t – an integer degree by which the module is suspended

OUTPUT:

A module which is identical to this module by a shift of degrees by the integer t.

EXAMPLES:

sage: A = SteenrodAlgebra(2)
sage: A2 = SteenrodAlgebra(2, profile=(3,2,1))

sage: Y = FPModule(A2, [0], [[Sq(1)]])
sage: X = Y.suspension(4)
sage: X.generator_degrees()
(4,)
sage: X.relations()
(Sq(1)*g[4],)

sage: M = FPModule(A, [2,3], [[Sq(2), Sq(1)], [0, Sq(2)]])
sage: Q = M.suspension(1)
sage: Q.generator_degrees()
(3, 4)
sage: Q.relations()
(Sq(2)*g[3] + Sq(1)*g[4], Sq(2)*g[4])
sage: Q = M.suspension(-3)
sage: Q.generator_degrees()
(-1, 0)
sage: Q = M.suspension(0)
sage: Q.generator_degrees()
(2, 3)
vector_presentation(n, verbose=False)

Return a free module isomorphic to the free module of module elements of degree n.

INPUT:

• n – the degree of the presentation

OUTPUT:

A vector space.

EXAMPLES:

sage: A = SteenrodAlgebra(2)
sage: M = FPModule(A, [0,2,4], [[Sq(4),Sq(2),0]])

sage: V = M.vector_presentation(4)
sage: V.dimension()
3

sage: len(M.basis_elements(4))
3
zero()

Return the zero element.

EXAMPLES: