Commutative rings¶
- class sage.categories.commutative_rings.CommutativeRings(base_category)[source]¶
Bases:
CategoryWithAxiom_singleton
The category of commutative rings.
commutative rings with unity, i.e. rings with commutative * and a multiplicative identity
EXAMPLES:
sage: C = CommutativeRings(); C Category of commutative rings sage: C.super_categories() [Category of rings, Category of commutative monoids]
>>> from sage.all import * >>> C = CommutativeRings(); C Category of commutative rings >>> C.super_categories() [Category of rings, Category of commutative monoids]
- class CartesianProducts(category, *args)[source]¶
Bases:
CartesianProductsCategory
- extra_super_categories()[source]¶
Let Sage knows that Cartesian products of commutative rings is a commutative ring.
EXAMPLES:
sage: CommutativeRings().Commutative().CartesianProducts().extra_super_categories() [Category of commutative rings] sage: cartesian_product([ZZ, Zmod(34), ....: QQ, GF(5)]) in CommutativeRings() True
>>> from sage.all import * >>> CommutativeRings().Commutative().CartesianProducts().extra_super_categories() [Category of commutative rings] >>> cartesian_product([ZZ, Zmod(Integer(34)), ... QQ, GF(Integer(5))]) in CommutativeRings() True
- class Finite(base_category)[source]¶
Bases:
CategoryWithAxiom_singleton
Check that Sage knows that Cartesian products of finite commutative rings is a finite commutative ring.
EXAMPLES:
sage: cartesian_product([Zmod(34), ....: GF(5)]) in Rings().Commutative().Finite() True
>>> from sage.all import * >>> cartesian_product([Zmod(Integer(34)), ... GF(Integer(5))]) in Rings().Commutative().Finite() True
- class ParentMethods[source]¶
Bases:
object
- cyclotomic_cosets(q, cosets=None)[source]¶
Return the (multiplicative) orbits of
q
in the ring.Let \(R\) be a finite commutative ring. The group of invertible elements \(R^*\) in \(R\) gives rise to a group action on \(R\) by multiplication. An orbit of the subgroup generated by an invertible element \(q\) is called a \(q\)-cyclotomic coset (since in a finite ring, each invertible element is a root of unity).
These cosets arise in the theory of minimal polynomials of finite fields, duadic codes and combinatorial designs. Fix a primitive element \(z\) of \(GF(q^k)\). The minimal polynomial of \(z^s\) over \(GF(q)\) is given by
\[M_s(x) = \prod_{i \in C_s} (x - z^i),\]where \(C_s\) is the \(q\)-cyclotomic coset mod \(n\) containing \(s\), \(n = q^k - 1\).
Note
When \(R = \ZZ / n \ZZ\) the smallest element of each coset is sometimes called a coset leader. This function returns sorted lists so that the coset leader will always be the first element of the coset.
INPUT:
q
– an invertible element of the ringcosets
– an optional lists of elements ofself
. If provided, the function only return the list of cosets that contain some element fromcosets
.
OUTPUT: list of lists
EXAMPLES:
sage: Zmod(11).cyclotomic_cosets(2) [[0], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]] sage: Zmod(15).cyclotomic_cosets(2) [[0], [1, 2, 4, 8], [3, 6, 9, 12], [5, 10], [7, 11, 13, 14]]
>>> from sage.all import * >>> Zmod(Integer(11)).cyclotomic_cosets(Integer(2)) [[0], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]] >>> Zmod(Integer(15)).cyclotomic_cosets(Integer(2)) [[0], [1, 2, 4, 8], [3, 6, 9, 12], [5, 10], [7, 11, 13, 14]]
Since the group of invertible elements of a finite field is cyclic, the set of squares is a particular case of cyclotomic coset:
sage: # needs sage.rings.finite_rings sage: K = GF(25, 'z') sage: a = K.multiplicative_generator() sage: K.cyclotomic_cosets(a**2, cosets=[1]) [[1, 2, 3, 4, z + 1, z + 3, 2*z + 1, 2*z + 2, 3*z + 3, 3*z + 4, 4*z + 2, 4*z + 4]] sage: sorted(b for b in K if not b.is_zero() and b.is_square()) [1, 2, 3, 4, z + 1, z + 3, 2*z + 1, 2*z + 2, 3*z + 3, 3*z + 4, 4*z + 2, 4*z + 4]
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> K = GF(Integer(25), 'z') >>> a = K.multiplicative_generator() >>> K.cyclotomic_cosets(a**Integer(2), cosets=[Integer(1)]) [[1, 2, 3, 4, z + 1, z + 3, 2*z + 1, 2*z + 2, 3*z + 3, 3*z + 4, 4*z + 2, 4*z + 4]] >>> sorted(b for b in K if not b.is_zero() and b.is_square()) [1, 2, 3, 4, z + 1, z + 3, 2*z + 1, 2*z + 2, 3*z + 3, 3*z + 4, 4*z + 2, 4*z + 4]
We compute some examples of minimal polynomials:
sage: # needs sage.rings.finite_rings sage: K = GF(27, 'z') sage: a = K.multiplicative_generator() sage: R.<X> = PolynomialRing(K, 'X') sage: a.minimal_polynomial('X') X^3 + 2*X + 1 sage: cyc3 = Zmod(26).cyclotomic_cosets(3, cosets=[1]); cyc3 [[1, 3, 9]] sage: prod(X - a**i for i in cyc3[0]) # needs sage.rings.finite_rings X^3 + 2*X + 1 sage: (a**7).minimal_polynomial('X') # needs sage.rings.finite_rings X^3 + X^2 + 2*X + 1 sage: cyc7 = Zmod(26).cyclotomic_cosets(3, cosets=[7]); cyc7 [[7, 11, 21]] sage: prod(X - a**i for i in cyc7[0]) # needs sage.rings.finite_rings X^3 + X^2 + 2*X + 1
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> K = GF(Integer(27), 'z') >>> a = K.multiplicative_generator() >>> R = PolynomialRing(K, 'X', names=('X',)); (X,) = R._first_ngens(1) >>> a.minimal_polynomial('X') X^3 + 2*X + 1 >>> cyc3 = Zmod(Integer(26)).cyclotomic_cosets(Integer(3), cosets=[Integer(1)]); cyc3 [[1, 3, 9]] >>> prod(X - a**i for i in cyc3[Integer(0)]) # needs sage.rings.finite_rings X^3 + 2*X + 1 >>> (a**Integer(7)).minimal_polynomial('X') # needs sage.rings.finite_rings X^3 + X^2 + 2*X + 1 >>> cyc7 = Zmod(Integer(26)).cyclotomic_cosets(Integer(3), cosets=[Integer(7)]); cyc7 [[7, 11, 21]] >>> prod(X - a**i for i in cyc7[Integer(0)]) # needs sage.rings.finite_rings X^3 + X^2 + 2*X + 1
Cyclotomic cosets of fields are useful in combinatorial design theory to provide so called difference families (see Wikipedia article Difference_set and
difference_family
). This is illustrated on the following examples:sage: K = GF(5) sage: a = K.multiplicative_generator() # needs sage.libs.pari sage: H = K.cyclotomic_cosets(a**2, cosets=[1, 2]); H # needs sage.rings.finite_rings [[1, 4], [2, 3]] sage: sorted(x - y for D in H for x in D for y in D if x != y) # needs sage.rings.finite_rings [1, 2, 3, 4] sage: K = GF(37) sage: a = K.multiplicative_generator() # needs sage.libs.pari sage: H = K.cyclotomic_cosets(a**4, cosets=[1]); H # needs sage.rings.finite_rings [[1, 7, 9, 10, 12, 16, 26, 33, 34]] sage: sorted(x - y for D in H for x in D for y in D if x != y) # needs sage.rings.finite_rings [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, ..., 33, 34, 34, 35, 35, 36, 36]
>>> from sage.all import * >>> K = GF(Integer(5)) >>> a = K.multiplicative_generator() # needs sage.libs.pari >>> H = K.cyclotomic_cosets(a**Integer(2), cosets=[Integer(1), Integer(2)]); H # needs sage.rings.finite_rings [[1, 4], [2, 3]] >>> sorted(x - y for D in H for x in D for y in D if x != y) # needs sage.rings.finite_rings [1, 2, 3, 4] >>> K = GF(Integer(37)) >>> a = K.multiplicative_generator() # needs sage.libs.pari >>> H = K.cyclotomic_cosets(a**Integer(4), cosets=[Integer(1)]); H # needs sage.rings.finite_rings [[1, 7, 9, 10, 12, 16, 26, 33, 34]] >>> sorted(x - y for D in H for x in D for y in D if x != y) # needs sage.rings.finite_rings [1, 1, 2, 2, 3, 3, 4, 4, 5, 5, ..., 33, 34, 34, 35, 35, 36, 36]
The method
cyclotomic_cosets
works on any finite commutative ring:sage: R = cartesian_product([GF(7), Zmod(14)]) sage: a = R((3,5)) sage: R.cyclotomic_cosets((3,5), [(1,1)]) [[(1, 1), (2, 11), (3, 5), (4, 9), (5, 3), (6, 13)]]
>>> from sage.all import * >>> R = cartesian_product([GF(Integer(7)), Zmod(Integer(14))]) >>> a = R((Integer(3),Integer(5))) >>> R.cyclotomic_cosets((Integer(3),Integer(5)), [(Integer(1),Integer(1))]) [[(1, 1), (2, 11), (3, 5), (4, 9), (5, 3), (6, 13)]]
- extra_super_categories()[source]¶
Let Sage know that finite commutative rings are Noetherian.
EXAMPLES:
sage: CommutativeRings().Finite().extra_super_categories() [Category of noetherian rings]
>>> from sage.all import * >>> CommutativeRings().Finite().extra_super_categories() [Category of noetherian rings]
- class ParentMethods[source]¶
Bases:
object
- derivation(arg=None, twist=None)[source]¶
Return the twisted or untwisted derivation over this ring specified by
arg
.Note
A twisted derivation with respect to \(\theta\) (or a \(\theta\)-derivation for short) is an additive map \(d\) satisfying the following axiom for all \(x, y\) in the domain:
\[d(xy) = \theta(x) d(y) + d(x) y.\]INPUT:
arg
– (optional) a generator or a list of coefficients that defines the derivationtwist
– (optional) the twisting homomorphism
EXAMPLES:
sage: R.<x,y,z> = QQ[] sage: R.derivation() # needs sage.modules d/dx
>>> from sage.all import * >>> R = QQ['x, y, z']; (x, y, z,) = R._first_ngens(3) >>> R.derivation() # needs sage.modules d/dx
In that case,
arg
could be a generator:sage: R.derivation(y) # needs sage.modules d/dy
>>> from sage.all import * >>> R.derivation(y) # needs sage.modules d/dy
or a list of coefficients:
sage: R.derivation([1,2,3]) # needs sage.modules d/dx + 2*d/dy + 3*d/dz
>>> from sage.all import * >>> R.derivation([Integer(1),Integer(2),Integer(3)]) # needs sage.modules d/dx + 2*d/dy + 3*d/dz
It is not possible to define derivations with respect to a polynomial which is not a variable:
sage: R.derivation(x^2) # needs sage.modules Traceback (most recent call last): ... ValueError: unable to create the derivation
>>> from sage.all import * >>> R.derivation(x**Integer(2)) # needs sage.modules Traceback (most recent call last): ... ValueError: unable to create the derivation
Here is an example with twisted derivations:
sage: R.<x,y,z> = QQ[] sage: theta = R.hom([x^2, y^2, z^2]) sage: f = R.derivation(twist=theta); f # needs sage.modules 0 sage: f.parent() # needs sage.modules Module of twisted derivations over Multivariate Polynomial Ring in x, y, z over Rational Field (twisting morphism: x |--> x^2, y |--> y^2, z |--> z^2)
>>> from sage.all import * >>> R = QQ['x, y, z']; (x, y, z,) = R._first_ngens(3) >>> theta = R.hom([x**Integer(2), y**Integer(2), z**Integer(2)]) >>> f = R.derivation(twist=theta); f # needs sage.modules 0 >>> f.parent() # needs sage.modules Module of twisted derivations over Multivariate Polynomial Ring in x, y, z over Rational Field (twisting morphism: x |--> x^2, y |--> y^2, z |--> z^2)
Specifying a scalar, the returned twisted derivation is the corresponding multiple of \(\theta - id\):
sage: R.derivation(1, twist=theta) # needs sage.modules [x |--> x^2, y |--> y^2, z |--> z^2] - id sage: R.derivation(x, twist=theta) # needs sage.modules x*([x |--> x^2, y |--> y^2, z |--> z^2] - id)
>>> from sage.all import * >>> R.derivation(Integer(1), twist=theta) # needs sage.modules [x |--> x^2, y |--> y^2, z |--> z^2] - id >>> R.derivation(x, twist=theta) # needs sage.modules x*([x |--> x^2, y |--> y^2, z |--> z^2] - id)
- derivation_module(codomain=None, twist=None)[source]¶
Return the module of derivations over this ring.
INPUT:
codomain
– an algebra over this ring or a ring homomorphism whose domain is this ring orNone
(default:None
); if it is a morphism, the codomain of derivations will be the codomain of the morphism viewed as an algebra overself
through the given morphism; ifNone
, the codomain will be this ringtwist
– a morphism from this ring tocodomain
orNone
(default:None
); ifNone
, the coercion map from this ring tocodomain
will be used
Note
A twisted derivation with respect to \(\theta\) (or a \(\theta\)-derivation for short) is an additive map \(d\) satisfying the following axiom for all \(x, y\) in the domain:
\[d(xy) = \theta(x) d(y) + d(x) y.\]EXAMPLES:
sage: R.<x,y,z> = QQ[] sage: M = R.derivation_module(); M # needs sage.modules Module of derivations over Multivariate Polynomial Ring in x, y, z over Rational Field sage: M.gens() # needs sage.modules (d/dx, d/dy, d/dz)
>>> from sage.all import * >>> R = QQ['x, y, z']; (x, y, z,) = R._first_ngens(3) >>> M = R.derivation_module(); M # needs sage.modules Module of derivations over Multivariate Polynomial Ring in x, y, z over Rational Field >>> M.gens() # needs sage.modules (d/dx, d/dy, d/dz)
We can specify a different codomain:
sage: K = R.fraction_field() sage: M = R.derivation_module(K); M # needs sage.modules Module of derivations from Multivariate Polynomial Ring in x, y, z over Rational Field to Fraction Field of Multivariate Polynomial Ring in x, y, z over Rational Field sage: M.gen() / x # needs sage.modules 1/x*d/dx
>>> from sage.all import * >>> K = R.fraction_field() >>> M = R.derivation_module(K); M # needs sage.modules Module of derivations from Multivariate Polynomial Ring in x, y, z over Rational Field to Fraction Field of Multivariate Polynomial Ring in x, y, z over Rational Field >>> M.gen() / x # needs sage.modules 1/x*d/dx
Here is an example with a non-canonical defining morphism:
sage: ev = R.hom([QQ(0), QQ(1), QQ(2)]) sage: ev Ring morphism: From: Multivariate Polynomial Ring in x, y, z over Rational Field To: Rational Field Defn: x |--> 0 y |--> 1 z |--> 2 sage: M = R.derivation_module(ev) # needs sage.modules sage: M # needs sage.modules Module of derivations from Multivariate Polynomial Ring in x, y, z over Rational Field to Rational Field
>>> from sage.all import * >>> ev = R.hom([QQ(Integer(0)), QQ(Integer(1)), QQ(Integer(2))]) >>> ev Ring morphism: From: Multivariate Polynomial Ring in x, y, z over Rational Field To: Rational Field Defn: x |--> 0 y |--> 1 z |--> 2 >>> M = R.derivation_module(ev) # needs sage.modules >>> M # needs sage.modules Module of derivations from Multivariate Polynomial Ring in x, y, z over Rational Field to Rational Field
Elements in \(M\) acts as derivations at \((0,1,2)\):
sage: # needs sage.modules sage: Dx = M.gen(0); Dx d/dx sage: Dy = M.gen(1); Dy d/dy sage: Dz = M.gen(2); Dz d/dz sage: f = x^2 + y^2 + z^2 sage: Dx(f) # = 2*x evaluated at (0,1,2) 0 sage: Dy(f) # = 2*y evaluated at (0,1,2) 2 sage: Dz(f) # = 2*z evaluated at (0,1,2) 4
>>> from sage.all import * >>> # needs sage.modules >>> Dx = M.gen(Integer(0)); Dx d/dx >>> Dy = M.gen(Integer(1)); Dy d/dy >>> Dz = M.gen(Integer(2)); Dz d/dz >>> f = x**Integer(2) + y**Integer(2) + z**Integer(2) >>> Dx(f) # = 2*x evaluated at (0,1,2) 0 >>> Dy(f) # = 2*y evaluated at (0,1,2) 2 >>> Dz(f) # = 2*z evaluated at (0,1,2) 4
An example with a twisting homomorphism:
sage: theta = R.hom([x^2, y^2, z^2]) sage: M = R.derivation_module(twist=theta); M # needs sage.modules Module of twisted derivations over Multivariate Polynomial Ring in x, y, z over Rational Field (twisting morphism: x |--> x^2, y |--> y^2, z |--> z^2)
>>> from sage.all import * >>> theta = R.hom([x**Integer(2), y**Integer(2), z**Integer(2)]) >>> M = R.derivation_module(twist=theta); M # needs sage.modules Module of twisted derivations over Multivariate Polynomial Ring in x, y, z over Rational Field (twisting morphism: x |--> x^2, y |--> y^2, z |--> z^2)
See also
- frobenius_endomorphism(n=1)[source]¶
Return the Frobenius endomorphism.
INPUT:
n
– nonnegative integer (default: 1)
OUTPUT:
The \(n\)-th power of the absolute arithmetic Frobenius endomorphism on this commutative ring.
EXAMPLES:
sage: K.<u> = PowerSeriesRing(GF(5)) sage: Frob = K.frobenius_endomorphism(); Frob Frobenius endomorphism x |--> x^5 of Power Series Ring in u over Finite Field of size 5 sage: Frob(u) u^5
>>> from sage.all import * >>> K = PowerSeriesRing(GF(Integer(5)), names=('u',)); (u,) = K._first_ngens(1) >>> Frob = K.frobenius_endomorphism(); Frob Frobenius endomorphism x |--> x^5 of Power Series Ring in u over Finite Field of size 5 >>> Frob(u) u^5
We can specify a power:
sage: f = K.frobenius_endomorphism(2); f Frobenius endomorphism x |--> x^(5^2) of Power Series Ring in u over Finite Field of size 5 sage: f(1+u) 1 + u^25
>>> from sage.all import * >>> f = K.frobenius_endomorphism(Integer(2)); f Frobenius endomorphism x |--> x^(5^2) of Power Series Ring in u over Finite Field of size 5 >>> f(Integer(1)+u) 1 + u^25
- is_commutative()[source]¶
Return whether the ring is commutative.
The answer is
True
only if the category is a sub-category ofCommutativeRings
.It is recommended to use instead
R in Rings().Commutative()
.EXAMPLES:
sage: QQ.is_commutative() True sage: QQ['x,y,z'].is_commutative() True
>>> from sage.all import * >>> QQ.is_commutative() True >>> QQ['x,y,z'].is_commutative() True
- krull_dimension()[source]¶
Return the Krull dimension of this commutative ring.
The Krull dimension is the length of the longest ascending chain of prime ideals.
This raises
NotImplementedError
by default for generic commutative rings.Fields and PIDs, with Krull dimension equal to 0 and 1, respectively, have naive implementations of
krull_dimension
. Orders in number fields also have Krull dimension 1.EXAMPLES:
Some polynomial rings:
sage: T.<x,y> = PolynomialRing(QQ,2); T Multivariate Polynomial Ring in x, y over Rational Field sage: T.krull_dimension() 2 sage: U.<x,y,z> = PolynomialRing(ZZ,3); U Multivariate Polynomial Ring in x, y, z over Integer Ring sage: U.krull_dimension() 4
>>> from sage.all import * >>> T = PolynomialRing(QQ,Integer(2), names=('x', 'y',)); (x, y,) = T._first_ngens(2); T Multivariate Polynomial Ring in x, y over Rational Field >>> T.krull_dimension() 2 >>> U = PolynomialRing(ZZ,Integer(3), names=('x', 'y', 'z',)); (x, y, z,) = U._first_ngens(3); U Multivariate Polynomial Ring in x, y, z over Integer Ring >>> U.krull_dimension() 4
All orders in number fields have Krull dimension 1, including non-maximal orders:
sage: # needs sage.rings.number_field sage: K.<i> = QuadraticField(-1) sage: R = K.order(2*i); R Order of conductor 2 generated by 2*i in Number Field in i with defining polynomial x^2 + 1 with i = 1*I sage: R.is_maximal() False sage: R.krull_dimension() 1 sage: R = K.maximal_order(); R Gaussian Integers generated by i in Number Field in i with defining polynomial x^2 + 1 with i = 1*I sage: R.krull_dimension() 1
>>> from sage.all import * >>> # needs sage.rings.number_field >>> K = QuadraticField(-Integer(1), names=('i',)); (i,) = K._first_ngens(1) >>> R = K.order(Integer(2)*i); R Order of conductor 2 generated by 2*i in Number Field in i with defining polynomial x^2 + 1 with i = 1*I >>> R.is_maximal() False >>> R.krull_dimension() 1 >>> R = K.maximal_order(); R Gaussian Integers generated by i in Number Field in i with defining polynomial x^2 + 1 with i = 1*I >>> R.krull_dimension() 1
- over(base=None, gen=None, gens=None, name=None, names=None)[source]¶
Return this ring, considered as an extension of
base
.INPUT:
base
– a commutative ring or a morphism orNone
(default:None
); the base of this extension or its defining morphismgen
– a generator of this extension (over its base) orNone
(default:None
)gens
– list of generators of this extension (over its base) orNone
(default:None
)name
– a variable name orNone
(default:None
)names
– list or a tuple of variable names orNone
(default:None
)
EXAMPLES:
We construct an extension of finite fields:
sage: # needs sage.rings.finite_rings sage: F = GF(5^2) sage: k = GF(5^4) sage: z4 = k.gen() sage: K = k.over(F); K # needs sage.modules Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base
>>> from sage.all import * >>> # needs sage.rings.finite_rings >>> F = GF(Integer(5)**Integer(2)) >>> k = GF(Integer(5)**Integer(4)) >>> z4 = k.gen() >>> K = k.over(F); K # needs sage.modules Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base
If not explicitly given, the default generator of the top ring (here k) is used and the same name is kept:
sage: K.gen() # needs sage.modules sage.rings.finite_rings z4 sage: K(z4) # needs sage.modules sage.rings.finite_rings z4
>>> from sage.all import * >>> K.gen() # needs sage.modules sage.rings.finite_rings z4 >>> K(z4) # needs sage.modules sage.rings.finite_rings z4
However, it is possible to specify another generator and/or another name. For example:
sage: # needs sage.modules sage.rings.finite_rings sage: Ka = k.over(F, name='a'); Ka Field in a with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base sage: Ka.gen() a sage: Ka(z4) a sage: # needs sage.modules sage.rings.finite_rings sage: Kb = k.over(F, gen=-z4+1, name='b') sage: Kb Field in b with defining polynomial x^2 + z2*x + 4 over its base sage: Kb.gen() b sage: Kb(-z4+1) b
>>> from sage.all import * >>> # needs sage.modules sage.rings.finite_rings >>> Ka = k.over(F, name='a'); Ka Field in a with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base >>> Ka.gen() a >>> Ka(z4) a >>> # needs sage.modules sage.rings.finite_rings >>> Kb = k.over(F, gen=-z4+Integer(1), name='b') >>> Kb Field in b with defining polynomial x^2 + z2*x + 4 over its base >>> Kb.gen() b >>> Kb(-z4+Integer(1)) b
Note that the shortcut
K.<a>
is also available:sage: KKa.<a> = k.over(F) # needs sage.modules sage.rings.finite_rings sage: KKa is Ka # needs sage.modules sage.rings.finite_rings True
>>> from sage.all import * >>> KKa = k.over(F, names=('a',)); (a,) = KKa._first_ngens(1)# needs sage.modules sage.rings.finite_rings >>> KKa is Ka # needs sage.modules sage.rings.finite_rings True
Building an extension on top of another extension is allowed:
sage: L = GF(5^12).over(K); L # needs sage.modules sage.rings.finite_rings Field in z12 with defining polynomial x^3 + (1 + (4*z2 + 2)*z4)*x^2 + (2 + 2*z4)*x - z4 over its base sage: L.base_ring() # needs sage.modules sage.rings.finite_rings Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base
>>> from sage.all import * >>> L = GF(Integer(5)**Integer(12)).over(K); L # needs sage.modules sage.rings.finite_rings Field in z12 with defining polynomial x^3 + (1 + (4*z2 + 2)*z4)*x^2 + (2 + 2*z4)*x - z4 over its base >>> L.base_ring() # needs sage.modules sage.rings.finite_rings Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base
The successive bases of an extension are accessible via the method
sage.rings.ring_extension.RingExtension_generic.bases()
:sage: L.bases() # needs sage.modules sage.rings.finite_rings [Field in z12 with defining polynomial x^3 + (1 + (4*z2 + 2)*z4)*x^2 + (2 + 2*z4)*x - z4 over its base, Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base, Finite Field in z2 of size 5^2]
>>> from sage.all import * >>> L.bases() # needs sage.modules sage.rings.finite_rings [Field in z12 with defining polynomial x^3 + (1 + (4*z2 + 2)*z4)*x^2 + (2 + 2*z4)*x - z4 over its base, Field in z4 with defining polynomial x^2 + (4*z2 + 3)*x + z2 over its base, Finite Field in z2 of size 5^2]
When
base
is omitted, the canonical base of the ring is used:sage: S.<x> = QQ[] sage: E = S.over(); E # needs sage.modules Univariate Polynomial Ring in x over Rational Field over its base sage: E.base_ring() # needs sage.modules Rational Field
>>> from sage.all import * >>> S = QQ['x']; (x,) = S._first_ngens(1) >>> E = S.over(); E # needs sage.modules Univariate Polynomial Ring in x over Rational Field over its base >>> E.base_ring() # needs sage.modules Rational Field
Here is an example where
base
is a defining morphism:sage: # needs sage.modules sage.rings.number_field sage: k.<a> = QQ.extension(x^2 - 2) sage: l.<b> = QQ.extension(x^4 - 2) sage: f = k.hom([b^2]) sage: L = l.over(f) sage: L Field in b with defining polynomial x^2 - a over its base sage: L.base_ring() Number Field in a with defining polynomial x^2 - 2
>>> from sage.all import * >>> # needs sage.modules sage.rings.number_field >>> k = QQ.extension(x**Integer(2) - Integer(2), names=('a',)); (a,) = k._first_ngens(1) >>> l = QQ.extension(x**Integer(4) - Integer(2), names=('b',)); (b,) = l._first_ngens(1) >>> f = k.hom([b**Integer(2)]) >>> L = l.over(f) >>> L Field in b with defining polynomial x^2 - a over its base >>> L.base_ring() Number Field in a with defining polynomial x^2 - 2
Similarly, one can create a tower of extensions:
sage: # needs sage.modules sage.rings.number_field sage: K = k.over() sage: L = l.over(Hom(K, l)(f)); L Field in b with defining polynomial x^2 - a over its base sage: L.base_ring() Field in a with defining polynomial x^2 - 2 over its base sage: L.bases() [Field in b with defining polynomial x^2 - a over its base, Field in a with defining polynomial x^2 - 2 over its base, Rational Field]
>>> from sage.all import * >>> # needs sage.modules sage.rings.number_field >>> K = k.over() >>> L = l.over(Hom(K, l)(f)); L Field in b with defining polynomial x^2 - a over its base >>> L.base_ring() Field in a with defining polynomial x^2 - 2 over its base >>> L.bases() [Field in b with defining polynomial x^2 - a over its base, Field in a with defining polynomial x^2 - 2 over its base, Rational Field]