fundamentally, is this a function to simplify symmetries that are obvious? such as derivative symmetries, i.e. a_,ji == a_,ij

or is this meant to dictate symmetries of non-derivative tensor values (but not derivatives)? i.e. g_ji,lk = g_ij,kl

or is this meant to dictate values anyhow anywhere? i.e. a_i,j == a_j,i

I'm leaning towards #1 and #2 but not #3

so use this for symmetries of derivatives and non-derivatives



SO THE TAKE-AWAY ...

1) swap variance with symbol.

2) assert the derivative type of the index match, error if they don't.

2.5) if all indexes have commas then error if any are upper (unless all are covariant derivatives)

3) allow an override for non-matching commas ... don't swap comma. still do swap variance.








simplifyAssertEq( a'_ji':symmetrizeIndexes(a,{1,2}), a'_ij')
${{{ a} _i} _j} = {{{ a} _i} _j}$
GOOD
time: 2.159000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy


TODO in the case of 3 this isn't used so often


simplifyAssertEq( a'_kji':symmetrizeIndexes(a,{1,2,3}), a'_ijk')
${{{{ a} _i} _j} _k} = {{{{ a} _i} _j} _k}$
GOOD
time: 1.808000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy

simplifyAssertEq( a'_jki':symmetrizeIndexes(a,{1,2,3}), a'_ijk')
${{{{ a} _i} _j} _k} = {{{{ a} _i} _j} _k}$
GOOD
time: 1.856000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy

simplifyAssertEq( a'_jik':symmetrizeIndexes(a,{1,2,3}), a'_ijk')
${{{{ a} _i} _j} _k} = {{{{ a} _i} _j} _k}$
GOOD
time: 1.594000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy


TODO make sure this works when?



maintain raise/lower


simplifyAssertEq( a'_j^i':symmetrizeIndexes(a,{1,2}), a'^i_j')
${{{ a} ^i} _j} = {{{ a} ^i} _j}$
GOOD
time: 1.981000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy


don't symmetrize a comma and a non-comma (should I restrict this?)


assertError(function() a'_j,i':symmetrizeIndexes(a,{1,2}) end)
nil
GOOD
time: 0.150000ms
stack: size: 0

    
    
    do allow with override
    
    

    simplifyAssertEq(a'_j,i':symmetrizeIndexes(a,{1,2},true), a'_i,j')
    ${{{ a} _i} _{,j}} = {{{ a} _i} _{,j}}$
    GOOD
    time: 0.960000ms
    stack: size: 7
    • Init
    • Prune
    • Expand
    • Prune
    • Factor
    • Prune
    • Tidy

    
    
    do symmetrize two commas
    
    

    simplifyAssertEq( a'_,ji':symmetrizeIndexes(a,{1,2}), a'_,ij')
    ${{{ a} _{,i}} _{,j}} = {{{ a} _{,i}} _{,j}}$
    GOOD
    time: 0.897000ms
    stack: size: 7
    • Init
    • Prune
    • Expand
    • Prune
    • Factor
    • Prune
    • Tidy

    simplifyAssertEq( a'_,kji':symmetrizeIndexes(a,{1,2,3}), a'_,ijk')
    ${{{{ a} _{,i}} _{,j}} _{,k}} = {{{{ a} _{,i}} _{,j}} _{,k}}$
    GOOD
    time: 1.026000ms
    stack: size: 7
    • Init
    • Prune
    • Expand
    • Prune
    • Factor
    • Prune
    • Tidy

    simplifyAssertEq( a'_,jki':symmetrizeIndexes(a,{1,2,3}), a'_,ijk')
    ${{{{ a} _{,i}} _{,j}} _{,k}} = {{{{ a} _{,i}} _{,j}} _{,k}}$
    GOOD
    time: 1.276000ms
    stack: size: 7
    • Init
    • Prune
    • Expand
    • Prune
    • Factor
    • Prune
    • Tidy

    simplifyAssertEq( a'_,jik':symmetrizeIndexes(a,{1,2,3}), a'_,ijk')
    ${{{{ a} _{,i}} _{,j}} _{,k}} = {{{{ a} _{,i}} _{,j}} _{,k}}$
    GOOD
    time: 1.541000ms
    stack: size: 7
    • Init
    • Prune
    • Expand
    • Prune
    • Factor
    • Prune
    • Tidy

    
    

    simplifyAssertEq( a'_ji,lk':symmetrizeIndexes(a,{1,2}):symmetrizeIndexes(a,{3,4}), a'_ij,kl')
    ${{{{{ a} _i} _j} _{,k}} _{,l}} = {{{{{ a} _i} _j} _{,k}} _{,l}}$
    GOOD
    time: 1.254000ms
    stack: size: 7
    • Init
    • Prune
    • Expand
    • Prune
    • Factor
    • Prune
    • Tidy

    assertError(function() a'_ji,lk':symmetrizeIndexes(a,{2,3}) end)
    nil
    GOOD
    time: 0.164000ms
    stack: size: 0

      simplifyAssertEq(a'_jl,ik':symmetrizeIndexes(a,{2,3},true), a'_ji,lk')
      ${{{{{ a} _j} _i} _{,l}} _{,k}} = {{{{{ a} _j} _i} _{,l}} _{,k}}$
      GOOD
      time: 1.173000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy

      
      
      if a_ij = a_ji
      
      
      then a^i_j = g^ik a_kj = g^ik a_jk = a_j^i
      
      
      and a^i_j,k = (g^im a_mj)_,k = g^im_,k a_mj + g^im a_mj,k = g^im_,k a_jm + g^im a_jm,k = (g^im a_jm)_,k = a_j^i_,k
      
      
      so even symmetries with non-matching variance that are wrapped in derivatives can be symmetrized
      
      

      simplifyAssertEq( a'_j^i_,k':symmetrizeIndexes(a,{1,2}), a'^i_j,k')
      ${{{{ a} ^i} _j} _{,k}} = {{{{ a} ^i} _j} _{,k}}$
      GOOD
      time: 1.168000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy

      simplifyAssertEq( a'_ji,k':symmetrizeIndexes(a,{1,2}), a'_ij,k')
      ${{{{ a} _i} _j} _{,k}} = {{{{ a} _i} _j} _{,k}}$
      GOOD
      time: 1.413000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy

      simplifyAssertEq( a'^ji_,k':symmetrizeIndexes(a,{1,2}), a'^ij_,k')
      ${{{{ a} ^i} ^j} _{,k}} = {{{{ a} ^i} ^j} _{,k}}$
      GOOD
      time: 1.137000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy

      
      
      same if the comma is raised? a_ij==a_ji <=> a_i^j,k==a^j_i^,k ?
      
      
      how about if multiple commas are upper? <=> a^i,jk == a^i,kj ?
      
      
      a^i,jk = (g^im a_m)^,jk = ((g^im a_m)_,n g^nj)_,p g^pk
      
      
      = ((g^im a_m)_,np g^nj + (g^im a_m)_,n g^nj_,p) g^pk
      
      
      = (g^im a_m)_,np g^pk g^nj + (g^im a_m)_,n g^nj_,p g^pk
      
      
      = (g^im_,n a_m + g^im a_m,n)_,p g^pk g^nj + (g^im_,n a_m + g^im a_m,n) g^nj_,p g^pk
      
      
      = g^im_,np g^pk g^nj a_m + g^im_,n a_m,p g^pk g^nj + g^im_,p a_m,n g^pk g^nj + g^im_,n a_m g^nj_,p g^pk + g^im a_m,n g^nj_,p g^pk + a_m,np g^im g^pk g^nj
      
      
      so it doesn't look like these match
      
      
      = g^im_,np g^pk g^nj a_m + g^im_,n a_m,p g^pk g^nj + g^im_,p a_m,n g^pk g^nj + g^im_,n a_m g^nk_,p g^pj + g^im a_m,n g^nk_,p g^pj + a_m,np g^im g^pk g^nj
      
      
      = a_m g^im_,np g^pj g^nk + g^im_,n a_m,p g^pj g^nk + g^im_,p a_m,n g^pj g^nk + g^im a_m,np g^pj g^nk + g^im_,n a_m g^nk_,p g^pj + g^im a_m,n g^nk_,p g^pj
      
      
      = a^i,kj
      
      
      this looks like a job for my CAS ... but it isn't looking like upper commas can be assumed to be symmetric
      
      
      so commas can only be symmetrized if they are all lowered
      
      

      simplifyAssertEq(a'_i,kj':symmetrizeIndexes(a,{2,3}), a'_i,jk')
      ${{{{ a} _i} _{,j}} _{,k}} = {{{{ a} _i} _{,j}} _{,k}}$
      GOOD
      time: 1.704000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy
      but if they are upper then cause an error
      
      

      assertError(function() a'_i^,jk':symmetrizeIndexes(a,{2,3}) end)
      nil
      GOOD
      time: 0.313000ms
      stack: size: 0
        unless explicitly overridden
        
        

        simplifyAssertEq(a'_i^,kj':symmetrizeIndexes(a,{2,3},true), a'_i^,jk')
        ${{{{ a} _i} ^{,j}} ^{,k}} = {{{{ a} _i} ^{,j}} ^{,k}}$
        GOOD
        time: 1.540000ms
        stack: size: 7
        • Init
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        
        
        if you symmetrize non-lower-matching that are encased in deriv indexes ... still fine. (even if the derivs are upper?)
        
        

        simplifyAssertEq( a'^j_i,kl':symmetrizeIndexes(a,{1,2}), a'_i^j_,kl')
        ${{{{{ a} _i} ^j} _{,k}} _{,l}} = {{{{{ a} _i} ^j} _{,k}} _{,l}}$
        GOOD
        time: 1.175000ms
        stack: size: 7
        • Init
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        
        
        TODO test for also sort any multiplied tensors?
        
        
        another thing symmetrizing can do ...
        
        
        g^kl (d_klj + d_jlk - d_ljk) symmetrize g {1,2}
        
        
        ... not only sort g^kl
        
        
        but also sort all indexes in all multiplied expressions which use 'k' or 'l'
        
        
        so this would become
        
        
        g^kl (d_klj + d_jkl - d_kjl)
        
        
        then another symmetrize d {2,3} gives us
        
        
        g^kl (d_kjl + d_jkl - d_kjl)
        
        
        g^kl d_jkl
        
        

        simplifyAssertEq( (g'^kl' * (d'_klj' + d'_jlk' - d'_ljk')):symmetrizeIndexes(g, {1,2}), g'^kl' * (d'_klj' + d'_jkl' - d'_kjl') )
        ${{{{{ g} ^k} ^l}} {{\left({{{{{{ d} _k} _l} _j} + {{{{ d} _j} _k} _l}}{-{{{{ d} _k} _j} _l}}}\right)}}} = {{{{{ g} ^k} ^l}} {{\left({{{{{{ d} _k} _l} _j} + {{{{ d} _j} _k} _l}}{-{{{{ d} _k} _j} _l}}}\right)}}}$
        GOOD
        time: 18.228000ms
        stack: size: 21
        • Init
        • unm:Prune:doubleNegative
        • +:Prune:flatten
        • Prune
        • *:Expand:apply
        • Expand
        • *:Prune:flatten
        • Prune
        • unm:Prune:doubleNegative
        • +:Prune:combineConstants
        • unm:Prune:doubleNegative
        • +:Prune:combineConstants
        • unm:Prune:doubleNegative
        • +:Prune:combineConstants
        • +:Factor:apply
        • Factor
        • Prune
        • Constant:Tidy:apply
        • *:Tidy:apply
        • *:Tidy:apply
        • Tidy

        simplifyAssertEq( (g'^kl' * (d'_klj' + d'_jlk' - d'_ljk')):symmetrizeIndexes(g, {1,2}):symmetrizeIndexes(d, {2,3}), g'^kl' * (d'_kjl' + d'_jkl' - d'_kjl') )
        ${{{{{ g} ^k} ^l}} {{\left({{{{{{ d} _k} _j} _l} + {{{{ d} _j} _k} _l}}{-{{{{ d} _k} _j} _l}}}\right)}}} = {{{{{ g} ^k} ^l}} {{\left({{{{{{ d} _k} _j} _l} + {{{{ d} _j} _k} _l}}{-{{{{ d} _k} _j} _l}}}\right)}}}$
        GOOD
        time: 7.466000ms
        stack: size: 12
        • Init
        • unm:Prune:doubleNegative
        • *:Prune:apply
        • +:Prune:combineConstants
        • +:Prune:flattenAddMul
        • +:Prune:flatten
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        simplifyAssertEq( (g'^kl' * (d'_klj' + d'_jlk' - d'_ljk')):symmetrizeIndexes(g, {1,2}):symmetrizeIndexes(d, {2,3})(), g'^kl' * d'_jkl' )
        ${{{{{ g} ^k} ^l}} {{{{{ d} _j} _k} _l}}} = {{{{{ g} ^k} ^l}} {{{{{ d} _j} _k} _l}}}$
        GOOD
        time: 5.030000ms
        stack: size: 7
        • Init
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        
        
        same with all-lower
        
        

        simplifyAssertEq( (g'_kl' * (d'^kl_j' + d'_j^lk' - d'^l_j^k')):symmetrizeIndexes(g, {1,2}), g'_kl' * (d'^kl_j' + d'_j^kl' - d'^k_j^l') )
        ${{{{{ g} _k} _l}} {{\left({{{{{{ d} ^k} ^l} _j} + {{{{ d} _j} ^k} ^l}}{-{{{{ d} ^k} _j} ^l}}}\right)}}} = {{{{{ g} _k} _l}} {{\left({{{{{{ d} ^k} ^l} _j} + {{{{ d} _j} ^k} ^l}}{-{{{{ d} ^k} _j} ^l}}}\right)}}}$
        GOOD
        time: 11.599000ms
        stack: size: 21
        • Init
        • unm:Prune:doubleNegative
        • +:Prune:flatten
        • Prune
        • *:Expand:apply
        • Expand
        • *:Prune:flatten
        • Prune
        • unm:Prune:doubleNegative
        • +:Prune:combineConstants
        • unm:Prune:doubleNegative
        • +:Prune:combineConstants
        • unm:Prune:doubleNegative
        • +:Prune:combineConstants
        • +:Factor:apply
        • Factor
        • Prune
        • Constant:Tidy:apply
        • *:Tidy:apply
        • *:Tidy:apply
        • Tidy

        simplifyAssertEq( (g'_kl' * (d'^kl_j' + d'_j^lk' - d'^l_j^k')):symmetrizeIndexes(g, {1,2}):symmetrizeIndexes(d, {2,3}), g'_kl' * (d'^k_j^l' + d'_j^kl' - d'^k_j^l') )
        ${{{{{ g} _k} _l}} {{\left({{{{{{ d} ^k} _j} ^l} + {{{{ d} _j} ^k} ^l}}{-{{{{ d} ^k} _j} ^l}}}\right)}}} = {{{{{ g} _k} _l}} {{\left({{{{{{ d} ^k} _j} ^l} + {{{{ d} _j} ^k} ^l}}{-{{{{ d} ^k} _j} ^l}}}\right)}}}$
        GOOD
        time: 7.206000ms
        stack: size: 12
        • Init
        • unm:Prune:doubleNegative
        • *:Prune:apply
        • +:Prune:combineConstants
        • +:Prune:flattenAddMul
        • +:Prune:flatten
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        simplifyAssertEq( (g'_kl' * (d'^kl_j' + d'_j^lk' - d'^l_j^k')):symmetrizeIndexes(g, {1,2}):symmetrizeIndexes(d, {2,3})(), g'_kl' * d'_j^kl' )
        ${{{{{ g} _k} _l}} {{{{{ d} _j} ^k} ^l}}} = {{{{{ g} _k} _l}} {{{{{ d} _j} ^k} ^l}}}$
        GOOD
        time: 3.368000ms
        stack: size: 7
        • Init
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        
        
        same with mixed upper/lower
        
        

        simplifyAssertEq( (delta'_k^l' * (d'^k_lj' + d'_jl^k' - d'_lj^k')):symmetrizeIndexes(delta, {1,2}), delta'_k^l' * (d'^k_lj' + d'_j^k_l' - d'^k_jl') )
        ${{{{{ δ} _k} ^l}} {{\left({{{{{{ d} ^k} _l} _j} + {{{{ d} _j} ^k} _l}}{-{{{{ d} ^k} _j} _l}}}\right)}}} = {{{{{ δ} _k} ^l}} {{\left({{{{{{ d} ^k} _l} _j} + {{{{ d} _j} ^k} _l}}{-{{{{ d} ^k} _j} _l}}}\right)}}}$
        GOOD
        time: 11.511000ms
        stack: size: 21
        • Init
        • unm:Prune:doubleNegative
        • +:Prune:flatten
        • Prune
        • *:Expand:apply
        • Expand
        • *:Prune:flatten
        • Prune
        • unm:Prune:doubleNegative
        • +:Prune:combineConstants
        • unm:Prune:doubleNegative
        • +:Prune:combineConstants
        • unm:Prune:doubleNegative
        • +:Prune:combineConstants
        • +:Factor:apply
        • Factor
        • Prune
        • Constant:Tidy:apply
        • *:Tidy:apply
        • *:Tidy:apply
        • Tidy

        simplifyAssertEq( (delta'_k^l' * (d'^k_lj' + d'_jl^k' - d'_lj^k')):symmetrizeIndexes(delta, {1,2}):symmetrizeIndexes(d, {2,3}), delta'_k^l' * (d'^k_jl' + d'_j^k_l' - d'^k_jl') )
        ${{{{{ δ} _k} ^l}} {{\left({{{{{{ d} ^k} _j} _l} + {{{{ d} _j} ^k} _l}}{-{{{{ d} ^k} _j} _l}}}\right)}}} = {{{{{ δ} _k} ^l}} {{\left({{{{{{ d} ^k} _j} _l} + {{{{ d} _j} ^k} _l}}{-{{{{ d} ^k} _j} _l}}}\right)}}}$
        GOOD
        time: 3.865000ms
        stack: size: 12
        • Init
        • unm:Prune:doubleNegative
        • *:Prune:apply
        • +:Prune:combineConstants
        • +:Prune:flattenAddMul
        • +:Prune:flatten
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        simplifyAssertEq( (delta'_k^l' * (d'^k_lj' + d'_jl^k' - d'_lj^k')):symmetrizeIndexes(delta, {1,2}):symmetrizeIndexes(d, {2,3})(), delta'_k^l' * d'_j^k_l' )
        ${{{{{ δ} _k} ^l}} {{{{{ d} _j} ^k} _l}}} = {{{{{ δ} _k} ^l}} {{{{{ d} _j} ^k} _l}}}$
        GOOD
        time: 2.752000ms
        stack: size: 7
        • Init
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        
        
        how about with commas? don't forget, you can't exchange comma positions, even if you override errors, because commas cannot precede non-comma indexes.
        
        
        in fact, I vote yes, because of exchaning labels of indexes. g^ab t_a,b = g^ab t_b,a regardless of any symmetry between t_a,b and t_b,a.
        
        
        assertError(function() (g'^kl' * (d'_kl,j' + d'_jl,k' - d'_lj,k')):symmetrizeIndexes(g, {1,2}) end)
        
        
        assertError(function() (g'^kl' * (d'_kl,j' + d'_jl,k' - d'_lj,k')):symmetrizeIndexes(g, {1,2}):symmetrizeIndexes(d, {2,3}) end)
        
        
        assertError(function() (g'^kl' * (d'_kl,j' + d'_jl,k' - d'_lj,k')):symmetrizeIndexes(g, {1,2}):symmetrizeIndexes(d, {2,3})() end)
        
        

        
        

        simplifyAssertEq( (g'^kl' * (d'_kl,j' + d'_jl,k' - d'_lj,k')):symmetrizeIndexes(g, {1,2}), g'^kl' * (d'_kl,j' + d'_jk,l' - d'_kj,l') )
        ${{{{{ g} ^k} ^l}} {{\left({{{{{{ d} _k} _l} _{,j}} + {{{{ d} _j} _k} _{,l}}}{-{{{{ d} _k} _j} _{,l}}}}\right)}}} = {{{{{ g} ^k} ^l}} {{\left({{{{{{ d} _k} _l} _{,j}} + {{{{ d} _j} _k} _{,l}}}{-{{{{ d} _k} _j} _{,l}}}}\right)}}}$
        GOOD
        time: 12.920000ms
        stack: size: 21
        • Init
        • unm:Prune:doubleNegative
        • +:Prune:flatten
        • Prune
        • *:Expand:apply
        • Expand
        • *:Prune:flatten
        • Prune
        • unm:Prune:doubleNegative
        • +:Prune:combineConstants
        • unm:Prune:doubleNegative
        • +:Prune:combineConstants
        • unm:Prune:doubleNegative
        • +:Prune:combineConstants
        • +:Factor:apply
        • Factor
        • Prune
        • Constant:Tidy:apply
        • *:Tidy:apply
        • *:Tidy:apply
        • Tidy

        simplifyAssertEq( (g'^kl' * (d'_kl,j' + d'_jl,k' - d'_lj,k')):symmetrizeIndexes(g, {1,2}):symmetrizeIndexes(d, {2,3}, true), g'^kl' * (d'_kj,l' + d'_jk,l' - d'_kj,l') )
        ${{{{{ g} ^k} ^l}} {{\left({{{{{{ d} _k} _j} _{,l}} + {{{{ d} _j} _k} _{,l}}}{-{{{{ d} _k} _j} _{,l}}}}\right)}}} = {{{{{ g} ^k} ^l}} {{\left({{{{{{ d} _k} _j} _{,l}} + {{{{ d} _j} _k} _{,l}}}{-{{{{ d} _k} _j} _{,l}}}}\right)}}}$
        GOOD
        time: 4.031000ms
        stack: size: 12
        • Init
        • unm:Prune:doubleNegative
        • *:Prune:apply
        • +:Prune:combineConstants
        • +:Prune:flattenAddMul
        • +:Prune:flatten
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        simplifyAssertEq( (g'^kl' * (d'_kl,j' + d'_jl,k' - d'_lj,k')):symmetrizeIndexes(g, {1,2}):symmetrizeIndexes(d, {2,3}, true)(), g'^kl' * d'_jk,l' )
        ${{{{{ g} ^k} ^l}} {{{{{ d} _j} _k} _{,l}}}} = {{{{{ g} ^k} ^l}} {{{{{ d} _j} _k} _{,l}}}}$
        GOOD
        time: 8.170000ms
        stack: size: 7
        • Init
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        
        
        this is working
        simplifyAssertEq( (d'^d_dc'):symmetrizeIndexes(d, {2,3}), d'^d_cd')
        ${{{{ d} ^d} _c} _d} = {{{{ d} ^d} _c} _d}$
        GOOD
        time: 1.906000ms
        stack: size: 7
        • Init
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy
        this is failing
        simplifyAssertEq( (a'^c' * d'^d_dc'):symmetrizeIndexes(d, {2,3}), a'^c' * d'^d_cd')
        ${{{{ a} ^c}} {{{{{ d} ^d} _c} _d}}} = {{{{ a} ^c}} {{{{{ d} ^d} _c} _d}}}$
        GOOD
        time: 1.759000ms
        stack: size: 7
        • Init
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        
        

        simplifyAssertEq( (g'_ab' * a'^bac'):symmetrizeIndexes(g, {1,2}), g'_ab' * a'^abc')
        ${{{{{ g} _a} _b}} {{{{{ a} ^a} ^b} ^c}}} = {{{{{ g} _a} _b}} {{{{{ a} ^a} ^b} ^c}}}$
        GOOD
        time: 1.490000ms
        stack: size: 7
        • Init
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        simplifyAssertEq( (g'_ab' * a'^bac' * g'_ef' * b'^feg' ):symmetrizeIndexes(g, {1,2}), g'_ab' * a'^abc' * g'_ef' * b'^efg')
        ${{{{{ g} _a} _b}} {{{{{ a} ^a} ^b} ^c}} {{{{ g} _e} _f}} {{{{{ b} ^e} ^f} ^g}}} = {{{{{ g} _a} _b}} {{{{{ a} ^a} ^b} ^c}} {{{{ g} _e} _f}} {{{{{ b} ^e} ^f} ^g}}}$
        GOOD
        time: 3.229000ms
        stack: size: 7
        • Init
        • Prune
        • Expand
        • Prune
        • Factor
        • Prune
        • Tidy

        
        
        can't symmetrize b_a,b without override
        assertError(function() ( g'^ab' * b'_a,b' ):symmetrizeIndexes(b, {1,2}) end)
        nil
        GOOD
        time: 0.252000ms
        stack: size: 0
          can't symmetrize b^a_,b without override
          assertError(function() ( b'^a_,b' ):symmetrizeIndexes(b, {1,2}) end)
          nil
          GOOD
          time: 0.080000ms
          stack: size: 0
            you can indirectly symmetrize b_a,b without override
            simplifyAssertEq( ( g'^ba' * b'_a,b' ):symmetrizeIndexes(g, {1,2}), g'^ab' * b'_a,b' )
            ${{{{{ g} ^a} ^b}} {{{{ b} _a} _{,b}}}} = {{{{{ g} ^a} ^b}} {{{{ b} _a} _{,b}}}}$
            GOOD
            time: 2.182000ms
            stack: size: 7
            • Init
            • Prune
            • Expand
            • Prune
            • Factor
            • Prune
            • Tidy

            
            
            fine
            simplifyAssertEq(( d'^ab' * b'_b,a' ):symmetrizeIndexes(d, {1,2}), d'^ab' * b'_a,b')
            ${{{{{ d} ^a} ^b}} {{{{ b} _a} _{,b}}}} = {{{{{ d} ^a} ^b}} {{{{ b} _a} _{,b}}}}$
            GOOD
            time: 1.346000ms
            stack: size: 7
            • Init
            • Prune
            • Expand
            • Prune
            • Factor
            • Prune
            • Tidy
            fine
            simplifyAssertEq(( d'_ab' * b'^b,a' ):symmetrizeIndexes(d, {1,2}), d'_ab' * b'^a,b')
            ${{{{{ d} _a} _b}} {{{{ b} ^a} ^{,b}}}} = {{{{{ d} _a} _b}} {{{{ b} ^a} ^{,b}}}}$
            GOOD
            time: 1.631000ms
            stack: size: 7
            • Init
            • Prune
            • Expand
            • Prune
            • Factor
            • Prune
            • Tidy
            you can't indirectly symmetrize b^a_,b without override ... but because it's indirect, don't cause an error, just skip it.
            simplifyAssertEq(( d'^a_b' * b'^b_,a' ):symmetrizeIndexes(d, {1,2}), d'^a_b' * b'^b_,a')
            ${{{{{ d} ^a} _b}} {{{{ b} ^b} _{,a}}}} = {{{{{ d} ^a} _b}} {{{{ b} ^b} _{,a}}}}$
            GOOD
            time: 3.280000ms
            stack: size: 7
            • Init
            • Prune
            • Expand
            • Prune
            • Factor
            • Prune
            • Tidy
            if you override, then fine , but maybe care about the commas and upper/lower a bit more? maybe not, it's overridden anyways
            simplifyAssertEq(( d'^a_b' * b'^b_,a' ):symmetrizeIndexes(d, {1,2}, true), d'^a_b' * b'_a^,b')
            ${{{{{ d} ^a} _b}} {{{{ b} _a} ^{,b}}}} = {{{{{ d} ^a} _b}} {{{{ b} _a} ^{,b}}}}$
            GOOD
            time: 1.351000ms
            stack: size: 7
            • Init
            • Prune
            • Expand
            • Prune
            • Factor
            • Prune
            • Tidy