Ejemplo n.º 1
0
Archivo: main.py Proyecto: LMFDB/lmfdb
def lattice_search_isometric(res, info, query):
    """
    We check for isometric lattices if the user enters a valid gram matrix
    but not one stored in the database

    This may become slow in the future: at the moment we compare against
    a list of stored matrices with same dimension and determinant
    (just compare with respect to dimension is slow)
    """
    if info['number'] == 0 and info.get('gram'):
        A = query['gram']
        n = len(A[0])
        d = matrix(A).determinant()
        for gram in db.lat_lattices.search({'dim': n, 'det': int(d)}, 'gram'):
            if isom(A, gram):
                query['gram'] = gram
                proj = lattice_search_projection
                count = parse_count(info)
                start = parse_start(info)
                res = db.lat_lattices.search(query, proj, limit=count, offset=start, info=info)
                break

    for v in res:
        v['min'] = v.pop('minimum')
    return res
Ejemplo n.º 2
0
def lattice_search_isometric(res, info, query):
    """
    We check for isometric lattices if the user enters a valid gram matrix
    but not one stored in the database

    This may become slow in the future: at the moment we compare against
    a list of stored matrices with same dimension and determinant
    (just compare with respect to dimension is slow)
    """
    if info['number'] == 0 and info.get('gram'):
        A = query['gram']
        n = len(A[0])
        d = matrix(A).determinant()
        for gram in db.lat_lattices.search({'dim': n, 'det': int(d)}, 'gram'):
            if isom(A, gram):
                query['gram'] = gram
                proj = lattice_search_projection
                count = parse_count(info)
                start = parse_start(info)
                res = db.lat_lattices.search(query, proj, limit=count, offset=start, info=info)
                break

    for v in res:
        v['min'] = v.pop('minimum')
    return res
Ejemplo n.º 3
0
def bmf_field_dim_table(**args):
    argsdict = to_dict(args)
    argsdict.update(to_dict(request.args))
    gl_or_sl = argsdict['gl_or_sl']

    field_label=argsdict['field_label']
    field_label = nf_string_to_label(field_label)

    start = parse_start(argsdict)

    info={}
    info['gl_or_sl'] = gl_or_sl
    # level_flag controls whether to list all levels ('all'), only
    # those with positive cuspidal dimension ('cusp'), or only those
    # with positive new dimension ('new').  Default is 'cusp'.
    level_flag = argsdict.get('level_flag', 'cusp')
    info['level_flag'] = level_flag
    count = parse_count(argsdict, 50)

    pretty_field_label = field_pretty(field_label)
    bread = [('Bianchi Modular Forms', url_for(".index")), (
        pretty_field_label, ' ')]
    properties = []
    query = {}
    query['field_label'] = field_label
    if gl_or_sl=='gl2_dims':
        info['group'] = 'GL(2)'
        info['bgroup'] = '\GL(2,\mathcal{O}_K)'
    else:
        info['group'] = 'SL(2)'
        info['bgroup'] = '\SL(2,\mathcal{O}_K)'
    if level_flag == 'all':
        query[gl_or_sl] = {'$exists': True}
    else:
        # Only get records where the cuspdial/new dimension is positive for some weight
        totaldim = gl_or_sl.replace('dims', level_flag) + '_totaldim'
        query[totaldim] = {'$gt': 0}
    t = ' '.join(['Dimensions of Spaces of {} Bianchi Modular Forms over'.format(info['group']), pretty_field_label])
    data = list(db.bmf_dims.search(query, limit=count, offset=start, info=info))
    nres = info['number']
    if not info['exact_count']:
        info['number'] = nres = db.bmf_dims.count(query)
        info['exact_count'] = True
    if nres > count or start != 0:
        info['report'] = 'Displaying items %s-%s of %s levels,' % (start + 1, min(nres, start + count), nres)
    else:
        info['report'] = 'Displaying all %s levels,' % nres

    info['field'] = field_label
    info['field_pretty'] = pretty_field_label
    nf = WebNumberField(field_label)
    info['base_galois_group'] = nf.galois_string()
    info['field_degree'] = nf.degree()
    info['field_disc'] = str(nf.disc())
    info['field_poly'] = teXify_pol(str(nf.poly()))
    weights = set()
    for dat in data:
        weights = weights.union(set(dat[gl_or_sl].keys()))
    weights = list([int(w) for w in weights])
    weights.sort()
    info['weights'] = weights
    info['nweights'] = len(weights)

    data.sort(key = lambda x: [int(y) for y in x['level_label'].split(".")])
    dims = {}
    for dat in data:
        dims[dat['level_label']] = d = {}
        for w in weights:
            sw = str(w)
            if sw in dat[gl_or_sl]:
                d[w] = {'d': dat[gl_or_sl][sw]['cuspidal_dim'],
                        'n': dat[gl_or_sl][sw]['new_dim']}
            else:
                d[w] = {'d': '?', 'n': '?'}
    info['nlevels'] = len(data)
    dimtable = [{'level_label': dat['level_label'],
                 'level_norm': dat['level_norm'],
                 'level_space': url_for(".render_bmf_space_webpage", field_label=field_label, level_label=dat['level_label']) if gl_or_sl=='gl2_dims' else "",
                  'dims': dims[dat['level_label']]} for dat in data]
    info['dimtable'] = dimtable
    return render_template("bmf-field_dim_table.html", info=info, title=t, properties=properties, bread=bread)
Ejemplo n.º 4
0
def search(info):
    """ query processing for Sato-Tate groups -- returns rendered results page """
    if 'jump' in info:
        return redirect(url_for('.by_label', label=info['jump']), 301)
    if 'label' in info:
        return redirect(url_for('.by_label', label=info['label']), 301)
    search_type = info.get("search_type", info.get("hst", "List"))
    template_kwds = {
        'bread': [('Sato-Tate Groups', url_for('.index')),
                  ('Search Results', '.')],
        'credit': credit_string,
        'learnmore': learnmore_list()
    }
    title = 'Sato-Tate Group Search Results'
    err_title = 'Sato-Tate Groups Search Input Error'
    count = parse_count(info, 50)
    start = parse_start(info)
    # if user clicked refine search always restart at 0
    if 'refine' in info:
        start = 0
    ratonly = (info.get('include_irrational', 'no').strip().lower() == 'no')
    if search_type == "Random" and not ratonly:
        info['err'] = err = 'Cannot select random irrational Sato-Tate group'
        flash_error(err)
        return render_template('st_results.html',
                               info=info,
                               title=err_title,
                               **template_kwds)
    query = {'rational': True} if ratonly else {}
    try:
        parse_ints(info, query, 'weight', 'weight')
        if 'weight' in query:
            weight_list = parse_ints_to_list_flash(info.get('weight'),
                                                   'weight')
        parse_ints(info, query, 'degree', 'degree')
        if 'degree' in query:
            degree_list = parse_ints_to_list_flash(info.get('degree'),
                                                   'degree')
        if info.get('identity_component'):
            query['identity_component'] = info['identity_component']
        parse_ints(info, query, 'components', 'components')
        if 'components' in query:
            components_list = parse_ints_to_list_flash(info.get('components'),
                                                       'components')
        parse_rational(info, query, 'trace_zero_density', 'trace zero density')
    except ValueError as err:
        info['err'] = str(err)
        return render_template('st_results.html',
                               info=info,
                               title=err_title,
                               **template_kwds)

    # Check mu(n) groups first (these are not stored in the database)
    results = []
    if ((not 'weight' in query or 0 in weight_list)
            and (not 'degree' in query or 1 in degree_list)
            and (not 'identity_component' in query
                 or query['identity_component'] == 'SO(1)')
            and (not 'trace_zero_density' in query
                 or query['trace_zero_density'] == '0')):
        if not 'components' in query:
            components_list = range(1, 3 if ratonly else start + count + 1)
        elif ratonly:
            components_list = [n for n in range(1, 3) if n in components_list]
        nres = len(
            components_list) if 'components' in query or ratonly else INFINITY
        if search_type == "Random" and nres > 0:
            # Need to return mu(1) and mu(2) sometimes
            otherlen = db.gps_sato_tate.count(query)
            r = ZZ.random_element(nres + otherlen)
            if r < nres:
                return redirect(
                    url_for(".by_label", label="0.1.%d" % components_list[r]),
                    307)
        for n in itertools.islice(components_list, start, start + count):
            results.append(mu_info(n))
    else:
        nres = 0

    if 'result_count' in info:
        nres += db.gps_sato_tate.count(query)
        return jsonify({"nres": str(nres)})
    if search_type == "Random":
        label = db.gps_sato_tate.random(query, "label")
        if label is not None:
            return redirect(url_for(".by_label", label=label), 307)

    # Now lookup other (rational) ST groups in database
    if nres != INFINITY:
        start2 = start - nres if start > nres else 0
        proj = [
            'label', 'weight', 'degree', 'real_dimension',
            'identity_component', 'name', 'pretty', 'components',
            'component_group', 'trace_zero_density', 'moments'
        ]
        try:
            res = db.gps_sato_tate.search(query,
                                          proj,
                                          limit=max(count - len(results), 0),
                                          offset=start2,
                                          info=info)
        except QueryCanceledError as err:
            ctx = ctx_proc_userdata()
            flash_error(
                'The search query took longer than expected! Please help us improve by reporting this error  <a href="%s" target=_blank>here</a>.'
                % ctx['feedbackpage'])
            info['err'] = str(err)
            return render_template('st_results.html',
                                   info=info,
                                   title=err_title,
                                   **template_kwds)
        info['number'] += nres
        if start < info['number'] and len(results) < count:
            for v in res:
                v['identity_component'] = st0_pretty(v['identity_component'])
                v['component_group'] = sg_pretty(v['component_group'])
                v['trace_moments'] = trace_moments(v['moments'])
                results.append(v)
    else:
        info['number'] = 'infinity'
    info['start'] = start
    info['count'] = count

    info['st0_list'] = st0_list
    info['st0_dict'] = st0_dict
    info['results'] = results
    info['stgroup_url'] = lambda dbc: url_for('.by_label', label=dbc['label'])
    return render_template('st_results.html',
                           info=info,
                           title=title,
                           **template_kwds)
Ejemplo n.º 5
0
def bmf_field_dim_table(**args):
    argsdict = to_dict(args)
    argsdict.update(to_dict(request.args))
    gl_or_sl = argsdict['gl_or_sl']

    field_label=argsdict['field_label']
    field_label = nf_string_to_label(field_label)

    start = parse_start(argsdict)

    info={}
    info['gl_or_sl'] = gl_or_sl
    # level_flag controls whether to list all levels ('all'), only
    # those with positive cuspidal dimension ('cusp'), or only those
    # with positive new dimension ('new').  Default is 'cusp'.
    level_flag = argsdict.get('level_flag', 'cusp')
    info['level_flag'] = level_flag
    count = parse_count(argsdict, 50)

    pretty_field_label = field_pretty(field_label)
    bread = [('Bianchi Modular Forms', url_for(".index")), (
        pretty_field_label, ' ')]
    properties = []
    if gl_or_sl=='gl2_dims':
        info['group'] = 'GL(2)'
        info['bgroup'] = '\GL(2,\mathcal{O}_K)'
    else:
        info['group'] = 'SL(2)'
        info['bgroup'] = '\SL(2,\mathcal{O}_K)'
    t = ' '.join(['Dimensions of Spaces of {} Bianchi Modular Forms over'.format(info['group']), pretty_field_label])
    query = {}
    query['field_label'] = field_label
    query[gl_or_sl] = {'$exists': True}
    data = db.bmf_dims.search(query, limit=count, offset=start, info=info)
    nres = info['number']
    if nres > count or start != 0:
        info['report'] = 'Displaying items %s-%s of %s levels,' % (start + 1, min(nres, start + count), nres)
    else:
        info['report'] = 'Displaying all %s levels,' % nres

    # convert data to a list and eliminate levels where all
    # new/cuspidal dimensions are 0.  (This could be done at the
    # search stage, but that requires adding new fields to each
    # record.)
    def filter(dat, flag):
        dat1 = dat[gl_or_sl]
        return any([int(dat1[w][flag])>0 for w in dat1])
    flag = 'cuspidal_dim' if level_flag=='cusp' else 'new_dim'
    data = [dat for dat in data if level_flag == 'all' or filter(dat, flag)]

    info['field'] = field_label
    info['field_pretty'] = pretty_field_label
    nf = WebNumberField(field_label)
    info['base_galois_group'] = nf.galois_string()
    info['field_degree'] = nf.degree()
    info['field_disc'] = str(nf.disc())
    info['field_poly'] = teXify_pol(str(nf.poly()))
    weights = set()
    for dat in data:
        weights = weights.union(set(dat[gl_or_sl].keys()))
    weights = list([int(w) for w in weights])
    weights.sort()
    info['weights'] = weights
    info['nweights'] = len(weights)

    data.sort(key = lambda x: [int(y) for y in x['level_label'].split(".")])
    dims = {}
    for dat in data:
        dims[dat['level_label']] = d = {}
        for w in weights:
            sw = str(w)
            if sw in dat[gl_or_sl]:
                d[w] = {'d': dat[gl_or_sl][sw]['cuspidal_dim'],
                        'n': dat[gl_or_sl][sw]['new_dim']}
            else:
                d[w] = {'d': '?', 'n': '?'}
    info['nlevels'] = len(data)
    dimtable = [{'level_label': dat['level_label'],
                 'level_norm': dat['level_norm'],
                 'level_space': url_for(".render_bmf_space_webpage", field_label=field_label, level_label=dat['level_label']) if gl_or_sl=='gl2_dims' else "",
                  'dims': dims[dat['level_label']]} for dat in data]
    info['dimtable'] = dimtable
    return render_template("bmf-field_dim_table.html", info=info, title=t, properties=properties, bread=bread)
Ejemplo n.º 6
0
def search(**args):
    """ query processing for Sato-Tate groups -- returns rendered results page """
    info = to_dict(args)
    if 'jump' in info:
        return redirect(url_for('.by_label', label=info['jump']), 301)
    if 'label' in info:
        return redirect(url_for('.by_label', label=info['label']), 301)
    template_kwds = {'bread':[('Sato-Tate Groups', url_for('.index')),('Search Results', '.')],
                     'credit':credit_string,
                     'learnmore':learnmore_list()}
    title = 'Sato-Tate Group Search Results'
    err_title = 'Sato-Tate Groups Search Input Error'
    count = parse_count(info, 25)
    start = parse_start(info)
    # if user clicked refine search always restart at 0
    if 'refine' in info:
        start = 0
    ratonly = True if info.get('rational_only','no').strip().lower() == 'yes' else False
    query = {'rational':True} if ratonly else {}
    try:
        parse_ints(info,query,'weight','weight')
        if 'weight' in query:
            weight_list = parse_ints_to_list_flash(info.get('weight'),'weight')
        parse_ints(info,query,'degree','degree')
        if 'degree' in query:
            degree_list = parse_ints_to_list_flash(info.get('degree'),'degree')
        if info.get('identity_component'):
            query['identity_component'] = info['identity_component']
        parse_ints(info,query,'components','components')
        if 'components' in query:
            components_list = parse_ints_to_list_flash(info.get('components'), 'components')
        parse_rational(info,query,'trace_zero_density','trace zero density')
    except ValueError as err:
        info['err'] = str(err)
        return render_template('st_results.html', info=info, title=err_title, **template_kwds)

    # Check mu(n) groups first (these are not stored in the database)
    results = []
    if (not 'weight' in query or 0 in weight_list) and \
       (not 'degree' in query or 1 in degree_list) and \
       (not 'identity_component' in query or query['identity_component'] == 'SO(1)') and \
       (not 'trace_zero_density' in query or query['trace_zero_density'] == '0'):
        if not 'components' in query:
            components_list = xrange(1,3 if ratonly else start+count+1)
        elif ratonly:
            components_list = [n for n in range(1,3) if n in components_list]
        nres = len(components_list) if 'components' in query or ratonly else INFINITY
        for n in itertools.islice(components_list,start,start+count):
            results.append(mu_info(n))
    else:
        nres = 0

    if 'result_count' in info:
        nres += db.gps_sato_tate.count(query)
        return jsonify({"nres":str(nres)})

    # Now lookup other (rational) ST groups in database
    if nres != INFINITY:
        start2 = start - nres if start > nres else 0
        proj = ['label','weight','degree','real_dimension','identity_component','name','pretty','components','component_group','trace_zero_density','moments']
        try:
            res = db.gps_sato_tate.search(query, proj, limit=max(count - len(results), 0), offset=start2, info=info)
        except QueryCanceledError as err:
            ctx = ctx_proc_userdata()
            flash_error('The search query took longer than expected! Please help us improve by reporting this error  <a href="%s" target=_blank>here</a>.' % ctx['feedbackpage'])
            info['err'] = str(err)
            return render_template('st_results.html', info=info, title=err_title, **template_kwds)
        info['number'] += nres
        if start < info['number'] and len(results) < count:
            for v in res:
                v['identity_component'] = st0_pretty(v['identity_component'])
                v['component_group'] = sg_pretty(v['component_group'])
                v['trace_moments'] = trace_moments(v['moments'])
                results.append(v)
    else:
        info['number'] = 'infinity'
        info['start'] = start
        info['count'] = count

    info['st0_list'] = st0_list
    info['st0_dict'] = st0_dict
    info['results'] = results
    info['stgroup_url'] = lambda dbc: url_for('.by_label', label=dbc['label'])
    return render_template('st_results.html', info=info, title=title, **template_kwds)
Ejemplo n.º 7
0
def search(info):
    """ query processing for Sato-Tate groups -- returns rendered results page """
    if 'jump' in info:
        return redirect(url_for('.by_label', label=info['jump']), 301)
    if 'label' in info:
        return redirect(url_for('.by_label', label=info['label']), 301)
    search_type = info.get("search_type", info.get("hst", "List"))
    template_kwds = {
        'bread': get_bread("Search results"),
        'credit': credit_string,
        'learnmore': learnmore_list()
    }
    title = 'Sato-Tate group search results'
    err_title = 'Sato-Tate group search input error'
    count = parse_count(info, 50)
    start = parse_start(info)
    # if user clicked refine search always restart at 0
    if 'refine' in info:
        start = 0
    ratonly = (info.get('include_irrational', 'no').strip().lower() == 'no')
    if search_type == "Random" and not ratonly:
        info['err'] = err = 'Cannot select random irrational Sato-Tate group'
        flash_error(err)
        return render_template('st_results.html',
                               info=info,
                               title=err_title,
                               **template_kwds)
    query = {'rational': True} if ratonly else {}
    try:
        parse_ints(info, query, 'weight', 'weight')
        if 'weight' in query:
            weight_list = parse_ints_to_list_flash(info.get('weight'),
                                                   'weight')
        parse_ints(info, query, 'degree', 'degree')
        if 'degree' in query:
            degree_list = parse_ints_to_list_flash(info.get('degree'),
                                                   'degree')
        if info.get('identity_component'):
            query['identity_component'] = info['identity_component']
        parse_ints(info, query, 'components', 'components')

        def refine_components(current, condition):
            if current is None:
                return condition
            return [x for x in condition if x in current]

        # The following are used to constraint which mu(n) will show up in search results
        components_list = None
        ommitted = set()
        if 'components' in query:
            components_list = parse_ints_to_list_flash(info.get('components'),
                                                       'components')
        parse_component_group(info, query)
        gps = query.get("component_group")
        if gps:
            if isinstance(gps, dict):
                gps = gps["$in"]
            else:
                gps = [gps]
            if not ratonly:
                cyclic_labels = set(
                    db.gps_small.search({"cyclic": True}, "label"))
            irrat = []
            for code in gps:
                if code in cyclics:
                    irrat.append(cyclics[code])
                elif re.match(cyclicre, code):
                    irrat.append(int(code[1:]))
                elif not ratonly and code in cyclic_labels:
                    irrat.append(int(code.split(".")[0]))
            components_list = refine_components(components_list, irrat)
        parse_rational(info, query, 'trace_zero_density', 'trace zero density')
        parse_ints(info, query, 'second_trace_moment')
        parse_ints(info, query, 'fourth_trace_moment')
        for name, ones in [('second_trace_moment', [1, 2]),
                           ('fourth_trace_moment', [1, 2, 4])]:
            if name in query:
                # E(x^2) for mu(1) and mu(2) are 1; others are 0
                # E(x^4) for mu(1), mu(2) and mu(4) are 1; others are 0
                E = parse_ints_to_list_flash(info.get(name),
                                             name.replace("_", " "))
                if 0 not in E:
                    components_list = refine_components(components_list, ones)
                if 1 not in E:
                    ommitted.update(ones)
        parse_ints(info, query, 'first_a2_moment')
        parse_bool(info, query, 'maximal')
        if "first_a2_moment" in query or query.get("maximal"):
            # mu(n) do not have a2 moments and none are maximal
            components_list = []
    except ValueError as err:
        info['err'] = str(err)
        return render_template('st_results.html',
                               info=info,
                               title=err_title,
                               **template_kwds)

    # Check mu(n) groups first (these are not stored in the database)
    results = []
    if ((not 'weight' in query or 0 in weight_list)
            and (not 'degree' in query or 1 in degree_list)
            and (not 'identity_component' in query
                 or query['identity_component'] == 'SO(1)')
            and (not 'trace_zero_density' in query
                 or query['trace_zero_density'] == '0')):
        nres = None
        if components_list is None:
            components_list = range(
                1, 3 if ratonly else (start + count + 1 + len(ommitted)))
            nres = None if ratonly else INFINITY
        elif ratonly:
            components_list = [n for n in range(1, 3) if n in components_list]
        components_list = [n for n in components_list if n not in ommitted]
        if nres is None:
            nres = len(components_list)
        if search_type == "Random" and nres > 0:
            # Need to return mu(1), mu(2) or mu(4) sometimes
            otherlen = db.gps_sato_tate.count(query)
            r = ZZ.random_element(nres + otherlen)
            if r < nres:
                return redirect(
                    url_for(".by_label", label="0.1.%d" % components_list[r]),
                    307)
        for n in itertools.islice(components_list, start, start + count):
            results.append(mu_info(n))
    else:
        nres = 0

    if 'result_count' in info:
        nres += db.gps_sato_tate.count(query)
        return jsonify({"nres": str(nres)})
    if search_type == "Random":
        label = db.gps_sato_tate.random(query, "label")
        if label is not None:
            return redirect(url_for(".by_label", label=label), 307)

    # Now lookup other (rational) ST groups in database
    if nres != INFINITY:
        start2 = start - nres if start > nres else 0
        proj = [
            'label', 'weight', 'degree', 'real_dimension',
            'identity_component', 'name', 'pretty', 'components',
            'component_group', 'trace_zero_density', 'moments'
        ]
        try:
            res = db.gps_sato_tate.search(query,
                                          proj,
                                          limit=max(count - len(results), 0),
                                          offset=start2,
                                          info=info)
        except QueryCanceledError as err:
            ctx = ctx_proc_userdata()
            flash_error(
                'The search query took longer than expected! Please help us improve by reporting this error  <a href="%s" target=_blank>here</a>.'
                % ctx['feedbackpage'])
            info['err'] = str(err)
            return render_template('st_results.html',
                                   info=info,
                                   title=err_title,
                                   **template_kwds)
        info['number'] += nres
        if start < info['number'] and len(results) < count:
            for v in res:
                v['identity_component'] = st0_pretty(v['identity_component'])
                v['component_group'] = sg_pretty(v['component_group'])
                v['trace_moments'] = trace_moments(v['moments'])
                results.append(v)
    else:
        info['number'] = 'infinity'
    info['start'] = start
    info['count'] = count

    info['st0_list'] = st0_list
    info['st0_dict'] = st0_dict
    info['results'] = results
    info['stgroup_url'] = lambda dbc: url_for('.by_label', label=dbc['label'])
    return render_template('st_results.html',
                           info=info,
                           title=title,
                           **template_kwds)