Exemplo n.º 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'])
        data['faltings_height'] = RR(self.faltings_height)
        data['stable_faltings_height'] = RR(self.stable_faltings_height)

        # 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}))
        
        # 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 p not 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'] = integer_squarefree_part(ZZ(self.cm))

            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]])

        # 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,' ')]
Exemplo n.º 2
0
def FIELD(label):
    nf = WebNumberField(label, gen_name=special_names.get(label, 'a'))
    nf.parse_NFelt = lambda s: nf.K()([QQ(c.encode()) for c in s.split(",")])
    nf.latex_poly = web_latex(nf.poly())
    return nf
Exemplo n.º 3
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'

        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 = "\(0\)" if self.Lratio != 0 else "odd" if self.sfe == -1 else "\(\ge2\), even"

        self.properties = [('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))]

        try:
            if self.CM == '?':
                self.CM = 'not determined'
            elif self.CM == 0:
                self.CM = 'no'
            else:
                if self.CM % 4 in [2, 3]:
                    self.CM = 4 * 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 = ', 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.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:
            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', '')]
Exemplo n.º 4
0
    def make_curve(self):
        # To start with the data fields of self are just those from
        # the database.  We need to reformat these, construct the
        # actual elliptic curve E, and compute some further (easy)
        # data about it.
        #

        # Weierstrass equation

        data = self.data = {}
        data['ainvs'] = [int(ai) for ai in self.ainvs]
        self.E = EllipticCurve(data['ainvs'])
        data['equation'] = web_latex(self.E)

        # conductor, j-invariant and discriminant

        data['conductor'] = N = ZZ(self.conductor)
        bad_primes = N.prime_factors()
        try:
            data['j_invariant'] = QQ(str(self.jinv))
        except KeyError:
            data['j_invariant'] = self.E.j_invariant()
        data['j_inv_factor'] = latex(0)
        if data['j_invariant']:
            data['j_inv_factor'] = latex(data['j_invariant'].factor())
        data['j_inv_str'] = unicode(str(data['j_invariant']))
        data['j_inv_latex'] = web_latex(data['j_invariant'])
        data['disc'] = D = self.E.discriminant()
        data['disc_latex'] = web_latex(data['disc'])
        data['disc_factor'] = latex(data['disc'].factor())
        data['cond_factor'] = latex(N.factor())
        data['cond_latex'] = web_latex(N)

        # CM and endomorphism ring

        data['CMD'] = self.cm
        data['CM'] = "no"
        data['EndE'] = "\(\Z\)"
        if self.cm:
            data['CM'] = "yes (\(D=%s\))" % data['CMD']
            if data['CMD'] % 4 == 0:
                d4 = ZZ(data['CMD']) // 4
                data['EndE'] = "\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = "\(\Z[(1+\sqrt{%s})/2]\)" % data['CMD']
            data['ST'] = '<a href="%s">$%s$</a>' % (url_for(
                'st.by_label', label='1.2.N(U(1))'), 'N(\\mathrm{U}(1))')
        else:
            data['ST'] = '<a href="%s">$%s$</a>' % (url_for(
                'st.by_label', label='1.2.SU(2)'), '\\mathrm{SU}(2)')

        # modular degree

        try:
            data['degree'] = self.degree
        except AttributeError:
            try:
                data['degree'] = self.E.modular_degree()
            except RuntimeError:
                data['degree']  # invalid, but will be displayed nicely

        # Minimal quadratic twist

        E_pari = self.E.pari_curve()
        from sage.libs.pari.all import PariError
        try:
            minq, minqD = self.E.minimal_quadratic_twist()
        except PariError:  # this does occur with 164411a1
            ec.debug(
                "PariError computing minimal quadratic twist of elliptic curve %s"
                % lmfdb_label)
            minq = self.E
            minqD = 1
        data['minq_D'] = minqD
        if self.E == minq:
            data['minq_label'] = self.lmfdb_label
            data['minq_info'] = '(itself)'
        else:
            minq_ainvs = [str(c) for c in minq.ainvs()]
            data['minq_label'] = db_ec().find_one({
                'jinv':
                str(self.E.j_invariant()),
                'ainvs':
                minq_ainvs
            })['lmfdb_label']
            data['minq_info'] = '(by %s)' % minqD

        minq_N, minq_iso, minq_number = split_lmfdb_label(data['minq_label'])

        # rational and integral points

        mw = self.mw = {}

        xintpoints_projective = [self.E.lift_x(x) for x in self.xintcoords]
        xintpoints = [P.xy() for P in xintpoints_projective]
        mw['int_points'] = ', '.join(web_latex(P) for P in xintpoints)

        # Generators of infinite order

        mw['rank'] = self.rank
        try:
            self.generators = [self.E(g) for g in parse_points(self.gens)]
            mw['generators'] = [web_latex(P.xy()) for P in self.generators]
            mw['heights'] = [P.height() for P in self.generators]
        except AttributeError:
            mw['generators'] = ''
            mw['heights'] = []

        # Torsion subgroup: order, structure, generators

        mw['tor_order'] = self.torsion
        tor_struct = [int(c) for c in self.torsion_structure]
        if mw['tor_order'] == 1:
            mw['tor_struct'] = '\mathrm{Trivial}'
            mw['tor_gens'] = ''
        else:
            mw['tor_struct'] = ' \\times '.join(
                ['\Z/{%s}\Z' % n for n in tor_struct])
            mw['tor_gens'] = ', '.join(
                web_latex(self.E(g).xy())
                for g in parse_points(self.torsion_generators))

        # Images of Galois representations

        try:
            data['galois_images'] = [
                trim_galois_image_code(s) for s in self.galois_images
            ]
            data['non_surjective_primes'] = self.non_surjective_primes
        except AttributeError:
            #print "No Galois image data"
            data['galois_images'] = []
            data['non_surjective_primes'] = []

        data['galois_data'] = [{
            'p': p,
            'image': im
        } for p, im in zip(data['non_surjective_primes'],
                           data['galois_images'])]

        if self.twoadic_gens:
            from sage.matrix.all import Matrix
            data['twoadic_gen_matrices'] = ','.join(
                [latex(Matrix(2, 2, M)) for M in self.twoadic_gens])
            data[
                'twoadic_rouse_url'] = ROUSE_URL_PREFIX + self.twoadic_label + ".html"
        # Leading term of L-function & BSD data

        bsd = self.bsd = {}

        r = self.rank
        if r >= 2:
            bsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r, r)
        elif r:
            bsd['lder_name'] = "L'(E,1)"
        else:
            bsd['lder_name'] = "L(E,1)"

        bsd['reg'] = self.regulator
        bsd['omega'] = self.real_period
        bsd['sha'] = int(0.1 + self.sha_an)
        bsd['lder'] = self.special_value

        # 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)

        if self.iso == '990h':
            data['Gamma0optimal'] = bool(self.number == 3)
        else:
            data['Gamma0optimal'] = bool(self.number == 1)

        data['p_adic_data_exists'] = False
        if data['Gamma0optimal']:
            data['p_adic_data_exists'] = (padic_db().find({
                'lmfdb_iso':
                self.lmfdb_iso
            }).count()) > 0
        data['p_adic_primes'] = [
            p for p in sage.all.prime_range(5, 100)
            if self.E.is_ordinary(p) and not p.divides(N)
        ]

        # Local data

        local_data = self.local_data = []
        # if we use E.tamagawa_numbers() it calls E.local_data(p) which
        # used to crash on some curves e.g. 164411a1
        tamagawa_numbers = []
        for p in bad_primes:
            local_info = self.E.local_data(p, algorithm="generic")
            local_data_p = {}
            local_data_p['p'] = p
            local_data_p['tamagawa_number'] = local_info.tamagawa_number()
            tamagawa_numbers.append(ZZ(local_info.tamagawa_number()))
            local_data_p['kodaira_symbol'] = web_latex(
                local_info.kodaira_symbol()).replace('$', '')
            local_data_p['reduction_type'] = local_info.bad_reduction_type()
            local_data_p['ord_cond'] = local_info.conductor_valuation()
            local_data_p['ord_disc'] = local_info.discriminant_valuation()
            local_data_p['ord_den_j'] = max(0,
                                            -self.E.j_invariant().valuation(p))
            local_data.append(local_data_p)

        cp_fac = [cp.factor() for cp in tamagawa_numbers]
        cp_fac = [
            latex(cp) if len(cp) < 2 else '(' + latex(cp) + ')'
            for cp in cp_fac
        ]
        bsd['tamagawa_factors'] = r'\cdot'.join(cp_fac)
        bsd['tamagawa_product'] = sage.misc.all.prod(tamagawa_numbers)

        cond, iso, num = split_lmfdb_label(self.lmfdb_label)
        data['newform'] = web_latex(self.E.q_eigenform(10))
        self.newform_label = newform_label(cond, 2, 1, iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms",
                                    level=cond,
                                    weight=2,
                                    character=1,
                                    label=iso)
        newform_exists_in_db = is_newform_in_db(self.newform_label)
        self._code = None

        self.friends = [('Isogeny class ' + self.lmfdb_iso,
                         url_for(".by_double_iso_label",
                                 conductor=N,
                                 iso_label=iso)),
                        ('Minimal quadratic twist %s %s' %
                         (data['minq_info'], data['minq_label']),
                         url_for(".by_triple_label",
                                 conductor=minq_N,
                                 iso_label=minq_iso,
                                 number=minq_number)),
                        ('All twists ',
                         url_for(".rational_elliptic_curves", jinv=self.jinv)),
                        ('L-function',
                         url_for("l_functions.l_function_ec_page",
                                 label=self.lmfdb_label))]
        if not self.cm:
            if N <= 300:
                self.friends += [('Symmetric square L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='2',
                                          label=self.lmfdb_iso))]
            if N <= 50:
                self.friends += [('Symmetric cube L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='3',
                                          label=self.lmfdb_iso))]
        if newform_exists_in_db:
            self.friends += [('Modular form ' + self.newform_label,
                              self.newform_link)]

        self.downloads = [('Download coefficients of q-expansion',
                           url_for(".download_EC_qexp",
                                   label=self.lmfdb_label,
                                   limit=100)),
                          ('Download all stored data',
                           url_for(".download_EC_all",
                                   label=self.lmfdb_label)),
                          ('Download Magma code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='magma')),
                          ('Download Sage code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='sage')),
                          ('Download GP code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='gp'))]

        self.plot = encode_plot(self.E.plot())
        self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
        self.properties = [('Label', self.lmfdb_label), (None, self.plot_link),
                           ('Conductor', '\(%s\)' % data['conductor']),
                           ('Discriminant', '\(%s\)' % data['disc']),
                           ('j-invariant', '%s' % data['j_inv_latex']),
                           ('CM', '%s' % data['CM']),
                           ('Rank', '\(%s\)' % mw['rank']),
                           ('Torsion Structure', '\(%s\)' % mw['tor_struct'])]

        self.title = "Elliptic Curve %s (Cremona label %s)" % (
            self.lmfdb_label, self.label)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                      ('$\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, ' ')]
Exemplo n.º 5
0
def parse_rational(inp, query, qfield):
    if QQ_RE.match(inp):
        query[qfield] = str(QQ(inp))
    else:
        raise SearchParsingError("It needs to be a rational number.")
Exemplo n.º 6
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.
        #
        self.field = make_field(self.field_label)
        pretty_field = field_pretty(self.field_label)
        self.field_knowl = nf_display_knowl(self.field_label,
                                            getDBConnection(), pretty_field)
        try:
            dims = db_dims().find_one({
                'field_label': self.field_label,
                'level_label': self.level_label
            })['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)))

        if db_ecnf().find_one({'class_label': self.label}):
            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)
        else:
            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', '')]
Exemplo n.º 7
0
def cyc_to_QZ(A):
    alpha = []
    for Ai in A:
        alpha.extend([QQ(k) / Ai for k in range(1, Ai + 1) if gcd(k, Ai) == 1])
    alpha.sort()
    return alpha
Exemplo n.º 8
0
def parse_bracketed_rats(inp,
                         query,
                         qfield,
                         maxlength=None,
                         exactlength=None,
                         split=True,
                         process=None,
                         listprocess=None,
                         keepbrackets=False,
                         extractor=None):
    if (not BRACKETED_RAT_RE.match(inp)
            or (maxlength is not None and inp.count(',') > maxlength - 1)
            or (exactlength is not None and inp.count(',') != exactlength - 1)
            or (exactlength is not None and inp == '[]' and exactlength > 0)):
        if exactlength == 2:
            lstr = "pair of rational numbers"
            example = "[2,3/2] or [3,3]"
        elif exactlength == 1:
            lstr = "list of 1 rational number"
            example = "[2/5]"
        elif exactlength is not None:
            lstr = "list of %s rational numbers" % exactlength
            example = str(range(2, exactlength + 2)).replace(
                ", ", "/13,") + " or " + str([3] * exactlength).replace(
                    ", ", "/4,")
        elif maxlength is not None:
            lstr = "list of at most %s rational numbers" % maxlength
            example = str(range(2, maxlength + 2)).replace(
                ", ", "/13,") + " or " + str(
                    [2] * max(1, maxlength - 2)).replace(", ", "/41,")
        else:
            lstr = "list of rational numbers"
            example = "[1/7,2,3] or [5,6/71]"
        raise ValueError(
            "It needs to be a %s in square brackets, such as %s." %
            (lstr, example))
    else:
        if inp == '[]':  # fixes bug in the code below (split never returns an empty list)
            if split:
                query[qfield] = []
            else:
                query[qfield] = ''
            return
        L = [QQ(a) for a in inp[1:-1].split(',')]
        if process is not None:
            L = [process(a) for a in L]
        if listprocess is not None:
            L = listprocess(L)
        if extractor is not None:
            for qf, v in zip(qfield, extractor(L)):
                if qf in query and query[qf] != v:
                    raise ValueError(
                        "Inconsistent specification of %s: %s vs %s" %
                        (qf, query[qf], v))
                query[qf] = v
        elif split:
            query[qfield] = L
        else:
            inp = '[%s]' % ','.join([str(a) for a in L])
            if keepbrackets:
                inp = inp.replace("[", "['").replace("]",
                                                     "']").replace(",", "','")
                query[qfield] = inp
            else:
                query[qfield] = inp[1:-1]
Exemplo n.º 9
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_ec_label",
                                           label=c['lmfdb_label'])
            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)
            c['FH'] = RealField(20)(c['faltings_height'])
            c['j_inv'] = QQ(tuple(
                c['jinv']))  # convert [num,den] to rational for display
            c['disc'] = c['signD'] * c['absD']

        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 = integer_squarefree_part(ZZ(self.cm))
            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)'
        }
Exemplo n.º 10
0
def multicrunch(surfsums, varname=None):
    """
    Given an iterable consisting of SURFSums, compute the rational function
    given by their combined sum.
    Note that this rational function necessarily has degree <= 0.
    """

    surfsums = list(surfsums)

    #
    # Combine the various critical sets and construct a candidate denominator.
    #

    critical = set().union(*(Q._critical for Q in surfsums))
    cand = dict()
    for Q in surfsums:
        E = Q._cand
        for r in E:
            if r not in cand or cand[r] < E[r]:
                cand[r] = E[r]

    if varname is None:
        varname = 's'

    R = QQ[varname]
    s = R.gen(0)
    g = R(prod((a * s - b)**e for ((a, b), e) in cand.items()))
    m = g.degree()

    logger.info('Total number of SURFs: %d' % sum(Q._count for Q in surfsums))

    for Q in surfsums:
        Q._file.flush()

    logger.info('Combined size of data files: %s' %
         readable_filesize(sum(os.path.getsize(Q._filename) for Q in surfsums)))
    logger.info('Number of critical points: %d' % len(critical))
    logger.info('Degree of candidate denominator: %d' % m)

    #
    # Construct m + 1 non-critical points for evaluation.
    #

    values = set()
    while len(values) < m + 1:
        x = QQ.random_element()
        if x in critical:
            continue
        values.add(x)
    values = list(values)

    #
    # Set up parallel computations.
    #

    # bucket_size = ceil(float(len(values)) / common.ncpus)
    # this was unused

    dat_filenames = [Q._filename for Q in surfsums]

    res_names = []
    val_names = []

    value_batches = [values[j::common.ncpus] for j in range(common.ncpus)]

    with TemporaryDirectory() as tmpdir:
        for j, v in enumerate(value_batches):
            if not v:
                break

            val_filename = os.path.join(tmpdir, 'values%d' % j)
            val_names.append(val_filename)
            res_names.append(os.path.join(tmpdir, 'results%d' % j))
            with open(val_filename, 'w') as val_file:
                val_file.write(str(len(v)) + '\n')
                for x in v:
                    val_file.write(str(x) + '\n')

        def fun(k):
            ret = crunch(['crunch', val_names[k], res_names[k]] + dat_filenames)
            if ret == 0:
                logger.info('Cruncher #%d finished.' % k)
            return ret

        logger.info('Launching %d crunchers.' % len(res_names))

        if not common.debug:
            fun = parallel(ncpus=len(res_names))(fun)
            for (arg, ret) in fun(list(range(len(res_names)))):
                if ret == 'NO DATA':
                    raise RuntimeError('A parallel process died')
                if ret != 0:
                    raise RuntimeError('crunch failed')
        else:
            for k in range(len(res_names)):
                fun(k)
                

        #
        # Collect results
        #
        pairs = []

        for j, rn in enumerate(res_names):
            it_batch = iter(value_batches[j])
            with open(rn, 'r') as res_file:
                for line in res_file:
                    # We also need to evaluate the candidate denominator 'g'
                    # from above at the given random points.
                    x = QQ(next(it_batch))
                    pairs.append((x, g(x) * QQ(line)))

    if len(values) != len(pairs):
        raise RuntimeError('Length of results is off')

    f = R.lagrange_polynomial(list(pairs))
    res = SR(f / g)
    return res.factor() if res else res
Exemplo n.º 11
0
    def add(self, S):
        if self._file.closed:
            raise SURFError('Lost access to the SURFSum file')

        self._count += 1

        # Binary format:
        # k scalar a[0] b[0] a[1] b[1] ... a[k-1] b[k-1]

        # NOTE:
        # In rare cases, we can run into numbers that don't fit into 32-bit
        # integers. We then use an ad hoc hack to reduce to smaller numbers.
        # To trigger this, count ideals in L(6,11).

        raw = list(map(int, [len(S.rays), S.scalar]))
        for a, b in S.rays:
            try:
                _ = array('i', [int(a), int(b)])
                raw.extend([int(a), int(b)])
            except OverflowError:
                if a:
                    raise SURFError('Ray does not fit into a pair of 32-bit integers')
            else:
                continue

            fac = factor(b)
            li = flatten([[p] * e for (p, e) in fac])
            li[0] *= fac.unit()
            # assert b == prod(li)
            if len(li) % 2 == 0:
                li[0] = -li[0]
            # assert -b == prod(-c for c in li)
            for c in li:
                raw.extend([int(0), int(c)])
            raw[0] += len(li) - 1

        try:
            self._file.write(array('i', raw).tobytes())
        except OverflowError:
            raise SURFError('Number too large to fit into a 32-bit integer')

        # Update the candidate denominator.
        E = {}
        for a, b in S.rays:
            if a == 0:
                continue

            self._critical.add(QQ(b) / QQ(a))

            # Only consider a*s-b with gcd(a,b) = 1 and a > 0.
            g = int(gcd((a, b)))
            a, b = a // g, b // g

            if a < 0:
                a, b = -a, -b

            # (possible, depending on the counting problem) TODO:
            # Get rid of things like s+1 (for subobjects) that cannot show up
            # in the final result.

            if (a, b) in E:
                E[(a, b)] += 1
            else:
                E[(a, b)] = 1

        # Now 'E' gives the multiplicities of candidate terms for S.
        # We take the largest multiplicities over all 'S'.
        for r in E:
            if r not in self._cand or self._cand[r] < E[r]:
                self._cand[r] = E[r]
Exemplo n.º 12
0
    def make_object(self, curve, endo, tama, ratpts, clus, is_curve):
        from lmfdb.genus2_curves.main import url_for_curve_label

        # all information about the curve, its Jacobian, isogeny class, and endomorphisms goes in the data dictionary
        # most of the data from the database gets polished/formatted before we put it in the data dictionary
        data = self.data = {}

        data['label'] = curve['label'] if is_curve else curve['class']
        data['slabel'] = data['label'].split('.')

        # set attributes common to curves and isogeny classes here
        data['Lhash'] = str(curve['Lhash'])
        data['cond'] = ZZ(curve['cond'])
        data['cond_factor_latex'] = web_latex_factored_integer(data['cond'])
        data['analytic_rank'] = ZZ(curve['analytic_rank'])
        data['mw_rank'] = ZZ(0) if curve.get('mw_rank') is None else ZZ(curve['mw_rank']) # 0 will be marked as a lower bound
        data['mw_rank_proved'] = curve['mw_rank_proved']
        data['analytic_rank_proved'] = curve['analytic_rank_proved']
        data['hasse_weil_proved'] = curve['hasse_weil_proved']
        data['st_group'] = curve['st_group']
        data['st_group_link'] = st_link_by_name(1,4,data['st_group'])
        data['st0_group_name'] = st0_group_name(curve['real_geom_end_alg'])
        data['is_gl2_type'] = curve['is_gl2_type']
        data['root_number'] = ZZ(curve['root_number'])
        data['lfunc_url'] = url_for("l_functions.l_function_genus2_page", cond=data['slabel'][0], x=data['slabel'][1])
        data['bad_lfactors'] = literal_eval(curve['bad_lfactors'])
        data['bad_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['bad_lfactors']]
        if is_curve:
            # invariants specific to curve
            data['class'] = curve['class']
            data['abs_disc'] = ZZ(curve['abs_disc'])
            data['disc'] = curve['disc_sign'] * data['abs_disc']
            data['min_eqn'] = literal_eval(curve['eqn'])
            data['min_eqn_display'] = min_eqns_pretty(data['min_eqn'])
            data['disc_factor_latex'] = web_latex_factored_integer(data['disc'])
            data['igusa_clebsch'] = [ZZ(a) for a in literal_eval(curve['igusa_clebsch_inv'])]
            data['igusa'] = [ZZ(a) for a in literal_eval(curve['igusa_inv'])]
            data['g2'] = [QQ(a) for a in literal_eval(curve['g2_inv'])]
            data['igusa_clebsch_factor_latex'] = [web_latex_factored_integer(i) for i in data['igusa_clebsch']]
            data['igusa_factor_latex'] = [ web_latex_factored_integer(j) for j in data['igusa'] ]
            data['aut_grp'] = small_group_label_display_knowl('%d.%d' % tuple(literal_eval(curve['aut_grp_id'])))
            data['geom_aut_grp'] = small_group_label_display_knowl('%d.%d' % tuple(literal_eval(curve['geom_aut_grp_id'])))
            data['num_rat_wpts'] = ZZ(curve['num_rat_wpts'])
            data['has_square_sha'] = "square" if curve['has_square_sha'] else "twice a square"
            P = curve['non_solvable_places']
            if len(P):
                sz = "except over "
                sz += ", ".join([QpName(p) for p in P])
                last = " and"
                if len(P) > 2:
                    last = ", and"
                sz = last.join(sz.rsplit(",",1))
            else:
                sz = "everywhere"
            data['non_solvable_places'] = sz
            data['two_selmer_rank'] = ZZ(curve['two_selmer_rank'])
            data['torsion_order'] = curve['torsion_order']

            data['end_ring_base'] = endo['ring_base']
            data['end_ring_geom'] = endo['ring_geom']
            data['real_period'] = decimal_pretty(str(curve['real_period']))
            data['regulator'] = decimal_pretty(str(curve['regulator'])) if curve['regulator'] > -0.5 else 'unknown'
            if data['mw_rank'] == 0 and data['mw_rank_proved']:
                data['regulator'] = '1' # display an exact 1 when we know this

            data['tamagawa_product'] = ZZ(curve['tamagawa_product']) if curve.get('tamagawa_product') else 0
            data['analytic_sha'] = ZZ(curve['analytic_sha']) if curve.get('analytic_sha') else 0
            data['leading_coeff'] = decimal_pretty(str(curve['leading_coeff'])) if curve['leading_coeff'] else 'unknown'

            data['rat_pts'] = ratpts['rat_pts']
            data['rat_pts_v'] =  ratpts['rat_pts_v']
            data['rat_pts_table'] = ratpts_table(ratpts['rat_pts'],ratpts['rat_pts_v'])
            data['rat_pts_simple_table'] = ratpts_simpletable(ratpts['rat_pts'],ratpts['rat_pts_v'],data['min_eqn'])

            data['mw_gens_v'] = ratpts['mw_gens_v']
            lower = len([n for n in ratpts['mw_invs'] if n == 0])
            upper = data['analytic_rank']
            invs = ratpts['mw_invs'] if data['mw_gens_v'] or lower >= upper else [0 for n in range(upper-lower)] + ratpts['mw_invs']
            if len(invs) == 0:
                data['mw_group'] = 'trivial'
            else:
                data['mw_group'] = r'\(' + r' \times '.join([ (r'\Z' if n == 0 else r'\Z/{%s}\Z' % n) for n in invs]) + r'\)'
            if lower >= upper:
                data['mw_gens_table'] = mw_gens_table (ratpts['mw_invs'], ratpts['mw_gens'], ratpts['mw_heights'], ratpts['rat_pts'])
                data['mw_gens_simple_table'] = mw_gens_simple_table (ratpts['mw_invs'], ratpts['mw_gens'], ratpts['mw_heights'], ratpts['rat_pts'], data['min_eqn'])

            if curve['two_torsion_field'][0]:
                data['two_torsion_field_knowl'] = nf_display_knowl (curve['two_torsion_field'][0], field_pretty(curve['two_torsion_field'][0]))
            else:
                t = curve['two_torsion_field']
                data['two_torsion_field_knowl'] = r"splitting field of \(%s\) with Galois group %s" % (intlist_to_poly(t[1]),group_display_knowl(t[2][0],t[2][1]))

            tamalist = [[item['p'],item['tamagawa_number']] for item in tama]
            data['local_table'] = local_table (data['cond'],data['abs_disc'],tamalist,data['bad_lfactors_pretty'],clus)

        else:
            # invariants specific to isogeny class
            curves_data = list(db.g2c_curves.search({"class" : curve['class']}, ['label','eqn']))
            if not curves_data:
                raise KeyError("No curves found in database for isogeny class %s of genus 2 curve %s." %(curve['class'],curve['label']))
            data['curves'] = [ {"label" : c['label'], "equation_formatted" : min_eqn_pretty(literal_eval(c['eqn'])), "url": url_for_curve_label(c['label'])} for c in curves_data ]
            lfunc_data = db.lfunc_lfunctions.lucky({'Lhash':str(curve['Lhash'])})
            if not lfunc_data:
                raise KeyError("No Lfunction found in database for isogeny class of genus 2 curve %s." %curve['label'])
            if lfunc_data and lfunc_data.get('euler_factors'):
                data['good_lfactors'] = [[nth_prime(n+1),lfunc_data['euler_factors'][n]] for n in range(len(lfunc_data['euler_factors'])) if nth_prime(n+1) < 30 and (data['cond'] % nth_prime(n+1))]
                data['good_lfactors_pretty'] = [ (c[0], list_to_factored_poly_otherorder(c[1])) for c in data['good_lfactors']]

        # Endomorphism data over QQ:
        data['gl2_statement_base'] = gl2_statement_base(endo['factorsRR_base'], r'\(\Q\)')
        data['factorsQQ_base'] = endo['factorsQQ_base']
        data['factorsRR_base'] = endo['factorsRR_base']
        data['end_statement_base'] = (r"Endomorphism %s over \(\Q\):<br>" %("ring" if is_curve else "algebra") +
            end_statement(data['factorsQQ_base'], endo['factorsRR_base'], ring=data['end_ring_base'] if is_curve else None))

        # Field over which all endomorphisms are defined
        data['end_field_label'] = endo['fod_label']
        data['end_field_poly'] = intlist_to_poly(endo['fod_coeffs'])
        data['end_field_statement'] = end_field_statement(data['end_field_label'], data['end_field_poly'])

        # Endomorphism data over QQbar:
        data['factorsQQ_geom'] = endo['factorsQQ_geom']
        data['factorsRR_geom'] = endo['factorsRR_geom']
        if data['end_field_label'] != '1.1.1.1':
            data['gl2_statement_geom'] = gl2_statement_base(data['factorsRR_geom'], r'\(\overline{\Q}\)')
            data['end_statement_geom'] = (r"Endomorphism %s over \(\overline{\Q}\):" %("ring" if is_curve else "algebra") +
                end_statement(data['factorsQQ_geom'], data['factorsRR_geom'], field=r'\overline{\Q}', ring=data['end_ring_geom'] if is_curve else None))
        data['real_geom_end_alg_name'] = real_geom_end_alg_name(curve['real_geom_end_alg'])
        data['geom_end_alg_name'] = geom_end_alg_name(curve['geom_end_alg'])
        data['end_alg_name'] = end_alg_name(curve['end_alg'])

        # Endomorphism data over intermediate fields not already treated (only for curves, not necessarily isogeny invariant):
        if is_curve:
            data['end_lattice'] = (endo['lattice'])[1:-1]
            if data['end_lattice']:
                data['end_lattice_statement'] = end_lattice_statement(data['end_lattice'])

        # Field over which the Jacobian decomposes (base field if Jacobian is geometrically simple)
        data['is_simple_geom'] = endo['is_simple_geom']
        data['split_field_label'] = endo['spl_fod_label']
        data['split_field_poly'] = intlist_to_poly(endo['spl_fod_coeffs'])
        data['split_field_statement'] = split_field_statement(data['is_simple_geom'], data['split_field_label'], data['split_field_poly'])

        # Elliptic curve factors for non-simple Jacobians
        if not data['is_simple_geom']:
            data['split_coeffs'] = endo['spl_facs_coeffs']
            if 'spl_facs_labels' in endo and len(endo['spl_facs_labels']) == len(endo['spl_facs_coeffs']):
                data['split_labels'] = endo['spl_facs_labels']
            data['split_condnorms'] = endo['spl_facs_condnorms']
            data['split_statement'] = split_statement(data['split_coeffs'], data.get('split_labels'), data['split_condnorms'])

        # Properties
        self.properties = properties = [('Label', data['label'])]
        if is_curve:
            plot_from_db = db.g2c_plots.lucky({"label": curve['label']})
            if (plot_from_db is None):
                self.plot = encode_plot(eqn_list_to_curve_plot(data['min_eqn'], ratpts['rat_pts'] if ratpts else []))
            else:
                self.plot = plot_from_db['plot']
            plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format(self.plot)

            properties += [
                (None, plot_link),
                ('Conductor', prop_int_pretty(data['cond'])),
                ('Discriminant', prop_int_pretty(data['disc'])),
                ]
            if data['mw_rank_proved']:
                properties += [('Mordell-Weil group', data['mw_group'])]
        else:
            properties += [('Conductor', prop_int_pretty(data['cond']))]
        properties += [
            ('Sato-Tate group', data['st_group_link']),
            (r'\(\End(J_{\overline{\Q}}) \otimes \R\)', r'\(%s\)' % data['real_geom_end_alg_name']),
            (r'\(\End(J_{\overline{\Q}}) \otimes \Q\)', r'\(%s\)' % data['geom_end_alg_name']),
            (r'\(\End(J) \otimes \Q\)', r'\(%s\)' % data['end_alg_name']),
            (r'\(\overline{\Q}\)-simple', bool_pretty(data['is_simple_geom'])),
            (r'\(\mathrm{GL}_2\)-type', bool_pretty(data['is_gl2_type'])),
            ]

        # Friends
        self.friends = friends = []
        if is_curve:
            friends.append(('Genus 2 curve %s.%s' % (data['slabel'][0], data['slabel'][1]), url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1])))

        # first deal with ECs and MFs
        ecs = []
        mfs = []
        if 'split_labels' in data:
            for friend_label in data['split_labels']:
                if is_curve:
                    ecs.append(("Elliptic curve " + friend_label, url_for_ec(friend_label)))
                else:
                    ecs.append(("Elliptic curve " + ec_label_class(friend_label), url_for_ec_class(friend_label)))
                try:
                    cond, iso = ec_label_class(friend_label).split(".")
                    newform_label = ".".join([cond, str(2), 'a', iso])
                    mfs.append(("Modular form " + newform_label, url_for("cmf.by_url_newform_label", level=cond, weight=2, char_orbit_label='a', hecke_orbit=iso)))
                except ValueError:
                    # means the friend isn't an elliptic curve over Q; adding Hilbert/Bianchi modular forms
                    # is dealt with via the L-functions instances below
                    pass

        ecs.sort(key=lambda x: key_for_numerically_sort(x[0]))
        mfs.sort(key=lambda x: key_for_numerically_sort(x[0]))

        # then again EC from lfun
        instances = []
        for elt in db.lfunc_instances.search({'Lhash':data['Lhash'], 'type' : 'ECQP'}, 'url'):
            instances.extend(elt.split('|'))

        # and then the other isogeny friends
        instances.extend([
            elt['url'] for elt in
            get_instances_by_Lhash_and_trace_hash(data["Lhash"],
                                                  4,
                                                  int(data["Lhash"])
                                                  )
            ])

        exclude = {elt[1].rstrip('/').lstrip('/') for elt in self.friends
                   if elt[1]}
        exclude.add(data['lfunc_url'].lstrip('/L/').rstrip('/'))
        for elt in ecs + mfs + names_and_urls(instances, exclude=exclude):
            # because of the splitting we must use G2C specific code
            add_friend(friends, elt)
        if is_curve:
            friends.append(('Twists', url_for(".index_Q",
                                              g20=str(data['g2'][0]),
                                              g21=str(data['g2'][1]),
                                              g22=str(data['g2'][2]))))

        friends.append(('L-function', data['lfunc_url']))

        # Breadcrumbs
        self.bread = bread = [
             ('Genus 2 curves', url_for(".index")),
             (r'$\Q$', url_for(".index_Q")),
             ('%s' % data['slabel'][0], url_for(".by_conductor", cond=data['slabel'][0])),
             ('%s' % data['slabel'][1], url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1]))
             ]
        if is_curve:
            bread += [
                ('%s' % data['slabel'][2], url_for(".by_url_isogeny_class_discriminant", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2])),
                ('%s' % data['slabel'][3], url_for(".by_url_curve_label", cond=data['slabel'][0], alpha=data['slabel'][1], disc=data['slabel'][2], num=data['slabel'][3]))
                ]

        # Title
        self.title = "Genus 2 " + ("curve " if is_curve else "isogeny class ") + data['label']

        # Code snippets (only for curves)
        if not is_curve:
            return
        self.code = code = {}
        code['show'] = {'sage':'','magma':''} # use default show names
        f,h = fh = data['min_eqn']
        g = simplify_hyperelliptic(fh)
        code['curve'] = {'sage':'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s));'%(f,h),
                         'magma':'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);'%(f,h) }
        code['simple_curve'] = {'sage':'X = HyperellipticCurve(R(%s))'%(g), 'magma':'X,pi:= SimplifiedModel(C);' }
        if data['abs_disc'] % 4096 == 0:
            ind2 = [a[0] for a in data['bad_lfactors']].index(2)
            bad2 = data['bad_lfactors'][ind2][1]
            magma_cond_option = ': ExcFactors:=[*<2,Valuation('+str(data['cond'])+',2),R!'+str(bad2)+'>*]'
        else:
            magma_cond_option = ''
        code['cond'] = {'magma': 'Conductor(LSeries(C%s)); Factorization($1);'% magma_cond_option}
        code['disc'] = {'magma':'Discriminant(C); Factorization(Integers()!$1);'}
        code['geom_inv'] = {'sage':'C.igusa_clebsch_invariants(); [factor(a) for a in _]',
                            'magma':'IgusaClebschInvariants(C); IgusaInvariants(C); G2Invariants(C);'}
        code['aut'] = {'magma':'AutomorphismGroup(C); IdentifyGroup($1);'}
        code['autQbar'] = {'magma':'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);'}
        code['num_rat_wpts'] = {'magma':'#Roots(HyperellipticPolynomials(SimplifiedModel(C)));'}
        if ratpts:
            code['rat_pts'] = {'magma': '[' + ','.join(["C![%s,%s,%s]"%(p[0],p[1],p[2]) for p in ratpts['rat_pts']]) + ']; // minimal model'}
            code['rat_pts_simp'] = {'magma': '[' + ','.join(["C![%s,%s,%s]"%(p[0],p[1],p[2]) for p in [simplify_hyperelliptic_point(data['min_eqn'], pt) for pt in ratpts['rat_pts']]]) + ']; // simplified model'}
        code['mw_group'] = {'magma':'MordellWeilGroupGenus2(Jacobian(C));'}
        code['two_selmer'] = {'magma':'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);'}
        code['has_square_sha'] = {'magma':'HasSquareSha(Jacobian(C));'}
        code['locally_solvable'] = {'magma':'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsEverywhereLocally(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);'}
        code['torsion_subgroup'] = {'magma':'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);'}
def set_info_for_web_newform(level=None, weight=None, character=None, label=None, **kwds):
    r"""
    Set the info for on modular form.

    """
    info = to_dict(kwds)
    info['level'] = level
    info['weight'] = weight
    info['character'] = character
    info['label'] = label
    if level is None or weight is None or character is None or label is None:
        s = "In set info for one form but do not have enough args!"
        s += "level={0},weight={1},character={2},label={3}".format(level, weight, character, label)
        emf_logger.critical(s)
    emf_logger.debug("In set_info_for_one_mf: info={0}".format(info))
    prec = my_get(info, 'prec', default_prec, int)
    bprec = my_get(info, 'bprec', default_display_bprec, int)
    emf_logger.debug("PREC: {0}".format(prec))
    emf_logger.debug("BITPREC: {0}".format(bprec))    
    try:
        WNF = WebNewForm_cached(level=level, weight=weight, character=character, label=label)
        if not WNF.has_updated():
            raise IndexError("Unfortunately, we do not have this newform in the database.")
        info['character_order'] = WNF.character.order
        info['code'] = WNF.code
        emf_logger.debug("defined webnewform for rendering!")
    except IndexError as e:
        info['error'] = e.message
    url0 = url_for("mf.modular_form_main_page")
    url1 = url_for("emf.render_elliptic_modular_forms")
    url2 = url_for("emf.render_elliptic_modular_forms", level=level)
    url3 = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight)
    url4 = url_for("emf.render_elliptic_modular_forms", level=level, weight=weight, character=character)
    bread = [(MF_TOP, url0), (EMF_TOP, url1)]
    bread.append(("Level %s" % level, url2))
    bread.append(("Weight %s" % weight, url3))
    bread.append(("Character \( %s \)" % (WNF.character.latex_name), url4))
    bread.append(("Newform %d.%d.%d.%s" % (level, weight, int(character), label),''))
    info['bread'] = bread
    
    properties2 = list()
    friends = list()
    space_url = url_for('emf.render_elliptic_modular_forms',level=level, weight=weight, character=character)
    friends.append(('\( S_{%s}(%s, %s)\)'%(WNF.weight, WNF.level, WNF.character.latex_name), space_url))
    if hasattr(WNF.base_ring, "lmfdb_url") and WNF.base_ring.lmfdb_url:
        friends.append(('Number field ' + WNF.base_ring.lmfdb_pretty, WNF.base_ring.lmfdb_url))
    if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_label:
        friends.append(('Number field ' + WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_url))
    friends = uniq(friends)
    friends.append(("Dirichlet character \(" + WNF.character.latex_name + "\)", WNF.character.url()))
    
    if WNF.dimension==0 and not info.has_key('error'):
        info['error'] = "This space is empty!"
    info['title'] = 'Newform ' + WNF.hecke_orbit_label
    info['learnmore'] = [('History of modular forms', url_for('.holomorphic_mf_history'))]    
    if 'error' in info:
        return info
    ## Until we have figured out how to do the embeddings correctly we don't display the Satake
    ## parameters for non-trivial characters....

    ## Example to illustrate the different cases
    ## base              = CyclotomicField(n) -- of degree phi(n) 
    ## coefficient_field = NumberField( p(x)) for some p in base['x'] of degree m
    ##   we would then have cdeg = m*phi(n) and bdeg = phi(n)
    ##   and rdeg = m
    ## Unfortunately, for e.g. base = coefficient_field = CyclotomicField(6)
    ## we get coefficient_field.relative_degree() == 2 although it should be 1
    cdeg = WNF.coefficient_field.absolute_degree()
    bdeg = WNF.base_ring.absolute_degree()
    if cdeg == 1:
        rdeg = 1
    else:
        ## just setting rdeg = WNF.coefficient_field.relative_degree() does not give correct result...
        ## 
        rdeg = QQ(cdeg)/QQ(bdeg)
    cf_is_QQ = (cdeg == 1)
    br_is_QQ = (bdeg == 1)
    if cf_is_QQ:
        info['satake'] = WNF.satake
    if WNF.complexity_of_first_nonvanishing_coefficients() > default_max_height:
        info['qexp'] = ""
        info['qexp_display'] = ''
        info['hide_qexp'] = True
        n,c = WNF.first_nonvanishing_coefficient()
        info['trace_nv'] = latex(WNF.first_nonvanishing_coefficient_trace())
        info['norm_nv'] = '\\approx ' + latex(WNF.first_nonvanishing_coefficient_norm().n())
        info['index_nv'] = n
    else:
        if WNF.prec < prec:
            #get WNF record at larger prec
            WNF.prec = prec
            WNF.update_from_db()
        info['qexp'] = WNF.q_expansion_latex(prec=10, name='\\alpha ')
        info['qexp_display'] = url_for(".get_qexp_latex", level=level, weight=weight, character=character, label=label)
        info["hide_qexp"] = False
    info['max_cn_qexp'] = WNF.q_expansion.prec()
    ## All combinations should be tested...
    ## 13/4/4/a -> base ring = coefficient_field = QQ(zeta_6)
    ## 13/3/8/a ->  base_ring = QQ(zeta_4), coefficient_field has poly x^2+(2\zeta_4+2x-3\zeta_$ over base_ring
    ## 13/4/3/a ->  base_ring = coefficient_field = QQ(zeta_3) 
    ## 13/4/1/a -> all rational
    ## 13/6/1/a/ -> base_ring = QQ, coefficient_field = Q(sqrt(17))
    ## These are variables which needs to be set properly below
    info['polvars'] = {'base_ring':'x','coefficient_field':'\\alpha'}
    if not cf_is_QQ:
        if rdeg>1: # not WNF.coefficient_field == WNF.base_ring:
            ## Here WNF.base_ring should be some cyclotomic field and we have an extension over this.
            p1 = WNF.coefficient_field.relative_polynomial()
            c_pol_ltx = web_latex_poly(p1, '\\alpha')  # make the variable \alpha
            c_pol_ltx_x = web_latex_poly(p1, 'x')
            zeta = p1.base_ring().gens()[0]
#           p2 = zeta.minpoly() #this is not used anymore
#           b_pol_ltx = web_latex_poly(p2, latex(zeta)) #this is not used anymore
            z1 = zeta.multiplicative_order() 
            info['coeff_field'] = [ WNF.coefficient_field.absolute_polynomial_latex('x'),c_pol_ltx_x, z1]
            if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_url:
                info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_label]
            if z1==4:
                info['polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\) and \(\zeta_4=i\).</div><br/>'.format(c_pol_ltx)
                info['polvars']['base_ring']='i'
            elif z1<=2:
                info['polynomial_st'] = '<div class="where">where</div> {0}\(\mathstrut=0\).</div><br/>'.format(c_pol_ltx)
            else:
                info['polynomial_st'] = '<div class="where">where</div> %s\(\mathstrut=0\) and \(\zeta_{%s}=e^{\\frac{2\\pi i}{%s}}\) '%(c_pol_ltx, z1,z1)
                info['polvars']['base_ring']='\zeta_{{ {0} }}'.format(z1)
                if z1==3:
                    info['polynomial_st'] += 'is a primitive cube root of unity.'
                else:
                    info['polynomial_st'] += 'is a primitive {0}-th root of unity.'.format(z1)
        elif not br_is_QQ:
            ## Now we have base and coefficient field being equal, meaning that since the coefficient field is not QQ it is some cyclotomic field
            ## generated by some \zeta_n 
            p1 = WNF.coefficient_field.absolute_polynomial()
            z1 = WNF.coefficient_field.gens()[0].multiplicative_order()
            c_pol_ltx = web_latex_poly(p1, '\\zeta_{{{0}}}'.format(z1))
            c_pol_ltx_x = web_latex_poly(p1, 'x')
            info['coeff_field'] = [ WNF.coefficient_field.absolute_polynomial_latex('x'), c_pol_ltx_x]
            if hasattr(WNF.coefficient_field, "lmfdb_url") and WNF.coefficient_field.lmfdb_url:
                info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty, WNF.coefficient_field.lmfdb_label]
            if z1==4:
                info['polynomial_st'] = '<div class="where">where \(\zeta_4=e^{{\\frac{{\\pi i}}{{ 2 }} }}=i \).</div>'.format(c_pol_ltx)
                info['polvars']['coefficient_field']='i'
            elif z1<=2:
                info['polynomial_st'] = '' 
            else:
                info['polynomial_st'] = '<div class="where">where \(\zeta_{{{0}}}=e^{{\\frac{{2\\pi i}}{{ {0} }} }}\) '.format(z1)
                info['polvars']['coefficient_field']='\zeta_{{{0}}}'.format(z1)
                if z1==3:
                    info['polynomial_st'] += 'is a primitive cube root of unity.</div>'
                else:
                    info['polynomial_st'] += 'is a primitive {0}-th root of unity.</div>'.format(z1)
    else:
        info['polynomial_st'] = ''
    if info["hide_qexp"]:
        info['polynomial_st'] = ''
    info['degree'] = int(cdeg)
    if cdeg==1:
        info['is_rational'] = 1
        info['coeff_field_pretty'] = [ WNF.coefficient_field.lmfdb_url, WNF.coefficient_field.lmfdb_pretty ]
    else:
        info['is_rational'] = 0
    emf_logger.debug("PREC2: {0}".format(prec))
    info['embeddings'] = WNF._embeddings['values'] #q_expansion_embeddings(prec, bprec,format='latex')
    info['embeddings_len'] = len(info['embeddings'])
    properties2 = [('Level', str(level)),
                       ('Weight', str(weight)),
                       ('Character', '$' + WNF.character.latex_name + '$'),
                       ('Label', WNF.hecke_orbit_label),
                       ('Dimension of Galois orbit', str(WNF.dimension))]
    if (ZZ(level)).is_squarefree():
        info['twist_info'] = WNF.twist_info
        if isinstance(info['twist_info'], list) and len(info['twist_info'])>0:
            info['is_minimal'] = info['twist_info'][0]
            if(info['twist_info'][0]):
                s = 'Is minimal<br>'
            else:
                s = 'Is a twist of lower level<br>'
            properties2 += [('Twist info', s)]
    else:
        info['twist_info'] = 'Twist info currently not available.'
        properties2 += [('Twist info', 'not available')]
    args = list()
    for x in range(5, 200, 10):
        args.append({'digits': x})
    alev = None
    CM = WNF._cm_values
    if CM is not None:
        if CM.has_key('tau') and len(CM['tau']) != 0:
            info['CM_values'] = CM
    info['is_cm'] = WNF.is_cm
    if WNF.is_cm == 1:
        info['cm_field'] = "2.0.{0}.1".format(-WNF.cm_disc)
        info['cm_disc'] = WNF.cm_disc
        info['cm_field_knowl'] = nf_display_knowl(info['cm_field'], getDBConnection(), field_pretty(info['cm_field']))
        info['cm_field_url'] = url_for("number_fields.by_label", label=info["cm_field"])
    if WNF.is_cm is None or WNF.is_cm==-1:
        s = '- Unknown (insufficient data)<br>'
    elif WNF.is_cm == 1:
        s = 'Yes<br>'
    else:
        s = 'No<br>'
    properties2.append(('CM', s))
    alev = WNF.atkin_lehner_eigenvalues()
    info['atkinlehner'] = None
    if isinstance(alev,dict) and len(alev.keys())>0 and level != 1:
        s1 = " Atkin-Lehner eigenvalues "
        s2 = ""
        for Q in alev.keys():
            s2 += "\( \omega_{ %s } \) : %s <br>" % (Q, alev[Q])
        properties2.append((s1, s2))
        emf_logger.debug("properties={0}".format(properties2))
        # alev = WNF.atkin_lehner_eigenvalues_for_all_cusps() 
        # if isinstance(alev,dict) and len(alev.keys())>0:
        #     emf_logger.debug("alev={0}".format(alev))
        #     info['atkinlehner'] = list()
        #     for Q in alev.keys():
        #         s = "\(" + latex(c) + "\)"
        #         Q = alev[c][0]
        #         ev = alev[c][1]
        #         info['atkinlehner'].append([Q, c, ev])
    if(level == 1):
        poly = WNF.explicit_formulas.get('as_polynomial_in_E4_and_E6','')
        if poly != '':
            d,monom,coeffs = poly
            emf_logger.critical("poly={0}".format(poly))
            info['explicit_formulas'] = '\('
            for i in range(len(coeffs)):
                c = QQ(coeffs[i])
                s = ""
                if d>1 and i >0 and c>0:
                    s="+"
                if c<0:
                    s="-"
                if c.denominator()>1:
                    cc = "\\frac{{ {0} }}{{ {1} }}".format(abs(c.numerator()),c.denominator())
                else:
                    cc = str(abs(c))
                s += "{0} \cdot ".format(cc)
                a = monom[i][0]; b = monom[i][1]
                if a == 1:
                    a = ""
                if b == 1:
                    b = ""
                if a == 0 and b != 0:
                    s+="E_6^{{ {0} }}(z)".format(b)
                elif b ==0 and a != 0:
                    s+="E_4^{{ {0} }}(z)".format(a)
                else:
                    s+="E_4^{{ {0} }}(z) \cdot E_6^{{ {1} }}(z)".format(a,b)
                info['explicit_formulas'] += s
            info['explicit_formulas'] += " \)"            
    # cur_url = '?&level=' + str(level) + '&weight=' + str(weight) + '&character=' + str(character) + '&label=' + str(label) # never used
    if len(WNF.parent.hecke_orbits) > 1:
        for label_other in WNF.parent.hecke_orbits.keys():
            if(label_other != label):
                s = 'Modular form '
                if character:
                    s += newform_label(level,weight,character,label_other)
                else:
                    s += newform_label(level,weight,1,label_other)

                url = url_for('emf.render_elliptic_modular_forms', level=level,
                              weight=weight, character=character, label=label_other)
                friends.append((s, url))

    s = 'L-Function '
    if character:
        s += newform_label(level,weight,character,label)
    else:
        s += newform_label(level,weight,1,label)
    # url =
    # "/L/ModularForm/GL2/Q/holomorphic?level=%s&weight=%s&character=%s&label=%s&number=%s"
    # %(level,weight,character,label,0)
    url = '/L' + url_for(
        'emf.render_elliptic_modular_forms', level=level, weight=weight, character=character, label=label)
    if WNF.coefficient_field_degree > 1:
        for h in range(WNF.coefficient_field_degree):
            s0 = s + ".{0}".format(h)
            url0 = url + "{0}/".format(h)
            friends.append((s0, url0))
    else:
        friends.append((s, url))
    # if there is an elliptic curve over Q associated to self we also list that
    if WNF.weight == 2 and WNF.coefficient_field_degree == 1:
        llabel = str(level) + '.' + label
        s = 'Elliptic curve isogeny class ' + llabel
        url = '/EllipticCurve/Q/' + llabel
        friends.append((s, url))
    info['properties2'] = properties2
    info['friends'] = friends
    info['max_cn'] = WNF.max_available_prec()
    return info
Exemplo n.º 14
0
def I9(k, p):
    return QQ(-_sage_const_1) / (_sage_const_2**_sage_const_3 * _sage_const_3)
Exemplo n.º 15
0
 def _dimension_formula(self,k,eps=1,cuspidal=1):
     ep = 0
     N = self._N
     if (2*k) % 4 == 1: ep = 1
     if (2*k) % 4 == 3: ep = -1
     if ep==0: return 0,0
     if eps==-1:
         ep = -ep
     twok = ZZ(2*k)
     K0 = 1
     sqf = ZZ(N).divide_knowing_divisible_by(squarefree_part(N))
     if sqf>12:
         b2 = max(sqf.divisors())
     else:
         b2 = 1
     b = sqrt(b2)
     if ep==1:
         K0 = floor(QQ(b+2)/QQ(2))
     else:
         # print "b=",b
         K0 = floor(QQ(b-1)/QQ(2))
     if is_even(N):
         e2 = ep*kronecker(2,twok)/QQ(4)
     else:
         e2 = 0
     N2 = odd_part(N)
     N22 = ZZ(N).divide_knowing_divisible_by(N2)
     k3 = kronecker(3,twok)
     if gcd(3,N)>1:
         if eps==1:
             e3 = -ep*kronecker(-3,4*k+ep-1)/QQ(3)
         else:
             e3 = -1*ep*kronecker(-3,4*k+ep+1)/QQ(3)
         #e3 = -1/3*ep
     else:
         f1 = kronecker(3,2*N22)*kronecker(-12,N2) - ep
         f2 = kronecker(-3,twok+1)
         e3 = f1*f2/QQ(6)
     ID = QQ(N+ep)*(k-1)/QQ(12)
     P = 0
     for d in ZZ(4*N).divisors():
         dm4=d % 4
         if dm4== 2 or dm4 == 1:
             h = 0
         elif d == 3:
             h = QQ(1)/QQ(3)
         elif d == 4:
             h = QQ(1)/QQ(2)
         else:
             h = class_nr_pos_def_qf(-d)
         if self._verbose>1:
             print("h({0})={1}".format(d,h))
         if h!=0:
             P= P + h
     P = QQ(P)/QQ(4)
     if self._verbose>0:
         print("P={0}".format(P))
     P=P + QQ(ep)*kronecker(-4,N)/QQ(8)
     if eps==-1:
         P = -P
     if self._verbose>0:
         print("P={0}".format(P))
     # P = -2*N**2 + N*(twok+10-ep*3) +(twok+10)*ep-1
     if self._verbose>0:
         print("ID={0}".format(ID))
     P =  P - QQ(1)/QQ(2*K0)
     # P = QQ(P)/QQ(24) - K0
     # P = P - K0
     res = ID + P + e2 + e3
     if self._verbose>1:
         print("twok={0}".format(twok))
         print("K0={0}".format(K0))
         print("ep={0}".format(ep))
         print("e2={0}".format(e2))
         print("e3={0}".format(e3))
         print("P={0}".format(P))
     if cuspidal==0:
         res = res + K0
     return res   #,ep
Exemplo n.º 16
0
    def make_curve(self):
        # To start with the data fields of self are just those from
        # the database.  We need to reformat these.

        # Old version: required constructing the actual elliptic curve
        # E, and computing some further data about it.

        # New version (May 2016): extra data fields now in the
        # database so we do not have to construct the curve or do any
        # computation with it on the fly.  As a failsafe the old way
        # is still included.

        data = self.data = {}
        try:
            data['ainvs'] = [int(c) for c in self.xainvs[1:-1].split(',')]
        except AttributeError:
            data['ainvs'] = [int(ai) for ai in self.ainvs]
        data['conductor'] = N = ZZ(self.conductor)
        data['j_invariant'] = QQ(str(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_str'] = unicode(str(data['j_invariant']))
        data['j_inv_latex'] = web_latex(data['j_invariant'])
        mw = self.mw = {}
        mw['rank'] = self.rank
        mw['int_points'] = ''
        if self.xintcoords:
            a1, a2, a3, a4, a6 = [ZZ(a) for a in data['ainvs']]

            def lift_x(x):
                f = ((x + a2) * x + a4) * x + a6
                b = (a1 * x + a3)
                d = (b * b + 4 * f).sqrt()
                return (x, (-b + d) / 2)

            mw['int_points'] = ', '.join(
                web_latex(lift_x(x)) for x in self.xintcoords)

        mw['generators'] = ''
        mw['heights'] = []
        if self.gens:
            mw['generators'] = [
                web_latex(tuple(P)) for P in parse_points(self.gens)
            ]

        mw['tor_order'] = self.torsion
        tor_struct = [int(c) for c in self.torsion_structure]
        if mw['tor_order'] == 1:
            mw['tor_struct'] = '\mathrm{Trivial}'
            mw['tor_gens'] = ''
        else:
            mw['tor_struct'] = ' \\times '.join(
                ['\Z/{%s}\Z' % n for n in tor_struct])
            mw['tor_gens'] = ', '.join(
                web_latex(tuple(P))
                for P in parse_points(self.torsion_generators))

        # try to get all the data we need from the database entry (now in self)
        try:
            data['equation'] = self.equation
            local_data = self.local_data
            D = self.signD * prod(
                [ld['p']**ld['ord_disc'] for ld in local_data])
            data['disc'] = D
            Nfac = Factorization([(ZZ(ld['p']), ld['ord_cond'])
                                  for ld in local_data])
            Dfac = Factorization([(ZZ(ld['p']), ld['ord_disc'])
                                  for ld in local_data],
                                 unit=ZZ(self.signD))

            data['minq_D'] = minqD = self.min_quad_twist['disc']
            minq_label = self.min_quad_twist['label']
            data['minq_label'] = db_ec().find_one(
                {'label': minq_label}, ['lmfdb_label'])['lmfdb_label']
            data['minq_info'] = '(itself)' if minqD == 1 else '(by %s)' % minqD
            try:
                data['degree'] = self.degree
            except AttributeError:
                data['degree'] = 0  # invalid, but will be displayed nicely
            mw['heights'] = self.heights
            if self.number == 1:
                data['an'] = self.anlist
                data['ap'] = self.aplist
            else:
                r = db_ec().find_one({
                    'lmfdb_iso': self.lmfdb_iso,
                    'number': 1
                }, ['anlist', 'aplist'])
                data['an'] = r['anlist']
                data['ap'] = r['aplist']

        # otherwise fall back to computing it from the curve
        except AttributeError:
            print("Falling back to constructing E")
            self.E = EllipticCurve(data['ainvs'])
            data['equation'] = web_latex(self.E)
            data['disc'] = D = self.E.discriminant()
            Nfac = N.factor()
            Dfac = D.factor()
            bad_primes = [p for p, e in Nfac]
            try:
                data['degree'] = self.degree
            except AttributeError:
                try:
                    data['degree'] = self.E.modular_degree()
                except RuntimeError:
                    data['degree'] = 0  # invalid, but will be displayed nicely
            minq, minqD = self.E.minimal_quadratic_twist()
            data['minq_D'] = minqD
            if minqD == 1:
                data['minq_label'] = self.lmfdb_label
                data['minq_info'] = '(itself)'
            else:
                # This relies on the minimal twist being in the
                # database, which is true when the database only
                # contains the Cremona database.  It would be a good
                # idea if, when the database is extended, we ensured
                # that for any curve included, all twists of smaller
                # conductor are also included.
                minq_ainvs = [str(c) for c in minq.ainvs()]
                data['minq_label'] = db_ec().find_one(
                    {
                        'jinv': str(self.E.j_invariant()),
                        'ainvs': minq_ainvs
                    }, ['lmfdb_label'])['lmfdb_label']
                data['minq_info'] = '(by %s)' % minqD

            if self.gens:
                self.generators = [self.E(g) for g in parse_points(self.gens)]
                mw['heights'] = [P.height() for P in self.generators]

            data['an'] = self.E.anlist(20, python_ints=True)
            data['ap'] = self.E.aplist(100, python_ints=True)
            self.local_data = local_data = []
            for p in bad_primes:
                ld = self.E.local_data(p, algorithm="generic")
                local_data_p = {}
                local_data_p['p'] = p
                local_data_p['cp'] = ld.tamagawa_number()
                local_data_p['kod'] = web_latex(ld.kodaira_symbol()).replace(
                    '$', '')
                local_data_p['red'] = ld.bad_reduction_type()
                rootno = -ld.bad_reduction_type()
                if rootno == 0:
                    rootno = self.E.root_number(p)
                local_data_p['rootno'] = rootno
                local_data_p['ord_cond'] = ld.conductor_valuation()
                local_data_p['ord_disc'] = ld.discriminant_valuation()
                local_data_p['ord_den_j'] = max(
                    0, -self.E.j_invariant().valuation(p))
                local_data.append(local_data_p)

        # If we got the data from the database, the root numbers may
        # not have been stored there, so we have to compute them.  If
        # there are additive primes this means constructing the curve.
        for ld in self.local_data:
            if not 'rootno' in ld:
                rootno = -ld['red']
                if rootno == 0:
                    try:
                        E = self.E
                    except AttributeError:
                        self.E = E = EllipticCurve(data['ainvs'])
                    rootno = E.root_number(ld['p'])
                ld['rootno'] = rootno

        minq_N, minq_iso, minq_number = split_lmfdb_label(data['minq_label'])

        data['disc_factor'] = latex(Dfac)
        data['cond_factor'] = latex(Nfac)
        data['disc_latex'] = web_latex(D)
        data['cond_latex'] = web_latex(N)

        data['galois_images'] = [
            trim_galois_image_code(s) for s in self.mod_p_images
        ]
        data['non_maximal_primes'] = self.non_maximal_primes
        data['galois_data'] = [{
            'p': p,
            'image': im
        } for p, im in zip(data['non_maximal_primes'], data['galois_images'])]

        data['CMD'] = self.cm
        data['CM'] = "no"
        data['EndE'] = "\(\Z\)"
        if self.cm:
            data['cm_ramp'] = [
                p for p in ZZ(self.cm).support()
                if not p in self.non_surjective_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'] = "yes (\(D=%s\))" % data['CMD']
            if data['CMD'] % 4 == 0:
                d4 = ZZ(data['CMD']) // 4
                data['EndE'] = "\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = "\(\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)')

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

        cond, iso, num = split_lmfdb_label(self.lmfdb_label)
        self.class_url = url_for(".by_double_iso_label",
                                 conductor=N,
                                 iso_label=iso)
        self.one_deg = ZZ(self.class_deg).is_prime()
        self.ncurves = db_ec().count({'lmfdb_iso': self.lmfdb_iso})
        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]])

        if self.twoadic_gens:
            from sage.matrix.all import Matrix
            data['twoadic_gen_matrices'] = ','.join(
                [latex(Matrix(2, 2, M)) for M in self.twoadic_gens])
            data[
                'twoadic_rouse_url'] = ROUSE_URL_PREFIX + self.twoadic_label + ".html"

        # Leading term of L-function & BSD data
        bsd = self.bsd = {}
        r = self.rank
        if r >= 2:
            bsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r, r)
        elif r:
            bsd['lder_name'] = "L'(E,1)"
        else:
            bsd['lder_name'] = "L(E,1)"

        bsd['reg'] = self.regulator
        bsd['omega'] = self.real_period
        bsd['sha'] = int(0.1 + self.sha_an)
        bsd['lder'] = self.special_value

        # 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)

        if self.iso == '990h':
            data['Gamma0optimal'] = bool(self.number == 3)
        else:
            data['Gamma0optimal'] = bool(self.number == 1)

        data['p_adic_data_exists'] = False
        if data['Gamma0optimal']:
            data['p_adic_data_exists'] = (padic_db().find({
                'lmfdb_iso':
                self.lmfdb_iso
            }).count()) > 0

        data['iwdata'] = []
        try:
            pp = [int(p) for p in self.iwdata]
            badp = [l['p'] for l in self.local_data]
            rtypes = [l['red'] for l in self.local_data]
            data[
                'iw_missing_flag'] = False  # flags that there is at least one "?" in the table
            data[
                'additive_shown'] = False  # flags that there is at least one additive prime in table
            for p in sorted(pp):
                rtype = ""
                if p in badp:
                    red = rtypes[badp.index(p)]
                    # Additive primes are excluded from the table
                    # if red==0:
                    #    continue
                    #rtype = ["nsmult","add", "smult"][1+red]
                    rtype = ["nonsplit", "add", "split"][1 + red]
                p = str(p)
                pdata = self.iwdata[p]
                if isinstance(pdata, type(u'?')):
                    if not rtype:
                        rtype = "ordinary" if pdata == "o?" else "ss"
                    if rtype == "add":
                        data['iwdata'] += [[p, rtype, "-", "-"]]
                        data['additive_shown'] = True
                    else:
                        data['iwdata'] += [[p, rtype, "?", "?"]]
                        data['iw_missing_flag'] = True
                else:
                    if len(pdata) == 2:
                        if not rtype:
                            rtype = "ordinary"
                        lambdas = str(pdata[0])
                        mus = str(pdata[1])
                    else:
                        rtype = "ss"
                        lambdas = ",".join([str(pdata[0]), str(pdata[1])])
                        mus = str(pdata[2])
                        mus = ",".join([mus, mus])
                    data['iwdata'] += [[p, rtype, lambdas, mus]]
        except AttributeError:
            # For curves with no Iwasawa data
            pass

        tamagawa_numbers = [ZZ(ld['cp']) for ld in local_data]
        cp_fac = [cp.factor() for cp in tamagawa_numbers]
        cp_fac = [
            latex(cp) if len(cp) < 2 else '(' + latex(cp) + ')'
            for cp in cp_fac
        ]
        bsd['tamagawa_factors'] = r'\cdot'.join(cp_fac)
        bsd['tamagawa_product'] = prod(tamagawa_numbers)

        data['newform'] = web_latex(
            PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True))
        data['newform_label'] = self.newform_label = newform_label(
            cond, 2, 1, iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms",
                                    level=cond,
                                    weight=2,
                                    character=1,
                                    label=iso)
        self.newform_exists_in_db = is_newform_in_db(self.newform_label)
        self._code = None

        self.class_url = url_for(".by_double_iso_label",
                                 conductor=N,
                                 iso_label=iso)
        self.friends = [('Isogeny class ' + self.lmfdb_iso, self.class_url),
                        ('Minimal quadratic twist %s %s' %
                         (data['minq_info'], data['minq_label']),
                         url_for(".by_triple_label",
                                 conductor=minq_N,
                                 iso_label=minq_iso,
                                 number=minq_number)),
                        ('All twists ',
                         url_for(".rational_elliptic_curves", jinv=self.jinv)),
                        ('L-function',
                         url_for("l_functions.l_function_ec_page",
                                 conductor_label=N,
                                 isogeny_class_label=iso))]
        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 = [('Download coefficients of q-expansion',
                           url_for(".download_EC_qexp",
                                   label=self.lmfdb_label,
                                   limit=1000)),
                          ('Download all stored data',
                           url_for(".download_EC_all",
                                   label=self.lmfdb_label)),
                          ('Download Magma code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='magma')),
                          ('Download Sage code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='sage')),
                          ('Download GP code',
                           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 = '<img src="%s" width="200" height="150"/>' % self.plot
        self.properties = [('Label', self.lmfdb_label), (None, self.plot_link),
                           ('Conductor', '\(%s\)' % data['conductor']),
                           ('Discriminant', '\(%s\)' % data['disc']),
                           ('j-invariant', '%s' % data['j_inv_latex']),
                           ('CM', '%s' % data['CM']),
                           ('Rank', '\(%s\)' % mw['rank']),
                           ('Torsion Structure', '\(%s\)' % mw['tor_struct'])]

        self.title = "Elliptic Curve %s (Cremona label %s)" % (
            self.lmfdb_label, self.label)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                      ('$\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, ' ')]
Exemplo n.º 17
0
    def __init__(self,WR,weight=QQ(1)/QQ(2),use_symmetry=True,group=SL2Z,dual=False,**kwargs):
        r"""
        WR should be a Weil representation.
        INPUT:
         - weight -- weight (should be consistent with the signature of self)
         - use_symmetry -- if False we do not symmetrize the functions with respect to Z
                        -- if True we need a compatible weight
        - 'group' -- Group to act on.
        """
        if isinstance(WR,(Integer,int)):
            #self.WR=WeilRepDiscriminantForm(WR)
            #self.WR=WeilModule(WR)
            self._weil_module = WeilModule(WR)
        elif hasattr(WR,"signature"):
            self._weil_module=WR
        else:
            raise ValueError,"{0} is not a Weil module!".format(WR)
        self._sym_type = 0

        if group.level() <>1:
            raise NotImplementedError,"Only Weil representations of SL2Z implemented!"
        self._group = MySubgroup(Gamma0(1))
        self._dual = int(dual)
        self._sgn = (-1)**self._dual
        self.Qv=[]
        self._weight = weight
        self._use_symmetry = use_symmetry
        self._kwargs = kwargs
        self._sgn = (-1)**int(dual)        
        half = QQ(1)/QQ(2)
        threehalf = QQ(3)/QQ(2)
        if use_symmetry:
            ## First find weight mod 2:
            twok= QQ(2)*QQ(weight)
            if not twok.is_integral():
                raise ValueError,"Only integral or half-integral weights implemented!"
            kmod2 = QQ(twok % 4)/QQ(2)
            if dual:
                sig_mod_4 = -self._weil_module.signature() % 4
            else:
                sig_mod_4 = self._weil_module.signature() % 4
            sym_type = 0
            if (kmod2,sig_mod_4) in [(half,1),(threehalf,3),(0,0),(1,2)]:
                sym_type = 1
            elif (kmod2,sig_mod_4) in [(half,3),(threehalf,1),(0,2),(1,0)]:
                sym_type = -1
            else:
                raise ValueError,"The Weil module with signature {0} is incompatible with the weight {1}!".format( self._weil_module.signature(),weight)
            ## Deven and Dodd contains the indices for the even and odd basis
            Deven=[]; Dodd=[]
            if sym_type==1:
                self._D = self._weil_module.even_submodule(indices=1)
            else: #sym_type==-1:
                self._D = self._weil_module.odd_submodule(indices=1)
            self._sym_type=sym_type
            dim = len(self._D)  #Dfinish-Dstart+1
        else:
            dim = len(self._weil_module.finite_quadratic_module().list())
            self._D = range(dim)
            self._sym_type=0
        if hasattr(self._weil_module,"finite_quadratic_module"):
#            for x in list(self._weil_module.finite_quadratic_module()):
            for x in self._weil_module.finite_quadratic_module():
                self.Qv.append(self._weil_module.finite_quadratic_module().Q(x))
        else:
            self.Qv=self._weil_module.Qv
        ambient_rank = self._weil_module.rank()
        MultiplierSystem.__init__(self,self._group,dual=dual,dimension=dim,ambient_rank=ambient_rank)
def test_masur_veech():
    from surface_dynamics.topological_recursion import MasurVeechTR

    MV = MasurVeechTR()

    for g, n, value in [(0, 4, QQ((2, 1))), (0, 5, QQ((1, 1))),
                        (0, 6, QQ((1, 2))), (0, 7, QQ((1, 4))),
                        (1, 1, QQ((2, 3))), (1, 2, QQ((1, 3))),
                        (1, 3, QQ((11, 60))), (1, 4, QQ((1, 10))),
                        (1, 5, QQ((163, 3024))), (2, 1, QQ((29, 840))),
                        (2, 2, QQ((337, 18144))), (3, 1, QQ((4111, 2223936)))]:
        coeff = 2**(4 * g - 2 + n) * ZZ(4 * g - 4 +
                                        n).factorial() / ZZ(6 * g - 7 +
                                                            2 * n).factorial()
        mv = MV.F(g, n, (0, ) * n)
        assert coeff * mv == value, (g, n, mv, value)
Exemplo n.º 19
0
    def make_curve(self):
        # To start with the data fields of self are just those from
        # the database.  We need to reformat these.

        # Old version: required constructing the actual elliptic curve
        # E, and computing some further data about it.

        # New version (May 2016): extra data fields now in the
        # database so we do not have to construct the curve or do any
        # computation with it on the fly.  As a failsafe the old way
        # is still included.

        data = self.data = {}
        data['ainvs'] = self.ainvs
        data['conductor'] = N = ZZ(self.conductor)
        data['j_invariant'] = QQ(str(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_str'] = unicode(str(data['j_invariant']))
        data['j_inv_latex'] = web_latex(data['j_invariant'])

        # extract data about MW rank, generators, heights and torsion:
        self.make_mw()

        # get more data from the database entry

        data['equation'] = self.equation
        local_data = self.local_data
        D = self.signD * prod([ld['p']**ld['ord_disc'] for ld in local_data])
        for ld in local_data:
            ld['kod'] = ld['kod'].replace("\\\\", "\\")
        data['disc'] = D
        Nfac = Factorization([(ZZ(ld['p']), ld['ord_cond'])
                              for ld in local_data])
        Dfac = Factorization([(ZZ(ld['p']), ld['ord_disc'])
                              for ld in local_data],
                             unit=ZZ(self.signD))

        data['minq_D'] = minqD = self.min_quad_twist['disc']
        minq_label = self.min_quad_twist['label']
        data['minq_label'] = db.ec_curves.lucky({'label': minq_label},
                                                'lmfdb_label')
        data['minq_info'] = '(itself)' if minqD == 1 else '(by %s)' % minqD
        if self.degree is None:
            data['degree'] = 0  # invalid, but will be displayed nicely
        else:
            data['degree'] = self.degree
        if self.number == 1:
            data['an'] = self.anlist
            data['ap'] = self.aplist
        else:
            r = db.ec_curves.lucky({'lmfdb_iso': self.lmfdb_iso, 'number': 1})
            data['an'] = r['anlist']
            data['ap'] = r['aplist']

        minq_N, minq_iso, minq_number = split_lmfdb_label(data['minq_label'])

        data['disc_factor'] = latex(Dfac)
        data['cond_factor'] = latex(Nfac)
        data['disc_latex'] = web_latex(D)
        data['cond_latex'] = web_latex(N)

        data['galois_images'] = [
            trim_galois_image_code(s) for s in self.mod_p_images
        ]
        data['non_maximal_primes'] = self.non_maximal_primes
        data['galois_data'] = [{
            'p': p,
            'image': im
        } for p, im in zip(data['non_maximal_primes'], data['galois_images'])]

        data['CMD'] = self.cm
        data['CM'] = "no"
        data['EndE'] = "\(\Z\)"
        if self.cm:
            data['cm_ramp'] = [
                p for p in ZZ(self.cm).support()
                if not p in self.non_maximal_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'] = "yes (\(D=%s\))" % data['CMD']
            if data['CMD'] % 4 == 0:
                d4 = ZZ(data['CMD']) // 4
                data['EndE'] = "\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = "\(\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)')

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

        cond, iso, num = split_lmfdb_label(self.lmfdb_label)
        self.class_url = url_for(".by_double_iso_label",
                                 conductor=N,
                                 iso_label=iso)
        self.one_deg = ZZ(self.class_deg).is_prime()
        self.ncurves = db.ec_curves.count({'lmfdb_iso': self.lmfdb_iso})
        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]])

        if self.twoadic_gens:
            from sage.matrix.all import Matrix
            data['twoadic_gen_matrices'] = ','.join(
                [latex(Matrix(2, 2, M)) for M in self.twoadic_gens])
            data[
                'twoadic_rouse_url'] = ROUSE_URL_PREFIX + self.twoadic_label + ".html"

        # Leading term of L-function & other BSD data
        self.make_bsd()

        # 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)

        if self.iso == '990h':
            data['Gamma0optimal'] = bool(self.number == 3)
        else:
            data['Gamma0optimal'] = bool(self.number == 1)

        data['p_adic_data_exists'] = False
        if data['Gamma0optimal']:
            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()

        data['newform'] = 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

        self.class_url = url_for(".by_double_iso_label",
                                 conductor=N,
                                 iso_label=iso)
        self.friends = [('Isogeny class ' + self.lmfdb_iso, self.class_url),
                        ('Minimal quadratic twist %s %s' %
                         (data['minq_info'], data['minq_label']),
                         url_for(".by_triple_label",
                                 conductor=minq_N,
                                 iso_label=minq_iso,
                                 number=minq_number)),
                        ('All twists ',
                         url_for(".rational_elliptic_curves", jinv=self.jinv)),
                        ('L-function',
                         url_for("l_functions.l_function_ec_page",
                                 conductor_label=N,
                                 isogeny_class_label=iso))]

        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 = [('Download coefficients of q-expansion',
                           url_for(".download_EC_qexp",
                                   label=self.lmfdb_label,
                                   limit=1000)),
                          ('Download all stored data',
                           url_for(".download_EC_all",
                                   label=self.lmfdb_label)),
                          ('Download Magma code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='magma')),
                          ('Download SageMath code',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='sage')),
                          ('Download GP code',
                           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.lmfdb_label), (None, self.plot_link),
                           ('Conductor', '\(%s\)' % data['conductor']),
                           ('Discriminant', '\(%s\)' % data['disc']),
                           ('j-invariant', '%s' % data['j_inv_latex']),
                           ('CM', '%s' % data['CM']),
                           ('Rank', '\(%s\)' % self.mw['rank']),
                           ('Torsion Structure',
                            '\(%s\)' % self.mw['tor_struct'])]

        self.title = "Elliptic Curve %s (Cremona label %s)" % (
            self.lmfdb_label, self.label)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                      ('$\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, ' ')]
def test_masur_veech_edge_weight():
    from surface_dynamics.topological_recursion import MasurVeechTR
    from sage.all import PolynomialRing

    R = PolynomialRing(QQ, 't')
    t = R.gen()
    MV = MasurVeechTR(edge_weight=t)
    for g, n, value in [
        (0, 3, R.one()), (0, 4, t), (0, 5, QQ((4, 9)) * t + QQ((5, 9)) * t**2),
        (0, 6, QQ((8, 27)) * t + QQ((4, 9)) * t**2 + QQ((7, 27)) * t**3),
        (1, 1, t), (1, 2, QQ((5, 9)) * t + QQ((4, 9)) * t**2),
        (1, 3, QQ((4, 9)) * t + QQ((13, 33)) * t**2 + QQ((16, 99)) * t**3),
        (2, 1, QQ((76, 261)) * t + QQ((125, 261)) * t**2 + QQ(
            (440, 2349)) * t**3 + QQ((100, 2349)) * t**4),
        (2, 2, QQ((296, 1011)) * t + QQ((19748, 45495)) * t**2 + QQ(
            (9127, 45495)) * t**3 + QQ((560, 9099)) * t**4 + QQ(
                (100, 9099)) * t**5)
    ]:
        p = MV.F(g, n, (0, ) * n)
        assert parent(p) is R
        p /= p(1)
        assert p == value, (g, n, p, value)
Exemplo n.º 21
0
def elliptic_curve_search(info):

    if info.get('download') == '1' and info.get('Submit') and info.get('query'):
        return download_search(info)

    if 'SearchAgain' in info:
        return rational_elliptic_curves()

    query = {}
    bread = info.get('bread',[('Elliptic Curves', url_for("ecnf.index")), ('$\Q$', url_for(".rational_elliptic_curves")), ('Search Results', '.')])

    if 'jump' in info:
        label = info.get('label', '').replace(" ", "")
        m = match_lmfdb_label(label)
        if m:
            try:
                return by_ec_label(label)
            except ValueError:
                return elliptic_curve_jump_error(label, info, wellformed_label=True)
        elif label.startswith("Cremona:"):
            label = label[8:]
            m = match_cremona_label(label)
            if m:
                try:
                    return by_ec_label(label)
                except ValueError:
                    return elliptic_curve_jump_error(label, info, wellformed_label=True)
        elif match_cremona_label(label):
            return elliptic_curve_jump_error(label, info, cremona_label=True)
        elif label:
            # Try to parse a string like [1,0,3,2,4] as valid
            # Weistrass coefficients:
            lab = re.sub(r'\s','',label)
            lab = re.sub(r'^\[','',lab)
            lab = re.sub(r']$','',lab)
            try:
                labvec = lab.split(',')
                labvec = [QQ(str(z)) for z in labvec] # Rationals allowed
                E = EllipticCurve(labvec)
                # Now we do have a valid curve over Q, but it might
                # not be in the database.
                ainvs = [str(c) for c in E.minimal_model().ainvs()]
                xainvs = ''.join(['[',','.join(ainvs),']'])
                data = db_ec().find_one({'xainvs': xainvs})
                if data is None:
                    data = db_ec().find_one({'ainvs': ainvs})
                    if data is None:
                        info['conductor'] = E.conductor()
                        return elliptic_curve_jump_error(label, info, missing_curve=True)
                return by_ec_label(data['lmfdb_label'])
            except (TypeError, ValueError, ArithmeticError):
                return elliptic_curve_jump_error(label, info)
        else:
            query['label'] = ''

    try:
        parse_rational(info,query,'jinv','j-invariant')
        parse_ints(info,query,'conductor')
        parse_ints(info,query,'torsion','torsion order')
        parse_ints(info,query,'rank')
        parse_ints(info,query,'sha','analytic order of &#1064;')
        parse_bracketed_posints(info,query,'torsion_structure',maxlength=2,process=str,check_divisibility='increasing')
        # speed up slow torsion_structure searches by also setting torsion
        if 'torsion_structure' in query and not 'torsion' in query:
            query['torsion'] = reduce(mul,[int(n) for n in query['torsion_structure']],1)
        if 'include_cm' in info:
            if info['include_cm'] == 'exclude':
                query['cm'] = 0
            elif info['include_cm'] == 'only':
                query['cm'] = {'$ne' : 0}

        parse_ints(info,query,field='isodeg',qfield='isogeny_degrees')

        parse_primes(info, query, 'surj_primes', name='surjective primes',
                     qfield='non-maximal_primes', mode='complement')
        if info.get('surj_quantifier') == 'exactly':
            mode = 'exact'
        else:
            mode = 'append'
        parse_primes(info, query, 'nonsurj_primes', name='non-surjective primes',
                     qfield='non-maximal_primes',mode=mode)
    except ValueError as err:
        info['err'] = str(err)
        return search_input_error(info, bread)

    count = parse_count(info,100)
    start = parse_start(info)

    if 'optimal' in info and info['optimal'] == 'on':
        # fails on 990h3
        query['number'] = 1

    info['query'] = query
    cursor = db_ec().find(query)
    nres = cursor.count()
    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0
    res = cursor.sort([('conductor', ASCENDING), ('iso_nlabel', ASCENDING),
                       ('lmfdb_number', ASCENDING)]).skip(start).limit(count)
    info['curves'] = res
    info['format_ainvs'] = format_ainvs
    info['curve_url'] = lambda dbc: url_for(".by_triple_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1], number=dbc['lmfdb_number'])
    info['iso_url'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1])
    info['number'] = nres
    info['start'] = start
    info['count'] = count
    info['more'] = int(start + count < nres)

    
    if nres == 1:
        info['report'] = 'unique match'
    elif nres == 2: 
        info['report'] = 'displaying both matches'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres
    credit = 'John Cremona'
    if 'non-surjective_primes' in query or 'non-maximal_primes' in query:
        credit += ' and Andrew Sutherland'

    t = info.get('title','Elliptic Curves search results')
    return render_template("ec-search-results.html", info=info, credit=credit, bread=bread, title=t)
def test_kontsevich():
    from surface_dynamics.topological_recursion import KontsevichTR
    K = KontsevichTR()
    # dim 0
    assert K.F(0, 3, [0, 0, 0]) == 1

    # dim 1
    assert K.F(1, 1, [0]) == 0
    assert K.F(1, 1, [1]) == QQ((1, 8))
    assert K.F(0, 4, [1, 0, 0, 0]) == 3

    # dim 2
    assert K.F(0, 5, [2, 0, 0, 0, 0]) == 15
    assert K.F(0, 5, [1, 1, 0, 0, 0]) == 18
    assert K.F(1, 2, [2, 0]) == QQ((5, 8))
    assert K.F(1, 2, [1, 1]) == QQ((3, 8))

    # dim 3
    assert K.F(2, 1, [4]) == QQ((105, 128))

    # dim 4
    assert K.F(2, 2, [5, 0]) == QQ((1155, 128))
    assert K.F(2, 2, [4, 1]) == QQ((945, 128))
    assert K.F(2, 2, [3, 2]) == QQ((1015, 128))

    # genus zero
    assert K.F(0, 3, (0, 0, 0)) == QQ((1, 1))
    assert K.F(0, 4, (1, 0, 0, 0)) == QQ((3, 1))
    assert K.F(0, 5, (2, 0, 0, 0, 0)) == QQ((15, 1))
    assert K.F(0, 5, (1, 1, 0, 0, 0)) == QQ((18, 1))
    assert K.F(0, 6, (3, 0, 0, 0, 0, 0)) == QQ((105, 1))
    assert K.F(0, 6, (2, 1, 0, 0, 0, 0)) == QQ((135, 1))
    assert K.F(0, 6, (1, 1, 1, 0, 0, 0)) == QQ((162, 1))
    assert K.F(0, 7, (4, 0, 0, 0, 0, 0, 0)) == QQ((945, 1))
    assert K.F(0, 7, (3, 1, 0, 0, 0, 0, 0)) == QQ((1260, 1))
    assert K.F(0, 7, (2, 2, 0, 0, 0, 0, 0)) == QQ((1350, 1))
    assert K.F(0, 7, (2, 1, 1, 0, 0, 0, 0)) == QQ((1620, 1))
    assert K.F(0, 7, (1, 1, 1, 1, 0, 0, 0)) == QQ((1944, 1))

    # genus one
    assert K.F(1, 1, (1, )) == QQ((1, 8))
    assert K.F(1, 2, (2, 0)) == QQ((5, 8))
    assert K.F(1, 2, (1, 1)) == QQ((3, 8))
    assert K.F(1, 3, (3, 0, 0)) == QQ((35, 8))
    assert K.F(1, 3, (2, 1, 0)) == QQ((15, 4))
    assert K.F(1, 3, (1, 1, 1)) == QQ((9, 4))
    assert K.F(1, 4, (4, 0, 0, 0)) == QQ((315, 8))
    assert K.F(1, 4, (3, 1, 0, 0)) == QQ((315, 8))
    assert K.F(1, 4, (2, 2, 0, 0)) == QQ((75, 2))
    assert K.F(1, 4, (2, 1, 1, 0)) == QQ((135, 4))
    assert K.F(1, 4, (1, 1, 1, 1)) == QQ((81, 4))

    # genus two
    assert K.F(2, 1, [4]) == QQ((105, 128))
    assert K.F(2, 2, [5, 0]) == QQ((1155, 128))
    assert K.F(2, 2, [4, 1]) == QQ((945, 128))
    assert K.F(2, 2, [3, 2]) == QQ((1015, 128))
    assert K.F(2, 3, [6, 0, 0]) == QQ((15015, 128))
    assert K.F(2, 3, [5, 1, 0]) == QQ((3465, 32))
    assert K.F(2, 3, [4, 2, 0]) == QQ((3465, 32))
    assert K.F(2, 3, [3, 3, 0]) == QQ((7105, 64))
    assert K.F(2, 3, [4, 1, 1]) == QQ((2835, 32))
    assert K.F(2, 3, [3, 2, 1]) == QQ((3045, 32))
    assert K.F(2, 4, [7, 0, 0, 0]) == QQ((225225, 128))
    assert K.F(2, 4, [6, 1, 0, 0]) == QQ((225225, 128))
    assert K.F(2, 4, [5, 2, 0, 0]) == QQ((3465, 2))
    assert K.F(2, 4, [5, 1, 1, 0]) == QQ((51975, 32))
    assert K.F(2, 4, [4, 3, 0, 0]) == QQ((112455, 64))
    assert K.F(2, 4, [4, 2, 1, 0]) == QQ((51975, 32))
    assert K.F(2, 4, [4, 1, 1, 1]) == QQ((42525, 32))
    assert K.F(2, 4, [3, 3, 1, 0]) == QQ((106575, 64))
    assert K.F(2, 4, [3, 2, 2, 0]) == QQ((13125, 8))
    assert K.F(2, 4, [3, 2, 1, 1]) == QQ((45675, 32))
    assert K.F(2, 4, [2, 2, 2, 1]) == QQ((23625, 16))

    # genus three
    assert K.F(3, 1, [7]) == QQ((25025, 1024))
    assert K.F(3, 2, [8, 0]) == QQ((425425, 1024))
    assert K.F(3, 2, [7, 1]) == QQ((375375, 1024))
    assert K.F(3, 2, [6, 2]) == QQ((385385, 1024))
    assert K.F(3, 2, [5, 3]) == QQ((193655, 512))
    assert K.F(3, 2, [4, 4]) == QQ((191205, 512))
    assert K.F(3, 3, [9, 0, 0]) == QQ((8083075, 1024))
    assert K.F(3, 3, [8, 1, 0]) == QQ((3828825, 512))
    assert K.F(3, 3, [7, 2, 0]) == QQ((3828825, 512))
    assert K.F(3, 3, [7, 1, 1]) == QQ((3378375, 512))
    assert K.F(3, 3, [6, 3, 0]) == QQ((7732725, 1024))
    assert K.F(3, 3, [6, 2, 1]) == QQ((3468465, 512))
    assert K.F(3, 3, [5, 4, 0]) == QQ((1923075, 256))
    assert K.F(3, 3, [5, 3, 1]) == QQ((1742895, 256))
    assert K.F(3, 3, [5, 2, 2]) == QQ((883575, 128))
    assert K.F(3, 3, [4, 4, 1]) == QQ((1720845, 256))
    assert K.F(3, 3, [4, 3, 2]) == QQ((1765575, 256))
    assert K.F(3, 3, [3, 3, 3]) == QQ((3570875, 512))

    # Witten <tau_{3g-2}>_{g,1} = 1 / (24^g g!)
    assert all((24**g * factorial(g) *
                K.F(g, 1, [3 * g - 2]) == ZZ(6 * g - 3).multifactorial(2))
               for g in range(1, 10))
Exemplo n.º 23
0
def elliptic_curve_search(**args):
    info = to_dict(args)
    query = {}
    bread = [('Elliptic Curves', url_for("ecnf.index")),
             ('$\Q$', url_for(".rational_elliptic_curves")),
             ('Search Results', '.')]
    if 'SearchAgain' in args:
        return rational_elliptic_curves()

    if 'jump' in args:
        label = info.get('label', '').replace(" ", "")
        m = match_lmfdb_label(label)
        if m:
            try:
                return by_ec_label(label)
            except ValueError:
                return elliptic_curve_jump_error(label,
                                                 info,
                                                 wellformed_label=True)
        elif label.startswith("Cremona:"):
            label = label[8:]
            m = match_cremona_label(label)
            if m:
                try:
                    return by_ec_label(label)
                except ValueError:
                    return elliptic_curve_jump_error(label,
                                                     info,
                                                     wellformed_label=True)
        elif match_cremona_label(label):
            return elliptic_curve_jump_error(label, info, cremona_label=True)
        elif label:
            # Try to parse a string like [1,0,3,2,4] as valid
            # Weistrass coefficients:
            lab = re.sub(r'\s', '', label)
            lab = re.sub(r'^\[', '', lab)
            lab = re.sub(r']$', '', lab)
            try:
                labvec = lab.split(',')
                labvec = [QQ(str(z)) for z in labvec]  # Rationals allowed
                E = EllipticCurve(labvec)
                # Now we do have a valid curve over Q, but it might
                # not be in the database.
                ainvs = [str(c) for c in E.minimal_model().ainvs()]
                data = db_ec().find_one({'ainvs': ainvs})
                if data is None:
                    info['conductor'] = E.conductor()
                    return elliptic_curve_jump_error(label,
                                                     info,
                                                     missing_curve=True)
                return by_ec_label(data['lmfdb_label'])
            except (TypeError, ValueError, ArithmeticError):
                return elliptic_curve_jump_error(label, info)
        else:
            query['label'] = ''

    if info.get('jinv'):
        j = clean_input(info['jinv'])
        j = j.replace('+', '')
        if not QQ_RE.match(j):
            info[
                'err'] = 'Error parsing input for the j-invariant.  It needs to be a rational number.'
            return search_input_error(info, bread)
        query['jinv'] = str(QQ(j))  # to simplify e.g. 1728/1

    for field in ['conductor', 'torsion', 'rank', 'sha']:
        if info.get(field):
            info[field] = clean_input(info[field])
            ran = info[field]
            ran = ran.replace('..', '-').replace(' ', '')
            if not LIST_RE.match(ran):
                names = {
                    'conductor': 'conductor',
                    'torsion': 'torsion order',
                    'rank': 'rank',
                    'sha': 'analytic order of &#1064;'
                }
                info[
                    'err'] = 'Error parsing input for the %s.  It needs to be an integer (such as 25), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 4,9,16 or 4-25, 81-121).' % names[
                        field]
                return search_input_error(info, bread)
            # Past input check
            tmp = parse_range2(ran, field)
            # work around syntax for $or
            # we have to foil out multiple or conditions
            if tmp[0] == '$or' and '$or' in query:
                newors = []
                for y in tmp[1]:
                    oldors = [dict.copy(x) for x in query['$or']]
                    for x in oldors:
                        x.update(y)
                    newors.extend(oldors)
                tmp[1] = newors
            query[tmp[0]] = tmp[1]

    if 'optimal' in info and info['optimal'] == 'on':
        # fails on 990h3
        query['number'] = 1

    if 'torsion_structure' in info and info['torsion_structure']:
        info['torsion_structure'] = clean_input(info['torsion_structure'])
        if not TORS_RE.match(info['torsion_structure']):
            info[
                'err'] = 'Error parsing input for the torsion structure.  It needs to be one or more integers in square brackets, such as [6], [2,2], or [2,4].  Moreover, each integer should be bigger than 1, and each divides the next.'
            return search_input_error(info, bread)
        query['torsion_structure'] = [
            str(a) for a in parse_list(info['torsion_structure'])
        ]

    if info.get('surj_primes'):
        info['surj_primes'] = clean_input(info['surj_primes'])
        format_ok = LIST_POSINT_RE.match(info['surj_primes'])
        if format_ok:
            surj_primes = [int(p) for p in info['surj_primes'].split(',')]
            format_ok = all([ZZ(p).is_prime(proof=False) for p in surj_primes])
        if format_ok:
            query['non-surjective_primes'] = {"$nin": surj_primes}
        else:
            info[
                'err'] = 'Error parsing input for surjective primes.  It needs to be a prime (such as 5), or a comma-separated list of primes (such as 2,3,11).'
            return search_input_error(info, bread)

    if info.get('nonsurj_primes'):
        info['nonsurj_primes'] = clean_input(info['nonsurj_primes'])
        format_ok = LIST_POSINT_RE.match(info['nonsurj_primes'])
        if format_ok:
            nonsurj_primes = [
                int(p) for p in info['nonsurj_primes'].split(',')
            ]
            format_ok = all(
                [ZZ(p).is_prime(proof=False) for p in nonsurj_primes])
        if format_ok:
            if info['surj_quantifier'] == 'exactly':
                nonsurj_primes.sort()
                query['non-surjective_primes'] = nonsurj_primes
            else:
                if 'non-surjective_primes' in query:
                    query['non-surjective_primes'] = {
                        "$nin": surj_primes,
                        "$all": nonsurj_primes
                    }
                else:
                    query['non-surjective_primes'] = {"$all": nonsurj_primes}
        else:
            info[
                'err'] = 'Error parsing input for nonsurjective primes.  It needs to be a prime (such as 5), or a comma-separated list of primes (such as 2,3,11).'
            return search_input_error(info, bread)

    info['query'] = query

    count_default = 100
    if info.get('count'):
        try:
            count = int(info['count'])
        except:
            count = count_default
    else:
        count = count_default
    info['count'] = count

    start_default = 0
    if info.get('start'):
        try:
            start = int(info['start'])
            if (start < 0):
                start += (1 - (start + 1) / count) * count
        except:
            start = start_default
    else:
        start = start_default

    cursor = db_ec().find(query)
    nres = cursor.count()
    if (start >= nres):
        start -= (1 + (start - nres) / count) * count
    if (start < 0):
        start = 0
    res = cursor.sort([('conductor', ASCENDING), ('lmfdb_iso', ASCENDING),
                       ('lmfdb_number', ASCENDING)]).skip(start).limit(count)
    info['curves'] = res
    info['format_ainvs'] = format_ainvs
    info['curve_url'] = lambda dbc: url_for(".by_triple_label",
                                            conductor=dbc['conductor'],
                                            iso_label=split_lmfdb_label(dbc[
                                                'lmfdb_iso'])[1],
                                            number=dbc['lmfdb_number'])
    info['iso_url'] = lambda dbc: url_for(".by_double_iso_label",
                                          conductor=dbc['conductor'],
                                          iso_label=split_lmfdb_label(dbc[
                                              'lmfdb_iso'])[1])
    info['number'] = nres
    info['start'] = start
    if nres == 1:
        info['report'] = 'unique match'
    elif nres == 2:
        info['report'] = 'displaying both matches'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (
                start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres
    credit = 'John Cremona'
    if 'non-surjective_primes' in query:
        credit += 'and Andrew Sutherland'
    t = 'Elliptic Curves search results'
    return render_template("search_results.html",
                           info=info,
                           credit=credit,
                           bread=bread,
                           title=t)
Exemplo n.º 24
0
    Chen-Moeller-Zagier for quadratic principal stratum, Elise tables, Eskin-Okounkov,
    Eskin-Okounkov-Pandharipande, etc)
"""

from sage.all import ZZ, QQ, zeta, pi
from sage.arith.misc import bernoulli, factorial

from .abelian_strata import AbelianStratum, AbelianStratumComponent
from .quadratic_strata import QuadraticStratum, QuadraticStratumComponent

# In the table below, the volume is normalized by dividing by zeta(2g)
# These values appear in
# - Eskin-Masur-Zorich "principal boundary ..."
abelian_volumes_table = {
    # dim 2
    AbelianStratum(0).hyperelliptic_component(): QQ((2,1)),
    # dim 4
    AbelianStratum(2).hyperelliptic_component(): QQ((3,4)),
    # dim 5
    AbelianStratum(1,1).hyperelliptic_component(): QQ((2,3)),
    # dim 6
    AbelianStratum(4).hyperelliptic_component(): QQ((9,64)),
    AbelianStratum(4).odd_component(): QQ((7,18)),
    # dim 7
    AbelianStratum(3,1).unique_component(): QQ((16,45)),
    AbelianStratum(2,2).hyperelliptic_component(): QQ((1,10)),
    AbelianStratum(2,2).odd_component(): QQ((7,32)),
    # dim 8
    AbelianStratum(6).hyperelliptic_component(): QQ((25, 1536)),
    AbelianStratum(6).odd_component(): QQ((1,4)),
    AbelianStratum(6).even_component(): QQ((64,405)),
Exemplo n.º 25
0
    def make_curve(self):
        # To start with the data fields of self are just those from
        # the database.  We need to reformat these.

        # Old version: required constructing the actual elliptic curve
        # E, and computing some further data about it.

        # New version (May 2016): extra data fields now in the
        # database so we do not have to construct the curve or do any
        # computation with it on the fly.  As a failsafe the old way
        # is still included.

        data = self.data = {}
        data['ainvs'] = [ZZ(ai) for ai in self.ainvs]
        data['conductor'] = N = ZZ(self.conductor)
        data['j_invariant'] = QQ(str(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'])

        # extract data about MW rank, generators, heights and torsion:
        self.make_mw()

        # get more data from the database entry

        data['equation'] = self.equation
        local_data = self.local_data
        D = self.signD * prod([ld['p']**ld['ord_disc'] for ld in local_data])
        for ld in local_data:
            ld['kod'] = ld['kod'].replace("\\\\", "\\")
        data['disc'] = D
        Nfac = Factorization([(ZZ(ld['p']), ld['ord_cond'])
                              for ld in local_data])
        Dfac = Factorization([(ZZ(ld['p']), ld['ord_disc'])
                              for ld in local_data],
                             unit=ZZ(self.signD))

        data['minq_D'] = minqD = self.min_quad_twist['disc']
        data['minq_label'] = self.min_quad_twist[
            'lmfdb_label'] if self.label_type == 'LMFDB' else self.min_quad_twist[
                'label']
        data['minq_info'] = '(itself)' if minqD == 1 else '(by {})'.format(
            minqD)

        if self.degree is None:
            data['degree'] = 0  # invalid, but will be displayed nicely
        else:
            data['degree'] = self.degree

        try:
            data['an'] = self.anlist
            data['ap'] = self.aplist
        except AttributeError:
            r = db.ec_curves.lucky({'lmfdb_iso': self.lmfdb_iso, 'number': 1})
            data['an'] = r['anlist']
            data['ap'] = r['aplist']

        data['disc_factor'] = latex(Dfac)
        data['cond_factor'] = latex(Nfac)
        data['disc_latex'] = web_latex(D)
        data['cond_latex'] = web_latex(N)

        data['galois_images'] = [
            trim_galois_image_code(s) for s in self.mod_p_images
        ]
        data['non_maximal_primes'] = self.non_maximal_primes
        data['galois_data'] = [{
            'p': p,
            'image': im
        } for p, im in zip(data['non_maximal_primes'], data['galois_images'])]

        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.non_maximal_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)')

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

        cond, iso, num = split_lmfdb_label(self.lmfdb_label)
        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]])

        if self.twoadic_gens:
            from sage.matrix.all import Matrix
            data['twoadic_gen_matrices'] = ','.join(
                [latex(Matrix(2, 2, M)) for M in self.twoadic_gens])
            data[
                'twoadic_rouse_url'] = ROUSE_URL_PREFIX + self.twoadic_label + ".html"

        # Leading term of L-function & other BSD data
        self.make_bsd()

        # 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
        data[
            'manin_constant'] = self.manin_constant  # (conditional on data['optimality_known'])

        if N < OPTIMALITY_BOUND:

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

        else:

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

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

        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()

        data['newform'] = 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.iso)
            self.class_name = self.iso
        else:
            self.class_url = url_for(".by_double_iso_label",
                                     conductor=N,
                                     iso_label=iso)
            self.class_name = self.lmfdb_iso
        data['class_name'] = self.class_name
        data['number'] = self.number

        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=self.jinv))]

        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.label if self.label_type == 'Cremona' else self.lmfdb_label),
            (None, self.plot_link), ('Conductor', '%s' % data['conductor']),
            ('Discriminant', '%s' % data['disc']),
            ('j-invariant', '%s' % data['j_inv_latex']),
            ('CM', '%s' % data['CM']), ('Rank', '%s' % self.mw['rank']),
            ('Torsion Structure', r'\(%s\)' % self.mw['tor_struct'])
        ]

        if self.label_type == 'Cremona':
            self.title = "Elliptic curve with Cremona label {} (LMFDB label {})".format(
                self.label, self.lmfdb_label)
        else:
            self.title = "Elliptic curve with LMFDB label {} (Cremona label {})".format(
                self.lmfdb_label, self.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, ' ')]
Exemplo n.º 26
0
    def rho(self,M,silent=0,numeric=0,prec=-1):
        r""" The Weil representation acting on SL(2,Z).

        INPUT::

        -``M`` -- element of SL2Z
        - ''numeric'' -- set to 1 to return a Matrix_complex_dense with prec=prec instead of exact
        - ''prec'' -- precision
        EXAMPLES::
        
            sage: WR=WeilRepDiscriminantForm(1,dual=False)
            sage: S,T=SL2Z.gens()
            sage: WR.rho(S)
            [
            [-zeta8^3 -zeta8^3]
            [-zeta8^3  zeta8^3], sqrt(1/2)
            ]
            sage: WR.rho(T)
            [
            [       1        0]
            [       0 -zeta8^2], 1
            ]
            sage: A=SL2Z([-1,1,-4,3]); WR.rho(A)
            [
            [zeta8^2       0]
            [      0       1], 1
            ]
            sage: A=SL2Z([41,77,33,62]); WR.rho(A)
            [
            [-zeta8^3  zeta8^3]
            [   zeta8    zeta8], sqrt(1/2)
            ]

        """
        N=self._N; D=2*N; D2=2*D
        if numeric==0:
            K=CyclotomicField (lcm(4*self._N,8))
            z=K(CyclotomicField(4*self._N).gen())
            rho=matrix(K,D)
        else:
            CF = MPComplexField(prec)
            RF = CF.base()
            MS = MatrixSpace(CF,int(D),int(D))
            rho = Matrix_complex_dense(MS)
            #arg = RF(2)*RF.pi()/RF(4*self._N)
            z = CF(0,RF(2)*RF.pi()/RF(4*self._N)).exp()
        [a,b,c,d]=M
        fak=1; sig=1
        if c<0:
            # need to use the reflection 
            # r(-A)=r(Z)r(A)sigma(Z,A)  where sigma(Z,A)=-1 if c>0
            sig=-1
            if numeric==0:
                fz=CyclotomicField(4).gen() # = i
            else:
                fz=CF(0,1)
            # the factor is rho(Z) sigma(Z,-A)
            #if(c < 0 or (c==0 and d>0)):
            #    fak=-fz
            #else:
            #sig=1
            #fz=1
            fak=fz
            a=-a; b=-b; c=-c; d=-d;
            A=SL2Z([a,b,c,d])
            if numeric==0:
                chi=self.xi(A)            
            else:
                chi=CF(self.xi(A).complex_embedding(prec))
            if(silent>0):
                print("fz={0}".format(fz))
                print("chi={0}".format(chi))
        elif c == 0: # then we use the simple formula
            if d < 0:
                sig=-1
                if numeric == 0:
                    fz=CyclotomicField(4).gen()
                else:
                    fz=CF(0,1)
                fak=fz
                a=-a; b=-b; c=-c; d=-d;
            else:
                fak=1
            for alpha in range(D):
                arg=(b*alpha*alpha ) % D2
                if(sig==-1):
                    malpha = (D - alpha) % D
                    rho[malpha,alpha]=fak*z**arg
                else:
                    #print "D2=",D2
                    #print "b=",b
                    #print "arg=",arg
                    rho[alpha,alpha]=z**arg
            return [rho,1]
        else:
            if numeric==0:
                chi=self.xi(M)            
            else:
                chi=CF(self.xi(M).complex_embedding(prec))
        Nc=gcd(Integer(D),Integer(c))
        #chi=chi*sqrt(CF(Nc)/CF(D))
        if(valuation(Integer(c),2)==valuation(Integer(D),2)):
            xc=Integer(N)
        else:
            xc=0
        if silent>0:
            print("c={0}".format(c))
            print("xc={0}".format(xc))
            print("chi={0}".format(chi))
        for alpha in range(D):
            al=QQ(alpha)/QQ(D)
            for beta in range(D):
                be=QQ(beta)/QQ(D)
                c_div=False
                if(xc==0):
                    alpha_minus_dbeta=(alpha-d*beta) % D
                else:
                    alpha_minus_dbeta=(alpha-d*beta-xc) % D
                if silent > 0: # and alpha==7 and beta == 7):
                    print("alpha,beta={0},{1}".format(alpha,beta))
                    print("c,d={0},{1}".format(c,d))
                    print("alpha-d*beta={0}".format(alpha_minus_dbeta))
                invers=0
                for r in range(D):
                    if (r*c - alpha_minus_dbeta) % D ==0:
                        c_div=True
                        invers=r
                        break
                if c_div and silent > 0:
                    print("invers={0}".format(invers))
                    print(" inverse(alpha-d*beta) mod c={0}".format(invers))
                elif(silent>0):
                    print(" no inverse!")
                if(c_div):
                    y=invers
                    if xc==0:
                        argu=a*c*y**2+b*d*beta**2+2*b*c*y*beta
                    else:
                        argu=a*c*y**2+2*xc*(a*y+b*beta)+b*d*beta**2+2*b*c*y*beta
                    argu = argu % D2
                    tmp1=z**argu  # exp(2*pi*I*argu)
                    if silent>0:# and alpha==7 and beta==7):
                        print("a,b,c,d={0},{1},{2},{3}".format(a,b,c,d))
                        print("xc={0}".format(xc))
                        print("argu={0}".format(argu))
                        print("exp(...)={0}".format(tmp1))
                        print("chi={0}".format(chi))
                        print("sig={0}".format(sig))
                    if sig == -1:
                        minus_alpha = (D - alpha) % D
                        rho[minus_alpha,beta]=tmp1*chi
                    else:
                        rho[alpha,beta]=tmp1*chi
        #print "fak=",fak
        if numeric==0:            
            return [fak*rho,sqrt(QQ(Nc)/QQ(D))]
        else:
            return [CF(fak)*rho,RF(sqrt(QQ(Nc)/QQ(D)))]
Exemplo n.º 27
0
def parse_NFelt(K, s):
    r"""
    Returns an element of K defined by the string s.
    """
    return K([QQ(c.encode()) for c in s.split(",")])
Exemplo n.º 28
0
    def __init__(self,N,k=None,dual=False,sym_type=0,verbose=0):
        r""" Creates a Weil representation (or its dual) of the discriminant form given by D=Z/2NZ.

        
        EXAMPLES::


            sage: WR=WeilRepDiscriminantForm(1,dual=True)
            sage: WR.D
            [0, 1/2]
            sage: WR.D_as_integers
            [0, 1]
            sage: WR.Qv
            [0, -1/4]
            sage: WR=WeilRepDiscriminantForm(1,dual=False)
            sage: WR.D
            [0, 1/2]
            sage: WR.D_as_integers
            [0, 1]
            sage: WR.Qv
            [0, 1/4]

            
        
        """
        ## If N<0 we use |N| and set dual rep. to true
        self._verbose = verbose
        if N<0:
            self._N=-N
            self.dual = not dual
            self._is_dual_rep= not dual # do we use dual representation or not
        else:
            self._N=N
            self._is_dual_rep=dual
        
        N2=Integer(2*self._N)
        self.group=SL2Z
        self._level=4*self._N
        self._D_as_integers=list(range(0,N2))
        self._even_submodule=[]
        self._odd_submodule=[]
        self._D=list()
        for x in range(0,N2):
            y=QQ(x)/QQ(N2)
            self._D.append(y)
        self.Qv=list()              # List of +- q(x) for x in D
        self.Qv_times_level=list()      # List of +- 4N*q(x) for x in D
        if self._is_dual_rep: # we add this already here for efficiency
            sig=-1
        else:
            sig=1
        for x in self._D:
            y=sig*self.Q(x)
            self.Qv.append(y)
            self.Qv_times_level.append(self._level*y)

        self._signature = sig
        self._sigma_invariant = CyclotomicField(8).gens()[0]**-self._signature
        self._rank = N2
        self._weight = None
        self._sym_type = sym_type
        if sym_type==0 and k != None: # Then we set it
            self._weight = QQ(k)
            if ((self._weight-QQ(1)/QQ(2)) % 2) == 0:
                sym_type = sig
            elif ((self._weight-QQ(3)/QQ(2)) % 2) == 0:
                sym_type = -sig
            else:
                raise ValueError("Got incompatible weight and signature!")
        elif sym_type != 0 and k == None:  ## Set the weight
            if sig==sym_type:
                self._weight = QQ(1)/QQ(2)
            elif sig==-sym_type:
                self._weight = QQ(3)/QQ(2)
            else:
                raise ValueError("Got incompatible symmetry type and signature!")
        elif sym_type==0 and k==None:  ## Set the weight
            ## We make a choice
            self._sym_type = sig
            self._weight = QQ(1)/QQ(2)
        else:
            ## Check consistency
            self._weight = QQ(k)
            if ((self._weight-QQ(1)/QQ(2)) % 2) == 0 and self._sym_type == sig:
                pass
            elif ((self._weight-QQ(3)/QQ(2)) % 2) == 0 and self._sym_type == -sig:
                pass

            else:
                raise ValueError("Need either sym type or weight!")
Exemplo n.º 29
0
def parse_newton_polygon(inp, query, qfield):
    polygons = []
    for polygon in BRACKETING_RE.finditer(inp):
        polygon = polygon.groups()[0][1:-1]
        if '[' in polygon or ']' in polygon:
            raise ValueError("Mismatched brackets")
        if '(' in polygon or ')' in polygon:
            # user is specifying break points
            if PAREN_RE.sub('', polygon).replace(',', ''):
                raise ValueError("Mismatched parentheses: %s" % polygon)
            lastx = ZZ(0)
            lasty = QQ(0)
            lastslope = None
            slopes = []
            for point in PAREN_RE.finditer(polygon):
                point = point.groups()[0]
                xy = point[1:-1].split(',')
                if len(xy) != 2:
                    raise ValueError("Malformed break point: %s" % point)
                try:
                    x = ZZ(xy[0])
                    y = QQ(xy[1])
                except TypeError as err:
                    raise ValueError(str(err))
                if x <= lastx:
                    raise ValueError(
                        "Break points must be sorted by x-coordinate: %s" %
                        point)
                slope = (y - lasty) / (x - lastx)
                if lastslope is not None and slope <= lastslope:
                    raise ValueError(
                        "Slopes specified by break points must be increasing: %s"
                        % point)
                slopes.extend([str(slope)] * (x - lastx))
                lastx = x
                lasty = y
                lastslope = slope
        else:
            slopes = []
            lastslope = None
            for slope in polygon.split(','):
                if not QQ_RE.match(slope):
                    raise ValueError("%s is not a rational slope" % slope)
                qslope = QQ(slope)
                if lastslope is not None and qslope < lastslope:
                    raise ValueError("Slopes must be increasing: %s, %s" %
                                     (lastslope, slope))
                lastslope = qslope
                slopes.append(slope)
        polygons.append(slopes)
    replaced = BRACKETING_RE.sub('#', inp)
    if '[' in replaced or ']' in replaced:
        raise ValueError("Mismatched brackets")
    extra_slopes = []
    for slope in replaced.split(','):
        if slope == '#':
            continue
        if not QQ_RE.match(slope):
            raise ValueError("%s is not a rational slope" % slope)
        #extra_slopes.append(slope)
        raise ValueError("You cannot specify slopes on their own")
    if len(polygons) + len(extra_slopes) == 1:
        if polygons:
            query[qfield] = {'$regex': '^' + ' '.join(polygons[0])}
        else:  # won't occur because of the ValueError("You cannot specify slopes on their own") above
            query[qfield] = extra_slopes[0]
    else:
        collapse_ors([
            '$or',
            ([{
                qfield: {
                    '$regex': '^' + ' '.join(poly)
                }
            } for poly in polygons])
        ], query)  # +
Exemplo n.º 30
0
def FIELD(label):
    nf = WebNumberField(label, gen_name=special_names.get(label, 'a'))
    nf.parse_NFelt = lambda s: nf.K()([QQ(str(c)) for c in s])
    return nf