Ejemplo n.º 1
0
def bianchi_modular_form_by_label(lab):
    if lab == '':
        # do nothing: display the top page
        return redirect(url_for(".index"))
    if isinstance(lab, basestring):
        res = db_forms().find_one({'label': lab})
    else:
        res = lab
        lab = res['label']

    if res == None:
        flash(Markup("No Bianchi modular form in the database has label or name <span style='color:black'>%s</span>" % lab), "error")
        return redirect(url_for(".index"))
    else:
        return redirect(url_for(".render_bmf_webpage", field_label = res['field_label'], level_label = res['level_label'], label_suffix = res['label_suffix']))
def bianchi_modular_form_by_label(lab):
    if lab == '':
        # do nothing: display the top page
        return redirect(url_for(".index"))
    if isinstance(lab, basestring):
        res = db_forms().find_one({'label': lab})
    else:
        res = lab
        lab = res['label']

    if res == None:
        flash(Markup("No Bianchi modular form in the database has label or name <span style='color:black'>%s</span>" % lab), "error")
        return redirect(url_for(".index"))
    else:
        return redirect(url_for(".render_bmf_webpage", field_label = res['field_label'], level_label = res['level_label'], label_suffix = res['label_suffix']))
Ejemplo n.º 3
0
def render_bmf_space_webpage(field_label, level_label):
    info = {}
    t = "Bianchi modular forms of level %s over %s" % (level_label,
                                                       field_label)
    credit = bianchi_credit
    bread = [('Bianchi modular forms', url_for(".index")),
             (field_pretty(field_label),
              url_for(".render_bmf_field_dim_table_gl2",
                      field_label=field_label)), (level_label, '')]
    friends = []
    properties2 = []

    if not field_label_regex.match(field_label):
        info[
            'err'] = "%s is not a valid label for an imaginary quadratic field" % field_label
    else:
        pretty_field_label = field_pretty(field_label)
        if not db_dims().find({'field_label': field_label}):
            info[
                'err'] = "no dimension information exists in the database for field %s" % pretty_field_label
        else:
            t = "Bianchi Modular Forms of level %s over %s" % (
                level_label, pretty_field_label)
            data = db_dims().find({
                'field_label': field_label,
                'level_label': level_label
            })
            nres = data.count()
            if nres == 0:
                info[
                    'err'] = "no dimension information exists in the database for level %s and field %s" % (
                        level_label, pretty_field_label)
            else:
                data = data.next()
                info['label'] = data['label']
                nf = WebNumberField(field_label)
                info['base_galois_group'] = nf.galois_string()
                info['field_label'] = field_label
                info['pretty_field_label'] = pretty_field_label
                info['level_label'] = level_label
                info['level_norm'] = data['level_norm']
                info['field_degree'] = nf.degree()
                info['field_classno'] = nf.class_number()
                info['field_disc'] = str(nf.disc())
                info['field_poly'] = teXify_pol(str(nf.poly()))
                info['field_knowl'] = nf_display_knowl(field_label,
                                                       getDBConnection(),
                                                       pretty_field_label)
                w = 'i' if nf.disc() == -4 else 'a'
                L = nf.K().change_names(w)
                alpha = L.gen()
                info['field_gen'] = latex(alpha)
                I = ideal_from_label(L, level_label)
                info['level_gen'] = latex(I.gens_reduced()[0])
                info['level_fact'] = latex(I.factor())
                dim_data = data['gl2_dims']
                weights = dim_data.keys()
                weights.sort(key=lambda w: int(w))
                for w in weights:
                    dim_data[w]['dim'] = dim_data[w]['cuspidal_dim']
                info['dim_data'] = dim_data
                info['weights'] = weights
                info['nweights'] = len(weights)

                newdim = data['gl2_dims']['2']['new_dim']
                newforms = db_forms().find({
                    'field_label': field_label,
                    'level_label': level_label
                }).sort('label_suffix', ASCENDING)
                info['nfdata'] = [{
                    'label':
                    f['short_label'],
                    'url':
                    url_for(".render_bmf_webpage",
                            field_label=f['field_label'],
                            level_label=f['level_label'],
                            label_suffix=f['label_suffix']),
                    'wt':
                    f['weight'],
                    'dim':
                    f['dimension'],
                    'sfe':
                    "+1" if f['sfe'] == 1 else "-1",
                    'bc':
                    bc_info(f['bc']),
                    'cm':
                    cm_info(f['CM']),
                } for f in newforms]
                info['nnewforms'] = len(info['nfdata'])
                properties2 = [('Base field', pretty_field_label),
                               ('Level', info['level_label']),
                               ('Norm', str(info['level_norm'])),
                               ('New dimension', str(newdim))]
                friends = [('Newform {}'.format(f['label']), f['url'])
                           for f in info['nfdata']]

    return render_template("bmf-space.html",
                           info=info,
                           credit=credit,
                           title=t,
                           bread=bread,
                           properties2=properties2,
                           friends=friends)
Ejemplo n.º 4
0
def bianchi_modular_form_search(**args):
    """Function to handle requests from the top page, either jump to one
    newform or do a search.
    """
    info = to_dict(args)  # what has been entered in the search boxes
    if 'label' in info:
        # The Label button has been pressed.
        return bianchi_modular_form_by_label(info['label'])

    query = {}
    for field in ['field_label', 'weight', 'level_norm', 'dimension']:
        if info.get(field):
            if field == 'weight':
                query['weight'] = info[field]
            elif field == 'field_label':
                parse_nf_string(info, query, field, 'base number field', field)
            elif field == 'label':
                query[field] = info[field]
            elif field == 'dimension':
                query['dimension'] = int(info[field])
            elif field == 'level_norm':
                query[field] = parse_range(info[field])
            else:
                query[field] = info[field]

    if not 'sfe' in info:
        info['sfe'] = "any"
    elif info['sfe'] != "any":
        query['sfe'] = int(info['sfe'])
    if 'include_cm' in info:
        if info['include_cm'] == 'exclude':
            query['CM'] = 0
        elif info['include_cm'] == 'only':
            query['CM'] = {'$nin': [0, '?']}
    if 'include_base_change' in info and info['include_base_change'] == 'off':
        query['bc'] = 0
    else:
        info['include_base_change'] = "on"

    start = 0
    if 'start' in request.args:
        start = int(request.args['start'])
    count = 50
    if 'count' in request.args:
        count = int(request.args['count'])

    info['query'] = dict(query)
    res = db_forms().find(query).sort([('level_norm', ASCENDING),
                                       ('label', ASCENDING)
                                       ]).skip(start).limit(count)
    nres = res.count()

    if nres > 0:
        info['field_pretty_name'] = field_pretty(res[0]['field_label'])
    else:
        info['field_pretty_name'] = ''
    info['number'] = nres

    if nres == 1:
        info['report'] = 'unique match'
    elif nres == 2:
        info['report'] = 'displaying both matches'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying items %s-%s of %s matches' % (
                start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres

    res_clean = []
    for v in res:
        v_clean = {}
        v_clean['field_label'] = v['field_label']
        v_clean['short_label'] = v['short_label']
        v_clean['level_label'] = v['level_label']
        v_clean['label_suffix'] = v['label_suffix']
        v_clean['label'] = v['label']
        v_clean['level_ideal'] = teXify_pol(v['level_ideal'])
        v_clean['dimension'] = v['dimension']
        v_clean['sfe'] = "+1" if v['sfe'] == 1 else "-1"
        v_clean['url'] = url_for('.render_bmf_webpage',
                                 field_label=v['field_label'],
                                 level_label=v['level_label'],
                                 label_suffix=v['label_suffix'])
        v_clean['bc'] = bc_info(v['bc'])
        v_clean['cm'] = cm_info(v['CM'])
        res_clean.append(v_clean)

    info['forms'] = res_clean
    info['count'] = count
    info['start'] = start
    info['more'] = int(start + count < nres)

    t = 'Bianchi modular form search results'

    bread = [('Bianchi Modular Forms', url_for(".index")),
             ('Search results', ' ')]
    properties = []
    return render_template("bmf-search_results.html",
                           info=info,
                           title=t,
                           properties=properties,
                           bread=bread,
                           learnmore=learnmore_list())
Ejemplo n.º 5
0
def random_bmf():  # Random Hilbert modular form
    return bianchi_modular_form_by_label(
        random_object_from_collection(db_forms()))
Ejemplo n.º 6
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.

        # 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'] = 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_forms().find_one({'label':self.bmf_label}) != None:
                    self.friends += [('Bianchi Modular Form %s' % self.bmf_label, self.bmf_url)]
                else:
                    self.friends += [('Bianchi Modular Form %s not available' % 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.º 7
0
def bianchi_modular_form_search(**args):
    """Function to handle requests from the top page, either jump to one
    newform or do a search.
    """
    info = to_dict(args)  # what has been entered in the search boxes
    if 'label' in info:
        # The Label button has been pressed.
        label = info['label']
        dat = label.split("-")
        if len(dat)==2: # assume field & level, display space
            return render_bmf_space_webpage(dat[0], dat[1])
        else: # assume single newform label; will display an error if invalid
            return bianchi_modular_form_by_label(label)

    query = {}
    for field in ['field_label', 'weight', 'level_norm', 'dimension']:
        if info.get(field):
            if field == 'weight':
                query['weight'] = info[field]
            elif field == 'field_label':
                parse_nf_string(info,query,field,'base number field',field)
            elif field == 'label':
                query[field] = info[field]
            elif field == 'dimension':
                query['dimension'] = int(info[field])
            elif field == 'level_norm':
                query[field] = parse_range(info[field])
            else:
                query[field] = info[field]

    if not 'sfe' in info:
        info['sfe'] = "any"
    elif info['sfe'] != "any":
        query['sfe'] = int(info['sfe'])
    if 'include_cm' in info:
        if info['include_cm'] == 'exclude':
            query['CM'] = 0
        elif info['include_cm'] == 'only':
            query['CM'] = {'$nin' : [0,'?']}
    if 'include_base_change' in info and info['include_base_change'] == 'off':
        query['bc'] = 0
    else:
        info['include_base_change'] = "on"

    start = 0
    if 'start' in request.args:
        start = int(request.args['start'])
    count = 50
    if 'count' in request.args:
        count = int(request.args['count'])

    info['query'] = dict(query)
    res = db_forms().find(query).sort([('level_norm', ASCENDING), ('label', ASCENDING)]).skip(start).limit(count)
    nres = res.count()

    if nres > 0:
        info['field_pretty_name'] = field_pretty(res[0]['field_label'])
    else:
        info['field_pretty_name'] = ''
    info['number'] = nres

    if nres == 1:
        info['report'] = 'unique match'
    elif nres == 2:
        info['report'] = 'displaying both matches'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying items %s-%s of %s matches' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres

    res_clean = []
    for v in res:
        v_clean = {}
        v_clean['field_label'] = v['field_label']
        v_clean['short_label'] = v['short_label']
        v_clean['level_label'] = v['level_label']
        v_clean['level_norm']  = v['level_norm']
        v_clean['level_number'] = v['level_label'].split(".")[1]
        v_clean['label_suffix'] = v['label_suffix']
        v_clean['label'] = v['label']
        v_clean['level_ideal'] = teXify_pol(v['level_ideal'])
        v_clean['dimension'] = v['dimension']
        v_clean['sfe'] = "+1" if v['sfe']==1 else "-1"
        v_clean['url'] = url_for('.render_bmf_webpage',field_label=v['field_label'], level_label=v['level_label'], label_suffix=v['label_suffix'])
        v_clean['bc'] = bc_info(v['bc'])
        v_clean['cm'] = cm_info(v['CM'])
        res_clean.append(v_clean)

    res_clean.sort(key=lambda x: [int(x['level_norm']), int(x['level_number']), x['label_suffix']])
    info['forms'] = res_clean
    info['count'] = count
    info['start'] = start
    info['more'] = int(start + count < nres)

    t = 'Bianchi modular form search results'

    bread = [('Bianchi Modular Forms', url_for(".index")), (
        'Search Results', ' ')]
    properties = []
    return render_template("bmf-search_results.html", info=info, title=t, properties=properties, bread=bread, learnmore=learnmore_list())
Ejemplo n.º 8
0
def random_bmf():    # Random Hilbert modular form
    return bianchi_modular_form_by_label( random_object_from_collection( db_forms() ) )
Ejemplo n.º 9
0
def render_bmf_space_webpage(field_label, level_label):
    info = {}
    t = "Bianchi modular forms of level %s over %s" % (level_label, field_label)
    credit = bianchi_credit
    bread = [('Modular Forms', url_for('mf.modular_form_main_page')),
             ('Bianchi Modular Forms', url_for(".index")),
             (field_pretty(field_label), url_for(".render_bmf_field_dim_table_gl2", field_label=field_label)),
             (level_label, '')]
    friends = []
    properties2 = []

    if not field_label_regex.match(field_label):
        info['err'] = "%s is not a valid label for an imaginary quadratic field" % field_label
    else:
        pretty_field_label = field_pretty(field_label)
        if not db_dims().find({'field_label': field_label}):
            info['err'] = "no dimension information exists in the database for field %s" % pretty_field_label
        else:
            t = "Bianchi Modular Forms of level %s over %s" % (level_label, pretty_field_label)
            data = db_dims().find({'field_label': field_label, 'level_label': level_label})
            nres = data.count()
            if nres==0:
                info['err'] = "no dimension information exists in the database for level %s and field %s" % (level_label, pretty_field_label)
            else:
                data = data.next()
                info['label'] = data['label']
                info['nf'] = nf = WebNumberField(field_label)
                info['field_label'] = field_label
                info['pretty_field_label'] = pretty_field_label
                info['level_label'] = level_label
                info['level_norm'] = data['level_norm']
                info['field_poly'] = teXify_pol(str(nf.poly()))
                info['field_knowl'] = nf_display_knowl(field_label, getDBConnection(), pretty_field_label)
                w = 'i' if nf.disc()==-4 else 'a'
                L = nf.K().change_names(w)
                alpha = L.gen()
                info['field_gen'] = latex(alpha)
                I = ideal_from_label(L,level_label)
                info['level_gen'] = latex(I.gens_reduced()[0])
                info['level_fact'] = web_latex_ideal_fact(I.factor(), enclose=False)
                dim_data = data['gl2_dims']
                weights = dim_data.keys()
                weights.sort(key=lambda w: int(w))
                for w in weights:
                    dim_data[w]['dim']=dim_data[w]['cuspidal_dim']
                info['dim_data'] = dim_data
                info['weights'] = weights
                info['nweights'] = len(weights)

                newdim = data['gl2_dims']['2']['new_dim']
                newforms = db_forms().find({'field_label':field_label, 'level_label':level_label}).sort('label_suffix', ASCENDING)
                info['nfdata'] = [{
                    'label': f['short_label'],
                    'url': url_for(".render_bmf_webpage",field_label=f['field_label'], level_label=f['level_label'], label_suffix=f['label_suffix']),
                    'wt': f['weight'],
                    'dim': f['dimension'],
                    'sfe': "+1" if f['sfe']==1 else "-1",
                    'bc': bc_info(f['bc']),
                    'cm': cm_info(f['CM']),
                    } for f in newforms]
                info['nnewforms'] = len(info['nfdata'])
                properties2 = [('Base field', pretty_field_label), ('Level',info['level_label']), ('Norm',str(info['level_norm'])), ('New dimension',str(newdim))]
                friends = [('Newform {}'.format(f['label']), f['url']) for f in info['nfdata'] ]

    return render_template("bmf-space.html", info=info, credit=credit, title=t, bread=bread, properties2=properties2, friends=friends)
Ejemplo n.º 10
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.

        # 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'] = 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_forms().find_one({'label':self.bmf_label}) != None:
                    self.friends += [('Bianchi Modular Form %s' % self.bmf_label, self.bmf_url)]
                else:
                    self.friends += [('Bianchi Modular Form %s not available' % 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])))