Exemplo n.º 1
0
def add_trace_and_norm_ladic(g, D, alpha_geo, verbose=True):
    if verbose:
        print "add_trace_and_norm_ladic()"
    #load Fields
    L = D['L']
    if L is QQ:
        QQx = PolynomialRing(QQ, "x")
        L = NumberField(QQx.gen(), "b")

    prec = D['prec']
    CCap = ComplexField(prec)

    # load endo
    alpha = D['alpha']
    rosati = bound_rosati(alpha_geo)

    if alpha.base_ring() is not L:
        alpha_K = copy(alpha)
        alpha = Matrix(L, 2, 2)
        #shift alpha field from K to L
        for i, row in enumerate(alpha_K.rows()):
            for j, elt in enumerate(row):
                if elt not in L:
                    assert elt.base_ring().absolute_polynomial(
                    ) == L.absolute_polynomial()
                    alpha[i, j] = L(elt.list())
                else:
                    alpha[i, j] = L(elt)

    # load algx_poly
    algx_poly_coeff = D['algx_poly']

    #sometimes, by mistake the algx_poly is defined over K where K == L, but with a different name
    for i, elt in enumerate(algx_poly_coeff):
        if elt not in L:
            assert elt.base_ring().absolute_polynomial(
            ) == L.absolute_polynomial()
            algx_poly_coeff[i] = L(elt.list())
        else:
            algx_poly_coeff[i] = L(elt)

    x_poly = vector(CCap, D['x_poly'])
    for i in [0, 1]:
        assert almost_equal(
            x_poly[i],
            algx_poly_coeff[i]), "%s != %s" % (algx_poly_coeff[i], x_poly[i])

    # load P
    P0 = vector(L, [D['P'][0], D['P'][1]])
    for i, elt in enumerate(P0):
        if elt not in L:
            assert elt.base_ring().absolute_polynomial(
            ) == L.absolute_polynomial()
            P0[i] = L(elt.list())
        else:
            P0[i] = L(elt)
    if verbose:
        print "P0 = %s" % (P0, )

    # load image points, P1 and P2

    L_poly = PolynomialRing(L, "xL")
    xL = L_poly.gen()

    Xpoly = L_poly(algx_poly_coeff)
    if Xpoly.is_irreducible():
        M = Xpoly.root_field("c")
    else:
        # this avoids bifurcation later on in the code, we don't want to be always checking if M is L
        M = NumberField(xL, "c")

    # trying to be sure that we keep the same complex_embedding...
    M_complex_embedding = 0
    if L.gen() not in QQ:
        M_complex_embedding = None
        Lgen_CC = toCCap(L.gen(), prec=prec)
        for i, _ in enumerate(M.complex_embeddings()):
            if norm(Lgen_CC - M(L.gen()).complex_embedding(prec=prec, i=i)
                    ) < CCap(2)**(-0.7 * Lgen_CC.prec()) * Lgen_CC.abs():
                M_complex_embedding = i

        assert M_complex_embedding is not None, "\nL = %s\n%s = %s\n%s" % (
            L, L.gen(), Lgen_CC, M.complex_embeddings())

    M_poly = PolynomialRing(M, "xM")
    xM = M_poly.gen()

    # convert everything to M
    P0_M = vector(M, [elt for elt in P0])
    alpha_M = Matrix(M, [[elt for elt in row] for row in alpha.rows()])
    Xpoly_M = M_poly(Xpoly)

    for i in [0, 1]:
        assert almost_equal(x_poly[i],
                            Xpoly_M.list()[i],
                            ithcomplex_embedding=M_complex_embedding
                            ), "%s != %s" % (Xpoly_M.list()[i], x_poly[i])

    P1 = vector(M, 2)
    P1_ap = vector(CCap, D['R'][0])
    P2 = vector(M, 2)
    P2_ap = vector(CCap, D['R'][1])

    M_Xpoly_roots = Xpoly_M.roots()
    assert len(M_Xpoly_roots) > 0

    Ypoly_M = prod([xM**2 - g(root)
                    for root, _ in M_Xpoly_roots])  # also \in L_poly

    assert sum(m for _, m in Ypoly_M.roots(M)) == Ypoly_M.degree(
    ), "%s != %s\n%s\n%s" % (sum(m for _, m in Ypoly_M.roots(M)),
                             Ypoly_M.degree(), Ypoly_M, Ypoly_M.roots(M))

    if len(M_Xpoly_roots) == 1:
        # we have a double root
        P1[0] = M_Xpoly_roots[0][0]
        P2[0] = M_Xpoly_roots[0][0]
        ae_prec = prec * 0.4
    else:
        assert len(M_Xpoly_roots) == 2
        ae_prec = prec
        # we have two distinct roots
        P1[0] = M_Xpoly_roots[0][0]
        P2[0] = M_Xpoly_roots[1][0]
        if not_equal(P1_ap[0], P1[0],
                     ithcomplex_embedding=M_complex_embedding):
            P1[0] = M_Xpoly_roots[1][0]
            P2[0] = M_Xpoly_roots[0][0]

    assert almost_equal(
        P1_ap[0],
        P1[0],
        ithcomplex_embedding=M_complex_embedding,
        prec=ae_prec), "\n%s = %s \n != %s" % (
            P1[0], toCCap(
                P1[0], ithcomplex_embedding=M_complex_embedding), CC(P1_ap[0]))
    assert almost_equal(
        P2_ap[0],
        P2[0],
        ithcomplex_embedding=M_complex_embedding,
        prec=ae_prec), "\n%s = %s \n != %s" % (
            P2[0], toCCap(
                P2[0], ithcomplex_embedding=M_complex_embedding), CC(P2_ap[0]))

    # figure out the right square root

    # pick the default branch
    P1[1] = sqrt(g(P1[0]))
    P2[1] = sqrt(g(P2[0]))

    if 0 in [P1[1], P2[1]]:
        print "one of image points is a Weirstrass point"
        print P1
        print P2
        raise ZeroDivisionError

    #switch if necessary
    if not_equal(P1_ap[1],
                 P1[1],
                 ithcomplex_embedding=M_complex_embedding,
                 prec=ae_prec):
        P1[1] *= -1

    if not_equal(P2_ap[1],
                 P2[1],
                 ithcomplex_embedding=M_complex_embedding,
                 prec=ae_prec):
        P2[1] *= -1

    # double check
    for i in [0, 1]:
        assert almost_equal(P1_ap[i],
                            P1[i],
                            ithcomplex_embedding=M_complex_embedding,
                            prec=ae_prec), "%s != %s" % (P1_ap[i], P1[i])
        assert almost_equal(P2_ap[i],
                            P2[i],
                            ithcomplex_embedding=M_complex_embedding,
                            prec=ae_prec), "%s != %s" % (P2_ap[i], P2[i])

    # now alpha, P0 \in L
    # P1, P2 \in L

    if verbose:
        print "P1 = %s\nP2 = %s" % (P1, P2)
        print "Computing the trace and the norm ladically\n"
        trace_and_norm = trace_and_norm_ladic(L,
                                              M,
                                              P0_M,
                                              P1,
                                              P2,
                                              g,
                                              2 * alpha_M,
                                              16 * rosati,
                                              primes=ceil(prec * L.degree() /
                                                          61))
    else:
        trace_and_norm = trace_and_norm_ladic(L,
                                              M,
                                              P0_M,
                                              P1,
                                              P2,
                                              g,
                                              2 * alpha_M,
                                              16 * rosati,
                                              primes=ceil(prec * L.degree() /
                                                          61))

    # Convert the coefficients to polynomials
    trace_numerator, trace_denominator, norm_numerator, norm_denominator = [
        L_poly(coeff) for coeff in trace_and_norm
    ]

    assert trace_numerator(P0[0]) == trace_denominator(
        P0[0]) * -algx_poly_coeff[1], "%s/%s (%s) != %s" % (
            trace_numerator, trace_denominator, P0[0], -algx_poly_coeff[1])
    assert norm_numerator(P0[0]) == norm_denominator(
        P0[0]) * algx_poly_coeff[0], "%s/%s (%s) != %s" % (
            norm_numerator, norm_denominator, P0[0], algx_poly_coeff[0])
    buffer = "# x1 + x2 = degree %d/ degree %d\n" % (
        trace_numerator.degree(), trace_denominator.degree())
    buffer += "# = (%s) / (%s) \n" % (trace_numerator, trace_denominator)
    buffer += "# max(%d, %d) <= %d\n\n" % (
        trace_numerator.degree(), trace_denominator.degree(), 16 * rosati)

    buffer += "# x1 * x2 = degree %d/ degree %d\n" % (
        norm_numerator.degree(), norm_denominator.degree())
    buffer += "# = (%s) / (%s) \n" % (norm_numerator, norm_denominator)
    buffer += "# max(%d, %d) <= %d\n" % (
        norm_numerator.degree(), norm_denominator.degree(), 16 * rosati)

    if verbose:
        print buffer
        print "\n"
    assert max(trace_numerator.degree(),
               trace_denominator.degree()) <= 16 * rosati
    assert max(norm_numerator.degree(),
               norm_denominator.degree()) <= 16 * rosati

    if verbose:
        print "Veritfying if x1*x2 and x1 + x2 are correct..."

    verified = verify_algebraically(g,
                                    P0,
                                    alpha,
                                    trace_and_norm,
                                    verbose=verbose)
    if verbose:
        print "\nDoes it act on the tangent space as expected? %s\n" % verified
        print "Done add_trace_and_norm_ladic()"

    return verified, [
        trace_numerator.list(),
        trace_denominator.list(),
        norm_numerator.list(),
        norm_denominator.list()
    ]
Exemplo n.º 2
0
def compute_alpha_point(g,
                        iaj,
                        alpha,
                        P0,
                        digits,
                        power,
                        verbose,
                        aggressive=True,
                        append=""):
    # input:
    # * g, defining polynomial of the hyperelliptic curve
    # * iaj = InvertAJglobal class
    # * alpha = analytic representation of the endomorphism acting on the tangent space
    # * digits = how many digits to work with
    # * power, we will divide by 2**power before inverting the abel jacobi map
    # * P0, a point in the curve for which we will compute alpha*2(P - \infty) = P1 + P2 - \infty
    # * verbose
    # * agressive, raise ZeroDivisionError  if we get a P1[0] = P2[0] or one of the points is infty
    # * append, a string to append to the numberfield generators
    #
    # output: a dictionary with the following keys
    # TODO add the keys

    output = {}
    K = alpha.base_ring()
    CCap = iaj.C
    prec = CCap.precision()
    output['prec'] = prec
    x0, y0 = P0
    Kz = PolynomialRing(K, "z")
    z = Kz.gen()
    if verbose:
        print "compute_alpha_point()"
        print "P0 = %s" % (P0, )
    #deal with the field of definition
    if y0 in K:
        if K is QQ:
            L = K
            from_K_to_L = QQ.hom(1, QQ)
        else:
            L = K.change_names("b" + append)
            from_K_to_L = L.structure()[1]
    else:
        L, from_K_to_L = (z**2 - g(x0)).splitting_field("b" + append,
                                                        simplify_all=True,
                                                        map=True)

    output['L'] = L
    #    output['L_str'] = sage_str_numberfield(L, 'x','b'+append);
    output['from_K_to_L'] = from_K_to_L
    #    output['L_gen'] =  toCCap(L.gen(), 53);

    # figure out y0 in L
    y0_ap = toCCap(y0, prec)
    y0s = [elt for elt, _ in (z**2 - g(x0)).roots(L)]
    assert len(y0s) == 2
    y0s_ap = [toCCap(elt, prec) for elt in y0s]
    if norm(y0_ap - y0s_ap[0]) < norm(y0_ap - y0s_ap[1]):
        y0 = y0s[0]
    else:
        y0 = y0s[1]

    P0 = vector(L, [x0, y0])

    alpha_L = Matrix(L, [[from_K_to_L(elt) for elt in row]
                         for row in alpha.rows()])
    alpha_ap = Matrix(CCap, [toCCap_list(row, prec) for row in alpha_L.rows()])

    output['P'] = P0
    output['alpha'] = alpha_L

    if verbose:
        print "L = %s" % L
        print "%s = %s" % (L.gen(), toCCap(L.gen(), 53))
        print "P0 = %s" % (P0, )
        print "alpha = %s" % ([[elt for elt in row]
                               for row in alpha_L.rows()], )

    P0_ap = vector(CCap, toCCap_list(P0, prec + 192))

    if verbose:
        print "P0_ap = %s" % (vector(CC, P0_ap), )

    if verbose:
        print "Computing AJ of P0..."
        c, w = cputime(), walltime()
        ajP0 = vector(CCap, AJ1_digits(g, P0_ap, digits))
        print "Time: CPU %.2f s, Wall: %.2f s" % (
            cputime(c),
            walltime(w),
        )
        print
    else:
        ajP0 = vector(CCap, AJ1_digits(g, P0_ap, digits))

    output['ajP'] = ajP0

    aj2P0 = 2 * ajP0
    alpha2P0_an = alpha_ap * aj2P0
    if verbose:
        print "Working over %s" % CCap

    invertAJ_tries = 3
    for i in range(invertAJ_tries):
        #try invertAJ_tries times to invertAJ
        try:
            if verbose:
                print "\n\ninverting AJ..."
                c, w = cputime(), walltime()
                alpha2P0_div = iaj.invertAJ(alpha2P0_an, power)
                print "Time: CPU %.2f s, Wall: %.2f s" % (
                    cputime(c),
                    walltime(w),
                )
                print "\n\n"
            else:
                alpha2P0_div = iaj.invertAJ(alpha2P0_an, power)
            break
        except AssertionError as error:
            print error
            if verbose:
                print "an assertion failed while inverting AJ.."
            if i == invertAJ_tries - 1:
                if verbose:
                    print "retrying with a new P0"
                    print
                raise ZeroDivisionError
            else:
                iaj.iajlocal.set_basepoints()
                if verbose:
                    print "retrying again with a new set of base points"

    if verbose:
        print "Computing the Mumford coordinates of alpha(2*P0 - 2*W)"
        c, w = cputime(), walltime()
        R0, R1 = alpha2P0_div.coordinates()
        print "Time: CPU %.2f s, Wall: %.2f s" % (
            cputime(c),
            walltime(w),
        )
    else:
        R0, R1 = alpha2P0_div.coordinates()

    points = [R0, R1]
    x_poly = alpha2P0_div.x_coordinates()
    output['R'] = points
    output['x_poly'] = x_poly

    if (R0 in [+Infinity, -Infinity]) or (R1 in [+Infinity, -Infinity]):
        if aggressive:
            # we want to avoid these situations
            if verbose:
                print "One of the coordinates is at infinity"
                if R0 in [+Infinity, -Infinity]:
                    print "R0 = %s" % (R0, )
                else:
                    print "R1 = %s" % (R1, )
                print "retrying with a new P0"
                print
            raise ZeroDivisionError
        else:
            return output

    buffer = "# R0 = %s\n" % (vector(CC, R0), )
    buffer += "# R1 = %s\n" % (vector(CC, R1), )
    buffer += "# and \n# x_poly = %s\n" % (vector(CC, x_poly), )

    if verbose:
        print buffer
    assert len(x_poly) == 3

    algx_poly = [NF_embedding(coeff, L) for coeff in x_poly]
    buffer = "algx_poly = %s;\n" % (algx_poly, )
    if L != QQ:
        buffer += "#where %s ~ %s\n" % (L.gen(), L.gen().complex_embedding())
    buffer += "\n"
    if verbose:
        print buffer
        sys.stdout.flush()
        sys.stderr.flush()

    output['algx_poly'] = algx_poly

    if None in algx_poly:
        if aggressive:
            if verbose:
                print "No algebraic expression  for the polynomial"
                print "retrying with a new P0"
                sys.stdout.flush()
                sys.stderr.flush()
            raise ZeroDivisionError
        else:
            return output
    #c, b, a = algx_poly
    #if aggressive and b**2 - 4*a*c == 0:
    #    raise ZeroDivisionError
    if verbose:
        print "Done compute_alpha_point()"
    return output
Exemplo n.º 3
0
def newton_linear(P0, P1, P2, f, alpha, PSring, prec):
    assert P0.base_ring() is P1.base_ring()
    assert P1.base_ring() is P2.base_ring()
    assert P0.base_ring() is alpha.base_ring()
    assert P0.base_ring() is PSring.base_ring()
    assert f.base_ring() in [QQ, ZZ, P0.base_ring()]
    T = PSring.gen()
    #xi_0 = xi(0)
    x0_0 = PSring(P0[0])
    x1_0 = PSring(P1[0])
    x2_0 = PSring(P2[0])

    y0_0 = P0[1]
    y1_0 = P1[1]
    y2_0 = P2[1]

    b0, b1, b2 = 1, 1, 1

    py0_0 = sqrt(f(x0_0 + T)).list()[0]
    py1_0 = sqrt(f(x1_0 + T)).list()[0]
    py2_0 = sqrt(f(x2_0 + T)).list()[0]

    if PSring.base_ring().is_exact():
        if y0_0 != py0_0:
            b0 = -1
        if y1_0 != py1_0:
            b1 = -1
        if y2_0 != py2_0:
            b2 = -1
        assert y0_0 == b0 * py0_0, "wrong branch at P0? %s != %s" % (y0_0, b0 *
                                                                     py0_0)
        assert y1_0 == b1 * py1_0, "wrong branch at P1? %s != %s" % (y1_0, b1 *
                                                                     py1_0)
        assert y2_0 == b2 * py2_0, "wrong branch at P2? %s != %s" % (y2_0, b2 *
                                                                     py2_0)
    else:
        if norm(y0_0 - py0_0) > norm(y0_0 + py0_0):
            b0 = -1
        if norm(y1_0 - py1_0) > norm(y1_0 + py1_0):
            b1 = -1
        if norm(y2_0 - py2_0) > norm(y2_0 + py2_0):
            b2 = -1
        closetozero = 2**(-0.8 * PSring.base_ring().prec())
        assert norm(y0_0 +
                    b0 * py0_0) > norm(y0_0), "%.3e vs %.3e wrong branch?" % (
                        norm(y0_0 - b0 * py0_0), norm(y0_0 + b0 * py0_0))
        assert norm(y0_0 - b0 * py0_0) < norm(
            y0_0) * closetozero, "%.3e vs %.3e wrong branch?" % (
                norm(y0_0 - b0 * py0_0), norm(y0_0 + b0 * py0_0))

        assert norm(y1_0 +
                    b1 * py1_0) > norm(y1_0), "%.3e vs %.3e wrong branch?" % (
                        norm(y1_0 - b1 * py1_0), norm(y1_0 + b1 * py1_0))
        assert norm(y1_0 - b1 * py1_0) < norm(
            y1_0) * closetozero, "%.3e vs %.3e wrong branch?" % (
                norm(y1_0 - b1 * py1_0), norm(y1_0 + b1 * py1_0))

        assert norm(y2_0 +
                    b2 * py2_0) > norm(y2_0), "%.3e vs %.3e wrong branch?" % (
                        norm(y2_0 - b2 * py2_0), norm(y2_0 + b2 * py2_0))
        assert norm(y2_0 - b2 * py2_0) < norm(
            y2_0) * closetozero, "%.3e vs %.3e wrong branch?" % (
                norm(y2_0 - b2 * py2_0), norm(y2_0 + b2 * py2_0))

    x1 = x1_0 + O(T)
    x2 = x2_0 + O(T)

    p = 1

    Tsub = x0_0 + T
    fps = PSring(f)(Tsub)
    sqrtfps = sqrt(fps)

    row0 = PSring(alpha.row(0).list())(Tsub)
    row1 = PSring(alpha.row(1).list())(Tsub)

    if x1_0 != x2_0:
        # Iteration to solve the differential equation, gains 1 term
        # alternatively we could solve a linear ODE to double the number of terms
        while p < prec:
            m = b0 / ((x2 - x1) * sqrtfps)
            dx1 = m * b1 * sqrt(f(x1)) * (row0 * x2 - row1)
            dx2 = m * b2 * sqrt(f(x2)) * (row1 - row0 * x1)
            p += 1
            x1 = x1_0 + dx1.integral() + O(T**p)
            x2 = x2_0 + dx2.integral() + O(T**p)
    else:
        #the degenerate case
        row0_y = row0 * b0 / sqrtfps
        half = P0.base_ring()(1 / 2)
        while p < prec:
            dx1 = half * b1 * sqrt(f(x1)) * row0_y
            x1 = x1_0 + dx1.integral() + O(T**p)
            p += 1
        # check second equation
        if 2 * x1 * x1.derivative() * b1 / sqrt(f(x1)) != row1 * b0 / sqrtfps:
            print "x1(0) = x2(0), but x1 != x2"
            raise ZeroDivisionError

        x2 = x1

    return x1, x2
Exemplo n.º 4
0
    def support(self, basis):
        # Input:  a basis in H**0( D_0) for H**0((g+1)\infty - E), where E is an effective divisor of degree g/2
        # Output: returns the support of E as a list of g points 
 
        # Computing the intersection of 
        # <1, x, x**2,..., x**g> with <basis>
        B = basis.augment( identity_matrix(self.g + 1).stack(Matrix(basis.nrows() - (self.g + 1), (self.g + 1))))
        KB, upper, lower  = Kernel(B, basis.ncols() + self.g )
        if self.verbose:
            print "KB upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
        maxlower = self.lower
        
        result = [None for _ in range(self.g)]
        
        # if dim of the intersection of <1, x, x**2,..., x**g> with <basis> is 1
        if self.threshold_check(upper, lower):
            # we have the expected rank, all the roots are simple, unless E = 2*P
            # as in genus = 2 we can't have E = tau(P) + P
            maxlower = max(maxlower, lower);

            Rw = PolynomialRing(self.Rdoubleextraprec, "T")
            poly = Rw( KB.column(0)[-(self.g + 1):].list() )
            
            if self.g == 2:
                a, b, c = list(poly)
                disc = (b**2 - 4*a*c).abs()
                #a2 = (a**2).abs()
                dpoly = poly.derivative()
                if self.threshold_check((a**2).abs(), disc):
                    xcoordinates = dpoly.complex_roots() + dpoly.complex_roots()
                    maxlower = max(maxlower, disc);
                else:
                    xcoordinates = poly.complex_roots()
            else:
                xcoordinates = poly.complex_roots()

            for i, x in enumerate(xcoordinates):
                    y0 = self.Rextraprec(sqrt(self.f(x)));
                    x0 = self.Rextraprec(x)
                    vp = vector(self.R, [x0**u * y0**v for u, v in self.Vexps[:basis.nrows()] ]);
                    vn = vector(self.R, [x0**u * (-y0)**v for u, v in self.Vexps[:basis.nrows()] ]);
                    np = norm( vp * basis);
                    nn = norm( vn * basis);
                    #is it a simple root?
                    if dpoly(x).abs() < self.notzero:
                        assert self.g == 2, "one needs to be extra careful for genus > 2" 
                        
                    if self.threshold_check(np, nn) and not self.threshold_check(nn, np): #np > nn ~ 0
                        result[i] = (x0, -y0);
                        maxlower = max(maxlower, nn);
                    elif  not self.threshold_check(np, nn) and self.threshold_check(nn, np): #nn > np ~ 0
                        result[i] = (x0, y0);
                        maxlower = max(maxlower, np);

                    else:
                        print "sign for y is not clear: neg = %s, pos = %s,\ny = %s + %s * I = 0?" % tuple(vector(RealField(15), (nn, np, y0.real(), y0.imag())));
                        if nn > np:
                            result[i] = (x0, y0);
                            maxlower = max(maxlower, np);

                        else:
                            result[i] = (x0, -y0);
                            maxlower = max(maxlower, nn);

#                    else:
#                        assert self.g == 2, "for now only genus 2"
#                        # for g = 2,  we can't have E = P + tau(P), as (x - x0) \in H**0((g+1)\infty - E)
#                        # thus the rank of B should be at most  basis.ncols() + 1
#                        for j, xj in enumerate(xcoordinates[i+1:]):
#                            if (x0 - xj).abs() < self.notzero:
#                                # we might have a double root, and at the moment this should only work for g == 2
#                                break;
#                        #j is the other root 
#                        if self.threshold_check(np, nn) and not self.threshold_check(nn, np):
#                            result[j] = result[i] = (x0, -y0);
#                        elif not self.threshold_check(np, nn) and self.threshold_check(nn, np):
#                            result[j] = result[i] = (x0, y0);
#                        else:
#                            #this covers the case that y0 ~ 0
#                            if self.f(x0) > self.almostzero:
#                                print "sign for y is not clear: neg = %.2e, pos = %.2e,\nassuming y = %.2e + %.2e * I = 0" % (nn, np, y0.real(), y0.imag());
#                            result[j] = result[i] = (x0, 0);
#                    
#                                
            return result, maxlower;
        else:
            if self.verbose:
                print "there is at least a root at infinity, i.e. \inf_{+,-} \in supp E"
                print (RealField(35)(upper), RealField(35)(lower))
            # there is at least a root at infinity, i.e. \inf_{+,-} \in supp E
            # recall that \inf_{+} + \inf_{-} ~ P + tau(P), and in this case we have booth roots at infinity 
            assert self.g == 2, "for now only genus 2"


            Ebasis, upper, lower = EqnMatrix(basis,  basis.ncols() )
            assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
            maxlower = max(maxlower, lower);

            B = basis.augment( identity_matrix(self.g ).stack(Matrix(basis.nrows() - (self.g ), (self.g ))))
            KB, upper, lower  = Kernel(B, basis.ncols() + self.g - 1 )

            # 1 \in <basis>
            v0 = vector(self.R, [0] * basis.nrows())
            v0[0] = 1
            norm_one = norm(Ebasis * v0)
      
            if not self.threshold_check(upper, lower):
                # dim <1, x> cap <basis> = 2

                #1 \in <basis>
                assert self.threshold_check(1, norm_one),  "upper = %s lower = %s norm_one = %s " % (RealField(35)(upper), RealField(35)(lower), RealField(35)(norm_one));
                maxlower = max(maxlower, norm_one);
                
                #x \in <basis>

                vx = vector(self.R, [0]*basis.nrows())
                vx[1] = 1
                lower = norm(Ebasis * vx)
                assert self.threshold_check(1, lower), "lower = %s" % (RealField(35)(lower),);
                maxlower = max(maxlower, lower);
                
                vx2 = vector(self.R, [0]*basis.nrows())
                vx2[2] = 1
                lower = norm(Ebasis * vx2)
                if self.threshold_check(1, lower):
                    # E = \inf_{+} + \inf_{-} 
                    # <1, x, x^2>  \in H**0((g+1)\infty - E)
                    # x \in H^0 => 0 + 2 \infty - E >= 0
                    # x^2 \in H^0 => 4 * P_0 + \infty - E >= 0 for all P0

                    maxlower = max(maxlower, lower);
                    return [+Infinity, -Infinity], maxlower

                # <1, x>  \in H**0((g+1)\infty - E)
                # but not x^2
                # supp(E) \subsetneq { \inf_{+}, \inf_{-}  }
                if self.f.degree() % 2 == 0:
                    # we need to figure out the sign at infinity
                    Maug = Matrix(basis.nrows() - self.g - 1, self.g + 1).stack(identity_matrix(self.g + 1))
                    B = basis.augment( Maug )
                    KB, upper, lower  = Kernel(B, basis.ncols() + self.g )

                    a, b, c = KB.column(0)[-(2 + 1):].list()
                    assert self.threshold_check(upper, lower), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))

                    tmp = (-b/c) / sqrt(self.f.list()[-1]);
                    assert self.threshold_check( tmp.real(), tmp.imag()), "upper = %s lower = %s" % (RealField(35)(upper), RealField(35)(lower))
                    infsign = round(tmp.real());
                    assert infsign in [1, -1]


                    return [infsign*Infinity, infsign*Infinity], maxlower


                return [+Infinity, +Infinity], maxlower
            else:
                maxlower = max(maxlower, lower);
                #1 \notin <basis>
                assert self.threshold_check(norm_one),  "upper = %s lower = %s norm_one = %s " % (RealField(35)(upper), RealField(35)(lower), RealField(35)(norm_one));
                        
                        
            Rw = PolynomialRing(self.Rdoubleextraprec, "T")
            xcoordinates = Rw(KB.column(0)[-(self.g):].list()).complex_roots()
            assert len(xcoordinates) == 1;
            x0 = xcoordinates[0];
            y0 = self.Rextraprec(sqrt(self.f(x0)));

                        
            
            # if dim <1, x, x**2> cap <basis> >= 2
            # then dim <1, x> cap <basis> >= 1

            
            
            
            # we must have <1, x> \subset <basis>

            # double check that (x - x0) and (x - x0)**2 are in <basis>
            
            # (x - x0)
            v1 = vector(self.R, [0]*basis.nrows())
            v1[0] = -x0
            v1[1] = 1
            lower = norm(Ebasis * v1)
            assert self.threshold_check(1, lower), "lower = %s" % (RealField(35)(lower),);
            maxlower = max(maxlower, lower);

            # (x - x0)**2
            v2 = vector(self.R, [0]*basis.nrows())
            v2[0] = x0**2
            v2[1] = - 2*x0
            v2[2] = 1
            lower = norm(Ebasis * v2)
            assert self.threshold_check(1, lower), "lower = %s" % (RealField(35)(lower),);

            maxlower = max(maxlower, lower);

            
            # (x - x0)**3
            v3 = vector(self.R, [0]*basis.nrows())
            v3[0] = -x0**3
            v3[1] = 3*x0**2
            v3[2] = -3*x0
            v3[3] = 1
            nc = norm(Ebasis * v3)
            
            
            vp = vector(self.R, [x0**i * y0**j for i,j in self.Vexps[:basis.nrows()]]);
            vn = vector(self.R, [x0**i * (-y0)**j for i,j in self.Vexps[:basis.nrows()]]);

            np = norm( vp * basis);
            nn = norm( vn * basis);
            

            # either E = P + \inf_{+/-} 
            # or E = P + tau(P)   with P != \inf_{*}, but in this case E ~ \inf_+ + \inf_-        

            if self.threshold_check(np, nn) and not self.threshold_check(nn, np): #np > nn ~ 0
                result[0] = (x0, -y0);
                maxlower = max(maxlower, nn);

            elif not self.threshold_check(np, nn) and self.threshold_check(nn, np): #nn > np ~ 0
                result[0]  = (x0, y0);
                maxlower = max(maxlower, np);

            else:
                if self.threshold_check(1,nc) and self.threshold_check(1,np) and self.threshold_check(1,nn):
                    result[0] = (x0, y0)
                    result[1] = (x0, -y0)
                    maxlower = max(maxlower, nc, np, nn);
                    # this is equivalent to:  return result, maxlower
                    return [+Infinity, -Infinity], maxlower
                if self.f(x0) > self.almostzero :
                    print "sign for y is not clear: neg = %s, pos = %s,\nassuming y = %s + %s * I = 0" % tuple( vector( RealField(15), (nn, np, y0.real(), y0.imag())));
                result[0] = (x0, 0);
            
            # E = P + \inf_{+/-} 
            # P = result[0]
            x0, y0 = result[0]



            # Now figure out what infinity is in the supp of E
            # by checking if   y - s*x**(g+1) - (y0 - s*x0**(g+1)) \in <basis>
            # for s = sign * sqrt(an)
            sqrtan =  self.Rextraprec( sqrt( self.an) );
            # vp -> no pole at inf_{+} -> inf_{+} \in supp E
            vp = vector(self.R, [0]*basis.nrows())
            # vn -> no pole at inf_{-} -> inf_{-} \in supp E
            vn = vector(self.R, [0]*basis.nrows())
            vp[0] = -(y0 - sqrtan*x0**(self.g + 1))
            vn[0] = -(y0 + sqrtan*x0**(self.g + 1))
            vp[self.g + 1] = -sqrtan
            vn[self.g + 1] = sqrtan
            vp[self.g + 2] = 1
            vn[self.g + 2] = 1
            
            np = norm( Ebasis * vp );
            nn = norm( Ebasis * vn );

            


            if self.threshold_check(np * nc, nn) and not self.threshold_check(nn * nc, np) and not self.threshold_check(nn * np, nc): #np * nc > nn ~ 0
                maxlower = max(maxlower, nn);
                result[1] = -Infinity ;
            elif not self.threshold_check(np * nc, nn) and self.threshold_check(nn * nc, np) and not self.threshold_check(nn * np, nc): #nn * nc > np ~ 0
                maxlower = max(maxlower, np);
                result[1] = +Infinity
            elif not self.threshold_check(np * nc, nn) and not self.threshold_check(nn * nc, np) and self.threshold_check(nn * np, nc): # np*nn > nc
                # this should have been rulled out before, but now it looks more likely to have P + tau(P)
                # instead of E = P + inf
                maxlower = max(maxlower, nc);
                #this is equivalent to: result[1] = (x0, -y0)
                result = [+Infinity, -Infinity]
            else:
                print "inf_{?} \in supp E not clear: neg = %s, pos = %s, conj = %s" % tuple(vector(RealField(15),(nn, np, nc)));
                mn = min(nn, np, nc)
                maxlower = max(maxlower, mn);
                if np == mn:
                    result[1] = +Infinity;
                elif nn == mn:
                    result[1] = -Infinity;
                elif nc == mn:
                    #this is equivalent to: result[1] = (x0, -y0)
                    result = [+Infinity, -Infinity]
                else:
                    assert False, "something went wrong"
            return result, maxlower
Exemplo n.º 5
0
        y0 = sqrt(g(x0))
    print "\tQi = (%s, -/+%s)" % (x0, y0)
    Q0, Q1 = vector(CCap, (x0, y0)), vector(CCap, (x0, -y0))

    points = [P0, P1, Q0, Q1]
    pairs = [[P0, Q0], [P0, Q1], [P1, Q0], [P1, Q1]]

    print "\tTesting P -> Divisor(P, {0,1} ) -> Divisor(P, {0,1}).compute_coordinates() = P - \inf_{(-1)^{0,1}}?"
    for i, P in enumerate(points):
        for sign in range(2):
            #point - \infty_{ (-1)^sign} ~
            # point + \inty_{ (-1)^{sign + 1} } - D0
            DP = Divisor(Pic, [P], sign)
            R0, R1 = DP.compute_coordinates()
            R0 = vector(R0)
            N = norm(P - R0)
            N = RealField(15)(N)
            print "\t\tP + \pm Infinity = R0 + \pm Infinity? : %s" % N
            if R1 != (-1)**(sign + 1) * Infinity or N > threshold:
                print "\t\t!! WARNING !!"
                print "\t\t\tsomething went wrong?"
                print "\t\t\tsign = %s R1 = %s" % (sign, R1)
                print "\t\t\tP = %s" % vector(CC, P)
                print "\t\t\tR0 = %s" % vector(CC, R0)

    print "\tTesting P, Q -> Divisor(P,Q) -> Divisor(P,Q).compute_coordinates() = P + Q - D0?"
    for i, pair in enumerate(pairs):
        p0, p1 = pair
        Dp0p1 = Divisor(Pic, [p0, p1])
        R0, R1 = Dp0p1.coordinates()
        R0 = vector(R0)
Exemplo n.º 6
0
def gram_matrix(N,
                weight,
                prec=501,
                tol=1E-40,
                sv_min=1E-1,
                sv_max=1E15,
                bl=None,
                set_dim=None,
                force_prec=False):
    r""" Computes a matrix of p_{r,D}(r',D')
    for a basis of P_{r,D}, i.e. dim linearly independent P's
    INPUT: N      = Integer
           weight = Real
    OPTIONAL: 
           tol    = error bound for the Poincaré series
           sv_min = minimal allowed singular value when determining whether a given set is linarly independent or not.
           sv_max = maximally allowed singular value
           bl     = list of pairs (D_i,r_i) from which  we compute a matrix of coeffficients p_{D_i,r_i}(D_j,r_j)
        """
    # If we have supplied a list of D's and r's we make a gram matrix relative to these
    # otherwise we find a basis, i.e. linearly independent forms with correct dimension
    # find the dimension
    wt = '%.4f' % weight
    if (N < 10):
        stN = "0" + str(N)
    else:
        stN = str(N)
    v = dict()
    filename_work = "__N" + stN + "-" + wt + "--finding basis.txt"
    fp = open(filename_work, "write")
    fp.write("starting to find basis")
    fp.close()
    if (silent > 0):
        print("Forcing precision:{0}".format(force_prec))
    set_verbose(0)
    if (bl != None):
        dim = len(bl)
        l = bl
    else:
        if (set_dim != None and set_dim > 0):
            dim = set_dim
        else:
            dim = dimension_jac_cusp_forms(int(weight + 0.5), N, -1)
        l = list_of_basis(N, weight, prec, tol, sv_min, sv_max, set_dim=dim)
    j = 0
    for [D, r] in l.values():
        for [Dp, rp] in l.values():
            # Recall that the gram matrix is symmetric. We need only compute the upper diagonal
            if (list(v.values()).count([Dp, rp, D, r]) == 0):
                v[j] = [D, r, Dp, rp]
                j = j + 1
    # now v is a list we can get into computing coefficients
    # first we print the "gram data" (list of indices) to the file
    s = str(N) + ": (AI[" + str(N) + "],["
    indices = dict()
    for j in range(len(l)):
        Delta = l[j][0]
        r = l[j][1]
        diff = (r * r - Delta) % (4 * N)
        if diff != 0:
            raise ValueError(
                "ERROR r^2={0} not congruent to Delta={1} mod {2}!".format(
                    r * r, Delta, 4 * N))
        s = s + "(" + str(Delta) + "," + str(r) + ")"
        indices[j] = [Delta, r]
        if j < len(l) - 1:
            s = s + ","
        else:
            s = s + "]),"
    s = s + "\n"
    if silent > 0:
        print(s + "\n")
    filename2 = "PS_Gramdata" + stN + "-" + wt + ".txt"
    fp = open(filename2, "write")
    fp.write(s)
    fp.close()
    try:
        os.remove(filename_work)
    except os.error:
        print("Could not remove file:{0}".format(filename_work))
        pass
    filename_work = "__N" + stN + "-" + wt + "--computing_gram_matrix.txt"
    fp = open(filename_work, "write")
    fp.write("")
    fp.close()
    #print "tol=",tol
    #set_verbose(2)
    #print "force_prec(gram_mat)=",force_prec
    res = ps_coefficients_holomorphic_vec(N,
                                          weight,
                                          v,
                                          tol,
                                          prec,
                                          force_prec=force_prec)
    set_verbose(0)

    res['indices'] = indices
    maxerr = 0.0
    for j in res['errs'].keys():
        tmperr = abs(res['errs'][j])
        #print "err(",j,")=",tmperr
        if (tmperr > maxerr):
            maxerr = tmperr
        # switch format for easier vewing
        res['errs'][j] = RR(tmperr)
    if silent > 0:
        print("maxerr={0}".format(RR(maxerr)))
    res['maxerr'] = maxerr
    wt_phalf = '%.4f' % (weight + 0.5)
    filename3 = "PS_Gramerr" + stN + "-" + wt + ".txt"
    fp = open(filename3, "write")
    wt
    s = "MAXERR[" + wt_phalf + "][" + stN + "]=" + str(RR(maxerr))
    fp.write(s)
    fp.close()
    if (res['ok']):
        Cps = res['data']
    else:
        print("Failed to compute Fourier coefficients!")
        return 0
    RF = RealField(prec)
    A = matrix(RF, dim)
    kappa = weight
    fourpi = RF(4.0) * pi.n(prec)
    one = RF(1.0)
    N4 = RF(4 * N)
    C = dict()
    if (silent > 1):
        print("v={0}".format(v))
        print("dim={0}".format(dim))
    lastix = 0
    # First set the upper right part of A
    for j in range(dim):
        ddim = dim - j
        if (silent > 1):
            print("j={0} ddim={1} lastix={2]".format(j, ddim, lastix))
        for k in range(0, ddim):
            # need to scale with |D|^(k+0.5)
            if (silent > 1):
                print("k={0}".format(k))
                print("lastix+k={0}".format(lastix + k))
            mm = RF(abs(v[lastix + k][0])) / N4
            tmp = RF(mm**(weight - one))
            if (silent > 1):
                print("ddim+k={0}".format(ddim + k))
            A[j, j + k] = Cps[lastix + k] * tmp
            C[v[lastix + k][0], v[lastix + k][1]] = Cps[lastix + k]
        lastix = lastix + k + 1
    # And add the lower triangular part to mak the matrix symmetric
    for j in range(dim):
        for k in range(0, j):
            A[j, k] = A[k, j]
    # And print the gram matrix
    res['matrix'] = A
    dold = mpmath.mp.dps
    mpmath.mp.dps = int(prec / 3.3)
    AInt = mpmath.matrix(int(A.nrows()), int(A.ncols()))
    AMp = mpmath.matrix(int(A.nrows()), int(A.ncols()))
    for ir in range(A.nrows()):
        for ik in range(A.ncols()):
            AInt[ir, ik] = mpmath.mpi(A[ir, ik] - tol, A[ir, ik] + tol)
            AMp[ir, ik] = mpmath.mpf(A[ir, ik])
    d = mpmath.det(AMp)
    if (silent > 1):
        print("det(A-as-mpmath)={0}".format(d))
    di = mpmath.det(AInt)
    if (silent > 1):
        print("det(A-as-interval)={0}".format(di))
    res['det'] = (RF(di.a), RF(di.b))

    filename = "PS_Gram" + stN + "-" + wt + ".txt"
    if (silent > 1):
        print("printing to file: {0}".format(filename))
    print_matrix_to_file(A, filename, 'A[' + str(N) + ']')
    if (silent > 1):
        print("A-A.transpose()={0}".format(norm(A - A.transpose())))
    B = A ^ -1
    #[d,B]=mat_inverse(A)
    if (silent > 1):
        print("A={0}".format(A.n(100)))
        print("det(A)={0}".format(di))
        print("Done making inverse!")
    #res['det']=d
    res['inv'] = B
    mpmath.mp.dps = dold
    filename = "PS_Gram-inv" + stN + "-" + wt + ".txt"
    print_matrix_to_file(B, filename, ' AI[' + str(N) + ']')
    # first make the filename
    s = '%.1e' % tol
    filename3 = "PS_Coeffs" + stN + "-" + wt + "-" + s + ".sobj"
    # If the file already exist we load it and append the new data
    if (silent > 0):
        print("saving data to: {0}".format(filename3))
    try:
        f = open(filename3, "read")
    except IOError:
        if (silent > 0):
            print("no file before!")
        # do nothing
    else:
        if silent > 0:
            print("file: {0} exists!".format(filename3))
        f.close()
        Cold = load(filename3)
        for key in Cold.keys():
            #                print"key:",key
            if key not in C:  # then we add it
                print("key:", key, " does not exist in the new version!")
                C[key] = Cold[key]
                save(C, filename3)
    ## Save the whole thing
    filename = "PS_all_gram" + stN + "-" + wt + ".sobj"
    save(res, filename)
    ## our work is completed and we can remove the file
    try:
        os.remove(filename_work)
    except os.error:
        print("Could not remove file: {0}".format(filename_work))
        pass
    return res