def signature_function_of_integral_matrix(V, prec=53): """ Computes the signature function sigma of V via numerical methods. Returns two lists, the first representing a partition of [0, 1]: x_0 = 0 < x_1 < x_2 < ... < x_n = 1 and the second list consisting of the values [v_0, ... , v_(n-1)] of sigma on the interval (x_i, x_(i+1)). Currently, the value of sigma *at* x_i is not computed. """ poly = alexander_poly_from_seifert(V) RR = RealField(prec) CC = ComplexField(prec) pi = RR.pi() I = CC.gen() partition = [RR(0)] + [a for a, e in roots_on_unit_circle(poly, prec) ] + [RR(1)] n = len(partition) - 1 values = [] for i in range(n): omega = exp((2 * pi * I) * (partition[i] + partition[i + 1]) / 2) A = (1 - omega) * V + (1 - omega.conjugate()) * V.transpose() values.append(signature_via_numpy(A)) assert list(reversed(values)) == values return partition, values
def from_conjugacy_class_index_to_polynomial(self, index): """ A function converting from a conjugacy class index (starting at 1) to the local Euler polynomial. Saves a sequence of processed polynomials, obtained from the local factors table, so it can reuse computations from prime to prime This sequence is indexed by conjugacy class indices (starting at 1, filled with dummy first) and gives the corresponding polynomials in the form [coeff_deg_0, coeff_deg_1, ...], where coeff_deg_i is in ComplexField(). This could be changed later, or made parametrizable """ try: return self._from_conjugacy_class_index_to_polynomial_fn(index) except AttributeError: local_factors = self.local_factors_table() field = ComplexField() root_of_unity = exp( (field.gen()) * 2 * field.pi() / int(self.character_field())) local_factor_processed_pols = [ 0 ] # dummy to account for the shift in indices for pol in local_factors: local_factor_processed_pols.append( process_polynomial_over_algebraic_integer( pol, field, root_of_unity)) def tmp(conjugacy_class_index_start_1): return local_factor_processed_pols[ conjugacy_class_index_start_1] self._from_conjugacy_class_index_to_polynomial_fn = tmp return self._from_conjugacy_class_index_to_polynomial_fn(index)
def eu(p): """ local euler factor """ if self.selfdual: K = QQ else: K = ComplexField() R = PolynomialRing(K, "T") T = R.gens()[0] if self.conductor % p != 0: return 1 - ComplexField()(chi(p)) * T else: return R(1)
def AJ1_digits(f, P, desired_digits, mesh=4): for k in range(1, f.degree() + 1): assert mesh >= 2 # the guess should take less than 2s working_digits = 300 SetPariPrec(working_digits) CF = ComplexField(ceil(RR(log(10) / log(2)) * working_digits)) aj = {} correct_digits = {} sum = 0 total = 0 guess = 10000 CF = ComplexField(log(10) / log(2) * working_digits) for i in range(mesh, max(0, mesh - 3), -1): PariIntNumInit(i) aj[i] = AJ1(CF, f, P, k) if i < mesh: correct_digits[i] = RR((-log( max([ abs(CF((aj[mesh][j] - x) / aj[mesh][j])) for j, x in enumerate(aj[i]) ])) / log(10.)) / working_digits) if i + 1 < mesh: sum += correct_digits[i + 1] / correct_digits[i] total += 1 for i in sorted(correct_digits.keys()): if correct_digits[i] > 1: guess = i break avg = sum / total if guess == 0 and avg > 1.1: guess = mesh - 1 + ceil( log((1.1 / correct_digits[mesh - 1])) / log(avg)) if guess != 0 and 2**guess * desired_digits**2 * log( RR(desired_digits))**3 < (300**2 * 2**11 * log(RR(300))**3): SetPariPrec(ceil(desired_digits) + 10 * guess) PariIntNumInit(guess) CF = ComplexField(log(10) / log(2) * desired_digits) result = vector(CF, AJ1(CF, f, P, k)) # avoiding memory leaks gp._reset_expect() load_gp() return result else: gp._reset_expect() load_gp() raise OverflowError
def coefficient_embedding(self, n, i): r""" Return the i-th complex embedding of coefficient C(n). Note that if it is not in the dictionary we compute the embedding (but not the coefficient). """ embc = self._embeddings['values'].get(n, None) bitprec = self._embeddings['bitprec'] if embc is None: c = self.coefficient(n) if hasattr(c, "complex_embeddings"): embc = c.complex_embeddings(bitprec) else: embc = [ ComplexField(bitprec)(c) for x in range(self.coefficient_field_degree) ] self._embeddings['values'][n] = embc else: if len(embc) < self.coefficient_field_degree: embc = [embc[0] for x in range(self.coefficient_field_degree)] self._embeddings['values'][n] = embc if i > len(embc): raise ValueError, "Embedding nr. {0} does not exist of a number field of degree {1},embc={2}".format( i, self.coefficient_field.absolute_degree(), embc) return embc[i]
def get_integral_from_1_to_oo(self, n, k): r""" Compute \int_{1}^{+Infinity} f|A_n(it) t^k dt """ CF = ComplexField(self._prec) if not self._integrals.has_key((n, k)): c = self.coefficient_at_coset(n) w = self.width(n) my_integral = 0 if self._prec <= 53: if w == 1: l = 1 for a in c: my_integral += a * exp_z_integral(CF(0, 1), l, k) l += 1 else: l = 1 for a in c: my_integral += a * exp_z_integral_w(CF(0, 1), l, w, k) l += 1 else: l = 1 for a in c: my_integral += a * exp_z_integral_wmp(CF(0, 1), l, w, k) l += 1 self._integrals[(n, k)] = my_integral return self._integrals[(n, k)]
def coefficient_at_coset(self, n): r""" Compute Fourier coefficients of f|A_n """ if hasattr(n, "matrix"): n = self._get_coset_n(n) if not self._base_coeffs: self.coefficients_f() CF = ComplexField(self._prec) if not self._coefficients_at_coset.has_key(n): M = self.truncation_M(n) h, w = self.get_shift_and_width_for_coset(n) zN = CyclotomicField(w).gens()[0] prec1 = self._prec + ceil(log_b(M, 2)) RF = RealField(prec1) coeffs = [] fak = RF(w)**-(RF(self._k) / RF(2)) #print "f=",f,n for i in range(M): al = CF(self.atkin_lehner(n)) c0 = self._base_coeffs_embedding[i] #if hasattr(c0,"complex_embeddings"): # c0 = c0.complex_embedding(prec1) #else: # c0 = CF(c0) qN = zN**((i + 1) * h) #print "qN=",qN,type(qN) an = fak * al * c0 * qN.complex_embedding(prec1) #an = self.atkin_lehner(n)*self._base_coeffs[i]*zN**((i+1)*h) #an = f*an.complex_embedding(prec1) coeffs.append(an) self._coefficients_at_coset[n] = coeffs return self._coefficients_at_coset[n]
def polish_R_longitude_vals(self, precision=196): R = ComplexField(precision) L_holo = self.gluing_system.L_nomial # The minus sign is because the FFT path is oriented clockwise. path = [ R(self.radius) * U1Q(-n, self.order, precision=precision) for n in range(self.order) ] holos = [] evs = [] self._print('Polishing shapes to %d bits precision:' % precision) for m in range(self.degree): row = [] for n in range(self.order): self._print('\rlift %d %d ' % (m, n), end='') r = self.R_fibers[n].shapes[m] s = PolishedShapeSet(rough_shapes=r, target_holonomy=path[n], precision=precision) row.append(L_holo(array(list(s)))) holos.append(row) self._print('\r', end='') row = [sqrt(z) for z in row] row = [ self.set_sign(choice, z) for choice, z in zip(self.R_choices[m], row) ] evs.append(row) self.polished_R_path = path self.polished_R_longitude_holos = holos self.polished_R_longitude_evs = evs
def bisection(H, low, high, s, target_slope, epsilon=1.0e-8): CC = ComplexField() low_fiber = H.T_fibers[low] high_fiber = H.T_fibers[high] M = H.manifold F = H.fibrator assert check_slope(H, low, s) < target_slope < check_slope(H, high, s) print('finding:', target_slope) count = 0 while count < 100: z = (low_fiber.H_meridian + high_fiber.H_meridian) / 2 target_holonomy = z / abs(z) target_holonomy_arg = CC(target_holonomy).log().imag() new_fiber = H.transport(low_fiber, complex(target_holonomy)) shapes = new_fiber.shapes[s] new_slope = lifted_slope(M, target_holonomy_arg, shapes) if abs(new_slope - target_slope) < epsilon: return new_fiber.shapes[s] if new_slope < target_slope: low_fiber = new_fiber print(new_slope, 'too low') else: high_fiber = new_fiber print(new_slope, 'too high') count += 1 print(count) print('limit exceeded') return new_fiber.shapes[s]
def __call__(self, prec): roots = [r[0] for r in self._min_poly.roots(ComplexField(prec))] def dist_to_defining_root(z): return abs(z - self._approx_root) return sorted(roots, key=dist_to_defining_root)[0]
def __init__(self, f, prec, verbose=False): self.verbose = verbose self.prec = prec self.f = f self.C = ComplexField(prec) self.Pic = PicardGroup.PicardGroup(f, self.C, self.verbose) self.iajlocal = InvertAJlocal.InvertAJlocal(f, prec, verbose=verbose) self.genus = self.iajlocal
def _initialize(self): N, F = self.N, ComplexField(self.precision) self.zhat = array([F((-2 * k * pi * I / N).exp()) for k in range(N)], dtype='O') self.izhat = array([F((2 * k * pi * I / N).exp()) for k in range(N)], dtype='O') self.z2hat = self.zhat.take(xrange(0, 2 * N, 2), mode='wrap') self.iz2hat = self.izhat.take(xrange(0, 2 * N, 2), mode='wrap')
def signature_via_numpy(A): CC = ComplexField(53) A = A.change_ring(CC).numpy() assert np.linalg.norm(A - A.conjugate().transpose()) < 10e-10 eigs = np.linalg.eigh(A)[0] smallest = min(np.abs(eigs)) assert smallest > 1e-5 return np.sum(eigs > 0) - np.sum(eigs < 0)
def init_dir_char(self, chi): """ Initiate with a Web Dirichlet character. """ self.original_object = [chi] chi = chi.chi.primitive_character() self.object_type = "dirichletcharacter" self.dim = 1 self.motivic_weight = 0 self.conductor = ZZ(chi.conductor()) self.bad_semistable_primes = [] self.bad_pot_good = self.conductor.prime_factors() if chi.is_odd(): aa = 1 bb = I else: aa = 0 bb = 1 self.sign = chi.gauss_sum_numerical() / (bb * float(sqrt(chi.modulus()))) # this has now type python complex. later we need a gp complex self.sign = ComplexField()(self.sign) self.mu_fe = [aa] self.nu_fe = [] self.gammaV = [aa] self.langlands = True self.selfdual = (chi.multiplicative_order() <= 2) # rather than all( abs(chi(m).imag) < 0.0001 for m in range(chi.modulus() ) ) self.primitive = True self.set_dokchitser_Lfunction() self.set_number_of_coefficients() self.dirichlet_coefficients = [ chi(m) for m in range(self.numcoeff + 1) ] if self.selfdual: self.coefficient_type = 2 else: self.coefficient_type = 3 self.coefficient_period = chi.modulus() self.besancon_bound = 10000 def eu(p): """ local euler factor """ if self.selfdual: K = QQ else: K = ComplexField() R = PolynomialRing(K, "T") T = R.gens()[0] if self.conductor % p != 0: return 1 - ComplexField()(chi(p)) * T else: return R(1) self.local_euler_factor = eu self.ld.gp().quit()
def mpmath_matrix_to_sage(A): entries = list(A) if all(isinstance(e, mp.mpf) for e in entries): F = RealField(mp.prec) entries = [F(e) for e in entries] else: F = ComplexField(mp.prec) entries = [F(e.real, e.imag) for e in entries] return matrix(F, A.rows, A.cols, entries)
def __init__(self, real, imag=None): def find_prec(s): if isinstance(s, string_types): # strip negatives and exponent s = s.replace("-","") if "e" in s: s = s[:s.find("e")] return ceil(len(s) * 3.322) else: try: return s.parent().precision() except Exception: return 53 if imag is None: # Process strings if isinstance(real, string_types): M = CC_RE.match(real) if M is None: raise ValueError("'%s' not a valid complex number" % real) a, b = M.groups() # handle missing coefficient of i if b == '-': b = '-1' elif b in ['+', '']: b = '1' # The following is a good guess for the bit-precision, # but we use LmfdbRealLiterals to ensure that our number # prints the same as we got it. prec = max(find_prec(a), find_prec(b), 53) parent = ComplexField(prec) R = parent._real_field() self._real_literal = LmfdbRealLiteral(R, a) self._imag_literal = LmfdbRealLiteral(R, b) elif isinstance(real, LmfdbRealLiteral): parent = ComplexField(real.parent().precision()) self._real_literal = real self._imag_literal = parent._real_field()(0) elif isintance(real, ComplexLiteral): parent = real.parent() self._real_literal = real._real_literal self._imag_literal = real._imag_literal else: raise TypeError("Object '%s' of type %s not valid input" % (real, type(real))) else: prec = max(find_prec(real), find_prec(imag), 53) R = RealField(prec) parent = ComplexField(prec) for x, xname in [(real, '_real_literal'), (imag, '_imag_literal')]: if isinstance(x, string_types): x = LmfdbRealLiteral(R, x) if not isinstance(x, LmfdbRealLiteral): raise TypeError("Object '%s' of type %s not valid input" % (x, type(x))) setattr(self, xname, x) ComplexNumber.__init__(self, self.real(), self.imag())
def qrp_wrapper(A, rank = None, extra_prec = 16, ctx = None): with mpmath.mp.workprec(A.base_ring().precision() + extra_prec): # print mpmath.mp.prec Am = mpmath.matrix(map(list, A.rows())) qm, rm, pm = qrp_mpmath(Am, rank, extra_prec, ctx) def to_sage(field,A): return Matrix(field, [[ field(A[i,j].real, A[i,j].imag) for j in range(A.cols)] for i in range(A.rows)]) return to_sage(ComplexField(mpmath.mp.prec), qm), to_sage(A.base_ring(), rm), to_sage(A.base_ring(), pm)
def tensor_local_factors(f1, f2, d): """ takes two euler factors f1, f2 and a prec and returns the euler factor for the tensor product (with respect to that precision d """ # base rings are either QQ or CC K1 = f1.base_ring() K2 = f2.base_ring() if K1 == ComplexField() or K2 == ComplexField(): K = ComplexField() else: K = QQ R = PowerSeriesRing(K, "T") if not f1.parent().is_exact(): # ideally f1,f2 should already be in PSR if f1.prec() < d: raise ValueError if not f2.parent().is_exact(): # but the user might give them as polys... if f2.prec() < d: raise ValueError f1 = R(f1) f2 = R(f2) if f1 == 1 or f2 == 1: f = R(1) f = f.add_bigoh(d + 1) return f l1 = f1.log().derivative() p1 = l1.prec() c1 = l1.list() while len(c1) < p1: c1.append(0) l2 = f2.log().derivative() p2 = l2.prec() c2 = l2.list() while len(c2) < p2: c2.append(0) C = [0] * len(c1) for i in range(len(c1)): C[i] = c1[i] * c2[i] E = -R(C).integral() E = E.add_bigoh(d + 1) E = E.exp() # coerce to R return E
def from_conjugacy_class_index_to_polynomial(self, index): """ A function converting from a conjugacy class index (starting at 1) to the local Euler polynomial. Saves a sequence of processed polynomials, obtained from the local factors table, so it can reuse computations from prime to prime This sequence is indexed by conjugacy class indices (starting at 1, filled with dummy first) and gives the corresponding polynomials in the form [coeff_deg_0, coeff_deg_1, ...], where coeff_deg_i is in ComplexField(). This could be changed later, or made parametrizable """ try: return self._from_conjugacy_class_index_to_polynomial_fn(index) except AttributeError: local_factors = self.local_factors_table() field = ComplexField() root_of_unity = exp((field.gen()) * 2 * field.pi() / int(self.character_field())) local_factor_processed_pols = [0] # dummy to account for the shift in indices for pol in local_factors: local_factor_processed_pols.append( process_polynomial_over_algebraic_integer(pol, field, root_of_unity)) def tmp(conjugacy_class_index_start_1): return local_factor_processed_pols[conjugacy_class_index_start_1] self._from_conjugacy_class_index_to_polynomial_fn = tmp return self._from_conjugacy_class_index_to_polynomial_fn(index)
def sage(self): """ Return as an element of the approriate RealField or ComplexField """ if not _within_sage: raise ImportError("Not within SAGE.") if self.gen.type() == 't_REAL': return RealField(self._precision)(self.gen) elif self.gen.type() == 't_COMPLEX': return ComplexField(self._precision)(self.gen) else: return self.gen.sage()
def special_value(self, n): r""" Compute L(f,n) Recall that L(f,n+1)=(2pii)^(n+1)*(-1)^(n+1)/Gamma(n+1) * r_n(f) """ RF = RealField(self._prec) CF = ComplexField(self._prec) if n < 0 or n > self._w + 1: print "{0} is not a special point for this f!".format(n) return if not self._polynomials: self._get_polynomials() rk = self.get_rk(0, n - 1) return CF(0, 2 * RF.pi())**(n) * (-1)**(n) / RF(n).gamma() * rk
def parse_file(filename, prec=53): from sage.all import RealField, ComplexField RR = RealField(prec) CC = ComplexField(prec) data = open(filename).read() open('polys.txt', 'w').write(data) data = data.split('THE SOLUTIONS')[-1] data = re.subn('[*]{3,}', '', data)[0] ans = [] solutions = re.findall('(solution \d+ : \s* start residual .*?) ==', data, re.DOTALL) for sol in solutions: kind = sol.split('=')[-1].strip() if kind == 'no solution': continue mult = int(re.search('^m : (\d+)', sol, re.MULTILINE).group(1)) err = float(re.search('== err :\s+(.*?)\s+= ', sol).group(1)) coors = re.findall('^ (.*) :\s+(\S*)\s+(\S*)', sol, re.MULTILINE) if kind.startswith('real'): coors = { restore_forbidden(var): RR(real) for var, real, imag in coors } ans.append({ 'kind': 'real', 'mult': mult, 'err': err, 'coors': coors }) elif kind.startswith('complex'): coors = { restore_forbidden(var): CC(RR(real), RR(imag)) for var, real, imag in coors } ans.append({ 'kind': 'complex', 'mult': mult, 'err': err, 'coors': coors }) num_real = int( re.search('Number of real solutions\s+:\s(.*).', data).group(1)) num_complex = int( re.search('Number of complex solutions\s+:\s(.*).', data).group(1)) kinds = [sol['kind'] for sol in ans] assert kinds.count('real') == num_real assert kinds.count('complex') == num_complex return ans
def eu(p): """ Local euler factor """ ans = F.q_expansion_embeddings(p + 1) K = ComplexField() R = PolynomialRing(K, "T") T = R.gens()[0] N = self.conductor if N % p != 0 : # good reduction return 1 - ans[p-1][self.number] * T + T**2 elif N % (p**2) != 0: # semistable reduction return 1 - ans[p-1][self.number] * T else: return R(1)
def petersson_norm(self, type=1): r""" Compute the Petersson norm of f. ALGORITHM: Uses (f,f) = < rho_{f}^{+} | T - T^-1 , rho_f^{-}> for k even and (f,f) = < rho_{f}^{+} | T - T^-1 , rho_f^{+}> for k odd. See e.g. Thm 3.3. in Pasol - Popa "Modular forms and period polynomials" """ if self._peterson_norm <> 0: return self._peterson_norm T = SL2Z([1, 1, 0, 1]) Ti = SL2Z([1, -1, 0, 1]) norm = 0 for n in range(self._dim): if type == 1: p1 = self.slash_action(n, T, sym='plus') p2 = self.slash_action(n, Ti, sym='plus') else: p1 = self.slash_action(n, T, sym='minus') p2 = self.slash_action(n, Ti, sym='minus') pL = p1 - p2 #print "Pl=",pL if self.function().weight() % 2 == 1: if type == 1: pR = self.polynomial_plus(n) else: pR = self.polynomial_minus(n) else: if type == 1: pR = self.polynomial_minus(n) else: pR = self.polynomial_plus(n) #print "PR=",pR t = self.pair_two_pols(pL, pR) #print "t=",t norm += t CF = ComplexField(self._prec) c2 = CF(3) * CF(0, 2)**(self._k - 1) self._peterson_norm = -norm / c2 return self._peterson_norm
def eu(p): """ Local euler factor """ # There was no function q_expansion_embeddings before the transition to postgres # so I'm not sure what this is supposed to do. ans = F.q_expansion_embeddings(p + 1) K = ComplexField() R = PolynomialRing(K, "T") T = R.gens()[0] N = self.conductor if N % p != 0: # good reduction return 1 - ans[p - 1][self.number] * T + T**2 elif N % (p**2) != 0: # semistable reduction return 1 - ans[p - 1][self.number] * T else: return R(1)
def _get_polynomial(self, n): r""" Compute P(f|A_n)(X) """ if self._polynomials.has_key(n): return self._polynomials[n] CF = ComplexField(self._prec) X = CF['X'].gens()[0] k = self._k pols = {} ## For each component we get a polynomial p = X.parent().zero() for l in range(self._w + 1): rk = self.get_rk(n, self._w - l) if self._verbose > 0: print "rk=", rk fak = binomial(self._w, l) * (-1)**l p += CF(fak) * CF(rk) * X**l self._polynomials[n] = p return p
def __init__(self, G, k=0, prec=53, multiplier=None, verbose=0, holomorphic=True): r""" Setup the associated space. """ if isinstance(G, (int, Integer)): self._N = G self._group = MySubgroup(Gamma0(G)) else: self._group = G self._N = G.level() self._k = k self._verbose = verbose self._holomorphic = holomorphic self._prec = prec self._RF = RealField(prec) self._CF = ComplexField(prec)
def __repr__(self): out = "" out += "A divisor class of the hyperelliptic curve defined by %s" % self.Pic.f if self.coordinates_input: if len(self.coordinates_cache) == 1: if self.sign == 0: sign = "+" else: sign = "-" out += " equivalent to [%s - \infty_%s]." % ( self.coordinates_cache[0], sign) if len(self.coordinates_cache) == 2: out += " equivalent to [%s + %s - (\infty_{+} + \infty_{-}]." % ( self.coordinates_cache[0], self.coordinates_cache[1]) else: out += " equivalent to " for i in range(1, self.Pic.g): out += "P%d + " % i out += "P%d - %d * (\infty_+ \infty_-) satisfying " % ( self.Pic.g, self.Pic.g / 2) out += "\nP_i = %s" % Matrix(ComplexField(20), self.compute_coordinates()) return out
def h(t, prec): Dop, x, Dx = DifferentialOperators(QQ) L = Dx * (x * (x - 1) * (x - t)) * Dx + x hprec = prec + 100 C = ComplexField(hprec) CBF = ComplexBallField(hprec) # Formal monodromy + connection matrices base = t / 2 m1 = L.numerical_transition_matrix([0, base], ZZ(2)**(-prec)) m2 = L.numerical_transition_matrix([t, base], ZZ(2)**(-prec)) delta = matrix(CBF, [[1, 0], [2 * pi * i, 1]]) mat = m1 * delta * ~m1 * m2 * delta * ~m2 # log(eigenvalue) tr = mat.trace().real().mid() Pol, la = PolynomialRing(C, 'la').objgen() char = (la + 1 / la - tr).numerator() rt = char.roots(multiplicities=False)[0] val = (rt.log() / C(2 * i * pi))**2 return val
def get_satake_parameters(k, N=1, chi=0, fi=0, prec=10, bits=53, angles=False): r""" Compute the Satake parameters and return an html-table. INPUT: - ''k'' -- positive integer : the weight - ''N'' -- positive integer (default 1) : level - ''chi'' -- non-neg. integer (default 0) use character nr. chi - ''fi'' -- non-neg. integer (default 0) We want to use the element nr. fi f=Newforms(N,k)[fi] -''prec'' -- compute parameters for p <=prec -''bits'' -- do real embedings intoi field of bits precision -''angles''-- return the angles t_p instead of the alpha_p here alpha_p=p^((k-1)/2)exp(i*t_p) """ (t, f) = _get_newform(k, N, chi, fi) if (not t): return f K = f.base_ring() RF = RealField(bits) CF = ComplexField(bits) if (K != QQ): M = len(K.complex_embeddings()) ems = dict() for j in range(M): ems[j] = list() ps = prime_range(prec) alphas = list() for p in ps: ap = f.coefficients(ZZ(prec))[p] if (K == QQ): f1 = QQ(4 * p**(k - 1) - ap**2) alpha_p = (QQ(ap) + I * f1.sqrt()) / QQ(2) # beta_p=(QQ(ap)-I*f1.sqrt())/QQ(2) # satake[p]=(alpha_p,beta_p) ab = RF(p**((k - 1) / 2)) norm_alpha = alpha_p / ab t_p = CF(norm_alpha).argument() if (angles): alphas.append(t_p) else: alphas.append(alpha_p) else: for j in range(M): app = ap.complex_embeddings(bits)[j] f1 = (4 * p**(k - 1) - app**2) alpha_p = (app + I * f1.sqrt()) / RealField(bits)(2) ab = RF(p**((k - 1) / 2)) norm_alpha = alpha_p / ab t_p = CF(norm_alpha).argument() if (angles): ems[j].append(t_p) else: ems[j].append(alpha_p) tbl = dict() tbl['headersh'] = ps if (K == QQ): tbl['headersv'] = [""] tbl['data'] = [alphas] tbl['corner_label'] = "$p$" else: tbl['data'] = list() tbl['headersv'] = list() tbl['corner_label'] = "Embedding \ $p$" for j in ems.keys(): tbl['headersv'].append(j) tbl['data'].append(ems[j]) # logger.debug(tbl) s = html_table(tbl) return s
def get_values_at_CM_points(k, N=1, chi=0, fi=0, digits=12, verbose=0): r""" Computes and returns a list of values of f at a collection of CM points as complex floating point numbers. INPUT: - ''k'' -- positive integer : the weight - ''N'' -- positive integer (default 1) : level - ''chi'' -- non-neg. integer (default 0) use character nr. chi - ''fi'' -- non-neg. integer (default 0) We want to use the element nr. fi f=Newforms(N,k)[fi] -''digits'' -- we want this number of corrrect digits in the value OUTPUT: -''s'' string representation of a dictionary {I:f(I):rho:f(rho)}. TODO: Get explicit, algebraic values if possible! """ (t, f) = _get_newform(k, N, chi, fi) if (not t): return f bits = max(53, ceil(digits * 4)) CF = ComplexField(bits) RF = ComplexField(bits) eps = RF(10**-(digits + 1)) logger.debug("eps=" % eps) K = f.base_ring() cm_vals = dict() # the points we want are i and rho. More can be added later... rho = CyclotomicField(3).gen() zi = CyclotomicField(4).gen() points = [rho, zi] maxprec = 1000 # max size of q-expansion minprec = 10 # max size of q-expansion for tau in points: q = CF(exp(2 * pi * I * tau)) fexp = dict() if (K == QQ): v1 = CF(0) v2 = CF(1) try: for prec in range(minprec, maxprec, 10): logger.debug("prec=%s" % prec) v2 = f.q_expansion(prec)(q) err = abs(v2 - v1) logger.debug("err=%s" % err) if (err < eps): raise StopIteration() v1 = v2 cm_vals[tau] = "" except StopIteration: cm_vals[tau] = str(fq) else: v1 = dict() v2 = dict() err = dict() cm_vals[tau] = dict() for h in range(K.degree()): v1[h] = 1 v2[h] = 0 try: for prec in range(minprec, maxprec, 10): logger.debug("prec=%s" % prec) for h in range(K.degree()): fexp[h] = list() v2[h] = 0 for n in range(prec): c = f.coefficients(ZZ(prec))[n] cc = c.complex_embeddings(CF.prec())[h] v2[h] = v2[h] + cc * q**n err[h] = abs(v2[h] - v1[h]) logger.debug("v1[%s]=%s" % (h, v1[h])) logger.debug("v2[%s]=%s" % (h, v2[h])) logger.debug("err[%s]=%s" % (h, err[h])) if (max(err.values()) < eps): raise StopIteration() v1[h] = v2[h] except StopIteration: pass for h in range(K.degree()): if (err[h] < eps): cm_vals[tau][h] = v2[h] else: cm_vals[tau][h] = "" logger.debug("vals=%s" % cm_vals) logger.debug("errs=%s" % err) tbl = dict() tbl['corner_label'] = ['$\tau$'] tbl['headersh'] = ['$\\rho=\zeta_{3}$', '$i$'] if (K == QQ): tbl['headersv'] = ['$f(\\tau)$'] tbl['data'] = [cm_vals] else: tbl['data'] = list() tbl['headersv'] = list() for h in range(K.degree()): tbl['headersv'].append("$\sigma_{%s}(f(\\tau))$" % h) row = list() for tau in points: row.append(cm_vals[tau][h]) tbl['data'].append(row) s = html_table(tbl) # s=html.table([cm_vals.keys(),cm_vals.values()]) return s
def compute_cm_values_numeric(self,digits=12,insert_in_db=True): r""" Compute CM-values numerically. """ if isinstance(self._cm_values,dict) and self._cm_values <> {}: return self._cm_values # the points we want are i and rho. More can be added later... bits = ceil(int(digits) * int(4)) CF = ComplexField(bits) RF = ComplexField(bits) eps = RF(10 ** - (digits + 1)) if(self._verbose > 1): wmf_logger.debug("eps={0}".format(eps)) K = self.base_ring() # recall that degree = self.degree() cm_vals = dict() rho = CyclotomicField(3).gen() zi = CyclotomicField(4).gen() points = [rho, zi] maxprec = 1000 # max size of q-expansion minprec = 10 # max size of q-expansion for tau in points: q = CF(exp(2 * pi * I * tau)) fexp = dict() cm_vals[tau] = dict() if(tau == I and self.level() == -1): # cv= #"Exact(soon...)" #_cohen_exact_formula(k) for h in range(degree): cm_vals[tau][h] = cv continue if K.absolute_degree()==1: v1 = CF(0) v2 = CF(1) try: for prec in range(minprec, maxprec, 10): if(self._verbose > 1): wmf_logger.debug("prec={0}".format(prec)) v2 = self.as_factor().q_eigenform(prec).truncate(prec)(q) err = abs(v2 - v1) if(self._verbose > 1): wmf_logger.debug("err={0}".format(err)) if(err < eps): raise StopIteration() v1 = v2 cm_vals[tau][0] = None except StopIteration: cm_vals[tau][0] = v2 else: v1 = dict() v2 = dict() err = dict() for h in range(degree): v1[h] = 1 v2[h] = 0 try: for prec in range(minprec, maxprec, 10): if(self._verbose > 1): wmf_logger.debug("prec={0}".format(prec)) c = self.coefficients(range(prec),insert_in_db=insert_in_db) for h in range(degree): fexp[h] = list() v2[h] = 0 for n in range(prec): cn = c[n] if hasattr(cn, 'complex_embeddings'): cc = cn.complex_embeddings(CF.prec())[h] else: cc = CF(cn) v2[h] = v2[h] + cc * q ** n err[h] = abs(v2[h] - v1[h]) if(self._verbose > 1): wmf_logger.debug("v1[{0}]={1}".format(h,v1[h])) wmf_logger.debug("v2[{0}]={1}".format(h,v2[h])) wmf_logger.debug("err[{0}]={2}".format(h,err[h])) if(max(err.values()) < eps): raise StopIteration() v1[h] = v2[h] except StopIteration: pass for h in range(degree): if(err[h] < eps): cm_vals[tau][h] = v2[h] else: cm_vals[tau][h] = None self._cm_values = cm_vals
def dimension(self,k,ignore=False, debug = 0): if k < 2 and not ignore: raise NotImplementedError("k has to >= 2") s = self._signature if not (2*k in ZZ): raise ValueError("k has to be integral or half-integral") if (2*k+s)%2 != 0: return 0 m = self._m n2 = self._n2 if self._v2.has_key(0): v2 = self._v2[0] else: v2 = 1 if self._g != None: if not self._aniso_formula: vals = self._g.values() #else: #print "using aniso_formula" M = self._g else: vals = self._M.values() M = self._M if (2*k+s)%4 == 0: d = Integer(1)/Integer(2)*(m+n2) # |dimension of the Weil representation on even functions| self._d = d self._alpha4 = 1/Integer(2)*(vals[0]+v2) # the codimension of SkL in MkL else: d = Integer(1)/Integer(2)*(m-n2) # |dimension of the Weil representation on odd functions| self._d = d self._alpha4 = 1/Integer(2)*(vals[0]-v2) # the codimension of SkL in MkL prec = ceil(max(log(M.order(),2),52)+1)+17 #print prec RR = RealField(prec) CC = ComplexField(prec) if debug > 0: print "d, m = {0}, {1}".format(d,m) eps = exp( 2 * CC.pi() * CC(0,1) * (s + 2*k) / Integer(4) ) eps = round(real(eps)) if self._alpha3 is None or self._last_eps != eps: self._last_eps = eps if self._aniso_formula: self._alpha4 = 1 self._alpha3 = -sum([BB(a)*mm for a,mm in self._v2.iteritems() if a != 0]) #print self._alpha3 self._alpha3 += Integer(d) - Integer(1) - self._g.beta_formula() #print self._alpha3, self._g.a5prime_formula() self._alpha3 = self._alpha3/RR(2) else: self._alpha3 = eps*sum([(1-a)*mm for a,mm in self._v2.iteritems() if a != 0]) if debug>0: print "alpha3t = ", self._alpha3 self._alpha3 += sum([(1-a)*mm for a,mm in vals.iteritems() if a != 0]) #print self._alpha3 self._alpha3 = self._alpha3 / Integer(2) alpha3 = self._alpha3 alpha4 = self._alpha4 if debug > 0: print alpha3, alpha4 g1=M.char_invariant(1) g1=CC(g1[0]*g1[1]) #print g1 g2=M.char_invariant(2) g2=CC(g2[0]*g2[1]) if debug > 0: print g2, g2.parent() g3=M.char_invariant(-3) g3=CC(g3[0]*g3[1]) if debug > 0: print "eps = {0}".format(eps) if debug > 0: print "d/4 = {0}, m/4 = {1}, e^(2pi i (2k+s)/8) = {2}".format(RR(d) / RR(4), sqrt(RR(m)) / RR(4), CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8)))) if eps == 1: g2_2 = real(g2) else: g2_2 = imag(g2)*CC(0,1) alpha1 = RR(d) / RR(4) - sqrt(RR(m)) / RR(4) * CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8)) * g2_2) if debug > 0: print alpha1 alpha2 = RR(d) / RR(3) + sqrt(RR(m)) / (3 * sqrt(RR(3))) * real(exp(CC(2 * CC.pi() * CC(0,1) * (4 * k + 3 * s - 10) / 24)) * (g1 + eps*g3)) if debug > 0: print "alpha1 = {0}, alpha2 = {1}, alpha3 = {2}, g1 = {3}, g2 = {4}, g3 = {5}, d = {6}, k = {7}, s = {8}".format(alpha1, alpha2, alpha3, g1, g2, g3, d, k, s) dim = real(d + (d * k / Integer(12)) - alpha1 - alpha2 - alpha3) if debug > 0: print "dimension:", dim if abs(dim-round(dim)) > 1e-6: raise RuntimeError("Error ({0}) too large in dimension formula for {1} and k={2}".format(abs(dim-round(dim)), self._M if self._M is not None else self._g, k)) dimr = dim dim = Integer(round(dim)) if k >=2 and dim < 0: raise RuntimeError("Negative dimension (= {0}, {1})!".format(dim, dimr)) return dim
def dimension(self,k,ignore=False, debug = 0): if k < 2 and not ignore: raise NotImplementedError("k has to >= 2") s = self._signature if not (2*k in ZZ): raise ValueError("k has to be integral or half-integral") if (2*k+s)%4 != 0 and not ignore: raise NotImplementedError("2k has to be congruent to -signature mod 4") if self._v2.has_key(0): v2 = self._v2[0] else: v2 = 1 if self._g != None: if not self._aniso_formula: vals = self._g.values() #else: #print "using aniso_formula" M = self._g else: vals = self._M.values() M = self._M prec = ceil(max(log(M.order(),2),52)+1)+17 #print prec RR = RealField(prec) CC = ComplexField(prec) d = self._d m = self._m if debug > 0: print d,m if self._alpha3 == None: if self._aniso_formula: self._alpha4 = 1 self._alpha3 = -sum([BB(a)*mm for a,mm in self._v2.iteritems() if a != 0]) #print self._alpha3 self._alpha3 += Integer(d) - Integer(1) - self._g.beta_formula() #print self._alpha3, self._g.a5prime_formula() self._alpha3 = self._alpha3/RR(2) else: self._alpha3 = sum([(1-a)*mm for a,mm in self._v2.iteritems() if a != 0]) #print self._alpha3 self._alpha3 += sum([(1-a)*mm for a,mm in vals.iteritems() if a != 0]) #print self._alpha3 self._alpha3 = self._alpha3 / Integer(2) self._alpha4 = 1/Integer(2)*(vals[0]+v2) # the codimension of SkL in MkL alpha3 = self._alpha3 alpha4 = self._alpha4 if debug > 0: print alpha3, alpha4 g1=M.char_invariant(1) g1=CC(g1[0]*g1[1]) #print g1 g2=M.char_invariant(2) g2=RR(real(g2[0]*g2[1])) if debug > 0: print g2, g2.parent() g3=M.char_invariant(-3) g3=CC(g3[0]*g3[1]) if debug > 0: print RR(d) / RR(4), sqrt(RR(m)) / RR(4), CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8))) alpha1 = RR(d) / RR(4) - (sqrt(RR(m)) / RR(4) * CC(exp(2 * CC.pi() * CC(0,1) * (2 * k + s) / Integer(8))) * g2) if debug > 0: print alpha1 alpha2 = RR(d) / RR(3) + sqrt(RR(m)) / (3 * sqrt(RR(3))) * real(exp(CC(2 * CC.pi() * CC(0,1) * (4 * k + 3 * s - 10) / 24)) * (g1+g3)) if debug > 0: print alpha1, alpha2, g1, g2, g3, d, k, s dim = real(d + (d * k / Integer(12)) - alpha1 - alpha2 - alpha3) if debug > 0: print "dimension:", dim if abs(dim-round(dim)) > 1e-6: raise RuntimeError("Error ({0}) too large in dimension formula for {1} and k={2}".format(abs(dim-round(dim)), self._M if self._M is not None else self._g, k)) dimr = dim dim = Integer(round(dim)) if k >=2 and dim < 0: raise RuntimeError("Negative dimension (= {0}, {1})!".format(dim, dimr)) return dim
def get_values_at_CM_points(k, N=1, chi=0, fi=0, digits=12, verbose=0): r""" Computes and returns a list of values of f at a collection of CM points as complex floating point numbers. INPUT: - ''k'' -- positive integer : the weight - ''N'' -- positive integer (default 1) : level - ''chi'' -- non-neg. integer (default 0) use character nr. chi - ''fi'' -- non-neg. integer (default 0) We want to use the element nr. fi f=Newforms(N,k)[fi] -''digits'' -- we want this number of corrrect digits in the value OUTPUT: -''s'' string representation of a dictionary {I:f(I):rho:f(rho)}. TODO: Get explicit, algebraic values if possible! """ (t, f) = _get_newform(k, N, chi, fi) if(not t): return f bits = max(53, ceil(digits * 4)) CF = ComplexField(bits) RF = ComplexField(bits) eps = RF(10 ** -(digits + 1)) logger.debug("eps=" % eps) K = f.base_ring() cm_vals = dict() # the points we want are i and rho. More can be added later... rho = CyclotomicField(3).gen() zi = CyclotomicField(4).gen() points = [rho, zi] maxprec = 1000 # max size of q-expansion minprec = 10 # max size of q-expansion for tau in points: q = CF(exp(2 * pi * I * tau)) fexp = dict() if(K == QQ): v1 = CF(0) v2 = CF(1) try: for prec in range(minprec, maxprec, 10): logger.debug("prec=%s" % prec) v2 = f.q_expansion(prec)(q) err = abs(v2 - v1) logger.debug("err=%s" % err) if(err < eps): raise StopIteration() v1 = v2 cm_vals[tau] = "" except StopIteration: cm_vals[tau] = str(fq) else: v1 = dict() v2 = dict() err = dict() cm_vals[tau] = dict() for h in range(K.degree()): v1[h] = 1 v2[h] = 0 try: for prec in range(minprec, maxprec, 10): logger.debug("prec=%s" % prec) for h in range(K.degree()): fexp[h] = list() v2[h] = 0 for n in range(prec): c = f.coefficients(ZZ(prec))[n] cc = c.complex_embeddings(CF.prec())[h] v2[h] = v2[h] + cc * q ** n err[h] = abs(v2[h] - v1[h]) logger.debug("v1[%s]=%s" % (h, v1[h])) logger.debug("v2[%s]=%s" % (h, v2[h])) logger.debug("err[%s]=%s" % (h, err[h])) if(max(err.values()) < eps): raise StopIteration() v1[h] = v2[h] except StopIteration: pass for h in range(K.degree()): if(err[h] < eps): cm_vals[tau][h] = v2[h] else: cm_vals[tau][h] = "" logger.debug("vals=%s" % cm_vals) logger.debug("errs=%s" % err) tbl = dict() tbl['corner_label'] = ['$\tau$'] tbl['headersh'] = ['$\\rho=\zeta_{3}$', '$i$'] if(K == QQ): tbl['headersv'] = ['$f(\\tau)$'] tbl['data'] = [cm_vals] else: tbl['data'] = list() tbl['headersv'] = list() for h in range(K.degree()): tbl['headersv'].append("$\sigma_{%s}(f(\\tau))$" % h) row = list() for tau in points: row.append(cm_vals[tau][h]) tbl['data'].append(row) s = html_table(tbl) # s=html.table([cm_vals.keys(),cm_vals.values()]) return s
def init_tensor_product(self, V, W): """ We are given two Galois representations and we will return their tensor product. """ self.original_object = V.original_object + W.original_object self.object_type = "tensorproduct" self.V1 = V self.V2 = W self.dim = V.dim * W.dim self.motivic_weight = V.motivic_weight + W.motivic_weight self.langlands = False # status 2014 :) self.besancon_bound = min(V.besancon_bound, W.besancon_bound) bad2 = ZZ(W.conductor).prime_factors() bad_primes = [x for x in ZZ(V.conductor).prime_factors() if x in bad2] for p in bad_primes: if ( p not in V.bad_semistable_primes and p not in W.bad_semistable_primes) : # this condition above only applies to the current type of objects # for general reps we would have to test the lines below # to be certain that the formulae are correct. #if ((p not in V.bad_semistable_primes or p not in W.bad_pot_good) and #(p not in W.bad_semistable_primes or p not in V.bad_pot_good) and #(p not in V.bad_semistable_primes or p not in W.bad_semistable_primes)): raise NotImplementedError("Currently tensor products of Galois representations are only implemented under some conditions.", "The behaviour at %d is too wild (both factors must be semistable)." % p) # check for the possibily of getting poles if V.weight == W.weight and V.conductor == W.conductor : Vans = V.algebraic_coefficients(50) Wans = W.algebraic_coefficients(50) CC = ComplexField() if ((Vans[2] in ZZ and Wans[2] in ZZ and all(Vans[n] == Wans[n] for n in range(1,50) ) ) or all( CC(Vans[n]) == CC(Wans[n]) for n in range(1,50) ) ): raise NotImplementedError("It seems you are asking to tensor a "+ "Galois representation with its dual " + "which results in the L-function having "+ "a pole. This is not implemented here.") scommon = [x for x in V.bad_semistable_primes if x in W.bad_semistable_primes] N = W.conductor ** V.dim N *= V.conductor ** W.dim for p in bad_primes: n1_tame = V.dim - V.local_euler_factor(p).degree() n2_tame = W.dim - W.local_euler_factor(p).degree() nn = n1_tame * n2_tame N = N // p ** nn if p in scommon: # both are degree 1 in this case N = N // p self.conductor = N h1 = selberg_to_hodge(V.motivic_weight,V.mu_fe,V.nu_fe) h2 = selberg_to_hodge(W.motivic_weight,W.mu_fe,W.nu_fe) h = tensor_hodge(h1, h2) w,m,n = hodge_to_selberg(h) self.mu_fe = m self.nu_fe = n _, self.gammaV = gamma_factors(h) # this is used in getting the Dirichlet coefficients. self.bad_primes_info = [] for p in bad_primes: # we have to check if this works in all bad cases ! f1 = V.local_euler_factor(p) f2 = W.local_euler_factor(p) # might be dodgy if f1 or f2 is an approx to the Euler factor if p in scommon: E = tensor_local_factors(f1,f2,V.dim*W.dim) T = f1.parent().gens()[0] # right answer is E(T)*E(pT) self.bad_primes_info.append([p,E*E(p*T),1-T]) #bad_primes_info.append() with 1-T as the second argument is equivalent to taking the first argument as the results (it does a convolution, as in the next line) else: self.bad_primes_info.append([p,f1,f2]) CC = ComplexField() I = CC.gens()[0] self.sign = I ** root_number_at_oo(h) self.sign /= I ** (root_number_at_oo(h1) * V.dim) self.sign /= I ** (root_number_at_oo(h2) * W.dim) self.sign *= V.sign ** W.dim self.sign *= W.sign ** V.dim for p in bad_primes: if p not in V.bad_semistable_primes or p not in V.bad_semistable_primes: f1 = V.local_euler_factor(p) f2 = W.local_euler_factor(p) det1 = f1.leading_coefficient() * (-1) ** f1.degree() det2 = f2.leading_coefficient() * (-1) ** f2.degree() n1_tame = V.dim - f1.degree() n2_tame = W.dim - f2.degree() n1_wild = ZZ(V.conductor).valuation(p) - n1_tame n2_wild = ZZ(W.conductor).valuation(p) - n2_tame # additionally, we would need to correct this by # replacing det1 by chi1(p) if p is semistable for V # however for all the possible input this currently does # not affect the sign if p in V.bad_semistable_primes: chi1p = 1 # here else: chi1p = det1 if p in W.bad_semistable_primes: chi2p = 1 # here else: chi2p = det2 corr = chi1p ** n2_wild corr *= det1 ** n2_tame corr *= chi2p ** n1_wild corr *= det2 ** n1_tame corr *= (-1) ** (n1_tame * n2_tame) self.sign *= corr/corr.abs() #self.primitive = False self.set_dokchitser_Lfunction() # maybe we should change this to take as many coefficients as implemented # in other Lfunctions self.set_number_of_coefficients() someans = self.algebraic_coefficients(50) # why not. if all( x in ZZ for x in someans): self.selfdual = True else: CC = ComplexField() self.selfdual = all( CC(an).imag().abs() < 0.0001 for an in someans) self.coefficient_type = max(V.coefficient_type, W.coefficient_type) self.coefficient_period = ZZ(V.coefficient_period).lcm(W.coefficient_period) self.ld.gp().quit()