generators.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. from sympy.combinatorics.permutations import Permutation
  2. from sympy.core.symbol import symbols
  3. from sympy.matrices import Matrix
  4. from sympy.utilities.iterables import variations, rotate_left
  5. def symmetric(n):
  6. """
  7. Generates the symmetric group of order n, Sn.
  8. Examples
  9. ========
  10. >>> from sympy.combinatorics.generators import symmetric
  11. >>> list(symmetric(3))
  12. [(2), (1 2), (2)(0 1), (0 1 2), (0 2 1), (0 2)]
  13. """
  14. yield from (Permutation(perm) for perm in variations(range(n), n))
  15. def cyclic(n):
  16. """
  17. Generates the cyclic group of order n, Cn.
  18. Examples
  19. ========
  20. >>> from sympy.combinatorics.generators import cyclic
  21. >>> list(cyclic(5))
  22. [(4), (0 1 2 3 4), (0 2 4 1 3),
  23. (0 3 1 4 2), (0 4 3 2 1)]
  24. See Also
  25. ========
  26. dihedral
  27. """
  28. gen = list(range(n))
  29. for i in range(n):
  30. yield Permutation(gen)
  31. gen = rotate_left(gen, 1)
  32. def alternating(n):
  33. """
  34. Generates the alternating group of order n, An.
  35. Examples
  36. ========
  37. >>> from sympy.combinatorics.generators import alternating
  38. >>> list(alternating(3))
  39. [(2), (0 1 2), (0 2 1)]
  40. """
  41. for perm in variations(range(n), n):
  42. p = Permutation(perm)
  43. if p.is_even:
  44. yield p
  45. def dihedral(n):
  46. """
  47. Generates the dihedral group of order 2n, Dn.
  48. The result is given as a subgroup of Sn, except for the special cases n=1
  49. (the group S2) and n=2 (the Klein 4-group) where that's not possible
  50. and embeddings in S2 and S4 respectively are given.
  51. Examples
  52. ========
  53. >>> from sympy.combinatorics.generators import dihedral
  54. >>> list(dihedral(3))
  55. [(2), (0 2), (0 1 2), (1 2), (0 2 1), (2)(0 1)]
  56. See Also
  57. ========
  58. cyclic
  59. """
  60. if n == 1:
  61. yield Permutation([0, 1])
  62. yield Permutation([1, 0])
  63. elif n == 2:
  64. yield Permutation([0, 1, 2, 3])
  65. yield Permutation([1, 0, 3, 2])
  66. yield Permutation([2, 3, 0, 1])
  67. yield Permutation([3, 2, 1, 0])
  68. else:
  69. gen = list(range(n))
  70. for i in range(n):
  71. yield Permutation(gen)
  72. yield Permutation(gen[::-1])
  73. gen = rotate_left(gen, 1)
  74. def rubik_cube_generators():
  75. """Return the permutations of the 3x3 Rubik's cube, see
  76. https://www.gap-system.org/Doc/Examples/rubik.html
  77. """
  78. a = [
  79. [(1, 3, 8, 6), (2, 5, 7, 4), (9, 33, 25, 17), (10, 34, 26, 18),
  80. (11, 35, 27, 19)],
  81. [(9, 11, 16, 14), (10, 13, 15, 12), (1, 17, 41, 40), (4, 20, 44, 37),
  82. (6, 22, 46, 35)],
  83. [(17, 19, 24, 22), (18, 21, 23, 20), (6, 25, 43, 16), (7, 28, 42, 13),
  84. (8, 30, 41, 11)],
  85. [(25, 27, 32, 30), (26, 29, 31, 28), (3, 38, 43, 19), (5, 36, 45, 21),
  86. (8, 33, 48, 24)],
  87. [(33, 35, 40, 38), (34, 37, 39, 36), (3, 9, 46, 32), (2, 12, 47, 29),
  88. (1, 14, 48, 27)],
  89. [(41, 43, 48, 46), (42, 45, 47, 44), (14, 22, 30, 38),
  90. (15, 23, 31, 39), (16, 24, 32, 40)]
  91. ]
  92. return [Permutation([[i - 1 for i in xi] for xi in x], size=48) for x in a]
  93. def rubik(n):
  94. """Return permutations for an nxn Rubik's cube.
  95. Permutations returned are for rotation of each of the slice
  96. from the face up to the last face for each of the 3 sides (in this order):
  97. front, right and bottom. Hence, the first n - 1 permutations are for the
  98. slices from the front.
  99. """
  100. if n < 2:
  101. raise ValueError('dimension of cube must be > 1')
  102. # 1-based reference to rows and columns in Matrix
  103. def getr(f, i):
  104. return faces[f].col(n - i)
  105. def getl(f, i):
  106. return faces[f].col(i - 1)
  107. def getu(f, i):
  108. return faces[f].row(i - 1)
  109. def getd(f, i):
  110. return faces[f].row(n - i)
  111. def setr(f, i, s):
  112. faces[f][:, n - i] = Matrix(n, 1, s)
  113. def setl(f, i, s):
  114. faces[f][:, i - 1] = Matrix(n, 1, s)
  115. def setu(f, i, s):
  116. faces[f][i - 1, :] = Matrix(1, n, s)
  117. def setd(f, i, s):
  118. faces[f][n - i, :] = Matrix(1, n, s)
  119. # motion of a single face
  120. def cw(F, r=1):
  121. for _ in range(r):
  122. face = faces[F]
  123. rv = []
  124. for c in range(n):
  125. for r in range(n - 1, -1, -1):
  126. rv.append(face[r, c])
  127. faces[F] = Matrix(n, n, rv)
  128. def ccw(F):
  129. cw(F, 3)
  130. # motion of plane i from the F side;
  131. # fcw(0) moves the F face, fcw(1) moves the plane
  132. # just behind the front face, etc...
  133. def fcw(i, r=1):
  134. for _ in range(r):
  135. if i == 0:
  136. cw(F)
  137. i += 1
  138. temp = getr(L, i)
  139. setr(L, i, list(getu(D, i)))
  140. setu(D, i, list(reversed(getl(R, i))))
  141. setl(R, i, list(getd(U, i)))
  142. setd(U, i, list(reversed(temp)))
  143. i -= 1
  144. def fccw(i):
  145. fcw(i, 3)
  146. # motion of the entire cube from the F side
  147. def FCW(r=1):
  148. for _ in range(r):
  149. cw(F)
  150. ccw(B)
  151. cw(U)
  152. t = faces[U]
  153. cw(L)
  154. faces[U] = faces[L]
  155. cw(D)
  156. faces[L] = faces[D]
  157. cw(R)
  158. faces[D] = faces[R]
  159. faces[R] = t
  160. def FCCW():
  161. FCW(3)
  162. # motion of the entire cube from the U side
  163. def UCW(r=1):
  164. for _ in range(r):
  165. cw(U)
  166. ccw(D)
  167. t = faces[F]
  168. faces[F] = faces[R]
  169. faces[R] = faces[B]
  170. faces[B] = faces[L]
  171. faces[L] = t
  172. def UCCW():
  173. UCW(3)
  174. # defining the permutations for the cube
  175. U, F, R, B, L, D = names = symbols('U, F, R, B, L, D')
  176. # the faces are represented by nxn matrices
  177. faces = {}
  178. count = 0
  179. for fi in range(6):
  180. f = []
  181. for a in range(n**2):
  182. f.append(count)
  183. count += 1
  184. faces[names[fi]] = Matrix(n, n, f)
  185. # this will either return the value of the current permutation
  186. # (show != 1) or else append the permutation to the group, g
  187. def perm(show=0):
  188. # add perm to the list of perms
  189. p = []
  190. for f in names:
  191. p.extend(faces[f])
  192. if show:
  193. return p
  194. g.append(Permutation(p))
  195. g = [] # container for the group's permutations
  196. I = list(range(6*n**2)) # the identity permutation used for checking
  197. # define permutations corresponding to cw rotations of the planes
  198. # up TO the last plane from that direction; by not including the
  199. # last plane, the orientation of the cube is maintained.
  200. # F slices
  201. for i in range(n - 1):
  202. fcw(i)
  203. perm()
  204. fccw(i) # restore
  205. assert perm(1) == I
  206. # R slices
  207. # bring R to front
  208. UCW()
  209. for i in range(n - 1):
  210. fcw(i)
  211. # put it back in place
  212. UCCW()
  213. # record
  214. perm()
  215. # restore
  216. # bring face to front
  217. UCW()
  218. fccw(i)
  219. # restore
  220. UCCW()
  221. assert perm(1) == I
  222. # D slices
  223. # bring up bottom
  224. FCW()
  225. UCCW()
  226. FCCW()
  227. for i in range(n - 1):
  228. # turn strip
  229. fcw(i)
  230. # put bottom back on the bottom
  231. FCW()
  232. UCW()
  233. FCCW()
  234. # record
  235. perm()
  236. # restore
  237. # bring up bottom
  238. FCW()
  239. UCCW()
  240. FCCW()
  241. # turn strip
  242. fccw(i)
  243. # put bottom back on the bottom
  244. FCW()
  245. UCW()
  246. FCCW()
  247. assert perm(1) == I
  248. return g