def get_number_field_integral_basis(c_string): r"""Get the integral basis for the field specified by the string. INPUT: c_string -- string, a string of comma-separated coefficients with no spaces: the coefficients of the normalized (using gp.polredabs) defining polynomial OUTPUT: fld_bool -- bool, True if the number field has a page in the LMFDB, False otherwise K_new -- number field, the number field with defining polynomial that is the normalized version (given by gp.polredabs) of the one with coefficients specified by c_string a -- number field element, generator for K_new the integral basis for K_new recorded on its LMFDB page """ C = getDBconnection() c_hash = field_coeffs_string_to_hash(c_string) field = C.numberfields.fields.find_one({'coeffhash':c_hash}) fld_bool = True try: field['degree'] except TypeError: fld_bool = False if fld_bool: field_str = field['coeffs'] int_basis_str = field['zk'] poly = coeffs_to_poly(field_str) K_new = NumberField(poly, names=('a',)) (a,) = K_new._first_ngens(1) return fld_bool, K_new, a, [K_new(eval(preparse(el))) for el in int_basis_str] else: # could add polynomial to list of number fields missing from LMFDB here return fld_bool, None, None, None
def find_field(pol, verbose=False): """ pol is a string holding a list of coefficients, constant first, 1 last, e.g. '-2,0,1' Looks up this defining polynomial kn LMFDB and returns its label, or None """ coeffs = str_to_list(pol) deg = len(coeffs)-1 if deg==2: c, b, a = coeffs d = ZZ(b*b-4*a*c).squarefree_part() D = d if (d-1)%4==0 else 4*d absD = D.abs() s = 0 if d<0 else 2 return '2.{}.{}.1'.format(s,absD) from lmfdb.number_fields.number_field import poly_to_field_label poly = Qx(coeffs) Flabel = poly_to_field_label(poly) if Flabel==None: print("********* field with polynomial {} is not in the database!".format(poly)) K = NumberField(poly, 'a') poly = K.optimized_representation()[0].defining_polynomial() print("********* using optimised polynomial {}".format(poly)) return poly_to_str(poly) else: if verbose: print("{} has label {}".format(pol,Flabel)) return Flabel
def _check(k, j): M = vvsmf(j, k, prec) if M.dimension() > 0: self.assertEqual(M.dimension(), len(M.basis())) _chply = M.hecke_charpoly(2) for cply, _ in _chply.factor(): K = NumberField(cply, names="a") a = K.gens()[0] f = M.eigenform_with_eigenvalue_t2(a) self.assert_hecke_eigen_values(f)
def upsert_embedding(id_number, skip = False): rowcc = db.mf_hecke_cc.lucky({'id':id_number}, projection=['an', 'hecke_orbit_code','id','lfunction_label', 'embedding_root_imag','embedding_root_real']) if rowcc is None: return if skip: if rowcc.get("embedding_root_imag", None) is not None: if rowcc.get("embedding_root_real", None) is not None: return row_embeddings = {} hecke_orbit_code = rowcc['hecke_orbit_code'] newform = db.mf_newforms.lucky({'hecke_orbit_code':hecke_orbit_code}) if newform is None: # No newform in db return if newform['dim'] == 1: row_embeddings['embedding_root_imag'] = 0 row_embeddings['embedding_root_real'] = 0 elif newform['weight'] == 1: return elif newform.get('field_poly', None) is None: return else: # print rowcc['lfunction_label'] HF = NumberField(ZZx(newform['field_poly']), "v") numerators = newform['hecke_ring_numerators'] denominators = newform['hecke_ring_denominators'] betas = [HF(elt)/denominators[i] for i, elt in enumerate(numerators)] embeddings = HF.complex_embeddings(prec=2000) an_nf = list(db.mf_hecke_nf.search({'hecke_orbit_code':hecke_orbit_code}, ['n','an'], sort=['n'])) betas_embedded = [map(elt, betas) for elt in embeddings] CCC = betas_embedded[0][0].parent() qexp = [convert_eigenvals_to_qexp(elt, an_nf) for elt in betas_embedded] min_len = min(len(rowcc['an']), len(qexp[0])) an_cc = vector(CCC, map(lambda x: CCC(x[0], x[1]), rowcc['an'][:min_len])) #qexp_diff = [ (vector(CCC, elt[:min_len]) - an_cc).norm() for elt in qexp ] # normalized, to avoid the unstability comming from large weight qexp_diff = [ vector([(elt- an_cc[i])/elt.abs() for i, elt in enumerate(q) if elt != 0]).norm() for j,q in enumerate(qexp)] qexp_diff_sorted = sorted(qexp_diff) min_diff = qexp_diff_sorted[0] #print "min_diff = %.2e \t min_diff/2nd = %.2e" % (min_diff, min_diff/qexp_diff_sorted[1]) #assuring that is something close to zero, and that no other value is close to it assert min_diff < 1e-6 assert min_diff/qexp_diff_sorted[1] < 1e-15 for i, elt in enumerate(qexp_diff): if elt == min_diff: row_embeddings['embedding_root_real'] = float(embeddings[i](HF.gen()).real()) row_embeddings['embedding_root_imag'] = float(embeddings[i](HF.gen()).imag()) break assert len(row_embeddings) == 2 db.mf_hecke_cc.upsert({'id': rowcc['id']}, row_embeddings)
def test_web_latex_ideal_fact(self): r""" Checking utility: web_latex_ideal_fact """ from sage.all import NumberField x = var('x') K = NumberField(x**2 - 5, 'a') a = K.gen() I = K.ideal(2/(5+a)).factor() self.assertEqual(web_latex_ideal_fact(I), '\\( \\left(-a\\right)^{-1} \\)')
def Hecke_field_primes(fpol, ell, degree=None, verbose=False): """Given a polynomial fpol defining a number field K and a prime ell, return the list of primes of K above ell. Set degree to a suitable positive integer to only return primes of that degree, e.g. degree=1 will only give primes whose residue field is GF(ell). """ if verbose: print("Checking field poly {} at ell={}".format(fpol,ell)) Qx = PolynomialRing(QQ,'x') K = NumberField(Qx(fpol), 'a_') ellK = K.primes_above(ell, degree=degree) if verbose: print("{} primes of norm {}".format(len(ellK),ell)) return ellK
def list_factored_to_factored_poly_otherorder(sfacts_fc_list, galois=False, vari = 'T', p = None): """ Either return the polynomial in a nice factored form, or return a pair, with first entry the factored polynomial and the second entry a list describing the Galois groups of the factors. vari allows to choose the variable of the polynomial to be returned. """ gal_list=[] ZZpT = PolynomialRing(ZZ, ['p',vari], order = 'negdeglex') ZZT = PolynomialRing(ZZ, vari) outstr = '' for g, e in sfacts_fc_list: if galois: # hack because currently sage only handles monic polynomials: this_poly = ZZT(list(reversed(g))) this_degree = this_poly.degree() this_number_field = NumberField(this_poly, "a") this_gal = this_number_field.galois_group(type='pari') this_t_number = this_gal.group().__pari__()[2].sage() gal_list.append([this_degree, this_t_number]) # casting from ZZT -> ZZpT if p is None: gtoprint = dict( zip( zip( [0]*len(g), range(len(g))), g) ) else: gtoprint = {} for i, elt in enumerate(g): if elt != 0: val = ZZ(elt).valuation(p) gtoprint[(val, i)] = elt/p**val glatex = latex(ZZpT(gtoprint)) if e > 1: outstr += '( %s )^{%d}' % (glatex, e) elif len(sfacts_fc_list) > 1: outstr += '( %s )' % (glatex,) else: outstr += glatex if galois: # 2 factors of degree 2 if len(sfacts_fc_list)==2: if len(sfacts_fc_list[0][0]) == 3 and len(sfacts_fc_list[1][0]) == 3: troubletest = ZZT(sfacts_fc_list[0][0]).disc()*ZZT(sfacts_fc_list[1][0]).disc() if troubletest.is_square(): gal_list=[[2,1]] return outstr, gal_list return outstr
def RM_and_notCM(ef, RM_coeff): QQt = PolynomialRing(QQ, 't') RM_field = NumberField(QQt(RM_coeff),'r') possible_CM = None; for p1 in ef: if len(p1) == 5: p = sqrt(p1[-1]) if QQt(p1).is_irreducible() and is_ordinary(p1) and is_totally_split(RM_field, p): N = NumberField(QQt(p1), "a") if possible_CM is None: possible_CM = N; elif not N.is_isomorphic(possible_CM): return True; else: pass; return False
def test_ramanujan_conj(self): '''Test Ramanujan conjectures for eigenforms of determinant weights less than or equal to 29. ''' prec = 6 hpl = hilbert_series_maybe(10) for k in range(22, 30): if hpl[k] != 0: N = sym10_space(k, prec, data_directory=data_dir) self.assertEqual(N.dimension(), len(N.basis())) _chply = N.hecke_charpoly(2) for cply, _ in _chply.factor(): K = NumberField(cply, names="a") a = K.gens()[0] f = N.eigenform_with_eigenvalue_t2(a) self.assert_ramanujan_conj_eigenform(f)
def test_gothic_veech(): x = polygen(QQ) K = NumberField(x**2 - 2, 'sqrt2', embedding=AA(2)**QQ((1, 2))) sqrt2 = K.gen() x = QQ((1, 2)) y = 1 a = x + y * sqrt2 b = -3 * x - QQ((3, 2)) + 3 * y * sqrt2 S = translation_surfaces.cathedral(a, b) O = GL2ROrbitClosure(S) assert O.ambient_stratum() == AbelianStratum(2, 2, 2) for d in O.decompositions(4, 50): assert d.parabolic() O.update_tangent_space_from_flow_decomposition(d) assert O.dimension() == O.absolute_dimension() == 2 assert O.field_of_definition() == O.V2._isomorphic_vector_space.base_ring()
def test_D9_exact_real(): pytest.importorskip('pyexactreal') from pyexactreal import ExactReals R = ExactReals(QQ) x = polygen(QQ) K = NumberField(x**3 - 2, 'a', embedding=AA(2)**QQ((1,3))) a = K.gen() S = translation_surfaces.mcmullen_genus2_prototype(2,1,0,-1,R.random_element([0.1, 0.2])) O = GL2ROrbitClosure(S) for d in O.decompositions(5): ncyl, nmin, nund = d.num_cylinders_minimals_undetermined() assert (nund == 0) assert ((nmin == 0) or (ncyl == 0 and 1 <= nmin <= 2)) O.update_tangent_space_from_flow_decomposition(d) assert O.dimension() == 3
def create_small_record(self, min_prec=10, want_prec=100, max_length = 5242880, max_height_qexp = default_max_height): ### creates a duplicate record (fs) of this webnewform ### with lower precision to load faster on the web ### we aim to have at most max_length bytes ### but at least min_prec coefficients and we desire to have want_prec if min_prec>=self.prec: raise ValueError("Need higher precision, self.prec = {}".format(self.prec)) if not hasattr(self, '_file_record_length'): self.update_from_db() l = self._file_record_length if l > max_length or self.prec > want_prec: nl = float(l)/float(self.prec)*float(want_prec) if nl > max_length: prec = max([floor(float(self.prec)/float(l)*float(max_length)), min_prec]) else: prec = want_prec emf_logger.debug("Creating a new record with prec = {}".format(prec)) self.prec = prec include_coeffs = self.complexity_of_first_nonvanishing_coefficients() <= default_max_height if include_coeffs: self.q_expansion = self.q_expansion.truncate_powerseries(prec) self._coefficients = {n:c for n,c in self._coefficients.iteritems() if n<prec} else: self.q_expansion = self.q_expansion.truncate_powerseries(1) self._coefficients = {} self.prec = 0 self.coefficient_field = NumberField(self.absolute_polynomial, names=str(self.coefficient_field.gen())) self._embeddings['values'] = {n:c for n,c in self._embeddings['values'].iteritems() if n<prec} self._embeddings['prec'] = prec self.save_to_db()
def number_field(self): p = self._min_poly if p is None: raise ValueError('Minimal polynomial is not known.') q = p.change_ring(QQ) q = (1 / q.leading_coefficient()) * q return NumberField(q, 'z', embedding=self._approx_root)
def get_smallest_good_number_field(d): """ Gets the smallest "good" number field of degree d, where "good" means - Galois over Q - Does not contain the Hilbert class field of an imaginary quadratic field and smallest is in terms of absolute value of discriminant. This connects to the LMFDB API for searching, and returns the correct hit. Output: - Delta_K - discriminant of number field - f_K - Definining polynomial of number field """ the_url = SGNF_URL_TRUNK.format(str(d)) data_this_degree = requests.get(url=the_url).json()["data"] for dat in data_this_degree: poly = R(dat["coeffs"]) K = NumberField(poly, name="a") Delta_K = dat["disc_sign"] * dat["disc_abs"] _, contains_hilbert_class_field = contains_imaginary_quadratic_field(K) if not contains_hilbert_class_field: return (Delta_K, poly, K, dat["label"]) raise NotImplementedError("need more hits")
def ramified_extension(self, n, embedding=False): r""" Return a purely ramified extension with given ramification degree. INPUT: - ``n`` -- a positive integer - ``embedding`` -- a boolean (default: ``False``) OUTPUT: A finite extension `L` of this p-adic field `K` such that `L/K` is purely ramified, of degree ``n``. If ``embedding`` is ``True`` then the pair `(L,\phi)` is returned, where `\phi:K\to L` is the canonical embedding. """ P = self.polynomial() x = P.parent().gen() if self.is_Qp(): P = x**n - self.p() else: P = P(x**n) L0 = NumberField(P, 'pi'+str(P.degree()), maximize_at_primes=[]) vL = self.base_valuation().extension(L0) return FakepAdicCompletion(L0, vL)
def _test_an_dict_over_Q(ainvs, B=100): """ Test that the an_dict function works and gives the correct answer for an elliptic curve defined over QQ, by computing using the generic code in this file, and comparing with the output of Sage's anlist function for rational elliptic curves. """ from sage.all import polygen, QQ, NumberField, EllipticCurve x = polygen(QQ,'x') F = NumberField(x - 1,'a'); a = F.gen() E = EllipticCurve(F, ainvs) EQ = EllipticCurve(QQ, ainvs) v = EQ.anlist(B) an = an_dict(E, B) for i, j in an.iteritems(): assert j == v[i[0]]
def set_euler_factors(self): # Sets: # - euler_factors # - bad_lfactors bound = 100 power = self.power if self.curve.genus() == 1: E = self.curve ZZT = PolynomialRing(ZZ, "T") T = ZZT.gen() K = E.base_field() if K == QQ: K = NumberField(T,"a") # making sure SAGE sees K as a numberfield E = E.change_ring(K) N = (E.conductor() * K.discriminant()**2).absolute_norm() assert N == self.conductor def get_eulerfactor(p): Lp = 1 for f, _ in K.fractional_ideal(p).factor(): f = K.fractional_ideal(f) if f.divides(N): local_factor = (1 - E.local_data(f).bad_reduction_type() * T) Lp *= local_factor( T ** f.absolute_norm().valuation(p) ) else: frob = ZZT(E.local_data(f).minimal_model().change_ring(f.residue_field()).frobenius_polynomial()) Lp *= frob.reverse()( T ** f.absolute_norm().valuation(p) ) return list(map(int, Lp)) if power > 1: euler_factors = {} for p, v in self.hard_factors.items(): euler_factors[p] = v for p in prime_range(bound): if p in self.hard_factors: continue _, ma, p = euler_factors(p) euler_factors[p] = sym_pol_ECQ(-ma, p, power) else: euler_factors = {p: get_eulerfactor(p) for p in prime_range(bound)} else: raise NotImplementedError("only implemented for genus 1 at the moment") self.euler_factors = [euler_factors[p] for p in prime_range(bound)] self.bad_lfactors = [[p, euler_factors[p]] for p in Integer(self.conductor).prime_divisors()]
def test1(B=50): """ Tests that the functions all run without crashing over a specific number field. Does not test that the output is correct. That should be in another test. """ from sage.all import polygen, QQ, NumberField, EllipticCurve x = polygen(QQ,'x') F = NumberField(x**2 - x - 1,'a'); a = F.gen() E = EllipticCurve([1,a+1,a,a,0]) ap(E,F.ideal(3)) primes_of_bounded_norm(F,B) ap_list(E,B) assert len(ap_list(E,B,primes=True)) == 2 apd = ap_dict(E,B) reduced_rep(F.ideal(3)) assert an_dict(E,B) == an_dict_from_ap(apd, E.conductor(), B)
def make_base_field(rec): if rec["base_field"] == [-1, 1]: K = QQ # is there a Sage version of RationalsAsNumberField()? else: R = PolynomialRing(QQ, "T") poly = R(rec["base_field"]) K = NumberField(poly, "nu") return K
def cli_handler(args): # pylint: disable=redefined-outer-name f = R(args.f) K = NumberField(f, name="a") loglevel = logging.DEBUG if args.verbose else logging.INFO logging.basicConfig( format="%(asctime)s %(levelname)s: %(message)s", datefmt="%H:%M:%S", level=loglevel, ) logging.debug("Debugging level for log messages set.") if args.dlmv: dlmv_bound = DLMV(K) logging.info( "DLMV bound for {} is:\n\n{}\n\nwhich is approximately {}".format( K, dlmv_bound, RR(dlmv_bound))) else: logging.warning( "Only checking Type 2 primes up to %s. " "To check all, use the PARI/GP script.", args.bound, ) if args.norm_bound: norm_bound = args.norm_bound auto_stop_strategy = False else: norm_bound = 50 # still needed for Type 1 auto_stop_strategy = True superset, type_3_fields = get_isogeny_primes( K, args.bound, args.ice, args.appendix_bound, norm_bound=norm_bound, auto_stop_strategy=auto_stop_strategy, ) superset_list = list(superset) superset_list.sort() logging.info(f"superset = {superset_list}") possible_new_isog_primes = superset - EC_Q_ISOGENY_PRIMES possible_new_isog_primes_list = list(possible_new_isog_primes) possible_new_isog_primes_list.sort() logging.info( f"Possible new isogeny primes = {possible_new_isog_primes_list}") if type_3_fields: how_many_fields = len(type_3_fields) logging.info( f"Outside of the above set, any isogeny primes must be " f"of Momose Type 3 with imaginary quadratic field L, for L one " f"of the following {how_many_fields} field(s):\n {type_3_fields}" )
def test_Heckemethods(self): from sage.all import NumberField, var x = var('x') k = NumberField(x**3 - x**2 + x + 1, 'a') modlabel, numlabel = '82.-5a0+1a2', '5.3.3' mod = WebHecke.label2ideal(k, modlabel) assert WebHecke.ideal2label(mod) == modlabel num = WebHecke.label2number(numlabel) assert WebHecke.number2label(num) == numlabel
def _test(self): from sage.all import PolynomialRing, QQ, NumberField, GaussValuation, FunctionField R = PolynomialRing(QQ, 'x') x = R.gen() K = NumberField(x**6 + 126 * x**3 + 126, 'pi') v = K.valuation(2) R = PolynomialRing(K, 'x') x = R.gen() v = GaussValuation(R, v).augmentation(x, QQ(2) / 3) F = FunctionField(K, 'x') x = F.gen() v = F.valuation(v) S = PolynomialRing(F, 'y') y = S.gen() w0 = GaussValuation(S, v) G = y**2 - x**3 - 3 w1 = w0.mac_lane_step(G)[0] w1.mac_lane_step(G)
def test_nf(): from sage.all import NumberField, QQ, AA, Rational, polygen from pyeantic.sage_conversion import sage_nf_to_eantic x = polygen(QQ) # linear K = NumberField(x - 3, 'x', embedding=QQ(3)) L = sage_nf_to_eantic(K) # quadratic K = NumberField(2*x**2 - 3, 'A', embedding=AA(Rational((3,2)))**Rational((1,2))) L = sage_nf_to_eantic(K) # cubic p = x**3 - x**2 - x - 1 s = p.roots(AA, False)[0] K = NumberField(x**3 - x**2 - x - 1, 's', embedding=s) L = sage_nf_to_eantic(K)
def test_field_iso(pol1, pol2): if pol1 == pol2: return True if pol1.degree() != pol2.degree(): return False assert pol1.is_irreducible() and pol2.is_irreducible() res = 0 < len( pol1.change_ring(PolynomialRing(NumberField(pol2, 'b'), 'y')).roots()) #print("testing isomorphism of {} and {}: {}".format(pol1,pol2, res)) return res
def test_download_sage(self): # A dimension 1 example L1 = self.tc.get( '/ModularForm/GL2/ImaginaryQuadratic/2.0.3.1/18333.3/a/download/sage' ) L1_level = self.check_compile_and_get_level(L1) assert L1_level.norm() == Integer(18333) assert 'NN = ZF.ideal((6111, 3*a + 5052))' in L1.get_data(as_text=True) assert '(27*a-22,),(-29*a+15,),(-29*a+14,),(29*a-11,),(-29*a+18,),(-29*a+9,)' in L1.get_data( as_text=True) assert 'hecke_eigenvalues_array = [0, -1, 2, -1, 1, -3, 4, 0, -2, -8, 7, -9, -8, -4, -9, 8, 10, -11,' in L1.get_data( as_text=True) """ Observe that example 1 above checks equality of the level norm between the loaded sage code and what appears on the homepage, but then checks for a particular presentation of that ideal in the text file. The problem with this is that the choice of generators for the ideal are not unique, and could potentially change from one sage release to the next. An alternative is to check for equality of the ideals themselves, and that is the strategy adopted in the following example. """ # A dimension 2 example L2 = self.tc.get( '/ModularForm/GL2/ImaginaryQuadratic/2.0.4.1/377.1/a2/download/sage' ) L2_level = self.check_compile_and_get_level(L2) P = PolynomialRing(QQ, 'x') g = P([1, 0, 1]) F = NumberField(g, 'i') i = F.gen() ZF = F.ring_of_integers() L2_level_actual = ZF.ideal( (16 * i - 11)) # the level displayed on BMF homepage assert L2_level == L2_level_actual assert L2_level.norm() == 377 assert '(2*i+3,),(i+4,),(i-4,),(-2*i+5,),(2*i+5,),(i+6,)' in L2.get_data( as_text=True) assert 'hecke_eigenvalues_array = [-z, 2*z, -1, 2*z+2, "not known", 2*z-1, 4, 2*z+3, "not known", 2*z+1, -2*z-5, -4*z+5, -4*z+5, 2*z+1, 2*z]' in L2.get_data( as_text=True)
def IsGeometricallyNotSquareOfCM(LPolys): g = 2 # only for surfaces CMDisc = -1 for p in range(2, maxP): # loop over primes if LPolys[p] <> 0: q = LPolys[p] q = twistPolynomial(q, 2 * extensionBounds[g]) if (q.is_square() == False): return True r = q.factor() r = r[0][0] if r.degree() == 2: if r.coefficients(sparse=False)[1] % p <> 0: K = NumberField(r, 'u') d = K.disc() if CMDisc == -1: CMDisc = d if CMDisc <> d: return True return False
def number_field_from_dict(d): r""" INPUT: - 'd' -- {'base':F,'p':p,'g':g } where p is a polynomial in the variable(s) xN with coefficients in K. (The 'x' is just a convention) OUTPUT: - 'F' -- Number field extending K with relative minimal polynomial p. """ K = d['base']; p=d['relative polynomial']; g=d['gens'] if K=='QQ': K = QQ elif isinstance(K,dict): K = number_field_from_dict(K) else: raise ValueError,"Could not construct number field!" F = NumberField(K[g](p),names=g) if F.absolute_degree()==1: F = QQ return F
def get_hmfs_hecke_field_and_eigenvals(label): """Get the Hecke field and eigenvalues for the Hilbert modular form with given label. INPUT: label -- string, the label of the Hilbert modular form OUTPUT: K_old -- number field, the field containing the Hecke eigenvalues e -- number field element, a generator for K_old over QQ eigenvals -- list, a list of the Hecke eigenvalues """ C = getDBconnection() # Should I use find_one, or something else? R = PolynomialRing(QQ, names=('x')) form = C.hmfs.forms.find_one({'label': label}) poly = R(str(form['hecke_polynomial'])) K_old = NumberField(poly, names=('e', )) (e, ) = K_old._first_ngens(1) eigenvals_str = form['hecke_eigenvalues'] eigenvals = [K_old(eval(preparse(el))) for el in eigenvals_str] return K_old, e, eigenvals
def get_hmfs_hecke_field_and_eigenvals(label): """Get the Hecke field and eigenvalues for the Hilbert modular form with given label. INPUT: label -- string, the label of the Hilbert modular form OUTPUT: K_old -- number field, the field containing the Hecke eigenvalues e -- number field element, a generator for K_old over QQ eigenvals -- list, a list of the Hecke eigenvalues """ C = getDBconnection() # Should I use find_one, or something else? R = PolynomialRing(QQ,names=('x')) form = C.hmfs.forms.find_one({'label':label}) poly = R(str(form['hecke_polynomial'])) K_old = NumberField(poly, names=('e',)) (e,) = K_old._first_ngens(1) eigenvals_str = form['hecke_eigenvalues'] eigenvals = [K_old(eval(preparse(el))) for el in eigenvals_str] return K_old, e, eigenvals
def compare_data(d1,d2, keylist=['dims', 'traces', 'polys','ALs', 'eigdata'], verbose=False): assert d1.keys()==d1.keys() QX = PolynomialRing(QQ,'x') nforms = len(d1.keys()) nstep = ZZ(max(1,int(nforms/20.0))) nf = 0 print("Comparing data for {} newforms".format(nforms)) for k in d1.keys(): nf+=1 if nf%nstep==0: print("compared {}/{} ({:0.3f}%)".format(nf,nforms,100.0*nf/nforms)) if d1[k]!=d2[k]: for key in keylist: # take copies! we want to be able to change these without affecting the input dicts t1=copy(d1[k][key]) t2=copy(d2[k][key]) if key=='polys': n=len(t1) for i in range(n): if t1[i]!=t2[i]: pol1 = QX(t1[i]) pol2 = QX(t2[i]) F1 = NumberField(pol1,'a') F2 = NumberField(pol2,'a') if F1.is_isomorphic(F2): pol1=pol2=F1.optimized_representation()[0].defining_polynomial() t1[i]=t2[i]=list(pol1) if t1!=t2: if key=='traces': print("traces differ for {}: \nfirst #= {}, \nsecond #={}".format(k,[len(t) for t in t1],[len(t) for t in t2])) print("first starts\t {}".format(t1[0][:10])) print("second starts\t {}".format(t2[0][:10])) elif key=='eigdata': for f1,f2 in zip(t1,t2): ok, reason = compare_eigdata(k,f1,f2,verbose) if not ok: print("an do not match for (N,k,o)={}: {}".format(k, reason)) else: print("{} differ for {}: \nfirst {}, \nsecond {}".format(key,k,t1,t2))
def bestify_newform(nf, dmax=20, Detail=0): r""" Input is a dict with keys { 'Nko', 'chipoly', 'SB', 'ALeigs', 'dim', 'traces', 'poly', 'eigdata' } (with ALeigs only when o=1 and eigdata only when 1<dim<=dmax) Here eigdata is a dict of the form 'pol': list of d+1 coefficients of polynomial defining Hecke field F 'bas': list of lists of rationals holding dxd matrix whose rows define a Q-basis for F in terms of the power basis 'ancs': list of lists of d rationals giving coefficients of each a_n w.r.t. that basis 'n': 0 (not yet set) 'm': 0 (not yet set) Output adds 'best_poly' and applies a change of basis to eigdata changing 'pol' and 'bas' so the basis coefficients are w.r.t. the best_poly power basis and not the poly power basis. """ Nko = nf['Nko'] dim = nf['dim'] if dim == 1: nf['best_poly'] = nf['poly'] return nf if dim > dmax and dmax > 0: nf['best_poly'] = None return nf Qx = PolynomialRing(QQ, 'x') pari_Qx_poly_to_sage = lambda f: Qx(gen_to_sage(f.Vecrev())) poly = Qx(nf['poly'].list()) if Detail: print("non-best poly for {} is {}".format(Nko, poly)) nf['best_poly'] = best_poly = polredbest_stable(poly) if Detail: print("best_poly for {} is {}".format(Nko, best_poly)) # Now the real work starts Fold = NumberField(poly, 'a') #print("Fold = {}".format(Fold)) Fnew = NumberField(best_poly, 'b') #print("Fnew = {}".format(Fnew)) iso = Fold.is_isomorphic( Fnew, isomorphism_maps=True)[1][0] # we do not care which isomorphism #print("iso = {}".format(iso)) iso = pari_Qx_poly_to_sage(iso) iso = Fold.hom([iso(Fnew.gen())]) new_basis_matrix = [ a.list() for a in [iso(b) for b in [Fold(co) for co in nf['eigdata']['bas']]] ] nf['eigdata']['bas'] = new_basis_matrix nf['eigdata']['pol'] = best_poly.list() return nf
def field_from_label(lab): r""" Returns a number field from its LMFDB label. IQF only. INPUT: - ``s`` (string)-- an LMFDB field label of the form 2.0.d.1 OUTPUT: A number field, Q(sqrt(-d)) with standard defining polynomial """ K = NumberField(polys[lab], gen_names[lab]) print("Created field from label {}: {}".format(lab, K)) return K
def decode_eigdata(k, ed, detail=1): if detail: print("Decoding eigdata for space {}".format(k)) Qx = PolynomialRing(QQ,'x') pol = Qx(ed['poly']) F = NumberField(pol,'a') if detail: print("Field = {}".format(F)) basis = [F(co) for co in ed['basis']] if detail: print("Basis = {}".format(basis)) ans = [sum(b*a for a,b in zip(an,basis)) for an in ed['ans']] if detail: print("ans = {} (first 10 only)".format(ans[:10])) return {'field': F, 'basis': basis, 'ans': ans}
def RankBoundProductEC(LPolys): g = 2 # only for surfaces NotSquareCM = IsGeometricallyNotSquareOfCM(LPolys) if NotSquareCM == False : return 8; IsSquare = True for p in range (2,maxP): if LPolys[p] <> 0 : q = LPolys[p] q = twistPolynomial(q, 2*extensionBounds[g]) if(q.is_square() == False) : IsSquare = False break if IsSquare : return 4 FoundDifferentDiscriminants = False Initialized = False Discriminants = {} for p in range (2,maxP): if LPolys[p] <> 0 : q = LPolys[p] q = twistPolynomial(q, 2*extensionBounds[g]) if(q.is_square() == False) : r = q.factor() l1 = r[0][0]; l2 = r[1][0]; if l1.degree() == 2 and l2.degree() == 2: if l1.coefficients(sparse = False)[1] % p <> 0 and l2.coefficients(sparse = False)[2] % p <> 0 : K1 = NumberField(l1, 'u1'); K2 = NumberField(l2, 'u2'); d1 = K1.discriminant() d2 = K2.discriminant() if d1 <> d2 : FoundDifferentDiscriminants = True if not Initialized : Initialized = True Discriminants = {d1, d2} Discriminants = Discriminants.intersection({d1, d2}) if len(Discriminants) == 0 : break; if FoundDifferentDiscriminants : return 2 + len(Discriminants) else : if len(Discriminants) == 0 : return 2; else : return 4;
def absolute_number_field(maxdeg=10): """ Return an absolute extension of QQ of degree at most 10. EXAMPLES:: sage: import sage.rings.tests sage: sage.rings.tests.absolute_number_field() Number Field in a with defining polynomial x^5 + 82*x^4 - 46*x^3 + 39*x^2 - x - 41 """ from sage.all import ZZ, NumberField R = ZZ['x'] while True: f = R.random_element(degree=ZZ.random_element(x=1,y=maxdeg),x=-100,y=100) if f.degree() <= 0: continue f = f + R.gen()**(f.degree()+1) # make monic if f.is_irreducible(): return NumberField(f, 'a')
def rational_unimodular_representation(ideal): R = ideal.ring() vars = list(R.gens()) J = giac(ideal.gens()) rur = J.gbasis(vars, 'rur') # Yikes: giacpy_sage vs the giac interface give different types. # So using repr. if repr(rur[0]) != 'rur': raise ValueError(('Could not find RUR, got %r instead. ' 'Is the variety 0-dimensional?') % rur[0]) # [x.sage() for rur[4:]] doesn't work with the giac interface (it tries # to convert the slicing to a giac expression that giac does not understand) # # However, rur.sage()[0] gave some trouble, too. # # So we convert with .sage() after having checked we have rur, but before # we inspect the other items. rur = rur.sage() # Defining polynomial of number field, as a symbolic expression. p = rur[2] assert len(p.variables()) == 1 v = p.variables()[0] S = PolynomialRing(QQ, repr(v)) T = PolynomialRing(QQ, 'x') p = T(S(p)) p = p / p.leading_coefficient() ans = [] for q, e in p.factor(): K = NumberField(q, 'a') def toK(f): return K(T(S(f))) denom = toK(rur[3]) rep = [toK(f) / denom for f in rur[4:]] sub_dict = dict(zip(vars, rep)) assert all(g.subs(sub_dict) == 0 for g in ideal.gens()) ans.append((K, sub_dict)) return ans
def field_from_label(lab): r""" Returns a number field from its LMFDB label. Only for 5 IQFs at present. """ global the_fields if lab in the_fields: return the_fields[lab] x = polygen(QQ) deg, s, abs_disc, _ = lab.split(".") assert deg == '2' assert s == '0' d = -ZZ(abs_disc) t = d % 4 assert t in [0, 1] pol = x**2 - t * x + (t - d) // 4 K = NumberField(pol, 'a') print "Created field from label %s: %s" % (lab, K) the_fields[lab] = K return K
def field_intersection_list(defining_polynomials): # try to just use discriminants of the first 1000 polynomials D = 0 for f in defining_polynomials[:1000]: D = GCD(D, f.discriminant()) if D == 1: return f.parent().gen() L = NumberField(defining_polynomials[0], 'a') for f in defining_polynomials: K = NumberField(f, 'b') # the 1st argument should be the 'smaller' field L = NumberField(field_intersection(L, K), 'a') if L.degree() == 1: return f.parent().gen() else: return polredabs(L.absolute_polynomial())
def nf_lookup(label): r""" Returns a NumberField from its label, caching the result. """ global nf_lookup_table, special_names #print "Looking up number field with label %s" % label if label in nf_lookup_table: #print "We already have it: %s" % nf_lookup_table[label] return nf_lookup_table[label] #print "We do not have it yet, finding in database..." field = C.numberfields.fields.find_one({'label': label}) if not field: raise ValueError("Invalid field label: %s" % label) #print "Found it!" coeffs = [ZZ(c) for c in field['coeffs'].split(",")] gen_name = special_names.get(label, 'a') K = NumberField(PolynomialRing(QQ, 'x')(coeffs), gen_name) #print "The field with label %s is %s" % (label, K) nf_lookup_table[label] = K return K
def _alpha20_3(): x = var("x") K = NumberField(x ** 2 - ZZ(1378464) * x + ZZ(328189501440), "alpha20_3") return K.gens()[0]
def upsert_embedding(id_number, skip = True): rowcc = db.mf_hecke_cc.lucky({'id':id_number}, projection=['an_normalized', 'hecke_orbit_code','id','lfunction_label', 'embedding_root_imag','embedding_root_real']) if rowcc is None: return if skip: if rowcc.get("embedding_root_imag", None) is not None: if rowcc.get("embedding_root_real", None) is not None: return row_embeddings = {} hecke_orbit_code = rowcc['hecke_orbit_code'] newform = db.mf_newforms.lucky({'hecke_orbit_code':hecke_orbit_code},['label','weight','field_poly','dim']) if newform is None: # No newform in db return if newform['dim'] == 1: row_embeddings['embedding_root_imag'] = 0 row_embeddings['embedding_root_real'] = 0 elif newform['weight'] == 1: return elif newform.get('field_poly', None) is None: return else: # print rowcc['lfunction_label'] HF = NumberField(ZZx(newform['field_poly']), "v") hecke_nf = db.mf_hecke_nf.lucky({'hecke_orbit_code':hecke_orbit_code}, ['hecke_ring_cyclotomic_generator','an','field_poly','hecke_ring_numerators','hecke_ring_denominators', 'hecke_ring_power_basis']) assert hecke_nf is not None assert newform['field_poly'] == hecke_nf['field_poly'] assert hecke_nf['hecke_ring_cyclotomic_generator'] == 0 if hecke_nf['hecke_ring_power_basis']: v = HF.gens()[0] betas = [ v**i for i in range(len(newform['field_poly'])) ] else: numerators = hecke_nf.get('hecke_ring_numerators') denominators = hecke_nf.get('hecke_ring_denominators') betas = [HF(elt)/denominators[i] for i, elt in enumerate(numerators)] embeddings = HF.complex_embeddings(prec=2000) an_nf = hecke_nf['an'] betas_embedded = [map(elt, betas) for elt in embeddings] CCC = betas_embedded[0][0].parent() normalization = -CCC(newform['weight'] - 1).real()/2 qexp = [convert_eigenvals_to_qexp(elt, an_nf, normalization) for elt in betas_embedded] min_len = min(len(rowcc['an_normalized']), len(qexp[0])) an_cc = vector(CCC, map(lambda x: CCC(x[0], x[1]), rowcc['an_normalized'][:min_len])) #qexp_diff = [ (vector(CCC, elt[:min_len]) - an_cc).norm() for elt in qexp ] # normalized, to avoid the unstability comming from large weight qexp_diff = [ vector([(elt- an_cc[i])/elt.abs() for i, elt in enumerate(q) if elt != 0]).norm() for j,q in enumerate(qexp)] qexp_diff_sorted = sorted(qexp_diff) min_diff = qexp_diff_sorted[0] #assuring that is something close to zero, and that no other value is close to it assert min_diff < 1e-6 and min_diff/qexp_diff_sorted[1] < 1e-15, "id = %d label = %s\nmin_diff = %.2e \t min_diff/2nd = %.2e\nan_cc = %s\nqexp = %s" % (id_number, rowcc['lfunction_label'], min_diff, min_diff/qexp_diff_sorted[1], vector(ComplexField(20), an_cc[:5]), matrix(ComplexField(20), [elt[:5] for elt in qexp])) for i, elt in enumerate(qexp_diff): if elt == min_diff: row_embeddings['embedding_root_real'] = float(embeddings[i](HF.gen()).real()) row_embeddings['embedding_root_imag'] = float(embeddings[i](HF.gen()).imag()) break assert len(row_embeddings) == 2 db.mf_hecke_cc.upsert({'id': rowcc['id']}, row_embeddings)
class WebNewForm(WebObject, CachedRepresentation): _key = ['level', 'weight', 'character', 'label', 'version'] _file_key = ['hecke_orbit_label','version'] _file_key_multi = ['prec'] if emf_version > 1.3: _collection_name = 'webnewforms2' else: _collection_name = 'webnewforms' def __init__(self, level=1, weight=12, character=1, label='a', prec=0, parent=None, update_from_db=True,**kwargs): emf_logger.debug("In WebNewForm {0}".format((level,weight,character,label,parent,update_from_db))) if isinstance(level,basestring) or kwargs.has_key('hecke_orbit_label'): hecke_orbit_label = kwargs.get('hecke_orbit_label', level) level,weight,character,label = parse_newform_label(hecke_orbit_label) self._reduction = (type(self),(level,weight,character,label),{'parent':parent,'update_from_db':update_from_db}) if isinstance(character, WebChar): character_number = character.number else: character_number = character character = None if parent is None else parent.character if not isinstance(label,basestring): if isinstance(label,(int,Integer)): label = cremona_letter_code(label) else: raise ValueError,"Need label either string or integer! We got:{0}".format(label) emf_logger.debug("Before init properties 0") self._properties = WebProperties( WebInt('level', value=level), WebInt('weight', value=weight), WebCharProperty('character', modulus=level, number=character_number, value = character, include_in_update = True if character is None else False), WebStr('character_naming_scheme', value='Conrey'), WebStr('sage_version', value=''), WebStr('hecke_orbit_label', default_value=newform_label(level, weight, character_number, label)), WebStr('label', default_value=label), WebInt('dimension'), WebqExp('q_expansion'), WebCoeffs('_coefficients'), WebDict('_embeddings'), WebInt('prec',value=0, save_to_db=False, save_to_fs=True), WebNumberField('base_ring'), WebNumberField('coefficient_field'), WebInt('coefficient_field_degree'), WebList('twist_info', required = False), WebInt('is_cm', required = False), WebInt('cm_disc', required = False, default_value=0), WebDict('_cm_values',required=False), WebBool('is_cuspidal',default_value=True), WebDict('satake', required=False), WebDict('_atkin_lehner_eigenvalues', required=False), WebBool('is_rational'), WebPoly('absolute_polynomial'), WebFloat('version', value=float(emf_version), save_to_fs=True), WebDict('explicit_formulas',required=False), WebDate('creation_date',value=None), WebModFormSpaceProperty('parent', value=parent, level = level, weight = weight, character = character_number, update_hecke_orbits=False, update_from_db=update_from_db) # include_in_update = True if parent is None # else False), ) self._add_to_fs_query = {'prec': {'$gt': int(prec-1)}} super(WebNewForm, self).__init__( update_from_db=update_from_db, **kwargs ) self._add_to_fs_query = {'prec': {'$gt': int(self.prec-1)}} # We're setting the WebEigenvalues property after calling __init__ of the base class # because it will set hecke_orbit_label from the db first ## ## We don't init the eigenvalues (since E*v is slow) ## unless we (later) request a coefficient which is not ## in self._coefficients self.eigenvalues = WebEigenvalues(self.hecke_orbit_label, prec = self.prec, \ init_dynamic_properties=False, \ update_from_db = False) self.make_code_snippets() def update_from_db(self, ignore_precision = False, ignore_precision_if_failed = True, **kwargs): # this finds the (file) record with the # lowest precision (=smallest record) # above or equal to self.prec if not ignore_precision: self._add_to_fs_query = {'prec': {'$gt': int(self.prec-1)}} self._sort_files = [('prec', pymongo.ASCENDING)] else: # However, if ignore_precision is True, # then we just ignore this field # This is for compatibility reasons # as older versions did not have the prec stored in the fs file_key_multi = self._file_key_multi self._file_key_multi = None self._add_to_fs_query = None self._sort_files = [] super(WebNewForm,self).update_from_db(**kwargs) if not self.has_updated() and ignore_precision_if_failed: self.update_from_db(ignore_precision = True, ignore_precision_if_failed = False) if ignore_precision: # restore file_key_multi self._file_key_multi = file_key_multi self._sort_files = [('prec', pymongo.ASCENDING)] #remember the precision we just got from the db for queries self._add_to_fs_query = {'prec': {'$gt': int(self.prec-1)}} def __repr__(self): if self.dimension == 0: s = "Zero " else: s = "" s = "WebNewform in S_{0}({1},chi_{2}) with label {3}".format(self.weight,self.level,self.character.number,self.label) return s def init_dynamic_properties(self): if self.q_expansion is not None: if not self.q_expansion.prec >= self.prec: self._properties['q_expansion'].set_from_coefficients(self._coefficients) self._properties['q_expansion'].maxprec = self.prec def q_expansion_latex(self, prec=None, name=None): return self._properties['q_expansion'].latex(prec, name, keepzeta=True) def value(self, z, embedding=0): if self.prec == 0: return 0 else: q = exp(2*CC.pi()*CC(0,1)*z) return sum(self.coefficient_embedding(n,embedding)*q**n for n in range(self.prec)) def coefficient(self, n): r""" Return coefficient nr. n """ #emf_logger.debug("In coefficient: n={0}".format(n)) if n==0: if self.is_cuspidal: return 0 c = self._coefficients.get(n, None) if c is None: c = self.coefficients([n])[0] return c def first_nonvanishing_coefficient(self, return_index = True): r""" Return the first Fourier coefficient of self of index >1 that does not vanish. if return_index is True, we also return the index of that coefficient """ return self._coefficients.first_nonvanishing_coefficient(return_index=return_index) def first_nonvanishing_coefficient_norm(self): return self._coefficients.first_nonvanishing_coefficient_norm() def first_nonvanishing_coefficient_trace(self): return self._coefficients.first_nonvanishing_coefficient_trace() def complexity_of_first_nonvanishing_coefficients(self, number_of_coefficients=4): return self._coefficients.coefficient_complexity(number_of_coefficients) def coefficient_embeddings(self, n): r""" Return all emneddings of the coefficient a(n) of self. """ if not 'values' in self._embeddings: raise ValueError('We do not have any embeddings. for coefficient a({})'.format(n)) else: if n < self.prec: return self._embeddings['values'][n] else: raise ValueError('We do not have coefficient a({})'.format(n)) def coefficient_embedding(self,n,i): r""" Return the i-th complex embedding of coefficient C(n). Note that if it is not in the dictionary we compute the embedding (but not the coefficient). """ if not 'values' in self._embeddings: self._embeddings['values'] = {} if not 'bitprec' in self._embeddings: self._embeddings['bitprec'] = {} embc = self._embeddings['values'].get(n,None) bitprec = self._embeddings['bitprec'] if embc is None: c = self.coefficient(n) if hasattr(c,"complex_embeddings"): embc = c.complex_embeddings(bitprec) else: embc = [ComplexField(bitprec)(c) for x in range(self.coefficient_field_degree)] self._embeddings['values'][n]=embc else: if len(embc) < self.coefficient_field_degree: embc = [embc[0] for x in range(self.coefficient_field_degree)] self._embeddings['values'][n]=embc if i > len(embc): raise ValueError,"Embedding nr. {0} does not exist of a number field of degree {1},embc={2}".format(i,self.coefficient_field_degree,embc) return embc[i] def coefficients(self, nrange=range(1, 10), save_to_db=False): r""" Gives the coefficients in a range. We assume that the self._ap containing Hecke eigenvalues are stored. """ if len(nrange) == 0: return [] if not isinstance(nrange, list): M = nrange nrange = range(0, M) if len(nrange) > 1: emf_logger.debug("getting coeffs in range {0}--{1}".format(nrange[0],nrange[-1])) else: emf_logger.debug("getting coeffs in range {0}--{0}".format(nrange[0])) res = [] recompute = False for n in nrange: c = self._coefficients.get(n, None) #emf_logger.debug("c({0}) in self._coefficients={1}".format(n,c)) if c is None: if n == 0 and self.is_cuspidal: c = 0 else: recompute = True c = self.coefficient_n_recursive(n) self._coefficients[n] = c res.append(c) if recompute and save_to_db: self.save_to_db(update=True) return res def coefficient_n_recursive(self, n): r""" Reimplement the recursive algorithm in sage modular/hecke/module.py We do this because of a bug in sage with .eigenvalue() """ from sage.all import factor ev = self.eigenvalues c2 = self._coefficients.get(2) if c2 is not None: K = c2.parent() else: if ev.max_coefficient_in_db() >= 2: if not ev.has_eigenvalue(2): ev.init_dynamic_properties() else: raise StopIteration,"Newform does not have eigenvalue a(2)!" self._coefficients[2]=ev[2] K = ev[2].parent() prod = K(1) if K.absolute_degree()>1 and K.is_relative(): KZ = K.base_field() else: KZ = K #emf_logger.debug("K= {0}".format(K)) F = factor(n) for p, r in F: #emf_logger.debug("parent_char_val[{0}]={1}".format(p,self.parent.character_used_in_computation.value(p))) #emf_logger.debug("char_val[{0}]={1}".format(p,self.character.value(p))) (p, r) = (int(p), int(r)) pr = p**r cp = self._coefficients.get(p) if cp is None: if ev.has_eigenvalue(p): cp = ev[p] elif ev.max_coefficient_in_db() >= p: ev.init_dynamic_properties() cp = ev[p] #emf_logger.debug("c{0} = {1}, parent={2}".format(p,cp,cp.parent())) if cp is None: raise IndexError,"p={0} is outside the range of computed primes (primes up to {1})! for label:{2}".format(p,max(ev.primes()),self.label) if self._coefficients.get(pr) is None: if r == 1: c = cp else: # a_{p^r} := a_p * a_{p^{r-1}} - eps(p)p^{k-1} a_{p^{r-2}} apr1 = self.coefficient_n_recursive(pr//p) #ap = self.coefficient_n_recursive(p) apr2 = self.coefficient_n_recursive(pr//(p*p)) val = self.character.value(p) if val == 0: c = cp*apr1 else: eps = KZ(val) c = cp*apr1 - eps*(p**(self.weight-1)) * apr2 #emf_logger.debug("c({0})={1}".format(pr,c)) #ev[pr]=c self._coefficients[pr]=c try: prod *= K(self._coefficients[pr]) except: if hasattr(self._coefficients[pr],'vector'): if len(self._coefficients[pr].vector()) == len(K.power_basis()): prod *= K(self._coefficients[pr].vector()) else: emf_logger.debug("vec={0}".format(self._coefficients[pr].vector())) raise ArithmeticError,"Wrong size of vectors!" else: raise ArithmeticError,"Can not compute product of coefficients!" return prod def available_precs(self): r""" The precision is the number of computed Fourier coefficients. We have several records in the database for each newform, each in a different precision. This method returns a list of the precisions that are available in the database for this newform. """ files = self.get_file_list() try: return [x['prec'] for x in files] except KeyError: #backwards compatibility try: return [self.get_db_record()['prec']] except KeyError: return [self.prec] def max_available_prec(self): try: ps = self.available_precs() except IndexError: ps = [0] return max(ps) def delete_file_with_prec(self, prec): files = self.get_file_list({'prec': int(prec)}) for f in files: self._files.delete(f['_id']) def max_cn(self): r""" The largest N for which we are sure that we can compute a(n) for all 1<=n<=N """ return self.eigenvalues.max_coefficient_in_db() #if self.eigenvalues.primes()==[]: # return 1 #return max(self.eigenvalues.primes()) + 1 def atkin_lehner_eigenvalue(self, Q): r""" Return the Atkin-Lehner eigenvalues of self corresponding to Q|N """ if not (self.character.is_trivial() or self.character.order == 2): return None l = self.atkin_lehner_eigenvalues() return l.get(Q) def atkin_lehner_eigenvalues(self): r""" Return the Atkin-Lehner eigenvalues of self. EXAMPLES:: sage: get_atkin_lehner_eigenvalues(4,14,0) '{2: 1, 14: 1, 7: 1}' sage: get_atkin_lehner_eigenvalues(4,14,1) '{2: -1, 14: 1, 7: -1}' """ if not (self.character.is_trivial() or self.character.order == 2): return None if(len(self._atkin_lehner_eigenvalues.keys()) > 0): return self._atkin_lehner_eigenvalues def atkin_lehner_eigenvalues_for_all_cusps(self): r""" """ self._atkin_lehner_eigenvalues_at_cusps = {} G =Gamma0(self.level) for c in Gamma0(self.level).cusps(): aev = self.atkin_lehner_eigenvalues() if aev is None: self._atkin_lehner_eigenvalues_at_cusps = None else: for Q,ev in aev.items(): if G.are_equivalent(c,Q/self.level): self._atkin_lehner_eigenvalues_at_cusps[c] = Q,ev return self._atkin_lehner_eigenvalues_at_cusps def url(self): return url_for('emf.render_elliptic_modular_forms', level=self.level, weight=self.weight, character=self.character.number, label=self.label) def create_small_record(self, min_prec=10, want_prec=100, max_length = 5242880, max_height_qexp = default_max_height): ### creates a duplicate record (fs) of this webnewform ### with lower precision to load faster on the web ### we aim to have at most max_length bytes ### but at least min_prec coefficients and we desire to have want_prec if min_prec>=self.prec: raise ValueError("Need higher precision, self.prec = {}".format(self.prec)) if not hasattr(self, '_file_record_length'): self.update_from_db() l = self._file_record_length if l > max_length or self.prec > want_prec: nl = float(l)/float(self.prec)*float(want_prec) if nl > max_length: prec = max([floor(float(self.prec)/float(l)*float(max_length)), min_prec]) else: prec = want_prec emf_logger.debug("Creating a new record with prec = {}".format(prec)) self.prec = prec include_coeffs = self.complexity_of_first_nonvanishing_coefficients() <= default_max_height if include_coeffs: self.q_expansion = self.q_expansion.truncate_powerseries(prec) self._coefficients = {n:c for n,c in self._coefficients.iteritems() if n<prec} else: self.q_expansion = self.q_expansion.truncate_powerseries(1) self._coefficients = {} self.prec = 0 self.coefficient_field = NumberField(self.absolute_polynomial, names=str(self.coefficient_field.gen())) self._embeddings['values'] = {n:c for n,c in self._embeddings['values'].iteritems() if n<prec} self._embeddings['prec'] = prec self.save_to_db() def download_to_sage(self, prec=None): r""" Minimal version for now to download to sage. Does not work for high values of prec for large degree number fields (timeout). """ if prec is None: prec = self.prec s = "var('x')\n" if self.base_ring.absolute_degree() > 1: s += "K.<{brgen}>=NumberField({crpol})\n".format(brgen=str(self.base_ring.gen()), crpol=self.base_ring.polynomial().change_variable_name('x')) if self.coefficient_field.is_absolute(): if self.coefficient_field.absolute_degree() > 1: s += "L.<{cfgen}> = NumberField({cfpol})\n".format( cfgen=str(self.coefficient_field.gen()), cfpol=self.absolute_polynomial ) elif self.coefficient_field.relative_degree() > 1: s += "y = polygen(K)\n" s += "L.<{cfgen}> = NumberField({cfpol})\n".format( cfgen=str(self.coefficient_field.gen()), cfpol=self.coefficient_field.relative_polynomial().change_variable_name('y') ) s = s + "D = DirichletGroup({N})\n".format( N = self.level ) C = self.character.sage_character.parent() s = s + "f = {{'coefficients': {coeffs}, 'level' : {level}, 'weight': {weight}, 'character': D.Element(D,vector({elt})), 'label': '{label}','dimension': {dim}, 'is_cm': {cm} , 'cm_discriminant': {cm_disc}, 'atkin_lehner': {al}, 'explicit_formulas': {ep}}}".format(coeffs = self.coefficients(range(prec)), level=self.level, weight=self.weight, elt = list(self.character.sage_character.element()), label=self.hecke_orbit_label, dim=self.dimension, cm=self.is_cm, cm_disc=None if not self.is_cm else self.cm_disc , al=self.atkin_lehner_eigenvalues(), ep = self.explicit_formulas ) s = s + "\n\n#EXAMPLE\n" s = s + "#sage: f['coefficients'][7]\n#{}\n".format(self.coefficient(7)) s = s + "#sage: f['character']\n#{}".format(self.character.sage_character) emf_logger.debug("Generated sage file for {}".format(self.hecke_orbit_label)) return s def sage_newform_number(self): ##store this in the db!! return orbit_index_from_label(self.label) def make_code_snippets(self): self.code = deepcopy(self.parent.code) self.code['show'] = {'sage':''} # Fill in placeholders for this specific newform: self.code['f']['sage'] = self.code['f']['sage'].format(newform_number=self.sage_newform_number()) #self.code['f']['sage'] = self.code['f']['sage'].split("\n") # remove final empty line if len(self.code['f']['sage'][-1])==0: self.code['f']['sage'] = self.code['f']['sage'][:-1] def dump_coefficients(self, prec): if prec is None: prec = self.prec return dumps(self.coefficients(range(prec)))
def session(): from sqlalchemy.orm import sessionmaker Session = sessionmaker(bind=engine) return Session() ######################################################## # Convenience functions to use the database ######################################################## from sage.all import (QQ, ZZ, NumberField, polygen, dumps, gcd, parallel, divisors, cartesian_product_iterator) from sage.rings.all import is_Ideal from psage.modform.hilbert.sqrt5.hmf import primes_of_bounded_norm from psage.number_fields.sqrt5.prime import Prime x = polygen(QQ, 'x') F = NumberField(x**2 - x - 1, 'a') a = F.gen() def ideal_to_tuple(N): v = N.free_module().echelonized_basis_matrix().list() return int(v[0]), int(v[1]), int(v[3]) def tuple_to_ideal(t): return F.ideal([t[0] + a*t[1], t[2] + a*t[2]]) def fast_ideal(P): return Prime(P) if is_Ideal(P) else P def store_space(s, H): """ s = session
def list_to_factored_poly_otherorder(s, galois=False, vari = 'T'): """ Either return the polynomial in a nice factored form, or return a pair, with first entry the factored polynomial and the second entry a list describing the Galois groups of the factors. vari allows to choose the variable of the polynomial to be returned. """ gal_list=[] if len(s) == 1: if galois: return [str(s[0]), [[0,0]]] return str(s[0]) sfacts = factor(PolynomialRing(ZZ, 'T')(s)) sfacts_fc = [[v[0],v[1]] for v in sfacts] if sfacts.unit() == -1: sfacts_fc[0][0] *= -1 outstr = '' x = var('x') for v in sfacts_fc: this_poly = v[0] # if the factor is -1+T^2, replace it by 1-T^2 # this should happen an even number of times, mod powers if this_poly.substitute(T=0) == -1: this_poly = -1*this_poly v[0] = this_poly if galois: this_degree = this_poly.degree() # hack because currently sage only handles monic polynomials: this_poly = expand(x**this_degree*this_poly.substitute(T=1/x)) this_number_field = NumberField(this_poly, "a") this_gal = this_number_field.galois_group(type='pari') this_t_number = this_gal.group().__pari__()[2].sage() gal_list.append([this_degree, this_t_number]) vcf = v[0].list() started = False if len(sfacts) > 1 or v[1] > 1: outstr += '(' for i in range(len(vcf)): if vcf[i] != 0: if started and vcf[i] > 0: outstr += '+' started = True if i == 0: outstr += str(vcf[i]) else: if abs(vcf[i]) != 1: outstr += str(vcf[i]) elif vcf[i] == -1: outstr += '-' if i == 1: outstr += vari #instead of putting in T for the variable, put in a variable of your choice elif i > 1: outstr += vari + '^{' + str(i) + '}' if len(sfacts) > 1 or v[1] > 1: outstr += ')' if v[1] > 1: outstr += '^{' + str(v[1]) + '}' if galois: if galois and len(sfacts_fc)==2: if sfacts[0][0].degree()==2 and sfacts[1][0].degree()==2: troubletest = sfacts[0][0].disc()*sfacts[1][0].disc() if troubletest.is_square(): gal_list=[[2,1]] return [outstr, gal_list] return outstr
def find_newform_label(level,weight,character,field,aps): r""" Find the label of the newform orbit in the database which matches the input. INPUT: - 'level' -- the level, - 'weight' -- the weight - 'character' -- the character' - 'field' -- the field, given in terms of a list of integer coefficients for the absolute polynomial - 'aps' -- the coefficients - given as a dictionary of lists giving the coefficient in terms of the generator of the field as above. EXAMPLE: sage: find_newform_label(9,16,1,[-119880,0,1],{2:[0,1]}) u'e' sage: find_newform_label(71,2,1,[-3,-4,1,1],{3:[0,-1,0]}) u'a' sage: find_newform_label(71,2,1,[-3,-4,1,1],{5:[5,1,-1]}) u'a' NOTE: We implicitly assume that the input given is correct in the sense that if there is a unique orbit with a coefficient field of the same degree as the input then we simply return that label. (This will save a lot of time...) """ from web_modform_space import WebModFormSpace from sage.all import NumberField,QQ M = WebModFormSpace(level=level,weight=weight,character=character) if M.dimension_new_cusp_forms==1: return 'a' orbits = M.hecke_orbits ## construct field from field input... if not isinstance(field,list): raise ValueError,"Need to give field as a list!" if not isinstance(aps,dict): raise ValueError,"Need to give aps as a dict!" if field == [1]: NF = QQ else: NF = NumberField(QQ['x'](field),names='x') degree_of_input = NF.absolute_degree() degrees = map(lambda x:x[1].coefficient_field_degree,orbits.viewitems()) if degrees.count(degree_of_input)==0: raise ValueError,"No newform with this level, weight, character and field degree!" if degrees.count(degree_of_input)==1: ## If there is a unique mathcing field we return this orbit label. l = filter(lambda x: x[1].coefficient_field_degree==degree_of_input,orbits.viewitems() ) return l[0][0] aps_input = { p: NF(a) for p,a in aps.viewitems()} possible_labels = orbits.keys() for label,f in orbits.viewitems(): if f.coefficient_field_degree != degree_of_input: possible_labels.remove(label) continue try: for p,ap_input in aps_input.viewitems(): if f.coefficient_field == QQ: homs = [lambda x: x] else: homs = f.coefficient(p).parent().Hom(NF) for h in homs: ap = h(f.coefficient(p)) if ap_input != ap: possible_labels.remove(label) raise StopIteration except StopIteration: continue if len(possible_labels) > 1: raise ArithmeticError,"Not sufficient data (or errors) to determine orbit!" if len(possible_labels) == 0: raise ArithmeticError,"Not sufficient data (or errors) to determine orbit! NO matching label found!" return possible_labels[0]
sage: c = F.primes_above(389)[0] sage: T = hecke_ops(c, TH) sage: for nm,p,t in T: ... print nm, p, t.charpoly().factor() 5 a + 2 (x - 6) * (x^2 + 4*x - 1) * (x^2 - x - 4)^2 9 3 (x - 10) * (x^2 + 3*x - 9) * (x^4 - 5*x^3 + 3*x^2 + 6*x - 4) 11 a + 3 (x - 12) * (x + 3)^2 * (x^4 - 17*x^2 + 68) 11 2*a + 3 (x - 12) * (x^2 + 5*x + 5) * (x^4 - x^3 - 23*x^2 + 18*x + 52) """ from sage.all import (NumberField, polygen, QQ, ZZ, QuaternionAlgebra, cached_function, disk_cached_function) x = polygen(QQ,'x') F = NumberField(x**2 - x -1, 'a') O_F = F.ring_of_integers() B = QuaternionAlgebra(F, -1, -1, 'i,j,k') def modp_splitting(p): """ INPUT: - p -- ideal of the number field K = B.base() with ring O of integers. OUTPUT: - matrices I, J in M_2(O/p) such that i |--> I and j |--> J defines an algebra morphism, i.e., I^2=a, J^2=b, I*J=-J*I. EXAMPLES::
def _a47(): x = var("x") K = NumberField( x ** 3 - x ** 2 - ZZ(524706) * x + ZZ(103406706), names="a47") return K.gens()[0]