test_secondquant.py 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280
  1. from sympy.physics.secondquant import (
  2. Dagger, Bd, VarBosonicBasis, BBra, B, BKet, FixedBosonicBasis,
  3. matrix_rep, apply_operators, InnerProduct, Commutator, KroneckerDelta,
  4. AnnihilateBoson, CreateBoson, BosonicOperator,
  5. F, Fd, FKet, BosonState, CreateFermion, AnnihilateFermion,
  6. evaluate_deltas, AntiSymmetricTensor, contraction, NO, wicks,
  7. PermutationOperator, simplify_index_permutations,
  8. _sort_anticommuting_fermions, _get_ordered_dummies,
  9. substitute_dummies, FockStateBosonKet,
  10. ContractionAppliesOnlyToFermions
  11. )
  12. from sympy.concrete.summations import Sum
  13. from sympy.core.function import (Function, expand)
  14. from sympy.core.numbers import (I, Rational)
  15. from sympy.core.singleton import S
  16. from sympy.core.symbol import (Dummy, Symbol, symbols)
  17. from sympy.functions.elementary.miscellaneous import sqrt
  18. from sympy.printing.repr import srepr
  19. from sympy.simplify.simplify import simplify
  20. from sympy.testing.pytest import slow, raises
  21. from sympy.printing.latex import latex
  22. def test_PermutationOperator():
  23. p, q, r, s = symbols('p,q,r,s')
  24. f, g, h, i = map(Function, 'fghi')
  25. P = PermutationOperator
  26. assert P(p, q).get_permuted(f(p)*g(q)) == -f(q)*g(p)
  27. assert P(p, q).get_permuted(f(p, q)) == -f(q, p)
  28. assert P(p, q).get_permuted(f(p)) == f(p)
  29. expr = (f(p)*g(q)*h(r)*i(s)
  30. - f(q)*g(p)*h(r)*i(s)
  31. - f(p)*g(q)*h(s)*i(r)
  32. + f(q)*g(p)*h(s)*i(r))
  33. perms = [P(p, q), P(r, s)]
  34. assert (simplify_index_permutations(expr, perms) ==
  35. P(p, q)*P(r, s)*f(p)*g(q)*h(r)*i(s))
  36. assert latex(P(p, q)) == 'P(pq)'
  37. def test_index_permutations_with_dummies():
  38. a, b, c, d = symbols('a b c d')
  39. p, q, r, s = symbols('p q r s', cls=Dummy)
  40. f, g = map(Function, 'fg')
  41. P = PermutationOperator
  42. # No dummy substitution necessary
  43. expr = f(a, b, p, q) - f(b, a, p, q)
  44. assert simplify_index_permutations(
  45. expr, [P(a, b)]) == P(a, b)*f(a, b, p, q)
  46. # Cases where dummy substitution is needed
  47. expected = P(a, b)*substitute_dummies(f(a, b, p, q))
  48. expr = f(a, b, p, q) - f(b, a, q, p)
  49. result = simplify_index_permutations(expr, [P(a, b)])
  50. assert expected == substitute_dummies(result)
  51. expr = f(a, b, q, p) - f(b, a, p, q)
  52. result = simplify_index_permutations(expr, [P(a, b)])
  53. assert expected == substitute_dummies(result)
  54. # A case where nothing can be done
  55. expr = f(a, b, q, p) - g(b, a, p, q)
  56. result = simplify_index_permutations(expr, [P(a, b)])
  57. assert expr == result
  58. def test_dagger():
  59. i, j, n, m = symbols('i,j,n,m')
  60. assert Dagger(1) == 1
  61. assert Dagger(1.0) == 1.0
  62. assert Dagger(2*I) == -2*I
  63. assert Dagger(S.Half*I/3.0) == I*Rational(-1, 2)/3.0
  64. assert Dagger(BKet([n])) == BBra([n])
  65. assert Dagger(B(0)) == Bd(0)
  66. assert Dagger(Bd(0)) == B(0)
  67. assert Dagger(B(n)) == Bd(n)
  68. assert Dagger(Bd(n)) == B(n)
  69. assert Dagger(B(0) + B(1)) == Bd(0) + Bd(1)
  70. assert Dagger(n*m) == Dagger(n)*Dagger(m) # n, m commute
  71. assert Dagger(B(n)*B(m)) == Bd(m)*Bd(n)
  72. assert Dagger(B(n)**10) == Dagger(B(n))**10
  73. assert Dagger('a') == Dagger(Symbol('a'))
  74. assert Dagger(Dagger('a')) == Symbol('a')
  75. def test_operator():
  76. i, j = symbols('i,j')
  77. o = BosonicOperator(i)
  78. assert o.state == i
  79. assert o.is_symbolic
  80. o = BosonicOperator(1)
  81. assert o.state == 1
  82. assert not o.is_symbolic
  83. def test_create():
  84. i, j, n, m = symbols('i,j,n,m')
  85. o = Bd(i)
  86. assert latex(o) == "{b^\\dagger_{i}}"
  87. assert isinstance(o, CreateBoson)
  88. o = o.subs(i, j)
  89. assert o.atoms(Symbol) == {j}
  90. o = Bd(0)
  91. assert o.apply_operator(BKet([n])) == sqrt(n + 1)*BKet([n + 1])
  92. o = Bd(n)
  93. assert o.apply_operator(BKet([n])) == o*BKet([n])
  94. def test_annihilate():
  95. i, j, n, m = symbols('i,j,n,m')
  96. o = B(i)
  97. assert latex(o) == "b_{i}"
  98. assert isinstance(o, AnnihilateBoson)
  99. o = o.subs(i, j)
  100. assert o.atoms(Symbol) == {j}
  101. o = B(0)
  102. assert o.apply_operator(BKet([n])) == sqrt(n)*BKet([n - 1])
  103. o = B(n)
  104. assert o.apply_operator(BKet([n])) == o*BKet([n])
  105. def test_basic_state():
  106. i, j, n, m = symbols('i,j,n,m')
  107. s = BosonState([0, 1, 2, 3, 4])
  108. assert len(s) == 5
  109. assert s.args[0] == tuple(range(5))
  110. assert s.up(0) == BosonState([1, 1, 2, 3, 4])
  111. assert s.down(4) == BosonState([0, 1, 2, 3, 3])
  112. for i in range(5):
  113. assert s.up(i).down(i) == s
  114. assert s.down(0) == 0
  115. for i in range(5):
  116. assert s[i] == i
  117. s = BosonState([n, m])
  118. assert s.down(0) == BosonState([n - 1, m])
  119. assert s.up(0) == BosonState([n + 1, m])
  120. def test_basic_apply():
  121. n = symbols("n")
  122. e = B(0)*BKet([n])
  123. assert apply_operators(e) == sqrt(n)*BKet([n - 1])
  124. e = Bd(0)*BKet([n])
  125. assert apply_operators(e) == sqrt(n + 1)*BKet([n + 1])
  126. def test_complex_apply():
  127. n, m = symbols("n,m")
  128. o = Bd(0)*B(0)*Bd(1)*B(0)
  129. e = apply_operators(o*BKet([n, m]))
  130. answer = sqrt(n)*sqrt(m + 1)*(-1 + n)*BKet([-1 + n, 1 + m])
  131. assert expand(e) == expand(answer)
  132. def test_number_operator():
  133. n = symbols("n")
  134. o = Bd(0)*B(0)
  135. e = apply_operators(o*BKet([n]))
  136. assert e == n*BKet([n])
  137. def test_inner_product():
  138. i, j, k, l = symbols('i,j,k,l')
  139. s1 = BBra([0])
  140. s2 = BKet([1])
  141. assert InnerProduct(s1, Dagger(s1)) == 1
  142. assert InnerProduct(s1, s2) == 0
  143. s1 = BBra([i, j])
  144. s2 = BKet([k, l])
  145. r = InnerProduct(s1, s2)
  146. assert r == KroneckerDelta(i, k)*KroneckerDelta(j, l)
  147. def test_symbolic_matrix_elements():
  148. n, m = symbols('n,m')
  149. s1 = BBra([n])
  150. s2 = BKet([m])
  151. o = B(0)
  152. e = apply_operators(s1*o*s2)
  153. assert e == sqrt(m)*KroneckerDelta(n, m - 1)
  154. def test_matrix_elements():
  155. b = VarBosonicBasis(5)
  156. o = B(0)
  157. m = matrix_rep(o, b)
  158. for i in range(4):
  159. assert m[i, i + 1] == sqrt(i + 1)
  160. o = Bd(0)
  161. m = matrix_rep(o, b)
  162. for i in range(4):
  163. assert m[i + 1, i] == sqrt(i + 1)
  164. def test_fixed_bosonic_basis():
  165. b = FixedBosonicBasis(2, 2)
  166. # assert b == [FockState((2, 0)), FockState((1, 1)), FockState((0, 2))]
  167. state = b.state(1)
  168. assert state == FockStateBosonKet((1, 1))
  169. assert b.index(state) == 1
  170. assert b.state(1) == b[1]
  171. assert len(b) == 3
  172. assert str(b) == '[FockState((2, 0)), FockState((1, 1)), FockState((0, 2))]'
  173. assert repr(b) == '[FockState((2, 0)), FockState((1, 1)), FockState((0, 2))]'
  174. assert srepr(b) == '[FockState((2, 0)), FockState((1, 1)), FockState((0, 2))]'
  175. @slow
  176. def test_sho():
  177. n, m = symbols('n,m')
  178. h_n = Bd(n)*B(n)*(n + S.Half)
  179. H = Sum(h_n, (n, 0, 5))
  180. o = H.doit(deep=False)
  181. b = FixedBosonicBasis(2, 6)
  182. m = matrix_rep(o, b)
  183. # We need to double check these energy values to make sure that they
  184. # are correct and have the proper degeneracies!
  185. diag = [1, 2, 3, 3, 4, 5, 4, 5, 6, 7, 5, 6, 7, 8, 9, 6, 7, 8, 9, 10, 11]
  186. for i in range(len(diag)):
  187. assert diag[i] == m[i, i]
  188. def test_commutation():
  189. n, m = symbols("n,m", above_fermi=True)
  190. c = Commutator(B(0), Bd(0))
  191. assert c == 1
  192. c = Commutator(Bd(0), B(0))
  193. assert c == -1
  194. c = Commutator(B(n), Bd(0))
  195. assert c == KroneckerDelta(n, 0)
  196. c = Commutator(B(0), B(0))
  197. assert c == 0
  198. c = Commutator(B(0), Bd(0))
  199. e = simplify(apply_operators(c*BKet([n])))
  200. assert e == BKet([n])
  201. c = Commutator(B(0), B(1))
  202. e = simplify(apply_operators(c*BKet([n, m])))
  203. assert e == 0
  204. c = Commutator(F(m), Fd(m))
  205. assert c == +1 - 2*NO(Fd(m)*F(m))
  206. c = Commutator(Fd(m), F(m))
  207. assert c.expand() == -1 + 2*NO(Fd(m)*F(m))
  208. C = Commutator
  209. X, Y, Z = symbols('X,Y,Z', commutative=False)
  210. assert C(C(X, Y), Z) != 0
  211. assert C(C(X, Z), Y) != 0
  212. assert C(Y, C(X, Z)) != 0
  213. i, j, k, l = symbols('i,j,k,l', below_fermi=True)
  214. a, b, c, d = symbols('a,b,c,d', above_fermi=True)
  215. p, q, r, s = symbols('p,q,r,s')
  216. D = KroneckerDelta
  217. assert C(Fd(a), F(i)) == -2*NO(F(i)*Fd(a))
  218. assert C(Fd(j), NO(Fd(a)*F(i))).doit(wicks=True) == -D(j, i)*Fd(a)
  219. assert C(Fd(a)*F(i), Fd(b)*F(j)).doit(wicks=True) == 0
  220. c1 = Commutator(F(a), Fd(a))
  221. assert Commutator.eval(c1, c1) == 0
  222. c = Commutator(Fd(a)*F(i),Fd(b)*F(j))
  223. assert latex(c) == r'\left[{a^\dagger_{a}} a_{i},{a^\dagger_{b}} a_{j}\right]'
  224. assert repr(c) == 'Commutator(CreateFermion(a)*AnnihilateFermion(i),CreateFermion(b)*AnnihilateFermion(j))'
  225. assert str(c) == '[CreateFermion(a)*AnnihilateFermion(i),CreateFermion(b)*AnnihilateFermion(j)]'
  226. def test_create_f():
  227. i, j, n, m = symbols('i,j,n,m')
  228. o = Fd(i)
  229. assert isinstance(o, CreateFermion)
  230. o = o.subs(i, j)
  231. assert o.atoms(Symbol) == {j}
  232. o = Fd(1)
  233. assert o.apply_operator(FKet([n])) == FKet([1, n])
  234. assert o.apply_operator(FKet([n])) == -FKet([n, 1])
  235. o = Fd(n)
  236. assert o.apply_operator(FKet([])) == FKet([n])
  237. vacuum = FKet([], fermi_level=4)
  238. assert vacuum == FKet([], fermi_level=4)
  239. i, j, k, l = symbols('i,j,k,l', below_fermi=True)
  240. a, b, c, d = symbols('a,b,c,d', above_fermi=True)
  241. p, q, r, s = symbols('p,q,r,s')
  242. assert Fd(i).apply_operator(FKet([i, j, k], 4)) == FKet([j, k], 4)
  243. assert Fd(a).apply_operator(FKet([i, b, k], 4)) == FKet([a, i, b, k], 4)
  244. assert Dagger(B(p)).apply_operator(q) == q*CreateBoson(p)
  245. assert repr(Fd(p)) == 'CreateFermion(p)'
  246. assert srepr(Fd(p)) == "CreateFermion(Symbol('p'))"
  247. assert latex(Fd(p)) == r'{a^\dagger_{p}}'
  248. def test_annihilate_f():
  249. i, j, n, m = symbols('i,j,n,m')
  250. o = F(i)
  251. assert isinstance(o, AnnihilateFermion)
  252. o = o.subs(i, j)
  253. assert o.atoms(Symbol) == {j}
  254. o = F(1)
  255. assert o.apply_operator(FKet([1, n])) == FKet([n])
  256. assert o.apply_operator(FKet([n, 1])) == -FKet([n])
  257. o = F(n)
  258. assert o.apply_operator(FKet([n])) == FKet([])
  259. i, j, k, l = symbols('i,j,k,l', below_fermi=True)
  260. a, b, c, d = symbols('a,b,c,d', above_fermi=True)
  261. p, q, r, s = symbols('p,q,r,s')
  262. assert F(i).apply_operator(FKet([i, j, k], 4)) == 0
  263. assert F(a).apply_operator(FKet([i, b, k], 4)) == 0
  264. assert F(l).apply_operator(FKet([i, j, k], 3)) == 0
  265. assert F(l).apply_operator(FKet([i, j, k], 4)) == FKet([l, i, j, k], 4)
  266. assert str(F(p)) == 'f(p)'
  267. assert repr(F(p)) == 'AnnihilateFermion(p)'
  268. assert srepr(F(p)) == "AnnihilateFermion(Symbol('p'))"
  269. assert latex(F(p)) == 'a_{p}'
  270. def test_create_b():
  271. i, j, n, m = symbols('i,j,n,m')
  272. o = Bd(i)
  273. assert isinstance(o, CreateBoson)
  274. o = o.subs(i, j)
  275. assert o.atoms(Symbol) == {j}
  276. o = Bd(0)
  277. assert o.apply_operator(BKet([n])) == sqrt(n + 1)*BKet([n + 1])
  278. o = Bd(n)
  279. assert o.apply_operator(BKet([n])) == o*BKet([n])
  280. def test_annihilate_b():
  281. i, j, n, m = symbols('i,j,n,m')
  282. o = B(i)
  283. assert isinstance(o, AnnihilateBoson)
  284. o = o.subs(i, j)
  285. assert o.atoms(Symbol) == {j}
  286. o = B(0)
  287. def test_wicks():
  288. p, q, r, s = symbols('p,q,r,s', above_fermi=True)
  289. # Testing for particles only
  290. str = F(p)*Fd(q)
  291. assert wicks(str) == NO(F(p)*Fd(q)) + KroneckerDelta(p, q)
  292. str = Fd(p)*F(q)
  293. assert wicks(str) == NO(Fd(p)*F(q))
  294. str = F(p)*Fd(q)*F(r)*Fd(s)
  295. nstr = wicks(str)
  296. fasit = NO(
  297. KroneckerDelta(p, q)*KroneckerDelta(r, s)
  298. + KroneckerDelta(p, q)*AnnihilateFermion(r)*CreateFermion(s)
  299. + KroneckerDelta(r, s)*AnnihilateFermion(p)*CreateFermion(q)
  300. - KroneckerDelta(p, s)*AnnihilateFermion(r)*CreateFermion(q)
  301. - AnnihilateFermion(p)*AnnihilateFermion(r)*CreateFermion(q)*CreateFermion(s))
  302. assert nstr == fasit
  303. assert (p*q*nstr).expand() == wicks(p*q*str)
  304. assert (nstr*p*q*2).expand() == wicks(str*p*q*2)
  305. # Testing CC equations particles and holes
  306. i, j, k, l = symbols('i j k l', below_fermi=True, cls=Dummy)
  307. a, b, c, d = symbols('a b c d', above_fermi=True, cls=Dummy)
  308. p, q, r, s = symbols('p q r s', cls=Dummy)
  309. assert (wicks(F(a)*NO(F(i)*F(j))*Fd(b)) ==
  310. NO(F(a)*F(i)*F(j)*Fd(b)) +
  311. KroneckerDelta(a, b)*NO(F(i)*F(j)))
  312. assert (wicks(F(a)*NO(F(i)*F(j)*F(k))*Fd(b)) ==
  313. NO(F(a)*F(i)*F(j)*F(k)*Fd(b)) -
  314. KroneckerDelta(a, b)*NO(F(i)*F(j)*F(k)))
  315. expr = wicks(Fd(i)*NO(Fd(j)*F(k))*F(l))
  316. assert (expr ==
  317. -KroneckerDelta(i, k)*NO(Fd(j)*F(l)) -
  318. KroneckerDelta(j, l)*NO(Fd(i)*F(k)) -
  319. KroneckerDelta(i, k)*KroneckerDelta(j, l) +
  320. KroneckerDelta(i, l)*NO(Fd(j)*F(k)) +
  321. NO(Fd(i)*Fd(j)*F(k)*F(l)))
  322. expr = wicks(F(a)*NO(F(b)*Fd(c))*Fd(d))
  323. assert (expr ==
  324. -KroneckerDelta(a, c)*NO(F(b)*Fd(d)) -
  325. KroneckerDelta(b, d)*NO(F(a)*Fd(c)) -
  326. KroneckerDelta(a, c)*KroneckerDelta(b, d) +
  327. KroneckerDelta(a, d)*NO(F(b)*Fd(c)) +
  328. NO(F(a)*F(b)*Fd(c)*Fd(d)))
  329. def test_NO():
  330. i, j, k, l = symbols('i j k l', below_fermi=True)
  331. a, b, c, d = symbols('a b c d', above_fermi=True)
  332. p, q, r, s = symbols('p q r s', cls=Dummy)
  333. assert (NO(Fd(p)*F(q) + Fd(a)*F(b)) ==
  334. NO(Fd(p)*F(q)) + NO(Fd(a)*F(b)))
  335. assert (NO(Fd(i)*NO(F(j)*Fd(a))) ==
  336. NO(Fd(i)*F(j)*Fd(a)))
  337. assert NO(1) == 1
  338. assert NO(i) == i
  339. assert (NO(Fd(a)*Fd(b)*(F(c) + F(d))) ==
  340. NO(Fd(a)*Fd(b)*F(c)) +
  341. NO(Fd(a)*Fd(b)*F(d)))
  342. assert NO(Fd(a)*F(b))._remove_brackets() == Fd(a)*F(b)
  343. assert NO(F(j)*Fd(i))._remove_brackets() == F(j)*Fd(i)
  344. assert (NO(Fd(p)*F(q)).subs(Fd(p), Fd(a) + Fd(i)) ==
  345. NO(Fd(a)*F(q)) + NO(Fd(i)*F(q)))
  346. assert (NO(Fd(p)*F(q)).subs(F(q), F(a) + F(i)) ==
  347. NO(Fd(p)*F(a)) + NO(Fd(p)*F(i)))
  348. expr = NO(Fd(p)*F(q))._remove_brackets()
  349. assert wicks(expr) == NO(expr)
  350. assert NO(Fd(a)*F(b)) == - NO(F(b)*Fd(a))
  351. no = NO(Fd(a)*F(i)*F(b)*Fd(j))
  352. l1 = list(no.iter_q_creators())
  353. assert l1 == [0, 1]
  354. l2 = list(no.iter_q_annihilators())
  355. assert l2 == [3, 2]
  356. no = NO(Fd(a)*Fd(i))
  357. assert no.has_q_creators == 1
  358. assert no.has_q_annihilators == -1
  359. assert str(no) == ':CreateFermion(a)*CreateFermion(i):'
  360. assert repr(no) == 'NO(CreateFermion(a)*CreateFermion(i))'
  361. assert latex(no) == r'\left\{{a^\dagger_{a}} {a^\dagger_{i}}\right\}'
  362. raises(NotImplementedError, lambda: NO(Bd(p)*F(q)))
  363. def test_sorting():
  364. i, j = symbols('i,j', below_fermi=True)
  365. a, b = symbols('a,b', above_fermi=True)
  366. p, q = symbols('p,q')
  367. # p, q
  368. assert _sort_anticommuting_fermions([Fd(p), F(q)]) == ([Fd(p), F(q)], 0)
  369. assert _sort_anticommuting_fermions([F(p), Fd(q)]) == ([Fd(q), F(p)], 1)
  370. # i, p
  371. assert _sort_anticommuting_fermions([F(p), Fd(i)]) == ([F(p), Fd(i)], 0)
  372. assert _sort_anticommuting_fermions([Fd(i), F(p)]) == ([F(p), Fd(i)], 1)
  373. assert _sort_anticommuting_fermions([Fd(p), Fd(i)]) == ([Fd(p), Fd(i)], 0)
  374. assert _sort_anticommuting_fermions([Fd(i), Fd(p)]) == ([Fd(p), Fd(i)], 1)
  375. assert _sort_anticommuting_fermions([F(p), F(i)]) == ([F(i), F(p)], 1)
  376. assert _sort_anticommuting_fermions([F(i), F(p)]) == ([F(i), F(p)], 0)
  377. assert _sort_anticommuting_fermions([Fd(p), F(i)]) == ([F(i), Fd(p)], 1)
  378. assert _sort_anticommuting_fermions([F(i), Fd(p)]) == ([F(i), Fd(p)], 0)
  379. # a, p
  380. assert _sort_anticommuting_fermions([F(p), Fd(a)]) == ([Fd(a), F(p)], 1)
  381. assert _sort_anticommuting_fermions([Fd(a), F(p)]) == ([Fd(a), F(p)], 0)
  382. assert _sort_anticommuting_fermions([Fd(p), Fd(a)]) == ([Fd(a), Fd(p)], 1)
  383. assert _sort_anticommuting_fermions([Fd(a), Fd(p)]) == ([Fd(a), Fd(p)], 0)
  384. assert _sort_anticommuting_fermions([F(p), F(a)]) == ([F(p), F(a)], 0)
  385. assert _sort_anticommuting_fermions([F(a), F(p)]) == ([F(p), F(a)], 1)
  386. assert _sort_anticommuting_fermions([Fd(p), F(a)]) == ([Fd(p), F(a)], 0)
  387. assert _sort_anticommuting_fermions([F(a), Fd(p)]) == ([Fd(p), F(a)], 1)
  388. # i, a
  389. assert _sort_anticommuting_fermions([F(i), Fd(j)]) == ([F(i), Fd(j)], 0)
  390. assert _sort_anticommuting_fermions([Fd(j), F(i)]) == ([F(i), Fd(j)], 1)
  391. assert _sort_anticommuting_fermions([Fd(a), Fd(i)]) == ([Fd(a), Fd(i)], 0)
  392. assert _sort_anticommuting_fermions([Fd(i), Fd(a)]) == ([Fd(a), Fd(i)], 1)
  393. assert _sort_anticommuting_fermions([F(a), F(i)]) == ([F(i), F(a)], 1)
  394. assert _sort_anticommuting_fermions([F(i), F(a)]) == ([F(i), F(a)], 0)
  395. def test_contraction():
  396. i, j, k, l = symbols('i,j,k,l', below_fermi=True)
  397. a, b, c, d = symbols('a,b,c,d', above_fermi=True)
  398. p, q, r, s = symbols('p,q,r,s')
  399. assert contraction(Fd(i), F(j)) == KroneckerDelta(i, j)
  400. assert contraction(F(a), Fd(b)) == KroneckerDelta(a, b)
  401. assert contraction(F(a), Fd(i)) == 0
  402. assert contraction(Fd(a), F(i)) == 0
  403. assert contraction(F(i), Fd(a)) == 0
  404. assert contraction(Fd(i), F(a)) == 0
  405. assert contraction(Fd(i), F(p)) == KroneckerDelta(i, p)
  406. restr = evaluate_deltas(contraction(Fd(p), F(q)))
  407. assert restr.is_only_below_fermi
  408. restr = evaluate_deltas(contraction(F(p), Fd(q)))
  409. assert restr.is_only_above_fermi
  410. raises(ContractionAppliesOnlyToFermions, lambda: contraction(B(a), Fd(b)))
  411. def test_evaluate_deltas():
  412. i, j, k = symbols('i,j,k')
  413. r = KroneckerDelta(i, j) * KroneckerDelta(j, k)
  414. assert evaluate_deltas(r) == KroneckerDelta(i, k)
  415. r = KroneckerDelta(i, 0) * KroneckerDelta(j, k)
  416. assert evaluate_deltas(r) == KroneckerDelta(i, 0) * KroneckerDelta(j, k)
  417. r = KroneckerDelta(1, j) * KroneckerDelta(j, k)
  418. assert evaluate_deltas(r) == KroneckerDelta(1, k)
  419. r = KroneckerDelta(j, 2) * KroneckerDelta(k, j)
  420. assert evaluate_deltas(r) == KroneckerDelta(2, k)
  421. r = KroneckerDelta(i, 0) * KroneckerDelta(i, j) * KroneckerDelta(j, 1)
  422. assert evaluate_deltas(r) == 0
  423. r = (KroneckerDelta(0, i) * KroneckerDelta(0, j)
  424. * KroneckerDelta(1, j) * KroneckerDelta(1, j))
  425. assert evaluate_deltas(r) == 0
  426. def test_Tensors():
  427. i, j, k, l = symbols('i j k l', below_fermi=True, cls=Dummy)
  428. a, b, c, d = symbols('a b c d', above_fermi=True, cls=Dummy)
  429. p, q, r, s = symbols('p q r s')
  430. AT = AntiSymmetricTensor
  431. assert AT('t', (a, b), (i, j)) == -AT('t', (b, a), (i, j))
  432. assert AT('t', (a, b), (i, j)) == AT('t', (b, a), (j, i))
  433. assert AT('t', (a, b), (i, j)) == -AT('t', (a, b), (j, i))
  434. assert AT('t', (a, a), (i, j)) == 0
  435. assert AT('t', (a, b), (i, i)) == 0
  436. assert AT('t', (a, b, c), (i, j)) == -AT('t', (b, a, c), (i, j))
  437. assert AT('t', (a, b, c), (i, j, k)) == AT('t', (b, a, c), (i, k, j))
  438. tabij = AT('t', (a, b), (i, j))
  439. assert tabij.has(a)
  440. assert tabij.has(b)
  441. assert tabij.has(i)
  442. assert tabij.has(j)
  443. assert tabij.subs(b, c) == AT('t', (a, c), (i, j))
  444. assert (2*tabij).subs(i, c) == 2*AT('t', (a, b), (c, j))
  445. assert tabij.symbol == Symbol('t')
  446. assert latex(tabij) == '{t^{ab}_{ij}}'
  447. assert str(tabij) == 't((_a, _b),(_i, _j))'
  448. assert AT('t', (a, a), (i, j)).subs(a, b) == AT('t', (b, b), (i, j))
  449. assert AT('t', (a, i), (a, j)).subs(a, b) == AT('t', (b, i), (b, j))
  450. def test_fully_contracted():
  451. i, j, k, l = symbols('i j k l', below_fermi=True)
  452. a, b, c, d = symbols('a b c d', above_fermi=True)
  453. p, q, r, s = symbols('p q r s', cls=Dummy)
  454. Fock = (AntiSymmetricTensor('f', (p,), (q,))*
  455. NO(Fd(p)*F(q)))
  456. V = (AntiSymmetricTensor('v', (p, q), (r, s))*
  457. NO(Fd(p)*Fd(q)*F(s)*F(r)))/4
  458. Fai = wicks(NO(Fd(i)*F(a))*Fock,
  459. keep_only_fully_contracted=True,
  460. simplify_kronecker_deltas=True)
  461. assert Fai == AntiSymmetricTensor('f', (a,), (i,))
  462. Vabij = wicks(NO(Fd(i)*Fd(j)*F(b)*F(a))*V,
  463. keep_only_fully_contracted=True,
  464. simplify_kronecker_deltas=True)
  465. assert Vabij == AntiSymmetricTensor('v', (a, b), (i, j))
  466. def test_substitute_dummies_without_dummies():
  467. i, j = symbols('i,j')
  468. assert substitute_dummies(att(i, j) + 2) == att(i, j) + 2
  469. assert substitute_dummies(att(i, j) + 1) == att(i, j) + 1
  470. def test_substitute_dummies_NO_operator():
  471. i, j = symbols('i j', cls=Dummy)
  472. assert substitute_dummies(att(i, j)*NO(Fd(i)*F(j))
  473. - att(j, i)*NO(Fd(j)*F(i))) == 0
  474. def test_substitute_dummies_SQ_operator():
  475. i, j = symbols('i j', cls=Dummy)
  476. assert substitute_dummies(att(i, j)*Fd(i)*F(j)
  477. - att(j, i)*Fd(j)*F(i)) == 0
  478. def test_substitute_dummies_new_indices():
  479. i, j = symbols('i j', below_fermi=True, cls=Dummy)
  480. a, b = symbols('a b', above_fermi=True, cls=Dummy)
  481. p, q = symbols('p q', cls=Dummy)
  482. f = Function('f')
  483. assert substitute_dummies(f(i, a, p) - f(j, b, q), new_indices=True) == 0
  484. def test_substitute_dummies_substitution_order():
  485. i, j, k, l = symbols('i j k l', below_fermi=True, cls=Dummy)
  486. f = Function('f')
  487. from sympy.utilities.iterables import variations
  488. for permut in variations([i, j, k, l], 4):
  489. assert substitute_dummies(f(*permut) - f(i, j, k, l)) == 0
  490. def test_dummy_order_inner_outer_lines_VT1T1T1():
  491. ii = symbols('i', below_fermi=True)
  492. aa = symbols('a', above_fermi=True)
  493. k, l = symbols('k l', below_fermi=True, cls=Dummy)
  494. c, d = symbols('c d', above_fermi=True, cls=Dummy)
  495. v = Function('v')
  496. t = Function('t')
  497. dums = _get_ordered_dummies
  498. # Coupled-Cluster T1 terms with V*T1*T1*T1
  499. # t^{a}_{k} t^{c}_{i} t^{d}_{l} v^{lk}_{dc}
  500. exprs = [
  501. # permut v and t <=> swapping internal lines, equivalent
  502. # irrespective of symmetries in v
  503. v(k, l, c, d)*t(c, ii)*t(d, l)*t(aa, k),
  504. v(l, k, c, d)*t(c, ii)*t(d, k)*t(aa, l),
  505. v(k, l, d, c)*t(d, ii)*t(c, l)*t(aa, k),
  506. v(l, k, d, c)*t(d, ii)*t(c, k)*t(aa, l),
  507. ]
  508. for permut in exprs[1:]:
  509. assert dums(exprs[0]) != dums(permut)
  510. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  511. def test_dummy_order_inner_outer_lines_VT1T1T1T1():
  512. ii, jj = symbols('i j', below_fermi=True)
  513. aa, bb = symbols('a b', above_fermi=True)
  514. k, l = symbols('k l', below_fermi=True, cls=Dummy)
  515. c, d = symbols('c d', above_fermi=True, cls=Dummy)
  516. v = Function('v')
  517. t = Function('t')
  518. dums = _get_ordered_dummies
  519. # Coupled-Cluster T2 terms with V*T1*T1*T1*T1
  520. exprs = [
  521. # permut t <=> swapping external lines, not equivalent
  522. # except if v has certain symmetries.
  523. v(k, l, c, d)*t(c, ii)*t(d, jj)*t(aa, k)*t(bb, l),
  524. v(k, l, c, d)*t(c, jj)*t(d, ii)*t(aa, k)*t(bb, l),
  525. v(k, l, c, d)*t(c, ii)*t(d, jj)*t(bb, k)*t(aa, l),
  526. v(k, l, c, d)*t(c, jj)*t(d, ii)*t(bb, k)*t(aa, l),
  527. ]
  528. for permut in exprs[1:]:
  529. assert dums(exprs[0]) != dums(permut)
  530. assert substitute_dummies(exprs[0]) != substitute_dummies(permut)
  531. exprs = [
  532. # permut v <=> swapping external lines, not equivalent
  533. # except if v has certain symmetries.
  534. #
  535. # Note that in contrast to above, these permutations have identical
  536. # dummy order. That is because the proximity to external indices
  537. # has higher influence on the canonical dummy ordering than the
  538. # position of a dummy on the factors. In fact, the terms here are
  539. # similar in structure as the result of the dummy substitutions above.
  540. v(k, l, c, d)*t(c, ii)*t(d, jj)*t(aa, k)*t(bb, l),
  541. v(l, k, c, d)*t(c, ii)*t(d, jj)*t(aa, k)*t(bb, l),
  542. v(k, l, d, c)*t(c, ii)*t(d, jj)*t(aa, k)*t(bb, l),
  543. v(l, k, d, c)*t(c, ii)*t(d, jj)*t(aa, k)*t(bb, l),
  544. ]
  545. for permut in exprs[1:]:
  546. assert dums(exprs[0]) == dums(permut)
  547. assert substitute_dummies(exprs[0]) != substitute_dummies(permut)
  548. exprs = [
  549. # permut t and v <=> swapping internal lines, equivalent.
  550. # Canonical dummy order is different, and a consistent
  551. # substitution reveals the equivalence.
  552. v(k, l, c, d)*t(c, ii)*t(d, jj)*t(aa, k)*t(bb, l),
  553. v(k, l, d, c)*t(c, jj)*t(d, ii)*t(aa, k)*t(bb, l),
  554. v(l, k, c, d)*t(c, ii)*t(d, jj)*t(bb, k)*t(aa, l),
  555. v(l, k, d, c)*t(c, jj)*t(d, ii)*t(bb, k)*t(aa, l),
  556. ]
  557. for permut in exprs[1:]:
  558. assert dums(exprs[0]) != dums(permut)
  559. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  560. def test_get_subNO():
  561. p, q, r = symbols('p,q,r')
  562. assert NO(F(p)*F(q)*F(r)).get_subNO(1) == NO(F(p)*F(r))
  563. assert NO(F(p)*F(q)*F(r)).get_subNO(0) == NO(F(q)*F(r))
  564. assert NO(F(p)*F(q)*F(r)).get_subNO(2) == NO(F(p)*F(q))
  565. def test_equivalent_internal_lines_VT1T1():
  566. i, j, k, l = symbols('i j k l', below_fermi=True, cls=Dummy)
  567. a, b, c, d = symbols('a b c d', above_fermi=True, cls=Dummy)
  568. v = Function('v')
  569. t = Function('t')
  570. dums = _get_ordered_dummies
  571. exprs = [ # permute v. Different dummy order. Not equivalent.
  572. v(i, j, a, b)*t(a, i)*t(b, j),
  573. v(j, i, a, b)*t(a, i)*t(b, j),
  574. v(i, j, b, a)*t(a, i)*t(b, j),
  575. ]
  576. for permut in exprs[1:]:
  577. assert dums(exprs[0]) != dums(permut)
  578. assert substitute_dummies(exprs[0]) != substitute_dummies(permut)
  579. exprs = [ # permute v. Different dummy order. Equivalent
  580. v(i, j, a, b)*t(a, i)*t(b, j),
  581. v(j, i, b, a)*t(a, i)*t(b, j),
  582. ]
  583. for permut in exprs[1:]:
  584. assert dums(exprs[0]) != dums(permut)
  585. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  586. exprs = [ # permute t. Same dummy order, not equivalent.
  587. v(i, j, a, b)*t(a, i)*t(b, j),
  588. v(i, j, a, b)*t(b, i)*t(a, j),
  589. ]
  590. for permut in exprs[1:]:
  591. assert dums(exprs[0]) == dums(permut)
  592. assert substitute_dummies(exprs[0]) != substitute_dummies(permut)
  593. exprs = [ # permute v and t. Different dummy order, equivalent
  594. v(i, j, a, b)*t(a, i)*t(b, j),
  595. v(j, i, a, b)*t(a, j)*t(b, i),
  596. v(i, j, b, a)*t(b, i)*t(a, j),
  597. v(j, i, b, a)*t(b, j)*t(a, i),
  598. ]
  599. for permut in exprs[1:]:
  600. assert dums(exprs[0]) != dums(permut)
  601. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  602. def test_equivalent_internal_lines_VT2conjT2():
  603. # this diagram requires special handling in TCE
  604. i, j, k, l, m, n = symbols('i j k l m n', below_fermi=True, cls=Dummy)
  605. a, b, c, d, e, f = symbols('a b c d e f', above_fermi=True, cls=Dummy)
  606. p1, p2, p3, p4 = symbols('p1 p2 p3 p4', above_fermi=True, cls=Dummy)
  607. h1, h2, h3, h4 = symbols('h1 h2 h3 h4', below_fermi=True, cls=Dummy)
  608. from sympy.utilities.iterables import variations
  609. v = Function('v')
  610. t = Function('t')
  611. dums = _get_ordered_dummies
  612. # v(abcd)t(abij)t(ijcd)
  613. template = v(p1, p2, p3, p4)*t(p1, p2, i, j)*t(i, j, p3, p4)
  614. permutator = variations([a, b, c, d], 4)
  615. base = template.subs(zip([p1, p2, p3, p4], next(permutator)))
  616. for permut in permutator:
  617. subslist = zip([p1, p2, p3, p4], permut)
  618. expr = template.subs(subslist)
  619. assert dums(base) != dums(expr)
  620. assert substitute_dummies(expr) == substitute_dummies(base)
  621. template = v(p1, p2, p3, p4)*t(p1, p2, j, i)*t(j, i, p3, p4)
  622. permutator = variations([a, b, c, d], 4)
  623. base = template.subs(zip([p1, p2, p3, p4], next(permutator)))
  624. for permut in permutator:
  625. subslist = zip([p1, p2, p3, p4], permut)
  626. expr = template.subs(subslist)
  627. assert dums(base) != dums(expr)
  628. assert substitute_dummies(expr) == substitute_dummies(base)
  629. # v(abcd)t(abij)t(jicd)
  630. template = v(p1, p2, p3, p4)*t(p1, p2, i, j)*t(j, i, p3, p4)
  631. permutator = variations([a, b, c, d], 4)
  632. base = template.subs(zip([p1, p2, p3, p4], next(permutator)))
  633. for permut in permutator:
  634. subslist = zip([p1, p2, p3, p4], permut)
  635. expr = template.subs(subslist)
  636. assert dums(base) != dums(expr)
  637. assert substitute_dummies(expr) == substitute_dummies(base)
  638. template = v(p1, p2, p3, p4)*t(p1, p2, j, i)*t(i, j, p3, p4)
  639. permutator = variations([a, b, c, d], 4)
  640. base = template.subs(zip([p1, p2, p3, p4], next(permutator)))
  641. for permut in permutator:
  642. subslist = zip([p1, p2, p3, p4], permut)
  643. expr = template.subs(subslist)
  644. assert dums(base) != dums(expr)
  645. assert substitute_dummies(expr) == substitute_dummies(base)
  646. def test_equivalent_internal_lines_VT2conjT2_ambiguous_order():
  647. # These diagrams invokes _determine_ambiguous() because the
  648. # dummies can not be ordered unambiguously by the key alone
  649. i, j, k, l, m, n = symbols('i j k l m n', below_fermi=True, cls=Dummy)
  650. a, b, c, d, e, f = symbols('a b c d e f', above_fermi=True, cls=Dummy)
  651. p1, p2, p3, p4 = symbols('p1 p2 p3 p4', above_fermi=True, cls=Dummy)
  652. h1, h2, h3, h4 = symbols('h1 h2 h3 h4', below_fermi=True, cls=Dummy)
  653. from sympy.utilities.iterables import variations
  654. v = Function('v')
  655. t = Function('t')
  656. dums = _get_ordered_dummies
  657. # v(abcd)t(abij)t(cdij)
  658. template = v(p1, p2, p3, p4)*t(p1, p2, i, j)*t(p3, p4, i, j)
  659. permutator = variations([a, b, c, d], 4)
  660. base = template.subs(zip([p1, p2, p3, p4], next(permutator)))
  661. for permut in permutator:
  662. subslist = zip([p1, p2, p3, p4], permut)
  663. expr = template.subs(subslist)
  664. assert dums(base) != dums(expr)
  665. assert substitute_dummies(expr) == substitute_dummies(base)
  666. template = v(p1, p2, p3, p4)*t(p1, p2, j, i)*t(p3, p4, i, j)
  667. permutator = variations([a, b, c, d], 4)
  668. base = template.subs(zip([p1, p2, p3, p4], next(permutator)))
  669. for permut in permutator:
  670. subslist = zip([p1, p2, p3, p4], permut)
  671. expr = template.subs(subslist)
  672. assert dums(base) != dums(expr)
  673. assert substitute_dummies(expr) == substitute_dummies(base)
  674. def test_equivalent_internal_lines_VT2():
  675. i, j, k, l = symbols('i j k l', below_fermi=True, cls=Dummy)
  676. a, b, c, d = symbols('a b c d', above_fermi=True, cls=Dummy)
  677. v = Function('v')
  678. t = Function('t')
  679. dums = _get_ordered_dummies
  680. exprs = [
  681. # permute v. Same dummy order, not equivalent.
  682. #
  683. # This test show that the dummy order may not be sensitive to all
  684. # index permutations. The following expressions have identical
  685. # structure as the resulting terms from of the dummy substitutions
  686. # in the test above. Here, all expressions have the same dummy
  687. # order, so they cannot be simplified by means of dummy
  688. # substitution. In order to simplify further, it is necessary to
  689. # exploit symmetries in the objects, for instance if t or v is
  690. # antisymmetric.
  691. v(i, j, a, b)*t(a, b, i, j),
  692. v(j, i, a, b)*t(a, b, i, j),
  693. v(i, j, b, a)*t(a, b, i, j),
  694. v(j, i, b, a)*t(a, b, i, j),
  695. ]
  696. for permut in exprs[1:]:
  697. assert dums(exprs[0]) == dums(permut)
  698. assert substitute_dummies(exprs[0]) != substitute_dummies(permut)
  699. exprs = [
  700. # permute t.
  701. v(i, j, a, b)*t(a, b, i, j),
  702. v(i, j, a, b)*t(b, a, i, j),
  703. v(i, j, a, b)*t(a, b, j, i),
  704. v(i, j, a, b)*t(b, a, j, i),
  705. ]
  706. for permut in exprs[1:]:
  707. assert dums(exprs[0]) != dums(permut)
  708. assert substitute_dummies(exprs[0]) != substitute_dummies(permut)
  709. exprs = [ # permute v and t. Relabelling of dummies should be equivalent.
  710. v(i, j, a, b)*t(a, b, i, j),
  711. v(j, i, a, b)*t(a, b, j, i),
  712. v(i, j, b, a)*t(b, a, i, j),
  713. v(j, i, b, a)*t(b, a, j, i),
  714. ]
  715. for permut in exprs[1:]:
  716. assert dums(exprs[0]) != dums(permut)
  717. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  718. def test_internal_external_VT2T2():
  719. ii, jj = symbols('i j', below_fermi=True)
  720. aa, bb = symbols('a b', above_fermi=True)
  721. k, l = symbols('k l', below_fermi=True, cls=Dummy)
  722. c, d = symbols('c d', above_fermi=True, cls=Dummy)
  723. v = Function('v')
  724. t = Function('t')
  725. dums = _get_ordered_dummies
  726. exprs = [
  727. v(k, l, c, d)*t(aa, c, ii, k)*t(bb, d, jj, l),
  728. v(l, k, c, d)*t(aa, c, ii, l)*t(bb, d, jj, k),
  729. v(k, l, d, c)*t(aa, d, ii, k)*t(bb, c, jj, l),
  730. v(l, k, d, c)*t(aa, d, ii, l)*t(bb, c, jj, k),
  731. ]
  732. for permut in exprs[1:]:
  733. assert dums(exprs[0]) != dums(permut)
  734. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  735. exprs = [
  736. v(k, l, c, d)*t(aa, c, ii, k)*t(d, bb, jj, l),
  737. v(l, k, c, d)*t(aa, c, ii, l)*t(d, bb, jj, k),
  738. v(k, l, d, c)*t(aa, d, ii, k)*t(c, bb, jj, l),
  739. v(l, k, d, c)*t(aa, d, ii, l)*t(c, bb, jj, k),
  740. ]
  741. for permut in exprs[1:]:
  742. assert dums(exprs[0]) != dums(permut)
  743. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  744. exprs = [
  745. v(k, l, c, d)*t(c, aa, ii, k)*t(bb, d, jj, l),
  746. v(l, k, c, d)*t(c, aa, ii, l)*t(bb, d, jj, k),
  747. v(k, l, d, c)*t(d, aa, ii, k)*t(bb, c, jj, l),
  748. v(l, k, d, c)*t(d, aa, ii, l)*t(bb, c, jj, k),
  749. ]
  750. for permut in exprs[1:]:
  751. assert dums(exprs[0]) != dums(permut)
  752. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  753. def test_internal_external_pqrs():
  754. ii, jj = symbols('i j')
  755. aa, bb = symbols('a b')
  756. k, l = symbols('k l', cls=Dummy)
  757. c, d = symbols('c d', cls=Dummy)
  758. v = Function('v')
  759. t = Function('t')
  760. dums = _get_ordered_dummies
  761. exprs = [
  762. v(k, l, c, d)*t(aa, c, ii, k)*t(bb, d, jj, l),
  763. v(l, k, c, d)*t(aa, c, ii, l)*t(bb, d, jj, k),
  764. v(k, l, d, c)*t(aa, d, ii, k)*t(bb, c, jj, l),
  765. v(l, k, d, c)*t(aa, d, ii, l)*t(bb, c, jj, k),
  766. ]
  767. for permut in exprs[1:]:
  768. assert dums(exprs[0]) != dums(permut)
  769. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  770. def test_dummy_order_well_defined():
  771. aa, bb = symbols('a b', above_fermi=True)
  772. k, l, m = symbols('k l m', below_fermi=True, cls=Dummy)
  773. c, d = symbols('c d', above_fermi=True, cls=Dummy)
  774. p, q = symbols('p q', cls=Dummy)
  775. A = Function('A')
  776. B = Function('B')
  777. C = Function('C')
  778. dums = _get_ordered_dummies
  779. # We go through all key components in the order of increasing priority,
  780. # and consider only fully orderable expressions. Non-orderable expressions
  781. # are tested elsewhere.
  782. # pos in first factor determines sort order
  783. assert dums(A(k, l)*B(l, k)) == [k, l]
  784. assert dums(A(l, k)*B(l, k)) == [l, k]
  785. assert dums(A(k, l)*B(k, l)) == [k, l]
  786. assert dums(A(l, k)*B(k, l)) == [l, k]
  787. # factors involving the index
  788. assert dums(A(k, l)*B(l, m)*C(k, m)) == [l, k, m]
  789. assert dums(A(k, l)*B(l, m)*C(m, k)) == [l, k, m]
  790. assert dums(A(l, k)*B(l, m)*C(k, m)) == [l, k, m]
  791. assert dums(A(l, k)*B(l, m)*C(m, k)) == [l, k, m]
  792. assert dums(A(k, l)*B(m, l)*C(k, m)) == [l, k, m]
  793. assert dums(A(k, l)*B(m, l)*C(m, k)) == [l, k, m]
  794. assert dums(A(l, k)*B(m, l)*C(k, m)) == [l, k, m]
  795. assert dums(A(l, k)*B(m, l)*C(m, k)) == [l, k, m]
  796. # same, but with factor order determined by non-dummies
  797. assert dums(A(k, aa, l)*A(l, bb, m)*A(bb, k, m)) == [l, k, m]
  798. assert dums(A(k, aa, l)*A(l, bb, m)*A(bb, m, k)) == [l, k, m]
  799. assert dums(A(k, aa, l)*A(m, bb, l)*A(bb, k, m)) == [l, k, m]
  800. assert dums(A(k, aa, l)*A(m, bb, l)*A(bb, m, k)) == [l, k, m]
  801. assert dums(A(l, aa, k)*A(l, bb, m)*A(bb, k, m)) == [l, k, m]
  802. assert dums(A(l, aa, k)*A(l, bb, m)*A(bb, m, k)) == [l, k, m]
  803. assert dums(A(l, aa, k)*A(m, bb, l)*A(bb, k, m)) == [l, k, m]
  804. assert dums(A(l, aa, k)*A(m, bb, l)*A(bb, m, k)) == [l, k, m]
  805. # index range
  806. assert dums(A(p, c, k)*B(p, c, k)) == [k, c, p]
  807. assert dums(A(p, k, c)*B(p, c, k)) == [k, c, p]
  808. assert dums(A(c, k, p)*B(p, c, k)) == [k, c, p]
  809. assert dums(A(c, p, k)*B(p, c, k)) == [k, c, p]
  810. assert dums(A(k, c, p)*B(p, c, k)) == [k, c, p]
  811. assert dums(A(k, p, c)*B(p, c, k)) == [k, c, p]
  812. assert dums(B(p, c, k)*A(p, c, k)) == [k, c, p]
  813. assert dums(B(p, k, c)*A(p, c, k)) == [k, c, p]
  814. assert dums(B(c, k, p)*A(p, c, k)) == [k, c, p]
  815. assert dums(B(c, p, k)*A(p, c, k)) == [k, c, p]
  816. assert dums(B(k, c, p)*A(p, c, k)) == [k, c, p]
  817. assert dums(B(k, p, c)*A(p, c, k)) == [k, c, p]
  818. def test_dummy_order_ambiguous():
  819. aa, bb = symbols('a b', above_fermi=True)
  820. i, j, k, l, m = symbols('i j k l m', below_fermi=True, cls=Dummy)
  821. a, b, c, d, e = symbols('a b c d e', above_fermi=True, cls=Dummy)
  822. p, q = symbols('p q', cls=Dummy)
  823. p1, p2, p3, p4 = symbols('p1 p2 p3 p4', above_fermi=True, cls=Dummy)
  824. p5, p6, p7, p8 = symbols('p5 p6 p7 p8', above_fermi=True, cls=Dummy)
  825. h1, h2, h3, h4 = symbols('h1 h2 h3 h4', below_fermi=True, cls=Dummy)
  826. h5, h6, h7, h8 = symbols('h5 h6 h7 h8', below_fermi=True, cls=Dummy)
  827. A = Function('A')
  828. B = Function('B')
  829. from sympy.utilities.iterables import variations
  830. # A*A*A*A*B -- ordering of p5 and p4 is used to figure out the rest
  831. template = A(p1, p2)*A(p4, p1)*A(p2, p3)*A(p3, p5)*B(p5, p4)
  832. permutator = variations([a, b, c, d, e], 5)
  833. base = template.subs(zip([p1, p2, p3, p4, p5], next(permutator)))
  834. for permut in permutator:
  835. subslist = zip([p1, p2, p3, p4, p5], permut)
  836. expr = template.subs(subslist)
  837. assert substitute_dummies(expr) == substitute_dummies(base)
  838. # A*A*A*A*A -- an arbitrary index is assigned and the rest are figured out
  839. template = A(p1, p2)*A(p4, p1)*A(p2, p3)*A(p3, p5)*A(p5, p4)
  840. permutator = variations([a, b, c, d, e], 5)
  841. base = template.subs(zip([p1, p2, p3, p4, p5], next(permutator)))
  842. for permut in permutator:
  843. subslist = zip([p1, p2, p3, p4, p5], permut)
  844. expr = template.subs(subslist)
  845. assert substitute_dummies(expr) == substitute_dummies(base)
  846. # A*A*A -- ordering of p5 and p4 is used to figure out the rest
  847. template = A(p1, p2, p4, p1)*A(p2, p3, p3, p5)*A(p5, p4)
  848. permutator = variations([a, b, c, d, e], 5)
  849. base = template.subs(zip([p1, p2, p3, p4, p5], next(permutator)))
  850. for permut in permutator:
  851. subslist = zip([p1, p2, p3, p4, p5], permut)
  852. expr = template.subs(subslist)
  853. assert substitute_dummies(expr) == substitute_dummies(base)
  854. def atv(*args):
  855. return AntiSymmetricTensor('v', args[:2], args[2:] )
  856. def att(*args):
  857. if len(args) == 4:
  858. return AntiSymmetricTensor('t', args[:2], args[2:] )
  859. elif len(args) == 2:
  860. return AntiSymmetricTensor('t', (args[0],), (args[1],))
  861. def test_dummy_order_inner_outer_lines_VT1T1T1_AT():
  862. ii = symbols('i', below_fermi=True)
  863. aa = symbols('a', above_fermi=True)
  864. k, l = symbols('k l', below_fermi=True, cls=Dummy)
  865. c, d = symbols('c d', above_fermi=True, cls=Dummy)
  866. # Coupled-Cluster T1 terms with V*T1*T1*T1
  867. # t^{a}_{k} t^{c}_{i} t^{d}_{l} v^{lk}_{dc}
  868. exprs = [
  869. # permut v and t <=> swapping internal lines, equivalent
  870. # irrespective of symmetries in v
  871. atv(k, l, c, d)*att(c, ii)*att(d, l)*att(aa, k),
  872. atv(l, k, c, d)*att(c, ii)*att(d, k)*att(aa, l),
  873. atv(k, l, d, c)*att(d, ii)*att(c, l)*att(aa, k),
  874. atv(l, k, d, c)*att(d, ii)*att(c, k)*att(aa, l),
  875. ]
  876. for permut in exprs[1:]:
  877. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  878. def test_dummy_order_inner_outer_lines_VT1T1T1T1_AT():
  879. ii, jj = symbols('i j', below_fermi=True)
  880. aa, bb = symbols('a b', above_fermi=True)
  881. k, l = symbols('k l', below_fermi=True, cls=Dummy)
  882. c, d = symbols('c d', above_fermi=True, cls=Dummy)
  883. # Coupled-Cluster T2 terms with V*T1*T1*T1*T1
  884. # non-equivalent substitutions (change of sign)
  885. exprs = [
  886. # permut t <=> swapping external lines
  887. atv(k, l, c, d)*att(c, ii)*att(d, jj)*att(aa, k)*att(bb, l),
  888. atv(k, l, c, d)*att(c, jj)*att(d, ii)*att(aa, k)*att(bb, l),
  889. atv(k, l, c, d)*att(c, ii)*att(d, jj)*att(bb, k)*att(aa, l),
  890. ]
  891. for permut in exprs[1:]:
  892. assert substitute_dummies(exprs[0]) == -substitute_dummies(permut)
  893. # equivalent substitutions
  894. exprs = [
  895. atv(k, l, c, d)*att(c, ii)*att(d, jj)*att(aa, k)*att(bb, l),
  896. # permut t <=> swapping external lines
  897. atv(k, l, c, d)*att(c, jj)*att(d, ii)*att(bb, k)*att(aa, l),
  898. ]
  899. for permut in exprs[1:]:
  900. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  901. def test_equivalent_internal_lines_VT1T1_AT():
  902. i, j, k, l = symbols('i j k l', below_fermi=True, cls=Dummy)
  903. a, b, c, d = symbols('a b c d', above_fermi=True, cls=Dummy)
  904. exprs = [ # permute v. Different dummy order. Not equivalent.
  905. atv(i, j, a, b)*att(a, i)*att(b, j),
  906. atv(j, i, a, b)*att(a, i)*att(b, j),
  907. atv(i, j, b, a)*att(a, i)*att(b, j),
  908. ]
  909. for permut in exprs[1:]:
  910. assert substitute_dummies(exprs[0]) != substitute_dummies(permut)
  911. exprs = [ # permute v. Different dummy order. Equivalent
  912. atv(i, j, a, b)*att(a, i)*att(b, j),
  913. atv(j, i, b, a)*att(a, i)*att(b, j),
  914. ]
  915. for permut in exprs[1:]:
  916. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  917. exprs = [ # permute t. Same dummy order, not equivalent.
  918. atv(i, j, a, b)*att(a, i)*att(b, j),
  919. atv(i, j, a, b)*att(b, i)*att(a, j),
  920. ]
  921. for permut in exprs[1:]:
  922. assert substitute_dummies(exprs[0]) != substitute_dummies(permut)
  923. exprs = [ # permute v and t. Different dummy order, equivalent
  924. atv(i, j, a, b)*att(a, i)*att(b, j),
  925. atv(j, i, a, b)*att(a, j)*att(b, i),
  926. atv(i, j, b, a)*att(b, i)*att(a, j),
  927. atv(j, i, b, a)*att(b, j)*att(a, i),
  928. ]
  929. for permut in exprs[1:]:
  930. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  931. def test_equivalent_internal_lines_VT2conjT2_AT():
  932. # this diagram requires special handling in TCE
  933. i, j, k, l, m, n = symbols('i j k l m n', below_fermi=True, cls=Dummy)
  934. a, b, c, d, e, f = symbols('a b c d e f', above_fermi=True, cls=Dummy)
  935. p1, p2, p3, p4 = symbols('p1 p2 p3 p4', above_fermi=True, cls=Dummy)
  936. h1, h2, h3, h4 = symbols('h1 h2 h3 h4', below_fermi=True, cls=Dummy)
  937. from sympy.utilities.iterables import variations
  938. # atv(abcd)att(abij)att(ijcd)
  939. template = atv(p1, p2, p3, p4)*att(p1, p2, i, j)*att(i, j, p3, p4)
  940. permutator = variations([a, b, c, d], 4)
  941. base = template.subs(zip([p1, p2, p3, p4], next(permutator)))
  942. for permut in permutator:
  943. subslist = zip([p1, p2, p3, p4], permut)
  944. expr = template.subs(subslist)
  945. assert substitute_dummies(expr) == substitute_dummies(base)
  946. template = atv(p1, p2, p3, p4)*att(p1, p2, j, i)*att(j, i, p3, p4)
  947. permutator = variations([a, b, c, d], 4)
  948. base = template.subs(zip([p1, p2, p3, p4], next(permutator)))
  949. for permut in permutator:
  950. subslist = zip([p1, p2, p3, p4], permut)
  951. expr = template.subs(subslist)
  952. assert substitute_dummies(expr) == substitute_dummies(base)
  953. # atv(abcd)att(abij)att(jicd)
  954. template = atv(p1, p2, p3, p4)*att(p1, p2, i, j)*att(j, i, p3, p4)
  955. permutator = variations([a, b, c, d], 4)
  956. base = template.subs(zip([p1, p2, p3, p4], next(permutator)))
  957. for permut in permutator:
  958. subslist = zip([p1, p2, p3, p4], permut)
  959. expr = template.subs(subslist)
  960. assert substitute_dummies(expr) == substitute_dummies(base)
  961. template = atv(p1, p2, p3, p4)*att(p1, p2, j, i)*att(i, j, p3, p4)
  962. permutator = variations([a, b, c, d], 4)
  963. base = template.subs(zip([p1, p2, p3, p4], next(permutator)))
  964. for permut in permutator:
  965. subslist = zip([p1, p2, p3, p4], permut)
  966. expr = template.subs(subslist)
  967. assert substitute_dummies(expr) == substitute_dummies(base)
  968. def test_equivalent_internal_lines_VT2conjT2_ambiguous_order_AT():
  969. # These diagrams invokes _determine_ambiguous() because the
  970. # dummies can not be ordered unambiguously by the key alone
  971. i, j, k, l, m, n = symbols('i j k l m n', below_fermi=True, cls=Dummy)
  972. a, b, c, d, e, f = symbols('a b c d e f', above_fermi=True, cls=Dummy)
  973. p1, p2, p3, p4 = symbols('p1 p2 p3 p4', above_fermi=True, cls=Dummy)
  974. h1, h2, h3, h4 = symbols('h1 h2 h3 h4', below_fermi=True, cls=Dummy)
  975. from sympy.utilities.iterables import variations
  976. # atv(abcd)att(abij)att(cdij)
  977. template = atv(p1, p2, p3, p4)*att(p1, p2, i, j)*att(p3, p4, i, j)
  978. permutator = variations([a, b, c, d], 4)
  979. base = template.subs(zip([p1, p2, p3, p4], next(permutator)))
  980. for permut in permutator:
  981. subslist = zip([p1, p2, p3, p4], permut)
  982. expr = template.subs(subslist)
  983. assert substitute_dummies(expr) == substitute_dummies(base)
  984. template = atv(p1, p2, p3, p4)*att(p1, p2, j, i)*att(p3, p4, i, j)
  985. permutator = variations([a, b, c, d], 4)
  986. base = template.subs(zip([p1, p2, p3, p4], next(permutator)))
  987. for permut in permutator:
  988. subslist = zip([p1, p2, p3, p4], permut)
  989. expr = template.subs(subslist)
  990. assert substitute_dummies(expr) == substitute_dummies(base)
  991. def test_equivalent_internal_lines_VT2_AT():
  992. i, j, k, l = symbols('i j k l', below_fermi=True, cls=Dummy)
  993. a, b, c, d = symbols('a b c d', above_fermi=True, cls=Dummy)
  994. exprs = [
  995. # permute v. Same dummy order, not equivalent.
  996. atv(i, j, a, b)*att(a, b, i, j),
  997. atv(j, i, a, b)*att(a, b, i, j),
  998. atv(i, j, b, a)*att(a, b, i, j),
  999. ]
  1000. for permut in exprs[1:]:
  1001. assert substitute_dummies(exprs[0]) != substitute_dummies(permut)
  1002. exprs = [
  1003. # permute t.
  1004. atv(i, j, a, b)*att(a, b, i, j),
  1005. atv(i, j, a, b)*att(b, a, i, j),
  1006. atv(i, j, a, b)*att(a, b, j, i),
  1007. ]
  1008. for permut in exprs[1:]:
  1009. assert substitute_dummies(exprs[0]) != substitute_dummies(permut)
  1010. exprs = [ # permute v and t. Relabelling of dummies should be equivalent.
  1011. atv(i, j, a, b)*att(a, b, i, j),
  1012. atv(j, i, a, b)*att(a, b, j, i),
  1013. atv(i, j, b, a)*att(b, a, i, j),
  1014. atv(j, i, b, a)*att(b, a, j, i),
  1015. ]
  1016. for permut in exprs[1:]:
  1017. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  1018. def test_internal_external_VT2T2_AT():
  1019. ii, jj = symbols('i j', below_fermi=True)
  1020. aa, bb = symbols('a b', above_fermi=True)
  1021. k, l = symbols('k l', below_fermi=True, cls=Dummy)
  1022. c, d = symbols('c d', above_fermi=True, cls=Dummy)
  1023. exprs = [
  1024. atv(k, l, c, d)*att(aa, c, ii, k)*att(bb, d, jj, l),
  1025. atv(l, k, c, d)*att(aa, c, ii, l)*att(bb, d, jj, k),
  1026. atv(k, l, d, c)*att(aa, d, ii, k)*att(bb, c, jj, l),
  1027. atv(l, k, d, c)*att(aa, d, ii, l)*att(bb, c, jj, k),
  1028. ]
  1029. for permut in exprs[1:]:
  1030. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  1031. exprs = [
  1032. atv(k, l, c, d)*att(aa, c, ii, k)*att(d, bb, jj, l),
  1033. atv(l, k, c, d)*att(aa, c, ii, l)*att(d, bb, jj, k),
  1034. atv(k, l, d, c)*att(aa, d, ii, k)*att(c, bb, jj, l),
  1035. atv(l, k, d, c)*att(aa, d, ii, l)*att(c, bb, jj, k),
  1036. ]
  1037. for permut in exprs[1:]:
  1038. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  1039. exprs = [
  1040. atv(k, l, c, d)*att(c, aa, ii, k)*att(bb, d, jj, l),
  1041. atv(l, k, c, d)*att(c, aa, ii, l)*att(bb, d, jj, k),
  1042. atv(k, l, d, c)*att(d, aa, ii, k)*att(bb, c, jj, l),
  1043. atv(l, k, d, c)*att(d, aa, ii, l)*att(bb, c, jj, k),
  1044. ]
  1045. for permut in exprs[1:]:
  1046. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  1047. def test_internal_external_pqrs_AT():
  1048. ii, jj = symbols('i j')
  1049. aa, bb = symbols('a b')
  1050. k, l = symbols('k l', cls=Dummy)
  1051. c, d = symbols('c d', cls=Dummy)
  1052. exprs = [
  1053. atv(k, l, c, d)*att(aa, c, ii, k)*att(bb, d, jj, l),
  1054. atv(l, k, c, d)*att(aa, c, ii, l)*att(bb, d, jj, k),
  1055. atv(k, l, d, c)*att(aa, d, ii, k)*att(bb, c, jj, l),
  1056. atv(l, k, d, c)*att(aa, d, ii, l)*att(bb, c, jj, k),
  1057. ]
  1058. for permut in exprs[1:]:
  1059. assert substitute_dummies(exprs[0]) == substitute_dummies(permut)
  1060. def test_issue_19661():
  1061. a = Symbol('0')
  1062. assert latex(Commutator(Bd(a)**2, B(a))
  1063. ) == '- \\left[b_{0},{b^\\dagger_{0}}^{2}\\right]'
  1064. def test_canonical_ordering_AntiSymmetricTensor():
  1065. v = symbols("v")
  1066. c, d = symbols(('c','d'), above_fermi=True,
  1067. cls=Dummy)
  1068. k, l = symbols(('k','l'), below_fermi=True,
  1069. cls=Dummy)
  1070. # formerly, the left gave either the left or the right
  1071. assert AntiSymmetricTensor(v, (k, l), (d, c)
  1072. ) == -AntiSymmetricTensor(v, (l, k), (d, c))