実現したいこと
複雑ネットワークでウィルスが感染する様子を調べたいのですがデータの数が多く処理に時間が掛かってしまうため高速したいです。
###プログラムの概要
1step毎に7000~10000の数のノードデータ(ノードの名称id,x座標、y座標)が記載されたものが1800stepまであり、1step毎に読み込み、感染ノードであれば1を、それ以外のとき0をnode_listの最後に追加します。その後、関数を呼び出しノード同士の座標をそれぞれ比較して、座標の距離を求めて範囲内であれば感染リストに格納します。感染リストは、次のstep時に、参照して、新たに感染リストに追加していきます。stepの最後に時間と感染リストの数を出力します。
発生している問題・エラーメッセージ
1step毎にノードの数の階乗回for文でループしているため、1stepあたり約40秒ほど時間がかかってしまってしまい、1800秒間では約20時間掛かっています。
該当のソースコード
Python
1 2import sys 3import random 4import math 5import time 6import re 7 8#2点の差が縦横100mの距離の長さ 9#sqrt(100^2+100^2) 10D_100=math.sqrt((100*100)+(100*100)) 11 12Input = "node_data.txt" 13Output="output.txt" 14def file_write(output,infeced_list,t): 15 with open(output, 'a') as f: 16 f.write("%d %d\n" % (t,len(infeced_list))) 17 f.close() 18 19def SUMOTraceParser(): 20 #ファイルオープン 21 f1 = open(FCDOutput, 'r') 22 node_list = [] # ノードデータ保存リスト((車のid,x,y,レーン)) 23 infected_list=[] #感染リスト(id) 24 row_no = 0 #行数カウント 25 while True: 26 line = f1.readline() 27 line = line.replace("\n", "") # 改行削除 28 #timestep 29 if "timestep" in line: 30 t = re.sub(r"[^\d.]", "", line) 31 t = int(float(t)) 32 row_no+=1 33 #ノードデータ読み込み、node_listに追加 34 elif "end" not in line and "timestep" not in line: 35 row_no += 1 36 # 分割 37 l = line.split(',') 38 # ダブルコーテション削除 39 for i in range(len(l)): 40 l[i] = l[i].replace("''", "") 41 l[i]=float(l[i]) 42 l[i]=int(l[i]) 43 # 感染リストにidがあるとき 44 if l[0] in infected_list: 45 node_list.append((l[0],l[1],l[2], 1)) #1を追加 46 else: 47 node_list.append((l[0],l[1],l[2], 0)) #0を追加 48 #1stepの読み込み終了時 49 elif "end" in line: 50 test_list=Infect(node_list,t,infected_list) #関数呼び出し 51 infected_list=test_list 52 file_write(Output,infected_list,t) #ファイルに感染したノードを書き込み 53 node_list=[] 54 row_no+=1 55 if t == 1800: 56 # 強制終了 57 sys.exit() 58#ノード同士を比較して、感染リストに格納する関数 59def Infect(node_list, t, infected_list): 60 node_list.sort() #sort 61 node_list2=reversed(node_list) #revresed 62 node_id_list=set() #idリスト 63 #node_listを階乗回ループする 64 for i in range(len(node_list)): 65 for j in range(len(node_list2)-i): 66 A=None 67 #x,y差を止める 68 x_1=node_list[i][1] - node_list[j][1] 69 y_1=node_list[i][2] - node_list[j][2] 70 #2乗する 71 x_2=pow(x_1,2) 72 y_2=pow(y_1,2) 73 D=math.sqrt(x_2+y_2) #2点間の距離計算 74 if D<D_100: 75 if node_list[i][0] != node_list[j][0]: #同一ノードではないとき 76 # どちらかが1(感染状態)のとき 77 if node_list[i][3] == 1 and node_list[j][3] == 0: 78 A=True 79 if node_list[i][3] == 0 and node_list[j][3] == 1: 80 A=True 81 if A==True: 82 A=None 83 # 確率1%の確率で 84 b=random.random() 85 if b < 0.1: 86 infected_list.append(node_list[j][0]) #感染リストに追加 87 88 node_id_list.add(node_list[i][0]) 89 90 # 感染するノードをランダムに選択 91 if t==start_s: 92 infected_list=random.sample(node_id_list,1) 93 # リストの重複を削除 94 infected_list = list(set(infected_list)) 95 return infected_list 96 97if __name__ == '__main__': 98 SUMOTraceParser() 99
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。