Exemplo n.º 1
0
def _minimize_level(G):
    r"""
    Utility function. Given a matrix group `G` contained in `SL(2, \ZZ / N\ZZ)`
    for some `N`, test whether or not `G` is the preimage of a subgroup of
    smaller level, and if so, return that subgroup.

    The trivial group is handled specially: instead of returning a group, it
    returns an integer `N`, representing the trivial subgroup of `SL(2, \ZZ /
    N\ZZ)`.

    EXAMPLE::

        sage: M = MatrixSpace(Zmod(9), 2, 2)
        sage: G = MatrixGroup([M(x) for x in [[1,1,0,1],[1,3,0,1],[1,0,3,1],[4,0,0,7]]]); G
        Matrix group over Ring of integers modulo 9 with 4 generators:
         [[[1, 1], [0, 1]], [[1, 3], [0, 1]], [[1, 0], [3, 1]], [[4, 0], [0, 7]]]
        sage: sage.modular.arithgroup.congroup_generic._minimize_level(G)
        Matrix group over Ring of integers modulo 3 with 1 generators:
         [[[1, 1], [0, 1]]]

        sage: G = MatrixGroup([M(x) for x in [[1,3,0,1],[1,0,3,1],[4,0,0,7]]]); G
        Matrix group over Ring of integers modulo 9 with 3 generators:
         [[[1, 3], [0, 1]], [[1, 0], [3, 1]], [[4, 0], [0, 7]]]
        sage: sage.modular.arithgroup.congroup_generic._minimize_level(G)
        3
    """
    from congroup_gamma import Gamma_constructor as Gamma
    Glist = list(G)
    N = G.base_ring().characteristic()
    i = Gamma(N).index()

    for p in N.prime_divisors():
        j = Gamma(N // p).index()
        k = len(
            [g for g in Glist if g.matrix().change_ring(Zmod(N // p)) == 1])
        if k == i // j:
            if N // p == 1:
                return ZZ(1)
            H = MatrixGroup(
                [g.matrix().change_ring(Zmod(N // p)) for g in G.gens()])
            return _minimize_level(H)

    # now sanitize the generators (remove duplicates and copies of the identity)
    new_gens = [x.matrix() for x in G.gens() if x.matrix() != 1]
    all([x.set_immutable() for x in new_gens])
    new_gens = list(Set(new_gens))
    if new_gens == []:
        return ZZ(G.base_ring().characteristic())
    return MatrixGroup(new_gens)
Exemplo n.º 2
0
    def image_mod_n(self):
        r"""
        Return the image of this group in `SL(2, \ZZ / N\ZZ)`.

        EXAMPLE::

            sage: Gamma0(3).image_mod_n()
            Matrix group over Ring of integers modulo 3 with 2 generators:
             [[[2, 0], [0, 2]], [[1, 1], [0, 1]]]

        TEST::

            sage: for n in [2..20]:
            ...     for g in Gamma0(n).gamma_h_subgroups():
            ...       G = g.image_mod_n()
            ...       assert G.order() == Gamma(n).index() / g.index()
        """
        N = self.level()
        if N == 1:
            raise NotImplementedError, "Matrix groups over ring of integers modulo 1 not implemented"
        gens = [
            matrix(Zmod(N), 2, 2, [x, 0, 0, Zmod(N)(1) / x])
            for x in self._generators_for_H()
        ]
        gens += [matrix(Zmod(N), 2, [1, 1, 0, 1])]
        return MatrixGroup(gens)
Exemplo n.º 3
0
    def as_matrix_group(self):
        """
        Return this group, but as a general matrix group, i.e., throw away
        the extra structure of general unitary group.

        EXAMPLES::

            sage: G = SU(4,GF(5))
            sage: G.as_matrix_group()
            Matrix group over Finite Field in a of size 5^2 with 2 generators:
            [[[a, 0, 0, 0],
              [0, 2*a + 3, 0, 0],
              [0, 0, 4*a + 1, 0],
              [0, 0, 0, 3*a]],
             [[1, 0, 4*a + 3, 0],
              [1, 0, 0, 0],
              [0, 2*a + 4, 0, 1],
              [0, 3*a + 1, 0, 0]]]

        ::

            sage: G = GO(3,GF(5))
            sage: G.as_matrix_group()
            Matrix group over Finite Field of size 5 with 2 generators:
            [[[2, 0, 0], [0, 3, 0], [0, 0, 1]], [[0, 1, 0], [1, 4, 4], [0, 2, 1]]]
        """
        from sage.groups.matrix_gps.matrix_group import MatrixGroup
        return MatrixGroup([g.matrix() for g in self.gens()])
Exemplo n.º 4
0
def QuaternionMatrixGroupGF3():
    r"""
    The quaternion group as a set of `2\times 2` matrices over `GF(3)`.

    OUTPUT:

    A matrix group consisting of `2\times 2` matrices with
    elements from the finite field of order 3.  The group is
    the quaternion group, the nonabelian group of order 8 that
    is not isomorphic to the group of symmetries of a square
    (the dihedral group `D_4`).

    .. note::
        This group is most easily available via ``groups.matrix.QuaternionGF3()``.

    EXAMPLES:

    The generators are the matrix representations of the
    elements commonly called `I` and `J`, while `K`
    is the product of `I` and `J`. ::

        sage: from sage.groups.misc_gps.misc_groups import QuaternionMatrixGroupGF3
        sage: Q = QuaternionMatrixGroupGF3()
        sage: Q.order()
        8
        sage: aye = Q.gens()[0]; aye
        [1 1]
        [1 2]
        sage: jay = Q.gens()[1]; jay
        [2 1]
        [1 1]
        sage: kay = aye*jay; kay
        [0 2]
        [1 0]

    TESTS::

        sage: groups.matrix.QuaternionGF3()
        Matrix group over Finite Field of size 3 with 2 generators:
            [[[1, 1], [1, 2]], [[2, 1], [1, 1]]]

        sage: Q = QuaternionMatrixGroupGF3()
        sage: QP = Q.as_permutation_group()
        sage: QP.is_isomorphic(QuaternionGroup())
        True
        sage: H = DihedralGroup(4)
        sage: H.order()
        8
        sage: QP.is_abelian(), H.is_abelian()
        (False, False)
        sage: QP.is_isomorphic(H)
        False
    """
    from sage.rings.finite_rings.constructor import FiniteField
    from sage.matrix.matrix_space import MatrixSpace
    from sage.groups.matrix_gps.matrix_group import MatrixGroup
    MS = MatrixSpace(FiniteField(3), 2)
    aye = MS([1,1,1,2])
    jay = MS([2,1,1,1])
    return MatrixGroup([aye, jay])
Exemplo n.º 5
0
    def image_mod_n(self):
        r"""
        Return the image of this group modulo `N`, as a subgroup of `SL(2, \ZZ
        / N\ZZ)`. This is just the trivial subgroup.

        EXAMPLE::

            sage: Gamma(3).image_mod_n()
            Matrix group over Ring of integers modulo 3 with 1 generators: 
             [[[1, 0], [0, 1]]]
        """
        return MatrixGroup([matrix(Zmod(self.level()), 2, 2, 1)])
Exemplo n.º 6
0
    def center(self):
        """
        Return the center of this linear group as a matrix group.

        EXAMPLES::

            sage: G = SU(3,GF(2))
            sage: G.center()
            Matrix group over Finite Field in a of size 2^2 with 1 generators:
             [[[a, 0, 0], [0, a, 0], [0, 0, a]]]
            sage: GL(2,GF(3)).center()
            Matrix group over Finite Field of size 3 with 1 generators:
             [[[2, 0], [0, 2]]]
            sage: GL(3,GF(3)).center()
            Matrix group over Finite Field of size 3 with 1 generators:
             [[[2, 0, 0], [0, 2, 0], [0, 0, 2]]]
            sage: GU(3,GF(2)).center()
            Matrix group over Finite Field in a of size 2^2 with 1 generators:
             [[[a + 1, 0, 0], [0, a + 1, 0], [0, 0, a + 1]]]
            sage: A=Matrix(FiniteField(5), [[2,0,0], [0,3,0], [0,0,1]])
            sage: B=Matrix(FiniteField(5), [[1,0,0], [0,1,0], [0,1,1]])
            sage: MatrixGroup([A,B]).center()
            Matrix group over Finite Field of size 5 with 1 generators:
             [[[1, 0, 0], [0, 1, 0], [0, 0, 1]]]
        """
        try:
            return self.__center
        except AttributeError:
            pass
        G = list(self._gap_().Center().GeneratorsOfGroup())
        from sage.groups.matrix_gps.matrix_group import MatrixGroup
        if len(G) == 0:
            self.__center = MatrixGroup([self.one()])
        else:
            F = self.field_of_definition()
            self.__center = MatrixGroup([g._matrix_(F) for g in G])
        return self.__center
Exemplo n.º 7
0
    def to_even_subgroup(self):
        r"""
        Return the smallest even subgroup of `SL(2, \ZZ)` containing self.

        EXAMPLE::

            sage: G = Gamma(3)
            sage: G.to_even_subgroup()
            Congruence subgroup of SL(2,Z) of level 3, preimage of:
             Matrix group over Ring of integers modulo 3 with 1 generators:
             [[[2, 0], [0, 2]]]
        """
        if self.is_even():
            return self
        else:
            G = self.image_mod_n()
            H = MatrixGroup(G.gens() + [G.matrix_space()(-1)])
            return CongruenceSubgroup_constructor(H)
Exemplo n.º 8
0
def CongruenceSubgroup_constructor(*args):
    r"""
    Attempt to create a congruence subgroup from the given data.

    The allowed inputs are as follows:

    - A :class:`~sage.groups.matrix_gps.matrix_group.MatrixGroup` object. This
      must be a group of matrices over `\ZZ / N\ZZ` for some `N`, with
      determinant 1, in which case the function will return the group of
      matrices in `SL(2, \ZZ)` whose reduction mod `N` is in the given group.

    - A list of matrices over `\ZZ / N\ZZ` for some `N`. The function will then
      compute the subgroup of `SL(2, \ZZ)` generated by these matrices, and
      proceed as above.

    - An integer `N` and a list of matrices (over any ring coercible to `\ZZ /
      N\ZZ`, e.g. over `\ZZ`). The matrices will then be coerced to `\ZZ /
      N\ZZ`.

    The function checks that the input G is valid. It then tests to see if
    `G` is the preimage mod `N` of some group of matrices modulo a proper
    divisor `M` of `N`, in which case it replaces `G` with this group before
    continuing.

    EXAMPLES::

        sage: from sage.modular.arithgroup.congroup_generic import CongruenceSubgroup_constructor as CS
        sage: CS(2, [[1,1,0,1]])
        Congruence subgroup of SL(2,Z) of level 2, preimage of:
         Matrix group over Ring of integers modulo 2 with 1 generators:
         [[[1, 1], [0, 1]]]
        sage: CS([matrix(Zmod(2), 2, [1,1,0,1])])
        Congruence subgroup of SL(2,Z) of level 2, preimage of:
         Matrix group over Ring of integers modulo 2 with 1 generators:
         [[[1, 1], [0, 1]]]
        sage: CS(MatrixGroup([matrix(Zmod(2), 2, [1,1,0,1])]))
        Congruence subgroup of SL(2,Z) of level 2, preimage of:
         Matrix group over Ring of integers modulo 2 with 1 generators:
         [[[1, 1], [0, 1]]]
        sage: CS(SL(2, 2))
        Modular Group SL(2,Z)

    Some invalid inputs::

        sage: CS(SU(2, 7))
        Traceback (most recent call last):
        ...
        TypeError: Ring of definition must be Z / NZ for some N
    """
    if isinstance(args[0], MatrixGroup_generic):
        G = args[0]

    elif type(args[0]) == type([]):
        G = MatrixGroup(args[0])

    elif args[0] in ZZ:
        M = MatrixSpace(Zmod(args[0]), 2)
        G = MatrixGroup([M(x) for x in args[1]])

    R = G.matrix_space().base_ring()
    if not hasattr(R, "cover_ring") or R.cover_ring() != ZZ:
        raise TypeError, "Ring of definition must be Z / NZ for some N"

    if not all([x.matrix().det() == 1 for x in G.gens()]):
        raise ValueError, "Group must be contained in SL(2, Z / N)"
    GG = _minimize_level(G)
    if GG in ZZ:
        from all import Gamma
        return Gamma(GG)
    else:
        return CongruenceSubgroupFromGroup(GG)
Exemplo n.º 9
0
def CongruenceSubgroup_constructor(*args):
    r"""
    Attempt to create a congruence subgroup from the given data.

    The allowed inputs are as follows:

    - A :class:`~sage.groups.matrix_gps.matrix_group.MatrixGroup` object. This
      must be a group of matrices over `\ZZ / N\ZZ` for some `N`, with
      determinant 1, in which case the function will return the group of
      matrices in `SL(2, \ZZ)` whose reduction mod `N` is in the given group.

    - A list of matrices over `\ZZ / N\ZZ` for some `N`. The function will then
      compute the subgroup of `SL(2, \ZZ)` generated by these matrices, and
      proceed as above.

    - An integer `N` and a list of matrices (over any ring coercible to `\ZZ /
      N\ZZ`, e.g. over `\ZZ`). The matrices will then be coerced to `\ZZ /
      N\ZZ`.

    The function checks that the input G is valid. It then tests to see if
    `G` is the preimage mod `N` of some group of matrices modulo a proper
    divisor `M` of `N`, in which case it replaces `G` with this group before
    continuing.

    EXAMPLES::

        sage: from sage.modular.arithgroup.congroup_generic import CongruenceSubgroup_constructor as CS
        sage: CS(2, [[1,1,0,1]])
        Congruence subgroup of SL(2,Z) of level 2, preimage of:
         Matrix group over Ring of integers modulo 2 with 1 generators:
         [[[1, 1], [0, 1]]]
        sage: CS([matrix(Zmod(2), 2, [1,1,0,1])])
        Congruence subgroup of SL(2,Z) of level 2, preimage of:
         Matrix group over Ring of integers modulo 2 with 1 generators:
         [[[1, 1], [0, 1]]]
        sage: CS(MatrixGroup([matrix(Zmod(2), 2, [1,1,0,1])]))
        Congruence subgroup of SL(2,Z) of level 2, preimage of:
         Matrix group over Ring of integers modulo 2 with 1 generators:
         [[[1, 1], [0, 1]]]
        sage: CS(SL(2, 2))
        Modular Group SL(2,Z)

    Some invalid inputs::

        sage: CS(SU(2, 7))
        Traceback (most recent call last):
        ...
        TypeError: Ring of definition must be Z / NZ for some N
    """
    if isinstance(args[0], MatrixGroup_generic):
        G = args[0]

    elif type(args[0]) == type([]):
        G = MatrixGroup(args[0])

    elif args[0] in ZZ:
        M = MatrixSpace(Zmod(args[0]), 2)
        G = MatrixGroup([M(x) for x in args[1]])

    R = G.matrix_space().base_ring()
    if not hasattr(R, "cover_ring") or R.cover_ring() != ZZ:
        raise TypeError, "Ring of definition must be Z / NZ for some N"

    if not all([x.matrix().det() == 1 for x in G.gens()]):
        raise ValueError, "Group must be contained in SL(2, Z / N)"
    GG = _minimize_level(G)
    if GG in ZZ:
        from all import Gamma
        return Gamma(GG)
    else:
        return CongruenceSubgroupFromGroup(GG)