Ticket #10334: trac_10334-permgroup_cleanup-mh.patch

File trac_10334-permgroup_cleanup-mh.patch, 66.9 KB (added by Mike Hansen, 12 years ago)
  • sage/groups/perm_gps/all.py

    # HG changeset patch
    # User Mike Hansen <mhansen@gmail.com>
    # Date 1297156518 -3600
    # Node ID ee795c580c40cb36b87d095f6dfb76c8bced56d5
    # Parent  303edc238a82222287eaecf99f8ccc7c185edb72
    #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  
    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  
    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  
    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.
     135    """
     136    Load the GAP hap package into the default GAP interpreter
     137    interface. If this fails, try one more time to load it.
    143138
    144      EXAMPLES::
     139    EXAMPLES::
    145140
    146          sage: sage.groups.perm_gps.permgroup.load_hap()
    147      """
    148      try:
    149          gap.eval('LoadPackage("hap")')
    150      except:
    151          gap.eval('LoadPackage("hap")')
     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    """
     
    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"""
     
    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   
     
    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
    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         """
     
    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 = [()]
     
    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:
     
    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        """
     
    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.
     960        """
     961        Return the orbit of the given integer under the group action.
    902962
    903          EXAMPLES::
     963        EXAMPLES::
    904964
    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()
     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.
     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.
    922982
    923          EXAMPLES::
     983        EXAMPLES::
    924984
    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
     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.
     998        """
     999        Return the subgroup of ``self`` which stabilize the given position.
     1000        ``self`` and its stabilizers must have same degree.
    9411001
    942          EXAMPLES::
     1002        EXAMPLES::
    9431003
    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))
     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.
     1035        """
     1036        Return a Strong Generating System of ``self`` according the given
     1037        base for the right action of ``self`` on itself.
    9781038
    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.
     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.
    9831043
    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
     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
    9881048
    989          .. math::
     1049        .. math::
    9901050
    991             G = G_0 \supset G_1 \supset G_2 \supset \dots \supset G_n = \{e\}
     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}`
     1053        Then the algorithm returns `[ G_i.\mathrm{transversals}(\mathrm{pos}_{i+1})]_{1 \leq i \leq n}`
    9941054
    995          INPUT:
     1055        INPUT:
    9961056
    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``)
     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``)
    10001060
    1001          OUTPUT:
     1061        OUTPUT:
    10021062
    1003          - A list of lists of permutations from the group, which form a strong
    1004            generating system.
     1063        - A list of lists of permutations from the group, which form a strong
     1064          generating system.
    10051065
    1006          TESTS::
     1066        TESTS::
    10071067
    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
     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
    10121072
    1013          EXAMPLES::
     1073        EXAMPLES::
    10141074
    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
     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"""
     
    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
     
    11151175            (1,2)(4,5)
    11161176        """
    11171177        current_randstate().set_seed_gap()
    1118 
    1119         return self._element_class()(self._gap_().Random(),
    1120                                        self, check=False)
     1178        return self(self._gap_().Random(), check=False)
    11211179
    11221180    def group_id(self):
    11231181        """
     
    11301188            sage: G.group_id()    # optional - database_gap
    11311189            [12, 4]
    11321190        """
    1133         return [Integer(n) for n in eval(str(self._gap_().IdGroup()))]
     1191        return [Integer(n) for n in self._gap_().IdGroup()]
    11341192
    11351193    def id(self):
    11361194        """
     
    11601218            sage: G.center()
    11611219            Permutation Group with generators [()]
    11621220        """
    1163         C = self._gap_().Center()
    1164         return PermutationGroup(gap_group=C)
     1221        return PermutationGroup(gap_group=self._gap_().Center())
    11651222
    1166     def direct_product(self,other,maps=True):
     1223    def direct_product(self, other, maps=True):
    11671224        """
    11681225        Wraps GAP's ``DirectProduct``, ``Embedding``, and ``Projection``.
    11691226       
     
    12081265            sage: D,iota1,iota2,pr1,pr2 = G.direct_product(G)
    12091266            sage: D; iota1; iota2; pr1; pr2
    12101267            Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
    1211             Homomorphism : Cyclic group of order 4 as a permutation group --> Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
    1212             Homomorphism : Cyclic group of order 4 as a permutation group --> Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
    1213             Homomorphism : Permutation Group with generators [(1,2,3,4), (5,6,7,8)] --> Cyclic group of order 4 as a permutation group
    1214             Homomorphism : Permutation Group with generators [(1,2,3,4), (5,6,7,8)] --> Cyclic group of order 4 as a permutation group
    1215        
    1216         ::
    1217        
     1268            Permutation group morphism:
     1269              From: Cyclic group of order 4 as a permutation group
     1270              To:   Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
     1271              Defn: Embedding( Group( [ (1,2,3,4), (5,6,7,8) ] ), 1 )
     1272            Permutation group morphism:
     1273              From: Cyclic group of order 4 as a permutation group
     1274              To:   Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
     1275              Defn: Embedding( Group( [ (1,2,3,4), (5,6,7,8) ] ), 2 )
     1276            Permutation group morphism:
     1277              From: Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
     1278              To:   Cyclic group of order 4 as a permutation group
     1279              Defn: Projection( Group( [ (1,2,3,4), (5,6,7,8) ] ), 1 )
     1280            Permutation group morphism:
     1281              From: Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
     1282              To:   Cyclic group of order 4 as a permutation group
     1283              Defn: Projection( Group( [ (1,2,3,4), (5,6,7,8) ] ), 2 )
    12181284            sage: g=D([(1,3),(2,4)]); g
    12191285            (1,3)(2,4)
    12201286            sage: d=D([(1,4,3,2),(5,7),(6,8)]); d
     
    12251291            (1,4,3,2)
    12261292            (1,3)(2,4)
    12271293        """
    1228         from sage.groups.perm_gps.permgroup_morphism import PermutationGroupMorphism_from_gap
    1229         G1 = self._gap_init_()
    1230         G2 = other._gap_init_()
    1231         cmd1 = "G:=DirectProduct("+G1+","+G2+")"
    1232         cmd2 = "iota1:=Embedding(G,1)"
    1233         cmd3 = "iota2:=Embedding(G,2)"
    1234         cmd4 = "pr1:=Projection(G,1)"
    1235         cmd5 = "pr2:=Projection(G,2)"
    1236         if not(maps):
    1237             return PermutationGroup(gap_group=gap.eval(cmd1))
     1294        G = self._gap_().DirectProduct(other._gap_())
     1295        D = PermutationGroup(gap_group=G)
     1296        if not maps:
     1297            return D
    12381298        else:
    1239             D = PermutationGroup_generic(gap_group=gap.eval(cmd1))
    1240             iota1 = PermutationGroupMorphism_from_gap(self,D, cmd2, "iota1")
    1241             iota2 = PermutationGroupMorphism_from_gap(other,D, cmd3, "iota2")
    1242             pr1 = PermutationGroupMorphism_from_gap(D,self, cmd4, "pr1")
    1243             pr2 = PermutationGroupMorphism_from_gap(D,other, cmd5, "pr2")
    1244             return D,iota1,iota2,pr1,pr2
     1299            from sage.groups.perm_gps.permgroup_morphism import PermutationGroupMorphism_from_gap
     1300            iota1 = PermutationGroupMorphism_from_gap(self,  D, G.Embedding(1))
     1301            iota2 = PermutationGroupMorphism_from_gap(other, D, G.Embedding(2))
     1302            pr1 = PermutationGroupMorphism_from_gap(D, self, G.Projection(1))
     1303            pr2 = PermutationGroupMorphism_from_gap(D, other, G.Projection(2))
     1304            return D, iota1, iota2, pr1, pr2
    12451305
    12461306    def subgroup(self, gens):
    12471307        """
     
    12711331            sage: N = PermutationGroup([(1,2,3)])
    12721332            sage: G.quotient(N)
    12731333            Permutation Group with generators [(1,2)]
     1334            sage: G.quotient(G)
     1335            Permutation Group with generators [()]
    12741336        """
    1275         G = self
    1276         gap.eval("G := %s"%G._gap_().name())
    1277         gap.eval("N := %s"%N._gap_().name())
    1278         gap.eval("Q := G/N;")
    1279         gap.eval("phi := RegularActionHomomorphism( Q );")
    1280         gap.eval("gens := GeneratorsOfGroup( Image( phi ));")
    1281         n = Integer(gap.eval("n := Length(gens);"))
    1282         if n>0:
    1283             gens = [self._element_class()(gap.eval("gens[%s];"%i)) for i in range(1,n+1)]
    1284             Q = PermutationGroup(gens)
    1285             return Q
    1286         else:
    1287             return PermutationGroup([()])
     1337        Q = self._gap_() / N._gap_()
     1338        phi = Q.RegularActionHomomorphism()
     1339        gens = phi.Image().GeneratorsOfGroup()
     1340        return PermutationGroup([self(gen) for gen in gens])
    12881341
    12891342    def quotient_group(self, N):
    12901343        """
     
    13061359            doctest:...: DeprecationWarning: quotient_group() is deprecated; use quotient() instead.
    13071360            Permutation Group with generators [(1,2)]
    13081361        """
    1309         import warnings
    1310         warnings.warn('quotient_group() is deprecated; use quotient() instead.', DeprecationWarning, stacklevel=2)
    13111362        from sage.misc.misc import deprecation
    13121363        deprecation('quotient_group() is deprecated; use quotient() instead.')
    1313 
    13141364        return self.quotient(N)
    13151365
    13161366
     1367    @hap_decorator
    13171368    def cohomology(self, n, p = 0):
    13181369        r"""
    13191370        Computes the group cohomology `H^n(G, F)`, where `F = \ZZ`
     
    13551406        - D. Joyner, 'A primer on computational group homology and
    13561407          cohomology', http://front.math.ucdavis.edu/0706.0549.
    13571408        """
    1358         if not is_package_installed('gap_packages'):
    1359              raise RuntimeError, "You must install the optional gap_packages package."
    1360         load_hap()
    1361         from sage.rings.arith import is_prime
    1362         if not (p == 0 or is_prime(p)):
    1363             raise ValueError, "p must be 0 or prime"
    1364         G = self
    1365         GG = G._gap_init_()
    13661409        if p == 0:
    1367             L = eval(gap.eval("GroupCohomology(%s,%s)"%(GG,n)))
     1410            L = self._gap_().GroupCohomology(n).sage()
    13681411        else:
    1369             L = eval(gap.eval("GroupCohomology(%s,%s,%s)"%(GG,n,p)))
    1370         return AbelianGroup(len(L),L)
     1412            L = self._gap_().GroupCohomology(n, p).sage()
     1413        return AbelianGroup(len(L), L)
    13711414
     1415    @hap_decorator
    13721416    def cohomology_part(self, n, p = 0):
    13731417        """
    13741418        Computes the p-part of the group cohomology `H^n(G, F)`,
     
    13921436
    13931437        - David Joyner and Graham Ellis
    13941438        """
    1395         if not is_package_installed('gap_packages'):
    1396              raise RuntimeError, "You must install the optional gap_packages package."
    1397         load_hap()
    1398         from sage.rings.arith import is_prime
    1399         if not (p == 0 or is_prime(p)):
    1400             raise ValueError, "p must be 0 or prime"
    1401         G = self
    1402         GG = G._gap_init_()
    14031439        if p == 0:
    1404             H = AbelianGroup(1,[1])
     1440            return AbelianGroup(1, [1])
    14051441        else:
    1406             gap.eval("S := SylowSubgroup(%s,%s)"%(GG,p))
    1407             gap.eval("R:=ResolutionFiniteGroup(S,%s)"%(n+1))
    1408             gap.eval("HR:=HomToIntegers(R)")
    1409             L = eval(gap.eval("Cohomology(HR,%s)"%n))
    1410         return AbelianGroup(len(L),L)
     1442            G = self._gap_()
     1443            S = G.SylowSubgroup(p)
     1444            R = S.ResolutionFiniteGroup(n+1)
     1445            HR = R.HomToIntegers()
     1446            L = HR.Cohomology(n).sage()
     1447            return AbelianGroup(len(L), L)
    14111448
     1449    @hap_decorator
    14121450    def homology(self, n, p = 0):
    14131451        r"""
    14141452        Computes the group homology `H_n(G, F)`, where
     
    14501488        - D. Joyner, "A primer on computational group homology and cohomology",
    14511489          http://front.math.ucdavis.edu/0706.0549
    14521490        """
    1453         if not is_package_installed('gap_packages'):
    1454              raise RuntimeError, "You must install the optional gap_packages package."
    1455         load_hap()
    1456         from sage.rings.arith import is_prime
    1457         if not (p == 0 or is_prime(p)):
    1458             raise ValueError, "p must be 0 or prime"
    1459         G = self
    1460         GG = G._gap_init_()
    14611491        if p == 0:
    1462             L = eval(gap.eval("GroupHomology(%s,%s)"%(GG,n)))
     1492            L = self._gap_().GroupHomology(n).sage()
    14631493        else:
    1464             L = eval(gap.eval("GroupHomology(%s,%s,%s)"%(GG,n,p)))
    1465         return AbelianGroup(len(L),L)
     1494            L = self._gap_().GroupHomology(n, p).sage()
     1495        return AbelianGroup(len(L), L)
    14661496
     1497    @hap_decorator
    14671498    def homology_part(self, n, p = 0):
    14681499        r"""
    14691500        Computes the `p`-part of the group homology
     
    14841515
    14851516        - David Joyner and Graham Ellis
    14861517        """
    1487         if not is_package_installed('gap_packages'):
    1488              raise RuntimeError, "You must install the optional gap_packages package."
    1489         gap.eval('LoadPackage("hap")')
    1490         from sage.rings.arith import is_prime
    1491         if not (p == 0 or is_prime(p)):
    1492             raise ValueError, "p must be 0 or prime"
    1493         G = self
    1494         GG = G._gap_init_()
    14951518        if p == 0:
    1496             H = AbelianGroup(1,[1])
     1519            return AbelianGroup(1, [1])
    14971520        else:
    1498             gap.eval("S := SylowSubgroup(%s,%s)"%(GG,p))
    1499             gap.eval("R:=ResolutionFiniteGroup(S,%s)"%(n+1))
    1500             gap.eval("TR:=TensorWithIntegers(R);")
    1501             L = eval(gap.eval("Homology(TR,%s)"%n))
    1502         return AbelianGroup(len(L),L)
     1521            S = self._gap_().SylowSubgroup(p)
     1522            R = S.ResolutionFiniteGroup(n+1)
     1523            TR = R.TensorWithIntegers()
     1524            L = TR.Homology(n).sage()
     1525            return AbelianGroup(len(L), L)
    15031526
    15041527    def character_table(self):
    15051528        r"""
     
    15841607        cl   = G.ConjugacyClasses()
    15851608        n    = Integer(cl.Length())
    15861609        irrG = G.Irr()
    1587         ct   = [[irrG[i+1,j+1] for j in range(n)] for i in range(n)]
     1610        ct   = [[irrG[i+1, j+1] for j in range(n)] for i in range(n)]
    15881611
    15891612        from sage.rings.all import CyclotomicField
    15901613        e = irrG.Flat().Conductor()
     
    15931616
    15941617        # Finally return the result as a matrix.
    15951618        from sage.matrix.all import MatrixSpace
    1596         MS = MatrixSpace(K,n)
     1619        MS = MatrixSpace(K, n)
    15971620        return MS(ct)
    15981621
    15991622    def irreducible_characters(self):
     
    16061629            sage: [x.values() for x in irr]
    16071630            [[1, -1, 1], [2, 0, -1], [1, 1, 1]]
    16081631        """
    1609         Irr = self._gap_().Irr()
    1610         L = []
    1611         for irr in Irr:
    1612             L.append(ClassFunction(self, irr))
    1613         return L
     1632        return [ClassFunction(self, irr) for irr in self._gap_().Irr()]
    16141633
    16151634    def trivial_character(self):
    16161635        r"""
     
    16211640            sage: SymmetricGroup(3).trivial_character()
    16221641            Character of Symmetric group of order 3! as a permutation group
    16231642        """
    1624         values = [1]*Integer(self._gap_().NrConjugacyClasses())
     1643        values = [1]*self._gap_().NrConjugacyClasses().sage()
    16251644        return self.character(values)
    16261645
    16271646    def character(self, values):
     
    16371656            sage: G.character([1]*n)
    16381657            Character of Alternating group of order 4!/2 as a permutation group
    16391658        """
    1640         return ClassFunction(self,values)
     1659        return ClassFunction(self, values)
    16411660
    16421661    def conjugacy_classes_representatives(self):
    16431662        """
     
    16551674        ::
    16561675       
    16571676            sage: G = SymmetricGroup(5)
    1658             sage: G.conjugacy_classes_representatives ()
     1677            sage: G.conjugacy_classes_representatives()
    16591678            [(), (1,2), (1,2)(3,4), (1,2,3), (1,2,3)(4,5), (1,2,3,4), (1,2,3,4,5)]
    16601679       
    16611680        AUTHORS:
     
    16631682        - David Joyner and William Stein (2006-01-04)
    16641683        """
    16651684        cl = self._gap_().ConjugacyClasses()
    1666         n = Integer(cl.Length())
    1667         L = gap("List([1..Length(%s)], i->Representative(%s[i]))"%(
    1668             cl.name(),  cl.name()))
    1669         return [self._element_class()(L[i], self, check=False) \
    1670                 for i in range(1,n+1)]
     1685        return [self(rep.Representative(), check=False) for rep in cl]
    16711686
    16721687    def conjugacy_classes_subgroups(self):
    16731688        """
     
    17021717
    17031718        - David Joyner (2006-10)
    17041719        """
    1705         G = self._gap_()
    1706         cl = G.ConjugacyClassesSubgroups()
    1707         n = Integer(cl.Length())
    1708         L = gap("List([1..Length(%s)], i->Representative(%s[i]))"%(
    1709             cl.name(),  cl.name()))
    1710         return [PermutationGroup(gap_group=L[i])for i in range(1,n+1)]
     1720        cl = self._gap_().ConjugacyClassesSubgroups()
     1721        return [PermutationGroup(gap_group=sub.Representative()) for sub in cl]
    17111722       
    17121723    def normalizer(self, g):
    17131724        """
     
    18391850        """
    18401851        return self._gap_().IsElementaryAbelian().bool()
    18411852   
    1842     def isomorphism_to(self,right):
     1853    def isomorphism_to(self, right):
    18431854        """
    18441855        Return an isomorphism from ``self`` to ``right`` if the groups
    18451856        are isomorphic, otherwise ``None``.
     
    18651876            sage: G = PermutationGroup([(1,2,3), (2,3)])
    18661877            sage: H = PermutationGroup([(1,2,4), (1,4)])
    18671878            sage: G.isomorphism_to(H)
    1868             Homomorphism : Permutation Group with generators [(2,3), (1,2,3)] --> Permutation Group with generators [(1,2,4), (1,4)]
     1879            Permutation group morphism:
     1880              From: Permutation Group with generators [(2,3), (1,2,3)]
     1881              To:   Permutation Group with generators [(1,2,4), (1,4)]
     1882              Defn: [(2,3), (1,2,3)] -> [(2,4), (1,2,4)]
    18691883        """
    18701884        current_randstate().set_seed_gap()
    1871 
    18721885        if not isinstance(right, PermutationGroup_generic):
    18731886            raise TypeError, "right must be a permutation group"
    1874         G = self._gap_init_()
    1875         H = right._gap_init_()
    1876         gap.eval("x:=IsomorphismGroups( %s, %s )"%(G,H))
    1877         s = gap.eval("x")
    1878         if s == "fail":
     1887       
     1888        iso = self._gap_().IsomorphismGroups(right)
     1889        if str(iso) == "fail":
    18791890            return None
    1880         # slice and dice the GAP return to build a Sage group homomorphism
    1881         src, dst = s.split("->")
    1882         # we eval to get things as lists
    1883         srcs = from_gap_list(self, src)
    1884         dsts = from_gap_list(right, dst)
     1891       
     1892        dsts = [right(iso.Image(x), check=False) for x in self.gens()]
     1893       
    18851894        from permgroup_morphism import PermutationGroupMorphism_im_gens
    1886         return PermutationGroupMorphism_im_gens(self, right, srcs, dsts)
     1895        return PermutationGroupMorphism_im_gens(self, right, dsts)
    18871896
    18881897    def is_isomorphic(self, right):
    18891898        """
     
    19161925        """
    19171926        if not isinstance(right, PermutationGroup_generic):
    19181927            raise TypeError, "right must be a permutation group"
    1919         G = self._gap_()
    1920         H = right._gap_()
    1921         return gap.eval("IsomorphismGroups( %s, %s )"%(G.name(),H.name())) != "fail"
    1922 
     1928        iso = self._gap_().IsomorphismGroups(right)
     1929        return str(iso) != 'fail'
     1930       
    19231931    def is_monomial(self):
    19241932        """
    19251933        Returns ``True`` if the group is monomial. A finite group is monomial
     
    19631971            False
    19641972        """
    19651973        if not(self.is_subgroup(other)):
    1966             raise TypeError("%s must be a subgroup of %s"%(self,other))
     1974            raise TypeError("%s must be a subgroup of %s"%(self, other))
    19671975        return other._gap_().IsNormal(self._gap_()).bool()
    19681976   
    19691977    def is_perfect(self):
     
    20392047        """
    20402048        return self._gap_().IsSolvableGroup().bool()
    20412049   
    2042     def is_subgroup(self,other):
     2050    def is_subgroup(self, other):
    20432051        """
    20442052        Returns ``True`` if ``self`` is a subgroup of ``other``.
    20452053       
     
    20972105            sage: gap(G).IsTransitive()
    20982106            true
    20992107        """
    2100         return self._gap_().IsTransitive('[1..%s]'%self.degree()).bool()
     2108        return self._gap_().IsTransitive(self._set_gap()).bool()
    21012109   
    2102     def normalizes(self,other):
     2110    def normalizes(self, other):
    21032111        r"""
    21042112        Returns ``True`` if the group ``other`` is normalized by ``self``.
    21052113        Wraps GAP's ``IsNormal`` function.
     
    21502158            Permutation Group with generators [()]
    21512159        """
    21522160        current_randstate().set_seed_gap()
    2153         ans = []
    2154         DS = self._gap_().CompositionSeries()
    2155         n = DS.Length()
    2156         for i in range(1,n+1):
    2157             ans.append(PermutationGroup(DS[i].GeneratorsOfGroup()))
    2158         return ans
     2161        CS = self._gap_().CompositionSeries()
     2162        return [PermutationGroup(gap_group=group) for group in CS]
    21592163
    21602164    def derived_series(self):
    21612165        """
     
    21752179            [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)]]
    21762180        """
    21772181        current_randstate().set_seed_gap()
    2178         ans = []
    21792182        DS = self._gap_().DerivedSeries()
    2180         n = DS.Length()
    2181         for i in range(1,n+1):
    2182             ans.append(PermutationGroup(DS[i].GeneratorsOfGroup()))
    2183         return ans
    2184    
     2183        return [PermutationGroup(gap_group=group) for group in DS]   
     2184
    21852185    def lower_central_series(self):
    21862186        """
    21872187        Return the lower central series of this group as a list of
     
    22002200            [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)]]
    22012201        """
    22022202        current_randstate().set_seed_gap()
    2203         ans = []
    2204         DS = self._gap_().LowerCentralSeriesOfGroup()
    2205         n = DS.Length()
    2206         for i in range(1,n+1):
    2207             ans.append(PermutationGroup(DS[i].GeneratorsOfGroup()))
    2208         return ans
     2203        LCS = self._gap_().LowerCentralSeriesOfGroup()
     2204        return [PermutationGroup(gap_group=group) for group in LCS]   
    22092205
    22102206    def molien_series(self):
    22112207        r"""
     
    22352231            sage: G.molien_series()     
    22362232            1/(-x^6 + x^5 + x^4 - x^2 - x + 1)
    22372233        """
    2238         G = self
    2239         GG = G._gap_init_()
    2240         gap.eval("pi := NaturalCharacter( %s )"%GG)
    2241         gap.eval("cc := ConstituentsOfCharacter( pi )")
    2242         M = gap.eval("M := MolienSeries(Sum(cc))")
    2243         R = PolynomialRing(RationalField(),"x")
    2244         x = R.gen()
    2245         nn = gap.eval("NumeratorOfRationalFunction(M)")
    2246         dd = gap.eval("DenominatorOfRationalFunction(M)")
    2247         FF = FractionField(R)
    2248         return FF(nn.replace("_1",""))/FF(dd.replace("_1",""))
     2234        pi = self._gap_().NaturalCharacter()
     2235        cc = pi.ConstituentsOfCharacter()
     2236        M = cc.Sum().MolienSeries()
     2237
     2238        R = QQ['x']
     2239        nn = M.NumeratorOfRationalFunction()
     2240        dd = M.DenominatorOfRationalFunction()
     2241        return (R(str(nn).replace("_1","")) /
     2242                R(str(dd).replace("_1","")))
    22492243   
    22502244    def normal_subgroups(self):
    22512245        """
     
    22692263            sage: NH[2].is_isomorphic(G)
    22702264            True
    22712265        """
    2272         ans = []
    22732266        NS = self._gap_().NormalSubgroups()
    2274         n = NS.Length()
    2275         for i in range(1,n+1):
    2276             ans.append(PermutationGroup(NS[i].GeneratorsOfGroup()))
    2277         return ans
     2267        return [PermutationGroup(gap_group=group) for group in NS]
    22782268
    22792269    def poincare_series(self, p=2, n=10):
    22802270        """
     
    23022292        - David Joyner and Graham Ellis
    23032293        """
    23042294        if not is_package_installed('gap_packages'):
    2305              raise RuntimeError, "You must install the optional gap_packages package."
     2295            raise RuntimeError, "You must install the optional gap_packages package."
    23062296        load_hap()
    23072297        from sage.rings.arith import is_prime
    23082298        if not (p == 0 or is_prime(p)):
    23092299            raise ValueError, "p must be 0 or prime"
    2310         G = self
    2311         GG = G._gap_init_()
    2312         ff = gap.eval("ff := PoincareSeriesPrimePart(%s,%s,%s)"%(GG,p,n))
    2313         R = PolynomialRing(RationalField(),"x")
    2314         x = R.gen()
    2315         nn = gap.eval("NumeratorOfRationalFunction(ff)").replace("x_1","x")
    2316         dd = gap.eval("DenominatorOfRationalFunction(ff)").replace("x_1","x")
    2317         FF = FractionField(R)
    2318         return FF(nn)/FF(dd)
     2300
     2301        ff = self._gap_().PoincareSeriesPrimePart(p, n)
     2302        R = QQ['x']
     2303        nn = ff.NumeratorOfRationalFunction()
     2304        dd = ff.DenominatorOfRationalFunction()
     2305        return (R(str(nn).replace('x_1', 'x')) /
     2306                R(str(dd).replace('x_1', 'x')))
    23192307
    23202308
    23212309    def sylow_subgroup(self, p):
     
    23322320            sage: G.sylow_subgroup(5)
    23332321            Permutation Group with generators [()]
    23342322        """
    2335         G = self
    2336         gap.eval("G := %s"%G._gap_init_())
    2337         gap.eval("Ssgp := SylowSubgroup(G, %s);"%p)
    2338         gap.eval("gens := GeneratorsOfGroup( Ssgp );")
    2339         N = Integer(gap.eval("N := Length(gens);"))
    2340         if N>0:
    2341             gens = [self._element_class()(gap.eval("gens[%s];"%j)) for j in range(1,N+1)]
    2342             H = PermutationGroup(gens)
    2343         else:
    2344             H = PermutationGroup([()])
    2345         return H
    2346 
     2323        return PermutationGroup(gap_group=self._gap_().SylowSubgroup(p))
    23472324       
    23482325    def upper_central_series(self):
    23492326        """
     
    23532330        EXAMPLES:
    23542331
    23552332        These computations use pseudo-random numbers, so we set
    2356         the seed for reproducible testing.
    2357        
    2358         ::
    2359        
     2333        the seed for reproducible testing::
     2334
    23602335            sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])
    23612336            sage: G.upper_central_series()
    23622337            [Permutation Group with generators [()]]
    23632338        """
    23642339        current_randstate().set_seed_gap()
    2365         ans = []
    2366         DS = self._gap_().UpperCentralSeriesOfGroup()
    2367         n = DS.Length()
    2368         for i in range(1,n+1):
    2369             ans.append(PermutationGroup(gap_group=DS[i]))
    2370         return ans
     2340        UCS = self._gap_().UpperCentralSeriesOfGroup()
     2341        return [PermutationGroup(gap_group=group) for group in UCS]
    23712342
    23722343class PermutationGroup_subgroup(PermutationGroup_generic):
    23732344    """
     
    25202491        if not isinstance(other, PermutationGroup_generic):
    25212492            return -1
    25222493        c = PermutationGroup_generic.__cmp__(self, other)
    2523         if c: return c
     2494        if c:
     2495            return c
    25242496        if hasattr(other, 'ambient_group'):
    2525              o_ambient = other.ambient_group()
     2497            o_ambient = other.ambient_group()
    25262498        else:
    2527              o_ambient = other
    2528         return cmp(self.ambient_group(),o_ambient)
     2499            o_ambient = other
     2500        return cmp(self.ambient_group(), o_ambient)
    25292501
    25302502    def _repr_(self):
    25312503        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  
    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()
     
    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
     
    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)
     
    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]
     
    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.
     
    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)
     
    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  
    367367            Category of finite permutation groups
    368368            sage: TestSuite(G).run()
    369369        """
    370         self._set = _set
    371         self._deg = max(self._set)
    372         n = len(self._set)
    373 
     370        n = len(_set)
    374371        #Create the generators for the symmetric group
    375372        if n == 1:
    376373            gens = [ [] ]
    377374        else:
    378             gens = [ tuple(self._set) ]
     375            gens = [ tuple(_set) ]
    379376            if n > 2:
    380                 gens.append( tuple(self._set[:2]) )
     377                gens.append( tuple(_set[:2]) )
    381378
    382379        PermutationGroup_symalt.__init__(self, gap_group='%s(%s)'%(self._gap_name,n))
    383380
     381        self._set = _set
     382        self._deg = max(_set)
     383
    384384    def _repr_(self):
    385385        """
    386386        EXAMPLES:
     
    933933
    934934        self._d = d
    935935        self._n = n
     936        self._set = range(1, d+1)
    936937
    937938    def _repr_(self):
    938939        """