generators.py 7.3 KB

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