# Non-commutative Algebra $LM=t^2 ML$, using NCAlgebra/Mathematica

I am currently using the NCAlgebra package, and am working with the algebra where $LM=t^2 ML$, where t is commutative.

SetNonCommutative[L,M]
SetCommutative[t]

rule:=L**M -> t^2 M**L
NCReplaceAll[L**M, rule]


t^2 M**L

NCReplaceRepeated[L**M^2, L**M -> t^2 M**L]


t^2 M**L**M

NCReplaceRepeated[NCReplaceRepeated[L**M^2, rule], rule]


t^4 M**M**L

I was wondering if there was a way for me to easily have the package show that $LM^2=t^4M^2L$. (I thought the NCReplaceRepeated should have done this, but for me it was not doing so, as shown in the picture.)

In the end I will be wanting to work with polynomials in t,M, and L. And will want to simplify/expand the multiplication of such polynomials.

For example have that, $a(M)L^k \cdot b(M)L^n = a(M)b(t^{2k}M)L^{k+n}$, where $a(M)$ and $b(M)$ are polynomials.

Also if possible, I would like to have $M**M=M^2$(and the same for $L$).

Any help/tips would be greatly apreciated.

Disclaimer: I'm thoroughly unfamiliar with NCAlgebra, but I thought this question was a good excuse to take a look. I have done a fair amount of monkeying around with NonCommutativeMultiply on my own.

First, notice that NCAlgebra removes the attribute Flat from NonCommutativeMultiply (in fact, all of NonCommutativeMultiply's attributes are removed).

Let's take a look at what actually happens in the evaluation of NCReplaceRepeated. We can query

?? NCReplaceRepeated

NCReplaceAll[NCReplacePrivateexpr_,NCReplacePrivaterule_]:=
ReplaceAll@@({NCReplacePrivateexpr,NCReplacePrivaterule}/.
NCReplacePrivateNCReplaceFlatRules)/.
NCReplacePrivateNCReplaceReverseFlatRules


If you're unfamiliar with packages and contexts, NCReplacePrivatesymbolName just means it's a 'private' symbol in the NCReplace package -- that is, a symbol the user doesn't usually need, and hence its name is hidden. (More properly, it's a symbol which belongs to a different Context, but I won't get into that.)

In any case, let's first look at the values of NCReplacePrivateNCReplaceFlatRules and NCReplacePrivateNCReplaceReverseFlatRules :

NCReplacePrivateNCReplaceFlatRules

{NonCommutativeMultiply -> NCReplacePrivateFlatNCMultiply}

NCReplacePrivateNCReplaceReverseFlatRules

{NCReplacePrivateFlatNCMultiply -> NonCommutativeMultiply}

? NCReplacePrivateFlatNCMultiply

Attributes[NCReplacePrivateFlatNCMultiply]={Flat,OneIdentity}

? NonCommutativeMultiply

(* No attributes mentioned *)


Ah, ok. First, note that before loading NCAlgebra, NonCommutativeMultiply had attributes {Flat, OneIdentity, Protected}. NCAlgebra (kind of) mentions this in the docs :

The reason is that making an operator Flat is a convenience that comes with a price: lack of control over execution and evaluation. Since NCAlgebra has to operate at a very low level this lack of control over evaluation is fatal. Indeed, making NonCommutativeMultiply have an attribute Flat will throw Mathematica into infinite loops in seemingly trivial noncommutative expression. Hey, email us if you find a way around that :)

If you're unsure what the Flat attribute does, the NCAlgebra docs have a good explanation in this context at the start of section 5.1.

As the package mentions, problems (apparently, though believably) occur when a symbol has both Flat attribute and NCAlgebra's built-in definitions for dealing with commutative/non-commutative symbols. One such rule is the one that pulls powers of t out of NonCommutativeMultiply :

L ** t^2 ** M

t^2 L ** M


The whole point is that this can't happen automatically in NCReplacePrivateFlatNCMultiply, because of the Flat attribute. Why does this matter? Because what NCReplaceRepeated is doing is precisely replacing all instances of NonCommutativeMultiply (both in the expression you're replacing and the replacement rules themselves) with NCReplacePrivateFlatNCMultiply, and then replacing back to NonCommutativeMultiply at the end.

Let's take a look at what happens if we do this process ourselves:

L ** M^2 /. NCReplacePrivateNCReplaceFlatRules

NCReplacePrivateFlatNCMultiply[L, M, M]

% /. (L ** M -> t^2 M ** L /. NCReplacePrivateNCReplaceFlatRules)

NCReplacePrivateFlatNCMultiply[ t^2 NCReplacePrivateFlatNCMultiply[M, L], M]

% /. NCReplacePrivateNCReplaceReverseFlatRules

t^2 M ** L ** M


We can see the issue in the second-to-last step: the t^2 prevents NCReplacePrivateFlatNCMultiply from flattening -- the flattening only occurs after converting back to NonCommutativeMultiply. This is the reason why applying NCReplaceRepeated a second time works -- everything is flattened out by the end of the first call, allowing the replacement to happen in the second call.

# What can we do about it?

## Quick and dirty

Note that

NCReplaceRepeated[L ** M ** M, A___ ** L ** M ** B___ :> t^2 A ** M ** L ** B]


t^4 M ** M ** L

works right away. Of course, this requires putting all your rules into such a 'non-flat' form manually. You could try to automate that, but the following method is hopefully more robust.

## More elegant solution

We can define our own function:

ClearAll@NCreallyReplaceRepeated
NCreallyReplaceRepeated[expr_, rule_] :=
FixedPoint[ NCReplaceRepeated[#, rule] &, expr]

NCreallyReplaceRepeated[L ** M ** M, L ** M -> t^2 M ** L]

t^4 M ** M ** L


### Small caveat

Note that the above involves doing the exact same ReplaceAll on the transformation rules themselves within each iteration of FixedPoint. Usually this is fine, though it could be the bottleneck for very long rules. To avoid this, I recommend instead:

ClearAll@NCreallyReplaceRepeated2
NCreallyReplaceRepeated2[expr_, rule_] :=
With[{ruleTrans = rule /. NCReplacePrivateNCReplaceFlatRules},
FixedPoint[
ReplaceAll[NCReplacePrivateNCReplaceReverseFlatRules]
@*(ReplaceRepeated[#, ruleTrans] &)
@*ReplaceAll[NCReplacePrivateNCReplaceFlatRules],
expr]
]

NCreallyReplaceRepeated2[L ** M ** M, L ** M -> t^2 M ** L]

t^4 M ** M ** L

• Thanks for your careful analysis of the problem. This is better dealt with by adding an additional rule to the private FlatNCMultiply. I have added that in the latest release of NCAlgebra. – Mauricio de Oliveira Nov 29 '17 at 17:19

• I am still having this issue in $5.0.4$ with NCRR. I am new to the package, though, so it might be on my end. – Elliot G Sep 2 '18 at 22:10