예제 #1
0
파일: qmodnz.py 프로젝트: sagemath/sage
    def random_element(self):
        r"""
        Return a random element of `\Q/n\Z`.

        The denominator is selected
        using the ``1/n`` distribution on integers, modified to return
        a positive value.  The numerator is then selected uniformly.

        EXAMPLES::

            sage: G = QQ/(6*ZZ)
            sage: G.random_element()
            47/16
            sage: G.random_element()
            1
            sage: G.random_element()
            3/5
        """
        if self.n == 0:
            return self(QQ.random_element())
        d = ZZ.random_element()
        if d >= 0:
            d = 2 * d + 1
        else:
            d = -2 * d
        n = ZZ.random_element((self.n * d).ceil())
        return self(n / d)
 def mult_order(x):
     ct = ZZ.one()
     cur = x
     while cur != one:
         cur *= x
         ct += ZZ.one()
     return ZZ(ct)
예제 #3
0
    def graded_dimension(self, k):
        r"""
        Return the dimension of the ``k``-th graded piece of ``self``.

        The `k`-th graded part of a free Lie algebra on `n` generators
        has dimension

        .. MATH::

            \frac{1}{k} \sum_{d \mid k} \mu(d) n^{k/d},

        where `\mu` is the Mobius function.

        REFERENCES:

        [MKO1998]_

        EXAMPLES::

            sage: L = LieAlgebra(QQ, 'x', 3)
            sage: H = L.Hall()
            sage: [H.graded_dimension(i) for i in range(1, 11)]
            [3, 3, 8, 18, 48, 116, 312, 810, 2184, 5880]
            sage: H.graded_dimension(0)
            0
        """
        if k == 0:
            return 0
        from sage.arith.all import moebius
        s = len(self.lie_algebra_generators())
        k = ZZ(k) # Make sure we have something that is in ZZ
        return sum(moebius(d) * s**(k // d) for d in k.divisors()) // k
예제 #4
0
파일: qmodnz.py 프로젝트: sagemath/sage
    def __iter__(self):
        r"""
        Create an iterator that generates the elements of `\Q/n\Z` without
        repetition, organized by increasing denominator.

        For a fixed denominator, elements are listed by increasing numerator.

        EXAMPLES:

        The first 19 elements of `\Q/5\Z`::

            sage: import itertools
            sage: list(itertools.islice(QQ/(5*ZZ), 19r))
            [0, 1, 2, 3, 4, 1/2, 3/2, 5/2, 7/2, 9/2, 1/3, 2/3, 4/3, 5/3,
             7/3, 8/3, 10/3, 11/3, 13/3]
        """
        if self.n == 0:
            for x in QQ:
                yield self(x)
        else:
            d = ZZ(0)
            while True:
                for a in d.coprime_integers((d * self.n).floor()):
                    yield self(a / d)
                d += 1
예제 #5
0
def add_sha_tor_primes(N1, N2):
    """
    Add the 'sha', 'sha_primes', 'torsion_primes' fields to every
    curve in the database whose conductor is between N1 and N2
    inclusive.
    """
    query = {}
    query["conductor"] = {"$gte": int(N1), "$lte": int(N2)}
    res = curves.find(query)
    res = res.sort([("conductor", pymongo.ASCENDING)])
    n = 0
    for C in res:
        label = C["lmfdb_label"]
        if n % 1000 == 0:
            print label
        n += 1
        torsion = ZZ(C["torsion"])
        sha = RR(C["sha_an"]).round()
        sha_primes = sha.prime_divisors()
        torsion_primes = torsion.prime_divisors()
        data = {}
        data["sha"] = int(sha)
        data["sha_primes"] = [int(p) for p in sha_primes]
        data["torsion_primes"] = [int(p) for p in torsion_primes]
        curves.update({"lmfdb_label": label}, {"$set": data}, upsert=True)
예제 #6
0
        def phi(self, i):
            r"""
            Return `\varphi_i` of ``self``.

            EXAMPLES::

                sage: S = crystals.OddNegativeRoots(['A', [2,2]])
                sage: mg = S.module_generator()
                sage: [mg.phi(i) for i in S.index_set()]
                [0, 0, 1, 0, 0]
                sage: b = mg.f(0)
                sage: [b.phi(i) for i in S.index_set()]
                [0, 1, 0, 1, 0]
                sage: b = mg.f_string([0,1,0,-1,0,-1]); b
                {-e[-2]+e[1], -e[-2]+e[2], -e[-1]+e[1]}
                sage: [b.phi(i) for i in S.index_set()]
                [2, 0, 0, 1, 1]

            TESTS::

                sage: S = crystals.OddNegativeRoots(['A', [2,1]])
                sage: def count_f(x, i):
                ....:     ret = -1
                ....:     while x is not None:
                ....:         x = x.f(i)
                ....:         ret += 1
                ....:     return ret
                sage: for x in S:
                ....:     for i in S.index_set():
                ....:         assert x.phi(i) == count_f(x, i)
            """
            if i == 0:
                return ZZ.zero() if (-1,1) in self.value else ZZ.one()

            count = 0
            ret = 0
            if i < 0:
                lst = sorted(self.value, key=lambda x: (x[1], -x[0]))
                for val in reversed(lst):
                    # We don't have to check val[1] because this is an odd root
                    if val[0] == i:
                        if count == 0:
                            ret += 1
                        else:
                            count -= 1
                    elif val[0] == i - 1:
                        count += 1

            else: # i > 0
                lst = sorted(self.value, key=lambda x: (-x[0], -x[1]))
                for val in lst:
                    # We don't have to check val[0] because this is an odd root
                    if val[1] == i:
                        if count == 0:
                            ret += 1
                        else:
                            count -= 1
                    elif val[1] == i + 1:
                        count += 1
            return ret
예제 #7
0
def twoadic(line):
    r""" Parses one line from a 2adic file.  Returns the label and a dict
    containing fields with keys '2adic_index', '2adic_log_level',
    '2adic_gens' and '2adic_label'.

    Input line fields:

    conductor iso number ainvs index level gens label

    Sample input lines:

    110005 a 2 [1,-1,1,-185793,29503856] 12 4 [[3,0,0,1],[3,2,2,3],[3,0,0,3]] X24
    27 a 1 [0,0,1,0,-7] inf inf [] CM
    """
    data = split(line)
    assert len(data) == 8
    label = data[0] + data[1] + data[2]
    model = data[7]
    if model == "CM":
        return label, {"2adic_index": int(0), "2adic_log_level": None, "2adic_gens": None, "2adic_label": None}

    index = int(data[4])
    level = ZZ(data[5])
    log_level = int(level.valuation(2))
    assert 2 ** log_level == level
    if data[6] == "[]":
        gens = []
    else:
        gens = data[6][1:-1].replace("],[", "];[").split(";")
        gens = [[int(c) for c in g[1:-1].split(",")] for g in gens]

    return label, {"2adic_index": index, "2adic_log_level": log_level, "2adic_gens": gens, "2adic_label": model}
예제 #8
0
파일: clt.py 프로젝트: zrathustra/mmap
    def __init__(self, params, asym=False):
        # set parameters
        (self.alpha, self.beta, self.rho, self.rho_f, self.eta, self.bound, self.n, self.k) = params

        self.x0 = ZZ(1)
        
        self.primes = [random_prime(2**self.eta, lbound = 2**(self.eta - 1), proof=False) for i in range(self.n)]
        primes = self.primes
        
        self.x0 = prod(primes)

        # generate CRT coefficients
        self.coeff = [ZZ((self.x0/p_i) * ZZ(Zmod(p_i)(self.x0/p_i)**(-1))) for p_i in primes]

        # generate secret g_i
        self.g = [random_prime(2**self.alpha, proof=False) for i in range(self.n)]

        # generate zs and zs^(-1)
        z = []
        zinv = []

        # generate z and z^(-1)
        if not asym:
            while True:
                z = ZZ.random_element(self.x0)  
                try:
                    zinv = ZZ(Zmod(self.x0)(z)**(-1))
                    break
                except ZeroDivisionError:
                    ''' Error occurred, retry sampling '''

            z, self.zinv = zip(*[(z,zinv) for i in range(self.k)])

        else: # asymmetric version
            for i in range(self.k):
                while True:
                    z_i = ZZ.random_element(self.x0)  
                    try:
                        zinv_i = ZZ(Zmod(self.x0)(z_i)**(-1))
                        break
                    except ZeroDivisionError:
                        ''' Error occurred, retry sampling '''

                z.append(z_i)
                zinv.append(zinv_i)

            self.zinv = zinv

        # generate p_zt
        zk = Zmod(self.x0)(1)
        self.p_zt = 0
        for z_i in z:
            zk *= Zmod(self.x0)(z_i)
        for i in range(self.n):
            self.p_zt += Zmod(self.x0)(ZZ(Zmod(self.primes[i])(self.g[i])**(-1) * Zmod(self.primes[i])(zk)) * ZZ.random_element(2**self.beta) * (self.x0/self.primes[i]))

        self.p_zt = Zmod(self.x0)(self.p_zt)
예제 #9
0
def iterator_fast(n, l):
    """
    Iterate over all ``l`` weighted integer vectors with total weight ``n``.

    INPUT:

    - ``n`` -- an integer
    - ``l`` -- the weights in weakly decreasing order

    EXAMPLES::

        sage: from sage.combinat.integer_vector_weighted import iterator_fast
        sage: list(iterator_fast(3, [2,1,1]))
        [[1, 1, 0], [1, 0, 1], [0, 3, 0], [0, 2, 1], [0, 1, 2], [0, 0, 3]]
        sage: list(iterator_fast(2, [2]))
        [[1]]

    Test that :trac:`20491` is fixed::

        sage: type(list(iterator_fast(2, [2]))[0][0])
        <type 'sage.rings.integer.Integer'>
    """
    if n < 0:
        return

    zero = ZZ.zero()
    one = ZZ.one()

    if not l:
        if n == 0:
            yield []
        return
    if len(l) == 1:
        if n % l[0] == 0:
            yield [n // l[0]]
        return

    k = 0
    cur = [n // l[k] + one]
    rem = n - cur[-1] * l[k] # Amount remaining
    while cur:
        cur[-1] -= one
        rem += l[k]
        if rem == zero:
            yield cur + [zero] * (len(l) - len(cur))
        elif cur[-1] < zero or rem < zero:
            rem += cur.pop() * l[k]
            k -= 1
        elif len(l) == len(cur) + 1:
            if rem % l[-1] == zero:
                yield cur + [rem // l[-1]]
        else:
            k += 1
            cur.append(rem // l[k] + one)
            rem -= cur[-1] * l[k]
예제 #10
0
def dimension__jacobi_scalar(k, m) :
    raise RuntimeError( "There is a bug in the implementation" )
    m = ZZ(m)
    
    dimension = 0
    for d in (m // m.squarefree_part()).isqrt().divisors() :
        m_d = m // d**2
        dimension += sum ( dimension__jacobi_scalar_f(k, m_d, f)
                            for f in m_d.divisors() )
    
    return dimension
예제 #11
0
    def __init__(self, p, base_ring):
        r"""
        Initialisation function.

        EXAMPLE::

            sage: pAdicWeightSpace(17)
            Space of 17-adic weight-characters defined over '17-adic Field with capped relative precision 20'
        """
        ParentWithBase.__init__(self, base=base_ring)
        p = ZZ(p)
        if not p.is_prime(): 
            raise ValueError, "p must be prime"
        self._p = p
        self._param = Qp(p)((p == 2 and 5) or (p + 1))
예제 #12
0
    def __iter__(self):
        """
        Iterate over ``self``.

        EXAMPLES::

            sage: S = SignedPermutations(2)
            sage: [x for x in S]
            [[1, 2], [1, -2], [-1, 2], [-1, -2],
             [2, 1], [2, -1], [-2, 1], [-2, -1]]
        """
        pmone = [ZZ.one(), -ZZ.one()]
        for p in self._P:
            for c in itertools.product(pmone, repeat=self._n):
                yield self.element_class(self, c, p)
예제 #13
0
    def long_element(self, index_set=None):
        """
        Return the longest element of ``self``, or of the
        parabolic subgroup corresponding to the given ``index_set``.

        INPUT:

        - ``index_set`` -- (optional) a subset (as a list or iterable)
          of the nodes of the indexing set

        EXAMPLES::

            sage: S = SignedPermutations(4)
            sage: S.long_element()
            [-1, -2, -3, -4]

        TESTS:

        Check that this is the element of maximal length (:trac:`25200`)::

            sage: S = SignedPermutations(4)
            sage: S.long_element().length() == max(x.length() for x in S)
            True
            sage: all(SignedPermutations(n).long_element().length() == n^2
            ....:     for n in range(2,10))
            True
        """
        if index_set is not None:
            return super(SignedPermutations, self).long_element()
        return self.element_class(self, [-ZZ.one()] * self._n, self._P.one())
예제 #14
0
    def _inner_qq(self, qelt1, qelt2):
        """
        Symmetric form between two elements of the root lattice
        associated to ``self``.

        EXAMPLES::

            sage: P = RootSystem(['F',4,1]).weight_lattice(extended=true)
            sage: Lambda = P.fundamental_weights()
            sage: V = IntegrableRepresentation(Lambda[0])
            sage: alpha = V.root_lattice().simple_roots()
            sage: Matrix([[V._inner_qq(alpha[i], alpha[j]) for j in V._index_set] for i in V._index_set])
            [   2   -1    0    0    0]
            [  -1    2   -1    0    0]
            [   0   -1    2   -1    0]
            [   0    0   -1    1 -1/2]
            [   0    0    0 -1/2    1]

        .. WARNING:

            If ``qelt1`` or ``qelt1`` accidentally gets coerced into
            the extended weight lattice, this will return an answer,
            and it will be wrong. To make this code robust, parents
            should be checked. This is not done since in the application
            the parents are known, so checking would unnecessarily slow
            us down.
        """
        mc1 = qelt1.monomial_coefficients()
        mc2 = qelt2.monomial_coefficients()
        zero = ZZ.zero()
        return sum(mc1.get(i, zero) * mc2.get(j, zero)
                   * self._cartan_matrix[i,j] / self._eps[i]
                   for i in self._index_set for j in self._index_set)
예제 #15
0
    def _inner_pp(self, pelt1, pelt2):
        """
        Symmetric form between an two elements of the weight lattice
        associated to ``self``.

        EXAMPLES::

            sage: P = RootSystem(['G',2,1]).weight_lattice(extended=true)
            sage: Lambda = P.fundamental_weights()
            sage: V = IntegrableRepresentation(Lambda[0])
            sage: alpha = V.root_lattice().simple_roots()
            sage: Matrix([[V._inner_pp(Lambda[i],P(alpha[j])) for j in V._index_set] for i in V._index_set])
            [  1   0   0]
            [  0 1/3   0]
            [  0   0   1]
            sage: Matrix([[V._inner_pp(Lambda[i],Lambda[j]) for j in V._index_set] for i in V._index_set])
            [  0   0   0]
            [  0 2/3   1]
            [  0   1   2]
        """
        mc1 = pelt1.monomial_coefficients()
        mc2 = pelt2.monomial_coefficients()
        zero = ZZ.zero()
        mc1d = mc1.get('delta', zero)
        mc2d = mc2.get('delta', zero)
        return sum(mc1.get(i,zero) * self._ac[i] * mc2d
                   + mc2.get(i,zero) * self._ac[i] * mc1d
                   for i in self._index_set) \
               + sum(mc1.get(i,zero) * mc2.get(j,zero) * self._ip[ii,ij]
                     for ii, i in enumerate(self._index_set_classical)
                     for ij, j in enumerate(self._index_set_classical))
예제 #16
0
    def __init__(self, field, num_integer_primes=10000, max_iterations=100):
        r"""
        Construct a new iterator of small degree one primes.

        EXAMPLES::

            sage: x = QQ['x'].gen()
            sage: K.<a> = NumberField(x^2 - 3)
            sage: K.primes_of_degree_one_list(3) # random
            [Fractional ideal (2*a + 1), Fractional ideal (-a + 4), Fractional ideal (3*a + 2)]
        """
        self._field = field
        self._poly = self._field.absolute_field("b").defining_polynomial()
        self._poly = ZZ["x"](self._poly.denominator() * self._poly())  # make integer polynomial

        # this uses that [ O_K : Z[a] ]^2 = | disc(f(x)) / disc(O_K) |
        from sage.libs.pari.all import pari

        self._prod_of_small_primes = ZZ(
            pari("TEMPn = %s; TEMPps = primes(TEMPn); prod(X = 1, TEMPn, TEMPps[X])" % num_integer_primes)
        )
        self._prod_of_small_primes //= self._prod_of_small_primes.gcd(self._poly.discriminant())

        self._integer_iter = iter(ZZ)
        self._queue = []
        self._max_iterations = max_iterations
예제 #17
0
def random_solution(B,K):
    r"""
    Returns a random solution in non-negative integers to the equation `a_1 + 2
    a_2 + 3 a_3 + ... + B a_B = K`, using a greedy algorithm.

    Note that this is *much* faster than using
    ``WeightedIntegerVectors.random_element()``.

    INPUT:

    - ``B``, ``K`` -- non-negative integers.

    OUTPUT:

    - list.

    EXAMPLES::

        sage: from sage.modular.overconvergent.hecke_series import random_solution
        sage: random_solution(5,10)
        [1, 1, 1, 1, 0]
    """
    a = []
    for i in xrange(B,1,-1):
        ai = ZZ.random_element((K // i) + 1)
        a.append(ai)
        K = K - ai*i
    a.append(K)
    a.reverse()

    return a
예제 #18
0
파일: heisenberg.py 프로젝트: sagemath/sage
    def __classcall_private__(cls, n=1, R=0):
        """
        Normalize input to ensure a unique representation.

        EXAMPLES::

            sage: H1 = groups.matrix.Heisenberg(n=2, R=5)
            sage: H2 = groups.matrix.Heisenberg(n=2, R=ZZ.quo(5))
            sage: H1 is H2
            True

            sage: H1 = groups.matrix.Heisenberg(n=2)
            sage: H2 = groups.matrix.Heisenberg(n=2, R=ZZ)
            sage: H1 is H2
            True
        """
        if n not in ZZ or n <= 0:
            raise TypeError("degree of Heisenberg group must be a positive integer")
        if R in ZZ:
            if R == 0:
                R = ZZ
            elif R > 1:
                R = ZZ.quo(R)
            else:
                raise ValueError("R must be a positive integer")
        elif R is not ZZ and R not in Rings().Finite():
            raise NotImplementedError("R must be a finite ring or ZZ")
        return super(HeisenbergGroup, cls).__classcall__(cls, n, R)
예제 #19
0
    def residue_field(self):
        r"""
        Return the residue class field of this ideal, which must be prime.

        .. TODO::

            Implement this for more general rings. Currently only defined
            for `\ZZ` and for number field orders.

        EXAMPLES::

            sage: P = ZZ.ideal(61); P
            Principal ideal (61) of Integer Ring
            sage: F = P.residue_field(); F
            Residue field of Integers modulo 61
            sage: pi = F.reduction_map(); pi
            Partially defined reduction map:
              From: Rational Field
              To:   Residue field of Integers modulo 61
            sage: pi(123/234)
            6
            sage: pi(1/61)
            Traceback (most recent call last):
            ...
            ZeroDivisionError: Cannot reduce rational 1/61 modulo 61: it has negative valuation
            sage: lift = F.lift_map(); lift
            Lifting map:
              From: Residue field of Integers modulo 61
              To:   Integer Ring
            sage: lift(F(12345/67890))
            33
            sage: (12345/67890) % 61
            33

        TESTS::

            sage: ZZ.ideal(96).residue_field()
            Traceback (most recent call last):
            ...
            ValueError: The ideal (Principal ideal (96) of Integer Ring) is not prime

        ::

            sage: R.<x>=QQ[]
            sage: I=R.ideal(x^2+1)
            sage: I.is_prime()
            True
            sage: I.residue_field()
            Traceback (most recent call last):
            ...
            TypeError: residue fields only supported for polynomial rings over finite fields.
        """
        if not self.is_prime():
            raise ValueError("The ideal (%s) is not prime"%self)
        from sage.rings.integer_ring import ZZ
        if self.ring() is ZZ:
            return ZZ.residue_field(self, check = False)
        raise NotImplementedError("residue_field() is only implemented for ZZ and rings of integers of number fields.")
예제 #20
0
def allbsd(line):
    r""" Parses one line from an allbsd file.  Returns the label and a
    dict containing fields with keys 'conductor', 'iso', 'number',
    'ainvs', 'rank', 'torsion', 'torsion_primes', 'tamagawa_product',
    'real_period', 'special_value', 'regulator', 'sha_an', 'sha',
    'sha_primes', all values being strings or floats or ints or lists
    of ints.

    Input line fields:

    conductor iso number ainvs rank torsion tamagawa_product real_period special_value regulator sha_an

    Sample input line:

    11 a 1 [0,-1,1,-10,-20] 0 5 5 1.2692093042795534217 0.25384186085591068434 1 1.00000000000000000000

    """
    data = split(line)
    label = data[0] + data[1] + data[2]
    ainvs = parse_ainvs(data[3])

    torsion = ZZ(data[5])
    sha_an = RR(data[10])
    sha = sha_an.round()
    sha_primes = sha.prime_divisors()
    torsion_primes = torsion.prime_divisors()

    data = {
        'conductor': int(data[0]),
        'iso': data[0] + data[1],
        'number': int(data[2]),
        'ainvs': ainvs,
        'rank': int(data[4]),
        'tamagawa_product': int(data[6]),
        'real_period': float(data[7]),
        'special_value': float(data[8]),
        'regulator': float(data[9]),
        'sha_an': float(sha_an),
        'sha':  int(sha),
        'sha_primes':  [int(p) for p in sha_primes],
        'torsion':  int(torsion),
        'torsion_primes':  [int(p) for p in torsion_primes]
        }

    return label, data
예제 #21
0
파일: util.py 프로젝트: mmasdeu/shp
def period_from_coords(p, E, P, prec=20):
    r"""
    Given a point `P` in the formal group of the elliptic curve `E` with split multiplicative reduction,
    this produces an element `u` in `\QQ_p^{\times}` mapped to the point `P` by the Tate parametrisation.
    The algorithm return the unique such element in `1+p\ZZ_p`.

    INPUT:

    - ``P`` - a point on the elliptic curve.

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

    """
    R = Qp(p, prec)
    if P[0].valuation(p) >= 0:
        raise ValueError, "The point must lie in the formal group."
    Etate = E.tate_curve(p)
    Eq = Etate.curve(prec=prec)
    isom = Etate._isomorphism(prec=prec)
    C = isom[0]
    r = isom[1]
    s = isom[2]
    t = isom[3]
    xx = r + C ** 2 * P[0]
    yy = t + s * C ** 2 * P[0] + C ** 3 * P[1]
    try:
        EqCp = Eq.change_ring(yy.parent())
        Pq = EqCp([xx, yy])
    except:
        raise RuntimeError, "Bug : Point %s does not lie on the curve " % [xx, yy]

    tt = -xx / yy
    eqhat = Eq.formal()
    eqlog = eqhat.log(prec + 3)
    z = eqlog(tt)
    u = ZZ(1)
    fac = ZZ(1)
    for i in range(1, 2 * prec + 1):
        fac = fac * i
        u = u + z ** i / fac
    q = Etate.parameter(prec=prec)
    un = u * q ** (-(u.valuation() / q.valuation()).floor())
    return un
예제 #22
0
파일: library.py 프로젝트: Findstat/sage
    def Birkhoff_polytope(self, n):
        """
        Return the Birkhoff polytope with `n!` vertices.

        The vertices of this polyhedron are the (flattened) `n` by `n`
        permutation matrices. So the ambient vector space has dimension `n^2`
        but the dimension of the polyhedron is `(n-1)^2`.

        INPUT:

        - ``n`` -- a positive integer giving the size of the permutation matrices.

        .. SEEALSO::

            :meth:`sage.matrix.matrix2.Matrix.as_sum_of_permutations` -- return
            the current matrix as a sum of permutation matrices

        EXAMPLES::

            sage: b3 = polytopes.Birkhoff_polytope(3)
            sage: b3.f_vector()
            (1, 6, 15, 18, 9, 1)
            sage: print b3.ambient_dim(), b3.dim()
            9 4
            sage: b3.is_lattice_polytope()
            True
            sage: p3 = b3.ehrhart_polynomial()     # optional - latte_int
            sage: p3                               # optional - latte_int
            1/8*t^4 + 3/4*t^3 + 15/8*t^2 + 9/4*t + 1
            sage: [p3(i) for i in [1,2,3,4]]       # optional - latte_int
            [6, 21, 55, 120]
            sage: [len((i*b3).integral_points()) for i in [1,2,3,4]]
            [6, 21, 55, 120]

            sage: b4 = polytopes.Birkhoff_polytope(4)
            sage: print b4.n_vertices(), b4.ambient_dim(), b4.dim()
            24 16 9
        """
        from itertools import permutations
        verts = []
        for p in permutations(range(n)):
            verts.append( [ZZ.one() if p[i]==j else ZZ.zero() for j in range(n) for i in range(n) ] )
        return Polyhedron(vertices=verts, base_ring=ZZ)
예제 #23
0
    def cardinality(self):
        """
        Return the cardinality of ``self``.

        EXAMPLES::

            sage: IntegerVectors(3, 3, min_part=1).cardinality()
            1
            sage: IntegerVectors(5, 3, min_part=1).cardinality()
            6
            sage: IntegerVectors(13, 4, max_part=4).cardinality()
            20
            sage: IntegerVectors(k=4, max_part=3).cardinality()
            256
            sage: IntegerVectors(k=3, min_part=2, max_part=4).cardinality()
            27
            sage: IntegerVectors(13, 4, min_part=2, max_part=4).cardinality()
            16
        """
        if self.k is None:
            if self.n is None:
                return PlusInfinity()
            if ('max_length' not in self.constraints
                    and self.constraints.get('min_part', 0) <= 0):
                return PlusInfinity()
        elif ('max_part' in self.constraints
                and self.constraints['max_part'] != PlusInfinity()):
            if (self.n is None and len(self.constraints) == 2
                    and 'min_part' in self.constraints
                    and self.constraints['min_part'] >= 0):
                num = self.constraints['max_part'] - self.constraints['min_part'] + 1
                return Integer(num ** self.k)
            if len(self.constraints) == 1:
                m = self.constraints['max_part']
                if self.n is None:
                    return Integer((m + 1) ** self.k)
                if m >= self.n:
                    return Integer(binomial(self.n + self.k - 1, self.n))
                # do by inclusion / exclusion on the number
                # i of parts greater than m
                return Integer(sum( (-1)**i * binomial(self.n+self.k-1-i*(m+1), self.k-1) \
                    * binomial(self.k,i) for i in range(self.n/(m+1)+1) ))
        return ZZ.sum(ZZ.one() for x in self)
예제 #24
0
파일: fields.py 프로젝트: Etn40ff/sage
        def gcd(self,other):
            """
            Greatest common divisor.

            NOTE:

            Since we are in a field and the greatest common divisor is
            only determined up to a unit, it is correct to either return
            zero or one. Note that fraction fields of unique factorization
            domains provide a more sophisticated gcd.

            EXAMPLES::

                sage: GF(5)(1).gcd(GF(5)(1))
                1
                sage: GF(5)(1).gcd(GF(5)(0))
                1
                sage: GF(5)(0).gcd(GF(5)(0))
                0

            For fields of characteristic zero (i.e., containing the
            integers as a sub-ring), evaluation in the integer ring is
            attempted. This is for backwards compatibility::

                sage: gcd(6.0,8); gcd(6.0,8).parent()
                2
                Integer Ring

            If this fails, we resort to the default we see above::

                sage: gcd(6.0*CC.0,8*CC.0); gcd(6.0*CC.0,8*CC.0).parent()
                1.00000000000000
                Complex Field with 53 bits of precision

            AUTHOR:

            - Simon King (2011-02): Trac ticket #10771

            """
            P = self.parent()
            try:
                other = P(other)
            except (TypeError, ValueError):
                raise ArithmeticError("The second argument can not be interpreted in the parent of the first argument. Can't compute the gcd")
            from sage.rings.integer_ring import ZZ
            if ZZ.is_subring(P):
                try:
                    return ZZ(self).gcd(ZZ(other))
                except TypeError:
                    pass
            # there is no custom gcd, so, we resort to something that always exists
            # (that's new behaviour)
            if self==0 and other==0:
                return P.zero()
            return P.one()
예제 #25
0
    def __init__(self, parent, k, chi=None):
        r"""
        Create a locally algebraic weight-character.

        EXAMPLES::

            sage: pAdicWeightSpace(29)(13, DirichletGroup(29, Qp(29)).0)
            (13, 29, [2 + 2*29 + ... + O(29^20)])
        """
        WeightCharacter.__init__(self, parent)
        k = ZZ(k)
        self._k = k
        if chi is None: 
            chi = trivial_character(self._p, QQ)
        n = ZZ(chi.conductor())
        if n == 1: 
            n = self._p
        if not n.is_power_of(self._p):
            raise ValueError, "Character must have %s-power conductor" % p
        self._chi = DirichletGroup(n, chi.base_ring())(chi)
예제 #26
0
    def one(self):
        """
        Return the identity element of ``self``.

        EXAMPLES::

            sage: S = SignedPermutations(4)
            sage: S.one()
            [1, 2, 3, 4]
        """
        return self.element_class(self, [ZZ.one()] * self._n, self._P.identity())
예제 #27
0
파일: fields.py 프로젝트: Etn40ff/sage
        def lcm(self,other):
            """
            Least common multiple.

            NOTE:

            Since we are in a field and the least common multiple is
            only determined up to a unit, it is correct to either return
            zero or one. Note that fraction fields of unique factorization
            domains provide a more sophisticated lcm.

            EXAMPLES::

                sage: GF(2)(1).lcm(GF(2)(0))
                0
                sage: GF(2)(1).lcm(GF(2)(1))
                1

            If the field contains the integer ring, it is first
            attempted to compute the gcd there::

                sage: lcm(15.0,12.0); lcm(15.0,12.0).parent()
                60
                Integer Ring

            If this fails, we resort to the default we see above::

                sage: lcm(6.0*CC.0,8*CC.0); lcm(6.0*CC.0,8*CC.0).parent()
                1.00000000000000
                Complex Field with 53 bits of precision
                sage: lcm(15.2,12.0)
                1.00000000000000

            AUTHOR:

            - Simon King (2011-02): Trac ticket #10771

            """
            P = self.parent()
            try:
                other = P(other)
            except (TypeError, ValueError):
                raise ArithmeticError("The second argument can not be interpreted in the parent of the first argument. Can't compute the lcm")
            from sage.rings.integer_ring import ZZ
            if ZZ.is_subring(P):
                try:
                    return ZZ(self).lcm(ZZ(other))
                except TypeError:
                    pass
            # there is no custom lcm, so, we resort to something that always exists
            if self==0 or other==0:
                return P.zero()
            return P.one()
예제 #28
0
파일: clt.py 프로젝트: zrathustra/mmap
    def encode(self, m, S):
        ''' encodes a vector m (in ZZ^n) to index set S '''

        c = Zmod(self.x0)(0)

        for i in range(self.n):
            r_i = ZZ.random_element(2**self.rho)
            c += Zmod(self.x0)((m[i] + self.g[i] * r_i) * self.coeff[i])

        zinv = prod([self.zinv[i] for i in S])

        return Zmod(self.x0)(c * zinv)
예제 #29
0
    def simple_reflection(self, i):
        r"""
        Return the ``i``-th simple reflection of ``self``.

        EXAMPLES::

            sage: S = SignedPermutations(4)
            sage: S.simple_reflection(1)
            [2, 1, 3, 4]
            sage: S.simple_reflection(4)
            [1, 2, 3, -4]
        """
        if i not in self.index_set():
            raise ValueError("i must be in the index set")
        if i < self._n:
            p = list(range(1, self._n + 1))
            p[i - 1] = i + 1
            p[i] = i
            return self.element_class(self, [ZZ.one()] * self._n, self._P(p))
        temp = [ZZ.one()] * self._n
        temp[-1] = -ZZ.one()
        return self.element_class(self, temp, self._P.identity())
예제 #30
0
        def coeff(m):
            m = ZZ(m)
            if m < 0:
                return ZZ(0)
            elif m == 0:
                return ZZ(1)

            factor = -2*k / QQ(bernoulli(k)) / lamk
            sum1   = sigma(m, k-1)
            if M.divides(m):
                sum2 = (lamk-1) * sigma(ZZ(m/M), k-1)
            else:
                sum2 = ZZ(0)
            if (M == 1):
                sum3 = ZZ(0)
            else:
                if (m == 1):
                    N = ZZ(1)
                else:
                    N = ZZ(m / M**ZZ(m.valuation(M)))
                sum3 = -sigma(ZZ(N), k-1) * ZZ(m/N)**(k-1) / (lamk + 1)

            return factor * (sum1 + sum2 + sum3) * dval**m
예제 #31
0
def my_level1_UpGj(p, k, m):
    r"""
    Returns a square matrix `A` over ``IntegerRing(p^m)``. The matrix `A` is the finite
    square matrix which occurs on input p,k and m in Step 6 of Algorithm 1 in
    [Lau2011]_. Notational change from paper: In Step 1 following Wan we defined
    j by `k = k_0 + j(p-1)` with `0 \le k_0 < p-1`. Here we replace j by
    ``kdiv`` so that we may use j as a column index for matrices.

    INPUT:

    - ``p`` -- prime at least 5.
    - ``k`` -- the weight.
    - ``m`` -- positive integer.

    OUTPUT:

    - the matrix A and the matrix E.
    """
    # Step 1
    t = cputime()

    if k == 1:
        k0 = p
    else:
        k0 = k % (p - 1)

    n = floor(((p + 1) / (p - 1)) * (m + 1))
    ell = dimension_modular_forms(1, k0 + n * (p - 1))
    ellp = ell * p
    mdash = m + ceil(n / (p + 1))

    verbose("done step 1", t)
    t = cputime()
    # Steps 2 and 3

    e, Ep1 = katz_expansions(k0, p, ellp, mdash, n)

    verbose("done steps 2+3", t)
    t = cputime()
    # Step 4

    G = compute_G(p, Ep1)

    verbose("done step 4a", t)
    t = cputime()
    k = ZZ(k)  # convert to sage integer
    if k == 1:
        kdiv = -1
    else:
        kdiv = k // (p - 1)
    Gkdiv = G**kdiv
    u = []
    for i in range(0, ell):
        ei = e[i]
        ui = Gkdiv * ei
        u.append(ui)

    verbose("done step 4b", t)
    t = cputime()
    # Step 5 and computation of T in Step 6

    S = e[0][0].parent()
    T = matrix(S, ell, ell)

    for i in range(0, ell):
        for j in range(0, ell):
            T[i, j] = u[i][p * j]

    verbose("done step 5", t)
    t = cputime()
    # Step 6: solve T = AE using fact E is upper triangular.
    # Warning: assumes that T = AE (rather than pT = AE) has
    # a solution over Z/(p^mdash). This has always been the case in
    # examples computed by the author, see Note 3.1.

    A = matrix(S, ell, ell)
    verbose("solving a square matrix problem of dimension %s" % ell, t)

    #A = solve_XAB_echelon(e.submatrix(0,0,nrows=ell,ncols=ell), T)

    for i in range(ell):
        Ti = T[i]
        for j in range(ell):
            ej = Ti.parent()([e[j][l] for l in range(0, ell)])
            lj = ZZ(ej[j])
            A[i, j] = S(ZZ(Ti[j]) / lj)
            Ti = Ti - A[i, j] * ej

    A = MatrixSpace(Zmod(p**m), ell, ell)(A)
    verbose("done step 6", t)

    e = Matrix(ZZ, ell, ell, [e[j][l] for j in range(ell) for l in range(ell)])
    return A, e, ell, mdash
예제 #32
0
def make_conductor(ecnfdata, hfield):
    N, c, d = [ZZ(c) for c in ecnfdata['conductor_ideal'][1:-1].split(',')]
    return hfield.K().ideal([N // d, c + d * hfield.K().gen()])
예제 #33
0
 def __init__(self, v, R=None, weight=2, character=None):
     if R is None:
         R = v[0].parent()
     self._qexp = [R(o) for o in v]
     self._weight = ZZ(weight)
     self._character = character
예제 #34
0
def enumerate_totallyreal_fields_all(n,
                                     B,
                                     verbose=0,
                                     return_seqs=False,
                                     return_pari_objects=True):
    r"""
    Enumerates *all* totally real fields of degree ``n`` with discriminant
    at most ``B``, primitive or otherwise.

    INPUT:

    - ``n`` -- integer, the degree
    - ``B`` -- integer, the discriminant bound
    - ``verbose`` -- boolean or nonnegative integer or string (default: 0)
      give a verbose description of the computations being performed. If
      ``verbose`` is set to ``2`` or more then it outputs some extra
      information. If ``verbose`` is a string then it outputs to a file
      specified by ``verbose``
    - ``return_seqs`` -- (boolean, default False) If ``True``, then return
      the polynomials as sequences (for easier exporting to a file). This
      also returns a list of four numbers, as explained in the OUTPUT
      section below.
    - ``return_pari_objects`` -- (boolean, default: True) if both
      ``return_seqs`` and ``return_pari_objects`` are ``False`` then it
      returns the elements as Sage objects; otherwise it returns pari
      objects.

    EXAMPLES::

        sage: enumerate_totallyreal_fields_all(4, 2000)
        [[725, x^4 - x^3 - 3*x^2 + x + 1],
        [1125, x^4 - x^3 - 4*x^2 + 4*x + 1],
        [1600, x^4 - 6*x^2 + 4],
        [1957, x^4 - 4*x^2 - x + 1],
        [2000, x^4 - 5*x^2 + 5]]
        sage: enumerate_totallyreal_fields_all(1, 10)
        [[1, x - 1]]

    TESTS:

    Each of the outputs must be elements of Sage if ``return_pari_objects``
    is set to ``False``::

        sage: enumerate_totallyreal_fields_all(2, 10)
        [[5, x^2 - x - 1], [8, x^2 - 2]]
        sage: type(enumerate_totallyreal_fields_all(2, 10)[0][1])
        <type 'cypari2.gen.Gen'>
        sage: enumerate_totallyreal_fields_all(2, 10, return_pari_objects=False)[0][1].parent()
        Univariate Polynomial Ring in x over Rational Field


    In practice most of these will be found by
    :func:`~sage.rings.number_field.totallyreal.enumerate_totallyreal_fields_prim`,
    which is guaranteed to return all primitive fields but often returns
    many non-primitive ones as well. For instance, only one of the five
    fields in the example above is primitive, but
    :func:`~sage.rings.number_field.totallyreal.enumerate_totallyreal_fields_prim`
    finds four out of the five (the exception being `x^4 - 6x^2 + 4`).

    The following was fixed in :trac:`13101`::

        sage: enumerate_totallyreal_fields_all(8, 10^6)  # long time (about 2 s)
        []
    """

    S = []
    counts = [0, 0, 0, 0]
    if len(divisors(n)) > 4:
        raise ValueError("Only implemented for n = p*q with p,q prime")
    for d in divisors(n):
        if d > 1 and d < n:
            Sds = enumerate_totallyreal_fields_prim(
                d, int(math.floor((1. * B)**(1. * d / n))), verbose=verbose)
            for i in range(len(Sds)):
                if verbose:
                    print("=" * 80)
                    print("Taking F =", Sds[i][1])
                F = NumberField(ZZx(Sds[i][1]), 't')
                T = enumerate_totallyreal_fields_rel(F,
                                                     n / d,
                                                     B,
                                                     verbose=verbose,
                                                     return_seqs=return_seqs)
                if return_seqs:
                    for i in range(4):
                        counts[i] += T[0][i]
                    S += [[t[0], pari(t[1]).Polrev()] for t in T[1]]
                else:
                    S += [[t[0], t[1]] for t in T]
                j = i + 1
                for E in enumerate_totallyreal_fields_prim(
                        n / d,
                        int(
                            math.floor((1. * B)**(1. / d) /
                                       (1. * Sds[i][0])**(n * 1. / d**2)))):
                    for EF in F.composite_fields(NumberField(ZZx(E[1]), 'u')):
                        if EF.degree() == n and EF.disc() <= B:
                            S.append(
                                [EF.disc(),
                                 pari(EF.absolute_polynomial())])
    S += enumerate_totallyreal_fields_prim(n, B, verbose=verbose)
    S.sort(key=lambda x: (x[0], [QQ(x) for x in x[1].polrecip().Vec()]))
    weed_fields(S)

    # Output.
    if verbose:
        saveout = sys.stdout
        if isinstance(verbose, str):
            fsock = open(verbose, 'w')
            sys.stdout = fsock
        # Else, print to screen
        print("=" * 80)
        print("Polynomials tested: {}".format(counts[0]))
        print("Polynomials with discriminant with large enough square"
              " divisor: {}".format(counts[1]))
        print("Irreducible polynomials: {}".format(counts[2]))
        print("Polynomials with nfdisc <= B: {}".format(counts[3]))
        for i in range(len(S)):
            print(S[i])
        if isinstance(verbose, str):
            fsock.close()
        sys.stdout = saveout

    # Make sure to return elements that belong to Sage
    if return_seqs:
        return [[ZZ(_) for _ in counts],
                [[ZZ(s[0]), [QQ(_) for _ in s[1].polrecip().Vec()]]
                 for s in S]]
    elif return_pari_objects:
        return S
    else:
        Px = PolynomialRing(QQ, 'x')
        return [[ZZ(s[0]), Px([QQ(_) for _ in s[1].list()])] for s in S]
예제 #35
0
    def __init__(self, E, P, proof=None, algorithm="pari", globally=False):
        r"""
        Initializes the reduction data for the elliptic curve `E` at the prime `P`.

        INPUT:

        - ``E`` -- an elliptic curve defined over a number field, or `\QQ`.

        - ``P`` -- a prime ideal of the field, or a prime integer if the field is `\QQ`.

        - ``proof`` (bool)-- if True, only use provably correct
          methods (default controlled by global proof module).  Note
          that the proof module is number_field, not elliptic_curves,
          since the functions that actually need the flag are in
          number fields.

        - ``algorithm`` (string, default: "pari") -- Ignored unless the
          base field is `\QQ`.  If "pari", use the PARI C-library
          ``ellglobalred`` implementation of Tate's algorithm over
          `\QQ`. If "generic", use the general number field
          implementation.

        - ``globally`` (bool, default: False) -- If True, the algorithm
          uses the generators of principal ideals rather than an arbitrary
          uniformizer.

        .. note::

           This function is not normally called directly by users, who
           may access the data via methods of the EllipticCurve
           classes.

        EXAMPLES::

            sage: from sage.schemes.elliptic_curves.ell_local_data import EllipticCurveLocalData
            sage: E = EllipticCurve('14a1')
            sage: EllipticCurveLocalData(E,2)
            Local data at Principal ideal (2) of Integer Ring:
            Reduction type: bad non-split multiplicative
            Local minimal model: Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x - 6 over Rational Field
            Minimal discriminant valuation: 6
            Conductor exponent: 1
            Kodaira Symbol: I6
            Tamagawa Number: 2

        ::

            sage: EllipticCurveLocalData(E,2,algorithm="generic")
            Local data at Principal ideal (2) of Integer Ring:
            Reduction type: bad non-split multiplicative
            Local minimal model: Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x - 6 over Rational Field
            Minimal discriminant valuation: 6
            Conductor exponent: 1
            Kodaira Symbol: I6
            Tamagawa Number: 2

        ::

            sage: EllipticCurveLocalData(E,2,algorithm="pari")
            Local data at Principal ideal (2) of Integer Ring:
            Reduction type: bad non-split multiplicative
            Local minimal model: Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x - 6 over Rational Field
            Minimal discriminant valuation: 6
            Conductor exponent: 1
            Kodaira Symbol: I6
            Tamagawa Number: 2

        ::

            sage: EllipticCurveLocalData(E,2,algorithm="unknown")
            Traceback (most recent call last):
            ...
            ValueError: algorithm must be one of 'pari', 'generic'

        ::

            sage: EllipticCurveLocalData(E,3)
            Local data at Principal ideal (3) of Integer Ring:
            Reduction type: good
            Local minimal model: Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x - 6 over Rational Field
            Minimal discriminant valuation: 0
            Conductor exponent: 0
            Kodaira Symbol: I0
            Tamagawa Number: 1

        ::

            sage: EllipticCurveLocalData(E,7)
            Local data at Principal ideal (7) of Integer Ring:
            Reduction type: bad split multiplicative
            Local minimal model: Elliptic Curve defined by y^2 + x*y + y = x^3 + 4*x - 6 over Rational Field
            Minimal discriminant valuation: 3
            Conductor exponent: 1
            Kodaira Symbol: I3
            Tamagawa Number: 3
        """
        self._curve = E
        K = E.base_field()
        p = check_prime(K, P)  # error handling done in that function
        if algorithm != "pari" and algorithm != "generic":
            raise ValueError("algorithm must be one of 'pari', 'generic'")

        self._reduction_type = None
        if K is QQ:
            self._prime = ZZ.ideal(p)
        else:
            self._prime = p

        if algorithm == "pari" and K is QQ:
            Eint = E.integral_model()
            data = Eint.pari_curve().elllocalred(p)
            self._fp = data[0].sage()
            self._KS = KodairaSymbol(data[1].sage())
            self._cp = data[3].sage()
            # We use a global minimal model since we can:
            self._Emin_reduced = Eint.minimal_model()
            self._val_disc = self._Emin_reduced.discriminant().valuation(p)
            if self._fp > 0:
                self._reduction_type = Eint.ap(p)  # = 0,-1 or +1
        else:
            self._Emin, ch, self._val_disc, self._fp, self._KS, self._cp, self._split = self._tate(
                proof, globally)
            if self._fp > 0:
                if self._Emin.c4().valuation(p) > 0:
                    self._reduction_type = 0
                elif self._split:
                    self._reduction_type = +1
                else:
                    self._reduction_type = -1
예제 #36
0
def Lpvalue(f,
            g,
            h,
            p,
            prec,
            N=None,
            modformsring=False,
            weightbound=6,
            eps=None,
            orthogonal_form=None,
            magma_args=None,
            force_computation=False,
            derivative_order=2):
    if magma_args is None:
        magma_args = {}
    from sage.interfaces.magma import Magma
    magma = Magma(**magma_args)
    ll, mm = g.weight(), h.weight()
    t = 0  # Assume t = 0 here
    kk = ll + mm - 2 * (1 + t)  # Is this correct?
    p = ZZ(p)
    if N is None:
        N = LCM([ZZ(f.level()), ZZ(g.level()), ZZ(h.level())])
        N = N.prime_to_m_part(p)

    print("Tame level N = %s, prime p = %s" % (N, p))
    prec = ZZ(prec)

    print("Step 1: Compute the Up matrix")
    # A, eimat, elldash, mdash = UpOperator(p, N, k=kk, m=prec, modformsring=modformsring, weightbound=weightbound)
    computation_name = '%s_%s_%s_%s_%s' % (p, N, kk, prec,
                                           'triv' if eps is None else 'char')
    tmp_filename = '/tmp/magma_mtx_%s.tmp' % computation_name
    import os.path
    from sage.misc.persist import db, db_save
    try:
        if force_computation:
            raise IOError
        Apow, ord_basis, eimat, zetapm, elldash, mdash = db(
            'Lpvalue_Apow_ordbasis_eimat_%s' % computation_name)
    except IOError:
        if force_computation or not os.path.exists(tmp_filename):
            if eps is not None:
                eps_magma = sage_character_to_magma(eps, magma=magma)
                Am, zetapm, eimatm, elldash, mdash = magma.UpOperatorData(
                    p, eps_magma, kk, prec, nvals=5)
            else:
                Am, zetapm, eimatm, elldash, mdash = magma.UpOperatorData(
                    p, N, kk, prec, nvals=5)
            print(" ..Converting to Sage...")
            Amodulus = Am[1, 1].Parent().Modulus().sage()
            Arows = Am.NumberOfRows().sage()
            Acols = Am.NumberOfColumns().sage()
            Emodulus = eimatm[1, 1].Parent().Modulus().sage()
            Erows = eimatm.NumberOfRows().sage()
            Ecols = eimatm.NumberOfColumns().sage()
            magma.eval('F := Open("%s", "w");' % tmp_filename)
            magma.eval('fprintf F, "Matrix(Zmod(%s),%s, %s, "' %
                       (Amodulus, Arows,
                        Acols))  #%%o) \\n", ElementToSequence(%s)'%Am.name())
            magma.eval('fprintf F, "%%o", ElementToSequence(%s)' % Am.name())
            magma.eval('fprintf F, ") \\n"')
            magma.eval(
                'fprintf F, "Matrix(Zmod(%s),%s, %s, "' %
                (Emodulus, Erows,
                 Ecols))  #%%o) \\n", ElementToSequence(%s)'%eimatm.name())
            magma.eval('fprintf F, "%%o", ElementToSequence(%s)' %
                       eimatm.name())
            magma.eval('fprintf F, ") \\n"')
            magma.eval('fprintf F, "%%o\\n", %s' % zetapm.name())
            magma.eval('fprintf F, "%%o\\n", %s' % elldash.name())
            magma.eval('fprintf F, "%%o\\n", %s' % mdash.name())
            magma.eval('delete F;')
            # zetapm, elldash, mdash = zetapm.sage(), elldash.sage(), mdash.sage()
            magma.quit()

        # Read A and eimat from file
        from sage.structure.sage_object import load
        from sage.misc.sage_eval import sage_eval
        with open(tmp_filename, 'r') as fmagma:
            A = sage_eval(fmagma.readline(), preparse=False)
            eimat = sage_eval(fmagma.readline(), preparse=False)
            zetapm = sage_eval(fmagma.readline())
            elldash = sage_eval(fmagma.readline())
            mdash = sage_eval(fmagma.readline())

        print("Step 3b: Apply Up^(r-1) to H")
        V = list(find_Apow_and_ord(A, eimat, p, prec))
        Apow, ord_basis = V
        V.extend([eimat, zetapm, elldash, mdash])
        db_save(V, 'Lpvalue_Apow_ordbasis_eimat_%s' % computation_name)
        from posix import remove
        remove(tmp_filename)

    print("Step 2: p-depletion, Coleman primitive, and multiply")
    H = depletion_coleman_multiply(g, h, p, p * elldash, t=0)

    print("Step 3a: Compute Up(H)")
    UpH = vector([H(p * n) for n in range(elldash)])

    try:
        Emat = eimat.apply_map(lambda x: x.lift()).submatrix(0,
                                                             0,
                                                             ncols=elldash)
    except AttributeError:
        Emat = eimat.submatrix(0, 0, ncols=elldash)

    alphas = solve_xAb_echelon(Emat, UpH)
    Hord = (alphas * Apow.apply_map(lambda x: x.lift())) * Emat
    Hord = Hord.change_ring(Apow.parent().base_ring())

    print("Step 4: Project onto f-component")
    R = Qp(p, prec)
    if orthogonal_form is None:
        ell, piHord = project_onto_eigenspace(f, ord_basis,
                                              Hord.change_ring(R), kk, N * p,
                                              eps)
        n = 1
        while f[n] == 0:
            n += 1
        Lpa = R(piHord[n]) / R(f[n])

    else:
        ell, piHord = project_onto_eigenspace(
            f,
            ord_basis,
            Hord.change_ring(R),
            kk,
            N * p,
            eps,
            derivative_order=derivative_order)
        gplus, gminus = f, orthogonal_form
        l1 = 2
        while N * p * ell % l1 == 0 or gplus[l1] == 0:
            l1 = next_prime(l1)
        proj_mat = matrix([[gplus[l1], gplus[p]], [gminus[l1], gminus[p]]])
        Lpalist = (matrix([piHord[l1], piHord[p]]) * proj_mat**-1).list()
        Lpa = Lpalist[0]
        if Lpa.valuation() > prec / 2:  # this is quite arbitrary!
            Lpa = Lpalist[1]
        n = 1
        while f[n] == 0:
            n += 1
        Lpa = Lpa / f[n]
    return Lpa, ell
예제 #37
0
def BinaryQF_reduced_representatives(D, primitive_only=False):
    r"""
    Returns a list of inequivalent reduced representatives for the
    equivalence classes of positive definite binary forms of
    discriminant D.

    INPUT:

    - `D` -- (integer) A negative discriminant.

    - ``primitive_only`` -- (bool, default False) flag controlling whether only
      primitive forms are included.

    OUTPUT:

    (list) A lexicographically-ordered list of inequivalent reduced
    representatives for the equivalence classes of positive definite binary
    forms of discriminant `D`.  If ``primitive_only`` is ``True`` then
    imprimitive forms (which only exist when `D` is not fundamental) are
    omitted; otherwise they are included.

    EXAMPLES::

        sage: BinaryQF_reduced_representatives(-4)
        [x^2 + y^2]

        sage: BinaryQF_reduced_representatives(-163)
        [x^2 + x*y + 41*y^2]

        sage: BinaryQF_reduced_representatives(-12)
        [x^2 + 3*y^2, 2*x^2 + 2*x*y + 2*y^2]

        sage: BinaryQF_reduced_representatives(-16)
        [x^2 + 4*y^2, 2*x^2 + 2*y^2]

        sage: BinaryQF_reduced_representatives(-63)
        [x^2 + x*y + 16*y^2, 2*x^2 - x*y + 8*y^2, 2*x^2 + x*y + 8*y^2, 3*x^2 + 3*x*y + 6*y^2, 4*x^2 + x*y + 4*y^2]

    The number of inequivalent reduced binary forms with a fixed negative
    fundamental discriminant D is the class number of the quadratic field
    `Q(\sqrt{D})`::

        sage: len(BinaryQF_reduced_representatives(-13*4))
        2
        sage: QuadraticField(-13*4, 'a').class_number()
        2
        sage: p=next_prime(2^20); p
        1048583
        sage: len(BinaryQF_reduced_representatives(-p))
        689
        sage: QuadraticField(-p, 'a').class_number()
        689

        sage: BinaryQF_reduced_representatives(-23*9)
        [x^2 + x*y + 52*y^2,
        2*x^2 - x*y + 26*y^2,
        2*x^2 + x*y + 26*y^2,
        3*x^2 + 3*x*y + 18*y^2,
        4*x^2 - x*y + 13*y^2,
        4*x^2 + x*y + 13*y^2,
        6*x^2 - 3*x*y + 9*y^2,
        6*x^2 + 3*x*y + 9*y^2,
        8*x^2 + 7*x*y + 8*y^2]
        sage: BinaryQF_reduced_representatives(-23*9, primitive_only=True)
        [x^2 + x*y + 52*y^2,
        2*x^2 - x*y + 26*y^2,
        2*x^2 + x*y + 26*y^2,
        4*x^2 - x*y + 13*y^2,
        4*x^2 + x*y + 13*y^2,
        8*x^2 + 7*x*y + 8*y^2]

    TESTS::

        sage: BinaryQF_reduced_representatives(5)
        Traceback (most recent call last):
        ...
        ValueError: discriminant must be negative and congruent to 0 or 1 modulo 4
    """
    D = ZZ(D)
    if not (D < 0 and (D % 4 in [0, 1])):
        raise ValueError(
            "discriminant must be negative and congruent to 0 or 1 modulo 4")

    # For a fundamental discriminant all forms are primitive so we need not check:
    if primitive_only:
        primitive_only = not is_fundamental_discriminant(D)

    form_list = []

    from sage.misc.all import xsrange
    from sage.rings.arith import gcd

    # Only iterate over positive a and over b of the same
    # parity as D such that 4a^2 + D <= b^2 <= a^2
    for a in xsrange(1, 1 + ((-D) // 3).isqrt()):
        a4 = 4 * a
        s = D + a * a4
        w = 1 + (s - 1).isqrt() if s > 0 else 0
        if w % 2 != D % 2: w += 1
        for b in xsrange(w, a + 1, 2):
            t = b * b - D
            if t % a4 == 0:
                c = t // a4
                if (not primitive_only) or gcd([a, b, c]) == 1:
                    if b > 0 and a > b and c > a:
                        form_list.append(BinaryQF([a, -b, c]))
                    form_list.append(BinaryQF([a, b, c]))

    form_list.sort()
    return form_list
예제 #38
0
    def dimension_cusp_forms(self, k=2, eps=None, algorithm="CohenOesterle"):
        r"""
        Return the dimension of the space of cusp forms for self, or the
        dimension of the subspace corresponding to the given character if one
        is supplied.

        INPUT:

        - ``k`` - an integer (default: 2), the weight.

        - ``eps`` - either None or a Dirichlet character modulo N, where N is
          the level of this group. If this is None, then the dimension of the
          whole space is returned; otherwise, the dimension of the subspace of
          forms of character eps.

        - ``algorithm`` -- either "CohenOesterle" (the default) or "Quer". This
          specifies the method to use in the case of nontrivial character:
          either the Cohen--Oesterle formula as described in Stein's book, or
          by Möbius inversion using the subgroups GammaH (a method due to
          Jordi Quer).

        EXAMPLES:

        We compute the same dimension in two different ways ::

            sage: K = CyclotomicField(3)
            sage: eps = DirichletGroup(7*43,K).0^2
            sage: G = Gamma1(7*43)

        Via Cohen--Oesterle::

            sage: Gamma1(7*43).dimension_cusp_forms(2, eps)
            28

        Via Quer's method::

            sage: Gamma1(7*43).dimension_cusp_forms(2, eps, algorithm="Quer")
            28

        Some more examples::

            sage: G.<eps> = DirichletGroup(9)
            sage: [Gamma1(9).dimension_cusp_forms(k, eps) for k in [1..10]]
            [0, 0, 1, 0, 3, 0, 5, 0, 7, 0]
            sage: [Gamma1(9).dimension_cusp_forms(k, eps^2) for k in [1..10]]
            [0, 0, 0, 2, 0, 4, 0, 6, 0, 8]
        """
        from .all import Gamma0

        # first deal with special cases

        if eps is None:
            return GammaH_class.dimension_cusp_forms(self, k)

        N = self.level()
        K = eps.base_ring()
        eps = DirichletGroup(N, K)(eps)

        if K.characteristic() != 0:
            raise NotImplementedError('dimension_cusp_forms() is only implemented for rings of characteristic 0')

        if eps.is_trivial():
            return Gamma0(N).dimension_cusp_forms(k)

        if (k <= 0) or ((k % 2) == 1 and eps.is_even()) or ((k%2) == 0 and eps.is_odd()):
            return ZZ(0)

        if k == 1:
            try:
                n = self.dimension_cusp_forms(1)
                if n == 0:
                    return ZZ(0)
                else: # never happens at present
                    raise NotImplementedError("Computations of dimensions of spaces of weight 1 cusp forms not implemented at present")
            except NotImplementedError:
                raise

        # now the main part

        if algorithm == "Quer":
            n = eps.order()
            dim = ZZ(0)
            for d in n.divisors():
                G = GammaH_constructor(N,(eps**d).kernel())
                dim = dim + moebius(d)*G.dimension_cusp_forms(k)
            return dim//phi(n)

        elif algorithm == "CohenOesterle":
            from sage.modular.dims import CohenOesterle
            return ZZ( K(Gamma0(N).index() * (k-1)/ZZ(12)) + CohenOesterle(eps,k) )

        else: #algorithm not in ["CohenOesterle", "Quer"]:
            raise ValueError("Unrecognised algorithm in dimension_cusp_forms")
예제 #39
0
def lift_map(target):
    """
    Create a lift map, to be used for lifting the cross ratios of a matroid
    representation.

    .. SEEALSO::

        :meth:`lift_cross_ratios() <sage.matroids.utilities.lift_cross_ratios>`

    INPUT:

    - ``target`` -- a string describing the target (partial) field.

    OUTPUT:

    - a dictionary

    Depending on the value of ``target``, the following lift maps will be created:

    - "reg": a lift map from `\GF3` to the regular partial field `(\ZZ, <-1>)`.

    - "sru": a lift map from `\GF7` to the
      sixth-root-of-unity partial field `(\QQ(z), <z>)`, where `z` is a sixth root
      of unity. The map sends 3 to `z`.

    - "dyadic": a lift map from `\GF{11}` to the dyadic partial field `(\QQ, <-1, 2>)`.

    - "gm": a lift map from `\GF{19}` to the golden mean partial field
      `(\QQ(t), <-1,t>)`, where `t` is a root of `t^2-t-1`. The map sends `5` to `t`.

    The example below shows that the latter map satisfies three necessary conditions stated in
    :meth:`lift_cross_ratios() <sage.matroids.utilities.lift_cross_ratios>`

    EXAMPLES::

        sage: from sage.matroids.utilities import lift_map
        sage: lm = lift_map('gm')
        sage: for x in lm:
        ....:     if (x == 1) is not (lm[x] == 1):
        ....:         print 'not a proper lift map'
        ....:     for y in lm:
        ....:         if (x+y == 0) and not (lm[x]+lm[y] == 0):
        ....:             print 'not a proper lift map'
        ....:         if (x+y == 1) and not (lm[x]+lm[y] == 1):
        ....:             print 'not a proper lift map'
        ....:         for z in lm:
        ....:             if (x*y==z) and not (lm[x]*lm[y]==lm[z]):
        ....:                 print 'not a proper lift map'

    """
    if target == "reg":
        R = GF(3)
        return {R(1): ZZ(1)}

    if target == "sru":
        R = GF(7)
        z = ZZ['z'].gen()
        S = NumberField(z * z - z + 1, 'z')
        return {R(1): S(1), R(3): S(z), R(3)**(-1): S(z)**5}

    if target == "dyadic":
        R = GF(11)
        return {R(1): QQ(1), R(-1): QQ(-1), R(2): QQ(2), R(6): QQ(1 / 2)}

    if target == "gm":
        R = GF(19)
        t = QQ['t'].gen()
        G = NumberField(t * t - t - 1, 't')
        return {
            R(1): G(1),
            R(5): G(t),
            R(1) / R(5): G(1) / G(t),
            R(-5): G(-t),
            R(-5)**(-1): G(-t)**(-1),
            R(5)**2: G(t)**2,
            R(5)**(-2): G(t)**(-2)
        }

    raise NotImplementedError(target)
예제 #40
0
    def __init__(self, coxeter_matrix, base_ring, index_set):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: W = CoxeterGroup([[1,3,2],[3,1,3],[2,3,1]])
            sage: TestSuite(W).run() # long time
            sage: W = CoxeterGroup([[1,3,2],[3,1,4],[2,4,1]], base_ring=QQbar)
            sage: TestSuite(W).run() # long time
            sage: W = CoxeterGroup([[1,3,2],[3,1,6],[2,6,1]])
            sage: TestSuite(W).run(max_runs=30) # long time
            sage: W = CoxeterGroup([[1,3,2],[3,1,-1],[2,-1,1]])
            sage: TestSuite(W).run(max_runs=30) # long time

        We check that :trac:`16630` is fixed::

            sage: CoxeterGroup(['D',4], base_ring=QQ).category()
            Category of finite irreducible coxeter groups
            sage: CoxeterGroup(['H',4], base_ring=QQbar).category()
            Category of finite irreducible coxeter groups
            sage: F = CoxeterGroups().Finite()
            sage: all(CoxeterGroup([letter,i]) in F
            ....:     for i in range(2,5) for letter in ['A','B','D'])
            True
            sage: all(CoxeterGroup(['E',i]) in F for i in range(6,9))
            True
            sage: CoxeterGroup(['F',4]).category()
            Category of finite irreducible coxeter groups
            sage: CoxeterGroup(['G',2]).category()
            Category of finite irreducible coxeter groups
            sage: all(CoxeterGroup(['H',i]) in F for i in range(3,5))
            True
            sage: all(CoxeterGroup(['I',i]) in F for i in range(2,5))
            True
        """
        self._matrix = coxeter_matrix
        n = coxeter_matrix.rank()
        # Compute the matrix with entries `2 \cos( \pi / m_{ij} )`.
        MS = MatrixSpace(base_ring, n, sparse=True)
        one = MS.one()
        # FIXME: Hack because there is no ZZ \cup \{ \infty \}: -1 represents \infty
        E = UniversalCyclotomicField().gen
        if base_ring is UniversalCyclotomicField():

            def val(x):
                if x == -1:
                    return 2
                else:
                    return E(2 * x) + ~E(2 * x)
        elif is_QuadraticField(base_ring):

            def val(x):
                if x == -1:
                    return 2
                else:
                    return base_ring((E(2 * x) + ~E(2 * x)).to_cyclotomic_field())
        else:
            from sage.functions.trig import cos
            from sage.symbolic.constants import pi

            def val(x):
                if x == -1:
                    return 2
                else:
                    return base_ring(2 * cos(pi / x))
        gens = [one + MS([SparseEntry(i, j, val(coxeter_matrix[index_set[i], index_set[j]]))
                          for j in range(n)])
                for i in range(n)]
        # Make the generators dense matrices for consistency and speed
        gens = [g.dense_matrix() for g in gens]
        category = CoxeterGroups()
        # Now we shall see if the group is finite, and, if so, refine
        # the category to ``category.Finite()``. Otherwise the group is
        # infinite and we refine the category to ``category.Infinite()``.
        if self._matrix.is_finite():
            category = category.Finite()
        else:
            category = category.Infinite()
        if all(self._matrix._matrix[i, j] == 2
               for i in range(n) for j in range(i)):
            category = category.Commutative()
        if self._matrix.is_irreducible():
            category = category.Irreducible()
        self._index_set_inverse = {i: ii
                                   for ii, i in enumerate(self._matrix.index_set())}
        FinitelyGeneratedMatrixGroup_generic.__init__(self, ZZ(n), base_ring,
                                                      gens, category=category)
예제 #41
0
    def dimension_eis(self, k=2, eps=None, algorithm="CohenOesterle"):
        r"""
        Return the dimension of the space of Eisenstein series forms for self,
        or the dimension of the subspace corresponding to the given character
        if one is supplied.

        INPUT:

        - ``k`` - an integer (default: 2), the weight.

        - ``eps`` - either None or a Dirichlet character modulo N, where N is
          the level of this group. If this is None, then the dimension of the
          whole space is returned; otherwise, the dimension of the subspace of
          Eisenstein series of character eps.

        - ``algorithm`` -- either "CohenOesterle" (the default) or "Quer". This
          specifies the method to use in the case of nontrivial character:
          either the Cohen--Oesterle formula as described in Stein's book, or
          by Möbius inversion using the subgroups GammaH (a method due to
          Jordi Quer).

        AUTHORS:

        - William Stein - Cohen--Oesterle algorithm

        - Jordi Quer - algorithm based on GammaH subgroups

        - David Loeffler (2009) - code refactoring

        EXAMPLES:

        The following two computations use different algorithms::

            sage: [Gamma1(36).dimension_eis(1,eps) for eps in DirichletGroup(36)]
            [0, 4, 3, 0, 0, 2, 6, 0, 0, 2, 3, 0]
            sage: [Gamma1(36).dimension_eis(1,eps,algorithm="Quer") for eps in DirichletGroup(36)]
            [0, 4, 3, 0, 0, 2, 6, 0, 0, 2, 3, 0]

        So do these::

            sage: [Gamma1(48).dimension_eis(3,eps) for eps in DirichletGroup(48)]
            [0, 12, 0, 4, 0, 8, 0, 4, 12, 0, 4, 0, 8, 0, 4, 0]
            sage: [Gamma1(48).dimension_eis(3,eps,algorithm="Quer") for eps in DirichletGroup(48)]
            [0, 12, 0, 4, 0, 8, 0, 4, 12, 0, 4, 0, 8, 0, 4, 0]
        """
        from .all import Gamma0

        # first deal with special cases

        if eps is None:
            return GammaH_class.dimension_eis(self, k)

        N = self.level()
        K = eps.base_ring()
        eps = DirichletGroup(N, K)(eps)

        if eps.is_trivial():
            return Gamma0(N).dimension_eis(k)

        # Note case of k = 0 and trivial character already dealt with separately, so k <= 0 here is valid:
        if (k <= 0) or ((k % 2) == 1 and eps.is_even()) or ((k%2) == 0 and eps.is_odd()):
            return ZZ(0)

        if algorithm == "Quer":
            n = eps.order()
            dim = ZZ(0)
            for d in n.divisors():
                G = GammaH_constructor(N,(eps**d).kernel())
                dim = dim + moebius(d)*G.dimension_eis(k)
            return dim//phi(n)

        elif algorithm == "CohenOesterle":
            from sage.modular.dims import CohenOesterle
            j = 2-k
            # We use the Cohen-Oesterle formula in a subtle way to
            # compute dim M_k(N,eps) (see Ch. 6 of William Stein's book on
            # computing with modular forms).
            alpha = -ZZ( K(Gamma0(N).index()*(j-1)/ZZ(12)) + CohenOesterle(eps,j) )
            if k == 1:
                return alpha
            else:
                return alpha - self.dimension_cusp_forms(k, eps)

        else: #algorithm not in ["CohenOesterle", "Quer"]:
            raise ValueError("Unrecognised algorithm in dimension_eis")
예제 #42
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
예제 #43
0
    def _group_gens(self):
        r"""
        Return a set of generators of the group `S(K_0) / S(K_u)` (which is
        either `{\rm SL}_2(\ZZ / p^u \ZZ)` if the conductor is even, and a
        quotient of an Iwahori subgroup if the conductor is odd).

        EXAMPLES::

            sage: from sage.modular.local_comp.type_space import example_type_space
            sage: example_type_space()._group_gens()
            [[1, 1, 0, 1], [0, -1, 1, 0]]
            sage: example_type_space(3)._group_gens()
            [[1, 1, 0, 1], [1, 0, 3, 1], [2, 0, 0, 5]]
        """
        if (self.conductor() % 2) == 0:
            return [[ZZ(1), ZZ(1), ZZ(0), ZZ(1)],
                    [ZZ(0), ZZ(-1), ZZ(1), ZZ(0)]]
        else:
            p = self.prime()
            if p == 2:
                return [[ZZ(1), ZZ(1), ZZ(0), ZZ(1)],
                        [ZZ(1), ZZ(0), ZZ(p), ZZ(1)]]
            else:
                a = Zmod(p**(self.u() + 1))(ZZ(Zmod(p).unit_gens()[0]))
                return [[ZZ(1), ZZ(1), ZZ(0), ZZ(1)],
                        [ZZ(1), ZZ(0), ZZ(p), ZZ(1)], [ZZ(a), 0, 0,
                                                       ZZ(~a)]]
예제 #44
0
    def _sage_(self):
        """
        Convert self to a Sage object.

        EXAMPLES::

            sage: a = axiom(1/2); a #optional - axiom
              1
              -
              2
            sage: a.sage()          #optional - axiom
            1/2
            sage: _.parent()        #optional - axiom
            Rational Field

            sage: gp(axiom(1/2))    #optional - axiom
            1/2

            sage: fricas(1/2).sage() #optional - fricas
            1/2

        DoubleFloat's in Axiom are converted to be in RDF in Sage.

        ::

            sage: axiom(2.0).as_type('DoubleFloat').sage()  #optional - axiom
            2.0
            sage: _.parent() #optional - axiom
            Real Double Field


            sage: axiom(2.1234)._sage_() #optional - axiom
            2.12340000000000
            sage: _.parent()             #optional - axiom
            Real Field with 53 bits of precision
            sage: a = RealField(100)(pi)
            sage: axiom(a)._sage_()      #optional - axiom
            3.1415926535897932384626433833
            sage: _.parent()             #optional - axiom
            Real Field with 100 bits of precision
            sage: axiom(a)._sage_() == a #optional - axiom
            True
            sage: axiom(2.0)._sage_() #optional - axiom
            2.00000000000000
            sage: _.parent() #optional  - axiom
            Real Field with 53 bits of precision


        We can also convert Axiom's polynomials to Sage polynomials.
            sage: a = axiom(x^2 + 1)   #optional - axiom
            sage: a.type()             #optional - axiom
            Polynomial Integer
            sage: a.sage()             #optional - axiom
            x^2 + 1
            sage: _.parent()           #optional - axiom
            Univariate Polynomial Ring in x over Integer Ring
            sage: axiom('x^2 + y^2 + 1/2').sage()    #optional - axiom
            y^2 + x^2 + 1/2
            sage: _.parent()                         #optional - axiom
            Multivariate Polynomial Ring in y, x over Rational Field


        """
        P = self._check_valid()
        type = str(self.type())

        if type in ["Type", "Domain"]:
            return self._sage_domain()

        if type == "Float":
            from sage.rings.all import RealField, ZZ
            prec = max(self.mantissa().length()._sage_(), 53)
            R = RealField(prec)
            x, e, b = self.unparsed_input_form().lstrip('float(').rstrip(
                ')').split(',')
            return R(ZZ(x) * ZZ(b)**ZZ(e))
        elif type == "DoubleFloat":
            from sage.rings.all import RDF
            return RDF(repr(self))
        elif type.startswith('Polynomial'):
            from sage.rings.all import PolynomialRing
            base_ring = P(type.lstrip('Polynomial '))._sage_domain()
            vars = str(self.variables())[1:-1]
            R = PolynomialRing(base_ring, vars)
            return R(self.unparsed_input_form())

        #If all else fails, try using the unparsed input form
        try:
            import sage.misc.sage_eval
            return sage.misc.sage_eval.sage_eval(self.unparsed_input_form())
        except Exception:
            raise NotImplementedError
예제 #45
0
def my_levelN_UpGj(p, N, k, m, modformsring, bound):
    r"""

    INPUT:

    - ``p`` -- prime at least 5.
    - ``N`` -- integer at least 2 and not divisible by p (level).
    - ``k`` -- the weight of f.
    - ``m`` -- positive integer.
    - ``modformsring`` -- True or False.
    - ``bound`` -- (even) positive integer.

    OUTPUT:

    - the matrix A and the matrix E.
    """
    t = cputime()
    # Step 1

    if k == 1:
        k0 = p
    else:
        k0 = k % (p - 1)
    n = floor(((p + 1) / (p - 1)) * (m + 1))
    elldash = compute_elldash(p, N, k0, n)
    elldashp = elldash * p
    mdash = m + ceil(n / (p + 1))

    verbose("done step 1", t)
    t = cputime()
    # Steps 2 and 3
    e, Ep1 = my_higher_level_katz_exp(p, N, k0, m, mdash, elldash, elldashp,
                                      modformsring, bound)
    ell = dimension(transpose(e)[0].parent())
    S = e[0, 0].parent()

    verbose("done steps 2+3", t)
    t = cputime()
    # Step 4

    R = Ep1.parent()
    G = compute_G(p, Ep1)
    Alist = []

    verbose("done step 4a", t)
    t = cputime()

    k = ZZ(k)  # convert to sage integer

    if k == 1:
        kdiv = -1
    else:
        kdiv = k // (p - 1)
    Gkdiv = G**kdiv

    T = matrix(S, ell, elldash)
    for i in range(ell):
        ei = R(e[i].list())
        Gkdivei = Gkdiv * ei
        # act by G^kdiv
        for j in range(0, elldash):
            T[i, j] = Gkdivei[p * j]

    verbose("done steps 4b and 5", t)
    t = cputime()

    # Step 6: solve T = AE using fact E is upper triangular.
    # Warning: assumes that T = AE (rather than pT = AE) has
    # a solution over Z/(p^mdash). This has always been the case in
    # examples computed by the author, see Note 3.1.

    A = matrix(S, ell, ell)
    verbose("solving a square matrix problem of dimension %s" % ell)
    verbose("elldash is %s" % elldash)

    for i in range(0, ell):
        Ti = T[i]
        for j in range(0, ell):
            ej = Ti.parent()([e[j][l] for l in range(0, elldash)])
            ejleadpos = ej.nonzero_positions()[0]
            lj = ZZ(ej[ejleadpos])
            A[i, j] = S(ZZ(Ti[j]) / lj)
            Ti = Ti - A[i, j] * ej

    # A = solve_XAB_echelon(e.submatrix(0,0,nrows=ell,ncols=ell),T.submatrix(0,0,ncols=ell))

    A = MatrixSpace(Zmod(p**m), ell, ell)(A)
    verbose("done step 6", t)
    return A, e, elldash, mdash
예제 #46
0
    def dimension_new_cusp_forms(self, k=2, p=0):
        r"""
        Return the dimension of the space of new (or `p`-new)
        weight `k` cusp forms for this congruence subgroup.

        INPUT:

        - `k` -- an integer (default: 2), the weight. Not fully
          implemented for `k = 1`.
        - `p` -- integer (default: 0); if nonzero, compute the
          `p`-new subspace.

        OUTPUT: Integer

        ALGORITHM:

        This comes from the formula given in Theorem 1 of
        http://www.math.ubc.ca/~gerg/papers/downloads/DSCFN.pdf

        EXAMPLES::

            sage: Gamma0(11000).dimension_new_cusp_forms()
            240
            sage: Gamma0(11000).dimension_new_cusp_forms(k=1)
            0
            sage: Gamma0(22).dimension_new_cusp_forms(k=4)
            3
            sage: Gamma0(389).dimension_new_cusp_forms(k=2,p=17)
            32

        TESTS::

             sage: L = [1213, 1331, 2169, 2583, 2662, 2745, 3208,
             ....:      3232, 3465, 3608, 4040, 4302, 4338]
             sage: all(Gamma0(N).dimension_new_cusp_forms(2)==100 for N in L)
             True
        """
        from sage.arith.all import moebius
        from sage.functions.other import floor

        N = self.level()
        k = ZZ(k)

        if not (p == 0 or N % p):
            return (self.dimension_cusp_forms(k) -
                    2 * self.restrict(N // p).dimension_new_cusp_forms(k))

        if k < 2 or k % 2:
            return ZZ.zero()

        factors = list(N.factor())

        def s0(q, a):
            # function s_0^#
            if a == 1:
                return 1 - 1 / q
            elif a == 2:
                return 1 - 1 / q - 1 / q**2
            else:
                return (1 - 1 / q) * (1 - 1 / q**2)

        def vinf(q, a):
            # function v_oo^#
            if a % 2:
                return 0
            elif a == 2:
                return q - 2
            else:
                return q**(a / 2 - 2) * (q - 1)**2

        def v2(q, a):
            # function v_2^#
            if q % 4 == 1:
                if a == 2:
                    return -1
                else:
                    return 0
            elif q % 4 == 3:
                if a == 1:
                    return -2
                elif a == 2:
                    return 1
                else:
                    return 0
            elif a in (1, 2):
                return -1
            elif a == 3:
                return 1
            else:
                return 0

        def v3(q, a):
            # function v_3^#
            if q % 3 == 1:
                if a == 2:
                    return -1
                else:
                    return 0
            elif q % 3 == 2:
                if a == 1:
                    return -2
                elif a == 2:
                    return 1
                else:
                    return 0
            elif a in (1, 2):
                return -1
            elif a == 3:
                return 1
            else:
                return 0

        res = (k - 1) / 12 * N * prod(s0(q, a) for q, a in factors)
        res -= prod(vinf(q, a) for q, a in factors) / ZZ(2)
        res += (
            (1 - k) / 4 + floor(k / 4)) * prod(v2(q, a) for q, a in factors)
        res += (
            (1 - k) / 3 + floor(k / 3)) * prod(v3(q, a) for q, a in factors)
        if k == 2:
            res += moebius(N)
        return res
예제 #47
0
    def S_to_Q(self,S,Q):
        r"""
        Given $S$ a point on self over an extension field, computes the
        Coleman integrals $\{\int_S^Q x^i dx/2y \}_{i=0}^{2g-1}$

        **one should be able to feed $S,Q$ into coleman_integral,
        but currently that segfaults**

        INPUT:

        - S: a point with coordinates in an extension of $\Q_p$ (with unif. a)
        - Q: a non-Weierstrass point defined over $\Q_p$

        OUTPUT:

        the Coleman integrals $\{\int_S^Q x^i dx/2y \}_{i=0}^{2g-1}$ in terms of $a$

        EXAMPLES::

            sage: R.<x> = QQ['x']
            sage: H = HyperellipticCurve(x^3-10*x+9)
            sage: K = Qp(5,6)
            sage: HK = H.change_ring(K)
            sage: J.<a> = K.extension(x^20-5)
            sage: HJ  = H.change_ring(J)
            sage: w = HK.invariant_differential()
            sage: x,y = HK.monsky_washnitzer_gens()
            sage: P = HK(1,0)
            sage: Q = HK(0,3)
            sage: S = HK.get_boundary_point(HJ,P)
            sage: P_to_S = HK.P_to_S(P,S)
            sage: S_to_Q = HJ.S_to_Q(S,Q)
            sage: P_to_S + S_to_Q
            (2*a^40 + a^80 + a^100 + O(a^105), a^20 + 2*a^40 + 4*a^60 + 2*a^80 + O(a^105))
            sage: HK.coleman_integrals_on_basis(P,Q)
            (2*5^2 + 5^4 + 5^5 + 3*5^6 + O(5^7), 5 + 2*5^2 + 4*5^3 + 2*5^4 + 5^6 + O(5^7))

        AUTHOR:

        - Jennifer Balakrishnan

        """
        FS = self.frobenius(S)
        FS = (FS[0],FS[1])
        FQ = self.frobenius(Q)
        import sage.schemes.elliptic_curves.monsky_washnitzer as monsky_washnitzer
        try:
            M_frob, forms = self._frob_calc
        except AttributeError:
            M_frob, forms = self._frob_calc = monsky_washnitzer.matrix_of_frobenius_hyperelliptic(self)
        try:
            HJ = self._curve_over_ram_extn
            K = HJ.base_ring()
        except AttributeError:
            HJ = S.scheme()
            K = self.base_ring()
        g = self.genus()
        prec2 = K.precision_cap()
        p = K.prime()
        dim = 2*g
        V = VectorSpace(K,dim)
        if S == FS:
            S_to_FS = V(dim*[0])
        else:
            P = self(ZZ(FS[0][0]),ZZ(FS[1][0]))
            x,y = self.local_coord(P,prec2)
            integrals = [(x**i*x.derivative()/(2*y)).integral() for i in range(dim)]
            S_to_FS = vector([I(FS[1])-I(S[1]) for I in integrals])
        if HJ(Q[0],Q[1]) == HJ(FQ):
            FQ_to_Q = V(dim*[0])
        else:
            FQ_to_Q = V(self.tiny_integrals_on_basis(FQ, Q))
        try:
            L = [f(K(S[0]), K(S[1])) - f(K(Q[0]), K(Q[1])) for f in forms]
        except ValueError:
            forms = [f.change_ring(K) for f in forms]
            L = [f(S[0], S[1]) - f(Q[0], Q[1]) for f in forms]
        b = V(L)
        M_sys = matrix(K, M_frob).transpose() - 1
        B = (~M_sys)
        v = [B.list()[i].valuation() for i in range(len(B.list()))]
        vv= min(v)
        B = (p**(-vv)*B).change_ring(K)
        B = p**(vv)*B
        return B*(b-S_to_FS-FQ_to_Q)
예제 #48
0
파일: ambient_R.py 프로젝트: yarv/sage
class ModularFormsAmbient_R(ambient.ModularFormsAmbient):
    def __init__(self, M, base_ring):
        """
        Ambient space of modular forms over a ring other than QQ.

        EXAMPLES::

            sage: M = ModularForms(23,2,base_ring=GF(7)) ## indirect doctest
            sage: M
            Modular Forms space of dimension 3 for Congruence Subgroup Gamma0(23) of weight 2 over Finite Field of size 7
            sage: M == loads(dumps(M))
            True
        """
        self.__M = M
        if M.character() is not None:
            self.__R_character = M.character().change_ring(base_ring)
        else:
            self.__R_character = None
        ambient.ModularFormsAmbient.__init__(self, M.group(), M.weight(),
                                             base_ring, M.character())

    @cached_method(
        key=lambda self, sign: ZZ(sign)
    )  # convert sign to an Integer before looking this up in the cache
    def modular_symbols(self, sign=0):
        r"""
        Return the space of modular symbols attached to this space, with the given sign (default 0).

        TESTS::

            sage: K.<i> = QuadraticField(-1)
            sage: chi = DirichletGroup(5, base_ring = K).0
            sage: L.<c> = K.extension(x^2 - 402*i)
            sage: M = ModularForms(chi, 7, base_ring = L)
            sage: symbs = M.modular_symbols()
            sage: symbs.character() == chi
            True
            sage: symbs.base_ring() == L
            True
        """
        sign = ZZ(sign)
        return self.__M.modular_symbols(sign).change_ring(self.base_ring())

    def _repr_(self):
        """
        String representation for self.

        EXAMPLES::

            sage: M = ModularForms(23,2,base_ring=GF(7)) ## indirect doctest
            sage: M._repr_()
            'Modular Forms space of dimension 3 for Congruence Subgroup Gamma0(23) of weight 2 over Finite Field of size 7'

            sage: chi = DirichletGroup(109).0 ** 36
            sage: ModularForms(chi, 2, base_ring = chi.base_ring())
            Modular Forms space of dimension 9, character [zeta3] and weight 2 over Cyclotomic Field of order 108 and degree 36
        """
        s = str(self.__M)
        i = s.find('over')
        if i != -1:
            s = s[:i]
        return s + 'over %s' % self.base_ring()

    def _compute_q_expansion_basis(self, prec=None):
        """
        Compute q-expansions for a basis of self to precision prec.

        EXAMPLES::

            sage: M = ModularForms(23,2,base_ring=GF(7))
            sage: M._compute_q_expansion_basis(10)
            [q + 6*q^3 + 6*q^4 + 5*q^6 + 2*q^7 + 6*q^8 + 2*q^9 + O(q^10),
            q^2 + 5*q^3 + 6*q^4 + 2*q^5 + q^6 + 2*q^7 + 5*q^8 + O(q^10),
            1 + 5*q^3 + 5*q^4 + 5*q^6 + 3*q^8 + 5*q^9 + O(q^10)]

        TESTS:

        This checks that :trac:`13445` is fixed::

            sage: M = ModularForms(Gamma1(29), base_ring=GF(29))
            sage: S = M.cuspidal_subspace()
            sage: 0 in [f.valuation() for f in S.basis()]
            False
            sage: len(S.basis()) == dimension_cusp_forms(Gamma1(29), 2)
            True
        """
        if prec is None:
            prec = self.prec()
        R = self._q_expansion_ring()
        c = self.base_ring().characteristic()
        if c == 0:
            B = self.__M.q_expansion_basis(prec)
            return [R(f) for f in B]
        elif c.is_prime_power():
            K = self.base_ring()
            p = K.characteristic().prime_factors()[0]
            from sage.rings.all import GF
            Kp = GF(p)
            newB = [
                f.change_ring(K) for f in list(
                    self.__M.cuspidal_subspace().q_integral_basis(prec))
            ]
            A = Kp**prec
            gens = [f.padded_list(prec) for f in newB]
            V = A.span(gens)
            B = [f.change_ring(K) for f in self.__M.q_integral_basis(prec)]
            for f in B:
                fc = f.padded_list(prec)
                gens.append(fc)
                if not A.span(gens) == V:
                    newB.append(f)
                    V = A.span(gens)
            if len(newB) != self.dimension():
                raise RuntimeError(
                    "The dimension of the space is %s but the basis we computed has %s elements"
                    % (self.dimension(), len(newB)))
            lst = [R(f) for f in newB]
            return [f / f[f.valuation()] for f in lst]
        else:
            # this returns a basis of q-expansions, without guaranteeing that
            # the first vectors form a basis of the cuspidal subspace
            # TODO: bring this in line with the other cases
            # simply using the above code fails because free modules over
            # general rings do not have a .span() method
            B = self.__M.q_integral_basis(prec)
            return [R(f) for f in B]

    def cuspidal_submodule(self):
        r"""
        Return the cuspidal subspace of this space.

        EXAMPLES::

            sage: C = CuspForms(7, 4, base_ring=CyclotomicField(5)) # indirect doctest
            sage: type(C)
            <class 'sage.modular.modform.cuspidal_submodule.CuspidalSubmodule_R_with_category'>
        """
        return CuspidalSubmodule_R(self)

    def change_ring(self, R):
        r"""
        Return this modular forms space with the base ring changed to the ring R.

        EXAMPLES::

            sage: chi = DirichletGroup(109, CyclotomicField(3)).0
            sage: M9 = ModularForms(chi, 2, base_ring = CyclotomicField(9))
            sage: M9.change_ring(CyclotomicField(15))
            Modular Forms space of dimension 10, character [zeta3 + 1] and weight 2 over Cyclotomic Field of order 15 and degree 8
            sage: M9.change_ring(QQ)
            Traceback (most recent call last):
            ...
            ValueError: Space cannot be defined over Rational Field
        """
        if not R.has_coerce_map_from(self.__M.base_ring()):
            raise ValueError("Space cannot be defined over %s" % R)
        return ModularFormsAmbient_R(self.__M, R)
예제 #49
0
def q_binomial(n, k, q=None, algorithm='auto'):
    r"""
    Return the `q`-binomial coefficient.

    This is also known as the Gaussian binomial coefficient, and is defined by

    .. MATH::

        \binom{n}{k}_q = \frac{(1-q^n)(1-q^{n-1}) \cdots (1-q^{n-k+1})}
        {(1-q)(1-q^2)\cdots (1-q^k)}.

    See :wikipedia:`Gaussian_binomial_coefficient`.

    If `q` is unspecified, then the variable is the generator `q` for
    a univariate polynomial ring over the integers.

    INPUT:

    - ``n, k`` -- the values `n` and `k` defined above

    - ``q`` -- (default: ``None``) the variable `q`; if ``None``, then use a
      default variable in `\ZZ[q]`

    - ``algorithm`` -- (default: ``'auto'``) the algorithm to use and can be
      one of the following:

      - ``'auto'`` -- automatically choose the algorithm; see the algorithm
        section below
      - ``'naive'`` -- use the naive algorithm
      - ``'cyclotomic'`` -- use cyclotomic algorithm

    ALGORITHM:

    The naive algorithm uses the product formula. The cyclotomic
    algorithm uses a product of cyclotomic polynomials
    (cf. [CH2006]_).

    When the algorithm is set to ``'auto'``, we choose according to
    the following rules:

    - If ``q`` is a polynomial:

      When ``n`` is small or ``k`` is small with respect to ``n``, one
      uses the naive algorithm. When both ``n`` and ``k`` are big, one
      uses the cyclotomic algorithm.

    - If ``q`` is in the symbolic ring, one uses the cyclotomic algorithm.

    - Otherwise one uses the naive algorithm, unless ``q`` is a root of
      unity, then one uses the cyclotomic algorithm.

    EXAMPLES:

    By default, the variable is the generator of `\ZZ[q]`::

        sage: from sage.combinat.q_analogues import q_binomial
        sage: g = q_binomial(5,1) ; g
        q^4 + q^3 + q^2 + q + 1
        sage: g.parent()
        Univariate Polynomial Ring in q over Integer Ring

    The `q`-binomial coefficient vanishes unless `0 \leq k \leq n`::

        sage: q_binomial(4,5)
        0
        sage: q_binomial(5,-1)
        0

    Other variables can be used, given as third parameter::

        sage: p = ZZ['p'].gen()
        sage: q_binomial(4,2,p)
        p^4 + p^3 + 2*p^2 + p + 1

    The third parameter can also be arbitrary values::

        sage: q_binomial(5,1,2) == g.subs(q=2)
        True
        sage: q_binomial(5,1,1)
        5
        sage: q_binomial(4,2,-1)
        2
        sage: q_binomial(4,2,3.14)
        152.030056160000
        sage: R = GF(25, 't')
        sage: t = R.gen(0)
        sage: q_binomial(6, 3, t)
        2*t + 3

    We can also do this for more complicated objects such as matrices or
    symmetric functions::

        sage: q_binomial(4,2,matrix([[2,1],[-1,3]]))
        [ -6  84]
        [-84  78]
        sage: Sym = SymmetricFunctions(QQ)
        sage: s = Sym.schur()
        sage: q_binomial(4,1, s[2]+s[1])
        s[] + s[1] + s[1, 1] + s[1, 1, 1] + 2*s[2] + 4*s[2, 1] + 3*s[2, 1, 1]
         + 4*s[2, 2] + 3*s[2, 2, 1] + s[2, 2, 2] + 3*s[3] + 7*s[3, 1] + 3*s[3, 1, 1]
         + 6*s[3, 2] + 2*s[3, 2, 1] + s[3, 3] + 4*s[4] + 6*s[4, 1] + s[4, 1, 1]
         + 3*s[4, 2] + 3*s[5] + 2*s[5, 1] + s[6]

    TESTS:

    One checks that the first two arguments are integers::

        sage: q_binomial(1/2,1)
        Traceback (most recent call last):
        ...
        TypeError: no conversion of this rational to integer

    One checks that `n` is nonnegative::

        sage: q_binomial(-4,1)
        Traceback (most recent call last):
        ...
        ValueError: n must be nonnegative

    This also works for variables in the symbolic ring::

        sage: z = var('z')
        sage: factor(q_binomial(4,2,z))
        (z^2 + z + 1)*(z^2 + 1)

    This also works for complex roots of unity::

        sage: q_binomial(6, 1, QQbar(I))
        I + 1

    Note that the symbolic computation works (see :trac:`14982`)::

        sage: q_binomial(6, 1, I)
        I + 1

    Check that the algorithm does not matter::

        sage: q_binomial(6,3, algorithm='naive') == q_binomial(6,3, algorithm='cyclotomic')
        True

    One more test::

        sage: q_binomial(4, 2, Zmod(6)(2), algorithm='naive')
        5

    Check that it works with Python integer for ``q``::

        sage: q_binomial(3r, 2r, 1r)
        3

    REFERENCES:

    .. [CH2006] William Y.C. Chen and Qing-Hu Hou, *Factors of the Gaussian
       coefficients*, Discrete Mathematics 306 (2006), 1446-1449.
       :doi:`10.1016/j.disc.2006.03.031`

    AUTHORS:

    - Frederic Chapoton, David Joyner and William Stein
    """
    # sanity checks
    n = ZZ(n)
    k = ZZ(k)
    if n < 0:
        raise ValueError('n must be nonnegative')

    # polynomiality test
    if q is None:
        from sage.rings.polynomial.polynomial_ring import polygen
        q = polygen(ZZ, name='q')
        is_polynomial = True
    else:
        from sage.rings.polynomial.polynomial_element import Polynomial
        is_polynomial = isinstance(q, Polynomial)

    R = parent(q)
    try:
        zero = R.zero()
    except AttributeError:
        zero = R('0')
    try:
        one = R.one()
    except AttributeError:
        one = R('1')

    if not (0 <= k and k <= n):
        return zero

    k = min(n - k, k)  # Pick the smallest k

    # heuristic choice of the fastest algorithm
    if algorithm == 'auto':
        from sage.symbolic.ring import SR
        if is_polynomial:
            if n <= 70 or k <= n // 4:
                algorithm = 'naive'
            else:
                algorithm = 'cyclo_polynomial'
        elif q in SR:
            algorithm = 'cyclo_generic'
        else:
            algorithm = 'naive'
    elif algorithm == 'cyclotomic':
        if is_polynomial:
            algorithm = 'cyclo_polynomial'
        else:
            algorithm = 'cyclo_generic'
    elif algorithm != 'naive':
        raise ValueError("invalid algorithm choice")

    # the algorithms
    if algorithm == 'naive':
        denom = prod(one - q**i for i in range(1, k + 1))
        if not denom:  # q is a root of unity, use the cyclotomic algorithm
            from sage.rings.polynomial.cyclotomic import cyclotomic_value
            return cyclotomic_value(n, k, q, algorithm='cyclotomic')
        else:
            num = prod(one - q**i for i in range(n - k + 1, n + 1))
            try:
                try:
                    return num // denom
                except TypeError:
                    return num / denom
            except (TypeError, ZeroDivisionError):
                # use substitution instead
                return q_binomial(n, k)(q)
    elif algorithm == 'cyclo_generic':
        from sage.rings.polynomial.cyclotomic import cyclotomic_value
        return prod(
            cyclotomic_value(d, q) for d in range(2, n + 1)
            if (n // d) != (k // d) + ((n - k) // d))
    elif algorithm == 'cyclo_polynomial':
        return prod(
            R.cyclotomic_polynomial(d) for d in range(2, n + 1)
            if (n // d) != (k // d) + ((n - k) // d))
예제 #50
0
파일: llt.py 프로젝트: shrutig/sage
    def _llt_generic(self, skp, stat):
        r"""
        Takes in partition, list of partitions, or a list of skew
        partitions as well as a function which takes in two partitions and
        a level and returns a coefficient.

        INPUT:

        - ``self`` -- a family of LLT symmetric functions bases
        - ``skp`` -- a partition or a list of partitions or a list of skew partitions
        - ``stat`` -- a function which accepts two partitions and a value
          for the level and returns a coefficient which is a polynomial
          in a parameter `t`.  The first partition is the index of the
          LLT function, the second partition is the index of the monomial
          basis element.

        OUTPUT:

        - returns the monomial expansion of the LLT symmetric function
          indexed by ``skp``

        EXAMPLES::

            sage: L3 = SymmetricFunctions(FractionField(QQ['t'])).llt(3)
            sage: f = lambda skp,mu,level: QQ(1)
            sage: L3._llt_generic([3,2,1],f)
            m[1, 1] + m[2]
            sage: L3._llt_generic([[2,1],[1],[2]],f)
            m[1, 1, 1, 1, 1, 1] + m[2, 1, 1, 1, 1] + m[2, 2, 1, 1] + m[2, 2, 2] + m[3, 1, 1, 1] + m[3, 2, 1] + m[3, 3] + m[4, 1, 1] + m[4, 2] + m[5, 1] + m[6]
            sage: L3._llt_generic([[[2,2],[1]],[[2,1],[]]],f)
            m[1, 1, 1, 1] + m[2, 1, 1] + m[2, 2] + m[3, 1] + m[4]
        """
        if skp in sage.combinat.partition.Partitions():
            m = (sum(skp) / self.level()).floor()
            if m == 0:
                raise ValueError, "level (%=) must divide %s " % (sum(skp),
                                                                  self.level())
            mu = sage.combinat.partition.Partitions(ZZ(
                sum(skp) / self.level()))

        elif isinstance(
                skp, list
        ) and skp[0] in sage.combinat.skew_partition.SkewPartitions():
            #skp is a list of skew partitions
            skp2 = [
                sage.combinat.partition.Partition(
                    core=[], quotient=[skp[i][0] for i in range(len(skp))])
            ]
            skp2 += [
                sage.combinat.partition.Partition(
                    core=[], quotient=[skp[i][1] for i in range(len(skp))])
            ]
            mu = sage.combinat.partition.Partitions(
                ZZ((skp2[0].size() - skp2[1].size()) / self.level()))
            skp = skp2
        elif isinstance(
                skp, list) and skp[0] in sage.combinat.partition.Partitions():
            #skp is a list of partitions
            skp = sage.combinat.partition.Partition(core=[], quotient=skp)
            mu = sage.combinat.partition.Partitions(ZZ(
                sum(skp) / self.level()))
        else:
            raise ValueError, "LLT polynomials not defined for %s" % skp

        BR = self.base_ring()
        return sum([
            BR(stat(skp, nu, self.level()).subs(t=self.t)) * self._m(nu)
            for nu in mu
        ])
예제 #51
0
def MatrixGroup(*gens, **kwds):
    r"""
    Return the matrix group with given generators.

    INPUT:

    - ``*gens`` -- matrices, or a single list/tuple/iterable of
      matrices, or a matrix group.

    - ``check`` -- boolean keyword argument (optional, default:
      ``True``). Whether to check that each matrix is invertible.

    EXAMPLES::

        sage: F = GF(5)
        sage: gens = [matrix(F,2,[1,2, -1, 1]), matrix(F,2, [1,1, 0,1])]
        sage: G = MatrixGroup(gens); G
        Matrix group over Finite Field of size 5 with 2 generators (
        [1 2]  [1 1]
        [4 1], [0 1]
        )

    In the second example, the generators are a matrix over
    `\ZZ`, a matrix over a finite field, and the integer
    `2`. Sage determines that they both canonically map to
    matrices over the finite field, so creates that matrix group
    there::

        sage: gens = [matrix(2,[1,2, -1, 1]), matrix(GF(7), 2, [1,1, 0,1]), 2]
        sage: G = MatrixGroup(gens); G
        Matrix group over Finite Field of size 7 with 3 generators (
        [1 2]  [1 1]  [2 0]
        [6 1], [0 1], [0 2]
        )

    Each generator must be invertible::

        sage: G = MatrixGroup([matrix(ZZ,2,[1,2,3,4])])
        Traceback (most recent call last):
        ...
        ValueError: each generator must be an invertible matrix

        sage: F = GF(5); MS = MatrixSpace(F,2,2)
        sage: MatrixGroup([MS.0])
        Traceback (most recent call last):
        ...
        ValueError: each generator must be an invertible matrix
        sage: MatrixGroup([MS.0], check=False)  # works formally but is mathematical nonsense
        Matrix group over Finite Field of size 5 with 1 generators (
        [1 0]
        [0 0]
        )

    Some groups are not supported, or do not have much functionality
    implemented::

        sage: G = SL(0, QQ)
        Traceback (most recent call last):
        ...
        ValueError: the degree must be at least 1

        sage: SL2C = SL(2, CC);  SL2C
        Special Linear Group of degree 2 over Complex Field with 53 bits of precision
        sage: SL2C.gens()
        Traceback (most recent call last):
        ...
        AttributeError: 'LinearMatrixGroup_generic_with_category' object has no attribute 'gens'
    """
    if isinstance(gens[-1], dict):  # hack for unpickling
        kwds.update(gens[-1])
        gens = gens[:-1]
    check = kwds.get('check', True)
    if len(gens) == 1:
        if isinstance(gens[0], (list, tuple)):
            gens = list(gens[0])
        else:
            try:
                gens = [g.matrix() for g in gens[0]]
            except AttributeError:
                pass
    if len(gens) == 0:
        raise ValueError('need at least one generator')
    gens = normalize_square_matrices(gens)
    if check and any(not g.is_invertible() for g in gens):
        raise ValueError('each generator must be an invertible matrix')
    MS = gens.universe()
    base_ring = MS.base_ring()
    degree = ZZ(MS.ncols())  # == MS.nrows()
    from sage.libs.gap.libgap import libgap
    try:
        gap_gens = [libgap(matrix_gen) for matrix_gen in gens]
        gap_group = libgap.Group(gap_gens)
        return FinitelyGeneratedMatrixGroup_gap(degree, base_ring, gap_group)
    except (TypeError, ValueError):
        return FinitelyGeneratedMatrixGroup_generic(degree, base_ring, gens)
예제 #52
0
    def sturm_bound(self, weight=2):
        r"""
        Returns the Sturm bound for modular forms of the given weight and level
        this subgroup.

        INPUT:

        -  ``weight`` - an integer `\geq 2` (default: 2)

        EXAMPLES::
            sage: Gamma0(11).sturm_bound(2)
            2
            sage: Gamma0(389).sturm_bound(2)
            65
            sage: Gamma0(1).sturm_bound(12)
            1
            sage: Gamma0(100).sturm_bound(2)
            30
            sage: Gamma0(1).sturm_bound(36)
            3
            sage: Gamma0(11).sturm_bound()
            2
            sage: Gamma0(13).sturm_bound()
            3
            sage: Gamma0(16).sturm_bound()
            4
            sage: GammaH(16,[13]).sturm_bound()
            8
            sage: GammaH(16,[15]).sturm_bound()
            16
            sage: Gamma1(16).sturm_bound()
            32
            sage: Gamma1(13).sturm_bound()
            28
            sage: Gamma1(13).sturm_bound(5)
            70

        FURTHER DETAILS: This function returns a positive integer
        `n` such that the Hecke operators
        `T_1,\ldots, T_n` acting on *cusp forms* generate the
        Hecke algebra as a `\ZZ`-module when the character
        is trivial or quadratic. Otherwise, `T_1,\ldots,T_n`
        generate the Hecke algebra at least as a
        `\ZZ[\varepsilon]`-module, where
        `\ZZ[\varepsilon]` is the ring generated by the
        values of the Dirichlet character `\varepsilon`.
        Alternatively, this is a bound such that if two cusp forms
        associated to this space of modular symbols are congruent modulo
        `(\lambda, q^n)`, then they are congruent modulo
        `\lambda`.

        REFERENCES:

        - See the Agashe-Stein appendix to Lario and Schoof,
          *Some computations with Hecke rings and deformation rings*,
          Experimental Math., 11 (2002), no. 2, 303-311.

        - This result originated in the paper Sturm,
          *On the congruence of modular forms*,
          Springer LNM 1240, 275-280, 1987.

        REMARK: Kevin Buzzard pointed out to me (William Stein) in Fall
        2002 that the above bound is fine for `\Gamma_1(N)` with
        character, as one sees by taking a power of `f`. More
        precisely, if `f \cong 0 \pmod{p}` for first
        `s` coefficients, then `f^r \cong 0 \pmod{p}` for
        first `sr` coefficients. Since the weight of `f^r`
        is `r\cdot k(f)`, it follows that if
        `s \geq b`, where `b` is the Sturm bound for
        `\Gamma_0(N)` at weight `k(f)`, then `f^r`
        has valuation large enough to be forced to be `0` at
        `r*k(f)` by Sturm bound (which is valid if we choose
        `r` correctly). Thus `f \cong 0 \pmod{p}`.
        Conclusion: For `\Gamma_1(N)` with fixed character, the
        Sturm bound is *exactly* the same as for `\Gamma_0(N)`.

        A key point is that we are finding
        `\ZZ[\varepsilon]` generators for the Hecke algebra
        here, not `\ZZ`-generators. So if one wants
        generators for the Hecke algebra over `\ZZ`, this
        bound must be suitably modified (and I'm not sure what the
        modification is).

        AUTHORS:

        - William Stein
        """
        return ZZ((self.index() * weight / ZZ(12)).ceil())
예제 #53
0
def enumerate_totallyreal_fields_rel(F,
                                     m,
                                     B,
                                     a=[],
                                     verbose=0,
                                     return_seqs=False,
                                     return_pari_objects=True):
    r"""
    This function enumerates (primitive) totally real field extensions of
    degree `m>1` of the totally real field F with discriminant `d \leq B`;
    optionally one can specify the first few coefficients, where the sequence ``a``
    corresponds to a polynomial by

    ::

        a[d]*x^n + ... + a[0]*x^(n-d)

    if ``length(a) = d+1``, so in particular always ``a[d] = 1``.

    .. note::

        This is guaranteed to give all primitive such fields, and
        seems in practice to give many imprimitive ones.

    INPUT:

    - ``F`` -- number field, the base field
    - ``m`` -- integer, the degree
    - ``B`` -- integer, the discriminant bound
    - ``a`` -- list (default: []), the coefficient list to begin with
    - ``verbose`` -- boolean or nonnegative integer or string (default: 0)
      give a verbose description of the computations being performed. If
      ``verbose`` is set to ``2`` or more then it outputs some extra
      information. If ``verbose`` is a string then it outputs to a file
      specified by ``verbose``
    - ``return_seqs`` -- (boolean, default False) If ``True``, then return
      the polynomials as sequences (for easier exporting to a file). This
      also returns a list of four numbers, as explained in the OUTPUT
      section below.
    - ``return_pari_objects`` -- (boolean, default: True) if
      both ``return_seqs`` and ``return_pari_objects`` are ``False`` then
      it returns the elements as Sage objects; otherwise it returns pari
      objects.

    OUTPUT:

    - the list of fields with entries ``[d,fabs,f]``, where ``d`` is the
      discriminant, ``fabs`` is an absolute defining polynomial, and ``f``
      is a defining polynomial relative to ``F``, sorted by discriminant.

    - if ``return_seqs`` is ``True``, then the first field of the list is
      a list containing the count of four items as explained below

      - the first entry gives the number of polynomials tested
      - the second entry gives the number of polynomials with its
        discriminant having a large enough square divisor
      - the third entry is the number of irreducible polynomials
      - the fourth entry is the number of irreducible polynomials with
        discriminant at most ``B``

    EXAMPLES::

        sage: ZZx = ZZ['x']
        sage: F.<t> = NumberField(x^2-2)
        sage: enumerate_totallyreal_fields_rel(F, 1, 2000)
        [[1, [-2, 0, 1], xF - 1]]
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000)
        [[1600, x^4 - 6*x^2 + 4, xF^2 + xF - 1]]
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_seqs=True)
        [[9, 6, 5, 0], [[1600, [4, 0, -6, 0, 1], [-1, 1, 1]]]]

    TESTS:

    Each of the outputs must be elements of Sage if ``return_pari_objects``
    is set to ``False``::

        sage: type(enumerate_totallyreal_fields_rel(F, 2, 2000)[0][1])
        <type 'cypari2.gen.Gen'>
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][0].parent()
        Integer Ring
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][1].parent()
        Univariate Polynomial Ring in x over Rational Field
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][2].parent()
        Univariate Polynomial Ring in xF over Number Field in t with defining polynomial x^2 - 2
        sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_seqs=True)[1][0][1][0].parent()
        Rational Field

    AUTHORS:

    - John Voight (2007-11-01)
    """

    if not isinstance(m, Integer):
        try:
            m = Integer(m)
        except TypeError:
            raise TypeError("cannot coerce m (= %s) to an integer" % m)
    if (m < 1):
        raise ValueError("m must be at least 1.")

    n = F.degree() * m

    # Initialize
    S = {}  # dictionary of the form {(d, fabs): f, ...}
    dB_odlyzko = odlyzko_bound_totallyreal(n)
    dB = math.ceil(40000 * dB_odlyzko**n)
    counts = [0, 0, 0, 0]

    # Trivial case
    if m == 1:
        g = pari(F.defining_polynomial()).polrecip().Vec()
        if return_seqs:
            return [[0, 0, 0, 0], [1, [-1, 1], g]]
        elif return_pari_objects:
            return [[1, g, pari('xF-1')]]
        else:
            Px = PolynomialRing(QQ, 'xF')
            return [[ZZ(1), [QQ(_) for _ in g], Px.gen() - 1]]

    if verbose:
        saveout = sys.stdout
        if isinstance(verbose, str):
            fsock = open(verbose, 'w')
            sys.stdout = fsock
        # Else, print to screen
    f_out = [0] * m + [1]
    T = tr_data_rel(F, m, B, a)
    if verbose == 2:
        T.incr(f_out, verbose)
    else:
        T.incr(f_out)

    Fx = PolynomialRing(F, 'xF')

    nfF = pari(
        str(F.defining_polynomial()).replace('x', str(F.primitive_element())))
    parit = pari(str(F.primitive_element()))

    while f_out[m] != 0:
        counts[0] += 1
        if verbose:
            print("==>", f_out, end="")

        f_str = ''
        for i in range(len(f_out)):
            f_str += '(' + str(f_out[i]) + ')*x^' + str(i)
            if i < len(f_out) - 1:
                f_str += '+'
        nf = pari(f_str)
        if nf.poldegree('t') == 0:
            nf = nf.subst('x', 'x-t')
        nf = nf.polresultant(nfF, parit)
        d = nf.poldisc()
        #counts[0] += 1
        if d > 0 and nf.polsturm() == n:
            da = int_has_small_square_divisor(Integer(d))
            if d > dB or d <= B * da:
                counts[1] += 1
                if nf.polisirreducible():
                    counts[2] += 1
                    [zk, d] = nf.nfbasis_d()

                    if d <= B:
                        if verbose:
                            print("has discriminant", d, end="")

                        # Find a minimal lattice element
                        counts[3] += 1
                        ng = pari([nf, zk]).polredabs()

                        # Check if K is contained in the list.
                        if (d, ng) in S:
                            if verbose:
                                print("but is not new")
                        else:
                            if verbose:
                                print("and is new!")
                            S[(d, ng)] = Fx(f_out)
                    else:
                        if verbose:
                            print("has discriminant", abs(d), "> B")
                else:
                    if verbose:
                        print("is not absolutely irreducible")
            else:
                if verbose:
                    print("has discriminant", abs(d),
                          "with no large enough square divisor")
        else:
            if verbose:
                if d == 0:
                    print("is not squarefree")
                else:
                    print("is not totally real")
        if verbose == 2:
            T.incr(f_out, verbose=verbose)
        else:
            T.incr(f_out)

    # In the application of Smyth's theorem above, we exclude finitely
    # many possibilities which we must now throw back in.
    if m == 2:
        if Fx([-1, 1, 1]).is_irreducible():
            K = F.extension(Fx([-1, 1, 1]), 'tK')
            Kabs = K.absolute_field('tKabs')
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                S[(d, ng)] = Fx([-1, 1, 1])
        elif F.degree() == 2:
            for ff in [[1, -7, 13, -7, 1], [1, -8, 14, -7, 1]]:
                f = Fx(ff).factor()[0][0]
                K = F.extension(f, 'tK')
                Kabs = K.absolute_field('tKabs')
                Kabs_pari = pari(Kabs.defining_polynomial())
                d = K.absolute_discriminant()
                if abs(d) <= B:
                    ng = Kabs_pari.polredabs()
                    S[(d, ng)] = f
    elif m == 3:
        if Fx([-1, 6, -5, 1]).is_irreducible():
            K = F.extension(Fx([-1, 6, -5, 1]), 'tK')
            Kabs = K.absolute_field('tKabs')
            Kabs_pari = pari(Kabs.defining_polynomial())
            d = K.absolute_discriminant()
            if abs(d) <= B:
                ng = Kabs_pari.polredabs()
                S[(d, ng)] = Fx([-1, 6, -5, 1])

    # Convert S to a sorted list of triples [d, fabs, f], taking care
    # to use cmp() and not the comparison operators on PARI polynomials.
    S = [[s[0], s[1], t] for s, t in S.items()]
    S.sort(key=lambda x: (x[0], [QQ(x) for x in x[1].polrecip().Vec()]))

    # Now check for isomorphic fields
    weed_fields(S)

    # Output.
    if verbose:
        print("=" * 80)
        print("Polynomials tested: {}".format(counts[0]))
        print("Polynomials with discriminant with large enough square"
              " divisor: {}".format(counts[1]))
        print("Irreducible polynomials: {}".format(counts[2]))
        print("Polynomials with nfdisc <= B: {}".format(counts[3]))
        for i in range(len(S)):
            print(S[i])
        if isinstance(verbose, str):
            fsock.close()
        sys.stdout = saveout

    # Make sure to return elements that belong to Sage
    if return_seqs:
        return [[ZZ(x) for x in counts],
                [[
                    s[0], [QQ(x) for x in s[1].polrecip().Vec()],
                    s[2].coefficients(sparse=False)
                ] for s in S]]
    elif return_pari_objects:
        return S
    else:
        Px = PolynomialRing(QQ, 'x')
        return [[s[0], Px([QQ(_) for _ in s[1].list()]), s[2]] for s in S]
예제 #54
0
        def epsilon(self, i):
            r"""
            Return `\varepsilon_i` of ``self``.

            EXAMPLES::

                sage: S = crystals.OddNegativeRoots(['A', [2,2]])
                sage: mg = S.module_generator()
                sage: [mg.epsilon(i) for i in S.index_set()]
                [0, 0, 0, 0, 0]
                sage: b = mg.f_string([0,1,0,-1,0,-1,-2,-2]); b
                {-e[-3]+e[1], -e[-3]+e[2], -e[-1]+e[1]}
                sage: [b.epsilon(i) for i in S.index_set()]
                [2, 0, 1, 0, 0]
                sage: b = mg.f_string([0,1,0,-1,0,-1,-2,-2,2,-1,0]); b
                {-e[-3]+e[1], -e[-3]+e[3], -e[-2]+e[1], -e[-1]+e[1]}
                sage: [b.epsilon(i) for i in S.index_set()]
                [1, 0, 1, 0, 1]

            TESTS::

                sage: S = crystals.OddNegativeRoots(['A', [2,1]])
                sage: def count_e(x, i):
                ....:     ret = -1
                ....:     while x is not None:
                ....:         x = x.e(i)
                ....:         ret += 1
                ....:     return ret
                sage: for x in S:
                ....:     for i in S.index_set():
                ....:         assert x.epsilon(i) == count_e(x, i)
            """
            if i == 0:
                return ZZ.one() if (-1,1) in self.value else ZZ.zero()

            count = 0
            ret = 0
            if i < 0:
                lst = sorted(self.value, key=lambda x: (x[1], -x[0]))
                for val in lst:
                    # We don't have to check val[1] because this is an odd root
                    if val[0] == i - 1:
                        if count == 0:
                            ret += 1
                        else:
                            count -= 1
                    elif val[0] == i:
                        count += 1

            else: # i > 0
                lst = sorted(self.value, key=lambda x: (-x[0], -x[1]))
                for val in reversed(lst):
                    # We don't have to check val[0] because this is an odd root
                    if val[1] == i + 1:
                        if count == 0:
                            ret += 1
                        else:
                            count -= 1
                    elif val[1] == i:
                        count += 1
            return ret
예제 #55
0
    def _compute(self, verbose=False):
        """
        Computes the list of curves, the matrix and prime-degree
        isogenies.

        EXAMPLES::

            sage: K.<i> = QuadraticField(-1)
            sage: E = EllipticCurve(K, [0,0,0,0,1])
            sage: C = E.isogeny_class()
            sage: C2 = C.copy()
            sage: C2._mat
            sage: C2._compute()
            sage: C2._mat
            [1 3 6 2]
            [3 1 2 6]
            [6 2 1 3]
            [2 6 3 1]

            sage: C2._compute(verbose=True)
            possible isogeny degrees: [2, 3] -actual isogeny degrees: {2, 3} -added curve #1 (degree 2)... -added tuple [0, 1, 2]... -added tuple [1, 0, 2]... -added curve #2 (degree 3)... -added tuple [0, 2, 3]... -added tuple [2, 0, 3]...... relevant degrees: [2, 3]... -now completing the isogeny class... -processing curve #1... -added tuple [1, 0, 2]... -added tuple [0, 1, 2]... -added curve #3... -added tuple [1, 3, 3]... -added tuple [3, 1, 3]... -processing curve #2... -added tuple [2, 3, 2]... -added tuple [3, 2, 2]... -added tuple [2, 0, 3]... -added tuple [0, 2, 3]... -processing curve #3... -added tuple [3, 2, 2]... -added tuple [2, 3, 2]... -added tuple [3, 1, 3]... -added tuple [1, 3, 3]...... isogeny class has size 4
            Sorting permutation = {0: 1, 1: 2, 2: 0, 3: 3}
            Matrix = [1 3 6 2]
            [3 1 2 6]
            [6 2 1 3]
            [2 6 3 1]

        TESTS:

        Check that :trac:`19030` is fixed (codomains of reverse isogenies were wrong)::

            sage: K.<i> = NumberField(x^2+1)
            sage: E = EllipticCurve([1, i + 1, 1, -72*i + 8, 95*i + 146])
            sage: C = E.isogeny_class()
            sage: curves = C.curves
            sage: isos = C.isogenies()
            sage: isos[0][3].codomain() == curves[3]
            True

        """
        from sage.schemes.elliptic_curves.ell_curve_isogeny import fill_isogeny_matrix
        from sage.matrix.all import MatrixSpace
        from sage.sets.set import Set
        self._maps = None

        E = self.E.global_minimal_model(semi_global=True)

        degs = possible_isogeny_degrees(E)
        if verbose:
            import sys
            sys.stdout.write(" possible isogeny degrees: %s" % degs)
            sys.stdout.flush()
        isogenies = E.isogenies_prime_degree(degs)
        if verbose:
            sys.stdout.write(" -actual isogeny degrees: %s" % Set([phi.degree() for phi in isogenies]))
            sys.stdout.flush()
        # Add all new codomains to the list and collect degrees:
        curves = [E]
        ncurves = 1
        degs = []
        # tuples (i,j,l,phi) where curve i is l-isogenous to curve j via phi
        tuples = []

        def add_tup(t):
            for T in [t, [t[1],t[0],t[2],0]]:
                if not T in tuples:
                    tuples.append(T)
                    if verbose:
                        sys.stdout.write(" -added tuple %s..." % T[:3])
                        sys.stdout.flush()

        for phi in isogenies:
            E2 = phi.codomain()
            d = ZZ(phi.degree())
            if not any([E2.is_isomorphic(E3) for E3 in curves]):
                curves.append(E2)
                if verbose:
                    sys.stdout.write(" -added curve #%s (degree %s)..." % (ncurves,d))
                    sys.stdout.flush()
                add_tup([0,ncurves,d,phi])
                ncurves += 1
                if not d in degs:
                    degs.append(d)
        if verbose:
            sys.stdout.write("... relevant degrees: %s..." % degs)
            sys.stdout.write(" -now completing the isogeny class...")
            sys.stdout.flush()

        i = 1
        while i < ncurves:
            E1 = curves[i]
            if verbose:
                sys.stdout.write(" -processing curve #%s..." % i)
                sys.stdout.flush()

            isogenies = E1.isogenies_prime_degree(degs)

            for phi in isogenies:
                E2 = phi.codomain()
                d = phi.degree()
                js = [j for j,E3 in enumerate(curves) if E2.is_isomorphic(E3)]
                if js: # seen codomain already -- up to isomorphism
                    j = js[0]
                    if phi.codomain()!=curves[j]:
                        iso = E2.isomorphism_to(curves[j])
                        phi.set_post_isomorphism(iso)
                    assert phi.domain()==curves[i] and phi.codomain()==curves[j]
                    add_tup([i,j,d,phi])
                else:
                    curves.append(E2)
                    if verbose:
                        sys.stdout.write(" -added curve #%s..." % ncurves)
                        sys.stdout.flush()
                    add_tup([i,ncurves,d,phi])
                    ncurves += 1
            i += 1

        if verbose:
            print("... isogeny class has size %s" % ncurves)

        # key function for sorting
        if E.has_rational_cm():
            key_function = lambda E: (-E.cm_discriminant(),flatten([list(ai) for ai in E.ainvs()]))
        else:
            key_function = lambda E: flatten([list(ai) for ai in E.ainvs()])

        self.curves = sorted(curves,key=key_function)
        perm = {ix: self.curves.index(Ex) for ix, Ex in enumerate(curves)}
        if verbose:
            print("Sorting permutation = %s" % perm)

        mat = MatrixSpace(ZZ,ncurves)(0)
        self._maps = [[0] * ncurves for _ in range(ncurves)]
        for i,j,l,phi in tuples:
            if phi!=0:
                mat[perm[i],perm[j]] = l
                self._maps[perm[i]][perm[j]] = phi
        self._mat = fill_isogeny_matrix(mat)
        if verbose:
            print("Matrix = %s" % self._mat)

        if not E.has_rational_cm():
            self._qfmat = None
            return

        # In the CM case, we will have found some "horizontal"
        # isogenies of composite degree and would like to replace them
        # by isogenies of prime degree, mainly to make the isogeny
        # graph look better.  We also construct a matrix whose entries
        # are not degrees of cyclic isogenies, but rather quadratic
        # forms (in 1 or 2 variables) representing the isogeny
        # degrees.  For this we take a short cut: properly speaking,
        # when `\text{End}(E_1)=\text{End}(E_2)=O`, the set
        # `\text{Hom}(E_1,E_2)` is a rank `1` projective `O`-module,
        # hence has a well-defined ideal class associated to it, and
        # hence (using an identification between the ideal class group
        # and the group of classes of primitive quadratic forms of the
        # same discriminant) an equivalence class of quadratic forms.
        # But we currently only care about the numbers represented by
        # the form, i.e. which genus it is in rather than the exact
        # class.  So it suffices to find one form of the correct
        # discriminant which represents one isogeny degree from `E_1`
        # to `E_2` in order to obtain a form which represents all such
        # degrees.

        if verbose:
            print("Creating degree matrix (CM case)")

        allQs = {} # keys: discriminants d
                   # values: lists of equivalence classes of
                   # primitive forms of discriminant d
        def find_quadratic_form(d,n):
            if not d in allQs:
                from sage.quadratic_forms.binary_qf import BinaryQF_reduced_representatives

                allQs[d] = BinaryQF_reduced_representatives(d, primitive_only=True)
            # now test which of the Qs represents n
            for Q in allQs[d]:
                if Q.solve_integer(n):
                    return Q
            raise ValueError("No form of discriminant %d represents %s" %(d,n))

        mat = self._mat
        qfmat = [[0 for i in range(ncurves)] for j in range(ncurves)]
        for i, E1 in enumerate(self.curves):
            for j, E2 in enumerate(self.curves):
                if j<i:
                    qfmat[i][j] = qfmat[j][i]
                    mat[i,j] = mat[j,i]
                elif i==j:
                    qfmat[i][j] = [1]
                    # mat[i,j] already 1
                else:
                    d = E1.cm_discriminant()
                    if d != E2.cm_discriminant():
                        qfmat[i][j] = [mat[i,j]]
                        # mat[i,j] already unique
                    else: # horizontal isogeny
                        q = find_quadratic_form(d,mat[i,j])
                        qfmat[i][j] = list(q)
                        mat[i,j] = q.small_prime_value()

        self._mat = mat
        self._qfmat = qfmat
        if verbose:
            print("new matrix = %s" % mat)
            print("matrix of forms = %s" % qfmat)
예제 #56
0
    def rho(self, g):
        r"""
        Calculate the action of the group element `g` on the type space.

        EXAMPLES::

            sage: from sage.modular.local_comp.type_space import example_type_space
            sage: T = example_type_space(2)
            sage: m = T.rho([2,0,0,1]); m
            [-1  1  0 -1]
            [ 0  0 -1  1]
            [ 0 -1 -1  1]
            [ 1 -1 -2  2]
            sage: v = T.eigensymbol_subspace().basis()[0]
            sage: m * v == v
            True

        We test that it is a left action::

            sage: T = example_type_space(0)
            sage: a = [0,5,4,3]; b = [0,2,3,5]; ab = [1,4,2,2]
            sage: T.rho(ab) == T.rho(a) * T.rho(b)
            True

        An odd level example::

            sage: from sage.modular.local_comp.type_space import TypeSpace
            sage: T = TypeSpace(Newform('54a'), 3)
            sage: a = [0,1,3,0]; b = [2,1,0,1]; ab = [0,1,6,3]
            sage: T.rho(ab) == T.rho(a) * T.rho(b)
            True
        """
        if not self.is_minimal():
            raise NotImplementedError(
                "Group action on non-minimal type space not implemented")

        if self.u() == 0:
            # silly special case: rep is principal series or special, so SL2
            # action on type space is trivial
            raise ValueError("Representation is not supercuspidal")

        p = self.prime()
        f = p**self.u()
        g = [ZZ(_) for _ in g]
        d = (g[0] * g[3] - g[2] * g[1])

        # g is in S(K_0) (easy case)
        if d % f == 1:
            return self._rho_s(g)

        # g is in K_0, but not in S(K_0)

        if d % p != 0:
            try:
                a = self._a
            except AttributeError:
                self._discover_torus_action()
                a = self._a

            if not (f % 8):
                if d % 4 == 3:
                    return (
                        self.rho([-g[0], g[1], -g[2], g[3]]) *
                        self.t_space.star_involution().matrix().transpose())

            i = 0
            while (d * a**i) % f != 1:
                i += 1
                if i > f:
                    raise ArithmeticError
            return self._rho_s([a**i * g[0], g[1], a**i * g[2], g[3]
                                ]) * self._amat**(-i)

        # det(g) is not a unit

        if (self.conductor() % 2 == 0):
            if all(x.valuation(p) > 0 for x in g):
                eps = self.form().character()(crt(1, p, f, self.tame_level()))
                return ~eps * p**(self.form().weight() - 2) * self.rho(
                    [x // p for x in g])
            else:
                raise ArithmeticError("g(={0}) not in K".format(g))

        else:
            m = matrix(ZZ, 2, g)
            s = m.det().valuation(p)
            mm = (matrix(QQ, 2, [0, -1, p, 0])**(-s) * m).change_ring(ZZ)
            return self._unif_ramified()**s * self.rho(mm.list())
예제 #57
0
def possible_isogeny_degrees(E, verbose=False):
    r"""
    Return a list of primes `\ell` sufficient to generate the
    isogeny class of `E`.

    INPUT:

    - ``E`` -- An elliptic curve defined over a number field.

    OUTPUT:

    A finite list of primes `\ell` such that every curve isogenous to
    this curve can be obtained by a finite sequence of isogenies of
    degree one of the primes in the list.

    ALGORITHM:

    For curves without CM, the set may be taken to be the finite set
    of primes at which the Galois representation is not surjective,
    since the existence of an `\ell`-isogeny is equivalent to the
    image of the mod-`\ell` Galois representation being contained in a
    Borel subgroup.

    For curves with CM by the order `O` of discriminant `d`, the
    Galois representation is always non-surjective and the curve will
    admit `\ell`-isogenies for infinitely many primes `\ell`, but
    there are (of course) only finitely many codomains `E'`.  The
    primes can be divided according to the discriminant `d'` of the CM
    order `O'` associated to `E`: either `O=O'`, or one contains the
    other with index `\ell`, since `\ell O\subset O'` and vice versa.

    Case (1): `O=O'`.  The degrees of all isogenies between `E` and
    `E'` are precisely the integers represented by one of the classes
    of binary quadratic forms `Q` of discriminant `d`.  Hence to
    obtain all possible isomorphism classes of codomain `E'`, we need
    only use one prime `\ell` represented by each such class `Q`.  It
    would in fact suffice to use primes represented by forms which
    generate the class group.  Here we simply omit the principal class
    and one from each pair of inverse classes, and include a prime
    represented by each of the remaining forms.

    Case (2): `[O':O]=\ell`: so `d=\ell^2d;`.  We include all prime
    divisors of `d`.

    Case (3): `[O:O']=\ell`: we may assume that `\ell` does not divide
    `d` as we have already included these, so `\ell` either splits or
    is inert in `O`; the class numbers satisfy `h(O')=(\ell\pm1)h(O)`
    accordingly.  We include all primes `\ell` such that `\ell\pm1`
    divides the degree `[K:\QQ]`.

    For curves with only potential CM we proceed as in the CM case,
    using `2[K:\QQ]` instead of `[K:\QQ]`.

    EXAMPLES:

    For curves without CM we determine the primes at which the mod `p`
    Galois representation is reducible, i.e. contained in a Borel
    subgroup::

        sage: from sage.schemes.elliptic_curves.isogeny_class import possible_isogeny_degrees
        sage: E = EllipticCurve('11a1')
        sage: possible_isogeny_degrees(E)
        [5]

    We check that in this case `E` really does have rational
    `5`-isogenies::

        sage: [phi.degree() for phi in E.isogenies_prime_degree()]
        [5, 5]

    Over an extension field::

        sage: E3 = E.change_ring(CyclotomicField(3))
        sage: possible_isogeny_degrees(E3)
        [5]
        sage: [phi.degree() for phi in E3.isogenies_prime_degree()]
        [5, 5]

    For curves with CM by a quadratic order of class number greater
    than `1`, we use the structure of the class group to only give one
    prime in each ideal class::

        sage: pol = PolynomialRing(QQ,'x')([1,-3,5,-5,5,-3,1])
        sage: L.<a> = NumberField(pol)
        sage: j = hilbert_class_polynomial(-23).roots(L,multiplicities=False)[0]
        sage: E = EllipticCurve(j=j)
        sage: from sage.schemes.elliptic_curves.isogeny_class import possible_isogeny_degrees
        sage: possible_isogeny_degrees(E, verbose=True)
        CM case, discriminant = -23
        initial primes: {2}
        upward primes: {}
        downward ramified primes: {}
        downward split primes: {2, 3}
        downward inert primes: {5}
        primes generating the class group: [2]
        Complete set of primes: {2, 3, 5}
        [2, 3, 5]
    """
    if E.has_cm():
        d = E.cm_discriminant()

        if verbose:
            print("CM case, discriminant = %s" % d)

        from sage.libs.pari.all import pari
        from sage.sets.all import Set
        from sage.arith.all import kronecker_symbol

        n = E.base_field().absolute_degree()
        if not E.has_rational_cm():
            n *= 2
        divs = n.divisors()

        data = pari(d).quadclassunit()
        # This has 4 components: the class number, class group
        # structure (ignored), class group generators (as quadratic
        # forms) and regulator (=1 since d<0, ignored).

        h = data[0].sage()

        # We must have 2*h dividing n, and will need the quotient so
        # see if the j-invariants of any proper sub-orders could lie
        # in the same field

        n_over_2h = n//(2*h)

        # Collect possible primes.  First put in 2, and also 3 for
        # discriminant -3 (special case because of units):

        L = Set([ZZ(2), ZZ(3)]) if d==-3 else  Set([ZZ(2)])
        if verbose:
            print("initial primes: %s" % L)

        # Step 1: "vertical" primes l such that the isogenous curve
        # has CM by an order whose index is l or 1/l times the index
        # of the order O of discriminant d.  The latter case can only
        # happen when l^2 divides d.

        # Compute the ramified primes

        ram_l = d.odd_part().prime_factors()

        # if the CM is not rational we include all ramified primes,
        # which is simpler than using the class group later:

        if not E.has_rational_cm():
            L1 = Set(ram_l)
            L += L1
            if verbose:
                print("ramified primes: %s" % L1)

        else:

            # Find the "upward" primes (index divided by l):

            L1 = Set([l for l in ram_l if d.valuation(l)>1])
            L += L1
            if verbose:
                print("upward primes: %s" % L1)

            # Find the "downward" primes (index multiplied by l, class
            # number multiplied by l-kronecker_symbol(d,l)):

            # (a) ramified primes; the suborder has class number l*h, so l
            # must divide n/2h:

            L1 = Set([l for l in ram_l if l.divides(n_over_2h)])
            L += L1
            if verbose:
                print("downward ramified primes: %s" % L1)

        # (b) split primes; the suborder has class number (l-1)*h, so
        # l-1 must divide n/2h:

        L1 = Set([lm1+1 for lm1 in divs
                  if (lm1+1).is_prime() and kronecker_symbol(d,lm1+1)==+1])
        L += L1
        if verbose:
            print("downward split primes: %s" % L1)

        # (c) inert primes; the suborder has class number (l+1)*h, so
        # l+1 must divide n/2h:

        L1 = Set([lp1-1 for lp1 in divs
                  if (lp1-1).is_prime() and kronecker_symbol(d,lp1-1)==-1])
        L += L1
        if verbose:
            print("downward inert primes: %s" % L1)

        # Now find primes represented by each form of discriminant d.
        # In the rational CM case, we use all forms associated to
        # generators of the class group, otherwise only forms of order
        # 2:

        if E.has_rational_cm():
            from sage.quadratic_forms.binary_qf import BinaryQF
            Qs = [BinaryQF(list(q)) for q in data[2]]

            L1 = [Q.small_prime_value() for Q in Qs]
            if verbose:
                print("primes generating the class group: %s" % L1)
            L += Set(L1)

        # Return sorted list

        if verbose:
            print("Complete set of primes: %s" % L)

        return sorted(list(L))

    #  Non-CM case

    if verbose:
        print("Non-CM case, using Galois representation")

    return E.galois_representation().reducible_primes()
예제 #58
0
    def _compute(self):
        """
        Computes the list of curves, and possibly the matrix and
        prime-degree isogenies (depending on the algorithm selected).

        EXAMPLES::

            sage: isocls = EllipticCurve('48a1').isogeny_class('sage').copy()
            sage: isocls._mat
            sage: isocls._compute(); isocls._mat
            [0 2 2 2 0 0]
            [2 0 0 0 2 2]
            [2 0 0 0 0 0]
            [2 0 0 0 0 0]
            [0 2 0 0 0 0]
            [0 2 0 0 0 0]
        """
        algorithm = self._algorithm
        from sage.matrix.all import MatrixSpace
        self._maps = None
        if algorithm == "database":
            try:
                label = self.E.cremona_label(space=False)
            except RuntimeError:
                raise RuntimeError("unable to find %s in the database" % self.E)
            db = sage.databases.cremona.CremonaDatabase()
            curves = db.isogeny_class(label)
            if len(curves) == 0:
                raise RuntimeError("unable to find %s in the database" % self.E)
            # All curves will have the same conductor and isogeny class,
            # and there are most 8 of them, so lexicographic sorting is okay.
            self.curves = tuple(sorted(curves, key = lambda E: E.cremona_label()))
            self._mat = None
        elif algorithm == "sage":
            curves = [self.E.minimal_model()]
            ijl_triples = []
            l_list = None
            i = 0
            while i<len(curves):
                E = curves[i]
                isogs = E.isogenies_prime_degree(l_list)
                for phi in isogs:
                    Edash = phi.codomain()
                    l = phi.degree()
                    # look to see if Edash is new.  Note that the
                    # curves returned by isogenies_prime_degree() are
                    # standard minimal models, so it suffices to check
                    # equality rather than isomorphism here.
                    try:
                        j = curves.index(Edash)
                    except ValueError:
                        j = len(curves)
                        curves.append(Edash)
                    ijl_triples.append((i,j,l,phi))
                if l_list is None:
                    l_list = [ell for ell in set([ZZ(f.degree()) for f in isogs])]
                i += 1
            self.curves = tuple(curves)
            ncurves = len(curves)
            self._mat = MatrixSpace(ZZ, ncurves)(0)
            self._maps = [[0] * ncurves for _ in range(ncurves)]
            for i,j,l,phi in ijl_triples:
                self._mat[i,j] = l
                self._maps[i][j]=phi
        else:
            raise ValueError("unknown algorithm '%s'" % algorithm)
예제 #59
0
파일: fields.py 프로젝트: bopopescu/Sage-8
        def xgcd(self, other):
            """
            Compute the extended gcd of ``self`` and ``other``.

            INPUT:

            - ``other`` -- an element with the same parent as ``self``

            OUTPUT:

            A tuple ``(r, s, t)`` of elements in the parent of ``self`` such
            that ``r = s * self + t * other``. Since the computations are done
            over a field, ``r`` is zero if ``self`` and ``other`` are zero,
            and one otherwise.

            AUTHORS:

            - Julian Rueth (2012-10-19): moved here from
              :class:`sage.structure.element.FieldElement`

            EXAMPLES::

                sage: K = GF(5)
                sage: K(2).xgcd(K(1))
                (1, 3, 0)
                sage: K(0).xgcd(K(4))
                (1, 0, 4)
                sage: K(1).xgcd(K(1))
                (1, 1, 0)
                sage: GF(5)(0).xgcd(GF(5)(0))
                (0, 0, 0)

            The xgcd of non-zero floating point numbers will be a triple of
            floating points. But if the input are two integral floating points
            the result is a floating point version of the standard gcd on
            `\ZZ`::

                sage: xgcd(12.0, 8.0)
                (4.00000000000000, 1.00000000000000, -1.00000000000000)

                sage: xgcd(3.1, 2.98714)
                (1.00000000000000, 0.322580645161290, 0.000000000000000)

                sage: xgcd(0.0, 1.1)
                (1.00000000000000, 0.000000000000000, 0.909090909090909)
            """
            P = self.parent()
            try:
                has_zero_char = P.characteristic() == 0
            except (AttributeError, NotImplementedError):
                has_zero_char = False
            if has_zero_char:
                from sage.rings.integer_ring import ZZ
                try:
                    return tuple(P(x) for x in ZZ(self).xgcd(ZZ(other)))
                except TypeError:
                    pass

            if not self.is_zero():
                return (P.one(), ~self, P.zero())
            if not other.is_zero():
                return (P.one(), P.zero(), ~other)
            # else both are 0
            return (P.zero(), P.zero(), P.zero())
예제 #60
0
    def dimension_cusp_forms(self, k=2):
        r"""
        Return the dimension of the space of weight k cusp forms for this
        group. This is given by a standard formula in terms of k and various
        invariants of the group; see Diamond + Shurman, "A First Course in
        Modular Forms", section 3.5 and 3.6. If k is not given, default to k =
        2.

        For dimensions of spaces of cusp forms with character for Gamma1, use
        the standalone function dimension_cusp_forms().

        For weight 1 cusp forms this function only works in cases where one can
        prove solely in terms of Riemann-Roch theory that there aren't any cusp
        forms (i.e. when the number of regular cusps is strictly greater than
        the degree of the canonical divisor). Otherwise a NotImplementedError is
        raised.

        EXAMPLE::

            sage: Gamma1(31).dimension_cusp_forms(2)
            26
            sage: Gamma1(3).dimension_cusp_forms(1)
            0
            sage: Gamma1(4).dimension_cusp_forms(1) # irregular cusp
            0
            sage: Gamma1(31).dimension_cusp_forms(1)
            Traceback (most recent call last):
            ...
            NotImplementedError: Computation of dimensions of weight 1 cusp forms spaces not implemented in general
        """
        k = ZZ(k)
        if k <= 0: return ZZ(0)

        if not (k % 2):
            # k even

            if k == 2:
                return self.genus()

            else:
                return (k - 1) * (self.genus() - 1) + (
                    k // ZZ(4)) * self.nu2() + (k // ZZ(3)) * self.nu3() + (
                        k // ZZ(2) - 1) * self.ncusps()

        else:
            # k odd

            if self.is_even():
                return ZZ(0)

            else:
                e_reg = self.nregcusps()
                e_irr = self.nirregcusps()

                if k > 1:
                    return (k - 1) * (self.genus() - 1) + (
                        k // ZZ(3)) * self.nu3() + (k - 2) / ZZ(2) * e_reg + (
                            k - 1) / ZZ(2) * e_irr
                else:
                    if e_reg > 2 * self.genus() - 2:
                        return ZZ(0)
                    else:
                        raise NotImplementedError, "Computation of dimensions of weight 1 cusp forms spaces not implemented in general"