Ticket #10335: trac_10335-permgroup_domain-rebase.patch
File trac_10335-permgroup_domain-rebase.patch, 133.5 KB (added by , 9 years ago) |
---|
-
doc/de/tutorial/interfaces.rst
# HG changeset patch # User Mike Hansen <mhansen@gmail.com> # Date 1307563431 25200 # Node ID 4e461492179a94b3fa1bd7e49bd3c5fe4b20c286 # Parent 10f49e34d981dccab46b3c81dc60a14f0ee2d747 #10335: Add support for domains of permutation groups. This includes the functionality from #8929 by Jason Hill. diff --git a/doc/de/tutorial/interfaces.rst b/doc/de/tutorial/interfaces.rst
a b 172 172 173 173 sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]]) 174 174 sage: G.center() 175 Permutation Group with generators[()]175 Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()] 176 176 sage: G.group_id() # requires optional database_gap package 177 177 [120, 34] 178 178 sage: n = G.order(); n -
doc/de/tutorial/tour_groups.rst
diff --git a/doc/de/tutorial/tour_groups.rst b/doc/de/tutorial/tour_groups.rst
a b 23 23 [Permutation Group with generators [(1,2,3)(4,5), (3,4)], 24 24 Permutation Group with generators [(1,5)(3,4), (1,5)(2,4), (1,3,5)]] 25 25 sage: G.center() 26 Permutation Group with generators[()]26 Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()] 27 27 sage: G.random_element() # random output 28 28 (1,5,3)(2,4) 29 29 sage: print latex(G) -
doc/en/bordeaux_2008/nf_galois_groups.rst
diff --git a/doc/en/bordeaux_2008/nf_galois_groups.rst b/doc/en/bordeaux_2008/nf_galois_groups.rst
a b 41 41 sage: P = K.primes_above(2)[0] 42 42 sage: G.inertia_group(P) 43 43 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)] 46 46 47 47 If the number field is not Galois over `\QQ`, then the ``galois_group`` 48 48 command 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 232 232 233 233 sage: G = PermutationGroup(['(1,2,3)(4,5)', '(3,4)']) 234 234 sage: G.center() 235 Permutation Group with generators[()]235 Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()] 236 236 237 237 A similar syntax for matrix groups also works: 238 238 … … 244 244 [[[4, 0], [0, 4]]] 245 245 sage: G = PSL(2, 5 ) 246 246 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 [()] 248 248 249 249 Note: ``center`` can be spelled either way in GAP, not so in Sage. 250 250 -
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 569 569 570 570 sage: C20 = CyclicPermutationGroup(20) 571 571 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)]] 573 573 574 574 Be careful, this command uses some more advanced ideas and will not 575 575 usually list *all* of the subgroups of a group. Here we are relying on … … 623 623 sage: sg = K.conjugacy_classes_subgroups() 624 624 sage: print "sg:\n", sg 625 625 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)]] 627 627 sage: print "\nAn order two subgroup:\n", sg[1].list() 628 628 <BLANKLINE> 629 629 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 170 170 171 171 sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]]) 172 172 sage: G.center() 173 Permutation Group with generators[()]173 Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()] 174 174 sage: G.group_id() # requires optional database_gap package 175 175 [120, 34] 176 176 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 22 22 [Permutation Group with generators [(1,2,3)(4,5), (3,4)], 23 23 Permutation Group with generators [(1,5)(3,4), (1,5)(2,4), (1,3,5)]] 24 24 sage: G.center() 25 Permutation Group with generators[()]25 Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()] 26 26 sage: G.random_element() # random output 27 27 (1,5,3)(2,4) 28 28 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 175 175 176 176 sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]]) 177 177 sage: G.center() 178 Permutation Group with generators[()]178 Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()] 179 179 sage: G.group_id() # nécessite le paquet facultatif database_gap (optional) 180 180 [120, 34] 181 181 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 23 23 [Permutation Group with generators [(1,2,3)(4,5), (3,4)], 24 24 Permutation Group with generators [(1,5)(3,4), (1,5)(2,4), (1,3,5)]] 25 25 sage: G.center() 26 Permutation Group with generators[()]26 Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()] 27 27 sage: G.random_element() # sortie aléatoire (random) 28 28 (1,5,3)(2,4) 29 29 sage: print latex(G) -
doc/ru/tutorial/interfaces.rst
diff --git a/doc/ru/tutorial/interfaces.rst b/doc/ru/tutorial/interfaces.rst
a b 165 165 166 166 sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]]) 167 167 sage: G.center() 168 Permutation Group with generators[()]168 Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()] 169 169 sage: G.group_id() # requires optional database_gap package 170 170 [120, 34] 171 171 sage: n = G.order(); n -
doc/ru/tutorial/tour_groups.rst
diff --git a/doc/ru/tutorial/tour_groups.rst b/doc/ru/tutorial/tour_groups.rst
a b 22 22 [Permutation Group with generators [(1,2,3)(4,5), (3,4)], 23 23 Permutation Group with generators [(1,5)(3,4), (1,5)(2,4), (1,3,5)]] 24 24 sage: G.center() 25 Permutation Group with generators[()]25 Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()] 26 26 sage: G.random_element() # random output 27 27 (1,5,3)(2,4) 28 28 sage: print latex(G) -
sage/algebras/group_algebra_new.py
diff --git a/sage/algebras/group_algebra_new.py b/sage/algebras/group_algebra_new.py
a b 50 50 sage: a * b # a is automatically converted to an element of B 51 51 7*() + 5*(3,4) + 3*(2,3) + 9*(2,3,4) + 3*(1,2) + 6*(1,2)(3,4) + 3*(1,2,3) + (1,2,3,4) + 9*(1,3,2) + 3*(1,3,4) 52 52 sage: parent(a * b) 53 Group algebra of group "Symmetric Group(4)" over base ring Rational Field53 Group algebra of group "Symmetric group of order 4! as a permutation group" over base ring Rational Field 54 54 55 55 sage: G = GL(3, GF(7)) 56 56 sage: ZG = GroupAlgebra(G) -
sage/categories/finite_groups.py
diff --git a/sage/categories/finite_groups.py b/sage/categories/finite_groups.py
a b 82 82 83 83 sage: A = AlternatingGroup(4) 84 84 sage: A.semigroup_generators() 85 Family (( 1,2,3), (2,3,4))85 Family ((2,3,4), (1,2,3)) 86 86 """ 87 87 return self.group_generators() 88 88 -
sage/categories/g_sets.py
diff --git a/sage/categories/g_sets.py b/sage/categories/g_sets.py
a b 25 25 26 26 sage: S = SymmetricGroup(3) 27 27 sage: GSets(S) 28 Category of G-sets for Symmetric Group(3)28 Category of G-sets for Symmetric group of order 3! as a permutation group 29 29 30 30 TODO: should this derive from Category_over_base? 31 31 """ … … 44 44 EXAMPLES:: 45 45 46 46 sage: GSets(SymmetricGroup(8)) # indirect doctests 47 Category of G-sets for Symmetric Group(8)47 Category of G-sets for Symmetric group of order 8! as a permutation group 48 48 """ 49 49 return "G-sets for %s"%self.__G 50 50 … … 70 70 EXAMPLES:: 71 71 72 72 sage: GSets.an_instance() # indirect doctest 73 Category of G-sets for Symmetric Group(8)73 Category of G-sets for Symmetric group of order 8! as a permutation group 74 74 """ 75 75 from sage.groups.perm_gps.permgroup_named import SymmetricGroup 76 76 G = SymmetricGroup(8) -
sage/categories/groupoid.py
diff --git a/sage/categories/groupoid.py b/sage/categories/groupoid.py
a b 50 50 51 51 sage: S8 = SymmetricGroup(8) 52 52 sage: Groupoid(S8) 53 Groupoid with underlying set Symmetric Group(8)53 Groupoid with underlying set Symmetric group of order 8! as a permutation group 54 54 """ 55 55 return "Groupoid with underlying set %s"%self.__G 56 56 … … 76 76 EXAMPLES:: 77 77 78 78 sage: Groupoid.an_instance() # indirect doctest 79 Groupoid with underlying set Symmetric Group(8)79 Groupoid with underlying set Symmetric group of order 8! as a permutation group 80 80 """ 81 81 from sage.groups.perm_gps.permgroup_named import SymmetricGroup 82 82 G = SymmetricGroup(8) -
sage/categories/groups.py
diff --git a/sage/categories/groups.py b/sage/categories/groups.py
a b 68 68 69 69 sage: A = AlternatingGroup(4) 70 70 sage: A.group_generators() 71 Family (( 1,2,3), (2,3,4))71 Family ((2,3,4), (1,2,3)) 72 72 """ 73 73 return Family(self.gens()) 74 74 -
sage/categories/homset.py
diff --git a/sage/categories/homset.py b/sage/categories/homset.py
a b 61 61 Category of vector spaces over Rational Field 62 62 sage: G = AlternatingGroup(3) 63 63 sage: Hom(G, G) 64 Set of Morphisms from Alternating Group(3) to AlternatingGroup(3)in Category of finite permutation groups64 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 65 65 sage: Hom(ZZ, QQ, Sets()) 66 66 Set of Morphisms from Integer Ring to Rational Field in Category of sets 67 67 … … 235 235 236 236 sage: G = AlternatingGroup(3) 237 237 sage: S = End(G); S 238 Set of Morphisms from Alternating Group(3) to AlternatingGroup(3)in Category of finite permutation groups238 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 239 239 sage: from sage.categories.homset import is_Endset 240 240 sage: is_Endset(S) 241 241 True … … 400 400 sage: phi = Hom(SymmetricGroup(5), SymmetricGroup(6)).natural_map() 401 401 sage: phi 402 402 Coercion morphism: 403 From: Symmetric Group(5)404 To: Symmetric Group(6)403 From: Symmetric group of order 5! as a permutation group 404 To: Symmetric group of order 6! as a permutation group 405 405 sage: H(phi) 406 406 Composite map: 407 From: Symmetric Group(4)408 To: Symmetric Group(7)407 From: Symmetric group of order 4! as a permutation group 408 To: Symmetric group of order 7! as a permutation group 409 409 Defn: Composite map: 410 From: Symmetric Group(4)411 To: Symmetric Group(6)410 From: Symmetric group of order 4! as a permutation group 411 To: Symmetric group of order 6! as a permutation group 412 412 Defn: Call morphism: 413 From: Symmetric Group(4)414 To: Symmetric Group(5)413 From: Symmetric group of order 4! as a permutation group 414 To: Symmetric group of order 5! as a permutation group 415 415 then 416 416 Coercion morphism: 417 From: Symmetric Group(5)418 To: Symmetric Group(6)417 From: Symmetric group of order 5! as a permutation group 418 To: Symmetric group of order 6! as a permutation group 419 419 then 420 420 Call morphism: 421 From: Symmetric Group(6)422 To: Symmetric Group(7)421 From: Symmetric group of order 6! as a permutation group 422 To: Symmetric group of order 7! as a permutation group 423 423 424 424 sage: H = Hom(ZZ, ZZ, Sets()) 425 425 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 123 123 An other group can be specified as optional argument:: 124 124 125 125 sage: HopfAlgebrasWithBasis(QQ).example(SymmetricGroup(4)) 126 An example of Hopf algebra with basis: the group algebra of the Symmetric Group(4)over Rational Field126 An example of Hopf algebra with basis: the group algebra of the Symmetric group of order 4! as a permutation group over Rational Field 127 127 """ 128 128 from sage.categories.examples.hopf_algebras_with_basis import MyGroupAlgebra 129 129 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 115 115 sage: Map(QQ['x'], SymmetricGroup(6)) 116 116 Generic map: 117 117 From: Univariate Polynomial Ring in x over Rational Field 118 To: Symmetric Group(6)118 To: Symmetric group of order 6! as a permutation group 119 119 """ 120 120 if codomain is not None: 121 121 if PY_TYPE_CHECK(parent, type): -
sage/categories/pushout.py
diff --git a/sage/categories/pushout.py b/sage/categories/pushout.py
a b 2753 2753 2754 2754 rank = 10 2755 2755 2756 def __init__(self, gens ):2756 def __init__(self, gens, domain): 2757 2757 """ 2758 2758 EXAMPLES:: 2759 2759 2760 2760 sage: from sage.categories.pushout import PermutationGroupFunctor 2761 sage: PF = PermutationGroupFunctor([PermutationGroupElement([(1,2)])] ); PF2761 sage: PF = PermutationGroupFunctor([PermutationGroupElement([(1,2)])], [1,2]); PF 2762 2762 PermutationGroupFunctor[(1,2)] 2763 2763 """ 2764 2764 Functor.__init__(self, Groups(), Groups()) 2765 2765 self._gens = gens 2766 self._domain = domain 2766 2767 2767 2768 def __repr__(self): 2768 2769 """ … … 2785 2786 Permutation Group with generators [(1,2)] 2786 2787 """ 2787 2788 from sage.groups.perm_gps.permgroup import PermutationGroup 2788 return PermutationGroup([g for g in (R.gens() + self.gens()) if not g.is_one()]) 2789 return PermutationGroup([g for g in (R.gens() + self.gens()) if not g.is_one()], 2790 domain=self._domain) 2789 2791 2790 2792 def gens(self): 2791 2793 """ … … 2813 2815 """ 2814 2816 if self.__class__ != other.__class__: 2815 2817 return None 2816 return PermutationGroupFunctor(self.gens() + other.gens()) 2818 from sage.sets.all import FiniteEnumeratedSet 2819 2820 new_domain = set(self._domain).union(set(other._domain)) 2821 new_domain = FiniteEnumeratedSet(sorted(new_domain)) 2822 return PermutationGroupFunctor(self.gens() + other.gens(), 2823 new_domain) 2817 2824 2818 2825 class BlackBoxConstructionFunctor(ConstructionFunctor): 2819 2826 """ -
sage/combinat/permutation.py
diff --git a/sage/combinat/permutation.py b/sage/combinat/permutation.py
a b 561 561 cycles.append(tuple(cycle)) 562 562 return cycles 563 563 564 cycle_tuples = to_cycles 565 564 566 def _to_cycles_orig(self, singletons=True): 565 567 r""" 566 568 Returns the permutation p as a list of disjoint cycles. … … 3422 3424 3423 3425 p = range(1,n+1) 3424 3426 for cycle in cycles: 3427 if not cycle: 3428 continue 3425 3429 first = cycle[0] 3426 3430 for i in range(len(cycle)-1): 3427 3431 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 100 100 sage: [a.transport(perm) for perm in a.automorphism_group()] 101 101 [(1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4)] 102 102 """ 103 from sage.groups.all import SymmetricGroup 103 from sage.groups.all import SymmetricGroup, PermutationGroup 104 104 S = SymmetricGroup(len(self._labels)) 105 105 p = self.permutation_group_element() 106 return S.centralizer(p)106 return PermutationGroup(S.centralizer(p).gens()) 107 107 108 108 @accept_size 109 109 @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 98 98 ['a', 'c', 'b', 'd'], 99 99 ['a', 'c', 'b', 'd']] 100 100 """ 101 from sage.groups.all import SymmetricGroup 101 from sage.groups.all import SymmetricGroup, PermutationGroup 102 102 S = SymmetricGroup(len(self._labels)) 103 103 p = self.permutation_group_element() 104 return S.centralizer(p)104 return PermutationGroup(S.centralizer(p).gens()) 105 105 106 106 @accept_size 107 107 @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 828 828 sage: G = AbelianGroup(2,[2,3]); G 829 829 Multiplicative Abelian Group isomorphic to C2 x C3 830 830 sage: G.permutation_group() 831 Permutation Group with generators [(1, 4)(2,5)(3,6), (1,2,3)(4,5,6)]831 Permutation Group with generators [(1,2,3)(4,5,6), (1,4)(2,5)(3,6)] 832 832 """ 833 833 from sage.groups.perm_gps.permgroup import PermutationGroup 834 834 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 225 225 Multiplicative Abelian Group isomorphic to C2 x C3 x C4 226 226 sage: a,b,c=G.gens() 227 227 sage: Gp = G.permutation_group(); Gp 228 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)]228 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)] 229 229 sage: a.as_permutation() 230 230 (1,13)(2,14)(3,15)(4,16)(5,17)(6,18)(7,19)(8,20)(9,21)(10,22)(11,23)(12,24) 231 231 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 407 407 Character of Symmetric group of order 5! as a permutation group 408 408 sage: H = G.subgroup([(1,2,3), (1,2), (4,5)]) 409 409 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)] 411 411 sage: chi.restrict(H).values() 412 412 [3, -3, -3, -1, 0, 0] 413 413 """ … … 420 420 sage: G = SymmetricGroup(5) 421 421 sage: H = G.subgroup([(1,2,3), (1,2), (4,5)]) 422 422 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)] 424 424 sage: xi.induct(G) 425 425 Character of Symmetric group of order 5! as a permutation group 426 426 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 125 125 from sage.rings.all import QQ, Integer 126 126 from sage.interfaces.all import is_ExpectElement 127 127 from sage.interfaces.gap import gap, GapElement 128 from sage.groups.perm_gps.permgroup_element import PermutationGroupElement 128 from sage.groups.perm_gps.permgroup_element import PermutationGroupElement, standardize_generator 129 129 from sage.groups.abelian_gps.abelian_group import AbelianGroup 130 130 from sage.misc.cachefunc import cached_method 131 131 from sage.groups.class_function import ClassFunction 132 132 from sage.misc.package import is_package_installed 133 from sage.sets.finite_enumerated_set import FiniteEnumeratedSet 134 from sage.categories.all import FiniteEnumeratedSets 133 135 134 136 def load_hap(): 135 137 """ … … 231 233 srcs = map(G, srcs) 232 234 return srcs 233 235 234 def PermutationGroup(gens=None, gap_group=None, canonicalize=True):236 def PermutationGroup(gens=None, gap_group=None, domain=None, canonicalize=True, category=None): 235 237 """ 236 238 Return the permutation group associated to `x` (typically a 237 239 list of generators). … … 301 303 return gens._permgroup_() 302 304 if gens is not None and not isinstance(gens, (tuple, list, GapElement)): 303 305 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) 305 308 306 309 307 310 class PermutationGroup_generic(group.Group): … … 312 315 sage: G 313 316 Permutation Group with generators [(3,4), (1,2,3)(4,5)] 314 317 sage: G.center() 315 Permutation Group with generators[()]318 Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()] 316 319 sage: G.group_id() # optional - database_gap 317 320 [120, 34] 318 321 sage: n = G.order(); n … … 320 323 sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]]) 321 324 sage: TestSuite(G).run() 322 325 """ 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): 324 327 r""" 325 328 INPUT: 326 329 … … 347 350 sage: A4.__init__([[(1,2,3)],[(2,3,4)]]); A4 348 351 Permutation Group with generators [(2,3,4), (1,2,3)] 349 352 sage: A4.center() 350 Permutation Group with generators[()]353 Subgroup of (Permutation Group with generators [(2,3,4), (1,2,3)]) generated by [()] 351 354 sage: A4.category() 352 355 Category of finite permutation groups 353 356 sage: TestSuite(A4).run() … … 358 361 sage: TestSuite(PermutationGroup([])).run() 359 362 """ 360 363 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)) 362 365 if (gens is None and gap_group is None): 363 366 raise ValueError, "you must specify gens or gap_group" 364 367 365 368 #Handle the case where only the GAP group is specified. 366 369 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 383 402 384 403 def construction(self): 385 404 """ … … 400 419 (1,2,3) 401 420 sage: p.parent() 402 421 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') 403 434 """ 404 435 gens = self.gens() 405 436 if len(gens) == 1 and gens[0].is_one(): 406 437 return None 407 438 else: 408 439 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): 412 445 """ 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 415 448 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 422 458 """ 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 433 462 434 463 def _gap_init_(self): 435 464 r""" … … 445 474 sage: A4 = PermutationGroup([[(1,2,3)],[(2,3,4)]]); A4 446 475 Permutation Group with generators [(2,3,4), (1,2,3)] 447 476 sage: A4._gap_init_() 448 'Group([ (2,3,4), (1,2,3)])'477 'Group([PermList([1, 3, 4, 2]), PermList([2, 3, 1, 4])])' 449 478 """ 450 return self._gap_string479 return 'Group([%s])'%(', '.join([g._gap_init_() for g in self.gens()])) 451 480 452 481 def _magma_init_(self, magma): 453 482 r""" 454 483 Returns a string showing how to declare / initialize self in Magma. 455 484 456 485 EXAMPLES: 457 486 458 487 We explicitly construct the alternating group on four … … 463 492 Permutation Group with generators [(2,3,4), (1,2,3)] 464 493 sage: A4._magma_init_(magma) 465 494 '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)>' 466 499 """ 467 g = str(self.gens())[1:-1]500 g = ', '.join([g._gap_cycle_string() for g in self.gens()]) 468 501 return 'PermutationGroup<%s | %s>'%(self.degree(), g) 469 502 470 503 def __cmp__(self, right): … … 500 533 True 501 534 sage: H3 < H1 # since H3 is a subgroup of H1 502 535 True 503 504 536 """ 505 if not isinstance(right, PermutationGroup_generic): 537 if (not isinstance(right, PermutationGroup_generic) or 538 self.domain() != right.domain()): 506 539 return -1 507 540 if self is right: 508 541 return 0 … … 581 614 sage: G([(1,2)]) 582 615 Traceback (most recent call last): 583 616 ... 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)] 585 618 """ 586 619 try: 587 620 if x.parent() is self: … … 630 663 x_parent = x.parent() 631 664 if x_parent is self: 632 665 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) 636 670 raise TypeError, "no implicit coercion of element into permutation group" 637 671 638 672 @cached_method … … 645 679 sage: G = PermutationGroup([[(1,2,3,4)], [(1,2)]]) 646 680 sage: G.list() 647 681 [(), (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')] 648 687 """ 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__()) 654 689 655 690 def __contains__(self, item): 656 691 """ … … 671 706 True 672 707 sage: h in H 673 708 False 709 710 sage: G = PermutationGroup([[('a','b')]], domain=('a', 'b')) 711 sage: [('a', 'b')] in G 712 True 674 713 """ 675 714 try: 676 715 item = self(item, check=True) … … 709 748 sage: G = PermutationGroup([[(1,2,3)], [(1,2)]]) 710 749 sage: [a for a in G] 711 750 [(), (2,3), (1,2), (1,2,3), (1,3,2), (1,3)] 712 713 TODO: this currently returns an iterator over the elements of714 ``self.list()``. This should be made into a real iterator.715 751 """ 716 return iter(self.list()) 752 for g in self._gap_().Elements(): 753 yield self._element_class()(g, self, check=False) 717 754 718 755 def gens(self): 719 756 """ … … 769 806 sage: G = PermutationGroup([R,L,U,F,B,D]) 770 807 sage: len(G.gens_small()) 771 808 2 809 810 The output may be unpredictable, due to the use of randomized 811 algorithms in GAP. Note that both the following answers are equally valid. 812 813 :: 814 815 sage: G = PermutationGroup([[('a','b')], [('b', 'c')], [('a', 'c')]]) 816 sage: G.gens_small() # random 817 [('b','c'), ('a','c','b')] ## (on 64-bit Linux) 818 [('a','b'), ('a','c','b')] ## (on Solaris) 819 sage: len(G.gens_small()) == 2 820 True 772 821 """ 773 822 gens = self._gap_().SmallGeneratingSet() 774 823 return [self._element_class()(x, self, check=False) for x in gens] … … 825 874 (1,2,3)(4,5) 826 875 sage: e*g 827 876 (1,2,3)(4,5) 877 878 sage: S = SymmetricGroup(['a','b','c']) 879 sage: S.identity() 880 () 828 881 """ 829 882 return self._element_class()([], self, check=True) 830 883 … … 858 911 859 912 :: 860 913 861 sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]]) 914 sage: G = PermutationGroup([[('a','b','c'),('d','e')]]) 915 sage: G.largest_moved_point() 916 'e' 917 918 .. warning:: 919 920 The name of this function is not good; this function 921 should be deprecated in term of degree:: 922 923 sage: P = PermutationGroup([[1,2,3,4]]) 924 sage: P.largest_moved_point() 925 4 926 sage: P.cardinality() 927 1 928 """ 929 try: 930 return self._domain_from_gap[Integer(self._gap_().LargestMovedPoint())] 931 except KeyError: 932 return self.degree() 933 934 def degree(self): 935 """ 936 Returns the degree of this permutation group. 937 938 EXAMPLES:: 939 940 sage: S = SymmetricGroup(['a','b','c']) 941 sage: S.degree() 942 3 943 sage: G = PermutationGroup([(1,3),(4,5)]) 862 944 sage: G.degree() 863 945 5 864 946 865 TODO: the name of this function is not good; this function866 should be deprecated in term ofdegree::867 868 sage: P = PermutationGroup([[1,2,3,4]])869 sage: P.largest_moved_point()947 Note that you can explicitly specify the domain to get a 948 permutation group of smaller degree:: 949 950 sage: G = PermutationGroup([(1,3),(4,5)], domain=[1,3,4,5]) 951 sage: G.degree() 870 952 4 871 sage: P.cardinality()872 1873 953 """ 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): 954 return Integer(len(self._domain)) 955 956 def domain(self): 888 957 r""" 889 958 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. 959 on. 892 960 893 961 EXAMPLES:: 894 962 895 963 sage: P = PermutationGroup([(1,2),(3,5)]) 896 sage: P.set() 897 (1, 2, 3, 4, 5) 898 964 sage: P.domain() 965 {1, 2, 3, 4, 5} 966 sage: S = SymmetricGroup(['a', 'b', 'c']) 967 sage: S.domain() 968 {'a', 'b', 'c'} 899 969 """ 900 return tuple(self._set) 901 902 domain = set 903 904 def _set_gap(self): 970 return self._domain 971 972 def _domain_gap(self, domain=None): 905 973 """ 906 974 Returns a GAP string representation of the underlying set 907 that this group acts on. See also :meth:` set`.975 that this group acts on. See also :meth:`domain`. 908 976 909 977 EXAMPLES:: 910 978 911 979 sage: P = PermutationGroup([(1,2),(3,5)]) 912 sage: P._ set_gap()980 sage: P._domain_gap() 913 981 '[1, 2, 3, 4, 5]' 914 982 """ 915 return repr(list(self.set())) 983 if domain is None: 984 return repr(range(1, self.degree()+1)) 985 else: 986 try: 987 return repr([self._domain_to_gap[point] for point in domain]) 988 except KeyError: 989 raise ValueError, "domain must be a subdomain of self.domain()" 916 990 917 991 @cached_method 918 992 def smallest_moved_point(self): … … 927 1001 sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]]) 928 1002 sage: G.smallest_moved_point() 929 1003 1 1004 1005 Note that this function uses the ordering from the domain:: 1006 1007 sage: S = SymmetricGroup(['a','b','c']) 1008 sage: S.smallest_moved_point() 1009 'a' 930 1010 """ 931 return Integer(self._gap_().SmallestMovedPoint())1011 return self._domain_from_gap[Integer(self._gap_().SmallestMovedPoint())] 932 1012 933 1013 @cached_method 934 1014 def orbits(self): 935 1015 """ 936 Returns the orbits of [1,2,...,degree] under the group action. 1016 Returns the orbits of the elements of the domain under the 1017 group action. 937 1018 938 1019 EXAMPLES:: 939 1020 … … 943 1024 sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]]) 944 1025 sage: G.orbits() 945 1026 [[1, 2, 3, 4, 10], [5], [6], [7], [8], [9]] 1027 1028 sage: G = PermutationGroup([ [('c','d')], [('a','c')],[('b',)]]) 1029 sage: G.orbits() 1030 [['a', 'c', 'd'], ['b']] 946 1031 947 1032 The answer is cached:: 948 1033 … … 953 1038 954 1039 - Nathan Dunfield 955 1040 """ 956 return self._gap_().Orbits(self._set_gap()).sage() 1041 return [[self._domain_from_gap[x] for x in orbit] for orbit in 1042 self._gap_().Orbits(self._domain_gap()).sage()] 957 1043 958 1044 @cached_method 959 def orbit(self, integer):1045 def orbit(self, point): 960 1046 """ 961 Return the orbit of the given integerunder the group action.1047 Return the orbit of the given point under the group action. 962 1048 963 1049 EXAMPLES:: 964 1050 … … 968 1054 sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]]) 969 1055 sage: G.orbit(3) 970 1056 [3, 4, 10, 1, 2] 971 """ 972 return self._gap_().Orbit(integer).sage() 1057 1058 sage: G = PermutationGroup([ [('c','d')], [('a','c')] ]) 1059 sage: G.orbit('a') 1060 ['a', 'c', 'd'] 1061 """ 1062 point = self._domain_to_gap[point] 1063 return [self._domain_from_gap[x] for x in self._gap_().Orbit(point).sage()] 973 1064 974 def transversals(self, integer):1065 def transversals(self, point): 975 1066 """ 976 1067 If G is a permutation group acting on the set `X = \{1, 2, ...., n\}` 977 1068 and H is the stabilizer subgroup of <integer>, a right … … 988 1079 sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]]) 989 1080 sage: G.transversals(1) 990 1081 [(), (1,2)(3,4), (1,3,2,10,4), (1,4,2,10,3), (1,10,4,3,2)] 1082 1083 sage: G = PermutationGroup([ [('c','d')], [('a','c')] ]) 1084 sage: G.transversals('a') 1085 [(), ('a','c','d'), ('a','d','c')] 991 1086 """ 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): 1087 G = self._gap_() 1088 return [self(G.RepresentativeAction(self._domain_to_gap[point], self._domain_to_gap[i])) 1089 for i in self.orbit(point)] 1090 1091 def stabilizer(self, point): 998 1092 """ 999 1093 Return the subgroup of ``self`` which stabilize the given position. 1000 1094 ``self`` and its stabilizers must have same degree. … … 1003 1097 1004 1098 sage: G = PermutationGroup([ [(3,4)], [(1,3)] ]) 1005 1099 sage: G.stabilizer(1) 1006 Permutation Group with generators[(3,4)]1100 Subgroup of (Permutation Group with generators [(3,4), (1,3)]) generated by [(3,4)] 1007 1101 sage: G.stabilizer(3) 1008 Permutation Group with generators[(1,4)]1102 Subgroup of (Permutation Group with generators [(3,4), (1,3)]) generated by [(1,4)] 1009 1103 sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4,10)]]) 1010 1104 sage: G.stabilizer(10) 1011 Permutation Group with generators [(1,2)(3,4), (2,3,4)]1105 Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4,10)]) generated by [(2,3,4), (1,2)(3,4)] 1012 1106 sage: G.stabilizer(1) 1013 Permutation Group with generators[(2,3)(4,10), (2,10,4)]1107 Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4,10)]) generated by [(2,3)(4,10), (2,10,4)] 1014 1108 sage: G = PermutationGroup([[(2,3,4)],[(6,7)]]) 1015 1109 sage: G.stabilizer(1) 1016 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)] 1017 1111 sage: G.stabilizer(2) 1018 Permutation Group with generators[(6,7)]1112 Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7)] 1019 1113 sage: G.stabilizer(3) 1020 Permutation Group with generators[(6,7)]1114 Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7)] 1021 1115 sage: G.stabilizer(4) 1022 Permutation Group with generators[(6,7)]1116 Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7)] 1023 1117 sage: G.stabilizer(5) 1024 Permutation Group with generators[(6,7), (2,3,4)]1118 Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7), (2,3,4)] 1025 1119 sage: G.stabilizer(6) 1026 Permutation Group with generators[(2,3,4)]1120 Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(2,3,4)] 1027 1121 sage: G.stabilizer(7) 1028 Permutation Group with generators[(2,3,4)]1122 Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(2,3,4)] 1029 1123 sage: G.stabilizer(8) 1030 Permutation Group with generators[(6,7), (2,3,4)]1124 Subgroup of (Permutation Group with generators [(6,7), (2,3,4)]) generated by [(6,7), (2,3,4)] 1031 1125 """ 1032 return PermutationGroup(gap_group=gap.Stabilizer(self, position)) 1033 1034 def strong_generating_system(self, base_of_group = None): 1126 try: 1127 position = self._domain_to_gap[point] 1128 except KeyError: 1129 return self.subgroup(gens=self.gens()) 1130 return self.subgroup(gap_group=gap.Stabilizer(self, point)) 1131 1132 def strong_generating_system(self, base_of_group=None): 1035 1133 """ 1036 1134 Return a Strong Generating System of ``self`` according the given 1037 1135 base for the right action of ``self`` on itself. … … 1080 1178 [[(), (1,2)(3,4), (1,3)(2,4), (1,4)(2,3)], [(), (2,3,4), (2,4,3)], [(), (3,4)], [()]] 1081 1179 sage: G = PermutationGroup([[(1,2,3)],[(4,5,7)],[(1,4,6)]]) 1082 1180 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)], [()], [()]]1181 [[(), (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)], [()], [()]] 1084 1182 sage: G = PermutationGroup([[(1,2,3)],[(2,3,4)],[(3,4,5)]]) 1085 1183 sage: G.strong_generating_system([5,4,3,2,1]) 1086 1184 [[(), (1,5,3,4,2), (1,5,4,3,2), (1,5)(2,3), (1,5,2)], [(), (1,3)(2,4), (1,2)(3,4), (1,4)(2,3)], [(), (1,3,2), (1,2,3)], [()], [()]] … … 1096 1194 sgs = [] 1097 1195 stab = self 1098 1196 if base_of_group is None: 1099 base_of_group = self. set()1197 base_of_group = self.domain() 1100 1198 for j in base_of_group: 1101 1199 sgs.append(stab.transversals(j)) 1102 1200 stab = stab.stabilizer(j) … … 1140 1238 \langle (2,3,4), (1,2,3) \rangle 1141 1239 sage: A4._latex_() 1142 1240 '\\langle (2,3,4), (1,2,3) \\rangle' 1241 1242 sage: S = SymmetricGroup(['a','b','c']) 1243 sage: latex(S) 1244 \langle (\verb|a|,\verb|b|,\verb|c|), (\verb|a|,\verb|b|) \rangle 1143 1245 """ 1144 1246 return '\\langle ' + \ 1145 1247 ', '.join([x._latex_() for x in self.gens()]) + ' \\rangle' … … 1218 1320 1219 1321 sage: G = PermutationGroup([[(1,2,3,4)]]) 1220 1322 sage: G.center() 1221 Permutation Group with generators[(1,2,3,4)]1323 Subgroup of (Permutation Group with generators [(1,2,3,4)]) generated by [(1,2,3,4)] 1222 1324 sage: G = PermutationGroup([[(1,2,3,4)], [(1,2)]]) 1223 1325 sage: G.center() 1224 Permutation Group with generators[()]1326 Subgroup of (Permutation Group with generators [(1,2), (1,2,3,4)]) generated by [()] 1225 1327 """ 1226 return PermutationGroup(gap_group=self._gap_().Center()) 1328 return self.subgroup(gap_group=self._gap_().Center()) 1329 1330 def socle(self): 1331 r""" 1332 Returns the socle of ``self``. The socle of a group $G$ is 1333 the subgroup generated by all minimal normal subgroups. 1334 1335 EXAMPLES:: 1336 1337 sage: G=SymmetricGroup(4) 1338 sage: G.socle() 1339 Subgroup of (Symmetric group of order 4! as a permutation group) generated by [(1,2)(3,4), (1,4)(2,3)] 1340 sage: G.socle().socle() 1341 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)] 1342 1343 """ 1344 return self.subgroup(gap_group=self._gap_().Socle()) 1345 1346 def frattini_subgroup(self): 1347 r""" 1348 Returns the Frattini subgroup of ``self``. The Frattini 1349 subgroup of a group $G$ is the intersection of all 1350 maximal subgroups of $G$. 1351 1352 EXAMPLES:: 1353 1354 sage: G=PermutationGroup([[(1,2,3,4)],[(2,4)]]) 1355 sage: G.frattini_subgroup() 1356 Subgroup of (Permutation Group with generators [(2,4), (1,2,3,4)]) generated by [(1,3)(2,4)] 1357 sage: G=SymmetricGroup(4) 1358 sage: G.frattini_subgroup() 1359 Subgroup of (Symmetric group of order 4! as a permutation group) generated by [()] 1360 1361 """ 1362 return self.subgroup(gap_group=self._gap_().FrattiniSubgroup()) 1363 1364 def fitting_subgroup(self): 1365 r""" 1366 Returns the Fitting subgroup of ``self``. The Fitting 1367 subgroup of a group $G$ is the largest nilpotent normal 1368 subgroup of $G$. 1369 1370 EXAMPLES:: 1371 1372 sage: G=PermutationGroup([[(1,2,3,4)],[(2,4)]]) 1373 sage: G.fitting_subgroup() 1374 Subgroup of (Permutation Group with generators [(2,4), (1,2,3,4)]) generated by [(2,4), (1,2,3,4), (1,3)] 1375 sage: G=PermutationGroup([[(1,2,3,4)],[(1,2)]]) 1376 sage: G.fitting_subgroup() 1377 Subgroup of (Permutation Group with generators [(1,2), (1,2,3,4)]) generated by [(1,2)(3,4), (1,3)(2,4)] 1378 1379 """ 1380 return self.subgroup(gap_group=self._gap_().FittingSubgroup()) 1381 1382 def solvable_radical(self): 1383 r""" 1384 Returns the solvable radical of ``self``. The solvable 1385 radical (or just radical) of a group $G$ is the largest 1386 solvable normal subgroup of $G$. 1387 1388 EXAMPLES:: 1389 1390 sage: G=SymmetricGroup(4) 1391 sage: G.solvable_radical() 1392 Subgroup of (Symmetric group of order 4! as a permutation group) generated by [(1,2), (1,2,3,4)] 1393 sage: G=SymmetricGroup(5) 1394 sage: G.solvable_radical() 1395 Subgroup of (Symmetric group of order 5! as a permutation group) generated by [()] 1396 1397 """ 1398 return self.subgroup(gap_group=self._gap_().RadicalGroup()) 1227 1399 1228 1400 def intersection(self, other): 1229 1401 r""" … … 1310 1482 sage: G = DihedralGroup(6) 1311 1483 sage: a = PermutationGroupElement("(1,2,3,4)") 1312 1484 sage: G.conjugate(a) 1313 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)] 1314 1486 1315 1487 The element performing the conjugation can be specified in 1316 1488 several ways. :: … … 1318 1490 sage: G = DihedralGroup(6) 1319 1491 sage: strng = "(1,2,3,4)" 1320 1492 sage: G.conjugate(strng) 1321 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)] 1322 1494 sage: G = DihedralGroup(6) 1323 1495 sage: lst = [2,3,4,1] 1324 1496 sage: G.conjugate(lst) 1325 Permutation Group with generators [(1, 5,6,2,3,4), (1,4)(2,6)(3,5)]1497 Permutation Group with generators [(1,4)(2,6)(3,5), (1,5,6,2,3,4)] 1326 1498 sage: G = DihedralGroup(6) 1327 1499 sage: cycles = [(1,2,3,4)] 1328 1500 sage: G.conjugate(cycles) 1329 Permutation Group with generators [(1, 5,6,2,3,4), (1,4)(2,6)(3,5)]1501 Permutation Group with generators [(1,4)(2,6)(3,5), (1,5,6,2,3,4)] 1330 1502 1331 1503 Conjugation is a group automorphism, so conjugate groups 1332 1504 will be isomorphic. :: … … 1379 1551 1380 1552 INPUT: 1381 1553 1382 1383 1554 - ``self, other`` - permutation groups 1384 1555 1385 1386 1387 1556 OUTPUT: 1388 1557 1389 1390 1558 - ``D`` - a direct product of the inputs, returned as 1391 1559 a permutation group as well 1392 1560 … … 1400 1568 - ``pr2`` - the projection of ``D`` onto ``other`` (giving a 1401 1569 splitting 1 - self - D - other - 1) 1402 1570 1403 1404 1571 EXAMPLES:: 1405 1572 1406 1573 sage: G = CyclicPermutationGroup(4) 1407 1574 sage: D = G.direct_product(G,False) 1408 1575 sage: D 1409 Permutation Group with generators [( 1,2,3,4), (5,6,7,8)]1576 Permutation Group with generators [(5,6,7,8), (1,2,3,4)] 1410 1577 sage: D,iota1,iota2,pr1,pr2 = G.direct_product(G) 1411 1578 sage: D; iota1; iota2; pr1; pr2 1412 Permutation Group with generators [( 1,2,3,4), (5,6,7,8)]1579 Permutation Group with generators [(5,6,7,8), (1,2,3,4)] 1413 1580 Permutation group morphism: 1414 1581 From: Cyclic group of order 4 as a permutation group 1415 To: Permutation Group with generators [( 1,2,3,4), (5,6,7,8)]1582 To: Permutation Group with generators [(5,6,7,8), (1,2,3,4)] 1416 1583 Defn: Embedding( Group( [ (1,2,3,4), (5,6,7,8) ] ), 1 ) 1417 1584 Permutation group morphism: 1418 1585 From: Cyclic group of order 4 as a permutation group 1419 To: Permutation Group with generators [( 1,2,3,4), (5,6,7,8)]1586 To: Permutation Group with generators [(5,6,7,8), (1,2,3,4)] 1420 1587 Defn: Embedding( Group( [ (1,2,3,4), (5,6,7,8) ] ), 2 ) 1421 1588 Permutation group morphism: 1422 From: Permutation Group with generators [( 1,2,3,4), (5,6,7,8)]1589 From: Permutation Group with generators [(5,6,7,8), (1,2,3,4)] 1423 1590 To: Cyclic group of order 4 as a permutation group 1424 1591 Defn: Projection( Group( [ (1,2,3,4), (5,6,7,8) ] ), 1 ) 1425 1592 Permutation group morphism: 1426 From: Permutation Group with generators [( 1,2,3,4), (5,6,7,8)]1593 From: Permutation Group with generators [(5,6,7,8), (1,2,3,4)] 1427 1594 To: Cyclic group of order 4 as a permutation group 1428 1595 Defn: Projection( Group( [ (1,2,3,4), (5,6,7,8) ] ), 2 ) 1429 1596 sage: g=D([(1,3),(2,4)]); g … … 1436 1603 (1,4,3,2) 1437 1604 (1,3)(2,4) 1438 1605 """ 1439 G = self._gap_().DirectProduct(other ._gap_())1606 G = self._gap_().DirectProduct(other) 1440 1607 D = PermutationGroup(gap_group=G) 1441 1608 if not maps: 1442 1609 return D … … 1448 1615 pr2 = PermutationGroupMorphism_from_gap(D, other, G.Projection(2)) 1449 1616 return D, iota1, iota2, pr1, pr2 1450 1617 1451 def subgroup(self, gens ):1618 def subgroup(self, gens=None, gap_group=None, domain=None, category=None, canonicalize=True, check=True): 1452 1619 """ 1453 1620 Wraps the ``PermutationGroup_subgroup`` constructor. The argument 1454 1621 ``gens`` is a list of elements of ``self``. … … 1458 1625 sage: G = PermutationGroup([(1,2,3),(3,4,5)]) 1459 1626 sage: g = G((1,2,3)) 1460 1627 sage: G.subgroup([g]) 1461 Subgroup of Permutation Group with generators [(3,4,5), (1,2,3)]generated by [(1,2,3)]1628 Subgroup of (Permutation Group with generators [(3,4,5), (1,2,3)]) generated by [(1,2,3)] 1462 1629 """ 1463 return PermutationGroup_subgroup(self, gens )1464 1630 return PermutationGroup_subgroup(self, gens=gens, gap_group=gap_group, domain=None, 1631 category=category, canonicalize=canonicalize, check=check) 1465 1632 1466 1633 def quotient(self, N): 1467 1634 """ … … 1484 1651 # This is currently done using the right regular representation 1485 1652 # FIXME: GAP certainly knows of a better way! 1486 1653 phi = Q.RegularActionHomomorphism() 1487 return PermutationGroup(gap_group =phi.Image())1654 return PermutationGroup(gap_group=phi.Image()) 1488 1655 1489 1656 def quotient_group(self, N): 1490 1657 """ … … 1921 2088 sage: G = SymmetricGroup(5) 1922 2089 sage: G.conjugacy_classes_representatives() 1923 2090 [(), (1,2), (1,2)(3,4), (1,2,3), (1,2,3)(4,5), (1,2,3,4), (1,2,3,4,5)] 1924 2091 2092 :: 2093 2094 sage: S = SymmetricGroup(['a','b','c']) 2095 sage: S.conjugacy_classes_representatives() 2096 [(), ('a','b'), ('a','b','c')] 2097 1925 2098 AUTHORS: 1926 2099 1927 2100 - David Joyner and William Stein (2006-01-04) … … 1940 2113 sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]]) 1941 2114 sage: cl = G.conjugacy_classes_subgroups() 1942 2115 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)]] 2116 [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)]] 1951 2117 1952 2118 :: 1953 2119 1954 2120 sage: G = SymmetricGroup(3) 1955 2121 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)]] 2122 [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)]] 1960 2123 1961 2124 AUTHORS: 1962 2125 1963 2126 - David Joyner (2006-10) 1964 2127 """ 1965 2128 cl = self._gap_().ConjugacyClassesSubgroups() 1966 return [ PermutationGroup(gap_group=sub.Representative()) for sub in cl]2129 return [self.subgroup(gap_group=sub.Representative()) for sub in cl] 1967 2130 1968 2131 def subgroups(self): 1969 2132 r""" … … 1990 2153 `30030 = 2\cdot 3\cdot 5\cdot 7\cdot 11\cdot 13` takes 1991 2154 about twice as long. 1992 2155 1993 For faster results, which still exhibit the structure of the possible subgroups, use :meth:`conjugacy_classes_subgroups`. 2156 For faster results, which still exhibit the structure of 2157 the possible subgroups, use 2158 :meth:`conjugacy_classes_subgroups`. 1994 2159 1995 2160 EXAMPLES:: 1996 2161 … … 2001 2166 Permutation Group with generators [(1,2)], 2002 2167 Permutation Group with generators [(1,3)], 2003 2168 Permutation Group with generators [(1,2,3)], 2004 Permutation Group with generators [(1, 3,2), (1,2)]]2169 Permutation Group with generators [(1,2), (1,3,2)]] 2005 2170 2006 2171 sage: G = CyclicPermutationGroup(14) 2007 2172 sage: G.subgroups() … … 2160 2325 sage: A.cosets(S) 2161 2326 Traceback (most recent call last): 2162 2327 ... 2163 ValueError: Subgroup of SymmetricGroup(3) generated by [(1,2)] is not a subgroup of AlternatingGroup(3)2328 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 2164 2329 2165 2330 AUTHOR: 2166 2331 … … 2201 2366 sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]]) 2202 2367 sage: g = G([(1,3)]) 2203 2368 sage: G.normalizer(g) 2204 Permutation Group with generators[(2,4), (1,3)]2369 Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(2,4), (1,3)] 2205 2370 sage: g = G([(1,2,3,4)]) 2206 2371 sage: G.normalizer(g) 2207 Permutation Group with generators[(2,4), (1,2,3,4), (1,3)(2,4)]2372 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)] 2208 2373 sage: H = G.subgroup([G([(1,2,3,4)])]) 2209 2374 sage: G.normalizer(H) 2210 Permutation Group with generators[(2,4), (1,2,3,4), (1,3)(2,4)]2375 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)] 2211 2376 """ 2212 N = self._gap_().Normalizer(g) 2213 return PermutationGroup(N.GeneratorsOfGroup()) 2377 return self.subgroup(gap_group=self._gap_().Normalizer(g)) 2214 2378 2215 2379 def centralizer(self, g): 2216 2380 """ … … 2221 2385 sage: G = PermutationGroup([[(1,2),(3,4)], [(1,2,3,4)]]) 2222 2386 sage: g = G([(1,3)]) 2223 2387 sage: G.centralizer(g) 2224 Permutation Group with generators[(2,4), (1,3)]2388 Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(2,4), (1,3)] 2225 2389 sage: g = G([(1,2,3,4)]) 2226 2390 sage: G.centralizer(g) 2227 Permutation Group with generators[(1,2,3,4)]2391 Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(1,2,3,4)] 2228 2392 sage: H = G.subgroup([G([(1,2,3,4)])]) 2229 2393 sage: G.centralizer(H) 2230 Permutation Group with generators[(1,2,3,4)]2394 Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(1,2,3,4)] 2231 2395 """ 2232 N = self._gap_().Centralizer(g) 2233 return PermutationGroup(N.GeneratorsOfGroup()) 2396 return self.subgroup(gap_group=self._gap_().Centralizer(g)) 2234 2397 2235 2398 def isomorphism_type_info_simple_group(self): 2236 2399 """ … … 2454 2617 """ 2455 2618 if not(self.is_subgroup(other)): 2456 2619 raise TypeError("%s must be a subgroup of %s"%(self, other)) 2457 return other._gap_().IsNormal(self ._gap_()).bool()2620 return other._gap_().IsNormal(self).bool() 2458 2621 2459 2622 def is_perfect(self): 2460 2623 """ … … 2540 2703 sage: G.is_subgroup(H) 2541 2704 True 2542 2705 """ 2543 G = other 2544 gens = self.gens() 2545 for i in range(len(gens)): 2546 x = gens[i] 2547 if not (x in G): 2548 return False 2549 return True 2706 return all((x in other) for x in self.gens()) 2550 2707 2551 2708 def is_supersolvable(self): 2552 2709 """ … … 2561 2718 """ 2562 2719 return self._gap_().IsSupersolvableGroup().bool() 2563 2720 2564 def is_transitive(self): 2721 def non_fixed_points(self): 2722 r""" 2723 Returns the list of points not fixed by ``self``, i.e., the subset 2724 of ``self.domain()`` moved by some element of ``self``. 2725 2726 EXAMPLES:: 2727 2728 sage: G = PermutationGroup([[(3,4,5)],[(7,10)]]) 2729 sage: G.non_fixed_points() 2730 [3, 4, 5, 7, 10] 2731 sage: G = PermutationGroup([[(2,3,6)],[(9,)]]) # note: 9 is fixed 2732 sage: G.non_fixed_points() 2733 [2, 3, 6] 2565 2734 """ 2566 Return ``True`` if ``self`` is a transitive group, i.e., if the action 2567 of self on [1..n] is transitive. 2735 pnts = set() 2736 for gens in self.gens(): 2737 for cycles in gens.cycle_tuples(): 2738 for thispnt in cycles: 2739 if thispnt not in pnts: 2740 pnts.add(thispnt) 2741 return sorted(pnts) 2568 2742 2743 def fixed_points(self): 2744 r""" 2745 Returns the list of points fixed by ``self``, i.e., the subset 2746 of ``.domain()`` not moved by any element of ``self``. 2747 2748 EXAMPLES:: 2749 2750 sage: G=PermutationGroup([(1,2,3)]) 2751 sage: G.fixed_points() 2752 [] 2753 sage: G=PermutationGroup([(1,2,3),(5,6)]) 2754 sage: G.fixed_points() 2755 [4] 2756 sage: G=PermutationGroup([[(1,4,7)],[(4,3),(6,7)]]) 2757 sage: G.fixed_points() 2758 [2, 5] 2759 """ 2760 non_fixed_points = self.non_fixed_points() 2761 return [i for i in self.domain() if i not in non_fixed_points] 2762 2763 def is_transitive(self, domain=None): 2764 """ 2765 Returns ``True`` if ``self`` acts transitively on ``domain``. 2766 A group $G$ acts transitively on set $S$ if for all $x,y\in S$ 2767 there is some $g\in G$ such that $x^g=y$. 2768 2569 2769 EXAMPLES:: 2570 2770 2571 2771 sage: G = SymmetricGroup(5) … … 2575 2775 sage: G.is_transitive() 2576 2776 False 2577 2777 2778 :: 2779 2780 sage: G = PermutationGroup([[(1,2,3,4,5)],[(1,2)]]) #S_5 on [1..5] 2781 sage: G.is_transitive([1,4,5]) 2782 True 2783 sage: G.is_transitive([2..6]) 2784 False 2785 sage: G.is_transitive(G.non_fixed_points()) 2786 True 2787 sage: H = PermutationGroup([[(1,2,3)],[(4,5,6)]]) 2788 sage: H.is_transitive(H.non_fixed_points()) 2789 False 2790 2578 2791 Note that this differs from the definition in GAP, where 2579 2792 ``IsTransitive`` returns whether the group is transitive on the 2580 2793 set of points moved by the group. … … 2587 2800 sage: gap(G).IsTransitive() 2588 2801 true 2589 2802 """ 2590 return self._gap_().IsTransitive(self._set_gap()).bool() 2591 2803 #If the domain is not a subset of self.domain(), then the 2804 #action isn't transitive. 2805 try: 2806 domain = self._domain_gap(domain) 2807 except ValueError: 2808 return False 2809 2810 return self._gap_().IsTransitive(domain).bool() 2811 2812 2813 def is_primitive(self, domain=None): 2814 r""" 2815 Returns ``True`` if ``self`` acts primitively on ``domain``. 2816 A group $G$ acts primitively on a set $S$ if 2817 2818 1. $G$ acts transitively on $S$ and 2819 2820 2. the action induces no non-trivial block system on $S$. 2821 2822 INPUT: 2823 2824 - ``domain`` (optional) 2825 2826 EXAMPLES: 2827 2828 By default, test for primitivity of ``self`` on its domain. 2829 2830 sage: G = PermutationGroup([[(1,2,3,4)],[(1,2)]]) 2831 sage: G.is_primitive() 2832 True 2833 sage: G = PermutationGroup([[(1,2,3,4)],[(2,4)]]) 2834 sage: G.is_primitive() 2835 False 2836 2837 You can specify a domain on which to test primitivity:: 2838 2839 sage: G = PermutationGroup([[(1,2,3,4)],[(2,4)]]) 2840 sage: G.is_primitive([1..4]) 2841 False 2842 sage: G.is_primitive([1,2,3]) 2843 True 2844 sage: G = PermutationGroup([[(3,4,5,6)],[(3,4)]]) #S_4 on [3..6] 2845 sage: G.is_primitive(G.non_fixed_points()) 2846 True 2847 2848 """ 2849 #If the domain is not a subset of self.domain(), then the 2850 #action isn't primitive. 2851 try: 2852 domain = self._domain_gap(domain) 2853 except ValueError: 2854 return False 2855 2856 return self._gap_().IsPrimitive(domain).bool() 2857 2858 def is_semi_regular(self, domain=None): 2859 r""" 2860 Returns ``True`` if ``self`` acts semi-regularly on ``domain``. 2861 A group $G$ acts semi-regularly on a set $S$ if the point 2862 stabilizers of $S$ in $G$ are trivial. 2863 2864 ``domain`` is optional and may take several forms. See examples. 2865 2866 EXAMPLES:: 2867 2868 sage: G = PermutationGroup([[(1,2,3,4)]]) 2869 sage: G.is_semi_regular() 2870 True 2871 sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]]) 2872 sage: G.is_semi_regular() 2873 False 2874 2875 You can pass in a domain to test semi-regularity:: 2876 2877 sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]]) 2878 sage: G.is_semi_regular([1..4]) 2879 True 2880 sage: G.is_semi_regular(G.non_fixed_points()) 2881 False 2882 2883 """ 2884 try: 2885 domain = self._domain_gap(domain) 2886 except ValueError: 2887 return False 2888 return self._gap_().IsSemiRegular(domain).bool() 2889 2890 def is_regular(self, domain=None): 2891 r""" 2892 Returns ``True`` if ``self`` acts regularly on ``domain``. 2893 A group $G$ acts regularly on a set $S$ if 2894 2895 1. $G$ acts transitively on $S$ and 2896 2. $G$ acts semi-regularly on $S$. 2897 2898 EXAMPLES:: 2899 2900 sage: G = PermutationGroup([[(1,2,3,4)]]) 2901 sage: G.is_regular() 2902 True 2903 sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]]) 2904 sage: G.is_regular() 2905 False 2906 2907 You can pass in a domain on which to test regularity:: 2908 2909 sage: G = PermutationGroup([[(1,2,3,4)],[(5,6)]]) 2910 sage: G.is_regular([1..4]) 2911 True 2912 sage: G.is_regular(G.non_fixed_points()) 2913 False 2914 2915 """ 2916 try: 2917 domain = self._domain_gap(domain) 2918 except ValueError: 2919 return False 2920 return self._gap_().IsRegular(domain).bool() 2921 2922 2592 2923 def normalizes(self, other): 2593 2924 r""" 2594 2925 Returns ``True`` if the group ``other`` is normalized by ``self``. … … 2614 2945 In the last example, `G` and `H` are disjoint, so each normalizes the 2615 2946 other. 2616 2947 """ 2617 return self._gap_().IsNormal(other ._gap_()).bool()2948 return self._gap_().IsNormal(other).bool() 2618 2949 2619 2950 ############## Series ###################### 2620 2951 … … 2637 2968 sage: G = PermutationGroup([[(1,2,3),(4,5)], [(1,2)]]) 2638 2969 sage: CS = G.composition_series() 2639 2970 sage: CS[3] 2640 Permutation Group with generators[()]2971 Subgroup of (Permutation Group with generators [(1,2), (1,2,3)(4,5)]) generated by [()] 2641 2972 """ 2642 2973 current_randstate().set_seed_gap() 2643 2974 CS = self._gap_().CompositionSeries() 2644 return [ PermutationGroup(gap_group=group) for group in CS]2975 return [self.subgroup(gap_group=group) for group in CS] 2645 2976 2646 2977 def derived_series(self): 2647 2978 """ … … 2662 2993 """ 2663 2994 current_randstate().set_seed_gap() 2664 2995 DS = self._gap_().DerivedSeries() 2665 return [ PermutationGroup(gap_group=group) for group in DS]2996 return [self.subgroup(gap_group=group) for group in DS] 2666 2997 2667 2998 def lower_central_series(self): 2668 2999 """ … … 2683 3014 """ 2684 3015 current_randstate().set_seed_gap() 2685 3016 LCS = self._gap_().LowerCentralSeriesOfGroup() 2686 return [ PermutationGroup(gap_group=group) for group in LCS]3017 return [self.subgroup(gap_group=group) for group in LCS] 2687 3018 2688 3019 def molien_series(self): 2689 3020 r""" … … 2746 3077 True 2747 3078 """ 2748 3079 NS = self._gap_().NormalSubgroups() 2749 return [ PermutationGroup(gap_group=group) for group in NS]3080 return [self.subgroup(gap_group=group) for group in NS] 2750 3081 2751 3082 def poincare_series(self, p=2, n=10): 2752 3083 """ … … 2798 3129 2799 3130 sage: G = PermutationGroup(['(1,2,3)', '(2,3)']) 2800 3131 sage: G.sylow_subgroup(2) 2801 Permutation Group with generators[(2,3)]3132 Subgroup of (Permutation Group with generators [(2,3), (1,2,3)]) generated by [(2,3)] 2802 3133 sage: G.sylow_subgroup(5) 2803 Permutation Group with generators[()]3134 Subgroup of (Permutation Group with generators [(2,3), (1,2,3)]) generated by [()] 2804 3135 """ 2805 return PermutationGroup(gap_group=self._gap_().SylowSubgroup(p))3136 return self.subgroup(gap_group=self._gap_().SylowSubgroup(p)) 2806 3137 2807 3138 def upper_central_series(self): 2808 3139 """ … … 2816 3147 2817 3148 sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]]) 2818 3149 sage: G.upper_central_series() 2819 [ Permutation Group with generators[()]]3150 [Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()]] 2820 3151 """ 2821 3152 current_randstate().set_seed_gap() 2822 3153 UCS = self._gap_().UpperCentralSeriesOfGroup() 2823 return [ PermutationGroup(gap_group=group) for group in UCS]3154 return [self.subgroup(gap_group=group) for group in UCS] 2824 3155 2825 3156 class PermutationGroup_subgroup(PermutationGroup_generic): 2826 3157 """ … … 2832 3163 sage: G = CyclicPermutationGroup(4) 2833 3164 sage: gens = G.gens() 2834 3165 sage: H = DihedralGroup(4) 2835 sage: PermutationGroup_subgroup(H,list(gens))2836 Subgroup of Dihedral group of order 8 as a permutation groupgenerated by [(1,2,3,4)]2837 sage: K =PermutationGroup_subgroup(H,list(gens))3166 sage: H.subgroup(gens) 3167 Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)] 3168 sage: K = H.subgroup(gens) 2838 3169 sage: K.list() 2839 3170 [(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)] 2840 3171 sage: K.ambient_group() … … 2842 3173 sage: K.gens() 2843 3174 [(1,2,3,4)] 2844 3175 """ 2845 def __init__(self, ambient, gens, from_group = False, check=True, canonicalize=True): 3176 def __init__(self, ambient, gens=None, gap_group=None, domain=None, 3177 category=None, canonicalize=True, check=True): 2846 3178 r""" 2847 3179 Initialization method for the 2848 3180 ``PermutationGroup_subgroup`` class. … … 2872 3204 sage: H = CyclicPermutationGroup(4) 2873 3205 sage: gens = H.gens(); gens 2874 3206 [(1,2,3,4)] 2875 sage: S = PermutationGroup_subgroup(G,gens)3207 sage: S = G.subgroup(gens) 2876 3208 sage: S 2877 Subgroup of Dihedral group of order 8 as a permutation groupgenerated by [(1,2,3,4)]3209 Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)] 2878 3210 sage: S.list() 2879 3211 [(), (1,2,3,4), (1,3)(2,4), (1,4,3,2)] 2880 3212 sage: S.ambient_group() … … 2893 3225 """ 2894 3226 if not isinstance(ambient, PermutationGroup_generic): 2895 3227 raise TypeError, "ambient (=%s) must be perm group."%ambient 2896 if not isinstance(gens, list): 2897 raise TypeError, "gens (=%s) must be a list"%gens 2898 2899 self.__ambient_group = ambient 2900 self._gens = gens 2901 cmd = 'Group(%s)'%gens 2902 cmd = cmd.replace("'","") # get rid of quotes 2903 self._gap_string = cmd 2904 2905 G = ambient 3228 if domain is None: 3229 domain = ambient.domain() 3230 if category is None: 3231 category = ambient.category() 3232 PermutationGroup_generic.__init__(self, gens=gens, gap_group=gap_group, domain=domain, 3233 category=category, canonicalize=canonicalize) 3234 3235 self._ambient_group = ambient 2906 3236 if check: 2907 for g in gens:2908 if g not in G:3237 for g in self.gens(): 3238 if g not in ambient: 2909 3239 raise TypeError, "each generator must be in the ambient group" 2910 self.__ambient_group = G2911 2912 PermutationGroup_generic.__init__(self, gens, canonicalize=canonicalize)2913 3240 2914 3241 def __cmp__(self, other): 2915 3242 r""" 2916 3243 Compare ``self`` and ``other``. 2917 3244 2918 First, ``self`` and ``other`` are compared as permutation groups, see :method:`sage.groups.perm_gps.permgroup.PermutationGroup_generic.__cmp__`. 2919 Second, if both are equal, the ambient groups are compared, where (if necessary) 2920 ``other`` is considered a subgroup of itself. 3245 First, ``self`` and ``other`` are compared as permutation 3246 groups, see :method:`PermutationGroup_generic.__cmp__`. 3247 Second, if both are equal, the ambient groups are compared, 3248 where (if necessary) ``other`` is considered a subgroup of 3249 itself. 2921 3250 2922 3251 EXAMPLES:: 2923 3252 … … 2951 3280 sage: G 2952 3281 Symmetric group of order 6! as a permutation group 2953 3282 sage: G3 2954 Subgroup of SymmetricGroup(6) generated by [(1,2), (1,2,3,4,5,6)]3283 Subgroup of (Symmetric group of order 6! as a permutation group) generated by [(1,2), (1,2,3,4,5,6)] 2955 3284 sage: G is G3 2956 3285 False 2957 3286 sage: G == G3 # as permutation groups … … 2996 3325 sage: gens = H.gens() 2997 3326 sage: S = PermutationGroup_subgroup(G, list(gens)) 2998 3327 sage: S 2999 Subgroup of Dihedral group of order 8 as a permutation groupgenerated by [(1,2,3,4)]3328 Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)] 3000 3329 sage: S._repr_() 3001 'Subgroup of Dihedral group of order 8 as a permutation groupgenerated by [(1,2,3,4)]'3330 'Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]' 3002 3331 """ 3003 s = "Subgroup of %sgenerated by %s"%(self.ambient_group(), self.gens())3332 s = "Subgroup of (%s) generated by %s"%(self.ambient_group(), self.gens()) 3004 3333 return s 3005 3334 3006 3335 def _latex_(self): … … 3017 3346 sage: gens = H.gens() 3018 3347 sage: S = PermutationGroup_subgroup(G, list(gens)) 3019 3348 sage: latex(S) 3020 Subgroup of Dihedral group of order 8 as a permutation groupgenerated by [(1,2,3,4)]3349 Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)] 3021 3350 sage: S._latex_() 3022 'Subgroup of Dihedral group of order 8 as a permutation groupgenerated by [(1,2,3,4)]'3351 'Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)]' 3023 3352 """ 3024 3353 return self._repr_() 3025 3354 … … 3042 3371 sage: S.ambient_group() == G 3043 3372 True 3044 3373 """ 3045 return self.__ambient_group 3046 3047 def gens(self): 3374 return self._ambient_group 3375 3376 3377 def is_normal(self, other=None): 3048 3378 """ 3049 Return the generators for this subgroup. 3379 Return ``True`` if this group is a normal subgroup of 3380 ``other``. If ``other`` is not specified, then it is assumed 3381 to be the ambient group. 3050 3382 3051 EXAMPLES: 3052 3053 An example involving the dihedral group on four elements, 3054 `D_8`:: 3383 EXAMPLES:: 3055 3384 3056 sage: G = DihedralGroup(4) 3057 sage: H = CyclicPermutationGroup(4) 3058 sage: gens = H.gens() 3059 sage: S = PermutationGroup_subgroup(G, list(gens)) 3060 sage: S.gens() 3061 [(1,2,3,4)] 3062 sage: S.gens() == list(H.gens()) 3063 True 3385 sage: S = SymmetricGroup(['a','b','c']) 3386 sage: H = S.subgroup([('a', 'b', 'c')]); H 3387 Subgroup of (Symmetric group of order 3! as a permutation group) generated by [('a','b','c')] 3388 sage: H.is_normal() 3389 True 3390 3064 3391 """ 3065 return self._gens 3066 3392 if other is None: 3393 other = self.ambient_group() 3394 return PermutationGroup_generic.is_normal(self, other) 3395 -
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 9 9 cdef Element _gap_element 10 10 cdef __tuple 11 11 cdef PermutationGroupElement _new_c(self) 12 cpdef _gap_list(self) 12 13 cpdef list(self) 13 14 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 65 65 from sage.rings.all import ZZ, Integer, is_MPolynomial, is_Polynomial 66 66 from sage.matrix.all import MatrixSpace 67 67 from sage.interfaces.all import gap, is_GapElement, is_ExpectElement 68 68 from sage.sets.finite_enumerated_set import FiniteEnumeratedSet 69 69 import sage.structure.coerce as coerce 70 70 71 71 import operator 72 72 73 from sage.rings.integer import Integer74 75 73 from sage.rings.fast_arith cimport arith_llong 76 74 cdef arith_llong arith = arith_llong() 77 75 cdef extern from *: … … 80 78 #import permgroup_named 81 79 82 80 def 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 100 def 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)]) 84 125 return G(x, check=False) 85 126 127 86 128 def 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 """ 87 139 return isinstance(x, PermutationGroupElement) 88 140 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 99 141 def string_to_tuples(g): 100 142 """ 101 143 EXAMPLES:: … … 120 162 g = '[' + g + ']' 121 163 return sage_eval(g, preparse=False) 122 164 165 def 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 123 252 124 253 cdef class PermutationGroupElement(MultiplicativeGroupElement): 125 254 """ … … 292 421 sage: PermutationGroupElement([()]) 293 422 () 294 423 """ 295 from sage.interfaces.gap import GapElement296 424 from sage.groups.perm_gps.permgroup_named import SymmetricGroup 297 425 from sage.groups.perm_gps.permgroup import PermutationGroup_generic 426 from sage.combinat.permutation import from_cycles 298 427 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 308 433 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 320 439 321 440 if parent is None: 322 parent = SymmetricGroup( max(len(v),1))323 441 parent = SymmetricGroup(len(v)) 442 324 443 if check and parent.__class__ != SymmetricGroup: 325 444 if not (parent is None or isinstance(parent, PermutationGroup_generic)): 326 445 raise TypeError, 'parent must be a permutation group' 327 446 if parent is not None: 328 447 P = parent._gap_() 329 448 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) 331 450 332 451 Element.__init__(self, parent) 333 452 … … 361 480 sage_free(self.perm) 362 481 363 482 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()) 365 496 366 497 cdef PermutationGroupElement _new_c(self): 367 498 cdef PermutationGroupElement other = PY_NEW_SAME_TYPE(self) … … 375 506 other.perm = <int *>sage_malloc(sizeof(int) * other.n) 376 507 return other 377 508 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_()) 385 535 return self._gap_element 386 536 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 387 550 def _repr_(self): 388 551 """ 389 552 Return string representation of this permutation. 390 553 391 EXAMPLES: We create the permutation `(1,2,3)(4,5)` and392 print it. 393 394 ::395 554 EXAMPLES: 555 556 We create the permutation `(1,2,3)(4,5)` and 557 print it. :: 558 396 559 sage: g = PermutationGroupElement([(1,2,3),(4,5)]) 397 560 sage: g._repr_() 398 561 '(1,2,3)(4,5)' … … 407 570 sage: g 408 571 (1,2,3)(4,5) 409 572 """ 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() 414 574 415 575 def _latex_(self): 416 return str(self) 576 r""" 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[(\verb|a|,\verb|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()]) 417 591 418 592 def __getitem__(self, i): 419 593 """ … … 519 693 sage: g(x) 520 694 Traceback (most recent call last): 521 695 ... 522 ValueError: Must be an integer,list, tuple or string.696 ValueError: Must be in the domain or a list, tuple or string. 523 697 sage: g(3/2) 524 698 Traceback (most recent call last): 525 699 ... 526 ValueError: Must be an integer,list, tuple or string.700 ValueError: Must be in the domain or a list, tuple or string. 527 701 """ 702 to_gap = self._parent._domain_to_gap 703 from_gap = self._parent._domain_from_gap 528 704 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 530 720 permuted = [i[self.perm[j]] for j from 0 <= j < self.n] 531 721 if PY_TYPE_CHECK(i, tuple): 532 722 permuted = tuple(permuted) … … 535 725 permuted += i[self.n:] 536 726 return permuted 537 727 else: 538 if not isinstance(i, (int, Integer)):539 raise ValueError("Must be an integer, list, tuple or string.")540 728 j = i 541 729 if 1 <= j <= self.n: 542 return self.perm[j-1]+1730 return from_gap[self.perm[j-1]+1] 543 731 else: 544 return i732 return from_gap[i] 545 733 546 734 cpdef _act_on_(self, x, bint self_on_left): 547 735 """ … … 590 778 return left(tuple(sigma_x)) 591 779 592 780 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 """ 593 790 cdef PermutationGroupElement prod = left._new_c() 594 791 cdef PermutationGroupElement right = <PermutationGroupElement>_right 595 792 cdef int i … … 614 811 for i from 0 <= i < self.n: 615 812 inv.perm[self.perm[i]] = i 616 813 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 :: 617 829 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 618 863 cpdef list(self): 619 864 """ 620 865 Returns list of the images of the integers from 1 to n under this … … 633 878 (1,2) 634 879 sage: x.list() 635 880 [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 [] 636 889 """ 637 890 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] 639 901 640 902 def __hash__(self): 641 903 """ … … 654 916 1592966088 # 32-bit 655 917 2865702456085625800 # 64-bit 656 918 """ 657 return hash( self.tuple())658 919 return hash(tuple(self._gap_list())) 920 659 921 def tuple(self): 660 922 """ 661 Return tuple of images of integersunder self.923 Return tuple of images of the domain under self. 662 924 663 925 EXAMPLES:: 664 926 … … 666 928 sage: s = G([2,1,5,3,4]) 667 929 sage: s.tuple() 668 930 (2, 1, 5, 3, 4) 931 932 sage: S = SymmetricGroup(['a', 'b']) 933 sage: S.gen().tuple() 934 ('b', 'a') 669 935 """ 670 936 if self.__tuple is None: 671 937 self.__tuple = tuple(self.list()) … … 696 962 sage: x.dict() 697 963 {1: 2, 2: 1, 3: 3, 4: 4} 698 964 """ 965 from_gap = self._parent._domain_from_gap 699 966 cdef int i 700 967 u = {} 701 968 for i from 0 <= i < self.n: 702 u[i+1] = self.perm[i]+1969 u[i+1] = from_gap[self.perm[i]+1] 703 970 return u 704 971 705 972 def order(self): … … 816 1083 def orbit(self, n, bint sorted=True): 817 1084 """ 818 1085 Returns the orbit of the integer `n` under this group 819 element, as a sorted list of integers.1086 element, as a sorted list. 820 1087 821 1088 EXAMPLES:: 822 1089 … … 828 1095 [1, 2, 3] 829 1096 sage: g.orbit(10) 830 1097 [10] 1098 1099 :: 1100 1101 sage: s = SymmetricGroup(['a', 'b']).gen(0); s 1102 ('a','b') 1103 sage: s.orbit('a') 1104 ['a', 'b'] 831 1105 """ 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 832 1113 cdef int i = n 833 1114 cdef int start = i 834 1115 if 1 <= i <= self.n: 835 L = [ i]1116 L = [from_gap[i]] 836 1117 i = self.perm[i-1]+1 837 1118 while i != start: 838 PyList_Append(L, i)1119 PyList_Append(L,from_gap[i]) 839 1120 i = self.perm[i-1]+1 840 1121 if sorted: 841 1122 L.sort() 842 1123 return L 843 1124 else: 844 return [n]1125 return from_gap[n] 845 1126 846 1127 def cycles(self): 847 1128 """ … … 876 1157 sage_free(seen) 877 1158 return L 878 1159 879 def cycle_tuples(self ):1160 def cycle_tuples(self, singletons=False): 880 1161 """ 881 1162 Return self as a list of disjoint cycles, represented as tuples 882 1163 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')] 883 1191 """ 1192 from_gap = self._parent._domain_from_gap 884 1193 L = [] 885 1194 cdef int i, k 886 1195 cdef bint* seen = <bint *>sage_malloc(sizeof(bint) * self.n) 887 1196 for i from 0 <= i < self.n: seen[i] = 0 888 1197 for i from 0 <= i < self.n: 889 if seen[i] or self.perm[i] == i:1198 if seen[i]: 890 1199 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)) 898 1215 sage_free(seen) 899 1216 return L 900 1217 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 901 1237 def has_descent(self, i, side = "right", positive = False): 902 1238 """ 903 1239 INPUT: … … 944 1280 True 945 1281 sage: S._test_has_descent() 946 1282 """ 1283 to_gap = self._parent._domain_to_gap 1284 from_gap = self._parent._domain_from_gap 947 1285 if side == "right": 948 1286 self = ~self 1287 949 1288 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 959 1294 960 1295 def matrix(self): 961 1296 """ … … 980 1315 entries[i, self.perm[i]] = 1 981 1316 return M(entries) 982 1317 983 def word_problem( g, words, display=True):1318 def word_problem(self, words, display=True): 984 1319 """ 985 1320 G and H are permutation groups, g in G, H is a subgroup of G 986 1321 generated by a list (words) of elements of G. If g is in H, return … … 995 1330 EXAMPLE:: 996 1331 997 1332 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() 1000 1334 sage: h = g1^2*g2*g1 1001 1335 sage: h.word_problem([g1,g2], False) 1002 1336 ('x1^2*x2^-1*x1', '(1,2,3)(4,5)^2*(3,4)^-1*(1,2,3)(4,5)') … … 1005 1339 [['(1,2,3)(4,5)', 2], ['(3,4)', -1], ['(1,2,3)(4,5)', 1]] 1006 1340 ('x1^2*x2^-1*x1', '(1,2,3)(4,5)^2*(3,4)^-1*(1,2,3)(4,5)') 1007 1341 """ 1342 if not self._parent._has_natural_domain(): 1343 raise NotImplementedError 1344 1008 1345 import copy 1009 1346 from sage.groups.perm_gps.permgroup import PermutationGroup 1010 1347 from sage.interfaces.all import gap 1011 1348 1012 1349 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) 1018 1353 1019 1354 l1 = str(ans) 1020 1355 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 15 15 sage: g = G([(1,2,3,4)]) 16 16 sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens())) 17 17 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)] 19 19 sage: phi.kernel() 20 Permutation Group with generators[()]20 Subgroup of (Cyclic group of order 4 as a permutation group) generated by [()] 21 21 sage: phi.image(g) 22 22 (1,2,3,4) 23 23 sage: phi(g) … … 86 86 sage: g = G([(1,2,3,4)]) 87 87 sage: phi = PermutationGroupMorphism_im_gens(G, H, [1]) 88 88 sage: phi.kernel() 89 Permutation Group with generators[(1,2,3,4)]89 Subgroup of (Cyclic group of order 4 as a permutation group) generated by [(1,2,3,4)] 90 90 91 91 :: 92 92 … … 97 97 sage: G.is_isomorphic(pr1.kernel()) 98 98 True 99 99 """ 100 return PermutationGroup(gap_group=self._gap_().Kernel())100 return self.domain().subgroup(gap_group=self._gap_().Kernel()) 101 101 102 102 def image(self, J): 103 103 """ … … 111 111 sage: g = G([(1,2,3,4)]) 112 112 sage: phi = PermutationGroupMorphism_im_gens(G, H, map(H, G.gens())) 113 113 sage: phi.image(G) 114 Permutation Group with generators[(1,2,3,4)]114 Subgroup of (Dihedral group of order 8 as a permutation group) generated by [(1,2,3,4)] 115 115 sage: phi.image(g) 116 116 (1,2,3,4) 117 117 … … 122 122 sage: H = D[0] 123 123 sage: pr1 = D[3] 124 124 sage: pr1.image(G) 125 Permutation Group with generators[(3,7,5)(4,8,6), (1,2,6)(3,4,8)]125 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)] 126 126 sage: G.is_isomorphic(pr1.image(G)) 127 127 True 128 128 """ 129 H = self.codomain() 129 130 if J in self.domain(): 130 131 J = PermutationGroup([J]) 131 132 G = self._gap_().Image(J) 132 return PermutationGroup(gap_group=G).gens()[0]133 return H.subgroup(gap_group=G).gens()[0] 133 134 else: 134 135 G = self._gap_().Image(J) 135 return PermutationGroup(gap_group=G)136 return H.subgroup(gap_group=G) 136 137 137 138 def __call__(self, g): 138 139 """ … … 176 177 sage: H = G.subgroup([G([(1,2,3,4)])]) 177 178 sage: PermutationGroupMorphism_from_gap(H, G, gap.Identity) 178 179 Permutation group morphism: 179 From: Subgroup of Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]generated by [(1,2,3,4)]180 From: Subgroup of (Permutation Group with generators [(1,2)(3,4), (1,2,3,4)]) generated by [(1,2,3,4)] 180 181 To: Permutation Group with generators [(1,2)(3,4), (1,2,3,4)] 181 182 Defn: Identity 182 183 """ -
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 37 37 -- PSp(2n,q), projective symplectic linear group of $2n\times 2n$ matrices 38 38 over the finite field GF(q) 39 39 40 -- PSU(n,q), projective special unitary group of $n \times n$ matrices having40 -- PSU(n,q), projective special unitary group of $n \times n$ matrices having 41 41 coefficients in the finite field $GF(q^2)$ that respect a 42 42 fixed nondegenerate sesquilinear form, of determinant 1. 43 43 … … 78 78 from sage.groups.abelian_gps.abelian_group import AbelianGroup 79 79 from sage.misc.functional import is_even 80 80 from sage.misc.cachefunc import cached_method 81 from sage.misc.misc import deprecated_function_alias 81 82 from sage.groups.perm_gps.permgroup import PermutationGroup_generic 82 83 from sage.groups.perm_gps.permgroup_element import PermutationGroupElement 83 84 from sage.structure.unique_representation import UniqueRepresentation 84 85 from sage.structure.parent import Parent 85 86 from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets 87 from sage.sets.finite_enumerated_set import FiniteEnumeratedSet 86 88 from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets 87 89 from sage.categories.enumerated_sets import EnumeratedSets 88 90 from sage.sets.non_negative_integers import NonNegativeIntegers 89 91 from sage.sets.family import Family 90 92 91 93 class 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. 99 100 EXAMPLES:: 92 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 93 112 def __eq__(self, other): 94 95 96 113 """ 114 Overrides the default equality testing provided by 115 UniqueRepresentation by forcing a call to :meth:.`__cmp__`. 97 116 98 117 EXAMPLES:: 99 118 100 101 102 103 104 105 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 106 125 107 126 108 127 class PermutationGroup_symalt(PermutationGroup_unique): … … 112 131 """ 113 132 114 133 @staticmethod 115 def __classcall__(cls, n):134 def __classcall__(cls, domain): 116 135 """ 117 136 Normalizes the input of the constructor into a set 118 137 … … 141 160 sage: SymmetricGroup(-1) 142 161 Traceback (most recent call last): 143 162 ... 144 ValueError: n (=-1) must be an integer >= 0 or a list163 ValueError: domain (=-1) must be an integer >= 0 or a list 145 164 """ 146 if not isinstance(n, (tuple,list)): 147 try: 148 n = Integer(n) 149 except TypeError: 150 raise ValueError, "n (=%s) must be an integer >= 0 or a list (but n has type %s)"%(n,type(n)) 151 else: 152 if n < 0: 153 raise ValueError, "n (=%s) must be an integer >= 0 or a list"%n 154 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 155 179 156 try: 157 v = tuple(Integer(z) for z in n) 158 except TypeError: 159 raise ValueError, "each entry of list must be an integer" 180 return super(PermutationGroup_symalt, cls).__classcall__(cls, domain=v) 160 181 161 if v and min(v) < 1: # for SymmetricGroup(0), v is empty 162 raise ValueError, "each element of list must be positive" 163 164 return super(PermutationGroup_symalt, cls).__classcall__(cls, v) 165 166 def set(self): 167 """ 168 Returns the list of positive integers on which this group acts. 169 170 EXAMPLES: 171 sage: SymmetricGroup(3).set() 172 (1, 2, 3) 173 sage: SymmetricGroup([2,3,4]).set() 174 (2, 3, 4) 175 sage: AlternatingGroup(3).set() 176 (1, 2, 3) 177 sage: AlternatingGroup([2,3,4]).set() 178 (2, 3, 4) 179 """ 180 return self._set 181 182 @cached_method 183 def _has_natural_set(self): 184 """ 185 Returns true if the underlying set is of the form (1,...,n) 186 187 EXAMPLES:: 188 189 sage: SymmetricGroup(3)._has_natural_set() 190 True 191 sage: SymmetricGroup((1,2,3))._has_natural_set() 192 True 193 sage: SymmetricGroup((1,3))._has_natural_set() 194 False 195 sage: SymmetricGroup((3,2,1))._has_natural_set() 196 False 197 """ 198 set = self.set() 199 return set == tuple(range(1,len(set)+1)) 200 201 def __str__(self): 202 """ 203 EXAMPLES: 204 sage: S = SymmetricGroup([2,3,7]); S 205 Symmetric group of order 3! as a permutation group 206 sage: str(S) 207 'SymmetricGroup((2, 3, 7))' 208 sage: S = SymmetricGroup(5); S 209 Symmetric group of order 5! as a permutation group 210 sage: str(S) 211 'SymmetricGroup(5)' 212 sage: A = AlternatingGroup([2,3,7]); A 213 Alternating group of order 3!/2 as a permutation group 214 sage: str(A) 215 'AlternatingGroup((2, 3, 7))' 216 """ 217 set = self._set 218 if self._has_natural_set(): 219 set = len(set) 220 return "%s(%s)"%(self._gap_name, set) 182 set = deprecated_function_alias(PermutationGroup_generic.domain, 'Sage Version 4.7.1') 221 183 222 184 class SymmetricGroup(PermutationGroup_symalt): 223 def __init__(self, _set):185 def __init__(self, domain=None): 224 186 """ 225 187 The full symmetric group of order $n!$, as a permutation group. 226 188 If n is a list or tuple of positive integers then it returns the … … 243 205 sage: G = SymmetricGroup([1,2,4,5]) 244 206 sage: G 245 207 Symmetric group of order 4! as a permutation group 246 sage: G. set()247 (1, 2, 4, 5)208 sage: G.domain() 209 {1, 2, 4, 5} 248 210 sage: G = SymmetricGroup(4) 249 211 sage: G 250 212 Symmetric group of order 4! as a permutation group 251 sage: G. set()252 (1, 2, 3, 4)213 sage: G.domain() 214 {1, 2, 3, 4} 253 215 sage: G.category() 254 216 Join of Category of finite permutation groups and Category of finite weyl groups 255 217 sage: TestSuite(G).run() … … 261 223 from sage.categories.finite_weyl_groups import FiniteWeylGroups 262 224 from sage.categories.finite_permutation_groups import FinitePermutationGroups 263 225 from sage.categories.category import Category 226 264 227 #Note that we skip the call to the superclass initializer in order to 265 228 #avoid infinite recursion since SymmetricGroup is called by 266 229 #PermutationGroupElement 267 super(PermutationGroup_generic,self).__init__(category = Category.join([FinitePermutationGroups(), FiniteWeylGroups()])) 268 269 self._set = _set 270 self._deg = max(self._set+(0,)) # _set cat be empty 271 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)) 272 236 273 237 #Create the generators for the symmetric group 274 gens = [ tuple(self._ set) ]275 if n> 2:276 gens.append( tuple(self._ set[:2]) )238 gens = [ tuple(self._domain) ] 239 if len(self._domain) > 2: 240 gens.append( tuple(self._domain[:2]) ) 277 241 self._gens = [PermutationGroupElement(g, self, check=False) for g in gens] 278 242 279 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() 280 258 281 259 @cached_method 282 260 def index_set(self): … … 287 265 288 266 sage: S8 = SymmetricGroup(8) 289 267 sage: S8.index_set() 290 (1, 2, 3, 4, 5, 6, 7)268 [1, 2, 3, 4, 5, 6, 7] 291 269 292 270 sage: S = SymmetricGroup([3,1,4,5]) 293 271 sage: S.index_set() 294 (3, 1, 4)272 [3, 1, 4] 295 273 """ 296 return self. set()[:-1]274 return self.domain()[:-1] 297 275 298 276 def __cmp__(self, x): 299 277 """ … … 306 284 True 307 285 """ 308 286 if isinstance(x, SymmetricGroup): 309 return cmp((self._deg, self._ set), (x._deg, x._set))287 return cmp((self._deg, self._domain), (x._deg, x._domain)) 310 288 else: 311 289 return PermutationGroup_generic.__cmp__(self, x) 312 290 … … 316 294 sage: A = SymmetricGroup([2,3,7]); A 317 295 Symmetric group of order 3! as a permutation group 318 296 """ 319 return "Symmetric group of order %s! as a permutation group"%len(self._set) 320 321 _gap_name = 'SymmetricGroup' 297 return "Symmetric group of order %s! as a permutation group"%self.degree() 322 298 323 299 def simple_reflection(self, i): 324 300 """ … … 335 311 sage: A.simple_reflections() 336 312 Finite family {2: (2,3), 3: (3,7)} 337 313 """ 338 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) 339 315 340 316 def major_index(self, parameter=None): 341 317 r""" … … 367 343 return q_factorial(self.degree(), parameter) 368 344 369 345 class AlternatingGroup(PermutationGroup_symalt): 370 def __init__(self, _set):346 def __init__(self, domain=None): 371 347 """ 372 348 The alternating group of order $n!/2$, as a permutation group. 373 349 … … 389 365 sage: G = AlternatingGroup([1,2,4,5]) 390 366 sage: G 391 367 Alternating group of order 4!/2 as a permutation group 392 sage: G. set()393 (1, 2, 4, 5)368 sage: G.domain() 369 {1, 2, 4, 5} 394 370 sage: G.category() 395 371 Category of finite permutation groups 396 372 sage: TestSuite(G).run() 397 373 """ 398 n = len(_set) 399 #Create the generators for the symmetric group 400 if n == 1: 401 gens = [ [] ] 402 else: 403 gens = [ tuple(_set) ] 404 if n > 2: 405 gens.append( tuple(_set[:2]) ) 406 407 PermutationGroup_symalt.__init__(self, gap_group='%s(%s)'%(self._gap_name,n)) 408 409 self._set = _set 410 self._deg = max(_set) 374 PermutationGroup_symalt.__init__(self, gap_group='AlternatingGroup(%s)'%len(domain), domain=domain) 411 375 412 376 def _repr_(self): 413 377 """ … … 415 379 sage: A = AlternatingGroup([2,3,7]); A 416 380 Alternating group of order 3!/2 as a permutation group 417 381 """ 418 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() 419 383 420 _gap_name = 'AlternatingGroup' 384 def _gap_init_(self, gap=None): 385 """ 386 Returns the string used to create this group in GAP. 421 387 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 422 399 class CyclicPermutationGroup(PermutationGroup_unique): 423 400 def __init__(self, n): 424 401 """ … … 493 470 n = self.order() 494 471 a = list(factor(n)) 495 472 invs = [x[0]**x[1] for x in a] 496 G = AbelianGroup(len(a), invs)473 G = AbelianGroup(len(a), invs) 497 474 return G 498 475 499 476 class DiCyclicGroup(PermutationGroup_unique): … … 635 612 a = [tuple(range(1, halfr+1)), tuple(range(halfr+1, r+1))] 636 613 # With an odd part, a cycle of length m will give the right order for a 637 614 if m > 1: 638 a.append( tuple(range(r+1, r+m+1)) )615 a.append( tuple(range(r+1, r+m+1)) ) 639 616 640 617 # Representation of x 641 618 # Four-cycles that will conjugate the generator a properly … … 643 620 for i in range(0, fourthr)] 644 621 # With an odd part, transpositions will conjugate the m-cycle to create inverse 645 622 if m > 1: 646 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)] 647 624 648 PermutationGroup_generic.__init__(self, gens=[a, x])625 PermutationGroup_generic.__init__(self, gens=[a, x]) 649 626 650 627 def _repr_(self): 651 628 r""" … … 961 938 962 939 self._d = d 963 940 self._n = n 964 self._ set= range(1, d+1)941 self._domain = range(1, d+1) 965 942 966 943 def _repr_(self): 967 944 """ … … 1197 1174 sage: [TransitiveGroups(i).cardinality() for i in range(11)] # requires optional database_gap 1198 1175 [1, 1, 1, 2, 5, 5, 16, 7, 50, 34, 45] 1199 1176 1200 .. warning:: The database_gap contains all transitive groups 1201 up to degree 30:: 1177 .. warning:: 1202 1178 1203 sage: TransitiveGroups(31).cardinality() # requires optional database_gap 1204 Traceback (most recent call last): 1205 ... 1206 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 1207 1186 1208 1187 TESTS:: 1209 1188 … … 1282 1261 Category of finite permutation groups 1283 1262 sage: TestSuite(G).run() 1284 1263 """ 1285 from sage.groups.perm_gps.permgroup import PermutationGroup_generic1286 1264 id = 'Group([()])' if n == 1 else 'PGL(%s,%s)'%(n,q) 1287 1265 PermutationGroup_generic.__init__(self, gap_group=id) 1288 1266 self._q = q … … 1584 1562 class SuzukiGroup(PermutationGroup_unique): 1585 1563 def __init__(self, q, name='a'): 1586 1564 r""" 1587 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. 1588 1569 1589 1570 INPUT: 1590 1571 q -- 2^n, an odd power of 2; the size of the ground … … 1594 1575 finite field GF(q) 1595 1576 1596 1577 OUTPUT: 1597 A Suzuki group. 1578 1579 - A Suzuki group. 1598 1580 1599 EXAMPLES: 1581 EXAMPLES:: 1582 1600 1583 sage: SuzukiGroup(8) 1601 Permutation Group with generators [(1,2 8,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)] 1602 1585 sage: print SuzukiGroup(8) 1603 1586 The Suzuki group over Finite Field in a of size 2^3 1604 1587 … … 1611 1594 Finite Field in alpha of size 2^5 1612 1595 1613 1596 REFERENCES: 1614 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 1615 1599 """ 1616 1600 q = Integer(q) 1617 1601 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 340 340 sage: G.subgroup([ G(1), G([(1,5,2),(3,4,6)]), G([(1,2,5),(3,6,4)])]) 341 341 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 342 342 """ 343 if len(elts) == self.order(): return self 344 else: return GaloisGroup_subgroup(self, elts) 343 if len(elts) == self.order(): 344 return self 345 else: 346 return GaloisGroup_subgroup(self, elts) 345 347 346 348 # Proper number theory starts here. All the functions below make no sense 347 349 # unless the field is Galois. … … 557 559 sage: GaloisGroup_subgroup( G, [ G(1), G([(1,5,2),(3,4,6)]), G([(1,2,5),(3,6,4)])]) 558 560 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 559 561 """ 560 562 #XXX: This should be fixed so that this can use GaloisGroup_v2.__init__ 561 563 PermutationGroup_generic.__init__(self, elts, canonicalize = True) 562 564 self._ambient = ambient 563 565 self._number_field = ambient.number_field() 564 self._galois_closure=ambient._galois_closure 566 self._galois_closure = ambient._galois_closure 567 self._pari_data = ambient._pari_data 568 self._pari_gc = ambient._pari_gc 569 self._gc_map = ambient._gc_map 565 570 self._elts = elts 566 571 567 572 def fixed_field(self): … … 680 685 return min(w) 681 686 682 687 def __cmp__(self, other): 683 r"""Compare self to other. For some bizarre reason, if you just let it 688 r""" 689 Compare self to other. For some bizarre reason, if you just let it 684 690 inherit the cmp routine from PermutationGroupElement, cmp(x, y) works 685 691 but sorting lists doesn't. 686 692 … … 688 694 689 695 sage: K.<a> = NumberField(x^6 + 40*x^3 + 1372);G = K.galois_group() 690 696 sage: sorted([G.artin_symbol(Q) for Q in K.primes_above(5)]) 691 [(1, 2)(3,4)(5,6), (1,3)(2,6)(4,5), (1,5)(2,4)(3,6)]697 [(1,3)(2,6)(4,5), (1,2)(3,4)(5,6), (1,5)(2,4)(3,6)] 692 698 """ 693 return cmp(self.list(), other.list())699 return PermutationGroupElement.__cmp__(self, other) 694 700 695 701 696 702 -
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 6806 6806 sage: z = CyclotomicField(3).an_element(); z 6807 6807 zeta3 6808 6808 sage: c = K.character([1,z,z**2]); c 6809 Character of Subgroup of AlternatingGroup(4) generated by [(2,3,4)]6809 Character of Subgroup of (Alternating group of order 4!/2 as a permutation group) generated by [(2,3,4)] 6810 6810 sage: c(g^2); z^2 6811 6811 -zeta3 - 1 6812 6812 -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 181 181 """ 182 182 return Integer(len(self._elements)) 183 183 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 184 196 def _element_constructor_(self, el): 185 197 """ 186 198 TESTS:: -
sage/structure/parent.pyx
diff --git a/sage/structure/parent.pyx b/sage/structure/parent.pyx
a b 1772 1772 sage: S3.register_embedding(phi) 1773 1773 sage: S3.coerce_embedding() 1774 1774 Generic morphism: 1775 From: Alternating Group(3)1775 From: Alternating group of order 3!/2 as a permutation group 1776 1776 To: Special Linear Group of degree 3 over Rational Field 1777 1777 sage: S3.coerce_embedding()(p) 1778 1778 [0 0 1] -
sage/structure/parent_gens.pyx
diff --git a/sage/structure/parent_gens.pyx b/sage/structure/parent_gens.pyx
a b 368 368 if d.has_key('_element_constructor'): 369 369 return parent.Parent.__setstate__(self, d) 370 370 try: 371 self.__dict__ = d371 self.__dict__.update(d) 372 372 self._generator_orders = d['_generator_orders'] 373 373 except (AttributeError,KeyError): 374 374 pass