# Substituting requires many dummy index relabelling. # # Test 1: 'm' relabelling is triggered by a_{m} outside # 'n' relabelling in second term ditto # 'n' relabelling in first term because c_{pmn} -> c_{nmn} . def test01(): __cdbkernel__=create_scope() {d1,d2,d3,d4,m,n,p,r}::Indices(vector). obj1:= a_{m}*b_{n} + c_r b_r d_{m n}; substitute(_, $b_{p} -> c_{p m n} A^{m n} + c_{p}$ ) distribute(_) tst1:= a_{m} * c_{n d2 d1} * A^{d2 d1} + a_{m} * c_{n} + c_{r} * c_{r d1 d2} * A^{d1 d2} * d_{m n} + c_{r} * c_{r} * d_{m n} - @(obj1); assert(tst1==0) print('Test 01 passed') test01() def test02(): __cdbkernel__=create_scope() {m,n,p}::Indices(position=fixed). ex:= F_{m n} F^{m n}; rl:= F_{m n} -> G_{m n}; substitute(ex, rl) tst:= G_{m n} F^{m n} - @(ex); assert(tst==0) print('Test 02 passed') test02() def test02b(): # Product substitutions. __cdbkernel__=create_scope() {d1,d2,d3,d4,m,n,p,r,s,t,a,b}::Indices(vector). obj2:= a_{m n} * q * e * b_{m p} * o + d_{n p}; substitute(obj2, $a_{r s} b_{r t} -> c_{s t}$ ) tst2:= c_{n p} q e o + d_{n p} - @(obj2); assert(tst2==0) print('Test 02b passed') test02b() def test02c(): # Reducing to zero __cdbkernel__=create_scope() obj3:= A_{m n} B_{m n} k1_{a} k1_{a} k2_{b}; substitute(_, $k1_a k1_a -> 0$ ) assert(obj3==0) print('Test 02c passed') test02c() def test03(): # Upper and lower indices replaced automagically. # # Side note: the replacement # rl:= F_{m n} -> G_{m n} + H^{m n}; # is tricky. A rule will be generated for all objects # matched on the lhs. So _m and _n to something. But on the rhs, that would # not normally match. Best to disallow these rules. __cdbkernel__=create_scope() {m,n,p,q}::Indices(position=free). ex:= F_{p q} F^{p q}; rl:= F_{m n} -> G_{m n}; substitute(ex, rl) rename_dummies(ex) tst2:= G_{m n} G^{m n} - @(ex); assert(tst2==0) print('Test 03 passed') test03() def test04(): # Basic test of variational derivative. __cdbkernel__=create_scope() obj43:= A*B*A + D*E; vary(obj43, $A->C$) tst43:= C*B*A + A*B*C - @(obj43); assert(tst43==0) print('Test 04 passed') test04() def test04b(): # Indices in the pattern. __cdbkernel__=create_scope() obj4:= A_m A_n + B_m C_n + D_{m n} A_p A_p; substitute(_, $A_a A_a -> q$ ) tst4:= A_m A_n + B_m C_n + D_{m n} q - @(obj4); assert(tst4==0) print('Test 04b passed') #test04b() def test05(): # Variational derivative under Accents. __cdbkernel__=create_scope() \bar{?}::Accent. obj45:= \bar{A}*B*A; vary(obj45, $A -> C$) tst45:= \bar{C}*B*A + \bar{A}*B*C - @(obj45); assert(tst45==0) print('Test 05 passed') test05() def test06(): # Nested substitutes. __cdbkernel__=create_scope() {a,b,c,d}::Indices. { \partial{#}, \partialp{#} }::PartialDerivative. A::Depends(\partial{#}). B::Depends(\partialp{#}). \Omega{#}::Derivative. obj46:= \Omega( \partial_{a}{A} )( \partialp_{b}{B} ); rl:= \Omega( \partial_{a}{A??} )( B?? ) -> \partial_{a}{ \Omega(A??)(B??) }; substitute(obj46, rl) tst46:= \partial_{a}{ \Omega(A)(\partialp_{b}{B}) } - @(obj46); assert(tst46==0) print('Test 06 passed') test06() def test07(): # Vary multiple terms and single-factor terms. __cdbkernel__=create_scope() obj70:= A + B Q; vary(_, $A -> Q, B -> Z$ ) tst70:= Q + Z Q - @(obj70); assert(tst70==0) print('Test 07 passed') test07() def test17(): # Test 17: Object wildcards obj17:= [ A B, C]; substitute(_, $[ M? N?, P? ] -> P? M? N?$ ) tst17:= @(obj17) - C A B; assert(tst17==0) print('Test 17 passed') test17() def test84(): # Bug reported Sun, 9 Nov 2014 15:51:05 +0800 \partial{#}::PartialDerivative. yy:= a+ a*A; vary(yy, $A->\delta{A}$ ) tst84:= a \delta{A} - @(yy); assert(tst84==0) print('Test 84 passed') test84() def test100(): {\mu,\nu,\rho}::Indices(position=free). \partial{#}::PartialDerivative. ex:= \int{\partial_{\mu}{A_{\nu}} - \partial_{\nu}{A_{\mu}}}{x}; vary(ex, $A_{\mu} -> \delta{A_{\mu}}$) def test101(): __cdbkernel__=create_scope() {m,n,p}::Integer; A_{m}::SelfNonCommuting. ex:= A_{3} A_{2} A_{1} A_{0} + A_{0} A_{8}; rl:= A_{m} A_{n} | m > n -> Q; substitute(ex, rl, repeat=True) tst:= Q Q + A_{0} A_{8} - @(ex); assert(tst==0) print('Test 101 passed') test101() def test102(): __cdbkernel__=create_scope() {m,n,p}::Integer; {m,n,p}::Symbol; A_{m}::SelfNonCommuting; ex:= A_{2} A_{3} A_{1} + A_{1} A_{0}; rl:= A_{m} A_{n} | m > n -> A_{n} A_{m} + Q; ex.reset() while ex.changed(): distribute(ex) substitute(ex, rl) sort_product(ex) tst:= A_{1} A_{2} A_{3} + A_{3} Q + A_{2} Q + A_{0} A_{1} + Q - @(ex); assert(tst==0) print('Test 102 passed') test102() def test103(): __cdbkernel__=create_scope() \partial{#}::PartialDerivative; rl:= A_{m? n?} -> \partial_{m?}{B_{n?}}; ex:= A_{4 k} A_{k 4}; substitute(ex, rl) tst:= \partial_{4}{B_{k}} \partial_{k}{B_{4}} - @(ex); assert(tst==0) test103() def test104(): __cdbkernel__=create_scope() {m,n,p}::Indices(position=independent); ex:= g^{4}; rl:= g_{4} -> A; # How is this thing supposed to know that 4 is in the {m,n,p} set? substitute(ex, rl) tst:= g^{4} - @(ex); assert(tst==0) print("Test 104 passed") test104() def test105(): __cdbkernel__=create_scope() ex:= A_{m n} + B_{m n}; rl:= C?_{m? n?} -> n? C?_{n?}; substitute(ex, rl) tst:= n A_{n} + n B_{n} - @(ex); assert(tst==0) print("Test 105 passed") test105() def test106(): __cdbkernel__=create_scope() {m,n,p}::Indices(position=free); ex:=\int{ A_{m} A^{m} }{x}; rl:= A_{m} -> B_{m n} C^{n}; substitute(ex, rl) tst:= \int{ B_{m n} C^{n} B^{m}_{p} C^{p} }{x} - @(ex); assert(tst==0) print("Test 106 passed") test106() def test107(): __cdbkernel__=create_scope() ex:= A_{m n} - B_{m n}; substitute(ex, $_{m} -> _{2}$) tst:= A_{2 n} - B_{2 n} - @(ex); assert(tst==0) print("Test 107 passed") test107() def test108(): __cdbkernel__=create_scope() \nabla{#}::Derivative; {\mu,\nu,\rho,\sigma}::Indices(position=fixed); ex:= \nabla_{\mu}{K^{\nu}} = B_{\mu} D^{\nu}; substitute(_, $\nabla_{\mu}{A?^{\nu}} = C_{\mu}^{\nu}$) tst:= C_{\mu}^{\nu} = B_{\mu} D^{\nu}; assert(ex==tst) print("Test 108 passed") test108() def test109(): __cdbkernel__=create_scope() {\mu,\nu,\rho,\sigma}::Indices; \partial{#}::PartialDerivative; g_{\mu\nu}::Metric; g^{\mu\nu}::InverseMetric; g^{\mu}_{\nu}::KroneckerDelta; g_{\mu}^{\nu}::KroneckerDelta; ex:= \partial_{5}{ g^{5 5} } \partial_{5}{ g_{5 5} } - A_{5}; substitute(ex, $g_{5 5} -> B$) tst:= \partial_{5}{ g^{5 5} } \partial_{5}{B} - A_{5} - @(ex); assert(tst==0) print("Test 109 passed") test109() # def test110(): # {\mu,\nu,\rho}::Integer(0..d-1). # {\mu,\nu,\rho}::Indices. # {m,n}::Integer. # rl:= \alpha_{m}^{\mu} \alpha_{n}^{\nu} | m > n -> \alpha_{n}^{\nu} \alpha_{m}^{\mu} + \delta_{m}_{-n} \delta^{\mu\nu}; # ex:= \alpha_{1}^{\mu} \alpha_{0}^{\mu}; # substitute(ex, rl); def test110(): __cdbkernel__=create_scope() ex:= A + 2 B + C + 2 D; substitute(_, $B + D = Q$) tst:= A + C + 2 Q - @(ex); assert(tst==0) print("Test 110 passed") test110() def test111(): __cdbkernel__=create_scope() {t,x}::Coordinate; {\mu, \nu, \rho, \sigma}::Indices(values={t,x}, position=fixed); \partial{#}::PartialDerivative; ex:= \partial_{\mu}{ g_{\rho\sigma} }; rl:= \partial_{t}{ g_{\mu\nu} } -> C_{\mu\nu}; substitute(ex, rl) tst:= \partial_{\mu}{ g_{\rho\sigma} } - @(ex); assert(tst==0) print("Test 111 passed") test111() def test112(): __cdbkernel__=create_scope() {m,n,p,q}::Indices; ex:=A B_{m n} C; rl:=A?_{p q} -> - 2 A?_{p q}; substitute(ex, rl) tst:=-2 A B_{m n} C - @(ex); assert(tst==0) print("Test 112 passed") test112() def test113(): # spotted by Leo Brewin 15-Mar-2018. __cdbkernel__=create_scope() {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s}::Indices(position=fixed). ex := A^{f} A^{m} B_{g f} G^{a}_{m e} G^{e}_{b d}. substitute(_, $A^{e} B_{c e} G^{a}_{b d} -> A^{f} B_{f} R^{a}_{b c d}$) tst:= A^{f} B_{f} R^{a}_{m g e} A^{m} G^{e}_{b d} - @(ex); assert(tst==0) print("Test 113 passed") test113() def test114(): __cdbkernel__=create_scope() {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s}::Indices(position=fixed). ex := B^{c}_{a d} A^{d} A^{e}. substitute(ex, $A^{c} A^{b} B^{a}_{d b} -> A^{b} A^{c} C^{a}_{b d}$) tst:= A^{d} A^{e} C^{c}_{d a} - @(ex); assert(tst==0) print("Test 114 passed") test114() def test115(): __cdbkernel__=create_scope() {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s}::Indices(position=fixed). ex := B^{c}_{a d} A^{d} A^{e}. substitute(ex, $B^{a}_{d b} A^{c} A^{b} -> A^{b} A^{c} C^{a}_{b d}$) tst:= A^{d} A^{e} C^{c}_{d a} - @(ex); assert(tst==0) print("Test 115 passed") test115() def test116(): __cdbkernel__=create_scope() D{#}::Derivative; {\epsilon, \psi_{\mu},\psi_{\mu\nu} }::Spinor(dimension=4, type=Majorana); \Gamma_{#}::GammaMatrix(metric=\delta); ex:= \bar{D_{\mu}{\epsilon}} \Gamma^{m n p} D_{\nu}{\psi_{\rho}} e e_{m}^{\mu} e_{n}^{\nu} e_{p}^{\rho} + Q; pat:= \bar{D_{\mu}{\epsilon}} A??; sort_product(_) take_match(ex, pat) tst:= \bar{D_{\mu}{\epsilon}} \Gamma^{m n p} D_{\nu}{\psi_{\rho}} e e_{m}^{\mu} e_{n}^{\nu} e_{p}^{\rho} - @(ex); assert(tst==0) print("Test 116 passed") test116() def test117(): __cdbkernel__=create_scope() ex:= s A_{s}; substitute(ex, $s -> 1$) tst:= A_{s} - @(ex); assert(tst==0) print("Test 117a passed") {p,q,r,s,t,u,v,w}::Indices. ex := s**2 y^{r} y^{s} A_{r s}; substitute(ex, $s->1$) tst:= y^{r} y^{s} A_{r s} - @(ex); assert(tst==0) print("Test 117b passed") test117() def test118(): __cdbkernel__=create_scope() ex:= s A_{s}; substitute(ex, $_{s} -> _{1}$) tst:= s A_{1} - @(ex); assert(tst==0) print("Test 118 passed") test118() def test119(): __cdbkernel__=create_scope() {a,b,c,d,e,f}::Indices(spinor); {m,n,p,q}::Indices(spacetime); \theta^{a}::SelfAntiCommuting; ex:=\theta^{a} \sigma^{m}_{a b} \theta^{b} \tau^{n c d} \sigma^{p}_{d e} \theta^{e} \theta^{f}; rl:=\theta^{a} \theta^{b} \theta^{c} \sigma^{m}_{c d} \theta^{d} -> \tau^{m a b}; substitute(ex, rl) tst:= \tau^{n c d} \sigma^{p}_{d e} \tau^{m e f} - @(ex); assert(tst==0) print("Test 119 passed") test119() def test120(): __cdbkernel__=create_scope() {a,b,c,d,e,f}::Indices(spinor); {m,n,p,q}::Indices(spacetime); \theta^{a}::SelfAntiCommuting; ex:=\theta^{b} \sigma^{m}_{a b} \theta^{a} \tau^{n c d} \sigma^{p}_{d e} \theta^{e} \theta^{f}; rl:=\theta^{a} \theta^{b} \theta^{c} \sigma^{m}_{c d} \theta^{d} -> \tau^{m a b}; substitute(ex, rl) tst:= -\tau^{n c d} \sigma^{p}_{d e} \tau^{m e f} - @(ex); assert(tst==0) print("Test 120 passed") test120() def test121(): __cdbkernel__=create_scope() {\dagger}::Symbol. {a,n,\sigma,\tau}::Symbol; {\Gamma^{\dagger}_{\tau?}, N_{a? \tau?}, G_{n? \sigma?}}::NonCommuting. {\Gamma^{\dagger}_{\tau?}, N_{a? \tau?}}::Depends(\commutator{#}); rule:= N_{a? \tau?} G_{n?? \sigma?} -> n?? G_{(n??-1) \sigma?} \commutator{N_{a? \tau?}}{\Gamma^{\dagger}_{\sigma?}} + 1/2 n?? (n??-1) \commutator{\commutator{N_{a? \tau?}}{\Gamma^{\dagger}_{\sigma?}}}{\Gamma^{\dagger}_{\sigma?}} G_{(n??-2) \sigma?}; ex:=N_{a \tau} G_{{n-1} \sigma}; substitute(_,rule) tst:= (n-1) G_{{n-2} \sigma} \commutator{ N_{a \tau} }{ \Gamma^{\dagger}_{\sigma} } + 1/2 (n-1) (n-2) \commutator{ \commutator{ N_{a \tau} }{ \Gamma^{\dagger}_{\sigma} }}{ \Gamma^{\dagger}_{\sigma} } G_{{n-3} \sigma} - @(ex); assert(tst==0) print("Test 121 passed") test121() def test122(): __cdbkernel__=create_scope() ex:= L_{0 1} + L_{4 5}; rl:= L_{a? b?} | a? > 3 -> Q_{a? b?}; substitute(ex, rl) tst:= L_{0 1} + Q_{4 5} - @(ex); assert(tst==0) print("Test 122 passed") test122() def test123(): __cdbkernel__=create_scope() {A, B, C, D, E, F}::NonCommuting; ex:= A B C D E F + B C A D E F; substitute(_, $C D E -> Q$) tst:= A B F + B C A D E F - @(ex); assert(tst==0) print("Test 123a passed") ex:= A B C D E F + B C A D E F; substitute(_, $C D E -> Q$, partial=False) tst:= A B C D E F + B C A D E F - @(ex); assert(tst==0) print("Test 123b passed") ex:= A + B + C + D; substitute(_, $A + C = Q$); tst:= Q + B + D - @(ex); assert(tst==0) print("Test 123c passed") ex:= A + B + C + D; substitute(_, $A + C = Q$, partial=False); tst:= A + B + C + D - @(ex); assert(tst==0) print("Test 123d passed") #test123() # substitute(_, $A C?* F -> F A B C?* $, partial=False); def test124(): __cdbkernel__=create_scope() \dot{#}::Accent; {\dot{\alpha}, \dot{\beta}, \dot{\gamma}, \dot{\delta}}::Indices(spinor, position=fixed); {\dot{\alpha}, \dot{\beta}, \dot{\gamma}, \dot{\delta}}::Integer(1..2); \nabla{#}::Derivative; ex:=\nabla^{\dot{\gamma}}(\theta^{\dot{\alpha}}) \theta_{\dot{\alpha}}; substitute(_, $\nabla^{\dot{\alpha}}{\theta^{\dot{\beta}}} -> \epsilon^{\dot{\beta} \dot{\alpha}}$) tst:= \epsilon^{\dot{\alpha} \dot{\gamma}} \theta_{\dot{\alpha}} - @(ex); assert(tst==0) print("Test 124 passed") test124() def test125(): __cdbkernel__=create_scope() ex:=T_{A}; substitute(ex, $T{A?} = Q$) try: tst:= T_{A} - @(ex); assert(tst==0) print("Test 125a passed") except: assert(False) ex:=T{A}; substitute(ex, $T_{A?} = Q$) try: tst:= T{A} - @(ex); assert(tst==0) print("Test 125b passed") except: assert(False) test125() # \del{#}::LaTeXForm("\partial"). # ex:=\del_{m}{A}; # res=ex._latex_() # # ex:=A_{m}(x); # substitute(ex, $A{#}->Q$); # # \hat{R}_{a b c d} # R(x,y) def test126(): # Inside powers, dummies can be repeated. __cdbkernel__=create_scope() {n,m,p,q}::Indices; ex:= A^{n} / (A^{m} A^{m}); rename_dummies(ex) tst:= A^{n} / (A^{n} A^{n}) - @(ex); assert(tst==0) print("Test 126 passed") test126() def test127(): # Expect an exception when substituting with empty rule. __cdbkernel__=create_scope() ex:= A + B; try: substitute(ex, $ $); assert(False) except Exception: print("Test 127a passed") try: substitute(ex, ${ }$) assert(1==0) except Exception: print("Test 127b passed") test127() def test128(): # FIXME: adding create_scope here makes things fail, why? # __cdbkernel__=create_scope() a::Symbol; b::Symbol; {a**m?, b**n?, a, b}::NonCommuting; r1 := { a b**m? -> (1+b a) b**{m?-1}, a b -> 1 + b a, }; def act(ex): converge(ex): substitute(ex,r1) distribute(ex) collect_factors(ex) print(ex) return ex ex:=a b**5; act(ex); tst:= 5 b**4 + b**5 a - @(ex); assert(tst==0) print("Test 128 passed") test128()