test_permutations.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. from itertools import permutations
  2. from sympy.core.expr import unchanged
  3. from sympy.core.numbers import Integer
  4. from sympy.core.relational import Eq
  5. from sympy.core.symbol import Symbol
  6. from sympy.core.singleton import S
  7. from sympy.combinatorics.permutations import \
  8. Permutation, _af_parity, _af_rmul, _af_rmuln, AppliedPermutation, Cycle
  9. from sympy.printing import sstr, srepr, pretty, latex
  10. from sympy.testing.pytest import raises, warns_deprecated_sympy
  11. rmul = Permutation.rmul
  12. a = Symbol('a', integer=True)
  13. def test_Permutation():
  14. # don't auto fill 0
  15. raises(ValueError, lambda: Permutation([1]))
  16. p = Permutation([0, 1, 2, 3])
  17. # call as bijective
  18. assert [p(i) for i in range(p.size)] == list(p)
  19. # call as operator
  20. assert p(list(range(p.size))) == list(p)
  21. # call as function
  22. assert list(p(1, 2)) == [0, 2, 1, 3]
  23. raises(TypeError, lambda: p(-1))
  24. raises(TypeError, lambda: p(5))
  25. # conversion to list
  26. assert list(p) == list(range(4))
  27. assert Permutation(size=4) == Permutation(3)
  28. assert Permutation(Permutation(3), size=5) == Permutation(4)
  29. # cycle form with size
  30. assert Permutation([[1, 2]], size=4) == Permutation([[1, 2], [0], [3]])
  31. # random generation
  32. assert Permutation.random(2) in (Permutation([1, 0]), Permutation([0, 1]))
  33. p = Permutation([2, 5, 1, 6, 3, 0, 4])
  34. q = Permutation([[1], [0, 3, 5, 6, 2, 4]])
  35. assert len({p, p}) == 1
  36. r = Permutation([1, 3, 2, 0, 4, 6, 5])
  37. ans = Permutation(_af_rmuln(*[w.array_form for w in (p, q, r)])).array_form
  38. assert rmul(p, q, r).array_form == ans
  39. # make sure no other permutation of p, q, r could have given
  40. # that answer
  41. for a, b, c in permutations((p, q, r)):
  42. if (a, b, c) == (p, q, r):
  43. continue
  44. assert rmul(a, b, c).array_form != ans
  45. assert p.support() == list(range(7))
  46. assert q.support() == [0, 2, 3, 4, 5, 6]
  47. assert Permutation(p.cyclic_form).array_form == p.array_form
  48. assert p.cardinality == 5040
  49. assert q.cardinality == 5040
  50. assert q.cycles == 2
  51. assert rmul(q, p) == Permutation([4, 6, 1, 2, 5, 3, 0])
  52. assert rmul(p, q) == Permutation([6, 5, 3, 0, 2, 4, 1])
  53. assert _af_rmul(p.array_form, q.array_form) == \
  54. [6, 5, 3, 0, 2, 4, 1]
  55. assert rmul(Permutation([[1, 2, 3], [0, 4]]),
  56. Permutation([[1, 2, 4], [0], [3]])).cyclic_form == \
  57. [[0, 4, 2], [1, 3]]
  58. assert q.array_form == [3, 1, 4, 5, 0, 6, 2]
  59. assert q.cyclic_form == [[0, 3, 5, 6, 2, 4]]
  60. assert q.full_cyclic_form == [[0, 3, 5, 6, 2, 4], [1]]
  61. assert p.cyclic_form == [[0, 2, 1, 5], [3, 6, 4]]
  62. t = p.transpositions()
  63. assert t == [(0, 5), (0, 1), (0, 2), (3, 4), (3, 6)]
  64. assert Permutation.rmul(*[Permutation(Cycle(*ti)) for ti in (t)])
  65. assert Permutation([1, 0]).transpositions() == [(0, 1)]
  66. assert p**13 == p
  67. assert q**0 == Permutation(list(range(q.size)))
  68. assert q**-2 == ~q**2
  69. assert q**2 == Permutation([5, 1, 0, 6, 3, 2, 4])
  70. assert q**3 == q**2*q
  71. assert q**4 == q**2*q**2
  72. a = Permutation(1, 3)
  73. b = Permutation(2, 0, 3)
  74. I = Permutation(3)
  75. assert ~a == a**-1
  76. assert a*~a == I
  77. assert a*b**-1 == a*~b
  78. ans = Permutation(0, 5, 3, 1, 6)(2, 4)
  79. assert (p + q.rank()).rank() == ans.rank()
  80. assert (p + q.rank())._rank == ans.rank()
  81. assert (q + p.rank()).rank() == ans.rank()
  82. raises(TypeError, lambda: p + Permutation(list(range(10))))
  83. assert (p - q.rank()).rank() == Permutation(0, 6, 3, 1, 2, 5, 4).rank()
  84. assert p.rank() - q.rank() < 0 # for coverage: make sure mod is used
  85. assert (q - p.rank()).rank() == Permutation(1, 4, 6, 2)(3, 5).rank()
  86. assert p*q == Permutation(_af_rmuln(*[list(w) for w in (q, p)]))
  87. assert p*Permutation([]) == p
  88. assert Permutation([])*p == p
  89. assert p*Permutation([[0, 1]]) == Permutation([2, 5, 0, 6, 3, 1, 4])
  90. assert Permutation([[0, 1]])*p == Permutation([5, 2, 1, 6, 3, 0, 4])
  91. pq = p ^ q
  92. assert pq == Permutation([5, 6, 0, 4, 1, 2, 3])
  93. assert pq == rmul(q, p, ~q)
  94. qp = q ^ p
  95. assert qp == Permutation([4, 3, 6, 2, 1, 5, 0])
  96. assert qp == rmul(p, q, ~p)
  97. raises(ValueError, lambda: p ^ Permutation([]))
  98. assert p.commutator(q) == Permutation(0, 1, 3, 4, 6, 5, 2)
  99. assert q.commutator(p) == Permutation(0, 2, 5, 6, 4, 3, 1)
  100. assert p.commutator(q) == ~q.commutator(p)
  101. raises(ValueError, lambda: p.commutator(Permutation([])))
  102. assert len(p.atoms()) == 7
  103. assert q.atoms() == {0, 1, 2, 3, 4, 5, 6}
  104. assert p.inversion_vector() == [2, 4, 1, 3, 1, 0]
  105. assert q.inversion_vector() == [3, 1, 2, 2, 0, 1]
  106. assert Permutation.from_inversion_vector(p.inversion_vector()) == p
  107. assert Permutation.from_inversion_vector(q.inversion_vector()).array_form\
  108. == q.array_form
  109. raises(ValueError, lambda: Permutation.from_inversion_vector([0, 2]))
  110. assert Permutation(list(range(500, -1, -1))).inversions() == 125250
  111. s = Permutation([0, 4, 1, 3, 2])
  112. assert s.parity() == 0
  113. _ = s.cyclic_form # needed to create a value for _cyclic_form
  114. assert len(s._cyclic_form) != s.size and s.parity() == 0
  115. assert not s.is_odd
  116. assert s.is_even
  117. assert Permutation([0, 1, 4, 3, 2]).parity() == 1
  118. assert _af_parity([0, 4, 1, 3, 2]) == 0
  119. assert _af_parity([0, 1, 4, 3, 2]) == 1
  120. s = Permutation([0])
  121. assert s.is_Singleton
  122. assert Permutation([]).is_Empty
  123. r = Permutation([3, 2, 1, 0])
  124. assert (r**2).is_Identity
  125. assert rmul(~p, p).is_Identity
  126. assert (~p)**13 == Permutation([5, 2, 0, 4, 6, 1, 3])
  127. assert ~(r**2).is_Identity
  128. assert p.max() == 6
  129. assert p.min() == 0
  130. q = Permutation([[6], [5], [0, 1, 2, 3, 4]])
  131. assert q.max() == 4
  132. assert q.min() == 0
  133. p = Permutation([1, 5, 2, 0, 3, 6, 4])
  134. q = Permutation([[1, 2, 3, 5, 6], [0, 4]])
  135. assert p.ascents() == [0, 3, 4]
  136. assert q.ascents() == [1, 2, 4]
  137. assert r.ascents() == []
  138. assert p.descents() == [1, 2, 5]
  139. assert q.descents() == [0, 3, 5]
  140. assert Permutation(r.descents()).is_Identity
  141. assert p.inversions() == 7
  142. # test the merge-sort with a longer permutation
  143. big = list(p) + list(range(p.max() + 1, p.max() + 130))
  144. assert Permutation(big).inversions() == 7
  145. assert p.signature() == -1
  146. assert q.inversions() == 11
  147. assert q.signature() == -1
  148. assert rmul(p, ~p).inversions() == 0
  149. assert rmul(p, ~p).signature() == 1
  150. assert p.order() == 6
  151. assert q.order() == 10
  152. assert (p**(p.order())).is_Identity
  153. assert p.length() == 6
  154. assert q.length() == 7
  155. assert r.length() == 4
  156. assert p.runs() == [[1, 5], [2], [0, 3, 6], [4]]
  157. assert q.runs() == [[4], [2, 3, 5], [0, 6], [1]]
  158. assert r.runs() == [[3], [2], [1], [0]]
  159. assert p.index() == 8
  160. assert q.index() == 8
  161. assert r.index() == 3
  162. assert p.get_precedence_distance(q) == q.get_precedence_distance(p)
  163. assert p.get_adjacency_distance(q) == p.get_adjacency_distance(q)
  164. assert p.get_positional_distance(q) == p.get_positional_distance(q)
  165. p = Permutation([0, 1, 2, 3])
  166. q = Permutation([3, 2, 1, 0])
  167. assert p.get_precedence_distance(q) == 6
  168. assert p.get_adjacency_distance(q) == 3
  169. assert p.get_positional_distance(q) == 8
  170. p = Permutation([0, 3, 1, 2, 4])
  171. q = Permutation.josephus(4, 5, 2)
  172. assert p.get_adjacency_distance(q) == 3
  173. raises(ValueError, lambda: p.get_adjacency_distance(Permutation([])))
  174. raises(ValueError, lambda: p.get_positional_distance(Permutation([])))
  175. raises(ValueError, lambda: p.get_precedence_distance(Permutation([])))
  176. a = [Permutation.unrank_nonlex(4, i) for i in range(5)]
  177. iden = Permutation([0, 1, 2, 3])
  178. for i in range(5):
  179. for j in range(i + 1, 5):
  180. assert a[i].commutes_with(a[j]) == \
  181. (rmul(a[i], a[j]) == rmul(a[j], a[i]))
  182. if a[i].commutes_with(a[j]):
  183. assert a[i].commutator(a[j]) == iden
  184. assert a[j].commutator(a[i]) == iden
  185. a = Permutation(3)
  186. b = Permutation(0, 6, 3)(1, 2)
  187. assert a.cycle_structure == {1: 4}
  188. assert b.cycle_structure == {2: 1, 3: 1, 1: 2}
  189. # issue 11130
  190. raises(ValueError, lambda: Permutation(3, size=3))
  191. raises(ValueError, lambda: Permutation([1, 2, 0, 3], size=3))
  192. def test_Permutation_subclassing():
  193. # Subclass that adds permutation application on iterables
  194. class CustomPermutation(Permutation):
  195. def __call__(self, *i):
  196. try:
  197. return super().__call__(*i)
  198. except TypeError:
  199. pass
  200. try:
  201. perm_obj = i[0]
  202. return [self._array_form[j] for j in perm_obj]
  203. except TypeError:
  204. raise TypeError('unrecognized argument')
  205. def __eq__(self, other):
  206. if isinstance(other, Permutation):
  207. return self._hashable_content() == other._hashable_content()
  208. else:
  209. return super().__eq__(other)
  210. def __hash__(self):
  211. return super().__hash__()
  212. p = CustomPermutation([1, 2, 3, 0])
  213. q = Permutation([1, 2, 3, 0])
  214. assert p == q
  215. raises(TypeError, lambda: q([1, 2]))
  216. assert [2, 3] == p([1, 2])
  217. assert type(p * q) == CustomPermutation
  218. assert type(q * p) == Permutation # True because q.__mul__(p) is called!
  219. # Run all tests for the Permutation class also on the subclass
  220. def wrapped_test_Permutation():
  221. # Monkeypatch the class definition in the globals
  222. globals()['__Perm'] = globals()['Permutation']
  223. globals()['Permutation'] = CustomPermutation
  224. test_Permutation()
  225. globals()['Permutation'] = globals()['__Perm'] # Restore
  226. del globals()['__Perm']
  227. wrapped_test_Permutation()
  228. def test_josephus():
  229. assert Permutation.josephus(4, 6, 1) == Permutation([3, 1, 0, 2, 5, 4])
  230. assert Permutation.josephus(1, 5, 1).is_Identity
  231. def test_ranking():
  232. assert Permutation.unrank_lex(5, 10).rank() == 10
  233. p = Permutation.unrank_lex(15, 225)
  234. assert p.rank() == 225
  235. p1 = p.next_lex()
  236. assert p1.rank() == 226
  237. assert Permutation.unrank_lex(15, 225).rank() == 225
  238. assert Permutation.unrank_lex(10, 0).is_Identity
  239. p = Permutation.unrank_lex(4, 23)
  240. assert p.rank() == 23
  241. assert p.array_form == [3, 2, 1, 0]
  242. assert p.next_lex() is None
  243. p = Permutation([1, 5, 2, 0, 3, 6, 4])
  244. q = Permutation([[1, 2, 3, 5, 6], [0, 4]])
  245. a = [Permutation.unrank_trotterjohnson(4, i).array_form for i in range(5)]
  246. assert a == [[0, 1, 2, 3], [0, 1, 3, 2], [0, 3, 1, 2], [3, 0, 1,
  247. 2], [3, 0, 2, 1] ]
  248. assert [Permutation(pa).rank_trotterjohnson() for pa in a] == list(range(5))
  249. assert Permutation([0, 1, 2, 3]).next_trotterjohnson() == \
  250. Permutation([0, 1, 3, 2])
  251. assert q.rank_trotterjohnson() == 2283
  252. assert p.rank_trotterjohnson() == 3389
  253. assert Permutation([1, 0]).rank_trotterjohnson() == 1
  254. a = Permutation(list(range(3)))
  255. b = a
  256. l = []
  257. tj = []
  258. for i in range(6):
  259. l.append(a)
  260. tj.append(b)
  261. a = a.next_lex()
  262. b = b.next_trotterjohnson()
  263. assert a == b is None
  264. assert {tuple(a) for a in l} == {tuple(a) for a in tj}
  265. p = Permutation([2, 5, 1, 6, 3, 0, 4])
  266. q = Permutation([[6], [5], [0, 1, 2, 3, 4]])
  267. assert p.rank() == 1964
  268. assert q.rank() == 870
  269. assert Permutation([]).rank_nonlex() == 0
  270. prank = p.rank_nonlex()
  271. assert prank == 1600
  272. assert Permutation.unrank_nonlex(7, 1600) == p
  273. qrank = q.rank_nonlex()
  274. assert qrank == 41
  275. assert Permutation.unrank_nonlex(7, 41) == Permutation(q.array_form)
  276. a = [Permutation.unrank_nonlex(4, i).array_form for i in range(24)]
  277. assert a == [
  278. [1, 2, 3, 0], [3, 2, 0, 1], [1, 3, 0, 2], [1, 2, 0, 3], [2, 3, 1, 0],
  279. [2, 0, 3, 1], [3, 0, 1, 2], [2, 0, 1, 3], [1, 3, 2, 0], [3, 0, 2, 1],
  280. [1, 0, 3, 2], [1, 0, 2, 3], [2, 1, 3, 0], [2, 3, 0, 1], [3, 1, 0, 2],
  281. [2, 1, 0, 3], [3, 2, 1, 0], [0, 2, 3, 1], [0, 3, 1, 2], [0, 2, 1, 3],
  282. [3, 1, 2, 0], [0, 3, 2, 1], [0, 1, 3, 2], [0, 1, 2, 3]]
  283. N = 10
  284. p1 = Permutation(a[0])
  285. for i in range(1, N+1):
  286. p1 = p1*Permutation(a[i])
  287. p2 = Permutation.rmul_with_af(*[Permutation(h) for h in a[N::-1]])
  288. assert p1 == p2
  289. ok = []
  290. p = Permutation([1, 0])
  291. for i in range(3):
  292. ok.append(p.array_form)
  293. p = p.next_nonlex()
  294. if p is None:
  295. ok.append(None)
  296. break
  297. assert ok == [[1, 0], [0, 1], None]
  298. assert Permutation([3, 2, 0, 1]).next_nonlex() == Permutation([1, 3, 0, 2])
  299. assert [Permutation(pa).rank_nonlex() for pa in a] == list(range(24))
  300. def test_mul():
  301. a, b = [0, 2, 1, 3], [0, 1, 3, 2]
  302. assert _af_rmul(a, b) == [0, 2, 3, 1]
  303. assert _af_rmuln(a, b, list(range(4))) == [0, 2, 3, 1]
  304. assert rmul(Permutation(a), Permutation(b)).array_form == [0, 2, 3, 1]
  305. a = Permutation([0, 2, 1, 3])
  306. b = (0, 1, 3, 2)
  307. c = (3, 1, 2, 0)
  308. assert Permutation.rmul(a, b, c) == Permutation([1, 2, 3, 0])
  309. assert Permutation.rmul(a, c) == Permutation([3, 2, 1, 0])
  310. raises(TypeError, lambda: Permutation.rmul(b, c))
  311. n = 6
  312. m = 8
  313. a = [Permutation.unrank_nonlex(n, i).array_form for i in range(m)]
  314. h = list(range(n))
  315. for i in range(m):
  316. h = _af_rmul(h, a[i])
  317. h2 = _af_rmuln(*a[:i + 1])
  318. assert h == h2
  319. def test_args():
  320. p = Permutation([(0, 3, 1, 2), (4, 5)])
  321. assert p._cyclic_form is None
  322. assert Permutation(p) == p
  323. assert p.cyclic_form == [[0, 3, 1, 2], [4, 5]]
  324. assert p._array_form == [3, 2, 0, 1, 5, 4]
  325. p = Permutation((0, 3, 1, 2))
  326. assert p._cyclic_form is None
  327. assert p._array_form == [0, 3, 1, 2]
  328. assert Permutation([0]) == Permutation((0, ))
  329. assert Permutation([[0], [1]]) == Permutation(((0, ), (1, ))) == \
  330. Permutation(((0, ), [1]))
  331. assert Permutation([[1, 2]]) == Permutation([0, 2, 1])
  332. assert Permutation([[1], [4, 2]]) == Permutation([0, 1, 4, 3, 2])
  333. assert Permutation([[1], [4, 2]], size=1) == Permutation([0, 1, 4, 3, 2])
  334. assert Permutation(
  335. [[1], [4, 2]], size=6) == Permutation([0, 1, 4, 3, 2, 5])
  336. assert Permutation([[0, 1], [0, 2]]) == Permutation(0, 1, 2)
  337. assert Permutation([], size=3) == Permutation([0, 1, 2])
  338. assert Permutation(3).list(5) == [0, 1, 2, 3, 4]
  339. assert Permutation(3).list(-1) == []
  340. assert Permutation(5)(1, 2).list(-1) == [0, 2, 1]
  341. assert Permutation(5)(1, 2).list() == [0, 2, 1, 3, 4, 5]
  342. raises(ValueError, lambda: Permutation([1, 2], [0]))
  343. # enclosing brackets needed
  344. raises(ValueError, lambda: Permutation([[1, 2], 0]))
  345. # enclosing brackets needed on 0
  346. raises(ValueError, lambda: Permutation([1, 1, 0]))
  347. raises(ValueError, lambda: Permutation([4, 5], size=10)) # where are 0-3?
  348. # but this is ok because cycles imply that only those listed moved
  349. assert Permutation(4, 5) == Permutation([0, 1, 2, 3, 5, 4])
  350. def test_Cycle():
  351. assert str(Cycle()) == '()'
  352. assert Cycle(Cycle(1,2)) == Cycle(1, 2)
  353. assert Cycle(1,2).copy() == Cycle(1,2)
  354. assert list(Cycle(1, 3, 2)) == [0, 3, 1, 2]
  355. assert Cycle(1, 2)(2, 3) == Cycle(1, 3, 2)
  356. assert Cycle(1, 2)(2, 3)(4, 5) == Cycle(1, 3, 2)(4, 5)
  357. assert Permutation(Cycle(1, 2)(2, 1, 0, 3)).cyclic_form, Cycle(0, 2, 1)
  358. raises(ValueError, lambda: Cycle().list())
  359. assert Cycle(1, 2).list() == [0, 2, 1]
  360. assert Cycle(1, 2).list(4) == [0, 2, 1, 3]
  361. assert Cycle(3).list(2) == [0, 1]
  362. assert Cycle(3).list(6) == [0, 1, 2, 3, 4, 5]
  363. assert Permutation(Cycle(1, 2), size=4) == \
  364. Permutation([0, 2, 1, 3])
  365. assert str(Cycle(1, 2)(4, 5)) == '(1 2)(4 5)'
  366. assert str(Cycle(1, 2)) == '(1 2)'
  367. assert Cycle(Permutation(list(range(3)))) == Cycle()
  368. assert Cycle(1, 2).list() == [0, 2, 1]
  369. assert Cycle(1, 2).list(4) == [0, 2, 1, 3]
  370. assert Cycle().size == 0
  371. raises(ValueError, lambda: Cycle((1, 2)))
  372. raises(ValueError, lambda: Cycle(1, 2, 1))
  373. raises(TypeError, lambda: Cycle(1, 2)*{})
  374. raises(ValueError, lambda: Cycle(4)[a])
  375. raises(ValueError, lambda: Cycle(2, -4, 3))
  376. # check round-trip
  377. p = Permutation([[1, 2], [4, 3]], size=5)
  378. assert Permutation(Cycle(p)) == p
  379. def test_from_sequence():
  380. assert Permutation.from_sequence('SymPy') == Permutation(4)(0, 1, 3)
  381. assert Permutation.from_sequence('SymPy', key=lambda x: x.lower()) == \
  382. Permutation(4)(0, 2)(1, 3)
  383. def test_resize():
  384. p = Permutation(0, 1, 2)
  385. assert p.resize(5) == Permutation(0, 1, 2, size=5)
  386. assert p.resize(4) == Permutation(0, 1, 2, size=4)
  387. assert p.resize(3) == p
  388. raises(ValueError, lambda: p.resize(2))
  389. p = Permutation(0, 1, 2)(3, 4)(5, 6)
  390. assert p.resize(3) == Permutation(0, 1, 2)
  391. raises(ValueError, lambda: p.resize(4))
  392. def test_printing_cyclic():
  393. p1 = Permutation([0, 2, 1])
  394. assert repr(p1) == 'Permutation(1, 2)'
  395. assert str(p1) == '(1 2)'
  396. p2 = Permutation()
  397. assert repr(p2) == 'Permutation()'
  398. assert str(p2) == '()'
  399. p3 = Permutation([1, 2, 0, 3])
  400. assert repr(p3) == 'Permutation(3)(0, 1, 2)'
  401. def test_printing_non_cyclic():
  402. p1 = Permutation([0, 1, 2, 3, 4, 5])
  403. assert srepr(p1, perm_cyclic=False) == 'Permutation([], size=6)'
  404. assert sstr(p1, perm_cyclic=False) == 'Permutation([], size=6)'
  405. p2 = Permutation([0, 1, 2])
  406. assert srepr(p2, perm_cyclic=False) == 'Permutation([0, 1, 2])'
  407. assert sstr(p2, perm_cyclic=False) == 'Permutation([0, 1, 2])'
  408. p3 = Permutation([0, 2, 1])
  409. assert srepr(p3, perm_cyclic=False) == 'Permutation([0, 2, 1])'
  410. assert sstr(p3, perm_cyclic=False) == 'Permutation([0, 2, 1])'
  411. p4 = Permutation([0, 1, 3, 2, 4, 5, 6, 7])
  412. assert srepr(p4, perm_cyclic=False) == 'Permutation([0, 1, 3, 2], size=8)'
  413. def test_deprecated_print_cyclic():
  414. p = Permutation(0, 1, 2)
  415. try:
  416. Permutation.print_cyclic = True
  417. with warns_deprecated_sympy():
  418. assert sstr(p) == '(0 1 2)'
  419. with warns_deprecated_sympy():
  420. assert srepr(p) == 'Permutation(0, 1, 2)'
  421. with warns_deprecated_sympy():
  422. assert pretty(p) == '(0 1 2)'
  423. with warns_deprecated_sympy():
  424. assert latex(p) == r'\left( 0\; 1\; 2\right)'
  425. Permutation.print_cyclic = False
  426. with warns_deprecated_sympy():
  427. assert sstr(p) == 'Permutation([1, 2, 0])'
  428. with warns_deprecated_sympy():
  429. assert srepr(p) == 'Permutation([1, 2, 0])'
  430. with warns_deprecated_sympy():
  431. assert pretty(p, use_unicode=False) == '/0 1 2\\\n\\1 2 0/'
  432. with warns_deprecated_sympy():
  433. assert latex(p) == \
  434. r'\begin{pmatrix} 0 & 1 & 2 \\ 1 & 2 & 0 \end{pmatrix}'
  435. finally:
  436. Permutation.print_cyclic = None
  437. def test_permutation_equality():
  438. a = Permutation(0, 1, 2)
  439. b = Permutation(0, 1, 2)
  440. assert Eq(a, b) is S.true
  441. c = Permutation(0, 2, 1)
  442. assert Eq(a, c) is S.false
  443. d = Permutation(0, 1, 2, size=4)
  444. assert unchanged(Eq, a, d)
  445. e = Permutation(0, 2, 1, size=4)
  446. assert unchanged(Eq, a, e)
  447. i = Permutation()
  448. assert unchanged(Eq, i, 0)
  449. assert unchanged(Eq, 0, i)
  450. def test_issue_17661():
  451. c1 = Cycle(1,2)
  452. c2 = Cycle(1,2)
  453. assert c1 == c2
  454. assert repr(c1) == 'Cycle(1, 2)'
  455. assert c1 == c2
  456. def test_permutation_apply():
  457. x = Symbol('x')
  458. p = Permutation(0, 1, 2)
  459. assert p.apply(0) == 1
  460. assert isinstance(p.apply(0), Integer)
  461. assert p.apply(x) == AppliedPermutation(p, x)
  462. assert AppliedPermutation(p, x).subs(x, 0) == 1
  463. x = Symbol('x', integer=False)
  464. raises(NotImplementedError, lambda: p.apply(x))
  465. x = Symbol('x', negative=True)
  466. raises(NotImplementedError, lambda: p.apply(x))
  467. def test_AppliedPermutation():
  468. x = Symbol('x')
  469. p = Permutation(0, 1, 2)
  470. raises(ValueError, lambda: AppliedPermutation((0, 1, 2), x))
  471. assert AppliedPermutation(p, 1, evaluate=True) == 2
  472. assert AppliedPermutation(p, 1, evaluate=False).__class__ == \
  473. AppliedPermutation