この記事について
線形写像とか固有値とかが、何をしているのかよく分からなかったので、
pythonの練習ついでに作ってみました。
matplotlibとnumpy行列演算とtkinterが融合してます。
ただの勉強の副産物です。需要?信憑性?…あっ…ないです…
結論
\boldsymbol{r} = A\boldsymbol{v} \\
\\
\begin{pmatrix}
x_1 \\
y_1
\end{pmatrix}
 = 
\begin{pmatrix}
1 & 2 \\
3 & 4
\end{pmatrix}
\begin{pmatrix}
x_0 \\
y_0
\end{pmatrix}
こんな感じで作用してる真ん中の2*2の行列をAとしています。
x1とかの"r"eturnベクトルが変換後で、
x0とかの"v"ectorが変換前としたときに、
 
これが、
 
こう。
 
ベクトルつけると、こう。
\boldsymbol{r} = (t*A)\boldsymbol{v}
のようにt倍したものという式にして、tを下のバーで動かすと、
 
こう。
とまあこのように、
変換前の(x0,y0)を格子状の点として用意して、
その子らがどんな感じで(x1,y1)に動くか(移動過程ではなく、それぞれの行き先)
を見たいというのが目的です。
移動過程も見たいのですが、どうしたらいいのかわかりませんでした。
コード
コードはこんなのです。パパっと作っちゃったので、なっげぇです。
import tkinter
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
import numpy as np
# ベクトルも書きます?
vec_flag = True
### 関数 ###
# スライダーを移動したとき
def slider_scroll(
        value,
        x_min, x_max, x_n,
        y_min, y_max, y_n,
        A):
    t = float(value) # valueはstr()っぽいから治す
    x_data, y_data = create_point(x_min, x_max, x_n, y_min, y_max, y_n, t, A)
    if vec_flag == True:
        ax.cla()
        ax.quiver(o_x_data, o_y_data, x_data-o_x_data, y_data-o_y_data, color = "orange",
                angles = 'xy', scale_units = 'xy', scale = 1) # 始点x,始点y, 成分x, 成分y
        ax.plot(x_data, y_data, marker='o', linestyle="None") # https://beiznotes.org/matplotlib-plot-without-line/
        ax.grid()
    else:
        line.set_xdata(x_data)
        line.set_ydata(y_data)
    canvas.draw()
# 点を用意する関数(分かりやすい書き方なので最適化はお願いします)
def create_point(
        x_min, x_max, x_n,
        y_min, y_max, y_n,
        t, A):
    # arange用の分割幅を先に計算
    dx_width = (x_max - x_min)/(x_n)
    dy_width = (y_max - y_min)/(y_n)
    x_line = np.arange(x_min, x_max, dx_width) # 一列用意して
    x_data = np.tile(x_line, (y_n, 1)) # 並べる
    y_line = np.arange(y_min, y_max, dy_width) # 一列用意して
    y_line = y_line.reshape(y_n,1) # 行にして
    y_data = np.tile(y_line, (1, x_n)) # 並べる
    result_x = x_data.copy()
    result_y = y_data.copy()
    for x in range(x_n):
        for y in range(y_n):
            vector = np.array(
                    [[x],
                     [y]]
                    ) # ベクトル用意
            result = np.dot(t*A, vector) # 行列の積(pythonでは内積で書く)
            result_x[x,y] = result[0]
            result_y[x,y] = result[1]
    # 次元を1に矯正
    result_x = result_x.reshape(1, x_n*y_n)
    result_y = result_y.reshape(1, x_n*y_n)
    result_x = np.squeeze(result_x)
    result_y = np.squeeze(result_y)
    return result_x, result_y
if __name__ == "__main__":
    ### 変数 ###
    x_min = 0 # x_minから
    x_max = 5 # x_maxまで
    x_n = 5 # x_n個プロット
    y_min = 0 # y_minから
    y_max = 5 # y_maxまで
    y_n = 5 # y_n個プロット
    t = 1 # t倍して変化を見るための係数
    theta = 0 # 回転行列とか用の媒介変数
    A = np.array( # 表現行列
        [
            [1, 0],
            [0, 1]
        ]
    )
    # 単位行列
    E = np.array( # 表現行列
        [
            [1, 0],
            [0, 1]
        ]
    )
    #グラフデータ
    o_x_data, o_y_data = create_point(x_min, x_max, x_n, y_min, y_max, y_n, t, E)
    ### 表示本体 ###
    root = tkinter.Tk()
    root.title("matplotlib 埋め込み")
    #グラフ用オブジェクト生成
    fig = Figure(figsize=(5, 5))   #Figure
    ax = fig.add_subplot(1, 1, 1)           #Axes
    ax.set_xlim([x_min-1, x_max])
    ax.set_ylim([y_min-1, y_max])
    line, = ax.plot(o_x_data, o_y_data, marker='o', linestyle="None") # https://beiznotes.org/matplotlib-plot-without-line/
    ax.grid() # グリッド追加
    #Figureを埋め込み
    canvas = FigureCanvasTkAgg(fig, master=root)  # A tk.DrawingArea.
    canvas.get_tk_widget().pack()
    #ツールバーを表示
    toolbar=NavigationToolbar2Tk(canvas, root)
    ### スケールなどを用意 https://imagingsolution.net/program/python/tkinter/scale_trackbar/ ###
    # tを操作する用 
    scaleH = tkinter.Scale( root,
                    command = lambda value:slider_scroll(value, x_min, x_max, x_n, y_min, y_max, y_n, A),
                    orient=tkinter.HORIZONTAL,   # 配置の向き、水平(HORIZONTAL)、垂直(VERTICAL)
                    length = 300,           # 全体の長さ
                    width = 20,             # 全体の太さ
                    sliderlength = 20,      # スライダー(つまみ)の幅
                    from_ = -10,            # 最小値(開始の値)
                    to = 10,                # 最大値(終了の値)
                    resolution=0.1,         # 変化の分解能(初期値:1)
                    tickinterval=10         # 目盛りの分解能(初期値0で表示なし)
                    )
    scaleH.set(t)
    scaleH.pack()
    #---------------------------------------------------------------
    tkinter.mainloop()
参考
・tkinterとmatplotlibの合体!について:https://www.python-beginners.com/entry/20210720/1626710254
・グリッド追加 https://www.delftstack.com/ja/howto/matplotlib/how-to-show-pyplot-grid-in-matplotlib/
・スライドボタン追加 https://imagingsolution.net/program/python/tkinter/scale_trackbar/
など、後はわからなかったらその都度つまみ食いしました。ありがとうございました。

