Example #1
0
def render_group_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        label = label.replace('t', 'T')
        C = base.getDBConnection()
        data = C.transitivegroups.groups.find_one({'label': label})
        if data is None:
            bread = get_bread([("Search error", url_for('.search'))])
            info['err'] = "Group " + label + " was not found in the database."
            info['label'] = label
            return search_input_error(info, bread)
        title = 'Galois Group:' + label
        n = data['n']
        t = data['t']
        data['yesno'] = yesno
        order = data['order']
        data['orderfac'] = latex(ZZ(order).factor())
        orderfac = latex(ZZ(order).factor())
        data['ordermsg'] = "$%s=%s$" % (order, latex(orderfac))
        if ZZ(order) == 1:
            data['ordermsg'] = "$1$"
        if ZZ(order).is_prime():
            data['ordermsg'] = "$%s$ (is prime)" % order
        pgroup = len(ZZ(order).prime_factors()) < 2
        if n == 1:
            G = gap.SmallGroup(n, t)
        else:
            G = gap.TransitiveGroup(n, t)
        if ZZ(order) < ZZ('10000000000'):
            ctable = chartable(n, t)
        else:
            ctable = 'Group too large'
        data['gens'] = generators(n, t)
        if n == 1 and t == 1:
            data['gens'] = 'None needed'
        data['chartable'] = ctable
        data['parity'] = "$%s$" % data['parity']
        data['cclasses'] = conjclasses(G, n)
        data['subinfo'] = subfield_display(C, n, data['subs'])
        data['resolve'] = resolve_display(C, data['resolve'])
#    if len(data['resolve']) == 0: data['resolve'] = 'None'
        data['otherreps'] = otherrep_display(n, t, C, data['repns'])
        prop2 = [
            ('Order:', '\(%s\)' % order),
            ('n:', '\(%s\)' % data['n']),
            ('Cyclic:', yesno(data['cyc'])),
            ('Abelian:', yesno(data['ab'])),
            ('Solvable:', yesno(data['solv'])),
            ('Primitive:', yesno(data['prim'])),
            ('$p$-group:', yesno(pgroup)),
            ('Name:', group_display_short(n, t, C)),
        ]
        info.update(data)

        bread = get_bread([(label, ' ')])
        return render_template("gg-show-group.html", credit=GG_credit, title=title, bread=bread, info=info, properties2=prop2)
Example #2
0
def splitint(a,p):
    if a==1:
        return ' '
    j = valuation(a,p)
    if j==0:
        return str(a)
    a = a/p**j
    if a==1:
        return latex(ZZ(p**j).factor())
    return str(a)+r'\cdot'+latex(ZZ(p**j).factor())
Example #3
0
 def safe_reduce(f):
     if not m:
         return latex(f)
     try:
         if f in sam.field():
             return latex(redc(f))
         else:
             return latex(redp(f))
     except ZeroDivisionError:
         return '\\textrm{Unable to reduce} \\bmod\\mathfrak{m}'
Example #4
0
def make_map_latex(map_str):
    # FIXME: Get rid of nu when map is defined over QQ
    if "nu" not in map_str:
        R0 = QQ
    else:
        R0 = PolynomialRing(QQ,'nu')
    R = PolynomialRing(R0,2,'x,y')
    F = FractionField(R)
    phi = F(map_str)
    num = phi.numerator()
    den = phi.denominator()
    c_num = num.denominator()
    c_den = den.denominator()
    lc = c_den/c_num
    # rescale coeffs to make them integral. then try to factor out gcds
    # numerator
    num_new = c_num*num
    num_cs = num_new.coefficients()
    if R0 == QQ:
        num_cs_ZZ = num_cs
    else:
        num_cs_ZZ = []
        for el in num_cs:
            num_cs_ZZ = num_cs_ZZ + el.coefficients()
    num_gcd = gcd(num_cs_ZZ)
    # denominator
    den_new = c_den*den
    den_cs = den_new.coefficients()
    if R0 == QQ:
        den_cs_ZZ = den_cs
    else:
        den_cs_ZZ = []
        for el in den_cs:
            den_cs_ZZ = den_cs_ZZ + el.coefficients()
    den_gcd = gcd(den_cs_ZZ)
    lc = lc*(num_gcd/den_gcd)
    num_new = num_new/num_gcd
    den_new = den_new/den_gcd
    # make strings for lc, num, and den
    num_str = latex(num_new)
    den_str = latex(den_new)
    if lc==1:
        lc_str=""
    else:
        lc_str = latex(lc)
    if den_new==1:
        if lc ==1:
            phi_str = num_str
        else:
            phi_str = lc_str+"("+num_str+")"
    else:
        phi_str = lc_str+"\\frac{"+num_str+"}"+"{"+den_str+"}"
    return phi_str
Example #5
0
 def _latex_using_dpd_depth1(self, dpd_dct):
     names = [dpd_dct[c] for c in self._consts]
     _gcd = QQ(gcd(self._coeffs))
     coeffs = [c / _gcd for c in self._coeffs]
     coeffs_names = [(c, n) for c, n in zip(coeffs, names) if c != 0]
     tail_terms = ["%s %s %s" % ("+" if c > 0 else "", c, n) for c, n in coeffs_names[1:]]
     c0, n0 = coeffs_names[0]
     head_term = str(c0) + " " + str(n0)
     return r"\frac{{{pol_num}}}{{{pol_dnm}}} \left({terms}\right)".format(
         pol_dnm=latex(_gcd.denominator() * self._scalar_const._polynomial_expr()),
         pol_num=latex(_gcd.numerator()),
         terms=" ".join([head_term] + tail_terms),
     )
Example #6
0
def make_curve_latex(crv_str):
    # FIXME: Get rid of nu when map is defined over QQ
    if "nu" not in crv_str:
        R0 = QQ
    else:
        R0 = PolynomialRing(QQ,'nu')
    R = PolynomialRing(R0,2,'x,y')
    F = FractionField(R)
    sides = crv_str.split("=")
    lhs = latex(F(sides[0]))
    rhs = latex(F(sides[1]))
    eqn_str = lhs + '=' + rhs
    return eqn_str
Example #7
0
    def latex(self, prec=None, name=None, keepzeta=False):
        """
        Change the name of the variable in a polynomial.  If keepzeta, then don't change
        the name of zetaN in the defining polynomial of a cyclotomic field.
        (keepzeta not implemented yet)
        """
        if prec is None:
            qe = self.value()
        else:
            qe = self.value()
            if not qe is None:
                qe = qe.truncate_powerseries(prec)
        wl = web_latex_split_on_re(qe)
        if name is not None and self.value().base_ring().absolute_degree()>1:
            oldname = latex(self.value().base_ring().gen())
            subfrom = oldname.strip()
            subfrom = subfrom.replace("\\","\\\\")  
            subfrom = subfrom.replace("{","\\{")   # because x_{0} means something in a regular expression
            if subfrom[0].isalpha():
                subfrom = "\\b" + subfrom
            subto = name.replace("\\","\\\\") + " "
            if keepzeta and "zeta" in subfrom:
                pass  # keep the variable as-is
            else:
                wl = re.sub(subfrom, subto, wl)
            return wl

        else:
            return wl
Example #8
0
    def eigs_as_seqseq_to_qexp(self, prec_max):
        # Takes a sequence of sequence of integers and returns a string for the corresponding q expansion
        # For example, eigs_as_seqseq_to_qexp([[0,0],[1,3]]) returns "\((1+3\beta_{1})q\)\(+O(q^2)\)"
        prec = min(self.qexp_prec, prec_max)
        if prec == 0:
            return 'O(1)'
        eigseq = self.qexp[:prec]
        d = self.dim
        Rgens = self._get_Rgens()
        s = ''
        for j in range(len(eigseq)):
            term = sum([Rgens[i]*eigseq[j][i] for i in range(d)])
            if term != 0:
                latexterm = latex(term)
                if term.number_of_terms() > 1:
                    latexterm = r"\left(" +  latexterm + r"\right)"

                if j > 0:
                    if term == 1:
                        latexterm = ''
                    elif term == -1:
                        latexterm = '-'
                    if j == 1:
                        latexterm += ' q'
                    else:
                        latexterm += ' q^{%d}' % j
                #print latexterm
                if s != '' and latexterm[0] != '-':
                    latexterm = '+' + latexterm
                s += '\(' + latexterm + '\) '
        # Work around bug in Sage's latex
        s = s.replace('betaq', 'beta q')
        return s + '\(+O(q^{%d})\)' % prec
Example #9
0
 def eigs_as_seqseq_to_qexp(self, prec_max):
     # Takes a sequence of sequence of integers (or pairs of integers in the hecke_ring_cyclotomic_generator != 0 case) and returns a string for the corresponding q expansion
     # For example, eigs_as_seqseq_to_qexp([[0,0],[1,3]]) returns "\((1+3\beta_{1})q\)\(+O(q^2)\)"
     prec = min(self.qexp_prec, prec_max)
     if prec == 0:
         return 'O(1)'
     eigseq = self.qexp[:prec]
     use_knowl = too_big(eigseq, 10**24)
     s = ''
     for j in range(len(eigseq)):
         term = self._elt(eigseq[j])
         if term != 0:
             latexterm = latex(term)
             if use_knowl:
                 latexterm = make_bigint(latexterm)
             if term.number_of_terms() > 1:
                 latexterm = r"(" +  latexterm + r")"
             if j > 0:
                 if term == 1:
                     latexterm = ''
                 elif term == -1:
                     latexterm = '-'
                 if j == 1:
                     latexterm += ' q'
                 else:
                     latexterm += ' q^{%d}' % j
             if s != '' and latexterm[0] != '-':
                 latexterm = '+' + latexterm
             s += '\(' + latexterm + '\) '
     # Work around bug in Sage's latex
     s = s.replace('betaq', 'beta q')
     return s + '\(+O(q^{%d})\)' % prec
Example #10
0
 def disc_factored_latex(self):
     D = self.disc()
     s = ''
     if D < 0:
         D = -D
         s = r'-\,'
     return s + latex(D.factor())
Example #11
0
def web_latex_split_on_pm(x):
    on = ['+', '-']
 #   A = "\( %s \)" % latex(x)
    try:
        A = "\(" + x + "\)"  # assume we are given LaTeX to split on
    except:
        A = "\( %s \)" % latex(x)

       # need a more clever split_on_pm that inserts left and right properly
    A = A.replace("\\left","")
    A = A.replace("\\right","")
    for s in on:
  #      A = A.replace(s, '\) ' + s + ' \( ')
   #     A = A.replace(s, '\) ' + ' \( \mathstrut ' + s )
        A = A.replace(s, '\)' + ' \(\mathstrut ' + s + '\mathstrut ')
    # the above will be re-done using a more sophisticated method involving
    # regular expressions.  Below fixes bad spacing when the current approach
    # encounters terms like (-3+x)
    for s in on:
        A = A.replace('(\) \(\mathstrut '+s,'(' + s)
    A = A.replace('( {}','(')
    A = A.replace('(\) \(','(')
    A = A.replace('\(+','\(\mathstrut+')
    A = A.replace('\(-','\(\mathstrut-')
    A = A.replace('(  ','(')
    A = A.replace('( ','(')

    return A
Example #12
0
def web_latex_split_on_re(x, r = '(q[^+-]*[+-])'):

    def insert_latex(s):
        return s.group(1) + '\) \('

    if isinstance(x, (str, unicode)):
        return x
    else:
        A = "\( %s \)" % latex(x)
        c = re.compile(r)
        A = A.replace('+', '\) \( {}+ ')
        A = A.replace('-', '\) \( {}- ')
#        A = A.replace('\left(','\left( {}\\right.') # parantheses needs to be balanced
#        A = A.replace('\\right)','\left.\\right)')        
        A = A.replace('\left(','\\bigl(')
        A = A.replace('\\right)','\\bigr)')        
        A = c.sub(insert_latex, A)

    # the above will be re-done using a more sophisticated method involving
    # regular expressions.  Below fixes bad spacing when the current approach
    # encounters terms like (-3+x)
    A = A.replace('( {}','(')
    A = A.replace('(\) \(','(')
    A = A.replace('\(+','\(\mathstrut+')
    A = A.replace('\(-','\(\mathstrut-')
    A = A.replace('(  ','(')
    A = A.replace('( ','(')
    A = A.replace('+\) \(O','+O')
    return A
Example #13
0
 def get_local_algebra(self, p):
     local_algebra_dict = self._data.get('loc_algebras', None)
     if local_algebra_dict is None:
         return None
     if str(p) in local_algebra_dict:
         R = PolynomialRing(QQ, 'x')
         palg = local_algebra_dict[str(p)]
         palgs = [R(str(s)) for s in palg.split(',')]
         try:
             palgstr = [
                 list2string([int(c) for c in pol.coefficients(sparse=False)])
                 for pol in palgs]
             palgrec = [db.lf_fields.lucky({'p': p, 'coeffs': map(int, c.split(','))}) for c in palgstr]
             return [
                 [
                     LF['label'],
                     latex(f),
                     int(LF['e']),
                     int(LF['f']),
                     int(LF['c']),
                     group_display_knowl(LF['n'], LF['galT']),
                     LF['t'],
                     LF['u'],
                     LF['slopes']
                 ]
                 for LF, f in zip(palgrec, palgs) ]
         except: # we were unable to find the local fields in the database
             return None
Example #14
0
def nf_knowl_guts(label):
    out = ''
    wnf = WebNumberField(label)
    if wnf.is_null():
        return 'Cannot find global number field %s' % label
    out += "Global number field %s" % label
    out += '<div>'
    out += 'Defining polynomial: '
    out += "\(%s\)" % latex(wnf.poly())
    D = wnf.disc()
    Dfact = wnf.disc_factored_latex()
    if D.abs().is_prime() or D == 1:
        Dfact = "\(%s\)" % str(D)
    else:
        Dfact = '%s = \(%s\)' % (str(D),Dfact)
    out += '<br>Discriminant: '
    out += Dfact
    out += '<br>Signature: '
    out += str(wnf.signature())
    out += '<br>Galois group: '+group_pretty_and_nTj(wnf.degree(),wnf.galois_t(), True)
    out += '<br>Class number: %s ' % str(wnf.class_number_latex())
    if wnf.can_class_number():
        out += wnf.short_grh_string()
    out += '</div>'
    out += '<div align="right">'
    out += '<a href="%s">%s home page</a>' % (str(url_for("number_fields.number_field_render_webpage", natural=label)),label)
    out += '</div>'
    return out
Example #15
0
def web_latex_split_on(x, on=['+', '-']):
    if isinstance(x, (str, unicode)):
        return x
    else:
        A = "\( %s \)" % latex(x)
        for s in on:
            A = A.replace(s, '\) ' + s + ' \( ')
    return A
Example #16
0
def render_hgm_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        C = base.getDBConnection()
        data = C.hgm.motives.find_one({'label': label})
        if data is None:
            bread = get_bread([("Search error", url_for('.search'))])
            info['err'] = "Motive " + label + " was not found in the database."
            info['label'] = label
            return search_input_error(info, bread)
        title = 'Hypergeometric Motive:' + label
        A = data['A']
        B = data['B']
        tn,td = data['t']
        t = latex(QQ(str(tn)+'/'+str(td)))
        primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]
        locinfo = data['locinfo']
        for j in range(len(locinfo)):
            locinfo[j] = [primes[j]] + locinfo[j]
            locinfo[j][2] = poly_with_factored_coeffs(locinfo[j][2], primes[j])
        hodge = data['hodge']
        prop2 = [
            ('Degree', '\(%s\)' % data['degree']),
            ('Weight',  '\(%s\)' % data['weight']),
            ('Conductor', '\(%s\)' % data['cond']),
        ]
        # Now add factorization of conductor
        Cond = ZZ(data['cond'])
        if not (Cond.abs().is_prime() or Cond == 1):
            data['cond'] = "%s=%s" % (str(Cond), factorint(data['cond']))

        info.update({
                    'A': A,
                    'B': B,
                    't': t,
                    'degree': data['degree'],
                    'weight': data['weight'],
                    'sign': data['sign'],
                    'sig': data['sig'],
                    'hodge': hodge,
                    'cond': data['cond'],
                    'req': data['req'],
                    'locinfo': locinfo
                    })
        AB_data, t_data = data["label"].split("_t")
        #AB_data = data["label"].split("_t")[0]
        friends = [("Motive family "+AB_data.replace("_"," "), url_for(".by_family_label", label = AB_data))]
        friends.append(('L-function', url_for("l_functions.l_function_hgm_page", label=AB_data, t='t'+t_data)))
#        if rffriend != '':
#            friends.append(('Discriminant root field', rffriend))


        bread = get_bread([(label, ' ')])
        return render_template("hgm-show-motive.html", credit=HGM_credit, title=title, bread=bread, info=info, properties2=prop2, friends=friends)
Example #17
0
 def latex(self, prec=None, name=None):
     if prec is None:
         qe = self.value()
     else:
         qe = self.value().truncate_powerseries(prec)
     wl = web_latex_split_on_re(qe)
     if name is not None and self.value().base_ring().degree()>1:
         return wl.replace(latex(self.value().base_ring().gen()), name)
     else:
         return wl
Example #18
0
def web_latex_poly(pol, name='x', keepzeta=False):
    """
    Change the name of the variable in a polynomial.  If keepzeta, then don't change
    the name of zetaN in the defining polynomial of a cyclotomic field.
    (keepzeta not implemented yet)
    """
    # the next few lines were adapted from the lines after line 117 of web_newforms.py 
    oldname = latex(pol.parent().gen())
    subfrom = oldname.strip() 
    subfrom = subfrom.replace("\\","\\\\")  
    subfrom = subfrom.replace("{","\\{")   # because x_{0} means somethgn in a regular expression
    if subfrom[0].isalpha():
        subfrom = "\\b" + subfrom
    subto = name.replace("\\","\\\\")  
    subto += " "
#    print "converting from",subfrom,"to", subto, "of", latex(pol)
    newpol = re.sub(subfrom, subto, latex(pol))
#    print "result is",newpol
    return web_latex_split_on_pm(newpol)
Example #19
0
def formatfield(coef):
    coef = string2list(coef)
    thefield = WebNumberField.from_coeffs(coef)
    if thefield._data is None:
        deg = len(coef) - 1
        mypol = latex(coeff_to_poly(coef))
        mypol = mypol.replace(' ','').replace('+','%2B').replace('{', '%7B').replace('}','%7d')
        mypol = '<a title = "Field missing" knowl="nf.field.missing" kwargs="poly=%s">Deg %d</a>' % (mypol,deg)
        return mypol
    return nf_display_knowl(thefield.get_label(),thefield.field_pretty())
Example #20
0
 def myhelper(self, coefmult):
     coef = string2list(coefmult[0])
     subfield = self.from_coeffs(coef)
     if subfield._data is None:
         deg = len(coef) - 1
         mypol = latex(coeff_to_poly(coef))
         mypol = mypol.replace(' ','').replace('+','%2B').replace('{', '%7B').replace('}','%7d')
         mypol = '<a title = "Field missing" knowl="nf.field.missing" kwargs="poly=%s">Deg %d</a>' % (mypol,deg)
         return [mypol, coefmult[1]]
     return [nf_display_knowl(subfield.get_label(),subfield.field_pretty()), coefmult[1]]
Example #21
0
def web_latex(x, enclose=True):
    """
    Convert input to latex string unless it's a string or unicode. The key word
    argument `enclose` indicates whether to surround the string with
    `\(` and `\)` to tag it as an equation in html.

    Note:
    if input is a factored ideal, use web_latex_ideal_fact instead.

    Example:
    >>> x = var('x')
    >>> web_latex(x**23 + 2*x + 1)
    '\\( x^{23} + 2 \\, x + 1 \\)'
    """
    if isinstance(x, (str, unicode)):
        return x
    if enclose == True:
        return "\( %s \)" % latex(x)
    return " %s " % latex(x)
Example #22
0
    def make_bsd(self):
        bsd = self.bsd = {}
        r = self.rank
        if r >= 2:
            bsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r,r)
        elif r:
            bsd['lder_name'] = "L'(E,1)"
        else:
            bsd['lder_name'] = "L(E,1)"

        bsd['reg'] = self.regulator
        bsd['omega'] = self.real_period
        bsd['sha'] = self.sha
        bsd['lder'] = self.special_value

        tamagawa_numbers = [ZZ(_ld['cp']) for _ld in self.local_data]
        cp_fac = [cp.factor() for cp in tamagawa_numbers]
        cp_fac = [latex(cp) if len(cp)<2 else '('+latex(cp)+')' for cp in cp_fac]
        bsd['tamagawa_factors'] = r'\cdot'.join(cp_fac)
        bsd['tamagawa_product'] = prod(tamagawa_numbers)
Example #23
0
    def make_bsd(self):
        bsd = self.bsd = {}
        r = self.rank
        if r >= 2:
            bsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r,r)
        elif r:
            bsd['lder_name'] = "L'(E,1)"
        else:
            bsd['lder_name'] = "L(E,1)"

        bsd['reg'] = self.regulator
        bsd['omega'] = self.real_period
        bsd['sha'] = self.sha
        bsd['lder'] = self.special_value

        tamagawa_numbers = [ZZ(_ld['cp']) for _ld in self.local_data]
        cp_fac = [cp.factor() for cp in tamagawa_numbers]
        cp_fac = [latex(cp) if len(cp)<2 else '('+latex(cp)+')' for cp in cp_fac]
        bsd['tamagawa_factors'] = r'\cdot'.join(cp_fac)
        bsd['tamagawa_product'] = prod(tamagawa_numbers)
Example #24
0
def list_factored_to_factored_poly_otherorder(sfacts_fc_list,
                                              galois=False,
                                              vari='T',
                                              p=None):
    """
        Either return the polynomial in a nice factored form,
        or return a pair, with first entry the factored polynomial
        and the second entry a list describing the Galois groups
        of the factors.
        vari allows to choose the variable of the polynomial to be returned.
    """
    gal_list = []
    order = TermOrder('M(0,-1,0,-1)')
    ZZpT = PolynomialRing(ZZ, ['p', vari], order=order)
    ZZT = PolynomialRing(ZZ, vari)
    outstr = ''
    for g, e in sfacts_fc_list:
        if galois:
            # hack because currently sage only handles monic polynomials:
            this_poly = ZZT(list(reversed(g)))
            this_degree = this_poly.degree()
            this_number_field = NumberField(this_poly, "a")
            this_gal = this_number_field.galois_group(type='pari')
            this_t_number = this_gal.group().__pari__()[2].sage()
            gal_list.append([this_degree, this_t_number])

        # casting from ZZT -> ZZpT
        if p is None:
            gtoprint = {(0, i): gi for i, gi in enumerate(g)}
        else:
            gtoprint = {}
            for i, elt in enumerate(g):
                if elt != 0:
                    val = ZZ(elt).valuation(p)
                    gtoprint[(val, i)] = elt / p**val
        glatex = latex(ZZpT(gtoprint))
        if e > 1:
            outstr += '( %s )^{%d}' % (glatex, e)
        elif len(sfacts_fc_list) > 1:
            outstr += '( %s )' % (glatex, )
        else:
            outstr += glatex

    if galois:
        # 2 factors of degree 2
        if len(sfacts_fc_list) == 2:
            if len(sfacts_fc_list[0][0]) == 3 and len(
                    sfacts_fc_list[1][0]) == 3:
                troubletest = ZZT(sfacts_fc_list[0][0]).disc() * ZZT(
                    sfacts_fc_list[1][0]).disc()
                if troubletest.is_square():
                    gal_list = [[2, 1]]
        return outstr, gal_list
    return outstr
Example #25
0
 def display_character_values(self):
     Rgens = self._get_Rgens()
     d = self.dim
     gens = [r'      <td class="dark border-right border-bottom">\(n\)</td>']
     vals = [r'      <td class="dark border-right">\(\chi(n)\)</td>']
     for j, (g, chi_g) in enumerate(self.hecke_ring_character_values):
         term = sum(Rgens[i]*chi_g[i] for i in range(d))
         latexterm = latex(term)
         color = "dark" if j%2 else "light"
         gens.append(r'      <td class="%s border-bottom">\(%s\)</td>'%(color, g))
         vals.append(r'      <td class="%s">\(%s\)</td>'%(color, latexterm))
     return '    <tr>\n%s    </tr>\n    <tr>\n%s    </tr>'%('\n'.join(gens), '\n'.join(vals))
Example #26
0
    def make_class(self):
        self.ECNF = ECNF.by_label(self.label)

        # Create a list of the curves in the class from the database
        self.db_curves = [ECNF(c) for c in db_ec().find(
            {'field_label' : self.field_label, 'conductor_label' :
             self.conductor_label, 'iso_label' : self.iso_label}).sort('number')]
        size = len(self.db_curves)

        # Extract the isogeny degree matrix from the database if possible, else create it
        if hasattr(self,'isogeny_matrix'):
            from sage.matrix.all import Matrix
            self.isogeny_matrix = Matrix(self.isogeny_matrix)
        else:
            self.isogeny_matrix = make_iso_matrix(self.db_curves)

        # Create isogeny graph:
        self.graph = make_graph(self.isogeny_matrix)
        P = self.graph.plot(edge_labels=True)
        self.graph_img = encode_plot(P)
        self.graph_link = '<img src="%s" width="200" height="150"/>' % self.graph_img
        self.isogeny_matrix_str = latex(matrix(self.isogeny_matrix))

        self.curves = [[c.short_label, c.urls['curve'], c.latex_ainvs] for c in self.db_curves]

        self.urls = {}
        self.urls['class'] = url_for(".show_ecnf_isoclass", nf = self.field_label, conductor_label=self.conductor_label, class_label = self.iso_label)
        self.urls['conductor'] = url_for(".show_ecnf_conductor", nf = self.field_label, conductor_label=self.conductor_label)
        self.urls['field'] = url_for('.show_ecnf1', nf=self.ECNF.field_label)
        self.field = self.ECNF.field
        if self.field.is_real_quadratic():
            self.hmf_label = "-".join([self.field.label,self.conductor_label,self.iso_label])
            self.urls['hmf'] = url_for('hmf.render_hmf_webpage', field_label=self.field.label, label=self.hmf_label)

        if self.field.is_imag_quadratic():
            self.bmf_label = "-".join([self.field.label,self.conductor_label,self.iso_label])


        self.friends = []
        if self.field.is_real_quadratic():
            self.friends += [('Hilbert Modular Form '+self.hmf_label, self.urls['hmf'])]
        if self.field.is_imag_quadratic():
            self.friends += [('Bianchi Modular Form %s not yet available' % self.bmf_label, '')]

        self.properties = [('Label', self.ECNF.label),
                           (None, self.graph_link),
                           ('Conductor', '%s' % self.ECNF.cond)
                           ]

        self.bread = [('Elliptic Curves ', url_for(".index")),
                      (self.ECNF.field_label, self.urls['field']),
                      (self.ECNF.conductor_label, self.urls['conductor']),
                      ('isogeny class %s' % self.ECNF.short_label, self.urls['class'])]
Example #27
0
def ll_raw(*stuff):
    """For each argument, generate a latex representation, unless the
    argument is already a string. Superfluous curly braces and \\left
    or \\right commands are removed. Moreover, the variable la is
    replaced by lambda."""
    result = ""
    for s in stuff:
        if isinstance(s, basestring):
            result += s
        else:
            result += latex_strip(latex(s))
    return result
Example #28
0
def formatfield(coef):
    coef = string2list(coef)
    thefield = WebNumberField.from_coeffs(coef)
    if thefield._data is None:
        deg = len(coef) - 1
        mypol = latex(coeff_to_poly(coef))
        mypol = mypol.replace(' ', '').replace('+', '%2B').replace(
            '{', '%7B').replace('}', '%7d')
        mypol = '<a title = "Field missing" knowl="nf.field.missing" kwargs="poly=%s">Deg %d</a>' % (
            mypol, deg)
        return mypol
    return nf_display_knowl(thefield.get_label(), thefield.field_pretty())
Example #29
0
def specialValueString(L, s, sLatex, normalization="analytic"):
    ''' Returns the LaTex to dislpay for L(s)
        Will eventually be replaced by specialValueTriple.
    '''
    number_of_decimals = 10
    val = None
    if hasattr(L, "lfunc_data"):
        s_alg = s + p2sage(L.lfunc_data['analytic_normalization'])
        for x in p2sage(L.lfunc_data['values']):
            # the numbers here are always half integers
            # so this comparison is exact
            if x[0] == s_alg:
                val = x[1]
                break
    if val is None:
        if L.fromDB:
            val = "not computed"
        else:
            val = L.sageLfunction.value(s)
    if normalization == "arithmetic":
        lfunction_value_tex = L.texname_arithmetic.replace('s)', sLatex + ')')
    else:
        lfunction_value_tex = L.texname.replace('(s', '(' + sLatex)
    # We must test for NaN first, since it would show as zero otherwise
    # Try "RR(NaN) < float(1e-10)" in sage -- GT
    if CC(val).real().is_NaN():
        return "\\[{0}=\\infty\\]".format(lfunction_value_tex)
    elif val.abs() < 1e-10:
        return "\\[{0}=0\\]".format(lfunction_value_tex)
    elif normalization == "arithmetic":
        return (lfunction_value_tex,
                latex(
                    round(val.real(), number_of_decimals) +
                    round(val.imag(), number_of_decimals) * I))
    else:
        return "\\[{0} \\approx {1}\\]".format(
            lfunction_value_tex,
            latex(
                round(val.real(), number_of_decimals) +
                round(val.imag(), number_of_decimals) * I))
Example #30
0
def print_list_of_coefficients(info):
    r"""
    Print a table of Fourier coefficients in the requested format
    """
    level = my_get(info, "level", -1, int)
    weight = my_get(info, "weight", -1, int)
    bitprec = my_get(info, "bitprec", 12, int)  # number of digits
    character = my_get(info, "character", "", str)  # int(info.get('weight',0))
    fmt = info.get("format", "q_expansion")
    if character == "":
        character = "1"
    label = info.get("label", "")
    if character.isalnum():
        character = int(character)
    else:
        return "The character '{0}' is not well-defined!".format(character)
    print "--------------"
    if label == "" or level == -1 or weight == -1:
        return "Need to specify a modular form completely!!"

    number = int(info["number"]) + 1 if "number" in info else 20
    emf_logger.debug("number = {}".format(number))
    F = WebNewForm(level=level, weight=weight, character=character, label=label, prec=number)
    if not F.has_updated():
        return ""
    if not "number" in info:
        F.prec = number = max(F.parent.sturm_bound + 1, 20)
        F.update_from_db()
    shead = "Cusp forms of weight " + str(weight) + "on \(" + latex(F.parent.group) + "\)"
    s = ""
    if (character is not None) and (character > 0):
        shead = shead + " and character \( \chi_{" + str(character) + "}\)"
        # s="<table><tr><td>"
    coefs = ""
    if fmt == "sage":
        res = []
    if number > F.max_available_prec():
        raise IndexError, "The database does not contain this many ({0}) coefficients for this modular form! We only have {1}".format(
            number, F.max_available_prec()
        )
    if fmt == "sage":
        qe = F.coefficients(range(number))
        res.append(qe)
    else:
        coefs += print_coefficients_for_one_form(F, number, info["format"], bitprec=bitprec)
    if not fmt == "sage":
        return s + "\n" + coefs
    else:
        if len(res) == 1:
            res = res[0]
        # print "res=",res
        return dumps(res)
Example #31
0
def number_field_jump(info):
    query = {'label_orig': info['jump']}
    try:
        parse_nf_string(info, query, 'jump', name="Label", qfield='label')
        # we end up parsing the string twice, but that is okay
        F1, _, _ = input_string_to_poly(info['jump'])
        if F1 and F1.list() != db.nf_fields.lookup(query['label'], 'coeffs'):
            flash_info(
                r"The requested field $\Q[{}]/\langle {}\rangle$ is isomorphic to the field below, but uses a different defining polynomial."
                .format(str(F1.parent().gen()), latex(F1)))
        return redirect(url_for(".by_label", label=query['label']))
    except ValueError:
        return redirect(url_for(".number_field_render_webpage"))
Example #32
0
def render_hgm_webpage(args):
    data = None
    info = {}
    if 'label' in args:
        label = clean_input(args['label'])
        C = base.getDBConnection()
        data = C.hgm.motives.find_one({'label': label})
        if data is None:
            bread = get_bread([("Search error", url_for('.search'))])
            info['err'] = "Motive " + label + " was not found in the database."
            info['label'] = label
            return search_input_error(info, bread)
        title = 'Hypergeometric Motive:' + label
        A = data['A']
        B = data['B']
        tn = data['t']['n']
        td = data['t']['d']
        t = latex(QQ(str(tn)+'/'+str(td)))
        primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]
        locinfo = data['locinfo']
        for j in range(len(locinfo)):
            locinfo[j] = [primes[j]] + locinfo[j]
            locinfo[j][2] = poly_with_factored_coeffs(locinfo[j][2], primes[j])
        hodge = data['hodge']
        prop2 = [
            ('Degree', '\(%s\)' % data['degree']),
            ('Weight',  '\(%s\)' % data['weight']),
            ('Conductor', '\(%s\)' % data['cond']),
        ]
        info.update({
                    'A': A,
                    'B': B,
                    't': t,
                    'degree': data['degree'],
                    'weight': data['weight'],
                    'sign': data['sign'],
                    'sig': data['sig'],
                    'hodge': hodge,
                    'cond': data['cond'],
                    'req': data['req'],
                    'locinfo': locinfo
                    })
        friends = []
#        friends = [('Galois group', "/GaloisGroup/%dT%d" % (gn, gt))]
#        if unramfriend != '':
#            friends.append(('Unramified subfield', unramfriend))
#        if rffriend != '':
#            friends.append(('Discriminant root field', rffriend))

        bread = get_bread([(label, ' ')])
        return render_template("hgm-show-motive.html", credit=HGM_credit, title=title, bread=bread, info=info, properties2=prop2, friends=friends)
Example #33
0
def render_isogeny_class(iso_class):
    info = {}
    credit = 'John Cremona'
    label = iso_class

    C = base.getDBConnection()
    data = C.ellcurves.isogeny.find_one({'label': label})
    if data is None:
        return "No such isogeny class"
    ainvs = [int(a) for a in data['ainvs_for_optimal_curve']]
    E = EllipticCurve(ainvs)
    info = {'label': label}
    info['optimal_ainvs'] = ainvs
    if 'imag' in data:
        info['imag'] = data['imag']
    if 'real' in data:
        info['real'] = data['real']
    info['rank'] = data['rank']
    info['isogeny_matrix'] = latex(matrix(eval(data['isogeny_matrix'])))
    info['modular_degree'] = data['degree']
    #info['f'] = ajax_more(E.q_eigenform, 10, 20, 50, 100, 250)
    info['f'] = web_latex(E.q_eigenform(10))
    G = E.isogeny_graph()
    n = G.num_verts()
    G.relabel(range(1, n + 1))  # proper cremona labels...
    info['graph_img'] = image_src(G.plot(edge_labels=True))
    curves = data['label_of_curves_in_the_class']
    info['curves'] = list(curves)
    info['download_qexp_url'] = url_for('download_qexp',
                                        limit=100,
                                        ainvs=','.join([str(a)
                                                        for a in ainvs]))
    info['download_all_url'] = url_for('download_all', label=str(label))
    friends = [('Elliptic Curve %s' % l, "/EllipticCurve/Q/%s" % l)
               for l in data['label_of_curves_in_the_class']]
    friends.append(('Quadratic Twist', "/quadratic_twists/%s" % (label)))
    friends.append(('Modular Form',
                    url_for("emf.render_classical_modular_form_from_label",
                            label="%s" % (label))))
    info['friends'] = friends

    t = "Elliptic Curve Isogeny Class %s" % info['label']
    bread = [('Elliptic Curves ', url_for("rational_elliptic_curves")),
             ('isogeny class %s' % info['label'], ' ')]

    return render_template("elliptic_curve/iso_class.html",
                           info=info,
                           bread=bread,
                           credit=credit,
                           title=t)
Example #34
0
def print_geometric_data_Gamma0N(N):
    r""" Print data about Gamma0(N).
    """
    G = Gamma0(N)
    s = ""
    s = "<table>"
    s += "<tr><td>index:</td><td>%s</td></tr>" % G.index()
    s += "<tr><td>genus:</td><td>%s</td></tr>" % G.genus()
    s += "<tr><td>Cusps:</td><td>\(%s\)</td></tr>" % latex(G.cusps())
    s += "<tr><td colspan=\"2\">Number of elliptic fixed points</td></tr>"
    s += "<tr><td>order 2:</td><td>%s</td></tr>" % G.nu2()
    s += "<tr><td>order 3:</td><td>%s</td></tr>" % G.nu3()
    s += "</table>"
    return s
Example #35
0
def print_geometric_data_Gamma0N(N):
    r""" Print data about Gamma0(N).
    """
    G = Gamma0(N)
    s = ""
    s = "<table>"
    s += "<tr><td>index:</td><td>%s</td></tr>" % G.index()
    s += "<tr><td>genus:</td><td>%s</td></tr>" % G.genus()
    s += "<tr><td>Cusps:</td><td>\(%s\)</td></tr>" % latex(G.cusps())
    s += "<tr><td colspan=\"2\">Number of elliptic fixed points</td></tr>"
    s += "<tr><td>order 2:</td><td>%s</td></tr>" % G.nu2()
    s += "<tr><td>order 3:</td><td>%s</td></tr>" % G.nu3()
    s += "</table>"
    return s
Example #36
0
def make_curve_latex(crv_str, nu=None):
    if "nu" not in crv_str:
        R0 = QQ
    else:
        R0 = PolynomialRing(QQ, "nu")
    R = PolynomialRing(R0, 2, "x,y")
    #F = FractionField(R)
    sides = crv_str.split("=")
    lhs = R(sides[0])
    rhs = R(sides[1])
    if nu and ("nu" in crv_str):
        S = PolynomialRing(CC, 2, 'x,y')
        # evaluate at nu, if given
        new_lhs = dict()
        new_rhs = dict()
        for m, c in lhs.dict().items():
            new_lhs[m] = c.subs(nu=nu)
        for m, c in rhs.dict().items():
            new_rhs[m] = c.subs(nu=nu)
        lhs = S(new_lhs)  # R, or something else, like CC[]?
        rhs = S(new_rhs)
    eqn_str = latex(lhs) + "=" + latex(rhs)
    return eqn_str
Example #37
0
 def display_hecke_cutters(self):
     polynomials = []
     truncated = False
     for p,F in self.hecke_cutters:
         cut = len(F) - 1
         count = 0
         while cut >= 0 and count < 8:
             if F[cut]:
                 count += 1
             cut -= 1
         if count < 8 or cut == 0 and abs(F[0]) < 100:
             F = latex(coeff_to_poly(F, 'T%s'%p))
         else:
             # truncate to the first 8 nonzero coefficients
             F = [0]*(cut+1) + F[cut+1:]
             F = latex(coeff_to_poly(F, 'T%s'%p)) + r' + \cdots'
             truncated = True
         polynomials.append(web_latex_split_on_pm(F))
     title = 'linear operator'
     if len(polynomials) > 1:
         title += 's'
     knowl = display_knowl('mf.elliptic.hecke_cutter', title=title)
     desc = "<p>This newform can be constructed as the "
     if truncated or len(polynomials) > 1:
         if len(polynomials) > 1:
             desc += "intersection of the kernels "
         else:
             desc += "kernel "
         desc += "of the following %s acting on %s:</p>\n<table>"
         desc = desc % (knowl, self.display_newspace())
         desc += "\n".join("<tr><td>%s</td></tr>" % F for F in polynomials) + "\n</table>"
     elif len(polynomials) == 1:
         desc += "kernel of the %s %s acting on %s."
         desc = desc % (knowl, polynomials[0], self.display_newspace())
     else:
         desc = r"<p>There are no other newforms in %s.</p>"%(self.display_newspace())
     return desc
Example #38
0
def specialValueString(L, s, sLatex, normalization="analytic"):
    ''' Returns the LaTex to dislpay for L(s)
        Will eventually be replaced by specialValueTriple.
    '''
    number_of_decimals = 10
    val = None
    if hasattr(L,"lfunc_data"):
        s_alg = s+p2sage(L.lfunc_data['analytic_normalization'])
        for x in p2sage(L.lfunc_data['values']):
            # the numbers here are always half integers
            # so this comparison is exact
            if x[0] == s_alg:
                val = x[1]
                break
    if val is None:
        if L.fromDB:
            val = "not computed"
        else:
            val = L.sageLfunction.value(s)
    if normalization == "arithmetic":
        lfunction_value_tex = L.texname_arithmetic.replace('s)',  sLatex + ')')
    else:
        lfunction_value_tex = L.texname.replace('(s', '(' + sLatex)
    # We must test for NaN first, since it would show as zero otherwise
    # Try "RR(NaN) < float(1e-10)" in sage -- GT
    if CC(val).real().is_NaN():
        return "\\[{0}=\\infty\\]".format(lfunction_value_tex)
    elif val.abs() < 1e-10:
        return "\\[{0}=0\\]".format(lfunction_value_tex)
    elif normalization == "arithmetic":
        return(lfunction_value_tex,
               latex(round(val.real(), number_of_decimals)
                         + round(val.imag(), number_of_decimals) * I))
    else:
        return "\\[{0} \\approx {1}\\]".format(lfunction_value_tex,
                                               latex(round(val.real(), number_of_decimals)
                                                     + round(val.imag(), number_of_decimals) * I))
Example #39
0
 def jacobi_sum(self, val):
     mod, num = self.modulus, self.number
     val = int(val[0])
     psi = self.H[val]
     chi = self.chi.sage_character()
     psi = psi.sage_character()
     jacobi_sum = chi.jacobi_sum(psi)
     chitex = self.char2tex(mod, num, tag=False)
     psitex = self.char2tex(mod, val, tag=False)
     Gtex = '\Z/%s\Z' % mod
     chitexr = self.char2tex(mod, num, 'r', tag=False)
     psitex1r = self.char2tex(mod, val, '1-r', tag=False)
     deftex = r'\sum_{r\in %s} %s %s'%(Gtex,chitexr,psitex1r)
     from sage.all import latex
     return r"\( \displaystyle J(%s,%s) = %s = %s.\)" % (chitex, psitex, deftex, latex(jacobi_sum))
Example #40
0
 def myhelper(self, coefmult):
     coef = string2list(coefmult[0])
     subfield = self.from_coeffs(coef)
     if subfield._data is None:
         deg = len(coef) - 1
         mypol = latex(coeff_to_poly(coef))
         mypol = mypol.replace(' ', '').replace('+', '%2B').replace(
             '{', '%7B').replace('}', '%7d')
         mypol = '<a title = "Field missing" knowl="nf.field.missing" kwargs="poly=%s">Deg %d</a>' % (
             mypol, deg)
         return [mypol, coefmult[1]]
     return [
         nf_display_knowl(subfield.get_label(), subfield.field_pretty()),
         coefmult[1]
     ]
Example #41
0
 def get_local_algebra(self, p):
     local_algebra_dict = self._data.get('loc_algebras', None)
     if local_algebra_dict is None:
         return None
     if str(p) in local_algebra_dict:
         R = PolynomialRing(QQ, 'x')
         palg = local_algebra_dict[str(p)]
         palgs = [R(str(s)) for s in palg.split(',')]
         palgs = [list2string([int(c) for c in 
             pol.coefficients(sparse=False)]) for pol in palgs]
         palgs = [lfdb().find_one({'p': p, 'coeffs': c}) for c in palgs]
         return [[f['label'], latex(R(string2list(f['coeffs']))), 
             int(f['e']), int(f['f']),int(f['c']),
             group_display_knowl(f['gal'][0], f['gal'][1], db()),
             f['t'],f['u'],f['slopes']]
             for f in palgs]
     return None
Example #42
0
def web_latex_split_on(x, on=['+', '-']):
    r"""
    Convert input into a latex string. A different latex surround `\(` `\)` is
    used, with splits occuring at `on` (+ - by default).

    Example:
    >>> x = var('x')
    >>> web_latex_split_on(x**2 + 1)
    '\\( x^{2} \\) + \\(  1 \\)'
    """
    if isinstance(x, string_types):
        return x
    else:
        A = r"\( %s \)" % latex(x)
        for s in on:
            A = A.replace(s, r'\) ' + s + r' \( ')
    return A
Example #43
0
def bigpoly_knowl(f, nterms_cutoff=8, bigint_cutoff=12, var='x'):
    lng = web_latex(coeff_to_poly(f, var))
    if bigint_cutoff:
        lng = make_bigint(lng, bigint_cutoff, max_width=70).replace('"',"'")
    if len([c for c in f if c != 0]) > nterms_cutoff:
        short = "%s^{%s}" % (latex(coeff_to_poly([0,1], var)), len(f) - 1)
        i = len(f) - 2
        while i >= 0 and f[i] == 0:
            i -= 1
        if i >= 0: # nonzero terms
            if f[i] > 0:
                short += r" + \cdots"
            else:
                short += r" - \cdots"
        return r'<a title="[poly]" knowl="dynamic_show" kwargs="%s">\(%s\)</a>'%(lng, short)
    else:
        return lng
Example #44
0
def specialValueTriple(L, s, sLatex_analytic, sLatex_arithmetic):
    ''' Returns [L_arithmetic, L_analytic, L_val]
        Currently only used for genus 2 curves
        and Dirichlet characters.
        Eventually want to use for all L-functions.
    '''
    number_of_decimals = 10
    val = None
    if hasattr(L, "lfunc_data"):
        s_alg = s + p2sage(L.lfunc_data['analytic_normalization'])
        if 'values' in L.lfunc_data.keys():
            for x in p2sage(L.lfunc_data['values']):
                # the numbers here are always half integers
                # so this comparison is exact
                if x[0] == s_alg:
                    val = x[1]
                    break
    if val is None:
        if L.fromDB:
            val = "not computed"
        else:
            val = L.sageLfunction.value(s)
    # We must test for NaN first, since it would show as zero otherwise
    # Try "RR(NaN) < float(1e-10)" in sage -- GT

    lfunction_value_tex_arithmetic = L.texname_arithmetic.replace(
        's)', sLatex_arithmetic + ')')
    lfunction_value_tex_analytic = L.texname.replace('(s',
                                                     '(' + sLatex_analytic)

    try:
        if CC(val).real().is_NaN():
            Lval = "\\infty"
        elif val.abs() < 1e-10:
            Lval = "0"
        else:
            Lval = latex(
                round(val.real(), number_of_decimals) +
                round(val.imag(), number_of_decimals) * I)
    except (TypeError, NameError):
        Lval = val  # if val is text

    return [lfunction_value_tex_analytic, lfunction_value_tex_arithmetic, Lval]
Example #45
0
def raw_typeset(raw, typeset='', extra='', compressed=False):
    r"""
    Return a span with typeset material which will toggle to raw material
    when an icon is clicked on.

    The raw version can be a string, or a sage object which will stringify
    properly.

    If the typeset version can be gotten by just applying latex to the raw
    version, the typeset version can be omitted.

    If there is a string to appear between the toggled text and the icon,
    it can be given in the argument extra

    If one of these appear on a page, then the icon to toggle all of them
    on the page will appear in the upper right corner of the body of the
    page.
    """
    if not typeset:
        typeset = r'\({}\)'.format(latex(raw))

    typeset = f'<span class="tset-container">{typeset}</span>'
    # clean white space
    raw = re.sub(r'\s+', ' ', str(raw).strip())
    raw = f'<textarea rows="1" cols="{len(raw)}" class="raw-container">{raw}</textarea>'

    # the doublesclick behavior is set on load in javascript
    out = f"""
<span class="raw-tset-container tset {"compressed" if compressed else ""}">
    {typeset}
    {raw}
    {extra}
    <span class="raw-tset-copy-btn" onclick="copyrawcontainer(this)">
        <img alt="Copy content"
        class="tset-icon">
    </span>
    <span class="raw-tset-toggle" onclick="iconrawtset(this)">
        <img alt="Toggle raw display"
        class="tset-icon"
    </span>
</span>"""
    return out
Example #46
0
def web_latex_split_on_re(x, r = '(q[^+-]*[+-])'):
    r"""
    Convert input into a latex string, with splits into separate latex strings
    occurring on given regex `r`.
    CAUTION: this gives a different result than web_latex_split_on_pm

    Example:
    >>> x = var('x')
    >>> web_latex_split_on_re(x**2 + 1)
    '\\(x^{2} \\) \\(\\mathstrut+  1 \\)'
    """

    def insert_latex(s):
        return s.group(1) + r'\) \('

    if isinstance(x, string_types):
        return x
    else:
        A = r"\( %s \)" % latex(x)
        c = re.compile(r)
        A = A.replace(r'+', r'\) \( {}+ ')
        A = A.replace(r'-', r'\) \( {}- ')
#        A = A.replace('\left(','\left( {}\\right.') # parantheses needs to be balanced
#        A = A.replace('\\right)','\left.\\right)')
        A = A.replace(r'\left(',r'\bigl(')
        A = A.replace(r'\right)',r'\bigr)')
        A = c.sub(insert_latex, A)

    # the above will be re-done using a more sophisticated method involving
    # regular expressions.  Below fixes bad spacing when the current approach
    # encounters terms like (-3+x)
    A = A.replace(r'( {}', r'(')
    A = A.replace(r'(\) \(', r'(')
    A = A.replace(r'\(+', r'\(\mathstrut+')
    A = A.replace(r'\(-', r'\(\mathstrut-')
    A = A.replace(r'(  ', r'(')
    A = A.replace(r'( ', r'(')
    A = A.replace(r'+\) \(O', r'+O')
    return A
Example #47
0
    def jacobi_sum(self, val):

        mod, num = self.modulus, self.number

        try:
            val = int(val)
        except ValueError:
            raise Warning ("n must be a positive integer coprime to the modulus {} and no greater than it".format(mod))
        if gcd(mod, val) > 1:
            raise Warning ("n must be coprime to the modulus : %s"%mod)
        if val > mod:
            raise Warning ("n must be less than the modulus : %s"%mod)
        if val < 0:
            raise Warning ("n must be positive")

        chi_values_data = db.char_dir_values.lookup(
            "{}.{}".format(mod, num)
        )
        chi_valuepairs = chi_values_data['values_gens']
        chi_genvalues = [int(v) for g, v in chi_valuepairs]
        chi = self.chi.sage_character(self.order, chi_genvalues)

        psi = ConreyCharacter(self.modulus, val)
        psi_values_data = db.char_dir_values.lookup(
            "{}.{}".format(self.modulus, val)
        )
        psi_valuepairs = psi_values_data['values_gens']
        psi_genvalues = [int(v) for g, v in psi_valuepairs]
        psi = psi.sage_character(self.order, psi_genvalues)

        jacobi_sum = chi.jacobi_sum(psi)
        chitex = self.char2tex(mod, num, tag=False)
        psitex = self.char2tex(mod, val, tag=False)
        Gtex = r'\Z/%s\Z' % mod
        chitexr = self.char2tex(mod, num, 'r', tag=False)
        psitex1r = self.char2tex(mod, val, '1-r', tag=False)
        deftex = r'\sum_{r\in %s} %s %s'%(Gtex,chitexr,psitex1r)
        return r"\( \displaystyle J(%s,%s) = %s = %s \)" % (chitex, psitex, deftex, latex(jacobi_sum))
Example #48
0
    def _latex_(self):
        r""" Returns LaTeX string representation of self. 

        EXAMPLES::


            sage: WR=WeilRepDiscriminantForm(2,dual=False)
            sage: latex(WR)
            Weil representation of the discriminant form given by $\mathbb{Z}/4\mathbb{Z}$ with quadratic form $Q(x)=2\,x^{2} \mathrm{mod} 1$.


        """
        
        s="\\begin{verbatim}\\end{verbatim}"
        if self._is_dual_rep:
            s+="Dual of "
        else:
            s+=""
            #        s+="Weil representation of the discriminant form given by  $\\mathbb{Z}/"+str(2*self._N)+"\\mathbb{Z}$ \\text{ with quadratic form } Q(x)="+latex(self._N)+"\\,x^{2}\\, \\mathrm{mod}\\, 1$ .\end{verbatim}}"
        s+="Weil representation of the discriminant form given by  $\\mathbb{Z}/"+str(2*self._N)+"\\mathbb{Z}$"
        s+=" with quadratic form  $Q(x)="+latex(self._N)+"\\,x^{2}\\, \\mathrm{mod}\\, 1$."
            
        return s
Example #49
0
def web_latex_split_on_pm(x):
    r"""
    Convert input into a latex string, with specific handling of expressions
    including `+` and `-`.

    Example:
    >>> x = var('x')
    >>> web_latex_split_on_pm(x**2 + 1)
    '\\(x^{2} \\) \\(\\mathstrut +\\mathstrut  1 \\)'
    """
    on = ['+', '-']
 #   A = "\( %s \)" % latex(x)
    try:
        A = r"\(" + x + r"\)"  # assume we are given LaTeX to split on
    except:
        A = r"\( %s \)" % latex(x)

       # need a more clever split_on_pm that inserts left and right properly
    A = A.replace(r"\left","")
    A = A.replace(r"\right","")
    for s in on:
  #      A = A.replace(s, r'\) ' + s + r' \( ')
   #     A = A.replace(s, r'\) ' + r' \( \mathstrut ' + s )
        A = A.replace(s, r'\)' + r' \(\mathstrut ' + s + r'\mathstrut ')
    # the above will be re-done using a more sophisticated method involving
    # regular expressions.  Below fixes bad spacing when the current approach
    # encounters terms like (-3+x)
    for s in on:
        A = A.replace(r'(\) \(\mathstrut ' + s, '(' + s)
    A = A.replace(r'( {}', r'(')
    A = A.replace(r'(\) \(', r'(')
    A = A.replace(r'\(+', r'\(\mathstrut+')
    A = A.replace(r'\(-', r'\(\mathstrut-')
    A = A.replace(r'(  ', r'(')
    A = A.replace(r'( ', r'(')

    return A
Example #50
0
def render_hecke_algebras_webpage_l_adic(**args):
    data = None
    if 'orbit_label' in args and 'prime' in args:
        lab = clean_input(args.get('orbit_label'))
        if lab != args.get('orbit_label'):
            base_lab = ".".join([split(lab)[i] for i in [0, 1, 2]])
            return redirect(
                url_for('.render_hecke_algebras_webpage', label=base_lab), 301)
        try:
            ell = int(args.get('prime'))
        except ValueError:
            base_lab = ".".join([split(lab)[i] for i in [0, 1, 2]])
            return redirect(
                url_for('.render_hecke_algebras_webpage', label=base_lab), 301)
        data = db.hecke_ladic.lucky({'orbit_label': lab, 'ell': ell})
    if data is None:
        t = "Hecke algebra search error"
        bread = [('HeckeAlgebra', url_for(".hecke_algebras_render_webpage"))]
        flash_error(
            "%s is not a valid label for the &#x2113;-adic information for an Hecke algebra orbit in the database.",
            lab)
        return render_template("hecke_algebras-error.html",
                               title=t,
                               properties=[],
                               bread=bread,
                               learnmore=learnmore_list())
    info = {}
    info.update(data)

    proj = [
        'index', 'orbit_label', 'ell', 'idempotent', 'field', 'structure',
        'properties', 'operators'
    ]
    res = list(
        db.hecke_ladic.search(
            {
                'level': data['level'],
                'weight': data['weight'],
                'orbit_label': data['orbit_label'],
                'ell': data['ell']
            }, proj))

    for f in res:
        if f['idempotent'] != "":
            dim = len(sage_eval(f['idempotent']))
            l_max = sage_eval(f['idempotent'])[0][0].ndigits()
            if dim > 4 or l_max > 5:
                f['idempotent_display'] = []
            elif dim == 1:
                f['idempotent_display'] = sage_eval(f['idempotent'])[0][0]
            else:
                f['idempotent_display'] = latex(
                    matrix(sage_eval(f['idempotent'])))
        else:
            f['idempotent_display'] = latex(matrix([[1]]))
        del f['idempotent']
        f['download_id'] = [
            (i,
             url_for(".render_hecke_algebras_webpage_ell_download",
                     orbit_label=f['orbit_label'],
                     index=f['index'],
                     prime=f['ell'],
                     lang=i,
                     obj='idempotents')) for i in ['magma', 'sage']
        ]  # for 'gp' the code does not work, since p-adics are not implemented
        field = f.pop('field')
        if field is not None:
            f['deg'] = field[1]
            f['field_poly'] = field[2]
        structure = f.pop('structure')
        if structure is not None:
            f['dim'] = structure[0]
            f['num_gen'] = structure[1]
            s2 = sage_eval(structure[2])
            f['gens'] = [[int(s2.index(i) + 1), str(i)] for i in s2]
            f['rel'] = sage_eval(structure[3])
        properties = f.pop('properties')
        if properties is not None:
            f['grading'] = properties[0]
            f['gorenstein_def'] = properties[1]
            f['gorenstein'] = "yes" if properties[1] == 0 else "no"
        operators = f.pop('operators')
        if operators is not None:
            f['operators_mod_l'] = operators
            f['num_hecke_op'] = len(operators)
            f['size_op'] = size = sqrt(len(operators[0]))
            if size > 4:
                f['operators_mod_l_display'] = []
            elif size == 1:
                f['operators_mod_l_display'] = [[i + 1, operators[i][0]]
                                                for i in range(10)]
            else:
                f['operators_mod_l_display'] = [[
                    i + 1, latex(matrix(size, size, operators[i]))
                ] for i in range(5)]
            f['download_op'] = [
                (lang,
                 url_for(".render_hecke_algebras_webpage_ell_download",
                         orbit_label=f['orbit_label'],
                         index=f['index'],
                         prime=f['ell'],
                         lang=lang,
                         obj='operators')) for lang in ['magma', 'sage']
            ]  # for 'gp' the code does not work

    info['num_l_adic_orbits'] = len(res)
    info['l_adic_orbits'] = res
    info['level'] = int(data['level'])
    info['weight'] = int(data['weight'])
    info['base_lab'] = ".".join(
        [split(data['orbit_label'])[i] for i in [0, 1, 2]])
    info['orbit_label'] = str(data['orbit_label'])
    info['ell'] = int(data['ell'])

    bread = [('HeckeAlgebra', url_for(".hecke_algebras_render_webpage")),
             ('%s' % info['base_lab'],
              url_for('.render_hecke_algebras_webpage',
                      label=info['base_lab'])), ('%s' % info['ell'], ' ')]
    credit = hecke_algebras_credit
    info['properties'] = [('Level', '%s' % info['level']),
                          ('Weight', '%s' % info['weight']),
                          ('Characteristic', '%s' % info['ell']),
                          ('Orbit label', '%s' % info['orbit_label'])]
    info['friends'] = [('Modular form ' + info['base_lab'],
                        url_for("cmf.by_url_space_label",
                                level=info['level'],
                                weight=info['weight'],
                                char_orbit_label='a'))]

    t = "%s-adic and mod %s data for the Hecke algebra orbit %s" % (
        info['ell'], info['ell'], info['orbit_label'])
    return render_template("hecke_algebras_l_adic-single.html",
                           info=info,
                           credit=credit,
                           title=t,
                           bread=bread,
                           properties=info['properties'],
                           learnmore=learnmore_list(),
                           friends=info['friends'],
                           KNOWL_ID='hecke_algebra_l_adic.%s' %
                           (info['orbit_label']))
Example #51
0
def render_hecke_algebras_webpage(**args):
    data = None
    if 'label' in args:
        lab = clean_input(args.get('label'))
        if lab != args.get('label'):
            return redirect(
                url_for('.render_hecke_algebras_webpage', label=lab), 301)
        data = db.hecke_algebras.lookup(lab)
    if data is None:
        t = "Hecke algebra search error"
        bread = [('HeckeAlgebra', url_for(".hecke_algebras_render_webpage"))]
        flash_error(
            "%s is not a valid label for a Hecke algebra in the database.",
            lab)
        return render_template("hecke_algebras-error.html",
                               title=t,
                               properties=[],
                               bread=bread,
                               learnmore=learnmore_list())
    info = {}
    info.update(data)

    bread = [('HeckeAlgebra', url_for(".hecke_algebras_render_webpage")),
             ('%s' % data['label'], ' ')]
    credit = hecke_algebras_credit
    info['level'] = int(data['level'])
    info['weight'] = int(data['weight'])
    info['num_orbits'] = int(data['num_orbits'])
    dim_count = "not available"

    proj = [
        'orbit_label', 'hecke_op', 'num_hecke_op', 'Zbasis', 'discriminant',
        'disc_fac', 'Qbasis', 'Qalg_gen'
    ]
    orb = list(db.hecke_orbits.search({'parent_label': data['label']}, proj))
    if orb:
        #consistency check
        if len(orb) != int(data['num_orbits']):
            return search_input_error(info)

        dim_count = 0
        for v in orb:
            ops = sage_eval(v['hecke_op'])
            dim = int(matrix(ops[0]).nrows())
            dim_count += dim
            if dim > 4:
                v['hecke_op_display'] = []
            elif dim == 1:
                v['hecke_op_display'] = [[i + 1, ops[i][0][0]]
                                         for i in range(10)]
            else:
                v['hecke_op_display'] = [[i + 1, latex(matrix(ops[i]))]
                                         for i in range(5)]
            v['download_op'] = [
                (lang,
                 url_for(".render_hecke_algebras_webpage_download",
                         orbit_label=v['orbit_label'],
                         lang=lang,
                         obj='operators')) for lang in ['gp', 'magma', 'sage']
            ]
            if v['Zbasis'] is None:
                for key in [
                        'Zbasis', 'discriminant', 'disc_fac', 'Qbasis',
                        'Qalg_gen'
                ]:
                    del v[key]
            else:
                v['Zbasis'] = [[int(i) for i in j] for j in v['Zbasis']]
                v['disc_fac'] = [[int(i) for i in j] for j in v['disc_fac']]
                if dim > 4:
                    v['gen_display'] = []
                elif dim == 1:
                    v['gen_display'] = [v['Zbasis'][0][0]]
                else:
                    v['gen_display'] = [
                        latex(matrix(dim, dim, v['Zbasis'][i]))
                        for i in range(dim)
                    ]
                v['inner_twists'] = "not available"  # not yet in the database
                v['download_gen'] = [
                    (lang,
                     url_for(".render_hecke_algebras_webpage_download",
                             orbit_label=v['orbit_label'],
                             lang=lang,
                             obj='gen')) for lang in ['gp', 'magma', 'sage']
                ]
        info['orbits'] = orb

    info['dim_alg'] = dim_count
    info['l_adic'] = l_range
    info['properties'] = [('Label', '%s' % info['label']),
                          ('Level', '%s' % info['level']),
                          ('Weight', '%s' % info['weight'])]
    if info['num_orbits'] != 0:
        info['friends'] = [('Newforms space ' + info['label'],
                            url_for("cmf.by_url_space_label",
                                    level=info['level'],
                                    weight=info['weight'],
                                    char_orbit_label='a'))]
    else:
        info['friends'] = []
    t = "Hecke algebra %s" % info['label']
    return render_template("hecke_algebras-single.html",
                           info=info,
                           credit=credit,
                           title=t,
                           bread=bread,
                           properties=info['properties'],
                           learnmore=learnmore_list(),
                           friends=info['friends'],
                           KNOWL_ID='hecke_algebra.%s' % (info['label']))
Example #52
0
    def make_mwbsd(self):
        mwbsd = self.mwbsd = db.ec_mwbsd.lookup(self.lmfdb_label)

        # Some components are in the main table:

        mwbsd['analytic_rank'] = r = self.analytic_rank
        mwbsd['torsion'] = self.torsion
        tamagawa_numbers = [ld['tamagawa_number'] for ld in self.local_data]
        mwbsd['tamagawa_product'] = prod(tamagawa_numbers)
        if mwbsd['tamagawa_product'] > 1:
            cp_fac = [ZZ(cp).factor() for cp in tamagawa_numbers]
            cp_fac = [
                latex(cp) if len(cp) < 2 else '(' + latex(cp) + ')'
                for cp in cp_fac
            ]
            mwbsd['tamagawa_factors'] = r'\cdot'.join(cp_fac)
        else:
            mwbsd['tamagawa_factors'] = None

        try:
            mwbsd['rank'] = self.rank
            mwbsd['reg'] = self.regulator
            mwbsd['sha'] = self.sha
            mwbsd['sha2'] = latex_sha(self.sha)
        except AttributeError:
            mwbsd['rank'] = '?'
            mwbsd['reg'] = '?'
            mwbsd['sha'] = '?'
            mwbsd['sha2'] = '?'
            mwbsd['regsha'] = (mwbsd['special_value'] * self.torsion**2) / (
                mwbsd['tamagawa_product'] * mwbsd['real_period'])
            if r <= 1:
                mwbsd['rank'] = r

        # Integral points

        xintcoords = mwbsd['xcoord_integral_points']
        a1, _, a3, _, _ = ainvs = self.ainvs
        if a1 or a3:
            int_pts = sum([[(x, y) for y in make_y_coords(ainvs, x)]
                           for x in xintcoords], [])
            mwbsd['int_points'] = raw_typeset(
                ', '.join(str(P) for P in int_pts),
                ', '.join(web_latex(P) for P in int_pts))
        else:
            int_pts = [(x, make_y_coords(ainvs, x)[0]) for x in xintcoords]
            raw_form = sum([[P, (P[0], -P[1])] if P[1] else [P]
                            for P in int_pts], [])
            raw_form = ', '.join(str(P) for P in raw_form)
            mwbsd['int_points'] = raw_typeset(
                raw_form, ', '.join(pm_pt(P) for P in int_pts))

        # Generators (mod torsion) and heights:
        mwbsd['generators'] = [
            raw_typeset(weighted_proj_to_affine_point(P))
            for P in mwbsd['gens']
        ] if mwbsd['ngens'] else ''

        # Torsion structure and generators:
        if mwbsd['torsion'] == 1:
            mwbsd['tor_struct'] = ''
            mwbsd['tor_gens'] = ''
        else:
            mwbsd['tor_struct'] = r' \times '.join(
                r'\Z/{%s}\Z' % n for n in self.torsion_structure)
            tor_gens_tmp = [
                weighted_proj_to_affine_point(P)
                for P in mwbsd['torsion_generators']
            ]
            mwbsd['tor_gens'] = raw_typeset(
                ', '.join(str(P) for P in tor_gens_tmp),
                ', '.join(web_latex(P) for P in tor_gens_tmp))

        # BSD invariants
        if r >= 2:
            mwbsd['lder_name'] = "L^{(%s)}(E,1)/%s!" % (r, r)
        elif r:
            mwbsd['lder_name'] = "L'(E,1)"
        else:
            mwbsd['lder_name'] = "L(E,1)"
Example #53
0
    def make_curve(self):
        data = self.data = {}
        lmfdb_label = self.lmfdb_label

        # Some data fields of self are just those from the database.
        # These only need some reformatting.

        data['ainvs'] = self.ainvs
        data['conductor'] = N = self.conductor
        data['j_invariant'] = QQ(tuple(self.jinv))
        data['j_inv_factor'] = latex(0)
        if data['j_invariant']:  # don't factor 0
            data['j_inv_factor'] = latex(data['j_invariant'].factor())
        data['j_inv_latex'] = web_latex(data['j_invariant'])

        # retrieve local reduction data from table ec_localdata:

        self.local_data = local_data = list(
            db.ec_localdata.search({"lmfdb_label": lmfdb_label}))
        for ld in local_data:
            if ld['kodaira_symbol'] <= -14:
                # Work around bug in Sage's latex
                ld['kod'] = 'I_{%s}^{*}' % (-ld['kodaira_symbol'] - 4)
            else:
                ld['kod'] = latex(KodairaSymbol(ld['kodaira_symbol']))

        Nfac = Factorization([(ZZ(ld['prime']), ld['conductor_valuation'])
                              for ld in local_data])
        Dfac = Factorization([(ZZ(ld['prime']), ld['discriminant_valuation'])
                              for ld in local_data],
                             unit=ZZ(self.signD))
        data['disc_factor'] = latex(Dfac)
        data['disc'] = D = Dfac.value()
        data['cond_factor'] = latex(Nfac)
        data['disc_latex'] = web_latex(D)
        data['cond_latex'] = web_latex(N)

        # retrieve data about MW rank, generators, heights and
        # torsion, leading term of L-function & other BSD data from
        # table ec_mwbsd:

        self.make_mwbsd()

        # latex equation:

        latexeqn = latex_equation(self.ainvs)
        data['equation'] = raw_typeset(unlatex(latexeqn), latexeqn)

        # minimal quadratic twist:

        data['minq_D'] = minqD = self.min_quad_twist_disc
        data['minq_label'] = db.ec_curvedata.lucky(
            {'ainvs': self.min_quad_twist_ainvs},
            projection='lmfdb_label'
            if self.label_type == 'LMFDB' else 'Clabel')
        data['minq_info'] = '(itself)' if minqD == 1 else '(by {})'.format(
            minqD)

        # modular degree:

        try:
            data['degree'] = ZZ(self.degree)  # convert None to 0
        except AttributeError:  # if not computed, db has Null and the attribute is missing
            data['degree'] = 0  # invalid, but will be displayed nicely

        # coefficients of modular form / L-series:

        classdata = db.ec_classdata.lookup(self.lmfdb_iso)
        data['an'] = classdata['anlist']
        data['ap'] = classdata['aplist']

        # mod-p Galois images:

        data['galois_data'] = list(
            db.ec_galrep.search({'lmfdb_label': lmfdb_label}))
        for gd in data[
                'galois_data']:  # remove the prime prefix from each image code
            gd['image'] = trim_galois_image_code(gd['image'])

        # CM and Endo ring:

        data['CMD'] = self.cm
        data['CM'] = "no"
        data['EndE'] = r"\(\Z\)"
        if self.cm:
            data['cm_ramp'] = [
                p for p in ZZ(self.cm).support() if not p in self.nonmax_primes
            ]
            data['cm_nramp'] = len(data['cm_ramp'])
            if data['cm_nramp'] == 1:
                data['cm_ramp'] = data['cm_ramp'][0]
            else:
                data['cm_ramp'] = ", ".join(str(p) for p in data['cm_ramp'])
            data['cm_sqf'] = ZZ(self.cm).squarefree_part()

            data['CM'] = r"yes (\(D=%s\))" % data['CMD']
            if data['CMD'] % 4 == 0:
                d4 = ZZ(data['CMD']) // 4
                data['EndE'] = r"\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = r"\(\Z[(1+\sqrt{%s})/2]\)" % data['CMD']
            data['ST'] = st_link_by_name(1, 2, 'N(U(1))')
        else:
            data['ST'] = st_link_by_name(1, 2, 'SU(2)')

        # Isogeny degrees:

        cond, iso, num = split_lmfdb_label(lmfdb_label)
        self.class_deg = classdata['class_deg']
        self.one_deg = ZZ(self.class_deg).is_prime()
        isodegs = [str(d) for d in self.isogeny_degrees if d > 1]
        if len(isodegs) < 3:
            data['isogeny_degrees'] = " and ".join(isodegs)
        else:
            data['isogeny_degrees'] = " and ".join(
                [", ".join(isodegs[:-1]), isodegs[-1]])

        self.make_twoadic_data()

        # Optimality

        # The optimal curve in the class is the curve whose Cremona
        # label ends in '1' except for '990h' which was labelled
        # wrongly long ago. This is proved for N up to
        # OPTIMALITY_BOUND (and when there is only one curve in an
        # isogeny class, obviously) and expected for all N.

        # Column 'optimality' is 1 for certainly optimal curves, 0 for
        # certainly non-optimal curves, and is n>1 if the curve is one
        # of n in the isogeny class which may be optimal given current
        # knowledge.

        # Column "manin_constant' is the correct Manin constant
        # assuming that the optimal curve in the class is known, or
        # otherwise if it is the curve with (Cremona) number 1.

        # The code here allows us to update the display correctly by
        # changing one line in this file (defining OPTIMALITY_BOUND)
        # without changing the data.

        data['optimality_bound'] = OPTIMALITY_BOUND
        self.cremona_bound = CREMONA_BOUND
        if N < CREMONA_BOUND:
            data[
                'manin_constant'] = self.manin_constant  # (conditional on data['optimality_known'])
        else:
            data['manin_constant'] = 0  # (meaning not available)

        if N < OPTIMALITY_BOUND:

            data['optimality_code'] = int(
                self.Cnumber == (3 if self.Ciso == '990h' else 1))
            data['optimality_known'] = True
            data['manin_known'] = True
            if self.label_type == 'Cremona':
                data[
                    'optimal_label'] = '990h3' if self.Ciso == '990h' else self.Ciso + '1'
            else:
                data[
                    'optimal_label'] = '990.i3' if self.lmfdb_iso == '990.i' else self.lmfdb_iso + '1'

        elif N < CREMONA_BOUND:

            data['optimality_code'] = self.optimality
            data['optimality_known'] = (self.optimality < 2)

            if self.optimality == 1:
                data['manin_known'] = True
                data[
                    'optimal_label'] = self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label
            else:
                if self.Cnumber == 1:
                    data['manin_known'] = False
                    data[
                        'optimal_label'] = self.Clabel if self.label_type == 'Cremona' else self.lmfdb_label
                else:
                    # find curve #1 in this class and its optimailty code:
                    opt_curve = db.ec_curvedata.lucky(
                        {
                            'Ciso': self.Ciso,
                            'Cnumber': 1
                        },
                        projection=['Clabel', 'lmfdb_label', 'optimality'])
                    data['manin_known'] = (opt_curve['optimality'] == 1)
                    data['optimal_label'] = opt_curve[
                        'Clabel' if self.label_type ==
                        'Cremona' else 'lmfdb_label']

        else:
            data['optimality_code'] = None
            data['optimality_known'] = False
            data['manin_known'] = False
            data['optimal_label'] = ''

        # p-adic data:

        data['p_adic_primes'] = [
            p for i, p in enumerate(prime_range(5, 100))
            if (N * data['ap'][i]) % p != 0
        ]

        data['p_adic_data_exists'] = False
        if data['optimality_code'] == 1:
            data['p_adic_data_exists'] = db.ec_padic.exists(
                {'lmfdb_iso': self.lmfdb_iso})

        # Iwasawa data (where present)

        self.make_iwasawa()

        # Torsion growth data (where present)

        self.make_torsion_growth()

        # Newform

        rawnewform = str(PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True))
        data['newform'] = raw_typeset(
            rawnewform,
            web_latex(PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True)))
        data['newform_label'] = self.newform_label = ".".join(
            [str(cond), str(2), 'a', iso])
        self.newform_link = url_for("cmf.by_url_newform_label",
                                    level=cond,
                                    weight=2,
                                    char_orbit_label='a',
                                    hecke_orbit=iso)
        self.newform_exists_in_db = db.mf_newforms.label_exists(
            self.newform_label)
        self._code = None

        if self.label_type == 'Cremona':
            self.class_url = url_for(".by_ec_label", label=self.Ciso)
            self.class_name = self.Ciso
        else:
            self.class_url = url_for(".by_ec_label", label=self.lmfdb_iso)
            self.class_name = self.lmfdb_iso
        data['class_name'] = self.class_name
        data['Cnumber'] = self.Cnumber if N < CREMONA_BOUND else None

        self.friends = [('Isogeny class ' + self.class_name, self.class_url),
                        ('Minimal quadratic twist %s %s' %
                         (data['minq_info'], data['minq_label']),
                         url_for(".by_ec_label", label=data['minq_label'])),
                        ('All twists ',
                         url_for(".rational_elliptic_curves",
                                 jinv=data['j_invariant']))]

        lfun_url = url_for("l_functions.l_function_ec_page",
                           conductor_label=N,
                           isogeny_class_label=iso)
        origin_url = lfun_url.lstrip('/L/').rstrip('/')

        if db.lfunc_instances.exists({'url': origin_url}):
            self.friends += [('L-function', lfun_url)]
        else:
            self.friends += [('L-function not available', "")]

        if not self.cm:
            if N <= 300:
                self.friends += [('Symmetric square L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='2',
                                          conductor=N,
                                          isogeny=iso))]
            if N <= 50:
                self.friends += [('Symmetric cube L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='3',
                                          conductor=N,
                                          isogeny=iso))]
        if self.newform_exists_in_db:
            self.friends += [('Modular form ' + self.newform_label,
                              self.newform_link)]

        self.downloads = [('q-expansion to text',
                           url_for(".download_EC_qexp",
                                   label=self.lmfdb_label,
                                   limit=1000)),
                          ('All stored data to text',
                           url_for(".download_EC_all",
                                   label=self.lmfdb_label)),
                          ('Code to Magma',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='magma')),
                          ('Code to SageMath',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='sage')),
                          ('Code to GP',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='gp'))]

        try:
            self.plot = encode_plot(self.E.plot())
        except AttributeError:
            self.plot = encode_plot(EllipticCurve(data['ainvs']).plot())

        self.plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format(
            self.plot)
        self.properties = [
            ('Label', self.Clabel
             if self.label_type == 'Cremona' else self.lmfdb_label),
            (None, self.plot_link),
            ('Conductor', prop_int_pretty(data['conductor'])),
            ('Discriminant', prop_int_pretty(data['disc'])),
            ('j-invariant', '%s' % data['j_inv_latex']),
            ('CM', '%s' % data['CM']),
            ('Rank', 'unknown' if self.mwbsd['rank'] == '?' else
             prop_int_pretty(self.mwbsd['rank'])),
            ('Torsion structure', (r'\(%s\)' % self.mwbsd['tor_struct'])
             if self.mwbsd['tor_struct'] else 'trivial'),
        ]

        if self.label_type == 'Cremona':
            self.title = "Elliptic curve with Cremona label {} (LMFDB label {})".format(
                self.Clabel, self.lmfdb_label)
        elif N < CREMONA_BOUND:
            self.title = "Elliptic curve with LMFDB label {} (Cremona label {})".format(
                self.lmfdb_label, self.Clabel)
        else:
            self.title = "Elliptic curve with LMFDB label {}".format(
                self.lmfdb_label)

        self.bread = [('Elliptic curves', url_for("ecnf.index")),
                      (r'$\Q$', url_for(".rational_elliptic_curves")),
                      ('%s' % N, url_for(".by_conductor", conductor=N)),
                      ('%s' % iso,
                       url_for(".by_double_iso_label",
                               conductor=N,
                               iso_label=iso)), ('%s' % num, ' ')]
Example #54
0
    def make_passport_object(self, passport):
        from lmfdb.belyi.main import url_for_belyi_galmap_label
        # all information about the map goes in the data dictionary
        # most of the data from the database gets polished/formatted before we put it in the data dictionary
        data = self.data = {}

        for elt in ('plabel', 'abc', 'num_orbits', 'g', 'abc', 'deg',
                    'maxdegbf'):
            data[elt] = passport[elt]

        nt = passport['group'].split('T')
        data['group'] = group_display_knowl(int(nt[0]), int(nt[1]),
                                            getDBConnection())

        data['geomtype'] = geomtypelet_to_geomtypename_dict[
            passport['geomtype']]
        data['lambdas'] = [str(c)[1:-1] for c in passport['lambdas']]
        data['pass_size'] = passport['pass_size']

        # Permutation triples
        galmaps_for_plabel = belyi_db_galmaps().find({
            "plabel":
            passport['plabel']
        }).sort([('label_index', ASCENDING)])
        galmapdata = []
        for galmap in galmaps_for_plabel:
            # wrap number field nonsense
            F = belyi_base_field(galmap)
            # inLMFDB = False;
            field = {}
            if F._data == None:
                field['in_LMFDB'] = False
                fld_coeffs = galmap['base_field']
                pol = PolynomialRing(QQ, 'x')(fld_coeffs)
                field['base_field'] = latex(pol)
                field['isQQ'] = False
            else:
                field['in_LMFDB'] = True
                if F.poly().degree() == 1:
                    field['isQQ'] = True
                F.latex_poly = web_latex(F.poly())
                field['base_field'] = F

            galmapdatum = [
                galmap['label'].split('-')[-1],
                url_for_belyi_galmap_label(galmap['label']),
                galmap['orbit_size'],
                field,
                galmap['triples_cyc'][0][0],
                galmap['triples_cyc'][0][1],
                galmap['triples_cyc'][0][2],
            ]
            galmapdata.append(galmapdatum)
        data['galmapdata'] = galmapdata

        # Properties
        properties = [('Label', passport['plabel']),
                      ('Group', str(passport['group'])),
                      ('Orders', str(passport['abc'])),
                      ('Genus', str(passport['g'])),
                      ('Size', str(passport['pass_size'])),
                      ('Galois orbits', str(passport['num_orbits']))]
        self.properties = properties

        # Friends
        self.friends = []

        # Breadcrumbs

        groupstr, abcstr, sigma0, sigma1, sigmaoo, gstr = data['plabel'].split(
            "-")
        lambdasstr = '%s-%s-%s' % (sigma0, sigma1, sigmaoo)
        lambdasgstr = lambdasstr + "-" + gstr
        self.bread = [('Belyi Maps', url_for(".index")),
                      (groupstr,
                       url_for(".by_url_belyi_search_group", group=groupstr)),
                      (abcstr,
                       url_for(".by_url_belyi_search_group_triple",
                               group=groupstr,
                               abc=abcstr)),
                      (lambdasgstr,
                       url_for(".by_url_belyi_passport_label",
                               group=groupstr,
                               abc=abcstr,
                               sigma0=sigma0,
                               sigma1=sigma1,
                               sigmaoo=sigmaoo,
                               g=gstr))]

        # Title
        self.title = "Passport " + data['plabel']

        # Code snippets (only for curves)
        self.code = {}
        return
Example #55
0
    def make_galmap_object(self, galmap):
        from lmfdb.belyi.main import url_for_belyi_passport_label

        # all information about the map goes in the data dictionary
        # most of the data from the database gets polished/formatted before we put it in the data dictionary
        data = self.data = {}
        # the stuff that does not need to be polished
        for elt in ('label', 'plabel', 'triples_cyc', 'orbit_size', 'g', 'abc',
                    'deg'):
            data[elt] = galmap[elt]
        nt = galmap['group'].split('T')
        data['group'] = group_display_knowl(int(nt[0]), int(nt[1]),
                                            getDBConnection())

        data['geomtype'] = geomtypelet_to_geomtypename_dict[galmap['geomtype']]
        data['lambdas'] = [str(c)[1:-1] for c in galmap['lambdas']]

        data['isQQ'] = False
        data['in_LMFDB'] = False
        F = belyi_base_field(galmap)
        if F._data == None:
            fld_coeffs = galmap['base_field']
            pol = PolynomialRing(QQ, 'x')(fld_coeffs)
            data['base_field'] = latex(pol)
        else:
            data['in_LMFDB'] = True
            if F.poly().degree() == 1:
                data['isQQ'] = True
            F.latex_poly = web_latex(F.poly())
            data['base_field'] = F
        crv_str = galmap['curve']
        if crv_str == 'PP1':
            data['curve'] = '\mathbb{P}^1'
        else:
            data['curve'] = make_curve_latex(crv_str)

        # change pairs of floats to complex numbers
        embeds = galmap['embeddings']
        embed_strs = []
        for el in embeds:
            if el[1] < 0:
                el_str = str(el[0]) + str(el[1]) + "\sqrt{-1}"
            else:
                el_str = str(el[0]) + "+" + str(el[1]) + "\sqrt{-1}"
            embed_strs.append(el_str)

        data['map'] = make_map_latex(galmap['map'])
        data['embeddings_and_triples'] = []
        if data['isQQ']:
            for i in range(0, len(data['triples_cyc'])):
                triple_cyc = data['triples_cyc'][i]
                data['embeddings_and_triples'].append([
                    "\\text{not applicable (over $\mathbb{Q}$)}",
                    triple_cyc[0], triple_cyc[1], triple_cyc[2]
                ])
        else:
            for i in range(0, len(data['triples_cyc'])):
                triple_cyc = data['triples_cyc'][i]
                data['embeddings_and_triples'].append([
                    embed_strs[i], triple_cyc[0], triple_cyc[1], triple_cyc[2]
                ])

        data['lambdas'] = [str(c)[1:-1] for c in galmap['lambdas']]

        # Properties
        properties = [
            ('Label', galmap['label']),
            ('Group', str(galmap['group'])),
            ('Orders', str(galmap['abc'])),
            ('Genus', str(galmap['g'])),
            ('Size', str(galmap['orbit_size'])),
        ]
        self.properties = properties

        # Friends
        self.friends = [('Passport',
                         url_for_belyi_passport_label(galmap['plabel']))]

        # Breadcrumbs
        groupstr, abcstr, sigma0, sigma1, sigmaoo, gstr, letnum = data[
            'label'].split("-")
        lambdasstr = '%s-%s-%s' % (sigma0, sigma1, sigmaoo)
        lambdasgstr = lambdasstr + "-" + gstr
        self.bread = [
            ('Belyi Maps', url_for(".index")),
            (groupstr, url_for(".by_url_belyi_search_group", group=groupstr)),
            (abcstr,
             url_for(".by_url_belyi_search_group_triple",
                     group=groupstr,
                     abc=abcstr)),
            (lambdasgstr,
             url_for(".by_url_belyi_passport_label",
                     group=groupstr,
                     abc=abcstr,
                     sigma0=sigma0,
                     sigma1=sigma1,
                     sigmaoo=sigmaoo,
                     g=gstr)),
            (letnum,
             url_for(".by_url_belyi_galmap_label",
                     group=groupstr,
                     abc=abcstr,
                     sigma0=sigma0,
                     sigma1=sigma1,
                     sigmaoo=sigmaoo,
                     g=gstr,
                     letnum=letnum)),
        ]

        # Title
        self.title = "Belyi map " + data['label']

        # Code snippets (only for curves)
        self.code = {}
        return
Example #56
0
    def make_curve(self):
        # To start with the data fields of self are just those from
        # the database.  We need to reformat these.

        # Old version: required constructing the actual elliptic curve
        # E, and computing some further data about it.

        # New version (May 2016): extra data fields now in the
        # database so we do not have to construct the curve or do any
        # computation with it on the fly.  As a failsafe the old way
        # is still included.

        data = self.data = {}
        data['ainvs'] = [ZZ(ai) for ai in self.ainvs]
        data['conductor'] = N = ZZ(self.conductor)
        data['j_invariant'] = QQ(str(self.jinv))
        data['j_inv_factor'] = latex(0)
        if data['j_invariant']:  # don't factor 0
            data['j_inv_factor'] = latex(data['j_invariant'].factor())
        data['j_inv_str'] = unicode(str(data['j_invariant']))
        data['j_inv_latex'] = web_latex(data['j_invariant'])

        # extract data about MW rank, generators, heights and torsion:
        self.make_mw()

        # get more data from the database entry

        data['equation'] = self.equation
        local_data = self.local_data
        D = self.signD * prod([ld['p']**ld['ord_disc'] for ld in local_data])
        for ld in local_data:
            ld['kod'] = ld['kod'].replace("\\\\", "\\")
        data['disc'] = D
        Nfac = Factorization([(ZZ(ld['p']), ld['ord_cond'])
                              for ld in local_data])
        Dfac = Factorization([(ZZ(ld['p']), ld['ord_disc'])
                              for ld in local_data],
                             unit=ZZ(self.signD))

        data['minq_D'] = minqD = self.min_quad_twist['disc']
        data['minq_label'] = self.min_quad_twist[
            'lmfdb_label'] if self.label_type == 'LMFDB' else self.min_quad_twist[
                'label']
        data['minq_info'] = '(itself)' if minqD == 1 else '(by {})'.format(
            minqD)

        if self.degree is None:
            data['degree'] = 0  # invalid, but will be displayed nicely
        else:
            data['degree'] = self.degree

        try:
            data['an'] = self.anlist
            data['ap'] = self.aplist
        except AttributeError:
            r = db.ec_curves.lucky({'lmfdb_iso': self.lmfdb_iso, 'number': 1})
            data['an'] = r['anlist']
            data['ap'] = r['aplist']

        data['disc_factor'] = latex(Dfac)
        data['cond_factor'] = latex(Nfac)
        data['disc_latex'] = web_latex(D)
        data['cond_latex'] = web_latex(N)

        data['galois_images'] = [
            trim_galois_image_code(s) for s in self.mod_p_images
        ]
        data['non_maximal_primes'] = self.non_maximal_primes
        data['galois_data'] = [{
            'p': p,
            'image': im
        } for p, im in zip(data['non_maximal_primes'], data['galois_images'])]

        data['CMD'] = self.cm
        data['CM'] = "no"
        data['EndE'] = "\(\Z\)"
        if self.cm:
            data['cm_ramp'] = [
                p for p in ZZ(self.cm).support()
                if not p in self.non_maximal_primes
            ]
            data['cm_nramp'] = len(data['cm_ramp'])
            if data['cm_nramp'] == 1:
                data['cm_ramp'] = data['cm_ramp'][0]
            else:
                data['cm_ramp'] = ", ".join([str(p) for p in data['cm_ramp']])
            data['cm_sqf'] = ZZ(self.cm).squarefree_part()

            data['CM'] = "yes (\(D=%s\))" % data['CMD']
            if data['CMD'] % 4 == 0:
                d4 = ZZ(data['CMD']) // 4
                data['EndE'] = "\(\Z[\sqrt{%s}]\)" % d4
            else:
                data['EndE'] = "\(\Z[(1+\sqrt{%s})/2]\)" % data['CMD']
            data['ST'] = st_link_by_name(1, 2, 'N(U(1))')
        else:
            data['ST'] = st_link_by_name(1, 2, 'SU(2)')

        data['p_adic_primes'] = [
            p for i, p in enumerate(prime_range(5, 100))
            if (N * data['ap'][i]) % p != 0
        ]

        cond, iso, num = split_lmfdb_label(self.lmfdb_label)
        self.one_deg = ZZ(self.class_deg).is_prime()
        isodegs = [str(d) for d in self.isogeny_degrees if d > 1]
        if len(isodegs) < 3:
            data['isogeny_degrees'] = " and ".join(isodegs)
        else:
            data['isogeny_degrees'] = " and ".join(
                [", ".join(isodegs[:-1]), isodegs[-1]])

        if self.twoadic_gens:
            from sage.matrix.all import Matrix
            data['twoadic_gen_matrices'] = ','.join(
                [latex(Matrix(2, 2, M)) for M in self.twoadic_gens])
            data[
                'twoadic_rouse_url'] = ROUSE_URL_PREFIX + self.twoadic_label + ".html"

        # Leading term of L-function & other BSD data
        self.make_bsd()

        # Optimality (the optimal curve in the class is the curve
        # whose Cremona label ends in '1' except for '990h' which was
        # labelled wrongly long ago): this is proved for N up to
        # OPTIMALITY_BOUND (and when there is only one curve in an
        # isogeny class, obviously) and expected for all N.

        # Column 'optimality' is 1 for certainly optimal curves, 0 for
        # certainly non-optimal curves, and is n>1 if the curve is one
        # of n in the isogeny class which may be optimal given current
        # knowledge.

        # Column "manin_constant' is the correct Manin constant
        # assuming that the optimal curve in the class is known, or
        # otherwise if it is the curve with (Cremona) number 1.

        # The code here allows us to update the display correctly by
        # changing one line in this file (defining OPTIMALITY_BOUND)
        # without changing the data.

        data['optimality_bound'] = OPTIMALITY_BOUND
        data[
            'manin_constant'] = self.manin_constant  # (conditional on data['optimality_known'])

        if N < OPTIMALITY_BOUND:

            data['optimality_code'] = int(
                self.number == (3 if self.iso == '990h' else 1))
            data['optimality_known'] = True
            data['manin_known'] = True
            if self.label_type == 'Cremona':
                data[
                    'optimal_label'] = '990h3' if self.iso == '990h' else self.iso + '1'
            else:
                data[
                    'optimal_label'] = '990.i3' if self.lmfdb_iso == '990.i' else self.lmfdb_iso + '1'

        else:

            data['optimality_code'] = self.optimality
            data['optimality_known'] = (self.optimality < 2)

            if self.optimality == 1:
                data['manin_known'] = True
                data[
                    'optimal_label'] = self.label if self.label_type == 'Cremona' else self.lmfdb_label
            else:
                if self.number == 1:
                    data['manin_known'] = False
                    data[
                        'optimal_label'] = self.label if self.label_type == 'Cremona' else self.lmfdb_label
                else:
                    # find curve #1 in this class and its optimailty code:
                    opt_curve = db.ec_curves.lucky(
                        {
                            'iso': self.iso,
                            'number': 1
                        },
                        projection=['label', 'lmfdb_label', 'optimality'])
                    data['manin_known'] = (opt_curve['optimality'] == 1)
                    data['optimal_label'] = opt_curve[
                        'label' if self.label_type ==
                        'Cremona' else 'lmfdb_label']

        data['p_adic_data_exists'] = False
        if data['optimality_code'] == 1:
            data['p_adic_data_exists'] = db.ec_padic.exists(
                {'lmfdb_iso': self.lmfdb_iso})

        # Iwasawa data (where present)

        self.make_iwasawa()

        # Torsion growth data (where present)

        self.make_torsion_growth()

        data['newform'] = web_latex(
            PowerSeriesRing(QQ, 'q')(data['an'], 20, check=True))
        data['newform_label'] = self.newform_label = ".".join(
            [str(cond), str(2), 'a', iso])
        self.newform_link = url_for("cmf.by_url_newform_label",
                                    level=cond,
                                    weight=2,
                                    char_orbit_label='a',
                                    hecke_orbit=iso)
        self.newform_exists_in_db = db.mf_newforms.label_exists(
            self.newform_label)
        self._code = None

        if self.label_type == 'Cremona':
            self.class_url = url_for(".by_ec_label", label=self.iso)
            self.class_name = self.iso
        else:
            self.class_url = url_for(".by_double_iso_label",
                                     conductor=N,
                                     iso_label=iso)
            self.class_name = self.lmfdb_iso
        data['class_name'] = self.class_name
        data['number'] = self.number

        self.friends = [('Isogeny class ' + self.class_name, self.class_url),
                        ('Minimal quadratic twist %s %s' %
                         (data['minq_info'], data['minq_label']),
                         url_for(".by_ec_label", label=data['minq_label'])),
                        ('All twists ',
                         url_for(".rational_elliptic_curves", jinv=self.jinv))]

        lfun_url = url_for("l_functions.l_function_ec_page",
                           conductor_label=N,
                           isogeny_class_label=iso)
        origin_url = lfun_url.lstrip('/L/').rstrip('/')

        if db.lfunc_instances.exists({'url': origin_url}):
            self.friends += [('L-function', lfun_url)]
        else:
            self.friends += [('L-function not available', "")]

        if not self.cm:
            if N <= 300:
                self.friends += [('Symmetric square L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='2',
                                          conductor=N,
                                          isogeny=iso))]
            if N <= 50:
                self.friends += [('Symmetric cube L-function',
                                  url_for("l_functions.l_function_ec_sym_page",
                                          power='3',
                                          conductor=N,
                                          isogeny=iso))]
        if self.newform_exists_in_db:
            self.friends += [('Modular form ' + self.newform_label,
                              self.newform_link)]

        self.downloads = [('q-expansion to text',
                           url_for(".download_EC_qexp",
                                   label=self.lmfdb_label,
                                   limit=1000)),
                          ('All stored data to text',
                           url_for(".download_EC_all",
                                   label=self.lmfdb_label)),
                          ('Code to Magma',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='magma')),
                          ('Code to SageMath',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='sage')),
                          ('Code to GP',
                           url_for(".ec_code_download",
                                   conductor=cond,
                                   iso=iso,
                                   number=num,
                                   label=self.lmfdb_label,
                                   download_type='gp'))]

        try:
            self.plot = encode_plot(self.E.plot())
        except AttributeError:
            self.plot = encode_plot(EllipticCurve(data['ainvs']).plot())

        self.plot_link = '<a href="{0}"><img src="{0}" width="200" height="150"/></a>'.format(
            self.plot)
        self.properties = [
            ('Label',
             self.label if self.label_type == 'Cremona' else self.lmfdb_label),
            (None, self.plot_link), ('Conductor', '%s' % data['conductor']),
            ('Discriminant', '%s' % data['disc']),
            ('j-invariant', '%s' % data['j_inv_latex']),
            ('CM', '%s' % data['CM']), ('Rank', '%s' % self.mw['rank']),
            ('Torsion Structure', '\(%s\)' % self.mw['tor_struct'])
        ]

        if self.label_type == 'Cremona':
            self.title = "Elliptic Curve with Cremona label {} (LMFDB label {})".format(
                self.label, self.lmfdb_label)
        else:
            self.title = "Elliptic Curve with LMFDB label {} (Cremona label {})".format(
                self.lmfdb_label, self.label)

        self.bread = [('Elliptic Curves', url_for("ecnf.index")),
                      ('$\Q$', url_for(".rational_elliptic_curves")),
                      ('%s' % N, url_for(".by_conductor", conductor=N)),
                      ('%s' % iso,
                       url_for(".by_double_iso_label",
                               conductor=N,
                               iso_label=iso)), ('%s' % num, ' ')]
Example #57
0
def render_isogeny_class(iso_class):
    info = {}
    credit = 'John Cremona'
    lmfdb_iso = iso_class  # e.g. '11.a'
    N, iso, number = lmfdb_label_regex.match(lmfdb_iso).groups()

    CDB = lmfdb.base.getDBConnection().elliptic_curves.curves

    E1data = CDB.find_one({'lmfdb_label': lmfdb_iso + '1'})
    if E1data is None:
        return elliptic_curve_jump_error(lmfdb_iso, {})

    cremona_iso = E1data['iso']
    ainvs = [int(a) for a in E1data['ainvs']]
    E1 = EllipticCurve(ainvs)
    ver = sage.version.version.split('.')  # e.g. "6.1.beta2"
    ma = int(ver[0])
    mi = int(ver[1])
    if ma > 6 or ma == 6 and mi > 1:
        # Code for Sage 6.2 and later:
        isogeny_class = E1.isogeny_class()
        curves = isogeny_class.curves
        mat = isogeny_class.matrix()
    else:
        # Code for Sage 6.1 and before:
        curves, mat = E1.isogeny_class()
    size = len(curves)
    # Create a list of the curves in the class from the database, so
    # they are in the correct order!
    db_curves = [E1]
    optimal_flags = [False] * size
    degrees = [0] * size
    if 'degree' in E1data:
        degrees[0] = E1data['degree']
    else:
        try:
            degrees[0] = E1.modular_degree()
        except RuntimeError:
            pass
    cremona_labels = [E1data['label']] + [0] * (size - 1)
    if E1data['number'] == 1:
        optimal_flags[0] = True
    for i in range(2, size + 1):
        Edata = CDB.find_one({'lmfdb_label': lmfdb_iso + str(i)})
        E = EllipticCurve([int(a) for a in Edata['ainvs']])
        cremona_labels[i - 1] = Edata['label']
        if Edata['number'] == 1:
            optimal_flags[i - 1] = True
        if 'degree' in Edata:
            degrees[i - 1] = Edata['degree']
        else:
            try:
                degrees[i - 1] = E.modular_degree()
            except RuntimeError:
                pass
        db_curves.append(E)

    if cremona_iso == '990h':  # this isogeny class is labeled wrong in Cremona's tables
        optimal_flags = [False, False, True, False]

    # Now work out the permutation needed to match the two lists of curves:
    perm = [db_curves.index(E) for E in curves]
    # Apply the same permutation to the isogeny matrix:
    mat = [[mat[perm[i], perm[j]] for j in range(size)] for i in range(size)]

    info = {'label': lmfdb_iso}
    info['optimal_ainvs'] = ainvs
    info['rank'] = E1data['rank']
    info['isogeny_matrix'] = latex(matrix(mat))

    # info['f'] = ajax_more(E.q_eigenform, 10, 20, 50, 100, 250)
    info['f'] = web_latex(E.q_eigenform(10))
    info['graph_img'] = url_for('.plot_iso_graph', label=lmfdb_iso)

    info['curves'] = [[
        lmfdb_iso + str(i + 1), cremona_labels[i],
        str(list(c.ainvs())),
        c.torsion_order(), degrees[i], optimal_flags[i]
    ] for i, c in enumerate(db_curves)]

    friends = []
    #   friends.append(('Quadratic Twist', "/quadratic_twists/%s" % (lmfdb_iso)))
    friends.append(('L-function',
                    url_for("l_functions.l_function_ec_page",
                            label=lmfdb_iso)))
    friends.append(('Symmetric square L-function',
                    url_for("l_functions.l_function_ec_sym_page",
                            power='2',
                            label=lmfdb_iso)))
    friends.append(('Symmetric 4th power L-function',
                    url_for("l_functions.l_function_ec_sym_page",
                            power='4',
                            label=lmfdb_iso)))
    # render_one_elliptic_modular_form(level,weight,character,label,**kwds)

    friends.append(('Modular form ' + lmfdb_iso.replace('.', '.2'),
                    url_for("emf.render_elliptic_modular_forms",
                            level=N,
                            weight=2,
                            character=0,
                            label=iso)))

    info['friends'] = friends

    info['downloads'] = [('Download coeffients of q-expansion',
                          url_for(".download_EC_qexp",
                                  label=lmfdb_iso,
                                  limit=100)),
                         ('Download stored data for curves in this class',
                          url_for(".download_EC_all", label=lmfdb_iso))]

    if lmfdb_iso == cremona_iso:
        t = "Elliptic Curve Isogeny Class %s" % lmfdb_iso
    else:
        t = "Elliptic Curve Isogeny Class %s (Cremona label %s)" % (
            lmfdb_iso, cremona_iso)
    bread = [('Elliptic Curves ', url_for(".rational_elliptic_curves")),
             ('isogeny class %s' % lmfdb_iso, ' ')]

    return render_template("iso_class.html",
                           info=info,
                           bread=bread,
                           credit=credit,
                           title=t,
                           friends=info['friends'],
                           downloads=info['downloads'])
Example #58
0
def render_curve_webpage_by_label(label):
    C = lmfdb.base.getDBConnection()
    data = C.elliptic_curves.curves.find_one({'lmfdb_label': label})
    if data is None:
        return elliptic_curve_jump_error(label, {})
    info = {}
    ainvs = [int(a) for a in data['ainvs']]
    E = EllipticCurve(ainvs)
    cremona_label = data['label']
    lmfdb_label = data['lmfdb_label']
    N = ZZ(data['conductor'])
    cremona_iso_class = data['iso']  # eg '37a'
    lmfdb_iso_class = data['lmfdb_iso']  # eg '37.a'
    rank = data['rank']
    try:
        j_invariant = QQ(str(data['jinv']))
    except KeyError:
        j_invariant = E.j_invariant()
    if j_invariant == 0:
        j_inv_factored = latex(0)
    else:
        j_inv_factored = latex(j_invariant.factor())
    jinv = unicode(str(j_invariant))
    CMD = 0
    CM = "no"
    EndE = "\(\Z\)"
    if E.has_cm():
        CMD = E.cm_discriminant()
        CM = "yes (\(%s\))" % CMD
        if CMD % 4 == 0:
            d4 = ZZ(CMD) // 4
            # r = d4.squarefree_part()
            # f = (d4//r).isqrt()
            # f="" if f==1 else str(f)
            # EndE = "\(\Z[%s\sqrt{%s}]\)"%(f,r)
            EndE = "\(\Z[\sqrt{%s}]\)" % (d4)
        else:
            EndE = "\(\Z[(1+\sqrt{%s})/2]\)" % CMD

    # plot=E.plot()
    discriminant = E.discriminant()
    xintpoints_projective = [
        E.lift_x(x)
        for x in xintegral_point(data['x-coordinates_of_integral_points'])
    ]
    xintpoints = proj_to_aff(xintpoints_projective)
    if 'degree' in data:
        modular_degree = data['degree']
    else:
        try:
            modular_degree = E.modular_degree()
        except RuntimeError:
            modular_degree = 0  # invalid, will be displayed nicely

    G = E.torsion_subgroup().gens()
    E_pari = E.pari_curve(prec=200)
    from sage.libs.pari.all import PariError
    try:
        minq = E.minimal_quadratic_twist()[0]
    except PariError:  # this does occur with 164411a1
        print "PariError computing minimal quadratic twist of elliptic curve %s" % lmfdb_label
        minq = E
    if E == minq:
        minq_label = lmfdb_label
    else:
        minq_ainvs = [str(c) for c in minq.ainvs()]
        minq_label = C.elliptic_curves.curves.find_one({'ainvs': minq_ainvs
                                                        })['lmfdb_label']


# We do not just do the following, as Sage's installed database
# might not have all the curves in the LMFDB database.
# minq_label = E.minimal_quadratic_twist()[0].label()

    if 'gens' in data:
        generator = parse_gens(data['gens'])
    if len(G) == 0:
        tor_struct = '\mathrm{Trivial}'
        tor_group = '\mathrm{Trivial}'
    else:
        tor_group = ' \\times '.join(['\Z/{%s}\Z' % a.order() for a in G])
    if 'torsion_structure' in data:
        info['tor_structure'] = ' \\times '.join(
            ['\Z/{%s}\Z' % int(a) for a in data['torsion_structure']])
    else:
        info['tor_structure'] = tor_group

    def trim_galois_image_code(s):
        return s[2:] if s[1].isdigit() else s[1:]

    if 'galois_images' in data:
        galois_images = data['galois_images']
        galois_images = [trim_galois_image_code(s) for s in galois_images]
        non_surjective_primes = data['non-surjective_primes']

    galois_data = [{
        'p': p,
        'image': im
    } for p, im in zip(non_surjective_primes, galois_images)]

    info.update(data)
    if rank >= 2:
        lder_tex = "L%s(E,1)" % ("^{(" + str(rank) + ")}")
    elif rank == 1:
        lder_tex = "L%s(E,1)" % ("'" * rank)
    else:
        assert rank == 0
        lder_tex = "L(E,1)"
    info['Gamma0optimal'] = (cremona_label[-1] == '1'
                             if cremona_iso_class != '990h' else
                             cremona_label[-1] == '3')
    info['modular_degree'] = modular_degree
    p_adic_data_exists = (C.elliptic_curves.padic_db.find({
        'lmfdb_iso':
        lmfdb_iso_class
    }).count()) > 0 and info['Gamma0optimal']

    # Local data
    local_data = []
    for p in N.prime_factors():
        local_info = E.local_data(p, algorithm="generic")
        local_data.append({
            'p':
            p,
            'tamagawa_number':
            local_info.tamagawa_number(),
            'kodaira_symbol':
            web_latex(local_info.kodaira_symbol()).replace('$', ''),
            'reduction_type':
            local_info.bad_reduction_type()
        })

    mod_form_iso = lmfdb_label_regex.match(lmfdb_iso_class).groups()[1]

    tamagawa_numbers = [
        E.local_data(p, algorithm="generic").tamagawa_number()
        for p in N.prime_factors()
    ]
    # if we use E.tamagawa_numbers() it calls E.local_data(p) which
    # crashes on some curves e.g. 164411a1
    info.update({
        'conductor':
        N,
        'disc_factor':
        latex(discriminant.factor()),
        'j_invar_factor':
        j_inv_factored,
        'label':
        lmfdb_label,
        'cremona_label':
        cremona_label,
        'iso_class':
        lmfdb_iso_class,
        'cremona_iso_class':
        cremona_iso_class,
        'equation':
        web_latex(E),
        #'f': ajax_more(E.q_eigenform, 10, 20, 50, 100, 250),
        'f':
        web_latex(E.q_eigenform(10)),
        'generators':
        ', '.join(web_latex(g) for g in generator) if 'gens' in data else ' ',
        'lder':
        lder_tex,
        'p_adic_primes': [
            p for p in sage.all.prime_range(5, 100)
            if E.is_ordinary(p) and not p.divides(N)
        ],
        'p_adic_data_exists':
        p_adic_data_exists,
        'ainvs':
        format_ainvs(data['ainvs']),
        'CM':
        CM,
        'CMD':
        CMD,
        'EndE':
        EndE,
        'tamagawa_numbers':
        r' \cdot '.join(str(sage.all.factor(c)) for c in tamagawa_numbers),
        'local_data':
        local_data,
        'cond_factor':
        latex(N.factor()),
        'galois_data':
        galois_data,
        'xintegral_points':
        ', '.join(web_latex(P) for P in xintpoints),
        'tor_gens':
        ', '.join(web_latex(eval(g))
                  for g in data['torsion_generators']) if False else ', '.join(
                      web_latex(P.element().xy()) for P in list(G))
    })
    info['friends'] = [('Isogeny class ' + lmfdb_iso_class,
                        url_for(".by_ec_label", label=lmfdb_iso_class)),
                       ('Minimal quadratic twist ' + minq_label,
                        url_for(".by_ec_label", label=minq_label)),
                       ('All twists ',
                        url_for(".rational_elliptic_curves", jinv=jinv)),
                       ('L-function',
                        url_for("l_functions.l_function_ec_page",
                                label=lmfdb_label)),
                       ('Symmetric square L-function',
                        url_for("l_functions.l_function_ec_sym_page",
                                power='2',
                                label=lmfdb_iso_class)),
                       ('Symmetric 4th power L-function',
                        url_for("l_functions.l_function_ec_sym_page",
                                power='4',
                                label=lmfdb_iso_class))]

    info['friends'].append(
        ('Modular form ' + lmfdb_iso_class.replace('.', '.2'),
         url_for("emf.render_elliptic_modular_forms",
                 level=int(N),
                 weight=2,
                 character=0,
                 label=mod_form_iso)))

    info['downloads'] = [('Download coeffients of q-expansion',
                          url_for(".download_EC_qexp",
                                  label=lmfdb_label,
                                  limit=100)),
                         ('Download all stored data',
                          url_for(".download_EC_all", label=lmfdb_label))]

    # info['learnmore'] = [('Elliptic Curves', url_for(".not_yet_implemented"))]
    # info['plot'] = image_src(plot)
    info['plot'] = url_for('.plot_ec', label=lmfdb_label)

    properties2 = [('Label', '%s' % lmfdb_label),
                   (None, '<img src="%s" width="200" height="150"/>' %
                    url_for('.plot_ec', label=lmfdb_label)),
                   ('Conductor', '\(%s\)' % N),
                   ('Discriminant', '\(%s\)' % discriminant),
                   ('j-invariant', '%s' % web_latex(j_invariant)),
                   ('CM', '%s' % CM), ('Rank', '\(%s\)' % rank),
                   ('Torsion Structure', '\(%s\)' % tor_group)]
    # properties.extend([ "prop %s = %s<br/>" % (_,_*1923) for _ in range(12) ])
    credit = 'John Cremona and Andrew Sutherland'
    if info['label'] == info['cremona_label']:
        t = "Elliptic Curve %s" % info['label']
    else:
        t = "Elliptic Curve %s (Cremona label %s)" % (info['label'],
                                                      info['cremona_label'])

    bread = [('Elliptic Curves ', url_for(".rational_elliptic_curves")),
             ('Elliptic curves %s' % lmfdb_label, ' ')]

    return render_template("curve.html",
                           properties2=properties2,
                           credit=credit,
                           bread=bread,
                           title=t,
                           info=info,
                           friends=info['friends'],
                           downloads=info['downloads'])