変数分離形の微分方程式を解く

変数分離形は、1階常微分方程式の中で最も基本的かつ重要な形式の一つです。右辺が $x$ だけの関数と $y$ だけの関数の積で表せる場合、変数を分離して両辺を別々に積分することで解を求められます。

人口増加モデル、放射性崩壊、化学反応速度など、自然現象の多くが変数分離形の微分方程式で記述されます。本記事では、変数分離の手順を丁寧に解説し、具体的な応用例をPython実装とともに紹介します。

本記事の内容

  • 変数分離形の定義と判別法
  • 解法の手順
  • 具体例(指数増減、ロジスティック方程式)
  • Pythonでの数値解法と可視化

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

変数分離形とは

次の形の1階常微分方程式を変数分離形と呼びます。

$$ \frac{dy}{dx} = f(x) \cdot g(y) $$

右辺が $x$ だけの関数 $f(x)$ と $y$ だけの関数 $g(y)$ の積に分解できるのが特徴です。

解法の手順

$g(y) \neq 0$ のとき、次のように変数を分離します。

$$ \begin{align} \frac{dy}{dx} &= f(x) \cdot g(y) \\ \frac{1}{g(y)} \, dy &= f(x) \, dx \\ \int \frac{1}{g(y)} \, dy &= \int f(x) \, dx + C \end{align} $$

左辺は $y$ のみ、右辺は $x$ のみの積分となり、それぞれを独立に計算できます。

注意: $g(y_0) = 0$ となる $y_0$ が存在する場合、$y = y_0$ は定数解(平衡解)となります。この解は変数分離の過程で失われるため、別途確認が必要です。

具体例

例1: 指数増減 $y’ = ky$

最も基本的な変数分離形です。$k > 0$ なら指数増加、$k < 0$ なら指数減衰を表します。

$$ \begin{align} \frac{dy}{dx} &= ky \\ \frac{dy}{y} &= k \, dx \\ \int \frac{dy}{y} &= \int k \, dx \\ \ln|y| &= kx + C_0 \\ y &= Ce^{kx} \quad (C = \pm e^{C_0}) \end{align} $$

初期条件 $y(0) = y_0$ のとき、$C = y_0$ より $y = y_0 e^{kx}$ となります。

例2: ロジスティック方程式 $y’ = ry(1 – y/K)$

人口増加のモデルとして有名な方程式です。$r$ は増加率、$K$ は環境収容力です。

$$ \frac{dy}{dx} = ry\left(1 – \frac{y}{K}\right) $$

変数分離して部分分数分解します。

$$ \begin{align} \frac{dy}{y(1 – y/K)} &= r \, dx \\ \frac{K \, dy}{y(K – y)} &= r \, dx \end{align} $$

部分分数分解 $\frac{K}{y(K-y)} = \frac{1}{y} + \frac{1}{K-y}$ より、

$$ \begin{align} \int \left(\frac{1}{y} + \frac{1}{K-y}\right) dy &= \int r \, dx \\ \ln|y| – \ln|K – y| &= rx + C_0 \\ \ln\left|\frac{y}{K – y}\right| &= rx + C_0 \\ \frac{y}{K – y} &= Ae^{rx} \quad (A = e^{C_0}) \end{align} $$

$y$ について解くと、

$$ y = \frac{KAe^{rx}}{1 + Ae^{rx}} = \frac{K}{1 + \frac{1}{A}e^{-rx}} $$

初期条件 $y(0) = y_0$ より $A = y_0/(K – y_0)$ となり、

$$ \boxed{y(x) = \frac{K}{1 + \left(\frac{K}{y_0} – 1\right)e^{-rx}}} $$

$x \to \infty$ で $y \to K$(環境収容力に漸近)となることが確認できます。

例3: $y’ = \frac{x}{y}$

$$ \begin{align} y \, dy &= x \, dx \\ \int y \, dy &= \int x \, dx \\ \frac{y^2}{2} &= \frac{x^2}{2} + C \\ y^2 – x^2 &= 2C \end{align} $$

これは双曲線の族を表します。

Pythonでの実装

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

# --- 指数増減 y' = ky ---
k_vals = [0.5, -0.3, 1.0]
fig, axes = plt.subplots(1, 3, figsize=(15, 4))

# 指数増減
t = np.linspace(0, 5, 200)
for k in k_vals:
    y = np.exp(k * t)
    axes[0].plot(t, y, label=f'k = {k}')
axes[0].set_xlabel('x')
axes[0].set_ylabel('y')
axes[0].set_title("指数増減 $y' = ky$, $y(0)=1$")
axes[0].legend()
axes[0].grid(True, alpha=0.3)

# --- ロジスティック方程式 ---
K = 100  # 環境収容力
r = 0.5  # 増加率
y0_vals = [5, 20, 50, 120]

def logistic(t, y):
    return r * y * (1 - y / K)

t_span = [0, 20]
t_eval = np.linspace(0, 20, 300)

for y0 in y0_vals:
    sol = solve_ivp(logistic, t_span, [y0], t_eval=t_eval)
    axes[1].plot(sol.t, sol.y[0], label=f'$y_0 = {y0}$')

axes[1].axhline(y=K, color='k', linestyle='--', alpha=0.5, label=f'K = {K}')
axes[1].set_xlabel('t')
axes[1].set_ylabel('y')
axes[1].set_title(f"ロジスティック方程式 (r={r}, K={K})")
axes[1].legend()
axes[1].grid(True, alpha=0.3)

# --- y' = x/y (双曲線族) ---
x_range = np.linspace(-3, 3, 400)
for C in [-2, -1, 0, 1, 2]:
    disc = x_range**2 + 2 * C
    mask = disc > 0
    axes[2].plot(x_range[mask], np.sqrt(disc[mask]), 'b-', alpha=0.6)
    axes[2].plot(x_range[mask], -np.sqrt(disc[mask]), 'b-', alpha=0.6)

axes[2].set_xlabel('x')
axes[2].set_ylabel('y')
axes[2].set_title("$y' = x/y$ の解曲線(双曲線族)")
axes[2].set_xlim(-3, 3)
axes[2].set_ylim(-3, 3)
axes[2].set_aspect('equal')
axes[2].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('separation_of_variables.png', dpi=150, bbox_inches='tight')
plt.show()

ロジスティック方程式のグラフから、初期値によらず解が環境収容力 $K$ に漸近する様子が確認できます。$y_0 > K$ の場合は減少しながら $K$ に近づきます。

まとめ

本記事では、変数分離形の微分方程式の解法を解説しました。

  • 変数分離形は $y’ = f(x) \cdot g(y)$ の形
  • $y$ と $x$ を左辺・右辺に分けて両辺を積分する
  • $g(y) = 0$ の定数解を別途チェックする
  • 指数増減 $y’ = ky$ やロジスティック方程式が代表例
  • 部分分数分解と組み合わせて複雑な例にも対応できる

次のステップとして、以下の記事も参考にしてください。