Path: blob/master/src/sage/groups/affine_gps/affine_group.py
8815 views
r"""1Affine Groups23AUTHORS:45- Volker Braun: initial version6"""78##############################################################################9# Copyright (C) 2013 Volker Braun <[email protected]>10#11# Distributed under the terms of the GNU General Public License (GPL)12#13# The full text of the GPL is available at:14#15# http://www.gnu.org/licenses/16##############################################################################171819from sage.categories.groups import Groups20from sage.groups.group import Group21from sage.matrix.all import MatrixSpace22from sage.modules.all import FreeModule23from sage.structure.unique_representation import UniqueRepresentation24from sage.misc.cachefunc import cached_method2526from sage.groups.affine_gps.group_element import AffineGroupElement272829#################################################################3031class AffineGroup(UniqueRepresentation, Group):32r"""33An affine group.3435The affine group `\mathrm{Aff}(A)` (or general affine group) of an affine36space `A` is the group of all invertible affine transformations from the37space into itself.3839If we let `A_V` be the affine space of a vector space `V`40(essentially, forgetting what is the origin) then the affine group41`\mathrm{Aff}(A_V)` is the group generated by the general linear group42`GL(V)` together with the translations. Recall that the group of43translations acting on `A_V` is just `V` itself. The general linear and44translation subgroups do not quite commute, and in fact generate the45semidirect product4647.. MATH::4849\mathrm{Aff}(A_V) = GL(V) \ltimes V.5051As such, the group elements can be represented by pairs `(A, b)` of a52matrix and a vector. This pair then represents the transformation5354.. MATH::5556x \mapsto A x + b.5758We can also represent affine transformations as linear transformations by59considering `\dim(V) + 1` dimensonal space. We take the affine60transformation `(A, b)` to6162.. MATH::6364\begin{pmatrix}65A & b \\660 & 167\end{pmatrix}6869and lifting `x = (x_1, \ldots, x_n)` to `(x_1, \ldots, x_n, 1)`. Here70the `(n + 1)`-th component is always 1, so the linear representations71acts on the affine hyperplane `x_{n+1} = 1` as affine transformations72which can be seen directly from the matrix multiplication.7374INPUT:7576Something that defines an affine space. For example7778- An affine space itself:7980* ``A`` -- affine space8182- A vector space:8384* ``V`` -- a vector space8586- Degree and base ring:8788* ``degree`` -- An integer. The degree of the affine group, that89is, the dimension of the affine space the group is acting on.9091* ``ring`` -- A ring or an integer. The base ring of the affine92space. If an integer is given, it must be a prime power and93the corresponding finite field is constructed.9495* ``var`` -- (Defalut: ``'a'``) Keyword argument to specify the finite96field generator name in the case where ``ring`` is a prime power.9798EXAMPLES::99100sage: F = AffineGroup(3, QQ); F101Affine Group of degree 3 over Rational Field102sage: F(matrix(QQ,[[1,2,3],[4,5,6],[7,8,0]]), vector(QQ,[10,11,12]))103[1 2 3] [10]104x |-> [4 5 6] x + [11]105[7 8 0] [12]106sage: F([[1,2,3],[4,5,6],[7,8,0]], [10,11,12])107[1 2 3] [10]108x |-> [4 5 6] x + [11]109[7 8 0] [12]110sage: F([1,2,3,4,5,6,7,8,0], [10,11,12])111[1 2 3] [10]112x |-> [4 5 6] x + [11]113[7 8 0] [12]114115Instead of specifying the complete matrix/vector information, you can116also create special group elements::117118sage: F.linear([1,2,3,4,5,6,7,8,0])119[1 2 3] [0]120x |-> [4 5 6] x + [0]121[7 8 0] [0]122sage: F.translation([1,2,3])123[1 0 0] [1]124x |-> [0 1 0] x + [2]125[0 0 1] [3]126127Some additional ways to create affine groups::128129sage: A = AffineSpace(2, GF(4,'a')); A130Affine Space of dimension 2 over Finite Field in a of size 2^2131sage: G = AffineGroup(A); G132Affine Group of degree 2 over Finite Field in a of size 2^2133sage: G is AffineGroup(2,4) # shorthand134True135136sage: V = ZZ^3; V137Ambient free module of rank 3 over the principal ideal domain Integer Ring138sage: AffineGroup(V)139Affine Group of degree 3 over Integer Ring140141REFERENCES:142143- :wikipedia:`Affine_group`144"""145@staticmethod146def __classcall__(cls, *args, **kwds):147"""148Normalize input to ensure a unique representation.149150EXAMPLES::151152sage: A = AffineSpace(2, GF(4,'a'))153sage: AffineGroup(A) is AffineGroup(2,4)154True155sage: AffineGroup(A) is AffineGroup(2, GF(4,'a'))156True157sage: A = AffineGroup(2, QQ)158sage: V = QQ^2159sage: A is AffineGroup(V)160True161"""162if len(args) == 1:163V = args[0]164if isinstance(V, AffineGroup):165return V166try:167degree = V.dimension_relative()168except AttributeError:169degree = V.dimension()170ring = V.base_ring()171if len(args) == 2:172degree, ring = args173from sage.rings.integer import is_Integer174if is_Integer(ring):175from sage.rings.finite_rings.constructor import FiniteField176var = kwds.get('var', 'a')177ring = FiniteField(ring, var)178return super(AffineGroup, cls).__classcall__(cls, degree, ring)179180def __init__(self, degree, ring):181"""182Initialize ``self``.183184INPUT:185186- ``degree`` -- integer. The degree of the affine group, that187is, the dimension of the affine space the group is acting on188naturally.189190- ``ring`` -- a ring. The base ring of the affine space.191192EXAMPLES::193194sage: Aff6 = AffineGroup(6, QQ)195sage: Aff6 == Aff6196True197sage: Aff6 != Aff6198False199200TESTS::201202sage: G = AffineGroup(2, GF(5)); G203Affine Group of degree 2 over Finite Field of size 5204sage: TestSuite(G).run()205"""206self._degree = degree207Group.__init__(self, base=ring)208209Element = AffineGroupElement210211def _element_constructor_check(self, A, b):212"""213Verify that ``A``, ``b`` define an affine group element and raises a214``TypeError`` if the input does not define a valid group element.215216This is called from the group element constructor and can be217overridden for subgroups of the affine group. It is guaranteed218that ``A``, ``b`` are in the correct matrix/vetor space.219220INPUT:221222- ``A`` -- an element of :meth:`matrix_space`223224- ``b`` -- an element of :meth:`vector_space`225226TESTS::227228sage: Aff3 = AffineGroup(3, QQ)229sage: A = Aff3.matrix_space()([1,2,3,4,5,6,7,8,0])230sage: det(A)23127232sage: b = Aff3.vector_space().an_element()233sage: Aff3._element_constructor_check(A, b)234235sage: A = Aff3.matrix_space()([1,2,3,4,5,6,7,8,9])236sage: det(A)2370238sage: Aff3._element_constructor_check(A, b)239Traceback (most recent call last):240...241TypeError: A must be invertible242"""243if not A.is_invertible():244raise TypeError('A must be invertible')245246def _latex_(self):247r"""248Return a LaTeX representation of ``self``.249250EXAMPLES::251252sage: G = AffineGroup(6, GF(5))253sage: latex(G)254\mathrm{Aff}_{6}(\Bold{F}_{5})255"""256return "\\mathrm{Aff}_{%s}(%s)"%(self.degree(), self.base_ring()._latex_())257258def _repr_(self):259"""260Return a string representation of ``self``.261262EXAMPLES::263264sage: AffineGroup(6, GF(5))265Affine Group of degree 6 over Finite Field of size 5266"""267return "Affine Group of degree %s over %s"%(self.degree(), self.base_ring())268269def degree(self):270"""271Return the dimension of the affine space.272273OUTPUT:274275An integer.276277EXAMPLES::278279sage: G = AffineGroup(6, GF(5))280sage: g = G.an_element()281sage: G.degree()2826283sage: G.degree() == g.A().nrows() == g.A().ncols() == g.b().degree()284True285"""286return self._degree287288@cached_method289def matrix_space(self):290"""291Return the space of matrices representing the general linear292transformations.293294OUTPUT:295296The parent of the matrices `A` defining the affine group297element `Ax+b`.298299EXAMPLES::300301sage: G = AffineGroup(3, GF(5))302sage: G.matrix_space()303Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 5304"""305d = self.degree()306return MatrixSpace(self.base_ring(), d, d)307308@cached_method309def vector_space(self):310"""311Return the vector space of the underlying affine space.312313EXAMPLES::314315sage: G = AffineGroup(3, GF(5))316sage: G.vector_space()317Vector space of dimension 3 over Finite Field of size 5318"""319return FreeModule(self.base_ring(), self.degree())320321@cached_method322def linear_space(self):323r"""324Return the space of the affine transformations represented as linear325transformations.326327We can represent affine transformations `Ax + b` as linear328transformations by329330.. MATH::331332\begin{pmatrix}333A & b \\3340 & 1335\end{pmatrix}336337and lifting `x = (x_1, \ldots, x_n)` to `(x_1, \ldots, x_n, 1)`.338339.. SEEALSO::340341- :meth:`sage.groups.affine_gps.group_element.AffineGroupElement.matrix()`342343EXAMPLES::344345sage: G = AffineGroup(3, GF(5))346sage: G.linear_space()347Full MatrixSpace of 4 by 4 dense matrices over Finite Field of size 5348"""349dp = self.degree() + 1350return MatrixSpace(self.base_ring(), dp, dp)351352def linear(self, A):353"""354Construct the general linear transformation by ``A``.355356INPUT:357358- ``A`` -- anything that determines a matrix359360OUTPUT:361362The affine group element `x \mapsto A x`.363364EXAMPLES::365366sage: G = AffineGroup(3, GF(5))367sage: G.linear([1,2,3,4,5,6,7,8,0])368[1 2 3] [0]369x |-> [4 0 1] x + [0]370[2 3 0] [0]371"""372A = self.matrix_space()(A)373return self.element_class(self, A, self.vector_space().zero(), check=True, convert=False)374375def translation(self, b):376"""377Construct the translation by ``b``.378379INPUT:380381- ``b`` -- anything that determines a vector382383OUTPUT:384385The affine group element `x \mapsto x + b`.386387EXAMPLES::388389sage: G = AffineGroup(3, GF(5))390sage: G.translation([1,4,8])391[1 0 0] [1]392x |-> [0 1 0] x + [4]393[0 0 1] [3]394"""395b = self.vector_space()(b)396return self.element_class(self, self.matrix_space().one(), b, check=False, convert=False)397398def reflection(self, v):399"""400Construct the Householder reflection.401402A Householder reflection (transformation) is the affine transformation403corresponding to an elementary reflection at the hyperplane404perpendicular to `v`.405406INPUT:407408- ``v`` -- a vector, or something that determines a vector.409410OUTPUT:411412The affine group element that is just the Householder413transformation (a.k.a. Householder reflection, elementary414reflection) at the hyperplane perpendicular to `v`.415416EXAMPLES::417418sage: G = AffineGroup(3, QQ)419sage: G.reflection([1,0,0])420[-1 0 0] [0]421x |-> [ 0 1 0] x + [0]422[ 0 0 1] [0]423sage: G.reflection([3,4,-5])424[ 16/25 -12/25 3/5] [0]425x |-> [-12/25 9/25 4/5] x + [0]426[ 3/5 4/5 0] [0]427"""428v = self.vector_space()(v)429try:430two_norm2inv = self.base_ring()(2) / sum([ vi**2 for vi in v ])431except ZeroDivisionError:432raise ValueError('v has norm zero')433from sage.matrix.constructor import identity_matrix434A = self.matrix_space().one() - v.column() * (v.row() * two_norm2inv)435return self.element_class(self, A, self.vector_space().zero(), check=True, convert=False)436437def random_element(self):438"""439Return a random element of this group.440441EXAMPLES::442443sage: G = AffineGroup(4, GF(3))444sage: G.random_element() # random445[2 0 1 2] [1]446[2 1 1 2] [2]447x |-> [1 0 2 2] x + [2]448[1 1 1 1] [2]449sage: G.random_element() in G450True451"""452A = self.matrix_space().random_element()453while not A.is_invertible(): # a generic matrix is invertible454A.randomize()455b = self.vector_space().random_element()456return self.element_class(self, A, b, check=False, convert=False)457458@cached_method459def _an_element_(self):460"""461Return an element.462463TESTS::464465sage: G = AffineGroup(4,5)466sage: G.an_element() in G467True468"""469A = self.matrix_space().an_element()470while not A.is_invertible(): # a generic matrix is not always invertible471A.randomize()472b = self.vector_space().an_element()473return self.element_class(self, A, b, check=False, convert=False)474475476477