def elliptic_curve_search(info, query): parse_rational(info,query,'jinv','j-invariant') parse_ints(info,query,'conductor') parse_ints(info,query,'torsion','torsion order') parse_ints(info,query,'rank') parse_ints(info,query,'sha','analytic order of Ш') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2,check_divisibility='increasing') # speed up slow torsion_structure searches by also setting torsion #if 'torsion_structure' in query and not 'torsion' in query: # query['torsion'] = reduce(mul,[int(n) for n in query['torsion_structure']],1) if 'include_cm' in info: if info['include_cm'] == 'exclude': query['cm'] = 0 elif info['include_cm'] == 'only': query['cm'] = {'$ne' : 0} parse_element_of(info,query,field='isodeg',qfield='isogeny_degrees',split_interval=1000) #parse_ints(info,query,field='isodeg',qfield='isogeny_degrees') parse_primes(info, query, 'surj_primes', name='maximal primes', qfield='nonmax_primes', mode='complement') if info.get('surj_quantifier') == 'exactly': mode = 'exact' else: mode = 'append' parse_primes(info, query, 'nonsurj_primes', name='non-maximal primes', qfield='nonmax_primes',mode=mode, radical='nonmax_rad') if 'optimal' in info and info['optimal'] == 'on': # For all isogeny classes except 990h the optimal curve is number 1, while for class 990h it is number 3. # So setting query['number'] = 1 is nearly correct, but fails on 990h3. # Instead, we use this more complicated query: query.update({"$or":[{'iso':'990h', 'number':3}, {'iso':{'$ne':'990h'},'number':1}]}) info['curve_url_LMFDB'] = 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_LMFDB'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1]) info['curve_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['label']) info['iso_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['iso'])
def galois_group_search(info, query): def includes_composite(s): s = s.replace(' ','').replace('..','-') for interval in s.split(','): if '-' in interval[1:]: ix = interval.index('-',1) a,b = int(interval[:ix]), int(interval[ix+1:]) if b == a: if a != 1 and not a.is_prime(): return True if b > a and b > 3: return True else: a = ZZ(interval) if a != 1 and not a.is_prime(): return True parse_ints(info,query,'n','degree') parse_ints(info,query,'t') parse_ints(info,query,'order') parse_bracketed_posints(info, query, qfield='gapidfull', split=False, exactlength=2, keepbrackets=True, name='GAP id', field='gapid') for param in ('cyc', 'solv', 'prim'): parse_bool(info, query, param, process=int, blank=['0','Any']) parse_restricted(info,query,'parity',allowed=[1,-1],process=int,blank=['0','Any']) if 'order' in query and 'n' not in query: query['__sort__'] = ['order', 'gapid', 'n', 't'] degree_str = prep_ranges(info.get('n')) info['show_subs'] = degree_str is None or (LIST_RE.match(degree_str) and includes_composite(degree_str)) info['group_display'] = group_display_pretty info['yesno'] = yesno info['wgg'] = WebGaloisGroup.from_data
def higher_genus_w_automorphisms_search(info, query): if info.get('signature'): # allow for ; in signature info['signature'] = info['signature'].replace(';', ',') parse_bracketed_posints(info, query, 'signature', split=False, name='Signature', keepbrackets=True) if query.get('signature'): query['signature'] = info['signature'] = str( sort_sign(ast.literal_eval(query['signature']))).replace( ' ', '') parse_gap_id(info, query, 'group', qfield='group') parse_ints(info, query, 'g0') parse_ints(info, query, 'genus') parse_ints(info, query, 'dim') parse_group_order(info, query, 'group_order') if 'inc_hyper' in info: if info['inc_hyper'] == 'exclude': query['hyperelliptic'] = False elif info['inc_hyper'] == 'only': query['hyperelliptic'] = True if 'inc_cyc_trig' in info: if info['inc_cyc_trig'] == 'exclude': query['cyclic_trigonal'] = False elif info['inc_cyc_trig'] == 'only': query['cyclic_trigonal'] = True if 'inc_full' in info: if info['inc_full'] == 'exclude': query['full_auto'] = {'$exists': True} elif info['inc_full'] == 'only': query['full_auto'] = {'$exists': False} query['cc.1'] = 1 info['group_display'] = group_display info['sign_display'] = sign_display if 'sort_order' in info: if info['sort_order'] == '': query['__sort__'] = ['genus', 'group_order', 'g0', 'dim'] elif info['sort_order'] == 'descgenus': query['__sort__'] = [('genus', -1), 'group_order', 'g0', 'dim'] elif info['sort_order'] == 'g0': query['__sort__'] = ['g0', 'genus', 'group_order', 'dim'] elif info['sort_order'] == 'descg0': query['__sort__'] = [('g0', -1), 'genus', 'group_order', 'dim'] elif info.get('sort_order') == 'dim': query['__sort__'] = ['dim', 'genus', 'group_order', 'g0'] elif info.get('sort_order') == 'descdim': query['__sort__'] = [('dim', -1), 'genus', 'group_order', 'g0'] elif info.get('sort_order') == 'group_order': query['__sort__'] = ['group_order', 'genus', 'g0', 'dim'] elif info.get('sort_order') == 'descgroup_order': query['__sort__'] = [('group_order', -1), 'genus', 'g0', 'dim'] else: query['__sort__'] = ['genus', 'group_order', 'g0', 'dim']
def number_field_search(info, query): parse_ints(info,query,'degree') parse_galgrp(info,query, qfield=('degree', 'galt')) parse_bracketed_posints(info,query,'signature',qfield=('degree','r2'),exactlength=2,extractor=lambda L: (L[0]+2*L[1],L[1])) parse_signed_ints(info,query,'discriminant',qfield=('disc_sign','disc_abs')) parse_floats(info, query, 'rd') parse_floats(info, query, 'regulator') parse_ints(info,query,'class_number') parse_ints(info,query,'num_ram') parse_bool(info,query,'cm_field',qfield='cm') parse_bracketed_posints(info,query,'class_group',check_divisibility='increasing',process=int) parse_primes(info,query,'ur_primes',name='Unramified primes', qfield='ramps',mode='complement') # modes are now contained (in), exactly, include if 'ram_quantifier' in info and str(info['ram_quantifier']) == 'include': mode='append' elif 'ram_quantifier' in info and str(info['ram_quantifier']) == 'contained': mode='subsets' else: mode='exact' parse_primes(info,query,'ram_primes',name='Ramified primes', qfield='ramps',mode=mode,radical='disc_rad') ## This seems not to be used #if 'lucky' in info: # label = db.nf_fields.lucky(query, 0) # if label: # return redirect(url_for(".by_label", label=clean_input(label))) info['wnf'] = WebNumberField.from_data info['gg_display'] = group_pretty_and_nTj
def elliptic_curve_search(info, query): parse_rational(info,query,'jinv','j-invariant') parse_ints(info,query,'conductor') parse_ints(info,query,'torsion','torsion order') parse_ints(info,query,'rank') parse_ints(info,query,'sha','analytic order of Ш') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2,check_divisibility='increasing') # speed up slow torsion_structure searches by also setting torsion #if 'torsion_structure' in query and not 'torsion' in query: # query['torsion'] = reduce(mul,[int(n) for n in query['torsion_structure']],1) if 'include_cm' in info: if info['include_cm'] == 'exclude': query['cm'] = 0 elif info['include_cm'] == 'only': query['cm'] = {'$ne' : 0} parse_element_of(info,query,field='isodeg',qfield='isogeny_degrees',split_interval=1000) #parse_ints(info,query,field='isodeg',qfield='isogeny_degrees') parse_primes(info, query, 'surj_primes', name='maximal primes', qfield='nonmax_primes', mode='complement') if info.get('surj_quantifier') == 'exactly': mode = 'exact' else: mode = 'append' parse_primes(info, query, 'nonsurj_primes', name='non-maximal primes', qfield='nonmax_primes',mode=mode, radical='nonmax_rad') if 'optimal' in info and info['optimal'] == 'on': # fails on 990h3 query['number'] = 1 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])
def number_field_search(info, query): parse_ints(info,query,'degree') parse_galgrp(info,query, qfield=('degree', 'galt')) parse_bracketed_posints(info,query,'signature',qfield=('degree','r2'),exactlength=2,extractor=lambda L: (L[0]+2*L[1],L[1])) parse_signed_ints(info,query,'discriminant',qfield=('disc_sign','disc_abs')) parse_floats(info, query, 'rd') parse_ints(info,query,'class_number') parse_bool(info,query,'cm_field',qfield='cm') parse_bracketed_posints(info,query,'class_group',check_divisibility='increasing',process=int) parse_primes(info,query,'ur_primes',name='Unramified primes', qfield='ramps',mode='complement') # modes are now contained (in), exactly, include if 'ram_quantifier' in info and str(info['ram_quantifier']) == 'include': mode='append' elif 'ram_quantifier' in info and str(info['ram_quantifier']) == 'contained': mode='subsets' else: mode='exact' parse_primes(info,query,'ram_primes',name='Ramified primes', qfield='ramps',mode=mode,radical='disc_rad') ## This seems not to be used #if 'lucky' in info: # label = db.nf_fields.lucky(query, 0) # if label: # return redirect(url_for(".by_label", label=clean_input(label))) info['wnf'] = WebNumberField.from_data info['gg_display'] = group_pretty_and_nTj
def genus2_curve_search(info, query): info["st_group_list"] = st_group_list info["st_group_dict"] = st_group_dict info["real_geom_end_alg_list"] = real_geom_end_alg_list info["real_geom_end_alg_to_ST0_dict"] = real_geom_end_alg_to_ST0_dict info["aut_grp_list"] = aut_grp_list info["aut_grp_dict"] = aut_grp_dict info["geom_aut_grp_list"] = geom_aut_grp_list info["geom_aut_grp_dict"] = geom_aut_grp_dict parse_ints(info,query,'abs_disc','absolute discriminant') parse_bool(info,query,'is_gl2_type','is of GL2-type') parse_bool(info,query,'has_square_sha','has square Sha') parse_bool(info,query,'locally_solvable','is locally solvable') parse_bool(info,query,'is_simple_geom','is geometrically simple') parse_ints(info,query,'cond','conductor') parse_ints(info,query,'num_rat_pts','rational points') parse_ints(info,query,'num_rat_wpts','rational Weierstrass points') parse_bracketed_posints(info, query, 'torsion', 'torsion structure', maxlength=4,check_divisibility="increasing") parse_ints(info,query,'torsion_order','torsion order') if 'torsion' in query and not 'torsion_order' in query: query['torsion_order'] = reduce(mul,[int(n) for n in query['torsion']],1) if 'torsion' in query: query['torsion_subgroup'] = str(query['torsion']).replace(" ","") query.pop('torsion') # search using string key, not array of ints parse_ints(info,query,'two_selmer_rank','2-Selmer rank') parse_ints(info,query,'analytic_rank','analytic rank') # G2 invariants and drop-list items don't require parsing -- they are all strings (supplied by us, not the user) if 'g20' in info and 'g21' in info and 'g22' in info: query['g2_inv'] = "['%s','%s','%s']"%(info['g20'], info['g21'], info['g22']) if 'class' in info: query['class'] = info['class'] for fld in ('st_group', 'real_geom_end_alg', 'aut_grp_id', 'geom_aut_grp_id'): if info.get(fld): query[fld] = info[fld] info["curve_url"] = lambda label: url_for_curve_label(label) info["class_url"] = lambda label: url_for_isogeny_class_label(label)
def galois_group_search(info, query): def includes_composite(s): s = s.replace(' ','').replace('..','-') for interval in s.split(','): if '-' in interval[1:]: ix = interval.index('-',1) a,b = int(interval[:ix]), int(interval[ix+1:]) if b == a: if a != 1 and not a.is_prime(): return True if b > a and b > 3: return True else: a = ZZ(interval) if a != 1 and not a.is_prime(): return True parse_ints(info,query,'n','degree') parse_ints(info,query,'t') parse_ints(info,query,'order') parse_ints(info,query,'nilpotency') parse_bracketed_posints(info, query, qfield='gapidfull', split=False, exactlength=2, keepbrackets=True, name='GAP id', field='gapid') for param in ('cyc', 'solv', 'prim'): parse_bool(info, query, param, process=int, blank=['0','Any']) parse_restricted(info,query,'parity',allowed=[1,-1],process=int,blank=['0','Any']) if 'order' in query and 'n' not in query: query['__sort__'] = ['order', 'gapid', 'n', 't'] degree_str = prep_ranges(info.get('n')) info['show_subs'] = degree_str is None or (LIST_RE.match(degree_str) and includes_composite(degree_str)) info['group_display'] = group_display_short info['yesno'] = yesno info['wgg'] = WebGaloisGroup.from_data
def elliptic_curve_search(info, query): parse_nf_string(info, query, 'field', name="base number field", qfield='field_label') if query.get('field_label') == '1.1.1.1': return redirect(url_for("ec.rational_elliptic_curves", **request.args), 301) parse_ints(info, query, 'conductor_norm') parse_noop(info, query, 'conductor_label') parse_ints(info, query, 'torsion', name='Torsion order', qfield='torsion_order') parse_bracketed_posints(info, query, 'torsion_structure', maxlength=2) if 'torsion_structure' in query and not 'torsion_order' in query: query['torsion_order'] = reduce( mul, [int(n) for n in query['torsion_structure']], 1) parse_ints(info, query, field='isodeg', qfield='isogeny_degrees') if 'jinv' in info: if info.get('field', '').strip() == '2.2.5.1': info['jinv'] = info['jinv'].replace('phi', 'a') if info.get('field', '').strip() == '2.0.4.1': info['jinv'] = info['jinv'].replace('i', 'a') parse_nf_elt(info, query, 'jinv', name='j-invariant') if query.get('jinv'): query['jinv'] = ','.join(query['jinv']) if 'include_isogenous' in info and info['include_isogenous'] == 'off': info['number'] = 1 query['number'] = 1 if 'include_base_change' in info: if info['include_base_change'] == 'off': query['base_change'] = [] if info['include_base_change'] == 'only': query['base_change'] = {'$ne': []} else: info['include_base_change'] = "on" if 'include_Q_curves' in info: if info['include_Q_curves'] == 'exclude': query['q_curve'] = False elif info['include_Q_curves'] == 'only': query['q_curve'] = True if 'include_cm' in info: if info['include_cm'] == 'exclude': query['cm'] = 0 elif info['include_cm'] == 'only': query['cm'] = {'$ne': 0} info['field_pretty'] = field_pretty info['web_ainvs'] = web_ainvs
def elliptic_curve_search(info, query): parse_nf_string(info,query,'field',name="base number field",qfield='field_label') if query.get('field_label') == '1.1.1.1': return redirect(url_for("ec.rational_elliptic_curves", **request.args), 301) parse_ints(info,query,'conductor_norm') parse_noop(info,query,'conductor_label') parse_ints(info,query,'torsion',name='Torsion order',qfield='torsion_order') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2) if 'torsion_structure' in query and not 'torsion_order' in query: t_o = 1 for n in query['torsion_structure']: t_o *= int(n) query['torsion_order'] = t_o parse_element_of(info,query,field='isodeg',qfield='isogeny_degrees',split_interval=1000) if 'jinv' in info: if info.get('field','').strip() == '2.2.5.1': info['jinv'] = info['jinv'].replace('phi','a') if info.get('field','').strip() == '2.0.4.1': info['jinv'] = info['jinv'].replace('i','a') if not 'a' in info['jinv'] and not info.get('field'): # rational j-invariant allowed for any field parse_rational(info, query, 'jinv', name='j-invariant') if query.get('jinv'): query['jinv'] = {'$regex': '^' + query['jinv'] + '(,0)*$'} # nf elements like j,0,0,0 else: # j-invariant is a number field element parse_nf_elt(info, query, 'jinv', name='j-invariant') if query.get('jinv'): query['jinv'] = ','.join(query['jinv']) if info.get('one') == "yes": info['number'] = 1 query['number'] = 1 if 'include_base_change' in info: if info['include_base_change'] in ['exclude', 'off']: # off for backward compat with urls query['base_change'] = [] if info['include_base_change'] == 'only': query['base_change'] = {'$ne':[]} else: info['include_base_change'] = "on" if 'include_Q_curves' in info: if info['include_Q_curves'] == 'exclude': query['q_curve'] = False elif info['include_Q_curves'] == 'only': query['q_curve'] = True if 'include_cm' in info: if info['include_cm'] == 'exclude': query['cm'] = 0 elif info['include_cm'] == 'only': query['cm'] = {'$ne' : 0} parse_ints(info,query,field='cm_disc',qfield='cm') info['field_pretty'] = field_pretty info['web_ainvs'] = web_ainvs
def elliptic_curve_search(info, query): parse_rational(info,query,'jinv','j-invariant') parse_ints(info,query,'conductor') parse_ints(info,query,'torsion','torsion order') parse_ints(info,query,'rank') parse_ints(info,query,'sha','analytic order of Ш') parse_ints(info,query,'num_int_pts','num_int_pts') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2,check_divisibility='increasing') # speed up slow torsion_structure searches by also setting torsion #if 'torsion_structure' in query and not 'torsion' in query: # query['torsion'] = reduce(mul,[int(n) for n in query['torsion_structure']],1) if 'include_cm' in info: if info['include_cm'] == 'exclude': query['cm'] = 0 elif info['include_cm'] == 'only': query['cm'] = {'$ne' : 0} parse_element_of(info,query,field='isodeg',qfield='isogeny_degrees',split_interval=1000) #parse_ints(info,query,field='isodeg',qfield='isogeny_degrees') parse_primes(info, query, 'surj_primes', name='maximal primes', qfield='nonmax_primes', mode='complement') if info.get('surj_quantifier') == 'exactly': mode = 'exact' else: mode = 'append' parse_primes(info, query, 'nonsurj_primes', name='non-maximal primes', qfield='nonmax_primes',mode=mode, radical='nonmax_rad') if info.get('bad_quantifier') == 'exactly': mode = 'exact' elif info.get('bad_quantifier') == 'exclude': mode = 'complement' else: mode = 'append' parse_primes(info, query, 'bad_primes', name='bad primes', qfield='bad_primes',mode=mode) # The button which used to be labelled Optimal only no/yes" # (default no) has been renamed "Curves per isogeny class all/one" # (default one) but the only change in behavious is that we no # longer treat class 990h (where the optial curve is #3 not #1) as # special: the "one" option just restricts to curves whose # 'number' is 1. if 'optimal' in info and info['optimal'] == 'on': query.update({'number':1}) # Old behaviour was as follows: # For all isogeny classes except 990h the optimal curve is number 1, while for class 990h it is number 3. # So setting query['number'] = 1 is nearly correct, but fails on 990h3. # Instead, we use this more complicated query: # query.update({"$or":[{'iso':'990h', 'number':3}, {'iso':{'$ne':'990h'},'number':1}]}) info['curve_ainvs'] = lambda dbc: str([ZZ(ai) for ai in dbc['ainvs']]) info['curve_url_LMFDB'] = 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_LMFDB'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1]) info['curve_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['label']) info['iso_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['iso'])
def belyi_search(info, query): if "group" in query: info["group"] = query["group"] parse_bracketed_posints(info, query, "abc_list", "a, b, c", maxlength=3) if query.get("abc_list"): if len(query["abc_list"]) == 3: a, b, c = sorted(query["abc_list"]) query["a_s"] = a query["b_s"] = b query["c_s"] = c elif len(query["abc_list"]) == 2: a, b = sorted(query["abc_list"]) sub_query = [] sub_query.append({"a_s": a, "b_s": b}) sub_query.append({"b_s": a, "c_s": b}) query["$or"] = sub_query elif len(query["abc_list"]) == 1: a = query["abc_list"][0] query["$or"] = [{"a_s": a}, {"b_s": a}, {"c_s": a}] query.pop("abc_list") # a naive hack if info.get("abc"): for elt in ["a_s", "b_s", "c_s"]: info_hack = {} info_hack[elt] = info["abc"] parse_ints(info_hack, query, elt) parse_ints(info, query, "g", "g") parse_ints(info, query, "deg", "deg") parse_ints(info, query, "orbit_size", "orbit_size") parse_ints(info, query, "pass_size", "pass_size") parse_nf_string(info, query, 'field', name="base number field", qfield='base_field_label') # invariants and drop-list items don't require parsing -- they are all strings (supplied by us, not the user) for fld in ["geomtype", "group"]: if info.get(fld): query[fld] = info[fld] parse_bool(info, query, "is_primitive", name="is_primitive") if info.get("primitivization"): primitivization = info["primitivization"] if re.match(GALMAP_RE, primitivization): # 7T6-7_4.2.1_4.2.1-b query["primitivization"] = primitivization else: raise ValueError("%s is not a valid Belyi map label", primitivization)
def number_field_search(info, query): parse_ints(info, query, 'degree') parse_galgrp(info, query, qfield=('galois_label', 'degree')) parse_bracketed_posints(info, query, 'signature', qfield=('degree', 'r2'), exactlength=2, allow0=True, extractor=lambda L: (L[0] + 2 * L[1], L[1])) parse_signed_ints(info, query, 'discriminant', qfield=('disc_sign', 'disc_abs')) parse_floats(info, query, 'rd') parse_floats(info, query, 'regulator') parse_ints(info, query, 'class_number') parse_ints(info, query, 'num_ram') parse_bool(info, query, 'cm_field', qfield='cm') parse_bool(info, query, 'is_galois') parse_bracketed_posints(info, query, 'class_group', check_divisibility='increasing', process=int) parse_primes(info, query, 'ur_primes', name='Unramified primes', qfield='ramps', mode='exclude') parse_primes(info, query, 'ram_primes', name='Ramified primes', qfield='ramps', mode=info.get('ram_quantifier'), radical='disc_rad') parse_subfield(info, query, 'subfield', qfield='subfields', name='Intermediate field') parse_padicfields(info, query, 'completions', qfield='local_algs', name='$p$-adic completions') info['wnf'] = WebNumberField.from_data info['gg_display'] = group_pretty_and_nTj
def belyi_search(info, query): info["geometry_types_list"] = geometry_types_list info["geometry_types_dict"] = geometry_types_dict info["belyi_galmap_url"] = url_for_belyi_galmap_label if "group" in query: info["group"] = query["group"] parse_bracketed_posints(info, query, "abc_list", "a, b, c", maxlength=3) if query.get("abc_list"): if len(query["abc_list"]) == 3: a, b, c = sorted(query["abc_list"]) query["a_s"] = a query["b_s"] = b query["c_s"] = c elif len(query["abc_list"]) == 2: a, b = sorted(query["abc_list"]) sub_query = [] sub_query.append({"a_s": a, "b_s": b}) sub_query.append({"b_s": a, "c_s": b}) query["$or"] = sub_query elif len(query["abc_list"]) == 1: a = query["abc_list"][0] query["$or"] = [{"a_s": a}, {"b_s": a}, {"c_s": a}] query.pop("abc_list") # a naive hack if info.get("abc"): for elt in ["a_s", "b_s", "c_s"]: info_hack = {} info_hack[elt] = info["abc"] parse_ints(info_hack, query, elt) parse_ints(info, query, "g", "g") parse_ints(info, query, "deg", "deg") parse_ints(info, query, "orbit_size", "orbit_size") parse_ints(info, query, "pass_size", "pass_size") parse_nf_string(info, query, 'field', name="base number field", qfield='base_field_label') # invariants and drop-list items don't require parsing -- they are all strings (supplied by us, not the user) for fld in ["geomtype", "group"]: if info.get(fld): query[fld] = info[fld] info["nf_link"] = lambda elt: field_display_gen( elt.get('base_field_label'), elt.get('base_field'), truncate=16) parse_bool(info, query, "is_primitive", name="is_primitive")
def elliptic_curve_search(info, query): parse_nf_string(info,query,'field',name="base number field",qfield='field_label') if query.get('field_label') == '1.1.1.1': return redirect(url_for("ec.rational_elliptic_curves", **request.args), 301) parse_ints(info,query,'conductor_norm') parse_noop(info,query,'conductor_label') parse_ints(info,query,'torsion',name='Torsion order',qfield='torsion_order') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2) if 'torsion_structure' in query and not 'torsion_order' in query: query['torsion_order'] = reduce(mul,[int(n) for n in query['torsion_structure']],1) parse_ints(info,query,field='isodeg',qfield='isogeny_degrees') if 'jinv' in info: if info.get('field','').strip() == '2.2.5.1': info['jinv'] = info['jinv'].replace('phi','a') if info.get('field','').strip() == '2.0.4.1': info['jinv'] = info['jinv'].replace('i','a') parse_nf_elt(info,query,'jinv',name='j-invariant') if query.get('jinv'): query['jinv'] =','.join(query['jinv']) if 'include_isogenous' in info and info['include_isogenous'] == 'off': info['number'] = 1 query['number'] = 1 if 'include_base_change' in info: if info['include_base_change'] == 'off': query['base_change'] = [] if info['include_base_change'] == 'only': query['base_change'] = {'$ne':[]} else: info['include_base_change'] = "on" if 'include_Q_curves' in info: if info['include_Q_curves'] == 'exclude': query['q_curve'] = False elif info['include_Q_curves'] == 'only': query['q_curve'] = True if 'include_cm' in info: if info['include_cm'] == 'exclude': query['cm'] = 0 elif info['include_cm'] == 'only': query['cm'] = {'$ne' : 0} info['field_pretty'] = field_pretty info['web_ainvs'] = web_ainvs
def elliptic_curve_search(info, query): parse_rational_to_list(info,query,'jinv','j-invariant') parse_ints(info,query,'conductor') parse_ints(info,query,'torsion','torsion order') parse_ints(info,query,'rank') parse_ints(info,query,'sha','analytic order of Ш') parse_ints(info,query,'num_int_pts','num_int_pts') parse_ints(info,query,'class_size','class_size') parse_ints(info,query,'class_deg','class_deg') parse_floats(info,query,'regulator','regulator') parse_bool(info,query,'semistable','semistable') parse_bool(info,query,'potential_good_reduction','potential_good_reduction') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2,check_divisibility='increasing') # speed up slow torsion_structure searches by also setting torsion #if 'torsion_structure' in query and not 'torsion' in query: # query['torsion'] = reduce(mul,[int(n) for n in query['torsion_structure']],1) if 'include_cm' in info: if info['include_cm'] == 'exclude': query['cm'] = 0 elif info['include_cm'] == 'only': query['cm'] = {'$ne' : 0} parse_ints(info,query,field='cm_disc',qfield='cm') parse_element_of(info,query,'isogeny_degrees',split_interval=1000,contained_in=get_stats().isogeny_degrees) parse_primes(info, query, 'surj_primes', name='maximal primes', qfield='nonmax_primes', mode='exclude') parse_primes(info, query, 'nonsurj_primes', name='non-maximal primes', qfield='nonmax_primes',mode=info.get('surj_quantifier'), radical='nonmax_rad') parse_primes(info, query, 'bad_primes', name='bad primes', qfield='bad_primes',mode=info.get('bad_quantifier')) parse_primes(info, query, 'sha_primes', name='sha primes', qfield='sha_primes',mode=info.get('sha_quantifier')) # The button which used to be labelled Optimal only no/yes" # (default: no) has been renamed "Curves per isogeny class # all/one" (default: all). When this option is "one" we only list # one curve in each class, currently choosing the curve with # minimal Faltings heights, which is conjecturally the # Gamma_1(N)-optimal curve. if 'optimal' in info and info['optimal'] == 'on': query.update({'lmfdb_number':1}) info['curve_ainvs'] = lambda dbc: str([ZZ(ai) for ai in dbc['ainvs']]) info['curve_url_LMFDB'] = 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_LMFDB'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1]) info['cremona_bound'] = CREMONA_BOUND info['curve_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['Clabel']) info['iso_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['Ciso'])
def genus2_curve_search(info, query): info["st_group_list"] = st_group_list info["st_group_dict"] = st_group_dict info["real_geom_end_alg_list"] = real_geom_end_alg_list info["real_geom_end_alg_to_ST0_dict"] = real_geom_end_alg_to_ST0_dict info["aut_grp_list"] = aut_grp_list info["aut_grp_dict"] = aut_grp_dict info["geom_aut_grp_list"] = geom_aut_grp_list info["geom_aut_grp_dict"] = geom_aut_grp_dict info["geom_end_alg_list"] = geom_end_alg_list info["geom_end_alg_dict"] = geom_end_alg_dict parse_ints(info, query, 'abs_disc', 'absolute discriminant') parse_bool(info, query, 'is_gl2_type', 'is of GL2-type') parse_bool(info, query, 'has_square_sha', 'has square Sha') parse_bool(info, query, 'locally_solvable', 'is locally solvable') parse_bool(info, query, 'is_simple_geom', 'is geometrically simple') parse_ints(info, query, 'cond', 'conductor') parse_ints(info, query, 'num_rat_pts', 'rational points') parse_ints(info, query, 'num_rat_wpts', 'rational Weierstrass points') parse_bracketed_posints(info, query, 'torsion', 'torsion structure', maxlength=4, check_divisibility="increasing") parse_ints(info, query, 'torsion_order', 'torsion order') if 'torsion' in query and not 'torsion_order' in query: query['torsion_order'] = reduce(mul, [int(n) for n in query['torsion']], 1) if 'torsion' in query: query['torsion_subgroup'] = str(query['torsion']).replace(" ", "") query.pop('torsion') # search using string key, not array of ints parse_ints(info, query, 'two_selmer_rank', '2-Selmer rank') parse_ints(info, query, 'analytic_rank', 'analytic rank') # G2 invariants and drop-list items don't require parsing -- they are all strings (supplied by us, not the user) if 'g20' in info and 'g21' in info and 'g22' in info: query['g2_inv'] = "['%s','%s','%s']" % (info['g20'], info['g21'], info['g22']) if 'class' in info: query['class'] = info['class'] for fld in ('st_group', 'real_geom_end_alg', 'aut_grp_id', 'geom_aut_grp_id', 'geom_end_alg'): if info.get(fld): query[fld] = info[fld] info["curve_url"] = lambda label: url_for_curve_label(label) info["class_url"] = lambda label: url_for_isogeny_class_label(label)
def belyi_search(info, query): info['geometry_types_list'] = geometry_types_list info['geometry_types_dict'] = geometry_types_dict info["belyi_galmap_url"] = lambda label: url_for_belyi_galmap_label(label) if 'group' in query: info['group'] = query['group'] parse_bracketed_posints(info, query, 'abc_list', 'a, b, c', maxlength=3) if query.get('abc_list'): if len(query['abc_list']) == 3: a, b, c = sorted(query['abc_list']) query['a_s'] = a query['b_s'] = b query['c_s'] = c elif len(query['abc_list']) == 2: a, b = sorted(query['abc_list']) sub_query = [] sub_query.append({'a_s': a, 'b_s': b}) sub_query.append({'b_s': a, 'c_s': b}) query['$or'] = sub_query elif len(query['abc_list']) == 1: a = query['abc_list'][0] query['$or'] = [{'a_s': a}, {'b_s': a}, {'c_s': a}] query.pop('abc_list') # a naive hack if info.get('abc'): for elt in ['a_s', 'b_s', 'c_s']: info_hack = {} info_hack[elt] = info['abc'] parse_ints(info_hack, query, elt) parse_ints(info, query, 'g', 'g') parse_ints(info, query, 'deg', 'deg') parse_ints(info, query, 'orbit_size', 'orbit_size') # invariants and drop-list items don't require parsing -- they are all strings (supplied by us, not the user) for fld in ['geomtype', 'group']: if info.get(fld): query[fld] = info[fld]
def belyi_search(info, query): info["geometry_types_list"] = geometry_types_list info["geometry_types_dict"] = geometry_types_dict info["belyi_galmap_url"] = lambda label: url_for_belyi_galmap_label(label) if "group" in query: info["group"] = query["group"] parse_bracketed_posints(info, query, "abc_list", "a, b, c", maxlength=3) if query.get("abc_list"): if len(query["abc_list"]) == 3: a, b, c = sorted(query["abc_list"]) query["a_s"] = a query["b_s"] = b query["c_s"] = c elif len(query["abc_list"]) == 2: a, b = sorted(query["abc_list"]) sub_query = [] sub_query.append({"a_s": a, "b_s": b}) sub_query.append({"b_s": a, "c_s": b}) query["$or"] = sub_query elif len(query["abc_list"]) == 1: a = query["abc_list"][0] query["$or"] = [{"a_s": a}, {"b_s": a}, {"c_s": a}] query.pop("abc_list") # a naive hack if info.get("abc"): for elt in ["a_s", "b_s", "c_s"]: info_hack = {} info_hack[elt] = info["abc"] parse_ints(info_hack, query, elt) parse_ints(info, query, "g", "g") parse_ints(info, query, "deg", "deg") parse_ints(info, query, "orbit_size", "orbit_size") # invariants and drop-list items don't require parsing -- they are all strings (supplied by us, not the user) for fld in ["geomtype", "group"]: if info.get(fld): query[fld] = info[fld]
def belyi_search(info, query): info['geometry_types_list'] = geometry_types_list info['geometry_types_dict'] = geometry_types_dict info["belyi_galmap_url"] = lambda label: url_for_belyi_galmap_label(label) if 'group' in query: info['group'] = query['group'] parse_bracketed_posints(info, query, 'abc_list', 'a, b, c', maxlength=3) if query.get('abc_list'): if len(query['abc_list']) == 3: a, b, c = sorted(query['abc_list']) query['a_s'] = a query['b_s'] = b query['c_s'] = c elif len(query['abc_list']) == 2: a, b = sorted(query['abc_list']) sub_query = [] sub_query.append( {'a_s': a, 'b_s': b} ) sub_query.append( {'b_s': a, 'c_s': b} ) query['$or'] = sub_query elif len(query['abc_list']) == 1: a = query['abc_list'][0] query['$or'] = [{'a_s': a}, {'b_s': a}, {'c_s': a}] query.pop('abc_list') # a naive hack if info.get('abc'): for elt in ['a_s', 'b_s', 'c_s']: info_hack = {} info_hack[elt] = info['abc'] parse_ints(info_hack, query, elt) parse_ints(info, query, 'g','g') parse_ints(info, query, 'deg', 'deg') parse_ints(info, query, 'orbit_size', 'orbit_size') # invariants and drop-list items don't require parsing -- they are all strings (supplied by us, not the user) for fld in ['geomtype','group']: if info.get(fld): query[fld] = info[fld]
def hgm_search(info, query): family_search = False if info.get('Submit Family') or info.get('family'): family_search = True query['__title__'] = r'Hypergeometric Family over $\Q$ Search Result' query[ '__err_title__'] = r'Hypergeometric Family over $\Q$ Search Input Error' query['__table__'] = db.hgm_families queryab = {} for param in [ 'A', 'B', 'A2', 'B2', 'A3', 'B3', 'A5', 'B5', 'A7', 'B7', 'Au2', 'Bu2', 'Au3', 'Bu3', 'Au5', 'Bu5', 'Au7', 'Bu7' ]: parse_bracketed_posints(info, queryab, param, split=False, listprocess=lambda a: sorted(a, reverse=True)) # Combine the parts of the query if there are A,B parts if queryab: queryabrev = {} for k in queryab.keys(): queryabrev[k + 'rev'] = queryab[k] query['$or'] = [queryab, queryabrev] # generic, irreducible not in DB yet parse_ints(info, query, 'degree') parse_ints(info, query, 'weight') parse_bracketed_posints(info, query, 'famhodge', 'family Hodge vector', split=False) parse_restricted(info, query, 'sign', allowed=['+1', 1, -1], process=int) # Make a version to search reversed way if not family_search: parse_ints(info, query, 'conductor', 'Conductor', 'cond') parse_rational(info, query, 't') parse_bracketed_posints(info, query, 'hodge', 'Hodge vector') 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
def hgm_search(info, query): family_search = False if info.get('Submit Family') or info.get('family'): family_search = True query['__title__'] = r'Hypergeometric Family over $\Q$ Search Result' query['__err_title__'] = r'Hypergeometric Family over $\Q$ Search Input Error' query['__table__'] = db.hgm_families queryab = {} for param in ['A', 'B', 'A2', 'B2', 'A3', 'B3', 'A5', 'B5', 'A7', 'B7', 'Au2', 'Bu2', 'Au3', 'Bu3', 'Au5', 'Bu5', 'Au7', 'Bu7']: parse_bracketed_posints(info, queryab, param, split=False, listprocess=lambda a: sorted(a, reverse=True)) # Combine the parts of the query if there are A,B parts if queryab: queryabrev = {} for k in queryab.keys(): queryabrev[k+'rev'] = queryab[k] query['$or'] = [queryab, queryabrev] # generic, irreducible not in DB yet parse_ints(info, query, 'degree') parse_ints(info, query, 'weight') parse_bracketed_posints(info, query, 'famhodge', 'family Hodge vector',split=False) parse_restricted(info, query, 'sign', allowed=['+1',1,-1], process=int) # Make a version to search reversed way if not family_search: parse_ints(info, query, 'conductor', 'Conductor' , 'cond') parse_rational(info, query, 't') parse_bracketed_posints(info, query, 'hodge', 'Hodge vector') 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
def hgm_search(info, query): info["search_type"] = search_type = info.get("search_type", info.get("hst", "Motive")) if search_type in ["Family", "RandomFamily"]: query['__title__'] = r'Hypergeometric family over $\Q$ search result' query[ '__err_title__'] = r'Hypergeometric family over $\Q$ search input error' query['__table__'] = db.hgm_families queryab = {} p = info.get('p', '2') for param in ['A', 'B']: parse_bracketed_posints(info, queryab, param, split=True, keepbrackets=True, listprocess=lambda a: sorted(a, reverse=True)) parse_bracketed_posints(info, queryab, 'Ap', qfield='A' + p, split=True, keepbrackets=True, listprocess=lambda a: sorted(a, reverse=True)) parse_bracketed_posints(info, queryab, 'Bp', qfield='B' + p, split=True, keepbrackets=True, listprocess=lambda a: sorted(a, reverse=True)) parse_bracketed_posints(info, queryab, 'Apperp', qfield='Au' + p, split=True, keepbrackets=True, listprocess=lambda a: sorted(a, reverse=True)) parse_bracketed_posints(info, queryab, 'Bpperp', qfield='Bu' + p, split=True, keepbrackets=True, listprocess=lambda a: sorted(a, reverse=True)) # Combine the parts of the query if there are A,B parts if queryab: queryabrev = {} for k in queryab.keys(): queryabrev[k + 'rev'] = queryab[k] query['$or'] = [queryab, queryabrev] # generic, irreducible not in DB yet parse_ints(info, query, 'degree') parse_ints(info, query, 'weight') parse_bracketed_posints(info, query, 'famhodge', 'family Hodge vector', split=True) parse_restricted(info, query, 'sign', allowed=['+1', 1, -1], process=int) # Make a version to search reversed way if search_type not in ["Family", "RandomFamily"]: parse_ints(info, query, 'conductor', 'Conductor', 'cond') parse_rational(info, query, 't') parse_bracketed_posints(info, query, 'hodge', 'Hodge vector') query['__sort__'] = ['degree', 'weight', 'A', 'B', 'label'] # Should search on analytic conductor when available # Sorts A and B first by length, then by the elements of the list; could go another way info['make_label'] = make_abt_label info['make_t_label'] = make_t_label info['ab_label'] = ab_label info['display_t'] = display_t info['factorint'] = factorint
def genus2_curve_search(info, query): parse_ints(info, query, 'abs_disc', 'absolute discriminant') parse_bool(info, query, 'is_gl2_type', 'is of GL2-type') parse_bool(info, query, 'has_square_sha', 'has square Sha') parse_bool(info, query, 'locally_solvable', 'is locally solvable') parse_bool(info, query, 'is_simple_geom', 'is geometrically simple') parse_ints(info, query, 'cond', 'conductor') if info.get('analytic_sha') == "None": query['analytic_sha'] = None else: parse_ints(info, query, 'analytic_sha', 'analytic order of sha') parse_ints(info, query, 'num_rat_pts', 'rational points') parse_ints(info, query, 'num_rat_wpts', 'rational Weierstrass points') parse_bracketed_posints(info, query, 'torsion', 'torsion structure', maxlength=4, check_divisibility="increasing") parse_ints(info, query, 'torsion_order', 'torsion order') if 'torsion' in query and not 'torsion_order' in query: t_o = 1 for n in query['torsion']: t_o *= int(n) query['torsion_order'] = t_o if 'torsion' in query: query['torsion_subgroup'] = str(query['torsion']).replace(" ", "") query.pop('torsion') # search using string key, not array of ints geom_inv_type = info.get('geometric_invariants_type', 'igusa_clebsch_inv') if geom_inv_type == 'igusa_clebsch_inv': invlength = 4 elif geom_inv_type == 'igusa_inv': invlength = 5 else: invlength = 3 parse_bracketed_rats(info, query, 'geometric_invariants', qfield=geom_inv_type, exactlength=invlength, split=False, keepbrackets=True) parse_ints(info, query, 'two_selmer_rank', '2-Selmer rank') parse_ints(info, query, 'analytic_rank', 'analytic rank') # G2 invariants and drop-list items don't require parsing -- they are all strings (supplied by us, not the user) if 'g20' in info and 'g21' in info and 'g22' in info: query['g2_inv'] = "['%s','%s','%s']" % (info['g20'], info['g21'], info['g22']) if 'class' in info: query['class'] = info['class'] for fld in ('st_group', 'real_geom_end_alg', 'aut_grp_id', 'geom_aut_grp_id', 'end_alg', 'geom_end_alg'): if info.get(fld): query[fld] = info[fld] parse_primes(info, query, 'bad_primes', name='bad primes', qfield='bad_primes', mode=info.get('bad_quantifier')) info["curve_url"] = lambda label: url_for_curve_label(label) info["class_url"] = lambda label: url_for_isogeny_class_label(label)
def elliptic_curve_search(info, query): parse_nf_string(info, query, 'field', name="base number field", qfield='field_label') if query.get('field_label') == '1.1.1.1': return redirect(url_for("ec.rational_elliptic_curves", **request.args), 301) parse_ints(info, query, 'conductor_norm') parse_noop(info, query, 'conductor_label') parse_ints(info, query, 'rank') parse_ints(info, query, 'torsion', name='Torsion order', qfield='torsion_order') parse_bracketed_posints(info, query, 'torsion_structure', maxlength=2) if 'torsion_structure' in query and 'torsion_order' not in query: t_o = 1 for n in query['torsion_structure']: t_o *= int(n) query['torsion_order'] = t_o parse_element_of(info, query, 'isodeg', split_interval=1000, contained_in=ECNF_stats().isogeny_degrees) parse_bool(info, query, 'semistable', 'semistable') parse_bool(info, query, 'potential_good_reduction', 'potential_good_reduction') parse_ints(info, query, 'class_size', 'class_size') parse_ints(info, query, 'class_deg', 'class_deg') parse_ints(info, query, 'sha', 'analytic order of Ш') parse_floats(info, query, 'reg', 'regulator') parse_nf_jinv(info, query, 'jinv', 'j-invariant', field_label=query.get('field_label')) if info.get('one') == "yes": info['number'] = 1 query['number'] = 1 if 'include_base_change' in info: if info['include_base_change'] in [ 'exclude', 'off' ]: # off for backward compat with urls query['base_change'] = [] if info['include_base_change'] == 'only': query['base_change'] = {'$ne': []} else: info['include_base_change'] = "on" if 'include_Q_curves' in info: if info['include_Q_curves'] == 'exclude': query['q_curve'] = False elif info['include_Q_curves'] == 'only': query['q_curve'] = True parse_cm_list(info, query, field='cm_disc', qfield='cm', name="CM discriminant") if 'include_cm' in info: if info['include_cm'] == 'PCM': tmp = {'$ne': 0} if 'cm' in query: query['cm'] = {'$and': [tmp, query['cm']]} else: query['cm'] = tmp elif info['include_cm'] == 'PCMnoCM': tmp = {'$lt': 0} if 'cm' in query: query['cm'] = {'$and': [tmp, query['cm']]} else: query['cm'] = tmp elif info['include_cm'] == 'CM': tmp = {'$gt': 0} if 'cm' in query: query['cm'] = {'$and': [tmp, query['cm']]} else: query['cm'] = tmp elif info['include_cm'] == 'noPCM': tmp = 0 if 'cm' in query: query['cm'] = {'$and': [tmp, query['cm']]} else: query['cm'] = tmp parse_primes(info, query, 'conductor_norm_factors', name='bad primes', qfield='conductor_norm_factors', mode=info.get('bad_quantifier')) info['field_pretty'] = field_pretty parse_ints(info, query, 'bf_deg', name='Base field degree', qfield='degree')
def elliptic_curve_search(info, query): parse_nf_string(info,query,'field',name="base number field",qfield='field_label') if query.get('field_label') == '1.1.1.1': return redirect(url_for("ec.rational_elliptic_curves", **request.args), 301) parse_ints(info,query,'conductor_norm') parse_noop(info,query,'conductor_label') parse_ints(info,query,'rank') parse_ints(info,query,'torsion',name='Torsion order',qfield='torsion_order') parse_bracketed_posints(info,query,'torsion_structure',maxlength=2) if 'torsion_structure' in query and not 'torsion_order' in query: t_o = 1 for n in query['torsion_structure']: t_o *= int(n) query['torsion_order'] = t_o parse_element_of(info,query,'isodeg',split_interval=1000,contained_in=ECNF_stats().isogeny_degrees) parse_bool(info,query,'semistable','semistable') parse_bool(info,query,'potential_good_reduction','potential_good_reduction') parse_ints(info,query,'class_size','class_size') parse_ints(info,query,'class_deg','class_deg') parse_ints(info,query,'sha','analytic order of Ш') parse_floats(info,query,'reg','regulator') if 'jinv' in info: if info.get('field','').strip() == '2.2.5.1': info['jinv'] = info['jinv'].replace('phi','a') if info.get('field','').strip() == '2.0.4.1': info['jinv'] = info['jinv'].replace('i','a') if not 'a' in info['jinv'] and not info.get('field'): # rational j-invariant allowed for any field parse_rational(info, query, 'jinv', name='j-invariant') if query.get('jinv'): query['jinv'] = {'$regex': '^' + query['jinv'] + '(,0)*$'} # nf elements like j,0,0,0 else: # j-invariant is a number field element parse_nf_elt(info, query, 'jinv', name='j-invariant') if query.get('jinv'): query['jinv'] = ','.join(query['jinv']) if info.get('one') == "yes": info['number'] = 1 query['number'] = 1 if 'include_base_change' in info: if info['include_base_change'] in ['exclude', 'off']: # off for backward compat with urls query['base_change'] = [] if info['include_base_change'] == 'only': query['base_change'] = {'$ne':[]} else: info['include_base_change'] = "on" if 'include_Q_curves' in info: if info['include_Q_curves'] == 'exclude': query['q_curve'] = False elif info['include_Q_curves'] == 'only': query['q_curve'] = True if 'include_cm' in info: if info['include_cm'] == 'PCM': query['cm'] = {'$ne' : 0} elif info['include_cm'] == 'PCMnoCM': query['cm'] = {'$lt' : 0} elif info['include_cm'] == 'CM': query['cm'] = {'$gt' : 0} elif info['include_cm'] == 'noPCM': query['cm'] = 0 parse_ints(info,query,field='cm_disc',qfield='cm') parse_primes(info, query, 'conductor_norm_factors', name='bad primes', qfield='conductor_norm_factors',mode=info.get('bad_quantifier')) info['field_pretty'] = field_pretty info['web_ainvs'] = web_ainvs parse_ints(info,query,'bf_deg',name='Base field degree',qfield='degree')
def elliptic_curve_search(info, query): parse_rational_to_list(info, query, 'jinv', 'j-invariant') parse_ints(info, query, 'conductor') if info.get('conductor_type'): if info['conductor_type'] == 'prime': query['num_bad_primes'] = 1 query['semistable'] = True elif info['conductor_type'] == 'prime_power': query['num_bad_primes'] = 1 elif info['conductor_type'] == 'squarefree': query['semistable'] = True elif info['conductor_type'] == 'divides': if not isinstance(query.get('conductor'), int): err = "You must specify a single conductor" flash_error(err) raise ValueError(err) else: query['conductor'] = {'$in': integer_divisors(ZZ(query['conductor']))} parse_signed_ints(info, query, 'discriminant', qfield=('signD', 'absD')) parse_ints(info,query,'rank') parse_ints(info,query,'sha','analytic order of Ш') parse_ints(info,query,'num_int_pts','num_int_pts') parse_ints(info,query,'class_size','class_size') if info.get('class_deg'): parse_ints(info,query,'class_deg','class_deg') if not isinstance(query.get('class_deg'), int): err = "You must specify a single isogeny class degree" flash_error(err) raise ValueError(err) parse_floats(info,query,'regulator','regulator') parse_floats(info, query, 'faltings_height', 'faltings_height') if info.get('reduction'): if info['reduction'] == 'semistable': query['semistable'] = True elif info['reduction'] == 'not semistable': query['semistable'] = False elif info['reduction'] == 'potentially good': query['potential_good_reduction'] = True elif info['reduction'] == 'not potentially good': query['potential_good_reduction'] = False if info.get('torsion'): if info['torsion'][0] == '[': parse_bracketed_posints(info,query,'torsion',qfield='torsion_structure',maxlength=2,check_divisibility='increasing') else: parse_ints(info,query,'torsion') # speed up slow torsion_structure searches by also setting torsion #if 'torsion_structure' in query and not 'torsion' in query: # query['torsion'] = reduce(mul,[int(n) for n in query['torsion_structure']],1) if 'cm' in info: if info['cm'] == 'noCM': query['cm'] = 0 elif info['cm'] == 'CM': query['cm'] = {'$ne' : 0} else: parse_ints(info,query,field='cm',qfield='cm') parse_element_of(info,query,'isogeny_degrees',split_interval=200,contained_in=get_stats().isogeny_degrees) parse_primes(info, query, 'nonmax_primes', name='non-maximal primes', qfield='nonmax_primes', mode=info.get('nonmax_quantifier'), radical='nonmax_rad') parse_primes(info, query, 'bad_primes', name='bad primes', qfield='bad_primes',mode=info.get('bad_quantifier')) parse_primes(info, query, 'sha_primes', name='sha primes', qfield='sha_primes',mode=info.get('sha_quantifier')) if info.get('galois_image'): labels = [a.strip() for a in info['galois_image'].split(',')] elladic_labels = [a for a in labels if elladic_image_label_regex.fullmatch(a) and is_prime_power(elladic_image_label_regex.match(a)[1])] modell_labels = [a for a in labels if modell_image_label_regex.fullmatch(a) and is_prime(modell_image_label_regex.match(a)[1])] if len(elladic_labels)+len(modell_labels) != len(labels): err = "Unrecognized Galois image label, it should be the label of a subgroup of GL(2,Z_ell), such as %s, or the label of a subgroup of GL(2,F_ell), such as %s, or a list of such labels" flash_error(err, "13.91.3.2", "13S4") raise ValueError(err) if elladic_labels: query['elladic_images'] = {'$contains': elladic_labels} if modell_labels: query['modell_images'] = {'$contains': modell_labels} if 'cm' not in query: query['cm'] = 0 info['cm'] = "noCM" if query['cm']: # try to help the user out if they specify the normalizer of a Cartan in the CM case (these are either maximal or impossible if any(a.endswith("Nn") for a in modell_labels) or any(a.endswith("Ns") for a in modell_labels): err = "To search for maximal images, exclude non-maximal primes" flash_error(err) raise ValueError(err) else: # if the user specifies full mod-ell image with ell > 3, automatically exclude nonmax primes (if possible) max_labels = [a for a in modell_labels if a.endswith("G") and int(modell_image_label_regex.match(a)[1]) > 3] if max_labels: if info.get('nonmax_primes') and info['nonmax_quantifier'] != 'exclude': err = "To search for maximal images, exclude non-maximal primes" flash_error(err) raise ValueError(err) else: modell_labels = [a for a in modell_labels if a not in max_labels] max_primes = [modell_image_label_regex.match(a)[1] for a in max_labels] if info.get('nonmax_primes'): max_primes += [l.strip() for l in info['nonmax_primes'].split(',') if not l.strip() in max_primes] max_primes.sort(key=int) info['nonmax_primes'] = ','.join(max_primes) info['nonmax_quantifier'] = 'exclude' parse_primes(info, query, 'nonmax_primes', name='non-maximal primes', qfield='nonmax_primes', mode=info.get('nonmax_quantifier'), radical='nonmax_rad') info['galois_image'] = ','.join(modell_labels + elladic_labels) query['modell_images'] = { '$contains': modell_labels } # The button which used to be labelled Optimal only no/yes" # (default: no) has been renamed "Curves per isogeny class # all/one" (default: all). When this option is "one" we only list # one curve in each class, currently choosing the curve with # minimal Faltings heights, which is conjecturally the # Gamma_1(N)-optimal curve. if 'optimal' in info and info['optimal'] == 'on': query["__one_per__"] = "lmfdb_iso" info['curve_ainvs'] = lambda dbc: str([ZZ(ai) for ai in dbc['ainvs']]) info['curve_url_LMFDB'] = 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_LMFDB'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label(dbc['lmfdb_iso'])[1]) info['cremona_bound'] = CREMONA_BOUND info['curve_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['Clabel']) info['iso_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['Ciso']) info['FH'] = lambda dbc: RealField(20)(dbc['faltings_height'])
def genus2_curve_search(info, query): parse_ints(info, query, "abs_disc", "absolute discriminant") parse_bool(info, query, "is_gl2_type", "is of GL2-type") parse_bool(info, query, "has_square_sha", "has square Sha") parse_bool(info, query, "locally_solvable", "is locally solvable") parse_bool(info, query, "is_simple_geom", "is geometrically simple") parse_ints(info, query, "cond", "conductor") if info.get("analytic_sha") == "None": query["analytic_sha"] = None else: parse_ints(info, query, "analytic_sha", "analytic order of sha") parse_ints(info, query, "num_rat_pts", "rational points") parse_ints(info, query, "num_rat_wpts", "rational Weierstrass points") parse_bracketed_posints( info, query, "torsion", "torsion structure", maxlength=4, check_divisibility="increasing", ) parse_ints(info, query, "torsion_order", "torsion order") if "torsion" in query and "torsion_order" not in query: t_o = 1 for n in query["torsion"]: t_o *= int(n) query["torsion_order"] = t_o if "torsion" in query: query["torsion_subgroup"] = str(query["torsion"]).replace(" ", "") query.pop("torsion") # search using string key, not array of ints parse_bracketed_rats( info, query, "geometric_invariants", qfield="g2_inv", minlength=3, maxlength=5, listprocess=geom_inv_to_G2, split=False, keepbrackets=True, ) parse_ints(info, query, "two_selmer_rank", "2-Selmer rank") parse_ints(info, query, "analytic_rank", "analytic rank") # G2 invariants and drop-list items don't require parsing -- they are all strings (supplied by us, not the user) if "g20" in info and "g21" in info and "g22" in info: query["g2_inv"] = "['%s','%s','%s']" % (info["g20"], info["g21"], info["g22"]) if "class" in info: query["class"] = info["class"] # Support legacy aut_grp_id if info.get("aut_grp_id"): info["aut_grp_label"] = ".".join( info.pop("aut_grp_id")[1:-1].split(",")) if info.get("geom_aut_grp_id"): info["geom_aut_grp_label"] = ".".join( info.pop("geom_aut_grp_id")[1:-1].split(",")) for fld in ( "st_group", "real_geom_end_alg", "aut_grp_label", "geom_aut_grp_label", "end_alg", "geom_end_alg", ): if info.get(fld): query[fld] = info[fld] parse_primes( info, query, "bad_primes", name="bad primes", qfield="bad_primes", mode=info.get("bad_quantifier"), ) parse_sort(info, query)
def elliptic_curve_search(info, query): parse_rational(info, query, 'jinv', 'j-invariant') parse_ints(info, query, 'conductor') parse_ints(info, query, 'torsion', 'torsion order') parse_ints(info, query, 'rank') parse_ints(info, query, 'sha', 'analytic order of Ш') parse_bracketed_posints(info, query, 'torsion_structure', maxlength=2, check_divisibility='increasing') # speed up slow torsion_structure searches by also setting torsion #if 'torsion_structure' in query and not 'torsion' in query: # query['torsion'] = reduce(mul,[int(n) for n in query['torsion_structure']],1) if 'include_cm' in info: if info['include_cm'] == 'exclude': query['cm'] = 0 elif info['include_cm'] == 'only': query['cm'] = {'$ne': 0} parse_element_of(info, query, field='isodeg', qfield='isogeny_degrees', split_interval=1000) #parse_ints(info,query,field='isodeg',qfield='isogeny_degrees') parse_primes(info, query, 'surj_primes', name='maximal primes', qfield='nonmax_primes', mode='complement') if info.get('surj_quantifier') == 'exactly': mode = 'exact' else: mode = 'append' parse_primes(info, query, 'nonsurj_primes', name='non-maximal primes', qfield='nonmax_primes', mode=mode, radical='nonmax_rad') if 'optimal' in info and info['optimal'] == 'on': # For all isogeny classes except 990h the optimal curve is number 1, while for class 990h it is number 3. # So setting query['number'] = 1 is nearly correct, but fails on 990h3. # Instead, we use this more complicated query: query.update({ "$or": [{ 'iso': '990h', 'number': 3 }, { 'iso': { '$ne': '990h' }, 'number': 1 }] }) info['curve_url_LMFDB'] = 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_LMFDB'] = lambda dbc: url_for(".by_double_iso_label", conductor=dbc['conductor'], iso_label=split_lmfdb_label( dbc['lmfdb_iso'])[1]) info['curve_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['label']) info['iso_url_Cremona'] = lambda dbc: url_for(".by_ec_label", label=dbc['iso'])