シェルピンスキーの三角形
概要
- シェルピンスキーの三角形は自己相似性を持つ三角形フラクタルで、カオスゲームの例としても知られる
具体的手順
-
- 正三角形を描く
-
- ランダムに点を三角形内部に配置する
-
- 各点について、三角形の頂点のいずれかをランダムに選び、その頂点と点の中点を新しい点として配置する
-
- このプロセスを繰り返すと点が収束し、シェルピンスキーの三角形が形成される
実装例
import matplotlib.pyplot as plt
import numpy as np
def generate_sierpinski(n_points=50000, burn_in=100):
# 1. 三角形の3頂点を定義 (正三角形)
vertices = np.array([
[0.0, 0.0],
[1.0, 0.0],
[0.5, np.sqrt(3)/2]
])
# 2. 点を格納する配列を用意
points = np.zeros((n_points, 2))
# 3. 初期点をランダムに決定 (どこでも収束しますが、便宜上0〜1の乱数で開始)
current_point = np.random.rand(2)
# 4. カオスゲームの反復処理
# burn_in + n_points 回ループし、最初のburn_in回は記録せずに捨てる
total_steps = n_points + burn_in
# ランダムな頂点のインデックスを一度に生成(高速化)
random_indices = np.random.randint(0, 3, total_steps)
for i in range(total_steps):
# 頂点を取得
target_vertex = vertices[random_indices[i]]
# 更新式: 現在地とターゲット頂点の中点へ移動
# p_next = (p_current + v_target) / 2
current_point = (current_point + target_vertex) / 2.0
# burn-in期間を過ぎたら配列に保存
if i >= burn_in:
points[i - burn_in] = current_point
return points
# --- 実行と描画 ---
# データ生成
data = generate_sierpinski(n_points=100000)
# プロット
plt.figure(figsize=(10, 10))
# s=0.1 で点を極小にすることで、フラクタルの繊細な構造を可視化
plt.scatter(data[:, 0], data[:, 1], s=0.01, c='darkblue', alpha=0.8)
plt.axis('equal') # アスペクト比を等しくして正三角形に見えるようにする
plt.axis('off') # 軸を非表示
plt.title("Sierpinski Triangle via Chaos Game")
plt.show()
四角形を描画する場合
- 頂点の選択に対して制約を加えることで、シェルピンスキーの四角形を描画可能
import matplotlib.pyplot as plt
import numpy as np
def generate_sierpinski_square(n_points=50000, burn_in=100):
# 1. 四角形の4頂点を定義 (正方形: 反時計回り)
# 0:(0,0), 1:(1,0), 2:(1,1), 3:(0,1)
# 対角関係は (0,2) と (1,3) になります
vertices = np.array([
[0.0, 0.0],
[1.0, 0.0],
[1.0, 1.0],
[0.0, 1.0]
])
points = np.zeros((n_points, 2))
current_point = np.random.rand(2)
# 直前の頂点インデックスを保持する変数 (-1は初回用)
last_vertex_idx = -1
# 4. カオスゲームの反復処理 (制約付き)
# ※制約チェックのため、ループ内で乱数を生成します
total_steps = n_points + burn_in
for i in range(total_steps):
while True:
# 0~3のランダムなインデックスを生成
idx = np.random.randint(0, 4)
# 【制約】: 直前に選んだ頂点の「対角」にある頂点は選ばない
# 頂点は0,1,2,3と並んでいるため、対角は (last + 2) % 4 で判定可能
if last_vertex_idx != -1:
opposite_idx = (last_vertex_idx + 2) % 4
if idx == opposite_idx:
continue # 対角なら再抽選
# 制約をクリアしたら採用
break
# 頂点を更新
target_vertex = vertices[idx]
current_point = (current_point + target_vertex) / 2.0
# 採用した頂点インデックスを記録
last_vertex_idx = idx
if i >= burn_in:
points[i - burn_in] = current_point
return points
# --- 実行と描画 ---
data = generate_sierpinski_square(n_points=100000)
plt.figure(figsize=(10, 10))
plt.scatter(data[:, 0], data[:, 1], s=0.05, c='darkblue', alpha=0.8)
plt.axis('equal')
plt.axis('off')
plt.title("Fractal Square (Restricted Chaos Game: No Opposite Vertex)")
plt.show()
実用例
- DNAやタンパク質の配列解析などで、N角形を作成して視覚化すると、特定のパターンや繰り返し構造を発見しやすくなることがある
- これはカオスゲームが初期値依存性が低く、安定したフラクタルパターンを生成するため、データの特徴を捉えやすいから
- 例えば、DNA配列の各塩基(A, T, C, G)を四角形の頂点に対応させ、カオスゲームを用いて配列全体を視覚化することで、特定の遺伝子領域や繰り返し配列が明確に浮かび上がることがある