バーンズリーのシダ(Barnsley's fern)

バーンズリーのシダ(Barnsley's fern)

バーンズリーのシダ(Barnsley’s fern)は、確率的な方法で生成されるフラクタル構造の一種であり、数学的な美しさと興味深さで知られています。

このシダは、数学者であるMichael Barnsleyによって導入されました。


バーンズリーのシダは、次のような確率的な方法で生成されます。

まず、初期条件として $(0, 0) $の点を選びます。

その後、一連の確率的な変換を適用して新しい点を生成します。

これらの変換は、特定の確率で選択され、シダの形を生成します。

バーンズリーのシダの生成には、以下のような変換が使用されます:

  1. $1%$の確率で、点$ (x, y) $は$ (0, 0.16y) $に変換されます。
    これにより、葉の部分が生成されます。

  2. $85%$の確率で、点$ (x, y) $は$ (0.85x + 0.04y, -0.04x + 0.85y + 1.6) $に変換されます。
    これにより、が生成されます。

  3. $7%$の確率で、点$ (x, y) $は$ (0.20x - 0.26y, 0.23x + 0.22y + 1.6) $に変換されます。
    これにより、さらに複雑な枝が生成されます。

  4. $7%$の確率で、点$ (x, y) $は$ (-0.15x + 0.28y, 0.26x + 0.24y + 0.44) $に変換されます。
    これにより、より細かい枝が生成されます。

これらの変換を多数回繰り返すことで、バーンズリーのシダの構造が形成されます。

このフラクタル構造は、自然界に見られるシダの葉や枝の形状に類似しており、その美しさと複雑さから数学的な芸術の一形態として広く愛されています。

プログラム例

以下は、NetworkXを使用してバーンズリーのシダを生成し、グラフで表現するサンプルコードです。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import random
import networkx as nx
import matplotlib.pyplot as plt

# バーンズリーのシダ生成関数
def barnsley_fern(n):
# 初期条件
x, y = 0, 0
points = [(x, y)]

# バーンズリーのシダ生成
for _ in range(n):
r = random.random()
if r <= 0.01:
x, y = 0, 0.16 * y
elif r <= 0.86:
x, y = 0.85 * x + 0.04 * y, -0.04 * x + 0.85 * y + 1.6
elif r <= 0.93:
x, y = 0.20 * x - 0.26 * y, 0.23 * x + 0.22 * y + 1.6
else:
x, y = -0.15 * x + 0.28 * y, 0.26 * x + 0.24 * y + 0.44
points.append((x, y))

return points

# バーンズリーのシダを生成
fern_points = barnsley_fern(10000)

# グラフの作成
G = nx.Graph()

# ノードの追加
for i, (x, y) in enumerate(fern_points):
G.add_node(i, pos=(x, y))

# エッジの追加
for i in range(len(fern_points) - 1):
G.add_edge(i, i+1)

# グラフの描画
pos = nx.get_node_attributes(G, 'pos')
nx.draw(G, pos, node_size=0, edge_color='green', alpha=0.5, linewidths=0.5)
plt.title("Barnsley Fern using NetworkX")
plt.show()

このコードでは、バーンズリーのシダを生成するための関数 barnsley_fern を定義し、その結果をNetworkXのグラフに変換して描画しています。

生成されたグラフは、バーンズリーのシダの形を模倣した美しい構造を持っています。

[実行結果]

ソースコード解説

このソースコードは、Pythonを使用してバーンズリーのシダ(Barnsley’s fern)を生成し、NetworkXを使用してそのグラフを描画するものです。

以下では、コードの構造と各部分の役割について詳しく説明します。

1. バーンズリーのシダ生成関数の定義

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def barnsley_fern(n):
x, y = 0, 0 # 初期条件
points = [(x, y)] # 座標を格納するリスト

# バーンズリーのシダ生成
for _ in range(n):
r = random.random() # 0から1の乱数を生成
if r <= 0.01:
x, y = 0, 0.16 * y
elif r <= 0.86:
x, y = 0.85 * x + 0.04 * y, -0.04 * x + 0.85 * y + 1.6
elif r <= 0.93:
x, y = 0.20 * x - 0.26 * y, 0.23 * x + 0.22 * y + 1.6
else:
x, y = -0.15 * x + 0.28 * y, 0.26 * x + 0.24 * y + 0.44
points.append((x, y)) # 新しい座標をリストに追加

return points

この部分では、バーンズリーのシダを生成する関数 barnsley_fern が定義されています。

この関数は、生成する点の数 n を引数として受け取ります。

バーンズリーのシダは、一連の確率的な変換を繰り返すことで生成されます。

各ステップで、ランダムに選択された変換に基づいて新しい座標が計算され、リスト points に追加されます。

2. バーンズリーのシダを生成

1
fern_points = barnsley_fern(10000)

この行では、barnsley_fern 関数を呼び出して、$10000$個の点からなるバーンズリーのシダを生成し、fern_points に格納しています。

3. グラフの作成

1
G = nx.Graph()

この行では、NetworkXのグラフオブジェクト G を作成しています。

4. ノードの追加

1
2
for i, (x, y) in enumerate(fern_points):
G.add_node(i, pos=(x, y))

この部分では、バーンズリーのシダで生成された点をグラフのノードとして追加しています。

各ノードには、座標を属性として持つことができます。

ここでは、各ノードに座標情報を pos という名前の属性として追加しています。

5. エッジの追加

1
2
for i in range(len(fern_points) - 1):
G.add_edge(i, i+1)

この部分では、連続する点の間にエッジを追加しています。

これにより、シダの枝の構造が表現されます。

6. グラフの描画

1
2
3
4
pos = nx.get_node_attributes(G, 'pos')
nx.draw(G, pos, node_size=0, edge_color='green', alpha=0.5, linewidths=0.5)
plt.title("Barnsley Fern using NetworkX")
plt.show()

最後に、NetworkXdraw 関数を使用してグラフを描画しています。

ノードの座標pos から取得し、それに基づいてノードエッジが描画されます。

結果として得られるグラフは、バーンズリーのシダの形状を美しく表現しています。