A person experienced in noncommutative calculations simplifies expressions in two ways:
1. Write the expression in the shortest possible form with special attention given to subexpressions with physical or special mathematical meaning.
2. The other is to expand expressions, apply simplifying rules repeatedly to each term, and see which terms cancel.
The second method is the one which for commuting algebras has been developed to a high art in computer calculation. The idea is very simple and intuitive. Simplification is done with rules which replace complicated monomials with sums of simpler monomials, e.g.,
inv[1-x] ** x -> inv[1-x]-1
inv[a+b ** c] ** b ** c -> 1-inv[a+b ** c] ** inv[a] |
throughout the expression to be simplified. When you use NCAlgebra you will often be making up such rules and substituting them in expressions. In a fixed collection of applications you can make your life easier if you save the rules and use them over and over again. The best way to do this is to put them in a function, say
MyRules=
{inv[1-x_] :> inv[x]-1, inv[a+b ** c] ** b ** c -> 1-inv[a+b ** c] ** inv[a]}; MySimplify[expr_]:=Substitute[expr, MyRules]; |
One of the trickier fine points is how to set the blanks in your rules. If you do not use blanks that’s fine provided you always use the same letters and do not replace them with other notation in some equation. Clearly using blanks is much more powerful. The trick is how many. For example, x_ is ok here. APPENDIX E discusses this.
The next major point is not to go into a loop. To this end one must select an ordering, call it COM, on monomials. For mnemonic purposes it is best to select the ordering to reflect your intuitive idea of which monomials are more complicated than others. For example if all of your formulas involve polynomials in
x, inv[x], inv[1-x ** y], inv[1-y ** x],
y, inv[y] |
a natural partial ordering is given by low degree < high degree
We then subdivide equivalence classes of this ordering with
x inv[x] inv[1-x ** y] commutative expr < < < y inv[y] inv[1-y ** x] |
then we subdivide equivalence classes of this ordering with lexicographical order, i.e , x < y.
A reasonable convention is that higher order expressions move RIGHT.
For example, a basic equality is
inv[1-x ** y] ** x- x ** inv[1 - y ** x]==0 .
|
This translates to the rule
inv[1-x ** y] ** x -> x ** inv[1-y ** x]
|
because inv[1-x ** y] is ’complicated’ and we move it RIGHT. To harp on an earlier point we would suggest using the more powerful delayed assignment form of the rule:
inv[1-x__ ** y_] ** x__ :> x ** inv[1- y ** x]
|
IMPORTANT: these are the ordering conventions we use in NCSR. If you write rules consistent with them then you will then you can use them and NCSR without going into a loop. Indeed NCSR contains a “Gröbner basis” for reducing the set of polynomials in the expressions (inv).
Here is a summary of the ordering conventions ranked from most complicated to the least:
high degree>low degree
inv of complicated polynomials inv of simple polynomials complicated polynomials simple polynomials commuting elements and expressions in them. |
REMEMBER HIGHER ORDER EXPRESSIONS MOVE RIGHT.
Automatic generation of rules is the subject of the NCGB part of this document. Since running the NCGB code requires C++, you may not have it. Here NCSimplifyRationalX1[] does the trick.
Lying around in the directory NC/NCAlgebra/OldmmaGB/ is a primative NCSimplifyRationalX1[] which works entirely under Mma. We don’t support it since our efforts go to Mma C++ hybrids. We do not even recall its name. Anyone who resurrects it must be an intrepid adventurer.