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

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

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

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

1190閲覧

Python3で座標(x,y)がリスト形式で与えられたとき、2点間の距離で最長のものを求めたい。

Sakana4432

総合スコア4

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

3クリップ

投稿2022/08/22 13:31

リスト形式でN個の座標[x,y]が与えられたとき、すべての2点間の距離の中で最長になるユークリッド距離を求めるため、以下のプログラムを書いてみました。

出力は最長距離の2乗になっています。

このプログラムではnumpyをつかって求めていますが、他に計算時間を短縮できるような良いプログラムがあればご教授いただけないでしょうか。

よろしくお願い致します。

<制約>
座標x,yは、-10 ** 5<=x,y<=10 ** 5 の範囲
与えられる座標の数 N は, 1<=N<=2*10**5 の範囲

Python3

1import numpy as np 2 3N = int(input()) 4nodes = np.array([list(map(int,input().split())) for _ in range(N)]) 5 6longest = 0 7 8nodes_diff = np.expand_dims(nodes,axis=0) - np.expand_dims(nodes,axis=1) 9nodes_diff = np.reshape(nodes_diff,(-1,2)) 10for a,b in nodes_diff: 11 distance = a**2 + b**2 12 if dist > longest: 13 longest = distance 14 15print(longest) 16

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

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

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

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

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

guest

回答2

0

ベストアンサー

詳細未検証ですがMax Distance between 2 points in a data set and identifying the pointsの回答を参照の上、利用できるか検討ください。
上記の回答では3D座標が対象ですが、2Dでも同様にできるかと思います。

追記

検証してみました。
求めたい2点は、その性質上、対象となる点群の凸包を構成する点のはずです。
そこでscipy.spatialで凸包の点群=距離を計算すべき点を抽出します。
これらの数は元の数よりも大幅に少ないので計算量をかなり減らせ、提示の条件でも一瞬で求まりました。
参考:PythonでConvex-Hull(凸包)を用いたバウンディングボックスを求める

Python

1import numpy as np 2from scipy.spatial import ConvexHull 3from scipy.spatial.distance import cdist 4 5# テストデータ 6np.random.seed(110) 7N = 2*10**5 8points = np.random.rand(N, 2) 9points = points * (2*10**5) - 10**5 10print(points.shape) # (200000, 2) 11 12# Convex-Hull(凸包)を構成する点群を抽出する 13hull = ConvexHull(points) 14hullpoints = points[hull.vertices,:] 15print(hullpoints.shape) # (26, 2) 16 17# 上記の点群の各距離を求める 18hdist = cdist(hullpoints, hullpoints, metric='euclidean') 19print(hdist.shape) # (26, 26) 20 21# 最大距離をとる2点の位置を得る 22bestpair = np.unravel_index(hdist.argmax(), hdist.shape) 23print(bestpair) # (6, 17) 24 25# 点の位置 26best_points = np.array([hullpoints[bestpair[0]], hullpoints[bestpair[1]]]) 27print( best_points) 28#[[-99966.6622684 99769.28800939] 29# [ 99704.49893665 -99985.9459651 ]] 30 31# 最大距離 32best_dist = cdist(best_points, best_points, metric='euclidean') 33print(best_dist[0][1]) # 282437.11887281504

投稿2022/08/22 13:59

編集2022/08/23 00:47
can110

総合スコア38260

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

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

Sakana4432

2022/08/23 01:58

回答ありがとうございます。 凸包について無知だったので調べてみると、面白いものですね。 勉強になりました。
guest

0

計算時間を短縮できるかは未確認ですが、
Pythonでxy座標上の2点間の距離をforループを使わずに計算する方法
の「degree_distance」の最大値を計算すれば求まると思います

出力は最長距離の2乗

でよければnp.sqrt()は要らなくなります

 
ただし、

与えられる座標の数 N は,1<=N<=2*10**5 の範囲

の最大の場合は、「degree_distance」の要素数は
(2*10**5)**2=40000000000個
になり、必要なメモリー量は(もちろん変数の型によりますが)かなり大きくなります

さらに、「all_diffs」の要素数は「degree_distance」より多いし、計算過程で要素数がそれらと同じくらいの配列が一時的に作られると思うので、トータルで必要なメモリー量は相当なものになると思います

なので、この方法は座標数が多い場合はコンピュータの実メモリー量が多くないと計算できません
多少メモリーが足りなくても仮想記憶で計算できるかもしれませんが、その場合は計算が遅くなります

投稿2022/08/22 23:40

編集2022/08/22 23:44
jbpb0

総合スコア7651

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問