code / alex / psage / psage / modform / fourier_expansion_framework / monoidpowerseries / monoidpowerseries_lazyelement.py
241852 viewsr"""1An equivariant monoid power series with lazy evaluation.23AUTHOR :4-- Martin Raum (2009 - 08 - 05) Initial version5"""67#===============================================================================8#9# Copyright (C) 2009 Martin Raum10#11# This program is free software; you can redistribute it and/or12# modify it under the terms of the GNU General Public License13# as published by the Free Software Foundation; either version 314# of the License, or (at your option) any later version.15#16# This program is distributed in the hope that it will be useful,17# but WITHOUT ANY WARRANTY; without even the implied warranty of18# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU19# General Public License for more details.20#21# You should have received a copy of the GNU General Public License22# along with this program; if not, see <http://www.gnu.org/licenses/>.23#24#===============================================================================2526from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ambient import EquivariantMonoidPowerSeriesAmbient_abstract27from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import EquivariantMonoidPowerSeries_abstract28from sage.algebras.algebra_element import AlgebraElement29from sage.misc.misc import union30from sage.modules.module import Module31from sage.modules.module_element import ModuleElement32from sage.rings.ring import Ring3334#===============================================================================35# EquivariantMonoidPowerSeries_lazy36#===============================================================================3738def EquivariantMonoidPowerSeries_lazy(parent, precision, coefficient_function, components = None, bounding_precision = None) :39r"""40Construct a equivariant monoid power series, which calculates its coefficients41on demand.4243INPUT:44- ``parent`` -- An instance of :class:~`fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ambient.MonoidPowerSeriesAmbient_abstract`.45- ``precision`` -- A filter for the parent's action.46- ``coefficient_function`` -- A function returning for each pair of characters and47monoid element a Fourier coefficients.48- ``components`` -- ``None`` or a list of characters (default: ``None``). A list of components49that do not vanish. If ``None`` no component is assumed to be zero.50- ``bounding_precision`` -- ``None`` or a filter for the parent's action. If not ``None``51coefficients will be assumed to vanish outside the filter.5253OUTPUT:54An instance of :class:~`EquivariantMonoidPowerSeries_abstract_lazy`.5556EXAMPLES::57sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_lazyelement import *58sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *59sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_module import *60sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *61sage: emps = EquivariantMonoidPowerSeriesRing( NNMonoid(), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ) )62sage: h = EquivariantMonoidPowerSeries_lazy(emps, emps.action().filter(3), lambda (ch, k) : 1)63sage: m = FreeModule(QQ, 3)64sage: emps = EquivariantMonoidPowerSeriesModule( NNMonoid(), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m) )65sage: h = EquivariantMonoidPowerSeries_lazy(emps, emps.action().filter(3), lambda (ch, k) : m([1,2,3]))66sage: h = EquivariantMonoidPowerSeries_lazy(emps, emps.action().filter_all(), lambda (ch, k) : m([1,2,3]), bounding_precision = emps.action().filter(2))67sage: h = EquivariantMonoidPowerSeries_lazy(emps, emps.action().filter_all(), lambda (ch, k) : m([1,2,3]))68Traceback (most recent call last):69...70ValueError: Lazy equivariant monoid power series cannot have infinite precision.71"""72if (bounding_precision is None or bounding_precision.is_infinite()) and \73precision.is_infinite() and not (isinstance(components, list) and len(components) == 0) :74raise ValueError( "Lazy equivariant monoid power series cannot have infinite precision." )75if isinstance(parent, Module) :76return EquivariantMonoidPowerSeries_moduleelement_lazy(parent, precision, coefficient_function, components, bounding_precision)77if isinstance(parent, Ring) :78return EquivariantMonoidPowerSeries_algebraelement_lazy(parent, precision, coefficient_function, components, bounding_precision)7980#===============================================================================81# EquivariantMonoidPowerSeries_abstract_lazy82#===============================================================================8384class EquivariantMonoidPowerSeries_abstract_lazy (EquivariantMonoidPowerSeries_abstract) :85r"""86This class implements an equivariant monoid power series which calculates the87coefficients on demand.88"""8990def __init__(self, parent, precision, coefficient_function, components, bounding_precision = None ) :91r"""92INPUT:93- ``parent`` -- An instance of :class:~`fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ambient.MonoidPowerSeriesAmbient_abstract`.94- ``precision`` -- A filter for the parent's action.95- ``coefficient_function`` -- A function returning for each pair of characters and96monoid element a Fourier coefficients.97- ``components`` -- ``None`` or a list of characters. A list of components that do not98vanish. If ``None`` no component is assumed to be zero.99- ``bounding_precision`` -- ``None`` or a filter for the parent's action. If not ``None``100coefficients will be assumed to vanish outside the filter.101102TESTS::103sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_lazyelement import *104sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *105sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *106sage: emps = EquivariantMonoidPowerSeriesRing( NNMonoid(), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ) )107sage: h = EquivariantMonoidPowerSeries_abstract_lazy(emps, emps.action().filter(3), lambda (ch, k) : 1, None)108sage: h = EquivariantMonoidPowerSeries_abstract_lazy(emps, emps.action().filter(3), lambda (ch, k) : 1, [])109sage: h = EquivariantMonoidPowerSeries_abstract_lazy(emps, emps.action().filter_all(), lambda (ch, k) : 1, [], emps.action().filter(4))110"""111EquivariantMonoidPowerSeries_abstract.__init__(self, parent, precision)112113self.__bounding_precision = bounding_precision114self.__coefficient_function = coefficient_function115self.__coefficients = dict()116self.__coefficients_complete = False117self.__components = components118119def non_zero_components(self) :120r"""121Return all those characters which are not guaranteed to have only122vanishing coefficients associated with.123124OUTPUT:125A list of elements of the character monoid.126127NOTE:128This will only return the list passed during the construction129of self or a list of all characters.130131EXAMPLES::132sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_lazyelement import *133sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *134sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *135sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *136sage: emps = EquivariantMonoidPowerSeriesRing( NNMonoid(), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ) )137sage: e = EquivariantMonoidPowerSeries(emps, {emps.characters().one_element() : { 1 : 1}}, emps.action().filter_all())138sage: EquivariantMonoidPowerSeries_LazyMultiplication(e, e).non_zero_components()139[1]140sage: EquivariantMonoidPowerSeries_abstract_lazy(emps, emps.action().filter(3), lambda (ch, k) : 1, []).non_zero_components()141[]142"""143if self.__components is None :144self.__components = [c for c in self.parent().characters()]145146return self.__components147148def _bounding_precision(self) :149r"""150If a filter for the vanishing of coefficients is given return this. Otherwise,151return the precision, which is then guaranteed to be finite.152153OUTPUT:154A filter for the parent's action.155156TESTS::157sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_lazyelement import *158sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *159sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *160sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *161sage: emps = EquivariantMonoidPowerSeriesRing( NNMonoid(), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ) )162sage: e = EquivariantMonoidPowerSeries(emps, {}, emps.action().filter_all())163sage: EquivariantMonoidPowerSeries_LazyMultiplication(e, e)._bounding_precision()164Filtered NN with action up to 0165sage: EquivariantMonoidPowerSeries_abstract_lazy(emps, emps.action().filter(3), lambda (ch, k) : 1, [emps.characters().one_element()])._bounding_precision()166Filtered NN with action up to 3167sage: h = EquivariantMonoidPowerSeries_abstract_lazy(emps, emps.action().filter_all(), lambda (ch, k) : 1, [])._bounding_precision() ## This would call the parent168Traceback (most recent call last):169...170AttributeError: EquivariantMonoidPowerSeries_abstract_lazy instance has no attribute 'parent'171sage: h = EquivariantMonoidPowerSeries_abstract_lazy(emps, emps.action().filter_all(), lambda (ch, k) : 1, [], emps.action().filter(4))._bounding_precision() ## This would call the parent172Traceback (most recent call last):173...174AttributeError: EquivariantMonoidPowerSeries_abstract_lazy instance has no attribute 'parent'175sage: EquivariantMonoidPowerSeries_abstract_lazy(emps, emps.action().filter_all(), lambda (ch, k) : 1, [emps.characters().one_element()], emps.action().filter(4))._bounding_precision()176Filtered NN with action up to 4177sage: EquivariantMonoidPowerSeries_abstract_lazy(emps, emps.action().filter_all(), lambda (ch, k) : 1, [emps.characters().one_element()])._bounding_precision()178Traceback (most recent call last):179...180ValueError: No bounding precision for ...181"""182if len(self.non_zero_components()) == 0 :183return self.parent().action().zero_filter()184elif not self.__bounding_precision is None :185return min(self.__bounding_precision, self.precision())186elif self.precision().is_infinite() :187raise ValueError( "No bounding precision for %s." % (self,) )188189return self.precision()190191def coefficients(self, force_characters = False) :192r"""193Evaluate all coefficients within the precision bounds and return a194dictionary which saves all coefficients of this element.195196INPUT:197- ``force_characters`` -- A boolean (default: ``False``); If ``True`` the198the dictionary returned will have characters as keys199in any cases.200201OUTPUT:202Either of the following two:203- A dictionary with keys the elements of the parent's monoid and values in the204parent's coefficient domain.205- A dictionary with keys the parent's characters and values the a dictionary as follows. This206dictionary has keys the elements of the parent's monoid and values in the parent's207coefficient domain.208209EXAMPLES::210sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_lazyelement import *211sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *212sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *213sage: emps = EquivariantMonoidPowerSeriesRing( NNMonoid(), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ) )214sage: e = EquivariantMonoidPowerSeries_abstract_lazy(emps, emps.action().filter(3), lambda (ch, k) : 1, [emps.characters().one_element()])215sage: e.coefficients()216{0: 1, 1: 1, 2: 1}217sage: e.coefficients(True)218{1: {0: 1, 1: 1, 2: 1}}219"""220if not self.__coefficients_complete :221self.__coefficients_complete = True222223coefficient_function = self.__coefficient_function224225for ch in self.non_zero_components() :226if not ch in self.__coefficients :227coeffs = dict()228self.__coefficients[ch] = coeffs229for k in self._bounding_precision() :230coeffs[k] = coefficient_function((ch, k))231else :232coeffs = self.__coefficients[ch]233for k in self._bounding_precision() :234if not k in coeffs :235coeffs[k] = coefficient_function((ch, k))236237if len(self.__coefficients) == 0 and not force_characters :238return dict()239elif len(self.__coefficients) == 1 and not force_characters :240return self.__coefficients.values()[0]241else :242return self.__coefficients243244def _truncate_in_place(self, precision) :245r"""246Truncate ``self`` modifying also the coefficient cache.247248INPUT:249- ``precision`` -- A filter for the parent's action or a an object that can be converted250to a filter.251252OUTPUT:253``None``254255EXAMPLE:256sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_lazyelement import *257sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *258sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *259sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *260sage: emps = EquivariantMonoidPowerSeriesRing( NNMonoid(), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ) )261sage: h = EquivariantMonoidPowerSeries_abstract_lazy(emps, emps.action().filter(3), lambda (ch, k) : 1, None)262sage: e = EquivariantMonoidPowerSeries(emps, {emps.characters().one_element() : { 1 : 1}}, emps.action().filter_all())263sage: e = EquivariantMonoidPowerSeries_LazyMultiplication(e, e)264sage: e._truncate_in_place(emps.monoid().filter(2))265sage: e.coefficients()266{0: 0, 1: 0}267"""268precision = self.parent().action().filter(precision)269nprec = min(self.precision(), precision)270271if nprec != self.precision() :272for c in self.__coefficients :273d = self.__coefficients[c]274for k in d.keys() :275if not k in nprec :276del d[k]277278self._set_precision(nprec)279280def __getitem__(self, k) :281r"""282Evaluate and return the `k`-th coefficient if it below the series' precision. If no character is contained283in the key ``self`` must have only one nonvanishing component.284285INPUT:286- `k` -- A pair of an element of the parent's character monoid and287and element of the parent's monoid or an element of the parent's monoid.288289OUTPUT:290An element of the parent's coefficient domain.291292EXAMPLES::293sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_lazyelement import *294sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *295sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *296sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *297sage: emps = EquivariantMonoidPowerSeriesRing( NNMonoid(), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ) )298sage: e = EquivariantMonoidPowerSeries(emps, {emps.characters().one_element() : { 1 : 1, 2 : 4}}, emps.action().filter(3))299sage: e = EquivariantMonoidPowerSeries_LazyMultiplication(e, e)300sage: e[(emps.characters().one_element(),2)]3011302sage: e[1], e[2]303(0, 1)304"""305try :306(ch, s) = k307except TypeError :308ch = None309310try :311if not ch.parent() == self.parent().characters() :312ch = None313except AttributeError :314ch = None315316if ch is None :317ns = self.non_zero_components()318if len(ns) == 0 :319return 0320elif len(ns) == 1 :321ch = ns[0]322else :323raise ValueError, "you must specify a character"324325s = k326327if not s in self.precision() :328raise ValueError, "%s out of bound" % s329330try :331return self.__coefficients[ch][s]332except KeyError :333(rs, g) = self.parent()._reduction_function()(s)334try :335return self.parent()._character_eval_function()(g, ch) \336* self.parent()._apply_function()(g, self.__coefficients[ch][rs])337except KeyError :338e = self.__coefficient_function((ch, rs))339340try :341self.__coefficients[ch][rs] = e342except KeyError :343self.__coefficients[ch] = dict()344self.__coefficients[ch][rs] = e345346return e347348#===============================================================================349# EquivariantMonoidPowerSeries_modulelement_lazy350#===============================================================================351352class EquivariantMonoidPowerSeries_moduleelement_lazy (EquivariantMonoidPowerSeries_abstract_lazy, ModuleElement) :353r"""354A lazy element of a module of equivariant monoid power series.355"""356357def __init__(self, parent, precision, coefficient_function, components, bounding_precision ) :358r"""359INPUT:360- ``parent`` -- An instance of :class:~`fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ambient.MonoidPowerSeriesAmbient_abstract`.361- ``precision`` -- A filter for the parent's action.362- ``coefficient_function`` -- A function returning for each pair of characters and363monoid element a Fourier coefficients.364- ``components`` -- ``None`` or a list of characters. A list of components that do not365vanish. If ``None`` no component is assumed to be zero.366367TESTS::368sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_lazyelement import *369sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_module import *370sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *371sage: m = FreeModule(QQ, 3)372sage: emps = EquivariantMonoidPowerSeriesModule( NNMonoid(), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m) )373sage: h = EquivariantMonoidPowerSeries_moduleelement_lazy(emps, emps.action().filter(3), lambda (ch, k) : m([1,2,3]), None, None)374"""375ModuleElement.__init__(self, parent)376EquivariantMonoidPowerSeries_abstract_lazy.__init__(self, parent, precision,377coefficient_function, components, bounding_precision)378379#===============================================================================380# EquivariantMonoidPowerSeries_algebraelement_lazy381#===============================================================================382383class EquivariantMonoidPowerSeries_algebraelement_lazy (EquivariantMonoidPowerSeries_abstract_lazy, AlgebraElement) :384r"""385A lazy element of an algebra of equivariant monoid power series.386"""387388def __init__(self, parent, precision, coefficient_function, components, bounding_precision ) :389r"""390INPUT:391- ``parent`` -- An instance of :class:~`fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ambient.MonoidPowerSeriesAmbient_abstract`.392- ``precision`` -- A filter for the parent's action.393- ``coefficient_function`` -- A function returning for each pair of characters and394monoid element a Fourier coefficients.395- ``components`` -- ``None`` or a list of characters. A list of components that do not396vanish. If ``None`` no component is assumed to be zero.397398TESTS::399sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_lazyelement import *400sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *401sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *402sage: emps = EquivariantMonoidPowerSeriesRing( NNMonoid(), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ) )403sage: h = EquivariantMonoidPowerSeries_algebraelement_lazy(emps, emps.action().filter(3), lambda (ch, k) : 1, None, None)404"""405AlgebraElement.__init__(self, parent)406EquivariantMonoidPowerSeries_abstract_lazy.__init__(self, parent, precision,407coefficient_function, components, bounding_precision)408409#===============================================================================410# EquivariantMonoidPowerseries_MultiplicationDelayedFactory411#===============================================================================412413class EquivariantMonoidPowerseries_MultiplicationDelayedFactory :414r"""415A helper class for lazy multplication of equivariant monoid power series.416"""417418def __init__( self, left, right ) :419r"""420INPUT:421- ``left`` -- An instance of :class:~`fourier_expansion_framework.monoidpowerseries.EquivariantMonoidPowerSeries_abstract`.422- ``right`` -- An instance of :class:~`fourier_expansion_framework.monoidpowerseries.EquivariantMonoidPowerSeries_abstract`.423424NOTE:425``left`` and ``right`` must have the same parents.426427TESTS::428sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_lazyelement import *429sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *430sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *431sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *432sage: emps = EquivariantMonoidPowerSeriesRing( NNMonoid(), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ) )433sage: e = EquivariantMonoidPowerSeries(emps, {emps.characters().one_element() : { 1 : 1}}, emps.action().filter_all())434sage: EquivariantMonoidPowerSeries_LazyMultiplication(e, e).coefficients() # indirect doctest435{0: 0, 1: 0, 2: 1}436"""437assert left.parent() == right.parent()438439self.__left = left440self.__right = right441442self.__mul_fc = left.parent()._multiply_function()443self.__coefficient_ring = left.parent().coefficient_domain()444445self.__left_coefficients = None446self.__right_coefficients = None447448def getcoeff(self, (ch, k)) :449r"""450Return the `k`-th coefficient of the component ``ch`` of the product.451452INPUT:453- ``(ch, k)`` -- A pair of character and monoid element.454455TESTS::456sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_lazyelement import *457sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *458sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *459sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *460sage: emps = EquivariantMonoidPowerSeriesRing( NNMonoid(), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ) )461sage: e = EquivariantMonoidPowerSeries(emps, {emps.characters().one_element() : { 1 : 1}}, emps.action().filter_all())462sage: EquivariantMonoidPowerSeries_LazyMultiplication(e, e).coefficients() # indirect doctest463{0: 0, 1: 0, 2: 1}464"""465res = self.__coefficient_ring(0)466467if self.__left_coefficients is None :468self.__left_coefficients = self.__left.coefficients(True)469if self.__right_coefficients is None :470self.__right_coefficients = self.__right.coefficients(True)471472for c1 in self.__left_coefficients :473lcoeffs = self.__left_coefficients[c1]474if len(lcoeffs) == 0 : continue475476for c2 in self.__right_coefficients :477rcoeffs = self.__right_coefficients[c2]478if len(rcoeffs) == 0 : continue479480if c1 * c2 != ch :481continue482483res += self.__mul_fc( k, lcoeffs, rcoeffs, c1, c2, self.__coefficient_ring(0) )484485return res486487#===============================================================================488# EquivariantMonoidPowerSeries_LazyMultiplication489#===============================================================================490491def EquivariantMonoidPowerSeries_LazyMultiplication(left, right) :492r"""493The product of two equivariant monoid power series which is only evaluated494if a coefficient is demanded.495496INPUT:497- ``left`` -- An instance of :class:~`fourier_expansion_framework.monoidpowerseries.EquivariantMonoidPowerSeries_abstract`.498- ``right`` -- An instance of :class:~`fourier_expansion_framework.monoidpowerseries.EquivariantMonoidPowerSeries_abstract`.499500EXAMPLES:501sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_lazyelement import *502sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_element import *503sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import *504sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *505sage: emps = EquivariantMonoidPowerSeriesRing( NNMonoid(), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ) )506sage: e = EquivariantMonoidPowerSeries(emps, {emps.characters().one_element() : { 1 : 1}}, emps.action().filter_all())507sage: EquivariantMonoidPowerSeries_LazyMultiplication(e, e).coefficients() # indirect doctest508{0: 0, 1: 0, 2: 1}509"""510# TODO: Insert coercing511if not isinstance(left.parent(), EquivariantMonoidPowerSeriesAmbient_abstract) \512or not isinstance(right.parent(), EquivariantMonoidPowerSeriesAmbient_abstract) :513raise TypeError, "both factors must be power series"514515if left.parent() != right.parent() :516if left.parent() is right.parent().base_ring() :517parent = right.parent()518elif left.parent().base_ring() is right.parent() :519parent = left.parent()520521raise ValueError, "incorrect parents of the factors"522else :523parent = left.parent()524525coefficients_factory = \526EquivariantMonoidPowerseries_MultiplicationDelayedFactory( left, right )527528precision = min(left.precision(), right.precision())529bounding_precision = None530if precision.is_infinite() :531left_coefficients = left.coefficients(True)532right_coefficients = right.coefficients(True)533534left_keys = reduce(union, (set(c) for c in left_coefficients.itervalues()), set())535right_keys = reduce(union, (set(c) for c in right_coefficients.itervalues()), set())536537bounding_precision = left.parent().action(). \538minimal_composition_filter(left_keys, right_keys)539540return EquivariantMonoidPowerSeries_lazy( parent,541precision,542coefficients_factory.getcoeff,543bounding_precision = bounding_precision )544545546