shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2...

18
1 サメ-⼩⿂モデルの MAS をつくってみよう 2017.05 Ver.01 http://m-miura.jp/ はじめに このドキュメントについて このドキュメントは「システム/制御/情報」2017 年 5 ⽉号に掲載された解説記事「マルチエージェントシミュレーショ ンをはじめてみよう」の補⾜資料であり,記事の中で MAS のサンプルとして挙げている「サメ-⼩⿂モデル」につい て,具体的な構築⼿順を紹介します.サメ-⼩⿂モデルは記事の筆者が初学者に MAS を教える際の練習サン プルとして使⽤しているもので,極めて簡単なモデルでありながら視覚的に⾯⽩い創発現象を観察することができま す.サメ-⼩⿂モデルやそれを活⽤した教育プログラムに関しての詳細は上記解説記事をご覧下さい. artisoc について このドキュメントでは株式会社構造計画研究所が提供している MAS 開発プラットフォーム「artisoc」を⽤いてサメ- ⼩⿂モデルを構築する⼿順を紹介します.aritisoc はグラフィカルでユーザフレンドリな操作性と直感的なコーディ ンググロック構成などの特徴を持ち,初学者が MAS を学ぶ上で使⽤するのに適しています.また,artisoc は学 ⽣や教育機関に対して無料で公開されており,あなたが学⽣または教育機関職員であれば下記の WEB サイト からダウンロードして今すぐに MAS 構築の練習を初めることができます. artisoc4.0 WEB ページ:http://mas.kke.co.jp/modules/tinyd0/index.php?id=13 artisoc の使⽤⽅法やプログラム⽂法の細かいところは,上記 WEB サイトで公開されているマニュアル,書籍 「⼈⼯社会構築指南」(著:⼭影進,学⽣/教育機関向けには PDF 無料公開),artisoc ヘルプ等を参照 して下さい. モデルファイルについて 下記の WEB ページからサメ-⼩⿂モデルのファイルをダウンロードできるので,適宜ご利⽤下さい.ただし,本当に 簡単なモデルですので,初学者の⽅はまずは次ページ以降の⼿順に従って⾃分⾃⾝でモデル構築にトライしてみ て下さい. サメ-⼩⿂モデルダウンロードページ:http://m-miura.jp/mas/shark-fish/

Transcript of shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2...

Page 1: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

1

サメ-⼩⿂モデルの MAS をつくってみよう 2017.05 Ver.01

http://m-miura.jp/

はじめに このドキュメントについて このドキュメントは「システム/制御/情報」2017 年 5 ⽉号に掲載された解説記事「マルチエージェントシミュレーションをはじめてみよう」の補⾜資料であり,記事の中で MAS のサンプルとして挙げている「サメ-⼩⿂モデル」について,具体的な構築⼿順を紹介します.サメ-⼩⿂モデルは記事の筆者が初学者に MAS を教える際の練習サンプルとして使⽤しているもので,極めて簡単なモデルでありながら視覚的に⾯⽩い創発現象を観察することができます.サメ-⼩⿂モデルやそれを活⽤した教育プログラムに関しての詳細は上記解説記事をご覧下さい.

artisoc について このドキュメントでは株式会社構造計画研究所が提供している MAS 開発プラットフォーム「artisoc」を⽤いてサメ-⼩⿂モデルを構築する⼿順を紹介します.aritisoc はグラフィカルでユーザフレンドリな操作性と直感的なコーディンググロック構成などの特徴を持ち,初学者が MAS を学ぶ上で使⽤するのに適しています.また,artisoc は学⽣や教育機関に対して無料で公開されており,あなたが学⽣または教育機関職員であれば下記の WEB サイトからダウンロードして今すぐに MAS 構築の練習を初めることができます.

artisoc4.0 WEB ページ:http://mas.kke.co.jp/modules/tinyd0/index.php?id=13

artisoc の使⽤⽅法やプログラム⽂法の細かいところは,上記 WEB サイトで公開されているマニュアル,書籍「⼈⼯社会構築指南」(著:⼭影進,学⽣/教育機関向けには PDF 無料公開),artisoc ヘルプ等を参照して下さい.

モデルファイルについて 下記の WEB ページからサメ-⼩⿂モデルのファイルをダウンロードできるので,適宜ご利⽤下さい.ただし,本当に簡単なモデルですので,初学者の⽅はまずは次ページ以降の⼿順に従って⾃分⾃⾝でモデル構築にトライしてみて下さい.

サメ-⼩⿂モデルダウンロードページ:http://m-miura.jp/mas/shark-fish/

Page 2: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

2

MAS をつくってみよう 1. 空間,エージェント,変数を追加する artisoc を⽤いて MAS をつくる際に最初に⾏う作業は,空間,エージェント,変数を配置することです.この作業はツリーウインドウからマウスによる操作で⾏うことができます.artisoc を⽴ち上げると,Universe という要素だけが配置されたツリーウインドウが表⽰され,artisoc で MAS を構築する際の多くの作業がこのツリーウインドウを起点とします. Universe はシミュレーションに⽤いる空間,エージェント,変数などの全てを包含する最上位の要素だと思って下さい.まずは,Universe の下に空間を配置しましょう.ツリーウインドウで Universe と表⽰された部分を右クリックして出て来るサブメニューから「空間の追加」を選んで下さい.すると「空間プロパティ」が表⽰されるので,空間名を sea,空間の⼤きさを X:100,Y:100,ループするにチェックを⼊れて「了解」ボタンを押します(図1).これでサメと⼩⿂が動き回る空間「sea」が追加されました.

図 1. 空間プロパティ

次に空間 sea にエージェント型を追加しましょう.ツリーウインドウで sea と記述された部分を右クリックして,「エージェント型の追加」を選びます.すると,エージェント型プロパティが表⽰されるので,エージェント型名を shark として下さい.今回は⽣成エージェント数をコントロールパネルから操作することができるようにするので,エージェント型プロパティの画⾯では⽣成エージェント数は 0 としておきます.同様にして sea に fish というエージェント型を追加します. ⼀般的な MAS ではさらに各エージェント型の下に変数を追加しますが,今回のモデルでは追加の変数は必要ありません.エージェント型を追加した時点で各エージェント型の下には⾃動的に ID, X, Y, Layer, Directionの5つの変数が追加されます.今回のモデルではこのうち X,Y,Direction を⽤います. 次に Universe の下に表 1 に⽰す 4 つの変数を追加します.ツリーウインドウの Universe を右クリックし,「変数の追加」を選んで下さい.変数プロパティで変数名や変数の型を⼊⼒します.Universe の下に追加された変数は「Universe.変数名」と記述することでコード内のどこからでも参照,代⼊することができ,Global 変数のような形で使⽤することができます.

Page 3: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

3

表 1. Universe の下に追加する変数 変数名 変数の型 役割 Ns 整数(Integer) サメエージェントの数を指定する Nf 整数(Integer) ⼩⿂エージェントの数を指定する Rs 実数(Double) サメエージェントの視野を指定する Rf 実数(Double) ⼩⿂エージェントの視野を指定する

ここまででサメ-⼩⿂モデルに必要な最低限の空間,エージェント,変数の配置が終わりました.ツリーウインドウは図 2 のような状態になっているはずです.

図 2. 配置後のツリーウインドウ

Page 4: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

4

2. マップ出⼒を設定する artisoc では空間とその中で⾏動するエージェントを簡単な操作でグラフィカルに表⽰することができます.そのための設定として「出⼒設定」を⾏います. メニューバーの「設定」から「出⼒設定」を選びましょう.すると出⼒項⽬リストウインドウが表⽰されるので,「マップ出⼒」を選択して(通常は最初からマップ出⼒が選択された状態になっています)「追加ボタン」を押します.今回はマップ出⼒しか使⽤しませんが,他にも時系列グラフやヒストグラムなど,様々なグラフィカル出⼒を選択することができます. 追加ボタンを押すとマップ出⼒設定ウインドウが表⽰されます.ここではマップ名とマップタイトルにそれぞれ sea と⼊⼒して,左下のマップ要素リストという項⽬中の追加ボタンを押します.すると要素設定というウインドウが表⽰され,エージェントの表⽰に関する設定を⾏うことができます.まず要素名を「サメ」として出⼒対象に「shark」を選び,マーカーを●,エージェント表⽰⾊を⾚⾊に設定して「了解」を押しましょう.同様にして要素名を「⼩⿂」,出⼒対象を「fish」,⾊を⻘⾊にしてもうひとつマップ要素リストを追加します.ここまでの設定で図 3 のようになっているはずです.このまま「了解」を押して出⼒項⽬リストでもう⼀度「了解」を押せば設定完了です.これで空間とエージェントを表⽰する準備が整いました.

図 3. マップ出⼒設定

Page 5: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

5

3. コントロールパネルを設定する 次にエージェントの数や視野などのシミュレーションパラメータを GUI から操作するためのコントロールパネルを設定します.メニューバーの「設定」から「コントロールパネル設定」を選び,表⽰されるウインドウで「追加」ボタンを押しましょう.すると「ユーザ設定項⽬」というウインドウが表⽰されるので,コントロール名を「サメの数」,設定対象を「Ns」,インターフェースを「直接⼊⼒」に設定します(図 4).同様にして,⼩⿂の数(Nf),サメの視野(Rs),⼩⿂の視野(Rs)を全て「直接⼊⼒」で設定します(図 5).

図 4. ユーザ設定項⽬(コントロールパネル設定) 図 5. コントロールパネル-ユーザ設定項⽬リスト

ここまでの設定でコントロールパネルの準備ができました.この時点で⼀度実⾏ボタンを押してシミュレーションを開始してみましょう(図 6).すると,図 7 のようなコントロールパネルが表⽰されるはずです(マップ出⼒も表⽰されますが,この時点では⽣成数が 0 のためエージェントは上⼿く表⽰されません).最初はどれも 0 に設定されているので,図 7 のように各パラメータの値を⼊れましょう.

図 6. 実⾏ボタン 図.7 コントロールパネル

Page 6: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

6

4. エージェントを⽣成する 次に,エージェントを⽣成する処理をコードで記述しましょう.artisoc では処理のタイミングに応じたいくつかのコーディングブロックが⽤意されていて,ユーザは(基本的には)いずれかのコーディングブロックの中にコードを記述します.例えば,シミュレーション開始時に⼀度だけ実⾏する初期設定は Univ_Init というブロックに,各ステップのはじめに実⾏する処理は Univ_Step_Begin というブロックに記述します.これらのコーディングブロックはツリーウインドウの Universe と表⽰された部分をダブルクリックすることで表⽰するルールウインドウから記述することができます(図 8).各コーディングブロックの詳細と処理の流れについては artisoc のマニュアルまたは解説記事「マルチエージェントシミュレーションをはじめてみよう」の 2.3 節を参照して下さい.

図 8. Universe のコーディングブロック

エージェントを⽣成する処理は「シミュレーションが開始したときに⼀度だけ実⾏される処理」に該当するので,Univ_Init の中に記述します.Univ_Init の中に次のように記述して下さい. 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:

Univ_Init{

Dim i As Integer

For i = 0 to Universe.Ns - 1 CreateAgt(Universe.sea.shark)

Next i

For i = 0 to Universe.Nf - 1 CreateAgt(Universe.sea.fish)

Next i }

ここで 6 ⾏⽬の「CreateAgt(Universe.sea.shark)」は,サメ(shark)エージェントを 1 つ⽣成するという処理を⽰します.この処理を Ns 回繰り返すことで,全部で Ns 体の shark エージェントが⽣成されます.⼩⿂

Page 7: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

7

(fish)エージェントについても同様です(9~11 ⾏⽬).Dim や For,Next などのプログラミング⽂法の詳細については artisoc のマニュアルやヘルプを参照して下さい. これでシミュレーションを開始した直後にそれぞれ Ns 体,Nf 体のサメおよび⼩⿂エージェントが⽣成されるようになりました.しかしこの時点でシミュレーションを実⾏しても,マップ出⼒では図 9 のように左下に 1 つのサメエージェントが表⽰されるだけで,指定した数(Ns,Nf 体)のエージェントが⽣成されたようには⾒えません.これは,確かに指定した数のエージェントが⽣成されてはいるのですが,どのエージェントも座標が(0, 0)にいるので全て重なっていて,⼀番上のエージェントだけが表⽰されているように⾒えるためです.そこで次は,各エージェントの初期位置をランダムで決めるような処理を記述します.

図 9. シミュレーションの実⾏結果(ここまでの⼿順の時点)

Page 8: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

8

5. エージェントの初期配置をランダムにする 前節までの設定と記述では⽣成されたエージェントが全て(0, 0)の位置にいて図 9 のようになってしまうので,各エージェントが空間内のバラバラの位置にランダムで配置されるようにします.各エージェントに関する処理はツリーウインドウで各エージェントをダブルクリックして表⽰される「ルール:エージェント名」というウインドウで表⽰されるAgt_Init と Agt_Step というコーディングブロックに記述します(図 10).ここで Agt_Init にはエージェントが⽣成されたときに⼀度だけ実⾏される処理を,Agt_Step には各ステップでエージェントごとに実⾏される処理を記述します.

図 10. ルールウインドウ(各エージェント)

初期配置をランダムにする処理は「エージェントが⽣成されたときに⼀度だけ実⾏される処理」に該当するので,Agt_Init の中に記述します.shark と fish のそれぞれの Agt_Init の中に次のようなコードを記述して下さい. 1: 2: 3: 4: 5:

Agt_Init{ My.X = GetWidthSpaceOwn() * Rnd() My.Y = GetHeightSpaceOwn() * Rnd() My.Direction = 360 * Rnd() }

ここで My という記述は「このエージェント⾃⾝」を表します.例えば My.X = 100 と記述すると,「このエージェントの変数 X に 100 を代⼊する」という⽂になります.ここでは空間の横幅を取得する GetWidthSpaceOwn()という関数と,0~1 の間の実数をランダムで返す Rnd()という関数を⽤いて 2 ⾏⽬のように記述することで,X 座標の値を 0~空間の横幅 の間のランダムな数に設定しています.Y 座標についても同様です(3 ⾏⽬).また,4 ⾏⽬で値を代⼊している Direction という変数は,エージェントの向きを⾓度[degree]で指定します.ランダムな向きを向くために,代⼊する値を 0~360 の間のランダムな数としています.これらのコードを記述してからシミュレーションを実⾏すると,図 11 のようにエージェントが空間中にバラけて表⽰されます.

Page 9: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

9

図 11. シミュレーションの実⾏結果(ここまでの⼿順の時点)

6. ステップごとにエージェントが前に進むようにする 次はいよいよ,エージェントを動かしてみましょう.エージェントが現在向いている⽅向に指定の距離だけ進む Forward(arg)という関数があるので,これを使います.shark と fish それぞれの Agt_Step の中に下記のように記述して下さい. 1: 2: 3:

Agt_Step{ Forward(1) }

これで各ステップに各エージェントが距離 1 だけ進むようになります.5 の⼿順でエージェント⽣成時にランダムな⽅向を向くようにしているので,シミュレーションを実⾏すると各エージェントがバラバラの⽅向に進むことが確認できます.

Page 10: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

10

7. 視野内のエージェントのうち,最近接のエージェントを取得する サメ-⼩⿂モデルでは,各エージェントは下記のルールに従って動きます. 1) サメから⾒て視野内の最近接エージェントが⼩⿂だった場合,⼩⿂の⽅に向かう 2) サメから⾒て視野内の最近接エージェントがサメだった場合,最近接のサメから遠ざかる⽅向(反対⽅向)

に向かう 3) ⼩⿂から⾒て視野内にサメがいる場合,最近接のサメから遠ざかる⽅向(反対⽅向)に向かう これらのルールに該当する処理は Agt_Init に記述することになりますが,いずれの場合もまずは「視野内の最近接のエージェント」を取得しなければなりません.サメ(shark)エージェントの Agt_Init に記述するコードのうち,視野内の最近接エージェントを取得する部分のコードは下記のようになります. 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:

Dim arroundAgtSet as AgtSet Dim nearestAgt as Agt Dim nearestDistance as Double Dim one as Agt MakeAllAgtSetAroundOwn(arroundAgtSet, Universe.Rs, False) nearestAgt = GetAgt(arroundAgtSet, 0) nearestDistance = MeasureDistance(My.X, My.Y, My.X, My.Y, Universe.sea) For each one in arroundAgtSet

distance = MeasureDistance(My.X, My.Y, My.X, My.Y, Universe.sea) if distance < nearestDistance then

nearestDistance = distance nearestAgt = one

End if Next one

上のコードの中で使⽤している関数は下記のような処理を⾏います.詳しい使い⽅や説明は artisoc のヘルプ等を参照して下さい. — MakeAllAgtSetAroundOwn(arg1, arg2, arg3):arg2 で指定する距離内にいる全てのエージェントを

取得して,arg1 で指定するエージェント集合に⼊れる — GetAgt(arg1, arg2):arg1 で指定するエージェント集合の arg2 番⽬のエージェントを返す — MeasureDistance(arg1,arg2,arg3,arg4,arg5):arg1~arg4 で指定した座標間の距離を返す また,For each one in ~ の⽂は,エージェント集合に含まれるエージェントを順に取り出して処理を⾏っていく制御⽂です.これについても詳しくは artisoc のヘルプ等を参照して下さい. 上のコードで⾏われる処理の内容は下記のようになります.この処理の結果,エージェント型変数 nearestAgtには,⾃分から⾒て視野内(距離 Universe.Rs 内)にいるエージェントのうち,最も近いエージェントが代⼊されます.なぜそのようになるか,考えてみて下さい.

Page 11: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

11

[1] ⾃分から⾒て視野内(距離 Universe.Rs 内)にいるエージェントを全て取得し,エージェント集合型変数arroundAgtSet に代⼊する:6 ⾏⽬

[2] arroundAgtSet の⼀番最初(0 番⽬)のエージェントを取得し,nearestAgt に代⼊する.また,そのエージェントまでの距離を nearestDistance に代⼊する.これらは,繰り返し処理を⾏うにあたっての初期値である:8 ⾏⽬と 9 ⾏⽬

[3] arroundAgtSet の i 番⽬のエージェントを取り出して,そのエージェントまでの距離を測る:12 ⾏⽬ [4] その距離が現在の nearestDistance よりも⼩さかった場合,nearestDistance を⼩さい⽅の値に更新

し,nearestAgt を i 番⽬のエージェントに⼊れ替える:13 ⾏⽬~16 ⾏⽬ [5] i を 1 増加させながら[3]~[4]の⼿順を繰り返す:11 ⾏⽬~17 ⾏⽬ 上記の⼿順のうち[2]~[5]は「あるエージェント集合に⼊っているエージェントのうち,最も⾃分に近いエージェントを取り出す」という処理に相当し,そのような処理は⼩⿂(fish)エージェントの⽅でも使います.そこで次は,[2]~[5]の処理を関数としてまとめて,使いまわせるようにします.

8. 独⾃関数をつくる&使う artisoc では独⾃の関数やサブルーチンを定義することができます.それらを別のファイルに記述してインクルードすることもできますが,今回は同じモデルファイル中に記述することにします.この場合,ツリーウインドウで Universeをダブルクリックすると表⽰される「ルール:Universe」ウインドウの中に独⾃関数を記述します.このウインドウの中にすでに⽤意されている Univ_Init, Univ_Step_Begin,Univ_Step_End,Univ_Finish の外側であればどこに記述してもよいですが,今回は図 12 に⽰すように Univ_Finish の下の部分に記述することにしましょう.

図 12. 独⾃関数の記述場所

独⾃関数の定義⽅法については artisoc のマニュアルやヘルプなどを参照して下さい.ここでは⼿順 7 の項で⽰した[2]~[5]を関数化したものとして,図 12 に⽰す場所に下記のように記述します.

Page 12: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

12

1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:

Function GetNearestAgt(originAgt as Agt, arroundAgtSet as AgtSet) as Agt{ //arroundAgtSet に含まれるエージェントのうち,originAgt に最も距離が近いエージェントを返す Dim distance as Double Dim nearestDistance as Double Dim nearestAgt as Agt Dim one as Agt nearestAgt = GetAgt(arroundAgtSet, 0) nearestDistance = MeasureDistance(originAgt.X, originAgt.Y, nearestAgt.X, nearestAgt.Y, Universe.sea) For each one in arroundAgtSet

distance = MeasureDistance(originAgt.X, originAgt.Y, one.X, one.Y, Universe.sea) if distance < nearestDistance then

nearestDistance = distance nearestAgt = one

End if Next one Return(nearestAgt) }

これで GetNearestAgt(arg1, arg2)という関数を⽤いることで,arg2 で指定するエージェント集合に⼊っているエージェントのうち,arg1 に最も近いエージェントを返り値として取得することができるようになりました.⼿順 7 の項で⽰した[2]~[5]の処理が分からない,⾃分では書けないという初学者の⽅は安⼼して下さい.この部分の処理について理解できなくても,上記のように独⾃関数を記述すれば,GetNearestAgt( )を使⽤することができ,[2]~[5]の処理を⾏うことができます. 図 12 で⽰す部分に記述した独⾃関数は,「ルール:Universe」の中であればそのまま関数名を記述することで呼び出すことができます.各エージェントのルール(Agt_Init と Agt_Step)の中から呼び出す場合は関数名の前に@をつけて下さい.つまり,上記の独⾃関数を各エージェントのルールの中で使うためには,

@GetNearestAgt(arg1, arg2)

のように記述しなければなりません.

Page 13: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

13

9. サメの⾏動モデルを記述する ⼿順 8 で定義した独⾃関数を使って,サメ(shark)エージェントの⾏動ルールを記述しましょう.ルール:shark の Agt_Step の中に次のように記述して下さい. 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:

16: 17: 18: 19: 20:

Agt_Step{

Dim arroundAgtSet as AgtSet Dim nearestAgt as Agt

MakeAllAgtSetAroundOwn(arroundAgtSet, Universe.Rs, False)

If CountAgtSet(arroundAgtSet) > 0 then

nearestAgt = @GetNearestAgt(My, arroundAgtSet) If SpecifyAgtType(nearestAgt) == CAgtType("Universe.sea.shark") then

//視野内最近接エージェントがサメだった場合 My.Direction = GetDirection(My.X, My.Y, nearestAgt.X, nearestAgt.Y, Universe.sea) + 180

Else //視野内最近接エージェントが⼩⿂だった場合 My.Direction = GetDirection(My.X, My.Y, nearestAgt.X, nearestAgt.Y,

Universe.sea) End if

End if

Forward(1) }

8 ⾏⽬で「If CountAgtSet(arroundAgtSet) > 0 then」としているのは,視野内に他のエージェントがいた場合に向きを変える処理をするためです.CountAgtSet(arg1)はエージェント集合 arg1 に含まれるエージェントの数を数える関数であり,視野内にエージェントがいなかった場合は CountAgtSet (aroundAgt Set) の値が 0 となります.そこで,もし CountAgtSet(arroundAgtSet) > 0 ならば(すなわち arroundAgtSet に 1体以上のエージェントが含まれるならば)という分岐を⼊れておくのです.視野内に他のエージェントがいない場合は向きを変える処理が⾏われず,そのままの向きで距離 1 進みます:19 ⾏⽬. 9 ⾏⽬で独⾃関数 GetNearestAgt(My, arroundAgtSet)を使っています.Agt_Step から独⾃関数を呼び出す場合は関数名に@をつけるのを忘れないで下さい.9 ⾏⽬で視野内の最近接エージェントを nearestAgtに代⼊し,その後の If 分岐(10 ⾏⽬~17 ⾏⽬)で,nearestAgt が shark だった場合と fish だった場合で向き(My.Direction)を変える処理を分けています.nearestAgt がサメだった場合は,nearestAgt の⽅向(GetDirection 関数で取得する)とは反対⽅向(+180 度)を向くようにしています. SpecifyAgtType(), CagtType(), GetDirection()などの関数についてはヘルプを参照して下さい.

Page 14: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

14

10. ⼩⿂の⾏動モデルを記述する fish の Agt_Step も基本的には⼿順 9 で⽰した shark の Agt_Step と同じような形で記述しますが,下記の点で少しだけ異なります. — ⼩⿂の⽅は視野内のサメ(shark)エージェントだけを⾒ればよいので,MakeAllAgtSetAroundOwn()

ではなく,MakeOneAgtSetAroundOwn()を使います.使い⽅の詳細はヘルプを参照して下さい. — サメから逃げるときは少しだけスピードを早くしてあげます※この設定はなくても同じようなシミュレーション結果に

なります これらを考慮して,fish の Agt_Step には以下のように記述して下さい. 1: 2: 3: 4: 5: 6:

7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:

Agt_Step{

Dim arroundAgtSet as AgtSet Dim nearestAgt as Agt

MakeOneAgtSetAroundOwn(arroundAgtSet, Universe.Rs, Universe.sea.shark,

False)

If CountAgtSet(arroundAgtSet) == 0 then //視野内にサメエージェントがいなかったとき Forward(1)

Else //視野内にサメがいた場合 nearestAgt = @GetNearestAgt(My, arroundAgtSet) My.Direction = GetDirection(My.X, My.Y, nearestAgt.X, nearestAgt.Y,

Universe.sea) + 180 Forward(1.5)

End if }

Page 15: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

15

11. シミュレーションを実⾏する&コードまとめ ⼿順 10 まで終了すれば,サメ-⼩⿂モデルの完成です.実⾏ボタン(図 6)を押してシミュレーションを開始してみましょう.図 13 はサメの数:10,⼩⿂の数:500 のときのシミュレーションのキャプチャです.同じようなシミュレーション結果になることを確認して下さい.

図 13. シミュレーション実⾏中のマップ出⼒(サメの数:10,⼩⿂の数:500)

サメと⼩⿂の数や,⼩⿂の視野の値を変化させると,全体の挙動が変わります.条件によっては,個々のルールからは直感的には予想できない⾯⽩い創発現象が発⽣しますので,いろいろ試してみて下さい.創発現象については,解説記事「マルチエージェントシミュレーションをはじめてみよう」の 3 章をご覧下さい. 次ページ以降に本ドキュメントで紹介したサメ-⼩⿂モデルのコードをまとめます.シミュレーションが上⼿く動かなかった⽅はコードをチェックしてみて下さい.コードに問題がない場合は,要素の階層構造(ツリーウインドウ),出⼒設定(マップ出⼒),コントロールパネルのいずれかに問題がある可能性が⾼いので,⾒直して下さい. 質問・ご意⾒があれば,http://m-miura.jp/contact からご送信下さい.

Page 16: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

16

ルール:Universe Univ_Init{

Dim i As Integer

For i = 0 to Universe.Ns - 1 CreateAgt(Universe.sea.shark)

Next i

For i = 0 to Universe.Nf - 1 CreateAgt(Universe.sea.fish)

Next i } Univ_Step_Begin{ } Univ_Step_End{ } Univ_Finish{ } Function GetNearestAgt(originAgt as Agt, arroundAgtSet as AgtSet) as Agt{ //arroundAgtSet に含まれるエージェントのうち,originAgt に最も距離が近いエージェントを返す

Dim distance as Double Dim nearestDistance as Double Dim nearestAgt as Agt Dim one as Agt

nearestAgt = GetAgt(arroundAgtSet, 0) nearestDistance = MeasureDistance(originAgt.X, originAgt.Y, nearestAgt.X,

nearestAgt.Y, Universe.sea)

For each one in arroundAgtSet distance = MeasureDistance(originAgt.X, originAgt.Y, one.X, one.Y,

Universe.sea) if distance < nearestDistance then

nearestDistance = distance nearestAgt = one

End if Next one Return(nearestAgt)

}

Page 17: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

17

ルール:shark Agt_Init{

My.X = GetWidthSpaceOwn() * Rnd() My.Y = GetHeightSpaceOwn() * Rnd() My.Direction = 360 * Rnd()

} Agt_Step{

Dim arroundAgtSet as AgtSet Dim nearestAgt as Agt

MakeAllAgtSetAroundOwn(arroundAgtSet, Universe.Rs, False)

If CountAgtSet(arroundAgtSet) > 0 then

nearestAgt = @GetNearestAgt(My, arroundAgtSet) If SpecifyAgtType(nearestAgt) == CAgtType("Universe.sea.shark") then

//視野内最近接エージェントがサメだった場合 My.Direction = GetDirection(My.X, My.Y, nearestAgt.X, nearestAgt.Y,

Universe.sea) + 180 Else

//視野内最近接エージェントが⼩⿂だった場合 My.Direction = GetDirection(My.X, My.Y, nearestAgt.X, nearestAgt.Y,

Universe.sea) End if

End if

Forward(1) }

Page 18: shark-fish MAS v01 - M.MIURAm-miura.jp/data/shark-fish/shark-fish_MAS_v01.pdf · 2017. 5. 21. · 2 MASをつくってみよう 1. 空間,エージェント,変数を追加する

18

ルール:fish Agt_Init{

My.X = GetWidthSpaceOwn() * Rnd() My.Y = GetHeightSpaceOwn() * Rnd() My.Direction = 360 * Rnd()

} Agt_Step{

Dim arroundAgtSet as AgtSet Dim nearestAgt as Agt

MakeOneAgtSetAroundOwn(arroundAgtSet, Universe.Rf, Universe.sea.shark,

False)

If CountAgtSet(arroundAgtSet) == 0 then //視野内にサメエージェントがいなかったとき Forward(1)

Else //視野内にサメがいた場合 nearestAgt = @GetNearestAgt(My, arroundAgtSet) My.Direction = GetDirection(My.X, My.Y, nearestAgt.X, nearestAgt.Y,

Universe.sea) + 180 Forward(1.5)

End if }

その他の設定 空間 格⼦モデル,X:100,Y:100,ループする マップ出⼒ 原点位置:左下,表⽰型:チェス型,マーカーの拡⼤率:2.0 コントロールパネル

Ns,Nf,Rs,Rf を設定対象とし,全て直接⼊⼒インターフェース