On Tue, 8 Jul 1997, Marlies Brinksma wrote:
> Dear Carl,
>
> ...
>
> > > Times[4, Op[1,t],NonCommutativeMultiply[Op[2,v],Op[2,x]],Op[3,a],Op[6,s]]
> > > ^
> > > ... |
>
> I think you've missed one ] right behind Op[2,x]... ;)
>
> ...
>
Hi Marlies,
You're absolutely right. So, instead, how about the following approach.
Unprotect[NonCommutativeMultiply];
Clear[NonCommutativeMultiply];
Default[NonCommutativeMultiply]:=1;
Op[n_,a_] ** Op[m_,b_] := Op[m,b] Op[n,a] /; (n=!=m)
a_ ** b_?NumberQ := a b
b_?NumberQ ** a_ := a b
Op[n_,a_] ** (Op[n_,b_]**c_. d_) := Op[n,a]**Op[n,b]**c d
(Op[n_,b_]**c_. d_) ** Op[n_,a_] := Op[n,b]**c**Op[n,a] d
(Op[n_,a_]**c_. d_) ** (Op[n_,b_]**e_. f_) := (Op[n,a]**c**Op[n,b]**e d)**f
a_Times ** b_ := a b
b_ ** a_Times := a b
Protect[NonCommutativeMultiply];
Some comments about the above definitions.
a) The method works as follows:
1) First, absorb commuting quantities under a Times[ ] head.
2) Then, in adjacent expressions, collect Ops with the same index.
3) When there are no more Ops with the same index, then its okay
to absorb adjacent expressions under a common Times[ ] head.
b) You can choose as a default 1 (as above) or Sequence[]. The choice 1 is
clearer, but the choice Sequence[] is marginally faster.
c) You can avoid using defaults by adding some more definitions, e.g.,
Op[n_,a_] ** (Op[n_,b_] d_) := Op[n,a]**Op[n,b] d
Op[n_,a_] ** (Op[n_,b_]**c_ d_) := Op[n,a]**Op[n,b]**c d
d) If you have commuting quantities which are more complex than numbers,
change the NumberQ test appropriately.
e) The order of definitions is important.
f) There is something I don't understand about the way mma is handling the
first 3 definitions which causes it to exercise these definitions much
more often then necessary. It may have something to do with using a
default, which is why I suggested how you could avoid using a default.
I believe this accomplishes what you asked for. Good luck!
Carl Woll