# Why is TensorExpand so slow for vector operations?

I would like to expand the following tensor expression:

$Assumptions = {(a1 | b | c | d | e | f | g | h) ∈ Vectors[3, Reals], (m | Ε1 | Ε2) ∈ Reals}; exp=-32 I m^2 a1.(-b + d)\[Cross](-b + f) (b + c).(b + e) + 16 I m Ε2 a1.(b + e) (b + c).(-b + d)\[Cross](-b + f) + 16 I Ε1 Ε2 a1.(b + e) (b + c).(-b + d)\[Cross](-b + f) - 16 I m Ε2 (b + c).a1\[Cross](-b + f) (-b + d).(b + e) - 16 I Ε1 Ε2 (b + c).a1\[Cross](-b + f) (-b + d).(b + e) + 32 I m^2 a1.(b + c)\[Cross](b + e) (-b + d).(-b + f) + 32 I m Ε1 a1.(b + c)\[Cross](b + e) (-b + d).(-b + f) - 32 I m Ε2 (b + c).a1\[Cross](b + e) (-b + d).(-b + f) - 32 I Ε1 Ε2 (b + c).a1\[Cross](b + e) (-b + d).(-b + f) + 16 I m Ε2 (b + c).(-b + f) (-b + d).a1\[Cross](b + e) + 16 I Ε1 Ε2 (b + c).(-b + f) (-b + d).a1\[Cross](b + e) + 16 I Ε1 Ε2 (b + c).(b + e) (-b + d).a1\[Cross](-b + f) + 16 I m Ε2 a1.(b + c) (-b + d).(b + e)\[Cross](-b + f) + 16 I Ε1 Ε2 a1.(b + c) (-b + d).(b + e)\[Cross](-b + f) + 16 I m Ε2 (b + c).a1\[Cross](-b + d) (b + e).(-b + f) + 16 I Ε1 Ε2 (b + c).a1\[Cross](-b + d) (b + e).(-b + f) + 16 I m Ε2 (b + c).(-b + d) (b + e).a1\[Cross](-b + f) + 16 I Ε1 Ε2 (b + c).(-b + d) (b + e).a1\[Cross](-b + f) - 16 I a1.(g + h) (b + c).(b + e) (-g + h).(-b + d)\[Cross](-b + f) - 16 I a1.(-g + h)\[Cross](-b + f) (-b + d).(b + e) (g + h).(b + c) - 32 I a1.(-g + h)\[Cross](b + e) (-b + d).(-b + f) (g + h).(b + c) + 32 I a1.(-g + h) (-b + d).(b + e)\[Cross](-b + f) (g + h).(b + c) + 16 I a1.(-g + h)\[Cross](-b + d) (b + e).(-b + f) (g + h).(b + c) + 16 I a1.(-b + d)\[Cross](-b + f) (-g + h).(b + e) (g + h).(b + c) - 16 I a1.(b + e) (-g + h).(-b + d)\[Cross](-b + f) (g + h).(b + c) + 16 I a1.(-g + h)\[Cross](-b + f) (b + c).(b + e) (g + h).(-b + d) + 16 I a1.(-g + h)\[Cross](-b + f) (b + c).(-b + d) (g + h).(b + e) - 16 I a1.(-g + h)\[Cross](-b + d) (b + c).(-b + f) (g + h).(b + e) + 32 I a1.(-g + h) (b + c).(-b + d)\[Cross](-b + f) (g + h).(b + e) + 32 I a1.(-g + h)\[Cross](b + c) (-b + d).(-b + f) (g + h).(b + e) - 16 I a1.(-b + d)\[Cross](-b + f) (-g + h).(b + c) (g + h).(b + e) + 16 I a1.(b + c) (-g + h).(-b + d)\[Cross](-b + f) (g + h).(b + e) - 16 I a1.(-g + h)\[Cross](-b + d) (b + c).(b + e) (g + h).(-b + f) - 16 I a1.(-b + d)\[Cross](-b + f) (b + c).(b + e) (Ε1 Ε2 - (g + h).(-g + h)); TensorExpand[exp]  However, it is really slow in my laptop. It takes over 12 hours. I think even if I do it manually, it could be faster. Does anyone know the reason? ## 2 Answers I also don't know the reason for the poor performance of TensorExpand, but as a possible workaround I may suggest using FeynCalc. The package has its roots in the field of the High Energy Physics, that is, it is not a toolbox for tensor algebra like xAct and company. Yet, the current development version already has a built-in support for 3-vectors, which was added there to accomodate for nonrelativistic field theories. After having installed the development version according to the wiki via Import["https://raw.githubusercontent.com/FeynCalc/feyncalc/master/install.m"] InstallFeynCalc[InstallFeynCalcDevelopmentVersion -> True]  we can do the following vecs = {a1, b, c, d, e, f, g, h}; expTmp = (exp /. Dot -> dot /. Cross -> cross /. { dot[x_, cross[y_, z_]] /; SubsetQ[vecs, Variables[{x, y, z}]] :> CLC[][x, y, z], dot[x_, y_] /; SubsetQ[vecs, Variables[{x, y}]] :> CSP[x, y] }) // ExpandScalarProduct[#, EpsEvaluate -> True] & // FCE  Here I converted your original expression into the FeynCalc notation using CLC (a shortcut for the Cartesian Levi-Civita tensor) and CSP (a shortcut for the Cartesian scalar product). Mathematically CLC[][a,b,c] corresponds to$\varepsilon^{ijk} a^i b^j c^k$, while CSP[a,b] stands for$a^i b^i$. The explicit Cartesian indices are suppressed for technical reasons, to avoid the expensive canonicalization. However, you can also define a standalone$\varepsilon^{ijk}$via CLC[i,j,k] and 3-vector$a^i\$ as CV[a,i]. ExpandScalarProduct is FeynCalc function for expanding scalar product, while FCE converts the result from the internal notation used by the package (FeynCalcInternal) to the more concise external notation (FeynCalcExternal).

Then we can convert the result back into your original notation via

res = expTmp /. {
CSP[x_, y_] /; SubsetQ[vecs, Variables[{x, y}]] :> dot[x, y],
CLC[][x_, y_, z_] /; SubsetQ[vecs, Variables[{x, y, z}]] :>
dot[x, cross[y, z]]
} /. cross -> Cross /. dot -> Dot


which yields

(16*I)*m*\[CapitalEpsilon]2*(-a1 . Cross[b, e] - a1 . Cross[b, f] - a1 . Cross[e, f])*
(-b . b - b . c + b . d + c . d) + (16*I)*\[CapitalEpsilon]1*\[CapitalEpsilon]2*
(-a1 . Cross[b, e] - a1 . Cross[b, f] - a1 . Cross[e, f])*
(-b . b - b . c + b . d + c . d) + (16*I)*\[CapitalEpsilon]1*\[CapitalEpsilon]2*
(-a1 . Cross[b, d] + a1 . Cross[b, f] - a1 . Cross[d, f])*
(b . b + b . c + b . e + c . e) -
(32*I)*m^2*(a1 . Cross[b, d] - a1 . Cross[b, f] + a1 . Cross[d, f])*
(b . b + b . c + b . e + c . e) +
(16*I)*m*\[CapitalEpsilon]2*(a1 . Cross[b, d] + a1 . Cross[b, e] - a1 . Cross[d, e])*
(-b . b - b . c + b . f + c . f) + (16*I)*\[CapitalEpsilon]1*\[CapitalEpsilon]2*
(a1 . Cross[b, d] + a1 . Cross[b, e] - a1 . Cross[d, e])*
(-b . b - b . c + b . f + c . f) + (16*I)*m*\[CapitalEpsilon]2*(a1 . b + a1 . e)*
(-b . Cross[c, d] + b . Cross[c, f] + b . Cross[d, f] + c . Cross[d, f]) +
(16*I)*\[CapitalEpsilon]1*\[CapitalEpsilon]2*(a1 . b + a1 . e)*(-b . Cross[c, d] + b . Cross[c, f] +
b . Cross[d, f] + c . Cross[d, f]) -
(16*I)*m*\[CapitalEpsilon]2*(-a1 . Cross[b, c] - a1 . Cross[b, f] - a1 . Cross[c, f])*
(-b . b + b . d - b . e + d . e) - (16*I)*\[CapitalEpsilon]1*\[CapitalEpsilon]2*
(-a1 . Cross[b, c] - a1 . Cross[b, f] - a1 . Cross[c, f])*
(-b . b + b . d - b . e + d . e) -
(16*I)*(-a1 . Cross[b, g] + a1 . Cross[b, h] + a1 . Cross[f, g] -
a1 . Cross[f, h])*(b . g + b . h + c . g + c . h)*
(-b . b + b . d - b . e + d . e) -
(32*I)*m*\[CapitalEpsilon]2*(a1 . Cross[b, c] - a1 . Cross[b, e] - a1 . Cross[c, e])*
(b . b - b . d - b . f + d . f) - (32*I)*\[CapitalEpsilon]1*\[CapitalEpsilon]2*
(a1 . Cross[b, c] - a1 . Cross[b, e] - a1 . Cross[c, e])*
(b . b - b . d - b . f + d . f) +
(32*I)*m^2*(-a1 . Cross[b, c] + a1 . Cross[b, e] + a1 . Cross[c, e])*
(b . b - b . d - b . f + d . f) +
(32*I)*m*\[CapitalEpsilon]1*(-a1 . Cross[b, c] + a1 . Cross[b, e] + a1 . Cross[c, e])*
(b . b - b . d - b . f + d . f) -
(32*I)*(a1 . Cross[b, g] - a1 . Cross[b, h] + a1 . Cross[e, g] -
a1 . Cross[e, h])*(b . g + b . h + c . g + c . h)*
(b . b - b . d - b . f + d . f) +
(16*I)*(-a1 . Cross[b, g] + a1 . Cross[b, h] + a1 . Cross[f, g] -
a1 . Cross[f, h])*(b . b + b . c + b . e + c . e)*
(-b . g - b . h + d . g + d . h) + (16*I)*m*\[CapitalEpsilon]2*(a1 . b + a1 . c)*
(-b . Cross[d, e] - b . Cross[d, f] - b . Cross[e, f] + d . Cross[e, f]) +
(16*I)*\[CapitalEpsilon]1*\[CapitalEpsilon]2*(a1 . b + a1 . c)*(-b . Cross[d, e] - b . Cross[d, f] -
b . Cross[e, f] + d . Cross[e, f]) + (32*I)*(-a1 . g + a1 . h)*
(b . g + b . h + c . g + c . h)*(-b . Cross[d, e] - b . Cross[d, f] -
b . Cross[e, f] + d . Cross[e, f]) - (16*I)*(a1 . g + a1 . h)*
(b . b + b . c + b . e + c . e)*(-b . Cross[d, g] + b . Cross[d, h] +
b . Cross[f, g] - b . Cross[f, h] - d . Cross[f, g] + d . Cross[f, h]) -
(16*I)*(a1 . b + a1 . e)*(b . g + b . h + c . g + c . h)*
(-b . Cross[d, g] + b . Cross[d, h] + b . Cross[f, g] - b . Cross[f, h] -
d . Cross[f, g] + d . Cross[f, h]) +
(16*I)*m*\[CapitalEpsilon]2*(-a1 . Cross[b, c] - a1 . Cross[b, d] - a1 . Cross[c, d])*
(-b . b - b . e + b . f + e . f) + (16*I)*\[CapitalEpsilon]1*\[CapitalEpsilon]2*
(-a1 . Cross[b, c] - a1 . Cross[b, d] - a1 . Cross[c, d])*
(-b . b - b . e + b . f + e . f) +
(16*I)*(-a1 . Cross[b, g] + a1 . Cross[b, h] + a1 . Cross[d, g] -
a1 . Cross[d, h])*(b . g + b . h + c . g + c . h)*
(-b . b - b . e + b . f + e . f) +
(16*I)*(a1 . Cross[b, d] - a1 . Cross[b, f] + a1 . Cross[d, f])*
(b . g + b . h + c . g + c . h)*(-b . g + b . h - e . g + e . h) +
(16*I)*(-a1 . Cross[b, g] + a1 . Cross[b, h] + a1 . Cross[f, g] -
a1 . Cross[f, h])*(-b . b - b . c + b . d + c . d)*
(b . g + b . h + e . g + e . h) -
(16*I)*(-a1 . Cross[b, g] + a1 . Cross[b, h] + a1 . Cross[d, g] -
a1 . Cross[d, h])*(-b . b - b . c + b . f + c . f)*
(b . g + b . h + e . g + e . h) -
(16*I)*(a1 . Cross[b, d] - a1 . Cross[b, f] + a1 . Cross[d, f])*
(-b . g + b . h - c . g + c . h)*(b . g + b . h + e . g + e . h) +
(32*I)*(-a1 . g + a1 . h)*(-b . Cross[c, d] + b . Cross[c, f] +
b . Cross[d, f] + c . Cross[d, f])*(b . g + b . h + e . g + e . h) +
(32*I)*(a1 . Cross[b, g] - a1 . Cross[b, h] + a1 . Cross[c, g] -
a1 . Cross[c, h])*(b . b - b . d - b . f + d . f)*
(b . g + b . h + e . g + e . h) + (16*I)*(a1 . b + a1 . c)*
(-b . Cross[d, g] + b . Cross[d, h] + b . Cross[f, g] - b . Cross[f, h] -
d . Cross[f, g] + d . Cross[f, h])*(b . g + b . h + e . g + e . h) -
(16*I)*(-a1 . Cross[b, g] + a1 . Cross[b, h] + a1 . Cross[d, g] -
a1 . Cross[d, h])*(b . b + b . c + b . e + c . e)*
(-b . g - b . h + f . g + f . h) -
(16*I)*(a1 . Cross[b, d] - a1 . Cross[b, f] + a1 . Cross[d, f])*
(b . b + b . c + b . e + c . e)*(\[CapitalEpsilon]1*\[CapitalEpsilon]2 + g . g - h . h)


I don't know the answer but may have a solution. I noticed that as I started to break the expression up into components and used TensorExpand, it was evaluating quite quickly. Have you considered trying that?

• Yeah, it could be faster, but then, it fails at the reduce between the "components". Commented Aug 29, 2018 at 5:04