a field-theory motivated approach to computer algebra

# Patterns, conditionals and regular expressions

Patterns in Cadabra are quite a bit different from those in other computer algebra systems, because they are more tuned towards the pattern matching of objects common in tensorial expressions, rather than generic tree structures. Cadabra knows about three different pattern types: name patterns (for single names), object patterns (for things which include indices and arguments) and dummy patterns (things for which the name is irrelevant, like indices). Name patterns are things which match a single name in an object, without indices or arguments. They are constructed by writing a single question mark behind the name, as in
ex:= Q + R; substitute(_, $A? + B? -> 0$);
$$\displaystyle{}Q+R$$
Q + R
A_{\mu} B_{\nu} C_{\nu} D_{\mu}
$$\displaystyle{}0$$
0
A.D B.C
which matches all sums with two terms, each of which is a single symbol without indices or arguments. If you want to match instead any object, with or without indices or arguments, use the double question mark instead. To see the difference more explicitly, compare the two substitute commands in the following example
ex:=A_{m n} + B_{m n}; substitute(_, $A? + B? -> 0$ ); substitute(_, $A?? + B?? -> 0$ );
$$\displaystyle{}A_{m n}+B_{m n}$$
$$\displaystyle{}A_{m n}+B_{m n}$$
$$\displaystyle{}0$$
0
Note that it does not make sense to add arguments or indices to object patterns; a construction of the type A??_{\mu}(x) is meaningless and will be flagged as an error. There is a special handling of objects which are dummy objects. Objects of this type do not need the question mark, as their explicit name is never relevant. You can therefore write
ex:= A_{m n}; substitute(_, $A_{p q}->0$);
$$\displaystyle{}A_{m n}$$
$$\displaystyle{}0$$
0
to set all occurrances of the tensor $A$ with two subscript indices to zero, regardless of the names of the indices (as you can see, this command sets $A_{p q}$ to zero). When index sets are declared using the Indices property, these will be taken into account when matching.
When replacing object wildcards with something else that involves these objects, use the question mark notation also on the right-hand side of the rule. For instance,
ex:= C + D + E + F; substitute(_, $A? + B? -> A? A?$, repeat=True);
$$\displaystyle{}C+D+E+F$$
$$\displaystyle{}C C+E E$$
C C + E E
replaces every consecutive two terms in a sum by the square of the first term. The following example shows the difference between the presence or absence of question marks on the right-hand side:
ex:= C + D; substitute(_, $A? + B? -> A?$);
$$\displaystyle{}C$$
ex:= C + D; substitute(_, $A? + B? -> A A$);
$$\displaystyle{}A A$$
So be aware that the full pattern symbol needs to be used on the right-hand side (in contrast to many other computer algebra systems). Note that you can also use patterns to remove or add indices or arguments, as in
{\mu, \nu, \rho, \sigma}::Indices(vector); ex:= A_{\mu} B_{\nu} C_{\nu} D_{\mu}; substitute(_, $A?_{\rho} B?_{\rho} -> \dot{A?}{B?}$, repeat=True);
$$\displaystyle{}\text{Attached property Indices(position=free) to }\left[\mu, \nu, \rho, \sigma\right].$$
$$\displaystyle{}A_{\mu} B_{\nu} C_{\nu} D_{\mu}$$
$$\displaystyle{}A \cdot D B \cdot C$$

## Conditionals

In many algorithms, patterns can be supplemented by so-called conditionals. These are constraints on the objects that appear in the pattern. In the example below, the substitution is not carried out, as the rule applies only to patterns where the $n$ and $p$ indices are not equal,
ex:= A_{m n} B_{n q}; substitute(_, $A_{m n} B_{p q} | n != p -> 0$);
$$\displaystyle{}A_{m n} B_{n q}$$
$$\displaystyle{}A_{m n} B_{n q}$$
A_{m n} B_{n q}
$$\displaystyle{}A_{m n} B_{n q}$$
A_{m n} B_{n q}
Without the conditional, the substitution does apply,
ex:= A_{m n} B_{n q}; substitute(_, $A_{m n} B_{p q} -> 0$);
$$\displaystyle{}A_{m n} B_{n q}$$
A_{m n} B_{n q}
$$\displaystyle{}0$$
0
Note that the conditional follows directly after the pattern, not after the full substitution rule. A way to think about this is that the conditional is part of the pattern, not of the rule. The reason why the conditional follows the full pattern, and not directly the symbol to which it relates, is clear from the example above: the conditional is a "global" constraint on the pattern, not a local one on a single index. These conditions can be used to match names of objects using regular expressions. In the following example, the pattern M? will match against C7,
ex:= A + B3 + C7; substitute(_, $A + M? + N? | \regex{M?}{"[A-Z]7"} -> \sin(M? N?)/N?$);
$$\displaystyle{}A+B3+C7$$
A + B3 + C7
$$\displaystyle{}\sin\left(C7 B3\right) {B3}^{-1}$$
\sin(C7 B3) (B3)**(-1)
Without the condition, the first match of M? would be against B3,
ex:= A + B3 + C7; substitute(_, $A + M? + N? -> \sin(M? N?)/N?$);
$$\displaystyle{}A+B3+C7$$
A + B3 + C7
$$\displaystyle{}\sin\left(B3 C7\right) {C7}^{-1}$$
\sin(B3 C7) (C7)**(-1)