This repository has been archived by the owner on Jan 30, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
trac 32505: finitely presented graded modules
- Loading branch information
1 parent
a3bd572
commit fa91596
Showing
10 changed files
with
5,526 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
""" | ||
Finitely presented graded left modules over graded connected algebras | ||
""" | ||
|
||
|
||
# TODO: | ||
# | ||
# 1. Why do we need to define __bool__ and __eq__ in element.py? They should be taken care of automatically, once we define __nonzero__. | ||
# 2. inhheritance: free modules, elements, etc., should perhaps inherit from fp versions, or maybe both should inherit from generic classes, to consolidate some methods (like degree, _repr_, others?) | ||
# 3. Test with graded modules over other graded rings. (Should be okay, but add some doctests.) | ||
# | ||
# In __classcall__/__init__ for FP_Modules, allow as input a free module or a morphism of free modules? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,322 @@ | ||
r""" | ||
Elements of finitely presented graded modules | ||
This class implements construction and basic manipulation of elements of the | ||
Sage parent :class:`sage.modules.fp_graded.module.FP_Module`, which models | ||
finitely presented modules over connected graded algebras. | ||
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. | ||
""" | ||
|
||
#***************************************************************************** | ||
# Copyright (C) 2011 Robert R. Bruner <rrb@math.wayne.edu> and | ||
# Michael J. Catanzaro <mike@math.wayne.edu> | ||
# | ||
# This program is free software: you can redistribute it and/or modify | ||
# it under the terms of the GNU General Public License as published by | ||
# the Free Software Foundation, either version 2 of the License, or | ||
# (at your option) any later version. | ||
# https://www.gnu.org/licenses/ | ||
# **************************************************************************** | ||
|
||
from sage.misc.cachefunc import cached_method | ||
from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement | ||
|
||
from .free_element import FreeGradedModuleElement | ||
|
||
|
||
class FP_Element(IndexedFreeModuleElement): | ||
r""" | ||
A module element of a finitely presented graded module over | ||
a connected graded algebra. | ||
TESTS: | ||
sage: from sage.modules.fp_graded.module import FP_Module | ||
sage: FP_Module(SteenrodAlgebra(2), [0])([Sq(2)]) | ||
<Sq(2)> | ||
""" | ||
def free_element(self): | ||
r""" | ||
A lift of this element to the free module F, | ||
if this element is in a quotient of F. | ||
EXAMPLES:: | ||
sage: from sage.modules.fp_graded.module import FP_Module | ||
sage: M = FP_Module(SteenrodAlgebra(2), [0,1], [[Sq(4), Sq(3)]]) | ||
sage: x = M([Sq(1), 1]) | ||
sage: x | ||
<Sq(1), 1> | ||
sage: x.parent() | ||
Finitely presented left module on 2 generators and 1 relation over mod 2 Steenrod algebra, milnor basis | ||
sage: x.free_element() | ||
<Sq(1), 1> | ||
sage: x.free_element().parent() | ||
Finitely presented free left module on 2 generators over mod 2 Steenrod algebra, milnor basis | ||
""" | ||
C = self.parent().j.codomain() | ||
return C(self.dense_coefficient_list()) | ||
|
||
|
||
@cached_method | ||
def degree(self): | ||
r""" | ||
The degree of this element. | ||
OUTPUT: The integer degree of this element, or ``None`` if this is the | ||
zero element. | ||
EXAMPLES:: | ||
sage: from sage.modules.fp_graded.module import FP_Module | ||
sage: M = FP_Module(SteenrodAlgebra(2), [0,1], [[Sq(4), Sq(3)]]) | ||
sage: x = M.an_element(7) | ||
sage: x | ||
<Sq(0,0,1), Sq(3,1)> | ||
sage: x.degree() | ||
7 | ||
The zero element has no degree:: | ||
sage: (x-x).degree() | ||
Traceback (most recent call last): | ||
... | ||
ValueError: the zero element does not have a well-defined degree | ||
TESTS: | ||
sage: N = FP_Module(SteenrodAlgebra(2), [0], [[Sq(2)]]) | ||
sage: y = Sq(2)*N.generator(0) | ||
sage: y == 0 | ||
True | ||
sage: y.degree() | ||
Traceback (most recent call last): | ||
... | ||
ValueError: the zero element does not have a well-defined degree | ||
""" | ||
if self.is_zero(): | ||
raise ValueError("the zero element does not have a well-defined degree") | ||
return self.free_element().degree() | ||
|
||
|
||
def _repr_(self): | ||
r""" | ||
Return a string representation of this element. | ||
EXAMPLES:: | ||
sage: from sage.modules.fp_graded.module import FP_Module | ||
sage: M = FP_Module(SteenrodAlgebra(2), [0,1], [[Sq(4), Sq(3)]]) | ||
sage: [M.an_element(n) for n in range(1,10)] | ||
[<Sq(1), 1>, | ||
<Sq(2), Sq(1)>, | ||
<Sq(0,1), Sq(2)>, | ||
<Sq(1,1), Sq(3)>, | ||
<Sq(2,1), Sq(4)>, | ||
<Sq(0,2), Sq(5)>, | ||
<Sq(0,0,1), Sq(3,1)>, | ||
<Sq(1,0,1), Sq(1,2)>, | ||
<Sq(2,0,1), Sq(2,2)>] | ||
""" | ||
return self.free_element()._repr_() | ||
|
||
|
||
def _lmul_(self, a): | ||
r""" | ||
Act by left multiplication on this element by ``a``. | ||
INPUT: | ||
- ``a`` -- an element of the algebra this module is defined over. | ||
OUTPUT: the module element `a\cdot x` where `x` is this module element. | ||
EXAMPLES:: | ||
sage: from sage.modules.fp_graded.module import FP_Module | ||
sage: A2 = SteenrodAlgebra(2, profile=(3,2,1)) | ||
sage: M = FP_Module(A2, [0,3], [[Sq(2)*Sq(4), Sq(3)]]) | ||
sage: A2.Sq(2)*M.generator(1) | ||
<0, Sq(2)> | ||
sage: A2.Sq(2)*(A2.Sq(1)*A2.Sq(2)*M.generator(0) + M.generator(1)) | ||
<Sq(2,1), Sq(2)> | ||
TESTS: | ||
sage: elements = [M.an_element(n) for n in range(1,10)] | ||
sage: a = A2.Sq(3) | ||
sage: [a*x for x in elements] | ||
[<Sq(1,1), 0>, | ||
<0, 0>, | ||
<Sq(3,1), Sq(3)>, | ||
<0, Sq(1,1)>, | ||
<0, 0>, | ||
<Sq(3,2), Sq(3,1)>, | ||
<Sq(3,0,1), Sq(7)>, | ||
<Sq(1,1,1), Sq(5,1)>, | ||
<0, Sq(3,2)>] | ||
""" | ||
return self.parent()(a*self.free_element()) | ||
|
||
|
||
def vector_presentation(self): | ||
r""" | ||
A coordinate vector representing this module element when it is non-zero. | ||
These are coordinates with respect to the basis chosen by | ||
:meth:`sage.modules.fp_graded.module.FP_Module.basis_elements`. | ||
When the element is zero, it has no well defined degree, and this | ||
function returns ``None``. | ||
OUTPUT: A vector of elements in the ground field of the algebra for | ||
this module when this element is non-zero. Otherwise, the value | ||
``None``. | ||
.. SEEALSO:: | ||
:meth:`sage.modules.fp_graded.module.FP_Module.vector_presentation` | ||
:meth:`sage.modules.fp_graded.module.FP_Module.basis_elements` | ||
:meth:`sage.modules.fp_graded.module.FP_Module.element_from_coordinates` | ||
EXAMPLES:: | ||
sage: from sage.modules.fp_graded.module import FP_Module | ||
sage: A2 = SteenrodAlgebra(2, profile=(3,2,1)) | ||
sage: M = FP_Module(A2, (0,1)) | ||
sage: x = M.an_element(7) | ||
sage: v = x.vector_presentation(); v | ||
(1, 0, 0, 0, 0, 1, 0) | ||
sage: type(v) | ||
<type 'sage.modules.vector_mod2_dense.Vector_mod2_dense'> | ||
sage: V = M.vector_presentation(7) | ||
sage: v in V | ||
True | ||
sage: M.element_from_coordinates(v, 7) == x | ||
True | ||
We can use the basis for the module elements in the degree of `x`, | ||
together with the coefficients `v` to recreate the element `x`:: | ||
sage: basis = M.basis_elements(7) | ||
sage: x_ = sum( [c*b for (c,b) in zip(v, basis)] ); x_ | ||
<Sq(0,0,1), Sq(3,1)> | ||
sage: x == x_ | ||
True | ||
TESTS: | ||
sage: M.zero().vector_presentation() is None | ||
True | ||
""" | ||
# We cannot represent the zero element since it does not have a degree, | ||
# and we therefore do not know which vector space it belongs to. | ||
# | ||
# In this case, we could return the integer value 0 since coercion would | ||
# place it inside any vector space. However, this will not work for | ||
# homomorphisms, so we return None to be consistent. | ||
try: | ||
degree = self.free_element().degree() | ||
except ValueError: | ||
return None | ||
|
||
F_n = self.parent().vector_presentation(degree) | ||
return F_n.quotient_map()(self.free_element().vector_presentation()) | ||
|
||
|
||
def __nonzero__(self): | ||
r""" | ||
Determine if this element is non-zero. | ||
OUTPUT: The boolean value ``True`` if this element is non-zero, and ``False`` | ||
otherwise. | ||
EXAMPLES:: | ||
sage: from sage.modules.fp_graded.module import FP_Module | ||
sage: M = FP_Module(SteenrodAlgebra(2), [0,2,4], [[Sq(4),Sq(2),0]]) | ||
sage: M(0).__nonzero__() | ||
False | ||
sage: M((Sq(6), 0, Sq(2))).__nonzero__() | ||
True | ||
sage: a = M((Sq(1)*Sq(2)*Sq(1)*Sq(4), 0, 0)) | ||
sage: b = M((0, Sq(2)*Sq(2)*Sq(2), 0)) | ||
sage: a.__nonzero__() | ||
True | ||
sage: b.__nonzero__() | ||
True | ||
sage: (a + b).__nonzero__() | ||
False | ||
""" | ||
pres = self.vector_presentation() | ||
if pres is None: | ||
return False | ||
return bool(pres) | ||
|
||
__bool__ = __nonzero__ | ||
|
||
def __eq__(self, other): | ||
r""" | ||
True iff ``self`` and ``other`` are equal. | ||
EXAMPLES:: | ||
sage: from sage.modules.fp_graded.module import FP_Module | ||
sage: M = FP_Module(SteenrodAlgebra(2), [0,1], [[Sq(4), Sq(3)]]) | ||
sage: x = M([Sq(1), 1]) | ||
sage: x | ||
<Sq(1), 1> | ||
sage: x == x | ||
True | ||
sage: x == M.zero() | ||
False | ||
sage: x-x == M.zero() | ||
True | ||
""" | ||
try: | ||
return (self - other).is_zero() | ||
except TypeError: | ||
return False | ||
|
||
|
||
def normalize(self): | ||
r""" | ||
A normalized form of ``self``. | ||
OUTPUT: An instance of this element class representing the same | ||
module element as this element. | ||
EXAMPLES:: | ||
sage: from sage.modules.fp_graded.module import FP_Module | ||
sage: M = FP_Module(SteenrodAlgebra(2), [0,2,4], [[Sq(4),Sq(2),0]]) | ||
sage: m = M((Sq(6), 0, Sq(2))); m | ||
<Sq(6), 0, Sq(2)> | ||
sage: m.normalize() | ||
<Sq(6), 0, Sq(2)> | ||
sage: m == m.normalize() | ||
True | ||
sage: n = M((Sq(4), Sq(2), 0)); n | ||
<Sq(4), Sq(2), 0> | ||
sage: n.normalize() | ||
<0, 0, 0> | ||
sage: n == n.normalize() | ||
True | ||
""" | ||
if self.is_zero(): | ||
return self.parent().zero() | ||
|
||
v = self.vector_presentation() | ||
return self.parent().element_from_coordinates(v, self.degree()) |
Oops, something went wrong.