def pari_set_precision(x, precision): """ Promote a real number to an arbitrary precision Pari number with the same value. The precision should be given in bits. """ return pari(0) if x == 0 else pari(x).precision( prec_bits_to_dec(precision))
def conductor(self): B = pari("znconreyconductor(%s,%s,&chi0)" % (self.G, self.chi_pari)) if B.type() == 't_INT': # means chi is primitive self.chi_0 = self.chi_pari self.indlabel = self.number return int(B) else: self.chi_0 = pari("chi0") G_0 = Pari("znstar({},1)".format(B)) self.indlabel = int(pari("znconreyexp(%s,%s)" % (G_0, self.chi_0))) return int(B[0])
def to_polredabs(K): """ INPUT: * "K" - a number field OUTPUT: * "phi" - an isomorphism K -> L, where L = QQ['x']/f and f a polynomial such that f = polredabs(f) """ R = PolynomialRing(QQ, 'x') x = R.gen(0) if K == QQ: L = QQ.extension(x, 'w') return QQ.hom(L) L = K.absolute_field('a') m1 = L.structure()[1] f = L.absolute_polynomial() g = pari(f).polredabs(1) g, h = g[0].sage(locals={'x': x}), g[1].lift().sage(locals={'x': x}) if debug: print('f', f) print('g', g) print('h', h) M = QQ.extension(g, 'w') m2 = L.hom([h(M.gen(0))]) return m2 * m1
def polredbest_stable(pol): x = pol.parent().variable_name() f = pari(pol) oldf = None while f!=oldf: oldf, f = f, f.polredbest() return sagepol(f,x)
def to_polredabs(K): """ INPUT: * "K" - a number field OUTPUT: * "phi" - an isomorphism K -> L, where L = QQ['x']/f and f a polynomial such that f = polredabs(f) """ R = PolynomialRing(QQ,'x') x = R.gen(0) if K == QQ: L = QQ.extension(x,'w') return QQ.hom(L) L = K.absolute_field('a') m1 = L.structure()[1] f = L.absolute_polynomial() g = pari(f).polredabs(1) g,h = g[0].sage(locals={'x':x}),g[1].lift().sage(locals={'x':x}) if debug: print 'f',f print 'g',g print 'h',h M = QQ.extension(g,'w') m2 = L.hom([h(M.gen(0))]) return m2*m1
def sage_residue_field_degrees_function(nf): """ Version of above which takes a sage number field Used by Artin representation code when the Artin field is not in the database. """ D = nf.disc() return main_work(pari(nf), D, 'sage')
def from_polynomial(cls, pol): pol = PolynomialRing(QQ, 'x')(str(pol)) pol *= pol.denominator() R = pol.parent() pol = R(pari(pol).polredbest().polredabs()) return cls.from_coeffs( [int(c) for c in pol.coefficients(sparse=False)])
def sage_residue_field_degrees_function(nf): """ Version of above which takes a sage number field Used by Artin representation code when the Artin field is not in the database. """ D = nf.disc() return main_work(pari(nf),D,'sage')
def NewSpace(N, k, chi_number,Detail=0): G = pari(N).znstar(1) chi_dc = char_orbit_index_to_DC_number(N,chi_number) chi_gp = G.znconreylog(chi_dc) chi_order = ZZ(G.charorder(chi_gp)) chi_degree = euler_phi(chi_order) if Detail: print("order(chi) = {}, [Q(chi):Q] = {}".format(chi_order, chi_degree)) print("pari character = {}".format(chi_gp)) NK = [N,k,[G,chi_gp]] Snew = pari(NK).mfinit(0) rel_degree = Snew.mfdim() dim = chi_degree*rel_degree if Detail: print("Relative dimension = {}".format(rel_degree)) print("dim({}:{}:{}) = {}*{} = {}".format(N,k,chi_number,chi_degree,rel_degree,dim)) return NK, Snew
def __init__(self, modulus, number): assert gcd(modulus, number) == 1 self.modulus = Integer(modulus) self.number = Integer(number) self.G = Pari("znstar({},1)".format(modulus)) self.chi_pari = pari("znconreylog(%s,%d)" % (self.G, self.number)) self.chi_0 = None self.indlabel = None
def gpK(self): if not self.haskey('gpK'): Qx = PolynomialRing(QQ,'x') # while [1] is a perfectly good basis for Z, gp seems to want [] basis = [Qx(el.replace('a','x')) for el in self.zk()] if self.degree() > 1 else [] k1 = pari( "nfinit([%s,%s])" % (str(self.poly()),str(basis)) ) self._data['gpK'] = k1 return self._data['gpK']
def DC_char_to_gp_char(chi, G=None): """ If this function is to be called repeatedly with the same modulus it is better to precompute G and pass it, so save recomputation: """ if G is None: G = pari(chi.modulus()).znstar(1) return G.znconreylog(DC.number(chi))
def gauss_sum_numerical(self, a): # There seems to be a bug in pari when a is a multiple of the modulus, # so we deal with that separately if self.modulus.divides(a): if self.conductor() == 1: return euler_phi(self.modulus) else: return Integer(0) else: return pari("znchargauss(%s,%s,a=%d)" % (self.G, self.chi_pari, a))
def f(l_min, l_max): from pymongo import Connection C = Connection(address).research C.authenticate(user, password) C = C.ellcurves for v in C.find({'level':{'$gte':level_min, '$lt':level_max}, 'number':1, 'ap':{'$exists':False}}): E = pari('ellinit(%s,1)'%v['weq']) ap = dict([(str(p),int(E.ellap(p))) for p in P]) C.update({'_id':v['_id']}, {'$set':{'ap':ap}})
def polredabs(self): if "polredabs" in self._data.keys(): return self._data["polredabs"] else: pol = PolynomialRing(QQ, 'x')(self.polynomial()) pol *= pol.denominator() R = pol.parent() from sage.all import pari pol = R(pari(pol).polredabs()) self._data["polredabs"] = pol return pol
def polredabs(self): if "polredabs" in self._data.keys(): return self._data["polredabs"] else: pol = PolynomialRing(QQ, 'x')(map(str, self.polynomial())) # Need to map because the coefficients are given as unicode, which does not convert to QQ pol *= pol.denominator() R = pol.parent() from sage.all import pari pol = R(pari(pol).polredabs()) self._data["polredabs"] = pol return pol
def from_polynomial(cls, pol): try: # try to cast to ring pol = PolynomialRing(QQ, 'x')(pol) except Exception: # try again as a string pol = PolynomialRing(QQ, 'x')(str(pol)) pol *= pol.denominator() R = pol.parent() pol = R(pari(pol).polredbest().polredabs()) return cls.from_coeffs( [int(c) for c in pol.coefficients(sparse=False)])
def polredabs(self): if "polredabs" in self._data.keys(): return self._data["polredabs"] else: pol = PolynomialRing(QQ, 'x')(map(str,self.polynomial())) # Need to map because the coefficients are given as unicode, which does not convert to QQ pol *= pol.denominator() R = pol.parent() from sage.all import pari pol = R(pari(pol).polredabs()) self._data["polredabs"] = pol return pol
def from_polynomial(cls, pol): try: # try to cast to ring pol = PolynomialRing(QQ, 'x')(pol) except Exception: # try again as a string pol = PolynomialRing(QQ, 'x')(str(pol)) pol *= pol.denominator() # For some reason the error raised by Pari on a constant polynomial is not being caught if pol.degree() < 1: raise ValueError("Polynomial cannot be constant") R = pol.parent() pol = R(pari(pol).polredbest().polredabs()) return cls.from_coeffs([int(c) for c in pol.coefficients(sparse=False)])
def bounded_elements(N): """ Return elements in maximal order of B that have reduced norm whose trace is at most N. EXAMPLES:: sage: from sage.modular.hilbert.sqrt5 import bounded_elements sage: X = bounded_elements(3) sage: len(X) 180 sage: rnX = [a.reduced_norm() for a in X] sage: set([a.trace() for a in rnX]) set([2, 3]) sage: set([a.norm() for a in rnX]) set([1]) sage: X = bounded_elements(5) sage: len(X) 1200 sage: rnX = [a.reduced_norm() for a in X] sage: set([a.trace() for a in rnX]) set([2, 3, 4, 5]) sage: set([a.norm() for a in rnX]) set([1, 4, 5]) """ # Get our maximal order R = icosian_ring_gens_over_ZZ() # Compute Gram matrix of R G = gram_matrix_of_maximal_order(R) # Make PARI quadratic form from sage.all import pari qf = pari(G) # Get the vectors of norm up to N. # The 2 is because we had to scale by 2 to get # rid of denominator in Gram matrix. Z = qfminim(qf, N) Z2 = Z[2].sage().transpose() # For each vector, make the corresponding element of B. # TODO: This step massively dominates the runtime, and can be # easily made trivial with careful thought. V = [] for i in range(Z2.nrows()): w = Z2[i] V.append(sum(w[j]*R[j] for j in range(8))) return V
def bounded_elements(N): """ Return elements in maximal order of B that have reduced norm whose trace is at most N. EXAMPLES:: sage: from psage.modform.hilbert.sqrt5.sqrt5 import bounded_elements sage: X = bounded_elements(3) sage: len(X) 180 sage: rnX = [a.reduced_norm() for a in X] sage: set([a.trace() for a in rnX]) set([2, 3]) sage: set([a.norm() for a in rnX]) set([1]) sage: X = bounded_elements(5) sage: len(X) 1200 sage: rnX = [a.reduced_norm() for a in X] sage: set([a.trace() for a in rnX]) set([2, 3, 4, 5]) sage: set([a.norm() for a in rnX]) set([1, 4, 5]) """ # Get our maximal order R = icosian_ring_gens_over_ZZ() # Compute Gram matrix of R G = gram_matrix_of_maximal_order(R) # Make PARI quadratic form from sage.all import pari qf = pari(G) # Get the vectors of norm up to N. # The 2 is because we had to scale by 2 to get # rid of denominator in Gram matrix. Z = qfminim(qf, N) Z2 = Z[2].sage().transpose() # For each vector, make the corresponding element of B. # TODO: This step massively dominates the runtime, and can be # easily made trivial with careful thought. V = [] for i in range(Z2.nrows()): w = Z2[i] V.append(sum(w[j] * R[j] for j in range(8))) return V
def is_semisimple_modular(M, m, nprimes=5): """M is a pari matrix over Q(zeta_m). Check if M mod p has squarefree char poly for nprimes primes p=1 (mod m). If True for any p, return True since then the char poly of M itself must be square-free. If False for all p, return False since the M probably has non-squarefree char poly. There may therefore be false negatives. """ pol = cyclotomic_polynomial(m) pt = pari("t") np = 0 for p in prime_range(1000000): if m > 1 and not p % m == 1: continue np += 1 #print("testing modulo p={}".format(p)) if np > nprimes: #print("op not semisimple modulo {} primes, so returning False".format(nprimes)) return False zmodp = pari(pol.roots(GF(p))[0][0]) #print("zmodp = {}".format(zmodp)) try: Mmodp = M.lift() * pari(mod(1, p)) #print("Lifted matrix = {}".format(Mmodp)) Mmodp = Mmodp.subst(pt, zmodp) #print("matrix (mod {}) = {}".format(p,Mmodp)) modpcharpoly = Mmodp.charpoly() #print("char poly (mod {}) = {}".format(p,modpcharpoly)) if modpcharpoly.issquarefree(): #print("op is semisimple mod {}".format(p)) return True else: #print("op is not semisimple mod {}".format(p)) pass except PariError: ## happens if M not integral mod p np -= 1
def TraceHash(E): r"""Return the trace hash of this elliptic curve defined over either QQ or a number field. """ K = E.base_field() if K == QQ: E_pari = pari(E.a_invariants()).ellinit() return TraceHash_from_ap([E_pari.ellap(p) for p in TH_P]) if K not in TH_P_cache: TH_P_cache[K] = dict([(p,[P for P in K.primes_above(p) if P.norm()==p]) for p in TH_P]) def ap(p): return sum([E.reduction(P).trace_of_frobenius() for P in TH_P_cache[K][p]], 0) return TraceHash_from_ap([ap(p) for p in TH_P])
def residue_field_degrees_function(K): """ Given a sage field, returns a function that has input: a prime p output: the residue field degrees at the prime p """ k1 = pari(K) D = K.disc() def decomposition(p): if not ZZ(p).divides(D): dec = k1.idealprimedec(p) dec = [z[3] for z in dec] return dec else: raise ValueError("Expecting a prime not dividing D") return decomposition
def poly_to_field_label(pol): try: pol = PolynomialRing(QQ, 'x')(str(pol)) pol *= pol.denominator() R = pol.parent() pol = R(pari(pol).polredabs()) except: return None coeffs = list2string([int(c) for c in pol.coeffs()]) d = int(pol.degree()) query = {'coeffs': coeffs} C = base.getDBConnection() one = C.numberfields.fields.find_one(query) if one: return one['label'] return None
def alpha(self, z): """ INPUT: - z - an element of P^1(O_F/P). """ W = self.ideal_basis(z) G = self.ideal_gram(W) from sage.all import pari qf = pari(G) t = self.pi.trace() c = qfminim(qf, t) #print "number of vectors", c[0] for r in c[2].sage().transpose(): a = sum([W[i] * r[i] for i in range(8)]) if a.reduced_norm() == self.pi: return a raise ValueError, "bug"
def alpha(self, z): """ INPUT: - z - an element of P^1(O_F/P). """ W = self.ideal_basis(z) G = self.ideal_gram(W) from sage.all import pari qf = pari(G) t = self.pi.trace() c = qfminim(qf, t) #print "number of vectors", c[0] for r in c[2].sage().transpose(): a = sum([W[i]*r[i] for i in range(8)]) if a.reduced_norm() == self.pi: return a raise ValueError, "bug"
def G_name(self): """ More-or-less standardized name of the abstract group """ wnf = WebNumberField.from_polredabs(self.polredabs()) if not wnf.is_null(): mygalstring = wnf.galois_string() if re.search('Trivial', mygalstring) is not None: return '$C_1$' # Have to remove dollar signs return mygalstring if self.polredabs().degree() < 12: # Let pari compute it for us now from sage.all import pari galt = int(list(pari('polgalois(' + str(self.polredabs()) + ')'))[2]) from lmfdb.galois_groups.transitive_group import WebGaloisGroup tg = WebGaloisGroup.from_nt(self.polredabs().degree(), galt) return tg.display_short() return self._data["G-Name"]
def modular_units_of_degree(G,deg,rational = True, verbose = False,qfminim_bound = 10**5): """ Returns an iterator over all modular units on the curve X(G). INPUT: - ``G`` - a congruence subgroup - ``deg`` - int, the degree of modular unit to search for - ``rational`` - bool, true means modular unit should be defined over QQ - ``verbose`` - bool (default = false), wether or not to print progress - ``qfminim_bound`` - int (default - 10^5), given to pari's qfminim command, and is an upper bound on how many vectors of short l2 norm are returned by pari this function will raise an error if pari finds more short vectors then it returns """ if rational: L,D=rational_modular_unit_lattice(G) else: L,D=modular_unit_lattice(G) M = L.basis_matrix().change_ring(ZZ).LLL() GS_matrix=M*M.transpose() pari_gs=pari(GS_matrix) short_vectors=pari_gs.qfminim(deg**2*2,qfminim_bound) if verbose: print(short_vectors[:2]) count = 0 for i in short_vectors[2]: count+=1 if verbose and count%10000==0: print(count) v=vector(QQ,i.list())*M if v.norm(1)/2 == deg: yield L(v) assert short_vectors[0].sage() < 2*qfminim_bound
def modular_units_of_degree(G,deg,rational = True, verbose = False,qfminim_bound = 10**5): """ Returns an iterator over all modular units on the curve X(G). INPUT: - ``G`` - a congruence subgroup - ``deg`` - int, the degree of modular unit to search for - ``rational`` - bool, true means modular unit should be defined over QQ - ``verbose`` - bool (default = false), wether or not to print progress - ``qfminim_bound`` - int (default - 10^5), given to pari's qfminim command, and is an upper bound on how many vectors of short l2 norm are returned by pari this function will raise an error if pari finds more short vectors then it returns """ if rational: L,D=rational_modular_unit_lattice(G) else: L,D=modular_unit_lattice(G) M = L.basis_matrix().change_ring(ZZ).LLL() GS_matrix=M*M.transpose() pari_gs=pari(GS_matrix) short_vectors=pari_gs.qfminim(deg**2*2,qfminim_bound) if verbose: print short_vectors[:2] count = 0 for i in short_vectors[2]: count+=1 if verbose and count%10000==0: print count v=vector(QQ,i.list())*M if v.norm(1)/2 == deg: yield L(v) assert short_vectors[0].sage() < 2*qfminim_bound
def G_name(self): """ More-or-less standardized name of the abstract group """ import re wnf = WebNumberField.from_polredabs(self.polredabs()) if not wnf.is_null(): mygalstring = wnf.galois_string() if re.search('Trivial', mygalstring) is not None: return '$C_1$' # Have to remove dollar signs return mygalstring if self.polredabs().degree() < 12: # Let pari compute it for us now from sage.all import pari galt = int(list(pari('polgalois(' + str(self.polredabs()) + ')'))[2]) from lmfdb.transitive_group import WebGaloisGroup tg = WebGaloisGroup.from_nt(self.polredabs().degree(), galt) return tg.display_short() return self._data["G-Name"]
def __init__(self, number_field, mod_ideal=1, mod_archimedean=None): if mod_archimedean is None: mod_archimedean = [0] * len(number_field.real_places()) mod_ideal = number_field.ideal(mod_ideal) bnf = gp(number_field.pari_bnf()) # Use PARI to compute ray class group bnr = bnf.bnrinit([mod_ideal, mod_archimedean], 1) invariants = bnr[5][2] # bnr.clgp.cyc invariants = tuple([Integer(x) for x in invariants]) names = tuple(["I%i" % i for i in range(len(invariants))]) generators = bnr[5][3] # bnr.gen = bnr.clgp[3] generators = [number_field.ideal(pari(x)) for x in generators] AbelianGroup_class.__init__(self, invariants, names) self.__number_field = number_field self.__bnr = bnr self.__pari_mod = bnr[2][1] self.__mod_ideal = mod_ideal self.__mod_arch = mod_archimedean self.__generators = generators
def __init__(self, number_field, mod_ideal = 1, mod_archimedean = None): if mod_archimedean == None: mod_archimedean = [0] * len(number_field.real_places()) mod_ideal = number_field.ideal( mod_ideal ) bnf = gp(number_field.pari_bnf()) # Use PARI to compute ray class group bnr = bnf.bnrinit([mod_ideal, mod_archimedean],1) invariants = bnr[5][2] # bnr.clgp.cyc invariants = tuple([ Integer(x) for x in invariants ]) names = tuple([ "I%i"%i for i in range(len(invariants)) ]) generators = bnr[5][3] # bnr.gen = bnr.clgp[3] generators = [ number_field.ideal(pari(x)) for x in generators ] AbelianGroup_class.__init__(self, invariants, names) self.__number_field = number_field self.__bnr = bnr self.__pari_mod = bnr[2][1] self.__mod_ideal = mod_ideal self.__mod_arch = mod_archimedean self.__generators = generators
def residue_field_degrees_function(K): """ Given a sage field, returns a function that has input: a prime p output: the residue field degrees at the prime p """ k1 = pari(K) D = K.disc() def decomposition(p): if not ZZ(p).divides(D): #dec = k1.idealprimedec(p) # ar = ArtinRepresentation(1,29,1) print 'decomposing prime...***' try: print 'TRYING GP2' dec = gp2.idealprimedec(k1, p) except: dec = gp.idealprimedec(k1, p) dec = [z[3] for z in dec] return dec else: raise ValueError("Expecting a prime not dividing D") return decomposition
def zk(self): if self.haskey('zk'): zkstrings = self._data['zk'] return [str(u) for u in zkstrings] return list(pari(self.poly()).nfbasis())
def from_polynomial(cls, pol): pol = PolynomialRing(QQ, 'x')(str(pol)) pol *= pol.denominator() R = pol.parent() pol = R(pari(pol).polredbest().polredabs()) return cls.from_coeffs([int(c) for c in pol.coefficients(sparse=False)])
def render_field_webpage(args): data = None info = {} bread = [('Global Number Fields', url_for(".number_field_render_webpage"))] # This function should not be called unless label is set. label = clean_input(args['label']) nf = WebNumberField(label) data = {} if nf.is_null(): bread.append(('Search Results', ' ')) info['err'] = 'There is no field with label %s in the database' % label info['label'] = args['label_orig'] if 'label_orig' in args else args[ 'label'] return search_input_error(info, bread) info['wnf'] = nf data['degree'] = nf.degree() data['class_number'] = nf.class_number_latex() ram_primes = nf.ramified_primes() t = nf.galois_t() n = nf.degree() data['is_galois'] = nf.is_galois() data['is_abelian'] = nf.is_abelian() if nf.is_abelian(): conductor = nf.conductor() data['conductor'] = conductor dirichlet_chars = nf.dirichlet_group() if len(dirichlet_chars) > 0: data['dirichlet_group'] = [ '<a href = "%s">$\chi_{%s}(%s,·)$</a>' % (url_for('characters.render_Dirichletwebpage', modulus=data['conductor'], number=j), data['conductor'], j) for j in dirichlet_chars ] data['dirichlet_group'] = r'$\lbrace$' + ', '.join( data['dirichlet_group']) + r'$\rbrace$' if data['conductor'].is_prime() or data['conductor'] == 1: data['conductor'] = "\(%s\)" % str(data['conductor']) else: factored_conductor = factor_base_factor(data['conductor'], ram_primes) factored_conductor = factor_base_factorization_latex( factored_conductor) data['conductor'] = "\(%s=%s\)" % (str( data['conductor']), factored_conductor) data['galois_group'] = group_display_knowl(n, t) data['cclasses'] = cclasses_display_knowl(n, t) data['character_table'] = character_table_display_knowl(n, t) data['class_group'] = nf.class_group() data['class_group_invs'] = nf.class_group_invariants() data['signature'] = nf.signature() data['coefficients'] = nf.coeffs() nf.make_code_snippets() D = nf.disc() data['disc_factor'] = nf.disc_factored_latex() if D.abs().is_prime() or D == 1: data['discriminant'] = "\(%s\)" % str(D) else: data['discriminant'] = "\(%s=%s\)" % (str(D), data['disc_factor']) data['frob_data'], data['seeram'] = frobs(nf) # Bad prime information npr = len(ram_primes) ramified_algebras_data = nf.ramified_algebras_data() if isinstance(ramified_algebras_data, str): loc_alg = '' else: # [label, latex, e, f, c, gal] loc_alg = '' for j in range(npr): if ramified_algebras_data[j] is None: loc_alg += '<tr><td>%s<td colspan="7">Data not computed' % str( ram_primes[j]) else: mydat = ramified_algebras_data[j] p = ram_primes[j] loc_alg += '<tr><td rowspan="%d">$%s$</td>' % (len(mydat), str(p)) mm = mydat[0] myurl = url_for('local_fields.by_label', label=mm[0]) lab = mm[0] if mm[3] * mm[2] == 1: lab = r'$\Q_{%s}$' % str(p) loc_alg += '<td><a href="%s">%s</a><td>$%s$<td>$%d$<td>$%d$<td>$%d$<td>%s<td>$%s$' % ( myurl, lab, mm[1], mm[2], mm[3], mm[4], mm[5], show_slope_content(mm[8], mm[6], mm[7])) for mm in mydat[1:]: lab = mm[0] if mm[3] * mm[2] == 1: lab = r'$\Q_{%s}$' % str(p) loc_alg += '<tr><td><a href="%s">%s</a><td>$%s$<td>$%d$<td>$%d$<td>$%d$<td>%s<td>$%s$' % ( myurl, lab, mm[1], mm[2], mm[3], mm[4], mm[5], show_slope_content(mm[8], mm[6], mm[7])) loc_alg += '</tbody></table>' ram_primes = str(ram_primes)[1:-1] if ram_primes == '': ram_primes = r'\textrm{None}' data['phrase'] = group_phrase(n, t) zk = nf.zk() Ra = PolynomialRing(QQ, 'a') zk = [latex(Ra(x)) for x in zk] zk = ['$%s$' % x for x in zk] zk = ', '.join(zk) grh_label = '<small>(<a title="assuming GRH" knowl="nf.assuming_grh">assuming GRH</a>)</small>' if nf.used_grh( ) else '' # Short version for properties grh_lab = nf.short_grh_string() if 'Not' in str(data['class_number']): grh_lab = '' grh_label = '' pretty_label = field_pretty(label) if label != pretty_label: pretty_label = "%s: %s" % (label, pretty_label) info.update(data) if nf.degree() > 1: gpK = nf.gpK() rootof1coeff = gpK.nfrootsof1() rootofunityorder = int(rootof1coeff[1]) rootof1coeff = rootof1coeff[2] rootofunity = web_latex( Ra( str(pari("lift(%s)" % gpK.nfbasistoalg(rootof1coeff))).replace( 'x', 'a'))) rootofunity += ' (order $%d$)' % rootofunityorder else: rootofunity = web_latex(Ra('-1')) + ' (order $2$)' info.update({ 'label': pretty_label, 'label_raw': label, 'polynomial': web_latex_split_on_pm(nf.poly()), 'ram_primes': ram_primes, 'integral_basis': zk, 'regulator': web_latex(nf.regulator()), 'unit_rank': nf.unit_rank(), 'root_of_unity': rootofunity, 'fund_units': nf.units(), 'grh_label': grh_label, 'loc_alg': loc_alg }) bread.append(('%s' % info['label_raw'], ' ')) info['downloads_visible'] = True info['downloads'] = [('worksheet', '/')] info['friends'] = [] if nf.can_class_number(): # hide ones that take a lond time to compute on the fly # note that the first degree 4 number field missed the zero of the zeta function if abs(D**n) < 50000000: info['friends'].append(('L-function', "/L/NumberField/%s" % label)) info['friends'].append(('Galois group', "/GaloisGroup/%dT%d" % (n, t))) if 'dirichlet_group' in info: info['friends'].append(('Dirichlet character group', url_for("characters.dirichlet_group_table", modulus=int(conductor), char_number_list=','.join( [str(a) for a in dirichlet_chars]), poly=info['polynomial']))) resinfo = [] galois_closure = nf.galois_closure() if galois_closure[0] > 0: if len(galois_closure[1]) > 0: resinfo.append(('gc', galois_closure[1])) if len(galois_closure[2]) > 0: info['friends'].append(('Galois closure', url_for(".by_label", label=galois_closure[2][0]))) else: resinfo.append(('gc', [dnc])) sextic_twins = nf.sextic_twin() if sextic_twins[0] > 0: if len(sextic_twins[1]) > 0: resinfo.append(('sex', r' $\times$ '.join(sextic_twins[1]))) else: resinfo.append(('sex', dnc)) siblings = nf.siblings() # [degsib list, label list] # first is list of [deg, num expected, list of knowls] if len(siblings[0]) > 0: for sibdeg in siblings[0]: if len(sibdeg[2]) == 0: sibdeg[2] = dnc else: sibdeg[2] = ', '.join(sibdeg[2]) if len(sibdeg[2]) < sibdeg[1]: sibdeg[2] += ', some ' + dnc resinfo.append(('sib', siblings[0])) for lab in siblings[1]: if lab != '': labparts = lab.split('.') info['friends'].append(("Degree %s sibling" % labparts[0], url_for(".by_label", label=lab))) arith_equiv = nf.arith_equiv() if arith_equiv[0] > 0: if len(arith_equiv[1]) > 0: resinfo.append( ('ae', ', '.join(arith_equiv[1]), len(arith_equiv[1]))) for aelab in arith_equiv[2]: info['friends'].append(('Arithmetically equivalent sibling', url_for(".by_label", label=aelab))) else: resinfo.append(('ae', dnc, len(arith_equiv[1]))) info['resinfo'] = resinfo learnmore = learnmore_list() #if info['signature'] == [0,1]: # info['learnmore'].append(('Quadratic imaginary class groups', url_for(".render_class_group_data"))) # With Galois group labels, probably not needed here # info['learnmore'] = [('Global number field labels', # url_for(".render_labels_page")), ('Galois group # labels',url_for(".render_groups_page")), # (Completename,url_for(".render_discriminants_page"))] title = "Global Number Field %s" % info['label'] if npr == 1: primes = 'prime' else: primes = 'primes' properties2 = [('Label', label), ('Degree', '$%s$' % data['degree']), ('Signature', '$%s$' % data['signature']), ('Discriminant', '$%s$' % data['disc_factor']), ('Ramified ' + primes + '', '$%s$' % ram_primes), ('Class number', '%s %s' % (data['class_number'], grh_lab)), ('Class group', '%s %s' % (data['class_group_invs'], grh_lab)), ('Galois Group', group_display_short(data['degree'], t))] downloads = [] for lang in [["Magma", "magma"], ["SageMath", "sage"], ["Pari/GP", "gp"]]: downloads.append(('Download {} code'.format(lang[0]), url_for(".nf_code_download", nf=label, download_type=lang[1]))) from lmfdb.artin_representations.math_classes import NumberFieldGaloisGroup try: info["tim_number_field"] = NumberFieldGaloisGroup(nf._data['coeffs']) v = nf.factor_perm_repn(info["tim_number_field"]) def dopow(m): if m == 0: return '' if m == 1: return '*' return '*<sup>%d</sup>' % m info["mydecomp"] = [dopow(x) for x in v] except AttributeError: pass return render_template("number_field.html", properties2=properties2, credit=NF_credit, title=title, bread=bread, code=nf.code, friends=info.pop('friends'), downloads=downloads, learnmore=learnmore, info=info)
def Newforms_v2(N, k, chi_number, dmax=20, nan=100, Detail=0): t0 = time.time() G = pari(N).znstar(1) chi_dc = char_orbit_index_to_DC_number(N, chi_number) chi_gp = G.znconreylog(chi_dc) chi_order = ZZ(G.charorder(chi_gp)) if Detail: print("Decomposing space {}:{}:{}".format(N, k, chi_number)) NK = [N, k, [G, chi_gp]] pNK = pari(NK) if Detail > 1: print("NK = {} (gp character = {})".format(NK, chi_gp)) SturmBound = pNK.mfsturm() Snew = pNK.mfinit(0) total_dim = Snew.mfdim( ) # this is the relative dimension i.e. degree over Q(chi) # Get the character polynomial # Note that if the character order is 2*m with m odd then Pari uses the # m'th cyclotomic polynomial and not the 2m'th (e.g. for a # character of order 6 it uses t^2+t+1 and not t^2-t+1). chi_order_2 = chi_order // 2 if chi_order % 4 == 2 else chi_order chipoly = cyclotomic_polynomial(chi_order_2, 't') chi_degree = chipoly.degree() assert chi_degree == euler_phi(chi_order) == euler_phi(chi_order_2) t05 = time.time() if Detail: print( "Computed newspace {}:{}:{} in {:0.3f}, dimension={}*{}={}, now splitting into irreducible subspaces" .format(N, k, chi_number, t05 - t0, chi_degree, total_dim, chi_degree * total_dim)) if Detail > 1: print("Sturm bound = {}".format(SturmBound)) print("character order = {}".format(chi_order)) if total_dim == 0: if Detail: print("The space {}:{}:{} is empty".format(N, k, chi_number)) return [] # First just compute Hecke matrices one at a time, to find a splitting operator def Hecke_op_iter(): p = ZZ(1) while True: p = p.next_prime() # while p.divides(N): # p=p.next_prime() #print("Computing T_{}".format(p)) yield p, Snew.mfheckemat(p) Tp_iter = Hecke_op_iter() p, op = Tp_iter.next() s1 = time.time() if Detail: print("testing T_{}".format(p)) ok = is_semisimple_modular(op, chi_order_2) # f = op.charpoly() # ok = f.issquarefree() if ok: if Detail: print("Lucky first time: semisimple. Finding char poly") f = op.charpoly() ops = [(p, op)] while not ok: pi, opi = Tp_iter.next() if Detail: print("testing T_{}".format(pi)) ok = is_semisimple_modular(op, chi_order_2) # f = opi.charpoly() # ok = f.issquarefree() if ok: if Detail: print("success using T_{}. Finding char poly".format(pi)) op = opi f = op.charpoly() break else: #ops.append((pi,opi)) ops += [(pi, opi)] if Detail: print("T_{} not semisimple".format(pi)) print("testing combinations...") for j in range(5): co = [ZZ.random_element(-5, 5) for _ in ops] while not co: co = [ZZ.random_element(-5, 5) for _ in ops] if Detail: print("Testing lin comb of {} ops with coeffs {}".format( len(co), co)) op = sum([ci * opj[1] for ci, opj in zip(co, ops)]) ok = is_semisimple_modular(op, chi_order_2) # f=op.charpoly() # ok = f.issquarefree() if ok: if Detail: print( "success using {}-combo of T_p for p in {}. Finding char poly" .format(co, [opj[0] for opj in ops])) f = op.charpoly() break if not ok: raise RuntimeError( "failed to find a 0,1-combination of Tp which is semisimple") ffac = f.factor() nnf = ffac.matsize()[0] gp_pols = pari_col1(ffac) pols = [pol for pol in gp_pols] reldims = [pol.poldegree() for pol in pols] dims = [d * chi_degree for d in reldims] # We'll need the coefficients an, if any newforms have dimension >1 and <=dmax. an_needed = [ i for i, d in enumerate(dims) if d > 1 and (dmax == 0 or d <= dmax) ] if Detail: print("Need to compute a_n for {} newforms: {}".format( len(an_needed), an_needed)) s2 = time.time() if Detail: print("Computed splitting in {:0.3f}, # newforms = {}".format( s2 - s1, nnf)) print("relative dims = {}, absolute dims = {}".format(reldims, dims)) # Compute AL-matrices if character is trivial: if chi_order == 1: Qlist = [(pr, pr**e) for pr, e in ZZ(N).factor()] ALs = [Snew.mfatkininit(Q[1])[1] for Q in Qlist] if Detail: print("AL-matrices:") for Q, AL in zip(Qlist, ALs): print("W_{}={}".format(Q[1], AL)) if nnf == 1 and dims[0] > dmax and dmax > 0: if Detail: print( "Only one newform and dim={}, so use traceform to get traces". format(dims[0])) traces = pNK.mftraceform().mfcoefs(nan) if Detail > 1: print("raw traces: {}".format(traces)) if chi_degree > 1: # This is faster than the more simple # traces = [c.trace() for c in traces] gptrace = pari_trace(chi_degree) traces = pari.apply(gptrace, traces) if Detail > 1: print("traces to QQ: {}".format(traces)) traces = gen_to_sage(traces)[1:] traces[0] = dims[0] if Detail > 1: print("final traces: {}".format(traces)) traces = [traces] else: # >1 newform, or just one but its absolute dim is <=dmax hs = [f / fi for fi in pols] if Detail > 1: print("fs: {}".format(pols)) print("hs: {}".format(hs)) print(" with degrees {}".format([h.poldegree() for h in hs])) if Detail > 1: print("Starting to compute gcds") As = [(hi * (fi.gcdext(hi)[2])).subst(pari_x, op) for fi, hi in zip(pols, hs)] if Detail: print("Computed idempotent matrix decomposition") ims = [A.matimage() for A in As] U = pari.matconcat(ims) Uinv = U**(-1) if Detail: print("Computed U and U^-1") starts = [1 + sum(d for d in reldims[:i]) for i in range(len(reldims))] stops = [sum(d for d in reldims[:i + 1]) for i in range(len(reldims))] slicers = [pari_row_slice(r1, r2) for r1, r2 in zip(starts, stops)] ums = [slice(Uinv) for slice in slicers] imums = [imA * umA for imA, umA in zip(ims, ums)] s3 = time.time() if Detail: print("Computed projectors in {:0.3f}".format(s3 - s2)) print("Starting to compute {} Hecke matrices T_n".format(nan)) heckemats = Snew.mfheckemat(pari(range(1, nan + 1))) s4 = time.time() if Detail: print("Computed {} Hecke matrices in {:0.3f}s".format( nan, s4 - s3)) # If we are going to compute any a_n then we now compute # umA*T*imA for all Hecke matrices T, whose traces give the # traces and whose first columns (or any row or column) give # the coefficients of the a_n with respect to some # Q(chi)-basis for the Hecke field. # But if we only need the traces then it is faster to # precompute imA*umA=imAumA and then the traces are # trace(imAumA*T). NB trace(UMV)=trace(VUM)! if Detail: print("Computing traces") # Note that computing the trace of a matrix product is faster # than first computing the product and then the trace: gptrace = pari( 'c->if(type(c)=="t_POLMOD",trace(c),c*{})'.format(chi_degree)) traces = [[ gen_to_sage(gptrace(pari_trace_product(T, imum))) for T in heckemats ] for imum in imums] s4 = time.time() if Detail: print("Computed traces to Z in {:0.3f}".format(s4 - s3)) for tr in traces: print(tr[:20]) ans = [None for _ in range(nnf)] bases = [None for _ in range(nnf)] if an_needed: if Detail: print("...computing a_n...") for i in an_needed: dr = reldims[i] if Detail: print("newform #{}/{}, relative dimension {}".format( i, nnf, dr)) # method: for each irreducible component we have matrices # um and im (sizes dr x n and n x dr where n is the # relative dimension of the whole space) such that for # each Hecke matrix T, its restriction to the component is # um*T*im. To get the eigenvalue in a suitable basis all # we need do is take any one column (or row): we choose # the first column. So the computation can be done as # um*(T*im[,1]) (NB the placing of parentheses). imsicol1 = pari_col1(ims[i]) umsi = ums[i] ans[i] = [(umsi * (T * imsicol1)).Vec() for T in heckemats] if Detail: print("ans done") if Detail > 1: print("an: {}...".format(ans[i])) # Now compute the bases (of the relative Hecke field over # Q(chi) w.r.t which these coefficients are given. Here # we use e1 because we picked the first column just now. B = ums[i] * op * ims[i] e1 = pari_e1(dr) cols = [e1] while len(cols) < dr: cols.append(B * cols[-1]) W = pari.matconcat(cols) bases[i] = W.mattranspose()**(-1) if Detail > 1: print("basis = {}".format(bases[i].lift())) # Compute AL-eigenvalues if character is trivial: if chi_order == 1: ALeigs = [[[Q[0], gen_to_sage((umA * (AL * (pari_col1(imA))))[0])] for Q, AL in zip(Qlist, ALs)] for umA, imA in zip(ums, ims)] if Detail > 1: print("ALeigs: {}".format(ALeigs)) else: ALeigs = [[] for _ in range(nnf)] Nko = (N, k, chi_number) #print("len(traces) = {}".format(len(traces))) #print("len(newforms) = {}".format(len(newforms))) #print("len(pols) = {}".format(len(pols))) #print("len(ans) = {}".format(len(ans))) #print("len(ALeigs) = {}".format(len(ALeigs))) pari_nfs = [{ 'Nko': Nko, 'SB': SturmBound, 'chipoly': chipoly, 'poly': pols[i], 'ans': ans[i], 'basis': bases[i], 'ALeigs': ALeigs[i], 'traces': traces[i], } for i in range(nnf)] # We could return these as they are but the next processing step # will fail if the underlying gp process has quit, so we do the # processing here. # This processing returns full data but the polynomials have not # yet been polredbested and the an coefficients have not been # optimized (or even made integral): #return pari_nfs t1 = time.time() if Detail: print("{}: finished constructing pari newforms (time {:0.3f})".format( Nko, t1 - t0)) nfs = [process_pari_nf(nf, dmax, Detail) for nf in pari_nfs] if len(nfs) > 1: nfs.sort(key=lambda f: f['traces']) t2 = time.time() if Detail: print( "{}: finished first processing of newforms (time {:0.3f})".format( Nko, t2 - t1)) if Detail > 2: for nf in nfs: if 'eigdata' in nf: print(nf['eigdata']['ancs']) nfs = [bestify_newform(nf, dmax, Detail) for nf in nfs] t3 = time.time() if Detail: print("{}: finished bestifying newforms (time {:0.3f})".format( Nko, t3 - t2)) if Detail > 2: for nf in nfs: if 'eigdata' in nf: print(nf['eigdata']['ancs']) nfs = [integralify_newform(nf, dmax, Detail) for nf in nfs] t4 = time.time() if Detail: print("{}: finished integralifying newforms (time {:0.3f})".format( Nko, t4 - t3)) if Detail > 2: for nf in nfs: if 'eigdata' in nf: print(nf['eigdata']['ancs']) print("Total time for space {}: {:0.3f}".format(Nko, t4 - t0)) return nfs
def render_field_webpage(args): data = None C = base.getDBConnection() info = {} bread = [("Global Number Fields", url_for(".number_field_render_webpage"))] if "label" in args: label = clean_input(args["label"]) nf = WebNumberField(label) data = {} if nf.is_null(): bread.append(("Search results", " ")) label2 = re.sub(r"[<>]", "", args["label"]) if "You need to enter a field" in label2: info["err"] = label2 else: info["err"] = "No such field: %s in the database" % label2 info["label"] = args["label_orig"] if "label_orig" in args else args["label"] return search_input_error(info, bread) info["wnf"] = nf data["degree"] = nf.degree() data["class_number"] = nf.class_number() t = nf.galois_t() n = nf.degree() data["is_galois"] = nf.is_galois() data["is_abelian"] = nf.is_abelian() if nf.is_abelian(): conductor = nf.conductor() data["conductor"] = conductor dirichlet_chars = nf.dirichlet_group() if len(dirichlet_chars) > 0: data["dirichlet_group"] = [ '<a href = "%s">$\chi_{%s}(%s,·)$</a>' % (url_character(type="Dirichlet", modulus=data["conductor"], number=j), data["conductor"], j) for j in dirichlet_chars ] data["dirichlet_group"] = r"$\lbrace$" + ", ".join(data["dirichlet_group"]) + r"$\rbrace$" if data["conductor"].is_prime() or data["conductor"] == 1: data["conductor"] = "\(%s\)" % str(data["conductor"]) else: data["conductor"] = "\(%s=%s\)" % (str(data["conductor"]), latex(data["conductor"].factor())) data["galois_group"] = group_display_knowl(n, t, C) data["cclasses"] = cclasses_display_knowl(n, t, C) data["character_table"] = character_table_display_knowl(n, t, C) data["class_group"] = nf.class_group() data["class_group_invs"] = nf.class_group_invariants() data["signature"] = nf.signature() data["coefficients"] = nf.coeffs() D = nf.disc() ram_primes = D.prime_factors() data["disc_factor"] = nf.disc_factored_latex() if D.abs().is_prime() or D == 1: data["discriminant"] = "\(%s\)" % str(D) else: data["discriminant"] = "\(%s=%s\)" % (str(D), data["disc_factor"]) npr = len(ram_primes) ram_primes = str(ram_primes)[1:-1] if ram_primes == "": ram_primes = r"\textrm{None}" data["frob_data"], data["seeram"] = frobs(nf.K()) data["phrase"] = group_phrase(n, t, C) zk = pari(nf.K()).nf_subst("a") zk = list(zk.nf_get_zk()) Ra = PolynomialRing(QQ, "a") zk = [latex(Ra(x)) for x in zk] zk = ["$%s$" % x for x in zk] zk = ", ".join(zk) grh_label = ( '<small>(<a title="assuming GRH" knowl="nf.assuming_grh">assuming GRH</a>)</small>' if nf.used_grh() else "" ) # Short version for properties grh_lab = nf.short_grh_string() pretty_label = field_pretty(label) if label != pretty_label: pretty_label = "%s: %s" % (label, pretty_label) info.update(data) info.update( { "label": pretty_label, "label_raw": label, "polynomial": web_latex_split_on_pm(nf.K().defining_polynomial()), "ram_primes": ram_primes, "integral_basis": zk, "regulator": web_latex(nf.regulator()), "unit_rank": nf.unit_rank(), "root_of_unity": web_latex(nf.K().primitive_root_of_unity()), "fund_units": nf.units(), "grh_label": grh_label, } ) bread.append(("%s" % info["label_raw"], " ")) info["downloads_visible"] = True info["downloads"] = [("worksheet", "/")] info["friends"] = [] if nf.can_class_number(): info["friends"].append(("L-function", "/L/NumberField/%s" % label)) info["friends"].append(("Galois group", "/GaloisGroup/%dT%d" % (n, t))) if "dirichlet_group" in info: info["friends"].append( ( "Dirichlet group", url_for( "characters.dirichlet_group_table", modulus=int(conductor), char_number_list=",".join([str(a) for a in dirichlet_chars]), poly=info["polynomial"], ), ) ) info["learnmore"] = [ ("Global number field labels", url_for(".render_labels_page")), (Completename, url_for(".render_discriminants_page")), ] # With Galois group labels, probably not needed here # info['learnmore'] = [('Global number field labels', # url_for(".render_labels_page")), ('Galois group # labels',url_for(".render_groups_page")), # (Completename,url_for(".render_discriminants_page"))] title = "Global Number Field %s" % info["label"] if npr == 1: primes = "prime" else: primes = "primes" properties2 = [ ("Degree:", "%s" % data["degree"]), ("Signature:", "$%s$" % data["signature"]), ("Discriminant:", "$%s$" % data["disc_factor"]), ("Ramified " + primes + ":", "$%s$" % ram_primes), ("Class number:", "%s %s" % (data["class_number"], grh_lab)), ("Class group:", "%s %s" % (data["class_group_invs"], grh_lab)), ("Galois Group:", group_display_short(data["degree"], t, C)), ] from lmfdb.math_classes import NumberFieldGaloisGroup try: info["tim_number_field"] = NumberFieldGaloisGroup.find_one({"label": label}) v = nf.factor_perm_repn(info["tim_number_field"]) info["mydecomp"] = ["*" if x > 0 else "" for x in v] except AttributeError: pass # del info['_id'] return render_template( "number_field.html", properties2=properties2, credit=NF_credit, title=title, bread=bread, friends=info.pop("friends"), learnmore=info.pop("learnmore"), info=info, )
def pari_trace(d): return pari('c->if(type(c)=="t_POLMOD",trace(c),c*{})'.format(d))
def render_field_webpage(args): data = None info = {} bread = [('Global Number Fields', url_for(".number_field_render_webpage"))] # This function should not be called unless label is set. label = clean_input(args['label']) nf = WebNumberField(label) data = {} if nf.is_null(): bread.append(('Search Results', ' ')) info['err'] = 'There is no field with label %s in the database' % label info['label'] = args['label_orig'] if 'label_orig' in args else args['label'] return search_input_error(info, bread) info['wnf'] = nf data['degree'] = nf.degree() data['class_number'] = nf.class_number_latex() ram_primes = nf.ramified_primes() t = nf.galois_t() n = nf.degree() data['is_galois'] = nf.is_galois() data['is_abelian'] = nf.is_abelian() if nf.is_abelian(): conductor = nf.conductor() data['conductor'] = conductor dirichlet_chars = nf.dirichlet_group() if len(dirichlet_chars)>0: data['dirichlet_group'] = ['<a href = "%s">$\chi_{%s}(%s,·)$</a>' % (url_for('characters.render_Dirichletwebpage',modulus=data['conductor'], number=j), data['conductor'], j) for j in dirichlet_chars] data['dirichlet_group'] = r'$\lbrace$' + ', '.join(data['dirichlet_group']) + r'$\rbrace$' if data['conductor'].is_prime() or data['conductor'] == 1: data['conductor'] = "\(%s\)" % str(data['conductor']) else: factored_conductor = factor_base_factor(data['conductor'], ram_primes) factored_conductor = factor_base_factorization_latex(factored_conductor) data['conductor'] = "\(%s=%s\)" % (str(data['conductor']), factored_conductor) data['galois_group'] = group_display_knowl(n, t) data['cclasses'] = cclasses_display_knowl(n, t) data['character_table'] = character_table_display_knowl(n, t) data['class_group'] = nf.class_group() data['class_group_invs'] = nf.class_group_invariants() data['signature'] = nf.signature() data['coefficients'] = nf.coeffs() nf.make_code_snippets() D = nf.disc() data['disc_factor'] = nf.disc_factored_latex() if D.abs().is_prime() or D == 1: data['discriminant'] = "\(%s\)" % str(D) else: data['discriminant'] = "\(%s=%s\)" % (str(D), data['disc_factor']) data['frob_data'], data['seeram'] = frobs(nf) # Bad prime information npr = len(ram_primes) ramified_algebras_data = nf.ramified_algebras_data() if isinstance(ramified_algebras_data,str): loc_alg = '' else: # [label, latex, e, f, c, gal] loc_alg = '' for j in range(npr): if ramified_algebras_data[j] is None: loc_alg += '<tr><td>%s<td colspan="7">Data not computed'%str(ram_primes[j]) else: mydat = ramified_algebras_data[j] p = ram_primes[j] loc_alg += '<tr><td rowspan="%d">$%s$</td>'%(len(mydat),str(p)) mm = mydat[0] myurl = url_for('local_fields.by_label', label=mm[0]) lab = mm[0] if mm[3]*mm[2]==1: lab = r'$\Q_{%s}$'%str(p) loc_alg += '<td><a href="%s">%s</a><td>$%s$<td>$%d$<td>$%d$<td>$%d$<td>%s<td>$%s$'%(myurl,lab,mm[1],mm[2],mm[3],mm[4],mm[5],show_slope_content(mm[8],mm[6],mm[7])) for mm in mydat[1:]: lab = mm[0] if mm[3]*mm[2]==1: lab = r'$\Q_{%s}$'%str(p) loc_alg += '<tr><td><a href="%s">%s</a><td>$%s$<td>$%d$<td>$%d$<td>$%d$<td>%s<td>$%s$'%(myurl,lab,mm[1],mm[2],mm[3],mm[4],mm[5],show_slope_content(mm[8],mm[6],mm[7])) loc_alg += '</tbody></table>' ram_primes = str(ram_primes)[1:-1] if ram_primes == '': ram_primes = r'\textrm{None}' data['phrase'] = group_phrase(n, t) zk = nf.zk() Ra = PolynomialRing(QQ, 'a') zk = [latex(Ra(x)) for x in zk] zk = ['$%s$' % x for x in zk] zk = ', '.join(zk) grh_label = '<small>(<a title="assuming GRH" knowl="nf.assuming_grh">assuming GRH</a>)</small>' if nf.used_grh() else '' # Short version for properties grh_lab = nf.short_grh_string() if 'Not' in str(data['class_number']): grh_lab='' grh_label='' pretty_label = field_pretty(label) if label != pretty_label: pretty_label = "%s: %s" % (label, pretty_label) info.update(data) if nf.degree() > 1: gpK = nf.gpK() rootof1coeff = gpK.nfrootsof1() rootofunityorder = int(rootof1coeff[1]) rootof1coeff = rootof1coeff[2] rootofunity = web_latex(Ra(str(pari("lift(%s)" % gpK.nfbasistoalg(rootof1coeff))).replace('x','a'))) rootofunity += ' (order $%d$)' % rootofunityorder else: rootofunity = web_latex(Ra('-1'))+ ' (order $2$)' info.update({ 'label': pretty_label, 'label_raw': label, 'polynomial': web_latex_split_on_pm(nf.poly()), 'ram_primes': ram_primes, 'integral_basis': zk, 'regulator': web_latex(nf.regulator()), 'unit_rank': nf.unit_rank(), 'root_of_unity': rootofunity, 'fund_units': nf.units(), 'grh_label': grh_label, 'loc_alg': loc_alg }) bread.append(('%s' % info['label_raw'], ' ')) info['downloads_visible'] = True info['downloads'] = [('worksheet', '/')] info['friends'] = [] if nf.can_class_number(): # hide ones that take a lond time to compute on the fly # note that the first degree 4 number field missed the zero of the zeta function if abs(D**n) < 50000000: info['friends'].append(('L-function', "/L/NumberField/%s" % label)) info['friends'].append(('Galois group', "/GaloisGroup/%dT%d" % (n, t))) if 'dirichlet_group' in info: info['friends'].append(('Dirichlet character group', url_for("characters.dirichlet_group_table", modulus=int(conductor), char_number_list=','.join( [str(a) for a in dirichlet_chars]), poly=info['polynomial']))) resinfo=[] galois_closure = nf.galois_closure() if galois_closure[0]>0: if len(galois_closure[1])>0: resinfo.append(('gc', galois_closure[1])) if len(galois_closure[2]) > 0: info['friends'].append(('Galois closure',url_for(".by_label", label=galois_closure[2][0]))) else: resinfo.append(('gc', [dnc])) sextic_twins = nf.sextic_twin() if sextic_twins[0]>0: if len(sextic_twins[1])>0: resinfo.append(('sex', r' $\times$ '.join(sextic_twins[1]))) else: resinfo.append(('sex', dnc)) siblings = nf.siblings() # [degsib list, label list] # first is list of [deg, num expected, list of knowls] if len(siblings[0])>0: for sibdeg in siblings[0]: if len(sibdeg[2]) ==0: sibdeg[2] = dnc else: sibdeg[2] = ', '.join(sibdeg[2]) if len(sibdeg[2])<sibdeg[1]: sibdeg[2] += ', some '+dnc resinfo.append(('sib', siblings[0])) for lab in siblings[1]: if lab != '': labparts = lab.split('.') info['friends'].append(("Degree %s sibling"%labparts[0] ,url_for(".by_label", label=lab))) arith_equiv = nf.arith_equiv() if arith_equiv[0]>0: if len(arith_equiv[1])>0: resinfo.append(('ae', ', '.join(arith_equiv[1]), len(arith_equiv[1]))) for aelab in arith_equiv[2]: info['friends'].append(('Arithmetically equivalent sibling',url_for(".by_label", label=aelab))) else: resinfo.append(('ae', dnc, len(arith_equiv[1]))) info['resinfo'] = resinfo learnmore = learnmore_list() #if info['signature'] == [0,1]: # info['learnmore'].append(('Quadratic imaginary class groups', url_for(".render_class_group_data"))) # With Galois group labels, probably not needed here # info['learnmore'] = [('Global number field labels', # url_for(".render_labels_page")), ('Galois group # labels',url_for(".render_groups_page")), # (Completename,url_for(".render_discriminants_page"))] title = "Global Number Field %s" % info['label'] if npr == 1: primes = 'prime' else: primes = 'primes' properties2 = [('Label', label), ('Degree', '$%s$' % data['degree']), ('Signature', '$%s$' % data['signature']), ('Discriminant', '$%s$' % data['disc_factor']), ('Ramified ' + primes + '', '$%s$' % ram_primes), ('Class number', '%s %s' % (data['class_number'], grh_lab)), ('Class group', '%s %s' % (data['class_group_invs'], grh_lab)), ('Galois Group', group_display_short(data['degree'], t)) ] downloads = [] for lang in [["Magma","magma"], ["SageMath","sage"], ["Pari/GP", "gp"]]: downloads.append(('Download {} code'.format(lang[0]), url_for(".nf_code_download", nf=label, download_type=lang[1]))) from lmfdb.artin_representations.math_classes import NumberFieldGaloisGroup try: info["tim_number_field"] = NumberFieldGaloisGroup(nf._data['coeffs']) v = nf.factor_perm_repn(info["tim_number_field"]) def dopow(m): if m==0: return '' if m==1: return '*' return '*<sup>%d</sup>'% m info["mydecomp"] = [dopow(x) for x in v] except AttributeError: pass return render_template("number_field.html", properties2=properties2, credit=NF_credit, title=title, bread=bread, code=nf.code, friends=info.pop('friends'), downloads=downloads, learnmore=learnmore, info=info)
def h(d, prec=53): RF = RealField(prec) kappa = lambda d: RF(1) / 3 if d == 3 else (RF(1) / 2 if d == 4 else 1) return RF(pari("qfbclassno(%s,1)" % (-d))) * kappa(d)
def pari_row_slice(r1, r2): return pari("M -> M[{}..{},]".format(r1, r2))
def has_modular_unit_of_degree(G,deg,rational = True, verbose = False,qfminim_bound = 10**5,l2_step=0): """ Returns True,v if the modular curve X(G) has a modular unit v of degree equal to deg, and false,None otherwise. INPUT: - ``G`` - a congruence subgroup - ``deg`` - int, the degree of modular unit to search for - ``rational`` - bool, true means modular unit should be defined over QQ - ``verbose`` - bool (default = false), wether or not to print progress - ``qfminim_bound`` - int (default - 10^5), given to pari's qfminim command, and is an upper bound on how many vectors of short l2 norm are returned by pari this function will raise an error if pari finds more short vectors then it returns - ``l2_step`` - int (default = 0) If l2_step>0 this function first searches the modular units with l2 norm equal to l2_step then 2*l2_step, 3*l2_step, e.t.c. instead of searching all vectors with l2 norm 2*deg^2. The l2 norm of a modular unit with divisor n1*c1 + ... + nk*ck is the l2 norm of (n1,...nk). """ if rational: L,D=rational_modular_unit_lattice(G) else: L,D=modular_unit_lattice(G) M = L.basis_matrix().change_ring(ZZ).LLL() for v in M: if v.norm(1)/2 == deg: return True,L(v) GS_matrix=M*M.transpose() pari_gs=pari(GS_matrix) #just to speed up positive results if l2_step > 0: for l2 in range(l2_step,deg**2*2-l2_step+1,l2_step): short_vectors=pari_gs.qfminim(l2,qfminim_bound) if verbose: print short_vectors[:2] count = 0 for i in short_vectors[2]: count+=1 if verbose and count%10000==0: print count v=vector(QQ,i.list())*M if v.norm(1)/2 == deg: return True,L(v) short_vectors=pari_gs.qfminim(deg**2*2,qfminim_bound) if verbose: print short_vectors[:2] count = 0 for i in short_vectors[2]: count+=1 if verbose and count%10000==0: print count v=vector(QQ,i.list())*M if v.norm(1)/2 == deg: return True,L(v) assert short_vectors[0].sage() < 2*qfminim_bound return False,None
def render_field_webpage(args): data = None C = base.getDBConnection() info = {} bread = [('Global Number Fields', url_for(".number_field_render_webpage"))] # This function should not be called unless label is set. label = clean_input(args['label']) nf = WebNumberField(label) data = {} if nf.is_null(): bread.append(('Search results', ' ')) info['err'] = 'There is no field with label %s in the database' % label info['label'] = args['label_orig'] if 'label_orig' in args else args['label'] return search_input_error(info, bread) info['wnf'] = nf data['degree'] = nf.degree() data['class_number'] = nf.class_number() t = nf.galois_t() n = nf.degree() data['is_galois'] = nf.is_galois() data['is_abelian'] = nf.is_abelian() if nf.is_abelian(): conductor = nf.conductor() data['conductor'] = conductor dirichlet_chars = nf.dirichlet_group() if len(dirichlet_chars)>0: data['dirichlet_group'] = ['<a href = "%s">$\chi_{%s}(%s,·)$</a>' % (url_for('characters.render_Dirichletwebpage',modulus=data['conductor'], number=j), data['conductor'], j) for j in dirichlet_chars] data['dirichlet_group'] = r'$\lbrace$' + ', '.join(data['dirichlet_group']) + r'$\rbrace$' if data['conductor'].is_prime() or data['conductor'] == 1: data['conductor'] = "\(%s\)" % str(data['conductor']) else: data['conductor'] = "\(%s=%s\)" % (str(data['conductor']), latex(data['conductor'].factor())) data['galois_group'] = group_display_knowl(n, t, C) data['cclasses'] = cclasses_display_knowl(n, t, C) data['character_table'] = character_table_display_knowl(n, t, C) data['class_group'] = nf.class_group() data['class_group_invs'] = nf.class_group_invariants() data['signature'] = nf.signature() data['coefficients'] = nf.coeffs() nf.make_code_snippets() D = nf.disc() ram_primes = D.prime_factors() data['disc_factor'] = nf.disc_factored_latex() if D.abs().is_prime() or D == 1: data['discriminant'] = "\(%s\)" % str(D) else: data['discriminant'] = "\(%s=%s\)" % (str(D), data['disc_factor']) npr = len(ram_primes) ram_primes = str(ram_primes)[1:-1] if ram_primes == '': ram_primes = r'\textrm{None}' data['frob_data'], data['seeram'] = frobs(nf) data['phrase'] = group_phrase(n, t, C) zk = nf.zk() Ra = PolynomialRing(QQ, 'a') zk = [latex(Ra(x)) for x in zk] zk = ['$%s$' % x for x in zk] zk = ', '.join(zk) grh_label = '<small>(<a title="assuming GRH" knowl="nf.assuming_grh">assuming GRH</a>)</small>' if nf.used_grh() else '' # Short version for properties grh_lab = nf.short_grh_string() if 'Not' in str(data['class_number']): grh_lab='' grh_label='' pretty_label = field_pretty(label) if label != pretty_label: pretty_label = "%s: %s" % (label, pretty_label) info.update(data) if nf.degree() > 1: gpK = nf.gpK() rootof1coeff = gpK.nfrootsof1()[2] rootofunity = Ra(str(pari("lift(%s)" % gpK.nfbasistoalg(rootof1coeff))).replace('x','a')) else: rootofunity = Ra('-1') info.update({ 'label': pretty_label, 'label_raw': label, 'polynomial': web_latex_split_on_pm(nf.poly()), 'ram_primes': ram_primes, 'integral_basis': zk, 'regulator': web_latex(nf.regulator()), 'unit_rank': nf.unit_rank(), 'root_of_unity': web_latex(rootofunity), 'fund_units': nf.units(), 'grh_label': grh_label }) bread.append(('%s' % info['label_raw'], ' ')) info['downloads_visible'] = True info['downloads'] = [('worksheet', '/')] info['friends'] = [] if nf.can_class_number(): # hide ones that take a lond time to compute on the fly # note that the first degree 4 number field missed the zero of the zeta function if abs(D**n) < 50000000: info['friends'].append(('L-function', "/L/NumberField/%s" % label)) info['friends'].append(('Galois group', "/GaloisGroup/%dT%d" % (n, t))) if 'dirichlet_group' in info: info['friends'].append(('Dirichlet group', url_for("characters.dirichlet_group_table", modulus=int(conductor), char_number_list=','.join( [str(a) for a in dirichlet_chars]), poly=info['polynomial']))) info['learnmore'] = [('Global number field labels', url_for( ".render_labels_page")), (Completename, url_for(".render_discriminants_page")), ('How data was computed', url_for(".how_computed_page"))] if info['signature'] == [0,1]: info['learnmore'].append(('Quadratic imaginary class groups', url_for(".render_class_group_data"))) # With Galois group labels, probably not needed here # info['learnmore'] = [('Global number field labels', # url_for(".render_labels_page")), ('Galois group # labels',url_for(".render_groups_page")), # (Completename,url_for(".render_discriminants_page"))] title = "Global Number Field %s" % info['label'] if npr == 1: primes = 'prime' else: primes = 'primes' properties2 = [('Label', label), ('Degree', '%s' % data['degree']), ('Signature', '$%s$' % data['signature']), ('Discriminant', '$%s$' % data['disc_factor']), ('Ramified ' + primes + '', '$%s$' % ram_primes), ('Class number', '%s %s' % (data['class_number'], grh_lab)), ('Class group', '%s %s' % (data['class_group_invs'], grh_lab)), ('Galois Group', group_display_short(data['degree'], t, C)) ] from lmfdb.math_classes import NumberFieldGaloisGroup try: info["tim_number_field"] = NumberFieldGaloisGroup(nf._data['coeffs']) v = nf.factor_perm_repn(info["tim_number_field"]) def dopow(m): if m==0: return '' if m==1: return '*' return '*<sup>%d</sup>'% m info["mydecomp"] = [dopow(x) for x in v] except AttributeError: pass # del info['_id'] return render_template("number_field.html", properties2=properties2, credit=NF_credit, title=title, bread=bread, code=nf.code, friends=info.pop('friends'), learnmore=info.pop('learnmore'), info=info)
def conductor(self): bnr = self.parent().group().bnr() pari_cond = pari(bnr.bnrconductorofchar(self.list())) finite, arch = pari_cond return self.number_field().ideal(finite)
def enum_points(I): possibleValues = get_elements() R = I.ring() F = R.base() ch = F.characteristic() n = R.ngens() if n == 0: if I.is_zero(): yield [] return if I.is_one(): return if all(map(lambda _: _.degree() == 1, I.gens())) and (ch > 0 or I.dimension() == 0): # solve using linear algebra f = R.hom(n * [0], F) A = matrix([f(g.coefficient(xi)) for xi in R.gens()] for g in I.gens()) b = vector(-g.constant_coefficient() for g in I.gens()) v0 = A.solve_right(b) r = A.rank() if r == n: yield list(v0) else: K = A.right_kernel().matrix() for v in F**(n - r): yield list(v * K + v0) return if ch > 0 and I.is_homogeneous(): yield [F(0)] * n for pt in enum_proj_points(I): for sca in get_elements(): if sca != 0: yield [x * sca for x in pt] return elim = I.elimination_ideal(I.ring().gens()[1:]) g = elim.gens()[0] if g != 0: S = F['u'] pr1 = R.hom([S.gen()] + [0] * (n - 1), S) possibleValues = (v[0] for v in pr1(g).roots() if bound == None or global_height([v[0], F(1)]) <= bound + tolerance) if split: nonSplit = (f[0] for f in factor(pr1(g)) if f[0].degree() > 1) for f in nonSplit: if ch == 0: F_ = f.splitting_field('a') # `polredbest` from PARI/GP, improves performance significantly f = gen_to_sage( pari(F_.gen().minpoly('x')).polredbest(), {'x': S.gen()}) F_ = f.splitting_field('a') R_ = PolynomialRing(F_, 'x', n) I = R_.ideal( [f.change_ring(base_change(F, F_)) for f in I.gens()]) for pt in enum_points(I): yield pt return R_ = PolynomialRing(F, 'x', n - 1) if n == 1: for v in possibleValues: yield [v] else: for v in possibleValues: pr2 = R.hom([v] + list(R_.gens()), R_) for rest in enum_points(pr2(I)): yield [v] + rest
def pari_e1(d): return pari("{}~".format([int(j == 0) for j in range(d)]))
def polredabs(pol): return sagepol(pari(pol).polredabs()) if pol.base_ring()==QQ else pol
def render_field_webpage(args): data = None C = base.getDBConnection() info = {} bread = [('Global Number Fields', url_for(".number_field_render_webpage"))] if 'label' in args: label = clean_input(args['label']) nf = WebNumberField(label) data = {} if nf.is_null(): bread.append(('Search results', ' ')) label2 = re.sub(r'[<>]', '', args['label']) if 'You need to enter a field' in label2: info['err'] = label2 else: info['err'] = 'No such field: %s in the database' % label2 info['label'] = args['label_orig'] if 'label_orig' in args else args['label'] return search_input_error(info, bread) info['wnf'] = nf data['degree'] = nf.degree() data['class_number'] = nf.class_number() t = nf.galois_t() n = nf.degree() data['is_galois'] = nf.is_galois() data['is_abelian'] = nf.is_abelian() if nf.is_abelian(): conductor = nf.conductor() data['conductor'] = conductor dirichlet_chars = nf.dirichlet_group() data['dirichlet_group'] = ['<a href = "%s">$\chi_{%s}(%s,·)$</a>' % (url_for("render_Character", arg1=data['conductor'], arg2=j), data['conductor'], j) for j in dirichlet_chars] data['dirichlet_group'] = r'$\lbrace$' + ', '.join(data['dirichlet_group']) + r'$\rbrace$' if data['conductor'].is_prime() or data['conductor'] == 1: data['conductor'] = "\(%s\)" % str(data['conductor']) else: data['conductor'] = "\(%s=%s\)" % (str(data['conductor']), latex(data['conductor'].factor())) data['galois_group'] = group_display_knowl(n, t, C) data['cclasses'] = cclasses_display_knowl(n, t, C) data['character_table'] = character_table_display_knowl(n, t, C) data['class_group'] = nf.class_group() data['class_group_invs'] = nf.class_group_invariants() data['signature'] = nf.signature() D = nf.disc() ram_primes = D.prime_factors() data['disc_factor'] = nf.disc_factored_latex() if D.abs().is_prime() or D == 1: data['discriminant'] = "\(%s\)" % str(D) else: data['discriminant'] = "\(%s=%s\)" % (str(D), data['disc_factor']) npr = len(ram_primes) ram_primes = str(ram_primes)[1:-1] if ram_primes == '': ram_primes = r'\textrm{None}' data['frob_data'], data['seeram'] = frobs(nf.K()) data['phrase'] = group_phrase(n, t, C) zk = pari(nf.K()).nf_subst('a') zk = list(zk.nf_get_zk()) Ra = PolynomialRing(QQ, 'a') zk = [latex(Ra(x)) for x in zk] zk = ['$%s$' % x for x in zk] zk = ', '.join(zk) grh_label = '<small>(<a title="assuming GRH" knowl="nf.assuming_grh">assuming GRH</a>)</small>' if nf.used_grh() else '' # Short version for properties grh_lab = nf.short_grh_string() pretty_label = field_pretty(label) if label != pretty_label: pretty_label = "%s: %s" % (label, pretty_label) info.update(data) info.update({ 'label': pretty_label, 'label_raw': label, 'polynomial': web_latex_split_on_pm(nf.K().defining_polynomial()), 'ram_primes': ram_primes, 'integral_basis': zk, 'regulator': web_latex(nf.regulator()), 'unit_rank': nf.unit_rank(), 'root_of_unity': web_latex(nf.K().primitive_root_of_unity()), 'fund_units': nf.units(), 'grh_label': grh_label }) bread.append(('%s' % info['label_raw'], ' ')) info['downloads_visible'] = True info['downloads'] = [('worksheet', '/')] info['friends'] = [] if nf.can_class_number(): info['friends'].append(('L-function', "/L/NumberField/%s" % label)) info['friends'].append(('Galois group', "/GaloisGroup/%dT%d" % (n, t))) if 'dirichlet_group' in info: info['friends'].append(('Dirichlet group', url_for("dirichlet_group_table", modulus=int(conductor), char_number_list=','.join( [str(a) for a in dirichlet_chars]), poly=info['polynomial']))) info['learnmore'] = [('Global number field labels', url_for( ".render_labels_page")), (Completename, url_for(".render_discriminants_page"))] # With Galois group labels, probably not needed here # info['learnmore'] = [('Global number field labels', # url_for(".render_labels_page")), ('Galois group # labels',url_for(".render_groups_page")), # (Completename,url_for(".render_discriminants_page"))] title = "Global Number Field %s" % info['label'] if npr == 1: primes = 'prime' else: primes = 'primes' properties2 = [('Degree:', '%s' % data['degree']), ('Signature:', '$%s$' % data['signature']), ('Discriminant:', '$%s$' % data['disc_factor']), ('Ramified ' + primes + ':', '$%s$' % ram_primes), ('Class number:', '%s %s' % (data['class_number'], grh_lab)), ('Class group:', '%s %s' % (data['class_group_invs'], grh_lab)), ('Galois Group:', group_display_short(data['degree'], t, C)) ] from lmfdb.math_classes import NumberFieldGaloisGroup try: info["tim_number_field"] = NumberFieldGaloisGroup.find_one({"label": label}) v = nf.factor_perm_repn(info["tim_number_field"]) info["mydecomp"] = ['*' if x>0 else '' for x in v] except AttributeError: pass # del info['_id'] return render_template("number_field.html", properties2=properties2, credit=NF_credit, title=title, bread=bread, friends=info.pop('friends'), learnmore=info.pop('learnmore'), info=info)