def enumerate_hypergeometric_data(d, weight=None):
    r"""
    Return an iterator over parameters of hypergeometric motives (up to swapping).

    INPUT:

    - ``d`` -- the degree

    - ``weight`` -- optional integer, to specify the motivic weight

    EXAMPLES::

        sage: from sage.modular.hypergeometric_motive import enumerate_hypergeometric_data as enum
        sage: l = [H for H in enum(6, weight=2) if H.hodge_numbers()[0] == 1]
        sage: len(l)
        112
    """
    bound = 2 * d * d  # to make sure that phi(n) <= d
    possible = [(i, euler_phi(i)) for i in range(1, bound + 1)
                if euler_phi(i) <= d]
    poids = [z[1] for z in possible]
    N = len(poids)
    vectors = WeightedIntegerVectors(d, poids)

    def formule(u):
        return [possible[j][0] for j in range(N) for _ in range(u[j])]

    for a,b in combinations(vectors, 2):
        if not any(a[j] and b[j] for j in range(N)):
            H = HypergeometricData(cyclotomic=(formule(a), formule(b)))
            if weight is None or H.weight() == weight:
                yield H
Esempio n. 2
0
def enumerate_hypergeometric_data(d, weight=None):
    r"""
    Return an iterator over parameters of hypergeometric motives (up to swapping).

    INPUT:

    - ``d`` -- the degree

    - ``weight`` -- optional integer, to specify the motivic weight

    EXAMPLES::

        sage: from sage.modular.hypergeometric_motive import enumerate_hypergeometric_data as enum
        sage: l = [H for H in enum(6, weight=2) if H.hodge_numbers()[0] == 1]
        sage: len(l)
        112
    """
    bound = 2 * d * d  # to make sure that phi(n) <= d
    possible = [(i, euler_phi(i)) for i in range(1, bound + 1)
                if euler_phi(i) <= d]
    poids = [z[1] for z in possible]
    N = len(poids)
    vectors = WeightedIntegerVectors(d, poids)

    def formule(u):
        return [possible[j][0] for j in range(N) for _ in range(u[j])]

    for a, b in combinations(vectors, 2):
        if not any(a[j] and b[j] for j in range(N)):
            H = HypergeometricData(cyclotomic=(formule(a), formule(b)))
            if weight is None or H.weight() == weight:
                yield H
Esempio n. 3
0
 def _denominator():
     R = PolynomialRing(ZZ, "T")
     T = R.gen()
     denom = R(1)
     lc = self._f.list()[-1]
     if lc == 1:  # MONIC
         for i in range(2, self._delta + 1):
             if self._delta % i == 0:
                 phi = euler_phi(i)
                 G = IntegerModRing(i)
                 ki = G(self._q).multiplicative_order()
                 denom = denom * (T**ki - 1)**(phi // ki)
         return denom
     else:  # Non-monic
         x = PolynomialRing(self._Fq, "x").gen()
         f = x**self._delta - lc
         L = f.splitting_field("a")
         roots = [r for r, _ in f.change_ring(L).roots()]
         roots_dict = dict([(r, i) for i, r in enumerate(roots)])
         rootsfrob = [
             L.frobenius_endomorphism(self._Fq.degree())(r)
             for r in roots
         ]
         m = zero_matrix(len(roots))
         for i, r in enumerate(roots):
             m[i, roots_dict[rootsfrob[i]]] = 1
     return R(R(m.characteristic_polynomial()) // (T - 1))
Esempio n. 4
0
def num_cusps_of_width(N, d) -> Integer:
    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: from sage.modular.etaproducts import num_cusps_of_width
        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:
        raise ValueError("N and d must be positive integers with d|N")

    return euler_phi(d.gcd(N // d))
Esempio n. 5
0
def p072():
    # We want to find all rational numbers between 0 and 1 with a
    # denominator of at most 1,000,000.
    # As the d denominator increases, the new rational numbers counted
    # will be equal in number to the integers coprime to d.
    # So, euler phi function.
    return sum(euler_phi(d) for d in range(2, 1_000_001))
Esempio n. 6
0
def p073():
    # We want the rational numbers with denominators of at most 12000
    # between 1/3 and 1/2.
    # One approaches is to count the ones up to 1/2, then count the
    # ones up to 1/3, then subtract.
    # Due to symmetry, the rationals less than 1/2 will be half of those
    # counted by euler_phi - 1.
    # For the ones less than 1/3, I can brute force it.
    # There's theory behind this called Farey sequences, but brute
    # forcing is quicker than reading it.
    less_than_half = (sum(euler_phi(d) for d in range(2, 12001)) - 1) / 2
    rationals = set()
    for d in range(2, 12001):
        for n in range(1, d):
            if n / d > 1 / 3:
                break
            rationals.add(n / d)  # sage will treat this like a fraction
    less_than_third = len(rationals)
    return less_than_half - less_than_third
Esempio n. 7
0
    def __init__(self, cyclotomic=None, alpha_beta=None, gamma_list=None):
        r"""
        Creation of hypergeometric motives.

        INPUT:

        three possibilities are offered, each describing a quotient
        of products of cyclotomic polynomials.

        - ``cyclotomic`` -- a pair of lists of nonnegative integers,
          each integer `k` represents a cyclotomic polynomial `\Phi_k`

        - ``alpha_beta`` -- a pair of lists of rationals,
          each rational represents a root of unity

        - ``gamma_list`` -- a pair of lists of nonnegative integers,
          each integer `n` represents a polynomial `x^n - 1`

        In the last case, it is also allowed to send just one list of signed
        integers where signs indicate to which part the integer belongs to.

        EXAMPLES::

            sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
            sage: Hyp(cyclotomic=([2],[1]))
            Hypergeometric data for [1/2] and [0]

            sage: Hyp(alpha_beta=([1/2],[0]))
            Hypergeometric data for [1/2] and [0]
            sage: Hyp(alpha_beta=([1/5,2/5,3/5,4/5],[0,0,0,0]))
            Hypergeometric data for [1/5, 2/5, 3/5, 4/5] and [0, 0, 0, 0]

            sage: Hyp(gamma_list=([5],[1,1,1,1,1]))
            Hypergeometric data for [1/5, 2/5, 3/5, 4/5] and [0, 0, 0, 0]
            sage: Hyp(gamma_list=([5,-1,-1,-1,-1,-1]))
            Hypergeometric data for [1/5, 2/5, 3/5, 4/5] and [0, 0, 0, 0]
        """
        if gamma_list is not None:
            if isinstance(gamma_list[0], (list, tuple)):
                pos, neg = gamma_list
                gamma_list = pos + [-u for u in neg]
            cyclotomic = gamma_list_to_cyclotomic(gamma_list)
        if cyclotomic is not None:
            cyclo_up, cyclo_down = cyclotomic
            if any(x in cyclo_up for x in cyclo_down):
                raise ValueError('overlapping parameters not allowed')
            deg = sum(euler_phi(x) for x in cyclo_down)
            up_deg = sum(euler_phi(x) for x in cyclo_up)
            if up_deg != deg:
                msg = 'not the same degree: {} != {}'.format(up_deg, deg)
                raise ValueError(msg)
            cyclo_up.sort()
            cyclo_down.sort()
            alpha = cyclotomic_to_alpha(cyclo_up)
            beta = cyclotomic_to_alpha(cyclo_down)
        elif alpha_beta is not None:
            alpha, beta = alpha_beta
            if len(alpha) != len(beta):
                raise ValueError('alpha and beta not of the same length')
            alpha = sorted(u - floor(u) for u in alpha)
            beta = sorted(u - floor(u) for u in beta)
            cyclo_up = alpha_to_cyclotomic(alpha)
            cyclo_down = alpha_to_cyclotomic(beta)
            deg = sum(euler_phi(x) for x in cyclo_down)

        self._cyclo_up = tuple(cyclo_up)
        self._cyclo_down = tuple(cyclo_down)
        self._alpha = tuple(alpha)
        self._beta = tuple(beta)
        self._deg = deg
        self._gamma_array = cyclotomic_to_gamma(cyclo_up, cyclo_down)
        self._trace_coeffs = {}
        up = QQ.prod(capital_M(d) for d in cyclo_up)
        down = QQ.prod(capital_M(d) for d in cyclo_down)
        self._M_value = up / down
        if 0 in alpha:
            self._swap = HypergeometricData(alpha_beta=(beta, alpha))
        if self.weight() % 2:
            self._sign_param = 1
        else:
            if (deg % 2) != (0 in alpha):
                self._sign_param = prod(cyclotomic_polynomial(v).disc()
                                        for v in cyclo_down)
            else:
                self._sign_param = prod(cyclotomic_polynomial(v).disc()
                                        for v in cyclo_up)
    def __init__(self, cyclotomic=None, alpha_beta=None, gamma_list=None):
        r"""
        Creation of hypergeometric motives.

        INPUT:

        three possibilities are offered, each describing a quotient
        of products of cyclotomic polynomials.

        - ``cyclotomic`` -- a pair of lists of nonnegative integers,
          each integer `k` represents a cyclotomic polynomial `\Phi_k`

        - ``alpha_beta`` -- a pair of lists of rationals,
          each rational represents a root of unity

        - ``gamma_list`` -- a pair of lists of nonnegative integers,
          each integer `n` represents a polynomial `x^n - 1`

        In the last case, it is also allowed to send just one list of signed
        integers where signs indicate to which part the integer belongs to.

        EXAMPLES::

            sage: from sage.modular.hypergeometric_motive import HypergeometricData as Hyp
            sage: Hyp(cyclotomic=([2],[1]))
            Hypergeometric data for [1/2] and [0]

            sage: Hyp(alpha_beta=([1/2],[0]))
            Hypergeometric data for [1/2] and [0]
            sage: Hyp(alpha_beta=([1/5,2/5,3/5,4/5],[0,0,0,0]))
            Hypergeometric data for [1/5, 2/5, 3/5, 4/5] and [0, 0, 0, 0]

            sage: Hyp(gamma_list=([5],[1,1,1,1,1]))
            Hypergeometric data for [1/5, 2/5, 3/5, 4/5] and [0, 0, 0, 0]
            sage: Hyp(gamma_list=([5,-1,-1,-1,-1,-1]))
            Hypergeometric data for [1/5, 2/5, 3/5, 4/5] and [0, 0, 0, 0]
        """
        if gamma_list is not None:
            if isinstance(gamma_list[0], (list, tuple)):
                pos, neg = gamma_list
                gamma_list = pos + [-u for u in neg]
            cyclotomic = gamma_list_to_cyclotomic(gamma_list)
        if cyclotomic is not None:
            cyclo_up, cyclo_down = cyclotomic
            if any(x in cyclo_up for x in cyclo_down):
                raise ValueError('overlapping parameters not allowed')
            deg = sum(euler_phi(x) for x in cyclo_down)
            up_deg = sum(euler_phi(x) for x in cyclo_up)
            if up_deg != deg:
                msg = 'not the same degree: {} != {}'.format(up_deg, deg)
                raise ValueError(msg)
            cyclo_up.sort()
            cyclo_down.sort()
            alpha = cyclotomic_to_alpha(cyclo_up)
            beta = cyclotomic_to_alpha(cyclo_down)
        elif alpha_beta is not None:
            alpha, beta = alpha_beta
            if len(alpha) != len(beta):
                raise ValueError('alpha and beta not of the same length')
            alpha = sorted(u - floor(u) for u in alpha)
            beta = sorted(u - floor(u) for u in beta)
            cyclo_up = alpha_to_cyclotomic(alpha)
            cyclo_down = alpha_to_cyclotomic(beta)
            deg = sum(euler_phi(x) for x in cyclo_down)

        self._cyclo_up = cyclo_up
        self._cyclo_down = cyclo_down
        self._alpha = alpha
        self._beta = beta
        self._deg = deg
        if self.weight() % 2:
            self._sign_param = 1
        else:
            if deg % 2:
                self._sign_param = prod(cyclotomic_polynomial(v).disc()
                                        for v in cyclo_down)
            else:
                self._sign_param = prod(cyclotomic_polynomial(v).disc()
                                        for v in cyclo_up)