For example, I would like to define the algebra of quaternions. I coded something like
Unprotect[i, j, k]; ClearAll[i, j, k]
i /: i ** i := -1;
i /: i ** j := k;
i /: j ** i = -k;
i /: i ** k := -j;
i /: k ** i = j;
j /: j ** j := -1;
j /: j ** k := i;
j /: k ** j := -i;
k /: k ** k := -1;
Protect[i, j, k];
ExpandNCM[(h : NonCommutativeMultiply)[a___, b_Plus, c___]] :=
Distribute[h[a, b, c], Plus, h, Plus, ExpandNCM[h[##]] &];
ExpandNCM[(h : NonCommutativeMultiply)[a___, b_Times, c___]] :=
Most[b] ExpandNCM[h[a, Last[b], c]];
ExpandNCM[a_] := ExpandAll[a];
QQ = Collect[ExpandNCM[#], {i, j, k}] &;
However, I got two different results when calculating
(a i + b j + c k) ** (d i + e j + f k) // QQ
(a i + b j + c k) ** (l i + m j + n k) // QQ
The first one gave the expected result
k (a e-b d)+j (c d-a f)-a d+i (b f-c e)-b e-c f
while the second one gave a weird answer
i (a i**l+b j**l+c k**l)+j (a i**m+b j**m+c k**m)+k (a i**n+b j**n+c k**n)
I hope the NonCommutativeMultiply **
only operates on those i,j,k
. I don't know where the problem is.
I also want to know if there is a handy way to define a new algebra?
Updated
Now the algebra has been set up for +, *, **
but not Power
.
Here is the code
Unprotect[i, j, k]; ClearAll[i, j, k, ijkQ, ExpandNCM, Qconj, Qreal, \
Qimag]
i /: i ** i := -1;
i /: i*i := -1;
i /: i ** j := k;
i /: j ** i = -k;
i /: i ** k := -j;
i /: k ** i = j;
j /: j ** j := -1;
j /: j*j := -1;
j /: j ** k := i;
j /: k ** j := -i;
k /: k ** k := -1;
k /: k*k := -1;
i /: Qconj[i] := -i;
j /: Qconj[j] := -j;
k /: Qconj[k] := -k;
Protect[i, j, k];
Qconj[a_: 0] := a /; FreeQ[a, i | j | k];
Qconj[(b_: 1)*(q : i | j | k)] := b*Qconj[q] /; FreeQ[b, i | j | k];
Qconj[a_ + b_] := Qconj[a] + Qconj[b];
Qreal := Select[# + i, (FreeQ[#, i | j | k] &)] &;
Subscript[Qimag, x_] := ({0}~Join~
Cases[{#}, (a : (_?(FreeQ[#, i | j | k] &)) : 1)*x :> a,
Infinity])[[-1]] &
ExpandNCM[(h : NonCommutativeMultiply)[a___, b_Plus, c___]] :=
Distribute[h[a, b, c], Plus, h, Plus, ExpandNCM[h[##]] &];
ExpandNCM[(h : NonCommutativeMultiply)[a___,
b_?(FreeQ[#, i | j | k] &)*(q : i | j | k), c___]] :=
b*ExpandNCM[h[a, q, c]];
ExpandNCM[(h : NonCommutativeMultiply)[a___,
b_?(FreeQ[#, i | j | k] &), c___]] := b*ExpandNCM[h[a, c]];
ExpandNCM[(h : (Times | Plus))[a___, b_NonCommutativeMultiply,
c___]] := h[a, c, ExpandNCM[b]];
ExpandNCM[(h : NonCommutativeMultiply)[a_: 1]] := a;
ExpandNCM[a_] := ExpandAll[a];
QQ = Collect[ExpandNCM[#], {i, j, k}] &;
Now the problem is how to set up the rules for Power
, such as Exp[]
, Log[]
and Power[]
. For example, I want to define Power[q,n]
as q**q** ... **q
and then use it to define Exp[q]
. How should I do?
Note that the algebra of quaternions here is just an example. What I want is to define the rules for the algebra and let the Mathematica do the calculations. These rules will be changed.
Quaternion[...]
. this would be analogous toComplex[...]
(Note thatFullForm[a+b I]
isPlus[a, Times[Complex[0, 1], b]]
and justFullForm[I]
isComplex[0,1]
. Then you would define your operations for pairs of Quaternion elements. For your special symbols, you could definei = Quaternion[0,1,0,0]
and similarly for j and k. $\endgroup$Format
to provide a friendly display form for yourQuaternion[...]
s. $\endgroup$FullForm[a+b I]
isPlus[a, Times[Complex[0, 1], b]]
and notComplex[a,b]
becausea
andb
could be complex themselves.FullForm[1+2*I]
isComplex[1,2]
as expected because 1 and 2 are real. $\endgroup$