def EllipticCurve_from_hoeij_data(line): """Given a line of the file "http://www.math.fsu.edu/~hoeij/files/X1N/LowDegreePlaces" that is actually corresponding to an elliptic curve, this function returns the elliptic curve corresponding to this """ Rx = PolynomialRing(QQ, 'x') x = Rx.gen(0) Rxy = PolynomialRing(Rx, 'y') y = Rxy.gen(0) N = ZZ(line.split(",")[0].split()[-1]) x_rel = Rx(line.split(',')[-2][2:-4]) assert x_rel.leading_coefficient() == 1 y_rel = line.split(',')[-1][1:-5] K = QQ.extension(x_rel, 'x') x = K.gen(0) y_rel = Rxy(y_rel).change_ring(K) y_rel = y_rel / y_rel.leading_coefficient() if y_rel.degree() == 1: y = -y_rel[0] else: #print("needing an extension!!!!") L = K.extension(y_rel, 'y') y = L.gen(0) K = L #B=L.absolute_field('s') #f1,f2 = B.structure() #x,y=f2(x),f2(y) r = (x**2 * y - x * y + y - 1) / x / (x * y - 1) s = (x * y - y + 1) / x / y b = r * s * (r - 1) c = s * (r - 1) E = EllipticCurve([1 - c, -b, -b, 0, 0]) return N, E, K
def EllipticCurve_from_hoeij_data(line): """Given a line of the file "http://www.math.fsu.edu/~hoeij/files/X1N/LowDegreePlaces" that is actually corresponding to an elliptic curve, this function returns the elliptic curve corresponding to this """ Rx=PolynomialRing(QQ,'x') x = Rx.gen(0) Rxy = PolynomialRing(Rx,'y') y = Rxy.gen(0) N=ZZ(line.split(",")[0].split()[-1]) x_rel=Rx(line.split(',')[-2][2:-4]) assert x_rel.leading_coefficient()==1 y_rel=line.split(',')[-1][1:-5] K = QQ.extension(x_rel,'x') x = K.gen(0) y_rel=Rxy(y_rel).change_ring(K) y_rel=y_rel/y_rel.leading_coefficient() if y_rel.degree()==1: y = - y_rel[0] else: #print "needing an extension!!!!" L = K.extension(y_rel,'y') y = L.gen(0) K = L #B=L.absolute_field('s') #f1,f2 = B.structure() #x,y=f2(x),f2(y) r = (x**2*y-x*y+y-1)/x/(x*y-1) s = (x*y-y+1)/x/y b = r*s*(r-1) c = s*(r-1) E=EllipticCurve([1-c,-b,-b,0,0]) return N,E,K
def _test(self): from sage.all import GF, FunctionField, PolynomialRing k = GF(4) a = k.gen() R = PolynomialRing(k, 'b') b = R.gen() l = k.extension(b**2 + b + a, 'b') K = FunctionField(l, 'x') x = K.gen() R = PolynomialRing(K, 't') t = R.gen() F = t * x F.factor(proof=False)
def rank_disc(P1): R= PolynomialRing(QQ, 'T') T = R.gen(); if len(P1) != 5: return +Infinity, None p, p2 = P2_4factor(P1) cp = R(p2)(T/p) rank = 2 rank = 2; t_cp = cp n_cp = R(1) for z in cyclo_bound_4: q, r = t_cp.quo_rem( R(z) ) while r == 0: n_cp *= R(z); t_cp = q rank += len(z) -1 q, r = t_cp.quo_rem(R(z)) assert n_cp * t_cp == cp e = 1 assert rank == n_cp.degree() + 2 while (T-1)**(rank - 2) != characteristic_polynomial_extension(n_cp, e): e += 1 disc = (-1) * characteristic_polynomial_extension(t_cp, e)(1) * p**e assert rank % 2 == 0 return p, rank, disc.squarefree_part()
def irreps(p, q): """ Returns the irreducible representations of the cyclic group C_p over the field F_q, where p and q are distinct primes. Each representation is given by a matrix over F_q giving the action of the preferred generator of C_p. sage: [M.nrows() for M in irreps(3, 7)] [1, 1, 1] sage: [M.nrows() for M in irreps(7, 11)] [1, 3, 3] sage: sum(M.nrows() for M in irreps(157, 13)) 157 """ p, q = ZZ(p), ZZ(q) assert p.is_prime() and q.is_prime() and p != q R = PolynomialRing(GF(q), 'x') x = R.gen() polys = [f for f, e in (x**p - 1).factor()] polys.sort(key=lambda f: (f.degree(), -f.constant_coefficient())) reps = [poly_to_rep(f) for f in polys] assert all(A**p == 1 for A in reps) assert reps[0] == 1 return reps
def tensor_charpoly(f, g): r""" INPUT: - ``f`` -- the characteristic polynomial of a linear transformation - ``g`` -- the characteristic polynomial of a linear transformation OUTPUT: the characteristic polynomial of the tensor product of the linear transformations EXAMPLES:: sage: from crystalline_obstruction.main import tensor_charpoly sage: x = PolynomialRing(ZZ,"x").gen(); sage: tensor_charpoly((x - 3) * (x + 2), (x - 7) * (x + 5)) x^4 - 2*x^3 - 479*x^2 - 420*x + 44100 sage: (x - 21) * (x - 10) * (x + 14) * (x + 15) x^4 - 2*x^3 - 479*x^2 - 420*x + 44100 """ R = PolynomialRing(g.parent(), "y") y = R.gen() #x = g.parent().gen() A = f(y) B = R(g.homogenize(y)) return B.resultant(A)
def time_is_semistable(self): R = PolynomialRing(QQ, 'x') x = R.gen() Y = SuperellipticCurve(x**4 - 1, 3) v_2 = QQ.valuation(2) Y2 = SemistableModel(Y, v_2) return Y2.is_semistable()
def symbolic_to_polynomial(f, vars): # Rewrite a symbolic expression as a polynomial over SR in a given # list of variables. poly = f.polynomial(QQ) allvars = poly.variables() indices = [] for x in allvars: try: indices.append(vars.index(x)) except ValueError: indices.append(None) R = PolynomialRing(SR, len(vars), vars) res = R.zero() for coeff, alpha in zip(poly.coefficients(), poly.exponents()): if type(alpha) == int: # Once again, univariate polynomials receive special treatment # in Sage. alpha = [alpha] term = R(coeff) for i, e in enumerate(alpha): if not e: continue if indices[i] is None: term *= SR(allvars[i]**e) else: term *= R.gen(indices[i])**e res += term return res
def bad_factors_ec(E): """ INPUT: ``E`` -- an elliptic cuver over a number field OUTPUT: A list of pairs (f, bad_factor) where bad_factor are the coefficients of the associated to the prime f EXAMPLEs: sage: bad_factors_ec(EllipticCurve("35a2")) [(5, [1, 1]), (7, [1, -1])] sage: K.<a> = NumberField(x^2 - x - 7) sage: bad_factors_ec( EllipticCurve(K, [a + 1, a - 1, 1, 275*a - 886, -4395*a + 13961])) [(Fractional ideal (2), [1, 1]), (Fractional ideal (a - 1), [1, 1]), (Fractional ideal (a + 5), [1, -1])] sage: K.<phi> = NumberField(x^2 - x - 1) sage: bad_factors_ec(EllipticCurve(K, [1, phi + 1, phi, phi, 0])) [(Fractional ideal (5*phi - 2), [1, 1])] """ ZZT = PolynomialRing(ZZ, "T") T = ZZT.gen() F = E.conductor().factor() output = [None] * len(F) for i, (f, e) in enumerate(F): output[i] = (f, list(1 - E.local_data(f).bad_reduction_type() * T)) return output
def to_polredabs(K): """ INPUT: * "K" - a number field OUTPUT: * "phi" - an isomorphism K -> L, where L = QQ['x']/f and f a polynomial such that f = polredabs(f) """ R = PolynomialRing(QQ, 'x') x = R.gen(0) if K == QQ: L = QQ.extension(x, 'w') return QQ.hom(L) L = K.absolute_field('a') m1 = L.structure()[1] f = L.absolute_polynomial() g = pari(f).polredabs(1) g, h = g[0].sage(locals={'x': x}), g[1].lift().sage(locals={'x': x}) if debug: print('f', f) print('g', g) print('h', h) M = QQ.extension(g, 'w') m2 = L.hom([h(M.gen(0))]) return m2 * m1
def test_elliptic_curve(a, b, alpha=7, angles=12): from sage.all import cos, sin, pi E = EllipticCurve(QQ, [a, b]) rationalpoints = E.point_search(10) EQbar = EllipticCurve(QQbar, [a, b]) infx, infy, _ = rationalpoints[0] inf = EQbar(infx, infy) print inf R = PolynomialRing(QQ, "w") w = R.gen() f = w**3 + a * w + b iaj = InvertAJlocal(f, 256, method='gauss-legendre') iaj.set_basepoints([(mpmath.mpf(infx), mpmath.mpf(infy))]) for eps in [ cos(theta * 2 * pi / angles) + I * sin(theta * 2 * pi / angles) for theta in range(0, angles) ]: px = infx + eps py = iaj.sign * sqrt(-E.defining_polynomial().subs(x=px, y=0, z=1)) P = EQbar(px, py) try: (v, errorv) = iaj.to_J(px, infx) qx = (alpha * P - (alpha - 1) * inf).xy()[0] qxeps = CC(qx) + (mpmath.rand() + I * mpmath.rand()) / 1000 (t1, errort1) = iaj.solve(alpha * v, 100, iaj.error, [qxeps]) qxguess = t1[0, 0] print mpmath.fabs(qxguess - qx) < 2**(-mpmath.mp.prec / 2) except RuntimeWarning as detail: print detail
def sage_str_numberfield(nf, qq_variable, nf_variable): if nf == QQ: return 'QQ' else: assert nf.base_field() == QQ; Qpoly = PolynomialRing(QQ, qq_variable); return "NumberField(%s, '%s')" % (nf.defining_polynomial().subs(Qpoly.gen()), nf_variable);
def p_approximation_generic(f, p): r""" Return the generic `p`-approximation of ``f``. INPUT: - ``f`` -- a polynomial of degree `n` over a field `K`, with nonvanishing constant coefficient - ``p`` -- a prime number OUTPUT: Two polynomials `H` and `G` in `K(x)[t]` which are the `p`-approximation of the polynomial `F:=f(x+t)`, considered as polynomial in `t`. """ R = f.parent() x = R.gen() K = R.fraction_field() S = PolynomialRing(K, 't') t = S.gen() F = f(x + t) H, G = p_approximation(F, p) # d =[R(G[k]*f^k) for k in [0..f.degree()]] return H, G
def to_polredabs(K): """ INPUT: * "K" - a number field OUTPUT: * "phi" - an isomorphism K -> L, where L = QQ['x']/f and f a polynomial such that f = polredabs(f) """ R = PolynomialRing(QQ,'x') x = R.gen(0) if K == QQ: L = QQ.extension(x,'w') return QQ.hom(L) L = K.absolute_field('a') m1 = L.structure()[1] f = L.absolute_polynomial() g = pari(f).polredabs(1) g,h = g[0].sage(locals={'x':x}),g[1].lift().sage(locals={'x':x}) if debug: print 'f',f print 'g',g print 'h',h M = QQ.extension(g,'w') m2 = L.hom([h(M.gen(0))]) return m2*m1
def compute_order_element(self): if self._ring == None: self._ring = Endomorphism_ring(self._domain) deg = self.degree() trace = self.trace() R = PolynomialRing(self._ring.field(), 'x') x = R.gen() char_poly = x**2 - trace * x + deg roots = char_poly.roots(R) roots = [i[0] for i in roots for _ in range(i[1])] a = ZZ(roots[0][0].list()[0]) b = ZZ(roots[0][0].list()[1]) basis = self._ring.order().basis() A = multiplication_end(self._domain, a) # Isogeny is given by A+B*frobenius B = multiplication_end(self._domain, b) frob = frobenius(self._domain) if self.rational_maps() == add_maps( A, compose_endomorphisms(B, frob, self._domain), self._domain): return self._ring.field()(roots[0]) else: return self._ring.field()(roots[1])
def extension_of_finite_field(K, n): r""" Return a field extension of this finite field of degree n. INPUT: - ``K`` -- a finite field - ``n`` -- a positive integer OUTPUT: a field extension of `K` of degree `n`. This function is useful if `K` is constructed as an explicit extension `K = K_0[x]/(f)`; then ``K.extension(n)`` is not implemented. .. NOTE:: This function should be removed once ``trac.sagemath.org/ticket/26103`` has been merged. """ assert K.is_field() assert K.is_finite() q = K.order() R = PolynomialRing(K, 'z'+str(n)) z = R.gen() # we look for a small number e dividing q^n-1 but not q-1 e = min([d for d in (q**n-1).divisors() if not d.divides(q-1)]) F = (z**e-1).factor() f = [g for g, e in F if g.degree() == n][0] # this is very inefficient! return K.extension(f, 'z'+str(e))
def matlist_to_mat(mats, n=None): if not mats and n is None: raise ValueError('cannot guess size of matrices') R = PolynomialRing(QQ, 'y', len(mats)) if not mats: return matrix(R, n, n) return matrix(R, sum(R.gen(i) * a for i, a in enumerate(mats)))
def time_12_384(self): r""" TESTS:: sage: import henselization sage: from henselization.benchmarks.splitting_fields import SplittingField sage: SplittingField().time_12_384() # long time Factoring T^12 - 4*T^11 + 2*T^10 + 13*T^8 - 16*T^7 - 36*T^6 + 168*T^5 - 209*T^4 + 52*T^3 + 26*T^2 + 8*T - 13 over a field of degree 1 * 1… …factors with degrees [12] Found totally ramified part of degree 12 Factoring T^12 - 4*T^11 + 2*T^10 + 13*T^8 - 16*T^7 - 36*T^6 + 168*T^5 - 209*T^4 + 52*T^3 + 26*T^2 + 8*T - 13 over a field of degree 1 * 12… …factors with degrees [8, 2, 1, 1] Found unramified part of degree 2 Factoring T^12 - 4*T^11 + 2*T^10 + 13*T^8 - 16*T^7 - 36*T^6 + 168*T^5 - 209*T^4 + 52*T^3 + 26*T^2 + 8*T - 13 over a field of degree 2 * 1… …factors with degrees [12] Found totally ramified part of degree 12 Factoring T^12 - 4*T^11 + 2*T^10 + 13*T^8 - 16*T^7 - 36*T^6 + 168*T^5 - 209*T^4 + 52*T^3 + 26*T^2 + 8*T - 13 over a field of degree 2 * 12… …factors with degrees [4, 4, 1, 1, 1, 1] Found totally ramified part of degree 4 Factoring T^12 - 4*T^11 + 2*T^10 + 13*T^8 - 16*T^7 - 36*T^6 + 168*T^5 - 209*T^4 + 52*T^3 + 26*T^2 + 8*T - 13 over a field of degree 2 * 48… …factors with degrees [4, 1, 1, 1, 1, 1, 1, 1, 1] Found totally ramified part of degree 4 Factoring T^12 - 4*T^11 + 2*T^10 + 13*T^8 - 16*T^7 - 36*T^6 + 168*T^5 - 209*T^4 + 52*T^3 + 26*T^2 + 8*T - 13 over a field of degree 2 * 192… …factors with degrees [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] """ K = QQ.henselization(2) R = PolynomialRing(K, 'T') T = R.gen() f = T**12 - 4 * T**11 + 2 * T**10 + 13 * T**8 - 16 * T**7 - 36 * T**6 + 168 * T**5 - 209 * T**4 + 52 * T**3 + 26 * T**2 + 8 * T - 13 splitting_field(f)
def __init__(self, f, n, name='y'): R = f.parent() assert R.variable_name() != name, "variable names must be distinct" k = R.base_ring() assert k.characteristic() == 0 or ZZ(n).gcd(k.characteristic( )) == 1, "the characteristic of the base field must be prime to n" ff = f.factor() assert gcd( [m for g, m in ff] + [n]) == 1, "the equation y^n=f(x) must be absolutely irreducible" self._n = n self._f = f self._ff = ff self._name = name FX = FunctionField(k, R.variable_name()) S = PolynomialRing(FX, 'T') T = S.gen() FY = FX.extension(T**n - FX(f), name) self._function_field = FY self._constant_base_field = k self._extra_extension_degree = ZZ(1) self._covering_degree = n self._coordinate_functions = self.coordinate_functions() self._field_of_constants_degree = ZZ(1) self._is_separable = True
def _test(self): from sage.all import QQ, PolynomialRing, GaussValuation R = PolynomialRing(QQ, 'x') x = R.gen() v = QQ.valuation(2) v = GaussValuation(R, v).augmentation(x + 1, QQ(1) / 2) f = x**4 - 30 * x**2 - 75 v.mac_lane_step(f)
def muladd(cls, kyber, a, b, c, l=None): """ Compute `a \cdot b + c` using big-integer arithmetic :param cls: Skipper class :param kyber: Kyber class, inherit and change constants to change defaults :param a: vector of polynomials in `ZZ_q[x]/(x^n+1)` :param b: vector of polynomials in `ZZ_q[x]/(x^n+1)` :param c: polynomial in `ZZ_q[x]/(x^n+1)` :param l: bits of precision """ m, k = 4, kyber.k w = kyber.n//m R, x = PolynomialRing(ZZ, "x").objgen() f = R([1]+[0]*(w-1)+[1]) if l is None: # Could try passing degree w, but would require more careful # sneezing l = ceil(cls.prec(kyber)) R = PolynomialRing(ZZ, "x") x = R.gen() A = vector(R, k, [sum(cls.snort(cls.ff(a[j], m, i), f, 2**l) * x**i for i in range(m)) for j in range(k)]) C = sum(cls.snort(cls.ff(c, m, i), f, 2**l) * x**i for i in range(m)) B = vector(R, k, [sum(cls.snort(cls.ff(b[j], m, i), f, 2**l) * x**i for i in range(m)) for j in range(k)]) F = f(2**l) # MUL: k * 3^2 (Karatsuba for length 4) # % F here is applied to the 64-coeff-packs. # k comes from len(A) = len(B) = k, each constrains # a deg 4 poly needing (recursive) karatsuba => 9 W = (A*B + C) % F # MUL: 3 # specific trick for how we multiply degree n = 256 polys # the coefficients from above need readjustment # here doing 2**l * is basically doing y * !!! and if this wraps around # it takes care of the - in front W = sum((W[0+i] + (2**l * W[m+i] % F))*x**i for i in range(m-1)) + W[m-1]*x**(m-1) D = [cls.sneeze(W[i] % F, f, 2**l) for i in range(m)] d = [] for j in range(w): for i in range(m): d.append(D[i][j]) return R(d)
def _test(self): from sage.all import FunctionField, QQ, PolynomialRing K = FunctionField(QQ, 'x') x = K.gen() R = PolynomialRing(K, 'y') y = R.gen() L = K.extension(y**3 - 1 / x**3 * y + 2 / x**4, 'y') v = K.valuation(x) v.extensions(L)
def _test(self): from sage.all import QQ, PolynomialRing, GaussValuation, FunctionField R = PolynomialRing(QQ, 'x') x = R.gen() v = GaussValuation(R, QQ.valuation(2)) K = FunctionField(QQ, 'x') x = K.gen() v = K.valuation(v) K.valuation((v, K.hom(x/2), K.hom(2*x)))
def extract_frobenius_poly(E, f): p = E.base_field().characteristic() Q = PolynomialRing(E.base_field(), 'x') x = Q.gen() f = Q(f) if f.is_constant(): return f monomials = [x**(u.degree() // p) for u in f.monomials()] return sum([a[0] * a[1] for a in zip(f.coefficients(), monomials)])
def _test(self): from sage.all import PolynomialRing, QQ, NumberField, GaussValuation, FunctionField R = PolynomialRing(QQ, 'x') x = R.gen() K = NumberField(x**6 + 126 * x**3 + 126, 'pi') v = K.valuation(2) R = PolynomialRing(K, 'x') x = R.gen() v = GaussValuation(R, v).augmentation(x, QQ(2) / 3) F = FunctionField(K, 'x') x = F.gen() v = F.valuation(v) S = PolynomialRing(F, 'y') y = S.gen() w0 = GaussValuation(S, v) G = y**2 - x**3 - 3 w1 = w0.mac_lane_step(G)[0] w1.mac_lane_step(G)
def kernel_polynomial_from_kernel(E, kernel): R_ext = PolynomialRing(kernel[0].curve().base_field(), 'x') x = R_ext.gen() f = 1 for P in kernel: f *= (x - P[0]) R = PolynomialRing(E.base_field(), 'x') f = R(f / f.gcd(f.derivative())) f /= f.list()[len(f.list()) - 1] return f
def alexander_poly_from_seifert(V): R = PolynomialRing(ZZ, 't') t = R.gen() poly = (t * V - V.transpose()).determinant() if poly.leading_coefficient() < 0: poly = -poly e = min(poly.exponents()) if e > 0: poly = poly // t**e return poly
def time_is_semistable(self): K = FunctionField(QQ, 'x') x = K.gen() R = PolynomialRing(K, 'T') T = R.gen() f = 64 * x**3 * T - 64 * x**3 + 36 * x**2 * T**2 + 208 * x**2 * T + 192 * x**2 + 9 * x * T**3 + 72 * x * T**2 + 240 * x * T + 64 * x + T**4 + 9 * T**3 + 52 * T**2 + 48 * T L = K.extension(f, 'y') Y = SmoothProjectiveCurve(L) v = QQ.valuation(13) M = SemistableModel(Y, v) return M.is_semistable()
def clean_laurent_to_poly(p, error=10**-8): R = p.parent() P = PolynomialRing(R.base_ring(), R.variable_names()) t = P.gen() cp = clean_laurent(p, error) exponents = univ_exponents(cp) if len(exponents) == 0: return P(0) m = min(exponents) return sum([a * t**(n - m) for a, n in zip(cp.coefficients(), exponents)], P(0))
def x_coordinates(self): if self.x_coordinate_cache is None: c = self.coordinates() Rw = PolynomialRing(self.Pic.Rdoubleextraprec, "T") G = Rw(1) for pair in c: if pair not in [+Infinity, -Infinity]: G *= (Rw.gen() - pair[0]) self.x_coordinate_cache = list(G) return self.x_coordinate_cache
def _get_Rgens(self): d = self.dim if self.single_generator: if self.hecke_ring_power_basis and self.field_poly_root_of_unity != 0: R = PolynomialRing(QQ, self._nu_var) else: R = PolynomialRing(QQ, 'beta') beta = R.gen() return [beta**i for i in range(d)] else: R = PolynomialRing(QQ, ['beta%s' % i for i in range(1,d)]) return [1] + [g for g in R.gens()]
def _test(self): from sage.all import GF, PolynomialRing, proof k = GF(4, 'u') u = k.gen() R = PolynomialRing(k, 'v') v = R.gen() l = R.quo(v**3 + v + 1) v = l.gen() R = PolynomialRing(l, 'x,y') x, y = R.gens() f = y**3 + x**3 + (u + 1) * x with proof.WithProof('polynomial', False): f.factor()
def gen_func_maybe_except_cusp(j): ''' j: even nonnegative integer If j = 0, it returns the Hilbert series (as a rational function) of the space of Siegel-Eisenstein series and Klingen-Eisenstein series. If j > 0, it returns a Hilbert series which is equal to sum_{k > 0} dim N_{k, j} t^k up to a polynomial with degree < 5. Here N_{k, j} is the space of Klingen-Eisenstein series'. ''' R = PolynomialRing(QQ, names="t") t = R.gen() h1 = t ** 12 / ((1 - t ** 4) * (1 - t ** 6)) if j > 0: f = sum([t ** k * dimension_cusp_forms(1, k) for k in range(0, 5 + j)]) return (h1 - f) * t ** (-j) elif j == 0: return h1 + R(1) / (1 - t ** 2) - t ** 2
def gen_func_maybe_except_cusp_num(j): R = PolynomialRing(QQ, names="t") t = R.gen() dnm = (1 - t ** 4) * (1 - t ** 6) * (1 - t ** 10) * (1 - t ** 12) return R(gen_func_maybe_except_cusp(j) * dnm)
def t_dnm(): R = PolynomialRing(QQ, names="t") t = R.gen() dnm = (1 - t ** 4) * (1 - t ** 6) * (1 - t ** 10) * (1 - t ** 12) return dnm