サメ–小魚モデルの作成


今回はサメ–小魚モデルを実装してみた.

これはmiura & sakurama (2017)を参考に知ったモデルをPythonで組んでみたモデルである.

サメと小魚の動きがシミュレーションできて面白い.サメの挙動がおかしくなる部分があるが,それは今後の課題にしたい.

コードは下記.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

# エージェントクラスの定義
class Agent:
    def __init__(self, x, y, vx, vy, speed, fov, agent_type):
        self.x = x  # x座標
        self.y = y  # y座標
        self.vx = vx  # x方向の速度成分
        self.vy = vy  # y方向の速度成分
        self.speed = speed  # 移動速度
        self.fov = fov  # 視野(半径)
        self.agent_type = agent_type  # エージェントの種類('Shark'または'Fish')

    def update_direction(self, agents):
        # 自分以外のエージェントを取得
        other_agents = [agent for agent in agents if agent != self]
        if not other_agents:
            return

        # 他のエージェントとの距離を計算
        distances = []
        for agent in other_agents:
            dx = agent.x - self.x
            dy = agent.y - self.y
            # 周期境界条件の適用
            dx = dx - 100 if dx > 50 else dx + 100 if dx < -50 else dx
            dy = dy - 100 if dy > 50 else dy + 100 if dy < -50 else dy
            distance = np.hypot(dx, dy)
            if distance <= self.fov:
                distances.append((distance, agent, dx, dy))

        if not distances:
            # 視野内にエージェントがいない場合
            return

        # 最も近いエージェントを取得
        distances.sort(key=lambda x: x[0])
        nearest = distances[0]
        nearest_agent = nearest[1]
        dx = nearest[2]
        dy = nearest[3]

        # 行動ルールの実装
        if self.agent_type == 'Shark':
            if nearest_agent.agent_type == 'Fish':
                # 小魚を追いかける
                angle = np.arctan2(dy, dx)
                self.vx = np.cos(angle)
                self.vy = np.sin(angle)
            elif nearest_agent.agent_type == 'Shark':
                # 他のサメから逃げる
                angle = np.arctan2(-dy, -dx)
                self.vx = np.cos(angle)
                self.vy = np.sin(angle)
        elif self.agent_type == 'Fish':
            if nearest_agent.agent_type == 'Shark':
                # サメから逃げる
                angle = np.arctan2(-dy, -dx)
                self.vx = np.cos(angle)
                self.vy = np.sin(angle)
            # 小魚は他の小魚から逃げない

    def move(self):
        # エージェントの位置を更新
        self.x += self.vx * self.speed
        self.y += self.vy * self.speed
        # 周期境界条件の適用
        self.x = self.x % 100
        self.y = self.y % 100

# シミュレーションのパラメータ設定
num_sharks = 5       # サメの数
num_fish = 100        # 小魚の数
speed_shark = 1.5    # サメの速度
speed_fish = 1.0     # 小魚の速度
fov_shark = 15       # サメの視野
fov_fish = 10        # 小魚の視野
num_steps = 200      # シミュレーションのステップ数

agents = []

# サメエージェントの初期化
for _ in range(num_sharks):
    x = np.random.uniform(0, 100)
    y = np.random.uniform(0, 100)
    angle = np.random.uniform(0, 2*np.pi)
    vx = np.cos(angle)
    vy = np.sin(angle)
    agent = Agent(x, y, vx, vy, speed_shark, fov_shark, 'Shark')
    agents.append(agent)

# 小魚エージェントの初期化
for _ in range(num_fish):
    x = np.random.uniform(0, 100)
    y = np.random.uniform(0, 100)
    angle = np.random.uniform(0, 2*np.pi)
    vx = np.cos(angle)
    vy = np.sin(angle)
    agent = Agent(x, y, vx, vy, speed_fish, fov_fish, 'Fish')
    agents.append(agent)

# グラフの設定
fig, ax = plt.subplots(figsize=(6,6))
ax.set_xlim(0, 100)
ax.set_ylim(0, 100)
ax.set_xlabel('X Coordinate')  # X座標
ax.set_ylabel('Y Coordinate')  # Y座標
ax.set_title('Shark–Fish Model Simulation')  # サメ–小魚モデルのシミュレーション

# サメと小魚のプロットを初期化
shark_plot, = ax.plot([], [], 'bo', markersize=8, label='Shark')  # サメ
fish_plot, = ax.plot([], [], 'go', markersize=4, label='Fish')    # 小魚
ax.legend()

# 初期化関数
def init():
    shark_plot.set_data([], [])
    fish_plot.set_data([], [])
    return shark_plot, fish_plot

# アニメーション関数
def animate(i):
    # エージェントの方向を更新
    for agent in agents:
        agent.update_direction(agents)
    # エージェントの位置を更新
    for agent in agents:
        agent.move()
    # プロットデータの更新
    shark_x = [agent.x for agent in agents if agent.agent_type == 'Shark']
    shark_y = [agent.y for agent in agents if agent.agent_type == 'Shark']
    fish_x = [agent.x for agent in agents if agent.agent_type == 'Fish']
    fish_y = [agent.y for agent in agents if agent.agent_type == 'Fish']
    shark_plot.set_data(shark_x, shark_y)
    fish_plot.set_data(fish_x, fish_y)
    return shark_plot, fish_plot

# アニメーションの作成
ani = animation.FuncAnimation(fig, animate, frames=num_steps, init_func=init, interval=100, blit=True)

# アニメーションをGIFとして保存
ani.save('shark_fish_simulation.gif', writer='pillow')

参考文献

  • 三浦, 政司., & 桜間, 一徳. (2017). マルチエージェントシミュレーションをはじめてみよう. システム/制御/情報, 61(5), 169–174. https://doi.org/10.11509/isciesci.61.5_169

コメントを残す

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