Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
trac 32505: allow the resolution to be made up of maps between
Browse files Browse the repository at this point in the history
instances of free modules rather than finitely presented ones.
  • Loading branch information
jhpalmieri committed Jan 30, 2022
1 parent 5e02153 commit 11b3725
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 17 deletions.
45 changes: 41 additions & 4 deletions src/sage/modules/fp_graded/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -1107,7 +1107,7 @@ def submodule_inclusion(self, spanning_elements):
return Hom(F, self)(spanning_elements).image()


def resolution(self, k, top_dim=None, verbose=False):
def resolution(self, k, top_dim=None, verbose=False, as_free=False):
r"""
A resolution of this module of length ``k``.
Expand All @@ -1116,6 +1116,9 @@ def resolution(self, k, top_dim=None, verbose=False):
- ``k`` -- an non-negative integer
- ``verbose`` -- (default: ``False``) a boolean to control if
log messages should be emitted
- ``as_free`` -- (default: ``False``) if ``True``, return as
many morphisms as possible (all but the 0th one) as
morphisms between free modules
OUTPUT:
Expand All @@ -1141,6 +1144,33 @@ def resolution(self, k, top_dim=None, verbose=False):
EXAMPLES::
sage: from sage.modules.fp_graded.module import FPModule
sage: E.<x,y> = ExteriorAlgebra(QQ)
sage: triv = FPModule(E, [0], [[x], [y]]) # trivial module
sage: triv.res(3)
[Module morphism:
From: Finitely presented left module on 1 generator and 0 relations 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: Finitely presented left module on 2 generators and 0 relations over The exterior algebra of rank 2 over Rational Field
To: Finitely presented left module on 1 generator and 0 relations 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: Finitely presented left module on 3 generators and 0 relations over The exterior algebra of rank 2 over Rational Field
To: Finitely presented left module on 2 generators and 0 relations 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: Finitely presented left module on 4 generators and 0 relations over The exterior algebra of rank 2 over Rational Field
To: Finitely presented left module on 3 generators and 0 relations 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: A2 = SteenrodAlgebra(2, profile=(3,2,1))
sage: M = FPModule(A2, [0,1], [[Sq(2), Sq(1)]])
sage: M.resolution(0)
Expand Down Expand Up @@ -1188,6 +1218,12 @@ def resolution(self, k, top_dim=None, verbose=False):
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'
sage: res2 = M.resolution(2, as_free=True)
sage: [type(f) for f in res]
[<class 'sage.modules.fp_graded.homspace.FPModuleHomspace_with_category_with_equality_by_id.element_class'>,
<class 'sage.modules.fp_graded.free_homspace.FreeGradedModuleHomspace_with_category_with_equality_by_id.element_class'>]
<class 'sage.modules.fp_graded.free_homspace.FreeGradedModuleHomspace_with_category_with_equality_by_id.element_class'>]
"""
def _print_progress(i, k):
if verbose:
Expand All @@ -1213,8 +1249,6 @@ def _print_progress(i, k):

ret_complex.append(pres)

from .morphism import FPModuleMorphism

# f_i: F_i -> F_i-1, for i > 1
for i in range(2, k+1):
_print_progress(i, k)
Expand All @@ -1223,5 +1257,8 @@ def _print_progress(i, k):
ret_complex.append(f._resolve_kernel(top_dim=top_dim,
verbose=verbose))

return ret_complex
if as_free:
return ret_complex[0:1] + [f._lift_to_free_morphism() for f in ret_complex[1:]]
else:
return ret_complex

83 changes: 70 additions & 13 deletions src/sage/modules/fp_graded/morphism.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@

from sage.categories.homset import End, Hom
from sage.categories.morphism import Morphism
from sage.misc.cachefunc import cached_method
from sage.misc.cachefunc import cached_method, cached_function
from sage.rings.infinity import PlusInfinity


def _create_relations_matrix(module, relations, source_degs, target_degs):
r"""
The action by the given relations can be written as multiplication by
Expand Down Expand Up @@ -169,7 +168,7 @@ class FPModuleMorphism(Morphism):
sage: w = Hom(Q, F)( (F((1, 0)), F((0, 1))) )
Traceback (most recent call last):
...
...
ValueError: relation Sq(6)*g[2] + Sq(5)*g[3] is not sent to zero
"""
def __init__(self, parent, values):
Expand Down Expand Up @@ -1487,10 +1486,9 @@ def _resolve_kernel(self, top_dim=None, verbose=False):
.. NOTE::
If the algebra for this module is finite and has a
``top_class`` method, then no ``top_dim`` needs to be
specified in order to ensure that this function
terminates.
If the algebra for this module is finite, then no
``top_dim`` needs to be specified in order to ensure that
this function terminates.
TESTS::
Expand Down Expand Up @@ -1549,14 +1547,10 @@ def _resolve_kernel(self, top_dim=None, verbose=False):
print ('The domain of the morphism is trivial, so there is nothing to resolve.')
return j

# TODO:
#
# Handle algebras which are finite dimensional but which have
# no top_class method, for example exterior algebras.
if not self.base_ring().dimension() < PlusInfinity():
limit = PlusInfinity()
else:
limit = (self.base_ring().top_class().degree() + max(self.domain().generator_degrees()))
limit = _top_dim(self.base_ring()) + max(self.domain().generator_degrees())

if top_dim is not None:
limit = min(top_dim, limit)
Expand Down Expand Up @@ -1694,7 +1688,7 @@ def _resolve_image(self, top_dim=None, verbose=False):

degree_values = [0] + [v.degree() for v in self._values if v]
limit = PlusInfinity() if not self.base_ring().is_finite() else\
(self.base_ring().top_class().degree() + max(degree_values))
(_top_dim(self.base_ring()) + max(degree_values))

if top_dim is not None:
limit = min(top_dim, limit)
Expand Down Expand Up @@ -1792,3 +1786,66 @@ def fp_module(self):
return FPModule(self.base_ring(),
self.codomain().generator_degrees(),
tuple([r.coefficients() for r in self._values]))


def _lift_to_free_morphism(self):
"""
If ``self`` is a map between finitely presented modules which are
actually free, then return this morphism as a
FreeGradedModuleMorphism. Otherwise raise an error.
EXAMPLES::
sage: from sage.modules.fp_graded.module import FPModule
sage: A2 = SteenrodAlgebra(2, profile=(3,2,1))
sage: M = FPModule(A2, [0], relations=[[Sq(1)]])
sage: N = FPModule(A2, [0], relations=[[Sq(4)],[Sq(1)]])
sage: f = Hom(M,N)([A2.Sq(3)*N.generator(0)])
sage: f._lift_to_free_morphism()
Traceback (most recent call last):
...
ValueError: the domain and/or codomain are not free
sage: MF = FPModule(A2, [0, 1])
sage: f = Hom(MF, MF)([A2.Sq(3) * MF.generator(0), A2.Sq(0, 1) * MF.generator(1)])
sage: f._lift_to_free_morphism()
Free module endomorphism of 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[0] |--> Sq(3)*g[0]
g[1] |--> Sq(0,1)*g[1]
"""
if self.domain().relations() or self.codomain().relations():
raise ValueError("the domain and/or codomain are not free")
M = self.domain()._free_module()
N = self.codomain()._free_module()
return Hom(M, N)([N(v.coefficients()) for v in self.values()])


@cached_function
def _top_dim(algebra):
r"""
The top dimension of ``algebra``
This returns ``PlusInfinity`` if the algebra is
infinite-dimensional. If the algebra has a ``top_class``
method, then it is used in the computation; otherwise the
computation may be slow.
EXAMPLES::
sage: from sage.modules.fp_graded.morphism import _top_dim
sage: E.<x,y,z> = ExteriorAlgebra(QQ)
sage: _top_dim(E)
3
sage: _top_dim(SteenrodAlgebra(2, profile=(3,2,1)))
23
"""
if not algebra.dimension() < PlusInfinity():
return PlusInfinity()
try:
alg_top_dim = algebra.top_class().degree()
except AttributeError:
# This could be very slow, but it should handle the case
# when the algebra is finite-dimensional but has no
# top_class method, e.g., exterior algebras.
alg_top_dim = max(a.degree() for a in algebra.basis())
return alg_top_dim

0 comments on commit 11b3725

Please sign in to comment.