Python のシミュレーション 2


前回は交通渋滞が起こる要素を見てみたが,今回は渋滞を起こさない家庭を見てみたい.

基本的に道路が空いていれば渋滞は起きないはずである.そこで車の台数を減らしてみた.

すると見事に渋滞が起こらなくなった.

import numpy as np
	import matplotlib.pyplot as plt
	import imageio
	import os
	
	# シミュレーションパラメータ
	RADIUS = 25  # 円の半径(メートル)
	NUM_CARS = 5  # 車の数
	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' を確認してください。")

コメントを残す

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