Beispiel #1
0
 def _height(P,check=True):
     if check:
         assert P.curve() == self._E, "the point P must lie on the curve from which the height function was created"
     Q = n * P
     cQ = denominator(Q[0])
     uQ = self.lift(Q,prec = prec)
     si = self.__padic_sigma_square(uQ, prec=prec)
     nn = self._q.valuation()
     qEu = self._q/p**nn
     return -(log(si*self._Csquare()/cQ) + log(uQ)**2/log(qEu)) / n**2
Beispiel #2
0
 def _height(P,check=True):
     if check:
         assert P.curve() == self._E, "the point P must lie on the curve from which the height function was created"
     Q = n * P
     cQ = denominator(Q[0])
     uQ = self.lift(Q,prec = prec)
     si = self.__padic_sigma_square(uQ, prec=prec)
     nn = self._q.valuation()
     qEu = self._q/p**nn
     return -(log(si*self._Csquare()/cQ) + log(uQ)**2/log(qEu)) / n**2
    def newton_sqrt(self,f,x0, prec):
        r"""
        Takes the square root of the power series `f` by Newton's method

        NOTE:

        this function should eventually be moved to `p`-adic power series ring

        INPUT:

        - f power series wtih coefficients in `\QQ_p` or an extension
        - x0 seeds the Newton iteration
        - prec precision

        OUTPUT:

        the square root of `f`

        EXAMPLES::

            sage: R.<x> = QQ['x']
            sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x)
            sage: Q = H(0,0)
            sage: u,v = H.local_coord(Q,prec=100)
            sage: K = Qp(11,5)
            sage: HK = H.change_ring(K)
            sage: L.<a> = K.extension(x^20-11)
            sage: HL = H.change_ring(L)
            sage: S = HL(u(a),v(a))
            sage: f = H.hyperelliptic_polynomials()[0]
            sage: y = HK.newton_sqrt( f(u(a)^11), a^11,5)
            sage: y^2 - f(u(a)^11)
            O(a^122)

        AUTHOR:

        - Jennifer Balakrishnan

        """
        z = x0
        try:
            x = f.parent().variable_name()
            if x!='a' :  #this is to distinguish between extensions of Qp that are finite vs. not
                S = f.base_ring()[[x]]
                x = S.gen()
        except ValueError:
            pass
        z = x0
        loop_prec = (log(RR(prec))/log(RR(2))).ceil()
        for i in range(loop_prec):
            z = (z+f/z)/2
        try:
            return z + O(x**prec)
        except (NameError,ArithmeticError,TypeError):
            return z
    def newton_sqrt(self,f,x0, prec):
        r"""
        Takes the square root of the power series `f` by Newton's method

        NOTE:

        this function should eventually be moved to `p`-adic power series ring

        INPUT:

        - f power series wtih coefficients in `\QQ_p` or an extension
        - x0 seeds the Newton iteration
        - prec precision

        OUTPUT:

        the square root of `f`

        EXAMPLES::

            sage: R.<x> = QQ['x']
            sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x)
            sage: Q = H(0,0)
            sage: u,v = H.local_coord(Q,prec=100)
            sage: K = Qp(11,5)
            sage: HK = H.change_ring(K)
            sage: L.<a> = K.extension(x^20-11)
            sage: HL = H.change_ring(L)
            sage: S = HL(u(a),v(a))
            sage: f = H.hyperelliptic_polynomials()[0]
            sage: y = HK.newton_sqrt( f(u(a)^11), a^11,5)
            sage: y^2 - f(u(a)^11)
            O(a^122)

        AUTHOR:

        - Jennifer Balakrishnan

        """
        z = x0
        try:
            x = f.parent().variable_name()
            if x!='a' :  #this is to distinguish between extensions of Qp that are finite vs. not
                S = f.base_ring()[[x]]
                x = S.gen()
        except ValueError:
            pass
        z = x0
        loop_prec = (log(RR(prec))/log(RR(2))).ceil()
        for i in range(loop_prec):
            z = (z+f/z)/2
        try:
            return z + O(x**prec)
        except (NameError,ArithmeticError,TypeError):
            return z
Beispiel #5
0
    def L_invariant(self, prec=20):
        r"""
        Returns the *mysterious* `\mathcal{L}`-invariant associated
        to an elliptic curve with split multiplicative reduction.

        One
        instance where this constant appears is in the exceptional
        case of the `p`-adic Birch and Swinnerton-Dyer conjecture as
        formulated in [MTT]_. See [Col]_ for a detailed discussion.

        INPUT:

        - ``prec`` - the `p`-adic precision, default is 20.

        REFERENCES:

        [MTT]_

        .. [Col] Pierre Colmez, Invariant `\mathcal{L}` et derivees de
           valeurs propres de Frobenius, preprint, 2004.

        EXAMPLES::

            sage: eq = EllipticCurve('130a1').tate_curve(5)
            sage: eq.L_invariant(prec=10)
            5^3 + 4*5^4 + 2*5^5 + 2*5^6 + 2*5^7 + 3*5^8 + 5^9 + O(5^10)
        """
        if not self.is_split():
            raise RuntimeError("The curve must have split multiplicative "
                               "reduction")
        qE = self.parameter(prec=prec)
        n = qE.valuation()
        u = qE / self._p**n
        # the p-adic logarithm of Iwasawa normalised by log(p) = 0
        return log(u) / n
Beispiel #6
0
    def L_invariant(self,prec=20):
        r"""
        Returns the *mysterious* `\mathcal{L}`-invariant associated
        to an elliptic curve with split multiplicative reduction. One
        instance where this constant appears is in the exceptional
        case of the `p`-adic Birch and Swinnerton-Dyer conjecture as
        formulated in [MTT]. See [Col] for a detailed discussion.

        INPUT:

        - ``prec`` - the `p`-adic precision, default is 20.

        REFERENCES:

        - [MTT] B. Mazur, J. Tate, and J. Teitelbaum,
          On `p`-adic analogues of the conjectures of Birch and
          Swinnerton-Dyer, Inventiones mathematicae 84, (1986), 1-48.

        - [Col] Pierre Colmez, Invariant `\mathcal{L}` et derivees de
          valeurs propores de Frobenius, preprint, 2004.

        EXAMPLES::

            sage: eq = EllipticCurve('130a1').tate_curve(5)
            sage: eq.L_invariant(prec=10)
            5^3 + 4*5^4 + 2*5^5 + 2*5^6 + 2*5^7 + 3*5^8 + 5^9 + O(5^10)
        """

        if not self.is_split():
               raise RuntimeError("The curve must have split multiplicative reduction")
        qE = self.parameter(prec=prec)
        n = qE.valuation()
        u = qE/self._p**n  # the p-adic logarithm of Iwasawa normalised by log(p) = 0
        return log(u)/n
def entropy(x, q=2):
    """
    Compute the entropy at `x` on the `q`-ary symmetric channel.

    INPUT:

    - ``x`` - real number in the interval `[0, 1]`.

    - ``q`` - (default: 2) integer greater than 1. This is the base of the
      logarithm.

    EXAMPLES::

        sage: codes.bounds.entropy(0, 2)
        0
        sage: codes.bounds.entropy(1/5,4).factor()    # optional - sage.symbolic
        1/10*(log(3) - 4*log(4/5) - log(1/5))/log(2)
        sage: codes.bounds.entropy(1, 3)              # optional - sage.symbolic
        log(2)/log(3)

    Check that values not within the limits are properly handled::

        sage: codes.bounds.entropy(1.1, 2)
        Traceback (most recent call last):
        ...
        ValueError: The entropy function is defined only for x in the interval [0, 1]
        sage: codes.bounds.entropy(1, 1)
        Traceback (most recent call last):
        ...
        ValueError: The value q must be an integer greater than 1
    """
    if x < 0 or x > 1:
        raise ValueError("The entropy function is defined only for x in the"
                         " interval [0, 1]")
    q = ZZ(q)  # This will error out if q is not an integer
    if q < 2:  # Here we check that q is actually at least 2
        raise ValueError("The value q must be an integer greater than 1")
    if x == 0:
        return 0
    if x == 1:
        return log(q - 1, q)
    H = x * log(q - 1, q) - x * log(x, q) - (1 - x) * log(1 - x, q)
    return H
Beispiel #8
0
def from_sparse6(G, g6_string):
    r"""
    Fill ``G`` with the data of a sparse6 string.

    INPUT:

    - ``G`` -- a graph

    - ``g6_string`` -- a sparse6 string

    EXAMPLE::

        sage: from sage.graphs.graph_input import from_sparse6
        sage: g = Graph()
        sage: from_sparse6(g, ':I`ES@obGkqegW~')
        sage: g.is_isomorphic(graphs.PetersenGraph())
        True
    """
    from .generic_graph_pyx import length_and_string_from_graph6, int_to_binary_string
    from math import ceil, floor
    from sage.misc.functional import log
    n = g6_string.find('\n')
    if n == -1:
        n = len(g6_string)
    s = g6_string[:n]
    n, s = length_and_string_from_graph6(s[1:])
    if n == 0:
        edges = []
    else:
        k = int(ceil(log(n, 2)))
        ords = [ord(i) for i in s]
        if any(o > 126 or o < 63 for o in ords):
            raise RuntimeError(
                "The string seems corrupt: valid characters are \n" +
                ''.join([chr(i) for i in range(63, 127)]))
        bits = ''.join([int_to_binary_string(o - 63).zfill(6) for o in ords])
        b = []
        x = []
        for i in range(int(floor(len(bits) / (k + 1)))):
            b.append(int(bits[(k + 1) * i:(k + 1) * i + 1], 2))
            x.append(int(bits[(k + 1) * i + 1:(k + 1) * i + k + 1], 2))
        v = 0
        edges = []
        for i in range(len(b)):
            if b[i] == 1:
                v += 1
            if x[i] > v:
                v = x[i]
            else:
                if v < n:
                    edges.append((x[i], v))
    G.add_vertices(range(n))
    G.add_edges(edges)
Beispiel #9
0
def from_sparse6(G, g6_string):
    r"""
    Fill ``G`` with the data of a sparse6 string.

    INPUT:

    - ``G`` -- a graph

    - ``g6_string`` -- a sparse6 string

    EXAMPLE::

        sage: from sage.graphs.graph_input import from_sparse6
        sage: g = Graph()
        sage: from_sparse6(g, ':I`ES@obGkqegW~')
        sage: g.is_isomorphic(graphs.PetersenGraph())
        True
    """
    from generic_graph_pyx import length_and_string_from_graph6, int_to_binary_string
    from math import ceil, floor
    from sage.misc.functional import log
    n = g6_string.find('\n')
    if n == -1:
        n = len(g6_string)
    s = g6_string[:n]
    n, s = length_and_string_from_graph6(s[1:])
    if n == 0:
        edges = []
    else:
        k = int(ceil(log(n,2)))
        ords = [ord(i) for i in s]
        if any(o > 126 or o < 63 for o in ords):
            raise RuntimeError("The string seems corrupt: valid characters are \n" + ''.join([chr(i) for i in xrange(63,127)]))
        bits = ''.join([int_to_binary_string(o-63).zfill(6) for o in ords])
        b = []
        x = []
        for i in xrange(int(floor(len(bits)/(k+1)))):
            b.append(int(bits[(k+1)*i:(k+1)*i+1],2))
            x.append(int(bits[(k+1)*i+1:(k+1)*i+k+1],2))
        v = 0
        edges = []
        for i in xrange(len(b)):
            if b[i] == 1:
                v += 1
            if x[i] > v:
                v = x[i]
            else:
                if v < n:
                    edges.append((x[i],v))
    G.add_vertices(range(n))
    G.add_edges(edges)
Beispiel #10
0
def gv_info_rate(n, delta, q):
    r"""
    The Gilbert-Varshamov lower bound for information rate.

    The Gilbert-Varshamov lower bound for information rate of a `q`-ary code of
    length `n` and minimum distance `n\delta`.

    EXAMPLES::

        sage: RDF(codes.bounds.gv_info_rate(100,1/4,3))  # abs tol 1e-15
        0.36704992608261894
    """
    q = ZZ(q)
    return log(gilbert_lower_bound(n, q, int(n * delta)), q) / n
Beispiel #11
0
    def an_padic(self, p, prec=0, use_twists=True):
        r"""
        Returns the conjectural order of `Sha(E/\QQ)`,
        according to the `p`-adic analogue of the Birch
        and Swinnerton-Dyer conjecture as formulated
        in [MTT]_ and [BP]_.

        REFERENCES:

        .. [MTT] B. Mazur, J. Tate, and J. Teitelbaum, On `p`-adic
           analogues of the conjectures of Birch and Swinnerton-Dyer,
           Inventiones mathematicae 84, (1986), 1-48.

        .. [BP] Dominique Bernardi and Bernadette Perrin-Riou,
           Variante `p`-adique de la conjecture de Birch et
           Swinnerton-Dyer (le cas supersingulier),
           C. R. Acad. Sci. Paris, Ser I. Math, 317 (1993), no 3,
           227-232.

        .. [SW] William Stein and Christian Wuthrich, Computations
           About Tate-Shafarevich Groups using Iwasawa theory,
           preprint 2009.

        INPUT:

        - ``p`` - a prime > 3

        - ``prec`` (optional) - the precision used in the computation of the `p`-adic L-Series

        - ``use_twists`` (default = ``True``) - If ``True`` the algorithm may change
          to a quadratic twist with minimal conductor to do the modular
          symbol computations rather than using the modular symbols of the
          curve itself. If ``False`` it forces the computation using the
          modular symbols of the curve itself.

        OUTPUT:  `p`-adic number - that conjecturally equals `\# Sha(E/\QQ)`.

        If ``prec`` is set to zero (default) then the precision is set so that
        at least the first `p`-adic digit of conjectural `\# Sha(E/\QQ)` is
        determined.

        EXAMPLES:

        Good ordinary examples::

            sage: EllipticCurve('11a1').sha().an_padic(5)    # rank 0
            1 + O(5^2)
            sage: EllipticCurve('43a1').sha().an_padic(5)    # rank 1
            1 + O(5)
            sage: EllipticCurve('389a1').sha().an_padic(5,4) # rank 2, long time (2s on sage.math, 2011)
            1 + O(5^3)
            sage: EllipticCurve('858k2').sha().an_padic(7)   # rank 0, non trivial sha, long time (10s on sage.math, 2011)
            Traceback (most recent call last):                           # 32-bit (see ticket :trac: `112111`)
            ...                                                          # 32-bit
            OverflowError: Python int too large to convert to C long     # 32-bit
            7^2 + O(7^6) # 64-bit
            sage: EllipticCurve('300b2').sha().an_padic(3)   # 9 elements in sha, long time (2s on sage.math, 2011)
            3^2 + O(3^6)
            sage: EllipticCurve('300b2').sha().an_padic(7, prec=6)  # long time
            2 + 7 + O(7^8)

        Exceptional cases::

            sage: EllipticCurve('11a1').sha().an_padic(11) # rank 0
            1 + O(11^2)
            sage: EllipticCurve('130a1').sha().an_padic(5) # rank 1
            1 + O(5)

        Non-split, but rank 0 case (:trac:`7331`)::

            sage: EllipticCurve('270b1').sha().an_padic(5) # rank 0, long time (2s on sage.math, 2011)
            1 + O(5^2)

        The output has the correct sign::

            sage: EllipticCurve('123a1').sha().an_padic(41) # rank 1, long time (3s on sage.math, 2011)
            1 + O(41)

        Supersingular cases::

            sage: EllipticCurve('34a1').sha().an_padic(5) # rank 0
            1 + O(5^2)
            sage: EllipticCurve('53a1').sha().an_padic(5) # rank 1, long time (11s on sage.math, 2011)
            1 + O(5)

        Cases that use a twist to a lower conductor::

            sage: EllipticCurve('99a1').sha().an_padic(5)
            1 + O(5)
            sage: EllipticCurve('240d3').sha().an_padic(5)  # sha has 4 elements here
            4 + O(5)
            sage: EllipticCurve('448c5').sha().an_padic(7,prec=4, use_twists=False)  # long time (2s on sage.math, 2011)
            2 + 7 + O(7^6)
            sage: EllipticCurve([-19,34]).sha().an_padic(5)  # see :trac: `6455`, long time (4s on sage.math, 2011)
            1 + O(5)
        """
        try:
            return self.__an_padic[(p,prec)]
        except AttributeError:
            self.__an_padic = {}
        except KeyError:
            pass

        E = self.Emin
        tam = E.tamagawa_product()
        tors = E.torsion_order()**2
        reg = E.padic_regulator(p)
        # todo : here we should cache the rank computation
        r = E.rank()


        if use_twists and p > 2:
            Et, D = E.minimal_quadratic_twist()
            # trac 6455 : we have to assure that the twist back is allowed
            D = ZZ(D)
            if D % p == 0:
                D = D/p
            for ell in D.prime_divisors():
                if ell % 2 == 1:
                    if Et.conductor() % ell**2 == 0:
                        D = D/ell
            ve = valuation(D,2)
            de = (D/2**ve).abs()
            if de % 4 == 3:
                de = -de
            Et = E.quadratic_twist(de)
            # now check individually if we can twist by -1 or 2 or -2
            Nmin = Et.conductor()
            Dmax = de
            for DD in [-4*de,8*de,-8*de]:
                Et = E.quadratic_twist(DD)
                if Et.conductor() < Nmin and valuation(Et.conductor(),2) <= valuation(DD,2):
                    Nmin = Et.conductor()
                    Dmax = DD
            D = Dmax
            Et = E.quadratic_twist(D)
            lp = Et.padic_lseries(p)
        else :
            lp = E.padic_lseries(p)
            D = 1

        if r == 0 and D == 1:
            # short cut for rank 0 curves, we do not
            # to compute the p-adic L-function, the leading
            # term will be the L-value divided by the Neron
            # period.
            ms = E.modular_symbol(sign=+1, normalize='L_ratio')
            lstar = ms(0)/E.real_components()
            bsd = tam/tors
            if prec == 0:
                prec = valuation(lstar/bsd, p)
            shan = Qp(p,prec=prec+2)(lstar/bsd)


        elif E.is_ordinary(p):
            K = reg.parent()
            lg = log(K(1+p))

            if (E.is_good(p) or E.ap(p) == -1):
                if not E.is_good(p):
                    eps = 2
                else:
                    eps = (1-arith.kronecker_symbol(D,p)/lp.alpha())**2
                # according to the p-adic BSD this should be equal to the leading term of the p-adic L-series divided by sha:
                bsdp = tam * reg * eps/tors/lg**r
            else:
                r += 1   # exceptional zero
                eq = E.tate_curve(p)
                Li = eq.L_invariant()

                # according to the p-adic BSD (Mazur-Tate-Teitelbaum)
                # this should be equal to the leading term of the p-adic L-series divided by sha:
                bsdp = tam * reg * Li/tors/lg**r


            v = bsdp.valuation()
            if v > 0:
                verbose("the prime is irregular.")

            # determine how much prec we need to prove at least the triviality of
            # the p-primary part of Sha

            if prec == 0:
                n = max(v,2)
                bounds = lp._prec_bounds(n,r+1)
                while bounds[r] <= v:
                    n += 1
                    bounds = lp._prec_bounds(n,r+1)
                verbose("set precision to %s"%n)
            else:
                n = max(2,prec)

            not_yet_enough_prec = True
            while not_yet_enough_prec:
                lps = lp.series(n,quadratic_twist=D,prec=r+1)
                lstar = lps[r]
                if (lstar != 0) or (prec != 0):
                    not_yet_enough_prec = False
                else:
                    n += 1
                    verbose("increased precision to %s"%n)

            shan = lstar/bsdp

        elif E.is_supersingular(p):
            K = reg[0].parent()
            lg = log(K(1+p))


            # according to the p-adic BSD this should be equal to the leading term of the D_p - valued
            # L-series :
            bsdp = tam /tors/lg**r * reg
            # note this is an element in Q_p^2

            verbose("the algebraic leading terms : %s"%bsdp)

            v = [bsdp[0].valuation(),bsdp[1].valuation()]

            if prec == 0:
                n = max(min(v)+2,3)
            else:
                n = max(3,prec)

            verbose("...computing the p-adic L-series")
            not_yet_enough_prec = True
            while not_yet_enough_prec:
                lps = lp.Dp_valued_series(n,quadratic_twist=D,prec=r+1)
                lstar = [lps[0][r],lps[1][r]]
                verbose("the leading terms : %s"%lstar)
                if (lstar[0] != 0 or lstar[1] != 0) or ( prec != 0):
                    not_yet_enough_prec = False
                else:
                    n += 1
                    verbose("increased precision to %s"%n)

            verbose("...putting things together")
            if bsdp[0] != 0:
                shan0 = lstar[0]/bsdp[0]
            else:
                shan0 = 0   # this should actually never happen
            if bsdp[1] != 0:
                shan1 = lstar[1]/bsdp[1]
            else:
                shan1 = 0   # this should conjecturally only happen when the rank is 0
            verbose("the two values for Sha : %s"%[shan0,shan1])

            # check consistency (the first two are only here to avoid a bug in the p-adic L-series
            # (namely the coefficients of zero-relative precision are treated as zero)
            if shan0 != 0 and shan1 != 0 and shan0 - shan1 != 0:
                raise RuntimeError("There must be a bug in the supersingular routines for the p-adic BSD.")

            #take the better
            if shan1 == 0 or shan0.precision_relative() > shan1.precision_relative():
                shan = shan0
            else:
                shan = shan1

        else:
            raise ValueError("The curve has to have semi-stable reduction at p.")

        self.__an_padic[(p,prec)] = shan
        return shan
Beispiel #12
0
def attack(m, q, r=4, sigma=3.0, subfield_only=False):
    K = CyclotomicField(m, 'z')
    z = K.gen()
    OK = K.ring_of_integers()
    G = K.galois_group()

    n = euler_phi(m)
    mprime = m / r
    nprime = euler_phi(mprime)
    Gprime = [tau for tau in G if tau(z**r) == z**r]

    R = PolynomialRing(IntegerRing(), 'a')
    a = R.gen()
    phim = a**n + 1
    D = DiscreteGaussianDistributionIntegerSampler(sigma)

    print "sampling f,g"
    while True:
        f = sum([D() * z**i for i in range(n)])
        fx = sum([f[i] * a**i for i in range(n)])

        res = inverse(fx, phim, q)
        if res[0]:
            f_inv = sum([res[1][i] * z**i for i in range(n)])
            print "f_inv * f = %s (mod %d)" % ((f * f_inv).mod(q), q)
            break

    g = sum([D() * z**i for i in range(n)])
    print "done sampling f, g"

    #h = [g*f^{-1)]_q
    h = (g * f_inv).mod(q)

    lognorm_f = log(f.vector().norm(), 2)
    lognorm_g = log(g.vector().norm(), 2)

    print "f*h - g = %s" % (f * h - g).mod(q)
    print "log q = ", log(q, 2).n(precision)
    print "log |f| = %s, log |g| = %s" % (lognorm_f.n(precision),
                                          lognorm_g.n(precision))
    print "log |(f,g)| = ", log(
        sqrt(f.vector().norm()**2 + g.vector().norm()**2), 2).n(precision)

    print "begin computing N(f), N(g), N(h), Tr(h), fbar"
    fprime = norm(f, Gprime)
    gprime = norm(g, Gprime)
    hprime = norm(h, Gprime).mod(q)
    htr = trace(h, Gprime)
    fbar = prod([tau(f) for tau in Gprime[1:]])
    print "end computing N(f), N(g), N(h), Tr(h), fbar"

    lognorm_fp = log(fprime.vector().norm(), 2)
    lognorm_gp = log(gprime.vector().norm(), 2)

    print "%d * log |f| - log |f'| = %s" % (r, r * lognorm_f.n(precision) -
                                            lognorm_fp.n(precision))
    print "log |(f', g')| = ", log(
        sqrt(fprime.vector().norm()**2 + gprime.vector().norm()**2),
        2).n(precision)
    print "log |N(f), Tr(g fbar)| = ", log(
        sqrt(fprime.vector().norm()**2 +
             trace(g * fbar, Gprime).vector().norm()**2), 2).n(precision)

    #(fprime, gprime) lies in the lattice \Lambda_hprime^q
    print "f'*h' - g' = %s " % (hprime * fprime - gprime).mod(q)
    print "N(f) Tr(h) - Tr(g fbar) = %s" % (htr * fprime -
                                            trace(g * fbar, Gprime)).mod(q)

    if not subfield_only:
        ntru_full = NTRU(h, K, q)
        full_sv = ntru_full.shortest_vector()

        print "log |v| = %s" % log(full_sv.norm(), 2).n(precision)

    ntru_subfield = NTRU_subfield(hprime, q, nprime, r)
    ntru_trace_subfield = NTRU_subfield(htr, q, nprime, r)

    print "begin computing Shortest Vector of subfield lattice"
    norm_sv = ntru_subfield.shortest_vector()
    tr_sv = ntru_trace_subfield.shortest_vector()
    print "end computing Shortest Vector of subfield lattice"

    norm_xp = sum(
        [coerce(Integer, norm_sv[i]) * z**(r * i) for i in range(nprime)])
    tr_xp = sum(
        [coerce(Integer, tr_sv[i]) * z**(r * i) for i in range(nprime)])

    print "Norm map: log |(x',y')| = ", log(norm_sv.norm(), 2).n(precision)
    print "Trace map: log |(x', y')| = ", log(tr_sv.norm(), 2).n(precision)
    #test if xprime belongs to <fprime>
    mat = []
    for i in range(nprime):
        coordinate = (fprime * z**(r * i)).vector().list()
        mat.append([coordinate[r * j] for j in range(nprime)])
    FL = IntegerLattice(mat)
    print norm_sv[:nprime] in FL
    print tr_sv[:nprime] in FL

    norm_x = norm_xp
    norm_y = mod_q(norm_x * h, q)

    tr_x = tr_xp
    tr_y = mod_q(tr_x * h, q)

    print "Norm map: log |(x,y)| = ", log(
        sqrt(norm_x.vector().norm()**2 + norm_y.vector().norm()**2),
        2).n(precision)
    print "Trace map: log |(x,y)| = ", log(
        sqrt(tr_x.vector().norm()**2 + tr_y.vector().norm()**2),
        2).n(precision)
Beispiel #13
0
 def neg_xlog2x(p):
     if p == 0:
         return 0
     else:
         return -p * log(p, 2)
Beispiel #14
0
    def an_padic(self, p, prec=0, use_twists=True):
        r"""
        Returns the conjectural order of `Sha(E/\QQ)`,
        according to the `p`-adic analogue of the Birch
        and Swinnerton-Dyer conjecture as formulated
        in [MTT]_ and [BP]_.

        REFERENCES:

        .. [MTT] \B. Mazur, J. Tate, and J. Teitelbaum, On `p`-adic
           analogues of the conjectures of Birch and Swinnerton-Dyer,
           Inventiones mathematicae 84, (1986), 1-48.

        .. [BP] Dominique Bernardi and Bernadette Perrin-Riou,
           Variante `p`-adique de la conjecture de Birch et
           Swinnerton-Dyer (le cas supersingulier),
           C. R. Acad. Sci. Paris, Sér I. Math., 317 (1993), no. 3,
           227-232.

        INPUT:

        - ``p`` - a prime > 3

        - ``prec`` (optional) - the precision used in the computation of the
          `p`-adic L-Series

        - ``use_twists`` (default = ``True``) - If ``True`` the algorithm may
          change to a quadratic twist with minimal conductor to do the modular
          symbol computations rather than using the modular symbols of the
          curve itself. If ``False`` it forces the computation using the
          modular symbols of the curve itself.

        OUTPUT:  `p`-adic number - that conjecturally equals `\# Sha(E/\QQ)`.

        If ``prec`` is set to zero (default) then the precision is set so that
        at least the first `p`-adic digit of conjectural `\# Sha(E/\QQ)` is
        determined.

        EXAMPLES:

        Good ordinary examples::

            sage: EllipticCurve('11a1').sha().an_padic(5)    # rank 0
            1 + O(5^22)
            sage: EllipticCurve('43a1').sha().an_padic(5)    # rank 1
            1 + O(5)
            sage: EllipticCurve('389a1').sha().an_padic(5,4) # rank 2, long time (2s on sage.math, 2011)
            1 + O(5^3)
            sage: EllipticCurve('858k2').sha().an_padic(7)   # rank 0, non trivial sha, long time (10s on sage.math, 2011)
            7^2 + O(7^24)
            sage: EllipticCurve('300b2').sha().an_padic(3)   # 9 elements in sha, long time (2s on sage.math, 2011)
            3^2 + O(3^24)
            sage: EllipticCurve('300b2').sha().an_padic(7, prec=6)  # long time
            2 + 7 + O(7^8)

        Exceptional cases::

            sage: EllipticCurve('11a1').sha().an_padic(11) # rank 0
            1 + O(11^22)
            sage: EllipticCurve('130a1').sha().an_padic(5) # rank 1
            1 + O(5)

        Non-split, but rank 0 case (:trac:`7331`)::

            sage: EllipticCurve('270b1').sha().an_padic(5) # rank 0, long time (2s on sage.math, 2011)
            1 + O(5^22)

        The output has the correct sign::

            sage: EllipticCurve('123a1').sha().an_padic(41) # rank 1, long time (3s on sage.math, 2011)
            1 + O(41)

        Supersingular cases::

            sage: EllipticCurve('34a1').sha().an_padic(5) # rank 0
            1 + O(5^22)
            sage: EllipticCurve('53a1').sha().an_padic(5) # rank 1, long time (11s on sage.math, 2011)
            1 + O(5)

        Cases that use a twist to a lower conductor::

            sage: EllipticCurve('99a1').sha().an_padic(5)
            1 + O(5)
            sage: EllipticCurve('240d3').sha().an_padic(5)  # sha has 4 elements here
            4 + O(5)
            sage: EllipticCurve('448c5').sha().an_padic(7,prec=4, use_twists=False)  # long time (2s on sage.math, 2011)
            2 + 7 + O(7^6)
            sage: EllipticCurve([-19,34]).sha().an_padic(5)  # see trac #6455, long time (4s on sage.math, 2011)
            1 + O(5)

        Test for :trac:`15737`::

            sage: E = EllipticCurve([-100,0])
            sage: s = E.sha()
            sage: s.an_padic(13)
            1 + O(13^20)
        """
        try:
            return self.__an_padic[(p,prec)]
        except AttributeError:
            self.__an_padic = {}
        except KeyError:
            pass

        E = self.Emin
        tam = E.tamagawa_product()
        tors = E.torsion_order()**2
        r = E.rank()
        if r > 0 :
            reg = E.padic_regulator(p)
        else:
            if E.is_supersingular(p):
                reg = vector([ Qp(p,20)(1), 0 ])
            else:
                reg = Qp(p,20)(1)

        if use_twists and p > 2:
            Et, D = E.minimal_quadratic_twist()
            # trac 6455 : we have to assure that the twist back is allowed
            D = ZZ(D)
            if D % p == 0:
                D = ZZ(D/p)
            for ell in D.prime_divisors():
                if ell % 2 == 1:
                    if Et.conductor() % ell**2 == 0:
                        D = ZZ(D/ell)
            ve = valuation(D,2)
            de = ZZ( (D/2**ve).abs() )
            if de % 4 == 3:
                de = -de
            Et = E.quadratic_twist(de)
            # now check individually if we can twist by -1 or 2 or -2
            Nmin = Et.conductor()
            Dmax = de
            for DD in [-4*de,8*de,-8*de]:
                Et = E.quadratic_twist(DD)
                if Et.conductor() < Nmin and valuation(Et.conductor(),2) <= valuation(DD,2):
                    Nmin = Et.conductor()
                    Dmax = DD
            D = Dmax
            Et = E.quadratic_twist(D)
            lp = Et.padic_lseries(p)
        else :
            lp = E.padic_lseries(p)
            D = 1

        if r == 0 and D == 1:
            # short cut for rank 0 curves, we do not
            # to compute the p-adic L-function, the leading
            # term will be the L-value divided by the Neron
            # period.
            ms = E.modular_symbol(sign=+1, normalize='L_ratio')
            lstar = ms(0)/E.real_components()
            bsd = tam/tors
            if prec == 0:
                #prec = valuation(lstar/bsd, p)
                prec = 20
            shan = Qp(p,prec=prec+2)(lstar/bsd)


        elif E.is_ordinary(p):
            K = reg.parent()
            lg = log(K(1+p))

            if (E.is_good(p) or E.ap(p) == -1):
                if not E.is_good(p):
                    eps = 2
                else:
                    eps = (1-arith.kronecker_symbol(D,p)/lp.alpha())**2
                # according to the p-adic BSD this should be equal to the leading term of the p-adic L-series divided by sha:
                bsdp = tam * reg * eps/tors/lg**r
            else:
                r += 1   # exceptional zero
                eq = E.tate_curve(p)
                Li = eq.L_invariant()

                # according to the p-adic BSD (Mazur-Tate-Teitelbaum)
                # this should be equal to the leading term of the p-adic L-series divided by sha:
                bsdp = tam * reg * Li/tors/lg**r


            v = bsdp.valuation()
            if v > 0:
                verbose("the prime is irregular for this curve.")

            # determine how much prec we need to prove at least the
            # triviality of the p-primary part of Sha

            if prec == 0:
                n = max(v,2)
                bounds = lp._prec_bounds(n,r+1)
                while bounds[r] <= v:
                    n += 1
                    bounds = lp._prec_bounds(n,r+1)
                verbose("set precision to %s"%n)
            else:
                n = max(2,prec)

            not_yet_enough_prec = True
            while not_yet_enough_prec:
                lps = lp.series(n,quadratic_twist=D,prec=r+1)
                lstar = lps[r]
                if (lstar != 0) or (prec != 0):
                    not_yet_enough_prec = False
                else:
                    n += 1
                    verbose("increased precision to %s"%n)

            shan = lstar/bsdp

        elif E.is_supersingular(p):
            K = reg[0].parent()
            lg = log(K(1+p))


            # according to the p-adic BSD this should be equal to the leading term of the D_p - valued
            # L-series :
            bsdp = tam /tors/lg**r * reg
            # note this is an element in Q_p^2

            verbose("the algebraic leading terms : %s"%bsdp)

            v = [bsdp[0].valuation(),bsdp[1].valuation()]

            if prec == 0:
                n = max(min(v)+2,3)
            else:
                n = max(3,prec)

            verbose("...computing the p-adic L-series")
            not_yet_enough_prec = True
            while not_yet_enough_prec:
                lps = lp.Dp_valued_series(n,quadratic_twist=D,prec=r+1)
                lstar = [lps[0][r],lps[1][r]]
                verbose("the leading terms : %s"%lstar)
                if (lstar[0] != 0 or lstar[1] != 0) or ( prec != 0):
                    not_yet_enough_prec = False
                else:
                    n += 1
                    verbose("increased precision to %s"%n)

            verbose("...putting things together")
            if bsdp[0] != 0:
                shan0 = lstar[0]/bsdp[0]
            else:
                shan0 = 0   # this should actually never happen
            if bsdp[1] != 0:
                shan1 = lstar[1]/bsdp[1]
            else:
                shan1 = 0   # this should conjecturally only happen when the rank is 0
            verbose("the two values for Sha : %s"%[shan0,shan1])

            # check consistency (the first two are only here to avoid a bug in the p-adic L-series
            # (namely the coefficients of zero-relative precision are treated as zero)
            if shan0 != 0 and shan1 != 0 and shan0 - shan1 != 0:
                raise RuntimeError("There must be a bug in the supersingular routines for the p-adic BSD.")

            #take the better
            if shan1 == 0 or shan0.precision_relative() > shan1.precision_relative():
                shan = shan0
            else:
                shan = shan1

        else:
            raise ValueError("The curve has to have semi-stable reduction at p.")

        self.__an_padic[(p,prec)] = shan
        return shan
Beispiel #15
0
    def _name_maker(self, names):
        r"""
        Helper function to create names of elements of algebraic structures.

        INPUT:
        Identical to the input for :class:`OperationTable` and :meth:`change_names`,
        so look there for details.

        OUTPUT:

        - ``width`` - an integer giving the maximum width of the strings
          describing the elements.  This is used for formatting the ASCII
          version of the table.
        - ``name_list`` - a list of strings naming the elements, in the
          same order as given by the :meth:`list` method.
        - ``name_dict`` - a dictionary giving the correspondence between the
          strings and the actual elements.  So the keys are the strings and
          the values are the elements of the structure.

        EXAMPLES:

        This routine is tested extensively in the :class:`OperationTable`
        and :meth:`change_names` methods.  So we just demonstrate
        the nature of the output here. ::

            sage: from sage.matrix.operation_table import OperationTable
            sage: G=SymmetricGroup(3)
            sage: T=OperationTable(G, operator.mul)
            sage: w, l, d = T._name_maker('letters')
            sage: w
            1
            sage: l[0]
            'a'
            sage: d['a']
            ()

        TESTS:

        We test the error conditions here, rather than as part of the
        doctests for the :class:`OperationTable` and :meth:`change_names`
        methods that rely on this one. ::

            sage: from sage.matrix.operation_table import OperationTable
            sage: G=AlternatingGroup(3)
            sage: T=OperationTable(G, operator.mul)
            sage: T._name_maker(['x'])
            Traceback (most recent call last):
            ...
            ValueError: list of element names must be the same size as the set, 1 != 3
            sage: T._name_maker(['x', 'y', 4])
            Traceback (most recent call last):
            ...
            ValueError: list of element names must only contain strings, not 4
            sage: T._name_maker('blatzo')
            Traceback (most recent call last):
            ...
            ValueError: element names must be a list, or one of the keywords: 'letters', 'digits', 'elements'
        """
        from sage.misc.functional import log
        name_list = []
        if names == 'digits':
            if self._n == 0 or self._n == 1:
                width = 1
            else:
                width = int(log(self._n-1,10))+1
            for i in range(self._n):
                name_list.append('{0:0{1}d}'.format(i,width))
        elif names == 'letters':
            from string import ascii_lowercase as letters
            from sage.rings.integer import Integer
            base = len(letters)
            if self._n == 0 or self._n == 1:
                width = 1
            else:
                width = int(log(self._n-1,base))+1
            for i in range(self._n):
                places = Integer(i).digits(base=base, digits=letters, padto=width)
                places.reverse()
                name_list.append(''.join(places))
        elif names == 'elements':
            width = 0
            for e in self._elts:
                estr = repr(e)
                if len(estr) > width:
                    width = len(estr)
                name_list.append(estr)
        elif isinstance(names, list):
            if len(names) != self._n:
                raise ValueError('list of element names must be the same size as the set, %s != %s'%(len(names), self._n))
            width = 0
            for name in names:
                if not isinstance(name, str):
                    raise ValueError('list of element names must only contain strings, not %s' % name)
                if len(name) > width:
                    width = len(name)
                name_list.append(name)
        else:
            raise ValueError("element names must be a list, or one of the keywords: 'letters', 'digits', 'elements'")
        name_dict = {}
        for i in range(self._n):
            name_dict[name_list[i]]=self._elts[i]
        return width, name_list, name_dict
Beispiel #16
0
 def neg_xlog2x(p):
     if p == 0:
         return 0
     else:  
         return -p*log(p,2)
Beispiel #17
0
def field_to_bytes(alpha, q):
    if q & 0x1 == 1:
        t = ceil(log(q, 2))
        l = ceil(t / 8)
        return Integer_to_bytes(alpha.lift(), l)