Funkcją malowane, czyli słów kilka o fraktalach

02.12.2009 - Wiktor Zychla
TrudnośćTrudność

Zbiory Julii i Mandelbrota

Aby zrozumieć w jaki sposób powstają jedne z najciekawszych fraktali, fraktalne zbiory Julii i Mandelbrota, zaczniemy od przyjrzenia się właściwościom prostych układów iteracyjnych.

Zacznijmy najprościej jak się tylko da. Weźmy jakieś x. Niech początkowo wartość x wynosi 1. Kolejna wartość będzie obliczania z poprzedniej przez pomnożenie tej poprzedniej przez 2. W ten sposób powstaje nowy x, z którym postępujemy tak samo.

Idea jest prosta - układy iteracyjne polegają na tym, że kolejne wartości powstaje z poprzedniej według tej samej reguły. W naszym przypadku, gdy układ iteracyjny zdefiniowany jest tak jak powyżej, a mówiąc bardziej formalnie

x0 = 1
xn+1 = 2 * xn

otrzymamy ciąg: 1, 2, 4, 8, 16, 32 itd.

Co by się stało, gdyby początkowym punktem było nie 1, ale na przykład 1.0001? Drugą wartością zamiast 2 byłoby 2.0002, potem 4.0004, 8.0008, 16.0016 itd. Widać, że błąd powiększałby się proporcjonalnie, ale jego wielkość w stosunku do wartości ciągu byłaby stała. Wiele prostych układów iteracyjnych zachowuje się w taki przewidywalny sposób - błędy obliczeniowe kumulują się w sposób przewidywalny.

Spróbujmy zająć się przez chwilę innym prostym układem iteracyjnym:

xn+1 = 4 * xn * (1-xn)

Dla początkowej wartości x z przedziału [0,1] wartości ciągu też będą należały do przedziału [0,1] (dlaczego?). Jak poprzednio, prześledźmy iteracje dla jakichś dwóch nieodległych wartości początkowych, np. 0.2 i 0.2000001. Zobaczmy czy podobnie jak poprzednio błąd narasta proporcjonalnie w stosunku do wartości (będziemy śledzić jak zmienia się odległość między powstającymi dwoma ciągami).

Początkowe iteracje nie zapowiadają jeszcze nic złego:

	xa=0.2000000, xb=0.2000001, błąd=0.0000001
	xa=0.6400000, xb=0.6400002, błąd=0.0000002
	xa=0.9216000, xb=0.9215997, błąd=0.0000003
	xa=0.2890138, xb=0.2890147, błąd=0.0000009
	xa=0.8219392, xb=0.8219408, błąd=0.0000015
	xa=0.5854205, xb=0.5854166, błąd=0.0000039
	xa=0.9708133, xb=0.9708160, błąd=0.0000027
	xa=0.1133392, xb=0.1133291, błąd=0.0000101
	
... ale mniej więcej od 20-tej iteracji układ zaczyna zachowywać się bardzo nieciekawie
	...
	xa=0.8708927, xb=0.0382300, błąd=0.8326627
	xa=0.4497544, xb=0.1470737, błąd=0.3026806
	xa=0.9899015, xb=0.5017722, błąd=0.4881293
	xa=0.0399860, xb=0.9999874, błąd=0.9600014
	xa=0.1535486, xb=0.0000503, błąd=0.1534983
	...
	
Wartości ciągu xa i xb nie wykazują żadnego związku, a błąd urósł do tego samego rzędu co te wartości!

Katastrofa!

Takie zachowanie się układów iteracyjnych nazwano zachowaniem chaotycznym. Ich odkrycie było niesamowitym ciosem dla tych naukowców, którzy wierzyli, że poznanie praw przyrody to tylko kwestia czasu. Okazało się bowiem, że wiele funkcji o nieskomplikowanym wyrażeniu w postaci formuły matematycznej ma takie właśnie chaotyczne właściwości.

Wyobraźmy sobie, że naukowcy chcieliby na przykład umieć przewidywać pogodę z dowolnym wyprzedzeniem. Chcieliby mieć wzór, do którego wrzucaliby jakieś parametry z zadanego dnia (temperaturę, ciśnienie, wilgotność atmosfery itd.) i dostawaliby dokładne wartości tych parametrów w kolejnym dniu. Chcieliby mieć taki właśnie układ iteracyjny. Zaczynam dzisiaj, dostaję pogodę na jutro, z niej obliczam pogodę na pojutrze, potem na popojutrze i jak sobie wyliczam pogodę za rok, za sto lat itd.

Przez wiele lat wierzono, że skontruowanie takich wzorów to tylko kwestia czasu i zbudowania wystarczająco precyzyjnych modeli opisu zjawisk przyrodniczych (czy to w ogóle możliwe?). Nasz numeryczny eksperyment pokazuje jednak, że jeśli model opisu matematycznego okazałby się być chaotyczny (a takie niebezpieczeństwo oczywiście istnieje), to dowolnie małe zaburzenia w pomiarach parametrów fizycznych skutkowałyby powstaniem błędów obliczeniowych rujnujących wyniki obliczeń w perspektywie wielu iteracji.

Tymczasem istnieje „druga strona medalu”. Iterowanie prostych funkcji, mimo że prowadzi do zachowań chaotycznych, miewa przepiękną, fraktalną interpretację graficzną! Takie fraktale są składnikami rzeczywistości, która nas otacza, tak samo jak na przykład atomy. O ile jednak atomy są elementami świata fizycznego i jako takie są nietrwałe, o tyle fraktale są idealnie doskonałe, wieczne i niezmienne. Gdyby instrukcje ich tworzenia wysłać w kosmos (czy na jakieś inne płaszczyzny istnienia), można mieć pewność, że ktokolwiek je odtworzy, na pewno otrzyma dokładnie te same obrazy.

Fraktalne zbiory Julii „żyją” na płaszczyźnie. Powstają jako efekt chaotycznego zachowania się prostego układu iteracyjnego:

x0 = współrzędne punktu przestrzeni
xn+1 = xn * xn + c       (1)

(gdzie c jest jakąś ustaloną liczbą zespoloną)

Przyjmiemy, że powierzchnia obrazu graficznego będzie obrazem wycinka płaszczyzny [-2,2] x [-2,2]. Każdemu punktowi obrazu przypiszemy jednoznacznie punkt naszego wycinka, dokonując prostej liniowej transformacji.

Dobrze, mamy punkt, niech to będzie ten x. W jaki sposób wyliczyć x * x? Co to w ogóle znaczy pomnożyć przez siebie punkt?

Otóż każdy punkt płaszczyzny wyznacza jednoznacznie tak zwaną liczbę zespoloną. Liczby zespolone (punkty) można dodawać, odejmować ale także mnożyć i dzielić przez siebie, a nawet podnosić do potęgi czy wyciągać pierwiastki. Wynikami wszystkich działań są punkty, na przykład punkt (1,1) podniesiony do kwadratu to (0,2), a (1,2)*(2,-4) to (10,0).

Algorytm generowania fraktalnego zbioru Julii wymaga przeprowadzenia obliczenia kolejnych wartości naszego układu iteracyjnego (1) dla każdego punktu naszego wycinka przestrzeni zespolonej. Iteracja okazuje się mieć następujące własności: albo osiąga orbitę stałą (moduły zespolone kolejnych wyrazów układu iteracyjnego pozostają skończone) albo kolejne wartości iterowanego układu uciekają do "zespolonej" nieskończoności.

Przyjmijmy, że te punkty wycinka, dla których iteracja osiąga orbitę stałą oznaczymy kolorem białym i zaliczymy do wnętrza zbioru, pozostałe punkty, dla których iteracja ucieka do nieskończoności, ze zbioru wykluczymy.

I to wszystko. Możemy obejrzeć nasz pierwszy zbiór Julii, wygenerowany dla wartości parametru c w definicji (1) równego 0 (zespolone 0 + 0i).

Julia

Przecież to zwykłe kółko! Co w tym fraktalnego? Chwilowo nic, ale spróbujmy zmienić wartość parametru c na (0,1) (czyli zespolone 0 + 1i).

Julia 2

Co się stało z kółkiem? Otóż tu objawia się chaos w najczystszej postaci. Te punkty wycinka, których iterowanie naszego układu (x -> x * x + c) dla c = 0 + 1i prowadzi do osiągnięcia orbity stałej, układają się w kształt "dendrytu". Dla punktów sąsiadujących z dendrytem układ iteracyjny ucieka do nieskończoności.

Ale przecież te punkty leżą w naszym malutkim wycinku bardzo blisko, nieskończenie blisko siebie! Mimo to zachowanie się układu iteracyjnego jest dla nich zupełnie różne.

Zauważmy pewną ciekawą właściwość zbiorów Julii - otóż wykazują one łatwą do zauważenia symetrię względem środka układu współrzędnych, która dzieli płaszczyznę na dwie symetryczne względem siebie części. To nieprzypadkowe - dla układu iteracyjnego postaci x -> x * x * x + c mielibyśmy zbiory Julii o "trzech" symetrycznych ramionach, dla x -> x4 + c - o czterech ramionach, itd!

Poniższa aplikacja demonstruje animację fraktalnych zbiorów Julii, która powstaje przez ciągłą zmianę wartości parametru c w jakimś ograniczonym obszarze. Podczas animacji widać, że występują dwa "typy" zbiorów Julii - dla pewnych wartości parametru c zbiory są spójne (są jednym "kawałkiem"), dla innych są totalnie niespójne (składają się z nieskończenie wielu "kawałków").

Twoja przeglądarka nie obsługuje formantu typu Canvas

Zbiory Julii kryją w sobie jeszcze dwie fascynujące niespodzianki.

Pierwsza z nich to możliwość oglądania trójwymiarowych obrazów zbiorów Julii. Pomysł polega na tym, żeby zamiast w przestrzeni liczb zespolonych, iterować układ (1) w ciele kwaternionów. Tak otrzymane czterowymiarowe obrazy (przestrzeń kwaternionów ma cztery wymiary) można łatwo rzutować na trzy wymiary i oglądać obrazy korzystająjąc z technik stereoskopii

Julia 3D

Druga niespodzianka pojawia się wtedy, kiedy zmienimy nieco definicję układu iteracyjnego:

x0 = 0
xn+1 = xn2 + współrzędne punktu przestrzeni       (2)

Tak opisany układ iteracyjny generuje jeden, bardzo konkretny zbiór fraktalny (znikł parametr c za pomocą którego można było tworzyć całą rodzinę zbiorów Julii), ale za to wynikowy zbiór ma tyle niesamowitych właściwości, że napisano o nim niejeden artykuł i niejedną książkę.

Co to za tajemniczy zbiór? Niech Szanowny Czytelnik zechce przekonać się o tym samodzielnie.

Literatura

[1] H.O.Peitgen, H.Jürgens, D.Saupe: Granice chaosu FRAKTALE część I i II, Wydawnictwo Naukowe PWN, Warszawa 1995
0
Twoja ocena: Brak

Copyright © 2008-2010 Wrocławski Portal Informatyczny

design: rafalpolito.com