Fraktaalsed atraktorid ja Minkowski-Bouligandi dimensioon

Varasemas loengus uurisime, kuidas saab fraktaali dimensiooni defineerida, ja jõudsime sarnasusdimensiooni definitsioonini. See tööleht räägib alternatiivsest mõistest, mida nimetatakse Minkowski-Bouligandi dimensiooniks, ja näitab kuidas definitsiooni saab rakendada atraktoritele. Sarnane mõiste, mis tihti langeb kokku Minkowski-Bouligandi dimensiooniga, on Hausdorff-Besikovitši dimensioon.

In [1]:
%matplotlib inline

import matplotlib.pyplot as plt
import numpy as np
import numpy.random as rnd

Minkowski-Bouligandi dimensioon

Minkowski-Bouligandi dimensioon, või kastilugemise dimensioon, on veel üks võimalus, kuidas saab fraktaali dimensiooni defineerida. Selleks jagatakse faasiruumi $Q = \mathbb{R}^m$ ühtlaselt kastideks

$$Q^{\epsilon}_{i_1 \cdots i_m} = \left[\epsilon\left(i_1 - \frac{1}{2}\right), \epsilon\left(i_1 + \frac{1}{2}\right)\right) \times \ldots \times \left[\epsilon\left(i_m - \frac{1}{2}\right), \epsilon\left(i_m + \frac{1}{2}\right)\right).$$

Me nüüd uurime hulka $S \subset Q$. Olgu $N(\epsilon)$ nende suurusega $\epsilon$ kastide $Q^{\epsilon}_{i_1 \cdots i_m}$ arv, mille puhul kehtib $S \cap Q^{\epsilon}_{i_1 \cdots i_m} \neq \emptyset$, ehk hulga maht

$$N(\epsilon) = \#\left\{(i_1, \ldots, i_m) \in \mathbb{Z}^m, S \cap Q^{\epsilon}_{i_1 \cdots i_m} \neq \emptyset\right\}.$$

Piiril $\epsilon \to 0$ leiame, et kastide arv käitub kui $N(\epsilon) \approx C\epsilon^{-d}$, kus $C$ on konstantne $d$ on Minkowski-Bouligandi dimensioon. Logaritimi abil leiame

$$\ln N(\epsilon) \approx \ln C - d\ln\epsilon.$$

Sellest järeldub

$$d = -\lim_{\epsilon \to 0}\frac{\ln N(\epsilon) - \ln C}{\ln\epsilon} = -\lim_{\epsilon \to 0}\frac{\ln N(\epsilon)}{\ln\epsilon}.$$

Praktikas on tihti kasulikum, Minkowski-Bouligandi dimensioon teisel viisil arvutada. Tavaliselt teame, et hulk $S$ on risttahuka $R$ alamhulk, $S \subset R \subset Q$. Seega piisab sellest, et me jagame hulka $R$ kastideks, niiet kastide koguarv on lõplik. Kastide suuruseks kasutame $\epsilon = 2^{-p}$, millest järeldub $\ln\epsilon = -p\ln 2$. Seega kehtib

$$\ln N(2^{-p}) \approx \ln C + dp\ln 2.$$

Funktsioon

$$p \mapsto \frac{\ln N(2^{-p})}{\ln 2} = \log_2N(2^{-p})$$

seega käitub asümptootiliselt nagu lineaarne funktsioon, mille kasv on $d$, ja me võime defineerida

$$d = \lim_{p \to \infty}\frac{d}{dp}\log_2N(2^{-p}).$$

Piiril $p \to \infty$ ilmub aga praktiline probleem, et tihti teame ainult lõpliku arvu punkte $x_n \in S$, näiteks kui $S$ on diskreetse dünaamika atraktor, ja $(x_n)$ on trajektoor, mis koondub atraktorile, ja millest meil on lõplik osa $x_0, \ldots, x_{n_0 - 1}$ arvutatud. Kui me aga eeldame, et $S \approx S_{n_0} = \{x_n, n < n_0\}$, siis kehtib

$$N_{n_0}(\epsilon) = \#\left\{(i_1, \ldots, i_m) \in \mathbb{Z}^m, S \cap Q^{\epsilon}_{i_1 \cdots i_m} \neq \emptyset\right\} = \#\left\{(i_1, \ldots, i_m) \in \mathbb{Z}^m, \exists n < n_0: x_n \in Q^{\epsilon}_{i_1 \cdots i_m} \neq \emptyset\right\} \leq n_0,$$

kuna kastide arv, milles asub vähemalt üks punkt $x_n$, ei saa olla suurem kui punktide arv $n_0$. Seega $N_{n_0}(\epsilon)$ ei saa kasvata üle selle piiri. Praktiliselt peame seega sellega leppima, et on mõistlik ülempiir $p$, mis on seda suurem, mida suurem on punktide arv $n_0$.

Alljärgnev algoritm aitab hinnata Minkowski-Bouligandi dimensiooni, kui hulk asub kahemõõtmelises faasiruumis. pts on punktide loetelu, xmin ja xmax on ristküliku alumine-vasakpoolne ja ülemine-parempoolne nurk ning pmax on parameetri $p$ maksimaalne väärtus. Algoritm joonistab $\frac{d}{dp}\log_2N(2^{-p})$ sõltuvalt parameetrist $p$. Kui joon on horitsontaalne, võrdub $\frac{d}{dp}\log_2N(2^{-p})$ umbes Minkowski-Bouligandi dimensiooniga.

In [2]:
def hbdim(pts, xmin, xmax, pmax):
    sets = [np.zeros((2 ** p, 2 ** p), dtype=np.int8) for p in range(pmax + 1)]

    Xmin = np.array(xmin)
    Xdiff = np.array(xmax) - Xmin
    
    for x in pts:
        y = (x - Xmin) / Xdiff
        for p in range(pmax + 1):
            sets[p][int(2 ** p * y[0]), int(2 ** p * y[1])] = 1

    visited = [s.sum() for s in sets]
    logs = np.log2(visited)
    ldiff = np.diff(logs)

    print(visited)
    print(logs)
    print(ldiff)
    
    plt.plot(logs)
    plt.show()
    
    plt.plot(ldiff)
    plt.show()

Henon atraktor

Esimene fraktaal, millele me Minkowski-Bouligandi algoritmi rakendame, on Henoni atraktor. See on diskreetse dünaamika atraktor faasiruumis $Q = \mathbb{R}^2$, mis on definieeritud kui

\begin{align} x_{n + 1} &= y_n - ax_n^2 + 1,\\ y_{n + 1} &= bx_n. \end{align}

Seega defineerime:

In [3]:
def henon(x, a, b):
    return [x[1] + 1 - a * x[0] ** 2, b * x[0]]

Konstantsed parameetrid on tavaliselt valitud $a = 1.4$ ja $b = 0.3$:

In [4]:
a = 1.4
b = 0.3

Atraktori joonistamiseks on lisaks ka algtingimust vaja. Algtingimuseks valime $(x_0, y_0) = (0, 0)$.

In [5]:
x = [0, 0]

Atraktori jooonistamiseks arvutame trajektoori. Trajektoori algust $(x_0, y_0), \ldots, (x_{n_1}, y_{n_1})$ me ei joonista, kuna siis trajektoor alles läheneb atraktorile, vaid joonistame ainult osa $(x_{n_1 + 1}, y_{n_1 + 1}), \ldots, (x_{n_2}, y_{n_2})$. Selleks valime $n_1$ ja $n_2$ järgnevalt:

In [6]:
npre = 100
nmax = 1000000

Lõpuks joonistame:

In [7]:
res = []

for _ in range(npre):
    x = henon(x, a, b)

for _ in range(nmax):
    x = henon(x, a, b)
    res.append(x)

val = np.array(res)

fig = plt.figure(figsize=(8, 6), dpi=96)
ax = fig.add_subplot(111)
ax.scatter(val[:, 0], val[:, 1], marker=".", s=1, lw=0)
plt.show()

Lisaks arvutame ka Minkowski-Bouligandi dimensiooni eelnevalt defineeritud algoritmi abil. Kõik punktid trajektoori peal asuvad hulgas $(-1.5, 1.5) \times (-0.5, 0.5) \subset \mathbb{R}^2$. Seega valime:

In [8]:
hbdim(val, [-1.5, -0.5], [1.5, 0.5], 16)
[1, 4, 12, 26, 61, 144, 352, 811, 1924, 4438, 10512, 25382, 58896, 137528, 280927, 488172, 686643]
[ 0.          2.          3.5849625   4.70043972  5.93073734  7.169925
  8.45943162  9.6635581  10.90989308 12.11569395 13.35974956 14.63151813
 15.84588203 17.06936585 18.09983576 18.89703002 19.38920068]
[2.         1.5849625  1.11547722 1.23029762 1.23918766 1.28950662
 1.20412649 1.24633498 1.20580087 1.24405561 1.27176857 1.2143639
 1.22348381 1.03046992 0.79719426 0.49217066]

Joonis näitab, et logaritmide kasv on enam-vähem tasane vahemikus $1.2 \ldots 1.3$. Sellest järeldub, et Minkowski-Bouligandi dimensioon asub selles vahemikus. Kirjanduses leidub väärtus $1.261 \pm 0.003$.

Itereeritud funktsioonisüsteemid

Järgmisena uurime fraktaalide klassi, mis ei ole determineeritud dünaamika, vaid juhusliku dünaamika atraktorid. Faasiruumis $Q$ on antud $m$ funktsiooni $f_1, \ldots, f_m: Q \to Q$. Igal sammul $x_n \to x_{n + 1}$ valitakse juhuslikult ühe. Seega tekib juhuslik trajektoor. Sellist süsteemi nimetatakse itereeritud funktsioonisüsteemiks.

Alljärgnev kood joonistab sellist süsteemi.

In [9]:
def ifsplot(ifs, x0, npre, nmax):
    ni = len(ifs)
    wgh = []
    for fkt in ifs:
        wgh.append(fkt[2])
    wgh = np.array(wgh) / sum(wgh)

    rnd.seed()
    x = x0
    res = []

    for _ in range(npre):
        r = rnd.choice(ni, p=wgh)
        x = np.dot(ifs[r][0], x) + ifs[r][1]

    for _ in range(nmax):
        r = rnd.choice(ni, p=wgh)
        x = np.dot(ifs[r][0], x) + ifs[r][1]
        res.append(x)

    val = np.array(res)

    fig = plt.figure(figsize=(6, 6), dpi=96)
    ax = fig.add_subplot(111)
    ax.set_aspect('equal')
    ax.scatter(val[:, 0], val[:, 1], marker=".", s=1, lw=0)
    plt.show()
    
    return val

Nagu ka eelmise näite puhul valime joonistamiseks ainult trajektoori osa, mis asub atraktori lähedal.

In [10]:
npre = 100
nmax = 1000000

Lisaks valime ka algtingimust. Kuna trajektoor jälgib atraktori kuju, ei sõltu trajektoori kvalitatiivne kuju algtingimuse valikust.

In [11]:
x0 = np.array([0.3, 0.7])

Süsteemides, mida me uurime, on funktsioonid $f_i$ affiinsed teisendused kahemõõtmelises ruumis,

$$f_i(\underline{x}) = \underline{\underline{M}} \cdot \underline{x} + \underline{v}.$$

Sierpinski kolmnurk

Esimene näide on Sierpinski kolmnurk, mida me juba varasemas loengus joonistasime. Nüüd konstrueerime seda intereeritud funktsioonisüsteemina. Selleks valime:

In [12]:
sierp3 = [
    (np.array([[1/2, 0], [0, 1/2]]), np.array([0, 1]), 1),
    (np.array([[1/2, 0], [0, 1/2]]), np.array([np.sqrt(3)/2, -1/2]), 1),
    (np.array([[1/2, 0], [0, 1/2]]), np.array([-np.sqrt(3)/2, -1/2]), 1)
]

Tulemus on tuttav kuju:

In [13]:
val = ifsplot(sierp3, x0, npre, nmax)

Lisaks arvutame ka Minkowski-Bouligandi dimensiooni:

In [14]:
hbdim(val, [-2.0, -1.0], [2.0, 2.1], 16)
[1, 4, 12, 40, 116, 342, 1046, 3164, 9493, 28035, 81503, 227095, 508912, 775899, 915650, 970660, 990035]
[ 0.          2.          3.5849625   5.32192809  6.857981    8.41785251
 10.03066714 11.62753388 13.21264837 14.77494145 16.31456554 17.79293642
 18.95705668 19.56550934 19.80443672 19.88860652 19.91712   ]
[2.         1.5849625  1.73696559 1.5360529  1.55987152 1.61281462
 1.59686675 1.58511448 1.56229308 1.53962409 1.47837087 1.16412027
 0.60845266 0.23892738 0.0841698  0.02851349]

Joonis näitab, et Minkowski-Bouligandi dimensioon on umbes $1.55 \ldots 1.6$. Tuletame meelde, et sarnasusdimensioon on $\frac{\ln 3}{\ln 2}$:

In [15]:
np.log(3) / np.log(2)
Out[15]:
1.5849625007211563

Sierpinski vaip / nelinurk

Samuti tuttav näide on Sierpinski vaip, mida me konstrueerime järgnevalt:

In [16]:
sierp4 = [
    (np.array([[1/3, 0], [0, 1/3]]), np.array([1, 1]), 1),
    (np.array([[1/3, 0], [0, 1/3]]), np.array([1, -1]), 1),
    (np.array([[1/3, 0], [0, 1/3]]), np.array([-1, 1]), 1),
    (np.array([[1/3, 0], [0, 1/3]]), np.array([-1, -1]), 1),
    (np.array([[1/3, 0], [0, 1/3]]), np.array([1, 0]), 1),
    (np.array([[1/3, 0], [0, 1/3]]), np.array([0, 1]), 1),
    (np.array([[1/3, 0], [0, 1/3]]), np.array([-1, 0]), 1),
    (np.array([[1/3, 0], [0, 1/3]]), np.array([0, -1]), 1)
]

Ka selle süsteemi kuju on juba tuttav:

In [17]:
val = ifsplot(sierp4, x0, npre, nmax)

Järgmisena arvutame Minkowski-Bouligandi dimensiooni:

In [18]:
hbdim(val, [-1.6, -1.6], [1.6, 1.6], 16)
[1, 4, 16, 60, 240, 768, 2816, 10912, 39592, 145391, 442085, 775490, 931296, 980898, 994875, 998691, 999650]
[ 0.          2.          4.          5.9068906   7.9068906   9.5849625
 11.45943162 13.41362793 15.27292133 17.14957844 18.75396426 19.56474865
 19.82888026 19.9037436  19.92415575 19.92967884 19.93106354]
[2.00000000e+00 2.00000000e+00 1.90689060e+00 2.00000000e+00
 1.67807191e+00 1.87446912e+00 1.95419631e+00 1.85929340e+00
 1.87665711e+00 1.60438582e+00 8.10784393e-01 2.64131604e-01
 7.48633416e-02 2.04121475e-02 5.52309881e-03 1.38469325e-03]

Tulemus näitab, et ta on umbes $1.85 \ldots 1.9$. Sarnasusdimensioon on $\frac{\ln 8}{\ln 3}$:

In [19]:
np.log(8) / np.log(3)
Out[19]:
1.892789260714372

Sierpinski kuusnurk - variant 1

Lisaks eelnevalt näidatud kujudele võib näiteks ka kuusnurka konstrueerida. Üks võimalus on selline:

In [20]:
sierp6a = [
    (np.array([[1/3, 0], [0, 1/3]]), np.array([1, 0]), 1),
    (np.array([[1/3, 0], [0, 1/3]]), np.array([-1, 0]), 1),
    (np.array([[1/3, 0], [0, 1/3]]), np.array([0.5, np.sqrt(3)/2]), 1),
    (np.array([[1/3, 0], [0, 1/3]]), np.array([0.5, -np.sqrt(3)/2]), 1),
    (np.array([[1/3, 0], [0, 1/3]]), np.array([-0.5, np.sqrt(3)/2]), 1),
    (np.array([[1/3, 0], [0, 1/3]]), np.array([-0.5, -np.sqrt(3)/2]), 1)
]

Joonisel on tõepoolest kuusnurga sümmeetria:

In [21]:
val = ifsplot(sierp6a, x0, npre, nmax)

Arvutame Minkowski-Bouligandi dimensiooni:

In [22]:
hbdim(val, [-1.6, -1.5], [1.6, 1.5], 16)
[1, 4, 16, 52, 144, 476, 1408, 4418, 13697, 41524, 120594, 325089, 631071, 850082, 948885, 982753, 994405]
[ 0.          2.          4.          5.70043972  7.169925    8.89481776
 10.45943162 12.1091777  13.74157232 15.3416578  16.8797986  18.31047521
 19.2674428  19.69724249 19.85587373 19.90646934 19.92347402]
[2.         2.         1.70043972 1.46948528 1.72489276 1.56461386
 1.64974608 1.63239462 1.60008548 1.5381408  1.43067661 0.95696759
 0.42979968 0.15863124 0.05059561 0.01700469]

Väärtus on seega umbes $1.6 \ldots 1.65$. Analüütiliselt leiame sarnasusdimensiooni $\frac{\ln 6}{\ln 3}$.

In [23]:
np.log(6) / np.log(3)
Out[23]:
1.6309297535714573

Sierpinski kuusnurk - variant 2

Teine võimalus kuidas kuusnurka konstrueerida on selline:

In [24]:
sierp6b = [
    (np.array([[0, np.sqrt(3/25)], [-np.sqrt(3/25), 0]]), np.array([1, 0]), 1),
    (np.array([[0, np.sqrt(3/25)], [-np.sqrt(3/25), 0]]), np.array([-1, 0]), 1),
    (np.array([[0, np.sqrt(3/25)], [-np.sqrt(3/25), 0]]), np.array([0.5, np.sqrt(3)/2]), 1),
    (np.array([[0, np.sqrt(3/25)], [-np.sqrt(3/25), 0]]), np.array([0.5, -np.sqrt(3)/2]), 1),
    (np.array([[0, np.sqrt(3/25)], [-np.sqrt(3/25), 0]]), np.array([-0.5, np.sqrt(3)/2]), 1),
    (np.array([[0, np.sqrt(3/25)], [-np.sqrt(3/25), 0]]), np.array([-0.5, -np.sqrt(3)/2]), 1)
]

Ka seekord leiame kuusnurga sümmeetriat:

In [25]:
val = ifsplot(sierp6b, x0, npre, nmax)

Arvutame Minkowski-Bouligandi dimensiooni:

In [26]:
hbdim(val, [-1.6, -1.5], [1.6, 1.5], 16)
[1, 4, 16, 48, 160, 524, 1688, 5280, 17018, 53136, 163139, 424171, 733263, 903314, 968405, 990297, 996959]
[ 0.          2.          4.          5.5849625   7.32192809  9.033423
 10.72109919 12.36632221 14.05477388 15.69740201 17.31574219 18.69428646
 19.48397122 19.78486804 19.885251   19.91750174 19.92717465]
[2.         2.         1.5849625  1.73696559 1.71149491 1.68767619
 1.64522303 1.68845166 1.64262813 1.61834018 1.37854428 0.78968475
 0.30089682 0.10038296 0.03225074 0.00967291]

Tulemus on umbes $1.65 \ldots 1.7$ ja seega natuke suurem kui eelmisel korral. Analüütiliselt leiame sarnasusdimensiooni $\frac{\ln 6}{\ln\frac{5}{\sqrt{3}}} = \frac{2\ln 6}{2\ln 5 - \ln 3}$.

In [27]:
2 * np.log(6) / (2 * np.log(5) - np.log(3))
Out[27]:
1.6901290227715968

Sõnajalg

Teistsugune näide väiksema sümmeetriaga on sõnajalg, mida me defineerime järgnevalt:

In [28]:
fern = [
    (np.array([[0, 0], [0, 0.16]]), np.array([0, 0]), 1),
    (np.array([[0.85, 0.04], [-0.04, 0.85]]), np.array([0, 1.6]), 85),
    (np.array([[0.2, -0.26], [0.23, 0.22]]), np.array([0, 1.6]), 7),
    (np.array([[-0.15, 0.28], [0.26, 0.24]]), np.array([0, 0.44]), 7)
]

Tulemus selgitab selle kuju nime:

In [29]:
val = ifsplot(fern, x0, npre, nmax)

Arvutame Minkowski-Bouligandi dimensiooni:

In [30]:
hbdim(val, [-3.0, -0.1], [3.0, 11.0], 16)
[1, 4, 13, 39, 130, 455, 1588, 5714, 20264, 69523, 196506, 399981, 611260, 770664, 869795, 926586, 959238]
[ 0.          2.          3.70043972  5.28540222  7.02236781  8.82972274
 10.6329952  12.48028532 14.30663136 16.08520272 17.58421384 18.60957194
 19.22142664 19.55574247 19.73031589 19.82156536 19.87152929]
[2.         1.70043972 1.5849625  1.73696559 1.80735492 1.80327246
 1.84729012 1.82634604 1.77857136 1.49901112 1.02535811 0.61185469
 0.33431584 0.17457342 0.09124947 0.04996393]

Binaarne puu

Veel üks lihtne võimalus on binaarne puu, mida me järgmisena uurime.

In [31]:
tree = [
    (np.array([[0, 0], [0, 0.5]]), np.array([0, 0]), 1),
    (np.array([[0.42, -0.42], [0.42, 0.42]]), np.array([0, 0.2]), 8),
    (np.array([[0.42, 0.42], [-0.42, 0.42]]), np.array([0, 0.2]), 8),
    (np.array([[0.1, 0], [0, 0.1]]), np.array([0, 0.2]), 3)
]

Tulemus on selline:

In [32]:
val = ifsplot(tree, x0, npre, nmax)

Arvutame Minkowski-Bouligandi dimensiooni:

In [33]:
hbdim(val, [-0.25, 0], [0.25, 0.45], 16)
[1, 4, 13, 37, 109, 300, 804, 2183, 5826, 15323, 38400, 87114, 168126, 283770, 417475, 558211, 685314]
[ 0.          2.          3.70043972  5.20945337  6.76818432  8.22881869
  9.65105169 11.09209641 12.50828999 13.90341116 15.22881869 16.41061697
 17.35918332 18.11436255 18.67133028 19.09045103 19.38640563]
[2.         1.70043972 1.50901365 1.55873096 1.46063437 1.422233
 1.44104472 1.41619357 1.39512118 1.32540753 1.18179828 0.94856635
 0.75517923 0.55696773 0.41912075 0.29595461]

Test

In [34]:
def sierpn(s, n):
    return [(np.array([[s, 0], [0, s]]), np.array([np.cos(2 * i * np.pi / n), np.sin(2 * i * np.pi / n)]), 1) for i in range(n)]
In [35]:
nmax = 100000
vals = [ifsplot(sierpn(1 / (np.sqrt(0.25 + 2 * n) - 0.5), n), x0, npre, nmax) for n in range(2,11)]
In [ ]: