a field-theory motivated approach to computer algebra

# Default simplification

By default, Cadabra does very few things "by itself" with your expressions. It only collects equal terms, but even that can be turned off if you want to. The logic is that all simplification steps are contained in a function post_process, which is executed on every new input and on every completion of an algorithm. It can contain arbitrary code, but by default it reads
def post_process(ex): collect_terms(ex)
which simply collects equal terms. You can for instance apply a substitution on every input automatically,
def post_process(ex): distribute(ex) substitute(ex, $A_{m n} -> B_{m q} B_{q n}$) collect_terms(ex)
{m,n,p,q}::Indices(vector); A_{m n}::Symmetric; ex:=A_{m n} ( A_{n m} + C_{n m});
$$\displaystyle{}\text{Attached property Indices(position=free) to }\left[m, n, p, q\right].$$
$$\displaystyle{}\text{Attached property Symmetric to }B_{m q} B_{q n}.$$
$$\displaystyle{}B_{m q} B_{q n} B_{n p} B_{p m}+B_{m q} B_{q n} C_{n m}$$
B_{m q} B_{q n} B_{n p} B_{p m} + B_{m q} B_{q n} C_{n m}
As usual dummy indices have been relabelled appropriately.
The post_process function can be redefined on-the-fly in the middle of a notebook.