ここでは、単純なPythonを使用して、必要な比較回数を減らすことができる、非常に簡単な手法です。
まずX、Y、または(以下のコードでaxis
によって選択された)Z軸のいずれかに沿って点を並べ替えます。 X軸を選択するとしましょう。あなたのコードのようにポイントペアをループしますが、距離がmasking_radius
より大きいペアが見つかった場合は、そのX座標の差がmasking_radius
より大きいかどうかをテストします。そうであれば、より大きなj
のすべてのポイントがより大きなX座標を持つため、内部のj
ループから脱出することができます。
私のdist2
関数は、自乗距離を計算します。これは、平方根の計算が比較的遅いため、実際の距離を計算するよりも高速です。
私はまた、すなわち、それはスピードの比較のために、ポイントのすべてのペアをテストし、あなたのコードに似た振る舞いコードが含まれていました。高速コードが正しいことをチェックする役割も果たします。;)do_fast = 0
もちろん
13295 pairs
とdo_fast = 1
181937/499500 tests
13295 pairs
出力と
from random import seed, uniform
from operator import itemgetter
seed(42)
# Make some fake data
def make_point(hi=10.0):
return [uniform(-hi, hi) for _ in range(3)]
psize = 1000
points = [make_point() for _ in range(psize)]
masking_radius = 4.0
masking_radius2 = masking_radius ** 2
def dist2(p, q):
return (p[0] - q[0])**2 + (p[1] - q[1])**2 + (p[2] - q[2])**2
pair_count = 0
test_count = 0
do_fast = 1
if do_fast:
# Sort the points on one axis
axis = 0
points.sort(key=itemgetter(axis))
# Fast
for i, p in enumerate(points):
left, right = i - 1, i + 1
for j in range(i + 1, psize):
test_count += 1
q = points[j]
if dist2(p, q) < masking_radius2:
#interaction_pairs.append((i, j))
pair_count += 1
elif q[axis] - p[axis] >= masking_radius:
break
if i % 100 == 0:
print('\r {:3} '.format(i), flush=True, end='')
total_pairs = psize * (psize - 1) // 2
print('\r {}/{} tests'.format(test_count, total_pairs))
else:
# Slow
for i, p in enumerate(points):
for j in range(i+1, psize):
q = points[j]
if dist2(p, q) < masking_radius2:
#interaction_pairs.append((i, j))
pair_count += 1
if i % 100 == 0:
print('\r {:3} '.format(i), flush=True, end='')
print('\n', pair_count, 'pairs')
出力を、点対のほとんどが、互いにmasking_radius
内にある場合この技術を使用することで多くのメリットはありませんイケ。ポイントの並べ替えに時間がかかりますが、PythonのTimSortは効率的です(特にデータが部分的にソートされている場合)。masking_radius
が十分小さい場合は速度が大幅に向上するはずです。
ポイントは2次元または3次元ですか? 2の場合は、Cormenらの「Introduction to Algorithms *」で与えられた「最も近い点のペアを見つける」アルゴリズムの変種を試すことができます。 –
あなたのアルゴリズムは時間複雑さ 'O(n ** 2)'を持っていますが、Cormen'sは 'O(n * log(n))'を持っています。 Pythonコードの速度を上げる[pypy](http://pypy.org/)を試すこともできます。 –