Python のシミュレーション


最近,計算社会学というものにふれ,色々と試している.

今回は,交通渋滞のシミュレーションをしてみたい.

今回はこんな条件でシミュレーションを実施する.すると,見事に渋滞が起こって面白い.

1.	テストコースの定義:
•	半径25mの円形コース(周長約157.08m)を設定。
•	20台の車両を等間隔(約7.85m)で配置。
2.	車両エージェントの特性:
•	初期速度: 20 km/h(約5.56 m/s)。
•	各車両は前方車両との距離に基づいて速度を調整。
•	近づきすぎた場合: 速度を15 km/h(約4.17 m/s)に減速。
•	十分な車間距離がある場合: 速度を20 km/hに加速。
•	各シミュレーションステップごとに速度に±0.05 km/h(約0.0139 m/s)のゆらぎを追加。
import numpy as np
import matplotlib.pyplot as plt
import imageio
import os

# シミュレーションパラメータ
RADIUS = 25  # 円の半径(メートル)
NUM_CARS = 20  # 車の数
CIRCUMFERENCE = 2 * np.pi * RADIUS  # 円の周長
INITIAL_SPACING = CIRCUMFERENCE / NUM_CARS  # 初期車間距離

TARGET_SPEED = 20 / 3.6  # 目標速度(m/s)20 km/h
BRAKE_SPEED = 15 / 3.6  # 減速後の速度(m/s)15 km/h
MIN_DISTANCE = 5  # 最小車間距離(メートル)
SAFE_DISTANCE = 10  # 安全車間距離(メートル)

DELTA_T = 1  # 時間ステップ(秒)
TOTAL_STEPS = 200  # シミュレーションの総ステップ数

SPEED_FLUCTUATION = 0.05 / 3.6  # 速度のゆらぎ(m/s)

# 初期位置と速度の設定
positions = np.linspace(0, CIRCUMFERENCE, NUM_CARS, endpoint=False)
speeds = np.full(NUM_CARS, TARGET_SPEED)

# アニメーション用のフレームを保存するリスト
frames = []

# 一時的なフォルダを作成してフレームを保存
frame_dir = "frames"
if not os.path.exists(frame_dir):
    os.makedirs(frame_dir)

for step in range(TOTAL_STEPS):
    # ソートされた位置のインデックス
    sorted_indices = np.argsort(positions)
    sorted_positions = positions[sorted_indices]
    sorted_speeds = speeds[sorted_indices]

    # 距離を計算(前の車との距離)
    distances = np.roll(sorted_positions, -1) - sorted_positions
    distances[-1] += CIRCUMFERENCE  # 最後の車は最初の車との距離

    # 速度の更新
    new_speeds = sorted_speeds.copy()
    for i in range(NUM_CARS):
        distance = distances[i]
        if distance < MIN_DISTANCE:
            # 近づきすぎた場合、減速
            new_speeds[i] = BRAKE_SPEED
        elif distance > SAFE_DISTANCE:
            # 十分な距離がある場合、加速
            new_speeds[i] = TARGET_SPEED
        # それ以外は現在の速度を維持

    # 速度にゆらぎを追加
    fluctuations = np.random.uniform(-SPEED_FLUCTUATION, SPEED_FLUCTUATION, NUM_CARS)
    new_speeds += fluctuations

    # 速度の範囲を制限(例: 0から30 km/h)
    new_speeds = np.clip(new_speeds, 0, 30 / 3.6)

    speeds[sorted_indices] = new_speeds

    # 位置の更新
    positions += speeds * DELTA_T
    positions = positions % CIRCUMFERENCE  # 周長を超えたらリセット

    # プロット用のフレーム作成
    plt.figure(figsize=(6,6))
    ax = plt.gca()
    ax.set_xlim(-RADIUS-5, RADIUS+5)
    ax.set_ylim(-RADIUS-5, RADIUS+5)
    ax.set_aspect('equal')
    plt.axis('off')

    # 円形コースの描画
    circle = plt.Circle((0, 0), RADIUS, color='black', fill=False, linewidth=2)
    ax.add_artist(circle)

    # 車両の位置をプロット
    angles = (positions / CIRCUMFERENCE) * 2 * np.pi
    x = RADIUS * np.cos(angles)
    y = RADIUS * np.sin(angles)
    plt.scatter(x, y, color='red', s=50)

    # フレームの保存
    frame_path = os.path.join(frame_dir, f"frame_{step:04d}.png")
    plt.savefig(frame_path)
    plt.close()
    frames.append(frame_path)

    # プログレス表示
    if (step + 1) % 20 == 0:
        print(f"ステップ {step + 1}/{TOTAL_STEPS} 完了")

# GIFアニメーションの作成
images = []
for frame_path in frames:
    images.append(imageio.imread(frame_path))
imageio.mimsave('traffic_simulation.gif', images, fps=5)

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

print("シミュレーションとGIFの作成が完了しました。'traffic_simulation.gif' を確認してください。")

参考文献

コメントを残す

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