weyl_group.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. # -*- coding: utf-8 -*-
  2. from .cartan_type import CartanType
  3. from mpmath import fac
  4. from sympy.core.backend import Matrix, eye, Rational, igcd
  5. from sympy.core.basic import Atom
  6. class WeylGroup(Atom):
  7. """
  8. For each semisimple Lie group, we have a Weyl group. It is a subgroup of
  9. the isometry group of the root system. Specifically, it's the subgroup
  10. that is generated by reflections through the hyperplanes orthogonal to
  11. the roots. Therefore, Weyl groups are reflection groups, and so a Weyl
  12. group is a finite Coxeter group.
  13. """
  14. def __new__(cls, cartantype):
  15. obj = Atom.__new__(cls)
  16. obj.cartan_type = CartanType(cartantype)
  17. return obj
  18. def generators(self):
  19. """
  20. This method creates the generating reflections of the Weyl group for
  21. a given Lie algebra. For a Lie algebra of rank n, there are n
  22. different generating reflections. This function returns them as
  23. a list.
  24. Examples
  25. ========
  26. >>> from sympy.liealgebras.weyl_group import WeylGroup
  27. >>> c = WeylGroup("F4")
  28. >>> c.generators()
  29. ['r1', 'r2', 'r3', 'r4']
  30. """
  31. n = self.cartan_type.rank()
  32. generators = []
  33. for i in range(1, n+1):
  34. reflection = "r"+str(i)
  35. generators.append(reflection)
  36. return generators
  37. def group_order(self):
  38. """
  39. This method returns the order of the Weyl group.
  40. For types A, B, C, D, and E the order depends on
  41. the rank of the Lie algebra. For types F and G,
  42. the order is fixed.
  43. Examples
  44. ========
  45. >>> from sympy.liealgebras.weyl_group import WeylGroup
  46. >>> c = WeylGroup("D4")
  47. >>> c.group_order()
  48. 192.0
  49. """
  50. n = self.cartan_type.rank()
  51. if self.cartan_type.series == "A":
  52. return fac(n+1)
  53. if self.cartan_type.series in ("B", "C"):
  54. return fac(n)*(2**n)
  55. if self.cartan_type.series == "D":
  56. return fac(n)*(2**(n-1))
  57. if self.cartan_type.series == "E":
  58. if n == 6:
  59. return 51840
  60. if n == 7:
  61. return 2903040
  62. if n == 8:
  63. return 696729600
  64. if self.cartan_type.series == "F":
  65. return 1152
  66. if self.cartan_type.series == "G":
  67. return 12
  68. def group_name(self):
  69. """
  70. This method returns some general information about the Weyl group for
  71. a given Lie algebra. It returns the name of the group and the elements
  72. it acts on, if relevant.
  73. """
  74. n = self.cartan_type.rank()
  75. if self.cartan_type.series == "A":
  76. return "S"+str(n+1) + ": the symmetric group acting on " + str(n+1) + " elements."
  77. if self.cartan_type.series in ("B", "C"):
  78. return "The hyperoctahedral group acting on " + str(2*n) + " elements."
  79. if self.cartan_type.series == "D":
  80. return "The symmetry group of the " + str(n) + "-dimensional demihypercube."
  81. if self.cartan_type.series == "E":
  82. if n == 6:
  83. return "The symmetry group of the 6-polytope."
  84. if n == 7:
  85. return "The symmetry group of the 7-polytope."
  86. if n == 8:
  87. return "The symmetry group of the 8-polytope."
  88. if self.cartan_type.series == "F":
  89. return "The symmetry group of the 24-cell, or icositetrachoron."
  90. if self.cartan_type.series == "G":
  91. return "D6, the dihedral group of order 12, and symmetry group of the hexagon."
  92. def element_order(self, weylelt):
  93. """
  94. This method returns the order of a given Weyl group element, which should
  95. be specified by the user in the form of products of the generating
  96. reflections, i.e. of the form r1*r2 etc.
  97. For types A-F, this method current works by taking the matrix form of
  98. the specified element, and then finding what power of the matrix is the
  99. identity. It then returns this power.
  100. Examples
  101. ========
  102. >>> from sympy.liealgebras.weyl_group import WeylGroup
  103. >>> b = WeylGroup("B4")
  104. >>> b.element_order('r1*r4*r2')
  105. 4
  106. """
  107. n = self.cartan_type.rank()
  108. if self.cartan_type.series == "A":
  109. a = self.matrix_form(weylelt)
  110. order = 1
  111. while a != eye(n+1):
  112. a *= self.matrix_form(weylelt)
  113. order += 1
  114. return order
  115. if self.cartan_type.series == "D":
  116. a = self.matrix_form(weylelt)
  117. order = 1
  118. while a != eye(n):
  119. a *= self.matrix_form(weylelt)
  120. order += 1
  121. return order
  122. if self.cartan_type.series == "E":
  123. a = self.matrix_form(weylelt)
  124. order = 1
  125. while a != eye(8):
  126. a *= self.matrix_form(weylelt)
  127. order += 1
  128. return order
  129. if self.cartan_type.series == "G":
  130. elts = list(weylelt)
  131. reflections = elts[1::3]
  132. m = self.delete_doubles(reflections)
  133. while self.delete_doubles(m) != m:
  134. m = self.delete_doubles(m)
  135. reflections = m
  136. if len(reflections) % 2 == 1:
  137. return 2
  138. elif len(reflections) == 0:
  139. return 1
  140. else:
  141. if len(reflections) == 1:
  142. return 2
  143. else:
  144. m = len(reflections) // 2
  145. lcm = (6 * m)/ igcd(m, 6)
  146. order = lcm / m
  147. return order
  148. if self.cartan_type.series == 'F':
  149. a = self.matrix_form(weylelt)
  150. order = 1
  151. while a != eye(4):
  152. a *= self.matrix_form(weylelt)
  153. order += 1
  154. return order
  155. if self.cartan_type.series in ("B", "C"):
  156. a = self.matrix_form(weylelt)
  157. order = 1
  158. while a != eye(n):
  159. a *= self.matrix_form(weylelt)
  160. order += 1
  161. return order
  162. def delete_doubles(self, reflections):
  163. """
  164. This is a helper method for determining the order of an element in the
  165. Weyl group of G2. It takes a Weyl element and if repeated simple reflections
  166. in it, it deletes them.
  167. """
  168. counter = 0
  169. copy = list(reflections)
  170. for elt in copy:
  171. if counter < len(copy)-1:
  172. if copy[counter + 1] == elt:
  173. del copy[counter]
  174. del copy[counter]
  175. counter += 1
  176. return copy
  177. def matrix_form(self, weylelt):
  178. """
  179. This method takes input from the user in the form of products of the
  180. generating reflections, and returns the matrix corresponding to the
  181. element of the Weyl group. Since each element of the Weyl group is
  182. a reflection of some type, there is a corresponding matrix representation.
  183. This method uses the standard representation for all the generating
  184. reflections.
  185. Examples
  186. ========
  187. >>> from sympy.liealgebras.weyl_group import WeylGroup
  188. >>> f = WeylGroup("F4")
  189. >>> f.matrix_form('r2*r3')
  190. Matrix([
  191. [1, 0, 0, 0],
  192. [0, 1, 0, 0],
  193. [0, 0, 0, -1],
  194. [0, 0, 1, 0]])
  195. """
  196. elts = list(weylelt)
  197. reflections = elts[1::3]
  198. n = self.cartan_type.rank()
  199. if self.cartan_type.series == 'A':
  200. matrixform = eye(n+1)
  201. for elt in reflections:
  202. a = int(elt)
  203. mat = eye(n+1)
  204. mat[a-1, a-1] = 0
  205. mat[a-1, a] = 1
  206. mat[a, a-1] = 1
  207. mat[a, a] = 0
  208. matrixform *= mat
  209. return matrixform
  210. if self.cartan_type.series == 'D':
  211. matrixform = eye(n)
  212. for elt in reflections:
  213. a = int(elt)
  214. mat = eye(n)
  215. if a < n:
  216. mat[a-1, a-1] = 0
  217. mat[a-1, a] = 1
  218. mat[a, a-1] = 1
  219. mat[a, a] = 0
  220. matrixform *= mat
  221. else:
  222. mat[n-2, n-1] = -1
  223. mat[n-2, n-2] = 0
  224. mat[n-1, n-2] = -1
  225. mat[n-1, n-1] = 0
  226. matrixform *= mat
  227. return matrixform
  228. if self.cartan_type.series == 'G':
  229. matrixform = eye(3)
  230. for elt in reflections:
  231. a = int(elt)
  232. if a == 1:
  233. gen1 = Matrix([[1, 0, 0], [0, 0, 1], [0, 1, 0]])
  234. matrixform *= gen1
  235. else:
  236. gen2 = Matrix([[Rational(2, 3), Rational(2, 3), Rational(-1, 3)],
  237. [Rational(2, 3), Rational(-1, 3), Rational(2, 3)],
  238. [Rational(-1, 3), Rational(2, 3), Rational(2, 3)]])
  239. matrixform *= gen2
  240. return matrixform
  241. if self.cartan_type.series == 'F':
  242. matrixform = eye(4)
  243. for elt in reflections:
  244. a = int(elt)
  245. if a == 1:
  246. mat = Matrix([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]])
  247. matrixform *= mat
  248. elif a == 2:
  249. mat = Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])
  250. matrixform *= mat
  251. elif a == 3:
  252. mat = Matrix([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1]])
  253. matrixform *= mat
  254. else:
  255. mat = Matrix([[Rational(1, 2), Rational(1, 2), Rational(1, 2), Rational(1, 2)],
  256. [Rational(1, 2), Rational(1, 2), Rational(-1, 2), Rational(-1, 2)],
  257. [Rational(1, 2), Rational(-1, 2), Rational(1, 2), Rational(-1, 2)],
  258. [Rational(1, 2), Rational(-1, 2), Rational(-1, 2), Rational(1, 2)]])
  259. matrixform *= mat
  260. return matrixform
  261. if self.cartan_type.series == 'E':
  262. matrixform = eye(8)
  263. for elt in reflections:
  264. a = int(elt)
  265. if a == 1:
  266. mat = Matrix([[Rational(3, 4), Rational(1, 4), Rational(1, 4), Rational(1, 4),
  267. Rational(1, 4), Rational(1, 4), Rational(1, 4), Rational(-1, 4)],
  268. [Rational(1, 4), Rational(3, 4), Rational(-1, 4), Rational(-1, 4),
  269. Rational(-1, 4), Rational(-1, 4), Rational(1, 4), Rational(-1, 4)],
  270. [Rational(1, 4), Rational(-1, 4), Rational(3, 4), Rational(-1, 4),
  271. Rational(-1, 4), Rational(-1, 4), Rational(-1, 4), Rational(1, 4)],
  272. [Rational(1, 4), Rational(-1, 4), Rational(-1, 4), Rational(3, 4),
  273. Rational(-1, 4), Rational(-1, 4), Rational(-1, 4), Rational(1, 4)],
  274. [Rational(1, 4), Rational(-1, 4), Rational(-1, 4), Rational(-1, 4),
  275. Rational(3, 4), Rational(-1, 4), Rational(-1, 4), Rational(1, 4)],
  276. [Rational(1, 4), Rational(-1, 4), Rational(-1, 4), Rational(-1, 4),
  277. Rational(-1, 4), Rational(3, 4), Rational(-1, 4), Rational(1, 4)],
  278. [Rational(1, 4), Rational(-1, 4), Rational(-1, 4), Rational(-1, 4),
  279. Rational(-1, 4), Rational(-1, 4), Rational(-3, 4), Rational(1, 4)],
  280. [Rational(1, 4), Rational(-1, 4), Rational(-1, 4), Rational(-1, 4),
  281. Rational(-1, 4), Rational(-1, 4), Rational(-1, 4), Rational(3, 4)]])
  282. matrixform *= mat
  283. elif a == 2:
  284. mat = eye(8)
  285. mat[0, 0] = 0
  286. mat[0, 1] = -1
  287. mat[1, 0] = -1
  288. mat[1, 1] = 0
  289. matrixform *= mat
  290. else:
  291. mat = eye(8)
  292. mat[a-3, a-3] = 0
  293. mat[a-3, a-2] = 1
  294. mat[a-2, a-3] = 1
  295. mat[a-2, a-2] = 0
  296. matrixform *= mat
  297. return matrixform
  298. if self.cartan_type.series in ("B", "C"):
  299. matrixform = eye(n)
  300. for elt in reflections:
  301. a = int(elt)
  302. mat = eye(n)
  303. if a == 1:
  304. mat[0, 0] = -1
  305. matrixform *= mat
  306. else:
  307. mat[a - 2, a - 2] = 0
  308. mat[a-2, a-1] = 1
  309. mat[a - 1, a - 2] = 1
  310. mat[a -1, a - 1] = 0
  311. matrixform *= mat
  312. return matrixform
  313. def coxeter_diagram(self):
  314. """
  315. This method returns the Coxeter diagram corresponding to a Weyl group.
  316. The Coxeter diagram can be obtained from a Lie algebra's Dynkin diagram
  317. by deleting all arrows; the Coxeter diagram is the undirected graph.
  318. The vertices of the Coxeter diagram represent the generating reflections
  319. of the Weyl group, $s_i$. An edge is drawn between $s_i$ and $s_j$ if the order
  320. $m(i, j)$ of $s_is_j$ is greater than two. If there is one edge, the order
  321. $m(i, j)$ is 3. If there are two edges, the order $m(i, j)$ is 4, and if there
  322. are three edges, the order $m(i, j)$ is 6.
  323. Examples
  324. ========
  325. >>> from sympy.liealgebras.weyl_group import WeylGroup
  326. >>> c = WeylGroup("B3")
  327. >>> print(c.coxeter_diagram())
  328. 0---0===0
  329. 1 2 3
  330. """
  331. n = self.cartan_type.rank()
  332. if self.cartan_type.series in ("A", "D", "E"):
  333. return self.cartan_type.dynkin_diagram()
  334. if self.cartan_type.series in ("B", "C"):
  335. diag = "---".join("0" for i in range(1, n)) + "===0\n"
  336. diag += " ".join(str(i) for i in range(1, n+1))
  337. return diag
  338. if self.cartan_type.series == "F":
  339. diag = "0---0===0---0\n"
  340. diag += " ".join(str(i) for i in range(1, 5))
  341. return diag
  342. if self.cartan_type.series == "G":
  343. diag = "0≡≡≡0\n1 2"
  344. return diag