Пример #1
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, ' ')]
Пример #2
0
 def latex_kod(kod):
     return latex(
         KodairaSymbol(kod)) if kod > -14 else 'I_{%s}^{*}' % (-kod - 4)