Exemplo n.º 1
0
    def example(self):
        """
        EXAMPLES::

            sage: Groups().example()
            General Linear Group of degree 4 over Rational Field
        """
        from sage.rings.rational_field import QQ
        from sage.groups.matrix_gps.linear import GL
        return GL(4, QQ)
Exemplo n.º 2
0
    def __setstate__(self, state):
        """
        Restore from old pickle.

        EXAMPLES::

            sage: from sage.groups.group import Group
            sage: from sage.groups.matrix_gps.pickling_overrides import LegacyGeneralLinearGroup
            sage: state = dict()
            sage: state['_MatrixGroup_gap__n'] = 2
            sage: state['_MatrixGroup_gap__R'] = ZZ
            sage: M = Group.__new__(LegacyGeneralLinearGroup)
            sage: M.__setstate__(state)
            sage: M
            General Linear Group of degree 2 over Integer Ring
        """
        ring = state['_MatrixGroup_gap__R']
        n = state['_MatrixGroup_gap__n']
        G = GL(n, ring)
        self.__init__(G.degree(), G.base_ring(), G._special, G._name_string, G._latex_string)
Exemplo n.º 3
0
    def __setstate__(self, state):
        """
        Restore from old pickle.

        EXAMPLES::

            sage: from sage.groups.group import Group
            sage: from sage.groups.matrix_gps.pickling_overrides import LegacyGeneralLinearGroup
            sage: state = dict()
            sage: state['_MatrixGroup_gap__n'] = 2
            sage: state['_MatrixGroup_gap__R'] = ZZ
            sage: M = Group.__new__(LegacyGeneralLinearGroup)
            sage: M.__setstate__(state)
            sage: M
            General Linear Group of degree 2 over Integer Ring
        """
        ring = state['_MatrixGroup_gap__R']
        n = state['_MatrixGroup_gap__n']
        G = GL(n, ring)
        self.__init__(G.degree(), G.base_ring(), G._special, G._name_string, G._latex_string)
Exemplo n.º 4
0
    def example(self):
        """
        Returns an example of finite group, as per
        :meth:`Category.example`.

        EXAMPLES::

            sage: G = FiniteGroups().example(); G
            General Linear Group of degree 2 over Finite Field of size 3
        """
        from sage.groups.matrix_gps.linear import GL
        return GL(2, 3)
Exemplo n.º 5
0
    def __init__(self, degree, ring):
        """
        Initialize ``self``.

        INPUT:

        - ``degree`` -- integer. The degree of the affine group, that
          is, the dimension of the affine space the group is acting on
          naturally.

        - ``ring`` -- a ring. The base ring of the affine space.

        EXAMPLES::

            sage: Aff6 = AffineGroup(6, QQ)
            sage: Aff6 == Aff6
            True
            sage: Aff6 != Aff6
            False

        TESTS::

            sage: G = AffineGroup(2, GF(5)); G
            Affine Group of degree 2 over Finite Field of size 5
            sage: TestSuite(G).run()
            sage: G.category()
            Category of finite groups

            sage: Aff6 = AffineGroup(6, QQ)
            sage: Aff6.category()
            Category of infinite groups
        """
        self._degree = degree
        cat = Groups()
        if degree == 0 or ring in Rings().Finite():
            cat = cat.Finite()
        elif ring in Rings().Infinite():
            cat = cat.Infinite()
        self._GL = GL(degree, ring)
        Group.__init__(self, base=ring, category=cat)
Exemplo n.º 6
0
    def ProjectiveLine(p, r=None, u=None):
        r"""
        Return the projective line with action given by the matrices ``r``
        and ``u`` on the projective line over the field with ``p`` elements.

        If ``r`` and ``u`` are None, then r and u are choosen to be

        .. MATH::

            r: z \mapsto z+1   \qquad    u: z \mapsto 1/z

        The monodromy of this origami is included in `PGL(2,\ZZ/p\ZZ)`.

        EXAMPLES::

            sage: from surface_dynamics.all import *

        By default, the matrix used to generate the projective line origami are
        given by `z -> z+1` and `z -> 1/z` which gives a family of origamis
        which belongs to the strata ``H(2^k)``::

            sage: o = origamis.ProjectiveLine(3); o
            Projective line origami on GF(3)
             r = [1 1]    u = [0 1]
                 [0 1]        [1 0]
            sage: o.stratum()
            H_2(2)
            sage: o.veech_group().index()
            9
            sage: o.sum_of_lyapunov_exponents()
            4/3

            sage: o = origamis.ProjectiveLine(5); o
            Projective line origami on GF(5)
             r = [1 1]    u = [0 1]
                 [0 1]        [1 0]
            sage: o.stratum()
            H_3(2^2)
            sage: o.veech_group().index()
            9
            sage: o.sum_of_lyapunov_exponents()
            5/3

            sage: o = origamis.ProjectiveLine(7); o
            Projective line origami on GF(7)
             r = [1 1]    u = [0 1]
                 [0 1]        [1 0]
            sage: o.stratum()
            H_3(2^2)
            sage: o.veech_group().index()
            45
            sage: o.sum_of_lyapunov_exponents()
            5/3

        Any invertible matrix mod p can be choosed to generate the origami::

            sage: r = matrix([[1,3],[0,1]])
            sage: u = matrix([[1,0],[3,1]])
            sage: o = origamis.ProjectiveLine(5,r,u); o
            Projective line origami on GF(5)
             r = [1 3]    u = [1 0]
                 [0 1]        [3 1]
            sage: o.veech_group().index()
            10
            sage: o.sum_of_lyapunov_exponents()
            9/5
            sage: o.stratum_component()
            H_3(4)^hyp
        """
        from sage.arith.all import is_prime
        from sage.rings.finite_rings.finite_field_constructor import GF
        from sage.groups.matrix_gps.linear import GL
        from sage.modules.free_module import VectorSpace

        p = ZZ(p)
        if not p.is_prime():
            raise ValueError("p (={}) must be a prime number".format(p))

        G = GL(2,GF(p))
        V = VectorSpace(GF(p),2)

        if r is None:
            mr = G([[1,1],[0,1]])
        else:
            mr = G(r)
        if u is None:
            mu = G([[0,1],[1,0]])
        else:
            mu = G(u)

        sr = str(mr).split('\n')
        su = str(mu).split('\n')

        mr = mr
        mu = mu

        if r is None and u is None:
            positions = [(i,0) for i in xrange(p+1)]
        else:
            positions = None

        r = []
        u = []
        for i in xrange(p):
            v = V((i,1)) * mr
            if v[1]:
                r.append(int(v[0]/v[1]))
            else:
                r.append(p)

            v = V((i,1)) * mu
            if v[1]:
                u.append(int(v[0]/v[1]))
            else:
                u.append(p)

        v = V((1,0)) * mr
        if v[1]:
            r.append(int(v[0]/v[1]))
        else:
            r.append(p)

        v = V((1,0)) * mu
        if v[1]:
            u.append(int(v[0]/v[1]))
        else:
            u.append(p)

        o = Origami(r,u,
            as_tuple=True,
            positions=positions,
            name="Projective line origami on GF(%d)\n r = %s    u = %s\n     %s        %s"%(p,sr[0],su[0],sr[1],su[1]))
        return o
Exemplo n.º 7
0
class AffineGroup(UniqueRepresentation, Group):
    r"""
    An affine group.

    The affine group `\mathrm{Aff}(A)` (or general affine group) of an affine
    space `A` is the group of all invertible affine transformations from the
    space into itself.

    If we let `A_V` be the affine space of a vector space `V`
    (essentially, forgetting what is the origin) then the affine group
    `\mathrm{Aff}(A_V)` is the group generated by the general linear group
    `GL(V)` together with the translations. Recall that the group of
    translations acting on `A_V` is just `V` itself. The general linear and
    translation subgroups do not quite commute, and in fact generate the
    semidirect product

    .. MATH::

        \mathrm{Aff}(A_V) = GL(V) \ltimes V.

    As such, the group elements can be represented by pairs `(A, b)` of a
    matrix and a vector. This pair then represents the transformation

    .. MATH::

        x \mapsto A x + b.

    We can also represent affine transformations as linear transformations by
    considering `\dim(V) + 1` dimensional space. We take the affine
    transformation `(A, b)` to

    .. MATH::

        \begin{pmatrix}
        A & b \\
        0 & 1
        \end{pmatrix}

    and lifting `x = (x_1, \ldots, x_n)` to `(x_1, \ldots, x_n, 1)`. Here
    the `(n + 1)`-th component is always 1, so the linear representations
    acts on the affine hyperplane `x_{n+1} = 1` as affine transformations
    which can be seen directly from the matrix multiplication.

    INPUT:

    Something that defines an affine space. For example

    - An affine space itself:

      * ``A`` -- affine space

    - A vector space:

      * ``V`` -- a vector space

    - Degree and base ring:

      * ``degree`` -- An integer. The degree of the affine group, that
        is, the dimension of the affine space the group is acting on.

      * ``ring`` -- A ring or an integer. The base ring of the affine
        space. If an integer is given, it must be a prime power and
        the corresponding finite field is constructed.

      * ``var`` -- (default: ``'a'``) Keyword argument to specify the finite
        field generator name in the case where ``ring`` is a prime power.

    EXAMPLES::

        sage: F = AffineGroup(3, QQ); F
        Affine Group of degree 3 over Rational Field
        sage: F(matrix(QQ,[[1,2,3],[4,5,6],[7,8,0]]), vector(QQ,[10,11,12]))
              [1 2 3]     [10]
        x |-> [4 5 6] x + [11]
              [7 8 0]     [12]
        sage: F([[1,2,3],[4,5,6],[7,8,0]], [10,11,12])
              [1 2 3]     [10]
        x |-> [4 5 6] x + [11]
              [7 8 0]     [12]
        sage: F([1,2,3,4,5,6,7,8,0], [10,11,12])
              [1 2 3]     [10]
        x |-> [4 5 6] x + [11]
              [7 8 0]     [12]

    Instead of specifying the complete matrix/vector information, you can
    also create special group elements::

        sage: F.linear([1,2,3,4,5,6,7,8,0])
              [1 2 3]     [0]
        x |-> [4 5 6] x + [0]
              [7 8 0]     [0]
        sage: F.translation([1,2,3])
              [1 0 0]     [1]
        x |-> [0 1 0] x + [2]
              [0 0 1]     [3]

    Some additional ways to create affine groups::

        sage: A = AffineSpace(2, GF(4,'a'));  A
        Affine Space of dimension 2 over Finite Field in a of size 2^2
        sage: G = AffineGroup(A); G
        Affine Group of degree 2 over Finite Field in a of size 2^2
        sage: G is AffineGroup(2,4) # shorthand
        True

        sage: V = ZZ^3;  V
        Ambient free module of rank 3 over the principal ideal domain Integer Ring
        sage: AffineGroup(V)
        Affine Group of degree 3 over Integer Ring

    REFERENCES:

    -  :wikipedia:`Affine_group`
    """
    @staticmethod
    def __classcall__(cls, *args, **kwds):
        """
        Normalize input to ensure a unique representation.

        EXAMPLES::

            sage: A = AffineSpace(2, GF(4,'a'))
            sage: AffineGroup(A) is AffineGroup(2,4)
            True
            sage: AffineGroup(A) is AffineGroup(2, GF(4,'a'))
            True
            sage: A = AffineGroup(2, QQ)
            sage: V = QQ^2
            sage: A is AffineGroup(V)
            True
        """
        if len(args) == 1:
            V = args[0]
            if isinstance(V, AffineGroup):
                return V
            try:
                degree = V.dimension_relative()
            except AttributeError:
                degree = V.dimension()
            ring = V.base_ring()
        if len(args) == 2:
            degree, ring = args
            from sage.rings.integer import is_Integer
            if is_Integer(ring):
                from sage.rings.finite_rings.finite_field_constructor import FiniteField
                var = kwds.get('var', 'a')
                ring = FiniteField(ring, var)
        return super(AffineGroup, cls).__classcall__(cls, degree, ring)

    def __init__(self, degree, ring):
        """
        Initialize ``self``.

        INPUT:

        - ``degree`` -- integer. The degree of the affine group, that
          is, the dimension of the affine space the group is acting on
          naturally.

        - ``ring`` -- a ring. The base ring of the affine space.

        EXAMPLES::

            sage: Aff6 = AffineGroup(6, QQ)
            sage: Aff6 == Aff6
            True
            sage: Aff6 != Aff6
            False

        TESTS::

            sage: G = AffineGroup(2, GF(5)); G
            Affine Group of degree 2 over Finite Field of size 5
            sage: TestSuite(G).run()
            sage: G.category()
            Category of finite groups

            sage: Aff6 = AffineGroup(6, QQ)
            sage: Aff6.category()
            Category of infinite groups
        """
        self._degree = degree
        cat = Groups()
        if degree == 0 or ring in Rings().Finite():
            cat = cat.Finite()
        elif ring in Rings().Infinite():
            cat = cat.Infinite()
        self._GL = GL(degree, ring)
        Group.__init__(self, base=ring, category=cat)

    Element = AffineGroupElement

    def _element_constructor_check(self, A, b):
        """
        Verify that ``A``, ``b`` define an affine group element and raises a
        ``TypeError`` if the input does not define a valid group element.

        This is called from the group element constructor and can be
        overridden for subgroups of the affine group. It is guaranteed
        that ``A``, ``b`` are in the correct matrix/vector space.

        INPUT:

        - ``A`` -- an element of :meth:`matrix_space`

        - ``b`` -- an element of :meth:`vector_space`

        TESTS::

            sage: Aff3 = AffineGroup(3, QQ)
            sage: A = Aff3.matrix_space()([1,2,3,4,5,6,7,8,0])
            sage: det(A)
            27
            sage: b = Aff3.vector_space().an_element()
            sage: Aff3._element_constructor_check(A, b)

            sage: A = Aff3.matrix_space()([1,2,3,4,5,6,7,8,9])
            sage: det(A)
            0
            sage: Aff3._element_constructor_check(A, b)
            Traceback (most recent call last):
            ...
            TypeError: A must be invertible
        """
        if not A.is_invertible():
            raise TypeError('A must be invertible')

    def _latex_(self):
        r"""
        Return a LaTeX representation of ``self``.

        EXAMPLES::

            sage: G = AffineGroup(6, GF(5))
            sage: latex(G)
            \mathrm{Aff}_{6}(\Bold{F}_{5})
        """
        return "\\mathrm{Aff}_{%s}(%s)" % (self.degree(),
                                           self.base_ring()._latex_())

    def _repr_(self):
        """
        Return a string representation of ``self``.

        EXAMPLES::

            sage: AffineGroup(6, GF(5))
            Affine Group of degree 6 over Finite Field of size 5
        """
        return "Affine Group of degree %s over %s" % (self.degree(),
                                                      self.base_ring())

    def cardinality(self):
        """
        Return the cardinality of ``self``.

        EXAMPLES::

            sage: AffineGroup(6, GF(5)).cardinality()
            172882428468750000000000000000
            sage: AffineGroup(6, ZZ).cardinality()
            +Infinity
        """
        card_GL = self._GL.cardinality()
        return card_GL * self.base_ring().cardinality()**self.degree()

    def degree(self):
        """
        Return the dimension of the affine space.

        OUTPUT:

        An integer.

        EXAMPLES::

            sage: G = AffineGroup(6, GF(5))
            sage: g = G.an_element()
            sage: G.degree()
            6
            sage: G.degree() == g.A().nrows() == g.A().ncols() == g.b().degree()
            True
        """
        return self._degree

    @cached_method
    def matrix_space(self):
        """
        Return the space of matrices representing the general linear
        transformations.

        OUTPUT:

        The parent of the matrices `A` defining the affine group
        element `Ax+b`.

        EXAMPLES::

            sage: G = AffineGroup(3, GF(5))
            sage: G.matrix_space()
            Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 5
        """
        d = self.degree()
        return MatrixSpace(self.base_ring(), d, d)

    @cached_method
    def vector_space(self):
        """
        Return the vector space of the underlying affine space.

        EXAMPLES::

            sage: G = AffineGroup(3, GF(5))
            sage: G.vector_space()
            Vector space of dimension 3 over Finite Field of size 5
        """
        return FreeModule(self.base_ring(), self.degree())

    @cached_method
    def linear_space(self):
        r"""
        Return the space of the affine transformations represented as linear
        transformations.

        We can represent affine transformations `Ax + b` as linear
        transformations by

        .. MATH::

            \begin{pmatrix}
            A & b \\
            0 & 1
            \end{pmatrix}

        and lifting `x = (x_1, \ldots, x_n)` to `(x_1, \ldots, x_n, 1)`.

        .. SEEALSO::

            - :meth:`sage.groups.affine_gps.group_element.AffineGroupElement.matrix()`

        EXAMPLES::

            sage: G = AffineGroup(3, GF(5))
            sage: G.linear_space()
            Full MatrixSpace of 4 by 4 dense matrices over Finite Field of size 5
        """
        dp = self.degree() + 1
        return MatrixSpace(self.base_ring(), dp, dp)

    def linear(self, A):
        r"""
        Construct the general linear transformation by ``A``.

        INPUT:

        - ``A`` -- anything that determines a matrix

        OUTPUT:

        The affine group element `x \mapsto A x`.

        EXAMPLES::

            sage: G = AffineGroup(3, GF(5))
            sage: G.linear([1,2,3,4,5,6,7,8,0])
                  [1 2 3]     [0]
            x |-> [4 0 1] x + [0]
                  [2 3 0]     [0]
        """
        A = self.matrix_space()(A)
        return self.element_class(self,
                                  A,
                                  self.vector_space().zero(),
                                  check=True,
                                  convert=False)

    def translation(self, b):
        r"""
        Construct the translation by ``b``.

        INPUT:

        - ``b`` -- anything that determines a vector

        OUTPUT:

        The affine group element `x \mapsto x + b`.

        EXAMPLES::

            sage: G = AffineGroup(3, GF(5))
            sage: G.translation([1,4,8])
                  [1 0 0]     [1]
            x |-> [0 1 0] x + [4]
                  [0 0 1]     [3]
        """
        b = self.vector_space()(b)
        return self.element_class(self,
                                  self.matrix_space().one(),
                                  b,
                                  check=False,
                                  convert=False)

    def reflection(self, v):
        """
        Construct the Householder reflection.

        A Householder reflection (transformation) is the affine transformation
        corresponding to an elementary reflection at the hyperplane
        perpendicular to `v`.

        INPUT:

        - ``v`` -- a vector, or something that determines a vector.

        OUTPUT:

        The affine group element that is just the Householder
        transformation (a.k.a. Householder reflection, elementary
        reflection) at the hyperplane perpendicular to `v`.

        EXAMPLES::

            sage: G = AffineGroup(3, QQ)
            sage: G.reflection([1,0,0])
                  [-1  0  0]     [0]
            x |-> [ 0  1  0] x + [0]
                  [ 0  0  1]     [0]
            sage: G.reflection([3,4,-5])
                  [ 16/25 -12/25    3/5]     [0]
            x |-> [-12/25   9/25    4/5] x + [0]
                  [   3/5    4/5      0]     [0]
        """
        v = self.vector_space()(v)
        try:
            two_norm2inv = self.base_ring()(2) / sum([vi**2 for vi in v])
        except ZeroDivisionError:
            raise ValueError('v has norm zero')
        A = self.matrix_space().one() - v.column() * (v.row() * two_norm2inv)
        return self.element_class(self,
                                  A,
                                  self.vector_space().zero(),
                                  check=True,
                                  convert=False)

    def random_element(self):
        """
        Return a random element of this group.

        EXAMPLES::

            sage: G = AffineGroup(4, GF(3))
            sage: G.random_element()  # random
                  [2 0 1 2]     [1]
                  [2 1 1 2]     [2]
            x |-> [1 0 2 2] x + [2]
                  [1 1 1 1]     [2]
            sage: G.random_element() in G
            True
        """
        A = self._GL.random_element()
        b = self.vector_space().random_element()
        return self.element_class(self, A, b, check=False, convert=False)

    @cached_method
    def _an_element_(self):
        """
        Return an element.

        TESTS::

            sage: G = AffineGroup(4,5)
            sage: G.an_element() in G
            True
        """
        A = self._GL.an_element()
        b = self.vector_space().an_element()
        return self.element_class(self, A, b, check=False, convert=False)

    def some_elements(self):
        """
        Return some elements.

        EXAMPLES::

            sage: G = AffineGroup(4,5)
            sage: G.some_elements()
            [      [2 0 0 0]     [1]
                   [0 1 0 0]     [0]
             x |-> [0 0 1 0] x + [0]
                   [0 0 0 1]     [0],
                   [2 0 0 0]     [0]
                   [0 1 0 0]     [0]
             x |-> [0 0 1 0] x + [0]
                   [0 0 0 1]     [0],
                   [2 0 0 0]     [...]
                   [0 1 0 0]     [...]
             x |-> [0 0 1 0] x + [...]
                   [0 0 0 1]     [...]]
            sage: all(v.parent() is G for v in G.some_elements())
            True

            sage: G = AffineGroup(2,QQ)
            sage: G.some_elements()
            [      [1 0]     [1]
             x |-> [0 1] x + [0],
             ...]
        """
        mats = self._GL.some_elements()
        vecs = self.vector_space().some_elements()
        return [
            self.element_class(self, A, b, check=False, convert=False)
            for A in mats for b in vecs
        ]