Skip to content

Commit 036716b

Browse files
author
Release Manager
committed
sagemathgh-38703: Implementation of Ore modules This PR implements modules over Ore polynomial rings. More precisely, if $A[X;\theta,\partial]$ is a Ore polynomial ring, we propose an implementation of finite free modules $M$ over $A$ equipped with a map $f : M \to M$ such that $f(ax) = \theta(a) f(x) + \partial(a) x$ for all $a \in R$ and $x \in M$. Such a map is called *pseudolinear* and it endows `M` with a structure of module over $A[X;\theta,\partial]$ (the map $f$ corresponding to the multiplication by $X$). This PR includes: - an implementation of the category of Ore modules - an implementation of Ore modules, their submodules and their quotients (with an option to give chosen names to elements in a distinguished basis) - a constructor to create quotients of the form $A[X;\theta,\partial] / A[X;\theta,\partial]P$ - an implementation of morphisms between Ore modules, including methods for computing kernels, cokernels, images and coimages This is the second step (after PR sagemath#38650) towards the implemetation of Anderson motives. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [ ] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies sagemath#38650: pseudomorphisms URL: sagemath#38703 Reported by: Xavier Caruso Reviewer(s): Rubén Muñoz--Bertrand
2 parents 7d83063 + c7a800b commit 036716b

14 files changed

+3900
-9
lines changed

src/doc/en/reference/categories/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ Individual Categories
162162
sage/categories/monoids
163163
sage/categories/number_fields
164164
sage/categories/objects
165+
sage/categories/ore_modules
165166
sage/categories/partially_ordered_monoids
166167
sage/categories/permutation_groups
167168
sage/categories/pointed_sets

src/doc/en/reference/index.rst

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Linear Algebra
5151
* :doc:`Matrices and Spaces of Matrices <matrices/index>`
5252
* :doc:`Vectors and Modules <modules/index>`
5353
* :doc:`Tensors on Free Modules of Finite Rank <tensor_free_modules/index>`
54+
* :doc:`Modules over Ore rings <oremodules/index>`
5455

5556
Calculus and Analysis
5657
---------------------
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../conf_sub.py
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
Modules over Ore rings
2+
======================
3+
4+
Let `R` be a commutative ring, `\theta : K \to K` by a ring
5+
endomorphism and `\partial : K \to K` be a `\theta`-derivation,
6+
that is an additive map satisfying the following axiom
7+
8+
.. MATH::
9+
10+
\partial(x y) = \theta(x) \partial(y) + \partial(x) y
11+
12+
The Ore polynomial ring associated to these data is
13+
`\mathcal S = R[X; \theta, \partial]`; its elements are the
14+
usual polynomials over `R` but the multiplication is twisted
15+
according to the rule
16+
17+
.. MATH::
18+
19+
\partial(x y) = \theta(x) \partial(y) + \partial(x) y
20+
21+
We refer to :mod:`sage.rings.polynomial.ore_polynomial_ring.OrePolynomial`
22+
for more details.
23+
24+
A Ore module over `(R, \theta, \partial)` is by definition a
25+
module over `\mathcal S`; it is the same than a `R`-module `M`
26+
equipped with an additive `f : M \to M` such that
27+
28+
.. MATH::
29+
30+
f(a x) = \theta(a) f(x) + \partial(a) x
31+
32+
Such a map `f` is called a pseudomorphism
33+
(see also :meth:`sage.modules.free_module.FreeModule_generic.pseudohom`).
34+
35+
SageMath provides support for creating and manipulating Ore
36+
modules that are finite free over the base ring `R`.
37+
This includes, in particular, Frobenius modules and modules
38+
with connexions.
39+
40+
Modules, submodules and quotients
41+
---------------------------------
42+
43+
.. toctree::
44+
:maxdepth: 1
45+
46+
sage/modules/ore_module
47+
sage/modules/ore_module_element
48+
49+
Morphisms
50+
---------
51+
52+
.. toctree::
53+
:maxdepth: 1
54+
55+
sage/modules/ore_module_homspace
56+
sage/modules/ore_module_morphism

src/sage/categories/meson.build

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ py.install_sources(
148148
'noetherian_rings.py',
149149
'number_fields.py',
150150
'objects.py',
151+
'ore_modules.py',
151152
'partially_ordered_monoids.py',
152153
'permutation_groups.py',
153154
'pointed_sets.py',

src/sage/categories/ore_modules.py

+177
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
from sage.misc.lazy_attribute import lazy_attribute
2+
3+
from sage.categories.modules import Modules
4+
from sage.categories.category_types import Category_over_base_ring
5+
from sage.categories.homsets import Homsets
6+
from sage.rings.polynomial.ore_polynomial_ring import OrePolynomialRing
7+
8+
9+
class OreModules(Category_over_base_ring):
10+
r"""
11+
Category of Ore modules.
12+
"""
13+
@staticmethod
14+
def __classcall_private__(cls, ring, twist):
15+
r"""
16+
Normalize the input and call the init function.
17+
18+
INPUT:
19+
20+
- ``ring`` -- a commutative ring, the base ring of
21+
the Ore modules
22+
23+
- ``twist`` -- a twisting morphism/derivation or a
24+
Ore polynomial ring
25+
26+
TESTS::
27+
28+
sage: from sage.categories.ore_modules import OreModules
29+
sage: K.<a> = GF(5^3)
30+
sage: Frob = K.frobenius_endomorphism()
31+
sage: cat = OreModules(K, Frob)
32+
sage: cat
33+
Category of Ore modules over Finite Field in a of size 5^3 twisted by a |--> a^5
34+
35+
sage: S = cat.ore_ring('y')
36+
sage: cat is OreModules(K, S)
37+
True
38+
"""
39+
if isinstance(twist, OrePolynomialRing):
40+
ore = twist.change_var('x')
41+
if ore.base_ring() is not ring:
42+
raise ValueError("base rings do not match")
43+
else:
44+
ore = OrePolynomialRing(ring, twist, names='x', polcast=False)
45+
return cls.__classcall__(cls, ore)
46+
47+
def __init__(self, ore):
48+
r"""
49+
Initialize this category.
50+
51+
TESTS::
52+
53+
sage: from sage.categories.ore_modules import OreModules
54+
sage: K.<a> = GF(5^3)
55+
sage: Frob = K.frobenius_endomorphism()
56+
sage: cat = OreModules(K, Frob)
57+
58+
sage: TestSuite(cat).run()
59+
"""
60+
base = ore.base_ring()
61+
Category_over_base_ring.__init__(self, base)
62+
self._ore = ore
63+
64+
def __reduce__(self):
65+
r"""
66+
Return the arguments which were used to create this instance.
67+
68+
This method is needed for pickling.
69+
70+
TESTS::
71+
72+
sage: from sage.categories.ore_modules import OreModules
73+
sage: K.<a> = GF(5^3)
74+
sage: Frob = K.frobenius_endomorphism()
75+
sage: cat = OreModules(K, Frob)
76+
sage: cat2 = loads(dumps(cat)) # indirect doctest
77+
sage: cat is cat2
78+
True
79+
"""
80+
return OreModules, (self.base_ring(), self._ore)
81+
82+
def super_categories(self):
83+
r"""
84+
Return the immediate super categories of this category.
85+
86+
EXAMPLES::
87+
88+
sage: from sage.categories.ore_modules import OreModules
89+
sage: K.<a> = GF(5^3)
90+
sage: Frob = K.frobenius_endomorphism()
91+
sage: cat = OreModules(K, Frob)
92+
sage: cat.super_categories()
93+
[Category of vector spaces over Finite Field in a of size 5^3]
94+
"""
95+
return [Modules(self.base())]
96+
97+
def _repr_object_names(self):
98+
r"""
99+
Return a string representation naming the objects
100+
in this category.
101+
102+
EXAMPLES::
103+
104+
sage: from sage.categories.ore_modules import OreModules
105+
sage: K.<a> = GF(5^3)
106+
sage: Frob = K.frobenius_endomorphism()
107+
sage: cat = OreModules(K, Frob)
108+
sage: cat._repr_object_names()
109+
'Ore modules over Finite Field in a of size 5^3 twisted by a |--> a^5'
110+
"""
111+
return "Ore modules over %s %s" % (self.base_ring(), self._ore._repr_twist())
112+
113+
def ore_ring(self, var='x'):
114+
r"""
115+
Return the underlying Ore polynomial ring.
116+
117+
INPUT:
118+
119+
- ``var`` (default; ``x``) -- the variable name
120+
121+
EXAMPLES::
122+
123+
sage: from sage.categories.ore_modules import OreModules
124+
sage: K.<a> = GF(5^3)
125+
sage: Frob = K.frobenius_endomorphism()
126+
sage: cat = OreModules(K, Frob)
127+
sage: cat.ore_ring()
128+
Ore Polynomial Ring in x over Finite Field in a of size 5^3 twisted by a |--> a^5
129+
130+
sage: cat.ore_ring('y')
131+
Ore Polynomial Ring in y over Finite Field in a of size 5^3 twisted by a |--> a^5
132+
"""
133+
return self._ore.change_var(var)
134+
135+
def twisting_morphism(self):
136+
r"""
137+
Return the underlying twisting morphism.
138+
139+
EXAMPLES::
140+
141+
sage: from sage.categories.ore_modules import OreModules
142+
sage: K.<a> = GF(5^3)
143+
sage: Frob = K.frobenius_endomorphism()
144+
sage: cat = OreModules(K, Frob)
145+
sage: cat.twisting_morphism()
146+
Frobenius endomorphism a |--> a^5 on Finite Field in a of size 5^3
147+
148+
If the twising morphism is the identity, nothing is returned::
149+
150+
sage: R.<t> = QQ[]
151+
sage: d = R.derivation()
152+
sage: cat = OreModules(R, d)
153+
sage: cat.twisting_morphism()
154+
"""
155+
return self._ore.twisting_morphism()
156+
157+
def twisting_derivation(self):
158+
r"""
159+
Return the underlying twisting derivation.
160+
161+
EXAMPLES::
162+
163+
sage: from sage.categories.ore_modules import OreModules
164+
sage: R.<t> = QQ[]
165+
sage: d = R.derivation()
166+
sage: cat = OreModules(R, d)
167+
sage: cat.twisting_derivation()
168+
d/dt
169+
170+
If the twising derivation is zero, nothing is returned::
171+
172+
sage: K.<a> = GF(5^3)
173+
sage: Frob = K.frobenius_endomorphism()
174+
sage: cat = OreModules(K, Frob)
175+
sage: cat.twisting_derivation()
176+
"""
177+
return self._ore.twisting_derivation()

src/sage/modules/free_module_pseudomorphism.py

+65
Original file line numberDiff line numberDiff line change
@@ -500,5 +500,70 @@ def __eq__(self, other):
500500
if isinstance(other, FreeModulePseudoMorphism):
501501
return self.parent() is other.parent() and self._matrix == other._matrix
502502

503+
def ore_module(self, names=None):
504+
r"""
505+
Return the Ore module over which the Ore variable acts
506+
through this pseudomorphism.
507+
508+
INPUT:
509+
510+
- ``names`` -- a string, a list of strings or ``None``,
511+
the names of the vector of the canonical basis of the
512+
Ore module; if ``None``, elements are represented as
513+
vectors in `K^d` (where `K` is the base ring)
514+
515+
EXAMPLES::
516+
517+
sage: Fq.<z> = GF(7^3)
518+
sage: Frob = Fq.frobenius_endomorphism()
519+
sage: V = Fq^2
520+
sage: mat = matrix(2, [1, z, z^2, z^3])
521+
sage: f = V.pseudohom(mat, Frob)
522+
523+
sage: M = f.ore_module()
524+
sage: M
525+
Ore module of rank 2 over Finite Field in z of size 7^3 twisted by z |--> z^7
526+
527+
Here `M` is a module over the Ore ring `\mathbb F_q[X; \text{Frob}]`
528+
and the variable `X` acts on `M` through `f`::
529+
530+
sage: S.<X> = M.ore_ring()
531+
sage: S
532+
Ore Polynomial Ring in X over Finite Field in z of size 7^3 twisted by z |--> z^7
533+
sage: v = M((1,0))
534+
sage: X*v
535+
(1, z)
536+
537+
The argument ``names`` can be used to give chosen names
538+
to the vectors in the canonical basis::
539+
540+
sage: M = f.ore_module(names=('v', 'w'))
541+
sage: M.basis()
542+
[v, w]
543+
544+
or even::
545+
546+
sage: M = f.ore_module(names='e')
547+
sage: M.basis()
548+
[e0, e1]
549+
550+
Note that the bracket construction also works::
551+
552+
sage: M.<v,w> = f.ore_module()
553+
sage: M.basis()
554+
[v, w]
555+
sage: v + w
556+
v + w
557+
558+
We refer to :mod:`sage.modules.ore_module` for a
559+
tutorial on Ore modules in SageMath.
560+
561+
.. SEEALSO::
562+
563+
:mod:`sage.modules.ore_module`
564+
"""
565+
from sage.modules.ore_module import OreModule
566+
return OreModule(self._matrix, self.parent()._ore, names)
567+
503568
def _test_nonzero_equal(self, tester):
504569
pass

src/sage/modules/meson.build

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ py.install_sources(
2020
'module_functors.py',
2121
'multi_filtered_vector_space.py',
2222
'numpy_util.pxd',
23+
'ore_module.py',
24+
'ore_module_element.py',
25+
'ore_module_homspace.py',
26+
'ore_module_morphism.py',
2327
'quotient_module.py',
2428
'real_double_vector.py',
2529
'submodule.py',

0 commit comments

Comments
 (0)