カテゴリー: メルマガ

  • 経済や生物で使う微分方程式/中高数学駆け込み寺 第 3 回

    こちらに PDF が置いてあります.
    サイトでは見づらい方は PDF をご覧ください.

    マルサスの『人口論』と微分方程式

    あなたが高校生以上なら社会の授業で次のような言葉を聞いたことがあるかもしれません.

    人口は制限されなければ幾何級数的に増加するが生活資源は算術級数的にしか増加しないので生活資源は必ず不足する.

    これは有名なマルサスの『人口論』で議論された話です.
    幾何級数はいわゆる等比数列の和で,
    算術級数は等差数列の和です.
    マルサスは経済学者なので経済の話です.
    経済の話でこういう数学ネタが出てくるわけですね.

    ちなみに大学の経済学だと経済の話で微分積分が本当に出てきます.
    ときどき経済学部の入試で数学が受験科目に入っていることがあります.
    実際に大学に入ってから使うからです.
    それも高校の理系のレベルを越えた数学です.
    統計データをいろいろいじらないといけないので統計学が必要で,
    そっちでも割といろいろ数学が必要です.

    話を元に戻しましょう.
    マルサスの人口論に合わせて人口の増え方を考えます.
    ここではもっと一般的に生物の集団だと思いましょう.
    まずは生物の種類が 1 種類だとして考えていきます.
    生物っぽく人の数というよりも一般に個体数と呼ぶことにして,
    時刻 $t$ での個体数を $x(t)$ とします1.
    個体数の増加率を出生率の死亡率の差として定義します.
    微分方程式的にいうとこれは $x'(t) / x(t)$ です.
    増加率が一定値 $\alpha$ に等しいとすると $x'(t) / x(t) = \alpha$ だから次の微分方程式が出てきます.

    \begin{align}
    \frac{d x(t)}{dt}
    =
    \alpha x(t).
    \end{align}

    この微分方程式をマルサスモデルと言います.
    これを解くと $x(t) = x(0) e^{\alpha t}$ です.
    これで指数関数が出てきました.
    等比数列は一般項が $a_n = 2^{n}$ のように指数関数で書けている数列だから,
    これを足し上げていけばまさに幾何級数になりますね.
    放射性物質の崩壊とは指数の肩の符号が変わっているだけで,
    それ以外は同じ式です.
    放射性物質の崩壊と生物の個体数の変化を追う方程式が同じ形をしているわけです.

    シミュレーション

    シミュレーションの結果は放射性物質の崩壊のときと基本的に同じです.
    いちおうきちんとやっておきましょうか.
    まず微分方程式を次のように近似します.

    \begin{align}\label{math_refuge00005}
    \frac{x_{n+1} – x_{n}}{h}
    =
    \alpha x_n, \quad
    x_{n+1}
    =
    \alpha x_n + h x_n.
    \end{align}

    これにしたがって解いてみましょう.
    プログラムと結果の図はこのページの後半を確認してください.


    少し現実的な設定にしてみる

    もう少し現実的な設定にしてみます.
    個体数 $x(t)$ が大きくなると食物が足りなかったり,
    衛生状態の悪化で病気にかかりやすくなったりして増加率が減るはずです.
    そこで増加率 $\alpha$ を $\alpha – \beta x$ ($\alpha$, $\beta > 0$) に変えてみます.
    \begin{align}
    \frac{dx}{dt}
    =
    (\alpha – \beta x) x.
    \end{align}
    これにはロジスティック方程式という名前がついています.
    悪化を $\beta x$ と書くことに必然性はありません.
    とりあえずやってみただけです.

    ロジスティック方程式の厳密解

    解き方はさておき解は次のようになります.
    あなたがもしこの関数を微分できるなら,
    厳密解になることを計算して確認してみてください.
    \begin{align}
    x(t)
    =
    \frac{\alpha}{\beta} \frac{1}{1 + e^{- \alpha t}}.
    \end{align}

    これを近似すると次のようになります.
    \begin{align}
    \frac{x_{n+1} – x_{n}}{h}
    =
    (\alpha – \beta x_{n}) x_{n}, \quad
    x_{n+1}
    =
    x_n + h (\alpha – \beta x_{n}) x_{n}.
    \end{align}

    これも厳密解と比較しながら計算してみます.
    プログラムや図はこの記事の後半を参照してください.

    近似の精度が気になります

    これもよく近似できていることは認めてもらえるんじゃないでしょうか?
    でもうるさい人は「近似の精度はどう決めるの?」みたいなことを考えているはずです.

    もちろんいたって真っ当な指摘です.
    ただけっこう難しい問題がたくさんあって,
    なかなかスカっと綺麗に回答できません.
    あとで少し考えることにしてここではこのまま進みます.

    生物学として正しいの?

    あなたは数値計算の精度とかそれ以前の問題として,
    次のように思っているかもしれません.

    • この微分方程式で実際の生物の増減にあてはめられるの?
    • もっと現実的なことを考える必要があるんじゃないか?

    もちろんこれも正しい指摘です.

    例えばマルサスモデルでもロジスティック方程式でも右辺が気になります.
    実際には成長しないと子作りできないですからね.
    その成長が必要だという情報が方程式に盛り込まれていません.

    生物で考えるなら食物連鎖があるわけで食べられて個体数が減ることだってあります.
    天敵が増えたらその個体の数はあおりを受けて激減するはずです.

    もちろんこんなことは折り込み済みで,
    例えば遅延型微分方程式,
    ロトカ-ボルテラ方程式と呼ばれる方程式が対応しています.
    これを調べるのも面白いんですが,
    今回はこのくらいにしておきましょう.

    今回のポイント

    簡単にまとめると,
    今回は近似の精度が気になるあなたのために,
    実際どのくらいよく本当の解を近似できているのかを調べました.
    経済学や生物のようにあんまり数学との関係がなさそうな分野と数学の関係も紹介しています.

    数学的ポイント: 数列と漸化式

    長くなってきましたが最後にちょっと大事な話.
    式 \eqref{math_refuge00005} で $\alpha = 1$, $h = 1$ とすると $x_{n+1} = 2 x_n$ になります.
    この漸化式は高校でも出てくるやつで, もちろん公比 $2$ の等比数列の漸化式です.
    底が $2$ か $e$ かの違いはあっても指数関数で書けることは同じです.
    これはたまたまではなくて数学的に意味があることです.

    $x_{n+1} – x_{n}$ のように数列の隣の項の差を差分と言うことがあります.
    もちろん微分との関係を強く意識した言葉です.
    数列の問題, もっと言えば漸化式の問題は微分方程式とも深い関係があります2.
    あまり深入りはしませんが数学や物理に興味があるなら覚えておくといろいろ楽しいことがあります.

    アンケート

    今回もアンケートがあります.
    改善に繋げたいのでぜひ積極的に回答をお願いします.

    ではまた次回をお楽しみに!

    プログラミングパート

    マルサスモデル

    基本は放射性物質の崩壊と同じだからあっさり行こう.

    \begin{align}
    \frac{dx}{dt}
    =
    \alpha u.
    \end{align}
    厳密解は $x(t) = C_0 e^{\alpha t}$ だ.
    初期値を設定すれば $C_0$ はそこから決まる.

    微分を単純に離散化すると次のようになる.

    \begin{align}
    \frac{x_{n+1} – x_{n}}{h}
    =
    \alpha x_{n}.
    \end{align}

    整理すると次の通り.

    \begin{align}
    x_{n+1}
    =
    x_{n} + \alpha h x_{n}.
    \end{align}

    オイラー法でコードに落とそう.

    マルサスモデルの近似解プログラム

    
    %matplotlib inline
    import numpy as np
    import matplotlib.pyplot as plt
    
    def malthus_euler(nt, init = 10):
        dt = 2 / (nt - 1)
        # 初期条件設定
        x = np.zeros(nt)
        x[0] = init
    
        for i in range(1, nt):
            x[i] = x[i-1] + c * dt * x[i-1]
    
        return x
    
    
    c = 1
    init = 1
    nt = 101
    x_approx = malthus_euler(nt, init)
    plt.plot(np.linspace(0, 2, nt), x_approx)
    
    
    t = np.linspace(0, 2, nt)
    x_exact = init * np.exp(c * t)
    plt.plot(t, x_exact)
    
    
    plt.legend(['approximation', 'exact'])
    
    plt.show()
    

    RESULT

    放射性物質の崩壊の時との違い

    t が大きくなると厳密解の方が少し大きくなる.
    指数の肩の符号が違うだけなので,
    放射性物質の崩壊で形式的に時間を負の方に伸ばせば同じようにズレが出てくるはずだ.
    私の今の感覚だとこのズレが今回のように大きくなるように出るのかどうかまではわからない.

    何はともあれ区間の分割数 nt を大きくしてみたのが次の結果:
    具体的には 101 から 1001 にした.

    パラメータを修正して再計算

    ライブラリが読み込まれていたり関数 malthus_euler が定義されている前提のコード片なので,
    これだけで実行できるわけではない.
    IPython か Jupyter なら順にセルを読み込んでいけばそのまま実行できる.

    
    
    c = 1
    init = 1
    nt = 1001
    x_approx = malthus_euler(nt, init)
    plt.plot(np.linspace(0, 2, nt), x_approx)
    
    
    t = np.linspace(0, 2, nt)
    x_exact = init * np.exp(c * t)
    plt.plot(t, x_exact)
    
    
    plt.legend(['approximation', 'exact'])
    
    plt.show()
    

    RESULT

    注意

    $nt = 101$ よりも近似の精度が良くなった.
    この辺は単純に振る舞ってくれるようだ.

    調和振動子だとオイラー法自体がうまく動かないから注意したい.

    ロジスティック方程式

    方程式は次の通り.

    \begin{align}
    \frac{dx}{dt}
    =
    (\alpha – \beta x) x.
    \end{align}

    厳密解は次の通り.

    \begin{align}
    x(t)
    =
    \frac{\alpha}{\beta} \frac{1}{1 + e^{- \alpha t}}.
    \end{align}

    近似すると次の通り.

    \begin{align}
    \frac{x_{n+1} – x_{n}}{h}
    =
    (\alpha – \beta x_{n}) x_{n}, \quad
    x_{n+1}
    =
    x_n + h (\alpha – \beta x_{n}) x_{n}.
    \end{align}

    では数値的に解いてみよう.
    とりあえず $\alpha = 2$, $\beta = 1$ で計算している.

    ロジスティック方程式の近似解プログラム

    
    %matplotlib inline
    import numpy as np
    import matplotlib.pyplot as plt
    
    def logistics_euler(nt, init = 10):
        dt = T / (nt - 1)
        # 初期条件設定
        x = np.zeros(nt)
        x[0] = init
    
        # ベクトル計算で一気に計算したい
        for i in range(1, nt):
            x[i] = x[i-1] + dt * (alpha - beta * x[i-1]) * x[i-1]
    
        return x
    
    
    alpha = 2
    beta = 1
    init = 1
    nt = 101
    T = 5 # 時間変化を見る最大値
    x_approx = logistics_euler(nt, init)
    plt.plot(np.linspace(0, T, nt), x_approx)
    
    
    t = np.linspace(0, T, nt)
    x_exact = (alpha / beta) / (1 + np.exp(- alpha * t))
    plt.plot(t, x_exact)
    
    
    plt.legend(['approximation', 'exact'])
    
    plt.show()
    

    RESULT

    時間の刻みを変えてみる

    近似解と厳密解にちょっとズレが見える.
    そこで nt = 101 から nt = 1001 にしてみた.

    パラメータを修正して再計算

    
    
    alpha = 2
    beta = 1
    init = 1
    nt = 1001
    T = 5 # 時間変化を見る最大値
    x_approx = logistics_euler(nt, init)
    plt.plot(np.linspace(0, T, nt), x_approx)
    
    
    t = np.linspace(0, T, nt)
    x_exact = (alpha / beta) / (1 + np.exp(- alpha * t))
    plt.plot(t, x_exact)
    
    
    plt.legend(['approximation', 'exact'])
    
    plt.show()
    

    RESULT


    1. 本当は $x(t)$ は整数なんですがここではいったん実数だと思っておきます.
      この辺の処理は物理や化学でもよく出てきます.
      実はこの近似というか合理化もきちんとやっておかないといけません.
      ここではとてもやりきれませんけど.
      本当は時間についてもいろいろ議論があります. 
    2. もっと広く力学系と呼ばれる分野にまで広がります.
      力学系まで行くととんでもなく難しくなるのでとてもここで紹介はできません.
      でも幾何学とも関係してきたり整数論とも関係してきたり,
      射程範囲は広いです. 
  • 厳密解との比較: 放射性物質の崩壊/中高数学駆け込み寺 第 2 回

    こちらに PDF が置いてあります.
    サイトでは見づらい方はこちらをご覧ください.

    近似とは?

    今回アニメーションはありませんが引き続きシミュレーションの話をします.
    今回のテーマは近似についてです.

    シミュレーションというのはいいし,
    近似というのもいいけど,
    実際どのくらいよく近似できてるの?

    こういう問題を考えてみましょう.
    ちゃんと使えばすごく精度はいいですよ,
    というのが今回の主張です.

    • 微分方程式というのはいいけど近似なんて雑なことしたくない!
    • 近似なんてやって意味あるの? どうせ大雑把で使いものにならないんじゃないの?
    • 百歩譲って微分方程式は役に立つとしてもその近似計算は本当に役に立つの?

    こんな疑問に答えるのが今回のテーマです.

    放射性物質の崩壊に関する微分方程式

    で, ちょっと不吉な例ではあります.
    しかしというか残念ながらというか,
    役に立つ例になってしまったので放射性物質の崩壊に関する微分方程式を考えてみましょう.
    いちおう微分方程式から書いておきますね.
    \begin{align}\label{math_refuge00002}
    \frac{dx}{dt}
    =
    – c x.
    \end{align}
    気分だけ説明しておくと放射性物質が単位時間あたりに崩壊するスピードはそのときの放射性物質の量に比例する,
    というのを式で書いた形です.
    $c$ には物理的に大事な意味がありますが式や計算を軽くするためにここでは $c = 1$ にして話を進めます.
    そして前回のようにこの微分方程式を近似した式を書いてみます.
    \begin{align}\label{math_refuge00003}
    \frac{x_{n+1} – x_{n}}{h}
    =
    – x_{n}.
    \end{align}
    これは時間間隔 $h$ が十分小さければ時間 $h$ だけ離れた放射性物質の量 $x_{n+1}$ と $x_{n}$ の関係が上の式で書けることを意味しています.

    近似計算はどのくらい正確なの?

    物理的な話はこのくらいにして,
    この式にしたがって近似計算 (シミュレーション) したとき,
    本当の答えと近似した解がどのくらい近いのかを考えてみます.
    何でこれにしたかというともとの方程式の答えが厳密に書けるからです.
    あなたが指数関数, 特に自然対数の底 $e$ をご存知なら,
    式 \eqref{math_refuge00002} の答えは $x(t) = C e^{- t}$ と書けます.
    指数関数の微分をご存知ならこれを \eqref{math_refuge00002} に代入してみて本当に方程式の答えになっていることを確認してみてください.

    この答えと式 \eqref{math_refuge00003} にしたがって計算した答えがどのくらい一致するか,
    コンピュータに計算させてみましょう.
    結果はこの記事の後半,
    プログラムパートに載せてあります.

    近似なんていい加減ことしたくない!

    あなたは「近似なんて雑なことしていいの?」なんて思っているかもしれません.
    でも記事の後半にある「比較のために重ねる」節のグラフを見るとわかるように,
    厳密な様子ともよく合っているのでちゃんと使えば問題ありません.

    「ちゃんと使う」の「ちゃんと」が難しいと言われればそれはもちろんそうなんですが,
    それは本当に難しい話です.

    せっかくなので分割をどんどん大きくしていって近似の精度が上がっていく様子もグラフにしておきました.
    プログラムが書けるとこういうのもささっとやれます.
    遊びやすくなるのは本当にありがたいですね.
    中高生の頃にこれを知っていたら数学や物理だけじゃなくてプログラミングにもはまっていたと思います.

    やってみるとわかるんですが,
    書いたプログラムで意図通りの結果が出るとけっこう嬉しいです.
    パラメータをいじったり方程式を変えたり,
    ちょろっといじって遊べる要素も増えて遊べる範囲が広がるのもいいですね.

    Python プログラミングに関する資料,
    数値計算・シミュレーションに関する資料は GitHub に上げてありますし,
    今後も講座の進展に合わせて少しずつ増やしていくのでぜひあなたも遊んで遊んでみてください.
    このサイトにもいろいろな情報がありますよ.

    数学的なポイントまとめ

    あと今回の中高数学上のポイントを復習しておきます.
    指数関数とか自然対数の底とか,
    はたまたその微分が出てきました.
    放射性物質の崩壊をちゃんと調べるにはこういう数学が必要なんです.

    次回は経済や生物ネタです!

    次回はまた別の微分方程式を紹介します.
    経済学生物学で出てくる微分方程式ですよ.
    これが終わったらもう少し数学的にちゃんとした話をしましょう.
    まずは微分方程式の射程距離の長さを知ってほしいからです.
    もっとちゃんと数学の説明してほしいというあなた,
    もうちょっと我慢してください.

    今回もアンケートがあるのでぜひ回答をお願いします.

    ではまた次回をお楽しみに!

    プログラミングパート

    放射性物質の崩壊

    一番単純でしかも実際に使われる微分方程式として,
    まずは 1 階の線型常微分方程式を考えよう.

    ちょっと不吉な例であるが放射性物質の崩壊の方程式を紹介する.
    導出をしたければちゃんと物理を勉強してもらう必要がある.
    ここでは物理は省略して数学に集中する.

    \begin{align}
    \frac{dx}{dt}
    =
    – c u.
    \end{align}
    厳密解は $x(t) = C_0 e^{-ct}$ だ.
    初期値を設定すれば $C_0$ はそこから決まる.

    微分を単純に離散化すると次のようになる.

    \begin{align}
    \frac{x_{n+1} – x_{n}}{\Delta t}
    =
    -c x_{n}.
    \end{align}

    時間っぽく見えるよう $\Delta t$ と書いてみた.
    タイプが面倒なので $h$ と書くこともある.
    整理すると次の通り.

    \begin{align}
    x_{n+1}
    =
    x_{n} – c (\Delta t) x_{n}.
    \end{align}

    これに沿って計算したのがいわゆるオイラー法.
    コードに落としていこう.

    厳密解のグラフ

    まずは厳密解 $x(t) = e^{-t}$ をグラフに描こう.
    初期値は 1, 上の定数も $c = 1$ としている.

    
    %matplotlib inline
    import numpy as np
    import matplotlib.pyplot as plt
    
    
    c = 1
    init = 1
    nt = 100
    
    
    t = np.linspace(0, 2, nt)
    x_exact = init * np.exp(- c * t)
    plt.plot(t, x_exact)
    
    
    plt.legend(['exact'])
    
    plt.show()
    

    RESULT

    近次解

    今度は近次解を計算してグラフにしてみよう.

    
    %matplotlib inline
    import numpy as np
    import matplotlib.pyplot as plt
    
    def radioactive_euler(nt, init = 10):
        dt = 2 / (nt - 1)
        # 初期条件設定
        x = np.zeros(nt)
        x[0] = init
    
        for i in range(1, nt):
            x[i] = x[i-1] - c * dt * x[i-1]
    
        # ベクトル計算で書き直したい
    
        return x
    
    
    c = 1
    init = 1
    nt = 101
    x_approx = radioactive_euler(nt, init)
    plt.plot(np.linspace(0, 2, nt), x_approx)
    
    
    plt.legend(['approximation'])
    
    plt.show()
    

    RESULT

    比較のために重ねる

    これだけではよくわからないので重ねて描いてみる.

    
    
    x_approx = radioactive_euler(nt, init)
    plt.plot(np.linspace(0, 2, nt), x_approx)
    
    
    t = np.linspace(0, 2, nt)
    x_exact = init * np.exp(- c * t)
    plt.plot(t, x_exact)
    
    
    plt.legend(['approximation', 'exact'])
    
    plt.show()
    

    RESULT

    ほぼピッタリ重なって見える.
    シミュレーションの精度はけっこう良さそうだ.

    もちろん細かいことを言えばいろいろあるけれども,
    それはもっと進んだお話なので一旦不問にしておこう.

    細かく刻んだ方がいい近似になるはずだ

    上のグラフは区間を 100 分割して計算した.
    nt = 101 と言うところで分割を指定している.
    101 と言うのは分点数の指定なので実際の分割としては 100 等分なのだ.

    ここで刻みが荒いといい近似にならないことを大雑把に調べておこう.

    2 等分

    
    
    nt = 3
    x_approx = radioactive_euler(nt, init)
    plt.plot(np.linspace(0, 2, nt), x_approx)
    
    
    nt = 101
    t = np.linspace(0, 2, nt)
    x_exact = init * np.exp(- c * t)
    plt.plot(t, x_exact)
    
    
    plt.legend(['approximation', 'exact'])
    
    plt.show()
    

    RESULT

    4 等分

    何となくそれっぽい形にはなっている.
    もちろん精度は大したことない.

    
    
    nt = 5
    x_approx = radioactive_euler(nt, init)
    plt.plot(np.linspace(0, 2, nt), x_approx)
    
    
    nt = 101
    t = np.linspace(0, 2, nt)
    x_exact = init * np.exp(- c * t)
    plt.plot(t, x_exact)
    
    
    plt.legend(['approximation', 'exact'])
    
    plt.show()
    

    RESULTS

    10 等分

    あまり適当なことを言うのも良くないが, けっこう滑らかに見える.
    精度はまだまだ.

    
    
    nt = 11
    x_approx = radioactive_euler(nt, init)
    plt.plot(np.linspace(0, 2, nt), x_approx)
    
    
    nt = 101
    t = np.linspace(0, 2, nt)
    x_exact = init * np.exp(- c * t)
    plt.plot(t, x_exact)
    
    
    plt.legend(['approximation', 'exact'])
    
    plt.show()
    

    RESULT

    50 等分

    まだ差が目で見える.

    
    
    nt = 51
    x_approx = radioactive_euler(nt, init)
    plt.plot(np.linspace(0, 2, nt), x_approx)
    
    
    nt = 101
    t = np.linspace(0, 2, nt)
    x_exact = init * np.exp(- c * t)
    plt.plot(t, x_exact)
    
    
    plt.legend(['approximation', 'exact'])
    
    plt.show()
    

    RESULT

    1000 等分

    100 は最初にやってあるから一気に大きくしてみた.

    
    
    nt = 1001
    x_approx = radioactive_euler(nt, init)
    plt.plot(np.linspace(0, 2, nt), x_approx)
    
    
    nt = 101
    t = np.linspace(0, 2, nt)
    x_exact = init * np.exp(- c * t)
    plt.plot(t, x_exact)
    
    
    plt.legend(['approximation', 'exact'])
    
    plt.show()
    

    RESULT

    参考

    コンピュータで計算するとき,
    いろいろな都合があって分割数を多くすれば単純に精度が上がっていくと言うわけではない.
    桁落ちや丸め誤差のような問題がある.
    それはそれで別途検討する必要があるのだ.

  • はじめに: 全体の大枠を掴もう/中高数学駆け込み寺 第一回

    こちらに PDF が置いてあります.
    サイトでは見づらい方は PDF をご覧ください.

    講座の目的: 微分方程式のシミュレーション

    今回はイントロとして説明することがいくつかあります.
    私が作っている他の講座と同じように,
    この中高数学駆け込み寺では細かいことを詳しくやっていくよりも,
    数学を勉強するモチベーションになるように数学の大きな姿をお見せしていきます.
    で, 実際に何をするのかというと,
    微分方程式のシミュレーションを通じて中高数学の大枠を掴んでいきます.
    もっと具体的に言うと微分方程式のシミュレーションには中高でやる数学がほとんど全て出てきます.

    • この数学はこんなところでこういう風に使うのか!

    使われているシーンを具体的に見てもらってモチベーションにしてもらおう,
    そんな講座です.
    この講座では文字計算には慣れていることを前提にしています.

    微分方程式って何?

    • 微分方程式はどこでどんな風に使われているの?
    • この講座では具体的にどんなことをするの?

    あなたが中高生なら微分は聞いたこともないかもしれません.
    あなたが中高の数学の復習をしたいと思っている大人なら,
    「自分にはまだ微分なんて早いんじゃ?」と思っているかもしれません.
    メインの微分方程式が何だかわからないんじゃ読み進めるのはきついですよね?
    というわけでまずは微分方程式の説明をします.

    微分方程式は理工系の基礎です.
    いわゆる自然法則は微分方程式で表現されることが多いのです.
    これがどこで使われるかというと,
    例えば洪水が起きたときの被害予測に使われます.
    どんな規模で起きた洪水が市街地のどこまで進入してくるか?
    こういうシミュレーションをテレビで見たことがないでしょうか.
    このシミュレーションに使われているのが微分方程式です.

    微分方程式は何に使うの?

    他にも微分方程式はありとあらゆるところで使われています.
    ゲームの CG を自然に見せるためにはまさに自然法則に則って風や水の動きを表現しないといけません.
    だから微分方程式がその背後に隠れています.
    天気予報はいまの気象条件から未来の様子を予測する必要があります.
    この予測にも微分方程式を使っています.
    機械を動かしていると熱くなることがありますね?
    あまりにも熱くなりすぎると機械が暴走してしまうので熱を効率よく逃がす必要があります.
    そのためには熱の流れを考えてその流体の動きをきちんと制御する必要があります.
    ここでは熱の流れの微分方程式を考えてそれをシミュレーションします.
    車を作るとき空気抵抗を調べるためにも流体力学が必要で,
    シミュレーションも使ってモノづくりにも活かしています.
    他にもいちいち挙げきれないくらい身の回りに微分方程式のシミュレーションを使っているモノがあります.

    微分方程式自体をきちんと調べようと思うと大学の数学が必要です.
    でもシミュレーションを中心に考えれば中高の数学でかなりいろいろなことがわかります.
    わかるだけじゃなくて実際に微分方程式を解いて遊んでみることだってできます.
    この自分でも遊べるところまで持っていけるのが大事じゃないかと思っていて.
    それが微分方程式のシミュレーションを選んだ理由の 1 つです.

    さて, ここまでで微分方程式が何で大事かはわかってもらえたでしょうか?
    これをやれば数学をいろいろ遊び倒せそうと思ってもらえたら嬉しいです.
    ちゃんとがんばれば自分でゲームを作ったりもできますしね.
    次はもう少し数学的な内容に踏み込みましょう.

    何はともあれ微分に関する話をやるわけです.
    そして微分は高校でやる内容です.
    あなたは微分に対して嫌な思い出を持っているかもしれません.
    あなたは「中学レベルからやり直したいのにそんなの無理だ!」と思っているかもしれません.
    もっと簡単なところからやってほしいと思っているかもしれません.

    でもこの講座では中高数学の大枠を掴んでもらう講座です.
    そして今回はこの講座の大枠を掴んでもらう講座です.
    どうかもうしばらく辛抱して読み進めてください.

    シミュレーションの実際

    まず何をするのかを見てもらいたいので,
    次のページを開いて 1 番下までスクロールしてください.
    動画の再生ボタンがありますから動画を再生してみましょう.

    これは 1 次元移流方程式のシミュレーション結果です.
    プログラムを書いてコンピュータに計算させ,
    その結果をアニメーションさせています.
    移流方程式は微分方程式なのでそこで微分を使っています.

    コンピュータは数学的に厳密に微分を計算できません.
    極限を取れないからです.
    そうかといって全く何もできないわけじゃなくて.
    実は微分の定義にしたがって微分を近似して計算しています.
    微分を近似すると実はただの引き算 (と割り算) になります.

    さっきのページの上の方,
    式 (2)-(4) を見てください.
    こっちにも同じ式を書いておきますね.

    \begin{align}
    \frac{\partial u}{\partial x}
    \approx
    \frac{u(x+\Delta x)-u(x)}{\Delta x}.
    \end{align}

    \begin{align}
    \frac{u_i^{n+1}-u_i^n}{\Delta t} + c \frac{u_i^n – u_{i-1}^n}{\Delta x}
    =
    0.
    \end{align}

    \begin{align}
    u_i^{n+1}
    =
    u_i^n – c \frac{\Delta t}{\Delta x}(u_i^n-u_{i-1}^n). \label{math_refuge00001}
    \end{align}

    見ての通り加減乗除の四則演算しかしていません.
    特に上のページの (4) にあたる式 \eqref{math_refuge00001} に注目してください.
    実はこの式にしたがって計算した結果をアニメーションでお見せしたのがさっきの動画です.

    細かいことは追々やっていくとして何をしているか大雑把にいうと,
    ベクトルなり数列なりの計算です.
    また式 \eqref{math_refuge00001} を見てください.
    右上にある添字 $n$ に注目すれば左辺は $n+1$ で右辺は $n$ です.
    これは数列の漸化式とも思えますね?

    数列も高校でやる内容です.
    あなたが中学生ならちんぷんかんぷんでしょう.
    でも実際に高校でやることがモノづくりなり何なりで
    役に立っていることが感じてもらえればとりあえず OK です.
    ちなみに移流方程式は上でもちょっと出てきた流体力学で出てくる微分方程式です.

    もっと言うなら文字式の計算がゴリゴリ出てきていることも注意した方がいいでしょうか?
    文字式できないとこの計算全く追えないですからね.
    細かいことを言い出すときりがないので,
    いったん今回はこのくらいにしておきましょう.
    まとめると今回は次のポイントを掴んでもらえば十分です.

    今回のポイント

    • 微分方程式のシミュレーションをやっていく.
    • シミュレーションは実社会でいろいろな応用がある
    • 微分といっても近似を使うから結局は加減乗除しか使わない.
    • シミュレーションでは文字式の計算, ベクトル, 数列など中高の数学をバリバリ使っている.

    今回くらいのレベルでもベクトルで言うと
    100 次元ベクトルとかそういうレベルの計算が必要です.
    手計算ではやってられないのでプログラムを書いて計算して,
    さらにプログラムを書いて図にしたりアニメーションにしたりしています.
    このプログラミングについてはどこまで深掘りするかは未定です.
    要望が多いなら別にきちんとやろうかとも思っています.

    今回お見せしたのは変数が 2 つある偏微分方程式でちょっと難しいです.
    変数が 2 つあるとややこしいので次回以降,
    しばらく変数が 1 つしかない常微分方程式というのを見ていく予定です.

    最後にアンケートをお願いしています.
    改善に繋げていきたいのでぜひコメントをお願いします.

    では次回をお楽しみに!

  • 数列とは何か?プログラム解説 中高数学駆け込み寺

    1 階の線型常微分方程式

    復習でもう 1 回.

    一番単純でしかも実際に使われる微分方程式としてまずは 1 階の線型常微分方程式を考えよう.
    ちょっと不吉な例であるが放射性物質の崩壊の方程式を紹介する.
    導出をしたければちゃんと物理を勉強してもらう必要がある.
    ここでは物理は省略して数学に集中する.

    \begin{align}
    \frac{dx}{dt} = – c x.
    \end{align}
    厳密解は $x = C_0 e^{-ct}$ だ.
    初期値を設定すれば $C_0$ はそこから決まる.

    微分を単純に離散化すると次のようになる.

    \begin{align}
    \frac{x_{n+1} – x_{n}}{\Delta t}
    =
    -c x_{n}.
    \end{align}

    $\Delta t$ は $h$ と書くこともある.
    整理すると次の通り.

    \begin{align}
    x_{n+1}
    =
    x_{n} – c (\Delta t) x_{n}.
    \end{align}

    これに沿って計算したのがいわゆるオイラー法.
    次のセルではこれをコードに落としている.

    
    %matplotlib inline
    import numpy as np
    import matplotlib.pyplot as plt
    
    import base64
    img_file = "tmp/image.tmp.png"
    
    def radioactive_euler(nt, init = 10):
        dt = 2 / (nt - 1)
        # 初期条件設定
        x = np.zeros(nt)
        x[0] = init
    
        for i in range(1, nt):
            x[i] = x[i-1] - c * dt * x[i-1]
    
        # ベクトル計算で書き直したい
    
        return x
    
     # 近似解
    c = 1
    nt = 101
    init = 5
    x1 = radioactive_euler(nt, init)
    plt.plot(np.linspace(0, 2, nt), x1)
    
     # 厳密解
    t = np.linspace(0, 2, nt)
    x2 = init * np.exp(- c * t)
    plt.plot(t, x2)
    
     # 凡例
    plt.legend(['approximation', 'exact'])
    plt.show()
     # 描画
    #plt.savefig(img_file)
    #b64 = base64.encodestring(open(img_file, 'rb').read()).decode('utf-8')
    #img_str = "" % (b64)
    #print(img_str)
    

    RESULT

    2 階の常微分方程式

    こちらが単振動.

    次に 2 階の常微分方程式を紹介しよう.
    高校の物理で出てくるばねの振動(単振動)がまさにこの例だ.
    項を増やすと減衰振動になったり、外力をつけたりといろいろなケースがある.
    まずは一番単純な式を考えよう.

    \begin{align}
    \frac{d^2 x}{dt^2}
    =
    – \omega^2 x.
    \end{align}

    さっきのオイラー法なりルンゲ-クッタ法なりは 1 階の方程式に対する計算法なので直接は使えない.
    この場合は中間処理として $v = dx/dt$ を置いて計算すればいい.
    これは単なる数値計算の便法ではない.
    速度の意味もあるから, という表面的な理由ではなくもっと深く解析力学の文脈で物理としても大事な視点だ.
    もっといえばシンプレクティック計算法などもっといい計算法にも発展する.

    とりあえずオイラー法で計算したい.
    まずは微分方程式自体を書き直す.

    \begin{align}
    \frac{dx}{dt}
    =
    v, \quad
    \frac{dv}{dt}
    =
    – \omega^2 x.
    \end{align}

    これをオイラー法で近似しよう.

    \begin{align}
    x_{n+1}
    =
    x_{n} + h v_{n}, \quad
    v_{n+1}
    =
    v_{n} – h \omega^{2} x_{n}.
    \end{align}

    オイラー法をコードに落とす.

    
    %matplotlib inline
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib import animation
    
    def harmonic_euler(nt, init = (5, 0)):
        dt = t_range / (nt - 1)
        # 初期条件設定
        x = np.zeros(nt)
        v = np.zeros(nt)
        x[0] = init[0]
        v[0] = init[1]
    
        for i in range(1, nt):
            x[i] = x[i-1] + dt * v[i-1]
            v[i] = v[i-1] - dt * (omega ** 2) * x[i-1]
    
        # ベクトル計算で書き直したい
    
        return (x, v)
    
    
    omega = 2 * np.pi
    nt = 101
    t_range = 2
    init = (5, 0)
    harm = harmonic_euler(nt, init)
    t = np.linspace(0, 2, nt)
    
     # 厳密解
    x_exact = init[0] * np.cos(- omega * t)
    v_exact = - omega * init[0] * np.sin(omega * t)
    
     # グラフ描画
    plt.subplot(3, 1, 1)
    plt.title('x-t graph')
    plt.plot(np.linspace(0, 2, nt), harm[0])
    plt.plot(t, x_exact)
    plt.legend(['x approximation', 'x exact'])
    
    plt.subplot(3, 1, 2)
    plt.title('v-t graph')
    plt.plot(np.linspace(0, 2, nt), harm[1])
    plt.plot(t, v_exact)
    plt.legend(['v approximation', 'v exact'])
    
    plt.subplot(3, 1, 3)
    plt.title('phase space')
    plt.plot(harm[0], harm[1])
    
     # 描画
    plt.tight_layout()
    plt.show()
    #plt.savefig(img_file)
    #b64 = base64.encodestring(open(img_file, 'rb').read()).decode('utf-8')
    #img_str = "" % (b64)
    #print(img_str)
    

    RESULT

    オイラー法では近似の精度が悪い

    見ての通り時間が進むごとに誤差が大きくなる.
    nt を大きくすると少しはましになる.
    実際に上のコードで nt を大きくして再計算してみてほしい.

    あとまずいのは phase space の図だ.
    この系はエネルギーが保存する系だから相空間内の軌道が閉じてほしいのにそうなっていない.
    シンプレクティックにやれば解消できるようだが, とにかくここではよろしくない.

    この方程式でオイラー法はよろしくないことがわかった.
    とりあえずルンゲ-クッタでやってみよう.

    ルンゲ-クッタ法

    とりあえず近似式を書く.

    \begin{align}
    x_{n+1}
    &=
    x_{n} + \frac{h}{6} (k_{1} + 2 k_{2} + 2 k_{3} + k_{4}), \
    t_{n+1}
    &=
    t_{n} + h, \
    k_{1}
    &=
    v_{n}, \
    k_{2}
    &=
    v_{n} + \frac{h}{2} k_{1}, \
    k_{3}
    &=
    v_{n} + \frac{h}{2} k_{2}, \
    k_{4}
    &=
    v_{n} + h k_{3}.
    \end{align}

    次が $v$ の式.

    \begin{align}
    v_{n+1}
    &=
    v_{n} + \frac{h}{6} (k_{1} + 2 k_{2} + 2 k_{3} + k_{4}), \
    t_{n+1}
    &=
    t_{n} + h, \
    k_{1}
    &=
    – \omega^2 x_{n}, \
    k_{2}
    &=
    x_{n} – \frac{h}{2} \omega^2 k_{1}, \
    k_{3}
    &=
    x_{n} – \frac{h}{2} \omega^2 k_{2}, \
    k_{4}
    &=
    x_{n} – h \omega^2 k_{3}.
    \end{align}

    
    %matplotlib inline
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib import animation
    
    def harmonic_rk(nt, init = 10):
        dt = t_range / (nt - 1)
        # 初期条件設定
        x = np.zeros(nt)
        v = np.zeros(nt)
        x[0] = init[0]
        v[0] = init[1]
    
        def fx(t, x, v):
            return v
    
        def fv(t, x, v):
            return - (omega ** 2) * x
    
        # ベクトル計算で書き直したい
        for i in range(1, nt):
            xk1 = fx(dt * (i - 1), x[i-1], v[i-1])
            vk1 = fv(dt * (i - 1), x[i-1], v[i-1])
    
            xk2 = fx(dt * (i - 1/2), x[i-1] + xk1 * dt / 2, v[i-1] + vk1 * dt / 2)
            vk2 = fv(dt * (i - 1/2), x[i-1] + xk1 * dt / 2, v[i-1] + vk1 * dt / 2)
    
            xk3 = fx(dt * (i - 1/2), x[i-1] + xk2 * dt / 2, v[i-1] + vk2 * dt / 2)
            vk3 = fv(dt * (i - 1/2), x[i-1] + xk2 * dt / 2, v[i-1] + vk2 * dt / 2)
    
            xk4 = fx(dt * (i - 1),   x[i-1] + xk3 * dt,     v[i-1] + vk3 * dt)
            vk4 = fv(dt * (i - 1),   x[i-1] + xk3 * dt,     v[i-1] + vk3 * dt)
    
            x[i] = x[i-1] + dt / 6 * (xk1 + 2 * xk2 + 2 * xk3 + xk4)
            v[i] = v[i-1] + dt / 6 * (vk1 + 2 * vk2 + 2 * vk3 + vk4)
    
        return (x, v)
    
    
    omega = 2 * np.pi
    nt = 101
    t_range = 2
    init = (5, 0)
    harm = harmonic_rk(nt, init)
    t = np.linspace(0, 2, nt)
    
    
    x_exact = init[0] * np.cos(- omega * t)
    v_exact = - omega * init[0] * np.sin(omega * t)
    
    
    plt.subplot(3, 1, 1)
    plt.title('x-t graph')
    plt.plot(np.linspace(0, 2, nt), harm[0])
    plt.plot(t, x_exact)
    plt.legend(['x approximation', 'x exact'])
    
    plt.subplot(3, 1, 2)
    plt.title('v-t graph')
    plt.plot(np.linspace(0, 2, nt), harm[1])
    plt.plot(t, v_exact)
    plt.legend(['v approximation', 'v exact'])
    
    plt.subplot(3, 1, 3)
    plt.title('phase space')
    plt.plot(harm[0], harm[1])
    
     # 描画
    plt.tight_layout()
    plt.show()
    #plt.savefig(img_file)
    #b64 = base64.encodestring(open(img_file, 'rb').read()).decode('utf-8')
    #img_str = "" % (b64)
    #print(img_str)
    

    RESULT

    ルンゲ-クッタ短評

    今度の一致具合はなかなかよさそう.
    あくまで見た目の感じではあるけれども.

    良くなったのは一番下の図, 相空間軌道だ: ちゃんと閉じてくれた.

  • 2016-12-12 関数とは何か?/中高数学駆け込み寺

    次の URL から PDF をダウンロードしてください.

    前回から数学の話に入りました.
    今回は関数です.

    微分方程式は関数がみたす関係式,
    方程式に関する話なので関数がとても大事です.

    いろいろとはまるポイントはあるでしょう.
    しかし微分方程式から見て大事なことは
    そんなに夛くありません.

    まずは大きな流れに注目して,
    「何となくこんな感じか」というところだけ
    掴むようにしてください.

    実は数列も関数です.
    ここの理解は微分方程式を理解するときにも
    効いてくる大事なポイントです.

    次回は数列です.
    これも高校だといろいろな話がありますが,
    大事なポイントだけおさえていくので,
    楽しみにしていてください.

    今回のアンケートはこちらです.

    ここまで出したコンテンツは次の通りです。

    サイトにも上げてあるので
    必要ならそこからも辿ってみてください.
    数学や物理をはじめとした
    専門的な情報もいろいろ載っています.

    プログラムについては次のページにまとめてあります.
    追加もしていくのでぜひ確認してください.

    各回ごとにアンケートもあります.
    ぜひそちらの回答もお願いします.
    アンケートの URL は PDF の最後に貼ってあります.

    全体的に作り上げたら整理して
    まとめ直して最初から配信し直そうと思います.
    復習も兼ねてぜひそちらもしっかり見てください.

    この文章はサイトにも上げているのでそちらを見た方へ

    次のページから登録すればメールで
    コンテンツをお届けしていきます.
    いちいちサイトをチェックするのが面倒でしたら
    ぜひこちらから登録しておいてください.

    気に入ったならぜひご友人にも紹介してください.

    ではまたメールします.

  • 2016-12-11 ベクトルとは何か?/中高数学駆け込み寺

    次の URL から PDF をダウンロードしてください.

    前回までは微分方程式のシミュレーションや
    それで実際にできることをお話してきました.

    今回からは数学の話に
    踏み込んでいきます.

    大きな流れを掴んでほしいので,
    微分方程式のシミュレーションからの
    ベクトルの見方に集中して説明しています.

    まずはこんなものかと大掴みにしてください.

    今回のアンケートはこちらです.

    ここまで出したコンテンツは次の通りです。

    サイトにも上げてあるので
    必要ならそこからも辿ってみてください.
    数学や物理をはじめとした
    専門的な情報もいろいろ載っています.

    プログラムについては次のページにまとめてあります.
    追加もしていくのでぜひ確認してください.

    各回ごとにアンケートもあります.
    ぜひそちらの回答もお願いします.
    アンケートの URL は PDF の最後に貼ってあります.

    全体的に作り上げたら整理して
    まとめ直して最初から配信し直そうと思います.
    復習も兼ねてぜひそちらもしっかり見てください.

    この文章はサイトにも上げているのでそちらを見た方へ

    次のページから登録すればメールで
    コンテンツをお届けしていきます.
    いちいちサイトをチェックするのが面倒でしたら
    ぜひこちらから登録しておいてください.

    気に入ったならぜひご友人にも紹介してください.

    ではまたメールします.

  • 第 2 回 厳密解との比較: 放射性物質の崩壊/中高数学駆け込み寺

    次の URL から PDF をダウンロードしてください.

    今回は放射性物質の崩壊の微分方程式を調べてみます.
    もちろん微分方程式を直接調べるわけじゃなくて,
    近似して漸化式を解いています.

    近似なんて適当なことやってても大丈夫なの?
    あなたはこう思っているかもしれません.
    そこで今回は近似の精度について調べてみました.

    別サイトでグラフの比較も出しています.
    ぜひそっちも見てください.

    あなたは数学的に詳しいことが知りたいんだと
    思ってるかもしれません.

    でも, 微分方程式でどんなことをやっているか,
    それを紹介してからじゃないと
    勉強にも身が入らないんじゃないかと心配しています.

    だからもう少しどんなところで
    どう使われているかの話が続きます.

    数学の解説はもうちょっと待っててくださいね.

    今回のアンケートはこちらです.

    ここまで出したコンテンツは次の通りです。

    サイトにも上げてあるので
    必要ならそこからも辿ってみてください.
    数学や物理をはじめとした
    専門的な情報もいろいろ載っています.

    プログラムについては次のページにまとめてあります.
    追加もしていくのでぜひ確認してください.

    各回ごとにアンケートもあります.
    ぜひ回答をお願いします.
    今回のアンケートはこちらです.

    全体的に作り上げたら整理して
    まとめ直して最初から配信し直そうと思います.
    復習も兼ねてぜひそちらもしっかり見てください.

    この文章はサイトにも上げているのでそちらを見た方へ

    次のページから登録すればメールで
    コンテンツをお届けしていきます.
    いちいちサイトをチェックするのが面倒でしたら
    ぜひこちらから登録しておいてください.

    気に入ったならぜひご友人にも紹介してください.

    ではまたメールします.

  • 第 1 回 全体の大枠を掴もう/中高数学駆け込み寺

    初回のコンテンツを配信します.
    次の URL から PDF をダウンロードしてください.

    現代数学観光ツアーに参加されている方には
    初回をすでに配信していますが,
    数学駆け込み寺としては初の配信です.

    本来は順々にコンテンツを配信していくべきなんですが,
    まだ順番も検討中の状態です.

    まずはこんな感じでどうだろう?
    という今の想定で純にコンテンツをお送りしていきます.
    過去分の配信はサイトにも上げていますし,
    メルマガでも最後にまとめておくので,
    しばらくはそちらで対応します.

    • https://phasetr.com/blog/category/mailmagazine/

    一通りコンテンツがまとめられたら
    改めて初回から配信し直していく予定です.
    ぜひ復習に使ってください.

    で, 今回の内容です.
    何をネタにどんなことをするのか,
    ということでちょっと長めになっています.

    微分方程式というごつい言葉も出てきます.
    少しずつ説明していくので,
    いまは「そんなものか」と思って
    さらっと流してください.

    どこで何の役に立つにかも
    簡単に説明していますが,
    正直いろいろなところで使われていて,
    書き切れないくらいです.

    その辺もまた少しずつ紹介していきます.

    初回分を見たあとは
    アンケートへの回答もお願いします.
    現代数学観光ツアーで既にコンテンツを見たというあなた,
    ぜひアンケートにも回答してくださいね.

    • https://goo.gl/forms/uQikzCF209GiCCw92

    あなたのご意見を受けてどんどん
    ブラッシュアップさせていきます.
    アンケート以外にも質問があればお気軽にどうぞ.

    質問への返信は確約できませんが,
    何らかの形でコンテンツには反映させていきます.

    ではまたメールします.

  • コンテンツアーカイブを作りました

    コンテンツアーカイブを作りました

    新たにコンテンツアーカイブを作りました。

    理工系のための総合語学・リベラルアーツのコンセプトのもとに、数学・物理・プログラミング・英語(語学)を中心にしたコンテンツをこれまで以上に見やすく整理しています。

    これまで公開していなかったコンテンツも公開していくので、ぜひコンテンツアーカイブにあくせすしてください。

    コンテンツアーカイブは今後大量のページ・コンテンツを抱えていきます。もしあなたが「自分の趣味・興味に応じて好きなところをつまみ食いしたい」と思っているなら問題はないものの、次のような要望があるのもわかっています。

    • 一つ一つは面白いがコンテンツが多すぎて目が回る。
    • 興味あるものは見るが、実は面白いはずなのにそれが見つからない。
    • シリーズのコンテンツもあるだろうし、見る順番を指定してもらえると助かる。

    実際、ミニ講座としてまとめて作ったコンテンツもあり、一揃いで見てもらえると学習効率・効果が高いコンテンツ群もあります。これについても内容や提示の仕方を刷新し、特にミニ通信講座として提供します。ぜひご自身のご興味に応じて勉強を進めてください。