オンライン数学勉強会用イントロ

はじめに

まとめ

事前準備:sympy インストールとチェック

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
!pip install --upgrade sympy

import sympy as sp
from sympy.plotting import plot
from IPython.display import display

def custom_latex_printer(expr, **options):
    from IPython.display import Math, HTML
    from google.colab.output._publish import javascript
    url = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-AMS_CHTML"
    javascript(content="""window.MathJax = {
        tex2jax: {
            inlineMath: [ ['$','$'] ],
            processEscapes: true
        }
        };""")
    javascript(url=url)
    return sp.latex(expr, **options)

sp.init_printing(use_latex="mathjax", latex_printer=custom_latex_printer)

x = sp.Symbol('x')
expr = x**2-12*x+8
display(expr)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Collecting sympy
[?25l  Downloading https://files.pythonhosted.org/packages/ce/5b/acc12e3c0d0be685601fc2b2d20ed18dc0bf461380e763afc9d0a548deb0/sympy-1.5.1-py2.py3-none-any.whl (5.6MB)
     |████████████████████████████████| 5.6MB 3.3MB/s
[?25hRequirement already satisfied, skipping upgrade: mpmath>=0.19 in /usr/local/lib/python3.6/dist-packages (from sympy) (1.1.0)
Installing collected packages: sympy
  Found existing installation: sympy 1.1.1
    Uninstalling sympy-1.1.1:
      Successfully uninstalled sympy-1.1.1
Successfully installed sympy-1.5.1



<IPython.core.display.Javascript object>

$\displaystyle x^{2} - 12 x + 8$

はじめの注意

大方針

勉強のコツ

進め方の方針

基礎コンテンツの紹介

講座の構成

  1. 数学に関わる Python の基礎
    • 重要なライブラリ numpy のまとめ
    • 重要なライブラリ matplotlib のまとめ
    • 重要なライブラリ sympy のまとめ
    • 上記ライブラリを使った数学プログラミングのまとめ
  2. 線型代数:ベクトルと行列
  3. 微分積分
  4. 確率
  5. 統計
  6. 常微分方程式
  7. 偏微分方程式

大まかな説明

注意・当面の進めるイメージ

環境構築

Google Colab

Python のインストール

本題:数学とアニメーション

定積分のアニメーション

\begin{align} \int_0^1 f(x) dx &= \lim_{n \to \infty} \frac{1}{n} \sum_{k=0}^{n-1} f \left( \frac{k}{n} \right), \ n = 2 &\Rightarrow \frac{1}{2} \left(f\left(\frac02\right) + f\left(\frac12\right)\right) \ n = 3 &\Rightarrow \frac{1}{3} \left(f\left(\frac03\right) + f\left(\frac13\right) + f\left(\frac23\right)\right) \end{align}

アニメーション用の基本関数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import numpy as np
import matplotlib.pyplot as plt

def scatter_integral_body(num_data, is_left, f, param):
    # 描画領域の指定
    fig = plt.figure(figsize=(param["figsize_x"], param["figsize_y"]))
    subplot = fig.add_subplot(1, 1, 1)
    subplot.set_xlim(param["x_min"], param["x_max"])
    subplot.set_ylim(param["y_min"], param["y_max"])

    # 参考: グラフを折れ線で描く. 折れ線近似の様子を見たい場合に使う.
    #linex = np.linspace(param["x_min"], param["x_max"], num_data)
    #subplot.plot(linex, f(linex), color='blue')

    # 長方形の描画と面積の近似値計算
    area = 0
    step = (param["x_max"] - param["x_min"]) / num_data
    for x0 in np.arange(param["x_min"], param["x_max"], step):
        x = x0 if is_left else x0 + step
        rect = plt.Rectangle((x0, 0), step, f(x), alpha=param["alpha"])
        subplot.add_patch(rect)
        area += step * f(x)

    subplot.text(param["text_x"], param["text_y"], ('area = %f' % area))

    # 関数と三角関数の描画:上の supplot の処理の後に置かないと上の長方形が描かれない
    vf = np.vectorize(f)

    x_for_square = np.linspace(param["x_min"], param["x_max"], param["num_max"])
    y0 = vf(x_for_square)
    plt.plot(x_for_square, y0, color="red")

底辺と高さ 1 の直角三角形の面積

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from ipywidgets import interact

def scatter(num_data, is_left):
    def f(x):
        return x

    param = {
        "x_min": 0.0,
        "x_max": 1.0,
        "y_min": 0.0,
        "y_max": 1.0,
        "figsize_x": 4,
        "figsize_y": 4,
        "alpha": 0.5,
        "text_x": 0.2,
        "text_y": 0.7,
        "num_max": 50
    }
    scatter_integral_body(num_data, is_left, f, param)

num_max = 50
interact(scatter, num_data=(2, num_max, 1), is_left=True)
1
2
3
4
5
6
7
interactive(children=(IntSlider(value=26, description='num_data', max=50, min=2), Checkbox(value=True, descrip…





<function __main__.scatter>

参照用

\begin{align} \int_0^1 f(x) dx &= \lim_{n \to \infty} \frac{1}{n} \sum_{k=0}^{n-1} f \left( \frac{k}{n} \right), \ n = 2 &\Rightarrow \frac{1}{2} \left(f\left(\frac02\right) + f\left(\frac12\right)\right) \ n = 3 &\Rightarrow \frac{1}{3} \left(f\left(\frac03\right) + f\left(\frac13\right) + f\left(\frac23\right)\right) \end{align}

二次関数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from ipywidgets import interact

def scatter(num_data, is_left):
    def f(x):
        return x**2

    param = {
        "x_min": 0.0,
        "x_max": 2.0,
        "y_min": 0.0,
        "y_max": 4.0,
        "figsize_x": 4,
        "figsize_y": 4,
        "alpha": 0.5,
        "text_x": 0.2,
        "text_y": 3.0,
        "num_max": 50
    }
    scatter_integral_body(num_data, is_left, f, param)

num_max = 50
interact(scatter, num_data=(2, num_max, 1), is_left=True)
1
2
3
4
5
6
7
interactive(children=(IntSlider(value=26, description='num_data', max=50, min=2), Checkbox(value=True, descrip…





<function __main__.scatter>

定積分の大雑把なまとめ

1 次元の波動方程式

偏微分方程式としての波動方程式

\begin{align} u_{tt} = c^2 u_{xx}, \quad \frac{\partial^2 u}{\partial t^2} = c^2 \frac{\partial^2 u}{\partial x^2}. \end{align}

\begin{align} \frac{\partial u}{\partial t} &= \lim_{\Delta t \to 0}\frac{u(t + \Delta t, x) - u(t,x)}{\Delta t} \ &\simeq \frac{u(t + \Delta t, x) - u(t,x)}{\Delta t} \end{align}

\begin{align} \frac{\partial^2 u}{\partial t^2} = \frac{\partial}{\partial t} \frac{\partial u}{\partial t}= \frac{u_t(t+\Delta t,x) - u_t(t,x)}{\Delta t} &\simeq \frac{\frac{u(t + \Delta t, x) - u(t,x)}{\Delta t} - \frac{u(t , x) - u(t- \Delta t,x)}{\Delta t}}{\Delta t} \end{align}

最終的に計算する式

\begin{align} u(t + \Delta t, x ) = 2 u(t,x) - u(t - \Delta t, x) + \left(\frac{c \Delta t}{\Delta x}\right)^2 \left(u(t, x + \Delta x) - 2 u(t,x) + u(t, x - \Delta x) \right). \end{align}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from IPython.display import HTML
from matplotlib import animation
from tqdm import tqdm
import numpy as np
import matplotlib.pyplot as plt

lx = 1  # 計算領域の長さ
nx = 41 # 領域の分割数
xs = np.linspace(0, lx, nx)

def wave(nx):
    dx = lx / (nx - 1) # 空間方向の刻み
    nt = 500           # 計算回数
    dt = 0.01          # 時間刻み
    c = 1              # 波の速度
    f = 2.0            # 強制振動の周波数

    # 初期条件
    u0 = np.zeros(nx)

    # 結果の配列と nt, nx の次元を持つ配列で初期化
    us = np.zeros((nt, len(u0)))

    # 初期条件を結果の配列の各行にコピー
    us[:,:] = u0.copy()

    alpha = (c * dt / dx)**2

    for i in tqdm(range(1, nt-2)):
        t = i * dt
        # 左端を強制振動
        us[i, 0] = np.sin(2 * np.pi * f * t)
        us[i+1, 0] = np.sin(2 * np.pi * f * t)

        # 時間発展
        us[i+1, 1:-1] = 2 * us[i, 1:-1] - us[i-1, 1:-1] \
                        + alpha * (us[i, 2:] - 2 * us[i, 1:-1] + us[i, :-2])
        # 右端の境界値指定
        us[i+1, nx-1] = 0

    return us


## 解
us = wave(nx)

fig = plt.figure();

## グラフの軸の設定
ax = plt.axes(xlim=(0, lx), ylim=(-5, 5));
line, = ax.plot([], [], lw=2);

def animate(u):
    line.set_data(xs, u)
    return line

anim = animation.FuncAnimation(fig, animate, frames=us, interval=50)
#anim.save('07-pde_03_wave_ex01.tmp.mp4', writer="ffmpeg")
plt.close(anim._fig)
HTML(anim.to_jshtml(default_mode='reflect'))

1 次元の拡散方程式

偏微分方程式としての拡散方程式

\begin{align} \frac{\partial u}{\partial t}= \nu \frac{\partial^2 u}{\partial x^2}. \end{align}

最終的に計算する式

\begin{align} u(t+ \Delta t, x) = u(t, x) + \nu \frac{\Delta t}{(\Delta x)^2} (u(t, x + \Delta x) - 2u(t,x) + u(t, x - \Delta x)). \end{align}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import HTML
from matplotlib import animation

lx = 2  # 計算領域の長さ
nx = 41 # 領域の分割数
xs = np.linspace(0, lx, nx)

def diffusion(nx):
    dx = lx / (nx - 1) # 空間方向の刻み
    dt = 0.001         # 時間刻み
    nt = 200           # 計算回数
    nu = 1.0           # 拡散係数

    # 初期条件:中央以外すべて 0
    u0 = np.zeros(nx)
    # 真ん中に物質を置く
    x_center = int((nx - 1) / 2)
    u0[x_center-2: x_center+2] = 1

    # 結果の配列と nt, nx の次元を持つ配列で初期化
    us = np.zeros((nt, len(u0)))

    # 初期条件を結果の配列の各行にコピー
    us[:,:] = u0.copy()

    for i in range(0, nt-1):
        us[i+1, 1:-1] = us[i, 1:-1] + nu * dt / dx**2 *  (us[i, 2:] - 2 * us[i, 1:-1] + us[i, :-2])

    return us

us = diffusion(nx)

fig = plt.figure();

ax = plt.axes(xlim=(0, lx), ylim=(0, 1.2));
line, = ax.plot([], [], lw=2);

def animate(u):
    line.set_data(xs, u)
    return line

anim = animation.FuncAnimation(fig, animate, frames=us, interval=50)
#anim.save('07-pde_04_diffusion_ex01.tmp.mp4', writer="ffmpeg")
plt.close(anim._fig)
HTML(anim.to_jshtml(default_mode='reflect'))

2 次元の波動方程式

偏微分方程式としての波動方程式

\begin{align} u_{tt} = c^2 (u_{xx} + u_{yy}). \end{align}

最終的に計算する式

\begin{align} &u(t + \Delta t, x, y) \ &= 2 u(t,x,y) - u(t - \Delta t, x, y) \ \quad &+ \left(\frac{c \Delta t}{\Delta x}\right)^2 \left(u(t, x + \Delta x,y) - 2 u(t,x,y) + u(t, x - \Delta x,y) \right) \ \quad &+ \left(\frac{c \Delta t}{\Delta y}\right)^2 \left(u(t, x,y + \Delta y) - 2 u(t,x,y) + u(t, x,y - \Delta y) \right) \ \end{align}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
from IPython.display import HTML
from matplotlib import animation
from mpl_toolkits.mplot3d import Axes3D
from tqdm import tqdm
import numpy as np
import matplotlib.pyplot as plt

lx = 1  # 計算領域の長さ
ly = 1  # 計算領域の長さ
nx = 11 # 領域の分割数
ny = 11 # 領域の分割数
nx_center = int((nx - 1) / 2)
ny_center = int((ny - 1) / 2)
xs = np.linspace(0, lx, nx)
ys = np.linspace(0, ly, ny)

x1d = np.linspace(0, lx, nx)
y1d = np.linspace(0, ly, ny)
xs, ys = np.meshgrid(x1d, y1d)

def wave(nx, ny):
    dx = lx / (nx - 1)
    dy = ly / (ny - 1)
    nt = 300           # 計算回数
    dt = 0.5 * dx * dy # 時間刻み
    c = 1              # 波の速度
    f = 2.0            # 強制振動の周波数

    # 初期条件
    u0 = np.zeros((nx, ny))

    # 結果の配列と nt, nx, ny の次元を持つ配列で初期化
    us = np.zeros((nt, nx, ny))

    # 初期条件を結果の配列の各行にコピー
    us[:,:,:] = u0.copy()

    alpha_x = (c * dt / dx)**2
    alpha_y = (c * dt / dy)**2

    for i in tqdm(range(1, nt-2)):
        t = i * dt
        # 中心を強制振動
        us[i, nx_center, ny_center] = np.sin(2 * np.pi * f * t)
        us[i+1, nx_center, ny_center] = np.sin(2 * np.pi * f * t)

        # 時間発展
        us[i+1, 1:-1, 1:-1] = 2 * us[i, 1:-1, 1:-1] - us[i-1, 1:-1, 1:-1] \
                            + alpha_x * (us[i, 2:, 1:-1] - 2 * us[i, 1:-1, 1:-1] + us[i, :-2, 1:-1]) \
                            + alpha_y * (us[i, 1:-1, 2:] - 2 * us[i, 1:-1, 1:-1] + us[i, 1:-1, :-2])
        # 境界値指定
        us[i+1, 0, :] = 0
        us[i+1, nx-1, :] = 0
        us[i+1, :, 0] = 0
        us[i+1, :, ny-1] = 0

    return us


## 解
us = wave(nx, ny)

fig = plt.figure();
ax = fig.add_subplot(111, projection='3d')
ax.set_xlim(0, lx)
ax.set_ylim(0, ly)
ax.set_zlim(-2, 2)
ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
ax.set_zlabel('$u$')
surf = ax.plot_surface(xs, ys, us[0], rstride=1, cstride=1, linewidth=0, cmap='jet')

def animate(u):
    return ax.plot_surface(xs, ys, u, rstride=1, cstride=1, linewidth=0, cmap='jet')
    #surf.set_data(u)
    #return surf

anim = animation.FuncAnimation(fig, animate, frames=us, interval=50)
#anim.save('07-pde_06_wave_2dim_ex01.tmp.mp4', writer="ffmpeg")
plt.close(anim._fig)
HTML(anim.to_jshtml(default_mode='loop'))

微分方程式の大雑把なまとめ

次回以降

質疑応答

要望メモ

アンケート

毎回アンケートを取っています. 質問や要望がある場合もこちらにどうぞ.

アンケートは匿名なので気楽にコメントしてください. 直接返事してほしいことがあれば, メールなど適当な手段で連絡してください.