同期のモデリング


以前の投稿で,ホタルの光モデルというものを見た.

今回はその発展として状態推移を折れ線グラフとして可視化した.こうすることで数という観点からの推移がわかりやすくなる.

コードは下記.

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')

参考文献

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です