# 八元数の積をプログラムで確認

\vec{v}\vec{w}=-\underbrace{\vec{v}\cdot\vec{w}}_{内積}+\underbrace{\vec{v}×\vec{w}}_{外積}


シリーズの記事です。

この記事には関連記事があります。

# プログラム

Math7 に八元数の計算方法を教えて計算させます。

Math7.Octonion.fsx
namespace Math7

type octonion =
E | I | J | K | H of octonion

override x.ToString() =
match x with
|   E -> "1" | I -> "i" | J -> "j" | K -> "k"
| H E -> "h"
| H x -> string x + "_h"

member x.N =
match x with
| E -> 0 | I -> 1 | J -> 2 | K -> 3
| H x -> x.N + 4

member x.Next =
match x with
|   I -> J
|   J -> K
|   K -> I
| H x -> H x.Next
|   x -> x

static member (*)(a:octonion, b:octonion) =
match a, b with
|   x,   E            ->  1,   x  // i1 = i
|   E,   y            ->  1,   y  // 1i = i
|   x,   y when x = y -> -1,   E  // ii = -1
| H x, H E            -> -1,   x  // i_hh = -i
| H x, H y            -> y * x    // i_hj_h = ji
|   x, H E            ->  1, H x  // ih = i_h
|   x, H y when x = y -> -1, H E  // ii_h = -h
|   x, H y -> let c, z = y * x    // ij_h = (ji)h
c, H z
|   x,   y when x.Next = y        // ij = k
-> 1, y.Next
|   x,   y -> let c, z = y * x    // ji = -ij
-c, z

module Octonion =
let tests = testList()

let octs = [| E; I; J; K; H E; H I; H J; H K |]
let oct x = octs.[x]
let ijkh = function
| 0 -> ""
| x -> string (oct x)

let str es = es |> Seq.map ijkh |> Seq.filter ((<>) "") |> Term.strPower

let prod es =
let n, e = es |> Seq.fold (fun (n, x) y ->
let m, z = oct x * oct y
n * m, z.N) (1, E.N)
term(n, [], if e = E.N then [] else [e])

let conj = List.map <| fun (t:term) ->
if t.E.IsEmpty then t else -1 * t

let showProd title =
Term.showProd title "" str prod id Term.byIndexSign

OctonionProduct.fsx
#load "Math7.Octonion.fsx"
open Math7

let a = [for i in [1..7] -> term(1, [sprintf "a_%d" i], [i])]
let b = [for i in [1..7] -> term(1, [sprintf "b_%d" i], [i])]
let aa = term(1, ["a_0"], [])::a
let bb = term(1, ["b_0"], [])::b
Octonion.showProd "## 積（虚部）" (fun _ -> true) a b
Octonion.showProd "## 積（実部＋虚部）" (fun _ -> true) aa bb
Octonion.showProd "## 二乗（虚部）" (fun _ -> true) a a
Octonion.showProd "## 二乗（実部＋虚部）" ((=) 1) aa aa
Octonion.showProd "## ノルムの二乗" (fun _ -> true) (Octonion.conj aa) aa


## 積（虚部）

\begin{align}
&(a_1i+a_2j+a_3k+a_4h+a_5i_h+a_6j_h+a_7k_h)(b_1i+b_2j+b_3k+b_4h+b_5i_h+b_6j_h+b_7k_h) \\
&=a_1i(b_1i+b_2j+b_3k+b_4h+b_5i_h+b_6j_h+b_7k_h) \\
&=a_1b_1\underbrace{i^2}_{-1}+a_1b_2\underbrace{ij}_{k}+a_1b_3\underbrace{ik}_{-j}+a_1b_4\underbrace{ih}_{i_h}+a_1b_5\underbrace{ii_h}_{-h}+a_1b_6\underbrace{ij_h}_{-k_h}+a_1b_7\underbrace{ik_h}_{j_h} \\
&=-(a_1b_1+a_2b_2+a_3b_3+a_4b_4+a_5b_5+a_6b_6+a_7b_7) \\
\end{align}


$i$ の係数を $(a_2b_3-a_3b_2)+(a_4b_5-a_5b_4)+(a_7b_6-a_6b_7)$ のように三分割して見れば、3次元の外積が三重に入ったような形をしていることに気付きます。$i$ は3つの部分空間に属しているため、それぞれで外積としての成分を持つためです。

また、係数は基底（$i$ は1番目）を除いた添字（2,3,4,5,6,7）が使われており、相補的な関係にあることが分かります。他の項も同様です。これは3次元の外積と共通する特徴です。

\begin{align}
&(a_1i+a_2j+a_3k)(b_1i+b_2j+b_3k) \\
&=-(a_1b_1+a_2b_2+a_3b_3) \\
\end{align}


(a_1i)(b_1i)=-(a_1b_1)


## 積（実部＋虚部）

\begin{align}
&(a_0+a_1i+a_2j+a_3k+a_4h+a_5i_h+a_6j_h+a_7k_h)(b_0+b_1i+b_2j+b_3k+b_4h+b_5i_h+b_6j_h+b_7k_h) \\
&=a_0(b_0+b_1i+b_2j+b_3k+b_4h+b_5i_h+b_6j_h+b_7k_h) \\
&=a_0b_0+a_0b_1i+a_0b_2j+a_0b_3k+a_0b_4h+a_0b_5i_h+a_0b_6j_h+a_0b_7k_h \\
&=(a_0b_0-a_1b_1-a_2b_2-a_3b_3-a_4b_4-a_5b_5-a_6b_6-a_7b_7) \\
\end{align}


この計算をスカラーとベクトルの和の積と見なせば、ごく普通の掛け算として構造が見えて来ます。

\begin{align}
&(a_0+\vec{a})(b_0+\vec{b}) \\
&=a_0b_0+a_0\vec{b}+\vec{a}b_0+\vec{a}\vec{b} \\
&=\underbrace{a_0b_0}_{スカラー積}+\underbrace{a_0\vec{b}+b_0\vec{a}}_{スカラー倍}-\underbrace{\vec{a}\cdot\vec{b}}_{内積}+\underbrace{\vec{a}×\vec{b}}_{外積}
\end{align}


$i$ の項を $a_0(b_1)i+b_0(a_1)i+(a_2b_3-a_3b_2+a_4b_5-a_5b_4+a_7b_6-a_6b_7)i$ と分離すれば、ベクトルのスカラー倍と外積が重なっていることが確認できます。

この解釈では実部はベクトルの成分ではなく、ベクトルとして扱われるのは虚部の7次元です。実部まで含めた8次元ベクトルとしてうまく解釈できるかは不明です。

## 二乗（虚部）

\begin{align}
&(a_1i+a_2j+a_3k+a_4h+a_5i_h+a_6j_h+a_7k_h)^2 \\
&=a_1i(a_1i+a_2j+a_3k+a_4h+a_5i_h+a_6j_h+a_7k_h) \\
&=a_1^2\underbrace{i^2}_{-1}+a_1a_2\underbrace{ij}_{k}+a_1a_3\underbrace{ik}_{-j}+a_1a_4\underbrace{ih}_{i_h}+a_1a_5\underbrace{ii_h}_{-h}+a_1a_6\underbrace{ij_h}_{-k_h}+a_1a_7\underbrace{ik_h}_{j_h} \\
&=-(a_1^2+a_2^2+a_3^2+a_4^2+a_5^2+a_6^2+a_7^2) \\
\end{align}


## 二乗（実部＋虚部）

\begin{align}
&(a_0+a_1i+a_2j+a_3k+a_4h+a_5i_h+a_6j_h+a_7k_h)^2 \\
&=a_0(a_0+a_1i+a_2j+a_3k+a_4h+a_5i_h+a_6j_h+a_7k_h) \\
&=a_0^2+a_0a_1i+a_0a_2j+a_0a_3k+a_0a_4h+a_0a_5i_h+a_0a_6j_h+a_0a_7k_h \\
&=(a_0^2-a_1^2-a_2^2-a_3^2-a_4^2-a_5^2-a_6^2-a_7^2) \\
\end{align}


## ノルムの二乗

ノルムだけ見れば、実部を含めてユークリッド空間の8次元ベクトルとして扱えます。

\begin{align}
&(a_0-a_1i-a_2j-a_3k-a_4h-a_5i_h-a_6j_h-a_7k_h)(a_0+a_1i+a_2j+a_3k+a_4h+a_5i_h+a_6j_h+a_7k_h) \\
&=a_0(a_0+a_1i+a_2j+a_3k+a_4h+a_5i_h+a_6j_h+a_7k_h) \\