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)
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"))
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"))
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)
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"))
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"))
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)
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)
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
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"))
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)
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)
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())
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)
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, )
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 Ш'} 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)
def parse_artin_label(label): label = clean_input(label) if LABEL_RE.match(label): return label else: raise ValueError
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)
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 Ш", } 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)
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)
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)
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)
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,·)$</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, )
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)
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)
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)
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)
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']))
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 Ш'} 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)
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())
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)
def parse_artin_orbit_label(label): label = clean_input(label) if ORBIT_RE.match(label): return label else: raise ValueError
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)
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)
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 Ш'} 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)
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})
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'])
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 ℓ-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']))
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})
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)
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})
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())
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,·)$</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)
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())
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)
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,·)$</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)
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)
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)
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)
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'])
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)
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())
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)
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,·)$</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)
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 Ш' } 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)
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)
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 ℓ-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']))
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)