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

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

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

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Python

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

Q&A

解決済

3回答

1380閲覧

階乗ループの回数を減らす方法を教えて下さい。

Dobutori

総合スコア2

for

for文は、様々なプログラミング言語で使われている制御構造です。for文に定義している条件から外れるまで、for文内の命令文を繰り返し実行します。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

Python

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

1グッド

2クリップ

投稿2021/12/08 08:15

編集2021/12/08 08:27

前提・質問

複雑ネットワークの無向辺グラフで、ノードの位置が100m以内の時、ノードとノードをエッジ(枝)で繋げるプログラムを書いています。ノードの数は7000個あり、それぞれに座標(x,y)が与えられています。
リストの中身はnode_list((id,x,y))で、ループを回して、x,yの差が100m以内のノード同士を探しています。
1つのノードに対して、すべてのノードでx,yの差を求めているため、ループの回数が7000の階乗回回しています。
ループの回数を減らすためにはどうしたらいいでしょうか?

発生している問題

7000!回ループなので、処理が重くて計算ができないです。

該当のソースコード

for i in range(len(node_list)):
for j in range(len(node_list) - i):

x_difference = node_list[i][1] - node_list[j][1]
y_difference = node_list[i][2] - node_list[j][2]

if abs(x_difference) < 100 and abs(y_difference) < 100:

if node_list[i][0] != node_list[j][0]:

if (node_list[i][0], node_list[j][0]) not in edge_list and (
node_list[j][0], node_list[i][0]) not in edge_list:

node_edge_list.append((node_list[i][0], node_list[j][0]))
edge_list.append((node_list[i][0], node_list[j][0]))
edge_list.append((node_list[j][0], node_list[i][0]))

python3
takotakot👍を押しています

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

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

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

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

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

yambejp

2021/12/08 08:23

pythonであればタグ付けしてください
guest

回答3

0

こんばんわ。

付け足しになりますが、2点間の距離を求めるには以下のとおりにします。

点P(x1,y1)と点Q(x2,y2)との距離Dを求める式について D = sqrt( (x1 - x2)^2 + (y1 - y2)^2 )

投稿2021/12/08 09:17

srsnsts

総合スコア508

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

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

Dobutori

2021/12/08 17:10

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

0

ベストアンサー

インデントが崩れているのでよく分かりませんが、forループが二重になっているだけなので、7000 * 7000 / 2 → 約25M回の処理のように見えます。
遅い原因が本当にループ回数なのか確認した方が良いと思います。

たとえば、貼ってもらったコードでは node_edge_listedge_list にappendしているのでリストを使用していると思います。これだと、リストのサイズが大きくなると in で確認するのに時間がかかるようになります。これを以下のようにセット型にするだけで速度が改善されたりしませんか?

また、node_listの内容によっては node_edge_listedge_list がメモリを大量に消費するので、~16GBのマシンだとメモリが不足するかもしれません。

マシンにもよりますが、以下のコードで私の環境だと1分以内に処理が完了します。

python

1from random import randint 2 3size = 7000 4node_list = [[i, randint(0, 100), randint(0, 100)] for i in range(size)] 5node_edge_list = set() 6edge_list = set() 7 8for i in range(len(node_list)): 9 print(i) 10 for j in range(len(node_list) - i): 11 x_difference = node_list[i][1] - node_list[j][1] 12 y_difference = node_list[i][2] - node_list[j][2] 13 14 if abs(x_difference) < 100 and abs(y_difference) < 100: 15 if node_list[i][0] != node_list[j][0]: 16 if (node_list[i][0], node_list[j][0]) not in edge_list and ( 17 node_list[j][0], node_list[i][0]) not in edge_list: 18 node_edge_list.add((node_list[i][0], node_list[j][0])) 19 edge_list.add((node_list[i][0], node_list[j][0])) 20 edge_list.add((node_list[j][0], node_list[i][0]))

投稿2021/12/08 09:09

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

Dobutori

2021/12/08 17:11

プログラムの処理時間が11秒程度まで減らすことができました!ありがとうございました!
guest

0

今のコードでも階乗回のループにはなってません。
データの内容にもよりますが、現状で一番時間がかかってるコードはおそらく

Python

1if (node_list[i][0], node_list[j][0]) not in edge_list and ( 2node_list[j][0], node_list[i][0]) not in edge_list:

同じ辺を追加しないようにチェックしてるここです。edge_listをsetにすれば、計算できないというレベルの時間はかからないでしょう。

投稿2021/12/08 09:08

yudedako67

総合スコア2047

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

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

Dobutori

2021/12/08 17:11

setにすることで大幅に時間を短縮することができました!ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問