ライン検索アルゴリズムを高速化する別の方法は、各ラインの開始点を事前に計算してから、高価なロジックを適用してこれらの各ポイントからラインを計算することです。
高速ベクトル化されたコードで開始点を計算できるロジック(完全な行識別ロジックを提供していないため)については、限定的な見方をしました。
高速ベクトル化されたコードでそのようなことを実装できるようにするための最初のステップは、どのポイントが一列に並んでいるかを把握できるようにすることですが、上の直接のポイントはそうではありません。
import numpy
# using the array that was provided in the question
a = """0 x1 0 0 y1 0 z1
0 0 x2 0 y2 0 z2
0 0 x3 0 0 y3 z3
0 0 x4 0 0 y4 z4
0 x5 0 0 0 y5 z5
0 0 0 0 y6 0 0"""
array = numpy.array([int(v.strip()) if v.strip().isdigit() else i for i, v in enumerate(a.split(' '))]).reshape(6, 7)
次のような配列になります。
>>> print repr(array)
array([[ 0, 1, 0, 0, 4, 0, 6],
[ 0, 0 9, 0, 11, 0, 13],
[ 0, 0, 16, 0, 0, 19, 20],
[ 0, 0, 23, 0, 0, 26, 27],
[ 0, 29, 0, 0, 0, 33, 34],
[ 0, 0, 0, 0, 39, 0, 0]])
ここから、いくつかの厄介なローリングを行うことができます:
>>> print `numpy.roll(array, 1, axis=0)`
array([[ 0, 0, 0, 0, 39, 0, 0],
[ 0, 1, 0, 0, 4, 0, 6],
[ 0, 0, 9, 0, 11, 0, 13],
[ 0, 0, 16, 0, 0, 19, 20],
[ 0, 0, 23, 0, 0, 26, 27],
[ 0, 29, 0, 0, 0, 33, 34]])
これを組み合わせて、線の垂直方向の始点を得ることができます。
>>> potential_start_points = (array != 0) & (numpy.roll(array, 1, axis=0) == 0)
>>> # include the top row points, as they are certainly start points
>>> potential_start_points[0, :] = (array != 0)[0, :]
>>> print `potential_start_points`
array([[False, True, False, False, True, False, True],
[False, False, True, False, False, False, False],
[False, False, False, False, False, True, False],
[False, False, False, False, False, False, False],
[False, True, False, False, False, False, False],
[False, False, False, False, True, False, False]], dtype=bool)
ここから、ベクトル化されたロジックを改良して対角線などを選択することができますが、各Trueを繰り返し処理して、より複雑なインデックスベースのロジックを適用したいと思います。
xs, ys = numpy.where(potential_start_points)
for x, y in zip(xs, ys):
# do more complex logic here ...
結局のところ、この場合の問題は、6x7=42の数値を反復することから7を超える反復に減少しました。