5.Bardziej zaawansowane tematy. Programowanie rekursywne i dynamiczne Programy rekursywne to programy które "odwo uj si do siebie samych". W Mathematice bardzo atwo jest programowa rekursywnie cho w przeciwe stwie do j zyków programistycznych takich jak LISP (do których j zyk Mathematiki ma pewne podobie stwo) Mathematica nie jest zoptymalizowana do tego celu i nie uwa nie napisane programy rekursywne mog by bardzo powolne. Jednym ze sposobów przyspieszenia ich jest metoda zwana "programowaniem dynamicznym", lub, bardziej precyzyjnie, metoda "funkcji które zapami tuj swoje warto ci". Jest to bardzo po yteczna metoda któr naj atwiej zrozumie rozpatruj c przyk ady jej u ycia. Szybkie obliczanie liczb Fibonacciego. Liczby Fibonacciego s rozwi zaniami równania rekursywnego a n a n 2 a n a 0 0 a Funkcja RSolve rozwi zuje wiele równa tego typu: a n. RSolve a n a n a n 2, a 0 0, a, a n, n Fibonacci n Fibonacci n to po prostu zakodowana n-ta liczba Fibonacciego. Aby zobaczy definicj u wyamy FunctionExpand: FunctionExpand Fibonacci n 5 5 2 n 2 5 n cos Π n Teraz spróbujemy sami zdefiniowa liczby Fibonacciego. Zrobimy to na dwa sposoby. Pierwszy, to "zwyczajna rekursja". Fib 0 0; Fib ; Fib n_ : Fib n Fib n 2 Timing Fib 30.85534, 832 040 Niestety, to podej cie jest bardzo powolne i ju obliczenie 30tej liczby Fibonacciego zabiera zauwa aln ilo czasu. Nast pnie u yjemy "programowania dynamicznego". Na pierwszy rzut oka
2 5. Bardziej Zaawansowane Tematy.nb definicja wygl da dziwnie. Nale y zwróci uwag na równoczesne u ycie := i =. Clear Fib2 Fib2 0 0; Fib2 ; Fib2 n_ : Fib2 n Fib2 n Fib2 n 2 Timing Fib2 30 0.000266, 832 040 Tym razem dzia a to b yskawicznie. Co si dzieje podczas wykonywanie tych dwóch definicji-programów mo na prze ledzi za pomoc funkcji Trace. Ro nic wida wyra nie: Trace Fib 5 Fib 5, Fib 5 Fib 5 2, 5, 4, Fib 4, Fib 4 Fib 4 2, 4, 3, Fib 3, Fib 3 Fib 3 2, 3, 2, Fib 2, Fib 2 Fib 2 2, 2,, Fib,, 2 2, 0, Fib 0, 0, 0,, 3 2,, Fib,,, 2, 4 2, 2, Fib 2, Fib 2 Fib 2 2, 2,, Fib,, 2 2, 0, Fib 0, 0, 0,, 2, 3, 5 2, 3, Fib 3, Fib 3 Fib 3 2, 3, 2, Fib 2, Fib 2 Fib 2 2, 2,, Fib,, 2 2, 0, Fib 0, 0, 0,, 3 2,, Fib,,, 2, 3 2, 5 Widzimy e Fib wielkorotnie powtarza te same obliczenia. W przypadku Fib2 pierwsze oblicznie i nast pne s zupe nie inne. Najpierw usu my jesze raz Fib2 i definiujmy funkcj od pocz tku: Clear Fib2 Fib2 0 0; Fib2 ; Fib2 n_ : Fib2 n Fib2 n Fib2 n 2 Trace Fib2 5 Fib2 5, Fib2 5 Fib2 5 Fib2 5 2, 5, 4, Fib2 4, Fib2 4 Fib2 4 Fib2 4 2, 4, 3, Fib2 3, Fib2 3 Fib2 3 Fib2 3 2, 3, 2, Fib2 2, Fib2 2 Fib2 2 Fib2 2 2, 2,, Fib2,, 2 2, 0, Fib2 0, 0, 0,, Fib2 2,, 3 2,, Fib2,,, 2, Fib2 3 2, 2, 4 2, 2, Fib2 2,, 2, 3, Fib2 4 3, 3, 5 2, 3, Fib2 3, 2, 3 2, 5, Fib2 5 5, 5 Teraz wywo ajmy Fib2 jeszcze raz, tym razem dla n 6:
5. Bardziej Zaawansowane Tematy.nb 3 Trace Fib2 6 Fib2 6, Fib2 6 Fib2 6 Fib2 6 2, 6, 5, Fib2 5, 5, 6 2, 4, Fib2 4, 3, 5 3, 8, Fib2 6 8, 8 Widzimy wyra nie e Mathematica zapami ta a warto ci Fib2 n dla n 5 i wi cej nie musia a ich oblicza. Mo emy tak e sprawdzi bezpo rednio co Matheamtica wie o Fib i Fib2?Fib Global`Fib Fib 0 0 Fib Fib n_ : Fib n Fib n 2?Fib2 Global`Fib2 Fib2 0 0 Fib2 Fib2 2 Fib2 3 2 Fib2 4 3 Fib2 5 5 Fib2 n_ : Fib2 n Fib2 n Fib2 n 2 Oczywi cie to du y zysk w szybko ci w obliczeniach dzi ki u yciu programowania dynamicznego ma pewien koszt w u ytej pami ci. Pami mo emy odzyska przez: Clear Fib2 Imperatywne (proceduralne) i funkcyjne programowanie Dotychczas rozwa ali my dwa paradygmaty programowania u ywane w Mathematice: programowanie oparte na regu ach oraz funkcyjne. Teraz przejdziemy do programowania proceduralnego zwanego tak e imperatywnym. Jest to oczywi cie najbardziej powszechny paradygmat programowania, odaj cy dosy wiernie sposób dzia ania wi kszo ci wspó czesnych komputerów. Typowe dla tego paradygmatu jest przypisywanie warto ci zmiennym i u ywanie p tli w celu zmiany tych warto ci. Zaczniejmy od przyk adu.
4 5. Bardziej Zaawansowane Tematy.nb Clear x x ; x x ; x x ; x x ; x x ; x x ; x x ; Zauwa my e nie otrzymali my adengo wyniku. Tymniemniej x ma oczekiwan warto. x 7 Przyjrzyjmy si formie wewn trznej (FullForm) obliczanego wyra enia: FullForm Hold x ; x x ; x x ; x x ; x x ; x x ; x x ; Hold CompoundExpression Set x,, Set x, Plus x,, Set x, Plus x,, Set x, Plus x,, Set x, Plus x,, Set x, Plus x,, Set x, Plus x,, Null Zauwa my e Mathematica automatycznie daje nam warto ostatniego wyra enia w ComposedExpression. Je li wi c nie chcemy tego wyra enia otrzyma, u ywamy ostatniego argumentu Null. W wielu proceduralnych j zykach warto ci zmiennej x nie zwracana o ile nie u yje si Return[x] lub Print[x]. Poniewa Mathematica zawsze zwraca warto obliczanego wyra enia, Return[x] s u y do zupe nie innego celu. Je li na ko cu p tli w programie napisanym w Mathematice widzimy Return[x] (zamiast prostego x) mo emy by prawie pewni e autor nauczy si programowa w j zyku Fortran (lub C) i nadal pisze programy w tym j zyku. Nie jest to najbardziej wydajne i eleganckie podej cie do programowania w Mathematice ale dzia a! Teraz powtórzymy to samo u ywaj c p tli Do. Zauwa my e sama p tla Do nic nie zwraca - dla tego na ko cu kodu umie cili my x : Clear x x ; Do x x, 6 ; x 7 To samo mo na zapisa nieco krócej: x ; Do x, 6 ; x 7 Mathematica ma tak e inne p tle, np. While i For. Ogólnie lepiej stara si ich unika poniewa zazwyczaj mo na uzyska w Mathematice znacznie lepsze wyniki pod wzgl dem szybko ci u ywaj c funkcyjnych konstrukcji Nest, Fold, FixedPoint i Accumulate. Jest to, oczywi cie, zwiazane z natur Mathematiki, nie z programowaniem w ogólno ci. Nawet w Mathematice ró nica w szybko ci programów napisanych proceduralnie i funkcyjnie znika w sytuacjach w których udaje si u y tzw. kompilacji. Zmienne Lokalne Je li w programie przypisujemy zmiennym warto ci i zmieniamy je, musimy zwraca szczegu n uwag aby przypdakowo nie zmieni warto ci zmiennych które chciali my zachowa. Najprostszym sposobem zabezpieczenia si przed tak ewentualno ci jest u ywanie lokalnych zmiennych. Mathematica ma
5. Bardziej Zaawansowane Tematy.nb 5 trzy podstawowe konstrukcje lokalizuj ce zmienne: Block, Module and With. Ka da z nich dzia a inaczej i ma swoje silne i s abe strony.?block Block x, y,, expr specifies that expr is to be evaluated with local values for the symbols x, y,. Block x x 0,, expr defines initial local values for x,. Najpierw prosty przyk ad lokalizacji przez Block. Przypisujemy zmiennej x warto 3. Wewn trz Block zmieniamy jej warto na. Widzimy e "na zewn trz" warto x nie uleg a zmianie. x 3; Block x, x x 3 Dok adnie tak samo zachowa si Module?Module Module x, y,, expr specifies that occurrences of the symbols x, y, Module x x 0,, expr defines initial values for x,. in expr should be treated as local. x 3; Module x, y, z, x 5; y x z 6 x 3 Block and Module dzia aj zupe nie inaczej. Kiedy lokalizujemy zmienn u ywaj c Block jej warto jest najpierw zapisana, potem tymczasowo odebrana wraz z wszystkimi atrybutami zmiennej, i na koniec, po wyj ciu z Block oryginalna warto zostaje przywrócona zmiennej. W przypadku Module nazwy zmiennych s zmienione wewn trz Module, tak e nie konfliktuj z zewn trznymi. W przeciwie swie do Module i Block, wszystkie lokalne zmienne w With musz mie przypisane warto ci pocz tkowe: With x, y 2, x y 3 Nast pnie, zauwa my jedn cech która odró nia Module i With od Block. W tych pierwszych inicializacja (przypisanie warto ci pocz tkowych) dla wszystkich zmiennych odbywa si niezale nie: ClearAll f
6 5. Bardziej Zaawansowane Tematy.nb g x_list : Module u Length x, v u, v g, 2, 3 u ClearAll g g x_list : With u Length x, v u, v g, 2, 3 u Block zachowuje si inaczej: g x_list : Block u Length x, v u, v g, 2, 3 4 A oto inny wa ny przyk ad ilustruj cy ró nic mi dzy Block i Module: foo : x x ; foo Block x 2, foo 2 Chocia foo by o zdefiniowane na zewn trz struktury Block, jego warto zmienia a si wewn trz Block. Module zachowuje si inaczej: foo Module x 2, foo A wi c, ewaluacja wewnatrz Module zale na jest tylko od oryginalnej definicji zmiennej czy funkcji, co nie jest prawd w przypadku Blocku.
5. Bardziej Zaawansowane Tematy.nb 7 P tle i funkcyja iteracji Programy napisane wed ug imperatywnego paradygmatu zmieniaj warto ci przypisane jakiej zmiennej, po czym, aby otrzyma warto zmiennej nale y j jawnie ewaluowa. Rozwa my prosty przyk ad u ywaj cy p teli Do: Timing x ; Do x, 20 000 ; x 0.0248, 20 00 Teraz zrobimy to samo w paradygmie funkcyjnej. Programuj c w tym stylu u ywamy funkcji które zwracaj swoje warto ci zamiast zmienia warto jakiej zmiennej. Zamiast p teli u ywamy funkcji których argumentami s funkcje. Przyk adem takiej funkcji jest Nest:?Nest Nest f, expr, n gives an expression with f applied n times to expr. Nest f, a, 4 f f f f a Jest tak e blisko spokrewniona funkcja NestList?NestList NestList f, expr, n gives a list of the results of applying f to expr 0 through n times. NestList f, a, 4 a, f a, f f a, f f f a, f f f f a Zamiast u ywa p tli Do jak powy ej, uzyskujemy ten sam wynik programuj c funkcyjnie: Nest &,, 20 000 Timing 0.000682, 20 00 Zauwa my du ró nic w szybko ci. FoldList f, a, b, c, d, e a, f a, b, f f a, b, c, f f f a, b, c, d, f f f f a, b, c, d, e Pierwszy argument FoldList musi by funkcj dwóch argumentów. Poni sze przyk ady ilustruj dzia anie FoldList:
8 5. Bardziej Zaawansowane Tematy.nb FoldList Plus, 0, a, b, c, d 0, a, a b, a b c, a b c d FoldList Times,, a, b, c, d, a, a b, a b c, a b c d Zwró my uwag na jeszcze jedn funkcj tego typu:?accumulate Accumulate list gives a list of the successive accumulated totals of elements in list. Accumulate a, b, c, d, e a, a b, a b c, a b c d, a b c d e Oczywi cie ten sam wynik mo na uzyska przy pomocy bardziej ogólnej funkcji FoldList: FoldList Plus, 0, a, b, c, d, e 0, a, a b, a b c, a b c d, a b c d e Jednak e, bardziej wyspecializowana funkcja Accumulate, jest szybsza w dzia aniu na numerycznych argumentach: ls RandomInteger, 00, 000 ; a Accumulate ls ; Timing 0.000056, Null b Rest FoldList Plus, 0, ls ; Timing 0.000853, Null First b First a 5.232 Last a Last b True Wi ksza szybko wyspecializowanych funkcji w porównaniu z bardziej ogólnymi jest wa nym elementem w programowaniu w Mathematice.
5. Bardziej Zaawansowane Tematy.nb 9 http: reference.wolfram.com mathematica tutorial ApplyingFunctionsRepeatedly.html Block i zmienne globalne. Block jest najcz ciej u ywany w celu tymczasowej zmiany warto ci zmiennych globalnych. Na przyk ad, globalna zmienna $RecursionLimit ma domy ln warto : $RecursionLimit 256 Oznacza to e p tla w której d ugo rekursji przekroczy 256 kroków zostanie autmatycznie zatrzymana. Oczywi cie ma to u atwi wy apywanie b dów programistycznych które bez tego ograniczenia prowadzi yby do niesko czonych p tli. Czasem jednak to ogranicznie jest nie wygodne. Dla przyk adu, wró my jeszcze raz do dobrze znanej nam definicji: Clear Fib Fib ; Fib 2 ; Fib n_ : Fib n Fib n Fib n 2 ; Spróbyjmy Fib 3000 $RecursionLimit::reclim : Recursion depth of 256 exceeded. $RecursionLimit::reclim : Recursion depth of 256 exceeded. 54 22 222 37 037 658 776 676 579 57 233 76 483 35 206 693 809 497 Hold Fib 2745 Fib 2745 2 87 57 595 343 08 854 458 033 386 304 78 58 74 356 588 264 390 370 Hold Fib 2746 Fib 2746 2 Ograniczenie zmiennej $RecursionLimit do 256 powoduje e nasz kod nie chce dzia a. Mog iby my zmieni $RecursionLimit do wiekszej liczby albo ca kowicie go usun robi c go równym, ale robi c to nara amy si na nieprzyjemne konsekwencje w przysz o ci. Du o lepiej jest zmieni tymczasowo warto $RecursionLimit za pomoc Block. Zanim jednak to zrobimy musimy usun wszystkie definicje Fib bo Mathematica zapami ta a "zatrzymane" warto ci. Clear Fib Fib ; Fib 2 ; Fib n_ : Fib n Fib n Fib n 2 ;
0 5. Bardziej Zaawansowane Tematy.nb Block $RecursionLimit, Fib 3000 40 65 886 307 97 260 333 568 378 79 267 05 220 25 08 637 369 252 408 885 430 926 905 584 274 3 403 73 330 49 660 850 044 560 830 036 835 706 942 274 588 569 362 45 476 502 674 373 045 446 852 60 486 606 292 497 360 503 469 773 453 733 96 887 405 847 255 290 082 049 086 907 52 622 059 054 542 95 889 758 03 09 222 670 849 274 793 859 539 33 38 37 244 795 543 47 6 073 276 240 066 737 934 085 9 73 80 993 20 706 776 838 934 766 764 778 739 502 74 470 268 627 820 98 553 842 225 858 306 408 30 66 862 900 358 266 857 238 20 235 802 504 35 95 472 997 99 676 524 004 784 236 376 453 347 268 364 52 648 346 245 840 573 24 24 49 937 97 242 98 602 639 80 097 866 942 392 05 404 620 53 88 67 425 739 835 074 85 396 42 39 982 73 640 679 58 78 458 98 658 692 285 968 043 243 656 709 796 000 Zauwa my e globalna warto $RecursionLimit pozostaje nie zmieniona: $RecursionLimit 256 Przyk ad: Symulacja Ruchu Browna Jako przyk ad u ycia funkcji FoldList, NestList i Accumulate podajemy konstrukcj symulacji ruchu Browna (procesu Wienera). W Mathematice 9 konstrukcja staje si du o atwiejsza dzi ki nowym wbudowanym funkcjom RandomFunction i WienerProcess. Kod który podajemy poni ej dzia a w wersjach wy szych ni 6. Jedna cie ka cie k ruchu Browna (przebyt w czasie ) przybli amy przez losowe b dzenie z n krokami, gdzie ka dy krok jest liczb rzeczywist o rozk adzie normalnym z redni 0 i standardowym odchyleniem n. Jest szereg sposobów zaprogramowanie tego w Mathematice. Podajemy trzy. Accumulate (najszybsza metoda) BrownianMotion n_ : Accumulate Prepend RandomReal NormalDistribution 0, Sqrt n, n, 0 2. FoldList (powolniejsza) BrownianMotion n_ : FoldList Plus,0,RandomReal NormalDistribution 0,Sqrt n, n 3. NestList (jeszcze powolniejsza)
5. Bardziej Zaawansowane Tematy.nb BrownianMotion n_ : NestList RandomReal NormalDistribution 0,Sqrt n &,0,n ListLinePlot BrownianMotion 2000, DataRange 0, 0.5 0.2 0.4 0.6 0.8.0 0.5 Wiele cie ek Clear BrownianMotion BrownianMotion time_, steps_, paths_ : Transpose Accumulate Join ConstantArray 0, paths, Transpose RandomReal NormalDistribution 0, Sqrt time steps, paths, steps ListLinePlot BrownianMotion, 00, 0, DataRange 0,, PlotRange All 0.2 0.4 0.6 0.8.0 2
2 5. Bardziej Zaawansowane Tematy.nb Manipulate BlockRandom SeedRandom r ; ListLinePlot BrownianMotion time, steps, paths, DataRange 0, time, PlotRange 2, 2, steps, 00, "number of steps", 0, 300,, Appearance "Labeled", paths, 0, "number of paths",, 50,, Appearance "Labeled", time,, "time", 0.5, 0, Appearance "Labeled", r, 0, "", Button "randomize", r RandomInteger 2^64 &, SaveDefitition True, Initialization BrownianMotion time_, steps_, paths_ : Transpose Accumulate Join ConstantArray 0, paths, RandomReal NormalDistribution 0, Sqrt time steps, steps, paths number of steps 38 number of paths 3 time randomize 0.2 0.4 0.6 0.8.0 2 http: reference.wolfram.com mathematica tutorial PseudorandomNumbers.html