行列のメモ-

\documentclass{jsbook}

\usepackage{amsmath,amssymb}
\usepackage{bm}
%\usepackage{graphicx}
\usepackage{ascmac}
\usepackage[dvips]{graphicx}
\usepackage{graphicx}
\usepackage{bigdelim,multirow}
\usepackage{amsmath,amsthm,amssymb,cases}
\usepackage{ascmac}
\usepackage{eclbkbox}
\usepackage{wrapfig}
\usepackage{listings, jlisting}
\usepackage[dvips,usenames]{color}
\usepackage{makeidx}
\usepackage{url}
\usepackage[dvipdfmx,setpagesize=false]{hyperref}
\SweaveOpts{eps=TRUE}

\lstdefinestyle{MyFrame}{backgroundcolor=\color{green},frame=shadowbox}
\lstdefinestyle{MyC++Style} {language=C++,style=MyFrame,frame=none}
\lstset{
    language=R,
    basicstyle=\ttfamily,
    backgroundcolor={\color[gray]{.85}},
    keywordstyle=\color{blue}\bfseries,
}

\begin{document}

\chapter{行列}\label{Matrix}
\section{行列とは}
行列は数値を長方形に並べたもの。
$n$$m$列の行列は$n\times m$行列とも言い、次のように書く。
\begin{equation*}
  A_{nm} = \begin{pmatrix}
        a_{11} & \ldots & a_{1m} \\
        \vdots & \ddots & \vdots \\
        a_{n1} & \ldots & a_{nm}
      \end{pmatrix}
\end{equation*}
$n,m=1,2,...$であるから
$1\times 1$行列は次の通りで、これは行列とみなしてもよいが、ただの数値とみなしてもよい。
\begin{equation*}
  A_{11} = \begin{pmatrix}
        a_{11}\\
      \end{pmatrix}
\end{equation*}
ただの数値はスカラー値と呼ぶこともある。
行列が行列らしさを発揮するのは行も列も複数のときなので、「行列らしさ」の感じられるもっとも小さい行列は、というと、$2 \times 2$行列となる。
\begin{equation*}
  A_{22} = \begin{pmatrix}
        a_{11} & a_{11} \\
        a_{21} & a_{22}
      \end{pmatrix}
\end{equation*}
\section{行列の使い方}
\subsection{影響しあう関係〜推移行列}
2種類の生物X,Yが居て、Xは自然増するがYに捕食され、
YはXが居れば、それを捕食して増加するが、放っておけば減少するとする。
そのような関係が1年ごとに繰り返されると、X,Yの頭数はどう変わるかを、
行列を使ってシミュレーションしてみる。
第i年のX,Yの頭数を$x(i),y(i)$と書くことにする。
ここで$k_x,k_{xy},k_{yx},k_y$は係数で、Xの自然増を表す$k_x$は1より大、
YによるXの捕食を表す$k_{xy}$は負、Xに依存するYの増加を表す$k_{yx}$は正、
Yの自然減を表す$k_{y}$は1より小さい正の数であって、関係式は以下の通り。
\begin{eqnarray*}
x(i+1) &=& k_x \times x(i) + k_{xy} \times y(i)\\
y(i+1) &=& k_{yx} \times x(i) + k_y \times y(i)
\end{eqnarray*}
このとき4個の$k_*$の値を$2 \times 2$行列で表せば
\begin{equation*}
  K = \begin{pmatrix}
        k_x & x_{xy} \\
        k_{yx} & k_y
      \end{pmatrix}
\end{equation*}
となり、
\begin{equation*}
\begin{pmatrix}
 x(i+1)\\
 y(i+1)
\end{pmatrix}
= K 
\begin{pmatrix}
 x(i)\\
 y(i)
\end{pmatrix}
\end{equation*}
Rを使ってシミュレーションしてみる。ある状態に収束する様子が見て取れる。
\begin{lstlisting}
n.year <- 50
xy <- matrix(0,n.year,2)
K <- matrix(c(1.1,-0.2,0.1,0.8),byrow=TRUE,2,2)
xy[1,] <- c(100,5)
for(i in 2:n.year){
	xy[i,] <- K %*% xy[i-1,]
}
matplot(1:n.year,xy,type="l")
\end{lstlisting}
\begin{breakbox}
<<fig=TRUE>>=
n.year <- 50
xy <- matrix(0,n.year,2)
K <- matrix(c(1.1,-0.2,0.1,0.8),byrow=TRUE,2,2)
xy[1,] <- c(100,5)
for(i in 2:n.year){
	xy[i,] <- K %*% xy[i-1,]
}
matplot(1:n.year,xy,type="l")
@
\end{breakbox}
少し変えてみよう。

\subsection{回転・拡縮〜3次元画像処理}
\subsubsection{2次元の回転と拡縮}
適当な形を作ってみる。
\begin{lstlisting}
n.pt <- 10000
t <- seq(from = 0, to = 1, length = n.pt) * 2 * pi
t <- t[-1]
R <- rep(0,length(t))
ss <- rep(1,length(t))
s <- c(0,2*pi,runif(sample(3:8,1)) * 10-5)
for(j in 1:length(s)){
	ss <- ss * (t-s[j])^2
}
R <- R + runif(1) * ss 
t.2 <- c(t,t[1])
R.2 <- c(R,R[1])
R.2 <- (R.2 - min(R.2))/(max(R.2)-min(R.2))+1
xlim <- ylim <- range(X)
plot(R.2*cos(t.2),R.2*sin(t.2),cex=0.1)
\end{lstlising}
\begin{breakbox}
<<fig=TRUE>>=
n.pt <- 10000
t <- seq(from = 0, to = 1, length = n.pt) * 2 * pi
t <- t[-1]
R <- rep(0,length(t))
ss <- rep(1,length(t))
s <- c(0,2*pi,runif(sample(3:8,1)) * 10-5)
for(j in 1:length(s)){
	ss <- ss * (t-s[j])^2
}
R <- R + runif(1) * ss 
t.2 <- c(t,t[1])
R.2 <- c(R,R[1])
R.2 <- (R.2 - min(R.2))/(max(R.2)-min(R.2))+1
X <- cbind(R.2*cos(t.2),R.2*sin(t.2))
xlim <- ylim <- range(X)
plot(X,cex = 0.1,xlim=xlim,ylim=ylim)
@
\end{breakbox}
これを回転させるには、
\begin{equation*}
  M = \begin{pmatrix}
        \cos{\theta} & -\sin{\theta} \\
        \sin{\theta} & \cos{\theta}
      \end{pmatrix}
\end{equation*}
を各点の座標にかけてやればよい。
\begin{equation*}
M v
\end{equation*}
\begin{lstlisting}
theta <- pi/3
M <- matrix(c(cos(theta),-sin(theta),sin(theta),cos(theta)),byrow=TRUE,2,2)
X.rot <- t(M %*% t(X))
xlim <- ylim <- range(c(X,X.rot))
plot(X,type="l",cex = 0.1,xlim=xlim,ylim=ylim)
points(X.rot,cex=0.1,col=2)
\end{lstlisting}
\begin{breakbox}
<<fig=TRUE>>=
theta <- pi/3
M <- matrix(c(cos(theta),-sin(theta),sin(theta),cos(theta)),byrow=TRUE,2,2)
X.rot <- t(M %*% t(X))
xlim <- ylim <- range(c(X,X.rot))
plot(X,cex = 0.1,xlim=xlim,ylim=ylim)
points(X.rot,cex=0.1,col=2)
@
\end{breakbox}
これをx,y軸方向に$Lx,Ly$倍するには
\begin{equation*}
  L = \begin{pmatrix}
        Lx & 0 \\
        0 & Ly
      \end{pmatrix}
\end{equation*}
を各点の座標にかけてやればよい。
\begin{equation*}
L v
\end{equation*}

\begin{lstlisting}
Lx <- 2
Ly <- 0.5
L <- matrix(c(Lx,0,0,Ly),byrow=TRUE,2,2)
X.mult <- t(L %*% t(X))
xlim <- ylim <- range(c(X,X.rot,X.mult))
plot(X,cex = 0.1,xlim=xlim,ylim=ylim)
points(X.rot,cex=0.1,col=2)
points(X.mult,cex=0.1,col=3)
\end{lstlisting}
\begin{breakbox}
<<fig=TRUE>>=
Lx <- 2
Ly <- 0.5
L <- matrix(c(Lx,0,0,Ly),byrow=TRUE,2,2)
X.mult <- t(L %*% t(X))
xlim <- ylim <- range(c(X,X.rot,X.mult))
plot(X,type="l",cex = 0.1,xlim=xlim,ylim=ylim)
points(X.rot,cex=0.1,col=2)
points(X.mult,cex=0.1,col=3)
@
\end{breakbox}
\subsubsection{行列をかける順番について}
では、次の2つを試してみる。
\begin{itemize}
\item 回転してから、x,y軸方向に伸縮する
\item x,y軸方向に伸縮してから回転させる
\end{itemize}
それぞれ
\begin{eqnarray*}
LM v
ML v
\end{eqnarray*}
となる。
\begin{lstlisting}
X.rot.mult <- t((L %*% M) %*% t(X))
X.mult.rot <- t((M %*% L) %*% t(X))
xlim <- ylim <- range(c(X.rot.mult,X.mult.rot))
plot(X.rot.mult,type="l",cex = 0.1,xlim=xlim,ylim=ylim)
points(X.mult.rot,cex=0.1,col=2)
\end{lstlisting}
\begin{breakbox}
<<fig=TRUE>>=
X.rot.mult <- t((L %*% M) %*% t(X))
X.mult.rot <- t((M %*% L) %*% t(X))
xlim <- ylim <- range(c(X.rot.mult,X.mult.rot))
plot(X.rot.mult,type="l",cex = 0.1,xlim=xlim,ylim=ylim)
points(X.mult.rot,cex=0.1,col=2)
@
\end{breakbox}
2つの動きが異なることがわかる。
行列の掛け算は、$LM$$ML$とで違うことも意味している。
\subsection{3次元物体の回転}
3次元物体をいろいろな方向から眺めたいことはよくある。
人体画像がそのよい例である。
人体のデータが3次元座標で得られているので、正面から見てみよう。
横からも見て、上からも見てみる。
\begin{lstlisting}
perfumev <- as.matrix(read.table("perfume_v.txt"))
perfumev.2 <- rbind(perfumev,rep(max(perfumev),3))
perfumev.2 <- rbind(perfumev.2,rep(min(perfumev),3))
par(mfcol=c(1,3))
plot(perfumev.2[,c(1,2)],cex=0.01)
plot(perfumev.2[,c(3,2)],cex=0.01)
plot(perfumev.2[,c(1,3)],cex=0.01)
par(mfcol=c(1,1))
\end{lstlisting}
\begin{breakbox}
<<fig=TRUE>>=
perfumev <- as.matrix(read.table("perfume_v.txt"))
perfumev.2 <- rbind(perfumev,rep(max(perfumev),3))
perfumev.2 <- rbind(perfumev.2,rep(min(perfumev),3))
par(mfcol=c(1,3))
plot(perfumev.2[,c(1,2)],cex=0.01)
plot(perfumev.2[,c(3,2)],cex=0.01)
plot(perfumev.2[,c(1,3)],cex=0.01)
par(mfcol=c(1,1))
@
\end{breakbox}
このように3方向から眺められることは素晴らしいが、任意の角度から眺められたらさらによい。
3次元空間での回転を定義して、それを実行しよう。
v1-v3平面で回る(右端の表示での回転)は、頭を上に足を下にしたまま、背中を見せる回転である。
そのような回転をしたうえで、上から覗き込むように回転を加えよう。v2-v3平面で回る(左端の表示での回転)ことになる。
それぞれの回転は、3次元空間の3軸のうち2軸だけを取り出して、それについて、2次元回転をすることだから、次のように書ける。
\begin{equation*}
  M1 = \begin{pmatrix}
        \cos{\theta} & 0 & -\sin{\theta} \\
        0 & 1 & 0 \\
        \sin{\theta} & 0 & \cos{\theta}
      \end{pmatrix}
\end{equation*}
\begin{equation*}
  M2 = \begin{pmatrix}
        1 & 0 & 0 \\
        0 & \cos{\theta2} & -\sin{\theta2} \\
        0 & \sin{\theta2} & \cos{\theta2}
      \end{pmatrix}
\end{equation*}
その上で2つの回転をすればよい。
\begin{equation*}
  M2 M1
\end{equation*}

\begin{lstlisting}
theta1 <- pi/3
theta2 <- pi/4
M1 <- matrix(c(cos(theta1),0,-sin(theta1),0,1,0,sin(theta1),0,cos(theta1)),byrow=TRUE,3,3)
M2 <- matrix(c(1,0,0,0,cos(theta1),-sin(theta1),0,sin(theta1),cos(theta1)),byrow=TRUE,3,3)
M12 <- M2 %*% M1
perfumev.2.rot <- t(M12 %*% t(perfumev.2))
par(mfcol=c(1,3))
plot(perfumev.2.rot[,c(1,2)],cex=0.01)
plot(perfumev.2.rot[,c(3,2)],cex=0.01)
plot(perfumev.2.rot[,c(1,3)],cex=0.01)
par(mfcol=c(1,1))
\end{lstlisting}
\begin{breakbox}
<<fig=TRUE>>=
theta1 <- pi/3
theta2 <- pi/4
M1 <- matrix(c(cos(theta1),0,-sin(theta1),0,1,0,sin(theta1),0,cos(theta1)),byrow=TRUE,3,3)
M2 <- matrix(c(1,0,0,0,cos(theta1),-sin(theta1),0,sin(theta1),cos(theta1)),byrow=TRUE,3,3)
M12 <- M2 %*% M1
perfumev.2.rot <- t(M12 %*% t(perfumev.2))
par(mfcol=c(1,3))
plot(perfumev.2.rot[,c(1,2)],cex=0.01)
plot(perfumev.2.rot[,c(3,2)],cex=0.01)
plot(perfumev.2.rot[,c(1,3)],cex=0.01)
par(mfcol=c(1,1))
@
\end{breakbox}
\subsubsection{回転とは、そして、回転行列の特徴}
2次元、3次元の回転行列を扱ってきた。
任意次元の回転行列も2次元の回転の繰り返しで作ることができる。
\begin{lstlisting}
n <- 5
R <- diag(rep(1,n))
for(i in 1:n){
	a <- sample(1:n,2)
	theta <- runif(1)*2*pi
	tmp <- diag(rep(1,n))
	tmp[a,a] <- matrix(c(cos(theta),-sin(theta),sin(theta),cos(theta)),byrow=TRUE,2,2)
	R <- tmp %*% R
}
\end{lstlisting}
2次元の回転や3次元の回転は、像が「きちんと回転している」ということから、使用した
回転行列が「きちんと回転を表している」ことを実感できた。
ではここで作成した例のように高次元になったとき、行列が回転を表しているかどうかはどうやって確認すればよいだろうか。
回転では基底も回転する。
基底のうち、一般によく使われるのは正規直交基底。これは、2次元空間なら、(1,0)と(0,1)の2つ、3次元空間なら、(1,0,0),(0,1,0)と(0,0,1)の3つ、というように、各軸方向の単位ベクトルを合わせたもの。
これらはすべてが単位ベクトルで、どの2つも相互に直交する。
第i要素が1である単位ベクトルに行列を作用させると、行列の第i列が取り出される。
したがって、n個の単位行列からなる正規直交基底に行列を作用させると、正規直交基底が、その行列に移る。
今、回転では、ベクトルの長さも2つのベクトルが作る角度も変わらないから、移った先の基底のベクトルはすべて単位ベクトルで、それらは相互に直交しているはずである。
このような性質を行列の特徴で言い直すと、
\begin{itemize}
\item 直交行列である
\item 行列式が1である
\end{itemize}
直交行列とは、行列自身とその転置行列($a_{ij}$の値と$a_{ji}$の値を入れ替えた行列)との積が単位行列になるような(正方)行列のことであり、行列式とは$2 \times 2$行列で言えば
\begin{equation*}
a_{11}a_{22}-a_{12}a_{21}
\end{equation*}
と計算される行列を特徴づける量である。
上で作った回転行列と目される行列がこの条件を満足しているかどうかを確認してみます。
\begin{lstlisting}
R_t <- t(R)
R %*% R_t
R_t %*% R
det(R)
det(R_t)
\end{lstlisting}
\begin{breakbox}
<<fig=FALSE>>=
n <- 5
R <- diag(rep(1,n))
for(i in 1:n){
	a <- sample(1:n,2)
	theta <- runif(1)*2*pi
	tmp <- diag(rep(1,n))
	tmp[a,a] <- matrix(c(cos(theta),-sin(theta),sin(theta),cos(theta)),byrow=TRUE,2,2)
	R <- tmp %*% R
}
R_t <- t(R)
R %*% R_t
R_t %*% R
det(R)
det(R_t)
@
\end{breakbox}
\subsubsection{データの特徴を抽出する}
次のような3次元データを考えよう。
3人が立っている。
どの方向から見ると、一番「よく見える」だろうか。
3次元の対象を見るとき、3次元のうち2次元の絵を作って、残りの
1次元はつぶしてしまう。
したがって、2次元を選んだときに一番絵がばらついて見えるときが
「もっともよく見える」状態だと考えるのは、よいやり方の一つだろうと思える。
図のように点がばらついているとき、3つの互いに垂直な軸をとるとする。
このようなとき、第1の軸として、とりえるあらゆる軸のうち、分散が最大になるものを採用し、
ついで、第2の軸をとることにする。そのとき、第1の軸に垂直であることを条件にして、分散が最大になるようにする。多次元の場合には、順次、それまでに採用された軸に垂直であることを条件として順番に選んでいくことにする。
このようにすると、全部の軸について見てみなくても、上位の軸だけで結構、全体像が見えてくる可能性がある。
では、アイディアとして、この方法がよいと思われるが、それを実際にはどうしたらよいか、ということが問題になる。
そのときにデータ点の行列$D$をあるルール(特異値分解という方法)で分解して
\begin{equation*}
D = V \Sigma U^T
\end{equation*}
としてやる。
そうすると、回転行列$U$を使って$D$を回転させた
\begin{equation*}
DU = V \Sigma 
\end{equation*}
は、各軸の分散が上で述べたようなルールに従うことが知られている。
\begin{breakbox}
<<fig=TRUE>>=
# 3人の座標を取り込む
#perfumev <- as.matrix(read.table("perfume_v.txt"))
#perfume2v <- as.matrix(read.table("perfume_v2.txt"))
# 3人の立ち位置を少し変える
#perfume2v[,1] <- perfume2v[,1] +100
#perfume2v[,3] <- perfume2v[,3] + 200
#perfume3v <- as.matrix(read.table("perfume_v3.txt"))
#perfume3v[,1] <- perfume3v[,1] + 200
#perfume3v[,3] <- perfume3v[,3] - 200
# 3人の座標を一つの行列にする
#perfume.trio <- rbind(perfumev,perfume2v,perfume3v)
# 回転行列を適当に作って、3人の座標を回す
library(GPArotation)
R <- Random.Start(3)
perfume.trio <- t(R%*%t(perfume.trio))
# 点の数を少なめに取り直す
D <- perfume.trio[sample(1:length(perfume.trio[,1]),5000),]
# 3軸を平均が0になるように調整する
D <- D-mean(D)
mu <- apply(D,2,mean)
D <- t(t(D)-mu)
# 特異値分解する
svdout <-svd(D)
# US = DV のどちらでも回転後の座標が得られるので、2方法で求めておく
D2 <- svdout$u %*% diag(svdout$d)
D3 <- D%*% svdout$v

par(mfcol=c(3,3))
plot(D[,c(1,2)],cex=0.01)
plot(D[,c(3,2)],cex=0.01)
plot(D[,c(1,3)],cex=0.01)

plot(D2[,c(1,2)],cex=0.01)
plot(D2[,c(3,2)],cex=0.01)
plot(D2[,c(1,3)],cex=0.01)

plot(D3[,c(1,2)],cex=0.01)
plot(D3[,c(3,2)],cex=0.01)
plot(D3[,c(1,3)],cex=0.01)
par(mfcol=c(1,1))
apply(D2,2,var)
apply(D3,2,var)
@
\end{breakbox}
\subsubsection{状態の変化を表す推移行列}
2種類のものA1,A2があって、A1はA2の量に比例して増え、逆にA2はA1の量に比例して減るとする。
\begin{eqnarray*}
\delta a_1 = k a_2\\
\delta a_2 = - k a_1
\end{eqnarray*}
これは時刻$t$の量$a_1(t),a_2(t)$として表すと
\begin{eqnarray*}
a(t+\delta t) = a_1 + k a_2\\
a(t+\delta t) = - k a_1 + a_2
\end{eqnarray*}
これを$(a_1(t),a_2(t))^T$というベクトルで考えれば
\begin{equation*}
\begin{pmatrix}
a_1(t+\delta t)\\
a_2(t+\delta t)
\end{pmatrix} 
= 
\begin{pmatrix}
1 & k \\
-k & 1
\end{pmatrix}
\begin{pmatrix}
a_1(t)\\
a_2(t)
\end{pmatrix}
\end{equation*}
このように状態をベクトルで表すとき、行列がベクトルの時間変化を表すことができる場合も多い。
Rでやってみよう。
\begin{lstlisting}
k <- 0.001
A <- matrix(c(1,k,-k,1),byrow=TRUE,2,2)
n.t <- 10000
a <- matrix(0,n.t,2)
a[1,] <- c(1,0)
for(i in 2:n.t){
	a[i,] <- A %*% a[i-1,]
}
matplot(a,type="l")
\end{lstlisting}
\begin{breakbox}
<<fig=TRUE>>=
k <- 0.001
A <- matrix(c(1,k,-k,1),byrow=TRUE,2,2)
n.t <- 10000
a <- matrix(0,n.t,2)
a[1,] <- c(1,0)
for(i in 2:n.t){
	a[i,] <- A %*% a[i-1,]
}
matplot(a,type="l")
@
\end{breakbox}
要素数は2個に限る必要もなく、細胞内の化学反応系や生態系の捕食関係など、
この枠組みでとらえられる現象は非常に多い。
また、今回のシミュレーションは、短い時間を離散的に計算しているが、連続的な計算をすることもできる(指数行列)。
また、増減が複数の要素の量の積の影響を受けるなどの場合も推移行列で表現できるが、この章では扱わないこととする。
\subsection{行列は便利}
行列は基本的には以下の便利さがあるので、数値をたくさん使う場面(数値を扱う学術分野のすべて)で使われる。
便利さをまとめると以下の通り。
\begin{itemize}
\item $n\times m$個の数字($a_{ij}$)が必要なときに、1個の変数($A_{nm}$)を書くだけで済ませられる
\item たくさんの数字を使った計算を一気に実行できる。特に行列計算機能を持った計算機を持っていれば、楽。
\item 『行列がこれこれの特徴(P)を持っていたら、それそれの特徴(Q)を持つ、と言える』という便利な知識がたくさんある。したがって、Pを確かめる計算が簡単で、Qを確かめる計算が面倒臭いとき、Pをすればよい
\end{itemize}
\section{キーポイント}
\begin{itemize}
\item 行列の和と積。積は順序依存
\item 回転行列
\item 単位行列・転置行列・逆行列
\item 直交
\item 正規直交基底
\item 行列式 determinant
\item 特異値分解
\item 楕円と特異値分解
\item 推移行列
\item 指数行列
\end{itemize}
\end{document}
\documentclass{jsbook}

\usepackage{amsmath,amssymb}
\usepackage{bm}
%\usepackage{graphicx}
\usepackage{ascmac}
\usepackage[dvips]{graphicx}
\usepackage{graphicx}
\usepackage{bigdelim,multirow}
\usepackage{amsmath,amsthm,amssymb,cases}
\usepackage{ascmac}
\usepackage{url}
\usepackage{eclbkbox}
\usepackage{wrapfig}
\usepackage{listings, jlisting}
\usepackage[dvips,usenames]{color}
\usepackage{makeidx}
\SweaveOpts{eps=TRUE}

\lstdefinestyle{MyFrame}{backgroundcolor=\color{green},frame=shadowbox}
\lstdefinestyle{MyC++Style} {language=C++,style=MyFrame,frame=none}
\lstset{
    language=R,
    basicstyle=\ttfamily,
    backgroundcolor={\color[gray]{.85}},
    keywordstyle=\color{blue}\bfseries,
}

\begin{document}

\chapter{Rで行列を勉強する}
\section{Matrixオブジェクトの作成}
\subsection{行列を作る}
\begin{lstlisting}
# 行数と列数を指定する
n <- 2
m <- 3
# 行列の要素数分の値を作る
v <- 1:(n*m)
# 行列を作る
M <- matrix(v,n,m)
M
# 値の詰め方を変える
M2 <- matrix(v,n,m,byrow=TRUE)
M2
\end{lstlisting}
\begin{breakbox}
<<fig=FALSE>>=
# 行数と列数を指定する
n <- 2
m <- 3
# 行列の要素数分の値を作る
v <- 1:(n*m)
# 行列を作る
M <- matrix(v,n,m)
M
# 値の詰め方を変える
M2 <- matrix(v,n,m,byrow=TRUE)
M2
@
\end{breakbox}
\subsection{行列の四則演算〜数値を納めた箱として扱う}
同じ形の行列は数値を納めた箱として扱える。
\begin{lstlisting}
n <- 2
m <- 3
M1 <- matrix(1:(n*m),n,m)
M2 <- matrix(rep(1:2,(n*m)/2),n,m)
M1
M2
M1 + M2
M1 - M2
M1 * M2
M1 / M2
M1 ^ M2
\end{lstlisting}
\begin{breakbox}
<<fig=FALSE>>=
n <- 2
m <- 3
M1 <- matrix(1:(n*m),n,m)
M2 <- matrix(rep(1:2,(n*m)/2),n,m)
M1
M2
M1 + M2
M1 - M2
M1 * M2
M1 / M2
M1 ^ M2
@
\end{breakbox}
\section{行列の『積』}
\subsection{行列の『いわゆる積』}
$n\times m$ 行列$M_1$$m \times n$ の行列$M_2$に左からかけることができる。
行列の積$M_1 M_2$はRでは
\begin{lstlisting}
M1 %*% M2
\end{lstlisting}
と書かれこれは、$M1$の第$i$行ベクトルと$M2$の第$j$列ベクトルの内積が
$M_1 M_2$$(i,j)$成分となるような計算のこと。

\begin{lstlisting}
n <- 2
m <- 3
M1 <- matrix(1:(n*m),n,m)
M2 <- matrix(rep(1:2,(n*m)/2),m,n)
M1
M2
# 行列の積は次のように書く
M1 %*% M2
\end{lstlisting}
\begin{breakbox}
<<fig=FALSE>>=
n <- 2
m <- 3
M1 <- matrix(1:(n*m),n,m)
M2 <- matrix(rep(1:2,(n*m)/2),m,n)
M1
M2
# 行列の積は次のように書く
M1 %*% M2
@
\end{breakbox}
\subsection{行列の『いろいろな積』}
行列の『積』を理解するために2つの道を取る。
\begin{itemize}
\item 行列をベクトルの束と見て、ベクトルの『積』を考える
\item 行列の『積』を『行列の要素の総当たりの積』から考える
\end{itemize}
\subsubsection{ベクトルとベクトルの『積』}
長さ$n_v$のベクトル$V$と長さ$n_u$のベクトル$U$とを考える。
これらの要素の総当たりペアをとると、$n_v \times n_u$個の値が得られる。
これを$n_v\times n_u$行列として表現することはごく自然である。
($V$を列ベクトル、$U$を行ベクトルとみなしたときの行列の『いわゆる積』
ともみなせる)。
\begin{equation*}
V U^T = \begin{pmatrix}
v_1 u_1 & v_1 u_2 & ... & v_1 u_{n_u}\\
v_2 u_1 & v_2 u_2 & ... & v_2 u_{n_u}\\
... & ... & ... & ... \\
v_{n_v} u_1 & v_{n_v} u_2 & ... & v_{n_v} u_{n_u}
\end{pmatrix}
\end{equation*}
\begin{lstlisting}
nv <- 3
nu <- 4
V <- 1:nv
U <- 1:nu
V %*% t(U)
\end{lstlisting}
\begin{breakbox}
<<fig=FALSE>>=
nv <- 3
nu <- 4
V <- 1:nv
U <- 1:nu
V %*% t(U)
@
\end{breakbox}
これを一番「基本的なベクトルとベクトルの積」としよう。\\
長さが等しい2つのベクトルの場合には、「基本的なベクトルとベクトルの積」は正方行列になる。
その対角成分だけを取り出して和を取ったものが、ベクトルの内積
\begin{breakbox}
<<fig=FALSE>>=
nv <- 3
nu <- nv
V <- 1:nv
U <- 1:nu
W <- V %*% t(U)
diag(W)
sum(diag(W))
# 次のように計算してももちろんよい
sum(V*U)
@
\end{breakbox}
\subsubsection{3次元ベクトルの外積}
3次元ベクトルの間には「ベクトル積」という『積』があって、これは
\begin{equation*}
V U^T = \begin{pmatrix}
v_1 u_1 & v_1 u_2 & v_1 u_3\\
v_2 u_1 & v_2 u_2 & v_2 u_3\\
v_3 u_1 & v_3 u_2 & v_3 u_3
\end{pmatrix}
\end{equation*}
というベクトルの積の9成分のうち、
内積に使われた対角の3成分を使わず、
残りの6成分を、対称な2成分のトリオに分け、結果として、
3つの数字のベクトルにしたものである。
元のベクトルが3次元ベクトルであったが、2つの3次元ベクトルの『積』が
3次元ベクトルになっているので、「うまく閉じた関係」になっていることがわかる。
この『積』である3次元ベクトルには、有用な性質があることから、
名前を「ベクトル積・クロス積」と呼んでいる。
\begin{lstlisting}
my.cross.prod.3d <- function(v,u){
	c(v[2]*u[3]-v[3]*u[2], v[3]*u[1]-v[1]*u[3], v[1]*u[2]-v[2]*u[1])
}
\end{lstlisting}


\subsubsection{行列の要素の総当たりの積}
$n_1 \times m_1$ 行列 $M_1$$n_2 \times m_2$ 行列 $M_2$ との積の計算の仕方は一つではない。
$M_1$行列には$n_1 \times m_1$個の要素があり、$M_2$行列には$n_2 \times m_2$個の要素があるので、
それらの総当たりの積が$(n_1 \times m_1) \times (n_2 \times m_2)$個ある。
これを使って、複数の『行列の積』が定義できる。
この$(n_1 \times m_1) \times (n_2 \times m_2)$個の要素を
$(n_1 \times m_1)$$\times \times (n_2 \times m_2)$列の行列にするのはクロネッカー積。
\begin{lstlisting}
n1 <- 2
m1 <- 2
n2 <- 3
m2 <-2 
M1 <- matrix(1:(n1*n2),n1,m1)
M2 <- matrix(1:(n2*m2),n2,m2)
M1
M2
Kr<- M1 %x% M2
Kr
\end{lstlisting}
\begin{breakbox}
<<fig=FALSE>>=
n1 <- 2
m1 <- 2
n2 <- 3
m2 <-2 
M1 <- matrix(1:(n1*n2),n1,m1)
M2 <- matrix(1:(n2*m2),n2,m2)
M1
M2
Kr<- M1 %x% M2
Kr
@
\end{breakbox}
$M_1[i_1,j_2] \times M_2[i_2,j_2]$がクロネッカー積の何行目・何列目になっているかを目視で確認してみるとよい。\\
$(n_1 \times m_1) \times (n_2 \times m_2)$個の要素を
$n_1 \times m_1 \times n_2 \times m_2$と4次元の整理箱にしまう(Rならarrayオブジェクト)のが行列の外積。
これは、$M_1$の行ベクトルと$M_2$の列ベクトルの間のベクトル積を$n_1 \times m_2$個求め、それを$n_1 \times m_2$の行列状に並べたもの。ただし、$M_1$の行ベクトルと$M_2$の列ベクトルの間のベクトル積自体が$m_1 \times n_2$行列なので、出来上がったものは$n_1 \times m_1 \times n_2 \times m_2$と4次元になっている。
Rであれば以下のようにする。
その要素がクロネッカー積の要素と一致することも示しておく(証明ではなく、適当に作ってもいつも要素の値の集合が一致することを示す)。
\begin{lstlisting}
Vpr<- M1 %o% M2
Vpr
range(sort(Kr) - sort(Vpr))
\end{lstlisting}
\begin{lstlisting}
k <- 100
diffs <- rep(0,k)
for(i in 1:k){
	n1 <- sample(2:6,1)
	m1 <- sample(2:6,1)
	n2 <- sample(2:6,1)
	m2 <- sample(2:6,1)
	M1 <- matrix(runif(n1*m1),n1,m1)
	M2 <- matrix(runif(n2*m2),n2,m2)
	tmp1 <- M1 %o% M2
	tmp2 <- M1 %x% M2
	diffs[i] <- max(abs(sort(c(tmp1))-sort(c(tmp2))))
}
range(diffs)
\end{lstlisting}
\begin{breakbox}
<<fig=FALSE>>=
Vpr<- M1 %o% M2
Vpr
range(sort(Kr) - sort(Vpr))
@
\end{breakbox}
\begin{breakbox}
<<fig=FALSE>>=
k <- 100
diffs <- rep(0,k)
for(i in 1:k){
	n1 <- sample(2:6,1)
	m1 <- sample(2:6,1)
	n2 <- sample(2:6,1)
	m2 <- sample(2:6,1)
	M1 <- matrix(runif(n1*m1),n1,m1)
	M2 <- matrix(runif(n2*m2),n2,m2)
	tmp1 <- M1 %o% M2
	tmp2 <- M1 %x% M2
	diffs[i] <- max(abs(sort(c(tmp1))-sort(c(tmp2))))
}
range(diffs)
@
\end{breakbox}
\begin{itemize}
\item $m_1 = n_2$ のとき
\end{itemize}
\section{特徴的な行列}

\section{行列の色々}
\begin{lstlisting}
# 転置
A <- matrix(1:6,2,3)
t(A)
# 対角成分を取り出す
B <- matrix(1:16,4,4)
B
diag(B)
# 対角行列
D <- diag(1:4)
D
# 単位行列
D. <- diag(4)
D.
D.. <- diag(rep(1,4))
D..
\end{lstlisting}
連立方程式を解く。
\begin{equation*}
A x = b
\end{equation*}
\begin{lstlisting}
# 連立一次方程式を解く
A <- matrix(sample(1:9),3,3)
b <- c(2,3,5)
result <- solve(A,b)
result
A %*% result
# 逆行列
F <- matrix(rnorm(9),3,3)
F.inv <- solve(F)
F %*% F.inv
F.inv %*% F
# 固有値分解
eigen.out <- eigen(F)
V <- eigen.out$vectors
S <- diag(eigen.out$values)
V %*% S %*% solve(V)
V%*%t(V)
det(Re(V))
# 対称行列の固有値分解
F. <- F + t(F)
F.
eigen.out.2 <- eigen(F.)
V <- eigen.out.2$vectors
S <- diag(eigen.out.2$values)
V %*% S %*% t(V)
# Vは回転行列
V%*%t(V)
det(Re(V))
# 特異値分解
G <- matrix(rnorm(12),3,4)
G
svd.out <- svd(G)
svd.out$v %*% diag(svd.out$d) %*% svd.out$u
# svd.out$u は回転行列
svd.out$u %*% t(svd.out$u)
\end{lstlisting}
\begin{breakbox}
<<fig=FALSE>>=
# 転置
A <- matrix(1:6,2,3)
t(A)
# 対角成分を取り出す
B <- matrix(1:16,4,4)
B
diag(B)
# 対角行列
D <- diag(1:4)
D
# 単位行列
D. <- diag(4)
D.
D.. <- diag(rep(1,4))
D..
# 連立一次方程式を解く
A <- matrix(sample(1:9),3,3)
b <- c(2,3,5)
result <- solve(A,b)
result
A %*% result
# 逆行列
F <- matrix(rnorm(9),3,3)
F.inv <- solve(F)
F %*% F.inv
F.inv %*% F
# 固有値分解
eigen.out <- eigen(F)
V <- eigen.out$vectors
S <- diag(eigen.out$values)
V %*% S %*% solve(V)
V%*%t(V)
det(Re(V))
# 対称行列の固有値分解
F. <- F + t(F)
F.
eigen.out.2 <- eigen(F.)
V <- eigen.out.2$vectors
S <- diag(eigen.out.2$values)
V %*% S %*% t(V)
# Vは回転行列
V%*%t(V)
det(Re(V))
# 特異値分解
G <- matrix(rnorm(12),3,4)
G
svd.out <- svd(G)
svd.out$v %*% diag(svd.out$d) %*% svd.out$u
# svd.out$u は回転行列
svd.out$u %*% t(svd.out$u)
@
\end{breakbox}
\end{document}

外積代数のメモ

pdf_files

\documentclass{jsbook}

\usepackage{amsmath,amssymb}
\usepackage{bm}
%\usepackage{graphicx}
\usepackage{ascmac}
\usepackage[dvips]{graphicx}
\usepackage{graphicx}
\usepackage{bigdelim,multirow}
\usepackage{amsmath,amsthm,amssymb,cases}
\usepackage{ascmac}
\usepackage{eclbkbox}
\usepackage{wrapfig}
\usepackage{listings, jlisting}
\usepackage[dvips,usenames]{color}
\usepackage{makeidx}
\usepackage{url}
\usepackage[dvipdfmx,setpagesize=false]{hyperref}
\SweaveOpts{eps=TRUE}

\lstdefinestyle{MyFrame}{backgroundcolor=\color{green},frame=shadowbox}
\lstdefinestyle{MyC++Style} {language=C++,style=MyFrame,frame=none}
\lstset{
    language=R,
    basicstyle=\ttfamily,
    backgroundcolor={\color[gray]{.85}},
    keywordstyle=\color{blue}\bfseries,
}

\begin{document}

\chapter{外積代数}\label{ExteriorAlgebra}
\section{外積と外積代数}
\ref{R_Matrix}{Rで行列を勉強する}の記事で行列の積に関連してベクトルの
外積の話題が出た。\\
その外積を一般化して出来上がる外積代数に関する記事である。\\
3次元ベクトル空間$\mathbf{R}^3$でのベクトル積(外積)は、$a=(a_1,a_2,a_3),b=(b_1,b_2,b_3)$に対して、$a \times b = (|\begin{pmatrix} a_2 & a_3 \\ b_2 & b_3 \end{pmatrix}|,|\begin{pmatrix} a_3 & a_1 \\ b_3 & b_1 \end{pmatrix}|,|\begin{pmatrix} a_1 & a_2 \\ b_1 & b_2 \end{pmatrix}|)$ という$\mathbf{R}^3$のベクトル。\\
他方、内積は$<a,b>=\sum_{i=1}^3 a_i b_i$\\
内積の定義はn次元においてもそのまま通用するが、ベクトル積はそうはなっていない。\\その理由を含めて考えると、ベクトル積・外積代数というものが出てくる。それを以下に示す\\
\section{n次元のベクトル積とべき集合の要素数}
n次元空間ベクトルがn-1個あったとき、そのベクトル積は、n次元ベクトルになる\\
今、n-1個のベクトルを$x_2,x_3,...,x_n$とし、もう一つn次元ベクトル$x_1$を置く\\
$x_1,...,x_n$を行ベクトルとする行列$X$を考えると、そのDeterminant($det(X)$)が算出できる\\
$x_2,...,x_n$のベクトル積はn次元ベクトル$v$であって、$x_1$$v$との内積は$X$のDeterminantである($<x_1,v>=det(X)$)という関係にある\\
それをRで書くと次のようになる\\
\begin{lstlisting}
library(MCMCpack)
# 複素数行列のDeterminantの計算用関数
detComplex<-function(M){
	e.out<-eigen(M)
	prod(e.out[[1]])
}
# 外積計算用関数
ExteriorProduct<-function(V){
	ret<-rep(0,length(V[1,]))
	for(i in 1:length(ret)){
		ret[i]<-(-1)^(i+1)*detComplex(V[,-i])
	}
	ret
}
# 例えばn=7次でやってみる
n<-7
# 適当に複素数を要素とする正方行列を作る
X<-matrix(complex(real = rdirichlet(1,rep(1,n^2)), imaginary = rdirichlet(1,rep(1,n^2))),ncol=n)
# Hermite化する
X<-t(Conj(X))%*%X
# Determinantを計算する
detX<-detComplex(X)
detX
# n個のベクトルから適当にn-1個を選ぶ
s<-sample(1:n,(n-1))
# 選ばれたn-1個のベクトルについて外積を計算する
ep<-ExteriorProduct(X[s,])
# 外積は長さnのベクトルである
ep
# 選ばれなかったベクトルと、選ばれたn-1個のベクトルの外積との内積を計算すると
# 選ばれなかったベクトルと選ばれたベクトルとが作る行列のDeterminantになっていることが以下の計算でわかる
sum(X[-s,]*ep)
detComplex(X)
sum(X[-s,]*ep)-detComplex(X)
\end{lstlisting}
長さnのベクトルn-1本から、長さnのベクトルが1本できた。これは、n次元空間を$V$として$V^{n-1}$から$V$へと写したもの\\
ベクトル積を一般次元に拡張する\\
ベクトル積はn次元ベクトルがn-1本集まったときに定義できた\\
n次元ベクトルがr($r<n$)本集まったときに、ベクトル積様のものとなるのが、定義できる\\
それは、n-1個のベクトルが作る$(n-1)\times n$行列からn-2列を取り出したもの(n-1通りある)が作る$(n-1)\times (n-1)$行列のDeterminantに正負を考慮したものになっている\\
このベクトル積様なものの個数は、「組み合わせ」で決まるので、べき集合の要素数(n次元ベクトルn本に対して考えれば、$2^n$)になる\\
この$2^n$個の要素たちは「代数」的に完結するので、以下のように「\href{http://ja.wikipedia.org/wiki/%E5%A4%96%E7%A9%8D%E4%BB%A3%E6%95%B0}{Wiki外積代数}」としてまとめられる(参考→\href{http://d.hatena.ne.jp/ryamada22/20060514}{こちら})\\

外積代数はベクトル解析につながっている\\
外積・微分形式・外微分…時空間軌道の解析から始まった「曲線」「曲面」「多様体」に関する話題の一端である\href{http://d.hatena.ne.jp/ryamada/20110925}{この記事}につながる\\
\section{Gauss-Stokesの公式}
外積代数を用いて、微分形式・外微分などを用いることで積分に関する以下の公式がわかりやすくなる\\
\href{http://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%88%E3%83%BC%E3%82%AF%E3%82%B9%E3%81%AE%E5%AE%9A%E7%90%86}{Gauss-Stokesの公式}\\
「ベクトル場の回転を曲面上で面積分したものが、元のベクトル場を曲面の境界で線積分したものに一致する」\\
$\int_{\partial S} \omega = \int_S d\omega$
\section{外積代数・微分形式・外微分を自分の言葉で説明してみる}
自分なりに外積代数・微分形式・外微分・Gauss-Stokesの公式を書いてみる\\
n次元空間には、n個の線形独立なベクトルがおける。簡単に考えるなら、n本のベクトルからなる正規直交基底を考える\\
\subsection{外積代数}
外積代数では、1,2,...,nを要素とする集合のべき集合の要素である部分集合に対応したものを考える\\
そのような要素は$2^n$個ある\\
この$2^n$個は、部分集合であるが、部分集合としての要素数が、0,1,2,...,nのいずれかであって、それぞれの要素数は$\begin{pmatrix} n \\ i \end{pmatrix};r=0,1,...n$となっている\\
それらは符号の取り方の工夫をすることで、あるルールづけがなされている\\
\subsection{微分形式}
外積代数では「単位ベクトル」を考えたが、こちらは微分なので、「微小ベクトル」を考える。\\
微小ベクトルだが、方向については、「単位ベクトル」をそのままひきつぐ\\
外積代数と同様に$2^n$種類あるそれぞれに、関数がある\\
$f_{i}^r(x);r=0,1,...,n;i=1,2,...,\begin{pmatrix}n \\ r \end{pmatrix}$\\
外積代数では、対応する部分集合の要素数で0,1,...,n通りに分類できたが、この要素数rごとに$w^r=\sum_{i=1}^{\begin{pmatrix}n \\ r \end{pmatrix}} f_{i}^r (x) G_i^r$のように$G_i^r$(部分集合として要素数rの外積代数の一つ)に関して足し合わせたものをr次の微分形式と呼ぶ\\
\subsection{外微分}
r次の微分形式$w^r$の外微分$dw^r$を次のように定義する\\
$dw^r=\sum_{i=1}^{\begin{pmatrix}n \\ r \end{pmatrix}} df_i^r G_i^r$\\
ここで外積代数$G_i^r$の交代性が功を奏して、ぱたぱたと項が消える\\
\subsection{Gauss-Stokesの公式}
\begin{equation*}
\int_{\partial S} \omega = \int_S d\omega
\end{equation*}$w$$dw$はこのようにして定めた微分形式と外微分であって、この表現法を使うと、r次の微分形式を境界に関して積分したものと、その外微分を領域全体について積分したものとが一致する、ということが導ける\\
これは、空間が1次元のときには、外微分を領域(ここからここまで)について積分したものと、微分形式を境界(1次元線分の境界は2点)について向き・正負に注意して積分したものに一致することに対応する\\
\begin{equation*}
f(b)-f(a)=\int_a^b f'(x)dx
\end{equation*}
\section{外積代数の計算をRでやってみる}
次元nのとき、要素数は、nからi個を取り出して、その順列になる(それ以外は、0になる)から、$\sum_{i=0}^n \begin{pmatrix} n \\ i \end{pmatrix} \times i!$。それらが、$2^n$の基本要素で張られる\\
以下のソースではelemListが基本要素、allElemがすべての要素。MはallElemの演算結果を基本要素数の長さのベクトルで表している。またM2は、基本要素のどれに相当するかを符号つきで表している
<<fig=FALSE>>=
# 集合のパッケージ
library(sets)
library(gtools)

# 次元
n<-3
s<-1:n
# 順列・置換に関して、その符号を計算するには、置換を表す行列のdeterminantが使える
s2<-sample(s)
M<-diag(rep(1,n))[s2,]
det(M)
# それを使って、演算を、要素の組(集合)と符号とで表すことにする
# その関数
SignaturePermutation<-function(s){
	n<-length(s)
	sig<-1
	if(n>1){
		s2<-order(s)
		M<-diag(rep(1,n))[s2,]
		sig<-det(M)
	}
	list(set=as.set(s),sign=sig)

}
# 二つの要素を演算処理するとき、要素の重複があれば0になるので、それをする関数を作る
a<-sample(s,sample(0:n))
a
SignaturePermutation(a)
a2<-sample(s,sample(0:n))
a2
SignaturePermutation(a2)


Zerocheck<-function(s1,s2){
	ret<-TRUE
	if(length(set_intersection(as.set(s1),as.set(s2)))==0){
		ret<-FALSE
	}
	ret
}
Zerocheck(a,a2)


t<-as.set(s)
# 冪集合を作る
# これは、基本要素のセットとなる
pow.t<-set_power(t)

# 2^n個の基本要素をリストにする
# ID、要素数の等しいものごとに束ねたときの束内ID、集合
elemList<-list()
cnt<-1
numcnt<-1
cntINnumcnt<-1
currentn<-0
elemList[[1]]<-list()
for(i in pow.t){
	n<-length(i)
	print(n)
	print(i)
	if(n>currentn){
		cntINnumcnt<-1
		numcnt<-numcnt+1
		currentn<-n
		elemList[[numcnt]]<-list()
	}
	elemList[[numcnt]][[cntINnumcnt]]<-list(id=cnt,id2=cntINnumcnt,set=i,n=length(i))
	cntINnumcnt<-cntINnumcnt+1
	cnt<-cnt+1
}

# 演算順を自由にした、すべてについての情報をリストにする
allElem<-list()
cnt<-1
v<-c()
tmp<-SignaturePermutation(v)
allElem[[cnt]]<-list(id=cnt,v=v,set=tmp$set,sign=tmp$sign)
cnt<-cnt+1
for(i in 1:n){
	tmpperm<-permutations(n,i)
	for(j in 1:length(tmpperm[,1])){
		v<-tmpperm[j,]
		tmp<-SignaturePermutation(v)
		allElem[[cnt]]<-list(id=cnt,v=v,set=tmp$set,sign=tmp$sign)
		cnt<-cnt+1
	}
}
allElem

N<-length(allElem)

M<-array(0,c(N,N,2^n))
M2<-matrix(0,N,N)
for(i in 1:N){
	for(j in 1:N){
		vi<-allElem[[i]]$v
		vj<-allElem[[j]]$v
		#if(!(length(vi)==0 & length(vj)==0)){
			if(!Zerocheck(vi,vj)){
				tmpv<-c(vi,vj)
				tmpout<-SignaturePermutation(tmpv)
				print(tmpv)
				tmplen<-length(tmpv)
				for(k in 1:length(elemList[[tmplen+1]])){
					if(tmpout$set==elemList[[tmplen+1]][[k]]$set){
						print(elemList[[tmplen+1]][[k]])
						print(M[i,j,])
						M[i,j,elemList[[tmplen+1]][[k]]$id]<-tmpout$sign
						M2[i,j]<-elemList[[tmplen+1]][[k]]$id*tmpout$sign
						print(M[i,j,])
					}
				}
			}
		#}
	}
}
M2
@
\end{document}