(サムネイル画像:PexelsによるPixabayからの画像を編集)
今回で artisoc Cloud でのシュガー・モデルを完成させます。
今までの記事はこちらです。
1.エージェント数をカウントする
シュガー・モデルの目標は、生き物の増殖の様子を観察することです。
そのためには総個体数をカウントしていくことは非常に重要になります。
1-1.変数を追加する
まずはカウント用の変数を追加していきましょう。
モデルツリーの Universe 右横の「+」から「変数を追加」を選択し、「n_all」という変数を追加しましょう。
Universe から追加した変数は、コントロールパネルで値を入力するような定数として扱うことが多かったですが、この n_all は正真正銘 ”変数” として扱います。
1-2.カウントをプログラミングする
(1) シミュレーション開始時はエージェントの初期個体数が総個体数なので、Universe のプログラミング画面で def univ_init(self): の続きを以下のようにします。
def univ_init(self):
#creatureの生成
create_agt(Universe.field.creature, num=Universe.n0)
#creatureの初期配置
creatures = make_agtset(agttype=Universe.field.creature)
random_put_agtset_sqgrid(creatures, overlap=True)
#総個体数のカウント
Universe.n_all = Universe.n0
#foodの設置
for i in range(get_width_space(Universe.field)):
for j in range(get_height_space(Universe.field)):
Universe.field.food[i,j,0] = Universe.food_value
Universe.field.food_color[i,j,0] = rgb(0,0,255)
#creatureの初期配置 と #foodの設置 の間に #総個体数のカウント を追加しています。
(2) 各ステップ終了時に、そのときのエージェントの総個体数をカウントします。
artisoc では専用の count_agt関数を用いるだけでカウントできます。
def univ_step_end(self):
#(re_food)stepごとにfoodの復活
if count_step() % Universe.re_food == 0:
for i in range(get_width_space(Universe.field)):
for j in range(get_height_space(Universe.field)):
Universe.field.food[i,j,0] = Universe.food_value
Universe.field.food_color[i,j,0] = rgb(0,0,255)
#総個体数のカウント
Universe.n_all = count_agt(agttype=Universe.field.creature)
def univ_step_end(self): の下、#(re_food)stepごとにfoodの復活 の続きに #総個体数のカウント を追加しています。
1-3.総個体数をグラフ化する
せっかくカウントした個体数も見える化しなければ意味がありません。
(1) 出力画面の「出力」の右のアイコンから、「出力設定」を開き、「時系列グラフ」を選択して追加します。
(2) 「時系列グラフ設定」を以下のようにします。
ここはどの項目も好みで設定してOKです。
(3) 下の「時系列グラフ要素リスト」右横の「+」から、「時系列要素設定」を開き、以下のように設定します。
このとき、「出力値」を Universe.n_all にすること以外は自由に設定して構いません(今回は要素名を n_all に、グラフの色を緑色にしています)。
あとはすべての画面で「OK」を押して出力画面に戻ります。
(4) ここまでの成果を実行してみましょう。
マップ出力の右側にグラフが表示できれば完成です。
このグラフはロジスティック方程式のグラフと近い形になっていることが確認できます。
2.シミュレーション開始・終了時の処理
最後に、シミュレーションの開始時、終了時にコンソール画面に報告するように設定しましょう。
(1) Universe 画面の def univ_init(self): のすぐ下、#creatureの生成 の上に次の1行を追加します。
print("Begin Simulation")
これで、シミュレーション開始時にコンソール画面に”Begin Simulation”と表示されるようになります。
(2) def univ_finish(self): の下の pass を消して、以下のようにします。
def univ_finish(self):
print("t=", count_step(), ", N=", Universe.n_all)
print("End Simulation")
これでシミュレーション終了時にそのときのステップ数と総個体数を表示させ、”End Simulation” と表示させることができます。
以上で完成です!
プログラム全体は付録に載せていますので、不安な箇所がある方はそちらで確認してみてください。
シュガー・モデルを利用した研究としては、”コントロールパネルで設定できるパラメータを変えた際にどのような変化が生じるか”ということになると思います。
おまけ
基本的なシュガー・モデルはもう完成しているわけですが、ここでは少しだけ応用の方針を紹介したいと思います。
- アリの移動方法に関して、ランダムに移動するのではなく、視野の範囲内に餌があるマスを確認して、そこに移動するようにする。
- グラフの出力に関して、ロジスティック方程式と比較した際の環境収容力K(総個体数の限界値)を求められるようにする。
- アリ・エージェントに age という変数を追加し、年齢構造を組み込む。寿命で死ぬ設定にしたり、子供を生む年齢を制限したりする。時間遅れロジスティック方程式(ハッチンソン方程式)との対応も考えられる。
- 出力での色使いをこだわってみる。
あくまで「こういう案もあるよ」というだけであり、自由な発想で改良してほしいと思います。
まとめ
お疲れ様でした!
全3回にわたり作成してきたシュガー・モデルもこれで終了になります。
1つシミュレーションを完成させれば、他のシミュレーションも取り組みやすいと思いますので、オリジナルのシミュレーションも考えてみてほしいです。
また、この記事のみならず、artisoc Cloud には丁寧なマニュアルやチュートリアルが用意されていますので、そちらも是非確認してみてください。
付録
シュガー・モデル全体のコードを載せておきます。
Universe 画面
def univ_init(self):
print("Begin Simulation")
#creatureの生成
create_agt(Universe.field.creature, num=Universe.n0)
#creatureの初期配置
creatures = make_agtset(agttype=Universe.field.creature)
random_put_agtset_sqgrid(creatures, overlap=True)
#総個体数のカウント
Universe.n_all = Universe.n0
#foodの設置
for i in range(get_width_space(Universe.field)):
for j in range(get_height_space(Universe.field)):
Universe.field.food[i,j,0] = Universe.food_value
Universe.field.food_color[i,j,0] = rgb(0,0,255)
def univ_step_begin(self):
pass
def univ_step_end(self):
#(re_food)stepごとにfoodの復活
if count_step() % Universe.re_food == 0:
for i in range(get_width_space(Universe.field)):
for j in range(get_height_space(Universe.field)):
Universe.field.food[i,j,0] = Universe.food_value
Universe.field.food_color[i,j,0] = rgb(0,0,255)
#総個体数のカウント
Universe.n_all = count_agt(agttype=Universe.field.creature)
def univ_finish(self):
print("t=", count_step(), ", N=", Universe.n_all)
print("End Simulation")
creature(エージェント)画面
def agt_init(self):
self.assets = rand() * (10 * Universe.app)
def agt_step(self):
#単純移動
for i in range(int(rand() * Universe.view) + 1):
self.forward_direction_sqgrid(2 * int(rand() * 4),1)
#eat
self.assets = self.assets - Universe.app + Universe.field.food[self.x, self.y, 0]
Universe.field.food[self.x, self.y, 0] = 0
Universe.field.food_color[self.x, self.y, 0] = rgb(255,255,255)
#death
if self.assets < 0:
kill_agt(self)
return
#birth
if self.assets > 10 * Universe.app:
child = create_agt(Universe.field.creature)
child.x = self.x
child.y = self.y
child.assets = self.assets / 2
self.assets = self.assets / 2