質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

989閲覧

エージェントが持っている配列から3人以上が重複しているものを探す方法

HGK

総合スコア29

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/10/21 06:34

pythonで学級の様子をマルチエージェントシミュレーションを行おうと考えています
その際に、友人対象とする友人リンク、排斥対象とする排斥リンク、いじめ対象とするいじめリンクを設定しています
友人リンクと排斥リンクは好感度で定義します
いじめリンクは、生徒Aが友人リンクをお互いに張り合っているエージェント2人以上が同じ生徒Bに排斥リンクを張っているときに生徒Aから生徒Bにいじめリンクを張りますイメージ説明

これをシミュレーションは会話相手選択→話題選択→好感度更新→影響力更新
の流れで行います

それを以下のコードを書きました

python

1import numpy as np 2import random 3import pandas as pd 4 5a = 0.4 6b = 0.4 7c = 0.2 8v1 = 0.3 9v2 = 0.3 10v3 = 0.6 11w1 = 0.2 12w2 = 0.2 13w3 = 0.6 14ap = 0.3 15rm = 0.05 16q = 0.3 17issues =10 18 19 20def sign(x,y): 21 if x*y>0: 22 sign = 1 23 if x*y == 0: 24 sign = 0 25 if x*y<0: 26 sign = -1 27 return sign 28 29def gij(x,y,z): 30 change = v1*(sign(x,y)*(abs(x*y)**0.5)-z) 31 return change 32 33 34class Agent: 35 def __init__(self,agent_id): 36 self.id = agent_id 37 self.talk = [] 38 self.topic = [] 39 self.f = np.random.uniform(low=0.0, high=0.1, size=None) #影響力 40 self.s = {} #影響力更新で使用 41 self.friend_list = [] #友人リンク 42 self.hi_friend_list = [] #被友人リンク 43 self.exclusion_list = [] #排斥リンク 44 self.hi_exclusion_list = [] #被排斥リンク 45 self.bullying_list = [] #いじめリンク 46 self.hi_bullying_list = [] #被いじめリンク 47 self.lp = {} #lpi iu 自分からuへの好感度 48 self.lc = {} #lc iu 実際の好感度 49 self.lagent = {} #lpi ui uからの好感度 50 self.lpi = {} #lpi uj u→j 自分が思うuからjへの好感度 51 self.lx = {} #lpi ix 自分の話題xへの好感度 52 self.lxagent = {} #lpi ux 自分が思うuの話題xへの好感度 53 54 def First_set(self,agents): #初期設定 55 issues = 10 56 for agent in agents: 57 kari = {} 58 if agent is self: 59 continue 60 likability = np.random.uniform(low=-0.1, high=0.1, size=None) 61 self.lp[agent.id] = likability 62 self.lc[agent.id] = likability 63 like = np.random.uniform(low=-0.1, high=0.1, size=None) 64 self.lagent[agent.id] = like 65 for t in agents: 66 if t is agent: 67 continue 68 interested = np.random.uniform(low=-0.1, high=0.1, size=None) 69 kari[t.id] = interested 70 self.lpi[agent.id] = kari 71 72 for issue in range(issues): 73 instinct = np.random.uniform(low=-0.1, high=0.1, size=None) 74 self.lx[issue] = instinct 75 kari = {} 76 for agent in agents: 77 if issue is agent: 78 continue 79 instinct = np.random.uniform(low=-0.1, high=0.1, size=None) 80 kari[agent.id] = instinct 81 self.lxagent[issue] = kari 82 83 def decide_talk_man(self,agents): #会話相手選択 84 agents_except_me = {} 85 weights_for_me = [] 86 z = 0 87 for agent in agents: 88 if agent is self: 89 continue 90 h = a*self.lp[agent.id]+b*self.lagent[agent.id]*(1-(self.f-agent.f))+c*(self.f-agent.f) 91 h = (h+0.8)/1.6 92 z += h 93 for agent in agents: 94 if agent is self: 95 continue 96 h = a*self.lp[agent.id]+b*self.lagent[agent.id]*(1-(self.f-agent.f))+c*(self.f-agent.f) 97 h = (h+0.8)/1.6 98 weight = h / z 99 agents_except_me[agent.id] = agent.id 100 weights_for_me.append(weight) 101 self.talk = random.choices(list(agents_except_me), weights=weights_for_me) 102 return self.talk 103 104 def decide_topic(self,agents,talk): #話題選択 105 talks = self.talk[0] 106 topic_except_me = {} 107 weights_for_me = [] 108 zz = 0 109 110 for agent in agents: 111 if agent is self: 112 continue 113 if agent.id == talks: 114 for age in agents: 115 talk_f = agent.f 116 if age is agent or age is self: 117 continue 118 zz += abs(self.lp[age.id]*(1-(talk_f-self.f))+self.lpi[agent.id][age.id]*(1-(self.f-talk_f))) 119 120 for issue in range(issues): 121 for agent in agents: 122 if agent is self: 123 continue 124 if agent.id ==talks: 125 zz += abs(self.lx[issue]*(1-(talk_f-self.f))+self.lxagent[issue][agent.id]*(1-(self.f-talk_f))) 126 127 for agent in agents: 128 if agent is self: 129 continue 130 if agent.id == talks: 131 for age in agents: 132 if age is agent or age is self: 133 continue 134 r = abs(self.lp[age.id]*(1-(talk_f-self.f))+self.lpi[agent.id][age.id]*(1-(self.f-talk_f)))/zz 135 topic_except_me[age.id] = age.id 136 weights_for_me.append(r) 137 138 for issue in range(issues): 139 for agent in agents: 140 if agent is self: 141 continue 142 if agent.id ==talks: 143 r = abs(self.lx[issue]*(1-(talk_f-self.f))+self.lxagent[issue][agent.id]*(1-(self.f-talk_f)))/zz 144 issue += 31 145 topic_except_me[issue] = issue 146 weights_for_me.append(r) 147 148 self.topic = random.choices(list(topic_except_me), weights=weights_for_me) 149 return self.topic 150 151 def update_like1(self,agents,talk,topic): #好感度更新 152 talks = talk[0] 153 topics = topic[0] 154 if topics <= 30: 155 x = self.lp[talks] 156 y = self.lp[topics] 157 z = self.lpi[talks][topics] 158 else: 159 topics -= 31 160 x = self.lx[topics] 161 y = self.lp[talks] 162 z = self.lxagent[topics][talks] 163 l = x*y*z 164 if l>=0: 165 dlu1 = gij(y,z,x) 166 dlx1 = gij(x,z,y) 167 else: 168 if x >= y: 169 dlu1 = gij(x,z,0) 170 dlx1 = 0 171 else: 172 dlu1 = 0 173 dlx1 = gij(y,z,0) 174 for agent in agents: 175 if agent.id is talks: 176 r = w1*self.lp[talks]+w2*self.lagent[talks]*(1-(self.f-agent.f))+w3*(self.f-agent.f) 177 r = (r+0.8)/1.6 178 break 179 weights_for_stra = {r,1-r} 180 kinds_of_stra = ["mini","same"] 181 stra = random.choices(kinds_of_stra, weights=weights_for_stra) 182 if stra == "mini": 183 dlu2 = v2*(self.lagent[talks]-self.lp[talks]) 184 else: 185 dlu2 = v3*sign(1,(self.lagent[talks]))*(abs(self.lagent[talks]+self.lp[talks])) 186 187 dlu = dlu1+dlu2 188 dlx = dlx1 189 return dlu,dlx 190 191 def update_like2(self,talk,topic,dlu,dlx): #好感度更新2 192 talks = self.talk[0] 193 topics = self.topic[0] 194 self.lp[talks] = self.lp[talks]+dlu 195 196 if self.lp[talks] > 1.0: 197 self.lp[talks] = 1.0 198 elif self.lp[talks] < -1.0: 199 self.lp[talks] = -1.0 200 201 self.lc[talks] = self.lp[talks] 202 203 if topics <= 30: 204 self.lp[topics] += dlx 205 206 if self.lp[topics] > 1.0: 207 self.lp[topics] = 1.0 208 elif self.lp[topics] < -1.0: 209 self.lp[topics] = -1.0 210 else: 211 topics -= 31 212 self.lx[topics] += dlx 213 214 if self.lx[topics] > 1.0: 215 self.lx[topics] = 1.0 216 elif self.lx[topics] < -1.0: 217 self.lx[topics] = -1.0 218 219 220 def link(self,agents): #友人リンク、排斥リンクの設定 221 for agent in agents: 222 if agent is self: 223 continue 224 if self.lc[agent.id] >= 0.20: 225 if agent.id in self.friend_list: 226 continue 227 self.friend_list.append(agent.id) 228 agent.hi_friend_list.append(self.id) 229 elif self.lc[agent.id] <= -0.04: 230 if agent.id in self.exclusion_list: 231 continue 232 self.exclusion_list.append(agent.id) 233 agent.hi_exclusion_list.append(self.id) 234 else: 235 pass 236 237 def ijime_link(self,agents): #いじめリンク設定 238 for agent in agents: 239 if agent is self: 240 continue 241 if agent.id in self.friend_list and self.id in agent.friend_list: 242 if agent.id in self.bullying_list: 243 continue 244 candidate = set(self.exclusion_list) & set(agent.exclusion_list) 245 for age in agents: 246 if age is self or agent is age: 247 continue 248 if age.id in self.friend_list and self.id in agent.friend_list: 249 ijime = set(candidate) & set(age.exclusion_list) 250 if len(ijime) > 0: 251 self.bullying_list += list(ijime) 252 253 for agent in agents: 254 if agent is self: 255 continue 256 if agent.id in self.bullying_list: 257 if self.id in agent.hi_bullying_list: 258 continue 259 agent.hi_bullying_list.append(self.id) 260 261 def update_f(self,turn): #影響力更新 262 self.s[turn] = (len(self.hi_friend_list)-len(self.hi_exclusion_list)) 263 if turn > 0: 264 dr = rm*(self.s[turn]-self.s[turn-1]) 265 self.f += dr 266 267 if self.f > 1.0: 268 self.f = 1.0 269 elif self.f < 0: 270 self.f = 0 271 272 273 def updete_Pnet(self,agents): #他の生徒から他の生徒への好感度更新 274 for agent in agents: 275 for age in agents: 276 if agent is age or self is agent: 277 continue 278 E = np.random.uniform(low=-0.3, high=0.3, size=None) 279 dlp = ap*(agent.lc[age.id]-self.lpi[agent.id][age.id])+E 280 self.lpi[agent.id][age.id] += dlp 281 282 if self.lpi[agent.id][age.id] > 1.0: 283 self.lpi[agent.id][age.id] = 1.0 284 elif self.lpi[agent.id][age.id] < -1.0: 285 self.lpi[agent.id][age.id] = -1.0 286 287 288class Simulation: 289 def __init__(self): 290 self.agents = [] 291 292 def generate_agents(self, agents_num): 293 self.agents = [Agent(agent_id) for agent_id in range(agents_num)] 294 for agent in self.agents: 295 agent.First_set(self.agents) 296 297 def play_the_game(self): 298 num_agents = 31 299 turns = 4000 300 self.generate_agents(num_agents) 301 for turn in range(turns): 302 for agent in self.agents: 303 self.talk = agent.decide_talk_man(self.agents) 304 self.topic = agent.decide_topic(self.agents,self.talk) 305 dlu,dlx = agent.update_like1(self.agents,self.talk,self.topic) 306 agent.update_like2(self.talk,self.topic,dlu,dlx) 307 agent.link(self.agents) 308 agent.ijime_link(self.agents) 309 agent.update_f(turn) 310 agent.updete_Pnet(self.agents) 311 312sim = Simulation 313sim.play_the_game() 314for agent in sim.agents: 315 print(" Agent", ":",agent.id) 316 print(" いじめ",":",agent.bullying_list)

このコードを実行したところ時間がかかりすぎているため実行中に止まりました
原因はいじめリンクの設定のコードです

いじめリンクの設定のコードはどのようにすればよいでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

以下は返信コメントを受けての追記分です。

bullying_listの挙動が意図した物でないなら、何らかの方法で同じ物を含まないようにチェックする必要があります。たとえば、以下のようにijime_link()を変更した場合、私の環境(3年前のノートPC)上で num_agents = 31, turns = 4000 の設定で動かして完了まで7分くらいになります。
(プログラムの内容は見ていないので、この変更でOKなのかは不明ですが)

python

1import numpy as np 2import random 3from time import perf_counter 4import pandas as pd 5 6class Agent: 7 # 途中省略 8 def ijime_link(self,agents): #いじめリンク設定 9 for agent in agents: 10 if agent is self: 11 continue 12 if agent.id in self.friend_list and self.id in agent.friend_list: 13 if agent.id in self.bullying_list: 14 continue 15 candidate = set(self.exclusion_list) & set(agent.exclusion_list) 16 for age in agents: 17 if age is self or agent is age: 18 continue 19 if age.id in self.friend_list and self.id in agent.friend_list: 20 ijime = set(candidate) & set(age.exclusion_list) 21 for ij in ijime: 22 if ij not in self.bullying_list: 23 self.bullying_list.append(ij) 24 #if len(ijime) > 0: 25 # self.bullying_list += list(ijime) 26 27 for agent in agents: 28 if agent is self: 29 continue 30 if agent.id in self.bullying_list: 31 if self.id in agent.hi_bullying_list: 32 continue 33 agent.hi_bullying_list.append(self.id) 34 35 36class Simulation: 37 def __init__(self): 38 self.agents = [] 39 40 def generate_agents(self, agents_num): 41 self.agents = [Agent(agent_id) for agent_id in range(agents_num)] 42 for agent in self.agents: 43 agent.First_set(self.agents) 44 45 def play_the_game(self): 46 num_agents = 31 47 turns = 4000 48 self.generate_agents(num_agents) 49 for turn in range(turns): 50 for agent in self.agents: 51 self.talk = agent.decide_talk_man(self.agents) 52 self.topic = agent.decide_topic(self.agents,self.talk) 53 dlu,dlx = agent.update_like1(self.agents,self.talk,self.topic) 54 agent.update_like2(self.talk,self.topic,dlu,dlx) 55 agent.link(self.agents) 56 agent.ijime_link(self.agents) 57 agent.update_f(turn) 58 agent.updete_Pnet(self.agents) 59 60st = perf_counter() 61sim = Simulation() 62sim.play_the_game() 63ed = perf_counter() 64for agent in sim.agents: 65 print(" Agent", ":",agent.id) 66 print(" いじめ",":",agent.bullying_list) 67 68print(ed - st)

以下は以前の回答です。

試しに num_agents = 7, turns = 2000 の設定で動かしてみたところ、sim.play_the_game()が終わった時点で添付図のようにsim.agents[]のbullying_listが非常に大きなデータになっていました(13,595項目)。
イメージ説明

ijime_link()の処理を見てみると、以下のように延々とbullying_listを伸ばしていく処理になっていますが、そもそもこれは意図した動作なのでしょうか?
self.bullying_list += list(ijime)

投稿2021/10/21 08:21

編集2021/10/21 16:04
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

HGK

2021/10/21 14:44

回答ありがとうございます その処理は意図したものではありません 条件を満たした時、bullying_listに追加し、同じものは含まないというようにしたいです
HGK

2021/10/22 06:13

おかげで解決することができました ありがとうございます
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問