if there are no indexes in the expr or in find then it falls back on 'replace'
simplifyAssertEq( a:replaceIndex(a, b), b )
${b} = {b}$
GOOD
time: 0.626000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy

variance must match in order for the replace to work
simplifyAssertEq( a'_a':replaceIndex(a'^u', b'^u'), a'_a' )
${{ a} _a} = {{ a} _a}$
GOOD
time: 2.817000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy

simplifyAssertEq( a'^a':replaceIndex(a'^b', b'^b'), b'^a' )
${{ b} ^a} = {{ b} ^a}$
GOOD
time: 1.769000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy

simplifyAssertEq( a'^a':replaceIndex(a'^b', b'^b' + c'^b'), b'^a' + c'^a' )
${{{ b} ^a} + {{ c} ^a}} = {{{ b} ^a} + {{ c} ^a}}$
GOOD
time: 9.792000ms
stack: size: 8
  • Init
  • Prune
  • Expand
  • Prune
  • +:Factor:apply
  • Factor
  • Prune
  • Tidy
the sum indexes won't use the same symbol, because the symbols are not preserved and instead chosen among unused symbols in the result expression
simplifyAssertEq( a'^a':replaceIndex(a'^b', b'^bc' * c'_c'), b'^ab' * c'_b' )
${{{{{ b} ^a} ^b}} {{{ c} _b}}} = {{{{{ b} ^a} ^b}} {{{ c} _b}}}$
GOOD
time: 6.329000ms
stack: size: 8
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • *:Tidy:apply
  • Tidy

simplifyAssertEq( a'^a':replaceIndex(a'^b', b'^b' + c'^bc' * d'_c'), b'^a' + c'^ab' * d'_b' )
${{{ b} ^a} + {{{{{ c} ^a} ^b}} {{{ d} _b}}}} = {{{ b} ^a} + {{{{{ c} ^a} ^b}} {{{ d} _b}}}}$
GOOD
time: 12.475000ms
stack: size: 9
  • Init
  • Prune
  • Expand
  • Prune
  • +:Factor:apply
  • Factor
  • Prune
  • *:Tidy:apply
  • Tidy


simplifyAssertEq( a'_ab':replaceIndex(a'_uv', b'_uv'), b'_ab' )
${{{ b} _a} _b} = {{{ b} _a} _b}$
GOOD
time: 2.113000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy

simplifyAssertEq( a'_ab':replaceIndex(a'_uv', b'_vu'), b'_ba' )
${{{ b} _b} _a} = {{{ b} _b} _a}$
GOOD
time: 2.985000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy

simplifyAssertEq( a'_ba':replaceIndex(a'_uv', b'_vu'), b'_ab' )
${{{ b} _a} _b} = {{{ b} _a} _b}$
GOOD
time: 2.103000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy

simplifyAssertEq( a'_ab':replaceIndex(a'_vu', b'_uv'), b'_ba' )
${{{ b} _b} _a} = {{{ b} _b} _a}$
GOOD
time: 2.865000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy

simplifyAssertEq( a'_ba':replaceIndex(a'_vu', b'_uv'), b'_ab' )
${{{ b} _a} _b} = {{{ b} _a} _b}$
GOOD
time: 3.456000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy



simplifyAssertEq( (g'^am' * c'_mbc'):replaceIndex( g'^am' * c'_mbc', c'^a_bc' ), c'^a_bc')
${{{{ c} ^a} _b} _c} = {{{{ c} ^a} _b} _c}$
GOOD
time: 5.158000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy
mapping the sum index
simplifyAssertEq( (g'^am' * c'_mbc'):replaceIndex( g'^an' * c'_nbc', c'^a_bc' ), c'^a_bc')
${{{{ c} ^a} _b} _c} = {{{{ c} ^a} _b} _c}$
GOOD
time: 4.715000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy
mapping the fixed indexes
simplifyAssertEq( (g'^am' * c'_mbc'):replaceIndex( g'^im' * c'_mjk', c'^i_jk' ), c'^a_bc')
${{{{ c} ^a} _b} _c} = {{{{ c} ^a} _b} _c}$
GOOD
time: 5.965000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy
mapping both
simplifyAssertEq( (g'^am' * c'_mbc'):replaceIndex( g'^id' * c'_djk', c'^i_jk' ), c'^a_bc')
${{{{ c} ^a} _b} _c} = {{{{ c} ^a} _b} _c}$
GOOD
time: 2.905000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy


simplifyAssertEq( (a'_a' + b'_ab' * c'^b'):replaceIndex(a'_u', b'_u'), b'_a' + b'_ab' * c'^b' )
${{{ b} _a} + {{{{{ b} _a} _b}} {{{ c} ^b}}}} = {{{ b} _a} + {{{{{ b} _a} _b}} {{{ c} ^b}}}}$
GOOD
time: 8.138000ms
stack: size: 9
  • Init
  • Prune
  • Expand
  • Prune
  • +:Factor:apply
  • Factor
  • Prune
  • *:Tidy:apply
  • Tidy

TODO this should preserve the order of b_ab -> c_ab
simplifyAssertEq( (a'_a' + b'_ab' * c'^b'):replaceIndex(b'_uv', c'_uv'), a'_a' + c'_ab' * c'^b' )
${{{ a} _a} + {{{{{ c} _a} _b}} {{{ c} ^b}}}} = {{{ a} _a} + {{{{{ c} _a} _b}} {{{ c} ^b}}}}$
GOOD
time: 7.282000ms
stack: size: 9
  • Init
  • Prune
  • Expand
  • Prune
  • +:Factor:apply
  • Factor
  • Prune
  • *:Tidy:apply
  • Tidy

TODO this should preserve the order of b_ab -> d_ab
simplifyAssertEq( (a'_a' + b'_ab' * c'^b'):replaceIndex(b'_uv', d'_uv'), a'_a' + d'_ab' * c'^b' )
${{{ a} _a} + {{{{{ d} _a} _b}} {{{ c} ^b}}}} = {{{ a} _a} + {{{{{ d} _a} _b}} {{{ c} ^b}}}}$
GOOD
time: 13.205000ms
stack: size: 9
  • Init
  • Prune
  • Expand
  • Prune
  • +:Factor:apply
  • Factor
  • Prune
  • *:Tidy:apply
  • Tidy


simplifyAssertEq( a'^a_a':replaceIndex(a'^a_a', b'^a_a'), b'^a_a')
${{{ b} ^a} _a} = {{{ b} ^a} _a}$
GOOD
time: 2.739000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy

simplifyAssertEq( a'^a_a':replaceIndex(a'^u_u', b'^u_u'), b'^a_a')
${{{ b} ^a} _a} = {{{ b} ^a} _a}$
GOOD
time: 1.946000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy


simplifyAssertEq( (a'^a_a' * a'^b_b'):replaceIndex(a'^u_u', b'^u_u'), b'^a_a' * b'^b_b')
${{{{{ b} ^a} _a}} {{{{ b} ^b} _b}}} = {{{{{ b} ^a} _a}} {{{{ b} ^b} _b}}}$
GOOD
time: 9.532000ms
stack: size: 8
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • *:Tidy:apply
  • Tidy


simplifyAssertEq( a'^a_ab':replaceIndex(a'^a_ab', b'_b'), b'_b' )
${{ b} _b} = {{ b} _b}$
GOOD
time: 4.378000ms
stack: size: 7
  • Init
  • Prune
  • Expand
  • Prune
  • Factor
  • Prune
  • Tidy

simplifyAssertEq( a'^a_ab':replaceIndex(a'^a_ab', b'_b' + c'_a^a_b'), b'_b' + c'_a^a_b' )
${{{ b} _b} + {{{{ c} _a} ^a} _b}} = {{{ b} _b} + {{{{ c} _a} ^a} _b}}$
GOOD
time: 7.022000ms
stack: size: 8
  • Init
  • Prune
  • Expand
  • Prune
  • +:Factor:apply
  • Factor
  • Prune
  • Tidy

hmm, how to account for this? if the fixed indexes don't match then I still want it to fall back on a plain replace()

simplifyAssertEq( a'_t':replaceIndex(a'_t', b), b)
${b} = {b}$
GOOD
time: 0.600000ms
stack: size: 0

    simplifyAssertEq( a'_t':replaceIndex(a'_t', b'_u'), b'_u')
    ${{ b} _u} = {{ b} _u}$
    GOOD
    time: 1.286000ms
    stack: size: 7
    • Init
    • Prune
    • Expand
    • Prune
    • Factor
    • Prune
    • Tidy
    but in the event of a regular replace, I still want it to not collide sum indexes

    simplifyAssertEq( (a'_t' * b'^a_a'):replaceIndex(a'_t', c'_u' * d'^a_a'), c'_u' * b'^a_a' * d'^b_b')
    ${{{{{{ c} _u}} {{{{ d} ^b} _b}}}} {{{{ b} ^a} _a}}} = {{{{ c} _u}} {{{{ b} ^a} _a}} {{{{ d} ^b} _b}}}$
    GOOD
    time: 7.473000ms
    stack: size: 8
    • Init
    • Prune
    • Expand
    • Prune
    • Factor
    • Prune
    • *:Tidy:apply
    • Tidy
    what does this mean? the fixed indexes shouldn't have to match ...
    if they don't match then assume they are not correlated between the 'find' and 'replace'


    simplifyAssertEq( (a'_ij' + c'_,t' * b'_ij'):replaceIndex( c'_,t', c * d'^i_i' ), a'_ij' + c * d'^a_a' * b'_ij' )
    ${{{{ a} _i} _j} + {{{{{c}} {{{{ d} ^a} _a}}}} {{{{ b} _i} _j}}}} = {{{{ a} _i} _j} + {{{c}} {{{{ d} ^a} _a}} {{{{ b} _i} _j}}}}$
    GOOD
    time: 6.653000ms
    stack: size: 9
    • Init
    • Prune
    • Expand
    • Prune
    • +:Factor:apply
    • Factor
    • Prune
    • *:Tidy:apply
    • Tidy

    simplifyAssertEq( (a'_ab' + c'_,t' * b'_ab'):replaceIndex( c'_,t', c * d'^a_a' ), a'_ab' + c * d'^c_c' * b'_ab' )
    ${{{{ a} _a} _b} + {{{{{c}} {{{{ d} ^c} _c}}}} {{{{ b} _a} _b}}}} = {{{{ a} _a} _b} + {{{c}} {{{{ d} ^c} _c}} {{{{ b} _a} _b}}}}$
    GOOD
    time: 9.691000ms
    stack: size: 9
    • Init
    • Prune
    • Expand
    • Prune
    • +:Factor:apply
    • Factor
    • Prune
    • *:Tidy:apply
    • Tidy

    TODO so it looks like, when the replace expression has sum terms *AND* it is an Expression instead of just a TensorRef
    that's when the sum indexes aren't replaced correctly

    simplifyAssertEq( (a'_ij' + c'_,t' * b'_ij'):replaceIndex( c'_,t', c * d'^i_i' + e'^i_i' ), a'_ij' + (c * d'^a_a' + e'^a_a') * b'_ij' )
    ${{{{ a} _i} _j} + {{{\left({{{{c}} {{{{ d} ^a} _a}}} + {{{ e} ^a} _a}}\right)}} {{{{ b} _i} _j}}}} = {{{{ a} _i} _j} + {{{\left({{{{c}} {{{{ d} ^a} _a}}} + {{{ e} ^a} _a}}\right)}} {{{{ b} _i} _j}}}}$
    GOOD
    time: 18.099000ms
    stack: size: 18
    • Init
    • Prune
    • *:Expand:apply
    • Expand
    • *:Prune:flatten
    • +:Prune:flatten
    • Prune
    • +:Factor:apply
    • Factor
    • Prune
    • Expand
    • Prune
    • +:Factor:apply
    • Factor
    • Prune
    • *:Tidy:apply
    • *:Tidy:apply
    • Tidy


    printbr( g'_ij,t':eq(d * (d * b'^k_,i' * g'_kj' + d * b'^k_,j' * g'_ki' + d * b'^k' * c'_ijk' + d * b'^k' * c'_jik' + 2 * d'_,t' * g'_ij' - 2 * d * a * e'_ij') ):replaceIndex( d'_,t', frac(1,3) * (3 * d'_,i' * b'^i' - d * b'^i_,i' - frac(1,2) * d * b'^i' * g'_,i' / g + e * d * a) ) )
    ${{{{ g} _i} _j} _{,t}} = {{{d}} {{\left({{{{d}} {{{{ b} ^k} _{,i}}} {{{{ g} _k} _j}}} + {{{d}} {{{{ b} ^k} _{,j}}} {{{{ g} _k} _i}}} + {{{d}} {{{ b} ^k}} {{{{{ c} _i} _j} _k}}} + {{{d}} {{{ b} ^k}} {{{{{ c} _j} _i} _k}}} + {{{2}} {{{{\frac{1}{3}}} {{\left({{{{3}} {{{ d} _{,a}}} {{{ b} ^a}}}{-{{{d}} {{{{ b} ^a} _{,a}}}}}{-{{\frac{1}{g}} {{{\frac{1}{2}}} {{d}} {{{ b} ^a}} {{{ g} _{,a}}}}}} + {{{e}} {{d}} {{a}}}}\right)}}}} {{{{ g} _i} _j}}}{-{{{2}} {{d}} {{a}} {{{{ e} _i} _j}}}}}\right)}}}$
    GOOD
    time: 9.369000ms
    stack: size: 0

      only if extra indexes match. in this case, extra is 'k'.

      simplifyAssertEq( (g'_ab,t' * g'_cd,e'):replaceIndex(g'_ij,k', c'_ij'), g'_ab,t' * g'_cd,e')
      ${{{{{{ g} _a} _b} _{,t}}} {{{{{ g} _c} _d} _{,e}}}} = {{{{{{ g} _a} _b} _{,t}}} {{{{{ g} _c} _d} _{,e}}}}$
      GOOD
      time: 5.907000ms
      stack: size: 8
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • *:Tidy:apply
      • Tidy

      simplifyAssertEq( (g'_ab,t' * g'_cd,e'):replaceIndex(g'_ij,t', c'_ij'), c'_ab' * g'_cd,e')
      ${{{{{ c} _a} _b}} {{{{{ g} _c} _d} _{,e}}}} = {{{{{ c} _a} _b}} {{{{{ g} _c} _d} _{,e}}}}$
      GOOD
      time: 4.431000ms
      stack: size: 8
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • *:Tidy:apply
      • Tidy

      TODO make sure summed indexes aren't matched incorreclty
      replaceIndex with more general indexes should work
      simplifyAssertEq( a'^a_a':replaceIndex( a'^a_b', b'^a_b'), b'^a_a')
      ${{{ b} ^a} _a} = {{{ b} ^a} _a}$
      GOOD
      time: 1.417000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy
      replaceIndex with more specific (summed) indexes shouldn't
      simplifyAssertEq( a'^a_b':replaceIndex( a'^a_a', b'^a_a'), a'^a_b')
      ${{{ a} ^a} _b} = {{{ a} ^a} _b}$
      GOOD
      time: 1.417000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy
      and the two should be discernable
      simplifyAssertEq( (a'^a_b' * a'^c_c'):replaceIndex( a'^a_a', b'^a_a'), (a'^a_b' * b'^c_c'))
      ${{{{{ a} ^a} _b}} {{{{ b} ^c} _c}}} = {{{{{ a} ^a} _b}} {{{{ b} ^c} _c}}}$
      GOOD
      time: 3.761000ms
      stack: size: 8
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • *:Tidy:apply
      • Tidy
      same but replace with scalars
      in this case, a^a_b's indexes are considered extra since they are not in b as well, so they will be exactly matched in the expression. since no a^a_b exists, it will not match and not replace.
      simplifyAssertEq( a'^a_a':replaceIndex( a'^a_b', b), a'^a_a')
      ${{{ a} ^a} _a} = {{{ a} ^a} _a}$
      GOOD
      time: 1.418000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy

      simplifyAssertEq( a'^a_b':replaceIndex( a'^a_a', b), a'^a_b')
      ${{{ a} ^a} _b} = {{{ a} ^a} _b}$
      GOOD
      time: 1.856000ms
      stack: size: 7
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • Tidy

      simplifyAssertEq( (a'^a_b' * a'^c_c'):replaceIndex( a'^a_a', b), (a'^a_b' * b))
      ${{{{{ a} ^a} _b}} {{b}}} = {{{{{ a} ^a} _b}} {{b}}}$
      GOOD
      time: 2.363000ms
      stack: size: 8
      • Init
      • Prune
      • Expand
      • Prune
      • Factor
      • Prune
      • *:Tidy:apply
      • Tidy


      printbr( d'_,t':eq( frac(1,6) * ( d * ( 2 * e * a - b'^k_,i' * g'^ij' * g'_jk' - b'^k_,j' * g'_ik' * g'^ij' - b'^k' * g'^ij' * g'_ij,k' ) )):replaceIndex( g'_ij', c'_ij' / d^2 ) )
      ${{ d} _{,t}} = {{{\frac{1}{6}}} {{d}} {{\left({{{{2}} {{e}} {{a}}}{-{{{{{ b} ^k} _{,i}}} {{{{ g} ^i} ^j}} {{\frac{{{ c} _j} _k}{{d}^{2}}}}}}{-{{{{{ b} ^k} _{,j}}} {{\frac{{{ c} _i} _k}{{d}^{2}}}} {{{{ g} ^i} ^j}}}}{-{{{{ b} ^k}} {{{{ g} ^i} ^j}} {{{{{ g} _i} _j} _{,k}}}}}}\right)}}}$
      GOOD
      time: 6.624000ms
      stack: size: 0

        printbr( d'_,t':eq( 2 * e * a - b'^k_,i' * g'^ij' * g'_jk' - b'^k_,j' * g'_ik' * g'^ij' - b'^k' * g'^ij' * g'_ij,k' ):replaceIndex( g'_ij', c'_ij' / d^2 ) )
        ${{ d} _{,t}} = {{{{{{2}} {{e}} {{a}}}{-{{{{{ b} ^k} _{,i}}} {{{{ g} ^i} ^j}} {{\frac{{{ c} _j} _k}{{d}^{2}}}}}}}{-{{{{{ b} ^k} _{,j}}} {{\frac{{{ c} _i} _k}{{d}^{2}}}} {{{{ g} ^i} ^j}}}}}{-{{{{ b} ^k}} {{{{ g} ^i} ^j}} {{{{{ g} _i} _j} _{,k}}}}}}$
        GOOD
        time: 4.559000ms
        stack: size: 0


          simplifyAssertEq( d'_,t':eq( b'^k_,i' * g'^ij' * g'_jk' ):replaceIndex( g'_ij', c'_ij' / d^2 ), d'_,t':eq(b'^k_,i' * g'^ij' * c'_jk' / d^2) )
          ${{{ d} _{,t}} = {{{{{ b} ^k} _{,i}}} {{{{ g} ^i} ^j}} {{\frac{{{ c} _j} _k}{{d}^{2}}}}}} = {{{ d} _{,t}} = {\frac{{{{{ b} ^k} _{,i}}} {{{{ g} ^i} ^j}} {{{{ c} _j} _k}}}{{d}^{2}}}}$
          GOOD
          time: 28.092000ms
          stack: size: 22
          • Init
          • Prune
          • ^:Expand:integerPower
          • Expand
          • +:Prune:combineConstants
          • *:Prune:combinePows
          • Prune
          • ^:ExpandPolynomial:apply
          • +:Prune:combineConstants
          • *:Prune:combinePows
          • /:Factor:polydiv
          • Factor
          • *:Prune:flatten
          • *:Prune:apply
          • unm:Prune:doubleNegative
          • +:Prune:combineConstants
          • ^:Prune:xToTheZero
          • /:Prune:divToPowSub
          • *:Prune:factorDenominators
          • Prune
          • *:Tidy:apply
          • Tidy


          simplifyAssertEq( d'_,t':eq( g'^jk' * g'_jk' ):replaceIndex( g'_ij', c'_ij' / d^2 ), d'_,t':eq( g'^jk' * c'_jk' / d^2) )
          ${{{ d} _{,t}} = {{{{{ g} ^j} ^k}} {{\frac{{{ c} _j} _k}{{d}^{2}}}}}} = {{{ d} _{,t}} = {\frac{{{{{ g} ^j} ^k}} {{{{ c} _j} _k}}}{{d}^{2}}}}$
          GOOD
          time: 14.588000ms
          stack: size: 22
          • Init
          • Prune
          • ^:Expand:integerPower
          • Expand
          • +:Prune:combineConstants
          • *:Prune:combinePows
          • Prune
          • ^:ExpandPolynomial:apply
          • +:Prune:combineConstants
          • *:Prune:combinePows
          • /:Factor:polydiv
          • Factor
          • *:Prune:flatten
          • *:Prune:apply
          • unm:Prune:doubleNegative
          • +:Prune:combineConstants
          • ^:Prune:xToTheZero
          • /:Prune:divToPowSub
          • *:Prune:factorDenominators
          • Prune
          • *:Tidy:apply
          • Tidy

          does fixed in the find/repl to map into sums in the expr

          simplifyAssertEq( a'^i_i':replaceIndex(a'^i_j', b'^i_j'), b'^i_i')
          ${{{ b} ^i} _i} = {{{ b} ^i} _i}$
          GOOD
          time: 1.279000ms
          stack: size: 7
          • Init
          • Prune
          • Expand
          • Prune
          • Factor
          • Prune
          • Tidy

          why do neither of these work? because if there are *only* sum-indexes won't match, however if there are extra indexes then it will match. why do we have this constraint again?
          internal sum indexes do seem to work in replaceIndex, like A^a_a, but externally shared between two tensors don't: A^a * A_a ... why distinguish?

          print( (a'^a' * a'_a'):replaceIndex(a'^a' * a'_a', 2))
          ${{{ a} ^a}} {{{ a} _a}}$ GOOD time: 0.764000ms
          stack: size: 0

            print( (a'^a' * a'_a'):replaceIndex(a'^a' * a'_a', b'^a' * b'_a'))
            ${{{ a} ^a}} {{{ a} _a}}$ GOOD time: 1.268000ms
            stack: size: 0

              print( (c'_b' * a'^a' * a'_a'):replaceIndex(c'_b' * a'^a' * a'_a', 2))
              ${{{ c} _b}} {{{ a} ^a}} {{{ a} _a}}$ GOOD time: 1.768000ms
              stack: size: 0

                and what about when find/replace has a partial number of fixed indexes
                what should this produce? Technically it is invalid match, since the from and to don't have matching fixed indexes. So... assert error?
                assertError(function() return (a'_a' + b'_ab' * c'^b'):replaceIndex(b'_uv', c'_bv') end )
                ${{ a} _a} + {{{{{ b} _a} _b}} {{{ c} ^b}}}$
                BAD
                /home/chris/Projects/lua/symmath/tests/unit/unit.lua:206: expected an error, but found none
                stack traceback:
                /home/chris/Projects/lua/symmath/tests/unit/unit.lua:246: in function
                [C]: in function 'assert'
                /home/chris/Projects/lua/symmath/tests/unit/unit.lua:206: in function 'assertError'
                [string "assertError(function() return (a'_a' + b'_ab'..."]:1: in main chunk
                /home/chris/Projects/lua/symmath/tests/unit/unit.lua:238: in function
                [C]: in function 'xpcall'
                /home/chris/Projects/lua/symmath/tests/unit/unit.lua:237: in function 'exec'
                replaceIndex.lua:136: in function 'cb'
                /home/chris/Projects/lua/ext/timer.lua:54: in function 'timer'
                replaceIndex.lua:6: in main chunk
                [C]: at 0x55b5c2a9a3e0
                time: 0.633000ms
                stack: size: 0