Beispiel #1
0
def render_glnQ_group(args):
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        info = db.gps_qrep.lucky({'label': label})
        info['dispmat'] = dispmat
        info['groupname'] = '${}$'.format(group_names_pretty(info['group']))
        info['groupknowl'] = abstract_group_display_knowl(
            info['group'], info['groupname'])

        title = r'$\GL(' + str(info['dim']) + r',\Q)$ subgroup ' + label

        prop = [('Label', '%s' % label), ('Order', r'\(%s\)' % info['order']),
                ('Dimension', '%s' % info['dim'])]

        bread = get_bread([(label, )])

        #        downloads = [('Code to Magma', url_for(".hgcwa_code_download",  label=label, download_type='magma')),
        #                     ('Code to Gap', url_for(".hgcwa_code_download", label=label, download_type='gap'))]

        return render_template(
            "glnQ-show-group.html",
            title=title,
            bread=bread,
            info=info,
            properties=prop,
            #friends=friends,
            learnmore=learnmore_list(),
            #downloads=downloads,
            credit=credit_string)
Beispiel #2
0
def hgm_jump(info):
    label = clean_input(info['jump'])
    if HGM_LABEL_RE.match(label):
        return redirect(url_for_label(normalize_motive(label)), 301)
    if HGM_FAMILY_LABEL_RE.match(label):
        return redirect(url_for_label(normalize_family(label)), 301)
    flash_error('%s is not a valid label for a hypergeometric motive or family of hypergeometric motives', label)
    return redirect(url_for(".index"))
Beispiel #3
0
def hgm_jump(info):
    label = clean_input(info['jump_to'])
    if HGM_LABEL_RE.match(label):
        return render_hgm_webpage(normalize_motive(label))
    if HGM_FAMILY_LABEL_RE.match(label):
        return render_hgm_family_webpage(normalize_family(label))
    flash_error('%s is not a valid label for a hypergeometric motive or family of hypergeometric motives', label)
    return redirect(url_for(".index"))
Beispiel #4
0
def render_group_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        label = label.replace('t', 'T')
        C = base.getDBConnection()
        data = C.transitivegroups.groups.find_one({'label': label})
        if data is None:
            bread = get_bread([("Search error", url_for('.search'))])
            info['err'] = "Group " + label + " was not found in the database."
            info['label'] = label
            return search_input_error(info, bread)
        title = 'Galois Group:' + label
        n = data['n']
        t = data['t']
        data['yesno'] = yesno
        order = data['order']
        data['orderfac'] = latex(ZZ(order).factor())
        orderfac = latex(ZZ(order).factor())
        data['ordermsg'] = "$%s=%s$" % (order, latex(orderfac))
        if ZZ(order) == 1:
            data['ordermsg'] = "$1$"
        if ZZ(order).is_prime():
            data['ordermsg'] = "$%s$ (is prime)" % order
        pgroup = len(ZZ(order).prime_factors()) < 2
        if n == 1:
            G = gap.SmallGroup(n, t)
        else:
            G = gap.TransitiveGroup(n, t)
        if ZZ(order) < ZZ('10000000000'):
            ctable = chartable(n, t)
        else:
            ctable = 'Group too large'
        data['gens'] = generators(n, t)
        if n == 1 and t == 1:
            data['gens'] = 'None needed'
        data['chartable'] = ctable
        data['parity'] = "$%s$" % data['parity']
        data['cclasses'] = conjclasses(G, n)
        data['subinfo'] = subfield_display(C, n, data['subs'])
        data['resolve'] = resolve_display(C, data['resolve'])
#    if len(data['resolve']) == 0: data['resolve'] = 'None'
        data['otherreps'] = otherrep_display(n, t, C, data['repns'])
        prop2 = [
            ('Order:', '\(%s\)' % order),
            ('n:', '\(%s\)' % data['n']),
            ('Cyclic:', yesno(data['cyc'])),
            ('Abelian:', yesno(data['ab'])),
            ('Solvable:', yesno(data['solv'])),
            ('Primitive:', yesno(data['prim'])),
            ('$p$-group:', yesno(pgroup)),
            ('Name:', group_display_short(n, t, C)),
        ]
        info.update(data)

        bread = get_bread([(label, ' ')])
        return render_template("gg-show-group.html", credit=GG_credit, title=title, bread=bread, info=info, properties2=prop2)
Beispiel #5
0
def by_label(label):
    try:
        nflabel = nf_string_to_label(clean_input(label))
        if label != nflabel:
            return redirect(url_for(".by_label", label=nflabel), 301)
        return render_field_webpage({'label': nflabel})
    except ValueError as err:
        flash_error("%s is not a valid input for a <span style='color:black'>label</span>.  %s", label, str(err))
        return redirect(url_for(".number_field_render_webpage"))
Beispiel #6
0
def by_label(label):
    try:
        nflabel = nf_string_to_label(clean_input(label))
        if label != nflabel:
            return redirect(url_for(".by_label", label=nflabel), 301)
        return render_field_webpage({'label': nflabel})
    except ValueError as err:
        flash_error("<span style='color:black'>%s</span> us not a valid input for a <span style='color:black'>label</span>.  "+ str(err), label)
        return redirect(url_for(".number_field_render_webpage"))
Beispiel #7
0
def by_label(label):
    clean_label = clean_input(label)
    if clean_label != label:
        return redirect(url_for('.by_label', label=clean_label), 301)
    if label == '1.2.1.d1':
        return redirect(url_for('.by_label', label='1.2.1.2.1a'), 301)
    if label == '1.2.3.c1':
        return redirect(url_for('.by_label', label='1.2.3.1.1a'), 301)
    return search_by_label(label)
Beispiel #8
0
def by_label(label):
    clean_label = clean_input(label)
    if clean_label != label:
        return redirect(url_for('.by_label', label=clean_label), 301)
    if label == '1.2.1.d1':
        return redirect(url_for('.by_label', label='1.2.1.2.1a'), 301)
    if label == '1.2.3.c1':
        return redirect(url_for('.by_label', label='1.2.3.1.1a'), 301)
    return search_by_label(label)
Beispiel #9
0
def render_hgm_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        C = base.getDBConnection()
        data = C.hgm.motives.find_one({'label': label})
        if data is None:
            bread = get_bread([("Search error", url_for('.search'))])
            info['err'] = "Motive " + label + " was not found in the database."
            info['label'] = label
            return search_input_error(info, bread)
        title = 'Hypergeometric Motive:' + label
        A = data['A']
        B = data['B']
        tn,td = data['t']
        t = latex(QQ(str(tn)+'/'+str(td)))
        primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]
        locinfo = data['locinfo']
        for j in range(len(locinfo)):
            locinfo[j] = [primes[j]] + locinfo[j]
            locinfo[j][2] = poly_with_factored_coeffs(locinfo[j][2], primes[j])
        hodge = data['hodge']
        prop2 = [
            ('Degree', '\(%s\)' % data['degree']),
            ('Weight',  '\(%s\)' % data['weight']),
            ('Conductor', '\(%s\)' % data['cond']),
        ]
        # Now add factorization of conductor
        Cond = ZZ(data['cond'])
        if not (Cond.abs().is_prime() or Cond == 1):
            data['cond'] = "%s=%s" % (str(Cond), factorint(data['cond']))

        info.update({
                    'A': A,
                    'B': B,
                    't': t,
                    'degree': data['degree'],
                    'weight': data['weight'],
                    'sign': data['sign'],
                    'sig': data['sig'],
                    'hodge': hodge,
                    'cond': data['cond'],
                    'req': data['req'],
                    'locinfo': locinfo
                    })
        AB_data, t_data = data["label"].split("_t")
        #AB_data = data["label"].split("_t")[0]
        friends = [("Motive family "+AB_data.replace("_"," "), url_for(".by_family_label", label = AB_data))]
        friends.append(('L-function', url_for("l_functions.l_function_hgm_page", label=AB_data, t='t'+t_data)))
#        if rffriend != '':
#            friends.append(('Discriminant root field', rffriend))


        bread = get_bread([(label, ' ')])
        return render_template("hgm-show-motive.html", credit=HGM_credit, title=title, bread=bread, info=info, properties2=prop2, friends=friends)
Beispiel #10
0
def parse_artin_label(label, safe=False):
    try:
        label = clean_input(label)
        if LABEL_RE.match(label):
            return label
        if OLD_LABEL_RE.match(label):
            newlabel = db.artin_old2new_labels.lookup(label)['new']
        if newlabel:
            return newlabel
    except:
        if safe:
            return ''
    raise ValueError
Beispiel #11
0
def by_label(label):
    if label == "random":
        #This version leaves the word 'random' in the URL:
        #return render_field_webpage({'label': label})
        return redirect(url_for_label(db.nf_fields.random()), 301)
    try:
        nflabel = nf_string_to_label(clean_input(label))
        if label != nflabel:
            return redirect(url_for_label(nflabel), 301)
        return render_field_webpage({'label': nflabel})
    except ValueError as err:
        flash_error("%s is not a valid input for a <span style='color:black'>label</span>.  %s", label, str(err))
        return redirect(url_for(".number_field_render_webpage"))
Beispiel #12
0
def render_hgm_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        C = base.getDBConnection()
        data = C.hgm.motives.find_one({'label': label})
        if data is None:
            bread = get_bread([("Search error", url_for('.search'))])
            info['err'] = "Motive " + label + " was not found in the database."
            info['label'] = label
            return search_input_error(info, bread)
        title = 'Hypergeometric Motive:' + label
        A = data['A']
        B = data['B']
        tn = data['t']['n']
        td = data['t']['d']
        t = latex(QQ(str(tn)+'/'+str(td)))
        primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]
        locinfo = data['locinfo']
        for j in range(len(locinfo)):
            locinfo[j] = [primes[j]] + locinfo[j]
            locinfo[j][2] = poly_with_factored_coeffs(locinfo[j][2], primes[j])
        hodge = data['hodge']
        prop2 = [
            ('Degree', '\(%s\)' % data['degree']),
            ('Weight',  '\(%s\)' % data['weight']),
            ('Conductor', '\(%s\)' % data['cond']),
        ]
        info.update({
                    'A': A,
                    'B': B,
                    't': t,
                    'degree': data['degree'],
                    'weight': data['weight'],
                    'sign': data['sign'],
                    'sig': data['sig'],
                    'hodge': hodge,
                    'cond': data['cond'],
                    'req': data['req'],
                    'locinfo': locinfo
                    })
        friends = []
#        friends = [('Galois group', "/GaloisGroup/%dT%d" % (gn, gt))]
#        if unramfriend != '':
#            friends.append(('Unramified subfield', unramfriend))
#        if rffriend != '':
#            friends.append(('Discriminant root field', rffriend))

        bread = get_bread([(label, ' ')])
        return render_template("hgm-show-motive.html", credit=HGM_credit, title=title, bread=bread, info=info, properties2=prop2, friends=friends)
Beispiel #13
0
def render_hgm_family_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        C = base.getDBConnection()
        data = C.hgm.families.find_one({'label': label})
        if data is None:
            bread = get_bread([("Search error", url_for('.search'))])
            info['err'] = "Family of hypergeometric motives " + label + " was not found in the database."
            info['label'] = label
            return search_input_error(info, bread)
        title = 'Hypergeometric Motive Family:' + label
        A = data['A']
        B = data['B']
        hodge = data['hodge']
        prop2 = [
            ('Degree', '\(%s\)' % data['degree']),
            ('Weight',  '\(%s\)' % data['weight'])
        ]
        info.update({
                    'A': A,
                    'B': B,
                    'degree': data['degree'],
                    'weight': data['weight'],
                    'hodge': hodge,
                    'gal2': data['gal2'],
                    'gal3': data['gal3'],
                    'gal5': data['gal5'],
                    'gal7': data['gal7'],
                    })
        friends = []
#        friends = [('Galois group', "/GaloisGroup/%dT%d" % (gn, gt))]
#        if unramfriend != '':
#            friends.append(('Unramified subfield', unramfriend))
#        if rffriend != '':
#            friends.append(('Discriminant root field', rffriend))

        info.update({"plotcircle":  url_for(".hgm_family_circle_image", AB  =  "A"+".".join(map(str,A))+"_B"+".".join(map(str,B)))})
        info.update({"plotlinear": url_for(".hgm_family_linear_image", AB  = "A"+".".join(map(str,A))+"_B"+".".join(map(str,B)))})
        info.update({"plotconstant": url_for(".hgm_family_constant_image", AB  = "A"+".".join(map(str,A))+"_B"+".".join(map(str,B)))})
        bread = get_bread([(label, ' ')])
        return render_template("hgm-show-family.html", credit=HGM_credit, title=title, bread=bread, info=info, properties2=prop2, friends=friends)
Beispiel #14
0
def render_field_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        data = db.lf_fields.lookup(label)
        if data is None:
            if re.match(r'^\d+\.\d+\.\d+\.\d+$', label):
                flash_error("Field <span style='color:black'>%s</span> was not found in the database.", label)
            else:
                flash_error("<span style='color:black'>%s</span> is not a valid label for a local number field.", label)
            return redirect(url_for(".index"))
        title = 'Local Number Field ' + prettyname(data)
        polynomial = coeff_to_poly(data['coeffs'])
        p = data['p']
        Qp = r'\Q_{%d}' % p
        e = data['e']
        f = data['f']
        cc = data['c']
        gt = data['gal']
        gn = data['n']
        the_gal = WebGaloisGroup.from_nt(gn,gt)
        isgal = ' Galois' if the_gal.order() == gn else ' not Galois'
        abelian = ' and abelian' if the_gal.is_abelian() else ''
        galphrase = 'This field is'+isgal+abelian+' over $\Q_{%d}$.'%p
        autstring = r'\Gal' if the_gal.order() == gn else r'\Aut'
        prop2 = [
            ('Label', label),
            ('Base', '\(%s\)' % Qp),
            ('Degree', '\(%s\)' % data['n']),
            ('e', '\(%s\)' % e),
            ('f', '\(%s\)' % f),
            ('c', '\(%s\)' % cc),
            ('Galois group', group_pretty_and_nTj(gn, gt)),
        ]
        # Look up the unram poly so we can link to it
        unramlabel = db.lf_fields.lucky({'p': p, 'n': f, 'c': 0}, projection=0)
        if unramlabel is None:
            logger.fatal("Cannot find unramified field!")
            unramfriend = ''
        else:
            unramfriend = "/LocalNumberField/%s" % unramlabel
            unramdata = db.lf_fields.lookup(unramlabel)

        Px = PolynomialRing(QQ, 'x')
        Pxt=PolynomialRing(Px,'t')
        Pt = PolynomialRing(QQ, 't')
        Ptx = PolynomialRing(Pt, 'x')
        if data['f'] == 1:
            unramp = r'$%s$' % Qp
            # Eliminate t from the eisenstein polynomial
            eisenp = Pxt(str(data['eisen']).replace('y','x'))
            eisenp = Pt(str(data['unram'])).resultant(eisenp)
            eisenp = web_latex(eisenp)

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


        rflabel = db.lf_fields.lucky({'p': p, 'n': {'$in': [1, 2]}, 'rf': data['rf']}, projection=0)
        if rflabel is None:
            logger.fatal("Cannot find discriminant root field!")
            rffriend = ''
        else:
            rffriend = "/LocalNumberField/%s" % rflabel
        gsm = data['gsm']
        if gsm == [0]:
            gsm = 'Not computed'
        elif gsm == [-1]:
            gsm = 'Does not exist'
        else:
            gsm = web_latex(coeff_to_poly(gsm))


        info.update({
                    'polynomial': web_latex(polynomial),
                    'n': data['n'],
                    'p': p,
                    'c': data['c'],
                    'e': data['e'],
                    'f': data['f'],
                    't': data['t'],
                    'u': data['u'],
                    'rf': lf_display_knowl( rflabel, name=printquad(data['rf'], p)),
                    'base': lf_display_knowl(str(p)+'.1.0.1', name='$%s$'%Qp),
                    'hw': data['hw'],
                    'slopes': show_slopes(data['slopes']),
                    'gal': group_pretty_and_nTj(gn, gt, True),
                    'gt': gt,
                    'inertia': group_display_inertia(data['inertia']),
                    'unram': unramp,
                    'eisen': eisenp,
                    'gms': data['gms'],
                    'gsm': gsm,
                    'galphrase': galphrase,
                    'autstring': autstring,
                    'subfields': format_subfields(data['subfields'],p),
                    'aut': data['aut'],
                    })
        friends = [('Galois group', "/GaloisGroup/%dT%d" % (gn, gt))]
        if unramfriend != '':
            friends.append(('Unramified subfield', unramfriend))
        if rffriend != '':
            friends.append(('Discriminant root field', rffriend))

        bread = get_bread([(label, ' ')])
        return render_template("lf-show-field.html", credit=LF_credit, title=title, bread=bread, info=info, properties2=prop2, friends=friends, learnmore=learnmore_list())
Beispiel #15
0
def hgm_search(**args):
    info = to_dict(args)
    bread = get_bread([("Search results", url_for('.search'))])
    C = base.getDBConnection()
    query = {}
    if 'jump_to' in info:
        return render_hgm_webpage({'label': info['jump_to']})

    # t, generic, irreducible
    # 'A', 'B', 'hodge'
    for param in ['t', 'A', 'B']:
        if (param == 't' and PAIR_RE.match(info['t'])) or (param == 'A' and IF_RE.match(info[param])) or (param == 'B' and IF_RE.match(info[param])):
            query[param] = parse_list(info[param])
        else:
            print "Bad input"
            
    for param in ['degree','weight','sign']:
        if info.get(param):
            info[param] = clean_input(info[param])
            if param == 'gal':
                try:
                    gcs = complete_group_codes(info[param])
                    if len(gcs) == 1:
                        tmp = ['gal', list(gcs[0])]
                    if len(gcs) > 1:
                        tmp = [{'gal': list(x)} for x in gcs]
                        tmp = ['$or', tmp]
                except NameError as code:
                    info['err'] = 'Error parsing input for A: unknown group label %s.  It needs to be a <a title = "Galois group labels" knowl="nf.galois_group.name">group label</a>, such as C5 or 5T1, or comma separated list of labels.' % code
                    return search_input_error(info, bread)
            else:
                ran = info[param]
                ran = ran.replace('..', '-')
                if LIST_RE.match(ran):
                    tmp = parse_range2(ran, param)
                else:
                    names = {'weight': 'weight', 'degree': 'degree', 'sign': 'sign'}
                    info['err'] = 'Error parsing input for the %s.  It needs to be an integer (such as 5), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 2,3,8 or 3-5, 7, 8-11).' % names[param]
                    return search_input_error(info, bread)
            # work around syntax for $or
            # we have to foil out multiple or conditions
            if tmp[0] == '$or' and '$or' in query:
                newors = []
                for y in tmp[1]:
                    oldors = [dict.copy(x) for x in query['$or']]
                    for x in oldors:
                        x.update(y)
                    newors.extend(oldors)
                tmp[1] = newors
            query[tmp[0]] = tmp[1]

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

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

    # logger.debug(query)
    res = C.hgm.motives.find(query).sort([('degree', pymongo.ASCENDING), 
        ('label', pymongo.ASCENDING)])
    nres = res.count()
    res = res.skip(start).limit(count)

    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0

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

    return render_template("hgm-search.html", info=info, title="Hypergeometric Motive over $\Q$ Search Result", bread=bread, credit=HGM_credit)
Beispiel #16
0
def render_field_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        data = db.lf_fields.lookup(label)
        if data is None:
            if re.match(r'^\d+\.\d+\.\d+\.\d+$', label):
                flash_error("Field %s was not found in the database.", label)
            else:
                flash_error("%s is not a valid label for a $p$-adic field.",
                            label)
            return redirect(url_for(".index"))
        title = '$p$-adic field ' + prettyname(data)
        titletag = 'p-adic field ' + prettyname(data)
        polynomial = coeff_to_poly(data['coeffs'])
        p = data['p']
        Qp = r'\Q_{%d}' % p
        e = data['e']
        f = data['f']
        cc = data['c']
        gt = int(data['galois_label'].split('T')[1])
        gn = data['n']
        the_gal = WebGaloisGroup.from_nt(gn, gt)
        isgal = ' Galois' if the_gal.order() == gn else ' not Galois'
        abelian = ' and abelian' if the_gal.is_abelian() else ''
        galphrase = 'This field is' + isgal + abelian + r' over $\Q_{%d}.$' % p
        autstring = r'\Gal' if the_gal.order() == gn else r'\Aut'
        prop2 = [
            ('Label', label),
            ('Base', r'\(%s\)' % Qp),
            ('Degree', r'\(%s\)' % data['n']),
            ('e', r'\(%s\)' % e),
            ('f', r'\(%s\)' % f),
            ('c', r'\(%s\)' % cc),
            ('Galois group', group_pretty_and_nTj(gn, gt)),
        ]
        # Look up the unram poly so we can link to it
        unramlabel = db.lf_fields.lucky({'p': p, 'n': f, 'c': 0}, projection=0)
        if unramlabel is None:
            logger.fatal("Cannot find unramified field!")
            unramfriend = ''
        else:
            unramfriend = "/LocalNumberField/%s" % unramlabel
            unramdata = db.lf_fields.lookup(unramlabel)

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

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

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

        info.update({
            'polynomial':
            web_latex(polynomial),
            'n':
            data['n'],
            'p':
            p,
            'c':
            data['c'],
            'e':
            data['e'],
            'f':
            data['f'],
            't':
            data['t'],
            'u':
            data['u'],
            'rf':
            lf_display_knowl(rflabel, name=printquad(data['rf'], p)),
            'base':
            lf_display_knowl(str(p) + '.1.0.1', name='$%s$' % Qp),
            'hw':
            data['hw'],
            'slopes':
            show_slopes(data['slopes']),
            'gal':
            group_pretty_and_nTj(gn, gt, True),
            'gt':
            gt,
            'inertia':
            group_display_inertia(data['inertia']),
            'unram':
            unramp,
            'eisen':
            eisenp,
            'gms':
            data['gms'],
            'gsm':
            gsm,
            'galphrase':
            galphrase,
            'autstring':
            autstring,
            'subfields':
            format_subfields(data['subfields'], p),
            'aut':
            data['aut'],
        })
        friends = [('Galois group', "/GaloisGroup/%dT%d" % (gn, gt))]
        if unramfriend != '':
            friends.append(('Unramified subfield', unramfriend))
        if rffriend != '':
            friends.append(('Discriminant root field', rffriend))

        bread = get_bread([(label, ' ')])
        return render_template(
            "lf-show-field.html",
            credit=LF_credit,
            title=title,
            titletag=titletag,
            bread=bread,
            info=info,
            properties=prop2,
            friends=friends,
            learnmore=learnmore_list(),
            KNOWL_ID="lf.%s" % label,
        )
Beispiel #17
0
def elliptic_curve_search(**args):
    info = to_dict(args)
    query = {}
    bread = [('Elliptic Curves', url_for("ecnf.index")),
             ('$\Q$', url_for(".rational_elliptic_curves")),
             ('Search Results', '.')]
    if 'SearchAgain' in args:
        return rational_elliptic_curves()

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

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

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

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

    if 'torsion_structure' in info and info['torsion_structure']:
        res = parse_torsion_structure(info['torsion_structure'],2)
        if 'Error' in res:
            info['err'] = res
            return search_input_error(info, bread)
        #update info for repeat searches
        info['torsion_structure'] = str(res).replace(' ','')
        query['torsion_structure'] = [str(r) for r in res]

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

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

    if 'download' in info and info['download'] != '0':
        res = db_ec().find(query).sort([ ('conductor', ASCENDING), ('iso_nlabel', ASCENDING), ('lmfdb_number', ASCENDING) ])
        return download_search(info, res)
    
    count_default = 100
    if info.get('count'):
        try:
            count = int(info['count'])
        except:
            count = count_default
    else:
        count = count_default
    info['count'] = count

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

    cursor = db_ec().find(query)
    nres = cursor.count()
    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0
    res = cursor.sort([('conductor', ASCENDING), ('iso_nlabel', ASCENDING), ('lmfdb_number', ASCENDING)
                       ]).skip(start).limit(count)
    info['curves'] = res
    info['format_ainvs'] = format_ainvs
    info['curve_url'] = lambda dbc: url_for(".by_triple_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1], number=dbc['lmfdb_number'])
    info['iso_url'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1])
    info['number'] = nres
    info['start'] = start
    info['count'] = count
    info['more'] = int(start + count < nres)
    if nres == 1:
        info['report'] = 'unique match'
    elif nres == 2:
        info['report'] = 'displaying both matches'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres

    credit = 'John Cremona'
    if 'non-surjective_primes' in query:
        credit += 'and Andrew Sutherland'
    t = 'Elliptic Curves search results'
    return render_template("search_results.html", info=info, credit=credit, bread=bread, title=t)
Beispiel #18
0
def parse_artin_label(label):
    label = clean_input(label)
    if LABEL_RE.match(label):
        return label
    else:
        raise ValueError
Beispiel #19
0
def parse_artin_label(label):
    label = clean_input(label)
    if LABEL_RE.match(label):
        return label
    else:
        raise ValueError("Error parsing input %s.  It is not in a valid form for an Artin representation label, such as 9.2e12_587e3.10t32.1c1"% label)
Beispiel #20
0
def elliptic_curve_search(**args):
    info = to_dict(args)
    query = {}
    bread = [("Elliptic Curves", url_for("rational_elliptic_curves")), ("Search Results", ".")]
    if "jump" in args:
        label = info.get("label", "").replace(" ", "")
        m = lmfdb_label_regex.match(label)
        if m:
            try:
                return by_ec_label(label)
            except ValueError:
                return elliptic_curve_jump_error(label, info, wellformed_label=True)
        elif label.startswith("Cremona:"):
            label = label[8:]
            m = cremona_label_regex.match(label)
            if m:
                try:
                    return by_ec_label(label)
                except ValueError:
                    return elliptic_curve_jump_error(label, info, wellformed_label=True)
        elif cremona_label_regex.match(label):
            return elliptic_curve_jump_error(label, info, cremona_label=True)
        elif label:
            # Try to parse a string like [1,0,3,2,4]
            lab = re.sub(r"\s", "", label)
            lab = re.sub(r"^\[", "", lab)
            lab = re.sub(r"]$", "", lab)
            try:
                labvec = lab.split(",")
                labvec = [QQ(str(z)) for z in labvec]  # Rationals allowed
                E = EllipticCurve(labvec)
                ainvs = [str(c) for c in E.minimal_model().ainvs()]
                C = lmfdb.base.getDBConnection()
                data = C.elliptic_curves.curves.find_one({"ainvs": ainvs})
                if data is None:
                    return elliptic_curve_jump_error(label, info)
                return by_ec_label(data["lmfdb_label"])
            except (ValueError, ArithmeticError):
                return elliptic_curve_jump_error(label, info)
        else:
            query["label"] = ""

    if info.get("jinv"):
        j = clean_input(info["jinv"])
        j = j.replace("+", "")
        if not QQ_RE.match(j):
            info["err"] = "Error parsing input for the j-invariant.  It needs to be a rational number."
            return search_input_error(info, bread)
        query["jinv"] = j

    for field in ["conductor", "torsion", "rank", "sha_an"]:
        if info.get(field):
            info[field] = clean_input(info[field])
            ran = info[field]
            ran = ran.replace("..", "-").replace(" ", "")
            if not LIST_RE.match(ran):
                names = {
                    "conductor": "conductor",
                    "torsion": "torsion order",
                    "rank": "rank",
                    "sha_an": "analytic order of &#1064;",
                }
                info["err"] = (
                    "Error parsing input for the %s.  It needs to be an integer (such as 5), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 2,3,8 or 3-5, 7, 8-11)."
                    % names[field]
                )
                return search_input_error(info, bread)
            # Past input check
            tmp = parse_range2(ran, field)
            # work around syntax for $or
            # we have to foil out multiple or conditions
            if tmp[0] == "$or" and "$or" in query:
                newors = []
                for y in tmp[1]:
                    oldors = [dict.copy(x) for x in query["$or"]]
                    for x in oldors:
                        x.update(y)
                    newors.extend(oldors)
                tmp[1] = newors
            if field == "sha_an":  # database sha_an values are not all exact!
                query[tmp[0]] = {"$gt": tmp[1] - 0.1, "$lt": tmp[1] + 0.1}
                print query
            else:
                query[tmp[0]] = tmp[1]

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

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

    info["query"] = query

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

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

    print query
    cursor = lmfdb.base.getDBConnection().elliptic_curves.curves.find(query)
    nres = cursor.count()
    if start >= nres:
        start -= (1 + (start - nres) / count) * count
    if start < 0:
        start = 0
    res = (
        cursor.sort([("conductor", ASCENDING), ("lmfdb_iso", ASCENDING), ("lmfdb_number", ASCENDING)])
        .skip(start)
        .limit(count)
    )
    info["curves"] = res
    info["format_ainvs"] = format_ainvs
    info["number"] = nres
    info["start"] = start
    if nres == 1:
        info["report"] = "unique match"
    else:
        if nres > count or start != 0:
            info["report"] = "displaying matches %s-%s of %s" % (start + 1, min(nres, start + count), nres)
        else:
            info["report"] = "displaying all %s matches" % nres
    credit = "John Cremona"
    t = "Elliptic Curves"
    return render_template("elliptic_curve/elliptic_curve_search.html", info=info, credit=credit, bread=bread, title=t)
Beispiel #21
0
def elliptic_curve_search(**args):
    info = to_dict(args["data"])
    if "jump" in info:
        label = info.get("label", "").replace(" ", "")
        # This label should be a full isogeny class label or a full
        # curve label (including the field_label component)
        try:
            nf, cond_label, iso_label, number = split_full_label(label)
        except IndexError:
            if not "query" in info:
                info["query"] = {}
            bread = [("Elliptic Curves", url_for(".index"))]
            info["err"] = "No elliptic curve in the database has label %s." % label
            return search_input_error(info, bread)

        return show_ecnf(nf, cond_label, iso_label, number)

    query = {}
    bread = [("Elliptic Curves", url_for(".index")), ("Search Results", ".")]

    if "conductor_norm" in info:
        Nnorm = clean_input(info["conductor_norm"])
        Nnorm = Nnorm.replace("..", "-").replace(" ", "")
        tmp = parse_range2(Nnorm, "conductor_norm")
        if tmp[0] == "$or" and "$or" in query:
            newors = []
            for y in tmp[1]:
                oldors = [dict.copy(x) for x in query["$or"]]
                for x in oldors:
                    x.update(y)
                newors.extend(oldors)
            tmp[1] = newors
        query[tmp[0]] = tmp[1]

    if "conductor_label" in info:
        query["conductor_label"] = info["conductor_label"]

    if "jinv" in info:
        query["jinv"] = info["jinv"]

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

    if "torsion_structure" in info and info["torsion_structure"]:
        res = parse_torsion_structure(info["torsion_structure"], 2)
        if "Error" in res:
            info["err"] = res
            return search_input_error(info, bread)
        # update info for repeat searches
        info["torsion_structure"] = str(res).replace(" ", "")
        query["torsion_structure"] = [int(r) for r in res]

    if "include_isogenous" in info and info["include_isogenous"] == "off":
        query["number"] = 1

    if "include_base_change" in info and info["include_base_change"] == "off":
        query["base_change"] = []
    else:
        info["include_base_change"] = "on"

    if "field" in info:
        query["field_label"] = parse_field_string(info["field"])

    info["query"] = query

    # process count and start if not default:

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

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

    # make the query and trim results according to start/count:

    cursor = db_ecnf().find(query)
    nres = cursor.count()
    if start >= nres:
        start -= (1 + (start - nres) / count) * count
    if start < 0:
        start = 0
    res = (
        cursor.sort(
            [
                ("field_label", ASC),
                ("conductor_norm", ASC),
                ("conductor_label", ASC),
                ("iso_label", ASC),
                ("number", ASC),
            ]
        )
        .skip(start)
        .limit(count)
    )

    res = list(res)
    for e in res:
        e["numb"] = str(e["number"])
        e["field_knowl"] = nf_display_knowl(e["field_label"], getDBConnection(), e["field_label"])

    info["curves"] = res  # [ECNF(e) for e in res]
    info["number"] = nres
    info["start"] = start
    info["count"] = count
    info["more"] = int(start + count < nres)
    info["field_pretty"] = field_pretty
    info["web_ainvs"] = web_ainvs
    if nres == 1:
        info["report"] = "unique match"
    else:
        if nres > count or start != 0:
            info["report"] = "displaying matches %s-%s of %s" % (start + 1, min(nres, start + count), nres)
        else:
            info["report"] = "displaying all %s matches" % nres
    t = "Elliptic Curve search results"
    return render_template("ecnf-search-results.html", info=info, credit=ecnf_credit, bread=bread, title=t)
Beispiel #22
0
def elliptic_curve_search(**args):
    info = to_dict(args['data'])
    if 'jump' in info:
        label = info.get('label', '').replace(" ", "")
        # This label should be a full isogeny class label or a full
        # curve label (including the field_label component)
        try:
            nf, cond_label, iso_label, number = split_full_label(label)
        except IndexError:
            if not 'query' in info:
                info['query'] = {}
            bread = [("Elliptic Curves", url_for(".index"))]
            info['err'] = 'No elliptic curve in the database has label %s.' % label
            return search_input_error(info, bread)

        return show_ecnf(nf, cond_label, iso_label, number)

    query = {}
    bread = [('Elliptic Curves', url_for(".index")),
             ('Search Results', '.')]

    if 'conductor_norm' in info:
        Nnorm = clean_input(info['conductor_norm'])
        Nnorm = Nnorm.replace('..', '-').replace(' ', '')
        tmp = parse_range2(Nnorm, 'conductor_norm')
        if tmp[0] == '$or' and '$or' in query:
            newors = []
            for y in tmp[1]:
                oldors = [dict.copy(x) for x in query['$or']]
                for x in oldors:
                    x.update(y)
                newors.extend(oldors)
            tmp[1] = newors
        query[tmp[0]] = tmp[1]

    if 'conductor_label' in info:
        query['conductor_label'] = info['conductor_label']

    if 'jinv' in info:
        query['jinv'] = info['jinv']

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

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

    if 'include_isogenous' in info and info['include_isogenous'] == 'off':
        query['number'] = 1

    if 'include_base_change' in info and info['include_base_change'] == 'off':
        query['base_change'] = []
    else:
        info['include_base_change'] = "on"

    if 'field' in info:
        query['field_label'] = parse_field_string(info['field'])

    info['query'] = query

# process count and start if not default:

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

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

# make the query and trim results according to start/count:

    cursor = db_ecnf().find(query)
    nres = cursor.count()
    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0
    res = cursor.sort([('field_label', ASC), ('conductor_norm', ASC), ('conductor_label', ASC), ('iso_label', ASC), ('number', ASC)]).skip(start).limit(count)

    res = list(res)
    for e in res:
        e['numb'] = str(e['number'])
        e['field_knowl'] = nf_display_knowl(e['field_label'], getDBConnection(), e['field_label'])

    info['curves'] = res  # [ECNF(e) for e in res]
    info['number'] = nres
    info['start'] = start
    info['count'] = count
    info['more'] = int(start + count < nres)
    info['field_pretty'] = field_pretty
    info['web_ainvs'] = web_ainvs
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres
    t = 'Elliptic Curve search results'
    return render_template("ecnf-search-results.html", info=info, credit=ecnf_credit, bread=bread, title=t)
Beispiel #23
0
def number_field_search(**args):
    info = to_dict(args)

    info["learnmore"] = [
        ("Global number field labels", url_for(".render_labels_page")),
        ("Galois group labels", url_for(".render_groups_page")),
        (Completename, url_for(".render_discriminants_page")),
    ]
    t = "Global Number Field search results"
    bread = [("Global Number Fields", url_for(".number_field_render_webpage")), ("Search results", " ")]

    # for k in info.keys():
    #  nf_logger.debug(str(k) + ' ---> ' + str(info[k]))
    # nf_logger.debug('******************* '+ str(info['search']))
    if "natural" in info:
        field_id = info["natural"]
        field_id_parsed = parse_field_string(info["natural"])
        if FIELD_LABEL_RE.match(field_id_parsed):
            field_id_parsed = split_label(field_id_parsed)  # allows factored labels 11.11.11e20.1
        return render_field_webpage({"label": field_id_parsed, "label_orig": field_id})
    query = {}
    dlist = []
    for field in ["galois_group", "degree", "signature", "discriminant", "class_number", "class_group"]:
        if info.get(field):
            info[field] = clean_input(info[field])
            if field in ["class_group", "signature"]:
                # different regex for the two types
                if (field == "signature" and PAIR_RE.match(info[field])) or (
                    field == "class_group" and IF_RE.match(info[field])
                ):
                    query[field] = info[field][1:-1]
                else:
                    name = "class group" if field == "class_group" else "signature"
                    info["err"] = (
                        "Error parsing input for %s.  It needs to be a pair of integers in square brackets, such as [2,3] or [3,3]"
                        % name
                    )
                    return search_input_error(info, bread)
            else:
                if field == "galois_group":
                    try:
                        gcs = complete_group_codes(info[field])
                        if len(gcs) == 1:
                            query["galois"] = make_galois_pair(gcs[0][0], gcs[0][1])
                        # list(gcs[0])
                        if len(gcs) > 1:
                            query["galois"] = {"$in": [make_galois_pair(x[0], x[1]) for x in gcs]}
                    except NameError as code:
                        info["err"] = (
                            'Error parsing input for Galois group: unknown group label %s.  It needs to be a <a title = "Galois group labels" knowl="nf.galois_group.name">group label</a>, such as C5 or 5T1, or comma separated list of labels.'
                            % code
                        )
                        return search_input_error(info, bread)
                else:  # not signature, class group, or galois group
                    ran = info[field]
                    ran = ran.replace("..", "-")
                    if LIST_RE.match(ran):
                        if field == "discriminant":
                            # dlist will contain the disc conditions
                            # as sage ints
                            dlist = parse_discs(ran)
                            # now convert to a query
                            tmp = list_to_query(dlist)
                            # Two cases, could be a list of sign/inequalties
                            # or an '$or'
                            if len(tmp) == 1:
                                tmp = tmp[0]
                            else:
                                query[tmp[0][0]] = tmp[0][1]
                                tmp = tmp[1]
                        else:
                            tmp = parse_range2(ran, field)
                        # work around syntax for $or
                        # we have to foil out multiple or conditions
                        if tmp[0] == "$or" and "$or" in query:
                            newors = []
                            for y in tmp[1]:
                                oldors = [dict.copy(x) for x in query["$or"]]
                                for x in oldors:
                                    x.update(y)
                                newors.extend(oldors)
                            tmp[1] = newors
                        query[tmp[0]] = tmp[1]
                    else:
                        name = re.sub("_", " ", field)
                        info["err"] = (
                            "Error parsing input for %s.  It needs to be an integer (such as 5), a range of integers (such as 2-100 or 2..100), or a comma-separated list of these (such as 2,3,8 or 3-5, 7, 8-100)."
                            % name
                        )
                        return search_input_error(info, bread)
    if info.get("ur_primes"):
        # now we want a list of strings, no spaces, which might be big ints
        info["ur_primes"] = clean_input(info["ur_primes"])
        if LIST_SIMPLE_RE.match(info["ur_primes"]):
            ur_primes = info["ur_primes"].split(",")
            # Assuming this will be the only nor in the query
            query["$nor"] = [{"ramps": x} for x in ur_primes]
        else:
            info[
                "err"
            ] = "Error parsing input for unramified primes.  It needs to be an integer (such as 5), or a comma-separated list of integers (such as 2,3,11)."
            return search_input_error(info, bread)
    if info.get("ram_primes"):
        # now we want a list of strings, no spaces, which might be big ints
        info["ram_primes"] = clean_input(info["ram_primes"])
        if LIST_SIMPLE_RE.match(info["ram_primes"]):
            ram_primes = info["ram_primes"].split(",")
            if str(info["ram_quantifier"]) == "some":
                query["ramps"] = {"$all": ram_primes}
            else:
                query["ramps"] = ram_primes
        else:
            info[
                "err"
            ] = "Error parsing input for ramified primes.  It needs to be an integer (such as 5), or a comma-separated list of integers (such as 2,3,11)."
            return search_input_error(info, bread)

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

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

    C = base.getDBConnection()
    # nf_logger.debug(query)
    info["query"] = dict(query)
    if "lucky" in args:
        one = C.numberfields.fields.find_one(query)
        if one:
            label = one["label"]
            return render_field_webpage({"label": label})

    fields = C.numberfields.fields

    res = fields.find(query).sort([("degree", ASC), ("disc_abs_key", ASC), ("disc_sign", ASC), ("label", ASC)])

    if "download" in info and info["download"] != "0":
        return download_search(info, res)

    nres = res.count()
    res = res.skip(start).limit(count)

    if start >= nres:
        start -= (1 + (start - nres) / count) * count
    if start < 0:
        start = 0

    info["fields"] = res
    info["number"] = nres
    info["start"] = start
    if nres == 1:
        info["report"] = "unique match"
    else:
        if nres > count or start != 0:
            info["report"] = "displaying matches %s-%s of %s" % (start + 1, min(nres, start + count), nres)
        else:
            info["report"] = "displaying all %s matches" % nres

    info["wnf"] = WebNumberField.from_data
    return render_template("number_field_search.html", info=info, title=t, bread=bread)
Beispiel #24
0
def render_field_webpage(args):
    data = None
    C = base.getDBConnection()
    info = {}
    bread = [("Global Number Fields", url_for(".number_field_render_webpage"))]

    if "label" in args:
        label = clean_input(args["label"])
        nf = WebNumberField(label)
        data = {}
    if nf.is_null():
        bread.append(("Search results", " "))
        label2 = re.sub(r"[<>]", "", args["label"])
        if "You need to enter a field" in label2:
            info["err"] = label2
        else:
            info["err"] = "No such field: %s in the database" % label2
        info["label"] = args["label_orig"] if "label_orig" in args else args["label"]
        return search_input_error(info, bread)

    info["wnf"] = nf
    data["degree"] = nf.degree()
    data["class_number"] = nf.class_number()
    t = nf.galois_t()
    n = nf.degree()
    data["is_galois"] = nf.is_galois()
    data["is_abelian"] = nf.is_abelian()
    if nf.is_abelian():
        conductor = nf.conductor()
        data["conductor"] = conductor
        dirichlet_chars = nf.dirichlet_group()
        if len(dirichlet_chars) > 0:
            data["dirichlet_group"] = [
                '<a href = "%s">$\chi_{%s}(%s,&middot;)$</a>'
                % (url_character(type="Dirichlet", modulus=data["conductor"], number=j), data["conductor"], j)
                for j in dirichlet_chars
            ]
            data["dirichlet_group"] = r"$\lbrace$" + ", ".join(data["dirichlet_group"]) + r"$\rbrace$"
        if data["conductor"].is_prime() or data["conductor"] == 1:
            data["conductor"] = "\(%s\)" % str(data["conductor"])
        else:
            data["conductor"] = "\(%s=%s\)" % (str(data["conductor"]), latex(data["conductor"].factor()))
    data["galois_group"] = group_display_knowl(n, t, C)
    data["cclasses"] = cclasses_display_knowl(n, t, C)
    data["character_table"] = character_table_display_knowl(n, t, C)
    data["class_group"] = nf.class_group()
    data["class_group_invs"] = nf.class_group_invariants()
    data["signature"] = nf.signature()
    data["coefficients"] = nf.coeffs()
    D = nf.disc()
    ram_primes = D.prime_factors()
    data["disc_factor"] = nf.disc_factored_latex()
    if D.abs().is_prime() or D == 1:
        data["discriminant"] = "\(%s\)" % str(D)
    else:
        data["discriminant"] = "\(%s=%s\)" % (str(D), data["disc_factor"])
    npr = len(ram_primes)
    ram_primes = str(ram_primes)[1:-1]
    if ram_primes == "":
        ram_primes = r"\textrm{None}"
    data["frob_data"], data["seeram"] = frobs(nf.K())
    data["phrase"] = group_phrase(n, t, C)
    zk = pari(nf.K()).nf_subst("a")
    zk = list(zk.nf_get_zk())
    Ra = PolynomialRing(QQ, "a")
    zk = [latex(Ra(x)) for x in zk]
    zk = ["$%s$" % x for x in zk]
    zk = ", ".join(zk)
    grh_label = (
        '<small>(<a title="assuming GRH" knowl="nf.assuming_grh">assuming GRH</a>)</small>' if nf.used_grh() else ""
    )
    # Short version for properties
    grh_lab = nf.short_grh_string()
    pretty_label = field_pretty(label)
    if label != pretty_label:
        pretty_label = "%s: %s" % (label, pretty_label)

    info.update(data)
    info.update(
        {
            "label": pretty_label,
            "label_raw": label,
            "polynomial": web_latex_split_on_pm(nf.K().defining_polynomial()),
            "ram_primes": ram_primes,
            "integral_basis": zk,
            "regulator": web_latex(nf.regulator()),
            "unit_rank": nf.unit_rank(),
            "root_of_unity": web_latex(nf.K().primitive_root_of_unity()),
            "fund_units": nf.units(),
            "grh_label": grh_label,
        }
    )

    bread.append(("%s" % info["label_raw"], " "))
    info["downloads_visible"] = True
    info["downloads"] = [("worksheet", "/")]
    info["friends"] = []
    if nf.can_class_number():
        info["friends"].append(("L-function", "/L/NumberField/%s" % label))
    info["friends"].append(("Galois group", "/GaloisGroup/%dT%d" % (n, t)))
    if "dirichlet_group" in info:
        info["friends"].append(
            (
                "Dirichlet group",
                url_for(
                    "characters.dirichlet_group_table",
                    modulus=int(conductor),
                    char_number_list=",".join([str(a) for a in dirichlet_chars]),
                    poly=info["polynomial"],
                ),
            )
        )
    info["learnmore"] = [
        ("Global number field labels", url_for(".render_labels_page")),
        (Completename, url_for(".render_discriminants_page")),
    ]
    # With Galois group labels, probably not needed here
    # info['learnmore'] = [('Global number field labels',
    # url_for(".render_labels_page")), ('Galois group
    # labels',url_for(".render_groups_page")),
    # (Completename,url_for(".render_discriminants_page"))]
    title = "Global Number Field %s" % info["label"]

    if npr == 1:
        primes = "prime"
    else:
        primes = "primes"

    properties2 = [
        ("Degree:", "%s" % data["degree"]),
        ("Signature:", "$%s$" % data["signature"]),
        ("Discriminant:", "$%s$" % data["disc_factor"]),
        ("Ramified " + primes + ":", "$%s$" % ram_primes),
        ("Class number:", "%s %s" % (data["class_number"], grh_lab)),
        ("Class group:", "%s %s" % (data["class_group_invs"], grh_lab)),
        ("Galois Group:", group_display_short(data["degree"], t, C)),
    ]
    from lmfdb.math_classes import NumberFieldGaloisGroup

    try:
        info["tim_number_field"] = NumberFieldGaloisGroup.find_one({"label": label})
        v = nf.factor_perm_repn(info["tim_number_field"])
        info["mydecomp"] = ["*" if x > 0 else "" for x in v]
    except AttributeError:
        pass
    #    del info['_id']
    return render_template(
        "number_field.html",
        properties2=properties2,
        credit=NF_credit,
        title=title,
        bread=bread,
        friends=info.pop("friends"),
        learnmore=info.pop("learnmore"),
        info=info,
    )
Beispiel #25
0
def local_field_search(**args):
    info = to_dict(args)
    bread = get_bread([("Search results", url_for('.search'))])
    C = base.getDBConnection()
    query = {}
    if 'jump_to' in info:
        return render_field_webpage({'label': info['jump_to']})

    for param in ['p', 'n', 'c', 'e', 'gal']:
        if info.get(param):
            info[param] = clean_input(info[param])
            if param == 'gal':
                try:
                    gcs = complete_group_codes(info[param])
                    if len(gcs) == 1:
                        tmp = ['gal', list(gcs[0])]
                    if len(gcs) > 1:
                        tmp = [{'gal': list(x)} for x in gcs]
                        tmp = ['$or', tmp]
                except NameError as code:
                    info['err'] = 'Error parsing input for Galois group: unknown group label %s.  It needs to be a <a title = "Galois group labels" knowl="nf.galois_group.name">group label</a>, such as C5 or 5T1, or comma separated list of labels.' % code
                    return search_input_error(info, bread)
            else:
                ran = info[param]
                ran = ran.replace('..', '-')
                if LIST_RE.match(ran):
                    tmp = parse_range2(ran, param)
                else:
                    names = {'p': 'prime p', 'n': 'degree', 'c':
                             'discriminant exponent c', 'e': 'ramification index e'}
                    info['err'] = 'Error parsing input for the %s.  It needs to be an integer (such as 5), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 2,3,8 or 3-5, 7, 8-11).' % names[param]
                    return search_input_error(info, bread)
            # work around syntax for $or
            # we have to foil out multiple or conditions
            if tmp[0] == '$or' and '$or' in query:
                newors = []
                for y in tmp[1]:
                    oldors = [dict.copy(x) for x in query['$or']]
                    for x in oldors:
                        x.update(y)
                    newors.extend(oldors)
                tmp[1] = newors
            query[tmp[0]] = tmp[1]

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

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

    # logger.debug(query)
    res = C.localfields.fields.find(query).sort([('p', pymongo.ASCENDING), (
        'n', pymongo.ASCENDING), ('c', pymongo.ASCENDING), ('label', pymongo.ASCENDING)])
    nres = res.count()
    res = res.skip(start).limit(count)

    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0

    info['fields'] = res
    info['number'] = nres
    info['group_display'] = group_display_shortC(C)
    info['display_poly'] = format_coeffs
    info['slopedisp'] = show_slope_content
    info['start'] = start
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres

    return render_template("lf-search.html", info=info, title="Local Number Field Search Result", bread=bread, credit=LF_credit)
Beispiel #26
0
def render_field_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        C = base.getDBConnection()
        data = C.localfields.fields.find_one({'label': label})
        if data is None:
            bread = get_bread([("Search error", url_for('.search'))])
            info['err'] = "Field " + label + " was not found in the database."
            info['label'] = label
            return search_input_error(info, bread)
        title = 'Local Number Field:' + label
        polynomial = coeff_to_poly(data['coeffs'])
        p = data['p']
        e = data['e']
        f = data['f']
        cc = data['c']
        GG = data['gal']
        gn = GG[0]
        gt = GG[1]
        prop2 = [
            ('Base', '\(\Q_{%s}\)' % p),
            ('Degree', '\(%s\)' % data['n']),
            ('e', '\(%s\)' % e),
            ('f', '\(%s\)' % f),
            ('c', '\(%s\)' % cc),
            ('Galois group', group_display_short(gn, gt, C)),
        ]
        Pt = PolynomialRing(QQ, 't')
        Pyt = PolynomialRing(Pt, 'y')
        eisenp = Pyt(str(data['eisen']))
        unramp = Pyt(str(data['unram']))
        # Look up the unram poly so we can link to it
        unramdata = C.localfields.fields.find_one({'p': p, 'n': f, 'c': 0})
        if len(unramdata) > 0:
            unramfriend = "/LocalNumberField/%s" % unramdata['label']
        else:
            logger.fatal("Cannot find unramified field!")
            unramfriend = ''
        rfdata = C.localfields.fields.find_one({'p': p, 'n': {'$in': [1, 2]}, 'rf': data['rf']})
        if rfdata is None:
            logger.fatal("Cannot find discriminant root field!")
            rffriend = ''
        else:
            rffriend = "/LocalNumberField/%s" % rfdata['label']

        info.update({
                    'polynomial': web_latex(polynomial),
                    'n': data['n'],
                    'p': data['p'],
                    'c': data['c'],
                    'e': data['e'],
                    'f': data['f'],
                    't': data['t'],
                    'u': data['u'],
                    'rf': printquad(data['rf'], p),
                    'hw': data['hw'],
                    'slopes': show_slopes(data['slopes']),
                    'gal': group_display_knowl(gn, gt, C),
                    'gt': gt,
                    'inertia': group_display_inertia(data['inertia'], C),
                    'unram': web_latex(unramp),
                    'eisen': web_latex(eisenp),
                    'gms': data['gms'],
                    'aut': data['aut'],
                    })
        friends = [('Galois group', "/GaloisGroup/%dT%d" % (gn, gt))]
        if unramfriend != '':
            friends.append(('Unramified subfield', unramfriend))
        if rffriend != '':
            friends.append(('Discriminant root field', rffriend))

        bread = get_bread([(label, ' ')])
        return render_template("lf-show-field.html", credit=LF_credit, title=title, bread=bread, info=info, properties2=prop2, friends=friends)
Beispiel #27
0
def elliptic_curve_search(**args):
    info = to_dict(args["data"])
    if "jump" in info:
        label = info.get("label", "").replace(" ", "")
        # This label should be a full isogeny class label or a full
        # curve label (including the field_label component)
        label_parts = label.split("-", 2)
        nf = label_parts[0]
        cond_label = label_parts[1]
        cur_label = label_parts[2]
        return show_ecnf(nf, cond_label, cur_label)  ##!!!

    query = {}

    if "conductor_norm" in info:
        Nnorm = clean_input(info["conductor_norm"])
        Nnorm = Nnorm.replace("..", "-").replace(" ", "")
        tmp = parse_range2(Nnorm, "conductor_norm")
        if tmp[0] == "$or" and "$or" in query:
            newors = []
            for y in tmp[1]:
                oldors = [dict.copy(x) for x in query["$or"]]
                for x in oldors:
                    x.update(y)
                newors.extend(oldors)
            tmp[1] = newors
        query[tmp[0]] = tmp[1]

    if "conductor_label" in info:
        query["conductor_label"] = info["conductor_label"]

    if "include_isogenous" in info and info["include_isogenous"] == "off":
        query["number"] = 1

    if "field" in info:
        query["field_label"] = info["field"]

    info["query"] = query

    # process count and start if not default:

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

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

    # make the query and trim results according to start/count:

    cursor = db_ecnf().find(query)
    nres = cursor.count()
    if start >= nres:
        start -= (1 + (start - nres) / count) * count
    if start < 0:
        start = 0
    res = (
        cursor.sort(
            [
                ("field_label", ASC),
                ("conductor_norm", ASC),
                ("conductor_label", ASC),
                ("iso_label", ASC),
                ("number", ASC),
            ]
        )
        .skip(start)
        .limit(count)
    )

    bread = [("Elliptic Curves", url_for(".index")), ("Search Results", ".")]

    res = list(res)
    for e in res:
        e["numb"] = str(e["number"])
        e["field_knowl"] = nf_display_knowl(e["field_label"], getDBConnection(), e["field_label"])

    info["curves"] = res  # [ECNF(e) for e in res]
    info["number"] = nres
    info["start"] = start
    info["count"] = count
    info["more"] = int(start + count < nres)
    info["field_pretty"] = field_pretty
    info["web_ainvs"] = web_ainvs
    if nres == 1:
        info["report"] = "unique match"
    else:
        if nres > count or start != 0:
            info["report"] = "displaying matches %s-%s of %s" % (start + 1, min(nres, start + count), nres)
        else:
            info["report"] = "displaying all %s matches" % nres
    t = "Elliptic Curve search results"
    return render_template("ecnf-search-results.html", info=info, credit=ecnf_credit, bread=bread, title=t)
Beispiel #28
0
def galois_group_search(**args):
    info = to_dict(args)
    bread = get_bread([("Search results", url_for('.search'))])
    C = base.getDBConnection()
    query = {}
    if 'jump_to' in info:
        return render_group_webpage({'label': info['jump_to']})

    for param in ['n', 't']:
        if info.get(param):
            info[param] = clean_input(info[param])
            ran = info[param]
            ran = ran.replace('..', '-')
            if LIST_RE.match(ran):
                tmp = parse_range2(ran, param)
            else:
                names = {'n': 'degree', 't': 't'}
                info[
                    'err'] = 'Error parsing input for the %s.  It needs to be an integer (such as 5), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 2,3,8 or 3-5, 7, 8-11).' % names[
                        param]
                return search_input_error(info, bread)
            # work around syntax for $or
            # we have to foil out multiple or conditions
            if tmp[0] == '$or' and '$or' in query:
                newors = []
                for y in tmp[1]:
                    oldors = [dict.copy(x) for x in query['$or']]
                    for x in oldors:
                        x.update(y)
                    newors.extend(oldors)
                tmp[1] = newors
            query[tmp[0]] = tmp[1]
    for param in ['cyc', 'solv', 'prim', 'parity']:
        if info.get(param):
            info[param] = str(info[param])
            if info[param] == str(1):
                query[param] = 1
            elif info[param] == str(-1):
                query[param] = -1 if param == 'parity' else 0

    # Determine if we have any composite degrees
    info['show_subs'] = True
    if info.get('n'):
        info[
            'show_subs'] = False  # now only show subs if a composite n is allowed
        nparam = info.get('n')
        nparam.replace('..', '-')
        nlist = nparam.split(',')
        found = False
        for nl in nlist:
            if '-' in nl:
                inx = nl.index('-')
                ll, hh = nl[:inx], nl[inx + 1:]
                hh = int(hh)
                jj = int(ll)
                while jj <= hh and not found:
                    if not (ZZ(jj).is_prime() or ZZ(jj) == 1):
                        found = True
                    jj += 1
                if found:
                    break
            else:
                jj = ZZ(nl)
                if not (ZZ(jj).is_prime() or ZZ(jj) == 1):
                    found = True
                    break
        if found:
            info['show_subs'] = True

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

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

    res = C.transitivegroups.groups.find(query).sort([('n', pymongo.ASCENDING),
                                                      ('t', pymongo.ASCENDING)
                                                      ])
    nres = res.count()
    res = res.skip(start).limit(count)

    if (start >= nres):
        start -= (1 + (start - nres) / count) * count
    if (start < 0):
        start = 0

    info['groups'] = res
    info['group_display'] = group_display_shortC(C)
    info['report'] = "found %s groups" % nres
    info['yesno'] = yesno
    info['wgg'] = WebGaloisGroup.from_data
    info['start'] = start
    info['number'] = nres
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (
                start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres

    return render_template("gg-search.html",
                           info=info,
                           title="Galois Group Search Result",
                           bread=bread,
                           credit=GG_credit)
Beispiel #29
0
def render_hecke_algebras_webpage(**args):
    data = None
    if 'label' in args:
        lab = clean_input(args.get('label'))
        if lab != args.get('label'):
            return redirect(
                url_for('.render_hecke_algebras_webpage', label=lab), 301)
        data = db.hecke_algebras.lookup(lab)
    if data is None:
        t = "Hecke algebra search error"
        bread = [('HeckeAlgebra', url_for(".hecke_algebras_render_webpage"))]
        flash_error(
            "%s is not a valid label for a Hecke algebra in the database.",
            lab)
        return render_template("hecke_algebras-error.html",
                               title=t,
                               properties=[],
                               bread=bread,
                               learnmore=learnmore_list())
    info = {}
    info.update(data)

    bread = [('HeckeAlgebra', url_for(".hecke_algebras_render_webpage")),
             ('%s' % data['label'], ' ')]
    credit = hecke_algebras_credit
    info['level'] = int(data['level'])
    info['weight'] = int(data['weight'])
    info['num_orbits'] = int(data['num_orbits'])
    dim_count = "not available"

    proj = [
        'orbit_label', 'hecke_op', 'num_hecke_op', 'Zbasis', 'discriminant',
        'disc_fac', 'Qbasis', 'Qalg_gen'
    ]
    orb = list(db.hecke_orbits.search({'parent_label': data['label']}, proj))
    if orb:
        #consistency check
        if len(orb) != int(data['num_orbits']):
            return search_input_error(info)

        dim_count = 0
        for v in orb:
            ops = sage_eval(v['hecke_op'])
            dim = int(matrix(ops[0]).nrows())
            dim_count += dim
            if dim > 4:
                v['hecke_op_display'] = []
            elif dim == 1:
                v['hecke_op_display'] = [[i + 1, ops[i][0][0]]
                                         for i in range(10)]
            else:
                v['hecke_op_display'] = [[i + 1, latex(matrix(ops[i]))]
                                         for i in range(5)]
            v['download_op'] = [
                (lang,
                 url_for(".render_hecke_algebras_webpage_download",
                         orbit_label=v['orbit_label'],
                         lang=lang,
                         obj='operators')) for lang in ['gp', 'magma', 'sage']
            ]
            if v['Zbasis'] is None:
                for key in [
                        'Zbasis', 'discriminant', 'disc_fac', 'Qbasis',
                        'Qalg_gen'
                ]:
                    del v[key]
            else:
                v['Zbasis'] = [[int(i) for i in j] for j in v['Zbasis']]
                v['disc_fac'] = [[int(i) for i in j] for j in v['disc_fac']]
                if dim > 4:
                    v['gen_display'] = []
                elif dim == 1:
                    v['gen_display'] = [v['Zbasis'][0][0]]
                else:
                    v['gen_display'] = [
                        latex(matrix(dim, dim, v['Zbasis'][i]))
                        for i in range(dim)
                    ]
                v['inner_twists'] = "not available"  # not yet in the database
                v['download_gen'] = [
                    (lang,
                     url_for(".render_hecke_algebras_webpage_download",
                             orbit_label=v['orbit_label'],
                             lang=lang,
                             obj='gen')) for lang in ['gp', 'magma', 'sage']
                ]
        info['orbits'] = orb

    info['dim_alg'] = dim_count
    info['l_adic'] = l_range
    info['properties'] = [('Label', '%s' % info['label']),
                          ('Level', '%s' % info['level']),
                          ('Weight', '%s' % info['weight'])]
    if info['num_orbits'] != 0:
        info['friends'] = [('Newforms space ' + info['label'],
                            url_for("cmf.by_url_space_label",
                                    level=info['level'],
                                    weight=info['weight'],
                                    char_orbit_label='a'))]
    else:
        info['friends'] = []
    t = "Hecke algebra %s" % info['label']
    return render_template("hecke_algebras-single.html",
                           info=info,
                           credit=credit,
                           title=t,
                           bread=bread,
                           properties=info['properties'],
                           learnmore=learnmore_list(),
                           friends=info['friends'],
                           KNOWL_ID='hecke_algebra.%s' % (info['label']))
Beispiel #30
0
def elliptic_curve_search(**args):
    info = to_dict(args)
    query = {}
    bread = [('Elliptic Curves', url_for("rational_elliptic_curves")),
             ('Search Results', '.')]
    if 'jump' in args:
        label = info.get('label', '').replace(" ", "")
        m = lmfdb_label_regex.match(label)
        if m:
            try:
                return by_ec_label(label)
            except ValueError:
                return elliptic_curve_jump_error(label, info, wellformed_label=True)
        elif label.startswith("Cremona:"):
            label = label[8:]
            m = cremona_label_regex.match(label)
            if m:
                try:
                    return by_ec_label(label)
                except ValueError:
                    return elliptic_curve_jump_error(label, info, wellformed_label=True)
        elif cremona_label_regex.match(label):
            return elliptic_curve_jump_error(label, info, cremona_label=True)
        elif label:
            # Try to parse a string like [1,0,3,2,4]
            lab = re.sub(r'\s','',label)
            lab = re.sub(r'^\[','',lab)
            lab = re.sub(r']$','',lab)
            try:
                labvec = lab.split(',')
                labvec = [QQ(str(z)) for z in labvec] # Rationals allowed
                E = EllipticCurve(labvec)
                ainvs = [str(c) for c in E.minimal_model().ainvs()]
                C = lmfdb.base.getDBConnection()
                data = C.elliptic_curves.curves.find_one({'ainvs': ainvs})
                if data is None:
                    return elliptic_curve_jump_error(label, info)
                return by_ec_label(data['lmfdb_label'])
            except (ValueError, ArithmeticError):
                return elliptic_curve_jump_error(label, info)
        else:
            query['label'] = ''

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

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

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

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

    info['query'] = query

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

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

    print query
    cursor = lmfdb.base.getDBConnection().elliptic_curves.curves.find(query)
    nres = cursor.count()
    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0
    res = cursor.sort([('conductor', ASCENDING), ('lmfdb_iso', ASCENDING), ('lmfdb_number', ASCENDING)
                       ]).skip(start).limit(count)
    info['curves'] = res
    info['format_ainvs'] = format_ainvs
    info['number'] = nres
    info['start'] = start
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres
    credit = 'John Cremona'
    t = 'Elliptic Curves'
    return render_template("elliptic_curve/elliptic_curve_search.html", info=info, credit=credit, bread=bread, title=t)
Beispiel #31
0
def render_artin_representation_webpage(label):
    if re.compile(r'^\d+$').match(label):
        return artin_representation_search(**{'dimension': label})

    bread = get_bread([(label, ' ')])

    # label=dim.cond.nTt.indexcj, c is literal, j is index in conj class
    # Should we have a big try around this to catch bad labels?
    clean_label = clean_input(label)
    if clean_label != label:
        return redirect(url_for('.render_artin_representation_webpage', label=clean_label), 301)
    try:
        the_rep = ArtinRepresentation(label)
    except:
        flash(Markup("Error: <span style='color:black'>%s</span> is not the label of an Artin representation in the database." % (label)), "error")
        return search_input_error({'err':''}, bread)

    extra_data = {} # for testing?
    extra_data['galois_knowl'] = group_display_knowl(5,3) # for testing?
    #artin_logger.info("Found %s" % (the_rep._data))


    title = "Artin Representation %s" % label
    the_nf = the_rep.number_field_galois_group()
    if the_rep.sign() == 0:
        processed_root_number = "not computed"
    else:
        processed_root_number = str(the_rep.sign())
    properties = [("Label", label),
                  ("Dimension", str(the_rep.dimension())),
                  ("Group", the_rep.group()),
                  ("Conductor", "$" + the_rep.factored_conductor_latex() + "$"),
                  #("Bad primes", str(the_rep.bad_primes())),
                  ("Root number", processed_root_number),
                  ("Frobenius-Schur indicator", str(the_rep.indicator()))
                  ]

    friends = []
    nf_url = the_nf.url_for()
    if nf_url:
        friends.append(("Artin Field", nf_url))
    cc = the_rep.central_character()
    if cc is not None:
        if the_rep.dimension()==1:
            if cc.order == 2:
                cc_name = cc.symbol
            else:
                cc_name = cc.texname
            friends.append(("Dirichlet character "+cc_name, url_for("characters.render_Dirichletwebpage", modulus=cc.modulus, number=cc.number)))
        else:
            detrep = the_rep.central_character_as_artin_rep()
            friends.append(("Determinant representation "+detrep.label(), detrep.url_for()))
    add_lfunction_friends(friends,label)

    # once the L-functions are in the database, the link can always be shown
    #if the_rep.dimension() <= 6:
    if the_rep.dimension() == 1:
        # Zeta is loaded differently
        if cc.modulus == 1 and cc.number == 1:
            friends.append(("L-function", url_for("l_functions.l_function_dirichlet_page", modulus=cc.modulus, number=cc.number)))
        else:
            # looking for Lhash dirichlet_L_modulus.number
            mylhash = 'dirichlet_L_%d.%d'%(cc.modulus,cc.number)
            lres = db.lfunc_instances.lucky({'Lhash': mylhash})
            if lres is not None:
                friends.append(("L-function", url_for("l_functions.l_function_dirichlet_page", modulus=cc.modulus, number=cc.number)))

    # Dimension > 1
    elif int(the_rep.conductor())**the_rep.dimension() <= 729000000000000:
        friends.append(("L-function", url_for("l_functions.l_function_artin_page",
                                          label=the_rep.label())))
    info={}

    return render_template("artin-representation-show.html", credit=tim_credit, support=support_credit, title=title, bread=bread, friends=friends, object=the_rep, properties2=properties, extra_data=extra_data, info=info, learnmore=learnmore_list())
Beispiel #32
0
def elliptic_curve_search(**args):
    info = to_dict(args['data'])
    if 'jump' in info:
        label = info.get('label', '').replace(" ", "")
        label_parts = label.split("-",1)
        nf = label_parts[0]
        label = label_parts[1]
        return show_ecnf(nf,label)

    query = {}

    if 'conductor_norm' in info:
        Nnorm = clean_input(info['conductor_norm'])
        Nnorm = Nnorm.replace('..', '-').replace(' ', '')
        tmp = parse_range2(Nnorm, 'conductor_norm')
        if tmp[0] == '$or' and '$or' in query:
            newors = []
            for y in tmp[1]:
                oldors = [dict.copy(x) for x in query['$or']]
                for x in oldors:
                    x.update(y)
                newors.extend(oldors)
            tmp[1] = newors
        query[tmp[0]] = tmp[1]

    if 'include_isogenous' in info and info['include_isogenous'] == 'off':
        query['number'] = 1

    if 'field' in info:
        query['field_label'] = info['field']

    info['query'] = query

# process count and start if not default:

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

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

# make the query and trim results according to start/count:

    cursor = db_ecnf().find(query)
    nres = cursor.count()
    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0
    res = cursor.sort([('field_label', ASC), ('conductor_norm', ASC), ('conductor_label', ASC), ('iso_label', ASC), ('number', ASC)]).skip(start).limit(count)

    bread = []#[('Elliptic Curves over Number Fields', url_for(".elliptic_curve_search")),             ]
    bread = [('Elliptic Curves', url_for(".index")),
             ('Search Results', '.')]

    res = list(res)
    for e in res:
        e['field_knowl'] = nf_display_knowl(e['field_label'], getDBConnection(), e['field_label'])
    info['curves'] = res # [ECNF(e) for e in res]
    info['number'] = nres
    info['start'] = start
    info['count'] = count
    info['field_pretty'] = field_pretty
    info['web_ainvs'] = web_ainvs
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres
    t = 'Elliptic Curve search results'
    return render_template("ecnf-search-results.html", info=info, credit=ecnf_credit, bread=bread, title=t)
Beispiel #33
0
def parse_artin_orbit_label(label):
    label = clean_input(label)
    if ORBIT_RE.match(label):
        return label
    else:
        raise ValueError
Beispiel #34
0
def render_group_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        label = label.replace('t', 'T')
        C = base.getDBConnection()
        data = C.transitivegroups.groups.find_one({'label': label})
        if data is None:
            bread = get_bread([("Search error", url_for('.search'))])
            info['err'] = "Group " + label + " was not found in the database."
            info['label'] = label
            return search_input_error(info, bread)
        title = 'Galois Group:' + label
        wgg = WebGaloisGroup.from_data(data)
        n = data['n']
        t = data['t']
        data['yesno'] = yesno
        order = data['order']
        data['orderfac'] = latex(ZZ(order).factor())
        orderfac = latex(ZZ(order).factor())
        data['ordermsg'] = "$%s=%s$" % (order, latex(orderfac))
        if order == 1:
            data['ordermsg'] = "$1$"
        if ZZ(order).is_prime():
            data['ordermsg'] = "$%s$ (is prime)" % order
        pgroup = len(ZZ(order).prime_factors()) < 2
        if n == 1:
            G = gap.SmallGroup(n, t)
        else:
            G = gap.TransitiveGroup(n, t)
        if ZZ(order) < ZZ('10000000000'):
            ctable = chartable(n, t)
        else:
            ctable = 'Group too large'
        data['gens'] = generators(n, t)
        if n == 1 and t == 1:
            data['gens'] = 'None needed'
        data['chartable'] = ctable
        data['parity'] = "$%s$" % data['parity']
        data['cclasses'] = conjclasses(G, n)
        data['subinfo'] = subfield_display(C, n, data['subs'])
        data['resolve'] = resolve_display(C, data['resolve'])
#    if len(data['resolve']) == 0: data['resolve'] = 'None'
        data['otherreps'] = wgg.otherrep_list()
        query={'galois': bson.SON([('n', n), ('t', t)])}
        C = base.getDBConnection()
        intreps = C.transitivegroups.Gmodules.find({'n': n, 't': t})
        # turn cursor into a list
        intreps = [z for z in intreps]
        data['int_reps'] = [galois_module_knowl(n, t, z['index'], C) for z in intreps]
        data['int_reps_complete'] = int_reps_are_complete(intreps)

        friends = []
        one = C.numberfields.fields.find_one(query)
        if one:
            friends.append(('Number fields with this Galois group', url_for('number_fields.number_field_render_webpage')+"?galois_group=%dT%d" % (n, t) )) 
        prop2 = [
            ('Order:', '\(%s\)' % order),
            ('n:', '\(%s\)' % data['n']),
            ('Cyclic:', yesno(data['cyc'])),
            ('Abelian:', yesno(data['ab'])),
            ('Solvable:', yesno(data['solv'])),
            ('Primitive:', yesno(data['prim'])),
            ('$p$-group:', yesno(pgroup)),
            ('Name:', group_display_short(n, t, C)),
        ]
        info.update(data)

        bread = get_bread([(label, ' ')])
        return render_template("gg-show-group.html", credit=GG_credit, title=title, bread=bread, info=info, properties2=prop2, friends=friends)
Beispiel #35
0
def number_field_search(**args):
    info = to_dict(args)

    info['learnmore'] = [('Global number field labels', url_for(".render_labels_page")), ('Galois group labels', url_for(".render_groups_page")), (Completename, url_for(".render_discriminants_page"))]
    t = 'Global Number Field search results'
    bread = [('Global Number Fields', url_for(".number_field_render_webpage")), ('Search results', ' ')]

    # for k in info.keys():
    #  nf_logger.debug(str(k) + ' ---> ' + str(info[k]))
    # nf_logger.debug('******************* '+ str(info['search']))
    if 'natural' in info:
        field_id = info['natural']
        field_id_parsed = parse_field_string(info['natural'])
        if FIELD_LABEL_RE.match(field_id_parsed):
            field_id_parsed = split_label(field_id_parsed)  # allows factored labels 11.11.11e20.1
        return render_field_webpage({'label': field_id_parsed, 'label_orig': field_id})
    query = {}
    dlist = []
    for field in ['galois_group', 'degree', 'signature', 'discriminant', 'class_number', 'class_group']:
        if info.get(field):
            info[field] = clean_input(info[field])
            if field in ['class_group', 'signature']:
                # different regex for the two types
                if (field == 'signature' and PAIR_RE.match(info[field])) or (field == 'class_group' and IF_RE.match(info[field])):
                    query[field] = info[field][1:-1]
                else:
                    name = 'class group' if field == 'class_group' else 'signature'
                    info['err'] = 'Error parsing input for %s.  It needs to be a pair of integers in square brackets, such as [2,3] or [3,3]' % name
                    return search_input_error(info, bread)
            else:
                if field == 'galois_group':
                    try:
                        gcs = complete_group_codes(info[field])
                        if len(gcs) == 1:
                            query['galois'] = make_galois_pair(gcs[0][0], gcs[0][1])
# list(gcs[0])
                        if len(gcs) > 1:
                            query['galois'] = {'$in': [make_galois_pair(x[0], x[1]) for x in gcs]}
                    except NameError as code:
                        info['err'] = 'Error parsing input for Galois group: unknown group label %s.  It needs to be a <a title = "Galois group labels" knowl="nf.galois_group.name">group label</a>, such as C5 or 5T1, or comma separated list of labels.' % code
                        return search_input_error(info, bread)
                else:  # not signature, class group, or galois group
                    ran = info[field]
                    ran = ran.replace('..', '-')
                    if LIST_RE.match(ran):
                        if field == 'discriminant':
                            # dlist will contain the disc conditions
                            # as sage ints
                            dlist = parse_discs(ran)
                            # now convert to a query
                            tmp = list_to_query(dlist)
                            # Two cases, could be a list of sign/inequalties
                            # or an '$or'
                            if len(tmp) == 1:
                                tmp = tmp[0]
                            else:
                                query[tmp[0][0]] = tmp[0][1]
                                tmp = tmp[1]
                        else:
                            tmp = parse_range2(ran, field)
                        # work around syntax for $or
                        # we have to foil out multiple or conditions
                        if tmp[0] == '$or' and '$or' in query:
                            newors = []
                            for y in tmp[1]:
                                oldors = [dict.copy(x) for x in query['$or']]
                                for x in oldors:
                                    x.update(y)
                                newors.extend(oldors)
                            tmp[1] = newors
                        query[tmp[0]] = tmp[1]
                    else:
                        name = re.sub('_', ' ', field)
                        info['err'] = 'Error parsing input for %s.  It needs to be an integer (such as 5), a range of integers (such as 2-100 or 2..100), or a comma-separated list of these (such as 2,3,8 or 3-5, 7, 8-100).' % name
                        return search_input_error(info, bread)
    if info.get('ur_primes'):
        # now we want a list of strings, no spaces, which might be big ints
        info['ur_primes'] = clean_input(info['ur_primes'])
        if LIST_SIMPLE_RE.match(info['ur_primes']):
            ur_primes = info['ur_primes'].split(',')
            # Assuming this will be the only nor in the query
            query['$nor'] = [{'ramps': x} for x in ur_primes]
        else:
            info['err'] = 'Error parsing input for unramified primes.  It needs to be an integer (such as 5), or a comma-separated list of integers (such as 2,3,11).'
            return search_input_error(info, bread)
    if info.get('ram_primes'):
        # now we want a list of strings, no spaces, which might be big ints
        info['ram_primes'] = clean_input(info['ram_primes'])
        if LIST_SIMPLE_RE.match(info['ram_primes']):
            ram_primes = info['ram_primes'].split(',')
            if str(info['ram_quantifier']) == 'some':
                query['ramps'] = {'$all': ram_primes}
            else:
                query['ramps'] = ram_primes
        else:
            info['err'] = 'Error parsing input for ramified primes.  It needs to be an integer (such as 5), or a comma-separated list of integers (such as 2,3,11).'
            return search_input_error(info, bread)

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

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

    C = base.getDBConnection()
    # nf_logger.debug(query)
    info['query'] = dict(query)
    if 'lucky' in args:
        one = C.numberfields.fields.find_one(query)
        if one:
            label = one['label']
            return render_field_webpage({'label': label})

    fields = C.numberfields.fields

    res = fields.find(
        query).sort([('degree', ASC), ('disc_abs_key', ASC), ('disc_sign', ASC), ('label', ASC)])

    if 'download' in info and info['download'] != '0':
        return download_search(info, res)

    nres = res.count()
    res = res.skip(start).limit(count)

    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0

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

    info['wnf'] = WebNumberField.from_data
    return render_template("number_field_search.html", info=info, title=t, bread=bread)
Beispiel #36
0
def elliptic_curve_search(**args):
    info = to_dict(args)
    query = {}
    bread = [('Elliptic Curves', url_for("ecnf.index")),
             ('$\Q$', url_for(".rational_elliptic_curves")),
             ('Search Results', '.')]
    if 'SearchAgain' in args:
        return rational_elliptic_curves()

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

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

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

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

    if 'torsion_structure' in info and info['torsion_structure']:
        res = parse_torsion_structure(info['torsion_structure'])
        if 'Error' in res:
            info['err'] = res
            return search_input_error(info, bread)
        #update info for repeat searches
        info['torsion_structure'] = str(res).replace(' ','')
        query['torsion_structure'] = [str(r) for r in res]

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

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

    if 'download' in info and info['download'] != '0':
        res = db_ec().find(query).sort([ ('conductor', ASCENDING), ('lmfdb_iso', ASCENDING), ('lmfdb_number', ASCENDING) ])
        return download_search(info, res)
    
    count_default = 100
    if info.get('count'):
        try:
            count = int(info['count'])
        except:
            count = count_default
    else:
        count = count_default
    info['count'] = count

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

    cursor = db_ec().find(query)
    nres = cursor.count()
    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0
    res = cursor.sort([('conductor', ASCENDING), ('lmfdb_iso', ASCENDING), ('lmfdb_number', ASCENDING)
                       ]).skip(start).limit(count)
    info['curves'] = res
    info['format_ainvs'] = format_ainvs
    info['curve_url'] = lambda dbc: url_for(".by_triple_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1], number=dbc['lmfdb_number'])
    info['iso_url'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1])
    info['number'] = nres
    info['start'] = start
    if nres == 1:
        info['report'] = 'unique match'
    elif nres == 2:
        info['report'] = 'displaying both matches'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres
    credit = 'John Cremona'
    if 'non-surjective_primes' in query:
        credit += 'and Andrew Sutherland'
    t = 'Elliptic Curves search results'
    return render_template("search_results.html", info=info, credit=credit, bread=bread, title=t)
Beispiel #37
0
def by_label(label):
    clean_label = clean_input(label)
    if label != clean_label:
        return redirect(url_for_label(label=clean_label), 301)
    return render_field_webpage({'label': label})
Beispiel #38
0
def render_lattice_webpage(**args):
    f = None
    if 'label' in args:
        lab = clean_input(args.get('label'))
        if lab != args.get('label'):
            return redirect(url_for('.render_lattice_webpage', label=lab), 301)
        f = db.lat_lattices.lucky({'$or':[{'label': lab }, {'name': {'$contains': [lab]}}]})
    if f is None:
        t = "Integral Lattices Search Error"
        bread = [('Lattices', url_for(".lattice_render_webpage"))]
        flash(Markup("Error: <span style='color:black'>%s</span> is not a valid label or name for an integral lattice in the database." % (lab)),"error")
        return render_template("lattice-error.html", title=t, properties=[], bread=bread, learnmore=learnmore_list())
    info = {}
    info.update(f)

    info['friends'] = []

    bread = [('Lattice', url_for(".lattice_render_webpage")), ('%s' % f['label'], ' ')]
    credit = lattice_credit
    info['dim']= int(f['dim'])
    info['det']= int(f['det'])
    info['level']=int(f['level'])
    info['gram']=vect_to_matrix(f['gram'])
    info['density']=str(f['density'])
    info['hermite']=str(f['hermite'])
    info['minimum']=int(f['minimum'])
    info['kissing']=int(f['kissing'])
    info['aut']=int(f['aut'])

    if f['shortest']=="":
        info['shortest']==f['shortest']
    else:
        if f['dim']==1:
            info['shortest']=str(f['shortest']).strip('[').strip(']')
        else:
            if info['dim']*info['kissing']<100:
                info['shortest']=[str([tuple(v)]).strip('[').strip(']').replace('),', '), ') for v in f['shortest']]
            else:
                max_vect_num=min(int(round(100/(info['dim']))), int(round(info['kissing']/2))-1);
                info['shortest']=[str([tuple(f['shortest'][i])]).strip('[').strip(']').replace('),', '), ') for i in range(max_vect_num+1)]
                info['all_shortest']="no"
        info['download_shortest'] = [
            (i, url_for(".render_lattice_webpage_download", label=info['label'], lang=i, obj='shortest_vectors')) for i in ['gp', 'magma','sage']]

    if f['name']==['Leech']:
        info['shortest']=[str([1,-2,-2,-2,2,-1,-1,3,3,0,0,2,2,-1,-1,-2,2,-2,-1,-1,0,0,-1,2]), 
str([1,-2,-2,-2,2,-1,0,2,3,0,0,2,2,-1,-1,-2,2,-1,-1,-2,1,-1,-1,3]), str([1,-2,-2,-1,1,-1,-1,2,2,0,0,2,2,0,0,-2,2,-1,-1,-1,0,-1,-1,2])]
        info['all_shortest']="no"
        info['download_shortest'] = [
            (i, url_for(".render_lattice_webpage_download", label=info['label'], lang=i, obj='shortest_vectors')) for i in ['gp', 'magma','sage']]

    ncoeff=20
    if f['theta_series'] != "":
        coeff=[f['theta_series'][i] for i in range(ncoeff+1)]
        info['theta_series']=my_latex(print_q_expansion(coeff))
        info['theta_display'] = url_for(".theta_display", label=f['label'], number="")

    info['class_number']=int(f['class_number'])

    if f['dim']==1:
        info['genus_reps']=str(f['genus_reps']).strip('[').strip(']')
    else:
        if info['dim']*info['class_number']<50:
            info['genus_reps']=[vect_to_matrix(n) for n in f['genus_reps']]
        else:
            max_matrix_num=min(int(round(25/(info['dim']))), info['class_number']);
            info['all_genus_rep']="no"
            info['genus_reps']=[vect_to_matrix(f['genus_reps'][i]) for i in range(max_matrix_num+1)]
    info['download_genus_reps'] = [
        (i, url_for(".render_lattice_webpage_download", label=info['label'], lang=i, obj='genus_reps')) for i in ['gp', 'magma','sage']]

    if f['name'] != "":
        if f['name']==str(f['name']):
            info['name']= str(f['name'])
        else:
            info['name']=str(", ".join(str(i) for i in f['name']))
    else:
        info['name'] == ""
    info['comments']=str(f['comments'])
    if 'Leech' in info['comments']: # no need to duplicate as it is in the name
        info['comments'] = ''
    if info['name'] == "":
        t = "Integral Lattice %s" % info['label']
    else:
        t = "Integral Lattice "+info['label']+" ("+info['name']+")"
#This part code was for the dinamic knowl with comments, since the test is displayed this is redundant
#    if info['name'] != "" or info['comments'] !="":
#        info['knowl_args']= "name=%s&report=%s" %(info['name'], info['comments'].replace(' ', '-space-'))
    info['properties'] = [
        ('Dimension', '%s' %info['dim']),
        ('Determinant', '%s' %info['det']),
        ('Level', '%s' %info['level'])]
    if info['class_number'] == 0:
        info['properties']=[('Class number', 'not available')]+info['properties']
    else:
        info['properties']=[('Class number', '%s' %info['class_number'])]+info['properties']
    info['properties']=[('Label', '%s' % info['label'])]+info['properties']

    if info['name'] != "" :
        info['properties']=[('Name','%s' % info['name'] )]+info['properties']
#    friends = [('L-series (not available)', ' ' ),('Half integral weight modular forms (not available)', ' ')]
    return render_template("lattice-single.html", info=info, credit=credit, title=t, bread=bread, properties2=info['properties'], learnmore=learnmore_list(), KNOWL_ID="lattice.%s"%info['label'])
Beispiel #39
0
def render_hecke_algebras_webpage_l_adic(**args):
    data = None
    if 'orbit_label' in args and 'prime' in args:
        lab = clean_input(args.get('orbit_label'))
        if lab != args.get('orbit_label'):
            base_lab=".".join([split(lab)[i] for i in [0,1,2]])
            return redirect(url_for('.render_hecke_algebras_webpage', label=base_lab), 301)
        try:
            ell = int(args.get('prime'))
        except ValueError:
            base_lab=".".join([split(lab)[i] for i in [0,1,2]])
            return redirect(url_for('.render_hecke_algebras_webpage', label=base_lab), 301)
        data = db.hecke_ladic.lucky({'orbit_label': lab , 'ell': ell})
    if data is None:
        t = "Hecke Algebras Search Error"
        bread = [('HeckeAlgebra', url_for(".hecke_algebras_render_webpage"))]
        flash(Markup("Error: <span style='color:black'>%s</span> is not a valid label for the &#x2113;-adic information for an Hecke Algebra orbit in the database." % (lab)),"error")
        return render_template("hecke_algebras-error.html", title=t, properties=[], bread=bread, learnmore=learnmore_list())
    info = {}
    info.update(data)

    proj = ['index','orbit_label','ell','idempotent','field','structure','properties','operators']
    res = list(db.hecke_ladic.search({'level': data['level'],'weight': data['weight'],'orbit_label': data['orbit_label'], 'ell': data['ell']}, proj))

    for f in res:
        if f['idempotent'] != "":
            dim = len(sage_eval(f['idempotent']))
            l_max = sage_eval(f['idempotent'])[0][0].ndigits()
            if dim > 4 or l_max > 5:
                f['idempotent_display'] = []
            elif dim == 1:
                f['idempotent_display'] = sage_eval(f['idempotent'])[0][0]
            else:
                f['idempotent_display'] = latex(matrix(sage_eval(f['idempotent'])))
        else:
            f['idempotent_display']=latex(matrix([[1]]))
        del f['idempotent']
        f['download_id'] = [(i, url_for(".render_hecke_algebras_webpage_ell_download", orbit_label=f['orbit_label'], index=f['index'], prime=f['ell'], lang=i, obj='idempotents')) for i in ['magma','sage']]  # for 'gp' the code does not work, since p-adics are not implemented
        field = f.pop('field')
        if field is not None:
            f['deg'] = field[1]
            f['field_poly'] = field[2]
        structure = f.pop('structure')
        if structure is not None:
            f['dim'] = structure[0]
            f['num_gen'] = structure[1]
            s2 = sage_eval(structure[2])
            f['gens'] = [[int(s2.index(i)+1), str(i)] for i in s2]
            f['rel'] = sage_eval(structure[3])
        properties = f.pop('properties')
        if properties is not None:
            f['grading'] = properties[0]
            f['gorenstein_def'] = properties[1]
            f['gorenstein'] = "yes" if properties[1] == 0 else "no"
        operators = f.pop('operators')
        if operators is not None:
            f['operators_mod_l'] = operators
            f['num_hecke_op'] = len(operators)
            f['size_op'] = size = sqrt(len(operators[0]))
            if size > 4:
                f['operators_mod_l_display'] = []
            elif size == 1:
                f['operators_mod_l_display'] = [[i+1, operators[i][0]] for i in range(10)]
            else:
                f['operators_mod_l_display'] = [[i+1, latex(matrix(size,size,operators[i]))] for i in range(5)]
            f['download_op'] = [(lang, url_for(".render_hecke_algebras_webpage_ell_download", orbit_label=f['orbit_label'], index=f['index'], prime=f['ell'], lang=lang, obj='operators')) for lang in ['magma','sage']]  # for 'gp' the code does not work

    info['num_l_adic_orbits'] = len(res)
    info['l_adic_orbits'] = res
    info['level']=int(data['level'])
    info['weight']= int(data['weight'])
    info['base_lab']=".".join([split(data['orbit_label'])[i] for i in [0,1,2]])
    info['orbit_label']= str(data['orbit_label'])
    info['ell']=int(data['ell'])

    bread = [('HeckeAlgebra', url_for(".hecke_algebras_render_webpage")), ('%s' % info['base_lab'], url_for('.render_hecke_algebras_webpage', label=info['base_lab'])), ('%s' % info['ell'], ' ')]
    credit = hecke_algebras_credit
    info['properties'] = [
        ('Level', '%s' %info['level']),
        ('Weight', '%s' %info['weight']),
        ('Characteristic', '%s' %info['ell']),
        ('Orbit label', '%s' %info['orbit_label'])]
    info['friends'] = [('Modular form ' + info['base_lab'], url_for("cmf.by_url_space_label", level=info['level'], weight=info['weight'], char_orbit_label='a'))]

    t = "%s-adic and mod %s Data for the Hecke Algebra Orbit %s" % (info['ell'], info['ell'], info['orbit_label'])
    return render_template("hecke_algebras_l_adic-single.html", info=info, credit=credit, title=t, bread=bread, properties2=info['properties'], learnmore=learnmore_list(), friends=info['friends'], KNOWL_ID='hecke_algebra_l_adic.%s'%(info['orbit_label']))
Beispiel #40
0
def by_label(label):
    clean_label = clean_input(label)
    if clean_label != label:
        return redirect(url_for('.by_label', label=clean_label), 301)
    return render_group_webpage({'label': label})
Beispiel #41
0
def render_group_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        label = label.replace('t', 'T')
        C = base.getDBConnection()
        data = C.transitivegroups.groups.find_one({'label': label})
        if data is None:
            bread = get_bread([("Search error", url_for('.search'))])
            info['err'] = "Group " + label + " was not found in the database."
            info['label'] = label
            return search_input_error(info, bread)
        title = 'Galois Group: ' + label
        wgg = WebGaloisGroup.from_data(data)
        n = data['n']
        t = data['t']
        data['yesno'] = yesno
        order = data['order']
        data['orderfac'] = latex(ZZ(order).factor())
        orderfac = latex(ZZ(order).factor())
        data['ordermsg'] = "$%s=%s$" % (order, latex(orderfac))
        if order == 1:
            data['ordermsg'] = "$1$"
        if ZZ(order).is_prime():
            data['ordermsg'] = "$%s$ (is prime)" % order
        pgroup = len(ZZ(order).prime_factors()) < 2
        if n == 1:
            G = gap.SmallGroup(n, t)
        else:
            G = gap.TransitiveGroup(n, t)
        if ZZ(order) < ZZ('10000000000'):
            ctable = chartable(n, t)
        else:
            ctable = 'Group too large'
        data['gens'] = generators(n, t)
        if n == 1 and t == 1:
            data['gens'] = 'None needed'
        data['chartable'] = ctable
        data['parity'] = "$%s$" % data['parity']
        data['cclasses'] = conjclasses(G, n)
        data['subinfo'] = subfield_display(C, n, data['subs'])
        data['resolve'] = resolve_display(C, data['resolve'])
        data['otherreps'] = wgg.otherrep_list()
        if len(data['otherreps']) == 0:
            data['otherreps']="There is no other low degree representation."
        query={'galois': bson.SON([('n', n), ('t', t)])}
        C = base.getDBConnection()
        intreps = C.transitivegroups.Gmodules.find({'n': n, 't': t}).sort('index', pymongo.ASCENDING)
        # turn cursor into a list
        intreps = [z for z in intreps]
        if len(intreps) > 0:
            data['int_rep_classes'] = [str(z[0]) for z in intreps[0]['gens']]
            for onerep in intreps:
                onerep['gens']=[list_to_latex_matrix(z[1]) for z in onerep['gens']]
            data['int_reps'] = intreps
            data['int_reps_complete'] = int_reps_are_complete(intreps)
            dcq = data['moddecompuniq']
            if dcq[0] == 0:
                data['decompunique'] = 0
            else:
                data['decompunique'] = dcq[0]
                data['isoms'] = [[mult2mult(z[0]), mult2mult(z[1])] for z in dcq[1]]
                data['isoms'] = [[modules2string(n,t,z[0]), modules2string(n,t,z[1])] for z in data['isoms']]
                print dcq[1]
                print data['isoms']

        friends = []
        one = C.numberfields.fields.find_one(query)
        if one:
            friends.append(('Number fields with this Galois group', url_for('number_fields.number_field_render_webpage')+"?galois_group=%dT%d" % (n, t) )) 
        prop2 = [
            ('Order:', '\(%s\)' % order),
            ('n:', '\(%s\)' % data['n']),
            ('Cyclic:', yesno(data['cyc'])),
            ('Abelian:', yesno(data['ab'])),
            ('Solvable:', yesno(data['solv'])),
            ('Primitive:', yesno(data['prim'])),
            ('$p$-group:', yesno(pgroup)),
        ]
        pretty = group_display_pretty(n,t,C)
        if len(pretty)>0:
            prop2.extend([('Group:', pretty)])
            info['pretty_name'] = pretty
        data['name'] = re.sub(r'_(\d+)',r'_{\1}',data['name'])
        data['name'] = re.sub(r'\^(\d+)',r'^{\1}',data['name'])
        info.update(data)

        bread = get_bread([(label, ' ')])
        return render_template("gg-show-group.html", credit=GG_credit, title=title, bread=bread, info=info, properties2=prop2, friends=friends)
Beispiel #42
0
def by_label(label):
    clean_label = clean_input(label)
    if label != clean_label:
        return redirect(url_for('.by_label',label=clean_label), 301)
    return render_field_webpage({'label': label})
Beispiel #43
0
def render_artin_representation_webpage(label):
    if re.compile(r'^\d+$').match(label):
        return artin_representation_search(**{'dimension': label})

    bread = get_bread([(label, ' ')])

    # label=dim.cond.nTt.indexcj, c is literal, j is index in conj class
    # Should we have a big try around this to catch bad labels?
    clean_label = clean_input(label)
    if clean_label != label:
        return redirect(
            url_for('.render_artin_representation_webpage', label=clean_label),
            301)
    try:
        the_rep = ArtinRepresentation(label)
    except:
        try:
            newlabel = parse_artin_label(label)
            flash_error("Artin representation %s is not in database", newlabel)
            return redirect(url_for(".index"))
        except ValueError:
            flash_error(
                "%s is not in a valid form for an Artin representation label",
                label)
            return redirect(url_for(".index"))

    extra_data = {}  # for testing?
    extra_data['galois_knowl'] = group_display_knowl(5, 3)  # for testing?
    #artin_logger.info("Found %s" % (the_rep._data))

    title = "Artin Representation %s" % label
    the_nf = the_rep.number_field_galois_group()
    if the_rep.sign() == 0:
        processed_root_number = "not computed"
    else:
        processed_root_number = str(the_rep.sign())
    properties = [
        ("Label", label),
        ("Dimension", str(the_rep.dimension())),
        ("Group", the_rep.group()),
        ("Conductor", "$" + the_rep.factored_conductor_latex() + "$"),
        #("Bad primes", str(the_rep.bad_primes())),
        ("Root number", processed_root_number),
        ("Frobenius-Schur indicator", str(the_rep.indicator()))
    ]

    friends = []
    nf_url = the_nf.url_for()
    if nf_url:
        friends.append(("Artin Field", nf_url))
    cc = the_rep.central_character()
    if cc is not None:
        if the_rep.dimension() == 1:
            if cc.order == 2:
                cc_name = cc.symbol
            else:
                cc_name = cc.texname
            friends.append(("Dirichlet character " + cc_name,
                            url_for("characters.render_Dirichletwebpage",
                                    modulus=cc.modulus,
                                    number=cc.number)))
        else:
            detrep = the_rep.central_character_as_artin_rep()
            friends.append(("Determinant representation " + detrep.label(),
                            detrep.url_for()))
    add_lfunction_friends(friends, label)

    # once the L-functions are in the database, the link can always be shown
    #if the_rep.dimension() <= 6:
    if the_rep.dimension() == 1:
        # Zeta is loaded differently
        if cc.modulus == 1 and cc.number == 1:
            friends.append(("L-function",
                            url_for("l_functions.l_function_dirichlet_page",
                                    modulus=cc.modulus,
                                    number=cc.number)))
        else:
            # looking for Lhash dirichlet_L_modulus.number
            mylhash = 'dirichlet_L_%d.%d' % (cc.modulus, cc.number)
            lres = db.lfunc_instances.lucky({'Lhash': mylhash})
            if lres is not None:
                friends.append(
                    ("L-function",
                     url_for("l_functions.l_function_dirichlet_page",
                             modulus=cc.modulus,
                             number=cc.number)))

    # Dimension > 1
    elif int(the_rep.conductor())**the_rep.dimension() <= 729000000000000:
        friends.append(("L-function",
                        url_for("l_functions.l_function_artin_page",
                                label=the_rep.label())))
    info = {}

    return render_template("artin-representation-show.html",
                           credit=tim_credit,
                           support=support_credit,
                           title=title,
                           bread=bread,
                           friends=friends,
                           object=the_rep,
                           properties2=properties,
                           extra_data=extra_data,
                           info=info,
                           learnmore=learnmore_list())
Beispiel #44
0
def render_field_webpage(args):
    data = None
    info = {}
    bread = bread_prefix()

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

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

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

    info.update(data)
    rootofunity = '%s (order $%d$)' % (nf.root_of_1_gen(),
                                       nf.root_of_1_order())

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

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

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

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

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

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

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

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

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

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

        info["mydecomp"] = [dopow(x) for x in v]
    except AttributeError:
        pass
    return render_template("nf-show-field.html",
                           properties=properties,
                           credit=NF_credit,
                           title=title,
                           bread=bread,
                           code=nf.code,
                           friends=info.pop('friends'),
                           downloads=downloads,
                           learnmore=learnmore,
                           info=info,
                           KNOWL_ID="nf.%s" % label)
Beispiel #45
0
def render_artin_representation_webpage(label):
    if re.compile(r'^\d+$').match(label):
        return artin_representation_search(**{
            'dimension': label,
            'search_array': ArtinSearchArray()
        })

    # label=dim.cond.nTt.indexcj, c is literal, j is index in conj class
    # Should we have a big try around this to catch bad labels?
    clean_label = clean_input(label)
    if clean_label != label:
        return redirect(
            url_for('.render_artin_representation_webpage', label=clean_label),
            301)
    # We could have a single representation or a Galois orbit
    case = parse_any(label)
    if case[0] == 'malformed':
        try:
            raise ValueError
        except:
            flash_error(
                "%s is not in a valid form for the label for an Artin representation or a Galois orbit of Artin representations",
                label)
            return redirect(url_for(".index"))
    # Do this twice to customize error messages
    newlabel = case[1]
    case = case[0]
    if case == 'rep':
        try:
            the_rep = ArtinRepresentation(newlabel)
        except:
            newlabel = parse_artin_label(label)
            flash_error("Artin representation %s is not in database", label)
            return redirect(url_for(".index"))
    else:  # it is an orbit
        try:
            the_rep = ArtinRepresentation(newlabel + '.a')
        except:
            newlabel = parse_artin_orbit_label(newlabel)
            flash_error(
                "Galois orbit of Artin representations %s is not in database",
                label)
            return redirect(url_for(".index"))
        # in this case we want all characters
        num_conj = the_rep.galois_conjugacy_size()
        allchars = [
            ArtinRepresentation(newlabel + '.' +
                                num2letters(j)).character_formatted()
            for j in range(1, num_conj + 1)
        ]

    label = newlabel
    bread = get_bread([(label, ' ')])

    #artin_logger.info("Found %s" % (the_rep._data))

    if case == 'rep':
        title = "Artin representation %s" % label
    else:
        title = "Galois orbit of Artin representations %s" % label
    the_nf = the_rep.number_field_galois_group()
    if the_rep.sign() == 0:
        processed_root_number = "not computed"
    else:
        processed_root_number = str(the_rep.sign())
    properties = [("Label", label), ("Dimension", str(the_rep.dimension())),
                  ("Group", the_rep.group()),
                  ("Conductor", "$" + the_rep.factored_conductor_latex() + "$")
                  ]
    if case == 'rep':
        properties.append(("Root number", processed_root_number))
    properties.append(("Frobenius-Schur indicator", str(the_rep.indicator())))

    friends = []
    wnf = None
    nf_url = the_nf.url_for()
    if nf_url:
        friends.append(("Artin field", nf_url))
        wnf = the_nf.wnf()
    proj_nf = WebNumberField.from_coeffs(the_rep._data['Proj_Polynomial'])
    if proj_nf:
        friends.append(
            ("Projective Artin field",
             str(url_for("number_fields.by_label",
                         label=proj_nf.get_label()))))
    if case == 'rep':
        cc = the_rep.central_character()
        if cc is not None:
            if the_rep.dimension() == 1:
                if cc.order == 2:
                    cc_name = cc.symbol
                else:
                    cc_name = cc.texname
                friends.append(("Dirichlet character " + cc_name,
                                url_for("characters.render_Dirichletwebpage",
                                        modulus=cc.modulus,
                                        number=cc.number)))
            else:
                detrep = the_rep.central_character_as_artin_rep()
                friends.append(("Determinant representation " + detrep.label(),
                                detrep.url_for()))
        add_lfunction_friends(friends, label)

        # once the L-functions are in the database, the link can always be shown
        #if the_rep.dimension() <= 6:
        if the_rep.dimension() == 1:
            # Zeta is loaded differently
            if cc.modulus == 1 and cc.number == 1:
                friends.append(
                    ("L-function",
                     url_for("l_functions.l_function_dirichlet_page",
                             modulus=cc.modulus,
                             number=cc.number)))
            else:
                # looking for Lhash dirichlet_L_modulus.number
                mylhash = 'dirichlet_L_%d.%d' % (cc.modulus, cc.number)
                lres = db.lfunc_instances.lucky({'Lhash': mylhash})
                if lres is not None:
                    friends.append(
                        ("L-function",
                         url_for("l_functions.l_function_dirichlet_page",
                                 modulus=cc.modulus,
                                 number=cc.number)))

        # Dimension > 1
        elif int(the_rep.conductor())**the_rep.dimension() <= 729000000000000:
            friends.append(("L-function",
                            url_for("l_functions.l_function_artin_page",
                                    label=the_rep.label())))
        orblabel = re.sub(r'\.[a-z]+$', '', label)
        friends.append(("Galois orbit " + orblabel,
                        url_for(".render_artin_representation_webpage",
                                label=orblabel)))
    else:
        add_lfunction_friends(friends, label)
        friends.append(("L-function",
                        url_for("l_functions.l_function_artin_page",
                                label=the_rep.label())))
        for j in range(1, 1 + the_rep.galois_conjugacy_size()):
            newlabel = label + '.' + num2letters(j)
            friends.append(("Artin representation " + newlabel,
                            url_for(".render_artin_representation_webpage",
                                    label=newlabel)))

    info = {}  # for testing

    if case == 'rep':
        return render_template("artin-representation-show.html",
                               credit=tim_credit,
                               support=support_credit,
                               title=title,
                               bread=bread,
                               friends=friends,
                               object=the_rep,
                               cycle_string=cycle_string,
                               wnf=wnf,
                               properties=properties,
                               info=info,
                               learnmore=learnmore_list())
    # else we have an orbit
    return render_template("artin-representation-galois-orbit.html",
                           credit=tim_credit,
                           support=support_credit,
                           title=title,
                           bread=bread,
                           allchars=allchars,
                           friends=friends,
                           object=the_rep,
                           cycle_string=cycle_string,
                           wnf=wnf,
                           properties=properties,
                           info=info,
                           learnmore=learnmore_list())
Beispiel #46
0
def hgm_search(**args):
    info = to_dict(args)
    bread = get_bread([("Search results", url_for('.search'))])
    C = base.getDBConnection()
    query = {}
    if 'jump_to' in info:
        return render_hgm_webpage({'label': info['jump_to']})

    family_search = False
    if info.get('Submit Family') or info.get('family'):
        family_search = True

    # generic, irreducible not in DB yet
    for param in [
            'A', 'B', 'hodge', 'a2', 'b2', 'a3', 'b3', 'a5', 'b5', 'a7', 'b7'
    ]:
        if info.get(param):
            info[param] = clean_input(info[param])
            if IF_RE.match(info[param]):
                query[param] = parse_list(info[param])
                query[param].sort()
            else:
                name = param
                if field == 'hodge':
                    name = 'Hodge vector'
                info[
                    'err'] = 'Error parsing input for %s.  It needs to be a list of integers in square brackets, such as [2,3] or [1,1,1]' % name
                return search_input_error(info, bread)

    if info.get('t') and not family_search:
        info['t'] = clean_input(info['t'])
        try:
            tsage = QQ(str(info['t']))
            tlist = [int(tsage.numerator()), int(tsage.denominator())]
            query['t'] = tlist
        except:
            info[
                'err'] = 'Error parsing input for t.  It needs to be a rational number, such as 2/3 or -3'

    # sign can only be 1, -1, +1
    if info.get('sign') and not family_search:
        sign = info['sign']
        sign = re.sub(r'\s', '', sign)
        sign = clean_input(sign)
        if sign == '+1':
            sign = '1'
        if not (sign == '1' or sign == '-1'):
            info[
                'err'] = 'Error parsing input %s for sign.  It needs to be 1 or -1' % sign
            return search_input_error(info, bread)
        query['sign'] = int(sign)

    for param in ['degree', 'weight', 'conductor']:
        # We don't look at conductor in family searches
        if info.get(param) and not (param == 'conductor' and family_search):
            if param == 'conductor':
                cond = info['conductor']
                try:
                    cond = re.sub(r'(\d)\s+(\d)', r'\1 * \2',
                                  cond)  # implicit multiplication of numbers
                    cond = cond.replace(r'..', r'-')  # all ranges use -
                    cond = re.sub(r'[a..zA..Z]', '', cond)
                    cond = clean_input(cond)
                    tmp = parse_range2(cond, 'cond', myZZ)
                except:
                    info[
                        'err'] = 'Error parsing input for conductor.  It needs to be an integer (e.g., 8), a range of integers (e.g. 10-100), or a list of such (e.g., 5,7,8,10-100).  Integers may be given in factored form (e.g. 2^5 3^2) %s' % cond
                    return search_input_error(info, bread)
            else:  # not conductor
                info[param] = clean_input(info[param])
                ran = info[param]
                ran = ran.replace(r'..', r'-')
                if LIST_RE.match(ran):
                    tmp = parse_range2(ran, param)
                else:
                    names = {'weight': 'weight', 'degree': 'degree'}
                    info[
                        'err'] = 'Error parsing input for the %s.  It needs to be an integer (such as 5), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 2,3,8 or 3-5, 7, 8-11).' % names[
                            param]
                    return search_input_error(info, bread)
            # work around syntax for $or
            # we have to foil out multiple or conditions
            if tmp[0] == '$or' and '$or' in query:
                newors = []
                for y in tmp[1]:
                    oldors = [dict.copy(x) for x in query['$or']]
                    for x in oldors:
                        x.update(y)
                    newors.extend(oldors)
                tmp[1] = newors
            query[tmp[0]] = tmp[1]

    #print query
    count_default = 20
    if info.get('count'):
        try:
            count = int(info['count'])
        except:
            count = count_default
    else:
        count = count_default
    info['count'] = count

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

    # logger.debug(query)
    if family_search:
        res = C.hgm.families.find(query).sort([('label', pymongo.ASCENDING)])
    else:
        res = C.hgm.motives.find(query).sort([('cond', pymongo.ASCENDING),
                                              ('label', pymongo.ASCENDING)])
    nres = res.count()
    res = res.skip(start).limit(count)

    if (start >= nres):
        start -= (1 + (start - nres) / count) * count
    if (start < 0):
        start = 0

    info['motives'] = res
    info['number'] = nres
    info['start'] = start
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (
                start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres
    info['make_label'] = make_abt_label
    info['make_t_label'] = make_t_label
    info['ab_label'] = ab_label
    info['display_t'] = display_t
    info['family'] = family_search
    info['factorint'] = factorint

    if family_search:
        return render_template(
            "hgm-search.html",
            info=info,
            title="Hypergeometric Family over $\Q$ Search Result",
            bread=bread,
            credit=HGM_credit)
    else:
        return render_template(
            "hgm-search.html",
            info=info,
            title="Hypergeometric Motive over $\Q$ Search Result",
            bread=bread,
            credit=HGM_credit)
Beispiel #47
0
def render_field_webpage(args):
    data = None
    C = base.getDBConnection()
    info = {}
    bread = [('Global Number Fields', url_for(".number_field_render_webpage"))]

    if 'label' in args:
        label = clean_input(args['label'])
        nf = WebNumberField(label)
        data = {}
    if nf.is_null():
        bread.append(('Search results', ' '))
        label2 = re.sub(r'[<>]', '', args['label'])
        if 'You need to enter a field' in label2:
            info['err'] = label2
        else:
            info['err'] = 'No such field: %s in the database' % label2
        info['label'] = args['label_orig'] if 'label_orig' in args else args['label']
        return search_input_error(info, bread)

    info['wnf'] = nf
    data['degree'] = nf.degree()
    data['class_number'] = nf.class_number()
    t = nf.galois_t()
    n = nf.degree()
    data['is_galois'] = nf.is_galois()
    data['is_abelian'] = nf.is_abelian()
    if nf.is_abelian():
        conductor = nf.conductor()
        data['conductor'] = conductor
        dirichlet_chars = nf.dirichlet_group()
        data['dirichlet_group'] = ['<a href = "%s">$\chi_{%s}(%s,&middot;)$</a>' % (url_for("render_Character", arg1=data['conductor'], arg2=j), data['conductor'], j) for j in dirichlet_chars]
        data['dirichlet_group'] = r'$\lbrace$' + ', '.join(data['dirichlet_group']) + r'$\rbrace$'
        if data['conductor'].is_prime() or data['conductor'] == 1:
            data['conductor'] = "\(%s\)" % str(data['conductor'])
        else:
            data['conductor'] = "\(%s=%s\)" % (str(data['conductor']), latex(data['conductor'].factor()))
    data['galois_group'] = group_display_knowl(n, t, C)
    data['cclasses'] = cclasses_display_knowl(n, t, C)
    data['character_table'] = character_table_display_knowl(n, t, C)
    data['class_group'] = nf.class_group()
    data['class_group_invs'] = nf.class_group_invariants()
    data['signature'] = nf.signature()
    D = nf.disc()
    ram_primes = D.prime_factors()
    data['disc_factor'] = nf.disc_factored_latex()
    if D.abs().is_prime() or D == 1:
        data['discriminant'] = "\(%s\)" % str(D)
    else:
        data['discriminant'] = "\(%s=%s\)" % (str(D), data['disc_factor'])
    npr = len(ram_primes)
    ram_primes = str(ram_primes)[1:-1]
    if ram_primes == '':
        ram_primes = r'\textrm{None}'
    data['frob_data'], data['seeram'] = frobs(nf.K())
    data['phrase'] = group_phrase(n, t, C)
    zk = pari(nf.K()).nf_subst('a')
    zk = list(zk.nf_get_zk())
    Ra = PolynomialRing(QQ, 'a')
    zk = [latex(Ra(x)) for x in zk]
    zk = ['$%s$' % x for x in zk]
    zk = ', '.join(zk)
    grh_label = '<small>(<a title="assuming GRH" knowl="nf.assuming_grh">assuming GRH</a>)</small>' if nf.used_grh() else ''
    # Short version for properties
    grh_lab = nf.short_grh_string()
    pretty_label = field_pretty(label)
    if label != pretty_label:
        pretty_label = "%s: %s" % (label, pretty_label)

    info.update(data)
    info.update({
        'label': pretty_label,
        'label_raw': label,
        'polynomial': web_latex_split_on_pm(nf.K().defining_polynomial()),
        'ram_primes': ram_primes,
        'integral_basis': zk,
        'regulator': web_latex(nf.regulator()),
        'unit_rank': nf.unit_rank(),
        'root_of_unity': web_latex(nf.K().primitive_root_of_unity()),
        'fund_units': nf.units(),
        'grh_label': grh_label
    })

    bread.append(('%s' % info['label_raw'], ' '))
    info['downloads_visible'] = True
    info['downloads'] = [('worksheet', '/')]
    info['friends'] = []
    if nf.can_class_number():
        info['friends'].append(('L-function', "/L/NumberField/%s" % label))
    info['friends'].append(('Galois group', "/GaloisGroup/%dT%d" % (n, t)))
    if 'dirichlet_group' in info:
        info['friends'].append(('Dirichlet group', url_for("dirichlet_group_table",
                                                           modulus=int(conductor),
                                                           char_number_list=','.join(
                                                               [str(a) for a in dirichlet_chars]),
                                                           poly=info['polynomial'])))
    info['learnmore'] = [('Global number field labels', url_for(
        ".render_labels_page")), (Completename, url_for(".render_discriminants_page"))]
    # With Galois group labels, probably not needed here
    # info['learnmore'] = [('Global number field labels',
    # url_for(".render_labels_page")), ('Galois group
    # labels',url_for(".render_groups_page")),
    # (Completename,url_for(".render_discriminants_page"))]
    title = "Global Number Field %s" % info['label']

    if npr == 1:
        primes = 'prime'
    else:
        primes = 'primes'

    properties2 = [('Degree:', '%s' % data['degree']),
                   ('Signature:', '$%s$' % data['signature']),
                   ('Discriminant:', '$%s$' % data['disc_factor']),
                   ('Ramified ' + primes + ':', '$%s$' % ram_primes),
                   ('Class number:', '%s %s' % (data['class_number'], grh_lab)),
                   ('Class group:', '%s %s' % (data['class_group_invs'], grh_lab)),
                   ('Galois Group:', group_display_short(data['degree'], t, C))
                   ]
    from lmfdb.math_classes import NumberFieldGaloisGroup
    try:
        info["tim_number_field"] = NumberFieldGaloisGroup.find_one({"label": label})
        v = nf.factor_perm_repn(info["tim_number_field"])
        info["mydecomp"] = ['*' if x>0 else '' for x in v]
    except AttributeError:
        pass
#    del info['_id']
    return render_template("number_field.html", properties2=properties2, credit=NF_credit, title=title, bread=bread, friends=info.pop('friends'), learnmore=info.pop('learnmore'), info=info)
Beispiel #48
0
def render_hgm_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        C = base.getDBConnection()
        data = C.hgm.motives.find_one({'label': label})
        if data is None:
            bread = get_bread([("Search error", url_for('.search'))])
            info['err'] = "Motive " + label + " was not found in the database."
            info['label'] = label
            return search_input_error(info, bread)
        title = 'Hypergeometric Motive:' + label
        A = data['A']
        B = data['B']
        tn, td = data['t']
        t = latex(QQ(str(tn) + '/' + str(td)))
        primes = [
            2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61,
            67, 71
        ]
        locinfo = data['locinfo']
        for j in range(len(locinfo)):
            locinfo[j] = [primes[j]] + locinfo[j]
            locinfo[j][2] = poly_with_factored_coeffs(locinfo[j][2], primes[j])
        hodge = data['hodge']
        prop2 = [
            ('Degree', '\(%s\)' % data['degree']),
            ('Weight', '\(%s\)' % data['weight']),
            ('Conductor', '\(%s\)' % data['cond']),
        ]
        # Now add factorization of conductor
        Cond = ZZ(data['cond'])
        if not (Cond.abs().is_prime() or Cond == 1):
            data['cond'] = "%s=%s" % (str(Cond), factorint(data['cond']))

        info.update({
            'A': A,
            'B': B,
            't': t,
            'degree': data['degree'],
            'weight': data['weight'],
            'sign': data['sign'],
            'sig': data['sig'],
            'hodge': hodge,
            'cond': data['cond'],
            'req': data['req'],
            'locinfo': locinfo
        })
        AB_data, t_data = data["label"].split("_t")
        #AB_data = data["label"].split("_t")[0]
        friends = [("Motive family " + AB_data.replace("_", " "),
                    url_for(".by_family_label", label=AB_data))]
        friends.append(('L-function',
                        url_for("l_functions.l_function_hgm_page",
                                label=AB_data,
                                t='t' + t_data)))
        #        if rffriend != '':
        #            friends.append(('Discriminant root field', rffriend))

        bread = get_bread([(label, ' ')])
        return render_template("hgm-show-motive.html",
                               credit=HGM_credit,
                               title=title,
                               bread=bread,
                               info=info,
                               properties2=prop2,
                               friends=friends)
Beispiel #49
0
def galois_group_search(**args):
    info = to_dict(args)
    bread = get_bread([("Search results", url_for('.search'))])
    C = base.getDBConnection()
    query = {}
    if 'jump_to' in info:
        return render_group_webpage({'label': info['jump_to']})

    for param in ['n', 't']:
        if info.get(param):
            info[param] = clean_input(info[param])
            ran = info[param]
            ran = ran.replace('..', '-')
            if LIST_RE.match(ran):
                tmp = parse_range2(ran, param)
            else:
                names = {'n': 'degree', 't': 't'}
                info['err'] = 'Error parsing input for the %s.  It needs to be an integer (such as 5), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 2,3,8 or 3-5, 7, 8-11).' % names[param]
                return search_input_error(info, bread)
            # work around syntax for $or
            # we have to foil out multiple or conditions
            if tmp[0] == '$or' and '$or' in query:
                newors = []
                for y in tmp[1]:
                    oldors = [dict.copy(x) for x in query['$or']]
                    for x in oldors:
                        x.update(y)
                    newors.extend(oldors)
                tmp[1] = newors
            query[tmp[0]] = tmp[1]
    for param in ['cyc', 'solv', 'prim', 'parity']:
        if info.get(param):
            info[param] = str(info[param])
            if info[param] == str(1):
                query[param] = 1
            elif info[param] == str(-1):
                query[param] = -1 if param == 'parity' else 0

    # Determine if we have any composite degrees
    info['show_subs'] = True
    if info.get('n'):
        info['show_subs'] = False  # now only show subs if a composite n is allowed
        nparam = info.get('n')
        nparam.replace('..', '-')
        nlist = nparam.split(',')
        found = False
        for nl in nlist:
            if '-' in nl:
                inx = nl.index('-')
                ll, hh = nl[:inx], nl[inx + 1:]
                hh = int(hh)
                jj = int(ll)
                while jj <= hh and not found:
                    if not(ZZ(jj).is_prime() or ZZ(jj) == 1):
                        found = True
                    jj += 1
                if found:
                    break
            else:
                jj = ZZ(nl)
                if not (ZZ(jj).is_prime() or ZZ(jj) == 1):
                    found = True
                    break
        if found:
            info['show_subs'] = True

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

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

    res = C.transitivegroups.groups.find(query).sort([('n', pymongo.ASCENDING), ('t', pymongo.ASCENDING)])
    nres = res.count()
    res = res.skip(start).limit(count)

    if(start >= nres):
        start -= (1 + (start - nres) / count) * count
    if(start < 0):
        start = 0

    info['groups'] = res
    info['group_display'] = group_display_prettyC(C)
    info['report'] = "found %s groups" % nres
    info['yesno'] = yesno
    info['wgg'] = WebGaloisGroup.from_data
    info['start'] = start
    info['number'] = nres
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres

    return render_template("gg-search.html", info=info, title="Galois Group Search Result", bread=bread, credit=GG_credit)
Beispiel #50
0
def render_hgm_family_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        C = base.getDBConnection()
        data = C.hgm.families.find_one({'label': label})
        if data is None:
            bread = get_bread([("Search error", url_for('.search'))])
            info[
                'err'] = "Family of hypergeometric motives " + label + " was not found in the database."
            info['label'] = label
            return search_input_error(info, bread)
        title = 'Hypergeometric Motive Family:' + label
        A = data['A']
        B = data['B']
        hodge = data['hodge']
        prop2 = [('Degree', '\(%s\)' % data['degree']),
                 ('Weight', '\(%s\)' % data['weight'])]
        info.update({
            'A': A,
            'B': B,
            'degree': data['degree'],
            'weight': data['weight'],
            'hodge': hodge,
            'gal2': data['gal2'],
            'gal3': data['gal3'],
            'gal5': data['gal5'],
            'gal7': data['gal7'],
        })
        friends = [('Motives in the family',
                    url_for('hypergm.index') + "?A=%s&B=%s" % (str(A), str(B)))
                   ]
        #        if unramfriend != '':
        #            friends.append(('Unramified subfield', unramfriend))
        #        if rffriend != '':
        #            friends.append(('Discriminant root field', rffriend))

        info.update({
            "plotcircle":
            url_for(".hgm_family_circle_image",
                    AB="A" + ".".join(map(str, A)) + "_B" +
                    ".".join(map(str, B)))
        })
        info.update({
            "plotlinear":
            url_for(".hgm_family_linear_image",
                    AB="A" + ".".join(map(str, A)) + "_B" +
                    ".".join(map(str, B)))
        })
        info.update({
            "plotconstant":
            url_for(".hgm_family_constant_image",
                    AB="A" + ".".join(map(str, A)) + "_B" +
                    ".".join(map(str, B)))
        })
        bread = get_bread([(label, ' ')])
        return render_template("hgm-show-family.html",
                               credit=HGM_credit,
                               title=title,
                               bread=bread,
                               info=info,
                               properties2=prop2,
                               friends=friends)
Beispiel #51
0
def render_lattice_webpage(**args):
    f = None
    if 'label' in args:
        lab = clean_input(args.get('label'))
        if lab != args.get('label'):
            return redirect(url_for('.render_lattice_webpage', label=lab), 301)
        f = db.lat_lattices.lucky({'$or':[{'label': lab }, {'name': {'$contains': [lab]}}]})
    if f is None:
        t = "Integral Lattices Search Error"
        bread = [('Lattices', url_for(".lattice_render_webpage"))]
        flash_error("%s is not a valid label or name for an integral lattice in the database.", lab)
        return render_template("lattice-error.html", title=t, properties=[], bread=bread, learnmore=learnmore_list())
    info = {}
    info.update(f)

    info['friends'] = []

    bread = [('Lattice', url_for(".lattice_render_webpage")), ('%s' % f['label'], ' ')]
    credit = lattice_credit
    info['dim']= int(f['dim'])
    info['det']= int(f['det'])
    info['level']=int(f['level'])
    info['gram']=vect_to_matrix(f['gram'])
    info['density']=str(f['density'])
    info['hermite']=str(f['hermite'])
    info['minimum']=int(f['minimum'])
    info['kissing']=int(f['kissing'])
    info['aut']=int(f['aut'])

    if f['shortest']=="":
        info['shortest']==f['shortest']
    else:
        if f['dim']==1:
            info['shortest']=str(f['shortest']).strip('[').strip(']')
        else:
            if info['dim']*info['kissing']<100:
                info['shortest']=[str([tuple(v)]).strip('[').strip(']').replace('),', '), ') for v in f['shortest']]
            else:
                max_vect_num=min(int(round(100/(info['dim']))), int(round(info['kissing']/2))-1);
                info['shortest']=[str([tuple(f['shortest'][i])]).strip('[').strip(']').replace('),', '), ') for i in range(max_vect_num+1)]
                info['all_shortest']="no"
        info['download_shortest'] = [
            (i, url_for(".render_lattice_webpage_download", label=info['label'], lang=i, obj='shortest_vectors')) for i in ['gp', 'magma','sage']]

    if f['name']==['Leech']:
        info['shortest']=[str([1,-2,-2,-2,2,-1,-1,3,3,0,0,2,2,-1,-1,-2,2,-2,-1,-1,0,0,-1,2]), 
str([1,-2,-2,-2,2,-1,0,2,3,0,0,2,2,-1,-1,-2,2,-1,-1,-2,1,-1,-1,3]), str([1,-2,-2,-1,1,-1,-1,2,2,0,0,2,2,0,0,-2,2,-1,-1,-1,0,-1,-1,2])]
        info['all_shortest']="no"
        info['download_shortest'] = [
            (i, url_for(".render_lattice_webpage_download", label=info['label'], lang=i, obj='shortest_vectors')) for i in ['gp', 'magma','sage']]

    ncoeff=20
    if f['theta_series'] != "":
        coeff=[f['theta_series'][i] for i in range(ncoeff+1)]
        info['theta_series']=my_latex(print_q_expansion(coeff))
        info['theta_display'] = url_for(".theta_display", label=f['label'], number="")

    info['class_number']=int(f['class_number'])

    if f['dim']==1:
        info['genus_reps']=str(f['genus_reps']).strip('[').strip(']')
    else:
        if info['dim']*info['class_number']<50:
            info['genus_reps']=[vect_to_matrix(n) for n in f['genus_reps']]
        else:
            max_matrix_num=min(int(round(25/(info['dim']))), info['class_number']);
            info['all_genus_rep']="no"
            info['genus_reps']=[vect_to_matrix(f['genus_reps'][i]) for i in range(max_matrix_num+1)]
    info['download_genus_reps'] = [
        (i, url_for(".render_lattice_webpage_download", label=info['label'], lang=i, obj='genus_reps')) for i in ['gp', 'magma','sage']]

    if f['name'] != "":
        if f['name']==str(f['name']):
            info['name']= str(f['name'])
        else:
            info['name']=str(", ".join(str(i) for i in f['name']))
    else:
        info['name'] == ""
    info['comments']=str(f['comments'])
    if 'Leech' in info['comments']: # no need to duplicate as it is in the name
        info['comments'] = ''
    if info['name'] == "":
        t = "Integral Lattice %s" % info['label']
    else:
        t = "Integral Lattice "+info['label']+" ("+info['name']+")"
#This part code was for the dinamic knowl with comments, since the test is displayed this is redundant
#    if info['name'] != "" or info['comments'] !="":
#        info['knowl_args']= "name=%s&report=%s" %(info['name'], info['comments'].replace(' ', '-space-'))
    info['properties'] = [
        ('Dimension', '%s' %info['dim']),
        ('Determinant', '%s' %info['det']),
        ('Level', '%s' %info['level'])]
    if info['class_number'] == 0:
        info['properties']=[('Class number', 'not available')]+info['properties']
    else:
        info['properties']=[('Class number', '%s' %info['class_number'])]+info['properties']
    info['properties']=[('Label', '%s' % info['label'])]+info['properties']

    if info['name'] != "" :
        info['properties']=[('Name','%s' % info['name'] )]+info['properties']
#    friends = [('L-series (not available)', ' ' ),('Half integral weight modular forms (not available)', ' ')]
    return render_template("lattice-single.html", info=info, credit=credit, title=t, bread=bread, properties=info['properties'], learnmore=learnmore_list(), KNOWL_ID="lattice.%s"%info['label'])
Beispiel #52
0
def render_family(args):
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        dataz = list(db.hgcwa_passports.search({'label': label}))
        if not dataz:
            flash_error("No family with label %s was found in the database.",
                        label)
            return redirect(url_for(".index"))
        data = dataz[0]
        g = data['genus']
        g0 = data['g0']
        GG = ast.literal_eval(data['group'])
        gn = GG[0]
        gt = GG[1]

        gp_string = str(gn) + '.' + str(gt)
        pretty_group = sg_pretty(gp_string)

        if gp_string == pretty_group:
            spname = False
        else:
            spname = True
        title = 'Family of Genus ' + str(
            g) + ' Curves with Automorphism Group $' + pretty_group + '$'
        smallgroup = "[" + str(gn) + "," + str(gt) + "]"

        prop2 = [
            ('Genus', r'\(%d\)' % g), ('Quotient Genus', r'\(%d\)' % g0),
            ('Group', r'\(%s\)' % pretty_group),
            ('Signature',
             r'\(%s\)' % sign_display(ast.literal_eval(data['signature'])))
        ]
        info.update({
            'genus': data['genus'],
            'sign': sign_display(ast.literal_eval(data['signature'])),
            'group': pretty_group,
            'g0': data['g0'],
            'dim': data['dim'],
            'r': data['r'],
            'gpid': smallgroup
        })

        if spname:
            info.update({'specialname': True})

        Lcc = []
        Lall = []
        i = 1
        for dat in dataz:
            if ast.literal_eval(dat['con']) not in Lcc:
                urlstrng = dat['passport_label']
                Lcc.append(ast.literal_eval(dat['con']))
                Lall.append([
                    cc_display(ast.literal_eval(dat['con'])),
                    dat['passport_label'], urlstrng
                ])
                i = i + 1

        info.update({'passport': Lall})

        g2List = [
            '[2,1]', '[4,2]', '[8,3]', '[10,2]', '[12,4]', '[24,8]', '[48,29]'
        ]
        if g == 2 and data['group'] in g2List:
            g2url = "/Genus2Curve/Q/?geom_aut_grp_id=" + data['group']
            friends = [(r"Genus 2 curves over $\Q$", g2url)]
        else:
            friends = []

        br_g, br_gp, br_sign = split_family_label(label)

        bread_sign = label_to_breadcrumbs(br_sign)
        bread_gp = label_to_breadcrumbs(br_gp)

        bread = get_bread([(br_g, './?genus=' + br_g),
                           ('$' + pretty_group + '$',
                            './?genus=' + br_g + '&group=' + bread_gp),
                           (bread_sign, ' ')])
        learnmore = [('Completeness of the data',
                      url_for(".completeness_page")),
                     ('Source of the data', url_for(".how_computed_page")),
                     ('Reliability of the data', url_for(".reliability_page")),
                     ('Labeling convention', url_for(".labels_page"))]

        downloads = [('Code to Magma',
                      url_for(".hgcwa_code_download",
                              label=label,
                              download_type='magma')),
                     ('Code to Gap',
                      url_for(".hgcwa_code_download",
                              label=label,
                              download_type='gap'))]

        return render_template("hgcwa-show-family.html",
                               title=title,
                               bread=bread,
                               info=info,
                               properties=prop2,
                               friends=friends,
                               learnmore=learnmore,
                               downloads=downloads,
                               credit=credit)
Beispiel #53
0
def render_group_webpage(args):
    data = {}
    if 'label' in args:
        label = clean_input(args['label'])
        label = label.replace('t', 'T')
        data = db.gps_transitive.lookup(label)
        if data is None:
            if re.match(r'^\d+T\d+$', label):
                flash_error("Group %s was not found in the database.", label)
            else:
                flash_error("%s is not a valid label for a Galois group.",
                            label)
            return redirect(url_for(".index"))
        title = 'Galois group: ' + label
        wgg = WebGaloisGroup.from_nt(data['n'], data['t'])
        data['wgg'] = wgg
        n = data['n']
        t = data['t']
        data['yesno'] = yesno
        order = data['order']
        data['orderfac'] = latex(ZZ(order).factor())
        orderfac = latex(ZZ(order).factor())
        data['ordermsg'] = "$%s=%s$" % (order, latex(orderfac))
        if order == 1:
            data['ordermsg'] = "$1$"
        if ZZ(order).is_prime():
            data['ordermsg'] = "$%s$ (is prime)" % order
        pgroup = len(ZZ(order).prime_factors()) < 2
        if wgg.num_conjclasses() < 50:
            data['cclasses'] = wgg.conjclasses()
        if ZZ(order) < ZZ(10000000) and wgg.num_conjclasses() < 21:
            data['chartable'] = chartable(n, t)
        data['gens'] = wgg.generator_string()
        if n == 1 and t == 1:
            data['gens'] = 'None needed'
        data['num_cc'] = comma(wgg.num_conjclasses())
        data['parity'] = "$%s$" % data['parity']
        data['subinfo'] = subfield_display(n, data['subfields'])
        data['resolve'] = resolve_display(data['quotients'])
        if data['gapid'] == 0:
            data['gapid'] = "not available"
        else:
            data['gapid'] = small_group_display_knowl(
                int(data['order']), int(data['gapid']),
                str([int(data['order']),
                     int(data['gapid'])]))
        data['otherreps'] = wgg.otherrep_list()
        ae = data['arith_equiv']
        if ae > 0:
            if ae > 1:
                data[
                    'arith_equiv'] = r'A number field with this Galois group has %d <a knowl="nf.arithmetically_equivalent", title="arithmetically equivalent">arithmetically equivalent</a> fields.' % ae
            else:
                data[
                    'arith_equiv'] = r'A number field with this Galois group has exactly one <a knowl="nf.arithmetically_equivalent", title="arithmetically equivalent">arithmetically equivalent</a> field.'
        elif ae > -1:
            data[
                'arith_equiv'] = r'A number field with this Galois group has no <a knowl="nf.arithmetically_equivalent", title="arithmetically equivalent">arithmetically equivalent</a> fields.'
        else:
            data[
                'arith_equiv'] = r'Data on whether or not a number field with this Galois group has <a knowl="nf.arithmetically_equivalent", title="arithmetically equivalent">arithmetically equivalent</a> fields has not been computed.'
        intreps = list(db.gps_gmodules.search({'n': n, 't': t}))
        if len(intreps) > 0:
            data['int_rep_classes'] = [str(z[0]) for z in intreps[0]['gens']]
            for onerep in intreps:
                onerep['gens'] = [
                    list_to_latex_matrix(z[1]) for z in onerep['gens']
                ]
            data['int_reps'] = intreps
            data['int_reps_complete'] = int_reps_are_complete(intreps)
            dcq = data['moddecompuniq']
            if dcq[0] == 0:
                data['decompunique'] = 0
            else:
                data['decompunique'] = dcq[0]
                data['isoms'] = [[mult2mult(z[0]),
                                  mult2mult(z[1])] for z in dcq[1]]
                data['isoms'] = [[
                    modules2string(n, t, z[0]),
                    modules2string(n, t, z[1])
                ] for z in data['isoms']]
                #print dcq[1]
                #print data['isoms']

        friends = []
        if db.nf_fields.exists({'galois_label': "%dT%d" % (n, t)}):
            friends.append(
                ('Number fields with this Galois group',
                 url_for('number_fields.number_field_render_webpage') +
                 "?galois_group=%dT%d" % (n, t)))
        prop2 = [
            ('Label', label),
            ('Degree', prop_int_pretty(data['n'])),
            ('Order', prop_int_pretty(order)),
            ('Cyclic', yesno(data['cyc'])),
            ('Abelian', yesno(data['ab'])),
            ('Solvable', yesno(data['solv'])),
            ('Primitive', yesno(data['prim'])),
            ('$p$-group', yesno(pgroup)),
        ]
        pretty = group_display_short(n, t, emptyifnotpretty=True)
        if len(pretty) > 0:
            prop2.extend([('Group:', pretty)])
            data['pretty_name'] = pretty
        data['name'] = re.sub(r'_(\d+)', r'_{\1}', data['name'])
        data['name'] = re.sub(r'\^(\d+)', r'^{\1}', data['name'])
        data['nilpotency'] = '$%s$' % data['nilpotency']
        if data['nilpotency'] == '$-1$':
            data['nilpotency'] += ' (not nilpotent)'

        bread = get_bread([(label, ' ')])
        return render_template("gg-show-group.html",
                               credit=GG_credit,
                               title=title,
                               bread=bread,
                               info=data,
                               properties=prop2,
                               friends=friends,
                               KNOWL_ID="gg.%s" % label,
                               learnmore=learnmore_list())
Beispiel #54
0
def render_passport(args):
    info = {}
    if 'passport_label' in args:
        label = clean_input(args['passport_label'])
        dataz = list(db.hgcwa_passports.search({'passport_label': label}))
        if not dataz:
            bread = get_bread([("Search Error", url_for('.index'))])
            flash_error(
                "No refined passport with label %s was found in the database.",
                label)
            return redirect(url_for(".index"))
        data = dataz[0]
        g = data['genus']
        g0 = data['g0']
        GG = ast.literal_eval(data['group'])
        gn = GG[0]
        gt = GG[1]

        gp_string = str(gn) + '.' + str(gt)
        pretty_group = sg_pretty(gp_string)

        if gp_string == pretty_group:
            spname = False
        else:
            spname = True

        numb = len(dataz)

        try:
            numgenvecs = request.args['numgenvecs']
            numgenvecs = int(numgenvecs)
        except:
            numgenvecs = 20
        info['numgenvecs'] = numgenvecs

        title = 'One Refined Passport of Genus ' + str(
            g) + ' with Automorphism Group $' + pretty_group + '$'
        smallgroup = "[" + str(gn) + "," + str(gt) + "]"

        prop2 = [
            ('Genus', r'\(%d\)' % g), ('Quotient Genus', r'\(%d\)' % g0),
            ('Group', r'\(%s\)' % pretty_group),
            ('Signature',
             r'\(%s\)' % sign_display(ast.literal_eval(data['signature']))),
            ('Generating Vectors', r'\(%d\)' % numb)
        ]
        info.update({
            'genus': data['genus'],
            'cc': cc_display(data['con']),
            'sign': sign_display(ast.literal_eval(data['signature'])),
            'group': pretty_group,
            'gpid': smallgroup,
            'numb': numb,
            'disp_numb': min(numb, numgenvecs),
            'g0': data['g0']
        })

        if spname:
            info.update({'specialname': True})

        Ldata = []
        HypColumn = False
        Lfriends = []
        for i in range(0, min(numgenvecs, numb)):
            dat = dataz[i]
            x1 = dat['total_label']
            if 'full_auto' in dat:
                x2 = 'No'
                if dat['full_label'] not in Lfriends:
                    Lfriends.append(dat['full_label'])
            else:
                x2 = 'Yes'

            if 'hyperelliptic' in dat:
                x3 = tfTOyn(dat['hyperelliptic'])
                HypColumn = True
            else:
                x3 = ' '

            x4 = []
            if dat['g0'] == 0:
                for perm in dat['gen_vectors']:
                    cycperm = Permutation(perm).cycle_string()
                    x4.append(sep.join(split_perm(cycperm)))

            elif dat['g0'] > 0:
                for perm in dat['gen_vectors']:
                    cycperm = Permutation(perm).cycle_string()
                    #if display_perm == '()':
                    if cycperm == '()':
                        x4.append('Id(G)')
                    else:
                        x4.append(sep.join(split_perm(cycperm)))
            Ldata.append([x1, x2, x3, x4])

        info.update({'genvects': Ldata, 'HypColumn': HypColumn})
        info.update({'passport_cc': cc_display(ast.literal_eval(data['con']))})

        if 'eqn' in data:
            info.update({'eqns': data['eqn']})

        if 'ndim' in data:
            info.update({'Ndim': data['ndim']})

        other_data = False

        if 'hyperelliptic' in data:
            info.update({'ishyp': tfTOyn(data['hyperelliptic'])})
            other_data = True

        if 'hyp_involution' in data:
            inv = Permutation(data['hyp_involution']).cycle_string()
            info.update({'hypinv': sep.join(split_perm(inv))})

        if 'cyclic_trigonal' in data:
            info.update({'iscyctrig': tfTOyn(data['cyclic_trigonal'])})
            other_data = True

        if 'jacobian_decomp' in data:
            jcLatex, corrChar = decjac_format(data['jacobian_decomp'])
            info.update({'corrChar': corrChar, 'jacobian_decomp': jcLatex})

        if 'cinv' in data:
            cinv = Permutation(data['cinv']).cycle_string()
            info.update({'cinv': sep.join(split_perm(cinv))})

        info.update({'other_data': other_data})

        if 'full_auto' in data:
            full_G = ast.literal_eval(data['full_auto'])
            full_gn = full_G[0]
            full_gt = full_G[1]

            full_gp_string = str(full_gn) + '.' + str(full_gt)
            full_pretty_group = sg_pretty(full_gp_string)
            info.update({
                'fullauto': full_pretty_group,
                'signH': sign_display(ast.literal_eval(data['signH'])),
                'higgenlabel': data['full_label']
            })

        urlstrng, br_g, br_gp, br_sign, _ = split_passport_label(label)

        if Lfriends:
            friends = [("Full automorphism " + Lf, Lf) for Lf in Lfriends]
            friends += [("Family containing this refined passport ", urlstrng)]
        else:
            friends = [("Family containing this refined passport", urlstrng)]

        bread_sign = label_to_breadcrumbs(br_sign)
        bread_gp = label_to_breadcrumbs(br_gp)

        bread = get_bread([(br_g, './?genus=' + br_g),
                           ('$' + pretty_group + '$',
                            './?genus=' + br_g + '&group=' + bread_gp),
                           (bread_sign, urlstrng), (data['cc'][0], ' ')])

        learnmore = [('Completeness of the data',
                      url_for(".completeness_page")),
                     ('Source of the data', url_for(".how_computed_page")),
                     ('Reliability of the data', url_for(".reliability_page")),
                     ('Labeling convention', url_for(".labels_page"))]

        downloads = [('Code to Magma',
                      url_for(".hgcwa_code_download",
                              label=label,
                              download_type='magma')),
                     ('Code to Gap',
                      url_for(".hgcwa_code_download",
                              label=label,
                              download_type='gap'))]

        return render_template("hgcwa-show-passport.html",
                               title=title,
                               bread=bread,
                               info=info,
                               properties=prop2,
                               friends=friends,
                               learnmore=learnmore,
                               downloads=downloads,
                               credit=credit)
Beispiel #55
0
def render_group_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        label = label.replace('t', 'T')
        C = base.getDBConnection()
        data = C.transitivegroups.groups.find_one({'label': label})
        if data is None:
            bread = get_bread([("Search error", url_for('.search'))])
            info['err'] = "Group " + label + " was not found in the database."
            info['label'] = label
            return search_input_error(info, bread)
        title = 'Galois Group:' + label
        n = data['n']
        t = data['t']
        data['yesno'] = yesno
        order = data['order']
        data['orderfac'] = latex(ZZ(order).factor())
        orderfac = latex(ZZ(order).factor())
        data['ordermsg'] = "$%s=%s$" % (order, latex(orderfac))
        if ZZ(order) == 1:
            data['ordermsg'] = "$1$"
        if ZZ(order).is_prime():
            data['ordermsg'] = "$%s$ (is prime)" % order
        pgroup = len(ZZ(order).prime_factors()) < 2
        if n == 1:
            G = gap.SmallGroup(n, t)
        else:
            G = gap.TransitiveGroup(n, t)
        if ZZ(order) < ZZ('10000000000'):
            ctable = chartable(n, t)
        else:
            ctable = 'Group too large'
        data['gens'] = generators(n, t)
        if n == 1 and t == 1:
            data['gens'] = 'None needed'
        data['chartable'] = ctable
        data['parity'] = "$%s$" % data['parity']
        data['cclasses'] = conjclasses(G, n)
        data['subinfo'] = subfield_display(C, n, data['subs'])
        data['resolve'] = resolve_display(C, data['resolve'])
        #    if len(data['resolve']) == 0: data['resolve'] = 'None'
        data['otherreps'] = otherrep_display(n, t, C, data['repns'])
        prop2 = [
            ('Order:', '\(%s\)' % order),
            ('n:', '\(%s\)' % data['n']),
            ('Cyclic:', yesno(data['cyc'])),
            ('Abelian:', yesno(data['ab'])),
            ('Solvable:', yesno(data['solv'])),
            ('Primitive:', yesno(data['prim'])),
            ('$p$-group:', yesno(pgroup)),
            ('Name:', group_display_short(n, t, C)),
        ]
        info.update(data)

        bread = get_bread([(label, ' ')])
        return render_template("gg-show-group.html",
                               credit=GG_credit,
                               title=title,
                               bread=bread,
                               info=info,
                               properties2=prop2)
Beispiel #56
0
def render_field_webpage(args):
    data = None
    C = base.getDBConnection()
    info = {}
    bread = [('Global Number Fields', url_for(".number_field_render_webpage"))]

    if 'label' in args:
        label = clean_input(args['label'])
        nf = WebNumberField(label)
        data = {}
    if nf.is_null():
        bread.append(('Search results', ' '))
        label2 = re.sub(r'[<>]', '', args['label'])
        if 'You need to enter a field' in label2:
            info['err'] = label2
        else:
            info['err'] = 'No such field: %s in the database' % label2
        info['label'] = args['label_orig'] if 'label_orig' in args else args[
            'label']
        return search_input_error(info, bread)

    info['wnf'] = nf
    from lmfdb.WebNumberField import nf_display_knowl
    data['degree'] = nf.degree()
    data['class_number'] = nf.class_number()
    t = nf.galois_t()
    n = nf.degree()
    data['is_galois'] = nf.is_galois()
    data['is_abelian'] = nf.is_abelian()
    if nf.is_abelian():
        conductor = nf.conductor()
        data['conductor'] = conductor
        dirichlet_chars = nf.dirichlet_group()
        if len(dirichlet_chars) > 0:
            data['dirichlet_group'] = [
                '<a href = "%s">$\chi_{%s}(%s,&middot;)$</a>' %
                (url_for('characters.render_Dirichletwebpage',
                         modulus=data['conductor'],
                         number=j), data['conductor'], j)
                for j in dirichlet_chars
            ]
            data['dirichlet_group'] = r'$\lbrace$' + ', '.join(
                data['dirichlet_group']) + r'$\rbrace$'
        if data['conductor'].is_prime() or data['conductor'] == 1:
            data['conductor'] = "\(%s\)" % str(data['conductor'])
        else:
            data['conductor'] = "\(%s=%s\)" % (str(
                data['conductor']), latex(data['conductor'].factor()))
    data['galois_group'] = group_display_knowl(n, t, C)
    data['cclasses'] = cclasses_display_knowl(n, t, C)
    data['character_table'] = character_table_display_knowl(n, t, C)
    data['class_group'] = nf.class_group()
    data['class_group_invs'] = nf.class_group_invariants()
    data['signature'] = nf.signature()
    data['coefficients'] = nf.coeffs()
    D = nf.disc()
    ram_primes = D.prime_factors()
    data['disc_factor'] = nf.disc_factored_latex()
    if D.abs().is_prime() or D == 1:
        data['discriminant'] = "\(%s\)" % str(D)
    else:
        data['discriminant'] = "\(%s=%s\)" % (str(D), data['disc_factor'])
    npr = len(ram_primes)
    ram_primes = str(ram_primes)[1:-1]
    if ram_primes == '':
        ram_primes = r'\textrm{None}'
    data['frob_data'], data['seeram'] = frobs(nf.K())
    data['phrase'] = group_phrase(n, t, C)
    zk = nf.zk()
    Ra = PolynomialRing(QQ, 'a')
    zk = [latex(Ra(x)) for x in zk]
    zk = ['$%s$' % x for x in zk]
    zk = ', '.join(zk)
    grh_label = '<small>(<a title="assuming GRH" knowl="nf.assuming_grh">assuming GRH</a>)</small>' if nf.used_grh(
    ) else ''
    # Short version for properties
    grh_lab = nf.short_grh_string()
    if 'Not' in str(data['class_number']):
        grh_lab = ''
        grh_label = ''
    pretty_label = field_pretty(label)
    if label != pretty_label:
        pretty_label = "%s: %s" % (label, pretty_label)

    info.update(data)
    info.update({
        'label':
        pretty_label,
        'label_raw':
        label,
        'polynomial':
        web_latex_split_on_pm(nf.K().defining_polynomial()),
        'ram_primes':
        ram_primes,
        'integral_basis':
        zk,
        'regulator':
        web_latex(nf.regulator()),
        'unit_rank':
        nf.unit_rank(),
        'root_of_unity':
        web_latex(nf.K().primitive_root_of_unity()),
        'fund_units':
        nf.units(),
        'grh_label':
        grh_label
    })

    bread.append(('%s' % info['label_raw'], ' '))
    info['downloads_visible'] = True
    info['downloads'] = [('worksheet', '/')]
    info['friends'] = []
    if nf.can_class_number():
        info['friends'].append(('L-function', "/L/NumberField/%s" % label))
    info['friends'].append(('Galois group', "/GaloisGroup/%dT%d" % (n, t)))
    if 'dirichlet_group' in info:
        info['friends'].append(('Dirichlet group',
                                url_for("characters.dirichlet_group_table",
                                        modulus=int(conductor),
                                        char_number_list=','.join(
                                            [str(a) for a in dirichlet_chars]),
                                        poly=info['polynomial'])))
    info['learnmore'] = [('Global number field labels',
                          url_for(".render_labels_page")),
                         (Completename, url_for(".render_discriminants_page")),
                         ('Quadratic imaginary class groups',
                          url_for(".render_class_group_data"))]
    # With Galois group labels, probably not needed here
    # info['learnmore'] = [('Global number field labels',
    # url_for(".render_labels_page")), ('Galois group
    # labels',url_for(".render_groups_page")),
    # (Completename,url_for(".render_discriminants_page"))]
    title = "Global Number Field %s" % info['label']

    if npr == 1:
        primes = 'prime'
    else:
        primes = 'primes'

    properties2 = [
        ('Degree:', '%s' % data['degree']),
        ('Signature:', '$%s$' % data['signature']),
        ('Discriminant:', '$%s$' % data['disc_factor']),
        ('Ramified ' + primes + ':', '$%s$' % ram_primes),
        ('Class number:', '%s %s' % (data['class_number'], grh_lab)),
        ('Class group:', '%s %s' % (data['class_group_invs'], grh_lab)),
        ('Galois Group:', group_display_short(data['degree'], t, C))
    ]
    from lmfdb.math_classes import NumberFieldGaloisGroup
    try:
        info["tim_number_field"] = NumberFieldGaloisGroup.find_one(
            {"label": label})
        v = nf.factor_perm_repn(info["tim_number_field"])
        info["mydecomp"] = ['*' if x > 0 else '' for x in v]
    except AttributeError:
        pass


#    del info['_id']
    return render_template("number_field.html",
                           properties2=properties2,
                           credit=NF_credit,
                           title=title,
                           bread=bread,
                           friends=info.pop('friends'),
                           learnmore=info.pop('learnmore'),
                           info=info)
Beispiel #57
0
def elliptic_curve_search(**args):
    info = to_dict(args)
    query = {}
    bread = [('Elliptic Curves', url_for(".rational_elliptic_curves")),
             ('Search Results', '.')]
    if 'jump' in args:
        label = info.get('label', '').replace(" ", "")
        m = lmfdb_label_regex.match(label)
        if m:
            try:
                return by_ec_label(label)
            except ValueError:
                return elliptic_curve_jump_error(label,
                                                 info,
                                                 wellformed_label=True)
        elif label.startswith("Cremona:"):
            label = label[8:]
            m = cremona_label_regex.match(label)
            if m:
                try:
                    return by_ec_label(label)
                except ValueError:
                    return elliptic_curve_jump_error(label,
                                                     info,
                                                     wellformed_label=True)
        elif cremona_label_regex.match(label):
            return elliptic_curve_jump_error(label, info, cremona_label=True)
        elif label:
            # Try to parse a string like [1,0,3,2,4]
            lab = re.sub(r'\s', '', label)
            lab = re.sub(r'^\[', '', lab)
            lab = re.sub(r']$', '', lab)
            try:
                labvec = lab.split(',')
                labvec = [QQ(str(z)) for z in labvec]  # Rationals allowed
                E = EllipticCurve(labvec)
                ainvs = [str(c) for c in E.minimal_model().ainvs()]
                C = lmfdb.base.getDBConnection()
                data = C.elliptic_curves.curves.find_one({'ainvs': ainvs})
                if data is None:
                    return elliptic_curve_jump_error(label, info)
                return by_ec_label(data['lmfdb_label'])
            except (ValueError, ArithmeticError):
                return elliptic_curve_jump_error(label, info)
        else:
            query['label'] = ''

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

    for field in ['conductor', 'torsion', 'rank', 'sha_an']:
        if info.get(field):
            info[field] = clean_input(info[field])
            ran = info[field]
            ran = ran.replace('..', '-').replace(' ', '')
            if not LIST_RE.match(ran):
                names = {
                    'conductor': 'conductor',
                    'torsion': 'torsion order',
                    'rank': 'rank',
                    'sha_an': 'analytic order of &#1064;'
                }
                info[
                    'err'] = 'Error parsing input for the %s.  It needs to be an integer (such as 5), a range of integers (such as 2-10 or 2..10), or a comma-separated list of these (such as 2,3,8 or 3-5, 7, 8-11).' % names[
                        field]
                return search_input_error(info, bread)
            # Past input check
            tmp = parse_range2(ran, field)
            # work around syntax for $or
            # we have to foil out multiple or conditions
            if tmp[0] == '$or' and '$or' in query:
                newors = []
                for y in tmp[1]:
                    oldors = [dict.copy(x) for x in query['$or']]
                    for x in oldors:
                        x.update(y)
                    newors.extend(oldors)
                tmp[1] = newors
            if field == 'sha_an':  # database sha_an values are not all exact!
                query[tmp[0]] = {'$gt': tmp[1] - 0.1, '$lt': tmp[1] + 0.1}
            else:
                query[tmp[0]] = tmp[1]

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

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

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

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

    info['query'] = query

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

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

    cursor = lmfdb.base.getDBConnection().elliptic_curves.curves.find(query)
    nres = cursor.count()
    if (start >= nres):
        start -= (1 + (start - nres) / count) * count
    if (start < 0):
        start = 0
    res = cursor.sort([('conductor', ASCENDING), ('lmfdb_iso', ASCENDING),
                       ('lmfdb_number', ASCENDING)]).skip(start).limit(count)
    info['curves'] = res
    info['format_ainvs'] = format_ainvs
    info['number'] = nres
    info['start'] = start
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (
                start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres
    credit = 'John Cremona'
    if 'non-surjective_primes' in query:
        credit += 'and Andrew Sutherland'
    t = 'Elliptic Curves'
    return render_template("search_results.html",
                           info=info,
                           credit=credit,
                           bread=bread,
                           title=t)
Beispiel #58
0
def number_field_search(**args):
    info = to_dict(args)

    info['learnmore'] = [
        ('Global number field labels', url_for(".render_labels_page")),
        ('Galois group labels', url_for(".render_groups_page")),
        (Completename, url_for(".render_discriminants_page")),
        ('Quadratic imaginary class groups',
         url_for(".render_class_group_data"))
    ]
    t = 'Global Number Field search results'
    bread = [('Global Number Fields', url_for(".number_field_render_webpage")),
             ('Search results', ' ')]

    # for k in info.keys():
    #  nf_logger.debug(str(k) + ' ---> ' + str(info[k]))
    # nf_logger.debug('******************* '+ str(info['search']))

    if 'natural' in info:
        field_id = info['natural']
        field_id_parsed = parse_field_string(info['natural'])
        if FIELD_LABEL_RE.match(field_id_parsed):
            field_id_parsed = split_label(
                field_id_parsed)  # allows factored labels 11.11.11e20.1
        return render_field_webpage({
            'label': field_id_parsed,
            'label_orig': field_id
        })
    query = {}
    dlist = []
    for field in [
            'galois_group', 'degree', 'signature', 'discriminant',
            'class_number', 'class_group'
    ]:
        if info.get(field):
            info[field] = clean_input(info[field])
            if field in ['class_group', 'signature']:
                # different regex for the two types
                if (field == 'signature' and PAIR_RE.match(info[field])) or (
                        field == 'class_group' and IF_RE.match(info[field])):
                    query[field] = info[field][1:-1]
                else:
                    name = 'class group' if field == 'class_group' else 'signature'
                    info[
                        'err'] = 'Error parsing input for %s.  It needs to be a pair of integers in square brackets, such as [2,3] or [3,3]' % name
                    return search_input_error(info, bread)
            else:
                if field == 'galois_group':
                    try:
                        gcs = complete_group_codes(info[field])
                        if len(gcs) == 1:
                            query['galois'] = make_galois_pair(
                                gcs[0][0], gcs[0][1])


# list(gcs[0])
                        if len(gcs) > 1:
                            query['galois'] = {
                                '$in':
                                [make_galois_pair(x[0], x[1]) for x in gcs]
                            }
                    except NameError as code:
                        info[
                            'err'] = 'Error parsing input for Galois group: unknown group label %s.  It needs to be a <a title = "Galois group labels" knowl="nf.galois_group.name">group label</a>, such as C5 or 5T1, or comma separated list of labels.' % code
                        return search_input_error(info, bread)
                else:  # not signature, class group, or galois group
                    ran = info[field]
                    ran = ran.replace('..', '-')
                    if LIST_RE.match(ran):
                        if field == 'discriminant':
                            # dlist will contain the disc conditions
                            # as sage ints
                            dlist = parse_discs(ran)
                            # now convert to a query
                            tmp = list_to_query(dlist)
                            # Two cases, could be a list of sign/inequalties
                            # or an '$or'
                            if len(tmp) == 1:
                                tmp = tmp[0]
                            else:
                                query[tmp[0][0]] = tmp[0][1]
                                tmp = tmp[1]
                        else:
                            tmp = parse_range2(ran, field)
                        # work around syntax for $or
                        # we have to foil out multiple or conditions
                        if tmp[0] == '$or' and '$or' in query:
                            newors = []
                            for y in tmp[1]:
                                oldors = [dict.copy(x) for x in query['$or']]
                                for x in oldors:
                                    x.update(y)
                                newors.extend(oldors)
                            tmp[1] = newors
                        query[tmp[0]] = tmp[1]
                    else:
                        name = re.sub('_', ' ', field)
                        info[
                            'err'] = 'Error parsing input for %s.  It needs to be an integer (such as 5), a range of integers (such as 2-100 or 2..100), or a comma-separated list of these (such as 2,3,8 or 3-5, 7, 8-100).' % name
                        return search_input_error(info, bread)
    if info.get('ur_primes'):
        # now we want a list of strings, no spaces, which might be big ints
        info['ur_primes'] = clean_input(info['ur_primes'])
        if LIST_SIMPLE_RE.match(info['ur_primes']):
            ur_primes = info['ur_primes'].split(',')
            # Assuming this will be the only nor in the query
            query['$nor'] = [{'ramps': x} for x in ur_primes]
        else:
            info[
                'err'] = 'Error parsing input for unramified primes.  It needs to be an integer (such as 5), or a comma-separated list of integers (such as 2,3,11).'
            return search_input_error(info, bread)
    if info.get('ram_primes'):
        # now we want a list of strings, no spaces, which might be big ints
        info['ram_primes'] = clean_input(info['ram_primes'])
        if LIST_SIMPLE_RE.match(info['ram_primes']):
            ram_primes = info['ram_primes'].split(',')
            if str(info['ram_quantifier']) == 'some':
                query['ramps'] = {'$all': ram_primes}
            else:
                query['ramps'] = ram_primes
        else:
            info[
                'err'] = 'Error parsing input for ramified primes.  It needs to be an integer (such as 5), or a comma-separated list of integers (such as 2,3,11).'
            return search_input_error(info, bread)

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

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

    C = base.getDBConnection()
    # nf_logger.debug(query)
    info['query'] = dict(query)
    if 'lucky' in args:
        one = C.numberfields.fields.find_one(query)
        if one:
            label = one['label']
            return render_field_webpage({'label': label})

    fields = C.numberfields.fields

    res = fields.find(query).sort([('degree', ASC), ('disc_abs_key', ASC),
                                   ('disc_sign', ASC), ('label', ASC)])

    if 'download' in info and info['download'] != '0':
        return download_search(info, res)

    nres = res.count()
    res = res.skip(start).limit(count)

    if (start >= nres):
        start -= (1 + (start - nres) / count) * count
    if (start < 0):
        start = 0

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

    info['wnf'] = WebNumberField.from_data
    return render_template("number_field_search.html",
                           info=info,
                           title=t,
                           bread=bread)
Beispiel #59
0
def render_hecke_algebras_webpage_l_adic(**args):
    data = None
    if 'orbit_label' in args and 'prime' in args:
        lab = clean_input(args.get('orbit_label'))
        if lab != args.get('orbit_label'):
            base_lab = ".".join([split(lab)[i] for i in [0, 1, 2]])
            return redirect(
                url_for('.render_hecke_algebras_webpage', label=base_lab), 301)
        try:
            ell = int(args.get('prime'))
        except ValueError:
            base_lab = ".".join([split(lab)[i] for i in [0, 1, 2]])
            return redirect(
                url_for('.render_hecke_algebras_webpage', label=base_lab), 301)
        data = db.hecke_ladic.lucky({'orbit_label': lab, 'ell': ell})
    if data is None:
        t = "Hecke algebra search error"
        bread = [('HeckeAlgebra', url_for(".hecke_algebras_render_webpage"))]
        flash_error(
            "%s is not a valid label for the &#x2113;-adic information for an Hecke algebra orbit in the database.",
            lab)
        return render_template("hecke_algebras-error.html",
                               title=t,
                               properties=[],
                               bread=bread,
                               learnmore=learnmore_list())
    info = {}
    info.update(data)

    proj = [
        'index', 'orbit_label', 'ell', 'idempotent', 'field', 'structure',
        'properties', 'operators'
    ]
    res = list(
        db.hecke_ladic.search(
            {
                'level': data['level'],
                'weight': data['weight'],
                'orbit_label': data['orbit_label'],
                'ell': data['ell']
            }, proj))

    for f in res:
        if f['idempotent'] != "":
            dim = len(sage_eval(f['idempotent']))
            l_max = sage_eval(f['idempotent'])[0][0].ndigits()
            if dim > 4 or l_max > 5:
                f['idempotent_display'] = []
            elif dim == 1:
                f['idempotent_display'] = sage_eval(f['idempotent'])[0][0]
            else:
                f['idempotent_display'] = latex(
                    matrix(sage_eval(f['idempotent'])))
        else:
            f['idempotent_display'] = latex(matrix([[1]]))
        del f['idempotent']
        f['download_id'] = [
            (i,
             url_for(".render_hecke_algebras_webpage_ell_download",
                     orbit_label=f['orbit_label'],
                     index=f['index'],
                     prime=f['ell'],
                     lang=i,
                     obj='idempotents')) for i in ['magma', 'sage']
        ]  # for 'gp' the code does not work, since p-adics are not implemented
        field = f.pop('field')
        if field is not None:
            f['deg'] = field[1]
            f['field_poly'] = field[2]
        structure = f.pop('structure')
        if structure is not None:
            f['dim'] = structure[0]
            f['num_gen'] = structure[1]
            s2 = sage_eval(structure[2])
            f['gens'] = [[int(s2.index(i) + 1), str(i)] for i in s2]
            f['rel'] = sage_eval(structure[3])
        properties = f.pop('properties')
        if properties is not None:
            f['grading'] = properties[0]
            f['gorenstein_def'] = properties[1]
            f['gorenstein'] = "yes" if properties[1] == 0 else "no"
        operators = f.pop('operators')
        if operators is not None:
            f['operators_mod_l'] = operators
            f['num_hecke_op'] = len(operators)
            f['size_op'] = size = sqrt(len(operators[0]))
            if size > 4:
                f['operators_mod_l_display'] = []
            elif size == 1:
                f['operators_mod_l_display'] = [[i + 1, operators[i][0]]
                                                for i in range(10)]
            else:
                f['operators_mod_l_display'] = [[
                    i + 1, latex(matrix(size, size, operators[i]))
                ] for i in range(5)]
            f['download_op'] = [
                (lang,
                 url_for(".render_hecke_algebras_webpage_ell_download",
                         orbit_label=f['orbit_label'],
                         index=f['index'],
                         prime=f['ell'],
                         lang=lang,
                         obj='operators')) for lang in ['magma', 'sage']
            ]  # for 'gp' the code does not work

    info['num_l_adic_orbits'] = len(res)
    info['l_adic_orbits'] = res
    info['level'] = int(data['level'])
    info['weight'] = int(data['weight'])
    info['base_lab'] = ".".join(
        [split(data['orbit_label'])[i] for i in [0, 1, 2]])
    info['orbit_label'] = str(data['orbit_label'])
    info['ell'] = int(data['ell'])

    bread = [('HeckeAlgebra', url_for(".hecke_algebras_render_webpage")),
             ('%s' % info['base_lab'],
              url_for('.render_hecke_algebras_webpage',
                      label=info['base_lab'])), ('%s' % info['ell'], ' ')]
    credit = hecke_algebras_credit
    info['properties'] = [('Level', '%s' % info['level']),
                          ('Weight', '%s' % info['weight']),
                          ('Characteristic', '%s' % info['ell']),
                          ('Orbit label', '%s' % info['orbit_label'])]
    info['friends'] = [('Modular form ' + info['base_lab'],
                        url_for("cmf.by_url_space_label",
                                level=info['level'],
                                weight=info['weight'],
                                char_orbit_label='a'))]

    t = "%s-adic and mod %s data for the Hecke algebra orbit %s" % (
        info['ell'], info['ell'], info['orbit_label'])
    return render_template("hecke_algebras_l_adic-single.html",
                           info=info,
                           credit=credit,
                           title=t,
                           bread=bread,
                           properties=info['properties'],
                           learnmore=learnmore_list(),
                           friends=info['friends'],
                           KNOWL_ID='hecke_algebra_l_adic.%s' %
                           (info['orbit_label']))
Beispiel #60
0
def elliptic_curve_search(**args):
    info = to_dict(args['data'])
    if 'jump' in info:
        label = info.get('label', '').replace(" ", "")
        # This label should be a full isogeny class label or a full
        # curve label (including the field_label component)
        try:
            nf, cond_label, iso_label, number = split_full_label(label.strip())
        except IndexError:
            if not 'query' in info:
                info['query'] = {}
            bread = [("Elliptic Curves", url_for(".index"))]
            info[
                'err'] = 'No elliptic curve in the database has label %s.' % label
            return search_input_error(info, bread)

        return show_ecnf(nf, cond_label, iso_label, number)

    query = {}
    bread = [('Elliptic Curves', url_for(".index")), ('Search Results', '.')]

    if 'conductor_norm' in info:
        Nnorm = clean_input(info['conductor_norm'])
        Nnorm = Nnorm.replace('..', '-').replace(' ', '')
        tmp = parse_range2(Nnorm, 'conductor_norm')
        if tmp[0] == '$or' and '$or' in query:
            newors = []
            for y in tmp[1]:
                oldors = [dict.copy(x) for x in query['$or']]
                for x in oldors:
                    x.update(y)
                newors.extend(oldors)
            tmp[1] = newors
        query[tmp[0]] = tmp[1]

    if 'conductor_label' in info:
        query['conductor_label'] = info['conductor_label']

    if 'jinv' in info:
        query['jinv'] = info['jinv']

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

    if 'torsion_structure' in info and info['torsion_structure']:
        res = parse_torsion_structure(info['torsion_structure'], 2)
        if 'Error' in res:
            info['err'] = res
            return search_input_error(info, bread)
        #update info for repeat searches
        info['torsion_structure'] = str(res).replace(' ', '')
        query['torsion_structure'] = [int(r) for r in res]

    if 'include_isogenous' in info and info['include_isogenous'] == 'off':
        query['number'] = 1

    if 'include_base_change' in info and info['include_base_change'] == 'off':
        query['base_change'] = []
    else:
        info['include_base_change'] = "on"

    if 'field' in info:
        query['field_label'] = parse_field_string(info['field'])

    info['query'] = query

    # process count and start if not default:

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

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


# make the query and trim results according to start/count:

    cursor = db_ecnf().find(query)
    nres = cursor.count()
    if (start >= nres):
        start -= (1 + (start - nres) / count) * count
    if (start < 0):
        start = 0
    res = cursor.sort([('field_label', ASC), ('conductor_norm', ASC),
                       ('conductor_label', ASC), ('iso_nlabel', ASC),
                       ('number', ASC)]).skip(start).limit(count)

    res = list(res)
    for e in res:
        e['numb'] = str(e['number'])
        e['field_knowl'] = nf_display_knowl(e['field_label'],
                                            getDBConnection(),
                                            e['field_label'])

    info['curves'] = res  # [ECNF(e) for e in res]
    info['number'] = nres
    info['start'] = start
    info['count'] = count
    info['more'] = int(start + count < nres)
    info['field_pretty'] = field_pretty
    info['web_ainvs'] = web_ainvs
    if nres == 1:
        info['report'] = 'unique match'
    else:
        if nres > count or start != 0:
            info['report'] = 'displaying matches %s-%s of %s' % (
                start + 1, min(nres, start + count), nres)
        else:
            info['report'] = 'displaying all %s matches' % nres
    t = 'Elliptic Curve search results'
    return render_template("ecnf-search-results.html",
                           info=info,
                           credit=ecnf_credit,
                           bread=bread,
                           title=t)