test_fp_groups.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. from sympy.core.singleton import S
  2. from sympy.combinatorics.fp_groups import (FpGroup, low_index_subgroups,
  3. reidemeister_presentation, FpSubgroup,
  4. simplify_presentation)
  5. from sympy.combinatorics.free_groups import (free_group, FreeGroup)
  6. from sympy.testing.pytest import slow
  7. """
  8. References
  9. ==========
  10. [1] Holt, D., Eick, B., O'Brien, E.
  11. "Handbook of Computational Group Theory"
  12. [2] John J. Cannon; Lucien A. Dimino; George Havas; Jane M. Watson
  13. Mathematics of Computation, Vol. 27, No. 123. (Jul., 1973), pp. 463-490.
  14. "Implementation and Analysis of the Todd-Coxeter Algorithm"
  15. [3] PROC. SECOND INTERNAT. CONF. THEORY OF GROUPS, CANBERRA 1973,
  16. pp. 347-356. "A Reidemeister-Schreier program" by George Havas.
  17. http://staff.itee.uq.edu.au/havas/1973cdhw.pdf
  18. """
  19. def test_low_index_subgroups():
  20. F, x, y = free_group("x, y")
  21. # Example 5.10 from [1] Pg. 194
  22. f = FpGroup(F, [x**2, y**3, (x*y)**4])
  23. L = low_index_subgroups(f, 4)
  24. t1 = [[[0, 0, 0, 0]],
  25. [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 3, 3]],
  26. [[0, 0, 1, 2], [2, 2, 2, 0], [1, 1, 0, 1]],
  27. [[1, 1, 0, 0], [0, 0, 1, 1]]]
  28. for i in range(len(t1)):
  29. assert L[i].table == t1[i]
  30. f = FpGroup(F, [x**2, y**3, (x*y)**7])
  31. L = low_index_subgroups(f, 15)
  32. t2 = [[[0, 0, 0, 0]],
  33. [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5],
  34. [4, 4, 5, 3], [6, 6, 3, 4], [5, 5, 6, 6]],
  35. [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5],
  36. [6, 6, 5, 3], [5, 5, 3, 4], [4, 4, 6, 6]],
  37. [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5],
  38. [6, 6, 5, 3], [7, 7, 3, 4], [4, 4, 8, 9], [5, 5, 10, 11],
  39. [11, 11, 9, 6], [9, 9, 6, 8], [12, 12, 11, 7], [8, 8, 7, 10],
  40. [10, 10, 13, 14], [14, 14, 14, 12], [13, 13, 12, 13]],
  41. [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5],
  42. [6, 6, 5, 3], [7, 7, 3, 4], [4, 4, 8, 9], [5, 5, 10, 11],
  43. [11, 11, 9, 6], [12, 12, 6, 8], [10, 10, 11, 7], [8, 8, 7, 10],
  44. [9, 9, 13, 14], [14, 14, 14, 12], [13, 13, 12, 13]],
  45. [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5],
  46. [6, 6, 5, 3], [7, 7, 3, 4], [4, 4, 8, 9], [5, 5, 10, 11],
  47. [11, 11, 9, 6], [12, 12, 6, 8], [13, 13, 11, 7], [8, 8, 7, 10],
  48. [9, 9, 12, 12], [10, 10, 13, 13]],
  49. [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 3, 3], [2, 2, 5, 6]
  50. , [7, 7, 6, 4], [8, 8, 4, 5], [5, 5, 8, 9], [6, 6, 9, 7],
  51. [10, 10, 7, 8], [9, 9, 11, 12], [11, 11, 12, 10], [13, 13, 10, 11],
  52. [12, 12, 13, 13]],
  53. [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 3, 3], [2, 2, 5, 6]
  54. , [7, 7, 6, 4], [8, 8, 4, 5], [5, 5, 8, 9], [6, 6, 9, 7],
  55. [10, 10, 7, 8], [9, 9, 11, 12], [13, 13, 12, 10], [12, 12, 10, 11],
  56. [11, 11, 13, 13]],
  57. [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 4, 4]
  58. , [7, 7, 6, 3], [8, 8, 3, 5], [5, 5, 8, 9], [6, 6, 9, 7],
  59. [10, 10, 7, 8], [9, 9, 11, 12], [13, 13, 12, 10], [12, 12, 10, 11],
  60. [11, 11, 13, 13]],
  61. [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8]
  62. , [5, 5, 6, 3], [9, 9, 3, 5], [10, 10, 8, 4], [8, 8, 4, 7],
  63. [6, 6, 10, 11], [7, 7, 11, 9], [12, 12, 9, 10], [11, 11, 13, 14],
  64. [14, 14, 14, 12], [13, 13, 12, 13]],
  65. [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8]
  66. , [6, 6, 6, 3], [5, 5, 3, 5], [8, 8, 8, 4], [7, 7, 4, 7]],
  67. [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8]
  68. , [9, 9, 6, 3], [6, 6, 3, 5], [10, 10, 8, 4], [11, 11, 4, 7],
  69. [5, 5, 10, 12], [7, 7, 12, 9], [8, 8, 11, 11], [13, 13, 9, 10],
  70. [12, 12, 13, 13]],
  71. [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8]
  72. , [9, 9, 6, 3], [6, 6, 3, 5], [10, 10, 8, 4], [11, 11, 4, 7],
  73. [5, 5, 12, 11], [7, 7, 10, 10], [8, 8, 9, 12], [13, 13, 11, 9],
  74. [12, 12, 13, 13]],
  75. [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8]
  76. , [9, 9, 6, 3], [10, 10, 3, 5], [7, 7, 8, 4], [11, 11, 4, 7],
  77. [5, 5, 9, 9], [6, 6, 11, 12], [8, 8, 12, 10], [13, 13, 10, 11],
  78. [12, 12, 13, 13]],
  79. [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8]
  80. , [9, 9, 6, 3], [10, 10, 3, 5], [7, 7, 8, 4], [11, 11, 4, 7],
  81. [5, 5, 12, 11], [6, 6, 10, 10], [8, 8, 9, 12], [13, 13, 11, 9],
  82. [12, 12, 13, 13]],
  83. [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8]
  84. , [9, 9, 6, 3], [10, 10, 3, 5], [11, 11, 8, 4], [12, 12, 4, 7],
  85. [5, 5, 9, 9], [6, 6, 12, 13], [7, 7, 11, 11], [8, 8, 13, 10],
  86. [13, 13, 10, 12]],
  87. [[1, 1, 0, 0], [0, 0, 2, 3], [4, 4, 3, 1], [5, 5, 1, 2], [2, 2, 4, 4]
  88. , [3, 3, 6, 7], [7, 7, 7, 5], [6, 6, 5, 6]]]
  89. for i in range(len(t2)):
  90. assert L[i].table == t2[i]
  91. f = FpGroup(F, [x**2, y**3, (x*y)**7])
  92. L = low_index_subgroups(f, 10, [x])
  93. t3 = [[[0, 0, 0, 0]],
  94. [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5], [4, 4, 5, 3],
  95. [6, 6, 3, 4], [5, 5, 6, 6]],
  96. [[0, 0, 1, 2], [1, 1, 2, 0], [3, 3, 0, 1], [2, 2, 4, 5], [6, 6, 5, 3],
  97. [5, 5, 3, 4], [4, 4, 6, 6]],
  98. [[0, 0, 1, 2], [3, 3, 2, 0], [4, 4, 0, 1], [1, 1, 5, 6], [2, 2, 7, 8],
  99. [6, 6, 6, 3], [5, 5, 3, 5], [8, 8, 8, 4], [7, 7, 4, 7]]]
  100. for i in range(len(t3)):
  101. assert L[i].table == t3[i]
  102. def test_subgroup_presentations():
  103. F, x, y = free_group("x, y")
  104. f = FpGroup(F, [x**3, y**5, (x*y)**2])
  105. H = [x*y, x**-1*y**-1*x*y*x]
  106. p1 = reidemeister_presentation(f, H)
  107. assert str(p1) == "((y_1, y_2), (y_1**2, y_2**3, y_2*y_1*y_2*y_1*y_2*y_1))"
  108. H = f.subgroup(H)
  109. assert (H.generators, H.relators) == p1
  110. f = FpGroup(F, [x**3, y**3, (x*y)**3])
  111. H = [x*y, x*y**-1]
  112. p2 = reidemeister_presentation(f, H)
  113. assert str(p2) == "((x_0, y_0), (x_0**3, y_0**3, x_0*y_0*x_0*y_0*x_0*y_0))"
  114. f = FpGroup(F, [x**2*y**2, y**-1*x*y*x**-3])
  115. H = [x]
  116. p3 = reidemeister_presentation(f, H)
  117. assert str(p3) == "((x_0,), (x_0**4,))"
  118. f = FpGroup(F, [x**3*y**-3, (x*y)**3, (x*y**-1)**2])
  119. H = [x]
  120. p4 = reidemeister_presentation(f, H)
  121. assert str(p4) == "((x_0,), (x_0**6,))"
  122. # this presentation can be improved, the most simplified form
  123. # of presentation is <a, b | a^11, b^2, (a*b)^3, (a^4*b*a^-5*b)^2>
  124. # See [2] Pg 474 group PSL_2(11)
  125. # This is the group PSL_2(11)
  126. F, a, b, c = free_group("a, b, c")
  127. f = FpGroup(F, [a**11, b**5, c**4, (b*c**2)**2, (a*b*c)**3, (a**4*c**2)**3, b**2*c**-1*b**-1*c, a**4*b**-1*a**-1*b])
  128. H = [a, b, c**2]
  129. gens, rels = reidemeister_presentation(f, H)
  130. assert str(gens) == "(b_1, c_3)"
  131. assert len(rels) == 18
  132. @slow
  133. def test_order():
  134. F, x, y = free_group("x, y")
  135. f = FpGroup(F, [x**4, y**2, x*y*x**-1*y])
  136. assert f.order() == 8
  137. f = FpGroup(F, [x*y*x**-1*y**-1, y**2])
  138. assert f.order() is S.Infinity
  139. F, a, b, c = free_group("a, b, c")
  140. f = FpGroup(F, [a**250, b**2, c*b*c**-1*b, c**4, c**-1*a**-1*c*a, a**-1*b**-1*a*b])
  141. assert f.order() == 2000
  142. F, x = free_group("x")
  143. f = FpGroup(F, [])
  144. assert f.order() is S.Infinity
  145. f = FpGroup(free_group('')[0], [])
  146. assert f.order() == 1
  147. def test_fp_subgroup():
  148. def _test_subgroup(K, T, S):
  149. _gens = T(K.generators)
  150. assert all(elem in S for elem in _gens)
  151. assert T.is_injective()
  152. assert T.image().order() == S.order()
  153. F, x, y = free_group("x, y")
  154. f = FpGroup(F, [x**4, y**2, x*y*x**-1*y])
  155. S = FpSubgroup(f, [x*y])
  156. assert (x*y)**-3 in S
  157. K, T = f.subgroup([x*y], homomorphism=True)
  158. assert T(K.generators) == [y*x**-1]
  159. _test_subgroup(K, T, S)
  160. S = FpSubgroup(f, [x**-1*y*x])
  161. assert x**-1*y**4*x in S
  162. assert x**-1*y**4*x**2 not in S
  163. K, T = f.subgroup([x**-1*y*x], homomorphism=True)
  164. assert T(K.generators[0]**3) == y**3
  165. _test_subgroup(K, T, S)
  166. f = FpGroup(F, [x**3, y**5, (x*y)**2])
  167. H = [x*y, x**-1*y**-1*x*y*x]
  168. K, T = f.subgroup(H, homomorphism=True)
  169. S = FpSubgroup(f, H)
  170. _test_subgroup(K, T, S)
  171. def test_permutation_methods():
  172. F, x, y = free_group("x, y")
  173. # DihedralGroup(8)
  174. G = FpGroup(F, [x**2, y**8, x*y*x**-1*y])
  175. T = G._to_perm_group()[1]
  176. assert T.is_isomorphism()
  177. assert G.center() == [y**4]
  178. # DiheadralGroup(4)
  179. G = FpGroup(F, [x**2, y**4, x*y*x**-1*y])
  180. S = FpSubgroup(G, G.normal_closure([x]))
  181. assert x in S
  182. assert y**-1*x*y in S
  183. # Z_5xZ_4
  184. G = FpGroup(F, [x*y*x**-1*y**-1, y**5, x**4])
  185. assert G.is_abelian
  186. assert G.is_solvable
  187. # AlternatingGroup(5)
  188. G = FpGroup(F, [x**3, y**2, (x*y)**5])
  189. assert not G.is_solvable
  190. # AlternatingGroup(4)
  191. G = FpGroup(F, [x**3, y**2, (x*y)**3])
  192. assert len(G.derived_series()) == 3
  193. S = FpSubgroup(G, G.derived_subgroup())
  194. assert S.order() == 4
  195. def test_simplify_presentation():
  196. # ref #16083
  197. G = simplify_presentation(FpGroup(FreeGroup([]), []))
  198. assert not G.generators
  199. assert not G.relators
  200. def test_cyclic():
  201. F, x, y = free_group("x, y")
  202. f = FpGroup(F, [x*y, x**-1*y**-1*x*y*x])
  203. assert f.is_cyclic
  204. f = FpGroup(F, [x*y, x*y**-1])
  205. assert f.is_cyclic
  206. f = FpGroup(F, [x**4, y**2, x*y*x**-1*y])
  207. assert not f.is_cyclic
  208. def test_abelian_invariants():
  209. F, x, y = free_group("x, y")
  210. f = FpGroup(F, [x*y, x**-1*y**-1*x*y*x])
  211. assert f.abelian_invariants() == []
  212. f = FpGroup(F, [x*y, x*y**-1])
  213. assert f.abelian_invariants() == [2]
  214. f = FpGroup(F, [x**4, y**2, x*y*x**-1*y])
  215. assert f.abelian_invariants() == [2, 4]