A Very Large Scale Pattern Matching Problem in MathTensor


This is an evaluated Mathematica notebook. Since the notebook is intended to be interactive, it may be helpful to also view the unevaluated version

Steven M. Christensen

MathTensor, Inc.
Steven M. Christensen and Associates, Inc.

steve@smc.vnet.net

Based on a talk presented at the Mathematica Developer's Conference, Urbana, Illinois, October, 1995. This work is part of a collaboration with Dr. Stephen A. Fulling of the Mathematics Department at Texas A & M University.

Historical Introduction

The main reason I started working with SMP and then Mathematica was to do calculations in quantum field theory and gravitation. In these fields it is very common for incredibly large so-called symbol crunching calculations to be generated. Equations with thousands or even millions of terms can appear. In many cases it is necessary to apply a number of rules to each term in order to simplify the expressions down from many terms to a few (maybe tens or hundreds). One of the main problems we found can be explained simply:

In[1]:=

  Sum[coeff[i] RiemannTerm[i],{i,1,25}]

Out[1]=

  coeff[1] RiemannTerm[1] + coeff[2] RiemannTerm[2] + 
   
    coeff[3] RiemannTerm[3] + coeff[4] RiemannTerm[4] + 
   
    coeff[5] RiemannTerm[5] + coeff[6] RiemannTerm[6] + 
   
    coeff[7] RiemannTerm[7] + coeff[8] RiemannTerm[8] + 
   
    coeff[9] RiemannTerm[9] + coeff[10] RiemannTerm[10] + 
   
    coeff[11] RiemannTerm[11] + coeff[12] RiemannTerm[12] + 
   
    coeff[13] RiemannTerm[13] + coeff[14] RiemannTerm[14] + 
   
    coeff[15] RiemannTerm[15] + coeff[16] RiemannTerm[16] + 
   
    coeff[17] RiemannTerm[17] + coeff[18] RiemannTerm[18] + 
   
    coeff[19] RiemannTerm[19] + coeff[20] RiemannTerm[20] + 
   
    coeff[21] RiemannTerm[21] + coeff[22] RiemannTerm[22] + 
   
    coeff[23] RiemannTerm[23] + coeff[24] RiemannTerm[24] + 
   
    coeff[25] RiemannTerm[25]

Each coeff[ ] is some exact ratio of integers. Each RiemannTerm[ ] is some potentially complicated tensorial expression. There may be a few million terms of this kind. We know that almost all of these terms can be written as a linear combination of a much smaller number of "basis" RiemannTerms. So we might have

RiemannTerm[1], RiemannTerm[2], RiemannTerm[3]

as the basis and a lot of rules relating the other terms to these as in

RiemannTerm[25] -> rulecoeff[1] RiemannTerm[1] +
rulecoeff[2] RiemannTerm[2] +
rulecoeff[3] RiemannTerm[3]

In our calculations, we need to have the computer to the following things:

Load MathTensor

In[2]:=
  <<MathTensor.m

  Loading MathTensor for UNIX . . . 



========================================================
MathTensor (TM) 2.2 (UNIX (R)) (June 1, 1994)
by Leonard Parker and Steven M. Christensen
Copyright (c) 1991-1994 MathTensor, Inc.
Runs with Mathematica (R) Versions 2.X.
Licensed to machine smc.vnet.net.
========================================================
No unit system is chosen. If you want one,
you must edit the file called Conventions.m,
or enter a command to interactively set units.
Units: {}
Sign conventions: Rmsign = 1 Rcsign = 1
MetricgSign = 1 DetgSign = -1
TensorForm turned on,
ShowTime turned off,
MetricgFlag = True.
=========================================

Generate the equations we want to work with.

We already know that the terms in our equations will be constructed from products of the Riemann tensor, the object that measures the curvature of spacetimes. The Riemann tensor has a very well known structure. It is an object with four tensorial indices and these indices have an important set of symmetries.

The Riemann tensor has four indices, here "covariant" lower indices as entered in MathTensor.

In[3]:=

  RiemannR[la,lb,lc,ld]

Out[3]=

  R
   abcd

This object is antisymmetric under interchange of the first pair or second pari of indices.

In[4]:=

  RiemannR[lb,la,lc,ld]

Out[4]=

  -R
    abcd

In[5]:=

  RiemannR[la,lb,ld,lc]

Out[5]=

  -R
    abcd

The Riemann tensor is symmetric under interchange of the two pairs.

In[6]:=

  RiemannR[lc,ld,la,lb]

Out[6]=

  R
   abcd

If one index is raised to its contravariant position and summed with its corresponding lower index, the Riemann tensor is equal to the so-called Ricci tensor which is symmetric in its two indices.

In[7]:=

  RiemannR[la,lb,ua,ld]

Out[7]=

  R
   bd

Because of the antisymmetries in the pairs of indices, when one of the pairs is summed, the result is zero.

In[8]:=

  RiemannR[la,ua,lc,ld]

Out[8]=

  0

If the indices of the Riemann tensor are summed across pairs or on the indices on the Ricci tensor, we obtain the Riemann Scalar.

In[9]:=

  RiemannR[la,lb,ua,ub]

Out[9]=

  R

MathTensor understands these properties and applies them automatically to any terms generated. Many important rules are included in a set of RiemannRules. Other rules are also available, like the cyclic identity:

In[10]:=

  ?RiemannCyclicSecondThreeRule

   RiemannCyclicSecondThreeRule[la,lb,lc,ld] performs the
cyclic identity on lb, lb, and ld in an expression using
expr /. RiemannCyclicSecondThreeRule[la,lb,lc,ld].

In[11]:=

  RiemannR[lc,la,ld,lb] /. 
  RiemannCyclicSecondThreeRule[lc,la,ld,lb]

Out[11]=

  R     + R
   abcd    adbc

In[12]:=

  RiemannR[la,lb,lc,ld] RiemannR[ua,ud,ub,uc]

Out[12]=

         adbc
  R     R
   abcd

In[13]:=

  ApplyRules[%,RiemannRules]

  RiemannRule9c::Applied: RiemannRule9c has been used.

Out[13]=

           pqrs
  -(R     R    )
     pqrs
  --------------
        2

MathTensor knows all of the standard rules for terms up to the product of two Riemann tensors and its derivatives. It also knows some of the products of three Riemann tensor rules.

Here is a typical relatively small equation that appears in our work.

In[14]:=

  <<sigmarules.m

In[15]:=

  CD[sigma,la,lb,lc,ld,le,lf]

Out[15]=

  sigma
       ;abcdef

In[16]:=

  ApplyRules[%,SigmaLimitSixRule]

Out[16]

It is important to note that any index out of place or error in sign, etc. will ultimately lead to total nonsense in physical results.

Allow us to define the rules we need.

It is extremely difficult to determine the size of the minimal set of linearly independent Riemann tensor products. It requires very subtle use of group theoretical arguments like Young tableaux. Consider just one Riemann tensor term's possible indices with no summations:

In[17]:=

  indices40 = {la,lb,lc,ld}

Out[17]=

  { ,  ,  ,  }
   a  b  c  d

In[18]:=

  all40 = Permutations[indices40]

Out[18]=

  {{ ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
    a  b  c  d    a  b  d  c    a  c  b  d    a  c  d  b
   
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     a  d  b  c    a  d  c  b    b  a  c  d    b  a  d  c
   
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     b  c  a  d    b  c  d  a    b  d  a  c    b  d  c  a
   
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     c  a  b  d    c  a  d  b    c  b  a  d    c  b  d  a
   
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     c  d  a  b    c  d  b  a    d  a  b  c    d  a  c  b
   
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }}
     d  b  a  c    d  b  c  a    d  c  a  b    d  c  b  a

In[19]:=

  Table[RiemannR[Unlist[all40[[i]]]],{i,1,Length[all40]}]

Out[19]=

  {R    , -R    , R    , -R    , R    , -R    , -R    , 
    abcd    abcd   acbd    acbd   adbc    adbc    abcd
   
    R    , R    , -R    , R    , -R    , -R    , R    , 
     abcd   adbc    adbc   acbd    acbd    acbd   acbd
   
    -R    , R    , R    , -R    , -R    , R    , -R    , 
      adbc   adbc   abcd    abcd    adbc   adbc    acbd
   
    R    , -R    , R    }
     acbd    abcd   abcd

In[20]:=

  Union[% /. {-1 -> 1}]

Out[20]=

  {R    , R    , R    }
    abcd   acbd   adbc

So we see that the best MathTensor can do using the pre-defined Riemann tensor symmetries is reduce the list to three terms. Any equation we generate will have at most 3 terms. But group theory and well-known identities tell us that the dimension of the minimal set is 2. We need just 1 rule, the cyclic identity to reduce any expression down to 2 terms.

We can also consider situations with summed indices via

In[21]:=

  indices41 = {la,lb,lc,uc}

Out[21]=

            c
  { ,  ,  ,  }
   a  b  c

In[22]:=

  all41 = Permutations[indices41]

Out[22]=

             c          c                c          c
  {{ ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
    a  b  c       a  b     c    a  c  b       a  c     b
   
        c             c                   c          c
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     a     b  c    a     c  b    b  a  c       b  a     c
   
              c          c          c             c
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     b  c  a       b  c     a    b     a  c    b     c  a
   
              c          c                c          c
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     c  a  b       c  a     b    c  b  a       c  b     a
   
        c             c          c             c
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     c     a  b    c     b  a       a  b  c       a  c  b
   
     c             c             c             c
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }}
        b  a  c       b  c  a       c  a  b       c  b  a

In[23]:=

  Table[RiemannR[Unlist[all41[[i]]]],{i,1,Length[all41]}]

Out[23]=

  {0, 0, R  , -R  , R  , -R  , 0, 0, R  , -R  , R  , -R  , 
          ab    ab   ab    ab         ab    ab   ab    ab
   
    -R  , R  , -R  , R  , 0, 0, -R  , R  , -R  , R  , 0, 0}
      ab   ab    ab   ab          ab   ab    ab   ab

In[24]:=

  Rest[Union[% /. {-1 -> 1}]]

Out[24]=

  {R  }
    ab

There is only one object with two indices built out of one Riemann tensor. Now we can consider the case where we have a product of two Riemann tensors (with no derivatives for now) and 8 free indices. We can generate all possible permutations of these 8 indices and then split the list up into pairs of four indices.

In[25]:=

  indices80 = {la,lb,lc,ld,le,lf,lg,lh}

Out[25]=

  { ,  ,  ,  ,  ,  ,  ,  }
   a  b  c  d  e  f  g  h

In[26]:=

  all80 = Permutations[indices80];

In[27]:=

  all80part = Map[Partition[#,4]&,all80];

In[28]:=

  all80part[[1]]

Out[28]=

  {{ ,  ,  ,  }, { ,  ,  ,  }}
    a  b  c  d    e  f  g  h

In[29]:=

  Riemann80 = Table[RiemannR[Unlist[all80part[[i,1]]]]*
  RiemannR[Unlist[all80part[[i,2]]]],{i,1,Length[all80part]}];

In[30]:=

  Riemann80[[1]]

Out[30]=

  R     R
   abcd  efgh

This generates a lot of terms - 8! - many of which are equal or differ by a sign only.

In[31]:=

  Length[Riemann80]

Out[31]=

  40320

In[32]:=

  Riemann80a = Union[Riemann80 /. {-1 -> 1}]

Out[32]

In[33]:=

  Length[%]

Out[33]=

  315

So, we see that MathTensor will generate at most 315 two Riemann tensor structures with 8 free indices. From group theoretical calculations we find that there are really only 140 terms in the minimal basis. So at first sight we will have to generate 175 rules. But if we look at the terms, we immediately see that terms like RiemannR[la,le,lb,lc], where the second pair of indices is lexically before the second index, can be rewritten in the form RiemannR[la,lb,lc,le] or RiemannR[la,lc,lb,le] using the cylic identity alone. How many terms does this leave?

In order to determine this we must first have a rule that checks each term above to see if it can be rewritten:

In[34]:=

  RuleUnique[CyclicRule, RiemannR[la_,lb_,lc_,ld_],
  - RiemannR[la,lc,ld,lb] - RiemannR[la,ld,lb,lc],
  IndicesAndNotOrderedQ[{lb,lc}] && IndicesAndNotOrderedQ[{lb,ld}]]

In[35]:=

  Riemann80a /. CyclicRule

Out[35]

For our counting purposes we can remove terms from our list by defining a "fake" rule which simply sets to zero any term that is changed by CyclicRule:

In[36]:=

  RuleUnique[FakeCyclicRule,RiemannR[la_,lb_,lc_,ld_],
  0,IndicesAndNotOrderedQ[{lb,lc}] &&
  IndicesAndNotOrderedQ[{lb,ld}]]

In[37]:=

  Rest[Union[Riemann80a /. FakeCyclicRule]]

Out[37]

In[38]:=

  Length[%]

Out[38]=

  140

Aha! We don't need 175 rules, just 1! if we apply CyclicRule.

Now lets look at the case where we sum over the four pairs and generate scalars.

In[39]:=

  Union[%% /. {lb->ua,ld->uc,lf->ue,lh->ug}]

Out[39]

We use the MathTensor Canonicalize function to rename summed dummy indices in each term and obtain

In[40]:=

  Rest[Union[Map[Canonicalize[#]&,%] /. {-1 -> 1}]]

Out[40]=

    2       pq         pqrs         prqs
  {R , R   R  , R     R    , R     R    }
        pq       pqrs         pqrs

We see now that when we sum the indices on the minimal set above, we get 4 possible scalar objects with 2 Riemann tensors. But, we know that there can be only 3 independent objects in the minimal scalar set. So, even though the 2 Riemann tensor product set above is a minimal set, the scalar set derived from it is not. It is possible to show that the fourth term above is related to the third via

In[41]:=

  RuleUnique[TwoRiemannSummedRule,
  RiemannR[la_,lb_,lc_,ld_] * RiemannR[ua_,ub_,uc_,ud_],
  RiemannR[la,lb,lc,ld] RiemannR[ua,ub,uc,ud]/2,
  PairQ[la,ua] && PairQ[lb,uc] && PairQ[lc,ub] && PairQ[ld,ud]]

In[42]:=

  ApplyRules[%%[[4]],TwoRiemannSummedRule]

Out[42]=

         pqrs
  R     R
   pqrs
  -----------
       2

So using the CyclicRule and TwoRiemannSummedRule we can reduce any scalar expression with 2 Riemann tensor products down to a minimal size.

If we want to go to three Riemann tensors and then try to generate all the permutations we will have 12! = 479,001,600 terms. We will get Out of Memory errors. Even if we could generate that many terms, it is a waste of resources since we know some things about what MathTensor will do. We know that the la and lb indices can only be in two possible configurations due to the symmetries of the RiemannTensor and the lexical ordering of terms that Mathematica does. If we do the permutations on the 10 remaining indices we get 8 x 9! = 2,903,040 terms.

Group theory tells us that there are 46,200 terms in the minimal set! So to illustrate a simpler situtation we can look at the scalars with three Riemann tensors. We need to find a minimal set of 8. It is easy to show that all the terms that MathTensor could generate after the use of Canonicalize and CyclicRule will have the forms


The first terms are obviously just

In[43]:=

  terms1 = Map[Canonicalize[#]&,{ScalarR^3, ScalarR * RicciR[la,lb] RicciR[ua,ub],
  ScalarR * RiemannR[la,lb,lc,ld] RiemannR[ua,ub,uc,ud]}]

Out[43]=

    3         pq           pqrs
  {R , R R   R  , R R     R    }
          pq         pqrs

We might ask whether terms like

In[44]:=

  RicciR[la,lb] RicciR[lc,ld] RiemannR[ua,ub,uc,ud]

Out[44]=

           abcd
  R   R   R
   ab  cd

might not be generated even though it vanishes due to the symmetries of the Ricci and Riemann tensors. Clearly since I can type in this term and it does not automatically vanish, the term can appear. So, we will need to apply the Tsimplify function to our three Riemann tensor scalar expressions to eliminate such terms as with

In[45]:=

  Tsimplify[%]

Out[45]=

  0

Now we start off with the first Ricci tensor type term:

In[46]:=

  indices6 = {lc,uc,ld,ud,le,ue}

Out[46]=

      c     d     e
  { ,  ,  ,  ,  ,  }
   c     d     e

In[47]:=

  all6 = Permutations[%];

In[48]:=

  all6a = Map[Insert[#,ua,1]&,all6];

In[49]:=

  all6ab = Map[Insert[#,ub,3]&,%];

In[50]:=

  all6ab[[1]]

Out[50]=

   a     b  c     d     e
  { ,  ,  ,  ,  ,  ,  ,  }
      c        d     e

In[51]:=

  all6abpart = Map[Partition[#,4]&,all6ab];

In[52]:=

  Riemann6ab = Table[RicciR[la,lb] * 
  RiemannR[Unlist[all6abpart[[i,1]]]]*
  RiemannR[Unlist[all6abpart[[i,2]]]],{i,1,Length[all6abpart]}]

Out[52]

In[53]:=

  Rest[Union[Riemann6ab /. {-1 -> 1}]]

Out[53]

In[54]:=

  Union[Map[Canonicalize[#]&,%]]

Out[54]=

          pq             prqs            prqs
  {R R   R  , -(R   R   R    ), R   R   R    }
      pq         pq  rs          pq  rs

In[55]:=

  terms2 = Union[% /. {-1 -> 1}]

Out[55]=

          pq           prqs
  {R R   R  , R   R   R    }
      pq       pq  rs

In[56]:=

  terms = Union[terms1, terms2]

Out[56]=

    3         pq           pqrs           prqs
  {R , R R   R  , R R     R    , R   R   R    }
          pq         pqrs         pq  rs

Now, the second Ricci term types:

In[57]:=

  all6ab2 = Map[Insert[#,ub,5]&,all6a];

In[58]:=

  all6ab2[[1]]

Out[58]=

   a     c     b  d     e
  { ,  ,  ,  ,  ,  ,  ,  }
      c     d        e

In[59]:=

  all6ab2part = Map[Partition[#,4]&,all6ab2];

In[60]:=

  Riemann6ab2 = Table[RicciR[la,lb] * 
  RiemannR[Unlist[all6ab2part[[i,1]]]]*
  RiemannR[Unlist[all6ab2part[[i,2]]]],{i,1,Length[all6ab2part]}]

Out[60]

In[61]:=

  Rest[Union[Riemann6ab2 /. {-1 -> 1}]]

Out[61]

In[62]:=

  Union[Map[Canonicalize[#]&,%]]

Out[62]=

         p  qr            p  qrst           p  qrst
  {R   R   R  , -(R   R     R    ), R   R     R    , 
    pq  r          pq  rst           pq  rst
   
              p  qtrs           p  qtrs
    -(R   R     R    ), R   R     R    }
       pq  rst           pq  rst

In[63]:=

  terms3 = Union[% /. {-1 -> 1}]

Out[63]=

         p  qr          p  qrst          p  qtrs
  {R   R   R  , R   R     R    , R   R     R    }
    pq  r        pq  rst          pq  rst

In[64]:=

  terms = Union[terms, terms3]

Out[64]=

    3         pq        p  qr           pqrs           prqs
  {R , R R   R  , R   R   R  , R R     R    , R   R   R    , 
          pq       pq  r          pqrs         pq  rs
   
            p  qrst          p  qtrs
    R   R     R    , R   R     R    }
     pq  rst          pq  rst

In[65]:=

  indices4 = {le,ue,lf,uf}

Out[65]=

      e     f
  { ,  ,  ,  }
   e     f

In[66]:=

  all4 = Permutations[%]

Out[66]=

       e     f       e  f             e  f          f  e
  {{ ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
    e     f       e        f    e  f          e  f
   
        f  e          f     e    e        f    e     f
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     e        f    e     f          e  f          e     f
   
     e        f    e     f       e  f          e  f
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
        f  e          f     e          e  f          f  e
   
           e  f          f  e       e     f       e  f
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     f  e          f  e          f     e       f        e
   
        f     e       f  e       f     e       f        e
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     f     e       f        e       e     f       e  f
   
     f  e          f  e          f        e    f     e
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }}
           e  f          f  e       f  e          f     e

In[67]:=

  all4b = Map[Insert[#,ub,1]&,all4];

In[68]:=

  all4ab = Map[Insert[#,ua,1]&,all4b];

In[69]:=

  all4abc = Map[Insert[#,ud,5]&,all4ab];

In[70]:=

  all4abcd = Map[Insert[#,uc,5]&,all4abc];

In[71]:=

  all4abcd[[1]]

Out[71]=

   a  b     e  c  d     f
  { ,  ,  ,  ,  ,  ,  ,  }
         e           f

In[72]:=

  all4abcdpart = Map[Partition[#,4]&,all4abcd]

Out[72]

In[73]:=

  Riemann4abcd = Table[RiemannR[la,lb,lc,ld] * 
  RiemannR[Unlist[all4abcdpart[[i,1]]]]*
  RiemannR[Unlist[all4abcdpart[[i,2]]]],{i,1,Length[all4abcdpart]}]

Out[73]

In[74]:=

  Rest[Union[% /. {-1 -> 1}]]

Out[74]=

           fcd   eab          fab   ecd           cd  abef
  {R     R     R    , R     R     R    , R     R     R    , 
    abcd  e     f      abcd  e     f      abcd  ef
   
             ab  cdef
    R     R     R    }
     abcd  ef

In[75]:=

  Union[Map[Canonicalize[#]&,%]]

Out[75]=

              pq  rstu            pq  rstu
  {-(R     R     R    ), R     R     R    }
      pqrs  tu            pqrs  tu

In[76]:=

  Union[% /. {-1 -> 1}]

Out[76]=

            pq  rstu
  {R     R     R    }
    pqrs  tu

In[77]:=

  terms = Union[terms,%]

Out[77]=

    3         pq        p  qr           pqrs           prqs
  {R , R R   R  , R   R   R  , R R     R    , R   R   R    , 
          pq       pq  r          pqrs         pq  rs
   
            p  qrst          p  qtrs           pq  rstu
    R   R     R    , R   R     R    , R     R     R    }
     pq  rst          pq  rst          pqrs  tu

In[78]:=

  all4

Out[78]=

       e     f       e  f             e  f          f  e
  {{ ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
    e     f       e        f    e  f          e  f
   
        f  e          f     e    e        f    e     f
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     e        f    e     f          e  f          e     f
   
     e        f    e     f       e  f          e  f
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
        f  e          f     e          e  f          f  e
   
           e  f          f  e       e     f       e  f
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     f  e          f  e          f     e       f        e
   
        f     e       f  e       f     e       f        e
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     f     e       f        e       e     f       e  f
   
     f  e          f  e          f        e    f     e
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }}
           e  f          f  e       f  e          f     e

In[79]:=

  all4a = Map[Insert[#,ua,1]&,all4];

In[80]:=

  all4ab2 = Map[Insert[#,ub,3]&,all4a];

In[81]:=

  all4abc2 = Map[Insert[#,uc,5]&,all4ab2];

In[82]:=

  all4abcd2 = Map[Insert[#,ud,7]&,all4abc2];

In[83]:=

  all4abcd2[[1]]

Out[83]=

   a     b  e  c     d  f
  { ,  ,  ,  ,  ,  ,  ,  }
      e           f

In[84]:=

  all4abcd2part = Map[Partition[#,4]&,all4abcd2];

In[85]:=

  Riemann4abcd2 = Table[RiemannR[la,lb,lc,ld] * 
  RiemannR[Unlist[all4abcd2part[[i,1]]]]*
  RiemannR[Unlist[all4abcd2part[[i,2]]]],{i,1,Length[all4abcd2part]}]

Out[85]=

    ab  cd         ab  cd                a b  cedf
  {R   R   R    , R   R   R    , R     R     R    , 
            abcd           abcd   abcd  e f
   
            a b  cfde          abf   dce          abf   cde
    R     R     R    , R     R     R    , R     R     R    , 
     abcd  e f          abcd  e     f      abcd  e     f
   
     ab  cd         ab  cd                cdf   bae
    R   R   R    , R   R   R    , R     R     R    , 
             abcd           abcd   abcd  e     f
   
            dcf   bae          c d  aebf          d c  aebf
    R     R     R    , R     R     R    , R     R     R    , 
     abcd  e     f      abcd  e f          abcd  e f
   
            b a  cedf          b a  cfde          cdf   abe
    R     R     R    , R     R     R    , R     R     R    , 
     abcd  e f          abcd  e f          abcd  e     f
   
            dcf   abe   ab  cd         ab  cd
    R     R     R    , R   R   R    , R   R   R    , 
     abcd  e     f              abcd           abcd
   
            baf   dce          baf   cde          c d  afbe
    R     R     R    , R     R     R    , R     R     R    , 
     abcd  e     f      abcd  e     f      abcd  e f
   
            d c  afbe   ab  cd         ab  cd
    R     R     R    , R   R   R    , R   R   R    }
     abcd  e f                  abcd           abcd

In[86]:=

  Union[Map[Canonicalize[#]&,%] /. {-1 -> 1}]

Out[86]=

            pqrs           qs  ptru
  {R   R   R    , R     R     R    }
    pq  rs         pqrs  tu

In[87]:=

  Map[Tsimplify[#]&,%]

Out[87]=

               qs  ptru
  {0, R     R     R    }
       pqrs  tu

In[88]:=

  terms = Union[terms,Rest[%]]

Out[88]=

    3         pq        p  qr           pqrs           prqs
  {R , R R   R  , R   R   R  , R R     R    , R   R   R    , 
          pq       pq  r          pqrs         pq  rs
   
             qs  ptru          p  qrst          p  qtrs
    R     R     R    , R   R     R    , R   R     R    , 
     pqrs  tu           pq  rst          pq  rst
   
             pq  rstu
    R     R     R    }
     pqrs  tu

In[89]:=

  all4

Out[89]=

       e     f       e  f             e  f          f  e
  {{ ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
    e     f       e        f    e  f          e  f
   
        f  e          f     e    e        f    e     f
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     e        f    e     f          e  f          e     f
   
     e        f    e     f       e  f          e  f
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
        f  e          f     e          e  f          f  e
   
           e  f          f  e       e     f       e  f
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     f  e          f  e          f     e       f        e
   
        f     e       f  e       f     e       f        e
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, 
     f     e       f        e       e     f       e  f
   
     f  e          f  e          f        e    f     e
    { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }, { ,  ,  ,  }}
           e  f          f  e       f  e          f     e

In[90]:=

  all4a = Map[Insert[#,ua,1]&,all4];

In[91]:=

  all4ab3 = Map[Insert[#,ub,3]&,all4a];

In[92]:=

  all4abc3 = Map[Insert[#,uc,5]&,all4ab3];

In[93]:=

  all4abcd3 = Map[Insert[#,ud,7]&,all4abc3];

In[94]:=

  all4abcd3[[1]]

Out[94]=

   a     b  e  c     d  f
  { ,  ,  ,  ,  ,  ,  ,  }
      e           f

In[95]:=

  all4abcd3part = Map[Partition[#,4]&,all4abcd3];

In[96]:=

  Riemann4abcd3 = Table[RiemannR[la,lb,lc,ld] * 
  RiemannR[Unlist[all4abcd3part[[i,1]]]]*
  RiemannR[Unlist[all4abcd3part[[i,2]]]],{i,1,Length[all4abcd3part]}]

Out[96]=

    ab  cd         ab  cd                a b  cedf
  {R   R   R    , R   R   R    , R     R     R    , 
            abcd           abcd   abcd  e f
   
            a b  cfde          abf   dce          abf   cde
    R     R     R    , R     R     R    , R     R     R    , 
     abcd  e f          abcd  e     f      abcd  e     f
   
     ab  cd         ab  cd                cdf   bae
    R   R   R    , R   R   R    , R     R     R    , 
             abcd           abcd   abcd  e     f
   
            dcf   bae          c d  aebf          d c  aebf
    R     R     R    , R     R     R    , R     R     R    , 
     abcd  e     f      abcd  e f          abcd  e f
   
            b a  cedf          b a  cfde          cdf   abe
    R     R     R    , R     R     R    , R     R     R    , 
     abcd  e f          abcd  e f          abcd  e     f
   
            dcf   abe   ab  cd         ab  cd
    R     R     R    , R   R   R    , R   R   R    , 
     abcd  e     f              abcd           abcd
   
            baf   dce          baf   cde          c d  afbe
    R     R     R    , R     R     R    , R     R     R    , 
     abcd  e     f      abcd  e     f      abcd  e f
   
            d c  afbe   ab  cd         ab  cd
    R     R     R    , R   R   R    , R   R   R    }
     abcd  e f                  abcd           abcd

In[97]:=

  Union[Map[Canonicalize[#]&,Riemann4abcd3] /. {-1->1}]

Out[97]=

            pqrs           qs  ptru
  {R   R   R    , R     R     R    }
    pq  rs         pqrs  tu

In[98]:=

  Union[Map[Tsimplify[#]&,%]]

Out[98]=

               qs  ptru
  {0, R     R     R    }
       pqrs  tu

In[99]:=

  terms = Union[terms,Rest[%]]

Out[99]=

    3         pq        p  qr           pqrs           prqs
  {R , R R   R  , R   R   R  , R R     R    , R   R   R    , 
          pq       pq  r          pqrs         pq  rs
   
             qs  ptru          p  qrst          p  qtrs
    R     R     R    , R   R     R    , R   R     R    , 
     pqrs  tu           pq  rst          pq  rst
   
             pq  rstu
    R     R     R    }
     pqrs  tu

In[100]:=

  Length[%]

Out[100]=

  9

So using the symmetries of the Riemann tensor, its contractions to the Ricci tensor and Riemann scalar, and the Canonicalize and Tsimplify functions we can reduce any scalar expression into the 9 terms above. This is one more than we need to have a minimal set.

If we now apply CyclicRule,

In[101]:=

  terms /. CyclicRule

Out[101]=

    3         pq        p  qr           pqrs           prqs
  {R , R R   R  , R   R   R  , R R     R    , R   R   R    , 
          pq       pq  r          pqrs         pq  rs
   
             qs  ptru          p  qrst
    R     R     R    , R   R     R    , 
     pqrs  tu           pq  rst
   
            p    qrst    qsrt            pq  rstu
    R   R     (-R     + R    ), R     R     R    }
     pq  rst                     pqrs  tu

In[102]:=

  Map[Canonicalize[#]&,%]

Out[102]=

    3         pq        p  qr           pqrs           prqs
  {R , R R   R  , R   R   R  , R R     R    , R   R   R    , 
          pq       pq  r          pqrs         pq  rs
   
               pr  qust           p  qrst
    -(R     R     R    ), R   R     R    , 
       pqrs  tu            pq  rst
   
               p  qrst           pq  rstu
    -2 R   R     R    , R     R     R    }
        pq  rst          pqrs  tu

In[103]:=

  Union[% /. {-1 -> 1,-2 -> 1}]

Out[103]=

    3         pq        p  qr           pqrs           prqs
  {R , R R   R  , R   R   R  , R R     R    , R   R   R    , 
          pq       pq  r          pqrs         pq  rs
   
            p  qrst           pr  qust           pq  rstu
    R   R     R    , R     R     R    , R     R     R    }
     pq  rst          pqrs  tu           pqrs  tu

In[104]:=

  Length[%]

Out[104]=

  8

So, with the use of CyclicRule and Canonicalize, we finally get a list of 8 independent terms and a minimal set we can use. We also learn that we only need the CyclicRule added to reduce any expression to 8 terms.

Simplify the result down to the smallest equation possible.

Lets go back and look at the non-derivative Riemann tensor terms in the long six index sigma expression we showed earlier. We will drop the derivative terms

In[105]:=

  Drop[%16,12]

Out[105]

In[106]:=

  Length[%]

Out[106]=

  80

In[107]:=

  %% /. CyclicRule

Out[107]

In[108]:=

  Expand[%]
  

Out[108]

In[109]:=

  Length[%]

Out[109]=

  80

In[110]:=

  Tsimplify[%%]

Out[110]

In[111]:=

  Length[%]

Out[111]=

  70

In[112]:=

  RuleUnique[afixrule,RiemannR[b_,c_,d_,e_] *
  RiemannR[f_,g_,h_,i_], RiemannR[Raise[b],c,d,e]*
  RiemannR[f,g,h,Lower[i]],
  PairQ[b,i] && !SameQ[la,f]]

In[113]:=

  %%% /. afixrule

Out[113]

In[114]:=

  Length[%]

Out[114]=

  70

In[115]:=

  %% /. CyclicRule

Out[115]

In[116]:=

  Expand[%]

Out[116]

In[117]:=

  Length[%]

Out[117]=

  40

So we can reduce our original expression to a minimal set with the application of just a few simple rules.

Go up to Steven M. Christensen and Associates, Inc. Home Page