集合型

artisoc4とartisoc Cloudにおける集合型変数の扱いについて解説します。

集合型変数とはデータの集まりを表現する変数です。artisoc4では配列エージェント集合型の変数、artisoc Cloudではリスト型セット型の変数を用いて実現します。

配列とリスト

artisoc4での配列は、artisoc Cloudにおいてはリスト型変数を用いることでほぼ同様のことが実現できます。

artisoc4

artisoc4において配列変数を用いるためには、配列のサイズをツリー上であらかじめ定義します。下図の例では、長さ5の1次元配列を定義しています。

../../_images/artisoc4_artisocCloud_2.png

配列変数へアクセスするためには、()を用いて要素番号を指定します。

Universe.hairetsu(3) = 5  //配列変数の3番目の要素に5を代入

artisoc Cloud

artisoc Cloudにおいては、artisoc4での配列に正確に対応するデータ型は存在しません。その代わり、リスト型の変数を用いることができます。

リスト型の変数を定義するには、下のように[]を用います。

Universe.list1 = [1, 2, 3, 4, 5]  # 長さが5のリストを定義

リスト型の変数にアクセスするには、[]を用いて要素番号を指定します。

Universe.list1[3] = 10  # リストの3番目の要素に10を代入
print(Universe.list1)  # --> [1, 2, 3, 10, 5] (3番目の要素に10が入っている。要素番号は0から数えることに注意)

エージェント集合型とセット型・リスト型

artisoc4でのエージェント集合型変数は、artisoc Cloudではセット型もしくはリスト型の変数を用いて表現します。以下の典型的な2つのケースに分けて説明します。

  • 関数を用いてエージェント集合を取得するケース

  • 空のエージェント集合に要素を追加していくケース

関数を用いてエージェント集合を取得するケース

たとえば、関数を用いて周囲にいるエージェントを取得するケースを考えます。

artisoc4

たとえばMakeAllAgtsetAroundOwn関数を用いることで、周囲にいるエージェントをエージェント集合型の変数として取得できます。このとき、エージェント集合型変数を事前に定義しておく必要があります。

Dim neighbors as Agtset
MakeAllAgtsetAroundOwn(neighbors, 2, False)  //自分から距離2以内にいるエージェントをエージェント集合型変数neighborsに格納する

取得したエージェント集合から要素を取得するには、GetAgt関数を用いて要素番号を指定します。ランダムに1つの要素を取得する場合には、たとえば以下のようにします。

one = GetAgt(neighbors, int(rnd() * CountAgtset(neighbors)))  //ランダムな要素番号を生成することで、ランダムに要素を取得

artisoc Cloud

周囲にいるエージェントを取得するためには、たとえばmake_agtset_around_own関数を用います。このとき、エージェント集合型変数を事前に定義しておく必要はありません。また、関数名をself.に続けて記述すること、エージェント集合は関数の戻り値として与えられることに注意します。

neighbors = self.make_agtset_around_own(2, False)

このとき、エージェント集合neighborsはセット型の変数です。セット型は要素の順番が定義されず、したがって要素番号を指定して要素を取得することができないことに注意する必要があります。

ランダムに1つの要素を取得する場合には、以下のようにrandchoice関数を用います。

one = randchoice(neighbors)

空のエージェント集合に要素を追加していくケース

artisoc4

下図のように、ツリー上でエージェント集合型変数peopleを定義する場合を考えます。

../../_images/artisoc4_artisocCloud_3.png

このとき、変数の初期値は空のエージェント集合です。AddAgt関数を用いることで、ここにエージェントを追加していくことができます。

taro = create_agt(Universe.hiroba.hito)
AddAgt(Universe.people, taro)  //エージェント集合peopleにエージェントtaroを追加

hanako = CreateAgt(Universe.hiroba.hito)
AddAgt(Universe.people, hanako)  //エージェント集合peopleにエージェントhanakoを追加

この時点で、peopleには0番目の要素にtaro、1番目の要素にhanakoが格納されています。(要素番号は0番から数えることに注意してください)

エージェントを取り出すためには、GetAgt関数で位置を指定して取得します。

one = GetAgt(Universe.people, 1)  //1番目の要素(hanako)を取得

artisoc Cloud

artisoc Cloudで同じようなルールを実現するためには、リスト型またはセット型の変数を用います。リスト型は要素の順番が定義されますが、セット型では定義されません。

まずは、リスト型の変数を用いる場合を見てみます。

ツリー上でUniverse変数people_listを定義したとき、初期値は整数の0です。これをリスト型として用いるためには、univ_init内で初期化する必要があります。list()と記述することで空のリストを生成できますので、これをuniv_init内で代入します。

def univ_init(self):
    Universe.people_list = list()  # 変数people_listを空のリストとして初期化

リスト型変数に要素を追加するにはappend関数を用います。

taro = create_agt(Universe.hiroba.hito)
Universe.people_list.append(taro)  # peopleにtaroを追加

hanako = create_agt(Universe.hiroba.hito)
Universe.people_list.append(hanako)  # peopleにhanakoを追加

この時点で、peopleには0番目の要素にtaro、1番目の要素にhanakoが格納されています。(要素番号は0番から数えることに注意してください)

エージェントを取り出すためには、[]を用いて位置を指定します。

one = Universe.people_list[1]  # 1番目の要素(hanako)を取得

続いて、セット型の変数を用いる場合を見てみます。

ツリー上でuniverse変数people_setを定義します。このとき初期値は整数の0ですので、univ_initで空のセットとして初期化します。空のセットを生成するにはset()と記述します。

def univ_init(self):
    Universe.people_set = set()  # 変数people_setを空のセットとして初期化

セット型変数に要素を追加するにはadd関数を用います。

taro = create_agt(Universe.hiroba.hito)
Universe.people_set.add(taro)  # people_setにtaroを追加

hanako = create_agt(Universe.hiroba.hito)
Universe.people_set.add(hanako)  # people_setにhanakoを追加

セット型の変数では、要素の順番が定義されません。したがって、位置を指定して要素を取り出すことができないことに注意が必要です。

主な操作のまとめ

以下、peopleを集合型変数(エージェント集合型/セット型/リスト型)、taroをエージェントとして、基本的な操作についてまとめます。

要素の追加

artisoc4(エージェント集合型)

AddAgt(people, taro)

artisoc Cloud(セット型)

people.add(taro)

artisoc Cloud(リスト型)

people.append(taro)

要素の取得

artisoc4(エージェント集合型)

one = GetAgt(people, 1)  # 1番目の要素を取得

artisoc Cloud(セット型)

one = randchoice(people)  # ランダムに1つの要素を取得

※要素の順番が定義されないため、位置を指定して取得することはできない

artisoc Cloud(リスト型)

one = people[1]  # 1番目の要素を取得

要素の削除

artisoc4(エージェント集合型)

RemoveAgt(people, taro)

artisoc Cloud(セット型)

people.discard(taro)
people.remove(taro)

※removeの場合、集合に存在しない値を指定するとエラーになる

artisoc Cloud(リスト型)

people.remove(taro)

※リストに複数の同じ要素が存在する場合、最初の要素を削除する

要素の探索

artisoc4
GetAgtEntry関数を用います。要素が含まれている場合、要素番号のうち最も小さい値を整数で返します。含まれていない場合、-1を返します。

//peopleにtaroが含まれている場合、処理を行う
If GetAgtEntry(people, taro) >= 0 Then
  [処理]
End If

artisoc Cloud(セット型/リスト型)
演算子inを用います。要素が含まれているかどうかをTrue or Falseで返します。

//peopleにtaroが含まれている場合、処理を行う
if taro in people:
    [処理]

集合のクリア

artisoc4(エージェント集合型)

ClearAgtset(people)

artisoc Cloud(セット型/リスト型)

people.clear()

セット型からリスト型への変換

artisoc Cloudには、セット型からリスト型に変換するmake_agtlist関数が用意されています。

セット型からリスト型への変換にはこの関数を利用します。このとき、エージェントの属性値によって並べ替えをすることができます。

# セット型の変数people_setを属性tallの昇順に並べたリストを取得する
people_list = make_agtlist(people_set, key="tall")

単にリスト型に変換するだけであれば、list関数でも可能です。

# セット型の変数people_setをリスト型に変換する
people_list = list(people_set)

セット型とリスト型の使い分け

セット型とリスト型には、主に以下のような違いがあります。

  • 要素の順番 - セット型は持たず、リスト型は持つ

  • 要素の重複 - セット型は要素の重複を許さず、リスト型は持つ

  • 要素の探索- セット型はリスト型に比べて要素の探索が早い

セット型の長所の1つは、要素の探索が早いことです。要素の探索はセット型もリスト型もinを用いて同じ方法で行いますが、リスト型に比べてセット型のほうが素早く終わります。

if hanako in people:
    [hanakoがpeopleに含まれる場合の処理]

したがってって、要素の探索を頻繁に行う場合はセット型を、要素に順番を持たせたい場合はリスト型を用いるとよいでしょう。