예제 #1
0
def eigenvalue_fields(N, k, eps=None):
    """
    Return Hecke eigenvalue fields of the newforms in the space with
    given level, weight, and character.

    Note that computing this field involves taking random linear
    combinations of Hecke eigenvalues, so is not deterministic.  Set
    the random seed first (set_random_seed(0)) if you want this to be
    deterministic.

    INPUT:

        - N -- level; positive integer
        - k -- weight; integer at least 2
        - eps -- None or Dirichlet character; if specified N is ignored
        
    EXAMPLES::
    
        sage: import psage
        sage: psage.modform.rational.eigenvalue_fields(11,2)
        [Rational Field]
        sage: psage.modform.rational.eigenvalue_fields(43,2)
        [Rational Field, Number Field in alpha with defining polynomial x^2 - 2]
        sage: psage.modform.rational.eigenvalue_fields(DirichletGroup(13).0^2,2)
        [Cyclotomic Field of order 6 and degree 2]
        sage: psage.modform.rational.eigenvalue_fields(13,2,DirichletGroup(13).0^2)
        [Cyclotomic Field of order 6 and degree 2]
    """
    group = eps if eps else N
    from sage.all import ModularSymbols
    M = ModularSymbols(group=group, weight=k, sign=1).cuspidal_subspace()
    N = M.new_subspace()
    D = N.decomposition()
    X = [f.compact_system_of_eigenvalues([2])[1].base_ring() for f in D]
    return X
예제 #2
0
def is_torsion_same(p, K, chi, B=30, uniform=False):
    """Returns true if the minus part of J0(p) does not gain new torsion when
    base changing to K"""
    M = ModularSymbols(p)
    S = M.cuspidal_subspace()
    T = S.atkin_lehner_operator()
    S_min = (T + parent(T)(1)).kernel()
    J0_min = S_min.abelian_variety()

    d = K.degree()

    if uniform:
        frob_poly_data = [(q, d) for q in prime_range(d + 2, B) if q != p]
    else:
        frob_poly_data = [(q, 1) if chi(q) == 1 else (q, d)
                          for q in prime_range(d + 2, B) if gcd(q, p) == 1]

    point_counts = []

    for q, i in frob_poly_data:
        frob_pol_q = J0_min.frobenius_polynomial(q)
        frob_mat = companion_matrix(frob_pol_q)
        point_counts.append((frob_mat**i).charpoly()(1))

    # Recall that the rational torsion on J0(p) is entirely contained in
    # the minus part (theorem of Mazur), so checking no-growth of torsion
    # in minus part is done simply as follows

    return J0(p).rational_torsion_order(proof=False) == gcd(point_counts)
예제 #3
0
def count_points_J_H(G,p):
    """
    Returns the number of points on J_H(GF(p))
    
    INPUT:
        
    - G - a congruence subgroup of type GammaH
    - p - a prime
    
    OUTPUT:
        
    - the number of F_p points on the jacobian of the modular curve X_H
    
    EXAMPLES::

        sage: from mdsage import *
        sage: count_points_J_H(Gamma0(29),19)
        196
    """
    M=ModularSymbols(G,sign=1)
    S=M.cuspidal_subspace()
    dq=S.diamond_bracket_matrix(p)
    #print "computing tq"
    Tq=S.hecke_matrix(p)
    #assert (Tq-dq-p).det() == (Tq-p*dq-1).det()
    return (dq+p-Tq).det()
예제 #4
0
def upper_bound_index_cusps_in_JG_torsion(G, d, bound=60):
    """
    INPUT:
        
    - G - a congruence subgroup
    - d - integer, the size of the rational cuspidal subgroup
    - bound (optional, default = 60) - the bound for the primes p up to which to use
      the hecke matrix `T_p - <p> - p` for bounding the torsion subgroup
    
    OUTPUT:
        
    - an integer `i` such that `(\#J_G(\QQ)_{tors})/d` is a divisor of `i`.
    
    EXAMPLES::

        sage: from mdsage import *
        sage: d = rational_cuspidal_classgroup(Gamma1(23)).cardinality()
        sage: upper_bound_index_cusps_in_JG_torsion(Gamma1(23),d)
        1

    """
    N = G.level()
    M = ModularSymbols(G)
    Sint = cuspidal_integral_structure(M)
    kill_mat = (M.star_involution().matrix().restrict(Sint) - 1)
    kill = kill_mat.transpose().change_ring(ZZ).row_module()
    for p in prime_range(3, bound):
        if not N % p == 0:
            kill += kill_torsion_coprime_to_q(
                p, M).restrict(Sint).change_ring(ZZ).transpose().row_module()
        if kill.matrix().is_square() and kill.matrix().determinant() == d:
            #print p
            break
    kill_mat = kill.matrix().transpose()
    #print N,"index of torsion in stuff killed",kill.matrix().determinant()/d
    if kill.matrix().determinant() == d:
        return 1

    pm = integral_period_mapping(M)
    period_images1 = [
        sum([M.coordinate_vector(M([c, infinity])) for c in cusps]) * pm
        for cusps in galois_orbits(G)
    ]

    m = (Matrix(period_images1) * kill_mat).stack(kill_mat)
    diag = m.change_ring(ZZ).echelon_form().diagonal()
    #print diag,prod(diag)
    assert prod(diag) == kill.matrix().determinant() / d

    period_images2 = [
        M.coordinate_vector(M([c, infinity])) * pm for c in G.cusps()
        if c != Cusp(oo)
    ]
    m = (Matrix(period_images2) * kill_mat).stack(kill_mat)
    m, denom = m._clear_denom()
    diag = (m.change_ring(ZZ).echelon_form() / denom).diagonal()
    #print diag
    #print prod(i.numerator() for i in diag),"if this is 1 then :)"
    return prod(i.numerator() for i in diag)
예제 #5
0
def JG_torsion_upperbound(G, bound=60):
    """
    INPUT:
        
    - G - a congruence subgroup
    - bound (optional, default = 60) - the bound for the primes p up to which to use
      the hecke matrix `T_p - <p> - p` for bounding the torsion subgroup
    
    OUTPUT:
        
    - A subgroup of `(S_2(G) \otimes \QQ) / S_2(G)` that is guaranteed to contain
      the rational torison subgroup, together with a subgroup generated by the
      rational cusps.
      The subgroup is given as a subgroup of `S_2(G)/NS_2(G)` for a suitable integer N

    EXAMPLES::
        
        sage: from mdsage import *
        sage: d = rational_cuspidal_classgroup(Gamma1(23)).cardinality()
        sage: upper_bound_index_cusps_in_JG_torsion(Gamma1(23),d)
        1

    """
    N = G.level()
    M = ModularSymbols(G)
    Sint = cuspidal_integral_structure(M)
    kill_mat = (M.star_involution().matrix().restrict(Sint) - 1)
    kill = kill_mat.transpose().change_ring(ZZ).row_module()
    for p in prime_range(3, bound):
        if not N % p == 0:
            kill += kill_torsion_coprime_to_q(
                p, M).restrict(Sint).change_ring(ZZ).transpose().row_module()
        #if kill.matrix().is_square() and kill.matrix().determinant()==d:
        #    #print p
        #    break
    kill_mat = kill.matrix().transpose()
    #print N,"index of torsion in stuff killed",kill.matrix().determinant()/d
    #if kill.matrix().determinant()==d:
    #    return 1
    d = prod(kill_mat.smith_form()[0].diagonal())
    pm = integral_period_mapping(M)
    #period_images1=[sum([M.coordinate_vector(M([c,infinity])) for c in cusps])*pm for cusps in galois_orbits(G)]
    period_images2 = [
        M.coordinate_vector(M([c, infinity])) * pm for c in G.cusps()
        if c != Cusp(oo)
    ]

    m = (Matrix(period_images2) * kill_mat).stack(kill_mat)
    m, d2 = m._clear_denom()
    d = gcd(d, d2)
예제 #6
0
def is_formal_immersion(d, p):
    """This funtion returns an integer n such that we have a formall immersion in
    characteristic q != 2,p if and only if q does not divide n.
    """
    G = Gamma0(p)
    M = ModularSymbols(G, 2)
    S = M.cuspidal_subspace()
    I2 = M.hecke_operator(2) - 3
    if I2.matrix().rank() != S.dimension():
        raise RuntimeError(f"Formall immersion for d={d} p={p} failed"
                           "because I2 is not of the expected rank.")
    Te = R_dp(G.sturm_bound(), p).row_module()
    R = (R_dp(d, p).restrict_codomain(Te)).change_ring(ZZ)
    if R.rank() < d:
        return 0
    D = R.elementary_divisors()
    if D and D[-1]:
        return D[-1].prime_to_m_part(2)
    return 0
예제 #7
0
def is_rank_of_twist_zero(p, chi):
    """Returns true if the rank of the twist of the minus part of X_0(p)
    by the character chi is zero"""
    ML = ModularSymbols(p, base_ring=chi.base_ring())
    SL = ML.cuspidal_subspace()
    TL = SL.atkin_lehner_operator()
    S_min_L = (TL + parent(TL)(1)).kernel()

    for S in S_min_L.decomposition():
        my_map = S.rational_period_mapping()
        w = ML([0, oo])
        wmap = my_map(w)
        if wmap == 0:
            return False
        tw = ML.twisted_winding_element(0, chi)
        twmap = my_map(tw)
        if twmap == 0:
            return False

    return True
예제 #8
0
def R_dp(d, p):
    """Return the formal immersion matrix
    Args:
        d ([int]): degree of number field
        p ([prime]): prime whose formal immersion properties we'd like to check
    Returns:
        [Matrix]: The Matrix whose rows are (T_2-3)*T_i e  for i <= d.
                  This is for verifying the linear independance in
                  Corollary 6.4 of Derickx-Kamienny-Stein-Stoll.
    """
    M = ModularSymbols(Gamma0(p), 2)
    S = M.cuspidal_subspace()
    S_int = S.integral_structure()
    e = M([0, oo])
    I2 = M.hecke_operator(2) - 3

    def get_row(i):
        return S_int.coordinate_vector(
            S_int(M.coordinate_vector(I2(M.hecke_operator(i)(e)))))

    return Matrix([get_row(i) for i in range(1, d + 1)]).change_ring(ZZ)
예제 #9
0
def degrees(N, k, eps=None):
    """
    Return the degrees of the newforms of level N, weight k, with character eps.

    INPUT:

        - N -- level; positive integer or Dirichlet character
        - k -- weight; integer at least 2
        - eps -- None or Dirichlet character; if specified N is ignored
        
    EXAMPLES::

        sage: import psage
        sage: psage.modform.rational.degrees(11,2)
        [1]
        sage: psage.modform.rational.degrees(37,2)
        [1, 1]
        sage: psage.modform.rational.degrees(43,2)
        [1, 2]
        sage: psage.modform.rational.degrees(DirichletGroup(13).0^2,2)
        [1]
        sage: psage.modform.rational.degrees(13,2,DirichletGroup(13).0^2)
        [1]
        sage: psage.modform.rational.degrees(13,2)
        []
    """
    group = eps if eps else N
    from sage.all import ModularSymbols, dimension_new_cusp_forms
    d = dimension_new_cusp_forms(group, k)
    if d == 0:
        # A useful optimization!
        return []
    M = ModularSymbols(group=group, weight=k, sign=1).cuspidal_subspace()
    N = M.new_subspace()
    D = N.decomposition()
    # TODO: put in a consistency check.
    degs = [f.dimension() for f in D]
    assert sum(degs) == d, "major consistency check failed in degrees"
    return degs
예제 #10
0
파일: unfiled.py 프로젝트: merbst/psage
def modular_symbols_from_curve(C, N, num_factors=3):
    """
    Find the modular symbols spaces that shoudl correspond to the
    Jacobian of the given hyperelliptic curve, up to the number of
    factors we consider.
    
    INPUT:
        - C -- a hyperelliptic curve over QQ
        - N -- a positive integer
        - num_factors -- number of Euler factors to verify match up; this is
          important, because if, e.g., there is only one factor of degree g(C), we
          don't want to just immediately conclude that Jac(C) = A_f. 
        
    OUTPUT:
        - list of all sign 1 simple modular symbols factor of level N
          that correspond to a simple modular abelian A_f
          that is isogenous to Jac(C).  

    EXAMPLES::

        sage: from psage.modform.rational.unfiled import modular_symbols_from_curve

        sage: R.<x> = ZZ[]
        sage: f = x^7+4*x^6+5*x^5+x^4-3*x^3-2*x^2+1
        sage: C1 = HyperellipticCurve(f)
        sage: modular_symbols_from_curve(C1, 284)
        [Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 39 for Gamma_0(284) of weight 2 with sign 1 over Rational Field]
        
        sage: f = x^7-7*x^5-11*x^4+5*x^3+18*x^2+4*x-11
        sage: C2 = HyperellipticCurve(f)
        sage: modular_symbols_from_curve(C2, 284)
        [Modular Symbols subspace of dimension 3 of Modular Symbols space of dimension 39 for Gamma_0(284) of weight 2 with sign 1 over Rational Field]
    """
    # We will use the Eichler-Shimura relation and David Harvey's
    # p-adic point counting hypellfrob.  Harvey's code has the
    # constraint:   p > (2*g + 1)*(2*prec - 1).
    # So, find the smallest p not dividing N that satisfies the
    # above constraint, for our given choice of prec.

    f, f2 = C.hyperelliptic_polynomials()
    if f2 != 0:
        raise NotImplementedError, "curve must be of the form y^2 = f(x)"
    if f.degree() % 2 == 0:
        raise NotImplementedError, "curve must be of the form y^2 = f(x) with f(x) odd"

    prec = 1

    g = C.genus()
    B = (2 * g + 1) * (2 * prec - 1)

    from sage.rings.all import next_prime
    p = B

    # We use that if F(X) is the characteristic polynomial of the
    # Hecke operator T_p, then X^g*F(X+p/X) is the characteristic
    # polynomial of Frob_p, because T_p = Frob_p + p/Frob_p, according
    # to Eichler-Shimura.  Use this to narrow down the factors.

    from sage.all import ModularSymbols, Integers, get_verbose
    D = ModularSymbols(
        N, sign=1).cuspidal_subspace().new_subspace().decomposition()
    D = [A for A in D if A.dimension() == g]

    from sage.schemes.hyperelliptic_curves.hypellfrob import hypellfrob

    while num_factors > 0:
        p = next_prime(p)
        while N % p == 0:
            p = next_prime(p)

        R = Integers(p**prec)['X']
        X = R.gen()
        D2 = []
        # Compute the charpoly of Frobenius using hypellfrob
        M = hypellfrob(p, 1, f)
        H = R(M.charpoly())

        for A in D:
            F = R(A.hecke_polynomial(p))
            # Compute charpoly of Frobenius from F(X)
            G = R(F.parent()(X**g * F(X + p / X)))
            if get_verbose(): print(p, G, H)
            if G == H:
                D2.append(A)
        D = D2
        num_factors -= 1

    return D
예제 #11
0
def modular_symbols_ambient_from_lmfdb_mf(data):
    chi = dirichlet_character_from_lmfdb_mf(data)
    return ModularSymbols(chi.sage_character(), data[u'weight'])
예제 #12
0
    def __init__(self, p, congruence_type=1, sign=1, algorithm="custom", verbose=False, dump_dir=None):
        """
        Create a Kamienny criterion object.

        INPUT:

            - `p` -- prime -- verify that there is no order p torsion
              over a degree `d` field
            - `sign` -- 1 (default),-1 or 0 -- the sign of the modular symbols space to use 
            - ``algorithm`` -- "default" or "custom" whether to use a custom (faster)
              integral structure algorithm or to use the sage builtin algortihm
            - ``verbose`` -- bool; whether to print extra stuff while
              running.

        EXAMPLES::

            sage: from mdsage import *
            sage: C = KamiennyCriterion(29, algorithm="custom", verbose=False); C
            Kamienny's Criterion for p=29
            sage: C.use_custom_algorithm
            True
            sage: C.p
            29
            sage: C.verbose
            False        
        """
        self.verbose = verbose
        self.dump_dir = dump_dir
        if self.verbose: tm = cputime(); mem = get_memory_usage(); print("init")
        assert congruence_type == 0 or congruence_type == 1
        self.congruence_type=congruence_type
        try:
            p = ZZ(p)
            if congruence_type==0:
                self.congruence_group = Gamma0(p)
            if congruence_type==1:
                self.congruence_group = GammaH(p,[-1])
        except TypeError:
            self.congruence_group = GammaH(p.level(),[-1]+p._generators_for_H())
            self.congruence_type = ("H",self.congruence_group._list_of_elements_in_H())
            
        self.p = self.congruence_group.level()
  
        self.algorithm=algorithm
        self.sign=sign
        
        self.M = ModularSymbols(self.congruence_group, sign=sign)
        if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "modsym")
        self.S = self.M.cuspidal_submodule()
        if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "cuspsub")
        self.use_custom_algorithm = False
        if algorithm=="custom":
            self.use_custom_algorithm = True
        if self.use_custom_algorithm:
            int_struct = self.integral_cuspidal_subspace()
            if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "custom int_struct")
        else:    
            int_struct = self.S.integral_structure()
            if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "sage int_struct")
        self.S_integral = int_struct
        v = VectorSpace(GF(2), self.S.dimension()).random_element()
        self.v=v
        if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "rand_vect")
        if dump_dir:
            v.dump(dump_dir+"/vector%s_%s" % (p,congruence_type))
        if self.verbose: print("time and mem", cputime(tm), get_memory_usage(mem), "dump")