def hasse_conductor(self):
    """
    This is the product of all primes where the Hasse invariant equals -1

    EXAMPLES::

        sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5])
        sage: Q.hasse_invariant(2)
        -1
        sage: Q.hasse_invariant(37)
        -1
        sage: Q.hasse_conductor()
        74

    ::

        sage: DiagonalQuadraticForm(ZZ, [1, 1, 1]).hasse_conductor()
        1
        sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).hasse_conductor()
        10
    """
    D = self.disc()
    return prod(
        filter(lambda p: self.hasse_invariant(p) == -1,
               map(lambda x: x[0], factor(2 * self.level()))))
Exemple #2
0
def mumu(N):
    """
    Return 0 if any cube divides `N`. Otherwise return
    `(-2)^v` where `v` is the number of primes that
    exactly divide `N`.

    This is similar to the Moebius function.

    INPUT:

    -  ``N`` - an integer at least 1

    OUTPUT: Integer

    EXAMPLES::

        sage: from sage.modular.arithgroup.congroup_gammaH import mumu
        sage: mumu(27)
        0
        sage: mumu(6*25)
        4
        sage: mumu(7*9*25)
        -2
        sage: mumu(9*25)
        1
    """
    if N < 1:
        raise ValueError, "N must be at least 1"
    p = 1
    for _,r in factor(N):
        if r > 2:
            return ZZ(0)
        elif r == 1:
            p *= -2
    return ZZ(p)
Exemple #3
0
    def multiplicative_order(self):
        r"""
        Returns the *multiplicative* order of this element, which must be
        nonzero.

        EXAMPLES::

            sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
            sage: a = FiniteField_ext_pari(5**3, 'a').0
            sage: a.multiplicative_order()
            124
            sage: a**124
            1
        """
        try:
            return self.__multiplicative_order
        except AttributeError:
            if self.is_zero():
                raise ArithmeticError("Multiplicative order of 0 not defined.")
            n = self.parent().order() - 1
            order = 1
            for p, e in arith.factor(n):
                # Determine the power of p that divides the order.
                a = self**(n//(p**e))
                while a != 1:
                    order *= p
                    a = a**p
            self.__multiplicative_order = order
            return order
Exemple #4
0
    def create_key_and_extra_args(self,
                                  order,
                                  name=None,
                                  modulus=None,
                                  names=None,
                                  impl=None,
                                  proof=None,
                                  **kwds):
        """
        EXAMPLES::
        
            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), 'conway', None, '{}', 3, 2, True), {})
            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            ((9, ('a',), 'conway', None, "{'foo': 'value'}", 3, 2, True), {'foo': 'value'})
        """
        from sage.structure.proof.all import WithProof, arithmetic
        if proof is None: proof = arithmetic()
        with WithProof('arithmetic', proof):
            order = int(order)
            if order <= 1:
                raise ValueError("the order of a finite field must be > 1.")

            if arith.is_prime(order):
                name = None
                modulus = None
                p = integer.Integer(order)
                n = integer.Integer(1)
            elif arith.is_prime_power(order):
                if not names is None: name = names
                name = normalize_names(1, name)

                p, n = arith.factor(order)[0]

                if modulus is None or modulus == "default":
                    if exists_conway_polynomial(p, n):
                        modulus = "conway"
                    else:
                        if p == 2:
                            modulus = "minimal_weight"
                        else:
                            modulus = "random"
                elif modulus == "random":
                    modulus += str(random.randint(0, 1 << 128))

                if isinstance(modulus, (list, tuple)):
                    modulus = FiniteField(p)['x'](modulus)
                # some classes use 'random' as the modulus to
                # generate a random modulus, but we don't want
                # to cache it
                elif sage.rings.polynomial.polynomial_element.is_Polynomial(
                        modulus):
                    modulus = modulus.change_variable_name('x')
                elif not isinstance(modulus, str):
                    raise ValueError("Modulus parameter not understood.")
            else:  # Neither a prime, nor a prime power
                raise ValueError(
                    "the order of a finite field must be a prime power.")

            return (order, name, modulus, impl, str(kwds), p, n, proof), kwds
Exemple #5
0
 def multiplicative_order(self):
     r"""
     Returns the *multiplicative* order of this element, which must be
     nonzero.
     
     EXAMPLES::
     
         sage: from sage.rings.finite_rings.finite_field_ext_pari import FiniteField_ext_pari
         sage: a = FiniteField_ext_pari(5**3, 'a').0
         sage: a.multiplicative_order()
         124
         sage: a**124
         1
     """
     try:
         return self.__multiplicative_order
     except AttributeError:
         if self.is_zero():
             raise ArithmeticError("Multiplicative order of 0 not defined.")
         n = self.parent().order() - 1
         order = 1
         for p, e in arith.factor(n):
             # Determine the power of p that divides the order.
             a = self**(n // (p**e))
             while a != 1:
                 order *= p
                 a = a**p
         self.__multiplicative_order = order
         return order
Exemple #6
0
def mumu(N):
    """
    Return 0 if any cube divides `N`. Otherwise return
    `(-2)^v` where `v` is the number of primes that
    exactly divide `N`.

    This is similar to the Moebius function.

    INPUT:

    -  ``N`` - an integer at least 1

    OUTPUT: Integer

    EXAMPLES::

        sage: from sage.modular.arithgroup.congroup_gammaH import mumu
        sage: mumu(27)
        0
        sage: mumu(6*25)
        4
        sage: mumu(7*9*25)
        -2
        sage: mumu(9*25)
        1
    """
    if N < 1:
        raise ValueError, "N must be at least 1"
    p = 1
    for _, r in factor(N):
        if r > 2:
            return ZZ(0)
        elif r == 1:
            p *= -2
    return ZZ(p)
Exemple #7
0
    def coefficient_n_recursive(self, n):
        r"""
          Reimplement the recursive algorithm in sage modular/hecke/module.py
          We do this because of a bug in sage with .eigenvalue()
        """
        from sage.rings import arith
        ev = self.eigenvalues

        c2 = self._coefficients.get(2)
        if c2 is not None:
            K = c2.parent()
        else:
            if ev.max_coefficient_in_db() >= 2:
                ev.init_dynamic_properties()
            else:
                raise StopIteration, "Newform does not have eigenvalue a(2)!"
            self._coefficients[2] = ev[2]
            K = ev[2].parent()
        prod = K(1)
        if K.absolute_degree() > 1 and K.is_relative():
            KZ = K.base_field()
        else:
            KZ = K
        #emf_logger.debug("K= {0}".format(K))
        F = arith.factor(n)
        for p, r in F:
            #emf_logger.debug("parent_char_val[{0}]={1}".format(p,self.parent.character_used_in_computation.value(p)))
            #emf_logger.debug("char_val[{0}]={1}".format(p,self.character.value(p)))
            (p, r) = (int(p), int(r))
            pr = p**r
            cp = self._coefficients.get(p)
            #            emf_logger.debug("c{0} = {1}".format(p,cp))
            if cp is None:
                if ev.has_eigenvalue(p):
                    cp = ev[p]
                elif ev.max_coefficient_in_db() >= p:
                    ev.init_dynamic_properties()
                    cp = ev[p]
            if cp is None:
                raise IndexError, "p={0} is outside the range of computed primes (primes up to {1})! for label:{2}".format(
                    p, max(ev.primes()), self.label)
            if self._coefficients.get(pr) is None:
                if r == 1:
                    c = cp
                else:
                    eps = KZ(
                        self.parent.character_used_in_computation.value(p))
                    # a_{p^r} := a_p * a_{p^{r-1}} - eps(p)p^{k-1} a_{p^{r-2}}
                    apr1 = self.coefficient_n_recursive(pr // p)
                    #ap = self.coefficient_n_recursive(p)
                    k = self.weight
                    apr2 = self.coefficient_n_recursive(pr // (p * p))
                    c = cp * apr1 - eps * (p**(k - 1)) * apr2
                    #emf_logger.debug("c({0})={1}".format(pr,c))
                    #ev[pr]=c
                self._coefficients[pr] = c
            prod *= self._coefficients[pr]
        return prod
Exemple #8
0
    def coefficient_n_recursive(self, n):
        r"""
          Reimplement the recursive algorithm in sage modular/hecke/module.py
          We do this because of a bug in sage with .eigenvalue()
        """
        from sage.rings import arith
        ev = self.eigenvalues

        c2 = self._coefficients.get(2)
        if c2 is not None:
            K = c2.parent()
        else:
            if ev.max_coefficient_in_db() >= 2:
                ev.init_dynamic_properties()
            else:
                raise StopIteration,"Newform does not have eigenvalue a(2)!"
            self._coefficients[2]=ev[2]
            K = ev[2].parent()
        prod = K(1)
        if K.absolute_degree()>1 and K.is_relative():
            KZ = K.base_field()
        else:
            KZ = K
        #emf_logger.debug("K= {0}".format(K))
        F = arith.factor(n)
        for p, r in F:
            #emf_logger.debug("parent_char_val[{0}]={1}".format(p,self.parent.character_used_in_computation.value(p)))
            #emf_logger.debug("char_val[{0}]={1}".format(p,self.character.value(p)))
            (p, r) = (int(p), int(r))
            pr = p**r
            cp = self._coefficients.get(p)
#            emf_logger.debug("c{0} = {1}".format(p,cp))
            if cp is None:
                if ev.has_eigenvalue(p):
                    cp = ev[p]
                elif ev.max_coefficient_in_db() >= p:
                    ev.init_dynamic_properties()
                    cp = ev[p]
            if cp is None:
                raise IndexError,"p={0} is outside the range of computed primes (primes up to {1})! for label:{2}".format(p,max(ev.primes()),self.label)
            if self._coefficients.get(pr) is None:
                if r == 1:
                    c = cp
                else:
                    eps = KZ(self.parent.character_used_in_computation.value(p))
                    # a_{p^r} := a_p * a_{p^{r-1}} - eps(p)p^{k-1} a_{p^{r-2}}
                    apr1 = self.coefficient_n_recursive(pr//p)
                    #ap = self.coefficient_n_recursive(p)
                    k = self.weight
                    apr2 = self.coefficient_n_recursive(pr//(p*p))
                    c = cp*apr1 - eps*(p**(k-1)) * apr2
                    #emf_logger.debug("c({0})={1}".format(pr,c))
                            #ev[pr]=c
                self._coefficients[pr]=c
            prod *= self._coefficients[pr]
        return prod
Exemple #9
0
    def create_key_and_extra_args(self, order, name=None, modulus=None, names=None, impl=None, proof=None, **kwds):
        """
        EXAMPLES::

            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), 'conway', None, '{}', 3, 2, True), {})
            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            ((9, ('a',), 'conway', None, "{'foo': 'value'}", 3, 2, True), {'foo': 'value'})
        """
        from sage.structure.proof.all import WithProof, arithmetic

        if proof is None:
            proof = arithmetic()
        with WithProof("arithmetic", proof):
            order = int(order)
            if order <= 1:
                raise ValueError("the order of a finite field must be > 1.")

            if arith.is_prime(order):
                name = None
                modulus = None
                p = integer.Integer(order)
                n = integer.Integer(1)
            elif arith.is_prime_power(order):
                if not names is None:
                    name = names
                name = normalize_names(1, name)

                p, n = arith.factor(order)[0]

                if modulus is None or modulus == "default":
                    if exists_conway_polynomial(p, n):
                        modulus = "conway"
                    else:
                        if p == 2:
                            modulus = "minimal_weight"
                        else:
                            modulus = "random"
                elif modulus == "random":
                    modulus += str(random.randint(0, 1 << 128))

                if isinstance(modulus, (list, tuple)):
                    modulus = FiniteField(p)["x"](modulus)
                # some classes use 'random' as the modulus to
                # generate a random modulus, but we don't want
                # to cache it
                elif sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):
                    modulus = modulus.change_variable_name("x")
                elif not isinstance(modulus, str):
                    raise ValueError("Modulus parameter not understood.")
            else:  # Neither a prime, nor a prime power
                raise ValueError("the order of a finite field must be a prime power.")

            return (order, name, modulus, impl, str(kwds), p, n, proof), kwds
    def factored_order(self):
        """
        EXAMPLES::

            sage: R = IntegerModRing(18)
            sage: FF = IntegerModRing(17)
            sage: R.factored_order()
            2 * 3^2
            sage: FF.factored_order()
            17
        """
        return factor(self.__order, int_=(self.__order < 2**31))
Exemple #11
0
    def factored_order(self):
        """
        EXAMPLES::

            sage: R = IntegerModRing(18)
            sage: FF = IntegerModRing(17)
            sage: R.factored_order()
            2 * 3^2
            sage: FF.factored_order()
            17
        """
        return factor(self.__order, int_=(self.__order < 2 ** 31))
Exemple #12
0
    def create_key_and_extra_args(self,
                                  order,
                                  name=None,
                                  modulus=None,
                                  names=None,
                                  impl=None,
                                  proof=None,
                                  **kwds):
        """
        EXAMPLES::

            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True), {})
            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            ((9, ('a',), x^2 + 2*x + 2, None, "{'foo': 'value'}", 3, 2, True), {'foo': 'value'})
        """
        from sage.structure.proof.all import WithProof, arithmetic
        if proof is None: proof = arithmetic()
        with WithProof('arithmetic', proof):
            order = int(order)
            if order <= 1:
                raise ValueError("the order of a finite field must be > 1.")

            if arith.is_prime(order):
                name = None
                modulus = None
                p = integer.Integer(order)
                n = integer.Integer(1)
            elif arith.is_prime_power(order):
                if not names is None: name = names
                name = normalize_names(1, name)

                p, n = arith.factor(order)[0]

                if modulus is None or isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    if modulus == "default":  # for backward compatibility
                        modulus = None
                    modulus = GF(p)['x'].irreducible_element(n,
                                                             algorithm=modulus)
                elif isinstance(modulus, (list, tuple)):
                    modulus = GF(p)['x'](modulus)
                elif sage.rings.polynomial.polynomial_element.is_Polynomial(
                        modulus):
                    modulus = modulus.change_variable_name('x')
                else:
                    raise TypeError("wrong type for modulus parameter")
            else:
                raise ValueError(
                    "the order of a finite field must be a prime power.")

            return (order, name, modulus, impl, str(kwds), p, n, proof), kwds
Exemple #13
0
def irred(K, n):
    F = []
    p = K.characteristic()
    for ell, exp in factor(n):
        if ell == 2:
            F.append(rand_irred(K, ell**exp))
        elif ell.divides(p-1):
            F.append(kummer(K, ell, exp))
        elif ell.divides(p+1):
            F.append(cheby(K, ell, exp))
        else:
            F.append(rand_irred(K, ell**exp))

    return reduce(comp_prod, F)
Exemple #14
0
    def factored_order(self):
        """
        EXAMPLES::

            sage: R = IntegerModRing(18)
            sage: FF = IntegerModRing(17)
            sage: R.factored_order()
            2 * 3^2
            sage: FF.factored_order()
            17
        """
        if self.__factored_order is not None:
            return self.__factored_order
        self.__factored_order = factor(self.__order, int_=(self.__order < 2**31))
        return self.__factored_order
Exemple #15
0
def squarefree_part(x):
    """
    Returns the square free part of `x`, i.e., a divisor
    `z` such that `x = z y^2`, for a perfect square
    `y^2`.

    EXAMPLES::

        sage: squarefree_part(100)
        1
        sage: squarefree_part(12)
        3
        sage: squarefree_part(10)
        10
        sage: squarefree_part(216r) # see #8976
        6

    ::

        sage: x = QQ['x'].0
        sage: S = squarefree_part(-9*x*(x-6)^7*(x-3)^2); S
        -9*x^2 + 54*x
        sage: S.factor()
        (-9) * (x - 6) * x

    ::

        sage: f = (x^3 + x + 1)^3*(x-1); f
        x^10 - x^9 + 3*x^8 + 3*x^5 - 2*x^4 - x^3 - 2*x - 1
        sage: g = squarefree_part(f); g
        x^4 - x^3 + x^2 - 1
        sage: g.factor()
        (x - 1) * (x^3 + x + 1)
    """
    try:
        return x.squarefree_part()
    except AttributeError:
        pass
    from sage.rings.arith import factor
    from sage.structure.all import parent
    F = factor(x)
    n = parent(x)(1)
    for p, e in F:
        if e%2 != 0:
            n *= p
    return n * F.unit()
Exemple #16
0
    def factored_unit_order(self):
        """
        Returns a list of Factorization objects, each the factorization of the
        order of the units in a `\ZZ / p^n \ZZ` component of this group (using
        the Chinese Remainder Theorem).

        EXAMPLES::

            sage: R = Integers(8*9*25*17*29)
            sage: R.factored_unit_order()
            [2^2, 2 * 3, 2^2 * 5, 2^4, 2^2 * 7]
        """
        ans = []
        from sage.structure.factorization import Factorization
        for p, e in self.factored_order():
            ans.append(Factorization([(p,e-1)]) * factor(p-1, int_=(self.__order < 2**31)))
        return ans
Exemple #17
0
def squarefree_part(x):
    """
    Returns the square free part of `x`, i.e., a divisor
    `z` such that `x = z y^2`, for a perfect square
    `y^2`.

    EXAMPLES::

        sage: squarefree_part(100)
        1
        sage: squarefree_part(12)
        3
        sage: squarefree_part(10)
        10
        sage: squarefree_part(216r) # see #8976
        6

    ::

        sage: x = QQ['x'].0
        sage: S = squarefree_part(-9*x*(x-6)^7*(x-3)^2); S
        -9*x^2 + 54*x
        sage: S.factor()
        (-9) * (x - 6) * x

    ::

        sage: f = (x^3 + x + 1)^3*(x-1); f
        x^10 - x^9 + 3*x^8 + 3*x^5 - 2*x^4 - x^3 - 2*x - 1
        sage: g = squarefree_part(f); g
        x^4 - x^3 + x^2 - 1
        sage: g.factor()
        (x - 1) * (x^3 + x + 1)
    """
    try:
        return x.squarefree_part()
    except AttributeError:
        pass
    from sage.rings.arith import factor
    from sage.structure.all import parent
    F = factor(x)
    n = parent(x)(1)
    for p, e in F:
        if e%2 != 0:
            n *= p
    return n * F.unit()
Exemple #18
0
    def create_key_and_extra_args(self, order, name=None, modulus=None, names=None,
                                  impl=None, proof=None, **kwds):
        """
        EXAMPLES::

            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True), {})
            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            ((9, ('a',), x^2 + 2*x + 2, None, "{'foo': 'value'}", 3, 2, True), {'foo': 'value'})
        """
        from sage.structure.proof.all import WithProof, arithmetic
        if proof is None: proof = arithmetic()
        with WithProof('arithmetic', proof):
            order = int(order)
            if order <= 1:
                raise ValueError("the order of a finite field must be > 1.")

            if arith.is_prime(order):
                name = None
                modulus = None
                p = integer.Integer(order)
                n = integer.Integer(1)
            elif arith.is_prime_power(order):
                if not names is None: name = names
                name = normalize_names(1,name)

                p, n = arith.factor(order)[0]

                if modulus is None or isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    if modulus == "default":    # for backward compatibility
                        modulus = None
                    modulus = GF(p)['x'].irreducible_element(n, algorithm=modulus)
                elif isinstance(modulus, (list, tuple)):
                    modulus = GF(p)['x'](modulus)
                elif sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):
                    modulus = modulus.change_variable_name('x')
                else:
                    raise TypeError("wrong type for modulus parameter")
            else:
                raise ValueError("the order of a finite field must be a prime power.")

            return (order, name, modulus, impl, str(kwds), p, n, proof), kwds
def clifford_conductor(self):
    """
    This is the product of all primes where the Clifford invariant is -1

    Note: For ternary forms, this is the discriminant of the
    quaternion algebra associated to the quadratic space
    (i.e. the even Clifford algebra)

    EXAMPLES::

        sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5])
        sage: Q.clifford_invariant(2)
        1
        sage: Q.clifford_invariant(37)
        -1
        sage: Q.clifford_conductor()
        37

    ::

        sage: DiagonalQuadraticForm(ZZ, [1, 1, 1]).clifford_conductor()
        2
        sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).clifford_conductor()
        30

    For hyperbolic spaces, the clifford conductor is 1::

        sage: H = QuadraticForm(ZZ, 2, [0, 1, 0])
        sage: H.clifford_conductor()
        1
        sage: (H + H).clifford_conductor()
        1
        sage: (H + H + H).clifford_conductor()
        1
        sage: (H + H + H + H).clifford_conductor()
        1

    """
    D = self.disc()
    return prod([
        x[0] for x in factor(2 * self.level())
        if self.clifford_invariant(x[0]) == -1
    ])
Exemple #20
0
    def other_keys(self, key, K):
        """
        EXAMPLES::

            sage: key, extra = GF.create_key_and_extra_args(9, 'a'); key
            (9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True)
            sage: K = GF.create_object(0, key); K
            Finite Field in a of size 3^2
            sage: GF.other_keys(key, K)
            [(9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True),
             (9, ('a',), x^2 + 2*x + 2, 'givaro', '{}', 3, 2, True)]
        """
        if len(key) == 5:  # backward compat
            order, name, modulus, impl, _ = key
            p, n = arith.factor(order)[0]
            proof = True
        else:
            order, name, modulus, impl, _, p, n, proof = key

        from sage.structure.proof.all import WithProof
        with WithProof('arithmetic', proof):
            if K.degree() > 1:
                modulus = K.modulus().change_variable_name('x')
            new_keys = [(order, name, modulus, impl, _, p, n, proof)]
            from finite_field_prime_modn import FiniteField_prime_modn
            if isinstance(K, FiniteField_prime_modn):
                impl = 'modn'
            elif isinstance(K, FiniteField_givaro):
                impl = 'givaro'
            else:
                from finite_field_ntl_gf2e import FiniteField_ntl_gf2e
                from finite_field_ext_pari import FiniteField_ext_pari
                from finite_field_pari_ffelt import FiniteField_pari_ffelt
                if isinstance(K, FiniteField_ntl_gf2e):
                    impl = 'ntl'
                elif isinstance(K, FiniteField_ext_pari):
                    impl = 'pari_mod'
                elif isinstance(K, FiniteField_pari_ffelt):
                    impl = 'pari_ffelt'
            new_keys.append((order, name, modulus, impl, _, p, n, proof))
            return new_keys
Exemple #21
0
    def other_keys(self, key, K):
        """
        EXAMPLES::

            sage: key, extra = GF.create_key_and_extra_args(9, 'a'); key
            (9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True)
            sage: K = GF.create_object(0, key); K
            Finite Field in a of size 3^2
            sage: GF.other_keys(key, K)
            [(9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True),
             (9, ('a',), x^2 + 2*x + 2, 'givaro', '{}', 3, 2, True)]
        """
        if len(key) == 5: # backward compat
            order, name, modulus, impl, _ = key
            p, n = arith.factor(order)[0]
            proof = True
        else:
            order, name, modulus, impl, _, p, n, proof = key

        from sage.structure.proof.all import WithProof
        with WithProof('arithmetic', proof):
            if K.degree() > 1:
                modulus = K.modulus().change_variable_name('x')
            new_keys = [(order, name, modulus, impl, _, p, n, proof)]
            from finite_field_prime_modn import FiniteField_prime_modn
            if isinstance(K, FiniteField_prime_modn):
                impl = 'modn'
            elif isinstance(K, FiniteField_givaro):
                impl = 'givaro'
            else:
                from finite_field_ntl_gf2e import FiniteField_ntl_gf2e
                from finite_field_ext_pari import FiniteField_ext_pari
                from finite_field_pari_ffelt import FiniteField_pari_ffelt
                if isinstance(K, FiniteField_ntl_gf2e):
                    impl = 'ntl'
                elif isinstance(K, FiniteField_ext_pari):
                    impl = 'pari_mod'
                elif isinstance(K, FiniteField_pari_ffelt):
                    impl = 'pari_ffelt'
            new_keys.append( (order, name, modulus, impl, _, p, n, proof) )
            return new_keys
def clifford_conductor(self):
    """
    This is the product of all primes where the Clifford invariant is -1

    Note: For ternary forms, this is the discriminant of the
    quaternion algebra associated to the quadratic space
    (i.e. the even Clifford algebra)

    EXAMPLES::

        sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5])
        sage: Q.clifford_invariant(2)
        1
        sage: Q.clifford_invariant(37)
        -1
        sage: Q.clifford_conductor()
        37

    ::

        sage: DiagonalQuadraticForm(ZZ, [1, 1, 1]).clifford_conductor()
        2
        sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).clifford_conductor()
        30

    For hyperbolic spaces, the clifford conductor is 1::

        sage: H = QuadraticForm(ZZ, 2, [0, 1, 0])
        sage: H.clifford_conductor()
        1
        sage: (H + H).clifford_conductor()
        1
        sage: (H + H + H).clifford_conductor()
        1
        sage: (H + H + H + H).clifford_conductor()
        1

    """
    D = self.disc()
    return prod(filter(lambda p: self.clifford_invariant(p) == -1,
                       map(lambda x: x[0], factor(2 * self.level()))))
def hasse_conductor(self):
    """
    This is the product of all primes where the Hasse invariant equals -1

    EXAMPLES::

        sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5])
        sage: Q.hasse_invariant(2)
        -1
        sage: Q.hasse_invariant(37)
        -1
        sage: Q.hasse_conductor()
        74

    ::

        sage: DiagonalQuadraticForm(ZZ, [1, 1, 1]).hasse_conductor()
        1
        sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).hasse_conductor()
        10
    """
    D = self.disc()
    return prod([x[0] for x in factor(2 * self.level()) if self.hasse_invariant(x[0]) == -1])
def hasse_conductor(self):
    """
    This is the product of all primes where the Hasse invariant equals -1

    EXAMPLES::

        sage: Q = QuadraticForm(ZZ, 3, [1, 0, -1, 2, -1, 5])
        sage: Q.hasse_invariant(2)
        -1
        sage: Q.hasse_invariant(37)
        -1
        sage: Q.hasse_conductor()
        74

    ::

        sage: DiagonalQuadraticForm(ZZ, [1, 1, 1]).hasse_conductor()
        1
        sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).hasse_conductor()
        10
    """
    D = self.disc()
    return prod(filter(lambda(p):self.hasse_invariant(p)==-1, \
             map(lambda(x):x[0],factor(2*self.level()))))
"""
Example use of the count_finite_algebras tool.

Charlotte Aten ([email protected]) 2016
"""

import sage.all
from count_finite_algebras import *
from sage.rings.arith import factor

print("Dislpay a tuple of all partitions of the natural number `i` from 1 through 6.")
for n in range(1,6):
    print(partition(n))
print("")

print("Display the cycle counts for each partition of 4.")
for part in partition(4):
    print([part,cycle_count(part, 4)])
print("")

print("Display the summand for each of the partitions of 4.")
for part in partition(4):
    print("The summand for {} is {}.".format(part,summand(part,4)))
print("")

print("For `n` from 1 through 10 show the number `c` of isomorphism classes of magmas of order `n`")
print("as well as the prime factorization of `c`.")
for n in range(1,11):
    c = finite_algebra_count(n)
    print((n,c,factor(c)))
def difference_family(v, k, l=1, existence=False, check=True):
    r"""
    Return a (``k``, ``l``)-difference family on an Abelian group of cardinality ``v``.

    Let `G` be a finite Abelian group. For a given subset `D` of `G`, we define
    `\Delta D` to be the multi-set of differences `\Delta D = \{x - y; x \in D,
    y \in D, x \not= y\}`. A `(G,k,\lambda)`-*difference family* is a collection
    of `k`-subsets of `G`, `D = \{D_1, D_2, \ldots, D_b\}` such that the union
    of the difference sets `\Delta D_i` for `i=1,...b`, seen as a multi-set,
    contains each element of `G \backslash \{0\}` exactly `\lambda`-times.

    When there is only one block, i.e. `\lambda(v - 1) = k(k-1)`, then a
    `(G,k,\lambda)`-difference family is also called a *difference set*.

    See also :wikipedia:`Difference_set`.

    If there is no such difference family, an ``EmptySetError`` is raised and if
    there is no construction at the moment ``NotImplementedError`` is raised.

    EXAMPLES::

        sage: K,D = designs.difference_family(73,4)
        sage: D
        [[0, 1, 8, 64],
         [0, 25, 54, 67],
         [0, 41, 36, 69],
         [0, 3, 24, 46],
         [0, 2, 16, 55],
         [0, 50, 35, 61]]

        sage: K,D = designs.difference_family(337,7)
        sage: D
        [[1, 175, 295, 64, 79, 8, 52],
         [326, 97, 125, 307, 142, 249, 102],
         [121, 281, 310, 330, 123, 294, 226],
         [17, 279, 297, 77, 332, 136, 210],
         [150, 301, 103, 164, 55, 189, 49],
         [35, 59, 215, 218, 69, 280, 135],
         [289, 25, 331, 298, 252, 290, 200],
         [191, 62, 66, 92, 261, 180, 159]]

    For `k=6,7` we look at the set of small prime powers for which a
    construction is available::

        sage: def prime_power_mod(r,m):
        ....:     k = m+r
        ....:     while True:
        ....:         if is_prime_power(k):
        ....:             yield k
        ....:         k += m

        sage: from itertools import islice
        sage: l6 = {True:[], False: [], Unknown: []}
        sage: for q in islice(prime_power_mod(1,30), 60):
        ....:     l6[designs.difference_family(q,6,existence=True)].append(q)
        sage: l6[True]
        [31, 121, 151, 181, 211, ...,  3061, 3121, 3181]
        sage: l6[Unknown]
        [61]
        sage: l6[False]
        []

        sage: l7 = {True: [], False: [], Unknown: []}
        sage: for q in islice(prime_power_mod(1,42), 60):
        ....:     l7[designs.difference_family(q,7,existence=True)].append(q)
        sage: l7[True]
        [337, 421, 463, 883, 1723, 3067, 3319, 3529, 3823, 3907, 4621, 4957, 5167]
        sage: l7[Unknown]
        [43, 127, 169, 211, ..., 4999, 5041, 5209]
        sage: l7[False]
        []

    Other constructions for `\lambda > 1`::

        sage: for v in xrange(2,100):
        ....:     constructions = []
        ....:     for k in xrange(2,10):
        ....:         for l in xrange(2,10):
        ....:             if designs.difference_family(v,k,l,existence=True):
        ....:                 constructions.append((k,l))
        ....:                 _ = designs.difference_family(v,k,l)
        ....:     if constructions:
        ....:         print "%2d: %s"%(v, ', '.join('(%d,%d)'%(k,l) for k,l in constructions))
         2: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
         3: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
         4: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
         5: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
         7: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
         8: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
         9: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        11: (3,2), (4,3), (4,6), (5,2), (5,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        13: (3,2), (4,3), (5,4), (5,5), (6,5), (7,6), (8,7), (9,8)
        15: (4,6), (5,6), (7,3)
        16: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        17: (3,2), (4,3), (5,4), (5,5), (6,5), (7,6), (8,7), (9,8)
        19: (3,2), (4,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,4), (9,5), (9,6), (9,7), (9,8)
        21: (4,3), (6,3), (6,5)
        22: (4,2), (6,5), (7,4), (8,8)
        23: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        25: (3,2), (4,3), (5,4), (6,5), (7,6), (7,7), (8,7), (9,8)
        27: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        28: (3,2), (6,5)
        29: (3,2), (4,3), (5,4), (6,5), (7,3), (7,6), (8,4), (8,6), (8,7), (9,8)
        31: (3,2), (4,2), (4,3), (5,2), (5,4), (6,5), (7,6), (8,7), (9,8)
        32: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        33: (5,5), (6,5)
        34: (4,2)
        35: (5,2), (8,4)
        37: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,2), (9,3), (9,8)
        39: (6,5)
        40: (3,2)
        41: (3,2), (4,3), (5,4), (6,3), (6,5), (7,6), (8,7), (9,8)
        43: (3,2), (4,2), (4,3), (5,4), (6,5), (7,2), (7,3), (7,6), (8,4), (8,7), (9,8)
        46: (4,2), (6,2)
        47: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        49: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,3), (9,8)
        51: (5,2), (6,3)
        53: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        55: (9,4)
        57: (7,3)
        59: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        61: (3,2), (4,3), (5,4), (6,2), (6,3), (6,5), (7,6), (8,7), (9,8)
        64: (3,2), (4,3), (5,4), (6,5), (7,2), (7,6), (8,7), (9,8)
        67: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        71: (3,2), (4,3), (5,2), (5,4), (6,5), (7,3), (7,6), (8,4), (8,7), (9,8)
        73: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        75: (5,2)
        79: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        81: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        83: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        85: (7,2), (7,3), (8,2)
        89: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,8)
        97: (3,2), (4,3), (5,4), (6,5), (7,6), (8,7), (9,3), (9,8)

    TESTS:

    Check more of the Wilson constructions from [Wi72]_::

        sage: Q5 = [241, 281,421,601,641, 661, 701, 821,881]
        sage: Q9 = [73, 1153, 1873, 2017]
        sage: Q15 = [76231]
        sage: Q4 = [13, 73, 97, 109, 181, 229, 241, 277, 337, 409, 421, 457]
        sage: Q8 = [1009, 3137, 3697]
        sage: for Q,k in [(Q4,4),(Q5,5),(Q8,8),(Q9,9),(Q15,15)]:
        ....:     for q in Q:
        ....:         assert designs.difference_family(q,k,1,existence=True) is True
        ....:         _ = designs.difference_family(q,k,1)

    Check Singer difference sets::

        sage: sgp = lambda q,d: ((q**(d+1)-1)//(q-1), (q**d-1)//(q-1), (q**(d-1)-1)//(q-1))

        sage: for q in range(2,10):
        ....:     if is_prime_power(q):
        ....:         for d in [2,3,4]:
        ....:           v,k,l = sgp(q,d)
        ....:           assert designs.difference_family(v,k,l,existence=True) is True
        ....:           _ = designs.difference_family(v,k,l)

    Check twin primes difference sets::

        sage: for p in [3,5,7,9,11]:
        ....:     v = p*(p+2); k = (v-1)/2;  lmbda = (k-1)/2
        ....:     G,D = designs.difference_family(v,k,lmbda)

    Check the database:

        sage: from sage.combinat.designs.database import DF
        sage: for v,k,l in DF:
        ....:     df = designs.difference_family(v,k,l,check=True)

    .. TODO::

        Implement recursive constructions from Buratti "Recursive for difference
        matrices and relative difference families" (1998) and Jungnickel
        "Composition theorems for difference families and regular planes" (1978)
    """
    from block_design import are_hyperplanes_in_projective_geometry_parameters

    from database import DF

    if (v, k, l) in DF:
        if existence:
            return True

        vv, blocks = DF[v, k, l].iteritems().next()

        # Build the group
        from sage.rings.finite_rings.integer_mod_ring import Zmod
        if len(vv) == 1:
            G = Zmod(vv[0])
        else:
            from sage.categories.cartesian_product import cartesian_product
            G = cartesian_product([Zmod(i) for i in vv])

        df = [[G(i) for i in b] for b in blocks]

        if check:
            assert is_difference_family(
                G, df, v=v, k=k,
                l=l), "Sage built an invalid ({},{},{})-DF!".format(v, k, l)

        return G, df

    e = k * (k - 1)
    t = l * (v - 1) // e  # number of blocks

    D = None

    factorization = arith.factor(v)

    if len(factorization) == 1:  # i.e. is v a prime power
        from sage.rings.finite_rings.constructor import GF
        G = K = GF(v, 'z')
        x = K.multiplicative_generator()

        if l == (k - 1):
            if existence:
                return True
            return K, K.cyclotomic_cosets(x**((v - 1) // k))[1:]

        if t == 1:
            # some of the difference set constructions VI.18.48 from the
            # Handbook of combinatorial designs
            # q = 3 mod 4
            if v % 4 == 3 and k == (v - 1) // 2:
                if existence:
                    return True
                D = K.cyclotomic_cosets(x**2, [1])

            # q = 4t^2 + 1, t odd
            elif v % 8 == 5 and k == (v - 1) // 4 and arith.is_square(
                (v - 1) // 4):
                if existence:
                    return True
                D = K.cyclotomic_cosets(x**4, [1])

            # q = 4t^2 + 9, t odd
            elif v % 8 == 5 and k == (v + 3) // 4 and arith.is_square(
                (v - 9) // 4):
                if existence:
                    return True
                D = K.cyclotomic_cosets(x**4, [1])
                D[0].insert(0, K.zero())

        if D is None and l == 1:
            one = K.one()

            # Wilson (1972), Theorem 9
            if k % 2 == 1:
                m = (k - 1) // 2
                xx = x**m
                to_coset = {
                    x**i * xx**j: i
                    for i in xrange(m) for j in xrange((v - 1) / m)
                }
                r = x**((v - 1) // k)  # primitive k-th root of unity
                if len(set(to_coset[r**j - one]
                           for j in xrange(1, m + 1))) == m:
                    if existence:
                        return True
                    B = [r**j for j in xrange(k)
                         ]  # = H^((k-1)t) whose difference is
                    # H^(mt) (r^i - 1, i=1,..,m)
                    # Now pick representatives a translate of R for by a set of
                    # representatives of H^m / H^(mt)
                    D = [[x**(i * m) * b for b in B] for i in xrange(t)]

            # Wilson (1972), Theorem 10
            else:
                m = k // 2
                xx = x**m
                to_coset = {
                    x**i * xx**j: i
                    for i in xrange(m) for j in xrange((v - 1) / m)
                }
                r = x**((v - 1) // (k - 1))  # primitive (k-1)-th root of unity
                if (all(to_coset[r**j - one] != 0 for j in xrange(1, m))
                        and len(set(to_coset[r**j - one]
                                    for j in xrange(1, m))) == m - 1):
                    if existence:
                        return True
                    B = [K.zero()] + [r**j for j in xrange(k - 1)]
                    D = [[x**(i * m) * b for b in B] for i in xrange(t)]

            # Wilson (1972), Theorem 11
            if D is None and k == 6:
                r = x**((v - 1) // 3)  # primitive cube root of unity
                r2 = r * r
                xx = x**5
                to_coset = {
                    x**i * xx**j: i
                    for i in xrange(5) for j in xrange((v - 1) / 5)
                }
                for c in to_coset:
                    if c == 1 or c == r or c == r2:
                        continue
                    if len(
                            set(to_coset[elt]
                                for elt in (r - 1, c * (r - 1), c - 1, c - r,
                                            c - r**2))) == 5:
                        if existence:
                            return True
                        B = [one, r, r**2, c, c * r, c * r**2]
                        D = [[x**(i * 5) * b for b in B] for i in xrange(t)]
                        break

    # Twin prime powers construction (see :wikipedia:`Difference_set`)
    #
    # i.e. v = p(p+2) where p and p+2 are prime powers
    #      k = (v-1)/2
    #      lambda = (k-1)/2
    elif (len(factorization) == 2
          and abs(pow(*factorization[0]) - pow(*factorization[1])) == 2
          and k == (v - 1) // 2 and (l is None or 2 * l == (v - 1) // 2 - 1)):

        # A difference set can be built from the set of elements
        # (x,y) in GF(p) x GF(p+2) such that:
        #
        # - either y=0
        # - x and y with x and y     squares
        # - x and y with x and y non-squares
        if existence:
            return True

        from sage.rings.finite_rings.constructor import FiniteField
        from sage.categories.cartesian_product import cartesian_product
        from itertools import product
        p, q = pow(*factorization[0]), pow(*factorization[1])
        if p > q:
            p, q = q, p
        Fp = FiniteField(p, 'x')
        Fq = FiniteField(q, 'x')
        Fpset = set(Fp)
        Fqset = set(Fq)
        Fp_squares = set(x**2 for x in Fpset)
        Fq_squares = set(x**2 for x in Fqset)

        # Pairs of squares, pairs of non-squares
        d = []
        d.extend(
            product(Fp_squares.difference([0]), Fq_squares.difference([0])))
        d.extend(
            product(Fpset.difference(Fp_squares),
                    Fqset.difference(Fq_squares)))

        # All (x,0)
        d.extend((x, 0) for x in Fpset)

        G = cartesian_product([Fp, Fq])
        D = [d]

    if D is None and are_hyperplanes_in_projective_geometry_parameters(
            v, k, l):
        _, (q, d) = are_hyperplanes_in_projective_geometry_parameters(
            v, k, l, True)
        if existence:
            return True
        else:
            G, D = singer_difference_set(q, d)

    if D is None:
        if existence:
            return Unknown
        raise NotImplementedError("No constructions for these parameters")

    if check and not is_difference_family(G, D, verbose=False):
        raise RuntimeError

    return G, D
Exemple #27
0
def O(*x):
    """
    Big O constructor for various types.

    EXAMPLES:

    This is useful for writing power series elements. ::

        sage: R.<t> = ZZ[['t']]
        sage: (1+t)^10 + O(t^5)
        1 + 10*t + 45*t^2 + 120*t^3 + 210*t^4 + O(t^5)

    A power series ring is created implicitly if a polynomial element is passed in. ::

        sage: R.<x> = QQ['x']
        sage: O(x^100)
        O(x^100)
        sage: 1/(1+x+O(x^5))
        1 - x + x^2 - x^3 + x^4 + O(x^5)
        sage: R.<u,v> = QQ[[]]
        sage: 1 + u + v^2 + O(u, v)^5
        1 + u + v^2 + O(u, v)^5

    This is also useful to create p-adic numbers. ::

        sage: O(7^6)
        O(7^6)
        sage: 1/3 + O(7^6)
        5 + 4*7 + 4*7^2 + 4*7^3 + 4*7^4 + 4*7^5 + O(7^6)

    It behaves well with respect to adding negative powers of p::

        sage: a = O(11^-32); a
        O(11^-32)
        sage: a.parent()
        11-adic Field with capped relative precision 20

    There are problems if you add a rational with very negative valuation to a big_oh. ::

        sage: 11^-12 + O(11^15)
        11^-12 + O(11^8)

    The reason that this fails is that the O function doesn't know the right precision cap to use.  If you cast explicitly or use other means of element creation, you can get around this issue. ::

        sage: K = Qp(11, 30)
        sage: K(11^-12) + O(11^15)
        11^-12 + O(11^15)
        sage: 11^-12 + K(O(11^15))
        11^-12 + O(11^15)
        sage: K(11^-12, absprec = 15)
        11^-12 + O(11^15)
        sage: K(11^-12, 15)
        11^-12 + O(11^15)

    """
    if len(x) > 1:
        if isinstance(x[0], multi_power_series_ring_element.MPowerSeries):
            return multi_power_series_ring_element.MO(x)
    x = x[0]

    if isinstance(x, power_series_ring_element.PowerSeries):
        return x.parent()(0, x.degree())

    elif isinstance(x, Polynomial):
        if x.parent().ngens() != 1:
            raise NotImplementedError("completion only currently defined for univariate polynomials")
        if not x.is_monomial():
            raise NotImplementedError("completion only currently defined for the maximal ideal (x)")
        return x.parent().completion(x.parent().gen())(0, x.degree())

    elif isinstance(x, laurent_series_ring_element.LaurentSeries):
        return laurent_series_ring_element.LaurentSeries(x.parent(), 0).add_bigoh(x.valuation())

    elif isinstance(x, (int,long,integer.Integer,rational.Rational)):  # p-adic number
        if x <= 0:
            raise ArithmeticError("x must be a prime power >= 2")
        F = arith.factor(x)
        if len(F) != 1:
            raise ArithmeticError("x must be prime power")
        p, r = F[0]
        if r >= 0:
            return padics_factory.Zp(p, prec = max(r, 20), type = 'capped-rel')(0, absprec = r)
        else:
            return padics_factory.Qp(p, prec = max(r, 20), type = 'capped-rel')(0, absprec = r)

    elif isinstance(x, padic_generic_element.pAdicGenericElement):
         return x.parent()(0, absprec = x.valuation())
    raise ArithmeticError("O(x) not defined")
Exemple #28
0
    def create_object(self, version, key, check_irreducible=True, elem_cache=None,
                      names=None, **kwds):
        """
        EXAMPLES::

            sage: K = GF(19) # indirect doctest
            sage: TestSuite(K).run()
        """
        # IMPORTANT!  If you add a new class to the list of classes
        # that get cached by this factor object, then you *must* add
        # the following method to that class in order to fully support
        # pickling:
        #
        #     def __reduce__(self):   # and include good doctests, please!
        #         return self._factory_data[0].reduce_data(self)
        #
        # This is not in the base class for finite fields, since some finite
        # fields need not be created using this factory object, e.g., residue
        # class fields.

        if len(key) == 5:
            # for backward compatibility of pickles (see trac 10975).
            order, name, modulus, impl, _ = key
            p, n = arith.factor(order)[0]
            proof = True
        else:
            order, name, modulus, impl, _, p, n, proof = key

        if elem_cache is None:
            elem_cache = order < 500

        if n == 1 and (impl is None or impl == 'modn'):
            from finite_field_prime_modn import FiniteField_prime_modn
            # Using a check option here is probably a worthwhile
            # compromise since this constructor is simple and used a
            # huge amount.
            K = FiniteField_prime_modn(order, check=False)
        else:
            # We have to do this with block so that the finite field
            # constructors below will use the proof flag that was
            # passed in when checking for primality, factoring, etc.
            # Otherwise, we would have to complicate all of their
            # constructors with check options (like above).
            from sage.structure.proof.all import WithProof
            with WithProof('arithmetic', proof):
                if check_irreducible and polynomial_element.is_Polynomial(modulus):
                    if modulus.parent().base_ring().characteristic() == 0:
                        modulus = modulus.change_ring(FiniteField(p))
                    if not modulus.is_irreducible():
                        raise ValueError("finite field modulus must be irreducible but it is not.")
                    if modulus.degree() != n:
                        raise ValueError("The degree of the modulus does not correspond to the cardinality of the field.")
                if name is None:
                    raise TypeError("you must specify the generator name.")
                if impl is None:
                    if order < zech_log_bound:
                        # DO *NOT* use for prime subfield, since that would lead to
                        # a circular reference in the call to ParentWithGens in the
                        # __init__ method.
                        impl = 'givaro'
                    elif order % 2 == 0:
                        impl = 'ntl'
                    else:
                        impl = 'pari_ffelt'
                if impl == 'givaro':
                    if kwds.has_key('repr'):
                        repr = kwds['repr']
                    else:
                        repr = 'poly'
                    K = FiniteField_givaro(order, name, modulus, repr=repr, cache=elem_cache)
                elif impl == 'ntl':
                    from finite_field_ntl_gf2e import FiniteField_ntl_gf2e
                    K = FiniteField_ntl_gf2e(order, name, modulus)
                elif impl == 'pari_ffelt':
                    from finite_field_pari_ffelt import FiniteField_pari_ffelt
                    K = FiniteField_pari_ffelt(p, modulus, name)
                elif (impl == 'pari_mod'
                      or impl == 'pari'):    # for unpickling old pickles
                    from finite_field_ext_pari import FiniteField_ext_pari
                    K = FiniteField_ext_pari(order, name, modulus)
                else:
                    raise ValueError("no such finite field implementation: %s" % impl)

            # Temporary; see create_key_and_extra_args() above.
            if kwds.has_key('prefix'):
                K._prefix = kwds['prefix']

        return K
Exemple #29
0
    def create_key_and_extra_args(self, order, name=None, modulus=None, names=None,
                                  impl=None, proof=None, **kwds):
        """
        EXAMPLES::

            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True), {})
            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            ((9, ('a',), x^2 + 2*x + 2, None, "{'foo': 'value'}", 3, 2, True), {'foo': 'value'})
        """
        from sage.structure.proof.all import WithProof, arithmetic
        if proof is None: proof = arithmetic()
        with WithProof('arithmetic', proof):
            order = int(order)
            if order <= 1:
                raise ValueError("the order of a finite field must be > 1.")

            if arith.is_prime(order):
                name = None
                modulus = None
                p = integer.Integer(order)
                n = integer.Integer(1)
            elif arith.is_prime_power(order):
                if not names is None: name = names
                name = normalize_names(1,name)

                p, n = arith.factor(order)[0]

                # The following is a temporary solution that allows us
                # to construct compatible systems of finite fields
                # until algebraic closures of finite fields are
                # implemented in Sage.  It requires the user to
                # specify two parameters:
                #
                # - `conway` -- boolean; if True, this field is
                #   constructed to fit in a compatible system using
                #   a Conway polynomial.
                # - `prefix` -- a string used to generate names for
                #   automatically constructed finite fields
                #
                # See the docstring of FiniteFieldFactory for examples.
                #
                # Once algebraic closures of finite fields are
                # implemented, this syntax should be superseded by
                # something like the following:
                #
                #     sage: Fpbar = GF(5).algebraic_closure('z')
                #     sage: F, e = Fpbar.subfield(3)  # e is the embedding into Fpbar
                #     sage: F
                #     Finite field in z3 of size 5^3
                #
                # This temporary solution only uses actual Conway
                # polynomials (no pseudo-Conway polynomials), since
                # pseudo-Conway polynomials are not unique, and until
                # we have algebraic closures of finite fields, there
                # is no good place to store a specific choice of
                # pseudo-Conway polynomials.
                if name is None:
                    if not (kwds.has_key('conway') and kwds['conway']):
                        raise ValueError("parameter 'conway' is required if no name given")
                    if not kwds.has_key('prefix'):
                        raise ValueError("parameter 'prefix' is required if no name given")
                    name = kwds['prefix'] + str(n)

                if kwds.has_key('conway') and kwds['conway']:
                    from conway_polynomials import conway_polynomial
                    if not kwds.has_key('prefix'):
                        raise ValueError("a prefix must be specified if conway=True")
                    if modulus is not None:
                        raise ValueError("no modulus may be specified if conway=True")
                    # The following raises a RuntimeError if no polynomial is found.
                    modulus = conway_polynomial(p, n)

                if modulus is None or isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    if modulus == "default":    # for backward compatibility
                        modulus = None
                    modulus = GF(p)['x'].irreducible_element(n, algorithm=modulus)
                elif isinstance(modulus, (list, tuple)):
                    modulus = GF(p)['x'](modulus)
                elif sage.rings.polynomial.polynomial_element.is_Polynomial(modulus):
                    modulus = modulus.change_variable_name('x')
                else:
                    raise TypeError("wrong type for modulus parameter")
            else:
                raise ValueError("the order of a finite field must be a prime power.")

            return (order, name, modulus, impl, str(kwds), p, n, proof), kwds
Exemple #30
0
def difference_family(v, k, l=1, existence=False, explain_construction=False, check=True):
    r"""
    Return a (``k``, ``l``)-difference family on an Abelian group of cardinality ``v``.

    Let `G` be a finite Abelian group. For a given subset `D` of `G`, we define
    `\Delta D` to be the multi-set of differences `\Delta D = \{x - y; x \in D,
    y \in D, x \not= y\}`. A `(G,k,\lambda)`-*difference family* is a collection
    of `k`-subsets of `G`, `D = \{D_1, D_2, \ldots, D_b\}` such that the union
    of the difference sets `\Delta D_i` for `i=1,...b`, seen as a multi-set,
    contains each element of `G \backslash \{0\}` exactly `\lambda`-times.

    When there is only one block, i.e. `\lambda(v - 1) = k(k-1)`, then a
    `(G,k,\lambda)`-difference family is also called a *difference set*.

    See also :wikipedia:`Difference_set`.

    If there is no such difference family, an ``EmptySetError`` is raised and if
    there is no construction at the moment ``NotImplementedError`` is raised.

    INPUT:

    - ``v,k,l`` -- parameters of the difference family. If ``l`` is not provided
      it is assumed to be ``1``.

    - ``existence`` -- if ``True``, then return either ``True`` if Sage knows
      how to build such design, ``Unknown`` if it does not and ``False`` if it
      knows that the design does not exist..

    - ``explain_construction`` -- instead of returning a difference family,
      returns a string that explains the construction used.

    - ``check`` -- boolean (default: ``True``). If ``True`` then the result of
      the computation is checked before being returned. This should not be
      needed but ensures that the output is correct.

    OUTPUT:

    A pair ``(G,D)`` made of a group `G` and a difference family `D` on that
    group. Or, if ``existence`` is ``True`` a troolean or if
    ``explain_construction`` is ``True`` a string.

    EXAMPLES::

        sage: G,D = designs.difference_family(73,4)
        sage: G
        Finite Field of size 73
        sage: D
        [[0, 1, 8, 64],
         [0, 2, 16, 55],
         [0, 3, 24, 46],
         [0, 25, 54, 67],
         [0, 35, 50, 61],
         [0, 36, 41, 69]]
        sage: print designs.difference_family(73, 4, explain_construction=True)
        Radical difference family on a finite field

        sage: G,D = designs.difference_family(15,7,3)
        sage: G
        The cartesian product of (Finite Field of size 3, Finite Field of size 5)
        sage: D
        [[(1, 1), (1, 4), (2, 2), (2, 3), (0, 0), (1, 0), (2, 0)]]
        sage: print designs.difference_family(15,7,3,explain_construction=True)
        Twin prime powers difference family

        sage: print designs.difference_family(91,10,1,explain_construction=True)
        Singer difference set

    For `k=6,7` we look at the set of small prime powers for which a
    construction is available::

        sage: def prime_power_mod(r,m):
        ....:     k = m+r
        ....:     while True:
        ....:         if is_prime_power(k):
        ....:             yield k
        ....:         k += m

        sage: from itertools import islice
        sage: l6 = {True:[], False: [], Unknown: []}
        sage: for q in islice(prime_power_mod(1,30), 60):
        ....:     l6[designs.difference_family(q,6,existence=True)].append(q)
        sage: l6[True]
        [31, 121, 151, 181, 211, ...,  3061, 3121, 3181]
        sage: l6[Unknown]
        [61]
        sage: l6[False]
        []

        sage: l7 = {True: [], False: [], Unknown: []}
        sage: for q in islice(prime_power_mod(1,42), 60):
        ....:     l7[designs.difference_family(q,7,existence=True)].append(q)
        sage: l7[True]
        [337, 421, 463, 883, 1723, 3067, 3319, 3529, 3823, 3907, 4621, 4957, 5167]
        sage: l7[Unknown]
        [43, 127, 169, 211, ..., 4999, 5041, 5209]
        sage: l7[False]
        []

    List available constructions::

        sage: for v in xrange(2,100):
        ....:     constructions = []
        ....:     for k in xrange(2,10):
        ....:         for l in xrange(1,10):
        ....:             if designs.difference_family(v,k,l,existence=True):
        ....:                 constructions.append((k,l))
        ....:                 _ = designs.difference_family(v,k,l)
        ....:     if constructions:
        ....:         print "%2d: %s"%(v, ', '.join('(%d,%d)'%(k,l) for k,l in constructions))
         3: (2,1)
         4: (3,2)
         5: (2,1), (4,3)
         6: (5,4)
         7: (2,1), (3,1), (3,2), (4,2), (6,5)
         8: (7,6)
         9: (2,1), (4,3), (8,7)
        10: (9,8)
        11: (2,1), (4,6), (5,2), (5,4), (6,3)
        13: (2,1), (3,1), (3,2), (4,1), (4,3), (5,5), (6,5)
        15: (3,1), (4,6), (5,6), (7,3)
        16: (3,2), (5,4), (6,2)
        17: (2,1), (4,3), (5,5), (8,7)
        19: (2,1), (3,1), (3,2), (4,2), (6,5), (9,4), (9,8)
        21: (3,1), (4,3), (5,1), (6,3), (6,5)
        22: (4,2), (6,5), (7,4), (8,8)
        23: (2,1)
        25: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (7,7), (8,7)
        27: (2,1), (3,1)
        28: (3,2), (6,5)
        29: (2,1), (4,3), (7,3), (7,6), (8,4), (8,6)
        31: (2,1), (3,1), (3,2), (4,2), (5,2), (5,4), (6,1), (6,5)
        33: (3,1), (5,5), (6,5)
        34: (4,2)
        35: (5,2)
        37: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (9,2), (9,8)
        39: (3,1), (6,5)
        40: (3,2), (4,1)
        41: (2,1), (4,3), (5,1), (5,4), (6,3), (8,7)
        43: (2,1), (3,1), (3,2), (4,2), (6,5), (7,2), (7,3), (7,6), (8,4)
        45: (3,1), (5,1)
        46: (4,2), (6,2)
        47: (2,1)
        49: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (8,7), (9,3)
        51: (3,1), (5,2), (6,3)
        52: (4,1)
        53: (2,1), (4,3)
        55: (3,1), (9,4)
        57: (3,1), (7,3), (8,1)
        59: (2,1)
        61: (2,1), (3,1), (3,2), (4,3), (5,1), (5,4), (6,2), (6,3), (6,5)
        63: (3,1)
        64: (3,2), (4,1), (7,2), (7,6), (9,8)
        65: (5,1)
        67: (2,1), (3,1), (3,2), (6,5)
        69: (3,1)
        71: (2,1), (5,2), (5,4), (7,3), (7,6), (8,4)
        73: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (8,7), (9,1), (9,8)
        75: (3,1), (5,2)
        76: (4,1)
        79: (2,1), (3,1), (3,2), (6,5)
        81: (2,1), (3,1), (4,3), (5,1), (5,4), (8,7)
        83: (2,1)
        85: (4,1), (7,2), (7,3), (8,2)
        89: (2,1), (4,3), (8,7)
        91: (6,1)
        97: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (8,7), (9,3)

    TESTS:

    Check more of the Wilson constructions from [Wi72]_::

        sage: Q5 = [241, 281,421,601,641, 661, 701, 821,881]
        sage: Q9 = [73, 1153, 1873, 2017]
        sage: Q15 = [76231]
        sage: Q4 = [13, 73, 97, 109, 181, 229, 241, 277, 337, 409, 421, 457]
        sage: Q8 = [1009, 3137, 3697]
        sage: for Q,k in [(Q4,4),(Q5,5),(Q8,8),(Q9,9),(Q15,15)]:
        ....:     for q in Q:
        ....:         assert designs.difference_family(q,k,1,existence=True) is True
        ....:         _ = designs.difference_family(q,k,1)

    Check Singer difference sets::

        sage: sgp = lambda q,d: ((q**(d+1)-1)//(q-1), (q**d-1)//(q-1), (q**(d-1)-1)//(q-1))

        sage: for q in range(2,10):
        ....:     if is_prime_power(q):
        ....:         for d in [2,3,4]:
        ....:           v,k,l = sgp(q,d)
        ....:           assert designs.difference_family(v,k,l,existence=True) is True
        ....:           _ = designs.difference_family(v,k,l)

    Check twin primes difference sets::

        sage: for p in [3,5,7,9,11]:
        ....:     v = p*(p+2); k = (v-1)/2;  lmbda = (k-1)/2
        ....:     G,D = designs.difference_family(v,k,lmbda)

    Check the database:

        sage: from sage.combinat.designs.database import DF
        sage: for v,k,l in DF:
        ....:     df = designs.difference_family(v,k,l,check=True)

    Check a failing construction (:trac:`17528`):

        sage: designs.difference_family(9,3)
        Traceback (most recent call last):
        ...
        NotImplementedError: No construction available for (9,3,1)-difference family

    .. TODO::

        Implement recursive constructions from Buratti "Recursive for difference
        matrices and relative difference families" (1998) and Jungnickel
        "Composition theorems for difference families and regular planes" (1978)
    """
    from block_design import are_hyperplanes_in_projective_geometry_parameters

    from database import DF

    if (v,k,l) in DF:
        if existence:
            return True
        elif explain_construction:
            return "The database contains a ({},{},{})-difference family".format(v,k,l)

        vv, blocks = next(DF[v,k,l].iteritems())

        # Build the group
        from sage.rings.finite_rings.integer_mod_ring import Zmod
        if len(vv) == 1:
            G = Zmod(vv[0])
        else:
            from sage.categories.cartesian_product import cartesian_product
            G = cartesian_product([Zmod(i) for i in vv])

        df = [[G(i) for i in b] for b in blocks]

        if check and not is_difference_family(G, df, v=v, k=k, l=l):
            raise RuntimeError("There is an invalid ({},{},{})-difference "
                    "family in the database... Please contact "
                    "*****@*****.**".format(v,k,l))

        return G,df

    e = k*(k-1)
    if (l*(v-1)) % e:
        if existence:
            return Unknown
        raise NotImplementedError("No construction available for ({},{},{})-difference family".format(v,k,l))
    t = l*(v-1) // e  # number of blocks

    # trivial construction
    if k == (v-1) and l == (v-2):
        from sage.rings.finite_rings.integer_mod_ring import Zmod
        G = Zmod(v)
        return G, [range(1,v)]

    factorization = arith.factor(v)
    D = None

    if len(factorization) == 1:  # i.e. is v a prime power
        from sage.rings.finite_rings.constructor import GF
        G = K = GF(v,'z')

        if radical_difference_family(K, k, l, existence=True):
            if existence:
                return True
            elif explain_construction:
                return "Radical difference family on a finite field"
            else:
                D = radical_difference_family(K,k,l)

        elif l == 1 and k == 6 and df_q_6_1(K,existence=True):
            if existence:
                return True
            elif explain_construction:
                return "Wilson 1972 difference family made from the union of two cyclotomic cosets"
            else:
                D = df_q_6_1(K)

    # Twin prime powers construction
    # i.e. v = p(p+2) where p and p+2 are prime powers
    #      k = (v-1)/2
    #      lambda = (k-1)/2 (ie 2l+1 = k)
    elif (k == (v-1)//2 and
          l == (k-1)//2 and
          len(factorization) == 2 and
          abs(pow(*factorization[0]) - pow(*factorization[1])) == 2):
        if existence:
            return True
        elif explain_construction:
            return "Twin prime powers difference family"
        else:
            p = pow(*factorization[0])
            q = pow(*factorization[1])
            if p > q:
                p,q = q,p
            G,D = twin_prime_powers_difference_set(p,check=False)

    if D is None and are_hyperplanes_in_projective_geometry_parameters(v,k,l):
        _, (q,d) = are_hyperplanes_in_projective_geometry_parameters(v,k,l,True)
        if existence:
            return True
        elif explain_construction:
            return "Singer difference set"
        else:
            G,D = singer_difference_set(q,d)

    if D is None:
        if existence:
            return Unknown
        raise NotImplementedError("No constructions for these parameters")

    if check and not is_difference_family(G,D,v=v,k=k,l=l,verbose=False):
        raise RuntimeError("There is a problem. Sage built the following "
                "difference family on G='{}' with parameters ({},{},{}):\n "
                "{}\nwhich seems to not be a difference family... "
                "Please contact [email protected]".format(G,v,k,l,D))

    return G, D
Exemple #31
0
def CohenOesterle(eps, k):
    r"""
    Compute the Cohen-Oesterle function associate to eps, `k`.
    This is a summand in the formula for the dimension of the space of
    cusp forms of weight `2` with character
    `\varepsilon`.
    
    INPUT:
    
    
    -  ``eps`` - Dirichlet character
    
    -  ``k`` - integer
    
    
    OUTPUT: element of the base ring of eps.
    
    EXAMPLES::
    
        sage: G.<eps> = DirichletGroup(7)
        sage: sage.modular.dims.CohenOesterle(eps, 2)
        -2/3
        sage: sage.modular.dims.CohenOesterle(eps, 4)
        -1
    """
    N = eps.modulus()
    facN = factor(N)
    f = eps.conductor()
    gamma_k = 0
    if k % 4 == 2:
        gamma_k = frac(-1, 4)
    elif k % 4 == 0:
        gamma_k = frac(1, 4)
    mu_k = 0
    if k % 3 == 2:
        mu_k = frac(-1, 3)
    elif k % 3 == 0:
        mu_k = frac(1, 3)

    def _lambda(r, s, p):
        """
        Used internally by the CohenOesterle function.
        
        INPUT:
        
        
        -  ``r, s, p`` - integers
        
        
        OUTPUT: Integer
        
        EXAMPLES: (indirect doctest)
        
        ::
        
            sage: K = CyclotomicField(3)
            sage: eps = DirichletGroup(7*43,K).0^2
            sage: sage.modular.dims.CohenOesterle(eps,2)
            -4/3
        """
        if 2 * s <= r:
            if r % 2 == 0:
                return p**(r // 2) + p**((r // 2) - 1)
            return 2 * p**((r - 1) // 2)
        return 2 * (p**(r - s))

    #end def of lambda
    K = eps.base_ring()
    return K(frac(-1,2) * mul([_lambda(r,valuation(f,p),p) for p, r in facN]) + \
               gamma_k * mul([CO_delta(r,p,N,eps)         for p, r in facN]) + \
                mu_k    * mul([CO_nu(r,p,N,eps)            for p, r in facN]))
Exemple #32
0
    def create_object(self,
                      version,
                      key,
                      check_irreducible=True,
                      elem_cache=None,
                      names=None,
                      **kwds):
        """
        EXAMPLES::
        
            sage: K = GF(19)
            sage: TestSuite(K).run()
        """
        # IMPORTANT!  If you add a new class to the list of classes
        # that get cached by this factor object, then you *must* add
        # the following method to that class in order to fully support
        # pickling:
        #
        #     def __reduce__(self):   # and include good doctests, please!
        #         return self._factory_data[0].reduce_data(self)
        #
        # This is not in the base class for finite fields, since some finite
        # fields need not be created using this factory object, e.g., residue
        # class fields.

        if len(key) == 5:
            # for backward compatibility of pickles (see trac 10975).
            order, name, modulus, impl, _ = key
            p, n = arith.factor(order)[0]
            proof = True
        else:
            order, name, modulus, impl, _, p, n, proof = key

        if isinstance(modulus, str) and modulus.startswith("random"):
            modulus = "random"

        if elem_cache is None:
            elem_cache = order < 500

        if n == 1 and (impl is None or impl == 'modn'):
            from finite_field_prime_modn import FiniteField_prime_modn
            # Using a check option here is probably a worthwhile
            # compromise since this constructor is simple and used a
            # huge amount.
            K = FiniteField_prime_modn(order, check=False, **kwds)
        else:
            # We have to do this with block so that the finite field
            # constructors below will use the proof flag that was
            # passed in when checking for primality, factoring, etc.
            # Otherwise, we would have to complicate all of their
            # constructors with check options (like above).
            from sage.structure.proof.all import WithProof
            with WithProof('arithmetic', proof):
                if check_irreducible and polynomial_element.is_Polynomial(
                        modulus):
                    if modulus.parent().base_ring().characteristic() == 0:
                        modulus = modulus.change_ring(FiniteField(p))
                    if not modulus.is_irreducible():
                        raise ValueError(
                            "finite field modulus must be irreducible but it is not."
                        )
                    if modulus.degree() != n:
                        raise ValueError(
                            "The degree of the modulus does not correspond to the cardinality of the field."
                        )
                if name is None:
                    raise TypeError("you must specify the generator name.")
                if order < zech_log_bound:
                    # DO *NOT* use for prime subfield, since that would lead to
                    # a circular reference in the call to ParentWithGens in the
                    # __init__ method.
                    K = FiniteField_givaro(order,
                                           name,
                                           modulus,
                                           cache=elem_cache,
                                           **kwds)
                else:
                    if order % 2 == 0 and (impl is None or impl == 'ntl'):
                        from element_ntl_gf2e import FiniteField_ntl_gf2e
                        K = FiniteField_ntl_gf2e(order, name, modulus, **kwds)
                    else:
                        from finite_field_ext_pari import FiniteField_ext_pari
                        K = FiniteField_ext_pari(order, name, modulus, **kwds)

        return K
Exemple #33
0
def O(*x):
    """
    Big O constructor for various types.

    EXAMPLES:

    This is useful for writing power series elements. ::

        sage: R.<t> = ZZ[['t']]
        sage: (1+t)^10 + O(t^5)
        1 + 10*t + 45*t^2 + 120*t^3 + 210*t^4 + O(t^5)

    A power series ring is created implicitly if a polynomial element is passed in. ::

        sage: R.<x> = QQ['x']
        sage: O(x^100)
        O(x^100)
        sage: 1/(1+x+O(x^5))
        1 - x + x^2 - x^3 + x^4 + O(x^5)
        sage: R.<u,v> = QQ[[]]
        sage: 1 + u + v^2 + O(u, v)^5
        1 + u + v^2 + O(u, v)^5

    This is also useful to create p-adic numbers. ::

        sage: O(7^6)
        O(7^6)
        sage: 1/3 + O(7^6)
        5 + 4*7 + 4*7^2 + 4*7^3 + 4*7^4 + 4*7^5 + O(7^6)

    It behaves well with respect to adding negative powers of p::

        sage: a = O(11^-32); a
        O(11^-32)
        sage: a.parent()
        11-adic Field with capped relative precision 20

    There are problems if you add a rational with very negative valuation to a big_oh. ::

        sage: 11^-12 + O(11^15)
        11^-12 + O(11^8)

    The reason that this fails is that the O function doesn't know the right precision cap to use.  If you cast explicitly or use other means of element creation, you can get around this issue. ::

        sage: K = Qp(11, 30)
        sage: K(11^-12) + O(11^15)
        11^-12 + O(11^15)
        sage: 11^-12 + K(O(11^15))
        11^-12 + O(11^15)
        sage: K(11^-12, absprec = 15)
        11^-12 + O(11^15)
        sage: K(11^-12, 15)
        11^-12 + O(11^15)

    """
    if len(x) > 1:
        if isinstance(x[0], multi_power_series_ring_element.MPowerSeries):
            return multi_power_series_ring_element.MO(x)
    x = x[0]

    if isinstance(x, power_series_ring_element.PowerSeries):
        return x.parent()(0, x.degree())

    elif isinstance(x, Polynomial):
        if x.parent().ngens() != 1:
            raise NotImplementedError(
                "completion only currently defined for univariate polynomials")
        if not x.is_monomial():
            raise NotImplementedError(
                "completion only currently defined for the maximal ideal (x)")
        return x.parent().completion(x.parent().gen())(0, x.degree())

    elif isinstance(x, laurent_series_ring_element.LaurentSeries):
        return laurent_series_ring_element.LaurentSeries(
            x.parent(), 0).add_bigoh(x.valuation())

    elif isinstance(
            x,
        (int, long, integer.Integer, rational.Rational)):  # p-adic number
        if x <= 0:
            raise ArithmeticError("x must be a prime power >= 2")
        F = arith.factor(x)
        if len(F) != 1:
            raise ArithmeticError("x must be prime power")
        p, r = F[0]
        if r >= 0:
            return padics_factory.Zp(p, prec=max(r, 20),
                                     type='capped-rel')(0, absprec=r)
        else:
            return padics_factory.Qp(p, prec=max(r, 20),
                                     type='capped-rel')(0, absprec=r)

    elif isinstance(x, padic_generic_element.pAdicGenericElement):
        return x.parent()(0, absprec=x.valuation())
    raise ArithmeticError("O(x) not defined")
Exemple #34
0
    def create_key_and_extra_args(self,
                                  order,
                                  name=None,
                                  modulus=None,
                                  names=None,
                                  impl=None,
                                  proof=None,
                                  **kwds):
        """
        EXAMPLES::

            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), x^2 + 2*x + 2, None, '{}', 3, 2, True), {})
            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            ((9, ('a',), x^2 + 2*x + 2, None, "{'foo': 'value'}", 3, 2, True), {'foo': 'value'})
        """
        from sage.structure.proof.all import WithProof, arithmetic
        if proof is None: proof = arithmetic()
        with WithProof('arithmetic', proof):
            order = int(order)
            if order <= 1:
                raise ValueError("the order of a finite field must be > 1.")

            if arith.is_prime(order):
                name = None
                modulus = None
                p = integer.Integer(order)
                n = integer.Integer(1)
            elif arith.is_prime_power(order):
                if not names is None: name = names
                name = normalize_names(1, name)

                p, n = arith.factor(order)[0]

                # The following is a temporary solution that allows us
                # to construct compatible systems of finite fields
                # until algebraic closures of finite fields are
                # implemented in Sage.  It requires the user to
                # specify two parameters:
                #
                # - `conway` -- boolean; if True, this field is
                #   constructed to fit in a compatible system using
                #   a Conway polynomial.
                # - `prefix` -- a string used to generate names for
                #   automatically constructed finite fields
                #
                # See the docstring of FiniteFieldFactory for examples.
                #
                # Once algebraic closures of finite fields are
                # implemented, this syntax should be superseded by
                # something like the following:
                #
                #     sage: Fpbar = GF(5).algebraic_closure('z')
                #     sage: F, e = Fpbar.subfield(3)  # e is the embedding into Fpbar
                #     sage: F
                #     Finite field in z3 of size 5^3
                #
                # This temporary solution only uses actual Conway
                # polynomials (no pseudo-Conway polynomials), since
                # pseudo-Conway polynomials are not unique, and until
                # we have algebraic closures of finite fields, there
                # is no good place to store a specific choice of
                # pseudo-Conway polynomials.
                if name is None:
                    if not (kwds.has_key('conway') and kwds['conway']):
                        raise ValueError(
                            "parameter 'conway' is required if no name given")
                    if not kwds.has_key('prefix'):
                        raise ValueError(
                            "parameter 'prefix' is required if no name given")
                    name = kwds['prefix'] + str(n)

                if kwds.has_key('conway') and kwds['conway']:
                    from conway_polynomials import conway_polynomial
                    if not kwds.has_key('prefix'):
                        raise ValueError(
                            "a prefix must be specified if conway=True")
                    if modulus is not None:
                        raise ValueError(
                            "no modulus may be specified if conway=True")
                    # The following raises a RuntimeError if no polynomial is found.
                    modulus = conway_polynomial(p, n)

                if modulus is None or isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    if modulus == "default":  # for backward compatibility
                        modulus = None
                    modulus = GF(p)['x'].irreducible_element(n,
                                                             algorithm=modulus)
                elif isinstance(modulus, (list, tuple)):
                    modulus = GF(p)['x'](modulus)
                elif sage.rings.polynomial.polynomial_element.is_Polynomial(
                        modulus):
                    modulus = modulus.change_variable_name('x')
                else:
                    raise TypeError("wrong type for modulus parameter")
            else:
                raise ValueError(
                    "the order of a finite field must be a prime power.")

            return (order, name, modulus, impl, str(kwds), p, n, proof), kwds
Exemple #35
0
def mutually_orthogonal_latin_squares(n,k=None, partitions = False):
    r"""
    Returns `k` Mutually Orthogonal `n\times n` Latin Squares (MOLS).

    For more information on Latin Squares and MOLS, see
    :mod:`~sage.combinat.designs.latin_squares` or the :wikipedia:`Latin_square`,
    or even the
    :wikipedia:`Wikipedia entry on MOLS <Graeco-Latin_square#Mutually_orthogonal_Latin_squares>`.

    INPUT:

    - ``n`` (integer) -- size of the latin square.

    - ``k`` (integer) -- returns `k` MOLS. If set to ``None`` (default), returns
      the maximum number of MOLS that Sage can build.

      .. WARNING::

          This has no reason to be the maximum number of `n\times n` MOLS, just
          the best Sage can do !

    - ``partition`` (boolean) -- a Latin Square can be seen as 3 partitions of
      the `n^2` cells of the array into `n` sets of size `n`, respectively :

      * The partition of rows
      * The partition of columns
      * The partition of number (cells numbered with 0, cells numbered with 1,
        ...)

      These partitions have the additional property that any two sets from
      different partitions intersect on exactly one element.

      When ``partition`` is set to ``True``, this function returns a list of `k+2`
      partitions satisfying this intersection property instead of the `k+2` MOLS
      (though the data is exactly the same in both cases).

    EXAMPLES::

        sage: designs.mutually_orthogonal_latin_squares(5)
        [
        [0 1 2 3 4]  [0 1 2 3 4]  [0 1 2 3 4]  [0 1 2 3 4]
        [3 0 1 4 2]  [4 3 0 2 1]  [1 2 4 0 3]  [2 4 3 1 0]
        [4 3 0 2 1]  [1 2 4 0 3]  [2 4 3 1 0]  [3 0 1 4 2]
        [1 2 4 0 3]  [2 4 3 1 0]  [3 0 1 4 2]  [4 3 0 2 1]
        [2 4 3 1 0], [3 0 1 4 2], [4 3 0 2 1], [1 2 4 0 3]
        ]
        sage: designs.mutually_orthogonal_latin_squares(7,3)
        [
        [0 1 2 3 4 5 6]  [0 1 2 3 4 5 6]  [0 1 2 3 4 5 6]
        [4 0 3 1 6 2 5]  [5 6 0 4 2 1 3]  [6 4 1 0 5 3 2]
        [5 6 0 4 2 1 3]  [6 4 1 0 5 3 2]  [1 3 5 2 0 6 4]
        [6 4 1 0 5 3 2]  [1 3 5 2 0 6 4]  [2 5 4 6 3 0 1]
        [1 3 5 2 0 6 4]  [2 5 4 6 3 0 1]  [3 2 6 5 1 4 0]
        [2 5 4 6 3 0 1]  [3 2 6 5 1 4 0]  [4 0 3 1 6 2 5]
        [3 2 6 5 1 4 0], [4 0 3 1 6 2 5], [5 6 0 4 2 1 3]
        ]
        sage: designs.mutually_orthogonal_latin_squares(5,2,partitions=True)
        [[[0, 1, 2, 3, 4],
          [5, 6, 7, 8, 9],
          [10, 11, 12, 13, 14],
          [15, 16, 17, 18, 19],
          [20, 21, 22, 23, 24]],
         [[0, 5, 10, 15, 20],
          [1, 6, 11, 16, 21],
          [2, 7, 12, 17, 22],
          [3, 8, 13, 18, 23],
          [4, 9, 14, 19, 24]],
        [[0, 6, 12, 18, 24],
          [1, 7, 14, 15, 23],
          [2, 9, 13, 16, 20],
          [3, 5, 11, 19, 22],
          [4, 8, 10, 17, 21]],
        [[0, 7, 13, 19, 21],
          [1, 9, 10, 18, 22],
          [2, 8, 11, 15, 24],
          [3, 6, 14, 17, 20],
          [4, 5, 12, 16, 23]]]

    TESTS::

        sage: designs.mutually_orthogonal_latin_squares(5,5)
        Traceback (most recent call last):
        ...
        ValueError: There exist at most n-1 MOLS of size n.
    """
    from sage.rings.finite_rings.constructor import FiniteField
    from sage.combinat.designs.block_design import AffineGeometryDesign
    from sage.rings.arith import is_prime_power
    from sage.matrix.constructor import Matrix
    from sage.rings.arith import factor

    if k is not None and k >= n:
        raise ValueError("There exist at most n-1 MOLS of size n.")

    if is_prime_power(n):
        if k is None:
            k = n-1
        # Section 6.4.1 of [Stinson2004]
        Fp = FiniteField(n,'x')
        B = AffineGeometryDesign(2,1,Fp).blocks()
        parallel_classes = [[] for _ in range(k+2)]
        for b in B:
            for p in parallel_classes:
                if (not p) or all(i not in p[0] for i in b):
                    p.append(b)
                    break

        if partitions:
            return parallel_classes

        coord = {v:i
                 for i,L in enumerate(parallel_classes[0]) for v in L}
        coord = {v:(coord[v],i)
                 for i,L in enumerate(parallel_classes[1]) for v in L}

        matrices = []
        for P in parallel_classes[2:]:
            matrices.append(Matrix({coord[v]:i for i,L in enumerate(P) for v in L }))
        return matrices
    else:
        # Theorem 6.33 of [Stinson2004], MacNeish's theorem.
        subcases = [p**i for p,i in factor(n)]
        s = min(subcases)-1
        if k is None:
            k = s
        elif k > s:
            raise NotImplementedError("I don't know how to build these MOLS.")
        subcalls = [mutually_orthogonal_latin_squares(p,k) for p in subcases]
        matrices = [latin_square_product(*[sc[i] for sc in subcalls])
                    for i in range(k)]

        if partitions:
            partitions = [[[i*n+j for j in range(n)] for i in range(n)],
                          [[j*n+i for j in range(n)] for i in range(n)]]
            for m in matrices:
                partition = [[] for i in range(n)]
                for i in range(n):
                    for j in range(n):
                        partition[m[i,j]].append(i*n+j)
                partitions.append(partition)

            return partitions

        else:
            return matrices
Exemple #36
0
def CohenOesterle(eps, k):
    r"""
    Compute the Cohen-Oesterle function associate to eps, `k`.
    This is a summand in the formula for the dimension of the space of
    cusp forms of weight `2` with character
    `\varepsilon`.

    INPUT:


    -  ``eps`` - Dirichlet character

    -  ``k`` - integer


    OUTPUT: element of the base ring of eps.

    EXAMPLES::

        sage: G.<eps> = DirichletGroup(7)
        sage: sage.modular.dims.CohenOesterle(eps, 2)
        -2/3
        sage: sage.modular.dims.CohenOesterle(eps, 4)
        -1
    """
    N    = eps.modulus()
    facN = factor(N)
    f    = eps.conductor()
    gamma_k = 0
    if k%4==2:
        gamma_k = frac(-1,4)
    elif k%4==0:
        gamma_k = frac(1,4)
    mu_k = 0
    if k%3==2:
        mu_k = frac(-1,3)
    elif k%3==0:
        mu_k = frac(1,3)
    def _lambda(r,s,p):
        """
        Used internally by the CohenOesterle function.

        INPUT:


        -  ``r, s, p`` - integers


        OUTPUT: Integer

        EXAMPLES: (indirect doctest)

        ::

            sage: K = CyclotomicField(3)
            sage: eps = DirichletGroup(7*43,K).0^2
            sage: sage.modular.dims.CohenOesterle(eps,2)
            -4/3
        """
        if 2*s<=r:
            if r%2==0:
                return p**(r//2) + p**((r//2)-1)
            return 2*p**((r-1)//2)
        return 2*(p**(r-s))
    #end def of lambda
    K = eps.base_ring()
    return K(frac(-1,2) * mul([_lambda(r,valuation(f,p),p) for p, r in facN]) + \
               gamma_k * mul([CO_delta(r,p,N,eps)         for p, r in facN]) + \
                mu_k    * mul([CO_nu(r,p,N,eps)            for p, r in facN]))
def mutually_orthogonal_latin_squares(n, k=None, partitions=False):
    r"""
    Returns `k` Mutually Orthogonal `n\times n` Latin Squares (MOLS).

    For more information on Latin Squares and MOLS, see
    :mod:`~sage.combinat.designs.latin_squares` or the :wikipedia:`Latin_square`,
    or even the
    :wikipedia:`Wikipedia entry on MOLS <Graeco-Latin_square#Mutually_orthogonal_Latin_squares>`.

    INPUT:

    - ``n`` (integer) -- size of the latin square.

    - ``k`` (integer) -- returns `k` MOLS. If set to ``None`` (default), returns
      the maximum number of MOLS that Sage can build.

      .. WARNING::

          This has no reason to be the maximum number of `n\times n` MOLS, just
          the best Sage can do !

    - ``partition`` (boolean) -- a Latin Square can be seen as 3 partitions of
      the `n^2` cells of the array into `n` sets of size `n`, respectively :

      * The partition of rows
      * The partition of columns
      * The partition of number (cells numbered with 0, cells numbered with 1,
        ...)

      These partitions have the additional property that any two sets from
      different partitions intersect on exactly one element.

      When ``partition`` is set to ``True``, this function returns a list of `k+2`
      partitions satisfying this intersection property instead of the `k+2` MOLS
      (though the data is exactly the same in both cases).

    EXAMPLES::

        sage: designs.mutually_orthogonal_latin_squares(5)
        [
        [0 1 2 3 4]  [0 1 2 3 4]  [0 1 2 3 4]  [0 1 2 3 4]
        [3 0 1 4 2]  [4 3 0 2 1]  [1 2 4 0 3]  [2 4 3 1 0]
        [4 3 0 2 1]  [1 2 4 0 3]  [2 4 3 1 0]  [3 0 1 4 2]
        [1 2 4 0 3]  [2 4 3 1 0]  [3 0 1 4 2]  [4 3 0 2 1]
        [2 4 3 1 0], [3 0 1 4 2], [4 3 0 2 1], [1 2 4 0 3]
        ]
        sage: designs.mutually_orthogonal_latin_squares(7,3)
        [
        [0 1 2 3 4 5 6]  [0 1 2 3 4 5 6]  [0 1 2 3 4 5 6]
        [4 0 3 1 6 2 5]  [5 6 0 4 2 1 3]  [6 4 1 0 5 3 2]
        [5 6 0 4 2 1 3]  [6 4 1 0 5 3 2]  [1 3 5 2 0 6 4]
        [6 4 1 0 5 3 2]  [1 3 5 2 0 6 4]  [2 5 4 6 3 0 1]
        [1 3 5 2 0 6 4]  [2 5 4 6 3 0 1]  [3 2 6 5 1 4 0]
        [2 5 4 6 3 0 1]  [3 2 6 5 1 4 0]  [4 0 3 1 6 2 5]
        [3 2 6 5 1 4 0], [4 0 3 1 6 2 5], [5 6 0 4 2 1 3]
        ]
        sage: designs.mutually_orthogonal_latin_squares(5,2,partitions=True)
        [[[0, 1, 2, 3, 4],
          [5, 6, 7, 8, 9],
          [10, 11, 12, 13, 14],
          [15, 16, 17, 18, 19],
          [20, 21, 22, 23, 24]],
         [[0, 5, 10, 15, 20],
          [1, 6, 11, 16, 21],
          [2, 7, 12, 17, 22],
          [3, 8, 13, 18, 23],
          [4, 9, 14, 19, 24]],
        [[0, 6, 12, 18, 24],
          [1, 7, 14, 15, 23],
          [2, 9, 13, 16, 20],
          [3, 5, 11, 19, 22],
          [4, 8, 10, 17, 21]],
        [[0, 7, 13, 19, 21],
          [1, 9, 10, 18, 22],
          [2, 8, 11, 15, 24],
          [3, 6, 14, 17, 20],
          [4, 5, 12, 16, 23]]]

    TESTS::

        sage: designs.mutually_orthogonal_latin_squares(5,5)
        Traceback (most recent call last):
        ...
        ValueError: There exist at most n-1 MOLS of size n.
    """
    from sage.rings.finite_rings.constructor import FiniteField
    from sage.combinat.designs.block_design import AffineGeometryDesign
    from sage.rings.arith import is_prime_power
    from sage.matrix.constructor import Matrix
    from sage.rings.arith import factor

    if k is not None and k >= n:
        raise ValueError("There exist at most n-1 MOLS of size n.")

    if is_prime_power(n):
        if k is None:
            k = n - 1
        # Section 6.4.1 of [Stinson2004]
        Fp = FiniteField(n, 'x')
        B = AffineGeometryDesign(2, 1, Fp).blocks()
        parallel_classes = [[] for _ in range(k + 2)]
        for b in B:
            for p in parallel_classes:
                if (not p) or all(i not in p[0] for i in b):
                    p.append(b)
                    break

        if partitions:
            return parallel_classes

        coord = {v: i for i, L in enumerate(parallel_classes[0]) for v in L}
        coord = {
            v: (coord[v], i)
            for i, L in enumerate(parallel_classes[1]) for v in L
        }

        matrices = []
        for P in parallel_classes[2:]:
            matrices.append(
                Matrix({coord[v]: i
                        for i, L in enumerate(P) for v in L}))
        return matrices
    else:
        # Theorem 6.33 of [Stinson2004], MacNeish's theorem.
        subcases = [p**i for p, i in factor(n)]
        s = min(subcases) - 1
        if k is None:
            k = s
        elif k > s:
            raise NotImplementedError("I don't know how to build these MOLS.")
        subcalls = [mutually_orthogonal_latin_squares(p, k) for p in subcases]
        matrices = [
            latin_square_product(*[sc[i] for sc in subcalls]) for i in range(k)
        ]

        if partitions:
            partitions = [[[i * n + j for j in range(n)] for i in range(n)],
                          [[j * n + i for j in range(n)] for i in range(n)]]
            for m in matrices:
                partition = [[] for i in range(n)]
                for i in range(n):
                    for j in range(n):
                        partition[m[i, j]].append(i * n + j)
                partitions.append(partition)

            return partitions

        else:
            return matrices
Exemple #38
0
    def dft(self, chi = lambda x: x):
        """
        A discrete Fourier transform "over `\QQ`" using exact
        `N`-th roots of unity.

        EXAMPLES::

            sage: J = range(6)
            sage: A = [ZZ(1) for i in J]
            sage: s = IndexedSequence(A,J)
            sage: s.dft(lambda x:x^2)
            Indexed sequence: [6, 0, 0, 6, 0, 0]
             indexed by [0, 1, 2, 3, 4, 5]
            sage: s.dft()
            Indexed sequence: [6, 0, 0, 0, 0, 0]
             indexed by [0, 1, 2, 3, 4, 5]
            sage: G = SymmetricGroup(3)
            sage: J = G.conjugacy_classes_representatives()
            sage: s = IndexedSequence([1,2,3],J) # 1,2,3 are the values of a class fcn on G
            sage: s.dft()   # the "scalar-valued Fourier transform" of this class fcn
            Indexed sequence: [8, 2, 2]
             indexed by [(), (1,2), (1,2,3)]
            sage: J = AbelianGroup(2,[2,3],names='ab')
            sage: s = IndexedSequence([1,2,3,4,5,6],J)
            sage: s.dft()   # the precision of output is somewhat random and architecture dependent.
            Indexed sequence: [21.0000000000000, -2.99999999999997 - 1.73205080756885*I, -2.99999999999999 + 1.73205080756888*I, -9.00000000000000 + 0.0000000000000485744257349999*I, -0.00000000000000976996261670137 - 0.0000000000000159872115546022*I, -0.00000000000000621724893790087 - 0.0000000000000106581410364015*I]
                indexed by Multiplicative Abelian group isomorphic to C2 x C3
            sage: J = CyclicPermutationGroup(6)
            sage: s = IndexedSequence([1,2,3,4,5,6],J)
            sage: s.dft()   # the precision of output is somewhat random and architecture dependent.
            Indexed sequence: [21.0000000000000, -2.99999999999997 - 1.73205080756885*I, -2.99999999999999 + 1.73205080756888*I, -9.00000000000000 + 0.0000000000000485744257349999*I, -0.00000000000000976996261670137 - 0.0000000000000159872115546022*I, -0.00000000000000621724893790087 - 0.0000000000000106581410364015*I]
                indexed by Cyclic group of order 6 as a permutation group
            sage: p = 7; J = range(p); A = [kronecker_symbol(j,p) for j in J]
            sage: s = IndexedSequence(A,J)
            sage: Fs = s.dft()
            sage: c = Fs.list()[1]; [x/c for x in Fs.list()]; s.list()
            [0, 1, 1, -1, 1, -1, -1]
            [0, 1, 1, -1, 1, -1, -1]

        The DFT of the values of the quadratic residue symbol is itself, up to
        a constant factor (denoted c on the last line above).

        .. TODO::

            Read the parent of the elements of S; if `\QQ` or `\CC` leave as
            is; if AbelianGroup, use abelian_group_dual; if some other
            implemented Group (permutation, matrix), call .characters()
            and test if the index list is the set of conjugacy classes.
        """
        J = self.index_object()   ## index set of length N
        N = len(J)
        S = self.list()
        F = self.base_ring()   ## elements must be coercible into QQ(zeta_N)
        if not(J[0] in ZZ):
            G = J[0].parent() ## if J is not a range it is a group G
        if J[0] in ZZ and F.base_ring().fraction_field()==QQ:
            ## assumes J is range(N)
            zeta = CyclotomicField(N).gen()
            FT = [sum([S[i]*chi(zeta**(i*j)) for i in J]) for j in J]
        elif not(J[0] in ZZ) and G.is_abelian() and F == ZZ or (F.is_field() and F.base_ring()==QQ):
            if is_PermutationGroupElement(J[0]):
                ## J is a CyclicPermGp
                n = G.order()
                a = list(factor(n))
                invs = [x[0]**x[1] for x in a]
                G = AbelianGroup(len(a),invs)
            ## assumes J is AbelianGroup(...)
            Gd = G.dual_group()
            FT = [sum([S[i]*chid(G.list()[i]) for i in range(N)])
                  for chid in Gd]
        elif not(J[0] in ZZ) and G.is_finite() and F == ZZ or (F.is_field() and F.base_ring()==QQ):
            ## assumes J is the list of conj class representatives of a
            ## PermuationGroup(...) or Matrixgroup(...)
            chi = G.character_table()
            FT = [sum([S[i]*chi[i,j] for i in range(N)]) for j in range(N)]
        else:
            raise ValueError("list elements must be in QQ(zeta_"+str(N)+")")
        return IndexedSequence(FT,J)
Exemple #39
0
def difference_family(v, k, l=1, existence=False, explain_construction=False, check=True):
    r"""
    Return a (``k``, ``l``)-difference family on an Abelian group of cardinality ``v``.

    Let `G` be a finite Abelian group. For a given subset `D` of `G`, we define
    `\Delta D` to be the multi-set of differences `\Delta D = \{x - y; x \in D,
    y \in D, x \not= y\}`. A `(G,k,\lambda)`-*difference family* is a collection
    of `k`-subsets of `G`, `D = \{D_1, D_2, \ldots, D_b\}` such that the union
    of the difference sets `\Delta D_i` for `i=1,...b`, seen as a multi-set,
    contains each element of `G \backslash \{0\}` exactly `\lambda`-times.

    When there is only one block, i.e. `\lambda(v - 1) = k(k-1)`, then a
    `(G,k,\lambda)`-difference family is also called a *difference set*.

    See also :wikipedia:`Difference_set`.

    If there is no such difference family, an ``EmptySetError`` is raised and if
    there is no construction at the moment ``NotImplementedError`` is raised.

    INPUT:

    - ``v,k,l`` -- parameters of the difference family. If ``l`` is not provided
      it is assumed to be ``1``.

    - ``existence`` -- if ``True``, then return either ``True`` if Sage knows
      how to build such design, ``Unknown`` if it does not and ``False`` if it
      knows that the design does not exist.

    - ``explain_construction`` -- instead of returning a difference family,
      returns a string that explains the construction used.

    - ``check`` -- boolean (default: ``True``). If ``True`` then the result of
      the computation is checked before being returned. This should not be
      needed but ensures that the output is correct.

    OUTPUT:

    A pair ``(G,D)`` made of a group `G` and a difference family `D` on that
    group. Or, if ``existence`` is ``True`` a troolean or if
    ``explain_construction`` is ``True`` a string.

    EXAMPLES::

        sage: G,D = designs.difference_family(73,4)
        sage: G
        Finite Field of size 73
        sage: D
        [[0, 1, 5, 18],
         [0, 3, 15, 54],
         [0, 9, 45, 16],
         [0, 27, 62, 48],
         [0, 8, 40, 71],
         [0, 24, 47, 67]]

        sage: print designs.difference_family(73, 4, explain_construction=True)
        The database contains a (73,4)-evenly distributed set

        sage: G,D = designs.difference_family(15,7,3)
        sage: G
        The cartesian product of (Finite Field of size 3, Finite Field of size 5)
        sage: D
        [[(1, 1), (1, 4), (2, 2), (2, 3), (0, 0), (1, 0), (2, 0)]]
        sage: print designs.difference_family(15,7,3,explain_construction=True)
        Twin prime powers difference family

        sage: print designs.difference_family(91,10,1,explain_construction=True)
        Singer difference set

    For `k=6,7` we look at the set of small prime powers for which a
    construction is available::

        sage: def prime_power_mod(r,m):
        ....:     k = m+r
        ....:     while True:
        ....:         if is_prime_power(k):
        ....:             yield k
        ....:         k += m

        sage: from itertools import islice
        sage: l6 = {True:[], False: [], Unknown: []}
        sage: for q in islice(prime_power_mod(1,30), 60):
        ....:     l6[designs.difference_family(q,6,existence=True)].append(q)
        sage: l6[True]
        [31, 121, 151, 181, 211, ...,  3061, 3121, 3181]
        sage: l6[Unknown]
        [61]
        sage: l6[False]
        []

        sage: l7 = {True: [], False: [], Unknown: []}
        sage: for q in islice(prime_power_mod(1,42), 60):
        ....:     l7[designs.difference_family(q,7,existence=True)].append(q)
        sage: l7[True]
        [169, 337, 379, 421, 463, 547, 631, 673, 757, 841, 883, 967, ...,  4621, 4957, 5167]
        sage: l7[Unknown]
        [43, 127, 211, 2017, 2143, 2269, 2311, 2437, 2521, 2647, ..., 4999, 5041, 5209]
        sage: l7[False]
        []

    List available constructions::

        sage: for v in xrange(2,100):
        ....:     constructions = []
        ....:     for k in xrange(2,10):
        ....:         for l in xrange(1,10):
        ....:             if designs.difference_family(v,k,l,existence=True):
        ....:                 constructions.append((k,l))
        ....:                 _ = designs.difference_family(v,k,l)
        ....:     if constructions:
        ....:         print "%2d: %s"%(v, ', '.join('(%d,%d)'%(k,l) for k,l in constructions))
         3: (2,1)
         4: (3,2)
         5: (2,1), (4,3)
         6: (5,4)
         7: (2,1), (3,1), (3,2), (4,2), (6,5)
         8: (7,6)
         9: (2,1), (4,3), (8,7)
        10: (9,8)
        11: (2,1), (4,6), (5,2), (5,4), (6,3)
        13: (2,1), (3,1), (3,2), (4,1), (4,3), (5,5), (6,5)
        15: (3,1), (4,6), (5,6), (7,3)
        16: (3,2), (5,4), (6,2)
        17: (2,1), (4,3), (5,5), (8,7)
        19: (2,1), (3,1), (3,2), (4,2), (6,5), (9,4), (9,8)
        21: (3,1), (4,3), (5,1), (6,3), (6,5)
        22: (4,2), (6,5), (7,4), (8,8)
        23: (2,1)
        25: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (7,7), (8,7)
        27: (2,1), (3,1)
        28: (3,2), (6,5)
        29: (2,1), (4,3), (7,3), (7,6), (8,4), (8,6)
        31: (2,1), (3,1), (3,2), (4,2), (5,2), (5,4), (6,1), (6,5)
        33: (3,1), (5,5), (6,5)
        34: (4,2)
        35: (5,2)
        37: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (9,2), (9,8)
        39: (3,1), (6,5)
        40: (3,2), (4,1)
        41: (2,1), (4,3), (5,1), (5,4), (6,3), (8,7)
        43: (2,1), (3,1), (3,2), (4,2), (6,5), (7,2), (7,3), (7,6), (8,4)
        45: (3,1), (5,1)
        46: (4,2), (6,2)
        47: (2,1)
        49: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (8,7), (9,3)
        51: (3,1), (5,2), (6,3)
        52: (4,1)
        53: (2,1), (4,3)
        55: (3,1), (9,4)
        57: (3,1), (7,3), (8,1)
        59: (2,1)
        61: (2,1), (3,1), (3,2), (4,1), (4,3), (5,1), (5,4), (6,2), (6,3), (6,5)
        63: (3,1)
        64: (3,2), (4,1), (7,2), (7,6), (9,8)
        65: (5,1)
        67: (2,1), (3,1), (3,2), (6,5)
        69: (3,1)
        71: (2,1), (5,2), (5,4), (7,3), (7,6), (8,4)
        73: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (8,7), (9,1), (9,8)
        75: (3,1), (5,2)
        76: (4,1)
        79: (2,1), (3,1), (3,2), (6,5)
        81: (2,1), (3,1), (4,3), (5,1), (5,4), (8,7)
        83: (2,1)
        85: (4,1), (7,2), (7,3), (8,2)
        89: (2,1), (4,3), (8,7)
        91: (6,1), (7,1)
        97: (2,1), (3,1), (3,2), (4,1), (4,3), (6,5), (8,7), (9,3)

    TESTS:

    Check more of the Wilson constructions from [Wi72]_::

        sage: Q5 = [241, 281,421,601,641, 661, 701, 821,881]
        sage: Q9 = [73, 1153, 1873, 2017]
        sage: Q15 = [76231]
        sage: Q4 = [13, 73, 97, 109, 181, 229, 241, 277, 337, 409, 421, 457]
        sage: Q8 = [1009, 3137, 3697]
        sage: for Q,k in [(Q4,4),(Q5,5),(Q8,8),(Q9,9),(Q15,15)]:
        ....:     for q in Q:
        ....:         assert designs.difference_family(q,k,1,existence=True) is True
        ....:         _ = designs.difference_family(q,k,1)

    Check Singer difference sets::

        sage: sgp = lambda q,d: ((q**(d+1)-1)//(q-1), (q**d-1)//(q-1), (q**(d-1)-1)//(q-1))

        sage: for q in range(2,10):
        ....:     if is_prime_power(q):
        ....:         for d in [2,3,4]:
        ....:           v,k,l = sgp(q,d)
        ....:           assert designs.difference_family(v,k,l,existence=True) is True
        ....:           _ = designs.difference_family(v,k,l)

    Check twin primes difference sets::

        sage: for p in [3,5,7,9,11]:
        ....:     v = p*(p+2); k = (v-1)/2;  lmbda = (k-1)/2
        ....:     G,D = designs.difference_family(v,k,lmbda)

    Check the database::

        sage: from sage.combinat.designs.database import DF,EDS
        sage: for v,k,l in DF:
        ....:     assert designs.difference_family(v,k,l,existence=True) is True
        ....:     df = designs.difference_family(v,k,l,check=True)

        sage: for k in EDS:
        ....:     for v in EDS[k]:
        ....:         assert designs.difference_family(v,k,1,existence=True) is True
        ....:         df = designs.difference_family(v,k,1,check=True)

    Check a failing construction (:trac:`17528`)::

        sage: designs.difference_family(9,3)
        Traceback (most recent call last):
        ...
        NotImplementedError: No construction available for (9,3,1)-difference family

    .. TODO::

        Implement recursive constructions from Buratti "Recursive for difference
        matrices and relative difference families" (1998) and Jungnickel
        "Composition theorems for difference families and regular planes" (1978)
    """
    from block_design import are_hyperplanes_in_projective_geometry_parameters

    from database import DF, EDS

    if (v,k,l) in DF:
        if existence:
            return True
        elif explain_construction:
            return "The database contains a ({},{},{})-difference family".format(v,k,l)

        vv, blocks = next(DF[v,k,l].iteritems())

        # Build the group
        from sage.rings.finite_rings.integer_mod_ring import Zmod
        if len(vv) == 1:
            G = Zmod(vv[0])
        else:
            from sage.categories.cartesian_product import cartesian_product
            G = cartesian_product([Zmod(i) for i in vv])

        df = [[G(i) for i in b] for b in blocks]

        if check and not is_difference_family(G, df, v=v, k=k, l=l):
            raise RuntimeError("There is an invalid ({},{},{})-difference "
                    "family in the database... Please contact "
                    "*****@*****.**".format(v,k,l))

        return G,df

    elif l == 1 and k in EDS and v in EDS[k]:
        if existence:
            return True
        elif explain_construction:
            return "The database contains a ({},{})-evenly distributed set".format(v,k)

        from sage.rings.finite_rings.constructor import GF
        poly,B = EDS[k][v]
        if poly is None:  # q is prime
            K = G = GF(v)
        else:
            K = G = GF(v,'a',modulus=poly)

        B = map(K,B)
        e = k*(k-1)/2
        xe = G.multiplicative_generator()**e
        df = [[xe**j*b for b in B] for j in range((v-1)/(2*e))]
        if check and not is_difference_family(G, df, v=v, k=k, l=l):
            raise RuntimeError("There is an invalid ({},{})-evenly distributed "
                     "set in the database... Please contact "
                     "*****@*****.**".format(v,k,l))
        return G,df

    e = k*(k-1)
    if (l*(v-1)) % e:
        if existence:
            return Unknown
        raise NotImplementedError("No construction available for ({},{},{})-difference family".format(v,k,l))
    t = l*(v-1) // e  # number of blocks

    # trivial construction
    if k == (v-1) and l == (v-2):
        from sage.rings.finite_rings.integer_mod_ring import Zmod
        G = Zmod(v)
        return G, [range(1,v)]

    factorization = arith.factor(v)
    D = None

    if len(factorization) == 1:  # i.e. is v a prime power
        from sage.rings.finite_rings.constructor import GF
        G = K = GF(v,'z')

        if radical_difference_family(K, k, l, existence=True):
            if existence:
                return True
            elif explain_construction:
                return "Radical difference family on a finite field"
            else:
                D = radical_difference_family(K,k,l)

        elif l == 1 and k == 6 and df_q_6_1(K,existence=True):
            if existence:
                return True
            elif explain_construction:
                return "Wilson 1972 difference family made from the union of two cyclotomic cosets"
            else:
                D = df_q_6_1(K)

    # Twin prime powers construction
    # i.e. v = p(p+2) where p and p+2 are prime powers
    #      k = (v-1)/2
    #      lambda = (k-1)/2 (ie 2l+1 = k)
    elif (k == (v-1)//2 and
          l == (k-1)//2 and
          len(factorization) == 2 and
          abs(pow(*factorization[0]) - pow(*factorization[1])) == 2):
        if existence:
            return True
        elif explain_construction:
            return "Twin prime powers difference family"
        else:
            p = pow(*factorization[0])
            q = pow(*factorization[1])
            if p > q:
                p,q = q,p
            G,D = twin_prime_powers_difference_set(p,check=False)

    if D is None and are_hyperplanes_in_projective_geometry_parameters(v,k,l):
        _, (q,d) = are_hyperplanes_in_projective_geometry_parameters(v,k,l,True)
        if existence:
            return True
        elif explain_construction:
            return "Singer difference set"
        else:
            G,D = singer_difference_set(q,d)

    if D is None:
        if existence:
            return Unknown
        raise NotImplementedError("No constructions for these parameters")

    if check and not is_difference_family(G,D,v=v,k=k,l=l,verbose=False):
        raise RuntimeError("There is a problem. Sage built the following "
                "difference family on G='{}' with parameters ({},{},{}):\n "
                "{}\nwhich seems to not be a difference family... "
                "Please contact [email protected]".format(G,v,k,l,D))

    return G, D
Exemple #40
0
    def dft(self, chi = lambda x: x):
        """
        A discrete Fourier transform "over `\QQ`" using exact
        `N`-th roots of unity.

        EXAMPLES::

            sage: J = range(6)
            sage: A = [ZZ(1) for i in J]
            sage: s = IndexedSequence(A,J)
            sage: s.dft(lambda x:x^2)
            Indexed sequence: [6, 0, 0, 6, 0, 0]
             indexed by [0, 1, 2, 3, 4, 5]
            sage: s.dft()
            Indexed sequence: [6, 0, 0, 0, 0, 0]
             indexed by [0, 1, 2, 3, 4, 5]
            sage: G = SymmetricGroup(3)
            sage: J = G.conjugacy_classes_representatives()
            sage: s = IndexedSequence([1,2,3],J) # 1,2,3 are the values of a class fcn on G
            sage: s.dft()   # the "scalar-valued Fourier transform" of this class fcn
            Indexed sequence: [8, 2, 2]
             indexed by [(), (1,2), (1,2,3)]
            sage: J = AbelianGroup(2,[2,3],names='ab')
            sage: s = IndexedSequence([1,2,3,4,5,6],J)
            sage: s.dft()   # the precision of output is somewhat random and architecture dependent.
            Indexed sequence: [21.0000000000000, -2.99999999999997 - 1.73205080756885*I, -2.99999999999999 + 1.73205080756888*I, -9.00000000000000 + 0.0000000000000485744257349999*I, -0.00000000000000976996261670137 - 0.0000000000000159872115546022*I, -0.00000000000000621724893790087 - 0.0000000000000106581410364015*I]
                indexed by Multiplicative Abelian group isomorphic to C2 x C3
            sage: J = CyclicPermutationGroup(6)
            sage: s = IndexedSequence([1,2,3,4,5,6],J)
            sage: s.dft()   # the precision of output is somewhat random and architecture dependent.
            Indexed sequence: [21.0000000000000, -2.99999999999997 - 1.73205080756885*I, -2.99999999999999 + 1.73205080756888*I, -9.00000000000000 + 0.0000000000000485744257349999*I, -0.00000000000000976996261670137 - 0.0000000000000159872115546022*I, -0.00000000000000621724893790087 - 0.0000000000000106581410364015*I]
                indexed by Cyclic group of order 6 as a permutation group
            sage: p = 7; J = range(p); A = [kronecker_symbol(j,p) for j in J]
            sage: s = IndexedSequence(A,J)
            sage: Fs = s.dft()
            sage: c = Fs.list()[1]; [x/c for x in Fs.list()]; s.list()
            [0, 1, 1, -1, 1, -1, -1]
            [0, 1, 1, -1, 1, -1, -1]

        The DFT of the values of the quadratic residue symbol is itself, up to
        a constant factor (denoted c on the last line above).

        .. TODO::

            Read the parent of the elements of S; if `\QQ` or `\CC` leave as
            is; if AbelianGroup, use abelian_group_dual; if some other
            implemented Group (permutation, matrix), call .characters()
            and test if the index list is the set of conjugacy classes.
        """
        J = self.index_object()   ## index set of length N
        N = len(J)
        S = self.list()
        F = self.base_ring()   ## elements must be coercible into QQ(zeta_N)
        if not(J[0] in ZZ):
            G = J[0].parent() ## if J is not a range it is a group G
        if J[0] in ZZ and F.base_ring().fraction_field()==QQ:
            ## assumes J is range(N)
            zeta = CyclotomicField(N).gen()
            FT = [sum([S[i]*chi(zeta**(i*j)) for i in J]) for j in J]
        elif not(J[0] in ZZ) and G.is_abelian() and F == ZZ or (F.is_field() and F.base_ring()==QQ):
            if is_PermutationGroupElement(J[0]):
                ## J is a CyclicPermGp
                n = G.order()
                a = list(factor(n))
                invs = [x[0]**x[1] for x in a]
                G = AbelianGroup(len(a),invs)
            ## assumes J is AbelianGroup(...)
            Gd = G.dual_group()
            FT = [sum([S[i]*chid(G.list()[i]) for i in range(N)])
                  for chid in Gd]
        elif not(J[0] in ZZ) and G.is_finite() and F == ZZ or (F.is_field() and F.base_ring()==QQ):
            ## assumes J is the list of conj class representatives of a
            ## PermuationGroup(...) or Matrixgroup(...)
            chi = G.character_table()
            FT = [sum([S[i]*chi[i,j] for i in range(N)]) for j in range(N)]
        else:
            raise ValueError("list elements must be in QQ(zeta_"+str(N)+")")
        return IndexedSequence(FT,J)
Exemple #41
0
def O(*x, **kwds):
    """
    Big O constructor for various types.

    EXAMPLES:

    This is useful for writing power series elements::

        sage: R.<t> = ZZ[['t']]
        sage: (1+t)^10 + O(t^5)
        1 + 10*t + 45*t^2 + 120*t^3 + 210*t^4 + O(t^5)

    A power series ring is created implicitly if a polynomial
    element is passed::

        sage: R.<x> = QQ['x']
        sage: O(x^100)
        O(x^100)
        sage: 1/(1+x+O(x^5))
        1 - x + x^2 - x^3 + x^4 + O(x^5)
        sage: R.<u,v> = QQ[[]]
        sage: 1 + u + v^2 + O(u, v)^5
        1 + u + v^2 + O(u, v)^5

    This is also useful to create `p`-adic numbers::

        sage: O(7^6)
        O(7^6)
        sage: 1/3 + O(7^6)
        5 + 4*7 + 4*7^2 + 4*7^3 + 4*7^4 + 4*7^5 + O(7^6)

    It behaves well with respect to adding negative powers of `p`::

        sage: a = O(11^-32); a
        O(11^-32)
        sage: a.parent()
        11-adic Field with capped relative precision 20

    There are problems if you add a rational with very negative
    valuation to an `O`-Term::

        sage: 11^-12 + O(11^15)
        11^-12 + O(11^8)

    The reason that this fails is that the constructor doesn't know
    the right precision cap to use. If you cast explicitly or use
    other means of element creation, you can get around this issue::

        sage: K = Qp(11, 30)
        sage: K(11^-12) + O(11^15)
        11^-12 + O(11^15)
        sage: 11^-12 + K(O(11^15))
        11^-12 + O(11^15)
        sage: K(11^-12, absprec = 15)
        11^-12 + O(11^15)
        sage: K(11^-12, 15)
        11^-12 + O(11^15)

    We can also work with `asymptotic expansions`_::

        sage: A.<n> = AsymptoticRing(growth_group='QQ^n * n^QQ * log(n)^QQ', coefficient_ring=QQ); A
        doctest:...: FutureWarning:
        This class/method/function is marked as experimental. ...
        Asymptotic Ring <QQ^n * n^QQ * log(n)^QQ> over Rational Field
        sage: O(n)
        O(n)

    TESTS::

        sage: var('x, y')
        (x, y)
        sage: O(x)
        Traceback (most recent call last):
        ...
        ArithmeticError: O(x) not defined
        sage: O(y)
        Traceback (most recent call last):
        ...
        ArithmeticError: O(y) not defined
        sage: O(x, y)
        Traceback (most recent call last):
        ...
        ArithmeticError: O(x, y) not defined
        sage: O(4, 2)
        Traceback (most recent call last):
        ...
        ArithmeticError: O(4, 2) not defined
    """
    if len(x) > 1:
        if isinstance(x[0], multi_power_series_ring_element.MPowerSeries):
            return multi_power_series_ring_element.MO(x, **kwds)
        else:
            raise ArithmeticError("O(%s) not defined" %
                                  (', '.join(str(e) for e in x),))

    x = x[0]

    if isinstance(x, power_series_ring_element.PowerSeries):
        return x.parent()(0, x.degree(), **kwds)

    elif isinstance(x, Polynomial):
        if x.parent().ngens() != 1:
            raise NotImplementedError("completion only currently defined "
                                      "for univariate polynomials")
        if not x.is_monomial():
            raise NotImplementedError("completion only currently defined "
                                      "for the maximal ideal (x)")
        return x.parent().completion(x.parent().gen())(0, x.degree(), **kwds)

    elif isinstance(x, laurent_series_ring_element.LaurentSeries):
        return laurent_series_ring_element.LaurentSeries(x.parent(), 0).\
            add_bigoh(x.valuation(), **kwds)

    elif isinstance(x, (int, long, integer.Integer, rational.Rational)):
        # p-adic number
        if x <= 0:
            raise ArithmeticError("x must be a prime power >= 2")
        F = arith.factor(x)
        if len(F) != 1:
            raise ArithmeticError("x must be prime power")
        p, r = F[0]
        if r >= 0:
            return padics_factory.Zp(p, prec=max(r, 20),
                                     type='capped-rel')(0, absprec=r, **kwds)
        else:
            return padics_factory.Qp(p, prec=max(r, 20),
                                     type='capped-rel')(0, absprec=r, **kwds)

    elif isinstance(x, padic_generic_element.pAdicGenericElement):
         return x.parent()(0, absprec=x.valuation(), **kwds)
    elif hasattr(x, 'O'):
        return x.O(**kwds)
    raise ArithmeticError("O(%s) not defined" % (x,))