def test01(): __cdbkernel__=create_scope() ex:= a*b+a*c+d; factor_in(_, $b,c$) tst:=(b+c)*a + d - @(ex); assert(tst==0) print('Test 01 passed') test01() def test01b(): __cdbkernel__=create_scope() ex:= a*b*c+a*c+d; factor_in(_, $b,c$) tst:=(b*c+c)*a + d - @(ex); assert(tst==0) print('Test 01b passed') test01b() def test02(): __cdbkernel__=create_scope() ex:=2*a+b*a; factor_in(_, $b$) tst:=(2+b)*a - @(ex); assert(tst==0) print('Test 02 passed') test02() def test03(): __cdbkernel__=create_scope() ex:= 3*a*b + 5*c*b; factor_in(_, $a,c$) tst:=(3 a + 5 c) b - @(ex); assert(tst==0) print('Test 03 passed') test03() def test04(): __cdbkernel__=create_scope() ex:= a b + a c e - 4 q - 2 g a d + a d - 3 p s - 9/2 a; factor_out(_, $a$) tst4:= -4 q - 3 p s + a*(b + c e - 2 g d + d - 9/2) - @(ex); assert(tst4==0) print('Test 04 passed') test04() def test05(): __cdbkernel__=create_scope() ex:= c - a; factor_out(_, $a$) tst:= c - a - @(ex); assert(tst==0) print('Test 05 passed') test05() def test06(): __cdbkernel__=create_scope() ex:= 3 a b + 2 a c e + 5 a c + 7 e f - 2 c e + c d - a d + a - c; factor_out(ex, $a,c$) tst5:= a * c * (2 * e + 5) + c * ( - 2 * e + d - 1) + a * (3 * b - d + 1) + 7 * e * f - @(ex); assert(tst5==0) print('Test 06 passed') test06() # Non-commuting objects # Basic behaviour def test07(): __cdbkernel__=create_scope() {A, B, C, D, E}::NonCommuting; ex := A B + A C + D A + E A: factor_out(_, $A$, right=True) factor_out(_, $A$, right=False) tst := A*(B + C) + (D + E)*A - @(ex); assert(tst==0) print('Test 07 passed') test07() def test08(): __cdbkernel__=create_scope() {A, B, C, D}::AntiCommuting. obj := A B + A C + D A: factor_out(_, $A$) tst := A*(B + C - D) - @(obj); assert(tst==0) print('Test 08 passed') test08() # Ordering of pulled out factors def test09(): __cdbkernel__=create_scope() {A, B}::AntiCommuting. obj := A B c X + c B A Y: factor_out(_, $A, B, c$) tst := A B c * (X - Y) - @(obj); assert(tst==0) print('Test 09 passed') test09() def test10(): __cdbkernel__=create_scope() {A, B}::AntiCommuting. {A, X, Y}::NonCommuting. {B, X, Y}::NonCommuting. obj := A B c X + c B A Y + X A B c + Y c B A: factor_out(_, $c, A, B$) factor_out(_, $c, A, B$, right=True) tst := (A B (X-Y) + (-X+Y) A B) c - @(obj); assert(tst==0) print('Test 10 passed') test10() # Ordering past a non commuting term def test11(): __cdbkernel__=create_scope() {A, B, C, D, E}::AntiCommuting. {A, X}::NonCommuting. {B, X}::NonCommuting. obj := X A B Y + X B A Z: factor_out(_, $A, B, X$) tst := X A B (Y - Z) - @(obj); assert(tst==0) print('Test 11 passed') test11() def test12(): __cdbkernel__=create_scope() {A, B, C, D, E}::AntiCommuting. {A, X}::NonCommuting. {B, X}::NonCommuting. obj := A B X A B Y + B A X B A Z: factor_out(_, $A, B, X$) tst := A B X A B (Y + Z) - @(obj); assert(tst==0) print('Test 12 passed') test12() def test13(): __cdbkernel__=create_scope() {A, B, C, D, E}::AntiCommuting. {A, X}::NonCommuting. {B, X}::NonCommuting. obj := A B C D Y + D A B C Z: factor_out(_, $A, B, C, D$) tst := A B C D (Y - Z) - @(obj); assert(tst==0) print('Test 13 passed') test13() # Indices. def test14(): __cdbkernel__=create_scope() obj:= A_{a} B_{b} + A_{a} C_{b} + A_{b} D_{a}; factor_out(_, $A_{a}$) tst:= A_{a} (B_{b} + C_{b}) + A_{b} D_{a} - @(obj); assert(tst==0) print('Test 14 passed') test14() def test15(): __cdbkernel__=create_scope() ex:= 3 A G B_{m} C D + 4 E_{m} ; factor_out(_, $ A $ ) tst:= 3 A G B_{m} C D + 4 E_{m} - @(ex); assert(tst==0) print('Test 15 passed') test15() def test16(): __cdbkernel__=create_scope() ex:= 3 A G B_{m} C D + 4 E_{m} ; factor_out(_, $ A $, right=True ) tst:= 4 E_{m} + 3 G B_{m} C D A - @(ex); assert(tst==0) print('Test 16 passed') test16() def test17(): __cdbkernel__=create_scope() ex:= x*x + x*x*x; factor_in(ex, $x$) tst:= x*x + x*x*x - @(ex); assert(tst==0) print("Test 17 passed") test17() def test18(): __cdbkernel__=create_scope() {a,b,c,d,e}::Indices; D{#}::Derivative; ex:= D_{a}{D_{b}{F}} - D_{b}{D_{a}{F}} - S A_{a b}; factor_in(ex, $ S $) tst:= D_{a}{D_{b}{F}} - D_{b}{D_{a}{F}} - S A_{a b} - @(ex); assert(tst==0) print("Test 18 passed") test18() # @reset. # {a,b,m,n,p,q}::Indices. # obj6:= A_{m n} C_{m n} D_{p q} + A_{p m} C_{m n} D_{n q} + A_{m n} C_{m n} E_{p q} Q; # @factor_out!(%){ A_{a b}, C_{m n} }; # # NOTE: see the email to James Allen on Thu, 14 Oct 2010 20:58:52 +0100. # Should be solved by modifying @rename_dummies. The text below is obsolete but # kept until the bug is fixed. # # This is very subtle. Consider # # A_{m n} C_{n p} D_{m p} + A_{q r} C_{r s} E_{q t} F_{t s} # # This can clearly factor_out A & C. Standard comparison of the two prefactors # would give a match, since A_{m n} C_{n p} and A_{q r} C_{r s} are equivalent. # But we would need to relabel indices along the way. # # However, @collect_terms does not do this type of collecting either: it requires # you to rename dummies first. If we do that, our problem goes away here too. #{m,n,p,q,r,s,t}::Indices. #A_{m n} C_{n p} D_{m p} + A_{q r} C_{r s} E_{q t} F_{t s}; #@rename_dummies!(%); # So the conclusion is that we would prefer to stick to a simpler matching, in which # we only allow for dummy index names to differ. But what do we then do with #{m,n,p,q,r,s,t}::Indices. #A_{m n} D_{m p} Q_{n p} + A_{q r} E_{q t} F_{t s} Q_{r s} ; #@rename_dummies!(%); # -> A_{m n} * D_{m p} * Q_{n p} + A_{m n} * E_{m p} * F_{p q} * Q_{n q}; # This does not lead to equal A*Q factors. So it seems that we are forced # to do a comparison in which we flag # # A_{m n} Q_{m n} and A_{m n} Q_{n q} as un-equal # # A_{m n} Q_{n q} and A_{m n} Q_{n p} as equal # # # {m,n,p,q,r,s,t}::Indices; # ex:= A_{m n} D_{m p} Q_{n p} + A_{q r} E_{q t} F_{t s} Q_{r s} ; # factor_out(_, $A_{m n}$); # sort_product(_); # rename_dummies(_);