diff --git a/src/sage/rings/polynomial/ore_polynomial_element.pyx b/src/sage/rings/polynomial/ore_polynomial_element.pyx index f6081b1cc1a..328010cf83e 100644 --- a/src/sage/rings/polynomial/ore_polynomial_element.pyx +++ b/src/sage/rings/polynomial/ore_polynomial_element.pyx @@ -20,7 +20,7 @@ AUTHORS: - Xavier Caruso (2020-05) """ -############################################################################# +# *************************************************************************** # Copyright (C) 2020 Xavier Caruso # # This program is free software: you can redistribute it and/or modify @@ -28,7 +28,7 @@ AUTHORS: # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # http://www.gnu.org/licenses/ -#**************************************************************************** +# *************************************************************************** import re from cysignals.signals cimport sig_check diff --git a/src/sage/rings/polynomial/ore_polynomial_ring.py b/src/sage/rings/polynomial/ore_polynomial_ring.py index 16294384bcf..f5f6a6253d9 100644 --- a/src/sage/rings/polynomial/ore_polynomial_ring.py +++ b/src/sage/rings/polynomial/ore_polynomial_ring.py @@ -1,9 +1,10 @@ r""" Univariate Ore Polynomial Rings -This module provides the :class:`~sage.rings.polynomial.ore_polynomial_ring.OrePolynomialRing`. -which constructs a general dense univariate Ore polynomial ring over a commutative base with -equipped with an endomorphism and/or a derivation. +This module provides the +:class:`~sage.rings.polynomial.ore_polynomial_ring.OrePolynomialRing`, +which constructs a general dense univariate Ore polynomial ring over a +commutative base with equipped with an endomorphism and/or a derivation. AUTHOR: @@ -68,14 +69,14 @@ class OrePolynomialRing(UniqueRepresentation, Algebra): - ``names`` -- a string or a list of strings - - ``sparse`` -- a boolean (default: ``False``). Currently not supported. + - ``sparse`` -- a boolean (default: ``False``); currently not supported EXAMPLES: .. RUBRIC:: The case of a twisting endomorphism We create the Ore ring `\GF{5^3}[x, \text{Frob}]` where Frob is the - Frobenius endomorphism. + Frobenius endomorphism:: sage: k. = GF(5^3) sage: Frob = k.frobenius_endomorphism() @@ -96,7 +97,7 @@ class OrePolynomialRing(UniqueRepresentation, Algebra): We emphasize that it is necessary to repeat the name of the variable in the right hand side. Indeed, the following fails (it is interpreted - by Sage as a classical polynomial ring with variable name ``Frob``). + by Sage as a classical polynomial ring with variable name ``Frob``):: sage: T. = k[Frob] Traceback (most recent call last): @@ -147,13 +148,15 @@ class OrePolynomialRing(UniqueRepresentation, Algebra): sage: F. = Qq(3^2) sage: sigma = F.frobenius_endomorphism(); sigma - Frobenius endomorphism on 3-adic Unramified Extension Field in u defined by x^2 + 2*x + 2 lifting u |--> u^3 on the residue field + Frobenius endomorphism on 3-adic Unramified Extension Field in u + defined by x^2 + 2*x + 2 lifting u |--> u^3 on the residue field sage: der = F.derivation(3, twist=sigma); der (3 + O(3^21))*([Frob] - id) sage: M. = F['X', der] sage: M - Ore Polynomial Ring in X over 3-adic Unramified Extension Field in u defined by x^2 + 2*x + 2 twisted by Frob and (3 + O(3^21))*([Frob] - id) + Ore Polynomial Ring in X over 3-adic Unramified Extension Field in u + defined by x^2 + 2*x + 2 twisted by Frob and (3 + O(3^21))*([Frob] - id) We emphasize that we only need to pass in the twisted derivation as it already contains in it the datum of the twisting endomorphism. @@ -166,6 +169,8 @@ class OrePolynomialRing(UniqueRepresentation, Algebra): .. RUBRIC:: Examples of variable name context + Consider the following:: + sage: R. = ZZ[] sage: sigma = R.hom([t+1]) sage: S. = SkewPolynomialRing(R, sigma); S @@ -187,7 +192,7 @@ class OrePolynomialRing(UniqueRepresentation, Algebra): .. RUBRIC:: Uniqueness and immutability In Sage, there is exactly one Ore polynomial ring for each quadruple - (base ring, twisting morphism, twisting derivation, name of the variable). + (base ring, twisting morphism, twisting derivation, name of the variable):: sage: k. = GF(7^3) sage: Frob = k.frobenius_endomorphism() @@ -642,12 +647,12 @@ def characteristic(self): """ return self.base_ring().characteristic() - @cached_method def twisting_morphism(self, n=1): r""" - Return the twisting endomorphism defining this Ore polynomial ring iterated ``n`` times - or ``None`` if this Ore polynomial ring is not twisted by an endomorphism. + Return the twisting endomorphism defining this Ore polynomial ring + iterated ``n`` times or ``None`` if this Ore polynomial ring is not + twisted by an endomorphism. INPUT: @@ -676,7 +681,8 @@ def twisting_morphism(self, n=1): sage: T.twisting_morphism(-1) Frobenius endomorphism a |--> a^(5^2) on Finite Field in a of size 5^3 - Sometimes it fails, even if the twisting morphism is actually invertible:: + Sometimes it fails, even if the twisting morphism is + actually invertible:: sage: K = R.fraction_field() sage: phi = K.hom([(t+1)/(t-1)]) @@ -722,10 +728,11 @@ def twisting_morphism(self, n=1): def twist_map(self, n=1): r""" - Return the twisting endomorphism defining this Ore polynomial ring iterated ``n`` times - or ``None`` if this Ore polynomial ring is not twisted by an endomorphism. + Return the twisting endomorphism defining this Ore polynomial ring + iterated ``n`` times or ``None`` if this Ore polynomial ring is not + twisted by an endomorphism. - This method is deprecated. You should use :meth:`twisting_morphism` instead. + This method is deprecated. Use :meth:`twisting_morphism` instead. INPUT: @@ -772,7 +779,6 @@ def twisting_derivation(self): """ return self._derivation - @cached_method def gen(self, n=0): r""" @@ -869,8 +875,8 @@ def is_exact(self): def is_sparse(self): r""" - Return ``True`` if the elements of this Ore polynomial ring are sparsely - represented. + Return ``True`` if the elements of this Ore polynomial ring are + sparsely represented. .. WARNING:: @@ -933,15 +939,17 @@ def random_element(self, degree=2, monic=False, *args, **kwds): sage: S.random_element(monic=True) # random x^2 + (2*t^2 + t + 1)*x + 3*t^2 + 3*t + 2 - Use ``degree`` to obtain polynomials of higher degree + Use ``degree`` to obtain polynomials of higher degree:: sage: p = S.random_element(degree=5) # random (t^2 + 3*t)*x^4 + (4*t + 4)*x^3 + (4*t^2 + 4*t)*x^2 + (2*t^2 + 1)*x + 3 + sage: p.degree() <= 5 + True When ``monic`` is ``False``, the returned Ore polynomial may have a degree less than ``degree`` (it happens when the random leading - coefficient is zero). However, if ``monic`` is ``True``, this can't - happen:: + coefficient is zero). However, if ``monic`` is ``True``, this + cannot happen:: sage: p = S.random_element(degree=4, monic=True) sage: p.leading_coefficient() == S.base_ring().one() @@ -1051,3 +1059,4 @@ def is_commutative(self): True """ return self._morphism is None and self._derivation is None + diff --git a/src/sage/rings/polynomial/skew_polynomial_element.pyx b/src/sage/rings/polynomial/skew_polynomial_element.pyx index 0fd90c93d22..6ccb5e0d2f3 100644 --- a/src/sage/rings/polynomial/skew_polynomial_element.pyx +++ b/src/sage/rings/polynomial/skew_polynomial_element.pyx @@ -36,10 +36,9 @@ AUTHORS: - Johan Rosenkilde (2016-08-03): changes for bug fixes, docstring and doctest errors - """ -############################################################################# +# *************************************************************************** # Copyright (C) 2012 Xavier Caruso # # This program is free software: you can redistribute it and/or modify @@ -345,7 +344,8 @@ cdef class SkewPolynomial_generic_dense(OrePolynomial_generic_dense): sage: a.operator_eval(t) 2*t^2 + 2*t + 3 - Evaluation points outside the base ring is usually not possible due to the twisting morphism:: + Evaluation points outside the base ring is usually not possible + due to the twisting morphism:: sage: R. = QQ[] sage: sigma = R.hom([t+1]) @@ -354,7 +354,9 @@ cdef class SkewPolynomial_generic_dense(OrePolynomial_generic_dense): sage: a.operator_eval(1/t) Traceback (most recent call last): ... - TypeError: 1/t fails to convert into the map's domain Univariate Polynomial Ring in t over Rational Field, but a `pushforward` method is not properly implemented + TypeError: 1/t fails to convert into the map's domain + Univariate Polynomial Ring in t over Rational Field, + but a `pushforward` method is not properly implemented """ cdef RingHomomorphism sigma = self._parent.twisting_morphism() cdef list coefficients = self.list() @@ -414,7 +416,7 @@ cdef class SkewPolynomial_generic_dense(OrePolynomial_generic_dense): return r def multi_point_evaluation(self, eval_pts): - """ + r""" Evaluate ``self`` at list of evaluation points. INPUT: @@ -431,7 +433,7 @@ cdef class SkewPolynomial_generic_dense(OrePolynomial_generic_dense): repeatedly. If fast skew polynomial multiplication is available, an asymptotically faster method is possible using standard divide and conquer techniques and - :meth:`sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing_general.minimal_vanishing_polynomial`. + :meth:`~sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing.minimal_vanishing_polynomial`. EXAMPLES:: @@ -671,3 +673,4 @@ cdef class SkewPolynomial_generic_dense(OrePolynomial_generic_dense): q.append(c) q.reverse() return (self._new_c(q, parent), self._new_c(a[:db], parent, 1)) + diff --git a/src/sage/rings/polynomial/skew_polynomial_finite_field.pyx b/src/sage/rings/polynomial/skew_polynomial_finite_field.pyx index ac6288866f0..3a5334610b6 100644 --- a/src/sage/rings/polynomial/skew_polynomial_finite_field.pyx +++ b/src/sage/rings/polynomial/skew_polynomial_finite_field.pyx @@ -1,19 +1,21 @@ r""" Univariate Dense Skew Polynomials over Finite Fields -This module provides the :class:`~sage.rings.polynomial.skew_polynomial_finite_field.SkewPolynomial_finite_field_dense` -which constructs a single univariate skew polynomial over a finite field equipped with the Frobenius -endomorphism. Among other things, it implements the fast factorization algorithm designed in [CL2017]_. +This module provides the +class:`~sage.rings.polynomial.skew_polynomial_finite_field.SkewPolynomial_finite_field_dense`, +which constructs a single univariate skew polynomial over a finite field +equipped with the Frobenius endomorphism. Among other things, it implements +the fast factorization algorithm designed in [CL2017]_. AUTHOR:: - Xavier Caruso (2012-06-29): initial version -- Arpit Merchant (2016-08-04): improved docstrings, fixed doctests and refactored classes and methods - +- Arpit Merchant (2016-08-04): improved docstrings, fixed doctests and + refactored classes and methods """ -############################################################################# +# *************************************************************************** # Copyright (C) 2012 Xavier Caruso # # This program is free software: you can redistribute it and/or modify @@ -55,8 +57,8 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): return self._norm_factor def is_irreducible(self): - """ - Return True if this skew polynomial is irreducible. + r""" + Return ``True`` if this skew polynomial is irreducible. EXAMPLES:: @@ -103,13 +105,13 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): def type(self, N): - """ + r""" Return the `N`-type of this skew polynomial (see definition below). INPUT: - - ``N`` -- an irreducible polynomial in the - center of the underlying skew polynomial ring + - ``N`` -- an irreducible polynomial in the + center of the underlying skew polynomial ring .. NOTE:: @@ -118,11 +120,11 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): DEFINITION: The `N`-type of a skew polynomial `a` is the Partition - `(t_0, t_1, t_2, ...)` defined by + `(t_0, t_1, t_2, \ldots)` defined by .. MATH:: - t_0 + \cdots + t_i = \frac{\deg gcd(a,N^i)}{\deg N} + t_0 + \cdots + t_i = \frac{\deg gcd(a,N^i)}{\deg N}, where `\deg N` is the degree of `N` considered as an element in the center. @@ -215,7 +217,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): # ---------------- cdef SkewPolynomial_finite_field_dense _rdivisor_c(self, N): - """ + r""" Return a right divisor of this skew polynomial whose reduced norm is `N`. @@ -322,11 +324,11 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): sage: Q._reduced_norm_factor_uniform() z + 1 - Now, we consider the product `R = P*Q`; it admits 32 irreducible - divisors but among them, only one has norm `z + 2`, the others - having norm `z + 1`. - Therefore this method outputs `z + 2` with probability 1/32 - and `z + 1` with probability 31/32. + Now, we consider the product `R = P \cdot Q`; it admits `32` + irreducible divisors but among them, only one has norm `z + 2`, + the others having norm `z + 1`. + Therefore this method outputs `z + 2` with probability `1 / 32` + and `z + 1` with probability `31 / 32`:: sage: R = P*Q sage: counts = { z+1: 0, z+2: 0 } @@ -360,7 +362,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): def _irreducible_divisors(self, bint right): - """ + r""" Return an iterator over all irreducible monic divisors of this skew polynomial. @@ -472,7 +474,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): def right_irreducible_divisor(self, uniform=False): - """ + r""" Return a right irreducible divisor of this skew polynomial. INPUT: @@ -517,7 +519,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): x^3 + x^2 + (4*t^2 + 2*t + 4)*x + t^2 + 3 By convention, the zero skew polynomial has no irreducible - divisor: + divisor:: sage: S(0).right_irreducible_divisor() Traceback (most recent call last): @@ -547,7 +549,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): return D def left_irreducible_divisor(self, uniform=False): - """ + r""" Return a left irreducible divisor of this skew polynomial. INPUT: @@ -585,7 +587,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): x^3 + (t^2 + t + 2)*x^2 + (3*t^2 + t)*x + 2*t + 1 By convention, the zero skew polynomial has no irreducible - divisor: + divisor:: sage: S(0).left_irreducible_divisor() Traceback (most recent call last): @@ -620,11 +622,11 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): def right_irreducible_divisors(self): - """ + r""" Return an iterator over all irreducible monic right divisors of this skew polynomial. - EXAMPLES: + EXAMPLES:: sage: k. = GF(5^3) sage: Frob = k.frobenius_endomorphism() @@ -655,11 +657,11 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): return self._irreducible_divisors(True) def left_irreducible_divisors(self): - """ + r""" Return an iterator over all irreducible monic left divisors of this skew polynomial. - EXAMPLES: + EXAMPLES:: sage: k. = GF(5^3) sage: Frob = k.frobenius_endomorphism() @@ -691,7 +693,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): def count_irreducible_divisors(self): - """ + r""" Return the number of irreducible monic divisors of this skew polynomial. @@ -708,7 +710,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): sage: S. = k['x',Frob] We illustrate that a skew polynomial may have a number of irreducible - divisors greater than its degree. + divisors greater than its degree:: sage: a = x^4 + (4*t + 3)*x^3 + t^2*x^2 + (4*t^2 + 3*t)*x + 3*t sage: a.count_irreducible_divisors() @@ -752,7 +754,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): # ---------------------- cdef _factor_c(self): - """ + r""" Compute a factorization of ``self``. This is the low level implementation of :meth:`factor`. @@ -824,7 +826,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): cdef _factor_uniform_c(self): - """ + r""" Compute a uniformly distrbuted factorization of ``self``. This is the low level implementation of :meth:`factor`. @@ -932,7 +934,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): def factor(self, uniform=False): - """ + r""" Return a factorization of this skew polynomial. INPUT: @@ -970,7 +972,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): There is a priori no guarantee on the distribution of the factorizations we get. Passing in the keyword ``uniform=True`` ensures the output is uniformly distributed among all - factorizations. + factorizations:: sage: a.factor(uniform=True) # random (x + t^2 + 4) * (x + t) * (x + t + 3) @@ -979,7 +981,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): sage: a.factor(uniform=True) # random (x + 2*t^2 + 3*t) * (x + 4*t + 2) * (x + 2*t + 2) - By convention, the zero skew polynomial has no factorization: + By convention, the zero skew polynomial has no factorization:: sage: S(0).factor() Traceback (most recent call last): @@ -1000,7 +1002,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): def count_factorizations(self): - """ + r""" Return the number of factorizations (as a product of a unit and a product of irreducible monic factors) of this skew polynomial. @@ -1045,7 +1047,7 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): # Not optimized: # many calls to reduced_norm, reduced_norm_factor, _rdivisor_c, which are slow def factorizations(self): - """ + r""" Return an iterator over all factorizations (as a product of a unit and a product of irreducible monic factors) of this skew polynomial. @@ -1104,3 +1106,4 @@ cdef class SkewPolynomial_finite_field_dense(SkewPolynomial_finite_order_dense): unit = self.leading_coefficient() for factors in factorizations_rec(~unit*self): yield Factorization(factors, sort=False, unit=unit) + diff --git a/src/sage/rings/polynomial/skew_polynomial_finite_order.pyx b/src/sage/rings/polynomial/skew_polynomial_finite_order.pyx index afe08a36caa..1dadb5c0e65 100644 --- a/src/sage/rings/polynomial/skew_polynomial_finite_order.pyx +++ b/src/sage/rings/polynomial/skew_polynomial_finite_order.pyx @@ -5,11 +5,11 @@ AUTHOR:: - Xavier Caruso (2012-06-29): initial version -- Arpit Merchant (2016-08-04): improved docstrings, fixed doctests and refactored classes and methods - +- Arpit Merchant (2016-08-04): improved docstrings, fixed doctests + and refactored classes and methods """ -############################################################################# +# *************************************************************************** # Copyright (C) 2012 Xavier Caruso # # This program is free software: you can redistribute it and/or modify @@ -68,7 +68,6 @@ cdef class SkewPolynomial_finite_order_dense(SkewPolynomial_generic_dense): t^2 + 1 sage: x.parent() is S True - """ SkewPolynomial_generic_dense.__init__ (self, parent, x, check, construct, **kwds) self._norm = None @@ -180,7 +179,7 @@ cdef class SkewPolynomial_finite_order_dense(SkewPolynomial_generic_dense): 3*z + 4 The reduced trace lies in the center of `S`, which is a univariate - polynomial ring in the variable `z = x^3` over `GF(5)`. + polynomial ring in the variable `z = x^3` over `\GF{5}`:: sage: tr.parent() Univariate Polynomial Ring in z over Finite Field of size 5 @@ -193,7 +192,7 @@ cdef class SkewPolynomial_finite_order_dense(SkewPolynomial_generic_dense): 3*x^3 + 4 By default, the name of the central variable is usually ``z`` (see - :meth:`sage.rings.polynomial.skew_polynomial_ring.SkewPolynomiaRing_finite_order.center` + :meth:`~sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing_finite_order.center` for more details about this). However, the user can specify a different variable name if desired:: @@ -251,7 +250,7 @@ cdef class SkewPolynomial_finite_order_dense(SkewPolynomial_generic_dense): z^3 + 4*z^2 + 4 The reduced norm lies in the center of `S`, which is a univariate - polynomial ring in the variable `z = x^3` over `GF(5)`. + polynomial ring in the variable `z = x^3` over `\GF{5}`:: sage: N.parent() Univariate Polynomial Ring in z over Finite Field of size 5 @@ -264,7 +263,7 @@ cdef class SkewPolynomial_finite_order_dense(SkewPolynomial_generic_dense): x^9 + 4*x^6 + 4 By default, the name of the central variable is usually ``z`` (see - :meth:`sage.rings.polynomial.skew_polynomial_ring.SkewPolynomiaRing_finite_order.center` + :meth:`~sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing_finite_order.center` for more details about this). However, the user can speciify a different variable name if desired:: @@ -338,8 +337,8 @@ cdef class SkewPolynomial_finite_order_dense(SkewPolynomial_generic_dense): def is_central(self): - """ - Return True if this skew polynomial lies in the center. + r""" + Return ``True`` if this skew polynomial lies in the center. EXAMPLES:: @@ -363,7 +362,7 @@ cdef class SkewPolynomial_finite_order_dense(SkewPolynomial_generic_dense): def bound(self): - """ + r""" Return a bound of this skew polynomial (i.e. a multiple of this skew polynomial lying in the center). @@ -398,8 +397,7 @@ cdef class SkewPolynomial_finite_order_dense(SkewPolynomial_generic_dense): z^2 + z + 4 We observe that the bound is explicity given as an element of the - center (which is a univariate polynomial ring in the variable - `z`). + center (which is a univariate polynomial ring in the variable `z`). We can use conversion to send it in the skew polynomial ring:: sage: S(b) @@ -446,7 +444,7 @@ cdef class SkewPolynomial_finite_order_dense(SkewPolynomial_generic_dense): def optimal_bound(self): - """ + r""" Return the optimal bound of this skew polynomial (i.e. the monic multiple of this skew polynomial of minimal degree lying in the center). @@ -468,8 +466,7 @@ cdef class SkewPolynomial_finite_order_dense(SkewPolynomial_generic_dense): z + 3 We observe that the bound is explicity given as an element of the - center (which is a univariate polynomial ring in the variable - `z`). + center (which is a univariate polynomial ring in the variable `z`). We can use conversion to send it in the skew polynomial ring:: sage: S(b) @@ -495,4 +492,5 @@ cdef class SkewPolynomial_finite_order_dense(SkewPolynomial_generic_dense): # TODO: # fast multiplication - # reduced characteristic polynomial + # reduced characteristic polynomial + diff --git a/src/sage/rings/polynomial/skew_polynomial_ring.py b/src/sage/rings/polynomial/skew_polynomial_ring.py index af837dfa5d7..ecfb2527903 100644 --- a/src/sage/rings/polynomial/skew_polynomial_ring.py +++ b/src/sage/rings/polynomial/skew_polynomial_ring.py @@ -1,18 +1,20 @@ r""" Skew Univariate Polynomial Rings -This module provides the :class:`~sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing`. -In the class hierarchy in Sage, the locution *Skew Polynomial* is used for a Ore polynomial -without twisting derivation. +This module provides the +:class:`~sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing`. +In the class hierarchy in Sage, the locution *Skew Polynomial* is used +for a Ore polynomial without twisting derivation. This module also provides: -- the class :class:`~sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing_finite_order` - which is a specialized class for skew polynomial rings over fields equipped with an automorphism of - finite order. It inherits from :class:`~sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing` +- the class :class:`~sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing_finite_order`, + which is a specialized class for skew polynomial rings over fields + equipped with an automorphism of finite order. It inherits from + :class:`~sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing` but contains more methods and provides better algorithms. -- the class :class:`~sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing_finite_field` +- the class :class:`~sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing_finite_field`, which is a specialized class for skew polynomial rings over finite fields. .. SEEALSO:: @@ -28,8 +30,8 @@ - Johan Rosenkilde (2016-08-03): changes for bug fixes, docstring and doctest errors - """ + # *************************************************************************** # Copyright (C) 2012 Xavier Caruso # @@ -40,7 +42,7 @@ # https://www.gnu.org/licenses/ # *************************************************************************** -from sage.structure.richcmp import op_EQ +from sage.structure.richcmp import op_EQ, op_NE from sage.structure.category_object import normalize_names from sage.rings.ring import Field @@ -59,18 +61,18 @@ # Helper functions def _base_ring_to_fraction_field(S): - """ + r""" Return the unique skew polynomial ring over the fraction field of ``S.base_ring()`` which has ``S`` a sub-ring (internal method). INPUT: - - ``S`` -- a skew polynomial ring. + - ``S`` -- a skew polynomial ring OUTPUT: - - ``Q`` -- the skew polynomial ring over the fraction field of - ``S.base_ring``. + - ``Q`` -- the skew polynomial ring over the fraction field + of ``S.base_ring`` EXAMPLES:: @@ -96,7 +98,7 @@ def _base_ring_to_fraction_field(S): def _minimal_vanishing_polynomial(R, eval_pts): - """ + r""" Return the minimal vanishing polynomial (internal function). See the documentation for @@ -104,7 +106,7 @@ def _minimal_vanishing_polynomial(R, eval_pts): INPUT: - - ``R`` -- A skew polynomial ring over a field. + - ``R`` -- a skew polynomial ring over a field - ``eval_pts`` -- a list of evaluation points @@ -120,7 +122,8 @@ def _minimal_vanishing_polynomial(R, eval_pts): sage: S. = k['x',Frob] sage: eval_pts = [1, t, t^2] sage: b = _minimal_vanishing_polynomial(S, eval_pts); b - doctest:...: FutureWarning: This class/method/function is marked as experimental. It, its functionality or its interface might change without a formal deprecation. + doctest:...: FutureWarning: This class/method/function is marked as experimental. + It, its functionality or its interface might change without a formal deprecation. See http://trac.sagemath.org/13215 for details. x^3 + 4 """ @@ -144,7 +147,7 @@ def _minimal_vanishing_polynomial(R, eval_pts): def _lagrange_polynomial(R, eval_pts, values): - """ + r""" Return the Lagrange polynomial of the given points if it exists. Otherwise return an unspecified polynomial (internal method). @@ -164,7 +167,7 @@ def _lagrange_polynomial(R, eval_pts, values): OUTPUT: - - the Lagrange polynomial. + - the Lagrange polynomial EXAMPLES:: @@ -189,13 +192,16 @@ def _lagrange_polynomial(R, eval_pts, values): Traceback (most recent call last): ... ValueError: the given evaluation points are linearly dependent over the fixed field of the twisting morphism, - so a Lagrange polynomial could not be determined (and might not exist). + so a Lagrange polynomial could not be determined (and might not exist) """ l = len(eval_pts) if l == 1: if eval_pts[0].is_zero(): # This is due to linear dependence among the eval_pts. - raise ValueError("the given evaluation points are linearly dependent over the fixed field of the twisting morphism, so a Lagrange polynomial could not be determined (and might not exist).") + raise ValueError("the given evaluation points are linearly dependent" + " over the fixed field of the twisting morphism," + " so a Lagrange polynomial could not be determined" + " (and might not exist)") return (values[0] / eval_pts[0]) * R.one() else: t = l // 2 @@ -250,17 +256,18 @@ def __init__(self, base_ring, morphism, derivation, name, sparse, category=None) OrePolynomialRing.__init__(self, base_ring, morphism, None, name, sparse, category) def minimal_vanishing_polynomial(self, eval_pts): - """ + r""" Return the minimal-degree, monic skew polynomial which vanishes at all the given evaluation points. The degree of the vanishing polynomial is at most the length of - ``eval_pts``. Equality holds if and only if the elements of ``eval_pts`` - are linearly independent over the fixed field of ``self.twisting_morphism()``. + ``eval_pts``. Equality holds if and only if the elements of + ``eval_pts`` are linearly independent over the fixed field of + ``self.twisting_morphism()``. - ``eval_pts`` -- list of evaluation points which are linearly - independent over the fixed field of the twisting morphism of the associated - skew polynomial ring + independent over the fixed field of the twisting morphism of + the associated skew polynomial ring OUTPUT: @@ -275,14 +282,15 @@ def minimal_vanishing_polynomial(self, eval_pts): sage: b = S.minimal_vanishing_polynomial(eval_pts); b x^3 + 4 - The minimal vanishing polynomial evaluates to 0 at each of the evaluation points:: + The minimal vanishing polynomial evaluates to 0 at each of + the evaluation points:: sage: eval = b.multi_point_evaluation(eval_pts); eval [0, 0, 0] - If the evaluation points are linearly dependent over the fixed field of - the twisting morphism, then the returned polynomial has lower degree than the - number of evaluation points:: + If the evaluation points are linearly dependent over the fixed + field of the twisting morphism, then the returned polynomial has + lower degree than the number of evaluation points:: sage: S.minimal_vanishing_polynomial([t]) x + 3*t^2 + 3*t @@ -296,22 +304,23 @@ def lagrange_polynomial(self, points): Return the minimal-degree polynomial which interpolates the given points. - More precisely, given `n` pairs `(x_1, y_1), ..., (x_n, y_n) \in R^2`, - where `R` is ``self.base_ring()``, compute a skew polynomial `p(x)` such - that `p(x_i) = y_i` for each `i`, under the condition that the `x_i` are - linearly independent over the fixed field of ``self.twisting_morphism()``. + More precisely, given `n` pairs `(x_1, y_1), \ldots, (x_n, y_n) \in R^2`, + where `R` is ``self.base_ring()``, compute a skew polynomial `p(x)` + such that `p(x_i) = y_i` for each `i`, under the condition that + the `x_i` are linearly independent over the fixed field of + ``self.twisting_morphism()``. If the `x_i` are linearly independent over the fixed field of - ``self.twisting_morphism()`` then such a polynomial is guaranteed to exist. - Otherwise, it might exist depending on the `y_i`, but the algorithm used - in this implementation does not support that, and so an error is always - raised. + ``self.twisting_morphism()`` then such a polynomial is guaranteed + to exist. Otherwise, it might exist depending on the `y_i`, but + the algorithm used in this implementation does not support that, + and so an error is always raised. INPUT: - - ``points`` -- a list of pairs ``(x_1, y_1),..., (x_n, y_n)`` of - elements of the base ring of ``self``. The `x_i` should be linearly - independent over the fixed field of ``self.twisting_morphism()``. + - ``points`` -- a list of pairs `(x_1, y_1), \ldots, (x_n, y_n)` of + elements of the base ring of ``self``; the `x_i` should be linearly + independent over the fixed field of ``self.twisting_morphism()`` OUTPUT: @@ -342,7 +351,7 @@ def lagrange_polynomial(self, points): Traceback (most recent call last): ... ValueError: the given evaluation points are linearly dependent over the fixed field of the twisting morphism, - so a Lagrange polynomial could not be determined (and might not exist). + so a Lagrange polynomial could not be determined (and might not exist) """ l = len(points) if not all(len(pair) == 2 for pair in points): @@ -354,7 +363,7 @@ def lagrange_polynomial(self, points): raise TypeError("the evaluation points must be distinct") zero_i = [i for i in range(l) if eval_pts[i].is_zero()] if zero_i and not values[zero_i[0]].is_zero(): - raise TypeError("a skew polynomial always evaluates to 0 at 0, but a non-zero value was requested.") + raise TypeError("a skew polynomial always evaluates to 0 at 0, but a non-zero value was requested") return _lagrange_polynomial(_base_ring_to_fraction_field(self), eval_pts, values) @@ -365,7 +374,7 @@ def lagrange_polynomial(self, points): class SectionSkewPolynomialCenterInjection(Section): r""" Section of the canonical injection of the center of a skew - polynomial ring into this ring + polynomial ring into this ring. TESTS:: @@ -378,7 +387,7 @@ class SectionSkewPolynomialCenterInjection(Section): """ def _call_(self, x): r""" - Return `x` viewed as an element of the center + Return `x` viewed as an element of the center. EXAMPLES:: @@ -412,7 +421,7 @@ def _call_(self, x): def _richcmp_(self, right, op): r""" - Compare this morphism with ``right`` + Compare this morphism with ``right``. TESTS:: @@ -425,18 +434,22 @@ def _richcmp_(self, right, op): sage: s = loads(dumps(sigma)) sage: s == sigma True + sage: s != sigma + False sage: s is sigma False """ if op == op_EQ: return (self.domain() is right.domain()) and (self.codomain() is right.codomain()) + if op == op_NE: + return (self.domain() is not right.domain()) or (self.codomain() is not right.codomain()) return NotImplemented class SkewPolynomialCenterInjection(RingHomomorphism): r""" Canonical injection of the center of a skew polynomial ring - into this ring + into this ring. TESTS:: @@ -448,7 +461,7 @@ class SkewPolynomialCenterInjection(RingHomomorphism): """ def __init__(self, domain, codomain, embed, order): r""" - Initialize this morphism + Initialize this morphism. EXAMPLES:: @@ -466,7 +479,7 @@ def __init__(self, domain, codomain, embed, order): def _repr_(self): r""" - Return a string representation of this morphism + Return a string representation of this morphism. EXAMPLES:: @@ -483,7 +496,7 @@ def _repr_(self): def _call_(self, x): r""" - Return the image of `x` by this morphism + Return the image of `x` by this morphism. TESTS:: @@ -504,7 +517,7 @@ def _call_(self, x): def _richcmp_(self, right, op): r""" - Compare this morphism with ``right`` + Compare this morphism with ``right``. TESTS:: @@ -516,16 +529,20 @@ def _richcmp_(self, right, op): sage: i = loads(dumps(iota)) sage: i == iota True + sage: i != iota + False sage: i is iota False """ if op == op_EQ: return (self.domain() is right.domain()) and (self.codomain() is right.codomain()) + if op == op_NE: + return (self.domain() is not right.domain()) or (self.codomain() is not right.codomain()) return NotImplemented def section(self): r""" - Return a section of this morphism + Return a section of this morphism. EXAMPLES:: @@ -546,13 +563,12 @@ class SkewPolynomialRing_finite_order(SkewPolynomialRing): .. SEEALSO:: - :meth:`sage.rings.polynomial.skew_polynomial_ring_constructor.SkewPolynomialRing` - :class:`sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing` - :mod:`sage.rings.polynomial.skew_polynomial_finite_order` + - :class:`sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing` + - :mod:`sage.rings.polynomial.skew_polynomial_finite_order` """ def __init__(self, base_ring, morphism, derivation, name, sparse, category=None): r""" - Initialize this skew polynomial + Initialize this skew polynomial. TESTS:: @@ -604,7 +620,7 @@ def center(self, name=None, names=None, default=False): .. NOTE:: - If F denotes the subring of R fixed by `\sigma` and `\sigma` + If `F` denotes the subring of `R` fixed by `\sigma` and `\sigma` has order `r`, the center of `K[x,\sigma]` is `F[x^r]`, that is a univariate polynomial ring over `F`. @@ -669,7 +685,7 @@ def center(self, name=None, names=None, default=False): sage: S1.center() is S2.center() True - ABOUT THE DEFAULT NAME OF THE CENTRAL VARIABLE: + .. RUBRIC:: About the default name of the central variable A priori, the default is ``z``. @@ -737,14 +753,13 @@ def center(self, name=None, names=None, default=False): ###################################################### class SkewPolynomialRing_finite_field(SkewPolynomialRing_finite_order): - """ + r""" A specialized class for skew polynomial rings over finite fields. .. SEEALSO:: - :meth:`sage.rings.polynomial.skew_polynomial_ring_constructor.SkewPolynomialRing` - :class:`sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing_general` - :mod:`sage.rings.polynomial.skew_polynomial_finite_field` + - :class:`sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing` + - :mod:`sage.rings.polynomial.skew_polynomial_finite_field` .. TODO:: @@ -752,7 +767,7 @@ class SkewPolynomialRing_finite_field(SkewPolynomialRing_finite_order): multiplication and factorization. """ def __init__(self, base_ring, morphism, derivation, names, sparse, category=None): - """ + r""" This method is a constructor for a general, dense univariate skew polynomial ring over a finite field. @@ -786,7 +801,7 @@ def __init__(self, base_ring, morphism, derivation, names, sparse, category=None self._matrix_retraction = None def _new_retraction_map(self, seed=None): - """ + r""" Create a retraction map from the ring of coefficient of this skew polynomial ring to its fixed subfield under the twisting morphism @@ -836,7 +851,7 @@ def _new_retraction_map(self, seed=None): self._matrix_retraction = MatrixSpace(self._constants, 1, k.degree())(trace) def _retraction(self, x, newmap=False, seed=None): - """ + r""" Return the image of `x` under the retraction map (see also :meth:`_new_retraction_map`) @@ -880,3 +895,4 @@ def _retraction(self, x, newmap=False, seed=None): if newmap or seed is not None or self._matrix_retraction is None: self._new_retraction_map() return (self._matrix_retraction*self.base_ring()(x)._vector_())[0] +