Path: blob/master/src/sage/groups/semimonomial_transformations/semimonomial_transformation.pyx
8815 views
r"""1Elements of a semimonomial transformation group.23The semimonomial transformation group of degree `n` over a ring `R` is4the semidirect product of the monomial transformation group of degree `n`5(also known as the complete monomial group over the group of units6`R^{\times}` of `R`) and the group of ring automorphisms.78The multiplication of two elements `(\phi, \pi, \alpha)(\psi, \sigma, \beta)`9with1011- `\phi, \psi \in {R^{\times}}^n`1213- `\pi, \sigma \in S_n` (with the multiplication `\pi\sigma`14done from left to right (like in GAP) --15that is, `(\pi\sigma)(i) = \sigma(\pi(i))` for all `i`.)1617- `\alpha, \beta \in Aut(R)`1819is defined by2021.. math::2223(\phi, \pi, \alpha)(\psi, \sigma, \beta) =24(\phi \cdot \psi^{\pi, \alpha}, \pi\sigma, \alpha \circ \beta)2526with27`\psi^{\pi, \alpha} = (\alpha(\psi_{\pi(1)-1}), \ldots, \alpha(\psi_{\pi(n)-1}))`28and an elementwisely defined multiplication of vectors. (The indexing29of vectors is `0`-based here, so `\psi = (\psi_0, \psi_1, \ldots, \psi_{n-1})`.)30313233The parent is34:class:`~sage.groups.semimonomial_transformations.semimonomial_transformation_group.SemimonomialTransformationGroup`.3536AUTHORS:3738- Thomas Feulner (2012-11-15): initial version39- Thomas Feulner (2013-12-27): :trac:`15576` dissolve dependency on40Permutations().global_options()['mul']4142EXAMPLES::4344sage: S = SemimonomialTransformationGroup(GF(4, 'a'), 4)45sage: G = S.gens()46sage: G[0]*G[1]47((a, 1, 1, 1); (1,2,3,4), Ring endomorphism of Finite Field in a of size 2^248Defn: a |--> a)4950TESTS::5152sage: TestSuite(G[0]).run()53"""54include "../../ext/stdsage.pxi"555657def _is_id(f, R):58"""59Test some automorphism `f` of a ring `R` if it is the identity60automorphism.6162EXAMPLES::6364sage: from sage.groups.semimonomial_transformations.semimonomial_transformation import _is_id65sage: F.<a> = GF(8)66sage: f = F.hom([a**2])67sage: _is_id(f, F)68False69"""70for r in R.gens():71if r != f(r):72return False73return True747576def _inverse(f, R):77"""78Returns the inverse to the automorphism `f` of a ring `R`.7980EXAMPLES::8182sage: from sage.groups.semimonomial_transformations.semimonomial_transformation import _inverse83sage: F.<a> = GF(8)84sage: f = F.hom([a**2])85sage: _inverse(f, F)*f == F.hom([a])86True87"""88g = f89while not _is_id(g*f, R):90g *= f91return g9293cdef class SemimonomialTransformation(MultiplicativeGroupElement):94r"""95An element in the semimonomial group over a ring `R`. See96:class:`~sage.groups.semimonomial_transformations.semimonomial_transformation_group.SemimonomialTransformationGroup`97for the details on the multiplication of two elements.9899The init method should never be called directly. Use the call via the100parent101:class:`~sage.groups.semimonomial_transformations.semimonomial_transformation_group.SemimonomialTransformationGroup`.102instead.103104EXAMPLES::105106sage: F.<a> = GF(9)107sage: S = SemimonomialTransformationGroup(F, 4)108sage: g = S(v = [2, a, 1, 2])109sage: h = S(perm = Permutation('(1,2,3,4)'), autom=F.hom([a**3]))110sage: g*h111((2, a, 1, 2); (1,2,3,4), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1)112sage: h*g113((2*a + 1, 1, 2, 2); (1,2,3,4), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1)114sage: S(g)115((2, a, 1, 2); (), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a)116sage: S(1) # the one element in the group117((1, 1, 1, 1); (), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a)118"""119def __init__(self, parent, v, perm, alpha):120r"""121The init method should never be called directly. Use the call via the122parent instead. See123:meth:`sage.groups.semimonomial_transformations.semimonomial_transformation.SemimonomialTransformation.__call__`.124125EXAMPLES::126127sage: F.<a> = GF(9)128sage: S = SemimonomialTransformationGroup(F, 4)129sage: g = S(v = [2, a, 1, 2]) #indirect doctest130"""131MultiplicativeGroupElement.__init__(self, parent)132self.v = tuple(v)133self.perm = perm134self.alpha = alpha135136cdef _new_c(self):137# Create a copy of self.138cdef SemimonomialTransformation x139x = PY_NEW(SemimonomialTransformation)140x._parent = self._parent141x.v = self.v142x.perm = self.perm143x.alpha = self.alpha144return x145146def __copy__(self):147"""148Return a copy of ``self``.149150EXAMPLES::151152sage: F.<a> = GF(9)153sage: s = SemimonomialTransformationGroup(F, 4).an_element()154sage: t = copy(s) #indirect doctest155sage: t is s156False157sage: t == s158True159"""160return self._new_c()161162def __hash__(self):163"""164Return hash of this element.165166EXAMPLES::167168sage: F.<a> = GF(9)169sage: hash( SemimonomialTransformationGroup(F, 4).an_element() ) #random #indirect doctest1706279637968393375107171"""172return hash(self.v) + hash(self.perm) + hash(self.get_autom())173174cpdef MonoidElement _mul_(left, MonoidElement _right):175r"""176Multiplication of elements.177178The multiplication of two elements `(\phi, \pi, \alpha)` and179`(\psi, \sigma, \beta)` with180181- `\phi, \psi \in {R^{\times}}^n`182183- `\pi, \sigma \in S_n`184185- `\alpha, \beta \in Aut(R)`186187is defined by:188189.. math::190191(\phi, \pi, \alpha)(\psi, \sigma, \beta) =192(\phi \cdot \psi^{\pi, \alpha}, \pi\sigma, \alpha \circ \beta)193194with195`\psi^{\pi, \alpha} = (\alpha(\psi_{\pi(1)-1}), \ldots, \alpha(\psi_{\pi(n)-1}))`196and an elementwisely defined multiplication of vectors. (The indexing197of vectors is `0`-based here, so `\psi = (\psi_0, \psi_1, \ldots, \psi_{n-1})`.)198Furthermore, the multiplication `\pi\sigma` is done from left to right199(like in GAP) -- that is, `(\pi\sigma)(i) = \sigma(\pi(i))` for all `i`.200201EXAMPLES::202203sage: F.<a> = GF(9)204sage: s = SemimonomialTransformationGroup(F, 4).an_element()205sage: s*s #indirect doctest206((a, 2*a + 1, 1, 1); (1,3)(2,4), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> a)207"""208cdef SemimonomialTransformation right = <SemimonomialTransformation> _right209cdef i210v = left.perm.action(right.v)211alpha = left.get_autom()212v = [left.v[i]*alpha(v[i]) for i in range(left.parent().degree())]213return left.parent()(v=v, perm=left.perm.right_action_product(right.perm),214autom=alpha*right.get_autom(), check=False)215216def __invert__(self):217"""218Return the inverse of ``self``.219220EXAMPLES::221222sage: F.<a> = GF(9)223sage: S = SemimonomialTransformationGroup(F, 4)224sage: s = S.an_element()225sage: s*s**(-1) == S(1) # indirect doctest226True227"""228cdef i229alpha = _inverse(self.get_autom(), self.get_autom().domain())230inv_perm = self.perm.inverse()231v = [alpha(self.v[i]**(-1)) for i in range(len(self.v))]232return self.parent()(v=inv_perm.action(v), perm=inv_perm, autom=alpha,233check=False)234235def __repr__(self):236"""237String representation of `self`.238239EXAMPLES::240241sage: F.<a> = GF(9)242sage: SemimonomialTransformationGroup(F, 4).an_element() # indirect doctest243((a, 1, 1, 1); (1,4,3,2), Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1)244"""245return "(%s; %s, %s)"%(self.v, self.perm.cycle_string(),246self.get_autom())247248def __cmp__(self, right):249"""250Compare group elements ``self`` and ``right``.251252EXAMPLES::253254sage: F.<a> = GF(9)255sage: g = SemimonomialTransformationGroup(F, 4).gens()256sage: g[0] > g[1] # indirect doctest257True258sage: g[1] != g[2] # indirect doctest259True260"""261return (<Element> self)._cmp(right)262263cdef int _cmp_c_impl(left, Element _right) except -2:264cdef SemimonomialTransformation right = <SemimonomialTransformation> _right265return cmp([left.v, left.perm, left.get_autom()],266[right.v, right.perm, right.get_autom()])267268def __reduce__(self):269"""270Returns a function and its arguments needed to create this271semimonomial group element. This is used in pickling.272273EXAMPLES::274275sage: F.<a> = GF(9)276sage: SemimonomialTransformationGroup(F, 4).an_element().__reduce__()277(Semimonomial transformation group over Finite Field in a of size 3^2 of degree 4, (0, (a, 1, 1, 1), [4, 1, 2, 3], Ring endomorphism of Finite Field in a of size 3^2278Defn: a |--> 2*a + 1))279"""280return (self.parent(), (0, self.v, self.perm, self.get_autom()))281282def get_v(self):283"""284Returns the component corresponding to `{R^{\times}}^n` of ``self``.285286EXAMPLES::287288sage: F.<a> = GF(9)289sage: SemimonomialTransformationGroup(F, 4).an_element().get_v()290(a, 1, 1, 1)291"""292return self.v293294def get_v_inverse(self):295"""296Returns the (elementwise) inverse of the component corresponding to297`{R^{\times}}^n` of ``self``.298299EXAMPLES::300301sage: F.<a> = GF(9)302sage: SemimonomialTransformationGroup(F, 4).an_element().get_v_inverse()303(a + 2, 1, 1, 1)304"""305return tuple(x**(-1) for x in self.v)306307def get_perm(self):308"""309Returns the component corresponding to `S_n` of ``self``.310311EXAMPLES::312313sage: F.<a> = GF(9)314sage: SemimonomialTransformationGroup(F, 4).an_element().get_perm()315[4, 1, 2, 3]316"""317return self.perm318319def get_autom(self):320"""321Returns the component corresponding to `Aut(R)` of ``self``.322323EXAMPLES::324325sage: F.<a> = GF(9)326sage: SemimonomialTransformationGroup(F, 4).an_element().get_autom()327Ring endomorphism of Finite Field in a of size 3^2 Defn: a |--> 2*a + 1328"""329return self.alpha330331def invert_v(self):332"""333Elementwisely inverts all entries of ``self`` which334correspond to the component `{R^{\times}}^n`.335336The other components of ``self`` keep unchanged.337338EXAMPLES::339340sage: F.<a> = GF(9)341sage: x = copy(SemimonomialTransformationGroup(F, 4).an_element())342sage: x.invert_v();343sage: x.get_v() == SemimonomialTransformationGroup(F, 4).an_element().get_v_inverse()344True345"""346self.v = tuple([x**(-1) for x in self.v])347348349