test_permutations.py 20 KB

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