code / alex / psage / psage / modform / fourier_expansion_framework / gradedexpansions / expansion_module.py
241849 viewsr"""1Module abstractly spanned by Fourier expansions.23AUTHOR:4- Martin Raum (2010 - 05 - 15) Initial version5"""67#===============================================================================8#9# Copyright (C) 2010 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.gradedexpansions.expansion_lazy_evaluation import LazyFourierExpansionEvaluation27from psage.modform.fourier_expansion_framework.gradedexpansions.fourierexpansionwrapper import FourierExpansionWrapper28from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_ring import EquivariantMonoidPowerSeriesAmbient_abstract, MonoidPowerSeriesAmbient_abstract29from sage.categories.pushout import pushout30from sage.interfaces.magma import magma31from sage.matrix.constructor import matrix32from sage.misc.cachefunc import cached_method33from sage.misc.flatten import flatten34from sage.misc.latex import latex35from sage.misc.misc import union36from sage.modules.free_module import FreeModule, FreeModule_generic, \37FreeModule_ambient_pid, FreeModule_submodule_pid38from sage.modules.free_module import is_FreeModule39from sage.modules.free_module_element import FreeModuleElement_generic_dense40from sage.modules.free_module_element import vector41from sage.rings.arith import random_prime42from sage.rings.integer_ring import ZZ43from sage.rings.number_field.order import Order44from sage.rings.padics.factory import Qp45from sage.rings.principal_ideal_domain import PrincipalIdealDomain46from sage.rings.rational_field import QQ47from sage.rings.ring import Ring48from sage.structure.element import Element49from sage.structure.sequence import Sequence, Sequence_generic50import itertools5152#===============================================================================53# ExpansionModule54#===============================================================================5556def ExpansionModule(forms) :57r"""58Construct a module of over the forms' base ring of rank ``len(forms)``59with underlying expansions associated to.6061INPUT:62- ``forms`` -- A sequence or nonempty list of (equivariant) monoid power series.6364OUTPUT:65An instance of :class:~`.ExpansionModule_abstract`.6667EXAMPLES::68sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *69sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *70sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *71sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))72sage: m = FreeModule(QQ, 3)73sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))74sage: em = ExpansionModule([emps.one_element(), emps.one_element()])75sage: em = ExpansionModule([empsm.zero_element(), empsm.zero_element()])76sage: mps = MonoidPowerSeriesRing(ZZ, NNMonoid())77sage: em = ExpansionModule([mps.one_element()])78sage: mpsm = MonoidPowerSeriesModule(m, NNMonoid())79sage: em = ExpansionModule([mpsm.zero_element()])8081TESTS::82sage: em = ExpansionModule(Sequence([], universe = emps))83sage: em = ExpansionModule(Sequence([], universe = empsm))84sage: h = EquivariantMonoidPowerSeries(emps, {emps.characters().one_element(): {1: 1, 3: 2}}, emps.action().filter_all())85sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0]), 2: m([0,0,1])}}, empsm.action().filter_all())86sage: em = ExpansionModule([emps.one_element(), h, h^2])87sage: em = ExpansionModule([empsm.zero_element(), hv, hv * h])88sage: em = ExpansionModule([])89Traceback (most recent call last):90...91ValueError: Empty modules must be constructed with a universe.92sage: em = ExpansionModule(Sequence([], universe = m))93Traceback (most recent call last):94...95ValueError: Common parent of all forms must be a monoid power series ring or module.96sage: qa = QuaternionAlgebra(QQ, -1, -1)97sage: em = ExpansionModule(Sequence([], universe = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", qa)) ))98Traceback (most recent call last):99...100TypeError: The forms' base ring must be a commutative ring.101"""102if not isinstance(forms, Sequence_generic) :103forms = Sequence(forms)104if len(forms) == 0 :105raise ValueError( "Empty modules must be constructed with a universe." )106107if not isinstance(forms.universe(), (MonoidPowerSeriesAmbient_abstract,108EquivariantMonoidPowerSeriesAmbient_abstract)) :109raise ValueError( "Common parent of all forms must be a monoid power series ring or module." )110111if isinstance(forms.universe(), EquivariantMonoidPowerSeriesAmbient_abstract) \112and forms.universe().representation().base_ring() == forms.universe().representation().codomain() :113base_ring = forms.universe().base_ring()114elif isinstance(forms.universe(), MonoidPowerSeriesAmbient_abstract) \115and isinstance(forms.universe().coefficient_domain(), Ring) :116base_ring = forms.universe().base_ring()117else :118base_ring = forms.universe().base_ring().base_ring()119120if not base_ring.is_commutative():121raise TypeError( "The forms' base ring must be a commutative ring." )122123if base_ring.is_field() \124or isinstance(base_ring, PrincipalIdealDomain) \125or ( isinstance(base_ring, Order) \126and base_ring.is_maximal() and base_ring.class_number() == 1 ) :127return ExpansionModule_ambient_pid(forms)128else :129return ExpansionModule_generic(forms)130131#===============================================================================132# ExpansionModule_abstract133#===============================================================================134135class ExpansionModule_abstract :136r"""137An abstract implementation of a module with expansions associated to its basis elements.138"""139140def __init__(self, basis, **kwds) :141r"""142INPUT:143- ``basis`` -- A sequence of (equivariant) monoid power series.144145TESTS::146sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *147sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *148sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *149sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_abstract150sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))151sage: em = ExpansionModule_abstract(Sequence([emps.one_element(), emps.one_element()]))152"""153self.__abstract_basis = basis154155def _abstract_basis(self) :156r"""157Return a basis in terms of elements of the graded ambient.158159OUTPUT:160A sequence of (equivariant) monoid power series.161162TESTS::163sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *164sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *165sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *166sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))167sage: basis = Sequence([emps.one_element(), emps.one_element()])168sage: em = ExpansionModule(basis)169sage: em._abstract_basis() == basis170True171"""172return self.__abstract_basis173174@cached_method175def precision(self) :176r"""177A common precision of the expansions associated to the basis elements.178179OUTPUT:180A filter for the expansions' parent's action or monoid.181182TESTS::183sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *184sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *185sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *186sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))187sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))188sage: em.precision()189Filtered NN with action up to +Infinity190sage: em = ExpansionModule(Sequence([emps.one_element().truncate(3), emps.one_element()]))191sage: em.precision()192Filtered NN with action up to 3193sage: em = ExpansionModule(Sequence([], universe = emps))194sage: em.precision()195Filtered NN with action up to +Infinity196"""197if len(self.__abstract_basis) != 0 :198return min([b.precision() for b in self.__abstract_basis])199else :200if isinstance(self.__abstract_basis.universe(), EquivariantMonoidPowerSeriesAmbient_abstract) :201return self.__abstract_basis.universe().action().filter_all()202else :203return self.__abstract_basis.universe().monoid().filter_all()204205def _bounding_precision(self) :206r"""207A common precision of the expansions associtated to the basis elements208if it is finite or in case it is not a filter that comprises all209nonzero coefficient of the expansion.210211OUTPUT:212A filter for the expansions' parent's action or monoid.213214TESTS::215sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *216sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *217sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *218sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))219sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))220sage: em._bounding_precision()221Filtered NN with action up to 1222sage: em = ExpansionModule(Sequence([emps.one_element().truncate(4), emps.one_element()]))223sage: em._bounding_precision()224Filtered NN with action up to 4225sage: em = ExpansionModule(Sequence([], universe = emps))226sage: em._bounding_precision()227Filtered NN with action up to 0228"""229if len(self.__abstract_basis) != 0 :230return max([b._bounding_precision() for b in self.__abstract_basis])231else :232if isinstance(self.__abstract_basis.universe(), EquivariantMonoidPowerSeriesAmbient_abstract) :233return self.__abstract_basis.universe().action().zero_filter()234else :235return self.__abstract_basis.universe().monoid().zero_filter()236237@cached_method238def _check_precision(self, precision = None, lazy_rank_check = False) :239r"""240Check whether the elements of this module are uniquely determined241by their Fourier expansions up to ``precision``. If ``precision`` is ``None``242the precision of this module will be used.243244INPUT:245- ``precision`` -- A filter for the expansions' parent monoid or action or ``None`` (default: ``None``).246- ``lazy_rank_check`` -- A boolean (default: ``False``); If ``True`` the involved rank checks will247be done over `Q_p` (with finite precision).248249OUTPUT:250A boolean.251252TESTS::253sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *254sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *255sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *256sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))257sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))258sage: em._check_precision()259False260sage: em = ExpansionModule(Sequence([], universe = emps))261sage: em._check_precision()262True263sage: em._check_precision(lazy_rank_check = True)264True265sage: h = EquivariantMonoidPowerSeries(emps, {emps.characters().one_element(): {1: 1, 3: 2}}, emps.action().filter_all())266sage: em = ExpansionModule(Sequence([emps.one_element(), h]))267sage: em._check_precision()268True269sage: em._check_precision(emps.action().filter(1))270False271sage: m = FreeModule(QQ, 3)272sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))273sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0])}}, empsm.action().filter_all())274sage: hv2 = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,1,0])}}, empsm.action().filter_all())275sage: em = ExpansionModule(Sequence([hv, hv2]))276sage: em._check_precision()277True278"""279if lazy_rank_check and not( self.base_ring() is ZZ or self.base_ring() is QQ) :280raise NotImplemented, "lazy rank checks only implemented for ZZ and QQ"281282if precision is None :283precision = self.precision()284elif not precision <= self.precision() :285raise ValueError, "precison must be less equal self.__graded_ambient.precision()"286287if precision.is_infinite() :288precision = self._bounding_precision()289if self.precision().is_infinite() :290total_precision = self._bounding_precision()291else :292total_precision = self.precision()293294basis_fe_expansion = self.fourier_expansion_homomorphism().matrix()295296if precision != self.precision() :297if isinstance(self._abstract_basis().universe().coefficient_domain(), Ring) :298indices = [i for (i,k) in enumerate(total_precision) if k in precision]299else :300indices = [i for (i,(k,_)) in enumerate(301itertools.product(total_precision, range(self._abstract_basis().universe().coefficient_domain().rank())) )302if k in precision]303basis_fe_expansion = basis_fe_expansion.matrix_from_columns(indices)304305if lazy_rank_check :306basis_fe_expansion = matrix(Qp(random_prime(10**9), 10), basis_fe_expansion)307308return basis_fe_expansion.rank() >= self.rank()309310def _fourier_expansion_of_element(self, e) :311r"""312The Fourier expansion of an element optained via linear combinations313of the basis' Fourier expansions.314315INPUT:316- `e` -- An element of ``self``.317318OUTPUT:319A (equivariant) monoid power series.320321TESTS::322sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *323sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *324sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *325sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))326sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))327sage: fe = em._fourier_expansion_of_element(em([1,0]))328sage: m = FreeModule(QQ, 3)329sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))330sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0])}}, empsm.action().filter_all())331sage: em = ExpansionModule(Sequence([hv]))332sage: fe = em._fourier_expansion_of_element(em([1]))333"""334return sum( (e[k]*b for (k,b) in enumerate(self.__abstract_basis) if e[k] != 0),335self.__abstract_basis.universe()(0) )336337@cached_method338def _non_zero_characters(self) :339r"""340Return those characters which cannot be guaranteed to have vanishing Fourier341expansion associated with for all basis elements of ``self``.342343OUTPUT:344A list of characters of the expansions' parent if it is equivariant345or otherwise None.346347TESTS::348sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *349sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *350sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *351sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))352sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))353sage: em._non_zero_characters()354[1]355sage: em = ExpansionModule(Sequence([EquivariantMonoidPowerSeries(emps, {}, emps.action().filter_all())]))356sage: em._non_zero_characters()357[]358"""359if isinstance(self.__abstract_basis.universe(), EquivariantMonoidPowerSeriesAmbient_abstract) :360return list( reduce(union, [ set(b.non_zero_components())361for b in flatten(self.__abstract_basis, tuple) ], set()) )362else :363return None364365@cached_method366def _fourier_expansion_indices(self) :367r"""368A list of Fourier indices which are considered by the Fourier expansion morphism.369370OUTPUT:371A list of monoid elements or components indices and monoid elements372in case the expansions' parent is not equivariant. Otherwise, it373is pairs of characters and monoid elements possibly with a component374index in case the coefficient domain of the expansions parent is only375a module.376377SEE:378:meth:~`.fourier_expansion_homomorphism`.379380TESTS::381sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *382sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *383sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *384sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))385sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))386sage: em._fourier_expansion_indices()387[(1, 0)]388sage: m = FreeModule(QQ, 3)389sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))390sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0]), 2: m([0,0,1])}}, empsm.action().filter_all())391sage: em = ExpansionModule(Sequence([hv]))392sage: em._fourier_expansion_indices()393[(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))]394sage: mps = MonoidPowerSeriesRing(ZZ, NNMonoid())395sage: em = ExpansionModule([mps.one_element()])396sage: em._fourier_expansion_indices()397[0]398sage: mpsm = MonoidPowerSeriesModule(m, NNMonoid())399sage: hv = MonoidPowerSeries(mpsm, {1: m([1,0,0]), 2: m([0,0,1])}, mpsm.monoid().filter_all())400sage: em = ExpansionModule([hv])401sage: em._fourier_expansion_indices()402[(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1), (0, 2), (1, 2), (2, 2)]403"""404characters = self._non_zero_characters()405406if isinstance(self.__abstract_basis.universe().coefficient_domain(), Ring) :407if characters is None :408return list(self._bounding_precision())409else :410return [ (ch, k) for k in self._bounding_precision()411for ch in characters ]412else :413if characters is None :414return [ (i, k) for k in self._bounding_precision()415for i in range(self.__abstract_basis.universe().coefficient_domain().rank()) ]416else :417return [ (i,(ch, k)) for k in self._bounding_precision()418for ch in characters419for i in range(self.__abstract_basis.universe().coefficient_domain().rank()) ]420421@cached_method422def fourier_expansion_homomorphism(self, precision = None) :423r"""424A morphism mapping elements of the underlying module to425a module such that each component of the image corresponds to an426Fourier coefficient of the Fourier expansion associated with this427element.428429INPUT:430- ``precision`` -- A fitler for the expansions monoid or action or ``None``431(default: ``None``); If not ``None`` the Fourier expansions432of the basis will be truncated to this precision.433434OUTPUT:435A morphism from ``self`` to a free module over the expansions' base ring.436437TESTS::438sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *439sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *440sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *441sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", QQ))442sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))443sage: em.fourier_expansion_homomorphism()444Free module morphism defined by the matrix445[1]446[1]447Domain: Module of Fourier expansions in Ring of equivariant monoid power ...448Codomain: Vector space of dimension 1 over Rational Field449sage: m = FreeModule(QQ, 3)450sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))451sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0]), 2: m([0,0,1])}}, empsm.action().filter_all())452sage: em = ExpansionModule(Sequence([hv]))453sage: em.fourier_expansion_homomorphism()454Free module morphism defined by the matrix455[0 0 0 1 0 0 0 0 1]456Domain: Module of Fourier expansions in Module of equivariant monoid ...457Codomain: Vector space of dimension 9 over Rational Field458"""459keys = self._fourier_expansion_indices()460461codomain = FreeModule(self.base_ring(), len(keys))462if isinstance(self.__abstract_basis.universe().coefficient_domain(), Ring) :463basis_images = [ codomain([b[k] for k in keys])464for b in self.__abstract_basis ]465else :466basis_images = [ codomain([b[k][i] for (i,k) in keys])467for b in self.__abstract_basis ]468469return self.Hom(codomain)(basis_images)470471@cached_method472def _fourier_expansion_matrix_over_fraction_field(self) :473r"""474The matrix associated with the Fourier expansion homomorphism475such that its base ring is a field.476477OUTPUT:478A matrix over the fraction field of the expansions' base ring.479480SEE:481:meth:~`.fourier_expansion_homomorphism`.482483TESTS::484sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *485sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *486sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *487sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))488sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))489sage: em._fourier_expansion_matrix_over_fraction_field().base_ring()490Rational Field491"""492if self.base_ring().is_field() :493return self.fourier_expansion_homomorphism().matrix()494else :495return self.fourier_expansion_homomorphism().matrix(). \496base_extend(self.base_ring().fraction_field())497498@cached_method499def pivot_elements(self) :500r"""501Determine a set of generators, which minimally span the image of the Fourier expansion502homomorphism.503504SEE:505:meth:~`.fourier_expansion_homomorphism`.506507OUTPUT:508A list of indices.509510TESTS::511sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *512sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *513sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *514sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))515sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))516sage: em.pivot_elements()517[0]518sage: em = ExpansionModule(Sequence([emps.one_element().truncate(0), emps.one_element().truncate(0)]))519sage: em.pivot_elements()520[]521sage: em = ExpansionModule(Sequence([], universe = emps))522sage: em.pivot_elements()523[]524sage: m = FreeModule(QQ, 3)525sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))526sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0]), 2: m([0,0,1])}}, empsm.action().filter_all())527sage: em = ExpansionModule(Sequence([hv,hv]))528sage: em.pivot_elements()529[0]530"""531expansion_matrix = self.fourier_expansion_homomorphism().matrix().transpose()532533if expansion_matrix.rank() == self.rank() :534return range(self.rank())535else :536return list(expansion_matrix.pivots())537538def _element_to_fourier_expansion_generator(self, e) :539r"""540Given a monoid power series `e` return a generator iterating over the components of541the image of `e` under the Fourier expansion morphism.542543INTPUT:544- `e` -- An element of the ``self``.545546OUTPUT:547A generator over elements of the expansions' base ring.548549SEE::550:meth:~`.fourier_expansion_homomorphism`.551552TESTS::553sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *554sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *555sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *556sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))557sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))558sage: list(em._element_to_fourier_expansion_generator(em([3,0]).fourier_expansion()))559[3]560sage: m = FreeModule(QQ, 3)561sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))562sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0]), 2: m([0,0,1])}}, empsm.action().filter_all())563sage: em = ExpansionModule(Sequence([hv]))564sage: list(em._element_to_fourier_expansion_generator(em([1]).fourier_expansion()))565[0, 0, 0, 1, 0, 0, 0, 0, 1]566sage: mps = MonoidPowerSeriesRing(ZZ, NNMonoid())567sage: em = ExpansionModule([mps.one_element()])568sage: list(em._element_to_fourier_expansion_generator(em([2]).fourier_expansion()))569[2]570sage: mpsm = MonoidPowerSeriesModule(m, NNMonoid())571sage: hv = MonoidPowerSeries(mpsm, {1: m([1,0,0]), 2: m([0,0,1])}, mpsm.monoid().filter_all())572sage: em = ExpansionModule([hv])573sage: list(em._element_to_fourier_expansion_generator(em([1]).fourier_expansion()))574[0, 0, 0, 1, 0, 0, 0, 0, 1]575"""576keys = self._fourier_expansion_indices()577578if isinstance(self.__abstract_basis.universe().coefficient_domain(), Ring) :579return (e[k] if k in e else 0 for k in keys)580else :581return (e[k][i] if k in e else 0 for (i,k) in keys)582583def coordinates(self, x, in_base_ring = True, force_ambigous = False) :584r"""585The coordinates in ``self`` of an element either of the following:586- An element of a submodule.587- An expansion in the parent of the basis' expansions.588589INPUT:590- `x` -- Either of the types listed above.591- ``in_base_ring`` -- A boolean (default: ``True``); If ``True``592enforce the result to be definied over the593base ring of ``self``.594- ``force_ambigous`` -- A boolean (default: ``False``); If ``True``595also return the solutions that are not unique.596597OUTPUT:598A list of elements in the base ring or and extension of it.599600NOTE:601If the Fourier expansion of `x` lakes sufficient precision the602expansions associated to ``self`` will be truncated.603604TESTS::605sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *606sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *607sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *608sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))609sage: em = ExpansionModule(Sequence([emps.one_element()]))610sage: em.coordinates(2 * emps.one_element())611[2]612sage: m = FreeModule(QQ, 3)613sage: empsm = EquivariantMonoidPowerSeriesModule(NNMonoid(True), TrivialCharacterMonoid("1", QQ), TrivialRepresentation("1", m))614sage: hv = EquivariantMonoidPowerSeries(empsm, {empsm.characters().one_element(): {1: m([1,0,0]), 2: m([0,0,1])}}, empsm.action().filter_all())615sage: em = ExpansionModule(Sequence([hv]))616sage: em.coordinates(2 * hv)617[2]618sage: mps = MonoidPowerSeriesRing(ZZ, NNMonoid())619sage: em = ExpansionModule([mps.one_element()])620sage: em.coordinates(3 * mps.one_element())621[3]622sage: mpsm = MonoidPowerSeriesModule(m, NNMonoid())623sage: hv = MonoidPowerSeries(mpsm, {1: m([1,0,0]), 2: m([0,0,1])}, mpsm.monoid().filter_all())624sage: em = ExpansionModule([hv])625sage: em.coordinates(2 * hv)626[2]627sage: em = ExpansionModule(Sequence([emps.one_element()]))628sage: h = EquivariantMonoidPowerSeries(emps, {}, emps.action().filter_all())629sage: em.coordinates(h)630[0]631sage: em.coordinates(1 / 2 * emps.one_element())632Traceback (most recent call last):633...634ArithmeticError: Equivariant monoid power series in Ring of equivariant monoid power series over NN is not contained in this space.635sage: em.coordinates(1 / 2 * emps.one_element(), in_base_ring = False )636[1/2]637sage: K.<rho> = CyclotomicField(6)638sage: em.coordinates(rho * emps.one_element(), in_base_ring = False)639[zeta6]640sage: h = EquivariantMonoidPowerSeries(emps, {emps.characters().one_element(): {1: 2, 2: 3}}, emps.action().filter_all())641sage: em.coordinates(h)642Traceback (most recent call last):643...644ArithmeticError: Equivariant monoid power series in Ring of equivariant monoid power series over NN is not contained in this space.645sage: em.coordinates(hv)646Traceback (most recent call last):647...648ArithmeticError: No coordinates for Monoid power series in Module of monoid power series over NN with action.649sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element()]))650sage: em.coordinates(2 * emps.one_element())651Traceback (most recent call last):652...653ValueError: Not unambigous coordinates available in this submodule.654sage: h = EquivariantMonoidPowerSeries(emps, {}, emps.action().filter_all())655sage: em = ExpansionModule(Sequence([h]))656sage: em.coordinates(emps.one_element())657Traceback (most recent call last):658...659ValueError: Not unambigous coordinates available in this submodule.660"""661if isinstance(x, Element) :662P = x.parent()663if P is self :664if self.ambient_module() is self :665return x.list()666else :667return list(self.coordinate_vector(x))668669670if isinstance(P, (EquivariantMonoidPowerSeriesAmbient_abstract,671MonoidPowerSeriesAmbient_abstract)) :672673if not force_ambigous and \674not self._check_precision() :675raise ValueError( "Not unambigous coordinates available in this submodule." )676677if P != self.__abstract_basis.universe() :678try :679Pnew = pushout(self.__abstract_basis.universe(), P)680except TypeError :681raise ArithmeticError( "No coordinates for %s." % (x,) )682683if isinstance(Pnew, EquivariantMonoidPowerSeriesAmbient_abstract) \684and Pnew.representation().base_ring() == Pnew.representation().codomain() :685A = Pnew.base_ring()686elif isinstance(Pnew, MonoidPowerSeriesAmbient_abstract) \687and isinstance(Pnew.coefficient_domain(), Ring) :688A = Pnew.base_ring()689else :690A = Pnew.base_ring().base_ring()691692try :693x = Pnew(x)694except TypeError :695raise ArithmeticError( "No coordinates for %s." % (x,) )696else :697A = self.base_ring()698699# check those components of x, which have to be zero700if not self._non_zero_characters() is None :701x._cleanup_coefficients()702if set( x.non_zero_components() ) - set( self._non_zero_characters() ) != set() :703raise ArithmeticError( "%s is not contained in this space." % (x,) )704705if in_base_ring :706fe_matrix = self.fourier_expansion_homomorphism().matrix().transpose()707x_fe_vector = matrix( A, fe_matrix.nrows(),708list(self._element_to_fourier_expansion_generator(x)) )709else :710fe_matrix = self._fourier_expansion_matrix_over_fraction_field().transpose()711x_fe_vector = matrix( A, fe_matrix.nrows(),712list(self._element_to_fourier_expansion_generator(x)) )713714if self._non_zero_characters() is None :715if isinstance(self.__abstract_basis.universe().coefficient_domain(), Ring) :716valid_indices = [ i for (i,k) in enumerate(self._fourier_expansion_indices())717if k in x.precision() ]718else :719valid_indices = [ i for (i,(_,k)) in enumerate(self._fourier_expansion_indices())720if k in x.precision() ]721else :722if isinstance(self.__abstract_basis.universe().coefficient_domain(), Ring) :723valid_indices = [ i for (i,(_,k)) in enumerate(self._fourier_expansion_indices())724if k in x.precision() ]725else :726valid_indices = [ i for (i,(_,(_,k))) in enumerate(self._fourier_expansion_indices())727if k in x.precision() ]728729fe_matrix = fe_matrix.matrix_from_rows(valid_indices)730x_fe_vector = x_fe_vector.matrix_from_rows(valid_indices)731fe_matrix = matrix(A, fe_matrix)732733## TODO: use linbox734try :735## TODO: We deactivate the magma interface as it is almost never used and736## it is in bad shape737if True or (A is not ZZ and A is not QQ) :738raise TypeError739740magma_fe_matrix = magma(fe_matrix.transpose())741742if not force_ambigous and \743len(valid_indices) != self.fourier_expansion_homomorphism().matrix().ncols() and \744magma_fe_matrix.Rank() != self.rank() :745raise ValueError( "No unambigous coordinates available." )746747coords = magma(fe_matrix.transpose()).Solution(magma(x_fe_vector.transpose())).sage()748coords = coords.row(0)749except TypeError, msg :750if "Runtime error in 'Solution': No solution exists" in msg :751raise ArithmeticError( "%s is not contained in this space." % (x,) )752753if not force_ambigous and \754len(valid_indices) != self.fourier_expansion_homomorphism().matrix().ncols() and \755fe_matrix.rank() != self.rank() :756raise ValueError( "No unambigous coordinates available." )757758try :759coords = fe_matrix.solve_right(x_fe_vector)760except ValueError, msg :761raise ArithmeticError( "%s is not contained in this space, %s" % (x, msg) )762coords = coords.column(0)763764if self.precision() != self._bounding_precision() and \765not x.precision() < self._bounding_precision() :766if not self.change_ring(A)(list(coords)).fourier_expansion() == x :767raise ArithmeticError( "%s is not contained in this space." % (x,) )768769if in_base_ring :770try :771return [self.base_ring()(c) for c in coords]772except TypeError :773raise ArithmeticError( "%s is not contained in this space." % (x,) )774else :775return list(coords)776777#! elif isinstance(P, (EquivariantMonoidPowerSeriesAmbient_abstract,778# MonoidPowerSeriesAmbient_abstract)) :779#! if isinstance(x, (tuple, Element)) :780781raise ArithmeticError( "No coordinates for %s." % (x,) )782783def _sparse_module(self):784r"""785TESTS::786sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *787sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *788sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *789sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))790sage: em = ExpansionModule(Sequence([emps.one_element()]))791sage: em._sparse_module()792Traceback (most recent call last):793...794NotImplementedError795"""796raise NotImplementedError797798def _dense_module(self):799r"""800TESTS::801sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *802sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *803sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *804sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))805sage: em = ExpansionModule(Sequence([emps.one_element()]))806sage: em._dense_module() is em807True808"""809return self810811def _repr_(self) :812r"""813TESTS::814sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *815sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *816sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *817sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))818sage: ExpansionModule(Sequence([emps.one_element()]))819Module of Fourier expansions in Ring of equivariant monoid power series over NN820"""821return "Module of Fourier expansions in %s" % (self.__abstract_basis.universe(),)822823def _latex_(self) :824r"""825TESTS::826sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *827sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *828sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *829sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))830sage: latex( ExpansionModule(Sequence([emps.one_element()])) )831\text{Module of Fourier expansions in }\text{Ring of equivariant monoid power series over }\Bold{N}832"""833return r"\text{Module of Fourier expansions in }%s" % (latex(self.__abstract_basis.universe()),)834835836class ExpansionModule_generic ( ExpansionModule_abstract, FreeModule_generic ) :837r"""838A generic module of abstract elements with Fourier expansions attached to.839The base ring has to be an integral domain.840"""841842def __init__(self, basis, degree, **kwds) :843r"""844INPUT:845- ``basis`` -- A sequence of (equivariant) monoid power series.846- ``degree`` -- An integer; The ambient's module dimension.847- ``kwds`` -- A keyword dictionary that will be forwarded to848initialization of the underlying free module.849850NOTE:851The base ring of the expansions' parent must be an integral852domain.853854TESTS::855sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *856sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *857sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_generic, ExpansionModuleVector_generic858sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *859sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))860sage: em = ExpansionModule_generic(Sequence([emps.one_element()]), 2)861sage: em = ExpansionModule_generic(Sequence([emps.one_element()]), 2, _element_class = ExpansionModuleVector_generic )862"""863if not hasattr(self, '_element_class') :864if '_element_class' in kwds :865self._element_class = kwds['_element_class']866else :867self._element_class = ExpansionModuleVector_generic868869ExpansionModule_abstract.__init__(self, basis)870FreeModule_generic.__init__(self, basis.universe().base_ring(), len(basis), degree, sparse = False)871872def gen(self, i) :873r"""874The `i`-th generator of the module.875876INPUT:877- `i` -- An integer.878879OUTPUT:880An element of ``self``.881882TESTS::883sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *884sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *885sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_generic886sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *887sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))888sage: em = ExpansionModule_generic(Sequence([emps.one_element()]), 1)889sage: em.gen(0)890Traceback (most recent call last):891...892NotImplementedError893"""894raise NotImplementedError895896def basis(self) :897r"""898A basis of ``self``.899900OUTPUT:901A list of elements of ``self``.902903TESTS::904sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *905sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *906sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_generic907sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *908sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))909sage: em = ExpansionModule_generic(Sequence([emps.one_element()]), 1)910sage: em.basis()911Traceback (most recent call last):912...913NotImplementedError914"""915raise NotImplementedError916917def change_ring(self, R):918r"""919Return the ambient expansion module over `R` with the same basis as ``self``.920921INPUT:922- `R` -- A ring.923924OUTPUT:925An instance of :class:~`.ExpansionModule_generic`.926927TESTS::928sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *929sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *930sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *931sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_generic932sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))933sage: em = ExpansionModule_generic(Sequence([emps.one_element()]), 2)934sage: em.change_ring(ZZ) is em935True936sage: em.change_ring(QQ).base_ring()937Rational Field938"""939if self.base_ring() == R :940return self941942R = pushout(self._abstract_basis().universe(), R)943944return ExpansionModule_generic(Sequence(self._abstract_basis(), universe = R), self.degree(), _element_class = self._element_class)945946#===============================================================================947# _fourier_expansion_kernel948#949# This will be used in ExpansionModule_ambient_pid and950# ExpansionModule_submodule_pid951#===============================================================================952953def _fourier_expansion_kernel(self) :954r"""955The kernel of the Fourier expansion morphism.956957OUTPUT:958A module over the basis ring.959960SEE:961:meth:~`.ExpansionModule_abstract.fourier_expansion_homomorphism`.962963TESTS::964sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *965sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *966sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *967sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))968sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))969sage: em.fourier_expansion_kernel()970Free module of degree 3 and rank 2 over Integer Ring971Echelon basis matrix:972[ 1 0 -1]973[ 0 1 -1]974sage: em.span([em([1,0,0]), em([1,2,0])]).fourier_expansion_kernel()975Free module of degree 2 and rank 1 over Integer Ring976Echelon basis matrix:977[ 3 -1]978"""979return self.fourier_expansion_homomorphism().matrix().left_kernel()980981#===============================================================================982# _span983#984# This will be used in ExpansionModule_ambient_pid and985# ExpansionModule_submodule_pid986#===============================================================================987988def _span( self, gens, base_ring = None, check = True, already_echelonized = False ) :989r"""990The expansion submodule spanned by ``gens``.991992INPUT:993- ``gens`` -- A list, tuple or sequence of module elements.994- ``base_ring`` -- A ring or ``None`` (default: ``None``); If ``None``995the base ring of ``self`` will be used.996- ``check`` -- A boolean (default: ``True``); If ``True`` check997whether the generators are appropriately coerced.998- ``already_echelonized`` -- A boolean (default: ``False``); If ``True``999the generators are already in echelon form1000with respect to the ambient's basis.10011002OUTPUT:1003An instance of :class:~`.ExpansionModule_submodule_pid`.10041005TESTS::1006sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *1007sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *1008sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *1009sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))1010sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))1011sage: em.span([em([1,0,0]), em([1,2,0])])1012Module of Fourier expansions in Ring of equivariant monoid power series over NN1013sage: em.span([em([1,0,0]), em([1,2,0])]).span([em([1,0,0])])1014Module of Fourier expansions in Ring of equivariant monoid power series over NN1015"""1016if is_FreeModule(gens):1017gens = gens.gens()1018if not isinstance(gens, (list, tuple, Sequence)):1019raise TypeError, "Argument gens (= %s) must be a list, tuple, or sequence." % (gens,)10201021if base_ring is None or base_ring == self.base_ring() :1022gens = Sequence(gens, check = check, universe = self.ambient_module())10231024return ExpansionModule_submodule_pid(self.ambient_module(), gens)1025else:1026try:1027M = self.ambient_module().change_ring(base_ring)1028except TypeError:1029raise ValueError, "Argument base_ring (= %s) is not compatible " % (base_ring,) + \1030"with the base field (= %s)." % (self.base_field(),)1031try:1032return M.span(gens)1033except TypeError:1034raise ValueError, "Argument gens (= %s) is not compatible " % (gens,) + \1035"with base_ring (= %s)." % (base_ring,)10361037#===============================================================================1038# ExpansionModule_ambient_pid1039#===============================================================================10401041class ExpansionModule_ambient_pid ( ExpansionModule_abstract, FreeModule_ambient_pid ) :1042r"""1043An ambient module of expansions over a principal ideal domain.1044"""10451046def __init__(self, basis, _element_class = None, **kwds) :1047r"""1048INPUT:1049- ``basis`` -- A list or sequence of (equivariant) monoid power series.1050- ``element_class`` -- A type or ``None`` (default: ``None``); The element class1051attached to ``self``. If ``None`` :class:~`.ExpansionModuleVector_generic`1052will be used.10531054TESTS::1055sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *1056sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *1057sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *1058sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid, ExpansionModuleVector_generic1059sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))1060sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))1061sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]), _element_class = ExpansionModuleVector_generic)1062"""1063if not hasattr(self, '_element_class') :1064if not _element_class is None :1065self._element_class = _element_class1066else :1067self._element_class = ExpansionModuleVector_generic10681069if isinstance(basis.universe(), EquivariantMonoidPowerSeriesAmbient_abstract) \1070and basis.universe().representation().base_ring() == basis.universe().representation().codomain() :1071base_ring = basis.universe().base_ring()1072elif isinstance(basis.universe(), MonoidPowerSeriesAmbient_abstract) \1073and isinstance(basis.universe().coefficient_domain(), Ring) :1074base_ring = basis.universe().base_ring()1075else :1076base_ring = basis.universe().base_ring().base_ring()10771078ExpansionModule_abstract.__init__(self, basis)1079FreeModule_ambient_pid.__init__(self, base_ring, len(basis))10801081global _fourier_expansion_kernel, _span1082fourier_expansion_kernel = _fourier_expansion_kernel1083span = _span10841085def gen(self, i) :1086r"""1087The `i`-th generator of the module.10881089INPUT:1090- `i` -- An integer.10911092OUTPUT:1093An element of ``self``.10941095TESTS::1096sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *1097sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *1098sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *1099sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid1100sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))1101sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))1102sage: em.gen(0)1103(1, 0, 0)1104"""1105return self._element_class(self, FreeModule_ambient_pid.gen(self, i))11061107def basis(self) :1108r"""1109A basis of ``self``.11101111OUTPUT:1112A list of elements of ``self``.11131114TESTS::1115sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *1116sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *1117sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *1118sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid1119sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))1120sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))1121sage: em.basis()1122[(1, 0, 0), (0, 1, 0), (0, 0, 1)]1123"""1124return map(lambda b: self._element_class(self, b), FreeModule_ambient_pid.basis(self))11251126def change_ring(self, R):1127r"""1128Return the ambient expansion module over `R` with the same basis as ``self``.11291130INPUT:1131- `R` -- A ring.11321133OUTPUT:1134An instance of :class:~`.ExpansionModule_ambient_pid`.11351136TESTS::1137sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *1138sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *1139sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *1140sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid1141sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))1142sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))1143sage: em.change_ring(ZZ) is em1144True1145sage: emq = em.change_ring(QQ)1146sage: emq.base_ring()1147Rational Field1148sage: emq.ambient_module() is emq1149True1150"""1151if self.base_ring() == R :1152return self11531154R = pushout(self._abstract_basis().universe(), R)11551156return ExpansionModule_ambient_pid(Sequence(self._abstract_basis(), universe = R), _element_class = self._element_class)11571158def ambient_module(self) :1159r"""1160Return the ambient module of ``self``.11611162OUTPUT:1163An instance of :class:~`.ExpansionModule_ambient_pid`.11641165TESTS::1166sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *1167sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *1168sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *1169sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid1170sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))1171sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))1172sage: em.ambient_module() is em1173True1174"""1175return self11761177#===============================================================================1178# ExpansionModule_submodule_pid1179#===============================================================================11801181class ExpansionModule_submodule_pid ( ExpansionModule_abstract, FreeModule_submodule_pid ) :1182r"""1183A submodule of another module of expansions over a principal ideal domain.1184"""11851186def __init__(self, ambient, gens, _element_class = None, **kwds) :1187r"""1188INPUT:1189- ``ambient`` -- An instance of :class:~`.ExpansionModule_ambient_pid` or :class:~`.ExpansionModule_submodule_pid`.1190- ``gens`` -- A list, tuple or sequence of elements of ``ambient``.1191- ``element_class`` -- A type or ``None`` (default: ``None``); The element class1192attached to ``self``. If ``None`` :class:~`.ExpansionModuleVector_generic`1193will be used.11941195TESTS::1196sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *1197sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *1198sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *1199sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid, ExpansionModule_submodule_pid, ExpansionModuleVector_generic1200sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))1201sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))1202sage: ems = ExpansionModule_submodule_pid(em, [em([1,0,0]), em([1,2,0])])1203sage: ems = ExpansionModule_submodule_pid(em, [em([1,0,0]), em([1,2,0])], _element_class = ExpansionModuleVector_generic)1204"""1205if not hasattr(self, '_element_class') :1206if not _element_class is None :1207self._element_class = _element_class1208else :1209self._element_class = ExpansionModuleVector_generic12101211if ambient.precision().is_infinite() :1212ExpansionModule_abstract.__init__(self, Sequence( map( lambda g: g.fourier_expansion(), gens ),1213universe = ambient._abstract_basis().universe() ))1214else :1215ExpansionModule_abstract.__init__(self, Sequence( map( lambda g: LazyFourierExpansionEvaluation( ambient._abstract_basis().universe(), g,1216ambient.precision() ),1217gens ),1218universe = ambient._abstract_basis().universe() ))1219FreeModule_submodule_pid.__init__(self, ambient, gens)12201221global _fourier_expansion_kernel, _span1222fourier_expansion_kernel = _fourier_expansion_kernel1223span = _span12241225def gen(self, i) :1226r"""1227The `i`-th generator of the module.12281229INPUT:1230- `i` -- An integer.12311232OUTPUT:1233An element of ``self``.12341235TESTS::1236sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *1237sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *1238sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *1239sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid, ExpansionModule_submodule_pid1240sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))1241sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))1242sage: ems = ExpansionModule_submodule_pid(em, [em([1,0,0]), em([1,2,0])])1243sage: ems.gen(0)1244(1, 0, 0)1245"""1246return self._element_class(self, super(ExpansionModule_submodule_pid, self).gen(i).list())12471248# TODO: The module should be hidden so that we can adopt the category framework1249# def basis(self) :1250# r"""1251# A basis of ``self``.12521253# OUTPUT:1254# A list of elements of ``self``.12551256# TESTS::1257# sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *1258# sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *1259# sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *1260# sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid, ExpansionModule_submodule_pid1261# sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))1262# sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))1263# sage: ems = ExpansionModule_submodule_pid(em, [em([1,0,0]), em([1,2,0])])1264# sage: ems.basis()1265# [(1, 0, 0), (0, 2, 0)]1266# """1267# return [self._element_class(self, b.list()) for b in super().basis()]12681269def change_ring(self, R):1270r"""1271Return the ambient expansion module over `R` with the same basis as ``self``.12721273INPUT:1274- `R` -- A ring.12751276OUTPUT:1277An instance of :class:~`.ExpansionModule_ambient_pid`.1278TESTS::1279sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *1280sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *1281sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *1282sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModule_ambient_pid, ExpansionModule_submodule_pid1283sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))1284sage: em = ExpansionModule_ambient_pid(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))1285sage: ems = ExpansionModule_submodule_pid(em, [em([1,0,0]), em([1,2,0])])1286sage: emc = ems.change_ring(ZZ)1287sage: emc.ambient_module() is emc1288True1289sage: emc = ems.change_ring(QQ)1290sage: emc.ambient_module() is emc1291True1292sage: emc.base_ring()1293Rational Field1294"""1295if self.base_ring() == R :1296return ExpansionModule_ambient_pid(self._abstract_basis(), _element_class = self._element_class)12971298R = pushout(self._abstract_basis().universe(), R)12991300return ExpansionModule_ambient_pid(Sequence(self._abstract_basis(), universe = R), _element_class = self._element_class)13011302#===============================================================================1303# ExpansionModuleVector_generic1304#===============================================================================13051306class ExpansionModuleVector_generic ( FreeModuleElement_generic_dense, FourierExpansionWrapper ) :1307r"""1308A generic implementation of an element in a module of expansions.1309"""13101311def __init__(self, parent, x, coerce = True, copy = True) :1312r"""1313INPUT:1314- ``parent`` -- An instance of :class:~`.ExpansionModule_abstract`.1315- `x` -- A list or tuple of integers or an element that admits coordinates1316in ``parent``.1317- ``coerce`` -- A boolean (default: ``True``); If ``True`` coerce coordinates into the base ring.1318- ``copy`` -- A boolean (default: ``True``); If ``True`` store a copy of the coordinates.13191320TESTS::1321sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *1322sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *1323sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *1324sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModuleVector_generic1325sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))1326sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))1327sage: ExpansionModuleVector_generic(em, [1,0,2])1328(1, 0, 2)1329"""1330if not isinstance(x, (list, tuple)) and x != 0 :1331x = parent.ambient_module().coordinates(x)1332coerce = False1333copy = False13341335FreeModuleElement_generic_dense.__init__(self, parent, x, coerce, copy)13361337def _add_(left, right) :1338r"""1339TESTS::1340sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *1341sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *1342sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *1343sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))1344sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))1345sage: em.0 + em.11346(1, 1, 0)1347"""1348return left.parent()._element_class(left.parent(), FreeModuleElement_generic_dense._add_(left, right))13491350def __copy__(self) :1351r"""1352Return a copy of ``self``.13531354OUTPUT:1355An instance of :class:~`.ExpansionModuleVector_generic`.13561357TESTS::1358sage: from psage.modform.fourier_expansion_framework.gradedexpansions import *1359sage: from psage.modform.fourier_expansion_framework.monoidpowerseries import *1360sage: from psage.modform.fourier_expansion_framework.monoidpowerseries.monoidpowerseries_basicmonoids import *1361sage: from psage.modform.fourier_expansion_framework.gradedexpansions.expansion_module import ExpansionModuleVector_generic1362sage: emps = EquivariantMonoidPowerSeriesRing(NNMonoid(True), TrivialCharacterMonoid("1", ZZ), TrivialRepresentation("1", ZZ))1363sage: em = ExpansionModule(Sequence([emps.one_element(), emps.one_element(), emps.one_element()]))1364sage: copy(ExpansionModuleVector_generic(em, [1,0,2])) == ExpansionModuleVector_generic(em, [1,0,2])1365True1366"""1367return ExpansionModuleVector_generic( self.parent(), self.list(), coerce = False, copy = True)136813691370