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

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

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

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

Q&A

解決済

2回答

574閲覧

idから復元したエージェントの名称が取得出来ない

IT_takumin

総合スコア8

Python

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

0グッド

0クリップ

投稿2022/11/20 04:51

前提

シミュレーションを行うためにエージェントベースモデルを改変してます。
ゴールした事でシミュレーション環境から除外させたエージェントを最後にから復元させてその名前を出力した所、エラーが出て詰まってしまいました。

実現したいこと

除外させたエージェントを最後にIDから復元させてその名前を出力出来る様にしたい

発生している問題・エラーメッセージ

AttributeError Traceback (most recent call last) <ipython-input-13-404c461c4122> in <module> 1 for ptr, log in survival.items(): 2 agent = _ctypes.PyObj_FromPtr(ptr) # idから復元 ----> 3 print(agent.name) 4 5 AttributeError: 'Affine2D' object has no attribute 'name'

該当のソースコード

python

1import numpy as np 2import matplotlib.pyplot as plt 3import matplotlib.animation as animation 4from IPython.display import HTML 5import _ctypes 6 7a1 = -0.034298 8b1 = 3.348394 9c1 = 4.252840 10d1 = -0.003423 11 12survival=dict() 13 14 15class Agent: 16 def __init__(self, name = None, pos = None, vel = None, SIZE = 10, VEL = 1, 17 RANGE_SEPARATE = 0.5,color = None): 18 self.name = name if name else 'agent_02' 19 self.pos = pos if pos else np.random.uniform(-SIZE, SIZE, 2) 20 self.vel = vel if vel else np.random.uniform(-VEL, VEL, 2) 21 self.SIZE = SIZE 22 self.VEL = VEL 23 self.RANGE_SEPARATE = RANGE_SEPARATE#分離範囲 24 self.vel_tmp = np.zeros(2)#移動 25 self.color = color if color else 'k' 26 27 28 def distance(self, other):#ユークリッド距離 29 return np.linalg.norm(self.pos - other.pos) 30 31 def ruleSeparate(self, others, ratio = 1): 32 others = [other for other in others if self.distance(other) < self.RANGE_SEPARATE]#範囲内に入ったエージェントの選別 33 v = np.zeros(2) 34 if not others: 35 return 0 36 for other in others: 37 d = self.pos - other.pos#dが-になる時ある? 38 v += d / self.distance(other)#進行方向の単位ベクトル 39 self.vel_tmp += v / len(others) * ratio#平均を出してそれをratio倍する 40 return v / len(others) * ratio 41 42 43 44 def calculate(self, others): 45 self.ruleSeparate(others, 0.5) 46 47 def update(self) -> bool:#返り値の型名 48 self.vel += self.vel_tmp#進行速度ベクトル更新 49 v = np.linalg.norm(self.vel) 50 #壁に当たったら反転 51 if (abs(self.pos + self.vel)[0] > self.SIZE): 52 self.vel[0] = -self.vel[0] 53 if (abs(self.pos + self.vel)[1] > self.SIZE): 54 self.vel[1] = -self.vel[1] 55 56 self.pos += self.vel#位置更新 57 self.vel_tmp = np.zeros(2)##進行速度ベクトル初期化 58 return True 59 60class AgentEdited(Agent): 61 def __init__(self, *args, **kwargs): 62 super(AgentEdited, self).__init__(*args, **kwargs) 63 #クラス(子クラス)で別のクラス(親クラス)を継承できます。継承することで、親クラスのメソッドを子クラスから呼び出せる 64 #super().親クラスのメソッド # python3系での標準の書き方 65 #super(親クラスのオブジェクト, self).親クラスのメソッド # python2系での書き方 66 #不特定多数の引数を受け取ることができる仕組みを作るのが「*args」「**kwargs」 67 self.color = kwargs.get('color', 'r') 68 self.name=kwargs.get('agent_01') 69 70 71 72 73 def ruleSeparate(self, others, ratio = 1): 74 others = [other for other in others if self.distance(other) < self.RANGE_SEPARATE] 75 v = np.zeros(2) 76 if not others: 77 return 0 78 for other in others: 79 d = self.pos - other.pos 80 vel = self.vel - other.vel 81 TTNP = d / (vel + 1e-5) # 0除算防止のため微小値を挿入 82 DINP = self.distance(other) 83 v += 1/(1+np.exp(-(c1+d1*TTNP))) * 1/(1+np.exp(-(b1+a1*DINP))) 84 self.vel_tmp += v / len(others) * ratio 85 return v / len(others) * ratio 86 87 def calculate(self, others): 88 self.ruleSeparate(others) # only separate 89 90def calc_rad(pos2, pos1):#角計算 91 return np.arctan2(pos2[1] - pos1[1], pos2[0] - pos1[0]) 92 93#np.arctan(x)は引数が一つでarctan(x)をラジアンで返す。返り値は-pi / 2からpi / 2(-90度から90度)の間になる。 94#np.arctan2(y, x)は引数が二つで、arctan(y / x)をラジアンで返す。この角度は、極座標平面において原点から座標(x, y)へのベクトルがx軸の正の方向となす角度(偏角)であり、返り値は-piからpi(-180度から180度)の間になる 95#print(np.degrees(np.arctan2(-1, 1))) 96# -45.0 97#print(np.degrees(np.arctan2(1, -1))) 98# 135.0 99 100def rotate_vec(vec, rad):#ベクトル更新 101 return np.dot(vec, np.array([[np.cos(rad), -np.sin(rad)], [np.sin(rad), np.cos(rad)]]).T) 102 103class AgentGoForWall(AgentEdited): 104 def __init__(self, *args, **kwargs): 105 super(AgentGoForWall, self).__init__(*args, **kwargs) 106 survival[id(self)] = [self.pos] # カウント初期化 107 108 self.color = kwargs.get('color', 'b') 109 self.name=kwargs.get('agent_03') 110 111 max_distance = 0 112 self.goal = None # 角が一番遠い場所 113 for px in [-self.SIZE, self.SIZE]: 114 for py in [-self.SIZE, self.SIZE]: 115 dist = np.linalg.norm(self.pos - np.array([px, py])) 116 if max_distance < dist: 117 max_distance = dist#最大値の更新 118 self.goal = np.array([px, py]) 119 self.vel = rotate_vec(np.array([self.VEL, 0]), calc_rad(self.goal, self.pos)) 120 121 def update(self) -> bool:#"返り値の型名" 122 self.vel += self.vel_tmp 123 self.vel += rotate_vec(np.array([self.VEL, 0]), calc_rad(self.goal, self.pos)) 124 125 v = np.linalg.norm(self.vel) 126 self.vel =self.vel /v 127 128 if abs(self.pos + self.vel)[0] > self.SIZE or abs(self.pos + self.vel)[1] > self.SIZE: 129 return False # deactivate this Agent 130 131 self.pos += self.vel 132 survival[id(self)].append(self.pos) # カウントアップ 133 self.vel_tmp = np.zeros(2) 134 return True 135 136class Boids: 137 def __init__(self, AGENT = 20):#Agent数 138 self.agents = [Agent() for _ in range(AGENT)] 139 140 def calculate(self): 141 for agent in self.agents: 142 agent.calculate([other for other in self.agents if agent != other]) 143 144 def update(self): 145 self.agents = [agent for agent in self.agents if agent.update()] 146 147 def simulation(self): 148 self.calculate() 149 self.update() 150 151 def positions(self):#showimageはpos_arrayを渡してた 152 x, y, c = list(), list(), list() 153 for agent in self.agents: 154 x.append(agent.pos[0]) 155 y.append(agent.pos[1]) 156 c.append(agent.color) 157 return (np.array(x), np.array(y)), c 158 159 160np.random.seed( 0 ) 161B = Boids(0) 162num_central=1 163for i in range(num_central): 164 B.agents.append(AgentEdited()) 165num=100 166for i in range(num): 167 B.agents.append(AgentGoForWall()) 168 169fig, ax = plt.subplots(figsize = (6, 6)) 170ax.set_xlim(-10, 10) 171ax.set_ylim(-10, 10) 172ax.grid(True) 173ims = [] 174for t in range(100): 175 B.simulation() 176 plot_data,plot_color = B.positions() 177 im=ax.scatter(*plot_data, marker="o", s=20, c=plot_color) 178 ims.append([im]) 179 180ani = animation.ArtistAnimation(fig, ims, interval=400, repeat=False) 181HTML(ani.to_jshtml()) 182 183for ptr, log in survival.items(): 184 agent = _ctypes.PyObj_FromPtr(ptr) # idから復元 185 print(agent.name + ": " + len(log))

試した事

各エージェントの実行時にself.nameで定義していておそらく、そこで問題が起きているという所までは理解出来たが解決方法がわからなかったです。

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

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

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

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

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

guest

回答2

0

ベストアンサー

やっぱりそういう問題が起きますね,Boids().add_agent()関数を用意して,領域内に残存するAgentactiveと,これまでに追加されたことのあるAgentevery,壁に向かうAgentgo2wallなど個別に管理するようにします.

Python

1class AgentGoForWall(AgentEdited): 2 def __init__(self, *args, **kwargs): 3 super(AgentGoForWall, self).__init__(*args, **kwargs) 4 self.log = [self.pos] # カウント初期化 5 6 self.color = kwargs.get('color', 'b') 7 self.name=kwargs.get('agent_03') 8 9 max_distance = 0 10 self.goal = None # 角が一番遠い場所 11 for px in [-self.SIZE, self.SIZE]: 12 for py in [-self.SIZE, self.SIZE]: 13 dist = np.linalg.norm(self.pos - np.array([px, py])) 14 if max_distance < dist: 15 max_distance = dist#最大値の更新 16 self.goal = np.array([px, py]) 17 self.vel = rotate_vec(np.array([self.VEL, 0]), calc_rad(self.goal, self.pos)) 18 19 def update(self) -> bool:#"返り値の型名" 20 self.vel += self.vel_tmp 21 self.vel += rotate_vec(np.array([self.VEL, 0]), calc_rad(self.goal, self.pos)) 22 23 v = np.linalg.norm(self.vel) 24 self.vel =self.vel /v 25 26 if abs(self.pos + self.vel)[0] > self.SIZE or abs(self.pos + self.vel)[1] > self.SIZE: 27 return False # deactivate this Agent 28 29 self.pos += self.vel 30 self.log.append(self.pos) # カウントアップ 31 self.vel_tmp = np.zeros(2) 32 return True 33 34class Boids: 35 def __init__(self, AGENT = 20):#Agent数 36 self.active = list() 37 self.every = list() 38 self.go2wall = list() 39 for _ in range(AGENT): 40 self.add_agent(Agent()) 41 42 def add_agent(self, agent): 43 self.active.append(agent) 44 self.every.append(agent) 45 if isinstance(agent, AgentGoForWall): 46 self.go2wall.append(agent) 47 48 def calculate(self): 49 for agent in self.active: 50 agent.calculate([other for other in self.active if agent != other]) 51 52 def update(self): 53 self.active = [agent for agent in self.active if agent.update()] 54 55 def simulation(self): 56 self.calculate() 57 self.update() 58 59 def positions(self):#showimageはpos_arrayを渡してた 60 x, y, c = list(), list(), list() 61 for agent in self.active: 62 x.append(agent.pos[0]) 63 y.append(agent.pos[1]) 64 c.append(agent.color) 65 return (np.array(x), np.array(y)), c 66 67np.random.seed( 0 ) 68B = Boids(0) 69num_central=1 70for i in range(num_central): 71 B.add_agent(AgentEdited()) 72num=100 73for i in range(num): 74 B.add_agent(AgentGoForWall()) 75 76for t in range(100): 77 B.simulation() 78 plot_data,plot_color = B.positions() 79 80for agent in B.go2wall: 81 print(f"{agent.name}: {len(agent.log)}")

これまではAgentたちをBoidsクラスのリストに直接appendしていましたが,add_agent()を利用することでアクティブなAgentやこれまでに追加されたAgentなど,全ての管理を任せるようにしましょう.

投稿2022/11/21 06:48

PondVillege

総合スコア1579

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

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

0

直接解決につながる回答ではありませんが、idからインスタンスなどの実体を復元するのは問題があるようなので避けた方がよいと思います。
詳細はIs it possible to dereference variable id's?を参照ください。

投稿2022/11/21 06:26

can110

総合スコア38266

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

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

IT_takumin

2022/11/21 10:55

ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問