def genus2_curve_search(**args): info = to_dict(args) 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_dict"] = real_geom_end_alg_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 query = {} # database callable bread = [('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('Search Results', '.')] #if 'SearchAgain' in args: # return rational_genus2_curves() if 'jump' in args: return render_curve_webpage_by_label(info["jump"]) if info.get("disc"): field = "abs_disc" ran = info["disc"] ran = ran.replace('..', '-').replace(' ','') # Past input check dlist = parse_discs(ran) tmp = g2_list_to_query(dlist) if len(tmp) == 1: tmp = tmp[0] else: query[tmp[0][0]] = tmp[0][1] tmp = tmp[1] # 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 info.get("is_gl2_type"): if info['is_gl2_type'] == "True": query['is_gl2_type']= True elif info['is_gl2_type'] == "False": query['is_gl2_type']= False for fld in ['st_group', 'real_geom_end_alg']: if info.get(fld): query[fld] = info[fld] for fld in ['aut_grp', 'geom_aut_grp','igusa_clebsch']: if info.get(fld): query[fld] = map(int,info[fld].strip()[1:-1].split(",")) if info.get('torsion'): res = parse_torsion_structure(info['torsion'],4) if 'Error' in res: # no error handling of malformed input yet! info['torsion'] = '' #info['err'] = res #return search_input_error(info, bread) else: #update info for repeat searches info['torsion'] = str(res).replace(' ','') query['torsion'] = [int(r) for r in res] if info.get('ic0'): query['igusa_clebsch']=[info['ic0'], info['ic1'], info['ic2'], info['ic3'] ] for fld in ["cond", "num_rat_wpts", "torsion_order", "two_selmer_rank"]: if info.get(fld): field = fld ran = str(info[field]) ran = ran.replace('..', '-').replace(' ','') # 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] info["query"] = dict(query) 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 cursor = db_g2c().curves.find(query) nres = cursor.count() if(start >= nres): start -= (1 + (start - nres) / count) * count if(start < 0): start = 0 res = cursor.sort([("cond", pymongo.ASCENDING), ("class", pymongo.ASCENDING), ("disc_key", pymongo.ASCENDING), ("label", pymongo.ASCENDING)]).skip(start).limit(count) nres = res.count() 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 res_clean = [] for v in res: v_clean = {} v_clean["label"] = v["label"] v_clean["isog_label"] = v["class"] isogeny_class = db_g2c().isogeny_classes.find_one({'label' : isog_label(v["label"])}) v_clean["is_gl2_type"] = isogeny_class["is_gl2_type"] if isogeny_class["is_gl2_type"] == True: v_clean["is_gl2_type_display"] = '✔' #checkmark else: v_clean["is_gl2_type_display"] = '' v_clean["equation_formatted"] = list_to_min_eqn(v["min_eqn"]) v_clean["st_group_name"] = st_group_name(isogeny_class['st_group']) res_clean.append(v_clean) info["curves"] = res_clean info["curve_url"] = lambda dbc: url_for_label(dbc['label']) info["isog_url"] = lambda dbc: isog_url_for_label(dbc['label']) info["start"] = start info["count"] = count info["more"] = int(start+count<nres) credit = credit_string title = 'Genus 2 Curves search results' return render_template("search_results_g2.html", info=info, credit=credit, bread=bread, title=title)
def genus2_curve_search(**args): info = to_dict(args) 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_dict"] = real_geom_end_alg_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 query = {} # database callable bread = [('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('Search Results', '.')] #if 'SearchAgain' in args: # return rational_genus2_curves() if 'jump' in args: return render_curve_webpage_by_label(info["jump"]) if info.get("disc"): field = "abs_disc" ran = info["disc"] ran = ran.replace('..', '-').replace(' ','') # Past input check dlist = parse_discs(ran) tmp = g2_list_to_query(dlist) if len(tmp) == 1: tmp = tmp[0] else: query[tmp[0][0]] = tmp[0][1] tmp = tmp[1] # 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 info.get("is_gl2_type"): if info['is_gl2_type'] == "True": query['is_gl2_type']= True elif info['is_gl2_type'] == "False": query['is_gl2_type']= False for fld in ['st_group', 'real_geom_end_alg']: if info.get(fld): query[fld] = info[fld] for fld in ['aut_grp', 'geom_aut_grp','torsion','igusa_clebsch']: if info.get(fld): query[fld] = map(int,info[fld].strip()[1:-1].split(",")) if info.get('ic0'): query['igusa_clebsch']=[info['ic0'], info['ic1'], info['ic2'], info['ic3'] ] for fld in ["cond", "num_rat_wpts", "torsion_order", "two_selmer_rank"]: if info.get(fld): field = fld ran = str(info[field]) ran = ran.replace('..', '-').replace(' ','') # 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] info["query"] = dict(query) 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 cursor = db_g2c().curves.find(query) nres = cursor.count() if(start >= nres): start -= (1 + (start - nres) / count) * count if(start < 0): start = 0 res = cursor.sort([("cond", pymongo.ASCENDING), ("class", pymongo.ASCENDING), ("disc_key", pymongo.ASCENDING), ("label", pymongo.ASCENDING)]).skip(start).limit(count) nres = res.count() 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 res_clean = [] for v in res: v_clean = {} v_clean["label"] = v["label"] v_clean["isog_label"] = v["class"] isogeny_class = db_g2c().isogeny_classes.find_one({'label' : isog_label(v["label"])}) v_clean["is_gl2_type"] = isogeny_class["is_gl2_type"] if isogeny_class["is_gl2_type"] == True: v_clean["is_gl2_type_display"] = '✔' #checkmark else: v_clean["is_gl2_type_display"] = '' v_clean["equation_formatted"] = list_to_min_eqn(v["min_eqn"]) v_clean["st_group_name"] = st_group_name(isogeny_class['st_group']) res_clean.append(v_clean) info["curves"] = res_clean info["curve_url"] = lambda dbc: url_for_label(dbc['label']) info["isog_url"] = lambda dbc: isog_url_for_label(dbc['label']) info["start"] = start info["count"] = count info["more"] = int(start+count<nres) credit = credit_string title = 'Genus 2 Curves search results' return render_template("search_results_g2.html", info=info, credit=credit, bread=bread, title=title)
def genus2_curve_search(**args): info = to_dict(args) query = {} # database callable bread = [('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('Search Results', '.')] #if 'SearchAgain' in args: # return rational_genus2_curves() if 'jump' in args: return render_curve_webpage_by_label(info["jump"]) if info.get("disc"): field = "abs_disc" ran = info["disc"] ran = ran.replace('..', '-').replace(' ', '') # Past input check dlist = parse_discs(ran) tmp = g2_list_to_query(dlist) if len(tmp) == 1: tmp = tmp[0] else: query[tmp[0][0]] = tmp[0][1] tmp = tmp[1] print tmp # 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 info.get("is_gl2_type"): query['is_gl2_type'] = bool(info['is_gl2_type']) for fld in ['aut_grp', 'geom_aut_grp', 'st_group', 'real_geom_end_alg']: if info.get(fld): query[fld] = info[fld] for fld in ['aut_grp', 'geom_aut_grp']: if info.get(fld): query[fld] = eval(info[fld]) if info.get("cond"): field = "cond" ran = str(info[field]) ran = ran.replace('..', '-').replace(' ', '') # Past input check tmp = parse_range2(ran, field) print tmp # 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 info.get("count"): try: count = int(info["count"]) except: count = 100 else: count = 100 info["query"] = dict(query) #res = db_g2c().curves.find(query).sort([("cond", pymongo.ASCENDING), #("label", pymongo.ASCENDING)]).limit(count) res = db_g2c().curves.find(query).sort([("cond", pymongo.ASCENDING), ("class", pymongo.ASCENDING), ("disc_key", pymongo.ASCENDING), ("label", pymongo.ASCENDING)]) nres = res.count() if nres == 1: info["report"] = "unique match" else: if nres > count: info["report"] = "displaying first %s of %s matches" % (count, nres) else: info["report"] = "displaying all %s matches" % nres res_clean = [] for v in res: v_clean = {} v_clean["label"] = v["label"] v_clean["isog_label"] = v["class"] isogeny_class = db_g2c().isogeny_classes.find_one( {'label': isog_label(v["label"])}) v_clean["is_gl2_type"] = isogeny_class["is_gl2_type"] v_clean["equation_formatted"] = list_to_min_eqn(v["min_eqn"]) res_clean.append(v_clean) info["curves"] = res_clean info["curve_url"] = lambda dbc: url_for_label(dbc['label']) info["isog_url"] = lambda dbc: isog_url_for_label(dbc['label']) credit = credit_string title = 'Genus 2 Curves search results' return render_template("search_results_g2.html", info=info, credit=credit, bread=bread, title=title)
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)
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 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 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 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 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 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 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(" ", "") 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 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 genus2_curve_search(**args): info = to_dict(args) query = {} # database callable bread = [('Genus 2 Curves', url_for(".index")), ('$\Q$', url_for(".index_Q")), ('Search Results', '.')] #if 'SearchAgain' in args: # return rational_genus2_curves() if 'jump' in args: return render_curve_webpage_by_label(info["jump"]) if info.get("disc"): field = "abs_disc" ran = info["disc"] ran = ran.replace('..', '-').replace(' ','') # Past input check dlist = parse_discs(ran) tmp = g2_list_to_query(dlist) if len(tmp) == 1: tmp = tmp[0] else: query[tmp[0][0]] = tmp[0][1] tmp = tmp[1] print tmp # 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 info.get("is_gl2_type"): query['is_gl2_type']=bool(info['is_gl2_type']) for fld in ['aut_grp', 'geom_aut_grp','st_group','real_geom_end_alg']: if info.get(fld): query[fld] = info[fld] for fld in ['aut_grp', 'geom_aut_grp']: if info.get(fld): query[fld] = eval(info[fld]) if info.get("cond"): field = "cond" ran = str(info[field]) ran = ran.replace('..', '-').replace(' ','') # Past input check tmp = parse_range2(ran, field) print tmp # 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 info.get("count"): try: count = int(info["count"]) except: count = 100 else: count = 100 info["query"] = dict(query) #res = db_g2c().curves.find(query).sort([("cond", pymongo.ASCENDING), #("label", pymongo.ASCENDING)]).limit(count) res = db_g2c().curves.find(query).sort([("cond", pymongo.ASCENDING), ("class", pymongo.ASCENDING), ("disc_key", pymongo.ASCENDING), ("label", pymongo.ASCENDING)]) nres = res.count() if nres == 1: info["report"] = "unique match" else: if nres > count: info["report"] = "displaying first %s of %s matches" % (count, nres) else: info["report"] = "displaying all %s matches" % nres res_clean = [] for v in res: v_clean = {} v_clean["label"] = v["label"] v_clean["isog_label"] = v["class"] isogeny_class = db_g2c().isogeny_classes.find_one({'label' : isog_label(v["label"])}) v_clean["is_gl2_type"] = isogeny_class["is_gl2_type"] v_clean["equation_formatted"] = list_to_min_eqn(v["min_eqn"]) res_clean.append(v_clean) info["curves"] = res_clean info["curve_url"] = lambda dbc: url_for_label(dbc['label']) info["isog_url"] = lambda dbc: isog_url_for_label(dbc['label']) credit = 'Genus 2 Team' title = 'Genus 2 Curves search results' return render_template("search_results_g2.html", info=info, credit=credit, bread=bread, title=title)
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 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 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 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 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 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 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 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 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)