Univariate skew polynomial rings¶
This module provides the
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 - SkewPolynomialRing_finite_order, which is a specialized class for skew polynomial rings over fields equipped with an automorphism of finite order. It inherits from- SkewPolynomialRingbut contains more methods and provides better algorithms.
- the class - SkewPolynomialRing_finite_field, which is a specialized class for skew polynomial rings over finite fields.
See also
AUTHOR:
- Xavier Caruso (2012-06-29): initial version 
- Arpit Merchant (2016-08-04): improved docstrings, fixed doctests and refactored classes and methods 
- Johan Rosenkilde (2016-08-03): changes for bug fixes, docstring and doctest errors 
- class sage.rings.polynomial.skew_polynomial_ring.SectionSkewPolynomialCenterInjection[source]¶
- Bases: - Section- Section of the canonical injection of the center of a skew polynomial ring into this ring. 
- class sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialCenterInjection(domain, codomain, embed, order)[source]¶
- Bases: - RingHomomorphism- Canonical injection of the center of a skew polynomial ring into this ring. - section()[source]¶
- Return a section of this morphism. - EXAMPLES: - sage: # needs sage.rings.finite_rings sage: k.<a> = GF(5^3) sage: S.<x> = SkewPolynomialRing(k, k.frobenius_endomorphism()) sage: Z = S.center() sage: iota = S.convert_map_from(Z) sage: sigma = iota.section() sage: sigma(x^3) z - >>> from sage.all import * >>> # needs sage.rings.finite_rings >>> k = GF(Integer(5)**Integer(3), names=('a',)); (a,) = k._first_ngens(1) >>> S = SkewPolynomialRing(k, k.frobenius_endomorphism(), names=('x',)); (x,) = S._first_ngens(1) >>> Z = S.center() >>> iota = S.convert_map_from(Z) >>> sigma = iota.section() >>> sigma(x**Integer(3)) z 
 
- class sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing(base_ring, morphism, derivation, name, sparse, category=None)[source]¶
- Bases: - OrePolynomialRing- Initialize - self.- INPUT: - base_ring– a commutative ring
- twisting_morphism– an automorphism of the base ring
- name– string or list of strings representing the name of the variables of ring
- sparse– boolean (default:- False)
- category– a category
 - EXAMPLES: - sage: R.<t> = ZZ[] sage: sigma = R.hom([t + 1]) sage: S.<x> = SkewPolynomialRing(R,sigma) sage: S.category() Category of algebras over Univariate Polynomial Ring in t over Integer Ring sage: S([1]) + S([-1]) 0 sage: TestSuite(S).run() - >>> from sage.all import * >>> R = ZZ['t']; (t,) = R._first_ngens(1) >>> sigma = R.hom([t + Integer(1)]) >>> S = SkewPolynomialRing(R,sigma, names=('x',)); (x,) = S._first_ngens(1) >>> S.category() Category of algebras over Univariate Polynomial Ring in t over Integer Ring >>> S([Integer(1)]) + S([-Integer(1)]) 0 >>> TestSuite(S).run() - lagrange_polynomial(points)[source]¶
- Return the minimal-degree polynomial which interpolates the given points. - 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.- INPUT: - points– 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: the Lagrange polynomial - EXAMPLES: - sage: # needs sage.rings.finite_rings sage: k.<t> = GF(5^3) sage: Frob = k.frobenius_endomorphism() sage: S.<x> = k['x', Frob] sage: points = [(t, 3*t^2 + 4*t + 4), (t^2, 4*t)] sage: d = S.lagrange_polynomial(points); d x + t sage: R.<t> = ZZ[] sage: sigma = R.hom([t + 1]) sage: T.<x> = R['x', sigma] sage: points = [(1, t^2 + 3*t + 4), (t, 2*t^2 + 3*t + 1), (t^2, t^2 + 3*t + 4)] sage: p = T.lagrange_polynomial(points); p ((-t^4 - 2*t - 3)/-2)*x^2 + (-t^4 - t^3 - t^2 - 3*t - 2)*x + (-t^4 - 2*t^3 - 4*t^2 - 10*t - 9)/-2 sage: p.multi_point_evaluation([1, t, t^2]) == [t^2 + 3*t + 4, 2*t^2 + 3*t + 1, t^2 + 3*t + 4] True - >>> from sage.all import * >>> # needs sage.rings.finite_rings >>> k = GF(Integer(5)**Integer(3), names=('t',)); (t,) = k._first_ngens(1) >>> Frob = k.frobenius_endomorphism() >>> S = k['x', Frob]; (x,) = S._first_ngens(1) >>> points = [(t, Integer(3)*t**Integer(2) + Integer(4)*t + Integer(4)), (t**Integer(2), Integer(4)*t)] >>> d = S.lagrange_polynomial(points); d x + t >>> R = ZZ['t']; (t,) = R._first_ngens(1) >>> sigma = R.hom([t + Integer(1)]) >>> T = R['x', sigma]; (x,) = T._first_ngens(1) >>> points = [(Integer(1), t**Integer(2) + Integer(3)*t + Integer(4)), (t, Integer(2)*t**Integer(2) + Integer(3)*t + Integer(1)), (t**Integer(2), t**Integer(2) + Integer(3)*t + Integer(4))] >>> p = T.lagrange_polynomial(points); p ((-t^4 - 2*t - 3)/-2)*x^2 + (-t^4 - t^3 - t^2 - 3*t - 2)*x + (-t^4 - 2*t^3 - 4*t^2 - 10*t - 9)/-2 >>> p.multi_point_evaluation([Integer(1), t, t**Integer(2)]) == [t**Integer(2) + Integer(3)*t + Integer(4), Integer(2)*t**Integer(2) + Integer(3)*t + Integer(1), t**Integer(2) + Integer(3)*t + Integer(4)] True - If the \(x_i\) are linearly dependent over the fixed field of - self.twisting_morphism(), then an error is raised:- sage: T.lagrange_polynomial([(t, 1), (2*t, 3)]) 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) - >>> from sage.all import * >>> T.lagrange_polynomial([(t, Integer(1)), (Integer(2)*t, Integer(3))]) 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) 
 - minimal_vanishing_polynomial(eval_pts)[source]¶
- 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_ptsare 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
 - OUTPUT: the minimal vanishing polynomial - EXAMPLES: - sage: # needs sage.rings.finite_rings sage: k.<t> = GF(5^3) sage: Frob = k.frobenius_endomorphism() sage: S.<x> = k['x', Frob] sage: eval_pts = [1, t, t^2] sage: b = S.minimal_vanishing_polynomial(eval_pts); b x^3 + 4 - >>> from sage.all import * >>> # needs sage.rings.finite_rings >>> k = GF(Integer(5)**Integer(3), names=('t',)); (t,) = k._first_ngens(1) >>> Frob = k.frobenius_endomorphism() >>> S = k['x', Frob]; (x,) = S._first_ngens(1) >>> eval_pts = [Integer(1), t, t**Integer(2)] >>> b = S.minimal_vanishing_polynomial(eval_pts); b x^3 + 4 - The minimal vanishing polynomial evaluates to 0 at each of the evaluation points: - sage: eval = b.multi_point_evaluation(eval_pts); eval # needs sage.rings.finite_rings [0, 0, 0] - >>> from sage.all import * >>> eval = b.multi_point_evaluation(eval_pts); eval # needs sage.rings.finite_rings [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: - sage: S.minimal_vanishing_polynomial([t]) # needs sage.rings.finite_rings x + 3*t^2 + 3*t sage: S.minimal_vanishing_polynomial([t, 3*t]) # needs sage.rings.finite_rings x + 3*t^2 + 3*t - >>> from sage.all import * >>> S.minimal_vanishing_polynomial([t]) # needs sage.rings.finite_rings x + 3*t^2 + 3*t >>> S.minimal_vanishing_polynomial([t, Integer(3)*t]) # needs sage.rings.finite_rings x + 3*t^2 + 3*t 
 
- class sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing_finite_field(base_ring, morphism, derivation, names, sparse, category=None)[source]¶
- Bases: - SkewPolynomialRing_finite_order- A specialized class for skew polynomial rings over finite fields. - See also - Todo - Add methods related to center of skew polynomial ring, irreducibility, karatsuba multiplication and factorization. 
- class sage.rings.polynomial.skew_polynomial_ring.SkewPolynomialRing_finite_order(base_ring, morphism, derivation, name, sparse, category=None)[source]¶
- Bases: - SkewPolynomialRing- A specialized class for skew polynomial rings whose twising morphism has finite order. - See also - center(name=None, names=None, default=False)[source]¶
- Return the center of this skew polynomial ring. - Note - 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\). - INPUT: - name– string or- None(default:- None); the name for the central variable (namely \(x^r\))
- default– boolean (default:- False); if- True, set the default variable name for the center to- name
 - EXAMPLES: - sage: # needs sage.rings.finite_rings sage: k.<t> = GF(5^3) sage: Frob = k.frobenius_endomorphism() sage: S.<x> = k['x',Frob]; S Ore Polynomial Ring in x over Finite Field in t of size 5^3 twisted by t |--> t^5 sage: Z = S.center(); Z Univariate Polynomial Ring in z over Finite Field of size 5 sage: Z.gen() z - >>> from sage.all import * >>> # needs sage.rings.finite_rings >>> k = GF(Integer(5)**Integer(3), names=('t',)); (t,) = k._first_ngens(1) >>> Frob = k.frobenius_endomorphism() >>> S = k['x',Frob]; (x,) = S._first_ngens(1); S Ore Polynomial Ring in x over Finite Field in t of size 5^3 twisted by t |--> t^5 >>> Z = S.center(); Z Univariate Polynomial Ring in z over Finite Field of size 5 >>> Z.gen() z - We can pass in another variable name: - sage: S.center(name='y') # needs sage.rings.finite_rings Univariate Polynomial Ring in y over Finite Field of size 5 - >>> from sage.all import * >>> S.center(name='y') # needs sage.rings.finite_rings Univariate Polynomial Ring in y over Finite Field of size 5 - or use the bracket notation: - sage: Zy.<y> = S.center(); Zy # needs sage.rings.finite_rings Univariate Polynomial Ring in y over Finite Field of size 5 sage: y.parent() is Zy # needs sage.rings.finite_rings True - >>> from sage.all import * >>> Zy = S.center(names=('y',)); (y,) = Zy._first_ngens(1); Zy # needs sage.rings.finite_rings Univariate Polynomial Ring in y over Finite Field of size 5 >>> y.parent() is Zy # needs sage.rings.finite_rings True - A coercion map from the center to the skew polynomial ring is set: - sage: # needs sage.rings.finite_rings sage: S.has_coerce_map_from(Zy) True sage: P = y + x; P x^3 + x sage: P.parent() Ore Polynomial Ring in x over Finite Field in t of size 5^3 twisted by t |--> t^5 sage: P.parent() is S True - >>> from sage.all import * >>> # needs sage.rings.finite_rings >>> S.has_coerce_map_from(Zy) True >>> P = y + x; P x^3 + x >>> P.parent() Ore Polynomial Ring in x over Finite Field in t of size 5^3 twisted by t |--> t^5 >>> P.parent() is S True - together with a conversion map in the reverse direction: - sage: Zy(x^6 + 2*x^3 + 3) # needs sage.rings.finite_rings y^2 + 2*y + 3 sage: Zy(x^2) # needs sage.rings.finite_rings Traceback (most recent call last): ... ValueError: x^2 is not in the center - >>> from sage.all import * >>> Zy(x**Integer(6) + Integer(2)*x**Integer(3) + Integer(3)) # needs sage.rings.finite_rings y^2 + 2*y + 3 >>> Zy(x**Integer(2)) # needs sage.rings.finite_rings Traceback (most recent call last): ... ValueError: x^2 is not in the center - Two different skew polynomial rings can share the same center: - sage: S1.<x1> = k['x1', Frob] # needs sage.rings.finite_rings sage: S2.<x2> = k['x2', Frob] # needs sage.rings.finite_rings sage: S1.center() is S2.center() # needs sage.rings.finite_rings True - >>> from sage.all import * >>> S1 = k['x1', Frob]; (x1,) = S1._first_ngens(1)# needs sage.rings.finite_rings >>> S2 = k['x2', Frob]; (x2,) = S2._first_ngens(1)# needs sage.rings.finite_rings >>> S1.center() is S2.center() # needs sage.rings.finite_rings True - About the default name of the central variable - A priori, the default is - z.- However, a variable name is given the first time this method is called, the given name become the default for the next calls: - sage: # needs sage.rings.finite_rings sage: K.<t> = GF(11^3) sage: phi = K.frobenius_endomorphism() sage: A.<X> = K['X', phi] sage: C.<u> = A.center() # first call sage: C Univariate Polynomial Ring in u over Finite Field of size 11 sage: A.center() # second call: the variable name is still u Univariate Polynomial Ring in u over Finite Field of size 11 sage: A.center() is C True - >>> from sage.all import * >>> # needs sage.rings.finite_rings >>> K = GF(Integer(11)**Integer(3), names=('t',)); (t,) = K._first_ngens(1) >>> phi = K.frobenius_endomorphism() >>> A = K['X', phi]; (X,) = A._first_ngens(1) >>> C = A.center(names=('u',)); (u,) = C._first_ngens(1)# first call >>> C Univariate Polynomial Ring in u over Finite Field of size 11 >>> A.center() # second call: the variable name is still u Univariate Polynomial Ring in u over Finite Field of size 11 >>> A.center() is C True - We can update the default variable name by passing in the argument - default=True:- sage: # needs sage.rings.finite_rings sage: D.<v> = A.center(default=True) sage: D Univariate Polynomial Ring in v over Finite Field of size 11 sage: A.center() Univariate Polynomial Ring in v over Finite Field of size 11 sage: A.center() is D True - >>> from sage.all import * >>> # needs sage.rings.finite_rings >>> D = A.center(default=True, names=('v',)); (v,) = D._first_ngens(1) >>> D Univariate Polynomial Ring in v over Finite Field of size 11 >>> A.center() Univariate Polynomial Ring in v over Finite Field of size 11 >>> A.center() is D True