Ejemplo n.º 1
0
 def newton_plot(self):
     S = [QQ(s) for s in self.slopes]
     C = Counter(S)
     pts = [(0,0)]
     x = y = 0
     for s in sorted(C):
         c = C[s]
         x += c
         y += c*s
         pts.append((x,y))
     L = Graphics()
     L += line([(0,0),(0,y+0.2)],color="grey")
     for i in range(1,y+1):
         L += line([(0,i),(0.06,i)],color="grey")
     for i in range(1,C[0]):
         L += line([(i,0),(i,0.06)],color="grey")
     for i in range(len(pts)-1):
         P = pts[i]
         Q = pts[i+1]
         for x in range(P[0],Q[0]+1):
             L += line([(x,P[1]),(x,P[1] + (x-P[0])*(Q[1]-P[1])/(Q[0]-P[0]))],color="grey")
         for y in range(P[1],Q[1]):
             L += line([(P[0] + (y-P[1])*(Q[0]-P[0])/(Q[1]-P[1]),y),(Q[0],y)],color="grey")
     L += line(pts, thickness = 2)
     L.axes(False)
     L.set_aspect_ratio(1)
     return encode_plot(L, pad=0, pad_inches=0, bbox_inches='tight')
Ejemplo n.º 2
0
def mu_portrait(n):
    """ returns an encoded scatter plot of the nth roots of unity in the complex plane """
    if n <= 120:
        plot =  list_plot([(cos(2*pi*m/n),sin(2*pi*m/n)) for m in range(n)],pointsize=30+60/n, axes=False)
    else:
        plot = circle((0,0),1,thickness=3)
    plot.xmin(-1); plot.xmax(1); plot.ymin(-1); plot.ymax(1)
    plot.set_aspect_ratio(4.0/3.0)
    return encode_plot(plot)
Ejemplo n.º 3
0
def nu1_mu_portrait(n):
    """ returns an encoded scatter plot of the nth roots of unity in the complex plane """
    if n == 1:
        return db.gps_sato_tate.lookup('1.2.1.2.1a').get('trace_histogram')
    if n <= 120:
        plot =  sum([line2d([(-2*cos(2*pi*m/n),-2*sin(2*pi*m/n)),(2*cos(2*pi*m/n),2*sin(2*pi*m/n))],thickness=3) for m in range(n)]) + circle((0,0),0.1,rgbcolor=(0,0,0),fill=True)
    else:
        plot = circle((0,0),2,fill=True)
    plot.xmin(-2); plot.xmax(2); plot.ymin(-2); plot.ymax(2)
    plot.set_aspect_ratio(4.0/3.0)
    plot.axes(False)
    return encode_plot(plot)
Ejemplo n.º 4
0
def su2_mu_portrait(n):
    """ returns an encoded line plot of SU(2) x mu(n) in the complex plane """
    if n == 1:
        return db.gps_sato_tate.lookup('1.2.3.1.1a').get('trace_histogram')
    if n <= 120:
        plot =  sum([line2d([(-2*cos(2*pi*m/n),-2*sin(2*pi*m/n)),(2*cos(2*pi*m/n),2*sin(2*pi*m/n))],thickness=3) for m in range(n)])
    else:
        plot = circle((0,0),2,fill=True)
    plot.xmin(-2); plot.xmax(2); plot.ymin(-2); plot.ymax(2)
    plot.set_aspect_ratio(4.0/3.0)
    plot.axes(False)
    return encode_plot(plot)
Ejemplo n.º 5
0
    def make_class(self):
        self.ECNF = ECNF.by_label(self.label)

        # Create a list of the curves in the class from the database
        self.db_curves = [ECNF(c) for c in db_ec().find(
            {'field_label' : self.field_label, 'conductor_label' :
             self.conductor_label, 'iso_label' : self.iso_label}).sort('number')]
        size = len(self.db_curves)

        # Extract the isogeny degree matrix from the database if possible, else create it
        if hasattr(self,'isogeny_matrix'):
            from sage.matrix.all import Matrix
            self.isogeny_matrix = Matrix(self.isogeny_matrix)
        else:
            self.isogeny_matrix = make_iso_matrix(self.db_curves)

        # Create isogeny graph:
        self.graph = make_graph(self.isogeny_matrix)
        P = self.graph.plot(edge_labels=True)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img
        self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix))

        self.curves = [[c.short_label, c.urls['curve'], c.latex_ainvs] for c in self.db_curves]

        self.urls = {}
        self.urls['class'] = url_for(".show_ecnf_isoclass", nf = self.field_label, conductor_label=self.conductor_label, class_label = self.iso_label)
        self.urls['conductor'] = url_for(".show_ecnf_conductor", nf = self.field_label, conductor_label=self.conductor_label)
        self.urls['field'] = url_for('.show_ecnf1', nf=self.ECNF.field_label)
        self.field = self.ECNF.field
        if self.field.is_real_quadratic():
            self.hmf_label = "-".join([self.field.label,self.conductor_label,self.iso_label])
            self.urls['hmf'] = url_for('hmf.render_hmf_webpage', field_label=self.field.label, label=self.hmf_label)

        if self.field.is_imag_quadratic():
            self.bmf_label = "-".join([self.field.label,self.conductor_label,self.iso_label])


        self.friends = []
        if self.field.is_real_quadratic():
            self.friends += [('Hilbert Modular Form '+self.hmf_label, self.urls['hmf'])]
        if self.field.is_imag_quadratic():
            self.friends += [('Bianchi Modular Form %s not yet available' % self.bmf_label, '')]

        self.properties = [('Label', self.ECNF.label),
                           (None, self.graph_link),
                           ('Conductor', '%s' % self.ECNF.cond)
                           ]

        self.bread = [('Elliptic Curves ', url_for(".index")),
                      (self.ECNF.field_label, self.urls['field']),
                      (self.ECNF.conductor_label, self.urls['conductor']),
                      ('isogeny class %s' % self.ECNF.short_label, self.urls['class'])]
Ejemplo n.º 6
0
 def circle_plot(self):
     pts = []
     pi = RR.pi()
     for angle in self.angles:
         angle = RR(angle)*pi
         c = angle.cos()
         s = angle.sin()
         if abs(s) < 0.00000001:
             pts.append((c,s))
         else:
             pts.extend([(c,s),(c,-s)])
     P = points(pts,size=100) + circle((0,0),1,color='black')
     P.axes(False)
     P.set_aspect_ratio(1)
     return encode_plot(P)
Ejemplo n.º 7
0
    def make_E(self):
        #print("Creating ECNF object for {}".format(self.label))
        #sys.stdout.flush()
        K = self.field.K()

        # a-invariants
        self.ainvs = parse_ainvs(K,self.ainvs)
        self.latex_ainvs = web_latex(self.ainvs)
        self.numb = str(self.number)

        # Conductor, discriminant, j-invariant
        if self.conductor_norm==1:
            N = K.ideal(1)
        else:
            N = ideal_from_string(K,self.conductor_ideal)
        # The following can trigger expensive computations!
        #self.cond = web_latex(N)
        self.cond = pretty_ideal(N)
        self.cond_norm = web_latex(self.conductor_norm)
        local_data = self.local_data

        # NB badprimes is a list of primes which divide the
        # discriminant of this model.  At most one of these might
        # actually be a prime of good reduction, if the curve has no
        # global minimal model.
        badprimes = [ideal_from_string(K,ld['p']) for ld in local_data]
        badnorms = [ZZ(ld['normp']) for ld in local_data]
        mindisc_ords = [ld['ord_disc'] for ld in local_data]

        # Assumption: the curve models stored in the database are
        # either global minimal models or minimal at all but one
        # prime, so the list here has length 0 or 1:

        self.non_min_primes = [ideal_from_string(K,P) for P in self.non_min_p]
        self.is_minimal = (len(self.non_min_primes) == 0)
        self.has_minimal_model = self.is_minimal
        disc_ords = [ld['ord_disc'] for ld in local_data]
        if not self.is_minimal:
            Pmin = self.non_min_primes[0]
            P_index = badprimes.index(Pmin)
            self.non_min_prime = pretty_ideal(Pmin)
            disc_ords[P_index] += 12

        if self.conductor_norm == 1:  # since the factorization of (1) displays as "1"
            self.fact_cond = self.cond
            self.fact_cond_norm = '1'
        else:
            Nfac = Factorization([(P,ld['ord_cond']) for P,ld in zip(badprimes,local_data)])
            self.fact_cond = web_latex_ideal_fact(Nfac)
            Nnormfac = Factorization([(q,ld['ord_cond']) for q,ld in zip(badnorms,local_data)])
            self.fact_cond_norm = web_latex(Nnormfac)

        # D is the discriminant ideal of the model
        D = prod([P**e for P,e in zip(badprimes,disc_ords)], K.ideal(1))
        self.disc = pretty_ideal(D)
        Dnorm = D.norm()
        self.disc_norm = web_latex(Dnorm)
        if Dnorm == 1:  # since the factorization of (1) displays as "1"
            self.fact_disc = self.disc
            self.fact_disc_norm = '1'
        else:
            Dfac = Factorization([(P,e) for P,e in zip(badprimes,disc_ords)])
            self.fact_disc = web_latex_ideal_fact(Dfac)
            Dnormfac = Factorization([(q,e) for q,e in zip(badnorms,disc_ords)])
            self.fact_disc_norm = web_latex(Dnormfac)

        if not self.is_minimal:
            Dmin = ideal_from_string(K,self.minD)
            self.mindisc = pretty_ideal(Dmin)
            Dmin_norm = Dmin.norm()
            self.mindisc_norm = web_latex(Dmin_norm)
            if Dmin_norm == 1:  # since the factorization of (1) displays as "1"
                self.fact_mindisc = self.mindisc
                self.fact_mindisc_norm = self.mindisc
            else:
                Dminfac = Factorization([(P,e) for P,edd in zip(badprimes,mindisc_ords)])
                self.fact_mindisc = web_latex_ideal_fact(Dminfac)
                Dminnormfac = Factorization([(q,e) for q,e in zip(badnorms,mindisc_ords)])
                self.fact_mindisc_norm = web_latex(Dminnormfac)

        j = self.field.parse_NFelt(self.jinv)
        # if j:
        #     d = j.denominator()
        #     n = d * j  # numerator exists for quadratic fields only!
        #     g = GCD(list(n))
        #     n1 = n / g
        #     self.j = web_latex(n1)
        #     if d != 1:
        #         if n1 > 1:
        #         # self.j = "("+self.j+")\(/\)"+web_latex(d)
        #             self.j = web_latex(r"\frac{%s}{%s}" % (self.j, d))
        #         else:
        #             self.j = web_latex(d)
        #         if g > 1:
        #             if n1 > 1:
        #                 self.j = web_latex(g) + self.j
        #             else:
        #                 self.j = web_latex(g)
        self.j = web_latex(j)

        self.fact_j = None
        # See issue 1258: some j factorizations work but take too long
        # (e.g. EllipticCurve/6.6.371293.1/1.1/a/1).  Note that we do
        # store the factorization of the denominator of j and display
        # that, which is the most interesting part.

        # Images of Galois representations

        if not hasattr(self,'galois_images'):
            #print "No Galois image data"
            self.galois_images = "?"
            self.non_surjective_primes = "?"
            self.galois_data = []
        else:
            self.galois_data = [{'p': p,'image': im }
                                for p,im in zip(self.non_surjective_primes,
                                                self.galois_images)]

        # CM and End(E)
        self.cm_bool = "no"
        self.End = "\(\Z\)"
        if self.cm:
            self.rational_cm = K(self.cm).is_square()
            self.cm_sqf = ZZ(self.cm).squarefree_part()
            self.cm_bool = "yes (\(%s\))" % self.cm
            if self.cm % 4 == 0:
                d4 = ZZ(self.cm) // 4
                self.End = "\(\Z[\sqrt{%s}]\)" % (d4)
            else:
                self.End = "\(\Z[(1+\sqrt{%s})/2]\)" % self.cm

        # Galois images in CM case:
        if self.cm and self.galois_images != '?':
            self.cm_ramp = [p for p in ZZ(self.cm).support() if not p in self.non_surjective_primes]
            self.cm_nramp = len(self.cm_ramp)
            if self.cm_nramp==1:
                self.cm_ramp = self.cm_ramp[0]
            else:
                self.cm_ramp = ", ".join([str(p) for p in self.cm_ramp])

        # Sato-Tate:
        # The lines below will need to change once we have curves over non-quadratic fields
        # that contain the Hilbert class field of an imaginary quadratic field
        if self.cm:
            if self.signature == [0,1] and ZZ(-self.abs_disc*self.cm).is_square():
                self.ST = st_link_by_name(1,2,'U(1)')
            else:
                self.ST = st_link_by_name(1,2,'N(U(1))')
        else:
            self.ST = st_link_by_name(1,2,'SU(2)')

        # Q-curve / Base change
        self.qc = self.q_curve
        if self.qc == "?":
            self.qc = "not determined"
        elif self.qc == True:
            self.qc = "yes"
        elif self.qc == False:
            self.qc = "no"
        else: # just in case
            self.qc = "not determined"

        # Torsion
        self.ntors = web_latex(self.torsion_order)
        self.tr = len(self.torsion_structure)
        if self.tr == 0:
            self.tor_struct_pretty = "Trivial"
        if self.tr == 1:
            self.tor_struct_pretty = "\(\Z/%s\Z\)" % self.torsion_structure[0]
        if self.tr == 2:
            self.tor_struct_pretty = r"\(\Z/%s\Z\times\Z/%s\Z\)" % tuple(self.torsion_structure)

        torsion_gens = [parse_point(K,P) for P in self.torsion_gens]
        self.torsion_gens = ",".join([web_point(P) for P in torsion_gens])

        # Rank or bounds
        try:
            self.rk = web_latex(self.rank)
        except AttributeError:
            self.rk = "?"
        try:
            self.rk_bnds = "%s...%s" % tuple(self.rank_bounds)
        except AttributeError:
            self.rank_bounds = [0, Infinity]
            self.rk_bnds = "not available"

        # Generators
        try:
            gens = [parse_point(K,P) for P in self.gens]
            self.gens = ", ".join([web_point(P) for P in gens])
            if self.rk == "?":
                self.reg = "not available"
            else:
                if gens:
                    try:
                        self.reg = self.reg
                    except AttributeError:
                        self.reg = "not available"
                    pass # self.reg already set
                else:
                    self.reg = 1  # otherwise we only get 1.00000...

        except AttributeError:
            self.gens = "not available"
            self.reg = "not available"
            try:
                if self.rank == 0:
                    self.reg = 1
            except AttributeError:
                pass

        # Local data
        for P,ld in zip(badprimes,local_data):
            ld['p'] = web_latex(P)
            ld['norm'] = P.norm()
            ld['kod'] = ld['kod'].replace('\\\\', '\\')
            ld['kod'] = web_latex(ld['kod']).replace('$', '')

        # URLs of self and related objects:
        self.urls = {}
        # It's useful to be able to use this class out of context, when calling url_for will fail:
        try:
            self.urls['curve'] = url_for(".show_ecnf", nf=self.field_label, conductor_label=quote(self.conductor_label), class_label=self.iso_label, number=self.number)
        except RuntimeError:
            return
        self.urls['class'] = url_for(".show_ecnf_isoclass", nf=self.field_label, conductor_label=quote(self.conductor_label), class_label=self.iso_label)
        self.urls['conductor'] = url_for(".show_ecnf_conductor", nf=self.field_label, conductor_label=quote(self.conductor_label))
        self.urls['field'] = url_for(".show_ecnf1", nf=self.field_label)

        # Isogeny information

        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:
            self.isogeny_degrees = " and ".join(isodegs)
        else:
            self.isogeny_degrees = " and ".join([", ".join(isodegs[:-1]),isodegs[-1]])


        sig = self.signature
        totally_real = sig[1] == 0
        imag_quadratic = sig == [0,1]

        if totally_real:
            self.hmf_label = "-".join([self.field.label, self.conductor_label, self.iso_label])
            self.urls['hmf'] = url_for('hmf.render_hmf_webpage', field_label=self.field.label, label=self.hmf_label)
            if sig[0] <= 2:
                self.urls['Lfunction'] = url_for("l_functions.l_function_ecnf_page", field_label=self.field_label, conductor_label=self.conductor_label, isogeny_class_label=self.iso_label)
            elif self.abs_disc ** 2 * self.conductor_norm < 70000:
                # we shouldn't trust the Lfun computed on the fly for large conductor
                self.urls['Lfunction'] = url_for("l_functions.l_function_hmf_page", field=self.field_label, label=self.hmf_label, character='0', number='0')

        if imag_quadratic:
            self.bmf_label = "-".join([self.field.label, self.conductor_label, self.iso_label])
            self.bmf_url = url_for('bmf.render_bmf_webpage', field_label=self.field_label, level_label=self.conductor_label, label_suffix=self.iso_label)
            self.urls['Lfunction'] = url_for("l_functions.l_function_ecnf_page", field_label=self.field_label, conductor_label=self.conductor_label, isogeny_class_label=self.iso_label)

        self.friends = []
        self.friends += [('Isogeny class ' + self.short_class_label, self.urls['class'])]
        self.friends += [('Twists', url_for('ecnf.index', field=self.field_label, jinv=rename_j(j)))]
        if totally_real:
            self.friends += [('Hilbert Modular Form ' + self.hmf_label, self.urls['hmf'])]

        if imag_quadratic:
            if "CM" in self.label:
                self.friends += [('Bianchi Modular Form is not cuspidal', '')]
            else:
                if db.bmf_forms.label_exists(self.bmf_label):
                    self.friends += [('Bianchi Modular Form %s' % self.bmf_label, self.bmf_url)]
                else:
                    self.friends += [('(Bianchi Modular Form %s)' % self.bmf_label, '')]

        if 'Lfunction' in self.urls:
            self.friends += [('L-function', self.urls['Lfunction'])]
        else:
            self.friends += [('L-function not available', "")]

        self.properties = [
            ('Base field', self.field.field_pretty()),
            ('Label', self.label)]

        # Plot
        if K.signature()[0]:
            self.plot = encode_plot(EC_nf_plot(K,self.ainvs, self.field.generator_name()))
            self.plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format(self.plot)
            self.properties += [(None, self.plot_link)]

        self.properties += [
            ('Conductor', self.cond),
            ('Conductor norm', self.cond_norm),
            # See issue #796 for why this is hidden (can be very large)
            # ('j-invariant', self.j),
            ('CM', self.cm_bool)]

        if self.base_change:
            self.properties += [('base-change', 'yes: %s' % ','.join([str(lab) for lab in self.base_change]))]
        else:
            self.base_change = []  # in case it was False instead of []
            self.properties += [('base-change', 'no')]
        self.properties += [('Q-curve', self.qc)]

        r = self.rk
        if r == "?":
            r = self.rk_bnds
        self.properties += [
            ('Torsion order', self.ntors),
            ('Rank', r),
        ]

        for E0 in self.base_change:
            self.friends += [('Base-change of %s /\(\Q\)' % E0, url_for("ec.by_ec_label", label=E0))]

        self._code = None # will be set if needed by get_code()

        self.downloads = [('Download all stored data', url_for(".download_ECNF_all", nf=self.field_label, conductor_label=quote(self.conductor_label), class_label=self.iso_label, number=self.number))]
        for lang in [["Magma","magma"], ["SageMath","sage"], ["GP", "gp"]]:
            self.downloads.append(('Download {} code'.format(lang[0]),
                                   url_for(".ecnf_code_download", nf=self.field_label, conductor_label=quote(self.conductor_label),
                                           class_label=self.iso_label, number=self.number, download_type=lang[1])))
Ejemplo n.º 8
0
    def make_curve(self):
        # To start with the data fields of self are just those from the
        # databases.  We reformat these, while computing some further (easy)
        # data about the curve on the fly.

        # Initialize data:
        data = self.data = {}
        endodata = self.endodata = {}

        # Polish data from database before putting it into the data dictionary:
        disc = ZZ(self.disc_sign) * ZZ(self.disc_key[3:])
        # to deal with disc_key, uncomment line above and comment line below
        #disc = ZZ(self.disc_sign) * ZZ(self.abs_disc)
        data['disc'] = disc
        data['cond'] = ZZ(self.cond)
        data['min_eqn'] = self.min_eqn
        data['min_eqn_display'] = list_to_min_eqn(self.min_eqn)
        data['disc_factor_latex'] = web_latex(factor(data['disc']))
        data['cond_factor_latex'] = web_latex(factor(int(self.cond)))
        data['aut_grp'] = groupid_to_meaningful(self.aut_grp)
        data['geom_aut_grp'] = groupid_to_meaningful(self.geom_aut_grp)
        data['igusa_clebsch'] = [ZZ(a) for a in self.igusa_clebsch]
        data['igusa'] = [ZZ(a) for a in self.igusa]
        data['g2'] = self.g2inv
        data['ic_norm'] = data['igusa_clebsch']
        data['igusa_norm'] = data['igusa']
        # Should we ever want to normalize the invariants further, then
        # uncomment the following lines:
        #data['ic_norm'] = normalize_invariants(data['igusa_clebsch'], [2, 4, 6,
        #    10])
        #data['igusa_norm'] = normalize_invariants(data['igusa'], [2, 4, 6, 8,
        #    10])
        data['ic_norm_factor_latex'] = [web_latex(zfactor(i)) for i in
            data['ic_norm']]
        data['igusa_norm_factor_latex'] = [ web_latex(zfactor(j)) for j in
            data['igusa_norm'] ]
        data['num_rat_wpts'] = ZZ(self.num_rat_wpts)
        data['two_selmer_rank'] = ZZ(self.two_selmer_rank)
        data['analytic_rank'] = ZZ(self.analytic_rank)
        data['has_square_sha'] = "square" if self.has_square_sha else "twice a square"
        data['locally_solvable'] = "yes" if self.locally_solvable else "no"
        if len(self.torsion) == 0:
            data['tor_struct'] = '\mathrm{trivial}'
        else:
            tor_struct = [ ZZ(a) for a in self.torsion ]
            data['tor_struct'] = ' \\times '.join([ '\Z/{%s}\Z' % n for n in
                tor_struct ])

        # Data derived from Sato-Tate group:
        isogeny_class = g2cdb().isogeny_classes.find_one({'label' :
            isog_label(self.label)})
        st_data = get_st_data(isogeny_class)
        for key in st_data.keys():
            data[key] = st_data[key]

        # GL_2 statement over the base field
        endodata['gl2_statement_base'] = \
            gl2_statement_base(self.factorsRR_base, r'\(\Q\)')

        # NOTE: In what follows there is some copying of code and data that is
        # stupid from the point of view of efficiency but likely better from
        # that of maintenance.

        # Endomorphism data over QQ:
        endodata['factorsQQ_base'] = self.factorsQQ_base
        endodata['factorsRR_base'] = self.factorsRR_base
        endodata['ring_base'] = self.ring_base
        endodata['endo_statement_base'] = \
            """Endomorphism ring over \(\Q\):""" + \
            endo_statement(endodata['factorsQQ_base'],
                endodata['factorsRR_base'], endodata['ring_base'], r'')
        # Field of definition data:
        endodata['fod_label'] = self.fod_label
        endodata['fod_poly'] = intlist_to_poly(self.fod_coeffs)
        endodata['fod_statement'] = fod_statement(endodata['fod_label'],
            endodata['fod_poly'])
        # Endomorphism data over QQbar:
        endodata['factorsQQ_geom'] = self.factorsQQ_geom
        endodata['factorsRR_geom'] = self.factorsRR_geom
        endodata['ring_geom'] = self.ring_geom
        if self.fod_label != '1.1.1.1':
            endodata['gl2_statement_geom'] = \
                gl2_statement_base(self.factorsRR_geom, r'\(\overline{\Q}\)')
            endodata['endo_statement_geom'] = \
            """Endomorphism ring over \(\overline{\Q}\):""" + \
            endo_statement(endodata['factorsQQ_geom'],
                endodata['factorsRR_geom'], endodata['ring_geom'],
                r'\overline{\Q}')

        # Full endomorphism lattice minus entries already treated:
        N = len(self.lattice)
        endodata['lattice'] = (self.lattice)[1:N - 1]
        if endodata['lattice']:
            endodata['lattice_statement_preamble'] = \
                lattice_statement_preamble()
            endodata['lattice_statement'] = \
                lattice_statement(endodata['lattice'])

        # Splitting field description:
        #endodata['is_simple_base'] = self.is_simple_base
        endodata['is_simple_geom'] = self.is_simple_geom
        endodata['spl_fod_label'] = self.spl_fod_label
        endodata['spl_fod_poly'] = intlist_to_poly(self.spl_fod_coeffs)
        endodata['spl_fod_statement'] = \
            spl_fod_statement(endodata['is_simple_geom'],
                endodata['spl_fod_label'], endodata['spl_fod_poly'])

        # Isogeny factors:
        if not endodata['is_simple_geom']:
            endodata['spl_facs_coeffs'] = self.spl_facs_coeffs
            # This could be done non-uniformly as well... later.
            if len(self.spl_facs_labels) == len(self.spl_facs_coeffs):
                endodata['spl_facs_labels'] = self.spl_facs_labels
            else:
                endodata['spl_facs_labels'] = ['' for coeffs in
                    self.spl_facs_coeffs]
            endodata['spl_facs_condnorms'] = self.spl_facs_condnorms
            endodata['spl_statement'] = \
                spl_statement(endodata['spl_facs_coeffs'],
                    endodata['spl_facs_labels'],
                    endodata['spl_facs_condnorms'])

        # Title
        self.title = "Genus 2 Curve %s" % (self.label)

        # Lady Gaga box
        self.plot = encode_plot(eqn_list_to_curve_plot(self.min_eqn))
        self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
        self.properties = [
                ('Label', self.label),
               (None, self.plot_link),
               ('Conductor','%s' % self.cond),
               ('Discriminant', '%s' % data['disc']),
               ('Invariants', '%s </br> %s </br> %s </br> %s' % tuple(data['ic_norm'])),
               ('Sato-Tate group', data['st_group_href']),
               ('\(%s\)' % data['real_geom_end_alg_disp'][0],
                '\(%s\)' % data['real_geom_end_alg_disp'][1]),
               ('\(\mathrm{GL}_2\)-type','%s' % data['is_gl2_type_name'])]
        x = self.label.split('.')[1]
        self.friends = [
            ('Isogeny class %s' % isog_label(self.label),
                url_for(".by_double_iso_label",
                    conductor = self.cond,
                    iso_label = x)),
            ('L-function',
                url_for("l_functions.l_function_genus2_page",
                    cond=self.cond,x=x)),
            ('Twists',
                url_for(".index_Q",
                    g20 = self.g2inv[0],
                    g21 = self.g2inv[1],
                    g22 = self.g2inv[2]))
            #('Siegel modular form someday', '.')
            ]

        if not endodata['is_simple_geom']:
            self.friends += [('Elliptic curve %s' % lab,url_for_ec(lab)) for lab in endodata['spl_facs_labels'] if lab != '']
        #self.downloads = [('Download all stored data', '.')]

        # Breadcrumbs
        iso = self.label.split('.')[1]
        num = '.'.join(self.label.split('.')[2:4])
        self.bread = [
             ('Genus 2 Curves', url_for(".index")),
             ('$\Q$', url_for(".index_Q")),
             ('%s' % self.cond, url_for(".by_conductor", conductor=self.cond)),
             ('%s' % iso, url_for(".by_double_iso_label", conductor=self.cond,
                 iso_label=iso)),
             ('Genus 2 curve %s' % num, url_for(".by_g2c_label",
                 label=self.label))
             ]

        # Make code that is used on the page:
        self.make_code_snippets()
Ejemplo n.º 9
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']

        # 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({'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)

        if len(bad_primes)>1:
            bsd['tamagawa_factors'] = r' \cdot '.join(str(c.factor()) for c in tamagawa_numbers)
        else:
            bsd['tamagawa_factors'] = ''
        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.make_code_snippets()

        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)),
            ('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', label=self.lmfdb_iso)),
            ('Symmetric 4th power L-function', url_for("l_functions.l_function_ec_sym_page", power='4', label=self.lmfdb_iso)),
            ('Modular form ' + self.lmfdb_iso.replace('.', '.2'), url_for("emf.render_elliptic_modular_forms", level=int(N), weight=2, character=0, label=iso))]

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

        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,' ')]
Ejemplo n.º 10
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
        # and compute some further (easy) data about it.
        #

        # Weierstrass equation

        data = self.data = {}

        disc = ZZ(self.disc_sign) * ZZ(self.disc_key[3:]) 
        # to deal with disc_key, uncomment line above and remove line below
        #disc = ZZ(self.disc_sign) * ZZ(self.abs_disc)
        data['disc'] = disc
        data['cond'] = ZZ(self.cond)
        data['min_eqn'] = list_to_min_eqn(self.min_eqn)
        data['disc_factor_latex'] = web_latex(factor(data['disc']))
        data['cond_factor_latex'] = web_latex(factor(int(self.cond)))
        data['aut_grp'] = groupid_to_meaningful(self.aut_grp)
        data['geom_aut_grp'] = groupid_to_meaningful(self.geom_aut_grp)
        data['igusa_clebsch'] = [ZZ(a)  for a in self.igusa_clebsch]
        if len(self.torsion) == 0:
            data['tor_struct'] = '\mathrm{trivial}'
        else:
            tor_struct = [ZZ(a)  for a in self.torsion]
            data['tor_struct'] = ' \\times '.join(['\Z/{%s}\Z' % n for n in tor_struct])
        isogeny_class = db_g2c().isogeny_classes.find_one({'label' : isog_label(self.label)})

        for endalgtype in ['end_ring', 'rat_end_alg', 'real_end_alg', 'geom_end_ring', 'rat_geom_end_alg', 'real_geom_end_alg']:
            if endalgtype in isogeny_class:
                data[endalgtype + '_name'] = end_alg_name(isogeny_class[endalgtype])
            else:
                data[endalgtype + '_name'] = ''

        data['geom_end_field'] = isogeny_class['geom_end_field']
        if data['geom_end_field'] <> '':
            data['geom_end_field_name'] = field_pretty(data['geom_end_field'])
        else:
            data['geom_end_field_name'] = ''        

        data['st_group_name'] = st_group_name(isogeny_class['st_group'])
        if isogeny_class['is_gl2_type']:
            data['is_gl2_type_name'] = 'yes'
        else:
            data['is_gl2_type_name'] = 'no'
        if 'is_simple' in isogeny_class:
            if isogeny_class['is_simple']:
                data['is_simple_name'] = 'yes'
            else:
                data['is_simple_name'] = 'no'
        else:
            data['is_simple_name'] = '?'
        if 'is_geom_simple' in isogeny_class:
            if isogeny_class['is_geom_simple']:
                data['is_geom_simple_name'] = 'yes'
            else:
                data['is_geom_simple_name'] = 'no'
        else:
            data['is_geom_simple_name'] = '?'

        x = self.label.split('.')[1]
        self.friends = [
            ('Isogeny class %s' % isog_label(self.label), url_for(".by_double_iso_label", conductor = self.cond, iso_label = x)),
            ('L-function', url_for("l_functions.l_function_genus2_page", cond=self.cond,x=x)),
            ('Siegel modular form someday', '.')]
        self.downloads = [
             ('Download Euler factors', '.')]
        iso = self.label.split('.')[1]
        num = '.'.join(self.label.split('.')[2:4])
        self.plot = encode_plot(eqn_list_to_curve_plot(self.min_eqn))
        self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
        self.properties = [('Label', self.label),
                           (None, self.plot_link),
                           ('Conductor','%s' % self.cond),
                           ('Discriminant', '%s' % data['disc']),
                           ('Invariants', '%s </br> %s </br> %s </br> %s'% tuple(data['igusa_clebsch'])), 
                           ('Sato-Tate group', '\(%s\)' % data['st_group_name']), 
                           ('\(\mathrm{End}(J_{\overline{\Q}}) \otimes \R\)','\(%s\)' % data['real_geom_end_alg_name']),
                           ('\(\mathrm{GL}_2\)-type','%s' % data['is_gl2_type_name'])]
        self.title = "Genus 2 Curve %s" % (self.label)
        self.bread = [
             ('Genus 2 Curves', url_for(".index")),
             ('$\Q$', url_for(".index_Q")),
             ('%s' % self.cond, url_for(".by_conductor", conductor=self.cond)),
             ('%s' % iso, url_for(".by_double_iso_label", conductor=self.cond, iso_label=iso)),
             ('Genus 2 curve %s' % num, url_for(".by_g2c_label", label=self.label))]
Ejemplo n.º 11
0
    def make_object(self, curve, endo, tama, ratpts, 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'] = curve['Lhash']
        data['cond'] = ZZ(curve['cond'])
        data['cond_factor_latex'] = web_latex(factor(int(data['cond'])))
        data['analytic_rank'] = ZZ(curve['analytic_rank'])
        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['disc_key'][3:]) # use disc_key rather than abs_disc (will work when abs_disc > 2^63)
            data['disc'] = curve['disc_sign'] * curve['abs_disc']
            data['min_eqn'] = literal_eval(curve['eqn'])
            data['min_eqn_display'] = list_to_min_eqn(data['min_eqn'])
            data['disc_factor_latex'] = web_latex(factor(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(zfactor(i)) for i in data['igusa_clebsch']]
            data['igusa_factor_latex'] = [ web_latex(zfactor(j)) for j in data['igusa'] ]
            data['aut_grp_id'] = curve['aut_grp_id']
            data['geom_aut_grp_id'] = curve['geom_aut_grp_id']
            data['num_rat_wpts'] = ZZ(curve['num_rat_wpts'])
            data['two_selmer_rank'] = ZZ(curve['two_selmer_rank'])
            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['torsion_order'] = curve['torsion_order']
            data['torsion_factors'] = [ ZZ(a) for a in literal_eval(curve['torsion_subgroup']) ]
            if len(data['torsion_factors']) == 0:
                data['torsion_subgroup'] = '\mathrm{trivial}'
            else:
                data['torsion_subgroup'] = ' \\times '.join([ '\Z/{%s}\Z' % n for n in data['torsion_factors'] ])
            data['end_ring_base'] = endo['ring_base']
            data['end_ring_geom'] = endo['ring_geom']
            data['tama'] = ''
            for i in range(tama.count()):
            	item = tama.next()
            	if item['tamagawa_number'] > 0:
            		tamgwnr = str(item['tamagawa_number'])
            	else:
            		tamgwnr = 'N/A'
            	data['tama'] += tamgwnr + ' (p = ' + str(item['p']) + ')'
            	if (i+1 < tama.count()):
            		data['tama'] += ', '
            if ratpts:
                if len(ratpts['rat_pts']):
                    data['rat_pts'] = ',  '.join(web_latex('(' +' : '.join(P) + ')') for P in ratpts['rat_pts'])
                data['rat_pts_v'] =  2 if ratpts['rat_pts_v'] else 1
                # data['mw_rank'] = ratpts['mw_rank']
                # data['mw_rank_v'] = ratpts['mw_rank_v']
            else:
                data['rat_pts_v'] = 0
            if curve['two_torsion_field'][0]:
                data['two_torsion_field_knowl'] = nf_display_knowl (curve['two_torsion_field'][0], getDBConnection(), field_pretty(curve['two_torsion_field'][0]))
            else:
                t = curve['two_torsion_field']
                data['two_torsion_field_knowl'] = """splitting field of \(%s\) with Galois group %s"""%(intlist_to_poly(t[1]),group_display_knowl(t[2][0],t[2][1],getDBConnection()))
        else:
            # invariants specific to isogeny class
            curves_data = g2c_db_curves().find({"class" : curve['class']},{'_id':int(0),'label':int(1),'eqn':int(1),'disc_key':int(1)}).sort([("disc_key", ASCENDING), ("label", ASCENDING)])
            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" : list_to_min_eqn(literal_eval(c['eqn'])), "url": url_for_curve_label(c['label'])} for c in curves_data ]
            lfunc_data = g2c_db_lfunction_by_hash(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'] = """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'] = """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'] = end_alg_name(curve['real_geom_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:
            self.plot = encode_plot(eqn_list_to_curve_plot(data['min_eqn'], data['rat_pts'].split(',') if 'rat_pts' in data else []))
            plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format(self.plot)

            properties += [
                (None, plot_link),
                ('Conductor',str(data['cond'])),
                ('Discriminant', str(data['disc'])),
                ]
        properties += [
            ('Sato-Tate group', data['st_group_link']),
            ('\(\\End(J_{\\overline{\\Q}}) \\otimes \\R\)', '\(%s\)' % data['real_geom_end_alg_name']),
            ('\(\\overline{\\Q}\)-simple', bool_pretty(data['is_simple_geom'])),
            ('\(\mathrm{GL}_2\)-type', bool_pretty(data['is_gl2_type'])),
            ]

        # Friends
        self.friends = friends = [('L-function', data['lfunc_url'])]
        if is_curve:
            friends.append(('Isogeny class %s.%s' % (data['slabel'][0], data['slabel'][1]), url_for(".by_url_isogeny_class_label", cond=data['slabel'][0], alpha=data['slabel'][1])))
        for friend in g2c_db_lfunction_instances().find({'Lhash':data['Lhash']},{'_id':False,'url':True}):
            if 'url' in friend:
                add_friend (friends, lfunction_friend_from_url(friend['url']))
            if 'urls' in friend:
                for url in friends['urls']:
                    add_friend (friends, lfunction_friend_from_url(friend['url']))
        if 'split_labels' in data:
            for friend_label in data['split_labels']:
                if is_curve:
                    add_friend (friends, ("Elliptic curve " + friend_label, url_for_ec(friend_label)))
                else:
                    add_friend (friends, ("EC isogeny class " + ec_label_class(friend_label), url_for_ec_class(friend_label)))
        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]))))

        # Breadcrumbs
        self.bread = bread = [
             ('Genus 2 Curves', url_for(".index")),
             ('$\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
        code['curve'] = {'sage':'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s))'%(data['min_eqn'][0],data['min_eqn'][1]),
                              'magma':'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);'%(data['min_eqn'][0],data['min_eqn'][1])}
        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['igusa_clebsch'] = {'sage':'C.igusa_clebsch_invariants(); [factor(a) for a in _]',
                                      'magma':'IgusaClebschInvariants(C); [Factorization(Integers()!a): a in $1];'}
        code['igusa'] = {'magma':'IgusaInvariants(C); [Factorization(Integers()!a): a in $1];'}
        code['g2'] = {'magma':'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']]) + '];' }
        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);'}
Ejemplo n.º 12
0
    def make_curve(self):
        # To start with the data fields of self are just those from the
        # databases.  We reformat these, while computing some further (easy)
        # data about the curve on the fly.

        # Initialize data:
        data = self.data = {}
        endodata = self.endodata = {}

        # Polish data from database before putting it into the data dictionary:
        disc = ZZ(self.disc_sign) * ZZ(self.disc_key[3:])
        # to deal with disc_key, uncomment line above and comment line below
        #disc = ZZ(self.disc_sign) * ZZ(self.abs_disc)
        data['disc'] = disc
        data['abs_disc'] = ZZ(self.disc_key[3:])
        data['cond'] = ZZ(self.cond)
        data['min_eqn'] = self.min_eqn
        data['min_eqn_display'] = list_to_min_eqn(self.min_eqn)
        data['disc_factor_latex'] = web_latex(factor(data['disc']))
        data['cond_factor_latex'] = web_latex(factor(int(self.cond)))
        data['aut_grp_id'] = self.aut_grp_id
        data['geom_aut_grp_id'] = self.geom_aut_grp_id
        data['igusa_clebsch'] = [ZZ(a) for a in self.igusa_clebsch]
        data['igusa'] = [ZZ(a) for a in self.igusa]
        data['g2'] = self.g2inv
        data['ic_norm'] = data['igusa_clebsch']
        data['igusa_norm'] = data['igusa']
        # Should we ever want to normalize the invariants further, then
        # uncomment the following lines:
        #data['ic_norm'] = normalize_invariants(data['igusa_clebsch'], [2, 4, 6,
        #    10])
        #data['igusa_norm'] = normalize_invariants(data['igusa'], [2, 4, 6, 8,
        #    10])
        data['ic_norm_factor_latex'] = [web_latex(zfactor(i)) for i in data['ic_norm']]
        data['igusa_norm_factor_latex'] = [ web_latex(zfactor(j)) for j in data['igusa_norm'] ]
        data['num_rat_wpts'] = ZZ(self.num_rat_wpts)
        data['two_selmer_rank'] = ZZ(self.two_selmer_rank)
        data['analytic_rank'] = ZZ(self.analytic_rank)
        data['has_square_sha'] = "square" if self.has_square_sha else "twice a square"
        data['locally_solvable'] = "yes" if self.locally_solvable else "no"
        if len(self.torsion) == 0:
            data['tor_struct'] = '\mathrm{trivial}'
        else:
            tor_struct = [ ZZ(a) for a in self.torsion ]
            data['tor_struct'] = ' \\times '.join([ '\Z/{%s}\Z' % n for n in tor_struct ])

        # Data derived from Sato-Tate group:
        isogeny_class = g2cdb().isogeny_classes.find_one({'label' : isogeny_class_label(self.label)})
        st_data = get_st_data(isogeny_class)
        for key in st_data.keys():
            data[key] = st_data[key]

        # GL_2 statement over the base field
        endodata['gl2_statement_base'] = \
            gl2_statement_base(self.factorsRR_base, r'\(\Q\)')

        # NOTE: In what follows there is some copying of code and data that is
        # stupid from the point of view of efficiency but likely better from
        # that of maintenance.

        # Endomorphism data over QQ:
        endodata['factorsQQ_base'] = self.factorsQQ_base
        endodata['factorsRR_base'] = self.factorsRR_base
        endodata['ring_base'] = self.ring_base
        endodata['endo_statement_base'] = \
            """Endomorphism ring over \(\Q\):""" + \
            endo_statement(endodata['factorsQQ_base'],
                endodata['factorsRR_base'], endodata['ring_base'], r'')
        # Field of definition data:
        endodata['fod_label'] = self.fod_label
        endodata['fod_poly'] = intlist_to_poly(self.fod_coeffs)
        endodata['fod_statement'] = fod_statement(endodata['fod_label'],
            endodata['fod_poly'])
        # Endomorphism data over QQbar:
        endodata['factorsQQ_geom'] = self.factorsQQ_geom
        endodata['factorsRR_geom'] = self.factorsRR_geom
        endodata['ring_geom'] = self.ring_geom
        if self.fod_label != '1.1.1.1':
            endodata['gl2_statement_geom'] = \
                gl2_statement_base(self.factorsRR_geom, r'\(\overline{\Q}\)')
            endodata['endo_statement_geom'] = \
                """Endomorphism ring over \(\overline{\Q}\):""" + \
                endo_statement(
                    endodata['factorsQQ_geom'],
                    endodata['factorsRR_geom'],
                    endodata['ring_geom'],
                    r'\overline{\Q}')

        # Full endomorphism lattice minus entries already treated:
        N = len(self.lattice)
        endodata['lattice'] = (self.lattice)[1:N - 1]
        if endodata['lattice']:
            endodata['lattice_statement_preamble'] = lattice_statement_preamble()
            endodata['lattice_statement'] = lattice_statement(endodata['lattice'])

        # Splitting field description:
        #endodata['is_simple_base'] = self.is_simple_base
        endodata['is_simple_geom'] = self.is_simple_geom
        endodata['spl_fod_label'] = self.spl_fod_label
        endodata['spl_fod_poly'] = intlist_to_poly(self.spl_fod_coeffs)
        endodata['spl_fod_statement'] = spl_fod_statement(
            endodata['is_simple_geom'],
            endodata['spl_fod_label'], endodata['spl_fod_poly'])

        # Isogeny factors:
        if not endodata['is_simple_geom']:
            endodata['spl_facs_coeffs'] = self.spl_facs_coeffs
            # This could be done non-uniformly as well... later.
            if len(self.spl_facs_labels) == len(self.spl_facs_coeffs):
                endodata['spl_facs_labels'] = self.spl_facs_labels
            else:
                endodata['spl_facs_labels'] = ['' for coeffs in
                    self.spl_facs_coeffs]
            endodata['spl_facs_condnorms'] = self.spl_facs_condnorms
            endodata['spl_statement'] = spl_statement(
                endodata['spl_facs_coeffs'],
                endodata['spl_facs_labels'],
                endodata['spl_facs_condnorms'])

        # Title
        self.title = "Genus 2 Curve %s" % (self.label)

        alpha = self.label.split('.')[1]
        num = self.label.split('.')[3]

        # Lady Gaga box
        self.plot = encode_plot(eqn_list_to_curve_plot(self.min_eqn))
        self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
        self.properties = (
            ('Label', self.label),
            (None, self.plot_link),
            ('Conductor','%s' % self.cond),
            ('Discriminant', '%s' % data['disc']),
            ('Invariants', '%s </br> %s </br> %s </br> %s' % tuple(data['ic_norm'])),
            ('Sato-Tate group', data['st_group_href']),
            ('\(%s\)' % data['real_geom_end_alg_disp'][0],
             '\(%s\)' % data['real_geom_end_alg_disp'][1]),
            ('\(\mathrm{GL}_2\)-type','%s' % data['is_gl2_type_name'])
            )
        self.friends = [
            ('Isogeny class %s' % isogeny_class_label(self.label),
             url_for(".by_url_isogeny_class_label", cond = self.cond,alpha =alpha)),
            ('L-function', url_for("l_functions.l_function_genus2_page", cond=self.cond,x=alpha)),
            ('Twists', url_for(".index_Q", g20 = self.g2inv[0], g21 = self.g2inv[1], g22 = self.g2inv[2]))
            #('Siegel modular form someday', '.')
            ]

        if not endodata['is_simple_geom']:
            self.friends += [('Elliptic curve %s' % lab,url_for_ec(lab)) for lab in endodata['spl_facs_labels'] if lab != '']
        #self.downloads = [('Download all stored data', '.')]

        # Breadcrumbs
        self.bread = (
             ('Genus 2 Curves', url_for(".index")),
             ('$\Q$', url_for(".index_Q")),
             ('%s' % self.cond, url_for(".by_conductor", cond=self.cond)),
             ('%s' % alpha, url_for(".by_url_isogeny_class_label", cond=self.cond, alpha=alpha)),
             ('%s' % self.abs_disc, url_for(".by_url_isogeny_class_discriminant", cond=self.cond, alpha=alpha, disc=self.abs_disc)),
             ('%s' % num, url_for(".by_url_curve_label", cond=self.cond, alpha=alpha, disc=self.abs_disc, num=num))
             )

        # Make code that is used on the page:
        self.code = {}
        self.code['show'] = {'sage':'','magma':''} # use default show names
        self.code['curve'] = {'sage':'R.<x> = PolynomialRing(QQ); C = HyperellipticCurve(R(%s), R(%s))'%(self.data['min_eqn'][0],self.data['min_eqn'][1]),
                              'magma':'R<x> := PolynomialRing(Rationals()); C := HyperellipticCurve(R!%s, R!%s);'%(self.data['min_eqn'][0],self.data['min_eqn'][1])}
        if self.data['disc'] % 4096 == 0:
            ind2 = [a[0] for a in self.data['isogeny_class']['bad_lfactors']].index(2)
            bad2 = self.data['isogeny_class']['bad_lfactors'][ind2][1]
            magma_cond_option = ': ExcFactors:=[*<2,Valuation('+str(self.data['cond'])+',2),R!'+str(bad2)+'>*]'
        else:
            magma_cond_option = ''
        self.code['cond'] = {'magma': 'Conductor(LSeries(C%s)); Factorization($1);'% magma_cond_option}
        self.code['disc'] = {'magma':'Discriminant(C); Factorization(Integers()!$1);'}
        self.code['igusa_clebsch'] = {'sage':'C.igusa_clebsch_invariants(); [factor(a) for a in _]',
                                      'magma':'IgusaClebschInvariants(C); [Factorization(Integers()!a): a in $1];'}
        self.code['igusa'] = {'magma':'IgusaInvariants(C); [Factorization(Integers()!a): a in $1];'}
        self.code['g2'] = {'magma':'G2Invariants(C);'}
        self.code['aut'] = {'magma':'AutomorphismGroup(C); IdentifyGroup($1);'}
        self.code['autQbar'] = {'magma':'AutomorphismGroup(ChangeRing(C,AlgebraicClosure(Rationals()))); IdentifyGroup($1);'}
        self.code['num_rat_wpts'] = {'magma':'#Roots(HyperellipticPolynomials(SimplifiedModel(C)));'}
        self.code['two_selmer'] = {'magma':'TwoSelmerGroup(Jacobian(C)); NumberOfGenerators($1);'}
        self.code['has_square_sha'] = {'magma':'HasSquareSha(Jacobian(C));'}
        self.code['locally_solvable'] = {'magma':'f,h:=HyperellipticPolynomials(C); g:=4*f+h^2; HasPointsLocallyEverywhere(g,2) and (#Roots(ChangeRing(g,RealField())) gt 0 or LeadingCoefficient(g) gt 0);'}
        self.code['tor_struct'] = {'magma':'TorsionSubgroup(Jacobian(SimplifiedModel(C))); AbelianInvariants($1);'}
Ejemplo n.º 13
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])
        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 = 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 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,' ')]
Ejemplo n.º 14
0
    def make_class(self):
        self.ainvs_str = self.ainvs
        self.ainvs = [int(a) for a in self.ainvs_str]
        self.E = EllipticCurve(self.ainvs)
        self.CM = self.E.has_cm()

        try:
            # Extract the isogeny degree matrix from the database
            size = len(self.isogeny_matrix)
            from sage.matrix.all import Matrix

            self.isogeny_matrix = Matrix(self.isogeny_matrix)
        except AttributeError:
            # Failsafe: construct it from scratch
            self.isogeny_matrix = self.E.isogeny_class(order="lmfdb").matrix()
            size = self.isogeny_matrix.nrows()
        self.ncurves = size

        # Create isogeny graph:
        self.graph = make_graph(self.isogeny_matrix)
        P = self.graph.plot(edge_labels=True)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img

        # Create a list of the curves in the class from the database
        self.db_curves = [self.E]
        self.optimal_flags = [False] * size
        self.degrees = [0] * size
        if self.degree:
            self.degrees[0] = self.degree
        else:
            try:
                self.degrees[0] = self.E.modular_degree()
            except RuntimeError:
                pass

        # Fill in the curves in the class by looking each one up in the db:

        self.cremona_labels = [self.label] + [0] * (size - 1)
        if self.number == 1:
            self.optimal_flags[0] = True
        for i in range(2, size + 1):
            Edata = db_ec().find_one({"lmfdb_label": self.lmfdb_iso + str(i)})
            Ei = EllipticCurve([int(a) for a in Edata["ainvs"]])
            self.cremona_labels[i - 1] = Edata["label"]
            if Edata["number"] == 1:
                self.optimal_flags[i - 1] = True
            if "degree" in Edata:
                self.degrees[i - 1] = Edata["degree"]
            else:
                try:
                    self.degrees[i - 1] = Ei.modular_degree()
                except RuntimeError:
                    pass
            self.db_curves.append(Ei)

        if self.iso == "990h":  # this isogeny class is labeled wrong in Cremona's tables
            self.optimal_flags = [False, False, True, False]

        self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix))

        N, iso, number = split_lmfdb_label(self.lmfdb_iso)

        self.newform = web_latex(self.E.q_eigenform(10))
        self.newform_label = newform_label(N, 2, 1, iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms", level=N, weight=2, character=1, label=iso)
        newform_exists_in_db = is_newform_in_db(self.newform_label)

        self.lfunction_link = url_for("l_functions.l_function_ec_page", label=self.lmfdb_iso)

        self.curves = [
            dict(
                [
                    ("label", self.lmfdb_iso + str(i + 1)),
                    ("url", url_for(".by_triple_label", conductor=N, iso_label=iso, number=i + 1)),
                    ("cremona_label", self.cremona_labels[i]),
                    ("ainvs", str(list(c.ainvs()))),
                    ("torsion", c.torsion_order()),
                    ("degree", self.degrees[i]),
                    ("optimal", self.optimal_flags[i]),
                ]
            )
            for i, c in enumerate(self.db_curves)
        ]

        self.friends = [("L-function", self.lfunction_link)]
        if not self.CM:
            self.friends += [
                (
                    "Symmetric square L-function",
                    url_for("l_functions.l_function_ec_sym_page", power="2", label=self.lmfdb_iso),
                ),
                (
                    "Symmetric 4th power L-function",
                    url_for("l_functions.l_function_ec_sym_page", power="4", label=self.lmfdb_iso),
                ),
            ]
        if newform_exists_in_db:
            self.friends += [("Modular form " + self.newform_label, self.newform_link)]

        self.properties = [
            ("Label", self.lmfdb_iso),
            ("Number of curves", str(self.ncurves)),
            ("Conductor", "\(%s\)" % N),
            ("CM", "%s" % self.CM),
            ("Rank", "\(%s\)" % self.rank),
            ("Graph", ""),
            (None, self.graph_link),
        ]

        self.downloads = [
            ("Download coefficients of newform", url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=100)),
            ("Download stored data for all curves", url_for(".download_EC_all", label=self.lmfdb_iso)),
        ]

        if self.lmfdb_iso == self.iso:
            self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso
        else:
            self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % (self.lmfdb_iso, self.iso)

        self.bread = [
            ("Elliptic Curves", url_for("ecnf.index")),
            ("$\Q$", url_for(".rational_elliptic_curves")),
            ("%s" % N, url_for(".by_conductor", conductor=N)),
            ("%s" % iso, " "),
        ]
Ejemplo n.º 15
0
    def make_class(self):

        # Create a list of the curves in the class from the database
        self.db_curves = [c for c in db_ec().find(
            {'field_label': self.field_label, 'conductor_label':
             self.conductor_label, 'iso_label': self.iso_label}).sort('number')]

        # Rank or bounds
        try:
            self.rk = web_latex(self.db_curves[0]['rank'])
        except KeyError:
            self.rk = "?"
        try:
            self.rk_bnds = "%s...%s" % tuple(self.db_curves[0]['rank_bounds'])
        except KeyError:
            self.rank_bounds = [0, sage.rings.infinity.Infinity]
            self.rk_bnds = "not recorded"


        # Extract the isogeny degree matrix from the database if possible, else create it
        if hasattr(self, 'isogeny_matrix'):
            from sage.matrix.all import Matrix
            self.isogeny_matrix = Matrix(self.isogeny_matrix)
        else:
            self.isogeny_matrix = make_iso_matrix(self.db_curves)

        # Create isogeny graph:
        self.graph = make_graph(self.isogeny_matrix)
        P = self.graph.plot(edge_labels=True)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img
        self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix))

        self.field = field_pretty(self.field_label)
        self.field_knowl = nf_display_knowl(self.field_label, lmfdb.base.getDBConnection(), self.field)
        def curve_url(c):
            return url_for(".show_ecnf",
                           nf=c['field_label'],
                           conductor_label=c['conductor_label'],
                           class_label=c['iso_label'],
                           number=c['number'])

        self.curves = [[c['short_label'], curve_url(c), web_ainvs(self.field_label,c['ainvs'])] for c in self.db_curves]

        self.urls = {}
        self.urls['class'] = url_for(".show_ecnf_isoclass", nf=self.field_label, conductor_label=self.conductor_label, class_label=self.iso_label)
        self.urls['conductor'] = url_for(".show_ecnf_conductor", nf=self.field_label, conductor_label=self.conductor_label)
        self.urls['field'] = url_for('.show_ecnf1', nf=self.field_label)
        sig = self.signature
        totally_real = sig[1] == 0
        imag_quadratic = sig == [0,1]
        if totally_real:
            self.hmf_label = "-".join([self.field_label, self.conductor_label, self.iso_label])
            self.urls['hmf'] = url_for('hmf.render_hmf_webpage', field_label=self.field_label, label=self.hmf_label)
            self.urls['Lfunction'] = url_for("l_functions.l_function_hmf_page", field=self.field_label, label=self.hmf_label, character='0', number='0')

        if imag_quadratic:
            self.bmf_label = "-".join([self.field_label, self.conductor_label, self.iso_label])

        self.friends = []
        if totally_real:
            self.friends += [('Hilbert Modular Form ' + self.hmf_label, self.urls['hmf'])]
            self.friends += [('L-function', self.urls['Lfunction'])]
        if imag_quadratic:
            self.friends += [('Bianchi Modular Form %s not available' % self.bmf_label, '')]

        self.properties = [('Base field', self.field),
                           ('Label', self.class_label),
                           (None, self.graph_link),
                           ('Conductor', '%s' % self.conductor_label)
                       ]
        if self.rk != '?':
            self.properties += [('Rank', '%s' % self.rk)]
        else:
            if self.rk_bnds == 'not recorded':
                self.properties += [('Rank', '%s' % self.rk_bnds)]
            else:
                self.properties += [('Rank bounds', '%s' % self.rk_bnds)]

        self.bread = [('Elliptic Curves ', url_for(".index")),
                      (self.field_label, self.urls['field']),
                      (self.conductor_label, self.urls['conductor']),
                      ('isogeny class %s' % self.short_label, self.urls['class'])]
Ejemplo n.º 16
0
    def make_class(self):
        self.ainvs_str = self.ainvs
        self.ainvs = [int(a) for a in self.ainvs_str]
        self.E = EllipticCurve(self.ainvs)
        self.CM = self.E.has_cm()

        try:
            # Extract the isogeny degree matrix from the database
            size = len(self.isogeny_matrix)
            from sage.matrix.all import Matrix
            self.isogeny_matrix = Matrix(self.isogeny_matrix)
        except AttributeError:
            # Failsafe: construct it from scratch
            self.isogeny_matrix = self.E.isogeny_class(order="lmfdb").matrix()
            size = self.isogeny_matrix.nrows()

        # Create isogeny graph:
        self.graph = make_graph(self.isogeny_matrix)
        P = self.graph.plot(edge_labels=True)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img

        # Create a list of the curves in the class from the database
        self.db_curves = [self.E]
        self.optimal_flags = [False] * size
        self.degrees = [0] * size
        if self.degree:
            self.degrees[0] = self.degree
        else:
            try:
                self.degrees[0] = self.E.modular_degree()
            except RuntimeError:
                pass

        # Fill in the curves in the class by looking each one up in the db:

        self.cremona_labels = [self.label] + [0] * (size - 1)
        if self.number == 1:
            self.optimal_flags[0] = True
        for i in range(2, size + 1):
            Edata = db_ec().find_one({'lmfdb_label': self.lmfdb_iso + str(i)})
            Ei = EllipticCurve([int(a) for a in Edata['ainvs']])
            self.cremona_labels[i - 1] = Edata['label']
            if Edata['number'] == 1:
                self.optimal_flags[i - 1] = True
            if 'degree' in Edata:
                self.degrees[i - 1] = Edata['degree']
            else:
                try:
                    self.degrees[i - 1] = Ei.modular_degree()
                except RuntimeError:
                    pass
            self.db_curves.append(Ei)


        if self.iso == '990h':  # this isogeny class is labeled wrong in Cremona's tables
            self.optimal_flags = [False, False, True, False]

        self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix))

        N, iso, number = lmfdb_label_regex.match(self.lmfdb_iso).groups()

        self.newform = web_latex(self.E.q_eigenform(10))
        self.newform_label = self.lmfdb_iso.replace('.', '.2')
        self.newform_link = url_for("emf.render_elliptic_modular_forms", level=N, weight=2, character=0, label=iso)

        self.lfunction_link = url_for("l_functions.l_function_ec_page", label=self.lmfdb_iso)

        self.curves = [[self.lmfdb_iso + str(i + 1),
                        self.cremona_labels[i],
                        str(list(c.ainvs())),
                        c.torsion_order(),
                        self.degrees[i],
                        self.optimal_flags[i]]
                       for i, c in enumerate(self.db_curves)]

        self.friends = [
        ('L-function', self.lfunction_link),
        ('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', label=self.lmfdb_iso)),
        ('Symmetric 4th power L-function', url_for("l_functions.l_function_ec_sym_page", power='4', label=self.lmfdb_iso)),
        ('Modular form ' + self.newform_label, self.newform_link)]

        self.properties = [('Label', self.lmfdb_iso),
                           (None, self.graph_link),
                           ('Conductor', '\(%s\)' % N),
                           ('CM', '%s' % self.CM),
                           ('Rank', '\(%s\)' % self.rank)
                           ]


        self.downloads = [('Download coeffients of newform', url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=100)),
                         ('Download stored data for all curves', url_for(".download_EC_all", label=self.lmfdb_iso))]

        if self.lmfdb_iso == self.iso:
            self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso
        else:
            self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % (self.lmfdb_iso, self.iso)

        self.bread = [('Elliptic Curves ', url_for(".rational_elliptic_curves")), ('isogeny class %s' % self.lmfdb_iso, ' ')]
Ejemplo n.º 17
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
        # and compute some further (easy) data about it.
        #

        # Weierstrass equation

        data = self.data = {}

        disc = ZZ(self.disc_sign) * ZZ(self.disc_key[3:]) 
        # to deal with disc_key, uncomment line above and remove line below
        #disc = ZZ(self.disc_sign) * ZZ(self.abs_disc)
        data['disc'] = disc
        data['cond'] = ZZ(self.cond)
        data['min_eqn'] = self.min_eqn
        data['min_eqn_display'] = list_to_min_eqn(self.min_eqn)
        data['disc_factor_latex'] = web_latex(factor(data['disc']))
        data['cond_factor_latex'] = web_latex(factor(int(self.cond)))
        data['aut_grp'] = groupid_to_meaningful(self.aut_grp)
        data['geom_aut_grp'] = groupid_to_meaningful(self.geom_aut_grp)
        data['igusa_clebsch'] = [ZZ(a) for a in self.igusa_clebsch]
        data['igusa'] = igusa_clebsch_to_igusa(data['igusa_clebsch'])
        data['g2'] = igusa_to_g2(data['igusa'])
        data['ic_norm'] = normalize_invariants(data['igusa_clebsch'],[1,2,3,5])
        data['igusa_norm'] = normalize_invariants(data['igusa'],[1,2,3,4,5])
        data['ic_norm_factor_latex'] = [web_latex(zfactor(i)) for i in data['ic_norm']]
        data['igusa_norm_factor_latex'] = [web_latex(zfactor(j)) for j in data['igusa_norm']]
        data['num_rat_wpts'] = ZZ(self.num_rat_wpts)
        data['two_selmer_rank'] = ZZ(self.two_selmer_rank)
        if len(self.torsion) == 0:
            data['tor_struct'] = '\mathrm{trivial}'
        else:
            tor_struct = [ZZ(a)  for a in self.torsion]
            data['tor_struct'] = ' \\times '.join(['\Z/{%s}\Z' % n for n in tor_struct])
        isogeny_class = db_g2c().isogeny_classes.find_one({'label' : isog_label(self.label)})
        end_data = get_end_data(isogeny_class)
        for key in end_data.keys():
            data[key] = end_data[key]
        x = self.label.split('.')[1]

        self.make_code_snippets()

        self.friends = [
            ('Isogeny class %s' % isog_label(self.label), url_for(".by_double_iso_label", conductor = self.cond, iso_label = x)),
            ('L-function', url_for("l_functions.l_function_genus2_page", cond=self.cond,x=x)),
            
            ('Twists',url_for(".index_Q", ic0 = self.igusa_clebsch[0], ic1 = self.igusa_clebsch[1],ic2 = self.igusa_clebsch[2],ic3 = self.igusa_clebsch[3])),
            #('Twists2',url_for(".index_Q", igusa_clebsch = str(self.igusa_clebsch)))  #doesn't work.
            #('Siegel modular form someday', '.')
            ]
        self.downloads = [
             ('Download all stored data', '.')]
        iso = self.label.split('.')[1]
        num = '.'.join(self.label.split('.')[2:4])
        self.plot = encode_plot(eqn_list_to_curve_plot(self.min_eqn))
        self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
        self.properties = [('Label', self.label),
                           (None, self.plot_link),
                           ('Conductor','%s' % self.cond),
                           ('Discriminant', '%s' % data['disc']),
                           ('Invariants', '%s </br> %s </br> %s </br> %s'% tuple(data['ic_norm'])), 
                           ('Sato-Tate group', '\(%s\)' % data['st_group_name']), 
                           ('\(%s\)' % data['real_geom_end_alg_name'][0],'\(%s\)' % data['real_geom_end_alg_name'][1]),
                           ('\(\mathrm{GL}_2\)-type','%s' % data['is_gl2_type_name'])]
        self.title = "Genus 2 Curve %s" % (self.label)
        self.bread = [
             ('Genus 2 Curves', url_for(".index")),
             ('$\Q$', url_for(".index_Q")),
             ('%s' % self.cond, url_for(".by_conductor", conductor=self.cond)),
             ('%s' % iso, url_for(".by_double_iso_label", conductor=self.cond, iso_label=iso)),
             ('Genus 2 curve %s' % num, url_for(".by_g2c_label", label=self.label))]
Ejemplo n.º 18
0
    def make_class(self):

        # Create a list of the curves in the class from the database
        self.db_curves = [c for c in db_ec().find(
            {'field_label': self.field_label, 'conductor_label':
             self.conductor_label, 'iso_label': self.iso_label}).sort('number')]
        size = len(self.db_curves)

        # Extract the isogeny degree matrix from the database if possible, else create it
        if hasattr(self, 'isogeny_matrix'):
            from sage.matrix.all import Matrix
            self.isogeny_matrix = Matrix(self.isogeny_matrix)
        else:
            self.isogeny_matrix = make_iso_matrix(self.db_curves)

        # Create isogeny graph:
        self.graph = make_graph(self.isogeny_matrix)
        P = self.graph.plot(edge_labels=True)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img
        self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix))

        self.field = field_pretty(self.field_label)
        self.field_knowl = nf_display_knowl(self.field_label, lmfdb.base.getDBConnection(), self.field)
        def curve_url(c):
            return url_for(".show_ecnf",
                           nf=c['field_label'],
                           conductor_label=c['conductor_label'],
                           class_label=c['iso_label'],
                           number=c['number'])

        self.curves = [[c['short_label'], curve_url(c), web_ainvs(self.field_label,c['ainvs'])] for c in self.db_curves]

        self.urls = {}
        self.urls['class'] = url_for(".show_ecnf_isoclass", nf=self.field_label, conductor_label=self.conductor_label, class_label=self.iso_label)
        self.urls['conductor'] = url_for(".show_ecnf_conductor", nf=self.field_label, conductor_label=self.conductor_label)
        self.urls['field'] = url_for('.show_ecnf1', nf=self.field_label)
        real_quadratic = self.signature == [2,0]
        imag_quadratic = self.signature == [0,1]
        if real_quadratic:
            self.hmf_label = "-".join([self.field_label, self.conductor_label, self.iso_label])
            self.urls['hmf'] = url_for('hmf.render_hmf_webpage', field_label=self.field_label, label=self.hmf_label)

        if imag_quadratic:
            self.bmf_label = "-".join([self.field_label, self.conductor_label, self.iso_label])

        self.friends = []
        if real_quadratic:
            self.friends += [('Hilbert Modular Form ' + self.hmf_label, self.urls['hmf'])]
        if imag_quadratic:
            self.friends += [('Bianchi Modular Form %s not yet available' % self.bmf_label, '')]

        self.properties = [('Base field', self.field),
                           ('Label', self.class_label),
                           (None, self.graph_link),
                           ('Conductor', '%s' % self.conductor_label)
                           ]

        self.bread = [('Elliptic Curves ', url_for(".index")),
                      (self.field_label, self.urls['field']),
                      (self.conductor_label, self.urls['conductor']),
                      ('isogeny class %s' % self.short_label, self.urls['class'])]
Ejemplo n.º 19
0
    def make_class(self):

        # Create a list of the curves in the class from the database
        self.db_curves = list(db.ec_nfcurves.search(
            {'field_label': self.field_label,
             'conductor_norm': self.conductor_norm,
             'conductor_label': self.conductor_label,
             'iso_nlabel': self.iso_nlabel}))

        # Rank or bounds
        try:
            self.rk = web_latex(self.db_curves[0]['rank'])
        except KeyError:
            self.rk = "?"
        try:
            self.rk_bnds = "%s...%s" % tuple(self.db_curves[0]['rank_bounds'])
        except KeyError:
            self.rank_bounds = [0, Infinity]
            self.rk_bnds = "not recorded"


        # Extract the isogeny degree matrix from the database
        if not hasattr(self, 'isogeny_matrix'):
            # this would happen if the class is initiated with a curve
            # which is not #1 in its class:
            self.isogeny_matrix = self.db_curves[0].isogeny_matrix
        self.isogeny_matrix = Matrix(self.isogeny_matrix)
        self.one_deg = ZZ(self.class_deg).is_prime()

        # Create isogeny graph:
        self.graph = make_graph(self.isogeny_matrix)
        P = self.graph.plot(edge_labels=True)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img
        self.isogeny_matrix_str = latex(Matrix(self.isogeny_matrix))

        self.field = FIELD(self.field_label)
        self.field_name = field_pretty(self.field_label)
        self.field_knowl = nf_display_knowl(self.field_label, self.field_name)
        def curve_url(c):
            return url_for(".show_ecnf",
                           nf=c['field_label'],
                           conductor_label=c['conductor_label'],
                           class_label=c['iso_label'],
                           number=c['number'])

        self.curves = [[c['short_label'], curve_url(c), web_ainvs(self.field_label,c['ainvs'])] for c in self.db_curves]

        self.urls = {}
        self.urls['class'] = url_for(".show_ecnf_isoclass", nf=self.field_label, conductor_label=self.conductor_label, class_label=self.iso_label)
        self.urls['conductor'] = url_for(".show_ecnf_conductor", nf=self.field_label, conductor_label=self.conductor_label)
        self.urls['field'] = url_for('.show_ecnf1', nf=self.field_label)
        sig = self.signature
        totally_real = sig[1] == 0
        imag_quadratic = sig == [0,1]
        if totally_real:
            self.hmf_label = "-".join([self.field_label, self.conductor_label, self.iso_label])
            self.urls['hmf'] = url_for('hmf.render_hmf_webpage', field_label=self.field_label, label=self.hmf_label)
            if sig[0] <= 2:
                self.urls['Lfunction'] = url_for("l_functions.l_function_ecnf_page", field_label=self.field_label, conductor_label=self.conductor_label, isogeny_class_label=self.iso_label)
            elif self.abs_disc ** 2 * self.conductor_norm < 40000:
                # we shouldn't trust the Lfun computed on the fly for large conductor
                self.urls['Lfunction'] = url_for("l_functions.l_function_hmf_page", field=self.field_label, label=self.hmf_label, character='0', number='0')

        if imag_quadratic:
            self.bmf_label = "-".join([self.field_label, self.conductor_label, self.iso_label])
            self.bmf_url = url_for('bmf.render_bmf_webpage', field_label=self.field_label, level_label=self.conductor_label, label_suffix=self.iso_label)
            self.urls['Lfunction'] = url_for("l_functions.l_function_ecnf_page", field_label=self.field_label, conductor_label=self.conductor_label, isogeny_class_label=self.iso_label)

        self.friends = []
        if totally_real:
            self.friends += [('Hilbert Modular Form ' + self.hmf_label, self.urls['hmf'])]

        if imag_quadratic:
            #self.friends += [('Bianchi Modular Form %s not available' % self.bmf_label, '')]
            self.friends += [('Bianchi Modular Form %s' % self.bmf_label, self.bmf_url)]

        if 'Lfunction' in self.urls:
            self.friends += [('L-function', self.urls['Lfunction'])]
        else:
            self.friends += [('L-function not available', "")]


        self.properties = [('Base field', self.field_name),
                           ('Label', self.class_label),
                           (None, self.graph_link),
                           ('Conductor', '%s' % self.conductor_label)
                       ]
        if self.rk != '?':
            self.properties += [('Rank', '%s' % self.rk)]
        else:
            if self.rk_bnds == 'not recorded':
                self.properties += [('Rank', '%s' % self.rk_bnds)]
            else:
                self.properties += [('Rank bounds', '%s' % self.rk_bnds)]

        self.bread = [('Elliptic Curves ', url_for(".index")),
                      (self.field_label, self.urls['field']),
                      (self.conductor_label, self.urls['conductor']),
                      ('isogeny class %s' % self.short_label, self.urls['class'])]
Ejemplo n.º 20
0
    def make_E(self):
        coeffs = self.ainvs  # list of 5 lists of d strings
        self.ainvs = [self.field.parse_NFelt(x) for x in coeffs]
        self.latex_ainvs = web_latex(self.ainvs)
        from sage.schemes.elliptic_curves.all import EllipticCurve

        self.E = E = EllipticCurve(self.ainvs)
        self.equn = web_latex(E)
        self.numb = str(self.number)

        # Conductor, discriminant, j-invariant
        N = E.conductor()
        self.cond = web_latex(N)
        self.cond_norm = web_latex(N.norm())
        if N.norm() == 1:  # since the factorization of (1) displays as "1"
            self.fact_cond = self.cond
        else:
            self.fact_cond = web_latex_ideal_fact(N.factor())
        self.fact_cond_norm = web_latex(N.norm().factor())

        D = self.field.K().ideal(E.discriminant())
        self.disc = web_latex(D)
        self.disc_norm = web_latex(D.norm())
        if D.norm() == 1:  # since the factorization of (1) displays as "1"
            self.fact_disc = self.disc
        else:
            self.fact_disc = web_latex_ideal_fact(D.factor())
        self.fact_disc_norm = web_latex(D.norm().factor())

        # Minimal model?
        #
        # All curves in the database should be given
        # by models which are globally minimal if possible, else
        # minimal at all but one prime.  But we do not rely on this
        # here, and the display should be correct if either (1) there
        # exists a global minimal model but this model is not; or (2)
        # this model is non-minimal at more than one prime.
        #
        self.non_min_primes = non_minimal_primes(E)
        self.is_minimal = len(self.non_min_primes) == 0
        self.has_minimal_model = True
        if not self.is_minimal:
            self.non_min_prime = ",".join([web_latex(P) for P in self.non_min_primes])
            self.has_minimal_model = has_global_minimal_model(E)

        if not self.is_minimal:
            Dmin = minimal_discriminant_ideal(E)
            self.mindisc = web_latex(Dmin)
            self.mindisc_norm = web_latex(Dmin.norm())
            if Dmin.norm() == 1:  # since the factorization of (1) displays as "1"
                self.fact_mindisc = self.mindisc
            else:
                self.fact_mindisc = web_latex_ideal_fact(Dmin.factor())
            self.fact_mindisc_norm = web_latex(Dmin.norm().factor())

        j = E.j_invariant()
        if j:
            d = j.denominator()
            n = d * j  # numerator exists for quadratic fields only!
            g = GCD(list(n))
            n1 = n / g
            self.j = web_latex(n1)
            if d != 1:
                if n1 > 1:
                    # self.j = "("+self.j+")\(/\)"+web_latex(d)
                    self.j = web_latex(r"\frac{%s}{%s}" % (self.j, d))
                else:
                    self.j = web_latex(d)
                if g > 1:
                    if n1 > 1:
                        self.j = web_latex(g) + self.j
                    else:
                        self.j = web_latex(g)
        self.j = web_latex(j)

        self.fact_j = None
        if j.is_zero():
            self.fact_j = web_latex(j)
        else:
            try:
                self.fact_j = web_latex(j.factor())
            except (ArithmeticError, ValueError):  # if not all prime ideal factors principal
                pass

        # CM and End(E)
        self.cm_bool = "no"
        self.End = "\(\Z\)"
        if self.cm:
            self.cm_bool = "yes (\(%s\))" % self.cm
            if self.cm % 4 == 0:
                d4 = ZZ(self.cm) // 4
                self.End = "\(\Z[\sqrt{%s}]\)" % (d4)
            else:
                self.End = "\(\Z[(1+\sqrt{%s})/2]\)" % self.cm

        # Q-curve / Base change
        self.qc = "no"
        try:
            if self.q_curve:
                self.qc = "yes"
        except AttributeError:  # in case the db entry does not have this field set
            pass

        # Torsion
        self.ntors = web_latex(self.torsion_order)
        self.tr = len(self.torsion_structure)
        if self.tr == 0:
            self.tor_struct_pretty = "Trivial"
        if self.tr == 1:
            self.tor_struct_pretty = "\(\Z/%s\Z\)" % self.torsion_structure[0]
        if self.tr == 2:
            self.tor_struct_pretty = r"\(\Z/%s\Z\times\Z/%s\Z\)" % tuple(self.torsion_structure)
        torsion_gens = [E([self.field.parse_NFelt(x) for x in P]) for P in self.torsion_gens]
        self.torsion_gens = ",".join([web_latex(P) for P in torsion_gens])

        # Rank or bounds
        try:
            self.rk = web_latex(self.rank)
        except AttributeError:
            self.rk = "?"
        try:
            self.rk_bnds = "%s...%s" % tuple(self.rank_bounds)
        except AttributeError:
            self.rank_bounds = [0, Infinity]
            self.rk_bnds = "not recorded"

        # Generators
        try:
            gens = [E([self.field.parse_NFelt(x) for x in P]) for P in self.gens]
            self.gens = ", ".join([web_latex(P) for P in gens])
            if self.rk == "?":
                self.reg = "unknown"
            else:
                if gens:
                    self.reg = E.regulator_of_points(gens)
                else:
                    self.reg = 1  # otherwise we only get 1.00000...

        except AttributeError:
            self.gens = "not recorded"
            self.reg = "unknown"
            try:
                if self.rank == 0:
                    self.reg = 1
            except AttributeError:
                pass

        # Local data
        self.local_data = []
        for p in N.prime_factors():
            self.local_info = E.local_data(p, algorithm="generic")
            self.local_data.append(
                {
                    "p": web_latex(p),
                    "norm": web_latex(p.norm().factor()),
                    "tamagawa_number": self.local_info.tamagawa_number(),
                    "kodaira_symbol": web_latex(self.local_info.kodaira_symbol()).replace("$", ""),
                    "reduction_type": self.local_info.bad_reduction_type(),
                    "ord_den_j": max(0, -E.j_invariant().valuation(p)),
                    "ord_mindisc": self.local_info.discriminant_valuation(),
                    "ord_cond": self.local_info.conductor_valuation(),
                }
            )

        # URLs of self and related objects:
        self.urls = {}
        # It's useful to be able to use this class out of context, when calling url_for will fail:
        try:
            self.urls["curve"] = url_for(
                ".show_ecnf",
                nf=self.field_label,
                conductor_label=quote(self.conductor_label),
                class_label=self.iso_label,
                number=self.number,
            )
        except RuntimeError:
            return
        self.urls["class"] = url_for(
            ".show_ecnf_isoclass",
            nf=self.field_label,
            conductor_label=quote(self.conductor_label),
            class_label=self.iso_label,
        )
        self.urls["conductor"] = url_for(
            ".show_ecnf_conductor", nf=self.field_label, conductor_label=quote(self.conductor_label)
        )
        self.urls["field"] = url_for(".show_ecnf1", nf=self.field_label)

        sig = self.signature
        real_quadratic = sig == [2, 0]
        totally_real = sig[1] == 0
        imag_quadratic = sig == [0, 1]

        if totally_real:
            self.hmf_label = "-".join([self.field.label, self.conductor_label, self.iso_label])
            self.urls["hmf"] = url_for("hmf.render_hmf_webpage", field_label=self.field.label, label=self.hmf_label)
            self.urls["Lfunction"] = url_for(
                "l_functions.l_function_hmf_page",
                field=self.field_label,
                label=self.hmf_label,
                character="0",
                number="0",
            )

        if imag_quadratic:
            self.bmf_label = "-".join([self.field.label, self.conductor_label, self.iso_label])

        self.friends = []
        self.friends += [("Isogeny class " + self.short_class_label, self.urls["class"])]
        self.friends += [("Twists", url_for("ecnf.index", field_label=self.field_label, jinv=self.jinv))]
        if totally_real:
            self.friends += [("Hilbert Modular Form " + self.hmf_label, self.urls["hmf"])]
            self.friends += [("L-function", self.urls["Lfunction"])]
        if imag_quadratic:
            self.friends += [("Bianchi Modular Form %s not yet available" % self.bmf_label, "")]

        self.properties = [("Base field", self.field.field_pretty()), ("Label", self.label)]

        # Plot
        if E.base_field().signature()[0]:
            self.plot = encode_plot(EC_nf_plot(E, self.field.generator_name()))
            self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
            self.properties += [(None, self.plot_link)]

        self.properties += [
            ("Conductor", self.cond),
            ("Conductor norm", self.cond_norm),
            # See issue #796 for why this is hidden
            # ('j-invariant', self.j),
            ("CM", self.cm_bool),
        ]

        if self.base_change:
            self.properties += [("base-change", "yes: %s" % ",".join([str(lab) for lab in self.base_change]))]
        else:
            self.base_change = []  # in case it was False instead of []
            self.properties += [("Q-curve", self.qc)]

        r = self.rk
        if r == "?":
            r = self.rk_bnds
        self.properties += [("Torsion order", self.ntors), ("Rank", r)]

        for E0 in self.base_change:
            self.friends += [("Base-change of %s /\(\Q\)" % E0, url_for("ec.by_ec_label", label=E0))]

        self.make_code_snippets()
Ejemplo n.º 21
0
    def make_E(self):
        K = self.field.K()

        # a-invariants
        self.ainvs = parse_ainvs(K,self.ainvs)
        self.latex_ainvs = web_latex(self.ainvs)
        self.numb = str(self.number)

        # Conductor, discriminant, j-invariant
        N = ideal_from_string(K,self.conductor_ideal)
        self.cond = web_latex(N)
        self.cond_norm = web_latex(self.conductor_norm)
        local_data = self.local_data

        # NB badprimes is a list of primes which divide the
        # discriminant of this model.  At most one of these might
        # actually be a prime of good reduction, if the curve has no
        # global minimal model.
        badprimes = [ideal_from_string(K,ld['p']) for ld in local_data]
        badnorms = [ZZ(ld['normp']) for ld in local_data]
        mindisc_ords = [ld['ord_disc'] for ld in local_data]

        # Assumption: the curve models stored in the database are
        # either global minimal models or minimal at all but one
        # prime, so the list here has length 0 or 1:

        self.non_min_primes = [ideal_from_string(K,P) for P in self.non_min_p]
        self.is_minimal = (len(self.non_min_primes) == 0)
        self.has_minimal_model = self.is_minimal
        disc_ords = [ld['ord_disc'] for ld in local_data]
        if not self.is_minimal:
            Pmin = self.non_min_primes[0]
            P_index = badprimes.index(Pmin)
            self.non_min_prime = web_latex(Pmin)
            disc_ords[P_index] += 12

        if self.conductor_norm == 1:  # since the factorization of (1) displays as "1"
            self.fact_cond = self.cond
            self.fact_cond_norm = self.cond
        else:
            Nfac = Factorization([(P,ld['ord_cond']) for P,ld in zip(badprimes,local_data)])
            self.fact_cond = web_latex_ideal_fact(Nfac)
            Nnormfac = Factorization([(q,ld['ord_cond']) for q,ld in zip(badnorms,local_data)])
            self.fact_cond_norm = web_latex(Nnormfac)

        # D is the discriminant ideal of the model
        D = prod([P**e for P,e in zip(badprimes,disc_ords)], K.ideal(1))
        self.disc = web_latex(D)
        Dnorm = D.norm()
        self.disc_norm = web_latex(Dnorm)
        if Dnorm == 1:  # since the factorization of (1) displays as "1"
            self.fact_disc = self.disc
            self.fact_disc_norm = self.disc
        else:
            Dfac = Factorization([(P,e) for P,e in zip(badprimes,disc_ords)])
            self.fact_disc = web_latex_ideal_fact(Dfac)
            Dnormfac = Factorization([(q,e) for q,e in zip(badnorms,disc_ords)])
            self.fact_disc_norm = web_latex(Dnormfac)


        if not self.is_minimal:
            Dmin = ideal_from_string(K,self.minD)
            self.mindisc = web_latex(Dmin)
            Dmin_norm = Dmin.norm()
            self.mindisc_norm = web_latex(Dmin_norm)
            if Dmin_norm == 1:  # since the factorization of (1) displays as "1"
                self.fact_mindisc = self.mindisc
                self.fact_mindisc_norm = self.mindisc
            else:
                Dminfac = Factorization([(P,e) for P,edd in zip(badprimes,mindisc_ords)])
                self.fact_mindisc = web_latex_ideal_fact(Dminfac)
                Dminnormfac = Factorization([(q,e) for q,e in zip(badnorms,mindisc_ords)])
                self.fact_mindisc_norm = web_latex(Dminnormfac)

        j = self.field.parse_NFelt(self.jinv)
        # if j:
        #     d = j.denominator()
        #     n = d * j  # numerator exists for quadratic fields only!
        #     g = GCD(list(n))
        #     n1 = n / g
        #     self.j = web_latex(n1)
        #     if d != 1:
        #         if n1 > 1:
        #         # self.j = "("+self.j+")\(/\)"+web_latex(d)
        #             self.j = web_latex(r"\frac{%s}{%s}" % (self.j, d))
        #         else:
        #             self.j = web_latex(d)
        #         if g > 1:
        #             if n1 > 1:
        #                 self.j = web_latex(g) + self.j
        #             else:
        #                 self.j = web_latex(g)
        self.j = web_latex(j)

        self.fact_j = None
        # See issue 1258: some j factorizations work but take too long
        # (e.g. EllipticCurve/6.6.371293.1/1.1/a/1).  Note that we do
        # store the factorization of the denominator of j and display
        # that, which is the most interesting part.

        # CM and End(E)
        self.cm_bool = "no"
        self.End = "\(\Z\)"
        if self.cm:
            self.cm_bool = "yes (\(%s\))" % self.cm
            if self.cm % 4 == 0:
                d4 = ZZ(self.cm) // 4
                self.End = "\(\Z[\sqrt{%s}]\)" % (d4)
            else:
                self.End = "\(\Z[(1+\sqrt{%s})/2]\)" % self.cm
            # The line below will need to change once we have curves over non-quadratic fields
            # that contain the Hilbert class field of an imaginary quadratic field
            if self.signature == [0,1] and ZZ(-self.abs_disc*self.cm).is_square():
                self.ST = st_link_by_name(1,2,'U(1)')
            else:
                self.ST = st_link_by_name(1,2,'N(U(1))')
        else:
            self.ST = st_link_by_name(1,2,'SU(2)')

        # Q-curve / Base change
        self.qc = "no"
        try:
            if self.q_curve:
                self.qc = "yes"
        except AttributeError:  # in case the db entry does not have this field set
            pass

        # Torsion
        self.ntors = web_latex(self.torsion_order)
        self.tr = len(self.torsion_structure)
        if self.tr == 0:
            self.tor_struct_pretty = "Trivial"
        if self.tr == 1:
            self.tor_struct_pretty = "\(\Z/%s\Z\)" % self.torsion_structure[0]
        if self.tr == 2:
            self.tor_struct_pretty = r"\(\Z/%s\Z\times\Z/%s\Z\)" % tuple(self.torsion_structure)

        torsion_gens = [parse_point(K,P) for P in self.torsion_gens]
        self.torsion_gens = ",".join([web_point(P) for P in torsion_gens])

        # Rank or bounds
        try:
            self.rk = web_latex(self.rank)
        except AttributeError:
            self.rk = "?"
        try:
            self.rk_bnds = "%s...%s" % tuple(self.rank_bounds)
        except AttributeError:
            self.rank_bounds = [0, Infinity]
            self.rk_bnds = "not available"

        # Generators
        try:
            gens = [parse_point(K,P) for P in self.gens]
            self.gens = ", ".join([web_point(P) for P in gens])
            if self.rk == "?":
                self.reg = "not available"
            else:
                if gens:
                    try:
                        self.reg = self.reg
                    except AttributeError:
                        self.reg = "not available"
                    pass # self.reg already set
                else:
                    self.reg = 1  # otherwise we only get 1.00000...

        except AttributeError:
            self.gens = "not available"
            self.reg = "not available"
            try:
                if self.rank == 0:
                    self.reg = 1
            except AttributeError:
                pass

        # Local data
        for P,ld in zip(badprimes,local_data):
            ld['p'] = web_latex(P)
            ld['norm'] = P.norm()
            ld['kod'] = web_latex(ld['kod']).replace('$', '')

        # URLs of self and related objects:
        self.urls = {}
        # It's useful to be able to use this class out of context, when calling url_for will fail:
        try:
            self.urls['curve'] = url_for(".show_ecnf", nf=self.field_label, conductor_label=quote(self.conductor_label), class_label=self.iso_label, number=self.number)
        except RuntimeError:
            return
        self.urls['class'] = url_for(".show_ecnf_isoclass", nf=self.field_label, conductor_label=quote(self.conductor_label), class_label=self.iso_label)
        self.urls['conductor'] = url_for(".show_ecnf_conductor", nf=self.field_label, conductor_label=quote(self.conductor_label))
        self.urls['field'] = url_for(".show_ecnf1", nf=self.field_label)

        sig = self.signature
        totally_real = sig[1] == 0
        imag_quadratic = sig == [0,1]

        if totally_real:
            self.hmf_label = "-".join([self.field.label, self.conductor_label, self.iso_label])
            self.urls['hmf'] = url_for('hmf.render_hmf_webpage', field_label=self.field.label, label=self.hmf_label)
            self.urls['Lfunction'] = url_for("l_functions.l_function_hmf_page", field=self.field_label, label=self.hmf_label, character='0', number='0')

        if imag_quadratic:
            self.bmf_label = "-".join([self.field.label, self.conductor_label, self.iso_label])

        self.friends = []
        self.friends += [('Isogeny class ' + self.short_class_label, self.urls['class'])]
        self.friends += [('Twists', url_for('ecnf.index', field=self.field_label, jinv=rename_j(j)))]
        if totally_real:
            self.friends += [('Hilbert Modular Form ' + self.hmf_label, self.urls['hmf'])]
            self.friends += [('L-function', self.urls['Lfunction'])]
        if imag_quadratic:
            self.friends += [('Bianchi Modular Form %s not available' % self.bmf_label, '')]

        self.properties = [
            ('Base field', self.field.field_pretty()),
            ('Label', self.label)]

        # Plot
        if K.signature()[0]:
            self.plot = encode_plot(EC_nf_plot(K,self.ainvs, self.field.generator_name()))
            self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
            self.properties += [(None, self.plot_link)]

        self.properties += [
            ('Conductor', self.cond),
            ('Conductor norm', self.cond_norm),
            # See issue #796 for why this is hidden (can be very large)
            # ('j-invariant', self.j),
            ('CM', self.cm_bool)]

        if self.base_change:
            self.properties += [('base-change', 'yes: %s' % ','.join([str(lab) for lab in self.base_change]))]
        else:
            self.base_change = []  # in case it was False instead of []
            self.properties += [('Q-curve', self.qc)]

        r = self.rk
        if r == "?":
            r = self.rk_bnds
        self.properties += [
            ('Torsion order', self.ntors),
            ('Rank', r),
        ]

        for E0 in self.base_change:
            self.friends += [('Base-change of %s /\(\Q\)' % E0, url_for("ec.by_ec_label", label=E0))]

        self._code = None # will be set if needed by get_code()
Ejemplo n.º 22
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
            badprimes = [ZZ(ld['p']) for ld in 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()
                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)

        jfac = Factorization([(ZZ(ld['p']),ld['ord_den_j']) for ld in local_data])

        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['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)')

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

        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

        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'] = sage.misc.all.prod(tamagawa_numbers)

        cond, iso, num = split_lmfdb_label(self.lmfdb_label)
        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.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 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,' ')]
Ejemplo n.º 23
0
    def make_class(self):
        self.ainvs_str = self.ainvs
        self.ainvs = [int(a) for a in self.ainvs_str]
        self.E = EllipticCurve(self.ainvs)
        self.CM = self.E.has_cm()

        try:
            # Extract the isogeny degree matrix from the database
            size = len(self.isogeny_matrix)
            from sage.matrix.all import Matrix
            self.isogeny_matrix = Matrix(self.isogeny_matrix)
        except AttributeError:
            # Failsafe: construct it from scratch
            self.isogeny_matrix = self.E.isogeny_class(order="lmfdb").matrix()
            size = self.isogeny_matrix.nrows()
        self.ncurves = size

        # Create isogeny graph:
        self.graph = make_graph(self.isogeny_matrix)
        P = self.graph.plot(edge_labels=True)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img

        # Create a list of the curves in the class from the database
        self.db_curves = [self.E]
        self.optimal_flags = [False] * size
        self.degrees = [0] * size
        if self.degree:
            self.degrees[0] = self.degree
        else:
            try:
                self.degrees[0] = self.E.modular_degree()
            except RuntimeError:
                pass

        # Fill in the curves in the class by looking each one up in the db:

        self.cremona_labels = [self.label] + [0] * (size - 1)
        if self.number == 1:
            self.optimal_flags[0] = True
        for i in range(2, size + 1):
            Edata = db_ec().find_one({'lmfdb_label': self.lmfdb_iso + str(i)})
            Ei = EllipticCurve([int(a) for a in Edata['ainvs']])
            self.cremona_labels[i - 1] = Edata['label']
            if Edata['number'] == 1:
                self.optimal_flags[i - 1] = True
            if 'degree' in Edata:
                self.degrees[i - 1] = Edata['degree']
            else:
                try:
                    self.degrees[i - 1] = Ei.modular_degree()
                except RuntimeError:
                    pass
            self.db_curves.append(Ei)


        if self.iso == '990h':  # this isogeny class is labeled wrong in Cremona's tables
            self.optimal_flags = [False, False, True, False]

        self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix))

        N, iso, number = split_lmfdb_label(self.lmfdb_iso)

        self.newform = web_latex(self.E.q_eigenform(10))
        self.newform_label = newform_label(N,2,1,iso)
        self.newform_link = url_for("emf.render_elliptic_modular_forms", level=N, weight=2, character=1, label=iso)
        self.newform_exists_in_db = is_newform_in_db(self.newform_label)

        self.lfunction_link = url_for("l_functions.l_function_ec_page", label=self.lmfdb_iso)

        self.curves = [dict([('label',self.lmfdb_iso + str(i + 1)),
                             ('url',url_for(".by_triple_label", conductor=N, iso_label=iso, number=i+1)),
                             ('cremona_label',self.cremona_labels[i]),
                             ('ainvs',str(list(c.ainvs()))),
                             ('torsion',c.torsion_order()),
                             ('degree',self.degrees[i]),
                             ('optimal',self.optimal_flags[i])])
                       for i, c in enumerate(self.db_curves)]

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

        self.properties = [('Label', self.lmfdb_iso),
                           ('Number of curves', str(self.ncurves)),
                           ('Conductor', '\(%s\)' % N),
                           ('CM', '%s' % self.CM),
                           ('Rank', '\(%s\)' % self.rank),
                           ('Graph', ''),(None, self.graph_link)
                           ]


        self.downloads = [('Download coefficients of newform', url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=1000)),
                         ('Download stored data for all curves', url_for(".download_EC_all", label=self.lmfdb_iso))]

        if self.lmfdb_iso == self.iso:
            self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso
        else:
            self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % (self.lmfdb_iso, self.iso)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                      ('$\Q$', url_for(".rational_elliptic_curves")),
                      ('%s' % N, url_for(".by_conductor", conductor=N)),
                      ('%s' % iso, ' ')]
        self.code = {}
        self.code['show'] = {'sage':''} # use default show names
        self.code['class'] = {'sage':'E = EllipticCurve("%s1")\n'%(self.lmfdb_iso) + '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)'}
Ejemplo n.º 24
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, " "),
        ]
Ejemplo n.º 25
0
    def make_E(self):
        coeffs = self.ainvs # list of 5 lists of d strings
        self.ainvs = [self.field.parse_NFelt(x) for x in coeffs]
        self.latex_ainvs = web_latex(self.ainvs)
        from sage.schemes.elliptic_curves.all import EllipticCurve
        self.E = E = EllipticCurve(self.ainvs)
        self.equn = web_latex(E)
        self.numb = str(self.number)

        # Conductor, discriminant, j-invariant
        N = E.conductor()
        self.cond = web_latex(N)
        self.cond_norm = web_latex(N.norm())
        if N.norm()==1:  # since the factorization of (1) displays as "1"
            self.fact_cond = self.cond
        else:
            self.fact_cond = web_latex_ideal_fact(N.factor())
        self.fact_cond_norm = web_latex(N.norm().factor())

        D = self.field.K().ideal(E.discriminant())
        self.disc = web_latex(D)
        self.disc_norm = web_latex(D.norm())
        if D.norm()==1:  # since the factorization of (1) displays as "1"
            self.fact_disc = self.disc
        else:
            self.fact_disc = web_latex_ideal_fact(D.factor())
        self.fact_disc_norm = web_latex(D.norm().factor())

        # Minimal model?
        #
        # All curves in the database should be given
        # by models which are globally minimal if possible, else
        # minimal at all but one prime.  But we do not rely on this
        # here, and the display should be correct if either (1) there
        # exists a global minimal model but this model is not; or (2)
        # this model is non-minimal at more than one prime.
        #
        self.non_min_primes = non_minimal_primes(E)
        self.is_minimal = (len(self.non_min_primes)==0)
        self.has_minimal_model = True
        if not self.is_minimal:
            self.non_min_prime = ','.join([web_latex(P) for P in self.non_min_primes])
            self.has_minimal_model = has_global_minimal_model(E)

        if not self.is_minimal:
            Dmin = minimal_discriminant_ideal(E)
            self.mindisc = web_latex(Dmin)
            self.mindisc_norm = web_latex(Dmin.norm())
            if Dmin.norm()==1:  # since the factorization of (1) displays as "1"
                self.fact_mindisc = self.mindisc
            else:
                self.fact_mindisc = web_latex_ideal_fact(Dmin.factor())
            self.fact_mindisc_norm = web_latex(Dmin.norm().factor())


        j = E.j_invariant()
        if j:
            d = j.denominator()
            n = d*j # numerator exists for quadratic fields only!
            g = GCD(list(n))
            n1 = n/g
            self.j = web_latex(n1)
            if d!=1:
                if n1>1:
                #self.j = "("+self.j+")\(/\)"+web_latex(d)
                    self.j = web_latex(r"\frac{%s}{%s}" % (self.j,d))
                else:
                    self.j = web_latex(d)
                if g>1:
                    if n1>1:
                        self.j = web_latex(g) + self.j
                    else:
                        self.j = web_latex(g)
        self.j = web_latex(j)

        self.fact_j = None
        if j.is_zero():
            self.fact_j = web_latex(j)
        else:
            try:
                self.fact_j = web_latex(j.factor())
            except (ArithmeticError,ValueError): # if not all prime ideal factors principal
                pass

        # CM and End(E)
        self.cm_bool = "no"
        self.End = "\(\Z\)"
        if self.cm:
            self.cm_bool = "yes (\(%s\))" % self.cm
            if self.cm%4==0:
                d4 = ZZ(self.cm)//4
                self.End = "\(\Z[\sqrt{%s}]\)"%(d4)
            else:
                self.End = "\(\Z[(1+\sqrt{%s})/2]\)" % self.cm

        # Q-curve / Base change
        self.qc = "no"
        try:
            if self.q_curve:
                self.qc = "yes"
        except AttributeError: # in case the db entry does not have this field set
            pass

        # Torsion
        self.ntors = web_latex(self.torsion_order)
        self.tr = len(self.torsion_structure)
        if self.tr==0:
            self.tor_struct_pretty = "Trivial"
        if self.tr==1:
            self.tor_struct_pretty = "\(\Z/%s\Z\)" % self.torsion_structure[0]
        if self.tr==2:
            self.tor_struct_pretty = r"\(\Z/%s\Z\times\Z/%s\Z\)" % tuple(self.torsion_structure)
        torsion_gens = [E([self.field.parse_NFelt(x) for x in P])
                        for P in self.torsion_gens]
        self.torsion_gens = ",".join([web_latex(P) for P in torsion_gens])


        # Rank etc
        try:
            self.rk = web_latex(self.rank)
        except AttributeError:
            self.rk = "not recorded"
#       if rank in self:
#            self.r = web_latex(self.rank)

        # Local data
        self.local_data = []
        for p in N.prime_factors():
            self.local_info = E.local_data(p, algorithm="generic")
            self.local_data.append({'p': web_latex(p),
                               'norm': web_latex(p.norm().factor()),
                               'tamagawa_number': self.local_info.tamagawa_number(),
                               'kodaira_symbol': web_latex(self.local_info.kodaira_symbol()).replace('$', ''),
                               'reduction_type': self.local_info.bad_reduction_type(),
                                'ord_den_j': max(0,-E.j_invariant().valuation(p)),
                                'ord_mindisc': self.local_info.discriminant_valuation()
                               })

        # URLs of self and related objects:
        self.urls = {}
        self.urls['curve'] = url_for(".show_ecnf", nf = self.field_label, conductor_label=self.conductor_label, class_label = self.iso_label, number = self.number)
        self.urls['class'] = url_for(".show_ecnf_isoclass", nf = self.field_label, conductor_label=self.conductor_label, class_label = self.iso_label)
        self.urls['conductor'] = url_for(".show_ecnf_conductor", nf = self.field_label, conductor_label=self.conductor_label)
        self.urls['field'] = url_for(".show_ecnf1", nf=self.field_label)

        if self.field.is_real_quadratic():
            self.hmf_label = "-".join([self.field.label,self.conductor_label,self.iso_label])
            self.urls['hmf'] = url_for('hmf.render_hmf_webpage', field_label=self.field.label, label=self.hmf_label)

        if self.field.is_imag_quadratic():
            self.bmf_label = "-".join([self.field.label,self.conductor_label,self.iso_label])


        self.friends = []
        self.friends += [('Isogeny class '+self.short_class_label, self.urls['class'])]
        self.friends += [('Twists',url_for('ecnf.index',field_label=self.field_label,jinv=self.jinv))]
        if self.field.is_real_quadratic():
            self.friends += [('Hilbert Modular Form '+self.hmf_label, self.urls['hmf'])]
        if self.field.is_imag_quadratic():
            self.friends += [('Bianchi Modular Form %s not yet available' % self.bmf_label, '')]

        self.properties = [
            ('Base field', self.field.field_pretty()),
            ('Label' , self.label)]

        # Plot
        if E.base_field().signature()[0]:
            self.plot = encode_plot(EC_nf_plot(E,self.field.generator_name()))
            self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
            self.properties += [(None, self.plot_link)]

        self.properties += [
            ('Conductor' , self.cond),
            ('Conductor norm' , self.cond_norm),
            ('j-invariant' , self.j),
            ('CM' , self.cm_bool)]

        if self.base_change:
            self.properties += [('base-change', 'yes: %s' % ','.join([str(lab) for lab in self.base_change]))]
        else:
            self.base_change = [] # in case it was False instead of []
            self.properties += [('Q-curve' , self.qc)]

        self.properties += [
            ('Torsion order' , self.ntors),
            ('Rank' , self.rk),
            ]

        for E0 in self.base_change:
            self.friends += [('Base-change of %s /\(\Q\)' % E0 , url_for("ec.by_ec_label", label=E0))]
Ejemplo n.º 26
0
    def make_E(self):
        coeffs = self.ainvs  # list of 5 lists of d strings
        self.ainvs = [self.field.parse_NFelt(x) for x in coeffs]
        self.latex_ainvs = web_latex(self.ainvs)
        from sage.schemes.elliptic_curves.all import EllipticCurve
        self.E = E = EllipticCurve(self.ainvs)
        self.equn = web_latex(E)
        self.numb = str(self.number)

        # Conductor, discriminant, j-invariant
        N = E.conductor()
        self.cond = web_latex(N)
        self.cond_norm = web_latex(N.norm())
        if N.norm() == 1:  # since the factorization of (1) displays as "1"
            self.fact_cond = self.cond
        else:
            self.fact_cond = web_latex_ideal_fact(N.factor())
        self.fact_cond_norm = web_latex(N.norm().factor())

        D = self.field.K().ideal(E.discriminant())
        self.disc = web_latex(D)
        self.disc_norm = web_latex(D.norm())
        if D.norm() == 1:  # since the factorization of (1) displays as "1"
            self.fact_disc = self.disc
        else:
            self.fact_disc = web_latex_ideal_fact(D.factor())
        self.fact_disc_norm = web_latex(D.norm().factor())

        # Minimal model?
        #
        # All curves in the database should be given
        # by models which are globally minimal if possible, else
        # minimal at all but one prime.  But we do not rely on this
        # here, and the display should be correct if either (1) there
        # exists a global minimal model but this model is not; or (2)
        # this model is non-minimal at more than one prime.
        #
        self.non_min_primes = non_minimal_primes(E)
        self.is_minimal = (len(self.non_min_primes) == 0)
        self.has_minimal_model = True
        if not self.is_minimal:
            self.non_min_prime = ','.join([web_latex(P) for P in self.non_min_primes])
            self.has_minimal_model = has_global_minimal_model(E)

        if not self.is_minimal:
            Dmin = minimal_discriminant_ideal(E)
            self.mindisc = web_latex(Dmin)
            self.mindisc_norm = web_latex(Dmin.norm())
            if Dmin.norm() == 1:  # since the factorization of (1) displays as "1"
                self.fact_mindisc = self.mindisc
            else:
                self.fact_mindisc = web_latex_ideal_fact(Dmin.factor())
            self.fact_mindisc_norm = web_latex(Dmin.norm().factor())

        j = E.j_invariant()
        if j:
            d = j.denominator()
            n = d * j  # numerator exists for quadratic fields only!
            g = GCD(list(n))
            n1 = n / g
            self.j = web_latex(n1)
            if d != 1:
                if n1 > 1:
                # self.j = "("+self.j+")\(/\)"+web_latex(d)
                    self.j = web_latex(r"\frac{%s}{%s}" % (self.j, d))
                else:
                    self.j = web_latex(d)
                if g > 1:
                    if n1 > 1:
                        self.j = web_latex(g) + self.j
                    else:
                        self.j = web_latex(g)
        self.j = web_latex(j)

        self.fact_j = None
        # See issue 1258: some j factorizations work bu take too long (e.g. EllipticCurve/6.6.371293.1/1.1/a/1)
        # If these are really wanted, they could be precomputed and stored in the db
        if j.is_zero():
            self.fact_j = web_latex(j)
        else:
            if self.field.K().degree() < 3: #j.numerator_ideal().norm()<1000000000000:
                try:
                    self.fact_j = web_latex(j.factor())
                except (ArithmeticError, ValueError):  # if not all prime ideal factors principal
                    pass

        # CM and End(E)
        self.cm_bool = "no"
        self.End = "\(\Z\)"
        if self.cm:
            self.cm_bool = "yes (\(%s\))" % self.cm
            if self.cm % 4 == 0:
                d4 = ZZ(self.cm) // 4
                self.End = "\(\Z[\sqrt{%s}]\)" % (d4)
            else:
                self.End = "\(\Z[(1+\sqrt{%s})/2]\)" % self.cm
            # The line below will need to change once we have curves over non-quadratic fields
            # that contain the Hilbert class field of an imaginary quadratic field
            if self.signature == [0,1] and ZZ(-self.abs_disc*self.cm).is_square():
                self.ST = '<a href="%s">$%s$</a>' % (url_for('st.by_label', label='1.2.U(1)'),'\\mathrm{U}(1)')
            else:
                self.ST = '<a href="%s">$%s$</a>' % (url_for('st.by_label', label='1.2.N(U(1))'),'N(\\mathrm{U}(1))')
        else:
            self.ST = '<a href="%s">$%s$</a>' % (url_for('st.by_label', label='1.2.SU(2)'),'\\mathrm{SU}(2)')

        # Q-curve / Base change
        self.qc = "no"
        try:
            if self.q_curve:
                self.qc = "yes"
        except AttributeError:  # in case the db entry does not have this field set
            pass

        # Torsion
        self.ntors = web_latex(self.torsion_order)
        self.tr = len(self.torsion_structure)
        if self.tr == 0:
            self.tor_struct_pretty = "Trivial"
        if self.tr == 1:
            self.tor_struct_pretty = "\(\Z/%s\Z\)" % self.torsion_structure[0]
        if self.tr == 2:
            self.tor_struct_pretty = r"\(\Z/%s\Z\times\Z/%s\Z\)" % tuple(self.torsion_structure)
        torsion_gens = [E([self.field.parse_NFelt(x) for x in P])
                        for P in self.torsion_gens]
        self.torsion_gens = ",".join([web_latex(P) for P in torsion_gens])

        # Rank or bounds
        try:
            self.rk = web_latex(self.rank)
        except AttributeError:
            self.rk = "?"
        try:
            self.rk_bnds = "%s...%s" % tuple(self.rank_bounds)
        except AttributeError:
            self.rank_bounds = [0, Infinity]
            self.rk_bnds = "not available"

        # Generators
        try:
            gens = [E([self.field.parse_NFelt(x) for x in P])
                    for P in self.gens]
            self.gens = ", ".join([web_latex(P) for P in gens])
            if self.rk == "?":
                self.reg = "not available"
            else:
                if gens:
                    self.reg = E.regulator_of_points(gens)
                else:
                    self.reg = 1  # otherwise we only get 1.00000...

        except AttributeError:
            self.gens = "not available"
            self.reg = "not available"
            try:
                if self.rank == 0:
                    self.reg = 1
            except AttributeError:
                pass

        # Local data
        self.local_data = []
        for p in N.prime_factors():
            self.local_info = E.local_data(p, algorithm="generic")
            self.local_data.append({'p': web_latex(p),
                                    'norm': web_latex(p.norm().factor()),
                                    'tamagawa_number': self.local_info.tamagawa_number(),
                                    'kodaira_symbol': web_latex(self.local_info.kodaira_symbol()).replace('$', ''),
                                    'reduction_type': self.local_info.bad_reduction_type(),
                                    'ord_den_j': max(0, -E.j_invariant().valuation(p)),
                                    'ord_mindisc': self.local_info.discriminant_valuation(),
                                    'ord_cond': self.local_info.conductor_valuation()
                                    })

        # URLs of self and related objects:
        self.urls = {}
        # It's useful to be able to use this class out of context, when calling url_for will fail:
        try:
            self.urls['curve'] = url_for(".show_ecnf", nf=self.field_label, conductor_label=quote(self.conductor_label), class_label=self.iso_label, number=self.number)
        except RuntimeError:
            return
        self.urls['class'] = url_for(".show_ecnf_isoclass", nf=self.field_label, conductor_label=quote(self.conductor_label), class_label=self.iso_label)
        self.urls['conductor'] = url_for(".show_ecnf_conductor", nf=self.field_label, conductor_label=quote(self.conductor_label))
        self.urls['field'] = url_for(".show_ecnf1", nf=self.field_label)

        sig = self.signature
        real_quadratic = sig == [2,0]
        totally_real = sig[1] == 0
        imag_quadratic = sig == [0,1]

        if totally_real:
            self.hmf_label = "-".join([self.field.label, self.conductor_label, self.iso_label])
            self.urls['hmf'] = url_for('hmf.render_hmf_webpage', field_label=self.field.label, label=self.hmf_label)
            self.urls['Lfunction'] = url_for("l_functions.l_function_hmf_page", field=self.field_label, label=self.hmf_label, character='0', number='0')

        if imag_quadratic:
            self.bmf_label = "-".join([self.field.label, self.conductor_label, self.iso_label])

        self.friends = []
        self.friends += [('Isogeny class ' + self.short_class_label, self.urls['class'])]
        self.friends += [('Twists', url_for('ecnf.index', field_label=self.field_label, jinv=self.jinv))]
        if totally_real:
            self.friends += [('Hilbert Modular Form ' + self.hmf_label, self.urls['hmf'])]
            self.friends += [('L-function', self.urls['Lfunction'])]
        if imag_quadratic:
            self.friends += [('Bianchi Modular Form %s not available' % self.bmf_label, '')]

        self.properties = [
            ('Base field', self.field.field_pretty()),
            ('Label', self.label)]

        # Plot
        if E.base_field().signature()[0]:
            self.plot = encode_plot(EC_nf_plot(E, self.field.generator_name()))
            self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
            self.properties += [(None, self.plot_link)]

        self.properties += [
            ('Conductor', self.cond),
            ('Conductor norm', self.cond_norm),
            # See issue #796 for why this is hidden
            # ('j-invariant', self.j),
            ('CM', self.cm_bool)]

        if self.base_change:
            self.properties += [('base-change', 'yes: %s' % ','.join([str(lab) for lab in self.base_change]))]
        else:
            self.base_change = []  # in case it was False instead of []
            self.properties += [('Q-curve', self.qc)]

        r = self.rk
        if r == "?":
            r = self.rk_bnds
        self.properties += [
            ('Torsion order', self.ntors),
            ('Rank', r),
        ]

        for E0 in self.base_change:
            self.friends += [('Base-change of %s /\(\Q\)' % E0, url_for("ec.by_ec_label", label=E0))]

        self._code = None # will be set if needed by get_code()
Ejemplo n.º 27
0
    def make_class(self):
        self.CM = self.cm
        N, iso, number = split_lmfdb_label(self.lmfdb_iso)

        # Extract the size of the isogeny class from the database
        ncurves = self.class_size
        # Create a list of the curves in the class from the database
        self.curves = [db.ec_curves.lucky({'iso':self.iso, 'lmfdb_number': i+1})
                          for i in range(ncurves)]

        # Set optimality flags.  The optimal curve is number 1 except
        # in one case which is labeled differently in the Cremona tables
        for c in self.curves:
            c['optimal'] = (c['number']==(3 if self.label == '990h' else 1))
            c['ai'] = c['ainvs']
            c['url'] = url_for(".by_triple_label", conductor=N, iso_label=iso, number=c['lmfdb_number'])

        from sage.matrix.all import Matrix
        self.isogeny_matrix = Matrix(self.isogeny_matrix)
        self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix))

        # Create isogeny graph:
        self.graph = make_graph(self.isogeny_matrix)
        P = self.graph.plot(edge_labels=True)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img


        self.newform =  web_latex(PowerSeriesRing(QQ, 'q')(self.anlist, 20, check=True))
        self.newform_label = db.mf_newforms.lucky({'level':N, 'weight':2, 'related_objects':{'$contains':'EllipticCurve/Q/%s/%s' % (N, iso)}},'label')
        self.newform_exists_in_db = self.newform_label is not None
        if self.newform_label is not None:
            char_orbit, hecke_orbit = self.newform_label.split('.')[2:]
            self.newform_link = url_for("cmf.by_url_newform_label", level=N, weight=2, char_orbit_label=char_orbit, hecke_orbit=hecke_orbit)

        self.lfunction_link = url_for("l_functions.l_function_ec_page", conductor_label = N, isogeny_class_label = iso)

        self.friends =  [('L-function', self.lfunction_link)]
        if not self.CM:
            self.CM = "no"
            if int(N)<=300:
                self.friends += [('Symmetric square L-function', url_for("l_functions.l_function_ec_sym_page", power='2', conductor = N, isogeny = iso))]
            if int(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.properties = [('Label', self.lmfdb_iso),
                           ('Number of curves', str(ncurves)),
                           ('Conductor', '\(%s\)' % N),
                           ('CM', '%s' % self.CM),
                           ('Rank', '\(%s\)' % self.rank),
                           ('Graph', ''),(None, self.graph_link)
                           ]


        self.downloads = [('Download q-expansion', url_for(".download_EC_qexp", label=self.lmfdb_iso, limit=1000)),
                         ('Download stored data for all curves', url_for(".download_EC_all", label=self.lmfdb_iso))]

        if self.lmfdb_iso == self.iso:
            self.title = "Elliptic Curve Isogeny Class %s" % self.lmfdb_iso
        else:
            self.title = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % (self.lmfdb_iso, self.iso)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                      ('$\Q$', url_for(".rational_elliptic_curves")),
                      ('%s' % N, url_for(".by_conductor", conductor=N)),
                      ('%s' % iso, ' ')]
        self.code = {}
        self.code['show'] = {'sage':''} # use default show names
        self.code['class'] = {'sage':'E = EllipticCurve("%s1")\n'%(self.lmfdb_iso) + '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)'}
Ejemplo n.º 28
0
    def make_curve(self):
        # To start with the data fields of self are just those from the
        # databases.  We reformat these, while computing some further (easy)
        # data about the curve on the fly.

        # Get data from databases:
        data = self.data = {}
        endodata = self.endodata = {}

        # Polish data from database before putting it into the data dictionary:
        disc = ZZ(self.disc_sign) * ZZ(self.disc_key[3:]) 
        # to deal with disc_key, uncomment line above and comment line below
        #disc = ZZ(self.disc_sign) * ZZ(self.abs_disc)
        data['disc'] = disc
        data['cond'] = ZZ(self.cond)
        data['min_eqn'] = self.min_eqn
        data['min_eqn_display'] = list_to_min_eqn(self.min_eqn)
        data['disc_factor_latex'] = web_latex(factor(data['disc']))
        data['cond_factor_latex'] = web_latex(factor(int(self.cond)))
        data['aut_grp'] = groupid_to_meaningful(self.aut_grp)
        data['geom_aut_grp'] = groupid_to_meaningful(self.geom_aut_grp)
        data['igusa_clebsch'] = [ZZ(a) for a in self.igusa_clebsch]
        data['igusa'] = igusa_clebsch_to_igusa(data['igusa_clebsch'])
        data['g2'] = igusa_to_g2(data['igusa'])
        data['ic_norm'] = normalize_invariants(data['igusa_clebsch'],[1,2,3,5])
        data['igusa_norm'] = normalize_invariants(data['igusa'],[1,2,3,4,5])
        data['ic_norm_factor_latex'] = [web_latex(zfactor(i)) for i in
                data['ic_norm']]
        data['igusa_norm_factor_latex'] = [web_latex(zfactor(j)) for j in
                data['igusa_norm']]
        data['num_rat_wpts'] = ZZ(self.num_rat_wpts)
        data['two_selmer_rank'] = ZZ(self.two_selmer_rank)
        if len(self.torsion) == 0:
            data['tor_struct'] = '\mathrm{trivial}'
        else:
            tor_struct = [ZZ(a)  for a in self.torsion]
            data['tor_struct'] = ' \\times '.join(['\Z/{%s}\Z' % n for n in
                tor_struct])

        # Data from old endomorphism functionality, used in isogeny class as
        # well. Calls the get_end_data function above.
        isogeny_class = db_g2c().isogeny_classes.find_one({'label' :
            isog_label(self.label)})
        end_data = get_end_data(isogeny_class)
        for key in end_data.keys():
            data[key] = end_data[key]

        # GL_2 statement over the base field
        endodata['gl2_statement_base'] = gl2_statement(self.factorsRR_base,
                r'\(\Q\)')
        
        # NOTE: In what follows there is some copying of code and data that is
        # stupid from the point of view of efficiency but likely better from
        # that of maintenance.
        
        # Endomorphism data over QQ:
        endodata['factorsQQ_base'] = self.factorsQQ_base
        endodata['factorsRR_base'] = self.factorsRR_base
        endodata['ring_base'] = self.ring_base
        endodata['endo_statement_base'] = \
        """Endomorphism ring over \(\Q\):<br>""" + \
        endo_statement(endodata['factorsQQ_base'], endodata['factorsRR_base'],
                endodata['ring_base'], r'')
        # Field of definition data:
        endodata['fod_label'] = self.fod_label
        endodata['fod_poly'] = intlist_to_poly(self.fod_coeffs)
        endodata['fod_statement'] = fod_statement(endodata['fod_label'],
                endodata['fod_poly'])
        # Endomorphism data over QQbar:
        endodata['factorsQQ_geom'] = self.factorsQQ_geom
        endodata['factorsRR_geom'] = self.factorsRR_geom
        endodata['ring_geom'] = self.ring_geom
        if self.fod_label != '1.1.1.1':
            endodata['endo_statement_geom'] = \
            """Endomorphism ring over \(\overline{\Q}\):<br>""" + \
            endo_statement(endodata['factorsQQ_geom'],
                    endodata['factorsRR_geom'], endodata['ring_geom'],
                    r'\overline{\Q}')

        # Full endomorphism lattice:
        endodata['lattice'] = self.lattice[1:len(self.lattice) - 1]
        if endodata['lattice']:
            endodata['lattice_statement_preamble'] = \
            lattice_statement_preamble()
            endodata['lattice_statement'] = \
            lattice_statement(endodata['lattice'])

        # Splitting field description:
        #endodata['is_simple_base'] = self.is_simple_base
        endodata['is_simple_geom'] = self.is_simple_geom
        endodata['spl_fod_label'] = self.spl_fod_label
        endodata['spl_fod_poly'] = intlist_to_poly(self.spl_fod_coeffs)
        endodata['spl_fod_statement'] = \
        spl_fod_statement(endodata['is_simple_geom'],
                endodata['spl_fod_label'], endodata['spl_fod_poly'])
        
        # Isogeny factors:
        if not endodata['is_simple_geom']:
            endodata['spl_facs_coeffs'] = self.spl_facs_coeffs
            # This could be done non-uniformly as well... later.
            if len(self.spl_facs_labels) == len(self.spl_facs_coeffs):
                endodata['spl_facs_labels'] = self.spl_facs_labels
            else:
                endodata['spl_facs_labels'] = ['' for coeffs in
                        self.spl_facs_coeffs]
            endodata['spl_facs_condnorms'] = self.spl_facs_condnorms
            endodata['spl_statement'] = \
            spl_statement(endodata['spl_facs_coeffs'],
                    endodata['spl_facs_labels'],
                    endodata['spl_facs_condnorms'])

        x = self.label.split('.')[1]
        self.make_code_snippets()
        self.friends = [
            ('Isogeny class %s' % isog_label(self.label), url_for(".by_double_iso_label", conductor = self.cond, iso_label = x)),
            ('L-function', url_for("l_functions.l_function_genus2_page", cond=self.cond,x=x)),
            
            ('Twists',url_for(".index_Q", ic0 = self.igusa_clebsch[0], ic1 = self.igusa_clebsch[1],ic2 = self.igusa_clebsch[2],ic3 = self.igusa_clebsch[3])),
            #('Twists2',url_for(".index_Q", igusa_clebsch = str(self.igusa_clebsch)))  #doesn't work.
            #('Siegel modular form someday', '.')
            ]
        self.downloads = [
             ('Download all stored data', '.')]
        iso = self.label.split('.')[1]
        num = '.'.join(self.label.split('.')[2:4])
        self.plot = encode_plot(eqn_list_to_curve_plot(self.min_eqn))
        self.plot_link = '<img src="%s" width="200" height="150"/>' % self.plot
        self.properties = [('Label', self.label),
                           (None, self.plot_link),
                           ('Conductor','%s' % self.cond),
                           ('Discriminant', '%s' % data['disc']),
                           ('Invariants', '%s </br> %s </br> %s </br> %s'% tuple(data['ic_norm'])), 
                           ('Sato-Tate group', '\(%s\)' % data['st_group_name']), 
                           ('\(%s\)' % data['real_geom_end_alg_name'][0],'\(%s\)' % data['real_geom_end_alg_name'][1]),
                           ('\(\mathrm{GL}_2\)-type','%s' % data['is_gl2_type_name'])]
        self.title = "Genus 2 Curve %s" % (self.label)
        self.bread = [
             ('Genus 2 Curves', url_for(".index")),
             ('$\Q$', url_for(".index_Q")),
             ('%s' % self.cond, url_for(".by_conductor", conductor=self.cond)),
             ('%s' % iso, url_for(".by_double_iso_label", conductor=self.cond, iso_label=iso)),
             ('Genus 2 curve %s' % num, url_for(".by_g2c_label", label=self.label))]