Ticket #8500: trac_8500_number_transitive_group-review-nt.patch
File trac_8500_number_transitive_group-review-nt.patch, 19.2 KB (added by , 12 years ago) |
---|
-
doc/en/reference/groups.rst
# HG changeset patch # User Nicolas M. Thiery <nthiery@users.sf.net> # Date 1271620682 -7200 # Node ID e5b6f9e216992b1c359b343a6338eb405f2bf5ca # Parent cdea1400fc2897a06c5f1cbaa8f7caa8db2b919b #8500: Add the set of TransitiveGroups; reviewer's patch diff --git a/doc/en/reference/groups.rst b/doc/en/reference/groups.rst
a b Groups 13 13 sage/groups/abelian_gps/abelian_group_morphism 14 14 sage/groups/abelian_gps/dual_abelian_group 15 15 sage/groups/perm_gps/permgroup 16 sage/groups/perm_gps/permgroup_named 16 17 sage/groups/perm_gps/permgroup_element 17 18 sage/groups/perm_gps/permgroup_morphism 18 19 sage/groups/perm_gps/cubegroup -
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 You can construct the following permutat 16 16 17 17 -- DiCyclicGroup, nonabelian groups of order `4m` with a unique element of order 2 18 18 19 -- TransitiveGroup, $ i^{th}$ transitive group of degree $n$19 -- TransitiveGroup, $n^{th}$ transitive group of degree $d$ 20 20 from the GAP tables of transitive groups (requires 21 21 the "optional" package database_gap) 22 22 23 -- TransitiveGroups(d), TransitiveGroups(), set of all of the above 24 23 25 -- MathieuGroup(degree), Mathieu group of degree 9, 10, 11, 12, 21, 22, 23, or 24. 24 26 25 27 -- KleinFourGroup, subgroup of $S_4$ of order $4$ which is not $C_2 \times C_2$ … … from sage.rings.all import Integer 72 74 from sage.interfaces.all import gap 73 75 from sage.rings.finite_field import FiniteField as GF 74 76 from sage.rings.arith import factor 77 from sage.rings.integer_ring import ZZ 75 78 from sage.groups.abelian_gps.abelian_group import AbelianGroup 76 79 from sage.misc.functional import is_even 77 80 from sage.misc.cachefunc import cached_method … … from sage.structure.parent import Parent 82 85 from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets 83 86 from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets 84 87 from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets 88 from sage.categories.enumerated_sets import EnumeratedSets 85 89 from sage.sets.non_negative_integers import NonNegativeIntegers 86 90 from sage.sets.family import Family 87 91 … … class MathieuGroup(PermutationGroup_uniq 859 863 Mathieu group of degree 12 and order 95040 as a permutation group 860 864 """ 861 865 return "Mathieu group of degree %s and order %s as a permutation group"%(self._n,self.order()) 862 866 863 867 class TransitiveGroup(PermutationGroup_unique): 864 868 def __init__(self, d, n): 865 869 """ 866 870 The transitive group from the GAP tables of transitive groups. 867 871 868 872 INPUT: 869 873 d -- positive integer; the degree 870 874 n -- positive integer; the number … … class TransitiveGroup(PermutationGroup_u 874 878 875 879 EXAMPLES:: 876 880 877 sage: G = TransitiveGroup(1,1); G 881 sage: TransitiveGroup(0,1) 882 Transitive group number 1 of degree 0 883 sage: TransitiveGroup(1,1) 878 884 Transitive group number 1 of degree 1 879 sage: G = TransitiveGroup(5, 2); G # requires optional database_gap 885 sage: G = TransitiveGroup(5, 2); G # requires optional database_gap 880 886 Transitive group number 2 of degree 5 881 sage: G.gens() # requires optional database_gap 887 sage: G.gens() # requires optional database_gap 882 888 [(1,2,3,4,5), (1,4)(2,3)] 883 889 884 sage: G.category() 890 sage: G.category() # requires optional database_gap 885 891 Category of finite permutation groups 886 sage: TestSuite(G).run() 892 893 .. warning:: this follows GAP's naming convention of indexing 894 the transitive groups starting from ``1``:: 895 896 sage: TransitiveGroup(5,0) # requires optional database_gap 897 Traceback (most recent call last): 898 ... 899 AssertionError: n should be in {1,..,5} 900 901 .. warning:: only transitive groups of "small" degree are 902 available in GAP's database:: 903 904 sage: TransitiveGroup(31,1) # requires optional database_gap 905 Traceback (most recent call last): 906 ... 907 NotImplementedError: Only the transitive groups of order less than 30 are available in GAP's database 908 909 TESTS:: 910 911 sage: TestSuite(TransitiveGroup(0,1)).run() 912 sage: TestSuite(TransitiveGroup(1,1)).run() 913 sage: TestSuite(TransitiveGroup(5,2)).run()# requires optional database_gap 914 915 sage: TransitiveGroup(1,5) 916 Traceback (most recent call last): 917 ... 918 AssertionError: n should be in {1,..,1} 887 919 """ 888 id = 'Group([()])' if d in [0,1] else 'TransitiveGroup(%s,%s)'%(d,n) 920 d = ZZ(d) 921 n = ZZ(n) 922 assert d >= 0 923 assert n > 0 924 max_n = TransitiveGroups(d).cardinality() 925 assert n <= max_n, "n should be in {1,..,%s}"%max_n 926 gap_group = 'Group([()])' if d in [0,1] else 'TransitiveGroup(%s,%s)'%(d,n) 889 927 try: 890 PermutationGroup_generic.__init__(self, gap_group= id)928 PermutationGroup_generic.__init__(self, gap_group=gap_group) 891 929 except RuntimeError: 892 930 from sage.misc.misc import verbose 893 931 verbose("Warning: Computing with TransitiveGroups requires the optional database_gap package. Please install it.", level=0) 894 932 895 933 self._d = d 896 934 self._n = n 897 935 898 936 def _repr_(self): 899 937 """ 900 938 EXAMPLES: … … class TransitiveGroup(PermutationGroup_u 903 941 """ 904 942 return "Transitive group number %s of degree %s"%(self._n, self._d) 905 943 906 def number_of_transitive_groups(degree):944 def TransitiveGroups(d=None): 907 945 """ 908 Returns the number of transitive groups of a given ``degree``. 909 As in Gap, transitive groups of degree `n` are indexed from 1 to 910 number_of_transitive_groups(n). 946 INPUT: 911 947 912 The database_gap contains all transitive groups up to degree 30. 948 - ``d`` -- an integer (optional) 949 950 Returns the set of all transitive groups of a given degree 951 ``d``. If ``d`` is not specified, it returns the set of all 952 transitive groups. 953 954 Warning: TransitiveGroups requires the optional GAP database 955 package. Please install it with ``sage -i database_gap``. 913 956 914 957 EXAMPLES:: 915 958 916 sage: from sage.groups.perm_gps.permgroup_named import number_of_transitive_groups 917 sage: k = number_of_transitive_groups(12); k # requires optional database_gap 918 301 919 sage: type(k) # requires optional database_gap 920 <type 'sage.rings.integer.Integer'> 921 sage: [number_of_transitive_groups(Integer(i)) for i in range(11)] # requires optional database_gap 922 [1, 1, 1, 2, 5, 5, 16, 7, 50, 34, 45] 923 sage: for i in range(number_of_transitive_groups(5)): # requires optional database_gap 924 ... print TransitiveGroup(6,i+1).cardinality() 925 6 926 6 927 12 928 12 929 18 959 sage: TransitiveGroups(3) 960 Transitive Groups of degree 3 961 sage: TransitiveGroups(7) 962 Transitive Groups of degree 7 963 sage: TransitiveGroups(8) 964 Transitive Groups of degree 8 965 966 sage: TransitiveGroups() 967 Transitive Groups 968 969 .. warning:: in practice, the database currently only contains 970 transitive groups up to degree 30:: 971 972 sage: TransitiveGroups(31).cardinality() # requires optional database_gap 973 Traceback (most recent call last): 974 ... 975 NotImplementedError: Only the transitive groups of order less than 30 are available in GAP's database 976 930 977 """ 931 if (not isinstance(degree, Integer)) or degree < 0: 932 raise ValueError("A transitive group acts on a non negative integer number of positions") 933 if degree == 0: # gap.NrTransitiveGroups(0) --> fail : This ligne can't be removed. 934 return 1 935 if degree > 30: 936 raise NotImplementedError 937 else: 938 try: 939 G = PermutationGroup_generic(gap_group='TransitiveGroup(2,1)') 940 return Integer(gap.NrTransitiveGroups(gap(degree))) 941 except RuntimeError: 942 from sage.misc.misc import verbose 943 verbose("Warning: Computing with TransitiveGroups requires the optional database_gap package. Please install it.", level=0) 944 945 def TransitiveGroups(n=None): 946 """ 947 Returns the set of transitive groups of a given degree ``n`` if 948 specified, it returns the set of all transitive groups up to 949 degree 30 otherwise. 950 951 Warning: Computing with TransitiveGroups requires the optional 952 database_gap package. Please install it. 953 954 EXAMPLES:: 955 956 sage: from sage.groups.perm_gps.permgroup_named import number_of_transitive_groups 957 sage: TransitiveGroups(3) # requires optional database_gap 958 Transitive Groups of degree 3 959 sage: TransitiveGroups(7) # requires optional database_gap 960 Transitive Groups of degree 7 961 sage: TransitiveGroups(8) # requires optional database_gap 962 Transitive Groups of degree 8 963 964 If no degree is specified, it Returns the complete database which 965 contains all transitive groups up to degree 30:: 966 967 sage: TransitiveGroups() # requires optional database_gap 968 Transitive Groups 969 """ 970 # tests of the file takes [234.0 s] on a macbook(2009) with the following check 971 # if any(['database_gap' == p.split("-")[0] for p in optional_packages()[0]]): 972 # instead of [59.8 s] for the hard coded following check over an optional 973 # object 974 try: 975 G = PermutationGroup_generic(gap_group='TransitiveGroup(2,1)') 976 except RuntimeError: 977 from sage.misc.misc import verbose 978 verbose("Warning: Computing with TransitiveGroups requires the optional database_gap package. Please install it.", level=0) 979 980 if n == None: 978 if d == None: 981 979 return TransitiveGroupsAll() 982 980 else: 983 if (not isinstance(n, Integer)) or n < 0: 984 raise ValueError("A transitive group acts on a non negative integer number of positions") 985 if n < 31: 986 return TransitiveGroupsOfDegree(n) 987 else: 988 raise NotImplementedError 989 981 d == Integer(d) 982 assert d >= 0, "A transitive group acts on a non negative integer number of positions" 983 return TransitiveGroupsOfDegree(d) 990 984 991 985 class TransitiveGroupsAll(DisjointUnionEnumeratedSets): 992 986 """ … … class TransitiveGroupsAll(DisjointUnionE 994 988 995 989 EXAMPLES:: 996 990 997 sage: L = TransitiveGroups(); L # requires optional database_gap991 sage: L = TransitiveGroups(); L 998 992 Transitive Groups 999 sage: L.cardinality() # requires optional database_gap 993 sage: L.category() 994 Category of infinite enumerated sets 995 sage: L.cardinality() 1000 996 +Infinity 1001 sage: p = L.__iter__() # requires optional database_gap 997 998 sage: p = L.__iter__() # requires optional database_gap 1002 999 sage: (p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next(), p.next()) # requires optional database_gap 1003 1000 (Transitive group number 1 of degree 0, Transitive group number 1 of degree 1, Transitive group number 1 of degree 2, Transitive group number 1 of degree 3, Transitive group number 2 of degree 3, Transitive group number 1 of degree 4, Transitive group number 2 of degree 4, Transitive group number 3 of degree 4) 1004 1001 … … class TransitiveGroupsAll(DisjointUnionE 1016 1013 """ 1017 1014 DisjointUnionEnumeratedSets.__init__(self, Family(NonNegativeIntegers(), lambda i: TransitiveGroups(i)) ) 1018 1015 1019 def _ _repr__(self):1016 def _repr_(self): 1020 1017 """ 1021 1018 TESTS:: 1022 1019 1023 sage: TransitiveGroups() # requires optional database_gap 1020 sage: TransitiveGroups() # requires optional database_gap # indirect doctest 1024 1021 Transitive Groups 1025 1022 """ 1026 1023 return "Transitive Groups" … … class TransitiveGroupsAll(DisjointUnionE 1033 1030 True 1034 1031 sage: TransitiveGroup(6,5) in TransitiveGroups() # requires optional database_gap 1035 1032 True 1033 sage: 1 in TransitiveGroups() # requires optional database_gap 1034 False 1036 1035 """ 1037 1036 return isinstance(G,TransitiveGroup) 1038 1037 … … class TransitiveGroupsAll(DisjointUnionE 1042 1041 1043 1042 EXAMPLES:: 1044 1043 1045 sage: TransitiveGroups(5). _an_element_() # requires optional database_gap1044 sage: TransitiveGroups(5).an_element() # requires optional database_gap # indirect doctest 1046 1045 Transitive group number 1 of degree 5 1047 1046 """ 1048 1047 return TransitiveGroup(7,3) 1049 1048 1050 1049 class TransitiveGroupsOfDegree(UniqueRepresentation, Parent): 1051 1050 """ 1052 The Set of Transitive Groups of a given smalldegree.1051 The set of all transitive groups of a given (small) degree. 1053 1052 1054 1053 EXAMPLES:: 1055 1054 1056 sage: S = TransitiveGroups(4); S # requires optional database_gap1055 sage: S = TransitiveGroups(4); S # requires optional database_gap 1057 1056 Transitive Groups of degree 4 1058 sage: list(S) # requires optional database_gap1057 sage: list(S) # requires optional database_gap 1059 1058 [Transitive group number 1 of degree 4, Transitive group number 2 of degree 4, Transitive group number 3 of degree 4, Transitive group number 4 of degree 4, Transitive group number 5 of degree 4] 1060 1059 1061 TEST:: 1062 1063 sage: TestSuite(TransitiveGroups(6)).run() # requires optional database_gap # long time 1060 sage: TransitiveGroups(5).an_element() # requires optional database_gap 1061 Transitive group number 1 of degree 5 1062 1063 We write the cardinality of all transitive groups of degree 5:: 1064 1065 sage: for G in TransitiveGroups(5): # requires optional database_gap 1066 ... print G.cardinality() 1067 5 1068 10 1069 20 1070 60 1071 120 1072 1073 TESTS:: 1074 1075 sage: TestSuite(TransitiveGroups(3)).run() # requires optional database_gap 1076 1077 1064 1078 """ 1065 1079 def __init__(self, n): 1066 1080 """ … … class TransitiveGroupsOfDegree(UniqueRep 1073 1087 self._degree = n 1074 1088 Parent.__init__(self, category = FiniteEnumeratedSets()) 1075 1089 1076 def _ _repr__(self):1090 def _repr_(self): 1077 1091 """ 1078 1092 TESTS:: 1079 1093 … … class TransitiveGroupsOfDegree(UniqueRep 1090 1104 False 1091 1105 sage: TransitiveGroup(4,3) in TransitiveGroups(4) # requires optional database_gap 1092 1106 True 1107 sage: 1 in TransitiveGroups(4) # requires optional database_gap 1108 False 1093 1109 """ 1094 1110 if isinstance(G,TransitiveGroup): 1095 1111 return G._d == self._degree 1096 1112 else: 1097 1113 False 1098 1114 1099 def _an_element_(self): 1100 """ 1101 Returns an element of ``self``. 1115 def __getitem__(self, n): 1116 r""" 1117 INPUT: 1118 1119 - ``n`` -- a positive integer 1120 1121 Returns the `n`-th transitive group of a given degree. 1102 1122 1103 1123 EXAMPLES:: 1104 1124 1105 sage: TransitiveGroups(5)._an_element_() # requires optional database_gap 1106 Transitive group number 1 of degree 5 1125 sage: TransitiveGroups(5)[3] # requires optional database_gap# 1126 Transitive group number 3 of degree 5 1127 1128 .. warning:: this follows GAP's naming convention of indexing 1129 the transitive groups starting from ``1``:: 1130 1131 sage: TransitiveGroups(5)[0] 1132 Traceback (most recent call last): 1133 ... 1134 assert n > 0 1135 AssertionError 1107 1136 """ 1108 return TransitiveGroup(self._degree, 1)1137 return TransitiveGroup(self._degree, n) 1109 1138 1110 1139 def __iter__(self): 1111 1140 """ … … class TransitiveGroupsOfDegree(UniqueRep 1114 1143 sage: list(TransitiveGroups(5)) # indirect doctest # requires optional database_gap 1115 1144 [Transitive group number 1 of degree 5, Transitive group number 2 of degree 5, Transitive group number 3 of degree 5, Transitive group number 4 of degree 5, Transitive group number 5 of degree 5] 1116 1145 """ 1117 for i in range(1,number_of_transitive_groups(self._degree)+1):1118 yield TransitiveGroup(self._degree,i)1146 for n in xrange(1, self.cardinality() + 1): 1147 yield self[n] 1119 1148 1149 _an_element_ = EnumeratedSets.ParentMethods._an_element_ 1150 1151 @cached_method 1120 1152 def cardinality(self): 1121 """ 1122 Returns the cardinality of ``self``. 1153 r""" 1154 Returns the cardinality of ``self``, that is the number of 1155 transitive groups of a given degree. 1123 1156 1124 1157 EXAMPLES:: 1125 1126 sage: TransitiveGroups( 2).cardinality()# requires optional database_gap1158 1159 sage: TransitiveGroups(0).cardinality() # requires optional database_gap 1127 1160 1 1128 sage: TransitiveGroups(7).cardinality() # requires optional database_gap 1161 sage: TransitiveGroups(2).cardinality() # requires optional database_gap 1162 1 1163 sage: TransitiveGroups(7).cardinality() # requires optional database_gap 1129 1164 7 1130 sage: TransitiveGroups(12).cardinality() # requires optional database_gap1165 sage: TransitiveGroups(12).cardinality() # requires optional database_gap 1131 1166 301 1167 sage: [TransitiveGroups(i).cardinality() for i in range(11)] # requires optional database_gap 1168 [1, 1, 1, 2, 5, 5, 16, 7, 50, 34, 45] 1169 1170 .. warning:: The database_gap contains all transitive groups 1171 up to degree 30:: 1172 1173 sage: TransitiveGroups(31).cardinality() # requires optional database_gap 1174 Traceback (most recent call last): 1175 ... 1176 NotImplementedError: Only the transitive groups of order less than 30 are available in GAP's database 1177 1178 TESTS:: 1179 1180 sage: type(TransitiveGroups(12).cardinality()) # requires optional database_gap 1181 <type 'sage.rings.integer.Integer'> 1182 sage: type(TransitiveGroups(0).cardinality()) 1183 <type 'sage.rings.integer.Integer'> 1132 1184 """ 1133 return number_of_transitive_groups(self._degree) 1185 # gap.NrTransitiveGroups(0) fails, so Sage needs to handle this 1186 1187 # While we are at it, and since Sage also handles the 1188 # transitive group of degree 1, we may as well handle 1 1189 if self._degree <= 1: 1190 return ZZ(1) 1191 else: 1192 try: 1193 return Integer(gap.NrTransitiveGroups(gap(self._degree))) 1194 except RuntimeError: 1195 from sage.misc.misc import verbose 1196 verbose("Warning: TransitiveGroups requires the GAP database package. Please install it with ``sage -i database_gap``.", level=0) 1197 except TypeError: 1198 raise NotImplementedError, "Only the transitive groups of order less than 30 are available in GAP's database" 1134 1199 1135 1200 class PermutationGroup_plg(PermutationGroup_unique): 1136 1201 def base_ring(self):