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

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

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

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

最適化

最適化とはメソッドやデザインの最適な処理方法を選択することです。パフォーマンスの向上を目指す為に行われます。プログラミングにおける最適化は、アルゴリズムのスピードアップや、要求されるリソースを減らすことなどを指します。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Python

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

Q&A

2回答

1296閲覧

階乗のループがある複雑ネットワーク解析プログラムを高速化したい

Dobutori

総合スコア2

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

最適化

最適化とはメソッドやデザインの最適な処理方法を選択することです。パフォーマンスの向上を目指す為に行われます。プログラミングにおける最適化は、アルゴリズムのスピードアップや、要求されるリソースを減らすことなどを指します。

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Python

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

0グッド

2クリップ

投稿2022/01/05 05:51

実現したいこと

複雑ネットワークでウィルスが感染する様子を調べたいのですがデータの数が多く処理に時間が掛かってしまうため高速したいです。
###プログラムの概要
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

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

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

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

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

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

guest

回答2

0

scipy.spatial.KDTreeを使うと距離計算が楽になります。
参考:【Python】scipy KD treeの使い方
以下は人は入れ替わらない前提でのコード例です。

Python

1import numpy as np 2from scipy import spatial 3 4FIELD_SIZE = 25000 5INFECT_DIST = 100 6INFECT_RATE = 0.1 7N_AGENT = 10000 8 9infecteds_cur = np.zeros(N_AGENT, dtype=int) # 感染状態 1=感染 10 11# 最初の感染者 12np.random.seed(110) 13init_idx = np.random.randint(N_AGENT) 14infecteds_cur[init_idx] = 1 15 16for step in range(1800): 17 infecteds_next = infecteds_cur.copy() 18 19 # とりあえず人の位置をランダムに更新 20 positions = np.random.uniform(0,FIELD_SIZE, [N_AGENT,2]) 21 tree = spatial.KDTree(positions) 22 23 # 感染者 24 infected_idxs = np.where(infecteds_cur == 1)[0] 25 for infected_i in infected_idxs: 26 27 # 近辺の人を取得 28 neighbours = np.array(tree.query_ball_point(positions[infected_i], INFECT_DIST)) 29 neighbours = neighbours[neighbours != infected_i] # 自分は除く 30 31 for n_i in neighbours: 32 # 未感染→感染 33 if infecteds_cur[n_i] == 0 and np.random.uniform(0,1) < INFECT_RATE: 34 infecteds_next[n_i] = 1 35 36 infecteds_cur = infecteds_next # 次の状態へ 37 infected_cnt = len(infecteds_cur[infecteds_cur == 1]) 38 39 print(step, infected_cnt) 40 41 # 人は治らず入れ替わらないので打ち切り 42 if infected_cnt >= N_AGENT: 43 break

投稿2022/01/06 09:13

can110

総合スコア38341

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

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

0

階乗ではなく2乗ですね。
色々と問題は見受けられますがそれはさておき、
ループ回数を減らす手段としては、以下が思いつきます。
・座標を100m×100mのマス目に区切り、まず全ノードをマスに割り振る
・2×2の4マスごとに、それらのマスにあるノードの間で処理をする
・1マスづつずらして繰り返す
座標の範囲が狭ければ単純に配列にすればよく、範囲が広ければ疎行列的な扱いが必要になるでしょう。
連想配列として扱い、隣のマスを求めるのが面倒なので逆にノードごとに隣を含む4マスに割り振っておくのが楽かなと思います。

投稿2022/01/05 14:32

ikadzuchi

総合スコア3047

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

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

Dobutori

2022/01/06 07:02

座標範囲は縦25000m,横20000mのデータなので、この場合は疎行列の方がいいのでしょうか。
ikadzuchi

2022/01/10 07:45

250*200で50kマスですか。マスあたり(ポインタとして)8バイトとしても高々400kBなので密でじゅうぶん可能だと思います。 ただ改めて考えてみると、密か疎かというのはC言語などでメモリ上のデータ配置を考えるような場合についての話で、Pythonのようなメモリアドレスを直接扱わない言語ですとそもそも考える必要は無かったかもしれません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問