Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241849 views
1
r"""
2
Module abstractly spanned by Fourier expansions.
3
4
AUTHOR:
5
- Martin Raum (2010 - 05 - 15) Initial version
6
"""
7
8
#===============================================================================
9
#
10
# Copyright (C) 2010 Martin Raum
11
#
12
# This program is free software; you can redistribute it and/or
13
# modify it under the terms of the GNU General Public License
14
# as published by the Free Software Foundation; either version 3
15
# of the License, or (at your option) any later version.
16
#
17
# This program is distributed in the hope that it will be useful,
18
# but WITHOUT ANY WARRANTY; without even the implied warranty of
19
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
# General Public License for more details.
21
#
22
# You should have received a copy of the GNU General Public License
23
# along with this program; if not, see <http://www.gnu.org/licenses/>.
24
#
25
#===============================================================================
26
27
from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_lazy_evaluation import LazyFourierExpansionEvaluation
28
from psage.modform.fourier_expansion_framework.gradedexpansions.fourierexpansionwrapper import FourierExpansionWrapper
29
from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import EquivariantMonoidPowerSeriesAmbient_abstract, MonoidPowerSeriesAmbient_abstract
30
from sage.categories.pushout import pushout
31
from sage.interfaces.magma import magma
32
from sage.matrix.constructor import matrix
33
from sage.misc.cachefunc import cached_method
34
from sage.misc.flatten import flatten
35
from sage.misc.latex import latex
36
from sage.misc.misc import union
37
from sage.modules.free_module import FreeModule, FreeModule_generic, \
38
FreeModule_ambient_pid, FreeModule_submodule_pid
39
from sage.modules.free_module import is_FreeModule
40
from sage.modules.free_module_element import FreeModuleElement_generic_dense
41
from sage.modules.free_module_element import vector
42
from sage.rings.arith import random_prime
43
from sage.rings.integer_ring import ZZ
44
from sage.rings.number_field.order import Order
45
from sage.rings.padics.factory import Qp
46
from sage.rings.principal_ideal_domain import PrincipalIdealDomain
47
from sage.rings.rational_field import QQ
48
from sage.rings.ring import Ring
49
from sage.structure.element import Element
50
from sage.structure.sequence import Sequence, Sequence_generic
51
import itertools
52
53
#===============================================================================
54
# ExpansionModule
55
#===============================================================================
56
57
def ExpansionModule(forms) :
58
r"""
59
Construct a module of over the forms' base ring of rank ``len(forms)``
60
with underlying expansions associated to.
61
62
INPUT:
63
- ``forms`` -- A sequence or nonempty list of (equivariant) monoid power series.
64
65
OUTPUT:
66
An instance of :class:~`.ExpansionModule_abstract`.
67
68
EXAMPLES::
69
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
70
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
71
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
72
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))
73
sage: m = FreeModule(QQ, 3)
74
sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))
75
sage: em = ExpansionModule([emps.one_element(), emps.one_element()])
76
sage: em = ExpansionModule([empsm.zero_element(), empsm.zero_element()])
77
sage: mps = MonoidPowerSeriesRing(ZZ, NNMonoid())
78
sage: em = ExpansionModule([mps.one_element()])
79
sage: mpsm = MonoidPowerSeriesModule(m, NNMonoid())
80
sage: em = ExpansionModule([mpsm.zero_element()])
81
82
TESTS::
83
sage: em = ExpansionModule(Sequence([], universe = emps))
84
sage: em = ExpansionModule(Sequence([], universe = empsm))
85
sage: h = EquivariantMonoidPowerSeries(emps, {emps.characters().one_element(): {1: 1, 3: 2}}, emps.action().filter_all())
86
sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0]), 2: m([0,0,1])}}, empsm.action().filter_all())
87
sage: em = ExpansionModule([emps.one_element(), h, h^2])
88
sage: em = ExpansionModule([empsm.zero_element(), hv, hv * h])
89
sage: em = ExpansionModule([])
90
Traceback (most recent call last):
91
...
92
ValueError: Empty modules must be constructed with a universe.
93
sage: em = ExpansionModule(Sequence([], universe = m))
94
Traceback (most recent call last):
95
...
96
ValueError: Common parent of all forms must be a monoid power series ring or module.
97
sage: qa = QuaternionAlgebra(QQ, -1, -1)
98
sage: em = ExpansionModule(Sequence([], universe = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", qa)) ))
99
Traceback (most recent call last):
100
...
101
TypeError: The forms' base ring must be a commutative ring.
102
"""
103
if not isinstance(forms, Sequence_generic) :
104
forms = Sequence(forms)
105
if len(forms) == 0 :
106
raise ValueError( "Empty modules must be constructed with a universe." )
107
108
if not isinstance(forms.universe(), (MonoidPowerSeriesAmbient_abstract,
109
EquivariantMonoidPowerSeriesAmbient_abstract)) :
110
raise ValueError( "Common parent of all forms must be a monoid power series ring or module." )
111
112
if isinstance(forms.universe(), EquivariantMonoidPowerSeriesAmbient_abstract) \
113
and forms.universe().representation().base_ring() == forms.universe().representation().codomain() :
114
base_ring = forms.universe().base_ring()
115
elif isinstance(forms.universe(), MonoidPowerSeriesAmbient_abstract) \
116
and isinstance(forms.universe().coefficient_domain(), Ring) :
117
base_ring = forms.universe().base_ring()
118
else :
119
base_ring = forms.universe().base_ring().base_ring()
120
121
if not base_ring.is_commutative():
122
raise TypeError( "The forms' base ring must be a commutative ring." )
123
124
if base_ring.is_field() \
125
or isinstance(base_ring, PrincipalIdealDomain) \
126
or ( isinstance(base_ring, Order) \
127
and base_ring.is_maximal() and base_ring.class_number() == 1 ) :
128
return ExpansionModule_ambient_pid(forms)
129
else :
130
return ExpansionModule_generic(forms)
131
132
#===============================================================================
133
# ExpansionModule_abstract
134
#===============================================================================
135
136
class ExpansionModule_abstract :
137
r"""
138
An abstract implementation of a module with expansions associated to its basis elements.
139
"""
140
141
def __init__(self, basis, **kwds) :
142
r"""
143
INPUT:
144
- ``basis`` -- A sequence of (equivariant) monoid power series.
145
146
TESTS::
147
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
148
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
149
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
150
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_abstract
151
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))
152
sage: em = ExpansionModule_abstract(Sequence([emps.one_element(), emps.one_element()]))
153
"""
154
self.__abstract_basis = basis
155
156
def _abstract_basis(self) :
157
r"""
158
Return a basis in terms of elements of the graded ambient.
159
160
OUTPUT:
161
A sequence of (equivariant) monoid power series.
162
163
TESTS::
164
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
165
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
166
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
167
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))
168
sage: basis = Sequence([emps.one_element(), emps.one_element()])
169
sage: em = ExpansionModule(basis)
170
sage: em._abstract_basis() == basis
171
True
172
"""
173
return self.__abstract_basis
174
175
@cached_method
176
def precision(self) :
177
r"""
178
A common precision of the expansions associated to the basis elements.
179
180
OUTPUT:
181
A filter for the expansions' parent's action or monoid.
182
183
TESTS::
184
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
185
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
186
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
187
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))
188
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))
189
sage: em.precision()
190
Filtered NN with action up to +Infinity
191
sage: em = ExpansionModule(Sequence([emps.one_element().truncate(3), emps.one_element()]))
192
sage: em.precision()
193
Filtered NN with action up to 3
194
sage: em = ExpansionModule(Sequence([], universe = emps))
195
sage: em.precision()
196
Filtered NN with action up to +Infinity
197
"""
198
if len(self.__abstract_basis) != 0 :
199
return min([b.precision() for b in self.__abstract_basis])
200
else :
201
if isinstance(self.__abstract_basis.universe(), EquivariantMonoidPowerSeriesAmbient_abstract) :
202
return self.__abstract_basis.universe().action().filter_all()
203
else :
204
return self.__abstract_basis.universe().monoid().filter_all()
205
206
def _bounding_precision(self) :
207
r"""
208
A common precision of the expansions associtated to the basis elements
209
if it is finite or in case it is not a filter that comprises all
210
nonzero coefficient of the expansion.
211
212
OUTPUT:
213
A filter for the expansions' parent's action or monoid.
214
215
TESTS::
216
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
217
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
218
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
219
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))
220
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))
221
sage: em._bounding_precision()
222
Filtered NN with action up to 1
223
sage: em = ExpansionModule(Sequence([emps.one_element().truncate(4), emps.one_element()]))
224
sage: em._bounding_precision()
225
Filtered NN with action up to 4
226
sage: em = ExpansionModule(Sequence([], universe = emps))
227
sage: em._bounding_precision()
228
Filtered NN with action up to 0
229
"""
230
if len(self.__abstract_basis) != 0 :
231
return max([b._bounding_precision() for b in self.__abstract_basis])
232
else :
233
if isinstance(self.__abstract_basis.universe(), EquivariantMonoidPowerSeriesAmbient_abstract) :
234
return self.__abstract_basis.universe().action().zero_filter()
235
else :
236
return self.__abstract_basis.universe().monoid().zero_filter()
237
238
@cached_method
239
def _check_precision(self, precision = None, lazy_rank_check = False) :
240
r"""
241
Check whether the elements of this module are uniquely determined
242
by their Fourier expansions up to ``precision``. If ``precision`` is ``None``
243
the precision of this module will be used.
244
245
INPUT:
246
- ``precision`` -- A filter for the expansions' parent monoid or action or ``None`` (default: ``None``).
247
- ``lazy_rank_check`` -- A boolean (default: ``False``); If ``True`` the involved rank checks will
248
be done over `Q_p` (with finite precision).
249
250
OUTPUT:
251
A boolean.
252
253
TESTS::
254
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
255
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
256
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
257
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))
258
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))
259
sage: em._check_precision()
260
False
261
sage: em = ExpansionModule(Sequence([], universe = emps))
262
sage: em._check_precision()
263
True
264
sage: em._check_precision(lazy_rank_check = True)
265
True
266
sage: h = EquivariantMonoidPowerSeries(emps, {emps.characters().one_element(): {1: 1, 3: 2}}, emps.action().filter_all())
267
sage: em = ExpansionModule(Sequence([emps.one_element(), h]))
268
sage: em._check_precision()
269
True
270
sage: em._check_precision(emps.action().filter(1))
271
False
272
sage: m = FreeModule(QQ, 3)
273
sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))
274
sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0])}}, empsm.action().filter_all())
275
sage: hv2 = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,1,0])}}, empsm.action().filter_all())
276
sage: em = ExpansionModule(Sequence([hv, hv2]))
277
sage: em._check_precision()
278
True
279
"""
280
if lazy_rank_check and not( self.base_ring() is ZZ or self.base_ring() is QQ) :
281
raise NotImplemented, "lazy rank checks only implemented for ZZ and QQ"
282
283
if precision is None :
284
precision = self.precision()
285
elif not precision <= self.precision() :
286
raise ValueError, "precison must be less equal self.__graded_ambient.precision()"
287
288
if precision.is_infinite() :
289
precision = self._bounding_precision()
290
if self.precision().is_infinite() :
291
total_precision = self._bounding_precision()
292
else :
293
total_precision = self.precision()
294
295
basis_fe_expansion = self.fourier_expansion_homomorphism().matrix()
296
297
if precision != self.precision() :
298
if isinstance(self._abstract_basis().universe().coefficient_domain(), Ring) :
299
indices = [i for (i,k) in enumerate(total_precision) if k in precision]
300
else :
301
indices = [i for (i,(k,_)) in enumerate(
302
itertools.product(total_precision, range(self._abstract_basis().universe().coefficient_domain().rank())) )
303
if k in precision]
304
basis_fe_expansion = basis_fe_expansion.matrix_from_columns(indices)
305
306
if lazy_rank_check :
307
basis_fe_expansion = matrix(Qp(random_prime(10**9), 10), basis_fe_expansion)
308
309
return basis_fe_expansion.rank() >= self.rank()
310
311
def _fourier_expansion_of_element(self, e) :
312
r"""
313
The Fourier expansion of an element optained via linear combinations
314
of the basis' Fourier expansions.
315
316
INPUT:
317
- `e` -- An element of ``self``.
318
319
OUTPUT:
320
A (equivariant) monoid power series.
321
322
TESTS::
323
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
324
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
325
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
326
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))
327
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))
328
sage: fe = em._fourier_expansion_of_element(em([1,0]))
329
sage: m = FreeModule(QQ, 3)
330
sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))
331
sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0])}}, empsm.action().filter_all())
332
sage: em = ExpansionModule(Sequence([hv]))
333
sage: fe = em._fourier_expansion_of_element(em([1]))
334
"""
335
return sum( (e[k]*b for (k,b) in enumerate(self.__abstract_basis) if e[k] != 0),
336
self.__abstract_basis.universe()(0) )
337
338
@cached_method
339
def _non_zero_characters(self) :
340
r"""
341
Return those characters which cannot be guaranteed to have vanishing Fourier
342
expansion associated with for all basis elements of ``self``.
343
344
OUTPUT:
345
A list of characters of the expansions' parent if it is equivariant
346
or otherwise None.
347
348
TESTS::
349
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
350
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
351
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
352
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))
353
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))
354
sage: em._non_zero_characters()
355
[1]
356
sage: em = ExpansionModule(Sequence([EquivariantMonoidPowerSeries(emps, {}, emps.action().filter_all())]))
357
sage: em._non_zero_characters()
358
[]
359
"""
360
if isinstance(self.__abstract_basis.universe(), EquivariantMonoidPowerSeriesAmbient_abstract) :
361
return list( reduce(union, [ set(b.non_zero_components())
362
for b in flatten(self.__abstract_basis, tuple) ], set()) )
363
else :
364
return None
365
366
@cached_method
367
def _fourier_expansion_indices(self) :
368
r"""
369
A list of Fourier indices which are considered by the Fourier expansion morphism.
370
371
OUTPUT:
372
A list of monoid elements or components indices and monoid elements
373
in case the expansions' parent is not equivariant. Otherwise, it
374
is pairs of characters and monoid elements possibly with a component
375
index in case the coefficient domain of the expansions parent is only
376
a module.
377
378
SEE:
379
:meth:~`.fourier_expansion_homomorphism`.
380
381
TESTS::
382
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
383
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
384
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
385
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))
386
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))
387
sage: em._fourier_expansion_indices()
388
[(1, 0)]
389
sage: m = FreeModule(QQ, 3)
390
sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))
391
sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0]), 2: m([0,0,1])}}, empsm.action().filter_all())
392
sage: em = ExpansionModule(Sequence([hv]))
393
sage: em._fourier_expansion_indices()
394
[(0, (1, 0)), (1, (1, 0)), (2, (1, 0)), (0, (1, 1)), (1, (1, 1)), (2, (1, 1)), (0, (1, 2)), (1, (1, 2)), (2, (1, 2))]
395
sage: mps = MonoidPowerSeriesRing(ZZ, NNMonoid())
396
sage: em = ExpansionModule([mps.one_element()])
397
sage: em._fourier_expansion_indices()
398
[0]
399
sage: mpsm = MonoidPowerSeriesModule(m, NNMonoid())
400
sage: hv = MonoidPowerSeries(mpsm, {1: m([1,0,0]), 2: m([0,0,1])}, mpsm.monoid().filter_all())
401
sage: em = ExpansionModule([hv])
402
sage: em._fourier_expansion_indices()
403
[(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2)]
404
"""
405
characters = self._non_zero_characters()
406
407
if isinstance(self.__abstract_basis.universe().coefficient_domain(), Ring) :
408
if characters is None :
409
return list(self._bounding_precision())
410
else :
411
return [ (ch, k) for k in self._bounding_precision()
412
for ch in characters ]
413
else :
414
if characters is None :
415
return [ (i, k) for k in self._bounding_precision()
416
for i in range(self.__abstract_basis.universe().coefficient_domain().rank()) ]
417
else :
418
return [ (i,(ch, k)) for k in self._bounding_precision()
419
for ch in characters
420
for i in range(self.__abstract_basis.universe().coefficient_domain().rank()) ]
421
422
@cached_method
423
def fourier_expansion_homomorphism(self, precision = None) :
424
r"""
425
A morphism mapping elements of the underlying module to
426
a module such that each component of the image corresponds to an
427
Fourier coefficient of the Fourier expansion associated with this
428
element.
429
430
INPUT:
431
- ``precision`` -- A fitler for the expansions monoid or action or ``None``
432
(default: ``None``); If not ``None`` the Fourier expansions
433
of the basis will be truncated to this precision.
434
435
OUTPUT:
436
A morphism from ``self`` to a free module over the expansions' base ring.
437
438
TESTS::
439
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
440
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
441
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
442
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))
443
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))
444
sage: em.fourier_expansion_homomorphism()
445
Free module morphism defined by the matrix
446
[1]
447
[1]
448
Domain: Module of Fourier expansions in Ring of equivariant monoid power ...
449
Codomain: Vector space of dimension 1 over Rational Field
450
sage: m = FreeModule(QQ, 3)
451
sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))
452
sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0]), 2: m([0,0,1])}}, empsm.action().filter_all())
453
sage: em = ExpansionModule(Sequence([hv]))
454
sage: em.fourier_expansion_homomorphism()
455
Free module morphism defined by the matrix
456
[0 0 0 1 0 0 0 0 1]
457
Domain: Module of Fourier expansions in Module of equivariant monoid ...
458
Codomain: Vector space of dimension 9 over Rational Field
459
"""
460
keys = self._fourier_expansion_indices()
461
462
codomain = FreeModule(self.base_ring(), len(keys))
463
if isinstance(self.__abstract_basis.universe().coefficient_domain(), Ring) :
464
basis_images = [ codomain([b[k] for k in keys])
465
for b in self.__abstract_basis ]
466
else :
467
basis_images = [ codomain([b[k][i] for (i,k) in keys])
468
for b in self.__abstract_basis ]
469
470
return self.Hom(codomain)(basis_images)
471
472
@cached_method
473
def _fourier_expansion_matrix_over_fraction_field(self) :
474
r"""
475
The matrix associated with the Fourier expansion homomorphism
476
such that its base ring is a field.
477
478
OUTPUT:
479
A matrix over the fraction field of the expansions' base ring.
480
481
SEE:
482
:meth:~`.fourier_expansion_homomorphism`.
483
484
TESTS::
485
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
486
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
487
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
488
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
489
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))
490
sage: em._fourier_expansion_matrix_over_fraction_field().base_ring()
491
Rational Field
492
"""
493
if self.base_ring().is_field() :
494
return self.fourier_expansion_homomorphism().matrix()
495
else :
496
return self.fourier_expansion_homomorphism().matrix(). \
497
base_extend(self.base_ring().fraction_field())
498
499
@cached_method
500
def pivot_elements(self) :
501
r"""
502
Determine a set of generators, which minimally span the image of the Fourier expansion
503
homomorphism.
504
505
SEE:
506
:meth:~`.fourier_expansion_homomorphism`.
507
508
OUTPUT:
509
A list of indices.
510
511
TESTS::
512
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
513
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
514
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
515
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
516
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))
517
sage: em.pivot_elements()
518
[0]
519
sage: em = ExpansionModule(Sequence([emps.one_element().truncate(0), emps.one_element().truncate(0)]))
520
sage: em.pivot_elements()
521
[]
522
sage: em = ExpansionModule(Sequence([], universe = emps))
523
sage: em.pivot_elements()
524
[]
525
sage: m = FreeModule(QQ, 3)
526
sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))
527
sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0]), 2: m([0,0,1])}}, empsm.action().filter_all())
528
sage: em = ExpansionModule(Sequence([hv,hv]))
529
sage: em.pivot_elements()
530
[0]
531
"""
532
expansion_matrix = self.fourier_expansion_homomorphism().matrix().transpose()
533
534
if expansion_matrix.rank() == self.rank() :
535
return range(self.rank())
536
else :
537
return list(expansion_matrix.pivots())
538
539
def _element_to_fourier_expansion_generator(self, e) :
540
r"""
541
Given a monoid power series `e` return a generator iterating over the components of
542
the image of `e` under the Fourier expansion morphism.
543
544
INTPUT:
545
- `e` -- An element of the ``self``.
546
547
OUTPUT:
548
A generator over elements of the expansions' base ring.
549
550
SEE::
551
:meth:~`.fourier_expansion_homomorphism`.
552
553
TESTS::
554
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
555
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
556
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
557
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
558
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))
559
sage: list(em._element_to_fourier_expansion_generator(em([3,0]).fourier_expansion()))
560
[3]
561
sage: m = FreeModule(QQ, 3)
562
sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))
563
sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0]), 2: m([0,0,1])}}, empsm.action().filter_all())
564
sage: em = ExpansionModule(Sequence([hv]))
565
sage: list(em._element_to_fourier_expansion_generator(em([1]).fourier_expansion()))
566
[0, 0, 0, 1, 0, 0, 0, 0, 1]
567
sage: mps = MonoidPowerSeriesRing(ZZ, NNMonoid())
568
sage: em = ExpansionModule([mps.one_element()])
569
sage: list(em._element_to_fourier_expansion_generator(em([2]).fourier_expansion()))
570
[2]
571
sage: mpsm = MonoidPowerSeriesModule(m, NNMonoid())
572
sage: hv = MonoidPowerSeries(mpsm, {1: m([1,0,0]), 2: m([0,0,1])}, mpsm.monoid().filter_all())
573
sage: em = ExpansionModule([hv])
574
sage: list(em._element_to_fourier_expansion_generator(em([1]).fourier_expansion()))
575
[0, 0, 0, 1, 0, 0, 0, 0, 1]
576
"""
577
keys = self._fourier_expansion_indices()
578
579
if isinstance(self.__abstract_basis.universe().coefficient_domain(), Ring) :
580
return (e[k] if k in e else 0 for k in keys)
581
else :
582
return (e[k][i] if k in e else 0 for (i,k) in keys)
583
584
def coordinates(self, x, in_base_ring = True, force_ambigous = False) :
585
r"""
586
The coordinates in ``self`` of an element either of the following:
587
- An element of a submodule.
588
- An expansion in the parent of the basis' expansions.
589
590
INPUT:
591
- `x` -- Either of the types listed above.
592
- ``in_base_ring`` -- A boolean (default: ``True``); If ``True``
593
enforce the result to be definied over the
594
base ring of ``self``.
595
- ``force_ambigous`` -- A boolean (default: ``False``); If ``True``
596
also return the solutions that are not unique.
597
598
OUTPUT:
599
A list of elements in the base ring or and extension of it.
600
601
NOTE:
602
If the Fourier expansion of `x` lakes sufficient precision the
603
expansions associated to ``self`` will be truncated.
604
605
TESTS::
606
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
607
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
608
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
609
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
610
sage: em = ExpansionModule(Sequence([emps.one_element()]))
611
sage: em.coordinates(2 * emps.one_element())
612
[2]
613
sage: m = FreeModule(QQ, 3)
614
sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))
615
sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0]), 2: m([0,0,1])}}, empsm.action().filter_all())
616
sage: em = ExpansionModule(Sequence([hv]))
617
sage: em.coordinates(2 * hv)
618
[2]
619
sage: mps = MonoidPowerSeriesRing(ZZ, NNMonoid())
620
sage: em = ExpansionModule([mps.one_element()])
621
sage: em.coordinates(3 * mps.one_element())
622
[3]
623
sage: mpsm = MonoidPowerSeriesModule(m, NNMonoid())
624
sage: hv = MonoidPowerSeries(mpsm, {1: m([1,0,0]), 2: m([0,0,1])}, mpsm.monoid().filter_all())
625
sage: em = ExpansionModule([hv])
626
sage: em.coordinates(2 * hv)
627
[2]
628
sage: em = ExpansionModule(Sequence([emps.one_element()]))
629
sage: h = EquivariantMonoidPowerSeries(emps, {}, emps.action().filter_all())
630
sage: em.coordinates(h)
631
[0]
632
sage: em.coordinates(1 / 2 * emps.one_element())
633
Traceback (most recent call last):
634
...
635
ArithmeticError: Equivariant monoid power series in Ring of equivariant monoid power series over NN is not contained in this space.
636
sage: em.coordinates(1 / 2 * emps.one_element(), in_base_ring = False )
637
[1/2]
638
sage: K.<rho> = CyclotomicField(6)
639
sage: em.coordinates(rho * emps.one_element(), in_base_ring = False)
640
[zeta6]
641
sage: h = EquivariantMonoidPowerSeries(emps, {emps.characters().one_element(): {1: 2, 2: 3}}, emps.action().filter_all())
642
sage: em.coordinates(h)
643
Traceback (most recent call last):
644
...
645
ArithmeticError: Equivariant monoid power series in Ring of equivariant monoid power series over NN is not contained in this space.
646
sage: em.coordinates(hv)
647
Traceback (most recent call last):
648
...
649
ArithmeticError: No coordinates for Monoid power series in Module of monoid power series over NN with action.
650
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))
651
sage: em.coordinates(2 * emps.one_element())
652
Traceback (most recent call last):
653
...
654
ValueError: Not unambigous coordinates available in this submodule.
655
sage: h = EquivariantMonoidPowerSeries(emps, {}, emps.action().filter_all())
656
sage: em = ExpansionModule(Sequence([h]))
657
sage: em.coordinates(emps.one_element())
658
Traceback (most recent call last):
659
...
660
ValueError: Not unambigous coordinates available in this submodule.
661
"""
662
if isinstance(x, Element) :
663
P = x.parent()
664
if P is self :
665
if self.ambient_module() is self :
666
return x.list()
667
else :
668
return list(self.coordinate_vector(x))
669
670
671
if isinstance(P, (EquivariantMonoidPowerSeriesAmbient_abstract,
672
MonoidPowerSeriesAmbient_abstract)) :
673
674
if not force_ambigous and \
675
not self._check_precision() :
676
raise ValueError( "Not unambigous coordinates available in this submodule." )
677
678
if P != self.__abstract_basis.universe() :
679
try :
680
Pnew = pushout(self.__abstract_basis.universe(), P)
681
except TypeError :
682
raise ArithmeticError( "No coordinates for %s." % (x,) )
683
684
if isinstance(Pnew, EquivariantMonoidPowerSeriesAmbient_abstract) \
685
and Pnew.representation().base_ring() == Pnew.representation().codomain() :
686
A = Pnew.base_ring()
687
elif isinstance(Pnew, MonoidPowerSeriesAmbient_abstract) \
688
and isinstance(Pnew.coefficient_domain(), Ring) :
689
A = Pnew.base_ring()
690
else :
691
A = Pnew.base_ring().base_ring()
692
693
try :
694
x = Pnew(x)
695
except TypeError :
696
raise ArithmeticError( "No coordinates for %s." % (x,) )
697
else :
698
A = self.base_ring()
699
700
# check those components of x, which have to be zero
701
if not self._non_zero_characters() is None :
702
x._cleanup_coefficients()
703
if set( x.non_zero_components() ) - set( self._non_zero_characters() ) != set() :
704
raise ArithmeticError( "%s is not contained in this space." % (x,) )
705
706
if in_base_ring :
707
fe_matrix = self.fourier_expansion_homomorphism().matrix().transpose()
708
x_fe_vector = matrix( A, fe_matrix.nrows(),
709
list(self._element_to_fourier_expansion_generator(x)) )
710
else :
711
fe_matrix = self._fourier_expansion_matrix_over_fraction_field().transpose()
712
x_fe_vector = matrix( A, fe_matrix.nrows(),
713
list(self._element_to_fourier_expansion_generator(x)) )
714
715
if self._non_zero_characters() is None :
716
if isinstance(self.__abstract_basis.universe().coefficient_domain(), Ring) :
717
valid_indices = [ i for (i,k) in enumerate(self._fourier_expansion_indices())
718
if k in x.precision() ]
719
else :
720
valid_indices = [ i for (i,(_,k)) in enumerate(self._fourier_expansion_indices())
721
if k in x.precision() ]
722
else :
723
if isinstance(self.__abstract_basis.universe().coefficient_domain(), Ring) :
724
valid_indices = [ i for (i,(_,k)) in enumerate(self._fourier_expansion_indices())
725
if k in x.precision() ]
726
else :
727
valid_indices = [ i for (i,(_,(_,k))) in enumerate(self._fourier_expansion_indices())
728
if k in x.precision() ]
729
730
fe_matrix = fe_matrix.matrix_from_rows(valid_indices)
731
x_fe_vector = x_fe_vector.matrix_from_rows(valid_indices)
732
fe_matrix = matrix(A, fe_matrix)
733
734
## TODO: use linbox
735
try :
736
## TODO: We deactivate the magma interface as it is almost never used and
737
## it is in bad shape
738
if True or (A is not ZZ and A is not QQ) :
739
raise TypeError
740
741
magma_fe_matrix = magma(fe_matrix.transpose())
742
743
if not force_ambigous and \
744
len(valid_indices) != self.fourier_expansion_homomorphism().matrix().ncols() and \
745
magma_fe_matrix.Rank() != self.rank() :
746
raise ValueError( "No unambigous coordinates available." )
747
748
coords = magma(fe_matrix.transpose()).Solution(magma(x_fe_vector.transpose())).sage()
749
coords = coords.row(0)
750
except TypeError, msg :
751
if "Runtime error in 'Solution': No solution exists" in msg :
752
raise ArithmeticError( "%s is not contained in this space." % (x,) )
753
754
if not force_ambigous and \
755
len(valid_indices) != self.fourier_expansion_homomorphism().matrix().ncols() and \
756
fe_matrix.rank() != self.rank() :
757
raise ValueError( "No unambigous coordinates available." )
758
759
try :
760
coords = fe_matrix.solve_right(x_fe_vector)
761
except ValueError, msg :
762
raise ArithmeticError( "%s is not contained in this space, %s" % (x, msg) )
763
coords = coords.column(0)
764
765
if self.precision() != self._bounding_precision() and \
766
not x.precision() < self._bounding_precision() :
767
if not self.change_ring(A)(list(coords)).fourier_expansion() == x :
768
raise ArithmeticError( "%s is not contained in this space." % (x,) )
769
770
if in_base_ring :
771
try :
772
return [self.base_ring()(c) for c in coords]
773
except TypeError :
774
raise ArithmeticError( "%s is not contained in this space." % (x,) )
775
else :
776
return list(coords)
777
778
#! elif isinstance(P, (EquivariantMonoidPowerSeriesAmbient_abstract,
779
# MonoidPowerSeriesAmbient_abstract)) :
780
#! if isinstance(x, (tuple, Element)) :
781
782
raise ArithmeticError( "No coordinates for %s." % (x,) )
783
784
def _sparse_module(self):
785
r"""
786
TESTS::
787
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
788
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
789
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
790
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
791
sage: em = ExpansionModule(Sequence([emps.one_element()]))
792
sage: em._sparse_module()
793
Traceback (most recent call last):
794
...
795
NotImplementedError
796
"""
797
raise NotImplementedError
798
799
def _dense_module(self):
800
r"""
801
TESTS::
802
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
803
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
804
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
805
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
806
sage: em = ExpansionModule(Sequence([emps.one_element()]))
807
sage: em._dense_module() is em
808
True
809
"""
810
return self
811
812
def _repr_(self) :
813
r"""
814
TESTS::
815
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
816
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
817
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
818
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
819
sage: ExpansionModule(Sequence([emps.one_element()]))
820
Module of Fourier expansions in Ring of equivariant monoid power series over NN
821
"""
822
return "Module of Fourier expansions in %s" % (self.__abstract_basis.universe(),)
823
824
def _latex_(self) :
825
r"""
826
TESTS::
827
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
828
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
829
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
830
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
831
sage: latex( ExpansionModule(Sequence([emps.one_element()])) )
832
\text{Module of Fourier expansions in }\text{Ring of equivariant monoid power series over }\Bold{N}
833
"""
834
return r"\text{Module of Fourier expansions in }%s" % (latex(self.__abstract_basis.universe()),)
835
836
837
class ExpansionModule_generic ( ExpansionModule_abstract, FreeModule_generic ) :
838
r"""
839
A generic module of abstract elements with Fourier expansions attached to.
840
The base ring has to be an integral domain.
841
"""
842
843
def __init__(self, basis, degree, **kwds) :
844
r"""
845
INPUT:
846
- ``basis`` -- A sequence of (equivariant) monoid power series.
847
- ``degree`` -- An integer; The ambient's module dimension.
848
- ``kwds`` -- A keyword dictionary that will be forwarded to
849
initialization of the underlying free module.
850
851
NOTE:
852
The base ring of the expansions' parent must be an integral
853
domain.
854
855
TESTS::
856
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
857
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
858
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_generic, ExpansionModuleVector_generic
859
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
860
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
861
sage: em = ExpansionModule_generic(Sequence([emps.one_element()]), 2)
862
sage: em = ExpansionModule_generic(Sequence([emps.one_element()]), 2, _element_class = ExpansionModuleVector_generic )
863
"""
864
if not hasattr(self, '_element_class') :
865
if '_element_class' in kwds :
866
self._element_class = kwds['_element_class']
867
else :
868
self._element_class = ExpansionModuleVector_generic
869
870
ExpansionModule_abstract.__init__(self, basis)
871
FreeModule_generic.__init__(self, basis.universe().base_ring(), len(basis), degree, sparse = False)
872
873
def gen(self, i) :
874
r"""
875
The `i`-th generator of the module.
876
877
INPUT:
878
- `i` -- An integer.
879
880
OUTPUT:
881
An element of ``self``.
882
883
TESTS::
884
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
885
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
886
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_generic
887
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
888
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
889
sage: em = ExpansionModule_generic(Sequence([emps.one_element()]), 1)
890
sage: em.gen(0)
891
Traceback (most recent call last):
892
...
893
NotImplementedError
894
"""
895
raise NotImplementedError
896
897
def basis(self) :
898
r"""
899
A basis of ``self``.
900
901
OUTPUT:
902
A list of elements of ``self``.
903
904
TESTS::
905
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
906
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
907
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_generic
908
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
909
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
910
sage: em = ExpansionModule_generic(Sequence([emps.one_element()]), 1)
911
sage: em.basis()
912
Traceback (most recent call last):
913
...
914
NotImplementedError
915
"""
916
raise NotImplementedError
917
918
def change_ring(self, R):
919
r"""
920
Return the ambient expansion module over `R` with the same basis as ``self``.
921
922
INPUT:
923
- `R` -- A ring.
924
925
OUTPUT:
926
An instance of :class:~`.ExpansionModule_generic`.
927
928
TESTS::
929
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
930
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
931
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
932
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_generic
933
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
934
sage: em = ExpansionModule_generic(Sequence([emps.one_element()]), 2)
935
sage: em.change_ring(ZZ) is em
936
True
937
sage: em.change_ring(QQ).base_ring()
938
Rational Field
939
"""
940
if self.base_ring() == R :
941
return self
942
943
R = pushout(self._abstract_basis().universe(), R)
944
945
return ExpansionModule_generic(Sequence(self._abstract_basis(), universe = R), self.degree(), _element_class = self._element_class)
946
947
#===============================================================================
948
# _fourier_expansion_kernel
949
#
950
# This will be used in ExpansionModule_ambient_pid and
951
# ExpansionModule_submodule_pid
952
#===============================================================================
953
954
def _fourier_expansion_kernel(self) :
955
r"""
956
The kernel of the Fourier expansion morphism.
957
958
OUTPUT:
959
A module over the basis ring.
960
961
SEE:
962
:meth:~`.ExpansionModule_abstract.fourier_expansion_homomorphism`.
963
964
TESTS::
965
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
966
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
967
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
968
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
969
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))
970
sage: em.fourier_expansion_kernel()
971
Free module of degree 3 and rank 2 over Integer Ring
972
Echelon basis matrix:
973
[ 1 0 -1]
974
[ 0 1 -1]
975
sage: em.span([em([1,0,0]), em([1,2,0])]).fourier_expansion_kernel()
976
Free module of degree 2 and rank 1 over Integer Ring
977
Echelon basis matrix:
978
[ 3 -1]
979
"""
980
return self.fourier_expansion_homomorphism().matrix().left_kernel()
981
982
#===============================================================================
983
# _span
984
#
985
# This will be used in ExpansionModule_ambient_pid and
986
# ExpansionModule_submodule_pid
987
#===============================================================================
988
989
def _span( self, gens, base_ring = None, check = True, already_echelonized = False ) :
990
r"""
991
The expansion submodule spanned by ``gens``.
992
993
INPUT:
994
- ``gens`` -- A list, tuple or sequence of module elements.
995
- ``base_ring`` -- A ring or ``None`` (default: ``None``); If ``None``
996
the base ring of ``self`` will be used.
997
- ``check`` -- A boolean (default: ``True``); If ``True`` check
998
whether the generators are appropriately coerced.
999
- ``already_echelonized`` -- A boolean (default: ``False``); If ``True``
1000
the generators are already in echelon form
1001
with respect to the ambient's basis.
1002
1003
OUTPUT:
1004
An instance of :class:~`.ExpansionModule_submodule_pid`.
1005
1006
TESTS::
1007
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
1008
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
1009
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
1010
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
1011
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))
1012
sage: em.span([em([1,0,0]), em([1,2,0])])
1013
Module of Fourier expansions in Ring of equivariant monoid power series over NN
1014
sage: em.span([em([1,0,0]), em([1,2,0])]).span([em([1,0,0])])
1015
Module of Fourier expansions in Ring of equivariant monoid power series over NN
1016
"""
1017
if is_FreeModule(gens):
1018
gens = gens.gens()
1019
if not isinstance(gens, (list, tuple, Sequence)):
1020
raise TypeError, "Argument gens (= %s) must be a list, tuple, or sequence." % (gens,)
1021
1022
if base_ring is None or base_ring == self.base_ring() :
1023
gens = Sequence(gens, check = check, universe = self.ambient_module())
1024
1025
return ExpansionModule_submodule_pid(self.ambient_module(), gens)
1026
else:
1027
try:
1028
M = self.ambient_module().change_ring(base_ring)
1029
except TypeError:
1030
raise ValueError, "Argument base_ring (= %s) is not compatible " % (base_ring,) + \
1031
"with the base field (= %s)." % (self.base_field(),)
1032
try:
1033
return M.span(gens)
1034
except TypeError:
1035
raise ValueError, "Argument gens (= %s) is not compatible " % (gens,) + \
1036
"with base_ring (= %s)." % (base_ring,)
1037
1038
#===============================================================================
1039
# ExpansionModule_ambient_pid
1040
#===============================================================================
1041
1042
class ExpansionModule_ambient_pid ( ExpansionModule_abstract, FreeModule_ambient_pid ) :
1043
r"""
1044
An ambient module of expansions over a principal ideal domain.
1045
"""
1046
1047
def __init__(self, basis, _element_class = None, **kwds) :
1048
r"""
1049
INPUT:
1050
- ``basis`` -- A list or sequence of (equivariant) monoid power series.
1051
- ``element_class`` -- A type or ``None`` (default: ``None``); The element class
1052
attached to ``self``. If ``None`` :class:~`.ExpansionModuleVector_generic`
1053
will be used.
1054
1055
TESTS::
1056
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
1057
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
1058
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
1059
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid, ExpansionModuleVector_generic
1060
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
1061
sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))
1062
sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]), _element_class = ExpansionModuleVector_generic)
1063
"""
1064
if not hasattr(self, '_element_class') :
1065
if not _element_class is None :
1066
self._element_class = _element_class
1067
else :
1068
self._element_class = ExpansionModuleVector_generic
1069
1070
if isinstance(basis.universe(), EquivariantMonoidPowerSeriesAmbient_abstract) \
1071
and basis.universe().representation().base_ring() == basis.universe().representation().codomain() :
1072
base_ring = basis.universe().base_ring()
1073
elif isinstance(basis.universe(), MonoidPowerSeriesAmbient_abstract) \
1074
and isinstance(basis.universe().coefficient_domain(), Ring) :
1075
base_ring = basis.universe().base_ring()
1076
else :
1077
base_ring = basis.universe().base_ring().base_ring()
1078
1079
ExpansionModule_abstract.__init__(self, basis)
1080
FreeModule_ambient_pid.__init__(self, base_ring, len(basis))
1081
1082
global _fourier_expansion_kernel, _span
1083
fourier_expansion_kernel = _fourier_expansion_kernel
1084
span = _span
1085
1086
def gen(self, i) :
1087
r"""
1088
The `i`-th generator of the module.
1089
1090
INPUT:
1091
- `i` -- An integer.
1092
1093
OUTPUT:
1094
An element of ``self``.
1095
1096
TESTS::
1097
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
1098
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
1099
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
1100
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid
1101
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
1102
sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))
1103
sage: em.gen(0)
1104
(1, 0, 0)
1105
"""
1106
return self._element_class(self, FreeModule_ambient_pid.gen(self, i))
1107
1108
def basis(self) :
1109
r"""
1110
A basis of ``self``.
1111
1112
OUTPUT:
1113
A list of elements of ``self``.
1114
1115
TESTS::
1116
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
1117
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
1118
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
1119
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid
1120
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
1121
sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))
1122
sage: em.basis()
1123
[(1, 0, 0), (0, 1, 0), (0, 0, 1)]
1124
"""
1125
return map(lambda b: self._element_class(self, b), FreeModule_ambient_pid.basis(self))
1126
1127
def change_ring(self, R):
1128
r"""
1129
Return the ambient expansion module over `R` with the same basis as ``self``.
1130
1131
INPUT:
1132
- `R` -- A ring.
1133
1134
OUTPUT:
1135
An instance of :class:~`.ExpansionModule_ambient_pid`.
1136
1137
TESTS::
1138
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
1139
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
1140
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
1141
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid
1142
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
1143
sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))
1144
sage: em.change_ring(ZZ) is em
1145
True
1146
sage: emq = em.change_ring(QQ)
1147
sage: emq.base_ring()
1148
Rational Field
1149
sage: emq.ambient_module() is emq
1150
True
1151
"""
1152
if self.base_ring() == R :
1153
return self
1154
1155
R = pushout(self._abstract_basis().universe(), R)
1156
1157
return ExpansionModule_ambient_pid(Sequence(self._abstract_basis(), universe = R), _element_class = self._element_class)
1158
1159
def ambient_module(self) :
1160
r"""
1161
Return the ambient module of ``self``.
1162
1163
OUTPUT:
1164
An instance of :class:~`.ExpansionModule_ambient_pid`.
1165
1166
TESTS::
1167
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
1168
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
1169
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
1170
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid
1171
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
1172
sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))
1173
sage: em.ambient_module() is em
1174
True
1175
"""
1176
return self
1177
1178
#===============================================================================
1179
# ExpansionModule_submodule_pid
1180
#===============================================================================
1181
1182
class ExpansionModule_submodule_pid ( ExpansionModule_abstract, FreeModule_submodule_pid ) :
1183
r"""
1184
A submodule of another module of expansions over a principal ideal domain.
1185
"""
1186
1187
def __init__(self, ambient, gens, _element_class = None, **kwds) :
1188
r"""
1189
INPUT:
1190
- ``ambient`` -- An instance of :class:~`.ExpansionModule_ambient_pid` or :class:~`.ExpansionModule_submodule_pid`.
1191
- ``gens`` -- A list, tuple or sequence of elements of ``ambient``.
1192
- ``element_class`` -- A type or ``None`` (default: ``None``); The element class
1193
attached to ``self``. If ``None`` :class:~`.ExpansionModuleVector_generic`
1194
will be used.
1195
1196
TESTS::
1197
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
1198
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
1199
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
1200
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid, ExpansionModule_submodule_pid, ExpansionModuleVector_generic
1201
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
1202
sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))
1203
sage: ems = ExpansionModule_submodule_pid(em, [em([1,0,0]), em([1,2,0])])
1204
sage: ems = ExpansionModule_submodule_pid(em, [em([1,0,0]), em([1,2,0])], _element_class = ExpansionModuleVector_generic)
1205
"""
1206
if not hasattr(self, '_element_class') :
1207
if not _element_class is None :
1208
self._element_class = _element_class
1209
else :
1210
self._element_class = ExpansionModuleVector_generic
1211
1212
if ambient.precision().is_infinite() :
1213
ExpansionModule_abstract.__init__(self, Sequence( map( lambda g: g.fourier_expansion(), gens ),
1214
universe = ambient._abstract_basis().universe() ))
1215
else :
1216
ExpansionModule_abstract.__init__(self, Sequence( map( lambda g: LazyFourierExpansionEvaluation( ambient._abstract_basis().universe(), g,
1217
ambient.precision() ),
1218
gens ),
1219
universe = ambient._abstract_basis().universe() ))
1220
FreeModule_submodule_pid.__init__(self, ambient, gens)
1221
1222
global _fourier_expansion_kernel, _span
1223
fourier_expansion_kernel = _fourier_expansion_kernel
1224
span = _span
1225
1226
def gen(self, i) :
1227
r"""
1228
The `i`-th generator of the module.
1229
1230
INPUT:
1231
- `i` -- An integer.
1232
1233
OUTPUT:
1234
An element of ``self``.
1235
1236
TESTS::
1237
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
1238
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
1239
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
1240
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid, ExpansionModule_submodule_pid
1241
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
1242
sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))
1243
sage: ems = ExpansionModule_submodule_pid(em, [em([1,0,0]), em([1,2,0])])
1244
sage: ems.gen(0)
1245
(1, 0, 0)
1246
"""
1247
return self._element_class(self, super(ExpansionModule_submodule_pid, self).gen(i).list())
1248
1249
# TODO: The module should be hidden so that we can adopt the category framework
1250
# def basis(self) :
1251
# r"""
1252
# A basis of ``self``.
1253
1254
# OUTPUT:
1255
# A list of elements of ``self``.
1256
1257
# TESTS::
1258
# sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
1259
# sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
1260
# sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
1261
# sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid, ExpansionModule_submodule_pid
1262
# sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
1263
# sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))
1264
# sage: ems = ExpansionModule_submodule_pid(em, [em([1,0,0]), em([1,2,0])])
1265
# sage: ems.basis()
1266
# [(1, 0, 0), (0, 2, 0)]
1267
# """
1268
# return [self._element_class(self, b.list()) for b in super().basis()]
1269
1270
def change_ring(self, R):
1271
r"""
1272
Return the ambient expansion module over `R` with the same basis as ``self``.
1273
1274
INPUT:
1275
- `R` -- A ring.
1276
1277
OUTPUT:
1278
An instance of :class:~`.ExpansionModule_ambient_pid`.
1279
TESTS::
1280
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
1281
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
1282
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
1283
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid, ExpansionModule_submodule_pid
1284
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
1285
sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))
1286
sage: ems = ExpansionModule_submodule_pid(em, [em([1,0,0]), em([1,2,0])])
1287
sage: emc = ems.change_ring(ZZ)
1288
sage: emc.ambient_module() is emc
1289
True
1290
sage: emc = ems.change_ring(QQ)
1291
sage: emc.ambient_module() is emc
1292
True
1293
sage: emc.base_ring()
1294
Rational Field
1295
"""
1296
if self.base_ring() == R :
1297
return ExpansionModule_ambient_pid(self._abstract_basis(), _element_class = self._element_class)
1298
1299
R = pushout(self._abstract_basis().universe(), R)
1300
1301
return ExpansionModule_ambient_pid(Sequence(self._abstract_basis(), universe = R), _element_class = self._element_class)
1302
1303
#===============================================================================
1304
# ExpansionModuleVector_generic
1305
#===============================================================================
1306
1307
class ExpansionModuleVector_generic ( FreeModuleElement_generic_dense, FourierExpansionWrapper ) :
1308
r"""
1309
A generic implementation of an element in a module of expansions.
1310
"""
1311
1312
def __init__(self, parent, x, coerce = True, copy = True) :
1313
r"""
1314
INPUT:
1315
- ``parent`` -- An instance of :class:~`.ExpansionModule_abstract`.
1316
- `x` -- A list or tuple of integers or an element that admits coordinates
1317
in ``parent``.
1318
- ``coerce`` -- A boolean (default: ``True``); If ``True`` coerce coordinates into the base ring.
1319
- ``copy`` -- A boolean (default: ``True``); If ``True`` store a copy of the coordinates.
1320
1321
TESTS::
1322
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
1323
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
1324
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
1325
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModuleVector_generic
1326
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
1327
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))
1328
sage: ExpansionModuleVector_generic(em, [1,0,2])
1329
(1, 0, 2)
1330
"""
1331
if not isinstance(x, (list, tuple)) and x != 0 :
1332
x = parent.ambient_module().coordinates(x)
1333
coerce = False
1334
copy = False
1335
1336
FreeModuleElement_generic_dense.__init__(self, parent, x, coerce, copy)
1337
1338
def _add_(left, right) :
1339
r"""
1340
TESTS::
1341
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
1342
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
1343
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
1344
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
1345
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))
1346
sage: em.0 + em.1
1347
(1, 1, 0)
1348
"""
1349
return left.parent()._element_class(left.parent(), FreeModuleElement_generic_dense._add_(left, right))
1350
1351
def __copy__(self) :
1352
r"""
1353
Return a copy of ``self``.
1354
1355
OUTPUT:
1356
An instance of :class:~`.ExpansionModuleVector_generic`.
1357
1358
TESTS::
1359
sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *
1360
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *
1361
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
1362
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModuleVector_generic
1363
sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))
1364
sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))
1365
sage: copy(ExpansionModuleVector_generic(em, [1,0,2])) == ExpansionModuleVector_generic(em, [1,0,2])
1366
True
1367
"""
1368
return ExpansionModuleVector_generic( self.parent(), self.list(), coerce = False, copy = True)
1369
1370