Example #1
0
def nf_knowl_guts(label):
    out = ''
    wnf = WebNumberField(label)
    if wnf.is_null():
        return 'Cannot find number field %s' % label
    out += "Number field %s" % label
    out += '<div>'
    out += 'Defining polynomial: '
    out += raw_typeset(wnf.poly(), r"\(%s\)" % latex(wnf.poly()))
    D = wnf.disc()
    Dfact = wnf.disc_factored_latex()
    if D.abs().is_prime() or D == 1:
        Dfact = r"\(%s\)" % str(D)
    else:
        Dfact = r'%s = \(%s\)' % (str(D), Dfact)
    out += '<br>Discriminant: '
    out += Dfact
    out += '<br>Signature: '
    out += str(wnf.signature())
    out += '<br>Galois group: ' + group_pretty_and_nTj(wnf.degree(),
                                                       wnf.galois_t(), True)
    out += '<br>Class number: %s ' % str(wnf.class_number_latex())
    if wnf.can_class_number():
        out += wnf.short_grh_string()
    out += '</div>'
    out += '<div align="right">'
    out += '<a href="%s">%s home page</a>' % (str(
        url_for("number_fields.by_label", label=label)), label)
    out += '</div>'
    return out
Example #2
0
def dirichlet_group_table(**args):
    modulus = request.args.get("modulus", 1, type=int)
    info = to_dict(args)
    if "modulus" not in info:
        info["modulus"] = modulus
    info['bread'] = bread('Group')
    char_number_list = request.args.get("char_number_list", None)
    if char_number_list is not None:
        try:
            info['char_number_list'] = char_number_list
            char_number_list = [int(a) for a in char_number_list.split(',')]
            info['poly'] = request.args.get("poly", '???')
        except (ValueError, AttributeError, TypeError) as err:
            flash_error("<span style='color:black'>%s</span> is not a valid input for <span style='color:black'>%s</span>. %s", char_number_list, 'char_number_list', str(err))
            return abort(404, 'grouptable needs a valid char_number_list argument')
    else:
        return abort(404, 'grouptable needs char_number_list argument')
    h, c = get_group_table(modulus, char_number_list)
    info['headers'] = h
    info['contents'] = c
    info['title'] = 'Group of Dirichlet characters'
    if info['poly'] != '???':
        try:
            info['poly'] = PolynomialRing(QQ, 'x')(info['poly'])
            info['poly'] = raw_typeset(info['poly'])
        except Exception:
            pass
    return render_template("CharacterGroupTable.html", **info)
Example #3
0
def lf_formatfield(coef):
    coef = string2list(coef)
    thefield = WebNumberField.from_coeffs(coef)
    thepoly = coeff_to_poly(coef)
    thepolylatex = '$%s$' % latex(coeff_to_poly(coef))
    if thefield._data is None:
        return raw_typeset(thepoly, thepolylatex)
    return nf_display_knowl(thefield.get_label(), thepolylatex)
Example #4
0
def get_congruent_number_data(n):
    info = {'n': n}
    info['rank'] = rank = int(get_CN_data('rank', n)[1])
    info['is_congruent'] = cong = rank > 0

    ainvs = [0, 0, 0, -n * n, 0]
    E = EllipticCurve(ainvs)
    info['E'] = E

    gens_string = get_CN_data('MWgroup', n)[1]
    gens = [E(g) for g in parse_gens_string(gens_string)]
    info['gens'] = ", ".join([str(g) for g in gens])
    info['missing_generator'] = len(gens) < rank

    # better typesetting of points
    info['gens'] = [raw_typeset(P.xy()) for P in gens]
    if len(gens) == 1:
        info['gen'] = info['gens'][0]

    info['conductor'] = N = int(get_CN_data('conductor', n)[1])
    assert N == E.conductor()

    info['triangle'] = None
    if cong:
        P = 2 * gens[0]
        x, y = P.xy()
        Z = 2 * x.sqrt()
        XplusY = 2 * (x + n).sqrt()
        XminusY = 2 * (x - n).sqrt()
        X = (XplusY + XminusY) / 2
        Y = XplusY - X
        assert X * X + Y * Y == Z * Z
        assert X * Y == 2 * n
        assert X > 0 and Y > 0 and Z > 0
        if X > Y:
            X, Y = Y, X
        info['triangle'] = {'X': X, 'Y': Y, 'Z': Z}

    res = db.ec_curvedata.search({'ainvs': ainvs})
    try:
        res = next(res)
        info['in_db'] = 'exact'
    except StopIteration:
        res = db.ec_curvedata.search({'jinv': [1728, 1], 'conductor': N})
        try:
            res = next(res)
            info['in_db'] = 'isomorphic'
        except StopIteration:
            info['in_db'] = False

    if info['in_db']:
        info['label'] = label = res['lmfdb_label'] if res else None
        info['url'] = url_for(".by_ec_label", label=label)

    return info
Example #5
0
    def computation_roots(self):
        # Write these as p-adic series.  Start with helper
        self.lowered = self.lower_precision()

        def help_padic(n, p, prec):
            """
              Take an integer n, prime p, and precision prec, and return a 
              prec-tuple of the p-adic coefficients of j
            """
            n = ZZ(n)
            res = [0 for j in range(prec)]
            while n < 0:
                n += p**prec
            for k in range(prec):
                res[k] = n % p
                n = (n - res[k]) / p
            return res

        # Second helper, in case some arrays are not extended by 0
        def getel(li, j):
            if j < len(li):
                return li[j]
            return 0

        myroots = self._data["QpRts"]
        p = self._data['QpRts-p']
        prec = self._data['QpRts-prec']
        myroots = [[help_padic(z, p, prec) for z in t] for t in myroots]
        myroots = [[[
            getel(root[j], r)
            for j in range(len(self._data['QpRts-minpoly']) - 1)
        ] for r in range(prec)] for root in myroots]
        myroots = [[coeff_to_poly(x, var='a') for x in root]
                   for root in myroots]
        # Use power series so degrees increase
        # Use formal p so we can make a power series
        PR = PowerSeriesRing(PolynomialRing(QQ, 'a'), 'p')
        rawrts = [str(PR(x)) + r'+O(p^{})'.format(prec) for x in myroots]
        rawrts = [z.replace('p', str(p)) for z in rawrts]
        myroots = [
            web_latex(PR(x), enclose=False) + r'+O(p^{' + str(prec) + r'})'
            for x in myroots
        ]
        # change p into its value
        myroots = [r'\({}\)'.format(z) for z in myroots]
        myroots = [
            re.sub(r'([a)\d]) *p', r'\1\\cdot ' + str(p), z) for z in myroots
        ]
        typesetrts = [z.replace('p', str(p)) for z in myroots]
        return [raw_typeset(z[0], z[1]) for z in zip(rawrts, typesetrts)]
Example #6
0
def modular_form_display(label, number):
    try:
        number = int(number)
    except ValueError:
        number = 10
    if number < 10:
        number = 10
    if number > 1000:
        number = 1000
    ainvs = db.ec_curvedata.lookup(label, 'ainvs', 'lmfdb_label')
    if ainvs is None:
        return elliptic_curve_jump_error(label, {})
    E = EllipticCurve(ainvs)
    modform = E.q_eigenform(number)
    modform_string = raw_typeset(modform)
    return modform_string
Example #7
0
    def make_mwbsd(self):
        mwbsd = self.mwbsd = db.ec_mwbsd.lookup(self.lmfdb_label)

        # Some components are in the main table:

        mwbsd['analytic_rank'] = r = self.analytic_rank
        mwbsd['torsion'] = self.torsion
        tamagawa_numbers = [ld['tamagawa_number'] for ld in self.local_data]
        mwbsd['tamagawa_product'] = prod(tamagawa_numbers)
        if mwbsd['tamagawa_product'] > 1:
            cp_fac = [ZZ(cp).factor() for cp in tamagawa_numbers]
            cp_fac = [
                latex(cp) if len(cp) < 2 else '(' + latex(cp) + ')'
                for cp in cp_fac
            ]
            mwbsd['tamagawa_factors'] = r'\cdot'.join(cp_fac)
        else:
            mwbsd['tamagawa_factors'] = None

        try:
            mwbsd['rank'] = self.rank
            mwbsd['reg'] = self.regulator
            mwbsd['sha'] = self.sha
            mwbsd['sha2'] = latex_sha(self.sha)
        except AttributeError:
            mwbsd['rank'] = '?'
            mwbsd['reg'] = '?'
            mwbsd['sha'] = '?'
            mwbsd['sha2'] = '?'
            mwbsd['regsha'] = (mwbsd['special_value'] * self.torsion**2) / (
                mwbsd['tamagawa_product'] * mwbsd['real_period'])
            if r <= 1:
                mwbsd['rank'] = r

        # Integral points

        xintcoords = mwbsd['xcoord_integral_points']
        a1, _, a3, _, _ = ainvs = self.ainvs
        if a1 or a3:
            int_pts = sum([[(x, y) for y in make_y_coords(ainvs, x)]
                           for x in xintcoords], [])
            mwbsd['int_points'] = raw_typeset(
                ', '.join(str(P) for P in int_pts),
                ', '.join(web_latex(P) for P in int_pts))
        else:
            int_pts = [(x, make_y_coords(ainvs, x)[0]) for x in xintcoords]
            raw_form = sum([[P, (P[0], -P[1])] if P[1] else [P]
                            for P in int_pts], [])
            raw_form = ', '.join(str(P) for P in raw_form)
            mwbsd['int_points'] = raw_typeset(
                raw_form, ', '.join(pm_pt(P) for P in int_pts))

        # Generators (mod torsion) and heights:
        mwbsd['generators'] = [
            raw_typeset(weighted_proj_to_affine_point(P))
            for P in mwbsd['gens']
        ] if mwbsd['ngens'] else ''

        # Torsion structure and generators:
        if mwbsd['torsion'] == 1:
            mwbsd['tor_struct'] = ''
            mwbsd['tor_gens'] = ''
        else:
            mwbsd['tor_struct'] = r' \times '.join(
                r'\Z/{%s}\Z' % n for n in self.torsion_structure)
            tor_gens_tmp = [
                weighted_proj_to_affine_point(P)
                for P in mwbsd['torsion_generators']
            ]
            mwbsd['tor_gens'] = raw_typeset(
                ', '.join(str(P) for P in tor_gens_tmp),
                ', '.join(web_latex(P) for P in tor_gens_tmp))

        # BSD invariants
        if r >= 2:
            mwbsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r, r)
        elif r:
            mwbsd['lder_name'] = "L'(E,1)"
        else:
            mwbsd['lder_name'] = "L(E,1)"
Example #8
0
    def make_curve(self):
        data = self.data = {}
        lmfdb_label = self.lmfdb_label

        # Some data fields of self are just those from the database.
        # These only need some reformatting.

        data['ainvs'] = self.ainvs
        data['conductor'] = N = self.conductor
        data['j_invariant'] = QQ(tuple(self.jinv))
        data['j_inv_factor'] = latex(0)
        if data['j_invariant']:  # don't factor 0
            data['j_inv_factor'] = latex(data['j_invariant'].factor())
        data['j_inv_latex'] = web_latex(data['j_invariant'])

        # retrieve local reduction data from table ec_localdata:

        self.local_data = local_data = list(
            db.ec_localdata.search({"lmfdb_label": lmfdb_label}))
        for ld in local_data:
            if ld['kodaira_symbol'] <= -14:
                # Work around bug in Sage's latex
                ld['kod'] = 'I_{%s}^{*}' % (-ld['kodaira_symbol'] - 4)
            else:
                ld['kod'] = latex(KodairaSymbol(ld['kodaira_symbol']))

        Nfac = Factorization([(ZZ(ld['prime']), ld['conductor_valuation'])
                              for ld in local_data])
        Dfac = Factorization([(ZZ(ld['prime']), ld['discriminant_valuation'])
                              for ld in local_data],
                             unit=ZZ(self.signD))
        data['disc_factor'] = latex(Dfac)
        data['disc'] = D = Dfac.value()
        data['cond_factor'] = latex(Nfac)
        data['disc_latex'] = web_latex(D)
        data['cond_latex'] = web_latex(N)

        # retrieve data about MW rank, generators, heights and
        # torsion, leading term of L-function & other BSD data from
        # table ec_mwbsd:

        self.make_mwbsd()

        # latex equation:

        latexeqn = latex_equation(self.ainvs)
        data['equation'] = raw_typeset(unlatex(latexeqn), latexeqn)

        # minimal quadratic twist:

        data['minq_D'] = minqD = self.min_quad_twist_disc
        data['minq_label'] = db.ec_curvedata.lucky(
            {'ainvs': self.min_quad_twist_ainvs},
            projection='lmfdb_label'
            if self.label_type == 'LMFDB' else 'Clabel')
        data['minq_info'] = '(itself)' if minqD == 1 else '(by {})'.format(
            minqD)

        # modular degree:

        try:
            data['degree'] = ZZ(self.degree)  # convert None to 0
        except AttributeError:  # if not computed, db has Null and the attribute is missing
            data['degree'] = 0  # invalid, but will be displayed nicely

        # coefficients of modular form / L-series:

        classdata = db.ec_classdata.lookup(self.lmfdb_iso)
        data['an'] = classdata['anlist']
        data['ap'] = classdata['aplist']

        # mod-p Galois images:

        data['galois_data'] = list(
            db.ec_galrep.search({'lmfdb_label': lmfdb_label}))
        for gd in data[
                'galois_data']:  # remove the prime prefix from each image code
            gd['image'] = trim_galois_image_code(gd['image'])

        # CM and Endo ring:

        data['CMD'] = self.cm
        data['CM'] = "no"
        data['EndE'] = r"\(\Z\)"
        if self.cm:
            data['cm_ramp'] = [
                p for p in ZZ(self.cm).support() if not p in self.nonmax_primes
            ]
            data['cm_nramp'] = len(data['cm_ramp'])
            if data['cm_nramp'] == 1:
                data['cm_ramp'] = data['cm_ramp'][0]
            else:
                data['cm_ramp'] = ", ".join(str(p) for p in data['cm_ramp'])
            data['cm_sqf'] = ZZ(self.cm).squarefree_part()

            data['CM'] = r"yes (\(D=%s\))" % data['CMD']
            if data['CMD'] % 4 == 0:
                d4 = ZZ(data['CMD']) // 4
                data['EndE'] = r"\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = r"\(\Z[(1+\sqrt{%s})/2]\)" % data['CMD']
            data['ST'] = st_link_by_name(1, 2, 'N(U(1))')
        else:
            data['ST'] = st_link_by_name(1, 2, 'SU(2)')

        # Isogeny degrees:

        cond, iso, num = split_lmfdb_label(lmfdb_label)
        self.class_deg = classdata['class_deg']
        self.one_deg = ZZ(self.class_deg).is_prime()
        isodegs = [str(d) for d in self.isogeny_degrees if d > 1]
        if len(isodegs) < 3:
            data['isogeny_degrees'] = " and ".join(isodegs)
        else:
            data['isogeny_degrees'] = " and ".join(
                [", ".join(isodegs[:-1]), isodegs[-1]])

        self.make_twoadic_data()

        # Optimality

        # The optimal curve in the class is the curve whose Cremona
        # label ends in '1' except for '990h' which was labelled
        # wrongly long ago. This is proved for N up to
        # OPTIMALITY_BOUND (and when there is only one curve in an
        # isogeny class, obviously) and expected for all N.

        # Column 'optimality' is 1 for certainly optimal curves, 0 for
        # certainly non-optimal curves, and is n>1 if the curve is one
        # of n in the isogeny class which may be optimal given current
        # knowledge.

        # Column "manin_constant' is the correct Manin constant
        # assuming that the optimal curve in the class is known, or
        # otherwise if it is the curve with (Cremona) number 1.

        # The code here allows us to update the display correctly by
        # changing one line in this file (defining OPTIMALITY_BOUND)
        # without changing the data.

        data['optimality_bound'] = OPTIMALITY_BOUND
        self.cremona_bound = CREMONA_BOUND
        if N < CREMONA_BOUND:
            data[
                'manin_constant'] = self.manin_constant  # (conditional on data['optimality_known'])
        else:
            data['manin_constant'] = 0  # (meaning not available)

        if N < OPTIMALITY_BOUND:

            data['optimality_code'] = int(
                self.Cnumber == (3 if self.Ciso == '990h' else 1))
            data['optimality_known'] = True
            data['manin_known'] = True
            if self.label_type == 'Cremona':
                data[
                    'optimal_label'] = '990h3' if self.Ciso == '990h' else self.Ciso + '1'
            else:
                data[
                    'optimal_label'] = '990.i3' if self.lmfdb_iso == '990.i' else self.lmfdb_iso + '1'

        elif N < CREMONA_BOUND:

            data['optimality_code'] = self.optimality
            data['optimality_known'] = (self.optimality < 2)

            if self.optimality == 1:
                data['manin_known'] = True
                data[
                    'optimal_label'] = self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label
            else:
                if self.Cnumber == 1:
                    data['manin_known'] = False
                    data[
                        'optimal_label'] = self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label
                else:
                    # find curve #1 in this class and its optimailty code:
                    opt_curve = db.ec_curvedata.lucky(
                        {
                            'Ciso': self.Ciso,
                            'Cnumber': 1
                        },
                        projection=['Clabel', 'lmfdb_label', 'optimality'])
                    data['manin_known'] = (opt_curve['optimality'] == 1)
                    data['optimal_label'] = opt_curve[
                        'Clabel' if self.label_type ==
                        'Cremona' else 'lmfdb_label']

        else:
            data['optimality_code'] = None
            data['optimality_known'] = False
            data['manin_known'] = False
            data['optimal_label'] = ''

        # p-adic data:

        data['p_adic_primes'] = [
            p for i, p in enumerate(prime_range(5, 100))
            if (N * data['ap'][i]) % p != 0
        ]

        data['p_adic_data_exists'] = False
        if data['optimality_code'] == 1:
            data['p_adic_data_exists'] = db.ec_padic.exists(
                {'lmfdb_iso': self.lmfdb_iso})

        # Iwasawa data (where present)

        self.make_iwasawa()

        # Torsion growth data (where present)

        self.make_torsion_growth()

        # Newform

        rawnewform = str(PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True))
        data['newform'] = raw_typeset(
            rawnewform,
            web_latex(PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True)))
        data['newform_label'] = self.newform_label = ".".join(
            [str(cond), str(2), 'a', iso])
        self.newform_link = url_for("cmf.by_url_newform_label",
                                    level=cond,
                                    weight=2,
                                    char_orbit_label='a',
                                    hecke_orbit=iso)
        self.newform_exists_in_db = db.mf_newforms.label_exists(
            self.newform_label)
        self._code = None

        if self.label_type == 'Cremona':
            self.class_url = url_for(".by_ec_label", label=self.Ciso)
            self.class_name = self.Ciso
        else:
            self.class_url = url_for(".by_ec_label", label=self.lmfdb_iso)
            self.class_name = self.lmfdb_iso
        data['class_name'] = self.class_name
        data['Cnumber'] = self.Cnumber if N < CREMONA_BOUND else None

        self.friends = [('Isogeny class ' + self.class_name, self.class_url),
                        ('Minimal quadratic twist %s %s' %
                         (data['minq_info'], data['minq_label']),
                         url_for(".by_ec_label", label=data['minq_label'])),
                        ('All twists ',
                         url_for(".rational_elliptic_curves",
                                 jinv=data['j_invariant']))]

        lfun_url = url_for("l_functions.l_function_ec_page",
                           conductor_label=N,
                           isogeny_class_label=iso)
        origin_url = lfun_url.lstrip('/L/').rstrip('/')

        if db.lfunc_instances.exists({'url': origin_url}):
            self.friends += [('L-function', lfun_url)]
        else:
            self.friends += [('L-function not available', "")]

        if not self.cm:
            if N <= 300:
                self.friends += [('Symmetric square L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='2',
                                          conductor=N,
                                          isogeny=iso))]
            if N <= 50:
                self.friends += [('Symmetric cube L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='3',
                                          conductor=N,
                                          isogeny=iso))]
        if self.newform_exists_in_db:
            self.friends += [('Modular form ' + self.newform_label,
                              self.newform_link)]

        self.downloads = [('q-expansion to text',
                           url_for(".download_EC_qexp",
                                   label=self.lmfdb_label,
                                   limit=1000)),
                          ('All stored data to text',
                           url_for(".download_EC_all",
                                   label=self.lmfdb_label)),
                          ('Code to Magma',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='magma')),
                          ('Code to SageMath',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='sage')),
                          ('Code to GP',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='gp'))]

        try:
            self.plot = encode_plot(self.E.plot())
        except AttributeError:
            self.plot = encode_plot(EllipticCurve(data['ainvs']).plot())

        self.plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format(
            self.plot)
        self.properties = [
            ('Label', self.Clabel
             if self.label_type == 'Cremona' else self.lmfdb_label),
            (None, self.plot_link),
            ('Conductor', prop_int_pretty(data['conductor'])),
            ('Discriminant', prop_int_pretty(data['disc'])),
            ('j-invariant', '%s' % data['j_inv_latex']),
            ('CM', '%s' % data['CM']),
            ('Rank', 'unknown' if self.mwbsd['rank'] == '?' else
             prop_int_pretty(self.mwbsd['rank'])),
            ('Torsion structure', (r'\(%s\)' % self.mwbsd['tor_struct'])
             if self.mwbsd['tor_struct'] else 'trivial'),
        ]

        if self.label_type == 'Cremona':
            self.title = "Elliptic curve with Cremona label {} (LMFDB label {})".format(
                self.Clabel, self.lmfdb_label)
        elif N < CREMONA_BOUND:
            self.title = "Elliptic curve with LMFDB label {} (Cremona label {})".format(
                self.lmfdb_label, self.Clabel)
        else:
            self.title = "Elliptic curve with LMFDB label {}".format(
                self.lmfdb_label)

        self.bread = [('Elliptic curves', url_for("ecnf.index")),
                      (r'$\Q$', url_for(".rational_elliptic_curves")),
                      ('%s' % N, url_for(".by_conductor", conductor=N)),
                      ('%s' % iso,
                       url_for(".by_double_iso_label",
                               conductor=N,
                               iso_label=iso)), ('%s' % num, ' ')]
Example #9
0
def render_field_webpage(args):
    data = None
    info = {}
    bread = bread_prefix()

    # This function should not be called unless label is set.
    label = clean_input(args['label'])
    nf = WebNumberField(label)
    data = {}
    if nf.is_null():
        if re.match(r'^\d+\.\d+\.\d+\.\d+$', label):
            flash_error("Number field %s was not found in the database.",
                        label)
        else:
            flash_error("%s is not a valid label for a number field.", label)
        return redirect(url_for(".number_field_render_webpage"))

    info['wnf'] = nf
    data['degree'] = nf.degree()
    data['class_number'] = nf.class_number_latex()
    ram_primes = nf.ramified_primes()
    t = nf.galois_t()
    n = nf.degree()
    data['is_galois'] = nf.is_galois()
    data['autstring'] = r'\Gal' if data['is_galois'] else r'\Aut'
    data['is_abelian'] = nf.is_abelian()
    if nf.is_abelian():
        conductor = nf.conductor()
        data['conductor'] = conductor
        dirichlet_chars = nf.dirichlet_group()
        if dirichlet_chars:
            data['dirichlet_group'] = [
                r'<a href = "%s">$\chi_{%s}(%s,&middot;)$</a>' %
                (url_for('characters.render_Dirichletwebpage',
                         modulus=data['conductor'],
                         number=j), data['conductor'], j)
                for j in dirichlet_chars
            ]
            if len(data['dirichlet_group']) == 1:
                data[
                    'dirichlet_group'] = r'<span style="white-space:nowrap">$\lbrace$' + data[
                        'dirichlet_group'][0] + r'$\rbrace$</span>'
            else:
                data['dirichlet_group'] = r'$\lbrace$' + ', '.join(
                    data['dirichlet_group']
                    [:-1]) + ', <span style="white-space:nowrap">' + data[
                        'dirichlet_group'][-1] + r'$\rbrace$</span>'
        if data['conductor'].is_prime() or data['conductor'] == 1:
            data['conductor'] = r"\(%s\)" % str(data['conductor'])
        else:
            factored_conductor = factor_base_factor(data['conductor'],
                                                    ram_primes)
            factored_conductor = factor_base_factorization_latex(
                factored_conductor)
            data['conductor'] = r"\(%s=%s\)" % (str(
                data['conductor']), factored_conductor)
    data['galois_group'] = group_pretty_and_nTj(n, t, True)
    data['auts'] = db.gps_transitive.lookup(r'{}T{}'.format(n, t))['auts']
    data['cclasses'] = cclasses_display_knowl(n, t)
    data['character_table'] = character_table_display_knowl(n, t)
    data['class_group'] = nf.class_group()
    data['class_group_invs'] = nf.class_group_invariants()
    data['signature'] = nf.signature()
    data['coefficients'] = nf.coeffs()
    nf.make_code_snippets()
    D = nf.disc()
    data['disc_factor'] = nf.disc_factored_latex()
    if D.abs().is_prime() or D == 1:
        data['discriminant'] = bigint_knowl(D, cutoff=60, sides=3)
    else:
        data['discriminant'] = bigint_knowl(
            D, cutoff=60,
            sides=3) + r"\(\medspace = %s\)" % data['disc_factor']
    if nf.frobs():
        data['frob_data'], data['seeram'] = see_frobs(nf.frobs())
    else:  # fallback in case we haven't computed them in a case
        data['frob_data'], data['seeram'] = frobs(nf)
    # This could put commas in the rd, we don't want to trigger spaces
    data['rd'] = ('$%s$' % fixed_prec(nf.rd(), 2)).replace(',', '{,}')
    # Bad prime information
    npr = len(ram_primes)
    ramified_algebras_data = nf.ramified_algebras_data()
    if isinstance(ramified_algebras_data, str):
        loc_alg = ''
    else:
        # [label, latex, e, f, c, gal]
        loc_alg = ''
        for j in range(npr):
            if ramified_algebras_data[j] is None:
                loc_alg += '<tr><td>%s<td colspan="7">Data not computed' % str(
                    ram_primes[j]).rstrip('L')
            else:
                from lmfdb.local_fields.main import show_slope_content
                mydat = ramified_algebras_data[j]
                p = ram_primes[j]
                loc_alg += '<tr><td rowspan="%d">$%s$</td>' % (len(mydat),
                                                               str(p))
                mm = mydat[0]
                myurl = url_for('local_fields.by_label', label=mm[0])
                lab = mm[0]
                if mm[3] * mm[2] == 1:
                    lab = r'$\Q_{%s}$' % str(p)
                loc_alg += '<td><a href="%s">%s</a><td>$%s$<td>$%d$<td>$%d$<td>$%d$<td>%s<td>$%s$' % (
                    myurl, lab, mm[1], mm[2], mm[3], mm[4], mm[5],
                    show_slope_content(mm[8], mm[6], mm[7]))
                for mm in mydat[1:]:
                    lab = mm[0]
                    myurl = url_for('local_fields.by_label', label=lab)
                    if mm[3] * mm[2] == 1:
                        lab = r'$\Q_{%s}$' % str(p)
                    loc_alg += '<tr><td><a href="%s">%s</a><td>$%s$<td>$%d$<td>$%d$<td>$%d$<td>%s<td>$%s$' % (
                        myurl, lab, mm[1], mm[2], mm[3], mm[4], mm[5],
                        show_slope_content(mm[8], mm[6], mm[7]))
        loc_alg += '</tbody></table>'

    ram_primes = str(ram_primes)[1:-1]
    # Get rid of python L for big numbers
    ram_primes = ram_primes.replace('L', '')
    if not ram_primes:
        ram_primes = r'\textrm{None}'
    data['phrase'] = group_phrase(n, t)
    zkraw = nf.zk()
    Ra = PolynomialRing(QQ, 'a')
    zk = [latex(Ra(x)) for x in zkraw]
    zk = ['$%s$' % x for x in zk]
    zk = ', '.join(zk)
    zkraw = ', '.join(zkraw)
    grh_label = '<small>(<a title="assuming GRH" knowl="nf.assuming_grh">assuming GRH</a>)</small>' if nf.used_grh(
    ) else ''
    # Short version for properties
    grh_lab = nf.short_grh_string()
    if 'computed' in str(data['class_number']):
        grh_lab = ''
        grh_label = ''
    pretty_label = field_pretty(label)
    if label != pretty_label:
        pretty_label = "%s: %s" % (label, pretty_label)

    info.update(data)
    rootof1raw = unlatex(nf.root_of_1_gen())
    rootofunity = raw_typeset(rootof1raw,
                              nf.root_of_1_gen(),
                              extra='&nbsp;(order ${}$)'.format(
                                  nf.root_of_1_order()))
    safe_units = nf.units_safe()
    if 'too long' in safe_units:
        myunits = safe_units
    else:
        myunits = raw_typeset(unlatex(safe_units), safe_units)

    info.update({
        'label': pretty_label,
        'label_raw': label,
        'polynomial': raw_typeset(nf.poly()),
        'ram_primes': ram_primes,
        'integral_basis': raw_typeset(zkraw, zk),
        'regulator': web_latex(nf.regulator()),
        'unit_rank': nf.unit_rank(),
        'root_of_unity': rootofunity,
        'fund_units': myunits,
        'cnf': nf.cnf(),
        'grh_label': grh_label,
        'loc_alg': loc_alg
    })

    bread.append(('%s' % nf_label_pretty(info['label_raw']), ' '))
    info['downloads_visible'] = True
    info['downloads'] = [('worksheet', '/')]
    info['friends'] = []
    if nf.can_class_number():
        # hide ones that take a long time to compute on the fly
        # note that the first degree 4 number field missed the zero of the zeta function
        if abs(D**n) < 50000000:
            info['friends'].append(('L-function', "/L/NumberField/%s" % label))
    info['friends'].append(('Galois group', "/GaloisGroup/%dT%d" % (n, t)))
    if 'dirichlet_group' in info:
        info['friends'].append(('Dirichlet character group',
                                url_for("characters.dirichlet_group_table",
                                        modulus=int(conductor),
                                        char_number_list=','.join(
                                            str(a) for a in dirichlet_chars),
                                        poly=info['polynomial'])))
    resinfo = []
    galois_closure = nf.galois_closure()
    if galois_closure[0] > 0:
        if galois_closure[1]:
            resinfo.append(('gc', galois_closure[1]))
            if galois_closure[2]:
                info['friends'].append(('Galois closure',
                                        url_for(".by_label",
                                                label=galois_closure[2][0])))
        else:
            resinfo.append(('gc', [dnc]))

    sextic_twins = nf.sextic_twin()
    if sextic_twins[0] > 0:
        if sextic_twins[1]:
            resinfo.append(('sex', r' $\times$ '.join(sextic_twins[1])))
        else:
            resinfo.append(('sex', dnc))

    siblings = nf.siblings()
    # [degsib list, label list]
    # first is list of [deg, num expected, list of knowls]
    if siblings[0]:
        for sibdeg in siblings[0]:
            if not sibdeg[2]:
                sibdeg[2] = dnc
            else:
                nsibs = len(sibdeg[2])
                sibdeg[2] = ', '.join(sibdeg[2])
                if nsibs < sibdeg[1]:
                    sibdeg[2] += ', some ' + dnc

        resinfo.append(('sib', siblings[0]))
        for lab in siblings[1]:
            if lab:
                labparts = lab.split('.')
                info['friends'].append(("Degree %s sibling" % labparts[0],
                                        url_for(".by_label", label=lab)))

    arith_equiv = nf.arith_equiv()
    if arith_equiv[0] > 0:
        if arith_equiv[1]:
            resinfo.append(
                ('ae', ', '.join(arith_equiv[1]), len(arith_equiv[1])))
            for aelab in arith_equiv[2]:
                info['friends'].append(('Arithmetically equivalent sibling',
                                        url_for(".by_label", label=aelab)))
        else:
            resinfo.append(('ae', dnc, len(arith_equiv[1])))

    info['resinfo'] = resinfo
    learnmore = learnmore_list()
    title = "Number field %s" % info['label']

    if npr == 1:
        primes = 'prime'
    else:
        primes = 'primes'
    if len(ram_primes) > 30:
        ram_primes = 'see page'
    else:
        ram_primes = '$%s$' % ram_primes

    properties = [('Label', nf_label_pretty(label)),
                  ('Degree', prop_int_pretty(data['degree'])),
                  ('Signature', '$%s$' % data['signature']),
                  ('Discriminant', prop_int_pretty(D)),
                  ('Root discriminant', '%s' % data['rd']),
                  ('Ramified ' + primes + '', ram_primes),
                  ('Class number', '%s %s' % (data['class_number'], grh_lab)),
                  ('Class group',
                   '%s %s' % (data['class_group_invs'], grh_lab)),
                  ('Galois group', group_pretty_and_nTj(data['degree'], t))]
    downloads = [('Stored data to gp',
                  url_for('.nf_download', nf=label, download_type='data'))]
    for lang in [["Magma", "magma"], ["SageMath", "sage"], ["Pari/GP", "gp"]]:
        downloads.append(('Download {} code'.format(lang[0]),
                          url_for(".nf_download",
                                  nf=label,
                                  download_type=lang[1])))
    from lmfdb.artin_representations.math_classes import NumberFieldGaloisGroup
    from lmfdb.artin_representations.math_classes import artin_label_pretty
    try:
        info["tim_number_field"] = NumberFieldGaloisGroup(nf._data['coeffs'])
        arts = [
            z.label()
            for z in info["tim_number_field"].artin_representations()
        ]
        #print arts
        for ar in arts:
            info['friends'].append((
                'Artin representation ' + artin_label_pretty(ar),
                url_for(
                    "artin_representations.render_artin_representation_webpage",
                    label=ar)))
        v = nf.factor_perm_repn(info["tim_number_field"])

        def dopow(m):
            if m == 0:
                return ''
            if m == 1:
                return '*'
            return '*<sup>%d</sup>' % m

        info["mydecomp"] = [dopow(x) for x in v]
    except AttributeError:
        pass
    return render_template("nf-show-field.html",
                           properties=properties,
                           title=title,
                           bread=bread,
                           code=nf.code,
                           friends=info.pop('friends'),
                           downloads=downloads,
                           learnmore=learnmore,
                           info=info,
                           formatfield=formatfield,
                           KNOWL_ID="nf.%s" % label)
Example #10
0
def ez_raw_typeset(rawpol):
    return raw_typeset(rawpol)
Example #11
0
    def make_class(self):
        # Extract the size of the isogeny class from the database
        classdata = db.ec_classdata.lucky({'lmfdb_iso': self.lmfdb_iso})
        self.class_size = ncurves = classdata['class_size']

        # Create a list of the curves in the class from the database
        number_key = 'Cnumber' if self.label_type == 'Cremona' else 'lmfdb_number'
        self.curves = [
            db.ec_curvedata.lucky({
                'lmfdb_iso': self.lmfdb_iso,
                number_key: i + 1
            }) for i in range(ncurves)
        ]

        # Set optimality flags.  The optimal curve is conditionally
        # number 1 except in one case which is labeled differently in
        # the Cremona tables.  We know which curve is optimal iff the
        # optimality code for curve #1 is 1 (except for class 990h).

        # Note that self is actually an elliptic curve, with number=1.

        # The code here allows us to update the display correctly by
        # changing one line in this file (defining OPTIMALITY_BOUND)
        # without changing the data.

        self.cremona_bound = CREMONA_BOUND
        self.optimality_bound = OPTIMALITY_BOUND
        self.optimality_known = (self.conductor < OPTIMALITY_BOUND) or (
            (self.conductor < CREMONA_BOUND) and ((self.optimality == 1) or
                                                  (self.Ciso == '990h')))
        self.optimal_label = self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label

        if self.conductor < OPTIMALITY_BOUND:
            for c in self.curves:
                c['optimal'] = (c['Cnumber'] == (3 if self.Ciso == '990h' else
                                                 1))
                c['optimality_known'] = True
        elif self.conductor < CREMONA_BOUND:
            for c in self.curves:
                c['optimal'] = (c['optimality'] > 0
                                )  # this curve possibly optimal
                c['optimality_known'] = (c['optimality'] == 1
                                         )  # this curve certainly optimal
        else:
            for c in self.curves:
                c['optimal'] = None
                c['optimality_known'] = False

        for c in self.curves:
            c['ai'] = c['ainvs']
            c['curve_url_lmfdb'] = url_for(".by_triple_label",
                                           conductor=self.conductor,
                                           iso_label=self.iso_label,
                                           number=c['lmfdb_number'])
            c['curve_url_cremona'] = url_for(
                ".by_ec_label",
                label=c['Clabel']) if self.conductor < CREMONA_BOUND else "N/A"
            if self.label_type == 'Cremona':
                c['curve_label'] = c['Clabel']
                _, c_iso, c_number = split_cremona_label(c['Clabel'])
            else:
                c['curve_label'] = c['lmfdb_label']
                _, c_iso, c_number = split_lmfdb_label(c['lmfdb_label'])
            c['short_label'] = "{}{}".format(c_iso, c_number)

        from sage.matrix.all import Matrix
        M = classdata['isogeny_matrix']

        # permute rows/cols to match labelling: the rows/cols in the
        # ec_classdata table are with respect to LMFDB ordering.
        if self.label_type == 'Cremona':
            perm = lambda i: next(c for c in self.curves
                                  if c['Cnumber'] == i + 1)['lmfdb_number'] - 1
            M = [[M[perm(i)][perm(j)] for i in range(ncurves)]
                 for j in range(ncurves)]

        M = Matrix(M)

        self.isogeny_matrix_str = latex(M)

        # Create isogeny graph with appropriate vertex labels:

        self.graph = make_graph(M, [c['short_label'] for c in self.curves])
        P = self.graph.plot(edge_labels=True, vertex_size=1000)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img

        self.newform = raw_typeset(
            PowerSeriesRing(QQ, 'q')(classdata['anlist'], 20, check=True))
        self.newform_label = ".".join(
            [str(self.conductor),
             str(2), 'a', self.iso_label])
        self.newform_exists_in_db = db.mf_newforms.label_exists(
            self.newform_label)
        if self.newform_exists_in_db:
            char_orbit, hecke_orbit = self.newform_label.split('.')[2:]
            self.newform_link = url_for("cmf.by_url_newform_label",
                                        level=self.conductor,
                                        weight=2,
                                        char_orbit_label=char_orbit,
                                        hecke_orbit=hecke_orbit)

        self.lfunction_link = url_for("l_functions.l_function_ec_page",
                                      conductor_label=self.conductor,
                                      isogeny_class_label=self.iso_label)

        self.friends = [('L-function', self.lfunction_link)]

        if self.cm:
            # set CM field for Properties box.
            D = ZZ(self.cm).squarefree_part()
            coeffs = [(1 - D) // 4, -1, 1] if D % 4 == 1 else [-D, 0, 1]
            lab = db.nf_fields.lucky({'coeffs': coeffs}, projection='label')
            self.CMfield = field_pretty(lab)
        else:
            self.CMfield = "no"
            if self.conductor <= 300:
                self.friends += [('Symmetric square L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='2',
                                          conductor=self.conductor,
                                          isogeny=self.iso_label))]
            if self.conductor <= 50:
                self.friends += [('Symmetric cube L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='3',
                                          conductor=self.conductor,
                                          isogeny=self.iso_label))]
        if self.newform_exists_in_db:
            self.friends += [('Modular form ' + self.newform_label,
                              self.newform_link)]

        if self.label_type == 'Cremona':
            self.title = "Elliptic curve isogeny class with Cremona label {} (LMFDB label {})".format(
                self.Ciso, self.lmfdb_iso)
        elif self.conductor < CREMONA_BOUND:
            self.title = "Elliptic curve isogeny class with LMFDB label {} (Cremona label {})".format(
                self.lmfdb_iso, self.Ciso)
        else:
            self.title = "Elliptic curve isogeny class with LMFDB label {}".format(
                self.lmfdb_iso)

        self.properties = [
            ('Label',
             self.Ciso if self.label_type == 'Cremona' else self.lmfdb_iso),
            ('Number of curves', prop_int_pretty(ncurves)),
            ('Conductor', prop_int_pretty(self.conductor)),
            ('CM', '%s' % self.CMfield), ('Rank', prop_int_pretty(self.rank))
        ]
        if ncurves > 1:
            self.properties += [('Graph', ''), (None, self.graph_link)]

        self.downloads = [('q-expansion to text',
                           url_for(".download_EC_qexp",
                                   label=self.iso_label,
                                   limit=1000)),
                          ('All stored data to text',
                           url_for(".download_EC_all", label=self.iso_label))]

        self.bread = [('Elliptic curves', url_for("ecnf.index")),
                      (r'$\Q$', url_for(".rational_elliptic_curves")),
                      ('%s' % self.conductor,
                       url_for(".by_conductor", conductor=self.conductor)),
                      ('%s' % self.iso_label, ' ')]
        self.code = {}
        self.code['show'] = {'sage': ''}  # use default show names
        self.code['class'] = {
            'sage':
            'E = EllipticCurve("%s1")\n' % (self.iso_label) +
            'E.isogeny_class()\n'
        }
        self.code['curves'] = {'sage': 'E.isogeny_class().curves'}
        self.code['rank'] = {'sage': 'E.rank()'}
        self.code['q_eigenform'] = {'sage': 'E.q_eigenform(10)'}
        self.code['matrix'] = {'sage': 'E.isogeny_class().matrix()'}
        self.code['plot'] = {
            'sage': 'E.isogeny_graph().plot(edge_labels=True)'
        }
Example #12
0
def render_field_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        data = db.lf_fields.lookup(label)
        if data is None:
            if re.match(r'^\d+\.\d+\.\d+\.\d+$', label):
                flash_error("Field %s was not found in the database.", label)
            else:
                flash_error("%s is not a valid label for a $p$-adic field.",
                            label)
            return redirect(url_for(".index"))
        title = '$p$-adic field ' + prettyname(data)
        titletag = 'p-adic field ' + prettyname(data)
        polynomial = coeff_to_poly(data['coeffs'])
        p = data['p']
        Qp = r'\Q_{%d}' % p
        e = data['e']
        f = data['f']
        cc = data['c']
        gt = int(data['galois_label'].split('T')[1])
        gn = data['n']
        the_gal = WebGaloisGroup.from_nt(gn, gt)
        isgal = ' Galois' if the_gal.order() == gn else ' not Galois'
        abelian = ' and abelian' if the_gal.is_abelian() else ''
        galphrase = 'This field is' + isgal + abelian + r' over $\Q_{%d}.$' % p
        autstring = r'\Gal' if the_gal.order() == gn else r'\Aut'
        prop2 = [
            ('Label', label),
            ('Base', r'\(%s\)' % Qp),
            ('Degree', r'\(%s\)' % data['n']),
            ('e', r'\(%s\)' % e),
            ('f', r'\(%s\)' % f),
            ('c', r'\(%s\)' % cc),
            ('Galois group', group_pretty_and_nTj(gn, gt)),
        ]
        # Look up the unram poly so we can link to it
        unramlabel = db.lf_fields.lucky({'p': p, 'n': f, 'c': 0}, projection=0)
        if unramlabel is None:
            logger.fatal("Cannot find unramified field!")
            unramfriend = ''
        else:
            unramfriend = url_for_label(unramlabel)
            unramdata = db.lf_fields.lookup(unramlabel)

        Px = PolynomialRing(QQ, 'x')
        Pt = PolynomialRing(QQ, 't')
        Ptx = PolynomialRing(Pt, 'x')
        if data['f'] == 1:
            unramp = r'$%s$' % Qp
            eisenp = Ptx(str(data['eisen']).replace('y', 'x'))
            eisenp = raw_typeset(eisenp, web_latex(eisenp))

        else:
            unramp = data['unram'].replace('t', 'x')
            unramp = raw_typeset(unramp, web_latex(Px(str(unramp))))
            unramp = prettyname(
                unramdata
            ) + ' $\\cong ' + Qp + '(t)$ where $t$ is a root of ' + unramp
            eisenp = Ptx(str(data['eisen']).replace('y', 'x'))
            eisenp = raw_typeset(str(eisenp),
                                 web_latex(eisenp),
                                 extra=r'$\ \in' + Qp + '(t)[x]$')

        rflabel = db.lf_fields.lucky(
            {
                'p': p,
                'n': {
                    '$in': [1, 2]
                },
                'rf': data['rf']
            }, projection=0)
        if rflabel is None:
            logger.fatal("Cannot find discriminant root field!")
            rffriend = ''
        else:
            rffriend = url_for_label(rflabel)
        gsm = data['gsm']
        if gsm == [0]:
            gsm = 'Not computed'
        elif gsm == [-1]:
            gsm = 'Does not exist'
        else:
            gsm = lf_formatfield(','.join(str(b) for b in gsm))

        if 'wild_gap' in data:
            wild_inertia = abstract_group_display_knowl(
                f"{data['wild_gap'][0]}.{data['wild_gap'][1]}")
        else:
            wild_inertia = 'data not computed'

        info.update({
            'polynomial':
            raw_typeset(polynomial),
            'n':
            data['n'],
            'p':
            p,
            'c':
            data['c'],
            'e':
            data['e'],
            'f':
            data['f'],
            't':
            data['t'],
            'u':
            data['u'],
            'rf':
            lf_display_knowl(rflabel, name=printquad(data['rf'], p)),
            'base':
            lf_display_knowl(str(p) + '.1.0.1', name='$%s$' % Qp),
            'hw':
            data['hw'],
            'slopes':
            show_slopes(data['slopes']),
            'gal':
            group_pretty_and_nTj(gn, gt, True),
            'gt':
            gt,
            'inertia':
            group_display_inertia(data['inertia']),
            'wild_inertia':
            wild_inertia,
            'unram':
            unramp,
            'eisen':
            eisenp,
            'gms':
            data['gms'],
            'gsm':
            gsm,
            'galphrase':
            galphrase,
            'autstring':
            autstring,
            'subfields':
            format_subfields(data['subfields'], p),
            'aut':
            data['aut'],
        })
        friends = [('Galois group', "/GaloisGroup/%dT%d" % (gn, gt))]
        if unramfriend != '':
            friends.append(('Unramified subfield', unramfriend))
        if rffriend != '':
            friends.append(('Discriminant root field', rffriend))
        if db.nf_fields.exists({'local_algs': {'$contains': label}}):
            friends.append(
                ('Number fields with this completion',
                 url_for('number_fields.number_field_render_webpage') +
                 "?completions={}".format(label)))

        bread = get_bread([(label, ' ')])
        return render_template(
            "lf-show-field.html",
            title=title,
            titletag=titletag,
            bread=bread,
            info=info,
            properties=prop2,
            friends=friends,
            learnmore=learnmore_list(),
            KNOWL_ID="lf.%s" % label,
        )
Example #13
0
 def computation_minimal_polynomial_raw_typeset(self):
     pol = coeff_to_poly(self._data["QpRts-minpoly"])
     return raw_typeset(pol)
Example #14
0
 def polynomial_raw_typeset(self):
     return raw_typeset(coeff_to_poly(self.polynomial()))