ゴールデンスパイラル法
ゴールデンスパイラルメソッドを機能させることができなかったと言っていましたが、それは本当に良いので残念です。これを完全に理解して、これが「束ねられない」ようにする方法を理解できるようにしたいと思います。
これが、ほぼ正しいラティスを作成するための高速でランダムでない方法です。上で説明したように、完全な格子はありませんが、これで十分な場合があります。BendWavy.orgなどの他の方法と比較されますが、見栄えが良く、制限内の均等な間隔が保証されています。
プライマー:ユニットディスク上のヒマワリスパイラル
このアルゴリズムを理解するために、まず2Dヒマワリスパイラルアルゴリズムを紹介します。これは、最も不合理な数が黄金比で(1 + sqrt(5))/2
あり、「中心に立って、全回転の黄金比を回し、次にその方向に別の点を放出する」というアプローチでポイントを放出する場合、自然にスパイラルは、ポイントの数が増えるにつれて、ポイントが並ぶ明確な「バー」を持つことを拒否します。(注1.)
ディスク上の等間隔のアルゴリズムは、
from numpy import pi, cos, sin, sqrt, arange
import matplotlib.pyplot as pp
num_pts = 100
indices = arange(0, num_pts, dtype=float) + 0.5
r = sqrt(indices/num_pts)
theta = pi * (1 + 5**0.5) * indices
pp.scatter(r*cos(theta), r*sin(theta))
pp.show()
そして、次のような結果を生成します(n = 100およびn = 1000):
ポイントを放射状に配置する
重要な奇妙なことは式r = sqrt(indices / num_pts)
です。どうやって私はそれに来たのですか?(注2)
さて、ここでは平方根を使用しています。これは、ディスクの周りに等間隔のスペースを持たせるためです。すなわち、大型の限界にという同様であるN I少し領域たいR ∈(R、R + D R)、Θ ∈(θ、θ + D θ、その面積に比例する点の数を格納する)をこれは、Rの D のR dはθ。私たちはここに確率変数について話していることをふり今ならば、これは言うほど簡単な解釈を持っている(のための結合確率密度R、 Θ)がcr定数cの場合 = 1 /πを。。ユニットディスクの正規化は、cを強制します。
では、トリックを紹介しましょう。それはそれはとして知られている確率論から来て逆CDFをサンプリングし、あなたがしたいとします発生確率密度を持つ確率変数F(Zを)、あなたはランダム変数持つUの出てくるだけのように〜制服(0、1)random()
ほとんどのプログラミング言語で。これどうやってやるの?
- 最初に、密度を累積分布関数またはCDF に変換します。これをF(z)と呼びます。CDFは、導関数f(z)を使用して0から1に単調に増加します。
- 次に、CDFの逆関数F -1(z)を計算します。
- Z = F -1(U)がターゲット密度に従って分布していることがわかります。(注3)。
ここで、黄金比のスパイラルトリックでポイントをθのパターンにうまく均等に配置します。それを統合してみましょう。ユニットディスクの場合、F(r)= r 2になります。したがって、逆関数はF -1(u)= u 1/2であるため、極座標でディスク上にランダムな点を生成します。r = sqrt(random()); theta = 2 * pi * random()
ます。
この逆関数をランダムにサンプリングする代わりに、均一にサンプリングします。均一なサンプリングの良い点は、大きなNの制限内でポイントがどのように広がるかについての結果は、ランダムにサンプリングしたかのように動作することです。この組み合わせがトリックです。の代わりにrandom()
を使用します(arange(0, num_pts, dtype=float) + 0.5)/num_pts
。たとえば、10ポイントをサンプリングする場合はですr = 0.05, 0.15, 0.25, ... 0.95
。面積を均等にするためにrを均一にサンプリングし、ひまわりの増分を使用して、出力内のポイントのひどい「バー」を回避します。
ひまわりを球に乗せて
球に点を付けるために必要な変更は、球座標の極座標を切り替えるだけです。もちろん、単位球上にあるため、放射座標はこれに入りません。ここで、0≤私は物理学者としての訓練を受けたにもかかわらず、私は数学の座標を使用します、もう少し一貫ここで物事を保つためにφ ≤πは極から下って来るの緯度であり、0≤ θ ≤2πは経度です。上記との違いは、基本的に変数rをφに置き換えることです。
だった私たちの面積要素、R dはRの Dのθは、今ではあまりない-より-複雑罪(となりφ)D φ D θ。したがって、等間隔の結合密度はsin(φ)/4πです。θを積分すると、f(φ)= sin(φ)/ 2となるため、F(φ)=(1 − cos(φ))/ 2となります。我々は一様確率変数がACOSように見えるであろうことを確認でき、これを反転(1 - 2 Uに)、我々は代わりに使用するので、我々は、ランダムに一様にサンプリングする代わりにφ K 2( - = ACOS(1 kは+ 0.5)/N)。そして、残りのアルゴリズムは、これをx、y、z座標に投影するだけです。
from numpy import pi, cos, sin, arccos, arange
import mpl_toolkits.mplot3d
import matplotlib.pyplot as pp
num_pts = 1000
indices = arange(0, num_pts, dtype=float) + 0.5
phi = arccos(1 - 2*indices/num_pts)
theta = pi * (1 + 5**0.5) * indices
x, y, z = cos(theta) * sin(phi), sin(theta) * sin(phi), cos(phi);
pp.figure().add_subplot(111, projection='3d').scatter(x, y, z);
pp.show()
再びn = 100とn = 1000の場合、結果は次のようになります。
さらなる研究
マーティンロバーツのブログに一言お願いしたいと思いました。上記では、各インデックスに0.5を追加して、インデックスのオフセットを作成したことに注意してください。これは視覚的に魅力的でしたが、オフセットの選択は非常に重要であり、間隔全体で一定ではなく、正しく選択した場合、パッキングの精度が8%向上する可能性があることがわかりました。彼のR 2シーケンスで球をカバーする方法もあるはずです。これにより、おそらく、現状のままでも、たとえば、単位正方形は斜めにカットして、周りに伸ばして円にします。
ノート
これらの「バー」は数に合理的な近似によって形成され、その数に最も合理的な近似は、その継続的な分数式、から来ている整数で、有限または正の整数の無限の配列のいずれかであります:z + 1/(n_1 + 1/(n_2 + 1/(n_3 + ...)))
z
n_1, n_2, n_3, ...
def continued_fraction(r):
while r != 0:
n = floor(r)
yield n
r = 1/(r - n)
小数部1/(...)
は常に0と1の間にあるため、継続する小数部の大きな整数は、特に適切な合理的な近似を可能にします。したがって、最も不合理な数は、1 + 1/(1 + 1/(1 + ...))
特に適切な有理近似がないものです。黄金比の式を得るためにφを掛けてφ = 1 + 1 / φを解くことができます。
NumPyにあまり詳しくない人のために-すべての関数は「ベクトル化」されているため、sqrt(array)
他の言語で記述されるものと同じmap(sqrt, array)
です。したがって、これはコンポーネントごとのsqrt
アプリケーションです。スカラによる除算またはスカラによる加算についても同様です。これらはすべてのコンポーネントに並列に適用されます。
これが結果であることがわかったら、証明は簡単です。あなたは可能性があること何尋ねればZ < Z < Z + dはZ、これは確率何尋ねると同じであるZ < F -1(U)< Z + dはzは、適用Fを、それがあることを指摘し、すべての3つの式には、単調増加する関数、したがってF(z)< U < F(z + d z)、右側を展開してF(z)+ f(z)d z、そしてUは均一なので、この確率は約束どおりf(z)d zです。