自己組織化臨界のモデル


砂山崩しというモデルを見つけた.(開発者の名前を取って,BTW モデルとも言われるそうだ.)

この実装をしてみた.条件は下記である.

	ブロック追加
	•	毎回、ランダムに1つのマス目が選ばれ、そこに1つのブロックが追加される。
	•	既にブロックが積まれているマス目にブロックが落ちると、上に積み重なる。
	飛散
	•	1つのマス目に4つのブロックが積まれると、その4つのブロックが上下左右の4つの隣接マス目に分散される。
	•	分散先のマス目に既に3つのブロックがある場合、さらに分散が発生する可能性がある。

コードは下記.

import numpy as np
import matplotlib.pyplot as plt
import imageio
import os
import random

# シミュレーションパラメータ
GRID_SIZE = 20        # グリッドのサイズ 
NUM_STEPS = 1000      # シミュレーションのステップ数
GIF_INTERVAL = 5     # GIFにフレームを追加する間隔

# 出力ディレクトリ
OUTPUT_DIR = "sandpile_frames"
if not os.path.exists(OUTPUT_DIR):
    os.makedirs(OUTPUT_DIR)

# 初期化
grid = np.zeros((GRID_SIZE, GRID_SIZE), dtype=int)
frames = []

def topple(grid):
    """グリッド上のトップリング処理を実行する。"""
    unstable = grid >= 4
    while np.any(unstable):
        # トップリングするセルの座標を取得
        topple_cells = np.argwhere(unstable)
        for cell in topple_cells:
            i, j = cell
            grid[i, j] -= 4
            # 上下左右にブロックを追加
            if i > 0:
                grid[i-1, j] += 1
            if i < GRID_SIZE - 1:
                grid[i+1, j] += 1
            if j > 0:
                grid[i, j-1] += 1
            if j < GRID_SIZE - 1:
                grid[i, j+1] += 1
        unstable = grid >= 4

# カラーマップの設定
cmap = plt.cm.viridis
norm = plt.Normalize(vmin=0, vmax=4)

for step in range(NUM_STEPS):
    # ランダムにセルを選んでブロックを追加
    i = random.randint(0, GRID_SIZE - 1)
    j = random.randint(0, GRID_SIZE - 1)
    grid[i, j] += 1

    # トップリング処理
    topple(grid)

    # GIFに追加するフレームを取得
    if step % GIF_INTERVAL == 0:
        plt.figure(figsize=(6,6))
        plt.imshow(grid, cmap=cmap, norm=norm)
        plt.title(f"Step: {step}")
        plt.axis('off')
        frame_path = os.path.join(OUTPUT_DIR, f"frame_{step}.png")
        plt.savefig(frame_path)
        plt.close()
        frames.append(frame_path)

# GIFの作成
gif_path = "sandpile_simulation.gif"
with imageio.get_writer(gif_path, mode='I', duration=0.1) as writer:
    for frame_path in frames:
        image = imageio.imread(frame_path)
        writer.append_data(image)

# フレーム画像の削除(オプション)
for frame_path in frames:
    os.remove(frame_path)

print(f"シミュレーションが完了しました。GIFファイル: {gif_path}")

参考文献

コメントを残す

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