Ticket #10334: trac_10334-permgroup_cleanup-rebase-mh.patch

File trac_10334-permgroup_cleanup-rebase-mh.patch, 69.9 KB (added by Nicolas M. Thiéry, 12 years ago)
  • sage/groups/perm_gps/all.py

    # HG changeset patch
    # User Mike Hansen <mhansen@gmail.com>
    # Date 1297156518 -3600
    # Node ID 9d746c3029c39dfb1d7086469da307e3b5cf615b
    # Parent  c7d19f2c6a202690b915e640885d620cf2f68949
    #10334: miscellaneous cleanup in perm_gps preparing for domains
    
    diff --git a/sage/groups/perm_gps/all.py b/sage/groups/perm_gps/all.py
    a b from permgroup import PermutationGroup, 
    1111
    1212from permgroup_element import PermutationGroupElement,is_PermutationGroupElement
    1313
    14 from permgroup_morphism import is_PermutationGroupMorphism,PermutationGroupMap,PermutationGroupMorphism,PermutationGroupMorphism_im_gens,PermutationGroupMorphism_id
     14from permgroup_morphism import (is_PermutationGroupMorphism,
     15                                PermutationGroupMorphism as PermutationGroupMap,
     16                                PermutationGroupMorphism_im_gens,
     17                                PermutationGroupMorphism_id)
     18PermutationGroupMorphism = PermutationGroupMorphism_im_gens
    1519
    1620from cubegroup import CubeGroup, RubiksCube
  • sage/groups/perm_gps/cubegroup.py

    diff --git a/sage/groups/perm_gps/cubegroup.py b/sage/groups/perm_gps/cubegroup.py
    a b Rubik's cube group functions 
    55
    66.. note::
    77
    8   "Rubik's cube" is trademarked. We shall omit the trademark
     8  "Rubiks cube" is trademarked. We shall omit the trademark
    99  symbol below for simplicity.
    1010
    1111NOTATION: B denotes a clockwise quarter turn of the back face D
  • sage/groups/perm_gps/permgroup.py

    diff --git a/sage/groups/perm_gps/permgroup.py b/sage/groups/perm_gps/permgroup.py
    a b REFERENCES: 
    117117#  Distributed under the terms of the GNU General Public License (GPL)
    118118#                  http://www.gnu.org/licenses/
    119119#*****************************************************************************
     120from functools import wraps
     121
    120122from sage.misc.randstate import current_randstate
    121123import sage.groups.group as group
    122124
    123 from sage.rings.all      import RationalField, Integer
     125from sage.rings.all import QQ, Integer
    124126from sage.interfaces.all import is_ExpectElement
    125 from sage.interfaces.gap import gap, is_GapElement, GapElement
     127from sage.interfaces.gap import gap, GapElement
    126128from sage.groups.perm_gps.permgroup_element import PermutationGroupElement
    127 import sage.structure.coerce as coerce
    128 from sage.rings.finite_rings.constructor import FiniteField as GF
    129129from sage.groups.abelian_gps.abelian_group import AbelianGroup
    130 from sage.misc.functional import is_even, log
    131 from sage.rings.rational_field import RationalField
    132 from sage.matrix.matrix_space import MatrixSpace
    133 from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
    134 from sage.rings.fraction_field import FractionField
    135130from sage.misc.cachefunc import cached_method
    136131from sage.groups.class_function import ClassFunction
    137132from sage.misc.package import is_package_installed
    138133
    139134def load_hap():
    140      """
    141      Load the GAP hap package into the default GAP interpreter
    142      interface. If this fails, try one more time to load it.
    143 
    144      EXAMPLES::
    145 
    146          sage: sage.groups.perm_gps.permgroup.load_hap()
    147      """
    148      try:
    149          gap.eval('LoadPackage("hap")')
    150      except:
    151          gap.eval('LoadPackage("hap")')
     135    """
     136    Load the GAP hap package into the default GAP interpreter
     137    interface. If this fails, try one more time to load it.
     138
     139    EXAMPLES::
     140
     141        sage: sage.groups.perm_gps.permgroup.load_hap()
     142    """
     143    try:
     144        gap.eval('LoadPackage("hap")')
     145    except:
     146        gap.eval('LoadPackage("hap")')
     147
     148def hap_decorator(f):
     149    """
     150    A decorator for permutation group methods that require HAP.  It
     151    checks to see that HAP is installed as well as checks that the
     152    argument ``p`` is either 0 or prime.
     153
     154    EXAMPLES::
     155
     156        sage: from sage.groups.perm_gps.permgroup import hap_decorator
     157        sage: def foo(self, n, p=0): print "Done"
     158        sage: foo = hap_decorator(foo)
     159        sage: foo(None, 3)    #optional - gap_packages
     160        Done
     161        sage: foo(None, 3, 0) #optional - gap packages
     162        Done
     163        sage: foo(None, 3, 5) #optional - gap packages
     164        Done
     165        sage: foo(None, 3, 4) #optional - gap_packages
     166        Traceback (most recent call last):
     167        ...
     168        ValueError: p must be 0 or prime
     169    """
     170    @wraps(f)
     171    def wrapped(self, n, p=0):
     172        if not is_package_installed('gap_packages'):
     173            raise RuntimeError, "You must install the optional gap_packages package."
     174        load_hap()
     175        from sage.rings.arith import is_prime
     176        if not (p == 0 or is_prime(p)):
     177            raise ValueError, "p must be 0 or prime"
     178
     179        return f(self, n, p=p)
     180    return wrapped
    152181
    153182def direct_product_permgroups(P):
    154183    """
    def direct_product_permgroups(P): 
    167196        sage: direct_product_permgroups([])
    168197        Symmetric group of order 0! as a permutation group
    169198    """
    170     from permgroup_named import SymmetricGroup
    171199    n = len(P)
    172200    if n == 0:
     201        from sage.groups.perm_gps.permgroup_named import SymmetricGroup
    173202        return SymmetricGroup(0)
    174     if n == 1:
     203    elif n == 1:
    175204        return P[0]
    176     G = [H._gap_init_() for H in P]
    177     Glist = ""
    178     for H in G:
    179         Glist = Glist + H + ","
    180     cmd = "G:=DirectProduct([" + Glist[:-1] + "])"
    181     gap.eval(cmd)
    182     return PermutationGroup(gap_group=gap.eval("G"))
     205    else:
     206        G = gap.DirectProduct(*P)
     207        return PermutationGroup(gap_group=G)
    183208
    184209def from_gap_list(G, src):
    185210    r"""
    def PermutationGroup(gens=None, gap_grou 
    274299    """
    275300    if not is_ExpectElement(gens) and hasattr(gens, '_permgroup_'):
    276301        return gens._permgroup_()
    277     if gens is not None and not isinstance(gens, (tuple,list, GapElement)):
     302    if gens is not None and not isinstance(gens, (tuple, list, GapElement)):
    278303        raise TypeError, "gens must be a tuple, list, or GapElement"
    279304    return PermutationGroup_generic(gens=gens, gap_group=gap_group, canonicalize=canonicalize)
    280305   
    class PermutationGroup_generic(group.Gro 
    339364
    340365        #Handle the case where only the GAP group is specified.
    341366        if gens is None:
     367            from sage.interfaces.gap import gap
    342368            self._gap_string = gap_group if isinstance(gap_group, str) else str(gap_group)
    343369            self._gens = self._gens_from_gap()
    344             return None
    345 
    346         gens = [self._element_class()(x, check=False).list() for x in gens]
    347         self._deg = max([0]+[max(g) for g in gens])
    348         if not gens:  # length 0
    349              gens = [()]
    350         gens = [self._element_class()(x, self, check=False) for x in gens]
    351         if canonicalize:
    352              gens = list(set(gens))
    353              gens.sort()
    354         self._gens = gens
    355         self._gap_string = 'Group(%s)'%gens
     370            self._deg = gap(gap_group).LargestMovedPoint()
     371            self._set = range(1, self._deg+1)
     372        else:
     373            gens = [self._element_class()(x, check=False).list() for x in gens]
     374            self._deg = max([0]+[max(g) for g in gens])
     375            self._set = range(1, self._deg+1)
     376            if not gens:  # length 0
     377                gens = [()]
     378            gens = [self._element_class()(x, self, check=False) for x in gens]
     379            if canonicalize:
     380                gens = sorted(set(gens))
     381            self._gens = gens
     382            self._gap_string = 'Group(%s)'%gens
    356383
    357384    def construction(self):
    358385         """
    class PermutationGroup_generic(group.Gro 
    397424            gens = self._gap_().GeneratorsOfGroup()
    398425        except TypeError, s:
    399426            raise RuntimeError, "(It might be necessary to install the database_gap optional Sage package, if you haven't already.)\n%s"%s
    400         gens = [self._element_class()(gens[n],self, check=False)
     427        gens = [self._element_class()(gens[n], self, check=False)
    401428                       for n in range(1, int(gens.Length())+1)]
    402429        if gens == []:
    403430            gens = [()]
    class PermutationGroup_generic(group.Gro 
    844871            sage: P.cardinality()
    845872            1
    846873        """
    847         # This seems unndeeded since __init__ systematically sets self._deg
     874        # This seems unndeeded since __init__ systematically sets
     875        # self._deg This is actually needed because constructing the
     876        # __init__ of PermutationGroupElement sometimes calls this
     877        # group before is initialized.
    848878        try:
    849879            return self._deg
    850880        except AttributeError:
    class PermutationGroup_generic(group.Gro 
    854884
    855885    degree = largest_moved_point
    856886
     887    def set(self):
     888        r"""
     889        Returns the underlying set that this permutation group acts
     890        on.  By default, the set is {1, ..., n} where n is the largest
     891        moved point by the group.
     892
     893        EXAMPLES::
     894
     895            sage: P = PermutationGroup([(1,2),(3,5)])
     896            sage: P.set()
     897            (1, 2, 3, 4, 5)
     898
     899        """
     900        return tuple(self._set)
     901
     902    domain = set
     903
     904    def _set_gap(self):
     905        """
     906        Returns a GAP string representation of the underlying set
     907        that this group acts on.  See also :meth:`set`.
     908
     909        EXAMPLES::
     910
     911            sage: P = PermutationGroup([(1,2),(3,5)])
     912            sage: P._set_gap()
     913            '[1, 2, 3, 4, 5]'
     914        """
     915        return repr(list(self.set()))
     916
    857917    @cached_method
    858918    def smallest_moved_point(self):
    859919        """
    class PermutationGroup_generic(group.Gro 
    893953
    894954        - Nathan Dunfield
    895955        """
    896         return self._gap_().Orbits("[1..%d]" % self.largest_moved_point()).sage()
     956        return self._gap_().Orbits(self._set_gap()).sage()
    897957
    898958    @cached_method
    899959    def orbit(self, integer):
    900          """
    901          Return the orbit of the given integer under the group action.
    902 
    903          EXAMPLES::
    904 
    905              sage: G = PermutationGroup([ [(3,4)], [(1,3)] ])
    906              sage: G.orbit(3)
    907              [3, 4, 1]
    908              sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
    909              sage: G.orbit(3)                                                 
    910              [3, 4, 10, 1, 2]
    911          """
    912          return self._gap_().Orbit(integer).sage()
     960        """
     961        Return the orbit of the given integer under the group action.
     962
     963        EXAMPLES::
     964
     965            sage: G = PermutationGroup([ [(3,4)], [(1,3)] ])
     966            sage: G.orbit(3)
     967            [3, 4, 1]
     968            sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
     969            sage: G.orbit(3)                                                 
     970            [3, 4, 10, 1, 2]
     971        """
     972        return self._gap_().Orbit(integer).sage()
    913973   
    914974    def transversals(self, integer):
    915          """
    916          If G is a permutation group acting on the set `X = \{1, 2, ...., n\}`
    917          and H is the stabilizer subgroup of <integer>, a right
    918          (respectively left) transversal is a set containing exactly
    919          one element from each right (respectively left) coset of H. This
    920          method returns a right transversal of ``self`` by the stabilizer
    921          of ``self`` on <integer> position.
    922 
    923          EXAMPLES::
    924 
    925              sage: G = PermutationGroup([ [(3,4)], [(1,3)] ])           
    926              sage: G.transversals(1)
    927              [(), (1,3,4), (1,4,3)]
    928              sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
    929              sage: G.transversals(1)                                   
    930              [(), (1,2)(3,4), (1,3,2,10,4), (1,4,2,10,3), (1,10,4,3,2)]
    931          """
    932          trans = []
    933          for i in self.orbit(integer):
    934               trans.append(self(gap.RepresentativeAction(self._gap_(),integer,i)))
    935          return trans
     975        """
     976        If G is a permutation group acting on the set `X = \{1, 2, ...., n\}`
     977        and H is the stabilizer subgroup of <integer>, a right
     978        (respectively left) transversal is a set containing exactly
     979        one element from each right (respectively left) coset of H. This
     980        method returns a right transversal of ``self`` by the stabilizer
     981        of ``self`` on <integer> position.
     982
     983        EXAMPLES::
     984
     985            sage: G = PermutationGroup([ [(3,4)], [(1,3)] ])           
     986            sage: G.transversals(1)
     987            [(), (1,3,4), (1,4,3)]
     988            sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
     989            sage: G.transversals(1)                                   
     990            [(), (1,2)(3,4), (1,3,2,10,4), (1,4,2,10,3), (1,10,4,3,2)]
     991        """
     992        trans = []
     993        for i in self.orbit(integer):
     994             trans.append(self(gap.RepresentativeAction(self._gap_(),integer,i)))
     995        return trans
    936996
    937997    def stabilizer(self, position):
    938          """
    939          Return the subgroup of ``self`` which stabilize the given position.
    940          ``self`` and its stabilizers must have same degree.
    941 
    942          EXAMPLES::
    943 
    944              sage: G = PermutationGroup([ [(3,4)], [(1,3)] ])
    945              sage: G.stabilizer(1)
    946              Permutation Group with generators [(3,4)]
    947              sage: G.stabilizer(3)
    948              Permutation Group with generators [(1,4)]
    949              sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
    950              sage: G.stabilizer(10)
    951              Permutation Group with generators [(1,2)(3,4), (2,3,4)]
    952              sage: G.stabilizer(1)
    953              Permutation Group with generators [(2,3)(4,10), (2,10,4)]
    954              sage: G = PermutationGroup([[(2,3,4)],[(6,7)]])
    955              sage: G.stabilizer(1)
    956              Permutation Group with generators [(6,7), (2,3,4)]
    957              sage: G.stabilizer(2)
    958              Permutation Group with generators [(6,7)]
    959              sage: G.stabilizer(3)
    960              Permutation Group with generators [(6,7)]
    961              sage: G.stabilizer(4)
    962              Permutation Group with generators [(6,7)]
    963              sage: G.stabilizer(5)
    964              Permutation Group with generators [(6,7), (2,3,4)]
    965              sage: G.stabilizer(6)
    966              Permutation Group with generators [(2,3,4)]
    967              sage: G.stabilizer(7)
    968              Permutation Group with generators [(2,3,4)]
    969              sage: G.stabilizer(8)
    970              Permutation Group with generators [(6,7), (2,3,4)]
    971          """
    972          return PermutationGroup(gap_group=gap.Stabilizer(self, position))
     998        """
     999        Return the subgroup of ``self`` which stabilize the given position.
     1000        ``self`` and its stabilizers must have same degree.
     1001
     1002        EXAMPLES::
     1003
     1004            sage: G = PermutationGroup([ [(3,4)], [(1,3)] ])
     1005            sage: G.stabilizer(1)
     1006            Permutation Group with generators [(3,4)]
     1007            sage: G.stabilizer(3)
     1008            Permutation Group with generators [(1,4)]
     1009            sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
     1010            sage: G.stabilizer(10)
     1011            Permutation Group with generators [(1,2)(3,4), (2,3,4)]
     1012            sage: G.stabilizer(1)
     1013            Permutation Group with generators [(2,3)(4,10), (2,10,4)]
     1014            sage: G = PermutationGroup([[(2,3,4)],[(6,7)]])
     1015            sage: G.stabilizer(1)
     1016            Permutation Group with generators [(6,7), (2,3,4)]
     1017            sage: G.stabilizer(2)
     1018            Permutation Group with generators [(6,7)]
     1019            sage: G.stabilizer(3)
     1020            Permutation Group with generators [(6,7)]
     1021            sage: G.stabilizer(4)
     1022            Permutation Group with generators [(6,7)]
     1023            sage: G.stabilizer(5)
     1024            Permutation Group with generators [(6,7), (2,3,4)]
     1025            sage: G.stabilizer(6)
     1026            Permutation Group with generators [(2,3,4)]
     1027            sage: G.stabilizer(7)
     1028            Permutation Group with generators [(2,3,4)]
     1029            sage: G.stabilizer(8)
     1030            Permutation Group with generators [(6,7), (2,3,4)]
     1031        """
     1032        return PermutationGroup(gap_group=gap.Stabilizer(self, position))
    9731033
    9741034    def strong_generating_system(self, base_of_group = None):
    975          """
    976          Return a Strong Generating System of ``self`` according the given
    977          base for the right action of ``self`` on itself.
    978 
    979          ``base_of_group`` is a list of the  positions on which ``self`` acts,
    980          in any order. The algorithm returns a list of transversals and each
    981          transversal is a list of permutations. By default, ``base_of_group``
    982          is ``[1, 2, 3, ..., d]`` where `d` is the degree of the group.
    983 
    984          For ``base_of_group`` =
    985          `[ \mathrm{pos}_1, \mathrm{pos}_2, \dots , \mathrm{pos}_d]`
    986          let `G_i` be the subgroup of `G` = ``self`` which stabilizes
    987          `\mathrm{pos}_1, \mathrm{pos}_2, \dots , \mathrm{pos}_i`, so
    988 
    989          .. math::
    990 
    991             G = G_0 \supset G_1 \supset G_2 \supset \dots \supset G_n = \{e\}
     1035        """
     1036        Return a Strong Generating System of ``self`` according the given
     1037        base for the right action of ``self`` on itself.
     1038
     1039        ``base_of_group`` is a list of the  positions on which ``self`` acts,
     1040        in any order. The algorithm returns a list of transversals and each
     1041        transversal is a list of permutations. By default, ``base_of_group``
     1042        is ``[1, 2, 3, ..., d]`` where `d` is the degree of the group.
     1043
     1044        For ``base_of_group`` =
     1045        `[ \mathrm{pos}_1, \mathrm{pos}_2, \dots , \mathrm{pos}_d]`
     1046        let `G_i` be the subgroup of `G` = ``self`` which stabilizes
     1047        `\mathrm{pos}_1, \mathrm{pos}_2, \dots , \mathrm{pos}_i`, so
     1048
     1049        .. math::
     1050
     1051           G = G_0 \supset G_1 \supset G_2 \supset \dots \supset G_n = \{e\}
    9921052           
    993          Then the algorithm returns `[ G_i.\mathrm{transversals}(\mathrm{pos}_{i+1})]_{1 \leq i \leq n}`
    994 
    995          INPUT:
    996 
    997          - ``base_of_group`` (optional) -- default: ``[1, 2, 3, ..., d]``
    998            -- a list containing the integers
    999            `1, 2, \dots , d` in any order (`d` is the degree of ``self``)
    1000 
    1001          OUTPUT:
    1002 
    1003          - A list of lists of permutations from the group, which form a strong
    1004            generating system.
    1005 
    1006          TESTS::
    1007 
    1008              sage: G = SymmetricGroup(10)
    1009              sage: H = PermutationGroup([G.random_element() for i in range(randrange(1,3,1))])
    1010              sage: prod(map(lambda x : len(x), H.strong_generating_system()),1) == H.cardinality()
    1011              True
    1012 
    1013          EXAMPLES::
    1014 
    1015              sage: G = PermutationGroup([[(7,8)],[(3,4)],[(4,5)]])
    1016              sage: G.strong_generating_system()
    1017              [[()], [()], [(), (3,4,5), (3,5)], [(), (4,5)], [()], [()], [(), (7,8)], [()]]
    1018              sage: G = PermutationGroup([[(1,2,3,4)],[(1,2)]])
    1019              sage: G.strong_generating_system()
    1020              [[(), (1,2)(3,4), (1,3)(2,4), (1,4)(2,3)], [(), (2,3,4), (2,4,3)], [(), (3,4)], [()]]
    1021              sage: G = PermutationGroup([[(1,2,3)],[(4,5,7)],[(1,4,6)]])
    1022              sage: G.strong_generating_system()                         
    1023              [[(), (1,2,3), (1,4,6), (1,3,2), (1,5,7,4,6), (1,6,4), (1,7,5,4,6)], [(), (2,6,3), (2,3,6), (2,5,6,3)(4,7), (2,7,5,6,3), (2,4,5,6,3)], [(), (3,6)(5,7), (3,5,6), (3,7,4,5,6), (3,4,7,5,6)], [(), (4,5)(6,7), (4,7)(5,6), (4,6)(5,7)], [(), (5,6,7), (5,7,6)], [()], [()]]
    1024              sage: G = PermutationGroup([[(1,2,3)],[(2,3,4)],[(3,4,5)]])
    1025              sage: G.strong_generating_system([5,4,3,2,1])             
    1026              [[(), (1,5,3,4,2), (1,5,4,3,2), (1,5)(2,3), (1,5,2)], [(), (1,3)(2,4), (1,2)(3,4), (1,4)(2,3)], [(), (1,3,2), (1,2,3)], [()], [()]]
    1027              sage: G = PermutationGroup([[(3,4)]])
    1028              sage: G.strong_generating_system()
    1029              [[()], [()], [(), (3,4)], [()]]
    1030              sage: G.strong_generating_system(base_of_group=[3,1,2,4])
    1031              [[(), (3,4)], [()], [()], [()]]
    1032              sage: G = TransitiveGroup(12,17)                # optional
    1033              sage: G.strong_generating_system()              # optional
    1034              [[(), (1,4,11,2)(3,6,5,8)(7,10,9,12), (1,8,3,2)(4,11,10,9)(5,12,7,6), (1,7)(2,8)(3,9)(4,10)(5,11)(6,12), (1,12,7,2)(3,10,9,8)(4,11,6,5), (1,11)(2,8)(3,5)(4,10)(6,12)(7,9), (1,10,11,8)(2,3,12,5)(4,9,6,7), (1,3)(2,8)(4,10)(5,7)(6,12)(9,11), (1,2,3,8)(4,9,10,11)(5,6,7,12), (1,6,7,8)(2,3,4,9)(5,10,11,12), (1,5,9)(3,11,7), (1,9,5)(3,7,11)], [(), (2,6,10)(4,12,8), (2,10,6)(4,8,12)], [()], [()], [()], [()], [()], [()], [()], [()], [()], [()]]
    1035          """
    1036          sgs = []
    1037          stab = self
    1038          if base_of_group == None:
    1039               base_of_group = range(1,self.degree()+1)
    1040          for j in base_of_group:
    1041               sgs.append(stab.transversals(j))
    1042               stab = stab.stabilizer(j)
    1043          return sgs
     1053        Then the algorithm returns `[ G_i.\mathrm{transversals}(\mathrm{pos}_{i+1})]_{1 \leq i \leq n}`
     1054
     1055        INPUT:
     1056
     1057        - ``base_of_group`` (optional) -- default: ``[1, 2, 3, ..., d]``
     1058          -- a list containing the integers
     1059          `1, 2, \dots , d` in any order (`d` is the degree of ``self``)
     1060
     1061        OUTPUT:
     1062
     1063        - A list of lists of permutations from the group, which form a strong
     1064          generating system.
     1065
     1066        TESTS::
     1067
     1068            sage: G = SymmetricGroup(10)
     1069            sage: H = PermutationGroup([G.random_element() for i in range(randrange(1,3,1))])
     1070            sage: prod(map(lambda x : len(x), H.strong_generating_system()),1) == H.cardinality()
     1071            True
     1072
     1073        EXAMPLES::
     1074
     1075            sage: G = PermutationGroup([[(7,8)],[(3,4)],[(4,5)]])
     1076            sage: G.strong_generating_system()
     1077            [[()], [()], [(), (3,4,5), (3,5)], [(), (4,5)], [()], [()], [(), (7,8)], [()]]
     1078            sage: G = PermutationGroup([[(1,2,3,4)],[(1,2)]])
     1079            sage: G.strong_generating_system()
     1080            [[(), (1,2)(3,4), (1,3)(2,4), (1,4)(2,3)], [(), (2,3,4), (2,4,3)], [(), (3,4)], [()]]
     1081            sage: G = PermutationGroup([[(1,2,3)],[(4,5,7)],[(1,4,6)]])
     1082            sage: G.strong_generating_system()                         
     1083            [[(), (1,2,3), (1,4,6), (1,3,2), (1,5,7,4,6), (1,6,4), (1,7,5,4,6)], [(), (2,6,3), (2,3,6), (2,5,6,3)(4,7), (2,7,5,6,3), (2,4,5,6,3)], [(), (3,6)(5,7), (3,5,6), (3,7,4,5,6), (3,4,7,5,6)], [(), (4,5)(6,7), (4,7)(5,6), (4,6)(5,7)], [(), (5,6,7), (5,7,6)], [()], [()]]
     1084            sage: G = PermutationGroup([[(1,2,3)],[(2,3,4)],[(3,4,5)]])
     1085            sage: G.strong_generating_system([5,4,3,2,1])             
     1086            [[(), (1,5,3,4,2), (1,5,4,3,2), (1,5)(2,3), (1,5,2)], [(), (1,3)(2,4), (1,2)(3,4), (1,4)(2,3)], [(), (1,3,2), (1,2,3)], [()], [()]]
     1087            sage: G = PermutationGroup([[(3,4)]])
     1088            sage: G.strong_generating_system()
     1089            [[()], [()], [(), (3,4)], [()]]
     1090            sage: G.strong_generating_system(base_of_group=[3,1,2,4])
     1091            [[(), (3,4)], [()], [()], [()]]
     1092            sage: G = TransitiveGroup(12,17)                # optional
     1093            sage: G.strong_generating_system()              # optional
     1094            [[(), (1,4,11,2)(3,6,5,8)(7,10,9,12), (1,8,3,2)(4,11,10,9)(5,12,7,6), (1,7)(2,8)(3,9)(4,10)(5,11)(6,12), (1,12,7,2)(3,10,9,8)(4,11,6,5), (1,11)(2,8)(3,5)(4,10)(6,12)(7,9), (1,10,11,8)(2,3,12,5)(4,9,6,7), (1,3)(2,8)(4,10)(5,7)(6,12)(9,11), (1,2,3,8)(4,9,10,11)(5,6,7,12), (1,6,7,8)(2,3,4,9)(5,10,11,12), (1,5,9)(3,11,7), (1,9,5)(3,7,11)], [(), (2,6,10)(4,12,8), (2,10,6)(4,8,12)], [()], [()], [()], [()], [()], [()], [()], [()], [()], [()]]
     1095        """
     1096        sgs = []
     1097        stab = self
     1098        if base_of_group is None:
     1099            base_of_group = self.set()
     1100        for j in base_of_group:
     1101            sgs.append(stab.transversals(j))
     1102            stab = stab.stabilizer(j)
     1103        return sgs
     1104
    10441105
    10451106    def _repr_(self):
    10461107        r"""
    class PermutationGroup_generic(group.Gro 
    10991160            sage: G.order()
    11001161            1
    11011162        """
    1102         G = self
    1103         if G.gens()==[] or G.gens()==[G(1)]:
     1163        if not self.gens() or self.gens() == [self(1)]:
    11041164            return Integer(1)
    11051165        return Integer(self._gap_().Size())
    11061166
    class PermutationGroup_generic(group.Gro 
    11201180            ()
    11211181        """
    11221182        current_randstate().set_seed_gap()
    1123 
    1124         return self._element_class()(self._gap_().Random(),
    1125                                        self, check=False)
     1183        return self(self._gap_().Random(), check=False)
    11261184
    11271185    def group_id(self):
    11281186        """
    class PermutationGroup_generic(group.Gro 
    11351193            sage: G.group_id()    # optional - database_gap
    11361194            [12, 4]
    11371195        """
    1138         return [Integer(n) for n in eval(str(self._gap_().IdGroup()))]
     1196        return [Integer(n) for n in self._gap_().IdGroup()]
    11391197
    11401198    def id(self):
    11411199        """
    class PermutationGroup_generic(group.Gro 
    11651223            sage: G.center()
    11661224            Permutation Group with generators [()]
    11671225        """
    1168         C = self._gap_().Center()
    1169         return PermutationGroup(gap_group=C)
     1226        return PermutationGroup(gap_group=self._gap_().Center())
    11701227
    11711228    def intersection(self, other):
    11721229        r"""
    class PermutationGroup_generic(group.Gro 
    13081365            raise TypeError("{0} does not convert to a permutation group element".format(g))
    13091366        return PermutationGroup(gap_group=gap.ConjugateGroup(self, g))
    13101367
    1311     def direct_product(self,other,maps=True):
     1368    def direct_product(self, other, maps=True):
    13121369        """
    13131370        Wraps GAP's ``DirectProduct``, ``Embedding``, and ``Projection``.
    13141371       
    class PermutationGroup_generic(group.Gro 
    13531410            sage: D,iota1,iota2,pr1,pr2 = G.direct_product(G)
    13541411            sage: D; iota1; iota2; pr1; pr2
    13551412            Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
    1356             Homomorphism : Cyclic group of order 4 as a permutation group --> Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
    1357             Homomorphism : Cyclic group of order 4 as a permutation group --> Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
    1358             Homomorphism : Permutation Group with generators [(1,2,3,4), (5,6,7,8)] --> Cyclic group of order 4 as a permutation group
    1359             Homomorphism : Permutation Group with generators [(1,2,3,4), (5,6,7,8)] --> Cyclic group of order 4 as a permutation group
    1360        
    1361         ::
    1362        
     1413            Permutation group morphism:
     1414              From: Cyclic group of order 4 as a permutation group
     1415              To:   Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
     1416              Defn: Embedding( Group( [ (1,2,3,4), (5,6,7,8) ] ), 1 )
     1417            Permutation group morphism:
     1418              From: Cyclic group of order 4 as a permutation group
     1419              To:   Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
     1420              Defn: Embedding( Group( [ (1,2,3,4), (5,6,7,8) ] ), 2 )
     1421            Permutation group morphism:
     1422              From: Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
     1423              To:   Cyclic group of order 4 as a permutation group
     1424              Defn: Projection( Group( [ (1,2,3,4), (5,6,7,8) ] ), 1 )
     1425            Permutation group morphism:
     1426              From: Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
     1427              To:   Cyclic group of order 4 as a permutation group
     1428              Defn: Projection( Group( [ (1,2,3,4), (5,6,7,8) ] ), 2 )
    13631429            sage: g=D([(1,3),(2,4)]); g
    13641430            (1,3)(2,4)
    13651431            sage: d=D([(1,4,3,2),(5,7),(6,8)]); d
    class PermutationGroup_generic(group.Gro 
    13701436            (1,4,3,2)
    13711437            (1,3)(2,4)
    13721438        """
    1373         from sage.groups.perm_gps.permgroup_morphism import PermutationGroupMorphism_from_gap
    1374         G1 = self._gap_init_()
    1375         G2 = other._gap_init_()
    1376         cmd1 = "G:=DirectProduct("+G1+","+G2+")"
    1377         cmd2 = "iota1:=Embedding(G,1)"
    1378         cmd3 = "iota2:=Embedding(G,2)"
    1379         cmd4 = "pr1:=Projection(G,1)"
    1380         cmd5 = "pr2:=Projection(G,2)"
    1381         if not(maps):
    1382             return PermutationGroup(gap_group=gap.eval(cmd1))
     1439        G = self._gap_().DirectProduct(other._gap_())
     1440        D = PermutationGroup(gap_group=G)
     1441        if not maps:
     1442            return D
    13831443        else:
    1384             D = PermutationGroup_generic(gap_group=gap.eval(cmd1))
    1385             iota1 = PermutationGroupMorphism_from_gap(self,D, cmd2, "iota1")
    1386             iota2 = PermutationGroupMorphism_from_gap(other,D, cmd3, "iota2")
    1387             pr1 = PermutationGroupMorphism_from_gap(D,self, cmd4, "pr1")
    1388             pr2 = PermutationGroupMorphism_from_gap(D,other, cmd5, "pr2")
    1389             return D,iota1,iota2,pr1,pr2
     1444            from sage.groups.perm_gps.permgroup_morphism import PermutationGroupMorphism_from_gap
     1445            iota1 = PermutationGroupMorphism_from_gap(self,  D, G.Embedding(1))
     1446            iota2 = PermutationGroupMorphism_from_gap(other, D, G.Embedding(2))
     1447            pr1 = PermutationGroupMorphism_from_gap(D, self, G.Projection(1))
     1448            pr2 = PermutationGroupMorphism_from_gap(D, other, G.Projection(2))
     1449            return D, iota1, iota2, pr1, pr2
    13901450
    13911451    def subgroup(self, gens):
    13921452        """
    class PermutationGroup_generic(group.Gro 
    14061466    def quotient(self, N):
    14071467        """
    14081468        Returns the quotient of this permutation group by the normal
    1409         subgroup `N`.
     1469        subgroup `N`, as a permutation group.
    14101470
    14111471        Wraps the GAP operator "/".
    1412        
     1472
    14131473        EXAMPLES::
    1414        
     1474
    14151475            sage: G = PermutationGroup([(1,2,3), (2,3)])
    14161476            sage: N = PermutationGroup([(1,2,3)])
    14171477            sage: G.quotient(N)
    14181478            Permutation Group with generators [(1,2)]
     1479            sage: G.quotient(G)
     1480            Permutation Group with generators [()]
    14191481        """
    1420         G = self
    1421         gap.eval("G := %s"%G._gap_().name())
    1422         gap.eval("N := %s"%N._gap_().name())
    1423         gap.eval("Q := G/N;")
    1424         gap.eval("phi := RegularActionHomomorphism( Q );")
    1425         gap.eval("gens := GeneratorsOfGroup( Image( phi ));")
    1426         n = Integer(gap.eval("n := Length(gens);"))
    1427         if n>0:
    1428             gens = [self._element_class()(gap.eval("gens[%s];"%i)) for i in range(1,n+1)]
    1429             Q = PermutationGroup(gens)
    1430             return Q
    1431         else:
    1432             return PermutationGroup([()])
     1482        Q = self._gap_() / N._gap_()
     1483        # Return Q as a permutation group
     1484        # This is currently done using the right regular representation
     1485        # FIXME: GAP certainly knows of a better way!
     1486        phi = Q.RegularActionHomomorphism()
     1487        return PermutationGroup(gap_group = phi.Image())
    14331488
    14341489    def quotient_group(self, N):
    14351490        """
    class PermutationGroup_generic(group.Gro 
    14511506            doctest:...: DeprecationWarning: quotient_group() is deprecated; use quotient() instead.
    14521507            Permutation Group with generators [(1,2)]
    14531508        """
    1454         import warnings
    1455         warnings.warn('quotient_group() is deprecated; use quotient() instead.', DeprecationWarning, stacklevel=2)
    14561509        from sage.misc.misc import deprecation
    14571510        deprecation('quotient_group() is deprecated; use quotient() instead.')
    1458 
    14591511        return self.quotient(N)
    14601512
    14611513    def commutator(self, other=None):
    class PermutationGroup_generic(group.Gro 
    15571609                raise TypeError("{0} is not a permutation group".format(other))
    15581610            return PermutationGroup(gap_group=gap.CommutatorSubgroup(self, other))
    15591611
     1612    @hap_decorator
    15601613    def cohomology(self, n, p = 0):
    15611614        r"""
    15621615        Computes the group cohomology `H^n(G, F)`, where `F = \ZZ`
    class PermutationGroup_generic(group.Gro 
    15981651        - D. Joyner, 'A primer on computational group homology and
    15991652          cohomology', http://front.math.ucdavis.edu/0706.0549.
    16001653        """
    1601         if not is_package_installed('gap_packages'):
    1602              raise RuntimeError, "You must install the optional gap_packages package."
    1603         load_hap()
    1604         from sage.rings.arith import is_prime
    1605         if not (p == 0 or is_prime(p)):
    1606             raise ValueError, "p must be 0 or prime"
    1607         G = self
    1608         GG = G._gap_init_()
    16091654        if p == 0:
    1610             L = eval(gap.eval("GroupCohomology(%s,%s)"%(GG,n)))
     1655            L = self._gap_().GroupCohomology(n).sage()
    16111656        else:
    1612             L = eval(gap.eval("GroupCohomology(%s,%s,%s)"%(GG,n,p)))
    1613         return AbelianGroup(len(L),L)
    1614 
     1657            L = self._gap_().GroupCohomology(n, p).sage()
     1658        return AbelianGroup(len(L), L)
     1659
     1660    @hap_decorator
    16151661    def cohomology_part(self, n, p = 0):
    16161662        """
    16171663        Computes the p-part of the group cohomology `H^n(G, F)`,
    class PermutationGroup_generic(group.Gro 
    16351681
    16361682        - David Joyner and Graham Ellis
    16371683        """
    1638         if not is_package_installed('gap_packages'):
    1639              raise RuntimeError, "You must install the optional gap_packages package."
    1640         load_hap()
    1641         from sage.rings.arith import is_prime
    1642         if not (p == 0 or is_prime(p)):
    1643             raise ValueError, "p must be 0 or prime"
    1644         G = self
    1645         GG = G._gap_init_()
    16461684        if p == 0:
    1647             H = AbelianGroup(1,[1])
     1685            return AbelianGroup(1, [1])
    16481686        else:
    1649             gap.eval("S := SylowSubgroup(%s,%s)"%(GG,p))
    1650             gap.eval("R:=ResolutionFiniteGroup(S,%s)"%(n+1))
    1651             gap.eval("HR:=HomToIntegers(R)")
    1652             L = eval(gap.eval("Cohomology(HR,%s)"%n))
    1653         return AbelianGroup(len(L),L)
    1654 
     1687            G = self._gap_()
     1688            S = G.SylowSubgroup(p)
     1689            R = S.ResolutionFiniteGroup(n+1)
     1690            HR = R.HomToIntegers()
     1691            L = HR.Cohomology(n).sage()
     1692            return AbelianGroup(len(L), L)
     1693
     1694    @hap_decorator
    16551695    def homology(self, n, p = 0):
    16561696        r"""
    16571697        Computes the group homology `H_n(G, F)`, where
    class PermutationGroup_generic(group.Gro 
    16931733        - D. Joyner, "A primer on computational group homology and cohomology",
    16941734          http://front.math.ucdavis.edu/0706.0549
    16951735        """
    1696         if not is_package_installed('gap_packages'):
    1697              raise RuntimeError, "You must install the optional gap_packages package."
    1698         load_hap()
    1699         from sage.rings.arith import is_prime
    1700         if not (p == 0 or is_prime(p)):
    1701             raise ValueError, "p must be 0 or prime"
    1702         G = self
    1703         GG = G._gap_init_()
    17041736        if p == 0:
    1705             L = eval(gap.eval("GroupHomology(%s,%s)"%(GG,n)))
     1737            L = self._gap_().GroupHomology(n).sage()
    17061738        else:
    1707             L = eval(gap.eval("GroupHomology(%s,%s,%s)"%(GG,n,p)))
    1708         return AbelianGroup(len(L),L)
    1709 
     1739            L = self._gap_().GroupHomology(n, p).sage()
     1740        return AbelianGroup(len(L), L)
     1741
     1742    @hap_decorator
    17101743    def homology_part(self, n, p = 0):
    17111744        r"""
    17121745        Computes the `p`-part of the group homology
    class PermutationGroup_generic(group.Gro 
    17271760
    17281761        - David Joyner and Graham Ellis
    17291762        """
    1730         if not is_package_installed('gap_packages'):
    1731              raise RuntimeError, "You must install the optional gap_packages package."
    1732         gap.eval('LoadPackage("hap")')
    1733         from sage.rings.arith import is_prime
    1734         if not (p == 0 or is_prime(p)):
    1735             raise ValueError, "p must be 0 or prime"
    1736         G = self
    1737         GG = G._gap_init_()
    17381763        if p == 0:
    1739             H = AbelianGroup(1,[1])
     1764            return AbelianGroup(1, [1])
    17401765        else:
    1741             gap.eval("S := SylowSubgroup(%s,%s)"%(GG,p))
    1742             gap.eval("R:=ResolutionFiniteGroup(S,%s)"%(n+1))
    1743             gap.eval("TR:=TensorWithIntegers(R);")
    1744             L = eval(gap.eval("Homology(TR,%s)"%n))
    1745         return AbelianGroup(len(L),L)
     1766            S = self._gap_().SylowSubgroup(p)
     1767            R = S.ResolutionFiniteGroup(n+1)
     1768            TR = R.TensorWithIntegers()
     1769            L = TR.Homology(n).sage()
     1770            return AbelianGroup(len(L), L)
    17461771
    17471772    def character_table(self):
    17481773        r"""
    class PermutationGroup_generic(group.Gro 
    18271852        cl   = G.ConjugacyClasses()
    18281853        n    = Integer(cl.Length())
    18291854        irrG = G.Irr()
    1830         ct   = [[irrG[i+1,j+1] for j in range(n)] for i in range(n)]
     1855        ct   = [[irrG[i+1, j+1] for j in range(n)] for i in range(n)]
    18311856
    18321857        from sage.rings.all import CyclotomicField
    18331858        e = irrG.Flat().Conductor()
    class PermutationGroup_generic(group.Gro 
    18361861
    18371862        # Finally return the result as a matrix.
    18381863        from sage.matrix.all import MatrixSpace
    1839         MS = MatrixSpace(K,n)
     1864        MS = MatrixSpace(K, n)
    18401865        return MS(ct)
    18411866
    18421867    def irreducible_characters(self):
    class PermutationGroup_generic(group.Gro 
    18491874            sage: [x.values() for x in irr]
    18501875            [[1, -1, 1], [2, 0, -1], [1, 1, 1]]
    18511876        """
    1852         Irr = self._gap_().Irr()
    1853         L = []
    1854         for irr in Irr:
    1855             L.append(ClassFunction(self, irr))
    1856         return L
     1877        return [ClassFunction(self, irr) for irr in self._gap_().Irr()]
    18571878
    18581879    def trivial_character(self):
    18591880        r"""
    class PermutationGroup_generic(group.Gro 
    18641885            sage: SymmetricGroup(3).trivial_character()
    18651886            Character of Symmetric group of order 3! as a permutation group
    18661887        """
    1867         values = [1]*Integer(self._gap_().NrConjugacyClasses())
     1888        values = [1]*self._gap_().NrConjugacyClasses().sage()
    18681889        return self.character(values)
    18691890
    18701891    def character(self, values):
    class PermutationGroup_generic(group.Gro 
    18801901            sage: G.character([1]*n)
    18811902            Character of Alternating group of order 4!/2 as a permutation group
    18821903        """
    1883         return ClassFunction(self,values)
     1904        return ClassFunction(self, values)
    18841905
    18851906    def conjugacy_classes_representatives(self):
    18861907        """
    class PermutationGroup_generic(group.Gro 
    18981919        ::
    18991920       
    19001921            sage: G = SymmetricGroup(5)
    1901             sage: G.conjugacy_classes_representatives ()
     1922            sage: G.conjugacy_classes_representatives()
    19021923            [(), (1,2), (1,2)(3,4), (1,2,3), (1,2,3)(4,5), (1,2,3,4), (1,2,3,4,5)]
    19031924       
    19041925        AUTHORS:
    class PermutationGroup_generic(group.Gro 
    19061927        - David Joyner and William Stein (2006-01-04)
    19071928        """
    19081929        cl = self._gap_().ConjugacyClasses()
    1909         n = Integer(cl.Length())
    1910         L = gap("List([1..Length(%s)], i->Representative(%s[i]))"%(
    1911             cl.name(),  cl.name()))
    1912         return [self._element_class()(L[i], self, check=False) \
    1913                 for i in range(1,n+1)]
     1930        return [self(rep.Representative(), check=False) for rep in cl]
    19141931
    19151932    def conjugacy_classes_subgroups(self):
    19161933        """
    class PermutationGroup_generic(group.Gro 
    19451962
    19461963        - David Joyner (2006-10)
    19471964        """
    1948         G = self._gap_()
    1949         cl = G.ConjugacyClassesSubgroups()
    1950         n = Integer(cl.Length())
    1951         L = gap("List([1..Length(%s)], i->Representative(%s[i]))"%(
    1952             cl.name(),  cl.name()))
    1953         return [PermutationGroup(gap_group=L[i])for i in range(1,n+1)]
     1965        cl = self._gap_().ConjugacyClassesSubgroups()
     1966        return [PermutationGroup(gap_group=sub.Representative()) for sub in cl]
    19541967       
    19551968    def subgroups(self):
    19561969        r"""
    class PermutationGroup_generic(group.Gro 
    23092322        """
    23102323        return self._gap_().IsElementaryAbelian().bool()
    23112324   
    2312     def isomorphism_to(self,right):
     2325    def isomorphism_to(self, right):
    23132326        """
    23142327        Return an isomorphism from ``self`` to ``right`` if the groups
    23152328        are isomorphic, otherwise ``None``.
    class PermutationGroup_generic(group.Gro 
    23352348            sage: G = PermutationGroup([(1,2,3), (2,3)])
    23362349            sage: H = PermutationGroup([(1,2,4), (1,4)])
    23372350            sage: G.isomorphism_to(H)
    2338             Homomorphism : Permutation Group with generators [(2,3), (1,2,3)] --> Permutation Group with generators [(1,2,4), (1,4)]
     2351            Permutation group morphism:
     2352              From: Permutation Group with generators [(2,3), (1,2,3)]
     2353              To:   Permutation Group with generators [(1,2,4), (1,4)]
     2354              Defn: [(2,3), (1,2,3)] -> [(2,4), (1,2,4)]
    23392355        """
    23402356        current_randstate().set_seed_gap()
    2341 
    23422357        if not isinstance(right, PermutationGroup_generic):
    23432358            raise TypeError, "right must be a permutation group"
    2344         G = self._gap_init_()
    2345         H = right._gap_init_()
    2346         gap.eval("x:=IsomorphismGroups( %s, %s )"%(G,H))
    2347         s = gap.eval("x")
    2348         if s == "fail":
     2359       
     2360        iso = self._gap_().IsomorphismGroups(right)
     2361        if str(iso) == "fail":
    23492362            return None
    2350         # slice and dice the GAP return to build a Sage group homomorphism
    2351         src, dst = s.split("->")
    2352         # we eval to get things as lists
    2353         srcs = from_gap_list(self, src)
    2354         dsts = from_gap_list(right, dst)
     2363       
     2364        dsts = [right(iso.Image(x), check=False) for x in self.gens()]
     2365       
    23552366        from permgroup_morphism import PermutationGroupMorphism_im_gens
    2356         return PermutationGroupMorphism_im_gens(self, right, srcs, dsts)
     2367        return PermutationGroupMorphism_im_gens(self, right, dsts)
    23572368
    23582369    def is_isomorphic(self, right):
    23592370        """
    class PermutationGroup_generic(group.Gro 
    23862397        """
    23872398        if not isinstance(right, PermutationGroup_generic):
    23882399            raise TypeError, "right must be a permutation group"
    2389         G = self._gap_()
    2390         H = right._gap_()
    2391         return gap.eval("IsomorphismGroups( %s, %s )"%(G.name(),H.name())) != "fail"
    2392 
     2400        iso = self._gap_().IsomorphismGroups(right)
     2401        return str(iso) != 'fail'
     2402       
    23932403    def is_monomial(self):
    23942404        """
    23952405        Returns ``True`` if the group is monomial. A finite group is monomial
    class PermutationGroup_generic(group.Gro 
    24332443            False
    24342444        """
    24352445        if not(self.is_subgroup(other)):
    2436             raise TypeError("%s must be a subgroup of %s"%(self,other))
     2446            raise TypeError("%s must be a subgroup of %s"%(self, other))
    24372447        return other._gap_().IsNormal(self._gap_()).bool()
    24382448   
    24392449    def is_perfect(self):
    class PermutationGroup_generic(group.Gro 
    25092519        """
    25102520        return self._gap_().IsSolvableGroup().bool()
    25112521   
    2512     def is_subgroup(self,other):
     2522    def is_subgroup(self, other):
    25132523        """
    25142524        Returns ``True`` if ``self`` is a subgroup of ``other``.
    25152525       
    class PermutationGroup_generic(group.Gro 
    25672577            sage: gap(G).IsTransitive()
    25682578            true
    25692579        """
    2570         return self._gap_().IsTransitive('[1..%s]'%self.degree()).bool()
     2580        return self._gap_().IsTransitive(self._set_gap()).bool()
    25712581   
    2572     def normalizes(self,other):
     2582    def normalizes(self, other):
    25732583        r"""
    25742584        Returns ``True`` if the group ``other`` is normalized by ``self``.
    25752585        Wraps GAP's ``IsNormal`` function.
    class PermutationGroup_generic(group.Gro 
    26202630            Permutation Group with generators [()]
    26212631        """
    26222632        current_randstate().set_seed_gap()
    2623         ans = []
    2624         DS = self._gap_().CompositionSeries()
    2625         n = DS.Length()
    2626         for i in range(1,n+1):
    2627             ans.append(PermutationGroup(DS[i].GeneratorsOfGroup()))
    2628         return ans
     2633        CS = self._gap_().CompositionSeries()
     2634        return [PermutationGroup(gap_group=group) for group in CS]
    26292635
    26302636    def derived_series(self):
    26312637        """
    class PermutationGroup_generic(group.Gro 
    26452651            [Permutation Group with generators [(1,2,3)(4,5), (3,4)], Permutation Group with generators [(1,5)(3,4), (1,5)(2,4), (2,4)(3,5)]]
    26462652        """
    26472653        current_randstate().set_seed_gap()
    2648         ans = []
    26492654        DS = self._gap_().DerivedSeries()
    2650         n = DS.Length()
    2651         for i in range(1,n+1):
    2652             ans.append(PermutationGroup(DS[i].GeneratorsOfGroup()))
    2653         return ans
    2654    
     2655        return [PermutationGroup(gap_group=group) for group in DS]   
     2656
    26552657    def lower_central_series(self):
    26562658        """
    26572659        Return the lower central series of this group as a list of
    class PermutationGroup_generic(group.Gro 
    26702672            [Permutation Group with generators [(1,2,3)(4,5), (3,4)], Permutation Group with generators [(1,5)(3,4), (1,5)(2,3), (1,3)(2,4)]]
    26712673        """
    26722674        current_randstate().set_seed_gap()
    2673         ans = []
    2674         DS = self._gap_().LowerCentralSeriesOfGroup()
    2675         n = DS.Length()
    2676         for i in range(1,n+1):
    2677             ans.append(PermutationGroup(DS[i].GeneratorsOfGroup()))
    2678         return ans
     2675        LCS = self._gap_().LowerCentralSeriesOfGroup()
     2676        return [PermutationGroup(gap_group=group) for group in LCS]   
    26792677
    26802678    def molien_series(self):
    26812679        r"""
    class PermutationGroup_generic(group.Gro 
    27052703            sage: G.molien_series()     
    27062704            1/(-x^6 + x^5 + x^4 - x^2 - x + 1)
    27072705        """
    2708         G = self
    2709         GG = G._gap_init_()
    2710         gap.eval("pi := NaturalCharacter( %s )"%GG)
    2711         gap.eval("cc := ConstituentsOfCharacter( pi )")
    2712         M = gap.eval("M := MolienSeries(Sum(cc))")
    2713         R = PolynomialRing(RationalField(),"x")
    2714         x = R.gen()
    2715         nn = gap.eval("NumeratorOfRationalFunction(M)")
    2716         dd = gap.eval("DenominatorOfRationalFunction(M)")
    2717         FF = FractionField(R)
    2718         return FF(nn.replace("_1",""))/FF(dd.replace("_1",""))
     2706        pi = self._gap_().NaturalCharacter()
     2707        cc = pi.ConstituentsOfCharacter()
     2708        M = cc.Sum().MolienSeries()
     2709
     2710        R = QQ['x']
     2711        nn = M.NumeratorOfRationalFunction()
     2712        dd = M.DenominatorOfRationalFunction()
     2713        return (R(str(nn).replace("_1","")) /
     2714                R(str(dd).replace("_1","")))
    27192715   
    27202716    def normal_subgroups(self):
    27212717        """
    class PermutationGroup_generic(group.Gro 
    27392735            sage: NH[2].is_isomorphic(G)
    27402736            True
    27412737        """
    2742         ans = []
    27432738        NS = self._gap_().NormalSubgroups()
    2744         n = NS.Length()
    2745         for i in range(1,n+1):
    2746             ans.append(PermutationGroup(NS[i].GeneratorsOfGroup()))
    2747         return ans
     2739        return [PermutationGroup(gap_group=group) for group in NS]
    27482740
    27492741    def poincare_series(self, p=2, n=10):
    27502742        """
    class PermutationGroup_generic(group.Gro 
    27722764        - David Joyner and Graham Ellis
    27732765        """
    27742766        if not is_package_installed('gap_packages'):
    2775              raise RuntimeError, "You must install the optional gap_packages package."
     2767            raise RuntimeError, "You must install the optional gap_packages package."
    27762768        load_hap()
    27772769        from sage.rings.arith import is_prime
    27782770        if not (p == 0 or is_prime(p)):
    27792771            raise ValueError, "p must be 0 or prime"
    2780         G = self
    2781         GG = G._gap_init_()
    2782         ff = gap.eval("ff := PoincareSeriesPrimePart(%s,%s,%s)"%(GG,p,n))
    2783         R = PolynomialRing(RationalField(),"x")
    2784         x = R.gen()
    2785         nn = gap.eval("NumeratorOfRationalFunction(ff)").replace("x_1","x")
    2786         dd = gap.eval("DenominatorOfRationalFunction(ff)").replace("x_1","x")
    2787         FF = FractionField(R)
    2788         return FF(nn)/FF(dd)
     2772
     2773        ff = self._gap_().PoincareSeriesPrimePart(p, n)
     2774        R = QQ['x']
     2775        nn = ff.NumeratorOfRationalFunction()
     2776        dd = ff.DenominatorOfRationalFunction()
     2777        return (R(str(nn).replace('x_1', 'x')) /
     2778                R(str(dd).replace('x_1', 'x')))
    27892779
    27902780
    27912781    def sylow_subgroup(self, p):
    class PermutationGroup_generic(group.Gro 
    28022792            sage: G.sylow_subgroup(5)
    28032793            Permutation Group with generators [()]
    28042794        """
    2805         G = self
    2806         gap.eval("G := %s"%G._gap_init_())
    2807         gap.eval("Ssgp := SylowSubgroup(G, %s);"%p)
    2808         gap.eval("gens := GeneratorsOfGroup( Ssgp );")
    2809         N = Integer(gap.eval("N := Length(gens);"))
    2810         if N>0:
    2811             gens = [self._element_class()(gap.eval("gens[%s];"%j)) for j in range(1,N+1)]
    2812             H = PermutationGroup(gens)
    2813         else:
    2814             H = PermutationGroup([()])
    2815         return H
    2816 
     2795        return PermutationGroup(gap_group=self._gap_().SylowSubgroup(p))
    28172796       
    28182797    def upper_central_series(self):
    28192798        """
    class PermutationGroup_generic(group.Gro 
    28232802        EXAMPLES:
    28242803
    28252804        These computations use pseudo-random numbers, so we set
    2826         the seed for reproducible testing.
    2827        
    2828         ::
    2829        
     2805        the seed for reproducible testing::
     2806
    28302807            sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])
    28312808            sage: G.upper_central_series()
    28322809            [Permutation Group with generators [()]]
    28332810        """
    28342811        current_randstate().set_seed_gap()
    2835         ans = []
    2836         DS = self._gap_().UpperCentralSeriesOfGroup()
    2837         n = DS.Length()
    2838         for i in range(1,n+1):
    2839             ans.append(PermutationGroup(gap_group=DS[i]))
    2840         return ans
     2812        UCS = self._gap_().UpperCentralSeriesOfGroup()
     2813        return [PermutationGroup(gap_group=group) for group in UCS]
    28412814
    28422815class PermutationGroup_subgroup(PermutationGroup_generic):
    28432816    """
    class PermutationGroup_subgroup(Permutat 
    29902963        if not isinstance(other, PermutationGroup_generic):
    29912964            return -1
    29922965        c = PermutationGroup_generic.__cmp__(self, other)
    2993         if c: return c
     2966        if c:
     2967            return c
    29942968        if hasattr(other, 'ambient_group'):
    2995              o_ambient = other.ambient_group()
     2969            o_ambient = other.ambient_group()
    29962970        else:
    2997              o_ambient = other
    2998         return cmp(self.ambient_group(),o_ambient)
     2971            o_ambient = other
     2972        return cmp(self.ambient_group(), o_ambient)
    29992973
    30002974    def _repr_(self):
    30012975        r"""
  • sage/groups/perm_gps/permgroup_morphism.py

    diff --git a/sage/groups/perm_gps/permgroup_morphism.py b/sage/groups/perm_gps/permgroup_morphism.py
    a b AUTHORS: 
    1111EXAMPLES::
    1212
    1313    sage: G = CyclicPermutationGroup(4)
    14     sage: gens = G.gens()
    1514    sage: H = DihedralGroup(4)
    1615    sage: g = G([(1,2,3,4)])
    17     sage: phi = PermutationGroupMorphism_im_gens( G, H, gens, gens)
     16    sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))
    1817    sage: phi.image(G)
    1918    Permutation Group with generators [(1,2,3,4)]
    2019    sage: phi.kernel()
    EXAMPLES:: 
    2322    (1,2,3,4)
    2423    sage: phi(g)                       
    2524    (1,2,3,4)
    26     sage: phi.range()
     25    sage: phi.codomain()
    2726    Dihedral group of order 8 as a permutation group
    2827    sage: phi.codomain()
    2928    Dihedral group of order 8 as a permutation group
    EXAMPLES:: 
    3837#                  http://www.gnu.org/licenses/
    3938#*****************************************************************************
    4039
    41 
    42 import random
    43 
    44 import sage.structure.element as element
    45 import sage.groups.group as group
    46 from sage.categories.morphism import *
    47 
    48 from sage.rings.all      import RationalField, Integer
    49 from sage.matrix.all     import MatrixSpace
    50 from sage.interfaces.all import gap, is_GapElement, is_ExpectElement
     40from sage.misc.misc import deprecation
     41from sage.categories.morphism import Morphism
    5142from sage.groups.perm_gps.permgroup_element import PermutationGroupElement
    5243from sage.groups.perm_gps.permgroup import PermutationGroup, PermutationGroup_generic
    5344
    54 def gap_format(x):
    55     """
    56     Put a permutation in Gap format, as a string.
    57     """
    58     x = str(x).replace(' ','')
    59     return x.replace('),(',')(').replace('[','').replace(']','')
    60 
    61 def is_PermutationGroupMorphism(f):
    62     return isinstance(f, PermutationGroupMorphism);
    63 
    64 class PermutationGroupMap(Morphism):
     45class PermutationGroupMorphism(Morphism):
    6546    """
    6647    A set-theoretic map between PermutationGroups.
    6748    """
    68     def __init__(self, parent):
    69         Morphism.__init__(self, parent)
     49    def _repr_type(self):
     50        """
     51        Returns the type of this morphism.  This is used for printing
     52        the morphism.
    7053
    71     def _repr_type(self):
    72         return "PermutationGroup"
     54        EXAMPLES::
    7355
    74 class PermutationGroupMorphism_id:
    75     """
    76     TODO: NOT FINISHED YET!! Return the identity homomorphism from X to
    77     itself.
    78    
    79     EXAMPLES:
    80     """
    81     def __init__(self, X):
    82         PermutationGroupMorphism.__init__(self, X.Hom(X))
    83        
    84     def _repr_defn(self):
    85         return "Identity map of "+str(X)
    86 
    87 class PermutationGroupMorphism_from_gap:
    88     """
    89     This is a Python trick to allow Sage programmers to create a group
    90     homomorphism using GAP using very general constructions. An example
    91     of its usage is in the direct_product instance method of the
    92     PermutationGroup_generic class in permgroup.py.
    93    
    94     Basic syntax:
    95    
    96     PermutationGroupMorphism_from_gap(domain_group,
    97     range_group,'phi:=gap_hom_command;','phi') And don't forget the
    98     line: from sage.groups.perm_gps.permgroup_morphism import
    99     PermutationGroupMorphism_from_gap in your program.
    100    
    101     EXAMPLES::
    102    
    103         sage: from sage.groups.perm_gps.permgroup_morphism import PermutationGroupMorphism_from_gap
    104         sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])
    105         sage: H = G.subgroup([G([(1,2,3,4)])])
    106         sage: PermutationGroupMorphism_from_gap(H, G, 'phi:=Identity','phi')
    107         Homomorphism : Subgroup of Permutation Group with generators [(1,2)(3,4), (1,2,3,4)] generated by [(1,2,3,4)] --> Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]
    108     """
    109     def __init__(self, G, H, gap_hom_str, name="phi" ):
    110         self._domain = G
    111         self._codomain = H
    112         if not(isinstance(G, PermutationGroup_generic)):
    113             raise TypeError, "Sorry, the groups must be permutation groups."
    114         if not(isinstance(H, PermutationGroup_generic)):
    115             raise TypeError, "Sorry, the groups must be permutation groups."
    116         G0  = G._gap_init_()
    117         H0  = H._gap_init_()
    118         self.gap_hom_string = gap_hom_str
    119         self._name = name
    120         self.hom = gap.eval(gap_hom_str)
    121 
    122     def __repr__(self):
    123         return "Homomorphism : %s --> %s"%(self.domain(),self.range())
    124 
    125     def __str__(self):
    126         return "Homomorphism : %s --> %s"%(self.domain(),self.range())
    127 
    128     def _latex_(self):
    129         return self.domain()._latex_()+" \rightarrow "+self.range()._latex_()
    130 
    131     def domain(self):
    132         return self._domain
     56            sage: G = PSL(2,7)
     57            sage: D, iota1, iota2, pr1, pr2 = G.direct_product(G)
     58            sage: pr1._repr_type()
     59            'Permutation group'
     60        """
     61        return "Permutation group"
    13362
    13463    def range(self):
    135         return self._codomain
     64        """
     65        Returns the codomain of this morphism.  This method is
     66        deprecated.  Please use :meth:`codomain` instead.
    13667
    137     def codomain(self):
    138         return self._codomain
     68        EXAMPLES::
     69
     70            sage: G = PSL(2,7)
     71            sage: D, iota1, iota2, pr1, pr2 = G.direct_product(G)
     72            sage: pr1.range()
     73            doctest... DeprecationWarning: (Since Sage Version 5.0) range is deprecated. Please use codomain instead.
     74            Permutation Group with generators [(3,7,5)(4,8,6), (1,2,6)(3,4,8)]
     75        """
     76        deprecation('range is deprecated. Please use codomain instead.', 'Sage Version 5.0')
     77        return self.codomain()
    13978
    14079    def kernel(self):
    14180        """
    142         Computes the subgroup of the domain group which is the kernel of
    143         self.
    144        
     81        Returns the kernel of this homomorphism as a permutation group.
     82
    14583        EXAMPLES::
     84
     85            sage: G = CyclicPermutationGroup(4)
     86            sage: H = DihedralGroup(4)
     87            sage: g = G([(1,2,3,4)])
     88            sage: phi = PermutationGroupMorphism_im_gens(G, H, [1])
     89            sage: phi.kernel()
     90            Permutation Group with generators [(1,2,3,4)]
     91           
     92        ::
    14693       
    14794            sage: G = PSL(2,7)
    14895            sage: D = G.direct_product(G)
    class PermutationGroupMorphism_from_gap: 
    15198            sage: G.is_isomorphic(pr1.kernel())
    15299            True
    153100        """
    154         cmd = self.gap_hom_string
    155         gap.eval(cmd)
    156         gap_ker = gap.eval("Kernel("+self._name+")")
    157         return PermutationGroup(gap(gap_ker).GeneratorsOfGroup())
     101        return PermutationGroup(gap_group=self._gap_().Kernel())
    158102
    159103    def image(self, J):
    160104        """
    161         J must be an element or a subgroup of G. Computes the subgroup of H
    162         which is the image of J.
     105        J must be a subgroup of G. Computes the subgroup of H which is the
     106        image of J.
    163107       
    164108        EXAMPLES::
    165109       
     110            sage: G = CyclicPermutationGroup(4)
     111            sage: H = DihedralGroup(4)
     112            sage: g = G([(1,2,3,4)])
     113            sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))
     114            sage: phi.image(G)
     115            Permutation Group with generators [(1,2,3,4)]
     116            sage: phi.image(g)                 
     117            (1,2,3,4)
     118
     119        ::
     120
    166121            sage: G = PSL(2,7)
    167122            sage: D = G.direct_product(G)
    168123            sage: H = D[0]
    class PermutationGroupMorphism_from_gap: 
    174129        """
    175130        if J in self.domain():
    176131            J = PermutationGroup([J])
    177             cmd = self.gap_hom_string
    178             gap.eval(cmd)
    179             gG = gap.eval("Image("+self._name+", "+str(J._gap_init_())+")")
    180             return PermutationGroup(gap(gG).GeneratorsOfGroup()).gens[0]
    181         cmd = self.gap_hom_string
    182         gap.eval(cmd)
    183         gG = gap.eval("Image("+self._name+", "+str(J._gap_init_())+")")
    184         return PermutationGroup(gap(gG).GeneratorsOfGroup())
     132            G = self._gap_().Image(J)
     133            return PermutationGroup(gap_group=G).gens()[0]
     134        else:
     135            G = self._gap_().Image(J)
     136            return PermutationGroup(gap_group=G)
    185137
    186     def __call__( self, g ):
    187         """
    188         Some python code for wrapping GAP's Images function but only for
    189         permutation groups. Returns an error if g is not in G.
    190         """
    191         cmd = self.gap_hom_string
    192         gap.eval(cmd)
    193         return PermutationGroupElement(gap.eval("Image( "+self._name+", "+str(g)+")"),self.range(), check = True)
    194 
    195 class PermutationGroupMorphism_im_gens:
    196     """
    197     Some python code for wrapping GAP's GroupHomomorphismByImages
    198     function but only for permutation groups. Can be expensive if G is
    199     large. Returns "fail" if gens does not generate self or if the map
    200     does not extend to a group homomorphism, self - other.
    201    
    202     EXAMPLES::
    203    
    204         sage: G = CyclicPermutationGroup(4)
    205         sage: gens = G.gens()
    206         sage: H = DihedralGroup(4)
    207         sage: g = G([(1,3),(2,4)]); g
    208         (1,3)(2,4)
    209         sage: phi = PermutationGroupMorphism_im_gens( G, H, gens, gens)
    210         sage: phi
    211         Homomorphism : Cyclic group of order 4 as a permutation group --> Dihedral group of order 8 as a permutation group
    212         sage: phi(g)
    213         (1,3)(2,4)
    214         sage: gens1 = G.gens()
    215         sage: gens2 = ((4,3,2,1),)
    216         sage: phi = PermutationGroupMorphism_im_gens( G, G, gens1, gens2)
    217         sage: g = G([(1,2,3,4)]); g
    218         (1,2,3,4)
    219         sage: phi(g)
    220         (1,4,3,2)
    221    
    222     AUTHORS:
    223 
    224     - David Joyner (2006-02)
    225     """
    226     def __init__(self, G, H, gensG, imgsH ):
    227         self._domain = G
    228         self._codomain = H
    229         if not(isinstance(G, PermutationGroup_generic)):
    230             raise TypeError, "Sorry, the groups must be permutation groups."
    231         if not(isinstance(H, PermutationGroup_generic)):
    232             raise TypeError, "Sorry, the groups must be permutation groups."
    233         G0  = G._gap_init_()
    234         H0  = H._gap_init_()
    235         gaplist_gens = [gap_format(x) for x in gensG]
    236         gaplist_imgs = [gap_format(x) for x in imgsH]
    237         L = gaplist_gens
    238         if len(L) == 1:
    239             genss = "["+L[0]+"]"
    240         if len(L)>1:
    241             genss = "["+L[0]+''.join([","+L[i+1] for i in range(len(L)-1)])+"]"
    242         L = gaplist_imgs
    243         if len(L) == 1:
    244             imgss = "["+L[0]+"]"
    245         if len(L)>1:
    246             imgss = "["+L[0]+''.join([","+L[i+1] for i in range(len(L)-1)])+"]"
    247         args = str(G0)+","+str(H0)+","+genss+","+ imgss
    248         phi0 = gap.eval("phi := GroupHomomorphismByImages("+args+")")
    249         self.gap_hom_string = "phi := GroupHomomorphismByImages("+args+")"
    250         if phi0=="fail":
    251             raise ValueError,"The map "+str(gensG)+"-->"+str(imgsH)+" isn't a homomorphism."
    252         self.hom = gap.eval("phi")
    253 
    254     def __repr__(self):
    255         return "Homomorphism : %s --> %s"%(self.domain(),self.range())
    256 
    257     def __str__(self):
    258         return "Homomorphism : %s --> %s"%(self.domain(),self.range())
    259 
    260     def _latex_(self):
    261         return self.domain()._latex_()+" \rightarrow "+self.range()._latex_()
    262 
    263     def domain(self):
    264         return self._domain
    265 
    266     def range(self):
    267         return self._codomain
    268 
    269     def codomain(self):
    270         return self._codomain
    271 
    272     def kernel(self):
    273         cmd = self.gap_hom_string
    274         gap.eval(cmd)
    275         # phi is the generic name
    276         gap_ker = gap.eval("Kernel( phi )")
    277         return PermutationGroup(gap(gap_ker).GeneratorsOfGroup())
    278 
    279     def image(self, J):
    280         """
    281         J must be a subgroup of G. Computes the subgroup of H which is the
    282         image of J.
    283        
    284         EXAMPLES::
    285        
    286             sage: G = CyclicPermutationGroup(4)
    287             sage: gens = G.gens()
    288             sage: H = DihedralGroup(4)
    289             sage: g = G([(1,2,3,4)])
    290             sage: phi = PermutationGroupMorphism_im_gens( G, H, gens, gens)
    291             sage: phi.image(G)
    292             Permutation Group with generators [(1,2,3,4)]
    293             sage: phi.image(g)                 
    294             (1,2,3,4)
    295         """
    296         if J in self.domain():
    297             J = PermutationGroup([J])
    298             cmd = self.gap_hom_string
    299             gap.eval(cmd)
    300             # phi is the generic name
    301             gG = gap.eval("Image( phi," + str(J._gap_init_()) +");")
    302             return PermutationGroup(gap(gG).GeneratorsOfGroup()).gens()[0]
    303         cmd = self.gap_hom_string
    304         gap.eval(cmd)
    305         # phi is the generic name
    306         gG = gap.eval("Image( phi," + str(J._gap_init_()) +");")
    307         return PermutationGroup(gap(gG).GeneratorsOfGroup())
    308 
    309     def __call__( self, g ):
     138    def __call__(self, g):
    310139        """
    311140        Some python code for wrapping GAP's Images function but only for
    312141        permutation groups. Returns an error if g is not in G.
    class PermutationGroupMorphism_im_gens: 
    314143        EXAMPLES::
    315144       
    316145            sage: G = CyclicPermutationGroup(4)
    317             sage: gens = G.gens()
    318146            sage: H = DihedralGroup(4)
    319             sage: phi = PermutationGroupMorphism_im_gens( G, H, gens, gens)
     147            sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))
    320148            sage: g = G([(1,3),(2,4)]); g
    321149            (1,3)(2,4)
    322150            sage: phi(g)
    class PermutationGroupMorphism_im_gens: 
    324152        """
    325153        return self.image(g)
    326154
    327 PermutationGroupMorphism = PermutationGroupMorphism_im_gens
     155class PermutationGroupMorphism_id(PermutationGroupMorphism):
     156    pass
    328157
     158class PermutationGroupMorphism_from_gap(PermutationGroupMorphism):
     159    def __init__(self, G, H, gap_hom):
     160        """
     161        This is a Python trick to allow Sage programmers to create a group
     162        homomorphism using GAP using very general constructions. An example
     163        of its usage is in the direct_product instance method of the
     164        PermutationGroup_generic class in permgroup.py.
    329165
     166        Basic syntax:
     167
     168        PermutationGroupMorphism_from_gap(domain_group,
     169        range_group,'phi:=gap_hom_command;','phi') And don't forget the
     170        line: from sage.groups.perm_gps.permgroup_morphism import
     171        PermutationGroupMorphism_from_gap in your program.
     172
     173        EXAMPLES::
     174
     175            sage: from sage.groups.perm_gps.permgroup_morphism import PermutationGroupMorphism_from_gap
     176            sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])
     177            sage: H = G.subgroup([G([(1,2,3,4)])])
     178            sage: PermutationGroupMorphism_from_gap(H, G, gap.Identity)
     179            Permutation group morphism:
     180              From: Subgroup of Permutation Group with generators [(1,2)(3,4), (1,2,3,4)] generated by [(1,2,3,4)]
     181              To:   Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]
     182              Defn: Identity
     183        """
     184        if not all(isinstance(X, PermutationGroup_generic) for X in [G, H]):
     185            raise TypeError, "Sorry, the groups must be permutation groups."
     186        PermutationGroupMorphism.__init__(self, G, H)
     187        self._gap_hom = gap_hom
     188
     189    def _repr_defn(self):
     190        """
     191        Returns the definition of this morphism.  This is used when
     192        printing the morphism.
     193
     194        EXAMPLES::
     195       
     196            sage: from sage.groups.perm_gps.permgroup_morphism import PermutationGroupMorphism_from_gap
     197            sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])
     198            sage: H = G.subgroup([G([(1,2,3,4)])])
     199            sage: phi = PermutationGroupMorphism_from_gap(H, G, gap.Identity)
     200            sage: phi._repr_defn()
     201            'Identity'
     202        """
     203        return str(self._gap_hom).replace('\n', '')
     204
     205    def _gap_(self, gap=None):
     206        """
     207        Returns a GAP version of this morphism.
     208
     209        EXAMPLES::
     210
     211            sage: from sage.groups.perm_gps.permgroup_morphism import PermutationGroupMorphism_from_gap
     212            sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])
     213            sage: H = G.subgroup([G([(1,2,3,4)])])
     214            sage: phi = PermutationGroupMorphism_from_gap(H, G, gap.Identity)
     215            sage: phi._gap_()
     216            Identity
     217        """
     218        return self._gap_hom
     219
     220    def __call__(self, g):
     221        """
     222        Some python code for wrapping GAP's Images function but only for
     223        permutation groups. Returns an error if g is not in G.
     224       
     225        EXAMPLES::
     226       
     227            sage: G = PSL(2,7)
     228            sage: D = G.direct_product(G)
     229            sage: H = D[0]
     230            sage: pr1 = D[3]
     231            sage: [pr1(g) for g in G.gens()]
     232            [(3,7,5)(4,8,6), (1,2,6)(3,4,8)]
     233        """
     234        return self.codomain()(self._gap_().Image(g))
     235
     236
     237class PermutationGroupMorphism_im_gens(PermutationGroupMorphism):
     238    def __init__(self, G, H, gens=None, images=None):
     239        """
     240        Some python code for wrapping GAP's GroupHomomorphismByImages
     241        function but only for permutation groups. Can be expensive if G is
     242        large. Returns "fail" if gens does not generate self or if the map
     243        does not extend to a group homomorphism, self - other.
     244
     245        EXAMPLES::
     246
     247            sage: G = CyclicPermutationGroup(4)
     248            sage: H = DihedralGroup(4)
     249            sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens())); phi
     250            Permutation group morphism:
     251              From: Cyclic group of order 4 as a permutation group
     252              To:   Dihedral group of order 8 as a permutation group
     253              Defn: [(1,2,3,4)] -> [(1,2,3,4)]
     254            sage: g = G([(1,3),(2,4)]); g
     255            (1,3)(2,4)         
     256            sage: phi(g)
     257            (1,3)(2,4)
     258            sage: images = ((4,3,2,1),)
     259            sage: phi = PermutationGroupMorphism_im_gens(G, G, images)
     260            sage: g = G([(1,2,3,4)]); g
     261            (1,2,3,4)
     262            sage: phi(g)
     263            (1,4,3,2)
     264
     265        AUTHORS:
     266
     267        - David Joyner (2006-02)
     268        """
     269        if not all([isinstance(X, PermutationGroup_generic) for X in [G, H]]):
     270            raise TypeError, "Sorry, the groups must be permutation groups."
     271        if images is not None:
     272            deprecation('only the images need to be specified')
     273        else:
     274            images = gens
     275        PermutationGroupMorphism.__init__(self, G, H)
     276        self._images = [H(img) for img in images]
     277
     278    def _repr_defn(self):
     279        """
     280        Returns the definition of this morphism.  This is used when
     281        printing the morphism.
     282
     283        EXAMPLES::
     284
     285            sage: G = CyclicPermutationGroup(4)
     286            sage: H = DihedralGroup(4)
     287            sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))
     288            sage: phi._repr_defn()
     289            '[(1,2,3,4)] -> [(1,2,3,4)]'
     290        """
     291        return "%s -> %s"%(self.domain().gens(), self._images)
     292
     293    def _gap_(self):
     294        """
     295        Returns a GAP representation of this morphism.
     296
     297        EXAMPLES::
     298
     299            sage: G = CyclicPermutationGroup(4)
     300            sage: H = DihedralGroup(4)
     301            sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))
     302            sage: phi._gap_()
     303            GroupHomomorphismByImages( Group( [ (1,2,3,4) ] ), Group(
     304            [ (1,2,3,4), (1,4)(2,3) ] ), [ (1,2,3,4) ], [ (1,2,3,4) ] )
     305        """
     306        return self.domain()._gap_().GroupHomomorphismByImages(self.codomain(), self.domain().gens(), self._images)
     307
     308def is_PermutationGroupMorphism(f):
     309    """
     310    Returns True if the argument ``f`` is a PermutationGroupMorphism.
     311
     312    EXAMPLES::
     313
     314        sage: from sage.groups.perm_gps.permgroup_morphism import is_PermutationGroupMorphism
     315        sage: G = CyclicPermutationGroup(4)
     316        sage: H = DihedralGroup(4)
     317        sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))
     318        sage: is_PermutationGroupMorphism(phi)
     319        True
     320    """
     321    return isinstance(f, PermutationGroupMorphism)
  • sage/groups/perm_gps/permgroup_named.py

    diff --git a/sage/groups/perm_gps/permgroup_named.py b/sage/groups/perm_gps/permgroup_named.py
    a b class AlternatingGroup(PermutationGroup_ 
    425425            Category of finite permutation groups
    426426            sage: TestSuite(G).run()
    427427        """
    428         self._set = _set
    429         self._deg = max(self._set)
    430         n = len(self._set)
    431 
     428        n = len(_set)
    432429        #Create the generators for the symmetric group
    433430        if n == 1:
    434431            gens = [ [] ]
    435432        else:
    436             gens = [ tuple(self._set) ]
     433            gens = [ tuple(_set) ]
    437434            if n > 2:
    438                 gens.append( tuple(self._set[:2]) )
     435                gens.append( tuple(_set[:2]) )
    439436
    440437        PermutationGroup_symalt.__init__(self, gap_group='%s(%s)'%(self._gap_name,n))
    441438
     439        self._set = _set
     440        self._deg = max(_set)
     441
    442442    def _repr_(self):
    443443        """
    444444        EXAMPLES:
    class TransitiveGroup(PermutationGroup_u 
    991991
    992992        self._d = d
    993993        self._n = n
     994        self._set = range(1, d+1)
    994995
    995996    def _repr_(self):
    996997        """