====== Substitutions ======
Next topic: [[documentation:guide:list_of_transformations]]
----
====Basics====
The most frequent transformation in all computations is a substitution. Here
we shall discuss the usage aspects of substitutions, while the idea of the
underlying algorithms can be found in [[documentation:guide:Mappings of Indices]].
The very important feature of any tensorial CAS is automatic relabelling
of dummy indices in the case of dummy indices clash. Redberry takes care about
it in all types of substitutions. Consider, for example, the following simple
substitution:
\[ x = x_a{}^a \qquad\text{in}\qquad (x\, f_a + y_a) (x \, f_b + z_b) \]
Here is a code to perform this substitution in Redberry:
def s = 'x = x_a^a'.t
def t = '(x*f_a + y_a)*(x*f_b + z_b)'.t
println s >> t
> (x_{d}^{d}*f_{a}+y_{a})*(x_{c}^{c}*f_{b}+z_{b})
As one can see, the appropriate relabelling was performed automatically.
====Substitutions of tensor fields====
Redberry supports substitutions of [[documentation:ref:TensorField|tensorial functions]] and automatically performs matching of function arguments during substitution:
def s = 'F_ij[x_m, y_m] = x_i*y_j'.t
def t = 'T^ab*F_ab[p^a - q^a, p^a + q^a]'.t
println s >> t
> T^{ab}*(p_{a}-q_{a})*(p_{b}+q_{b})
If [[documentation:ref:TensorField]] depends on indexed argument, then some ambiguities arise when mapping the arguments. For example, the following substitution:
\[
F_i (x_{mn}) \,=\, x_{ij} f^j \qquad \rightarrow \qquad F_k(x_i\,y_j)
\]
can be performed in two different ways: (a) matching $x_{ij} \to x_i y_j$ gives $x_k y_j f^j$, (b) matching $x_{ij} \to x_j y_i$ gives $y_k x_j f^j$. This is because the indices of product ($x_i y_j$) are not ordered by their nature. To explicitly specify the matching rule in such ambiguous situations, Redberry allows to enter the correspondence of indices in the field arguments:
def s = 'F_i[x_mn] = x_ik*f^k'.t
def t = 'F_k[x_i*y_j]'.t //equivalent to F_k[x_i*y_j:_ij]
println s >> t
> x_{k}*y_{a}*f^{a}
t = 'F_k[x_i*y_j:_ji]'.t
println s >> t
> x_{a}*y_{k}*f^{a}
====Substitutions of products, sums, etc. ====
As well as [[documentation:ref:SimpleTensor]] and [[documentation:ref:TensorField]] substitutions, Redberry fully supports all other types of substitutions, taking into account both indices symmetries and indices contractions. Consider the following complicated example. Let's apply the following substitution
\[
f_{m} + R_{bma}\,F^{ba} - R_{ljm}\,F^{lj} = R_{bam}\,F^{ab}
\]
to tensor
\[
f_i + R_{ijk} F^{jk} + R_{ijk}\,F^{kj} - R_{kij}\,F^{jk},
\]
where $R_{abc}$ is antisymmetric: \( R_{abc} \,=\, - R_{cba}\). It is easy to show that the result will be zero. In Redberry one can e.g. do
addSymmetry 'R_mnp', -[[0, 2]].p
def s = 'f_m + R_bma*F^ba - R_ljm*F^lj = R_bam*F^ab'.t
def t = 'f_i + R_ijk*F^jk + R_ijk*F^kj - R_kij*F^jk'.t
println s >> t
> 0
We see, that Redberry matched the l.h.s. of the substitution in tensor ''t'' and automatically reduced the resulting sum to the standard form, which, in turn, gave zero.
Redberry takes into account not only predefined symmetries of simple
tensors, but also symmetries of any complicated expression, which arise from
its structure. For example:
def s = 'K_a * (A^ab - A^ba) = F^a*A_a^b'.t
def t = 'K_p * (A^qp - A^pq) + F^b*A_b^q'.t
println s >> t
> 0
The result is zero since tensor $(A_{cb} - A_{bc})$ is antisymmetric. As well,
Redberry takes care about symmetries of indexless objects:
def c = 'Cos[a - b] = c'.t,
s = 'Sin[a - b] = s'.t,
t = 'x = Cos[b - a]**3 + Sin[b - a]**3'.t
println (c | s) >> t
> x = c**3 - s**3
As one can see, the built-in definitions of sine and cosine are set up to be
odd and even respectively.
====Sequential vs. simultaneous substitutions====
There is an important note on applying several substitutions at a time using the
joining of transformations. Substitutions joined with ''&'' operator
will be applied sequentially. However, sometimes it is necessary to apply
several substitution rules "simultaneously". Consider the following example:
def X2YandY2X = 'x=y'.t & 'y=x'.t,
X2YorY2X = 'x=y'.t | 'y=x'.t,
tensor = 'x+2*y'.t
println X2YandY2X >> tensor
> 3*x
println X2YorY2X >> tensor
> y+2*x
The first transformation (''X2YandY2X'') means just sequential applying
of two provided substitutions, while the second (''X2YorY2X'')
performs both substitutions "simultaneously".
====Constructing substitutions====
Sometimes it is necessary to create substitution from a given l.h.s and r.h.s that are raised from other calculations (not entered "by hand"). In order to construct such expression programmatically from a given l.h.s. and r.h.s. one can use the following syntax:
def lhs = 'x'.t,
rhs = 'a + b'.t
//this is equivalent to subs = 'x = a + b'.t
def subs = lhs.eq(rhs)
//or equivalently
subs = "$lhs = $rhs".t
println subs >> 'x**2'.t
> (a + b)**2
====See also====
* Related guides: [[documentation:guide:applying_and_manipulating_transformations]], [[documentation:guide:list_of_transformations]]