# HG changeset patch
# User Mike Hansen <mhansen@gmail.com>
# Date 1307563431 25200
# Node ID 048c24f4556305b322f88fba8cff9c35933e97d6
# Parent  6c965fff4a5aaa3996d72985e35ee0c4170cbd44
#10335: Add support for domains of permutation groups.
This includes the functionality from #8929 by Jason Hill.

diff --git a/doc/en/bordeaux_2008/nf_galois_groups.rst b/doc/en/bordeaux_2008/nf_galois_groups.rst
--- a/doc/en/bordeaux_2008/nf_galois_groups.rst
+++ b/doc/en/bordeaux_2008/nf_galois_groups.rst
@@ -41,8 +41,8 @@
     sage: P = K.primes_above(2)[0]
     sage: G.inertia_group(P)
     Subgroup [(), (1,4,6)(2,5,3), (1,6,4)(2,3,5)] of Galois group of Number Field in alpha with defining polynomial x^6 + 40*x^3 + 1372
-    sage: sorted([G.artin_symbol(Q) for Q in K.primes_above(5)]) # (order is platform-dependent)
-    [(1,2)(3,4)(5,6), (1,3)(2,6)(4,5), (1,5)(2,4)(3,6)]
+    sage: sorted([G.artin_symbol(Q) for Q in K.primes_above(5)]) 
+    [(1,3)(2,6)(4,5), (1,2)(3,4)(5,6), (1,5)(2,4)(3,6)]
 
 If the number field is not Galois over `\QQ`, then the ``galois_group``
 command will construct its Galois closure and return the Galois group of that;
diff --git a/doc/en/constructions/groups.rst b/doc/en/constructions/groups.rst
--- a/doc/en/constructions/groups.rst
+++ b/doc/en/constructions/groups.rst
@@ -232,7 +232,7 @@
 
     sage: G = PermutationGroup(['(1,2,3)(4,5)', '(3,4)'])
     sage: G.center()
-    Permutation Group with generators [()]
+    Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]
 
 A similar syntax for matrix groups also works:
 
@@ -244,7 +244,7 @@
      [[[4, 0], [0, 4]]] 
     sage: G = PSL(2, 5 )
     sage: G.center()
-    Permutation Group with generators [()]
+    Subgroup of (The projective special linear group of degree 2 over Finite Field of size 5) generated by [()]
 
 Note: ``center`` can be spelled either way in GAP, not so in Sage.
 
diff --git a/doc/en/thematic_tutorials/group_theory.rst b/doc/en/thematic_tutorials/group_theory.rst
--- a/doc/en/thematic_tutorials/group_theory.rst
+++ b/doc/en/thematic_tutorials/group_theory.rst
@@ -569,7 +569,7 @@
 
     sage: C20 = CyclicPermutationGroup(20)
     sage: C20.conjugacy_classes_subgroups()
-    [Permutation Group with generators [()], Permutation Group with generators [(1,11)(2,12)(3,13)(4,14)(5,15)(6,16)(7,17)(8,18)(9,19)(10,20)], Permutation Group with generators [(1,6,11,16)(2,7,12,17)(3,8,13,18)(4,9,14,19)(5,10,15,20)], Permutation Group with generators [(1,5,9,13,17)(2,6,10,14,18)(3,7,11,15,19)(4,8,12,16,20)], Permutation Group with generators [(1,3,5,7,9,11,13,15,17,19)(2,4,6,8,10,12,14,16,18,20)], Permutation Group with generators [(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)]]
+    [Subgroup of (Cyclic group of order 20 as a permutation group) generated by [()], Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,11)(2,12)(3,13)(4,14)(5,15)(6,16)(7,17)(8,18)(9,19)(10,20)], Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,6,11,16)(2,7,12,17)(3,8,13,18)(4,9,14,19)(5,10,15,20)], Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,5,9,13,17)(2,6,10,14,18)(3,7,11,15,19)(4,8,12,16,20)], Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,3,5,7,9,11,13,15,17,19)(2,4,6,8,10,12,14,16,18,20)], Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)]]
 
 Be careful, this command uses some more advanced ideas and will not
 usually list *all* of the subgroups of a group. Here we are relying on
@@ -623,7 +623,7 @@
     sage: sg = K.conjugacy_classes_subgroups()
     sage: print "sg:\n", sg
     sg:
-    [Permutation Group with generators [()], Permutation Group with generators [(1,2)(3,12)(4,11)(5,10)(6,9)(7,8)], Permutation Group with generators [(1,7)(2,8)(3,9)(4,10)(5,11)(6,12)], Permutation Group with generators [(2,12)(3,11)(4,10)(5,9)(6,8)], Permutation Group with generators [(1,5,9)(2,6,10)(3,7,11)(4,8,12)], Permutation Group with generators [(2,12)(3,11)(4,10)(5,9)(6,8), (1,7)(2,8)(3,9)(4,10)(5,11)(6,12)], Permutation Group with generators [(1,2)(3,12)(4,11)(5,10)(6,9)(7,8), (1,7)(2,8)(3,9)(4,10)(5,11)(6,12)], Permutation Group with generators [(1,10,7,4)(2,11,8,5)(3,12,9,6)], Permutation Group with generators [(1,5,9)(2,6,10)(3,7,11)(4,8,12), (1,3,5,7,9,11)(2,4,6,8,10,12)], Permutation Group with generators [(1,5,9)(2,6,10)(3,7,11)(4,8,12), (1,2)(3,12)(4,11)(5,10)(6,9)(7,8)], Permutation Group with generators [(1,5,9)(2,6,10)(3,7,11)(4,8,12), (2,12)(3,11)(4,10)(5,9)(6,8)], Permutation Group with generators [(2,12)(3,11)(4,10)(5,9)(6,8), (1,10,7,4)(2,11,8,5)(3,12,9,6)], Permutation Group with generators [(1,5,9)(2,6,10)(3,7,11)(4,8,12), (1,3,5,7,9,11)(2,4,6,8,10,12), (2,12)(3,11)(4,10)(5,9)(6,8)], Permutation Group with generators [(1,5,9)(2,6,10)(3,7,11)(4,8,12), (1,3,5,7,9,11)(2,4,6,8,10,12), (1,2)(3,12)(4,11)(5,10)(6,9)(7,8)], Permutation Group with generators [(1,5,9)(2,6,10)(3,7,11)(4,8,12), (1,3,5,7,9,11)(2,4,6,8,10,12), (1,2,3,4,5,6,7,8,9,10,11,12)], Permutation Group with generators [(1,5,9)(2,6,10)(3,7,11)(4,8,12), (1,3,5,7,9,11)(2,4,6,8,10,12), (2,12)(3,11)(4,10)(5,9)(6,8), (1,2,3,4,5,6,7,8,9,10,11,12)]]
+    [Subgroup of (Dihedral group of order 24 as a permutation group) generated by [()], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2)(3,12)(4,11)(5,10)(6,9)(7,8)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,7)(2,8)(3,9)(4,10)(5,11)(6,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,5,9)(2,6,10)(3,7,11)(4,8,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,7)(2,8)(3,9)(4,10)(5,11)(6,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2)(3,12)(4,11)(5,10)(6,9)(7,8), (1,7)(2,8)(3,9)(4,10)(5,11)(6,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,10,7,4)(2,11,8,5)(3,12,9,6)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2)(3,12)(4,11)(5,10)(6,9)(7,8), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,10,7,4)(2,11,8,5)(3,12,9,6)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2)(3,12)(4,11)(5,10)(6,9)(7,8), (1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2,3,4,5,6,7,8,9,10,11,12), (1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,2,3,4,5,6,7,8,9,10,11,12), (1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)]]
     sage: print "\nAn order two subgroup:\n", sg[1].list()
     <BLANKLINE>
     An order two subgroup:
diff --git a/doc/en/tutorial/interfaces.rst b/doc/en/tutorial/interfaces.rst
--- a/doc/en/tutorial/interfaces.rst
+++ b/doc/en/tutorial/interfaces.rst
@@ -174,7 +174,7 @@
 
     sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])
     sage: G.center()
-    Permutation Group with generators [()]
+    Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]
     sage: G.group_id()     # requires optional database_gap package
     [120, 34]
     sage: n = G.order(); n
diff --git a/doc/en/tutorial/tour_groups.rst b/doc/en/tutorial/tour_groups.rst
--- a/doc/en/tutorial/tour_groups.rst
+++ b/doc/en/tutorial/tour_groups.rst
@@ -22,7 +22,7 @@
     [Permutation Group with generators [(1,2,3)(4,5), (3,4)],
      Permutation Group with generators [(1,5)(3,4), (1,5)(2,4), (1,3,5)]]
     sage: G.center()
-    Permutation Group with generators [()]
+    Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]
     sage: G.random_element()           # random output
     (1,5,3)(2,4)
     sage: print latex(G)
diff --git a/doc/fr/tutorial/interfaces.rst b/doc/fr/tutorial/interfaces.rst
--- a/doc/fr/tutorial/interfaces.rst
+++ b/doc/fr/tutorial/interfaces.rst
@@ -175,7 +175,7 @@
 
     sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])
     sage: G.center()
-    Permutation Group with generators [()]
+    Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]
     sage: G.group_id()    # nécessite le paquet facultatif database_gap (optional)
     [120, 34]
     sage: n = G.order(); n
diff --git a/doc/fr/tutorial/tour_groups.rst b/doc/fr/tutorial/tour_groups.rst
--- a/doc/fr/tutorial/tour_groups.rst
+++ b/doc/fr/tutorial/tour_groups.rst
@@ -23,7 +23,7 @@
     [Permutation Group with generators [(1,2,3)(4,5), (3,4)],
      Permutation Group with generators [(1,5)(3,4), (1,5)(2,4), (1,3,5)]]
     sage: G.center()
-    Permutation Group with generators [()]
+    Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]
     sage: G.random_element()           # sortie aléatoire (random)
     (1,5,3)(2,4)
     sage: print latex(G)
diff --git a/sage/categories/finite_groups.py b/sage/categories/finite_groups.py
--- a/sage/categories/finite_groups.py
+++ b/sage/categories/finite_groups.py
@@ -82,7 +82,7 @@
 
                 sage: A = AlternatingGroup(4)
                 sage: A.semigroup_generators()
-                Family ((1,2,3), (2,3,4))
+                Family ((2,3,4), (1,2,3))
             """
             return self.group_generators()
 
diff --git a/sage/categories/g_sets.py b/sage/categories/g_sets.py
--- a/sage/categories/g_sets.py
+++ b/sage/categories/g_sets.py
@@ -25,7 +25,7 @@
 
         sage: S = SymmetricGroup(3)
         sage: GSets(S)
-        Category of G-sets for SymmetricGroup(3)
+        Category of G-sets for Symmetric group of order 3! as a permutation group
 
     TODO: should this derive from Category_over_base?
     """
@@ -44,7 +44,7 @@
         EXAMPLES::
 
             sage: GSets(SymmetricGroup(8)) # indirect doctests
-            Category of G-sets for SymmetricGroup(8)
+            Category of G-sets for Symmetric group of order 8! as a permutation group
         """
         return "G-sets for %s"%self.__G
 
@@ -70,7 +70,7 @@
         EXAMPLES::
         
             sage: GSets.an_instance() # indirect doctest
-            Category of G-sets for SymmetricGroup(8)
+            Category of G-sets for Symmetric group of order 8! as a permutation group
         """
         from sage.groups.perm_gps.permgroup_named import SymmetricGroup
         G = SymmetricGroup(8)
diff --git a/sage/categories/groupoid.py b/sage/categories/groupoid.py
--- a/sage/categories/groupoid.py
+++ b/sage/categories/groupoid.py
@@ -50,7 +50,7 @@
 
             sage: S8 = SymmetricGroup(8)
             sage: Groupoid(S8)
-            Groupoid with underlying set SymmetricGroup(8)
+            Groupoid with underlying set Symmetric group of order 8! as a permutation group
         """
         return "Groupoid with underlying set %s"%self.__G
 
@@ -76,7 +76,7 @@
         EXAMPLES::
 
             sage: Groupoid.an_instance() # indirect doctest
-            Groupoid with underlying set SymmetricGroup(8)
+            Groupoid with underlying set Symmetric group of order 8! as a permutation group
         """
         from sage.groups.perm_gps.permgroup_named import SymmetricGroup
         G = SymmetricGroup(8)
diff --git a/sage/categories/groups.py b/sage/categories/groups.py
--- a/sage/categories/groups.py
+++ b/sage/categories/groups.py
@@ -68,7 +68,7 @@
 
                 sage: A = AlternatingGroup(4)
                 sage: A.group_generators()
-                Family ((1,2,3), (2,3,4))
+                Family ((2,3,4), (1,2,3))
             """
             return Family(self.gens())
 
diff --git a/sage/categories/homset.py b/sage/categories/homset.py
--- a/sage/categories/homset.py
+++ b/sage/categories/homset.py
@@ -63,7 +63,7 @@
         Category of vector spaces over Rational Field
         sage: G = AlternatingGroup(3)
         sage: Hom(G, G)
-        Set of Morphisms from AlternatingGroup(3) to AlternatingGroup(3) in Category of finite permutation groups
+        Set of Morphisms from Alternating group of order 3!/2 as a permutation group to Alternating group of order 3!/2 as a permutation group in Category of finite permutation groups
         sage: Hom(ZZ, QQ, Sets())
         Set of Morphisms from Integer Ring to Rational Field in Category of sets
 
@@ -196,7 +196,7 @@
     
         sage: G = AlternatingGroup(3)
         sage: S = End(G); S
-        Set of Morphisms from AlternatingGroup(3) to AlternatingGroup(3) in Category of finite permutation groups
+        Set of Morphisms from Alternating group of order 3!/2 as a permutation group to Alternating group of order 3!/2 as a permutation group in Category of finite permutation groups
         sage: from sage.categories.homset import is_Endset
         sage: is_Endset(S)
         True
@@ -361,26 +361,26 @@
             sage: phi = Hom(SymmetricGroup(5), SymmetricGroup(6)).natural_map()
             sage: phi
             Coercion morphism:
-              From: SymmetricGroup(5)
-              To:   SymmetricGroup(6)
+              From: Symmetric group of order 5! as a permutation group
+              To:   Symmetric group of order 6! as a permutation group
             sage: H(phi)
             Composite map:
-              From: SymmetricGroup(4)
-              To:   SymmetricGroup(7)
+              From: Symmetric group of order 4! as a permutation group
+              To:   Symmetric group of order 7! as a permutation group
               Defn:   Composite map:
-                      From: SymmetricGroup(4)
-                      To:   SymmetricGroup(6)
+                      From: Symmetric group of order 4! as a permutation group
+                      To:   Symmetric group of order 6! as a permutation group
                       Defn:   Call morphism:
-                              From: SymmetricGroup(4)
-                              To:   SymmetricGroup(5)
+                              From: Symmetric group of order 4! as a permutation group
+                              To:   Symmetric group of order 5! as a permutation group
                             then
                               Coercion morphism:
-                              From: SymmetricGroup(5)
-                              To:   SymmetricGroup(6)
+                              From: Symmetric group of order 5! as a permutation group
+                              To:   Symmetric group of order 6! as a permutation group
                     then
                       Call morphism:
-                      From: SymmetricGroup(6)
-                      To:   SymmetricGroup(7)
+                      From: Symmetric group of order 6! as a permutation group
+                      To:   Symmetric group of order 7! as a permutation group
 
             sage: H = Hom(ZZ, ZZ, Sets())
             sage: f = H( lambda x: x + 1 )
diff --git a/sage/categories/hopf_algebras_with_basis.py b/sage/categories/hopf_algebras_with_basis.py
--- a/sage/categories/hopf_algebras_with_basis.py
+++ b/sage/categories/hopf_algebras_with_basis.py
@@ -123,7 +123,7 @@
         An other group can be specified as optional argument::
 
             sage: HopfAlgebrasWithBasis(QQ).example(SymmetricGroup(4))
-            An example of Hopf algebra with basis: the group algebra of the SymmetricGroup(4) over Rational Field
+            An example of Hopf algebra with basis: the group algebra of the Symmetric group of order 4! as a permutation group over Rational Field
         """
         from sage.categories.examples.hopf_algebras_with_basis import MyGroupAlgebra
         from sage.groups.perm_gps.permgroup_named import DihedralGroup
diff --git a/sage/categories/map.pyx b/sage/categories/map.pyx
--- a/sage/categories/map.pyx
+++ b/sage/categories/map.pyx
@@ -115,7 +115,7 @@
             sage: Map(QQ['x'], SymmetricGroup(6))
             Generic map:
               From: Univariate Polynomial Ring in x over Rational Field
-              To:   SymmetricGroup(6)
+              To:   Symmetric group of order 6! as a permutation group
         """
         if codomain is not None:
             if PY_TYPE_CHECK(parent, type):
diff --git a/sage/categories/pushout.py b/sage/categories/pushout.py
--- a/sage/categories/pushout.py
+++ b/sage/categories/pushout.py
@@ -2710,16 +2710,17 @@
 
     rank = 10
 
-    def __init__(self, gens):
+    def __init__(self, gens, domain):
         """
         EXAMPLES::
 
             sage: from sage.categories.pushout import PermutationGroupFunctor
-            sage: PF = PermutationGroupFunctor([PermutationGroupElement([(1,2)])]); PF
+            sage: PF = PermutationGroupFunctor([PermutationGroupElement([(1,2)])], [1,2]); PF
             PermutationGroupFunctor[(1,2)]
         """
         Functor.__init__(self, Groups(), Groups())
         self._gens = gens
+        self._domain = domain
 
     def __repr__(self):
         """
@@ -2742,7 +2743,8 @@
             Permutation Group with generators [(1,2)]
         """
         from sage.groups.perm_gps.permgroup import PermutationGroup
-        return PermutationGroup([g for g in (R.gens() + self.gens()) if not g.is_one()])
+        return PermutationGroup([g for g in (R.gens() + self.gens()) if not g.is_one()],
+                                domain=self._domain)
 
     def gens(self):
         """
@@ -2770,7 +2772,12 @@
         """
         if self.__class__ != other.__class__:
             return None
-        return PermutationGroupFunctor(self.gens() + other.gens())
+        from sage.sets.all import FiniteEnumeratedSet
+
+        new_domain = set(self._domain).union(set(other._domain))
+        new_domain = FiniteEnumeratedSet(sorted(new_domain))
+        return PermutationGroupFunctor(self.gens() + other.gens(),
+                                       new_domain)
 
 class BlackBoxConstructionFunctor(ConstructionFunctor):
     """
diff --git a/sage/combinat/permutation.py b/sage/combinat/permutation.py
--- a/sage/combinat/permutation.py
+++ b/sage/combinat/permutation.py
@@ -562,6 +562,8 @@
                 cycles.append(tuple(cycle))
         return cycles
 
+    cycle_tuples = to_cycles
+
     def _to_cycles_orig(self, singletons=True):
         r"""
         Returns the permutation p as a list of disjoint cycles.
@@ -3423,6 +3425,8 @@
     
     p = range(1,n+1)
     for cycle in cycles:
+        if not cycle:
+            continue
         first = cycle[0]
         for i in range(len(cycle)-1):
             p[cycle[i]-1] = cycle[i+1]
diff --git a/sage/combinat/species/cycle_species.py b/sage/combinat/species/cycle_species.py
--- a/sage/combinat/species/cycle_species.py
+++ b/sage/combinat/species/cycle_species.py
@@ -100,10 +100,10 @@
             sage: [a.transport(perm) for perm in a.automorphism_group()]
             [(1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4)]
         """
-        from sage.groups.all import SymmetricGroup
+        from sage.groups.all import SymmetricGroup, PermutationGroup
         S = SymmetricGroup(len(self._labels))
         p = self.permutation_group_element()
-        return S.centralizer(p)
+        return PermutationGroup(S.centralizer(p).gens())
 
 @accept_size
 @cached_function
diff --git a/sage/combinat/species/permutation_species.py b/sage/combinat/species/permutation_species.py
--- a/sage/combinat/species/permutation_species.py
+++ b/sage/combinat/species/permutation_species.py
@@ -98,10 +98,10 @@
              ['a', 'c', 'b', 'd'],
              ['a', 'c', 'b', 'd']]
         """
-        from sage.groups.all import SymmetricGroup
+        from sage.groups.all import SymmetricGroup, PermutationGroup
         S = SymmetricGroup(len(self._labels))
         p = self.permutation_group_element()
-        return S.centralizer(p)
+        return PermutationGroup(S.centralizer(p).gens())
         
 @accept_size
 @cached_function
diff --git a/sage/groups/abelian_gps/abelian_group.py b/sage/groups/abelian_gps/abelian_group.py
--- a/sage/groups/abelian_gps/abelian_group.py
+++ b/sage/groups/abelian_gps/abelian_group.py
@@ -830,7 +830,7 @@
             sage: G = AbelianGroup(2,[2,3]); G
             Multiplicative Abelian Group isomorphic to C2 x C3
             sage: G.permutation_group()
-            Permutation Group with generators [(1,4)(2,5)(3,6), (1,2,3)(4,5,6)]
+            Permutation Group with generators [(1,2,3)(4,5,6), (1,4)(2,5)(3,6)]
         """
         from sage.groups.perm_gps.permgroup import PermutationGroup
         s = 'Image(IsomorphismPermGroup(%s))'%self._gap_init_()
diff --git a/sage/groups/abelian_gps/abelian_group_element.py b/sage/groups/abelian_gps/abelian_group_element.py
--- a/sage/groups/abelian_gps/abelian_group_element.py
+++ b/sage/groups/abelian_gps/abelian_group_element.py
@@ -227,7 +227,7 @@
             Multiplicative Abelian Group isomorphic to C2 x C3 x C4
             sage: a,b,c=G.gens()
             sage: Gp = G.permutation_group(); Gp
-            Permutation Group with generators [(1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24), (1,5,9)(2,6,10)(3,7,11)(4,8,12)(13,17,21)(14,18,22)(15,19,23)(16,20,24), (1,3,2,4)(5,7,6,8)(9,11,10,12)(13,15,14,16)(17,19,18,20)(21,23,22,24)]
+            Permutation Group with generators [(1,3,2,4)(5,7,6,8)(9,11,10,12)(13,15,14,16)(17,19,18,20)(21,23,22,24), (1,5,9)(2,6,10)(3,7,11)(4,8,12)(13,17,21)(14,18,22)(15,19,23)(16,20,24), (1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)]
             sage: a.as_permutation()
             (1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)
             sage: ap = a.as_permutation(); ap
diff --git a/sage/groups/class_function.py b/sage/groups/class_function.py
--- a/sage/groups/class_function.py
+++ b/sage/groups/class_function.py
@@ -407,7 +407,7 @@
             Character of Symmetric group of order 5! as a permutation group
             sage: H = G.subgroup([(1,2,3), (1,2), (4,5)])
             sage: chi.restrict(H)
-            Character of Subgroup of SymmetricGroup(5) generated by [(4,5), (1,2), (1,2,3)]
+            Character of Subgroup of (Symmetric group of order 5! as a permutation group) generated by [(4,5), (1,2), (1,2,3)]
             sage: chi.restrict(H).values()
             [3, -3, -3, -1, 0, 0]
         """
@@ -420,7 +420,7 @@
             sage: G = SymmetricGroup(5)
             sage: H = G.subgroup([(1,2,3), (1,2), (4,5)])
             sage: xi = H.trivial_character(); xi
-            Character of Subgroup of SymmetricGroup(5) generated by [(4,5), (1,2), (1,2,3)]
+            Character of Subgroup of (Symmetric group of order 5! as a permutation group) generated by [(4,5), (1,2), (1,2,3)]
             sage: xi.induct(G)
             Character of Symmetric group of order 5! as a permutation group
             sage: xi.induct(G).values()
diff --git a/sage/groups/perm_gps/permgroup.py b/sage/groups/perm_gps/permgroup.py
--- a/sage/groups/perm_gps/permgroup.py
+++ b/sage/groups/perm_gps/permgroup.py
@@ -125,11 +125,13 @@
 from sage.rings.all import QQ, Integer
 from sage.interfaces.all import is_ExpectElement
 from sage.interfaces.gap import gap, GapElement
-from sage.groups.perm_gps.permgroup_element import PermutationGroupElement
+from sage.groups.perm_gps.permgroup_element import PermutationGroupElement, standardize_generator
 from sage.groups.abelian_gps.abelian_group import AbelianGroup
 from sage.misc.cachefunc import cached_method
 from sage.groups.class_function import ClassFunction
 from sage.misc.package import is_package_installed
+from sage.sets.all import FiniteEnumeratedSet
+from sage.categories.all import FiniteEnumeratedSets
 
 def load_hap():
     """
@@ -231,7 +233,7 @@
     srcs = map(G, srcs)
     return srcs
 
-def PermutationGroup(gens=None, gap_group=None, canonicalize=True):
+def PermutationGroup(gens=None, gap_group=None, domain=None, canonicalize=True, category=None):
     """
     Return the permutation group associated to `x` (typically a
     list of generators).
@@ -301,7 +303,8 @@
         return gens._permgroup_()
     if gens is not None and not isinstance(gens, (tuple, list, GapElement)):
         raise TypeError, "gens must be a tuple, list, or GapElement"
-    return PermutationGroup_generic(gens=gens, gap_group=gap_group, canonicalize=canonicalize)
+    return PermutationGroup_generic(gens=gens, gap_group=gap_group, domain=domain,
+                                    canonicalize=canonicalize, category=category)
     
 
 class PermutationGroup_generic(group.Group):
@@ -312,7 +315,7 @@
         sage: G
         Permutation Group with generators [(3,4), (1,2,3)(4,5)]
         sage: G.center()
-        Permutation Group with generators [()]
+        Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]
         sage: G.group_id()          # optional - database_gap
         [120, 34]
         sage: n = G.order(); n
@@ -320,7 +323,7 @@
         sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])
         sage: TestSuite(G).run()
     """
-    def __init__(self, gens=None, gap_group=None, canonicalize=True):
+    def __init__(self, gens=None, gap_group=None, canonicalize=True, domain=None, category=None):
         r"""
         INPUT:
         
@@ -347,7 +350,7 @@
             sage: A4.__init__([[(1,2,3)],[(2,3,4)]]); A4
             Permutation Group with generators [(2,3,4), (1,2,3)]
             sage: A4.center()
-            Permutation Group with generators [()]
+            Subgroup of (Permutation Group with generators [(2,3,4), (1,2,3)]) generated by [()]
             sage: A4.category()
             Category of finite permutation groups
             sage: TestSuite(A4).run()
@@ -358,28 +361,44 @@
             sage: TestSuite(PermutationGroup([])).run()
         """
         from sage.categories.finite_permutation_groups import FinitePermutationGroups
-        super(PermutationGroup_generic, self).__init__(category = FinitePermutationGroups())
+        super(PermutationGroup_generic, self).__init__(category = FinitePermutationGroups().or_subcategory(category))
         if (gens is None and gap_group is None):
             raise ValueError, "you must specify gens or gap_group"
 
         #Handle the case where only the GAP group is specified.
         if gens is None:
-            from sage.interfaces.gap import gap
-            self._gap_string = gap_group if isinstance(gap_group, str) else str(gap_group)
-            self._gens = self._gens_from_gap()
-            self._deg = gap(gap_group).LargestMovedPoint()
-            self._set = range(1, self._deg+1)
-        else:
-            gens = [self._element_class()(x, check=False).list() for x in gens]
-            self._deg = max([0]+[max(g) for g in gens])
-            self._set = range(1, self._deg+1)
-            if not gens:  # length 0
-                gens = [()]
-            gens = [self._element_class()(x, self, check=False) for x in gens]
-            if canonicalize:
-                gens = sorted(set(gens))
-            self._gens = gens
-            self._gap_string = 'Group(%s)'%gens
+            if isinstance(gap_group, str):
+                gap_group = gap(gap_group)
+            gens = [gen for gen in gap_group.GeneratorsOfGroup()]
+
+        if domain is None:
+            gens = [standardize_generator(x) for x in gens]
+            domain = set()
+            for x in gens:
+                for cycle in x:
+                    domain = domain.union(cycle)
+            domain = sorted(domain)
+
+            #Here we need to check if all of the points are integers
+            #to make the domain contain all integers up to the max.
+            #This is needed for backward compatibility
+            if all(isinstance(p, (Integer, int, long)) for p in domain):
+                domain = range(1, max([1] + domain)+1)
+
+        if domain not in FiniteEnumeratedSets():
+            domain = FiniteEnumeratedSet(domain)
+
+        self._domain = domain
+        self._deg = len(self._domain)
+        self._domain_to_gap = dict((key, i+1) for i, key in enumerate(self._domain))
+        self._domain_from_gap = dict((i+1, key) for i, key in enumerate(self._domain))
+
+        if not gens:  # length 0
+            gens = [()]
+        gens = [self._element_class()(x, self, check=False) for x in gens]
+        if canonicalize:
+            gens = sorted(set(gens))
+        self._gens = gens
 
     def construction(self):
          """
@@ -400,36 +419,46 @@
              (1,2,3)
              sage: p.parent()
              Permutation Group with generators [(1,2), (1,3)]
+             sage: p.parent().domain()
+             {1, 2, 3}
+
+         Note that this will merge permutation groups with different
+         domains::
+
+             sage: g1 = PermutationGroupElement([(1,2),(3,4,5)])
+             sage: g2 = PermutationGroup([('a','b')], domain=['a', 'b']).gens()[0]
+             sage: g2
+             ('a','b')
+             sage: p = g1*g2; p
+             (1,2)(3,4,5)('a','b')
          """
          gens = self.gens()
          if len(gens) == 1 and gens[0].is_one():
               return None
          else:
               from sage.categories.pushout import PermutationGroupFunctor
-              return (PermutationGroupFunctor(gens), PermutationGroup([]))
-
-    def _gens_from_gap(self):
+              return (PermutationGroupFunctor(gens, self.domain()),
+                      PermutationGroup([]))
+
+    @cached_method
+    def _has_natural_domain(self):
         """
-        Returns the generators of the group by asking GAP for them.
-        
+        Returns True if the underlying domain is of the form (1,...,n)
+
         EXAMPLES::
-        
-            sage: S = SymmetricGroup(3)
-            sage: S._gap_string
-            'SymmetricGroup(3)'
-            sage: S._gens_from_gap()
-            [(1,2,3), (1,2)]
+
+            sage: SymmetricGroup(3)._has_natural_domain()
+            True
+            sage: SymmetricGroup((1,2,3))._has_natural_domain()
+            True
+            sage: SymmetricGroup((1,3))._has_natural_domain()
+            False
+            sage: SymmetricGroup((3,2,1))._has_natural_domain()
+            False
         """
-        try:
-            gens = self._gap_().GeneratorsOfGroup()
-        except TypeError, s:
-            raise RuntimeError, "(It might be necessary to install the database_gap optional Sage package, if you haven't already.)\n%s"%s
-        gens = [self._element_class()(gens[n], self, check=False)
-                       for n in range(1, int(gens.Length())+1)]
-        if gens == []:
-            gens = [()]
-        return gens
-
+        domain = self.domain()
+        natural_domain = FiniteEnumeratedSet(range(1, len(domain)+1))
+        return domain == natural_domain
 
     def _gap_init_(self):
         r"""
@@ -445,14 +474,14 @@
             sage: A4 = PermutationGroup([[(1,2,3)],[(2,3,4)]]); A4
             Permutation Group with generators [(2,3,4), (1,2,3)]
             sage: A4._gap_init_()
-            'Group([(2,3,4), (1,2,3)])'
+            'Group([PermList([1, 3, 4, 2]), PermList([2, 3, 1, 4])])'
         """
-        return self._gap_string
+        return 'Group([%s])'%(', '.join([g._gap_init_() for g in self.gens()]))
 
     def _magma_init_(self, magma):
         r"""
         Returns a string showing how to declare / initialize self in Magma.
-        
+    
         EXAMPLES:
 
         We explicitly construct the alternating group on four
@@ -463,8 +492,12 @@
             Permutation Group with generators [(2,3,4), (1,2,3)]
             sage: A4._magma_init_(magma)
             'PermutationGroup<4 | (2,3,4), (1,2,3)>'
+
+            sage: S = SymmetricGroup(['a', 'b', 'c'])
+            sage: S._magma_init_(magma)
+            'PermutationGroup<3 | (1,2,3), (1,2)>'
         """
-        g = str(self.gens())[1:-1]
+        g = ', '.join([g._gap_cycle_string() for g in self.gens()])
         return 'PermutationGroup<%s | %s>'%(self.degree(), g)
 
     def __cmp__(self, right):
@@ -500,9 +533,9 @@
             True
             sage: H3 < H1 # since H3 is a subgroup of H1
             True
-
         """
-        if not isinstance(right, PermutationGroup_generic):
+        if (not isinstance(right, PermutationGroup_generic) or
+            self.domain() != right.domain()):
             return -1
         if self is right:
             return 0
@@ -581,7 +614,7 @@
             sage: G([(1,2)])
             Traceback (most recent call last):
             ...
-            TypeError: permutation (1, 2) not in Permutation Group with generators [(1,2,3,4)]
+            TypeError: permutation [(1, 2)] not in Permutation Group with generators [(1,2,3,4)]
         """
         try:
             if x.parent() is self:
@@ -630,9 +663,10 @@
             x_parent = x.parent()
             if x_parent is self:
                 return x
-            elif (x_parent.degree() <= self.degree() and
-                  (self.__class__ == SymmetricGroup or x._gap_() in self._gap_())):
-                return self._element_class()(x.list(), self, check = False)
+
+            compatible_domains = all(point in self._domain_to_gap for point in x_parent.domain())
+            if  compatible_domains and (self.__class__ == SymmetricGroup or x._gap_() in self._gap_()):
+                return self._element_class()(x.cycle_tuples(), self, check=False)
         raise TypeError, "no implicit coercion of element into permutation group"
 
     @cached_method
@@ -645,12 +679,13 @@
             sage: G = PermutationGroup([[(1,2,3,4)], [(1,2)]])
             sage: G.list()
             [(), (3,4), (2,3), (2,3,4), (2,4,3), (2,4), (1,2), (1,2)(3,4), (1,2,3), (1,2,3,4), (1,2,4,3), (1,2,4), (1,3,2), (1,3,4,2), (1,3), (1,3,4), (1,3)(2,4), (1,3,2,4), (1,4,3,2), (1,4,2), (1,4,3), (1,4), (1,4,2,3), (1,4)(2,3)]
+
+            sage: G = PermutationGroup([[('a','b')]], domain=('a', 'b')); G
+            Permutation Group with generators [('a','b')]
+            sage: G.list()
+            [(), ('a','b')]
         """
-        X = self._gap_().Elements()
-        n = X.Length()
-        L = [self._element_class()(X[i], self, check = False)
-                            for i in range(1,n+1)]
-        return L
+        return list(self.__iter__())
 
     def __contains__(self, item):
         """
@@ -671,6 +706,10 @@
             True
             sage: h in H
             False
+
+            sage: G = PermutationGroup([[('a','b')]], domain=('a', 'b'))
+            sage: [('a', 'b')] in G
+            True
         """
         try:
             item = self(item, check=True)
@@ -709,11 +748,9 @@
             sage: G = PermutationGroup([[(1,2,3)], [(1,2)]])
             sage: [a for a in G]
             [(), (2,3), (1,2), (1,2,3), (1,3,2), (1,3)]
-
-        TODO: this currently returns an iterator over the elements of
-        ``self.list()``. This should be made into a real iterator.
         """
-        return iter(self.list())
+        for g in self._gap_().Elements():
+            yield self._element_class()(g, self, check=False)
 
     def gens(self):
         """
@@ -769,6 +806,10 @@
             sage: G = PermutationGroup([R,L,U,F,B,D])
             sage: len(G.gens_small())
             2
+
+            sage: G = PermutationGroup([[('a','b')], [('b', 'c')], [('a', 'c')]])
+            sage: G.gens_small()
+            [('a','b'), ('a','b','c')]
         """
         gens = self._gap_().SmallGeneratingSet()
         return [self._element_class()(x, self, check=False) for x in gens]
@@ -825,6 +866,10 @@
             (1,2,3)(4,5)
             sage: e*g
             (1,2,3)(4,5)
+
+            sage: S = SymmetricGroup(['a','b','c'])
+            sage: S.identity()
+            ()
         """
         return self._element_class()([], self, check=True)
    
@@ -858,61 +903,82 @@
         
         ::
         
-            sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])
+            sage: G = PermutationGroup([[('a','b','c'),('d','e')]])
+            sage: G.largest_moved_point()
+            'e'
+
+        .. warning::
+
+           The name of this function is not good; this function
+           should be deprecated in term of degree::
+
+                sage: P = PermutationGroup([[1,2,3,4]])
+                sage: P.largest_moved_point()
+                4
+                sage: P.cardinality()
+                1
+        """
+        try:
+            return self._domain_from_gap[Integer(self._gap_().LargestMovedPoint())]
+        except KeyError:
+            return self.degree()
+
+    def degree(self):
+        """
+        Returns the degree of this permutation group.
+
+        EXAMPLES::
+
+            sage: S = SymmetricGroup(['a','b','c'])
+            sage: S.degree()
+            3
+            sage: G = PermutationGroup([(1,3),(4,5)])
             sage: G.degree()
             5
 
-        TODO: the name of this function is not good; this function
-        should be deprecated in term of degree::
-
-            sage: P = PermutationGroup([[1,2,3,4]])
-            sage: P.largest_moved_point()
+        Note that you can explicitly specify the domain to get a
+        permutation group of smaller degree::
+        
+            sage: G = PermutationGroup([(1,3),(4,5)], domain=[1,3,4,5])
+            sage: G.degree()
             4
-            sage: P.cardinality()
-            1
         """
-        # This seems unndeeded since __init__ systematically sets
-        # self._deg This is actually needed because constructing the
-        # __init__ of PermutationGroupElement sometimes calls this
-        # group before is initialized.
-        try:
-            return self._deg
-        except AttributeError:
-            n = Integer(self._gap_().LargestMovedPoint())
-        self._deg = n
-        return n
-
-    degree = largest_moved_point
-
-    def set(self):
+        return Integer(len(self._domain))
+
+    def domain(self):
         r"""
         Returns the underlying set that this permutation group acts
-        on.  By default, the set is {1, ..., n} where n is the largest
-        moved point by the group.
+        on.
 
         EXAMPLES::
 
             sage: P = PermutationGroup([(1,2),(3,5)])
-            sage: P.set()
-            (1, 2, 3, 4, 5)
-
+            sage: P.domain()
+            {1, 2, 3, 4, 5}
+            sage: S = SymmetricGroup(['a', 'b', 'c'])
+            sage: S.domain()
+            {'a', 'b', 'c'}
         """
-        return tuple(self._set)
-
-    domain = set
-
-    def _set_gap(self):
+        return self._domain
+
+    def _domain_gap(self, domain=None):
         """
         Returns a GAP string representation of the underlying set
-        that this group acts on.  See also :meth:`set`.
+        that this group acts on.  See also :meth:`domain`.
 
         EXAMPLES::
 
             sage: P = PermutationGroup([(1,2),(3,5)])
-            sage: P._set_gap()
+            sage: P._domain_gap()
             '[1, 2, 3, 4, 5]'
         """
-        return repr(list(self.set()))
+        if domain is None:
+            return repr(range(1, self.degree()+1))
+        else:
+            try:
+                return repr([self._domain_to_gap[point] for point in domain])
+            except KeyError:
+                raise ValueError, "domain must be a subdomain of self.domain()"
 
     @cached_method
     def smallest_moved_point(self):
@@ -927,13 +993,20 @@
             sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
             sage: G.smallest_moved_point()
             1
+
+        Note that this function uses the ordering from the domain::
+
+            sage: S = SymmetricGroup(['a','b','c'])
+            sage: S.smallest_moved_point()
+            'a'
         """
-        return Integer(self._gap_().SmallestMovedPoint())
+        return self._domain_from_gap[Integer(self._gap_().SmallestMovedPoint())]
 
     @cached_method
     def orbits(self):
         """
-        Returns the orbits of [1,2,...,degree] under the group action.
+        Returns the orbits of the elements of the domain under the
+        group action.
         
         EXAMPLES::
         
@@ -943,6 +1016,10 @@
             sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
             sage: G.orbits()
             [[1, 2, 3, 4, 10], [5], [6], [7], [8], [9]]
+
+            sage: G = PermutationGroup([ [('c','d')], [('a','c')],[('b',)]])
+            sage: G.orbits()
+            [['a', 'c', 'd'], ['b']]
         
         The answer is cached::
         
@@ -953,12 +1030,13 @@
 
         - Nathan Dunfield
         """
-        return self._gap_().Orbits(self._set_gap()).sage()
+        return [[self._domain_from_gap[x] for x in orbit] for orbit in
+                self._gap_().Orbits(self._domain_gap()).sage()]
 
     @cached_method
-    def orbit(self, integer):
+    def orbit(self, point):
         """
-        Return the orbit of the given integer under the group action.
+        Return the orbit of the given point under the group action.
 
         EXAMPLES::
 
@@ -968,10 +1046,15 @@
             sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
             sage: G.orbit(3)                                                 
             [3, 4, 10, 1, 2]
-        """
-        return self._gap_().Orbit(integer).sage()
+
+            sage: G = PermutationGroup([ [('c','d')], [('a','c')] ])
+            sage: G.orbit('a')
+            ['a', 'c', 'd']
+        """ 
+        point = self._domain_to_gap[point]
+        return [self._domain_from_gap[x] for x in self._gap_().Orbit(point).sage()]
     
-    def transversals(self, integer):
+    def transversals(self, point):
         """
         If G is a permutation group acting on the set `X = \{1, 2, ...., n\}` 
         and H is the stabilizer subgroup of <integer>, a right 
@@ -988,13 +1071,16 @@
             sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
             sage: G.transversals(1)                                    
             [(), (1,2)(3,4), (1,3,2,10,4), (1,4,2,10,3), (1,10,4,3,2)]
+
+            sage: G = PermutationGroup([ [('c','d')], [('a','c')] ])
+            sage: G.transversals('a')
+            [(), ('a','c','d'), ('a','d','c')]            
         """
-        trans = []
-        for i in self.orbit(integer):
-             trans.append(self(gap.RepresentativeAction(self._gap_(),integer,i)))
-        return trans
-
-    def stabilizer(self, position):
+        G = self._gap_()
+        return [self(G.RepresentativeAction(self._domain_to_gap[point], self._domain_to_gap[i]))
+                for i in self.orbit(point)]
+
+    def stabilizer(self, point):
         """
         Return the subgroup of ``self`` which stabilize the given position.
         ``self`` and its stabilizers must have same degree.
@@ -1003,35 +1089,39 @@
 
             sage: G = PermutationGroup([ [(3,4)], [(1,3)] ])
             sage: G.stabilizer(1)
-            Permutation Group with generators [(3,4)]
+            Subgroup of (Permutation Group with generators [(3,4), (1,3)]) generated by [(3,4)]
             sage: G.stabilizer(3)
-            Permutation Group with generators [(1,4)]
+            Subgroup of (Permutation Group with generators [(3,4), (1,3)]) generated by [(1,4)]
             sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
             sage: G.stabilizer(10)
-            Permutation Group with generators [(1,2)(3,4), (2,3,4)]
+            Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4,10)]) generated by [(2,3,4), (1,2)(3,4)]
             sage: G.stabilizer(1) 
-            Permutation Group with generators [(2,3)(4,10), (2,10,4)]
+            Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4,10)]) generated by [(2,3)(4,10), (2,10,4)]
             sage: G = PermutationGroup([[(2,3,4)],[(6,7)]])
             sage: G.stabilizer(1)
-            Permutation Group with generators [(6,7), (2,3,4)]
+            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7), (2,3,4)]
             sage: G.stabilizer(2)
-            Permutation Group with generators [(6,7)]
+            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7)]
             sage: G.stabilizer(3)
-            Permutation Group with generators [(6,7)]
+            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7)]
             sage: G.stabilizer(4)
-            Permutation Group with generators [(6,7)]
+            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7)]
             sage: G.stabilizer(5)
-            Permutation Group with generators [(6,7), (2,3,4)]
+            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7), (2,3,4)]
             sage: G.stabilizer(6)
-            Permutation Group with generators [(2,3,4)]
+            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(2,3,4)]
             sage: G.stabilizer(7)
-            Permutation Group with generators [(2,3,4)]
+            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(2,3,4)]
             sage: G.stabilizer(8)
-            Permutation Group with generators [(6,7), (2,3,4)]
+            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7), (2,3,4)]
         """
-        return PermutationGroup(gap_group=gap.Stabilizer(self, position))
-
-    def strong_generating_system(self, base_of_group = None):
+        try:
+            position = self._domain_to_gap[point]
+        except KeyError:
+            return self.subgroup(gens=self.gens())
+        return self.subgroup(gap_group=gap.Stabilizer(self, point))
+
+    def strong_generating_system(self, base_of_group=None):
         """
         Return a Strong Generating System of ``self`` according the given 
         base for the right action of ``self`` on itself.
@@ -1080,7 +1170,7 @@
             [[(), (1,2)(3,4), (1,3)(2,4), (1,4)(2,3)], [(), (2,3,4), (2,4,3)], [(), (3,4)], [()]]
             sage: G = PermutationGroup([[(1,2,3)],[(4,5,7)],[(1,4,6)]])
             sage: G.strong_generating_system()                         
-            [[(), (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)], [()], [()]]
+            [[(), (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,5,7,6,3), (2,3,6), (2,7,5,6,3), (2,4,7,6,3)], [(), (3,6,7), (3,5,6), (3,7,6), (3,4,7,5,6)], [(), (4,5)(6,7), (4,7)(5,6), (4,6)(5,7)], [(), (5,7,6), (5,6,7)], [()], [()]]
             sage: G = PermutationGroup([[(1,2,3)],[(2,3,4)],[(3,4,5)]])
             sage: G.strong_generating_system([5,4,3,2,1])              
             [[(), (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)], [()], [()]]
@@ -1096,7 +1186,7 @@
         sgs = []
         stab = self
         if base_of_group is None:
-            base_of_group = self.set()
+            base_of_group = self.domain()
         for j in base_of_group:
             sgs.append(stab.transversals(j))
             stab = stab.stabilizer(j)
@@ -1140,6 +1230,10 @@
             \langle (2,3,4), (1,2,3) \rangle
             sage: A4._latex_()
             '\\langle (2,3,4), (1,2,3) \\rangle'
+
+            sage: S = SymmetricGroup(['a','b','c'])
+            sage: latex(S)
+            \langle (\texttt{a},\texttt{b},\texttt{c}), (\texttt{a},\texttt{b}) \rangle
         """
         return '\\langle ' + \
                ', '.join([x._latex_() for x in self.gens()]) + ' \\rangle'
@@ -1218,12 +1312,82 @@
         
             sage: G = PermutationGroup([[(1,2,3,4)]])
             sage: G.center()
-            Permutation Group with generators [(1,2,3,4)]
+            Subgroup of (Permutation Group with generators [(1,2,3,4)]) generated by [(1,2,3,4)]
             sage: G = PermutationGroup([[(1,2,3,4)], [(1,2)]])
             sage: G.center()
-            Permutation Group with generators [()]
+            Subgroup of (Permutation Group with generators [(1,2), (1,2,3,4)]) generated by [()]
         """
-        return PermutationGroup(gap_group=self._gap_().Center())
+        return self.subgroup(gap_group=self._gap_().Center())
+
+    def socle(self):
+        r"""
+        Returns the socle of ``self``. The socle of a group $G$ is
+        the subgroup generated by all minimal normal subgroups.
+        
+        EXAMPLES::
+        
+            sage: G=SymmetricGroup(4)
+            sage: G.socle()
+            Subgroup of (Symmetric group of order 4! as a permutation group) generated by [(1,2)(3,4), (1,4)(2,3)]
+            sage: G.socle().socle()
+            Subgroup of (Subgroup of (Symmetric group of order 4! as a permutation group) generated by [(1,2)(3,4), (1,4)(2,3)]) generated by [(1,3)(2,4), (1,4)(2,3)]
+        
+        """
+        return self.subgroup(gap_group=self._gap_().Socle())
+        
+    def frattini_subgroup(self):
+        r"""
+        Returns the Frattini subgroup of ``self``. The Frattini
+        subgroup of a group $G$ is the intersection of all
+        maximal subgroups of $G$.
+        
+        EXAMPLES::
+        
+            sage: G=PermutationGroup([[(1,2,3,4)],[(2,4)]])
+            sage: G.frattini_subgroup()
+            Subgroup of (Permutation Group with generators [(2,4), (1,2,3,4)]) generated by [(1,3)(2,4)]
+            sage: G=SymmetricGroup(4)
+            sage: G.frattini_subgroup()
+            Subgroup of (Symmetric group of order 4! as a permutation group) generated by [()]
+        
+        """
+        return self.subgroup(gap_group=self._gap_().FrattiniSubgroup())
+        
+    def fitting_subgroup(self):
+        r"""
+        Returns the Fitting subgroup of ``self``. The Fitting
+        subgroup of a group $G$ is the largest nilpotent normal
+        subgroup of $G$.
+        
+        EXAMPLES::
+        
+            sage: G=PermutationGroup([[(1,2,3,4)],[(2,4)]])
+            sage: G.fitting_subgroup()
+            Subgroup of (Permutation Group with generators [(2,4), (1,2,3,4)]) generated by [(2,4), (1,2,3,4), (1,3)]
+            sage: G=PermutationGroup([[(1,2,3,4)],[(1,2)]])
+            sage: G.fitting_subgroup()
+            Subgroup of (Permutation Group with generators [(1,2), (1,2,3,4)]) generated by [(1,2)(3,4), (1,3)(2,4)]
+        
+        """
+        return self.subgroup(gap_group=self._gap_().FittingSubgroup())
+        
+    def solvable_radical(self):
+        r"""
+        Returns the solvable radical of ``self``. The solvable
+        radical (or just radical) of a group $G$ is the largest
+        solvable normal subgroup of $G$.
+        
+        EXAMPLES::
+        
+            sage: G=SymmetricGroup(4)
+            sage: G.solvable_radical()
+            Subgroup of (Symmetric group of order 4! as a permutation group) generated by [(1,2), (1,2,3,4)]
+            sage: G=SymmetricGroup(5)
+            sage: G.solvable_radical()
+            Subgroup of (Symmetric group of order 5! as a permutation group) generated by [()]
+            
+        """
+        return self.subgroup(gap_group=self._gap_().RadicalGroup())
 
     def intersection(self, other):
         r"""
@@ -1310,7 +1474,7 @@
             sage: G = DihedralGroup(6)
             sage: a = PermutationGroupElement("(1,2,3,4)")
             sage: G.conjugate(a)
-            Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]
+            Permutation Group with generators [(1,4)(2,6)(3,5), (1,5,6,2,3,4)]
 
         The element performing the conjugation can be specified in
         several ways.  ::
@@ -1318,15 +1482,15 @@
             sage: G = DihedralGroup(6)
             sage: strng = "(1,2,3,4)"
             sage: G.conjugate(strng)
-            Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]
+            Permutation Group with generators [(1,4)(2,6)(3,5), (1,5,6,2,3,4)]
             sage: G = DihedralGroup(6)
             sage: lst = [2,3,4,1]
             sage: G.conjugate(lst)
-            Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]
+            Permutation Group with generators [(1,4)(2,6)(3,5), (1,5,6,2,3,4)]
             sage: G = DihedralGroup(6)
             sage: cycles = [(1,2,3,4)]
             sage: G.conjugate(cycles)
-            Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]
+            Permutation Group with generators [(1,4)(2,6)(3,5), (1,5,6,2,3,4)]
 
         Conjugation is a group automorphism, so conjugate groups
         will be isomorphic. ::
@@ -1379,14 +1543,10 @@
 
         INPUT:
         
-        
         -  ``self, other`` - permutation groups
         
-        
-        
         OUTPUT:
         
-        
         -  ``D`` - a direct product of the inputs, returned as
            a permutation group as well
         
@@ -1400,30 +1560,29 @@
         -  ``pr2`` - the projection of ``D`` onto ``other`` (giving a
            splitting 1 - self - D - other - 1)
         
-        
         EXAMPLES::
         
             sage: G = CyclicPermutationGroup(4)
             sage: D = G.direct_product(G,False)
             sage: D
-            Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
+            Permutation Group with generators [(5,6,7,8), (1,2,3,4)]
             sage: D,iota1,iota2,pr1,pr2 = G.direct_product(G)
             sage: D; iota1; iota2; pr1; pr2
-            Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
+            Permutation Group with generators [(5,6,7,8), (1,2,3,4)]
             Permutation group morphism:
               From: Cyclic group of order 4 as a permutation group
-              To:   Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
+              To:   Permutation Group with generators [(5,6,7,8), (1,2,3,4)]
               Defn: Embedding( Group( [ (1,2,3,4), (5,6,7,8) ] ), 1 )
             Permutation group morphism:
               From: Cyclic group of order 4 as a permutation group
-              To:   Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
+              To:   Permutation Group with generators [(5,6,7,8), (1,2,3,4)]
               Defn: Embedding( Group( [ (1,2,3,4), (5,6,7,8) ] ), 2 )
             Permutation group morphism:
-              From: Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
+              From: Permutation Group with generators [(5,6,7,8), (1,2,3,4)]
               To:   Cyclic group of order 4 as a permutation group
               Defn: Projection( Group( [ (1,2,3,4), (5,6,7,8) ] ), 1 )
             Permutation group morphism:
-              From: Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
+              From: Permutation Group with generators [(5,6,7,8), (1,2,3,4)]
               To:   Cyclic group of order 4 as a permutation group
               Defn: Projection( Group( [ (1,2,3,4), (5,6,7,8) ] ), 2 )
             sage: g=D([(1,3),(2,4)]); g
@@ -1436,7 +1595,7 @@
             (1,4,3,2)
             (1,3)(2,4)
         """
-        G = self._gap_().DirectProduct(other._gap_())
+        G = self._gap_().DirectProduct(other)
         D = PermutationGroup(gap_group=G)
         if not maps:
             return D
@@ -1448,7 +1607,7 @@
             pr2 = PermutationGroupMorphism_from_gap(D, other, G.Projection(2))
             return D, iota1, iota2, pr1, pr2
 
-    def subgroup(self, gens):
+    def subgroup(self, gens=None, gap_group=None, domain=None, category=None, canonicalize=True, check=True):
         """
         Wraps the ``PermutationGroup_subgroup`` constructor. The argument
         ``gens`` is a list of elements of ``self``.
@@ -1458,10 +1617,10 @@
             sage: G = PermutationGroup([(1,2,3),(3,4,5)])
             sage: g = G((1,2,3))
             sage: G.subgroup([g])
-            Subgroup of Permutation Group with generators [(3,4,5), (1,2,3)] generated by [(1,2,3)]
+            Subgroup of (Permutation Group with generators [(3,4,5), (1,2,3)]) generated by [(1,2,3)]
         """
-        return PermutationGroup_subgroup(self, gens)
-
+        return PermutationGroup_subgroup(self, gens=gens, gap_group=gap_group, domain=None,
+                                         category=category, canonicalize=canonicalize, check=check)
 
     def quotient(self, N):
         """
@@ -1484,7 +1643,7 @@
         # This is currently done using the right regular representation
         # FIXME: GAP certainly knows of a better way!
         phi = Q.RegularActionHomomorphism()
-        return PermutationGroup(gap_group = phi.Image())
+        return PermutationGroup(gap_group=phi.Image())
 
     def quotient_group(self, N):
         """
@@ -1921,7 +2080,13 @@
             sage: G = SymmetricGroup(5)
             sage: G.conjugacy_classes_representatives()
             [(), (1,2), (1,2)(3,4), (1,2,3), (1,2,3)(4,5), (1,2,3,4), (1,2,3,4,5)]
-        
+
+        ::
+
+            sage: S = SymmetricGroup(['a','b','c'])
+            sage: S.conjugacy_classes_representatives()
+            [(), ('a','b'), ('a','b','c')]
+
         AUTHORS:
 
         - David Joyner and William Stein (2006-01-04)
@@ -1940,30 +2105,20 @@
             sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])
             sage: cl = G.conjugacy_classes_subgroups()
             sage: cl
-            [Permutation Group with generators [()],
-             Permutation Group with generators [(1,2)(3,4)],
-             Permutation Group with generators [(1,3)(2,4)],
-             Permutation Group with generators [(2,4)],
-             Permutation Group with generators [(1,4)(2,3), (1,2)(3,4)],
-             Permutation Group with generators [(1,3)(2,4), (2,4)],
-             Permutation Group with generators [(1,3)(2,4), (1,2,3,4)],
-             Permutation Group with generators [(1,3)(2,4), (1,2)(3,4), (1,2,3,4)]]
+            [Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [()], Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(1,2)(3,4)], Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(1,3)(2,4)], Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(2,4)], Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(1,2)(3,4), (1,4)(2,3)], Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(2,4), (1,3)(2,4)], Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(1,2,3,4), (1,3)(2,4)], Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(1,2)(3,4), (1,2,3,4), (1,3)(2,4)]]
         
         ::
         
             sage: G = SymmetricGroup(3)
             sage: G.conjugacy_classes_subgroups()
-            [Permutation Group with generators [()],
-             Permutation Group with generators [(2,3)],
-             Permutation Group with generators [(1,2,3)],
-             Permutation Group with generators [(1,3,2), (1,2)]]
+            [Subgroup of (Symmetric group of order 3! as a permutation group) generated by [()], Subgroup of (Symmetric group of order 3! as a permutation group) generated by [(2,3)], Subgroup of (Symmetric group of order 3! as a permutation group) generated by [(1,2,3)], Subgroup of (Symmetric group of order 3! as a permutation group) generated by [(1,2), (1,3,2)]]
         
         AUTHORS:
 
         - David Joyner (2006-10)
         """
         cl = self._gap_().ConjugacyClassesSubgroups()
-        return [PermutationGroup(gap_group=sub.Representative()) for sub in cl]
+        return [self.subgroup(gap_group=sub.Representative()) for sub in cl]
         
     def subgroups(self):
         r"""
@@ -1990,7 +2145,9 @@
             `30030 = 2\cdot 3\cdot 5\cdot 7\cdot 11\cdot 13` takes
             about twice as long.
 
-            For faster results, which still exhibit the structure of the possible subgroups, use :meth:`conjugacy_classes_subgroups`.
+            For faster results, which still exhibit the structure of
+            the possible subgroups, use
+            :meth:`conjugacy_classes_subgroups`.
 
         EXAMPLES::
 
@@ -2001,7 +2158,7 @@
              Permutation Group with generators [(1,2)],
              Permutation Group with generators [(1,3)],
              Permutation Group with generators [(1,2,3)],
-             Permutation Group with generators [(1,3,2), (1,2)]]
+             Permutation Group with generators [(1,2), (1,3,2)]]
 
             sage: G = CyclicPermutationGroup(14)
             sage: G.subgroups()
@@ -2160,7 +2317,7 @@
             sage: A.cosets(S)
             Traceback (most recent call last):
             ...
-            ValueError: Subgroup of SymmetricGroup(3) generated by [(1,2)] is not a subgroup of AlternatingGroup(3)
+            ValueError: Subgroup of (Symmetric group of order 3! as a permutation group) generated by [(1,2)] is not a subgroup of Alternating group of order 3!/2 as a permutation group
 
         AUTHOR:
 
@@ -2201,16 +2358,15 @@
             sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])
             sage: g = G([(1,3)])
             sage: G.normalizer(g)
-            Permutation Group with generators [(2,4), (1,3)]
+            Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(2,4), (1,3)]
             sage: g = G([(1,2,3,4)])
             sage: G.normalizer(g)
-            Permutation Group with generators [(2,4), (1,2,3,4), (1,3)(2,4)]
+            Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(2,4), (1,2,3,4), (1,3)(2,4)]
             sage: H = G.subgroup([G([(1,2,3,4)])])
             sage: G.normalizer(H)
-            Permutation Group with generators [(2,4), (1,2,3,4), (1,3)(2,4)]
+            Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(2,4), (1,2,3,4), (1,3)(2,4)]
         """
-        N = self._gap_().Normalizer(g)
-        return PermutationGroup(N.GeneratorsOfGroup())
+        return self.subgroup(gap_group=self._gap_().Normalizer(g))
 
     def centralizer(self, g):
         """
@@ -2221,16 +2377,15 @@
             sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])
             sage: g = G([(1,3)])
             sage: G.centralizer(g)
-            Permutation Group with generators [(2,4), (1,3)]
+            Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(2,4), (1,3)]
             sage: g = G([(1,2,3,4)])
             sage: G.centralizer(g)
-            Permutation Group with generators [(1,2,3,4)]
+            Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(1,2,3,4)]
             sage: H = G.subgroup([G([(1,2,3,4)])])
             sage: G.centralizer(H)
-            Permutation Group with generators [(1,2,3,4)]
+            Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(1,2,3,4)]
         """
-        N = self._gap_().Centralizer(g)
-        return PermutationGroup(N.GeneratorsOfGroup())
+        return self.subgroup(gap_group=self._gap_().Centralizer(g))
 
     def isomorphism_type_info_simple_group(self):
         """
@@ -2444,7 +2599,7 @@
         """
         if not(self.is_subgroup(other)):
             raise TypeError("%s must be a subgroup of %s"%(self, other))
-        return other._gap_().IsNormal(self._gap_()).bool()
+        return other._gap_().IsNormal(self).bool()
     
     def is_perfect(self):
         """
@@ -2530,13 +2685,7 @@
             sage: G.is_subgroup(H)
             True
         """
-        G = other
-        gens = self.gens()
-        for i in range(len(gens)):
-            x = gens[i]
-            if not (x in G):
-                return False
-        return True
+        return all((x in other) for x in self.gens())
         
     def is_supersolvable(self):
         """
@@ -2551,11 +2700,54 @@
         """
         return self._gap_().IsSupersolvableGroup().bool()
 
-    def is_transitive(self):
+    def non_fixed_points(self):
+        r"""
+        Returns the list of points not fixed by ``self``, i.e., the subset
+        of ``self.domain()`` moved by some element of ``self``.
+
+        EXAMPLES::
+        
+            sage: G = PermutationGroup([[(3,4,5)],[(7,10)]])
+            sage: G.non_fixed_points()
+            [3, 4, 5, 7, 10]
+            sage: G = PermutationGroup([[(2,3,6)],[(9,)]]) # note: 9 is fixed
+            sage: G.non_fixed_points()
+            [2, 3, 6]
         """
-        Return ``True`` if ``self`` is a transitive group, i.e., if the action
-        of self on [1..n] is transitive.
+        pnts = set()
+        for gens in self.gens():
+            for cycles in gens.cycle_tuples():
+                for thispnt in cycles:
+                    if thispnt not in pnts:
+                        pnts.add(thispnt)
+        return sorted(pnts)
         
+    def fixed_points(self):
+        r"""
+        Returns the list of points fixed by ``self``, i.e., the subset
+        of ``.domain()`` not moved by any element of ``self``.
+        
+        EXAMPLES::
+        
+            sage: G=PermutationGroup([(1,2,3)])
+            sage: G.fixed_points()
+            []
+            sage: G=PermutationGroup([(1,2,3),(5,6)])
+            sage: G.fixed_points()
+            [4]
+            sage: G=PermutationGroup([[(1,4,7)],[(4,3),(6,7)]])
+            sage: G.fixed_points()
+            [2, 5]
+        """
+        non_fixed_points = self.non_fixed_points()
+        return [i for i in self.domain() if i not in non_fixed_points]
+
+    def is_transitive(self, domain=None):
+        """
+        Returns ``True`` if ``self`` acts transitively on ``domain``.
+        A group $G$ acts transitively on set $S$ if for all $x,y\in S$
+        there is some $g\in G$ such that $x^g=y$.       
+
         EXAMPLES::
         
             sage: G = SymmetricGroup(5)
@@ -2565,6 +2757,19 @@
             sage: G.is_transitive()
             False
 
+        ::
+        
+            sage: G = PermutationGroup([[(1,2,3,4,5)],[(1,2)]]) #S_5 on [1..5]
+            sage: G.is_transitive([1,4,5])
+            True
+            sage: G.is_transitive([2..6])
+            False
+            sage: G.is_transitive(G.non_fixed_points())
+            True
+            sage: H = PermutationGroup([[(1,2,3)],[(4,5,6)]])
+            sage: H.is_transitive(H.non_fixed_points())
+            False
+
         Note that this differs from the definition in GAP, where
         ``IsTransitive`` returns whether the group is transitive on the
         set of points moved by the group.
@@ -2577,8 +2782,126 @@
             sage: gap(G).IsTransitive()
             true
         """
-        return self._gap_().IsTransitive(self._set_gap()).bool()
-    
+        #If the domain is not a subset of self.domain(), then the
+        #action isn't transitive.
+        try:
+            domain = self._domain_gap(domain)
+        except ValueError:
+            return False
+
+        return self._gap_().IsTransitive(domain).bool()
+        
+
+    def is_primitive(self, domain=None):
+        r"""
+        Returns ``True`` if ``self`` acts primitively on ``domain``.
+        A group $G$ acts primitively on a set $S$ if
+        
+        1. $G$ acts transitively on $S$ and
+        
+        2. the action induces no non-trivial block system on $S$. 
+        
+        INPUT:
+
+        - ``domain`` (optional)
+        
+        EXAMPLES:
+            
+        By default, test for primitivity of ``self`` on its domain.
+        
+            sage: G = PermutationGroup([[(1,2,3,4)],[(1,2)]])
+            sage: G.is_primitive()
+            True
+            sage: G = PermutationGroup([[(1,2,3,4)],[(2,4)]])
+            sage: G.is_primitive()
+            False
+            
+        You can specify a domain on which to test primitivity::
+        
+            sage: G = PermutationGroup([[(1,2,3,4)],[(2,4)]])
+            sage: G.is_primitive([1..4])
+            False
+            sage: G.is_primitive([1,2,3])
+            True
+            sage: G = PermutationGroup([[(3,4,5,6)],[(3,4)]]) #S_4 on [3..6]
+            sage: G.is_primitive(G.non_fixed_points())
+            True
+        
+        """
+        #If the domain is not a subset of self.domain(), then the
+        #action isn't primitive.
+        try:
+            domain = self._domain_gap(domain)
+        except ValueError:
+            return False
+        
+        return self._gap_().IsPrimitive(domain).bool()
+
+    def is_semi_regular(self, domain=None):
+        r"""
+        Returns ``True`` if ``self`` acts semi-regularly on ``domain``.
+        A group $G$ acts semi-regularly on a set $S$ if the point
+        stabilizers of $S$ in $G$ are trivial.
+        
+        ``domain`` is optional and may take several forms. See examples.
+        
+        EXAMPLES::
+            
+            sage: G = PermutationGroup([[(1,2,3,4)]])
+            sage: G.is_semi_regular()
+            True
+            sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]])
+            sage: G.is_semi_regular()
+            False
+            
+        You can pass in a domain to test semi-regularity::
+        
+            sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]])
+            sage: G.is_semi_regular([1..4])
+            True
+            sage: G.is_semi_regular(G.non_fixed_points())
+            False
+            
+        """
+        try:
+            domain = self._domain_gap(domain)
+        except ValueError:
+            return False
+        return self._gap_().IsSemiRegular(domain).bool()
+
+    def is_regular(self, domain=None):
+        r"""
+        Returns ``True`` if ``self`` acts regularly on ``domain``.
+        A group $G$ acts regularly on a set $S$ if
+
+        1. $G$ acts transitively on $S$ and
+        2. $G$ acts semi-regularly on $S$.
+                
+        EXAMPLES::
+            
+            sage: G = PermutationGroup([[(1,2,3,4)]])
+            sage: G.is_regular()
+            True
+            sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]])
+            sage: G.is_regular()
+            False
+            
+        You can pass in a domain on which to test regularity::
+        
+            sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]])
+            sage: G.is_regular([1..4])
+            True
+            sage: G.is_regular(G.non_fixed_points())
+            False
+
+        """
+        try:
+            domain = self._domain_gap(domain)
+        except ValueError:
+            return False
+        return self._gap_().IsRegular(domain).bool()
+
+
     def normalizes(self, other):
         r"""
         Returns ``True`` if the group ``other`` is normalized by ``self``.
@@ -2604,7 +2927,7 @@
         In the last example, `G` and `H` are disjoint, so each normalizes the
         other.
         """
-        return self._gap_().IsNormal(other._gap_()).bool()
+        return self._gap_().IsNormal(other).bool()
 
     ############## Series ######################
     
@@ -2627,11 +2950,11 @@
             sage: G = PermutationGroup([[(1,2,3),(4,5)], [(1,2)]])
             sage: CS = G.composition_series()
             sage: CS[3]
-            Permutation Group with generators [()]
+            Subgroup of (Permutation Group with generators [(1,2), (1,2,3)(4,5)]) generated by [()]
         """
         current_randstate().set_seed_gap()
         CS = self._gap_().CompositionSeries()
-        return [PermutationGroup(gap_group=group) for group in CS]
+        return [self.subgroup(gap_group=group) for group in CS]
 
     def derived_series(self):
         """
@@ -2652,7 +2975,7 @@
         """
         current_randstate().set_seed_gap()
         DS = self._gap_().DerivedSeries()
-        return [PermutationGroup(gap_group=group) for group in DS]    
+        return [self.subgroup(gap_group=group) for group in DS]    
 
     def lower_central_series(self):
         """
@@ -2673,7 +2996,7 @@
         """
         current_randstate().set_seed_gap()
         LCS = self._gap_().LowerCentralSeriesOfGroup()
-        return [PermutationGroup(gap_group=group) for group in LCS]    
+        return [self.subgroup(gap_group=group) for group in LCS]    
 
     def molien_series(self):
         r"""
@@ -2736,7 +3059,7 @@
             True
         """
         NS = self._gap_().NormalSubgroups()
-        return [PermutationGroup(gap_group=group) for group in NS]
+        return [self.subgroup(gap_group=group) for group in NS]
 
     def poincare_series(self, p=2, n=10):
         """
@@ -2788,11 +3111,11 @@
         
             sage: G = PermutationGroup(['(1,2,3)', '(2,3)'])
             sage: G.sylow_subgroup(2)
-            Permutation Group with generators [(2,3)]
+            Subgroup of (Permutation Group with generators [(2,3), (1,2,3)]) generated by [(2,3)]
             sage: G.sylow_subgroup(5)
-            Permutation Group with generators [()]
+            Subgroup of (Permutation Group with generators [(2,3), (1,2,3)]) generated by [()]
         """
-        return PermutationGroup(gap_group=self._gap_().SylowSubgroup(p))
+        return self.subgroup(gap_group=self._gap_().SylowSubgroup(p))
         
     def upper_central_series(self):
         """
@@ -2806,11 +3129,11 @@
 
             sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])
             sage: G.upper_central_series()
-            [Permutation Group with generators [()]]
+            [Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]]
         """
         current_randstate().set_seed_gap()
         UCS = self._gap_().UpperCentralSeriesOfGroup()
-        return [PermutationGroup(gap_group=group) for group in UCS]
+        return [self.subgroup(gap_group=group) for group in UCS]
 
 class PermutationGroup_subgroup(PermutationGroup_generic):
     """
@@ -2822,9 +3145,9 @@
         sage: G = CyclicPermutationGroup(4)
         sage: gens = G.gens()
         sage: H = DihedralGroup(4)
-        sage: PermutationGroup_subgroup(H,list(gens))
-        Subgroup of Dihedral group of order 8 as a permutation group generated by [(1,2,3,4)]
-        sage: K=PermutationGroup_subgroup(H,list(gens))
+        sage: H.subgroup(gens)
+        Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]
+        sage: K = H.subgroup(gens)
         sage: K.list()
         [(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)]
         sage: K.ambient_group()
@@ -2832,7 +3155,8 @@
         sage: K.gens()
         [(1,2,3,4)]
     """
-    def __init__(self, ambient, gens, from_group = False, check=True, canonicalize=True):
+    def __init__(self, ambient, gens=None, gap_group=None, domain=None,
+                 category=None, canonicalize=True, check=True):
         r"""
         Initialization method for the
         ``PermutationGroup_subgroup`` class.
@@ -2862,9 +3186,9 @@
             sage: H = CyclicPermutationGroup(4)
             sage: gens = H.gens(); gens
             [(1,2,3,4)]
-            sage: S = PermutationGroup_subgroup(G,gens)
+            sage: S = G.subgroup(gens)
             sage: S
-            Subgroup of Dihedral group of order 8 as a permutation group generated by [(1,2,3,4)]
+            Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]
             sage: S.list()
             [(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)]
             sage: S.ambient_group()
@@ -2883,31 +3207,28 @@
         """
         if not isinstance(ambient, PermutationGroup_generic):
             raise TypeError, "ambient (=%s) must be perm group."%ambient
-        if not isinstance(gens, list):
-            raise TypeError, "gens (=%s) must be a list"%gens
-            
-        self.__ambient_group = ambient
-        self._gens = gens
-        cmd = 'Group(%s)'%gens
-        cmd = cmd.replace("'","")  # get rid of quotes
-        self._gap_string = cmd
-   
-        G = ambient
+        if domain is None:
+            domain = ambient.domain()
+        if category is None:
+            category = ambient.category()
+        PermutationGroup_generic.__init__(self, gens=gens, gap_group=gap_group, domain=domain,
+                                          category=category, canonicalize=canonicalize)
+
+        self._ambient_group = ambient
         if check:
-            for g in gens:
-                if g not in G:
+            for g in self.gens():
+                if g not in ambient:
                     raise TypeError, "each generator must be in the ambient group"
-        self.__ambient_group = G
-        
-        PermutationGroup_generic.__init__(self, gens, canonicalize=canonicalize)
 
     def __cmp__(self, other):
         r"""
         Compare ``self`` and ``other``.
 
-        First, ``self`` and ``other`` are compared as permutation groups, see :method:`sage.groups.perm_gps.permgroup.PermutationGroup_generic.__cmp__`.
-        Second, if both are equal, the ambient groups are compared, where (if necessary)
-        ``other`` is considered a subgroup of itself.
+        First, ``self`` and ``other`` are compared as permutation
+        groups, see :method:`PermutationGroup_generic.__cmp__`.
+        Second, if both are equal, the ambient groups are compared,
+        where (if necessary) ``other`` is considered a subgroup of
+        itself.
         
         EXAMPLES::
         
@@ -2941,7 +3262,7 @@
             sage: G
             Symmetric group of order 6! as a permutation group
             sage: G3
-            Subgroup of SymmetricGroup(6) generated by [(1,2), (1,2,3,4,5,6)]
+            Subgroup of (Symmetric group of order 6! as a permutation group) generated by [(1,2), (1,2,3,4,5,6)]
             sage: G is G3
             False
             sage: G == G3 # as permutation groups
@@ -2986,11 +3307,11 @@
             sage: gens = H.gens()
             sage: S = PermutationGroup_subgroup(G, list(gens))
             sage: S
-            Subgroup of Dihedral group of order 8 as a permutation group generated by [(1,2,3,4)]
+            Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]
             sage: S._repr_()
-            'Subgroup of Dihedral group of order 8 as a permutation group generated by [(1,2,3,4)]'
+            'Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]'
         """
-        s = "Subgroup of %s generated by %s"%(self.ambient_group(), self.gens())
+        s = "Subgroup of (%s) generated by %s"%(self.ambient_group(), self.gens())
         return s
 
     def _latex_(self):
@@ -3007,9 +3328,9 @@
             sage: gens = H.gens()
             sage: S = PermutationGroup_subgroup(G, list(gens))
             sage: latex(S)
-            Subgroup of Dihedral group of order 8 as a permutation group generated by [(1,2,3,4)]
+            Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]
             sage: S._latex_()
-            'Subgroup of Dihedral group of order 8 as a permutation group generated by [(1,2,3,4)]'
+            'Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]'
         """
         return self._repr_()
 
@@ -3032,25 +3353,25 @@
             sage: S.ambient_group() == G
             True
         """
-        return self.__ambient_group
-
-    def gens(self):
+        return self._ambient_group
+
+
+    def is_normal(self, other=None):
         """
-        Return the generators for this subgroup.
+        Return ``True`` if this group is a normal subgroup of
+        ``other``.  If ``other`` is not specified, then it is assumed
+        to be the ambient group.
         
-        EXAMPLES:
-
-        An example involving the dihedral group on four elements,
-        `D_8`::
+        EXAMPLES::
         
-            sage: G = DihedralGroup(4)
-            sage: H = CyclicPermutationGroup(4)
-            sage: gens = H.gens()
-            sage: S = PermutationGroup_subgroup(G, list(gens))
-            sage: S.gens()
-            [(1,2,3,4)]
-            sage: S.gens() == list(H.gens())
-            True
+           sage: S = SymmetricGroup(['a','b','c'])
+           sage: H = S.subgroup([('a', 'b', 'c')]); H
+           Subgroup of (Symmetric group of order 3! as a permutation group) generated by [('a','b','c')]
+           sage: H.is_normal()
+           True
+
         """
-        return self._gens
-    
+        if other is None:
+            other = self.ambient_group()
+        return PermutationGroup_generic.is_normal(self, other)
+
diff --git a/sage/groups/perm_gps/permgroup_element.pxd b/sage/groups/perm_gps/permgroup_element.pxd
--- a/sage/groups/perm_gps/permgroup_element.pxd
+++ b/sage/groups/perm_gps/permgroup_element.pxd
@@ -9,5 +9,6 @@
     cdef Element _gap_element
     cdef __tuple
     cdef PermutationGroupElement _new_c(self)
+    cpdef _gap_list(self)
     cpdef list(self)
     cdef public __custom_name
diff --git a/sage/groups/perm_gps/permgroup_element.pyx b/sage/groups/perm_gps/permgroup_element.pyx
--- a/sage/groups/perm_gps/permgroup_element.pyx
+++ b/sage/groups/perm_gps/permgroup_element.pyx
@@ -65,13 +65,11 @@
 from sage.rings.all      import ZZ, Integer, is_MPolynomial, is_Polynomial
 from sage.matrix.all     import MatrixSpace
 from sage.interfaces.all import gap, is_GapElement, is_ExpectElement
-
+from sage.sets.all import FiniteEnumeratedSet
 import sage.structure.coerce as coerce
 
 import operator
 
-from sage.rings.integer import Integer
-
 from sage.rings.fast_arith cimport arith_llong
 cdef arith_llong arith = arith_llong()
 cdef extern from *:
@@ -80,22 +78,66 @@
 #import permgroup_named
 
 def make_permgroup_element(G, x):
-    G._deg = len(x)
+    """
+    Returns a PermutationGroupElement given the permutation group
+    ``G`` and the permutation ``x`` in list notation.
+
+    This is function is used when unpickling old (pre-domain) versions
+    of permutation groups and their elements.  This now does a bit of
+    processing and calls :func:`make_permgroup_element_v2` which is
+    used in unpickling the current PermutationGroupElements.
+
+    EXAMPLES::
+
+        sage: from sage.groups.perm_gps.permgroup_element import make_permgroup_element
+        sage: S = SymmetricGroup(3)
+        sage: make_permgroup_element(S, [1,3,2])
+        (2,3)
+    """
+    domain = FiniteEnumeratedSet(range(1, len(x)+1))
+    return make_permgroup_element_v2(G, x, domain)
+
+def make_permgroup_element_v2(G, x, domain):
+    """
+    Returns a PermutationGroupElement given the permutation group
+    ``G``, the permutation ``x`` in list notation, and the domain
+    ``domain`` of the permutation group.
+
+    This is function is used when unpickling permutation groups and
+    their elements.  
+    
+    EXAMPLES::
+
+        sage: from sage.groups.perm_gps.permgroup_element import make_permgroup_element_v2
+        sage: S = SymmetricGroup(3)
+        sage: make_permgroup_element_v2(S, [1,3,2], S.domain())
+        (2,3)
+    """
+    # Note that it has to be in-sync with the __init__ method of
+    # PermutationGroup_generic since the elements have to be created
+    # before the PermutationGroup_generic is initialized.  The
+    # constructor for PermutationGroupElement requires that
+    # G._domain_to_gap be set.
+    G._domain = domain
+    G._deg = len(domain)
+    G._domain_to_gap = dict([(key, i+1) for i, key in enumerate(domain)])
+    G._domain_from_gap = dict([(i+1, key) for i, key in enumerate(domain)])
     return G(x, check=False)
 
+
 def is_PermutationGroupElement(x):
+    """
+    Returns True if ``x`` is a PermutationGroupElement.
+
+    EXAMPLES::
+
+        sage: p = PermutationGroupElement([(1,2),(3,4,5)])
+        sage: from sage.groups.perm_gps.permgroup_element import is_PermutationGroupElement
+        sage: is_PermutationGroupElement(p)
+        True    
+    """
     return isinstance(x, PermutationGroupElement)
 
-
-def gap_format(x):
-    """
-    Put a permutation in Gap format, as a string.
-    """
-    if isinstance(x, list) and not isinstance(x[0], tuple):
-        return gap.eval('PermList(%s)' % x)
-    x = str(x).replace(' ','').replace('\n','')
-    return x.replace('),(',')(').replace('[','').replace(']','').replace(',)',')') 
-
 def string_to_tuples(g):
     """
     EXAMPLES::
@@ -120,6 +162,93 @@
     g = '[' + g + ']'
     return sage_eval(g, preparse=False)
 
+def standardize_generator(g, convert_dict=None):
+    """
+    Standardizes the input for permutation group elements to a list of
+    tuples.  This was factored out of the
+    PermutationGroupElement.__init__ since
+    PermutationGroup_generic.__init__ needs to do the same computation
+    in order to compute the domain of a group when it's not explicitly
+    specified.
+
+    INPUT:
+
+    - ``g`` - a list, tuple, string, GapElement,
+      PermuationGroupElement
+
+    - ``convert_dict`` - (optional) a dictionary used to convert the
+      points to a number compatible with GAP.
+
+    OUTPUT:
+
+    The permutation in as a list of cycles.
+
+    EXAMPLES::
+
+        sage: from sage.groups.perm_gps.permgroup_element import standardize_generator
+        sage: standardize_generator('(1,2)')
+        [(1, 2)]
+
+        sage: p = PermutationGroupElement([(1,2)])
+        sage: standardize_generator(p)
+        [(1, 2)]
+        sage: standardize_generator(p._gap_())
+        [(1, 2)]
+        sage: standardize_generator((1,2))
+        [(1, 2)]
+        sage: standardize_generator([(1,2)])
+        [(1, 2)]
+
+    ::
+
+        sage: d = {'a': 1, 'b': 2}
+        sage: p = SymmetricGroup(['a', 'b']).gen(0); p
+        ('a','b')
+        sage: standardize_generator(p, convert_dict=d)
+        [(1, 2)]
+        sage: standardize_generator(p._gap_(), convert_dict=d)
+        [(1, 2)]
+        sage: standardize_generator(('a','b'), convert_dict=d)
+        [(1, 2)]
+        sage: standardize_generator([('a','b')], convert_dict=d)
+        [(1, 2)]
+    """
+    from sage.interfaces.gap import GapElement
+    from sage.combinat.permutation import Permutation
+    from sage.libs.pari.gen import gen
+
+    if isinstance(g, gen):
+        g = list(g)
+        
+    needs_conversion = True
+    if isinstance(g, GapElement):
+        g = str(g)
+        needs_conversion = False
+    if isinstance(g, PermutationGroupElement):
+        g = g.cycle_tuples()
+    if isinstance(g, str):
+        g = string_to_tuples(g)
+    if isinstance(g, tuple) and (len(g) == 0 or not isinstance(g[0], tuple)):
+        g = [g]
+
+    #Get the permutation in list notation
+    if PyList_CheckExact(g) and (len(g) == 0 or not PY_TYPE_CHECK(g[0], tuple)):
+        if convert_dict is not None and needs_conversion:
+            g = [convert_dict[x] for x in g]
+
+
+        #FIXME: Currently, we need to verify that g defines an actual
+        #permutation since the constructor Permutation does not
+        #perform this check.  When it does, we should remove this code.
+        #See #8392
+        if set(g) != set(range(1, len(g)+1)):
+            raise ValueError, "Invalid permutation vector: %s"%g
+        return Permutation(g).cycle_tuples()
+    else:
+        if convert_dict is not None and needs_conversion:
+            g = [tuple([convert_dict[x] for x in cycle])for cycle in g]
+
+    return g
 
 cdef class PermutationGroupElement(MultiplicativeGroupElement):
     """
@@ -292,42 +421,32 @@
             sage: PermutationGroupElement([()])
             ()
         """
-        from sage.interfaces.gap import GapElement
         from sage.groups.perm_gps.permgroup_named import SymmetricGroup
         from sage.groups.perm_gps.permgroup import PermutationGroup_generic
+        from sage.combinat.permutation import from_cycles
 
-        #Convert GAP elements to strings
-        if isinstance(g, GapElement):
-            g = str(g)
-        elif isinstance(g, PermutationGroupElement):
-            g = g.list()
-            
-        #Convert all the string to tuples
-        if isinstance(g, str):
-            g = string_to_tuples(g)
+        convert_dict = parent._domain_to_gap if parent is not None else None
+        try:
+            v = standardize_generator(g, convert_dict)
+        except KeyError:
+            raise ValueError, "Invalid permutation vector: %s" % g
 
-        if isinstance(g, tuple) and (len(g) == 0 or not isinstance(g[0], tuple)):
-            g = [g]
-
-        #Get the permutation in list notation
-        if PyList_CheckExact(g) and (len(g) == 0 or not PY_TYPE_CHECK(g[0], tuple)):
-            v = g if len(g) != 0 else [1]
-            self.__gap = 'PermList(%s)'%v
-        else:
-            from sage.combinat.permutation import Permutation
-            v = Permutation(g)._list
-            self.__gap = str(g)[1:-1].replace('), (',')(').replace(',)',')').strip(',')
+        
+        degree = max([1] + [max(cycle+(1,)) for cycle in v])
+        v = from_cycles(degree, v)
+        
+        self.__gap = 'PermList(%s)'%v
 
         if parent is None:
-            parent = SymmetricGroup(max(len(v),1))
-    
+            parent = SymmetricGroup(len(v))
+
         if check and parent.__class__ != SymmetricGroup:
             if not (parent is None or isinstance(parent, PermutationGroup_generic)):
                 raise TypeError, 'parent must be a permutation group'
             if parent is not None:
                 P = parent._gap_()
                 if not P.parent()(self.__gap) in P:
-                    raise TypeError, 'permutation %s not in %s'%(self.__gap, parent)
+                    raise TypeError, 'permutation %s not in %s'%(g, parent)
 
         Element.__init__(self, parent)
 
@@ -361,7 +480,19 @@
             sage_free(self.perm)
         
     def __reduce__(self):
-        return make_permgroup_element, (self._parent, self.list())
+        """
+        Returns a function and its arguments needed to create this
+        permutation group element.  This is used in pickling.
+        
+        EXAMPLES::
+
+           sage: g = PermutationGroupElement([(1,2,3),(4,5)]); g
+           (1,2,3)(4,5)
+           sage: func, args = g.__reduce__()
+           sage: func(*args)
+           (1,2,3)(4,5)
+        """
+        return make_permgroup_element_v2, (self._parent, self.list(), self._parent.domain())
         
     cdef PermutationGroupElement _new_c(self):
         cdef PermutationGroupElement other = PY_NEW_SAME_TYPE(self)
@@ -375,24 +506,56 @@
             other.perm = <int *>sage_malloc(sizeof(int) * other.n)
         return other
 
-    def _gap_(self, G=None):
-        if self._gap_element is None or \
-            (G is not None and self._gap_element._parent is not G):
-            if G is None:
-                import sage.interfaces.gap
-                G = sage.interfaces.gap.gap
-            self._gap_element = G("PermList(%s)" % self.list())
+    def _gap_(self, gap=None):
+        """
+        Returns 
+
+        EXAMPLES::
+
+            sage: g = PermutationGroupElement([(1,2,3),(4,5)]); g
+            (1,2,3)(4,5)
+            sage: a = g._gap_(); a
+            (1,2,3)(4,5)
+            sage: g._gap_() is g._gap_()
+            True
+            
+        Note that only one GapElement is cached:
+
+            sage: gap2 = Gap()
+            sage: b = g._gap_(gap2)
+            sage: c = g._gap_()
+            sage: a is c
+            False
+        """
+        if (self._gap_element is None or 
+            (gap is not None and self._gap_element._parent is not gap)):
+            if gap is None:
+                from sage.interfaces.gap import gap 
+            self._gap_element = gap(self._gap_init_())
         return self._gap_element
 
+    def _gap_init_(self):
+        """
+        Returns a GAP string representation for this
+        PermutationGroupElement.
+
+        EXAMPLES::
+
+            sage: g = PermutationGroupElement([(1,2,3),(4,5)])
+            sage: g._gap_init_()
+            'PermList([2, 3, 1, 5, 4])'
+        """
+        return 'PermList(%s)'%self._gap_list()
+
     def _repr_(self):
         """
         Return string representation of this permutation.
         
-        EXAMPLES: We create the permutation `(1,2,3)(4,5)` and
-        print it.
-        
-        ::
-        
+        EXAMPLES:
+
+        We create the permutation `(1,2,3)(4,5)` and
+        print it. ::
+
             sage: g = PermutationGroupElement([(1,2,3),(4,5)])
             sage: g._repr_()
             '(1,2,3)(4,5)'
@@ -407,13 +570,24 @@
             sage: g
             (1,2,3)(4,5)
         """
-        cycles = self.cycle_tuples()
-        if len(cycles) == 0:
-            return '()'
-        return ''.join([str(c) for c in cycles]).replace(', ',',')
+        return self.cycle_string()
 
     def _latex_(self):
-        return str(self)
+        """
+        Returns a latex representation of this permutation.
+
+        EXAMPLES::
+
+            sage: g = PermutationGroupElement([(1,2,3),(4,5)])
+            sage: latex(g)
+            (1,2,3)(4,5)
+            
+            sage: S = SymmetricGroup(['a', 'b'])
+            sage: latex(S.gens())
+            \left[(\texttt{a},\texttt{b})\right]
+        """
+        from sage.misc.latex import latex
+        return "".join(["(" + ",".join([latex(x) for x in cycle])+")" for cycle in self.cycle_tuples()])
 
     def __getitem__(self, i):
         """
@@ -519,14 +693,30 @@
             sage: g(x)
             Traceback (most recent call last):
             ...
-            ValueError: Must be an integer, list, tuple or string.
+            ValueError: Must be in the domain or a list, tuple or string.
             sage: g(3/2)
             Traceback (most recent call last):
             ...
-            ValueError: Must be an integer, list, tuple or string.
+            ValueError: Must be in the domain or a list, tuple or string.
         """
+        to_gap = self._parent._domain_to_gap
+        from_gap = self._parent._domain_from_gap
         cdef int j
-        if isinstance(i,(list,tuple,str)):
+
+        try:
+            i = to_gap[i]
+        except (KeyError, TypeError):
+            # We currently have to include this to maintain the
+            # current behavior where if you pass in an integer which
+            # is not in the domain of the permutation group, then that
+            # integer itself will be returned.          
+            if isinstance(i, (long, int, Integer)):
+                return i
+
+            
+            if not isinstance(i,(list,tuple,str)):
+                raise ValueError, "Must be in the domain or a list, tuple or string."
+            
             permuted = [i[self.perm[j]] for j from 0 <= j < self.n]
             if PY_TYPE_CHECK(i, tuple):
                 permuted = tuple(permuted)
@@ -535,13 +725,11 @@
             permuted += i[self.n:]
             return permuted
         else:
-            if not isinstance(i, (int, Integer)):
-                raise ValueError("Must be an integer, list, tuple or string.")
             j = i
             if 1 <= j <= self.n:
-                return self.perm[j-1]+1
+                return from_gap[self.perm[j-1]+1]
             else:
-                return i
+                return from_gap[i]
 
     cpdef _act_on_(self, x, bint self_on_left):
         """
@@ -590,6 +778,15 @@
                 return left(tuple(sigma_x))
 
     cpdef MonoidElement _mul_(left, MonoidElement _right):
+        """
+        EXAMPLES::
+
+            sage: S = SymmetricGroup(['a', 'b'])
+            sage: s = S([('a', 'b')]); s
+            ('a','b')
+            sage: s*s
+            ()
+        """
         cdef PermutationGroupElement prod = left._new_c()
         cdef PermutationGroupElement right = <PermutationGroupElement>_right
         cdef int i
@@ -614,7 +811,55 @@
         for i from 0 <= i < self.n:
             inv.perm[self.perm[i]] = i
         return inv
+
+    cpdef _gap_list(self):
+        """
+        Returns this permutation in list notation compatible with the
+        GAP numbering.
+
+        EXAMPLES::
+
+            sage: S = SymmetricGroup(3)
+            sage: s = S.gen(0); s
+            (1,2,3)
+            sage: s._gap_list()
+            [2, 3, 1]
+
+        ::
         
+            sage: S = SymmetricGroup(['a', 'b', 'c'])
+            sage: s = S.gen(0); s
+            ('a','b','c')
+            sage: s._gap_list()
+            [2, 3, 1]
+        """
+        cdef int i
+        return [self.perm[i]+1 for i from 0 <= i < self.n]
+
+    def _gap_cycle_string(self):
+        """
+        Returns a cycle string for this permutation compatible with
+        the GAP numbering.
+
+        EXAMPLES::
+
+            sage: S = SymmetricGroup(3)
+            sage: s = S.gen(0); s
+            (1,2,3)
+            sage: s._gap_cycle_string()
+            '(1,2,3)'
+
+        ::
+
+            sage: S = SymmetricGroup(['a', 'b', 'c'])
+            sage: s = S.gen(0); s
+            ('a','b','c')
+            sage: s._gap_cycle_string()
+            '(1,2,3)'
+        """
+        from sage.combinat.permutation import Permutation
+        return Permutation(self._gap_list()).cycle_string()
+
     cpdef list(self):
         """
         Returns list of the images of the integers from 1 to n under this
@@ -633,9 +878,26 @@
             (1,2)
             sage: x.list()
             [2, 1, 3, 4]
+
+        TESTS::
+
+            sage: S = SymmetricGroup(0)
+            sage: x = S.one(); x
+            ()
+            sage: x.list()
+            []
         """
         cdef int i
-        return [self.perm[i]+1 for i from 0 <= i < self.n]
+
+        #We need to do this to handle the case of SymmetricGroup(0)
+        #where the domain is (), but the permutation group element has
+        #an underlying representation of [1].  The 1 doesn't
+        #correspond to anything in the domain
+        if len(self._parent._domain) == 0:
+            return []
+        else:
+            from_gap = self._parent._domain_from_gap
+            return [from_gap[self.perm[i]+1] for i from 0 <= i < self.n]
 
     def __hash__(self):
         """
@@ -654,11 +916,11 @@
             1592966088          # 32-bit
             2865702456085625800 # 64-bit
         """
-        return hash(self.tuple())
-
+        return hash(tuple(self._gap_list()))
+    
     def tuple(self):
         """
-        Return tuple of images of integers under self.
+        Return tuple of images of the domain under self.
         
         EXAMPLES::
         
@@ -666,6 +928,10 @@
             sage: s = G([2,1,5,3,4])
             sage: s.tuple()
             (2, 1, 5, 3, 4)
+
+            sage: S = SymmetricGroup(['a', 'b'])
+            sage: S.gen().tuple()
+            ('b', 'a')
         """
         if self.__tuple is None:
             self.__tuple = tuple(self.list())
@@ -696,10 +962,11 @@
             sage: x.dict()
             {1: 2, 2: 1, 3: 3, 4: 4}
         """
+        from_gap = self._parent._domain_from_gap
         cdef int i
         u = {}
         for i from 0 <= i < self.n:
-            u[i+1] = self.perm[i]+1
+            u[i+1] = from_gap[self.perm[i]+1]
         return u
             
     def order(self):
@@ -816,7 +1083,7 @@
     def orbit(self, n, bint sorted=True):
         """
         Returns the orbit of the integer `n` under this group
-        element, as a sorted list of integers.
+        element, as a sorted list.
         
         EXAMPLES::
         
@@ -828,20 +1095,34 @@
             [1, 2, 3]
             sage: g.orbit(10)
             [10]
+
+        ::
+        
+            sage: s = SymmetricGroup(['a', 'b']).gen(0); s
+            ('a','b')
+            sage: s.orbit('a')
+            ['a', 'b']
         """
+        to_gap = self._parent._domain_to_gap
+        from_gap = self._parent._domain_from_gap
+        try:
+            n = to_gap[n]
+        except KeyError:
+            return [n]
+        
         cdef int i = n
         cdef int start = i
         if 1 <= i <= self.n:
-            L = [i]
+            L = [from_gap[i]]
             i = self.perm[i-1]+1
             while i != start:
-                PyList_Append(L,i)
+                PyList_Append(L,from_gap[i])
                 i = self.perm[i-1]+1
             if sorted:
                 L.sort()
             return L
         else:
-            return [n]
+            return from_gap[n]
                 
     def cycles(self):
         """
@@ -876,28 +1157,83 @@
         sage_free(seen)
         return L
         
-    def cycle_tuples(self):
+    def cycle_tuples(self, singletons=False):
         """
         Return self as a list of disjoint cycles, represented as tuples
         rather than permutation group elements.
+
+        INPUT:
+
+        - ``singletons`` - boolean (default: False) whether or not consider the
+          cycle that correspond to fixed point
+
+        EXAMPLES::
+
+            sage: p = PermutationGroupElement('(2,6)(4,5,1)')
+            sage: p.cycle_tuples()
+            [(1, 4, 5), (2, 6)]
+            sage: p.cycle_tuples(singletons=True)
+            [(1, 4, 5), (2, 6), (3,)]
+
+        EXAMPLES::
+
+            sage: S = SymmetricGroup(4)
+            sage: S.gen(0).cycle_tuples()
+            [(1, 2, 3, 4)]
+
+        ::
+        
+            sage: S = SymmetricGroup(['a','b','c','d'])
+            sage: S.gen(0).cycle_tuples()
+            [('a', 'b', 'c', 'd')]
+            sage: S([('a', 'b'), ('c', 'd')]).cycle_tuples()
+            [('a', 'b'), ('c', 'd')]
         """
+        from_gap = self._parent._domain_from_gap
         L = []
         cdef int i, k
         cdef bint* seen = <bint *>sage_malloc(sizeof(bint) * self.n)
         for i from 0 <= i < self.n: seen[i] = 0
         for i from 0 <= i < self.n:
-            if seen[i] or self.perm[i] == i:
+            if seen[i]:
                 continue
-            cycle = [i+1]
-            k = self.perm[i]
-            while k != i:
-                PyList_Append(cycle, k+1)
-                seen[k] = 1
-                k = self.perm[k]
-            PyList_Append(L, tuple(cycle))
+            if self.perm[i] == i:
+                if singletons:
+                    PyList_Append(L, (from_gap[i+1],))
+                    # it is not necessary to put seen[i] to 1 as we will never
+                    # see i again
+                else:
+                    continue
+            else:
+                cycle = [from_gap[i+1]]
+                k = self.perm[i]
+                while k != i:
+                    PyList_Append(cycle, from_gap[k+1])
+                    seen[k] = 1
+                    k = self.perm[k]
+                PyList_Append(L, tuple(cycle))
         sage_free(seen)
         return L
 
+    def cycle_string(self, singletons=False):
+        """
+        Return string representation of this permutation.
+        
+       EXAMPLES::
+
+            sage: g = PermutationGroupElement([(1,2,3),(4,5)])
+            sage: g.cycle_string()
+            '(1,2,3)(4,5)'
+
+            sage: g = PermutationGroupElement([3,2,1])
+            sage: g.cycle_string(singletons=True)
+            '(1,3)(2)'
+        """
+        cycles = self.cycle_tuples(singletons)
+        if len(cycles) == 0:
+            return '()'
+        return ''.join([repr(c) for c in cycles]).replace(', ',',').replace(',)',')')
+
     def has_descent(self, i, side = "right", positive = False):
         """
         INPUT:
@@ -944,18 +1280,17 @@
             True
             sage: S._test_has_descent()
         """
+        to_gap = self._parent._domain_to_gap
+        from_gap = self._parent._domain_from_gap
         if side == "right":
             self = ~self
+            
         try:
-            if not self.parent()._has_natural_set():
-                set = self.parent()._set
-                pos = set.index(i)
-                i1  = set[pos+1]
-                res = set.index(self(i)) > set.index(self(i1))
-                return res is not positive
-        except AttributeError:
-            pass
-        return (self(i) > self(i+1)) is not positive
+            i1 = from_gap[to_gap[i]+1]
+        except KeyError:
+            return False
+        
+        return (to_gap[self(i)] > to_gap[self(i1)]) is not positive
 
     def matrix(self):
         """
@@ -980,7 +1315,7 @@
             entries[i, self.perm[i]] = 1
         return M(entries)
 
-    def word_problem(g, words, display=True):
+    def word_problem(self, words, display=True):
         """
         G and H are permutation groups, g in G, H is a subgroup of G
         generated by a list (words) of elements of G. If g is in H, return
@@ -995,8 +1330,7 @@
         EXAMPLE::
         
             sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]], canonicalize=False)
-            sage: g1 = G.gens()[0]
-            sage: g2 = G.gens()[1]
+            sage: g1, g2 = G.gens()
             sage: h = g1^2*g2*g1
             sage: h.word_problem([g1,g2], False)
             ('x1^2*x2^-1*x1', '(1,2,3)(4,5)^2*(3,4)^-1*(1,2,3)(4,5)')
@@ -1005,16 +1339,17 @@
                [['(1,2,3)(4,5)', 2], ['(3,4)', -1], ['(1,2,3)(4,5)', 1]]
             ('x1^2*x2^-1*x1', '(1,2,3)(4,5)^2*(3,4)^-1*(1,2,3)(4,5)')
         """
+        if not self._parent._has_natural_domain():
+            raise NotImplementedError
+        
         import copy
         from sage.groups.perm_gps.permgroup import PermutationGroup
         from sage.interfaces.all import gap
-        
+
         G = gap(words[0].parent())
-        g = words[0].parent()(g)
-        gensH = gap(words)
-        H = gensH.Group()
-        hom = G.EpimorphismFromFreeGroup()
-        ans = hom.PreImagesRepresentative(gap(g))
+        g = words[0].parent()(self)
+        H = gap.Group(words)
+        ans = G.EpimorphismFromFreeGroup().PreImagesRepresentative(g)
         
         l1 = str(ans)
         l2 = copy.copy(l1)
diff --git a/sage/groups/perm_gps/permgroup_morphism.py b/sage/groups/perm_gps/permgroup_morphism.py
--- a/sage/groups/perm_gps/permgroup_morphism.py
+++ b/sage/groups/perm_gps/permgroup_morphism.py
@@ -15,9 +15,9 @@
     sage: g = G([(1,2,3,4)])
     sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))
     sage: phi.image(G)
-    Permutation Group with generators [(1,2,3,4)]
+    Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]
     sage: phi.kernel()
-    Permutation Group with generators [()]
+    Subgroup of (Cyclic group of order 4 as a permutation group) generated by [()]
     sage: phi.image(g)                  
     (1,2,3,4)
     sage: phi(g)                        
@@ -87,7 +87,7 @@
             sage: g = G([(1,2,3,4)])
             sage: phi = PermutationGroupMorphism_im_gens(G, H, [1])
             sage: phi.kernel()
-            Permutation Group with generators [(1,2,3,4)]
+            Subgroup of (Cyclic group of order 4 as a permutation group) generated by [(1,2,3,4)]
             
         ::
         
@@ -98,7 +98,7 @@
             sage: G.is_isomorphic(pr1.kernel())
             True
         """
-        return PermutationGroup(gap_group=self._gap_().Kernel())
+        return self.domain().subgroup(gap_group=self._gap_().Kernel())
 
     def image(self, J):
         """
@@ -112,7 +112,7 @@
             sage: g = G([(1,2,3,4)])
             sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))
             sage: phi.image(G)
-            Permutation Group with generators [(1,2,3,4)]
+            Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]
             sage: phi.image(g)                  
             (1,2,3,4)
 
@@ -123,17 +123,18 @@
             sage: H = D[0]
             sage: pr1 = D[3]
             sage: pr1.image(G)
-            Permutation Group with generators [(3,7,5)(4,8,6), (1,2,6)(3,4,8)]
+            Subgroup of (The projective special linear group of degree 2 over Finite Field of size 7) generated by [(3,7,5)(4,8,6), (1,2,6)(3,4,8)]
             sage: G.is_isomorphic(pr1.image(G))
             True
         """
+        H = self.codomain()
         if J in self.domain():
             J = PermutationGroup([J])
             G = self._gap_().Image(J)
-            return PermutationGroup(gap_group=G).gens()[0]
+            return H.subgroup(gap_group=G).gens()[0]
         else:
             G = self._gap_().Image(J)
-            return PermutationGroup(gap_group=G)
+            return H.subgroup(gap_group=G)
 
     def __call__(self, g):
         """
@@ -177,7 +178,7 @@
             sage: H = G.subgroup([G([(1,2,3,4)])])
             sage: PermutationGroupMorphism_from_gap(H, G, gap.Identity)
             Permutation group morphism:
-              From: Subgroup of Permutation Group with generators [(1,2)(3,4), (1,2,3,4)] generated by [(1,2,3,4)]
+              From: Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(1,2,3,4)]
               To:   Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]
               Defn: Identity
         """
diff --git a/sage/groups/perm_gps/permgroup_named.py b/sage/groups/perm_gps/permgroup_named.py
--- a/sage/groups/perm_gps/permgroup_named.py
+++ b/sage/groups/perm_gps/permgroup_named.py
@@ -37,7 +37,7 @@
 -- PSp(2n,q), projective symplectic linear group of $2n\times 2n$ matrices 
               over the finite field GF(q)
 
--- PSU(n,q), projective special unitary group of $n\times n$ matrices having
+-- PSU(n,q), projective special unitary group of $n \times n$ matrices having
              coefficients in the finite field $GF(q^2)$ that respect a 
              fixed nondegenerate sesquilinear form, of determinant 1.
 
@@ -78,32 +78,50 @@
 from sage.groups.abelian_gps.abelian_group import AbelianGroup
 from sage.misc.functional import is_even
 from sage.misc.cachefunc import cached_method
+from sage.misc.misc import deprecated_function_alias
 from sage.groups.perm_gps.permgroup import PermutationGroup_generic
 from sage.groups.perm_gps.permgroup_element import PermutationGroupElement
 from sage.structure.unique_representation import UniqueRepresentation
 from sage.structure.parent import Parent
 from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
+from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
 from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets
-from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
 from sage.categories.enumerated_sets import EnumeratedSets
 from sage.sets.non_negative_integers import NonNegativeIntegers
 from sage.sets.family import Family
 
 class PermutationGroup_unique(UniqueRepresentation, PermutationGroup_generic):
+    @staticmethod
+    def __classcall__(cls, *args, **kwds):
+        """
+        This makes sure that domain is a FiniteEnumeratedSet before it gets passed
+        on to the __init__ method.
 
+        EXAMPLES::
+
+            sage: SymmetricGroup(['a','b']).domain() #indirect doctest
+            {'a', 'b'}
+        """
+        domain = kwds.pop('domain', None)
+        if domain is not None:
+            if domain not in FiniteEnumeratedSets():
+                domain = FiniteEnumeratedSet(domain)
+            kwds['domain'] = domain
+        return super(PermutationGroup_unique, cls).__classcall__(cls, *args, **kwds)
+ 
     def __eq__(self, other):
-         """
-         Overrides the default equality testing provided by
-         UniqueRepresentation by forcing a call to :meth:.`__cmp__`.
+        """
+        Overrides the default equality testing provided by
+        UniqueRepresentation by forcing a call to :meth:.`__cmp__`.
 
-         EXAMPLES::
-
-             sage: G = SymmetricGroup(6)
-             sage: G3 = G.subgroup([G((1,2,3,4,5,6)),G((1,2))])
-             sage: G == G3
-             True
-         """
-         return self.__cmp__(other) == 0
+        EXAMPLES::
+        
+            sage: G = SymmetricGroup(6)
+            sage: G3 = G.subgroup([G((1,2,3,4,5,6)),G((1,2))])
+            sage: G == G3
+            True
+        """
+        return self.__cmp__(other) == 0
 
 
 class PermutationGroup_symalt(PermutationGroup_unique):
@@ -113,7 +131,7 @@
     """
 
     @staticmethod
-    def __classcall__(cls, n):
+    def __classcall__(cls, domain):
         """
         Normalizes the input of the constructor into a set
 
@@ -142,86 +160,29 @@
             sage: SymmetricGroup(-1)
             Traceback (most recent call last):
             ...
-            ValueError: n (=-1) must be an integer >= 0 or a list
+            ValueError: domain (=-1) must be an integer >= 0 or a list
         """
-        if not isinstance(n, (tuple,list)):
-            try:
-                n = Integer(n)
-            except TypeError:
-                raise ValueError, "n (=%s) must be an integer >= 0 or a list (but n has type %s)"%(n,type(n))
-            else:
-                if n < 0:
-                    raise ValueError, "n (=%s) must be an integer >= 0 or a list"%n
-                n = range(1, n+1)
+        if domain not in FiniteEnumeratedSets():
+            if not isinstance(domain, (tuple, list)):
+                try:
+                    domain = Integer(domain)
+                except TypeError:
+                    raise ValueError, "domain (=%s) must be an integer >= 0 or a finite set (but domain has type %s)"%(domain,type(domain))
+                
+                if domain < 0:
+                    raise ValueError, "domain (=%s) must be an integer >= 0 or a list"%domain
+                else:
+                    domain = range(1, domain+1)
+            v = FiniteEnumeratedSet(domain)
+        else:
+            v = domain
 
-        try:
-            v = tuple(Integer(z) for z in n)
-        except TypeError:
-            raise ValueError, "each entry of list must be an integer"
+        return super(PermutationGroup_symalt, cls).__classcall__(cls, domain=v)
 
-        if v and min(v) < 1: # for SymmetricGroup(0), v is empty
-            raise ValueError, "each element of list must be positive"
-
-        return super(PermutationGroup_symalt, cls).__classcall__(cls, v)
-
-    def set(self):
-        """
-        Returns the list of positive integers on which this group acts.
-
-        EXAMPLES:
-            sage: SymmetricGroup(3).set()
-            (1, 2, 3)
-            sage: SymmetricGroup([2,3,4]).set()
-            (2, 3, 4)
-            sage: AlternatingGroup(3).set()
-            (1, 2, 3)
-            sage: AlternatingGroup([2,3,4]).set()
-            (2, 3, 4)
-        """
-        return self._set
-
-    @cached_method
-    def _has_natural_set(self):
-        """
-        Returns true if the underlying set is of the form (1,...,n)
-
-        EXAMPLES::
-
-            sage: SymmetricGroup(3)._has_natural_set()
-            True
-            sage: SymmetricGroup((1,2,3))._has_natural_set()
-            True
-            sage: SymmetricGroup((1,3))._has_natural_set()
-            False
-            sage: SymmetricGroup((3,2,1))._has_natural_set()
-            False
-        """
-        set = self.set()
-        return set == tuple(range(1,len(set)+1))
-
-    def __str__(self):
-        """
-        EXAMPLES:
-            sage: S = SymmetricGroup([2,3,7]); S
-            Symmetric group of order 3! as a permutation group
-            sage: str(S)
-            'SymmetricGroup((2, 3, 7))'
-            sage: S = SymmetricGroup(5); S
-            Symmetric group of order 5! as a permutation group
-            sage: str(S)
-            'SymmetricGroup(5)'
-            sage: A = AlternatingGroup([2,3,7]); A
-            Alternating group of order 3!/2 as a permutation group
-            sage: str(A)
-            'AlternatingGroup((2, 3, 7))'
-        """
-        set = self._set
-        if self._has_natural_set():
-            set = len(set)
-        return "%s(%s)"%(self._gap_name, set)
+    set = deprecated_function_alias(PermutationGroup_generic.domain, 'Sage Version 4.7.1')
 
 class SymmetricGroup(PermutationGroup_symalt):
-    def __init__(self, _set):
+    def __init__(self, domain=None):
         """
         The full symmetric group of order $n!$, as a permutation group.
         If n is a list or tuple of positive integers then it returns the
@@ -244,13 +205,13 @@
             sage: G = SymmetricGroup([1,2,4,5])
             sage: G
             Symmetric group of order 4! as a permutation group
-            sage: G.set()
-            (1, 2, 4, 5)
+            sage: G.domain()
+            {1, 2, 4, 5}
             sage: G = SymmetricGroup(4)
             sage: G
             Symmetric group of order 4! as a permutation group
-            sage: G.set()
-            (1, 2, 3, 4)
+            sage: G.domain()
+            {1, 2, 3, 4}
             sage: G.category()
             Join of Category of finite permutation groups and Category of finite weyl groups
             sage: TestSuite(G).run()
@@ -262,22 +223,38 @@
         from sage.categories.finite_weyl_groups import FiniteWeylGroups
         from sage.categories.finite_permutation_groups import FinitePermutationGroups
         from sage.categories.category import Category
+        
         #Note that we skip the call to the superclass initializer in order to
         #avoid infinite recursion since SymmetricGroup is called by
         #PermutationGroupElement
-        super(PermutationGroup_generic,self).__init__(category = Category.join([FinitePermutationGroups(), FiniteWeylGroups()]))
-
-        self._set = _set
-        self._deg = max(self._set+(0,))  # _set cat be empty
-        n = len(self._set)
+        super(PermutationGroup_generic, self).__init__(category = Category.join([FinitePermutationGroups(), FiniteWeylGroups()]))
+        
+        self._domain = domain
+        self._deg = len(self._domain)
+        self._domain_to_gap = dict((key, i+1) for i, key in enumerate(self._domain))
+        self._domain_from_gap = dict((i+1, key) for i, key in enumerate(self._domain))
 
         #Create the generators for the symmetric group
-        gens = [ tuple(self._set) ]
-        if n > 2:
-            gens.append( tuple(self._set[:2]) )
+        gens = [ tuple(self._domain) ]
+        if len(self._domain) > 2:
+            gens.append( tuple(self._domain[:2]) )
         self._gens = [PermutationGroupElement(g, self, check=False) for g in gens]
 
-        self._gap_string = '%s(%s)'%(self._gap_name, n)
+
+    def _gap_init_(self, gap=None):
+        """
+        Returns the string used to create this group in GAP.
+
+        EXAMPLES::
+
+            sage: S = SymmetricGroup(3)
+            sage: S._gap_init_()
+            'SymmetricGroup(3)'
+            sage: S = SymmetricGroup(['a', 'b', 'c'])
+            sage: S._gap_init_()
+            'SymmetricGroup(3)'
+        """
+        return 'SymmetricGroup(%s)'%self.degree()
 
     @cached_method
     def index_set(self):
@@ -288,13 +265,13 @@
 
             sage: S8 = SymmetricGroup(8)
             sage: S8.index_set()
-            (1, 2, 3, 4, 5, 6, 7)
+            [1, 2, 3, 4, 5, 6, 7]
 
             sage: S = SymmetricGroup([3,1,4,5])
             sage: S.index_set()
-            (3, 1, 4)
+            [3, 1, 4]
         """
-        return self.set()[:-1]
+        return self.domain()[:-1]
 
     def __cmp__(self, x):
         """
@@ -307,7 +284,7 @@
             True
         """
         if isinstance(x, SymmetricGroup):
-            return cmp((self._deg, self._set), (x._deg, x._set))
+            return cmp((self._deg, self._domain), (x._deg, x._domain))
         else:
             return PermutationGroup_generic.__cmp__(self, x)
 
@@ -317,9 +294,7 @@
             sage: A = SymmetricGroup([2,3,7]); A
             Symmetric group of order 3! as a permutation group
         """
-        return "Symmetric group of order %s! as a permutation group"%len(self._set)
-
-    _gap_name = 'SymmetricGroup'
+        return "Symmetric group of order %s! as a permutation group"%self.degree()
 
     def simple_reflection(self, i):
         """
@@ -336,7 +311,7 @@
             sage: A.simple_reflections()
             Finite family {2: (2,3), 3: (3,7)}
         """
-        return self([(i, self._set[self._set.index(i)+1])], check=False)
+        return self([(i, self._domain[self._domain.index(i)+1])], check=False)
 
     def major_index(self, parameter=None):
         r"""
@@ -368,7 +343,7 @@
         return q_factorial(self.degree(), parameter)
 
 class AlternatingGroup(PermutationGroup_symalt):
-    def __init__(self, _set):
+    def __init__(self, domain=None):
         """
         The alternating group of order $n!/2$, as a permutation group.
 
@@ -390,25 +365,13 @@
             sage: G = AlternatingGroup([1,2,4,5])
             sage: G
             Alternating group of order 4!/2 as a permutation group
-            sage: G.set()
-            (1, 2, 4, 5)
+            sage: G.domain()
+            {1, 2, 4, 5}
             sage: G.category()
             Category of finite permutation groups
             sage: TestSuite(G).run()
         """
-        n = len(_set)
-        #Create the generators for the symmetric group
-        if n == 1:
-            gens = [ [] ]
-        else:
-            gens = [ tuple(_set) ]
-            if n > 2:
-                gens.append( tuple(_set[:2]) )
-
-        PermutationGroup_symalt.__init__(self, gap_group='%s(%s)'%(self._gap_name,n))
-
-        self._set = _set
-        self._deg = max(_set)
+        PermutationGroup_symalt.__init__(self, gap_group='AlternatingGroup(%s)'%len(domain), domain=domain)
 
     def _repr_(self):
         """
@@ -416,10 +379,23 @@
             sage: A = AlternatingGroup([2,3,7]); A
             Alternating group of order 3!/2 as a permutation group
         """
-        return "Alternating group of order %s!/2 as a permutation group" % len(self._set)
+        return "Alternating group of order %s!/2 as a permutation group"%self.degree()
 
-    _gap_name = 'AlternatingGroup'
+    def _gap_init_(self, gap=None):
+        """
+        Returns the string used to create this group in GAP.
 
+        EXAMPLES::
+
+            sage: A = AlternatingGroup(3)
+            sage: A._gap_init_()
+            'AlternatingGroup(3)'
+            sage: A = AlternatingGroup(['a', 'b', 'c'])
+            sage: A._gap_init_()
+            'AlternatingGroup(3)'
+        """
+        return 'AlternatingGroup(%s)'%(self.degree())
+                   
 class CyclicPermutationGroup(PermutationGroup_unique):
     def __init__(self, n):
         """
@@ -494,7 +470,7 @@
         n = self.order()
         a = list(factor(n))
         invs = [x[0]**x[1] for x in a]
-        G = AbelianGroup(len(a),invs)
+        G = AbelianGroup(len(a), invs)
         return G
 
 class DiCyclicGroup(PermutationGroup_unique):
@@ -636,7 +612,7 @@
         a = [tuple(range(1, halfr+1)), tuple(range(halfr+1, r+1))]
         # With an odd part, a cycle of length m will give the right order for a
         if m > 1:
-            a.append( tuple(range(r+1,r+m+1)) )
+            a.append( tuple(range(r+1, r+m+1)) )
 
         # Representation of  x
         # Four-cycles that will conjugate the generator  a  properly
@@ -644,9 +620,9 @@
                 for i in range(0, fourthr)]
         # With an odd part, transpositions will conjugate the m-cycle to create inverse
         if m > 1:
-            x += [(r+i+1,r+m-i) for i in range(0, (m-1)//2)]
+            x += [(r+i+1, r+m-i) for i in range(0, (m-1)//2)]
 
-        PermutationGroup_generic.__init__(self, gens=[a,x])
+        PermutationGroup_generic.__init__(self, gens=[a, x])
 
     def _repr_(self):
         r"""
@@ -962,7 +938,7 @@
 
         self._d = d
         self._n = n
-        self._set = range(1, d+1)
+        self._domain = range(1, d+1)
 
     def _repr_(self):
         """
@@ -1198,13 +1174,15 @@
             sage: [TransitiveGroups(i).cardinality() for i in range(11)] # requires optional database_gap
             [1, 1, 1, 2, 5, 5, 16, 7, 50, 34, 45]
 
-        .. warning:: The database_gap contains all transitive groups
-          up to degree 30::
+        .. warning::
 
-            sage: TransitiveGroups(31).cardinality()                     # requires optional database_gap
-            Traceback (most recent call last):
-            ...
-            NotImplementedError: Only the transitive groups of order less than 30 are available in GAP's database
+            The database_gap contains all transitive groups
+            up to degree 30::
+
+                sage: TransitiveGroups(31).cardinality()                     # requires optional database_gap
+                Traceback (most recent call last):
+                ...
+                NotImplementedError: Only the transitive groups of order less than 30 are available in GAP's database
 
         TESTS::
 
@@ -1283,7 +1261,6 @@
             Category of finite permutation groups
             sage: TestSuite(G).run()
         """
-        from sage.groups.perm_gps.permgroup import PermutationGroup_generic
         id = 'Group([()])' if n == 1 else 'PGL(%s,%s)'%(n,q)
         PermutationGroup_generic.__init__(self, gap_group=id)
         self._q = q
@@ -1585,7 +1562,10 @@
 class SuzukiGroup(PermutationGroup_unique):
     def __init__(self, q, name='a'):
         r"""
-        The Suzuki group over GF(q), $^2 B_2(2^{2k+1}) = Sz(2^{2k+1})$. A wrapper for the GAP function SuzukiGroup.
+        The Suzuki group over GF(q),
+        $^2 B_2(2^{2k+1}) = Sz(2^{2k+1})$.
+
+        A wrapper for the GAP function SuzukiGroup.
 
         INPUT:
             q -- 2^n, an odd power of 2; the size of the ground
@@ -1595,11 +1575,13 @@
                     finite field GF(q)
 
         OUTPUT:
-            A Suzuki group.
+        
+        - A Suzuki group.
 
-        EXAMPLES:
+        EXAMPLES::
+        
             sage: SuzukiGroup(8)
-            Permutation Group with generators [(1,28,10,44)(3,50,11,42)(4,43,53,64)(5,9,39,52)(6,36,63,13)(7,51,60,57)(8,33,37,16)(12,24,55,29)(14,30,48,47)(15,19,61,54)(17,59,22,62)(18,23,34,31)(20,38,49,25)(21,26,45,58)(27,32,41,65)(35,46,40,56), (1,2)(3,10)(4,42)(5,18)(6,50)(7,26)(8,58)(9,34)(12,28)(13,45)(14,44)(15,23)(16,31)(17,21)(19,39)(20,38)(22,25)(24,61)(27,60)(29,65)(30,55)(32,33)(35,52)(36,49)(37,59)(40,54)(41,62)(43,53)(46,48)(47,56)(51,63)(57,64)]
+            Permutation Group with generators [(1,2)(3,10)(4,42)(5,18)(6,50)(7,26)(8,58)(9,34)(12,28)(13,45)(14,44)(15,23)(16,31)(17,21)(19,39)(20,38)(22,25)(24,61)(27,60)(29,65)(30,55)(32,33)(35,52)(36,49)(37,59)(40,54)(41,62)(43,53)(46,48)(47,56)(51,63)(57,64), (1,28,10,44)(3,50,11,42)(4,43,53,64)(5,9,39,52)(6,36,63,13)(7,51,60,57)(8,33,37,16)(12,24,55,29)(14,30,48,47)(15,19,61,54)(17,59,22,62)(18,23,34,31)(20,38,49,25)(21,26,45,58)(27,32,41,65)(35,46,40,56)]
             sage: print SuzukiGroup(8)
             The Suzuki group over Finite Field in a of size 2^3
 
@@ -1612,7 +1594,8 @@
             Finite Field in alpha of size 2^5
 
         REFERENCES:
-            http://en.wikipedia.org/wiki/Group_of_Lie_type\#Suzuki-Ree_groups
+        
+        -  http://en.wikipedia.org/wiki/Group_of_Lie_type\#Suzuki-Ree_groups
         """
         q = Integer(q)
         from sage.rings.arith import valuation
diff --git a/sage/rings/number_field/galois_group.py b/sage/rings/number_field/galois_group.py
--- a/sage/rings/number_field/galois_group.py
+++ b/sage/rings/number_field/galois_group.py
@@ -343,8 +343,10 @@
             sage: G.subgroup([ G(1), G([(1,5,2),(3,4,6)]), G([(1,2,5),(3,6,4)])])
             Subgroup [(), (1,5,2)(3,4,6), (1,2,5)(3,6,4)] of Galois group of Number Field in b with defining polynomial x^6 - 14*x^4 + 20*x^3 + 49*x^2 - 140*x + 307
         """
-        if len(elts) == self.order(): return self
-        else: return GaloisGroup_subgroup(self, elts)
+        if len(elts) == self.order():
+            return self
+        else:
+            return GaloisGroup_subgroup(self, elts)
 
     # Proper number theory starts here. All the functions below make no sense
     # unless the field is Galois.
@@ -560,11 +562,14 @@
             sage: GaloisGroup_subgroup( G, [ G(1), G([(1,5,2),(3,4,6)]), G([(1,2,5),(3,6,4)])])
             Subgroup [(), (1,5,2)(3,4,6), (1,2,5)(3,6,4)] of Galois group of Number Field in b with defining polynomial x^6 - 14*x^4 + 20*x^3 + 49*x^2 - 140*x + 307
         """
-
+        #XXX: This should be fixed so that this can use GaloisGroup_v2.__init__
         PermutationGroup_generic.__init__(self, elts, canonicalize = True)
         self._ambient = ambient
         self._number_field = ambient.number_field()
-        self._galois_closure=ambient._galois_closure
+        self._galois_closure = ambient._galois_closure
+        self._pari_data = ambient._pari_data
+        self._pari_gc = ambient._pari_gc
+        self._gc_map = ambient._gc_map
         self._elts = elts
         
     def fixed_field(self):
@@ -683,7 +688,8 @@
         return min(w)    
 
     def __cmp__(self, other):
-        r"""Compare self to other. For some bizarre reason, if you just let it
+        r"""
+        Compare self to other. For some bizarre reason, if you just let it
         inherit the cmp routine from PermutationGroupElement, cmp(x, y) works
         but sorting lists doesn't.
         
@@ -691,9 +697,9 @@
         
             sage: K.<a> = NumberField(x^6 + 40*x^3 + 1372);G = K.galois_group()
             sage: sorted([G.artin_symbol(Q) for Q in K.primes_above(5)])
-            [(1,2)(3,4)(5,6), (1,3)(2,6)(4,5), (1,5)(2,4)(3,6)]
+            [(1,3)(2,6)(4,5), (1,2)(3,4)(5,6), (1,5)(2,4)(3,6)]
         """
-        return cmp(self.list(), other.list())
+        return PermutationGroupElement.__cmp__(self, other)
 
 
 
diff --git a/sage/rings/number_field/number_field.py b/sage/rings/number_field/number_field.py
--- a/sage/rings/number_field/number_field.py
+++ b/sage/rings/number_field/number_field.py
@@ -6785,7 +6785,7 @@
             sage: z = CyclotomicField(3).an_element(); z
             zeta3
             sage: c = K.character([1,z,z**2]); c
-            Character of Subgroup of AlternatingGroup(4) generated by [(2,3,4)]
+            Character of Subgroup of (Alternating group of order 4!/2 as a permutation group) generated by [(2,3,4)]
             sage: c(g^2); z^2
             -zeta3 - 1
             -zeta3 - 1
diff --git a/sage/sets/finite_enumerated_set.py b/sage/sets/finite_enumerated_set.py
--- a/sage/sets/finite_enumerated_set.py
+++ b/sage/sets/finite_enumerated_set.py
@@ -181,6 +181,18 @@
         """
         return Integer(len(self._elements))
 
+    def index(self, x):
+        """
+        Returns the index of ``x`` in this finite enumerated set.
+
+        EXAMPLES::
+
+            sage: S = FiniteEnumeratedSet(['a','b','c'])
+            sage: S.index('b')
+            1
+        """
+        return self._elements.index(x)
+
     def _element_constructor_(self, el):
         """
         TESTS::
diff --git a/sage/structure/parent.pyx b/sage/structure/parent.pyx
--- a/sage/structure/parent.pyx
+++ b/sage/structure/parent.pyx
@@ -1668,7 +1668,7 @@
             sage: S3.register_embedding(phi)
             sage: S3.coerce_embedding()
             Generic morphism:
-              From: AlternatingGroup(3)
+              From: Alternating group of order 3!/2 as a permutation group
               To:   Special Linear Group of degree 3 over Rational Field
             sage: S3.coerce_embedding()(p)
             [0 0 1]
diff --git a/sage/structure/parent_gens.pyx b/sage/structure/parent_gens.pyx
--- a/sage/structure/parent_gens.pyx
+++ b/sage/structure/parent_gens.pyx
@@ -368,7 +368,7 @@
         if d.has_key('_element_constructor'):
             return parent.Parent.__setstate__(self, d)
         try:
-            self.__dict__ = d
+            self.__dict__.update(d)
             self._generator_orders = d['_generator_orders']
         except (AttributeError,KeyError):
             pass
