Path: blob/master/src/sage/modular/modsym/p1list_nf.py
8820 views
r"""1Lists of Manin symbols (elements of `\mathbb{P}^1(R/N)`) over number fields23Lists of elements of `\mathbb{P}^1(R/N)` where `R` is the ring of integers of a number4field `K` and `N` is an integral ideal.56AUTHORS:78- Maite Aranes (2009): Initial version910EXAMPLES:1112We define a P1NFList:1314::1516sage: k.<a> = NumberField(x^3 + 11)17sage: N = k.ideal(5, a^2 - a + 1)18sage: P = P1NFList(N); P19The projective line over the ring of integers modulo the Fractional ideal (5, a^2 - a + 1)2021List operations with the P1NFList:2223::2425sage: len(P)262627sage: [p for p in P]28[M-symbol (0: 1) of level Fractional ideal (5, a^2 - a + 1),29...30M-symbol (1: 2*a^2 + 2*a) of level Fractional ideal (5, a^2 - a + 1)]3132The elements of the P1NFList are M-symbols:3334::3536sage: type(P[2])37<class 'sage.modular.modsym.p1list_nf.MSymbol'>3839Definition of MSymbols:4041::4243sage: alpha = MSymbol(N, 3, a^2); alpha44M-symbol (3: a^2) of level Fractional ideal (5, a^2 - a + 1)4546Find the index of the class of an M-Symbol `(c: d)` in the list:4748::4950sage: i = P.index(alpha)51sage: P[i].c*alpha.d - P[i].d*alpha.c in N52True5354Lift an MSymbol to a matrix in `SL(2, R)`:5556::5758sage: alpha = MSymbol(N, a + 2, 3*a^2)59sage: alpha.lift_to_sl2_Ok()60[1, -4*a^2 + 9*a - 21, a + 2, a^2 - 3*a + 3]61sage: Ok = k.ring_of_integers()62sage: M = Matrix(Ok, 2, alpha.lift_to_sl2_Ok())63sage: det(M)64165sage: M[1][1] - alpha.d in N66True6768Lift an MSymbol from P1NFList to a matrix in `SL(2, R)`6970::7172sage: P[3]73M-symbol (1: -2*a) of level Fractional ideal (5, a^2 - a + 1)74sage: P.lift_to_sl2_Ok(3)75[0, -1, 1, -2*a]76"""77#*****************************************************************************78# Copyright (C) 2009, Maite Aranes <[email protected]>79#80# Distributed under the terms of the GNU General Public License (GPL)81# http://www.gnu.org/licenses/82#*****************************************************************************838485from sage.structure.sage_object import SageObject8687from sage.misc.search import search8889_level_cache = {} # The info stored here is used in the normalization of MSymbols.9091def P1NFList_clear_level_cache():92"""93Clear the global cache of data for the level ideals.9495EXAMPLES::9697sage: k.<a> = NumberField(x^3 + 11)98sage: N = k.ideal(a+1)99sage: alpha = MSymbol(N, 2*a^2, 5)100sage: alpha.normalize()101M-symbol (-4*a^2: 5*a^2) of level Fractional ideal (a + 1)102sage: sage.modular.modsym.p1list_nf._level_cache103{Fractional ideal (a + 1): (...)}104sage: sage.modular.modsym.p1list_nf.P1NFList_clear_level_cache()105sage: sage.modular.modsym.p1list_nf._level_cache106{}107"""108global _level_cache109_level_cache = {}110111112class MSymbol(SageObject):113"""114The constructor for an M-symbol over a number field.115116INPUT:117118- ``N`` -- integral ideal (the modulus or level).119120- ``c`` -- integral element of the underlying number field or an MSymbol of121level N.122123- ``d`` -- (optional) when present, it must be an integral element such124that <c> + <d> + N = R, where R is the corresponding ring of integers.125126- ``check`` -- bool (default True). If ``check=False`` the constructor does127not check the condition <c> + <d> + N = R.128129OUTPUT:130131An M-symbol modulo the given ideal N, i.e. an element of the132projective line `\\mathbb{P}^1(R/N)`, where R is the ring of integers of133the underlying number field.134135EXAMPLES::136137sage: k.<a> = NumberField(x^3 + 11)138sage: N = k.ideal(a + 1, 2)139sage: MSymbol(N, 3, a^2 + 1)140M-symbol (3: a^2 + 1) of level Fractional ideal (2, a + 1)141142We can give a tuple as input:143144::145146sage: MSymbol(N, (1, 0))147M-symbol (1: 0) of level Fractional ideal (2, a + 1)148149We get an error if <c>, <d> and N are not coprime:150151::152153sage: MSymbol(N, 2*a, a - 1)154Traceback (most recent call last):155...156ValueError: (2*a, a - 1) is not an element of P1(R/N).157sage: MSymbol(N, (0, 0))158Traceback (most recent call last):159...160ValueError: (0, 0) is not an element of P1(R/N).161162Saving and loading works:163164::165166sage: alpha = MSymbol(N, 3, a^2 + 1)167sage: loads(dumps(alpha))==alpha168True169"""170def __init__(self, N, c, d=None, check=True):171"""172See ``MSymbol`` for full documentation.173174EXAMPLES::175176sage: k.<a> = NumberField(x^4 + 13*x - 7)177sage: N = k.ideal(5)178sage: MSymbol(N, 0, 6*a)179M-symbol (0: 6*a) of level Fractional ideal (5)180sage: MSymbol(N, a^2 + 3, 7)181M-symbol (a^2 + 3: 7) of level Fractional ideal (5)182"""183k = N.number_field()184R = k.ring_of_integers()185self.__N = N186if d is None: # if we give a list (c, d) or an MSymbol as input187if isinstance(c, MSymbol):188if c.N() is N:189c1 = R(c[0])190d1 = R(c[1])191else:192raise ValueError, "Cannot change level of an MSymbol"193else:194try:195c1 = R(c[0])196d1 = R(c[1])197except (ValueError, TypeError):198raise TypeError, "Unable to create a Manin symbol from %s"%c199else:200try:201c1 = R(c)202d1 = R(d)203except (ValueError, TypeError):204raise TypeError, "Unable to create a Manin symbol from (%s, %s)"%(c, d)205if check:206if (c1.is_zero() and d1.is_zero()) or not N.is_coprime(k.ideal(c1, d1)):207raise ValueError, "(%s, %s) is not an element of P1(R/N)."%(c1, d1)208self.__c, self.__d = (c1, d1)209210def __repr__(self):211"""212Returns the string representation of this MSymbol.213214EXAMPLES::215216sage: k.<a> = NumberField(x^2 + 23)217sage: N = k.ideal(3, a - 1)218sage: MSymbol(N, 3, a)219M-symbol (3: a) of level Fractional ideal (3, 1/2*a - 1/2)220"""221return "M-symbol (%s: %s) of level %s"%(self.__c, self.__d, self.__N)222223def _latex_(self):224r"""225Return latex representation of self.226227EXAMPLES::228229sage: k.<a> = NumberField(x^4 + 13*x - 7)230sage: N = k.ideal(a^3 - 1)231sage: alpha = MSymbol(N, 3, 5*a^2 - 1)232sage: latex(alpha) # indirect doctest233\(3: 5 a^{2} - 1\)234"""235return "\\(%s: %s\)"%(self.c._latex_(), self.d._latex_())236237def __cmp__(self, other):238"""239Comparison function for objects of the class MSymbol.240241The order is the same as for the underlying lists of lists.242243EXAMPLES::244245sage: k.<a> = NumberField(x^2 + 23)246sage: N = k.ideal(3, a - 1)247sage: alpha = MSymbol(N, 3, a)248sage: beta = MSymbol(N, 1, 0)249sage: alpha < beta250False251sage: beta = MSymbol(N, 3, a + 1)252sage: alpha < beta253True254"""255if not isinstance(other, MSymbol):256raise ValueError, "You can only compare with another M-symbol"257return cmp([self.__c.list(), self.__d.list()],258[other.__c.list(), other.__d.list()])259260def N(self):261"""262Returns the level or modulus of this MSymbol.263264EXAMPLES::265266sage: k.<a> = NumberField(x^2 + 23)267sage: N = k.ideal(3, a - 1)268sage: alpha = MSymbol(N, 3, a)269sage: alpha.N()270Fractional ideal (3, 1/2*a - 1/2)271"""272return self.__N273274def tuple(self):275"""276Returns the MSymbol as a list (c, d).277278EXAMPLES::279280sage: k.<a> = NumberField(x^2 + 23)281sage: N = k.ideal(3, a - 1)282sage: alpha = MSymbol(N, 3, a); alpha283M-symbol (3: a) of level Fractional ideal (3, 1/2*a - 1/2)284sage: alpha.tuple()285(3, a)286"""287return self.__c, self.__d288289def __getitem__(self, n):290"""291Indexing function for the list defined by an M-symbol.292293INPUT:294295- ``n`` -- integer (0 or 1, since the list defined by an M-symbol has296length 2)297298EXAMPLES::299300sage: k.<a> = NumberField(x^2 + 23)301sage: N = k.ideal(3, a - 1)302sage: alpha = MSymbol(N, 3, a); alpha303M-symbol (3: a) of level Fractional ideal (3, 1/2*a - 1/2)304sage: alpha[0]3053306sage: alpha[1]307a308"""309return self.tuple()[n]310311def __get_c(self):312"""313Returns the first coefficient of the M-symbol.314315EXAMPLES::316317sage: k.<a> = NumberField(x^3 + 11)318sage: N = k.ideal(a + 1, 2)319sage: alpha = MSymbol(N, 3, a^2 + 1)320sage: alpha.c # indirect doctest3213322"""323return self.__c324c = property(__get_c)325326def __get_d(self):327"""328Returns the second coefficient of the M-symbol.329330EXAMPLES::331332sage: k.<a> = NumberField(x^3 + 11)333sage: N = k.ideal(a + 1, 2)334sage: alpha = MSymbol(N, 3, a^2 + 1)335sage: alpha.d # indirect doctest336a^2 + 1337"""338return self.__d339d = property(__get_d)340341def lift_to_sl2_Ok(self):342"""343Lift the MSymbol to an element of `SL(2, Ok)`, where `Ok` is the ring344of integers of the corresponding number field.345346OUTPUT:347348A list of integral elements `[a, b, c', d']` that are the entries of349a 2x2 matrix with determinant 1. The lower two entries are congruent350(modulo the level) to the coefficients `c, d` of the MSymbol self.351352EXAMPLES::353354sage: k.<a> = NumberField(x^2 + 23)355sage: N = k.ideal(3, a - 1)356sage: alpha = MSymbol(N, 3*a + 1, a)357sage: alpha.lift_to_sl2_Ok()358[0, -1, 1, a]359"""360return lift_to_sl2_Ok(self.__N, self.__c, self.__d)361362def normalize(self, with_scalar=False):363"""364Returns a normalized MSymbol (a canonical representative of an element365of `\mathbb{P}^1(R/N)` ) equivalent to ``self``.366367INPUT:368369- ``with_scalar`` -- bool (default False)370371OUTPUT:372373- (only if ``with_scalar=True``) a transforming scalar `u`, such that374`(u*c', u*d')` is congruent to `(c: d)` (mod `N`), where `(c: d)`375are the coefficients of ``self`` and `N` is the level.376377- a normalized MSymbol (c': d') equivalent to ``self``.378379EXAMPLES::380381sage: k.<a> = NumberField(x^2 + 23)382sage: N = k.ideal(3, a - 1)383sage: alpha1 = MSymbol(N, 3, a); alpha1384M-symbol (3: a) of level Fractional ideal (3, 1/2*a - 1/2)385sage: alpha1.normalize()386M-symbol (0: 1) of level Fractional ideal (3, 1/2*a - 1/2)387sage: alpha2 = MSymbol(N, 4, a + 1)388sage: alpha2.normalize()389M-symbol (1: -a) of level Fractional ideal (3, 1/2*a - 1/2)390391We get the scaling factor by setting ``with_scalar=True``:392393::394395sage: alpha1.normalize(with_scalar=True)396(a, M-symbol (0: 1) of level Fractional ideal (3, 1/2*a - 1/2))397sage: r, beta1 = alpha1.normalize(with_scalar=True)398sage: r*beta1.c - alpha1.c in N399True400sage: r*beta1.d - alpha1.d in N401True402sage: r, beta2 = alpha2.normalize(with_scalar=True)403sage: r*beta2.c - alpha2.c in N404True405sage: r*beta2.d - alpha2.d in N406True407"""408N = self.__N409k = N.number_field()410R = k.ring_of_integers()411412if self.__c in N:413if with_scalar:414return N.reduce(self.d), MSymbol(N, 0, 1)415else:416return MSymbol(N, 0, 1)417if self.d in N:418if with_scalar:419return N.reduce(self.c), MSymbol(N, 1, 0)420else:421return MSymbol(N, 1, 0)422if N.is_coprime(self.c):423cinv = R(self.c).inverse_mod(N)424if with_scalar:425return N.reduce(self.c), MSymbol(N, 1, N.reduce(self.d*cinv))426else:427return MSymbol(N, 1, N.reduce(self.d*cinv))428429if _level_cache.has_key(N):430Lfacs, Lxs = _level_cache[N]431else:432Lfacs = [p**e for p, e in N.factor()]433Lxs = [(N/p).element_1_mod(p) for p in Lfacs]434# Lfacs, Lxs only depend of the ideal: same lists every time we435# call normalize for a given level, so we store the lists.436_level_cache[N] = (Lfacs, Lxs)437u = 0 # normalizer factor438p_i = 0439for p in Lfacs:440if p.is_coprime(self.c):441inv = self.c.inverse_mod(p)442else:443inv = self.d.inverse_mod(p)444u = u + inv*Lxs[p_i]445p_i = p_i + 1446c, d = (N.reduce(u*self.c), N.reduce(u*self.d))447if (c - 1) in N:448c = R(1)449if with_scalar:450return u.inverse_mod(N), MSymbol(N, c, d)451else:452return MSymbol(N, c, d)453454455#**************************************************************************456#* P1NFList class *457#**************************************************************************458class P1NFList(SageObject):459"""460The class for `\mathbb{P}^1(R/N)`, the projective line modulo `N`, where461`R` is the ring of integers of a number field `K` and `N` is an integral ideal.462463INPUT:464465- ``N`` - integral ideal (the modulus or level).466467OUTPUT:468469A P1NFList object representing `\mathbb{P}^1(R/N)`.470471EXAMPLES::472473sage: k.<a> = NumberField(x^3 + 11)474sage: N = k.ideal(5, a + 1)475sage: P = P1NFList(N); P476The projective line over the ring of integers modulo the Fractional ideal (5, a + 1)477478Saving and loading works.479480::481482sage: loads(dumps(P)) == P483True484"""485def __init__(self, N):486"""487The constructor for the class P1NFList. See ``P1NFList`` for full488documentation.489490EXAMPLES::491492sage: k.<a> = NumberField(x^2 + 5)493sage: N = k.ideal(3, a - 1)494sage: P = P1NFList(N); P495The projective line over the ring of integers modulo the Fractional ideal (3, a + 2)496"""497self.__N = N498self.__list = p1NFlist(N)499self.__list.sort()500501def __cmp__(self, other):502"""503Comparison function for objects of the class P1NFList.504505The order is the same as for the underlying modulus.506507EXAMPLES::508509sage: k.<a> = NumberField(x^2 + 23)510sage: N1 = k.ideal(3, a + 1)511sage: P1 = P1NFList(N1)512sage: N2 = k.ideal(a + 2)513sage: P2 = P1NFList(N2)514sage: P1 < P2515False516sage: P1 > P2517True518sage: P1 == P1NFList(N1)519True520"""521if not isinstance(other, P1NFList):522raise ValueError, "You can only compare with another P1NFList"523return cmp(self.__N, other.__N)524525def __getitem__(self, n):526"""527Standard indexing function for the class P1NFList.528529EXAMPLES::530531sage: k.<a> = NumberField(x^3 + 11)532sage: N = k.ideal(a)533sage: P = P1NFList(N)534sage: list(P) == P._P1NFList__list535True536sage: j = randint(0,len(P)-1)537sage: P[j] == P._P1NFList__list[j]538True539"""540return self.__list[n]541542def __len__(self):543"""544Returns the length of this P1NFList.545546EXAMPLES::547548sage: k.<a> = NumberField(x^3 + 11)549sage: N = k.ideal(5, a^2 - a + 1)550sage: P = P1NFList(N)551sage: len(P)55226553"""554return len(self.__list)555556def __repr__(self):557"""558Returns the string representation of this P1NFList.559560EXAMPLES::561562sage: k.<a> = NumberField(x^3 + 11)563sage: N = k.ideal(5, a+1)564sage: P = P1NFList(N); P565The projective line over the ring of integers modulo the Fractional ideal (5, a + 1)566567"""568return "The projective line over the ring of integers modulo the %s"%self.__N569570def list(self):571"""572Returns the underlying list of this P1NFList object.573574EXAMPLES::575576sage: k.<a> = NumberField(x^3 + 11)577sage: N = k.ideal(5, a+1)578sage: P = P1NFList(N)579sage: type(P)580<class 'sage.modular.modsym.p1list_nf.P1NFList'>581sage: type(P.list())582<type 'list'>583"""584return self.__list585586def normalize(self, c, d=None, with_scalar=False):587"""588Returns a normalised element of `\mathbb{P}^1(R/N)`.589590INPUT:591592- ``c`` -- integral element of the underlying number field, or an593MSymbol.594595- ``d`` -- (optional) when present, it must be an integral element of596the number field such that `(c, d)` defines an M-symbol of level `N`.597598- ``with_scalar`` -- bool (default False)599600OUTPUT:601602- (only if ``with_scalar=True``) a transforming scalar `u`, such that603`(u*c', u*d')` is congruent to `(c: d)` (mod `N`).604605- a normalized MSymbol (c': d') equivalent to `(c: d)`.606607EXAMPLES::608609sage: k.<a> = NumberField(x^2 + 31)610sage: N = k.ideal(5, a + 3)611sage: P = P1NFList(N)612sage: P.normalize(3, a)613M-symbol (1: 2*a) of level Fractional ideal (5, 1/2*a + 3/2)614615We can use an MSymbol as input:616617::618619sage: alpha = MSymbol(N, 3, a)620sage: P.normalize(alpha)621M-symbol (1: 2*a) of level Fractional ideal (5, 1/2*a + 3/2)622623If we are interested in the normalizing scalar:624625::626627sage: P.normalize(alpha, with_scalar=True)628(-a, M-symbol (1: 2*a) of level Fractional ideal (5, 1/2*a + 3/2))629sage: r, beta = P.normalize(alpha, with_scalar=True)630sage: (r*beta.c - alpha.c in N) and (r*beta.d - alpha.d in N)631True632"""633if d is None:634try:635c = MSymbol(self.__N, c) # check that c is an MSymbol636except ValueError: # catch special case of wrong level637raise ValueError, "The MSymbol is of a different level"638return c.normalize(with_scalar)639return MSymbol(self.N(), c, d).normalize(with_scalar)640641def N(self):642"""643Returns the level or modulus of this P1NFList.644645EXAMPLES::646647sage: k.<a> = NumberField(x^2 + 31)648sage: N = k.ideal(5, a + 3)649sage: P = P1NFList(N)650sage: P.N()651Fractional ideal (5, 1/2*a + 3/2)652"""653return self.__N654655def index(self, c, d=None, with_scalar=False):656"""657Returns the index of the class of the pair `(c, d)` in the fixed list658of representatives of `\mathbb{P}^1(R/N)`.659660INPUT:661662- ``c`` -- integral element of the corresponding number field, or an663MSymbol.664665- ``d`` -- (optional) when present, it must be an integral element of666the number field such that `(c, d)` defines an M-symbol of level `N`.667668- ``with_scalar`` -- bool (default False)669670OUTPUT:671672- ``u`` - the normalizing scalar (only if ``with_scalar=True``)673674- ``i`` - the index of `(c, d)` in the list.675676EXAMPLES::677678sage: k.<a> = NumberField(x^2 + 31)679sage: N = k.ideal(5, a + 3)680sage: P = P1NFList(N)681sage: P.index(3,a)6825683sage: P[5]==MSymbol(N, 3, a).normalize()684True685686We can give an MSymbol as input:687688::689690sage: alpha = MSymbol(N, 3, a)691sage: P.index(alpha)6925693694We cannot look for the class of an MSymbol of a different level:695696::697698sage: M = k.ideal(a + 1)699sage: beta = MSymbol(M, 0, 1)700sage: P.index(beta)701Traceback (most recent call last):702...703ValueError: The MSymbol is of a different level704705If we are interested in the transforming scalar:706707::708709sage: alpha = MSymbol(N, 3, a)710sage: P.index(alpha, with_scalar=True)711(-a, 5)712sage: u, i = P.index(alpha, with_scalar=True)713sage: (u*P[i].c - alpha.c in N) and (u*P[i].d - alpha.d in N)714True715"""716if d is None:717try:718c = MSymbol(self.__N, c) # check that c is an MSymbol719except ValueError: # catch special case of wrong level720raise ValueError, "The MSymbol is of a different level"721if with_scalar:722u, norm_c = c.normalize(with_scalar=True)723else:724norm_c = c.normalize()725else:726if with_scalar:727u, norm_c = MSymbol(self.__N, c, d).normalize(with_scalar=True)728else:729norm_c = MSymbol(self.__N, c, d).normalize()730t, i = search(self.__list, norm_c)731if t:732if with_scalar:733return u, i734else:735return i736return False737738def index_of_normalized_pair(self, c, d=None):739"""740Returns the index of the class `(c, d)` in the fixed list of741representatives of `\mathbb(P)^1(R/N)`.742743INPUT:744745- ``c`` -- integral element of the corresponding number field, or a746normalized MSymbol.747748- ``d`` -- (optional) when present, it must be an integral element of749the number field such that `(c, d)` defines a normalized M-symbol of750level `N`.751752OUTPUT:753754- ``i`` - the index of `(c, d)` in the list.755756EXAMPLES::757758sage: k.<a> = NumberField(x^2 + 31)759sage: N = k.ideal(5, a + 3)760sage: P = P1NFList(N)761sage: P.index_of_normalized_pair(1, 0)7623763sage: j = randint(0,len(P)-1)764sage: P.index_of_normalized_pair(P[j])==j765True766"""767if d is None:768try:769c = MSymbol(self.__N, c) # check that c is an MSymbol770except ValueError: # catch special case of wrong level771raise ValueError, "The MSymbol is of a different level"772t, i = search(self.__list, c)773else:774t, i = search(self.__list, MSymbol(self.__N, c, d))775if t: return i776return False777778def lift_to_sl2_Ok(self, i):779"""780Lift the `i`-th element of this P1NFList to an element of `SL(2, R)`,781where `R` is the ring of integers of the corresponding number field.782783INPUT:784785- ``i`` - integer (index of the element to lift)786787OUTPUT:788789If the `i`-th element is `(c : d)`, the function returns a list of790integral elements `[a, b, c', d']` that defines a 2x2 matrix with791determinant 1 and such that `c=c'` (mod `N`) and `d=d'` (mod `N`).792793EXAMPLES::794795sage: k.<a> = NumberField(x^2 + 23)796sage: N = k.ideal(3)797sage: P = P1NFList(N)798sage: len(P)79916800sage: P[5]801M-symbol (1/2*a + 1/2: -a) of level Fractional ideal (3)802sage: P.lift_to_sl2_Ok(5)803[1, -2, 1/2*a + 1/2, -a]804805::806807sage: Ok = k.ring_of_integers()808sage: L = [Matrix(Ok, 2, P.lift_to_sl2_Ok(i)) for i in range(len(P))]809sage: all([det(L[i]) == 1 for i in range(len(L))])810True811"""812return self[i].lift_to_sl2_Ok()813814def apply_S(self, i):815"""816Applies the matrix S = [0, -1, 1, 0] to the i-th M-Symbol of the list.817818INPUT:819820- ``i`` -- integer821822OUTPUT:823824integer -- the index of the M-Symbol obtained by the right action of825the matrix S = [0, -1, 1, 0] on the i-th M-Symbol.826827EXAMPLES::828829sage: k.<a> = NumberField(x^3 + 11)830sage: N = k.ideal(5, a + 1)831sage: P = P1NFList(N)832sage: j = P.apply_S(P.index_of_normalized_pair(1, 0))833sage: P[j]834M-symbol (0: 1) of level Fractional ideal (5, a + 1)835836We test that S has order 2:837838::839840sage: j = randint(0,len(P)-1)841sage: P.apply_S(P.apply_S(j))==j842True843"""844c, d = self.__list[i].tuple()845t, j = search(self.__list, self.normalize(d, -c))846return j847848def apply_TS(self, i):849"""850Applies the matrix TS = [1, -1, 0, 1] to the i-th M-Symbol of the list.851852INPUT:853854- ``i`` -- integer855856OUTPUT:857858integer -- the index of the M-Symbol obtained by the right action of859the matrix TS = [1, -1, 0, 1] on the i-th M-Symbol.860861EXAMPLES::862863sage: k.<a> = NumberField(x^3 + 11)864sage: N = k.ideal(5, a + 1)865sage: P = P1NFList(N)866sage: P.apply_TS(3)8672868869We test that TS has order 3:870871::872873sage: j = randint(0,len(P)-1)874sage: P.apply_TS(P.apply_TS(P.apply_TS(j)))==j875True876"""877c, d = self.__list[i].tuple()878t, j = search(self.__list, self.normalize(c + d, -c))879return j880881def apply_T_alpha(self, i, alpha=1):882"""883Applies the matrix T_alpha = [1, alpha, 0, 1] to the i-th M-Symbol of884the list.885886INPUT:887888- ``i`` -- integer889890- ``alpha`` -- element of the corresponding ring of integers(default 1)891892OUTPUT:893894integer -- the index of the M-Symbol obtained by the right action of895the matrix T_alpha = [1, alpha, 0, 1] on the i-th M-Symbol.896897EXAMPLES::898899sage: k.<a> = NumberField(x^3 + 11)900sage: N = k.ideal(5, a + 1)901sage: P = P1NFList(N)902sage: P.apply_T_alpha(4, a^ 2 - 2)9033904905We test that T_a*T_b = T_(a+b):906907::908909sage: P.apply_T_alpha(3, a^2 - 2)==P.apply_T_alpha(P.apply_T_alpha(3,a^2),-2)910True911"""912c, d = self.__list[i].tuple()913t, j = search(self.__list, self.normalize(c, alpha*c + d))914return j915916def apply_J_epsilon(self, i, e1, e2=1):917"""918Applies the matrix `J_{\epsilon}` = [e1, 0, 0, e2] to the i-th919M-Symbol of the list.920921e1, e2 are units of the underlying number field.922923INPUT:924925- ``i`` -- integer926927- ``e1`` -- unit928929- ``e2`` -- unit (default 1)930931OUTPUT:932933integer -- the index of the M-Symbol obtained by the right action of934the matrix `J_{\epsilon}` = [e1, 0, 0, e2] on the i-th M-Symbol.935936EXAMPLES::937938sage: k.<a> = NumberField(x^3 + 11)939sage: N = k.ideal(5, a + 1)940sage: P = P1NFList(N)941sage: u = k.unit_group().gens_values(); u942[-1, 2*a^2 + 4*a - 1]943sage: P.apply_J_epsilon(4, -1)9442945sage: P.apply_J_epsilon(4, u[0], u[1])9461947948::949950sage: k.<a> = NumberField(x^4 + 13*x - 7)951sage: N = k.ideal(a + 1)952sage: P = P1NFList(N)953sage: u = k.unit_group().gens_values(); u954[-1, a^3 + a^2 + a + 12, a^3 + 3*a^2 - 1]955sage: P.apply_J_epsilon(3, u[2]^2)==P.apply_J_epsilon(P.apply_J_epsilon(3, u[2]),u[2])956True957"""958c, d = self.__list[i].tuple()959t, j = search(self.__list, self.normalize(c*e1, d*e2))960return j961962963#**************************************************************************964# Global functions:965# - p1NFList --compute list of M-symbols966# - lift_to_sl2_Ok967# - make_coprime -- need it for ``lift_to_sl2_Ok``968# - psi -- useful to check cardinality of the M-symbols list969#**************************************************************************970971def p1NFlist(N):972"""973Returns a list of the normalized elements of `\\mathbb{P}^1(R/N)`, where974`N` is an integral ideal.975976INPUT:977978- ``N`` - integral ideal (the level or modulus).979980EXAMPLES::981982sage: k.<a> = NumberField(x^2 + 23)983sage: N = k.ideal(3)984sage: from sage.modular.modsym.p1list_nf import p1NFlist, psi985sage: len(p1NFlist(N))==psi(N)986True987"""988k = N.number_field()989990L = [MSymbol(N, k(0),k(1), check=False)]991#N.residues() = iterator through the residues mod N992L = L+[MSymbol(N, k(1), r, check=False) for r in N.residues()]993994from sage.rings.arith import divisors995for D in divisors(N):996if not D.is_trivial() and D!=N:997#we find Dp ideal coprime to N, in inverse class to D998if D.is_principal():999Dp = k.ideal(1)1000c = D.gens_reduced()[0]1001else:1002it = k.primes_of_degree_one_iter()1003Dp = it.next()1004while not Dp.is_coprime(N) or not (Dp*D).is_principal():1005Dp = it.next()1006c = (D*Dp).gens_reduced()[0]1007#now we find all the (c,d)'s which have associated divisor D1008I = D + N/D1009for d in (N/D).residues():1010if I.is_coprime(d):1011M = D.prime_to_idealM_part(N/D)1012u = (Dp*M).element_1_mod(N/D)1013d1 = u*d + (1-u)1014L.append(MSymbol(N, c, d1, check=False).normalize())1015return L10161017def lift_to_sl2_Ok(N, c, d):1018"""1019Lift a pair (c, d) to an element of `SL(2, O_k)`, where `O_k` is the ring1020of integers of the corresponding number field.10211022INPUT:10231024- ``N`` -- number field ideal10251026- ``c`` -- integral element of the number field10271028- ``d`` -- integral element of the number field10291030OUTPUT:10311032A list [a, b, c', d'] of integral elements that are the entries of1033a 2x2 matrix with determinant 1. The lower two entries are congruent to1034c, d modulo the ideal `N`.103510361037EXAMPLES::10381039sage: from sage.modular.modsym.p1list_nf import lift_to_sl2_Ok1040sage: k.<a> = NumberField(x^2 + 23)1041sage: Ok = k.ring_of_integers(k)1042sage: N = k.ideal(3)1043sage: M = Matrix(Ok, 2, lift_to_sl2_Ok(N, 1, a))1044sage: det(M)104511046sage: M = Matrix(Ok, 2, lift_to_sl2_Ok(N, 0, a))1047sage: det(M)104811049sage: (M[1][0] in N) and (M[1][1] - a in N)1050True1051sage: M = Matrix(Ok, 2, lift_to_sl2_Ok(N, 0, 0))1052Traceback (most recent call last):1053...1054ValueError: Cannot lift (0, 0) to an element of Sl2(Ok).10551056::10571058sage: k.<a> = NumberField(x^3 + 11)1059sage: Ok = k.ring_of_integers(k)1060sage: N = k.ideal(3, a - 1)1061sage: M = Matrix(Ok, 2, lift_to_sl2_Ok(N, 2*a, 0))1062sage: det(M)106311064sage: (M[1][0] - 2*a in N) and (M[1][1] in N)1065True1066sage: M = Matrix(Ok, 2, lift_to_sl2_Ok(N, 4*a^2, a + 1))1067sage: det(M)106811069sage: (M[1][0] - 4*a^2 in N) and (M[1][1] - (a+1) in N)1070True10711072::10731074sage: k.<a> = NumberField(x^4 - x^3 -21*x^2 + 17*x + 133)1075sage: Ok = k.ring_of_integers(k)1076sage: N = k.ideal(7, a)1077sage: M = Matrix(Ok, 2, lift_to_sl2_Ok(N, 0, a^2 - 1))1078sage: det(M)107911080sage: (M[1][0] in N) and (M[1][1] - (a^2-1) in N)1081True1082sage: M = Matrix(Ok, 2, lift_to_sl2_Ok(N, 0, 7))1083Traceback (most recent call last):1084...1085ValueError: <0> + <7> and the Fractional ideal (7, a) are not coprime.1086"""1087k = N.number_field()1088#check the input1089if c.is_zero() and d.is_zero():1090raise ValueError, "Cannot lift (%s, %s) to an element of Sl2(Ok)."%(c, d)1091if not N.is_coprime(k.ideal(c, d)):1092raise ValueError, "<%s> + <%s> and the %s are not coprime."%(c, d, N)1093#a few special cases1094if c - 1 in N:1095return [k(0), k(-1), 1, d]1096if d - 1 in N:1097return [k(1), k(0), c, 1]1098if c.is_zero(): # and d!=1, so won't happen for normalized M-symbols (c: d)1099it = k.primes_of_degree_one_iter()1100q = k.ideal(1)1101while not (q.is_coprime(d) and (q*N).is_principal()):1102q = it.next()1103m = (q*N).gens_reduced()[0]1104B = k.ideal(m).element_1_mod(k.ideal(d))1105return [(1-B)/d, -B/m, m, d]1106if d.is_zero(): # and c!=1, so won't happen for normalized M-symbols (c: d)1107it = k.primes_of_degree_one_iter()1108q = k.ideal(1)1109while not (q.is_coprime(c) and (q*N).is_principal()):1110q = it.next()1111m = (q*N).gens_reduced()[0]1112B = k.ideal(c).element_1_mod(k.ideal(m))1113return [(1-B)/m, -B/c, c, m]11141115c, d = make_coprime(N, c, d)11161117B = k.ideal(c).element_1_mod(k.ideal(d))1118b = -B/c1119a = (1-B)/d1120return [a, b, c, d]11211122def make_coprime(N, c, d):1123"""1124Returns (c, d') so d' is congruent to d modulo N, and such that c and d' are1125coprime (<c> + <d'> = R).11261127INPUT:11281129- ``N`` -- number field ideal11301131- ``c`` -- integral element of the number field11321133- ``d`` -- integral element of the number field11341135OUTPUT:11361137A pair (c, d') where c, d' are integral elements of the corresponding1138number field, with d' congruent to d mod N, and such that <c> + <d'> = R1139(R being the corresponding ring of integers).11401141EXAMPLES::11421143sage: from sage.modular.modsym.p1list_nf import make_coprime1144sage: k.<a> = NumberField(x^2 + 23)1145sage: N = k.ideal(3, a - 1)1146sage: c = 2*a; d = a + 11147sage: N.is_coprime(k.ideal(c, d))1148True1149sage: k.ideal(c).is_coprime(d)1150False1151sage: c, dp = make_coprime(N, c, d)1152sage: k.ideal(c).is_coprime(dp)1153True1154"""1155k = N.number_field()1156if k.ideal(c).is_coprime(d):1157return c, d1158else:1159q = k.ideal(c).prime_to_idealM_part(d)1160it = k.primes_of_degree_one_iter()1161r = k.ideal(1)1162qN = q*N1163while not (r.is_coprime(c) and (r*qN).is_principal()):1164r = it.next()1165m = (r*qN).gens_reduced()[0]1166d1 = d + m1167return c, d111681169def psi(N):1170"""1171The index `[\Gamma : \Gamma_0(N)]`, where `\Gamma = GL(2, R)` for `R` the1172corresponding ring of integers, and `\Gamma_0(N)` standard congruence1173subgroup.11741175EXAMPLES::11761177sage: from sage.modular.modsym.p1list_nf import psi1178sage: k.<a> = NumberField(x^2 + 23)1179sage: N = k.ideal(3, a - 1)1180sage: psi(N)1181411821183::11841185sage: k.<a> = NumberField(x^2 + 23)1186sage: N = k.ideal(5)1187sage: psi(N)1188261189"""1190if not N.is_integral():1191raise ValueError, "psi only defined for integral ideals"11921193from sage.misc.misc import prod1194return prod([(np+1)*np**(e-1) \1195for np,e in [(p.absolute_norm(),e) \1196for p,e in N.factor()]])119711981199