Homomorphisms of finitely presented modules over the Steenrod algebra¶
This class implements construction and basic manipulation of homomorphisms
between finitely presented graded modules
over the mod \(p\) Steenrod algebra.
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.steenrod.morphism.SteenrodFPModuleMorphism(parent, values, check=True)[source]¶
Bases:
FPModuleMorphism
- cokernel_projection(verbose=False)[source]¶
Compute the map to the cokernel of
self
.INPUT:
verbose
– boolean (default:False
); whether log messages are printed
OUTPUT:
The natural projection from the codomain of this homomorphism to its cokernel.
EXAMPLES:
sage: from sage.modules.fp_graded.steenrod.module import SteenrodFPModule sage: A1 = SteenrodAlgebra(2, profile=(2,1)) sage: M = SteenrodFPModule(A1, [0], [[Sq(2)]]) sage: F = SteenrodFPModule(A1, [0]) sage: r = Hom(F, M)([A1.Sq(1)*M.generator(0)]) sage: co = r.cokernel_projection(); co Module morphism: From: Finitely presented left module on 1 generator and 1 relation over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [2, 1] To: Finitely presented left module on 1 generator and 2 relations over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [2, 1] Defn: g[0] |--> g[0] sage: co.domain().is_trivial() False
>>> from sage.all import * >>> from sage.modules.fp_graded.steenrod.module import SteenrodFPModule >>> A1 = SteenrodAlgebra(Integer(2), profile=(Integer(2),Integer(1))) >>> M = SteenrodFPModule(A1, [Integer(0)], [[Sq(Integer(2))]]) >>> F = SteenrodFPModule(A1, [Integer(0)]) >>> r = Hom(F, M)([A1.Sq(Integer(1))*M.generator(Integer(0))]) >>> co = r.cokernel_projection(); co Module morphism: From: Finitely presented left module on 1 generator and 1 relation over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [2, 1] To: Finitely presented left module on 1 generator and 2 relations over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [2, 1] Defn: g[0] |--> g[0] >>> co.domain().is_trivial() False
- image(top_dim=None, verbose=False)[source]¶
Return the image of
self
.INPUT:
top_dim
– integer (optional); used by this function to stop the computation at the given degreeverbose
– boolean (default:False
); whether log messages are printed
OUTPUT:
An injective homomorphism into the codomain of
self
which is onto the image ofself
.EXAMPLES:
sage: from sage.modules.fp_graded.steenrod.module import SteenrodFPModule sage: A = SteenrodAlgebra(2) sage: M = SteenrodFPModule(A, [0,1], [[Sq(2),Sq(1)], [0,Sq(2)]]) sage: S = SteenrodFPModule(A, [0], [[Sq(2)]]) sage: f = Hom(S, M)([M([0,1])]) sage: f.is_injective() True sage: i = f.image(); i Module morphism: From: Finitely presented left module on 1 generator and 1 relation over mod 2 Steenrod algebra, milnor basis To: Finitely presented left module on 2 generators and 2 relations over mod 2 Steenrod algebra, milnor basis Defn: g[1] |--> g[1] sage: i.codomain() is M True
>>> from sage.all import * >>> from sage.modules.fp_graded.steenrod.module import SteenrodFPModule >>> A = SteenrodAlgebra(Integer(2)) >>> M = SteenrodFPModule(A, [Integer(0),Integer(1)], [[Sq(Integer(2)),Sq(Integer(1))], [Integer(0),Sq(Integer(2))]]) >>> S = SteenrodFPModule(A, [Integer(0)], [[Sq(Integer(2))]]) >>> f = Hom(S, M)([M([Integer(0),Integer(1)])]) >>> f.is_injective() True >>> i = f.image(); i Module morphism: From: Finitely presented left module on 1 generator and 1 relation over mod 2 Steenrod algebra, milnor basis To: Finitely presented left module on 2 generators and 2 relations over mod 2 Steenrod algebra, milnor basis Defn: g[1] |--> g[1] >>> i.codomain() is M True
Lift the map
f
over the inclusioni
:sage: f_ = f.lift(i) sage: f_.is_injective() True sage: f_.is_surjective() True sage: g = Hom(S, M)([M([Sq(3),Sq(2)])]) sage: j = g.image(); j Module morphism: From: Free graded left module on 0 generators over mod 2 Steenrod algebra, milnor basis To: Finitely presented left module on 2 generators and 2 relations over mod 2 Steenrod algebra, milnor basis
>>> from sage.all import * >>> f_ = f.lift(i) >>> f_.is_injective() True >>> f_.is_surjective() True >>> g = Hom(S, M)([M([Sq(Integer(3)),Sq(Integer(2))])]) >>> j = g.image(); j Module morphism: From: Free graded left module on 0 generators over mod 2 Steenrod algebra, milnor basis To: Finitely presented left module on 2 generators and 2 relations over mod 2 Steenrod algebra, milnor basis
So
g
had to be trivial:sage: g.is_zero() True
>>> from sage.all import * >>> g.is_zero() True
- is_injective(top_dim=None, verbose=False)[source]¶
Return
True
ifself
is injective.INPUT:
top_dim
– (optional) stop the computation at this degree; if not specified, this is determined usingprofile()
verbose
– boolean (default:False
); whether log messages are printed
EXAMPLES:
sage: from sage.modules.fp_graded.steenrod.module import SteenrodFPModule sage: A = SteenrodAlgebra(2) sage: M = SteenrodFPModule(A, [0,1], [[Sq(2),Sq(1)], [0,Sq(2)]]) sage: S = SteenrodFPModule(A, [0], [[Sq(2)]]) sage: f = Hom(S, M)([M([0,1])]) sage: f.is_injective() True sage: g = Hom(S, M).zero() sage: g.is_injective() False sage: z = Hom(SteenrodFPModule(A, []), M).zero() sage: z.is_injective() True sage: z.is_zero() True
>>> from sage.all import * >>> from sage.modules.fp_graded.steenrod.module import SteenrodFPModule >>> A = SteenrodAlgebra(Integer(2)) >>> M = SteenrodFPModule(A, [Integer(0),Integer(1)], [[Sq(Integer(2)),Sq(Integer(1))], [Integer(0),Sq(Integer(2))]]) >>> S = SteenrodFPModule(A, [Integer(0)], [[Sq(Integer(2))]]) >>> f = Hom(S, M)([M([Integer(0),Integer(1)])]) >>> f.is_injective() True >>> g = Hom(S, M).zero() >>> g.is_injective() False >>> z = Hom(SteenrodFPModule(A, []), M).zero() >>> z.is_injective() True >>> z.is_zero() True
- kernel_inclusion(top_dim=None, verbose=False)[source]¶
Return the kernel of
self
as a morphism.INPUT:
top_dim
– (optional) stop the computation at this degree; if not specified, this is determined usingprofile()
verbose
– boolean (default:False
); whether log messages are printed
OUTPUT: an injective homomorphism into the domain
self
which is onto the kernel of this homomorphism.EXAMPLES:
sage: from sage.modules.fp_graded.steenrod.module import SteenrodFPModule sage: A = SteenrodAlgebra(2) sage: M = SteenrodFPModule(A, [0,1], [[Sq(2),Sq(1)], [0,Sq(2)]]) sage: S = SteenrodFPModule(A, [0], [[Sq(2)]]) sage: f = Hom(S, M)([M([0,1])]) sage: f.is_injective() True sage: k = f.kernel_inclusion() sage: k == 0 True
>>> from sage.all import * >>> from sage.modules.fp_graded.steenrod.module import SteenrodFPModule >>> A = SteenrodAlgebra(Integer(2)) >>> M = SteenrodFPModule(A, [Integer(0),Integer(1)], [[Sq(Integer(2)),Sq(Integer(1))], [Integer(0),Sq(Integer(2))]]) >>> S = SteenrodFPModule(A, [Integer(0)], [[Sq(Integer(2))]]) >>> f = Hom(S, M)([M([Integer(0),Integer(1)])]) >>> f.is_injective() True >>> k = f.kernel_inclusion() >>> k == Integer(0) True
Since k is both trivial and injective, its domain should be the zero module:
sage: k.domain().is_trivial() True sage: g = Hom(S, M)([M([Sq(3),Sq(2)])]) sage: h = g.kernel_inclusion() sage: h.is_identity() True sage: ker = h.domain(); sage: ker is S True
>>> from sage.all import * >>> k.domain().is_trivial() True >>> g = Hom(S, M)([M([Sq(Integer(3)),Sq(Integer(2))])]) >>> h = g.kernel_inclusion() >>> h.is_identity() True >>> ker = h.domain(); >>> ker is S True
So \(g\) had to be trivial:
sage: g.is_zero() True
>>> from sage.all import * >>> g.is_zero() True
- profile()[source]¶
Return a finite profile over which
self
can be defined.This is in some ways the key method for these morphisms. As discussed in the “Theoretical background” section of
sage.modules.fp_graded.steenrod.module
, any homomorphism of finitely presented modules over the Steenrod algebra can be defined over a finite-dimensional sub-Hopf algebra, and this method identifies such a sub-Hopf algebra and returns its profile function.EXAMPLES:
sage: from sage.modules.fp_graded.steenrod.module import SteenrodFPModule sage: A = SteenrodAlgebra(2) sage: M = SteenrodFPModule(A, [0,1], [[Sq(2),Sq(1)], [0,Sq(2)]]) sage: one = Hom(M,M).identity() sage: one.profile() (2, 1) sage: zero = Hom(M,M).zero() sage: zero.profile() (2, 1) sage: A_fin = SteenrodAlgebra(2, profile=(2,1)) sage: M_fin = M.change_ring(A_fin)
>>> from sage.all import * >>> from sage.modules.fp_graded.steenrod.module import SteenrodFPModule >>> A = SteenrodAlgebra(Integer(2)) >>> M = SteenrodFPModule(A, [Integer(0),Integer(1)], [[Sq(Integer(2)),Sq(Integer(1))], [Integer(0),Sq(Integer(2))]]) >>> one = Hom(M,M).identity() >>> one.profile() (2, 1) >>> zero = Hom(M,M).zero() >>> zero.profile() (2, 1) >>> A_fin = SteenrodAlgebra(Integer(2), profile=(Integer(2),Integer(1))) >>> M_fin = M.change_ring(A_fin)
Change the ring of the module
M
:sage: M_fin.change_ring(A) is M True
>>> from sage.all import * >>> M_fin.change_ring(A) is M True
We can change rings to the finite sub-Hopf algebra defined by the profile we just computed:
sage: one_fin = one.change_ring(A_fin) sage: one_fin.domain() Finitely presented left module on 2 generators and 2 relations over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [2, 1]
>>> from sage.all import * >>> one_fin = one.change_ring(A_fin) >>> one_fin.domain() Finitely presented left module on 2 generators and 2 relations over sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [2, 1]
If we change back to the full Steenrod algebra, we are back where we started:
sage: one_fin.change_ring(A) == one True
>>> from sage.all import * >>> one_fin.change_ring(A) == one True