Edited at

四元数と行列で見る内積と外積の「内」と「外」

More than 1 year has passed since last update.

四元数を行列で計算すれば内積や外積の「内」と「外」が視覚的に分かることに気付いたのでメモします。最後に行列を生成する簡単なプログラムを掲載します。

【注】歴史的な由来は未確認です。

シリーズの記事です。


  1. 多項式の積を計算

  2. 外積と愉快な仲間たち

  3. ユークリッド空間のホッジ双対とバブルソート

  4. 四元数を作ろう

  5. 四元数と行列で見る内積と外積の「内」と「外」 ← この記事

  6. 八元数を作ろう

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

  8. 外積の成分をプログラムで確認

  9. 多元数の積の構成

  10. 十六元数を作ろう

関連するコードをまとめたリポジトリです。

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


四元数

複素数 $a+bi$ を二元数と捉えた場合、虚数の種類を増やして $a+bi+cj+dk$ としたのが四元数です。

$i, j, k$ はそれぞれ別の虚数で、以下の関係があります。

i^2=j^2=k^2=ijk=-1 \\

ij=-ji=k,\ jk=-kj=i,\ ki=-ik=j

※ 詳細は四元数を作ろうを参照してください。


行列による乗積表

$i,j,k$ の積は乗積表として表形式にまとめられますが、ここでは行列で示します。

\begin{align}

\left(\begin{matrix} i \\ j \\ k \end{matrix}\right)
\left(\begin{matrix} i & j & k \end{matrix}\right)
&=\left(\begin{matrix} ii & ij & ik \\ ji & jj & jk \\ ki & kj & kk \end{matrix}\right) \\
&=\left(\begin{matrix} -1 & k & -j \\ -k & -1 & i \\ j & -i & -1 \end{matrix}\right)
\end{align}

※ この種のベクトル計算を直積と呼びます。詳細は外積と愉快な仲間たちを参照してください。


3次元ベクトル

虚数 $i,j,k$ を3次元ベクトル空間の基底だと考えれば、四元数の虚部 $ai+bj+ck$ は3次元ベクトルだと見なせます。

ai+bj+ck\mapsto\left(\begin{matrix} a \\ b \\ c \end{matrix}\right)

※ 実部は無視します。


内積と外積

2本のベクトルを四元数で表して掛け算します。

\begin{align}

&(ai+bj+ck)(di+ej+fk) \\
&=ai(di+ej+fk) \\
&\quad +bi(di+ej+fk) \\
&\quad +cj(di+ej+fk) \\
&=ad\underbrace{ii}_{-1}+ae\underbrace{ij}_{k}+af\underbrace{ik}_{-j} \\
&\quad +bd\underbrace{ji}_{-k}+be\underbrace{jj}_{-1}+bf\underbrace{jk}_{i} \\
&\quad +cd\underbrace{ki}_{j}+ce\underbrace{kj}_{-i}+cf\underbrace{kk}_{-1} \\
&=-\underbrace{(ad+be+cf)}_{内積} \\
&\quad +\underbrace{(bf-ce)i+(cd-af)j+(ae-bd)k}_{外積}
\end{align}

実部が内積のマイナス、虚部が外積となります。

\begin{align}

内積 &\left(\begin{matrix}a\\b\\c\end{matrix}\right)\cdot\left(\begin{matrix}d\\e\\f\end{matrix}\right)=ad+be+cf \\
外積 &\left(\begin{matrix}a\\b\\c\end{matrix}\right)×\left(\begin{matrix}d\\e\\f\end{matrix}\right)=\left(\begin{matrix}bf-ce\\cd-af\\ae-bd\end{matrix}\right)
\end{align}

※ 内積がマイナスになっている点については、四元数が先にあって内積の概念が確立されたため、初期の内積は四元数と同じ符号で扱われていたそうです。符号にマイナスが付かないように修正したクリフォード代数というものがあります。詳細は外積と愉快な仲間たちを参照してください。

ここまではよくある説明です。


行列で計算

同じ計算を行列の二次形式でやってみます。

\begin{align}

&(ai+bj+ck)(di+ej+fk) \\
&=\left(\begin{matrix} i & j & k \end{matrix}\right)
\left(\begin{matrix} a \\ b \\ c \end{matrix}\right)
\left(\begin{matrix} d & e & f \end{matrix}\right)
\left(\begin{matrix} i \\ j \\ k \end{matrix}\right) \\
&=\left(\begin{matrix} i & j & k \end{matrix}\right)
\left(\begin{matrix} ad & ae & af \\ bd & be & bf \\ cd & ce & cf \end{matrix}\right)
\left(\begin{matrix} i \\ j \\ k \end{matrix}\right) \\
&=-(ad+be+cf) \\
&\quad +(bf-ce)i+(cd-af)j+(ae-bd)k
\end{align}

ここで3行目中央の行列に注目します。

\left(\begin{matrix}

\underbrace{ad}_{内} & \underbrace{ae}_{外} & \underbrace{af}_{外} \\
\underbrace{bd}_{外} & \underbrace{be}_{内} & \underbrace{bf}_{外} \\
\underbrace{cd}_{外} & \underbrace{ce}_{外} & \underbrace{cf}_{内}
\end{matrix}\right)

内側が内積で、外側が外積の成分です!


プログラム

行列を記述するのは大変なので、プログラムで生成してみました。(リポジトリ


QuaternionProduct.fsx

open System

let matrix m =
printfn @"\left(\begin{matrix}"
m |> Seq.map (String.concat " & ")
|> String.concat (@" \\" + Environment.NewLine)
|> printfn "%s"
printfn @"\end{matrix}\right)"

let v = [["a"]; ["b"]; ["c"]]
let w = [["d" ; "e" ; "f"]]

matrix v
matrix w
printfn "="
v
|> Seq.mapi (fun i r ->
w.[0] |> Seq.mapi (fun j c ->
if i = j then "内" else "外"
|> sprintf @"\underbrace{%s%s}_{%s}" r.[0] c))
|> matrix


\left(\begin{matrix}

a \\
b \\
c
\end{matrix}\right)
\left(\begin{matrix}
d & e & f
\end{matrix}\right)
=
\left(\begin{matrix}
\underbrace{ad}_{内} & \underbrace{ae}_{外} & \underbrace{af}_{外} \\
\underbrace{bd}_{外} & \underbrace{be}_{内} & \underbrace{bf}_{外} \\
\underbrace{cd}_{外} & \underbrace{ce}_{外} & \underbrace{cf}_{内}
\end{matrix}\right)