Finitely generated free graded left modules over connected graded algebras#

Let \(A\) be a connected graded algebra. Some methods here require in addition that \(A\) be an algebra over a field or a PID and that Sage has a description of a basis for \(A\).

For example, let \(p\) be a prime number. The mod \(p\) Steenrod algebra \(A_p\) is a connected algebra over the finite field of \(p\) elements. Many of the modules presented here will be defined over \(A_p\), or one of its sub-Hopf algebras. E.g.:

sage: A = SteenrodAlgebra(p=2)

However, the current implementation can use any connected graded algebra that has a graded basis where each graded part is finite dimensional. Another good family is the exterior algebras:

sage: E.<x,y,z> = ExteriorAlgebra(QQ)

A free module is defined by the graded algebra and an ordered tuple of degrees for the generators:

sage: M = A.free_graded_module(generator_degrees=(0,1))
sage: M
Free graded left module on 2 generators over
 mod 2 Steenrod algebra, milnor basis

sage: F.<a,b,c> = E.free_graded_module((0,3,6))
sage: F
Free graded left module on 3 generators over
 The exterior algebra of rank 3 over Rational Field

The resulting free modules will have generators in the degrees as specified:

sage: M.generator_degrees()
(0, 1)
sage: F.generator_degrees()
(0, 3, 6)

The default names for the generators are g[degree] if they are in distinct degrees, g[degree, i] otherwise. They can be given other names, as was done when creating the module F:

sage: M.generators()
(g[0], g[1])
sage: F.generators()
(a, b, c)

The connectivity of a module over a connected graded algebra is the minimum degree of all its module generators. Thus, if the module is non-trivial, the connectivity is an integer:

sage: M.connectivity()
0

Module elements#

For an \(A\)-module with generators \(\{g_i\}_{i=1}^N\), any homogeneous element of degree \(n\) has the form

\[x = \sum_{i=1}^N a_i\cdot g_i\,,\]

where \(a_i\in A_{n-\deg(g_i)}\) for all \(i\). The ordered set \(\{a_i\}\) is referred to as the coefficients of \(x\).

You can produce module elements from a given set of coefficients:

sage: coeffs = [Sq(5), Sq(1,1)]
sage: x = M(coeffs); x
Sq(5)*g[0] + Sq(1,1)*g[1]

You can also use the module action:

sage: Sq(2) * x
(Sq(4,1)+Sq(7))*g[0] + Sq(3,1)*g[1]

Each non-zero element has a well-defined degree:

sage: x.degree()
5

However the zero element does not:

sage: zero = M.zero(); zero
0
sage: zero.degree()
Traceback (most recent call last):
...
ValueError: the zero element does not have a well-defined degree

Any two elements can be added as long as they are in the same degree:

sage: y = M.an_element(5); y
Sq(2,1)*g[0] + Sq(4)*g[1]
sage: x + y
(Sq(2,1)+Sq(5))*g[0] + (Sq(1,1)+Sq(4))*g[1]

or when at least one of them is zero:

sage: x + zero == x
True

Finally, additive inverses exist:

sage: x - x
0

For every integer \(n\), the set of module elements of degree \(n\) form a free module over the ground ring \(k\). A basis for this free module can be computed:

sage: M.basis_elements(5)
(Sq(2,1)*g[0], Sq(5)*g[0], Sq(1,1)*g[1], Sq(4)*g[1])

together with a corresponding free module presentation:

sage: M.vector_presentation(5)
Vector space of dimension 4 over Finite Field of size 2

Given any element, its coordinates with respect to this basis can be computed:

sage: v = x.vector_presentation(); v
(0, 1, 1, 0)

Going the other way, any element can be constructed by specifying its coordinates:

sage: x_ = M.element_from_coordinates((0,1,1,0), 5)
sage: x_
Sq(5)*g[0] + Sq(1,1)*g[1]
sage: x_ == x
True

Module homomorphisms#

Homomorphisms of free graded \(A\)-modules \(M\to N\) are linear maps of their underlying free \(k\)-module which commute with the \(A\)-module structure.

To create a homomorphism, first create the object modeling the set of all such homomorphisms using the free function Hom:

sage: M = A.free_graded_module((0,1))
sage: N.<c2> = A.free_graded_module((2,))
sage: homspace = Hom(M, N); homspace
Set of Morphisms from Free graded left module on 2 generators
  over mod 2 Steenrod algebra, milnor basis
 to Free graded left module on 1 generator
  over mod 2 Steenrod algebra, milnor basis
 in Category of finite dimensional graded modules with basis
  over mod 2 Steenrod algebra, milnor basis

Just as module elements, homomorphisms are created using the homspace object. The only argument is a list of module elements in the codomain, corresponding to the module generators of the domain:

sage: values = [Sq(2)*c2, Sq(2)*Sq(1)*c2]
sage: f = homspace(values)

The resulting homomorphism is the one sending the \(i\)-th generator of the domain to the \(i\)-th codomain value given:

sage: f
Module morphism:
  From: Free graded left module on 2 generators over mod 2 Steenrod algebra, milnor basis
  To:   Free graded left module on 1 generator over mod 2 Steenrod algebra, milnor basis
  Defn: g[0] |--> Sq(2)*c2
        g[1] |--> (Sq(0,1)+Sq(3))*c2

Convenience methods exist for creating the trivial morphism:

sage: homspace.zero()
Module morphism:
  From: Free graded left module on 2 generators over mod 2 Steenrod algebra, milnor basis
  To:   Free graded left module on 1 generator over mod 2 Steenrod algebra, milnor basis
  Defn: g[0] |--> 0
        g[1] |--> 0

as well as the identity endomorphism:

sage: Hom(M, M).identity()
Module endomorphism of Free graded left module on 2 generators over mod 2 Steenrod algebra, milnor basis
  Defn: g[0] |--> g[0]
        g[1] |--> g[1]

Homomorphisms can be evaluated on elements of the domain module:

sage: v1 = f(Sq(7)*M.generator(0)); v1
Sq(3,2)*c2

sage: v2 = f(Sq(17)*M.generator(1)); v2
(Sq(11,3)+Sq(13,0,1)+Sq(17,1))*c2

and they respect the module action:

sage: v1 == Sq(7)*f(M.generator(0))
True

sage: v2 == Sq(17)*f(M.generator(1))
True

Any non-trivial homomorphism has a well-defined degree:

sage: f.degree()
4

but just as module elements, the trivial homomorphism does not:

sage: zero_map = homspace.zero()
sage: zero_map.degree()
Traceback (most recent call last):
...
ValueError: the zero morphism does not have a well-defined degree

Any two homomorphisms can be added as long as they are of the same degree:

sage: f2 = homspace([Sq(2)*c2, Sq(3)*c2])
sage: f + f2
Module morphism:
  From: Free graded left module on 2 generators over mod 2 Steenrod algebra, milnor basis
  To:   Free graded left module on 1 generator over mod 2 Steenrod algebra, milnor basis
  Defn: g[0] |--> 0
        g[1] |--> Sq(0,1)*c2

or when at least one of them is zero:

sage: f + zero_map == f
True

Finally, additive inverses exist:

sage: f - f == 0
True

The restriction of a homomorphism to the free module of \(n\)-dimensional module elements is a linear transformation:

sage: f_4 = f.vector_presentation(4); f_4
Vector space morphism represented by the matrix:
[0 1 0]
[1 1 1]
[0 1 0]
[0 0 0]
Domain: Vector space of dimension 4 over Finite Field of size 2
Codomain: Vector space of dimension 3 over Finite Field of size 2

This is compatible with the vector presentations of its domain and codomain modules:

sage: f.domain() is M
True
sage: f.codomain() is N
True
sage: f_4.domain() is M.vector_presentation(4)
True
sage: f_4.codomain() is N.vector_presentation(4 + f.degree())
True

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.

class sage.modules.fp_graded.free_module.FreeGradedModule(algebra, generator_degrees, category, names=None, **kwds)#

Bases: CombinatorialFreeModule

Create a finitely generated free graded module over a connected graded algebra, with generators in specified degrees.

INPUT:

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

  • generator_degrees – tuple of integers defining the number of generators of the module, and their degrees

  • names – optional, the names of the generators. If names is a comma-separated string like 'a, b, c', then those will be the names. Otherwise, for example if names is abc, then the names will be abc(d,i).

By default, if all generators are in distinct degrees, then the names of the generators will have the form g_{d} where d is the degree of the generator. If the degrees are not distinct, then the generators will be called g_{d,i} where d is the degree and i is its index in the list of generators in that degree.

EXAMPLES:

sage: from sage.modules.fp_graded.free_module import FreeGradedModule
sage: E.<x,y,z> = ExteriorAlgebra(QQ)
sage: M = FreeGradedModule(E, (-1,3))
sage: M
Free graded left module on 2 generators over
 The exterior algebra of rank 3 over Rational Field
sage: M.generator_degrees()
(-1, 3)
sage: a, b = M.generators()
sage: (x*y*b).degree()
5

names of generators:

sage: M.generators()
(g[-1], g[3])
sage: FreeGradedModule(E, (0, 0, 2)).generators()
(g[0, 0], g[0, 1], g[2, 0])
sage: FreeGradedModule(E, (0, 0, 2), names='x, y, z').generators()
(x, y, z)
sage: FreeGradedModule(E, (0, 0, 2), names='xyz').generators()
(xyz[0, 0], xyz[0, 1], xyz[2, 0])

names can also be defined implicitly using Sage’s M.<...> syntax:

sage: A = SteenrodAlgebra(2)
sage: M.<x,y,z> = FreeGradedModule(A, (-2,2,4))
sage: M
Free graded left module on 3 generators over
 mod 2 Steenrod algebra, milnor basis
sage: M.gens()
(x, y, z)
Element#

alias of FreeGradedModuleElement

an_element(n=None)#

Return an element of self.

This function chooses deterministically an element of the module in the given degree.

INPUT:

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

OUTPUT:

An element (of the given degree if specified).

EXAMPLES:

sage: from sage.modules.fp_graded.free_module import FreeGradedModule
sage: A = SteenrodAlgebra(2)
sage: M = FreeGradedModule(A, (0,2,4))
sage: M.an_element(172)
Sq(0,0,2,0,1,0,1)*g[0] + Sq(0,4,0,0,1,0,1)*g[2] + Sq(7,1,0,0,1,0,1)*g[4]

Zero is the only element in the trivial module:

sage: FreeGradedModule(A, ()).an_element()
0
basis_elements(n)#

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\), not a basis as a free module over \(A\).

INPUT:

  • n – an integer

OUTPUT:

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

EXAMPLES:

sage: A = SteenrodAlgebra(2)
sage: M.<m0, m2, m4> = A.free_graded_module((0,2,4))
sage: M.basis_elements(8)
(Sq(1,0,1)*m0,
 Sq(2,2)*m0,
 Sq(5,1)*m0,
 Sq(8)*m0,
 Sq(0,2)*m2,
 Sq(3,1)*m2,
 Sq(6)*m2,
 Sq(1,1)*m4,
 Sq(4)*m4)
change_ring(algebra)#

Change the base ring of self.

INPUT:

  • algebra – a connected graded algebra

OUTPUT:

The free graded module over algebra defined with the same number of generators of the same degrees as self.

EXAMPLES:

sage: from sage.modules.fp_graded.free_module import FreeGradedModule
sage: A = SteenrodAlgebra(2)
sage: A2 = SteenrodAlgebra(2, profile=(3,2,1))

sage: M = FreeGradedModule(A, [0,1])
sage: N = M.change_ring(A2); N
Free graded left module on 2 generators 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.

OUTPUT:

An integer equal to the minimal degree of all the generators, if this module is non-trivial. Otherwise, \(+\infty\).

EXAMPLES:

sage: from sage.modules.fp_graded.free_module import FreeGradedModule
sage: A = SteenrodAlgebra(2)
sage: M = FreeGradedModule(A, (-2,2,4))
sage: M.connectivity()
-2
element_from_coordinates(coordinates, n)#

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

INPUT:

  • coordinates – a sequence of elements of the ground ring

  • n – an integer

OUTPUT:

A module element of degree n.

EXAMPLES:

sage: A = SteenrodAlgebra(2)
sage: M = A.free_graded_module((0,1))
sage: x = M.element_from_coordinates((0,1,0,1), 5); x
Sq(5)*g[0] + Sq(4)*g[1]
sage: basis = M.basis_elements(5)
sage: y = 0*basis[0] + 1*basis[1] + 0*basis[2] + 1*basis[3]
sage: x == y
True

sage: M.element_from_coordinates((0,0,0,0), 5)
0
gen(index)#

Return the module generator with the given index.

EXAMPLES:

sage: from sage.modules.fp_graded.free_module import FreeGradedModule
sage: A = SteenrodAlgebra(2)
sage: M = FreeGradedModule(A, (0,2,4))
sage: M.generator(0)
g[0]
sage: M.generator(1)
g[2]
sage: M.generator(2)
g[4]
generator(index)#

Return the module generator with the given index.

EXAMPLES:

sage: from sage.modules.fp_graded.free_module import FreeGradedModule
sage: A = SteenrodAlgebra(2)
sage: M = FreeGradedModule(A, (0,2,4))
sage: M.generator(0)
g[0]
sage: M.generator(1)
g[2]
sage: M.generator(2)
g[4]
generator_degrees()#

The degrees of the module generators.

OUTPUT:

A tuple containing the degrees of the generators for this module, in the order that the generators were given when self was constructed.

EXAMPLES:

sage: from sage.modules.fp_graded.free_module import FreeGradedModule
sage: A = SteenrodAlgebra(2)
sage: M = FreeGradedModule(A, (-2,2,4))
sage: M.generator_degrees()
(-2, 2, 4)
generators()#

Return all the module generators.

EXAMPLES:

sage: from sage.modules.fp_graded.free_module import FreeGradedModule
sage: A = SteenrodAlgebra(2)
sage: M = FreeGradedModule(A, (-2,1))
sage: M.generators()
(g[-2], g[1])
has_relations()#

Return False as this has no relations.

This is for compatibility with FPModule.

EXAMPLES:

sage: from sage.modules.fp_graded.free_module import FreeGradedModule
sage: A = SteenrodAlgebra(2)
sage: F = FreeGradedModule(A, (-2,2,4))
sage: F.has_relations()
False
is_trivial()#

Return True if this module is trivial and False otherwise.

EXAMPLES:

sage: from sage.modules.fp_graded.free_module import FreeGradedModule
sage: A = SteenrodAlgebra(2)
sage: FreeGradedModule(A, (-2,2,4)).is_trivial()
False
sage: FreeGradedModule(A, ()).is_trivial()
True
minimal_presentation(top_dim=None, verbose=False)#

Return a minimal presentation of self.

OUTPUT:

The identity morphism as self is free.

EXAMPLES:

sage: from sage.modules.fp_graded.module import FPModule
sage: A2 = SteenrodAlgebra(2)

sage: M = A2.free_graded_module([0,1])
sage: M.minimal_presentation().is_identity()
True
relations()#

Return the relations of self, which is ().

This is for compatibility with FPModule.

EXAMPLES:

sage: from sage.modules.fp_graded.free_module import FreeGradedModule
sage: A = SteenrodAlgebra(2)
sage: F = FreeGradedModule(A, (-2,2,4))
sage: F.relations()
()
resolution(k, top_dim=None, verbose=False)#

Return a free resolution of self of length k.

Since self is free, the initial map in the resolution will be the identity, and the rest of the maps will be zero.

INPUT:

OUTPUT:

A list of homomorphisms \([1_M, 0, 0, \ldots, 0]\) consisting of the identity map on this module followed by zero maps. Other than this module, the other modules in the resolution will be zero.

EXAMPLES:

sage: E.<x,y,z> = ExteriorAlgebra(QQ)
sage: M = E.free_graded_module((1,2))
sage: M.resolution(0)
[Module endomorphism of Free graded left module on 2 generators over The exterior algebra of rank 3 over Rational Field
   Defn: g[1] |--> g[1]
         g[2] |--> g[2]]
sage: M.resolution(1)
[Module endomorphism of Free graded left module on 2 generators over The exterior algebra of rank 3 over Rational Field
   Defn: g[1] |--> g[1]
         g[2] |--> g[2],
 Module morphism:
   From: Free graded left module on 0 generators over The exterior algebra of rank 3 over Rational Field
   To:   Free graded left module on 2 generators over The exterior algebra of rank 3 over Rational Field]
sage: M.resolution(4)
[Module endomorphism of Free graded left module on 2 generators over The exterior algebra of rank 3 over Rational Field
   Defn: g[1] |--> g[1]
         g[2] |--> g[2],
 Module morphism:
   From: Free graded left module on 0 generators over The exterior algebra of rank 3 over Rational Field
   To:   Free graded left module on 2 generators over The exterior algebra of rank 3 over Rational Field,
 Module endomorphism of Free graded left module on 0 generators over The exterior algebra of rank 3 over Rational Field,
 Module endomorphism of Free graded left module on 0 generators over The exterior algebra of rank 3 over Rational Field,
 Module endomorphism of Free graded left module on 0 generators over The exterior algebra of rank 3 over Rational Field]
suspension(t)#

Suspend self by the given degree t.

INPUT:

  • t – an integer

OUTPUT:

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

EXAMPLES:

sage: from sage.modules.fp_graded.free_module import FreeGradedModule
sage: A = SteenrodAlgebra(2)
sage: M = FreeGradedModule(A, (0,2,4))
sage: M.suspension(4).generator_degrees()
(4, 6, 8)
sage: M.suspension(-4).generator_degrees()
(-4, -2, 0)
vector_presentation(n)#

Return a free module over the ground ring of the module algebra isomorphic to the degree n elements of self.

Let \(\mathcal{k}\) be the ground ring of the algebra over this module is defined, and let \(M_n\) be the free module of module elements of degree n.

The return value of this function is the free module \(\mathcal{k}^{r}\) where \(r = dim(M_n)\).

The isomorphism between \(k^{r}\) and \(M_n\) is given by the bijection taking the standard basis element \(e_i\) to the \(i\)-th element of the array returned by basis_elements().

INPUT:

  • n – an integer degree

OUTPUT:

A free module over the ground ring of the algebra over which self is defined, isomorphic to the free module of module elements of degree n.

EXAMPLES:

sage: A1 = SteenrodAlgebra(2, profile=[2,1])
sage: M.<x> = A1.free_graded_module((0,))
sage: M.vector_presentation(3)
Vector space of dimension 2 over Finite Field of size 2
sage: M.basis_elements(3)
(Sq(0,1)*x, Sq(3)*x)
sage: [M.vector_presentation(i).dimension() for i in range(-2, 9)]
[0, 0, 1, 1, 1, 2, 1, 1, 1, 0, 0]