# Real Cayley, quaternion, and octonian algebras

References:

1. chapter 22 of Fulton and Harris, Representation Theory , Springer-Verlag, 1991
2. page 45 of R. Schafer, An introduction to non-associative algebras, Dover, 1994
3. section 6.3 of I. Kantor and A. Solodovnikov, Hypercomplex numbers , Springer-Verlag, 1989
4. some notes based on discussions with D. Bump.
cayley0.htm, by wdj, 5-14-98

> with(linalg):

`Warning, new definition for norm`

`Warning, new definition for trace`

The Cayley algebra associated to 3-space R3

> x1:=[x11,x12,x13]; y1:=[y11,y12,y13];
x2:=[x21,x22,x23]; y2:=[y21,y22,y23];
v1:=array(1..2,1..2,[[a1,x1],[y1,b1]]);
v2:=array(1..2,1..2,[[a2,x2],[y2,b2]]);

The above arrays v1, v2 will be called Cayley numbers (elements of the Cayley algebra associated to R^3). The procedure below shows how they are to be multiplied.

> multiply_cayley:=proc(A::array,B::array)
#assumes arrays are Cayley numbers
local a1,a2,b1,b2,x1,x2,y1,y2,C,
x11,x12,x13,y11,y12,y13,x21,x22,x23,y21,y22,y23;
a1:=A[1,1];
b1:=A[2,2];
x1:=A[2,1];
y1:=A[1,2];
a2:=B[1,1];
b2:=B[2,2];
x2:=B[2,1];
y2:=B[1,2];
C:=array(1..2,1..2,[[a1*a2+dotprod(x1,y2,`orthogonal`),expand(a1*x2+b2*x1)],[expand(a2*x1+b1*x2),b1*b2+dotprod(x2,y1,`orthogonal`)]]);
RETURN(evalm(C));
end:

For example:

> multiply_cayley(v1,v2);

The Cayley numbers have a conjugation

> conjugate_cayley:=proc(w::array)
#assumes array is a Cayley number
local w0,x,y,a,b;
a:=w[1,1]; b:=w[2,2];
x:=w[1,2]; y:=w[2,1];
w0:=array(1..2,1..2,[[a,y],[x,b]]);
RETURN(evalm(w0));
end:

An example:

> conjugate_cayley(v1);

The conjugation is not an anti-automorphism but conj(v1*v2) and conj(v2)*conj(v1) do have the same trace:

> equal(multiply_cayley(conjugate_cayley(v1),conjugate_cayley(v2)),conjugate_cayley(multiply_cayley(v2,v1)));

> trace(multiply_cayley(conjugate_cayley(v1),conjugate_cayley(v2)))-
trace(conjugate_cayley(multiply_cayley(v2,v1)));

The Cayley numbers have a norm :

> norm_cayley:=proc(w::array)
#assumes array is a Cayley number
local w0,w1;
w0:=conjugate_cayley(w);
w1:=multiply_cayley(w,w0);
RETURN(trace(w1));
end:

An example:

> norm_cayley(v1);

By the well-known polarization identity, one may create out of this norm a bilinear form on the Cayley numbers, given below. The exceptional Lie group G2 is the group of algebra automorphisms of the Cayley numbers preserving the following form.
The special orthogonal group SO(8) is the group of
vector space automorphisms of the Cayley numbers preserving this form. The cayley_basis command below returns an orthonormal basis with respect to this form.

> bilinearform_cayley:=proc(w1::array,w2::array)
#assumes arrays are Cayley numbers
local x1,y1,a1,b1,x2,y2,a2,b2,form;
a1:=w1[1,1]; b1:=w1[2,2];
x1:=w1[1,2]; y1:=w1[2,1];
a2:=w2[1,1]; b2:=w2[2,2];
x2:=w2[1,2]; y2:=w2[2,1];
form:=a1*a2+b1*b2+dotprod(x1,x2,`orthogonal`)+dotprod(y1,y2,`orthogonal`);
RETURN(form);
end:

An example:

> bilinearform_cayley(v1,v2);

A vector space basis for this algebra is provided by the following procedure:

> cayley_basis:=proc()
local e1,e2,e3,e4,e5,e6,e7,e8;
e1:=array(1..2,1..2,[[0,[1,0,0]],[[0,0,0],0]]);
e2:=array(1..2,1..2,[[0,[0,1,0]],[[0,0,0],0]]);
e3:=array(1..2,1..2,[[0,[0,0,1]],[[0,0,0],0]]);
e4:=array(1..2,1..2,[[0,[0,0,0]],[[1,0,0],0]]);
e5:=array(1..2,1..2,[[0,[0,0,0]],[[0,1,0],0]]);
e6:=array(1..2,1..2,[[0,[0,0,0]],[[0,0,1],0]]);
e7:=array(1..2,1..2,[[1,[0,0,0]],[[0,0,0],0]]);
e8:=array(1..2,1..2,[[0,[0,0,0]],[[0,0,0],1]]);
RETURN([evalm(e1),evalm(e2),evalm(e3),evalm(e4),evalm(e5),evalm(e6),evalm(e7),evalm(e8)]);
end:

> Cbasis:=cayley_basis():
for i from 1 to 8 do
e[i]:=Cbasis[i]:
od:

A multiplication table may be built. Here are some more examples:

> multiply_cayley(e[3],e[4]);
multiply_cayley(e[2],e[5]);
multiply_cayley(e[1],e[4]);

> cayley_multiplication_table:=array(1..9,1..9,[[C,seq(e[i],i=1..8)],
[e[1],0,0,0,e[8],0,0,0,0],
[e[2],0,0,0,0,e[8],0,0,0],
[e[3],0,0,0,0,0,e[8],0,0],
[e[4],e[7],0,0,0,0,0,e[4],e[1]],
[e[5],0,e[7],0,0,0,0,e[5],e[1]],
[e[6],0,0,e[7],0,0,0,e[6],e[2]],
[e[7],0,0,0,e[1],e[2],e[3],e[7],0],
[e[8],0,0,0,e[4],e[5],e[6],0,e[8]]]);

Quaternions :

We will need a formal complex conjugation routine (instead of MAPLE's conjugate).

> conjugate_complex:=proc(w)
#assumes w is a complex number
local w0,x,y,r,s,t,u;
s:=coeff(w,I); r:=w-I*s;
w0:=r-s*I;
RETURN(w0);
end:

For example:

> conjugate_complex(x+I*y);

>

> w1:=[r1+I*s1,t1+I*u1]; w2:=[r2+I*s2,t2+I*u2];

The above two numbers w1, w2 will be called quaternions , regarded as a+b*j, where a and b are complex and j is the usual unit quaternion j.

> multiply_quaternion:=proc(w1::list,w2::list)
#assumes lists w1, w2 are quaternion numbers
local r1,s1,t1,u1,r2,s2,t2,u2,w,x1,x2,y1,y2;
x1:=w1[1];y1:=w1[2];x2:=w2[1]; y2:=w2[2];
w:=[evalc(expand(x1*x2-y1*conjugate_complex(y2))),evalc(expand(conjugate_complex(x2)*y1+y2*x1))];
RETURN(w);
end:

An example:

> multiply_quaternion(w1,w2);

The unit quaternions 1, i, j, k:

> q1:=[1,0]; qi:=[I,0]; qj:=[0,1]; qk:=[0,I];

> multiply_quaternion(qi,qj);
multiply_quaternion(qj,qk);
multiply_quaternion(qk,qi);
multiply_quaternion(q1,qk);

Quaternions have a conjugation anti-automorphism (so conj(w1*w2)=conj(w2)*conj(w1)):

> conjugate_quaternion:=proc(w::list)
#assumes list is a quaternion number
local w0,x,y,r,s,t,u;
x:=w[1];s:=coeff(x,I); r:=x-I*s;
y:=w[2];u:=coeff(y,I); t:=y-I*u;
w0:=[r-s*I,-t-u*I];
RETURN(w0);
end:

An example:

> conjugate_quaternion(w1);

Like the complex numbers, there is also a norm (some may define the norm or absolute value as the square-root of the quantity defined by the following procedure):

> norm_quaternion:=proc(w::list)
#assumes list is a quaternion number
local w0,w1;
w0:=conjugate_quaternion(w);
w1:=multiply_quaternion(w,w0);
RETURN(op(1,w1));
end:

>

> norm_quaternion(w1);

Octonians :

The octonian algebra is isomorphic to the Cayley algebra.

> o1:=[[r11+I*s11,t11+I*u11],[r12+I*s12,t12+I*u12]];
o2:=[[r21+I*s21,t21+I*u21],[r22+I*s22,t22+I*u22]];

>

The numbers o1, o2 above are called octonians . They may be multiplied together but, unlike the quaternions and the complex numbers, the multiplication is non-associative .

> multiply_octonian:=proc(oo1::list,oo2::list)
#assumes lists are octonian numbers
local a,b,c,d,w;
a:=oo1[1];b:=oo1[2]; c:=oo2[1];d:=oo2[2];
w:=[evalc(expand(multiply_quaternion(a,c)-multiply_quaternion(conjugate_quaternion(d),b))),evalc(expand(multiply_quaternion(d,a)+multiply_quaternion(b,conjugate_quaternion(c))))];
RETURN(w);
end:

An example:

> multiply_octonian(o1,o2);

The procedure below gives a vector spave basis for the octonians:

> octonian_basis:=proc()
local e1,e2,e3,e4,e5,e6,e7,e8;
e1:=[[1,0],[0,0]];
e2:=[[I,0],[0,0]];
e3:=[[0,1],[0,0]];
e4:=[[0,I],[0,0]];
e5:=[[0,0],[1,0]];
e6:=[[0,0],[I,0]];
e7:=[[0,0],[0,1]];
e8:=[[0,0],[0,I]];
RETURN([e1,e2,e3,e4,e5,e6,e7,e8]);
end:

>

> Obasis:=octonian_basis():
for i from 1 to 8 do
f[i]:=Obasis[i]:
od:

There is a simple rule for multiplying the basis elements of the octonians given by the following diagram. Note f[1]=[1,0] is the identity element. This diagram below differs slightly from that in [FH].

Some examples:

> multiply_octonian(f[3],f[4])-f[2];
multiply_octonian(f[2],f[3])-f[4];
multiply_octonian(f[6],f[4])-f[7];

Except for f[1], the basis elements of the octonians anti-commute: f[i]*f[j]=-f[j]*f[i] as the following examples indicate:

> multiply_octonian(f[8],f[3])+multiply_octonian(f[3],f[8]);

> multiply_octonian(f[7],f[3])+multiply_octonian(f[3],f[7]);

> multiply_octonian(f[8],f[4])+multiply_octonian(f[4],f[8]);

> multiply_octonian(f[8],f[2])+multiply_octonian(f[2],f[8]);

The octonians have a conjugation anti-automorphism (this anti-automorphism property is verified below):

> conjugate_octonian:=proc(oo::list)
#assumes list is octonian number
local a,b,w;
a:=oo[1];b:=oo[2]; w:=[conjugate_quaternion(a),-b];
RETURN(w);
end;

> expand(multiply_octonian(conjugate_octonian(o1),conjugate_octonian(o2))-conjugate_octonian(multiply_octonian(o2,o1)));
The anti-automorphism property

An example:

> conjugate_octonian(f[8]);

Like the complex numbers, there is also a norm :

> norm_octonian:=proc(w::list)
#assumes list is a octonian number
local w0,w1;
w0:=conjugate_octonian(w);
w1:=multiply_octonian(w,w0);
RETURN(op(1,op(1,w1)));
end:

> norm_octonian(o1);

All these procedures are contained in the MAPLE text file cayley.mpl, which can be read into MAPLE using the read command.

Last updated 5-14-98