MATLABでケアレスミスを無くそう!! (線形代数編)

ここに書いたコードは**R2021a**で実行しています.
## はじめに
COVID-19の影響により, 学校でのテスト形態も様変わりしてきました.
今までは「計算ミスをしても途中式を見てくれたからある程度点が取れていた」という人も, 「テストがオンラインで答えのみを入力する方式になってしまったから, 勉強した内容をしっかり理解していても, 点が取れない」という経験をよく耳にします (耳にするだけでなく, ごく最近, 自分もやらかしました..)

この記事は, そんな「理解度90%以上なのに, いい点数が取れない」という方に届けたく, 書き始めました.

**私たちはコンピュータではないので, 間違えるのは当たり前です!!**
**もし, 手計算に自信がない場合は以下の方法で自分の答えを確認してみてはいかがでしょうか!!**

**シリーズ他記事**
1. [微分積分編](https://qiita.com/hibs_MATLAB_Amb/items/8bb64b362c7a29491e23)

## MATLABの由来
みなさんMATLABって何の略か知っていますか？
実は「**MAT**rix **LAB**oratory」なんです!!

つまり, MATLABは線形代数で扱う行列の計算を主目的に作られたプログラミング言語なのです.
では早速, MATLABを使って線形代数の問題を解いていきましょう.

## MATLABでの行列の作り方
まずは, MATLABに問題の行列を入力する必要があります.
MATLABでは要素同士の間に, ","を書き, ";"で改行することで行列を入力します.

例えば, 

```math
A = 
\begin{bmatrix}
1 & 2 & 3 \\
4 & 5 & 6 \\
7 & 8 & 9 
\end{bmatrix}
```
をMATLABに入力してみる. このときは, 

```matlab:code
A = [1,2,3;4,5,6;7,8,9]
```
と書くことで, 

```text:output
A =

     1     2     3
     4     5     6
     7     8     9

```

という感じで行列が作れます.


## 行列の掛け算
行列の掛け算は単純な計算問題ですが, 3$\times$3以上の大きさの行列が出てくると非常に厄介です. そして, 計算ミスも日常茶飯事に起こります. しかし, こんなところでつまずいていては単位をとれるかどうかも怪しくなりかねない. そこで, 以下の問題にMATLABを適用してみます.

### 問題
以下の行列$A$及び$B$の積$AB$と$BA$を求めよ.

```math
A = \begin{bmatrix}
2 & 9 & 9 \\
7 & 9 & 2 \\
4 & 5 & 8 
\end{bmatrix}
\\
B = 
\begin{bmatrix}
6 & 6 & 2 \\
6 & 0 & 7 \\
0 & 1 & 5 
\end{bmatrix}
```
### 解法
実は, **MATLABでの行列の掛け算は, 普通の掛け算と何も変わりません.**
なので, 

```matlab:code
A = [2,9,9;7,9,2;4,5,8]
B = [6,6,2;6,0,7;0,1,5]

AB = A*B % Calculate Product AB
BA = B*A % Calculate Product BA
```
というコードで,

```text:output
A =

     2     9     9
     7     9     2
     4     5     8


B =

     6     6     2
     6     0     7
     0     1     5


AB =

    66    21   112
    96    44    87
    54    32    83


BA =

    62   118    82
    40    89   110
    27    34    42

```
簡単に答えを求められます!!

### (ちなみに)　アダマール積
行列の積にはいろいろな種類がありますが, 行列同士の掛け算と同じくらいよく使われるものに「アダマール積」があります. これは各行列の要素ごとの積を算出するものです.

```math
\begin{bmatrix}
a_1 & a_2 & a_3 \\
a_4 & a_5 & a_5 \\
a_7 & a_8 & a_9 
\end{bmatrix}
\circ
\begin{bmatrix}
b_1 & b_2 & b_3 \\
b_4 & b_5 & b_5 \\
b_7 & b_8 & b_9 
\end{bmatrix}
=
\begin{bmatrix}
a_1b_1 & a_2b_2 & a_3b_3 \\
a_4b_4 & a_5b_5 & a_5b_5 \\
a_7b_7 & a_8b_8 & a_9b_9 
\end{bmatrix}
```

これを解くには以下のコードのように"\*"の代わりに".\*"を用います. (詳しくは[MATLAB Onramp](https://www.mathworks.com/learn/tutorials/matlab-onramp.html)へ)

```matlab:code
A = [2,9,9;7,9,2;4,5,8] % Left Matrix
B = [6,6,2;6,0,7;0,1,5] % Right Matrix

A.*B % Calculate Hadamard Product
```

```text:output
A =

     2     9     9
     7     9     2
     4     5     8


B =

     6     6     2
     6     0     7
     0     1     5


ans =

    12    54    18
    42     0    14
     0     5    40

```

## 逆行列
逆行列の一番嫌らしいところは, 答えがあっているか確認するために行列の積を計算しなければならないので, 計算ミスをしてしまう危険性が非常に高いことです. しかし, MATLABでは[inv関数](https://www.mathworks.com/help/matlab/ref/inv.html)により以下のように逆行列を求められます.

### 問題
以下の行列$A$の逆行列を計算せよ.

```math
A = 
\begin{bmatrix}
2 & 9 & 9 \\
7 & 9 & 2 \\
4 & 5 & 8 
\end{bmatrix}
```

### 解法

```matlab:code
A = [2,9,9;7,9,2;4,5,8]
inverseA = inv(A) % Calculate Inverse Matrix
check = A*inv(A) % Check
```

```text:output
A =

     2     9     9
     7     9     2
     4     5     8


inverseA =

   -0.1956    0.0852    0.1987
    0.1514    0.0631   -0.1861
    0.0032   -0.0820    0.1420


check =

    1.0000         0         0
    0.0000    1.0000   -0.0000
   -0.0000         0    1.0000
```
上で行った行列の積も使えば, 計算結果があっているかの確認も楽々できちゃいます!

## 簡約化
簡約化はガウスジョルダン法での連立一次方程式の求解や, 行列の階数を求めるのに必須です. しかし, とにかく段階を踏んでコツコツ計算をしなければならず, かなり面倒です.

### 問題
以下の行列$A$の簡約行列を求めなさい.

```math
A = 
\begin{bmatrix}
9 & 1 & 0 & 9 \\
3 & 8 & 3 & 7 \\
0 & 1 & 5 & 2
\end{bmatrix}
```

### 解法
今回, 簡約化を行うときには, MATLABの[rref関数](https://www.mathworks.com/help/symbolic/rref.html)が役に立ちます.

```matlab:code
A = [9,1,0,9;3,8,3,7;0,1,5,2]
rref(A) % Calculate Simplified Matrix
```

```text:output
A =

     9     1     0     9
     3     8     3     7
     0     1     5     2


ans =

    1.0000         0         0    0.9560
         0    1.0000         0    0.3962
         0         0    1.0000    0.3208
```

## 行列式
3$\times$3までなら簡単だけど, 4$\times$4から余因子展開などで複雑になっていく行列式もMATLAB [det関数](https://www.mathworks.com/help/matlab/ref/det.html?s_tid=doc_ta)で一発です!!

### 問題
以下の行列$A$の行列式を求めなさい.

```math
A = 
\begin{bmatrix}
1 & 0 & 9 & 7 \\
3 & 7 & 3 & 1 \\
5 & 6 & 8 & 1 \\
6 & 0 & 2 & 1 
\end{bmatrix}
```

### 解法

```matlab:code
A = [1,0,9,7;3,7,3,1;5,6,8,1;6,0,2,1]
det(A) % Calculate Matrix Determinant
```

```text:output
A =

     1     0     9     7
     3     7     3     1
     5     6     8     1
     6     0     2     1


ans =

  -1.4210e+03
```

## 連立一次方程式の求解
簡約化で解いても, LU分解等を使っても面倒なことには間違いない問題ですね.

### 問題
以下の連立方程式を解け.

```math
\begin{bmatrix}
9 & 1 & 0  \\
3 & 8 & 3  \\
0 & 1 & 5 
\end{bmatrix}
\left\{\begin{array}{c}
x_1 \\
x_2 \\
x_3
\end{array}\right\}
=
\left\{\begin{array}{c}
9 \\
7 \\
2
\end{array}\right\}
```

### 解法
MATLABでの連立方程式の求解には[linsolve関数](https://www.mathworks.com/help/matlab/ref/linsolve.html?s_tid=doc_ta)を用います.

```matlab:code
A = [9,1,0;3,8,3;0,1,5]
B = [9;7;2]

x = linsolve(A,B) % Calculate
```

```text:output
A =

     9     1     0
     3     8     3
     0     1     5


B =

     9
     7
     2


x =

    0.9560
    0.3962
    0.3208
```




## 対角化
おそらく, 線形代数の計算問題において最も手間がかかる問題の一つではないでしょうか!? 対角化を行う場合は, 
1. 固有値を求める
2. 固有ベクトルを求める
3. 対角化完成
の手順で行います. これをMATLABでやると以下のようになります.

### 問題
以下の行列$A$で対角化を行い, 固有値, 固有ベクトル, 体格行列を求めなさい.

```math
A = 
\begin{bmatrix}
2 & 9 & 9 \\
7 & 9 & 2 \\
4 & 5 & 8 
\end{bmatrix}
```

### 解法

```matlab:code
A = [2,9,9;7,9,2;4,5,8]
EigenValue = eig(A) % Calculate Eigen Value
[EigenVector,Result] = eig(A) % Calculate EigenVector and Result
```

```text:output
A =

     2     9     9
     7     9     2
     4     5     8


EigenValue =

   18.2087
   -3.7955
    4.5868


EigenVector =

   -0.6171   -0.8794    0.2104
   -0.5837    0.4653   -0.6604
   -0.5277    0.1010    0.7209


Result =

   18.2087         0         0
         0   -3.7955         0
         0         0    4.5868
```

見ての通り, MATLABでの対角化に必要なのは[eig関数](https://www.mathworks.com/help/matlab/ref/eig.html)ただ1つだけなのです.

# 終わりに
[微分積分編](https://qiita.com/hibs_MATLAB_Amb/items/8bb64b362c7a29491e23)と比べていただけるとわかる通り, 明らかにコードの量が少なくなっています. これがMATLAB (**Matrix** Laboratory)が本領発揮したときのすごさなんだと思います.

もし, この記事を見て, 自分の計算を確認する術を知った人が, テストで高得点を取ってくれたらうれしいです!!