Spis rzeczy
Uwagi historyczne: styl logiczny i styl klasyczny
Temat
Wielkich Liczb wystąpił przy okazji
teorii funkcji rekursywnych, stworzonej przez uczniów Hilberta (i samego mistrza też?): Wilhelma Ackermanna i Gabriella Sudana, oraz przez jedną z nawybitniejszych matematyczek wszech czasów, Rozsę Peter (nie była uczniem Hilberta). Właśnie ona zaproponowała, by temat funkcji rekursywnych traktować jako samodzielną teorię. Otóż Hilbert postawił problem istnienia rekursywnej funkcji, która nie byłaby
pierwotnie rekursywną. Najpierw Sudan, a wkrótce i niezależnie Ackerman (nieco bardziej elegancko), podali takie funkcje. Skonstruowali funkcje rekursywne, które rosną szybciej niż jakakolwiek funkcja pierwotnie rekursywna. Używali 3 argumentów. Rozsa Peter zastąpiła 3 argumenty w funkcji Ackermanna przez 2. Ostatecznie funkcję tę uprościł Raphael Robinson, przez podanie elegantszych warunków początkowych. Tradycyjnie dalej nazywa się ją funkcją Ackermanna (czasem dodają nazwisko Peter). Uderza ekonomia ostatecznej definicji. Reprezentuje ona ciekawy, lecz nieco dziwny obiekt, który mi się podoba, ale odczuwam potrzebę także naturalniejszego podejścia, wykorzystującego konstrukcję przekątną, która musiała istnieć w Analizie Matematycznej chyba na długo przed Cantorem. Cantor stosował metodę przekątnej w teorii mnogości.
Metoda wspomnianych logików polegała na budowaniu wyrażenia, które w czasie rekurencji ogromniało, zawierając coraz więcej podwyrażeń, produkujących w czasie iteracji dalsze liczne podpodwyrażenia. Konstrukcja w końcu się zatrzymuje, bo każde wyrażenie ma parametry, które traktowane jako jeden parametr, stale maleje w leksykograicznym porządku. Porządek jest taki, że w dół można iść tylko skończenie wiele razy.
Wśród logików, zajmujących się rekursywnością i szybkością rośnięcia funkcji, liczy się między innymi Andrzej Gregorczyk.
Następcy wspomnianych wyżej matematyków dodali chyba niewiele, i nie wiem co było ich matematycznym celem (czy taki mieli). Wspomnę Knutha i Conway'a. Niektórzy skręcili w kierunku klasycznym. Widać też, że klasyczne podejście i logiczne są zbieżne.
Poniżej opiszę podejście klasyczne, ale koncepcyjnie jaśniej, niż jest to w spotkanej przeze mnie literaturze. Podkreślę i opiszę explicite ważne elementy konstrukcji, te które się koncepcyjnie liczą najbardziej.
UWAGA Nietrudno, po mojej tu nitce dojść do kłębka informacji na dany temat, zawartego w wikipedii.
Podejście koncepcyjne: arytmetyka, funkcje, kompozycja, operatory
Budowanie wielkich liczb, a raczej szybko rosnących funkcji, związane jest na początku z działaniami arytmetycznymi: następnik [;\nu(n) := n+1;], dodawanie, mnożenie, wreszcie potęgowanie, na przykład: [;\delta(n) := n^n;]. - to etap 1. Etap 2 polega na wprowadzeniu funkcji, zamiast izolowanych liczb. Jakoś należy przy definiowaniu funkcji operacje arytmetyczne iterować na wielką skalę; ale tak po prostu, to nie ma jak. Pomaga, na trzecim etapie, pojęcie kompozycji funkcji. Właśnie, jako etapm 3, wielokrotne iterowanie kompozycji pozwala przyspieszyć budowę szybko rosnących funkcji. Zajmijmy się tym etapem, czyli kompozycją.
Rozpatrujemy funkcje postaci [;f\ g\ \dots : \mathbf Z^+\rightarrow\mathbf Z^+;], zbioru nieujemnych liczb całkowitych [;\mathbf Z^+ := \{0\ 1\ 2\ \dots\};] w siebie.
Kompozycją (albo
superpozycją) dwóch funkcji [;f\ g;] nazywamy funkcję , zdefiniowaną jak następuje:
Na przykład:
- [;(\nu\circ\nu)(n) = n+2;]
- [;(\delta\circ\delta)(n) = \left(n^n\right)^{n^n};]
Następnie zdefiniujmy potęgę [;\bigcirc^n;] dowolnej funkcji [;f;] względem kompozycji. Zaczynamy od funkcji identycznościowej [;\iota : \mathbf Z^+\rightarrow\mathbf Z^+;], danej wzorem:
[;\iota(n) := n;]
Oczywiście:
[;\iota\circ f = f \circ\iota = f;]
dla dowolnej funkcji [;f : \mathbf Z^+\rightarrow\mathbf Z^+;]. Teraz już możemy przystąpić do definicji potęgi [;\bigcirc^n;]:
[;\bigcirc^0 f = \iota;]
[;\bigcirc^n f = (\bigcirc^{n-1} f)\circ f = f\circ (\bigcirc^{n-1} f);]
dla dowolnego [;n > 0;]. Na przykład [;\bigcirc^3 f = f\circ f\circ f;].
W szczególności:
- [;\left(\bigcirc^3 \nu\right)\left(n\right) = n+3;]
- [;\left(\bigcirc^k \nu\right)\left(n\right) = n+k;]
- [;\left(\bigcirc^n \nu\right)\left(n\right) = 2\cdot n;]
- [;\left(\bigcirc^3 \delta\right)\left(n\right) = \left(\left(n^n\right)^{n^n}\right)^{\left(n^n\right)^{n^n}};]
Zauważmy, że akcent przesunął się z definiowania funkcji, czyli przyporządkowania liczbom liczb, na definiowanie operatorów, czyli na przyporządkowywanie funkcjom funkcji:
[;\Omega : \hom(\mathbf Z^+\ \mathbf Z^+) \rightarrow \hom(\mathbf Z^+\ \mathbf Z^+);]
gdzie [;\hom(\mathbf Z^+\ \mathbf Z^+);] oznacza zbiór wszystkich funkcji [;\mathbf Z^+;] w siebie. Operatorem jest na przykład potęga [;\bigcirc^n;].
Wprowadzenie operatorów jest naszym czwartym etapem. Przypomnę je:
- operacje arytmetyczne
- fukcje
- kompozycja funkcji
- operatory
Teraz z kolei, dodam szybko, możnaby stosować kompozycję operatorów, i operatory operatorów, itd. Nie chce mi się tych konstrukcji uważać za nowe etapy. Zamiast tego raz na zawsze zauważmy, że operatory też są funkcjami (choć o innym zbiorze argumentów i wartości), więc dalsze kroki możemy koncepcyjnie uważać za znajome, za te same etapy, co już naszkicowane.
Możemy rozpatrywać także operatory dwóch zmiennych (ich zmienne przebiegają przez zbiór funkcji), jak na przykład [;\Delta;], gdzie:
[;h = \Delta^g f;]
wtedy i tylko wtedy, gdy:
[;h(n) =
\left(\bigcirc^{g(n)} f\right)(n);]
Innymi słowy:
[;\left(\Delta^g f\right)(n) :=
\left(\bigcirc^{g(n)} f\right)(n);]
Z operatora dwuargumentowego możemy uzyskać szereg operatorów jednoargumentowych (podobnie jest z operacjami arytmetycznymi), jak na przykład operatory (jednej zmiennej) [;\Delta^{\iota};] oraz [;\Theta;], zdefiniowane następująco:
[;\left(\Delta^{\iota} f\right)(n) := \left(\bigcirc^n f\right)(n);]
[;\left(\Theta f\right)(n) :=
\left(\bigcirc^{f(n)} f\right)(n);]
Ten pierwszy jest regularniejszy, a drugi bardziej chciwy (daje szybciej szybciej rosnące funkcje).
Zastosowania
Potęga kompozycyjna
Zacznijmy od operatora potęgi kompozycyjnej:
- [;\beta(n) := \left(\bigcirc^n \nu\right)\left(n\right) = 2\cdot n;]
- [;\left(\bigcirc^k \beta\right)\left(n\right) = 2^k\cdot n;]
- [;\gamma(n) := \left(\bigcirc^n \beta\right)\left(1\right) = 2^n;]
- [;\left(\bigcirc^k \gamma\right)\left(n\right) = 2^{2^{\dots^{2^n}}};] (k dwójek)
- [;\Gamma(n) := \left(\bigcirc^n \gamma\right)\left(1\right) = 2^{2^{\dots^{2^2}}};] (n dwójek)
Kolejne wartości [;\Gamma(n);], dla [;n = 0\ 1\ \2\dots;], wynoszą:
[;1\quad 2\quad 4\quad 16\quad 65536\quad 2^{65536}\quad 2^{2^{65536}}\quad \dots;]
Wyłoniła się regularność. Możemy zdefiniować ciąg eleganckich, coraz szybszych funkcji [;\beta_n;], poczynając od [;\beta;]:
- [;\beta_0:=\beta;]
- [;\beta_n (k) := \left(\bigcirc^k\beta_{n-1}\right)(1);] dla [;n>0;]
Tak więc [;\gamma = \beta_1,\quad\Gamma=\beta_2;]. Następne funkcje [;G:=\beta_3,\dots;] będą już potworne czyli monstrualne.
Skromna przekątna
Pora na sprawdzenie skromnej przekątnej [;\Delta^{\iota};]:
- [;\left(\Delta^{\iota} \nu\right)(n) = \left(\bigcirc^n \nu\right)(n) = \beta(n) = 2\cdot n;] czyli [;\Delta^{\iota} \nu = \beta;]
- [;\left(\Delta^{\iota} \beta\right)(n) = \left(\bigcirc^n \beta\right)(n) = n\cdot 2^n = n\cdot\gamma(n);]
- [;\left(\Delta^{\iota} \beta\right)(n) = \gamma(n+k);] dla [;n=2^k;]; czyli:
- [;\left(\Delta^{\iota} \beta\right)\circ\gamma = \gamma\circ(\gamma+\iota);]
- [;\left(\Delta^{\iota} \gamma\right)(n) = \left(\bigcirc^n \gamma\right)(n) = 2^{2^{\dots^{2^n}}};] (n dwójek)
- [;\left(\Delta^{\iota} \gamma\right)(n) = \Gamma(n+k);] dla [;n=\Gamma(k);]; czyli:
- [;\left(\Delta^{\iota} \gamma\right)\circ\Gamma = \Gamma\circ(\Gamma+\iota);]
Zachodzi ogólne twierdzenie:
TWIERDZENIE 0
[;(\Delta^{\iota} \beta_n)\circ\beta_{n+1} = \beta_{n+1}\circ(\beta_{n+1}+\iota);]
dla dowolnego [;n=0\ 1\ \dots;].
DOWÓD [;\left(\left(\Delta^{\iota} \beta_n\right)\circ\beta_{n+1}\right)(k) = \left(\Delta^{\iota} \beta_n\right)\left(\beta_{n+1}\left(k\right)\right);]
[;=\left(\bigcirc^{\beta_{n+1}\left(k\right)} \beta_n\right)\left(\beta_{n+1}\left(k\right)\right) = \left(\bigcirc^{\beta_{n+1}\left(k\right)} \beta_n\right)\left(\left(\bigcirc^k\beta_n\right)\left(1\right)\right);]
[;=\left(\bigcirc^{\beta_{n+1}\left(k\right)+k} \beta_n\right)\left(1\right) = \beta_{n+1}\left(\beta_{n+1}\left(k\right)+k\right);]
[;=\left(\beta_{n+1}\circ\left(\beta_{n+1}+\iota\right)\right)\left(k\right);]
KONIEC DOWODUTwierdzenie to pokazuje między innymi, że funkcja [;\Delta^{\iota}\beta_n;] jest nieco szybsza od [;\beta_{n+1};]. Przy tym słowo
nieco należy rozumieć w sensie koncepcyjnym, bo naiwnie to
o wiele.