예제 #1
0
 def __init__(self, N, P, p, e):
     self._N = N
     self._F = P.number_field()
     self._p = p
     from sage.rings.all import Integers
     f = e // 2 + 1
     assert f * 2 - 1 == e
     R0 = Integers(p**f)
     R1 = Integers(p**(f - 1))
     self._ring = RamifiedProductRing(R0, R1)
     self._im_gen = self._ring.gen()
     self._sqrt5 = (self._F.gen() * 2 - 1)**2
예제 #2
0
def _delta_poly_modulo(N, prec=10):
    """
    Return the q-expansion of `\Delta` modulo `N`. Used internally by
    the :func:`~delta_qexp` function. See the docstring of :func:`~delta_qexp`
    for more information.

    INPUT:

    - `N` -- positive integer modulo which we want to compute `\Delta`

    - ``prec`` -- integer; the absolute precision of the output

    OUTPUT:

        the polynomial of degree ``prec``-1 which is the truncation
        of `\Delta` modulo `N`, as an element of the polynomial
        ring in `q` over the integers modulo `N`.

    EXAMPLES::

        sage: from sage.modular.modform.vm_basis import _delta_poly_modulo
        sage: _delta_poly_modulo(5, 7)
        2*q^6 + 3*q^4 + 2*q^3 + q^2 + q
        sage: _delta_poly_modulo(10, 12)
        2*q^11 + 7*q^9 + 6*q^7 + 2*q^6 + 8*q^4 + 2*q^3 + 6*q^2 + q
    """
    if prec <= 0:
        raise ValueError("prec must be positive")
    v = [0] * prec

    # Let F = \sum_{n >= 0} (-1)^n (2n+1) q^(floor(n(n+1)/2)).
    # Then delta is F^8.

    stop = int((-1 + math.sqrt(8 * prec)) / 2.0)

    for n in xrange(stop + 1):
        v[n * (n + 1) // 2] = ((N - 1) * (2 * n + 1) if (n & 1) else
                               (2 * n + 1))

    from sage.rings.all import Integers

    P = PolynomialRing(Integers(N), 'q')
    f = P(v)
    t = verbose('made series')
    # fast way of computing f*f truncated at prec
    f = f._mul_trunc_(f, prec)
    t = verbose('squared (1 of 3)', t)
    f = f._mul_trunc_(f, prec)
    t = verbose('squared (2 of 3)', t)
    f = f._mul_trunc_(f, prec - 1)
    t = verbose('squared (3 of 3)', t)
    f = f.shift(1)
    t = verbose('shifted', t)

    return f
예제 #3
0
 def __init__(self, N, P, p, e):
     self._N = N
     self._F = P.number_field()
     self._p = p
     from sage.rings.all import Integers
     assert e % 2 == 0
     R = Integers(p**(e // 2))
     modulus = self._F.defining_polynomial().change_ring(R)
     S = R['x']
     self._ring = S.quotient_by_principal_ideal(modulus)
     self._im_gen = self._ring.gen()
예제 #4
0
def solve_mod(eqns, modulus, solution_dict=False):
    r"""
    Return all solutions to an equation or list of equations modulo the
    given integer modulus. Each equation must involve only polynomials
    in 1 or many variables.

    By default the solutions are returned as `n`-tuples, where `n`
    is the number of variables appearing anywhere in the given
    equations. The variables are in alphabetical order.

    INPUT:


    -  ``eqns`` - equation or list of equations

    -  ``modulus`` - an integer

    -  ``solution_dict`` - bool (default: False); if True or non-zero,
       return a list of dictionaries containing the solutions. If there
       are no solutions, return an empty list (rather than a list containing
       an empty dictionary). Likewise, if there's only a single solution,
       return a list containing one dictionary with that solution.


    EXAMPLES::

        sage: var('x,y')
        (x, y)
        sage: solve_mod([x^2 + 2 == x, x^2 + y == y^2], 14)
        [(4, 2), (4, 6), (4, 9), (4, 13)]
        sage: solve_mod([x^2 == 1, 4*x  == 11], 15)
        [(14,)]

    Fermat's equation modulo 3 with exponent 5::

        sage: var('x,y,z')
        (x, y, z)
        sage: solve_mod([x^5 + y^5 == z^5], 3)
        [(0, 0, 0), (0, 1, 1), (0, 2, 2), (1, 0, 1), (1, 1, 2), (1, 2, 0), (2, 0, 2), (2, 1, 0), (2, 2, 1)]

    We can solve with respect to a bigger modulus if it consists only of small prime factors::

        sage: [d] = solve_mod([5*x + y == 3, 2*x - 3*y == 9], 3*5*7*11*19*23*29, solution_dict = True)
        sage: d[x]
        12915279
        sage: d[y]
        8610183

    For cases where there are relatively few solutions and the prime
    factors are small, this can be efficient even if the modulus itself
    is large::

        sage: sorted(solve_mod([x^2 == 41], 10^20))
        [(4538602480526452429,), (11445932736758703821,), (38554067263241296179,),
        (45461397519473547571,), (54538602480526452429,), (61445932736758703821,),
        (88554067263241296179,), (95461397519473547571,)]

    We solve a simple equation modulo 2::

        sage: x,y = var('x,y')
        sage: solve_mod([x == y], 2)
        [(0, 0), (1, 1)]

    .. warning::

       The current implementation splits the modulus into prime
       powers, then naively enumerates all possible solutions
       (starting modulo primes and then working up through prime
       powers), and finally combines the solution using the Chinese
       Remainder Theorem.  The interface is good, but the algorithm is
       very inefficient if the modulus has some larger prime factors! Sage
       *does* have the ability to do something much faster in certain
       cases at least by using Groebner basis, linear algebra
       techniques, etc. But for a lot of toy problems this function as
       is might be useful. At least it establishes an interface.


    TESTS:

    Make sure that we short-circuit in at least some cases::

        sage: solve_mod([2*x==1], 2*next_prime(10^50))
        []

    Try multi-equation cases::

        sage: x, y, z = var("x y z")
        sage: solve_mod([2*x^2 + x*y, -x*y+2*y^2+x-2*y, -2*x^2+2*x*y-y^2-x-y], 12)
        [(0, 0), (4, 4), (0, 3), (4, 7)]
        sage: eqs = [-y^2+z^2, -x^2+y^2-3*z^2-z-1, -y*z-z^2-x-y+2, -x^2-12*z^2-y+z]
        sage: solve_mod(eqs, 11)
        [(8, 5, 6)]

    Confirm that modulus 1 now behaves as it should::

        sage: x, y = var("x y")
        sage: solve_mod([x==1], 1)
        [(0,)]
        sage: solve_mod([2*x^2+x*y, -x*y+2*y^2+x-2*y, -2*x^2+2*x*y-y^2-x-y], 1)
        [(0, 0)]


    """
    from sage.rings.all import Integer, Integers, crt_basis
    from sage.symbolic.expression import is_Expression
    from sage.misc.all import cartesian_product_iterator
    from sage.modules.all import vector
    from sage.matrix.all import matrix

    if not isinstance(eqns, (list, tuple)):
        eqns = [eqns]
    eqns = [eq if is_Expression(eq) else (eq.lhs() - eq.rhs()) for eq in eqns]
    modulus = Integer(modulus)
    if modulus < 1:
        raise ValueError("the modulus must be a positive integer")
    vars = list(set(sum([list(e.variables()) for e in eqns], [])))
    vars.sort(key=repr)

    if modulus == 1:  # degenerate case
        ans = [tuple(Integers(1)(0) for v in vars)]
        return ans

    factors = modulus.factor()
    crt_basis = vector(Integers(modulus),
                       crt_basis([p**i for p, i in factors]))
    solutions = []

    has_solution = True
    for p, i in factors:
        solution = _solve_mod_prime_power(eqns, p, i, vars)
        if len(solution) > 0:
            solutions.append(solution)
        else:
            has_solution = False
            break

    ans = []
    if has_solution:
        for solution in cartesian_product_iterator(solutions):
            solution_mat = matrix(Integers(modulus), solution)
            ans.append(
                tuple(
                    c.dot_product(crt_basis) for c in solution_mat.columns()))

    # if solution_dict == True:
    # Relaxed form suggested by Mike Hansen (#8553):
    if solution_dict:
        sol_dict = [dict(zip(vars, solution)) for solution in ans]
        return sol_dict
    else:
        return ans
예제 #5
0
def _solve_mod_prime_power(eqns, p, m, vars):
    r"""
    Internal help function for solve_mod, does little checking since it expects
    solve_mod to do that

    Return all solutions to an equation or list of equations modulo p^m.
    Each equation must involve only polynomials
    in 1 or many variables.

    The solutions are returned as `n`-tuples, where `n`
    is the number of variables in vars.

    INPUT:


    -  ``eqns`` - equation or list of equations

    -  ``p`` - a prime

    -  ``i`` - an integer > 0

    -  ``vars`` - a list of variables to solve for


    EXAMPLES::

        sage: var('x,y')
        (x, y)
        sage: solve_mod([x^2 + 2 == x, x^2 + y == y^2], 14)
        [(4, 2), (4, 6), (4, 9), (4, 13)]
        sage: solve_mod([x^2 == 1, 4*x  == 11], 15)
        [(14,)]

    Fermat's equation modulo 3 with exponent 5::

        sage: var('x,y,z')
        (x, y, z)
        sage: solve_mod([x^5 + y^5 == z^5], 3)
        [(0, 0, 0), (0, 1, 1), (0, 2, 2), (1, 0, 1), (1, 1, 2), (1, 2, 0), (2, 0, 2), (2, 1, 0), (2, 2, 1)]

    We solve a simple equation modulo 2::

        sage: x,y = var('x,y')
        sage: solve_mod([x == y], 2)
        [(0, 0), (1, 1)]


    .. warning::

       Currently this constructs possible solutions by building up
       from the smallest prime factor of the modulus.  The interface
       is good, but the algorithm is horrible if the modulus isn't the
       product of many small primes! Sage *does* have the ability to
       do something much faster in certain cases at least by using the
       Chinese Remainder Theorem, Groebner basis, linear algebra
       techniques, etc. But for a lot of toy problems this function as
       is might be useful. At the very least, it establishes an
       interface.

    TESTS:

    Confirm we can reproduce the first few terms of :oeis:`A187719`::

        sage: from sage.symbolic.relation import _solve_mod_prime_power
        sage: [sorted(_solve_mod_prime_power([x^2==41], 10, i, [x]))[0][0] for i in [1..13]]
        [1, 21, 71, 1179, 2429, 47571, 1296179, 8703821, 26452429, 526452429,
        13241296179, 19473547571, 2263241296179]

    """
    from sage.rings.all import Integers, PolynomialRing
    from sage.modules.all import vector
    from sage.misc.all import cartesian_product_iterator

    mrunning = 1
    ans = []
    for mi in range(m):
        mrunning *= p
        R = Integers(mrunning)
        S = PolynomialRing(R, len(vars), vars)
        eqns_mod = [S(eq) for eq in eqns]
        if mi == 0:
            possibles = cartesian_product_iterator(
                [range(len(R)) for _ in range(len(vars))])
        else:
            shifts = cartesian_product_iterator(
                [range(p) for _ in range(len(vars))])
            pairs = cartesian_product_iterator([shifts, ans])
            possibles = (tuple(vector(t) + vector(shift) * (mrunning // p))
                         for shift, t in pairs)
        ans = list(t for t in possibles if all(e(*t) == 0 for e in eqns_mod))
        if not ans: return ans

    return ans
예제 #6
0
def __startup__():
    import sage.algebras.steenrod.steenrod_algebra
    import types

    def resolution(self, memory=None, filename=None):
        """
        The minimal resolution of the ground field as a module over 'self'.

        TESTS::

            sage: from yacop.resolutions.minres import MinimalResolution
            sage: MinimalResolution(SteenrodAlgebra(7)) is SteenrodAlgebra(7).resolution()
            True
        """
        from yacop.resolutions.minres import MinimalResolution

        return MinimalResolution(self, memory=memory, filename=filename)

    setattr(
        sage.algebras.steenrod.steenrod_algebra.SteenrodAlgebra_generic,
        "resolution",
        resolution,
    )

    def Ext(algebra, M, N=None, filename=None):
        """
        ``Ext(M,N)`` over ``algebra``.
        """
        from yacop.resolutions.smashres import SmashResolution

        assert N is None
        return SmashResolution(M, algebra.resolution(),
                               filename=filename).Homology()

    setattr(sage.algebras.steenrod.steenrod_algebra.SteenrodAlgebra_generic,
            "Ext", Ext)

    # there are known issues in Sage with pickling of morphisms
    # and we don't want to document the same failures in our test
    # suite.
    from sage.combinat.free_module import CombinatorialFreeModule

    def p_test_pickling(self, tester=None, **options):
        if not hasattr(self,
                       "_can_test_pickling") or self._can_test_pickling():
            tester = self._tester(**options)
            from sage.misc.all import loads, dumps

            tester.assertEqual(loads(dumps(self)), self)
        else:
            tester.info(" (skipped, not picklable) ", newline=False)

    def e_test_pickling(self, tester=None, **options):
        if not hasattr(self,
                       "_can_test_pickling") or self._can_test_pickling():
            tester = self._tester(**options)
            from sage.misc.all import loads, dumps

            tester.assertEqual(loads(dumps(self)), self)
        else:
            tester.info(" (skipped, not picklable) ", newline=False)

    CombinatorialFreeModule._test_pickling = p_test_pickling
    # CombinatorialFreeModule.Element._test_pickling = e_test_pickling (no longer possible, by ticket/22632)

    # workaround for Sage Ticket #13814
    from sage.sets.family import LazyFamily
    from sage.rings.all import Integers

    if LazyFamily(Integers(),
                  lambda i: 2 * i) == LazyFamily(Integers(), lambda i: 2 * i):

        def noteq(self, other):
            if self is other:
                return True
            return False

        LazyFamily.__eq__ = noteq

    try:
        16 in LazyFamily(Integers(), lambda i: 2 * i)
    except:
        # we need to overwrite _contains_ in our module base to fix
        # the test suite of SteenrodModuleBase.basis()
        def __contains__(self, x):
            try:
                return self._contains_(x)
            except AttributeError:
                return super(LazyFamily, self).__contains__(x)

        LazyFamily.__contains__ = __contains__

    # workaround for #13811
    from sage.sets.family import AbstractFamily

    def __copy__(self):
        return self

    AbstractFamily.__copy__ = __copy__

    # LazyFamilies cannot be pickled... turn off the resulting noise
    def _test_pickling(self, tester=None, **options):
        pass

    LazyFamily._test_pickling = _test_pickling

    # workaround for Sage ticket #13833
    from sage.algebras.steenrod.steenrod_algebra import SteenrodAlgebra

    B = SteenrodAlgebra(2, profile=(3, 2, 1))
    A = SteenrodAlgebra(2)
    id = A.module_morphism(codomain=A, on_basis=lambda x: A.monomial(x))
    try:
        x = id(B.an_element())
    except AssertionError:
        from sage.categories.modules_with_basis import ModuleMorphismByLinearity

        origcall = ModuleMorphismByLinearity.__call__

        def call(self, *args):
            before = args[0:self._position]
            after = args[self._position + 1:len(args)]
            x = args[self._position]
            nargs = before + (self.domain()(x), ) + after
            return origcall(self, *nargs)

        ModuleMorphismByLinearity.__call__ = call

    # workaround for Sage ticket #18449
    from sage.sets.set_from_iterator import EnumeratedSetFromIterator
    from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
    from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
    from sage.categories.enumerated_sets import EnumeratedSets
    from sage.rings.integer_ring import ZZ

    C = CombinatorialFreeModule(ZZ, EnumeratedSetFromIterator(Integers))
    if False and sage.categories.tensor.tensor(
        (C, )).basis() in FiniteEnumeratedSets():

        def __init_18449__(self, set, function, name=None):
            """
            patched __init__ function from ticket #18449
            """
            from sage.combinat.combinat import CombinatorialClass  # workaround #12482
            from sage.structure.parent import Parent

            category = EnumeratedSets()
            if set in FiniteEnumeratedSets():
                category = FiniteEnumeratedSets()
            elif set in InfiniteEnumeratedSets():
                category = InfiniteEnumeratedSets()
            elif isinstance(set, (list, tuple)):
                category = FiniteEnumeratedSets()
            elif isinstance(set, CombinatorialClass):
                try:
                    if set.is_finite():
                        category = FiniteEnumeratedSets()
                except NotImplementedError:
                    pass
            Parent.__init__(self, category=category)
            from copy import copy

            self.set = copy(set)
            self.function = function
            self.function_name = name

        LazyFamily.__init__ = __init_18449__

    # use a lower max_runs value for the TestSuite
    from sage.misc.sage_unittest import InstanceTester

    InstanceTester.__init_original__ = InstanceTester.__init__

    def newinit(self, *args, **kwds):
        self.__init_original__(*args, **kwds)
        self._max_runs = 40

    InstanceTester.__init__ = newinit

    # fix a problem for __contain__ in Categories_over_base_ring
    # when more than one base is involved:
    from sage.categories.category import Category
    from sage.categories.category_types import Category_over_base_ring
    from sage.categories.modules import Modules
    from sage.categories.algebras import Algebras
    from sage.categories.modules_with_basis import ModulesWithBasis
    from sage.rings.finite_rings.finite_field_constructor import GF

    C = CombinatorialFreeModule(GF(5),
                                ZZ,
                                category=(ModulesWithBasis(GF(5)),
                                          Algebras(ZZ)))
    if C not in Modules(ZZ):
        _sagecode = Category_over_base_ring.__contains__
        Category_over_base_ring.__contains_sage__ = _sagecode

        def __contains_yacop__(self, Z):
            ans = self.__contains_sage__(Z)
            if not ans:
                try:
                    ans = self in Z.categories()
                except:
                    pass
            return ans

        Category_over_base_ring.__contains__ = __contains_yacop__

    # Sage insists that Subquotients of CartesianProducts are again CartesianProducts
    # (and similarly for TensorProducts). We forcefully disagree:
    from sage.categories.covariant_functorial_construction import RegressiveCovariantConstructionCategory

    @classmethod
    def default_super_categories_yacop(cls, category, *args):
        """
        TESTS::

            sage: import yacop

            sage: # an earlier version of this hack broke the MRO for quasi symmetric functions:
            sage: QuasiSymmetricFunctions(GF(3))
            Quasisymmetric functions over the Finite Field of size 3

        """
        sageresult = Category.join([
            category,
            super(RegressiveCovariantConstructionCategory,
                  cls).default_super_categories(category, *args)
        ])
        ans = sageresult
        if isinstance(ans, sage.categories.category.JoinCategory):
            j = [
                cat for cat in sageresult.super_categories()
                if not hasattr(cat, "yacop_no_default_inheritance")
            ]
            ans = Category.join(j)
        return ans

    RegressiveCovariantConstructionCategory.default_super_categories = default_super_categories_yacop