表現行列① 鏡映変換 (対称移動)

表現行列① 鏡映変換 (対称移動)

対称移動

 『線型写像』の記事で、あらゆる種類の線型変換は行列形式で表現できることを解説しました。中でも 鏡映変換 (反転・折り返し) は基本的な線型変換です。いくつかの種類について表現行列を調べてみます。

軸に関する鏡映変換

 任意の点を $x$ 軸に関して折り返す表現行列は
 
\[A=\begin{bmatrix}1&0\\0&-1\\\end{bmatrix}\tag{1}\]
で与えられます。実際、行列 $A$ によって、ベクトル $\boldsymbol{r}=\begin{bmatrix}x\\y\end{bmatrix}$ は
 
\[\begin{bmatrix}
1&0\\0&-1\\\end{bmatrix}
\begin{bmatrix}x\\y\end{bmatrix}
=\begin{bmatrix}x\\-y\end{bmatrix}\tag{2}\]
に変換されます。同様に、$y$ 軸に関する鏡映変換は
 
\[B=\begin{bmatrix}-1&0\\0&1\\\end{bmatrix}\tag{3}\]
で与えられます。鏡映変換を $2$ 回ほどこすと元に戻るので、鏡映変換行列 $Q$ について、常に $Q^2=I$ が成り立ちます。たとえば、(1) の $A$ を $2$ 乗してみると、
 
\[A^2=\begin{bmatrix}1&0\\0&-1\\\end{bmatrix}
\begin{bmatrix}1&0\\0&-1\\\end{bmatrix}=\begin{bmatrix}1&0\\0&1\\\end{bmatrix}\]
となっています。同様に $B^2=I$ も成り立ちます。

 Python を使って、行列 $A$ による $P(3,3)$ の点の移り先を確認しておきましょう。点を表示するために、当サイトの 関数ライブラリ に収められている coordinate() と pointer() を使います。

# SLA_021-1

import numpy as np
import matplotlib.pyplot as plt

# FigureとAxes
fig = plt.figure(figsize = (5, 5))
ax = fig.add_subplot(111)

# FigureとAxes
fig = plt.figure(figsize = (6, 6))
ax = fig.add_subplot(111)

# 座標を準備
coordinate(ax, [-6, 6], [-6, 6])

# 鏡映行列aを定義
a = np.array([[1,  0],
              [0, -1]])

# 変換前の点
p0 = np.array([3, 3])

# 変換後の点
p1 = np.dot(a, p0)

# 変換前の点p0をプロット
pointer(ax, p0[0], p0[1], "P0",
        pcolor = "red", textsize = 15)

# 変換前の後の点p1をプロット
pointer(ax, p1[0], p1[1], "P1",
        pcolor = "blue", textsize = 15)

plt.show()

 x軸に関する対称移動 (symmetric movement)

 線形変換は点の集合をまとめて変換することもできます。
 
 たとえば、直線 $y=2x$ 上の点を $\begin{bmatrix}t\\2t\end{bmatrix}$ で表すと、行列 $A$ によって
 
\[\begin{bmatrix}1&0\\0&-1\\\end{bmatrix}
\begin{bmatrix}t\\2t\end{bmatrix}
=\begin{bmatrix}t\\-2t\end{bmatrix}\]
に変換されます。これは直線 $y=2x$ 上の点が直線 $y=-2x$ 上に写ることを意味します。これも Python で確認してみましょう。

 numpy.linspace() で x の離散データを作成し、x と 2*x を numpy.vstack で縦に連結すると、直線 $y=2x$ 上の各点を表す 2 次元ベクトルを横に並べた
 
\[\begin{bmatrix}-6.0&-5.8125&-5.625&-5.4375& ... \\
-12.0&-11.625&-11.25&-10.825& ...\end{bmatrix}\]
という行列が生成されます。これに行列を作用させると、すべての点をまとめて変換できます。

# SLA_021-2

# FigureとAxes
fig = plt.figure(figsize = (6, 6))
ax = fig.add_subplot(111)

# 座標を設定
coordinate(ax, [-6, 6], [-6, 6])

# 鏡映行列aを定義
a = np.array([[1,  0],
              [0, -1]])

# x座標データ
x = np.linspace(-6, 6, 65)

# xと2xを縦に結合して直線データを作成
line_0 = np.vstack((x, 2*x))

# 行列aで直線を変換
line_1 = np.dot(a, line_0)

# 変換前の直線と変換後の直線をプロット
ax.plot(line_0[0], line_0[1],
        color = "red", label = "y = 2x")

ax.plot(line_1[0], line_1[1],
        color = "blue", label = "y = -2x")

# 凡例を表示
ax.legend()

plt.show()

 x軸に関する直線の対称移動 (symmetric movement)
 

線形代数セミナー: 射影,特異値分解,一般逆行列

新品価格
¥2,530から
(2019/10/27 13:08時点)

直線に関する鏡映変換

 任意の傾きをもつ直線 $y=mx$ について折り返しは
 
\[C=\frac{1}{1+m^2}
\begin{bmatrix}
1-m^2&2m\\2m&m^2-1\\\end{bmatrix}\tag{4}\]
によって表されます。この変換を実行する reflection()関数を定義して、点 $P_0(3, 3)$ の直線 $y=x/2$ に関する鏡映変換 (対称移動) を確認してみます。

# SLA_021-3

def reflection(x, m):
    a = np.array([[1 - m**2, 2*m],
                  [2*m, m**2 - 1]])
    a = a / (1 + m**2)
    ax = np.dot(a, x)
    return ax

# FigureとAxes
fig = plt.figure(figsize = (6, 6))
ax = fig.add_subplot(111)

# 座標を準備
coordinate(ax, [-6, 6], [-6, 6])

# 鏡映行列aを定義
a = np.array([[1,  0],
              [0, -1]])

# 変換前の点
p0 = np.array([3, 3])

# p0をy=0.5xに関して折り返す
p1 = reflection(p0, 0.5)

# y=0.5xをプロット
x = np.linspace(-6, 6, 65)
ax.plot(x, 0.5*x, color = "gray")

# 変換前の点p0をプロット
pointer(ax, p0[0], p0[1], "P0",
        pcolor = "red", textsize = 15)

# 変換前の後の点p1をプロット
pointer(ax, p1[0], p1[1], "P1",
        pcolor = "blue", textsize = 15)

 直線y=mxに関する鏡映変換 (折り返し)
 [参考文献] 図解でわかる線型代数