Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241849 views
1
r"""
2
Functors for ring and modules of graded expansions.
3
4
AUTHOR :
5
-- Martin Raum (2009 - 07 - 27) Initial version
6
"""
7
8
#===============================================================================
9
#
10
# Copyright (C) 2009 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 itertools import groupby, dropwhile
28
from sage.algebras.algebra import Algebra
29
from sage.categories.morphism import Morphism
30
from sage.categories.pushout import ConstructionFunctor, pushout
31
from sage.categories.rings import Rings
32
from sage.misc.misc import prod
33
from sage.modules.module import Module
34
from sage.rings.integer import Integer
35
from sage.structure.sequence import Sequence
36
import operator
37
38
#===============================================================================
39
# GradedExpansionFunctor
40
#===============================================================================
41
42
class GradedExpansionFunctor ( ConstructionFunctor ) :
43
r"""
44
Constructing a graded expansion ring or module from a base ring.
45
"""
46
47
rank = 10
48
49
def __init__( self, base_ring_generators, generators,
50
relations, grading, all_relations = True, reduce_before_evaluating = True ) :
51
r"""
52
INPUT:
53
- ``base_ring_generators`` -- A sequence of (equivariant) monoid power series with
54
coefficient domain the base ring of the coefficient
55
domain of the generators or ``None``.
56
- ``generators`` -- A sequence of (equivariant) monoid power series; The generators
57
of the ambient over the ring generated by the base ring
58
generators.
59
- ``relations`` -- An ideal in a polynomial ring with ``len(base_ring_generators) + len(generators)``
60
variables.
61
- ``grading`` -- A grading deriving from :class:~`fourier_expansion_framework.gradedexpansions.gradedexpansion_grading`;
62
A grading for the polynomial ring of the relations.
63
- ``all_relations`` -- A boolean (default: ``True``); If ``True`` the relations given
64
for the polynomial ring are all relations that the Fourier
65
expansion have.
66
- ``reduce_before_evaluating`` -- A boolean (default: ``True``); If ``True`` any monomial
67
will be Groebner reduced before the Fourier expansion
68
is calculated.
69
70
NOTE:
71
The grading must respect the relations of the generators.
72
73
TESTS::
74
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
75
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *
76
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *
77
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_grading import DegreeGrading
78
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_functor import *
79
sage: mps = MonoidPowerSeriesRing(QQ, NNMonoid(False))
80
sage: funct = GradedExpansionFunctor(Sequence([MonoidPowerSeries(mps, {1: 1}, mps.monoid().filter(4))]), Sequence([MonoidPowerSeries(mps, {1: 1, 2: 3}, mps.monoid().filter(4))]), PolynomialRing(QQ, ['a', 'b']).ideal(0), DegreeGrading((1,2)))
81
"""
82
if grading.ngens() != relations.ring().ngens() :
83
raise ValueError( "Grading must have the same number of variables as the relations' polynomial ring." )
84
85
self.__relations = relations
86
self.__grading = grading
87
self.__all_relations = all_relations
88
self.__reduce_before_evaluating = reduce_before_evaluating
89
90
self.__gen_expansions = Sequence(generators)
91
if base_ring_generators is None :
92
self.__base_gen_expansions = Sequence([], universe = self.__gen_expansions.universe().base_ring())
93
else :
94
self.__base_gen_expansions = Sequence(base_ring_generators)
95
96
if len(self.__base_gen_expansions) == 0 :
97
scalar_ring = self.__gen_expansions.universe().base_ring()
98
if self.__gen_expansions.universe().coefficient_domain() != self.__gen_expansions.universe().base_ring() :
99
scalar_ring = self.__gen_expansions.universe().base_ring().base_ring()
100
else :
101
scalar_ring = self.__gen_expansions.universe().base_ring()
102
else :
103
scalar_ring = self.__base_gen_expansions.universe().base_ring()
104
105
if not relations.base_ring().has_coerce_map_from(scalar_ring) :
106
raise ValueError( "The generators must be defined over the base ring of relations" )
107
108
if not isinstance(self.__gen_expansions.universe(), Algebra) and \
109
not isinstance(self.__gen_expansions.universe(), Module) :
110
raise TypeError( "The generators' universe must be an algebra or a module" )
111
112
ConstructionFunctor.__init__( self, Rings(), Rings() )
113
114
def __call__(self, R) :
115
r"""
116
The graded expansion ring with the given generators over the base
117
ring `R`.
118
119
INPUT:
120
- `R` -- A ring.
121
122
OUTPUT:
123
An instance of :class:~`fourier_expansion_framework.gradedexpansions.gradedexpansion_ambient.GradedExpansion_abstract`.
124
125
NOTE:
126
The ring of Fourier expansions given by the generators associated
127
with this functor must admit a base extension to `R`.
128
129
TESTS::
130
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
131
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *
132
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_module import *
133
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *
134
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_grading import DegreeGrading
135
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_functor import *
136
sage: K.<rho> = CyclotomicField(6)
137
sage: mps = MonoidPowerSeriesRing(QQ, NNMonoid(False))
138
sage: funct = GradedExpansionFunctor(Sequence([MonoidPowerSeries(mps, {1: 1}, mps.monoid().filter(4))]), Sequence([MonoidPowerSeries(mps, {1: 1, 2: 3}, mps.monoid().filter(4))]), PolynomialRing(QQ, ['a', 'b']).ideal(0), DegreeGrading((1,2)))
139
sage: funct(K)
140
Graded expansion ring with generators b
141
sage: m = FreeModule(QQ, 3)
142
sage: mpsm = MonoidPowerSeriesModule(m, NNMonoid(False))
143
sage: mps = mpsm.base_ring()
144
sage: funct = GradedExpansionFunctor(None, Sequence([MonoidPowerSeries(mpsm, {1 : m([1,2,3]), 2 : m([3,-3,2])}, mpsm.monoid().filter(4)), MonoidPowerSeries(mpsm, {1 : m([2,-1,-1]), 2 : m([1,0,0])}, mpsm.monoid().filter(4))]), PolynomialRing(QQ, ['a', 'b']).ideal(0), DegreeGrading((1,2)))
145
sage: funct(K)
146
Graded expansion module with generators a, b
147
"""
148
from gradedexpansion_ring import GradedExpansionRing_class
149
from gradedexpansion_module import GradedExpansionModule_class
150
151
R = pushout(self.__relations.ring(), R)
152
rel = R.ideal(self.__relations.gens())
153
154
if isinstance(self.__gen_expansions.universe(), Algebra) :
155
return GradedExpansionRing_class( self.__base_gen_expansions, self.__gen_expansions,
156
rel, self.__grading, self.__all_relations, self.__reduce_before_evaluating )
157
elif isinstance(self.__gen_expansions.universe(), Module) :
158
return GradedExpansionModule_class( self.__base_gen_expansions, self.__gen_expansions,
159
rel, self.__grading, self.__all_relations, self.__reduce_before_evaluating )
160
161
raise RuntimeError( "The generators' universe must be an algebra or a module." )
162
163
def __cmp__(self, other) :
164
r"""
165
TESTS::
166
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
167
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *
168
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *
169
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_grading import DegreeGrading
170
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_functor import *
171
sage: mps = MonoidPowerSeriesRing(QQ, NNMonoid(False))
172
sage: funct = GradedExpansionFunctor(Sequence([MonoidPowerSeries(mps, {1: 1}, mps.monoid().filter(4))]), Sequence([MonoidPowerSeries(mps, {1: 1, 2: 3}, mps.monoid().filter(4))]), PolynomialRing(QQ, ['a', 'b']).ideal(0), DegreeGrading((1,2)))
173
sage: funct == GradedExpansionFunctor(Sequence([MonoidPowerSeries(mps, {1: 1}, mps.monoid().filter(4))]), Sequence([MonoidPowerSeries(mps, {1: 1, 2: 3}, mps.monoid().filter(4))]), PolynomialRing(QQ, ['a', 'b']).ideal(0), DegreeGrading((1,2)))
174
True
175
sage: funct == GradedExpansionFunctor(None, Sequence([MonoidPowerSeries(mps, {1 : 4, 2 : 3}, mps.monoid().filter(4)), MonoidPowerSeries(mps, {1 : 1, 2 : 3}, mps.monoid().filter(4))]), PolynomialRing(QQ, ['a', 'b']).ideal(0), DegreeGrading((1,3)))
176
False
177
sage: P.<a,b> = PolynomialRing(QQ)
178
sage: funct == GradedExpansionFunctor(None, Sequence([MonoidPowerSeries(mps, {1 : 4, 2 : 3}, mps.monoid().filter(4)), MonoidPowerSeries(mps, {1 : 1, 2 : 3}, mps.monoid().filter(4))]), P.ideal(a^2 - b), DegreeGrading((1,2)))
179
False
180
sage: funct == GradedExpansionFunctor(None, Sequence([MonoidPowerSeries(mps, {1 : 4, 2 : 3}, mps.monoid().filter(4)), MonoidPowerSeries(mps, {1 : 1, 2 : 4}, mps.monoid().filter(4))]), PolynomialRing(QQ, ['a', 'b']).ideal(0), DegreeGrading((1,2)))
181
False
182
sage: funct == GradedExpansionFunctor(Sequence([MonoidPowerSeries(mps, {1 : 4}, mps.monoid().filter(4))]), Sequence([MonoidPowerSeries(mps, {1 : 4, 2 : 3}, mps.monoid().filter(4)), MonoidPowerSeries(mps, {1 : 1, 2 : 3}, mps.monoid().filter(4))]), PolynomialRing(QQ, ['a', 'b', 'c']).ideal(0), DegreeGrading((1,2,2)))
183
False
184
"""
185
c = cmp(type(self), type(other))
186
if c == 0 :
187
c = cmp(self.__relations, other.__relations)
188
if c == 0 :
189
c = cmp(self.__all_relations, other.__all_relations)
190
if c == 0 :
191
c = cmp(self.__grading, other.__grading)
192
if c == 0 :
193
c = cmp(self.__base_gen_expansions, other.__base_gen_expansions)
194
if c == 0 :
195
c = cmp(self.__gen_expansions, other.__gen_expansions)
196
197
return c
198
199
def merge(self, other) :
200
r"""
201
TESTS::
202
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
203
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *
204
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *
205
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_grading import DegreeGrading
206
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_functor import *
207
sage: mps = MonoidPowerSeriesRing(QQ, NNMonoid(False))
208
sage: funct = GradedExpansionFunctor(Sequence([MonoidPowerSeries(mps, {1: 1}, mps.monoid().filter(4))]), Sequence([MonoidPowerSeries(mps, {1: 1, 2: 3}, mps.monoid().filter(4))]), PolynomialRing(QQ, ['a', 'b']).ideal(0), DegreeGrading((1,2)))
209
sage: funct.merge(funct) is None
210
False
211
sage: funct2 = GradedExpansionFunctor(Sequence([MonoidPowerSeries(mps, {1: 1}, mps.monoid().filter(4))]), Sequence([MonoidPowerSeries(mps, {1: 1, 2: 3}, mps.monoid().filter(4))]), PolynomialRing(QQ, ['a', 'b']).ideal(0), DegreeGrading((3,2)))
212
sage: funct.merge(funct2) is None
213
True
214
sage: funct2 = GradedExpansionFunctor(Sequence([MonoidPowerSeries(mps, {1: 1}, mps.monoid().filter(4))]), Sequence([MonoidPowerSeries(mps, {1: 1, 2: 2}, mps.monoid().filter(4))]), PolynomialRing(QQ, ['a', 'b']).ideal(0), DegreeGrading((1,2)))
215
sage: funct.merge(funct2) is None
216
True
217
sage: K.<rho> = CyclotomicField(6)
218
sage: funct2 = GradedExpansionFunctor(Sequence([MonoidPowerSeries(mps, {1: 1}, mps.monoid().filter(4))]), Sequence([MonoidPowerSeries(mps, {1: 1, 2: 3}, mps.monoid().filter(4))]), PolynomialRing(K, ['a', 'b']).ideal(0), DegreeGrading((1,2)))
219
sage: funct2.merge(funct) is None
220
False
221
"""
222
#TODO: Implement merging of base rings
223
if self == other :
224
return self
225
226
if self.__all_relations != other.__all_relations or \
227
self.__grading != other.__grading or \
228
self.__base_gen_expansions != other.__base_gen_expansions or \
229
self.__gen_expansions != other.__gen_expansions :
230
return None
231
232
if self.__relations.ring().has_coerce_map_from(other.__relations.ring()) and \
233
self.__relations == self.__relations.ring().ideal(other.__relations.gens()) :
234
return self
235
236
return None
237
238
#===============================================================================
239
# GradedExpansionBaseringInjection
240
#===============================================================================
241
242
class GradedExpansionBaseringInjection ( Morphism ) :
243
r"""
244
The injection of the base ring into a ring of graded expansions.
245
"""
246
247
def __init__(self, domain, codomain ) :
248
r"""
249
INPUT:
250
- ``domain`` -- A ring.
251
- ``codomain`` -- A ring of graded expansions.
252
253
TESTS::
254
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
255
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *
256
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *
257
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_grading import DegreeGrading
258
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_ring import *
259
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_functor import *
260
sage: mps = MonoidPowerSeriesRing(QQ, NNMonoid(False))
261
sage: ger = GradedExpansionRing_class(None, Sequence([MonoidPowerSeries(mps, {1: 1}, mps.monoid().filter(4)), MonoidPowerSeries(mps, {1: 1, 2: 3}, mps.monoid().filter(4))]), PolynomialRing(QQ, ['a', 'b']).ideal(0), DegreeGrading((1,2)))
262
sage: GradedExpansionBaseringInjection(QQ, ger)
263
Base ring injection of Graded expansion ring with generators a, b morphism:
264
From: Rational Field
265
To: Graded expansion ring with generators a, b
266
"""
267
Morphism.__init__(self, domain, codomain)
268
269
self._repr_type_str = "Base ring injection of %s" % (codomain,)
270
271
def _call_(self, x) :
272
r"""
273
INPUT:
274
- `x` -- An element of the domain.
275
276
OUTPUT:
277
An element of the codomain.
278
279
TESTS::
280
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
281
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *
282
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *
283
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_grading import DegreeGrading
284
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_ring import *
285
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_functor import *
286
sage: mps = MonoidPowerSeriesRing(QQ, NNMonoid(False))
287
sage: ger = GradedExpansionRing_class(Sequence([MonoidPowerSeries(mps, {1: 1}, mps.monoid().filter(4))]), Sequence([MonoidPowerSeries(mps, {1: 1, 2: 3}, mps.monoid().filter(4))]), PolynomialRing(QQ, ['a', 'b']).ideal(0), DegreeGrading((1,2)))
288
sage: inj = GradedExpansionBaseringInjection(ger.base_ring(), ger)
289
sage: inj(ger.base_ring()(2))
290
Graded expansion 2
291
"""
292
return self.codomain()._element_constructor_(x)
293
294
def _call_with_args(self, x, *args, **kwds):
295
r"""
296
INPUT:
297
- `x` -- An element of the domain.
298
- `args`` -- Will be forwarded to the codomain's element constructor.
299
- ``kwds`` -- Will be forwarded to the codomain's element constructor.
300
301
OUTPUT:
302
An element of the codomain.
303
304
TESTS::
305
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
306
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *
307
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *
308
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_grading import DegreeGrading
309
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_ring import *
310
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_functor import *
311
sage: mps = MonoidPowerSeriesRing(QQ, NNMonoid(False))
312
sage: ger = GradedExpansionRing_class(Sequence([MonoidPowerSeries(mps, {1: 1}, mps.monoid().filter(4))]), Sequence([MonoidPowerSeries(mps, {1: 1, 2: 3}, mps.monoid().filter(4))]), PolynomialRing(QQ, ['a', 'b']).ideal(0), DegreeGrading((1,2)))
313
sage: inj = GradedExpansionBaseringInjection(ger.base_ring(), ger)
314
sage: h = inj(ger.base_ring()(0))
315
"""
316
return self.codomain()._element_constructor_(x, *args, **kwds)
317
318
#===============================================================================
319
# GradedExpansionEvaluationHomomorphism
320
#===============================================================================
321
322
class GradedExpansionEvaluationHomomorphism ( Morphism ) :
323
r"""
324
The evaluation of a polynomial by substituting the Fourier expansions
325
attached to a ring or module of graded expansions.
326
"""
327
328
def __init__(self, relations, base_ring_images, images, codomain, reduce = True) :
329
r"""
330
INPUT:
331
- ``relations`` -- An ideal in a polynomial ring.
332
- ``base_ring_images`` -- A list or sequence of elements of a ring of (equivariant)
333
monoid power series.
334
- ``images`` -- A list or sequence of monoid power series.
335
- ``codomain`` -- An ambient of (equivariant) monoid power series.
336
- ``reduce`` -- A boolean (default: ``True``); If ``True`` polynomials will
337
be reduced before the substitution is carried out.
338
339
TESTS::
340
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
341
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *
342
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *
343
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_grading import DegreeGrading
344
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_ring import *
345
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_functor import *
346
sage: mps = MonoidPowerSeriesRing(QQ, NNMonoid(False))
347
sage: ev = GradedExpansionEvaluationHomomorphism(PolynomialRing(QQ, ['a', 'b']).ideal(0), Sequence([MonoidPowerSeries(mps, {1 : 1}, mps.monoid().filter(2))]), Sequence([MonoidPowerSeries(mps, {1 : 1, 2 : 3}, mps.monoid().filter(4))]), mps, False)
348
"""
349
self.__relations = relations
350
self.__base_ring_images = base_ring_images
351
self.__images = images
352
self.__reduce = reduce
353
354
Morphism.__init__(self, relations.ring(), codomain)
355
356
self._repr_type_str = "Evaluation homomorphism from %s to %s" % (relations.ring(), codomain)
357
358
def _call_with_args(self, x, *args, **kwds) :
359
r"""
360
SEE:
361
:meth:~`._call_`.
362
363
NOTE:
364
``args`` and ``kwds`` will be ignored.
365
366
TESTS::
367
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
368
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *
369
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *
370
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_grading import DegreeGrading
371
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_ring import *
372
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_functor import *
373
sage: mps = MonoidPowerSeriesRing(QQ, NNMonoid(False))
374
sage: P.<a,b> = QQ[]
375
sage: ev = GradedExpansionEvaluationHomomorphism(P.ideal(0), Sequence([MonoidPowerSeries(mps, {1 : 1}, mps.monoid().filter(2))]), Sequence([MonoidPowerSeries(mps, {1 : 1, 2 : 3}, mps.monoid().filter(4))]), mps, False)
376
sage: h = ev(a, h = True)
377
"""
378
return self._call_(x)
379
380
def _call_(self, x) :
381
r"""
382
INPUT:
383
- `x` -- A polynomial.
384
385
OUTPUT:
386
An element of the codomain.
387
388
TESTS::
389
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *
390
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *
391
sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *
392
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_grading import DegreeGrading
393
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_ring import *
394
sage: from psage.modform.fourier_expansion_framework.gradedexpansions.gradedexpansion_functor import *
395
sage: mps = MonoidPowerSeriesRing(QQ, NNMonoid(False))
396
sage: P.<a,b> = QQ[]
397
sage: ev = GradedExpansionEvaluationHomomorphism(P.ideal(0), Sequence([MonoidPowerSeries(mps, {1 : 1}, mps.monoid().filter(2))]), Sequence([MonoidPowerSeries(mps, {1 : 1, 2 : 3}, mps.monoid().filter(4))]), mps, False)
398
sage: ev(a)
399
Monoid power series in Ring of monoid power series over NN
400
sage: ev = GradedExpansionEvaluationHomomorphism(P.ideal(a - b), Sequence([MonoidPowerSeries(mps, {1 : 1}, mps.monoid().filter(2))]), Sequence([MonoidPowerSeries(mps, {1 : 1, 2 : 3}, mps.monoid().filter(4))]), mps, True)
401
sage: ev(a - b).coefficients()
402
{0: 0}
403
"""
404
if self.__reduce :
405
x = self.__relations.reduce(x)
406
407
## Be careful not to directly substitute the elements of self.__images
408
## into the polynomial since they might be vectors, hence yielding
409
## an exception.
410
411
#=======================================================================
412
# if len(self.__base_ring_images) == 0 :
413
# parent = self.__images.universe()
414
# res = parent(0)
415
#
416
# for imexps,c in x.dict().iteritems() :
417
# if isinstance(imexps, int) :
418
# imexps = (imexps,)
419
# imexps = tuple(imexps)
420
#
421
# if imexps.count(0) == len(imexps) :
422
# res = res + c * parent(Integer(1))
423
# # this is the typical module case with an action
424
# # that does not respect the monoid structure
425
# elif imexps.count(0) == len(imexps) - 1 :
426
# i,e = dropwhile(lambda (_,e) : e == 0, enumerate(imexps)).next()
427
# if e == 1 :
428
# res = res + c * self.__images[i]
429
# else :
430
# res = res + c * self.__images[i]**e
431
# else :
432
# res = res + prod(map(operator.pow, self.__images, imexps))
433
#
434
# return res
435
#=======================================================================
436
437
expansion_ambient = self.__images.universe()
438
res = self.__images.universe().zero_element()
439
440
coeffs = x.dict()
441
xexps = groupby( sorted(x.exponents()),
442
lambda e: ([e] if isinstance(e, int) else list(e))[len(self.__base_ring_images):] )
443
444
for imexps, exps in xexps :
445
factor = self.__base_ring_images.universe().zero_element()
446
for e in exps :
447
factor = factor + coeffs[e] * prod(map( operator.pow, self.__base_ring_images,
448
([e] if isinstance(e,int) else e)[:len(self.__base_ring_images)] ))
449
450
imexps = tuple(imexps)
451
452
if imexps.count(0) == len(imexps) :
453
res = res + factor * expansion_ambient.one_element()
454
elif imexps.count(0) == len(imexps) - 1 :
455
i,e = dropwhile(lambda (_,e) : e == 0, enumerate(imexps)).next()
456
# this is the typical module case with an action
457
# that does not respect the monoid structure
458
if e == 1 :
459
res = res + factor * self.__images[i]
460
else :
461
res = res + factor * self.__images[i]**e
462
else :
463
res = res + factor * prod(map(operator.pow, self.__images, imexps))
464
465
return res
466
467