1.3 A Short Tutorial

NCAlgebra is a Mathematica package which allows one to do noncommutative algebraic computations. We will begin by presenting some calculations done with our package which should give some idea of what may be accomplished with NCAlgebra. We suggest that the reader later do these computations for himself with our package when it has been properly installed since it will provide a tutorial as well as an illustration.

To begin start Mathematica and load NCAlgebra.m or NCGB.m as shown in Section 1.2

In[1] << NC‘  
In[2] << NCAlgebra‘

The following examples are independent of each other, however they may be executed in one continuous session. At present, single-letter lower case variables are noncommutative by default and all others are commutative by default. In our package ** denotes noncommutative multiply.

In[3]:= a ** b - b ** a  
Out[3]= a ** b - b ** a  
 
In[4]:= A ** B - B ** A  
Out[4]= 0  
 
In[5]:= A ** b - b ** a  
Out[5]= A b - b ** a  
 
In[6]:= CommuteEverything[a ** b - b ** a]  
Out[6]= 0  
 
In[7]:= SetNonCommutative[A, B]  
Out[7]= {False, False}  
 
In[8]:= A ** B - B ** A  
Out[8]= A ** B - B ** A  
 
In[9]:= SetNonCommutative[A];  
In[10]:= SetCommutative[B];  
In[11]:= A ** B - B ** A  
Out[11]= 0

SNC is an alias for SetNonCommutative. So, SNC can be typed rather than the longer SetNonCommutative.

In[12]:= SNC[A];  
In[13]:= A ** a - a ** A  
Out[13]= -a ** A + A ** a  
 
In[14]:= SetCommutative[v];  
In[15]:= v ** b  
Out[15]= b v

Here is how to use NCAlgebra to manipulate and simplify expressions. tp[x] denotes the transpose of an element x, and aj[x] denotes the adjoint of an element x. Note that the properties of transposes and adjoints that everyone constantly uses are built-in.

In[16]:= NCCollect[a ** x + b ** x, x]  
Out[16]= (a + b) ** x  
 
In[17]:= NCExpand[(a + b) ** x]  
Out[17]= a ** x + b ** x  
 
In[18]:= NCCollect[tp[x] ** a ** x + tp[x] ** b ** x + z, {x, tp[x]}]  
Out[18]= z + tp[x] ** (a + b) ** x

You can compute directional derivatives and gradients.

In[19]:= DirectionalD[x ** x, x, h]  
Out[19]= h ** x + x ** h  
 
In[20]:= DirectionalD[tp[x] ** x + tp[x] ** A ** x + m ** x, x, h]  
Out[20]= m ** h + tp[h] ** x + tp[x] ** h + tp[h] ** A ** x + tp[x] ** A ** h  
 
In[21]:= (* In the next line, A is noncommutative and x represents a column vector*)  
In[22]:= Grad[tp[x] ** x + tp[x] ** A ** x + m ** x, x]  
Grad::limited: Grad gives correct answers only for a limited class of functions!  
Out[22]= 2 x + A ** x + tp[A] ** x + tp[m]

WARNING: Grad is trustworthy only on certain quadratics.

Rules can be used to modify expressions:

In[23]:= Substitute[x ** a ** b, a ** b -> c]  
Out[23]= x ** c  
 
In[24]:= Substitute[ tp[b ** a] + b ** a, b ** a -> p]  
Out[24]= p + tp[a] ** tp[b]  
 
In[25]:= SubstituteSymmetric[tp[b] ** tp[a] + w + a ** b, a ** b->c]  
Out[25]= c + w + tp[c]

WARNING: The Mathematica substitute commands \.    and \ :> are not reliable in NCAlgebra, so you must use our Substitute command.

The multiplicative identity is denoted Id in the program. At the present time, Id is set to 1. A element A may have an inverse, which will be denoted by inv[A], of it may have a left or right inverse, denoted inv[A] and invR[A], respectively.

In[26]:= MatMult[{{a, b}, {c, d}}, {{d, 2}, {e, 3}}]  
Out[26]= {{a ** d + b ** e, 2 a + 3 b}, {c ** d + d ** e, 2 c + 3 d}}  
 
In[27]:= tp[a ** b]  
Out[27]= tp[b] ** tp[a]  
 
In[28]:= tp[5]  
Out[28]= 5  
 
In[29]:= tp[2 + 3 I]  
Out[29]= 2 + 3 I  
 
In[30]:= tp[a]  
Out[30]= tp[a]  
 
In[31]:= tp[a + b]  
Out[31]= tp[a] + tp[b]  
 
In[32]:= tp[6 x]  
Out[32]= 6 tp[x]  
 
In[33]:= tp[tp[a]]  
Out[33]= a  
 
In[34]:= aj[5]  
Out[34]= 5  
 
In[35]:= aj[2 + 3 I]  
Out[35]= 2 - 3 I  
 
In[36]:= aj[a]  
Out[36]= aj[a]  
 
In[37]:= aj[a + b]  
Out[37]= aj[a] + aj[b]  
 
In[38]:= aj[6 x]  
Out[38]= 6 aj[x]  
 
In[39]:= aj[aj[a]]  
Out[39]= a  
 
In[40]:= Id  
Out[40]= 1  
 
In[41]:= inv[a ** b]  
Out[41]= inv[b] ** inv[a]  
 
In[42]:= inv[a] ** a  
Out[42]= 1  
 
In[43]:= a ** inv[a]  
Out[43]= 1  
 
In[44]:= a ** b ** inv[b]  
Out[44]= a  
 
In[45]:= invL[a] ** a  
Out[45]= 1  
 
In[46]:= a ** invR[a]  
Out[46]= 1  
 
In[47]:= a ** invL[a]  
Out[47]= a ** invL[a]  
 
In[48]:= invR[a] ** a  
Out[48]= invR[a] ** a

More extensive simplification can be obtained with NCSimplifyRational:

In[49]:= f1 = 1 + inv[d] ** c ** inv[S - a] ** b - inv[d] ** c ** \  
     inv[S - a + b ** inv[d] ** c] ** b - inv[d] ** c ** \  
     inv[S - a + b ** inv[d] ** c] ** b ** inv[d] ** c ** \  
     inv[S - a] ** b;  
In[50]:= NCSimplifyRational[f1]  
Out[50]= 1  
 
In[51]:= f2 = inv[1 + 2 a] ** a;  
In[52]:= NCSimplifyRational[f2]  
         1   inv[1 + 2 a]  
Out[52]= - - ------------  
         2        2

NCSR is the alias for NCSimplifyRational.

In[53]:= f3 = a ** inv[1 - a];  
In[54]:= NCSR[f3]  
Out[54]= -1 + inv[1 - a]  
 
In[55]:= f4 = inv[1 - b ** a] ** inv[a];  
In[56]:= NCSR[f4]  
Out[56]= inv[a] + b ** inv[1 - a ** b]

There is also a very limited NCSolve. Please consider using NCGB for serious equation solving.

In[57]:= NCSolve[a ** x == b, x]  
Out[57]= {x -> inv[a] ** b}

Note: NCSolve applies to some linear equations in only one unknown.