同期のモデリング
以前の投稿で,ホタルの光モデルというものを見た.
今回はその発展として状態推移を折れ線グラフとして可視化した.こうすることで数という観点からの推移がわかりやすくなる.
コードは下記.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from scipy.spatial.distance import cdist
# パラメータ設定
grid_size = 20 # グリッドのサイズ(20x20)
num_fireflies = grid_size * grid_size # ホタルの総数
positions = np.array([(i, j) for i in range(grid_size) for j in range(grid_size)]) # ホタルの位置
phases = np.random.rand(num_fireflies) # ホタルの初期位相(0から1の間のランダムな値)
T = 1.0 # サイクルタイム
dt = 0.01 # 時間の増分
num_steps = 500 # シミュレーションのステップ数
k = 0.05 # 位相調整の強さ
sync_number = 5 # 同期するホタルの数
sync_distance = 3 # 同期するホタルとの最大距離
# ホタル間の距離を計算
distances = cdist(positions, positions)
# 明るさの履歴と発光ホタル数を保存するリスト
brightness_history = []
num_lit_fireflies = [] # 発光しているホタルの数
# グラフの設定(サブプロットを使用)
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(6, 10))
# ホタルの散布図設定
cmap = plt.cm.get_cmap('hot')
brightness = 1 - phases # 初期の明るさ
scatter = ax1.scatter(positions[:, 0], positions[:, 1], c=brightness, cmap=cmap, s=20)
scatter.set_clim(0, 1)
ax1.set_xlim(-1, grid_size)
ax1.set_ylim(-1, grid_size)
ax1.set_xticks([])
ax1.set_yticks([])
ax1.set_aspect('equal')
ax1.set_title('Firefly Synchronization Simulation')
# 発光しているホタル数を示す折れ線グラフの設定
line, = ax2.plot([], [], color='blue')
ax2.set_xlim(0, num_steps)
ax2.set_ylim(0, num_fireflies)
ax2.set_xlabel('Step')
ax2.set_ylabel('Number of Lit Fireflies')
ax2.set_title('Number of Lit Fireflies Over Time')
# 折れ線グラフのデータ初期化
xdata = []
ydata = []
# 更新関数
def update(frame):
global phases
# 位相を更新
phases = (phases + dt / T) % 1.0
# 位相のコピーを作成
new_phases = np.copy(phases)
# 各ホタルについて同期処理を実行
for i in range(num_fireflies):
# 同期距離内にいるホタルのインデックスを取得
neighbor_indices = np.where((distances[i] > 0) & (distances[i] <= sync_distance))[0]
if len(neighbor_indices) > 0:
# 同期数だけランダムにホタルを選択
num_neighbors = min(sync_number, len(neighbor_indices))
selected_neighbors = np.random.choice(neighbor_indices, num_neighbors, replace=False)
for j in selected_neighbors:
# 位相差を計算
phase_diff = (phases[j] - phases[i] + 0.5) % 1.0 - 0.5
# 位相を調整
new_phases[i] += k * phase_diff
# 位相を更新
phases = new_phases % 1.0
# 明るさを計算
brightness = np.sin(np.pi * (1 - phases)) ** 2 # 明るさは0から1の間
brightness_history.append(brightness)
# 発光しているホタルの数を計算(明るさが閾値以上のホタルをカウント)
threshold = 0.9 # 明るさの閾値
num_lit = np.sum(brightness >= threshold)
num_lit_fireflies.append(num_lit)
# 散布図を更新
scatter.set_array(brightness)
# 折れ線グラフを更新
xdata.append(frame)
ydata.append(num_lit)
line.set_data(xdata, ydata)
return scatter, line
# アニメーションの作成
ani = FuncAnimation(fig, update, frames=num_steps, interval=50, blit=True)
# GIFファイルとして保存
ani.save('firefly_synchronization_with_graph.gif', writer='pillow')
参考文献
- MAS コミュニティ ホタルの光モデルhttps://mas.kke.co.jp/model/hotal_model/