def upsert_embedding(id_number, skip=True):
    rowcc = db.mf_hecke_cc.lucky({'id': id_number},
                                 projection=[
                                     'an_normalized', 'hecke_orbit_code', 'id',
                                     'lfunction_label', 'embedding_root_imag',
                                     'embedding_root_real'
                                 ])
    if rowcc is None:
        return
    if skip:
        if rowcc.get("embedding_root_imag", None) is not None:
            if rowcc.get("embedding_root_real", None) is not None:
                return
    row_embeddings = {}
    hecke_orbit_code = rowcc['hecke_orbit_code']
    newform = db.mf_newforms.lucky({'hecke_orbit_code': hecke_orbit_code},
                                   ['label', 'weight', 'field_poly', 'dim'])
    if newform is None:
        # No newform in db
        return
    if newform['dim'] == 1:
        row_embeddings['embedding_root_imag'] = 0
        row_embeddings['embedding_root_real'] = 0
    elif newform['weight'] == 1:
        return
    elif newform.get('field_poly', None) is None:
        return
    else:
        # print rowcc['lfunction_label']
        HF = NumberField(ZZx(newform['field_poly']), "v")
        hecke_nf = db.mf_hecke_nf.lucky(
            {'hecke_orbit_code': hecke_orbit_code}, [
                'hecke_ring_cyclotomic_generator', 'an', 'field_poly',
                'field_poly_root_of_unity', 'hecke_ring_numerators',
                'hecke_ring_denominators', 'hecke_ring_power_basis'
            ])
        assert hecke_nf is not None
        assert newform['field_poly'] == hecke_nf['field_poly']
        assert hecke_nf['hecke_ring_cyclotomic_generator'] == 0
        if hecke_nf['hecke_ring_power_basis'] or (
                hecke_nf['field_poly_root_of_unity'] != 0):
            v = HF.gens()[0]
            betas = [v**i for i in range(len(newform['field_poly']))]
        else:
            numerators = hecke_nf.get('hecke_ring_numerators')
            denominators = hecke_nf.get('hecke_ring_denominators')
            betas = [
                HF(elt) / denominators[i] for i, elt in enumerate(numerators)
            ]

        embeddings = HF.complex_embeddings(prec=2000)
        an_nf = hecke_nf['an']
        betas_embedded = [map(elt, betas) for elt in embeddings]
        CCC = betas_embedded[0][0].parent()
        normalization = -CCC(newform['weight'] - 1).real() / 2
        qexp = [
            convert_eigenvals_to_qexp(elt, an_nf, normalization)
            for elt in betas_embedded
        ]
        min_len = min(len(rowcc['an_normalized']), len(qexp[0]))
        an_cc = vector(
            CCC,
            map(lambda x: CCC(x[0], x[1]), rowcc['an_normalized'][:min_len]))
        #qexp_diff = [ (vector(CCC, elt[:min_len]) - an_cc).norm() for elt in qexp ]
        # normalized, to avoid the unstability coming from large weight
        qexp_diff = [
            vector([(elt - an_cc[i]) / elt.abs() for i, elt in enumerate(q)
                    if elt != 0]).norm() for j, q in enumerate(qexp)
        ]

        qexp_diff_sorted = sorted(qexp_diff)
        min_diff = qexp_diff_sorted[0]

        #assuring that is something close to zero, and that no other value is close to it
        assert min_diff < 1e-6 and min_diff / qexp_diff_sorted[
            1] < 1e-15, "id = %d label = %s\nmin_diff = %.2e \t min_diff/2nd = %.2e\nan_cc = %s\nqexp = %s" % (
                id_number, rowcc['lfunction_label'], min_diff, min_diff /
                qexp_diff_sorted[1], vector(ComplexField(20), an_cc[:5]),
                matrix(ComplexField(20), [elt[:5] for elt in qexp]))

        for i, elt in enumerate(qexp_diff):
            if elt == min_diff:
                row_embeddings['embedding_root_real'] = float(embeddings[i](
                    HF.gen()).real())
                row_embeddings['embedding_root_imag'] = float(embeddings[i](
                    HF.gen()).imag())
                break
    assert len(row_embeddings) == 2
    db.mf_hecke_cc.upsert({'id': rowcc['id']}, row_embeddings)
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()
    ]
def upsert_embedding(id_number, skip=False):
    rowcc = db.mf_hecke_cc.lucky({'id': id_number},
                                 projection=[
                                     'an', 'hecke_orbit_code', 'id',
                                     'lfunction_label', 'embedding_root_imag',
                                     'embedding_root_real'
                                 ])
    if rowcc is None:
        return
    if skip:
        if rowcc.get("embedding_root_imag", None) is not None:
            if rowcc.get("embedding_root_real", None) is not None:
                return
    row_embeddings = {}
    hecke_orbit_code = rowcc['hecke_orbit_code']
    newform = db.mf_newforms.lucky({'hecke_orbit_code': hecke_orbit_code})
    if newform is None:
        # No newform in db
        return
    if newform['dim'] == 1:
        row_embeddings['embedding_root_imag'] = 0
        row_embeddings['embedding_root_real'] = 0
    elif newform['weight'] == 1:
        return
    elif newform.get('field_poly', None) is None:
        return
    else:
        # print rowcc['lfunction_label']
        HF = NumberField(ZZx(newform['field_poly']), "v")
        numerators = newform['hecke_ring_numerators']
        denominators = newform['hecke_ring_denominators']
        betas = [HF(elt) / denominators[i] for i, elt in enumerate(numerators)]

        embeddings = HF.complex_embeddings(prec=2000)
        an_nf = list(
            db.mf_hecke_nf.search({'hecke_orbit_code': hecke_orbit_code},
                                  ['n', 'an'],
                                  sort=['n']))
        betas_embedded = [map(elt, betas) for elt in embeddings]
        CCC = betas_embedded[0][0].parent()
        qexp = [
            convert_eigenvals_to_qexp(elt, an_nf) for elt in betas_embedded
        ]
        min_len = min(len(rowcc['an']), len(qexp[0]))
        an_cc = vector(CCC,
                       map(lambda x: CCC(x[0], x[1]), rowcc['an'][:min_len]))
        #qexp_diff = [ (vector(CCC, elt[:min_len]) - an_cc).norm() for elt in qexp ]
        # normalized, to avoid the unstability comming from large weight
        qexp_diff = [
            vector([(elt - an_cc[i]) / elt.abs() for i, elt in enumerate(q)
                    if elt != 0]).norm() for j, q in enumerate(qexp)
        ]

        qexp_diff_sorted = sorted(qexp_diff)
        min_diff = qexp_diff_sorted[0]
        #print "min_diff = %.2e \t min_diff/2nd = %.2e" % (min_diff, min_diff/qexp_diff_sorted[1])

        #assuring that is something close to zero, and that no other value is close to it
        assert min_diff < 1e-6
        assert min_diff / qexp_diff_sorted[1] < 1e-15

        for i, elt in enumerate(qexp_diff):
            if elt == min_diff:
                row_embeddings['embedding_root_real'] = float(embeddings[i](
                    HF.gen()).real())
                row_embeddings['embedding_root_imag'] = float(embeddings[i](
                    HF.gen()).imag())
                break
    assert len(row_embeddings) == 2
    db.mf_hecke_cc.upsert({'id': rowcc['id']}, row_embeddings)
    def __classcall__(cls, embed, category=None):
        r"""
        Normalize parameters so embedded real number fields are unique::

            sage: from pyeantic import eantic, RealEmbeddedNumberField
            sage: K = NumberField(x**2 - 2, 'a', embedding=sqrt(AA(2)))
            sage: K = RealEmbeddedNumberField(K)
            sage: L = NumberField(x**2 - 2, 'a')
            sage: L = RealEmbeddedNumberField(L.embeddings(AA)[1])
            sage: M = eantic.renf_class.make("a^2 - 2", "a", "1.4 +/- .1")
            sage: M = RealEmbeddedNumberField(M)
            sage: K is L
            True
            sage: K is M
            True

        """
        if isinstance(embed, eantic.renf_class):
            # Since it is quite annoying to convert an fmpz polynomial, we parse
            # the printed representation of the renf_class. This is of course
            # not very robust…
            import re
            match = re.match("^NumberField\\(([^,]+), (\\[[^\\]]+\\])\\)$",
                             repr(embed))
            assert match, "renf_class printed in an unexpected way"
            minpoly = match.group(1)
            root_str = match.group(2)
            match = re.match("^\\d*\\*?([^\\^ *]+)[\\^ ]", minpoly)
            assert match, "renf_class printed leading coefficient in an unexpected way"
            minpoly = QQ[match.group(1)](minpoly)
            roots = []
            AA_roots = minpoly.roots(AA, multiplicities=False)
            for prec in [53, 64, 128, 256]:
                R = RealBallField(prec)
                root = R(root_str)
                roots = [aa for aa in AA_roots if R(aa).overlaps(root)]
                if len(roots) == 1:
                    break
            if len(roots) != 1:
                raise RuntimeError(
                    "cannot distinguish roots with limited ball field precision"
                )
            embed = NumberField(minpoly,
                                minpoly.variable_name(),
                                embedding=roots[0])
        if embed in NumberFields():
            if not RR.has_coerce_map_from(embed):
                raise ValueError(
                    "number field must be endowed with an embedding into the reals"
                )
            if not embed.is_absolute():
                raise NotImplementedError("number field must be absolute")
            # We recreate our NumberField from the embedding since number
            # fields with the same embedding might differ by other parameters
            # and therefore do not serve immediately as unique keys.
            embed = AA.coerce_map_from(embed)
        if isinstance(embed, Map):
            K = embed.domain()
            if K not in NumberFields():
                raise ValueError("domain must be a number field")
            if not AA.has_coerce_map_from(embed.codomain()):
                raise ValueError("codomain must coerce into RR")
            if not K.is_absolute():
                raise NotImplementedError("number field must be absolute")
            # We explicitly construct an embedding from the given embedding to
            # make sure that we get a useable key.
            minpoly = (QQ['x'].gen() - 1) if K is QQ else K.polynomial()
            minpoly = minpoly.change_variable_name('x')
            embedding = AA.one() if K is QQ else embed(K.gen())
            embed = NumberField(minpoly,
                                K.variable_name(),
                                embedding=embedding)
        else:
            raise TypeError(
                "cannot build RealEmbeddedNumberField from embedding %s" %
                (type(embed)))

        category = category or Fields()
        return super(RealEmbeddedNumberField,
                     cls).__classcall__(cls, embed, category)
Esempio n. 5
0
ar = ArtinRepresentation(label)

outfile = open(label, 'w')

cf = a['CharacterField']
cfz = ZZ(cf)
nf = ar.nf()
nfcc = nf.conjugacy_classes()
nfcc = [int(z.order()) for z in nfcc]
nfcc = lcm(nfcc)
if not cfz.divides(nfcc):
    print("Failure " + str(cfz) + " divides " + str(nfcc) + " from " + label)
    sys.exit()
R, x = QQ['x'].objgen()
pol1 = R.cyclotomic_polynomial(nfcc)
K, z = NumberField(R.cyclotomic_polynomial(nfcc), 'z').objgen()
RR, y = K['y'].objgen()
zsmall = z**(nfcc / cfz)
allpols = [
    sum(y**k * sum(pp[k][j] * zsmall**j for j in range(len(pp[k])))
        for k in range(len(pp))) for pp in ar.local_factors_table()
]
allroots = [myroots(pp, nfcc, z) for pp in allpols]

outfile.write(str(nfcc) + "\n")
outfile.write(str(allroots) + "\n")
j = 0
p = 1
while j < bound:
    p = next_prime(p)
    outfile.write(str(ar.any_prime_to_cc_index(p)) + "\n")
Esempio n. 6
0
    def extension(self, f, embedding=False):
        r"""
        Return a `p`-adic extension such that ``f`` has a root in an unramified
        extension of it.

        INPUT:

        - ``f`` -- a monic univariate polynomial over the number field `K_0`
          underlying this p-adic extension `K`, which is irreducible over `K`.
        - ``embedding`` -- a boolean (default: ``False``)

        OUTPUT:

        A `p`-adic extension `L` of `K` such that ``f`` has a root
        in an unramified extension of `L`, or (if ``embedding`` is ``True``)
        the pair `(L,\phi)`, where `\phi` is the canonical embedding of
        `K` into `L`.

        If `K_0` is the underlying number field, then `f\in K_0[x]` is irreducible
        over the completion `K`; the resulting finite extension `L/K`
        is a subextension of the extension of `K`

        .. MATH::

                K[x]/(f).

        However, the number field `L_0` underlying `L` is in general not
        equal to `K_0[x]/(f)`, and there may not exist any embedding of `K_0`
        into `L_0`.

        """
        # print("entering extension with ")
        # print("K = ", self)
        # print("f = ", f)
        # print()

        K0 = self.number_field()
        assert K0.has_coerce_map_from(f.parent().base_ring())
        f = f.change_ring(K0)

        vK = self.valuation()
        if embedding:
            raise NotImplementedError

        V = vK.mac_lane_approximants(f)
        assert len(V) == 1, "f is not irreducible"
        v = LimitValuation(V[0], f)
        pix = v.uniformizer()
        r = v(pix)
        for m in range(2,10):
            pix1 = pix.map_coefficients(lambda c:self.reduce(c, m))
            if v(pix1) == r:
                break
        assert m < 9, "m too small"
        # now pix1 is a polynomial over `K_0` which maps to a uniformizer for the
        # unique extension of vK to the relative extension L=K[x]/(f)/K
        g = self.characteristic_polynomial(f, pix1)
        # now g is the relative characteristic polynomial of the image pi of pix1 in L
        # we need the minimal polynomial, so we do a square free factorization
        g = g.squarefree_decomposition()[0][0]
        # now we compute the absolute characteristic polynomial of a root
        # of g

        done = False
        N = m+5
        while not done:
            Pmod = self.characteristic_polynomial_mod(g, N)
            # this is very heuristic; there should be a conclusive test whether
            # the result is correct, or the choice of the precision should be made correctly and
            # optimal from the start
            P = Pmod.map_coefficients(lambda c:c.lift(), QQ)
            P = P.squarefree_decomposition()[0][0]
            L0 = NumberField(P, 'pi%s'%P.degree())
            V = QQ.valuation(self.p()).extensions(L0)
            vL = V[0]
            e = ZZ(1/vL(vL.uniformizer()))
            f = vL.residue_field().degree()
            if 1/e == r:
                if len(V) == 1:
                    return FakepAdicCompletion(L0, vL)
                else:
                    QQp = FakepAdicCompletion(QQ, self.base_valuation())
                    g = QQp.approximate_irreducible_factor(P)
                    return QQp.extension(g)
            N = N + 5
Esempio n. 7
0
    def make_form(self):
        # To start with the data fields of self are just those from
        # the database.  We need to reformat these and compute some
        # further (easy) data about it.
        #
        from lmfdb.ecnf.WebEllipticCurve import FIELD
        self.field = FIELD(self.field_label)
        pretty_field = field_pretty(self.field_label)
        self.field_knowl = nf_display_knowl(self.field_label, pretty_field)
        try:
            dims = db.bmf_dims.lucky(
                {
                    'field_label': self.field_label,
                    'level_label': self.level_label
                },
                projection='gl2_dims')
            self.newspace_dimension = dims[str(self.weight)]['new_dim']
        except TypeError:
            self.newspace_dimension = 'not available'
        self.newspace_label = "-".join([self.field_label, self.level_label])
        self.newspace_url = url_for(".render_bmf_space_webpage",
                                    field_label=self.field_label,
                                    level_label=self.level_label)
        K = self.field.K()

        if self.dimension > 1:
            Qx = PolynomialRing(QQ, 'x')
            self.hecke_poly = Qx(str(self.hecke_poly))
            F = NumberField(self.hecke_poly, 'z')
            self.hecke_poly = web_latex(self.hecke_poly)

            def conv(ap):
                if '?' in ap:
                    return 'not known'
                else:
                    return F(str(ap))

            self.hecke_eigs = [conv(str(ap)) for ap in self.hecke_eigs]

        self.nap = len(self.hecke_eigs)
        self.nap0 = min(50, self.nap)
        self.hecke_table = [[
            web_latex(p.norm()),
            ideal_label(p),
            web_latex(p.gens_reduced()[0]),
            web_latex(ap)
        ] for p, ap in zip(primes_iter(K), self.hecke_eigs[:self.nap0])]
        level = ideal_from_label(K, self.level_label)
        self.level_ideal2 = web_latex(level)
        badp = level.prime_factors()
        self.have_AL = self.AL_eigs[0] != '?'
        if self.have_AL:
            self.AL_table = [[
                web_latex(p.norm()),
                ideal_label(p),
                web_latex(p.gens_reduced()[0]),
                web_latex(ap)
            ] for p, ap in zip(badp, self.AL_eigs)]
        self.sign = 'not determined'
        if self.sfe == 1:
            self.sign = "+1"
        elif self.sfe == -1:
            self.sign = "-1"

        if self.Lratio == '?':
            self.Lratio = "not determined"
            self.anrank = "not determined"
        else:
            self.Lratio = QQ(self.Lratio)
            self.anrank = "\(0\)" if self.Lratio != 0 else "odd" if self.sfe == -1 else "\(\ge2\), even"

        self.properties2 = [('Base field', pretty_field),
                            ('Weight', str(self.weight)),
                            ('Level norm', str(self.level_norm)),
                            ('Level', self.level_ideal2),
                            ('Label', self.label),
                            ('Dimension', str(self.dimension))]

        if self.CM == '?':
            self.CM = 'not determined'
        elif self.CM == 0:
            self.CM = 'no'
        self.properties2.append(('CM', str(self.CM)))

        self.bc_extra = ''
        self.bcd = 0
        self.bct = self.bc != '?' and self.bc != 0
        if self.bc == '?':
            self.bc = 'not determined'
        elif self.bc == 0:
            self.bc = 'no'
        elif self.bc == 1:
            self.bcd = self.bc
            self.bc = 'yes'
        elif self.bc > 1:
            self.bcd = self.bc
            self.bc = 'yes'
            self.bc_extra = ', of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{' + str(
                self.bcd) + '})\)'
        elif self.bc == -1:
            self.bc = 'no'
            self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\)'
        elif self.bc < -1:
            self.bcd = -self.bc
            self.bc = 'no'
            self.bc_extra = ', but is a twist of the base-change of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{' + str(
                self.bcd) + '})\)'
        self.properties2.append(('Base-change', str(self.bc)))

        curve_bc = db.ec_nfcurves.lucky({'class_label': self.label},
                                        projection="base_change")
        if curve_bc is not None:
            self.ec_status = 'exists'
            self.ec_url = url_for("ecnf.show_ecnf_isoclass",
                                  nf=self.field_label,
                                  conductor_label=self.level_label,
                                  class_label=self.label_suffix)
            curve_bc_parts = [split_lmfdb_label(lab) for lab in curve_bc]
            bc_urls = [
                url_for("emf.render_elliptic_modular_forms",
                        level=cond,
                        weight=2,
                        character=1,
                        label=iso) for cond, iso, num in curve_bc_parts
            ]
            bc_labels = [
                newform_label(cond, 2, 1, iso)
                for cond, iso, num in curve_bc_parts
            ]
            bc_exists = [is_newform_in_db(lab) for lab in bc_labels]
            self.bc_forms = [{
                'exists': ex,
                'label': lab,
                'url': url
            } for ex, lab, url in zip(bc_exists, bc_labels, bc_urls)]
        else:
            self.bc_forms = []
            if self.bct:
                self.ec_status = 'none'
            else:
                self.ec_status = 'missing'

        self.properties2.append(('Sign', self.sign))
        self.properties2.append(('Analytic rank', self.anrank))

        self.friends = []
        if self.dimension == 1:
            if self.ec_status == 'exists':
                self.friends += [
                    ('Elliptic curve isogeny class {}'.format(self.label),
                     self.ec_url)
                ]
            elif self.ec_status == 'missing':
                self.friends += [
                    ('Elliptic curve {} missing'.format(self.label), "")
                ]
            else:
                self.friends += [('No elliptic curve', "")]

        self.friends += [('Newspace {}'.format(self.newspace_label),
                          self.newspace_url)]
        self.friends += [('L-function not available', '')]
Esempio n. 8
0
def field_intersection_matrix(matrix_defining_polynomials):
    r"""
    INPUT:

        - a matrix of polynomials defining numberfields (f_ij)

    OUTPUT:

        - returns a pair per column entry (Ak, Bk)
            after picking a row with a small intersection, WLOG i = 0
            Let S_ij denote all the polynomials defining subfields of QQ[x]/fij

            Then Bk = S_0k \cap (\cap_{i > 0) \cup_j S_ij)
            If the list Bk can be obtained as list of subfields of one subfield
            then such subfield, otherwise Ak is None


    """
    if len(matrix_defining_polynomials[0]) == 1:
        f = field_intersection_list(
            [elt[0] for elt in matrix_defining_polynomials])
        return [[f, subfields_polynomials(f)]]

    # we would like to pick the row which has the smallest intersection
    # an easy to get something close to that,is by picking the one with
    # lowest GCD of the discriminants
    Di = None
    Dmin = None
    for i, row in enumerate(matrix_defining_polynomials):
        D = GCD([elt.discriminant() for elt in row])
        if Dmin is None or D < Dmin:
            Dmin = D
            Di = i
        if Dmin == 1:
            break

    working_row = matrix_defining_polynomials[Di]

    subfields_matrix = [None] * len(matrix_defining_polynomials)
    output = [None] * len(working_row)
    for k, f in enumerate(working_row):
        Lsubfields = Set(subfields_polynomials(f))
        for i, row in enumerate(matrix_defining_polynomials):
            if i != Di:
                if subfields_matrix[i] is None:
                    U = Set([])
                    for g in row:
                        Sg = Set(subfields_polynomials(g))
                        U = U.union(Sg)
                    subfields_matrix[i] = U
                # try to discard some subfields
                Lsubfields = Lsubfields.intersection(subfields_matrix[i])
                if Lsubfields.cardinality() == 1:
                    # QQ is the only possible subfield
                    break

        Lsubfields = list(Lsubfields)
        Lsubfields.sort()
        output[k] = [None, Lsubfields]
        # try to produce a single polynomial, if Lsubfields are all the subfields of a common subfield
        if len(Lsubfields) == 1:
            output[k][0] = f.parent().gen()
        else:
            if Lsubfields[-1].degree() != Lsubfields[-2].degree():
                # there is one field of maximal degree, that might contain all the others
                K = NumberField(Lsubfields[-1], 'a')
                maxsubfields = [
                    polredabs(sK.absolute_polynomial())
                    for sK, _, _ in K.subfields()
                ]
                if maxsubfields == Lsubfields:
                    output[k][0] = Lsubfields[-1]

    return output
Esempio n. 9
0
def DiscriminantBound(LPolys, alreadyTwisted=False):
    # returns a pair (type, bound), where type is one of "Z", "RM",
    # "QuadraticCM", "FullCM" and bound is a bound on the discriminant of the
    # field of endomorphisms
    discBound = 0

    CMField = QQ
    RMField = QQ
    FullCM = True
    RM = True

    for p in range(2, maxP):
        if LPolys[p] <> 0:
            q = LPolys[p]
            g = q.degree() / 2
            extDegree = extensionBounds[g]
            if alreadyTwisted:
                extDegree = 1
            break

    for p in range(2, maxP):
        if is_prime(p) and LPolys[p] <> 0:
            q = LPolys[p]
            # print q
            # print "Testing p =", p

            # print "Twisting the L-poly"
            q = twistPolynomial(q, extDegree)
            # print "Prime", p, "Polynomial", q;
            # print "Twisting ends, now test for irreducibility"
            if (q.is_irreducible()):
                # print "Irreducible polynomial"
                if (q.coefficients(sparse=False)[g] % p <> 0):
                    # print "Ordinary"
                    # print "Define K1"
                    K1 = NumberField(q, 'b')
                    # print K1
                    # print K1.discriminant()
                    # print "Define K1Real"
                    K1Real = K1.maximal_totally_real_subfield()[0]

                    # print "Comparisons"
                    if (CMField == QQ):
                        CMField = K1
                    if (RMField == QQ):
                        RMField = K1Real
                    if (FullCM and not CMField.is_isomorphic(K1)):
                        FullCM = False
                    if (RM and RMField.degree() == 1):
                        RM = False
                    if (RM and not RMField.is_isomorphic(K1Real)):
                        RM = False

                    FieldDiscriminant = K1.discriminant()
                    discBound = GCD(discBound, FieldDiscriminant)
                    # print "Current discriminant bound", discBound
                    if discBound <= 4:
                        return "Z", 1
    if FullCM:
        return "FullCM", discBound
    if RM:
        return "RM", discBound ^ (1 / g)

    return "Quadratic", discBound ^ (1 / g)
Esempio n. 10
0
def list_to_factored_poly_otherorder(s,
                                     galois=False,
                                     vari='T',
                                     prec=None,
                                     p=None):
    """ Either return the polynomial in a nice factored form,
        or return a pair, with first entry the factored polynomial
        and the second entry a list describing the Galois groups
        of the factors.
        vari allows to choose the variable of the polynomial to be returned.
    """
    gal_list = []
    if len(s) == 1:
        if galois:
            return [str(s[0]), [[0, 0]]]
        return str(s[0])
    sfacts = factor(PolynomialRing(ZZ, 'T')(s))
    sfacts_fc = [[v[0], v[1]] for v in sfacts]
    if sfacts.unit() == -1:
        sfacts_fc[0][0] *= -1
    outstr = ''
    for v in sfacts_fc:
        this_poly = v[0]
        # if the factor is -1+T^2, replace it by 1-T^2
        # this should happen an even number of times, mod powers
        if this_poly.substitute(T=0) == -1:
            this_poly = -1 * this_poly
            v[0] = this_poly
        if galois:
            this_degree = this_poly.degree()
            # hack because currently sage only handles monic polynomials:
            this_poly = this_poly.reverse()
            this_number_field = NumberField(this_poly, "a")
            this_gal = this_number_field.galois_group(type='pari')
            this_t_number = this_gal.group().__pari__()[2].sage()
            gal_list.append([this_degree, this_t_number])
        vcf = v[0].list()
        terms = 0
        if len(sfacts) > 1 or v[1] > 1:
            outstr += '('
        for i in range(len(vcf)):
            if vcf[i] != 0:
                if terms > 0 and vcf[i] > 0:
                    outstr += '+'
                if i == 0:
                    outstr += str(vcf[i])
                else:
                    if i == 1:
                        variableterm = vari
                    elif i > 1:
                        variableterm = vari + '^{' + str(i) + '}'

                    if terms == prec and i != len(vcf) - 1:
                        if vcf[i] < 0:
                            outstr += '+'  # we haven't added the +
                        outstr += 'O(%s)' % variableterm
                        break
                    if vcf[i] == 1:
                        outstr += variableterm
                    elif abs(vcf[i]) != 1:
                        if p is None or vcf[i] % p != 0:
                            outstr += str(vcf[i]) + variableterm
                        else:
                            # we try to factor p
                            res = vcf[i]
                            e = 0
                            while res % p == 0:
                                res /= p
                                e += 1
                            assert e != 0
                            pfactor = 'p^{%d}' % e if e > 1 else 'p'
                            if res == 1:
                                res = ''
                            elif res == -1:
                                res = '-'
                            else:
                                res = str(res)
                            outstr += '%s %s %s' % (res, pfactor, variableterm)
                    elif vcf[i] == -1:
                        outstr += '-' + variableterm
                terms += 1

        if len(sfacts) > 1 or v[1] > 1:
            outstr += ')'
        if v[1] > 1:
            outstr += '^{' + str(v[1]) + '}'
    if galois:
        if galois and len(sfacts_fc) == 2:
            if sfacts[0][0].degree() == 2 and sfacts[1][0].degree() == 2:
                troubletest = sfacts[0][0].disc() * sfacts[1][0].disc()
                if troubletest.is_square():
                    gal_list = [[2, 1]]
        return [outstr, gal_list]
    return outstr
Esempio n. 11
0
def subfields_polynomials(f):
    return [
        polredabs(sL.absolute_polynomial())
        for sL, _, _ in NumberField(f, 'a').subfields()
    ]
def get_form_data_from_file(nf, data_dir=NF_DIR, max_dim=50, verbose=False):
    """Fill in data for an incomplete WebNewform object by reading from a
    data file.  If a suitable file does not exist, the original
    WebNewform object is returned unchanged, with a message output.

    The data files only contain the extra data for dimensions less
    than some bound.  If the newform's dimension is greater then we do
    nothing.

    """
    if not nf.field_poly is None:
        return nf
    fname = label = nf.label
    datafile = "/".join([data_dir, fname])
    try:
        data = read_dtp(datafile, verbose=False)
    except FileNotFoundError:
        fname = fname[:fname.rindex(".")]
        datafile = "/".join([data_dir, fname])
        try:
            data = read_dtp(datafile, verbose=False)
        except FileNotFoundError:
            print("No file {} or {} found: no data available".format(datafile,label))
            return nf

    if verbose:
        print("Successfully read data for {} from file {}".format(label, fname))
        
    # Now we have data.  It is a dict with a single key (N,k,o) where
    # o is the character orbit number and value so we just extract the
    # single value for this key, which is another dict:

    data = list(data.values())[0]

    # This dict has keys ['dims', 'traces', 'ALs', 'polys',
    # 'eigdata'], and each value is a list, one per newform, so we
    # need to extract just one item from the relevant lists, according
    # to the newform we want.  This is determined by the 4th (last)
    # part of the label we have, which we need to convert to an
    # integer (from 0).

    # NB eigdata is a list of dicts (see later comment for details)
    # but *only* for components of dimension>1
    
    nf_index = class_to_int(label.split(".")[3])
    dims = data['dims']
    nf_eigdata_index = nf_index - dims.count(1)
    if verbose: # debug
        print("Newform label = {}".format(label))
        print("nf_index = {}".format(nf_index))
        print("len(polys) = {}".format(len(data['polys'])))
        print("len(dims) = {}".format(len(dims)))
        print("#dims>1 = {}".format(len(dims)-dims.count(1)))
        print("len(eigdata) = {}".format(len(data['eigdata'])))
        print("nf_eigdata_index = {}".format(nf_eigdata_index))
    dim = data['dims'][nf_index]
    assert dim == nf.dim
    nf.field_poly = data['polys'][nf_index]

    eigdata = data['eigdata'][nf_eigdata_index]

    # eigdata is a dict with keys  ['poly', 'basis', 'n', 'm', 'ans', 'char']
    chi_gens, chi_vals = eigdata['char']
    nf.hecke_ring_character_values = list(zip(chi_gens, chi_vals))
    # we will not need to access the char_order since this space has
    # already been selected to have an appropriate character.

    if verbose:
        print("hecke_ring_character_values = {}".format(nf.hecke_ring_character_values))
    
    Qx = PolynomialRing(QQ,'x')
    nf.hecke_field = K = NumberField(Qx(nf.field_poly), 'a_')
    nf.betas = [K(b) for b in eigdata['basis']]
    nf.an = eigdata['ans']
    nf.ap = [nf.an[p-1] for p in primes(len(nf.an))]

    if verbose: # debug
        print("We have {} a_n and {} a_p for newforms {}".format(len(nf.an), len(nf.ap), label))
    return nf
def get_forms(N, k, ell, max_dim=50, verbose=False):
    """
    Input: N (level), k (weight), ell (prime); and a verbosity flag

    Output: 2 lists of newforms of level N, weight k, whose character
    chi has order compatible with ell.

    (1) forms for which we have the Hecke field and which have at
    least one mod-ell reduction.  The reductions are stored as an
    attribute (.reductions) for each of these newforms.

    (2) forms for which we do not have the Hecke field in the
    database, for which we currently do nothing.

    """
    if N%ell==0:
        return [], []
    nfs  = db.mf_newforms
    heckes = db.mf_hecke_nf # for more ap
    forms  = [WebNewform.by_label(f_label) for f_label in
              nfs.search({'level':N, 'weight':k}, projection='label')]
    if verbose:
        print("forms with (N,k)=({},{}): {}".format(N,k,[f.label for f in forms]))

    # omit forms whose character order is invalid:
    
    forms = [f for f in forms if char_order_valid(f.char_order, ell)]
    if verbose:
        print("After char order check, forms with (N,k,ell)=({},{},{}): {}".format(N,k,ell,[(f.label,f.dim) for f in forms]))

    # for forms with no Hecke field, try to read from a data file

    forms_with_no_field = [f for f in forms if f.field_poly is None]

    if forms_with_no_field:
        if verbose:
            print("Before reading data files, {} forms have no Hecke field data: {}".format(len(forms_with_no_field), [f.label for f in forms_with_no_field]))

        for f in forms:
            if f.field_poly is None and f.dim <= max_dim:
                if verbose:
                    print("looking for a data file for form {}".format(f.label))
                f = get_form_data_from_file(f, max_dim=max_dim, verbose=verbose)

        forms_with_no_field = [(f.label,f.dim,ell) for f in forms if f.field_poly is None]
        if verbose:
            print("After reading data files, {} forms have no Hecke field data".format(len(forms_with_no_field)))

    # Now exclude any forms which still have no Hecke data:

    forms = [f for f in forms if f.field_poly]
    
    # find all mod-ell reduction maps from the Hecke order

    Qx = PolynomialRing(QQ,'x')
    for f in forms:
        f.hecke_field = NumberField(Qx(f.field_poly), 'a_')
        if verbose:
            print("making reductions for {} mod {}".format(f.label, ell))
            print("Hecke field is {}".format(f.hecke_field))
        f.reductions = make_reductions(f, ell, verbose)
        if verbose:
            print("finished making reductions for {} mod {}".format(f.label, ell))

        try:
            assert f.an
        except AttributeError:
            # get extra ap from the second table:
            anap = heckes.lucky({'label':f.label}, projection=['ap','an'])
            f.an = anap['an']
            f.ap = anap['ap']

            if verbose:
                nap = len(f.ap)
                print("Found {} ap and {} an in the second table".format(nap,len(f.an)))
        
    # Exclude forms with no mod-ell reductions:
        
    forms = [f for f in forms if f.reductions]
    if forms and verbose:
        print("{}.{} forms with mod-{} reductions:".format(N,k,ell))
        for f in forms:
            print("{} has {} reductions mod {}".format(f.label,len(f.reductions), ell))

    return forms, forms_with_no_field
Esempio n. 14
0
def find_newform_label(level, weight, character, field, aps):
    r"""
    Find the label of the newform orbit in the database which matches the input.
    
    INPUT:
    - 'level'     -- the level,
    - 'weight'    -- the weight
    - 'character' -- the character'
    - 'field'     -- the field, given in terms of a list of integer coefficients for the absolute polynomial  
    - 'aps'       -- the coefficients - given as a dictionary of lists giving the coefficient in terms of the generator of the field as above.
    
    
    EXAMPLE:
    
    sage: find_newform_label(9,16,1,[-119880,0,1],{2:[0,1]})
    u'e'
    sage: find_newform_label(71,2,1,[-3,-4,1,1],{3:[0,-1,0]})
    u'a'
    sage: find_newform_label(71,2,1,[-3,-4,1,1],{5:[5,1,-1]})
    u'a'
    
    NOTE: We implicitly assume that the input given is correct in the sense that 
        if there is a unique orbit with a coefficient field of the same degree as the input
        then we simply return that label. (This will save a lot of time...)
        
    """
    from web_modform_space import WebModFormSpace
    from sage.all import NumberField, QQ
    M = WebModFormSpace(level=level, weight=weight, character=character)
    if M.dimension_new_cusp_forms == 1:
        return 'a'
    orbits = M.hecke_orbits
    ## construct field from field input...
    if not isinstance(field, list):
        raise ValueError, "Need to give field as a list!"
    if not isinstance(aps, dict):
        raise ValueError, "Need to give aps as a dict!"
    if field == [1]:
        NF = QQ
    else:
        NF = NumberField(QQ['x'](field), names='x')
    degree_of_input = NF.absolute_degree()
    degrees = map(lambda x: x[1].coefficient_field_degree, orbits.viewitems())
    if degrees.count(degree_of_input) == 0:
        raise ValueError, "No newform with this level, weight, character and field degree!"
    if degrees.count(degree_of_input) == 1:
        ## If there is a unique mathcing field we return this orbit label.
        l = filter(lambda x: x[1].coefficient_field_degree == degree_of_input,
                   orbits.viewitems())
        return l[0][0]
    aps_input = {p: NF(a) for p, a in aps.viewitems()}
    possible_labels = orbits.keys()
    for label, f in orbits.viewitems():
        if f.coefficient_field_degree != degree_of_input:
            possible_labels.remove(label)
            continue
        try:
            for p, ap_input in aps_input.viewitems():
                if f.coefficient_field == QQ:
                    homs = [lambda x: x]
                else:
                    homs = f.coefficient(p).parent().Hom(NF)
                for h in homs:
                    ap = h(f.coefficient(p))
                    if ap_input != ap:
                        possible_labels.remove(label)
                        raise StopIteration
        except StopIteration:
            continue
    if len(possible_labels) > 1:
        raise ArithmeticError, "Not sufficient data (or errors) to determine orbit!"
    if len(possible_labels) == 0:
        raise ArithmeticError, "Not sufficient data (or errors) to determine orbit! NO matching label found!"
    return possible_labels[0]
Esempio n. 15
0
    ...       print nm, p, t.charpoly().factor()
    5 a + 2 (x - 6) * (x^2 + 4*x - 1) * (x^2 - x - 4)^2
    9 3 (x - 10) * (x^2 + 3*x - 9) * (x^4 - 5*x^3 + 3*x^2 + 6*x - 4)
    11 a + 3 (x - 12) * (x + 3)^2 * (x^4 - 17*x^2 + 68)
    11 2*a + 3 (x - 12) * (x^2 + 5*x + 5) * (x^4 - x^3 - 23*x^2 + 18*x + 52)
"""
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division

from builtins import range
from builtins import object
from sage.all import NumberField, polygen, QQ, ZZ, QuaternionAlgebra, cached_function, disk_cached_function

x = polygen(QQ, 'x')
F = NumberField(x**2 - x - 1, 'a')
O_F = F.ring_of_integers()
B = QuaternionAlgebra(F, -1, -1, 'i,j,k')


def modp_splitting(p):
    """
    INPUT:
        
        - p -- ideal of the number field K = B.base() with ring O of integers.
        
    OUTPUT:
        
        - matrices I, J in M_2(O/p) such that i |--> I and j |--> J defines 
          an algebra morphism, i.e., I^2=a, J^2=b, I*J=-J*I.
Esempio n. 16
0
def process_pari_nf(pari_nf, dmax=20, Detail=0):
    r"""
    Input is a dict with keys 'Nko' (N,k,chi_number), 'chipoly',  'SB' (Sturm bound), 'pari_newform',  'poly',  'ans',   'ALeigs', 'traces'

    Output adds 'traces' (unless already computed), and also 'eigdata' if 1<dimension<=dmax
    We do not yet use polredbest or optimize an coeffients

    NB This must be called on  each newform *before* the GP process associated with the data has been terminated.

    """
    Nko = pari_nf['Nko']
    chipoly = pari_nf['chipoly']
    poly = pari_nf['poly']
    SB = pari_nf['SB']
    ALeigs = pari_nf['ALeigs']
    traces = pari_nf['traces']
    assert traces # not None
    ans = pari_nf['ans']
    basis = pari_nf['basis']

    # initialize with data needing no more processing:

    newform = {'Nko': Nko, 'chipoly': chipoly, 'SB': SB, 'ALeigs':ALeigs, 'traces':traces}

    # Set the polynomial.  poly is the relative polynomial, in x (so
    # just x if the top degree is 1) with coefficients either integers
    # (if the bottom degree is 1) or polmods with modulus chipoly.
    #  rel_poly is in Qchi[x].

    Qx = PolynomialRing(QQ,'x')
    #pari_Qx_poly_to_sage = lambda f: Qx(gen_to_sage(f.Vecrev()))
    Qchi = NumberField(chipoly,'t')
    chi_degree = chipoly.degree()
    # NB the only reason for negating the chi_degree parameter here is to get around a bug in the Sage/pari interface
    pari_Qchi_to_sage = lambda elt: Qchi(gen_to_sage(elt.lift().Vecrev(chi_degree)))
    Qchi_x = PolynomialRing(Qchi,'x')
    pari_Qchix_poly_to_sage = lambda f: Qchi_x([pari_Qchi_to_sage(co) for co in f.Vecrev()])

    rel_poly = pari_Qchix_poly_to_sage(poly)
    rel_degree = rel_poly.degree()

    newform['dim'] = dim = chi_degree*rel_degree
    small = (dmax==0) or (dim<=dmax)

    # for 'small' spaces we compute more data, where 'small' means
    # dimension<=dmax (unless dmax==0 in which case all spaces are
    # deemed small).  However spaces of dimension 1 never need the
    # additional data.

    if Detail:
        print("{}: degree = {} = {}*{}".format(Nko, dim, chi_degree, rel_degree))
        if Detail>1:
            print("rel_poly for {} is {}".format(Nko,rel_poly))

    # The newform has its 'traces' field set already. We will have set
    # its 'ans' field where relevant (1<dim<=dmax) to a list of lists
    # of coefficients in Qchi.  In the genuinely relative case we'll
    # need to absolutise these.

    if Detail>1: print("raw ans = {}".format(ans))

    # dimension 1 spaces: little to do

    if dim==1:  # e.g. (11,2,1)[0]
        newform['poly'] = Qx.gen()
        return newform

    # no more data required for non-small spaces:

    if not small:
        return newform

    if chi_degree==1: # e.g. (13,4,1)[1]; now rel_degree>1
        # field is not relative, ans are lists of integers, coeffs w.r.t. basis
        t0=time.time()
        ancs = [gen_to_sage(an) for an in ans]
        t1 = time.time()
        if Detail:
            print("time for converting an coeffs to QQ = {}".format(t1-t0))
            if Detail>1:
                print("Coefficient vectors of ans: {}".format(ancs))
        newform['poly'] = rel_poly
        # basis is a pari matrix over Q
        basis = gen_to_sage(basis)

        newform['eigdata'] = {
            'pol': rel_poly.list(),
            'bas': basis,
            'n': 0, # temporary
            'm': 0, # temporary
            'ancs': ancs,
            }

        return newform

    if rel_degree==1: # e.g. (25,2,4)[0]; now chi_degree>1

        # the field is not relative; ans is a lists of 1-lists of
        # t_POLMOD modulo a GP poly in t, so we lift them and take
        # their coefficient vector to get the coordinates w.r.t. a
        # power basis for the field defined by chipoly.

        t0=time.time()
        ancs = [gen_to_sage(an[0].lift().Vecrev(dim)) for an in ans] # list of lists of integers/rationals
        t1 = time.time()
        if Detail:
            print("time for converting an coeffs to QQ = {}".format(t1-t0))
            if Detail>1:
                print("Coefficient vectors of ans: {}".format(ancs))
        newform['poly'] = chipoly
        # basis is a 1x1 gp matrix over Qchi, so we want the power basis for Qchi: trivial
        basis = [[int(i==j) for j in range(dim)] for i in range(dim)]

        newform['eigdata'] = {
            'pol': chipoly.list(),
            'bas': basis,
            'n': 0, # temporary
            'm': 0, # temporary
            'ancs': ancs,
            }

        return newform

    # Now we are in the genuinely relative case where chi_degree>1 and rel_degree>1
    # e.g. (25,2,5)

    # Now ans is a (python) list of nan (GP) lists of d_rel elements
    # of Qchi, and basis is a GP d_rel x d_rel matrix over Qchi

    #Setting the Hecke field as a relative extension of Qchi and as an absolute field:

    t0=time.time()
    Frel  = Qchi.extension(rel_poly,'b')
    newform['poly'] = abs_poly = Frel.absolute_polynomial()(Qx.gen())
    t1 = time.time()
    if Detail:
        print("absolute poly = {}".format(abs_poly))
        if Detail>1:
            print("Frel = {}".format(Frel))
            print("Time to construct Frel and find absolute poly = {}".format(t1-t0))
    Fabs = Frel.absolute_field('a')
    if Detail>1:
        print("Fabs = {}".format(Fabs))
    rel2abs = Fabs.structure()[1] # the isomorphism Frel --> Fabs
    z = rel2abs(Qchi.gen())
    zpow = [z**i for i in range(chi_degree)]
    # convert basis to a Sage list of lists of elements of Qchi:
    our_basis_coeffs = [[pari_Qchi_to_sage(basis[i,j]) for j in range(rel_degree)] for i in range(rel_degree)]
    #print("our basis coeffs: {} (parent {})".format(our_basis_coeffs, our_basis_coeffs[0][0].parent()))
    our_basis_rel = [Frel(b) for b in our_basis_coeffs]
    #print("our basis (Sage, relative): {}".format(our_basis_rel))
    our_basis_abs = [rel2abs(b) for b in our_basis_rel]
    #print("our basis (Sage, absolute): {}".format(our_basis_abs))
    basis = sum([[(zpowi*yj).list() for zpowi in zpow] for yj in our_basis_abs],[])
    #print("basis (Sage, matrix/Q): {}".format(basis))
    t2 = time.time()
    if Detail>1:
        print("Time to construct Fabs and y,z in Fabs and basis matrix = {}".format(t2-t1))

    #  Convert coordinates of the an.  After lifting these are lists
    #  of lists of polynomials in Q[t] so simply extracting
    #  coefficient vectors gives their coordinates in terms of the
    #  basis z^i*y_j where Qchi=Q(z) and [y_1,...,y_d_rel] is the
    #  Qchi-basis of Frel.  To relate these to the power basis of Fabs
    #  we only need the change of basis matrix whose rows give the
    #  power basis coefficients of each z^i*y_j (in the right order).

    ancs = [[gen_to_sage(c.lift().Vecrev(chi_degree)) for c in an] for an in ans]
    t4 = time.time()
    if Detail>1:
        print("Time to construct ancs) = {}".format(t4-t2))
    ancs = [sum([anci for anci in anc],[]) for anc in ancs]
    if Detail>1:
        print("Coefficient vectors of ans: {}".format(ancs))

    newform['eigdata'] = {
        'pol': abs_poly.list(),
        'bas': basis,
        'n': 0, # temporary
        'm': 0, # temporary
        'ancs': ancs,
    }

    return newform
Esempio n. 17
0
    def __init__(self,
                 E,
                 kernel=None,
                 rational_maps=None,
                 degree=None,
                 kernel_polynomial=None,
                 frobenius_power=0,
                 element=None,
                 ring=None,
                 isogeny=None):

        self._domain = E
        self._ring = ring
        self._field = NumberField(E.frobenius_polynomial(), 'c')
        self._order_element = element
        if isinstance(element, tuple):
            c = self._field.gen()
            self._order_element = element[0] + element[1] * c
        if isinstance(element, Integer):
            self._order_element = self._field(element)
        self._trace = None

        if isogeny != None:
            Isogeny.__init__(self,
                             E,
                             rational_maps=isogeny.rational_maps(),
                             codomain=E)

        # Construction using provided order element
        if element != None:

            # 0 endomorphism has to be dealt with separately
            if element == 0:

                Isogeny.__init__(self, E, 0)
                self._order_element = element
                self._trace = 0

            else:

                k1 = self._order_element.polynomial()[0]
                k2 = self._order_element.polynomial()[1]
                denom = k2.denominator().lcm(k1.denominator())
                a = k1.numerator() * (denom // k1.denominator())
                b = k2.numerator() * (denom // k2.denominator())

                A = multiplication_end(E, a)
                B = multiplication_end(E, b)
                frob = frobenius(E)

                rational_maps = add_maps(A, compose_endomorphisms(B, frob, E),
                                         E)
                if denom == 1:
                    Isogeny.__init__(self,
                                     E,
                                     rational_maps=rational_maps,
                                     codomain=E)
                else:
                    kernel = []
                    isg = Isogeny(E, rational_maps=rational_maps, codomain=E)

                    for P in isg.kernel():

                        Q = denom * P
                        if Q != (Q - Q):
                            kernel.append(Q)

                    kernel = list(dict.fromkeys(kernel))

                    Isogeny.__init__(self, E, kernel=kernel, codomain=E)

        # Otherwise use Isogeny class
        else:
            if degree != None:
                Isogeny.__init__(self, E, degree=degree, codomain=E)
            else:
                Isogeny.__init__(self,
                                 E,
                                 kernel=kernel,
                                 rational_maps=rational_maps,
                                 kernel_polynomial=kernel_polynomial,
                                 frobenius_power=frobenius_power,
                                 codomain=E)
Esempio n. 18
0
def process_pari_nf_v1(pari_nf, dmax=20, Detail=0):
    r"""
    Input is a dict with keys 'Nko' (N,k,chi_number), 'chipoly',  'SB' (Sturm bound), 'pari_newform',  'poly',  'ans',   'ALeigs', 'traces'

    Output adds 'traces' (unless already computed), and also 'eigdata' if 1<dimension<=dmax
    We do not yet use polredbest or optimize an coeffients
    """
    Nko = pari_nf['Nko']
    chipoly = pari_nf['chipoly']
    poly = pari_nf['poly']
    SB = pari_nf['SB']
    ALeigs = pari_nf['ALeigs']
    traces = pari_nf['traces']

    # initialize with data needing no more processing:

    newform = {'Nko': Nko, 'chipoly': chipoly, 'SB': SB, 'ALeigs':ALeigs, 'traces':traces}

    # Set the polynomial.  This is a polynomial in y, (just y if the
    # top degree is 1) with coefficients either integers (if the
    # bottom degree is 1) or polmods with modulus chipoly.  In all
    # cases rel_poly will be in Qchi[y].

    Qx = PolynomialRing(QQ,'x')
    #pari_Qx_poly_to_sage = lambda f: Qx(gen_to_sage(f.Vecrev()))
    Qchi = NumberField(chipoly,'t')
    chi_degree = chipoly.degree()
    # NB the only reason for negating the chi_degree parameter here is to get around a bug in the Sage/pari interface
    pari_Qchi_to_sage = lambda elt: Qchi(gen_to_sage(elt.lift().Vecrev(chi_degree)))
    Qchi_x = PolynomialRing(Qchi,'x')
    pari_Qchix_poly_to_sage = lambda f: Qchi_x([pari_Qchi_to_sage(co) for co in f.Vecrev()])

    rel_poly = pari_Qchix_poly_to_sage(poly)
    rel_degree = rel_poly.degree()

    newform['dim'] = dim = chi_degree*rel_degree
    small = (dmax==0) or (dim<=dmax)

    # for 'small' spaces we compute more data, where 'small' means
    # dimension<=dmax (unless dmax==0 in which case all spaces are
    # deemed small).  However spaces of dimension 1 never need the
    # additional data.

    if Detail:
        print("{}: degree = {} = {}*{}".format(Nko, dim, chi_degree, rel_degree))
        if Detail>1:
            print("rel_poly for {} is {}".format(Nko,rel_poly))

    # the newform will have its 'traces' field set already if it is
    # the only newform in its (N,k,chi)-newspace.  Otherwise we will
    # have set its 'ans' field and now compute the traces from that.
    # The 'ans' field will be None if we don't need the an, which is
    # if (1) the dimension is greater than dmax and (2) the
    # (N,k,chi)-newspace is irreducible.

    ans = pari_nf['ans']
    if Detail>1: print("raw ans = {}".format(ans))

    # dimension 1 spaces: special case simpler traces, and no more to do:

    x = Qx.gen()
    if dim==1:  # e.g. (11,2,1)[0]
        #traces = gen_to_sage(ans)[1:]
        newform['poly'] = x
        if Detail>1: print("traces = {}".format(newform['traces']))
        return newform

    # All dimensions >1: traces

    if newform['traces']==None:
        traces = [abstrace(an,dim) for an in ans][1:]
        # fix up trace(a_1)
        traces[0]=dim
        if Detail>1: print("traces = {}".format(traces))
        newform['traces'] = traces

    # no more data required for non-small spaces:

    if not small:
        return newform

    if chi_degree==1 or rel_degree==1: # e.g. (13,4,1)[1] or (25,2,4)[0] respectively

        # field is not relative, ans are t_POLMOD modulo pari_pol in y
        # or t, so if we lift them and take their coefficient vector
        # we'll get the coordinates w.r.t. a power basis for the field
        # defined by either rel_poly or chipoly.

        t0=time.time()
        # for an in ans[:20]:
        #     print("an = {}".format(an))
        #     print("an.lift() = {}".format(an.lift()))
        #     print("an.lift().Vecrev(dim) = {}".format(an.lift().Vecrev(dim)))
        #     print("gen_to_sage(an.lift().Vecrev(dim)) = {}".format(gen_to_sage(an.lift().Vecrev(dim))))
        ancs = [gen_to_sage(an.lift().Vecrev(dim)) for an in ans][1:]
        t1 = time.time()
        if Detail:
            print("time for converting an coeffs to QQ = {}".format(t1-t0))
        basis = [[int(i==j) for j in range(dim)] for i in range(dim)]
        newform['poly'] = poly = Qx(rel_poly) if chi_degree==1 else Qx(chipoly)

        if Detail>1:
            print("Coefficient vectors of ans: {}".format(ancs))

        newform['eigdata'] = {
            'pol': poly.list(),
            'bas': basis,
            'n': 0, # temporary
            'm': 0, # temporary
            'ancs': ancs,
            }

        return newform

    # Now we are in the genuinely relative case where chi_degree>1 and rel_degree>1
    # e.g. (25,2,5)

    #Setting the Hecke field as a relative extension of Qchi and as an absolute field:

    t0=time.time()
    Frel  = Qchi.extension(rel_poly,'b')
    abs_poly = Frel.absolute_polynomial()
    newform['poly'] = abs_poly(x)
    t1 = time.time()
    if Detail:
        print("absolute poly = {}".format(abs_poly))
        if Detail>1:
            print("Time to construct Frel and find absolute poly = {}".format(t1-t0))
    Fabs = Frel.absolute_field('a')
    rel2abs = Fabs.structure()[1] # the isomorphism Frel --> Fabs
    z = rel2abs(Qchi.gen())
    y = rel2abs(Frel.gen())
    zpow = [z**i for i in range(chi_degree)]
    ypow = [y**j for j in range(rel_degree)]
    basis = sum([[(zpowi*ypowj).list() for zpowi in zpow] for ypowj in ypow],[])
    t2 = time.time()
    if Detail>1:
        print("Time to construct Fabs and y,z in Fabs and basis matrix = {}".format(t2-t1))

    #  Get coordinates of the an.  After lifting twice these are
    #  polynomials in Q[t][y] so simply extracting coefficient vectors
    #  gives their coordinates in terms of the basis z^i*y^j where
    #  Qchi=Q(z) and F=Qchi(y).  To relate these to the power basis of
    #  Fabs we only need the change of basis matrix whose rows give
    #  the power basis coefficients of each z^i*y^j (in the right
    #  order).

    ancs = [[gen_to_sage(c.lift().Vecrev(chi_degree)) for c in a.lift().Vecrev(rel_degree)] for a in ans][1:]
    t4 = time.time()
    if Detail>1:
        print("Time to construct ancs) = {}".format(t4-t2))
    ancs = [sum([anci for anci in anc],[]) for anc in ancs]
    if Detail>1:
        print("Coefficient vectors of ans: {}".format(ancs))

    newform['eigdata'] = {
        'pol': abs_poly.list(),
        'bas': basis,
        'n': 0, # temporary
        'm': 0, # temporary
        'ancs': ancs,
    }

    return newform
Esempio n. 19
0
    def make_form(self, nap0=50):
        # To start with the data fields of self are just those from
        # the database.  We need to reformat these and compute some
        # further (easy) data about it.
        #
        from lmfdb.ecnf.WebEllipticCurve import FIELD
        self.field = FIELD(self.field_label)
        pretty_field = field_pretty(self.field_label)
        self.field_knowl = nf_display_knowl(self.field_label, pretty_field)
        try:
            dims = db.bmf_dims.lucky(
                {
                    'field_label': self.field_label,
                    'level_label': self.level_label
                },
                projection='gl2_dims')
            self.newspace_dimension = dims[str(self.weight)]['new_dim']
        except TypeError:
            self.newspace_dimension = 'not available'
        self.newspace_label = "-".join([self.field_label, self.level_label])
        self.newspace_url = url_for(".render_bmf_space_webpage",
                                    field_label=self.field_label,
                                    level_label=self.level_label)
        K = self.field.K()

        # 'hecke_poly_obj' is the non-LaTeX version of hecke_poly
        self.hecke_poly_obj = self.hecke_poly

        if self.dimension > 1:
            Qx = PolynomialRing(QQ, 'x')
            self.hecke_poly = Qx(str(self.hecke_poly))
            F = NumberField(self.hecke_poly, 'z')
            self.hecke_poly = web_latex(self.hecke_poly)

            def conv(ap):
                if '?' in ap:
                    return 'not known'
                else:
                    return F(str(ap))

            self.hecke_eigs = [conv(str(ap)) for ap in self.hecke_eigs]

        self.level = ideal_from_label(K, self.level_label)
        self.level_ideal2 = web_latex(self.level)
        badp = self.level.prime_factors()

        self.nap = len(self.hecke_eigs)
        self.nap0 = min(nap0, self.nap)
        self.neigs = self.nap0 + len(badp)
        self.hecke_table = [[
            web_latex(p.norm()),
            ideal_label(p),
            web_latex(p.gens_reduced()[0]),
            web_latex(ap)
        ] for p, ap in zip(primes_iter(K), self.hecke_eigs[:self.neigs])
                            if not p in badp]
        self.have_AL = self.AL_eigs[0] != '?'
        if self.have_AL:
            self.AL_table = [[
                web_latex(p.norm()),
                ideal_label(p),
                web_latex(p.gens_reduced()[0]),
                web_latex(ap)
            ] for p, ap in zip(badp, self.AL_eigs)]
            # The following helps to create Sage download data
            self.AL_table_data = [[p.gens_reduced(), ap]
                                  for p, ap in zip(badp, self.AL_eigs)]
        self.sign = 'not determined'

        try:
            if self.sfe == 1:
                self.sign = "$+1$"
            elif self.sfe == -1:
                self.sign = "$-1$"
        except AttributeError:
            self.sfe = '?'

        if self.Lratio == '?':
            self.Lratio = "not determined"
            self.anrank = "not determined"
        else:
            self.Lratio = QQ(self.Lratio)
            self.anrank = r"\(0\)" if self.Lratio != 0 else "odd" if self.sfe == -1 else r"\(\ge2\), even"

        self.properties = [('Label', self.label), ('Base field', pretty_field),
                           ('Weight', prop_int_pretty(self.weight)),
                           ('Level norm', prop_int_pretty(self.level_norm)),
                           ('Level', self.level_ideal2),
                           ('Dimension', prop_int_pretty(self.dimension))]

        try:
            if self.CM == '?':
                self.CM = 'not determined'
            elif self.CM == 0:
                self.CM = 'no'
            else:
                if int(self.CM) % 4 in [2, 3]:
                    self.CM = 4 * int(self.CM)
                self.CM = "$%s$" % self.CM
        except AttributeError:
            self.CM = 'not determined'
        self.properties.append(('CM', str(self.CM)))

        self.bc_extra = ''
        self.bcd = 0
        self.bct = self.bc != '?' and self.bc != 0
        if self.bc == '?':
            self.bc = 'not determined'
        elif self.bc == 0:
            self.bc = 'no'
        elif self.bc == 1:
            self.bcd = self.bc
            self.bc = 'yes'
        elif self.bc > 1:
            self.bcd = self.bc
            self.bc = 'yes'
            self.bc_extra = r', of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{' + str(
                self.bcd) + r'})\)'
        elif self.bc == -1:
            self.bc = 'no'
            self.bc_extra = r', but is a twist of the base change of a form over \(\mathbb{Q}\)'
        elif self.bc < -1:
            self.bcd = -self.bc
            self.bc = 'no'
            self.bc_extra = r', but is a twist of the base change of a form over \(\mathbb{Q}\) with coefficients in \(\mathbb{Q}(\sqrt{' + str(
                self.bcd) + r'})\)'
        self.properties.append(('Base change', str(self.bc)))

        curve_bc = db.ec_nfcurves.lucky({'class_label': self.label},
                                        projection="base_change")
        if curve_bc is not None:
            if curve_bc and "." not in curve_bc[0]:
                curve_bc = [
                    cremona_label_to_lmfdb_label(lab) for lab in curve_bc
                ]
            self.ec_status = 'exists'
            self.ec_url = url_for("ecnf.show_ecnf_isoclass",
                                  nf=self.field_label,
                                  conductor_label=self.level_label,
                                  class_label=self.label_suffix)
            curve_bc_parts = [split_lmfdb_label(lab) for lab in curve_bc]
            bc_urls = [
                url_for("cmf.by_url_newform_label",
                        level=cond,
                        weight=2,
                        char_orbit_label='a',
                        hecke_orbit=iso) for cond, iso, num in curve_bc_parts
            ]
            bc_labels = [
                ".".join([str(cond), str(2), 'a', iso])
                for cond, iso, _ in curve_bc_parts
            ]
            bc_exists = [db.mf_newforms.label_exists(lab) for lab in bc_labels]
            self.bc_forms = [{
                'exists': ex,
                'label': lab,
                'url': url
            } for ex, lab, url in zip(bc_exists, bc_labels, bc_urls)]
        else:
            self.bc_forms = []
            if self.bct or self.label in bmfs_with_no_curve:
                self.ec_status = 'none'
            else:
                self.ec_status = 'missing'

        self.properties.append(('Sign', self.sign))
        self.properties.append(('Analytic rank', self.anrank))

        self.friends = []
        self.friends += [('Newspace {}'.format(self.newspace_label),
                          self.newspace_url)]
        url = 'ModularForm/GL2/ImaginaryQuadratic/{}'.format(
            self.label.replace('-', '/'))
        Lfun = get_lfunction_by_url(url)
        if Lfun:
            instances = get_instances_by_Lhash_and_trace_hash(
                Lfun['Lhash'], Lfun['degree'], Lfun['trace_hash'])

            # This will also add the EC/G2C, as this how the Lfun was computed
            # and not add itself
            self.friends = names_and_urls(instances, exclude={url})
            self.friends.append(('L-function', '/L/' + url))
        else:
            # old code
            if self.dimension == 1:
                if self.ec_status == 'exists':
                    self.friends += [('Isogeny class {}'.format(self.label),
                                      self.ec_url)]
                elif self.ec_status == 'missing':
                    self.friends += [
                        ('Isogeny class {} missing'.format(self.label), "")
                    ]
                else:
                    self.friends += [('No elliptic curve', "")]

            self.friends += [('L-function not available', '')]
Esempio n. 20
0
def verify_algebraically_PS(g, P0, alpha, trace_and_norm, verbose=True):
    # input:
    # * P0 (only necessary to shift the series)
    # * [trace_numerator, trace_denominator, norm_numerator, norm_denominator]
    # output:
    # a boolean
    if verbose:
        print "verify_algebraically()"
    L = P0.base_ring()
    assert alpha.base_ring() is L
    L_poly = PolynomialRing(L, "xL")
    xL = L_poly.gen()
    # shifting the series makes our life easier
    trace_numerator, trace_denominator, norm_numerator, norm_denominator = [
        L_poly(coeff)(L_poly.gen() + P0[0]) for coeff in trace_and_norm
    ]
    L_fpoly = L_poly.fraction_field()
    trace = L_fpoly(trace_numerator) / L_fpoly(trace_denominator)
    norm = L_fpoly(norm_numerator) / L_fpoly(norm_denominator)

    Xpoly = L_poly([norm(0), -trace(0), 1])
    if verbose:
        print "xpoly = %s" % Xpoly

    if Xpoly.is_irreducible():
        M = Xpoly.root_field("c")
    else:
        # this avoids bifurcation later on in the code
        M = NumberField(xL, "c")
    if verbose:
        print M

    xi_degree = max(
        [elt.degree() for elt in [trace_denominator, norm_denominator]])
    D = 2 * xi_degree
    hard_bound = D + (4 + 2)
    soft_bound = hard_bound + 5
    M_ps = PowerSeriesRing(M, "T", default_prec=soft_bound)
    T = M_ps.gen()
    Tsub = T + P0[0]

    trace_M = M_ps(trace)
    norm_M = M_ps(norm)
    sqrtdisc = sqrt(trace_M**2 - 4 * norm_M)
    x1 = (trace_M - sqrtdisc) / 2
    x2 = (trace_M + sqrtdisc) / 2

    y1 = sqrt(g(x1))

    y2 = sqrt(g(x2))

    iy = 1 / sqrt(g(Tsub))

    dx1 = x1.derivative(T)
    dx2 = x2.derivative(T)

    dx1_y1 = dx1 / y1
    dx2_y2 = dx2 / y2

    eq1 = Matrix([[-2 * M_ps(alpha.row(0).list())(Tsub) * iy, dx1_y1, dx2_y2]])
    eq2 = Matrix(
        [[-2 * M_ps(alpha.row(1).list())(Tsub) * iy, x1 * dx1_y1,
          x2 * dx2_y2]])
    branches = Matrix([[1, 1, 1], [1, 1, -1], [1, -1, 1], [1, -1,
                                                           -1]]).transpose()
    meq1 = eq1 * branches
    meq2 = eq2 * branches
    algzero = False
    for j in range(4):
        if meq1[0, j] == 0 and meq2[0, j] == 0:
            algzero = True
            break
    if verbose:
        print "Done, verify_algebraically()  = %s" % algzero
    return algzero
Esempio n. 21
0
def list_to_factored_poly_otherorder(s, galois=False):
    """ Either return the polynomial in a nice factored form,
        or return a pair, with first entry the factored polynomial
        and the second entry a list describing the Galois groups
        of the factors.
    """
    gal_list = []
    if len(s) == 1:
        if galois:
            return [str(s[0]), [[0, 0]]]
        return str(s[0])
    sfacts = factor(PolynomialRing(ZZ, 'T')(s))
    sfacts_fc = [[v[0], v[1]] for v in sfacts]
    if sfacts.unit() == -1:
        sfacts_fc[0][0] *= -1
    outstr = ''
    x = var('x')
    for v in sfacts_fc:
        this_poly = v[0]
        # if the factor is -1+T^2, replace it by 1-T^2
        # this should happen an even number of times, mod powers
        if this_poly.substitute(T=0) == -1:
            this_poly = -1 * this_poly
            v[0] = this_poly
        if galois:
            this_degree = this_poly.degree()
            # hack because currently sage only handles monic polynomials:
            this_poly = expand(x**this_degree * this_poly.substitute(T=1 / x))
            this_number_field = NumberField(this_poly, "a")
            this_gal = this_number_field.galois_group(type='pari')
            this_t_number = this_gal.group()._pari_()[2]._sage_()
            gal_list.append([this_degree, this_t_number])
        vcf = v[0].list()
        started = False
        if len(sfacts) > 1 or v[1] > 1:
            outstr += '('
        for i in range(len(vcf)):
            if vcf[i] != 0:
                if started and vcf[i] > 0:
                    outstr += '+'
                started = True
                if i == 0:
                    outstr += str(vcf[i])
                else:
                    if abs(vcf[i]) != 1:
                        outstr += str(vcf[i])
                    elif vcf[i] == -1:
                        outstr += '-'
                    if i == 1:
                        outstr += 'T'
                    elif i > 1:
                        outstr += 'T^{' + str(i) + '}'
        if len(sfacts) > 1 or v[1] > 1:
            outstr += ')'
        if v[1] > 1:
            outstr += '^{' + str(v[1]) + '}'
    if galois:
        if galois and len(sfacts_fc) == 2:
            if sfacts[0][0].degree() == 2 and sfacts[1][0].degree() == 2:
                troubletest = sfacts[0][0].disc() * sfacts[1][0].disc()
                if troubletest.is_square():
                    gal_list = [[2, 1]]
        return [outstr, gal_list]
    return outstr
Esempio n. 22
0
def rational_univariate_representation(ideal):
    """
    Suppose an ideal I in QQ[x_1,...,x_n] is 0 dimensional, and we
    want to describe all the points of the finite set V(I) in CC^n.  A
    rational univariate representation (RUR) of V(I), is a collection
    of univariate polynomials h, g_0, g_1, ... , g_n in QQ[t] where
    deg(h) = #V(I) and deg(g_i) < deg(h) such that the points of V(I)
    correspond precisely to

       (g_1(z)/g_0(z), (g_2(z)/g_0(z), ... (g_n(z)/g_0(z))

    where z in CC is a root of h.

    In this variant, we factor h into irreducibles return each part of
    the RUR individually.

    Example:

    sage: R = PolynomialRing(QQ, ['x', 'y', 'z'])
    sage: x, y, z = R.gens()
    sage: I = R.ideal([x + y + z*z, x*y*z - 3, x*x + y*y + z*z - 2])
    sage: ans = rational_univariate_representation(I)
    sage: len(ans)
    1
    sage: K, rep, mult = ans[0]
    sage: mult
    1
    sage: h = K.polynomial(); h
    x^10 - 2*x^9 - 4*x^8 + 6*x^7 + 7*x^6 - 13*x^5 - 17/2*x^4 + 36*x^3 + 63/2*x^2 + 81/2
    sage: rep[y]
    a
    sage: 1215 * rep[x]  # Here g0 = 1215
    8*a^9 + 8*a^8 - 8*a^7 - 246*a^6 + 128*a^5 + 550*a^4 - 308*a^3 - 636*a^2 + 639*a + 1917
    sage: I.subs(rep).is_zero()
    True

    Here is an example using a Ptolemy variety:

    sage: M = Manifold('t00000')
    sage: obs = M.ptolemy_generalized_obstruction_classes(2)[1]
    sage: V = M.ptolemy_variety(2, obs)
    sage: I = V.ideal_with_non_zero_condition
    sage: ans = rational_univariate_representation(I)
    sage: ans[0][0].polynomial()
    x^8 - 4*x^7 - 2*x^6 + 14*x^5 + 14*x^4 - 7*x^3 - 13*x^2 - x + 5

    For more, see:

    https://en.wikipedia.org/wiki/System_of_polynomial_equations#Rational_univariate_representation

    """
    R = ideal.ring()
    vars = list(R.gens())
    J = giac(ideal.gens())
    rur = J.gbasis(vars, 'rur')
    # Yikes: giacpy_sage vs the giac interface give different types.
    # So using repr.
    if repr(rur[0]) != 'rur':
        raise ValueError(('Could not find RUR, got %r instead. '
                          'Is the variety 0-dimensional?') % rur[0])

    # [x.sage() for rur[4:]] doesn't work with the giac interface (it tries
    # to convert the slicing to a giac expression that giac does not understand)
    #
    # However, rur.sage()[0] gave some trouble, too.
    #
    # So we convert with .sage() after having checked we have rur, but before
    # we inspect the other items.
    rur = rur.sage()

    # Defining polynomial of number field, as a symbolic expression.
    p = rur[2]
    assert len(p.variables()) == 1
    v = p.variables()[0]

    S = PolynomialRing(QQ, repr(v))
    T = PolynomialRing(QQ, 'x')
    p = T(S(p))
    p = p/p.leading_coefficient()

    ans = []
    for q, e in p.factor():
        K = NumberField(q, 'a')

        def toK(f):
            return K(T(S(f)))

        denom = toK(rur[3])
        rep = [toK(f)/denom for f in rur[4:]]
        sub_dict = dict(zip(vars, rep))
        assert all(g.subs(sub_dict) == 0 for g in ideal.gens())
        ans.append((K, sub_dict, e))

    return ans
Esempio n. 23
0
 def field(self):
     if not self.__field:
         f = PolynomialRing(ZZ, name='x')(str(self.__field_poly))
         self.__field = QQ if f.degree() == 1 else NumberField(f, 'a')
     return self.__field
Esempio n. 24
0
def pretty_print_polynomial_list(pol, base, str_var='x', str_gen='r'):
    if pol[0] in QQ:
        return str(PolynomialRing(QQ, str_var)(pol))
    R = PolynomialRing(QQ, 't')
    F = NumberField(R(base), str_gen)
    return str(PolynomialRing(F, str_var)(pol))
Esempio n. 25
0
 def K(self):
     if not self.haskey('K'):
         self._data['K'] = NumberField(self.poly(), self.gen_name)
     return self._data['K']
Esempio n. 26
0
def endomorphisms_upper_bound(frob_list, eta_char0=None):
    r"""
    INPUT:

    - ``frob_list`` -- a list of Frobenius polynomials of A
    - ``eta_char0`` -- a putative value for eta(A)

    OUTPUT:
    - a boolean = did we manage to provide a putative upper bound on the centers?
    - a message, explaining what we have achieved to do.
    - None or a putative value for eta(A) (if this matches the input value, then we proved that this value is correct)
    - None or the number of factors assuming that eta(A) computed above is correct
    - None or a list of tuples
            [ (e_j n_j, n_j * dim A_j, L_j, RR_j ) for j in range(1, t + 1)],
      where we are assuming that the eta(A) and t above are correct and therefore we have
            A^{al} =  A^{al} = (A_1)^n_1 x ... x (A_k)^n_t
      where e_j ^2 is the dimension of End(A_j ^{al}) over its center and
      its center is a subfield of L_j.
      Assuming that L_j is indeed the center, then RR_j = End( A_j ^{n_j} ) \otimes RR.
    - Assuming eta(A) and t are correct, an upper bound for dim_Q End(A)

    """
    g = int(frob_list[0][1].degree() / 2)
    if eta_char0 is None:
        eta = 4 * g * g
        # max value found for eta_p
    else:
        eta = 2 * eta_char0

    t = g
    eta_lower = []
    for p, f in frob_list:
        dimtotal, fieldext, endo = endomorphism_frob(f)
        if dimtotal < eta:
            eta = dimtotal
            t = len(endo)
            eta_lower = []

        if dimtotal == eta:
            if len(endo) < t:
                t = len(endo)
                eta_lower = []
            if len(endo) == t:
                eta_lower.append([p, f, len(endo), dimtotal, fieldext, endo])

    if len(eta_lower) == 0:
        return False, "We  did not manage to find any prime where eta(A_p) = 2 * eta(A)", None, None, None, None

    eta_char0 = eta / 2

    multiset_char0 = None
    frob_factors = [[None] * len(eta_lower) for _ in range(t)]
    for i, (_, _, tp, etap, _, endo) in enumerate(eta_lower):
        assert t == tp
        assert eta == etap
        # endo[j] = mpj, mpj*deg(hpj), hpj
        # the multiset_char0 in the paper has y divided by 2
        multiset = sorted([(x, y) for x, y, _ in endo])
        if multiset_char0 is None:
            multiset_char0 = multiset
            frob_factors = {}
            for pair in Set(multiset):
                frob_factors[pair] = [[] for _ in eta_lower]
        if multiset_char0 != multiset:
            # we only managed to bound eta
            message = "We only managed to find an upper bound for eta."
            message += " If the upper bound for eta indeed is eta, then the number of factors is a strict upper bound"
            return False, message, eta_char0, t, None, None
        for x, y, hpj in endo:
            # endo[j] = mpj, mpj*deg(hpj), hpj
            frob_factors[(x, y)][i].append(polredabs(hpj))

    # it looks like we have a consistent upper bound for eta and t
    message = "We have putatively computed eta and t."
    message += " Under this assumption, we bounded the corresponding centers."

    #We can try to bound the center of each factor
    output = []
    total_dim = 0
    for pair, frob_matrix in frob_factors.iteritems():
        L = field_intersection_matrix(frob_matrix)
        ejnj, njdimAj = pair
        njdimAj = njdimAj // 2
        for Lj in L:
            # the only real functionality of the NumberField that we use is
            # Ljmax.is_CM()
            # so it doesn't matter which field of maximal degree we take
            Ljmax = NumberField(Lj[-1][-1], 'a')
            RRj = RR_representation(njdimAj, Ljmax, ejnj)
            output.append((ejnj, njdimAj, Lj, RRj))
            total_dim += ejnj**2 * Ljmax.degree()

    return True, message, eta_char0, t, output, total_dim
Esempio n. 27
0
def coeff_to_nf(c):
    return NumberField(coeff_to_poly(c), 'a')
Esempio n. 28
0
    def __call__(self, hmult, vmult):
        r"""
        INPUT:

        - ``hmult`` -- multiplicities of the horizontal twists

        - ``vmult`` -- multiplicities of the vertical twists
        """
        if len(hmult) != self._num_hcyls or len(vmult) != self._num_vcyls:
            raise ValueError("invalid input lengths")

        E = self._E
        H = E * diagonal_matrix(vmult)
        V = E.transpose() * diagonal_matrix(hmult)

        if self._num_hcyls < self._num_vcyls:
            F = H * V
        else:
            F = V * H
        p = F.charpoly()
        assert F.nrows() == F.ncols() == min(
            [self._num_hcyls, self._num_vcyls])

        pf = max(p.roots(AA, False))
        mp = pf.minpoly()
        if mp.degree() == 1:
            K = QQ
            pf = QQ(pf)
        else:
            fwd, bck, q = do_polred(pf.minpoly())
            im_gen = fwd(pf)
            K = NumberField(q, 'a', embedding=im_gen)
            pf = bck(K.gen())

        # Compute widths of the cylinders via Perron-Frobenius
        if self._num_hcyls < self._num_vcyls:
            hcirc = (F - pf).right_kernel_matrix()
            assert hcirc.nrows() == 1
            assert hcirc.ncols() == self._num_hcyls
            hcirc = hcirc[0]
            assert all(x > 0 for x in hcirc)
            vcirc = V * hcirc
            c = 1
            d = pf
        else:
            vcirc = (F - pf).right_kernel_matrix()
            assert vcirc.nrows() == 1
            assert vcirc.ncols() == self._num_vcyls
            vcirc = vcirc[0]
            assert all(x > 0 for x in vcirc)
            hcirc = H * vcirc
            d = 1
            c = pf

        # Solve linear systems to get heights
        h = [hcirc[i] * hmult[i] / c for i in range(self._num_hcyls)]
        v = [vcirc[i] * vmult[i] / d for i in range(self._num_vcyls)]

        C = ConvexPolygons(K)
        P = []
        for i in range(self._o.nb_squares()):
            hi = h[self._hcycles[i]]
            vi = v[self._vcycles[i]]
            P.append(C(edges=[(vi, 0), (0, hi), (-vi, 0), (0, -hi)]))

        surface = Surface_list(base_ring=K)
        for p in P:
            surface.add_polygon(p)
        r = self._o.r_tuple()
        u = self._o.u_tuple()
        for i in range(self._o.nb_squares()):
            surface.set_edge_pairing(i, 1, r[i], 3)
            surface.set_edge_pairing(i, 0, u[i], 2)
        surface.set_immutable()
        return TranslationSurface(surface)