
# Test gamma algebra manipulations. Implicitly tests the combinatorics
# module too.

def test01():
    __cdbkernel__=create_scope()
    \Gamma_{#}::GammaMatrix(metric=\delta).
    obj1:= \Gamma^{a b}\Gamma_{c};
    join_gamma(obj1)
    tst1:= \Gamma^{a b}_{c} + \Gamma^{a} \delta^{b}_{c} - \Gamma^{b} \delta^{a}_{c} - @(obj1);
    collect_terms(tst1)
    assert(tst1==0)
    print("Test 01 passed")

#test01()

# Test of the join functionality which keeps anti-symmetry in certain
# indicated indices implicit (obj3a) versus the full thing (obj3b).
#
# The logic is that if you _know_ that in the final result you are
# going to acanonicalorder in a given set of indices that appear
# on the gamma matrices that you start with, then you may as well
# forget about all explicit anti-symmetrisations in those indices.

def test02():
    __cdbkernel__=create_scope()
    \delta_{m n}::KroneckerDelta.
    \Gamma_{#}::GammaMatrix(metric=\delta).
    obj3a:= \Gamma_{c d}\Gamma_{m1 m2 m3}\Gamma_{n1 n2};

#test02()

def test02b():
    __cdbkernel__=create_scope()
    \bar{#}::DiracBar;
    \psi::Spinor(dimension=10);
    \Gamma{#}::GammaMatrix;
    ex:=\bar{\Gamma^{m n p} \psi};
    expand_diracbar(ex)
    tst:=\bar{\psi} \Gamma^{m n p} - @(ex);
    assert(tst==0)
    print("Test 02b passed")

#test02b()

# {m, n, p, q, r, a, b, c}::Indices(flat, position=free);
# {m, n, p, q, r, a, b, c}::Integer(1..10);
# \delta_{m n}::KroneckerDelta;
# ex:=\delta^{q q};
# eliminate_kronecker(ex);
# 
# {m, n, p, q, r, a, b, c}::Indices(flat, position=fixed);
# ex:=\delta_{q r};
# substitute(ex, $\delta^{q r} -> K^{q r}$)
# {m, n, p, q, r, a, b, c}::Indices(flat, position=free);
# substitute(ex, $\delta^{q r} -> K^{q r}$)
# 
# 
# 
# 
# \delta_{m n}::SelfCommuting;
# \delta_{m n}::KroneckerDelta;
# {m, n, p, q, r, a, b, c}::Indices(flat, position=free);
# {m, n, p, q, r, a, b, c}::Integer(1..10);
# 
# \GAMMA^{#}::GammaMatrix(metric=\delta).
# one:= \GAMMA^{m n p q r}\GAMMA^{a}\GAMMA^{b}\GAMMA^{m n p}\GAMMA^{c}\GAMMA^{q r};
# join_gamma(_);
# distribute(_);
# eliminate_kronecker(_);
# canonicalise(_);
# sort_product(_);
# 
# join_gamma(_);
# distribute(_);
# eliminate_kronecker(_);
# canonicalise(_);
# sort_product(_);
# 
# 
# \delta_{m n}::KroneckerDelta.
# \Gamma_{#}::GammaMatrix(metric=\delta)
# ex:=\Gamma_{a b c}\Gamma_{c d}\Gamma_{e};
# join_gamma(ex)
# distribute(ex)
# sort_product(ex)
# join_gamma(ex)


        
# segfault

# obj3b:= @(obj3a);
# @join!(obj3a){expand}{m1,m2,m3}{n1,n2};
# @distribute!(%);
# @prodsort!(%);
# @join!(%){expand}{m1,m2,m3}{n1,n2};
# @distribute!(%);
# @acanonicalorder!(%){_{m1},_{m2},_{m3}};
# @acanonicalorder!(%){_{n1},_{n2}};
# @canonicalise!(%);
# @collect_terms!(%);
# 
# @join!(obj3b){expand};
# @distribute!(%);
# @prodsort!(%);
# @join!(%){expand};
# @distribute!(%);
# @acanonicalorder!(obj3b){_{m1},_{m2},_{m3}};
# @acanonicalorder!(%){_{n1},_{n2}};
# @collect_terms!(%);
# 
# tst3:= @(obj3a)-@(obj3b);
# @canonicalise!(%);
# @collect_terms!(%);
# @assert(tst3);
# 
# # Another one, weird.
# \Gamma_{m1 m2 m3 r1 r2 r3 r4 l} * \Gamma_{n1 n2 n3};
# @join!(%){5}{expand}{n1,n2,n3};
# 
# \Gamma_{m1 m2 m3 r1 r2 r3 r4 l} * \Gamma_{n1 n2 n3};
# @join!(%){5}{expand};
# 
# 
# 
# 

# This is one from the Abra help document. Much nicer now in
# Cadabra 2.x.    

def test03():
    __cdbkernel__ = create_scope()
        
    \delta{#}::KroneckerDelta.
    {m, n, p, q, r, a, b, c}::Indices(flat).
    {m, n, p, q, r, a, b, c}::Integer(1..10).
    \GAMMA{#}::GammaMatrix(metric=\delta).

    def post_process(ex):
        distribute(ex)
        eliminate_kronecker(ex)
        sort_product(ex)
        canonicalise(ex)
        collect_terms(ex)

    one:= \GAMMA^{m n p q r}\GAMMA^{a}\GAMMA^{b}\GAMMA^{m n p}\GAMMA^{c}\GAMMA^{q r};
    for i in range(5):
        join_gamma(one)

    tst:=- 2016 * \GAMMA^{a b c} - 2016 * \GAMMA^{a} * \delta^{b c} + 2016 * \GAMMA^{b} * \delta^{a c} + 18144 * \GAMMA^{c} * \delta^{a b} - @(one);
    assert(tst==0)
    print("Test 03a passed")
    two:= \GAMMA^{a}*@(one);
    join_gamma(two)
    assert(two==0)
    print("Test 03b passed")

test03()

# 
# 
# # Test 5:= brackets
# #
# @reset.
# \Gamma_{#}::GammaMatrix(metric=\delta).
# obj5:= (\Gamma_r \Gamma_s);
# @join!(%);
# tst5:= (\Gamma_{r s} + \delta_{r s}) - @(obj5);
# @sumflatten!(%);
# @collect_terms!(%);
# @assert(tst5);
# 
# # Test 6:= taking care of dimensions
# #
# @reset;
# \Gamma_{#}::GammaMatrix(metric=\delta).
# {m,n,p,q,r,s,t}::Integer(0..3);
# obj6:= \Gamma_{m n p} \Gamma_{q r};
# @join!(%);
# tst6:= 6 * \Gamma_{m n r} * \delta_{p q}
#     + 6 * \Gamma_{m} * \delta_{p q} * \delta_{n r} - @(obj6);
# @collect_terms!(%);
# @assert(tst6);
# 
# 
# # Test 7:= back and front-split
# #
# @reset;
# \Gamma_{#}::GammaMatrix(metric=\delta).
# obj7:= \Gamma_{m n p q};
# @gammasplit(%);
# @join!(%){expand};
# @collect_terms!(%);
# tst7:= \Gamma_{m n p q} - @(obj7);
# @collect_terms!(%);
# @assert(tst7);
# 
# @reset;
# \Gamma_{#}::GammaMatrix(metric=\delta).
# obj8:= \Gamma_{m n p q};
# @gammasplit(%){front};
# @join!(%){expand};
# @collect_terms!(%);
# tst8:= \Gamma_{m n p q} - @(obj8);
# @collect_terms!(%);
# @assert(tst8);
# 
# 
# @reset;
# \delta_{m n}::KroneckerDelta.
# \Gamma_{#}::GammaMatrix(metric=\delta).
# \psi_{m}::GammaTraceless.
# \psi_{m}::Spinor.
# obj9:= T_{a b} * ( A_{m n} \Gamma_{r s p t u v} \psi_{p} B_{q r}
#           + A_{m n} \psi_{p} \Gamma_{r s p t u v} B_{q r} );
# @remove_gamma_trace!(%);
# @distribute!(%);
# @prodsort!(%);
# tst9:= - A_{m n} * B_{q r} * T_{a b} * \Gamma_{r s t u} * \psi_{v}
#  + A_{m n} * B_{q r} * T_{a b} * \Gamma_{r s t v} * \psi_{u}
#  - A_{m n} * B_{q r} * T_{a b} * \Gamma_{r s u v} * \psi_{t}
#  + A_{m n} * B_{q r} * T_{a b} * \Gamma_{r t u v} * \psi_{s}
#  - A_{m n} * B_{q r} * T_{a b} * \Gamma_{s t u v} * \psi_{r}
#  - A_{m n} * B_{q r} * T_{a b} * \psi_{r} * \Gamma_{s t u v}
#  + A_{m n} * B_{q r} * T_{a b} * \psi_{v} * \Gamma_{s t u r}
#  - A_{m n} * B_{q r} * T_{a b} * \psi_{u} * \Gamma_{s t v r}
#  + A_{m n} * B_{q r} * T_{a b} * \psi_{t} * \Gamma_{s u v r}
#  - A_{m n} * B_{q r} * T_{a b} * \psi_{s} * \Gamma_{t u v r}
#  - @(obj9);
# @collect_terms!(%);
# @assert(tst9);
# 
# # Test 10: Silly trivialities
# @reset.
# {m,n,p,q,r,s,t,m#}::Indices(flat).
# {m,n,p,q,r,s,t,m#}::Integer(0..3).
# \Gamma_{#{m}}::GammaMatrix(metric=\delta).
# \delta_{m n}::KroneckerDelta.
# \epsilon_{m n p q}::AntiSymmetric.
# obj10:= \epsilon_{m n p q} \Gamma_{m n p q} \Gamma_{r} \Gamma_{s t} \Gamma_{r};
# @join!(%){expand};
# @distribute!(%);
# @eliminate_kr!(%);
# @canonicalise!(%);
# @rename_dummies!(%);
# @collect_terms!(%);
# 
# @join!(%){expand}{m,n,p,q};
# @distribute!(%);
# @eliminate_kr!(%);
# @canonicalise!(%);
# @rename_dummies!(%);
# @collect_terms!(%);
# 
# @join!(%){expand};
# @distribute!(%);
# @eliminate_kr!(%);
# @canonicalise!(%);
# @rename_dummies!(%);
# @collect_terms!(%);
# # This one is a Schouten identity, so:
# @decompose_product!(%);
# @collect_terms!(%):
# @canonicalise!(%);
# @collect_terms!(%);
# @assert(obj10);
# 
# \epsilon_{m n p q}::AntiSymmetric.
# @asym[\epsilon_{s m n p} Q_{t}]{_{s},_{t},_{m},_{n},_{p}};
# 
# obj10b:= \epsilon_{m n p q} G_{m n p q} \Gamma_{r} \Gamma_{s t} \Gamma_{r};
# @join!(%){expand};
# @distribute!(%);
# @eliminate_kr!(%);
# @canonicalise!(%);
# @rename_dummies!(%);
# @collect_terms!(%);
# 
# @join!(%){expand}{m,n,p,q};
# @distribute!(%);
# @eliminate_kr!(%);
# @canonicalise!(%);
# @rename_dummies!(%);
# @collect_terms!(%);
# @assert(obj10b);
# 

# Numerical indices

def test03():
    __cdbkernel__ = create_scope()
    \delta{#}::KroneckerDelta.
    \gamma{#}::GammaMatrix(metric=\delta).
    obj3:= \gamma_{1 2}\gamma_{1 2};
    join_gamma(_);
    tst3:= \gamma_{1 2 1 2} 
        + \gamma_{1 2} * \delta_{1 2} - \gamma_{1 1} * \delta_{2 2} 
        - \gamma_{2 2} * \delta_{1 1} + \gamma_{2 1} * \delta_{1 2} 
        + \delta_{1 2} * \delta_{1 2} - \delta_{1 1} * \delta_{2 2}
        - @(obj3);
    display(tst3)
    assert(tst3==0)
    print("Test 03 passed")

test03()
        
# # Test 4: keeping upper and lower indices 
# #
# @reset.
# {\mu,\nu,\rho,a,b,c,d}::Indices(vector, position=fixed).
# {\mu,\nu,\rho,a,b,c,d}::Integer(0..10).
# \Gamma{#}::GammaMatrix(metric=g).
# obj4:= \Gamma_{\mu c d} \Gamma^{\nu \rho a b c};
# @join!(%){expand};
# 
# 

# Indices and sub-indices (bug reported 5-Apr-2009)

def test04():
    __cdbkernel__ = create_scope()
    {a,b,c,d, e,f, g, h#}::Indices(group).
    {M, N, P, Q#}::Indices(flat).
    {M, N, P, Q#}::Integer(1..10).
    {I,J,K,L#}::Indices(orthogonal, parent=flat).
    {I,J,K,L#}::Integer(3..10).
    {\mu, \nu, \lambda, \sigma#}::Indices(worldvolume, parent=flat).
    {\mu, \nu, \lambda, \sigma#}::Integer(0..2).
    \delta{\mu \nu}::KroneckerDelta.
    \Gamma{#}::GammaMatrix(metric=\delta).
    obj1:=\Gamma_{I J K}\Gamma_{\mu};
    join_gamma(_)
    tst1:= \Gamma_{I J K \mu} + \Gamma_{I J} * \delta_{K \mu} - \Gamma_{I K} * \delta_{J \mu} + \Gamma_{J K} * \delta_{I \mu} - @(obj1);
    assert(tst1==0)
    print("Test 04a passed")
    obj2:=\Gamma_{\mu}\Gamma_{I J K};
    join_gamma(_)
    tst2:= \Gamma_{\mu I J K} + \Gamma_{J K} * \delta_{I \mu} - \Gamma_{J I} * \delta_{K \mu} + \Gamma_{K I} * \delta_{J \mu}
      - @(obj2);
    assert(tst2==0)
    print("Test 04b passed")

test04()
        
    # 
# # Test 5: multiple spinor lines
# #
# @reset.
# \gamma{#}::GammaMatrix(spacetime).
# \Gamma{#}::GammaMatrix(susy).
# {\psi,\lambda}::Spinor(spacetime, susy).
# obj5:= \psi \gamma \Gamma \lambda;
# @prodsort!(%);
# 


def test05():
    def post_process(ex):
        sort_product(ex)
        eliminate_kronecker(ex)
        canonicalise(ex)
        collect_terms(ex)
    
    {\mu, \nu, \rho, \sigma}::Indices(vector, position=fixed);
    {m, n, p, q}::Indices(vector,position=fixed);
    \partial{#}::PartialDerivative;
    {\psi, \theta}::Spinor(dimension=10, type=MajoranaWeyl);
    {\psi, \theta}::AntiCommuting;
    \bar{#}::DiracBar;
    \Gamma{#}::GammaMatrix(metric=\eta);
    ex:=\bar{\Gamma^{\mu}\Gamma_{\nu}\theta} \partial_{\rho}{X^{\nu}};
    join_gamma(ex);
    canonicalise(ex);

test05()

{\mu,\nu}::Indices(curved).
{a,b,c}::Indices(flat).
\gamma{#}::GammaMatrix(metric=g).
ex := \gamma_{\mu} \gamma_{a};
ex2:= \gamma_{a}\gamma_{\mu}\gamma_{\nu}\gamma_{b};
join_gamma(_);
ex := \gamma_{a} \gamma_{b};
join_gamma(_);    

{\alpha,\beta}::Indices(position=fixed);
\gamma{#}::Matrix;
\lambda::ImplicitIndex;
ex:=\lambda^{\alpha} (\gamma^{m})_{\alpha \beta};
combine(ex);
