🎓 レベル:標準 | 重要度:A(必須)
📎 前提:Schellingの分居モデル | 関連:マルコフ連鎖と定常分布
要点(BLUF)
- 群集行動や感染症の伝播は、個体が局所的に接触して状態を移すエージェントモデルで自然に表せます。
- 格子上の SIR モデル(感受性 S → 感染 I → 回復 R)で、感染確率 がある閾値を超えると、小さなくすぶりから全体流行へ相転移します。
- で最終感染率 1%、 で 60% へ急変——パーコレーション的な創発する閾値現象を実証します。
1. エージェントベースの SIR モデル
感染症の古典は SIR(Susceptible / Infected / Recovered)です。各個体を格子上のエージェントとし、状態を持たせます。
- 状態:S(未感染・感受性)、I(感染中)、R(回復・免疫)。
- 感染ルール:S の個体は、周囲8近傍に感染者がいると確率的に感染。感染者1人につき感染確率 、近傍に 人いれば感染確率 。
- 回復ルール:I の個体は毎ステップ確率 で R になる(平均感染期間 )。
- 局所性:感染は隣接した個体の間でのみ起きる(平均場ではなく空間構造を持つ)。
平均化された ODE 版 SIR(稀少事象や疫学の本拠)と違い、エージェント版は空間的なクラスタ形成や個体のばらつきを直接表現できます。
2. 実装と流行曲線
import numpy as np
from scipy.signal import convolve2d
def abm_sir(L, beta, gamma, steps, seed, init_inf=5):
rng = np.random.default_rng(seed)
state = np.zeros((L, L), int) # 0=S, 1=I, 2=R
for _ in range(init_inf):
state[rng.integers(L), rng.integers(L)] = 1 # 初期感染者
I_series = [(state == 1).sum()]
for t in range(steps):
new = state.copy()
# 各セルの感染中の近傍数
inf_nb = convolve2d((state==1).astype(int), np.ones((3,3),int),
mode='same', boundary='wrap') - (state==1)
susceptible = (state == 0)
p_infect = 1 - (1-beta)**inf_nb # 近傍感染者からの感染確率
infect = susceptible & (rng.random((L,L)) < p_infect)
new[infect] = 1
recover = (state==1) & (rng.random((L,L)) < gamma) # 回復
new[recover] = 2
state = new
I_series.append((state==1).sum())
if (state==1).sum() == 0: break # 感染者ゼロで終息
attack_rate = (state==2).sum() / (L*L) # 最終感染率
return attack_rate, max(I_series)/(L*L), int(np.argmax(I_series))
ar, peak, t_peak = abm_sir(L=100, beta=0.07, gamma=0.1, steps=400, seed=3)
print(f"beta=0.07: 最終感染率={ar:.3f} 流行ピーク={peak:.1%} (t={t_peak})")
出力:
beta=0.07: 最終感染率=0.983 流行ピーク=10.3% (t=97)
出力の意味:感染確率 では、5人の初期感染者から始まって最終的に人口の98%が感染(R になった)し、流行のピーク(同時感染者が最大)は t=97 で人口の10.3%。感染者数が一度盛り上がってから収束する典型的な流行曲線(エピデミックカーブ)が、局所接触ルールだけから生まれます。
3. 創発する閾値:流行は急に立ち上がる
最も重要な創発現象が閾値(threshold)です。 を少しずつ上げると、流行は連続的にではなくある点で急に全体に広がります。
import numpy as np
from scipy.signal import convolve2d
def abm_sir(L, beta, gamma, steps, seed, init_inf=5):
rng = np.random.default_rng(seed)
state = np.zeros((L, L), int)
for _ in range(init_inf):
state[rng.integers(L), rng.integers(L)] = 1
I_series = [(state==1).sum()]
for t in range(steps):
new = state.copy()
inf_nb = convolve2d((state==1).astype(int), np.ones((3,3),int),
mode='same', boundary='wrap') - (state==1)
infect = (state==0) & (rng.random((L,L)) < 1-(1-beta)**inf_nb)
new[infect] = 1
recover = (state==1) & (rng.random((L,L)) < gamma)
new[recover] = 2
state = new
I_series.append((state==1).sum())
if (state==1).sum() == 0: break
return (state==2).sum()/(L*L), max(I_series)/(L*L), int(np.argmax(I_series))
print("beta を上げると流行が相転移する(gamma=0.1, 100x100, seed=3):")
for beta in [0.02, 0.03, 0.04, 0.05, 0.07, 0.10]:
ar, peak, tp = abm_sir(100, beta, 0.1, 400, seed=3)
print(f" beta={beta:.2f}: 最終感染率={ar:.3f} ピーク={peak:.1%} (t={tp})")
出力:
beta を上げると流行が相転移する(gamma=0.1, 100x100, seed=3):
beta=0.02: 最終感染率=0.001 ピーク=0.1% (t=1)
beta=0.03: 最終感染率=0.011 ピーク=0.2% (t=42)
beta=0.04: 最終感染率=0.597 ピーク=2.6% (t=142)
beta=0.05: 最終感染率=0.922 ピーク=4.7% (t=209)
beta=0.07: 最終感染率=0.983 ピーク=10.3% (t=97)
beta=0.10: 最終感染率=0.997 ピーク=16.3% (t=61)
出力の意味: では感染がほぼ広がらず(最終感染率1.1%、すぐ終息)、ところが に上げると突然最終感染率が60%へ跳ね上がる。この の間に閾値があり、それを境に「くすぶって消える」か「全体に広がる」かが切り替わります。これはパーコレーション転移と同種の相転移で、感染ネットワークが「臨界点」を超えて繋がるかどうかで決まります。個々の感染確率はわずかしか変えていないのに、マクロな帰結が劇的に変わる——これが流行モデルの核心的な創発です。
数式の直観的意味
閾値現象は「局所的な繋がりが、ある密度を超えると大域的な連結成分を作る」というパーコレーションの幾何です。感染が広がるには、感染者が回復する()までの間に平均1人以上の新規感染を生む必要がある——これが基本再生産数 の条件。格子上では近傍数が限られるので、 がある臨界値を超えて初めて感染経路が空間を貫通して繋がり、流行が「点火」する。 付近のピークが t=142 と遅いのは、臨界点近傍では伝播がぎりぎりで、ゆっくりとしか広がらないため(臨界減速)。閾値を十分超えた では一気に燃え広がりピークが t=61 と早い。Schelling の分居(Schellingの分居モデル)が「緩い選好→強い分居」だったように、ここでも「わずかな感染力の差→流行の有無」という、ミクロとマクロの非線形なギャップが現れます。平均場の ODE では見えにくい空間的な閾値を、エージェントモデルは直接見せてくれます。
⚠️ よくある誤解・落とし穴
- 「感染力が2倍なら被害も2倍」ではない:閾値の近くでは、わずかな の差で被害が桁違いに変わります(非線形)。
- 「全員が感染する」ではない:閾値を超えても、空間構造のため一部は感染を免れます(出力の escaped)。十分大きい で初めてほぼ全員に。
- 「ピークが早い=被害が大きい」ではない:ピーク時刻と最終感染率は別。臨界近傍は遅くてもじわじわ広がります。
- 「ABM と ODE は同じ結果」ではない:空間構造・個体性があると、平均場 ODE より流行が遅く・小さくなりがち。局所性が効きます。
- 「疫学の理論をここで展開」ではない:感染症動態の理論( の導出、ワクチン閾値)は疫学の本拠。ここはエージェント実装と創発的な閾値挙動に集中します(境界)。
対応シミュレーション参照
本文の格子 SIR(default_rng(3))と スイープによる閾値転移(最終感染率が0.03→0.04で1%→60%)。
関連ノート
- Schellingの分居モデル(前提・ミクロからマクロの創発)
- セルオートマトン(局所ルールからのパターン)
- マルコフ連鎖と定常分布(確率的状態遷移)
- 信頼性・稀少事象シミュレーション(稀少事象としての大流行)
- 第7章 エージェントベースモデル 目次
- シミュレーション・モンテカルロ法 全体目次