Ticket #10335: trac_10335-permgroup_domain-mh.patch

File trac_10335-permgroup_domain-mh.patch, 130.5 KB (added by mhansen, 10 years ago)
  • doc/en/bordeaux_2008/nf_galois_groups.rst

    # 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 b  
    4141    sage: P = K.primes_above(2)[0]
    4242    sage: G.inertia_group(P)
    4343    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
    44     sage: sorted([G.artin_symbol(Q) for Q in K.primes_above(5)]) # (order is platform-dependent)
    45     [(1,2)(3,4)(5,6), (1,3)(2,6)(4,5), (1,5)(2,4)(3,6)]
     44    sage: sorted([G.artin_symbol(Q) for Q in K.primes_above(5)])
     45    [(1,3)(2,6)(4,5), (1,2)(3,4)(5,6), (1,5)(2,4)(3,6)]
    4646
    4747If the number field is not Galois over `\QQ`, then the ``galois_group``
    4848command will construct its Galois closure and return the Galois group of that;
  • doc/en/constructions/groups.rst

    diff --git a/doc/en/constructions/groups.rst b/doc/en/constructions/groups.rst
    a b  
    232232
    233233    sage: G = PermutationGroup(['(1,2,3)(4,5)', '(3,4)'])
    234234    sage: G.center()
    235     Permutation Group with generators [()]
     235    Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]
    236236
    237237A similar syntax for matrix groups also works:
    238238
     
    244244     [[[4, 0], [0, 4]]]
    245245    sage: G = PSL(2, 5 )
    246246    sage: G.center()
    247     Permutation Group with generators [()]
     247    Subgroup of (The projective special linear group of degree 2 over Finite Field of size 5) generated by [()]
    248248
    249249Note: ``center`` can be spelled either way in GAP, not so in Sage.
    250250
  • doc/en/thematic_tutorials/group_theory.rst

    diff --git a/doc/en/thematic_tutorials/group_theory.rst b/doc/en/thematic_tutorials/group_theory.rst
    a b  
    569569
    570570    sage: C20 = CyclicPermutationGroup(20)
    571571    sage: C20.conjugacy_classes_subgroups()
    572     [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)]]
     572    [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)]]
    573573
    574574Be careful, this command uses some more advanced ideas and will not
    575575usually list *all* of the subgroups of a group. Here we are relying on
     
    623623    sage: sg = K.conjugacy_classes_subgroups()
    624624    sage: print "sg:\n", sg
    625625    sg:
    626     [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)]]
     626    [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)]]
    627627    sage: print "\nAn order two subgroup:\n", sg[1].list()
    628628    <BLANKLINE>
    629629    An order two subgroup:
  • doc/en/tutorial/interfaces.rst

    diff --git a/doc/en/tutorial/interfaces.rst b/doc/en/tutorial/interfaces.rst
    a b  
    174174
    175175    sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])
    176176    sage: G.center()
    177     Permutation Group with generators [()]
     177    Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]
    178178    sage: G.group_id()     # requires optional database_gap package
    179179    [120, 34]
    180180    sage: n = G.order(); n
  • doc/en/tutorial/tour_groups.rst

    diff --git a/doc/en/tutorial/tour_groups.rst b/doc/en/tutorial/tour_groups.rst
    a b  
    2222    [Permutation Group with generators [(1,2,3)(4,5), (3,4)],
    2323     Permutation Group with generators [(1,5)(3,4), (1,5)(2,4), (1,3,5)]]
    2424    sage: G.center()
    25     Permutation Group with generators [()]
     25    Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]
    2626    sage: G.random_element()           # random output
    2727    (1,5,3)(2,4)
    2828    sage: print latex(G)
  • doc/fr/tutorial/interfaces.rst

    diff --git a/doc/fr/tutorial/interfaces.rst b/doc/fr/tutorial/interfaces.rst
    a b  
    175175
    176176    sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])
    177177    sage: G.center()
    178     Permutation Group with generators [()]
     178    Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]
    179179    sage: G.group_id()    # nécessite le paquet facultatif database_gap (optional)
    180180    [120, 34]
    181181    sage: n = G.order(); n
  • doc/fr/tutorial/tour_groups.rst

    diff --git a/doc/fr/tutorial/tour_groups.rst b/doc/fr/tutorial/tour_groups.rst
    a b  
    2323    [Permutation Group with generators [(1,2,3)(4,5), (3,4)],
    2424     Permutation Group with generators [(1,5)(3,4), (1,5)(2,4), (1,3,5)]]
    2525    sage: G.center()
    26     Permutation Group with generators [()]
     26    Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]
    2727    sage: G.random_element()           # sortie aléatoire (random)
    2828    (1,5,3)(2,4)
    2929    sage: print latex(G)
  • sage/categories/finite_groups.py

    diff --git a/sage/categories/finite_groups.py b/sage/categories/finite_groups.py
    a b  
    8282
    8383                sage: A = AlternatingGroup(4)
    8484                sage: A.semigroup_generators()
    85                 Family ((1,2,3), (2,3,4))
     85                Family ((2,3,4), (1,2,3))
    8686            """
    8787            return self.group_generators()
    8888
  • sage/categories/g_sets.py

    diff --git a/sage/categories/g_sets.py b/sage/categories/g_sets.py
    a b  
    2525
    2626        sage: S = SymmetricGroup(3)
    2727        sage: GSets(S)
    28         Category of G-sets for SymmetricGroup(3)
     28        Category of G-sets for Symmetric group of order 3! as a permutation group
    2929
    3030    TODO: should this derive from Category_over_base?
    3131    """
     
    4444        EXAMPLES::
    4545
    4646            sage: GSets(SymmetricGroup(8)) # indirect doctests
    47             Category of G-sets for SymmetricGroup(8)
     47            Category of G-sets for Symmetric group of order 8! as a permutation group
    4848        """
    4949        return "G-sets for %s"%self.__G
    5050
     
    7070        EXAMPLES::
    7171       
    7272            sage: GSets.an_instance() # indirect doctest
    73             Category of G-sets for SymmetricGroup(8)
     73            Category of G-sets for Symmetric group of order 8! as a permutation group
    7474        """
    7575        from sage.groups.perm_gps.permgroup_named import SymmetricGroup
    7676        G = SymmetricGroup(8)
  • sage/categories/groupoid.py

    diff --git a/sage/categories/groupoid.py b/sage/categories/groupoid.py
    a b  
    5050
    5151            sage: S8 = SymmetricGroup(8)
    5252            sage: Groupoid(S8)
    53             Groupoid with underlying set SymmetricGroup(8)
     53            Groupoid with underlying set Symmetric group of order 8! as a permutation group
    5454        """
    5555        return "Groupoid with underlying set %s"%self.__G
    5656
     
    7676        EXAMPLES::
    7777
    7878            sage: Groupoid.an_instance() # indirect doctest
    79             Groupoid with underlying set SymmetricGroup(8)
     79            Groupoid with underlying set Symmetric group of order 8! as a permutation group
    8080        """
    8181        from sage.groups.perm_gps.permgroup_named import SymmetricGroup
    8282        G = SymmetricGroup(8)
  • sage/categories/groups.py

    diff --git a/sage/categories/groups.py b/sage/categories/groups.py
    a b  
    6868
    6969                sage: A = AlternatingGroup(4)
    7070                sage: A.group_generators()
    71                 Family ((1,2,3), (2,3,4))
     71                Family ((2,3,4), (1,2,3))
    7272            """
    7373            return Family(self.gens())
    7474
  • sage/categories/homset.py

    diff --git a/sage/categories/homset.py b/sage/categories/homset.py
    a b  
    6363        Category of vector spaces over Rational Field
    6464        sage: G = AlternatingGroup(3)
    6565        sage: Hom(G, G)
    66         Set of Morphisms from AlternatingGroup(3) to AlternatingGroup(3) in Category of finite permutation groups
     66        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
    6767        sage: Hom(ZZ, QQ, Sets())
    6868        Set of Morphisms from Integer Ring to Rational Field in Category of sets
    6969
     
    196196   
    197197        sage: G = AlternatingGroup(3)
    198198        sage: S = End(G); S
    199         Set of Morphisms from AlternatingGroup(3) to AlternatingGroup(3) in Category of finite permutation groups
     199        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
    200200        sage: from sage.categories.homset import is_Endset
    201201        sage: is_Endset(S)
    202202        True
     
    361361            sage: phi = Hom(SymmetricGroup(5), SymmetricGroup(6)).natural_map()
    362362            sage: phi
    363363            Coercion morphism:
    364               From: SymmetricGroup(5)
    365               To:   SymmetricGroup(6)
     364              From: Symmetric group of order 5! as a permutation group
     365              To:   Symmetric group of order 6! as a permutation group
    366366            sage: H(phi)
    367367            Composite map:
    368               From: SymmetricGroup(4)
    369               To:   SymmetricGroup(7)
     368              From: Symmetric group of order 4! as a permutation group
     369              To:   Symmetric group of order 7! as a permutation group
    370370              Defn:   Composite map:
    371                       From: SymmetricGroup(4)
    372                       To:   SymmetricGroup(6)
     371                      From: Symmetric group of order 4! as a permutation group
     372                      To:   Symmetric group of order 6! as a permutation group
    373373                      Defn:   Call morphism:
    374                               From: SymmetricGroup(4)
    375                               To:   SymmetricGroup(5)
     374                              From: Symmetric group of order 4! as a permutation group
     375                              To:   Symmetric group of order 5! as a permutation group
    376376                            then
    377377                              Coercion morphism:
    378                               From: SymmetricGroup(5)
    379                               To:   SymmetricGroup(6)
     378                              From: Symmetric group of order 5! as a permutation group
     379                              To:   Symmetric group of order 6! as a permutation group
    380380                    then
    381381                      Call morphism:
    382                       From: SymmetricGroup(6)
    383                       To:   SymmetricGroup(7)
     382                      From: Symmetric group of order 6! as a permutation group
     383                      To:   Symmetric group of order 7! as a permutation group
    384384
    385385            sage: H = Hom(ZZ, ZZ, Sets())
    386386            sage: f = H( lambda x: x + 1 )
  • sage/categories/hopf_algebras_with_basis.py

    diff --git a/sage/categories/hopf_algebras_with_basis.py b/sage/categories/hopf_algebras_with_basis.py
    a b  
    123123        An other group can be specified as optional argument::
    124124
    125125            sage: HopfAlgebrasWithBasis(QQ).example(SymmetricGroup(4))
    126             An example of Hopf algebra with basis: the group algebra of the SymmetricGroup(4) over Rational Field
     126            An example of Hopf algebra with basis: the group algebra of the Symmetric group of order 4! as a permutation group over Rational Field
    127127        """
    128128        from sage.categories.examples.hopf_algebras_with_basis import MyGroupAlgebra
    129129        from sage.groups.perm_gps.permgroup_named import DihedralGroup
  • sage/categories/map.pyx

    diff --git a/sage/categories/map.pyx b/sage/categories/map.pyx
    a b  
    115115            sage: Map(QQ['x'], SymmetricGroup(6))
    116116            Generic map:
    117117              From: Univariate Polynomial Ring in x over Rational Field
    118               To:   SymmetricGroup(6)
     118              To:   Symmetric group of order 6! as a permutation group
    119119        """
    120120        if codomain is not None:
    121121            if PY_TYPE_CHECK(parent, type):
  • sage/categories/pushout.py

    diff --git a/sage/categories/pushout.py b/sage/categories/pushout.py
    a b  
    27102710
    27112711    rank = 10
    27122712
    2713     def __init__(self, gens):
     2713    def __init__(self, gens, domain):
    27142714        """
    27152715        EXAMPLES::
    27162716
    27172717            sage: from sage.categories.pushout import PermutationGroupFunctor
    2718             sage: PF = PermutationGroupFunctor([PermutationGroupElement([(1,2)])]); PF
     2718            sage: PF = PermutationGroupFunctor([PermutationGroupElement([(1,2)])], [1,2]); PF
    27192719            PermutationGroupFunctor[(1,2)]
    27202720        """
    27212721        Functor.__init__(self, Groups(), Groups())
    27222722        self._gens = gens
     2723        self._domain = domain
    27232724
    27242725    def __repr__(self):
    27252726        """
     
    27422743            Permutation Group with generators [(1,2)]
    27432744        """
    27442745        from sage.groups.perm_gps.permgroup import PermutationGroup
    2745         return PermutationGroup([g for g in (R.gens() + self.gens()) if not g.is_one()])
     2746        return PermutationGroup([g for g in (R.gens() + self.gens()) if not g.is_one()],
     2747                                domain=self._domain)
    27462748
    27472749    def gens(self):
    27482750        """
     
    27702772        """
    27712773        if self.__class__ != other.__class__:
    27722774            return None
    2773         return PermutationGroupFunctor(self.gens() + other.gens())
     2775        from sage.sets.all import FiniteEnumeratedSet
     2776
     2777        new_domain = set(self._domain).union(set(other._domain))
     2778        new_domain = FiniteEnumeratedSet(sorted(new_domain))
     2779        return PermutationGroupFunctor(self.gens() + other.gens(),
     2780                                       new_domain)
    27742781
    27752782class BlackBoxConstructionFunctor(ConstructionFunctor):
    27762783    """
  • sage/combinat/permutation.py

    diff --git a/sage/combinat/permutation.py b/sage/combinat/permutation.py
    a b  
    562562                cycles.append(tuple(cycle))
    563563        return cycles
    564564
     565    cycle_tuples = to_cycles
     566
    565567    def _to_cycles_orig(self, singletons=True):
    566568        r"""
    567569        Returns the permutation p as a list of disjoint cycles.
     
    34233425   
    34243426    p = range(1,n+1)
    34253427    for cycle in cycles:
     3428        if not cycle:
     3429            continue
    34263430        first = cycle[0]
    34273431        for i in range(len(cycle)-1):
    34283432            p[cycle[i]-1] = cycle[i+1]
  • sage/combinat/species/cycle_species.py

    diff --git a/sage/combinat/species/cycle_species.py b/sage/combinat/species/cycle_species.py
    a b  
    100100            sage: [a.transport(perm) for perm in a.automorphism_group()]
    101101            [(1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4)]
    102102        """
    103         from sage.groups.all import SymmetricGroup
     103        from sage.groups.all import SymmetricGroup, PermutationGroup
    104104        S = SymmetricGroup(len(self._labels))
    105105        p = self.permutation_group_element()
    106         return S.centralizer(p)
     106        return PermutationGroup(S.centralizer(p).gens())
    107107
    108108@accept_size
    109109@cached_function
  • sage/combinat/species/permutation_species.py

    diff --git a/sage/combinat/species/permutation_species.py b/sage/combinat/species/permutation_species.py
    a b  
    9898             ['a', 'c', 'b', 'd'],
    9999             ['a', 'c', 'b', 'd']]
    100100        """
    101         from sage.groups.all import SymmetricGroup
     101        from sage.groups.all import SymmetricGroup, PermutationGroup
    102102        S = SymmetricGroup(len(self._labels))
    103103        p = self.permutation_group_element()
    104         return S.centralizer(p)
     104        return PermutationGroup(S.centralizer(p).gens())
    105105       
    106106@accept_size
    107107@cached_function
  • sage/groups/abelian_gps/abelian_group.py

    diff --git a/sage/groups/abelian_gps/abelian_group.py b/sage/groups/abelian_gps/abelian_group.py
    a b  
    830830            sage: G = AbelianGroup(2,[2,3]); G
    831831            Multiplicative Abelian Group isomorphic to C2 x C3
    832832            sage: G.permutation_group()
    833             Permutation Group with generators [(1,4)(2,5)(3,6), (1,2,3)(4,5,6)]
     833            Permutation Group with generators [(1,2,3)(4,5,6), (1,4)(2,5)(3,6)]
    834834        """
    835835        from sage.groups.perm_gps.permgroup import PermutationGroup
    836836        s = 'Image(IsomorphismPermGroup(%s))'%self._gap_init_()
  • sage/groups/abelian_gps/abelian_group_element.py

    diff --git a/sage/groups/abelian_gps/abelian_group_element.py b/sage/groups/abelian_gps/abelian_group_element.py
    a b  
    227227            Multiplicative Abelian Group isomorphic to C2 x C3 x C4
    228228            sage: a,b,c=G.gens()
    229229            sage: Gp = G.permutation_group(); Gp
    230             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)]
     230            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)]
    231231            sage: a.as_permutation()
    232232            (1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24)
    233233            sage: ap = a.as_permutation(); ap
  • sage/groups/class_function.py

    diff --git a/sage/groups/class_function.py b/sage/groups/class_function.py
    a b  
    407407            Character of Symmetric group of order 5! as a permutation group
    408408            sage: H = G.subgroup([(1,2,3), (1,2), (4,5)])
    409409            sage: chi.restrict(H)
    410             Character of Subgroup of SymmetricGroup(5) generated by [(4,5), (1,2), (1,2,3)]
     410            Character of Subgroup of (Symmetric group of order 5! as a permutation group) generated by [(4,5), (1,2), (1,2,3)]
    411411            sage: chi.restrict(H).values()
    412412            [3, -3, -3, -1, 0, 0]
    413413        """
     
    420420            sage: G = SymmetricGroup(5)
    421421            sage: H = G.subgroup([(1,2,3), (1,2), (4,5)])
    422422            sage: xi = H.trivial_character(); xi
    423             Character of Subgroup of SymmetricGroup(5) generated by [(4,5), (1,2), (1,2,3)]
     423            Character of Subgroup of (Symmetric group of order 5! as a permutation group) generated by [(4,5), (1,2), (1,2,3)]
    424424            sage: xi.induct(G)
    425425            Character of Symmetric group of order 5! as a permutation group
    426426            sage: xi.induct(G).values()
  • sage/groups/perm_gps/permgroup.py

    diff --git a/sage/groups/perm_gps/permgroup.py b/sage/groups/perm_gps/permgroup.py
    a b  
    125125from sage.rings.all import QQ, Integer
    126126from sage.interfaces.all import is_ExpectElement
    127127from sage.interfaces.gap import gap, GapElement
    128 from sage.groups.perm_gps.permgroup_element import PermutationGroupElement
     128from sage.groups.perm_gps.permgroup_element import PermutationGroupElement, standardize_generator
    129129from sage.groups.abelian_gps.abelian_group import AbelianGroup
    130130from sage.misc.cachefunc import cached_method
    131131from sage.groups.class_function import ClassFunction
    132132from sage.misc.package import is_package_installed
     133from sage.sets.all import FiniteEnumeratedSet
     134from sage.categories.all import FiniteEnumeratedSets
    133135
    134136def load_hap():
    135137    """
     
    231233    srcs = map(G, srcs)
    232234    return srcs
    233235
    234 def PermutationGroup(gens=None, gap_group=None, canonicalize=True):
     236def PermutationGroup(gens=None, gap_group=None, domain=None, canonicalize=True, category=None):
    235237    """
    236238    Return the permutation group associated to `x` (typically a
    237239    list of generators).
     
    301303        return gens._permgroup_()
    302304    if gens is not None and not isinstance(gens, (tuple, list, GapElement)):
    303305        raise TypeError, "gens must be a tuple, list, or GapElement"
    304     return PermutationGroup_generic(gens=gens, gap_group=gap_group, canonicalize=canonicalize)
     306    return PermutationGroup_generic(gens=gens, gap_group=gap_group, domain=domain,
     307                                    canonicalize=canonicalize, category=category)
    305308   
    306309
    307310class PermutationGroup_generic(group.Group):
     
    312315        sage: G
    313316        Permutation Group with generators [(3,4), (1,2,3)(4,5)]
    314317        sage: G.center()
    315         Permutation Group with generators [()]
     318        Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]
    316319        sage: G.group_id()          # optional - database_gap
    317320        [120, 34]
    318321        sage: n = G.order(); n
     
    320323        sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])
    321324        sage: TestSuite(G).run()
    322325    """
    323     def __init__(self, gens=None, gap_group=None, canonicalize=True):
     326    def __init__(self, gens=None, gap_group=None, canonicalize=True, domain=None, category=None):
    324327        r"""
    325328        INPUT:
    326329       
     
    347350            sage: A4.__init__([[(1,2,3)],[(2,3,4)]]); A4
    348351            Permutation Group with generators [(2,3,4), (1,2,3)]
    349352            sage: A4.center()
    350             Permutation Group with generators [()]
     353            Subgroup of (Permutation Group with generators [(2,3,4), (1,2,3)]) generated by [()]
    351354            sage: A4.category()
    352355            Category of finite permutation groups
    353356            sage: TestSuite(A4).run()
     
    358361            sage: TestSuite(PermutationGroup([])).run()
    359362        """
    360363        from sage.categories.finite_permutation_groups import FinitePermutationGroups
    361         super(PermutationGroup_generic, self).__init__(category = FinitePermutationGroups())
     364        super(PermutationGroup_generic, self).__init__(category = FinitePermutationGroups().or_subcategory(category))
    362365        if (gens is None and gap_group is None):
    363366            raise ValueError, "you must specify gens or gap_group"
    364367
    365368        #Handle the case where only the GAP group is specified.
    366369        if gens is None:
    367             from sage.interfaces.gap import gap
    368             self._gap_string = gap_group if isinstance(gap_group, str) else str(gap_group)
    369             self._gens = self._gens_from_gap()
    370             self._deg = gap(gap_group).LargestMovedPoint()
    371             self._set = range(1, self._deg+1)
    372         else:
    373             gens = [self._element_class()(x, check=False).list() for x in gens]
    374             self._deg = max([0]+[max(g) for g in gens])
    375             self._set = range(1, self._deg+1)
    376             if not gens:  # length 0
    377                 gens = [()]
    378             gens = [self._element_class()(x, self, check=False) for x in gens]
    379             if canonicalize:
    380                 gens = sorted(set(gens))
    381             self._gens = gens
    382             self._gap_string = 'Group(%s)'%gens
     370            if isinstance(gap_group, str):
     371                gap_group = gap(gap_group)
     372            gens = [gen for gen in gap_group.GeneratorsOfGroup()]
     373
     374        if domain is None:
     375            gens = [standardize_generator(x) for x in gens]
     376            domain = set()
     377            for x in gens:
     378                for cycle in x:
     379                    domain = domain.union(cycle)
     380            domain = sorted(domain)
     381
     382            #Here we need to check if all of the points are integers
     383            #to make the domain contain all integers up to the max.
     384            #This is needed for backward compatibility
     385            if all(isinstance(p, (Integer, int, long)) for p in domain):
     386                domain = range(1, max([1] + domain)+1)
     387
     388        if domain not in FiniteEnumeratedSets():
     389            domain = FiniteEnumeratedSet(domain)
     390
     391        self._domain = domain
     392        self._deg = len(self._domain)
     393        self._domain_to_gap = dict((key, i+1) for i, key in enumerate(self._domain))
     394        self._domain_from_gap = dict((i+1, key) for i, key in enumerate(self._domain))
     395
     396        if not gens:  # length 0
     397            gens = [()]
     398        gens = [self._element_class()(x, self, check=False) for x in gens]
     399        if canonicalize:
     400            gens = sorted(set(gens))
     401        self._gens = gens
    383402
    384403    def construction(self):
    385404         """
     
    400419             (1,2,3)
    401420             sage: p.parent()
    402421             Permutation Group with generators [(1,2), (1,3)]
     422             sage: p.parent().domain()
     423             {1, 2, 3}
     424
     425         Note that this will merge permutation groups with different
     426         domains::
     427
     428             sage: g1 = PermutationGroupElement([(1,2),(3,4,5)])
     429             sage: g2 = PermutationGroup([('a','b')], domain=['a', 'b']).gens()[0]
     430             sage: g2
     431             ('a','b')
     432             sage: p = g1*g2; p
     433             (1,2)(3,4,5)('a','b')
    403434         """
    404435         gens = self.gens()
    405436         if len(gens) == 1 and gens[0].is_one():
    406437              return None
    407438         else:
    408439              from sage.categories.pushout import PermutationGroupFunctor
    409               return (PermutationGroupFunctor(gens), PermutationGroup([]))
    410 
    411     def _gens_from_gap(self):
     440              return (PermutationGroupFunctor(gens, self.domain()),
     441                      PermutationGroup([]))
     442
     443    @cached_method
     444    def _has_natural_domain(self):
    412445        """
    413         Returns the generators of the group by asking GAP for them.
    414        
     446        Returns True if the underlying domain is of the form (1,...,n)
     447
    415448        EXAMPLES::
    416        
    417             sage: S = SymmetricGroup(3)
    418             sage: S._gap_string
    419             'SymmetricGroup(3)'
    420             sage: S._gens_from_gap()
    421             [(1,2,3), (1,2)]
     449
     450            sage: SymmetricGroup(3)._has_natural_domain()
     451            True
     452            sage: SymmetricGroup((1,2,3))._has_natural_domain()
     453            True
     454            sage: SymmetricGroup((1,3))._has_natural_domain()
     455            False
     456            sage: SymmetricGroup((3,2,1))._has_natural_domain()
     457            False
    422458        """
    423         try:
    424             gens = self._gap_().GeneratorsOfGroup()
    425         except TypeError, s:
    426             raise RuntimeError, "(It might be necessary to install the database_gap optional Sage package, if you haven't already.)\n%s"%s
    427         gens = [self._element_class()(gens[n], self, check=False)
    428                        for n in range(1, int(gens.Length())+1)]
    429         if gens == []:
    430             gens = [()]
    431         return gens
    432 
     459        domain = self.domain()
     460        natural_domain = FiniteEnumeratedSet(range(1, len(domain)+1))
     461        return domain == natural_domain
    433462
    434463    def _gap_init_(self):
    435464        r"""
     
    445474            sage: A4 = PermutationGroup([[(1,2,3)],[(2,3,4)]]); A4
    446475            Permutation Group with generators [(2,3,4), (1,2,3)]
    447476            sage: A4._gap_init_()
    448             'Group([(2,3,4), (1,2,3)])'
     477            'Group([PermList([1, 3, 4, 2]), PermList([2, 3, 1, 4])])'
    449478        """
    450         return self._gap_string
     479        return 'Group([%s])'%(', '.join([g._gap_init_() for g in self.gens()]))
    451480
    452481    def _magma_init_(self, magma):
    453482        r"""
    454483        Returns a string showing how to declare / initialize self in Magma.
    455        
     484   
    456485        EXAMPLES:
    457486
    458487        We explicitly construct the alternating group on four
     
    463492            Permutation Group with generators [(2,3,4), (1,2,3)]
    464493            sage: A4._magma_init_(magma)
    465494            'PermutationGroup<4 | (2,3,4), (1,2,3)>'
     495
     496            sage: S = SymmetricGroup(['a', 'b', 'c'])
     497            sage: S._magma_init_(magma)
     498            'PermutationGroup<3 | (1,2,3), (1,2)>'
    466499        """
    467         g = str(self.gens())[1:-1]
     500        g = ', '.join([g._gap_cycle_string() for g in self.gens()])
    468501        return 'PermutationGroup<%s | %s>'%(self.degree(), g)
    469502
    470503    def __cmp__(self, right):
     
    500533            True
    501534            sage: H3 < H1 # since H3 is a subgroup of H1
    502535            True
    503 
    504536        """
    505         if not isinstance(right, PermutationGroup_generic):
     537        if (not isinstance(right, PermutationGroup_generic) or
     538            self.domain() != right.domain()):
    506539            return -1
    507540        if self is right:
    508541            return 0
     
    581614            sage: G([(1,2)])
    582615            Traceback (most recent call last):
    583616            ...
    584             TypeError: permutation (1, 2) not in Permutation Group with generators [(1,2,3,4)]
     617            TypeError: permutation [(1, 2)] not in Permutation Group with generators [(1,2,3,4)]
    585618        """
    586619        try:
    587620            if x.parent() is self:
     
    630663            x_parent = x.parent()
    631664            if x_parent is self:
    632665                return x
    633             elif (x_parent.degree() <= self.degree() and
    634                   (self.__class__ == SymmetricGroup or x._gap_() in self._gap_())):
    635                 return self._element_class()(x.list(), self, check = False)
     666
     667            compatible_domains = all(point in self._domain_to_gap for point in x_parent.domain())
     668            if  compatible_domains and (self.__class__ == SymmetricGroup or x._gap_() in self._gap_()):
     669                return self._element_class()(x.cycle_tuples(), self, check=False)
    636670        raise TypeError, "no implicit coercion of element into permutation group"
    637671
    638672    @cached_method
     
    645679            sage: G = PermutationGroup([[(1,2,3,4)], [(1,2)]])
    646680            sage: G.list()
    647681            [(), (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)]
     682
     683            sage: G = PermutationGroup([[('a','b')]], domain=('a', 'b')); G
     684            Permutation Group with generators [('a','b')]
     685            sage: G.list()
     686            [(), ('a','b')]
    648687        """
    649         X = self._gap_().Elements()
    650         n = X.Length()
    651         L = [self._element_class()(X[i], self, check = False)
    652                             for i in range(1,n+1)]
    653         return L
     688        return list(self.__iter__())
    654689
    655690    def __contains__(self, item):
    656691        """
     
    671706            True
    672707            sage: h in H
    673708            False
     709
     710            sage: G = PermutationGroup([[('a','b')]], domain=('a', 'b'))
     711            sage: [('a', 'b')] in G
     712            True
    674713        """
    675714        try:
    676715            item = self(item, check=True)
     
    709748            sage: G = PermutationGroup([[(1,2,3)], [(1,2)]])
    710749            sage: [a for a in G]
    711750            [(), (2,3), (1,2), (1,2,3), (1,3,2), (1,3)]
    712 
    713         TODO: this currently returns an iterator over the elements of
    714         ``self.list()``. This should be made into a real iterator.
    715751        """
    716         return iter(self.list())
     752        for g in self._gap_().Elements():
     753            yield self._element_class()(g, self, check=False)
    717754
    718755    def gens(self):
    719756        """
     
    769806            sage: G = PermutationGroup([R,L,U,F,B,D])
    770807            sage: len(G.gens_small())
    771808            2
     809
     810            sage: G = PermutationGroup([[('a','b')], [('b', 'c')], [('a', 'c')]])
     811            sage: G.gens_small()
     812            [('a','b'), ('a','b','c')]
    772813        """
    773814        gens = self._gap_().SmallGeneratingSet()
    774815        return [self._element_class()(x, self, check=False) for x in gens]
     
    825866            (1,2,3)(4,5)
    826867            sage: e*g
    827868            (1,2,3)(4,5)
     869
     870            sage: S = SymmetricGroup(['a','b','c'])
     871            sage: S.identity()
     872            ()
    828873        """
    829874        return self._element_class()([], self, check=True)
    830875   
     
    858903       
    859904        ::
    860905       
    861             sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])
     906            sage: G = PermutationGroup([[('a','b','c'),('d','e')]])
     907            sage: G.largest_moved_point()
     908            'e'
     909
     910        .. warning::
     911
     912           The name of this function is not good; this function
     913           should be deprecated in term of degree::
     914
     915                sage: P = PermutationGroup([[1,2,3,4]])
     916                sage: P.largest_moved_point()
     917                4
     918                sage: P.cardinality()
     919                1
     920        """
     921        try:
     922            return self._domain_from_gap[Integer(self._gap_().LargestMovedPoint())]
     923        except KeyError:
     924            return self.degree()
     925
     926    def degree(self):
     927        """
     928        Returns the degree of this permutation group.
     929
     930        EXAMPLES::
     931
     932            sage: S = SymmetricGroup(['a','b','c'])
     933            sage: S.degree()
     934            3
     935            sage: G = PermutationGroup([(1,3),(4,5)])
    862936            sage: G.degree()
    863937            5
    864938
    865         TODO: the name of this function is not good; this function
    866         should be deprecated in term of degree::
    867 
    868             sage: P = PermutationGroup([[1,2,3,4]])
    869             sage: P.largest_moved_point()
     939        Note that you can explicitly specify the domain to get a
     940        permutation group of smaller degree::
     941       
     942            sage: G = PermutationGroup([(1,3),(4,5)], domain=[1,3,4,5])
     943            sage: G.degree()
    870944            4
    871             sage: P.cardinality()
    872             1
    873945        """
    874         # This seems unndeeded since __init__ systematically sets
    875         # self._deg This is actually needed because constructing the
    876         # __init__ of PermutationGroupElement sometimes calls this
    877         # group before is initialized.
    878         try:
    879             return self._deg
    880         except AttributeError:
    881             n = Integer(self._gap_().LargestMovedPoint())
    882         self._deg = n
    883         return n
    884 
    885     degree = largest_moved_point
    886 
    887     def set(self):
     946        return Integer(len(self._domain))
     947
     948    def domain(self):
    888949        r"""
    889950        Returns the underlying set that this permutation group acts
    890         on.  By default, the set is {1, ..., n} where n is the largest
    891         moved point by the group.
     951        on.
    892952
    893953        EXAMPLES::
    894954
    895955            sage: P = PermutationGroup([(1,2),(3,5)])
    896             sage: P.set()
    897             (1, 2, 3, 4, 5)
    898 
     956            sage: P.domain()
     957            {1, 2, 3, 4, 5}
     958            sage: S = SymmetricGroup(['a', 'b', 'c'])
     959            sage: S.domain()
     960            {'a', 'b', 'c'}
    899961        """
    900         return tuple(self._set)
    901 
    902     domain = set
    903 
    904     def _set_gap(self):
     962        return self._domain
     963
     964    def _domain_gap(self, domain=None):
    905965        """
    906966        Returns a GAP string representation of the underlying set
    907         that this group acts on.  See also :meth:`set`.
     967        that this group acts on.  See also :meth:`domain`.
    908968
    909969        EXAMPLES::
    910970
    911971            sage: P = PermutationGroup([(1,2),(3,5)])
    912             sage: P._set_gap()
     972            sage: P._domain_gap()
    913973            '[1, 2, 3, 4, 5]'
    914974        """
    915         return repr(list(self.set()))
     975        if domain is None:
     976            return repr(range(1, self.degree()+1))
     977        else:
     978            try:
     979                return repr([self._domain_to_gap[point] for point in domain])
     980            except KeyError:
     981                raise ValueError, "domain must be a subdomain of self.domain()"
    916982
    917983    @cached_method
    918984    def smallest_moved_point(self):
     
    927993            sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
    928994            sage: G.smallest_moved_point()
    929995            1
     996
     997        Note that this function uses the ordering from the domain::
     998
     999            sage: S = SymmetricGroup(['a','b','c'])
     1000            sage: S.smallest_moved_point()
     1001            'a'
    9301002        """
    931         return Integer(self._gap_().SmallestMovedPoint())
     1003        return self._domain_from_gap[Integer(self._gap_().SmallestMovedPoint())]
    9321004
    9331005    @cached_method
    9341006    def orbits(self):
    9351007        """
    936         Returns the orbits of [1,2,...,degree] under the group action.
     1008        Returns the orbits of the elements of the domain under the
     1009        group action.
    9371010       
    9381011        EXAMPLES::
    9391012       
     
    9431016            sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
    9441017            sage: G.orbits()
    9451018            [[1, 2, 3, 4, 10], [5], [6], [7], [8], [9]]
     1019
     1020            sage: G = PermutationGroup([ [('c','d')], [('a','c')],[('b',)]])
     1021            sage: G.orbits()
     1022            [['a', 'c', 'd'], ['b']]
    9461023       
    9471024        The answer is cached::
    9481025       
     
    9531030
    9541031        - Nathan Dunfield
    9551032        """
    956         return self._gap_().Orbits(self._set_gap()).sage()
     1033        return [[self._domain_from_gap[x] for x in orbit] for orbit in
     1034                self._gap_().Orbits(self._domain_gap()).sage()]
    9571035
    9581036    @cached_method
    959     def orbit(self, integer):
     1037    def orbit(self, point):
    9601038        """
    961         Return the orbit of the given integer under the group action.
     1039        Return the orbit of the given point under the group action.
    9621040
    9631041        EXAMPLES::
    9641042
     
    9681046            sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
    9691047            sage: G.orbit(3)                                                 
    9701048            [3, 4, 10, 1, 2]
    971         """
    972         return self._gap_().Orbit(integer).sage()
     1049
     1050            sage: G = PermutationGroup([ [('c','d')], [('a','c')] ])
     1051            sage: G.orbit('a')
     1052            ['a', 'c', 'd']
     1053        """
     1054        point = self._domain_to_gap[point]
     1055        return [self._domain_from_gap[x] for x in self._gap_().Orbit(point).sage()]
    9731056   
    974     def transversals(self, integer):
     1057    def transversals(self, point):
    9751058        """
    9761059        If G is a permutation group acting on the set `X = \{1, 2, ...., n\}`
    9771060        and H is the stabilizer subgroup of <integer>, a right
     
    9881071            sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
    9891072            sage: G.transversals(1)                                   
    9901073            [(), (1,2)(3,4), (1,3,2,10,4), (1,4,2,10,3), (1,10,4,3,2)]
     1074
     1075            sage: G = PermutationGroup([ [('c','d')], [('a','c')] ])
     1076            sage: G.transversals('a')
     1077            [(), ('a','c','d'), ('a','d','c')]           
    9911078        """
    992         trans = []
    993         for i in self.orbit(integer):
    994              trans.append(self(gap.RepresentativeAction(self._gap_(),integer,i)))
    995         return trans
    996 
    997     def stabilizer(self, position):
     1079        G = self._gap_()
     1080        return [self(G.RepresentativeAction(self._domain_to_gap[point], self._domain_to_gap[i]))
     1081                for i in self.orbit(point)]
     1082
     1083    def stabilizer(self, point):
    9981084        """
    9991085        Return the subgroup of ``self`` which stabilize the given position.
    10001086        ``self`` and its stabilizers must have same degree.
     
    10031089
    10041090            sage: G = PermutationGroup([ [(3,4)], [(1,3)] ])
    10051091            sage: G.stabilizer(1)
    1006             Permutation Group with generators [(3,4)]
     1092            Subgroup of (Permutation Group with generators [(3,4), (1,3)]) generated by [(3,4)]
    10071093            sage: G.stabilizer(3)
    1008             Permutation Group with generators [(1,4)]
     1094            Subgroup of (Permutation Group with generators [(3,4), (1,3)]) generated by [(1,4)]
    10091095            sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]])
    10101096            sage: G.stabilizer(10)
    1011             Permutation Group with generators [(1,2)(3,4), (2,3,4)]
     1097            Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4,10)]) generated by [(2,3,4), (1,2)(3,4)]
    10121098            sage: G.stabilizer(1)
    1013             Permutation Group with generators [(2,3)(4,10), (2,10,4)]
     1099            Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4,10)]) generated by [(2,3)(4,10), (2,10,4)]
    10141100            sage: G = PermutationGroup([[(2,3,4)],[(6,7)]])
    10151101            sage: G.stabilizer(1)
    1016             Permutation Group with generators [(6,7), (2,3,4)]
     1102            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7), (2,3,4)]
    10171103            sage: G.stabilizer(2)
    1018             Permutation Group with generators [(6,7)]
     1104            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7)]
    10191105            sage: G.stabilizer(3)
    1020             Permutation Group with generators [(6,7)]
     1106            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7)]
    10211107            sage: G.stabilizer(4)
    1022             Permutation Group with generators [(6,7)]
     1108            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7)]
    10231109            sage: G.stabilizer(5)
    1024             Permutation Group with generators [(6,7), (2,3,4)]
     1110            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7), (2,3,4)]
    10251111            sage: G.stabilizer(6)
    1026             Permutation Group with generators [(2,3,4)]
     1112            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(2,3,4)]
    10271113            sage: G.stabilizer(7)
    1028             Permutation Group with generators [(2,3,4)]
     1114            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(2,3,4)]
    10291115            sage: G.stabilizer(8)
    1030             Permutation Group with generators [(6,7), (2,3,4)]
     1116            Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7), (2,3,4)]
    10311117        """
    1032         return PermutationGroup(gap_group=gap.Stabilizer(self, position))
    1033 
    1034     def strong_generating_system(self, base_of_group = None):
     1118        try:
     1119            position = self._domain_to_gap[point]
     1120        except KeyError:
     1121            return self.subgroup(gens=self.gens())
     1122        return self.subgroup(gap_group=gap.Stabilizer(self, point))
     1123
     1124    def strong_generating_system(self, base_of_group=None):
    10351125        """
    10361126        Return a Strong Generating System of ``self`` according the given
    10371127        base for the right action of ``self`` on itself.
     
    10801170            [[(), (1,2)(3,4), (1,3)(2,4), (1,4)(2,3)], [(), (2,3,4), (2,4,3)], [(), (3,4)], [()]]
    10811171            sage: G = PermutationGroup([[(1,2,3)],[(4,5,7)],[(1,4,6)]])
    10821172            sage: G.strong_generating_system()                         
    1083             [[(), (1,2,3), (1,4,6), (1,3,2), (1,5,7,4,6), (1,6,4), (1,7,5,4,6)], [(), (2,6,3), (2,3,6), (2,5,6,3)(4,7), (2,7,5,6,3), (2,4,5,6,3)], [(), (3,6)(5,7), (3,5,6), (3,7,4,5,6), (3,4,7,5,6)], [(), (4,5)(6,7), (4,7)(5,6), (4,6)(5,7)], [(), (5,6,7), (5,7,6)], [()], [()]]
     1173            [[(), (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)], [()], [()]]
    10841174            sage: G = PermutationGroup([[(1,2,3)],[(2,3,4)],[(3,4,5)]])
    10851175            sage: G.strong_generating_system([5,4,3,2,1])             
    10861176            [[(), (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)], [()], [()]]
     
    10961186        sgs = []
    10971187        stab = self
    10981188        if base_of_group is None:
    1099             base_of_group = self.set()
     1189            base_of_group = self.domain()
    11001190        for j in base_of_group:
    11011191            sgs.append(stab.transversals(j))
    11021192            stab = stab.stabilizer(j)
     
    11401230            \langle (2,3,4), (1,2,3) \rangle
    11411231            sage: A4._latex_()
    11421232            '\\langle (2,3,4), (1,2,3) \\rangle'
     1233
     1234            sage: S = SymmetricGroup(['a','b','c'])
     1235            sage: latex(S)
     1236            \langle (\texttt{a},\texttt{b},\texttt{c}), (\texttt{a},\texttt{b}) \rangle
    11431237        """
    11441238        return '\\langle ' + \
    11451239               ', '.join([x._latex_() for x in self.gens()]) + ' \\rangle'
     
    12181312       
    12191313            sage: G = PermutationGroup([[(1,2,3,4)]])
    12201314            sage: G.center()
    1221             Permutation Group with generators [(1,2,3,4)]
     1315            Subgroup of (Permutation Group with generators [(1,2,3,4)]) generated by [(1,2,3,4)]
    12221316            sage: G = PermutationGroup([[(1,2,3,4)], [(1,2)]])
    12231317            sage: G.center()
    1224             Permutation Group with generators [()]
     1318            Subgroup of (Permutation Group with generators [(1,2), (1,2,3,4)]) generated by [()]
    12251319        """
    1226         return PermutationGroup(gap_group=self._gap_().Center())
     1320        return self.subgroup(gap_group=self._gap_().Center())
     1321
     1322    def socle(self):
     1323        r"""
     1324        Returns the socle of ``self``. The socle of a group $G$ is
     1325        the subgroup generated by all minimal normal subgroups.
     1326       
     1327        EXAMPLES::
     1328       
     1329            sage: G=SymmetricGroup(4)
     1330            sage: G.socle()
     1331            Subgroup of (Symmetric group of order 4! as a permutation group) generated by [(1,2)(3,4), (1,4)(2,3)]
     1332            sage: G.socle().socle()
     1333            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)]
     1334       
     1335        """
     1336        return self.subgroup(gap_group=self._gap_().Socle())
     1337       
     1338    def frattini_subgroup(self):
     1339        r"""
     1340        Returns the Frattini subgroup of ``self``. The Frattini
     1341        subgroup of a group $G$ is the intersection of all
     1342        maximal subgroups of $G$.
     1343       
     1344        EXAMPLES::
     1345       
     1346            sage: G=PermutationGroup([[(1,2,3,4)],[(2,4)]])
     1347            sage: G.frattini_subgroup()
     1348            Subgroup of (Permutation Group with generators [(2,4), (1,2,3,4)]) generated by [(1,3)(2,4)]
     1349            sage: G=SymmetricGroup(4)
     1350            sage: G.frattini_subgroup()
     1351            Subgroup of (Symmetric group of order 4! as a permutation group) generated by [()]
     1352       
     1353        """
     1354        return self.subgroup(gap_group=self._gap_().FrattiniSubgroup())
     1355       
     1356    def fitting_subgroup(self):
     1357        r"""
     1358        Returns the Fitting subgroup of ``self``. The Fitting
     1359        subgroup of a group $G$ is the largest nilpotent normal
     1360        subgroup of $G$.
     1361       
     1362        EXAMPLES::
     1363       
     1364            sage: G=PermutationGroup([[(1,2,3,4)],[(2,4)]])
     1365            sage: G.fitting_subgroup()
     1366            Subgroup of (Permutation Group with generators [(2,4), (1,2,3,4)]) generated by [(2,4), (1,2,3,4), (1,3)]
     1367            sage: G=PermutationGroup([[(1,2,3,4)],[(1,2)]])
     1368            sage: G.fitting_subgroup()
     1369            Subgroup of (Permutation Group with generators [(1,2), (1,2,3,4)]) generated by [(1,2)(3,4), (1,3)(2,4)]
     1370       
     1371        """
     1372        return self.subgroup(gap_group=self._gap_().FittingSubgroup())
     1373       
     1374    def solvable_radical(self):
     1375        r"""
     1376        Returns the solvable radical of ``self``. The solvable
     1377        radical (or just radical) of a group $G$ is the largest
     1378        solvable normal subgroup of $G$.
     1379       
     1380        EXAMPLES::
     1381       
     1382            sage: G=SymmetricGroup(4)
     1383            sage: G.solvable_radical()
     1384            Subgroup of (Symmetric group of order 4! as a permutation group) generated by [(1,2), (1,2,3,4)]
     1385            sage: G=SymmetricGroup(5)
     1386            sage: G.solvable_radical()
     1387            Subgroup of (Symmetric group of order 5! as a permutation group) generated by [()]
     1388           
     1389        """
     1390        return self.subgroup(gap_group=self._gap_().RadicalGroup())
    12271391
    12281392    def intersection(self, other):
    12291393        r"""
     
    13101474            sage: G = DihedralGroup(6)
    13111475            sage: a = PermutationGroupElement("(1,2,3,4)")
    13121476            sage: G.conjugate(a)
    1313             Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]
     1477            Permutation Group with generators [(1,4)(2,6)(3,5), (1,5,6,2,3,4)]
    13141478
    13151479        The element performing the conjugation can be specified in
    13161480        several ways.  ::
     
    13181482            sage: G = DihedralGroup(6)
    13191483            sage: strng = "(1,2,3,4)"
    13201484            sage: G.conjugate(strng)
    1321             Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]
     1485            Permutation Group with generators [(1,4)(2,6)(3,5), (1,5,6,2,3,4)]
    13221486            sage: G = DihedralGroup(6)
    13231487            sage: lst = [2,3,4,1]
    13241488            sage: G.conjugate(lst)
    1325             Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]
     1489            Permutation Group with generators [(1,4)(2,6)(3,5), (1,5,6,2,3,4)]
    13261490            sage: G = DihedralGroup(6)
    13271491            sage: cycles = [(1,2,3,4)]
    13281492            sage: G.conjugate(cycles)
    1329             Permutation Group with generators [(1,5,6,2,3,4), (1,4)(2,6)(3,5)]
     1493            Permutation Group with generators [(1,4)(2,6)(3,5), (1,5,6,2,3,4)]
    13301494
    13311495        Conjugation is a group automorphism, so conjugate groups
    13321496        will be isomorphic. ::
     
    13791543
    13801544        INPUT:
    13811545       
    1382        
    13831546        -  ``self, other`` - permutation groups
    13841547       
    1385        
    1386        
    13871548        OUTPUT:
    13881549       
    1389        
    13901550        -  ``D`` - a direct product of the inputs, returned as
    13911551           a permutation group as well
    13921552       
     
    14001560        -  ``pr2`` - the projection of ``D`` onto ``other`` (giving a
    14011561           splitting 1 - self - D - other - 1)
    14021562       
    1403        
    14041563        EXAMPLES::
    14051564       
    14061565            sage: G = CyclicPermutationGroup(4)
    14071566            sage: D = G.direct_product(G,False)
    14081567            sage: D
    1409             Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
     1568            Permutation Group with generators [(5,6,7,8), (1,2,3,4)]
    14101569            sage: D,iota1,iota2,pr1,pr2 = G.direct_product(G)
    14111570            sage: D; iota1; iota2; pr1; pr2
    1412             Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
     1571            Permutation Group with generators [(5,6,7,8), (1,2,3,4)]
    14131572            Permutation group morphism:
    14141573              From: Cyclic group of order 4 as a permutation group
    1415               To:   Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
     1574              To:   Permutation Group with generators [(5,6,7,8), (1,2,3,4)]
    14161575              Defn: Embedding( Group( [ (1,2,3,4), (5,6,7,8) ] ), 1 )
    14171576            Permutation group morphism:
    14181577              From: Cyclic group of order 4 as a permutation group
    1419               To:   Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
     1578              To:   Permutation Group with generators [(5,6,7,8), (1,2,3,4)]
    14201579              Defn: Embedding( Group( [ (1,2,3,4), (5,6,7,8) ] ), 2 )
    14211580            Permutation group morphism:
    1422               From: Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
     1581              From: Permutation Group with generators [(5,6,7,8), (1,2,3,4)]
    14231582              To:   Cyclic group of order 4 as a permutation group
    14241583              Defn: Projection( Group( [ (1,2,3,4), (5,6,7,8) ] ), 1 )
    14251584            Permutation group morphism:
    1426               From: Permutation Group with generators [(1,2,3,4), (5,6,7,8)]
     1585              From: Permutation Group with generators [(5,6,7,8), (1,2,3,4)]
    14271586              To:   Cyclic group of order 4 as a permutation group
    14281587              Defn: Projection( Group( [ (1,2,3,4), (5,6,7,8) ] ), 2 )
    14291588            sage: g=D([(1,3),(2,4)]); g
     
    14361595            (1,4,3,2)
    14371596            (1,3)(2,4)
    14381597        """
    1439         G = self._gap_().DirectProduct(other._gap_())
     1598        G = self._gap_().DirectProduct(other)
    14401599        D = PermutationGroup(gap_group=G)
    14411600        if not maps:
    14421601            return D
     
    14481607            pr2 = PermutationGroupMorphism_from_gap(D, other, G.Projection(2))
    14491608            return D, iota1, iota2, pr1, pr2
    14501609
    1451     def subgroup(self, gens):
     1610    def subgroup(self, gens=None, gap_group=None, domain=None, category=None, canonicalize=True, check=True):
    14521611        """
    14531612        Wraps the ``PermutationGroup_subgroup`` constructor. The argument
    14541613        ``gens`` is a list of elements of ``self``.
     
    14581617            sage: G = PermutationGroup([(1,2,3),(3,4,5)])
    14591618            sage: g = G((1,2,3))
    14601619            sage: G.subgroup([g])
    1461             Subgroup of Permutation Group with generators [(3,4,5), (1,2,3)] generated by [(1,2,3)]
     1620            Subgroup of (Permutation Group with generators [(3,4,5), (1,2,3)]) generated by [(1,2,3)]
    14621621        """
    1463         return PermutationGroup_subgroup(self, gens)
    1464 
     1622        return PermutationGroup_subgroup(self, gens=gens, gap_group=gap_group, domain=None,
     1623                                         category=category, canonicalize=canonicalize, check=check)
    14651624
    14661625    def quotient(self, N):
    14671626        """
     
    14841643        # This is currently done using the right regular representation
    14851644        # FIXME: GAP certainly knows of a better way!
    14861645        phi = Q.RegularActionHomomorphism()
    1487         return PermutationGroup(gap_group = phi.Image())
     1646        return PermutationGroup(gap_group=phi.Image())
    14881647
    14891648    def quotient_group(self, N):
    14901649        """
     
    19212080            sage: G = SymmetricGroup(5)
    19222081            sage: G.conjugacy_classes_representatives()
    19232082            [(), (1,2), (1,2)(3,4), (1,2,3), (1,2,3)(4,5), (1,2,3,4), (1,2,3,4,5)]
    1924        
     2083
     2084        ::
     2085
     2086            sage: S = SymmetricGroup(['a','b','c'])
     2087            sage: S.conjugacy_classes_representatives()
     2088            [(), ('a','b'), ('a','b','c')]
     2089
    19252090        AUTHORS:
    19262091
    19272092        - David Joyner and William Stein (2006-01-04)
     
    19402105            sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])
    19412106            sage: cl = G.conjugacy_classes_subgroups()
    19422107            sage: cl
    1943             [Permutation Group with generators [()],
    1944              Permutation Group with generators [(1,2)(3,4)],
    1945              Permutation Group with generators [(1,3)(2,4)],
    1946              Permutation Group with generators [(2,4)],
    1947              Permutation Group with generators [(1,4)(2,3), (1,2)(3,4)],
    1948              Permutation Group with generators [(1,3)(2,4), (2,4)],
    1949              Permutation Group with generators [(1,3)(2,4), (1,2,3,4)],
    1950              Permutation Group with generators [(1,3)(2,4), (1,2)(3,4), (1,2,3,4)]]
     2108            [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)]]
    19512109       
    19522110        ::
    19532111       
    19542112            sage: G = SymmetricGroup(3)
    19552113            sage: G.conjugacy_classes_subgroups()
    1956             [Permutation Group with generators [()],
    1957              Permutation Group with generators [(2,3)],
    1958              Permutation Group with generators [(1,2,3)],
    1959              Permutation Group with generators [(1,3,2), (1,2)]]
     2114            [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)]]
    19602115       
    19612116        AUTHORS:
    19622117
    19632118        - David Joyner (2006-10)
    19642119        """
    19652120        cl = self._gap_().ConjugacyClassesSubgroups()
    1966         return [PermutationGroup(gap_group=sub.Representative()) for sub in cl]
     2121        return [self.subgroup(gap_group=sub.Representative()) for sub in cl]
    19672122       
    19682123    def subgroups(self):
    19692124        r"""
     
    19902145            `30030 = 2\cdot 3\cdot 5\cdot 7\cdot 11\cdot 13` takes
    19912146            about twice as long.
    19922147
    1993             For faster results, which still exhibit the structure of the possible subgroups, use :meth:`conjugacy_classes_subgroups`.
     2148            For faster results, which still exhibit the structure of
     2149            the possible subgroups, use
     2150            :meth:`conjugacy_classes_subgroups`.
    19942151
    19952152        EXAMPLES::
    19962153
     
    20012158             Permutation Group with generators [(1,2)],
    20022159             Permutation Group with generators [(1,3)],
    20032160             Permutation Group with generators [(1,2,3)],
    2004              Permutation Group with generators [(1,3,2), (1,2)]]
     2161             Permutation Group with generators [(1,2), (1,3,2)]]
    20052162
    20062163            sage: G = CyclicPermutationGroup(14)
    20072164            sage: G.subgroups()
     
    21602317            sage: A.cosets(S)
    21612318            Traceback (most recent call last):
    21622319            ...
    2163             ValueError: Subgroup of SymmetricGroup(3) generated by [(1,2)] is not a subgroup of AlternatingGroup(3)
     2320            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
    21642321
    21652322        AUTHOR:
    21662323
     
    22012358            sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])
    22022359            sage: g = G([(1,3)])
    22032360            sage: G.normalizer(g)
    2204             Permutation Group with generators [(2,4), (1,3)]
     2361            Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(2,4), (1,3)]
    22052362            sage: g = G([(1,2,3,4)])
    22062363            sage: G.normalizer(g)
    2207             Permutation Group with generators [(2,4), (1,2,3,4), (1,3)(2,4)]
     2364            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)]
    22082365            sage: H = G.subgroup([G([(1,2,3,4)])])
    22092366            sage: G.normalizer(H)
    2210             Permutation Group with generators [(2,4), (1,2,3,4), (1,3)(2,4)]
     2367            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)]
    22112368        """
    2212         N = self._gap_().Normalizer(g)
    2213         return PermutationGroup(N.GeneratorsOfGroup())
     2369        return self.subgroup(gap_group=self._gap_().Normalizer(g))
    22142370
    22152371    def centralizer(self, g):
    22162372        """
     
    22212377            sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]])
    22222378            sage: g = G([(1,3)])
    22232379            sage: G.centralizer(g)
    2224             Permutation Group with generators [(2,4), (1,3)]
     2380            Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(2,4), (1,3)]
    22252381            sage: g = G([(1,2,3,4)])
    22262382            sage: G.centralizer(g)
    2227             Permutation Group with generators [(1,2,3,4)]
     2383            Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(1,2,3,4)]
    22282384            sage: H = G.subgroup([G([(1,2,3,4)])])
    22292385            sage: G.centralizer(H)
    2230             Permutation Group with generators [(1,2,3,4)]
     2386            Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(1,2,3,4)]
    22312387        """
    2232         N = self._gap_().Centralizer(g)
    2233         return PermutationGroup(N.GeneratorsOfGroup())
     2388        return self.subgroup(gap_group=self._gap_().Centralizer(g))
    22342389
    22352390    def isomorphism_type_info_simple_group(self):
    22362391        """
     
    24442599        """
    24452600        if not(self.is_subgroup(other)):
    24462601            raise TypeError("%s must be a subgroup of %s"%(self, other))
    2447         return other._gap_().IsNormal(self._gap_()).bool()
     2602        return other._gap_().IsNormal(self).bool()
    24482603   
    24492604    def is_perfect(self):
    24502605        """
     
    25302685            sage: G.is_subgroup(H)
    25312686            True
    25322687        """
    2533         G = other
    2534         gens = self.gens()
    2535         for i in range(len(gens)):
    2536             x = gens[i]
    2537             if not (x in G):
    2538                 return False
    2539         return True
     2688        return all((x in other) for x in self.gens())
    25402689       
    25412690    def is_supersolvable(self):
    25422691        """
     
    25512700        """
    25522701        return self._gap_().IsSupersolvableGroup().bool()
    25532702
    2554     def is_transitive(self):
     2703    def non_fixed_points(self):
     2704        r"""
     2705        Returns the list of points not fixed by ``self``, i.e., the subset
     2706        of ``self.domain()`` moved by some element of ``self``.
     2707
     2708        EXAMPLES::
     2709       
     2710            sage: G = PermutationGroup([[(3,4,5)],[(7,10)]])
     2711            sage: G.non_fixed_points()
     2712            [3, 4, 5, 7, 10]
     2713            sage: G = PermutationGroup([[(2,3,6)],[(9,)]]) # note: 9 is fixed
     2714            sage: G.non_fixed_points()
     2715            [2, 3, 6]
    25552716        """
    2556         Return ``True`` if ``self`` is a transitive group, i.e., if the action
    2557         of self on [1..n] is transitive.
     2717        pnts = set()
     2718        for gens in self.gens():
     2719            for cycles in gens.cycle_tuples():
     2720                for thispnt in cycles:
     2721                    if thispnt not in pnts:
     2722                        pnts.add(thispnt)
     2723        return sorted(pnts)
    25582724       
     2725    def fixed_points(self):
     2726        r"""
     2727        Returns the list of points fixed by ``self``, i.e., the subset
     2728        of ``.domain()`` not moved by any element of ``self``.
     2729       
     2730        EXAMPLES::
     2731       
     2732            sage: G=PermutationGroup([(1,2,3)])
     2733            sage: G.fixed_points()
     2734            []
     2735            sage: G=PermutationGroup([(1,2,3),(5,6)])
     2736            sage: G.fixed_points()
     2737            [4]
     2738            sage: G=PermutationGroup([[(1,4,7)],[(4,3),(6,7)]])
     2739            sage: G.fixed_points()
     2740            [2, 5]
     2741        """
     2742        non_fixed_points = self.non_fixed_points()
     2743        return [i for i in self.domain() if i not in non_fixed_points]
     2744
     2745    def is_transitive(self, domain=None):
     2746        """
     2747        Returns ``True`` if ``self`` acts transitively on ``domain``.
     2748        A group $G$ acts transitively on set $S$ if for all $x,y\in S$
     2749        there is some $g\in G$ such that $x^g=y$.       
     2750
    25592751        EXAMPLES::
    25602752       
    25612753            sage: G = SymmetricGroup(5)
     
    25652757            sage: G.is_transitive()
    25662758            False
    25672759
     2760        ::
     2761       
     2762            sage: G = PermutationGroup([[(1,2,3,4,5)],[(1,2)]]) #S_5 on [1..5]
     2763            sage: G.is_transitive([1,4,5])
     2764            True
     2765            sage: G.is_transitive([2..6])
     2766            False
     2767            sage: G.is_transitive(G.non_fixed_points())
     2768            True
     2769            sage: H = PermutationGroup([[(1,2,3)],[(4,5,6)]])
     2770            sage: H.is_transitive(H.non_fixed_points())
     2771            False
     2772
    25682773        Note that this differs from the definition in GAP, where
    25692774        ``IsTransitive`` returns whether the group is transitive on the
    25702775        set of points moved by the group.
     
    25772782            sage: gap(G).IsTransitive()
    25782783            true
    25792784        """
    2580         return self._gap_().IsTransitive(self._set_gap()).bool()
    2581    
     2785        #If the domain is not a subset of self.domain(), then the
     2786        #action isn't transitive.
     2787        try:
     2788            domain = self._domain_gap(domain)
     2789        except ValueError:
     2790            return False
     2791
     2792        return self._gap_().IsTransitive(domain).bool()
     2793       
     2794
     2795    def is_primitive(self, domain=None):
     2796        r"""
     2797        Returns ``True`` if ``self`` acts primitively on ``domain``.
     2798        A group $G$ acts primitively on a set $S$ if
     2799       
     2800        1. $G$ acts transitively on $S$ and
     2801       
     2802        2. the action induces no non-trivial block system on $S$.
     2803       
     2804        INPUT:
     2805
     2806        - ``domain`` (optional)
     2807       
     2808        EXAMPLES:
     2809           
     2810        By default, test for primitivity of ``self`` on its domain.
     2811       
     2812            sage: G = PermutationGroup([[(1,2,3,4)],[(1,2)]])
     2813            sage: G.is_primitive()
     2814            True
     2815            sage: G = PermutationGroup([[(1,2,3,4)],[(2,4)]])
     2816            sage: G.is_primitive()
     2817            False
     2818           
     2819        You can specify a domain on which to test primitivity::
     2820       
     2821            sage: G = PermutationGroup([[(1,2,3,4)],[(2,4)]])
     2822            sage: G.is_primitive([1..4])
     2823            False
     2824            sage: G.is_primitive([1,2,3])
     2825            True
     2826            sage: G = PermutationGroup([[(3,4,5,6)],[(3,4)]]) #S_4 on [3..6]
     2827            sage: G.is_primitive(G.non_fixed_points())
     2828            True
     2829       
     2830        """
     2831        #If the domain is not a subset of self.domain(), then the
     2832        #action isn't primitive.
     2833        try:
     2834            domain = self._domain_gap(domain)
     2835        except ValueError:
     2836            return False
     2837       
     2838        return self._gap_().IsPrimitive(domain).bool()
     2839
     2840    def is_semi_regular(self, domain=None):
     2841        r"""
     2842        Returns ``True`` if ``self`` acts semi-regularly on ``domain``.
     2843        A group $G$ acts semi-regularly on a set $S$ if the point
     2844        stabilizers of $S$ in $G$ are trivial.
     2845       
     2846        ``domain`` is optional and may take several forms. See examples.
     2847       
     2848        EXAMPLES::
     2849           
     2850            sage: G = PermutationGroup([[(1,2,3,4)]])
     2851            sage: G.is_semi_regular()
     2852            True
     2853            sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]])
     2854            sage: G.is_semi_regular()
     2855            False
     2856           
     2857        You can pass in a domain to test semi-regularity::
     2858       
     2859            sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]])
     2860            sage: G.is_semi_regular([1..4])
     2861            True
     2862            sage: G.is_semi_regular(G.non_fixed_points())
     2863            False
     2864           
     2865        """
     2866        try:
     2867            domain = self._domain_gap(domain)
     2868        except ValueError:
     2869            return False
     2870        return self._gap_().IsSemiRegular(domain).bool()
     2871
     2872    def is_regular(self, domain=None):
     2873        r"""
     2874        Returns ``True`` if ``self`` acts regularly on ``domain``.
     2875        A group $G$ acts regularly on a set $S$ if
     2876
     2877        1. $G$ acts transitively on $S$ and
     2878        2. $G$ acts semi-regularly on $S$.
     2879               
     2880        EXAMPLES::
     2881           
     2882            sage: G = PermutationGroup([[(1,2,3,4)]])
     2883            sage: G.is_regular()
     2884            True
     2885            sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]])
     2886            sage: G.is_regular()
     2887            False
     2888           
     2889        You can pass in a domain on which to test regularity::
     2890       
     2891            sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]])
     2892            sage: G.is_regular([1..4])
     2893            True
     2894            sage: G.is_regular(G.non_fixed_points())
     2895            False
     2896
     2897        """
     2898        try:
     2899            domain = self._domain_gap(domain)
     2900        except ValueError:
     2901            return False
     2902        return self._gap_().IsRegular(domain).bool()
     2903
     2904
    25822905    def normalizes(self, other):
    25832906        r"""
    25842907        Returns ``True`` if the group ``other`` is normalized by ``self``.
     
    26042927        In the last example, `G` and `H` are disjoint, so each normalizes the
    26052928        other.
    26062929        """
    2607         return self._gap_().IsNormal(other._gap_()).bool()
     2930        return self._gap_().IsNormal(other).bool()
    26082931
    26092932    ############## Series ######################
    26102933   
     
    26272950            sage: G = PermutationGroup([[(1,2,3),(4,5)], [(1,2)]])
    26282951            sage: CS = G.composition_series()
    26292952            sage: CS[3]
    2630             Permutation Group with generators [()]
     2953            Subgroup of (Permutation Group with generators [(1,2), (1,2,3)(4,5)]) generated by [()]
    26312954        """
    26322955        current_randstate().set_seed_gap()
    26332956        CS = self._gap_().CompositionSeries()
    2634         return [PermutationGroup(gap_group=group) for group in CS]
     2957        return [self.subgroup(gap_group=group) for group in CS]
    26352958
    26362959    def derived_series(self):
    26372960        """
     
    26522975        """
    26532976        current_randstate().set_seed_gap()
    26542977        DS = self._gap_().DerivedSeries()
    2655         return [PermutationGroup(gap_group=group) for group in DS]   
     2978        return [self.subgroup(gap_group=group) for group in DS]   
    26562979
    26572980    def lower_central_series(self):
    26582981        """
     
    26732996        """
    26742997        current_randstate().set_seed_gap()
    26752998        LCS = self._gap_().LowerCentralSeriesOfGroup()
    2676         return [PermutationGroup(gap_group=group) for group in LCS]   
     2999        return [self.subgroup(gap_group=group) for group in LCS]   
    26773000
    26783001    def molien_series(self):
    26793002        r"""
     
    27363059            True
    27373060        """
    27383061        NS = self._gap_().NormalSubgroups()
    2739         return [PermutationGroup(gap_group=group) for group in NS]
     3062        return [self.subgroup(gap_group=group) for group in NS]
    27403063
    27413064    def poincare_series(self, p=2, n=10):
    27423065        """
     
    27883111       
    27893112            sage: G = PermutationGroup(['(1,2,3)', '(2,3)'])
    27903113            sage: G.sylow_subgroup(2)
    2791             Permutation Group with generators [(2,3)]
     3114            Subgroup of (Permutation Group with generators [(2,3), (1,2,3)]) generated by [(2,3)]
    27923115            sage: G.sylow_subgroup(5)
    2793             Permutation Group with generators [()]
     3116            Subgroup of (Permutation Group with generators [(2,3), (1,2,3)]) generated by [()]
    27943117        """
    2795         return PermutationGroup(gap_group=self._gap_().SylowSubgroup(p))
     3118        return self.subgroup(gap_group=self._gap_().SylowSubgroup(p))
    27963119       
    27973120    def upper_central_series(self):
    27983121        """
     
    28063129
    28073130            sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]])
    28083131            sage: G.upper_central_series()
    2809             [Permutation Group with generators [()]]
     3132            [Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]]
    28103133        """
    28113134        current_randstate().set_seed_gap()
    28123135        UCS = self._gap_().UpperCentralSeriesOfGroup()
    2813         return [PermutationGroup(gap_group=group) for group in UCS]
     3136        return [self.subgroup(gap_group=group) for group in UCS]
    28143137
    28153138class PermutationGroup_subgroup(PermutationGroup_generic):
    28163139    """
     
    28223145        sage: G = CyclicPermutationGroup(4)
    28233146        sage: gens = G.gens()
    28243147        sage: H = DihedralGroup(4)
    2825         sage: PermutationGroup_subgroup(H,list(gens))
    2826         Subgroup of Dihedral group of order 8 as a permutation group generated by [(1,2,3,4)]
    2827         sage: K=PermutationGroup_subgroup(H,list(gens))
     3148        sage: H.subgroup(gens)
     3149        Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]
     3150        sage: K = H.subgroup(gens)
    28283151        sage: K.list()
    28293152        [(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)]
    28303153        sage: K.ambient_group()
     
    28323155        sage: K.gens()
    28333156        [(1,2,3,4)]
    28343157    """
    2835     def __init__(self, ambient, gens, from_group = False, check=True, canonicalize=True):
     3158    def __init__(self, ambient, gens=None, gap_group=None, domain=None,
     3159                 category=None, canonicalize=True, check=True):
    28363160        r"""
    28373161        Initialization method for the
    28383162        ``PermutationGroup_subgroup`` class.
     
    28623186            sage: H = CyclicPermutationGroup(4)
    28633187            sage: gens = H.gens(); gens
    28643188            [(1,2,3,4)]
    2865             sage: S = PermutationGroup_subgroup(G,gens)
     3189            sage: S = G.subgroup(gens)
    28663190            sage: S
    2867             Subgroup of Dihedral group of order 8 as a permutation group generated by [(1,2,3,4)]
     3191            Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]
    28683192            sage: S.list()
    28693193            [(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)]
    28703194            sage: S.ambient_group()
     
    28833207        """
    28843208        if not isinstance(ambient, PermutationGroup_generic):
    28853209            raise TypeError, "ambient (=%s) must be perm group."%ambient
    2886         if not isinstance(gens, list):
    2887             raise TypeError, "gens (=%s) must be a list"%gens
    2888            
    2889         self.__ambient_group = ambient
    2890         self._gens = gens
    2891         cmd = 'Group(%s)'%gens
    2892         cmd = cmd.replace("'","")  # get rid of quotes
    2893         self._gap_string = cmd
    2894    
    2895         G = ambient
     3210        if domain is None:
     3211            domain = ambient.domain()
     3212        if category is None:
     3213            category = ambient.category()
     3214        PermutationGroup_generic.__init__(self, gens=gens, gap_group=gap_group, domain=domain,
     3215                                          category=category, canonicalize=canonicalize)
     3216
     3217        self._ambient_group = ambient
    28963218        if check:
    2897             for g in gens:
    2898                 if g not in G:
     3219            for g in self.gens():
     3220                if g not in ambient:
    28993221                    raise TypeError, "each generator must be in the ambient group"
    2900         self.__ambient_group = G
    2901        
    2902         PermutationGroup_generic.__init__(self, gens, canonicalize=canonicalize)
    29033222
    29043223    def __cmp__(self, other):
    29053224        r"""
    29063225        Compare ``self`` and ``other``.
    29073226
    2908         First, ``self`` and ``other`` are compared as permutation groups, see :method:`sage.groups.perm_gps.permgroup.PermutationGroup_generic.__cmp__`.
    2909         Second, if both are equal, the ambient groups are compared, where (if necessary)
    2910         ``other`` is considered a subgroup of itself.
     3227        First, ``self`` and ``other`` are compared as permutation
     3228        groups, see :method:`PermutationGroup_generic.__cmp__`.
     3229        Second, if both are equal, the ambient groups are compared,
     3230        where (if necessary) ``other`` is considered a subgroup of
     3231        itself.
    29113232       
    29123233        EXAMPLES::
    29133234       
     
    29413262            sage: G
    29423263            Symmetric group of order 6! as a permutation group
    29433264            sage: G3
    2944             Subgroup of SymmetricGroup(6) generated by [(1,2), (1,2,3,4,5,6)]
     3265            Subgroup of (Symmetric group of order 6! as a permutation group) generated by [(1,2), (1,2,3,4,5,6)]
    29453266            sage: G is G3
    29463267            False
    29473268            sage: G == G3 # as permutation groups
     
    29863307            sage: gens = H.gens()
    29873308            sage: S = PermutationGroup_subgroup(G, list(gens))
    29883309            sage: S
    2989             Subgroup of Dihedral group of order 8 as a permutation group generated by [(1,2,3,4)]
     3310            Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]
    29903311            sage: S._repr_()
    2991             'Subgroup of Dihedral group of order 8 as a permutation group generated by [(1,2,3,4)]'
     3312            'Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]'
    29923313        """
    2993         s = "Subgroup of %s generated by %s"%(self.ambient_group(), self.gens())
     3314        s = "Subgroup of (%s) generated by %s"%(self.ambient_group(), self.gens())
    29943315        return s
    29953316
    29963317    def _latex_(self):
     
    30073328            sage: gens = H.gens()
    30083329            sage: S = PermutationGroup_subgroup(G, list(gens))
    30093330            sage: latex(S)
    3010             Subgroup of Dihedral group of order 8 as a permutation group generated by [(1,2,3,4)]
     3331            Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]
    30113332            sage: S._latex_()
    3012             'Subgroup of Dihedral group of order 8 as a permutation group generated by [(1,2,3,4)]'
     3333            'Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]'
    30133334        """
    30143335        return self._repr_()
    30153336
     
    30323353            sage: S.ambient_group() == G
    30333354            True
    30343355        """
    3035         return self.__ambient_group
    3036 
    3037     def gens(self):
     3356        return self._ambient_group
     3357
     3358
     3359    def is_normal(self, other=None):
    30383360        """
    3039         Return the generators for this subgroup.
     3361        Return ``True`` if this group is a normal subgroup of
     3362        ``other``.  If ``other`` is not specified, then it is assumed
     3363        to be the ambient group.
    30403364       
    3041         EXAMPLES:
    3042 
    3043         An example involving the dihedral group on four elements,
    3044         `D_8`::
     3365        EXAMPLES::
    30453366       
    3046             sage: G = DihedralGroup(4)
    3047             sage: H = CyclicPermutationGroup(4)
    3048             sage: gens = H.gens()
    3049             sage: S = PermutationGroup_subgroup(G, list(gens))
    3050             sage: S.gens()
    3051             [(1,2,3,4)]
    3052             sage: S.gens() == list(H.gens())
    3053             True
     3367           sage: S = SymmetricGroup(['a','b','c'])
     3368           sage: H = S.subgroup([('a', 'b', 'c')]); H
     3369           Subgroup of (Symmetric group of order 3! as a permutation group) generated by [('a','b','c')]
     3370           sage: H.is_normal()
     3371           True
     3372
    30543373        """
    3055         return self._gens
    3056    
     3374        if other is None:
     3375            other = self.ambient_group()
     3376        return PermutationGroup_generic.is_normal(self, other)
     3377
  • sage/groups/perm_gps/permgroup_element.pxd

    diff --git a/sage/groups/perm_gps/permgroup_element.pxd b/sage/groups/perm_gps/permgroup_element.pxd
    a b  
    99    cdef Element _gap_element
    1010    cdef __tuple
    1111    cdef PermutationGroupElement _new_c(self)
     12    cpdef _gap_list(self)
    1213    cpdef list(self)
    1314    cdef public __custom_name
  • sage/groups/perm_gps/permgroup_element.pyx

    diff --git a/sage/groups/perm_gps/permgroup_element.pyx b/sage/groups/perm_gps/permgroup_element.pyx
    a b  
    6565from sage.rings.all      import ZZ, Integer, is_MPolynomial, is_Polynomial
    6666from sage.matrix.all     import MatrixSpace
    6767from sage.interfaces.all import gap, is_GapElement, is_ExpectElement
    68 
     68from sage.sets.all import FiniteEnumeratedSet
    6969import sage.structure.coerce as coerce
    7070
    7171import operator
    7272
    73 from sage.rings.integer import Integer
    74 
    7573from sage.rings.fast_arith cimport arith_llong
    7674cdef arith_llong arith = arith_llong()
    7775cdef extern from *:
     
    8078#import permgroup_named
    8179
    8280def make_permgroup_element(G, x):
    83     G._deg = len(x)
     81    """
     82    Returns a PermutationGroupElement given the permutation group
     83    ``G`` and the permutation ``x`` in list notation.
     84
     85    This is function is used when unpickling old (pre-domain) versions
     86    of permutation groups and their elements.  This now does a bit of
     87    processing and calls :func:`make_permgroup_element_v2` which is
     88    used in unpickling the current PermutationGroupElements.
     89
     90    EXAMPLES::
     91
     92        sage: from sage.groups.perm_gps.permgroup_element import make_permgroup_element
     93        sage: S = SymmetricGroup(3)
     94        sage: make_permgroup_element(S, [1,3,2])
     95        (2,3)
     96    """
     97    domain = FiniteEnumeratedSet(range(1, len(x)+1))
     98    return make_permgroup_element_v2(G, x, domain)
     99
     100def make_permgroup_element_v2(G, x, domain):
     101    """
     102    Returns a PermutationGroupElement given the permutation group
     103    ``G``, the permutation ``x`` in list notation, and the domain
     104    ``domain`` of the permutation group.
     105
     106    This is function is used when unpickling permutation groups and
     107    their elements. 
     108   
     109    EXAMPLES::
     110
     111        sage: from sage.groups.perm_gps.permgroup_element import make_permgroup_element_v2
     112        sage: S = SymmetricGroup(3)
     113        sage: make_permgroup_element_v2(S, [1,3,2], S.domain())
     114        (2,3)
     115    """
     116    # Note that it has to be in-sync with the __init__ method of
     117    # PermutationGroup_generic since the elements have to be created
     118    # before the PermutationGroup_generic is initialized.  The
     119    # constructor for PermutationGroupElement requires that
     120    # G._domain_to_gap be set.
     121    G._domain = domain
     122    G._deg = len(domain)
     123    G._domain_to_gap = dict([(key, i+1) for i, key in enumerate(domain)])
     124    G._domain_from_gap = dict([(i+1, key) for i, key in enumerate(domain)])
    84125    return G(x, check=False)
    85126
     127
    86128def is_PermutationGroupElement(x):
     129    """
     130    Returns True if ``x`` is a PermutationGroupElement.
     131
     132    EXAMPLES::
     133
     134        sage: p = PermutationGroupElement([(1,2),(3,4,5)])
     135        sage: from sage.groups.perm_gps.permgroup_element import is_PermutationGroupElement
     136        sage: is_PermutationGroupElement(p)
     137        True   
     138    """
    87139    return isinstance(x, PermutationGroupElement)
    88140
    89 
    90 def gap_format(x):
    91     """
    92     Put a permutation in Gap format, as a string.
    93     """
    94     if isinstance(x, list) and not isinstance(x[0], tuple):
    95         return gap.eval('PermList(%s)' % x)
    96     x = str(x).replace(' ','').replace('\n','')
    97     return x.replace('),(',')(').replace('[','').replace(']','').replace(',)',')')
    98 
    99141def string_to_tuples(g):
    100142    """
    101143    EXAMPLES::
     
    120162    g = '[' + g + ']'
    121163    return sage_eval(g, preparse=False)
    122164
     165def standardize_generator(g, convert_dict=None):
     166    """
     167    Standardizes the input for permutation group elements to a list of
     168    tuples.  This was factored out of the
     169    PermutationGroupElement.__init__ since
     170    PermutationGroup_generic.__init__ needs to do the same computation
     171    in order to compute the domain of a group when it's not explicitly
     172    specified.
     173
     174    INPUT:
     175
     176    - ``g`` - a list, tuple, string, GapElement,
     177      PermuationGroupElement
     178
     179    - ``convert_dict`` - (optional) a dictionary used to convert the
     180      points to a number compatible with GAP.
     181
     182    OUTPUT:
     183
     184    The permutation in as a list of cycles.
     185
     186    EXAMPLES::
     187
     188        sage: from sage.groups.perm_gps.permgroup_element import standardize_generator
     189        sage: standardize_generator('(1,2)')
     190        [(1, 2)]
     191
     192        sage: p = PermutationGroupElement([(1,2)])
     193        sage: standardize_generator(p)
     194        [(1, 2)]
     195        sage: standardize_generator(p._gap_())
     196        [(1, 2)]
     197        sage: standardize_generator((1,2))
     198        [(1, 2)]
     199        sage: standardize_generator([(1,2)])
     200        [(1, 2)]
     201
     202    ::
     203
     204        sage: d = {'a': 1, 'b': 2}
     205        sage: p = SymmetricGroup(['a', 'b']).gen(0); p
     206        ('a','b')
     207        sage: standardize_generator(p, convert_dict=d)
     208        [(1, 2)]
     209        sage: standardize_generator(p._gap_(), convert_dict=d)
     210        [(1, 2)]
     211        sage: standardize_generator(('a','b'), convert_dict=d)
     212        [(1, 2)]
     213        sage: standardize_generator([('a','b')], convert_dict=d)
     214        [(1, 2)]
     215    """
     216    from sage.interfaces.gap import GapElement
     217    from sage.combinat.permutation import Permutation
     218    from sage.libs.pari.gen import gen
     219
     220    if isinstance(g, gen):
     221        g = list(g)
     222       
     223    needs_conversion = True
     224    if isinstance(g, GapElement):
     225        g = str(g)
     226        needs_conversion = False
     227    if isinstance(g, PermutationGroupElement):
     228        g = g.cycle_tuples()
     229    if isinstance(g, str):
     230        g = string_to_tuples(g)
     231    if isinstance(g, tuple) and (len(g) == 0 or not isinstance(g[0], tuple)):
     232        g = [g]
     233
     234    #Get the permutation in list notation
     235    if PyList_CheckExact(g) and (len(g) == 0 or not PY_TYPE_CHECK(g[0], tuple)):
     236        if convert_dict is not None and needs_conversion:
     237            g = [convert_dict[x] for x in g]
     238
     239
     240        #FIXME: Currently, we need to verify that g defines an actual
     241        #permutation since the constructor Permutation does not
     242        #perform this check.  When it does, we should remove this code.
     243        #See #8392
     244        if set(g) != set(range(1, len(g)+1)):
     245            raise ValueError, "Invalid permutation vector: %s"%g
     246        return Permutation(g).cycle_tuples()
     247    else:
     248        if convert_dict is not None and needs_conversion:
     249            g = [tuple([convert_dict[x] for x in cycle])for cycle in g]
     250
     251    return g
    123252
    124253cdef class PermutationGroupElement(MultiplicativeGroupElement):
    125254    """
     
    292421            sage: PermutationGroupElement([()])
    293422            ()
    294423        """
    295         from sage.interfaces.gap import GapElement
    296424        from sage.groups.perm_gps.permgroup_named import SymmetricGroup
    297425        from sage.groups.perm_gps.permgroup import PermutationGroup_generic
     426        from sage.combinat.permutation import from_cycles
    298427
    299         #Convert GAP elements to strings
    300         if isinstance(g, GapElement):
    301             g = str(g)
    302         elif isinstance(g, PermutationGroupElement):
    303             g = g.list()
    304            
    305         #Convert all the string to tuples
    306         if isinstance(g, str):
    307             g = string_to_tuples(g)
     428        convert_dict = parent._domain_to_gap if parent is not None else None
     429        try:
     430            v = standardize_generator(g, convert_dict)
     431        except KeyError:
     432            raise ValueError, "Invalid permutation vector: %s" % g
    308433
    309         if isinstance(g, tuple) and (len(g) == 0 or not isinstance(g[0], tuple)):
    310             g = [g]
    311 
    312         #Get the permutation in list notation
    313         if PyList_CheckExact(g) and (len(g) == 0 or not PY_TYPE_CHECK(g[0], tuple)):
    314             v = g if len(g) != 0 else [1]
    315             self.__gap = 'PermList(%s)'%v
    316         else:
    317             from sage.combinat.permutation import Permutation
    318             v = Permutation(g)._list
    319             self.__gap = str(g)[1:-1].replace('), (',')(').replace(',)',')').strip(',')
     434       
     435        degree = max([1] + [max(cycle+(1,)) for cycle in v])
     436        v = from_cycles(degree, v)
     437       
     438        self.__gap = 'PermList(%s)'%v
    320439
    321440        if parent is None:
    322             parent = SymmetricGroup(max(len(v),1))
    323    
     441            parent = SymmetricGroup(len(v))
     442
    324443        if check and parent.__class__ != SymmetricGroup:
    325444            if not (parent is None or isinstance(parent, PermutationGroup_generic)):
    326445                raise TypeError, 'parent must be a permutation group'
    327446            if parent is not None:
    328447                P = parent._gap_()
    329448                if not P.parent()(self.__gap) in P:
    330                     raise TypeError, 'permutation %s not in %s'%(self.__gap, parent)
     449                    raise TypeError, 'permutation %s not in %s'%(g, parent)
    331450
    332451        Element.__init__(self, parent)
    333452
     
    361480            sage_free(self.perm)
    362481       
    363482    def __reduce__(self):
    364         return make_permgroup_element, (self._parent, self.list())
     483        """
     484        Returns a function and its arguments needed to create this
     485        permutation group element.  This is used in pickling.
     486       
     487        EXAMPLES::
     488
     489           sage: g = PermutationGroupElement([(1,2,3),(4,5)]); g
     490           (1,2,3)(4,5)
     491           sage: func, args = g.__reduce__()
     492           sage: func(*args)
     493           (1,2,3)(4,5)
     494        """
     495        return make_permgroup_element_v2, (self._parent, self.list(), self._parent.domain())
    365496       
    366497    cdef PermutationGroupElement _new_c(self):
    367498        cdef PermutationGroupElement other = PY_NEW_SAME_TYPE(self)
     
    375506            other.perm = <int *>sage_malloc(sizeof(int) * other.n)
    376507        return other
    377508
    378     def _gap_(self, G=None):
    379         if self._gap_element is None or \
    380             (G is not None and self._gap_element._parent is not G):
    381             if G is None:
    382                 import sage.interfaces.gap
    383                 G = sage.interfaces.gap.gap
    384             self._gap_element = G("PermList(%s)" % self.list())
     509    def _gap_(self, gap=None):
     510        """
     511        Returns
     512
     513        EXAMPLES::
     514
     515            sage: g = PermutationGroupElement([(1,2,3),(4,5)]); g
     516            (1,2,3)(4,5)
     517            sage: a = g._gap_(); a
     518            (1,2,3)(4,5)
     519            sage: g._gap_() is g._gap_()
     520            True
     521           
     522        Note that only one GapElement is cached:
     523
     524            sage: gap2 = Gap()
     525            sage: b = g._gap_(gap2)
     526            sage: c = g._gap_()
     527            sage: a is c
     528            False
     529        """
     530        if (self._gap_element is None or
     531            (gap is not None and self._gap_element._parent is not gap)):
     532            if gap is None:
     533                from sage.interfaces.gap import gap
     534            self._gap_element = gap(self._gap_init_())
    385535        return self._gap_element
    386536
     537    def _gap_init_(self):
     538        """
     539        Returns a GAP string representation for this
     540        PermutationGroupElement.
     541
     542        EXAMPLES::
     543
     544            sage: g = PermutationGroupElement([(1,2,3),(4,5)])
     545            sage: g._gap_init_()
     546            'PermList([2, 3, 1, 5, 4])'
     547        """
     548        return 'PermList(%s)'%self._gap_list()
     549
    387550    def _repr_(self):
    388551        """
    389552        Return string representation of this permutation.
    390553       
    391         EXAMPLES: We create the permutation `(1,2,3)(4,5)` and
    392         print it.
    393        
    394         ::
    395        
     554        EXAMPLES:
     555
     556        We create the permutation `(1,2,3)(4,5)` and
     557        print it. ::
     558
    396559            sage: g = PermutationGroupElement([(1,2,3),(4,5)])
    397560            sage: g._repr_()
    398561            '(1,2,3)(4,5)'
     
    407570            sage: g
    408571            (1,2,3)(4,5)
    409572        """
    410         cycles = self.cycle_tuples()
    411         if len(cycles) == 0:
    412             return '()'
    413         return ''.join([str(c) for c in cycles]).replace(', ',',')
     573        return self.cycle_string()
    414574
    415575    def _latex_(self):
    416         return str(self)
     576        """
     577        Returns a latex representation of this permutation.
     578
     579        EXAMPLES::
     580
     581            sage: g = PermutationGroupElement([(1,2,3),(4,5)])
     582            sage: latex(g)
     583            (1,2,3)(4,5)
     584           
     585            sage: S = SymmetricGroup(['a', 'b'])
     586            sage: latex(S.gens())
     587            \left[(\texttt{a},\texttt{b})\right]
     588        """
     589        from sage.misc.latex import latex
     590        return "".join(["(" + ",".join([latex(x) for x in cycle])+")" for cycle in self.cycle_tuples()])
    417591
    418592    def __getitem__(self, i):
    419593        """
     
    519693            sage: g(x)
    520694            Traceback (most recent call last):
    521695            ...
    522             ValueError: Must be an integer, list, tuple or string.
     696            ValueError: Must be in the domain or a list, tuple or string.
    523697            sage: g(3/2)
    524698            Traceback (most recent call last):
    525699            ...
    526             ValueError: Must be an integer, list, tuple or string.
     700            ValueError: Must be in the domain or a list, tuple or string.
    527701        """
     702        to_gap = self._parent._domain_to_gap
     703        from_gap = self._parent._domain_from_gap
    528704        cdef int j
    529         if isinstance(i,(list,tuple,str)):
     705
     706        try:
     707            i = to_gap[i]
     708        except (KeyError, TypeError):
     709            # We currently have to include this to maintain the
     710            # current behavior where if you pass in an integer which
     711            # is not in the domain of the permutation group, then that
     712            # integer itself will be returned.         
     713            if isinstance(i, (long, int, Integer)):
     714                return i
     715
     716           
     717            if not isinstance(i,(list,tuple,str)):
     718                raise ValueError, "Must be in the domain or a list, tuple or string."
     719           
    530720            permuted = [i[self.perm[j]] for j from 0 <= j < self.n]
    531721            if PY_TYPE_CHECK(i, tuple):
    532722                permuted = tuple(permuted)
     
    535725            permuted += i[self.n:]
    536726            return permuted
    537727        else:
    538             if not isinstance(i, (int, Integer)):
    539                 raise ValueError("Must be an integer, list, tuple or string.")
    540728            j = i
    541729            if 1 <= j <= self.n:
    542                 return self.perm[j-1]+1
     730                return from_gap[self.perm[j-1]+1]
    543731            else:
    544                 return i
     732                return from_gap[i]
    545733
    546734    cpdef _act_on_(self, x, bint self_on_left):
    547735        """
     
    590778                return left(tuple(sigma_x))
    591779
    592780    cpdef MonoidElement _mul_(left, MonoidElement _right):
     781        """
     782        EXAMPLES::
     783
     784            sage: S = SymmetricGroup(['a', 'b'])
     785            sage: s = S([('a', 'b')]); s
     786            ('a','b')
     787            sage: s*s
     788            ()
     789        """
    593790        cdef PermutationGroupElement prod = left._new_c()
    594791        cdef PermutationGroupElement right = <PermutationGroupElement>_right
    595792        cdef int i
     
    614811        for i from 0 <= i < self.n:
    615812            inv.perm[self.perm[i]] = i
    616813        return inv
     814
     815    cpdef _gap_list(self):
     816        """
     817        Returns this permutation in list notation compatible with the
     818        GAP numbering.
     819
     820        EXAMPLES::
     821
     822            sage: S = SymmetricGroup(3)
     823            sage: s = S.gen(0); s
     824            (1,2,3)
     825            sage: s._gap_list()
     826            [2, 3, 1]
     827
     828        ::
    617829       
     830            sage: S = SymmetricGroup(['a', 'b', 'c'])
     831            sage: s = S.gen(0); s
     832            ('a','b','c')
     833            sage: s._gap_list()
     834            [2, 3, 1]
     835        """
     836        cdef int i
     837        return [self.perm[i]+1 for i from 0 <= i < self.n]
     838
     839    def _gap_cycle_string(self):
     840        """
     841        Returns a cycle string for this permutation compatible with
     842        the GAP numbering.
     843
     844        EXAMPLES::
     845
     846            sage: S = SymmetricGroup(3)
     847            sage: s = S.gen(0); s
     848            (1,2,3)
     849            sage: s._gap_cycle_string()
     850            '(1,2,3)'
     851
     852        ::
     853
     854            sage: S = SymmetricGroup(['a', 'b', 'c'])
     855            sage: s = S.gen(0); s
     856            ('a','b','c')
     857            sage: s._gap_cycle_string()
     858            '(1,2,3)'
     859        """
     860        from sage.combinat.permutation import Permutation
     861        return Permutation(self._gap_list()).cycle_string()
     862
    618863    cpdef list(self):
    619864        """
    620865        Returns list of the images of the integers from 1 to n under this
     
    633878            (1,2)
    634879            sage: x.list()
    635880            [2, 1, 3, 4]
     881
     882        TESTS::
     883
     884            sage: S = SymmetricGroup(0)
     885            sage: x = S.one(); x
     886            ()
     887            sage: x.list()
     888            []
    636889        """
    637890        cdef int i
    638         return [self.perm[i]+1 for i from 0 <= i < self.n]
     891
     892        #We need to do this to handle the case of SymmetricGroup(0)
     893        #where the domain is (), but the permutation group element has
     894        #an underlying representation of [1].  The 1 doesn't
     895        #correspond to anything in the domain
     896        if len(self._parent._domain) == 0:
     897            return []
     898        else:
     899            from_gap = self._parent._domain_from_gap
     900            return [from_gap[self.perm[i]+1] for i from 0 <= i < self.n]
    639901
    640902    def __hash__(self):
    641903        """
     
    654916            1592966088          # 32-bit
    655917            2865702456085625800 # 64-bit
    656918        """
    657         return hash(self.tuple())
    658 
     919        return hash(tuple(self._gap_list()))
     920   
    659921    def tuple(self):
    660922        """
    661         Return tuple of images of integers under self.
     923        Return tuple of images of the domain under self.
    662924       
    663925        EXAMPLES::
    664926       
     
    666928            sage: s = G([2,1,5,3,4])
    667929            sage: s.tuple()
    668930            (2, 1, 5, 3, 4)
     931
     932            sage: S = SymmetricGroup(['a', 'b'])
     933            sage: S.gen().tuple()
     934            ('b', 'a')
    669935        """
    670936        if self.__tuple is None:
    671937            self.__tuple = tuple(self.list())
     
    696962            sage: x.dict()
    697963            {1: 2, 2: 1, 3: 3, 4: 4}
    698964        """
     965        from_gap = self._parent._domain_from_gap
    699966        cdef int i
    700967        u = {}
    701968        for i from 0 <= i < self.n:
    702             u[i+1] = self.perm[i]+1
     969            u[i+1] = from_gap[self.perm[i]+1]
    703970        return u
    704971           
    705972    def order(self):
     
    8161083    def orbit(self, n, bint sorted=True):
    8171084        """
    8181085        Returns the orbit of the integer `n` under this group
    819         element, as a sorted list of integers.
     1086        element, as a sorted list.
    8201087       
    8211088        EXAMPLES::
    8221089       
     
    8281095            [1, 2, 3]
    8291096            sage: g.orbit(10)
    8301097            [10]
     1098
     1099        ::
     1100       
     1101            sage: s = SymmetricGroup(['a', 'b']).gen(0); s
     1102            ('a','b')
     1103            sage: s.orbit('a')
     1104            ['a', 'b']
    8311105        """
     1106        to_gap = self._parent._domain_to_gap
     1107        from_gap = self._parent._domain_from_gap
     1108        try:
     1109            n = to_gap[n]
     1110        except KeyError:
     1111            return [n]
     1112       
    8321113        cdef int i = n
    8331114        cdef int start = i
    8341115        if 1 <= i <= self.n:
    835             L = [i]
     1116            L = [from_gap[i]]
    8361117            i = self.perm[i-1]+1
    8371118            while i != start:
    838                 PyList_Append(L,i)
     1119                PyList_Append(L,from_gap[i])
    8391120                i = self.perm[i-1]+1
    8401121            if sorted:
    8411122                L.sort()
    8421123            return L
    8431124        else:
    844             return [n]
     1125            return from_gap[n]
    8451126               
    8461127    def cycles(self):
    8471128        """
     
    8761157        sage_free(seen)
    8771158        return L
    8781159       
    879     def cycle_tuples(self):
     1160    def cycle_tuples(self, singletons=False):
    8801161        """
    8811162        Return self as a list of disjoint cycles, represented as tuples
    8821163        rather than permutation group elements.
     1164
     1165        INPUT:
     1166
     1167        - ``singletons`` - boolean (default: False) whether or not consider the
     1168          cycle that correspond to fixed point
     1169
     1170        EXAMPLES::
     1171
     1172            sage: p = PermutationGroupElement('(2,6)(4,5,1)')
     1173            sage: p.cycle_tuples()
     1174            [(1, 4, 5), (2, 6)]
     1175            sage: p.cycle_tuples(singletons=True)
     1176            [(1, 4, 5), (2, 6), (3,)]
     1177
     1178        EXAMPLES::
     1179
     1180            sage: S = SymmetricGroup(4)
     1181            sage: S.gen(0).cycle_tuples()
     1182            [(1, 2, 3, 4)]
     1183
     1184        ::
     1185       
     1186            sage: S = SymmetricGroup(['a','b','c','d'])
     1187            sage: S.gen(0).cycle_tuples()
     1188            [('a', 'b', 'c', 'd')]
     1189            sage: S([('a', 'b'), ('c', 'd')]).cycle_tuples()
     1190            [('a', 'b'), ('c', 'd')]
    8831191        """
     1192        from_gap = self._parent._domain_from_gap
    8841193        L = []
    8851194        cdef int i, k
    8861195        cdef bint* seen = <bint *>sage_malloc(sizeof(bint) * self.n)
    8871196        for i from 0 <= i < self.n: seen[i] = 0
    8881197        for i from 0 <= i < self.n:
    889             if seen[i] or self.perm[i] == i:
     1198            if seen[i]:
    8901199                continue
    891             cycle = [i+1]
    892             k = self.perm[i]
    893             while k != i:
    894                 PyList_Append(cycle, k+1)
    895                 seen[k] = 1
    896                 k = self.perm[k]
    897             PyList_Append(L, tuple(cycle))
     1200            if self.perm[i] == i:
     1201                if singletons:
     1202                    PyList_Append(L, (from_gap[i+1],))
     1203                    # it is not necessary to put seen[i] to 1 as we will never
     1204                    # see i again
     1205                else:
     1206                    continue
     1207            else:
     1208                cycle = [from_gap[i+1]]
     1209                k = self.perm[i]
     1210                while k != i:
     1211                    PyList_Append(cycle, from_gap[k+1])
     1212                    seen[k] = 1
     1213                    k = self.perm[k]
     1214                PyList_Append(L, tuple(cycle))
    8981215        sage_free(seen)
    8991216        return L
    9001217
     1218    def cycle_string(self, singletons=False):
     1219        """
     1220        Return string representation of this permutation.
     1221       
     1222       EXAMPLES::
     1223
     1224            sage: g = PermutationGroupElement([(1,2,3),(4,5)])
     1225            sage: g.cycle_string()
     1226            '(1,2,3)(4,5)'
     1227
     1228            sage: g = PermutationGroupElement([3,2,1])
     1229            sage: g.cycle_string(singletons=True)
     1230            '(1,3)(2)'
     1231        """
     1232        cycles = self.cycle_tuples(singletons)
     1233        if len(cycles) == 0:
     1234            return '()'
     1235        return ''.join([repr(c) for c in cycles]).replace(', ',',').replace(',)',')')
     1236
    9011237    def has_descent(self, i, side = "right", positive = False):
    9021238        """
    9031239        INPUT:
     
    9441280            True
    9451281            sage: S._test_has_descent()
    9461282        """
     1283        to_gap = self._parent._domain_to_gap
     1284        from_gap = self._parent._domain_from_gap
    9471285        if side == "right":
    9481286            self = ~self
     1287           
    9491288        try:
    950             if not self.parent()._has_natural_set():
    951                 set = self.parent()._set
    952                 pos = set.index(i)
    953                 i1  = set[pos+1]
    954                 res = set.index(self(i)) > set.index(self(i1))
    955                 return res is not positive
    956         except AttributeError:
    957             pass
    958         return (self(i) > self(i+1)) is not positive
     1289            i1 = from_gap[to_gap[i]+1]
     1290        except KeyError:
     1291            return False
     1292       
     1293        return (to_gap[self(i)] > to_gap[self(i1)]) is not positive
    9591294
    9601295    def matrix(self):
    9611296        """
     
    9801315            entries[i, self.perm[i]] = 1
    9811316        return M(entries)
    9821317
    983     def word_problem(g, words, display=True):
     1318    def word_problem(self, words, display=True):
    9841319        """
    9851320        G and H are permutation groups, g in G, H is a subgroup of G
    9861321        generated by a list (words) of elements of G. If g is in H, return
     
    9951330        EXAMPLE::
    9961331       
    9971332            sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]], canonicalize=False)
    998             sage: g1 = G.gens()[0]
    999             sage: g2 = G.gens()[1]
     1333            sage: g1, g2 = G.gens()
    10001334            sage: h = g1^2*g2*g1
    10011335            sage: h.word_problem([g1,g2], False)
    10021336            ('x1^2*x2^-1*x1', '(1,2,3)(4,5)^2*(3,4)^-1*(1,2,3)(4,5)')
     
    10051339               [['(1,2,3)(4,5)', 2], ['(3,4)', -1], ['(1,2,3)(4,5)', 1]]
    10061340            ('x1^2*x2^-1*x1', '(1,2,3)(4,5)^2*(3,4)^-1*(1,2,3)(4,5)')
    10071341        """
     1342        if not self._parent._has_natural_domain():
     1343            raise NotImplementedError
     1344       
    10081345        import copy
    10091346        from sage.groups.perm_gps.permgroup import PermutationGroup
    10101347        from sage.interfaces.all import gap
    1011        
     1348
    10121349        G = gap(words[0].parent())
    1013         g = words[0].parent()(g)
    1014         gensH = gap(words)
    1015         H = gensH.Group()
    1016         hom = G.EpimorphismFromFreeGroup()
    1017         ans = hom.PreImagesRepresentative(gap(g))
     1350        g = words[0].parent()(self)
     1351        H = gap.Group(words)
     1352        ans = G.EpimorphismFromFreeGroup().PreImagesRepresentative(g)
    10181353       
    10191354        l1 = str(ans)
    10201355        l2 = copy.copy(l1)
  • sage/groups/perm_gps/permgroup_morphism.py

    diff --git a/sage/groups/perm_gps/permgroup_morphism.py b/sage/groups/perm_gps/permgroup_morphism.py
    a b  
    1515    sage: g = G([(1,2,3,4)])
    1616    sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))
    1717    sage: phi.image(G)
    18     Permutation Group with generators [(1,2,3,4)]
     18    Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]
    1919    sage: phi.kernel()
    20     Permutation Group with generators [()]
     20    Subgroup of (Cyclic group of order 4 as a permutation group) generated by [()]
    2121    sage: phi.image(g)                 
    2222    (1,2,3,4)
    2323    sage: phi(g)                       
     
    8787            sage: g = G([(1,2,3,4)])
    8888            sage: phi = PermutationGroupMorphism_im_gens(G, H, [1])
    8989            sage: phi.kernel()
    90             Permutation Group with generators [(1,2,3,4)]
     90            Subgroup of (Cyclic group of order 4 as a permutation group) generated by [(1,2,3,4)]
    9191           
    9292        ::
    9393       
     
    9898            sage: G.is_isomorphic(pr1.kernel())
    9999            True
    100100        """
    101         return PermutationGroup(gap_group=self._gap_().Kernel())
     101        return self.domain().subgroup(gap_group=self._gap_().Kernel())
    102102
    103103    def image(self, J):
    104104        """
     
    112112            sage: g = G([(1,2,3,4)])
    113113            sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens()))
    114114            sage: phi.image(G)
    115             Permutation Group with generators [(1,2,3,4)]
     115            Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]
    116116            sage: phi.image(g)                 
    117117            (1,2,3,4)
    118118
     
    123123            sage: H = D[0]
    124124            sage: pr1 = D[3]
    125125            sage: pr1.image(G)
    126             Permutation Group with generators [(3,7,5)(4,8,6), (1,2,6)(3,4,8)]
     126            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)]
    127127            sage: G.is_isomorphic(pr1.image(G))
    128128            True
    129129        """
     130        H = self.codomain()
    130131        if J in self.domain():
    131132            J = PermutationGroup([J])
    132133            G = self._gap_().Image(J)
    133             return PermutationGroup(gap_group=G).gens()[0]
     134            return H.subgroup(gap_group=G).gens()[0]
    134135        else:
    135136            G = self._gap_().Image(J)
    136             return PermutationGroup(gap_group=G)
     137            return H.subgroup(gap_group=G)
    137138
    138139    def __call__(self, g):
    139140        """
     
    177178            sage: H = G.subgroup([G([(1,2,3,4)])])
    178179            sage: PermutationGroupMorphism_from_gap(H, G, gap.Identity)
    179180            Permutation group morphism:
    180               From: Subgroup of Permutation Group with generators [(1,2)(3,4), (1,2,3,4)] generated by [(1,2,3,4)]
     181              From: Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(1,2,3,4)]
    181182              To:   Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]
    182183              Defn: Identity
    183184        """
  • sage/groups/perm_gps/permgroup_named.py

    diff --git a/sage/groups/perm_gps/permgroup_named.py b/sage/groups/perm_gps/permgroup_named.py
    a b  
    3737-- PSp(2n,q), projective symplectic linear group of $2n\times 2n$ matrices
    3838              over the finite field GF(q)
    3939
    40 -- PSU(n,q), projective special unitary group of $n\times n$ matrices having
     40-- PSU(n,q), projective special unitary group of $n \times n$ matrices having
    4141             coefficients in the finite field $GF(q^2)$ that respect a
    4242             fixed nondegenerate sesquilinear form, of determinant 1.
    4343
     
    7878from sage.groups.abelian_gps.abelian_group import AbelianGroup
    7979from sage.misc.functional import is_even
    8080from sage.misc.cachefunc import cached_method
     81from sage.misc.misc import deprecated_function_alias
    8182from sage.groups.perm_gps.permgroup import PermutationGroup_generic
    8283from sage.groups.perm_gps.permgroup_element import PermutationGroupElement
    8384from sage.structure.unique_representation import UniqueRepresentation
    8485from sage.structure.parent import Parent
    8586from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets
     87from sage.sets.finite_enumerated_set import FiniteEnumeratedSet
    8688from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets
    87 from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets
    8889from sage.categories.enumerated_sets import EnumeratedSets
    8990from sage.sets.non_negative_integers import NonNegativeIntegers
    9091from sage.sets.family import Family
    9192
    9293class PermutationGroup_unique(UniqueRepresentation, PermutationGroup_generic):
     94    @staticmethod
     95    def __classcall__(cls, *args, **kwds):
     96        """
     97        This makes sure that domain is a FiniteEnumeratedSet before it gets passed
     98        on to the __init__ method.
    9399
     100        EXAMPLES::
     101
     102            sage: SymmetricGroup(['a','b']).domain() #indirect doctest
     103            {'a', 'b'}
     104        """
     105        domain = kwds.pop('domain', None)
     106        if domain is not None:
     107            if domain not in FiniteEnumeratedSets():
     108                domain = FiniteEnumeratedSet(domain)
     109            kwds['domain'] = domain
     110        return super(PermutationGroup_unique, cls).__classcall__(cls, *args, **kwds)
     111 
    94112    def __eq__(self, other):
    95          """
    96          Overrides the default equality testing provided by
    97          UniqueRepresentation by forcing a call to :meth:.`__cmp__`.
     113        """
     114        Overrides the default equality testing provided by
     115        UniqueRepresentation by forcing a call to :meth:.`__cmp__`.
    98116
    99          EXAMPLES::
    100 
    101              sage: G = SymmetricGroup(6)
    102              sage: G3 = G.subgroup([G((1,2,3,4,5,6)),G((1,2))])
    103              sage: G == G3
    104              True
    105          """
    106          return self.__cmp__(other) == 0
     117        EXAMPLES::
     118       
     119            sage: G = SymmetricGroup(6)
     120            sage: G3 = G.subgroup([G((1,2,3,4,5,6)),G((1,2))])
     121            sage: G == G3
     122            True
     123        """
     124        return self.__cmp__(other) == 0
    107125
    108126
    109127class PermutationGroup_symalt(PermutationGroup_unique):
     
    113131    """
    114132
    115133    @staticmethod
    116     def __classcall__(cls, n):
     134    def __classcall__(cls, domain):
    117135        """
    118136        Normalizes the input of the constructor into a set
    119137
     
    142160            sage: SymmetricGroup(-1)
    143161            Traceback (most recent call last):
    144162            ...
    145             ValueError: n (=-1) must be an integer >= 0 or a list
     163            ValueError: domain (=-1) must be an integer >= 0 or a list
    146164        """
    147         if not isinstance(n, (tuple,list)):
    148             try:
    149                 n = Integer(n)
    150             except TypeError:
    151                 raise ValueError, "n (=%s) must be an integer >= 0 or a list (but n has type %s)"%(n,type(n))
    152             else:
    153                 if n < 0:
    154                     raise ValueError, "n (=%s) must be an integer >= 0 or a list"%n
    155                 n = range(1, n+1)
     165        if domain not in FiniteEnumeratedSets():
     166            if not isinstance(domain, (tuple, list)):
     167                try:
     168                    domain = Integer(domain)
     169                except TypeError:
     170                    raise ValueError, "domain (=%s) must be an integer >= 0 or a finite set (but domain has type %s)"%(domain,type(domain))
     171               
     172                if domain < 0:
     173                    raise ValueError, "domain (=%s) must be an integer >= 0 or a list"%domain
     174                else:
     175                    domain = range(1, domain+1)
     176            v = FiniteEnumeratedSet(domain)
     177        else:
     178            v = domain
    156179
    157         try:
    158             v = tuple(Integer(z) for z in n)
    159         except TypeError:
    160             raise ValueError, "each entry of list must be an integer"
     180        return super(PermutationGroup_symalt, cls).__classcall__(cls, domain=v)
    161181
    162         if v and min(v) < 1: # for SymmetricGroup(0), v is empty
    163             raise ValueError, "each element of list must be positive"
    164 
    165         return super(PermutationGroup_symalt, cls).__classcall__(cls, v)
    166 
    167     def set(self):
    168         """
    169         Returns the list of positive integers on which this group acts.
    170 
    171         EXAMPLES:
    172             sage: SymmetricGroup(3).set()
    173             (1, 2, 3)
    174             sage: SymmetricGroup([2,3,4]).set()
    175             (2, 3, 4)
    176             sage: AlternatingGroup(3).set()
    177             (1, 2, 3)
    178             sage: AlternatingGroup([2,3,4]).set()
    179             (2, 3, 4)
    180         """
    181         return self._set
    182 
    183     @cached_method
    184     def _has_natural_set(self):
    185         """
    186         Returns true if the underlying set is of the form (1,...,n)
    187 
    188         EXAMPLES::
    189 
    190             sage: SymmetricGroup(3)._has_natural_set()
    191             True
    192             sage: SymmetricGroup((1,2,3))._has_natural_set()
    193             True
    194             sage: SymmetricGroup((1,3))._has_natural_set()
    195             False
    196             sage: SymmetricGroup((3,2,1))._has_natural_set()
    197             False
    198         """
    199         set = self.set()
    200         return set == tuple(range(1,len(set)+1))
    201 
    202     def __str__(self):
    203         """
    204         EXAMPLES:
    205             sage: S = SymmetricGroup([2,3,7]); S
    206             Symmetric group of order 3! as a permutation group
    207             sage: str(S)
    208             'SymmetricGroup((2, 3, 7))'
    209             sage: S = SymmetricGroup(5); S
    210             Symmetric group of order 5! as a permutation group
    211             sage: str(S)
    212             'SymmetricGroup(5)'
    213             sage: A = AlternatingGroup([2,3,7]); A
    214             Alternating group of order 3!/2 as a permutation group
    215             sage: str(A)
    216             'AlternatingGroup((2, 3, 7))'
    217         """
    218         set = self._set
    219         if self._has_natural_set():
    220             set = len(set)
    221         return "%s(%s)"%(self._gap_name, set)
     182    set = deprecated_function_alias(PermutationGroup_generic.domain, 'Sage Version 4.7.1')
    222183
    223184class SymmetricGroup(PermutationGroup_symalt):
    224     def __init__(self, _set):
     185    def __init__(self, domain=None):
    225186        """
    226187        The full symmetric group of order $n!$, as a permutation group.
    227188        If n is a list or tuple of positive integers then it returns the
     
    244205            sage: G = SymmetricGroup([1,2,4,5])
    245206            sage: G
    246207            Symmetric group of order 4! as a permutation group
    247             sage: G.set()
    248             (1, 2, 4, 5)
     208            sage: G.domain()
     209            {1, 2, 4, 5}
    249210            sage: G = SymmetricGroup(4)
    250211            sage: G
    251212            Symmetric group of order 4! as a permutation group
    252             sage: G.set()
    253             (1, 2, 3, 4)
     213            sage: G.domain()
     214            {1, 2, 3, 4}
    254215            sage: G.category()
    255216            Join of Category of finite permutation groups and Category of finite weyl groups
    256217            sage: TestSuite(G).run()
     
    262223        from sage.categories.finite_weyl_groups import FiniteWeylGroups
    263224        from sage.categories.finite_permutation_groups import FinitePermutationGroups
    264225        from sage.categories.category import Category
     226       
    265227        #Note that we skip the call to the superclass initializer in order to
    266228        #avoid infinite recursion since SymmetricGroup is called by
    267229        #PermutationGroupElement
    268         super(PermutationGroup_generic,self).__init__(category = Category.join([FinitePermutationGroups(), FiniteWeylGroups()]))
    269 
    270         self._set = _set
    271         self._deg = max(self._set+(0,))  # _set cat be empty
    272         n = len(self._set)
     230        super(PermutationGroup_generic, self).__init__(category = Category.join([FinitePermutationGroups(), FiniteWeylGroups()]))
     231       
     232        self._domain = domain
     233        self._deg = len(self._domain)
     234        self._domain_to_gap = dict((key, i+1) for i, key in enumerate(self._domain))
     235        self._domain_from_gap = dict((i+1, key) for i, key in enumerate(self._domain))
    273236
    274237        #Create the generators for the symmetric group
    275         gens = [ tuple(self._set) ]
    276         if n > 2:
    277             gens.append( tuple(self._set[:2]) )
     238        gens = [ tuple(self._domain) ]
     239        if len(self._domain) > 2:
     240            gens.append( tuple(self._domain[:2]) )
    278241        self._gens = [PermutationGroupElement(g, self, check=False) for g in gens]
    279242
    280         self._gap_string = '%s(%s)'%(self._gap_name, n)
     243
     244    def _gap_init_(self, gap=None):
     245        """
     246        Returns the string used to create this group in GAP.
     247
     248        EXAMPLES::
     249
     250            sage: S = SymmetricGroup(3)
     251            sage: S._gap_init_()
     252            'SymmetricGroup(3)'
     253            sage: S = SymmetricGroup(['a', 'b', 'c'])
     254            sage: S._gap_init_()
     255            'SymmetricGroup(3)'
     256        """
     257        return 'SymmetricGroup(%s)'%self.degree()
    281258
    282259    @cached_method
    283260    def index_set(self):
     
    288265
    289266            sage: S8 = SymmetricGroup(8)
    290267            sage: S8.index_set()
    291             (1, 2, 3, 4, 5, 6, 7)
     268            [1, 2, 3, 4, 5, 6, 7]
    292269
    293270            sage: S = SymmetricGroup([3,1,4,5])
    294271            sage: S.index_set()
    295             (3, 1, 4)
     272            [3, 1, 4]
    296273        """
    297         return self.set()[:-1]
     274        return self.domain()[:-1]
    298275
    299276    def __cmp__(self, x):
    300277        """
     
    307284            True
    308285        """
    309286        if isinstance(x, SymmetricGroup):
    310             return cmp((self._deg, self._set), (x._deg, x._set))
     287            return cmp((self._deg, self._domain), (x._deg, x._domain))
    311288        else:
    312289            return PermutationGroup_generic.__cmp__(self, x)
    313290
     
    317294            sage: A = SymmetricGroup([2,3,7]); A
    318295            Symmetric group of order 3! as a permutation group
    319296        """
    320         return "Symmetric group of order %s! as a permutation group"%len(self._set)
    321 
    322     _gap_name = 'SymmetricGroup'
     297        return "Symmetric group of order %s! as a permutation group"%self.degree()
    323298
    324299    def simple_reflection(self, i):
    325300        """
     
    336311            sage: A.simple_reflections()
    337312            Finite family {2: (2,3), 3: (3,7)}
    338313        """
    339         return self([(i, self._set[self._set.index(i)+1])], check=False)
     314        return self([(i, self._domain[self._domain.index(i)+1])], check=False)
    340315
    341316    def major_index(self, parameter=None):
    342317        r"""
     
    368343        return q_factorial(self.degree(), parameter)
    369344
    370345class AlternatingGroup(PermutationGroup_symalt):
    371     def __init__(self, _set):
     346    def __init__(self, domain=None):
    372347        """
    373348        The alternating group of order $n!/2$, as a permutation group.
    374349
     
    390365            sage: G = AlternatingGroup([1,2,4,5])
    391366            sage: G
    392367            Alternating group of order 4!/2 as a permutation group
    393             sage: G.set()
    394             (1, 2, 4, 5)
     368            sage: G.domain()
     369            {1, 2, 4, 5}
    395370            sage: G.category()
    396371            Category of finite permutation groups
    397372            sage: TestSuite(G).run()
    398373        """
    399         n = len(_set)
    400         #Create the generators for the symmetric group
    401         if n == 1:
    402             gens = [ [] ]
    403         else:
    404             gens = [ tuple(_set) ]
    405             if n > 2:
    406                 gens.append( tuple(_set[:2]) )
    407 
    408         PermutationGroup_symalt.__init__(self, gap_group='%s(%s)'%(self._gap_name,n))
    409 
    410         self._set = _set
    411         self._deg = max(_set)
     374        PermutationGroup_symalt.__init__(self, gap_group='AlternatingGroup(%s)'%len(domain), domain=domain)
    412375
    413376    def _repr_(self):
    414377        """
     
    416379            sage: A = AlternatingGroup([2,3,7]); A
    417380            Alternating group of order 3!/2 as a permutation group
    418381        """
    419         return "Alternating group of order %s!/2 as a permutation group" % len(self._set)
     382        return "Alternating group of order %s!/2 as a permutation group"%self.degree()
    420383
    421     _gap_name = 'AlternatingGroup'
     384    def _gap_init_(self, gap=None):
     385        """
     386        Returns the string used to create this group in GAP.
    422387
     388        EXAMPLES::
     389
     390            sage: A = AlternatingGroup(3)
     391            sage: A._gap_init_()
     392            'AlternatingGroup(3)'
     393            sage: A = AlternatingGroup(['a', 'b', 'c'])
     394            sage: A._gap_init_()
     395            'AlternatingGroup(3)'
     396        """
     397        return 'AlternatingGroup(%s)'%(self.degree())
     398                   
    423399class CyclicPermutationGroup(PermutationGroup_unique):
    424400    def __init__(self, n):
    425401        """
     
    494470        n = self.order()
    495471        a = list(factor(n))
    496472        invs = [x[0]**x[1] for x in a]
    497         G = AbelianGroup(len(a),invs)
     473        G = AbelianGroup(len(a), invs)
    498474        return G
    499475
    500476class DiCyclicGroup(PermutationGroup_unique):
     
    636612        a = [tuple(range(1, halfr+1)), tuple(range(halfr+1, r+1))]
    637613        # With an odd part, a cycle of length m will give the right order for a
    638614        if m > 1:
    639             a.append( tuple(range(r+1,r+m+1)) )
     615            a.append( tuple(range(r+1, r+m+1)) )
    640616
    641617        # Representation of  x
    642618        # Four-cycles that will conjugate the generator  a  properly
     
    644620                for i in range(0, fourthr)]
    645621        # With an odd part, transpositions will conjugate the m-cycle to create inverse
    646622        if m > 1:
    647             x += [(r+i+1,r+m-i) for i in range(0, (m-1)//2)]
     623            x += [(r+i+1, r+m-i) for i in range(0, (m-1)//2)]
    648624
    649         PermutationGroup_generic.__init__(self, gens=[a,x])
     625        PermutationGroup_generic.__init__(self, gens=[a, x])
    650626
    651627    def _repr_(self):
    652628        r"""
     
    962938
    963939        self._d = d
    964940        self._n = n
    965         self._set = range(1, d+1)
     941        self._domain = range(1, d+1)
    966942
    967943    def _repr_(self):
    968944        """
     
    11981174            sage: [TransitiveGroups(i).cardinality() for i in range(11)] # requires optional database_gap
    11991175            [1, 1, 1, 2, 5, 5, 16, 7, 50, 34, 45]
    12001176
    1201         .. warning:: The database_gap contains all transitive groups
    1202           up to degree 30::
     1177        .. warning::
    12031178
    1204             sage: TransitiveGroups(31).cardinality()                     # requires optional database_gap
    1205             Traceback (most recent call last):
    1206             ...
    1207             NotImplementedError: Only the transitive groups of order less than 30 are available in GAP's database
     1179            The database_gap contains all transitive groups
     1180            up to degree 30::
     1181
     1182                sage: TransitiveGroups(31).cardinality()                     # requires optional database_gap
     1183                Traceback (most recent call last):
     1184                ...
     1185                NotImplementedError: Only the transitive groups of order less than 30 are available in GAP's database
    12081186
    12091187        TESTS::
    12101188
     
    12831261            Category of finite permutation groups
    12841262            sage: TestSuite(G).run()
    12851263        """
    1286         from sage.groups.perm_gps.permgroup import PermutationGroup_generic
    12871264        id = 'Group([()])' if n == 1 else 'PGL(%s,%s)'%(n,q)
    12881265        PermutationGroup_generic.__init__(self, gap_group=id)
    12891266        self._q = q
     
    15851562class SuzukiGroup(PermutationGroup_unique):
    15861563    def __init__(self, q, name='a'):
    15871564        r"""
    1588         The Suzuki group over GF(q), $^2 B_2(2^{2k+1}) = Sz(2^{2k+1})$. A wrapper for the GAP function SuzukiGroup.
     1565        The Suzuki group over GF(q),
     1566        $^2 B_2(2^{2k+1}) = Sz(2^{2k+1})$.
     1567
     1568        A wrapper for the GAP function SuzukiGroup.
    15891569
    15901570        INPUT:
    15911571            q -- 2^n, an odd power of 2; the size of the ground
     
    15951575                    finite field GF(q)
    15961576
    15971577        OUTPUT:
    1598             A Suzuki group.
     1578       
     1579        - A Suzuki group.
    15991580
    1600         EXAMPLES:
     1581        EXAMPLES::
     1582       
    16011583            sage: SuzukiGroup(8)
    1602             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)]
     1584            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)]
    16031585            sage: print SuzukiGroup(8)
    16041586            The Suzuki group over Finite Field in a of size 2^3
    16051587
     
    16121594            Finite Field in alpha of size 2^5
    16131595
    16141596        REFERENCES:
    1615             http://en.wikipedia.org/wiki/Group_of_Lie_type\#Suzuki-Ree_groups
     1597       
     1598        -  http://en.wikipedia.org/wiki/Group_of_Lie_type\#Suzuki-Ree_groups
    16161599        """
    16171600        q = Integer(q)
    16181601        from sage.rings.arith import valuation
  • sage/rings/number_field/galois_group.py

    diff --git a/sage/rings/number_field/galois_group.py b/sage/rings/number_field/galois_group.py
    a b  
    343343            sage: G.subgroup([ G(1), G([(1,5,2),(3,4,6)]), G([(1,2,5),(3,6,4)])])
    344344            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
    345345        """
    346         if len(elts) == self.order(): return self
    347         else: return GaloisGroup_subgroup(self, elts)
     346        if len(elts) == self.order():
     347            return self
     348        else:
     349            return GaloisGroup_subgroup(self, elts)
    348350
    349351    # Proper number theory starts here. All the functions below make no sense
    350352    # unless the field is Galois.
     
    560562            sage: GaloisGroup_subgroup( G, [ G(1), G([(1,5,2),(3,4,6)]), G([(1,2,5),(3,6,4)])])
    561563            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
    562564        """
    563 
     565        #XXX: This should be fixed so that this can use GaloisGroup_v2.__init__
    564566        PermutationGroup_generic.__init__(self, elts, canonicalize = True)
    565567        self._ambient = ambient
    566568        self._number_field = ambient.number_field()
    567         self._galois_closure=ambient._galois_closure
     569        self._galois_closure = ambient._galois_closure
     570        self._pari_data = ambient._pari_data
     571        self._pari_gc = ambient._pari_gc
     572        self._gc_map = ambient._gc_map
    568573        self._elts = elts
    569574       
    570575    def fixed_field(self):
     
    683688        return min(w)   
    684689
    685690    def __cmp__(self, other):
    686         r"""Compare self to other. For some bizarre reason, if you just let it
     691        r"""
     692        Compare self to other. For some bizarre reason, if you just let it
    687693        inherit the cmp routine from PermutationGroupElement, cmp(x, y) works
    688694        but sorting lists doesn't.
    689695       
     
    691697       
    692698            sage: K.<a> = NumberField(x^6 + 40*x^3 + 1372);G = K.galois_group()
    693699            sage: sorted([G.artin_symbol(Q) for Q in K.primes_above(5)])
    694             [(1,2)(3,4)(5,6), (1,3)(2,6)(4,5), (1,5)(2,4)(3,6)]
     700            [(1,3)(2,6)(4,5), (1,2)(3,4)(5,6), (1,5)(2,4)(3,6)]
    695701        """
    696         return cmp(self.list(), other.list())
     702        return PermutationGroupElement.__cmp__(self, other)
    697703
    698704
    699705
  • sage/rings/number_field/number_field.py

    diff --git a/sage/rings/number_field/number_field.py b/sage/rings/number_field/number_field.py
    a b  
    67856785            sage: z = CyclotomicField(3).an_element(); z
    67866786            zeta3
    67876787            sage: c = K.character([1,z,z**2]); c
    6788             Character of Subgroup of AlternatingGroup(4) generated by [(2,3,4)]
     6788            Character of Subgroup of (Alternating group of order 4!/2 as a permutation group) generated by [(2,3,4)]
    67896789            sage: c(g^2); z^2
    67906790            -zeta3 - 1
    67916791            -zeta3 - 1
  • sage/sets/finite_enumerated_set.py

    diff --git a/sage/sets/finite_enumerated_set.py b/sage/sets/finite_enumerated_set.py
    a b  
    181181        """
    182182        return Integer(len(self._elements))
    183183
     184    def index(self, x):
     185        """
     186        Returns the index of ``x`` in this finite enumerated set.
     187
     188        EXAMPLES::
     189
     190            sage: S = FiniteEnumeratedSet(['a','b','c'])
     191            sage: S.index('b')
     192            1
     193        """
     194        return self._elements.index(x)
     195
    184196    def _element_constructor_(self, el):
    185197        """
    186198        TESTS::
  • sage/structure/parent.pyx

    diff --git a/sage/structure/parent.pyx b/sage/structure/parent.pyx
    a b  
    16681668            sage: S3.register_embedding(phi)
    16691669            sage: S3.coerce_embedding()
    16701670            Generic morphism:
    1671               From: AlternatingGroup(3)
     1671              From: Alternating group of order 3!/2 as a permutation group
    16721672              To:   Special Linear Group of degree 3 over Rational Field
    16731673            sage: S3.coerce_embedding()(p)
    16741674            [0 0 1]
  • sage/structure/parent_gens.pyx

    diff --git a/sage/structure/parent_gens.pyx b/sage/structure/parent_gens.pyx
    a b  
    368368        if d.has_key('_element_constructor'):
    369369            return parent.Parent.__setstate__(self, d)
    370370        try:
    371             self.__dict__ = d
     371            self.__dict__.update(d)
    372372            self._generator_orders = d['_generator_orders']
    373373        except (AttributeError,KeyError):
    374374            pass