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 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 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 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 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 search(info): """ query processing for Sato-Tate groups -- returns rendered results page """ if 'jump' in info: return redirect(url_for('.by_label', label=info['jump']), 301) if 'label' in info: return redirect(url_for('.by_label', label=info['label']), 301) search_type = info.get("search_type", info.get("hst", "List")) template_kwds = { 'bread': [('Sato-Tate Groups', url_for('.index')), ('Search Results', '.')], 'credit': credit_string, 'learnmore': learnmore_list() } title = 'Sato-Tate Group Search Results' err_title = 'Sato-Tate Groups Search Input Error' count = parse_count(info, 50) start = parse_start(info) # if user clicked refine search always restart at 0 if 'refine' in info: start = 0 ratonly = (info.get('include_irrational', 'no').strip().lower() == 'no') if search_type == "Random" and not ratonly: info['err'] = err = 'Cannot select random irrational Sato-Tate group' flash_error(err) return render_template('st_results.html', info=info, title=err_title, **template_kwds) query = {'rational': True} if ratonly else {} try: parse_ints(info, query, 'weight', 'weight') if 'weight' in query: weight_list = parse_ints_to_list_flash(info.get('weight'), 'weight') parse_ints(info, query, 'degree', 'degree') if 'degree' in query: degree_list = parse_ints_to_list_flash(info.get('degree'), 'degree') if info.get('identity_component'): query['identity_component'] = info['identity_component'] parse_ints(info, query, 'components', 'components') if 'components' in query: components_list = parse_ints_to_list_flash(info.get('components'), 'components') parse_rational(info, query, 'trace_zero_density', 'trace zero density') except ValueError as err: info['err'] = str(err) return render_template('st_results.html', info=info, title=err_title, **template_kwds) # Check mu(n) groups first (these are not stored in the database) results = [] if ((not 'weight' in query or 0 in weight_list) and (not 'degree' in query or 1 in degree_list) and (not 'identity_component' in query or query['identity_component'] == 'SO(1)') and (not 'trace_zero_density' in query or query['trace_zero_density'] == '0')): if not 'components' in query: components_list = range(1, 3 if ratonly else start + count + 1) elif ratonly: components_list = [n for n in range(1, 3) if n in components_list] nres = len( components_list) if 'components' in query or ratonly else INFINITY if search_type == "Random" and nres > 0: # Need to return mu(1) and mu(2) sometimes otherlen = db.gps_sato_tate.count(query) r = ZZ.random_element(nres + otherlen) if r < nres: return redirect( url_for(".by_label", label="0.1.%d" % components_list[r]), 307) for n in itertools.islice(components_list, start, start + count): results.append(mu_info(n)) else: nres = 0 if 'result_count' in info: nres += db.gps_sato_tate.count(query) return jsonify({"nres": str(nres)}) if search_type == "Random": label = db.gps_sato_tate.random(query, "label") if label is not None: return redirect(url_for(".by_label", label=label), 307) # Now lookup other (rational) ST groups in database if nres != INFINITY: start2 = start - nres if start > nres else 0 proj = [ 'label', 'weight', 'degree', 'real_dimension', 'identity_component', 'name', 'pretty', 'components', 'component_group', 'trace_zero_density', 'moments' ] try: res = db.gps_sato_tate.search(query, proj, limit=max(count - len(results), 0), offset=start2, info=info) except QueryCanceledError as err: ctx = ctx_proc_userdata() flash_error( 'The search query took longer than expected! Please help us improve by reporting this error <a href="%s" target=_blank>here</a>.' % ctx['feedbackpage']) info['err'] = str(err) return render_template('st_results.html', info=info, title=err_title, **template_kwds) info['number'] += nres if start < info['number'] and len(results) < count: for v in res: v['identity_component'] = st0_pretty(v['identity_component']) v['component_group'] = sg_pretty(v['component_group']) v['trace_moments'] = trace_moments(v['moments']) results.append(v) else: info['number'] = 'infinity' info['start'] = start info['count'] = count info['st0_list'] = st0_list info['st0_dict'] = st0_dict info['results'] = results info['stgroup_url'] = lambda dbc: url_for('.by_label', label=dbc['label']) return render_template('st_results.html', info=info, title=title, **template_kwds)
def search(**args): """ query processing for Sato-Tate groups -- returns rendered results page """ info = to_dict(args) if 'jump' in info: return redirect(url_for('.by_label', label=info['jump']), 301) if 'label' in info: return redirect(url_for('.by_label', label=info['label']), 301) template_kwds = {'bread':[('Sato-Tate Groups', url_for('.index')),('Search Results', '.')], 'credit':credit_string, 'learnmore':learnmore_list()} title = 'Sato-Tate Group Search Results' err_title = 'Sato-Tate Groups Search Input Error' count = parse_count(info, 25) start = parse_start(info) # if user clicked refine search always restart at 0 if 'refine' in info: start = 0 ratonly = True if info.get('rational_only','no').strip().lower() == 'yes' else False query = {'rational':True} if ratonly else {} try: parse_ints(info,query,'weight','weight') if 'weight' in query: weight_list = parse_ints_to_list_flash(info.get('weight'),'weight') parse_ints(info,query,'degree','degree') if 'degree' in query: degree_list = parse_ints_to_list_flash(info.get('degree'),'degree') if info.get('identity_component'): query['identity_component'] = info['identity_component'] parse_ints(info,query,'components','components') if 'components' in query: components_list = parse_ints_to_list_flash(info.get('components'), 'components') parse_rational(info,query,'trace_zero_density','trace zero density') except ValueError as err: info['err'] = str(err) return render_template('st_results.html', info=info, title=err_title, **template_kwds) # Check mu(n) groups first (these are not stored in the database) results = [] if (not 'weight' in query or 0 in weight_list) and \ (not 'degree' in query or 1 in degree_list) and \ (not 'identity_component' in query or query['identity_component'] == 'SO(1)') and \ (not 'trace_zero_density' in query or query['trace_zero_density'] == '0'): if not 'components' in query: components_list = xrange(1,3 if ratonly else start+count+1) elif ratonly: components_list = [n for n in range(1,3) if n in components_list] nres = len(components_list) if 'components' in query or ratonly else INFINITY for n in itertools.islice(components_list,start,start+count): results.append(mu_info(n)) else: nres = 0 if 'result_count' in info: nres += db.gps_sato_tate.count(query) return jsonify({"nres":str(nres)}) # Now lookup other (rational) ST groups in database if nres != INFINITY: start2 = start - nres if start > nres else 0 proj = ['label','weight','degree','real_dimension','identity_component','name','pretty','components','component_group','trace_zero_density','moments'] try: res = db.gps_sato_tate.search(query, proj, limit=max(count - len(results), 0), offset=start2, info=info) except QueryCanceledError as err: ctx = ctx_proc_userdata() flash_error('The search query took longer than expected! Please help us improve by reporting this error <a href="%s" target=_blank>here</a>.' % ctx['feedbackpage']) info['err'] = str(err) return render_template('st_results.html', info=info, title=err_title, **template_kwds) info['number'] += nres if start < info['number'] and len(results) < count: for v in res: v['identity_component'] = st0_pretty(v['identity_component']) v['component_group'] = sg_pretty(v['component_group']) v['trace_moments'] = trace_moments(v['moments']) results.append(v) else: info['number'] = 'infinity' info['start'] = start info['count'] = count info['st0_list'] = st0_list info['st0_dict'] = st0_dict info['results'] = results info['stgroup_url'] = lambda dbc: url_for('.by_label', label=dbc['label']) return render_template('st_results.html', info=info, title=title, **template_kwds)
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 search(info): """ query processing for Sato-Tate groups -- returns rendered results page """ if 'jump' in info: return redirect(url_for('.by_label', label=info['jump']), 301) if 'label' in info: return redirect(url_for('.by_label', label=info['label']), 301) search_type = info.get("search_type", info.get("hst", "List")) template_kwds = { 'bread': get_bread("Search results"), 'credit': credit_string, 'learnmore': learnmore_list() } title = 'Sato-Tate group search results' err_title = 'Sato-Tate group search input error' count = parse_count(info, 50) start = parse_start(info) # if user clicked refine search always restart at 0 if 'refine' in info: start = 0 ratonly = (info.get('include_irrational', 'no').strip().lower() == 'no') if search_type == "Random" and not ratonly: info['err'] = err = 'Cannot select random irrational Sato-Tate group' flash_error(err) return render_template('st_results.html', info=info, title=err_title, **template_kwds) query = {'rational': True} if ratonly else {} try: parse_ints(info, query, 'weight', 'weight') if 'weight' in query: weight_list = parse_ints_to_list_flash(info.get('weight'), 'weight') parse_ints(info, query, 'degree', 'degree') if 'degree' in query: degree_list = parse_ints_to_list_flash(info.get('degree'), 'degree') if info.get('identity_component'): query['identity_component'] = info['identity_component'] parse_ints(info, query, 'components', 'components') def refine_components(current, condition): if current is None: return condition return [x for x in condition if x in current] # The following are used to constraint which mu(n) will show up in search results components_list = None ommitted = set() if 'components' in query: components_list = parse_ints_to_list_flash(info.get('components'), 'components') parse_component_group(info, query) gps = query.get("component_group") if gps: if isinstance(gps, dict): gps = gps["$in"] else: gps = [gps] if not ratonly: cyclic_labels = set( db.gps_small.search({"cyclic": True}, "label")) irrat = [] for code in gps: if code in cyclics: irrat.append(cyclics[code]) elif re.match(cyclicre, code): irrat.append(int(code[1:])) elif not ratonly and code in cyclic_labels: irrat.append(int(code.split(".")[0])) components_list = refine_components(components_list, irrat) parse_rational(info, query, 'trace_zero_density', 'trace zero density') parse_ints(info, query, 'second_trace_moment') parse_ints(info, query, 'fourth_trace_moment') for name, ones in [('second_trace_moment', [1, 2]), ('fourth_trace_moment', [1, 2, 4])]: if name in query: # E(x^2) for mu(1) and mu(2) are 1; others are 0 # E(x^4) for mu(1), mu(2) and mu(4) are 1; others are 0 E = parse_ints_to_list_flash(info.get(name), name.replace("_", " ")) if 0 not in E: components_list = refine_components(components_list, ones) if 1 not in E: ommitted.update(ones) parse_ints(info, query, 'first_a2_moment') parse_bool(info, query, 'maximal') if "first_a2_moment" in query or query.get("maximal"): # mu(n) do not have a2 moments and none are maximal components_list = [] except ValueError as err: info['err'] = str(err) return render_template('st_results.html', info=info, title=err_title, **template_kwds) # Check mu(n) groups first (these are not stored in the database) results = [] if ((not 'weight' in query or 0 in weight_list) and (not 'degree' in query or 1 in degree_list) and (not 'identity_component' in query or query['identity_component'] == 'SO(1)') and (not 'trace_zero_density' in query or query['trace_zero_density'] == '0')): nres = None if components_list is None: components_list = range( 1, 3 if ratonly else (start + count + 1 + len(ommitted))) nres = None if ratonly else INFINITY elif ratonly: components_list = [n for n in range(1, 3) if n in components_list] components_list = [n for n in components_list if n not in ommitted] if nres is None: nres = len(components_list) if search_type == "Random" and nres > 0: # Need to return mu(1), mu(2) or mu(4) sometimes otherlen = db.gps_sato_tate.count(query) r = ZZ.random_element(nres + otherlen) if r < nres: return redirect( url_for(".by_label", label="0.1.%d" % components_list[r]), 307) for n in itertools.islice(components_list, start, start + count): results.append(mu_info(n)) else: nres = 0 if 'result_count' in info: nres += db.gps_sato_tate.count(query) return jsonify({"nres": str(nres)}) if search_type == "Random": label = db.gps_sato_tate.random(query, "label") if label is not None: return redirect(url_for(".by_label", label=label), 307) # Now lookup other (rational) ST groups in database if nres != INFINITY: start2 = start - nres if start > nres else 0 proj = [ 'label', 'weight', 'degree', 'real_dimension', 'identity_component', 'name', 'pretty', 'components', 'component_group', 'trace_zero_density', 'moments' ] try: res = db.gps_sato_tate.search(query, proj, limit=max(count - len(results), 0), offset=start2, info=info) except QueryCanceledError as err: ctx = ctx_proc_userdata() flash_error( 'The search query took longer than expected! Please help us improve by reporting this error <a href="%s" target=_blank>here</a>.' % ctx['feedbackpage']) info['err'] = str(err) return render_template('st_results.html', info=info, title=err_title, **template_kwds) info['number'] += nres if start < info['number'] and len(results) < count: for v in res: v['identity_component'] = st0_pretty(v['identity_component']) v['component_group'] = sg_pretty(v['component_group']) v['trace_moments'] = trace_moments(v['moments']) results.append(v) else: info['number'] = 'infinity' info['start'] = start info['count'] = count info['st0_list'] = st0_list info['st0_dict'] = st0_dict info['results'] = results info['stgroup_url'] = lambda dbc: url_for('.by_label', label=dbc['label']) return render_template('st_results.html', info=info, title=title, **template_kwds)
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'])