Esempio n. 1
0
    def __call__(self, x):
        """
        EXAMPLES::
        
            sage: W = WeylGroup(['A',2])
            sage: W(1)
            [1 0 0]
            [0 1 0]
            [0 0 1]
        
        ::
        
            sage: W(2)
            Traceback (most recent call last):
            ...
            TypeError: no way to coerce element into self.

            sage: W2 = WeylGroup(['A',3])
            sage: W(1) in W2  # indirect doctest
            False

        """
        if isinstance(x, self.element_class) and x.parent() is self:
            return x
        from sage.matrix.matrix import is_Matrix
        if not (x in ZZ or is_Matrix(x)): # this should be handled by self.matrix_space()(x)
            raise TypeError, "no way to coerce element into self"
        M = self.matrix_space()(x)
        # This is really bad, especially for infinite groups!
        # TODO: compute the image of rho, compose by s_i until back in
        # the fundamental chamber. Return True iff the matrix is the identity
        g = self._element_constructor_(M)
        if not gap(g) in gap(self):
            raise TypeError, "no way to coerce element into self."
        return g
Esempio n. 2
0
    def __call__(self, x):
        """
        EXAMPLES::
        
            sage: W = WeylGroup(['A',2])
            sage: W(1)
            [1 0 0]
            [0 1 0]
            [0 0 1]
        
        ::
        
            sage: W(2)
            Traceback (most recent call last):
            ...
            TypeError: no way to coerce element into self.

            sage: W2 = WeylGroup(['A',3])
            sage: W(1) in W2  # indirect doctest
            False

        """
        if isinstance(x, self.element_class) and x.parent() is self:
            return x
        from sage.matrix.matrix import is_Matrix
        if not (x in ZZ or is_Matrix(x)): # this should be handled by self.matrix_space()(x)
            raise TypeError, "no way to coerce element into self"
        M = self.matrix_space()(x)
        # This is really bad, especially for infinite groups!
        # TODO: compute the image of rho, compose by s_i until back in
        # the fundamental chamber. Return True iff the matrix is the identity
        g = self._element_constructor_(M)
        if not gap(g) in gap(self):
            raise TypeError, "no way to coerce element into self."
        return g
Esempio n. 3
0
 def __init__(self, homset, imgsH, check=True):
     MatrixGroupMorphism.__init__(self, homset)   # sets the parent
     G = homset.domain()
     H = homset.codomain()
     gaplist_gens = [gap(x) for x in G.gens()]
     gaplist_imgs = [gap(x) for x in imgsH]
     genss = '[%s]'%(','.join(str(v) for v in gaplist_gens))
     imgss = '[%s]'%(','.join(str(v) for v in gaplist_imgs))
     args = '%s, %s, %s, %s'%(G._gap_init_(), H._gap_init_(), genss, imgss)
     self._gap_str = 'GroupHomomorphismByImages(%s)'%args
     phi0 = gap(self)
     if gap.eval("IsGroupHomomorphism(%s)"%phi0.name())!="true":
         raise ValueError,"The map "+str(gensG)+"-->"+str(imgsH)+" isn't a homomorphism."
Esempio n. 4
0
 def __init__(self, homset, imgsH, check=True):
     MatrixGroupMorphism.__init__(self, homset)  # sets the parent
     G = homset.domain()
     H = homset.codomain()
     gaplist_gens = [gap(x) for x in G.gens()]
     gaplist_imgs = [gap(x) for x in imgsH]
     genss = '[%s]' % (','.join(str(v) for v in gaplist_gens))
     imgss = '[%s]' % (','.join(str(v) for v in gaplist_imgs))
     args = '%s, %s, %s, %s' % (G._gap_init_(), H._gap_init_(), genss,
                                imgss)
     self._gap_str = 'GroupHomomorphismByImages(%s)' % args
     phi0 = gap(self)
     if gap.eval("IsGroupHomomorphism(%s)" % phi0.name()) != "true":
         raise ValueError, "The map " + str(gensG) + "-->" + str(
             imgsH) + " isn't a homomorphism."
Esempio n. 5
0
    def pushforward(self, J, *args, **kwds):
        """
        The image of an element or a subgroup.

        INPUT:

        ``J`` -- a subgroup or an element of the domain of ``self``.

        OUTPUT:

        The image of ``J`` under ``self``

        NOTE:

        ``pushforward`` is the method that is used when a map is called on
        anything that is not an element of its domain. For historical reasons,
        we keep the alias ``image()`` for this method.

        EXAMPLES::

            sage: F = GF(7); MS = MatrixSpace(F,2,2)
            sage: F.multiplicative_generator()
            3
            sage: G = MatrixGroup([MS([3,0,0,1])])
            sage: a = G.gens()[0]^2
            sage: phi = G.hom([a])
            sage: phi.image(G.gens()[0]) # indirect doctest
            [2 0]
            [0 1]
            sage: H = MatrixGroup([MS(a.list())])
            sage: H
            Matrix group over Finite Field of size 7 with 1 generators:
             [[[2, 0], [0, 1]]]

        The following tests against trac ticket #10659::

            sage: phi(H)   # indirect doctestest
            Matrix group over Finite Field of size 7 with 1 generators:
             [[[4, 0], [0, 1]]]
        """
        phi = gap(self)
        F = self.codomain().base_ring()
        from sage.all import MatrixGroup
        gapJ = gap(J)
        if gap.eval("IsGroup(%s)" % gapJ.name()) == "true":
            return MatrixGroup(
                [x._matrix_(F) for x in phi.Image(gapJ).GeneratorsOfGroup()])
        return phi.Image(gapJ)._matrix_(F)
Esempio n. 6
0
    def invariant_quadratic_form(self):
        r"""
        Return the quadratic form `q(v) = v Q v^t` on the space on
        which this group `G` that satisfies the equation
        `q(v) = q(v M)` for all `v \in V` and
        `M \in G`.
        
        .. note::

           Uses GAP's command InvariantQuadraticForm.
        
        OUTPUT:
        
        
        -  ``Q`` - matrix that defines the invariant quadratic
           form.
        
        
        EXAMPLES::
        
            sage: G = SO( 4, GF(7), 1)
            sage: G.invariant_quadratic_form()
            [0 1 0 0]
            [0 0 0 0]
            [0 0 3 0]
            [0 0 0 1]
        """
        F = self.base_ring()
        I = gap(self).InvariantQuadraticForm()
        Q = I.attribute("matrix")
        return Q._matrix_(F)
Esempio n. 7
0
    def invariant_quadratic_form(self):
        """
        This wraps GAP's command "InvariantQuadraticForm". From the GAP
        documentation:

        INPUT:

        -  ``self`` - a matrix group G

        OUTPUT:

        -  ``Q`` - the matrix satisfying the property: The
           quadratic form q on the natural vector space V on which G acts is
           given by `q(v) = v Q v^t`, and the invariance under G is
           given by the equation `q(v) = q(v M)` for all
           `v \in V` and `M \in G`.

        EXAMPLES::

            sage: G = GO( 4, GF(7), 1)
            sage: G.invariant_quadratic_form()
            [0 1 0 0]
            [0 0 0 0]
            [0 0 3 0]
            [0 0 0 1]
        """
        F = self.base_ring()
        G = self._gap_init_()
        cmd = "r := InvariantQuadraticForm("+G+")"
        gap.eval(cmd)
        cmd = "r.matrix"
        Q = gap(cmd)
        return Q._matrix_(F)
Esempio n. 8
0
    def __call__(self, g):
        """
        Evaluate the character on the group element `g`.

        Return an error if `g` is not in `G`.

        EXAMPLES::

            sage: G = GL(2,7)
            sage: values = G.gap().CharacterTable().Irr()[2].List().sage()
            sage: chi = ClassFunction(G, values)
            sage: z = G([[3,0],[0,3]]); z
            [3 0]
            [0 3]
            sage: chi(z)
            zeta3
            sage: G = GL(2,3)
            sage: chi = G.irreducible_characters()[3]
            sage: g = G.conjugacy_classes_representatives()[6]
            sage: chi(g)
            zeta8^3 + zeta8

            sage: G = SymmetricGroup(3)
            sage: h = G((2,3))
            sage: triv = G.trivial_character()
            sage: triv(h)
            1
        """
        return self._base_ring(gap(g)._operation("^", self._gap_classfunction))
Esempio n. 9
0
    def character_table(self):
        """
        Returns the character table as a matrix

        Each row is an irreducible character. For larger tables you
        may preface this with a command such as
        gap.eval("SizeScreen([120,40])") in order to widen the screen.

        EXAMPLES::

            sage: WeylGroup(['A',3]).character_table()
            CT1
            <BLANKLINE>
                 2  3  2  2  .  3
                 3  1  .  .  1  .
            <BLANKLINE>
                   1a 4a 2a 3a 2b
            <BLANKLINE>
            X.1     1 -1 -1  1  1
            X.2     3  1 -1  . -1
            X.3     2  .  . -1  2
            X.4     3 -1  1  . -1
            X.5     1  1  1  1  1
        """
        gens_str = ', '.join(str(g.gap()) for g  in self.gens())
        ctbl = gap('CharacterTable(Group({0}))'.format(gens_str))
        return ctbl.Display()
Esempio n. 10
0
    def cardinality(self):
        """
        Implements :meth:`EnumeratedSets.ParentMethods.cardinality`.

        EXAMPLES::
        
            sage: G = Sp(4,GF(3))
            sage: G.cardinality()
            51840
            sage: G = SL(4,GF(3))
            sage: G.cardinality()
            12130560
            sage: F = GF(5); MS = MatrixSpace(F,2,2)
            sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]
            sage: G = MatrixGroup(gens)
            sage: G.cardinality()
            480
            sage: G = MatrixGroup([matrix(ZZ,2,[1,1,0,1])])
            sage: G.cardinality()
            +Infinity
        """
        g = self._gap_()
        if g.IsFinite().bool():
            return integer.Integer(gap(self).Size())
        return infinity
Esempio n. 11
0
    def random_element(self):
        """
        Return a random element of this group.
        
        EXAMPLES::
        
            sage: G = Sp(4,GF(3))
            sage: G.random_element()  # random
            [2 1 1 1]
            [1 0 2 1]
            [0 1 1 0]
            [1 0 0 1]
            sage: G.random_element() in G
            True

        ::
        
            sage: F = GF(5); MS = MatrixSpace(F,2,2)
            sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]
            sage: G = MatrixGroup(gens)
            sage: G.random_element()  # random
            [1 3]
            [0 3]
            sage: G.random_element() in G
            True
        """
        # Note: even with fixed random seed, the Random() element
        # returned by gap does depend on execution order and
        # architecture. Presumably due to different memory loctions.
        current_randstate().set_seed_gap()
        F = self.field_of_definition()
        return self.element_class(gap(self).Random()._matrix_(F), self, check=False)
Esempio n. 12
0
 def gens(self):
     """
     Return generators for this matrix group.
     
     EXAMPLES::
     
         sage: G = GO(3,GF(5))
         sage: G.gens()
         [
         [2 0 0]
         [0 3 0]
         [0 0 1],
         [0 1 0]
         [1 4 4]
         [0 2 1]
         ]
     """
     try:
         return self.__gens
     except AttributeError:
         pass
     F = self.field_of_definition()
     gap_gens = list(gap(self).GeneratorsOfGroup())
     gens = Sequence([self.element_class(g._matrix_(F), self, check=False) for g in gap_gens],
                     cr=True, universe=self, check=False)
     self.__gens = gens
     return gens
Esempio n. 13
0
    def random_element(self):
        """
        Return a random element of this group.

        EXAMPLES::

            sage: G = Sp(4,GF(3))
            sage: G.random_element()  # random
            [2 1 1 1]
            [1 0 2 1]
            [0 1 1 0]
            [1 0 0 1]
            sage: G.random_element() in G
            True

        ::

            sage: F = GF(5); MS = MatrixSpace(F,2,2)
            sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]
            sage: G = MatrixGroup(gens)
            sage: G.random_element()  # random
            [1 3]
            [0 3]
            sage: G.random_element() in G
            True
        """
        # Note: even with fixed random seed, the Random() element
        # returned by gap does depend on execution order and
        # architecture. Presumably due to different memory loctions.
        current_randstate().set_seed_gap()
        F = self.field_of_definition()
        return self.element_class(gap(self).Random()._matrix_(F),
                                  self,
                                  check=False)
Esempio n. 14
0
    def gens(self):
        """
        Return generators for this matrix group.

        EXAMPLES::

            sage: G = GO(3,GF(5))
            sage: G.gens()
            [
            [2 0 0]
            [0 3 0]
            [0 0 1],
            [0 1 0]
            [1 4 4]
            [0 2 1]
            ]
        """
        try:
            return self.__gens
        except AttributeError:
            pass
        F = self.field_of_definition()
        gap_gens = list(gap(self).GeneratorsOfGroup())
        gens = Sequence([
            self.element_class(g._matrix_(F), self, check=False)
            for g in gap_gens
        ],
                        cr=True,
                        universe=self,
                        check=False)
        self.__gens = gens
        return gens
Esempio n. 15
0
    def character_table(self):
        """
        Returns the character table as a matrix

        Each row is an irreducible character. For larger tables you
        may preface this with a command such as
        gap.eval("SizeScreen([120,40])") in order to widen the screen.

        EXAMPLES::

            sage: WeylGroup(['A',3]).character_table()
            CT1
            <BLANKLINE>
                 2  3  2  2  .  3
                 3  1  .  .  1  .
            <BLANKLINE>
                   1a 4a 2a 3a 2b
            <BLANKLINE>
            X.1     1 -1 -1  1  1
            X.2     3  1 -1  . -1
            X.3     2  .  . -1  2
            X.4     3 -1  1  . -1
            X.5     1  1  1  1  1
        """
        gens_str = ', '.join(str(g.gap()) for g  in self.gens())
        ctbl = gap('CharacterTable(Group({0}))'.format(gens_str))
        return ctbl.Display()
Esempio n. 16
0
    def __call__(self, g):
        """
        Evaluate the character on the group element `g`.

        Return an error if `g` is not in `G`.

        EXAMPLES::

            sage: G = GL(2,7)
            sage: values = G.gap().CharacterTable().Irr()[2].List().sage()
            sage: chi = ClassFunction(G, values)
            sage: z = G([[3,0],[0,3]]); z
            [3 0]
            [0 3]
            sage: chi(z)
            zeta3
            sage: G = GL(2,3)
            sage: chi = G.irreducible_characters()[3]
            sage: g = G.conjugacy_classes_representatives()[6]
            sage: chi(g)
            zeta8^3 + zeta8

            sage: G = SymmetricGroup(3)
            sage: h = G((2,3))
            sage: triv = G.trivial_character()
            sage: triv(h)
            1
        """
        return self._base_ring(gap(g)._operation("^", self._gap_classfunction))
Esempio n. 17
0
    def invariant_quadratic_form(self):
        r"""
        Return the quadratic form `q(v) = v Q v^t` on the space on
        which this group `G` that satisfies the equation
        `q(v) = q(v M)` for all `v \in V` and
        `M \in G`.

        .. note::

           Uses GAP's command InvariantQuadraticForm.

        OUTPUT:

        -  ``Q`` - matrix that defines the invariant quadratic
           form.

        EXAMPLES::

            sage: G = SO( 4, GF(7), 1)
            sage: G.invariant_quadratic_form()
            [0 1 0 0]
            [0 0 0 0]
            [0 0 3 0]
            [0 0 0 1]
        """
        F = self.base_ring()
        I = gap(self).InvariantQuadraticForm()
        Q = I.attribute('matrix')
        return Q._matrix_(F)
Esempio n. 18
0
    def cardinality(self):
        """
        Implements :meth:`EnumeratedSets.ParentMethods.cardinality`.

        EXAMPLES::

            sage: G = Sp(4,GF(3))
            sage: G.cardinality()
            51840
            sage: G = SL(4,GF(3))
            sage: G.cardinality()
            12130560
            sage: F = GF(5); MS = MatrixSpace(F,2,2)
            sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]
            sage: G = MatrixGroup(gens)
            sage: G.cardinality()
            480
            sage: G = MatrixGroup([matrix(ZZ,2,[1,1,0,1])])
            sage: G.cardinality()
            +Infinity
        """
        g = self._gap_()
        if g.IsFinite().bool():
            return integer.Integer(gap(self).Size())
        return infinity
Esempio n. 19
0
    def pushforward(self, J, *args,**kwds):
        """
        The image of an element or a subgroup.

        INPUT:

        ``J`` -- a subgroup or an element of the domain of ``self``.

        OUTPUT:

        The image of ``J`` under ``self``
        
        NOTE:

        ``pushforward`` is the method that is used when a map is called on
        anything that is not an element of its domain. For historical reasons,
        we keep the alias ``image()`` for this method.

        EXAMPLES::
        
            sage: F = GF(7); MS = MatrixSpace(F,2,2)
            sage: F.multiplicative_generator()
            3
            sage: G = MatrixGroup([MS([3,0,0,1])])
            sage: a = G.gens()[0]^2
            sage: phi = G.hom([a])
            sage: phi.image(G.gens()[0]) # indirect doctest
            [2 0]
            [0 1]
            sage: H = MatrixGroup([MS(a.list())])
            sage: H
            Matrix group over Finite Field of size 7 with 1 generators:
             [[[2, 0], [0, 1]]]

        The following tests against trac ticket #10659::

            sage: phi(H)   # indirect doctestest
            Matrix group over Finite Field of size 7 with 1 generators: 
             [[[4, 0], [0, 1]]]
        """
        phi = gap(self)
        F = self.codomain().base_ring()
        from sage.all import MatrixGroup
        gapJ = gap(J)
        if gap.eval("IsGroup(%s)"%gapJ.name()) == "true":
            return MatrixGroup([x._matrix_(F) for x in phi.Image(gapJ).GeneratorsOfGroup()])
        return phi.Image(gapJ)._matrix_(F)
Esempio n. 20
0
    def module_composition_factors(self, algorithm=None):
        r"""
        Returns a list of triples consisting of [base field, dimension,
        irreducibility], for each of the Meataxe composition factors
        modules. The algorithm="verbose" option returns more information, but
        in Meataxe notation.

        EXAMPLES::

            sage: F=GF(3);MS=MatrixSpace(F,4,4)
            sage: M=MS(0)
            sage: M[0,1]=1;M[1,2]=1;M[2,3]=1;M[3,0]=1
            sage: G = MatrixGroup([M])
            sage: G.module_composition_factors()
            [(Finite Field of size 3, 1, True),
             (Finite Field of size 3, 1, True),
             (Finite Field of size 3, 2, True)]
            sage: F = GF(7); MS = MatrixSpace(F,2,2)
            sage: gens = [MS([[0,1],[-1,0]]),MS([[1,1],[2,3]])]
            sage: G = MatrixGroup(gens)
            sage: G.module_composition_factors()
            [(Finite Field of size 7, 2, True)]

        Type "G.module_composition_factors(algorithm='verbose')" to get a
        more verbose version.

        For more on MeatAxe notation, see
        http://www.gap-system.org/Manuals/doc/htm/ref/CHAP067.htm
        """
        from sage.misc.sage_eval import sage_eval
        F = self.base_ring()
        if not (F.is_finite()):
            raise NotImplementedError, "Base ring must be finite."
        q = F.cardinality()
        gens = self.gens()
        n = self.degree()
        MS = MatrixSpace(F, n, n)
        mats = []  # initializing list of mats by which the gens act on self
        W = self.matrix_space().row_space()
        for g in gens:
            p = MS(g.matrix())
            m = p.rows()
            mats.append(m)
        mats_str = str(gap([[list(r) for r in m] for m in mats]))
        gap.eval("M:=GModuleByMats(" + mats_str + ", GF(" + str(q) + "))")
        gap.eval("MCFs := MTX.CompositionFactors( M )")
        N = eval(gap.eval("Length(MCFs)"))
        if algorithm == "verbose":
            print gap.eval('MCFs') + "\n"
        L = []
        for i in range(1, N + 1):
            gap.eval("MCF := MCFs[%s]" % i)
            L.append(
                tuple([
                    sage_eval(gap.eval("MCF.field")),
                    eval(gap.eval("MCF.dimension")),
                    sage_eval(gap.eval("MCF.IsIrreducible"))
                ]))
        return sorted(L)
Esempio n. 21
0
    def module_composition_factors(self, algorithm=None):
        r"""
        Return a list of triples consisting of [base field, dimension,
        irreducibility], for each of the Meataxe composition factors
        modules. The ``algorithm="verbose"`` option returns more information,
        but in Meataxe notation.

        EXAMPLES::

            sage: F=GF(3);MS=MatrixSpace(F,4,4)
            sage: M=MS(0)
            sage: M[0,1]=1;M[1,2]=1;M[2,3]=1;M[3,0]=1
            sage: G = MatrixGroup([M])
            sage: G.module_composition_factors()
            [(Finite Field of size 3, 1, True),
             (Finite Field of size 3, 1, True),
             (Finite Field of size 3, 2, True)]
            sage: F = GF(7); MS = MatrixSpace(F,2,2)
            sage: gens = [MS([[0,1],[-1,0]]),MS([[1,1],[2,3]])]
            sage: G = MatrixGroup(gens)
            sage: G.module_composition_factors()
            [(Finite Field of size 7, 2, True)]

        Type ``G.module_composition_factors(algorithm='verbose')`` to get a
        more verbose version.

        For more on MeatAxe notation, see
        http://www.gap-system.org/Manuals/doc/ref/chap69.html
        """
        from sage.misc.sage_eval import sage_eval
        F = self.base_ring()
        if not(F.is_finite()):
            raise NotImplementedError("Base ring must be finite.")
        q = F.cardinality()
        gens = self.gens()
        n = self.degree()
        MS = MatrixSpace(F,n,n)
        mats = [] # initializing list of mats by which the gens act on self
        W = self.matrix_space().row_space()
        for g in gens:
            p = MS(g.matrix())
            m = p.rows()
            mats.append(m)
        mats_str = str(gap([[list(r) for r in m] for m in mats]))
        gap.eval("M:=GModuleByMats("+mats_str+", GF("+str(q)+"))")
        gap.eval("MCFs := MTX.CompositionFactors( M )")
        N = eval(gap.eval("Length(MCFs)"))
        if algorithm == "verbose":
            print(gap.eval('MCFs') + "\n")
        L = []
        for i in range(1,N+1):
            gap.eval("MCF := MCFs[%s]"%i)
            L.append(tuple([sage_eval(gap.eval("MCF.field")),
                            eval(gap.eval("MCF.dimension")),
                            sage_eval(gap.eval("MCF.IsIrreducible")) ]))
        return sorted(L)
Esempio n. 22
0
    def __call__(self, x):
        """
        EXAMPLES::

            sage: F = GF(5); MS = MatrixSpace(F,2,2)
            sage: G = MatrixGroup([MS(1), MS([1,2,3,4])])
            sage: G.matrix_space()
            Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 5
            sage: G(1)
            [1 0]
            [0 1]
        """
        if isinstance(x, self.element_class) and x.parent() is self:
            return x
        M = self.matrix_space()(x)
        g = self.element_class(M, self)
        if not gap(g) in gap(self):
            raise TypeError, "no way to coerce element to self."
        return g
Esempio n. 23
0
 def __call__(self, x):
     """
     EXAMPLES::
     
         sage: F = GF(5); MS = MatrixSpace(F,2,2)
         sage: G = MatrixGroup([MS(1), MS([1,2,3,4])])
         sage: G.matrix_space()
         Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 5
         sage: G(1)
         [1 0]
         [0 1]
     """
     if isinstance(x, self.element_class) and x.parent() is self:
         return x
     M = self.matrix_space()(x)
     g = self.element_class(M, self)
     if not gap(g) in gap(self):
         raise TypeError, "no way to coerce element to self."
     return g
Esempio n. 24
0
 def __contains__(self, x):
     """
     Return True if `x` is an element of this abelian group.
     
     EXAMPLES::
     
         sage: F = GF(5); MS = MatrixSpace(F,2,2)
         sage: G = MatrixGroup([MS(1), MS([1,2,3,4])])
         sage: G
         Matrix group over Finite Field of size 5 with 2 generators: 
          [[[1, 0], [0, 1]], [[1, 2], [3, 4]]]
         sage: G.cardinality()
         8
         sage: G(1)
         [1 0]
         [0 1]
         sage: G.1 in G
         True
         sage: 1 in G
         True
         sage: [1,2,3,4] in G
         True
         sage: matrix(GF(5),2,[1,2,3,5]) in G
         False
         sage: G(matrix(GF(5),2,[1,2,3,5]))
         Traceback (most recent call last):
         ...
         TypeError: no way to coerce element to self.
     """
     if isinstance(x, self.element_class):
         if x.parent() == self:
             return True
         return gap(x) in gap(self)
     try:
         self(x)
         return True
     except TypeError:
         return False
Esempio n. 25
0
    def __contains__(self, x):
        """
        Return True if `x` is an element of this abelian group.

        EXAMPLES::

            sage: F = GF(5); MS = MatrixSpace(F,2,2)
            sage: G = MatrixGroup([MS(1), MS([1,2,3,4])])
            sage: G
            Matrix group over Finite Field of size 5 with 2 generators:
             [[[1, 0], [0, 1]], [[1, 2], [3, 4]]]
            sage: G.cardinality()
            8
            sage: G(1)
            [1 0]
            [0 1]
            sage: G.1 in G
            True
            sage: 1 in G
            True
            sage: [1,2,3,4] in G
            True
            sage: matrix(GF(5),2,[1,2,3,5]) in G
            False
            sage: G(matrix(GF(5),2,[1,2,3,5]))
            Traceback (most recent call last):
            ...
            TypeError: no way to coerce element to self.
        """
        if isinstance(x, self.element_class):
            if x.parent() == self:
                return True
            return gap(x) in gap(self)
        try:
            self(x)
            return True
        except TypeError:
            return False
Esempio n. 26
0
    def cardinality(self):
        """
        EXAMPLES::

            sage: G = Sp(4,GF(3))
            sage: G.cardinality()
            51840
            sage: G = SL(4,GF(3))
            sage: G.cardinality()
            12130560
            sage: F = GF(5); MS = MatrixSpace(F,2,2)
            sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]
            sage: G = MatrixGroup(gens)
            sage: G.cardinality()
            480
            sage: G = MatrixGroup([matrix(ZZ,2,[1,1,0,1])])
            sage: G.cardinality()
            +Infinity
        """
        return integer.Integer(gap(self).Size())
Esempio n. 27
0
 def cardinality(self):
     """
     EXAMPLES::
     
         sage: G = Sp(4,GF(3))
         sage: G.cardinality()
         51840
         sage: G = SL(4,GF(3))
         sage: G.cardinality()
         12130560
         sage: F = GF(5); MS = MatrixSpace(F,2,2)
         sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[0,1]])]
         sage: G = MatrixGroup(gens)
         sage: G.cardinality()
         480
         sage: G = MatrixGroup([matrix(ZZ,2,[1,1,0,1])])
         sage: G.cardinality()
         +Infinity
     """
     return integer.Integer(gap(self).Size())
Esempio n. 28
0
    def kernel(self):
        """
        Return the kernel of ``self``, i.e., a matrix group.

        EXAMPLES::
        
            sage: F = GF(7); MS = MatrixSpace(F,2,2)
            sage: F.multiplicative_generator()
            3
            sage: G = MatrixGroup([MS([3,0,0,1])])
            sage: a = G.gens()[0]^2
            sage: phi = G.hom([a])
            sage: phi.kernel()
            Matrix group over Finite Field of size 7 with 1 generators: 
             [[[6, 0], [0, 1]]]

        """
        gap_ker = gap(self).Kernel()
        from sage.all import MatrixGroup
        F = self.domain().base_ring()
        return MatrixGroup([x._matrix_(F) for x in gap_ker.GeneratorsOfGroup()])
Esempio n. 29
0
    def kernel(self):
        """
        Return the kernel of ``self``, i.e., a matrix group.

        EXAMPLES::

            sage: F = GF(7); MS = MatrixSpace(F,2,2)
            sage: F.multiplicative_generator()
            3
            sage: G = MatrixGroup([MS([3,0,0,1])])
            sage: a = G.gens()[0]^2
            sage: phi = G.hom([a])
            sage: phi.kernel()
            Matrix group over Finite Field of size 7 with 1 generators:
             [[[6, 0], [0, 1]]]

        """
        gap_ker = gap(self).Kernel()
        from sage.all import MatrixGroup
        F = self.domain().base_ring()
        return MatrixGroup(
            [x._matrix_(F) for x in gap_ker.GeneratorsOfGroup()])
Esempio n. 30
0
 def character_table(self):
     """
     Returns the GAP character table as a string. For larger tables you
     may preface this with a command such as
     gap.eval("SizeScreen([120,40])") in order to widen the screen.
     
     EXAMPLES::
     
         sage: print WeylGroup(['A',3]).character_table()
         CT1
         <BLANKLINE>
              2  3  2  2  .  3
              3  1  .  .  1  .
         <BLANKLINE>
                1a 4a 2a 3a 2b
         <BLANKLINE>
         X.1     1 -1 -1  1  1
         X.2     3  1 -1  . -1
         X.3     2  .  . -1  2
         X.4     3 -1  1  . -1
         X.5     1  1  1  1  1
     """
     return gap.eval("Display(CharacterTable(%s))" % gap(self).name())
Esempio n. 31
0
 def character_table(self):
     """
     Returns the GAP character table as a string. For larger tables you
     may preface this with a command such as
     gap.eval("SizeScreen([120,40])") in order to widen the screen.
     
     EXAMPLES::
     
         sage: print WeylGroup(['A',3]).character_table()
         CT1
         <BLANKLINE>
              2  3  2  2  .  3
              3  1  .  .  1  .
         <BLANKLINE>
                1a 4a 2a 3a 2b
         <BLANKLINE>
         X.1     1 -1 -1  1  1
         X.2     3  1 -1  . -1
         X.3     2  .  . -1  2
         X.4     3 -1  1  . -1
         X.5     1  1  1  1  1
     """
     return gap.eval("Display(CharacterTable(%s))" % gap(self).name())
Esempio n. 32
0
    def as_permutation_group(self, algorithm=None):
        r"""
        Return a permutation group representation for the group.

        In most cases occurring in practice, this is a permutation
        group of minimal degree (the degree begin determined from
        orbits under the group action). When these orbits are hard to
        compute, the procedure can be time-consuming and the degree
        may not be minimal.

        INPUT:

        - ``algorithm`` -- ``None`` or ``'smaller'``. In the latter
          case, try harder to find a permutation representation of
          small degree.

        OUTPUT:

        A permutation group isomorphic to ``self``. The
        ``algorithm='smaller'`` option tries to return an isomorphic
        group of low degree, but is not guaranteed to find the
        smallest one.

        EXAMPLES::

            sage: MS = MatrixSpace(GF(2), 5, 5)
            sage: A = MS([[0,0,0,0,1],[0,0,0,1,0],[0,0,1,0,0],[0,1,0,0,0],[1,0,0,0,0]])
            sage: G = MatrixGroup([A])
            sage: G.as_permutation_group()
            Permutation Group with generators [(1,2)]
            sage: MS = MatrixSpace( GF(7), 12, 12)
            sage: GG = gap("ImfMatrixGroup( 12, 3 )")
            sage: GG.GeneratorsOfGroup().Length()
            3
            sage: g1 = MS(eval(str(GG.GeneratorsOfGroup()[1]).replace("\n","")))
            sage: g2 = MS(eval(str(GG.GeneratorsOfGroup()[2]).replace("\n","")))
            sage: g3 = MS(eval(str(GG.GeneratorsOfGroup()[3]).replace("\n","")))
            sage: G = MatrixGroup([g1, g2, g3])
            sage: G.cardinality()
            21499084800
            sage: set_random_seed(0); current_randstate().set_seed_gap()
            sage: P = G.as_permutation_group()
            sage: P.cardinality()
            21499084800
            sage: P.degree()  # random output
            144
            sage: set_random_seed(3); current_randstate().set_seed_gap()
            sage: Psmaller = G.as_permutation_group(algorithm="smaller")
            sage: Psmaller.cardinality()
            21499084800
            sage: Psmaller.degree()  # random output
            108

        In this case, the "smaller" option returned an isomorphic group of
        lower degree. The above example used GAP's library of irreducible
        maximal finite ("imf") integer matrix groups to construct the
        MatrixGroup G over GF(7). The section "Irreducible Maximal Finite
        Integral Matrix Groups" in the GAP reference manual has more
        details.
        """
        # Note that the output of IsomorphismPermGroup() depends on
        # memory locations and will change if you change the order of
        # doctests and/or architecture
        from sage.groups.perm_gps.permgroup import PermutationGroup
        if not self.is_finite():
            raise NotImplementedError, "Group must be finite."
        n = self.degree()
        MS = MatrixSpace(self.base_ring(), n, n)
        mats = []  # initializing list of mats by which the gens act on self
        for g in self.gens():
            p = MS(g.matrix())
            m = p.rows()
            mats.append(m)
        mats_str = str(gap([[list(r) for r in m] for m in mats]))
        gap.eval("iso:=IsomorphismPermGroup(Group(" + mats_str + "))")
        if algorithm == "smaller":
            gap.eval(
                "small:= SmallerDegreePermutationRepresentation( Image( iso ) );"
            )
            C = gap("Image( small )")
        else:
            C = gap("Image( iso )")
        return PermutationGroup(gap_group=C)
Esempio n. 33
0
    def as_permutation_group(self, algorithm=None):
        r"""
        Return a permutation group representation for the group.

        In most cases occurring in practice, this is a permutation
        group of minimal degree (the degree begin determined from
        orbits under the group action). When these orbits are hard to
        compute, the procedure can be time-consuming and the degree
        may not be minimal.

        INPUT:

        - ``algorithm`` -- ``None`` or ``'smaller'``. In the latter
          case, try harder to find a permutation representation of
          small degree.

        OUTPUT:

        A permutation group isomorphic to ``self``. The
        ``algorithm='smaller'`` option tries to return an isomorphic
        group of low degree, but is not guaranteed to find the
        smallest one.

        EXAMPLES::
        
            sage: MS = MatrixSpace(GF(2), 5, 5)
            sage: A = MS([[0,0,0,0,1],[0,0,0,1,0],[0,0,1,0,0],[0,1,0,0,0],[1,0,0,0,0]])
            sage: G = MatrixGroup([A])
            sage: G.as_permutation_group()
            Permutation Group with generators [(1,2)]
            sage: MS = MatrixSpace( GF(7), 12, 12)
            sage: GG = gap("ImfMatrixGroup( 12, 3 )")
            sage: GG.GeneratorsOfGroup().Length()
            3
            sage: g1 = MS(eval(str(GG.GeneratorsOfGroup()[1]).replace("\n","")))
            sage: g2 = MS(eval(str(GG.GeneratorsOfGroup()[2]).replace("\n","")))
            sage: g3 = MS(eval(str(GG.GeneratorsOfGroup()[3]).replace("\n","")))
            sage: G = MatrixGroup([g1, g2, g3])
            sage: G.cardinality()
            21499084800
            sage: set_random_seed(0); current_randstate().set_seed_gap()
            sage: P = G.as_permutation_group()
            sage: P.cardinality()
            21499084800
            sage: P.degree()  # random output
            144
            sage: set_random_seed(3); current_randstate().set_seed_gap()
            sage: Psmaller = G.as_permutation_group(algorithm="smaller")
            sage: Psmaller.cardinality()
            21499084800
            sage: Psmaller.degree()  # random output
            108

        In this case, the "smaller" option returned an isomorphic group of
        lower degree. The above example used GAP's library of irreducible
        maximal finite ("imf") integer matrix groups to construct the
        MatrixGroup G over GF(7). The section "Irreducible Maximal Finite
        Integral Matrix Groups" in the GAP reference manual has more
        details.

        TESTS::

            sage: A= matrix(QQ, 2, [0, 1, 1, 0])
            sage: B= matrix(QQ, 2, [1, 0, 0, 1])
            sage: a, b= MatrixGroup([A, B]).as_permutation_group().gens()
            sage: a.order(), b.order()
            (2, 1)
        """
        # Note that the output of IsomorphismPermGroup() depends on
        # memory locations and will change if you change the order of
        # doctests and/or architecture
        from sage.groups.perm_gps.permgroup import PermutationGroup
        if not self.is_finite():
            raise NotImplementedError("Group must be finite.")
        n = self.degree()
        MS = MatrixSpace(self.base_ring(), n, n)
        mats = [] # initializing list of mats by which the gens act on self
        for g in self.gens():
            p = MS(g.matrix())
            m = p.rows()
            mats.append(m)
        mats_str = str(gap([[list(r) for r in m] for m in mats]))
        gap.eval("iso:=IsomorphismPermGroup(Group("+mats_str+"))")
        if algorithm == "smaller":
            gap.eval("small:= SmallerDegreePermutationRepresentation( Image( iso ) );")
            C = gap("Image( small )")
        else:
            C = gap("Image( iso )")
        return PermutationGroup(gap_group=C, canonicalize=False)
Esempio n. 34
0
    def word_problem(self, gens=None):
        r"""
        Write this group element in terms of the elements of the list
        ``gens``, or the standard generators of the parent of self if
        ``gens`` is None.
        
        INPUT:

        - ``gens`` - a list of elements that can be coerced into the parent of
          self, or None.

        ALGORITHM: Use GAP, which has optimized algorithms for solving the
        word problem (the GAP functions EpimorphismFromFreeGroup and
        PreImagesRepresentative).
        
        EXAMPLE::
        
            sage: G = GL(2,5); G
            General Linear Group of degree 2 over Finite Field of size 5
            sage: G.gens()
            [
            [2 0]
            [0 1],
            [4 1]
            [4 0]
            ]
            sage: G(1).word_problem([G.1, G.0])
            1
        
        Next we construct a more complicated element of the group from the
        generators::
        
            sage: s,t = G.0, G.1
            sage: a = (s * t * s); b = a.word_problem(); b
            ([2 0]
            [0 1]) *
            ([4 1]
            [4 0]) *
            ([2 0]
            [0 1])
            sage: b.prod() == a
            True

        We solve the word problem using some different generators::

            sage: s = G([2,0,0,1]); t = G([1,1,0,1]); u = G([0,-1,1,0])
            sage: a.word_problem([s,t,u])
            ([2 0]
            [0 1])^-1 *
            ([1 1]
            [0 1])^-1 *
            ([0 4]
            [1 0]) *
            ([2 0]
            [0 1])^-1

        We try some elements that don't actually generate the group::

            sage: a.word_problem([t,u])
            Traceback (most recent call last):
            ...
            ValueError: Could not solve word problem

        AUTHORS:

        - David Joyner and William Stein
        - David Loeffler (2010): fixed some bugs
        """
        G = self.parent()
        gg = gap(G)
        if not gens:
            gens = gg.GeneratorsOfGroup()
        else:
            gens = gap([G(x) for x in gens])
        H = gens.Group()
        hom = H.EpimorphismFromFreeGroup()
        in_terms_of_gens = str(hom.PreImagesRepresentative(self))
        if 'identity' in in_terms_of_gens:
            return Factorization([])
        elif in_terms_of_gens == 'fail':
            raise ValueError, "Could not solve word problem"
        v = list(H.GeneratorsOfGroup())
        F = G.field_of_definition()
        w = [G(x._matrix_(F)) for x in v]
        factors = [Factorization([(x,1)]) for x in w]
        d = dict([('x%s'%(i+1),factors[i]) for i in range(len(factors))])

        from sage.misc.sage_eval import sage_eval
        F = sage_eval(str(in_terms_of_gens), d)
        F._set_cr(True)
        return F
Esempio n. 35
0
    def _call_(self, g):
        """
        Some python code for wrapping GAP's Images function for a matrix
        group G. Returns an error if g is not in G.

        EXAMPLES::

            sage: F = GF(5); MS = MatrixSpace(F,2,2)
            sage: g = MS([1,1,0,1])
            sage: G = MatrixGroup([g])
            sage: phi = G.hom(G.gens())
            sage: phi(G.0)
            [1 1]
            [0 1]
            sage: phi(G(g^2))
            [1 2]
            [0 1]

        ::

            sage: F = GF(5); MS = MatrixSpace(F,2,2)
            sage: gens = [MS([1,2,  -1,1]),MS([1,1,  0,1])]
            sage: G = MatrixGroup(gens)
            sage: phi = G.hom(G.gens())
            sage: phi(G.0)
            [1 2]
            [4 1]
            sage: phi(G.1)
            [1 1]
            [0 1]

        TEST:

        The following tests that the call method was successfully
        improved in trac ticket #10659::

            sage: O = WeylGroup(['D',6])
            sage: r = prod(O.gens())
            sage: r_ = r^-1
            sage: f = O.hom([r*x*r_ for x in O.gens()])  # long time (19s on sage.math, 2011)
            sage: [f(x) for x in O.gens()]  # long time
            [
            [1 0 0 0 0 0]  [1 0 0 0 0 0]  [1 0 0 0 0 0]  [ 0  0  0  0 -1  0]
            [0 0 1 0 0 0]  [0 1 0 0 0 0]  [0 1 0 0 0 0]  [ 0  1  0  0  0  0]
            [0 1 0 0 0 0]  [0 0 0 1 0 0]  [0 0 1 0 0 0]  [ 0  0  1  0  0  0]
            [0 0 0 1 0 0]  [0 0 1 0 0 0]  [0 0 0 0 1 0]  [ 0  0  0  1  0  0]
            [0 0 0 0 1 0]  [0 0 0 0 1 0]  [0 0 0 1 0 0]  [-1  0  0  0  0  0]
            [0 0 0 0 0 1], [0 0 0 0 0 1], [0 0 0 0 0 1], [ 0  0  0  0  0  1],
            <BLANKLINE>
            [0 0 0 0 0 1]  [ 0  0  0  0  0 -1]
            [0 1 0 0 0 0]  [ 0  1  0  0  0  0]
            [0 0 1 0 0 0]  [ 0  0  1  0  0  0]
            [0 0 0 1 0 0]  [ 0  0  0  1  0  0]
            [0 0 0 0 1 0]  [ 0  0  0  0  1  0]
            [1 0 0 0 0 0], [-1  0  0  0  0  0]
            ]
            sage: f(O)  # long time
            Matrix group over Rational Field with 6 generators:
             [[[1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1]], [[1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1]], [[1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1]], [[0, 0, 0, 0, -1, 0], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0], [-1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1]], [[0, 0, 0, 0, 0, 1], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [1, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, -1], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [-1, 0, 0, 0, 0, 0]]]

        """
        phi = gap(self)
        G = self.domain()
        F = G.base_ring()
        h = gap(g)
        return phi.Image(h)._matrix_(F)
Esempio n. 36
0
 def __cmp__(self, H):
     if not isinstance(H, MatrixGroup_gap):
         return cmp(type(self), type(H))
     return cmp(gap(self), gap(H))
Esempio n. 37
0
    def invariant_generators(self):
        """
        Wraps Singular's invariant_algebra_reynolds and invariant_ring
        in finvar.lib, with help from Simon King and Martin Albrecht.
        Computes generators for the polynomial ring
        `F[x_1,\ldots,x_n]^G`, where G in GL(n,F) is a finite
        matrix group.

        In the "good characteristic" case the polynomials returned form a
        minimal generating set for the algebra of G-invariant polynomials.
        In the "bad" case, the polynomials returned are primary and
        secondary invariants, forming a not necessarily minimal generating
        set for the algebra of G-invariant polynomials.

        EXAMPLES::

            sage: F = GF(7); MS = MatrixSpace(F,2,2)
            sage: gens = [MS([[0,1],[-1,0]]),MS([[1,1],[2,3]])]
            sage: G = MatrixGroup(gens)
            sage: G.invariant_generators()
            [x1^7*x2 - x1*x2^7, x1^12 - 2*x1^9*x2^3 - x1^6*x2^6 + 2*x1^3*x2^9 + x2^12, x1^18 + 2*x1^15*x2^3 + 3*x1^12*x2^6 + 3*x1^6*x2^12 - 2*x1^3*x2^15 + x2^18]
            sage: q = 4; a = 2
            sage: MS = MatrixSpace(QQ, 2, 2)
            sage: gen1 = [[1/a,(q-1)/a],[1/a, -1/a]]; gen2 = [[1,0],[0,-1]]; gen3 = [[-1,0],[0,1]]
            sage: G = MatrixGroup([MS(gen1),MS(gen2),MS(gen3)])
            sage: G.cardinality()
            12
            sage: G.invariant_generators()
            [x1^2 + 3*x2^2, x1^6 + 15*x1^4*x2^2 + 15*x1^2*x2^4 + 33*x2^6]
            sage: F = GF(5); MS = MatrixSpace(F,2,2)
            sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[-1,1]])]
            sage: G = MatrixGroup(gens)
            sage: G.invariant_generators()  # long time (67s on sage.math, 2012)
            [x1^20 + x1^16*x2^4 + x1^12*x2^8 + x1^8*x2^12 + x1^4*x2^16 + x2^20, x1^20*x2^4 + x1^16*x2^8 + x1^12*x2^12 + x1^8*x2^16 + x1^4*x2^20]
            sage: F=CyclotomicField(8)
            sage: z=F.gen()
            sage: a=z+1/z
            sage: b=z^2
            sage: MS=MatrixSpace(F,2,2)
            sage: g1=MS([[1/a,1/a],[1/a,-1/a]])
            sage: g2=MS([[1,0],[0,b]])
            sage: g3=MS([[b,0],[0,1]])
            sage: G=MatrixGroup([g1,g2,g3])
            sage: G.invariant_generators()  # long time (12s on sage.math, 2011)
            [x1^8 + 14*x1^4*x2^4 + x2^8,
             x1^24 + 10626/1025*x1^20*x2^4 + 735471/1025*x1^16*x2^8 + 2704156/1025*x1^12*x2^12 + 735471/1025*x1^8*x2^16 + 10626/1025*x1^4*x2^20 + x2^24]

        AUTHORS:

        - David Joyner, Simon King and Martin Albrecht.

        REFERENCES:

        - Singular reference manual

        - B. Sturmfels, "Algorithms in invariant theory", Springer-Verlag, 1993.

        - S. King, "Minimal Generating Sets of non-modular invariant rings of
          finite groups", arXiv:math.AC/0703035
        """
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        from sage.interfaces.singular import singular
        gens = self.gens()
        singular.LIB("finvar.lib")
        n = self.degree()  #len((gens[0].matrix()).rows())
        F = self.base_ring()
        q = F.characteristic()
        ## test if the field is admissible
        if F.gen() == 1:  # we got the rationals or GF(prime)
            FieldStr = str(F.characteristic())
        elif hasattr(F, 'polynomial'):  # we got an algebraic extension
            if len(F.gens()) > 1:
                raise NotImplementedError, "can only deal with finite fields and (simple algebraic extensions of) the rationals"
            FieldStr = '(%d,%s)' % (F.characteristic(), str(F.gen()))
        else:  # we have a transcendental extension
            FieldStr = '(%d,%s)' % (F.characteristic(), ','.join(
                [str(p) for p in F.gens()]))

        ## Setting Singular's variable names
        ## We need to make sure that field generator and variables get different names.
        if str(F.gen())[0] == 'x':
            VarStr = 'y'
        else:
            VarStr = 'x'
        VarNames = '(' + ','.join(
            (VarStr + str(i + 1) for i in range(n))) + ')'
        R = singular.ring(FieldStr, VarNames, 'dp')
        if hasattr(F,
                   'polynomial') and F.gen() != 1:  # we have to define minpoly
            singular.eval('minpoly = ' +
                          str(F.polynomial()).replace('x', str(F.gen())))
        A = [singular.matrix(n, n, str((x.matrix()).list())) for x in gens]
        Lgens = ','.join((x.name() for x in A))
        PR = PolynomialRing(F, n, [VarStr + str(i) for i in range(1, n + 1)])
        if q == 0 or (q > 0 and self.cardinality() % q != 0):
            from sage.all import Integer, Matrix
            try:
                gapself = gap(self)
                # test whether the backwards transformation works as well:
                for i in range(self.ngens()):
                    if Matrix(gapself.gen(i + 1), F) != self.gen(i).matrix():
                        raise ValueError
            except (TypeError, ValueError):
                gapself is None
            if gapself is not None:
                ReyName = 't' + singular._next_var_name()
                singular.eval('matrix %s[%d][%d]' %
                              (ReyName, self.cardinality(), n))
                En = gapself.Enumerator()
                for i in range(1, self.cardinality() + 1):
                    M = Matrix(En[i], F)
                    D = [{} for foobar in range(self.degree())]
                    for x, y in M.dict().items():
                        D[x[0]][x[1]] = y
                    for row in range(self.degree()):
                        for t in D[row].items():
                            singular.eval('%s[%d,%d]=%s[%d,%d]+(%s)*var(%d)' %
                                          (ReyName, i, row + 1, ReyName, i,
                                           row + 1, repr(t[1]), t[0] + 1))
                foobar = singular(ReyName)
                IRName = 't' + singular._next_var_name()
                singular.eval('matrix %s = invariant_algebra_reynolds(%s)' %
                              (IRName, ReyName))
            else:
                ReyName = 't' + singular._next_var_name()
                singular.eval('list %s=group_reynolds((%s))' %
                              (ReyName, Lgens))
                IRName = 't' + singular._next_var_name()
                singular.eval('matrix %s = invariant_algebra_reynolds(%s[1])' %
                              (IRName, ReyName))

            OUT = [
                singular.eval(IRName + '[1,%d]' % (j))
                for j in range(1, 1 + singular('ncols(' + IRName + ')'))
            ]
            return [PR(gen) for gen in OUT]
        if self.cardinality() % q == 0:
            PName = 't' + singular._next_var_name()
            SName = 't' + singular._next_var_name()
            singular.eval('matrix %s,%s=invariant_ring(%s)' %
                          (PName, SName, Lgens))
            OUT = [
                singular.eval(PName + '[1,%d]' % (j))
                for j in range(1, 1 + singular('ncols(' + PName + ')'))
            ] + [
                singular.eval(SName + '[1,%d]' % (j))
                for j in range(2, 1 + singular('ncols(' + SName + ')'))
            ]
            return [PR(gen) for gen in OUT]
Esempio n. 38
0
    def word_problem(self, gens=None):
        r"""
        Write this group element in terms of the elements of the list
        ``gens``, or the standard generators of the parent of self if
        ``gens`` is None.
        
        INPUT:

        - ``gens`` - a list of elements that can be coerced into the parent of
          self, or None.

        ALGORITHM: Use GAP, which has optimized algorithms for solving the
        word problem (the GAP functions EpimorphismFromFreeGroup and
        PreImagesRepresentative).
        
        EXAMPLE::
        
            sage: G = GL(2,5); G
            General Linear Group of degree 2 over Finite Field of size 5
            sage: G.gens()
            [
            [2 0]
            [0 1],
            [4 1]
            [4 0]
            ]
            sage: G(1).word_problem([G.1, G.0])
            1
        
        Next we construct a more complicated element of the group from the
        generators::
        
            sage: s,t = G.0, G.1
            sage: a = (s * t * s); b = a.word_problem(); b
            ([2 0]
            [0 1]) *
            ([4 1]
            [4 0]) *
            ([2 0]
            [0 1])
            sage: b.prod() == a
            True

        We solve the word problem using some different generators::

            sage: s = G([2,0,0,1]); t = G([1,1,0,1]); u = G([0,-1,1,0])
            sage: a.word_problem([s,t,u])
            ([2 0]
            [0 1])^-1 *
            ([1 1]
            [0 1])^-1 *
            ([0 4]
            [1 0]) *
            ([2 0]
            [0 1])^-1

        We try some elements that don't actually generate the group::

            sage: a.word_problem([t,u])
            Traceback (most recent call last):
            ...
            ValueError: Could not solve word problem

        AUTHORS:

        - David Joyner and William Stein
        - David Loeffler (2010): fixed some bugs
        """
        G = self.parent()
        gg = gap(G)
        if not gens:
            gens = gg.GeneratorsOfGroup()
        else:
            gens = gap([G(x) for x in gens])
        H = gens.Group()
        hom = H.EpimorphismFromFreeGroup()
        in_terms_of_gens = str(hom.PreImagesRepresentative(self))
        if "identity" in in_terms_of_gens:
            return Factorization([])
        elif in_terms_of_gens == "fail":
            raise ValueError, "Could not solve word problem"
        v = list(H.GeneratorsOfGroup())
        F = G.field_of_definition()
        w = [G(x._matrix_(F)) for x in v]
        factors = [Factorization([(x, 1)]) for x in w]
        d = dict([("x%s" % (i + 1), factors[i]) for i in range(len(factors))])

        from sage.misc.sage_eval import sage_eval

        F = sage_eval(str(in_terms_of_gens), d)
        F._set_cr(True)
        return F
        def cycle_index(self, parent = None):
            r"""
            INPUT:

             - ``self`` - a permutation group `G`
             - ``parent`` -- a free module with basis indexed by partitions,
               or behave as such, with a ``term`` and ``sum`` method
               (default: the symmetric functions over the rational field in the p basis)

            Returns the *cycle index* of `G`, which is a gadget counting
            the elements of `G` by cycle type, averaged over the group:

            .. math::

                P = \frac{1}{|G|} \sum_{g\in G} p_{ \operatorname{cycle\ type}(g) }

            EXAMPLES:

            Among the permutations of the symmetric group `S_4`, there is
            the identity, 6 cycles of length 2, 3 products of two cycles
            of length 2, 8 cycles of length 3, and 6 cycles of length 4::

                sage: S4 = SymmetricGroup(4)
                sage: P = S4.cycle_index()
                sage: 24 * P
                p[1, 1, 1, 1] + 6*p[2, 1, 1] + 3*p[2, 2] + 8*p[3, 1] + 6*p[4]

            If `l = (l_1,\dots,l_k)` is a partition, ``|G| P[l]`` is the number
            of elements of `G` with cycles of length `(p_1,\dots,p_k)`::

                sage: 24 * P[ Partition([3,1]) ]
                8

            The cycle index plays an important role in the enumeration of
            objects modulo the action of a group (Polya enumeration), via
            the use of symmetric functions and plethysms. It is therefore
            encoded as a symmetric function, expressed in the powersum
            basis::

                sage: P.parent()
                Symmetric Functions over Rational Field in the powersum basis

            This symmetric function can have some nice properties; for
            example, for the symmetric group `S_n`, we get the complete
            symmetric function `h_n`::

                sage: S = SymmetricFunctions(QQ); h = S.h()
                sage: h( P )
                h[4]

            TODO: add some simple examples of Polya enumeration, once it
            will be easy to expand symmetric functions on any alphabet.

            Here are the cycle indices of some permutation groups::

                sage: 6 * CyclicPermutationGroup(6).cycle_index()
                p[1, 1, 1, 1, 1, 1] + p[2, 2, 2] + 2*p[3, 3] + 2*p[6]

                sage: 60 * AlternatingGroup(5).cycle_index()
                p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5]

                sage: for G in TransitiveGroups(5):               # optional - database_gap # long time
                ...       G.cardinality() * G.cycle_index()
                p[1, 1, 1, 1, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 10*p[4, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5]
                p[1, 1, 1, 1, 1] + 10*p[2, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 20*p[3, 2] + 30*p[4, 1] + 24*p[5]

            One may specify another parent for the result::

                sage: F = CombinatorialFreeModule(QQ, Partitions())
                sage: P = CyclicPermutationGroup(6).cycle_index(parent = F)
                sage: 6 * P
                B[[1, 1, 1, 1, 1, 1]] + B[[2, 2, 2]] + 2*B[[3, 3]] + 2*B[[6]]
                sage: P.parent() is F
                True

            This parent should have a ``term`` and ``sum`` method::

                sage: CyclicPermutationGroup(6).cycle_index(parent = QQ)
                Traceback (most recent call last):
                  ...
                AssertionError: `parent` should be (or behave as) a free module with basis indexed by partitions

            REFERENCES:

             .. [Ker1991] A. Kerber. Algebraic combinatorics via finite group actions, 2.2 p. 70.
               BI-Wissenschaftsverlag, Mannheim, 1991.

            AUTHORS:

             - Nicolas Borie and Nicolas M. Thiery

            TESTS::

                sage: P = PermutationGroup([]); P
                Permutation Group with generators [()]
                sage: P.cycle_index()
                p[1]
                sage: P = PermutationGroup([[(1)]]); P
                Permutation Group with generators [()]
                sage: P.cycle_index()
                p[1]
            """
            from sage.combinat.permutation import Permutation
            if parent is None:
                 from sage.rings.rational_field import QQ
                 from sage.combinat.sf.sf import SymmetricFunctions
                 parent = SymmetricFunctions(QQ).powersum()
            else:
                assert hasattr(parent, "term") and hasattr(parent, "sum"), \
                    "`parent` should be (or behave as) a free module with basis indexed by partitions"
            base_ring = parent.base_ring()
            # TODO: use self.conjugacy_classes() once available
            from sage.interfaces.gap import gap
            CC = ([Permutation(self(C.Representative())).cycle_type(), base_ring(C.Size())] for C in gap(self).ConjugacyClasses())
            return parent.sum( parent.term( partition, coeff ) for (partition, coeff) in CC)/self.cardinality()
Esempio n. 40
0
    def invariant_generators(self):
        """
        Wraps Singular's invariant_algebra_reynolds and invariant_ring
        in finvar.lib, with help from Simon King and Martin Albrecht.
        Computes generators for the polynomial ring
        `F[x_1,\ldots,x_n]^G`, where G in GL(n,F) is a finite
        matrix group.
        
        In the "good characteristic" case the polynomials returned form a
        minimal generating set for the algebra of G-invariant polynomials.
        In the "bad" case, the polynomials returned are primary and
        secondary invariants, forming a not necessarily minimal generating
        set for the algebra of G-invariant polynomials.
        
        EXAMPLES::
        
            sage: F = GF(7); MS = MatrixSpace(F,2,2)
            sage: gens = [MS([[0,1],[-1,0]]),MS([[1,1],[2,3]])]
            sage: G = MatrixGroup(gens)
            sage: G.invariant_generators()
            [x1^7*x2 - x1*x2^7, x1^12 - 2*x1^9*x2^3 - x1^6*x2^6 + 2*x1^3*x2^9 + x2^12, x1^18 + 2*x1^15*x2^3 + 3*x1^12*x2^6 + 3*x1^6*x2^12 - 2*x1^3*x2^15 + x2^18]
            sage: q = 4; a = 2
            sage: MS = MatrixSpace(QQ, 2, 2)
            sage: gen1 = [[1/a,(q-1)/a],[1/a, -1/a]]; gen2 = [[1,0],[0,-1]]; gen3 = [[-1,0],[0,1]]
            sage: G = MatrixGroup([MS(gen1),MS(gen2),MS(gen3)])
            sage: G.cardinality()
            12
            sage: G.invariant_generators()
            [x1^2 + 3*x2^2, x1^6 + 15*x1^4*x2^2 + 15*x1^2*x2^4 + 33*x2^6]
            sage: F = GF(5); MS = MatrixSpace(F,2,2)
            sage: gens = [MS([[1,2],[-1,1]]),MS([[1,1],[-1,1]])]
            sage: G = MatrixGroup(gens)
            sage: G.invariant_generators()  # long time (64s on sage.math, 2011)
            [x1^20 + x1^16*x2^4 + x1^12*x2^8 + x1^8*x2^12 + x1^4*x2^16 + x2^20, x1^20*x2^4 + x1^16*x2^8 + x1^12*x2^12 + x1^8*x2^16 + x1^4*x2^20]
            sage: F=CyclotomicField(8)
            sage: z=F.gen()
            sage: a=z+1/z
            sage: b=z^2
            sage: MS=MatrixSpace(F,2,2)
            sage: g1=MS([[1/a,1/a],[1/a,-1/a]])
            sage: g2=MS([[1,0],[0,b]])
            sage: g3=MS([[b,0],[0,1]])
            sage: G=MatrixGroup([g1,g2,g3])
            sage: G.invariant_generators()  # long time (12s on sage.math, 2011)
            [x1^8 + 14*x1^4*x2^4 + x2^8,
             x1^24 + 10626/1025*x1^20*x2^4 + 735471/1025*x1^16*x2^8 + 2704156/1025*x1^12*x2^12 + 735471/1025*x1^8*x2^16 + 10626/1025*x1^4*x2^20 + x2^24]
        
        AUTHORS:

        - David Joyner, Simon King and Martin Albrecht.
        
        REFERENCES:

        - Singular reference manual

        - B. Sturmfels, "Algorithms in invariant theory", Springer-Verlag, 1993.

        - S. King, "Minimal Generating Sets of non-modular invariant rings of
          finite groups", arXiv:math.AC/0703035
        """
        from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
        from sage.interfaces.singular import singular
        gens = self.gens()
        singular.LIB("finvar.lib")
        n = self.degree() #len((gens[0].matrix()).rows())
        F = self.base_ring()
        q = F.characteristic()
        ## test if the field is admissible
        if F.gen()==1: # we got the rationals or GF(prime)
            FieldStr = str(F.characteristic())
        elif hasattr(F,'polynomial'): # we got an algebraic extension
            if len(F.gens())>1:
                raise NotImplementedError, "can only deal with finite fields and (simple algebraic extensions of) the rationals"
            FieldStr = '(%d,%s)'%(F.characteristic(),str(F.gen()))
        else: # we have a transcendental extension
            FieldStr = '(%d,%s)'%(F.characteristic(),','.join([str(p) for p in F.gens()]))
        
        ## Setting Singular's variable names
        ## We need to make sure that field generator and variables get different names.
        if str(F.gen())[0]=='x': 
            VarStr = 'y'
        else:
            VarStr = 'x'
        VarNames='('+','.join((VarStr+str(i+1) for i in range(n)))+')'
        R=singular.ring(FieldStr,VarNames,'dp')
        if hasattr(F,'polynomial') and F.gen()!=1: # we have to define minpoly
            singular.eval('minpoly = '+str(F.polynomial()).replace('x',str(F.gen())))
        A = [singular.matrix(n,n,str((x.matrix()).list())) for x in gens]
        Lgens = ','.join((x.name() for x in A))
        PR = PolynomialRing(F,n,[VarStr+str(i) for i in range(1,n+1)])
        if q == 0 or (q > 0 and self.cardinality()%q != 0):
            from sage.all import Integer, Matrix
            try:
                gapself = gap(self)
                # test whether the backwards transformation works as well:
                for i in range(self.ngens()):
                    if Matrix(gapself.gen(i+1),F) != self.gen(i).matrix():
                        raise ValueError
            except (TypeError,ValueError):
                gapself is None
            if gapself is not None:
                ReyName = 't'+singular._next_var_name()
                singular.eval('matrix %s[%d][%d]'%(ReyName,self.cardinality(),n))
                En = gapself.Enumerator()
                for i in range(1,self.cardinality()+1):
                    M = Matrix(En[i],F)
                    D = [{} for foobar in range(self.degree())]
                    for x,y in M.dict().items():
                        D[x[0]][x[1]] = y
                    for row in range(self.degree()):
                        for t in D[row].items():
                            singular.eval('%s[%d,%d]=%s[%d,%d]+(%s)*var(%d)'%(ReyName,i,row+1,ReyName,i,row+1, repr(t[1]),t[0]+1))
                foobar = singular(ReyName)
                IRName = 't'+singular._next_var_name()
                singular.eval('matrix %s = invariant_algebra_reynolds(%s)'%(IRName,ReyName))
            else:
                ReyName = 't'+singular._next_var_name()
                singular.eval('list %s=group_reynolds((%s))'%(ReyName,Lgens))
                IRName = 't'+singular._next_var_name()
                singular.eval('matrix %s = invariant_algebra_reynolds(%s[1])'%(IRName,ReyName))

            OUT = [singular.eval(IRName+'[1,%d]'%(j)) for j in range(1,1+singular('ncols('+IRName+')'))]
            return [PR(gen) for gen in OUT]
        if self.cardinality()%q == 0:
            PName = 't'+singular._next_var_name()
            SName = 't'+singular._next_var_name()
            singular.eval('matrix %s,%s=invariant_ring(%s)'%(PName,SName,Lgens))
            OUT = [singular.eval(PName+'[1,%d]'%(j)) for j in range(1,1+singular('ncols('+PName+')'))] + [singular.eval(SName+'[1,%d]'%(j)) for j in range(2,1+singular('ncols('+SName+')'))]
            return [PR(gen) for gen in OUT]
Esempio n. 41
0
    def as_permutation_group(self, algorithm=None):
        r"""
        Return a permutation group representation for the group.

        In most cases occurring in practice, this is a permutation
        group of minimal degree (the degree being determined from
        orbits under the group action). When these orbits are hard to
        compute, the procedure can be time-consuming and the degree
        may not be minimal.

        INPUT:

        - ``algorithm`` -- ``None`` or ``'smaller'``. In the latter
          case, try harder to find a permutation representation of
          small degree.

        OUTPUT:

        A permutation group isomorphic to ``self``. The
        ``algorithm='smaller'`` option tries to return an isomorphic
        group of low degree, but is not guaranteed to find the
        smallest one.

        EXAMPLES::
        
            sage: MS = MatrixSpace(GF(2), 5, 5)
            sage: A = MS([[0,0,0,0,1],[0,0,0,1,0],[0,0,1,0,0],[0,1,0,0,0],[1,0,0,0,0]])
            sage: G = MatrixGroup([A])
            sage: G.as_permutation_group()
            Permutation Group with generators [(1,2)]
            sage: MS = MatrixSpace( GF(7), 12, 12)
            sage: GG = gap("ImfMatrixGroup( 12, 3 )")
            sage: GG.GeneratorsOfGroup().Length()
            3
            sage: g1 = MS(eval(str(GG.GeneratorsOfGroup()[1]).replace("\n","")))
            sage: g2 = MS(eval(str(GG.GeneratorsOfGroup()[2]).replace("\n","")))
            sage: g3 = MS(eval(str(GG.GeneratorsOfGroup()[3]).replace("\n","")))
            sage: G = MatrixGroup([g1, g2, g3])
            sage: G.cardinality()
            21499084800
            sage: set_random_seed(0); current_randstate().set_seed_gap()
            sage: P = G.as_permutation_group()
            sage: P.cardinality()
            21499084800
            sage: P.degree()  # random output
            144
            sage: set_random_seed(3); current_randstate().set_seed_gap()
            sage: Psmaller = G.as_permutation_group(algorithm="smaller")
            sage: Psmaller.cardinality()
            21499084800
            sage: Psmaller.degree()  # random output
            108

        In this case, the "smaller" option returned an isomorphic group of
        lower degree. The above example used GAP's library of irreducible
        maximal finite ("imf") integer matrix groups to construct the
        MatrixGroup G over GF(7). The section "Irreducible Maximal Finite
        Integral Matrix Groups" in the GAP reference manual has more
        details.

        TESTS::

            sage: A= matrix(QQ, 2, [0, 1, 1, 0])
            sage: B= matrix(QQ, 2, [1, 0, 0, 1])
            sage: a, b= MatrixGroup([A, B]).as_permutation_group().gens()
            sage: a.order(), b.order()
            (2, 1)

        Check that ``_permutation_group_morphism`` works (:trac:`25706`)::

            sage: MG = GU(3,2).as_matrix_group()
            sage: PG = MG.as_permutation_group()  # this constructs the morphism
            sage: mg = MG.an_element()
            sage: MG._permutation_group_morphism(mg)
            (1,2,6,19,35,33)(3,9,26,14,31,23)(4,13,5)(7,22,17)(8,24,12)(10,16,32,27,20,28)(11,30,18)(15,25,36,34,29,21)
        """
        # Note that the output of IsomorphismPermGroup() depends on
        # memory locations and will change if you change the order of
        # doctests and/or architecture
        from sage.groups.perm_gps.permgroup import PermutationGroup
        if not self.is_finite():
            raise NotImplementedError("Group must be finite.")
        n = self.degree()
        MS = MatrixSpace(self.base_ring(), n, n)
        mats = [] # initializing list of mats by which the gens act on self
        for g in self.gens():
            p = MS(g.matrix())
            m = p.rows()
            mats.append(m)
        mats_str = str(gap([[list(r) for r in m] for m in mats]))
        gap.eval("iso:=IsomorphismPermGroup(Group("+mats_str+"))")
        gap_permutation_map = gap("iso;")
        if algorithm == "smaller":
            gap.eval("small:= SmallerDegreePermutationRepresentation( Image( iso ) );")
            C = gap("Image( small )")
        else:
            C = gap("Image( iso )")
        PG = PermutationGroup(gap_group=C, canonicalize=False)

        def permutation_group_map(element):
            return PG(gap_permutation_map.ImageElm(element.gap()))

        from sage.categories.homset import Hom
        self._permutation_group_morphism = Hom(self, PG)(permutation_group_map)

        return PG
Esempio n. 42
0
 def __cmp__(self, H):
     if not isinstance(H, MatrixGroup_gap):
         return cmp(type(self), type(H))
     return cmp(gap(self), gap(H))
Esempio n. 43
0
        def cycle_index(self, parent = None):
            r"""
            INPUT:

             - ``self`` - a permutation group `G`
             - ``parent`` -- a free module with basis indexed by partitions,
               or behave as such, with a ``term`` and ``sum`` method
               (default: the symmetric functions over the rational field in the p basis)

            Returns the *cycle index* of `G`, which is a gadget counting
            the elements of `G` by cycle type, averaged over the group:

            .. math::

                P = \frac{1}{|G|} \sum_{g\in G} p_{ \operatorname{cycle\ type}(g) }

            EXAMPLES:

            Among the permutations of the symmetric group `S_4`, there is
            the identity, 6 cycles of length 2, 3 products of two cycles
            of length 2, 8 cycles of length 3, and 6 cycles of length 4::

                sage: S4 = SymmetricGroup(4)
                sage: P = S4.cycle_index()
                sage: 24 * P
                p[1, 1, 1, 1] + 6*p[2, 1, 1] + 3*p[2, 2] + 8*p[3, 1] + 6*p[4]

            If `l = (l_1,\dots,l_k)` is a partition, ``|G| P[l]`` is the number
            of elements of `G` with cycles of length `(p_1,\dots,p_k)`::

                sage: 24 * P[ Partition([3,1]) ]
                8

            The cycle index plays an important role in the enumeration of
            objects modulo the action of a group (Polya enumeration), via
            the use of symmetric functions and plethysms. It is therefore
            encoded as a symmetric function, expressed in the powersum
            basis::

                sage: P.parent()
                Symmetric Functions over Rational Field in the powersum basis

            This symmetric function can have some nice properties; for
            example, for the symmetric group `S_n`, we get the complete
            symmetric function `h_n`::

                sage: S = SymmetricFunctions(QQ); h = S.h()
                sage: h( P )
                h[4]

            TODO: add some simple examples of Polya enumeration, once it
            will be easy to expand symmetric functions on any alphabet.

            Here are the cycle indices of some permutation groups::

                sage: 6 * CyclicPermutationGroup(6).cycle_index()
                p[1, 1, 1, 1, 1, 1] + p[2, 2, 2] + 2*p[3, 3] + 2*p[6]

                sage: 60 * AlternatingGroup(5).cycle_index()
                p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5]

                sage: for G in TransitiveGroups(5):               # optional - database_gap # long time
                ...       G.cardinality() * G.cycle_index()
                p[1, 1, 1, 1, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 5*p[2, 2, 1] + 10*p[4, 1] + 4*p[5]
                p[1, 1, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 24*p[5]
                p[1, 1, 1, 1, 1] + 10*p[2, 1, 1, 1] + 15*p[2, 2, 1] + 20*p[3, 1, 1] + 20*p[3, 2] + 30*p[4, 1] + 24*p[5]

            One may specify another parent for the result::

                sage: F = CombinatorialFreeModule(QQ, Partitions())
                sage: P = CyclicPermutationGroup(6).cycle_index(parent = F)
                sage: 6 * P
                B[[1, 1, 1, 1, 1, 1]] + B[[2, 2, 2]] + 2*B[[3, 3]] + 2*B[[6]]
                sage: P.parent() is F
                True

            This parent should have a ``term`` and ``sum`` method::

                sage: CyclicPermutationGroup(6).cycle_index(parent = QQ)
                Traceback (most recent call last):
                  ...
                AssertionError: `parent` should be (or behave as) a free module with basis indexed by partitions

            REFERENCES:

             .. [Ker1991] A. Kerber. Algebraic combinatorics via finite group actions, 2.2 p. 70.
               BI-Wissenschaftsverlag, Mannheim, 1991.

            AUTHORS:

             - Nicolas Borie and Nicolas M. Thiery

            TESTS::

                sage: P = PermutationGroup([]); P
                Permutation Group with generators [()]
                sage: P.cycle_index()
                p[1]
                sage: P = PermutationGroup([[(1)]]); P
                Permutation Group with generators [()]
                sage: P.cycle_index()
                p[1]
            """
            from sage.combinat.permutation import Permutation
            if parent is None:
                 from sage.rings.rational_field import QQ
                 from sage.combinat.sf.sf import SymmetricFunctions
                 parent = SymmetricFunctions(QQ).powersum()
            else:
                assert hasattr(parent, "term") and hasattr(parent, "sum"), \
                    "`parent` should be (or behave as) a free module with basis indexed by partitions"
            base_ring = parent.base_ring()
            # TODO: use self.conjugacy_classes() once available
            from sage.interfaces.gap import gap
            CC = ([Permutation(self(C.Representative())).cycle_type(), base_ring(C.Size())] for C in gap(self).ConjugacyClasses())
            return parent.sum( parent.term( partition, coeff ) for (partition, coeff) in CC)/self.cardinality()
Esempio n. 44
0
    def _call_( self, g ):
        """
        Some python code for wrapping GAP's Images function for a matrix
        group G. Returns an error if g is not in G.
        
        EXAMPLES::
        
            sage: F = GF(5); MS = MatrixSpace(F,2,2)
            sage: g = MS([1,1,0,1])
            sage: G = MatrixGroup([g])
            sage: phi = G.hom(G.gens())
            sage: phi(G.0)
            [1 1]
            [0 1]
            sage: phi(G(g^2))
            [1 2]
            [0 1]
        
        ::
        
            sage: F = GF(5); MS = MatrixSpace(F,2,2)
            sage: gens = [MS([1,2,  -1,1]),MS([1,1,  0,1])]
            sage: G = MatrixGroup(gens)
            sage: phi = G.hom(G.gens())
            sage: phi(G.0)
            [1 2]
            [4 1]
            sage: phi(G.1)
            [1 1]
            [0 1]

        TEST:

        The following tests that the call method was successfully
        improved in trac ticket #10659::

            sage: O = WeylGroup(['D',6])
            sage: r = prod(O.gens())
            sage: r_ = r^-1
            sage: f = O.hom([r*x*r_ for x in O.gens()])  # long time (19s on sage.math, 2011)
            sage: [f(x) for x in O.gens()]  # long time
            [
            [1 0 0 0 0 0]  [1 0 0 0 0 0]  [1 0 0 0 0 0]  [ 0  0  0  0 -1  0]
            [0 0 1 0 0 0]  [0 1 0 0 0 0]  [0 1 0 0 0 0]  [ 0  1  0  0  0  0]
            [0 1 0 0 0 0]  [0 0 0 1 0 0]  [0 0 1 0 0 0]  [ 0  0  1  0  0  0]
            [0 0 0 1 0 0]  [0 0 1 0 0 0]  [0 0 0 0 1 0]  [ 0  0  0  1  0  0]
            [0 0 0 0 1 0]  [0 0 0 0 1 0]  [0 0 0 1 0 0]  [-1  0  0  0  0  0]
            [0 0 0 0 0 1], [0 0 0 0 0 1], [0 0 0 0 0 1], [ 0  0  0  0  0  1],
            <BLANKLINE>
            [0 0 0 0 0 1]  [ 0  0  0  0  0 -1]
            [0 1 0 0 0 0]  [ 0  1  0  0  0  0]
            [0 0 1 0 0 0]  [ 0  0  1  0  0  0]
            [0 0 0 1 0 0]  [ 0  0  0  1  0  0]
            [0 0 0 0 1 0]  [ 0  0  0  0  1  0]
            [1 0 0 0 0 0], [-1  0  0  0  0  0]
            ]
            sage: f(O)  # long time
            Matrix group over Rational Field with 6 generators: 
             [[[1, 0, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1]], [[1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 0, 0, 1]], [[1, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 0, 1, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 1]], [[0, 0, 0, 0, -1, 0], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0], [-1, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 1]], [[0, 0, 0, 0, 0, 1], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [1, 0, 0, 0, 0, 0]], [[0, 0, 0, 0, 0, -1], [0, 1, 0, 0, 0, 0], [0, 0, 1, 0, 0, 0], [0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 1, 0], [-1, 0, 0, 0, 0, 0]]]

        """
        phi = gap(self)
        G = self.domain()
        F = G.base_ring()
        h = gap(g)
        return phi.Image(h)._matrix_(F)