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 inex:= 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
writeex:= 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)