Esempio n. 1
0
    def iter_positive_forms_with_content(self):
        if self.__disc is infinity:
            raise ValueError("infinity is not a true filter index")

        if self.__reduced:
            for a in range(1, isqrt(self.__disc // 3) + 1):
                for b in range(a + 1):
                    g = gcd(a, b)
                    for c in range(a,
                                   (b**2 + (self.__disc - 1)) // (4 * a) + 1):
                        yield (a, b, c), gcd(g, c)
        else:
            maxtrace = floor(5 * self.__disc / 15 + sqrt(self.__disc) / 2)
            for a in range(1, maxtrace + 1):
                for c in range(1, maxtrace - a + 1):
                    g = gcd(a, c)

                    Bu = isqrt(4 * a * c - 1)

                    di = 4 * a * c - self.__disc
                    if di >= 0:
                        Bl = isqrt(di) + 1
                    else:
                        Bl = 0

                    for b in range(-Bu, -Bl + 1):
                        yield (a, b, c), gcd(g, b)
                    for b in range(Bl, Bu + 1):
                        yield (a, b, c), gcd(g, b)
        #! if self.__reduced

        raise StopIteration
Esempio n. 2
0
    def order_at_cusp(self, cusp):
        r"""
        Return the order of vanishing of self at the given cusp.

        INPUT:


        -  ``cusp`` -  a CuspFamily object


        OUTPUT:


        - an integer


        EXAMPLES::

            sage: e = EtaProduct(2, {2:24, 1:-24})
            sage: e.order_at_cusp(CuspFamily(2, 1)) # cusp at infinity
            1
            sage: e.order_at_cusp(CuspFamily(2, 2)) # cusp 0
            -1
        """
        if not isinstance(cusp, CuspFamily):
            raise TypeError("Argument (=%s) should be a CuspFamily" % cusp)
        if cusp.level() != self.level():
            raise ValueError("Cusp not on right curve!")
        return 1 / ZZ(24) / gcd(cusp.width(),
                                self.level() // cusp.width()) * sum([
                                    ell * self.r(ell) / cusp.width() *
                                    (gcd(cusp.width(),
                                         self.level() // ell))**2
                                    for ell in self._keys
                                ])
Esempio n. 3
0
    def _find_cusps(self):
        r"""
        Calculate the reduced representatives of the equivalence classes of
        cusps for this group. Adapted from code by Ron Evans.

        EXAMPLE::

            sage: Gamma(8).cusps() # indirect doctest
            [0, 1/4, 1/3, 3/8, 1/2, 2/3, 3/4, 1, 4/3, 3/2, 5/3, 2, 7/3, 5/2, 8/3, 3, 7/2, 11/3, 4, 14/3, 5, 6, 7, Infinity]
        """
        n = self.level()
        C = [QQ(x) for x in xrange(n)]

        n0 = n // 2
        n1 = (n + 1) // 2

        for r in xrange(1, n1):
            if r > 1 and gcd(r, n) == 1:
                C.append(ZZ(r) / ZZ(n))
            if n0 == n / 2 and gcd(r, n0) == 1:
                C.append(ZZ(r) / ZZ(n0))

        for s in xrange(2, n1):
            for r in xrange(1, 1 + n):
                if GCD_list([s, r, n]) == 1:
                    # GCD_list is ~40x faster than gcd, since gcd wastes loads
                    # of time initialising a Sequence type.
                    u, v = _lift_pair(r, s, n)
                    C.append(ZZ(u) / ZZ(v))

        return [Cusp(x) for x in sorted(C)] + [Cusp(1, 0)]
    def iter_positive_forms_with_content(self) :
        if self.__disc is infinity :
            raise ValueError, "infinity is not a true filter index"
        
        
        if self.__reduced :        
            for a in xrange(1,isqrt(self.__disc // 3) + 1) :
                for b in xrange(a+1) :
                    g = gcd(a, b)
                    for c in xrange(a, (b**2 + (self.__disc - 1))//(4*a) + 1) :
                        yield (a,b,c), gcd(g,c)
        else :
            maxtrace = floor(5*self.__disc / 15 + sqrt(self.__disc)/2)
            for a in xrange(1, maxtrace + 1) :
                for c in xrange(1, maxtrace - a + 1) :
                    g = gcd(a,c)
                    
                    Bu = isqrt(4*a*c - 1)

                    di = 4*a*c - self.__disc
                    if di >= 0 :
                        Bl = isqrt(di) + 1 
                    else :
                        Bl = 0
                    
                    for b in xrange(-Bu, -Bl + 1) :
                        yield (a,b,c), gcd(g,b)
                    for b in xrange(Bl, Bu + 1) :
                        yield (a,b,c), gcd(g,b)
        #! if self.__reduced

        raise StopIteration
Esempio n. 5
0
def DuadicCodeOddPair(F, S1, S2):
    """
    Constructs the "odd pair" of duadic codes associated to the
    "splitting" S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import _is_a_splitting
        sage: n = 11; q = 3
        sage: C = Zmod(n).cyclotomic_cosets(q); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: _is_a_splitting(S1,S2,11)
        True
        sage: codes.DuadicCodeOddPair(GF(q),S1,S2)
        ([11, 6] Cyclic Code over GF(3),
         [11, 6] Cyclic Code over GF(3))

    This is consistent with Theorem 6.1.3 in [HP2003]_.
    """
    from sage.misc.stopgap import stopgap
    stopgap(
        "The function DuadicCodeOddPair has several issues which may cause wrong results",
        25896)

    from .cyclic_code import CyclicCode
    n = len(S1) + len(S2) + 1
    if not _is_a_splitting(S1, S2, n):
        raise TypeError("%s, %s must be a splitting of %s." % (S1, S2, n))
    q = F.order()
    k = Mod(q, n).multiplicative_order()
    FF = GF(q**k, "z")
    z = FF.gen()
    zeta = z**((q**k - 1) / n)
    P1 = PolynomialRing(FF, "x")
    x = P1.gen()
    g1 = prod([x - zeta**i for i in S1 + [0]])
    g2 = prod([x - zeta**i for i in S2 + [0]])
    j = sum([x**i / n for i in range(n)])
    P2 = PolynomialRing(F, "x")
    x = P2.gen()
    coeffs1 = [
        _lift2smallest_field(c)[0] for c in (g1 + j).coefficients(sparse=False)
    ]
    coeffs2 = [
        _lift2smallest_field(c)[0] for c in (g2 + j).coefficients(sparse=False)
    ]
    gg1 = P2(coeffs1)
    gg2 = P2(coeffs2)
    gg1 = gcd(gg1, x**n - 1)
    gg2 = gcd(gg2, x**n - 1)
    C1 = CyclicCode(length=n, generator_pol=gg1)
    C2 = CyclicCode(length=n, generator_pol=gg2)
    return C1, C2
    def _iter_positive_forms_with_content_and_discriminant(self) :
        if self.__disc is infinity :
            raise ValueError, "infinity is not a true filter index"
        
        if self.__reduced :
            for (l, (u,x)) in enumerate(self.__p1list) :
                if u == 0 :
                    for a in xrange(self.__level, isqrt(self.__disc // 4) + 1, self.__level) :
                        frpa = 4 * a
                        for b in xrange(a+1) :
                            g = gcd(a // self.__level,b)
                            bsq = b**2

                            for c in xrange(a, (b**2 + (self.__disc - 1))//(4*a) + 1) :
                                yield (((a,b,c), l), gcd(g,c), frpa*c - bsq)
                else :
                    for a in xrange(1, isqrt(self.__disc // 3) + 1) :
                        frpa = 4 * a
                        for b in xrange(a+1) :
                            g = gcd(a, b)
                            bsq = b**2
                                                        
                            ## We need x**2 * a + x * b + c % N == 0
                            h = (-((x**2 + 1) * a + x * b)) % self.__level
                            for c in xrange( a + h,
                                             (b**2 + (self.__disc - 1))//(4*a) + 1, self.__level ) :
                                yield (((a,b,c), l), gcd(g,(x**2 * a + x * b + c) // self.__level), frpa*c - bsq)
        #! if self.__reduced
        else :
            raise NotImplementedError
        
        raise StopIteration
Esempio n. 7
0
    def _find_cusps(self):
        r"""
        Calculate the reduced representatives of the equivalence classes of
        cusps for this group. Adapted from code by Ron Evans.

        EXAMPLES::

            sage: Gamma(8).cusps() # indirect doctest
            [0, 1/4, 1/3, 3/8, 1/2, 2/3, 3/4, 1, 4/3, 3/2, 5/3, 2, 7/3, 5/2, 8/3, 3, 7/2, 11/3, 4, 14/3, 5, 6, 7, Infinity]
        """
        n = self.level()
        C = [QQ(x) for x in range(n)]

        n0=n//2
        n1=(n+1)//2

        for r in range(1, n1):
            if r > 1 and gcd(r,n)==1:
                C.append(ZZ(r)/ZZ(n))
            if n0==n/2 and gcd(r,n0)==1:
                C.append(ZZ(r)/ZZ(n0))

        for s in range(2,n1):
            for r in range(1, 1+n):
                if GCD_list([s,r,n])==1:
                    # GCD_list is ~40x faster than gcd, since gcd wastes loads
                    # of time initialising a Sequence type.
                    u,v = _lift_pair(r,s,n)
                    C.append(ZZ(u)/ZZ(v))

        return [Cusp(x) for x in sorted(C)] + [Cusp(1,0)]
Esempio n. 8
0
File: jack.py Progetto: imark83/sage
def normalize_coefficients(self, c):
    r"""
    If our coefficient ring is the field of fractions over a univariate
    polynomial ring over the rationals, then we should clear both the
    numerator and denominator of the denominators of their
    coefficients.

    INPUT:

    - ``self`` -- a Jack basis of the symmetric functions
    - ``c`` -- a coefficient in the base ring of ``self``

    OUTPUT:

    - divide numerator and denominator by the greatest common divisor

    EXAMPLES::

        sage: JP = SymmetricFunctions(FractionField(QQ['t'])).jack().P()
        sage: t = JP.base_ring().gen()
        sage: a = 2/(1/2*t+1/2)
        sage: JP._normalize_coefficients(a)
        4/(t + 1)
        sage: a = 1/(1/3+1/6*t)
        sage: JP._normalize_coefficients(a)
        6/(t + 2)
        sage: a = 24/(4*t^2 + 12*t + 8)
        sage: JP._normalize_coefficients(a)
        6/(t^2 + 3*t + 2)
    """
    BR = self.base_ring()
    if is_FractionField(BR) and BR.base_ring() == QQ:
        denom = c.denominator()
        numer = c.numerator()

        # Clear the denominators
        a = lcm([i.denominator() for i in denom.coefficients(sparse=False)])
        b = lcm([i.denominator() for i in numer.coefficients(sparse=False)])
        l = Integer(a).lcm(Integer(b))
        denom *= l
        numer *= l

        # Divide through by the gcd of the numerators
        a = gcd([i.numerator() for i in denom.coefficients(sparse=False)])
        b = gcd([i.numerator() for i in numer.coefficients(sparse=False)])
        l = Integer(a).gcd(Integer(b))

        denom = denom // l
        numer = numer // l

        return c.parent()(numer, denom)
    else:
        return c
Esempio n. 9
0
    def _find_cusps(self):
        r"""
        Return an ordered list of inequivalent cusps for self, i.e. a
        set of representatives for the orbits of self on
        `\mathbf{P}^1(\QQ)`.  These are returned in a reduced
        form; see self.reduce_cusp for the definition of reduced.

        ALGORITHM:
            Lemma 3.2 in Cremona's 1997 book shows that for the action
            of Gamma1(N) on "signed projective space"
            `\Q^2 / (\Q_{\geq 0}^+)`, we have `u_1/v_1 \sim u_2 / v_2`
            if and only if `v_1 = v_2 \bmod N` and `u_1 = u_2 \bmod
            gcd(v_1, N)`. It follows that every orbit has a
            representative `u/v` with `v \le N` and `0 \le u \le
            gcd(v, N)`.  We iterate through all pairs `(u,v)`
            satisfying this.

            Having found a set containing at least one of every
            equivalence class modulo Gamma1(N), we can be sure of
            picking up every class modulo GammaH(N) since this
            contains Gamma1(N); and the reduce_cusp call does the
            checking to make sure we don't get any duplicates.

        EXAMPLES::

            sage: Gamma1(5)._find_cusps()
            [0, 2/5, 1/2, Infinity]
            sage: Gamma1(35)._find_cusps()
            [0, 2/35, 1/17, 1/16, 1/15, 1/14, 1/13, 1/12, 3/35, 1/11, 1/10, 1/9, 4/35, 1/8, 2/15, 1/7, 1/6, 6/35, 1/5, 3/14, 8/35, 1/4, 9/35, 4/15, 2/7, 3/10, 11/35, 1/3, 12/35, 5/14, 13/35, 2/5, 3/7, 16/35, 17/35, 1/2, 8/15, 4/7, 3/5, 9/14, 7/10, 5/7, 11/14, 4/5, 6/7, 9/10, 13/14, Infinity]
            sage: Gamma1(24)._find_cusps() == Gamma1(24).cusps(algorithm='modsym')
            True
            sage: GammaH(24, [13,17])._find_cusps() == GammaH(24,[13,17]).cusps(algorithm='modsym')
            True
        """

        s = []
        hashes = []
        N = self.level()

        for d in range(1, 1 + N):
            w = N.gcd(d)
            M = int(w) if w > 1 else 2
            for a in range(1, M):
                if gcd(a, w) != 1:
                    continue
                while gcd(a, d) != 1:
                    a += w
                c = self.reduce_cusp(Cusp(a, d))
                h = hash(c)
                if not h in hashes:
                    hashes.append(h)
                    s.append(c)
        return sorted(s)
Esempio n. 10
0
    def _find_cusps(self):
        r"""
        Return an ordered list of inequivalent cusps for self, i.e. a
        set of representatives for the orbits of self on
        `\mathbf{P}^1(\QQ)`.  These are returned in a reduced
        form; see self.reduce_cusp for the definition of reduced.

        ALGORITHM:
            Lemma 3.2 in Cremona's 1997 book shows that for the action
            of Gamma1(N) on "signed projective space"
            `\Q^2 / (\Q_{\geq 0}^+)`, we have `u_1/v_1 \sim u_2 / v_2`
            if and only if `v_1 = v_2 \bmod N` and `u_1 = u_2 \bmod
            gcd(v_1, N)`. It follows that every orbit has a
            representative `u/v` with `v \le N` and `0 \le u \le
            gcd(v, N)`.  We iterate through all pairs `(u,v)`
            satisfying this.

            Having found a set containing at least one of every
            equivalence class modulo Gamma1(N), we can be sure of
            picking up every class modulo GammaH(N) since this
            contains Gamma1(N); and the reduce_cusp call does the
            checking to make sure we don't get any duplicates.

        EXAMPLES::

            sage: Gamma1(5)._find_cusps()
            [0, 2/5, 1/2, Infinity]
            sage: Gamma1(35)._find_cusps()
            [0, 2/35, 1/17, 1/16, 1/15, 1/14, 1/13, 1/12, 3/35, 1/11, 1/10, 1/9, 4/35, 1/8, 2/15, 1/7, 1/6, 6/35, 1/5, 3/14, 8/35, 1/4, 9/35, 4/15, 2/7, 3/10, 11/35, 1/3, 12/35, 5/14, 13/35, 2/5, 3/7, 16/35, 17/35, 1/2, 8/15, 4/7, 3/5, 9/14, 7/10, 5/7, 11/14, 4/5, 6/7, 9/10, 13/14, Infinity]
            sage: Gamma1(24)._find_cusps() == Gamma1(24).cusps(algorithm='modsym')
            True
            sage: GammaH(24, [13,17])._find_cusps() == GammaH(24,[13,17]).cusps(algorithm='modsym')
            True
        """

        s = []
        hashes = []
        N = self.level()

        for d in range(1, 1+N):
            w = N.gcd(d)
            M = int(w) if w > 1 else 2
            for a in range(1,M):
                if gcd(a, w) != 1:
                    continue
                while gcd(a, d) != 1:
                    a += w
                c = self.reduce_cusp(Cusp(a,d))
                h = hash(c)
                if not h in hashes:
                    hashes.append(h)
                    s.append(c)
        return sorted(s)
Esempio n. 11
0
def DuadicCodeOddPair(F,S1,S2):
    """
    Constructs the "odd pair" of duadic codes associated to the
    "splitting" S1, S2 of n.

    .. warning::

       Maybe the splitting should be associated to a sum of
       q-cyclotomic cosets mod n, where q is a *prime*.

    EXAMPLES::

        sage: from sage.coding.code_constructions import _is_a_splitting
        sage: n = 11; q = 3
        sage: C = Zmod(n).cyclotomic_cosets(q); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: _is_a_splitting(S1,S2,11)
        True
        sage: codes.DuadicCodeOddPair(GF(q),S1,S2)
        ([11, 6] Cyclic Code over GF(3),
         [11, 6] Cyclic Code over GF(3))

    This is consistent with Theorem 6.1.3 in [HP2003]_.
    """
    from .cyclic_code import CyclicCode
    n = len(S1) + len(S2) + 1
    if not _is_a_splitting(S1,S2,n):
        raise TypeError("%s, %s must be a splitting of %s."%(S1,S2,n))
    q = F.order()
    k = Mod(q,n).multiplicative_order()
    FF = GF(q**k,"z")
    z = FF.gen()
    zeta = z**((q**k-1)/n)
    P1 = PolynomialRing(FF,"x")
    x = P1.gen()
    g1 = prod([x-zeta**i for i in S1+[0]])
    g2 = prod([x-zeta**i for i in S2+[0]])
    j = sum([x**i/n for i in range(n)])
    P2 = PolynomialRing(F,"x")
    x = P2.gen()
    coeffs1 = [_lift2smallest_field(c)[0] for c in (g1+j).coefficients(sparse=False)]
    coeffs2 = [_lift2smallest_field(c)[0] for c in (g2+j).coefficients(sparse=False)]
    gg1 = P2(coeffs1)
    gg2 = P2(coeffs2)
    gg1 = gcd(gg1, x**n - 1)
    gg2 = gcd(gg2, x**n - 1)
    C1 = CyclicCode(length = n, generator_pol = gg1)
    C2 = CyclicCode(length = n, generator_pol = gg2)
    return C1,C2
 def eval(self, expansion, weight = None) :
     if weight is None :
         try :
             weight = expansion.weight()
         except AttributeError :
             raise ValueError, "weight must be defined for the Hecke action"
     
     precision = expansion.precision()
     if precision.is_infinite() :
         precision = expansion._bounding_precision()
     else :
         precision = precision._hecke_operator(self.__l)
     characters = expansion.non_zero_components()
     expansion_level = precision.level()
     
     if gcd(expansion_level, self.__l) != 1 :
         raise ValueError, "Level of expansion and of Hecke operator must be coprime."
     
     hecke_expansion = dict()
     for ch in characters :
         hecke_expansion[ch] = dict( (k, self.hecke_coeff(expansion, ch, k, weight, expansion_level))
                                     for k in precision )
     
     result = expansion.parent()._element_constructor_(hecke_expansion)
     result._set_precision(expansion.precision()._hecke_operator(self.__l))
     
     return result
Esempio n. 13
0
    def cardinality(self):
        """
        Return the number of Lyndon words with the evaluation e.

        EXAMPLES::

            sage: LyndonWords([]).cardinality()
            0
            sage: LyndonWords([2,2]).cardinality()
            1
            sage: LyndonWords([2,3,2]).cardinality()
            30

        Check to make sure that the count matches up with the number of
        Lyndon words generated::

            sage: comps = [[],[2,2],[3,2,7],[4,2]] + Compositions(4).list()
            sage: lws = [LyndonWords(comp) for comp in comps]
            sage: all(lw.cardinality() == len(lw.list()) for lw in lws)
            True
        """
        evaluation = self._e
        le = list(evaluation)
        if not evaluation:
            return Integer(0)
        n = sum(evaluation)
        return sum(
            moebius(j) * multinomial([ni // j for ni in evaluation])
            for j in divisors(gcd(le))) // n
Esempio n. 14
0
def find_correct_matrix(M, N):
    r"""
    Given a matrix M1 that maps infinity to a/c this returns a matrix M2 Matrix([[A,B],[C,D]]) that maps infinity to a Gamma0(N)-equivalent cusp A/C and satisfies, C|N, C>0, (A,N)=1 and N|B.
    It also returns T^n = Matrix([[1,n],[0,1]]) such that M2*T^n*M1**(-1) is in Gamma0(N).
    """
    a, b, c, d = list(map(lambda x: ZZ(x), M.list()))
    if (c > 0 and c.divides(N) and gcd(a, N) == 1 and b % N == 0):
        return M, identity_matrix(2)
    if c == 0:
        return Matrix([[1, 0], [N, 1]]), identity_matrix(2)
    cusps = cusps_of_gamma0(N)
    for cusp in cusps:
        if Cusp(QQ(a) / QQ(c)).is_gamma0_equiv(cusp, N):
            break
    A, C = cusp.numerator(), cusp.denominator()
    _, D, b = xgcd(A, N * C)
    M2 = Matrix([[A, -N * b], [C, D]])
    n = 0
    T = Matrix([[1, 1], [0, 1]])
    tmp = identity_matrix(2)
    while True:
        if N.divides((M2 * tmp * M**(-1))[1][0]):
            return M2, tmp
        elif N.divides((M2 * tmp**(-1) * M**(-1))[1][0]):
            return M2, tmp**(-1)
        tmp = tmp * T
    def get_representatives( self, t, N) :
        r"""
        A helper function used in hecke_coeff that computes the right
        coset representatives of $\Gamma^0(t) \cap \Gamma_0(N) \ Gamma_0(N)$ where
        $\Gamma^0(t)$ is the subgroup of $SL(2,Z)$ where the upper right hand
        corner is divisible by $t$.

        NOTE
            We use the bijection $\Gamma^0(t)\SL(2,Z) \rightarrow P^1(\Z/t\Z)$
            given by $A \mapsto [1:0]A$.
        """
        if t == 1 : return [(1,0,0,1)]
        
        rep_list = []
        
        for (x,y) in P1List(t):
            ## we know that (N, x, y) = 1
            N1 = gcd(N, x)
            if N1 != 1 :
                x = x + t * N // N1

            ## we calculate a pair c,d satisfying a minimality condition
            ## to make later multiplications cheaper
            (_, d, c) = Integer(x)._xgcd(Integer(N * y), minimal=True)
            
            #print (x, y, -N * c, d)
            rep_list.append((x, y, -N * c, d))
                
        return rep_list
Esempio n. 16
0
    def __init__(self, base_field, length, designed_distance,
                 primitive_root=None, offset=1, jump_size=1, b=0):
        """
        TESTS:

        ``designed_distance`` must be between 1 and ``length`` (inclusive),
        otherwise an exception is raised::

            sage: C = codes.BCHCode(GF(2), 15, 16)
            Traceback (most recent call last):
            ...
            ValueError: designed_distance must belong to [1, n]
        """
        if not (0 < designed_distance <= length):
            raise ValueError("designed_distance must belong to [1, n]")

        if base_field not in Fields() or not base_field.is_finite():
            raise ValueError("base_field has to be a finite field")

        q = base_field.cardinality()
        s = Zmod(length)(q).multiplicative_order()
        if gcd(jump_size, q ** s - 1) != 1:
            raise ValueError("jump_size must be coprime with the order of "
                             "the multiplicative group of the splitting field")

        D = [(offset + jump_size * i) % length
             for i in range(designed_distance - 1)]

        super(BCHCode, self).__init__(field=base_field, length=length,
                                      D=D, primitive_root=primitive_root)
        self._default_decoder_name = "UnderlyingGRS"
        self._jump_size = jump_size
        self._offset = offset
        self._designed_distance = designed_distance
Esempio n. 17
0
    def random_element(self, bound=100, *args, **kwds):
        r"""
        Return a random element of `{\rm SL}_2(\ZZ)` with entries whose
        absolute value is strictly less than bound (default 100).
        Additional arguments and keywords are passed to the random_element
        method of ZZ.

        (Algorithm: Generate a random pair of integers at most bound. If they
        are not coprime, throw them away and start again. If they are, find an
        element of `{\rm SL}_2(\ZZ)` whose bottom row is that, and
        left-multiply it by `\begin{pmatrix} 1 & w \\ 0 & 1\end{pmatrix}` for
        an integer `w` randomly chosen from a small enough range that the
        answer still has entries at most bound.)

        It is, unfortunately, not true that all elements of SL2Z with entries <
        bound appear with equal probability; those with larger bottom rows are
        favoured, because there are fewer valid possibilities for w.

        EXAMPLES::

            sage: SL2Z.random_element()
            [60 13]
            [83 18]
            sage: SL2Z.random_element(5)
            [-1  3]
            [ 1 -4]

        Passes extra positional or keyword arguments through::

            sage: SL2Z.random_element(5, distribution='1/n')
            [ 1 -4]
            [ 0  1]
        """
        if bound <= 1: raise ValueError("bound must be greater than 1")
        c = ZZ.random_element(1-bound, bound, *args, **kwds)
        d = ZZ.random_element(1-bound, bound, *args, **kwds)
        if gcd(c,d) != 1: # try again
            return self.random_element(bound, *args, **kwds)
        else:
            a,b,c,d = lift_to_sl2z(c,d,0)
            whi = bound
            wlo = bound
            if c > 0:
                whi = min(whi, ((bound - a)/ZZ(c)).ceil())
                wlo = min(wlo, ((bound + a)/ZZ(c)).ceil())
            elif c < 0:
                whi = min(whi, ((bound + a)/ZZ(-c)).ceil())
                wlo = min(wlo, ((bound - a)/ZZ(-c)).ceil())

            if d > 0:
                whi = min(whi, ((bound - b)/ZZ(d)).ceil())
                wlo = min(wlo, ((bound + b)/ZZ(d)).ceil())
            elif d < 0:
                whi = min(whi, ((bound + b)/ZZ(-d)).ceil())
                wlo = min(wlo, ((bound - b)/ZZ(-d)).ceil())

            w = ZZ.random_element(1-wlo, whi, *args, **kwds)
            a += c*w
            b += d*w
            return self([a,b,c,d])
Esempio n. 18
0
def hecke_matrix_on_ord(ll, ord_basis, weight = 2, level = 1, eps = None, p=None, prec=None, check_is_operator=True):
    R = ord_basis.parent().base_ring()
    if prec is None:
        try:
            prec = R.precision_cap()
        except AttributeError:
            pass
    ncols = ZZ(floor( (ord_basis.ncols() - 1) / ll)) + 1
    if ncols < ord_basis.nrows():
        raise ValueError("Cannot compute the matrix of T_ell with ell=%s because of lack of precision. (nrows = %s, ncols = %s)"%(ll, ord_basis.nrows(), ncols))
    M = Matrix(R, ord_basis.nrows(), ncols, 0)
    if eps is None:
        eps = lambda ll : ZZ(1) if gcd(level,ll) == 1 else ZZ(0)
    if weight is None:
        assert eps(ll) == 0
        llpow_eps = 0
    else:
        llpow_eps = ll**(weight-1) * eps(ll)

    for i, b in enumerate(ord_basis):
        for j in range(ncols):
            M[i, j] = b[j * ll]
            if j % ll == 0:
                M[i, j] += R(llpow_eps) * b[j // ll]
    small_mat = ord_basis.submatrix(0,0,ncols = ncols)
    assert is_echelon(small_mat)
    ans = solve_xAb_echelon(small_mat,M,p, prec, check=check_is_operator)
    return ans
Esempio n. 19
0
                def rational_catalan_number(self, p, polynomial=False):
                    r"""
                    Return the ``p``-th rational Catalan number
                    associated to ``self``.

                    It is defined by

                    .. MATH::

                        \prod_{i = 1}^n \frac{p + (p(d_i-1)) \mod h)}{d_i},

                    where `d_1, \ldots, d_n` are the degrees and
                    `h` is the Coxeter number. See [STW2016]_
                    for this formula.

                    INPUT:

                    - ``polynomial`` -- optional boolean (default ``False``)
                      if ``True``, return instead the `q`-analogue as a
                      polynomial in `q`

                    REFERENCES:

                    .. [STW2016] C. Stump, H. Thomas, N. Williams.
                       *Cataland II*, in preparation, 2016.

                    EXAMPLES::

                        sage: W = ColoredPermutations(1,3)
                        sage: [W.rational_catalan_number(p) for p in [5,7,8]]
                        [7, 12, 15]

                        sage: W = ColoredPermutations(2,2)
                        sage: [W.rational_catalan_number(p) for p in [7,9,11]]
                        [10, 15, 21]

                    TESTS::

                        sage: W = ColoredPermutations(1,4)
                        sage: W.rational_catalan_number(3, polynomial=True)
                        q^6 + q^4 + q^3 + q^2 + 1
                    """
                    from sage.arith.all import gcd
                    from sage.combinat.q_analogues import q_int

                    h = self.coxeter_number()
                    if not gcd(h, p) == 1:
                        raise ValueError(
                            "parameter p = %s is not coprime to the Coxeter number %s"
                            % (p, h))

                    if polynomial:
                        f = q_int
                    else:
                        f = lambda n: n

                    num = prod(
                        f(p + (p * (deg - 1)) % h) for deg in self.degrees())
                    den = prod(f(deg) for deg in self.degrees())
                    return num // den
Esempio n. 20
0
def _lift_pair(U,V,N):
    r"""
    Utility function. Given integers ``U, V, N``, with `N \ge 1` and `{\rm
    gcd}(U, V, N) = 1`, return a pair `(u, v)` congruent to `(U, V) \bmod N`,
    such that `{\rm gcd}(u,v) = 1`, `u, v \ge 0`, `v` is as small as possible,
    and `u` is as small as possible for that `v`.

    *Warning*: As this function is for internal use, it does not do a
    preliminary sanity check on its input, for efficiency. It will recover
    reasonably gracefully if ``(U, V, N)`` are not coprime, but only after
    wasting quite a lot of cycles!

    EXAMPLES::

        sage: from sage.modular.arithgroup.congroup_gamma import _lift_pair
        sage: _lift_pair(2,4,7)
        (9, 4)
        sage: _lift_pair(2,4,8) # don't do this
        Traceback (most recent call last):
        ...
        ValueError: (U, V, N) must be coprime
    """
    u = U % N
    v = V % N
    if v == 0:
        if u == 1:
            return (1,0)
        else:
            v = N
    while gcd(u, v) > 1:
        u = u+N
        if u > N*v: raise ValueError("(U, V, N) must be coprime")
    return (u, v)
    def eval(self, expansion, weight=None):
        if weight is None:
            try:
                weight = expansion.weight()
            except AttributeError:
                raise ValueError, "weight must be defined for the Hecke action"

        precision = expansion.precision()
        if precision.is_infinite():
            precision = expansion._bounding_precision()
        else:
            precision = precision._hecke_operator(self.__l)
        characters = expansion.non_zero_components()
        expansion_level = precision.level()

        if gcd(expansion_level, self.__l) != 1:
            raise ValueError, "Level of expansion and of Hecke operator must be coprime."

        hecke_expansion = dict()
        for ch in characters:
            hecke_expansion[ch] = dict(
                (k,
                 self.hecke_coeff(expansion, ch, k, weight, expansion_level))
                for k in precision)

        result = expansion.parent()._element_constructor_(hecke_expansion)
        result._set_precision(expansion.precision()._hecke_operator(self.__l))

        return result
    def get_representatives(self, t, N):
        r"""
        A helper function used in hecke_coeff that computes the right
        coset representatives of $\Gamma^0(t) \cap \Gamma_0(N) \ Gamma_0(N)$ where
        $\Gamma^0(t)$ is the subgroup of $SL(2,Z)$ where the upper right hand
        corner is divisible by $t$.

        NOTE
            We use the bijection $\Gamma^0(t)\SL(2,Z) \rightarrow P^1(\Z/t\Z)$
            given by $A \mapsto [1:0]A$.
        """
        if t == 1: return [(1, 0, 0, 1)]

        rep_list = []

        for (x, y) in P1List(t):
            ## we know that (N, x, y) = 1
            N1 = gcd(N, x)
            if N1 != 1:
                x = x + t * N // N1

            ## we calculate a pair c,d satisfying a minimality condition
            ## to make later multiplications cheaper
            (_, d, c) = Integer(x)._xgcd(Integer(N * y), minimal=True)

            #print (x, y, -N * c, d)
            rep_list.append((x, y, -N * c, d))

        return rep_list
Esempio n. 23
0
def num_cusps_of_width(N, d):
    r"""
    Return the number of cusps on `X_0(N)` of width d.

    INPUT:


    -  ``N`` - (integer): the level

    -  ``d`` - (integer): an integer dividing N, the cusp
       width


    EXAMPLES::

        sage: [num_cusps_of_width(18,d) for d in divisors(18)]
        [1, 1, 2, 2, 1, 1]
        sage: num_cusps_of_width(4,8)
        Traceback (most recent call last):
        ...
        ValueError: N and d must be positive integers with d|N
    """
    N = ZZ(N)
    d = ZZ(d)
    if N <= 0 or d <= 0 or (N % d) != 0:
        raise ValueError("N and d must be positive integers with d|N")

    return euler_phi(gcd(d, N//d))
Esempio n. 24
0
def find_gens_list(klist, r = 0, bound = None, verbose = True):
    """
    Use an elliptic curve variation of Rain's method to find a generator
    of a subfield of degree r within the ambient fields in klist.
    """
    p = klist[0].characteristic()
    ngcd = gcd([k.degree() for k in klist])
    nlcm = lcm([k.degree() for k in klist])
    if r == 0:
        r = ngcd
    assert all(k.degree() % r == 0 for k in klist)

    # This might be useful if elliptic curves defined over an 
    # extension of F_p are used.
    kb = k.base_ring()

    # List of candidates for l.
    lT = find_l(kb, r, bound)
    if lT is None:
        raise RuntimeError, "no suitable l found"

    # Find an elliptic curve with the given trace. 
    E = find_elliptic_curve(kb, lT)
    if E is None:
        raise RuntimeError, "no suitable elliptic curve found"

    return tuple(find_unique_orbit(E.change_ring(k), E.cardinality(extension_degree=k.degree()), lT[0], r) for k in klist)
Esempio n. 25
0
def bw_shift_rec(dop, shift=ZZ.zero()):
    Scalars = utilities.mypushout(dop.base_ring().base_ring(), shift.parent())
    if dop.parent().is_D():
        dop = DifferentialOperator(dop)  # compatibility bugware
        rop = dop._my_to_S()
    else:  # more compatibility bugware
        Pols_n = PolynomialRing(dop.base_ring().base_ring(), 'n')
        rop = dop.to_S(ore_algebra.OreAlgebra(Pols_n, 'Sn'))
    Pols_n, n = rop.base_ring().change_ring(Scalars).objgen()
    Rops = ore_algebra.OreAlgebra(Pols_n, 'Sn')
    ordrec = rop.order()
    rop = Rops([p(n - ordrec + shift) for p in rop])
    # Clear_denominators
    den = lcm([p.denominator() for p in rop])
    rop = den * rop
    # Remove constant common factors to make the recurrence smaller
    if Scalars is QQ:
        g = gcd(c for p in rop for c in p)
    # elif utilities.is_QQi(Scalars): # XXX: too slow (and not general enough)
    #     ZZi = Scalars.maximal_order()
    #     g = ZZi.zero()
    #     for c in (c1 for p in rop for c1 in p):
    #         g = ZZi(g).gcd(ZZi(c)) # gcd returns a nfe
    #         if g.is_one():
    #             g = None
    #             break
    else:
        g = None
    if g is not None:
        rop = (1 / g) * rop
    coeff = [rop[ordrec - k] for k in range(ordrec + 1)]
    return BwShiftRec(coeff)
Esempio n. 26
0
    def order_at_cusp(self, cusp):
        r"""
        Return the order of vanishing of self at the given cusp.

        INPUT:


        -  ``cusp`` -  a CuspFamily object


        OUTPUT:


        - an integer


        EXAMPLES::

            sage: e = EtaProduct(2, {2:24, 1:-24})
            sage: e.order_at_cusp(CuspFamily(2, 1)) # cusp at infinity
            1
            sage: e.order_at_cusp(CuspFamily(2, 2)) # cusp 0
            -1
        """
        if not isinstance(cusp, CuspFamily):
            raise TypeError("Argument (=%s) should be a CuspFamily" % cusp)
        if cusp.level() != self.level():
            raise ValueError("Cusp not on right curve!")
        return 1/ZZ(24)/gcd(cusp.width(), self.level()//cusp.width()) * sum( [ell*self.r(ell)/cusp.width() * (gcd(cusp.width(), self.level()//ell))**2  for ell in self._keys] )
Esempio n. 27
0
    def random_element(self, bound=100, *args, **kwds):
        r"""
        Return a random element of `{\rm SL}_2(\ZZ)` with entries whose
        absolute value is strictly less than bound (default 100).
        Additional arguments and keywords are passed to the random_element
        method of ZZ.

        (Algorithm: Generate a random pair of integers at most bound. If they
        are not coprime, throw them away and start again. If they are, find an
        element of `{\rm SL}_2(\ZZ)` whose bottom row is that, and
        left-multiply it by `\begin{pmatrix} 1 & w \\ 0 & 1\end{pmatrix}` for
        an integer `w` randomly chosen from a small enough range that the
        answer still has entries at most bound.)

        It is, unfortunately, not true that all elements of SL2Z with entries <
        bound appear with equal probability; those with larger bottom rows are
        favoured, because there are fewer valid possibilities for w.

        EXAMPLES::

            sage: SL2Z.random_element()
            [60 13]
            [83 18]
            sage: SL2Z.random_element(5)
            [-1  3]
            [ 1 -4]

        Passes extra positional or keyword arguments through::

            sage: SL2Z.random_element(5, distribution='1/n')
            [ 1 -4]
            [ 0  1]
        """
        if bound <= 1: raise ValueError("bound must be greater than 1")
        c = ZZ.random_element(1 - bound, bound, *args, **kwds)
        d = ZZ.random_element(1 - bound, bound, *args, **kwds)
        if gcd(c, d) != 1:  # try again
            return self.random_element(bound, *args, **kwds)
        else:
            a, b, c, d = lift_to_sl2z(c, d, 0)
            whi = bound
            wlo = bound
            if c > 0:
                whi = min(whi, ((bound - a) / ZZ(c)).ceil())
                wlo = min(wlo, ((bound + a) / ZZ(c)).ceil())
            elif c < 0:
                whi = min(whi, ((bound + a) / ZZ(-c)).ceil())
                wlo = min(wlo, ((bound - a) / ZZ(-c)).ceil())

            if d > 0:
                whi = min(whi, ((bound - b) / ZZ(d)).ceil())
                wlo = min(wlo, ((bound + b) / ZZ(d)).ceil())
            elif d < 0:
                whi = min(whi, ((bound + b) / ZZ(-d)).ceil())
                wlo = min(wlo, ((bound - b) / ZZ(-d)).ceil())

            w = ZZ.random_element(1 - wlo, whi, *args, **kwds)
            a += c * w
            b += d * w
            return self([a, b, c, d])
Esempio n. 28
0
def _lift_pair(U, V, N):
    r"""
    Utility function. Given integers ``U, V, N``, with `N \ge 1` and `{\rm
    gcd}(U, V, N) = 1`, return a pair `(u, v)` congruent to `(U, V) \bmod N`,
    such that `{\rm gcd}(u,v) = 1`, `u, v \ge 0`, `v` is as small as possible,
    and `u` is as small as possible for that `v`.

    *Warning*: As this function is for internal use, it does not do a
    preliminary sanity check on its input, for efficiency. It will recover
    reasonably gracefully if ``(U, V, N)`` are not coprime, but only after
    wasting quite a lot of cycles!

    EXAMPLE::

        sage: from sage.modular.arithgroup.congroup_gamma import _lift_pair
        sage: _lift_pair(2,4,7)
        (9, 4)
        sage: _lift_pair(2,4,8) # don't do this
        Traceback (most recent call last):
        ...
        ValueError: (U, V, N) must be coprime
    """
    u = U % N
    v = V % N
    if v == 0:
        if u == 1:
            return (1, 0)
        else:
            v = N
    while gcd(u, v) > 1:
        u = u + N
        if u > N * v: raise ValueError("(U, V, N) must be coprime")
    return (u, v)
Esempio n. 29
0
def num_cusps_of_width(N, d):
    r"""
    Return the number of cusps on `X_0(N)` of width d.

    INPUT:


    -  ``N`` - (integer): the level

    -  ``d`` - (integer): an integer dividing N, the cusp
       width


    EXAMPLES::

        sage: [num_cusps_of_width(18,d) for d in divisors(18)]
        [1, 1, 2, 2, 1, 1]
        sage: num_cusps_of_width(4,8)
        Traceback (most recent call last):
        ...
        ValueError: N and d must be positive integers with d|N
    """
    N = ZZ(N)
    d = ZZ(d)
    if N <= 0 or d <= 0 or (N % d) != 0:
        raise ValueError("N and d must be positive integers with d|N")

    return euler_phi(gcd(d, N // d))
def get_overconvergent_class_matrices(p,E,prec, sign_at_infinity,use_ps_dists = False,use_sage_db = False,parallelize = False,progress_bar = False):
    # If the moments are pre-calculated, will load them. Otherwise, calculate and
    # save them to disk.
    if use_ps_dists == False:
        raise NotImplementedError, 'Must use distributions from Pollack-Stevens code in the split case'

    sgninfty = 'plus' if sign_at_infinity == 1 else 'minus'
    dist_type = 'ps' if use_ps_dists == True else 'fm'
    fname = 'moments_%s_%s_%s_%s_%s.sobj'%(p,E.cremona_label(),sgninfty,prec,dist_type)
    if use_sage_db:
        try:
            Phi = db(fname)
            return Phi
        except IOError: pass
    phi0 = E.pollack_stevens_modular_symbol()
    if sign_at_infinity == 1:
        phi0 = phi0.plus_part()
    elif sign_at_infinity == -1:
        phi0 = phi0.minus_part()
    else:
        assert sign_at_infinity == 0
        phi0 = phi0.plus_part() + phi0.minus_part()
    phi0 = 1 / gcd([val.moment(0) for val in phi0.values()]) * phi0
    Phi = phi0.lift(p,M = prec - 1,algorithm = 'stevens',eigensymbol = True)
    Phi._liftee = phi0
    return Phi
Esempio n. 31
0
def _normalize_H(H, level):
    """
    Normalize representatives for a given subgroup H of the units
    modulo level.

    .. NOTE::

        This function does *not* make any attempt to find a minimal
        set of generators for H. It simply normalizes the inputs for use
        in hashing.

    EXAMPLES::

        sage: sage.modular.arithgroup.congroup_gammaH._normalize_H([23], 10)
        [3]
        sage: sage.modular.arithgroup.congroup_gammaH._normalize_H([1,5], 7)
        [5]
        sage: sage.modular.arithgroup.congroup_gammaH._normalize_H([4,18], 14)
        Traceback (most recent call last):
        ...
        ArithmeticError: The generators [4, 18] must be units modulo 14
        sage: sage.modular.arithgroup.congroup_gammaH._normalize_H([3,17], 14)
        [3]
        sage: sage.modular.arithgroup.congroup_gammaH._normalize_H([-1,7,9], 10)
        [7, 9]
    """
    H = [ZZ(h) for h in H]
    for h in H:
        if gcd(h, level) > 1:
            raise ArithmeticError('The generators %s must be units modulo %s'%(H, level))
    H = sorted(set([h%level for h in H]))
    if 1 in H:
        H.remove(1)
    return H
Esempio n. 32
0
def _normalize_H(H, level):
    """
    Normalize representatives for a given subgroup H of the units
    modulo level.

    .. NOTE::

        This function does *not* make any attempt to find a minimal
        set of generators for H. It simply normalizes the inputs for use
        in hashing.

    EXAMPLES::

        sage: sage.modular.arithgroup.congroup_gammaH._normalize_H([23], 10)
        [3]
        sage: sage.modular.arithgroup.congroup_gammaH._normalize_H([1,5], 7)
        [5]
        sage: sage.modular.arithgroup.congroup_gammaH._normalize_H([4,18], 14)
        Traceback (most recent call last):
        ...
        ArithmeticError: The generators [4, 18] must be units modulo 14
        sage: sage.modular.arithgroup.congroup_gammaH._normalize_H([3,17], 14)
        [3]
        sage: sage.modular.arithgroup.congroup_gammaH._normalize_H([-1,7,9], 10)
        [7, 9]
    """
    H = [ZZ(h) for h in H]
    for h in H:
        if gcd(h, level) > 1:
            raise ArithmeticError('The generators %s must be units modulo %s'%(H, level))
    H = sorted(set([h%level for h in H]))
    if 1 in H:
        H.remove(1)
    return H
Esempio n. 33
0
def _goodness(n, R, p):
    """
    Return the goodness of ``n`` for the sequence ``R`` and the prime ``p`` -- that is the largest
    non-``p`` prime power dividing ``period(n)``.

    INPUT:

    - ``n`` --  an integer

    - ``R`` -- an object in the class ``BinaryRecurrenceSequence``

    - ``p`` -- a rational prime

    OUTPUT:

    - An integer which is the "goodness" of ``n``, i.e. the largest non-``p`` prime power dividing ``period(n)``.

    EXAMPLES::

        sage: R = BinaryRecurrenceSequence(11,2)
        sage: sage.combinat.binary_recurrence_sequences._goodness(89,R,7)
        11

        sage: R = BinaryRecurrenceSequence(1,1)
        sage: sage.combinat.binary_recurrence_sequences._goodness(13,R,7)
        4
        sage: R.period(13)        #the period of R mod 13 is divisible by 7
        28

    """

    #The period of R mod ell
    K = R.period(n)

    return _largest_ppower_divisor(K / gcd(K, p))
Esempio n. 34
0
File: bch.py Progetto: sagemath/sage
    def __init__(self, base_field, length, designed_distance,
                 primitive_root=None, offset=1, jump_size=1, b=0):
        """
        TESTS:

        ``designed_distance`` must be between 1 and ``length`` (inclusive),
        otherwise an exception is raised::

            sage: C = codes.BCHCode(GF(2), 15, 16)
            Traceback (most recent call last):
            ...
            ValueError: designed_distance must belong to [1, n]
        """
        if not (0 < designed_distance <= length):
            raise ValueError("designed_distance must belong to [1, n]")

        if base_field not in Fields or not base_field.is_finite():
            raise ValueError("base_field has to be a finite field")

        q = base_field.cardinality()
        s = Zmod(length)(q).multiplicative_order()
        if gcd(jump_size, q ** s - 1) != 1:
            raise ValueError("jump_size must be coprime with the order of "
                             "the multiplicative group of the splitting field")

        D = [(offset + jump_size * i) % length
             for i in range(designed_distance - 1)]

        super(BCHCode, self).__init__(field=base_field, length=length,
                                      D=D, primitive_root=primitive_root)
        self._default_decoder_name = "UnderlyingGRS"
        self._jump_size = jump_size
        self._offset = offset
        self._designed_distance = designed_distance
Esempio n. 35
0
    def cardinality(self):
        """
        Returns the number of Lyndon words with the evaluation e.

        EXAMPLES::

            sage: LyndonWords([]).cardinality()
            0
            sage: LyndonWords([2,2]).cardinality()
            1
            sage: LyndonWords([2,3,2]).cardinality()
            30

        Check to make sure that the count matches up with the number of
        Lyndon words generated.

        ::

            sage: comps = [[],[2,2],[3,2,7],[4,2]] + Compositions(4).list()
            sage: lws = [LyndonWords(comp) for comp in comps]
            sage: all(lw.cardinality() == len(lw.list()) for lw in lws)
            True
        """
        evaluation = self._e
        le = builtins.list(evaluation)
        if len(evaluation) == 0:
            return 0

        n = sum(evaluation)

        return sum([
            moebius(j) * factorial(n / j) /
            prod([factorial(ni / j) for ni in evaluation])
            for j in divisors(gcd(le))
        ]) / n
Esempio n. 36
0
def blift(LF, Li, p, S=None):
    r"""
    Search for a solution to the given list of inequalities.

    If found, lift the solution to
    an appropriate valuation. See Lemma 3.3.6 in [Molnar]_

    INPUT:

    - ``LF`` -- a list of integer polynomials in one variable (the normalized coefficients)

    - ``Li`` -- an integer, the bound on coefficients

    - ``p`` -- a prime

    OUTPUT:

    - boolean -- whether or not the lift is successful

    - integer -- the lift

    EXAMPLES::

        sage: R.<b> = PolynomialRing(QQ)
        sage: from sage.dynamics.arithmetic_dynamics.endPN_minimal_model import blift
        sage: blift([8*b^3 + 12*b^2 + 6*b + 1, 48*b^2 + 483*b + 117, 72*b + 1341, -24*b^2 + 411*b + 99, -144*b + 1233, -216*b], 2, 3)
        (True, 4)
    """

    P = LF[0].parent()
    #Determine which inequalities are trivial, and scale the rest, so that we only lift
    #as many times as needed.
    keepScaledIneqs = [scale(P(coeff), Li, p) for coeff in LF if coeff != 0]
    keptVals = [i[2] for i in keepScaledIneqs if i[0]]
    if keptVals != []:
        #Determine the valuation to lift until.
        liftval = max(keptVals)
    else:
        #All inequalities are satisfied.
        return True, 1
    if S is None:
        S = PolynomialRing(Zmod(p), 'b')
    keptScaledIneqs = [S(i[1]) for i in keepScaledIneqs if i[0]]
    #We need a solution for each polynomial on the left hand side of the inequalities,
    #so we need only find a solution for their gcd.
    g = gcd(keptScaledIneqs)
    rts = g.roots(multiplicities=False)
    for r in rts:
        #Recursively try to lift each root
        r_initial = QQ(r)
        newInput = P([r_initial, p])
        LG = [F(newInput) for F in LF]
        lift, lifted = blift(LG, Li, p, S=S)
        if lift:
            #Lift successful.
            return True, r_initial + p * lifted
    #Lift non successful.
    return False, 0
Esempio n. 37
0
    def primitive(self, signed=True):
        """
        Return hyperplane defined by primitive equation.

        INPUT:

        - ``signed`` -- boolean (optional, default: ``True``); whether
          to preserve the overall sign

        OUTPUT:

        Hyperplane whose linear expression has common factors and
        denominators cleared. That is, the same hyperplane (with the
        same sign) but defined by a rescaled equation. Note that
        different linear expressions must define different hyperplanes
        as comparison is used in caching.

        If ``signed``, the overall rescaling is by a positive constant
        only.

        EXAMPLES::

            sage: H.<x,y> = HyperplaneArrangements(QQ)
            sage: h = -1/3*x + 1/2*y - 1;  h
            Hyperplane -1/3*x + 1/2*y - 1
            sage: h.primitive()
            Hyperplane -2*x + 3*y - 6
            sage: h == h.primitive()
            False
            sage: (4*x + 8).primitive()
            Hyperplane x + 0*y + 2

            sage: (4*x - y - 8).primitive(signed=True)   # default
            Hyperplane 4*x - y - 8
            sage: (4*x - y - 8).primitive(signed=False)
            Hyperplane -4*x + y + 8
        """
        from sage.arith.all import lcm, gcd

        coeffs = self.coefficients()
        try:
            d = lcm([x.denom() for x in coeffs])
            n = gcd([x.numer() for x in coeffs])
        except AttributeError:
            return self
        if not signed:
            for x in coeffs:
                if x > 0:
                    break
                if x < 0:
                    d = -d
                    break
        parent = self.parent()
        d = parent.base_ring()(d)
        n = parent.base_ring()(n)
        if n == 0:
            n = parent.base_ring().one()
        return parent(self * d / n)
Esempio n. 38
0
def blift(LF, Li, p, S=None):
    r"""
    Search for a solution to the given list of inequalities.

    If found, lift the solution to
    an appropriate valuation. See Lemma 3.3.6 in [Molnar]_

    INPUT:

    - ``LF`` -- a list of integer polynomials in one variable (the normalized coefficients).

    - ``Li`` -- an integer, the bound on coefficients.

    - ``p`` -- a prime.

    OUTPUT:

    - Boolean -- whether or not the lift is successful.

    - integer -- the lift.

    EXAMPLES::

        sage: R.<b> = PolynomialRing(QQ)
        sage: from sage.schemes.projective.endPN_minimal_model import blift
        sage: blift([8*b^3 + 12*b^2 + 6*b + 1, 48*b^2 + 483*b + 117, 72*b + 1341, -24*b^2 + 411*b + 99, -144*b + 1233, -216*b], 2, 3)
        (True, 4)
    """

    P = LF[0].parent()
    #Determine which inequalities are trivial, and scale the rest, so that we only lift
    #as many times as needed.
    keepScaledIneqs = [scale(P(coeff),Li,p) for coeff in LF if coeff != 0]
    keptVals = [i[2] for i in keepScaledIneqs if i[0]]
    if keptVals != []:
        #Determine the valuation to lift until.
        liftval = max(keptVals)
    else:
        #All inequalities are satisfied.
        return True,1
    if S is None:
        S = PolynomialRing(Zmod(p),'b')
    keptScaledIneqs = [S(i[1]) for i in keepScaledIneqs if i[0]]
    #We need a solution for each polynomial on the left hand side of the inequalities,
    #so we need only find a solution for their gcd.
    g = gcd(keptScaledIneqs)
    rts = g.roots(multiplicities = False)
    for r in rts:
        #Recursively try to lift each root
        r_initial = QQ(r)
        newInput = P([r_initial, p])
        LG = [F(newInput) for F in LF]
        lift,lifted = blift(LG,Li,p,S=S)
        if lift:
            #Lift successful.
            return True,r_initial + p*lifted
    #Lift non successful.
    return False,0
                def rational_catalan_number(self, p, polynomial=False):
                    r"""
                    Return the ``p``-th rational Catalan number
                    associated to ``self``.

                    It is defined by

                    .. MATH::

                        \prod_{i = 1}^n \frac{p + (p(d_i-1)) \mod h)}{d_i},

                    where `d_1, \ldots, d_n` are the degrees and
                    `h` is the Coxeter number. See [STW2016]_
                    for this formula.

                    INPUT:

                    - ``polynomial`` -- optional boolean (default ``False``)
                      if ``True``, return instead the `q`-analogue as a
                      polynomial in `q`

                    REFERENCES:

                    .. [STW2016] C. Stump, H. Thomas, N. Williams.
                       *Cataland II*, in preparation, 2016.

                    EXAMPLES::

                        sage: W = ColoredPermutations(1,3)
                        sage: [W.rational_catalan_number(p) for p in [5,7,8]]
                        [7, 12, 15]

                        sage: W = ColoredPermutations(2,2)
                        sage: [W.rational_catalan_number(p) for p in [7,9,11]]
                        [10, 15, 21]

                    TESTS::

                        sage: W = ColoredPermutations(1,4)
                        sage: W.rational_catalan_number(3, polynomial=True)
                        q^6 + q^4 + q^3 + q^2 + 1
                    """
                    from sage.arith.all import gcd
                    from sage.combinat.q_analogues import q_int

                    h = self.coxeter_number()
                    if not gcd(h,p) == 1:
                        raise ValueError("parameter p = %s is not coprime to the Coxeter number %s" % (p, h))

                    if polynomial:
                        f = q_int
                    else:
                        f = lambda n: n

                    num = prod(f(p + (p * (deg - 1)) % h)
                               for deg in self.degrees())
                    den = prod(f(deg) for deg in self.degrees())
                    return num // den
Esempio n. 40
0
    def primitive(self, signed=True):
        """
        Return hyperplane defined by primitive equation.

        INPUT:

        - ``signed`` -- boolean (optional, default: ``True``); whether
          to preserve the overall sign

        OUTPUT:

        Hyperplane whose linear expression has common factors and
        denominators cleared. That is, the same hyperplane (with the
        same sign) but defined by a rescaled equation. Note that
        different linear expressions must define different hyperplanes
        as comparison is used in caching.

        If ``signed``, the overall rescaling is by a positive constant
        only.

        EXAMPLES::

            sage: H.<x,y> = HyperplaneArrangements(QQ)
            sage: h = -1/3*x + 1/2*y - 1;  h
            Hyperplane -1/3*x + 1/2*y - 1
            sage: h.primitive()
            Hyperplane -2*x + 3*y - 6
            sage: h == h.primitive()
            False
            sage: (4*x + 8).primitive()
            Hyperplane x + 0*y + 2

            sage: (4*x - y - 8).primitive(signed=True)   # default
            Hyperplane 4*x - y - 8
            sage: (4*x - y - 8).primitive(signed=False)
            Hyperplane -4*x + y + 8
        """
        from sage.arith.all import lcm, gcd
        coeffs = self.coefficients()
        try:
            d = lcm([x.denom() for x in coeffs])
            n = gcd([x.numer() for x in coeffs])
        except AttributeError:
            return self
        if not signed:
            for x in coeffs:
                if x > 0:
                    break
                if x < 0:
                    d = -d
                    break
        parent = self.parent()
        d = parent.base_ring()(d)
        n = parent.base_ring()(n)
        if n == 0:
            n = parent.base_ring().one()
        return parent(self * d / n)
Esempio n. 41
0
 def arith_prod_of_partitions(l1, l2):
     # Given two partitions `l_1` and `l_2`, we construct a new partition `l_1 \\boxtimes l_2` by
     # the following procedure: each pair of parts `a \\in l_1` and `b \\in l_2` contributes
     # `\\gcd (a, b)`` parts of size `\\lcm (a, b)` to `l_1 \\boxtimes l_2`. If `l_1` and `l_2`
     # are partitions of integers `n` and `m`, respectively, then `l_1 \\boxtimes l_2` is a
     # partition of `nm`.
     term_iterable = chain.from_iterable(repeat(lcm(pair), gcd(pair))
                                         for pair in product(l1, l2))
     return Partition(sorted(term_iterable, reverse=True))
Esempio n. 42
0
 def arith_prod_of_partitions(l1, l2):
     # Given two partitions `l_1` and `l_2`, we construct a new partition `l_1 \\boxtimes l_2` by
     # the following procedure: each pair of parts `a \\in l_1` and `b \\in l_2` contributes
     # `\\gcd (a, b)`` parts of size `\\lcm (a, b)` to `l_1 \\boxtimes l_2`. If `l_1` and `l_2`
     # are partitions of integers `n` and `m`, respectively, then `l_1 \\boxtimes l_2` is a
     # partition of `nm`.
     term_iterable = chain.from_iterable(repeat(lcm(pair), gcd(pair))
                                         for pair in product(l1, l2))
     return Partition(sorted(term_iterable, reverse=True))
 def __contains__(self, f) :
     if self.__disc is infinity :
         return True
     
     (a, b, c) = f
     disc = 4*a*c - b**2
     if disc == 0 :
         return gcd([a, b, c]) < self._indefinite_content_bound()
     else :
         return disc < self.__disc
Esempio n. 44
0
    def __contains__(self, f):
        if self.__disc is infinity:
            return True

        (a, b, c) = f
        disc = 4 * a * c - b**2
        if disc == 0:
            return gcd([a, b, c]) < self._indefinite_content_bound()
        else:
            return disc < self.__disc
Esempio n. 45
0
def cusps_of_gamma0(N):
    r"""
    INPUT:
     - N, an int
    OUTPUT:
     - list of representatives of cusps of Gamma0(N) given in Corollary 6.3.23 of [Cohen-Stromberg]. In particular they are of the form  a/b with b|N, b>0 and (a,N) = 1
    """
    cusps = []
    for b in divisors(N):
        for a0 in range(gcd(b, N / b)):
            if gcd([a0, b, N / b]) == 1:
                a = a0
                while True:
                    if gcd(a, N) == 1:
                        cusps.append(QQ(a) / QQ(b))
                        break
                    else:
                        a += gcd(b, N / b)
    return cusps
Esempio n. 46
0
def cone_triangulate(C, hyperplane=None):
    r"""
    Triangulation of rational cone contained in the positive quadrant.

    EXAMPLES::

        sage: from surface_dynamics.misc.linalg import cone_triangulate
        sage: P = Polyhedron(rays=[(1,0,0),(0,1,0),(1,0,1),(0,1,1)])
        sage: list(cone_triangulate(P)) # random
        [[(0, 1, 1), (0, 1, 0), (1, 0, 0)], [(0, 1, 1), (1, 0, 1), (1, 0, 0)]]
        sage: len(_)
        2

        sage: rays = [(0, 1, 0, -1, 0, 0),
        ....: (1, 0, -1, 0, 0, -1),
        ....: (0, 1, -1, 0, 0, -1),
        ....: (0, 0, 1, 0, 0, 0),
        ....: (0, 0, 0, 1, 0, -1),
        ....: (1, -1, 0, 0, 1, -1),
        ....: (0, 0, 0, 0, 1, -1),
        ....: (0, 0, 1, -1, 1, 0),
        ....: (0, 0, 1, -1, 0, 0),
        ....: (0, 0, 1, 0, -1, 0),
        ....: (0, 0, 0, 1, -1, -1),
        ....: (1, -1, 0, 0, 0, -1),
        ....: (0, 0, 0, 0, 0, -1)]
        sage: P = Polyhedron(rays=rays)
        sage: list(cone_triangulate(P, hyperplane=(1, 2, 3, -1, 0, -5))) # random
        [[(0, 0, 0, 0, 0, -1),
          (0, 0, 0, 0, 1, -1),
          (0, 0, 0, 1, -1, -1),
          (0, 0, 1, 0, 0, 0),
          (0, 1, -1, 0, 0, -1),
          (1, -1, 0, 0, 1, -1)],
          ...
          (0, 0, 1, 0, 0, 0),
          (0, 1, -1, 0, 0, -1),
          (0, 1, 0, -1, 0, 0),
          (1, -1, 0, 0, 1, -1),
          (1, 0, -1, 0, 0, -1)]]
        sage: len(_)
        16
    """
    rays = [r.vector() for r in C.rays()]
    dim = len(rays[0])
    if hyperplane is None:
        hyperplane = [1] * dim
    scalings = [sum(x * h for x, h in zip(r, hyperplane)) for r in rays]
    assert all(s > 0 for s in scalings)
    normalized_rays = [r / s for r, s in zip(rays, scalings)]
    P = Polyhedron(vertices=normalized_rays)
    for t in P.triangulate():
        simplex = [P.Vrepresentation(i).vector() for i in t]
        yield [(r / gcd(r)).change_ring(ZZ) for r in simplex]
Esempio n. 47
0
    def _find_cusps(self):
        r"""
        Return an ordered list of inequivalent cusps for self, i.e. a
        set of representatives for the orbits of self on
        `\mathbb{P}^1(\QQ)`.  These are returned in a reduced
        form; see self.reduce_cusp for the definition of reduced.

        ALGORITHM:
            Uses explicit formulae specific to `\Gamma_0(N)`: a reduced cusp on
            `\Gamma_0(N)` is always of the form `a/d` where `d | N`, and `a_1/d
            \sim a_2/d` if and only if `a_1 \cong a_2 \bmod {\rm gcd}(d,
            N/d)`.

        EXAMPLES::

            sage: Gamma0(90)._find_cusps()
            [0, 1/45, 1/30, 1/18, 1/15, 1/10, 1/9, 2/15, 1/6, 1/5, 1/3, 11/30, 1/2, 2/3, 5/6, Infinity]
            sage: Gamma0(1).cusps()
            [Infinity]
            sage: Gamma0(180).cusps() == Gamma0(180).cusps(algorithm='modsym')
            True
        """
        N = self.level()
        s = []

        for d in arith.divisors(N):
            w = arith.gcd(d, N//d)
            if w == 1:
                if d == 1:
                    s.append(Cusp(1,0))
                elif d == N:
                    s.append(Cusp(0,1))
                else:
                    s.append(Cusp(1,d))
            else:
                for a in xrange(1, w):
                    if arith.gcd(a, w) == 1:
                        while arith.gcd(a, d//w) != 1:
                            a += w
                        s.append(Cusp(a,d))
        return sorted(s)
Esempio n. 48
0
    def _find_cusps(self):
        r"""
        Return an ordered list of inequivalent cusps for self, i.e. a
        set of representatives for the orbits of self on
        `\mathbb{P}^1(\QQ)`.  These are returned in a reduced
        form; see self.reduce_cusp for the definition of reduced.

        ALGORITHM:
            Uses explicit formulae specific to `\Gamma_0(N)`: a reduced cusp on
            `\Gamma_0(N)` is always of the form `a/d` where `d | N`, and `a_1/d
            \sim a_2/d` if and only if `a_1 \cong a_2 \bmod {\rm gcd}(d,
            N/d)`.

        EXAMPLES::

            sage: Gamma0(90)._find_cusps()
            [0, 1/45, 1/30, 1/18, 1/15, 1/10, 1/9, 2/15, 1/6, 1/5, 1/3, 11/30, 1/2, 2/3, 5/6, Infinity]
            sage: Gamma0(1).cusps()
            [Infinity]
            sage: Gamma0(180).cusps() == Gamma0(180).cusps(algorithm='modsym')
            True
        """
        N = self.level()
        s = []

        for d in arith.divisors(N):
            w = arith.gcd(d, N // d)
            if w == 1:
                if d == 1:
                    s.append(Cusp(1, 0))
                elif d == N:
                    s.append(Cusp(0, 1))
                else:
                    s.append(Cusp(1, d))
            else:
                for a in xrange(1, w):
                    if arith.gcd(a, w) == 1:
                        while arith.gcd(a, d // w) != 1:
                            a += w
                        s.append(Cusp(a, d))
        return sorted(s)
Esempio n. 49
0
    def _kohnen_rho(self, t, a):
        dt = (-1)**(t.nrows() // 2) * t.det()
        d = fundamental_discriminant(dt)
        eps = isqrt(dt // d)

        res = 1
        for (p, e) in gcd(a, eps).factor():
            pol = self._kohnen_rho_polynomial(t, p).coefficients()
            if e < len(pol):
                res = res * pol[e]

        return res
Esempio n. 50
0
    def _new_group_from_level(self, level):
        r"""
        Return a new group of the same type (Gamma0, Gamma1, or
        GammaH) as self of the given level. In the case that self is of type
        GammaH, we take the largest H inside `(\ZZ/ \text{level}\ZZ)^\times`
        which maps to H, namely its inverse image under the natural reduction
        map.

        EXAMPLES::

            sage: G = Gamma0(20)
            sage: G._new_group_from_level(4)
            Congruence Subgroup Gamma0(4)
            sage: G._new_group_from_level(40)
            Congruence Subgroup Gamma0(40)

            sage: G = Gamma1(10)
            sage: G._new_group_from_level(6)
            Traceback (most recent call last):
            ...
            ValueError: one level must divide the other

            sage: G = GammaH(50,[7]); G
            Congruence Subgroup Gamma_H(50) with H generated by [7]
            sage: G._new_group_from_level(25)
            Congruence Subgroup Gamma_H(25) with H generated by [7]
            sage: G._new_group_from_level(10)
            Congruence Subgroup Gamma0(10)
            sage: G._new_group_from_level(100)
            Congruence Subgroup Gamma_H(100) with H generated by [7, 57]
        """
        from .congroup_gamma0 import is_Gamma0
        from .congroup_gamma1 import is_Gamma1
        from .congroup_gammaH import is_GammaH
        from .all import Gamma0, Gamma1, GammaH
        N = self.level()
        if (level%N) and (N%level):
            raise ValueError("one level must divide the other")
        if is_Gamma0(self):
            return Gamma0(level)
        elif is_Gamma1(self):
            return Gamma1(level)
        elif is_GammaH(self):
            H = self._generators_for_H()
            if level > N:
                d = level // N
                diffs = [ N*i for i in range(d) ]
                newH = [ h + diff for h in H for diff in diffs ]
                return GammaH(level, [x for x in newH if gcd(level, x) == 1])
            else:
                return GammaH(level, [ h%level for h in H ])
        else:
            raise NotImplementedError
Esempio n. 51
0
 def _kohnen_rho(self, t, a) :
     dt = (-1)**(t.nrows() // 2) * t.det()
     d = fundamental_discriminant(dt)
     eps = isqrt(dt // d)
     
     res = 1
     for (p,e) in gcd(a, eps).factor() :
         pol = self._kohnen_rho_polynomial(t, p).coefficients()
         if e < len(pol) :
             res = res * pol[e]
         
     return res
Esempio n. 52
0
    def _new_group_from_level(self, level):
        r"""
        Return a new group of the same type (Gamma0, Gamma1, or
        GammaH) as self of the given level. In the case that self is of type
        GammaH, we take the largest H inside `(\ZZ/ \text{level}\ZZ)^\times`
        which maps to H, namely its inverse image under the natural reduction
        map.

        EXAMPLES::

            sage: G = Gamma0(20)
            sage: G._new_group_from_level(4)
            Congruence Subgroup Gamma0(4)
            sage: G._new_group_from_level(40)
            Congruence Subgroup Gamma0(40)

            sage: G = Gamma1(10)
            sage: G._new_group_from_level(6)
            Traceback (most recent call last):
            ...
            ValueError: one level must divide the other

            sage: G = GammaH(50,[7]); G
            Congruence Subgroup Gamma_H(50) with H generated by [7]
            sage: G._new_group_from_level(25)
            Congruence Subgroup Gamma_H(25) with H generated by [7]
            sage: G._new_group_from_level(10)
            Congruence Subgroup Gamma0(10)
            sage: G._new_group_from_level(100)
            Congruence Subgroup Gamma_H(100) with H generated by [7, 57]
        """
        from .congroup_gamma0 import is_Gamma0
        from .congroup_gamma1 import is_Gamma1
        from .congroup_gammaH import is_GammaH
        from .all import Gamma0, Gamma1, GammaH
        N = self.level()
        if (level%N) and (N%level):
            raise ValueError("one level must divide the other")
        if is_Gamma0(self):
            return Gamma0(level)
        elif is_Gamma1(self):
            return Gamma1(level)
        elif is_GammaH(self):
            H = self._generators_for_H()
            if level > N:
                d = level // N
                diffs = [ N*i for i in range(d) ]
                newH = [ h + diff for h in H for diff in diffs ]
                return GammaH(level, [x for x in newH if gcd(level, x) == 1])
            else:
                return GammaH(level, [ h%level for h in H ])
        else:
            raise NotImplementedError
Esempio n. 53
0
    def ncusps(self):
        r"""
        Return the number of cusps of this subgroup `\Gamma_0(N)`.

        EXAMPLES::

            sage: [Gamma0(n).ncusps() for n in [1..19]]
            [1, 2, 2, 3, 2, 4, 2, 4, 4, 4, 2, 6, 2, 4, 4, 6, 2, 8, 2]
            sage: [Gamma0(n).ncusps() for n in prime_range(2,100)]
            [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]
        """
        n = self.level()
        return sum([arith.euler_phi(arith.gcd(d,n//d)) for d in n.divisors()])
def basiclemma(self,M):
    """
    Finds a number represented by self and coprime to M.

    EXAMPLES::

        sage: Q = QuadraticForm(ZZ, 2, [2, 1, 3])
        sage: Q.basiclemma(6)
        71

    """
    a=self(self.basiclemmavec(M))
    assert gcd(a,M) == 1
    return a
Esempio n. 55
0
    def _mul_(self, other):
        """
        Multiply this Hecke operator by another element of the same algebra. If
        the other element is of the form `T_m` for some m, we check whether the
        product is equal to `T_{mn}` and return that; if the product is not
        (easily seen to be) of the form `T_{mn}`, then we calculate the product
        of the two matrices and return a Hecke algebra element defined by that.

        EXAMPLES: We create the space of modular symbols of level
        `11` and weight `2`, then compute `T_2`
        and `T_3` on it, along with their composition.

        ::

            sage: M = ModularSymbols(11)
            sage: t2 = M.hecke_operator(2); t3 = M.hecke_operator(3)
            sage: t2*t3 # indirect doctest
            Hecke operator T_6 on Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field
            sage: t3.matrix() * t2.matrix()
            [12  0 -2]
            [ 0  2  0]
            [ 0  0  2]
            sage: (t2*t3).matrix()
            [12  0 -2]
            [ 0  2  0]
            [ 0  0  2]

        When we compute `T_2^5` the result is not (easily seen to
        be) a Hecke operator of the form `T_n`, so it is returned
        as a Hecke module homomorphism defined as a matrix::

            sage: t2**5
            Hecke operator on Modular Symbols space of dimension 3 for Gamma_0(11) of weight 2 with sign 0 over Rational Field defined by:
            [243   0 -55]
            [  0 -32   0]
            [  0   0 -32]
        """
        if isinstance(other, HeckeOperator) and other.parent() == self.parent():
            n = None
            if arith.gcd(self.__n, other.__n) == 1:
                n = self.__n * other.__n
            else:
                P = set(arith.prime_divisors(self.domain().level()))
                if P.issubset(set(arith.prime_divisors(self.__n))) and \
                   P.issubset(set(arith.prime_divisors(other.__n))):
                    n = self.__n * other.__n
            if n:
                return HeckeOperator(self.parent(), n)
        # otherwise
        return self.matrix_form() * other
Esempio n. 56
0
    def cardinality(self):
        r"""
        Return the number of integer necklaces with the evaluation ``content``.

        The formula for the number of necklaces of content `\alpha`
        a composition of `n` is:

        .. MATH::

            \sum_{d|gcd(\alpha)} \phi(d)
            \binom{n/d}{\alpha_1/d, \ldots, \alpha_\ell/d},

        where `\phi(d)` is the Euler `\phi` function.

        EXAMPLES::

            sage: Necklaces([]).cardinality()
            0
            sage: Necklaces([2,2]).cardinality()
            2
            sage: Necklaces([2,3,2]).cardinality()
            30
            sage: Necklaces([0,3,2]).cardinality()
            2

        Check to make sure that the count matches up with the number of
        necklace words generated.

        ::

            sage: comps = [[],[2,2],[3,2,7],[4,2],[0,4,2],[2,0,4]]+Compositions(4).list()
            sage: ns = [Necklaces(comp) for comp in comps]
            sage: all(n.cardinality() == len(n.list()) for n in ns)
            True
        """
        evaluation = self._content
        le = list(evaluation)
        if not le:
            return ZZ.zero()

        n = sum(le)

        return ZZ.sum(euler_phi(j) * factorial(n // j) //
                      prod(factorial(ni // j) for ni in evaluation)
                      for j in divisors(gcd(le))) // n
 def reduce(self, t) :
     ## We compute the rational diagonal form of t. Whenever a zero entry occures we
     ## find a primitive isotropic vector and apply a base change, such that t finally
     ## has the form diag(0,0,...,P) where P is positive definite. P will then be a
     ## LLL reduced.
     
     ot = t
     t = matrix(QQ, t)
     n = t.nrows()
     u = identity_matrix(QQ, n)
     
     for i in xrange(n) :
         if t[i,i] < 0 :
             return None
         elif t[i,i] == 0 :
             ## get the isotropic vector
             v = u.column(i)
             v = v.denominator() * v
             v = v / gcd(list(v))
             u = self._gln_lift(v, 0)
             
             t = u.transpose() * ot * u
             ts = self.reduce(t.submatrix(1,1,n-1,n-1))
             if ts is None :
                 return None
             t.set_block(1, 1, ts[0])
             
             t.set_immutable()
             
             return (t,1)
         else :
             for j in xrange(i + 1, n) :
                 us = identity_matrix(QQ, n, n)
                 us[i,j] = -t[i,j]/t[i,i]
                 u = u * us
                  
                 t.add_multiple_of_row(j, i, -t[j,i]/t[i,i])
                 t.add_multiple_of_column(j, i, -t[i,j]/t[i,i])
     
     u = ot.LLL_gram()
     t = u.transpose() * ot * u
     t.set_immutable()
     
     return (t, 1)
Esempio n. 58
0
    def hecke_operator(self, n):
        """
        Return the `n`-th Hecke operator, for `n` any
        positive integer coprime to the level.

        EXAMPLES::

            sage: T = ModularSymbols(Gamma1(5),3).anemic_hecke_algebra()
            sage: T.hecke_operator(2)
            Hecke operator T_2 on Modular Symbols space of dimension 4 for Gamma_1(5) of weight 3 with sign 0 and over Rational Field
            sage: T.hecke_operator(5)
            Traceback (most recent call last):
            ...
            IndexError: Hecke operator T_5 not defined in the anemic Hecke algebra
        """
        n = int(n)
        if arith.gcd(self.module().level(), n) != 1:
            raise IndexError("Hecke operator T_%s not defined in the anemic Hecke algebra"%n)
        return self.module()._hecke_operator_class()(self, n)