Path: blob/master/src/sage/rings/finite_rings/hom_finite_field.pyx
8820 views
"""1This file provides several classes implementing:23- embeddings between finite fields45- Frobenius isomorphism on finite fields67EXAMPLES::89sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic1011Construction of an embedding::1213sage: k.<t> = GF(3^7)14sage: K.<T> = GF(3^21)15sage: f = FiniteFieldHomomorphism_generic(Hom(k, K)); f16Ring morphism:17From: Finite Field in t of size 3^718To: Finite Field in T of size 3^2119Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 22021sage: f(t)22T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 22324The map `f` has a method ``section`` which returns a partially defined25map which is the inverse of `f` on the image of `f`::2627sage: g = f.section(); g28Section of Ring morphism:29From: Finite Field in t of size 3^730To: Finite Field in T of size 3^2131Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 232sage: g(f(t^3+t^2+1))33t^3 + t^2 + 134sage: g(T)35Traceback (most recent call last):36...37ValueError: T is not in the image of Ring morphism:38From: Finite Field in t of size 3^739To: Finite Field in T of size 3^2140Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 24142There is no embedding of `GF(5^6)` into `GF(5^11)`::4344sage: k.<t> = GF(5^6)45sage: K.<T> = GF(5^11)46sage: FiniteFieldHomomorphism_generic(Hom(k, K))47Traceback (most recent call last):48...49ValueError: No embedding of Finite Field in t of size 5^6 into Finite Field in T of size 5^11505152Construction of Frobenius endomorphisms::5354sage: k.<t> = GF(7^14)55sage: Frob = k.frobenius_endomorphism(); Frob56Frobenius endomorphism t |--> t^7 on Finite Field in t of size 7^1457sage: Frob(t)58t^75960Some basic arithmetics is supported::6162sage: Frob^263Frobenius endomorphism t |--> t^(7^2) on Finite Field in t of size 7^1464sage: f = k.frobenius_endomorphism(7); f65Frobenius endomorphism t |--> t^(7^7) on Finite Field in t of size 7^1466sage: f*Frob67Frobenius endomorphism t |--> t^(7^8) on Finite Field in t of size 7^146869sage: Frob.order()701471sage: f.order()7227374Note that simplifications are made automatically::7576sage: Frob^1677Frobenius endomorphism t |--> t^(7^2) on Finite Field in t of size 7^1478sage: Frob^2879Identity endomorphism of Finite Field in t of size 7^148081And that comparisons work::8283sage: Frob == Frob^1584True85sage: Frob^14 == Hom(k, k).identity()86True8788AUTHOR:8990- Xavier Caruso (2012-06-29)91"""9293#############################################################################94# Copyright (C) 2012 Xavier Caruso <[email protected]>95#96# Distributed under the terms of the GNU General Public License (GPL)97#98# http://www.gnu.org/licenses/99#****************************************************************************100101102from sage.rings.integer cimport Integer103104from sage.categories.homset import Hom105from sage.structure.element cimport Element106107from sage.rings.finite_rings.finite_field_base import is_FiniteField108from sage.rings.morphism cimport RingHomomorphism, RingHomomorphism_im_gens, FrobeniusEndomorphism_generic109from sage.rings.finite_rings.constructor import FiniteField110111from sage.categories.map cimport Section112from sage.categories.morphism cimport Morphism113114from sage.misc.cachefunc import cached_method115116117cdef class SectionFiniteFieldHomomorphism_generic(Section):118"""119A class implementing sections of embeddings between finite fields.120"""121cpdef Element _call_(self, x): # Not optimized122"""123TESTS::124125sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic126sage: k.<t> = GF(3^7)127sage: K.<T> = GF(3^21)128sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))129sage: g = f.section()130sage: g(f(t^3+t^2+1))131t^3 + t^2 + 1132133sage: g(T)134Traceback (most recent call last):135...136ValueError: T is not in the image of Ring morphism:137From: Finite Field in t of size 3^7138To: Finite Field in T of size 3^21139Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 2140"""141for root, _ in x.minimal_polynomial().roots(ring=self.codomain()):142if self._inverse(root) == x:143return root144raise ValueError("%s is not in the image of %s" % (x, self._inverse))145146147def _repr_(self):148"""149Return a string representation of this section.150151EXAMPLES::152153sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic154sage: k.<t> = GF(3^7)155sage: K.<T> = GF(3^21)156sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))157sage: g = f.section()158sage: g._repr_()159'Section of Ring morphism:\n From: Finite Field in t of size 3^7\n To: Finite Field in T of size 3^21\n Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 2'160"""161return "Section of %s" % self._inverse162163164def _latex_(self):165r"""166Return a latex representation of this section.167168EXAMPLES::169170sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic171sage: k.<t> = GF(3^7)172sage: K.<T> = GF(3^21)173sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))174sage: g = f.section()175sage: g._latex_()176'\\verb"Section of "\\Bold{F}_{3^{7}} \\hookrightarrow \\Bold{F}_{3^{21}}'177"""178return '\\verb"Section of "' + self._inverse._latex_()179180181182cdef class FiniteFieldHomomorphism_generic(RingHomomorphism_im_gens):183"""184A class implementing embeddings between finite fields.185"""186def __init__(self, parent, im_gens=None, check=True, section_class=None):187"""188TESTS::189190sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic191sage: k.<t> = GF(3^7)192sage: K.<T> = GF(3^21)193sage: f = FiniteFieldHomomorphism_generic(Hom(k, K)); f194Ring morphism:195From: Finite Field in t of size 3^7196To: Finite Field in T of size 3^21197Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 2198199sage: k.<t> = GF(3^6)200sage: K.<t> = GF(3^9)201sage: FiniteFieldHomomorphism_generic(Hom(k, K))202Traceback (most recent call last):203...204ValueError: No embedding of Finite Field in t of size 3^6 into Finite Field in t of size 3^9205206sage: FiniteFieldHomomorphism_generic(Hom(ZZ, QQ))207Traceback (most recent call last):208...209TypeError: The domain is not a finite field210211sage: R.<x> = k[]212sage: FiniteFieldHomomorphism_generic(Hom(k, R))213Traceback (most recent call last):214...215TypeError: The codomain is not a finite field216"""217domain = parent.domain()218codomain = parent.codomain()219if not is_FiniteField(domain):220raise TypeError("The domain is not a finite field")221if not is_FiniteField(codomain):222raise TypeError("The codomain is not a finite field")223if domain.characteristic() != codomain.characteristic() or codomain.degree() % domain.degree() != 0:224raise ValueError("No embedding of %s into %s" % (domain, codomain))225if im_gens is None:226im_gens = domain.modulus().any_root(codomain)227check=False228RingHomomorphism_im_gens.__init__(self, parent, im_gens, check)229if section_class == None:230self._section_class = SectionFiniteFieldHomomorphism_generic231else:232self._section_class = section_class233234235def _latex_(self):236r"""237Return a latex representation of this embedding.238239EXAMPLES::240241sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic242sage: k.<t> = GF(3^7)243sage: K.<T> = GF(3^21)244sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))245sage: f._latex_()246'\\Bold{F}_{3^{7}} \\hookrightarrow \\Bold{F}_{3^{21}}'247"""248return self.domain()._latex_() + " \\hookrightarrow " + self.codomain()._latex_()249250251cpdef Element _call_(self, x):252"""253TESTS::254255sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic256sage: k.<t> = GF(3^3)257sage: K.<T> = GF(3^9)258sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))259sage: f(t)2602*T^6 + 2*T^4 + T^2 + T261262sage: a = k.random_element()263sage: b = k.random_element()264sage: f(a+b) == f(a) + f(b)265True266sage: f(a*b) == f(a) * f(b)267True268"""269if not self.domain().has_coerce_map_from(x.parent()):270raise TypeError("%s does not coerce to %s" % (x, self.domain()))271return x.polynomial()(self.im_gens()[0])272273274def is_injective(self):275"""276Return True since a embedding between finite fields is277always injective.278279EXAMPLES::280281sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic282sage: k.<t> = GF(3^3)283sage: K.<T> = GF(3^9)284sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))285sage: f.is_injective()286True287"""288return True289290291def is_surjective(self):292"""293Return true if this embedding is surjective (and hence an294isomorphism.295296EXAMPLES::297298sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic299sage: k.<t> = GF(3^3)300sage: K.<T> = GF(3^9)301sage: f = FiniteFieldHomomorphism_generic(Hom(k, K))302sage: f.is_surjective()303False304sage: g = FiniteFieldHomomorphism_generic(Hom(k, k))305sage: g.is_surjective()306True307"""308return self.domain().cardinality() == self.codomain().cardinality()309310311@cached_method312def section(self):313"""314Return the ``inverse`` of this embedding.315316It is a partially defined map whose domain is the codomain317of the embedding, but which is only defined on the image of318the embedding.319320EXAMPLES::321322sage: from sage.rings.finite_rings.hom_finite_field import FiniteFieldHomomorphism_generic323sage: k.<t> = GF(3^7)324sage: K.<T> = GF(3^21)325sage: f = FiniteFieldHomomorphism_generic(Hom(k, K));326sage: g = f.section(); g327Section of Ring morphism:328From: Finite Field in t of size 3^7329To: Finite Field in T of size 3^21330Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 2331sage: g(f(t^3+t^2+1))332t^3 + t^2 + 1333sage: g(T)334Traceback (most recent call last):335...336ValueError: T is not in the image of Ring morphism:337From: Finite Field in t of size 3^7338To: Finite Field in T of size 3^21339Defn: t |--> T^20 + T^19 + T^18 + 2*T^17 + 2*T^16 + 2*T^12 + T^9 + T^6 + 2*T^5 + T^3 + 2*T^2 + T + 2340"""341return self._section_class(self)342343344def __richcmp__(left, right, int op):345return (<Element>left)._richcmp(right, op)346347348def __hash__(self):349return Morphism.__hash__(self)350351352353cdef class FrobeniusEndomorphism_finite_field(FrobeniusEndomorphism_generic):354"""355A class implementing Frobenius endomorphisms on finite fields.356"""357def __init__(self, domain, n=1):358"""359INPUT:360361- ``domain`` -- a finite field362363- ``n`` -- an integer (default: 1)364365.. NOTE::366367`n` may be negative.368369OUTPUT:370371The `n`-th power of the absolute (arithmetic) Frobenius372endomorphism on ``domain``373374TESTS::375376sage: from sage.rings.finite_rings.hom_finite_field import FrobeniusEndomorphism_finite_field377sage: k.<t> = GF(5^3)378sage: FrobeniusEndomorphism_finite_field(k)379Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3380sage: FrobeniusEndomorphism_finite_field(k, 2)381Frobenius endomorphism t |--> t^(5^2) on Finite Field in t of size 5^3382383sage: FrobeniusEndomorphism_finite_field(k, t)384Traceback (most recent call last):385...386TypeError: n (=t) is not an integer387388sage: FrobeniusEndomorphism_finite_field(k['x'])389Traceback (most recent call last):390...391TypeError: The domain must be a finite field392"""393if not is_FiniteField(domain):394raise TypeError("The domain must be a finite field")395try:396n = Integer(n)397except TypeError:398raise TypeError("n (=%s) is not an integer" % n)399400if domain.is_finite():401self._degree = domain.degree()402self._power = n % self._degree403self._degree_fixed = domain.degree().gcd(self._power)404self._order = self._degree / self._degree_fixed405self._q = domain.characteristic() ** self._power406RingHomomorphism.__init__(self, Hom(domain, domain))407408409def _repr_(self):410"""411Return a string representation of this endomorphism.412413EXAMPLES::414415sage: k.<t> = GF(5^3)416sage: Frob = k.frobenius_endomorphism(); Frob417Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3418419sage: Frob._repr_()420'Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3'421"""422name = self.domain().variable_name()423if self._power == 0:424s = "Identity endomorphism of"425elif self._power == 1:426s = "Frobenius endomorphism %s |--> %s^%s on" % (name, name, self.domain().characteristic())427else:428s = "Frobenius endomorphism %s |--> %s^(%s^%s) on" % (name, name, self.domain().characteristic(), self._power)429s += " %s" % self.domain()430return s431432433def _repr_short(self):434"""435Return a short string representation of this endomorphism.436437EXAMPLES::438439sage: k.<t> = GF(5^3)440sage: Frob = k.frobenius_endomorphism(); Frob441Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3442443sage: Frob._repr_short()444't |--> t^5'445"""446name = self.domain().variable_name()447if self._power == 0:448s = "Identity"449elif self._power == 1:450s = "%s |--> %s^%s" % (name, name, self.domain().characteristic())451else:452s = "%s |--> %s^(%s^%s)" % (name, name, self.domain().characteristic(), self._power)453return s454455456def _latex_(self):457r"""458Return a latex representation of this endomorphism.459460EXAMPLES::461462sage: k.<t> = GF(5^3)463sage: Frob = k.frobenius_endomorphism()464sage: Frob._latex_()465't \\mapsto t^{5}'466"""467try:468name = self.domain().latex_variable_names()[0]469except IndexError:470name = "x"471if self._power == 0:472s = '\\verb"id"'473elif self._power == 1:474s = "%s \\mapsto %s^{%s}" % (name, name, self.domain().characteristic())475else:476s = "%s \\mapsto %s^{%s^{%s}}" % (name, name, self.domain().characteristic(), self._power)477return s478479480cpdef Element _call_(self, x):481"""482TESTS::483484sage: k.<t> = GF(5^3)485sage: Frob = k.frobenius_endomorphism()486sage: Frob(t)4872*t^2 + 4*t + 4488sage: Frob(t) == t^5489True490"""491return x ** self._q492493494def order(self):495"""496Return the order of this endomorphism.497498EXAMPLES::499500sage: k.<t> = GF(5^12)501sage: Frob = k.frobenius_endomorphism()502sage: Frob.order()50312504sage: (Frob^2).order()5056506sage: (Frob^9).order()5074508"""509if self._order == 0:510from sage.rings.infinity import Infinity511return Infinity512else:513return Integer(self._order)514515def power(self):516"""517Return an integer `n` such that this endormorphism518is the `n`-th power of the absolute (arithmetic)519Frobenius.520521EXAMPLES::522523sage: k.<t> = GF(5^12)524sage: Frob = k.frobenius_endomorphism()525sage: Frob.power()5261527sage: (Frob^9).power()5289529sage: (Frob^13).power()5301531"""532return self._power533534535def __pow__(self, n, modulus):536"""537Return the `n`-th iterate of this endomorphism.538539EXAMPLES::540541sage: k.<t> = GF(5^12)542sage: Frob = k.frobenius_endomorphism(); Frob543Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^12544sage: Frob^2545Frobenius endomorphism t |--> t^(5^2) on Finite Field in t of size 5^12546547The result is simplified if possible::548549sage: Frob^15550Frobenius endomorphism t |--> t^(5^3) on Finite Field in t of size 5^12551sage: Frob^36552Identity endomorphism of Finite Field in t of size 5^12553"""554return self.__class__(self.domain(), self.power()*n)555556557def _composition(self, right):558"""559Return self o right.560561EXAMPLES::562563sage: k.<t> = GF(5^12)564sage: f = k.frobenius_endomorphism(); f565Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^12566sage: g = k.frobenius_endomorphism(2); g567Frobenius endomorphism t |--> t^(5^2) on Finite Field in t of size 5^12568sage: f * g569Frobenius endomorphism t |--> t^(5^3) on Finite Field in t of size 5^12570571The result is simplified if possible::572573sage: f = k.frobenius_endomorphism(9)574sage: g = k.frobenius_endomorphism(10)575sage: f * g576Frobenius endomorphism t |--> t^(5^7) on Finite Field in t of size 5^12577"""578if isinstance(right, FrobeniusEndomorphism_finite_field):579return self.__class__(self.domain(), self._power + right.power())580else:581return RingHomomorphism._composition(self, right)582583584def fixed_field(self):585"""586Return the fixed field of ``self``.587588OUTPUT:589590- a tuple `(K, e)`, where `K` is the subfield of the domain591consisting of elements fixed by ``self`` and `e` is an592embedding of `K` into the domain.593594.. NOTE::595596The name of the variable used for the subfield (if it597is not a prime subfield) is suffixed by ``_fixed``.598599EXAMPLES::600601sage: k.<t> = GF(5^6)602sage: f = k.frobenius_endomorphism(2)603sage: kfixed, embed = f.fixed_field()604sage: kfixed605Finite Field in t_fixed of size 5^2606sage: embed607Ring morphism:608From: Finite Field in t_fixed of size 5^2609To: Finite Field in t of size 5^6610Defn: t_fixed |--> 4*t^5 + 2*t^4 + 4*t^2 + t611612sage: tfixed = kfixed.gen()613sage: embed(tfixed)6144*t^5 + 2*t^4 + 4*t^2 + t615"""616if self._degree_fixed == 1:617k = FiniteField(self._domain.characteristic())618from hom_prime_finite_field import FiniteFieldHomomorphism_prime619f = FiniteFieldHomomorphism_prime(Hom(k, self._domain))620else:621k = FiniteField(self._domain.characteristic()**self._degree_fixed,622name=self._domain.variable_name() + "_fixed")623f = FiniteFieldHomomorphism_generic(Hom(k, self._domain))624return k, f625626627def is_injective(self):628"""629Return true since any power of the Frobenius endomorphism630over a finite field is always injective.631632EXAMPLES::633634sage: k.<t> = GF(5^3)635sage: Frob = k.frobenius_endomorphism()636sage: Frob.is_injective()637True638"""639return True640641642def is_surjective(self):643"""644Return true since any power of the Frobenius endomorphism645over a finite field is always surjective.646647EXAMPLES::648649sage: k.<t> = GF(5^3)650sage: Frob = k.frobenius_endomorphism()651sage: Frob.is_surjective()652True653"""654return True655656657def is_identity(self):658"""659Return true if this morphism is the identity morphism.660661EXAMPLES::662663sage: k.<t> = GF(5^3)664sage: Frob = k.frobenius_endomorphism()665sage: Frob.is_identity()666False667sage: (Frob^3).is_identity()668True669"""670return self.power() == 0671672673def __richcmp__(left, right, int op):674return (<Element>left)._richcmp(right, op)675676677def __hash__(self):678return Morphism.__hash__(self)679680681from sage.structure.sage_object import register_unpickle_override682register_unpickle_override('sage.rings.finite_field_morphism', 'FiniteFieldHomomorphism_generic', FiniteFieldHomomorphism_generic)683684685