Wprowadzenie do Scilaba Bruno Pinçon Institut Elie Cartan Nancy E.S.I.A.L. Université Henri Poincaré Email : Bruno.Pincon@iecn.u-nancy.fr Przekªad z j¦zyka francuskiego Piotr Fulma« ski Katarzyna Szulc Wydziaª Matematyki Institut Elie Cartan Nancy Universytetu ódzkiego Université Henri Poincaré Email : fulmanp@math.uni.lodz.pl Email : Katarzyna.Szulc@iecn.u-nancy.fr Skrypt ten byª pocz¡ tkowo opracowany przez studentó w E.S.I.A.L. (École Supérieure d'Informatique et Application de Lorraine). Opisuje on niewielk¡ cze±¢ mo» liwo± ci Scilaba, w szczgó lno± ci te, któ re pozwalaj¡ zastosowa¢ notacje analizy numerycznej i maª ych symulacji stochastycznych takich jak: operacje na macierzach i wektorach o wspóª rz¦ dnych rzeczywistych; programowanie w Scilabie; prosta graka; niektó re funkcje dla dwó ch wymienionych powy» ej (generowanie liczb losowych, rozwiazywnie ró wna« , ...). ¦nditemize Scilab umo» liwia wykonanie wielu innych operacji, w szczgó lno± ci w dziedzinie automatyki, obró bki sygnaªó w dzwiekowych, symulacji systemó w dynamicznych (za pomoc¡ scicos)... Jako » e zamierzam systematycznie uzupelnia¢ ten dokument, jestem w peª ni otwarty na wszelkie uwagi, sugestie i krytyk¦ pozwalaj¡ ce mi na jego ulepszenie (ró wnie» w przypadku bª¦ dó w ortogracznych), piszcie do mnie. Maª a historia tego dokumentu: wersja 0.999 : modykacje rozdziaª u o grace oraz uzupeª nienie tre± ci rozdziaª u o programowaniu; wersja relatywna do Scilab-2.7; wersja 0.9999 (ten dokument) : dostosowanie rozdziaª u o grace do nowej graki obiektowej Scilaba; wersja relatywna do Scilab-4.0. ¦nditemize W wyniku dopisania kilku paragrafó w, dokument straciª na spó jno± ci. Istnieje jednak obecnie inny podr¦ cznik, któ ry jest dost¦ pny na stronie internetowej Scilaba (czytaj dalej). ¦m Podzi¦ kowania ¦ndcenter dla Doc Scilab, któ ry cz¦ sto pomagaª mi na forum u» ytkownikó w; dla Bertranda Guiheneufa, któ ry dostarczyª mi magiczn¡ scierzk¦ do skompilowania Scilaba 2.3.1 pod linuxem (kompilacja pod linuxem nowszych wersji nie powoduje prob- 1 lemó w); 1 dla moich kolegó w i przyjacióª Stéphane Mottelet , Antoine Grall, Christine BernierKatzentsev i Didier Schmitt; dla Helmuta Jarauscha, któ ry przetª umaczyª ten dokument na j¦ zyk niemiecki, i któ ry zwró ciª moj¡ uwag¦ na kilka bª edó w; i dla wszystkich czytelnikó w za ich wsparcie, uwagi i korekty. ¦nditemize ¦ndtitlepage dziekuje za ten pdf Stéphane ! 2 Spis tre±ci 1 2 Wiadomo±ci wst¦pne 4 1.1 Co to jest Scilab? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 1.2 Jak korzystac z tego dokumentu? . . . . . . . . . . . . . . . . . . . . . . . 4 1.3 Podstawy pracy w Scilabie . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.4 Gdzie znale¹¢ informacje na temat Scilaba? . . . . . . . . . . . . . . . . . 5 1.5 Jaki jest statut programu Scilab? . . . . . . . . . . . . . . . . . . . . . . . 6 Operacje na macierzach i wektorach 7 2.1 Wprowadzanie macierzy 7 2.2 Typowe wektory i macierze . . . . . . . . . . . . . . . . . . . . . . . . . . 8 2.3 Wyra»enia w Scilabie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.1 Kilka podstawowych przykªadów wyra»e« macierzowych . . . . . . 11 2.3.2 Dziaªania na elementach macierzy . . . . . . . . . . . . . . . . . . 14 2.3.3 Rozwi¡zywanie ukªadów równa« liniowych . . . . . . . . . . . . . . 15 2.3.4 Indeksowanie, wydobywanie podmacierzy, konkatenacj macierzy i wektorów . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 2.4 Informacje na temat ±rodowiska pracy(*) . . . . . . . . . . . . . . . . . . . 18 2.5 Wywoªanie pomocy z linii polece« . . . . . . . . . . . . . . . . . . . . . . . 19 2.6 Generator prostych wykresów . . . . . . . . . . . . . . . . . . . . . . . . . 19 2.7 Pisanie i wykonywanie skryptów 2.8 Dodatkowe informacje . . . . . . . . . . . . . . . . . . . . . . . 20 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 2.8.1 Skracanie instrukcji przy zapisie macierzowym . . . . . . . . . . . . 21 2.8.2 Pozostaªe uwagi dotycz¡ce rozwi¡zywania ukªadów równa« liniowych (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.9 3 2.8.3 Kilka prostych macierzy (*) . . . . . . . . . . . . . . . . . . . . . . 2.8.4 Funkcje wiczenia size i length 21 24 . . . . . . . . . . . . . . . . . . . . . . . . . 29 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 Programowanie w Scilabie 31 3.1 31 3.2 3.3 3.4 P¦tle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 P¦tla 3.1.2 P¦tla for . while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 Instrukcja warunkowa 3.2.1 Instrukcja 3.2.2 Instrukcja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . if-then-else . select-case (*) Inne rodzaje zmiennych 33 . . . . . . . . . . . . . . . . . . . . . . 33 . . . . . . . . . . . . . . . . . . . . . . 34 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.3.1 a«cuchy znaków . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 3.3.2 Listy (*) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 3.3.3 Niektóre wyra»enia z wektorami i macierzami typu logiczego (boolen) 40 Funkcje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.4.1 Przekazywanie parametrów (*) . . . . . . . . . . . . . . . . . . . . 44 3.4.2 Wy±wietlanie funkcji . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3 3.5 3.6 Instrukcja 3.4.4 Kilka przydatnych dla funkcji prymitywów . . . . . . . . . . . . . . Ró»ne ró»no±ci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.2 Priorytety operatorów . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.5.3 Rekursja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 3.5.4 Funkcja jest te» zmienn¡ . . . . . . . . . . . . . . . . . . . . . . . . 51 3.5.5 Okna dialogowe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 3.5.6 Konwersja ªa«cucha znakowego do wyra»enia . . . . . . . . . . . . 52 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53 Wejscie i wyj±cie w stylu Fortranu . . . . . . . . . . . . . . . . . . 53 Wej±cie i wyj±cie w stylu C . . . . . . . . . . . . . . . . . . . . . . . . . . 57 3.8 Uwagi zwi¡zane z szybko±ci¡ . . . . . . . . . . . . . . . . . . . . . . . . . . 58 3.9 ¢wiczenia 62 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Graka 64 4.1 Okna graczne 4.2 Wprowadzenie do . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . plot2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 65 4.3 plot2d 4.4 Inne wersje . . . . . . . . . . . . . . . . . . . . 71 4.5 Rysowanie wi¦kszej ilo±ci krzywych zªo»onych z ró»nej ilo±ci punktów . . . 72 4.6 Zabawa z kontekstem gracznym . . . . . . . . . . . . . . . . . . . . . . . 73 4.7 Tworzenie histogramów . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 4.8 Zapisywanie graki w ró»nych formatach . . . . . . . . . . . . . . . . . . . 75 4.9 Prosta animacja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . z argumentami opcjonalnymi . . . . . . . . . . . . . . . . . . . . . plot2d: plot2d2, plot2d3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.10.1 Wprowadzenie do plot3d . . . . . . . . . . . . . . . . . . . . . . . 4.10.2 Kolory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.10.3 plot3d z des facettes . . . . . . . . . . . . . . . . . . . . . . . . . . 4.10.4 Rysowanie powierzchni opisanej przy pomocy y(u; v), z = z (u; v) 4.10.5 plot3d x = x(u; v), y = 65 76 78 78 80 81 . . . . . . . . . . . . . . . . . . . . . . . . . . . 83 z interpolacj¡ kolorów . . . . . . . . . . . . . . . . . . . . . 85 4.11 Krzywe w przestrzeni . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86 4.12 Ró»no±ci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Zastosowania i uzupeªnienia 89 5.1 5.2 6 49 3.7 4.10 Powierzchnie 5 47 49 Dªugo±¢ identykatorów Czytanie i pisanie . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3.5.1 3.6.1 4 break 3.4.3 Równania ró»niczkowe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ode 5.1.1 Podstawowe u»ycie . . . . . . . . . . . . . . . . . . . . . . . . 5.1.2 Van der Pol jeszcze raz . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.3 Troche wi¦cej o 89 89 90 ode . . . . . . . . . . . . . . . . . . . . . . . . . . 92 Generowniw liczb losowych . . . . . . . . . . . . . . . . . . . . . . . . . . 94 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97 5.2.1 Funkcja 5.2.2 Funkcja rand . grand 5.3 Dystrubuanty i ich odwrotno±ci . . . . . . . . . . . . . . . . . . . . . . . . 98 5.4 Proste symulacje stochastyczne . . . . . . . . . . . . . . . . . . . . . . . . 99 5.4.1 Wprowadzenie i notacja . . . . . . . . . . . . . . . . . . . . . . . . 99 5.4.2 Przedziaªy ufno±ci 5.4.3 Wykres dystrubuanty empirycznej 5.4.4 Test 5.4.5 Test Koªmogorowa-Smirnova 5.4.6 ¢wiczenia 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . 99 . . . . . . . . . . . . . . . . . . 101 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102 . . . . . . . . . . . . . . . . . . . . . 103 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104 Ciekawostki 107 4 6.1 Deniowanie wektora i macierzy wspóªczynnik po wspóªczynniku . . . . 107 6.2 Na temat warto±ci zwracanych przez funkcj¦ . . . . . . . . . . . . . . . . . 108 6.3 Funkcja zostaªa zmidykowana ale... . . . . . . . . . . . . . . . . . . . . . 109 6.4 Problem z . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 6.5 Wektory wierszowe, wektory kolumnowe... . . . . . . . . . . . . . . . . . . 109 6.6 Operator porównania . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109 6.7 Liczby zespolone a liczby rzeczywiste . . . . . . . . . . . . . . . . . . . . . 109 6.8 Proste instrukcje a funkcje Scilaba . . . . . . . . . . . . . . . . . . . . . . 110 6.9 Obliczanie wyra»e« logicznych . . . . . . . . . . . . . . . . . . . . . . . . . 111 rand A Odpowiedzi do ¢wicze« z rozdziaªu 2 112 B Rozwi¡zania ¢wicze« z rozdziaªu 3 114 C Rozwi¡zania ¢wicze« z rozdziaªu 4 118 5 Rozdziaª 1 Wiadomo±ci wst¦pne 1.1 Co to jest Scilab? Dla osób znaj¡cych juz MATLAB-a odpowied¹ jest prosta Scilab jest jego darmowym odpowiednikiem (wi¦cej szczeguªów zwi¡zanych z tym tematem w dalszej cz¦±ci), pow- 1 w I.N.R.I.A. (Institut National de Recherche en Informatique et Automatique). staªym Skªadnia, z wyj¡tkiem nielicznych polece«, jest taka sama (istotne ró»nice wyst¦puj¡ w przypadku graki). Osobom nie znajacym MATLABA powiem tylko, ze Scilab jest przyst¦pnym ±rodowiskiem do wykonywania oblicze« numerycznych gdy» dysponuje on odpowiednimi metodami w tym zakresie: rozwiazywanie ukladów liniowych, wyznaczanie warto±ci wªasnych, wektoró w wªasnych, dekompozycja dla warto±ci osobliwych i pseldo-osobliwych, szybka transformacja Fouriera, rozwiazywanie równa« ró»niczkowych, algorytmy optymalizacji, rozwiazywanie równa« nieliniowych, generowanie liczb losowych, dla wielu niezaawansowanych zastosowa« algebry liniowej w automatyce. Ponadto Scilab wyposa»ony jest w funkcje slu»¡ce do tworzenia graki, zarówno niskopoziomowej (wielok¡ty, odczytywanie wspóªrz¦dnych poªo»enia kursora, itp.) jak i wysokopoziomowej (krzywe, powierzchnie itp.). Wprowadzony j¦zyk programowania, dzi¦ki operowaniu notacj¡ macierzow¡, jest prostym, ale pot¦»nym i efektywnym narz¦dziem. Wyszukiwanie bª¦dów w programach jest szybkie dzi¦ki ªatwemu operowaniu zmiennymi. W przypadku, gdy obliczenia b¦d¡ zbyt czasochªonne (j¦zyk jest interpretowany. . . ) mo»liwe jest ªatwe poª¡czenie programu Scilaba z podprogramami napisanymi w C czy FORTRAN-ie. 1.2 Jak korzystac z tego dokumentu? W rozdziale drugim wyja±nione zostaªy podstawy pracy z Scilabem jako narzedziem do obliczen macierzowych. Wystarczy przesledzic proponowane przyklady. Sekcje oznaczone gwiazdk¡ podczas pierwszego czytania mo»na pomin¡¢. Osoby zainteresowane zagadnieniami dotycz¡cymi graki, mog¡ przeanalizowa¢ pierwsze przykªady z rozdziaªu czwartego. Rozdziaª trzeci wyja±nia podstawy programowania w Scilabie. Zacz¡ªem pisa¢ rozdziaª pi¡ty, który przedstawia niektóre zastosowania podobnie jak rozdziaª Ciekawostki, który przedstawia najcz¦±ciej popeªniane bª¦dy przez u»ytkowników Scilaba (prze±lij mi równie» Twoje!). Ostatnim aspektem jest ±rodowisko graczne. Istniej¡ nieznaczne ró»nice pomi¦dzy 1 Scilab wyko»ystuje du»¡ ilo±¢ funkcji pochodz¡cych z ró»nych miejsc, dostepnych czesto przez Netlib 6 ±rodowiskami gracznymi przeznaczonymi dla Unix i Windows, polegaj¡ce na odmennym sposobie rozmieszczenia przycisków i menu. W tym dokumencie opieram si¦ na wersji Unix aczkolwiek u»ytkownicy wersji przeznaczonej dla systemu Windows nie powinni natra¢ na problemy ze znalezieniem odpowiednich opcji / przyciskow. 1.3 Podstawy pracy w Scilabie W najprostszym przypadku, Scilab mo»e byc wykorzystywany jako kalkulator zdolny wykonywa¢ obliczenia na wektorach i macierzach liczb rzeczywistych i/lub zespolonych (ale tak»e na zwykªych skalarach) oraz do wizualizacji krzywych i powierzchni. W na- jprostrzych zadaniech raczej nie ma potrzeby pisania programow. Dosy¢ szybko zaczniemy jednak korzysta¢ ze skryptów (zbiorów instrukcji, polece« Scilaba) a nastepnie funkcji. Oczywi±cie niezb¦dne w takich sytuacjach staje si¦ u»ycie edytora tekstu, na przykªad emacs (Unix, Windows), wordpad (Windows), vi lub vim (Unix)... Scilab posiada ak- tualnie wªasny, zintegrowany edytor (scipad), który mo»e równie» sªó»y¢ jako debuger dla funkcji. 1.4 Gdzie znale¹¢ informacje na temat Scilaba? W dalszej cz¦±ci dokumentu zakªada si¦, i» czytelnik dysponuje wersj¡ 4.0 programu. W celu uzyskania dodatkowych informacji odsyªam do Scilab home page: http://scilabsoft.inria.fr na której znale¹¢ mo»na ró»norodn¡ dokumentacj¦ oraz efekty pracy innych u»ytkowników. Scilab group wydaªa (w latach 1999 2001) okoªo dwudziestu artykuªów w czasopi±mie Linux magazie. S¡ one szczególnie polecane przez autora, gdy» poruszaj¡ wi¦kszo±¢ zagadnie« zwi¡zanych z Scilabem (wiekszo±ci z nich w tym opracowaniu nawet si¦ nie porusza). Uzyska¢ je mo»na pod adresem http://www.saphir-control.fr/articles/ Na temat Scilaba prowadzone jest równie» forum dyskusyjne, w ramach którego istnieje mo»liwo±¢ zadawania pyta«, dokonywania uwag, udzielania odpowiedzi na wcze±niej postawione pytania, itd: comp.sys.math.scilab Wszystkie zamieszczone tam wiadomo±ci s¡ archiwizowane i dostepne ze strony Scilab newsgroup archive. Wybieraj¡c jeden z dwóch odsyªaczy Books and Articles on Scilab lub Scilab Related Links umieszczonych na stronie gªównej uzyskujemy dost¦p do wielu ró»nych domowej Scilaba po wybraniu dokumentów. W szczególnosci: wprowadzenie B. Ycart (Démarrer en Scilab et statistiques en Scilab); Scilab Bag Of Tricks autorstwa Lydia E. van Dijk i Christoph L. Spiel, który jest raczej przeznaczony dla osób dobrze znajacych ju» Scilaba (rozwój tej ksi¡»ki zostaª niestety brutalnie przerwany kilka lat temu); Travaux Pratiques sur Scilab classes par themes umo»liwia dost¦p do projektów realizowanych przez studentøw ENPC; wprowadzenie do informatyki z u»yciem Scilab-a (verb+http://kiwi.emse.fr/SCILA Oczywi±cie w zale»no±ci od potrzeb znale¹¢ mo»na wiele innych opracowa« traktuj¡cych problem w nieco odmienny ni» zamieszczony tutaj sposób. 7 1.5 Jaki jest statut programu Scilab? Osoby dobrze znaj¡ce oprogramowanie na licencji GPL z pewno±ci¡ interesuje statut Scilaba jako programu darmowego. Oto jak na ten temat wypowiada si¦ Doc na forum: Scilab: is it really free? Yes it is. Scilab is not distributed under GPL or other standard free soft- ware copyrights (because of historical reasons), but Scilab is an Open Source Software and is free for academic and industrial use, without any restrictions. There are of course the usual restrictions concerning its redistribution; the only specic requirement is that we ask Scilab users to send us a notice (email is enough). For more details see Notice.ps or Notice.tex in the Scilab package. Answers to two frequently asked questions: Yes, Scilab can be included a commercial package (provided proper copyright notice is included). Yes, Scilab can be placed on commercial CD's (such as various Linux distributions). Nie mniej jednak Scilab obecnie nie odpowiada kryteriom FSF czy OSI aby móc by¢ traktowany jako program darmowy ze wzgl¦du na to, »e nie mo»na rozprowadz¢ wersji zmodykowanych (bez autoryzacji ze strony INRIA). Mimo to, dzi¦ki swojemu statutowi, Scilab pozostanie w przyszªo±ci programem darmowym wraz ze swoimi plikami ¹ródªowymi. Z drugiej strony zanosi si¦ na to, »e korsorcjum Scilab-a otrzyma licencj¦ typu GPL lub LGPL patrz CECILL, i »e ... tutu 8 Rozdziaª 2 Operacje na macierzach i wektorach Ta cz¦±¢ daje podstawy do poznania zastosowa« Scilaba jako narz¦dzia do operacji macierzowych. Aby rozpocz¡¢ prac¦ ze Scilaben wystarczy wpisa¢ scilab w terminalu1 Je±li wszystko przebiega prawidªowo, na ekranie uka»e si¦ okno Scilaba z gªównym menu zawieraj¡cym w szczególno±ci przyscisk Help, Demos a w oknie wprowadzania polece« uka»e si¦ ------------------------------------------scilab-4.0 Copyright (c) 1989-2006 Consortium Scilab (INRIA, ENPC) ------------------------------------------Startup execution: loading initial environment --> gdzie 2.1 --> jest znakiem zach¦ty. Wprowadzanie macierzy Podstawowym typem danych w Scilabie jest macierz liczb rzeczywistych lub zespolonych. Najprostszym sposobem deniowania macierzy (wektora, skalara b¦d¡cych w istocie szczególnymi przypadkami macierzy) w ±rodowisku Scilab jest wprowadzenie z klawiatury listy elementów macierzy, stosuj¡c nast¦puj¡c¡ konwencj¦: elementy tego samego wiersza oddzielone s¡ spacj¡ lub przecinkiem; lista elementów musi by¢ uj¦ta w nawias kwadratowy []; ka»dy wiersz, z wyj¡tkiem ostatniego, musi by¢ zako«czony ±rednikiem. Dla przykªadu komenda: -->A=[1 1 1;2 4 8;3 9 27] da na wyj±ciu 1 Albo klikn¡c odpowiedni¡ ikon¦. 9 A ! ! ! = 1. 2. 3. 1. 4. 9. 1. ! 8. ! 27. ! i oczywiscie macierz zostanie zachowana w pami¦ci. W przypadku, gdy in- strukcja zostanie zako«czona ±rednikiem, wynik nie pojawi si¦ na ekranie. Wpiszmy na przykªad -->b=[2 10 44 190]; aby zobaczy¢ wspóªrz¦dne wprowadzonego wektora, wystarczy napisa¢ -->b a odpowiedzi¡ b¦dzie b = ! 2. 10. 44. 190. ! Bardzo dªuga instrukcja mo»e by¢ napisana w kilku liniach, przy czym przechodz¡c do nast¦pnej linii, lini¦ poprzedni¡ nale»y zako«czy¢ trzema kropkami, jak w poni»szym przykªadzie: -->T = [ 1 0 0 0 0 0 --> 1 2 0 0 0 0 --> 1 2 3 0 0 0 --> 1 2 3 0 0 0 --> 1 2 3 4 0 0 --> 1 2 3 4 5 0 --> 1 2 3 4 5 6 ;... ;... ;... ;... ;... ;... ] co daje T ! ! ! ! ! ! = 1. 1. 1. 1. 1. 1. 0. 2. 2. 2. 2. 2. 0. 0. 3. 3. 3. 3. 0. 0. 0. 4. 4. 4. 0. 0. 0. 0. 5. 5. 0. 0. 0. 0. 0. 6. ! ! ! ! ! ! W przypadku wprowadzania liczb zespolonych stosuje si¦ nast¦puj¡c¡ skªadnie: -->c=1 + 2*%i c = 1. + 2.i -->Y = [ 1 + %i , -2 + 3*%i ; -1 , %i] Y = ! 1. + i - 2. + 3.i ! ! - 1. i ! 2.2 Typowe wektory i macierze Istniej¡ funkcj¦ do konstrukcji typowych macierzy i wektorów zatem przedstawiam tu jedn¡ z pierwszych list (jest ich wi¦cej, o których mówimy w dalszej cz¦±ci lub które mo»na znale¹¢ w Pomocy). Macierz jednostkowa Aby otrzyma¢ macierz jednostkow¡ o wymiarach 4 na 4 stosujemy instrukcj¦: 10 -->I=eye(4,4) I = ! 1. 0. ! 0. 1. ! 0. 0. ! 0. 0. 0. 0. 1. 0. Argumentami funkcji : je»eli n<m 0. ! 0. ! 0. ! 1. ! eye(n,m) (odpowiednio jest liczba wierszy (n) oraz kolumn (m) (Uwaga n > m) wówczas otrzymamy macierz odwzorowa- nia wzajemnie jednoznacznego, surjekcja (odpowiednio injekcja) przestrzeni kanonicznej Km na Kn.) Macierz diagonalna, wyciecie cz¦±ci diagonalnej macierzy Aby otrzyma¢ macierz diagonaln¡, w której elementy na gªównej przek¡tnej pochodz¡ z wcze±niej zdeniowanego wektora -->B=diag(b) B = ! 2. 0. ! 0. 10. ! 0. 0. ! 0. 0. Uwaga: Pisz¡c 0. 0. 44. 0. b 0. 0. 0. 190. b wpisujemy ! ! ! ! nadal mamy dost¦p do wcze±niej zdeniowanego wektora, co pokazuje, »e Scilab rozró»nia wielko±¢ liter. Zastosowanie na macierzy funkcji diag pozwala uzyska¢ gªówn¡ przek¡tn¡ macierzy jako wektor kolumnowy -->b=diag(B) b = ! 2. ! ! 10. ! ! 44. ! ! 190. ! (Funkcja ta przyjmuje tak»e drugi, opcjonalny, argument porównaj ¢wiczenia.) Macierze zerowa i jedynkowa zeros i ones pozwalaj¡ odpowiednio stworzy¢ macierze zerowe i macierze skªadaj¡ce si¦ z jedynkek. Podobnie jak dla funkcji eye ich argumentami s¡ Fnkcje liczba wierszy i liczba kolumn. -->C = ones(3,4) C = ! 1. 1. 1. ! 1. 1. 1. ! 1. 1. 1. 1. ! 1. ! 1. ! Mo»na tak»e u»y¢ jako argument nazw¦ macierzy ju» zdeniowanej w ±rodowisku. W efekcie otrzymujemy macierz o takich samych wymiarach co macierz b¦d¡ca argumentem -->O = zeros(C) O = ! 0. 0. 0. ! 0. 0. 0. ! 0. 0. 0. 0. ! 0. ! 0. ! 11 Macierz trójk¡tna triu i tril pozwalaj¡ -->U = triu(C) U = ! 1. 1. 1. 1. ! ! 0. 1. 1. 1. ! ! 0. 0. 1. 1. ! Funcje otrzyma¢ macierz trójk¡tn¡ górn¡ i doln¡: Macierze o elementach losowych Funkcja rand pozwala utworzy¢ macierz o elementach peudolosowych (pochodz¡- cych z przedziaªu [0,1); mo»liwe jest tak»e u»ycie rozkªadu normalnego jak i podanie zarodka dla generatora liczb pseudolosowych): -->M = rand(2, 6) M = ! 0.2113249 0.0002211 ! 0.7560439 0.3303271 0.6653811 0.6283918 0.8497452 0.6857310 0.8782165 0.0683740 0.5608486 ! 0.6623569 ! n elementowy wektor o staªej ró»nicy mi¦dzy elementami x o n wspóªrz¦dnych równomiernie rozmieszczonych pomi¦dzy x1 i xn (innymi sªowy tak aby xi+1 xi = xnn 1x1 , n w¦zªów, zatem n 1), u»ywamy funkcji linspace. -->x = linspace(0,1,11) x = ! 0. 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1. ! Aby wprowadzi¢ wektor (wierszowy) Instrukcj¡ analogiczn¡ pozwalaj¡c¡ utworzy¢ wektor o zadanej warto±ci pierwszej wspóªrz¦dnej, ustalonej ró»nicy pomi¦dzy wspóªrz¦dnymi i ostatniej wspóªrz¦dnej nie wi¦kszej ni» zadana warto±¢ jest -->y = 0:0.3:1 y = ! 0. 0.3 0.6 0.9 ! Skªadnia jest nast¦puj¡ca y = wartosc_poczatkowa:przyrost:wartosc_graniczna. Dok¡d pracujemy z liczbami caªkowitymi nie ma problemu z ustaleniem warto±ci granicznej odpowiadaj¡cej ostatniej skªadowej wektora. -->i = 0:2:12 i = ! 0. 2. 4. 6. 8. 10. 12. ! Dla liczb rzeczywistych jest to zdecydowanie trudniejsze do okre±lenia: (i) przyrost mo»e posiad¢ niesko«czone rozwini¦cie w reprezentacji binarnej lub jego sko«czone rozwini¦cie mo»e wybiega¢ poza zakres reprezentacji maszynowej liczb rzeczywistych powoduj¡c ich zaokr¡glenia; (ii) bª¦dy zaokr¡gle« numerycznych kumuluj¡ si¦ w miar¦ obliczania kolejnych skªadowych wektora. -->xx = 0:0.05:0.60 ans = ! 0. 0.05 0.1 0.15 0.2 0.25 0.3 0.35 0.4 0.45 0.5 0.55 ! Uwaga: w zale»no±ci od komputera na jakim uruchomiony zostanie Scilab powy»szy przykªad mo»e da¢ ró»nie wyniki, to znaczy 0:6 mo»e pojawi¢ si¦ jako ostatnia skªadowa. Cz¦sto przyrost równy jest 1, mo»na go w takiej sytuacj pomin¡¢: 12 -->ind = 1:5 ind = ! 1. 2. 3. 4. 5. ! W przypadku gdy przyrost jest dodatni (ujemny) oraz wartosc_poczatkowa>wartosc_gra (wartosc_poczatkowa<wartosc_granczna) otrzymujemy wektor bez wspóªrz¦dnych (!) nazywany w Scilabie macierz¡ pust¡ (patrz sekcja niektóre dodatkowe proste macierze): -->i=3:-1:4 i = [] -->i=1:0 i = [] 2.3 Wyra»enia w Scilabie Scilab jest j¦zykiem posiadaj¡cym bardzo prost¡ skªadni¦ (patrz rozdziaª nast¦pny), w której instrukcja przypisania ma posta¢ zmienna = wyrazenie lub pro±ciej wyrazenie gdzie w ostatnim przypadku warto±¢ zmiennej o nazwie ans. wyrazenia jest przypisana do domy±lnej Wyra»enia w Scilabie mog¡ by¢ tak proste (je±li chodzi o zapis) jak wyra»enia skalarne w innych j¦zykach programowania, ale mog¡ skªada¢ si¦ z macierzy i wektorów co cz¦sto sprawia trudno±¢ pocz¡tkujacym u»ytkownikom tego j¦zyka. Dla wyra»e« skalarnych mamy standardowe operatory +, -, * , / i ^ i najcz¦±ciej stosowane funkcje przedstawione w tabeli2 2.1. Deniuj¡c zmienn¡ (b¦d¡c¡ skalarem, wektorem, macierz¡) jej warto±¢ (warto±ci) nie musi by¢ wyra»ona przez konkretn¡ liczb¦, ale tak»e przez wyra»enie którego warto±¢ zostanie jej przypisana. -->M = [sin(%pi/3) sqrt(2) 5^(3/2) ; exp(-1) cosh(3.7) (1-sqrt(-3))/2] M = ! 0.8660254 1.4142136 11.18034 ! ! 0.3678794 20.236014 0.5 - 0.8660254i ! Uwaga: Powy»szy przykªad ilustruje potencjalne niebezpiecze«stwo podczas obliczania pierwiastka kwadratowego z liczy ujemnej. Scilab rozwa»a czy ma do czynienia z liczbami zespolonymi i zwraca jeden z pierwiastów jako rezultat. 2.3.1 Kilka podstawowych przykªadów wyra»e« macierzowych Dost¦pne s¡ wszystkie proste dziaªania wykonywane na macierzach: suma dwóch macierzy, iloczyn macierzy, iloczyn skalarny i macierzowy itd. Oto kilka przykªadów (w których wykorzystujemy wcze±niej zdeniowane macierze). Uwaga: Tekst wyst¦pujacy w danym wierszu po znaku // oznacza dla Scilab-a komentarz. Nie jest interpretowany a jedynie dostarcza pewnych uwag i wyja±nie« osobie czytaj¡cej kod. 2 Scilab dysponuje innymi funkcjami matematycznymi takimi jak funkcje Legendra, funkcje Bessela, funkcje eliptyczne, itd. . . oraz funkcje odnosz¡ce sie do znanych rozkªadów prawdopodobie«stwa (dystrybuanty i ich odwrotno±ci) 13 abs exp log log10 cos sin sinc tan cotg acos asin atan cosh sinh tanh acosh asinh atanh sqrt floor ceil int erf erfc gamma lngamma dlgamma warto±¢ bezwzgl¦dna, moduª eksponent logarytm naturalny logarytm o podstawie 10 cosinus (argument w radianach) sinus (argument w radianach) sin(x) x tangente (argument w radianach) cotangente (argument w radianach) arccos arcsin arctg cosinus hiperboliczny sinus hiperboliczny tangens hiperboliczny argch argsh argth pierwiastek kwadratowy E (x) = (bxc) = n , n x < n + 1; x2N dxe = n , n 1 < x n; x 2 N int(x) = bxc je±li x > 0 oraz = dxe dla x 0 2 R x e t2 dt funkcja bª¦du erf (x) = p 0 R dopeªnienie funkcji bª¦du okre±lone przez ercf (x) = 1 erf (x) = p2 x+1 e t2 dt R (x) = 0+1 tx 1 e t dt ln( (x)) d dx ln( (x)) Tablica 2.1: Wybrane funkcj u»ywane przez Scilaba. -->D = A + ones(A) D = ! 2. 2. 2. ! 3. 5. 9. ! 4. 10. 28. // napisz A aby zobaczyc wczesniejsza zawartosc macierzy ! ! ! -->A + M // nie mozna wykonac dzialania dodawania (niezgodnosc wymiaro !--error 8 inconsistent addition -->E = A*C E = ! 3. 3. ! 14. 14. ! 39. 39. // C jest macierza (3,4) zlozona z elementow o wartosci 1.0 3. 14. 39. 3. ! 14. ! 39. ! --> C*A // nie mozna wykonac mnozenia (niezgodnosc wymiarow): jaka jest odpowied !--error 10 inconsistent multiplication --> At = A' // transpozycje otrzymuje sie stawiajac za nazwa macierzy znak apostr 14 At ! ! ! = 1. 1. 1. --> Ac ! ! ! Ac = A + %i*eye(3,3) = 1. + i 1. 2. 4. + i 3. 9. 2. 4. 8. 3. ! 9. ! 27. ! // tworzymy macierz o elementach zespolonych 1. 8. 27. + i ! ! ! --> Ac_adj = Ac' // w ten sposob otrzymujemy macierz transponowana o elementach ze Ac_adj = ! 1. - i 2. 3. ! ! 1. 4. - i 9. ! ! 1. 8. 27. - i ! -->x = linspace(0,1,5)' // konstrukcja wektora kolumnowego x = ! 0. ! ! 0.25 ! ! 0.5 ! ! 0.75 ! ! 1. ! -->y = y = ! 1. ! 2. ! 3. ! 4. ! 5. (1:5)' // inny wektor kolumnowy ! ! ! ! ! -->p = y'*x p = 10. -->Pext = Pext = ! 0. ! 0. ! 0. ! 0. ! 0. --> Pext ans = ! 0. ! 0. ! 0. ! 0. ! 0. // iloczyn skalarny wektorow x i y y*x' // otrzymujemy macierz 5x5 rzedu 1, dlaczego? 0.25 0.5 0.75 1. 1.25 / 0.25 1. 2. 3. 4. 5. 0.5 1. 1.5 2. 2.5 0.75 1.5 2.25 3. 3.75 1. 2. 3. 4. 5. ! ! ! ! ! // macierz mozna podzielic przez skalar 2. 4. 6. 8. 10. 3. 6. 9. 12. 15. 4. 8. 12. 16. 20. 15 ! ! ! ! ! --> A^2 ans = ! 6. ! 34. ! 102. // podniesienie do potegi drugiej macierzy 14. 90. 282. 36. ! 250. ! 804. ! --> [0 1 0] * ans // mozna uzyc zmiennej ans, ktora zawiera wynik ostatniego dzi --> // przypisany do zadnej zmiennej ans = ! 34. 90. 250. ! --> Pext*x - y + rand(5,2)*rand(2,5)*ones(x) + triu(Pext)*tril(Pext)*y; --> // wpisz ans aby zobaczyc wynik Inn¡, bardzo interestuj¡c¡ cech¡ charakterystyczn¡, jest mo»liwo±¢ podania jako argumentu dla funkcji (z tabeli 2.1) macierzy zamiast kolejnych jej ele- f(A) oznacza obliczenie warto±ci A; otrzymamy sób macierz [f (aij )]. mentóws. Innymi sªowy wpisanie instrukcji funkcji f na kolejnych elementach macierzy Przykªady: -->sqrt(A) ans = ! 1. ! 1.4142136 ! 1.7320508 1. 2. 3. -->exp(A) ans = ! 2.7182818 ! 7.3890561 ! 20.085537 2.7182818 54.59815 8103.0839 1. ! 2.8284271 ! 5.1961524 ! 2.7182818 ! 2980.958 ! 5.320D+11 ! Uwaga: dla funkcji, które maj¡ sens dla macierzy (co innego dla funkcji które stosuje si¦ dla ka»dego elementu macierzy. . . ) na przyklad funkcja eksponent, nazwa funkcji jest poprzedzona liter¡ m w ten sposób aby otrzyma¢ eksponent macierzy A wystarczy wprowadzi¢ komend¦ expm 2.3.2 Dziaªania na elementach macierzy Aby pomno»y¢ lub podzieli¢ dwie macierze, A i B, o tych samych wymiarach, w taki spsób aby wynikiem byªa macierz, równie» o tych samych wymiarach, w której ka»dy element jest iloczynem (ilorazem) odpowiednich elementów macierzy A i B nale»y u»yc operatorów mentach [aij bij ] natomiast A./B .* lub ./. A.*B jest macierz¡ o ele- jest macierz¡ o elementach [aij =bij ]. Podobnie mo»na podnie±¢ do pot¦gi ka»dy z elementów macierzy wpisuj¡c operator A.^p pozwoli otrzyma¢ macierz o wyrazach [apij ]. Rozwa»my przykªad: -->A./A ans = ! 1. 1. 1. ! ! 1. 1. 1. ! ! 1. 1. 1. ! .^: Uwagi: W przypadku gdy A nie jest macierz¡ kwadratow¡ dziaªanie A^n b¦dzie 16 wykonywane na kolejnych elementach macierzy A. Zaleca si¦ jednak stosowanie zapisu A.^n poniewa» jest on bardziej czytelny. Je±li s jest skalarem oraz A jest macierz¡ wówczas s.^A daje macierz o wyrazach saij . 2.3.3 Rozwi¡zywanie ukªadów równa« liniowych Aby rozwi¡za¢ ukªad równa« liniowych gdzie macierz wspóªczynników jest kwadratowa, Scilab stosuje rozkªad LU z cz¦±ciow¡ zamian¡ wierszy prowadz¡c¡ do rozwiazania dwóch trójk¡tnych ukªadów równa«. Jest to jednak operacja niewidoczna dla u»ytkownika dzi¦ki wyko»ystaniu operatora -->b=(1:3)' b = ! 1. ! ! 2. ! ! 3. ! // tworzymy wektor b -->x=A\b x = ! 1. ! ! 0. ! ! 0. ! // rozwiazujemy Ax=b -->A*x - b ans = ! 0. ! ! 0. ! ! 0. ! \: // sprawdzamy poprawnosc wyniku Aby zapami¦ta¢ ten sposób post¦powania, nale»y mie¢ na uwadze ukªad pocz¡tkowy Ax = b a nast¦pnie pomno»y¢ ukªad lewostronnie przez A 1 (co oznacza podzielenie przez macierz A). Sposób ten daje dokªadny wynik, ale w ogólno±ci wys- t¦puj¡ bª¦dy zaokr¡glenia spowodowane arytmetyk¡ liczb zmiennoprzecinkowych. -->R = rand(100,100); // stawiamy srednik na koncu aby uniknac zalewu ekranu licz -->y = rand(100,1); // jak wyzej -->x=R\y; // rozwiazanie ukladu Rx=y -->norm(R*x-y) ans = 1.134D-13 // funkcja norm pozwala obliczyc norme wektorow (macierzy) // (obliczyc mozemy dwie normy -- euklidesowa i hermitea) Uwaga: Nie otrzymacie wyniku identycznego z moim je»eli funkcja rand nie zostanie u»yta tak jak w powy»szym przykªadzie. . . W momencie gdy rozwi¡zanie ukªadu liniowego jest w¡tpliwe, Scilab wy±wietla informacje ostrzegaj¡ce i pozwalaj¡ce podj¡¢ odpowiednie w takiej sytuacji dziaªania. 2.3.4 Indeksowanie, wydobywanie podmacierzy, konkatenacj macierzy i wektorów Aby odniesc si¦ do konkretnego elemetnu macierzy wystarczy przy nazwie poda¢ w nawiasie jego indeksy. Na przykªad: 17 -->A33=A(3,3) A33 = 27. -->x_30 = x(30,1) x_30 = - 1.2935412 -->x(1,30) !--error invalid index 21 -->x(30) ans = - 1.2935412 Uwaga: Je»eli macierz jest wektorem kolumnowym wystarczy jedynie wpisa¢ numer linii, w której znajduje si¦ szukany element; analogicznie post¦pujemy w przypadku wektora wierszowego. Zalet¡ j¦zyka Scilab jest mo»liwo±¢ ªatwego wydobywanie podmacierzy z macierzy wyj±ciowej. -->A(:,2) ans = ! 1. ! ! 4. ! ! 9. ! // aby uzyskac 2 kolumne,... -->A(3,:) // ... 3 wiersz ans = ! 3. 9. 27. ! -->A(1:2,1:2) // podmacierz glowna rzedu 2 ans = ! 1. 1. ! ! 2. 4. ! Omówmy teraz ogóln¡ skªadni¦. Niech macierz dalej v1 = (i1 ; : : : ; ip ) oraz v2 = (j1 ; : : : ; jq ) oznacza macierz o wymiarach odpowiadaj¡cych wierszom -->A([1 3],[2 3]) ans = ! 1. 1. ! ! 9. 27. ! i1 ; i2 ; : : : ; ip ma wymiary (n:m), niech oznaczaj¡ wektory (wierszowe lub kolumnowe), w których warto±ci s¡ takie, »e A(v1,v2) A 1 ik n et 1 jk m, wówczas (p; q) utworzon¡ z wyrazów macierzy A j1 ; j2 ; : : : ; jq . oraz kolumnom -->A([3 1],[2 1]) ans = ! 9. 3. ! ! 1. 1. ! W praktyce dokonujemy prostrzych ekstrakcji, wydobywa si¦ elementy umieszczone w przylegaj¡cych blokach na przykªad w kolumnach lub wierszach. W takim przypadku u»yjemy wyra»enia i_poczatkowe:przyrost:i_koncowe w celu wygenerowania wektora wska¹ników. Natomiast aby wygenerowa¢ peªny ob18 szar odpowiadaj¡cy wymiarowi u»yjemy operatora : (jak wida¢ to w pier- wszym przykªadzie). Zatem aby otrzyma¢ podmacierz zªo»on¡ z 1 i 3 wiersza zastosujemy -->A(1:2:3,:) ans = ! 1. 1. ! 3. 9. // lub inaczej A([1 3],:) 1. ! 27. ! Przejd¹my teraz do operacji konkatencaji macierzy, która umo»liwia poª¡czenie (ustawiaj¡c obok siebie) wiele macierzy w celu otrzymania jednej zwanej macierz¡ blokow¡. Dla przykªadu rozwa»my nast¦puj¡c¡ macierz podzielon¡ 01 2 3 4 1 B 1 4 9 16 C A=B @ 1 8 27 64 C A na bloki: = 1 16 81 256 Nale»y zatem zdeniowa¢ podmacierze -->A11=1; A11 A12 A21 A22 : A11 ; A12 ; A21 ; A22 : -->A12=[2 3 4]; -->A21=[1;1;1]; -->A22=[4 9 16;8 27 64;16 81 256]; ostatecznie otrzymujemy macierz -->A=[A11 A12; A = ! 1. 2. 3. ! 1. 4. 9. ! 1. 8. 27. ! 1. 16. 81. A21 A22] 4. 16. 64. 256. A powstaª¡ z poª¡czenia 4 bloków: ! ! ! ! Z punktu widzenia syntaktyki, macierze blokowe traktowane s¡ jak zwykªe skalary (nale»y przy tym oczywi±cie pami¦ta¢ o zgodno±ci wymiarów odpowidnich macierzy blokowych). Istnieje odr¦bna skªadnia sªu»¡ca do jenoczesnego usuni¦cia z macierzy wierszy lub kolumn: niech v = (k1 ; k2 ; : : : ; kp numerów wierszy lub kolumn macierzy usuni¦cie wierszy o numerach usunie kolumny kolumnowym), k1 ; k2 ; : : : ; kp . u(v)=[] b¦dzie wektorem skªadaj¡cym si¦ z M. k1 ; k2 ; : : : ; kp Polecenie z macierzy Ponadto je±li u M(v,:)=[] M, spowoduje natomiast M(:,v)=[] jest wektorem (wierszowym lub usunie odpowiednie skªadowe. Kolejno±¢ elementów macierzy Macierze w Scilabie s¡ skªadowane kolumna za kolumn¡ i ta kolejno±¢ elementów wykorzystywana jest w wielu funkcjach (porównaj dla przykªadu polecenie matrix, która umo»liwia zmian¦ wymiarów macierzy). W szczegól- no±ci dla operacji wstawiania i wydobywania mo»liwe jest u»ycie domy±lnego porz¡dku przy wykorzystaniu jednynie pojedy«czego wektora indeksów (w miejsce dwóch, jako wska¹nik kolumn lub wierszy). opartych na wcze±niej zdeniowanej macierzy -->A(5) ans = 19 A: Oto kilka przykªadów 2. -->A(5:9) ans = ! 2. ! ! 4. ! ! 8. ! ! 16. ! ! 3. ! -->A(5:9) A = ! 1. ! 1. ! 1. ! 1. 2.4 = -1 1. 1. 1. 1. // spowoduje wstawienie elementu o wartosci -1 - 1. 9. 27. 81. 4. 16. 64. 256. ! ! ! ! Informacje na temat ±rodowiska pracy(*) Wystarczy wpisa¢ who a otrzymamy w ten sposób nast¦puj¡ce informacje -->who your variables are... Anew A A22 A21 A12 A11 x_30 A33 x y R b Pext p Ac_adj Ac At E D cosh ind xx i linspace M U O zeros C B I Y c T startup i scicos_pal home PWD TMPDIR percentlib fraclablib soundlib xdesslib utillib tdcslib siglib s2flib roblib optlib m elemlib commlib polylib autolib armalib alglib mtlblib SCI % %T %z %s %nan %inf old newstacksize $ %t %f %eps %io %i %e %pi using 14875 elements out of 1000000. and 75 variables out of 1023 Zmienne, które zostaªy wprowadzone Anew, A,A22, A21, ...,b w porz¡dku odwrotnym do ich wczytywania. Wªa±ciwie pierwsz¡ utworzon¡ zmienn¡ byªa macierz A ale powi¦kszyli±my jej wymiar (z (3,3) do (4,4)) w przykªadzie prezentuj¡cym konkatenacj¦ macierzy. W takim przypadku zmienna pocz¡tkowa zostaje zast¡piona now¡ zmienn¡. O tym istotnym fakcie powiemy jeszcze przy okazcji omawiania programowania w Scilab-ie; Nazwy bibliotek Scilab-a (posiadaj¡cych rozszerzenie lib) i funkcji: cosh. To znaczy funkcje (te opisane w j¦zyku Scilab-a) oraz biblioteki traktowane s¡ przez Scilaba jak zmienne. Uwaga: Procedury w Scilabie zaprogramowane w Fortran 77 i C nazywane s¡ prymitywami Scilaba i nie s¡ uwa»ane za zmienne w Scilabie. W dalszej cz¦±ci tego dokumentu u»ywa si¦ czasem przesadnie sformuªowania prymityw aby zaznaczy¢ funkcje Scilab-a (programów w j¦zyku Scilab), które s¡ zawarte w standardowo dost¦pnym ±rodowisku. Staªe predeniowane, takie jak , e i i inne staªe, klasyczne w arytmetyce zmiennoprzecinkowej: a number, inf 1. Zmienne, których nazwa poprzedzona 20 eps oraz dwie nan - ang. not jest znakiem % epsilon maszynowy nie mog¡ zosta¢ usuni¦te. Bardzo istotna zmienna newstacksize okre±laj¡ca rozmiar stosu (to znaczy ilo±¢ dost¦pnej pami¦ci). Na koniec wy±wietlona zostaje informacja o ilo±ci u»ytych sªów 8 bitowych w odniesieniu do ich caªkowitej (dost¦pnej) ilo±ci a nast¦pnie ilo±¢ u»ytych zmiennych w stosunku do maksymalnej dozwolonej ich ilo±ci. Rozmiar stosu mo»na zmieni¢ za pomoc¡ polecenia nbmots oznacza nowy po»¡dany rozmiar. stacksize(nbmots) gdzie Ta sama komenda bez argumentu pozwala uzyska¢ rozmiar stosu mieszcz¡cy maksymaln¡ dopuszczaln¡ liczb¦ zmiennych. Tak wi¦c chc¡c usun¡¢ wektor pami¦ci nale»y u»y¢ polecenia v1 ze ±rodowiska a wi¦c zwolni¢ miejsce w clear v1. Polecenie clear u»yte bez argumentu usunie wszystkie zmienne. Chc¡c natomiast usun¡c wi¦cej ni» jedn¡ zmienn¡ mo»a poda¢ ich nazwy jako kolejne argumenty polecenia clear v1 v2 v3. 2.5 clear, na przykªad: Wywoªanie pomocy z linii polece« Pomoc mo»na otrzyma¢ wybieraj¡c przycisk od wersji 2 :7 Help z menu okna Scilab. Pocz¡wszy 3 strony pomocy s¡ w formacie HTML . Wpisuj¡c polecenie help (lub klikaj¡c na przycisk Help) pojawi si¦ strona HTML zawieraj¡ca odno±niki do wszystkich stron pomocy (Scilab and Elementary functions,...). Programming, Graphic Library, Utilities Klikaj¡c na wybran¡ nazw¦ otrzymuje si¦ list¦ szystkich funkcji zwi¡zanych z danym tematem, do ka»dej z nich doª¡czono krótki opis. Wybieraj¡c dan¡ funkcj¦ otrzymuje si¦ stron¦ z pytaniami dotycz¡cymi danej funkcji. Je»eli natomiast znana jest nazwa funkcji wystarczy help nazwa_funkcji w oknie Scilaba aby wej±¢ na odpowiedn¡ Polecenie apropos sªowo_kluczowe wy±wietli wszystkie strony na których wpisa¢ komend¦ stron¦. pojawia si¦ sªowo_kluczowe w nazwach funkcji lub ich opisach. Przeszukiwanie opcji mo»e okaza¢ sie niewygodne, gdy» cz¦sto wiele funkcji zgrupowanych jest pod jedn¡ nazw¡ (na przykªad jako Elementary functions mojetutu wyst¦puje bardzo du»o ró»nych funkcji, które w jakimkolwiek stopniu na t¦ nazw¦ zasªuguj¡); nie wahaj sie zatem u»ywa¢ polecenia 2.6 apropos Generator prostych wykresów Przypu±¢my, »e chcemy narysowa¢ wykres funkcji y = e x sin(4x) dla x 2 [0; 2]. Mo»na zdeniowa¢ podziaª przedziaªu poprzez funkcj¦ linespace -->x=linspace(0,2*%pi,101); a nast¦pnie policzy¢ warto±ci funkcji dla ka»dego elementu podziaªu wykrzystuj¡c w tym celu instrukcj¦ -->y=exp(-x).*sin(4*x); i ostatecznie -->plot(x,y,'x','y','y=exp(-x)*sin(4x)') gdzie trzy ostatnie ªa«cuchy znaków (odpowiednio: opis osi rz¦dnych i odci¦tych oraz nazwa wykresu) s¡ opcjonalne. Instrukcja ta pozwala narysowa¢ krzyw¡ przechodz¡c¡ przez punkty, których wspóªrz¦dne okre±la wektor osi odci¦tych oraz 3 y na osi rz¦dnych. Format podstawowy to XML a z niego otrzymuje si¦ HTML. 21 x na Je»eli punkty ukªadaj¡ si¦ cz¦±ciowo wzdªu» linii prostej wykres b¦dzie tym wierniejszy im wi¦kszej ilo±ci punktów u»yjemy Rysunek 2.1: Prosty wykres. Uwaga: Ta instrukcja jest ograniczona, zatem nie nale»y sugerowa¢ si¦ jedynie tym rozwi¡zaniem. W rozdziale dotycz¡cym graki wprowadza si¦ instrukcje plot2d, 2.7 która jest o wiele lepsza. Pisanie i wykonywanie skryptów Mo»liwe jest wpisanie ci¡gu instrukcji do pliku nazwaPliku i ich wywoªanie poprzez komend¦ -->exec('nazwa_pliku') Prostsz¡ metod¡ jest File okna Scilab. // lub exec nazwa_pliku wybranie pozycji File Operation znajduj¡c¡ si¦ w menu Menu pozwala wybra¢ insteresuj¡cy nas plik (ewentual- nie w celu jego modykazji); aby go wykona¢ wystarczy wybra¢ Exec. przykªad skryptu rozwa»my ponownie wykres funkcji zadaj¡c za ka»dym razem inny rozmiar przedziaªu e x sin(4x) [a; b] i ilo±¢ podprzedzaiªów. zatem w pliku nazywaj¡cym si¦ na przykªad Jako Napiszmy script1.sce nast¦puj¡ce instrukcje // pierwszy skrypt a = input(" Podaj lewy kraniec przyedzialu : "); b = input(" Podaj prawy kraniec przedzialu : "); n = input(" Podaj ilosc podprzedzialow : "); // obliczenie odcietych x = linspace(a,b,n+1); // obliczenie rzednych y = exp(-x).*sin(4*x); // maly rysunek clf() //wyczyszczenie zawartosci okna graficznego plot(x,y,"b") xtitle("x","y","y=exp(-x)*sin(4x)") Uwaga: Aby odnale¹¢ si¦ w naszych plikach Scilab-a zaleca si¦ wykorzysta¢ w *.sce (w by¢ *.scu). nazwie pliku skryptowego rozszerzenie wiera funkcj¦, rozszerzeniem powinno przypadku gdy plik za- Pewne edytory mog¡ by¢ wyposa»one w narz¦dzia specyczne dla edycji w Scilabie (zobacz strona Scialba). Dla emacs istniej¡ dwa, z krórych lep- szy pochodzi od Alexandra Vigodnera, którego najnowsze wersje mo»na znale¼¢ pod adresem http://www.geocities.com/avezunchik/scilab.html 22 2.8 Dodatkowe informacje 2.8.1 Skracanie instrukcji przy zapisie macierzowym Wcze±niej dowiedzieli±my si¦, »e mno»enie macierzy przez skalar (podobnie dzielenie macierzy przez skalar) jest zdeniowane w Scilabie. Natomiast Scilab stosuje uproszcze« mniej oczywistych, takich jak dodawanie skalara i macierzy. M + s gdzie M M + s*ones(M) Wyra»enie jest macierza a s skalarem jest skrótem dla instrukcji to znaczy skalar jest dodany do wszystkich elementów macierzy. Inny skrót: w wyra»eniu typu mencie A./B (oznaczaj¡cym dzielenie element po ele- macierzy o tych samych wymiarach), je»eli A jest skalarem wówczas wyrarzenie to jest skróconym zapisem dla instukcji : A*ones(B)./B otrzymuje sie macierz [a=bij ]. Takie uproszczenia pozwalaj¡ na zapis bardziej f jest x jest wektorem a s jest zmienn¡, wówczas syntetyczny w wielu przypadkach (por. ¢wiczenia). Na przykªad, je±li funkcj¡ zdeniowan¡ w ±rodowisku, s./f(x) x, w którym i-ta wspóªrz¦dna równa wyznaczy¢ wektor o wspóªrz¦dnych 1=f (xi ), jest wektorem tych samych wymiarów co jest s=f (xi ). W ten sposób, aby u»yjemy skªadni : 1./f(x) Taka skªadnia interpretuje 1. jako jedynk¦ i wynik nie b¦dzie wªa±ciwy. Do- brym rozwi¡zaniem aby otrzyma¢ poszukiwany wynik jest uj¦cie liczby w nawias lub oddzielenie liczby spacj¡ : (1)./f(x) // lub takze 1 ./f(x) lub 1.0./f(x) 2.8.2 Pozostaªe uwagi dotycz¡ce rozwi¡zywania ukªadów równa« liniowych (*) 1. W przypadku gdy mamy wi¦cej wyrazów wolnych, mo»na stosowa¢ nast¦puj¡ce polecenie : -->y1 = [1;0;0;0]; y2 = [1;2;3;4]; // przypadek gdy mamy 2 wyrazy wolne ( mozn --> // wiecej instrukcji w jednej lini) -->X=A\[y1,y2] // konkatenacja/zlaczenie y1 i y2 X = ! 4. - 0.8333333 ! ! - 3. 1.5 ! ! 1.3333333 - 0.5 ! ! - 0.25 0.0833333 ! Pierwsza kolumna macierzy X jest rozwi¡zaniem ukªadu równa« 2. natomiast druga jest rozwi¡zaniem ukªadu Ax2 = y 2 . Wcze±niej zobaczyli±my, »e je»eli A jest macierz¡ kwadratow¡ Ax1 = y1 , (n,n) oraz b jest wektorem kolumnowym o n wspóªrz¦dnych (a wi¦c macierz¡ (n,1)) to : x = A\b Ax = b. Je»eli natomiA oka»e sie macie»¡ osobliw¡, Scilab zwróci bª¡d. Na przykªad da nam rozwi¡zanie ukªadu równa« liniowych postaci ast macierz : -->A=[1 2;1 2]; 23 -->b=[1;1]; -->A\b !--error 19 singular matrix Podczas gdy macierz A jest ¹le uwarunkowana (lub ewentualnie ¹le zrównowa»ona) odpowied¹ b¦dzie dostarczona ale wraz z komentarzem w postaci ostrze»enia zawieraj¡cym oszacowanie odwrotno±ci uwarunkowania (cond(A) -->A=[1 2;1 2+3*%eps]; -->A\b warning matrix is close to singular or badly scaled. results may be inaccurate. rcond = 7.4015D-17 ! ! = jjAjj jjA 1 jj): ans = 1. ! 0. ! Z drugiej strony, je»eli macierz nie jest kwadratowa, ale posiada t¦ sam¡ liczb¦ wirszy co wektor wyrazów wolnych, Scilab obliczy rozwi¡zanie (w postaci wektora kolumnowego, którego liczba wspóªrz¦dnych b¦dzie równa liczbie kolumn macierzy A) nie informuj¡c u»ytkownika o bª¦dzie. W efek- cie, je»eli równanie Ax = b nie ma w ogólno±ci rozwi¡zania jednoznacznego 4 , mo»na zawsze wybra¢ wektor x który zwerykuje pewne wªasno±ci (x o minimalne normie i jednocze±nie b¦d¡cy rozwi¡zaniem min jjAx bjj). W tym przypadku takie rozwi¡zanie jest wynikiem dzieªanie innych algorytmów które umo»liwiaj¡ (ewentualne) otrzymanie pseªdo-rozwi¡zania5 . Niedogodno±¢ jest taka, »e jes±li zostanie popeªniony bª¡d podczas deniowania macierzy (na przykªad zdeniowana zaostanie dodatkowa kolumna tak, »e macierz b¦dzie miaªa wymiar (n,n+1)) bª¡d ten nie zostanie wykryty natychmiast. Rozwa»my przykªad : -->A(2,3)=1 A = ! 1. 2. 0. ! ! 1. 2. 1. ! // étourderie -->A\b ans = ! 0. ! ! 0.5 ! ! - 3.140D-16 ! -->A*ans - b ans = 1.0D-15 * ! - 0.1110223 ! 4 A (gdzie n = 6 m), mamy jedno rozwi¡zanie wtedy i tylko wtedy, gdy m > n, f0g i w konsekwencji b 2 ImA ten ostatni warunek jest wyj¡tkiem je±li b jest zadane z góry w Km ; w ka»dym niech (m; n) b¦dzie wymiarem macierzy KerA = innym przypadku albo nie ma »adnego rozwi¡zania albo isnieje niesko«czenie wiele rozwi¡za« 5 w przypadkach trudnych, tzn. takich, gdzie macierz nie ma maksymalnego rz¦du (rg (A) dwuwymiarowe) nale»y wyznaczy¢ rozwi¡zanie korzystaj¡c z pseªdo-odwrotnej macierzy do 24 < min(n; m) gdzie n i m s¡ A (x = pinv(A)*b). ! - 0.1110223 ! Poza zwróceniem naszej uwagi na konsekwencje tego typu zakªuce«, powy»szy przykªad ilustruje nast¦puj¡ce aspekty : x = A\y pozwala rozwi¡za¢ problem mniej kwadratowy (kiedy macierz nie ma maksymalnego rz¦du, nale»y lepiej u»y¢/wyko»ysta¢ x = pinv(A)*b, pseudo-inwersia zostanie obliczona poprzez dekompozycj¦ pojedynczych warto±ci A (t¦ dekompozycj¦ mo»na otrzyma¢ za pomoc¡ instukcji svd)); instrukcja A(2,3)=1 (bª¡d zakªucenia. . . ) jest w rzeczywisto±ci skrótem od : A = [A,[0;1]] A to znaczy Scilab domy±la si¦, »e macierz ma by¢ uzupeªniona (o 3 kolumn¦) ale brakuje mu jednego elementu. W takim przypadku uzupeªni je zerami. element na pozycji (2,2) jest równy 2+3 m . Epsilon maszynowy (m ) ma»e by¢ zdeniowany jako bardzo du»a liczba, dla której 1 m = 1 w arytmetyce zmiennoprzecinkowej6 . W konsekwencji musimy mie¢ 2 3m > 2 aby na ekranie pojawiªa si¦ 2. Wynika to z u»ytego domy±lnie formatu danych, mo»na go jednak zmodykawa¢ u»ywaj¡c instrukcji format : -->format('v',19) -->A(2,2) ans = 2.0000000000000009 W ten sposób zmienimy format domy±lny format('v',10) (patrz Help aby pozna¢ znaczenie argumentów). Rozwi¡zanie ukªadu Ax = b, które nie zostaªo przypisane »adnej konkret- niej zmniennej, jest domy±lnie nazwane ans. Zmienn¡ t¦ mo»na nast¦pnie wyko»ysta¢ do obliczenia warto±ci rezydualnej Ax b. 3. Przy u»yciu Scilaba mo»na równie» odpowiednio rozwi¡za¢ ukªad równa« postaci xA = b gdzie x i b s¡ wektorami wierszowymi, a A jest macierz¡ kwadratow¡ (poprzez transpozycj¦ wracamy do ukªadu klasycznego b> ), wystarczy pomno»y¢ prawostronnie przez A 1 operacji jest prawostronne podzielenie przez macierz x = b/A I podobnie jak poprzednio, je±li A A> x> = (odpowiednikiem tej A) : jest macierz¡ prostok¡tn¡ (gdzie liczba kolumn jest równa liczbie wierszy wektora b), Scilab wyznaczy rozwi¡zanie. 2.8.3 Kilka prostych macierzy (*) Suma, iloczym wspóªczynników macierzy, macierz pusta sum : // 1:6 = [1 2 3 4 5 6] : musiemy zatem otrzymac 6*7/2 = 21 !!!!! Aby zsymowa¢ wspóªczynniki macierzy, u»ywamy funkcji -->sum(1:6) ans = 21. Funckja ta przyjmuje przyjmuje argument dodatkowy dla obliczenia tylko wierszy lub tylko kolumn : 6 ±ci±le mówi¡c wszystkie liczby rzeczywiste zmiennoprzecinkowej j f l(x) nast¦puj¡co : x j j x takie, »e m x M mog¡ by¢ zakodowane/zapisane za pomoc¡ liczby f l(x) m x gdzie m i M s¡ odpowiednio najmniejsz¡ i najwi¦ksz¡ liczb¡ j j j dodatni¡ mo»liw¡ do zakodowania za pomoc¡ virgule ottante normalisée 25 -->B = [1 2 3; 4 5 6] B = ! 1. 2. 3. ! ! 4. 5. 6. ! -->sum(B,"r") // oblicza sume wyrazów w poszczegolnych kolumnach //otrzymujemy wektor wierszowy postaci ans = ! 5. 7. 9. ! -->sum(B,"c") // oblicza sume wyrazow w poszczegolnych wierszach // otrzymujemy wektor kolumnowy postaci ans = ! 6. ! ! 15. ! Jednym z wyj¡tkowo u»ytecznych obiektów jest macierz pusta któr¡ deniuje sie nast¦puj¡co : -->C =[] C = [] Macierz ta ma nast¦puj¡ce wªasno±ci :[] sum -->sum([]) ans = 0. funkcj¦ + A = A i []*A = []. Stosuj¡c teraz do macierzy pustej otrzymujemy naturalnie rezultat : wedªug matematycznej konwencji sumowania : S= je»eli E X i2E ui = n X i=1 ui jest zbiorem pustym wówczas gdy E = f1 ; 2 ; : : : ; n g S = 0 W analogiczny sposób, aby otrzy- ma¢ iloczyn elementów macierzy, stosuje sie funkcj¦ -->prod(1:5) ans = 120. // otrzymujemy 5! = 120 -->prod(B,"r") // napisz B aby zobczyc macierz... ans = ! 4. 10. 18. ! -->prod(B,"c") ans = ! 6. ! ! 120. ! -->prod(B) ans = 720. -->prod([]) ans = 26 prod : 1. wynik otrzymuje si± zgodnie z konwencj¡ znan¡ w matematyce : Y i2E ui = 1; si E = ;: Suma i iloczyn skumulowany Funkcje cumsum i cumprod obliczaj¡ odpowiednio sum¦ i iloczyn skumiulowany macierzy lub wektora : -->x = 1:6 x = ! 1. 2. 3. 4. -->cumsum(x) ans = ! 1. 3. 6. 10. 15. -->cumprod(x) ans = ! 1. 2. 6. 24. 120. 5. 6. ! 21. ! 720. ! Dla macierzy kumulowanie dokonuje si± zazwyczja jedynie w porz¡dku kolumnowym : -->x = [1 2 3;4 5 6] x = ! 1. 2. 3. ! ! 4. 5. 6. ! -->cumsum(x) ans = ! 1. 7. ! 5. 12. 15. ! 21. ! Podobnie jak w przypadku funkcji sum i prod, mo»na dokonywa¢ kumulowania wedªug wierszy i kolumn : -->cumsum(x,"r") // suma skumulowana wedlug kolumn ! ans = ! 1. 2. 3. ! ! 5. 7. 9. ! -->cumsum(x,"c") // suma skumulowana wedlug wierszy ! ans = ! 1. 3. 6. ! ! 4. 9. 15. ! Pojawia si¦ tutaj pozorna niezgodno±¢ pomi¦dzy nazw¡ a sposobem dokonywania oblicze« na wierszach i kolumnach7 : dla funkcji sum i prod argument informuje o ostatecznej formie otrzymanego wyniku (sum(x,»") pozwala otrzy- ma¢ wektor wierszowy (r jak row, ang. wiersz) a wi¦c sum¦ ka»dej kolumny) lecz 7 sum, prod, cumsum, cumprod, mean, st_deviation, min, max 27 minimum i maksimum wektora i macierzy Najmniejsz¡ i najwi¦ksz¡ warto±¢ wektora lub macierzy mo»na wyznaczy¢ posªuguj¡c si¦ funkjami funkcji sum i prod min i max. Ich dziaªanie jest takie jak w przypadku gdzie dodatkowy argument okre±la czy minimum lub mak- simum ma by¢ wyznaczone dla wiersza czy dla kolumny. Dodatkowo mo»liwe jest znalezienie wska¹nika dla miejsca w któtym znajduje sie owo minimum lub maksimum. Przykªady : -->x = rand(1,5) x = ! 0.7738714 0.7888738 0.3247241 0.4342711 0.2505764 ! -->min(x) ans = 0.2505764 -->[xmin, imin] = min(x) imin = 5. // min jest osiagniete w x(5) xmin = 0.2505764 -->y = rand(2,3) y = ! 0.1493971 0.475374 ! 0.1849924 0.1413027 0.8269121 ! 0.7530783 ! -->[ymin, imin] = min(y) imin = ! 2. 2. ! // min jest osiagniete dla y(2,2) ymin = 0.1413027 -->[ymin, imin] = min(y,"r") // minimum kazdej kolumny imin = ! 1. 2. 2. ! // => min to y(1,1) y(2,2) y(2,3) ymin = ! 0.1493971 0.1413027 0.7530783 ! -->[ymin, imin] = min(y,"c") // minimum kazdego wiersza imin = ! 1. ! // min to y(1,1) ! 2. ! // y(2,2) ymin = ! 0.1493971 ! ! 0.1413027 ! ±rednia i odchylenie standardowe Funkcje mean i st_deviation pozwalaj¡ wyznaczy¢ ±redni¡ i odchylenie standar- dowe wspóªrz¦dnych wektora lub macierzy. Formuªa u»ywana dla odchylenia 28 standardowego jest nast¦puj¡ca : -->x = 1:6 x = ! 1. 2. n 1 X (x) = (x n 1 i=1 i 3. 4. 5. x)2 !1=2 ; x = n 1X x n i=1 i 6. ! -->mean(x) ans = 3.5 -->st_deviation(x) ans = 1.8708287 Podobnie mo»na wyznaczy¢ ±redni¡ (a tak»e odchylenie standardowe) wiersza lub kolumny macierzy : -->x = [1 2 3;4 5 6] x = ! 1. 2. 3. ! ! 4. 5. 6. ! -->mean(x,"r") ans = ! 2.5 3.5 -->mean(x,"c") ans = ! ! // srednia wyrazow kazdej z kolumn macierzy 4.5 ! // srednia kazdego z wierszy 2. ! 5. ! Przeksztaªcenie macierzy Funkcja matrix umo»liwia takie przeksztaªcenie macierzy aby miaªa ona nowe wymiary (przy zachowaniu tych samych wspóªczynników). -->B = [1 2 3; 4 5 6] B = ! 1. 2. 3. ! ! 4. 5. 6. ! -->B_new = matrix(B,3,2) B_new = ! 1. 5. ! ! 4. 3. ! ! 2. 6. ! Jest to mo»liwe dzi¦ki temu, »e wspóªczynniki macierzy zapami¦tywane s¡ kolumnowo. Jednym z zastowowa« funkcji wierszowego na kolumnowy i odwrotnie. 29 v : jest transpozycja wektora A zamieniaj¡c (wektory v = A(:), przykªad : pozwala ona tak»e przeksztaªci¢ macierz kolumnowe) na wektor kolumnowy matrix Nale»y zaznaczy¢, »e w ogólno±ci wierszowe i -->A = rand(2,2) A = ! 0.8782165 0.5608486 ! ! 0.0683740 0.6623569 ! -->v=A(:) v = ! 0.8782165 ! 0.0683740 ! 0.5608486 ! 0.6623569 ! ! ! ! Wektory z post¦pem logarytmicznym Czasami istnieje potrzeba operownia wektorem którego wspóªrz¦dne stanowi¡ post¦p logarytmiczny (tzn. :xi +1 =xi = Cte): takie, »e stosunek dwuch s¡siednichc jest staªy mo»na u»y¢ w tym przypadku funkcj¦ logspace : logspace(a,b,n): n wspóªrz¦dnych w którym pierwsza i os10a i 10b , np: pozwalaj¡c¡ otrzyma¢ taki wektor o tatnia wsóªrz¦dna s¡ odpowiednio -->logspace(-2,5,8) ans = ! 0.01 0.1 1. 10. 100. 1000. 10000. 100000. ! Warto±ci i wektory wªasne spec pozwala obliczy¢ -->A = rand(5,5) A = ! 0.2113249 0.6283918 ! 0.7560439 0.8497452 ! 0.0002211 0.6857310 ! 0.3303271 0.8782165 ! 0.6653811 0.0683740 Funkcja warto±ci wªasne macierzy (kwadratowej!) : 0.5608486 0.6623569 0.7263507 0.1985144 0.5442573 0.2320748 0.2312237 0.2164633 0.8833888 0.6525135 0.3076091 0.9329616 0.2146008 0.312642 0.3616361 ! ! ! ! ! -->spec(A) ans = ! 2.4777836 ! ! - 0.0245759 + 0.5208514i ! ! - 0.0245759 - 0.5208514i ! ! 0.0696540 ! ! 0.5341598 ! oraz wy±wietla wyniki w postaci wektora kolumnowego (Scilab stosuje metod¦ QR polegaj¡c¡ na interacyjnej dekompozycji) Schur macierzy). Wektory wªasne mog¡ by¢ otrzymane za pomoc¡ bdiag. W gspec. ogólno±ci aby wyznaczy¢ warto±ci wªasne mo»na wyko»ysta¢ funkcj¦ 2.8.4 Funkcje size i length size pozwala uzyska¢ informacj¦ o wymiarach macierzy (w kolejno±ci: liczba wierszy, liczba kolumn): -->[nl,nc]=size(B) nc = 3. // B jest macierz\k{a} (2,3) z poprzedniego przyk\l{}adu 30 nl = 2. -->x=5:-1:1 x = ! 5. 4. 3. -->size(x) ans = ! 1. 5. ! natomiast length 2. 1. ! mówi o liczbie elementów macierzy (rzeczywistych lub ze- spolonych). W ten sposób dla wektora wierszowego lub kolumnowego otrzymuje si¦ dokªadnie liczb¦ jego wspóªczynników : -->length(x) ans = 5. -->length(B) ans = 6. Obie te instrukcje u»ywane s¡ po to aby pozna¢ rozmiar macierzy lub wek- size(A,'r') (lub size(A,1)) oraz size(A,'c') (lub size(A,2)) mówi¡ o liczbie wierszy (rows) oraz tora b¦d¡cego argumentem tych funkcji. Nale»y doda¢, »e kolumn (columns) macierzy 2.9 A. wiczenia 1. Zdeniowa¢ macierz wymiaru diag funkcji za pomoc¡ Help): n 0 2 B B 1 B B A=B 0 B B @ .. . 0 nast¦puj¡co (zob. 1 1 .. C . C C C 0 C C C A 0 0 .. . .. . .. . .. . .. . .. . .. . .. . .. . 0 szczegóªy dotycz¡ce 1 1 2 A b¦dzie macierz¡ kwadratow¡; czym b¦dzie diag(diag(A)) ? 2. Niech 3. Funkcja tril pozwala wydoby¢ trók¡tn¡ doln¡ cz¦±¢ macierzy (triu dla cz¦±ci trójk¡tnej górnej). Zdeniowa¢ dowoln¡ macierz kwadratow¡ za pomoc¡ górn¡ T rand) tak¡, »e A (np. i skonstruowa¢ pojedyncz¡ instrukcj¡ macierz trójk¡tn¡ tij = aij dla i > j (cz¦±ci trójk¡tne górne macierzy A i T tii = 1 (T jest diagonalnie jednostkowa). s¡ jednakowe) i tak¡, »e 4. Niech X b¦dzie macierz¡ (lub wektorem) zdeniowanym w ±rodowisku. Napisa¢ instrukcj¦ pozwalaj¡c¡ obliczy¢ macierz aru co X) w której element na pozycji nast¦puj¡cych przypadkach : (a) (b) (c) (d) f (x) = 2x2 3x + 1 f (x) = j2x2 3x + 1j f (x) = (x 1)(x + 4) f (x) = 1+1x2 31 (i; j ) Y (tego zamego rozmi- jest równy warto±ci f (Xij ) w 5. Naszkicowa¢ wykres funkcji f (x) = sinx x dla x 2 [0; 4] (napisa¢ skrypt). 6. Maªa ilustracja prawa wielkich liczb : obliczy¢ za pomoc¡ funkcji realizacji rozkªadu zero-jednkowego w postaci wektora P xk = k1 ki=1 xi skumulowan¡ tego wektora, tzn. wektor nych ma warto±¢ : x, x, rand obliczy¢ ±redni¡ którego ka»da z n wspóªrz¦d- oraz naszkicowa¢ wykres ci¡gu otrzy- manego w ten sposób. Zbada¢ jego zachowanie, zwi¦kszaj¡c warto±¢ 32 n n. Rozdziaª 3 Programowanie w Scilabie Scilab, oprócz prostych instrukcji (pozwalaj¡cych, z wyko»ystaniem instrukcji macierzowych, na bardzo syntetyczne programowanie bliskie j¦zykowi matematycznemu, co najmniej macierzowemu) dysponuje prostym aczkolwiek wystarczaj¡co kompletnym j¦zykiem programowania. Zasadnicz¡ ró»nic¡ w porównaniu z najpopularniejszymi dzi± j¦zykami (C, C++, Pascal, . . . ) jest brak konieczno±ci deklarowania zmiennych: w przeciwie«stwie do operacji wcze±niej wykonywanych, nie musimy w »adnym momencie precyzowa¢ rozmiaru macierzy ani jej typu (rzeczywista, zespolona, . . . ). To na interpreterze Scilaba spoczywa zadanie rozpoznawania ka»dego nowego obiektu. Takie podej±cie nie jest cz¦sto brane pod uwag¦, gdy» z punktu widzenia programisty prowadzi¢ mo»e do powstawania trudnych do wychwycenia bª¦dów. W przypadku j¦zyków takich jak Scilab (czy MATLAB) nie powoduje to problemów dzi¦ki u»ywaniu zapisu wektorowego/macierzowego oraz gotowych prostych instrukcji, pozwalaj¡cych na znaczne zmniejszenie ilo±ci zmiennych oraz wielko±ci kodu (tutu na przykªad instrukcje macierzowe pozwalaj¡ce unikn¡¢ maksimum p¦tli ). Inn¡ zalet¡ j¦zyków programowania tego typu jest to, »e dysponoj¡ one instrukcjami gracznymi (co pozwala unikn¡¢ »onglowania programem lub bibliotek¡ graczn¡) i s¡ one interpretowane (co umo»liwia ªatwe odnalezieniebª¦dów bez pomocy debugera). Dla odmiany niedogodnym jest, »e programy napisane w Scilabie s¡ wolniejsze od tych napisanych w C (ale program w C wymaga 50 razy wi¦cej czasu na napisanie i dopracowanie). Z drugiej strony, w aplikacjach gdzie ilo±¢ zmiennych jest szczególnie istotna (na przykªad macierz 1000 x 1000) lepiej powróci¢ do j¦zyka kompilowanego. Istotnym punktem wpªywaj¡cym na szybko±¢ wykonania jest konieczno±¢ stosowania maksymalnie cz¦sto instrukcji prostych i instrukcji macierzowych (oznacza to ograniczenie do minimum ilo±ci p¦tli)1 . W efekcie Scilab odwoªuje si¦ tak»e do skompilowanych funkcji (fortran) dzi¦ki czemu interpreter ma mniej pracy (pracuje mniej). Dla wykorzystania najlepszego z tych dwóch modeli (to znaczy szybko±ci j¦zyka kompilowanego i wygody ±rodowiska takiego jak Scilab), u»ytkownik ma mo»liwo±¢ wywoªywania podprogramów w fortranie(77) lub C. 3.1 P¦tle W Scilabie mamy mo»liwo±¢ u»ycia jednej z dwóch petli: 1 patrz równie»: sekcja Kilka uwag dotycz¡cych szybko±ci 33 for oraz while. 3.1.1 P¦tla for P¦tla for sªu»y do powtarzania pewnego ci¡gu instrukcji; zmienna staruj¡ca p¦tli przyjmuje kolejne warto±ci wektora liniowego -->v=[1 -1 1 -1] -->y=0; for k=v, y=y+k, end Ilo±¢ iteracji (powtórze«) okre±lona jest przez ilo±¢ skªadników wektora; w itej iteracji warto±¢ k jest równa nast¦puj¡co dla i := istart a» do instrukcje iend v(i). z krokiem Opisowo p¦tle istep for przedstwi¢ mo»na powtarzaj : koniec powtarzaj Jako wektora mo»na u»y¢ wyra»enia i_start:i_step:i_end; je±li przyrost iStep ma warto±¢ 1 to jak widzieli±my wcze±niej mo»e zosta¢ pomini¦ty. Przedstawiona wcze±niej jako przykªad p¦tla for mo»e zosta¢ tak»e napisana w bardziej naturalny sposób -->y=0; for i=1:4, y=y+v(i), end Kilka uwag: Zmienna steruj¡ca mo»e tak»e przyjmowa¢ warto±ci pochodz¡ce z macierzy. W takim przypadku ilo±¢ iteracji równa jest ilo±ci kolumn macierzy, a zmienna steruj¡ca w i-tym przebiegu p¦tli jest równa i-tej kolumnie macierzy -->A=rand(3,3);y=zeros(3,1); for k=A, y = y + k, end Dokªadna skªadnia instrukcji for wygl¡da nast¦puj¡co for zmienna = macierz, ciag instrukcji, end gdzie instrukcje oddzielone s¡ od siebie przecinkiem (lub ±rednikiem je±li nie chcemy widzie¢ na ekranie rezultatów wykonania instrukcji). Poniewa» lista zmiennych rozdzielonych przecinkiem równowa»na jest takiej samej li±cie rozdzielonej spacjami, dlatego w skryptach lub funkcjach cz¦±ciej stosuje si¦ wygodniejszy (bardziej czytelny) zapis: for zmienna = macierz instrukcja1 instrukcja2 ........... instrukcjan end gdzie instrukcja mo»e ko«czy¢ si¦ ±rednikiem (b¦dzie tak zawsze jesli chcemy unikn¡¢ pojawiania si¦ rezultaów instrukcji na ekranie)2 . 3.1.2 P¦tla while P¦tla while pozwala na powtarzanie ci¡gu instrukcji tak dªugo dopóki prawdziwy jest pewnien warunek: -->x=1 ; while x<14,x=2*x, end Zadaj¡c warunek mo»emy wykorzysta¢ nast¦puj¡ce operatory porównania: == ~= 2 < > <= >= lub równe mniejsze wi¦ksze mniejsze lub równe <> wi¦ksze lub równe ró»ne dziaªa to jedynie dla skryptów poniewa» w funkcji, wynik dowolnej instrukcji nie jest wy±wietlany nawet je±li nie jest ono zako«czona ±rednikiem ; to (domy±lne) zachowanie mo»na zmodykowa¢ za pomoc¡ instrukcji 34 mode Scilab posiada wbudowany typ logiczny, w którym dla oznaczenia prawdy stosuje si¦ symbole %t lub %T za± faªszu %f lub %F. Mo»na oczywi±cie zdeniowa¢ macierz lub wektor zªo»ony z warto±ci logicznych. Dost¦pne s¡ nast¦puj¡ce operatory logiczne : & | ~ et ou non while przedstawia si¦ jak poni»ej while warunek, instrukcja_1, ... ,instrukcja_N , end Formalna skªadnia p¦tli lub (cz¦sto w przypadku skryptu lub funkcji): while warunek instrukcja_1 ............. instrukcja_N end gdzie ka»da instrukcja_k mo»e zosta¢ zako«czona ±rednikiem, warunek za± jest wyra»eniem zwracaj¡cym warto±¢ logiczn¡. 3.2 Instrukcja warunkowa S¡ dwie instrukcje steruj¡ce przebiegiem wykonania programu: if-then-else oraz select-case. 3.2.1 Instrukcja if-then-else Spójrzmy na przykªad poni»ej : -->if x>0 then, y=-x,else,y=x,end // zmienna x powinna zostac wczesniej zdefini Podobnie jak to miaªo miejsce dla instrukcji p¦tli przecinki nie s¡ znakami obowi¡zkowymi. Jak w wi¦kszo±ci spotykaych j¦zyków programowania, w przypadku gdy nie podejmujemy »adnego dziaªania zwi¡zanego z niespeªnieniem warunku, mo»emy cz¦±¢ else zawiera¢ by miaªa kolejn¡ instrukcj¦ elseif co prowadzi do if warunek1 then ciag instrukcji wykonywanych gdy spelniony jest warunek1 elseif warunek2 then ciag instrukcji wykonywanych gdy spelniony jest warunek2 mo»na u»y¢ ... elseif warunekN then ciag instrukcji wykonywanych gdy spelniony jest warunekN else ciag instrukcji wykonywanych gdy nie jest spelniony zaden z warunków od 1 do N end 35 pomina¢. W przypadku gdy cz¦±¢ if-then-else zamiast ciagu else ogólnego schematu tej instrukcji else if oraz Podobnie jak dla instrukcji while warunek jest wyra»eniem zwracaj¡cym warto±¢ logiczn¡. 3.2.2 Instrukcja select-case (*) Spójrzmy na przykªad poni»ej (prosz¦ sprawdzi¢ jego dziaªanie dla ró»nych warto±ci zmiennej num)3 -->num = 1, select num, case 1, y = 'przypadek 1', case 2, y = 'przypadek 2',... -->else, y = 'inne przypadki ', end który w skrypcie lub funkcji przyjmie raczej posta¢ // zakladamy, ze zmienna num zostala dobrze okreslona select num case 1 y = 'przypadek 1' case 2 y = 'przypadek 2' else y = 'inne przypadki' end Scilab sukcesywnie porównuje warto±¢ zmiennej num z mo»liwymi przypadków (1, potem 2). pocz¡wszy od case warto±ciam Je±li zajdzie równo±¢, wykonywane s¡ instrukcj¦ równego zmiennej num a» do ko«ca instrukcji Przekazanie sterowania do nieobowi¡zkowej gaª¦¹i else gdy nie powiod¡ si¦ wszystkie wcze±niejsze testy. select-case. ma miejsce w sytuacji Formalnie instrukcja ta przedstawia si¦ nast¦puj¡co select zmienna_testjaca case wyrazenie_1 ciag instrukcji wykonywany gdy zmienna_testujaca równa jest wyrazeniu_1 ... case wyrazenieN ciag instrukcji wykonywany gdy zmienna_testujaca rowna jest wyrazeniu_N else ciag instrukcji wykonywany gdy zmienna_testujaca nie jest równa zadnemu z wyrazen od 1 do N end gdzie wyrazenie_i jest wyra»eniem zwracaj¡cym warto±¢, która mo»e zosta¢ porównana ze zmienna_testujaca. Konstrukcja select-case równowa»na jest nast¦puj¡cej konstrukcji if-then-else if zmienna_testujaca == wyrazenie_1 then ciag instrukcji wykonywany gdy zmienna_testujaca rowna jest wyrazeniu_1 ... elseif zmienna_testujaca = wyrazenie_N then ciag instrukcji wykonywany gdy zmienna_testujaca rowna jest wyrazeniu_N else ciag instrukcji wykonywany gdy 3 Zmienna y jest ªa«cuchem znaków patrz kolejny rozdziaª. 36 nie jest spelniony zaden z powyzszych warunków end 3.3 Inne rodzaje zmiennych Do tej pory u»ywali±my zmiennych b¦d¡cych macierzami (wektorami, skalarami) zªo»onymi z warto±ci typu rzeczywistego, zespolonego lub logicznego. Oprócz nich mamy równie» do dyspozycji zmienne reprezentuj¡ce ªa«cuchy znaków oraz listy. 3.3.1 a«cuchy znaków W przykªadzie dotycz¡cym konstrukcji select-case zmienna y jest typu ªa«cuch znaków. W Scilabie ªa«cuchy znaków ograniczane s¡ za pomoc¡ znaku apostrofu lub cudzysªowu (je±li chcemy który± z tych znaków wykorzysta¢ w takim ªa«cuchu, to nale»y napisa¢ go dwukrotnie). Aby przypisa¢ zmiennej czy_to_prawda warto±¢ Czy Scilab jest "cool" ? nale»y napisa¢ -->czy_to_prawda = "Czy Scilab jest ""cool"" ?" lub równowa»nie -->czy_to_prawda = 'Czy Scilab jest ""cool"" ?' Mo»na tak»e zdeniowa¢ macierz zªo»on¡ z ªa«cuchów znaków -->M = ["a" "bc" "def"] M = !a bc def ! -->size(M) // w celu otrzymania wymiarów skladowych ans = ! 1. 3. ! -->length(M) ans = ! 1. 2. 3. ! Zauwa»my, »e w tym przypadku length nie zachowuje si¦ tak samo jak dla macierzy liczbowej. Zwraca bowiem jako wynik macierz o takim samym wymiarze jak M, w której wspóªczynnik okre±lony przez wspóªrz¦dne (i; j ) równy jest co do warto±ci ilo±ci znaków w ªa«cuchu na pozycji (i; j ). Do ª¡czenia (konkatenacji) ªa«cuchów u»ywamy operatora + -->s1 = 'abc'; s2 = 'def'; s = s1 + s2 s = abcdef podci¡g wydobywamy za± (operacja extrakcja) przy pomocy funkcji -->part(s,3) ans = c -->part(s,3:4) ans = cd 37 part Drugim argumentem funkcji part jest wektor okre±laj¡cy indeksy znaków jakie mamy wydoby¢ z ªa«cucha. 3.3.2 Listy (*) Lista jest uporz¡dkowanym zbiorem obiektów Scilaba (macierzy i skalarów rzeczywistych, zespolonych czy te» zªo»onych z ª¡«cuchów znaków, warto±ci logicznych, funkcji, list, . . . ; ka»demu elementowi przypisuje si¦ numer). Dost¦pne s¡ dwa rodzaje list: zwykªe i typowane. Oto przykªad listy zwykªej : -->L=list(rand(2,2),["To jest jekis" " lancuch..."],[%t ; %f]) L = L(1) ! ! 0.2113249 0.7560439 0.0002211 ! 0.3303271 ! L(2) !To jest jakis lancuch... ! L(3) ! T ! ! F ! W ten oto sposób zdeniowali±my list¦, w której pierwszy element jest macierz¡ o wymiarze (2; 2), drugi wektorem ªa«cuchów znakowych a trzeci wektorem o skªadnikach logicznych. Oto kilka podstawowych operacji na listach -->M = L(1) M = ! ! // extrakcja (wydobycie) pierwszego skladnika 0.2113249 0.7560439 0.0002211 ! 0.3303271 ! -->L(1)(2,2) = 100; // modyfikowanie pierwszego skladnika -->L(1) ans = ! ! 0.2113249 0.7560439 0.0002211 ! 100. ! -->L(2)(4) = " znakow !"; // modyfikacja drugiego skladnika -->L(2) ans = !To jest jakis lancuch... znakow ! -->L(4)="Aby dodac czwarty skladnik" 38 ! L = L(1) ! ! 0.2113249 0.7560439 0.0002211 ! 100. ! L(2) !To jest jakis lancuch... znakow ! ! L(3) ! T ! ! F ! L(4) Aby dodac czwarty skladnik -->size(L) ans = // ile elementow ma lista 4. -->length(L) // idem (tutu?) ans = 4. -->L(2) = null() L = // usuniecie drugiego elementu L(1) ! ! 0.2113249 0.7560439 0.0002211 ! 100. ! L(2) ! T ! ! F ! L(3) Aby dodac czwarty skladnik -->Lbis=list(1,1:3) Lbis = // definicja innej listy 39 Lbis(1) 1. Lbis(2) ! 1. 2. -->L(3) = Lbis L = 3. ! // 3 skladnik L jest teraz lista L(1) ! ! 0.2113249 0.7560439 0.0002211 ! 100. ! L(2) ! T ! ! F ! L(3) L(3)(1) 1. L(3)(2) ! 1. 2. 3. ! Przejd¹my do list typowanych. W listach tego typu pierwszy element jest ªa«cuchem okre±laj¡cym typ elementów listy (tutu co pozwala zdeniowa¢ nowy typ danych a nast¦pnie operatory dla tego typu), kolejne elementy mog¡ by¢ dowolnymi obiektami Scilaba. Pierwszy element mo»e tak»e by¢ wek- torem zªo»onym z ªa«cuchów znaków; pierwszy okre±la typ elementów listy, pozostaªe za± mog¡ sªu»y¢ jako indeksy elementów listy (w miejsce ich numerów na li±cie). Rozwa»my nast¦pujacy przykªad: chcemy reprezentowa¢ wielo±cian (w którym wszystkie ±ciany maj¡ identyczn¡ ilo±¢ kraw¦dzi). W tym celu przechowujemy w macierzy wspóªrz¦dne wszystkich wierzchoªków (o wymiarze (3, ilo±¢ wierzchoªków)) do której odwoªywa¢ si¦ b¦dziemy u»ywaj¡c ciagu coord. Nast¦pnie deniujemy macierz (o wymiarze (ilo±¢ wierzchoªków na ±cian¦, ilo±¢ ±cian)) okre±laj¡c¡ zwi¡zek pomi¦dzy ±cian¡ a wierzchoªkami: dla ka»dej sciany podajemy numery wierzchoªków j¡ opisuj¡cych w kolejno±ci zgodnej z reguª¡ korkoci¡gu dla zewn¦trznego wektora normalnego. Do tej listy odwoªywa¢ si¦ b¦dziemy pisz¡c fence. Dla sze±cianu (porównaj rysunej 3.1) b¦dzie to wygl¡daªo jak poni»ej P=[ 0 0 1 1 0 0 1 1;... // wspolrzedne wierzcholkow 40 Rysunek 3.1: Numéros des sommets du cube 0 1 1 0 0 1 1 0;... 0 0 0 0 1 1 1 1]; connect = [1 2 3 4 5 8 7 6 3 7 8 4 2 6 7 3 1 5 6 2 1;... // zaleznosci pomiedzy wierzcholkami i scianami 4;... 8;... 5]; Pozostaje zdeniowa¢ list¦ typowan¡, która zawiera¢ b¦dzie wszystkie informacje o sze±cianie -->Cube = tlist(["polyedre","coord","fence"],P,connect) Cube = Cube(1) !polyedre coord fence ! Cube(2) ! ! ! 0. 0. 0. 0. 1. 0. 1. 1. 0. 1. 0. 0. 0. 0. 1. 0. 1. 1. 3. 7. 8. 4. 2. 6. 7. 3. 1. 5. 6. 2. 1. 4. 8. 5. 1. 1. 1. 1. ! 0. ! 1. ! Cube(3) ! ! ! ! 1. 2. 3. 4. 5. 8. 7. 6. ! ! ! ! W celu wskazania pewnego elementu z wykorzystniem jego numeru, mo»na wykorzysta¢ odpowiadaj¡cy jemy ªa«cuch znaków: -->Cube.coord(:,2) // lub inaczej ans = ! ! ! Cube("coord")(:,2) 0. ! 1. ! 0. ! -->Cube.fence(:,1) ans = ! ! ! ! 1. 2. 3. 4. ! ! ! ! Pomijaj¡c te szczególne mo»liwo±ci, listami typowanymi manipuluje si¦ tak samo jak innymi. Ich zalet¡ jest mo»liwo±¢ samodzielnego zdeniowania (i.e. przupisania) operatorów +, -, *, / itd. 41 na tli¢ie typu danych (porównaj przyszª¡ wersj¦ tej dokumentacji, albo dokumentacje zamieszczon¡ w sieci na domowej stronie Scilaba. 3.3.3 Niektóre wyra»enia z wektorami i macierzami typu logiczego (boolen) Typ boolowski (u»ywany do reprezentacji warto±ci logicznych typu prawda i faªsz) okazuje si¦ cz¦sto przydatny ze wzgl¦dów praktycznych podczas manipuowania macierzami. Gdy porównujemy dwie macierze tego samego wymiaru za pomoc¡ jednego z operatorów porównania (<, >, <=, >=,==, ~=) jako wynik otrzymujemy macierz o warto±ciach logicznych, równie» tego samego formatu, której zawarto±¢ jest wynikiem porównania element po elemencie odpowiadaj¡cych sobie elementów porównywanych macierzy -->A = rand(2,3) A = ! 0.2113249 0.0002211 ! 0.7560439 0.3303271 0.6653811 ! 0.6283918 ! -->B = rand(2,3) B = ! 0.8497452 0.8782165 ! 0.6857310 0.0683740 0.5608486 ! 0.6623569 ! -->A < B ans = ! T T F ! ! F F T ! Je±li natomiast porównujemy macierz z liczb¡, a wi¦c to faktycznie dokonujemy porównania A<s*one(A) A<s gdzie s jest skalarem -->A < 0.5 ans = ! T T F ! ! F T F ! Operatory logiczne równie» stosuje si¦ dla macierzy na zasadzie element po elemencie -->b1 = [%t %f %t] b1 = ! T F T ! -->b2 = [%f %f %t] b2 = ! F F T ! -->b1 & b2 ans = ! F F T ! -->b1 | b2 ans = ! T F T ! -->~b1 ans = 42 ! F T F ! Ponadto istniej¡ dwie przydatne funkcje pozwalaj¡ce dokona¢ wektoryzacji testu 1. Funkcja bool2s przeksztaªca macierz boolowsk¡ w macierz o takich samych wymiarach zamieniaj¡c warto±¢ logiczna prawda na 1, faªsz za± na 0 2. -->bool2s(b1) ans = ! 1. 0. 1. ! Funkcja find zwraca wspóªrz¦dne warto±ci prawda w macierzy boolowskiej -->v = rand(1,5) v = ! 0.5664249 0.4826472 0.3321719 0.5935095 0.5015342 ! -->find(v < 0.5) ans = ! 2. 3. ! // v < 0.5 daje wektor boolowski Stosowanie tych funkcji jest dosy¢ kosztowne czasowo (porównaj Kilka uwag zwi¡zanych z szybko±ci¡ wykonania). Funkcje and oraz or oznaczaj¡ce odpowied- nio iloczyn logiczny (i) oraz sum¦ logiczn¡ (lub) wszystkich elementów macierzy boolowskiej daj¡c w efekcie jedn¡ warto±¢ logiczn¡. Funkcje to mog¡ przyjmowa¢ dodatkowy argument okre±laj¡cy czy odpowiednie dziaªanie logiczne ma zosta¢ wykonane na wierszach czy kolumnach macierzy. 3.4 Funkcje W celu zdeniowania funkcji w Scilabie, najbardziej odpowiedni¡ metod¡ jest zapisanie jej w utworzonym pliku; b¦dzie mo»na do niego dopisywa¢ kolejne funkcje grupuj¡c na przykªad te zwi¡zane z tym samym czy podobnym zagadnieniem czy aplikacj¡. Ka»da funkcja powinna rozpoczyna¢ si¦ w nast¦puj¡cy sposób function [y1,y2,y3,...,yn]=nazwa_funkcji(x1,....,xm) gdzie xi s¡ argumentami funkcji, natomiast yi warto±ciami przez ni¡ zwracanymi. Dalej wyst¦puje ciaªo funkcji czyli wszystkie instrukcjie niezb¦dne do wykonania przez funkcj¦ okre±lonego zadania. Funkcja powinna ko«czyc si¦ sªowem endfunction. Oto pierwszy przykªad function [y] = silnia1(n) // silnia; zakladamy, ze n jest liczba naturalna y = prod(1:n) endfunction kluczowym Zaªó»my, »e powy»sz¡ funkcj¦ zapisali±my w pliku o nazwie silnia1.sci4 . Aby mo»na z niej korzysta¢ w Scilabie nale»y j¡ najpierw wczyta¢ getf("silnia1.sci") Mo»na tego // lub inaczej exec("silnia1.sci") dokona¢ tak»e z menu File operations tak jak dla skryptów. Dopiero teraz mo»emy u»y¢ zdeniowanych w danym pliku funkcji, zarówno w samodzielnych poleceniach jak i w skryptach czy innych funkcjach. -->m = silnia1(5) m = 120. 4 Tradycyjnie plik zawieraj¡cy funkcj¦ posiada rozszerznie .sci 43 natomiast skrypt .sce -->n1=2; n2 =3; silnia1(n2) ans = 6. -->silnia1(n1*n2) ans = 720. Zanim przejdziemy do kolejnych przykªadów musimy ustali¢ jeszcze pewn¡ ter- minologi¦. Argumenty wyj±ciowe (yi) oraz argumenty wej±ciowe (xi) nazywa¢ b¦dziemy argumentami formalnymi. U»ywaj¡c funkcji na przykªad w skrypcie czy w innej funkcji arg_s = silnia1(arg_e) u»yte argumenty (args oraz arge )nazywabdzimyargumentamiefektywnymi:Itakwpierwszymp Drugi przykªad pokazuje funkcj¦ znajduj¡c¡ pierwiastki trójmianu kwadratowego function [x1,x2] = trinom(a, b, c) // oblicza pierwiastki trojmianu kwadratowego postaci x^2 + b x + c = 0 // a, b oraz c musza byc liczbami rzeczywistymi lub zespolonymi roznymi od z delta = b^2 - 4*a*c x1 = (-b - sqrt(delta))/(2*a) x2 = (-b + sqrt(delta))/(2*a) endfunction Oto wyniki trzech prób jej u»ycia -->[r1, r2] = trinom(1,2,1) r2 = - 1. r1 = - 1. -->[r1, r2] = trinom(1,0,1) r2 = i r1 = - i -->trinom(1,0,1) // wywo\l{}anie bez tutu ans = - i Zauwa»my, »e w trzecim przypadku nie widzimy drugiego z pierwiastków. Jest to normalne zachowanie w sytuacji gdy funkcja zwraca wi¦cej ni» jedn¡ warto±¢ i nie zostan¡ one przypisane do zmiennych (tak jak ma to miejsce w drugim przypadku). W takiej sytuacji Scilab wykorzystuje domy±ln¡ zmienn¡ przechowywa¢ wynik; ans ans aby b¦dzie przyjmowaªo kolejene zwracane warto±ci aby ostatecznie przyj¡¢ warto±¢ równ¡ tej zwróconej jako ostaniej. Teraz trzeci przykªad. Nale»y rozwin¡¢ w punkcie bazie Newtona (Uwaga: Dla xi = 0 t wielomian zapisany w otrzymujemy baz¦ kanoniczn¡.) p(t) = c1 + c2 (t x1 ) + c3 (t x1 )(t x2 ) + : : : + cn (t x1 ) : : : (t xn 1 ): U»ywaj¡c rozkªadu na czynniki pierwsze i wykonuj¡c obliczenia od prawej do lewej (tutaj dla n = 4) p(t) = c1 + (t x1 )(c2 + (t x2 )(c3 + (t x3 )(c4 ))); 44 otrzymujemy algorytm Hornera (1) (2) (3) (4) p := c4 p := c3 + (t x3 )p p := c2 + (t x2 )p p := c1 + (t x1 )p. Uogólniaj¡c to na dowolne n otrzymujemy nast¦puj¡c¡ funkcj¦ Scilaba function [p]=myhorner(t,x,c) // rozwija wielomian c(1) + c(2)*(t-x(1)) + c(3)*(t-x(1))*(t-x(2)) + // ... + c(n)*(t-x(1))*...*(t-x(n-1)) // zgodnie z algorytmem Hornera n=length(c) p=c(n) for k=n-1:-1:1 p=c(k)+(t-x(k))*p end endfunction Je±li wektory coef, xx, tt zostaªy dobrze okre±lone instrukcja val = myhorner(tt,xx,coef) spowoduje przypisanie do val warto±ci równej coef1 + coef2 (tt xx1 ) + + coefm Maªe przypomnienie: instrukcja mY1 i=1 (tt xxi ) length zwraca iloczyn dwóch wymiarów macierzy daj¡c liczb¦ elementów co w przypadku wektora (kolumnowego lub wierszowego) równowa»ne jest jego dªugo±ci. Instrukcja ta, wraz z instrukcj¡ size zwracaj¡c¡ ilo±¢ wierszy i ilo±¢ kolumn, pozwala zrezygnowa¢ z przekazywania do funkcji informacji o wymiarze przekazywanych obiektów. 3.4.1 Przekazywanie parametrów (*) Przekazywanie parametrów odbywa si¦ przez referencj¦ je±li parametr ten nie jest modykowany przez funkcj¦, w przeciwnym przypadku przez warto±¢5 . Mo»na je wyko»ysta¢ (uwzgl¦dnia¢) w celu przyspieszenia pewnych funkcji. Poni»ej przedstawiamy sztuczny, ale dobrze ilustruj¡cy zagadnienie, przykªad ukazuj¡cy koszt zwi¡zany z przekazywaniem parametrów przez warto±¢. function [w] = toto(v, k) w = 2*v(k) endfunction function [w] = titi(v, k) v(k) = 2*v(k) w = v(k) endfunction // skrypt testujacy m = 200000; il_powtorzen = 2000; x = rand(m,1); 5 Przez warto±¢ czyli we wn¦trzu funkcji pracujemy na kopii przekazywanego argumentu. wn¦trzu funkcji pracujemy na oryginalnym argumecie. (przyp. tªum.) 45 Przez referencj¦ czyli we timer(); for i=1:nb_rep; y = toto(x,300); end; t1=timer()/il_powtorzen timer(); for i=1:nb_rep; y = titi(x,300); end; t2=timer()/il_powtorzen Otrzymane wyniki b¦d¡ ró»niªy si¦ w zale»no±ci od maszyny na jakiej dziaªa Scilab; my otrzymali±my t1 = t2 = 0.00002 0.00380 Wraz z zako«czeniem funkcji destrukcji ulegaj¡ wszystkie jej zmienne wewn¦trzne. 3.4.2 Wy±wietlanie funkcji Podczas debugowania funkcji przydatna okazuje si¦ funkcja disp(v1, v2, ...) v1, v2, . . . Nale»y mie¢ na uwadze, disp wyswietla warto±ci swoich argumentów w odwrotnej kolejno±ci. pozwalaj¡ca wy±wietli¢ warto±ci zmiennych »e funkcja W celu chwilowego wstrzymania wykonania programu u»y¢ mo»na funkcji pause; po jej napotkaniu mamy mo»liwo±¢ sprawdzenia warto±ci wszystkich zdeniowanych do tej pory zmiennych. Polecenie resume powoduje wznowie- nie przebiegu oblicze«. Istnieje tak»e inny sposób wskazywania miejsca wstrzymania programu (tak pause setbpt(nazwaf unkcji[; numerl inii]) Argumentem funkcji setbpt jest nazwaf unkcji; ktrama delbpt(nazwaf unkcji[; numerl inii]) Je±li nie zostanie wskazana »adna linia, wszystkie zwany break point, ang.) ni» dodawanie instrukcji punkty zatrzymania zostan¡ usuni¦te. Zdeniowane do tej pory punkty zatrzymania mo»na zobaczyc korzystaj¡c z trinom dispbpt (). Oto przykªad zwi¡zany z wcze±niej zdeniowan¡ funcj¡ (patrz strona 42). Zaªó»my, »e wczytali±my uprzednio t¡ funkcj¦ czy to za pomoc¡ funkcji getf czy te» exec. -->setbpt("trinom") // pierwszy punkt zatrzymania -->[r1,r2] = trinom(1,2,7) // rozpoczynamy obliczenia => zatrzymanie Stop after row 1 in function trinom : -1->a a = 1. // sprawdzamy wartosci zmiennych -1->b b = 2. -1->dispbpt() // sprawdzamy punkty zatrzymania breakpoints of function :trinom 1 -1->setbpt("trinom",5) // dodajemy kolejny punkt zatrzymania -1->x1 // x1 nie zostal jeszcze zdefiniowany x1 !--error 4 undefined variable : x1 -1->resume // wznawiamy wykonanie az do nastepnego punktu zatrzymania Stop after row 5 in function trinom : -1->x1 // teraz mozemy sprawdzic jaka wartosc ma x1 x1 = - 1. - 2.4494897i -1->x2 // x2 nie zostal jeszcze zdefiniowany (nastapi to dopiero w linii 6) 46 x2 !--error 4 undefined variable : x2 -1->dispbpt() // sprawdzamy punkty zatrzymania breakpoints of function :trinom 1 5 -1->resume // wznawiamy wykonanie funkcji r2 = - 1. + 2.4494897i r1 = - 1. - 2.4494897i -->delbpt("trinom") // usuwamy wszystkie punkty zatrzymania 47 3.4.3 Instrukcja break Instrukcja break pozwala przerwa¢ obliczenia wewn¡trz p¦tli for lub while i przekaza¢ sterowanie przebiegiem wykonanie do pierwszej instrukcji wyst¦puj¡cej po p¦tli. Wykorzysta¢ j¡ mo»na do zasymulowania niedost¦pnej standardowo a znanej cho¢by z Pascala p¦tli repeat-until czy odpowiadaj¡cej jej w j¦zyku C p¦tli do-while czy te» przerwania oblicze« w sytuacji gdy nie ma mo»liwo±ci ich dalszego kontynowania (na przykªad zerowy pierwszy elemnent na przk¡tnej w metodzie Gaussa). Zaªó»my, »e chcemy mie¢ p¦tle, w której warunek wyj±cia testowany jest na ko«cu powtarzaj ciag instrukcji dopoki spelniony jest warunek W Scilabie mo»na zrealizowa¢ to w nast¦puj¡cy sposób while %t // poczatek petli ciag instrukcji if warunek then, break, end end S¡ sytuacje gdy u»ycie instrukcji break jest bardzo naturalne i prowadzi do czytelnych i zwartych rozwi¡za«. Jako przykªad rozwa»my poszukiwanie w ªa«cuchu znaków sªowa l ropoczynaj¡cego si¦ na zadan¡ liter¦ . W tym celu napiszemy funkcj¦ (zwracaj¡c¡ 0 w przypadku gdy »aden z wyrazów nie rozpoczyna si¦ od zadanej litery) u»ywaj¡c p¦tli nie korzystaj¡c z instrukcji break function ind = znajdz(v,l) n = max(size(v)) i = 1 succes = %f while ~succes & (i <= n) succes = part(v(i),1) == l i = i + 1 end if succes then ind = i-1 else ind = 0 end endfunction Wykorzystanie instrukcji break prowadzi do bardziej naturalnego rozwi¡zania function ind = znajdz(v,l) n = max(size(v)) ind = 0 for i=1:n if part(v(i),1) == l then ind = i break end end endfunction 48 while i Uwaga: Powy»ej zastosowano funkcj¦ size zamiast odpowiedniejszej dla macierzy zªo»onych z ªa«cuchów znaków funkcji length6 (przypominamy, »e length zwraca macierz której warto±ci wspóªczynników okre±laj¡ ilo±¢ znaków w adpowiadaj¡cym ªa«cuchu). 3.4.4 Kilka przydatnych dla funkcji prymitywów length i size pozwalaj¡cymi otrzyma¢ wymiary przekazanych zmiennych, pause, resume, disp dzieki którym mo»emy debugowa¢ program dost¦pnych jest jeszcze kilka u»ytecznych funkcji jak error, warning, arg czy te» type, czy typeof. Poza funkcjami Funkcja Funkcja error error przerywa natychmiast wykonanie funkcji wy±wietlaj¡c przy tym odpowiedni komunikat. Oto funkcja obliczaj¡ca n! i sprawdzaj¡ca, czy n 2 N function [f] = silnia2(n) // oblicza silnie dla liczby naturalnej if (n - floor(n) ~=0) | n<0 then error('Blad w funkcji silnia2 : argument musi byc liczba naturalna') end f = prod(1:n) endfunction oraz rezultaty jej wykonania -->silnia2(3) ans = 6. -->silnia2(0.56) !--error 10000 Blad w funkcji silnia2 : argument musi byc liczba naturalna at line 6 of function silnia2 called by : silnia2(0.56) Funkcja Funkcja warning warning pozwala wy±wietli¢ pewien komunikat ostrzegawczy, ale nie przerywa wykonywanych operacji function [f] = silnia3(n) // oblicza silnie dla liczby naturalnej if (n - floor(n) ~=0) | n<0 then n = floor(abs(n)) warning('Przekazany argument nie jest liczba naturalna: obliczenia kontynuowa end f = prod(1:n) endfunction . . . i efekt wykonania -->fact3(-4.6) WARNING:Przekazany argument nie jest liczba naturalna: obliczenia kontynuowane dla 4! ans = 24. 6 Je±li chcemy aby nasza funkcji mogªa poprawnie dziaªa¢ niezale»nie od tego czy nie nale»y u»ywa¢ konstrukcji size(v,'r') lub size(v,'l') v ale zastosowan¡ wªa±nie 49 jest w postaci wiersza czy kolumny max(size(v)). v type(v) typeof(v) macierz zmiennych rzeczywistych lub zespolonych 1 constant macierz boolowska 4 boolean macierz ªa«cuchów znakowych 10 string lista 15 list lista typowana 16 typ listy funkcja 13 function typ zmiennej Tablica 3.1: Podobnie jak dla funkcji error tak i dla funkcji warning jedynym argumentem jest ªa«cuch + do ª¡czenia ªa«cuchów, z których sprintf pozwalaj¡cej przeksztaªci¢ liczby w znaków. W powy»szym przykªadzie u»yto operatora jeden jest otrzymany w wyniku dziaªania funkcji odpowiadaj¡cy im ªa«cuch znaków zale»ny od wyspecykowanego formatu. Funkcja type Funkcje te pozwalaj¡ pozna¢ typ zmiennej. danej, natomiast typeof et type typeof zwraca warto±¢ liczbow¡ okre±laj¡c¡ typ ªa«cuch znaków. Tabela 3.1 zawiera odpowiednie warto±ci dla poznanych rodzajów zmiennych. Jako przykªad wykorzystania tych funkcji podamy funkcj¦ licz¡c¡ silnie, która posiada pewne zabezpieczenia na wypadek podania zmiennej nieodpowiedniego typu function [f] = silnia4(n) // funkcja silnia bardziej ,,opancerzona'' if type(n) ~= 1 then error("Blad w funkcji silnia4: podano argument nieodpowiedniego typu...") end [nl,nc]=size(n) if (nl ~= 1) | (nc ~= 1) then error("Blad w funkcji silnia4: argument nie moze byc macierza...") end if (n - floor(n) ~=0) | n<0 then n = floor(abs(n)) warning('Przekazany argument nie jest liczba naturalna: obliczenia kontynuowane dla end f = prod(1:n) endfunction Funkcja Funkcja arg argn i opcjonalne argumety zwraca dwie liczby okre±laj¡ce ilo±¢ argumentów z jak¡ funkcj¦ wywoªano oraz ilo±¢ argumentów jakie zwraca. Wywoªanie przyjmuje posta¢ [lhs,rhs] = argn() gdzie lhs (ang. left hend side) okre±la ilo±¢ zwracanych argumentów, rhs (ang. right hend side) okre±la ilo±¢ przyj¦tych efektywnie argumentów. Poni»ej prezentujemy przykªad funkcji z jednym argumentem klasycznym oraz dowoma opcjonalnymi function [y] = argopt(x, coefMult, coefAdd) [lhs, rhs] = argn() if rhs < 1 | rhs > 3 then error("Nieprawidlowa ilosc argumentow") end 50 if ~exists("coef_mult","local") then coef_mult = 1 end if ~exists("coef_add","local") then coef_add = 0 end y = coef_mult*x + coef_add endfunction Funkcja exists coefm ultoraz coefa ddzostayokrelone 7 pozwala okre±li¢ czy argumenty przyjejwywoaniuczynaleyprzypisaimpewnwartodomyln:Uzy -->y1 = argopt(5) y1 = 5. -->y2 = argopt(5, coef_add=10) y2 = 15. -->y3 = argopt(5, coef_mult=2, coef_add=6) y3 = 16. -->y4 = argopt(5, coef_add=6, coef_mult=2) // y4 powinno byc równe y3 y4 = 16. 3.5 Ró»ne ró»no±ci 3.5.1 Dªugo±¢ identykatorów Identykatory w Scilabie rozró»niane s¡ na podstawie pierwszych 24 liter -->a234567890123456789012345 = 1 a23456789012345678901234 = 1. -->a234567890123456789012345 a23456789012345678901234 = 1. Oczywi±cie mo»na u»ywa¢ nazw dªu»szych, ale i tak pod uwag¦ branych jest pierwszych 24 liter. 3.5.2 Priorytety operatorów W Scilabie operatory zwi¡zane z dziaªaniami arytmetycznymi maj¡ wy»szy priorytet ni» operatory sªu»¡ce do porówna«. W tabeli 3.2 przedstawiono operatory arytmetyczne w kolejno±ci od najwy»szego do najni»szego priorytetu. Dla operatorów logicznych negacja (not) ( 7 Dodatkowy argument local zaw¦»a zakres poszukiw« zmiennej do bie»¡cej funkcji. 51 ' ^ .^ * .* / ./ \ + Tablica 3.2: ) ma wy»szy priorytet ni» i (and) (&), który z kolei ma wy»szy priorytet ni» lub (or) (|). W czytaniu/zapisie bardziej zªo»onych wyra»e« mo»na pomóc sobie u»ywaj¡c dodatkowo naw- 8 iasów i robi¡c spacje wokóª wyra»e« . Tricks. Wi¦cej szczegóªów mo»na znale¹¢ w Scilab Bags of Kilka uwag 1. Jak w wi¦kszo±ci j¦zyków, stosowanie unarnego operatora minus wymaga ostro»no±ci. Bª¦dny jest zapis operand1 op - operand2 gdzie op jest pewnym operatorem. W takiej sytucji nale»y zastosowac nawiasy operand1 operator (- operand2) 2. W wyra»eniach typu operand1 op1 operand2 op2 operand3 op3 operand4 gdzie wszystkie operatory maj¡ ten sam priorytet obliczanie warto±ci wyra»enia odbywa si¦ na ogóª od lewej do prawej strony {((operand1 op1 operand2) op2 operand3) op3 operand4} Dla operatora pot¦gowania kolejno±¢ ta jest odwrotna; zapis a^(b^c). a^b^c Jest to zgodne z matematycznym zapisem takiego dziaªania traktowany jest jak ab c które wªa±nie w takiej kolejno±ci si¦ wykonuje. a | b czy a & b a jak i b a dopiero potem wyko- 3. Inaczej ni» w j¦zyku C obliczanie warto±ci wyra»e« boolowskich postaci poprzedzone jest obliczeniem zarówno warto±ci wyra»enia nana zostanie na nich operacja sum czy iloczynu logicznego. St¡d te» poni»sze rozwi¡zanie wygeneruje bª¡d while i>0 & temp < v(i) v(i+1) = v(i) i = i-1 end przy próbie obliczenia drugiego wyra»enia (temp < v(i)) gdy» indeks wektora jest zawsze liczb¡ wi¦ksz¡ lub równ¡ 1. 3.5.3 Rekursja O rekursji powiemy gdy funkcja b¦dzie wywoªywa¢ sam¡ siebie. Prosz¦ spojrze¢ na dwa poni»sze przykªady (s¡ to standardowe przykªady ilustruj¡ce rekursj¦; drugi z nich, skªadniowo poprawny i dziaªaj¡cy, pokazuje wad¦ rozwi¡za« rekursywnych dªugi czas oblicze« a tak»e mo»liwo±¢ przepeªnienia stosu) function f=silnia(n) // silnia if n <= 1 then 8 Oczywi±cie nawiasy s¡ niezb¦dne je±li chcemy zmieni¢ priorytet wyra»enia. 52 f = 1 else f = n*silnia(n-1) end endfunction function f=fib(n) // oblicza n-ty wyraz ciagu Fibonnaciego: // fib(0) = 1, fib(1) = 1, fib(n+2) = fib(n+1) + fib(n) if n <= 1 then f = 1 else f = fib(n-1) + fib(n-2) end endfunction 3.5.4 Funkcja jest te» zmienn¡ Funkcja w Scilabie mo»e by¢ traktowana jak dowolna inna zmienna, w szczególno±ci mo»e sta¢ si¦ ona argumentem innej funkcji. Przyjrzyjmy si¦ poni»szemu przykªadowi dwóch funkcji function [y] = f(x) y = sin(x).*exp(-abs(x)) endfunction function dessine_fonction(a, b, fonction, n) // n jest argumentem opcjonalnym o wartosci domyslnej 61 [lhs, rhs] = argn(0) if rhs == 3 then n = 61 end x = linspace(a,b,n) y = fonction(x) plot(x,y) endfunction Po ich wczytaniu mo»emy wykona¢ nast¦puj¡ce polecenia -->dessine_fonction(-2*%pi,2*%pi,f) -->dessine_fonction(-2*%pi,2*%pi,f,21) Scilab, za pomoc¡ funkcji deff, oferuje mo»liwo±¢ bezpo±redniego deniowania funkcji w ±rodowisku (bez potrzeby zapisywania jej w pliku a nast¦pnie wczytywania przez funkcj¦ getf) deff('[y1,y2,...]=nazwa_funkcji(x1,x2,....)',text) gdzie text jest wektorem kolumnowym zªo»onym z ªa«cuchów znaków reprezentujacych kolejne instrukcje deff('[y]=f(x)','y = sin(x).*exp(-abs(x))') Taka mo»liwo±¢ jest interesuj¡ca w wielu przypadkach. 1. W skrypcie wyko»ystujacym prost¡ funkcj¦ która musi by¢ do±¢ cz¦sto modykowana; w tym przypadku mo»na zdeniowa¢ funkcj¦ za pomoc¡ instrukcji deff w skrypcie, który nie przeplata si¦ z innym plikiem, w którym funkcja jest zwycajnie zdeniowana; pocz¡wszy od wersji 2.6 mo»na deniowa¢ funkcje w skrypcie wedlug zwycajnej skªadni, co jest praktyczniejsze ni» deff; w naszym skrypcie mo»na wiec napisa¢ funkcje na pocz¡tku tekstu: 53 // definicja funkcji wykorzystywanych w skrypcie function .... endfunction function .... endfunction // poczatek skryptu wlasciwego .... 2. Pozwala ona na dynamczne deniowanie pewnych partii kodu w oparciu o ju» przeprowadzone dziaªania i/lub dodane nowe czy to z pliku, czy przez interakcj¦ z u»ytkownikiem na przykªad przez okna dialogowe (patrz tak»e funkcje evstr oraz execstr). 3.5.5 Okna dialogowe W przykªadzie z rodziaªu 2 widzieli±my wykorzystanie funkcji teraktywne pobranie pewnych danych od u»ytkownika. Funkcja input pozwalaj¡cej na indisp pozwalaªa natomiast wyprowadzi¢ pewne informacje na ekran. W Scilabie dost¦pna jest grupa funkcji zwi¡zanych z oknami dialogowymi, menu, wyborem pliku: x_mdialog, x_message, xgetfile x_choices, x_choose, x_dialog, x_matrix, . Po szczegóªowe informacje z nimi zwi¡zane odsyªamy do pomocy (zawarte s¡ tam równie» odpowiednie przykªady). 3.5.6 Konwersja ªa«cucha znakowego do wyra»enia Cz¦sto u»ytecznym okazuje si¦ mo»liwo±¢ ewaluacji wyra»enia podanego w postaci ªa«cucha znaków (czyli napisu). Konwersji takiej dokona¢ mo»emy za pomoca funkcji evstr -->c = "sqrt(3)/2" c = sqrt(3)/2 -->d = evstr(c) d = 0.8660254 W takim ªa«cuchu znaków mo»na u»ywa¢ zdeniowanych uprzenio zmiennych -->a = 1; -->b=evstr("2 + a") b = 3. Funkcja ta oczywi±cie mo»liwa jest tak»e do zastosowania w stosunku do macierzy zªo»onych z ªa«cuchów znaków 9 -->evstr(["a" "2" ]) ans = ! 1. 2. ! -->evstr([" a + [1 2]" "[4 , 5]"]) ans = ! 2. 3. 4. 5. ! 9 A tak»e list, patrz help. 54 -->evstr(["""a""" """b"""]) ans = !a b ! Istnieje tak»e funkcja, // zamiana lancucha na lancuch execstr, pozwalaj¡ca wykona¢ instrukc¦ Scilaba podan¡ w formie ªa«cucha znaków -->execstr("A=rand(2,2)") -->A A = ! 0.2113249 0.0002211 ! ! 0.7560439 0.3303271 ! 3.6 Czytanie i pisanie . . . . . . z/do pliku lub okna Scilaba. Scilab posiada dwie rodziny wej±¢/wyj±¢. Powinno si¦ unika¢ mieszania ze sob¡ obsªuguj¡cych je funkcji zwªaszcza gdy operacje te zwi¡zane s¡ z plikiem. 3.6.1 Wej±cie i wyj±cie w stylu Fortranu W rozdziale drugim widzieli±my jak zapisywa¢ i odczytywa¢ macierz liczb rzeczywistych za pomoc¡ funkcji read oraz write. To samo mo»emy zrobi¢ w stosunku do wektora kolumnowego zªo»onego z ªa«cuchów znaków -->v = ["Scilab is free";"Octave is free";"Matlab is ?"]; -->write("toto.dat",v,"(A)") // zobacz jak wyglada plik toto.dat -->w = read("toto.dat",-1,1,"(A)") w = !Scilab is free ! !Octave is free ! !Matlab is ? ! ! ! ! ! Podczas zapisu dodajemy trzeci argument okre±laj¡cy format zapisu w stylu Fortaranu. Jest nim ªa«cuch znaków, zawarty pomi¦dzy nawiasami okr¡gªymi, zawieraj¡cy jed¡ lub wi¦cej specykacji zapisu (rozdzielonych przecinkiem); w przykªadzie powy»ej A oznacza, »e chcemy zapisa¢ ªa«cuch znaków. Przy odczycie drugi i trzeci argument oznaczaj¡ odpowiednio ilo±c linii (-1 oznacza czytanie do ko«ca pliku) i kolumn. W przypadku macierzy liczbowych nale»y ponadto poda¢ format okre±laj¡cy precyzj¦ z jak¡ nale»y wynik zapisa¢. Generalnie mo»liwo±ci Scilaba dotycz¡ce obsªugi plików s¡ identyczne jak dla Fortrana 77, dlatego te» mo»na szuka¢ informacji na ten temat w ksi¡»kach jemu po±wi¦conych. Poni»ej podane zostan¡ przykªady zwi¡zane z dost¦pem sekwencyjnym do plików tekstowych. Otwieranie pliku Plik otwieramy za pomoc¡ funkcji file 55 [unit, [err]]=file('open', file-name ,[status]) gdzie file-name jest ªa«cuchem znaków okre±laj¡cym plik (ewentualnie poprzedzonym ±cie»k¡ dost¦pu, je±li nie znajduje si¦ on w »adnym z katalogów b¦d¡cych w ±cie»ce przeszukiwania Scilaba; ±cie»k¦ t¡ mo»na zmieni¢ za pomoc¡ funkcji status chdir). przyjmuje jedn¡ z nast¦puj¡cych warto±ci new w celu otworzenia nowego pliku; je±li plik o podanej nazwie istnieje, generowany jest bª¡d; old w celu otworzenia ju» istniej¡cego pliku; je±li plik o podanej nazwie nie istnieje, generowany jest bª¡d; unknow je±li plik o podanej nazwie nie istnieje, to zostanie utowrzony, w przeciwnym razie zostanie otwarty plik ju» istniej¡cy; W przypadku braku argumentu status przyjmowana jest dla niego domy±lna warto±¢ new. unit jest zmienn¡ za pomoc¡ której b¦dziemy odwoªywa¢ si¦ do otwieranego pliku podczas operacji plikowych; Je±li obecny b¦dzie argument err mo»liwe b¦dzie stwierdzenie czy operacja otwierania pliku si¦ powiodªa; w przeciwnym razie Scilab generuje bª¡d. Warto±¢ równa brak b¦dów zwi¡zanych z otwieraniem pliku. W innym przypadku pisz¡c 0 oznacza error(err) mo»na zobaczy¢ troch¦ wi¦cej szczegóªów na temat napotkanego bª¦du -->error(240) // zakladamy, ze err=240 !--error 240 File error(240) already exists or directory write access denied U»ycie funkcji xgetfile pozwala na interaktywny wybór pliku przez przegl¡danie drzewa hierarchi plików i katalogów. Pisanie i czytanie Zaªó»my, »e mamy otwarty plik. Je±li plik ju» istniaª, czytanie/pisanie rozpocznie si¦ od pocz¡tku (b¦dziemy mówi¢, »e wska¹nik pliku zostaª ustawiony na pocz¡tek pliku). chcemy pisa¢ na koniec pliku nale»y wcze±niej, za pomoc¡ funkcji Je±li file("last", unit), ustawi¢ wska¹nik pliku na jego koniec. Powrót na pocz¡tek mo»liwy jest po wykonaniu instrukcji file("rewind", unit). n punktów Pi = (xi ; yi ) oraz m odcinków; ka»dy opisany jako jeden segment Pi P!j przez podanie numeru (w tablicy punktów) punktu pocz¡tkowego (tutaj i) i ko«cowego (tutaj j ). Poni»ej przedstawiamy format pliku Oto pierwszy przykªad. Chcemy zapisa¢ do pliku list¦ odcinków na pªaszczy¹nie. W tym celu rozwa»amy linia z tekstem n x_1 y_1 ... x_n y_n m i1 j1 ... im jm 56 W linii z tekstem mo»emy zawrze¢ pewne dodatkowe informacje zwi¡zane z plikiem. Nast¦pnie podajemy ilo±¢ punktów oraz ich wspóªrz¦dne. Dalej za± ilo±¢ odcinków i numery wierzchoªków text, punkty P wymiaru (n; 2), odcinki za± przez macierz connect wymiaru (m; 2). Wszystkie je tworz¡cych. Zaªó»my, »e linia z tekstem reprezentowana jest przez zmienn¡ przez macierz te informacje zostan¡ zapisane po wprowadzeniu nast¦puj¡cego ci¡gu instrukcji write(unit,texte) write(unit,size(P,1)) write(unit,P) write(unit,size(connect,1)) write(unit,connect) file("close",unit) // // // // // // zapisanie linii z tekstem zapisanie ilosci punktow zapisanie wspolrzednych punktow zapisanie ilosci odcinkow zapisanie punktów definiujacych odcinki zamkniecie pliku Efekt mo»e wygl¡da¢ jak poni»ej przypadkowy wielokat 5.0000000000000 0.28553641680628 0.86075146449730 0.84941016510129 0.52570608118549 0.99312098976225 5.0000000000000 1.0000000000000 2.0000000000000 3.0000000000000 4.0000000000000 5.0000000000000 0.64885628735647 0.99231909401715 5.0041977781802D-02 0.74855065811425 0.41040589986369 2.0000000000000 3.0000000000000 4.0000000000000 5.0000000000000 1.0000000000000 co nie prezentuje si¦ elegancko, gdy» nie podali±my formatu w jakim nale»y dane zapisa¢. Jak 10 . Ponadto tekst zostaª wida¢ liczby caªkowite traktowane s¡ przez Scilaba jak rzeczywiste poprzedzony spacj¡ (której nie byªo w text). W celu poprawienia tych niedogodno±ci, nale»y doda¢ specykacj¦ okre±laj¡c¡ sposób traktowania danych Dla liczb caªkowitych nale»y u»y¢ Ix, gdzie x jest dodatni¡ liczb¡ okre±laj¡c¡ szeroko±¢ pola. y za± szeroko±¢ mantysy; wyj±cie przyjmuje wówczas posta¢ [znak]0.mantysaE[znak]wykladnik. Dla liczb rzeczywistych nale»y u»y¢ Ex.y, gdzie x okre±la caªkowit¡ szeroko±¢ pola, Dla liczb zmiennopozycyjnych podwójnej prezycji otrzymamy w ten sposób zapis z 16 cyframi znacz¡cymi i wykªadnikiem o warto±ciach pomi¦dzy -330 i +300 co ª¡cznie daje szeroko±¢ okoªo 24 znaków. Tak wi¦c mo»na u»y¢ formatu E24.16 (w zale»nie od wielko±ci liczb oraz oczekiwanej formy ich prezentacji inne formaty mog¡ okaza¢ si¦ bardziej odpowied- nie). Dla unikni¦cia spacji na pocz¡tku tekstu nale»y u»y¢ A. Rozwa»aj¡¢ poprzedni przykªad mo»emy uzyska¢ bardziej elegancki format zapisu (zakªadamy, »e ilo±¢ punktów jest nie wi¦ksza jak 999) write(unit,texte,"(A)") write(unit,size(P,1),"(I3)") 10 // zapisanie linii z tekstem // zapisanie ilosci punktow Od wersji 2.5 mamy do dyspozycji typy int8, int16 et int32; patrze 57 Help. mopen mclose mprintf, mscanf mfprintf, mfscanf msprintf, msscanf otwieranie pliku zamykanie pliku pisanie i czytanie z okna Scilaba pisanie i czytanie z pliku pisanie i czytanie z ªa«cucha znaków Tablica 3.3: write(unit,P,"(2(X,E24.16))") write(unit,size(connect,1),"(I3)") write(unit,connect,"(2(X,I3))") file("close",unit) (format // // // // zapisanie wspolrzednych punktow zapisanie ilosci odcinkow zapisanie punktow definiujacych odcinki zamkniecie pliku X odpowiada za wypisanie jednego biaªego znaku, natomiast powtórzenie 2(X,E24.16) oznacza »e w tej samej lini chcemy wypisa¢ dwa pola zawieraj¡ce biªy znak, po nim za± liczb¦ zmiennoprzecinkow¡ zapisan¡ na 24 znakach) przypadkowy wielokat 5 0.2855364168062806E+00 0.8607514644972980E+00 0.8494101651012897E+00 0.5257060811854899E+00 0.9931209897622466E+00 5 1 2 2 3 3 4 4 5 5 1 0.6488562873564661E+00 0.9923190940171480E+00 0.5004197778180242E-01 0.7485506581142545E+00 0.4104058998636901E+00 Aby odczyta¢ utworzony w ten sposób plik mo»na u»y¢ nast¦puj¡cej sekwencji instrukcji texte=read(unit,1,1,"(A)") n = read(unit,1,1) P = read(unit,n,2) m = read(unit,1,1) connect = read(unit,m,2) file("close",unit) // // // // // // odczytanie odczytanie odczytanie odczytanie odczytanie zamkniecie linii z tekstem ilosci punktow wspolrzednych punktow ilosci odcinkow punktow definiujacych odcinki pliku Przygl¡daj¡c si¦ podanym przykªadom, wida¢, »e zamykanie pliku odbywa si¦ za pomoc¡ insrukcji file(close,unit). Czytanie b¡d¹ pisanie do okna Scilaba odbywa si¦ przy pomocy, odpowiednio, funkcji = %io(1) et unit = %io(2). stosuj¡c standardow¡ funkcj¦ unit Przy wypisywaniu mo»na ró»nie» osi¡gn¡¢ lepsze efekty ni» disp (patrz przykªad w rozdziale Ciekawostki w sekcji Proste instrukcje i funkcje Scilaba, funkcja MonteCarlo). 3.7 Wej±cie i wyj±cie w stylu C Podstawowe funkcje zwi¡zane z obsªuga plików przedstawiono w tabeli 3.3. teraz wyja±ni¢ kwestie zwi¡zane z u»yciem funkcji pisz¡cych na przykªadzie 58 Postaramy si¦ mprintf. n = 17; m = -23; a = 0.2; b = 1.23e-02; c = a + %i*b; s = "kukulka"; mprintf("\n\r mprintf("\n\r mprintf("\n\r mprintf("\n\r mprintf("\n\r mprintf("\n\r n a a a c s = = = = = = %d, m = %d", n, m); // %d dla calkowitych %g", a); // %g dla rzeczywistych %e", a); // %e dla rzeczywistych (notacja z wykladnikiem) %24.16e", a); // okreslenie ilosci wyswietlanych cyfr %g + i %g", real(c), imag(c)); // liczba zespolona %s", s); // %s dla lancucha znakow Zapisuj¡c powy»sze instrukcje w pliku i wywoªuj¡c je poleceniem exec("demo_mprintf.sce"); jako wyj±cie powinni±my zobaczy¢ n a a a c s = = = = = = 17, m = -23 0.2 2.000000e-01 2.0000000000000001e-01 0.2 + i 0.0123 kukulka Do peªnego zrozumienia brakuje jeszcze kilka wyja±nie« Konstrukcja %x \n\r powoduje przej±cie do nowej linii (w systemie Unix wystarczy samo \n). jest dyrektyw¡ formatuj¡c¡ wyj±cie, to znaczy okre±laj¡c¡ w jaki sposób nale»y trak- towa¢ (i w konsekwencji wy±wietli¢) zmienn¡. I tak 1. %d 2. %e dla liczb rzeczywistych przedstawianych w notacji naukowej (z wykªadnikiem). dla liczb caªkowitych cie powinno przyjmowa¢ posta¢ [ ]c0 :c1 :::c6 ed1 d2 [d3 ]. rozdzielone przecinkiem (pomi¦dzy znakiem Wyj±- Dodaj¡c dwie liczby caªkowie % oraz e) pkre±lamy caªkowit¡ ilo±¢ znaków na jakich liczba zostanie zapisana oraz ilo±¢ cufr po przecinku. 3. %g powoduje wy±wietlenie liczby bez wykªadnika (je±li mie±ci si¦ ona w odpowiednim przedziale) lub z wykªadnikiem. 4. %.3f powoduje wy±wietlenie liczby rzeczywistej bez wykªadnika zapisanej na 5 znakach i 3 cyframi po przecinku. 5. %s dla ªa«cucha znaków. Ka»dej dyrektywie musi odpowiada¢ jedna warto±¢, która ma zosta¢ wy±wietlona (pochodz¡ca od zmiennej, wyra»enia czy te» staªej). Je±li chcemy wy±wietli¢ 4 liczby caªkowite musimy poda¢ 4 dyrektywy mprintf("%d %d %d %d", expr1, expr2, expr3, expr4); Ciekawostka Dlaczego wy±wietlenie liczby 0:2 w formacie 24.16e wygl¡da dziwnie? Wynika to z niemo»no±ci 0:2 w systemie dwójkowym. reprezentacji z odpowiedni¡ precyzj¡ liczby 59 3.8 Uwagi zwi¡zane z szybko±ci¡ Zobaczmy dwa przykªady przedstawiaj¡ce kilka znanych sposobów tutu. Zaªó»my, »e chcemy znale¹¢ (obliczy¢ tutu) macierz Vandermondea 2 1 t1 t21 : : : 66 1 t2 t22 : : : A = 6 .. .. .. .. 4. . . . 3 tn1 tn2 7 7 . . . 1 tm t2m : : : tnm 75 Oto narzucaj¡cy si¦ w pierwszej chwili kod function A=vandm1(t,n) // obliczenie macierzy Vandermonde A=[a(i,j)] 1<= i <= m // 1<= j <= n+1 // gdzie a(i,j) = ti^(j-1) // t musi byc wektorem kolumnowym o m skladowych m=size(t,'r') for i = 1:m for j = 1:n+1 A(i,j) = t(i)^(j-1) end end endfunction Poniewa» w Scilabie a priori nie deklaruje si¦ rozmiaru macierzy ani innych obiektów dlatego nie ma potrzeby informowania funkcji, »e nasza macierz A jest wymiaru (m; n + 1). jak post¦puj¡ obliczenia Scilab musi upora¢ si¦ ze zmianami w macierzy A W miar¦ wynikaj¡cymi ze i = 1 A jest wektorem liniowym o j skªadowych, dla i > 1 A jest (i; n + 1), mamy wi¦c n + m 1 zmian wymiaru macierzy A co oczywi±cie zwi¦kszania jej wymiaru (dla macierz¡ wymiaru zwi¡zane jest z potrzeb¡ po±wi¦cenia na to pewnej ilo±ci czasu, tym wi¦kszej im wi¦ksza jest macierz). Problem ten mo»na obej±¢ wykorzystuj¡c pseudo-deklaracj¦ zeros(m,n+1) function A=vandm2(t,n) // identycznie jak w vandm2 oprocz pseudo-deklaracji dla A m=size(t,'r') A = zeros(m,n+1) // pseudo-deklaracja for i = 1:m for j = 1:n+1 A(i,j) = t(i)^(j-1) end end endfunction Tym oto sposobem pozbywamy si¦ tego problemu i zyskujemy cenny czas, który mo»na spo»ytkowa¢ efektywniej. : -->t = linspace(0,1,1000)'; -->timer(); A = vandm1(t,200); timer() ans = 6.04 -->timer(); A = vandm2(t,200); timer() ans = 1.26 A instrukcj¦ ones(m,n+1) (unikamy wtedy obliczania pierwszej kolumny ), wykonuj¡c jedynie mno»enie aij = aij 1 ti (to natomiast pozwala unikn¡¢ oblicze« zwi¡zanych z pot¦gowaniem) widzimy Mo»na próbowa¢ zoptymalizowa¢ ten kod stosuj¡c przy inicjalizacji macierzy odwracaj¡c dwie p¦tle, ale co± zyskujemy. Lepsze rezultaty mo»na osi¡gn¡¢ zauwa»aj¡c, »e konstrukcja macierzy A umo»liwia wykorzystanie instrukcji wektorowych 60 function A=vandm5(t,n) // dobra metoda: uzycie zapisu macierzowego m=size(t,'r') A=ones(m,n+1) for i=1:n A(:,i+1)=t.^i end endfunction function A=vandm6(t,n) // wskaznik na vandm5 z malym ulepszeniem m=size(t,'r') A=ones(m,n+1) for i=1:n A(:,i+1)=A(:,i).*t end endfunction Prowadzi to do znacznego poprawienia szybko±ci oblicze« -->timer(); A = vandm5(t,200); timer() ans = 0.05 -->timer(); A = vandm6(t,200); timer() ans = 0.02 Oto drugi przykªad: zadanie polega na rozwini¦ciu funkcji kapelusz (patrz rysunek 3.2) w wielu punktach (liczby rzeczywiste ustawione w wektor lub macierz): 8 0 > > < t (t) = bc > > :c ta si a t b si b t c 0 si t c si a a t b Chc¡c zdeniowa¢ t¡ funkcj¦ w kawaªkach rozwijanie w punkcie wymaga¢ bedzie dodatkowych Rysunek 3.2: Funkcja kapelusz testów. Gdy obliczenia b¦d¡ dotyczy¢ wielu punktów dobrze by byªo zastanowi¢ si¦ nad mo»liwo±i¡ wektoryzacji oblicze«. Pierwszy kod realizuj¡cy postawione zadanie mógªby wygl¡da¢ nast¦puj¡co function [y]=phi1(t,a,b,c) // rozwija funkcje ,,kapelusz'' (z parametrami a, b oraz c) na wektorze // (czytaj macierzy) t w sensie ,,element po elemencie'' // a,b oraz c musza spelniac zaleznosc a < b < c [n,m] = size(t) y = zeros(t) for j=1:m, for i=1:n if t(i,j) > a then if t(i,j) < b then y(i,j) = (t(i,j) - a)/(b - a) elseif t(i,j) < c then y(i,j) = (c - t(i,j))/(c - b) 61 end end end, end endfunction daj¡c w efekcie -->a = -0.2 ; b=0 ; c=0.15; -->t = rand(200000,1)-0.5; -->timer(); y1 = phi1(t,a,b,c); timer() ans = 2.46 Kolejna próba, w której wykorzystujemy funkcj¦ macierzy liczb rzeczywistych wedªug schematu: bool2s konwertuj¡c¡ macierz boolowsk¡ do prawda przechodzi w 1, faªsz przechodzi w 0 function [y]=phi2(t,a,b,c) // rozwija funkcje ,,kapelusz'' (z parametrami a, b oraz c) na wektorze // (czytaj macierzy) t w sensie ,,element po elemencie'' // a,b oraz c musza spelniac zaleznosc a < b < c Indicatrice_a_b = bool2s( (a < t) & (t <= b) ) Indicatrice_b_c = bool2s( (b < t) & (t < c ) ) y = Indicatrice_a_b .* (t - a)/(b - a) + Indicatrice_b_c .* (c - t)/(c - b) endfunction function [y]=phi3(t,a,b,c) // jak phi2 z niewielka optymalizacja t_le_b = ( t <= b ) Indicatrice_a_b = bool2s( (a < t) & t_le_b ) Indicatrice_b_c = bool2s( ~t_le_b & (t < c) ) y = Indicatrice_a_b .* (t - a)/(b - a) + Indicatrice_b_c .* (c - t)/(c - b) endfunction okazuje si¦ lepszym rozwi¡zaniem -->timer(); y2 = phi2(t,a,b,c); timer() ans = 0.12 -->timer(); y3 = phi3(t,a,b,c); timer() ans = 0.12 -->timer(); y4 = phi4(t,a,b,c); timer() // patrz dalej na definicje phi4 ans = 0.1 Uwagi Niewielka optymalizacja w phi2 nie przyniosªa »adnych zysków (jak miaªo to natomiast miejsce dla poprzedniej wersji Scilaba uruchomionej na innej maszynie); Kod phi4 korzysta z funkcji find, która jest bez w¡tpienia bardziej naturalna i prostsza w u»yciu: dla wektora boolowskiego b(i)=%t b zwraca ona wektor i zªo»ony z indeksów takich, »e (pusty gdy wszystkie warto±ci s¡ faªszem). Przykªad -->x = rand(1,6) x = ! 0.8497452 0.6857310 0.8782165 62 0.0683740 0.5608486 0.6623569 ! -->ind = find( 0.3<x & x<0.7 ) ind = ! 2. 5. 6. ! Dla macierzy boolowskiej A otrzymujemy tak¡ sam¡ list¦ je±li przyjmiemy, »e macierz jest du»ym wektorem gdzie elementy uªo»one s¡ kolumna po kolumnie. St¡d korzystaj¡c z drugiego argumentu mo»na uzyska¢ list¦ z indeksami kolumn i wierszy w których speªniony jest warunek -->A = rand(2,2) A = ! 0.7263507 0.5442573 ! ! 0.1985144 0.2320748 ! -->[il,ic]=find(A<0.5) ic = ! 1. 2. ! il = ! 2. 2. ! Spójrzmy teraz na kod funkcji phi4 function [y]=phi4(t,a,b,c) // uzycie funkcji find jest bardziej naturalne t_le_b = ( t <= b ) indices_a_b = find( a<t & t_le_b ) indices_b_c = find( ~t_le_b & t<c ) y = zeros(t) y(indices_a_b) = (t(indices_a_b) - a)/(b - a) y(indices_b_c) = (c - t(indices_b_c))/(c - b) endfunction Wniosek: je±li obliczenia trwaj¡ za dªugo, spróbujmy dokona¢ wektoryzacji. Je±li taka operacja nie jest mo»liwa lub niewystarczaj¡ca, nie pozostaje nic innego jak napisanie istotnych fragmentów w C lub Fortranie 77. 3.9 wiczenia 1. Napisz funkcj¦ rozwi¡zuj¡c¡ ukªad równa« liniowych z górn¡ macierz¡ trójk¡tn¡. funkcji size U»yj pozwalaj¡cej uzyska¢ wymiary macierzy [n,m]=size(A) Za pierwszym razem napisz klasyczny algorytm wykorzystuj¡c dwie p¦tle. Nast¦pnie spróbuj zast¡pi¢ p¦tle instrukcj¡ macierzow¡. W celu przetestowania swojej funkcji mo»na wygenerowa¢ macierz zªo»on¡ z elementów pseudo-losowych i wydoby¢ z niej macierz trójk¡tn¡ poleceniem A=triu(rand(4,4)) 2. Rozwi¡zanie ukªadu równa« ró»niczkowych pierwszego rz¦du dx (t) = Ax(t); x(0) = x0 2 Rn ; x(t) 2 Rn ; A 2 Mnn (R) dt uzyska¢ mo»na wykorzystuj¡c eksponent macierzy (patrz kurs analizy, rok pierwszy). x(t) = eAt x0 Poniewa» Scilab posiada funkcj¦ licz¡c¡ eksponent macierzy (expm) pozostaje jeszcze kilka rzeczy do zrobienia. Chcemy otrzyma¢ rozwi¡zanie dla 63 t 2 [0; T ]. W tym celu mo»na znale¹¢ liczb¦ n wystarczaj¡co du»¡ na tym przedziale tk = kt, t = T=n oraz wykorzysta¢ wªasno±ci exponent w celu uproszczenia oblcze« x(tk ) = eAkt x0 = ek(At) x0 = (eAt )k x0 = eAt x(tk 1 ) At, nast¦pnie wykona¢ n mno»e« macierzy x(t1 ); x(t2 ); : : : ; x(tn ). Napisz skrypt rozwi¡zuj¡cy równanie Zatem wystarczy obliczy¢ exponentel macierzy wektorowych aby otrzyma¢ ró»niczkowe postaci (oscylacje z amortyzacj¡) x00 + x0 + kx = 0; przyjmuj¡c na przykªad = 0:1; k = 1; x(0) = x0 (0) = 1 które przyjmuje oczywi±cie posta¢ ukªadu dwóch równa« pierwszego rz¦du. Na zako«czenie mo»na zobrazowa¢ zmiany x jako funkcj¦ czasu a nast¦pnie trajektorj¦ w przestrzeni fa- zowej. Pomi¦dzy oknami gracznymi mo»na przechodzi¢ za pomoc¡ funkcji --> --> --> --> --> xset("window",window //koniec obiczen xset(``window'',0) // wybor okna o numerze 0 instrukcje dla pierwszego rysunku (który pokaze sie w oknie 0) xset(``window'',1) // wybor okna o numerze 1 instrukcje dla drugiego rysunku (który pokaze sie w oknie 1) [i,info]=intervalle_de(t,x) dla okre±lenia przedziaªu i takiego, »e xi t xi+1 za pomoc¡ metody dychotomii (skªadowe wektora x s¡ takie »e xi < xi+1 ). Gdy t 2= [x1 ; xn ] zmienna boolowska info powinna przyjmowa¢ warto±¢ równ¡ %f (oraz %t w 3. Napisz funkcj¦ przeciwnym razie). myhorner tak aby mogªa dziaªa¢ w przypadku gdy argument t jest macierz¡ p (takiego samego wymiaru jak t) gdzie ka»dy wspóªczynodpowiada rozwini¦ciu wielomianu t(i,j)). 4. Napisz funkcj¦ (funkcja powinna zwraca¢ macierz nik (i; j ) 5. Napisz funkcj¦ [y] = sygnal_fourier(t,T,cs), która zwraca szereg Fouriera wykorzys- tuj¡c funkcje 2t 2t 4t 4t f1 (t; T ) = 1; f2 (t; T ) = sin( t); f3 (t; T ) = cos( ); f4 (t; T ) = sin( ); f5 (t; T ) = cos( ); T T T T zamiast funkcji eksponenet. T jest parametrem (okres), sygnaª za± opisywany jest przez przez wektor cs zªo»ony ze wspóªczynników w bazach f1 ; f2 ; f3 ; Ilo±¢ funkcji uzyska¢ length zastosowanej do cs. Zaleca si¦ wykorzystanie funkcji pomocniczej [y]=f(t,T,k) obliczaj¡cej fk (t; T ). Wszystko to powinno pozwala¢ na stosowanie dla wektora czy macierzy instants t co pozwoli na ªatwe zobrazowanie sygnaªu mo»na dzi¦ki instrukcji --> --> --> --> --> --> T = 1 // okres t = linspace(0,T,101) // momenty ... cs = [0.1 1 0.2 0 0 0.1] // sygnal ze skladowa ciagla // fundamentalna, bez harmonicznej 1 (okres 2T) ale z harmoniczna 2 [y] = sygnal_fourier(t,T,cs); // obliczenie sygnalu plot(t,y) // wykres 6. Oto funkcja licz¡ca iloczyn wektorowy dwóch wektorów function [v]=prod_vect(v1,v2) // iloczyn wektorowy v = v1 /\ v2 v(1) = v1(2)*v2(3) - v1(3)*v2(2) v(2) = v1(3)*v2(1) - v1(1)*v2(3) v(3) = v1(1)*v2(2) - v1(2)*v2(1) endfunction 64 Dokonaj wektoryzacji tego kodu w taki sposób aby obliczac w (tej) jednej funkcji produkt wektorowy vi = 1 zawierajacej te wektory. 7. Spotkanie : vi ^ vi 2 gdzie vi, vi 1 i vi 2 function [v]=pro oznaczaj¡ i-t¡ kolumn¦ macierzy (3,n) Pan A i Pani B zamierzaj¡ spotka¢ si¦ mi¦dzy godzin¡ 17:00 a 18:00. Ka»de z nich przyb¦dzie niezale»nie od drugiego pomi¦dzy [17; 18]. Pani B b¦dzie czeka¢ 5 minut zanim odejdzie, Pan A 10 minut. (a) Jakie jest prawdopodobie«stwo, »e si¦ spotkaj¡? (odp. 67/288) (b) Znajd¹ (przybli»one) wyniki przez symulacj¦: napisz funkcj¦ prawdopodobie«stwo empiryczne spotkania przy m próbach. [p] = rdv(m) (c) Przetestuj dziaªanie swojej funkcji dla coraz wi¦kszych warto±ci 65 m. zwracaj¡c¡ Rozdziaª 4 Graka W zakresie tworzenia graki Scilab posiada wiele mo»liwo±ci zarówno je±li bra¢ pod uwag¦ operacje niskopoziomowe jak te» bardziej zlo»one funkcje pozwalaj¡ce operowa¢ skomplikowanymi obiektami. W dalszym ci¡gu zostanie wyja±niona jedynie maªa cz¦±¢ dost¦pnych mo»liwo±ci. Uwaga: Dla osób znaj¡cych instrukcje graczne MATLABA Stephane Mottelet napisaªa (tutu czy napisal) bibliotek¦ funkcji gracznych wywoªywanych w stylu MATLABA; dost¦pna jest ona pod adresem http://www.dma.utc.fr/~mottelet/scilab/ 4.1 Okna graczne Wywoªanie instrukcji gracznej takiej jak plot czy plot3d powoduje umieszczenie rysowanego obrazu w oknie racznym o numerze 0. Wywoªanie funkcji gracznej powoduje na ogóª powstanie nowego obrazu na ju» istniej¡cym, st¡d potrzeba uprzedniego wymazania zawarto±ci okna przy pomocy funkcji aj¡c z menu File opcj¦ xbasc(). Wymazania zawarto±ci okna mo»na tak»e dokona¢ wybierclear. Manipulowanie oknami mo»liwe jest dzieki nast¦puj¡cym funkcjom xset("window",num) num okno o numerze staje si¦ oknem bie»¡cym; je±li »adne okno nie istniaªo to zostanie utworzone xselect() uaktywnia bie»¡ce okno; je±li »adne okno nie istniaªo to zostanie utworzone xbasc([num]) wymazuje zawarto±¢ okna o numerze num ; je±li zostanie pomini¦ty numer to wymazana zostanie zawarto±¢ bie»¡cego okna xdel([num]) powoduje zamkni¦cie okna o numerze num ; je±li zostanie pomini¦ty numer to zamkni¦te zostanie bie»¡ce okno Jako generaln¡ zasad¦ mo»na przyj¡¢, »e po wybraniu bie»¡cego okna (przez xset("window",num)) xset("nom",a1,a2,...) mo»emy dokonywa¢ zmian w parametrach nom okre±la nazw¦ parametru, który chcemy zmieni¢ jak na przykªad chcemy dostosowa¢ grybo±¢ strzaªek czy colormap gdy chcemy zmieni¢ u»y- za pomoca instrukcji zwi¡zanych z oknem. thickness gdy wan¡ palet¦ kolorów. Za nazw¡ podajemy jeden lub wi¦cej argumentów wmaganych do ustawienia nowej warto±ci parmetru. Zbiór tych parametrów nazywany jest kontekstem gracznym; ka»de okno posiada swój taki kontekst. W celu zdobycia wi¦kszej ilo±¢ informacji na temat parametów (których jest caªkiem pokany zbiór) odsyªsamy do Library. Help-u i tematu Graphic W wi¦kszo±ci sytuacji mog¡ one by¢ zmieniane interaktywnie przez menu graczne, ukazuj¡ce si¦ po wydaniu polecenia xset(). 66 Uwaga: W tym menu dost¦pne jest równie» ( podokno opisuj¡ce kolory; nie jest jenak mo»liwe wprowadzanie zmian do tego» opisu. ina funkcji [a1,a2,...]=xget('nazwa') Rodz- pozwala otrzyma¢ parametry zwi¡zane z pewnym kontekstem gracznym. 4.2 Wprowadzenie do plot2 Wcze±nie mieli±my ju» do czynienia z prosta instrukcj¡ wi¦cej krzywych lepiej stosowa¢ funkcj¦ plot2d. plot. Je±li jednak zamierzamy wykre±lic Najpro±ciej mo»na j¡ u»y¢ jak to pokazano poni»ej x=linspace(-1,1,61)'; // odci\k{e}te (wektor kolumnowy) y = x.^2; // rz\k{e}dne (równie\.z wektor kolumnowy) plot2d(x,y) // --> il lui faut des vecteurs colonnes ! tutu Doªó»my teraz inn¡ krzyw¡ . . . ybis = 1 - x.^2; plot2d(x,ybis) xtitle("Krzywe...") // dodajemy tytu\l{} 1 ni» poprzednie . . . i jeszcze jedn¡, która tutu jest w innej skali yter = 2*y; plot2d(x,yter) Zauwa»my, »e Scilab przeskalowaª okno tak aby zmie±ciªa si¦ w nim trzecia krzywa, ale tak»e odrysowaª dwie poprzednie krzywe w nowej skali (wydaje si¦ to naturalne, ale mechanizm ten nie byª obecny a» do wersji 2.6 wprowadzaj¡c czesto w bªad). Mo»liwe jest wykre±lenie tych trzech krzywych za jednym razem xbasc() // aby wyczy\'scic obszar rysowania plot2d(x,[y ybis yter]) // konkatenacja macierzy xtitle("Krzywe...","x","y") // tytu\l{} i nazwy dla obu osi Otrzymujemy w ten sposób wykres podobny do tego przedstawionego na rysunku 4.1. Rysunek 4.1: Les fonctions W x2 , 1 x2 et 2x2 plot2d(Mx,My) nc jest równa ilo±ci krzywych a i-ta krzywa jest otrzymywana na podstawie wektorów Mx(:,i) (odci¦te) i My(:,i) celu jednoczesnego wykre±lenia kilku krzywych, instrukcja przyjmuje posta¢ gdzie Mx (rz¦dne). oraz My s¡ macierzami o identycznym wymiarze, ilo±¢ kolumn W sytuacji gdy wektor odci¦tych jest taki sam dla wszystkich krzywych (jak w naszym przypadku), mo»na poda¢ go jeden raz zamiast powtarza¢ zamiast 4.3 plot2d([x x .. plot2d x],My)). nc razy (plot2d(x,My) z argumentami opcjonalnymi Ogólna skªadnia przedstawia si¦ nast¦puj¡co plot2d(Mx,My <,opt_arg>*) gdzie 1 2 <,opt_arg>* oznacza opcjonalny ci¡g dodatkowych argumentów postaci 2 Pod poj¦ciem skali rozumiemy tutaj obszar w jakim zostanie wykre±lona krzywa oraz ewentualne dodatkowe cechy. argumentFormalny = argumentEfektywny 67 sªowoKluczowe=warto±¢ podanych w dowolnej kolejno±ci. Poka»emy podstawowe epcje przy pomocy kilku przykªadów 1. Wybór koloru i deniowanie legendy W poprzednim przykªadzie mo»na byªo zaobserwowa¢, »e Scilab wykre±liª 3 krzywe przy u»yciu 3 ró»nych (pierwszych) kolorów okre±lonch w domy±lnej palecie kolorów 1 czarny 5 czerwony 23 oletowy 2 niebieski 6 oªkowo-ró»owy 26 br¡zowy 3 jasno-zielony 13 ciemno-zielony 29 ró»owy 4 cyan 16 jasno-niebieski tutu 32 jaune orangé xset() pozwala na ich zmian¦ 3 . Celem wybrania koloru u»ywamy zapisu styl=vect, gdzie vect jest wektorem liniowym zawieraj¡cym numery kolorów dla ka»dej krzywej. Legend¦ otrzymujemy pisz¡c leg=str, gdzie str jest ªañcuchem znaków postaci leg1@leg2@... w którym legi jest podpisem dla i-tej krzywej. Oto przykªad (porówaj Instrukcja rysunek (4.2)) : x = linspace(0,15,200)'; y = besselj(1:5,x); xbasc() plot2d(x, y, style=[2 3 4 5 6], leg="J1@J2@J3@J4@J5") xtitle("Funkcje Bessela J1, J2,...","x","y") Poniewa» kolejno±¢ argumentów opcjonalnych nie jest istotna równie dobrze mo»na napisa¢ plot2d(x, y, leg="J1@J2@J3@J4@J5", style=[2 3 4 5 6]) Rysunek 4.2: Wybrany styl i legenda 2. Wkresy zawieraj¡ce symbole Czasami, gdy wa»ne jest wyrane wskazanie punktów przez które wykres przechodzi, przydatne mog¡ okaza¢ si¦ znaczniki tutu. Mo»emy wybra¢ jeden z kilku rodzajów zancznika przedstawionych poni»ej styl 0 symbol -1 -2 -3 -4 -5 -6 -7 -8 + } 4 5 | -9 Dla przykªadu spróbujmy (porównaj rysunek (4.3)) : x = linspace(0,2*%pi,40)'; y = sin(x); yp = sin(x) + 0.1*rand(x,"normal"); xbasc() plot2d(x, [yp y], style=[-2 2], leg="y=sin(x)+perturbation@y=sin(x)") Rysunek 4.3: dessin en trait plain et avec des symboles non reliés tutu 3. Okre±lanie skali Oto przykªad gdzie niezb¦dne jest narzucenie skali izometrycznej tutu bowiem chcemy narysowa¢ okr¡g (patrz rysunek (4.4)). postaci frameflag=val, gdzie val Dodatkowy parametr b¦dzie powinna przyj¡¢ warto±¢ 4 aby otrzyma¢ skale izome- tryczn¡ (dobran¡ na podstawie warto±ci minimalnej i naksymalnej) 3 tutu 68 t = linspace(0,2*%pi,60)'; x1 = 2*cos(t); y1 = sin(t); // elipsa x2 = cos(t); y2 = y1; // okr\k{a}g x3 = linspace(-2,2,60)'; y3 = erf(x3); // funkcja b\l{}\k{e}du legenda = "elipsa@okr\k{a}g@funkcja b\l{}\k{e}du" plot2d([x1 x2 x3],[y1 y2 y3],style=[1 2 3], frameflag=4, leg=legenda) xtitle("Znowu krzywe...","x","y") Rysunek 4.4: Elipsa, okr¡g i funkcja bª¦du W pewnych przypadkach frameflag towarzyszy¢ powinien parametr rect. Je±li na przykªad chcemy samodzielnie okre±li¢ obszar rysowania (zwalniaj¡c z tego punkcj¦ musimy napisa¢ plot2d tutu) rect = [xmin ; ymin ; xmax ; ymax ] w poª¡czeniu z frameflag=1 jak w przykªadzie poni»ej x = linspace(-5,5,200)'; y = 1 ./(1 + x.^2); xbasc() plot2d(x, y, frameflag=1, rect=[-6,0,6,1.1]) xtitle("Funkcja Rungego tutu") Oto wszystkie mo»liwe warto±ci dla frameflag=0 frameflag=1 frameflag=2 frameflag=3 frameflag=4 frameflag=5 frameflag=6 frameflag=7 frameflag=8 Uwaga: frameflag u»ycie wcze±niej zdeniowanej skali (lub domy±lnej) skala zadana przez kwadrat skala obliczona jako maksimum i minimum z Mx i My échelle isométrique calculée en fonction de rect tutu skala izometryczna obliczona jako maksimum i minimum z Mx et My identycznie 1 ale z ewntualnym dostosowaniem graduation tutu identycznie 2 mais avec adaptation eventuelle pour la graduation identycznie 1 ale wcze±niejsze krzywe s¡ odrysowywane identycznie 2 ale wcze±niejsze krzywe s¡ odrysowywane W przypadkach 4 i 5 mo»e zaj±¢ (ewentualna) modykacja obszaru rysowania w taki sposób aby stopniowanie (tutu) (które jest zawsze tutu) tutu (tak zwane tutu). 4. Precyzowanie umieszczenis osi Rozmieszczenie osi mo»emy okre±la¢ pisz¡c axesflag=val. W kolenym przykªadzie (patrz rysunek (4.5)) przetna si¦ wpunkcie (0; 0) val ma warto±¢ 5 co powoduje, »e osie 4 bez tutu boite englobante : x = linspace(-14,14,300)'; y = sinc(x); xbasc() plot2d(x, y, style=2, axesflag=5) xtitle("Funkcja sinc") Rysunek 4.5: Umieszczenie osi otrzymane dla Oto tabela podaj¡ca wszytkie mo»liwo±ci: 4 Gdy punkt (0; 0) jest we wn¦trzu obszaru rysowania. 69 axesflag=5 bez pudeªka, osi oraz jednostek z pudeªkiem, osiami i jednostkami (x na dole, y po lewej) z pudelkiem, ale bez osi i jednostek z pudeªkiem, osiami i jednostkami (x na dole, y po lewej) bez pudeªka, ale z osiami i jednostkami (punkt przeci¦cia w ±rodku) bez pudeªka, ale z osiami i jednostkami (punkt przeci¦cia dla x = 0 i y = 0) axesflag=0 axesflag=1 axesflag=2 axesflag=3 axesflag=4 axesflag=5 5. Skala logarytmiczna Odpowiedni parametr jest postaci logflag=str, gdzie str jest ªañcuchem zªo»onym z dówch znaków pierwszy dotyczy osi OX, drugi OY i ka»dy przyjmuje warto±¢ n (nie logarytmiczna) lub l (logarytmiczna). x = logspace(0,4,200)'; y = 1 ./x; xbasc() subplot(1,2,1) plot2d(x, y, style=2, logflag= "ln") xtitle("logflag=""ln""") subplot(1,2,2) plot2d(x, y, style=2, logflag= "ll") xtitle("logflag=""ll""") Rysunek 4.6: Wykorzystanie parametru logflag subplot(m,n,num) w jednym oknie m informuje o podziale okna w pionie na m równych cz¦±ci, n decyduje o podziale w poziomie num jest natomiast kolejnym numerem Przykªad ten pokazuje tak»e jak przy pomocy funkcji umie±ci¢ kilka (niezale»nych) wykresów. Parametr okna spo±ród mn okien. Okna numerowane s¡ od lewej do prawej i od góry do doªu poczynaj¡c od numeru 1. St¡d okno na pozycji (i; j ) ma numer 5 n (i 1) + j . Nic nie stoi na przeszkodzie aby modykowa¢ siatk¦ tutu celem dobranie najbardziej nam odpowiadaj¡cego ukªadu wykresów. Na przykªad xbasc() subplot(1,2,1) titlepage("po lewej") subplot(3,2,2) titlepage(["po prawej";"powy\.zej"]) subplot(3,2,4) titlepage(["po prawej";"w centrum"]) subplot(3,2,6) titlepage(["po prawej";"poni\.zej"]) xselect() tutu okna w pionie na dwie cz¦±ci (lew¡ i praw¡), okna po prawej podzielono w poziomie na trzy cz¦sci. Funkcj¦ subplot mo»na rozumie¢ jako dyrektyw¦ pozwalaj¡c¡ wybra¢ pewien podobszar okna gracznego. 6. Sªowo kluczowe strf frameflag i axesflag oraz, ze plot2d zawiera tak»e ag¦ okre±la- Pozwala ono zast¡pi¢ zarazem wzgl¦du na kompatybilno±¢ z wcze±niejszymi wersjami j¡c¡ czy ma ono zastosowanie do legendy, czy nie tutu. Podawana warto±¢ skªada si¦ z trzech znaków xyz, gdzie x równe 0 (nie ma legendy) lub 1 (legenda tworzona jest przez podanie 5 A nie m (i 1) + j jak napisane jest w pomocy! 70 leg=val) ; frameag ; cyfra od 0 do 5, odpowiadaj¡ca warto±ci podawanej w axesag. y cyfra od 0 do 9, odpowiadaj¡ca warto±ci podawanej w z En fait il faut savoir l'utiliser car les séquences optionnelles de nombreuses primitives de dessin ne disposent pas encore des mots clés frameflag i axesflag tutu. Dodatkowo jest to bardzo praktyczne je±li chcemy doda¢ nowy wykres do ju» istniej¡cego bez zmieniania skali i ramki co mo»na osi¡gna¢ pisz¡c frameflag=0, axesflag=0). 4.4 Inne wersje (unikaj¡c w ten sposób pisania plot2d: plot2d2, plot2d3 Zasadniczo u»ywa si¦ ich jak 1. strf="000" plot2d taka sama skªadnia, takie same argumenty opcjonalne. plot2d2 tutu pozwala narysowa¢ funkcj¦ w oparciu o skalary: w miejsce wykresu prostego odcinka wprowadzamy punkty do (xi+1 ; yi )) (xi ; yi ) et (xi+1 ; yi+1 ), plot2d2 odcinek poziomy (od (xi ; yi ) (xi+1 ; yi ) do (xi+1 ; yi+1 )). Oto przykªad a nast¦pnie odcinek pionowy (od (porównaj rysunek (4.7)): n = 10; x = (0:n)'; y = x; xbasc() plot2d2(x,y, style=2, frameflag=5, rect=[0,-1,n+1,n+1]) xtitle("plot2d2") Rysunek 4.7: Wykorzystanie 2. plot2d2 plot2d3 Rysuje diagram tutu batonow: dla ka»dego punktu segment pionowy od (xi ; yi ) plot2d3 rysuje jeden (xi ; 0) do (xi ; yi ) (porównaj rysunek (4.8)) : n = 6; x = (0:n)'; y = binomial(0.5,n)'; xbasc() plot2d3(x,y, style=2, frameflag=5, rect=[-1,0,n+1,0.32]) xtitle("Prawdopodobienstwo dla prawa binomialnego tutu B(6,1/2)") Rysunek 4.8: Wykorzystanie plot2d3 4.5 Rysowanie wi¦kszej ilo±ci krzywych zªo»onych z ró»nej ilo±ci punktów Za pomoc¡ plot2d i jego wariantów nie mo»na narysowa¢ za jednym razem wi¦kszej ilo±ci krzywych, które nie s¡ dyskretyzowane na takiej samej ilo±ci przedziaªów (i chyba takich samych przedziaªów tutu) co poci¡ga za soba konieczno±¢ kilkakrotnego u»ycia tej funkcji. Od wersji 2.6 mo»na oby¢ si¦ bez podawania skali bez obawy o przykre niespodzianki, poniewa» domy±lnie (frameflag=8) wcze±niejsze krzywe s¡ odrysowywane w przypadku zmiany skali. Dlatego je±li kto± chce opanowa¢ skal¦ (chodzi tutaj chyba o to aby nie byla ona zmieniana 71 automatycznie tutu), musi to zrobic przy pierwszym wywoªaniu a dla nast¦pnych u»ywa¢ frameflag=06 . Oto odpowiedni przykªad (porównaj rysunek (4.9)) x1 = linspace(0,1,61)'; x2 = linspace(0,1,31)'; x3 = linspace(0.1,0.9,12)'; y1 = x1.*(1-x1).*cos(2*%pi*x1); y2 = x2.*(1-x2); y3 = x3.*(1-x3) + 0.1*(rand(x3)-0.5); // identyczne jak y2, ale z zaburzeniem ymin = min([y1 ; y2 ; y3]); ymax = max([y1 ; y2 ; y3]); dy = (ymax - ymin)*0.05; // aby doda\'c margines tutu rect = [0,ymin - dy,1,ymax+dy]; // okno wykresu xbasc() // wyczyszczenie poprzednich wykresów plot2d(x1, y1, style=1, frameflag=5, rect=rect) // 1-sze wywo\l{}anie, które ustali sk plot2d(x2, y2, style=2, frameflag=0) // 2-ie i 3-ie wywo\l{}anie; plot2d(x3, y3, style=-1,frameflag=0) // u\.zywamy poprzedniej skali xtitle("Krzywe...","x","y") Uwaga: Wypróuj ten przykªad pisz¡c frameflag=1 w miejsce frameflag=5. Nie mo»na mie¢ Rysunek 4.9: Jeszcze krzywe... osobnej legendy dla ka»dej krzywej niemniej jest to mo»liwe do osi¡gni¦cia przy pomocy niewielkiej ilo±ci progamowania. 4.6 Zabawa z kontekstem gracznym moze lepiej praca? :))) Je±li wyprobowali±my poprzednie przykªady bez w¡tpienia i z ochot¡ b¦dziemy chcieli modykowa¢ niekóre rzeczy jak rozmiar symboli, rozmiar czy styl u»tego fontu lub te» grubo±¢ strzaªek. 1. Fonty : Aby zmieni¢ font nale»y u»y¢ poni»szego wywoªania xset("font",font_id,fontsize_id) gdzie font_id i fontsize_id s¡ liczbami caªkowitymi odpowiadaj¡cymi odpowiednio z rodzaj i wielko±¢ wybranego fontu. Bie»¡cy font mo»na otrzyma¢ pisz¡c f=xget("font") gdzie f jest wektorem, f(1) f(2) jego wielko±¢. Mo»na prosxset("font size",size_id) i fontsize_id = xget("fon opisuje rodzaj fontu a tozmienia¢/uzyska¢ wielko±¢ za pomoc¡ Oto te, które s¡ teraz dost¦pne Nazwa fontu Identykator Courier 0 Symbol 1 Wielko±¢ Identykator 8 pts 0 Times 2 Times-Italic 3 10 pts 1 12 pts 2 Times-Bold 4 14 pts 3 18 pts 4 Times-Bold-Italic 5 24 pts 5 Uwagi: 6 Courier est à chasse xe tutu; font Symbol pozwala na u»ycie liter greckich (p odpowiada Metoda ta jest konieczna je±li u»ywamy skali iso-metrycznej. 72 , a , etc...); 2. Times jest fontem domy±lnym a jego domy±lny rozmiar to 10 punktów. rozmiar symboli: zmieniamy poleceniem xset("mark size",marksize_id) bie»¡cy otrzymujemy natomiast pisz¡c marksize_id = xget("mark size") gdzie podobnie jak dla fontów rozmiar okre±lamy za pomoca cyfr od 0 do 5; 0 jest wielko±ci¡ domy±ln¡. 3. grubo±¢ linii: zmieniamy / otrzymujemy pisz¡c xset("thickness",thickness_id) thickness_id = xget("thickness") Grubo±¢ jest wielko±ci¡ dodatni¡ odpowiadaj¡c¡ liczbie pikseli (na grubo±¢) jak¡ ma mie¢ krzywa. Dokonuj¡c zmiany grubo±ci kre±lonych linii wpªywamy tak»e, czy tego chcemy czy nie, na grubo±¢ kre±lonej ramki i skali na osiach. Wyj±ciem w takiej sytuacji jest dwukrotne tworzenie rysunku. Za pierwszym razem pomijamy ramk¦ i skal¦ (axesflag=0). Nast¦pnie powracamy do normalnej grubo±ci i nie zmieniaj¡c skali widocznego obszaru (frameflag=0) rysujemy co± poza nim (na przykªad krzyw¡ zredukowana do jednego punktu ( 1; 1)): xset("thickness", 3) plot2d(x, y, axesflag=0, ...) xset("thickness", 1) plot2d(-%inf, -%inf, frameflag=0, ...) Zatem drugie wywoªanie sªu»y jedynie do narysowania ramki i skali. 4.7 Tworzenie histogramów Odpowiednia do tego celu funkcja scilaba nazywa si¦ histplot a jej wywoªanie jest nast¦puj¡ce histplot(n, X, <,opt_arg>*) gdzie n 1. 2. ni < ni+1 ): w przypadku gdy n jest wektorem liniowym dane dzielone s¡ na k klas Ci = [ni ; ni+1 [ (wektor n ma wi¦c k + 1 skªadowych); w przypadku gdy n jest liczb¡ caªkowit¡, dane dzielone s¡ na n równoodlegªych klas 8 < c1 = min(X ); cn+1 = max(X ) C1 = [c1 ; c2 ]; Ci =]ci ; ci+1 ]; i = 2; :::; n; avec ci+1 = ci + C : C = (c n+1 c1 )=n jest albo liczb¡ caªkowit¡ albo wektorem liniowym (w którym X wektor (liniowy lub kolumnowy) z danymi; <,opt_arg>* ci¡g opcjonalnych argumentów jak dla plot2d z dodatkow¡ kombinacj¡ nor- malization = val gdzie val jest staª¡ (zmienn¡ lub wyra»eniem) boolowskim (domy±lnie true). Kiedy histogram jest znormalizowany, tutu son intégrale vaut 1 et approche donc une densité (dans le cas contraire, la valeur d'une plage correspond au nombre de composantes de X tombant dans cette plage). spondant à l'intervalle : ( Plus précisemment, la plage de l'histogramme corre- Ci vaut donc (m étant le nombre de données, et Ci = ni+1 ni ) fXj 2Ci g mCi card fXj 2 Ci g card 73 normalization = vrai si normalization = faux si Poni»ej przedstawiamy maªy przykªad, tutu toujours avec la loi normale (patrz rysunek (4.10)) : X = rand(100000,1,"normal"); classes = linspace(-5,5,21); histplot(classes,X) // tutu on lui superpose le tracé de la densité de N(0,1) x = linspace(-5,5,60)'; y = exp(-x.^2/2)/sqrt(2*%pi); plot2d(x,y, style=2, frameflag=0, axesflag=0) Rysunek 4.10: Histogram próbki liczb losowych wybranych z rozkªadem 4.8 Zapisywanie graki w ró»nych formatach W celu zachowanie utworzonego rysunku wybieramy z menu Export File okna gracznego opcj¦ a nast¦pnie wybieramy po»¡dany format. tutu - sprawdzi¢ to Wi¦kszo±¢ z nich opiera si¦ na postscripcie... pliku typu 4.9 N (0; 1) tutu . Pocz¡wszy od wersji 2.5 mamy tak»e mo»liwo±¢ eksportu graki do gif. Prosta animacja Realizacja animacji przy pomocy Scilaba jest do±¢ prosta, jako »e pozwala on na podwójne buforowanie dzi¦ki czemu unikamy efektu migotania, gdy» wykres tworzony jest w ukryciu i dopiero potem pokazywany. 7 Mamy do wyboru dwa drivery maj¡ce wpªyw na tworzenie wykresu na ekranie Rec, który powoduje, »e wszystkie operacje graczne zwi¡zane s¡ z oknem; jest to domy±lny drvier; X11, tutu qui se contente simplement d'acher les graphiques (il est alors imposible de zoomer). Do celów tworzenia animacji najcz¦sciej odpowiedni b¦dzie ten ostatni; wybieramy go pisz¡c driver("X11") (w celu powrócenia do drivera domy±lnego piszemy driver(ec")). Przy podwójnym buforowaniu ka»dy kolejny obraz tworzony jest najpierw w pami¦ci (powstaje wówczas tak zwana pixmapa) a dopiero póniej przenoszony na ekran. Oto prosty schemat post¦powania przy tworzeniu animacji driver("X11") // tutu pas d'enregistrement des opérations graphiques xset("pixmap",1) // przej\'scie do trybu podwójnego buforowania ........... // ewentualne instrukcje ustalaj\k{a}ce skal\k{e} for i=1:nb_dessins xset("wwpc") // wyczyszczenie pixmapy ....... ....... // tworzenie i-tego rysunku ....... xset("wshow") // przeniesienie rysunku na ekran end xset("pixmap",0) // powrót do bezpo\'sredniego tworzenia rysunków na ekranie driver("Rec") // przej\'scie do domy\'slego drivera 7 Oprócz driverów pozwalaj¡cych tworzy¢ rysunki jako postscript, fig 74 czy gif. Uwaga: W powy»szym post¦powaniu czyszczenie caªego obszaru rysowania przy pomocy xset("wwpc")nie czynno±ci¡ wymagan¡. Zamiast tego mo»na u»y¢ na przykªad funkcji xclea, co uchroni nas przed ka»dorazowym odrysowywaniem tych obszarów rysunku, które si¦ nie zmieniaj¡. Aby tutu u»y¢ technik maskowania nale»y za pomoc¡ wywoªanie zmieni¢ funkcj¦ steruj¡c¡ wy±wietlaniem (gdzie num xset('alufunction',num) to liczba caªkowita zwi¡zana z wybran¡ funkcj¡); patrz Help i przykªady. Poni»ej przedstawiony zostanie przykªad animacji: poruszaj¡cy si¦ ±rodek ci¦»ko±ci prostok¡ta (o dªugo±ci L i szeroko±ci l) po okr¦gu o promieniu r i ±rodku w punkcie (0; 0); prostok¡t dodatkowo obraca si¦ wokóª swojego ±rodka ci¦»ko±ci. tutu Il y a certain un nombre de détails qui se greent autour du canevas général exposé ci-avant : l'ordre plot2d sert uniquement à régler l'échelle (isométrique) pour les dessins ; xset("background",1) impose la couleur 1 (du noir dans la carte des couleurs par défaut) comme couleur d'arrière plan, mais il est recommandé d'exécuter l'instruction xbasr() pour mettre eectivement à jour la couleur du fond ; xfpoly suivi de xpoly pour dessiner xset("thickness",3)) ; à chaque fois xset(¢olor",num) ; le dessin consiste à appeler la fonction le bord (avec ici 3 pixels ce qui est obtenu avec on change la couleur à utiliser avec l'instruction xset("default") repositionne le contexte graphique de la fen¦tre à des valeurs par défaut ; ainsi la variable 1, background pixmap reprend la valeur 0, thickness la valeur sa valeur par défaut, etc... n = 4000; L = 0.6; l = 0.3; r = 0.7; nb_tours = 4; t = linspace(0,nb_tours*2*%pi,n)'; xg = r*cos(t); yg = r*sin(t); xy = [-L/2 L/2 L/2 -L/2;... // 4 punkty graniczne -l/2 -l/2 l/2 l/2]; xselect() driver("X11") xset("pixmap",1) plot2d(\%inf,\%inf, frameflag=3, rect=[-1,-1,1,1], axesflag=0) xset("background",1); // czarne t\l{}o xbasr() // tutu utile pour la mise a jour du background xset("thickness",3) // zwi\k{e}kszenie grubo\'sci kre\'slonych linii (3 pixele) xset("font",2,4) for i=1:n xset("wwpc") theta = 3*t(i); xyr = [cos(theta) -sin(theta);... sin(theta) cos(theta)]*xy; xset("color",2) xfpoly(xyr(1,:)+xg(i), xyr(2,:)+yg(i)) xset("color",5) xpoly(xyr(1,:)+xg(i), xyr(2,:)+yg(i),"lines",1) xset("color",32) xtitle("Animation simple") xset("wshow") // przeniesienie pixmapy na ekran end driver("Rec") // powrot do domy\'slnego drivera xset("default") // przywrócenie domy\'slnego kontekstu graficznego 75 4.10 Powierzchnie Podstawow¡ funkcj¡ pozwalaj¡c¡ na tworzenie wykresów powierzchni jest plot3d8 . Przy preprezentacji powierzchni za pomoca facettes tutu mamy mo»liwo±¢ okre±lenia innego koloru dla ka»dej z nich. Od wersji 2.6 mo»na tak»e, zarówno dla fscettes trójk¡tnych jak i kwadratowych okre±li¢ kolor dla ka»dego z wierzchoªków, przez co rendu tutu otrzymywane jest przez interpolacj¦ kolorów okre±lonych w wierzchoªkach. 4.10.1 Wprowadzenie do plot3d Gdy powierzchnia opisane jest przez równanie typu z = f (x; y), j¡ narysowa¢ je±li argumenty s¡ z obszaru prostok¡tnego. f (x; y) = cos(x)cos(y) dla (x; y) 2 [0; 2] [0; 2] : szczególnie ªatwo mo»na Jako przykªad rozwa»my funkcj¦ x=linspace(0,2*\%pi,31); // dyskretyzacja zmiennej x (a tak\.ze y : b\k{e}dzie to s z=cos(x)'*cos(x); // zbiór warto\'sci zmiennej z : macierz z(i,j) = f(x(i),y( plot3d(x,x,z) // rysunek Rysunek 4.11: Funkcja z = cos(x)cos(y) 9 W efekcie otrzymamy co± podobnego do rysunku (4.11) . W najbardziej ogólnej formie funkcji plot3d lub plot3d1 u»ywamy pisz¡c plot3d(x,y,z <,opt_arg>*) plot3d1(x,y,z <,opt_arg>*) gdzie dla form¦ plot2d, <,opt_arg>* sªowo_kluczowe=warto±¢. ozancza ci¡g argumentów opcjonalnych, W najprostszym przypadku, x i y opt_arg przyjmuje s¡ wektorami liniowymi (1; nx) i (1; ny)) odpowiadaj¡cymi dyskretyzacji zmiennej x oraz y, natomiast z jest macierz¡ (nx; ny) tak¡, »e zi;j jest wysoko±ci¡ w punkcie (xi ; yj ). ( Opcjonalne argumenty to: 1. theta=val_theta i alpha=val_alpha to dwa k¡ty (w stopniach) okre±laj¡ce punkt widzenia O jest ±rodkiem pudeªka englobante tutu, Oc kierunk= kt(Oz; Oc) i = kt(0x; Oc0 ) gdzie Oc0 jest rzutem Oc we wspóªrz¦dnych sferycznych (je±li iem patrzenia kamery, wówczas na pªaszczyzn¦ 2. Oxy); leg=val_leg pozwala okre±li¢ nazw¦ dla ka»ej z osi (na przykªad leg="x@y@z"), argument efektywny val_leg jest ªañcuchem znakowym, w którym @ stanowi separator pomi¦dzy nazwami; 3. flag=val_ag gdzie val_ag jest wektorem o trzech skªadowych [mode type box] pozwalaj¡cym okre±li¢: mode zwi¡zany jest z rysunkiem faces tutu i siatki: 10 dla mode > 0, faces niewidoczne s¡ usuwane , siatka pozostaje widoczna; dla mode = 0, otrzymujemy tutu un rendu (fr. l de fer, ang. wireframe) (a) parametr i. ii. de la surface; iii. dla 8 9 plot3d1 mode < 0, faces niewidoczne s¡ usuwane a siatka nie jest rysowana. u»ywana analogicznie pozwala uzale»ni¢ warto±¢ koloru od warto±ci przyjmowanej na osi OZ. Dokªadnie rzecz bior¡c rysunek ten przedstawia efekt u»ycia funkcji plot3d1 gdzie na potrzeby publikacji zamiast kolorów u»yto odcieni szaro±ci a tak»e ustawiono troch¦ inny punkt widzenia. 10 tutu actuellement c'est l'algorithme du peintre qui est utilisé, c-a-d qu'un tri des facettes est eectué et les plus éloignées de l'observateur sont dessinées en premier. 76 Dodatnio okre±lona strona face tutu (patrz dalej) b¦dzie malowana z wykorzystaniem koloru numer instrukcj¡ mode za± strona przeciwna przy u»yciu koloru, który mo»emy okre±li¢ xset("hidden3d",colorid) (domy±lnie jest to 4 kolor z palety). type pozwala okre±li¢ skal¦: type otrzymana skala (b) parametr 0 u»ycie poprzedniej skali (tutu ou par défaut) 1 skala wraz z 2 skala otrzymana w oparciu o minimum i maximum zmiennych tutu 3 jak 1 ale skala jest izometryczna 4 jak 2 ale skala jest izometryczna 5 variante de 3 6 variante de 4 (c) parametr 4. ebox box kontroluje tutu le pourtour du graphe : box otrzymany efekt 0 juste le dessin de la surface 2 osie pod powierzchnia s¡ rysowane 3 jak dla 2 z dodatkowym tutu la boite englobante 4 jak dla 3 z dodatkowym tutu la graduation des axes ebox=val_ebox pozwala okre±li¢ tutu la boite englobante, val_ebox [xmin ; xmax ; ymin ; ymax ; zmin ; zmax ]. jest wektorem o 6 skªadowych Oto maªy przykªad, w którym u»ywa si¦ prawie wszystkich parametrów plot3d. Jest to prosta animacja pozwalaj¡ca lepiej zrozumie¢ zmiane punktu widzenia przy pomocy parametrów theta i alpha. W skrypcie tym u»ywamy flag=[2 4 4], co oznacza mode = 2 powierzchnia b¦dzie rysowana (jej dodatno okre±lona strona) kolorem 2 oraz b¦dzie widoczna siatka; type = 4 zostanie u»yta skala izometryczna obliczona na podstawie danych (jest to równowa»ne wyborowi type = 3 z parametrem ebox przyjmuj¡cym warto±ci równe mini- mum i maksimum danych); box = 4 rysunek b¦dzie zawieraª pudeªko tutu boite oraz stopniowanie et des graduations. x=linspace(-%pi,%pi,31); z=sin(x)'*sin(x); n = 200; theta = linspace(30,390,n); // pe\l{}ny obrót alpha = [linspace(60,0,n/2) linspace(0,80,n/2)]; // od góry // do do\l{}u xselect() xset("pixmap",1) // aktywowanie podwójnego buforowania driver("X11") // zmieniamy parametr theta for i=1:n xset("wwpc") // wyczyszczenie bie\.z\k{a}cego bufora plot3d(x,x,z,theta=theta(i),alpha=alpha(1),leg="x@y@z",flag=[2 4 4]) xtitle("zmiany punktu widzenia przy pomocy parametru theta") xset("wshow") end // zmieniamy parametr alpha for i=1:n xset("wwpc") // wyczyszczenie bie\.z\k{a}cego bufora plot3d(x,x,z,theta=theta(n),alpha=alpha(i),leg="x@y@z",flag=[2 4 4]) xtitle("zmiany punktu widzenia przy pomocy parametru alpha") 77 xset("wshow") end xset("pixmap",0) driver("Rec") 4.10.2 Kolory Powró¢my jeszcze na chwilk¦ do ostatniego przykªadu i zamiast uzale»niaj¡c tym samym kolory od warto±ci zmiennej z. plot3d napiszmy plot3d1 Narysowana powierzchnia powinna przypomina¢ w tym momencie mozaike gdy» wykorzystywana plaeta kolorów domy±lnie nie jest ci¡gªa. (nb_couleurs,3), Paleta kolorów jest macierz¡ o wymiarze gdzie i-ta linia deniuje intensy- wno±ci skªadowej czerwonej (warto±¢ zawarta w przedziale od 0 do 1), zielonej i niebieskiej dla i-tego koloru. Maj¡c tak¡ macierz, któr¡ nazwiemy C, polecenie xset(¢olormap",C) pozwala j¡ wczyta¢ (zaªadowa¢) do kontekstu gracznego bie»¡cego okna gracznego. Funkcje, hotcolormap oraz greycolormap 11 . dostarczaj¡ mapy ze stopniow¡ zmian¡ kolorów Maªa uwaga: je±li dokonujemy zmiany palety kolorów po narysowaniu jakiego± rysunku, zmiany nie b¦d¡ widoczne natychmiast (jest to zachowania normalne); wystarczy zmieni¢ rozmiar okna lub tutu d'envoyer l'ordre xbasr(numero_fenetre). Oto nowy przykªad x = linspace(0,2*%pi,31); z = cos(x)'*cos(x); C = hotcolormap(32); // hot colormap z 32 kolorami xset("colormap",C) xset("hidden3d",30) // wybór koloru 30 do rysowania po ujemnie okre\'slonej stroni xbasc() plot3d1(x,x,z, flag=[1 4 4]) // spróbuj tak\.ze z flag=[-1 4 4] Uwaga : w plot3d1, wykorzystuje si¦ jedynie znak parametru zostanie narysowana, nie zostanie za± gdy mode < 0). mode (je±li mode 0 siatka 4.10.3 plot3d z des facettes Chc¡c u»y¢ tej funkcji w jak najogólniejszej postaci nale»y poda¢ opis powierzchni uwzgl¦dnia- xf, yf, zf o wymiarze (nb_sommets_par_face, nb_faces), gdzie xf(j,i),yf(j,i),zf(j,i) s¡ wspóªrz¦dnymi j¡c pojedyñczy tutu facettes. Okre±lany jest on przy pomocy 3 macierzy j-tego wierzchoªka i-tego tutu facette. Poza tymi zmianami dalsze u»ycie jest takie samo jak w poprzednich przykªadach: plot3d(xf,yf,zf <,opt_arg>*) Orientacja tutu facettes jest odmienna od zwyczajowo przyj¦tej (patrz rysunek (4.12). Rysunek 4.12: orientacja tut facettes w Scilab-ie W celu zdenowania kolorów dla ka»dego facette, trzeci argument musi by¢ list¡ : gdzie colors jest wektorem o rozmiarze nb_faces, colors(i) list(zf,colors) okre±lan numer (w palecie) koloru i-tego tutu facette. Jak w pierwszym przykªadzie, narysujemy ±ciany trój±cianu z rysunku (4.13), dla którego: 2 3 2 3 2 3 2 3 0 1 0 0 P1 = 4 0 5 ; P2 = 4 0 5 ; P3 = 4 1 5 ; P4 = 4 0 5 ; 0 11 Patrz tak»e sekcja 0 Contributions na stronie Scilab. 78 0 1 Rysunek 4.13: Trój±cian gdzie denicja ±cian jest nast¦pujaca (w ten sposób otrzymujemy ±ciany zewn¦trzne z orientacj¡ dodatni¡ dla Scilab-a): f1 = (P1 ; P2 ; P3 ); f2 = (P2 ; P4 ; P3 ); f3 = (P1 ; P3 ; P4 ); f4 = (P1 ; P4 ; P2 ) Napiszmy wi¦c: // f1 f2 f3 f4 xf = [ 0 1 0 0; 1 0 0 0; 0 0 0 1]; yf = [ 0 0 0 0; 0 0 1 0; 1 1 0 0]; zf = [ 0 0 0 0; 0 1 0 1; 0 0 1 0]; // tutu ouf ! xbasc() plot3d(xf,yf,list(zf,2:5), flag=[1 4 4], leg="x@y@z",alpha=30, theta=230) xselect() Otrzymany efekt powinien przypomina¢ rysunek 4.14. Mo»na zauwa»y¢, »e plot3d u»ywa prostej tutu projection orthographique et non une projection perspective plus réaliste. Rysunek 4.14: Trój±cian narysowany w Scilab-ie. Na bie»¡ce potrzeby, obliczenia tutu des facettes, mog¡ by¢ efektywniejsze dzi¦ki funkcjom: eval3dp i nf3d genfac3d dla powierzchni deniowanych przy pomocy z dla powierzchni zdeniowanych przy pomocy z (u; v) (patrz 4.10.4) ; x = x(u; v); y = y(u; v); z = = f (x; y) (przykªad pokazany jest troch¦ dalej (4.10.5)). Je±li powierzchnia (wielo±cian) zdeniowana jest w taki sam sposób jak trój±cian z przykªadu nie mo»na jego narysowa¢ bezpo±rednio przy u»yciu plot3d. W celu otrzymania opisu oczeki- wanego przez Scilab-a mo»na wykorzysta¢ funkcj¦ podobn¡ do przedstawionej poni»ej: function [xf,yf,zf] = facettes_polyedre(P) // tutu transforme la structure Polyedre de l'exemple // sur les tlist en description de facettes pour // visualisation avec plot3d [ns, nf] = size(P.face) // ns: ilo\'s\'c wierzcho\l{}ków tworz\k{a}cych \'scian\k{ // nf: ilo\'s\'c \'scian xf=zeros(P.face); yf=zeros(P.face); zf=zeros(P.face) for j=1:ns num = connect(ns+1-j,:) // dla odwrócenia orientacji xf(j,:) = P.coord(1, num) yf(j,:) = P.coord(2, num) 79 zf(j,:) = P.coord(3, num) end endfunction Maj¡c tak okre±lon¡ funkcj¦, rysunek wielo±cianu otrzymamy pisz¡c [xf,yf,zf] = facettes_polyedre(Cube); plot3d(xf,yf,list(zf,2:7), flag=[1 4 0],theta=50,alpha=60) 4.10.4 Rysowanie powierzchni opisanej przy pomocy x = x(u; v), y = y(u; v), z = z (u; v) Odpowied: wzi¡¢ dyskretyzacj¦ dziedziny parametrów obliczy¢ tutu les facettes przy pomocy funkcji (eval3dp). Ze wzgl¦dów wydajno±ciowych, funkcja okre±laj¡ca parametry powierzchni powinna by¢ napisana wektorowo. Je±li (u1 ; u2 ; : : : ; um ) i (v1 ; v2 ; : : : ; vn ) stanowi¡ dyskre- tyzacj¦ dziedziny parametrów, funkcja powinna by¢ wywoªywana jednokrotnie z dwoma du»ymi wektorami rozmiaru m n: U = (u| 1 ; u2 ;{z: : : ; um}; |u1 ; u2 ;{z: : : ; um}; : : : : : : ; |u1 ; u2 ;{z: : : ; um}) n 1 2 V = (v|1 ; v1{z ; : : : ; v}1 ; v|2 ; v2{z ; : : : ; v}2 ; : : : : : : ; |vn ; vn{z ; : : : ; vn}) m fois v1 m fois v2 m fois W oparciu o te dwa wektory, funkcja powinna tworzy¢ 3 wektory takie, »e: vn X; Y et Z wymiaru mn Xk = x(Uk ; Vk ); Yk = y(Uk ; Vk ); Zk = z (Uk ; Vk ) 12 de façon à pouvoir ¦tre utilisée Oto kilka przykªadów parametryzacji powierzchni, tutu écrite avec eval3dp : function [x,y,z] = tore(theta, phi) // tutu paramétrisation classique d'un tore de rayons R et r et d'axe Oz R = 1; r = 0.2 x = (R + r*cos(phi)).*cos(theta) y = (R + r*cos(phi)).*sin(theta) z = r*sin(phi) endfunction function [x,y,z] = helice_torique(theta, phi) // tutu paramétrisation d'une helice torique R = 1; r = 0.3 x = (R + r*cos(phi)).*cos(theta) y = (R + r*cos(phi)).*sin(theta) z = r*sin(phi) + 0.5*theta endfunction function [x,y,z] = moebius(theta, rho) // wst\k{e}ga Moëbius-a R = 1; x = (R + rho.*sin(theta/2)).*cos(theta) y = (R + rho.*sin(theta/2)).*sin(theta) z = rho.*cos(theta/2) endfunction 12 Piszemy je w naturalny sposób, pami¦taj¡c aby zamiast *i/ 80 napisa¢ .* i ./ i wszystko powinno dziaªa¢! function [x,y,z] = tore_bossele(theta, phi) // tutu paramétrisation d'un tore dont le petit rayon r est variable avec theta R = 1; r = 0.2*(1+ 0.4*sin(8*theta)) x = (R + r.*cos(phi)).*cos(theta) y = (R + r.*cos(phi)).*sin(theta) z = r.*sin(phi) endfunction Oto przykªad wykorzystuj¡cy ostatni¡ powierzchni¦: // skrypt rysuj\k{a}cy powierzchni\k{e} opisan\k{a} za pomoc\k{a} równania parametrycz theta = linspace(0, 2*%pi, 160); phi = linspace(0, -2*%pi, 20); [xf, yf, zf] = eval3dp(tore_bossele, theta, phi); // tutu calcul des facettes xbasc() plot3d1(xf,yf,zf) xselect() Je±li chcemy u»y¢ kolorów a nie otrzymujemy ich na rysunku, spowodowane jest to niewªa±ciw¡ orientacj¡; wystarczy odwróci¢ kierunek jednego z wektorów stanowi¡cego dyskretyzacj¦ dziedziny. Rysunek 4.15: Un tore bosselé... tutu tutu Funkcja nf3d jest lekko podobna do zdeniowa¢ soit-m¦me des matrices X; Y; Z eval3dp, ale maj¡c dyskretyzacj¦ uiv trzeba tak¡, »e: Xi;j = x(ui ; vj ) Yi;j = y(ui ; vj ) Zi;j = z (ui ; vj ) et vos facettes s'obtiennent alors avec [xf,yf,zf] = nf3d(X,Y,Z). Jako przykªad rozwa»my wst¦g¦ Moëbius-a dénit juste avant : nt = 120; nr = 10; rho = linspace(-0.5,0.5,nr); theta = linspace(0,2*%pi,nt); R = 1; X = (R + rho'*sin(theta/2)).*(ones(nr,1)*cos(theta)); Y = (R + rho'*sin(theta/2)).*(ones(nr,1)*sin(theta)); Z = rho'*cos(theta/2); [xf,yf,zf] = nf3d(X,Y,Z); xbasc() plot3d(xf,yf,zf, flag=[2 4 6], alpha=60, theta=50) xselect() Uwaga: w celu otrzymania pawidªowej macierzy nale»aªo u»y¢ funkcji ones, tutu ce qui ne rend pas le code très clair: funkcja eval3dp jest ªatwiejsza w u»yciu! Rysunek 4.16: Wst¦ga Moëbius-a 81 4.10.5 plot3d z interpolacj¡ kolorów Od wersji 2.6 , mo»liwe jest okre±lenie koloru dla ka»dego wierzchoªka tutu d'une facette. colors takiego samego wymiaru jak xf, yf, zf daj¡c¡ opis ka»dego facette, to znaczy tak¡, »e colors(i,j) jest kolorem zwi¡zanym z i-tym wierzchoªkiem j-tego face, i poª¡czy¢ z trzecim argumentem (zf) w list¦: Wystarczy okte±li¢ macierz plot3d(xf,yf,list(zf,colors) <,opt_arg>*) Oto przykªad pocz¡tkowy plot3d bez rysowania siatki: tutu une couleur par face pour le dessin de gauche, tutu une couleur par sommet pour celui de droite. Aby obliczy¢ wartosci kolorów, wykorzystano pomcnicz¡ funkcj¦ wi¡»¡c¡ w sposób liniowy dsearch dost¦pnej od wersji 2.7 ale mo»na b¦dzie mo»na wykorzytanie funkcji genfac3d warto±ci na karcie gracznej tutu!!!. (u»yto funkcji ªatwo tutu vous en passer). Zauwa»y¢ tak»e pozwalaj¡cej na obliczenie tutu les facettes. // przyk\l{}ad wykorzystania plot3d z interpolacj\k{a} kolorów function [col] = associe_couleur(val) // przypisanie koloru dla ka\.zdej z warto\'sci z val tutu przypsanie do warto\'sci?!!! n1 = 1 // numer 1-ego koloru n2 = xget("lastpattern") // numer ostatniego koloru nb_col = n2 - n1 + 1 classes = linspace(min(val),max(val),nb_col) col = dsearch(val, classes) endfunction x=linspace(0,2*\%pi,31); z=cos(x)'*cos(x); [xf,yf,zf] = genfac3d(x,x,z); xset("colormap",graycolormap(64)) zmeanf = mean(zf,"r"); zcolf = associe_couleur(zmeanf); zcols = associe_couleur(zf); xbasc() xset("font",6,2) // font 6 (helvetica) tutu n'est disponible // que dans la version cvs de scilab subplot(1,2,1) plot3d(xf,yf,list(zf,zcolf), flag=[-1 4 4]) xtitle("Jeden kolor na tutu face") subplot(1,2,2) plot3d(xf,yf,list(zf,zcols), flag=[-1 4 4]) xtitle("Jeden kolor na wierzcho\l{}ek") xselect() Rysunek 4.17: Z i bez interpolacji kolorów. 4.11 Krzywe w przestrzeni Podstawow¡ funkcj¡ pozwalaj¡c¡ rysowa¢ krzywe w przestrzeni jest przykªad tutu de l'hélice: 82 param3d. Oto klasyczny t = linspace(0,4*\%pi,100); x = cos(t); y = sin(t) ; z = t; param3d(x,y,z) // ewentualne wymazanie okna graficznego za pomoc\k{a} xbasc() tutu mais comme cette dernière ne permet que d'achier une seule courbe nous allons nous concentrer sur param3d1 qui permet de faire plus de choses. Oto jej skªadnia: param3d1(x,y,z <,opt_arg>*) param3d1(x,y,list(z,colors) <,opt_arg>*) Macierze x, y et z musz¡ by¢ tego samego wymiaru (np,nc) a ilo±¢ krzywych (nc) jest okre±ªona przez ilo±¢ kolumn (jak dla plot2d). Parametry opcjonalne s¡ takie same jak dla plot3d, modulo le fait que flag tutu ne ne comporte pas de paramètre mode. colors jest wektorem okre±laj¡cym styl dla ka»dej krzywej (dokªadnie jak plot2d), to znaczy gdy colors(i) jest warto±ci¡ caªkowit¡ dodatni¡, i-ta krzywa rysowana jest i-tym kolorem z fnkcji bie»¡cej palety kolorów (tutu ou avec diérents pointillés sur un terminal noir et blanc); je±li za± zawarta jest pomi¦dzy -9 i 0, otrzymujemy rysnek zªo»ony z punktów (tutu non reliés) zaznaczonych odpowiednim symbolem. Oto przykªad, który powinien doprowadzi¢ nas do rysunku (4.18): t = linspace(0,4*\%pi,100)'; x1 = cos(t); y1 = sin(t) ; z1 = 0.1*t; // spirala x2 = x1 + 0.1*(1-rand(x1)); y2 = y1 + 0.1*(1-rand(y1)); z2 = z1 + 0.1*(1-rand(z1)); xbasc(); xset("font",2,3) param3d1([x1 x2],[y1 y2],list([z1 z2], [1,-9]), flag=[4 4]) xset("font",4,4) xtitle("Spirala z per\l{}ami") Rysunek 4.18: Krzywa i punkty w przestrzeni. Jak dla plot2d funkcj¦ t¡ nale»y wywoªa¢ kilkakrotnie je±li ró»ne krzywe nie maj¡ takiej samej ilo±ci punktówon. Oto skrypt, wyja±niaj¡cy jak utworzy¢ dwie grupy punktów ze ró»nymi znakami i kolorami: n = 50; // ilo\'s\'c punktów P = rand(n,3); // losowanie punktów // tutu on impose les dimensions de la boite englobante ebox = [0 1 0 1 0 1]; // rozdzielenie punktów na dwie grupy aby pokaza\'c jak przypisa\'c // ró\.zne symbole i kolory do punktów m = 30; P1 = P(1:m,:) ; P2 = P(m+1:n,:); // rysunek xbasc() // pierwsza grupa punktów xset("color",2) // tutu du bleu avec la carte par defaut niebieski w domy\'slnej palecie (? param3d1(P1(:,1),P1(:,2),list(P1(:,3), -9), alpha=60, theta=30,... leg="x@y@z", flag=[3 4], ebox=ebox) // tutu flag=[3 4] : 3 -> echelle iso se basant sur ebox // tutu 4 -> boite + graduation // druga grupa punktów xset("color",5) // tutu du rouge avec la carte par defaut param3d1(P2(:,1),P2(:,2),list(P2(:,3), -5), flag=[0 0]) 83 // tutu -5 pour des triangles inverses // tutu [0 0] : echelle fixée et cadre dessiné avec l'appel précédent xset("color",1) // aby ustawi\'c czarny jako bie\.z\k{a}cy kolor xtitle("Punkty...") xselect() 4.12 Ró»no±ci Istnieje jeszcze wiele prymitywów gracznych: 1. contour2d i contour pozwalaj¡ rysowa¢ linie poziomicowe dla funkcji z = f (x; y) okre±lonej na prostok¡cie; 2. grayplot i Sgrayplot pozwalaj¡ reprezentowa¢ warto±ci funkcji tutu qui permettent de représenter les valeurs d'une telle fonction en utilisant des couleurs ; 3. fec odgrywaja tak¡ sam¡ rol¦ jak dwie poprzednie dla funkcji okre±lonej tutu est dénie sur une triangulation plane ; 4. champ pozwala okre±li¢ pole wektorowe w 2D ; 5. tutu wiele funkcji wywoªywanych w tym rozdziale dopuszcza ró»ne parametry aby tworzy¢ wykresy funkcji bardziej bezpo±rednio si on fournit une fonction scilab comme argument (le nom de ces fonctions commence par un f fchamp,...). fplot2d, fcontour2d, fplot3d, fplot3d1, 13 wystarczy przejrze¢ tutu rubrique (dziaª,sekcja (?!)) Aby zda¢ sobie spraw¦ z mo»liwo±ci Graphic Library pomocy. Od wersji 2.7 istnieje nowy model graczny zorientowany obiektowo pozwalaj¡cy modykowa¢ wªa±ciwo±ci graki po ujrzeniu rysunku. Domy±lnie nie jest on aktywny, ale je±li kto± chce poeksperymentowa¢ nale»y wyda¢ polecenie: set("figure_style","new") przed utworzeniem rysunku. Jako »e ten nowy tryb jest w trakcie rozwijania zalecane jest u»wanie wersji tutu cvs de scilab. Biblioteka Enrico Ségré, któr¡ mo»na tutu ±ci¡gn¡¢ z jego strony: http://www.weizmann.ac.il/~fesegre/ tutu complète celle de Scilab et contient takze funkcje pozwalaj¡ce upro±ci¢ tutu certaines taches. 13 tutu attention risque de noyade ! 84 Rozdziaª 5 Zastosowania i uzupeªnienia Rozdziaª ten przedstawia metody rozwi¡zywania w Scilabie pewnych typów problemów analizy numerycznej (aktualnie równa« ró»niczkowych...) oraz dostarcza uzupeªnie«/dodatkowych informacji niezb¦dnych podczas projektowania prostych symulacji stochastycznych. 5.1 Równania ró»niczkowe Scilab dysponuje pot¦»nym interfejsem dla rozwi¡zywania numerycznego (w sposób przybli»ony) równa« ró»niczkowych przy zastosowaniu prostej instrucji ode. Rozwa»my zatem nast¦puj¡ce równanie ró»niczkowe z warunkiem pocz¡tkowym : 0 u = f (t; u) gdzie u (t ) jest wektorem w Rn, f u(t0 ) = u0 jest funkcj¡ R Rn ! Rn, oraz u0 2 Rn. Zakªadamy warunki brzegowe dla których rozwi¡zanie istnieje i jest jednoznaczne a» do okresu T. 5.1.1 Podstawowe u»ycie ode Zdeniujmy funkcj f jako funkcj¦ Scilaba w nast¦puj¡cyj sposób : function [f] = moja_funkcja(t,u) //tutaj kod definiujacy f jako funkcje t i u. endfunction Rmq : Podobnie, je±li równanie jest niezale»ne, nale»y mimo wszystko doprowadzi¢ równanie do postaci w której mamy funkcj¦ zale»ne od zmiennej Van der Pola : kªad¡c t. Oto przykªad kodu dla równania y00 = c(1 y2 )y0 y u1 (t) = y(t) oraz u2 (t) = y0 (t) przeksztaªcamy je do ukªadu dwóch równa« ró»niczkowych pierwaszego rz¦du : d u 1 (t ) 2 (t ) = uc(1 u21 (t))u2 (t) u1 (t) dt u2 (t) function [f] = VanDerPol(t,u) // drugi skladnik dla rownania Van der Pol (c = 0.4) f(1) = u(2) f(2) = 0.4*(1 - u(1)^2)*u(2) - u(1) endfunction Nast¦pnie wywoªujemy od u0 ode aby rozwi¡za¢ równanie (ukªad równa«) wzgl¦dem t0 w T , wychodz¡c (wektor kolumnowy) i chc¡c otrzyma¢ rozwi¡zanie w chwili T , wpiszemy instrukcj¦ : 85 t(1) = t0 ; t(2); :::; t(m) = t = linspace(t0,T,m); [U] = ode(u0,t0,t,moja_funkcja) Otrzymamy w ten sposób macierz cz¦±ciowym dla t ui (t(j )) U o wymiarach (n; m), w której U(i,j) jest rozwi¡zaniem (i-ta skªadowa w chwili t(j )). Uwaga : Liczba skªadowych branych (czyli momenty w których otrzymuje si¦ rozwi¡zanie) nie maj¡ nic wspólnego z pre- cyzj¡ oblicze«. Liczba skªadników jakie przyjmujemy dla t (momenty, dla których obliczamy rozwi¡zanie) nie ma wpªywu na precyzj¦ obliczen. Dokªadno±¢ oblicze« jest determinowana przez inne parametry (maj¡ce warto±ci domy±lne). Z drugiej strony, oprócz ode istnieje wiele innych algorytmów, które daj¡ si¦ zastosowa¢ do ró»nych sytuacji. Aby wybra¢ odpowiedni¡ metod¦ nale»y doda¢ odpowiedni parametr w trakcie wywoªania (patrz Help). Domy±lnie (tzn. bez wybierania explicite jednej metody) stosowana jest metoda Adamsa predykcji, natomiast 1 w przypadku gdy Scilab okre±li równanie jako raide (sztywne) algorytm zostaje zmieniony na metod¦ Gear-a. Oto kompletny przykªad dla równania Van der Pola. W tym przypadku przestrze« stanów jest pªaska, mo»na zatem otrzyma¢ obraz dynamiki rysuj¡c pole wektorowe w prostok¡cie [xmin ; xmax ] [ymin ; ymax ] za pomoc¡ instrukcji gracznej fchamp w nast¦puj¡cy sposób: fchamp(moja_funkcja,t,x,y) mojaf unkcjaoznaczanazwfunkcjiScilababdcskadnikiempoprawejstronierwnaniarnicz kowego; tjestmomentemwktrymchcemynaszkicowapole(wprzypadkucigymrwnaniamoemyprzyjdow gdzie // 1/ kreslimy pole wektorowe odpowiadajace rownaniu Van der Pola n = 30; delta = 5 x = linspace(-delta,delta,n); // tutaj y = x xbasc() fchamp(VanDerPol,0,x,x) xselect() // 2/ rozwiazujemy rownanie rozniczkowe m = 500 ; T = 30 ; t = linspace(0,T,m); // moment w ktorym znajduje sie rozwiazanie u0 = [-2.5 ; 2.5]; // warunek poczatkowy [u] = ode(u0, 0, t, VanDerPol); plot2d(u(1,:)',u(2,:)',2,"000") 5.1.2 Van der Pol jeszcze raz W tej cz¦±ci zwrócimy nasz¡ uwag¦ na mo»liwo±ci graczne Scilaba pozwalan¡ce otrzyma¢ wiele »¡danych trajektorii bez ponownego uruchamiania skryptu z inn¡ warto±ci¡ argumentu u0 . U»yjemy równie» skal¦ izometryczn¡ dla rysunków. Po wy±wietleniu pola wektorowego, 2 ka»dy warunek pocz¡tkowy b¦dzie zadany poprzez klikni¦cie lewym przyciskiem myszy ; pojawi si¦ wówczas punkt na »¡danej pozycji pocz¡tkowej. Jest to mo»liwe dzi¦ki funkcji xclick, której skªadnia jest nast¦puj¡ca : [c_i,c_x,c_y]=xclick(); Jak wida¢, Scilab dyspinuje odpowiednimi procedurami, które umo»liwiaj¡ miedzy innymi reagowanie na tzw zdarzenia graczne jak klikni¦cie mysz¡. Kiedy takie zdarzenia ma miejsce, nast¦puje automatczna lokalizacja pozycji punktu (w bie»¡cej skali) poprzez przypisanie jego wsp󪻦dnych do zmiennych c_x oraz c_y. Trzeci argument, czyli odpowiedni klawisz myszy zgodnie z poni»sz¡ tabelk¡ : 1 2 równanie jest raide w przypadku gdy (mniej lub bardziej) ª¡czy si¦ z metodami jednoznacznymi jak sugerowano w jednym z artykuªów dotycz¡cych Scilaba, zamieszczonym w Linux Magazine 86 c_i oznacza warto±¢ dla c_i klawisz 0 lewy 1 ±rodkowy 2 prawy W skrypcie wyko»ystano klikni¦cie na lewy klawisz myszy jako ten, wyznaczaj¡cy punkt pocz¡tkowy dla p¦ku zdarze«. couleur pozwala u»yjemy fchamp do- Na koniec nadano ka»dej z wyrysowanych trajektorii inny kolor (tablica wybra¢ jeden z dost¦pnych kolorów). Aby otrzyma¢ skal¦ izometryczn¡ daj¡c opcjonalny argument jak dla frameag i axesag plot2d (nale»y u»y¢ strf=wartosc_strf jako »e parametry nie s¡ akceptowane). Ostatni aspekt : aby zaznaczy¢ punkt pocz¡tkowy obrysowano go maªym kóªkiem, natomiast aby pokaza¢ wszystkie mo»liwo±ci okna gracznego wyko»ystano sze±cienny ukªad wspóªrz¦dnych. Ostatnia uwaga : podczas gdy jest wy±wietlone pole wektorowe, mo»na maksymalizowa¢ okno graczne! Klikaj¡c dwukrotnie otrzymano rysunek (5.1) wszystkie trajektorie zbiegaj¡ do jednej sfery, czego sie spodziewamy, z puktu widzenia teoretycznego dla tego równania // 1/ wykres pola wektorowego dla rownania Van der Pola n = 30; delta_x = 6 delta_y = 4 x = linspace(-delta_x,delta_x,n); y = linspace(-delta_y,delta_y,n); xbasc() fchamp(VanDerPol,0,x,y, strf="041") xselect() // 2/ rozwiazanie rownania rozniczkowego m = 500 ; T = 30 ; t = linspace(0,T,m); couleurs = [21 2 3 4 5 6 19 28 32 9 13 22 18 21 12 30 27] // 17 kolorow num = -1 while %t [c_i,c_x,c_y]=xclick(); if c_i == 0 then plot2d(c_x, c_y, style=-9, strf="000") // male o aby zaznaczyc C.I. u0 = [c_x;c_y]; [u] = ode(u0, 0, t, VanDerPol); num = modulo(num+1,length(couleurs)); plot2d(u(1,:)',u(2,:)', style=couleurs(num+1), strf="000") elseif c_i == 2 then break end end Rysunek 5.1: Niektóre trajektorie w przestrzeni fazowej dla równania Van der Pol-a 5.1.3 Troche wi¦cej o ode W tym drugim przykªadzie u»yjemy funkcji ode z drugim czªonem, który przyjmuje dodatkowy parametr oraz ustalimy sami tolerancj¦ dla kroku czasowego podczas rozwi¡zywania. 87 Oto nasze nowe równanie ró»niczkowe ( Równanie Brusselator) : du1 dt du2 dt = 2 (6 + )u1 + u21 x2 = (5 + )u1 u21 u2 które przyjmuje jako punkt krytyczny Pstat = (2; (5 + )=2). Poniewa» warto±ci parametru zmieniaj¡ si¦ z ujemnej na dodatni¡, punkt stacjonarny zmienia swój charakter (jest staªy lub zmienny, wchodz¡c, dla = 0 w zjawisko rozgaª¦zienia Hopf). Interesuj¡ nas trajektorie z warunkiemi pocz¡tkowymi z s¡siedztwa tego punktu. Oto funkcja licz¡ca to równanie : function [f] = Brusselator(t,u,eps) // f(1) = 2 - (6+eps)*u(1) + u(1)^2*u(2) f(2) = (5+eps)*u(1) - u(1)^2*u(2) endfunction Aby poda¢ parametr, zast¡pimy w wywoªaniu ode nazw¦ funkcji (tutaj Brusselator) przez uporz¡dkowan¡ list¦ zawieraj¡c¡ nazw¦ funkcji oraz jej parametry : [x] = ode(x0,t0,t,list(moja_funkcja, par1, par2, ...)) W naszym przypadku : [x] = ode(x0,t0,t,list(Brusselator, eps)) a nast¦pnie zastosujemy fchamp aby narysowa¢ pole. Aby ustali¢ zakres tolerancji dla bª¦du lokalnego rozwi¡zania u»yjemy dodatkowych parametrów rtol oraz trami. atol zaraz po nazwie funckji (lub listy zawieraj¡cej t¦ funkcj¦ wraz z jej parame- W ka»dym kroku czasowym, e (tzn. v(tk 1 ) = U (tk 1 )) : bª¦du lokalnego tk 1 ! tk = tk 1 + tk , obliczane jest oszacowanie bª¦du dla kroku czasowego wychodz¡c z warunku pocz¡tkowego e (t k ) ' U (t k ) Z tk tk 1 f (t; v(t))dt + U (tk 1 ) ! (drugi skªadnik jest rozwi¡zaniem dokªadnym zale»nym od rozwi¡zania mumerycznego U (tk 1 ) otrzymanego w poprzednim kroku) a nast¦pnie sprawdza czy zawiera si¦ on w zakresie tolerancji formuowane za pomoc¡ dwóch parametrów rtol et atol : toli = rtoli jUi (tk )j + atoli ; 1 i n w przypadku gdy dane s¡ dwa wektory dªugo±ci n dla tych praramertów, oraz: toli = rtol jUi (tk )j + atol; 1 i n gdy dane s¡ skalary. Je»eli jei(tk )j toli dla wszystkich skªadowych tk , krok jest akceptowany a nast¦pnie obliczony zostaje nowy krok czasowy w taki sposób, »e kryterium naªo»one na przyszªy bª¡d b¦dzie miaªo pewne szanse na zrealizowanie si¦. W przeciwnym razie, ponownie caªkuje si¦ pocz¡wszy od t( k 1) przyjmuj¡c nowy, nieco mniejszy krok czasowy (obliczony wg zasady, »e przyszªy test bª¦du lokalnego b¦dzie równie» speªniony z silnym prawdopodobie«stwem). Metody tego typu oprócz zmiennych post¦pu czasowgo, manipuluj¡ równie» kolejno±ci¡ równa« w celu otrzymania dobrej wydajno±ci informacji... Domy±lnie stosowanymi warto±ciami s¡ rtol = 10 5 i atol = 10 7 (za wyj¡tkiem typów wybieraj¡cych metod¦ Runge Kutta). Wa»na uwaga : caªkowanie mo»e cz¦sto sie nie powi¹¢... Poni»ej przedstawiamy przykªadowy skrypt, w którym punkty krytyczne oznaczono maªymi, czarnymi kwadratami (otrzymano je przy pomocy prostej funkcji gracznej 88 xfrect) : // Brusselator eps = -4 P_stat = [2 ; (5+eps)/2]; // granice dla wykresu pola wektorowego delta_x = 6; delta_y = 4; x_min = P_stat(1) - delta_x; x_max = P_stat(1) + delta_x; y_min = P_stat(2) - delta_y; y_max = P_stat(2) + delta_y; n = 20; x = linspace(x_min, x_max, n); y = linspace(y_min, y_max, n); // 1/ wykres pola wektorowego xbasc() fchamp(list(Brusselator,eps),0,x,y, strf="041") xfrect(P_stat(1)-0.08,P_stat(2)+0.08,0.16,0.16) // dla zaznaczenia punktow krytycznych xselect() // 2/ rozwiazanie rownania rozniczkowego m = 500 ; T = 5 ; rtol = 1.d-09; atol = 1.d-10; // zakres tolerancji bledu t = linspace(0,T,m); couleurs = [21 2 3 4 5 6 19 28 32 9 13 22 18 21 12 30 27] num = -1 while %t [c_i,c_x,c_y]=xclick(); if c_i == 0 then plot2d(c_x, c_y, style=-9, strf="000") // male o aby zanaczyc C.I. u0 = [c_x;c_y]; [u] = ode(u0, 0, t, rtol, atol, list(Brusselator,eps)); num = modulo(num+1,length(couleurs)); plot2d(u(1,:)',u(2,:)', style=couleurs(num+1), strf="000") elseif c_i == 2 then break end end Rysunek 5.2: Niektóre trajektorie w polu fazowym dla Brusselatora ( 5.2 = 4) Generownie liczb losowych 5.2.1 Funkcja rand Do tej pory funkcja ta sªu»yªa nam gªównie do wypeªniania liczbami losowymi naszych macierzy i wektorów... Funkcja ta u»ywa liniowego generatora nast¦puj¡co Xn+1 = f (Xn ) = (aXn + c) mod m; n 0; Jej okres jest z pewno±ci¡ równy [0; m 1].) m (oznacza to, »e f gdzie 3 : 8 < m = 231 843314861 : ac == 453816693 jest permutacj¡ cykliczn¡ na przedziale Zauwa»my, »e wszystkie generatory liczb losowych w komputerze s¡ ci¡gami ideal- nie zdterminowanymi, które wygladaj¡ jak losowe (dla dobrych generatorów) wedªóg pewnej liczby testów statystycznych. Aby przeksztaªci¢ je do liczb rzeczywistych z przedziaªu 3 Wedªug tego, co autor rozumiaª ogl¡dan¡c kod 89 [0; 1), m (i otrzymuje si¦ generator liczb rzeczywistych, który w przybli»eniu speªnia rozkªad jednostajny na [0; 1)). Skªadnik pocz¡tkowy szeregu jest cz¦sto zwany inicjatorem i przyjmuje domy±lnie warto±¢ X0 = 0. Zatem pierwsze wywoªanie rand(pierwszy dzieli si¦ otrzyman¡ dan¡ przez otrzymany wspóªczynnik je±li wypeªniamy macierz lub wektor) jest zawsze : u1 = 453816693=231 0:2113249 Istnieje mo»liwo±¢ zmiany, w dowolnym momencie inicjatora za pomoc¡ instrukcji : rand("seed",inicjator) gdzie inicjator jest zawarty w przedziale [0; m 1]. Cz¦sto istnieje potrzeba zainicjowania szeregu poprzez wybór inicjatora mniej lub bardziej przypadkowo (sytuacja taka, aby nie mie¢ tej samej liczby za ka»dym razem), mo»emy chcie¢ na przykªad otrzyma¢ losowo dat¦ lub godzin¦. Scilab dysponuje funkcj¡ getdate która generuje wektor zªo»ony z 9 elementów. W±ród nich s¡: drugi oznacza miesi¡c (1-12), szósty, dzie« miesi¡ca (1-31), siódmy, godzin¦ (0-23), ósmy, minuty (0-59), i dziewi¡ty, sekundy (0-61 ?). Aby otrzyma¢ inicjator mo»na na przykªad dodawa¢ powy»sze elementy mi¦dzy sob¡ : v = getdate() rand("seed", sum(v([2 6 7 8 9]))) Zwró¢my uwag¦ równie» na mo»liwo±¢ zast¡pienia bierz¡cego inicjatora przez : germe = rand("seed") Pocz¡wszy od rozkªadu jednostajnego na [0; 1), mo»na otrzyma¢ inne rozkªady a funkcja rand dostarcza dostateczny interface pozwalaj¡cy otrzyma¢ rozkªad normalny (±rednia 0 i wariancja 1). Aby przej±¢ od jednego do drugiego, stosuje sie nast¦puj¡c¡ skªadnie : rand("normal") // aby otrzymac rozklad normalny rand("uniform") // aby powrocic do rozkladu jednostajnego Domy±lnie generator przyjmuje rozkªad jednostajny ale jest rozs¡dnie w ka»dej symulacji upewni¢ sie czy rand daje oczekiwany wynik u»ywaj¡c jedn¡ w tych instrukcji. Mo»na zraszt¡ sprawdzi¢ aktualny rozk¡ad za pomoc¡ : loi=rand("info") // jeden z rozkladow: "jednostajny" lub "normalny" Ponowne wywoªanie 1. A = rand(n,m) 2. je±li B rand mo»e przyj¡¢ nast¦puj¡ce formy : uzupeªnia macierz A (n,m) liczbami losowymi ; jest macierz¡ ju» zdeniowan¡ o wymiarach (n; m) efekt (pozwala unikn¡¢ poszukiwania wymiarów macierzy 3. wreszcie, u = rand() to B) A = rand(B) daje ten sam ; daje pojedyncz¡ liczb¦ losow¡. Do dwóch pierwszych metod mo»na doda¢ argument aby wskaza¢ dodatkowo rozkªad : rand(n,m,loi), A = rand(B,loi), uniform. gdzie loi 90 jest jednym z dwóch ªa«cuchów normal A = lub Wybrane zastosowania z u»yciem funkcji rand Pocz¡wszy od rozkªadu jednostajnego, w prosty sposób mo»na otrzyma¢ macierz (n,m) liczb wdªug : 1. rozkªad jednostajny na [a; b] : X = a + (b-a)*rand(n,m) 2. rozkªad jednostajny na liczbach caªkowitych z przedziaªu [n1 ; n2 ] : X = floor(n1 + (n2+1-n1)*rand(n,m)) (losujemy nast¦puj¡ce liczby rzeczywiste rozkªadu jednostajnego na przedziele rzeczywistym [n1 ; n2 + 1) a nast¦pnie bierzemy ich cz¦±¢ caªkowit¡). Symulacja pojedynczej próby Bernulliego z prawdopodobie«stwem sukcesu p: succes = rand() < p 4 symuluj¡cej rozkªad dwumianowy otrzymujemy dzi¦ki prostej metodzie B (N; p) : X = sum(bool2s(rand(1,N) < p)) (bool2s przekstaªca sukcesy w 1 i nie sumuje ich w funkcji sum). Z uwagi na fakt, »e wykony- wanie iteracji przez Scilaba jest do±c wolne, mo»na otrzyma¢ bezpo±rednio wektor (kolumnowy) skªadaj¡cy si¦ z m realizacji tego rozkªadu : X = sum(bool2s(rand(m,N) < p),"c") ale ko»ystne b¦dzie u»ycie funkcji 5 grand, która u»ywa metod¦ bardziej ambitn¡. Z drugiej strony, je±li u»ywacie tego sposobu , jest bardziej przej»y±cie aby kodowa¢ go jako funkcj¦ Scilaba. A oto prosta funkcja symuluj¡ce rozkªad geometryczny (ilo±¢ prób Bernulliego potrzeb- 6 : nych aby otrzyma¢ sukces) function [X] = G(p) // rozklad geometryczny X = 1 while rand() > p // porazka X = X+1 end endfunction Wreszcie, w nawi¡zaniu do rokªadu Normalnego (±rednia N (0; 1), otrzymamy rozkªad Normalny N (; 2) i odchylenie standardowe ) za pomoc¡ : rand("normal") X = mu + sigma*rand(n,m) // aby otrzymac macierz (n,m) tych liczb // lub przy uzyciu pojedynczej instrukcji : X = mu + sigma*rand(n,m,"normal") 5.2.2 Funkcja grand W skomplikowanych symulacjach wyko»ystuj¡cych wiele liczb losowych klasyczna funkcja z jej okresem rz¦du u»ycie grand 231 (' 2:147 109 ) mo»e okaza¢ si¦ troch¦ za ciasna. która równie» umo»liwia symulacj¦ wszystkich klasycznych rozkªadów. u»ywa sie prawie w taki sam sposób co 5 6 ale bardzo efektywnej dla du»ych N ! w ogólno±ci u»ywa¢ b¦dziemy funkcji grand pozwala otrzyma¢ wiekszo±¢ klasycznych rozkªadów ta funkcja jest bardziej efektywna dla maªych grand rand, tzn. »e mo»na u»y¢ jednej z dwóch nast¦puj¡cych A musi by¢ zdeniowana w momencie jaj wywoªania) : skªadni (oczywi±cie dla drugiej macierz 4 rand Jest zatem wskazane p. 91 grand(n,m,loi, [p1, p2, ...]) grand(A,loi, [p1, p2, ...]) où loi oznacza ªa«cuch znaków precyzuj¡cy rozkªad po którym nas¦puj¡ ewentualnie jego parametry. Kilka przykªadów (aby otrzyma¢ prób¦ n realizacji, pod postaci¡ wektora kolum- nowego) : 1. rozkªad jednostajny na liczbach caªkowitych z du»ego przedziaªu [0; m[ : X = grand(n,1,"lgi") gdzie m zale»y od generatora bazy (domy±lnie m = 232 ) ; 2. rozkªad jednostajny na liczbach caªkowitych z przedziaªu [k1 ; k2 ] : X = grand(n,1,"uin",k1,k2) (musi by¢ speªniony warunek aby k2 k1 2147483561 bo w przeciwnym wypadku prob- lem ten jest sygnalizowany jako bª¡d); 3. dla rozkªadu jednostajnego na przedziale [0; 1) : X = grand(n,1,"def") 4. dla rozkªadu jednostajnego na przedziaªe [a; b) : X = grand(n,1,"unf",a,b) 5. dla rozkªadu dwumianowego B (N; p) : X = grand(n,1,"bin",N,p) 6. dla rozkªadu geometrycznego G(p) : X = grand(n,1,"geom",p) : 7. dla rozkªadu Poissona ze ±redni¡ X = grand(n,1,"poi",mu) 8. dla rozkªadu wykªadniczego ze ±redni¡ : X = grand(n,1,"exp",lambda) 9. dla rozkªadu normalnego ze ±redni¡ i odchyleniem standardowym : X = grand(n,1,"nor",mu,sigma) Inne przykªady mo»na znale¹¢ na stronach pomocy. Pocz¡wszy od wersji 2.7 grand jest wyposarzony w ró»ne generatory bazowe (ktore generuj¡ liczby wedªug rozkªadu lgi). Domy±lnie czny okres rz¦du 219937 grand u»ywa MensenneT wister, który ma giganty7 oraz istnieje we wszystkoch 6 generatorach . Aby operowa¢ tymi generatorami, mo»na u»y¢ nast¦puj¡cych instrukcji: nom_gen = grand("getgen") grand(±etgen",nom_gen) etat = grand("getsd") grand(±etsd",e1,e2,..) 7 zwraca (nazw¦) bierz¡cego generatora generator , zwraca stan wewn¦trzny bierz¡cego generatora "mt" , , ¢lcg4" ¢lcg2" "fsultra" i "urand" , ten ostatni b¦d¡cy poprostu generatorem staje si¦ bierz¡cym generatorem ustawia wewn¦trzny stan bierz¡cego generatora ,"kiss" , nom_gen rand. 92 Wymiar stanu wewn¦trznego ka»dego generatora zale»y od jego typu: od jednej wchodz¡cej dla urand do 624 wchodz¡cych plus index dla Mersenne Twister8 . Je»eli chcecie wykona¢ ponownie t¦ sam¡ symulacj¦, musicie zna¢ stan wewn¦trzny (z przed symulacji) u»ywanego generatora oraz go zapisac w taki lub inny sposób. Przykªad: grand("setgen","kiss") e = [1 2 3 4]; // kiss staje sie generatorem bierzacym // stan jaki chce palowyc na kiss // (musi miec 4 wejsciowe) grand("setsd",e(1),e(2),e(3),e(4)); // zrobione! grand("getsd") // musi zwrocic wektor e X = grand(10,1,"def"); // 10 liczb s1 = sum(X); X = grand(10,1,"def"); // znowu 10 liczb s2 = sum(X); s1 == s2 // ogolnie s1 bedzie sie roznic od s2 grand("setsd",e(1),e(2),e(3),e(4)); // powrot do stanu pierwotnego X = grand(10,1,"def"); // znowu 10 liczb s3 = sum(X); s1 == s3 // s1 musi byc rowne s3 5.3 Dystrubuanty i ich odwrotno±ci 2r , ...) Dystrybuanty s¡ cz¦sto u»ywane przy testach statystycznych ( poniewa» pozwalaj¡ na obliczenia, niech : 1. dystrybuanta w 1 lub kilku punktach ; 2. jej odwrotno±¢ w 1 lub kilku punktach ; 3. jeden z parametrów rozkªadu jest dany przez pozostaªe i par¦ (x; F (x)) ; W Helpie, dystrybuanty mo»na znale¢ pod hasªem Cumulative Distribution Functions..., wszystkie te funkcje poprzedzone s¡ skrótem cdf. Przykªadowo dla rozkªadu Normalnego N (; 2), funkcja która nas interesuje nosi nazw¦ cdfnor i jej skªadnia jest nast¦puj¡ca : 1. 2. 3. [P,Q]=cdfnor("PQ",X,mu,sigma) aby otrzyma¢ P = F; (X ) i Q = 1 P , X, mu oraz sigma mog¡ by¢ wektorami (o tych zamych wymiarach) i wówczas otrzymuje sie dla P i Q wektor za pomoc¡ Pi = Fi ;i (Xi ) ; [X]=cdfnor("X",mu,sigma,P,Q) aby otrzyma¢ X = F;1 (P ) (podobnie jak poprzednio argumentami mog¡ by¢ wektory o tych zamych wymiarach i wówczas otrzymuje si¦ Xi = Fi1;i (Pi ) ; [mu]=cdfnor("Mean",sigma,P,Q,X) aby otrzyma¢ ±redni¡ ; 4. i ostatecznie [sigma]=cdfnor("Std",P,Q,X,mu) aby dosta¢ odchylenie standardowe. Dwie ostatnie skªadnie funkcjonuj¡ tak»e gdy argumentami s¡ wektory o jednakowych wymiarach. Uwagi : p oraz q = 1 p pozwala uzyska¢ precyzj¦ w obszarze gdzie p jest bliskie 0 lub 1. Dla p bliskiego 0 funkcja wyko»ystuje warto±¢ p, natomiast dla p bliskiego 1 funkcja wyko»ystuje warto±¢ q ; mo»liwo±¢ jednoczesnej pracy z ªa«cuch znaków pozwalaj¡cy otrzyma¢ funkcj¦ odwrotn¡ nie zawsze ma posta¢ zobacznie na odpowiednich stronach pomocy. 8 procedura inicjuj¡ca wraz z pojedy«czym wej±ciem istnieje nie mniej jednak dla tego generatora. 93 "X"... 5.4 Proste symulacje stochastyczne 5.4.1 Wprowadzenie i notacja Cz¦sto symulacja polega przede wszystkim na otrzymaniu wektora : xm = (x1 ; ::::; xm ) którego skªadowe s¡ rozumiane jako realizacje niezale»nych zmiennych losowych i podobnie rozkªad X1 ; X2 ; ::::; Xm rand lub grand9 . W przypadku próby X zmienn¡ losow¡ generuj¡c¡ ten sam xm otrzymuje sie bezpo±rednio lub po±rednio za pomoc¡ funkcji (b¦dziemy oznacza¢ przez rozkªad). W praktyce wektor xm poszukujemy zbli»onych charakterystyk jej rozkªadu takich jak warto±¢ oczekiwana, odchylenie standardowe, dystrybuanta (lub funkcja g¦sto±ci) lub te» gdy stawiamy hipotez¦ dotycz¡c¡ rozkªadu, aby okre±li¢ jej parametry, albo, gdy parametry s¡ ju» znane, werykowa¢ za pomoc¡ testów statystycznych, »e nasza próba jest (mo»liwie) dobrze reprezentatywn¡ zmienn¡ losow¡ która pod¡»a efektywnie za rozkªadem itd... <-??????????????????????????? Dla przypadków, które nas interesuj¡, znane s¡ przewa»nie dokªadne wyniki teoretyczne, a symulacja sªu»y jedynie do zilustrowania wniosków, twierdze« (lgn?, TCL =? CTG, itd...), dziaªania metody lub algorytmu, ... 5.4.2 Przedziaªy ufno±ci Niekiedy o empirycznej warto±ci oczekiwanej otrzymanej z naszej próby (w Scilabie : = mean(xm)) chcieliby±my powiedzie¢, »e mie±ci si¦ w pewnym przedziale. x_bar_m Ponadto chcieliby±my zna¢ ów przedziaª aby móc zapisa¢, »¦ : E [X ] 2 Ic = 0:05 gdzie najcz¦±ciej lub 0:01 z prawdopodobie«stwem 1 (przedziaªy ufno±ci odpowiednio 95% i 99%). W celu wyznaczenia tych przedziaªów za punkt wyj±cia posªu»y na C.T.G.. Je±li przyjmiemy : m 1X X m = X m i=1 i xm jest pojedyncz¡ realizacj¡), wówczas prowo zbie»ne do E [X ] i na mocy C.T.G (przy pewnych za zmienn¡ losow¡ dla warto±ci ±redniej (gdzie wielkich liczb mówi nam, »e zaªo»eniach...) mamy : X m jest pm(X Z b 1 2 p lim P ( a < b ) = e t =2 dt m !+ 1 2 a 2 (przyjmuje si¦, »e V ar [X ] = ). Dla dostatecznie du»ych m przyjmuje si¦, »e : pm(X E [X ]) Zb 2 1 m P (a < b) p e t =2 dt 2 a m E [X ]) Je»eli chcemy aby przedziaª ufno±ci byª symetryczny : p1 2 9 Z a a e t2 =2 dt = F N (0;1) (a) FN (0;1) ( a) = 2FN (0;1) (a) 1 = 1 w wi¦kszo±ci przypadków próba statystyczna dotyczy miar zycznych (temperatura, ci±nienie,...), biometrycznych (wzrost,waga), sonda»y, itd... otrzymane dane s¡ zbierane w plikach (lub bazach danych); pewne programy (jak R) proponuj¡ dla nich ukªad danych (dla których studenci b¦d¡ mogli robi¢ r¦cznie !) niestety Scilab nie dysponuje tak¡ mo»liwo±ci¡; niemniej przypadków gdzie u»ywamy takich symulacji jest równie wiele, na przykªad aby przestudiowa¢ zachowanie pewnych systemów wej±ciowych (lub zakªuce«) losowych lub podobnie aby rozwi¡za¢ problemy czysto deterministyczne ale dla których metody analizy numerycznej s¡ zbyt skomplikowane lub niemo»liwe do zaimplementowania<-??? . 94 wówczas : 1 (1 a = FN (0 ;1) 2 1 ( ) FN (0 ;1) 2 ) albo co zapisuje si¦ w scilabie : a_alpha = cdfnor("X", 0, 1, 1-alpha/2, alpha/2) Otrzymujemy ostatecznie 10 : a a p ; xm + p ] m m E [X ] 2 [xm 1 z prawdopodobie«stwem (je»eli przybli»enie granicy jest poprawne...). Problem pojawia si¦ w momencie gdy nieznane jest odchylenie standardowe... Wyko»ystuje v u m u 1 X Sm = t (Xi X m )2 m 1 si¦ wówczas etymator : i=1 Zast¦puj¡c odchylenie standardowe przez sm (gdzie sm jest pojedyncz¡ realizacj¡ Sm ), otrzy- mujemy przedziaª ufno±ci, który przyjmujemy równie» dla warto±ci empirycznej. Szczególne przypadki : 1. je±li Xi ma rozkªad normalny N (; 2 ) wówczas : pm Xm t(m 1) Sm gdzie t(k) ma rozkªad Studenta o k stopniach swobody. w tym przypadku wszelkie poprzednie przybli»enia trac¡ moc (przybli»enie granicy i przybli»enie odchylenia standardowego) oraz otrzymuje sie : 2 [xm gdzie sm a sm pm ; xm + apsmm ] avec probabilité 1 jest empirycznym odchyleniem stndardowym z próby (sm w scilabie) gdzie a = st_deviation(xm) jest warto±ci¡ krytyczn¡ rozkªadu Studenta : a = Ft(m1 1) (1 2 ) 11 przez : otrzyman¡ w scilacie a_alpha = cdft("T", m-1, 1-alpha/2, alpha/2) 2. w momencie gdy wariancja wyra»a si¦ przez funkj¦ warto±ci oczekiwanej (Bernouilli, Poisson, wykªadniczy,...) mo»na pzsªu»y¢ die przybli»eniem odchylenia standardowego i otrzymuje si¦ przedziaª ufno±ci poprzez rozwi¡zanie odpowiedniej nierówno±ci. 5.4.3 Wykres dystrubuanty empirycznej Dystrybuant¡ zmienne losowej X nazywamy funkcj¦ : F (x) = Probabilité que X x 10 11 dla przedziaªu z 95%, mamy a ' 1:96 cz¦sto zast¦powane przez 2. zobacz na odpowiednich stronach pomocy : wªa±ciwie funkcje cdf nie maj¡ regularnej/uniwersalnej skªadni i musi by¢ zawsze oznaczeniem pozwalaj¡cym otrzyma¢ funkcj¦ odwrotn¡ do dystybuanty, tutaj jest to 95 "T" ! "X" nie Dystrybuanta empiryczna pochodz¡ca z próby xm jest deniowana jako : Fxm (x) = cardfxi <= xg=m Jest to funkcja schodkowa, któr¡ liczy si¦ ªatwo je±li posortujemy wektor cym (mamy wi¦c Fxm (x) = i=m dla xi x < xi+1 ). w scilabie jest funkcja sort która sortuje malej¡co12 . xm w porz¡dku rosn¡- Standardowym algorytmem sortuj¡cym Aby posortowa¢ wektor xm w porz¡dku rosn¡cym u»yjemy : xm = - sort(-xm) £atwym sposobem narysowania wykresu jest funkcja plot2d2. Oto przykªadowy kod : dystrybuanta_empiryczna(xm) // wykres dystrybuanty (empirycznej) // na próbie xm m = length(xm) xm = - sort(-xm(:)) ym = (1:m)'/m plot2d2(xm, ym, leg="dystrybuanta empiryczna") endfunction Zwró¢my uwag¦ na zapis : xm(:), który jest analogiczny do zapisywania wektora wierszowego. A teraz przykªad dla rozkªadu normalnego N (0; 1) : m = 100; xm = grand(m,1,"nor",0,1); xbasc() dystrybuanta_empiryczna(xm); // wykres fct dystrybuanty empirycznej // dane dla wykresu dystrybuanty "dokladnej" x = linspace(-4,4,100)'; y = cdfnor("PQ", x, zeros(x), ones(x)); plot2d(x, y, style=2) // nanosimy krzywa na pierwszy wykres xtitle("Dystrybyanty dokladna i empiryczna") który daje nast¦puj¡cy wykres (5.3). Rysunek 5.3: Systrybuanta dokªadna i empiryczna rozkªadu normalnego 5.4.4 Test 2 xm = (x1 ; :::; xm ) b¦dzie nasz¡ prób¡ dla dalszej analizy. Niech b¦dzie dana hipoteza H zmienne losowe postaci (X1 ; :::; Xm ) maj¡ rozkªad L. Chcemy wiedzie¢ czy hipoteza jest Niech : prawdziwa czy nie. Dla naszej próby mo»na bez w¡tpienia obliczy¢ statystyki elementarne (±redni¡ i odchylenie standardowe empiryczne) i je»eli s¡ one dostatecznie bliskie warto±ci oczekiwanej oraz odchyleniu standardowemu rozkªadu statystyczny. Test 2 Na przykªad zakªadaj¡c, »e rozkªad y= zobacz tak»e funkcj¦ gsort, mo»na wówczas zastosowa¢ test L jest zadany przez f(vi; pi); 1 i ng. obliczeniu wielko±ci : 12 L, stosuje si¦ dla rozkªadów dyskretnych o sko«czonej liczbie warto±ci. Pn i=1 (oi mpi która robi wi¦cej rzeczy 96 mpi )2 Test polega na gdzie oi jest liczb¡ realizacji xj równych vi i na przyrównaniu otrzymanej wielko±ci y do yy . Je»eli do rówanania na y wstawiwy w miejsce próby x1 ; :::; xm , zmienne losowe X1 ; :::; Xm w 14 zmienn¡ losow¡ Y , któr¡ mo»na przybli»a¢ (dla dostatecznie du»ych ten sposób zdeniujemy 2 m) rozkªadem o n 1 stopniach swobody. Warto±¢ progow¡ otrzymujemy przez : y = F 21 (1 ) warto±ci progowej y 13 je±li , test b¦dzie pozytywny n 1 przy = 0:05 lub = 0:01. W Scilabie warto±¢ t¦ otrzymamy poprzez : y_progowe = cdfchi("X", n-1, 1-alpha, alpha) Aby obliczy¢ cz¦sto±¢ oi za pomoc¡ Scilaba mo»emy u»y¢ nast¦puj¡cej metody : occ = zeros(n,1); for i=1:n occ(i) = sum(bool2s(xm == v(i))); // albo length(find(xm==v(i))) end if sum(occ) ~= m then, error("b\l{}\k{a}d oblicze\'n"), end I aby otrzyma¢ wielko±¢ y mo»na napisa¢ (stosuj¡c zapis wktorowy15 ) : y = sum( (occ - m*p).^2 ./ (m*p) ) pod warunkiem, »e co occ p (wektor przwdopodobie«stw rozkªadu L), b¦dzie tych samych wymiarów (tutaj wektor kolumnowy ??????????). Uwagi : 2 jest wa»ne gdy m = mini pi ) jako minimalny przybli»anie rozkªadem mpmin > 5 (pmin jest dostatecznie du»e... »adamy cz¦sto warunek zastosowania tego testu; w ten sposób mo»ecie werykowa¢ to zaªo»enie i napisa¢ wiadomo±¢ aby uprzedzi¢ u»ytkownika je»eli nie jest speªnione. mo»na ªatwo pogrupowa¢ te obliczenia w funkcji; dla rozkªadu ci¡gªego test mo»e si¦ stosowa¢ grupuj¡c wielko±ci na przedziaªy, na przykªad dla rozkªadu U[0;1] , stosuje si¦ n równomiernie rozªo»onych przedziaªów; podobnie dla rozkªadu dyskretnego o niesko«czonej liczbie wielko±ci, mo»na pogrupowa¢ je w kolejki rozkªadu; podobn¡ procedur¦ mo»na zastosowa¢ dla roskªadów sko«czonych dla których warynek zastosowania testu nie jest speªniony. je»eli testujecie rozkªad w którym pewne parametry zostaªy wcze±niej obliczone na podstawie danych, nale»y okre±li¢ liczb¦ stopni swobody dla rozkªadu spodziewamy si¦ rozkªadu 2 ; na przykªad je±li B (n 1; p) i u»yjemy p = xm =(n 1) wówczas nieprzekraczaln¡ warto±y = F21 (1 ) a nie y = n 2 ci¡ progow¡ dla testowanej hipotezy zerowej b¦dzie F21 (1 n 1 ). 5.4.5 Test Koªmogorowa-Smirnova X b¦dzie rzeczywist¡ zmienn¡ losow¡ dla której dystrybuanta rozkªadu jest funkcj¡ F oraz X1 , X2 ,..., Xm , m niezale»nych zmiennych losowych. Dla realizacji Xi (mówimy m = (x ; ::::; x )), mo»na skonstruowa¢ dystrybuant¦ empiryczn¡ która przy (m ! wektor x 1 m +1) d¡zy do dystrybuanty teoretycznej. Test KS polega na okre±leniu ró»nicy pomi¦dzy Niech ci¡gª¡ 13 14 15 oi nie odbiega zbytnio od mpi , zatem je»eli y , sk¡d odrzucimy hipotez¦ dla y > y ... z intuicyjnego punktu widzenia je»eli hipoteza jest dobra oczekujemy, »e hipoteza jest faªszywa oczekujemy »e otrzymamy wysok¡ warto±¢ poprzez zmienn¡ losow¡ wektorow¡ O = (O1 ; :::; On ) maj¡c¡ rozkªad wielomianowy<-????? ¢wiczenie: przeksztaª¢ t¦ instrukcj¦ wektorow¡ aby zrozumie¢ jak (i dlaczego) dziaªa. 97 dystrybuant¡ teoretyczn¡ i empiryczn¡ (otrzyman¡ na podstawie naszej próby p w nast¦puj¡cy sposób : km = m sup jF (x) 1<x<+1 (x1 ; ::::; xm )) Fxm (x)j i na porównaniu jej z wielko±ci¡ dopuszczaln¡. Je»eli zast¡pimy nasz¡ realizac¦ przez odpowied- km staje si¦ równie» zmienn¡ losow¡ (któr¡ zapisujemy jako Km ). nie zmienne losowe, wówczas Zgodnie z teori¡ jej dystrybuanta jej rozkªadu jest nast¦puj¡ca : lim P (Km x) = H (x) = 1 2 m!+1 i odrzycimy t¦ hipoteze gdy: = 0:05 lub 0:01 km > H 1 (1 na przykªad. ) Je±li u»ywamy przybli»enia nieprzekraczalna warto±¢ progowa jest : kseuil = Obliczenie j =1 2 2 ( 1)j 1 e 2j x 2 , je»eli rozwa»ana hipoteza jest faªszywa, otrzymane warto±ci km b¦d¡ du»e Jak przy te±cie z +1 X r H (x) ' 1 2e 2x2 wówczas 1 2 ln( ) 2 km nie sprawia problemu je»eli posortuje si¦ wektor (x1 ; x2 ; : : : ; xm ). Sortowaniw b¦dzie efektywne gdy zwrócimy uwag¦ ne fakt aby : sup x2[xi ;xi+1 [ i m Fxm (x) F (x) = F (xi ); sup et x2[xi ;xi+1 [ F (x) Fxm (x) = F (xi+1 ) i m dwie nast¦pne wielko±ci mo»na ªatwo policzy¢ : p += m km p km = m p j (Fxm (x) F (x)) = m max ( 1 j m m 1<x<+1 sup F (xj )) p j 1 ) m (F (x) Fxm (x)) = m max (F (xj ) 1 j m 1<x<+1 + i otrzymujemy w ten sposób km = max(km ; km ). sup 5.4.6 ¢wiczenia Czy to sprawka kostki ? Rzucamy 200 razy symetryczn¡ kost¡ do gry, do±wiadczenie jest nast¦puj¡ce : rzucamy tyle razy a» wypadnie 1 (ale nie wi¦cej ni» 10 rzutów). Otrzymali±my nast¦puj¡ce wyniki : liczba rzutów 1 2 3 4 5 6 7 8 9 10 11 ilo±¢ do±wiadcze« 36 25 26 27 12 12 8 7 8 9 30 na przykªad 36 razy jedynka pojawiªa sie w pierwszym rzycie, 25 razy jedynka pojawiªa sie w drugim »ucie, itd... Wykona¢ test 2 aby udzieli¢ odpowiedzi na postawione pytanie. 98 Urna Polya Losujemy N razy z urny Polya zawieraj¡cej pocz¡tkowo r kul czerwonych i v kul zielonych. Ka»de losowanie polega na wyci¡gni¦ciu jednej kuli i jej odªo»eniu spowrotem do urny wraz z c kulami tego samego koloru. Przez Xk oznaczamy stosunek kul zielonych po k losowaniach do sumy kul, Vk oznacza ilo±¢ kul zielonych : v X0 = ; V = v: v+r 0 Je»eli v = r = c = 1, wynik b¦dzie nast¦puj¡cy : 1. E (XN ) = E (X0 ) = X0 = 1=2 ; 1 N +1 2. XN ma rozkªad normalny na zbiorze f N +2 ; :::::; N +2 g ; 3. dla N ! +1, XN jest zbie»ne do rozkªadu jednostajnego na przedziale [0; 1). Wyko»ystacie symulacj¦ aby zilustrowa¢ dwa pierwsze wyniki. 1. Aby przeprowadzi¢ ró»ne symulacje, mo»na napisa¢ funkcj¦ zale»n¡ od parametru która wykonuje N kolejnych losowa«. Funkcja ta zwraca wi¦c XN i VN N i : function [XN, VN] = Urna_Polya(N) // symulacja N losowan z "Urny Polya" : VN = 1 ; V_plus_R = 2 ; XN = 0.5 for i=1:N u = rand() // losowanie jednej kuli V_plus_R = V_plus_R + 1 // zwieksza ilosc kul if (u <= XN) then // wylosowalislmy kule zielona : mamy XN prawdopodobienstw // wylosowania kuli zielonej (1 - XN dla kuli czerwonej) VN = VN + 1 end XN = VN / V_plus_R // aktualizujemy stosunek kul zielonych end endfunction niestety skuteczne wykonanie statystyk wymaga wielokrotnego wywoªania tej funkcji, a zatem, z uwagi na stosunkowo powolne wykonywanie iteracji przez Scilab, nale»y naposa¢ funkcj¦ wykonuj¡c¡ m procesów równolegªych . Mo»na u»y¢ funkcji find aby naprawi¢????? urny z których losujemy kule zielone. 2. Napisa¢ skrypt znajduj¡cy poprzez symulac¦ warto±¢ oczekiwan¡ (wraz z jej przedzieªem ufno±ci). 3. Rozwin¡¢ poprzedni skrypt testuj¡c hipotez¦ H dotycz¡c¡ rozkªadu zmiennej losowej 1 N +1 H : XN ma rozkªad jednostajny na zbiorze f N +2 ; :::::; N +2 g 2 za pomoc¡ testu . XN 4. Porówna¢ wyniki gracznie, na przykªad rysuj¡c na jednym rysunku dystrybuant¦ empiryczn¡ i teoretyczn¡, lub te» narysowa¢ wykres funkcji g¦sto±ci rozkªadu 2 dla otrzy- manych wielko±ci przez ten test, wielko±ci progowe zaznaczy¢ liniami pionowymi. Most ????? Proces stochastyczny (w którym U oznacza rozkªad jednostajny na przedziale n 1 X Xn (t) = p (1 n i=1 fUi tg jest taki, »e dla ustalonego t) t 2]0; 1[ mamy : lim X (t) = Y (t) N (0; t(1 n !+ 1 n 99 t)) [0; 1]) : Chcemy zilustrowa¢ wyniki za pomoc¡ symulacji. Schemat pracy : 1. Napisa¢ funkcj¦ Scilaba alizacj¦ function [X] = pont_brownien(t,n) pozwalaj¡c¡ otrzyma¢ re- Xn (t) ; w ci¡gu wywoªamy t¦ funkcj¦ m razy z warto±ci¡ n dostatecznie du»ym16 nale»y zatem napisa¢ j¡ bez u»ycia pentli. 2. Napisa¢ sktypt scilaba wyko»ystuj¡c t¦ symulacj¦ mostu Brownien : wykona¢ m symulacji Xn (t) (z du»ym n) i przedstawi¢ gracznie zachowanie rozkªadu (rysuj¡c jego dystrybuant¦ empiryczn¡ i nakªadaj¡c na ni¡ dystrybuant¦ teoretyczn¡ Y (t)) a nast¦pnie zastosowa¢ test Koªmogorowa-Smirnova. Mo»na umie±ci¢ poprzedni¡ funkcj¦ na pocz¡tku skryptu aby pracowa¢ tylko z jednym plikiem. m i n : kiedy m wierzy ...?????????????.......gdz n nie jest dostatecznie du»e (poniewa» rozkªad normalny otrzymuje si¦ z granicy gdy n ! +1), nale»y zatem zwi¦kszy¢ n... Dla t = 0:3, mo»ecie na przykªad przetestowa¢ z n = 1000 i m = 200; 500; 1000, i test daje dobre wyniki (»adko od»uca hipotez¦ zerow¡) ale dla m = 10000 test jest prawie zawsze negatywny. Je»eli zwi¦kszymy n (na przykªad do n = 10000 ale obliczenia zaczynaj¡ by¢ nieco dªu»sze na komputerze Uwaga : nie jest ªatwo dobra¢ odpowiednie wielko±ci dla test si¦ nie powiódª poniewa» uznaª, »e PC wykonanym w 2003) wówczas test ponownie staje si¦ normalnie pozytywny. 16 aby przybli»y¢ Y ( t) ! 100 Rozdziaª 6 Ciekawostki W tej cz¦±ci przedstawiono/przytoczono przegl¡d niektórych bª¦dów cz¦sto spotykanych w Scilabie... 6.1 Deniowanie wektora i macierzy wspóªczynnik po wspóªczyn- niku Ten bª¡d jest jednym z najcz¦strzych. Rozwa»my nast¦puj¡cy skrypt : K = 100 // jedyny parametr w tym skrypcie for k=1:K x(k) = cos y(k) = cos innego end plot(x,y) Je»eli uruchomimy ten skrypt po raz pierwszy, zostan¡ zdeniowane dwa wektory x i y. Po- jawia si¦ jeden maªy bª¡d poniewa» w ka»dej iteracji Scilab redeniuje rozmiary tych wektorów (nie wie, »e ich wymiarem ko«cowym b¦dzie (K,1)). Zauwa»my równie», »e domy±lnie stworzy wektor kolumnowy. Podczas drugiero wywoªania (zmieniaj¡c parametr znane i takie, »e k s¡ rówenie» ich wspóªrz¦dne. W konsekwencji je»eli nowa warto±¢ K < 100 jest tylko K > 100 wówczas nasze wektory K K...) wektory xiy s¡ jest mniejsze od 100 (pocz¡tkowa wielko±¢ parametru K) zatem zmieniane x i y K jest taka, »e : maj¡ zawsze 100 wspóªrz¦dnych (zmodykowane pierwszych) a wykres nie pokazuje tego co oczekujemy ; nie pojawia si¦ »aden problem (za wyj¡tkiem tego, »e rozmiar wektora jest za ka»dym razem aktualizowany pocz¡wszy od 101 iteracji) Najlepszym sposobem jest zdeniowanie wektorów xiy za pomoc¡ inicjalizacji ich rodzaju : x = zeros(K,1) ; y = zeros(K,1) w ten sposób uniknie si¦ wszelkich bª¦dów. Nasz skrypt zatem przyjmie posta¢ : K = 100 // jedyny parametr w tym skrypcie x = zeros(K,1); y = zeros(K,1); for k=1:K x(k) = cos y(k) = cos innego end plot(x,y) 101 6.2 Na temat warto±ci zwracanych przez funkcj¦ Zaªó»my, »e mamy zaimplementowan¡ funkcj¦ w Scilabie zwracaj¡c¡ dwa argumenty, na przykªad : function [x1,x2] = resol(a,b,c) // rozwi\k{a}zanie równania kwadratowego a x^2 + b x + c = 0 // formu\l{}ad poprawiona dla wi\k{e}kszo\'sci metod numerycznych // (w celu unikni\k{e}cia odejmowania dwóch s\k{a}siednich liczb) if (a == 0) then error(" nie rozwa\.zamy przypadku gdy a=0 !") else delta = b^2 - 4*a*c if (delta < 0) then error(" nie rozwa\.zamy przypadku gdy delta < 0 ") else if (b < 0) then x1 = (-b + sqrt(delta))/(2*a) ; x2 = c/(a*x1) else x2 = (-b - sqrt(delta))/(2*a) ; x1 = c/(a*x2) end end end endfunction W ogólnym przypadku je»eli wywoªamy funkcj¦ w Scilabie w nast¦puj¡cy sposób : -->resol(1.e-08, 0.8, 1.e-08) ans = - 1.250D-08 jej wynik jest przypisany zmiennej ans. Ale zmienna ta jest pojedyncz¡ liczb¡, a funkcja zwraca dwie warto±ci z których tylko pierwsza jast przypisana zmienne ans. Aby zobaczy¢ drug¡ warto±¢ u»yjemy skªadni : -->[x1,x2] = resol(1.e-08, 0.8, 1.e-08) x2 = - 80000000. x1 = - 1.250D-08 Inna, niebezpieczniejsza puªapka jest nast¦puj¡ca. Zaªó»my, »e znamy precyzj¦ z jak¡ dziaªa aic k) obliczymy wszystkie pierwiastki dla ta formuªa (w stosunku do precyzji dziaªania formóª klasycznych). Aby dobra¢ warto±ci (na przykªad a = c = 10 k przyjmuj¡c ró»ne warot±ci kolejnych parametrów równania i ustawimy je jako dwa wektory sªu»ce do póniejszej analizy. Najprostrzy schemat jest nast¦puj¡cy : b = 0.8; kmax = 20; k = 1:kmax; x1 = zeros(kmax,1); x2=zeros(kmax,1); for i = 1:kmax a = 10^(-k(i)); // c = a [x1(i), x2(i)] = resol(a, b, a); // BLAD ! end Taka skªadnia nie zadziaªa (jedynie w przypadku gdy funkcja zwraca jedn¡ warto±¢). Nale»y wykona¢ to w dwóch krokach : 102 [rac1, rac2] = resol(a, b, a); x1(i) = rac1; x2(i) = rac2; Uwaga : 6.3 Problem ten jest rozwi¡zany w wercjach rozwijaj¡cych (cvs) dla Scilaba. Funkcja zostaªa zmidykowana ale... wszystko dziaªa tak jak przed modykacj¡ ! By¢ mo»e zapomnieli±cie zapisa¢ zmiany w waszym edytorze albo, co jest bardziej prawdopodobne, zapomnieli±cie zaªadowa¢ plik zawieraj¡cy funkcj¦ w Scilabie za pomoc¡ instrukcji getf (lub exec) pomoc¡ strzaªki 6.4 getf (lub exec) ! Jedna maªa wskazówka : instrukcja jest z pewno¡ci¡ zapisana niedaleko w historii komend, wystarczy zatem za " odszuka¢ t¦ instrukcj¦. Problem z Domy±lnie funkcja rand rand dostarcza liczby losowe wedªug rozkªadu jednostajnego na przedziale [0; 1[, mo»na jednak otrzyma¢ rozkªad normalny N (0; 1) za pomoc¡ : rand(«ormal"). Chc¡c rand("uniform"). Aby unikn¡¢ funkcji rand. precyzowaªo rozkªad powróci¢ do rozkªadu jednostajnego nale»y wpisa¢ instrukcj¦ tego problemu najlepiej pami¦ta¢ aby ka»de wywoªanie który nas aktualnie interesuje (patrz poprzedni rozdziaª). 6.5 Wektory wierszowe, wektory kolumnowe... W kontek±cie macierzowym ich posta¢ jest sprecyzowana, ale dla innych zastosowa« nie zawsze s¡ one rozrózniane i stosuje sie funkcj¦ która dziaªa w obydwu przypadkach. Aby przyspieszy¢ obliczenia dobrze jest odwoªa¢ si¦ do skªakni macierzowej i wybra¢ jedn¡ lub drug¡ form¦ wektora. Mo»na wyko»ysta¢ funkcj¦ matrix w nast¦puj¡cy sposób : x = matrix(x,1,length(x)) // aby otrzyma\'c wektor wierszowy x = matrix(x,length(x),1) // aby otrzyma\'c wektor kolumnowy Chc¡c otrzyma¢ w prosty sposób wektor kolumnowy mo»na wyko±ysta¢ instrukcj¦ : x = x(:) 6.6 Operator porównania W pewnyc przypadkach Scilab akceptuje symbol = jako operator porównania : -->2 = 1 Warning: obsolete use of = instead of == ! ans = F ale lepiej jest zawsze u»ywa¢ symbolu 6.7 ==. Liczby zespolone a liczby rzeczywiste Scilab jest tak skonstruowany aby traktowa¢ liczby rzeczywiste w taki sam sposób jak liczby zespolone ! px i log(x) Jest to calkiem praktyczne ale mo»e niekiedy by¢ przyczyn¡ niespodzianek, na przykªad podczas szacowania funkcji rzeczywistej poza jej dziedzin¡ (na przykªad 103 dla x < 0, acos (x) i asin (x) dla x 2= [ 1; 1], acosh (x) x < 1) dla ) poniewa» Scilab zwraca wówczas oszacowanie cz¦±ci zespolonej tej funkcji. Aby dowiedzie¢ si¦ czy dziaªamy na zmiennej zespolonej czy rzeczywistej nale»y u»y¢ funkcji isreal : -->x = 1 x = 1. -->isreal(x) ans = T -->c = 1 + %i c = 1. + i -->isreal(c) ans = F -->c = 1 + 0*%i c = 1. -->isreal(c) ans = F 6.8 Proste instrukcje a funkcje Scilaba W niniejszym opracowaniu cz¦stu stosuje sie zamiennie terminów prosta instrukcja i funkcja aby wskaza¢ procedury dost¦pne w bie»¡cej werksji Scilaba. Istnieje jednak fundamentalna ró»nica pomi¦dzy prost¡ instrukcj¡ która jest kodowana w fortranie 77 lub w C a funkcj¡ (zwan¡ równie» makro) która jest kodowana w j¦zyku Scilaba : funkcja jest wówcz¡s rozumiana jako zmienna Scilaba, i dzi¦ki temu mo»na j¡ u»y¢ jako argumentu dla inne funkcji. Pocz¡wszy od wersji 2.7, proste instrukcje bywaj¡ zmiennymi w Scilabie (fptr). Niemniej jednak przysparzaj¡ wiele problemów (aktualnie rozwi¡zanych w rozwini¦ciach). Oto przykªad problemu jaki mo»na spotka¢ : funkcja nast¦puj¡ca pozwalaj¡ca przybli»a¢ zbiór przy zastosowaniu metody Monte Carlo : function [im,sm]=MonteCarlo(a,b,f,m) // /b // przybli\.zenie | f(x) dx przy zastosowaniu metody Monte Carlo // /a // zwracane jest równie\.z empiryczne odchylenie standardowe xm = grand(m,1,"unf",a,b) ym = f(xm) im = (b-a)*mean(ym) sm = (b-a)*st_deviation(ym) endfunction Jako argument f oczekuje si¦ funkcji Scilaba ale ten kod powienien równie» dziaªa¢ dla funkcji 1 poniewa» s¡ one teraz rozwa»ane matematycznych które nale»¡ do prostych instrukcji Scilaba 1 na przykªad sin, exp i wiele innych. 104 jako zmienne. Niemniej jednak test z u»yciem prostej instrukcji exp nie powiedzie si¦ : -->[I,sigma]=MonteCarlo(0,1,exp,10000) // bug ! Wywoªuj¡c funkcj¦ MonteCarlo za pomoc¡ getf z opcj¡ nie kompilowania : -->getf("MonteCarlo.sci","n") bª¡d ten [bug] (skorygowany w aktualnym cvs) b¦dzie wówczas omini¦ty. 6.9 Obliczanie wyra»e« logicznych W przeciwie«stwie do j¦zyka C, obliczenie warto±ci logicznej wyra»e« : a lub b aib poprzedzone jest wyliczeniem warto±ci logicznej a i b, dopiero potem zostanie wykonana na nich operacja sumy czy iloczynu logicznego (Priorytety operatorów zamieszczono w rozdziale Programowanie). 105 Dodatek A Odpowiedzi do ¢wicze« z rozdziaªu 2 1. --> n = 5 // dla ustalenia warto\'sci n... --> A = 2*eye(n,n) - diag(ones(n-1,1),1) - diag(ones(n-1,1),-1) Szybszym sposobem jest u»ycie funkcji toeplitz : -->n=5; // pour fixer une valeur a n... -->toeplitz([2 -1 zeros(1,n-2)]) 2. Je»eli A jest macierz¡ diagonalne macierzy (n; n), diag(A) zwróci wektor kolumnowy zawieraj¡cy elementy A (a zatem otrzymamy wektor kolumnowy o wymiarze n). n, w której elementy tt diag(diag(A)) zwróci macierz kwadratow¡ diagonaln¡ o wymiarze diagonalne b¦d¡ takie jak w macierzy wyj±ciowej. 3. Oto jedna z mo»liwo±ci : --> A = rand(5,5) --> T = tril(A) - diag(diag(A)) + eye(A) 4.(a) --> Y = 2*X.^2 - 3*X + ones(X) --> Y = 2*X.^2 - 3*X + 1 // wyko\.zystuj\k{a}c zapis skrócony --> Y = 1 + X.*(-3 + 2*X) // oraz schemat Hornera (b) --> Y = abs(1 + X.*(-3 + 2*X)) (c) --> Y = (X - 1).*(X + 4) // wyko\.zystuj\k{a}c zapis skrócony (d) --> Y = ones(X)./(ones(X) + X.^2) --> Y = (1)./(1 + X.^2) // z skrótami 5. Oto skrypt : n = 101; // dyskretyzacja x = linspace(0,4*%pi,n); y = [1 , sin(x(2:n))./x(2:n)]; // aby zapobiec dzieleniu przez zero... plot(x,y,"x","y","y=sin(x)/x") 6. Mo»liwe rozwi¡zanie (dla ró»nych warto±ci n = 2000; x = rand(1,n); xbar = cumsum(x)./(1:n); 106 n) : plot(1:n, xbar, "n","xbar", ... "ilustracja lgn : xbar(n) -> 0.5 qd n -> + oo") 107 Dodatek B Rozwi¡zania ¢wicze« z rozdziaªu 3 1. Klasyczny algorytm wyko»ystu¡cy dwie p¦tle : function [x] = sol_tri_sup1(U,b) // // rozwi\k{a}zanie Ux = b gdzie U jest macierz\k{a} trójk\k{a}tn\k{a} górn\ // [n,m] = size(U) // kilka wyj\k{a}tków .... if n ~= m then error(' Macierz nie jest kwadratowa') end [p,q] = size(b) if p ~= m then error(' Wyraz wolny ma nieprawid\l{}owy wymiar') end // pocz\k{a}tek algorytmu x = zeros(b) // rezerwuje miejsce dla x for i = n:-1:1 suma = b(i,:) for j = i+1:n suma = suma - U(i,j)*x(j,:) end if U(i,i) ~= 0 then x(i,:) = suma/U(i,i) else error(' Macierz jest nieodwracalna') end end endfunction A oto wersja wykorzystuj¡ca pojedy«cz¡ p¦tl¦ function [x] = sol_tri_sup2(U,b) // // [n,m] = size(U) // niektóre wyj\k{a}tki .... if n ~= m then error(' Macierz nie jest kwadratowa') end 108 [p,q] = size(b) if p ~= m then error(' Wektor wyrazów wolnych ma z\l{}y wymiar) end // pocz\k{a}tek algorytmu x = zeros(b) // rezerwuje miejsce dla x for i = n:-1:1 suma = b(i,:) - U(i,i+1:n)*x(i+1:n,:) // zobacz komentarz ko\'ncowy if U(i,i) ~= 0 then x(i,:) = suma/U(i,i) else error(' Nie mo\.zna odwróci\'c macierzy') end end endfunction Komentarz : w pierwszej iteracji (dla i = n) macierze U(i,i+1:n) et x(i+1:n,:) s¡ puste. Odpowiadaj¡ one obiektom zdeniowanym w Scilabie (macierz pusta), które oznaczone s¡ przez []. 2. A = A + []. suma = b(n,:). Dodawanie macierzy pustej jest zdeniowane i daje : pierwszej iteracji mamy suma = b(n,:) + [] to znaczy Zatem w // // skrypt rozwiazujacy x" + alpha*x' + k*x = 0 // // Aby przeksztalcic rownanie do postaci ukladu rownan pierwszego rzedu // kladziemy : X(1,t) = x(t) i X(2,t) = x'(t) // // Otrzymujemy wowczas : X'(t) = A X(t) z : A = [0 1;-k -alpha] // k = 1; alpha = 0.1; T = 20; // moment koncowy n = 100; // dyskretyzacja czasowa : przedzial [0,T] zostanie // podzielony na n przedzialow t = linspace(0,T,n+1); // momenty czasowe : X(:,i) bedzie korespondowal z dt = T/n; // zmiana czasu A = [0 1;-k -alpha]; X = zeros(2,n+1); X(:,1) = [1;1]; // warunki poczatkowe M = expm(A*dt); // oblicza exponent A dt // obliczenia for i=2:n+1 X(:,i) = M*X(:,i-1); end // wyswitlenie rezultatów xset("window",0) xbasc() xselect() plot(t,X(1,:),'czas','pozycja','Courbe x(t)') xset("window",1) xbasc() xselect() 109 X(:,t( plot(X(1,:),X(2,:),'pozycja','predkosc','Trajektoria w przestrzeni stanow') 3. 4. function [i,info]=przedzial(t,x) // poszukuje dychotomii przedzialu i takiej, ze: x(i)<= t <= x(i+1) // jezeli t nie jest z przedzialu [x(1),x(n)] zwraca info = %f n=length(x) if t < x(1) | t > x(n) then info = %f i = 0 // kladziemy wartosc domyslna else info = %t i_dolne=1 i_gorne=n while i_gorne - i_dolne > 1 itest = floor((i_gorne + i_dolne)/2 ) if ( t >= x(itest) ) then, i_dolne= itest, else, i_gorne=itest, end end i=i_dolne end endfunction function [p]=myhorner(t,x,c) // rozwiniecie wielomianu c(1) + c(2)*(t-x(1)) + // algorytmem Hornera // t jest wektorem (lub macierza) momentów czasu n=length(c) p=c(n)*ones(t) for k=n-1:-1:1 p=c(k)+(t-x(k)).*p end endfunction c(3)*(t-x(1))*(t-x(2)) + ... 5. Rozwini¦cie w szereg Fouriera : function [y]=signal_fourier(t,T,cs) // // // // // ta funkcja zwraca T-okresowy sygnal t : wektor momentow dla których obliczmy sygnal y ( y(i) odpowiadaj\k{a}cy t(i) ) T : okres sygnalu cs : jest wektorem ktory wskazuje amplitude kazdej funkcji f(i,t,T) l=length(cs) y=zeros(t) for j=1:l y=y + cs(j)*f(j,t,T) end endfunction function [y]=f(i,t,T) // wielomiany trygonometryczne dla sygna\l{}u o okresie T : // jesli i jest parzyste : f(i)(t)=sin(2*pi*k*t/T) (z k=i/2) // jesli i jest nieparzyste : f(i)(t)=cos(2*pi*k*t/T) (z k=floor(i/2)) 110 // stad w szczególnosci f(1)(t)=1 jest traktowany ponizej // jako przypadek szczegolny i niezbyt wa\.zny // t jest wektorem mamentów czasowych if i==1 then y=ones(t) else k=floor(i/2) if modulo(i,2)==0 then y=sin(2*%pi*k*t/T) else y=cos(2*%pi*k*t/T) end end endfunction 6. Spotkanie : niech TA i TB b¦d¡ momentami przybycia Pana A i Pani B. S¡ to dwie zmi- U ([17; 18]) a spotkanie ma miejsce jezeli [TA ; TA + 1=6] [ [TB ; TB + 1=12] 6= ;. Doswiadczenie spotkania odpowiada realizacji zmienne losowej wektorowej R = (TA ; TB ) która, zgodnie z hipotezami, ma rozkªad zero-jedynkowy na kwadracie [17; 18] [17; 18]. Prawdopodobie«stwo spotkania wyznacza sie wi¦c w opar- enne losowe niezale»ne o rozkªadzie ciu o zale»no±¢ pomi¦dzy powie»chni¡ obszaru (odpowiadaj¡c¡ pojedynczemu spotkaniu) zdeniowan¡ jako: 8 < TA TB + 1=12 6 : TTB;T TA2 +[171;=18] A B oraz powie»chni¡ kwadratow¡ (1), przez co otrzymuje sie p = 67=288. Aby obliczy¢ to prawdopodobie«stwo, mo»na przyj¡¢ ze spotkanie powinno miec miejsce pomi¦dzy poªódniem a godzin¡ pierwsz¡. Poprzez symulacj¦ otrzymuje sie m do±wiadcze« a praw- dopodobie«stwo empiryczne jest liczb¡ przypadków w których spotkanie ma miejce podzielon¡ przez m. A oto rozwi¡zanie : function [p] = rdv(m) tA = rand(m,1) tB = rand(m,1) spotkanie = tA+1/6 > tB & tB+1/12 > tA; p = sum(bool2s(spotkanie))/m endfunction mo»na tak»e wyko»ysta¢ funkcje grand opisan¡ w rozdziale dotycz¡cym zastosowa« : function [p] = rdv(m) tA = grand(m,1,"unf",17,18) tB = grand(m,1,"unf",17,18) spotkanie = tA+1/6 > tB & tB+1/12 > tA; p = sum(bool2s(spotkanie))/m endfunction 111 Dodatek C Rozwi¡zania ¢wicze« z rozdziaªu 4 Czy to sprawka kostki? Je»eli przez J J ma przy zaªo»eniu, »e kostka jest symetryczna. W oznaczymy zmienn¡ losow¡ b¦d¡c¡ wynikiem do±wiadczenia, wówczas rozkªad geometryczny G (p ) gdzie p = 1 =6 ten sposób mo»emy okre±li¢ prawdopodobie«stwo poszczególnych zmiennych losowych jako (przymujemy q = 1 p = 5=6) : P (J = 1) = p; P (J = 2) = qp; P (J = 3) = q2 p; ::::; P (J = 10) = q9 p; P (J > 10) = q10 W drugiej cz¦±ci tabeli podano cz¦sto±¢ wyst¦powania poszczególnych zmiennych losowych, co w skrypcie zapiszemy nast¦puj¡co : occ= [36 ; 25 ; 26 ; 27 ; 12 ; 12 ; 8 ; 7 ; 8 ; 9 ; 30]; p = 1/6; q = 5/6; pr = [p*q.^(0:9) , q^10]'; y = sum( (occ - m*pr).^2 ./ (m*pr) ); y_progowy = cdfchi("X", 10, 0.95, 0.05); mprintf("\n\r Test dla :") mprintf("\n\r y = %g, et y_progowy (95 \%) = %g", y, y_progowy) mprintf("\n\r 200*min(pr) = %g", 200*min(pr)) Otrzmujemy y = 7:73915 gdy yseuil = 18:307, zatem kostka wydaje si¦ by¢ prawidªowa. 200 min(pr) ' 6:5 co jest znacznie poni»ej warunku pozwalaj¡cego Niemniej jednak mamy zastosowa¢ test (nale»aªoby wykona¢ jeszcze kilka dodatkowych do±wiadcze«). Urna Polya Funkcja scilaba function [XN, VN] = Urna_Polya_rownolegla(N,m) VN = ones(m,1) ; V_plus_R = 2 ; XN = 0.5*ones(m,1) for i=1:N u = grand(m,1,"de"f) // losowanie jednej kuli V_plus_R = V_plus_R + 1 // dodaje kule ind = find(u <= XN) // znajduje numer urny z której // wylosowano kule zielona VN(ind) = VN(ind) + 1 // zwiekszamy liczbe kul zielonych w tej urnie XN = VN / V_plus_R // aktualizujemy proporcje kul zielonych end endfunction Skrypt Scilaba // symulacja polya : 112 N = 10; m = 5000; [XN, VN] = Urna_Polya_rownolegla(N,m); // 1/ obliczenie wartosci oczekiwanej i przedzialu ufnosci EN = mean(XN); // wartosc oczekiwana empiryczna sigma = st_deviation(XN); // odchylenie standardowe empiryczne delta = 2*sigma/sqrt(m); // zaokraglenie dla przedzialu empirycznego (2 dla 1.9599..) mprintf("\n\r E teoretyczne = 0.5"); mprintf("\n\r E oszacowane = %g",EN); mprintf("\n\r Przedzial (empiryczny) ufnosci przy 95\% : [%g,%g]",EN-delta,EN+delta); // 2/ test chi2 alpha = 0.05; p = 1/(N+1); // prawdopodobienstwo kazdego wyniku (rozklad jednostajny) occ = zeros(N+1,1); for i=1:N+1 occ(i) = sum(bool2s(XN == i/(N+2))); end if sum(occ) ~= m then, error(" Problem..."), end // mala poprawka Y = sum( (occ - m*p).^2 / (m*p) ); Y_seuil = cdfchi("X",N,1-alpha,alpha); mprintf("\n\r Test chi 2 : ") mprintf("\n\r ----------- ") mprintf("\n\r wielkosc otrzymana w tescie : %g", Y); mprintf("\n\r wielkosc progowa : %g", Y_progowe); if (Y > Y_progowe) then mprintf("\n\r Wniosek : Hipoteza odrzucona !") else mprintf("\n\r Wniosek : Hipoteza nie odrzucona !") end // 3/ ilustracja graficzna function [d] = gestosc_chi2(X,N) d = X.^(N/2 - 1).*exp(-X/2)/(2^(N/2)*gamma(N/2)) endfunction czestosc = occ/m; ymax = max([czestosc ; p]); rect = [0 0 1 ymax*1.05]; xbasc(); xset("font",2,2) subplot(2,1,1) plot2d3((1:N+1)'/(N+2), czestosc, style=2 , ... frameflag=1, rect=rect, nax=[0 N+2 0 1]) plot2d((1:N+1)'/(N+2),p*ones(N+1,1), style=-2, strf="000") xtitle("Czestosci empiryczne (kreski pionowe) i prawdopodobienstwa teoretyczne (krzy\.zyk subplot(2,1,2) // rysujemy g\k{e}sto\'s\'c chi2 ???a N ddl X = linspace(0,1.1*max([Y_seuil Y]),50)'; D = densite_chi2(X,N); plot2d(X,D, style=1, leg="densite chi2", axesflag=2) // kreski pionowe dla Y plot2d3(Y, densite_chi2(Y,N), style=2, strf="000") xstring(Y,-0.01, "Y") // kreski pionowe dla Yseuil plot2d3(Y_seuil, densite_chi2(Y_seuil,N), style=5, strf="000") xstring(Y_seuil,-0.01, "Yseuil") xtitle("Pozycja Y w odniesieniu do warto\'sci Yseuil") Poni»ej przedstawiono rezultaty otrzymane dla E dok\l{}adne = 0.5 113 N = 10 et m = 5000 (patrz wykres (C.1)) : E oszacowane = 0.4959167 Przedzia\l{} ufno\'sci dla 95% : [0.4884901,0.5033433] Test du chi 2 : -------------warto\'s\'c otrzymana w te\'scie : 8.3176 warto\'s\'c progowa : 18.307038 Wniosek : Hipoteza nie odrzucona ! Rysunek C.1: Ilustracja dla testu 2 urny Polya... Most ?brownien? Funkcja function [X] = most_brownien(t,n) X = sum(bool2s(grand(n,1,"def") <= t) - t)/sqrt(n) endfunction Skrypt Skrypt ten wykonuje m symulacji zmiennej losowej Xn (t), przedstawia wykres funkcji rozkªadu n = +1) i empirycznego, nakªadaj¡c na niego wykres funkcji rozkªadu oczekiwanego (dla wreszcie oblicza test KS : t = 0.3; sigma = sqrt(t*(1-t)); // oczekiwane odchylenie standardowe n = 4000; // n "du\.ze" m = 2000; // licczba symulacji X = zeros(m,1); // zainicjowanie wektora realizacji for k=1:m X(k) = most_brownien(t,n); // p\k{e}tla licz\k{a}ca kolejne realizacje end // wykres funkcji rozk\l{}adu empirycznego X = - sort(-X); // tri prcum = (1:m)'/m; xbasc() plot2d2(X, prcum) x = linspace(min(X),max(X),60)'; // odci\k{e}te i [P,Q]=cdfnor("PQ",x,0*ones(x),sigma*ones(x)); // rz\k{e}dne dla funkcji dok\l{}adenj plot2d(x,P,style=2, strf="000") // rzutujemy je na wykres pocz\k{a}tkowy // zastosowanie testu KS alpha = 0.05; FX = cdfnor("PQ",X,0*ones(X),sigma*ones(X)); Dplus = max( (1:m)'/m - FX ); Dminus = max( FX - (0:m-1)'/m ); Km = sqrt(m)*max([Dplus ; Dminus]); K_progowe = sqrt(0.5*log(2/alpha)); // prezentacja wyników // mprintf("\n\r Test KS : ") mprintf("\n\r -------- ") 114 mprintf("\n\r warto\'s\'c mprintf("\n\r warto\'s\'c if (Km > K_progowe) then mprintf("\n\r Wniosek : else mprintf("\n\r Wniosek : end Oto rezultaty otrzymane dla otrzymana w te\'scie : %g", Km); progowa : %g",K_seuil); Hipoteza odrzycona !") Hipoteza nie odrzucona !") n = 1000 i m = 4000 : Test KS : -------warto\'s\'c otrzymana w te\'sci : 1.1204036 warto\'s\'c progowa : 1.2212382 Wniosek : Hipoteza nie odrzucona ! 115