I have a complex expression involving second-rank tensors and Kronecker Deltas. How can I instruct Mathematica to utilize the Kronecker Deltas and perform proper index replacements? For example, consider an expression like this:

$$K_{12, \mu_1\nu_1} K_{23,\mu_2\nu_2} K_{34,\mu_3\nu_3}K_{45,\mu_4\nu_4} \delta_{\mu_2\nu_1}\delta_{\mu_3\nu_2} \delta_{\mu_4\nu_3}\delta_{\nu_4\mu_1}\rightarrow {\rm tr}(K_{12}K_{23}K_{34}K_{45})$$

Is it necessary to use packages like xAct, or can this be achieved directly in Mathematica?

Here comes the Mathematica code:

KroneckerDelta[ν4, μ1] * KroneckerDelta[μ2, ν1] *
 KroneckerDelta[μ3, ν2] * KroneckerDelta[μ4, ν3] *
 Indexed[K, {12, Indexed[μ, 1], Indexed[ν, 1]}] *
 Indexed[K, {23, Indexed[μ, 2], Indexed[ν, 2]}] *
 Indexed[K, {34, Indexed[μ, 3], Indexed[ν, 3]}] *
 Indexed[K, {45, Indexed[μ, 4], Indexed[ν, 4]}]

After resolving the KroneckerDelta issue, how could I define a general rule to ask Mathematica to identify equal Lorentz indices and contract them? For instance in the following case:                   ```    
  Indexed[F, {1, 2, \[Nu]1, c1}]*Indexed[F, {2, 3, \[Beta]1, f1}]*Indexed[F, {3, 4, \[Kappa]1, m1}]*Indexed[F, {4, 1, \[Eta]1, a1}]*Indexed[k, {1, \[Mu]1}]*Indexed[k, {2, \[Alpha]1}]*
  Indexed[k, {3, \[Gamma]1}]*Indexed[k, {4, \[Zeta]1}]*Indexed[K, {1, 2, \[Nu]1, \[Alpha]1}]*Indexed[K, {2, 3, \[Beta]1, \[Gamma]1}]*Indexed[K, {3, 4, \[Kappa]1, \[Zeta]1}]*Indexed[K, {4, 1, \[Eta]1, \[Mu]1}]*
  Indexed[q, {1, a1}]*Indexed[q, {2, c1}]*Indexed[q, {3, f1}]*Indexed[q, {4, m1}]

which should give:                                                             ```Indexed[q, 2] . Transpose[Indexed[F, {1, 2}]] . Indexed[K, {1, 2}] . Indexed[k, 2]*Indexed[q, 3] . Transpose[Indexed[F, {2, 3}]] . Indexed[K, {2, 3}] . Indexed[k, 3]*
  Indexed[q, 4] . Transpose[Indexed[F, {3, 4}]] . Indexed[K, {3, 4}] . Indexed[k, 4]*Indexed[q, 1] . Transpose[Indexed[F, {4, 1}]] . Indexed[K, {4, 1}] . Indexed[k, 1]
  • $\begingroup$ One option is to perform explicit summation over the range of your indices. I.e. for mu_sub4, Sum[expr,{mu_sub4,1,n}] where n is the dimensionality of your space - 4 for a Lorentz index. Repeat for the other indices. $\endgroup$
    – user87932
    Aug 25, 2023 at 18:18

2 Answers 2


Updated so that tensors K12, K23, etc. are used instead of a 4 index K tensor

One idea is to use the resource functions "EinsteinSummation" and "IdentityTensorReduce". The "EinsteinSummation" resource function converts a tensor expression with indices (where repeated indices indicate contraction) into a symbolic TensorContract object:

$Assumptions = (K12 | K23 | K34 | K45) ∈ Matrices[{d, d}];

expr = ResourceFunction["EinsteinSummation"][
    {{m1, n1}, {m2, n2}, {m3, n3}, {m4, n4}, {m2, n1}, {m3, n2}, {m4, n3}, {m1, n4}},
    {K12, K23, K34, K45, IdentityMatrix[d], IdentityMatrix[d], IdentityMatrix[d], IdentityMatrix[d]}

TensorContract[TensorProduct[K12, K23, K34, K45, IdentityMatrix[d], IdentityMatrix[d], IdentityMatrix[d], IdentityMatrix[d]], {{1, 15}, {2, 10}, {3, 9}, {4, 12}, {5, 11}, {6, 14}, {7, 13}, {8, 16}}]

Then, you can use the "IdentityTensorReduce" resource function to eliminate the identity tensors:

e2 = ResourceFunction["IdentityTensorReduce"][expr]

TensorContract[ TensorProduct[K12, K23, K34, K45], {{1, 8}, {2, 3}, {4, 5}, {6, 7}}]

Finally, you can use the "FromTensor" resource function to convert to your desired final representation.


Tr[K45 . K12 . K23 . K34]

which is the same as your desired answer (up to cyclic permutations of the trace).

  • $\begingroup$ @N0va, Thank you, for your valuable input. My primary concern revolves around the substantial quantity of terms that persists even after eliminating the Kronecker deltas. Despite this, not all of these terms remain distinct once they are appropriately contracted. I anticipate the occurrence of only around 7 to 8 distinct tensor contractions. I'm trying to find a way to tell Mathematica to perform these contractions. $\endgroup$
    – Hawi
    Aug 27, 2023 at 22:55
  • $\begingroup$ @Hawi Are you using my code? It seems you are using N0va's answer, not mine. I will say that converting to TensorContract objects and using TensorReduce ought to canonicalize the terms so that only distinct tensor contractions remain. $\endgroup$
    – Carl Woll
    Aug 28, 2023 at 14:37
  • $\begingroup$ Sorry for the confusion. I am using N0va's code to handle the Kronecker delta functions. Meanwhile, your idea sounds quite promising. I will attempt to incorporate it into my code. $\endgroup$
    – Hawi
    Aug 28, 2023 at 20:56

It is of course possible to write something up which collapses the Kronecker Deltas. That being said this does not lead to an expression like ${\rm tr}(K_{12}K_{23}K_{34}K_{45})$ since your given expression has no notion whatsoever of summation. Mathematica of course does not have a sum convention -- à la 'sum over repeated indices' -- and thus a 'simplification' to a matrix product and a trace is of course not possible without additional code. As far as I understand it Mathematica is still (as of version 13) rather limited when it comes to symbolic computations involving matrices/non-commuting operators. So maybe a package (like FormTracer) might actually be what you are really looking for.

Coming back to the somewhat simple task of just collapsing the Kronecker Deltas: the following rule collapses the Deltas and does the appropriate index replacements





Indexed[K, {12, Indexed[\[Nu], {4}], Indexed[\[Nu], {1}]}] Indexed[K, {23, Indexed[\[Nu], {1}], Indexed[\[Nu], {2}]}] Indexed[K, {34, Indexed[\[Nu], {2}], Indexed[\[Nu], {3}]}] Indexed[K, {45, Indexed[\[Nu], {3}], Indexed[\[Nu], {4}]}]

Obvious problems with this: this simple code has no notion of what a summation index is so it will not work properly with something like $\delta_{0,\mu}$. To get something like this working properly one would have to introduce a notation of a summation index, open external index etc.. Which again is not necessarily difficult: one could adapt the replacement rule generation to replace only Indexed objects like Indexed[\[Mu],1] but this is all rather specific and again without a real notion of summation. Going with a package might again be the way to go (or to write some proper methods for handle such summations/contractions).

  • $\begingroup$ That is a great help, thx. $\endgroup$
    – Hawi
    Aug 26, 2023 at 12:40
  • $\begingroup$ what does the Level[x,-1] do? This code works fine except in some terms it seems to do more than it is supposed to. For instance, I should not have free Lorentz indices in my expressions since all are traced, but some appear to have some free ones. $\endgroup$
    – Hawi
    Aug 28, 2023 at 8:56
  • $\begingroup$ Level[x,-1] breaks x down into all subexpressions: depending on the expression this might not be very robust/create some odd rules: more rigorous selection of valid KroneckerDelta‘s might be necessary to get it working more properly as I eluded to in the answer. But again on its own an approach without a proper notion of summations/contractions might not get you very far. If you want to send a link or update your question to involve the problematic expressions I can look into updating the rule I gave here. $\endgroup$
    – N0va
    Aug 28, 2023 at 14:46
  • $\begingroup$ Yeah sorry I am not looking trough 1024 terms to debug cases where it works and where it does not. A few comments: I think you are using Rule where you should really use RuleDelayed and I do not know what the goal here is but I think you should really look into using a proper package or clean up the code. $\endgroup$
    – N0va
    Aug 29, 2023 at 16:01
  • $\begingroup$ Sure, thx for your comments anyway. I actually did not want you to go through them to find the bug :), I thought this might give an idea of what type of contractions I am dealing with. $\endgroup$
    – Hawi
    Aug 29, 2023 at 16:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.