Python初心者必見!微分方程式を解くたった5つのステップ

Pythonのコードと微分方程式を描いたイラストPython
この記事は約12分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Python初心者必見!

本記事ではPythonを使って微分方程式を解く方法をご紹介します。

プログラミングの初心者から上級者まで、Pythonの使い方から微分方程式の基礎までを丁寧に解説します。

それでは、始めていきましょう。

●Pythonとは

Pythonは、高水準のプログラミング言語で、その特徴はシンプルで読みやすいコードにあります。

科学技術計算やデータ分析、ウェブ開発など、幅広い用途に使用されています。

○Pythonの基本

Pythonは、インデント(スペースやタブ)を使ってコードのブロックを定義する独特の構文を持っています。

また、変数を使用する際には事前に型を定義する必要はありません。

これらの特徴が、Pythonを初心者にも扱いやすい言語としています。

○Pythonのインストール方法

Pythonを使用するためにはまずインストールする必要があります。公式サイトからダウンロードできます。

インストール後には、コマンドプロンプト(またはターミナル)で”python”と入力し、正しくインストールされていることを確認します。

●微分方程式とは

微分方程式とは、未知関数やその微分を含む方程式のことを指します。

自然科学や工学の分野で頻繁に用いられ、現象の理論的背景を説明するのに役立ちます。

○微分方程式の基本

微分方程式の基本は、未知関数とその微分の関係を表す方程式であるということです。

微分方程式は、自然現象や社会現象をモデル化するのに有用で、物理学や生物学、経済学など多岐にわたる分野で使われています。

○微分方程式の種類

微分方程式には主に二つの種類があります。

一つ目は「常微分方程式」で、これは一つの未知関数とその微分のみを含むものです。

二つ目は「偏微分方程式」で、これは二つ以上の未知関数とそれらの偏微分を含むものです。

●Pythonで微分方程式を解く方法

Pythonを使って微分方程式を解くには、scipyというライブラリが有用です。

これは、科学計算を行うためのライブラリで、微分方程式を解くための関数も提供しています。

○サンプルコード1:初級レベルの微分方程式を解く

まずは初級レベルの微分方程式をPythonで解く方法を見ていきましょう。

このコードでは、scipy.integrateのodeint関数を使って微分方程式を解くコードを紹介しています。

この例では、常微分方程式dy/dt = -2yを解いています。

from scipy.integrate import odeint

def func(y, t):
    dydt = -2.0 * y
    return dydt

y0 = 1.0

t = np.linspace(0, 5, 100)

y = odeint(func, y0, t)

このコードを実行すると、初期値y0 = 1.0から始まる微分方程式dy/dt = -2yの解を得ることができます。

np.linspaceは0から5までの区間を100等分して時間の配列を作成しています。

○サンプルコード2:中級レベルの微分方程式を解く

次に、少し複雑な微分方程式に挑戦します。

このコードでは、scipy.integrateのodeint関数を使って微分方程式を解くコードを紹介しています。

この例では、二階の常微分方程式d^2y/dt^2 = -yを解いています。

from scipy.integrate import odeint
import numpy as np

def func(y, t):
    dydt = [y[1], -y[0]]
    return dydt

y0 = [1.0, 0.0]

t = np.linspace(0, 10, 100)

y = odeint(func, y0, t)

このコードを実行すると、初期値y0 = [1.0, 0.0]から始まる微分方程式d^2y/dt^2 = -yの解を得ることができます。

ここで、y[0]はy、y[1]はyの一階微分dy/dtを表しています。

○サンプルコード3:高級レベルの微分方程式を解く

ここまでのステップで基本的な微分方程式の理解とPythonでの解き方を学んできました。

ここでは、さらに難易度を上げた微分方程式の解法をPythonで解く手順を説明します。

サンプルコード3では、二次元の微分方程式系(システム)を解きます。

具体的には、ローレンツ方程式という物理学でよく用いられる方程式を取り上げます。

ローレンツ方程式は次の3つの連立微分方程式からなります。

dx/dt = σ(y-x)
dy/dt = x(ρ-z) – y
dz/dt = xy – βz

ここでσ, ρ, βは定数で、通常はσ=10, ρ=28, β=8/3とすることが多いです。

この例では、これらの値を使用します。

from scipy.integrate import odeint
import numpy as np

# ローレンツ方程式
def lorenz(state, t):
    sigma = 10
    rho = 28
    beta = 8/3
    x, y, z = state  
    return sigma*(y-x), x*(rho-z)-y, x*y-beta*z  # dx/dt, dy/dt, dz/dt

init_state = [1, 1, 1]  # 初期値
t = np.arange(0, 30.0, 0.01)  # 時間軸
solution = odeint(lorenz, init_state, t)  # ローレンツ方程式の数値解

このコードではまず、scipy.integrateodeint関数とnumpyをインポートします。

そして、lorenz関数を定義して、ローレンツ方程式の右辺を定義します。

これにより、微分方程式の形がPythonの関数として表現されます。

次に初期状態init_stateを定義し、時間軸tを設定します。

最後にodeint関数を使って微分方程式を解き、その解をsolutionに格納します。

このコードを実行すると、ローレンツ方程式の解が得られ、それを使ってさまざまな解析や図示が可能になります。

次に、得られた結果を可視化してみましょう。

それにはmatplotlibを使います。

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot(solution[:, 0], solution[:, 1], solution[:, 2])
plt.show()

このコードでは、3次元プロットのためにmatplotlib.pyplotmpl_toolkits.mplot3dをインポートします。

そして、figureを作成し、その上に3Dの軸を描きます。その後、解の各要素をプロットし、結果を表示します。

このコードを実行すると、ローレンツ方程式の解が3次元空間上に描かれ、蝶形に見える特徴的なパターン(ローレンツアトラクタ)が視覚的に確認できます。

以上がPythonを用いた高度な微分方程式の解法です。

ローレンツ方程式はカオス理論の基礎となる方程式で、微小な初期値の違いが結果に大きな違いを生む敏感性を持つため、その解析は非常に興味深いものです。

Pythonを使えばこのように複雑な微分方程式も手軽に解くことができますが、高度な問題に挑戦する際は、微分方程式の理論的な知識が必要になることもあります。

そのため、より深く学びたい方は数学の参考書やオンラインのリソースを活用すると良いでしょう。

●Pythonで微分方程式を解く際の注意点と対処法

Pythonで微分方程式を解く際には、いくつかの注意点があります。

その一つが、微分方程式の解が存在しない、または一意的でない場合です。

初めて微分方程式を扱うとき、すべての方程式が解を持つと思いがちですが、それは必ずしも真ではありません。

例えば、次のような微分方程式は解を持ちません。

from sympy import Function, dsolve, Eq, Derivative, sin
from sympy.abc import x

f = Function('f')
dsolve(Derivative(f(x), x, x) + 9*f(x), f(x))

このコードは二階の微分方程式を解こうとしますが、その解は存在しません。

このため、エラーが発生します。このような問題に直面したときは、微分方程式の形を見直したり、解の存在条件について調査することが必要です。

また、数値計算における別の一般的な問題は、計算精度と計算時間のトレードオフです。

数値解法を使用する場合、計算の精度を上げるためにはより細かい時間ステップを用いる必要があります。

しかし、それは計算時間の増加につながるため、適切なバランスを見つけることが重要です。

さらに、微分方程式の初期値が重要であることも理解しておくべきです。

特に、微分方程式がカオス的な振る舞いを示す場合(例えばローレンツ方程式など)、微小な初期値の違いが解の振る舞いに大きな影響を及ぼします。

以上のように、微分方程式の解析にはさまざまな注意点が伴いますが、それぞれの問題に対してPythonでは有効な対処法があります。

Pythonで微分方程式を解く際には、これらの点を理解しておくことで、より効果的なコーディングが可能となります。

●Pythonを使った微分方程式の応用例

Pythonで微分方程式を解く技術は、実際の問題解決に役立てることができます。

例えば、物理学や経済学など、様々な学問領域で微分方程式は頻繁に利用されます

ここでは、それぞれの分野での応用例を2つ紹介します。

○サンプルコード4:応用例1 – 物理問題への適用

まずは、物理学で頻繁に利用される単振動の問題を考えてみましょう。

この問題は次のような2階の微分方程式で表現されます。

m * d²x/dt² + γ * dx/dt + k * x = 0

ここで、mは質量、γは減衰定数、kはばね定数、xは位置、tは時間を表します。

下記のサンプルコードは、この方程式をPythonで解くためのものです。

import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt

# 微分方程式
def model(x, t):
    dx1dt = x[1]
    dx2dt = -(gamma/m)*x[1] - (k/m)*x[0]
    return [dx1dt, dx2dt]

# パラメータ設定
k = 2.5  # ばね定数
m = 1.5  # 質量
gamma = 0.1  # 減衰定数
x0 = [2, 0]  # 初期位置と速度

t = np.linspace(0, 50, 1000)  # 時間軸
x = odeint(model, x0, t)  # 微分方程式を解く

# 結果をプロット
plt.plot(t, x[:, 0])
plt.xlabel('時間')
plt.ylabel('位置')
plt.title('単振動のシミュレーション')
plt.grid(True)
plt.show()

このコードでは、まずscipy.integrateモジュールのodeint関数を使って微分方程式を解きます。

そしてmatplotlib.pyplotを使って結果をグラフに表示します。

初期位置と速度を[2, 0]と設定し、時間の範囲を0から50までとしています。

結果は、振動が時間とともに減衰していく様子を示しています。

○サンプルコード5:応用例2 – 経済学のモデリングに適用

経済学では、投資や貯蓄などの経済的行動を理解するために微分方程式が使用されます。

ここでは、ソロー・スワンモデルという経済成長モデルを考えてみましょう。

このモデルは次の微分方程式で表されます。

dK/dt = sY - (δ + n + g)K

ここで、Kは資本ストック、YはGDP、sは貯蓄率、δは固定資本減耗率、nは労働人口成長率、gは技術進歩率を表しています。

下記のサンプルコードは、この経済成長モデルをPythonで解くためのものです。

from scipy.integrate import solve_ivp

# パラメータ設定
s = 0.2  # 貯蓄率
delta = 0.05  # 固定資本減耗率
n = 0.01  # 労働人口成長率
g = 0.02  # 技術進歩率

# 微分方程式
def solow_swan(t, k):
    return s*k**(1/3) - (delta + n + g)*k

# 初期資本
k0 = [1]

# 微分方程式を解く
sol = solve_ivp(solow_swan, [0, 100], k0, t_eval=np.linspace(0, 100, 200))

# 結果をプロット
plt.plot(sol.t, sol.y[0])
plt.xlabel('時間')
plt.ylabel('資本ストック')
plt.title('ソロー・スワンモデルによる経済成長のシミュレーション')
plt.grid(True)
plt.show()

このコードでは、scipy.integrate.solve_ivp関数を使って微分方程式を解きます。

また、微分方程式の形式がdK/dt = sY - (δ + n + g)Kとなっているため、これをコード上で実装するためにはk**(1/3)という形でKの立方根を用います。

初期の資本ストックを1として、時間の範囲を0から100までとし、微分方程式を解きます。

結果は資本ストックが時間とともに増加し、最終的に一定の値に収束していく様子を示しています。

まとめ

この記事では、Pythonを使用して微分方程式を解く方法を学びました。

具体的なサンプルコードを通じて、初心者でも理解しやすいように、微分方程式の基礎から応用までを幅広く解説しました。

微分方程式は物理学や経済学など、多くの学問領域で利用されています。

Pythonで微分方程式を扱う技術を身につけることで、より多くの問題に対応できるようになり、新たな視点で問題を解く力を身につけることができます。

これからもPythonを活用して、数学の問題解決に挑戦してみてください。