Example #1
0
    def upper_bound_on_elliptic_factors(self, p=None, ellmax=2):
        r"""
        Return an upper bound (provably correct) on the number of
        elliptic curves of conductor equal to the level of this
        supersingular module.

        INPUT:

        - ``p`` - (default: 997) prime to work modulo

        ALGORITHM: Currently we only use `T_2`.  Function will be
        extended to use more Hecke operators later.

        The prime p is replaced by the smallest prime that doesn't
        divide the level.

        EXAMPLE::

            sage: SupersingularModule(37).upper_bound_on_elliptic_factors()
            2

        (There are 4 elliptic curves of conductor 37, but only 2 isogeny
        classes.)
        """
        # NOTE: The heuristic runtime is *very* roughly `p^2/(2\cdot 10^6)`.
        #ellmax -- (default: 2) use Hecke operators T_ell with ell <= ellmax
        if p is None:
            p = 997

        while self.level() % p == 0:
            p = rings.next_prime(p)

        ell = 2
        t = self.hecke_matrix(ell).change_ring(rings.GF(p))

        # TODO: temporarily try using sparse=False
        # turn this off when sparse rank is optimized.
        t = t.dense_matrix()

        B = 2 * math.sqrt(ell)
        bnd = 0
        lower = -int(math.floor(B))
        upper = int(math.floor(B)) + 1
        for a in range(lower, upper):
            tm = verbose("computing T_%s - %s" % (ell, a))
            if a == lower:
                c = a
            else:
                c = 1
            for i in range(t.nrows()):
                t[i, i] += c
            tm = verbose("computing kernel", tm)
            #dim = t.kernel().dimension()
            dim = t.nrows() - t.rank()
            bnd += dim
            verbose('got dimension = %s; new bound = %s' % (dim, bnd), tm)
        return bnd
Example #2
0
    def upper_bound_on_elliptic_factors(self, p=None, ellmax=2):
        r"""
        Return an upper bound (provably correct) on the number of
        elliptic curves of conductor equal to the level of this
        supersingular module.

        INPUT:

        - ``p`` - (default: 997) prime to work modulo

        ALGORITHM: Currently we only use `T_2`.  Function will be
        extended to use more Hecke operators later.

        The prime p is replaced by the smallest prime that doesn't
        divide the level.

        EXAMPLE::

            sage: SupersingularModule(37).upper_bound_on_elliptic_factors()
            2

        (There are 4 elliptic curves of conductor 37, but only 2 isogeny
        classes.)
        """
        # NOTE: The heuristic runtime is *very* roughly `p^2/(2\cdot 10^6)`.
        # ellmax -- (default: 2) use Hecke operators T_ell with ell <= ellmax
        if p is None:
            p = 997

        while self.level() % p == 0:
            p = rings.next_prime(p)

        ell = 2
        t = self.hecke_matrix(ell).change_ring(rings.GF(p))

        # TODO: temporarily try using sparse=False
        # turn this off when sparse rank is optimized.
        t = t.dense_matrix()

        B = 2 * math.sqrt(ell)
        bnd = 0
        lower = -int(math.floor(B))
        upper = int(math.floor(B)) + 1
        for a in range(lower, upper):
            tm = verbose("computing T_%s - %s" % (ell, a))
            if a == lower:
                c = a
            else:
                c = 1
            for i in range(t.nrows()):
                t[i, i] += c
            tm = verbose("computing kernel", tm)
            # dim = t.kernel().dimension()
            dim = t.nrows() - t.rank()
            bnd += dim
            verbose("got dimension = %s; new bound = %s" % (dim, bnd), tm)
        return bnd
Example #3
0
File: hmf.py Project: bubonic/psage
def next_prime_not_dividing(P, I):
    while True:
        p = P.smallest_integer()
        if p == 1:
            Q = F.ideal(2)
        elif p % 5 in [2,3]: # inert
            Q = F.primes_above(next_prime(p))[0]
        elif p == 5:
            Q = F.ideal(7)
        else: # p split
            A = F.primes_above(p)
            if A[0] == P:
                Q = A[1]
            else:
                Q = F.primes_above(next_prime(p))[0]
        if not Q.divides(I):
            return Q
        else:
            P = Q # try again
Example #4
0
def next_prime_not_dividing(P, I):
    while True:
        p = P.smallest_integer()
        if p == 1:
            Q = F.ideal(2)
        elif p % 5 in [2,3]: # inert
            Q = F.primes_above(next_prime(p))[0]
        elif p == 5:
            Q = F.ideal(7)
        else: # p split
            A = F.primes_above(p)
            if A[0] == P:
                Q = A[1]
            else:
                Q = F.primes_above(next_prime(p))[0]
        if not Q.divides(I):
            return Q
        else:
            P = Q # try again
def max_det_prime(n):
    """
    Return the largest prime so that it is reasonably efficiency to
    compute modulo that prime with n x n matrices in LinBox.

    INPUT:
        n -- a positive integer
        
    OUTPUT:
        a prime number

    EXAMPLES:
        sage: from sage.matrix.matrix_integer_dense_hnf import max_det_prime
        sage: max_det_prime(10000)
        524309
        sage: max_det_prime(1000)
        2097169
        sage: max_det_prime(10)
        16777259
    """
    k = int(26 - math.ceil(math.log(n)*0.7213475205))
    return next_prime(2**k)
Example #6
0
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
Example #7
0
File: hmf.py Project: bubonic/psage
def next_prime_of_characteristic_coprime_to(P, I):
    p = next_prime(P.smallest_integer())
    N = ZZ(I.norm())
    while N%p == 0:
        p = next_prime(p)
    return F.primes_above(p)[0]
Example #8
0
def next_prime_of_characteristic_coprime_to(P, I):
    p = next_prime(P.smallest_integer())
    N = ZZ(I.norm())
    while N%p == 0:
        p = next_prime(p)
    return F.primes_above(p)[0]
Example #9
0
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