def hecke_eigenvalue(self, m): ''' Assuming self is an eigenform, returns mth Hecke eigenvalue. ''' t = self._none_zero_tpl() K = self.base_ring if hasattr(K, "fraction_field"): K = K.fraction_field() if self.sym_wt == 0 and ZZ(m).is_prime_power() and factor(m)[0][1] == 2: p = factor(m)[0][0] lp = self.hecke_eigenvalue(p) return K(self._hecke_tp2_for_eigenform(p, t, lp)) / self[t] else: return K(self.hecke_operator(m, t) / self[t])
def dirichlet_series_coeffs(self, prec, eps=1e-10): """ Return the coefficients of the Dirichlet series representation of self, up to the given precision. INPUT: - prec -- positive integer - eps -- None or a positive real; any coefficient with absolute value less than eps is set to 0. """ # Use multiplicativity to compute the Dirichlet series # coefficients, then make a DirichletSeries object. zero = RDF(0) coeffs = [RDF(0), RDF(1)] + [None] * (prec - 2) from sage.all import log, floor # TODO: slow # prime-power indexed coefficients for p in prime_range(2, prec): B = floor(log(prec, p)) + 1 series = self._local_series(p, B) p_pow = p for i in range(1, B): coeffs[p_pow] = series[i] if ( eps is None or abs(series[i]) > eps) else zero p_pow *= p # non-prime-powers from sage.all import factor for n in range(2, prec): if coeffs[n] is None: a = prod(coeffs[p**e] for p, e in factor(n)) coeffs[n] = a if (eps is None or abs(a) > eps) else zero return coeffs
def list_to_factored_poly_otherorder(s): if len(s) == 1: 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 = '' for v in sfacts_fc: 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 += 'T' elif i > 1: outstr += 'T^{' + str(i) + '}' if len(sfacts) > 1 or v[1] > 1: outstr += ')' if v[1] > 1: outstr += '^{' + str(v[1]) + '}' return outstr
def dirichlet_series_coeffs(self, prec, eps=1e-10): """ Return the coefficients of the Dirichlet series representation of self, up to the given precision. INPUT: - prec -- positive integer - eps -- None or a positive real; any coefficient with absolute value less than eps is set to 0. """ # Use multiplicativity to compute the Dirichlet series # coefficients, then make a DirichletSeries object. zero = RDF(0) coeffs = [RDF(0),RDF(1)] + [None]*(prec-2) from sage.all import log, floor # TODO: slow # prime-power indexed coefficients for p in prime_range(2, prec): B = floor(log(prec, p)) + 1 series = self._local_series(p, B) p_pow = p for i in range(1, B): coeffs[p_pow] = series[i] if (eps is None or abs(series[i])>eps) else zero p_pow *= p # non-prime-powers from sage.all import factor for n in range(2, prec): if coeffs[n] is None: a = prod(coeffs[p**e] for p, e in factor(n)) coeffs[n] = a if (eps is None or abs(a) > eps) else zero return coeffs
def build_matrix(P, M, c=1000): factors_M = factor(M) rows = [] # add logarithms for p in P: row = [] for q, e in factors_M: row.extend(Zmod(q**e)(p).generalised_log() ) # generalised_log() uses unit_gens() generators row = [c * x for x in row] # multiply logs by a large constant to help LLL rows.append(row) height = len(rows) width = len(rows[0]) # add unit matrix for i, row in enumerate(rows): row.extend([1 if j == i else 0 for j in range(0, height)]) # add group orders generators_M = [g for q, e in factors_M for g in Zmod(q**e).unit_gens()] for i, g in enumerate(generators_M): rows.append([ g.multiplicative_order() * c if j == i else 0 for j in range(0, width + height) ]) return Matrix(rows)
def web_latex_factored_integer(x, enclose=True, equals=False): r""" Given any x that can be converted to a ZZ, creates latex string representing x in factored form Returns 0 for 0, replaces -1\cdot with -. If equals=true returns latex string for x = factorization but omits "= factorization" if abs(x)=0,1,prime """ x = ZZ(x) if abs(x) in [0,1] or abs(x).is_prime(): return web_latex(x, enclose=enclose) if equals: s = web_latex(factor(x), enclose=False).replace(r"-1 \cdot","-") s = " %s = %s " % (x, s) else: s = web_latex(factor(x), enclose=False).replace(r"-1 \cdot","-") return r"\( %s \)" % s if enclose else s
def pohlig_hellman(g, h, group, order=None): """Pohlig-Hellman algorithm for computing discrete logarithms in a finite abelian group `group` whose order is a smooth integer. INPUT: - `g` must be a primitive element of `group` - `h` must be an element of `group` OUTPUT: - `x` such that ``g^x = h`` See https://en.wikipedia.org/wiki/Pohlig%E2%80%93Hellman_algorithm for details. """ if order is None: order = group.order() decomposition = factor(order) residues = [] moduli = [] for pi, ei in decomposition: # compute the residue of x mod pi^ni modulus = pi**ei ni = order // modulus gi, hi = g**ni, h**ni residue = pohlig_hellman_prime(gi, hi, group, pi, ei) residues.append(residue) moduli.append(modulus) x = CRT(residues, moduli) return x
def factor(n): # For small n, use hand-rolled factoring algorithm to avoid slow imports. if n <= 2**16: return _factor(n) from sage.all import factor return factor(n)
def list_to_factored_poly_otherorder(s): if len(s) == 1: 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 = '' for v in sfacts_fc: 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 += 'T' elif i > 1: outstr += 'T^{' + str(i) + '}' if len(sfacts) > 1 or v[1] > 1: outstr += ')' if v[1] > 1: outstr += '^{' + str(v[1]) + '}' return outstr
def pohlig_hellman(G, A, E): """Pohlig-Hellman algorithm for computing discrete logarithms in an elliptic curve `E` whose order is a smooth integer. INPUT: - `G` must be an element of `E` - `A` must be an element of the sub-group generated by `G` OUTPUT: - `n` such that `n*G = A` """ n = G.order() decomposition = factor(n) residues = [] moduli = [] for pi, ei in decomposition: # compute the residue of x mod pi^ni modulus = pi**ei ni = n // modulus Gi, Ai = ni * G, ni * A x = pohlig_hellman_prime(Gi, Ai, E, pi, ei) residues.append(x) moduli.append(modulus) x = CRT(residues, moduli) return x
def formtest(minD, maxD, k, eps=-1): ds = {} for D in range(minD, maxD + 1): if (eps * D) % 4 == 1: dif, d, dd = compare_formulas_2(eps * D, k) if dif <= 1e-6: print(D, factor(D)) print(dif, d, dd)
def hecke_charpoly(self, m, var="x", algorithm='linbox'): p, i = factor(m)[0] if not (ZZ(m).is_prime_power() and 0 < i < 3): raise RuntimeError("m must be a prime or the square of a prime.") if i == 1: return self._hecke_tp_charpoly(p, var=var, algorithm=algorithm) if i == 2: return self._hecke_tp2_charpoly(p, var=var, algorithm=algorithm)
def _prime_power_divisors(n): divisors = [] for p, e in factor(n): for i in range(1, e + 1): divisors.append(p**i) divisors.sort() return divisors
def _polynomial_gcd_crt(a, b, modulus): gs = [] ps = [] for p, _ in factor(modulus): zmodp = Zmod(p) gs.append(_polynomial_gcd(a.change_ring(zmodp), b.change_ring(zmodp)).change_ring(ZZ)) ps.append(p) return gs[0] if len(gs) == 1 else crt(gs, ps)
def myfunc(inp, n): fn = list(factor(inp)) pvals = [[localfactorsa[self.any_prime_to_cc_index(z[0]) - 1], z[1]] for z in fn] # -1 is the marker that the prime divides the conductor for j in range(len(pvals)): if pvals[j][0] < 0: return -1 pvals = sum([z[0] * z[1] for z in pvals]) return pvals % n
def myfunc(inp, n): fn = list(factor(inp)) pvals = [[localfactorsa[self.any_prime_to_cc_index(z[0])-1], z[1]] for z in fn] # -1 is the marker that the prime divides the conductor for j in range(len(pvals)): if pvals[j][0] < 0: return -1 pvals = sum([z[0]*z[1] for z in pvals]) return (pvals % n)
def id_dirichlet(fun, N, n): N = Integer(N) if N == 1: return (1, 1) p2 = valuation(N, 2) N2 = 2**p2 Nodd = N // N2 Nfact = list(factor(Nodd)) #print "n = "+str(n) #for j in range(20): # print "chi(%d) = e(%d/%d)"%(j+2, fun(j+2,n), n) plist = [z[0] for z in Nfact] ppows = [z[0]**z[1] for z in Nfact] ppows2 = list(ppows) idems = [1 for z in Nfact] proots = [primitive_root(z) for z in ppows] # Get CRT idempotents if p2 > 0: ppows2.append(N2) for j in range(len(plist)): exps = [1 for z in idems] if p2 > 0: exps.append(1) exps[j] = proots[j] idems[j] = crt(exps, ppows2) idemvals = [fun(z, n) for z in idems] # now normalize to right root of unity base idemvals = [ idemvals[j] * euler_phi(ppows[j]) / n for j in range(len(idemvals)) ] ans = [ Integer(mod(proots[j], ppows[j])**idemvals[j]) for j in range(len(proots)) ] ans = crt(ans, ppows) # There are cases depending on 2-part of N if p2 == 0: return (N, ans) if p2 == 1: return (N, crt([1, ans], [2, Nodd])) if p2 == 2: my3 = crt([3, 1], [N2, Nodd]) if fun(my3, n) == 0: return (N, crt([1, ans], [4, Nodd])) else: return (N, crt([3, ans], [4, Nodd])) # Final case 2^3 | N my5 = crt([5, 1], [N2, Nodd]) test1 = fun(my5, n) * N2 / 4 / n test1 = Integer(mod(5, N2)**test1) minusone = crt([-1, 1], [N2, Nodd]) test2 = (fun(minusone, n) * N2 / 4 / n) % (N2 / 4) if test2 > 0: test1 = Integer(mod(-test1, N2)) return (N, crt([test1, ans], [N2, Nodd]))
def ll_common_denominator(f): """For a polynomial f with fractional coefficients, write out the polynomial such that there is only a single denominator.""" # f should be a polynomial if not is_Polynomial(f): return ll_raw(f) # first determine the lcm of the denominators of the coefficients cd = reduce(lcm, [c.denominator() for c in f]) if is_Polynomial(cd) and cd.degree() > 0: return "\\frac{" + ll_raw(cd * f) + "}{" + ll_raw(factor(cd)) + "}" else: return ll_raw(f)
def factor_offline(n): print( "failed to factor in http://factordb.com\nThe length of n is %s\nIt might need a very long time and sagemath is required" % (len(n))) choice = input('Do you want to factor in your local computer?\n[y/n]') if choice[0] is 'y': try: from sage.all import factor p, q = map(int, re.split(r'\s*\*\s*', str(factor(n)))) return (pp, qq) except ImportError as e: raise Exception("Can't factor n")
def properties(self): nilp_str = f"yes, of class {self.nilpotency_class}" if self.nilpotent else "no" solv_str = f"yes, of length {self.derived_length}" if self.solvable else "no" props = [ ("Label", self.label), ("Order", web_latex(factor(self.order))), ("Exponent", web_latex(factor(self.exponent))), (None, self.image()), ] if self.abelian: props.append(("Abelian", "yes")) if self.simple: props.extend([("Simple", "yes"), (r"#$\operatorname{Aut}(G)$", web_latex(factor(self.aut_order)))]) else: props.append((r"#$\operatorname{Aut}(G)$", web_latex(factor(self.aut_order)))) else: if self.simple: props.append(("Simple", "yes")) else: props.extend([("Nilpotent", nilp_str), ("Solvable", solv_str)]) props.extend([ (r"#$G^{\mathrm{ab}}$", web_latex(self.Gab_order_factor())), ("#$Z(G)$", web_latex(self.cent_order_factor())), (r"#$\operatorname{Aut}(G)$", web_latex(factor(self.aut_order))), (r"#$\operatorname{Out}(G)$", web_latex(factor(self.outer_order))), ]) props.extend([ ("Rank", f"${self.rank}$"), ("Perm deg.", f"${self.transitive_degree}$"), # ("Faith. dim.", str(self.faithful_reps[0][0])), ]) return props
def _hecke_eigen_needed_tuples(self, m): tpl = self._none_zero_tpl() p, i = factor(m)[0] if not (ZZ(m).is_prime_power() and 0 < i < 3): raise RuntimeError("m must be a prime or the square of a prime.") if i == 1: return uniq(reduced_form_with_sign(t)[0] for t in self._hecke_tp_needed_tuples(p, tpl)) if i == 2: l1 = self._hecke_eigen_needed_tuples(p) l = [reduced_form_with_sign(t)[0] for t in self._hecke_tp2_needed_tuples(p, tpl)] return uniq(l1 + l)
def get_way_count(surface_count): n = (surface_count + 3) // 2 factors = [x for x, _ in factor(n)] def f(x): first_k = (x * (-x % 3) - 2) // 3 last_k = (n - 2) // 3 last_k = last_k - (last_k - first_k) % x return (last_k - first_k) // x + 1 return ((n - 2) // 3 + 1 + sum( (+1 if len(subset) % 2 == 0 else -1) * f(prod(subset)) for subset in Subsets(factors) if subset))
def sylow_subgroups(self): """ Returns a list of pairs (p, P) where P is a WebAbstractSubgroup representing a p-Sylow subgroup. """ syl_dict = {} for sub in self.subgroups.values(): if sub.sylow > 0: syl_dict[sub.sylow] = sub syl_list = [] for p, e in factor(self.order): if p in syl_dict: syl_list.append((p, syl_dict[p])) return syl_list
def id_dirichlet(fun, N, n): N = Integer(N) if N == 1: return (1, 1) p2 = valuation(N, 2) N2 = 2 ** p2 Nodd = N / N2 Nfact = list(factor(Nodd)) # print "n = "+str(n) # for j in range(20): # print "chi(%d) = e(%d/%d)"%(j+2, fun(j+2,n), n) plist = [z[0] for z in Nfact] ppows = [z[0] ** z[1] for z in Nfact] ppows2 = list(ppows) idems = [1 for z in Nfact] proots = [primitive_root(z) for z in ppows] # Get CRT idempotents if p2 > 0: ppows2.append(N2) for j in range(len(plist)): exps = [1 for z in idems] if p2 > 0: exps.append(1) exps[j] = proots[j] idems[j] = crt(exps, ppows2) idemvals = [fun(z, n) for z in idems] # now normalize to right root of unity base idemvals = [idemvals[j] * euler_phi(ppows[j]) / n for j in range(len(idemvals))] ans = [Integer(mod(proots[j], ppows[j]) ** idemvals[j]) for j in range(len(proots))] ans = crt(ans, ppows) # There are cases depending on 2-part of N if p2 == 0: return (N, ans) if p2 == 1: return (N, crt([1, ans], [2, Nodd])) if p2 == 2: my3 = crt([3, 1], [N2, Nodd]) if fun(my3, n) == 0: return (N, crt([1, ans], [4, Nodd])) else: return (N, crt([3, ans], [4, Nodd])) # Final case 2^3 | N my5 = crt([5, 1], [N2, Nodd]) test1 = fun(my5, n) * N2 / 4 / n test1 = Integer(mod(5, N2) ** test1) minusone = crt([-1, 1], [N2, Nodd]) test2 = (fun(minusone, n) * N2 / 4 / n) % (N2 / 4) if test2 > 0: test1 = Integer(mod(-test1, N2)) return (N, crt([test1, ans], [N2, Nodd]))
def gen_unsafe_curve(bits, attempts=-1): """generates a random curve that has only small factors""" while attempts != 0: E, F = gen_random_curve(bits) factors = [x for x, y in factor(E.order())] bit_lengths = [int(f).bit_length() for f in factors] if all(l <= MAX_BITS_FOR_FACTOR for l in bit_lengths): a = E.ainvs()[3] b = E.ainvs()[4] p = F.cardinality() P = gen_generator(E) return a, b, p, P.xy() if attempts > 0: attempts -= 1
def pohlighellman(g, h): phi = g.multiplicative_order() factors = factor(phi) chinese_pairs = [] for pi, ei in factors: n = phi / (pi**ei) print("testing n = %s" % n) hn = h**n print(("Searching h^%d in subgroup " "g^%d using Baby-step giant-step") % (n, n)) a = babystepgiantstep(g**n, hn) print("Found g^(%s * %s) == %s" % (n, a, hn)) chinese_pairs.append([a, pi**ei]) return crt(*map(list, zip(*chinese_pairs)))
def hecke_operator(self, m, tpl): ''' Assumes m is a prime or the square of a prime. And returns the tpl th Fourier coefficient of T(m)self. cf Andrianov, Zhuravlev, Modular Forms and Hecke Operators, pp 242. ''' p, i = factor(m)[0] if not (ZZ(m).is_prime_power() and 0 < i < 3): raise RuntimeError("m must be a prime or the square of a prime.") if self.sym_wt == 0: if i == 1: return self._hecke_tp(p, tpl) elif i == 2: return self._hecke_tp2(p, tpl) else: return self._hecke_op_vector_vld(p, i, tpl)
def pohlig(E, H, P) -> int: # pohlig-hellman algorithm, factor the order of the curve # and use bsgs to solve for each factor, then use CRT to # get a solution. bases = [] resids = [] for i, j in factor(E.order()): e = i**j logging.info(f' pohlig: {e}') t = E.order() // e tH = H * t tP = P * t dlog = bsgs(tP, tH, (0, e), '+') bases.append(dlog) resids.append(e) return CRT_list(bases, resids)
def pohlighellman(g, h): phi = g.multiplicative_order() factors = factor(phi) chinese_pairs = [] for pi, ei in factors: n = phi / (pi ** ei) print("testing n = %s" % n) hn = h ** n print("h^%s = %s" % (n, hn)) for i in range(pi ** ei): print("Testing g^(%s * %s) == %s" % (i, n, hn)) if g ** (n * i) == hn: print("Found x mod %s = %s" % (pi ** ei, i)) chinese_pairs.append([i, pi ** ei]) break return crt(*map(list, zip(*chinese_pairs)))
def pohlig_hellman(g,h,p): ''' Pohlig Hellman Algorithm: - currently only applicable to <g> = Fp ''' n = p - 1 # order of group print('n=',n) # factor n n_factors = factor(n) print('n_factors=', n_factors) i = 0 eqs = [] for i, f in enumerate(n_factors): q, e = f q, e = int(q), int(e) pi = int(pow(q,e)) exp = int( n // pi ) gi = pow(g, exp) hi = pow(h, exp) print('--------------------') print(f'p{i}={pi}') print(f'exp{i}={exp}') print(f'g{i}={gi}') print(f'h{i}={hi}') # Solve the DLP: gi^yi = hi (mod p) yi = babygiantstep(p, gi, hi) print(f'y{i}={yi}') # Generate equation to solve using Chinese Remainder Theorem eqs.append((yi, pi)) print(f'x{i}={yi} (mod {pi})') print('--------------------') # Knit together the smaller DLP solutions using the Chinese # Remainder Theorem to get the actual solution x, m = chinese_remainder_theorem(eqs) print('x=', x) return x
def compute_dirichlet_series(p_list, PREC): ''' computes the dirichlet series for a Lfunction_SMF2_scalar_valued ''' # p_list is a list of pairs (p,y) where p is a prime and y is the list of roots of the Euler factor at x LL = [0] * PREC # create an empty list of the right size and now populate it with the powers of p for (p, y) in p_list: # FIXME p_prec is never used, but perhaps it should be? # p_prec = log(PREC) / log(p) + 1 ep = euler_p_factor(y, PREC) for n in range(ep.prec()): if p ** n < PREC: LL[p ** n] = ep.coefficients()[n] for i in range(1, PREC): f = factor(i) if len(f) > 1: # not a prime power LL[i] = prod([LL[p ** e] for (p, e) in f]) return LL[1:]
def show_factored_eqs(eqs, only_print=False, numbers=False, variables=False, print_latex=False, print_eqs=True): r""" Show given equations factored. """ for i, eq in enumerate(eqs): factors = factor(eq) if numbers: print(i) if variables: print(latex(eq.variables())) if print_latex: print(latex(factors) + '=0\,, \\\\') if print_eqs: if only_print: print(factors) else: show(factors)
def get_composite_discrete_root(a, m): # Prime factorization of m m_factors = factor(m) # returns [(base, exp), (base,exp)...] cr = [] for m_factor in m_factors: p = m_factor[0] # Find x s.t. x^ = p y1, y2 = get_discrete_root(a, p) y1, y2 = int(y1), int(y2) factor_roots = ((y1, p), (y2, p)) cr.append(factor_roots) y = y1 if y1 < y2 else y2 roots = [] n = len(cr) i = 0 while i < math.ceil(n / 2): factor_roots = cr[i] for j, froot in enumerate(factor_roots): k = 0 while k < n: if k != i: k_root = cr[k] for other_root in k_root: sys_eq = [froot, other_root] x, m = chinese_remainder_theorem(sys_eq) roots.append(x) k = k + 1 i = i + 1 return roots
def __init__(self, K, N_max=10**5): """ Compute J working over the field K. """ self.N_max = N_max self.K = K from sage.all import prime_powers, factor PP = prime_powers(N_max+1)[1:] n = len(PP) self.a = [K(0)]*n self.s = [K(0)]*n self.pv = [0]*n i = 0 for pv in PP: F = factor(pv) p, v = F[0] self.pv[i] = K(pv) logp = K(p).log() self.a[i] = logp/K(pv).sqrt() self.s[i] = v*logp i += 1
def __init__(self, K, N_max=10**5): """ Compute J working over the field K. """ self.N_max = N_max self.K = K from sage.all import prime_powers, factor PP = prime_powers(N_max + 1)[1:] n = len(PP) self.a = [K(0)] * n self.s = [K(0)] * n self.pv = [0] * n i = 0 for pv in PP: F = factor(pv) p, v = F[0] self.pv[i] = K(pv) logp = K(p).log() self.a[i] = logp / K(pv).sqrt() self.s[i] = v * logp i += 1
def zfactor(n): return factor(n) if n != 0 else 0
def make_object(self, curve, endo, tama, ratpts, is_curve): from lmfdb.genus2_curves.main import url_for_curve_label # all information about the curve, its Jacobian, isogeny class, and endomorphisms goes in the data dictionary # most of the data from the database gets polished/formatted before we put it in the data dictionary data = self.data = {} data['label'] = curve['label'] if is_curve else curve['class'] data['slabel'] = data['label'].split('.') # set attributes common to curves and isogeny classes here data['Lhash'] = str(curve['Lhash']) data['cond'] = ZZ(curve['cond']) data['cond_factor_latex'] = web_latex(factor(int( data['cond']))).replace(r"-1 \cdot", "-") data['analytic_rank'] = ZZ(curve['analytic_rank']) data['mw_rank'] = ZZ(0) if curve.get('mw_rank') is None else ZZ( curve['mw_rank']) # 0 will be marked as a lower bound data['mw_rank_proved'] = curve['mw_rank_proved'] data['analytic_rank_proved'] = curve['analytic_rank_proved'] data['hasse_weil_proved'] = curve['hasse_weil_proved'] data['st_group'] = curve['st_group'] data['st_group_link'] = st_link_by_name(1, 4, data['st_group']) data['st0_group_name'] = st0_group_name(curve['real_geom_end_alg']) data['is_gl2_type'] = curve['is_gl2_type'] data['root_number'] = ZZ(curve['root_number']) data['lfunc_url'] = url_for("l_functions.l_function_genus2_page", cond=data['slabel'][0], x=data['slabel'][1]) data['bad_lfactors'] = literal_eval(curve['bad_lfactors']) data['bad_lfactors_pretty'] = [(c[0], list_to_factored_poly_otherorder(c[1])) for c in data['bad_lfactors']] if is_curve: # invariants specific to curve data['class'] = curve['class'] data['abs_disc'] = ZZ(curve['abs_disc']) data['disc'] = curve['disc_sign'] * data['abs_disc'] data['min_eqn'] = literal_eval(curve['eqn']) data['min_eqn_display'] = min_eqns_pretty(data['min_eqn']) data['disc_factor_latex'] = web_latex(factor( data['disc'])).replace(r"-1 \cdot", "-") data['igusa_clebsch'] = [ ZZ(a) for a in literal_eval(curve['igusa_clebsch_inv']) ] data['igusa'] = [ZZ(a) for a in literal_eval(curve['igusa_inv'])] data['g2'] = [QQ(a) for a in literal_eval(curve['g2_inv'])] data['igusa_clebsch_factor_latex'] = [ web_latex(zfactor(i)).replace(r"-1 \cdot", "-") for i in data['igusa_clebsch'] ] data['igusa_factor_latex'] = [ web_latex(zfactor(j)).replace(r"-1 \cdot", "-") for j in data['igusa'] ] data['aut_grp'] = small_group_label_display_knowl( '%d.%d' % tuple(literal_eval(curve['aut_grp_id']))) data['geom_aut_grp'] = small_group_label_display_knowl( '%d.%d' % tuple(literal_eval(curve['geom_aut_grp_id']))) data['num_rat_wpts'] = ZZ(curve['num_rat_wpts']) data['has_square_sha'] = "square" if curve[ 'has_square_sha'] else "twice a square" P = curve['non_solvable_places'] if len(P): sz = "except over " sz += ", ".join([QpName(p) for p in P]) last = " and" if len(P) > 2: last = ", and" sz = last.join(sz.rsplit(",", 1)) else: sz = "everywhere" data['non_solvable_places'] = sz data['two_selmer_rank'] = ZZ(curve['two_selmer_rank']) data['torsion_order'] = curve['torsion_order'] data['end_ring_base'] = endo['ring_base'] data['end_ring_geom'] = endo['ring_geom'] data['real_period'] = decimal_pretty(str(curve['real_period'])) data['regulator'] = decimal_pretty( str(curve['regulator'] )) if curve['regulator'] > -0.5 else 'unknown' if data['mw_rank'] == 0 and data['mw_rank_proved']: data['regulator'] = '1' # display an exact 1 when we know this data['tamagawa_product'] = ZZ( curve['tamagawa_product']) if curve.get( 'tamagawa_product') else 0 data['analytic_sha'] = ZZ( curve['analytic_sha']) if curve.get('analytic_sha') else 0 data['leading_coeff'] = decimal_pretty( str(curve['leading_coeff'] )) if curve['leading_coeff'] else 'unknown' data['rat_pts'] = ratpts['rat_pts'] data['rat_pts_v'] = ratpts['rat_pts_v'] data['rat_pts_table'] = ratpts_table(ratpts['rat_pts'], ratpts['rat_pts_v']) data['mw_gens_v'] = ratpts['mw_gens_v'] lower = len([n for n in ratpts['mw_invs'] if n == 0]) upper = data['analytic_rank'] invs = ratpts[ 'mw_invs'] if data['mw_gens_v'] or lower >= upper else [ 0 for n in range(upper - lower) ] + ratpts['mw_invs'] if len(invs) == 0: data['mw_group'] = 'trivial' else: data['mw_group'] = r'\(' + r' \times '.join([ (r'\Z' if n == 0 else r'\Z/{%s}\Z' % n) for n in invs ]) + r'\)' if lower >= upper: data['mw_gens_table'] = mw_gens_table(ratpts['mw_invs'], ratpts['mw_gens'], ratpts['mw_heights'], ratpts['rat_pts']) if curve['two_torsion_field'][0]: data['two_torsion_field_knowl'] = nf_display_knowl( curve['two_torsion_field'][0], field_pretty(curve['two_torsion_field'][0])) else: t = curve['two_torsion_field'] data[ 'two_torsion_field_knowl'] = r"splitting field of \(%s\) with Galois group %s" % ( intlist_to_poly( t[1]), group_display_knowl(t[2][0], t[2][1])) tamalist = [[item['p'], item['tamagawa_number']] for item in tama] data['local_table'] = local_table(data['abs_disc'], data['cond'], tamalist, data['bad_lfactors_pretty']) else: # invariants specific to isogeny class curves_data = list( db.g2c_curves.search({"class": curve['class']}, ['label', 'eqn'])) if not curves_data: raise KeyError( "No curves found in database for isogeny class %s of genus 2 curve %s." % (curve['class'], curve['label'])) data['curves'] = [{ "label": c['label'], "equation_formatted": min_eqn_pretty(literal_eval(c['eqn'])), "url": url_for_curve_label(c['label']) } for c in curves_data] lfunc_data = db.lfunc_lfunctions.lucky( {'Lhash': str(curve['Lhash'])}) if not lfunc_data: raise KeyError( "No Lfunction found in database for isogeny class of genus 2 curve %s." % curve['label']) if lfunc_data and lfunc_data.get('euler_factors'): data['good_lfactors'] = [ [nth_prime(n + 1), lfunc_data['euler_factors'][n]] for n in range(len(lfunc_data['euler_factors'])) if nth_prime(n + 1) < 30 and (data['cond'] % nth_prime(n + 1)) ] data['good_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['good_lfactors'] ] # Endomorphism data over QQ: data['gl2_statement_base'] = gl2_statement_base( endo['factorsRR_base'], r'\(\Q\)') data['factorsQQ_base'] = endo['factorsQQ_base'] data['factorsRR_base'] = endo['factorsRR_base'] data['end_statement_base'] = ( r"Endomorphism %s over \(\Q\):<br>" % ("ring" if is_curve else "algebra") + end_statement(data['factorsQQ_base'], endo['factorsRR_base'], ring=data['end_ring_base'] if is_curve else None)) # Field over which all endomorphisms are defined data['end_field_label'] = endo['fod_label'] data['end_field_poly'] = intlist_to_poly(endo['fod_coeffs']) data['end_field_statement'] = end_field_statement( data['end_field_label'], data['end_field_poly']) # Endomorphism data over QQbar: data['factorsQQ_geom'] = endo['factorsQQ_geom'] data['factorsRR_geom'] = endo['factorsRR_geom'] if data['end_field_label'] != '1.1.1.1': data['gl2_statement_geom'] = gl2_statement_base( data['factorsRR_geom'], r'\(\overline{\Q}\)') data['end_statement_geom'] = ( r"Endomorphism %s over \(\overline{\Q}\):" % ("ring" if is_curve else "algebra") + end_statement( data['factorsQQ_geom'], data['factorsRR_geom'], field=r'\overline{\Q}', ring=data['end_ring_geom'] if is_curve else None)) data['real_geom_end_alg_name'] = real_geom_end_alg_name( curve['real_geom_end_alg']) data['geom_end_alg_name'] = geom_end_alg_name(curve['geom_end_alg']) # Endomorphism data over intermediate fields not already treated (only for curves, not necessarily isogeny invariant): if is_curve: data['end_lattice'] = (endo['lattice'])[1:-1] if data['end_lattice']: data['end_lattice_statement'] = end_lattice_statement( data['end_lattice']) # Field over which the Jacobian decomposes (base field if Jacobian is geometrically simple) data['is_simple_geom'] = endo['is_simple_geom'] data['split_field_label'] = endo['spl_fod_label'] data['split_field_poly'] = intlist_to_poly(endo['spl_fod_coeffs']) data['split_field_statement'] = split_field_statement( data['is_simple_geom'], data['split_field_label'], data['split_field_poly']) # Elliptic curve factors for non-simple Jacobians if not data['is_simple_geom']: data['split_coeffs'] = endo['spl_facs_coeffs'] if 'spl_facs_labels' in endo and len( endo['spl_facs_labels']) == len(endo['spl_facs_coeffs']): data['split_labels'] = endo['spl_facs_labels'] data['split_condnorms'] = endo['spl_facs_condnorms'] data['split_statement'] = split_statement(data['split_coeffs'], data.get('split_labels'), data['split_condnorms']) # Properties self.properties = properties = [('Label', data['label'])] if is_curve: plot_from_db = db.g2c_plots.lucky({"label": curve['label']}) if (plot_from_db is None): self.plot = encode_plot( eqn_list_to_curve_plot( data['min_eqn'], ratpts['rat_pts'] if ratpts else [])) else: self.plot = plot_from_db['plot'] plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format( self.plot) properties += [ (None, plot_link), ('Conductor', str(data['cond'])), ('Discriminant', str(data['disc'])), ] if data['mw_rank_proved']: properties += [('Mordell-Weil group', data['mw_group'])] properties += [ ('Sato-Tate group', data['st_group_link']), (r'\(\End(J_{\overline{\Q}}) \otimes \R\)', r'\(%s\)' % data['real_geom_end_alg_name']), (r'\(\End(J_{\overline{\Q}}) \otimes \Q\)', r'\(%s\)' % data['geom_end_alg_name']), (r'\(\overline{\Q}\)-simple', bool_pretty(data['is_simple_geom'])), (r'\(\mathrm{GL}_2\)-type', bool_pretty(data['is_gl2_type'])), ] # Friends self.friends = friends = [] if is_curve: friends.append(('Isogeny class %s.%s' % (data['slabel'][0], data['slabel'][1]), url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1]))) # first deal with EC ecs = [] if 'split_labels' in data: for friend_label in data['split_labels']: if is_curve: ecs.append(("Elliptic curve " + friend_label, url_for_ec(friend_label))) else: ecs.append( ("Isogeny class " + ec_label_class(friend_label), url_for_ec_class(friend_label))) ecs.sort(key=lambda x: key_for_numerically_sort(x[0])) # then again EC from lfun instances = [] for elt in db.lfunc_instances.search( { 'Lhash': data['Lhash'], 'type': 'ECQP' }, 'url'): instances.extend(elt.split('|')) # and then the other isogeny friends instances.extend([ elt['url'] for elt in get_instances_by_Lhash_and_trace_hash( data["Lhash"], 4, int(data["Lhash"])) ]) exclude = { elt[1].rstrip('/').lstrip('/') for elt in self.friends if elt[1] } exclude.add(data['lfunc_url'].lstrip('/L/').rstrip('/')) for elt in ecs + names_and_urls(instances, exclude=exclude): # because of the splitting we must use G2C specific code add_friend(friends, elt) if is_curve: friends.append(('Twists', url_for(".index_Q", g20=str(data['g2'][0]), g21=str(data['g2'][1]), g22=str(data['g2'][2])))) friends.append(('L-function', data['lfunc_url'])) # Breadcrumbs self.bread = bread = [('Genus 2 Curves', url_for(".index")), (r'$\Q$', url_for(".index_Q")), ('%s' % data['slabel'][0], url_for(".by_conductor", cond=data['slabel'][0])), ('%s' % data['slabel'][1], url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1]))] if is_curve: bread += [('%s' % data['slabel'][2], url_for(".by_url_isogeny_class_discriminant", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2])), ('%s' % data['slabel'][3], url_for(".by_url_curve_label", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2], num=data['slabel'][3]))] # Title self.title = "Genus 2 " + ("Curve " if is_curve else "Isogeny Class ") + data['label'] # Code snippets (only for curves) if not is_curve: return self.code = code = {} code['show'] = {'sage': '', 'magma': ''} # use default show names f, h = fh = data['min_eqn'] g = simplify_hyperelliptic(fh) code['curve'] = { 'sage': 'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s));' % (f, h), 'magma': 'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);' % (f, h) } code['simple_curve'] = { 'sage': 'X = HyperellipticCurve(R(%s))' % (g), 'magma': 'X,pi:= SimplifiedModel(C);' } if data['abs_disc'] % 4096 == 0: ind2 = [a[0] for a in data['bad_lfactors']].index(2) bad2 = data['bad_lfactors'][ind2][1] magma_cond_option = ': ExcFactors:=[*<2,Valuation(' + str( data['cond']) + ',2),R!' + str(bad2) + '>*]' else: magma_cond_option = '' code['cond'] = { 'magma': 'Conductor(LSeries(C%s)); Factorization($1);' % magma_cond_option } code['disc'] = { 'magma': 'Discriminant(C); Factorization(Integers()!$1);' } code['geom_inv'] = { 'sage': 'C.igusa_clebsch_invariants(); [factor(a) for a in _]', 'magma': 'IgusaClebschInvariants(C); IgusaInvariants(C); G2Invariants(C);' } code['aut'] = {'magma': 'AutomorphismGroup(C); IdentifyGroup($1);'} code['autQbar'] = { 'magma': 'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);' } code['num_rat_wpts'] = { 'magma': '#Roots(HyperellipticPolynomials(SimplifiedModel(C)));' } if ratpts: code['rat_pts'] = { 'magma': '[' + ','.join([ "C![%s,%s,%s]" % (p[0], p[1], p[2]) for p in ratpts['rat_pts'] ]) + '];' } code['mw_group'] = {'magma': 'MordellWeilGroupGenus2(Jacobian(C));'} code['two_selmer'] = { 'magma': 'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);' } code['has_square_sha'] = {'magma': 'HasSquareSha(Jacobian(C));'} code['locally_solvable'] = { 'magma': 'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsEverywhereLocally(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);' } code['torsion_subgroup'] = { 'magma': 'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);' }
def make_curve(self): # To start with the data fields of self are just those from the # databases. We reformat these, while computing some further (easy) # data about the curve on the fly. # Initialize data: data = self.data = {} endodata = self.endodata = {} # Polish data from database before putting it into the data dictionary: disc = ZZ(self.disc_sign) * ZZ(self.disc_key[3:]) # to deal with disc_key, uncomment line above and comment line below #disc = ZZ(self.disc_sign) * ZZ(self.abs_disc) data['disc'] = disc data['abs_disc'] = ZZ(self.disc_key[3:]) data['cond'] = ZZ(self.cond) data['min_eqn'] = self.min_eqn data['min_eqn_display'] = list_to_min_eqn(self.min_eqn) data['disc_factor_latex'] = web_latex(factor(data['disc'])) data['cond_factor_latex'] = web_latex(factor(int(self.cond))) data['aut_grp_id'] = self.aut_grp_id data['geom_aut_grp_id'] = self.geom_aut_grp_id data['igusa_clebsch'] = [ZZ(a) for a in self.igusa_clebsch] data['igusa'] = [ZZ(a) for a in self.igusa] data['g2'] = self.g2inv data['ic_norm'] = data['igusa_clebsch'] data['igusa_norm'] = data['igusa'] # Should we ever want to normalize the invariants further, then # uncomment the following lines: #data['ic_norm'] = normalize_invariants(data['igusa_clebsch'], [2, 4, 6, # 10]) #data['igusa_norm'] = normalize_invariants(data['igusa'], [2, 4, 6, 8, # 10]) data['ic_norm_factor_latex'] = [web_latex(zfactor(i)) for i in data['ic_norm']] data['igusa_norm_factor_latex'] = [ web_latex(zfactor(j)) for j in data['igusa_norm'] ] data['num_rat_wpts'] = ZZ(self.num_rat_wpts) data['two_selmer_rank'] = ZZ(self.two_selmer_rank) data['analytic_rank'] = ZZ(self.analytic_rank) data['has_square_sha'] = "square" if self.has_square_sha else "twice a square" data['locally_solvable'] = "yes" if self.locally_solvable else "no" if len(self.torsion) == 0: data['tor_struct'] = '\mathrm{trivial}' else: tor_struct = [ ZZ(a) for a in self.torsion ] data['tor_struct'] = ' \\times '.join([ '\Z/{%s}\Z' % n for n in tor_struct ]) # Data derived from Sato-Tate group: isogeny_class = g2cdb().isogeny_classes.find_one({'label' : isogeny_class_label(self.label)}) st_data = get_st_data(isogeny_class) for key in st_data.keys(): data[key] = st_data[key] # GL_2 statement over the base field endodata['gl2_statement_base'] = \ gl2_statement_base(self.factorsRR_base, r'\(\Q\)') # NOTE: In what follows there is some copying of code and data that is # stupid from the point of view of efficiency but likely better from # that of maintenance. # Endomorphism data over QQ: endodata['factorsQQ_base'] = self.factorsQQ_base endodata['factorsRR_base'] = self.factorsRR_base endodata['ring_base'] = self.ring_base endodata['endo_statement_base'] = \ """Endomorphism ring over \(\Q\):""" + \ endo_statement(endodata['factorsQQ_base'], endodata['factorsRR_base'], endodata['ring_base'], r'') # Field of definition data: endodata['fod_label'] = self.fod_label endodata['fod_poly'] = intlist_to_poly(self.fod_coeffs) endodata['fod_statement'] = fod_statement(endodata['fod_label'], endodata['fod_poly']) # Endomorphism data over QQbar: endodata['factorsQQ_geom'] = self.factorsQQ_geom endodata['factorsRR_geom'] = self.factorsRR_geom endodata['ring_geom'] = self.ring_geom if self.fod_label != '1.1.1.1': endodata['gl2_statement_geom'] = \ gl2_statement_base(self.factorsRR_geom, r'\(\overline{\Q}\)') endodata['endo_statement_geom'] = \ """Endomorphism ring over \(\overline{\Q}\):""" + \ endo_statement( endodata['factorsQQ_geom'], endodata['factorsRR_geom'], endodata['ring_geom'], r'\overline{\Q}') # Full endomorphism lattice minus entries already treated: N = len(self.lattice) endodata['lattice'] = (self.lattice)[1:N - 1] if endodata['lattice']: endodata['lattice_statement_preamble'] = lattice_statement_preamble() endodata['lattice_statement'] = lattice_statement(endodata['lattice']) # Splitting field description: #endodata['is_simple_base'] = self.is_simple_base endodata['is_simple_geom'] = self.is_simple_geom endodata['spl_fod_label'] = self.spl_fod_label endodata['spl_fod_poly'] = intlist_to_poly(self.spl_fod_coeffs) endodata['spl_fod_statement'] = spl_fod_statement( endodata['is_simple_geom'], endodata['spl_fod_label'], endodata['spl_fod_poly']) # Isogeny factors: if not endodata['is_simple_geom']: endodata['spl_facs_coeffs'] = self.spl_facs_coeffs # This could be done non-uniformly as well... later. if len(self.spl_facs_labels) == len(self.spl_facs_coeffs): endodata['spl_facs_labels'] = self.spl_facs_labels else: endodata['spl_facs_labels'] = ['' for coeffs in self.spl_facs_coeffs] endodata['spl_facs_condnorms'] = self.spl_facs_condnorms endodata['spl_statement'] = spl_statement( endodata['spl_facs_coeffs'], endodata['spl_facs_labels'], endodata['spl_facs_condnorms']) # Title self.title = "Genus 2 Curve %s" % (self.label) alpha = self.label.split('.')[1] num = self.label.split('.')[3] # Lady Gaga box self.plot = encode_plot(eqn_list_to_curve_plot(self.min_eqn)) self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot self.properties = ( ('Label', self.label), (None, self.plot_link), ('Conductor','%s' % self.cond), ('Discriminant', '%s' % data['disc']), ('Invariants', '%s </br> %s </br> %s </br> %s' % tuple(data['ic_norm'])), ('Sato-Tate group', data['st_group_href']), ('\(%s\)' % data['real_geom_end_alg_disp'][0], '\(%s\)' % data['real_geom_end_alg_disp'][1]), ('\(\mathrm{GL}_2\)-type','%s' % data['is_gl2_type_name']) ) self.friends = [ ('Isogeny class %s' % isogeny_class_label(self.label), url_for(".by_url_isogeny_class_label", cond = self.cond,alpha =alpha)), ('L-function', url_for("l_functions.l_function_genus2_page", cond=self.cond,x=alpha)), ('Twists', url_for(".index_Q", g20 = self.g2inv[0], g21 = self.g2inv[1], g22 = self.g2inv[2])) #('Siegel modular form someday', '.') ] if not endodata['is_simple_geom']: self.friends += [('Elliptic curve %s' % lab,url_for_ec(lab)) for lab in endodata['spl_facs_labels'] if lab != ''] #self.downloads = [('Download all stored data', '.')] # Breadcrumbs self.bread = ( ('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('%s' % self.cond, url_for(".by_conductor", cond=self.cond)), ('%s' % alpha, url_for(".by_url_isogeny_class_label", cond=self.cond, alpha=alpha)), ('%s' % self.abs_disc, url_for(".by_url_isogeny_class_discriminant", cond=self.cond, alpha=alpha, disc=self.abs_disc)), ('%s' % num, url_for(".by_url_curve_label", cond=self.cond, alpha=alpha, disc=self.abs_disc, num=num)) ) # Make code that is used on the page: self.code = {} self.code['show'] = {'sage':'','magma':''} # use default show names self.code['curve'] = {'sage':'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s))'%(self.data['min_eqn'][0],self.data['min_eqn'][1]), 'magma':'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);'%(self.data['min_eqn'][0],self.data['min_eqn'][1])} if self.data['disc'] % 4096 == 0: ind2 = [a[0] for a in self.data['isogeny_class']['bad_lfactors']].index(2) bad2 = self.data['isogeny_class']['bad_lfactors'][ind2][1] magma_cond_option = ': ExcFactors:=[*<2,Valuation('+str(self.data['cond'])+',2),R!'+str(bad2)+'>*]' else: magma_cond_option = '' self.code['cond'] = {'magma': 'Conductor(LSeries(C%s)); Factorization($1);'% magma_cond_option} self.code['disc'] = {'magma':'Discriminant(C); Factorization(Integers()!$1);'} self.code['igusa_clebsch'] = {'sage':'C.igusa_clebsch_invariants(); [factor(a) for a in _]', 'magma':'IgusaClebschInvariants(C); [Factorization(Integers()!a): a in $1];'} self.code['igusa'] = {'magma':'IgusaInvariants(C); [Factorization(Integers()!a): a in $1];'} self.code['g2'] = {'magma':'G2Invariants(C);'} self.code['aut'] = {'magma':'AutomorphismGroup(C); IdentifyGroup($1);'} self.code['autQbar'] = {'magma':'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);'} self.code['num_rat_wpts'] = {'magma':'#Roots(HyperellipticPolynomials(SimplifiedModel(C)));'} self.code['two_selmer'] = {'magma':'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);'} self.code['has_square_sha'] = {'magma':'HasSquareSha(Jacobian(C));'} self.code['locally_solvable'] = {'magma':'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsLocallyEverywhere(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);'} self.code['tor_struct'] = {'magma':'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);'}
def modn_exponent(n): """ given a nonzero integer n, returns the group exponent of (Z/nZ)* """ return lcm([(p - 1) * p**(e - 1) for (p, e) in factor(n)]) // (1 if n % 8 else 2)
def make_object(self, curve, endo, tama, ratpts, is_curve): from lmfdb.genus2_curves.main import url_for_curve_label # all information about the curve, its Jacobian, isogeny class, and endomorphisms goes in the data dictionary # most of the data from the database gets polished/formatted before we put it in the data dictionary data = self.data = {} data['label'] = curve['label'] if is_curve else curve['class'] data['slabel'] = data['label'].split('.') # set attributes common to curves and isogeny classes here data['Lhash'] = curve['Lhash'] data['cond'] = ZZ(curve['cond']) data['cond_factor_latex'] = web_latex(factor(int(data['cond']))) data['analytic_rank'] = ZZ(curve['analytic_rank']) data['st_group'] = curve['st_group'] data['st_group_link'] = st_link_by_name(1,4,data['st_group']) data['st0_group_name'] = st0_group_name(curve['real_geom_end_alg']) data['is_gl2_type'] = curve['is_gl2_type'] data['root_number'] = ZZ(curve['root_number']) data['lfunc_url'] = url_for("l_functions.l_function_genus2_page", cond=data['slabel'][0], x=data['slabel'][1]) data['bad_lfactors'] = literal_eval(curve['bad_lfactors']) data['bad_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['bad_lfactors']] if is_curve: # invariants specific to curve data['class'] = curve['class'] data['abs_disc'] = ZZ(curve['disc_key'][3:]) # use disc_key rather than abs_disc (will work when abs_disc > 2^63) data['disc'] = curve['disc_sign'] * curve['abs_disc'] data['min_eqn'] = literal_eval(curve['eqn']) data['min_eqn_display'] = list_to_min_eqn(data['min_eqn']) data['disc_factor_latex'] = web_latex(factor(data['disc'])) data['igusa_clebsch'] = [ZZ(a) for a in literal_eval(curve['igusa_clebsch_inv'])] data['igusa'] = [ZZ(a) for a in literal_eval(curve['igusa_inv'])] data['g2'] = [QQ(a) for a in literal_eval(curve['g2_inv'])] data['igusa_clebsch_factor_latex'] = [web_latex(zfactor(i)) for i in data['igusa_clebsch']] data['igusa_factor_latex'] = [ web_latex(zfactor(j)) for j in data['igusa'] ] data['aut_grp_id'] = curve['aut_grp_id'] data['geom_aut_grp_id'] = curve['geom_aut_grp_id'] data['num_rat_wpts'] = ZZ(curve['num_rat_wpts']) data['two_selmer_rank'] = ZZ(curve['two_selmer_rank']) data['has_square_sha'] = "square" if curve['has_square_sha'] else "twice a square" P = curve['non_solvable_places'] if len(P): sz = "except over " sz += ", ".join([QpName(p) for p in P]) last = " and" if len(P) > 2: last = ", and" sz = last.join(sz.rsplit(",",1)) else: sz = "everywhere" data['non_solvable_places'] = sz data['torsion_order'] = curve['torsion_order'] data['torsion_factors'] = [ ZZ(a) for a in literal_eval(curve['torsion_subgroup']) ] if len(data['torsion_factors']) == 0: data['torsion_subgroup'] = '\mathrm{trivial}' else: data['torsion_subgroup'] = ' \\times '.join([ '\Z/{%s}\Z' % n for n in data['torsion_factors'] ]) data['end_ring_base'] = endo['ring_base'] data['end_ring_geom'] = endo['ring_geom'] data['tama'] = '' for i in range(tama.count()): item = tama.next() if item['tamagawa_number'] > 0: tamgwnr = str(item['tamagawa_number']) else: tamgwnr = 'N/A' data['tama'] += tamgwnr + ' (p = ' + str(item['p']) + ')' if (i+1 < tama.count()): data['tama'] += ', ' if ratpts: if len(ratpts['rat_pts']): data['rat_pts'] = ', '.join(web_latex('(' +' : '.join(P) + ')') for P in ratpts['rat_pts']) data['rat_pts_v'] = 2 if ratpts['rat_pts_v'] else 1 # data['mw_rank'] = ratpts['mw_rank'] # data['mw_rank_v'] = ratpts['mw_rank_v'] else: data['rat_pts_v'] = 0 if curve['two_torsion_field'][0]: data['two_torsion_field_knowl'] = nf_display_knowl (curve['two_torsion_field'][0], getDBConnection(), field_pretty(curve['two_torsion_field'][0])) else: t = curve['two_torsion_field'] data['two_torsion_field_knowl'] = """splitting field of \(%s\) with Galois group %s"""%(intlist_to_poly(t[1]),group_display_knowl(t[2][0],t[2][1],getDBConnection())) else: # invariants specific to isogeny class curves_data = g2c_db_curves().find({"class" : curve['class']},{'_id':int(0),'label':int(1),'eqn':int(1),'disc_key':int(1)}).sort([("disc_key", ASCENDING), ("label", ASCENDING)]) if not curves_data: raise KeyError("No curves found in database for isogeny class %s of genus 2 curve %s." %(curve['class'],curve['label'])) data['curves'] = [ {"label" : c['label'], "equation_formatted" : list_to_min_eqn(literal_eval(c['eqn'])), "url": url_for_curve_label(c['label'])} for c in curves_data ] lfunc_data = g2c_db_lfunction_by_hash(curve['Lhash']) if not lfunc_data: raise KeyError("No Lfunction found in database for isogeny class of genus 2 curve %s." %curve['label']) if lfunc_data and lfunc_data.get('euler_factors'): data['good_lfactors'] = [[nth_prime(n+1),lfunc_data['euler_factors'][n]] for n in range(len(lfunc_data['euler_factors'])) if nth_prime(n+1) < 30 and (data['cond'] % nth_prime(n+1))] data['good_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['good_lfactors']] # Endomorphism data over QQ: data['gl2_statement_base'] = gl2_statement_base(endo['factorsRR_base'], r'\(\Q\)') data['factorsQQ_base'] = endo['factorsQQ_base'] data['factorsRR_base'] = endo['factorsRR_base'] data['end_statement_base'] = """Endomorphism %s over \(\Q\):<br>""" %("ring" if is_curve else "algebra") + \ end_statement(data['factorsQQ_base'], endo['factorsRR_base'], ring=data['end_ring_base'] if is_curve else None) # Field over which all endomorphisms are defined data['end_field_label'] = endo['fod_label'] data['end_field_poly'] = intlist_to_poly(endo['fod_coeffs']) data['end_field_statement'] = end_field_statement(data['end_field_label'], data['end_field_poly']) # Endomorphism data over QQbar: data['factorsQQ_geom'] = endo['factorsQQ_geom'] data['factorsRR_geom'] = endo['factorsRR_geom'] if data['end_field_label'] != '1.1.1.1': data['gl2_statement_geom'] = gl2_statement_base(data['factorsRR_geom'], r'\(\overline{\Q}\)') data['end_statement_geom'] = """Endomorphism %s over \(\overline{\Q}\):""" %("ring" if is_curve else "algebra") + \ end_statement(data['factorsQQ_geom'], data['factorsRR_geom'], field=r'\overline{\Q}', ring=data['end_ring_geom'] if is_curve else None) data['real_geom_end_alg_name'] = end_alg_name(curve['real_geom_end_alg']) # Endomorphism data over intermediate fields not already treated (only for curves, not necessarily isogeny invariant): if is_curve: data['end_lattice'] = (endo['lattice'])[1:-1] if data['end_lattice']: data['end_lattice_statement'] = end_lattice_statement(data['end_lattice']) # Field over which the Jacobian decomposes (base field if Jacobian is geometrically simple) data['is_simple_geom'] = endo['is_simple_geom'] data['split_field_label'] = endo['spl_fod_label'] data['split_field_poly'] = intlist_to_poly(endo['spl_fod_coeffs']) data['split_field_statement'] = split_field_statement(data['is_simple_geom'], data['split_field_label'], data['split_field_poly']) # Elliptic curve factors for non-simple Jacobians if not data['is_simple_geom']: data['split_coeffs'] = endo['spl_facs_coeffs'] if 'spl_facs_labels' in endo and len(endo['spl_facs_labels']) == len(endo['spl_facs_coeffs']): data['split_labels'] = endo['spl_facs_labels'] data['split_condnorms'] = endo['spl_facs_condnorms'] data['split_statement'] = split_statement(data['split_coeffs'], data.get('split_labels'), data['split_condnorms']) # Properties self.properties = properties = [('Label', data['label'])] if is_curve: self.plot = encode_plot(eqn_list_to_curve_plot(data['min_eqn'], data['rat_pts'].split(',') if 'rat_pts' in data else [])) plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format(self.plot) properties += [ (None, plot_link), ('Conductor',str(data['cond'])), ('Discriminant', str(data['disc'])), ] properties += [ ('Sato-Tate group', data['st_group_link']), ('\(\\End(J_{\\overline{\\Q}}) \\otimes \\R\)', '\(%s\)' % data['real_geom_end_alg_name']), ('\(\\overline{\\Q}\)-simple', bool_pretty(data['is_simple_geom'])), ('\(\mathrm{GL}_2\)-type', bool_pretty(data['is_gl2_type'])), ] # Friends self.friends = friends = [('L-function', data['lfunc_url'])] if is_curve: friends.append(('Isogeny class %s.%s' % (data['slabel'][0], data['slabel'][1]), url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1]))) for friend in g2c_db_lfunction_instances().find({'Lhash':data['Lhash']},{'_id':False,'url':True}): if 'url' in friend: add_friend (friends, lfunction_friend_from_url(friend['url'])) if 'urls' in friend: for url in friends['urls']: add_friend (friends, lfunction_friend_from_url(friend['url'])) if 'split_labels' in data: for friend_label in data['split_labels']: if is_curve: add_friend (friends, ("Elliptic curve " + friend_label, url_for_ec(friend_label))) else: add_friend (friends, ("EC isogeny class " + ec_label_class(friend_label), url_for_ec_class(friend_label))) if is_curve: friends.append(('Twists', url_for(".index_Q", g20 = str(data['g2'][0]), g21 = str(data['g2'][1]), g22 = str(data['g2'][2])))) # Breadcrumbs self.bread = bread = [ ('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('%s' % data['slabel'][0], url_for(".by_conductor", cond=data['slabel'][0])), ('%s' % data['slabel'][1], url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1])) ] if is_curve: bread += [ ('%s' % data['slabel'][2], url_for(".by_url_isogeny_class_discriminant", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2])), ('%s' % data['slabel'][3], url_for(".by_url_curve_label", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2], num=data['slabel'][3])) ] # Title self.title = "Genus 2 " + ("Curve " if is_curve else "Isogeny Class ") + data['label'] # Code snippets (only for curves) if not is_curve: return self.code = code = {} code['show'] = {'sage':'','magma':''} # use default show names code['curve'] = {'sage':'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s))'%(data['min_eqn'][0],data['min_eqn'][1]), 'magma':'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);'%(data['min_eqn'][0],data['min_eqn'][1])} if data['abs_disc'] % 4096 == 0: ind2 = [a[0] for a in data['bad_lfactors']].index(2) bad2 = data['bad_lfactors'][ind2][1] magma_cond_option = ': ExcFactors:=[*<2,Valuation('+str(data['cond'])+',2),R!'+str(bad2)+'>*]' else: magma_cond_option = '' code['cond'] = {'magma': 'Conductor(LSeries(C%s)); Factorization($1);'% magma_cond_option} code['disc'] = {'magma':'Discriminant(C); Factorization(Integers()!$1);'} code['igusa_clebsch'] = {'sage':'C.igusa_clebsch_invariants(); [factor(a) for a in _]', 'magma':'IgusaClebschInvariants(C); [Factorization(Integers()!a): a in $1];'} code['igusa'] = {'magma':'IgusaInvariants(C); [Factorization(Integers()!a): a in $1];'} code['g2'] = {'magma':'G2Invariants(C);'} code['aut'] = {'magma':'AutomorphismGroup(C); IdentifyGroup($1);'} code['autQbar'] = {'magma':'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);'} code['num_rat_wpts'] = {'magma':'#Roots(HyperellipticPolynomials(SimplifiedModel(C)));'} if ratpts: code['rat_pts'] = {'magma': '[' + ','.join(["C![%s,%s,%s]"%(p[0],p[1],p[2]) for p in ratpts['rat_pts']]) + '];' } code['two_selmer'] = {'magma':'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);'} code['has_square_sha'] = {'magma':'HasSquareSha(Jacobian(C));'} code['locally_solvable'] = {'magma':'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsEverywhereLocally(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);'} code['torsion_subgroup'] = {'magma':'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);'}
def list_to_factored_poly(s): return str(factor(PolynomialRing(ZZ, 't')(s))).replace('*','')
def find_curve(P, DB, NE, prec, sign_ap = None, magma = None, return_all = False, initial_data = None, ramification_at_infinity = None, **kwargs): r''' EXAMPLES: First example:: sage: from darmonpoints.findcurve import find_curve sage: find_curve(5,6,30,20) # long time # optional - magma # B = F<i,j,k>, with i^2 = -1 and j^2 = 3 ... '(1, 0, 1, -289, 1862)' A second example, now over a real quadratic:: sage: from darmonpoints.findcurve import find_curve sage: F.<r> = QuadraticField(5) sage: P = F.ideal(3/2*r + 1/2) sage: D = F.ideal(3) sage: find_curve(P,D,P*D,30,ramification_at_infinity = F.real_places()[:1]) # long time # optional - magma ... Now over a cubic of mixed signature:: sage: from darmonpoints.findcurve import find_curve sage: F.<r> = NumberField(x^3 -3) sage: P = F.ideal(r-2) sage: D = F.ideal(r-1) sage: find_curve(P,D,P*D,30) # long time # optional - magma ... ''' config = ConfigParser.ConfigParser() config.read('config.ini') param_dict = config_section_map(config, 'General') param_dict.update(config_section_map(config, 'FindCurve')) param_dict.update(kwargs) param = Bunch(**param_dict) # Get general parameters outfile = param.get('outfile') use_ps_dists = param.get('use_ps_dists',False) use_shapiro = param.get('use_shapiro',True) use_sage_db = param.get('use_sage_db',False) magma_seed = param.get('magma_seed',1515316) parallelize = param.get('parallelize',False) Up_method = param.get('up_method','naive') use_magma = param.get('use_magma',True) progress_bar = param.get('progress_bar',True) sign_at_infinity = param.get('sign_at_infinity',ZZ(1)) # Get find_curve specific parameters grouptype = param.get('grouptype') hecke_bound = param.get('hecke_bound',3) timeout = param.get('timeout',0) check_conductor = param.get('check_conductor',True) if initial_data is None: page_path = os.path.dirname(__file__) + '/KleinianGroups-1.0/klngpspec' if magma is None: from sage.interfaces.magma import Magma quit_when_done = True magma = Magma() else: quit_when_done = False if magma_seed is not None: magma.eval('SetSeed(%s)'%magma_seed) magma.attach_spec(page_path) magma.eval('Page_initialized := true') else: quit_when_done = False sys.setrecursionlimit(10**6) # global qE, Linv, G, Coh, phiE, xgen, xi1, xi2, Phi try: F = P.ring() Fdisc = F.discriminant() if not (P*DB).divides(NE): raise ValueError,'Conductor (NE) should be divisible by P*DB' p = ZZ(P.norm()).abs() except AttributeError: F = QQ P = ZZ(P) p = ZZ(P) Fdisc = ZZ(1) if NE % (P*DB) != 0: raise ValueError,'Conductor (NE) should be divisible by P*DB' Ncartan = kwargs.get('Ncartan',None) Np = NE / (P * DB) if Ncartan is not None: Np = Np / Ncartan**2 if use_ps_dists is None: use_ps_dists = False # More efficient our own implementation if not p.is_prime(): raise ValueError,'P (= %s) should be a prime, of inertia degree 1'%P working_prec = max([2 * prec + 10, 100]) sgninfty = 'plus' if sign_at_infinity == 1 else 'minus' fname = 'moments_%s_%s_%s_%s_%s_%s.sobj'%(Fdisc,p,DB,NE,sgninfty,prec) if outfile == 'log': outfile = '%s_%s_%s_%s_%s.log'%(P,NE,sgninfty,prec,datetime.datetime.now().strftime("%Y%m%d-%H%M%S")) outfile = outfile.replace('/','div') outfile = '/tmp/findcurve_' + outfile if F != QQ and ramification_at_infinity is None: if F.signature()[0] > 1: if F.signature()[1] == 1: ramification_at_infinity = F.real_places(prec = Infinity) # Totally 'definite' else: raise ValueError,'Please specify the ramification at infinity' elif F.signature()[0] == 1: if len(F.ideal(DB).factor()) % 2 == 0: ramification_at_infinity = [] # Split at infinity else: ramification_at_infinity = F.real_places(prec = Infinity) # Ramified at infinity else: ramification_at_infinity = None if outfile is not None: print("Partial results will be saved in %s"%outfile) if initial_data is not None: G,phiE = initial_data else: # Define the S-arithmetic group try: if F == QQ: abtuple = QuaternionAlgebra(DB).invariants() else: abtuple = quaternion_algebra_invariants_from_ramification(F,DB,ramification_at_infinity) G = BigArithGroup(P, abtuple, Np, use_sage_db = use_sage_db, grouptype = grouptype, magma = magma, seed = magma_seed, timeout = timeout, use_shapiro = use_shapiro, nscartan = Ncartan) except RuntimeError as e: if quit_when_done: magma.quit() mystr = str(e) if len(mystr) > 30: mystr = mystr[:14] + ' ... ' + mystr[-14:] if return_all: return ['Error when computing G: ' + mystr] else: return 'Error when computing G: ' + mystr # Define phiE, the cohomology class associated to the system of eigenvalues. Coh = ArithCoh(G) try: phiE = Coh.get_rational_cocycle(sign = sign_at_infinity,bound = hecke_bound,return_all = return_all,use_magma = True) except Exception as e: if quit_when_done: magma.quit() if return_all: return ['Error when finding cohomology class: ' + str(e)] else: return 'Error when finding cohomology class: ' + str(e) if use_sage_db: G.save_to_db() fwrite('Cohomology class found', outfile) try: ker = [G.inverse_shapiro(o) for o in G.get_homology_kernel()] except Exception as e: if quit_when_done: magma.quit() if return_all: return ['Problem calculating homology kernel: ' + str(e)] else: return 'Problem calculating homology kernel: ' + str(e) if not return_all: phiE = [phiE] ret_vals = [] for phi in phiE: try: Phi = get_overconvergent_class_quaternionic(P,phi,G,prec,sign_at_infinity,sign_ap,use_ps_dists,method = Up_method, progress_bar = progress_bar) except ValueError as e: ret_vals.append('Problem when getting overconvergent class: ' + str(e)) continue fwrite('Done overconvergent lift', outfile) # Find an element x of Gpn for not in the kernel of phi, # and such that both x and wp^-1 * x * wp are trivial in the abelianization of Gn. try: found = False for o in ker: phi_o = sum( [phi.evaluate(t**a) for t, a in o], 0 ) if use_shapiro: phi_o = phi_o.evaluate_at_identity() if phi_o != 0: found = True break if not found: raise RuntimeError('Cocycle evaluates always to zero') except Exception as e: ret_vals.append('Problem when choosing element in kernel: ' + str(e)) continue xgenlist = o found = False while not found: try: xi1, xi2 = lattice_homology_cycle(G,xgenlist,working_prec,outfile = outfile) found = True except PrecisionError: working_prec = 2 * working_prec verbose('Setting working_prec to %s'%working_prec) except Exception as e: ret_vals.append('Problem when computing homology cycle: ' + str(e)) verbose('Exception occurred: ' + str(e)) break if not found: continue try: qE1 = integrate_H1(G,xi1,Phi,1,method = 'moments',prec = working_prec, twist = False,progress_bar = progress_bar) qE2 = integrate_H1(G,xi2,Phi,1,method = 'moments',prec = working_prec, twist = True,progress_bar = progress_bar) except Exception as e: ret_vals.append('Problem with integration: %s'%str(e)) continue qE = qE1/qE2 qE = qE.add_bigoh(prec + qE.valuation()) Linv = qE.log(p_branch = 0)/qE.valuation() fwrite('Integral done. Now trying to recognize the curve', outfile) fwrite('F.<r> = NumberField(%s)'%(F.gen(0).minpoly()),outfile) fwrite('N_E = %s = %s'%(NE,factor(NE)),outfile) fwrite('D_B = %s = %s'%(DB,factor(DB)),outfile) fwrite('Np = %s = %s'%(Np,factor(Np)),outfile) if Ncartan is not None: fwrite('Ncartan = %s'%(Ncartan),outfile) fwrite('Calculation with p = %s and prec = %s+%s'%(P,prec,working_prec-prec),outfile) fwrite('qE = %s'%qE,outfile) fwrite('Linv = %s'%Linv,outfile) curve = discover_equation(qE,G._F_to_local,NE,prec,check_conductor = check_conductor) if curve is None: if quit_when_done: magma.quit() ret_vals.append('None') else: try: curve = curve.global_minimal_model() except AttributeError,NotImplementedError: pass fwrite('EllipticCurve(F, %s )'%(list(curve.a_invariants())), outfile) fwrite('=' * 60, outfile) ret_vals.append(str(curve.a_invariants()))
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 make_curve(self): # To start with the data fields of self are just those from # the database. We need to reformat these, construct the # and compute some further (easy) data about it. # # Weierstrass equation data = self.data = {} disc = ZZ(self.disc_sign) * ZZ(self.disc_key[3:]) # to deal with disc_key, uncomment line above and remove line below #disc = ZZ(self.disc_sign) * ZZ(self.abs_disc) data['disc'] = disc data['cond'] = ZZ(self.cond) data['min_eqn'] = list_to_min_eqn(self.min_eqn) data['disc_factor_latex'] = web_latex(factor(data['disc'])) data['cond_factor_latex'] = web_latex(factor(int(self.cond))) data['aut_grp'] = groupid_to_meaningful(self.aut_grp) data['geom_aut_grp'] = groupid_to_meaningful(self.geom_aut_grp) data['igusa_clebsch'] = [ZZ(a) for a in self.igusa_clebsch] if len(self.torsion) == 0: data['tor_struct'] = '\mathrm{trivial}' else: tor_struct = [ZZ(a) for a in self.torsion] data['tor_struct'] = ' \\times '.join(['\Z/{%s}\Z' % n for n in tor_struct]) isogeny_class = db_g2c().isogeny_classes.find_one({'label' : isog_label(self.label)}) for endalgtype in ['end_ring', 'rat_end_alg', 'real_end_alg', 'geom_end_ring', 'rat_geom_end_alg', 'real_geom_end_alg']: if endalgtype in isogeny_class: data[endalgtype + '_name'] = end_alg_name(isogeny_class[endalgtype]) else: data[endalgtype + '_name'] = '' data['geom_end_field'] = isogeny_class['geom_end_field'] if data['geom_end_field'] <> '': data['geom_end_field_name'] = field_pretty(data['geom_end_field']) else: data['geom_end_field_name'] = '' data['st_group_name'] = st_group_name(isogeny_class['st_group']) if isogeny_class['is_gl2_type']: data['is_gl2_type_name'] = 'yes' else: data['is_gl2_type_name'] = 'no' if 'is_simple' in isogeny_class: if isogeny_class['is_simple']: data['is_simple_name'] = 'yes' else: data['is_simple_name'] = 'no' else: data['is_simple_name'] = '?' if 'is_geom_simple' in isogeny_class: if isogeny_class['is_geom_simple']: data['is_geom_simple_name'] = 'yes' else: data['is_geom_simple_name'] = 'no' else: data['is_geom_simple_name'] = '?' x = self.label.split('.')[1] self.friends = [ ('Isogeny class %s' % isog_label(self.label), url_for(".by_double_iso_label", conductor = self.cond, iso_label = x)), ('L-function', url_for("l_functions.l_function_genus2_page", cond=self.cond,x=x)), ('Siegel modular form someday', '.')] self.downloads = [ ('Download Euler factors', '.')] iso = self.label.split('.')[1] num = '.'.join(self.label.split('.')[2:4]) self.plot = encode_plot(eqn_list_to_curve_plot(self.min_eqn)) self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot self.properties = [('Label', self.label), (None, self.plot_link), ('Conductor','%s' % self.cond), ('Discriminant', '%s' % data['disc']), ('Invariants', '%s </br> %s </br> %s </br> %s'% tuple(data['igusa_clebsch'])), ('Sato-Tate group', '\(%s\)' % data['st_group_name']), ('\(\mathrm{End}(J_{\overline{\Q}}) \otimes \R\)','\(%s\)' % data['real_geom_end_alg_name']), ('\(\mathrm{GL}_2\)-type','%s' % data['is_gl2_type_name'])] self.title = "Genus 2 Curve %s" % (self.label) self.bread = [ ('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('%s' % self.cond, url_for(".by_conductor", conductor=self.cond)), ('%s' % iso, url_for(".by_double_iso_label", conductor=self.cond, iso_label=iso)), ('Genus 2 curve %s' % num, url_for(".by_g2c_label", label=self.label))]
def make_object(self, curve, endo, is_curve): from lmfdb.genus2_curves.main import url_for_curve_label # all information about the curve, its Jacobian, isogeny class, and endomorphisms goes in the data dictionary # most of the data from the database gets polished/formatted before we put it in the data dictionary data = self.data = {} data['label'] = curve['label'] if is_curve else curve['class'] data['slabel'] = data['label'].split('.') # set attributes common to curves and isogeny classes here data['Lhash'] = curve['Lhash'] data['cond'] = ZZ(curve['cond']) data['cond_factor_latex'] = web_latex(factor(int(data['cond']))) data['analytic_rank'] = ZZ(curve['analytic_rank']) data['st_group'] = curve['st_group'] data['st_group_link'] = st_link_by_name(1, 4, data['st_group']) data['st0_group_name'] = st0_group_name(curve['real_geom_end_alg']) data['is_gl2_type'] = curve['is_gl2_type'] data['root_number'] = ZZ(curve['root_number']) data['lfunc_url'] = url_for("l_functions.l_function_genus2_page", cond=data['slabel'][0], x=data['slabel'][1]) data['bad_lfactors'] = literal_eval(curve['bad_lfactors']) data['bad_lfactors_pretty'] = [(c[0], list_to_factored_poly_otherorder(c[1])) for c in data['bad_lfactors']] if is_curve: # invariants specific to curve data['class'] = curve['class'] data['abs_disc'] = ZZ( curve['disc_key'][3:] ) # use disc_key rather than abs_disc (will work when abs_disc > 2^63) data['disc'] = curve['disc_sign'] * curve['abs_disc'] data['min_eqn'] = literal_eval(curve['eqn']) data['min_eqn_display'] = list_to_min_eqn(data['min_eqn']) data['disc_factor_latex'] = web_latex(factor(data['disc'])) data['igusa_clebsch'] = [ ZZ(a) for a in literal_eval(curve['igusa_clebsch_inv']) ] data['igusa'] = [ZZ(a) for a in literal_eval(curve['igusa_inv'])] data['g2'] = [QQ(a) for a in literal_eval(curve['g2_inv'])] data['igusa_clebsch_factor_latex'] = [ web_latex(zfactor(i)) for i in data['igusa_clebsch'] ] data['igusa_factor_latex'] = [ web_latex(zfactor(j)) for j in data['igusa'] ] data['aut_grp_id'] = curve['aut_grp_id'] data['geom_aut_grp_id'] = curve['geom_aut_grp_id'] data['num_rat_wpts'] = ZZ(curve['num_rat_wpts']) data['two_selmer_rank'] = ZZ(curve['two_selmer_rank']) data['has_square_sha'] = "square" if curve[ 'has_square_sha'] else "twice a square" data['locally_solvable'] = "yes" if curve[ 'locally_solvable'] else "no" data['torsion_order'] = curve['torsion_order'] data['torsion_factors'] = [ ZZ(a) for a in literal_eval(curve['torsion_subgroup']) ] if len(data['torsion_factors']) == 0: data['torsion_subgroup'] = '\mathrm{trivial}' else: data['torsion_subgroup'] = ' \\times '.join( ['\Z/{%s}\Z' % n for n in data['torsion_factors']]) data['end_ring_base'] = endo['ring_base'] data['end_ring_geom'] = endo['ring_geom'] else: # invariants specific to isogeny class curves_data = g2c_db_curves().find({ "class": curve['class'] }, { '_id': int(0), 'label': int(1), 'eqn': int(1), 'disc_key': int(1) }).sort([("disc_key", ASCENDING), ("label", ASCENDING)]) if not curves_data: raise KeyError( "No curves found in database for isogeny class %s of genus 2 curve %s." % (curve['class'], curve['label'])) data['curves'] = [{ "label": c['label'], "equation_formatted": list_to_min_eqn(literal_eval(c['eqn'])), "url": url_for_curve_label(c['label']) } for c in curves_data] lfunc_data = g2c_db_lfunction_by_hash(curve['Lhash']) if not lfunc_data: raise KeyError( "No Lfunction found in database for isogeny class of genus 2 curve %s." % curve['label']) if lfunc_data and lfunc_data.get('euler_factors'): data['good_lfactors'] = [ [nth_prime(n + 1), lfunc_data['euler_factors'][n]] for n in range(len(lfunc_data['euler_factors'])) if nth_prime(n + 1) < 30 and (data['cond'] % nth_prime(n + 1)) ] data['good_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['good_lfactors'] ] # Endomorphism data over QQ: data['gl2_statement_base'] = gl2_statement_base( endo['factorsRR_base'], r'\(\Q\)') data['factorsQQ_base'] = endo['factorsQQ_base'] data['factorsRR_base'] = endo['factorsRR_base'] data['end_statement_base'] = """Endomorphism %s over \(\Q\):<br>""" %("ring" if is_curve else "algebra") + \ end_statement(data['factorsQQ_base'], endo['factorsRR_base'], ring=data['end_ring_base'] if is_curve else None) # Field over which all endomorphisms are defined data['end_field_label'] = endo['fod_label'] data['end_field_poly'] = intlist_to_poly(endo['fod_coeffs']) data['end_field_statement'] = end_field_statement( data['end_field_label'], data['end_field_poly']) # Endomorphism data over QQbar: data['factorsQQ_geom'] = endo['factorsQQ_geom'] data['factorsRR_geom'] = endo['factorsRR_geom'] if data['end_field_label'] != '1.1.1.1': data['gl2_statement_geom'] = gl2_statement_base( data['factorsRR_geom'], r'\(\overline{\Q}\)') data['end_statement_geom'] = """Endomorphism %s over \(\overline{\Q}\):""" %("ring" if is_curve else "algebra") + \ end_statement(data['factorsQQ_geom'], data['factorsRR_geom'], field=r'\overline{\Q}', ring=data['end_ring_geom'] if is_curve else None) data['real_geom_end_alg_name'] = end_alg_name( curve['real_geom_end_alg']) # Endomorphism data over intermediate fields not already treated (only for curves, not necessarily isogeny invariant): if is_curve: data['end_lattice'] = (endo['lattice'])[1:-1] if data['end_lattice']: data['end_lattice_statement'] = end_lattice_statement( data['end_lattice']) # Field over which the Jacobian decomposes (base field if Jacobian is geometrically simple) data['is_simple_geom'] = endo['is_simple_geom'] data['split_field_label'] = endo['spl_fod_label'] data['split_field_poly'] = intlist_to_poly(endo['spl_fod_coeffs']) data['split_field_statement'] = split_field_statement( data['is_simple_geom'], data['split_field_label'], data['split_field_poly']) # Elliptic curve factors for non-simple Jacobians if not data['is_simple_geom']: data['split_coeffs'] = endo['spl_facs_coeffs'] if 'spl_facs_labels' in endo and len( endo['spl_facs_labels']) == len(endo['spl_facs_coeffs']): data['split_labels'] = endo['spl_facs_labels'] data['split_condnorms'] = endo['spl_facs_condnorms'] data['split_statement'] = split_statement(data['split_coeffs'], data.get('split_labels'), data['split_condnorms']) # Properties self.properties = properties = [('Label', data['label'])] if is_curve: self.plot = encode_plot(eqn_list_to_curve_plot(data['min_eqn'])) plot_link = '<img src="%s" width="200" height="150"/>' % self.plot properties += [ (None, plot_link), ('Conductor', str(data['cond'])), ('Discriminant', str(data['disc'])), ] properties += [ ('Sato-Tate group', data['st_group_link']), ('\(\\End(J_{\\overline{\\Q}}) \\otimes \\R\)', '\(%s\)' % data['real_geom_end_alg_name']), ('\(\\overline{\\Q}\)-simple', bool_pretty(data['is_simple_geom'])), ('\(\mathrm{GL}_2\)-type', bool_pretty(data['is_gl2_type'])), ] # Friends self.friends = friends = [('L-function', data['lfunc_url'])] if is_curve: friends.append(('Isogeny class %s.%s' % (data['slabel'][0], data['slabel'][1]), url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1]))) for friend in g2c_db_lfunction_instances().find( {'Lhash': data['Lhash']}, { '_id': False, 'url': True }): if 'url' in friend: add_friend(friends, lfunction_friend_from_url(friend['url'])) if 'urls' in friend: for url in friends['urls']: add_friend(friends, lfunction_friend_from_url(friend['url'])) if 'split_labels' in data: for friend_label in data['split_labels']: if is_curve: add_friend(friends, ("Elliptic curve " + friend_label, url_for_ec(friend_label))) else: add_friend( friends, ("EC isogeny class " + ec_label_class(friend_label), url_for_ec_class(friend_label))) if is_curve: friends.append(('Twists', url_for(".index_Q", g20=str(data['g2'][0]), g21=str(data['g2'][1]), g22=str(data['g2'][2])))) # Breadcrumbs self.bread = bread = [('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('%s' % data['slabel'][0], url_for(".by_conductor", cond=data['slabel'][0])), ('%s' % data['slabel'][1], url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1]))] if is_curve: bread += [('%s' % data['slabel'][2], url_for(".by_url_isogeny_class_discriminant", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2])), ('%s' % data['slabel'][3], url_for(".by_url_curve_label", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2], num=data['slabel'][3]))] # Title self.title = "Genus 2 " + ("Curve " if is_curve else "Isogeny Class ") + data['label'] # Code snippets (only for curves) if not is_curve: return self.code = code = {} code['show'] = {'sage': '', 'magma': ''} # use default show names code['curve'] = { 'sage': 'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s))' % (data['min_eqn'][0], data['min_eqn'][1]), 'magma': 'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);' % (data['min_eqn'][0], data['min_eqn'][1]) } if data['abs_disc'] % 4096 == 0: ind2 = [a[0] for a in data['bad_lfactors']].index(2) bad2 = data['bad_lfactors'][ind2][1] magma_cond_option = ': ExcFactors:=[*<2,Valuation(' + str( data['cond']) + ',2),R!' + str(bad2) + '>*]' else: magma_cond_option = '' code['cond'] = { 'magma': 'Conductor(LSeries(C%s)); Factorization($1);' % magma_cond_option } code['disc'] = { 'magma': 'Discriminant(C); Factorization(Integers()!$1);' } code['igusa_clebsch'] = { 'sage': 'C.igusa_clebsch_invariants(); [factor(a) for a in _]', 'magma': 'IgusaClebschInvariants(C); [Factorization(Integers()!a): a in $1];' } code['igusa'] = { 'magma': 'IgusaInvariants(C); [Factorization(Integers()!a): a in $1];' } code['g2'] = {'magma': 'G2Invariants(C);'} code['aut'] = {'magma': 'AutomorphismGroup(C); IdentifyGroup($1);'} code['autQbar'] = { 'magma': 'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);' } code['num_rat_wpts'] = { 'magma': '#Roots(HyperellipticPolynomials(SimplifiedModel(C)));' } code['two_selmer'] = { 'magma': 'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);' } code['has_square_sha'] = {'magma': 'HasSquareSha(Jacobian(C));'} code['locally_solvable'] = { 'magma': 'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsLocallyEverywhere(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);' } code['torsion_subgroup'] = { 'magma': 'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);' }
def make_curve(self): # To start with the data fields of self are just those from the # databases. We reformat these, while computing some further (easy) # data about the curve on the fly. # Initialize data: data = self.data = {} endodata = self.endodata = {} # Polish data from database before putting it into the data dictionary: disc = ZZ(self.disc_sign) * ZZ(self.disc_key[3:]) # to deal with disc_key, uncomment line above and comment line below #disc = ZZ(self.disc_sign) * ZZ(self.abs_disc) data['disc'] = disc data['cond'] = ZZ(self.cond) data['min_eqn'] = self.min_eqn data['min_eqn_display'] = list_to_min_eqn(self.min_eqn) data['disc_factor_latex'] = web_latex(factor(data['disc'])) data['cond_factor_latex'] = web_latex(factor(int(self.cond))) data['aut_grp'] = groupid_to_meaningful(self.aut_grp) data['geom_aut_grp'] = groupid_to_meaningful(self.geom_aut_grp) data['igusa_clebsch'] = [ZZ(a) for a in self.igusa_clebsch] data['igusa'] = [ZZ(a) for a in self.igusa] data['g2'] = self.g2inv data['ic_norm'] = data['igusa_clebsch'] data['igusa_norm'] = data['igusa'] # Should we ever want to normalize the invariants further, then # uncomment the following lines: #data['ic_norm'] = normalize_invariants(data['igusa_clebsch'], [2, 4, 6, # 10]) #data['igusa_norm'] = normalize_invariants(data['igusa'], [2, 4, 6, 8, # 10]) data['ic_norm_factor_latex'] = [ web_latex(zfactor(i)) for i in data['ic_norm'] ] data['igusa_norm_factor_latex'] = [ web_latex(zfactor(j)) for j in data['igusa_norm'] ] data['num_rat_wpts'] = ZZ(self.num_rat_wpts) data['two_selmer_rank'] = ZZ(self.two_selmer_rank) if len(self.torsion) == 0: data['tor_struct'] = '\mathrm{trivial}' else: tor_struct = [ZZ(a) for a in self.torsion] data['tor_struct'] = ' \\times '.join( ['\Z/{%s}\Z' % n for n in tor_struct]) # Data derived from Sato-Tate group: isogeny_class = db_g2c().isogeny_classes.find_one( {'label': isog_label(self.label)}) st_data = get_st_data(isogeny_class) for key in st_data.keys(): data[key] = st_data[key] # GL_2 statement over the base field endodata['gl2_statement_base'] = \ gl2_statement_base(self.factorsRR_base, r'\(\Q\)') # NOTE: In what follows there is some copying of code and data that is # stupid from the point of view of efficiency but likely better from # that of maintenance. # Endomorphism data over QQ: endodata['factorsQQ_base'] = self.factorsQQ_base endodata['factorsRR_base'] = self.factorsRR_base endodata['ring_base'] = self.ring_base endodata['endo_statement_base'] = \ """Endomorphism ring over \(\Q\):""" + \ endo_statement(endodata['factorsQQ_base'], endodata['factorsRR_base'], endodata['ring_base'], r'') # Field of definition data: endodata['fod_label'] = self.fod_label endodata['fod_poly'] = intlist_to_poly(self.fod_coeffs) endodata['fod_statement'] = fod_statement(endodata['fod_label'], endodata['fod_poly']) # Endomorphism data over QQbar: endodata['factorsQQ_geom'] = self.factorsQQ_geom endodata['factorsRR_geom'] = self.factorsRR_geom endodata['ring_geom'] = self.ring_geom if self.fod_label != '1.1.1.1': endodata['gl2_statement_geom'] = \ gl2_statement_base(self.factorsRR_geom, r'\(\overline{\Q}\)') endodata['endo_statement_geom'] = \ """Endomorphism ring over \(\overline{\Q}\):""" + \ endo_statement(endodata['factorsQQ_geom'], endodata['factorsRR_geom'], endodata['ring_geom'], r'\overline{\Q}') # Full endomorphism lattice minus entries already treated: N = len(self.lattice) endodata['lattice'] = (self.lattice)[1:N - 1] if endodata['lattice']: endodata['lattice_statement_preamble'] = \ lattice_statement_preamble() endodata['lattice_statement'] = \ lattice_statement(endodata['lattice']) # Splitting field description: #endodata['is_simple_base'] = self.is_simple_base endodata['is_simple_geom'] = self.is_simple_geom endodata['spl_fod_label'] = self.spl_fod_label endodata['spl_fod_poly'] = intlist_to_poly(self.spl_fod_coeffs) endodata['spl_fod_statement'] = \ spl_fod_statement(endodata['is_simple_geom'], endodata['spl_fod_label'], endodata['spl_fod_poly']) # Isogeny factors: if not endodata['is_simple_geom']: endodata['spl_facs_coeffs'] = self.spl_facs_coeffs # This could be done non-uniformly as well... later. if len(self.spl_facs_labels) == len(self.spl_facs_coeffs): endodata['spl_facs_labels'] = self.spl_facs_labels else: endodata['spl_facs_labels'] = [ '' for coeffs in self.spl_facs_coeffs ] endodata['spl_facs_condnorms'] = self.spl_facs_condnorms endodata['spl_statement'] = \ spl_statement(endodata['spl_facs_coeffs'], endodata['spl_facs_labels'], endodata['spl_facs_condnorms']) # Title self.title = "Genus 2 Curve %s" % (self.label) # Lady Gaga box self.plot = encode_plot(eqn_list_to_curve_plot(self.min_eqn)) self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot self.properties = [ ('Label', self.label), (None, self.plot_link), ('Conductor', '%s' % self.cond), ('Discriminant', '%s' % data['disc']), ('Invariants', '%s </br> %s </br> %s </br> %s' % tuple(data['ic_norm'])), ('Sato-Tate group', '\(%s\)' % data['st_group_name']), ('\(%s\)' % data['real_geom_end_alg_disp'][0], '\(%s\)' % data['real_geom_end_alg_disp'][1]), ('\(\mathrm{GL}_2\)-type', '%s' % data['is_gl2_type_name']) ] x = self.label.split('.')[1] self.friends = [ ('Isogeny class %s' % isog_label(self.label), url_for(".by_double_iso_label", conductor=self.cond, iso_label=x)), ('L-function', url_for("l_functions.l_function_genus2_page", cond=self.cond, x=x)), ('Twists', url_for(".index_Q", g20=self.g2inv[0], g21=self.g2inv[1], g22=self.g2inv[2])) #('Twists2', # url_for(".index_Q", # igusa_clebsch = str(self.igusa_clebsch))) #doesn't work. #('Siegel modular form someday', '.') ] self.downloads = [('Download all stored data', '.')] # Breadcrumbs iso = self.label.split('.')[1] num = '.'.join(self.label.split('.')[2:4]) self.bread = [('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('%s' % self.cond, url_for(".by_conductor", conductor=self.cond)), ('%s' % iso, url_for(".by_double_iso_label", conductor=self.cond, iso_label=iso)), ('Genus 2 curve %s' % num, url_for(".by_g2c_label", label=self.label))] # Make code that is used on the page: self.make_code_snippets()
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 main5(): n = 32295194023343 e = 29468811804857 d = 11127763319273 print(crack_given_decrypt(n, e * d - 1)) print(factor(n))
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 general_webpagedata(self): info = {} try: info['support'] = self.support except AttributeError: info['support'] = '' info['Ltype'] = self.Ltype() info['label'] = self.label info['credit'] = self.credit info['degree'] = int(self.degree) info['conductor'] = self.level if not is_prime(int(self.level)): info['conductor_factored'] = latex(factor(int(self.level))) info['sign'] = "$" + styleTheSign(self.sign) + "$" info['algebraic'] = self.algebraic if self.selfdual: info['selfdual'] = 'yes' else: info['selfdual'] = 'no' if self.primitive: info['primitive'] = 'yes' else: info['primitive'] = 'no' info['dirichlet'] = lfuncDShtml(self, "analytic") # Hack, fix this more general? info['dirichlet'] = info['dirichlet'].replace('*I','<em>i</em>') info['eulerproduct'] = lfuncEPtex(self, "abstract") info['functionalequation'] = lfuncFEtex(self, "analytic") info['functionalequationSelberg'] = lfuncFEtex(self, "selberg") if hasattr(self, 'positive_zeros'): info['positive_zeros'] = self.positive_zeros info['negative_zeros'] = self.negative_zeros if hasattr(self, 'plot'): info['plot'] = self.plot if hasattr(self, 'factorization'): info['factorization'] = self.factorization if self.fromDB and self.algebraic: info['dirichlet_arithmetic'] = lfuncDShtml(self, "arithmetic") info['eulerproduct_arithmetic'] = lfuncEPtex(self, "arithmetic") info['functionalequation_arithmetic'] = lfuncFEtex(self, "arithmetic") if self.motivic_weight % 2 == 0: arith_center = "\\frac{" + str(1 + self.motivic_weight) + "}{2}" else: arith_center = str(ZZ(1)/2 + self.motivic_weight/2) svt_crit = specialValueTriple(self, 0.5, '\\frac12',arith_center) info['sv_critical'] = svt_crit[0] + "\\ =\\ " + svt_crit[2] info['sv_critical_analytic'] = [svt_crit[0], svt_crit[2]] info['sv_critical_arithmetic'] = [svt_crit[1], svt_crit[2]] if self.motivic_weight % 2 == 1: arith_edge = "\\frac{" + str(2 + self.motivic_weight) + "}{2}" else: arith_edge = str(ZZ(1) + self.motivic_weight/2) svt_edge = specialValueTriple(self, 1, '1',arith_edge) info['sv_edge'] = svt_edge[0] + "\\ =\\ " + svt_edge[2] info['sv_edge_analytic'] = [svt_edge[0], svt_edge[2]] info['sv_edge_arithmetic'] = [svt_edge[1], svt_edge[2]] info['st_group'] = self.st_group info['st_link'] = self.st_link info['rank'] = self.order_of_vanishing info['motivic_weight'] = self.motivic_weight elif self.Ltype() != "artin" or (self.Ltype() == "artin" and self.sign != 0): try: info['sv_edge'] = specialValueString(self, 1, '1') info['sv_critical'] = specialValueString(self, 0.5, '1/2') except: info['sv_critical'] = "L(1/2): not computed" info['sv_edge'] = "L(1): not computed" return info
def make_curve(self): # To start with the data fields of self are just those from # the database. We need to reformat these, construct the # and compute some further (easy) data about it. # # Weierstrass equation data = self.data = {} disc = ZZ(self.disc_sign) * ZZ(self.disc_key[3:]) # to deal with disc_key, uncomment line above and remove line below #disc = ZZ(self.disc_sign) * ZZ(self.abs_disc) data['disc'] = disc data['cond'] = ZZ(self.cond) data['min_eqn'] = self.min_eqn data['min_eqn_display'] = list_to_min_eqn(self.min_eqn) data['disc_factor_latex'] = web_latex(factor(data['disc'])) data['cond_factor_latex'] = web_latex(factor(int(self.cond))) data['aut_grp'] = groupid_to_meaningful(self.aut_grp) data['geom_aut_grp'] = groupid_to_meaningful(self.geom_aut_grp) data['igusa_clebsch'] = [ZZ(a) for a in self.igusa_clebsch] data['igusa'] = igusa_clebsch_to_igusa(data['igusa_clebsch']) data['g2'] = igusa_to_g2(data['igusa']) data['ic_norm'] = normalize_invariants(data['igusa_clebsch'],[1,2,3,5]) data['igusa_norm'] = normalize_invariants(data['igusa'],[1,2,3,4,5]) data['ic_norm_factor_latex'] = [web_latex(zfactor(i)) for i in data['ic_norm']] data['igusa_norm_factor_latex'] = [web_latex(zfactor(j)) for j in data['igusa_norm']] data['num_rat_wpts'] = ZZ(self.num_rat_wpts) data['two_selmer_rank'] = ZZ(self.two_selmer_rank) if len(self.torsion) == 0: data['tor_struct'] = '\mathrm{trivial}' else: tor_struct = [ZZ(a) for a in self.torsion] data['tor_struct'] = ' \\times '.join(['\Z/{%s}\Z' % n for n in tor_struct]) isogeny_class = db_g2c().isogeny_classes.find_one({'label' : isog_label(self.label)}) end_data = get_end_data(isogeny_class) for key in end_data.keys(): data[key] = end_data[key] x = self.label.split('.')[1] self.make_code_snippets() self.friends = [ ('Isogeny class %s' % isog_label(self.label), url_for(".by_double_iso_label", conductor = self.cond, iso_label = x)), ('L-function', url_for("l_functions.l_function_genus2_page", cond=self.cond,x=x)), ('Twists',url_for(".index_Q", ic0 = self.igusa_clebsch[0], ic1 = self.igusa_clebsch[1],ic2 = self.igusa_clebsch[2],ic3 = self.igusa_clebsch[3])), #('Twists2',url_for(".index_Q", igusa_clebsch = str(self.igusa_clebsch))) #doesn't work. #('Siegel modular form someday', '.') ] self.downloads = [ ('Download all stored data', '.')] iso = self.label.split('.')[1] num = '.'.join(self.label.split('.')[2:4]) self.plot = encode_plot(eqn_list_to_curve_plot(self.min_eqn)) self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot self.properties = [('Label', self.label), (None, self.plot_link), ('Conductor','%s' % self.cond), ('Discriminant', '%s' % data['disc']), ('Invariants', '%s </br> %s </br> %s </br> %s'% tuple(data['ic_norm'])), ('Sato-Tate group', '\(%s\)' % data['st_group_name']), ('\(%s\)' % data['real_geom_end_alg_name'][0],'\(%s\)' % data['real_geom_end_alg_name'][1]), ('\(\mathrm{GL}_2\)-type','%s' % data['is_gl2_type_name'])] self.title = "Genus 2 Curve %s" % (self.label) self.bread = [ ('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('%s' % self.cond, url_for(".by_conductor", conductor=self.cond)), ('%s' % iso, url_for(".by_double_iso_label", conductor=self.cond, iso_label=iso)), ('Genus 2 curve %s' % num, url_for(".by_g2c_label", label=self.label))]
def list_to_factored_poly(s): return str(factor(PolynomialRing(ZZ, 't')(s))).replace('*', '')
def modn_exponent(n): """ given a nonzero integer n, returns the group exponent of (Z/nZ)* """ return lcm( [ (p-1)*p**(e-1) for (p,e) in factor(n) ] ) // (1 if n%8 else 2)
def make_curve(self): # To start with the data fields of self are just those from the # databases. We reformat these, while computing some further (easy) # data about the curve on the fly. # Initialize data: data = self.data = {} endodata = self.endodata = {} # Polish data from database before putting it into the data dictionary: disc = ZZ(self.disc_sign) * ZZ(self.disc_key[3:]) # to deal with disc_key, uncomment line above and comment line below #disc = ZZ(self.disc_sign) * ZZ(self.abs_disc) data['disc'] = disc data['cond'] = ZZ(self.cond) data['min_eqn'] = self.min_eqn data['min_eqn_display'] = list_to_min_eqn(self.min_eqn) data['disc_factor_latex'] = web_latex(factor(data['disc'])) data['cond_factor_latex'] = web_latex(factor(int(self.cond))) data['aut_grp'] = groupid_to_meaningful(self.aut_grp) data['geom_aut_grp'] = groupid_to_meaningful(self.geom_aut_grp) data['igusa_clebsch'] = [ZZ(a) for a in self.igusa_clebsch] data['igusa'] = [ZZ(a) for a in self.igusa] data['g2'] = self.g2inv data['ic_norm'] = data['igusa_clebsch'] data['igusa_norm'] = data['igusa'] # Should we ever want to normalize the invariants further, then # uncomment the following lines: #data['ic_norm'] = normalize_invariants(data['igusa_clebsch'], [2, 4, 6, # 10]) #data['igusa_norm'] = normalize_invariants(data['igusa'], [2, 4, 6, 8, # 10]) data['ic_norm_factor_latex'] = [web_latex(zfactor(i)) for i in data['ic_norm']] data['igusa_norm_factor_latex'] = [ web_latex(zfactor(j)) for j in data['igusa_norm'] ] data['num_rat_wpts'] = ZZ(self.num_rat_wpts) data['two_selmer_rank'] = ZZ(self.two_selmer_rank) data['analytic_rank'] = ZZ(self.analytic_rank) data['has_square_sha'] = "square" if self.has_square_sha else "twice a square" data['locally_solvable'] = "yes" if self.locally_solvable else "no" if len(self.torsion) == 0: data['tor_struct'] = '\mathrm{trivial}' else: tor_struct = [ ZZ(a) for a in self.torsion ] data['tor_struct'] = ' \\times '.join([ '\Z/{%s}\Z' % n for n in tor_struct ]) # Data derived from Sato-Tate group: isogeny_class = g2cdb().isogeny_classes.find_one({'label' : isog_label(self.label)}) st_data = get_st_data(isogeny_class) for key in st_data.keys(): data[key] = st_data[key] # GL_2 statement over the base field endodata['gl2_statement_base'] = \ gl2_statement_base(self.factorsRR_base, r'\(\Q\)') # NOTE: In what follows there is some copying of code and data that is # stupid from the point of view of efficiency but likely better from # that of maintenance. # Endomorphism data over QQ: endodata['factorsQQ_base'] = self.factorsQQ_base endodata['factorsRR_base'] = self.factorsRR_base endodata['ring_base'] = self.ring_base endodata['endo_statement_base'] = \ """Endomorphism ring over \(\Q\):""" + \ endo_statement(endodata['factorsQQ_base'], endodata['factorsRR_base'], endodata['ring_base'], r'') # Field of definition data: endodata['fod_label'] = self.fod_label endodata['fod_poly'] = intlist_to_poly(self.fod_coeffs) endodata['fod_statement'] = fod_statement(endodata['fod_label'], endodata['fod_poly']) # Endomorphism data over QQbar: endodata['factorsQQ_geom'] = self.factorsQQ_geom endodata['factorsRR_geom'] = self.factorsRR_geom endodata['ring_geom'] = self.ring_geom if self.fod_label != '1.1.1.1': endodata['gl2_statement_geom'] = \ gl2_statement_base(self.factorsRR_geom, r'\(\overline{\Q}\)') endodata['endo_statement_geom'] = \ """Endomorphism ring over \(\overline{\Q}\):""" + \ endo_statement(endodata['factorsQQ_geom'], endodata['factorsRR_geom'], endodata['ring_geom'], r'\overline{\Q}') # Full endomorphism lattice minus entries already treated: N = len(self.lattice) endodata['lattice'] = (self.lattice)[1:N - 1] if endodata['lattice']: endodata['lattice_statement_preamble'] = \ lattice_statement_preamble() endodata['lattice_statement'] = \ lattice_statement(endodata['lattice']) # Splitting field description: #endodata['is_simple_base'] = self.is_simple_base endodata['is_simple_geom'] = self.is_simple_geom endodata['spl_fod_label'] = self.spl_fod_label endodata['spl_fod_poly'] = intlist_to_poly(self.spl_fod_coeffs) endodata['spl_fod_statement'] = \ spl_fod_statement(endodata['is_simple_geom'], endodata['spl_fod_label'], endodata['spl_fod_poly']) # Isogeny factors: if not endodata['is_simple_geom']: endodata['spl_facs_coeffs'] = self.spl_facs_coeffs # This could be done non-uniformly as well... later. if len(self.spl_facs_labels) == len(self.spl_facs_coeffs): endodata['spl_facs_labels'] = self.spl_facs_labels else: endodata['spl_facs_labels'] = ['' for coeffs in self.spl_facs_coeffs] endodata['spl_facs_condnorms'] = self.spl_facs_condnorms endodata['spl_statement'] = \ spl_statement(endodata['spl_facs_coeffs'], endodata['spl_facs_labels'], endodata['spl_facs_condnorms']) # Title self.title = "Genus 2 Curve %s" % (self.label) # Lady Gaga box self.plot = encode_plot(eqn_list_to_curve_plot(self.min_eqn)) self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot self.properties = [ ('Label', self.label), (None, self.plot_link), ('Conductor','%s' % self.cond), ('Discriminant', '%s' % data['disc']), ('Invariants', '%s </br> %s </br> %s </br> %s' % tuple(data['ic_norm'])), ('Sato-Tate group', data['st_group_href']), ('\(%s\)' % data['real_geom_end_alg_disp'][0], '\(%s\)' % data['real_geom_end_alg_disp'][1]), ('\(\mathrm{GL}_2\)-type','%s' % data['is_gl2_type_name'])] x = self.label.split('.')[1] self.friends = [ ('Isogeny class %s' % isog_label(self.label), url_for(".by_double_iso_label", conductor = self.cond, iso_label = x)), ('L-function', url_for("l_functions.l_function_genus2_page", cond=self.cond,x=x)), ('Twists', url_for(".index_Q", g20 = self.g2inv[0], g21 = self.g2inv[1], g22 = self.g2inv[2])) #('Siegel modular form someday', '.') ] if not endodata['is_simple_geom']: self.friends += [('Elliptic curve %s' % lab,url_for_ec(lab)) for lab in endodata['spl_facs_labels'] if lab != ''] #self.downloads = [('Download all stored data', '.')] # Breadcrumbs iso = self.label.split('.')[1] num = '.'.join(self.label.split('.')[2:4]) self.bread = [ ('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('%s' % self.cond, url_for(".by_conductor", conductor=self.cond)), ('%s' % iso, url_for(".by_double_iso_label", conductor=self.cond, iso_label=iso)), ('Genus 2 curve %s' % num, url_for(".by_g2c_label", label=self.label)) ] # Make code that is used on the page: self.make_code_snippets()
def make_curve(self): # To start with the data fields of self are just those from the # databases. We reformat these, while computing some further (easy) # data about the curve on the fly. # Get data from databases: data = self.data = {} endodata = self.endodata = {} # Polish data from database before putting it into the data dictionary: disc = ZZ(self.disc_sign) * ZZ(self.disc_key[3:]) # to deal with disc_key, uncomment line above and comment line below #disc = ZZ(self.disc_sign) * ZZ(self.abs_disc) data['disc'] = disc data['cond'] = ZZ(self.cond) data['min_eqn'] = self.min_eqn data['min_eqn_display'] = list_to_min_eqn(self.min_eqn) data['disc_factor_latex'] = web_latex(factor(data['disc'])) data['cond_factor_latex'] = web_latex(factor(int(self.cond))) data['aut_grp'] = groupid_to_meaningful(self.aut_grp) data['geom_aut_grp'] = groupid_to_meaningful(self.geom_aut_grp) data['igusa_clebsch'] = [ZZ(a) for a in self.igusa_clebsch] data['igusa'] = igusa_clebsch_to_igusa(data['igusa_clebsch']) data['g2'] = igusa_to_g2(data['igusa']) data['ic_norm'] = normalize_invariants(data['igusa_clebsch'],[1,2,3,5]) data['igusa_norm'] = normalize_invariants(data['igusa'],[1,2,3,4,5]) data['ic_norm_factor_latex'] = [web_latex(zfactor(i)) for i in data['ic_norm']] data['igusa_norm_factor_latex'] = [web_latex(zfactor(j)) for j in data['igusa_norm']] data['num_rat_wpts'] = ZZ(self.num_rat_wpts) data['two_selmer_rank'] = ZZ(self.two_selmer_rank) if len(self.torsion) == 0: data['tor_struct'] = '\mathrm{trivial}' else: tor_struct = [ZZ(a) for a in self.torsion] data['tor_struct'] = ' \\times '.join(['\Z/{%s}\Z' % n for n in tor_struct]) # Data from old endomorphism functionality, used in isogeny class as # well. Calls the get_end_data function above. isogeny_class = db_g2c().isogeny_classes.find_one({'label' : isog_label(self.label)}) end_data = get_end_data(isogeny_class) for key in end_data.keys(): data[key] = end_data[key] # GL_2 statement over the base field endodata['gl2_statement_base'] = gl2_statement(self.factorsRR_base, r'\(\Q\)') # NOTE: In what follows there is some copying of code and data that is # stupid from the point of view of efficiency but likely better from # that of maintenance. # Endomorphism data over QQ: endodata['factorsQQ_base'] = self.factorsQQ_base endodata['factorsRR_base'] = self.factorsRR_base endodata['ring_base'] = self.ring_base endodata['endo_statement_base'] = \ """Endomorphism ring over \(\Q\):<br>""" + \ endo_statement(endodata['factorsQQ_base'], endodata['factorsRR_base'], endodata['ring_base'], r'') # Field of definition data: endodata['fod_label'] = self.fod_label endodata['fod_poly'] = intlist_to_poly(self.fod_coeffs) endodata['fod_statement'] = fod_statement(endodata['fod_label'], endodata['fod_poly']) # Endomorphism data over QQbar: endodata['factorsQQ_geom'] = self.factorsQQ_geom endodata['factorsRR_geom'] = self.factorsRR_geom endodata['ring_geom'] = self.ring_geom if self.fod_label != '1.1.1.1': endodata['endo_statement_geom'] = \ """Endomorphism ring over \(\overline{\Q}\):<br>""" + \ endo_statement(endodata['factorsQQ_geom'], endodata['factorsRR_geom'], endodata['ring_geom'], r'\overline{\Q}') # Full endomorphism lattice: endodata['lattice'] = self.lattice[1:len(self.lattice) - 1] if endodata['lattice']: endodata['lattice_statement_preamble'] = \ lattice_statement_preamble() endodata['lattice_statement'] = \ lattice_statement(endodata['lattice']) # Splitting field description: #endodata['is_simple_base'] = self.is_simple_base endodata['is_simple_geom'] = self.is_simple_geom endodata['spl_fod_label'] = self.spl_fod_label endodata['spl_fod_poly'] = intlist_to_poly(self.spl_fod_coeffs) endodata['spl_fod_statement'] = \ spl_fod_statement(endodata['is_simple_geom'], endodata['spl_fod_label'], endodata['spl_fod_poly']) # Isogeny factors: if not endodata['is_simple_geom']: endodata['spl_facs_coeffs'] = self.spl_facs_coeffs # This could be done non-uniformly as well... later. if len(self.spl_facs_labels) == len(self.spl_facs_coeffs): endodata['spl_facs_labels'] = self.spl_facs_labels else: endodata['spl_facs_labels'] = ['' for coeffs in self.spl_facs_coeffs] endodata['spl_facs_condnorms'] = self.spl_facs_condnorms endodata['spl_statement'] = \ spl_statement(endodata['spl_facs_coeffs'], endodata['spl_facs_labels'], endodata['spl_facs_condnorms']) x = self.label.split('.')[1] self.make_code_snippets() self.friends = [ ('Isogeny class %s' % isog_label(self.label), url_for(".by_double_iso_label", conductor = self.cond, iso_label = x)), ('L-function', url_for("l_functions.l_function_genus2_page", cond=self.cond,x=x)), ('Twists',url_for(".index_Q", ic0 = self.igusa_clebsch[0], ic1 = self.igusa_clebsch[1],ic2 = self.igusa_clebsch[2],ic3 = self.igusa_clebsch[3])), #('Twists2',url_for(".index_Q", igusa_clebsch = str(self.igusa_clebsch))) #doesn't work. #('Siegel modular form someday', '.') ] self.downloads = [ ('Download all stored data', '.')] iso = self.label.split('.')[1] num = '.'.join(self.label.split('.')[2:4]) self.plot = encode_plot(eqn_list_to_curve_plot(self.min_eqn)) self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot self.properties = [('Label', self.label), (None, self.plot_link), ('Conductor','%s' % self.cond), ('Discriminant', '%s' % data['disc']), ('Invariants', '%s </br> %s </br> %s </br> %s'% tuple(data['ic_norm'])), ('Sato-Tate group', '\(%s\)' % data['st_group_name']), ('\(%s\)' % data['real_geom_end_alg_name'][0],'\(%s\)' % data['real_geom_end_alg_name'][1]), ('\(\mathrm{GL}_2\)-type','%s' % data['is_gl2_type_name'])] self.title = "Genus 2 Curve %s" % (self.label) self.bread = [ ('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('%s' % self.cond, url_for(".by_conductor", conductor=self.cond)), ('%s' % iso, url_for(".by_double_iso_label", conductor=self.cond, iso_label=iso)), ('Genus 2 curve %s' % num, url_for(".by_g2c_label", label=self.label))]