MESA でマルチエージェントシミュレーションをしてみる

# はじめに
以前からマルチエージェントシミュレーションに興味があったため、今回 Python でマルチエージェントシミュレーションを実装してみました。

# やりたいこと
Python を用いてマルチエージェントシミュレーションを実装し、Streamlit に載せて簡単な GUI アプリとして公開する。
先に見せてしまいますが、成果物はこちらです。触ってみてもらえると嬉しいです。
[Predator-Prey Simulation](https://predatorprey-g8tdmsixgl25qijfzn5urm.streamlit.app/)

![PredatorPrey.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511606/bc7a4cfe-d6f9-99f1-21c7-c2f97e029ca6.gif)


# コンセプト
実装から可視化、デプロイまで簡単な言語はやはり Python なので、Python を用いて実現しようと思います。今回やりたいことはマルチエージェントシミュレーションの基礎的な理解と実装です。

基本コンセプトとしては、①手軽で便利な言語（Python）で、②手軽なライブラリ（Mesa）でマルチエージェントシミュレーションを実行し、③可視化（Plotly）を行い、④アプリ化（Streamlit）して公開します。

# 環境周り
①言語
Python 3.12.1

②マルチエージェントシミュレーション
Mesa 2.1.5

③可視化
Plotly 5.19.0

④アプリ化
Streamlit 1.31.1

# マルチエージェントシミュレーション
マルチエージェントシミュレーションの基本はこちらを元に学習しました。全体像を掴むのは１つ目のリンク先のカンファレンスペーパー、実装の雰囲気をなんとなく眺めたい方は２つ目のリンク先の動画が良いかと思います。私は両方目を通しました。
- [Mesa: An Agent-Based Modeling Framework](https://pdfs.semanticscholar.org/28a1/6e1b01b5897bde0e6fc676eacbc73d179ad6.pdf)
- [Agent-Based Models with Python: An Introduction to Mesa](https://www.complexityexplorer.org/courses/172-agent-based-models-with-python-an-introduction-to-mesa)

Mesa でマルチエージェントシミュレーションを実装する上では、いくつかのクラスを基本的な要素として利用することになるかと思います。こちらはカンファレンスペーパーが詳しいです（英語が得意でない方、すみません。翻訳かけてください）

**ほぼ必須の4クラス**
- Model：モデル全体の定義（ルールや進行を大体管理する）
- Agent：エージェントの状態や機能の定義
- Space（Grid や Network）：エージェントが配置される空間管理用の定義、
- Scheduler：シミュレーション内の時間管理用の定義（少し正確ではないですが）

**便利な2クラス**
- DataCollector：データ集計用の定義
- BatchRunner：各種実行自動化用の定義（らしい、使ってません）

# 実装
今回は Predator-Prey を実装しようと考えたので、こちらを参考にしています。~~ちなみにコードの完全版は載っていないようで、多くの部分は割と自力で実装しました。~~
- [Creating a Simple Predator-Prey Model with Mesa: A Python Simulation Library](https://medium.com/@ulriktpedersen/creating-a-simple-predator-prey-model-with-mesa-a-python-simulation-library-4835f29791ae)

先ほど書いたマルチエージェントシミュレーションの要素に合わせてざっくり実装を解説しておきます。

### Model
シミュレーションのルールみたいなのはだいたいここに定義しています。各種クラスをここで実体化して操作しています。（ちなみに実装上だと、Model と Agent は相互に参照可能にしています）
- Agent： Rabbit と Fox を定義。適当な頭数で初期化を実施
- Space：Environment でまた説明しますが、MultiGrid を採用
- Scheduler：RandomActivation を採用、要するにステップごとの Rabbit とか Fox の行動ターンはランダムな順序で開始
- DataCollector：ステップごとのエージェントの情報を記録

Model クラスにシミュレーションを進行させるために定義した機能はこちらです。
- set_init_agent
エージェントの配置
- create_agent
エージェントの初期化
- step
モデル内の時間を進める際にスケジュールとデータコレクタを実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511606/b35c876e-1896-a267-edba-b7d903f61a2c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511606/b542f6f5-9d29-935e-0dc3-244a2599ce4b.png)

### Agent
スクショは Rabbit だけ載せていますが Fox も別途定義しています、詳しくは [GitHub](https://github.com/MySweetEden/predator_prey) をご覧ください。
Rabbit には状態として現在地の情報と繁殖確率を与えています。
そして、以下の2つの機能を持っています。
- move：Grid 上で隣接するランダムな場所への移動
- reproduce：reproduce_ratio の確率で自身のいる位置に子どもを出産
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511606/8839cbbc-1d71-5266-508c-52de39354b91.png)

### Space
継承からわかる通り、MultiGrid を採用しています。
そして以下の3つの機能を持たせています。（正直特に書く必要ないんですがわかりやすさのため明示的に書いています）
- place_agent
エージェントを指定の場所に配置
- move_agent
エージェントを指定の場所に移動（配置と移動は違います、移動前のエージェントが消えるか否か）
- remove_agent
エージェントを Grid 上から消去
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511606/6f26958a-104d-91e1-3310-7b2e37162939.png)

### Scheduler
モデル内の時間管理を色々やってくれます。~~（があまり存在感ないです）~~
一応、新たにエージェントを定義する際に schedule に登録したり、エージェントを削除する場合に schedule から削除したりする必要があるので、忘れてはいけません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511606/c7c75c54-99e8-0db0-3f0d-538f81913c5e.png)

## DataCollector
エージェントを引数に取ったときの動作を設定して、モデル更新の際に呼び出すだけで、ステップごとの記録を勝手にとってくれるので便利です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/511606/8e47a059-9ebc-f06a-249b-2ec573641913.png)


私の具体的な実装はこちらです、ざっくり上記のイメージでプログラムを作成しています。パッケージ管理はいつも通り Rye を使っています。興味ある方はクローンして触ってみてください。
https://github.com/MySweetEden/predator_prey

再掲ですが、アプリ化したこちらもどうぞ。
[Predator-Prey Simulation](https://predatorprey-g8tdmsixgl25qijfzn5urm.streamlit.app/)

# おわりに
マルチエージェントシミュレーションを触ってみたかったので良い勉強になりました。実装はダラダラ１週間くらいかけてやった気がします。アプリ化は簡単でした。（Mac で Rye を使っていると requirements.txt が吐き出されなかったが、Streamlit をデプロイする際には必要。仕方がないので requirements.lock をベースに手作業で作りました。といってもファイル名を変えてよくわからん行を消したくらいですが）
いずれは生成AIなども組み込んで面白いシステムを作成できたらな、なんてことも考えたりしています。

# 参考
- [Mesa: An Agent-Based Modeling Framework](https://pdfs.semanticscholar.org/28a1/6e1b01b5897bde0e6fc676eacbc73d179ad6.pdf)
- [Agent-Based Models with Python: An Introduction to Mesa](https://www.complexityexplorer.org/courses/172-agent-based-models-with-python-an-introduction-to-mesa)
- [Creating a Simple Predator-Prey Model with Mesa: A Python Simulation Library](https://medium.com/@ulriktpedersen/creating-a-simple-predator-prey-model-with-mesa-a-python-simulation-library-4835f29791ae)