コード例 #1
0
    def create_key_and_extra_args(self,
                                  order,
                                  name=None,
                                  modulus=None,
                                  names=None,
                                  impl=None,
                                  proof=None,
                                  check_irreducible=True,
                                  prefix=None,
                                  repr=None,
                                  elem_cache=None,
                                  **kwds):
        """
        EXAMPLES::

            sage: GF.create_key_and_extra_args(9, 'a')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', 3, 2, True, None, 'poly', True), {})

        The order `q` can also be given as a pair `(p,n)`::

            sage: GF.create_key_and_extra_args((3, 2), 'a')
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', 3, 2, True, None, 'poly', True), {})

        We do not take invalid keyword arguments and raise a value error
        to better ensure uniqueness::

            sage: GF.create_key_and_extra_args(9, 'a', foo='value')
            Traceback (most recent call last):
            ...
            TypeError: ...create_key_and_extra_args() got an unexpected keyword argument 'foo'

        Moreover, ``repr`` and ``elem_cache`` are ignored when not
        using givaro::

            sage: GF.create_key_and_extra_args(16, 'a', impl='ntl', repr='poly')
            ((16, ('a',), x^4 + x + 1, 'ntl', 2, 4, True, None, None, None), {})
            sage: GF.create_key_and_extra_args(16, 'a', impl='ntl', elem_cache=False)
            ((16, ('a',), x^4 + x + 1, 'ntl', 2, 4, True, None, None, None), {})
            sage: GF(16, impl='ntl') is GF(16, impl='ntl', repr='foo')
            True

        We handle extra arguments for the givaro finite field and
        create unique objects for their defaults::

            sage: GF(25, impl='givaro') is GF(25, impl='givaro', repr='poly')
            True
            sage: GF(25, impl='givaro') is GF(25, impl='givaro', elem_cache=True)
            True
            sage: GF(625, impl='givaro') is GF(625, impl='givaro', elem_cache=False)
            True

        We explicitly take ``structure``, ``implementation`` and ``prec`` attributes
        for compatibility with :class:`~sage.categories.pushout.AlgebraicExtensionFunctor`
        but we ignore them as they are not used, see :trac:`21433`::

            sage: GF.create_key_and_extra_args(9, 'a', structure=None)
            ((9, ('a',), x^2 + 2*x + 2, 'givaro', 3, 2, True, None, 'poly', True), {})

        TESTS::

            sage: GF.create_key_and_extra_args((6, 1), 'a')
            Traceback (most recent call last):
            ...
            ValueError: the order of a finite field must be a prime power

            sage: GF.create_key_and_extra_args((9, 1), 'a')
            Traceback (most recent call last):
            ...
            ValueError: the order of a finite field must be a prime power

            sage: GF.create_key_and_extra_args((5, 0), 'a')
            Traceback (most recent call last):
            ...
            ValueError: the order of a finite field must be a prime power

            sage: GF.create_key_and_extra_args((3, 2, 1), 'a')
            Traceback (most recent call last):
            ...
            ValueError: wrong input for finite field constructor
        """
        import sage.arith.all
        from sage.structure.proof.all import WithProof, arithmetic
        if proof is None:
            proof = arithmetic()
        for key, val in kwds.items():
            if key not in [
                    'structure', 'implementation', 'prec', 'embedding',
                    'latex_names'
            ]:
                raise TypeError(
                    "create_key_and_extra_args() got an unexpected keyword argument '%s'"
                    % key)
            if not (val is None
                    or isinstance(val, list) and all(c is None for c in val)):
                raise NotImplementedError(
                    "ring extension with prescribed %s is not implemented" %
                    key)
        with WithProof('arithmetic', proof):
            if isinstance(order, tuple):
                if len(order) != 2:
                    raise ValueError(
                        'wrong input for finite field constructor')
                p, n = order
                p = Integer(p)
                if not p.is_prime() or n < 1:
                    raise ValueError(
                        "the order of a finite field must be a prime power")
                n = Integer(n)
                order = p**n
            else:
                order = Integer(order)
                if order <= 1:
                    raise ValueError(
                        "the order of a finite field must be at least 2")
                if order.is_prime():
                    p = order
                    n = Integer(1)
                else:
                    p, n = order.is_prime_power(get_data=True)
                    if n == 0:
                        raise ValueError(
                            "the order of a finite field must be a prime power"
                        )
            # at this point, order = p**n

            if n == 1:
                if impl is None:
                    impl = 'modn'
                name = ('x', )  # Ignore name
                # Every polynomial of degree 1 is irreducible
                check_irreducible = False
            else:
                if names is not None:
                    name = names
                if name is None:
                    if prefix is None:
                        prefix = 'z'
                    name = prefix + str(n)
                    if modulus is not None:
                        raise ValueError(
                            "no modulus may be specified if variable name not given"
                        )
                    # Fpbar will have a strong reference, since algebraic_closure caches its results,
                    # and the coefficients of modulus lie in GF(p)
                    Fpbar = GF(p).algebraic_closure(prefix)
                    # This will give a Conway polynomial if p,n is small enough to be in the database
                    # and a pseudo-Conway polynomial if it's not.
                    modulus = Fpbar._get_polynomial(n)
                    check_irreducible = False
                name = normalize_names(1, name)

                if impl is None:
                    if order < zech_log_bound:
                        impl = 'givaro'
                    elif p == 2:
                        impl = 'ntl'
                    else:
                        impl = 'pari_ffelt'

            # Determine modulus.
            # For the 'modn' implementation, we use the following
            # optimization which we also need to avoid an infinite loop:
            # a modulus of None is a shorthand for x-1.
            if modulus is not None or impl != 'modn':
                R = PolynomialRing(FiniteField(p), 'x')
                if modulus is None:
                    modulus = R.irreducible_element(n)
                if isinstance(modulus, str):
                    # A string specifies an algorithm to find a suitable modulus.
                    if modulus != "random" and modulus in self._modulus_cache[
                            order]:
                        modulus = self._modulus_cache[order][modulus]
                    else:
                        self._modulus_cache[order][
                            modulus] = modulus = R.irreducible_element(
                                n, algorithm=modulus)
                else:
                    if sage.rings.polynomial.polynomial_element.is_Polynomial(
                            modulus):
                        modulus = modulus.change_variable_name('x')
                    modulus = R(modulus).monic()

                    if modulus.degree() != n:
                        raise ValueError(
                            "the degree of the modulus does not equal the degree of the field"
                        )
                    if check_irreducible and not modulus.is_irreducible():
                        raise ValueError(
                            "finite field modulus must be irreducible but it is not"
                        )
                # If modulus is x - 1 for impl="modn", set it to None
                if impl == 'modn' and modulus[0] == -1:
                    modulus = None

            # Check extra arguments for givaro and setup their defaults
            # TODO: ntl takes a repr, but ignores it
            if impl == 'givaro':
                if repr is None:
                    repr = 'poly'
                if elem_cache is None:
                    elem_cache = (order < 500)
            else:
                # This has the effect of ignoring these keywords
                repr = None
                elem_cache = None

            return (order, name, modulus, impl, p, n, proof, prefix, repr,
                    elem_cache), {}
コード例 #2
0
    def product(self, left, right):
        """
        Return the product of ``left`` and ``right``.

        - ``left``, ``right`` -- symmetric functions written in the
          monomial basis ``self``.

        OUTPUT:

        - the product of ``left`` and ``right``, expanded in the
          monomial basis, as a dictionary whose keys are partitions and
          whose values are the coefficients of these partitions (more
          precisely, their respective monomial symmetric functions) in the
          product.

        EXAMPLES::

            sage: m = SymmetricFunctions(QQ).m()
            sage: a = m([2,1])
            sage: a^2
            4*m[2, 2, 1, 1] + 6*m[2, 2, 2] + 2*m[3, 2, 1] + 2*m[3, 3] + 2*m[4, 1, 1] + m[4, 2]

        ::

            sage: QQx.<x> = QQ['x']
            sage: m = SymmetricFunctions(QQx).m()
            sage: a = m([2,1])+x
            sage: 2*a # indirect doctest
            2*x*m[] + 2*m[2, 1]
            sage: a^2
            x^2*m[] + 2*x*m[2, 1] + 4*m[2, 2, 1, 1] + 6*m[2, 2, 2] + 2*m[3, 2, 1] + 2*m[3, 3] + 2*m[4, 1, 1] + m[4, 2]
        """
        # Use symmetrica to do the multiplication
        # A = left.parent()

        # Hack due to symmetrica crashing when both of the
        # partitions are the empty partition
        # if  R is ZZ or R is QQ:
        #     return symmetrica.mult_monomial_monomial(left, right)

        z_elt = {}
        for left_m, left_c in left._monomial_coefficients.items():
            for right_m, right_c in right._monomial_coefficients.items():

                # Hack due to symmetrica crashing when both of the
                # partitions are the empty partition
                if not left_m and not right_m:
                    z_elt[left_m] = left_c * right_c
                    continue

                d = symmetrica.mult_monomial_monomial({
                    left_m: Integer(1)
                }, {
                    right_m: Integer(1)
                }).monomial_coefficients()
                for m in d:
                    if m in z_elt:
                        z_elt[m] += left_c * right_c * d[m]
                    else:
                        z_elt[m] = left_c * right_c * d[m]
        return self._from_dict(z_elt)
コード例 #3
0
ファイル: homset.py プロジェクト: EnterStudios/sage-1
    def list(self):
        """
        Return a list of all the elements in this set of field homomorphisms.

        EXAMPLES::

            sage: K.<a> = GF(25)
            sage: End(K)
            Automorphism group of Finite Field in a of size 5^2
            sage: list(End(K))
            [Ring endomorphism of Finite Field in a of size 5^2
              Defn: a |--> 4*a + 1,
             Ring endomorphism of Finite Field in a of size 5^2
              Defn: a |--> a]
            sage: L.<z> = GF(7^6)
            sage: [g for g in End(L) if (g^3)(z) == z]
            [Ring endomorphism of Finite Field in z of size 7^6
              Defn: z |--> z,
             Ring endomorphism of Finite Field in z of size 7^6
              Defn: z |--> 5*z^4 + 5*z^3 + 4*z^2 + 3*z + 1,
             Ring endomorphism of Finite Field in z of size 7^6
              Defn: z |--> 3*z^5 + 5*z^4 + 5*z^2 + 2*z + 3]

        Between isomorphic fields with different moduli::

            sage: k1 = GF(1009)
            sage: k2 = GF(1009, modulus="primitive")
            sage: Hom(k1, k2).list()
            [
            Ring morphism:
              From: Finite Field of size 1009
              To:   Finite Field of size 1009
              Defn: 1 |--> 1
            ]
            sage: Hom(k2, k1).list()
            [
            Ring morphism:
              From: Finite Field of size 1009
              To:   Finite Field of size 1009
              Defn: 11 |--> 11
            ]

            sage: k1.<a> = GF(1009^2, modulus="first_lexicographic")
            sage: k2.<b> = GF(1009^2, modulus="conway")
            sage: Hom(k1, k2).list()
            [
            Ring morphism:
              From: Finite Field in a of size 1009^2
              To:   Finite Field in b of size 1009^2
              Defn: a |--> 290*b + 864,
            Ring morphism:
              From: Finite Field in a of size 1009^2
              To:   Finite Field in b of size 1009^2
              Defn: a |--> 719*b + 145
            ]

        TESTS:

        Check that :trac:`11390` is fixed::

            sage: K = GF(1<<16,'a'); L = GF(1<<32,'b')
            sage: K.Hom(L)[0]
            Ring morphism:
              From: Finite Field in a of size 2^16
              To:   Finite Field in b of size 2^32
              Defn: a |--> b^29 + b^27 + b^26 + b^23 + b^21 + b^19 + b^18 + b^16 + b^14 + b^13 + b^11 + b^10 + b^9 + b^8 + b^7 + b^6 + b^5 + b^2 + b
        """
        try:
            return self.__list
        except AttributeError:
            pass
        D = self.domain()
        C = self.codomain()
        if D.characteristic() == C.characteristic() and Integer(
                D.degree()).divides(Integer(C.degree())):
            f = D.modulus()
            g = C['x'](f)
            r = g.roots()
            v = [self(D.hom(a, C)) for a, _ in r]
            v = Sequence(v, immutable=True, cr=True)
        else:
            v = Sequence([], immutable=True, cr=False)
        self.__list = v
        return v
コード例 #4
0
def supersingular_j(FF):
    r"""
    Return a supersingular j-invariant over the finite
    field FF.

    INPUT:

    - ``FF``  -- finite field with p^2 elements, where p is a prime number

    OUTPUT:

    - finite field element -- a supersingular j-invariant
      defined over the finite field FF

    EXAMPLES:

    The following examples calculate supersingular j-invariants for a
    few finite fields::

        sage: supersingular_j(GF(7^2, 'a'))
        6

    Observe that in this example the j-invariant is not defined over
    the prime field::

        sage: supersingular_j(GF(15073^2, 'a'))
        4443*a + 13964
        sage: supersingular_j(GF(83401^2, 'a'))
        67977

    AUTHORS:

    - David Kohel -- [email protected]

    - Iftikhar Burhanuddin -- [email protected]
    """
    if not (FF.is_field()) or not (FF.is_finite()):
        raise ValueError("%s is not a finite field" % FF)
    prime = FF.characteristic()
    if not (Integer(prime).is_prime()):
        raise ValueError("%s is not a prime" % prime)
    if not (Integer(FF.cardinality())) == Integer(prime**2):
        raise ValueError("%s is not a quadratic extension" % FF)
    if kronecker(-1, prime) != 1:
        j_invss = 1728  # (2^2 * 3)^3
    elif kronecker(-2, prime) != 1:
        j_invss = 8000  # (2^2 * 5)^3
    elif kronecker(-3, prime) != 1:
        j_invss = 0  # 0^3
    elif kronecker(-7, prime) != 1:
        j_invss = 16581375  # (3 * 5 * 17)^3
    elif kronecker(-11, prime) != 1:
        j_invss = -32768  # -(2^5)^3
    elif kronecker(-19, prime) != 1:
        j_invss = -884736  # -(2^5 * 3)^3
    elif kronecker(-43, prime) != 1:
        j_invss = -884736000  # -(2^6 * 3 * 5)^3
    elif kronecker(-67, prime) != 1:
        j_invss = -147197952000  # -(2^5 * 3 * 5 * 11)^3
    elif kronecker(-163, prime) != 1:
        j_invss = -262537412640768000  # -(2^6 * 3 * 5 * 23 * 29)^3
    else:
        D = supersingular_D(prime)
        hc_poly = FF['x'](pari(D).polclass())
        root_hc_poly_list = list(hc_poly.roots())

        j_invss = root_hc_poly_list[0][0]
    return FF(j_invss)
コード例 #5
0
    def pthpowers(self, p, Bound):
        """
        Find the indices of proveably all pth powers in the recurrence sequence bounded by Bound.

        Let `u_n` be a binary recurrence sequence.  A ``p`` th power in `u_n` is a solution
        to `u_n = y^p` for some integer `y`.  There are only finitely many ``p`` th powers in
        any recurrence sequence [SS1983]_.

        INPUT:

        - ``p`` - a rational prime integer (the fixed p in `u_n = y^p`)

        - ``Bound`` - a natural number (the maximum index `n` in `u_n = y^p` that is checked).

        OUTPUT:

        - A list of the indices of all ``p`` th powers less bounded by ``Bound``.  If the sequence is degenerate and there are many ``p`` th powers, raises ``ValueError``.

        EXAMPLES::

            sage: R = BinaryRecurrenceSequence(1,1)        #the Fibonacci sequence
            sage: R.pthpowers(2, 10**30)        # long time (7 seconds) -- in fact these are all squares, c.f. [BMS2006]_
            [0, 1, 2, 12]

            sage: S = BinaryRecurrenceSequence(8,1) #a Lucas sequence
            sage: S.pthpowers(3,10**30)    # long time (3 seconds) -- provably finds the indices of all 3rd powers less than 10^30
            [0, 1, 2]

            sage: Q = BinaryRecurrenceSequence(3,3,2,1)
            sage: Q.pthpowers(11,10**30)          # long time (7.5 seconds)
            [1]

        If the sequence is degenerate, and there are no ``p`` th powers, returns `[]`.  Otherwise, if
        there are many ``p`` th powers, raises ``ValueError``.

        ::

            sage: T = BinaryRecurrenceSequence(2,0,1,2)
            sage: T.is_degenerate()
            True
            sage: T.is_geometric()
            True
            sage: T.pthpowers(7,10**30)
            Traceback (most recent call last):
            ...
            ValueError: The degenerate binary recurrence sequence is geometric or quasigeometric and has many pth powers.

            sage: L = BinaryRecurrenceSequence(4,0,2,2)
            sage: [L(i).factor() for i in range(10)]
            [2, 2, 2^3, 2^5, 2^7, 2^9, 2^11, 2^13, 2^15, 2^17]
            sage: L.is_quasigeometric()
            True
            sage: L.pthpowers(2,10**30)
            []

        NOTE: This function is primarily optimized in the range where ``Bound`` is much larger than ``p``.

        """

        #Thanks to Jesse Silliman for helpful conversations!

        #Reset the dictionary of good primes, as this depends on p
        self._PGoodness = {}
        #Starting lower bound on good primes
        self._ell = 1

        #If the sequence is geometric, then the `n`th term is `a*r^n`.  Thus the
        #property of being a ``p`` th power is periodic mod ``p``.  So there are either
        #no ``p`` th powers if there are none in the first ``p`` terms, or many if there
        #is at least one in the first ``p`` terms.

        if self.is_geometric() or self.is_quasigeometric():
            no_powers = True
            for i in range(1, 6 * p + 1):
                if _is_p_power(self(i), p):
                    no_powers = False
                    break
            if no_powers:
                if _is_p_power(self.u0, p):
                    return [0]
                return []
            else:
                raise ValueError(
                    "The degenerate binary recurrence sequence is geometric or quasigeometric and has many pth powers."
                )

        #If the sequence is degenerate without being geometric or quasigeometric, there
        #may be many ``p`` th powers or no ``p`` th powers.

        elif (self.b**2 + 4 * self.c) == 0:

            #This is the case if the matrix F is not diagonalizable, ie b^2 +4c = 0, and alpha/beta = 1.

            alpha = self.b / 2

            #In this case, u_n = u_0*alpha^n + (u_1 - u_0*alpha)*n*alpha^(n-1) = alpha^(n-1)*(u_0 +n*(u_1 - u_0*alpha)),
            #that is, it is a geometric term (alpha^(n-1)) times an arithmetic term (u_0 + n*(u_1-u_0*alpha)).

            #Look at classes n = k mod p, for k = 1,...,p.

            for k in range(1, p + 1):

                #The linear equation alpha^(k-1)*u_0 + (k+pm)*(alpha^(k-1)*u1 - u0*alpha^k)
                #must thus be a pth power.  This is a linear equation in m, namely, A + B*m, where

                A = (alpha**(k - 1) * self.u0 + k *
                     (alpha**(k - 1) * self.u1 - self.u0 * alpha**k))
                B = p * (alpha**(k - 1) * self.u1 - self.u0 * alpha**k)

                #This linear equation represents a pth power iff A is a pth power mod B.

                if _is_p_power_mod(A, p, B):
                    raise ValueError(
                        "The degenerate binary recurrence sequence has many pth powers."
                    )
            return []

        #We find ``p`` th powers using an elementary sieve.  Term `u_n` is a ``p`` th
        #power if and only if it is a ``p`` th power modulo every prime `\\ell`.  This condition
        #gives nontrivial information if ``p`` divides the order of the multiplicative group of
        #`\\Bold(F)_{\\ell}`, i.e. if `\\ell` is ` 1 \mod{p}`, as then only `1/p` terms are ``p`` th
        #powers modulo `\\ell``.

        #Thus, given such an `\\ell`, we get a set of necessary congruences for the index modulo the
        #the period of the sequence mod `\\ell`.  Then we intersect these congruences for many primes
        #to get a tight list modulo a growing modulus.  In order to keep this step manageable, we
        #only use primes `\\ell` that have particularly smooth periods.

        #Some congruences in the list will remain as the modulus grows.  If a congruence remains through
        #7 rounds of increasing the modulus, then we check if this corresponds to a perfect power (if
        #it does, we add it to our list of indices corresponding to ``p`` th powers).  The rest of the congruences
        #are transient and grow with the modulus.  Once the smallest of these is greater than the bound,
        #the list of known indices corresponding to ``p`` th powers is complete.

        else:

            if Bound < 3 * p:

                powers = []
                ell = p + 1

                while not is_prime(ell):
                    ell = ell + p

                F = GF(ell)
                a0 = F(self.u0)
                a1 = F(self.u1)  #a0 and a1 are variables for terms in sequence
                bf, cf = F(self.b), F(self.c)

                for n in range(Bound):  # n is the index of the a0

                    #Check whether a0 is a perfect power mod ell
                    if _is_p_power_mod(a0, p, ell):
                        #if a0 is a perfect power mod ell, check if nth term is ppower
                        if _is_p_power(self(n), p):
                            powers.append(n)

                    a0, a1 = a1, bf * a1 + cf * a0  #step up the variables

            else:

                powers = [
                ]  #documents the indices of the sequence that provably correspond to pth powers
                cong = [
                    0
                ]  #list of necessary congruences on the index for it to correspond to pth powers
                Possible_count = {
                }  #keeps track of the number of rounds a congruence lasts in cong

                #These parameters are involved in how we choose primes to increase the modulus
                qqold = 1  #we believe that we know complete information coming from primes good by qqold
                M1 = 1  #we have congruences modulo M1, this may not be the tightest list
                M2 = p  #we want to move to have congruences mod M2
                qq = 1  #the largest prime power divisor of M1 is qq

                #This loop ups the modulus.
                while True:

                    #Try to get good data mod M2

                    #patience of how long we should search for a "good prime"
                    patience = 0.01 * _estimated_time(
                        lcm(M2, p * next_prime_power(qq)), M1, len(cong), p)
                    tries = 0

                    #This loop uses primes to get a small set of congruences mod M2.
                    while True:

                        #only proceed if took less than patience time to find the next good prime
                        ell = _next_good_prime(p, self, qq, patience, qqold)
                        if ell:

                            #gather congruence data for the sequence mod ell, which will be mod period(ell) = modu
                            cong1, modu = _find_cong1(p, self, ell)

                            CongNew = [
                            ]  #makes a new list from cong that is now mod M = lcm(M1, modu) instead of M1
                            M = lcm(M1, modu)
                            for k in range(M // M1):
                                for i in cong:
                                    CongNew.append(k * M1 + i)
                            cong = set(CongNew)

                            M1 = M

                            killed_something = False  #keeps track of when cong1 can rule out a congruence in cong

                            #CRT by hand to gain speed
                            for i in list(cong):
                                if not (
                                        i % modu in cong1
                                ):  #congruence in cong is inconsistent with any in cong1
                                    cong.remove(i)  #remove that congruence
                                    killed_something = True

                            if M1 == M2:
                                if not killed_something:
                                    tries += 1
                                    if tries == 2:  #try twice to rule out congruences
                                        cong = list(cong)
                                        qqold = qq
                                        qq = next_prime_power(qq)
                                        M2 = lcm(M2, p * qq)
                                        break

                        else:
                            qq = next_prime_power(qq)
                            M2 = lcm(M2, p * qq)
                            cong = list(cong)
                            break

                    #Document how long each element of cong has been there
                    for i in cong:
                        if i in Possible_count:
                            Possible_count[i] = Possible_count[i] + 1
                        else:
                            Possible_count[i] = 1

                    #Check how long each element has persisted, if it is for at least 7 cycles,
                    #then we check to see if it is actually a perfect power
                    for i in Possible_count:
                        if Possible_count[i] == 7:
                            n = Integer(i)
                            if n < Bound:
                                if _is_p_power(self(n), p):
                                    powers.append(n)

                    #check for a contradiction
                    if len(cong) > len(powers):
                        if cong[len(powers)] > Bound:
                            break
                    elif M1 > Bound:
                        break

            return powers
コード例 #6
0
    def _element_constructor_(self,
                              arg1,
                              v=None,
                              perm=None,
                              autom=None,
                              check=True):
        r"""
        Coerce ``arg1`` into this permutation group, if ``arg1`` is 0,
        then we will try to coerce ``(v, perm, autom)``.

        INPUT:

        - ``arg1`` (optional) -- either the integers 0, 1 or an element of ``self``

        - ``v`` (optional) -- a vector of length ``self.degree()``

        - ``perm`` (optional) -- a permutaton of degree ``self.degree()``

        - ``autom`` (optional) -- an automorphism of the ring

        EXAMPLES::

            sage: F.<a> = GF(9)
            sage: S = SemimonomialTransformationGroup(F, 4)
            sage: S(1)
            ((1, 1, 1, 1); (), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a)
            sage: g = S(v=[1,1,1,a])
            sage: S(g)
            ((1, 1, 1, a); (), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a)
            sage: S(perm=Permutation('(1,2)(3,4)'))
            ((1, 1, 1, 1); (1,2)(3,4), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a)
            sage: S(autom=F.hom([a**3]))
            ((1, 1, 1, 1); (), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1)
        """
        from sage.categories.homset import End
        R = self.base_ring()
        if arg1 == 0:
            if v is None:
                v = [R.one()] * self.degree()
            if perm is None:
                perm = Permutation(range(1, self.degree() + 1))
            if autom is None:
                autom = R.hom(R.gens())

            if check:
                try:
                    v = [R(x) for x in v]
                except TypeError:
                    raise TypeError('the vector attribute %s ' % v +
                                    'should be iterable')
                if len(v) != self.degree():
                    raise ValueError('the length of the vector is %s,' %
                                     len(v) + ' should be %s' % self.degree())
                if not all(x.parent() is R and x.is_unit() for x in v):
                    raise ValueError('there is at least one element in the ' +
                                     'list %s not lying in %s ' % (v, R) +
                                     'or which is not invertible')
                try:
                    perm = Permutation(perm)
                except TypeError:
                    raise TypeError('the permutation attribute %s ' % perm +
                                    'could not be converted to a permutation')
                if len(perm) != self.degree():
                    raise ValueError('the permutation length is %s,' %
                                     len(perm) +
                                     ' should be %s' % self.degree())

                try:
                    if autom.parent() != End(R):
                        autom = End(R)(autom)
                except TypeError:
                    raise TypeError('%s of type %s' % (autom, type(autom)) +
                                    ' is not coerceable to an automorphism')
            return self.Element(self, v, perm, autom)
        else:
            try:
                if arg1.parent() is self:
                    return arg1
            except AttributeError:
                pass
            try:
                from sage.rings.integer import Integer
                if Integer(arg1) == 1:
                    return self()
            except TypeError:
                pass
            raise TypeError('the first argument must be an integer' +
                            ' or an element of this group')
コード例 #7
0
    def _derivative_(self, n, z, m, diff_param):
        """
        EXAMPLES::

            sage: n,z,m = var('n,z,m')
            sage: elliptic_pi(n,z,m).diff(n)
            1/4*(sqrt(-m*sin(z)^2 + 1)*n*sin(2*z)/(n*sin(z)^2 - 1)
            + 2*(m - n)*elliptic_f(z, m)/n
            + 2*(n^2 - m)*elliptic_pi(n, z, m)/n
            + 2*elliptic_e(z, m))/((m - n)*(n - 1))
            sage: elliptic_pi(n,z,m).diff(z)
            -1/(sqrt(-m*sin(z)^2 + 1)*(n*sin(z)^2 - 1))
            sage: elliptic_pi(n,z,m).diff(m)
            1/4*(m*sin(2*z)/(sqrt(-m*sin(z)^2 + 1)*(m - 1))
            - 2*elliptic_e(z, m)/(m - 1)
            - 2*elliptic_pi(n, z, m))/(m - n)
        """
        if diff_param == 0:
            return ((Integer(1) / (Integer(2) * (m - n) * (n - Integer(1)))) *
                    (elliptic_e(z, m) + ((m - n) / n) * elliptic_f(z, m) +
                     ((n**Integer(2) - m) / n) * elliptic_pi(n, z, m) -
                     (n * sqrt(Integer(1) - m * sin(z)**Integer(2)) *
                      sin(Integer(2) * z)) /
                     (Integer(2) * (Integer(1) - n * sin(z)**Integer(2)))))
        elif diff_param == 1:
            return (Integer(1) /
                    (sqrt(Integer(1) - m * sin(z)**Integer(Integer(2))) *
                     (Integer(1) - n * sin(z)**Integer(2))))
        elif diff_param == 2:
            return ((Integer(1) / (Integer(2) * (n - m))) * (
                elliptic_e(z, m) / (m - Integer(1)) + elliptic_pi(n, z, m) -
                (m * sin(Integer(2) * z)) /
                (Integer(2) *
                 (m - Integer(1)) * sqrt(Integer(1) - m * sin(z)**Integer(2))))
                    )
コード例 #8
0
ファイル: code_constructions.py プロジェクト: lwhsu/sagemath
def _is_a_splitting(S1, S2, n, return_automorphism=False):
    r"""
    Check wether ``(S1,S2)`` is a splitting of `\ZZ/n\ZZ`.

    A splitting of `R = \ZZ/n\ZZ` is a pair of subsets of `R` which is a
    partition of `R \\backslash \{0\}` and such that there exists an element `r`
    of `R` such that `r S_1 = S_2` and `r S_2 = S_1` (where `r S` is the
    point-wise multiplication of the elements of `S` by `r`).

    Splittings are useful for computing idempotents in the quotient
    ring `Q = GF(q)[x]/(x^n-1)`.

    INPUT:

    - ``S1, S2`` -- disjoint sublists partitioning ``[1, 2, ..., n-1]``

    - ``n`` (integer)

    - ``return_automorphism`` (boolean) -- whether to return the automorphism
      exchanging `S_1` and `S_2`.

    OUTPUT:

    If ``return_automorphism is False`` (default) the function returns boolean values.

    Otherwise, it returns a pair ``(b, r)`` where ``b`` is a boolean indicating
    whether `S1`, `S2` is a splitting of `n`, and `r` is such that `r S_1 = S_2`
    and `r S_2 = S_1` (if `b` is ``False``, `r` is equal to ``None``).

    EXAMPLES::

        sage: from sage.coding.code_constructions import _is_a_splitting
        sage: _is_a_splitting([1,2],[3,4],5)
        True
        sage: _is_a_splitting([1,2],[3,4],5,return_automorphism=True)
        (True, 4)

        sage: _is_a_splitting([1,3],[2,4,5,6],7)
        False
        sage: _is_a_splitting([1,3,4],[2,5,6],7)
        False

        sage: for P in SetPartitions(6,[3,3]):
        ....:     res,aut= _is_a_splitting(P[0],P[1],7,return_automorphism=True)
        ....:     if res:
        ....:         print((aut, P[0], P[1]))
        (6, {1, 2, 3}, {4, 5, 6})
        (3, {1, 2, 4}, {3, 5, 6})
        (6, {1, 3, 5}, {2, 4, 6})
        (6, {1, 4, 5}, {2, 3, 6})

    We illustrate now how to find idempotents in quotient rings::

        sage: n = 11; q = 3
        sage: C = Zmod(n).cyclotomic_cosets(q); C
        [[0], [1, 3, 4, 5, 9], [2, 6, 7, 8, 10]]
        sage: S1 = C[1]
        sage: S2 = C[2]
        sage: _is_a_splitting(S1,S2,11)
        True
        sage: F = GF(q)
        sage: P.<x> = PolynomialRing(F,"x")
        sage: I = Ideal(P,[x^n-1])
        sage: Q.<x> = QuotientRing(P,I)
        sage: i1 = -sum([x^i for i in S1]); i1
        2*x^9 + 2*x^5 + 2*x^4 + 2*x^3 + 2*x
        sage: i2 = -sum([x^i for i in S2]); i2
        2*x^10 + 2*x^8 + 2*x^7 + 2*x^6 + 2*x^2
        sage: i1^2 == i1
        True
        sage: i2^2 == i2
        True
        sage: (1-i1)^2 == 1-i1
        True
        sage: (1-i2)^2 == 1-i2
        True

    We return to dealing with polynomials (rather than elements of
    quotient rings), so we can construct cyclic codes::

        sage: P.<x> = PolynomialRing(F,"x")
        sage: i1 = -sum([x^i for i in S1])
        sage: i2 = -sum([x^i for i in S2])
        sage: i1_sqrd = (i1^2).quo_rem(x^n-1)[1]
        sage: i1_sqrd  == i1
        True
        sage: i2_sqrd = (i2^2).quo_rem(x^n-1)[1]
        sage: i2_sqrd  == i2
        True
        sage: C1 = codes.CyclicCode(length = n, generator_pol = gcd(i1, x^n - 1))
        sage: C2 = codes.CyclicCode(length = n, generator_pol = gcd(1-i2, x^n - 1))
        sage: C1.dual_code().systematic_generator_matrix() == C2.systematic_generator_matrix()
        True

    This is a special case of Theorem 6.4.3 in [HP2003]_.
    """
    R = IntegerModRing(n)
    S1 = set(R(x) for x in S1)
    S2 = set(R(x) for x in S2)

    # we first check whether (S1,S2) is a partition of R - {0}
    if (len(S1) + len(S2) != n - 1 or len(S1) != len(S2) or R.zero() in S1
            or R.zero() in S2 or not S1.isdisjoint(S2)):
        if return_automorphism:
            return False, None
        else:
            return False

    # now that we know that (S1,S2) is a partition, we look for an invertible
    # element b that maps S1 to S2 by multiplication
    for b in Integer(n).coprime_integers(n):
        if b != 1 and all(b * x in S2 for x in S1):
            if return_automorphism:
                return True, b
            else:
                return True
    if return_automorphism:
        return False, None
    else:
        return False
コード例 #9
0
def PolynomialRing(base_ring, *args, **kwds):
    r"""
    Return the globally unique univariate or multivariate polynomial
    ring with given properties and variable name or names.

    There are many ways to specify the variables for the polynomial ring:

    1. ``PolynomialRing(base_ring, name, ...)``
    2. ``PolynomialRing(base_ring, names, ...)``
    3. ``PolynomialRing(base_ring, n, names, ...)``
    4. ``PolynomialRing(base_ring, n, ..., var_array=var_array, ...)``

    The ``...`` at the end of these commands stands for additional
    keywords, like ``sparse`` or ``order``.

    INPUT:

    - ``base_ring`` -- a ring

    - ``n`` -- an integer

    - ``name`` -- a string

    - ``names`` -- a list or tuple of names (strings), or a comma separated string

    - ``var_array`` -- a list or tuple of names, or a comma separated string

    - ``sparse`` -- bool: whether or not elements are sparse. The
      default is a dense representation (``sparse=False``) for
      univariate rings and a sparse representation (``sparse=True``)
      for multivariate rings.

    - ``order`` -- string or
      :class:`~sage.rings.polynomial.term_order.TermOrder` object, e.g.,

      - ``'degrevlex'`` (default) -- degree reverse lexicographic
      - ``'lex'``  -- lexicographic
      - ``'deglex'`` -- degree lexicographic
      - ``TermOrder('deglex',3) + TermOrder('deglex',3)`` -- block ordering

    - ``implementation`` -- string or None; selects an implementation in cases
      where Sage includes multiple choices (currently `\ZZ[x]` can be
      implemented with ``'NTL'`` or ``'FLINT'``; default is ``'FLINT'``).
      For many base rings, the ``"singular"`` implementation is available.
      One can always specify ``implementation="generic"`` for a generic
      Sage implementation which does not use any specialized library.

    .. NOTE::

        If the given implementation does not exist for rings with the given
        number of generators and the given sparsity, then an error results.

    OUTPUT:

    ``PolynomialRing(base_ring, name, sparse=False)`` returns a univariate
    polynomial ring; also, PolynomialRing(base_ring, names, sparse=False)
    yields a univariate polynomial ring, if names is a list or tuple
    providing exactly one name. All other input formats return a
    multivariate polynomial ring.

    UNIQUENESS and IMMUTABILITY: In Sage there is exactly one
    single-variate polynomial ring over each base ring in each choice
    of variable, sparseness, and implementation.  There is also exactly
    one multivariate polynomial ring over each base ring for each
    choice of names of variables and term order.  The names of the
    generators can only be temporarily changed after the ring has been
    created.  Do this using the localvars context:

    EXAMPLES:

    **1. PolynomialRing(base_ring, name, ...)**

    ::

        sage: PolynomialRing(QQ, 'w')
        Univariate Polynomial Ring in w over Rational Field
        sage: PolynomialRing(QQ, name='w')
        Univariate Polynomial Ring in w over Rational Field

    Use the diamond brackets notation to make the variable
    ready for use after you define the ring::

        sage: R.<w> = PolynomialRing(QQ)
        sage: (1 + w)^3
        w^3 + 3*w^2 + 3*w + 1

    You must specify a name::

        sage: PolynomialRing(QQ)
        Traceback (most recent call last):
        ...
        TypeError: you must specify the names of the variables

        sage: R.<abc> = PolynomialRing(QQ, sparse=True); R
        Sparse Univariate Polynomial Ring in abc over Rational Field

        sage: R.<w> = PolynomialRing(PolynomialRing(GF(7),'k')); R
        Univariate Polynomial Ring in w over Univariate Polynomial Ring in k over Finite Field of size 7

    The square bracket notation::

        sage: R.<y> = QQ['y']; R
        Univariate Polynomial Ring in y over Rational Field
        sage: y^2 + y
        y^2 + y

    In fact, since the diamond brackets on the left determine the
    variable name, you can omit the variable from the square brackets::

        sage: R.<zz> = QQ[]; R
        Univariate Polynomial Ring in zz over Rational Field
        sage: (zz + 1)^2
        zz^2 + 2*zz + 1

    This is exactly the same ring as what PolynomialRing returns::

        sage: R is PolynomialRing(QQ,'zz')
        True

    However, rings with different variables are different::

        sage: QQ['x'] == QQ['y']
        False

    Sage has two implementations of univariate polynomials over the
    integers, one based on NTL and one based on FLINT.  The default
    is FLINT. Note that FLINT uses a "more dense" representation for
    its polynomials than NTL, so in particular, creating a polynomial
    like 2^1000000 * x^1000000 in FLINT may be unwise.
    ::

        sage: ZxNTL = PolynomialRing(ZZ, 'x', implementation='NTL'); ZxNTL
        Univariate Polynomial Ring in x over Integer Ring (using NTL)
        sage: ZxFLINT = PolynomialRing(ZZ, 'x', implementation='FLINT'); ZxFLINT
        Univariate Polynomial Ring in x over Integer Ring
        sage: ZxFLINT is ZZ['x']
        True
        sage: ZxFLINT is PolynomialRing(ZZ, 'x')
        True
        sage: xNTL = ZxNTL.gen()
        sage: xFLINT = ZxFLINT.gen()
        sage: xNTL.parent()
        Univariate Polynomial Ring in x over Integer Ring (using NTL)
        sage: xFLINT.parent()
        Univariate Polynomial Ring in x over Integer Ring

    There is a coercion from the non-default to the default
    implementation, so the values can be mixed in a single
    expression::

        sage: (xNTL + xFLINT^2)
        x^2 + x

    The result of such an expression will use the default, i.e.,
    the FLINT implementation::

        sage: (xNTL + xFLINT^2).parent()
        Univariate Polynomial Ring in x over Integer Ring

    The generic implementation uses neither NTL nor FLINT::

        sage: Zx = PolynomialRing(ZZ, 'x', implementation='generic'); Zx
        Univariate Polynomial Ring in x over Integer Ring
        sage: Zx.element_class
        <... 'sage.rings.polynomial.polynomial_element.Polynomial_generic_dense'>

    **2. PolynomialRing(base_ring, names, ...)**

    ::

        sage: R = PolynomialRing(QQ, 'a,b,c'); R
        Multivariate Polynomial Ring in a, b, c over Rational Field

        sage: S = PolynomialRing(QQ, ['a','b','c']); S
        Multivariate Polynomial Ring in a, b, c over Rational Field

        sage: T = PolynomialRing(QQ, ('a','b','c')); T
        Multivariate Polynomial Ring in a, b, c over Rational Field

    All three rings are identical::

        sage: R is S
        True
        sage: S is T
        True

    There is a unique polynomial ring with each term order::

        sage: R = PolynomialRing(QQ, 'x,y,z', order='degrevlex'); R
        Multivariate Polynomial Ring in x, y, z over Rational Field
        sage: S = PolynomialRing(QQ, 'x,y,z', order='invlex'); S
        Multivariate Polynomial Ring in x, y, z over Rational Field
        sage: S is PolynomialRing(QQ, 'x,y,z', order='invlex')
        True
        sage: R == S
        False

    Note that a univariate polynomial ring is returned, if the list
    of names is of length one. If it is of length zero, a multivariate
    polynomial ring with no variables is returned.

    ::

        sage: PolynomialRing(QQ,["x"])
        Univariate Polynomial Ring in x over Rational Field
        sage: PolynomialRing(QQ,[])
        Multivariate Polynomial Ring in no variables over Rational Field

    The Singular implementation always returns a multivariate ring,
    even for 1 variable::

        sage: PolynomialRing(QQ, "x", implementation="singular")
        Multivariate Polynomial Ring in x over Rational Field
        sage: P.<x> = PolynomialRing(QQ, implementation="singular"); P
        Multivariate Polynomial Ring in x over Rational Field

    **3. PolynomialRing(base_ring, n, names, ...)** (where the arguments
    ``n`` and ``names`` may be reversed)

    If you specify a single name as a string and a number of
    variables, then variables labeled with numbers are created.

    ::

        sage: PolynomialRing(QQ, 'x', 10)
        Multivariate Polynomial Ring in x0, x1, x2, x3, x4, x5, x6, x7, x8, x9 over Rational Field

        sage: PolynomialRing(QQ, 2, 'alpha0')
        Multivariate Polynomial Ring in alpha00, alpha01 over Rational Field

        sage: PolynomialRing(GF(7), 'y', 5)
        Multivariate Polynomial Ring in y0, y1, y2, y3, y4 over Finite Field of size 7

        sage: PolynomialRing(QQ, 'y', 3, sparse=True)
        Multivariate Polynomial Ring in y0, y1, y2 over Rational Field

    Note that a multivariate polynomial ring is returned when an
    explicit number is given.

    ::

        sage: PolynomialRing(QQ,"x",1)
        Multivariate Polynomial Ring in x over Rational Field
        sage: PolynomialRing(QQ,"x",0)
        Multivariate Polynomial Ring in no variables over Rational Field

    It is easy in Python to create fairly arbitrary variable names.  For
    example, here is a ring with generators labeled by the primes less
    than 100::

        sage: R = PolynomialRing(ZZ, ['x%s'%p for p in primes(100)]); R
        Multivariate Polynomial Ring in x2, x3, x5, x7, x11, x13, x17, x19, x23, x29, x31, x37, x41, x43, x47, x53, x59, x61, x67, x71, x73, x79, x83, x89, x97 over Integer Ring

    By calling the
    :meth:`~sage.structure.category_object.CategoryObject.inject_variables`
    method, all those variable names are available for interactive use::

        sage: R.inject_variables()
        Defining x2, x3, x5, x7, x11, x13, x17, x19, x23, x29, x31, x37, x41, x43, x47, x53, x59, x61, x67, x71, x73, x79, x83, x89, x97
        sage: (x2 + x41 + x71)^2
        x2^2 + 2*x2*x41 + x41^2 + 2*x2*x71 + 2*x41*x71 + x71^2

    **4. PolynomialRing(base_ring, n, ..., var_array=var_array, ...)**

    This creates an array of variables where each variables begins with an
    entry in ``var_array`` and is indexed from 0 to `n-1`. ::

        sage: PolynomialRing(ZZ, 3, var_array=['x','y'])
        Multivariate Polynomial Ring in x0, y0, x1, y1, x2, y2 over Integer Ring
        sage: PolynomialRing(ZZ, 3, var_array='a,b')
        Multivariate Polynomial Ring in a0, b0, a1, b1, a2, b2 over Integer Ring

    It is possible to create higher-dimensional arrays::

        sage: PolynomialRing(ZZ, 2, 3, var_array=('p', 'q'))
        Multivariate Polynomial Ring in p00, q00, p01, q01, p02, q02, p10, q10, p11, q11, p12, q12 over Integer Ring
        sage: PolynomialRing(ZZ, 2, 3, 4, var_array='m')
        Multivariate Polynomial Ring in m000, m001, m002, m003, m010, m011, m012, m013, m020, m021, m022, m023, m100, m101, m102, m103, m110, m111, m112, m113, m120, m121, m122, m123 over Integer Ring

    The array is always at least 2-dimensional. So, if
    ``var_array`` is a single string and only a single number `n`
    is given, this creates an `n \times n` array of variables::

        sage: PolynomialRing(ZZ, 2, var_array='m')
        Multivariate Polynomial Ring in m00, m01, m10, m11 over Integer Ring

    **Square brackets notation**

    You can alternatively create a polynomial ring over a ring `R` with
    square brackets::

        sage: RR["x"]
        Univariate Polynomial Ring in x over Real Field with 53 bits of precision
        sage: RR["x,y"]
        Multivariate Polynomial Ring in x, y over Real Field with 53 bits of precision
        sage: P.<x,y> = RR[]; P
        Multivariate Polynomial Ring in x, y over Real Field with 53 bits of precision

    This notation does not allow to set any of the optional arguments.

    **Changing variable names**

    Consider ::

        sage: R.<x,y> = PolynomialRing(QQ,2); R
        Multivariate Polynomial Ring in x, y over Rational Field
        sage: f = x^2 - 2*y^2

    You can't just globally change the names of those variables.
    This is because objects all over Sage could have pointers to
    that polynomial ring. ::

        sage: R._assign_names(['z','w'])
        Traceback (most recent call last):
        ...
        ValueError: variable names cannot be changed after object creation.

    However, you can very easily change the names within a ``with`` block::

        sage: with localvars(R, ['z','w']):
        ....:     print(f)
        z^2 - 2*w^2

    After the ``with`` block the names revert to what they were before::

        sage: print(f)
        x^2 - 2*y^2

    TESTS:

    We test here some changes introduced in :trac:`9944`.

    If there is no dense implementation for the given number of
    variables, then requesting a dense ring is an error::

        sage: S.<x,y> = PolynomialRing(QQ, sparse=False)
        Traceback (most recent call last):
        ...
        NotImplementedError: a dense representation of multivariate polynomials is not supported

    Check uniqueness if the same implementation is used for different
    values of the ``"implementation"`` keyword::

        sage: R = PolynomialRing(QQbar, 'j', implementation="generic")
        sage: S = PolynomialRing(QQbar, 'j', implementation=None)
        sage: R is S
        True

        sage: R = PolynomialRing(ZZ['t'], 'j', implementation="generic")
        sage: S = PolynomialRing(ZZ['t'], 'j', implementation=None)
        sage: R is S
        True

        sage: R = PolynomialRing(QQbar, 'j,k', implementation="generic")
        sage: S = PolynomialRing(QQbar, 'j,k', implementation=None)
        sage: R is S
        True

        sage: R = PolynomialRing(ZZ, 'j,k', implementation="singular")
        sage: S = PolynomialRing(ZZ, 'j,k', implementation=None)
        sage: R is S
        True

        sage: R = PolynomialRing(ZZ, 'p', sparse=True, implementation="generic")
        sage: S = PolynomialRing(ZZ, 'p', sparse=True)
        sage: R is S
        True

    The generic implementation is different in some cases::

        sage: R = PolynomialRing(GF(2), 'j', implementation="generic"); type(R)
        <class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_field_with_category'>
        sage: S = PolynomialRing(GF(2), 'j'); type(S)
        <class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_dense_mod_p_with_category'>

        sage: R = PolynomialRing(ZZ, 'x,y', implementation="generic"); type(R)
        <class 'sage.rings.polynomial.multi_polynomial_ring.MPolynomialRing_polydict_domain_with_category'>
        sage: S = PolynomialRing(ZZ, 'x,y'); type(S)
        <type 'sage.rings.polynomial.multi_polynomial_libsingular.MPolynomialRing_libsingular'>

    Sparse univariate polynomials only support a generic
    implementation::

        sage: R = PolynomialRing(ZZ, 'j', sparse=True); type(R)
        <class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_integral_domain_with_category'>
        sage: R = PolynomialRing(GF(49), 'j', sparse=True); type(R)
        <class 'sage.rings.polynomial.polynomial_ring.PolynomialRing_field_with_category'>

    If the requested implementation is not known or not supported for
    the given arguments, then an error results::

        sage: R.<x0> = PolynomialRing(ZZ, implementation='Foo')
        Traceback (most recent call last):
        ...
        ValueError: unknown implementation 'Foo' for dense polynomial rings over Integer Ring
        sage: R.<x0> = PolynomialRing(GF(2), implementation='GF2X', sparse=True)
        Traceback (most recent call last):
        ...
        ValueError: unknown implementation 'GF2X' for sparse polynomial rings over Finite Field of size 2
        sage: R.<x,y> = PolynomialRing(ZZ, implementation='FLINT')
        Traceback (most recent call last):
        ...
        ValueError: unknown implementation 'FLINT' for multivariate polynomial rings
        sage: R.<x> = PolynomialRing(QQbar, implementation="whatever")
        Traceback (most recent call last):
        ...
        ValueError: unknown implementation 'whatever' for dense polynomial rings over Algebraic Field
        sage: R.<x> = PolynomialRing(ZZ['t'], implementation="whatever")
        Traceback (most recent call last):
        ...
        ValueError: unknown implementation 'whatever' for dense polynomial rings over Univariate Polynomial Ring in t over Integer Ring
        sage: PolynomialRing(RR, "x,y", implementation="whatever")
        Traceback (most recent call last):
        ...
        ValueError: unknown implementation 'whatever' for multivariate polynomial rings
        sage: PolynomialRing(RR, name="x", implementation="singular")
        Traceback (most recent call last):
        ...
        NotImplementedError: polynomials over Real Field with 53 bits of precision are not supported in Singular

    The following corner case used to result in a warning message from
    ``libSingular``, and the generators of the resulting polynomial
    ring were not zero::

        sage: R = Integers(1)['x','y']
        sage: R.0 == 0
        True

    We verify that :trac:`13187` is fixed::

        sage: var('t')
        t
        sage: PolynomialRing(ZZ, name=t) == PolynomialRing(ZZ, name='t')
        True

    We verify that polynomials with interval coefficients from
    :trac:`7712` and :trac:`13760` are fixed::

        sage: P.<y,z> = PolynomialRing(RealIntervalField(2))
        sage: Q.<x> = PolynomialRing(P)
        sage: C = (y-x)^3
        sage: C(y/2)
        1.?*y^3
        sage: R.<x,y> = PolynomialRing(RIF,2)
        sage: RIF(-2,1)*x
        0.?e1*x

    For historical reasons, we allow redundant variable names with the
    angle bracket notation. The names must be consistent though! ::

        sage: P.<x,y> = PolynomialRing(ZZ, "x,y"); P
        Multivariate Polynomial Ring in x, y over Integer Ring
        sage: P.<x,y> = ZZ["x,y"]; P
        Multivariate Polynomial Ring in x, y over Integer Ring
        sage: P.<x,y> = PolynomialRing(ZZ, 2, "x"); P
        Traceback (most recent call last):
        ...
        TypeError: variable names specified twice inconsistently: ('x0', 'x1') and ('x', 'y')

    We test a lot of invalid input::

        sage: PolynomialRing(4)
        Traceback (most recent call last):
        ...
        TypeError: base_ring 4 must be a ring
        sage: PolynomialRing(QQ, -1)
        Traceback (most recent call last):
        ...
        ValueError: number of variables must be non-negative
        sage: PolynomialRing(QQ, 1)
        Traceback (most recent call last):
        ...
        TypeError: you must specify the names of the variables
        sage: PolynomialRing(QQ, "x", None)
        Traceback (most recent call last):
        ...
        TypeError: invalid arguments ('x', None) for PolynomialRing
        sage: PolynomialRing(QQ, "x", "y")
        Traceback (most recent call last):
        ...
        TypeError: variable names specified twice: 'x' and 'y'
        sage: PolynomialRing(QQ, 1, "x", 2)
        Traceback (most recent call last):
        ...
        TypeError: number of variables specified twice: 1 and 2
        sage: PolynomialRing(QQ, "x", names="x")
        Traceback (most recent call last):
        ...
        TypeError: variable names specified twice inconsistently: ('x',) and 'x'
        sage: PolynomialRing(QQ, name="x", names="x")
        Traceback (most recent call last):
        ...
        TypeError: keyword argument 'name' cannot be combined with 'names'
        sage: PolynomialRing(QQ, var_array='x')
        Traceback (most recent call last):
        ...
        TypeError: you must specify the number of the variables
        sage: PolynomialRing(QQ, 2, 'x', var_array='x')
        Traceback (most recent call last):
        ...
        TypeError: unable to convert 'x' to an integer
    """
    if not ring.is_Ring(base_ring):
        raise TypeError("base_ring {!r} must be a ring".format(base_ring))

    n = -1  # Unknown number of variables
    names = None  # Unknown variable names

    # Use a single-variate ring by default unless the "singular"
    # implementation is asked.
    multivariate = kwds.get("implementation") == "singular"

    # Check specifically for None because it is an easy mistake to
    # make and Integer(None) returns 0, so we wouldn't catch this
    # otherwise.
    if any(arg is None for arg in args):
        raise TypeError(
            "invalid arguments {!r} for PolynomialRing".format(args))

    if "var_array" in kwds:
        for forbidden in "name", "names":
            if forbidden in kwds:
                raise TypeError(
                    "keyword argument '%s' cannot be combined with 'var_array'"
                    % forbidden)

        names = kwds.pop("var_array")
        if isinstance(names, (tuple, list)):
            # Input is a 1-dimensional array
            dim = 1
        else:
            # Input is a 0-dimensional (if a single string was given)
            # or a 1-dimensional array
            names = normalize_names(-1, names)
            dim = len(names) > 1
        multivariate = True

        if not args:
            raise TypeError("you must specify the number of the variables")
        # The total dimension must be at least 2
        if len(args) == 1 and not dim:
            args = [args[0], args[0]]

        # All arguments in *args should be a number of variables
        suffixes = [""]
        for arg in args:
            k = Integer(arg)
            if k < 0:
                raise ValueError("number of variables must be non-negative")
            suffixes = [s + str(i) for s in suffixes for i in range(k)]
        names = [v + s for s in suffixes for v in names]
    else:  # No "var_array" keyword
        if "name" in kwds:
            if "names" in kwds:
                raise TypeError(
                    "keyword argument 'name' cannot be combined with 'names'")
            names = [kwds.pop("name")]

        # Interpret remaining arguments in *args as either a number of
        # variables or as variable names
        for arg in args:
            try:
                k = Integer(arg)
            except TypeError:
                # Interpret arg as names
                if names is not None:
                    raise TypeError(
                        "variable names specified twice: %r and %r" %
                        (names, arg))
                names = arg
            else:
                # Interpret arg as number of variables
                if n >= 0:
                    raise TypeError(
                        "number of variables specified twice: %r and %r" %
                        (n, arg))
                if k < 0:
                    raise ValueError(
                        "number of variables must be non-negative")
                n = k
                # If number of variables was explicitly given, always
                # return a multivariate ring
                multivariate = True

    if names is None:
        try:
            names = kwds.pop("names")
        except KeyError:
            raise TypeError("you must specify the names of the variables")

    names = normalize_names(n, names)

    # At this point, we have only handled the "names" keyword if it was
    # needed. Since we know the variable names, it would logically be
    # an error to specify an additional "names" keyword. However,
    # people often abuse the preparser with
    #   R.<x> = PolynomialRing(QQ, 'x')
    # and we allow this for historical reasons. However, the names
    # must be consistent!
    if "names" in kwds:
        kwnames = kwds.pop("names")
        if kwnames != names:
            raise TypeError(
                "variable names specified twice inconsistently: %r and %r" %
                (names, kwnames))

    if multivariate or len(names) != 1:
        return _multi_variate(base_ring, names, **kwds)
    else:
        return _single_variate(base_ring, names, **kwds)
コード例 #10
0
def build_alphabet(data=None, names=None, name=None):
    r"""
    Return an object representing an ordered alphabet.

    INPUT:

    - ``data`` -- the letters of the alphabet; it can be:

      * a list/tuple/iterable of letters; the iterable may be infinite
      * an integer `n` to represent `\{1, \ldots, n\}`, or infinity to
        represent `\NN`

    - ``names`` -- (optional) a list for the letters (i.e. variable names) or
      a string for prefix for all letters; if given a list, it must have the
      same cardinality as the set represented by ``data``

    - ``name`` -- (optional) if given, then return a named set and can be
      equal to : ``'lower', 'upper', 'space',
      'underscore', 'punctuation', 'printable', 'binary', 'octal', 'decimal',
      'hexadecimal', 'radix64'``.

      You can use many of them at once, separated by spaces : ``'lower
      punctuation'`` represents the union of the two alphabets ``'lower'`` and
      ``'punctuation'``.

      Alternatively, ``name`` can be set to ``"positive integers"`` (or
      ``"PP"``) or ``"natural numbers"`` (or ``"NN"``).

      ``name`` cannot be combined with ``data``.

    EXAMPLES:

    If the argument is a Set, it just returns it::

        sage: build_alphabet(ZZ) is ZZ
        True
        sage: F = FiniteEnumeratedSet('abc')
        sage: build_alphabet(F) is F
        True

    If a list, tuple or string is provided, then it builds a proper Sage class
    (:class:`~sage.sets.totally_ordered_finite_set.TotallyOrderedFiniteSet`)::

        sage: build_alphabet([0,1,2])
        {0, 1, 2}
        sage: F = build_alphabet('abc'); F
        {'a', 'b', 'c'}
        sage: print(type(F).__name__)
        TotallyOrderedFiniteSet_with_category

    If an integer and a set is given, then it constructs a
    :class:`~sage.sets.totally_ordered_finite_set.TotallyOrderedFiniteSet`::

        sage: build_alphabet(3, ['a','b','c'])
        {'a', 'b', 'c'}

    If an integer and a string is given, then it considers that string as a
    prefix::

        sage: build_alphabet(3, 'x')
        {'x0', 'x1', 'x2'}

    If no data is provided, ``name`` may be a string which describe an alphabet.
    The available names decompose into two families. The first one are 'positive
    integers', 'PP', 'natural numbers' or 'NN' which refer to standard set of
    numbers::

        sage: build_alphabet(name="positive integers")
        Positive integers
        sage: build_alphabet(name="PP")
        Positive integers
        sage: build_alphabet(name="natural numbers")
        Non negative integers
        sage: build_alphabet(name="NN")
        Non negative integers

    The other families for the option ``name`` are among 'lower', 'upper',
    'space', 'underscore', 'punctuation', 'printable', 'binary', 'octal',
    'decimal', 'hexadecimal', 'radix64' which refer to standard set of
    characters. Theses names may be combined by separating them by a space::

        sage: build_alphabet(name="lower")
        {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}
        sage: build_alphabet(name="hexadecimal")
        {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}
        sage: build_alphabet(name="decimal punctuation")
        {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ', ',', '.', ';', ':', '!', '?'}

    In the case the alphabet is built from a list or a tuple, the order on the
    alphabet is given by the elements themselves::

        sage: A = build_alphabet([0,2,1])
        sage: A(0) < A(2)
        True
        sage: A(2) < A(1)
        False

    If a different order is needed, you may use
    :class:`~sage.sets.totally_ordered_finite_set.TotallyOrderedFiniteSet` and
    set the option ``facade`` to ``False``. That way, the comparison fits the
    order of the input::

        sage: A = TotallyOrderedFiniteSet([4,2,6,1], facade=False)
        sage: A(4) < A(2)
        True
        sage: A(1) < A(6)
        False

    Be careful, the element of the set in the last example are no more
    integers and do not compare equal with integers::

        sage: type(A.an_element())
        <class 'sage.sets.totally_ordered_finite_set.TotallyOrderedFiniteSet_with_category.element_class'>
        sage: A(1) == 1
        False
        sage: 1 == A(1)
        False

    We give an example of an infinite alphabet indexed by the positive
    integers and the prime numbers::

        sage: build_alphabet(oo, 'x')
        Lazy family (x(i))_{i in Non negative integers}
        sage: build_alphabet(Primes(), 'y')
        Lazy family (y(i))_{i in Set of all prime numbers: 2, 3, 5, 7, ...}

    TESTS::

        sage: Alphabet(3, name="punctuation")
        Traceback (most recent call last):
        ...
        ValueError: name cannot be specified with any other argument
        sage: Alphabet(8, ['e']*10)
        Traceback (most recent call last):
        ...
        ValueError: invalid value for names
        sage: Alphabet(8, x)
        Traceback (most recent call last):
        ...
        ValueError: invalid value for names
        sage: Alphabet(name=x, names="punctuation")
        Traceback (most recent call last):
        ...
        ValueError: name cannot be specified with any other argument
        sage: Alphabet(x)
        Traceback (most recent call last):
        ...
        ValueError: unable to construct an alphabet from the given parameters
    """
    # If both 'names' and 'data' are defined
    if name is not None and (data is not None or names is not None):
        raise ValueError("name cannot be specified with any other argument")

    # Swap arguments if we need to try and make sure we have "good" user input
    if isinstance(names, (int, Integer)) or names == Infinity \
            or (data is None and names is not None):
        data, names = names, data

    # data is an integer
    if isinstance(data, (int, Integer)):
        if names is None:
            from sage.sets.integer_range import IntegerRange
            return IntegerRange(Integer(data))
        if isinstance(names, str):
            return TotallyOrderedFiniteSet(
                [names + '%d' % i for i in range(data)])
        if len(names) == data:
            return TotallyOrderedFiniteSet(names)
        raise ValueError("invalid value for names")

    if data == Infinity:
        data = NonNegativeIntegers()

    # data is an iterable
    if isinstance(data, (tuple, list, str, range)) or data in Sets():
        if names is not None:
            if not isinstance(names, str):
                raise TypeError("names must be a string when data is a set")
            return Family(data, lambda i: names + str(i), name=names)
        if data in Sets():
            return data
        return TotallyOrderedFiniteSet(data)

    # Alphabet defined from a name
    if name is not None:
        if not isinstance(name, str):
            raise TypeError("name must be a string")
        if name == "positive integers" or name == "PP":
            from sage.sets.positive_integers import PositiveIntegers
            return PositiveIntegers()
        if name == "natural numbers" or name == "NN":
            return NonNegativeIntegers()

        data = []
        for alpha_name in name.split(' '):
            try:
                data.extend(list(set_of_letters[alpha_name]))
            except KeyError:
                raise TypeError("name is not recognized")
        return TotallyOrderedFiniteSet(data)

    # Alphabet(**nothing**)
    if data is None:  # name is also None
        from sage.sets.pythonclass import Set_PythonType
        return Set_PythonType(object)

    raise ValueError(
        "unable to construct an alphabet from the given parameters")
コード例 #11
0
ファイル: code_constructions.py プロジェクト: lwhsu/sagemath
def QuadraticResidueCodeEvenPair(n, F):
    """
    Quadratic residue codes of a given odd prime length and base ring
    either don't exist at all or occur as 4-tuples - a pair of
    "odd-like" codes and a pair of "even-like" codes. If `n > 2` is prime
    then (Theorem 6.6.2 in [HP2003]_) a QR code exists over `GF(q)` iff q is a
    quadratic residue mod `n`.

    They are constructed as "even-like" duadic codes associated the
    splitting (Q,N) mod n, where Q is the set of non-zero quadratic
    residues and N is the non-residues.

    EXAMPLES::

        sage: codes.QuadraticResidueCodeEvenPair(17, GF(13))  # known bug (#25896)
        ([17, 8] Cyclic Code over GF(13),
         [17, 8] Cyclic Code over GF(13))
        sage: codes.QuadraticResidueCodeEvenPair(17, GF(2))
        ([17, 8] Cyclic Code over GF(2),
         [17, 8] Cyclic Code over GF(2))
        sage: codes.QuadraticResidueCodeEvenPair(13,GF(9,"z"))  # known bug (#25896)
        ([13, 6] Cyclic Code over GF(9),
         [13, 6] Cyclic Code over GF(9))
        sage: C1,C2 = codes.QuadraticResidueCodeEvenPair(7,GF(2))
        sage: C1.is_self_orthogonal()
        True
        sage: C2.is_self_orthogonal()
        True
        sage: C3 = codes.QuadraticResidueCodeOddPair(17,GF(2))[0]
        sage: C4 = codes.QuadraticResidueCodeEvenPair(17,GF(2))[1]
        sage: C3.systematic_generator_matrix() == C4.dual_code().systematic_generator_matrix()
        True

    This is consistent with Theorem 6.6.9 and Exercise 365 in [HP2003]_.

    TESTS::

        sage: codes.QuadraticResidueCodeEvenPair(14,Zmod(4))
        Traceback (most recent call last):
        ...
        ValueError: the argument F must be a finite field
        sage: codes.QuadraticResidueCodeEvenPair(14,GF(2))
        Traceback (most recent call last):
        ...
        ValueError: the argument n must be an odd prime
        sage: codes.QuadraticResidueCodeEvenPair(5,GF(2))
        Traceback (most recent call last):
        ...
        ValueError: the order of the finite field must be a quadratic residue modulo n
    """
    from sage.arith.srange import srange
    from sage.categories.finite_fields import FiniteFields
    if F not in FiniteFields():
        raise ValueError("the argument F must be a finite field")
    q = F.order()
    n = Integer(n)
    if n <= 2 or not n.is_prime():
        raise ValueError("the argument n must be an odd prime")
    Q = quadratic_residues(n)
    Q.remove(0)  # non-zero quad residues
    N = [x for x in srange(1, n) if x not in Q]  # non-zero quad non-residues
    if q not in Q:
        raise ValueError(
            "the order of the finite field must be a quadratic residue modulo n"
        )
    return DuadicCodeEvenPair(F, Q, N)
コード例 #12
0
 def __init__(self, _pol, _dm):
     self.pol = _pol
     self.dm = Integer(_dm)
コード例 #13
0
def splitting_field(poly,
                    name,
                    map=False,
                    degree_multiple=None,
                    abort_degree=None,
                    simplify=True,
                    simplify_all=False):
    """
    Compute the splitting field of a given polynomial, defined over a
    number field.

    INPUT:

    - ``poly`` -- a monic polynomial over a number field

    - ``name`` -- a variable name for the number field

    - ``map`` -- (default: ``False``) also return an embedding of
      ``poly`` into the resulting field. Note that computing this
      embedding might be expensive.

    - ``degree_multiple`` -- a multiple of the absolute degree of
      the splitting field.  If ``degree_multiple`` equals the actual
      degree, this can enormously speed up the computation.

    - ``abort_degree`` -- abort by raising a :class:`SplittingFieldAbort`
      if it can be determined that the absolute degree of the splitting
      field is strictly larger than ``abort_degree``.

    - ``simplify`` -- (default: ``True``) during the algorithm, try
      to find a simpler defining polynomial for the intermediate
      number fields using PARI's ``polred()``.  This usually speeds
      up the computation but can also considerably slow it down.
      Try and see what works best in the given situation.

    - ``simplify_all`` -- (default: ``False``) If ``True``, simplify
      intermediate fields and also the resulting number field.

    OUTPUT:

    If ``map`` is ``False``, the splitting field as an absolute number
    field.  If ``map`` is ``True``, a tuple ``(K, phi)`` where ``phi``
    is an embedding of the base field in ``K``.

    EXAMPLES::

        sage: R.<x> = PolynomialRing(QQ)
        sage: K.<a> = (x^3 + 2).splitting_field(); K
        Number Field in a with defining polynomial x^6 + 3*x^5 + 6*x^4 + 11*x^3 + 12*x^2 - 3*x + 1
        sage: K.<a> = (x^3 - 3*x + 1).splitting_field(); K
        Number Field in a with defining polynomial x^3 - 3*x + 1

    The ``simplify`` and ``simplify_all`` flags usually yield
    fields defined by polynomials with smaller coefficients.
    By default, ``simplify`` is True and ``simplify_all`` is False.

    ::

        sage: (x^4 - x + 1).splitting_field('a', simplify=False)
        Number Field in a with defining polynomial x^24 - 2780*x^22 + 2*x^21 + 3527512*x^20 - 2876*x^19 - 2701391985*x^18 + 945948*x^17 + 1390511639677*x^16 + 736757420*x^15 - 506816498313560*x^14 - 822702898220*x^13 + 134120588299548463*x^12 + 362240696528256*x^11 - 25964582366880639486*x^10 - 91743672243419990*x^9 + 3649429473447308439427*x^8 + 14310332927134072336*x^7 - 363192569823568746892571*x^6 - 1353403793640477725898*x^5 + 24293393281774560140427565*x^4 + 70673814899934142357628*x^3 - 980621447508959243128437933*x^2 - 1539841440617805445432660*x + 18065914012013502602456565991
        sage: (x^4 - x + 1).splitting_field('a', simplify=True)
        Number Field in a with defining polynomial x^24 + 8*x^23 - 32*x^22 - 310*x^21 + 540*x^20 + 4688*x^19 - 6813*x^18 - 32380*x^17 + 49525*x^16 + 102460*x^15 - 129944*x^14 - 287884*x^13 + 372727*x^12 + 150624*x^11 - 110530*x^10 - 566926*x^9 + 1062759*x^8 - 779940*x^7 + 863493*x^6 - 1623578*x^5 + 1759513*x^4 - 955624*x^3 + 459975*x^2 - 141948*x + 53919
        sage: (x^4 - x + 1).splitting_field('a', simplify_all=True)
        Number Field in a with defining polynomial x^24 - 3*x^23 + 2*x^22 - x^20 + 4*x^19 + 32*x^18 - 35*x^17 - 92*x^16 + 49*x^15 + 163*x^14 - 15*x^13 - 194*x^12 - 15*x^11 + 163*x^10 + 49*x^9 - 92*x^8 - 35*x^7 + 32*x^6 + 4*x^5 - x^4 + 2*x^2 - 3*x + 1

    Reducible polynomials also work::

        sage: pol = (x^4 - 1)*(x^2 + 1/2)*(x^2 + 1/3)
        sage: pol.splitting_field('a', simplify_all=True)
        Number Field in a with defining polynomial x^8 - x^4 + 1

    Relative situation::

        sage: R.<x> = PolynomialRing(QQ)
        sage: K.<a> = NumberField(x^3 + 2)
        sage: S.<t> = PolynomialRing(K)
        sage: L.<b> = (t^2 - a).splitting_field()
        sage: L
        Number Field in b with defining polynomial t^6 + 2

    With ``map=True``, we also get the embedding of the base field
    into the splitting field::

        sage: L.<b>, phi = (t^2 - a).splitting_field(map=True)
        sage: phi
        Ring morphism:
          From: Number Field in a with defining polynomial x^3 + 2
          To:   Number Field in b with defining polynomial t^6 + 2
          Defn: a |--> b^2
        sage: (x^4 - x + 1).splitting_field('a', simplify_all=True, map=True)[1]
        Ring morphism:
          From: Rational Field
          To:   Number Field in a with defining polynomial x^24 - 3*x^23 + 2*x^22 - x^20 + 4*x^19 + 32*x^18 - 35*x^17 - 92*x^16 + 49*x^15 + 163*x^14 - 15*x^13 - 194*x^12 - 15*x^11 + 163*x^10 + 49*x^9 - 92*x^8 - 35*x^7 + 32*x^6 + 4*x^5 - x^4 + 2*x^2 - 3*x + 1
          Defn: 1 |--> 1

    We can enable verbose messages::

        sage: set_verbose(2)
        sage: K.<a> = (x^3 - x + 1).splitting_field()
        verbose 1 (...: splitting_field.py, splitting_field) Starting field: y
        verbose 1 (...: splitting_field.py, splitting_field) SplittingData to factor: [(3, 0)]
        verbose 2 (...: splitting_field.py, splitting_field) Done factoring (time = ...)
        verbose 1 (...: splitting_field.py, splitting_field) SplittingData to handle: [(2, 2), (3, 3)]
        verbose 1 (...: splitting_field.py, splitting_field) Bounds for absolute degree: [6, 6]
        verbose 2 (...: splitting_field.py, splitting_field) Handling polynomial x^2 + 23
        verbose 1 (...: splitting_field.py, splitting_field) New field before simplifying: x^2 + 23 (time = ...)
        verbose 1 (...: splitting_field.py, splitting_field) New field: y^2 - y + 6 (time = ...)
        verbose 2 (...: splitting_field.py, splitting_field) Converted polynomials to new field (time = ...)
        verbose 1 (...: splitting_field.py, splitting_field) SplittingData to factor: []
        verbose 2 (...: splitting_field.py, splitting_field) Done factoring (time = ...)
        verbose 1 (...: splitting_field.py, splitting_field) SplittingData to handle: [(3, 3)]
        verbose 1 (...: splitting_field.py, splitting_field) Bounds for absolute degree: [6, 6]
        verbose 2 (...: splitting_field.py, splitting_field) Handling polynomial x^3 - x + 1
        verbose 1 (...: splitting_field.py, splitting_field) New field: y^6 + 3*y^5 + 19*y^4 + 35*y^3 + 127*y^2 + 73*y + 271 (time = ...)
        sage: set_verbose(0)

    Try all Galois groups in degree 4. We use a quadratic base field
    such that ``polgalois()`` cannot be used::

        sage: R.<x> = PolynomialRing(QuadraticField(-11))
        sage: C2C2pol = x^4 - 10*x^2 + 1
        sage: C2C2pol.splitting_field('x')
        Number Field in x with defining polynomial x^8 + 24*x^6 + 608*x^4 + 9792*x^2 + 53824
        sage: C4pol = x^4 + x^3 + x^2 + x + 1
        sage: C4pol.splitting_field('x')
        Number Field in x with defining polynomial x^8 - x^7 - 2*x^6 + 5*x^5 + x^4 + 15*x^3 - 18*x^2 - 27*x + 81
        sage: D8pol = x^4 - 2
        sage: D8pol.splitting_field('x')
        Number Field in x with defining polynomial x^16 + 8*x^15 + 68*x^14 + 336*x^13 + 1514*x^12 + 5080*x^11 + 14912*x^10 + 35048*x^9 + 64959*x^8 + 93416*x^7 + 88216*x^6 + 41608*x^5 - 25586*x^4 - 60048*x^3 - 16628*x^2 + 12008*x + 34961
        sage: A4pol = x^4 - 4*x^3 + 14*x^2 - 28*x + 21
        sage: A4pol.splitting_field('x')
        Number Field in x with defining polynomial x^24 - 20*x^23 + 290*x^22 - 3048*x^21 + 26147*x^20 - 186132*x^19 + 1130626*x^18 - 5913784*x^17 + 26899345*x^16 - 106792132*x^15 + 371066538*x^14 - 1127792656*x^13 + 2991524876*x^12 - 6888328132*x^11 + 13655960064*x^10 - 23000783036*x^9 + 32244796382*x^8 - 36347834476*x^7 + 30850889884*x^6 - 16707053128*x^5 + 1896946429*x^4 + 4832907884*x^3 - 3038258802*x^2 - 200383596*x + 593179173
        sage: S4pol = x^4 + x + 1
        sage: S4pol.splitting_field('x')
        Number Field in x with defining polynomial x^48 ...

    Some bigger examples::

        sage: R.<x> = PolynomialRing(QQ)
        sage: pol15 = chebyshev_T(31, x) - 1    # 2^30*(x-1)*minpoly(cos(2*pi/31))^2
        sage: pol15.splitting_field('a')
        Number Field in a with defining polynomial x^15 - x^14 - 14*x^13 + 13*x^12 + 78*x^11 - 66*x^10 - 220*x^9 + 165*x^8 + 330*x^7 - 210*x^6 - 252*x^5 + 126*x^4 + 84*x^3 - 28*x^2 - 8*x + 1
        sage: pol48 = x^6 - 4*x^4 + 12*x^2 - 12
        sage: pol48.splitting_field('a')
        Number Field in a with defining polynomial x^48 ...

    If you somehow know the degree of the field in advance, you
    should add a ``degree_multiple`` argument.  This can speed up the
    computation, in particular for polynomials of degree >= 12 or
    for relative extensions::

        sage: pol15.splitting_field('a', degree_multiple=15)
        Number Field in a with defining polynomial x^15 + x^14 - 14*x^13 - 13*x^12 + 78*x^11 + 66*x^10 - 220*x^9 - 165*x^8 + 330*x^7 + 210*x^6 - 252*x^5 - 126*x^4 + 84*x^3 + 28*x^2 - 8*x - 1

    A value for ``degree_multiple`` which isn't actually a
    multiple of the absolute degree of the splitting field can
    either result in a wrong answer or the following exception::

        sage: pol48.splitting_field('a', degree_multiple=20)
        Traceback (most recent call last):
        ...
        ValueError: inconsistent degree_multiple in splitting_field()

    Compute the Galois closure as the splitting field of the defining polynomial::

        sage: R.<x> = PolynomialRing(QQ)
        sage: pol48 = x^6 - 4*x^4 + 12*x^2 - 12
        sage: K.<a> = NumberField(pol48)
        sage: L.<b> = pol48.change_ring(K).splitting_field()
        sage: L
        Number Field in b with defining polynomial x^48 ...

    Try all Galois groups over `\QQ` in degree 5 except for `S_5`
    (the latter is infeasible with the current implementation)::

        sage: C5pol = x^5 + x^4 - 4*x^3 - 3*x^2 + 3*x + 1
        sage: C5pol.splitting_field('x')
        Number Field in x with defining polynomial x^5 + x^4 - 4*x^3 - 3*x^2 + 3*x + 1
        sage: D10pol = x^5 - x^4 - 5*x^3 + 4*x^2 + 3*x - 1
        sage: D10pol.splitting_field('x')
        Number Field in x with defining polynomial x^10 - 28*x^8 + 216*x^6 - 681*x^4 + 902*x^2 - 401
        sage: AGL_1_5pol = x^5 - 2
        sage: AGL_1_5pol.splitting_field('x')
        Number Field in x with defining polynomial x^20 + 10*x^19 + 55*x^18 + 210*x^17 + 595*x^16 + 1300*x^15 + 2250*x^14 + 3130*x^13 + 3585*x^12 + 3500*x^11 + 2965*x^10 + 2250*x^9 + 1625*x^8 + 1150*x^7 + 750*x^6 + 400*x^5 + 275*x^4 + 100*x^3 + 75*x^2 + 25
        sage: A5pol = x^5 - x^4 + 2*x^2 - 2*x + 2
        sage: A5pol.splitting_field('x')
        Number Field in x with defining polynomial x^60 ...

    We can use the ``abort_degree`` option if we don't want to compute
    fields of too large degree (this can be used to check whether the
    splitting field has small degree)::

        sage: (x^5+x+3).splitting_field('b', abort_degree=119)
        Traceback (most recent call last):
        ...
        SplittingFieldAbort: degree of splitting field equals 120
        sage: (x^10+x+3).splitting_field('b', abort_degree=60)  # long time (10s on sage.math, 2014)
        Traceback (most recent call last):
        ...
        SplittingFieldAbort: degree of splitting field is a multiple of 180

    Use the ``degree_divisor`` attribute to recover the divisor of the
    degree of the splitting field or ``degree_multiple`` to recover a
    multiple::

        sage: from sage.rings.number_field.splitting_field import SplittingFieldAbort
        sage: try:  # long time (4s on sage.math, 2014)
        ....:     (x^8+x+1).splitting_field('b', abort_degree=60, simplify=False)
        ....: except SplittingFieldAbort as e:
        ....:     print e.degree_divisor
        ....:     print e.degree_multiple
        120
        1440

    TESTS::

        sage: from sage.rings.number_field.splitting_field import splitting_field
        sage: splitting_field(polygen(QQ), name='x', map=True, simplify_all=True)
        (Number Field in x with defining polynomial x, Ring morphism:
          From: Rational Field
          To:   Number Field in x with defining polynomial x
          Defn: 1 |--> 1)
    """
    from sage.misc.all import verbose, cputime

    degree_multiple = Integer(degree_multiple or 0)
    abort_degree = Integer(abort_degree or 0)

    # Kpol = PARI polynomial in y defining the extension found so far
    F = poly.base_ring()
    if is_RationalField(F):
        Kpol = pari("'y")
    else:
        Kpol = F.pari_polynomial("y")
    # Fgen = the generator of F as element of Q[y]/Kpol
    # (only needed if map=True)
    if map:
        Fgen = F.gen()._pari_()
    verbose("Starting field: %s" % Kpol)

    # L and Lred are lists of SplittingData.
    # L contains polynomials which are irreducible over K,
    # Lred contains polynomials which need to be factored.
    L = []
    Lred = [SplittingData(poly._pari_with_name(), degree_multiple)]

    # Main loop, handle polynomials one by one
    while True:
        # Absolute degree of current field K
        absolute_degree = Integer(Kpol.poldegree())

        # Compute minimum relative degree of splitting field
        rel_degree_divisor = Integer(1)
        for splitting in L:
            rel_degree_divisor = rel_degree_divisor.lcm(splitting.poldegree())

        # Check for early aborts
        abort_rel_degree = abort_degree // absolute_degree
        if abort_rel_degree and rel_degree_divisor > abort_rel_degree:
            raise SplittingFieldAbort(absolute_degree * rel_degree_divisor,
                                      degree_multiple)

        # First, factor polynomials in Lred and store the result in L
        verbose("SplittingData to factor: %s" %
                [s._repr_tuple() for s in Lred])
        t = cputime()
        for splitting in Lred:
            m = splitting.dm.gcd(degree_multiple).gcd(
                factorial(splitting.poldegree()))
            if m == 1:
                continue
            factors = Kpol.nffactor(splitting.pol)[0]
            for q in factors:
                d = q.poldegree()
                fac = factorial(d)
                # Multiple of the degree of the splitting field of q,
                # note that the degree equals fac iff the Galois group is S_n.
                mq = m.gcd(fac)
                if mq == 1:
                    continue
                # Multiple of the degree of the splitting field of q
                # over the field defined by adding square root of the
                # discriminant.
                # If the Galois group is contained in A_n, then mq_alt is
                # also the degree multiple over the current field K.
                # Here, we have equality if the Galois group is A_n.
                mq_alt = mq.gcd(fac // 2)

                # If we are over Q, then use PARI's polgalois() to compute
                # these degrees exactly.
                if absolute_degree == 1:
                    try:
                        G = q.polgalois()
                    except PariError:
                        pass
                    else:
                        mq = Integer(G[0])
                        mq_alt = mq // 2 if (G[1] == -1) else mq

                # In degree 4, use the cubic resolvent to refine the
                # degree bounds.
                if d == 4 and mq >= 12:  # mq equals 12 or 24
                    # Compute cubic resolvent
                    a0, a1, a2, a3, a4 = (q / q.pollead()).Vecrev()
                    assert a4 == 1
                    cubicpol = pari([
                        4 * a0 * a2 - a1 * a1 - a0 * a3 * a3, a1 * a3 - 4 * a0,
                        -a2, 1
                    ]).Polrev()
                    cubicfactors = Kpol.nffactor(cubicpol)[0]
                    if len(cubicfactors) == 1:  # A4 or S4
                        # After adding a root of the cubic resolvent,
                        # the degree of the extension defined by q
                        # is a factor 3 smaller.
                        L.append(SplittingData(cubicpol, 3))
                        rel_degree_divisor = rel_degree_divisor.lcm(3)
                        mq = mq // 3  # 4 or 8
                        mq_alt = 4
                    elif len(cubicfactors) == 2:  # C4 or D8
                        # The irreducible degree 2 factor is
                        # equivalent to x^2 - q.poldisc().
                        discpol = cubicfactors[1]
                        L.append(SplittingData(discpol, 2))
                        mq = mq_alt = 4
                    else:  # C2 x C2
                        mq = mq_alt = 4

                if mq > mq_alt >= 3:
                    # Add quadratic resolvent x^2 - D to decrease
                    # the degree multiple by a factor 2.
                    discpol = pari([-q.poldisc(), 0, 1]).Polrev()
                    discfactors = Kpol.nffactor(discpol)[0]
                    if len(discfactors) == 1:
                        # Discriminant is not a square
                        L.append(SplittingData(discpol, 2))
                        rel_degree_divisor = rel_degree_divisor.lcm(2)
                    mq = mq_alt

                L.append(SplittingData(q, mq))
                rel_degree_divisor = rel_degree_divisor.lcm(q.poldegree())
                if abort_rel_degree and rel_degree_divisor > abort_rel_degree:
                    raise SplittingFieldAbort(
                        absolute_degree * rel_degree_divisor, degree_multiple)
        verbose("Done factoring", t, level=2)

        if len(L) == 0:  # Nothing left to do
            break

        # Recompute absolute degree multiple
        new_degree_multiple = absolute_degree
        for splitting in L:
            new_degree_multiple *= splitting.dm
        degree_multiple = new_degree_multiple.gcd(degree_multiple)

        # Absolute degree divisor
        degree_divisor = rel_degree_divisor * absolute_degree

        # Sort according to degree to handle low degrees first
        L.sort(key=lambda x: x.key())
        verbose("SplittingData to handle: %s" % [s._repr_tuple() for s in L])
        verbose("Bounds for absolute degree: [%s, %s]" %
                (degree_divisor, degree_multiple))

        # Check consistency
        if degree_multiple % degree_divisor != 0:
            raise ValueError(
                "inconsistent degree_multiple in splitting_field()")
        for splitting in L:
            # The degree of the splitting field must be a multiple of
            # the degree of the polynomial. Only do this check for
            # SplittingData with minimal dm, because the higher dm are
            # defined as relative degree over the splitting field of
            # the polynomials with lesser dm.
            if splitting.dm > L[0].dm:
                break
            if splitting.dm % splitting.poldegree() != 0:
                raise ValueError(
                    "inconsistent degree_multiple in splitting_field()")

        # Add a root of f = L[0] to construct the field N = K[x]/f(x)
        splitting = L[0]
        f = splitting.pol
        verbose("Handling polynomial %s" % (f.lift()), level=2)
        t = cputime()
        Npol, KtoN, k = Kpol.rnfequation(f, flag=1)

        # Make Npol monic integral primitive, store in Mpol
        # (after this, we don't need Npol anymore, only Mpol)
        Mdiv = pari(1)
        Mpol = Npol
        while True:
            denom = Integer(Mpol.pollead())
            if denom == 1:
                break
            denom = pari(denom.factor().radical_value())
            Mpol = (Mpol * (denom**Mpol.poldegree())).subst(
                "x",
                pari([0, 1 / denom]).Polrev("x"))
            Mpol /= Mpol.content()
            Mdiv *= denom

        # We are finished for sure if we hit the degree bound
        finished = (Mpol.poldegree() >= degree_multiple)

        if simplify_all or (simplify and not finished):
            # Find a simpler defining polynomial Lpol for Mpol
            verbose("New field before simplifying: %s" % Mpol, t)
            t = cputime()
            M = Mpol.polred(flag=3)
            n = len(M[0]) - 1
            Lpol = M[1][n].change_variable_name("y")
            LtoM = M[0][n].change_variable_name("y").Mod(
                Mpol.change_variable_name("y"))
            MtoL = LtoM.modreverse()
        else:
            # Lpol = Mpol
            Lpol = Mpol.change_variable_name("y")
            MtoL = pari("'y")

        NtoL = MtoL / Mdiv
        KtoL = KtoN.lift().subst("x", NtoL).Mod(Lpol)
        Kpol = Lpol  # New Kpol (for next iteration)
        verbose("New field: %s" % Kpol, t)
        if map:
            t = cputime()
            Fgen = Fgen.lift().subst("y", KtoL)
            verbose("Computed generator of F in K", t, level=2)
        if finished:
            break

        t = cputime()

        # Convert f and elements of L from K to L and store in L
        # (if the polynomial is certain to remain irreducible) or Lred.
        Lold = L[1:]
        L = []
        Lred = []

        # First add f divided by the linear factor we obtained,
        # mg is the new degree multiple.
        mg = splitting.dm // f.poldegree()
        if mg > 1:
            g = [c.subst("y", KtoL).Mod(Lpol) for c in f.Vecrev().lift()]
            g = pari(g).Polrev()
            g /= pari([k * KtoL - NtoL, 1]).Polrev()  # divide linear factor
            Lred.append(SplittingData(g, mg))

        for splitting in Lold:
            g = [c.subst("y", KtoL) for c in splitting.pol.Vecrev().lift()]
            g = pari(g).Polrev()
            mg = splitting.dm
            if Integer(g.poldegree()).gcd(
                    f.poldegree()) == 1:  # linearly disjoint fields
                L.append(SplittingData(g, mg))
            else:
                Lred.append(SplittingData(g, mg))
        verbose("Converted polynomials to new field", t, level=2)

    # Convert Kpol to Sage and construct the absolute number field
    Kpol = PolynomialRing(RationalField(),
                          name=poly.variable_name())(Kpol / Kpol.pollead())
    K = NumberField(Kpol, name)
    if map:
        return K, F.hom(Fgen, K)
    else:
        return K
コード例 #14
0
    def create_object(self, version, key, **kwds):
        """
        EXAMPLES::

            sage: K = GF(19) # indirect doctest
            sage: TestSuite(K).run()

        We try to create finite fields with various implementations::

            sage: k = GF(2, impl='modn')
            sage: k = GF(2, impl='givaro')
            sage: k = GF(2, impl='ntl')
            sage: k = GF(2, impl='pari')
            Traceback (most recent call last):
            ...
            ValueError: the degree must be at least 2
            sage: k = GF(2, impl='supercalifragilisticexpialidocious')
            Traceback (most recent call last):
            ...
            ValueError: no such finite field implementation: 'supercalifragilisticexpialidocious'
            sage: k.<a> = GF(2^15, impl='modn')
            Traceback (most recent call last):
            ...
            ValueError: the 'modn' implementation requires a prime order
            sage: k.<a> = GF(2^15, impl='givaro')
            sage: k.<a> = GF(2^15, impl='ntl')
            sage: k.<a> = GF(2^15, impl='pari')
            sage: k.<a> = GF(3^60, impl='modn')
            Traceback (most recent call last):
            ...
            ValueError: the 'modn' implementation requires a prime order
            sage: k.<a> = GF(3^60, impl='givaro')
            Traceback (most recent call last):
            ...
            ValueError: q must be < 2^16
            sage: k.<a> = GF(3^60, impl='ntl')
            Traceback (most recent call last):
            ...
            ValueError: q must be a 2-power
            sage: k.<a> = GF(3^60, impl='pari')
        """
        # 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 = Integer(order).factor()[0]
            proof = True
            prefix = kwds.get('prefix', None)
            # We can set the defaults here to be those for givaro
            #   as they are otherwise ignored
            repr = 'poly'
            elem_cache = (order < 500)
        elif len(key) == 8:
            # For backward compatibility of pickles (see trac #21433)
            order, name, modulus, impl, _, p, n, proof = key
            prefix = kwds.get('prefix', None)
            # We can set the defaults here to be those for givaro
            #   as they are otherwise ignored
            repr = kwds.get('repr', 'poly')
            elem_cache = kwds.get('elem_cache', (order < 500))
        else:
            order, name, modulus, impl, p, n, proof, prefix, repr, elem_cache = key

        if impl == 'modn':
            if n != 1:
                raise ValueError(
                    "the 'modn' implementation requires a prime order")
            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, modulus=modulus)
        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.
            from sage.structure.proof.all import WithProof
            with WithProof('arithmetic', proof):
                if impl == 'givaro':
                    K = FiniteField_givaro(order, name, modulus, repr,
                                           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' or impl == 'pari':
                    from .finite_field_pari_ffelt import FiniteField_pari_ffelt
                    K = FiniteField_pari_ffelt(p, modulus, name)
                else:
                    raise ValueError(
                        "no such finite field implementation: %r" % impl)

            # Temporary; see create_key_and_extra_args() above.
            if prefix is not None:
                K._prefix = prefix

        return K
コード例 #15
0
    def _find_scaling_period(self):
        r"""
        Uses the integral period map of the modular symbol implementation in sage
        in order to determine the scaling. The resulting modular symbol is correct
        only for the `X_0`-optimal curve, at least up to a possible factor +- a
        power of 2.

        EXAMPLES::

            sage: E = EllipticCurve('11a1')
            sage: m = sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1,normalize='period')
            sage: m._e
            (1/5, 1)
            sage: E = EllipticCurve('11a2')
            sage: m = sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1,normalize='period')
            sage: m._e
            (1, 5)
            sage: E = EllipticCurve('121b2')
            sage: m = sage.schemes.elliptic_curves.ell_modular_symbols.ModularSymbolSage(E,+1,normalize='period')
            sage: m._e
            (0, 11/2, 0, 11/2, 11/2, 0, 0, -3, 2, 1/2, -1, 3/2)

        TESTS::

            sage: E = EllipticCurve('19a1')
            sage: m = E.modular_symbol(sign=+1, implementation='sage', normalize='none')
            sage: m._find_scaling_period()
            sage: m._scaling
            1

            sage: E = EllipticCurve('19a2')
            sage: m = E.modular_symbol(sign=+1, implementation='sage', normalize='none')
            sage: m._scaling
            1
            sage: m._find_scaling_period()
            sage: m._scaling
            3
        """
        P = self._modsym.integral_period_mapping()
        self._e = P.matrix().transpose().row(0)
        self._e /= 2
        E = self._E
        try:
            crla = parse_cremona_label(E.label())
        except RuntimeError:  # raised when curve is outside of the table
            print(
                "Warning : Could not normalize the modular symbols, maybe all further results will be multiplied by a rational number."
            )
            self._scaling = 1
        else:
            cr0 = Integer(crla[0]).str() + crla[1] + '1'
            E0 = EllipticCurve(cr0)
            if self._sign == 1:
                q = E0.period_lattice().basis()[0] / E.period_lattice().basis(
                )[0]
            else:
                q = E0.period_lattice().basis()[1].imag() / E.period_lattice(
                ).basis()[1].imag()
                if E0.real_components() == 1:
                    q *= 2
                if E.real_components() == 1:
                    q /= 2
            q = QQ(int(round(q * 200))) / 200
            verbose('scale modular symbols by %s' % q)
            self._scaling = q
        c = self(0)  #  required, to change base point from oo to 0
        if c < 0:
            c *= -1
            self._scaling *= -1
        self._at_zero = c
        self._e *= self._scaling
コード例 #16
0
def are_hyperplanes_in_projective_geometry_parameters(v,
                                                      k,
                                                      lmbda,
                                                      return_parameters=False):
    r"""
    Return ``True`` if the parameters ``(v,k,lmbda)`` are the one of hyperplanes in
    a (finite Desarguesian) projective space.

    In other words, test whether there exists a prime power ``q`` and an integer
    ``d`` greater than two such that:

    - `v = (q^{d+1}-1)/(q-1) = q^d + q^{d-1} + ... + 1`
    - `k = (q^d - 1)/(q-1) = q^{d-1} + q^{d-2} + ... + 1`
    - `lmbda = (q^{d-1}-1)/(q-1) = q^{d-2} + q^{d-3} + ... + 1`

    If it exists, such a pair ``(q,d)`` is unique.

    INPUT:

    - ``v,k,lmbda`` (integers)

    OUTPUT:

    - a boolean or, if ``return_parameters`` is set to ``True`` a pair
      ``(True, (q,d))`` or ``(False, (None,None))``.

    EXAMPLES::

        sage: from sage.combinat.designs.block_design import are_hyperplanes_in_projective_geometry_parameters
        sage: are_hyperplanes_in_projective_geometry_parameters(40,13,4)
        True
        sage: are_hyperplanes_in_projective_geometry_parameters(40,13,4,return_parameters=True)
        (True, (3, 3))
        sage: PG = designs.ProjectiveGeometryDesign(3,2,GF(3))
        sage: PG.is_t_design(return_parameters=True)
        (True, (2, 40, 13, 4))

        sage: are_hyperplanes_in_projective_geometry_parameters(15,3,1)
        False
        sage: are_hyperplanes_in_projective_geometry_parameters(15,3,1,return_parameters=True)
        (False, (None, None))

    TESTS::

        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 [3,4,5,7,8,9,11]:
        ....:     for d in [2,3,4,5]:
        ....:         v,k,l = sgp(q,d)
        ....:         assert are_hyperplanes_in_projective_geometry_parameters(v,k,l,True) == (True, (q,d))
        ....:         assert are_hyperplanes_in_projective_geometry_parameters(v+1,k,l) is False
        ....:         assert are_hyperplanes_in_projective_geometry_parameters(v-1,k,l) is False
        ....:         assert are_hyperplanes_in_projective_geometry_parameters(v,k+1,l) is False
        ....:         assert are_hyperplanes_in_projective_geometry_parameters(v,k-1,l) is False
        ....:         assert are_hyperplanes_in_projective_geometry_parameters(v,k,l+1) is False
        ....:         assert are_hyperplanes_in_projective_geometry_parameters(v,k,l-1) is False
    """
    import sage.arith.all as arith

    q1 = Integer(v - k)
    q2 = Integer(k - lmbda)

    if (lmbda <= 0 or q1 < 4 or q2 < 2 or not q1.is_prime_power()
            or not q2.is_prime_power()):
        return (False, (None, None)) if return_parameters else False

    p1, e1 = q1.factor()[0]
    p2, e2 = q2.factor()[0]

    k = arith.gcd(e1, e2)
    d = e1 // k
    q = p1**k
    if e2 // k != d - 1 or lmbda != (q**(d - 1) - 1) // (q - 1):
        return (False, (None, None)) if return_parameters else False

    return (True, (q, d)) if return_parameters else True
コード例 #17
0
    def polynomial(self, n):
        r"""
        Return the pseudo-Conway polynomial of degree `n` in this
        lattice.

        INPUT:

        - ``n`` -- positive integer

        OUTPUT:

        - a pseudo-Conway polynomial of degree `n` for the prime `p`.

        ALGORITHM:

        Uses an algorithm described in [HL99]_, modified to find
        pseudo-Conway polynomials rather than Conway polynomials.  The
        major difference is that we stop as soon as we find a
        primitive polynomial.

        REFERENCE:

        .. [HL99] \L. Heath and N. Loehr (1999).  New algorithms for
           generating Conway polynomials over finite fields.
           Proceedings of the tenth annual ACM-SIAM symposium on
           discrete algorithms, pp. 429-437.

        EXAMPLES::

            sage: from sage.rings.finite_rings.conway_polynomials import PseudoConwayLattice
            sage: PCL = PseudoConwayLattice(2, use_database=False)
            sage: PCL.polynomial(3)
            x^3 + x + 1
            sage: PCL.polynomial(4)
            x^4 + x^3 + 1
            sage: PCL.polynomial(60)
            x^60 + x^59 + x^58 + x^55 + x^54 + x^53 + x^52 + x^51 + x^48 + x^46 + x^45 + x^42 + x^41 + x^39 + x^38 + x^37 + x^35 + x^32 + x^31 + x^30 + x^28 + x^24 + x^22 + x^21 + x^18 + x^17 + x^16 + x^15 + x^14 + x^10 + x^8 + x^7 + x^5 + x^3 + x^2 + x + 1
        """
        if n in self.nodes:
            return self.nodes[n]

        p = self.p
        n = Integer(n)

        if n == 1:
            f = self.ring.gen() - FiniteField(p).multiplicative_generator()
            self.nodes[1] = f
            return f

        # Work in an arbitrary field K of order p**n.
        K = FiniteField(p**n, names='a')

        # TODO: something like the following
        # gcds = [n.gcd(d) for d in self.nodes.keys()]
        # xi = { m: (...) for m in gcds }
        xi = {
            q: self.polynomial(n // q).any_root(K,
                                                -n // q,
                                                assume_squarefree=True)
            for q in n.prime_divisors()
        }

        # The following is needed to ensure that in the concrete instantiation
        # of the "new" extension all previous choices are compatible.
        _frobenius_shift(K, xi)

        # Construct a compatible element having order the lcm of orders
        q, x = xi.popitem()
        v = p**(n // q) - 1
        for q, xitem in six.iteritems(xi):
            w = p**(n // q) - 1
            g, alpha, beta = v.xgcd(w)
            x = x**beta * xitem**alpha
            v = v.lcm(w)

        r = p**n - 1
        # Get the missing part of the order to be primitive
        g = r // v
        # Iterate through g-th roots of x until a primitive one is found
        z = x.nth_root(g)
        root = K.multiplicative_generator()**v
        while z.multiplicative_order() != r:
            z *= root
        # The following should work but tries to create a huge list
        # whose length overflows Python's ints for large parameters
        #Z = x.nth_root(g, all=True)
        #for z in Z:
        #    if z.multiplicative_order() == r:
        #         break
        f = z.minimal_polynomial()
        self.nodes[n] = f
        return f
コード例 #18
0
ファイル: latin_squares.py プロジェクト: shalec/sage
def MOLS_table(start,stop=None,compare=False,width=None):
    r"""
    Prints the MOLS table that Sage can produce.

    INPUT:

    - ``start,stop`` (integers) -- print the table of MOLS for value of `n` such
      that ``start<=n<stop``. If only one integer is given as input, it is
      interpreted as the value of ``stop`` with ``start=0`` (same behaviour as
      ``range``).

    - ``compare`` (boolean) -- if sets to ``True`` the MOLS displays
      with `+` and `-` entries its difference with the table from the
      Handbook of Combinatorial Designs (2ed).

    - ``width`` (integer) -- the width of each column of the table. By default,
      it is computed from range of values determined by the parameters ``start``
      and ``stop``.

    EXAMPLES::

        sage: from sage.combinat.designs.latin_squares import MOLS_table
        sage: MOLS_table(100)
               0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19
            ________________________________________________________________________________
          0| +oo +oo   1   2   3   4   1   6   7   8   2  10   5  12   4   4  15  16   5  18
         20|   4   5   3  22   7  24   4  26   5  28   4  30  31   5   4   5   8  36   4   5
         40|   7  40   5  42   5   6   4  46   8  48   6   5   5  52   5   6   7   7   5  58
         60|   5  60   5   6  63   7   5  66   5   6   6  70   7  72   5   7   6   6   6  78
         80|   9  80   8  82   6   6   6   6   7  88   6   7   6   6   6   6   7  96   6   8
        sage: MOLS_table(100, width=4)
                 0    1    2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19
             ____________________________________________________________________________________________________
           0|  +oo  +oo    1    2    3    4    1    6    7    8    2   10    5   12    4    4   15   16    5   18
          20|    4    5    3   22    7   24    4   26    5   28    4   30   31    5    4    5    8   36    4    5
          40|    7   40    5   42    5    6    4   46    8   48    6    5    5   52    5    6    7    7    5   58
          60|    5   60    5    6   63    7    5   66    5    6    6   70    7   72    5    7    6    6    6   78
          80|    9   80    8   82    6    6    6    6    7   88    6    7    6    6    6    6    7   96    6    8
        sage: MOLS_table(100, compare=True)
               0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19
            ________________________________________________________________________________
          0|                                                           +               +
         20|
         40|
         60|   +
         80|
        sage: MOLS_table(50, 100, compare=True)
               0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19
            ________________________________________________________________________________
         40|
         60|   +
         80|
    """
    from .orthogonal_arrays import largest_available_k
    if stop is None:
        start,stop = 0,start
    # make start and stop be congruent to 0 mod 20
    start = start - (start%20)
    stop  = stop-1
    stop  = stop  + (20-(stop%20))
    assert start%20 == 0 and stop%20 == 0
    if stop <= start:
        return

    if compare:
        from sage.env import SAGE_SHARE
        handbook_file = open(SAGE_SHARE+"/combinatorial_designs/MOLS_table.txt",'r')
        hb = [int(_) for _ in handbook_file.readlines()[9].split(',')]
        handbook_file.close()

    # choose an appropriate width (needs to be >= 3 because "+oo" should fit)
    if width is None:
        from sage.rings.integer import Integer
        width = max(3, Integer(stop-1).ndigits(10))

    print(" " * (width + 2) + " ".join("{i:>{width}}".format(i=i,width=width)
                                       for i in range(20)))
    print(" " * (width + 1) + "_" * ((width + 1) * 20), end="")
    for i in range(start,stop):
        if i % 20 == 0:
            print("\n{:>{width}}|".format(i, width=width), end="")
        k = largest_available_k(i)-2
        if compare:
            if i < 2 or hb[i] == k:
                c = ""
            elif hb[i] < k:
                c = "+"
            else:
                c = "-"
        else:
            if i < 2:
                c = "+oo"
            else:
                c = k
        print(' {:>{width}}'.format(c, width=width), end="")
コード例 #19
0
    def _derivative_(self, z, m, diff_param):
        """
        EXAMPLES::

            sage: x,m = var('x,m')
            sage: elliptic_f(x,m).diff(x)
            1/sqrt(-m*sin(x)^2 + 1)
            sage: elliptic_f(x,m).diff(m)
            -1/2*elliptic_f(x, m)/m
            + 1/4*sin(2*x)/(sqrt(-m*sin(x)^2 + 1)*(m - 1))
            - 1/2*elliptic_e(x, m)/((m - 1)*m)
        """
        if diff_param == 0:
            return Integer(1) / sqrt(Integer(1) - m * sin(z)**Integer(2))
        elif diff_param == 1:
            return (elliptic_e(z, m) / (Integer(2) * (Integer(1) - m) * m) -
                    elliptic_f(z, m) / (Integer(2) * m) -
                    (sin(Integer(2) * z) /
                     (Integer(4) * (Integer(1) - m) *
                      sqrt(Integer(1) - m * sin(z)**Integer(2)))))
コード例 #20
0
    def frequency_distribution(self, length=1, prec=0):
        """
        Returns the probability space of character frequencies. The output
        of this method is different from that of the method
        :func:`characteristic_frequency()
        <sage.monoids.string_monoid.AlphabeticStringMonoid.characteristic_frequency>`.
        One can think of the characteristic frequency probability of an
        element in an alphabet `A` as the expected probability of that element
        occurring. Let `S` be a string encoded using elements of `A`. The
        frequency probability distribution corresponding to `S` provides us
        with the frequency probability of each element of `A` as observed
        occurring in `S`. Thus one distribution provides expected
        probabilities, while the other provides observed probabilities.

        INPUT:

        - ``length`` -- (default ``1``) if ``length=1`` then consider the
          probability space of monogram frequency, i.e. probability
          distribution of single characters. If ``length=2`` then consider
          the probability space of digram frequency, i.e. probability
          distribution of pairs of characters. This method currently
          supports the generation of probability spaces for monogram
          frequency (``length=1``) and digram frequency (``length=2``).

        - ``prec`` -- (default ``0``) a non-negative integer representing
          the precision (in number of bits) of a floating-point number. The
          default value ``prec=0`` means that we use 53 bits to represent
          the mantissa of a floating-point number. For more information on
          the precision of floating-point numbers, see the function
          :func:`RealField() <sage.rings.real_mpfr.RealField>` or refer to the module
          :mod:`real_mpfr <sage.rings.real_mpfr>`.

        EXAMPLES:

        Capital letters of the English alphabet::

            sage: M = AlphabeticStrings().encoding("abcd")
            sage: L = M.frequency_distribution().function()
            sage: sorted(L.items())
            <BLANKLINE>
            [(A, 0.250000000000000),
            (B, 0.250000000000000),
            (C, 0.250000000000000),
            (D, 0.250000000000000)]

        The binary number system::

            sage: M = BinaryStrings().encoding("abcd")
            sage: L = M.frequency_distribution().function()
            sage: sorted(L.items())
            [(0, 0.593750000000000), (1, 0.406250000000000)]

        The hexadecimal number system::

            sage: M = HexadecimalStrings().encoding("abcd")
            sage: L = M.frequency_distribution().function()
            sage: sorted(L.items())
            <BLANKLINE>
            [(1, 0.125000000000000),
            (2, 0.125000000000000),
            (3, 0.125000000000000),
            (4, 0.125000000000000),
            (6, 0.500000000000000)]

        Get the observed frequency probability distribution of digrams in the
        string "ABCD". This string consists of the following digrams: "AB",
        "BC", and "CD". Now find out the frequency probability of each of
        these digrams as they occur in the string "ABCD"::

            sage: M = AlphabeticStrings().encoding("abcd")
            sage: D = M.frequency_distribution(length=2).function()
            sage: sorted(D.items())
            [(AB, 0.333333333333333), (BC, 0.333333333333333), (CD, 0.333333333333333)]
        """
        if not length in (1, 2):
            raise NotImplementedError("Not implemented")
        if prec == 0:
            RR = RealField()
        else:
            RR = RealField(prec)
        S = self.parent()
        n = S.ngens()
        if length == 1:
            Alph = S.gens()
        else:
            Alph = tuple([ x*y for x in S.gens() for y in S.gens() ])
        X = {}
        N = len(self)-length+1
        eps = RR(Integer(1)/N)
        for i in range(N):
            c = self[i:i+length]
            if c in X:
                X[c] += eps
            else:
                X[c] = eps
        # Return a dictionary of probability distribution. This should
        # allow for easier parsing of the dictionary.
        from sage.probability.random_variable import DiscreteProbabilitySpace
        return DiscreteProbabilitySpace(Alph, X, RR)
コード例 #21
0
def carmichael_lambda(n):
    r"""
    Return the Carmichael function of a positive integer ``n``.

    The Carmichael function of `n`, denoted `\lambda(n)`, is the smallest
    positive integer `k` such that `a^k \equiv 1 \pmod{n}` for all
    `a \in \ZZ/n\ZZ` satisfying `\gcd(a, n) = 1`. Thus, `\lambda(n) = k`
    is the exponent of the multiplicative group `(\ZZ/n\ZZ)^{\ast}`.

    INPUT:

    - ``n`` -- a positive integer.

    OUTPUT:

    - The Carmichael function of ``n``.

    ALGORITHM:

    If `n = 2, 4` then `\lambda(n) = \varphi(n)`. Let `p \geq 3` be an odd
    prime and let `k` be a positive integer. Then
    `\lambda(p^k) = p^{k - 1}(p - 1) = \varphi(p^k)`. If `k \geq 3`, then
    `\lambda(2^k) = 2^{k - 2}`. Now consider the case where `n > 3` is
    composite and let `n = p_1^{k_1} p_2^{k_2} \cdots p_t^{k_t}` be the
    prime factorization of `n`. Then

    .. MATH::

        \lambda(n)
        = \lambda(p_1^{k_1} p_2^{k_2} \cdots p_t^{k_t})
        = \text{lcm}(\lambda(p_1^{k_1}), \lambda(p_2^{k_2}), \dots, \lambda(p_t^{k_t}))

    EXAMPLES:

    The Carmichael function of all positive integers up to and including 10::

        sage: from sage.crypto.util import carmichael_lambda
        sage: list(map(carmichael_lambda, [1..10]))
        [1, 1, 2, 2, 4, 2, 6, 2, 6, 4]

    The Carmichael function of the first ten primes::

        sage: list(map(carmichael_lambda, primes_first_n(10)))
        [1, 2, 4, 6, 10, 12, 16, 18, 22, 28]

    Cases where the Carmichael function is equivalent to the Euler phi
    function::

        sage: carmichael_lambda(2) == euler_phi(2)
        True
        sage: carmichael_lambda(4) == euler_phi(4)
        True
        sage: p = random_prime(1000, lbound=3, proof=True)
        sage: k = randint(1, 1000)
        sage: carmichael_lambda(p^k) == euler_phi(p^k)
        True

    A case where `\lambda(n) \neq \varphi(n)`::

        sage: k = randint(1, 1000)
        sage: carmichael_lambda(2^k) == 2^(k - 2)
        True
        sage: carmichael_lambda(2^k) == 2^(k - 2) == euler_phi(2^k)
        False

    Verifying the current implementation of the Carmichael function using
    another implementation. The other implementation that we use for
    verification is an exhaustive search for the exponent of the
    multiplicative group `(\ZZ/n\ZZ)^{\ast}`. ::

        sage: from sage.crypto.util import carmichael_lambda
        sage: n = randint(1, 500)
        sage: c = carmichael_lambda(n)
        sage: def coprime(n):
        ....:     return [i for i in range(n) if gcd(i, n) == 1]
        sage: def znpower(n, k):
        ....:     L = coprime(n)
        ....:     return list(map(power_mod, L, [k]*len(L), [n]*len(L)))
        sage: def my_carmichael(n):
        ....:     for k in range(1, n):
        ....:         L = znpower(n, k)
        ....:         ones = [1] * len(L)
        ....:         T = [L[i] == ones[i] for i in range(len(L))]
        ....:         if all(T):
        ....:             return k
        sage: c == my_carmichael(n)
        True

    Carmichael's theorem states that `a^{\lambda(n)} \equiv 1 \pmod{n}`
    for all elements `a` of the multiplicative group `(\ZZ/n\ZZ)^{\ast}`.
    Here, we verify Carmichael's theorem. ::

        sage: from sage.crypto.util import carmichael_lambda
        sage: n = randint(1, 1000)
        sage: c = carmichael_lambda(n)
        sage: ZnZ = IntegerModRing(n)
        sage: M = ZnZ.list_of_elements_of_multiplicative_group()
        sage: ones = [1] * len(M)
        sage: P = [power_mod(a, c, n) for a in M]
        sage: P == ones
        True

    TESTS:

    The input ``n`` must be a positive integer::

        sage: from sage.crypto.util import carmichael_lambda
        sage: carmichael_lambda(0)
        Traceback (most recent call last):
        ...
        ValueError: Input n must be a positive integer.
        sage: carmichael_lambda(randint(-10, 0))
        Traceback (most recent call last):
        ...
        ValueError: Input n must be a positive integer.

    Bug reported in :trac:`8283`::

        sage: from sage.crypto.util import carmichael_lambda
        sage: type(carmichael_lambda(16))
        <type 'sage.rings.integer.Integer'>

    REFERENCES:

    - :wikipedia:`Carmichael_function`
    """
    n = Integer(n)
    # sanity check
    if n < 1:
        raise ValueError("Input n must be a positive integer.")

    L = n.factor()
    t = []

    # first get rid of the prime factor 2
    if n & 1 == 0:
        e = L[0][1]
        L = L[1:]   # now, n = 2**e * L.value()
        if e < 3:   # for 1 <= k < 3, lambda(2**k) = 2**(k - 1)
            e = e - 1
        else:       # for k >= 3, lambda(2**k) = 2**(k - 2)
            e = e - 2
        t.append(1 << e)  # 2**e

    # then other prime factors
    t += [p**(k - 1) * (p - 1) for p, k in L]

    # finish the job
    return lcm(t)
コード例 #22
0
ファイル: ascii_art.py プロジェクト: chenkenshin/sage
    def __add__(self, Nelt):
        r"""
        Concatenate two ascii art object.

        By default, when two object are concatenated, the new one will be
        splittable between both.

        If the baseline is defined, the concatenation is computed such that the
        new baseline coincidate with the olders.

        For example, let `T` be a tree with it's baseline ascii art
        representation in the middle::

            o
             \
              o
             / \
            o   o

        and let `M` be a matrix with it's baseline ascii art representation at
        the middle two::

            [1 2 3]
            [4 5 6]
            [7 8 9]

        then the concatenation of both will give::

            o
             \   [1 2 3]
              o  [4 5 6]
             / \ [7 8 9]
            o   o

        If one of the objects has not baseline, the concatenation is realized
        from the top::

            o    [1 2 3]
             \   [4 5 6]
              o  [7 8 9]
             / \
            o   o

        TESTS::

            sage: from sage.misc.ascii_art import AsciiArt
            sage: l5 = AsciiArt(lines=['|' for _ in range(5)], baseline=2); l5
            |
            |
            |
            |
            |
            sage: l3 = AsciiArt(lines=['|' for _ in range(3)], baseline=1); l3
            |
            |
            |
            sage: l3 + l5
             |
            ||
            ||
            ||
             |
            sage: l5 + l3
            |
            ||
            ||
            ||
            |
            sage: l5._baseline = 0
            sage: l5 + l3
            |
            |
            |
            ||
            ||
             |
            sage: l5._baseline = 4
            sage: l5 + l3
             |
            ||
            ||
            |
            |
            |
            sage: l3._baseline = 0
            sage: l3 + l5
            |
            |
            ||
             |
             |
             |
             |
        """
        new_matrix = []
        new_h = AsciiArt._compute_new_h(self, Nelt)
        new_baseline = AsciiArt._compute_new_baseline(self, Nelt)

        if self._baseline != None and Nelt._baseline != None:
            # left traitement
            for line in self._matrix:
                new_matrix.append(line + " "**Integer(self._l - len(line)))

            if new_h > self._h:
                # |                 new_h > self._h
                # |                 new_baseline > self._baseline
                # ||<-- baseline    number of white lines at the bottom
                #  | }               :: Nelt._baseline - self._baseline
                #  | }
                if new_baseline > self._baseline:
                    for k in range(new_baseline - self._baseline):
                        new_matrix.append(" "**Integer(self._l))
                #  | }              new_h > self._h
                #  | }              new_h - new_baseline > self._h - self._baseline
                # ||<-- baseline    number of white lines at the top
                # ||                :: new_h - new_baseline - self._h + self._baseline
                # ||
                #  |
                #  |
                if new_h - new_baseline > self._h - self._baseline:
                    for _ in range((new_h - new_baseline) -
                                   (self._h - self._baseline)):
                        new_matrix.insert(0, " "**Integer(self._l))

            # right traitement
            i = 0
            if new_h > Nelt._h:
                # |  }              new_h > Nelt._h
                # |  }              new_h - new_baseline > Nelt._h - self._baseline
                # ||<-- baseline    number of white lines at the top
                # ||                :: new_h - new_baseline - Nelt._h + Nelt._baseline
                # ||
                # ||
                # |

                i = max(new_h - new_baseline - Nelt._h + Nelt._baseline, 0)

            for j in range(Nelt._h):
                new_matrix[i + j] += Nelt._matrix[j]
        else:
            for line in self._matrix:
                new_matrix.append(line + " "**Integer(self._l - len(line)))
            for i, line_i in enumerate(Nelt._matrix):
                if i == len(new_matrix):
                    new_matrix.append(" "**Integer(self._l) + line_i)
                else:
                    new_matrix[i] += line_i

        # breakpoint
        new_breakpoints = list(self._breakpoints)
        new_breakpoints.append(self._l)
        for bp in Nelt._breakpoints:
            new_breakpoints.append(bp + self._l)
        from sage.misc.misc import uniq
        return AsciiArt(lines=new_matrix,
                        breakpoints=uniq(new_breakpoints),
                        baseline=new_baseline,
                        atomic=False)
コード例 #23
0
    def period(self, m):
        """
        Return the period of the binary recurrence sequence modulo
        an integer ``m``.

        If `n_1` is congruent to `n_2` modulo ``period(m)``, then `u_{n_1}` is
        is congruent to `u_{n_2}` modulo ``m``.

        INPUT:

        - ``m`` -- an integer (modulo which the period of the recurrence relation is calculated).

        OUTPUT:

        - The integer (the period of the sequence modulo m)

        EXAMPLES:

        If `p = \\pm 1 \\mod 5`, then the period of the Fibonacci sequence
        mod `p` is `p-1` (c.f. Lemma 3.3 of [BMS2006]_).

        ::

            sage: R = BinaryRecurrenceSequence(1,1)
            sage: R.period(31)
            30

            sage: [R(i) % 4 for i in range(12)]
            [0, 1, 1, 2, 3, 1, 0, 1, 1, 2, 3, 1]
            sage: R.period(4)
            6

        This function works for degenerate sequences as well.

        ::

            sage: S = BinaryRecurrenceSequence(2,0,1,2)
            sage: S.is_degenerate()
            True
            sage: S.is_geometric()
            True
            sage: [S(i) % 17 for i in range(16)]
            [1, 2, 4, 8, 16, 15, 13, 9, 1, 2, 4, 8, 16, 15, 13, 9]
            sage: S.period(17)
            8

        Note: the answer is cached.
        """

        #If we have already computed the period mod m, then we return the stored value.

        if m in self._period_dict:
            return self._period_dict[m]

        else:
            R = Integers(m)
            A = matrix(R, [[0, 1], [self.c, self.b]])
            w = matrix(R, [[self.u0], [self.u1]])
            Fac = list(m.factor())
            Periods = {}

            #To compute the period mod m, we compute the least integer n such that A^n*w == w.  This necessarily
            #divides the order of A as a matrix in GL_2(Z/mZ).

            #We compute the period modulo all distinct prime powers dividing m, and combine via the lcm.
            #To compute the period mod p^e, we first compute the order mod p.  Then the period mod p^e
            #must divide p^{4e-4}*period(p), as the subgroup of matrices mod p^e, which reduce to
            #the identity mod p is of order (p^{e-1})^4.  So we compute the period mod p^e by successively
            #multiplying the period mod p by powers of p.

            for i in Fac:
                p = i[0]
                e = i[1]
                #first compute the period mod p
                if p in self._period_dict:
                    perp = self._period_dict[p]
                else:
                    F = A.change_ring(GF(p))
                    v = w.change_ring(GF(p))
                    FF = F**(p - 1)
                    p1fac = list((p - 1).factor())

                    #The order of any matrix in GL_2(F_p) either divides p(p-1) or (p-1)(p+1).
                    #The order divides p-1 if it is diagonalizable.  In any case, det(F^(p-1))=1,
                    #so if tr(F^(p-1)) = 2, then it must be triangular of the form [[1,a],[0,1]].
                    #The order of the subgroup of matrices of this form is p, so the order must divide
                    #p(p-1) -- in fact it must be a multiple of p.  If this is not the case, then the
                    #order divides (p-1)(p+1).  As the period divides the order of the matrix in GL_2(F_p),
                    #these conditions hold for the period as well.

                    #check if the order divides (p-1)
                    if FF * v == v:
                        M = p - 1
                        Mfac = p1fac

                    #check if the trace is 2, then the order is a multiple of p dividing p*(p-1)
                    elif (FF).trace() == 2:
                        M = p - 1
                        Mfac = p1fac
                        F = F**p  #replace F by F^p as now we only need to determine the factor dividing (p-1)

                    #otherwise it will divide (p+1)(p-1)
                    else:
                        M = (p + 1) * (p - 1)
                        p2fac = list(
                            (p + 1).factor()
                        )  #factor the (p+1) and (p-1) terms separately and then combine for speed
                        Mfac_dic = {}
                        for i in list(p1fac + p2fac):
                            if i[0] not in Mfac_dic:
                                Mfac_dic[i[0]] = i[1]
                            else:
                                Mfac_dic[i[0]] = Mfac_dic[i[0]] + i[1]
                        Mfac = [(i, Mfac_dic[i]) for i in Mfac_dic]

                    #Now use a fast order algorithm to compute the period.  We know that the period divides
                    #M = i_1*i_2*...*i_l where the i_j denote not necessarily distinct prime factors.  As
                    #F^M*v == v, for each i_j, if F^(M/i_j)*v == v, then the period divides (M/i_j).  After
                    #all factors have been iterated over, the result is the period mod p.

                    Mfac = list(Mfac)
                    C = []

                    #expand the list of prime factors so every factor is with multiplicity 1

                    for i in range(len(Mfac)):
                        for j in range(Mfac[i][1]):
                            C.append(Mfac[i][0])

                    Mfac = C
                    n = M
                    for i in Mfac:
                        b = Integer(n / i)
                        if F**b * v == v:
                            n = b
                    perp = n

                #Now compute the period mod p^e by stepping up by multiples of p
                F = A.change_ring(Integers(p**e))
                v = w.change_ring(Integers(p**e))
                FF = F**perp
                if FF * v == v:
                    perpe = perp
                else:
                    tries = 0
                    while True:
                        tries += 1
                        FF = FF**p
                        if FF * v == v:
                            perpe = perp * p**tries
                            break
                Periods[p] = perpe

            #take the lcm of the periods mod all distinct primes dividing m
            period = 1
            for p in Periods:
                period = lcm(Periods[p], period)

            self._period_dict[m] = period  #cache the period mod m
            return period
コード例 #24
0
ファイル: linear_extensions.py プロジェクト: shalec/sage
    def cardinality(self):
        """
        Return the number of linear extensions.

        EXAMPLES::

            sage: N = Poset({0: [2, 3], 1: [3]})
            sage: N.linear_extensions().cardinality()
            5

        TESTS::

            sage: Poset().linear_extensions().cardinality()
            1
            sage: Posets.ChainPoset(1).linear_extensions().cardinality()
            1
            sage: Posets.BooleanLattice(4).linear_extensions().cardinality()
            1680384
        """
        from sage.rings.integer import Integer

        n = len(self._poset)
        if not n:
            return Integer(1)

        up = self._poset._hasse_diagram.to_dictionary()
        # Convert to the Hasse diagram so our poset can be realized on
        # the set {0,...,n-1} with a nice dictionary of edges

        for i in range(n):
            up[n - 1 - i] = sorted(
                set(up[n - 1 - i] +
                    [item for x in up[n - 1 - i] for item in up[x]]))
        # Compute the principal order filter for each element.

        Jup = {1: []}
        # Jup will be a dictionary giving up edges in J(P)

        # We will perform a loop where after k loops, we will have a
        # list of up edges for the lattice of order ideals for P
        # restricted to entries 0,...,k.
        loc = [1] * n

        # This list will be indexed by entries in P. After k loops,
        # the entry loc[i] will correspond to the element of J(P) that
        # is the principal order ideal of i, restricted to the
        # elements 0,...,k .

        m = 1
        # m keeps track of how many elements we currently have in J(P).
        # We start with just the empty order ideal, and no relations.
        for x in range(n):
            # Use the existing Jup table to compute all covering
            # relations in J(P) for things that are above loc(x).
            K = [[loc[x]]]
            j = 0
            while K[j]:
                K.append([b for a in K[j] for b in Jup[a]])
                j += 1
            K = sorted(set(item for sublist in K for item in sublist))
            for j in range(len(K)):
                i = m + j + 1
                Jup[i] = [m + K.index(a) + 1 for a in Jup[K[j]]]
                # These are copies of the covering relations with
                # elements from K, but now with the underlying
                # elements containing x.
                Jup[K[j]] = Jup[K[j]] + [i]
                # There are the new covering relations we get between
                # ideals that don't contain x and those that do.
            for y in up[x]:
                loc[y] = K.index(loc[y]) + m + 1
                # Updates loc[y] if y is above x.
            m += len(K)
        # Now we have a dictionary of covering relations for J(P). The
        # following shortcut works to count maximal chains, since we
        # made J(P) naturally labelled, and J(P) has a unique maximal
        # element and minimum element.

        Jup[m] = Integer(1)
        while m > 1:
            m -= 1
            ct = Integer(0)
            for j in Jup[m]:
                ct += Jup[j]
            Jup[m] = ct
        return ct
コード例 #25
0
def frac(a, b):
    """
    Return the fraction ``a/b``.
    """
    return Integer(a) / Integer(b)
コード例 #26
0
    def __init__(self, *l, **d):
        """
        TESTS::

            sage: s = AbelianStratum(0)
            sage: s == loads(dumps(s))
            True
            sage: s = AbelianStratum(1,1,1,1)
            sage: s == loads(dumps(s))
            True

            sage: AbelianStratum('no','way')
            Traceback (most recent call last):
            ...
            ValueError: input must be a list of integers

            sage: AbelianStratum([1,1,1,1], marked_separatrix='full')
            Traceback (most recent call last):
            ...
            ValueError: marked_separatrix must be one of 'no', 'in', 'out'
        """
        if l == ():
            pass

        elif hasattr(l[0], "__iter__") and len(l) == 1:
            l = l[0]

        if not all(isinstance(i, (Integer, int)) for i in l):
            raise ValueError("input must be a list of integers")

        if 'marked_separatrix' in d:
            m = d['marked_separatrix']

            if m is None:
                m = 'no'

            if (m != 'no' and m != 'in' and m != 'out'):
                raise ValueError("marked_separatrix must be one of 'no', "
                                 "'in', 'out'")
            self._marked_separatrix = m

        else:  # default value
            self._marked_separatrix = 'no'

        self._zeroes = list(l)

        if not self._marked_separatrix == 'no':
            self._zeroes[1:] = sorted(self._zeroes[1:], reverse=True)
        else:
            self._zeroes.sort(reverse=True)

        self._genus = sum(l) / 2 + 1

        self._genus = Integer(self._genus)

        zeroes = sorted(x for x in self._zeroes if x > 0)

        if self._genus == 1:
            self._cc = (HypCCA, )

        elif self._genus == 2:
            self._cc = (HypCCA, )

        elif self._genus == 3:
            if zeroes == [2, 2] or zeroes == [4]:
                self._cc = (HypCCA, OddCCA)
            else:
                self._cc = (CCA, )

        elif len(zeroes) == 1:
            # just one zeros [2g-2]
            self._cc = (HypCCA, OddCCA, EvenCCA)

        elif zeroes == [self._genus - 1, self._genus - 1]:
            # two similar zeros [g-1, g-1]
            if self._genus % 2 == 0:
                self._cc = (HypCCA, NonHypCCA)

            else:
                self._cc = (HypCCA, OddCCA, EvenCCA)

        elif len([x for x in zeroes if x % 2]) == 0:
            # even zeroes [2 l_1, 2 l_2, ..., 2 l_n]
            self._cc = (OddCCA, EvenCCA)

        else:
            self._cc = (CCA, )
コード例 #27
0
    def _render_on_subplot(self, subplot):
        """
        TESTS:

        A somewhat random plot, but fun to look at::

            sage: x,y = var('x,y')
            sage: contour_plot(x^2-y^3+10*sin(x*y), (x, -4, 4), (y, -4, 4),plot_points=121,cmap='hsv')
        """
        from sage.rings.integer import Integer
        options = self.options()
        fill = options['fill']
        contours = options['contours']
        if options.has_key('cmap'):
            cmap = get_cmap(options['cmap'])
        elif fill or contours is None:
            cmap = get_cmap('gray')
        else:
            if isinstance(contours, (int, Integer)):
                cmap = get_cmap([(i, i, i)
                                 for i in xsrange(0, 1, 1 / contours)])
            else:
                l = Integer(len(contours))
                cmap = get_cmap([(i, i, i) for i in xsrange(0, 1, 1 / l)])

        x0, x1 = float(self.xrange[0]), float(self.xrange[1])
        y0, y1 = float(self.yrange[0]), float(self.yrange[1])

        if isinstance(contours, (int, Integer)):
            contours = int(contours)

        CSF = None
        if fill:
            if contours is None:
                CSF = subplot.contourf(self.xy_data_array,
                                       cmap=cmap,
                                       extent=(x0, x1, y0, y1),
                                       label=options['legend_label'])
            else:
                CSF = subplot.contourf(self.xy_data_array,
                                       contours,
                                       cmap=cmap,
                                       extent=(x0, x1, y0, y1),
                                       extend='both',
                                       label=options['legend_label'])

        linewidths = options.get('linewidths', None)
        if isinstance(linewidths, (int, Integer)):
            linewidths = int(linewidths)
        elif isinstance(linewidths, (list, tuple)):
            linewidths = tuple(int(x) for x in linewidths)
        linestyles = options.get('linestyles', None)
        if contours is None:
            CS = subplot.contour(self.xy_data_array,
                                 cmap=cmap,
                                 extent=(x0, x1, y0, y1),
                                 linewidths=linewidths,
                                 linestyles=linestyles,
                                 label=options['legend_label'])
        else:
            CS = subplot.contour(self.xy_data_array,
                                 contours,
                                 cmap=cmap,
                                 extent=(x0, x1, y0, y1),
                                 linewidths=linewidths,
                                 linestyles=linestyles,
                                 label=options['legend_label'])
        if options.get('labels', False):
            label_options = options['label_options']
            label_options['fontsize'] = int(label_options['fontsize'])
            if fill and label_options is None:
                label_options['inline'] = False
            subplot.clabel(CS, **label_options)
        if options.get('colorbar', False):
            colorbar_options = options['colorbar_options']
            from matplotlib import colorbar
            cax, kwds = colorbar.make_axes_gridspec(subplot,
                                                    **colorbar_options)
            if CSF is None:
                cb = colorbar.Colorbar(cax, CS, **kwds)
            else:
                cb = colorbar.Colorbar(cax, CSF, **kwds)
                cb.add_lines(CS)
コード例 #28
0
from sage.modular.modsym.all import ModularSymbols
from sage.libs.eclib.newforms import ECModularSymbol
from sage.databases.cremona import parse_cremona_label

from sage.arith.all import next_prime, kronecker_symbol, prime_divisors, valuation
from sage.rings.infinity import unsigned_infinity as infinity
from sage.rings.integer import Integer
from sage.modular.cusps import Cusps
from sage.rings.integer_ring import ZZ
from sage.rings.rational_field import QQ
from sage.misc.all import verbose

from sage.schemes.elliptic_curves.constructor import EllipticCurve

oo = Cusps(infinity)
zero = Integer(0)


def modular_symbol_space(E, sign, base_ring, bound=None):
    r"""
    Creates the space of modular symbols of a given sign over a give base_ring,
    attached to the isogeny class of the elliptic curve ``E``.

    INPUT:

    - ``E`` - an elliptic curve over `\QQ`
    - ``sign`` - integer, -1, 0, or 1
    - ``base_ring`` - ring
    - ``bound`` - (default: None) maximum number of Hecke operators to
      use to cut out modular symbols factor.  If None, use
      enough to provably get the correct answer.
コード例 #29
0
        def _cardinality_from_iterator(self, *ignored_args, **ignored_kwds):
            """
            The cardinality of ``self``.

            OUTPUT: an ``Integer``

            This brute force implementation of :meth:`cardinality`
            iterates through the elements of ``self`` to count them.

            EXAMPLES::

                sage: C = FiniteEnumeratedSets().example(); C
                An example of a finite enumerated set: {1,2,3}
                sage: C._cardinality_from_iterator()
                3

            This is the default implementation of :meth:`cardinality`
            from the category ``FiniteEnumeratedSet()``. To test this,
            we need a fresh example::

                sage: from sage.categories.examples.finite_enumerated_sets import Example
                sage: class FreshExample(Example): pass
                sage: C = FreshExample(); C.rename("FreshExample")
                sage: C.cardinality
                <bound method FreshExample_with_category._cardinality_from_iterator of FreshExample>

            TESTS:

            This method shall return an ``Integer``; we test this
            here, because :meth:`_test_enumerated_set_iter_cardinality`
            does not do it for us::

                sage: type(C._cardinality_from_iterator())
                <type 'sage.rings.integer.Integer'>

            We ignore additional inputs since during doctests classes which
            override ``cardinality()`` call up to the category rather than
            their own ``cardinality()`` method (see :trac:`13688`)::

                sage: C = FiniteEnumeratedSets().example()
                sage: C._cardinality_from_iterator(algorithm='testing')
                3

            Here is a more complete example::

                sage: class TestParent(Parent):
                ...     def __init__(self):
                ...         Parent.__init__(self, category=FiniteEnumeratedSets())
                ...     def __iter__(self):
                ...         yield 1
                ...         return
                ...     def cardinality(self, dummy_arg):
                ...         return 1 # we don't want to change the semantics of cardinality()
                sage: P = TestParent()
                sage: P.cardinality(-1)
                1
                sage: v = P.list(); v
                [1]
                sage: P.cardinality()
                1
                sage: P.cardinality('use alt algorithm') # Used to break here: see :trac:`13688`
                1
                sage: P.cardinality(dummy_arg='use alg algorithm') # Used to break here: see :trac:`13688`
                1
            """
            c = 0
            for _ in self:
                c += 1
            return Integer(c)
コード例 #30
0
ファイル: cyclic_code.py プロジェクト: lwhsu/sagemath
    def defining_set(self, primitive_root=None):
        r"""
        Returns the set of exponents of the roots of ``self``'s generator
        polynomial over the extension field. Of course, it depends on the
        choice of the primitive root of the splitting field.


        INPUT:

        - ``primitive_root`` (optional) -- a primitive root of the extension
          field

        EXAMPLES:

        We provide a defining set at construction time::

            sage: F = GF(16, 'a')
            sage: n = 15
            sage: C = codes.CyclicCode(length=n, field=F, D=[1,2])
            sage: C.defining_set()
            [1, 2]

        If the defining set was provided by the user, it might have been
        expanded at construction time. In this case, the expanded defining set
        will be returned::

            sage: C = codes.CyclicCode(length=13, field=F, D=[1, 2])
            sage: C.defining_set()
            [1, 2, 3, 5, 6, 9]

        If a generator polynomial was passed at construction time,
        the defining set is computed using this polynomial::

            sage: R.<x> = F[]
            sage: n = 7
            sage: g = x ** 3 + x + 1
            sage: C = codes.CyclicCode(generator_pol=g, length=n)
            sage: C.defining_set()
            [1, 2, 4]

        Both operations give the same result::

            sage: C1 = codes.CyclicCode(length=n, field=F, D=[1, 2, 4])
            sage: C1.generator_polynomial() == g
            True

        Another one, in a reversed order::

            sage: n = 13
            sage: C1 = codes.CyclicCode(length=n, field=F, D=[1, 2])
            sage: g = C1.generator_polynomial()
            sage: C2 = codes.CyclicCode(generator_pol=g, length=n)
            sage: C1.defining_set() == C2.defining_set()
            True
        """
        if (hasattr(self, "_defining_set")
                and (primitive_root is None
                     or primitive_root == self._primitive_root)):
            return self._defining_set
        else:
            F = self.base_field()
            n = self.length()
            q = F.cardinality()
            g = self.generator_polynomial()

            s = Zmod(n)(q).multiplicative_order()

            if primitive_root is None:
                Fsplit, F_to_Fsplit = F.extension(Integer(s), map=True)
                FE = RelativeFiniteFieldExtension(Fsplit,
                                                  F,
                                                  embedding=F_to_Fsplit)
                alpha = Fsplit.zeta(n)
            else:
                try:
                    alpha = primitive_root
                    Fsplit = alpha.parent()
                    FE = RelativeFiniteFieldExtension(Fsplit, F)
                    F_to_Fsplit = FE.embedding()
                except ValueError:
                    raise ValueError("primitive_root does not belong to the "
                                     "right splitting field")
                if alpha.multiplicative_order() != n:
                    raise ValueError("primitive_root must have multiplicative "
                                     "order equal to the code length")

            Rsplit = Fsplit['xx']
            gsplit = Rsplit([F_to_Fsplit(coeff) for coeff in g])
            roots = gsplit.roots(multiplicities=False)
            D = [root.log(alpha) for root in roots]
            self._field_embedding = FE
            self._primitive_root = alpha
            self._defining_set = sorted(D)
            return self._defining_set