Exemple #1
0
    def generate_isogenies(self):
        if self._inseparable_degree != 1:

            current_curve = self._separable_domain_extended
            current_kernel = self._separable_kernel
        else:

            current_curve = self.extended_curve()
            current_kernel = self._kernel

        degree_factors = list(factor(self._degree))

        primes = [i[0] for i in degree_factors for _ in range(i[1])]
        isogenies = list()
        for l in primes:

            isogeny = prime_isogeny(current_curve, current_kernel, l)

            if isinstance(isogeny, tuple):
                current_curve = isogeny[0]
                current_kernel = map_points(isogeny, current_kernel)
            else:
                current_curve = isogeny.codomain()
                current_kernel = map_points(isogeny, current_kernel)
            isogenies.append(isogeny)
        self._isogeny_factors = isogenies
Exemple #2
0
    def prime_candidates(self):
        r"""
        Determine those primes `p` where `\mu_B` might not be a
        `(p)`-minimal polynomial.

        OUTPUT:

        A list of primes.

        EXAMPLES::

            sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials
            sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])
            sage: C = ComputeMinimalPolynomials(B)
            sage: C.prime_candidates()
            [2, 3, 5]
            sage: C.p_minimal_polynomials(2)
            {2: x^2 + 3*x + 2}
            sage: C.p_minimal_polynomials(3)
            {}
            sage: C.p_minimal_polynomials(5)
            {}

        This means that `3` and `5` were candidates, but actually, `\mu_B` turns
        out to be a `(3)`-minimal polynomial and a `(5)`-minimal polynomial.
        """
        from sage.arith.misc import factor

        F, T = self._B.frobenius(2)

        return [p for (p, t) in factor(T.det())]
Exemple #3
0
    def prime_candidates(self):
        r"""
        Determine those primes `p` where `\mu_B` might not be a
        `(p)`-minimal polynomial.

        OUTPUT:

        A list of primes.

        EXAMPLES::

            sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials
            sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])
            sage: C = ComputeMinimalPolynomials(B)
            sage: C.prime_candidates()
            [2, 3, 5]
            sage: C.p_minimal_polynomials(2)
            {2: x^2 + 3*x + 2}
            sage: C.p_minimal_polynomials(3)
            {}
            sage: C.p_minimal_polynomials(5)
            {}

        This means that `3` and `5` were candidates, but actually, `\mu_B` turns
        out to be a `(3)`-minimal polynomial and a `(5)`-minimal polynomial.
        """
        from sage.arith.misc import factor

        F, T = self._B.frobenius(2)

        return [p for (p, t) in factor(T.det())]
 def endomorphism_index(self):
     j = self._j_invariant
     field = j.parent()
     t = self._domain.trace_of_frobenius()
     self._trace = t
     Dv = t**2 - 4 * self._domain.base_field().order()
     D = Dv.squarefree_part()
     v = Dv // D
     if D % 4 != 1:
         v = v // 4
     ls = [(i[0], i[1] // 2) for i in list(factor(v)) if i[1] >= 2]
     u = 1
     for a in ls:
         l = a[0]
         Phi = ClassicalModularPolynomialDatabase()[l]
         dist = len(find_descending_path(j, Phi, l, special=False)) - 1
         ex = a[1] - dist
         u *= l**ex
     self._index = u
 def coefficient(self, m):
     if m <= 0:
         # TODO: we are assuming the form is a cusp form
         return 0
     elif m == 1:
         return 1
     from sage.arith.misc import factor
     fact = factor(m)
     if len(fact) == 1:
         p, j = fact[0]
         a_p = self._apdict[p]
         # prime power
         if j == 1:
             return a_p
         else:
             return (a_p * self.coefficient(p**(j - 1)) -
                     self.character()(p) * p**(self.weight() - 1) *
                     self.coefficient(p**(j - 2)))
     else:
         from sage.misc.all import prod
         return prod(self.coefficient(p**k) for p, k in fact)
Exemple #6
0
def covector_txt(covec, m=0, factor_coeff=False):
    r"""
    Return a txt description of the covector.

    INPUT:

    - ``covec`` -- a dictionary in the format of :meth:`extract_a_solution`
    - ``m`` -- the stopping degree of the factorization of the covector
    - ``factor_coeff`` -- (default:``False``) a boolean; whether to factor the 
      coefficients for the output

    OUTPUT:

    A text string whose rows describe the coefficients of the covector, e.g.

    (12)^{2}(2)(1)^{3}(112):-15

    means that the covector contains a summand `-15\lambda_{12122111112}`.

    The components are given as factored strings with the final term
    having degree as close to `m` as possible. The coefficients are integers.
    """

    rows = []
    for X in covec:
        Xs = X.leading_support()
        if factor_coeff:
            coeff = str(factor(covec[X]))
        else:
            coeff = str(covec[X])
        fstr, final = factorstr_withfinal(Xs, m)
        rows.append(("%s:%s" % (fstr, coeff), final, Xs))
    sortkey = lambda row: (getattr(row[2], '_grade', 1), row[1], row[2])
    sortedrows = [fstr for fstr, final, Xs in sorted(rows, key=sortkey)]

    return "\n".join(sortedrows)
Exemple #7
0
    def null_ideal(self, b=0):
        r"""
        Return the `(b)`-ideal `N_{(b)}(B)=\{f\in D[X] \mid f(B)\in M_n(bD)\}`.

        INPUT:

        - ``b`` -- an element of `D` (default: 0)

        OUTPUT:

        An ideal in `D[X]`.

        EXAMPLES::

            sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials
            sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])
            sage: C = ComputeMinimalPolynomials(B)
            sage: C.null_ideal()
            Principal ideal (x^3 + x^2 - 12*x - 20) of
                Univariate Polynomial Ring in x over Integer Ring
            sage: C.null_ideal(2)
            Ideal (2, x^2 + x) of
                Univariate Polynomial Ring in x over Integer Ring
            sage: C.null_ideal(4)
            Ideal (4, x^2 + 3*x + 2) of
                Univariate Polynomial Ring in x over Integer Ring
            sage: C.null_ideal(8)
            Ideal (8, x^3 + x^2 - 12*x - 20, 2*x^2 + 6*x + 4) of
                Univariate Polynomial Ring in x over Integer Ring
            sage: C.null_ideal(3)
            Ideal (3, x^3 + x^2 - 12*x - 20) of
                Univariate Polynomial Ring in x over Integer Ring
            sage: C.null_ideal(6)
            Ideal (6, 2*x^3 + 2*x^2 - 24*x - 40, 3*x^2 + 3*x) of
                Univariate Polynomial Ring in x over Integer Ring
        """
        from sage.arith.misc import factor

        mu_B_coefficients = []
        generators = []

        if b == 0:
            mu_B_coefficients = [1]
        else:
            for (p, t) in factor(b):
                cofactor = b // p**t
                p_polynomials = self.p_minimal_polynomials(p, t)
                generators += [
                    cofactor * p**(t - s) * nu
                    for s, nu in iteritems(p_polynomials)
                ]
                if not p_polynomials or max(iterkeys(p_polynomials)) < t:
                    mu_B_coefficients.append(cofactor)

            assert all((g(self._B) % b).is_zero() for g in generators), \
                "Polynomials not in %s-ideal" % (b,)

        if mu_B_coefficients:
            (mu_B_coefficient, ) = self._D.ideal(mu_B_coefficients).gens()
            generators = [mu_B_coefficient * self.mu_B] + generators

        if b != 0:
            generators = [self._DX(b)] + generators

        return self._DX.ideal(generators)
Exemple #8
0
def MacMahonOmega(var,
                  expression,
                  denominator=None,
                  op=operator.ge,
                  Factorization_sort=False,
                  Factorization_simplify=True):
    r"""
    Return `\Omega_{\mathrm{op}}` of ``expression`` with respect to ``var``.

    To be more precise, calculate

    .. MATH::

        \Omega_{\mathrm{op}} \frac{n}{d_1 \dots d_n}

    for the numerator `n` and the factors `d_1`, ..., `d_n` of
    the denominator, all of which are Laurent polynomials in ``var``
    and return a (partial) factorization of the result.

    INPUT:

    - ``var`` -- a variable or a representation string of a variable

    - ``expression`` -- a
      :class:`~sage.structure.factorization.Factorization`
      of Laurent polynomials or, if ``denominator`` is specified,
      a Laurent polynomial interpreted as the numerator of the
      expression

    - ``denominator`` -- a Laurent polynomial or a
      :class:`~sage.structure.factorization.Factorization` (consisting
      of Laurent polynomial factors) or a tuple/list of factors (Laurent
      polynomials)

    - ``op`` -- (default: ``operator.ge``) an operator

      At the moment only ``operator.ge`` is implemented.

    - ``Factorization_sort`` (default: ``False``) and
      ``Factorization_simplify`` (default: ``True``) -- are passed on to
      :class:`sage.structure.factorization.Factorization` when creating
      the result

    OUTPUT:

    A (partial) :class:`~sage.structure.factorization.Factorization`
    of the result whose factors are Laurent polynomials

    .. NOTE::

        The numerator of the result may not be factored.

    REFERENCES:

    - [Mac1915]_

    - [APR2001]_

    EXAMPLES::

        sage: L.<mu, x, y, z, w> = LaurentPolynomialRing(ZZ)

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu])
        1 * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu, 1 - z/mu])
        1 * (-x + 1)^-1 * (-x*y + 1)^-1 * (-x*z + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z/mu])
        (-x*y*z + 1) * (-x + 1)^-1 * (-y + 1)^-1 * (-x*z + 1)^-1 * (-y*z + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu^2])
        1 * (-x + 1)^-1 * (-x^2*y + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^2, 1 - y/mu])
        (x*y + 1) * (-x + 1)^-1 * (-x*y^2 + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z/mu^2])
        (-x^2*y*z - x*y^2*z + x*y*z + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 * (-x^2*z + 1)^-1 * (-y^2*z + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu^3])
        1 * (-x + 1)^-1 * (-x^3*y + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu^4])
        1 * (-x + 1)^-1 * (-x^4*y + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^3, 1 - y/mu])
        (x*y^2 + x*y + 1) * (-x + 1)^-1 * (-x*y^3 + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^4, 1 - y/mu])
        (x*y^3 + x*y^2 + x*y + 1) * (-x + 1)^-1 * (-x*y^4 + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu^2, 1 - y/mu, 1 - z/mu])
        (x*y*z + x*y + x*z + 1) *
        (-x + 1)^-1 * (-x*y^2 + 1)^-1 * (-x*z^2 + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^2, 1 - y*mu, 1 - z/mu])
        (-x*y*z^2 - x*y*z + x*z + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 * (-x*z^2 + 1)^-1 * (-y*z + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z*mu, 1 - w/mu])
        (x*y*z*w^2 + x*y*z*w - x*y*w - x*z*w - y*z*w + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 * (-z + 1)^-1 *
        (-x*w + 1)^-1 * (-y*w + 1)^-1 * (-z*w + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z/mu, 1 - w/mu])
        (x^2*y*z*w + x*y^2*z*w - x*y*z*w - x*y*z - x*y*w + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 *
        (-x*z + 1)^-1 * (-x*w + 1)^-1 * (-y*z + 1)^-1 * (-y*w + 1)^-1

        sage: MacMahonOmega(mu, mu^-2, [1 - x*mu, 1 - y/mu])
        x^2 * (-x + 1)^-1 * (-x*y + 1)^-1
        sage: MacMahonOmega(mu, mu^-1, [1 - x*mu, 1 - y/mu])
        x * (-x + 1)^-1 * (-x*y + 1)^-1
        sage: MacMahonOmega(mu, mu, [1 - x*mu, 1 - y/mu])
        (-x*y + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1
        sage: MacMahonOmega(mu, mu^2, [1 - x*mu, 1 - y/mu])
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

    We demonstrate the different allowed input variants::

        sage: MacMahonOmega(mu,
        ....:     Factorization([(mu, 2), (1 - x*mu, -1), (1 - y/mu, -1)]))
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2,
        ....:     Factorization([(1 - x*mu, 1), (1 - y/mu, 1)]))
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2, [1 - x*mu, 1 - y/mu])
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2, (1 - x*mu)*(1 - y/mu))  # not tested because not fully implemented
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2 / ((1 - x*mu)*(1 - y/mu)))  # not tested because not fully implemented
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

    TESTS::

        sage: MacMahonOmega(mu, 1, [1 - x*mu])
        1 * (-x + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x/mu])
        1
        sage: MacMahonOmega(mu, 0, [1 - x*mu])
        0
        sage: MacMahonOmega(mu, L(1), [])
        1
        sage: MacMahonOmega(mu, L(0), [])
        0
        sage: MacMahonOmega(mu, 2, [])
        2
        sage: MacMahonOmega(mu, 2*mu, [])
        2
        sage: MacMahonOmega(mu, 2/mu, [])
        0

    ::

        sage: MacMahonOmega(mu, Factorization([(1/mu, 1), (1 - x*mu, -1),
        ....:                                  (1 - y/mu, -2)], unit=2))
        2*x * (-x + 1)^-1 * (-x*y + 1)^-2
        sage: MacMahonOmega(mu, Factorization([(mu, -1), (1 - x*mu, -1),
        ....:                                  (1 - y/mu, -2)], unit=2))
        2*x * (-x + 1)^-1 * (-x*y + 1)^-2
        sage: MacMahonOmega(mu, Factorization([(mu, -1), (1 - x, -1)]))
        0
        sage: MacMahonOmega(mu, Factorization([(2, -1)]))
        1 * 2^-1

    ::

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - z, 1 - y/mu])
        1 * (-z + 1)^-1 * (-x + 1)^-1 * (-x*y + 1)^-1

    ::

        sage: MacMahonOmega(mu, 1, [1 - x*mu], op=operator.lt)
        Traceback (most recent call last):
        ...
        NotImplementedError: At the moment, only Omega_ge is implemented.

        sage: MacMahonOmega(mu, 1, Factorization([(1 - x*mu, -1)]))
        Traceback (most recent call last):
        ...
        ValueError: Factorization (-mu*x + 1)^-1 of the denominator
        contains negative exponents.

        sage: MacMahonOmega(2*mu, 1, [1 - x*mu])
        Traceback (most recent call last):
        ...
        ValueError: 2*mu is not a variable.

        sage: MacMahonOmega(mu, 1, Factorization([(0, 2)]))
        Traceback (most recent call last):
        ...
        ZeroDivisionError: Denominator contains a factor 0.

        sage: MacMahonOmega(mu, 1, [2 - x*mu])
        Traceback (most recent call last):
        ...
        NotImplementedError: Factor 2 - x*mu is not normalized.

        sage: MacMahonOmega(mu, 1, [1 - x*mu - mu^2])
        Traceback (most recent call last):
        ...
        NotImplementedError: Cannot handle factor 1 - x*mu - mu^2.

    ::

        sage: L.<mu, x, y, z, w> = LaurentPolynomialRing(QQ)
        sage: MacMahonOmega(mu, 1/mu,
        ....:     Factorization([(1 - x*mu, 1), (1 - y/mu, 2)], unit=2))
        1/2*x * (-x + 1)^-1 * (-x*y + 1)^-2
    """
    from sage.arith.misc import factor
    from sage.misc.misc_c import prod
    from sage.rings.integer_ring import ZZ
    from sage.rings.polynomial.laurent_polynomial_ring \
        import LaurentPolynomialRing, LaurentPolynomialRing_univariate
    from sage.structure.factorization import Factorization

    if op != operator.ge:
        raise NotImplementedError(
            'At the moment, only Omega_ge is implemented.')

    if denominator is None:
        if isinstance(expression, Factorization):
            numerator = expression.unit() * \
                        prod(f**e for f, e in expression if e > 0)
            denominator = tuple(f for f, e in expression if e < 0
                                for _ in range(-e))
        else:
            numerator = expression.numerator()
            denominator = expression.denominator()
    else:
        numerator = expression
    # at this point we have numerator/denominator

    if isinstance(denominator, (list, tuple)):
        factors_denominator = denominator
    else:
        if not isinstance(denominator, Factorization):
            denominator = factor(denominator)
        if not denominator.is_integral():
            raise ValueError(
                'Factorization {} of the denominator '
                'contains negative exponents.'.format(denominator))
        numerator *= ZZ(1) / denominator.unit()
        factors_denominator = tuple(factor for factor, exponent in denominator
                                    for _ in range(exponent))
    # at this point we have numerator/factors_denominator

    P = var.parent()
    if isinstance(P, LaurentPolynomialRing_univariate) and P.gen() == var:
        L = P
        L0 = L.base_ring()
    elif var in P.gens():
        var = repr(var)
        L0 = LaurentPolynomialRing(
            P.base_ring(), tuple(v for v in P.variable_names() if v != var))
        L = LaurentPolynomialRing(L0, var)
        var = L.gen()
    else:
        raise ValueError('{} is not a variable.'.format(var))

    other_factors = []
    to_numerator = []
    decoded_factors = []
    for factor in factors_denominator:
        factor = L(factor)
        D = factor.dict()
        if not D:
            raise ZeroDivisionError('Denominator contains a factor 0.')
        elif len(D) == 1:
            exponent, coefficient = next(iteritems(D))
            if exponent == 0:
                other_factors.append(L0(factor))
            else:
                to_numerator.append(factor)
        elif len(D) == 2:
            if D.get(0, 0) != 1:
                raise NotImplementedError(
                    'Factor {} is not normalized.'.format(factor))
            D.pop(0)
            exponent, coefficient = next(iteritems(D))
            decoded_factors.append((-coefficient, exponent))
        else:
            raise NotImplementedError(
                'Cannot handle factor {}.'.format(factor))
    numerator = L(numerator) / prod(to_numerator)

    result_numerator, result_factors_denominator = \
        _Omega_(numerator.dict(), decoded_factors)
    if result_numerator == 0:
        return Factorization([], unit=result_numerator)

    return Factorization([(result_numerator, 1)] + list(
        (f, -1) for f in other_factors) + list(
            (1 - f, -1) for f in result_factors_denominator),
                         sort=Factorization_sort,
                         simplify=Factorization_simplify)
Exemple #9
0
    def null_ideal(self, b=0):
        r"""
        Return the `(b)`-ideal `N_{(b)}(B)=\{f\in D[X] \mid f(B)\in M_n(bD)\}`.

        INPUT:

        - ``b`` -- an element of `D` (default: 0)

        OUTPUT:

        An ideal in `D[X]`.

        EXAMPLES::

            sage: from sage.matrix.compute_J_ideal import ComputeMinimalPolynomials
            sage: B = matrix(ZZ, [[1, 0, 1], [1, -2, -1], [10, 0, 0]])
            sage: C = ComputeMinimalPolynomials(B)
            sage: C.null_ideal()
            Principal ideal (x^3 + x^2 - 12*x - 20) of
                Univariate Polynomial Ring in x over Integer Ring
            sage: C.null_ideal(2)
            Ideal (2, x^2 + x) of
                Univariate Polynomial Ring in x over Integer Ring
            sage: C.null_ideal(4)
            Ideal (4, x^2 + 3*x + 2) of
                Univariate Polynomial Ring in x over Integer Ring
            sage: C.null_ideal(8)
            Ideal (8, x^3 + x^2 - 12*x - 20, 2*x^2 + 6*x + 4) of
                Univariate Polynomial Ring in x over Integer Ring
            sage: C.null_ideal(3)
            Ideal (3, x^3 + x^2 - 12*x - 20) of
                Univariate Polynomial Ring in x over Integer Ring
            sage: C.null_ideal(6)
            Ideal (6, 2*x^3 + 2*x^2 - 24*x - 40, 3*x^2 + 3*x) of
                Univariate Polynomial Ring in x over Integer Ring
        """
        from sage.arith.misc import factor

        mu_B_coefficients = []
        generators = []

        if b == 0:
            mu_B_coefficients = [1]
        else:
            for (p, t) in factor(b):
                cofactor = b // p**t
                p_polynomials = self.p_minimal_polynomials(p, t)
                generators += [cofactor*p**(t-s)*nu
                               for s, nu in iteritems(p_polynomials)]
                if not p_polynomials or max(iterkeys(p_polynomials)) < t:
                    mu_B_coefficients.append(cofactor)

            assert all((g(self._B) % b).is_zero() for g in generators), \
                "Polynomials not in %s-ideal" % (b,)

        if mu_B_coefficients:
            (mu_B_coefficient,) = self._D.ideal(mu_B_coefficients).gens()
            generators = [mu_B_coefficient * self.mu_B] + generators

        if b != 0:
            generators = [self._DX(b)] + generators

        return self._DX.ideal(generators)
Exemple #10
0
def find_monomials(polynomial,
                   poly_degree,
                   r,
                   s,
                   form="list",
                   sort_type="zero",
                   early_finish=True,
                   rolling_output=True,
                   out_file=None):
    """This function finds all monomials that, in relation to the given monomial, fit
	   the criteria of the problem.

	   ***ATTENTION: DESPITE THE VARIABLE DECLARATIONS AT THE BEGINNING OF THE FUNCTION,
	   THIS FUNCTION WILL NOT WORK CORRECTLY IF ALL VARIABLES IN THE INPUT POLYNOMIAL
	   HAVE NOT ALREADY BEEN DECLARED.***

		Args:
		    polynomial(symb exp): The polynomial to which monomials will be matched.
		    poly_degree(int): The degree of the input polynomial.
		    r(int): The r value for the input polynomial.
		    s(int): The s value for the input polynomial.
		    form(str): If form is "list", the function will return a list of monomials.
			       If form is "tup", the function will return a list of tuples with
			       the form: (monomial, coefficient).
		    sort_type(str): If sort_type is "zero", monomials are sorted by distance of
				    the coefficient from zero. If sort type is "value", monomials
				    are sorted by the coefficient's value.
		Returns:
		    monomials(list): Returns either a list of monomials or a list of tuples depending
				     on the value of form. Sorted by value or distance from zero of
				     coefficients depending on the value of sort_type. If there are
				     no working monomials, the function returns an empty list.
	"""

    if out_file != None:
        try:
            file = open(out_file, "w+")
        except:
            out_file = None
            print "File failed to open, printing to stdout..."
            print
    #Double check that variables are declared to prevent errors when forming monomials.
    for num in xrange(1, r + 1):
        var("x" + str(num))
    for num in xrange(1, s + 1):
        var("y" + str(num))

# Declare ring as R
    ringlists = ring_lists(r, s)
    R, ringlists[1] = PolynomialRing(RationalField(), r + s,
                                     ringlists[0]).objgens()

    #Monomials must be checked against the expanded monomial
    # polynomial_expanded = polynomial.expand() #--- This was the old way
    polynomial_expanded = type_change(polynomial, ring=R)
    """This variable will be used to create a monomial "template" with all the essential
	   variables and variables in place of exponent values.
	"""
    test_monomial = create_template_monomial(r, s)
    """This block creates a list of placeholders for x and y variable exponents in the order
	   they appear.
	"""

    list_of_both_powers = create_power_list(r, s)
    """This block finds all possible exponent combinations for x and y variables
	   in a list form, then finds all possible permutations of that list.
	"""

    list_of_power_values = create_power_values(r, s, poly_degree)
    """Now, every list of exponent possibilites is subbed into the monomial template,
	   then checked against the expanded polynomial. If it is present in the expanded
	   form, it is added to the final list.
	"""
    workable_monomials = []
    for power_values in list_of_power_values:
        for power_set in multiset_permutations(power_values):
            temp_test_monomial = test_monomial
            power_set = list(power_set)
            if r > 0 and s > 0:
                testing_list = check_monomial_rs(r, s, power_set,
                                                 temp_test_monomial,
                                                 list_of_both_powers,
                                                 polynomial_expanded, R)
            elif r > 0 and s == 0:
                testing_list = check_monomial_r(r, s, power_set,
                                                temp_test_monomial,
                                                list_of_both_powers,
                                                polynomial_expanded, R)
            elif r == 0 and s > 0:
                testing_list = check_monomial_s(r, s, power_set,
                                                temp_test_monomial,
                                                list_of_both_powers,
                                                polynomial_expanded, R)
            else:
                raise ValueError(
                    "Invalid r and s inputs. r and s may not be bellow zero and may not both be zero"
                )

            if testing_list[0] == 1:
                workable_monomials.append(
                    (testing_list[2] * testing_list[1], int(testing_list[2])))
                if rolling_output == True:
                    if out_file != None:
                        file.write(str(testing_list[2] * testing_list[1]))
                        file.write("\n")
                    else:
                        print testing_list[2] * testing_list[1]
                #The following block tests to see if the function can finish early
                if early_finish == True:
                    fin = 1
                    for fac in list(factor(int(testing_list[2]))):
                        if r + s > 9:
                            prime_range = xrange(-5, 6)
                        else:
                            prime_range = xrange(-3, 4)
                        if fac[0] not in prime_range:
                            fin = 0
                    if fin == 1:
                        if form == "list":
                            for i in xrange(0, len(workable_monomials)):
                                workable_monomials[i] = workable_monomials[i][
                                    0]
                        return workable_monomials

    #Changes output depending on preferences set at the outset.
    if len(workable_monomials) > 0:
        if sort_type == "zero":
            workable_monomials = sorted(workable_monomials,
                                        key=lambda tup: abs(tup[1]))
        else:
            workable_monomials = sorted(workable_monomials,
                                        key=lambda tup: tup[1])

    if form == "list":
        for i in xrange(0, len(workable_monomials)):
            workable_monomials[i] = workable_monomials[i][0]

    return workable_monomials
Exemple #11
0
def darmon_point(P,
                 E,
                 beta,
                 prec,
                 ramification_at_infinity=None,
                 input_data=None,
                 magma=None,
                 working_prec=None,
                 recognize_point=True,
                 **kwargs):
    r'''

    EXAMPLES:

    We first need to import the module::

    sage: from darmonpoints.darmonpoints import darmon_point

    A first example (Stark--Heegner point)::

    sage: from darmonpoints.darmonpoints import darmon_point
    sage: darmon_point(7,EllipticCurve('35a1'),41,20, cohomological=False, use_magma=False, use_ps_dists = True)
    Starting computation of the Darmon point
    ...
    (-70*alpha + 449 : 2100*alpha - 13444 : 1)

    A quaternionic (Greenberg) point::

    sage: darmon_point(13,EllipticCurve('78a1'),5,20) # long time # optional - magma

    A Darmon point over a cubic (1,1) field::

    sage: F.<r> = NumberField(x^3 - x^2 - x + 2)
    sage: E = EllipticCurve([-r -1, -r, -r - 1,-r - 1, 0])
    sage: N = E.conductor()
    sage: P = F.ideal(r^2 - 2*r - 1)
    sage: beta = -3*r^2 + 9*r - 6
    sage: darmon_point(P,E,beta,20) # long time # optional - magma

    '''
    # global G, Coh, phiE, Phi, dK, J, J1, cycleGn, nn, Jlist

    config = ConfigParser.ConfigParser()
    config.read('config.ini')
    param_dict = config_section_map(config, 'General')
    param_dict.update(config_section_map(config, 'DarmonPoint'))
    param_dict.update(kwargs)
    param = Bunch(**param_dict)

    # Get general parameters
    outfile = param.get('outfile')
    use_ps_dists = param.get('use_ps_dists', False)
    use_shapiro = param.get('use_shapiro', False)
    use_sage_db = param.get('use_sage_db', False)
    magma_seed = param.get('magma_seed', 1515316)
    parallelize = param.get('parallelize', False)
    Up_method = param.get('up_method', 'naive')
    use_magma = param.get('use_magma', True)
    progress_bar = param.get('progress_bar', True)
    sign_at_infinity = param.get('sign_at_infinity', ZZ(1))

    # Get darmon_point specific parameters
    idx_orientation = param.get('idx_orientation')
    idx_embedding = param.get('idx_embedding', 0)
    algorithm = param.get('algorithm')
    quaternionic = param.get('quaternionic')
    cohomological = param.get('cohomological', True)

    if Up_method == "bigmatrix" and use_shapiro == True:
        import warnings
        warnings.warn(
            'Use of "bigmatrix" for Up iteration is incompatible with Shapiro Lemma trick. Using "naive" method for Up.'
        )
        Up_method = 'naive'

    if working_prec is None:
        working_prec = max([2 * prec + 10, 30])

    if use_magma:
        page_path = os.path.dirname(__file__) + '/KleinianGroups-1.0/klngpspec'
        if magma is None:
            from sage.interfaces.magma import Magma
            magma = Magma()
            quit_when_done = True
        else:
            quit_when_done = False
        magma.attach_spec(page_path)
    else:
        quit_when_done = False

    sys.setrecursionlimit(10**6)

    F = E.base_ring()
    beta = F(beta)
    DB, Np, Ncartan = get_heegner_params(P, E, beta)
    if quaternionic is None:
        quaternionic = (DB != 1)
    if cohomological is None:
        cohomological = quaternionic
    if quaternionic and not cohomological:
        raise ValueError(
            "Need cohomological algorithm when dealing with quaternions")
    if use_ps_dists is None:
        use_ps_dists = False if cohomological else True
    try:
        p = ZZ(P)
    except TypeError:
        p = ZZ(P.norm())
    if not p.is_prime():
        raise ValueError('P (= %s) should be a prime, of inertia degree 1' % P)

    if F == QQ:
        dK = ZZ(beta)
        extra_conductor_sq = dK / fundamental_discriminant(dK)
        assert ZZ(extra_conductor_sq).is_square()
        extra_conductor = extra_conductor_sq.sqrt()
        dK = dK / extra_conductor_sq
        assert dK == fundamental_discriminant(dK)
        if dK % 4 == 0:
            dK = ZZ(dK / 4)
        beta = dK
    else:
        dK = beta

    # Compute the completion of K at p
    x = QQ['x'].gen()
    K = F.extension(x * x - dK, names='alpha')
    if F == QQ:
        dK = K.discriminant()
    else:
        dK = K.relative_discriminant()

    hK = K.class_number()

    sgninfty = 'plus' if sign_at_infinity == 1 else 'minus'
    if hasattr(E, 'cremona_label'):
        Ename = E.cremona_label()
    elif hasattr(E, 'ainvs'):
        Ename = E.ainvs()
    else:
        Ename = 'unknown'
    fname = 'moments_%s_%s_%s_%s.sobj' % (P, Ename, sgninfty, prec)

    if use_sage_db:
        print("Moments will be stored in database as %s" % (fname))

    if outfile == 'log':
        outfile = '%s_%s_%s_%s_%s_%s.log' % (
            P, Ename, dK, sgninfty, prec,
            datetime.datetime.now().strftime("%Y%m%d-%H%M%S"))
        outfile = outfile.replace('/', 'div')
        outfile = '/tmp/darmonpoint_' + outfile

    fwrite("Starting computation of the Darmon point", outfile)
    fwrite('D_B = %s  %s' % (DB, factor(DB)), outfile)
    fwrite('Np = %s' % Np, outfile)
    if Ncartan is not None:
        fwrite('Ncartan = %s' % Ncartan, outfile)
    fwrite('dK = %s (class number = %s)' % (dK, hK), outfile)
    fwrite('Calculation with p = %s and prec = %s' % (P, prec), outfile)
    fwrite('Elliptic curve %s: %s' % (Ename, E), outfile)
    if outfile is not None:
        print("Partial results will be saved in %s" % outfile)

    if input_data is None:
        if cohomological:
            # Define the S-arithmetic group
            if F != QQ and ramification_at_infinity is None:
                if F.signature()[0] > 1:
                    if F.signature()[1] == 1:
                        ramification_at_infinity = F.real_places(
                            prec=Infinity)  # Totally 'definite'
                    else:
                        raise ValueError(
                            'Please specify the ramification at infinity')
                elif F.signature()[0] == 1:
                    if len(F.ideal(DB).factor()) % 2 == 0:
                        ramification_at_infinity = []  # Split at infinity
                    else:
                        ramification_at_infinity = F.real_places(
                            prec=Infinity)  # Ramified at infinity
                else:
                    ramification_at_infinity = None
            if F == QQ:
                abtuple = QuaternionAlgebra(DB).invariants()
            else:
                abtuple = quaternion_algebra_invariants_from_ramification(
                    F, DB, ramification_at_infinity, magma=magma)

            G = BigArithGroup(P,
                              abtuple,
                              Np,
                              base=F,
                              outfile=outfile,
                              seed=magma_seed,
                              use_sage_db=use_sage_db,
                              magma=magma,
                              use_shapiro=use_shapiro,
                              nscartan=Ncartan)

            # Define the cycle ( in H_1(G,Div^0 Hp) )
            Coh = ArithCoh(G)
            while True:
                try:
                    cycleGn, nn, ell = construct_homology_cycle(
                        p,
                        G.Gn,
                        beta,
                        working_prec,
                        lambda q: Coh.hecke_matrix(q).minpoly(),
                        outfile=outfile,
                        elliptic_curve=E)
                    break
                except PrecisionError:
                    working_prec *= 2
                    verbose(
                        'Encountered precision error, trying with higher precision (= %s)'
                        % working_prec)
                except ValueError:
                    fwrite(
                        'ValueError occurred when constructing homology cycle. Returning the S-arithmetic group.',
                        outfile)
                    if quit_when_done:
                        magma.quit()
                    return G
                except AssertionError as e:
                    fwrite(
                        'Assertion occurred when constructing homology cycle. Returning the S-arithmetic group.',
                        outfile)
                    fwrite('%s' % str(e), outfile)
                    if quit_when_done:
                        magma.quit()
                    return G
            eisenstein_constant = -ZZ(E.reduction(ell).count_points())
            fwrite(
                'r = %s, so a_r(E) - r - 1 = %s' % (ell, eisenstein_constant),
                outfile)
            fwrite('exponent = %s' % nn, outfile)
            phiE = Coh.get_cocycle_from_elliptic_curve(E,
                                                       sign=sign_at_infinity)
            if hasattr(E, 'ap'):
                sign_ap = E.ap(P)
            else:
                try:
                    sign_ap = ZZ(P.norm() + 1 - E.reduction(P).count_points())
                except ValueError:
                    sign_ap = ZZ(P.norm() + 1 - Curve(E).change_ring(
                        P.residue_field()).count_points(1)[0])

            Phi = get_overconvergent_class_quaternionic(
                P,
                phiE,
                G,
                prec,
                sign_at_infinity,
                sign_ap,
                use_ps_dists=use_ps_dists,
                use_sage_db=use_sage_db,
                parallelize=parallelize,
                method=Up_method,
                progress_bar=progress_bar,
                Ename=Ename)
            # Integration with moments
            tot_time = walltime()
            J = integrate_H1(G,
                             cycleGn,
                             Phi,
                             1,
                             method='moments',
                             prec=working_prec,
                             parallelize=parallelize,
                             twist=True,
                             progress_bar=progress_bar)
            verbose('integration tot_time = %s' % walltime(tot_time))
            if use_sage_db:
                G.save_to_db()
        else:  # not cohomological
            nn = 1
            eisenstein_constant = 1
            if algorithm is None:
                if Np == 1:
                    algorithm = 'darmon_pollack'
                else:
                    algorithm = 'guitart_masdeu'
            w = K.maximal_order().ring_generators()[0]
            r0, r1 = w.coordinates_in_terms_of_powers()(K.gen())
            QQp = Qp(p, working_prec)
            Cp = QQp.extension(w.minpoly().change_ring(QQp), names='g')
            v0 = K.hom([r0 + r1 * Cp.gen()])

            # Optimal embeddings of level one
            fwrite("Computing optimal embeddings of level one...", outfile)
            Wlist = find_optimal_embeddings(K,
                                            use_magma=use_magma,
                                            extra_conductor=extra_conductor)
            fwrite("Found %s such embeddings." % len(Wlist), outfile)
            if idx_embedding is not None:
                if idx_embedding >= len(Wlist):
                    fwrite(
                        'There are not enough embeddings. Taking the index modulo %s'
                        % len(Wlist), outfile)
                    idx_embedding = idx_embedding % len(Wlist)
                fwrite('Taking only embedding number %s' % (idx_embedding),
                       outfile)
                Wlist = [Wlist[idx_embedding]]

            # Find the orientations
            orients = K.maximal_order().ring_generators()[0].minpoly().roots(
                Zmod(Np), multiplicities=False)
            fwrite("Possible orientations: %s" % orients, outfile)
            if len(Wlist) == 1 or idx_orientation == -1:
                fwrite("Using all orientations, since hK = 1", outfile)
                chosen_orientation = None
            else:
                fwrite("Using orientation = %s" % orients[idx_orientation],
                       outfile)
                chosen_orientation = orients[idx_orientation]

            emblist = []
            for i, W in enumerate(Wlist):
                tau, gtau, sign, limits = find_tau0_and_gtau(
                    v0,
                    Np,
                    W,
                    algorithm=algorithm,
                    orientation=chosen_orientation,
                    extra_conductor=extra_conductor)
                fwrite(
                    'n_evals = %s' % sum(
                        (num_evals(t1, t2) for t1, t2 in limits)), outfile)
                emblist.append((tau, gtau, sign, limits))

            # Get the cohomology class from E
            Phi = get_overconvergent_class_matrices(P,
                                                    E,
                                                    prec,
                                                    sign_at_infinity,
                                                    use_ps_dists=use_ps_dists,
                                                    use_sage_db=use_sage_db,
                                                    parallelize=parallelize,
                                                    progress_bar=progress_bar)

            J = 1
            Jlist = []
            for i, emb in enumerate(emblist):
                fwrite(
                    "Computing %s-th period, attached to the embedding: %s" %
                    (i, Wlist[i].list()), outfile)
                tau, gtau, sign, limits = emb
                n_evals = sum((num_evals(t1, t2) for t1, t2 in limits))
                fwrite(
                    "Computing one period...(total of %s evaluations)" %
                    n_evals, outfile)
                newJ = prod((double_integral_zero_infty(Phi, t1, t2)
                             for t1, t2 in limits))**ZZ(sign)
                Jlist.append(newJ)
                J *= newJ
    else:  # input_data is not None
        Phi, J = input_data[1:3]
    fwrite('Integral done. Now trying to recognize the point', outfile)
    fwrite('J_psi = %s' % J, outfile)
    fwrite('g belongs to %s' % J.parent(), outfile)
    #Try to recognize a generator
    if quaternionic:
        local_embedding = G.base_ring_local_embedding(working_prec)
        twopowlist = [
            4, 3, 2, 1,
            QQ(1) / 2,
            QQ(3) / 2,
            QQ(1) / 3,
            QQ(2) / 3,
            QQ(1) / 4,
            QQ(3) / 4,
            QQ(5) / 2,
            QQ(4) / 3
        ]
    else:
        local_embedding = Qp(p, working_prec)
        twopowlist = [
            4, 3, 2, 1,
            QQ(1) / 2,
            QQ(3) / 2,
            QQ(1) / 3,
            QQ(2) / 3,
            QQ(1) / 4,
            QQ(3) / 4,
            QQ(5) / 2,
            QQ(4) / 3
        ]

    known_multiple = QQ(
        nn * eisenstein_constant
    )  # It seems that we are not getting it with present algorithm.
    while known_multiple % p == 0:
        known_multiple = ZZ(known_multiple / p)

    if not recognize_point:
        fwrite('known_multiple = %s' % known_multiple, outfile)
        if quit_when_done:
            magma.quit()
        return J, Jlist

    candidate, twopow, J1 = recognize_J(E,
                                        J,
                                        K,
                                        local_embedding=local_embedding,
                                        known_multiple=known_multiple,
                                        twopowlist=twopowlist,
                                        prec=prec,
                                        outfile=outfile)

    if candidate is not None:
        HCF = K.hilbert_class_field(names='r1') if hK > 1 else K
        if hK == 1:
            try:
                verbose('candidate = %s' % candidate)
                Ptsmall = E.change_ring(HCF)(candidate)
                fwrite('twopow = %s' % twopow, outfile)
                fwrite(
                    'Computed point:  %s * %s * %s' %
                    (twopow, known_multiple, Ptsmall), outfile)
                fwrite('(first factor is not understood, second factor is)',
                       outfile)
                fwrite(
                    '(r satisfies %s = 0)' %
                    (Ptsmall[0].parent().gen().minpoly()), outfile)
                fwrite('================================================',
                       outfile)
                if quit_when_done:
                    magma.quit()
                return Ptsmall
            except (TypeError, ValueError):
                verbose("Could not recognize the point.")
        else:
            verbose('candidate = %s' % candidate)
            fwrite('twopow = %s' % twopow, outfile)
            fwrite(
                'Computed point:  %s * %s * (x,y)' % (twopow, known_multiple),
                outfile)
            fwrite('(first factor is not understood, second factor is)',
                   outfile)
            try:
                pols = [HCF(c).relative_minpoly() for c in candidate[:2]]
            except AttributeError:
                pols = [HCF(c).minpoly() for c in candidate[:2]]
            fwrite('Where x satisfies %s' % pols[0], outfile)
            fwrite('and y satisfies %s' % pols[1], outfile)
            fwrite('================================================', outfile)
            if quit_when_done:
                magma.quit()
            return candidate
    else:
        fwrite('================================================', outfile)
        if quit_when_done:
            magma.quit()
        return []
Exemple #12
0
def MacMahonOmega(var, expression, denominator=None, op=operator.ge,
          Factorization_sort=False, Factorization_simplify=True):
    r"""
    Return `\Omega_{\mathrm{op}}` of ``expression`` with respect to ``var``.

    To be more precise, calculate

    .. MATH::

        \Omega_{\mathrm{op}} \frac{n}{d_1 \dots d_n}

    for the numerator `n` and the factors `d_1`, ..., `d_n` of
    the denominator, all of which are Laurent polynomials in ``var``
    and return a (partial) factorization of the result.

    INPUT:

    - ``var`` -- a variable or a representation string of a variable

    - ``expression`` -- a
      :class:`~sage.structure.factorization.Factorization`
      of Laurent polynomials or, if ``denominator`` is specified,
      a Laurent polynomial interpreted as the numerator of the
      expression

    - ``denominator`` -- a Laurent polynomial or a
      :class:`~sage.structure.factorization.Factorization` (consisting
      of Laurent polynomial factors) or a tuple/list of factors (Laurent
      polynomials)

    - ``op`` -- (default: ``operator.ge``) an operator

      At the moment only ``operator.ge`` is implemented.

    - ``Factorization_sort`` (default: ``False``) and
      ``Factorization_simplify`` (default: ``True``) -- are passed on to
      :class:`sage.structure.factorization.Factorization` when creating
      the result

    OUTPUT:

    A (partial) :class:`~sage.structure.factorization.Factorization`
    of the result whose factors are Laurent polynomials

    .. NOTE::

        The numerator of the result may not be factored.

    REFERENCES:

    - [Mac1915]_

    - [APR2001]_

    EXAMPLES::

        sage: L.<mu, x, y, z, w> = LaurentPolynomialRing(ZZ)

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu])
        1 * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu, 1 - z/mu])
        1 * (-x + 1)^-1 * (-x*y + 1)^-1 * (-x*z + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z/mu])
        (-x*y*z + 1) * (-x + 1)^-1 * (-y + 1)^-1 * (-x*z + 1)^-1 * (-y*z + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu^2])
        1 * (-x + 1)^-1 * (-x^2*y + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^2, 1 - y/mu])
        (x*y + 1) * (-x + 1)^-1 * (-x*y^2 + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z/mu^2])
        (-x^2*y*z - x*y^2*z + x*y*z + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 * (-x^2*z + 1)^-1 * (-y^2*z + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu^3])
        1 * (-x + 1)^-1 * (-x^3*y + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y/mu^4])
        1 * (-x + 1)^-1 * (-x^4*y + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^3, 1 - y/mu])
        (x*y^2 + x*y + 1) * (-x + 1)^-1 * (-x*y^3 + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^4, 1 - y/mu])
        (x*y^3 + x*y^2 + x*y + 1) * (-x + 1)^-1 * (-x*y^4 + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu^2, 1 - y/mu, 1 - z/mu])
        (x*y*z + x*y + x*z + 1) *
        (-x + 1)^-1 * (-x*y^2 + 1)^-1 * (-x*z^2 + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu^2, 1 - y*mu, 1 - z/mu])
        (-x*y*z^2 - x*y*z + x*z + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 * (-x*z^2 + 1)^-1 * (-y*z + 1)^-1

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z*mu, 1 - w/mu])
        (x*y*z*w^2 + x*y*z*w - x*y*w - x*z*w - y*z*w + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 * (-z + 1)^-1 *
        (-x*w + 1)^-1 * (-y*w + 1)^-1 * (-z*w + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - y*mu, 1 - z/mu, 1 - w/mu])
        (x^2*y*z*w + x*y^2*z*w - x*y*z*w - x*y*z - x*y*w + 1) *
        (-x + 1)^-1 * (-y + 1)^-1 *
        (-x*z + 1)^-1 * (-x*w + 1)^-1 * (-y*z + 1)^-1 * (-y*w + 1)^-1

        sage: MacMahonOmega(mu, mu^-2, [1 - x*mu, 1 - y/mu])
        x^2 * (-x + 1)^-1 * (-x*y + 1)^-1
        sage: MacMahonOmega(mu, mu^-1, [1 - x*mu, 1 - y/mu])
        x * (-x + 1)^-1 * (-x*y + 1)^-1
        sage: MacMahonOmega(mu, mu, [1 - x*mu, 1 - y/mu])
        (-x*y + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1
        sage: MacMahonOmega(mu, mu^2, [1 - x*mu, 1 - y/mu])
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

    We demonstrate the different allowed input variants::

        sage: MacMahonOmega(mu,
        ....:     Factorization([(mu, 2), (1 - x*mu, -1), (1 - y/mu, -1)]))
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2,
        ....:     Factorization([(1 - x*mu, 1), (1 - y/mu, 1)]))
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2, [1 - x*mu, 1 - y/mu])
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2, (1 - x*mu)*(1 - y/mu))  # not tested because not fully implemented
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

        sage: MacMahonOmega(mu, mu^2 / ((1 - x*mu)*(1 - y/mu)))  # not tested because not fully implemented
        (-x*y^2 - x*y + y^2 + y + 1) * (-x + 1)^-1 * (-x*y + 1)^-1

    TESTS::

        sage: MacMahonOmega(mu, 1, [1 - x*mu])
        1 * (-x + 1)^-1
        sage: MacMahonOmega(mu, 1, [1 - x/mu])
        1
        sage: MacMahonOmega(mu, 0, [1 - x*mu])
        0
        sage: MacMahonOmega(mu, L(1), [])
        1
        sage: MacMahonOmega(mu, L(0), [])
        0
        sage: MacMahonOmega(mu, 2, [])
        2
        sage: MacMahonOmega(mu, 2*mu, [])
        2
        sage: MacMahonOmega(mu, 2/mu, [])
        0

    ::

        sage: MacMahonOmega(mu, Factorization([(1/mu, 1), (1 - x*mu, -1),
        ....:                                  (1 - y/mu, -2)], unit=2))
        2*x * (-x + 1)^-1 * (-x*y + 1)^-2
        sage: MacMahonOmega(mu, Factorization([(mu, -1), (1 - x*mu, -1),
        ....:                                  (1 - y/mu, -2)], unit=2))
        2*x * (-x + 1)^-1 * (-x*y + 1)^-2
        sage: MacMahonOmega(mu, Factorization([(mu, -1), (1 - x, -1)]))
        0
        sage: MacMahonOmega(mu, Factorization([(2, -1)]))
        1 * 2^-1

    ::

        sage: MacMahonOmega(mu, 1, [1 - x*mu, 1 - z, 1 - y/mu])
        1 * (-z + 1)^-1 * (-x + 1)^-1 * (-x*y + 1)^-1

    ::

        sage: MacMahonOmega(mu, 1, [1 - x*mu], op=operator.lt)
        Traceback (most recent call last):
        ...
        NotImplementedError: At the moment, only Omega_ge is implemented.

        sage: MacMahonOmega(mu, 1, Factorization([(1 - x*mu, -1)]))
        Traceback (most recent call last):
        ...
        ValueError: Factorization (-mu*x + 1)^-1 of the denominator
        contains negative exponents.

        sage: MacMahonOmega(2*mu, 1, [1 - x*mu])
        Traceback (most recent call last):
        ...
        ValueError: 2*mu is not a variable.

        sage: MacMahonOmega(mu, 1, Factorization([(0, 2)]))
        Traceback (most recent call last):
        ...
        ZeroDivisionError: Denominator contains a factor 0.

        sage: MacMahonOmega(mu, 1, [2 - x*mu])
        Traceback (most recent call last):
        ...
        NotImplementedError: Factor 2 - x*mu is not normalized.

        sage: MacMahonOmega(mu, 1, [1 - x*mu - mu^2])
        Traceback (most recent call last):
        ...
        NotImplementedError: Cannot handle factor 1 - x*mu - mu^2.

    ::

        sage: L.<mu, x, y, z, w> = LaurentPolynomialRing(QQ)
        sage: MacMahonOmega(mu, 1/mu,
        ....:     Factorization([(1 - x*mu, 1), (1 - y/mu, 2)], unit=2))
        1/2*x * (-x + 1)^-1 * (-x*y + 1)^-2
    """
    from sage.arith.misc import factor
    from sage.misc.misc_c import prod
    from sage.rings.integer_ring import ZZ
    from sage.rings.polynomial.laurent_polynomial_ring \
        import LaurentPolynomialRing, LaurentPolynomialRing_univariate
    from sage.structure.factorization import Factorization

    if op != operator.ge:
        raise NotImplementedError('At the moment, only Omega_ge is implemented.')

    if denominator is None:
        if isinstance(expression, Factorization):
            numerator = expression.unit() * \
                        prod(f**e for f, e in expression if e > 0)
            denominator = tuple(f for f, e in expression if e < 0
                                for _ in range(-e))
        else:
            numerator = expression.numerator()
            denominator = expression.denominator()
    else:
        numerator = expression
    # at this point we have numerator/denominator

    if isinstance(denominator, (list, tuple)):
        factors_denominator = denominator
    else:
        if not isinstance(denominator, Factorization):
            denominator = factor(denominator)
        if not denominator.is_integral():
            raise ValueError('Factorization {} of the denominator '
                             'contains negative exponents.'.format(denominator))
        numerator *= ZZ(1) / denominator.unit()
        factors_denominator = tuple(factor
                                    for factor, exponent in denominator
                                    for _ in range(exponent))
    # at this point we have numerator/factors_denominator

    P = var.parent()
    if isinstance(P, LaurentPolynomialRing_univariate) and P.gen() == var:
        L = P
        L0 = L.base_ring()
    elif var in P.gens():
        var = repr(var)
        L0 = LaurentPolynomialRing(
            P.base_ring(), tuple(v for v in P.variable_names() if v != var))
        L = LaurentPolynomialRing(L0, var)
        var = L.gen()
    else:
        raise ValueError('{} is not a variable.'.format(var))

    other_factors = []
    to_numerator = []
    decoded_factors = []
    for factor in factors_denominator:
        factor = L(factor)
        D = factor.dict()
        if not D:
            raise ZeroDivisionError('Denominator contains a factor 0.')
        elif len(D) == 1:
            exponent, coefficient = next(iteritems(D))
            if exponent == 0:
                other_factors.append(L0(factor))
            else:
                to_numerator.append(factor)
        elif len(D) == 2:
            if D.get(0, 0) != 1:
                raise NotImplementedError('Factor {} is not normalized.'.format(factor))
            D.pop(0)
            exponent, coefficient = next(iteritems(D))
            decoded_factors.append((-coefficient, exponent))
        else:
            raise NotImplementedError('Cannot handle factor {}.'.format(factor))
    numerator = L(numerator) / prod(to_numerator)

    result_numerator, result_factors_denominator = \
        _Omega_(numerator.dict(), decoded_factors)
    if result_numerator == 0:
        return Factorization([], unit=result_numerator)

    return Factorization([(result_numerator, 1)] +
                         list((f, -1) for f in other_factors) +
                         list((1-f, -1) for f in result_factors_denominator),
                         sort=Factorization_sort,
                         simplify=Factorization_simplify)
Exemple #13
0
def darmon_point(P, E, beta, prec, ramification_at_infinity = None, input_data = None, magma = None, working_prec = None, **kwargs):
    r'''

    EXAMPLES:

    We first need to import the module::

    sage: from darmonpoints.darmonpoints import darmon_point

    A first example (Stark--Heegner point)::

    sage: from darmonpoints.darmonpoints import darmon_point
    sage: darmon_point(7,EllipticCurve('35a1'),41,20, cohomological=False, use_magma=False, use_ps_dists = True)
    Starting computation of the Darmon point
    ...
    (-70*alpha + 449 : 2100*alpha - 13444 : 1)

    A quaternionic (Greenberg) point::

    sage: darmon_point(13,EllipticCurve('78a1'),5,20) # long time # optional - magma

    A Darmon point over a cubic (1,1) field::

    sage: F.<r> = NumberField(x^3 - x^2 - x + 2)
    sage: E = EllipticCurve([-r -1, -r, -r - 1,-r - 1, 0])
    sage: N = E.conductor()
    sage: P = F.ideal(r^2 - 2*r - 1)
    sage: beta = -3*r^2 + 9*r - 6
    sage: darmon_point(P,E,beta,20) # long time # optional - magma

    '''
    # global G, Coh, phiE, Phi, dK, J, J1, cycleGn, nn, Jlist

    config = ConfigParser.ConfigParser()
    config.read('config.ini')
    param_dict = config_section_map(config, 'General')
    param_dict.update(config_section_map(config, 'DarmonPoint'))
    param_dict.update(kwargs)
    param = Bunch(**param_dict)

    # Get general parameters
    outfile = param.get('outfile')
    use_ps_dists = param.get('use_ps_dists',False)
    use_shapiro = param.get('use_shapiro',True)
    use_sage_db = param.get('use_sage_db',False)
    magma_seed = param.get('magma_seed',1515316)
    parallelize = param.get('parallelize',False)
    Up_method = param.get('up_method','naive')
    use_magma = param.get('use_magma',True)
    progress_bar = param.get('progress_bar',True)
    sign_at_infinity = param.get('sign_at_infinity',ZZ(1))

    # Get darmon_point specific parameters
    idx_orientation = param.get('idx_orientation')
    idx_embedding = param.get('idx_embedding',0)
    algorithm = param.get('algorithm')
    quaternionic = param.get('quaternionic')
    cohomological = param.get('cohomological',True)

    if Up_method == "bigmatrix" and use_shapiro == True:
        import warnings
        warnings.warn('Use of "bigmatrix" for Up iteration is incompatible with Shapiro Lemma trick. Using "naive" method for Up.')
        Up_method = 'naive'

    if working_prec is None:
        working_prec = max([2 * prec + 10, 30])

    if use_magma:
        page_path = os.path.dirname(__file__) + '/KleinianGroups-1.0/klngpspec'
        if magma is None:
            from sage.interfaces.magma import Magma
            magma = Magma()
            quit_when_done = True
        else:
            quit_when_done = False
        magma.attach_spec(page_path)
    else:
        quit_when_done = False

    sys.setrecursionlimit(10**6)

    F = E.base_ring()
    beta = F(beta)
    DB,Np,Ncartan = get_heegner_params(P,E,beta)
    if quaternionic is None:
        quaternionic = ( DB != 1 )
    if cohomological is None:
        cohomological = quaternionic
    if quaternionic and not cohomological:
        raise ValueError("Need cohomological algorithm when dealing with quaternions")
    if use_ps_dists is None:
        use_ps_dists = False if cohomological else True
    try:
        p = ZZ(P)
    except TypeError:
        p = ZZ(P.norm())
    if not p.is_prime():
        raise ValueError,'P (= %s) should be a prime, of inertia degree 1'%P

    if F == QQ:
        dK = ZZ(beta)
        extra_conductor_sq = dK/fundamental_discriminant(dK)
        assert ZZ(extra_conductor_sq).is_square()
        extra_conductor = extra_conductor_sq.sqrt()
        dK = dK / extra_conductor_sq
        assert dK == fundamental_discriminant(dK)
        if dK % 4 == 0:
            dK = ZZ(dK/4)
        beta = dK
    else:
        dK = beta

    # Compute the completion of K at p
    x = QQ['x'].gen()
    K = F.extension(x*x - dK,names = 'alpha')
    if F == QQ:
        dK = K.discriminant()
    else:
        dK = K.relative_discriminant()

    hK = K.class_number()

    sgninfty = 'plus' if sign_at_infinity == 1 else 'minus'
    if hasattr(E,'cremona_label'):
        Ename = E.cremona_label()
    elif hasattr(E,'ainvs'):
        Ename = E.ainvs()
    else:
        Ename = 'unknown'
    fname = 'moments_%s_%s_%s_%s.sobj'%(P,Ename,sgninfty,prec)

    if use_sage_db:
        print("Moments will be stored in database as %s"%(fname))

    if outfile == 'log':
        outfile = '%s_%s_%s_%s_%s_%s.log'%(P,Ename,dK,sgninfty,prec,datetime.datetime.now().strftime("%Y%m%d-%H%M%S"))
        outfile = outfile.replace('/','div')
        outfile = '/tmp/darmonpoint_' + outfile

    fwrite("Starting computation of the Darmon point",outfile)
    fwrite('D_B = %s  %s'%(DB,factor(DB)),outfile)
    fwrite('Np = %s'%Np,outfile)
    if Ncartan is not None:
        fwrite('Ncartan = %s'%Ncartan,outfile)
    fwrite('dK = %s (class number = %s)'%(dK,hK),outfile)
    fwrite('Calculation with p = %s and prec = %s'%(P,prec),outfile)
    fwrite('Elliptic curve %s: %s'%(Ename,E),outfile)
    if outfile is not None:
        print("Partial results will be saved in %s"%outfile)

    if input_data is None:
        if cohomological:
            # Define the S-arithmetic group
            if F != QQ and ramification_at_infinity is None:
                if F.signature()[0] > 1:
                    if F.signature()[1] == 1:
                        ramification_at_infinity = F.real_places(prec = Infinity) # Totally 'definite'
                    else:
                        raise ValueError,'Please specify the ramification at infinity'
                elif F.signature()[0] == 1:
                    if len(F.ideal(DB).factor()) % 2 == 0:
                        ramification_at_infinity = [] # Split at infinity
                    else:
                        ramification_at_infinity = F.real_places(prec = Infinity) # Ramified at infinity
                else:
                    ramification_at_infinity = None
            if F == QQ:
                abtuple = QuaternionAlgebra(DB).invariants()
            else:
                abtuple = quaternion_algebra_invariants_from_ramification(F, DB, ramification_at_infinity)

            G = BigArithGroup(P,abtuple,Np,base = F,outfile = outfile,seed = magma_seed,use_sage_db = use_sage_db,magma = magma, use_shapiro = use_shapiro, nscartan=Ncartan)

            # Define the cycle ( in H_1(G,Div^0 Hp) )
            Coh = ArithCoh(G)
            while True:
                try:
                    cycleGn,nn,ell = construct_homology_cycle(G,beta,working_prec,lambda q: Coh.hecke_matrix(q).minpoly(), outfile = outfile, elliptic_curve = E)
                    break
                except PrecisionError:
                    working_prec *= 2
                    verbose('Encountered precision error, trying with higher precision (= %s)'%working_prec)
                except ValueError:
                    fwrite('ValueError occurred when constructing homology cycle. Returning the S-arithmetic group.', outfile)
                    if quit_when_done:
                        magma.quit()
                    return G
                except AssertionError as e:
                    fwrite('Assertion occurred when constructing homology cycle. Returning the S-arithmetic group.', outfile)
                    fwrite('%s'%str(e), outfile)
                    if quit_when_done:
                        magma.quit()
                    return G
            eisenstein_constant = -ZZ(E.reduction(ell).count_points())
            fwrite('r = %s, so a_r(E) - r - 1 = %s'%(ell,eisenstein_constant), outfile)
            fwrite('exponent = %s'%nn, outfile)
            phiE = Coh.get_cocycle_from_elliptic_curve(E, sign = sign_at_infinity)
            if hasattr(E,'ap'):
                sign_ap = E.ap(P)
            else:
                try:
                    sign_ap = ZZ(P.norm() + 1 - E.reduction(P).count_points())
                except ValueError:
                    sign_ap = ZZ(P.norm() + 1 - Curve(E).change_ring(P.residue_field()).count_points(1)[0])

            Phi = get_overconvergent_class_quaternionic(P,phiE,G,prec,sign_at_infinity,sign_ap,use_ps_dists = use_ps_dists,use_sage_db = use_sage_db,parallelize = parallelize,method = Up_method, progress_bar = progress_bar,Ename = Ename)
            # Integration with moments
            tot_time = walltime()
            J = integrate_H1(G,cycleGn,Phi,1,method = 'moments',prec = working_prec,parallelize = parallelize,twist = True,progress_bar = progress_bar)
            verbose('integration tot_time = %s'%walltime(tot_time))
            if use_sage_db:
                G.save_to_db()
        else: # not cohomological
            nn = 1
            eisenstein_constant = 1
            if algorithm is None:
                if Np == 1:
                    algorithm = 'darmon_pollack'
                else:
                    algorithm = 'guitart_masdeu'
            w = K.maximal_order().ring_generators()[0]
            r0,r1 = w.coordinates_in_terms_of_powers()(K.gen())
            QQp = Qp(p,working_prec)
            Cp = QQp.extension(w.minpoly().change_ring(QQp),names = 'g')
            v0 = K.hom([r0 + r1 * Cp.gen()])

            # Optimal embeddings of level one
            fwrite("Computing optimal embeddings of level one...", outfile)
            Wlist = find_optimal_embeddings(K,use_magma = use_magma, extra_conductor = extra_conductor)
            fwrite("Found %s such embeddings."%len(Wlist), outfile)
            if idx_embedding is not None:
                if idx_embedding >= len(Wlist):
                    fwrite('There are not enough embeddings. Taking the index modulo %s'%len(Wlist), outfile)
                    idx_embedding = idx_embedding % len(Wlist)
                fwrite('Taking only embedding number %s'%(idx_embedding), outfile)
                Wlist = [Wlist[idx_embedding]]

            # Find the orientations
            orients = K.maximal_order().ring_generators()[0].minpoly().roots(Zmod(Np),multiplicities = False)
            fwrite("Possible orientations: %s"%orients, outfile)
            if len(Wlist) == 1 or idx_orientation == -1:
                fwrite("Using all orientations, since hK = 1", outfile)
                chosen_orientation = None
            else:
                fwrite("Using orientation = %s"%orients[idx_orientation], outfile)
                chosen_orientation = orients[idx_orientation]

            emblist = []
            for i,W in enumerate(Wlist):
                tau, gtau,sign,limits = find_tau0_and_gtau(v0,Np,W,algorithm = algorithm,orientation = chosen_orientation,extra_conductor = extra_conductor)
                fwrite('n_evals = %s'%sum((num_evals(t1,t2) for t1,t2 in limits)), outfile)
                emblist.append((tau,gtau,sign,limits))

            # Get the cohomology class from E
            Phi = get_overconvergent_class_matrices(P,E,prec,sign_at_infinity,use_ps_dists = use_ps_dists,use_sage_db = use_sage_db,parallelize = parallelize,progress_bar = progress_bar)

            J = 1
            Jlist = []
            for i,emb in enumerate(emblist):
                fwrite("Computing %s-th period, attached to the embedding: %s"%(i,Wlist[i].list()), outfile)
                tau, gtau,sign,limits = emb
                n_evals = sum((num_evals(t1,t2) for t1,t2 in limits))
                fwrite("Computing one period...(total of %s evaluations)"%n_evals, outfile)
                newJ = prod((double_integral_zero_infty(Phi,t1,t2) for t1,t2 in limits))**ZZ(sign)
                Jlist.append(newJ)
                J *= newJ
    else: # input_data is not None
        Phi,J = input_data[1:3]
    fwrite('Integral done. Now trying to recognize the point', outfile)
    fwrite('J_psi = %s'%J,outfile)
    fwrite('g belongs to %s'%J.parent(),outfile)
    #Try to recognize a generator
    if quaternionic:
        local_embedding = G.base_ring_local_embedding(working_prec)
        twopowlist = [4, 3, 2, 1, QQ(1)/2, QQ(3)/2, QQ(1)/3, QQ(2)/3, QQ(1)/4, QQ(3)/4, QQ(5)/2, QQ(4)/3]
    else:
        local_embedding = Qp(p,working_prec)
        twopowlist = [4, 3, 2, 1, QQ(1)/2, QQ(3)/2, QQ(1)/3, QQ(2)/3, QQ(1)/4, QQ(3)/4, QQ(5)/2, QQ(4)/3]

    known_multiple = QQ(nn * eisenstein_constant) # It seems that we are not getting it with present algorithm.
    while known_multiple % p == 0:
        known_multiple = ZZ(known_multiple / p)

    candidate,twopow,J1 = recognize_J(E,J,K,local_embedding = local_embedding,known_multiple = known_multiple,twopowlist = twopowlist,prec = prec, outfile = outfile)

    if candidate is not None:
        HCF = K.hilbert_class_field(names = 'r1') if hK > 1 else K
        if hK == 1:
            try:
                verbose('candidate = %s'%candidate)
                Ptsmall = E.change_ring(HCF)(candidate)
                fwrite('twopow = %s'%twopow,outfile)
                fwrite('Computed point:  %s * %s * %s'%(twopow,known_multiple,Ptsmall),outfile)
                fwrite('(first factor is not understood, second factor is)',outfile)
                fwrite('(r satisfies %s = 0)'%(Ptsmall[0].parent().gen().minpoly()),outfile)
                fwrite('================================================',outfile)
                if quit_when_done:
                    magma.quit()
                return Ptsmall
            except (TypeError,ValueError):
                verbose("Could not recognize the point.")
        else:
            verbose('candidate = %s'%candidate)
            fwrite('twopow = %s'%twopow,outfile)
            fwrite('Computed point:  %s * %s * (x,y)'%(twopow,known_multiple),outfile)
            fwrite('(first factor is not understood, second factor is)',outfile)
            try:
                pols = [HCF(c).relative_minpoly() for c in candidate[:2]]
            except AttributeError:
                pols = [HCF(c).minpoly() for c in candidate[:2]]
            fwrite('Where x satisfies %s'%pols[0],outfile)
            fwrite('and y satisfies %s'%pols[1],outfile)
            fwrite('================================================',outfile)
            if quit_when_done:
                magma.quit()
            return candidate
    else:
        fwrite('================================================',outfile)
        if quit_when_done:
            magma.quit()
        return []