行列の線形変換のデモプログラムを書いてみた

#初めに
数学ガールの秘密ノート「行列が描くもの」
第４章トランスフォームで「リサ」が行う線形変換のデモンストレーションを
Pythonで行ってみました

#動作環境
Python3

#実装例と結果
以下、本書の記述順に記載しています

###点を表示
グラフ上に点(2, 1)に表示

```python
import matplotlib.pyplot as plt
import numpy as np

p21 = np.array([2, 1])
plt.plot(p21[0], p21[1], marker='.')

plt.show()
```

<img width="551" alt="Screen Shot 2020-04-28 at 11.27.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/1190a637-f554-2560-f8e5-39347337beb5.png">


###点を移動
点(2, 1)を行列

```math
\begin{pmatrix}
2 & 0 \\
0 & 2 
\end{pmatrix}
```
で線形変換して点(4, 2)に移す

<img width="525" alt="Screen Shot 2020-04-28 at 11.24.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/3340374f-6900-0751-7434-6cf22052c637.png">

```python
import matplotlib.pyplot as plt
import numpy as np

p21 = np.array([2, 1])
p21to42 = np.array([[2, 0], [0, 2]]) @ p21

fig = plt.figure()
ax = fig.add_subplot(111)
ax.annotate('', xy=p21to42,
                xytext=p21,
                arrowprops=dict(shrink=0, width=1, headwidth=8))
ax.set_xlim([0, 5])
ax.set_ylim([0, 5])

plt.plot(p21[0], p21[1], marker='.')
plt.plot(p21to42[0], p21to42[1], marker='.')

plt.show()
```

###複数の点を移動
複数の点を行列

```math
\begin{pmatrix}
2 & 0 \\
0 & 2 
\end{pmatrix}
```
で線形変換する

```python
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(111)

for x in np.linspace(-1, 1, 11):
    for y in np.linspace(-1, 1, 11):
        marker = '8'
        if x > 0 and y > 0:
            marker = '$1$'
        elif x < 0 and y > 0:
            marker = '$2$'
        elif x < 0 and y < 0:
            marker = '$3$'
        elif x > 0 and y < 0:
            marker = '$4$'

        pOrg = np.array([x, y])
        pTra = np.array([[2, 0], [0, 2]]) @ pOrg

        ax.annotate('', xy=pTra,
                        xytext=pOrg,
                        arrowprops=dict(shrink=0.1, width=1, headwidth=3))

        plt.plot(pOrg[0], pOrg[1], marker = marker)
        plt.plot(pTra[0], pTra[1], marker = marker)

ax.set_xlim([-2, 2])
ax.set_ylim([-2, 2])
plt.show()
```

<img width="542" alt="Screen Shot 2020-04-28 at 13.07.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/566091a9-ca5b-a894-cd79-7e8aa1802713.png">


```math
\begin{pmatrix}
1/2 & 0 \\
0 & 1/2 
\end{pmatrix}
```
で線形変換すると
<img width="547" alt="Screen Shot 2020-04-28 at 13.15.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/cc835726-1151-dd51-2111-52351f70d5ef.png">

```math
\begin{pmatrix}
3 & 0 \\
0 & 2 
\end{pmatrix}
```
で線形変換すると

<img width="528" alt="Screen Shot 2020-04-28 at 13.17.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/2883d2d7-98bc-2a51-5c92-b04a69680c20.png">

```math
\begin{pmatrix}
2 & 1 \\
1 & 3 
\end{pmatrix}
```
で線形変換すると
<img width="527" alt="Screen Shot 2020-04-28 at 13.20.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/0f069270-275a-ba53-47d0-584bde00577a.png">

###線形変換の合成
(0, 0),(1, 0),(1, 1),(0, 1)で囲まれる図形を行列

```math
\begin{pmatrix}
2 & 1 \\
1 & 3 
\end{pmatrix}
```

で変換した後、行列

```math
\begin{pmatrix}
0 & -1 \\
1 & 0 
\end{pmatrix}
```

で変換する

```python
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax1 = fig.add_subplot(131)
ax2 = fig.add_subplot(132)
ax3 = fig.add_subplot(133)

original = np.array([[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]])
trans1 = np.array([[0, 0]])
trans2 = np.array([[0, 0]])
for ele in original:
    _ele1 = np.array([[2, 1], [1, 3]]) @ ele
    _ele2 = np.array([[0, -1], [1, 0]]) @ _ele1
    trans1 = np.vstack((trans1, np.array([_ele1])))
    trans2 = np.vstack((trans2, np.array([_ele2])))

ax1.plot(original[:,0], original[:,1], marker = ".", label='original')
ax2.plot(trans1[:,0], trans1[:,1], marker = ".", label='trans1')
ax3.plot(trans2[:,0], trans2[:,1], marker = ".", label='trans2')

ax1.legend(loc = 'upper center')
ax2.legend(loc = 'upper center')
ax3.legend(loc = 'upper center')
ax1.set_xlim([-4, 4])
ax1.set_ylim([-4, 4])
ax2.set_xlim([-4, 4])
ax2.set_ylim([-4, 4])
ax3.set_xlim([-4, 4])
ax3.set_ylim([-4, 4])
plt.show()
```

<img width="803" alt="Screen Shot 2020-04-28 at 18.19.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/295c01cc-450c-8796-670e-f0742f07912c.png">

下図のように変換順が異なると、図形も異なる
通常の数式のようにABx = BAxが成り立たないことがわかります

<img width="1025" alt="Screen Shot 2020-04-28 at 18.31.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628168/ab2d1ea4-94a0-da42-0597-bc37e06c8ddd.png">