Notatki z Matlaba Rafał Zduńczyk January 6, 2018 Lab 1: Macierze i indeksowanie Na początku dobrze zapisywać swoją pracę jako diary (dziennik): diary a p r i l s f o o l Teraz każda komenda i odpowiedź Matlaba będzie zapisana w aktualnym folderze Matlaba w pliku aprilsfool aż do użycia komendy diary o f f Zdefiniujmy zmienną b jako liczbę: b=4 Jak widać, symbol = jest używany jako operator przypisania. Zatem do porównywania obiektów będziemy używać czegoś innego. Zdefiniujmy c i d jako poziome wektory: c =[1 2 3 ], d=[4 5 6 ] Żeby podzielić każdy wyraz c przez b, piszemy c. / b Wynik jest wektorem. Pojedynczy symbol / (bez kropki) jest zarezerwowany dla dzielenia macierzowego, tj. mnożenia przez macierz odwrotną: 1 A=[1 2 3 ; 4 5 6 ; 7 8 9 ] ; 2 B=[2 1 4 ; 4 4 2 ; 2 1 2 ] ; 3 C1=A/B 4 C2=A. /B 5 C3=B\A 6 c /b 7 c. / b Zatem C1 jest iloczynem A przez odwrotność B, podczas gdy C2 jest wynikiem dzielenia po współrzędnych. C3 jest identyczne z C1, czasem może okazać się wygodne napisać najpierw dzielnik, a potem dzielną. Zauważmy, że kolumny oddzielane są spacjami lub przecinkami, zaś wiersze średnikami. Średnik ponadto jest używany na koniec komendy, wyniku której nie chcemy wyświetlać. Podobnie jak./ oraz / były, odpowiednio, dzieleniem po współrzędnych i macierzowym, tak samo są.*, *,.\, \,.^ oraz ^ operatory z kropkami działają po współrzędnych, a bez kropek macierzowo. Żeby zdefiniować skończony ciąg arytmetyczny piszemy [a:b:c], gdzie a jest pierwszym wyrazem, b różnicą (krokiem, skokiem), a c górnym ograniczeniem. Zauważmy, że c nie musi oznaczać ostatniego wyrazu, co widać na poniższym przykładzie [ 2 : 4 : 1 3 ] gdzie ostatni wyraz to oczywiście 10. Ostatnia odpowiedź Matlaba (przypisania są tu ignorowane) jest przechowywana jako (tymczasowa) zmienna ans, do której można się odwoływać jak do każdej innej zmiennej: Z podziękowaniami dla Julity, Karoliny oraz Sylwii 1
ans lub lub ans ( 1 ) ans ( 2 : 5 ) Oczywiście te komendy nie zadziałają jedna po drugiej: ans(1) zamienia ans na macierz 1 ˆ 1, więc ans(2:5) nie zadziała. Odwołanie do pojedynczego wyrazu (lub większego obszaru) dwuwymiarowej macierzy wymaga nawiasu okrągłego, indeksy oddziela sie przecinkiem i obowiązuje zasada wiersze pierwsze. Zatem, A(2,4) to odwołanie do drugiego wiersza, czwartej kolumny. Żeby w odwołaniu pojawił się zakres indeksów, używa się dwukropka, a end odwołuje się do ostatniego możliwego indeksu. A(2:4,3) odwołuje się do trzeciej kolumny, wiersze 2 4, a więc jest to pionowy wektor 3 ˆ 1. A(4,:) odwołuje się do całego czwartego wiersza. A(end-1,end-1) odwołuje się do wyrazu w przedostatnim wierszu i przedostatniej kolumnie. A(1:2:end,1) wybiera co drugi wyraz z pierwszej kolumny. Tej samej struktury używa się do modyfikacji macierzy: A(4,3)=1 zmienia wybrany wyraz na 1. A(end+1,:)=0 dodaje wiersz złożony z samych zer. A(:,1)=[] odrzuca pierwszą kolumnę. Lab 2: Wbudowane funkcje Żeby zmierzyć rozmiar wektora v (poziomej macierzy 1 ˆ n) używa się funkcji length(v), a dla macierzy o większej liczbie wymiarów jest dostępna funkcja size. size(a) zwraca wektor, którego pierwszy wyraz to liczba wierszy, drugi liczba kolumn itd., gdyż macierze mogą mieć więcej niż dwa wymiary. size(a,1) zwraca samą liczbę wierszy. Nie można użyć size(a)(1) w tym celu. Matlab nie obsługuje komend zawierających ciąg )(. Prowadziłoby to do niejednoznaczności typu: size(a)(1) czy size(1)(a)? Konstruując macierze o zadanych własnościach można korzystać z nastepujących funkcji eye(7) macierz jednostkowa 7 ˆ 7. ones(3,4) macierz 3 ˆ 4 złożona z samych jedynek. ones(3) macierz 3 ˆ 3 złożona z samych jedynek. ones(size(a)) macierz tego samego rozmiaru, co A, złożona z samych jedynek. ones(size(a,1),1) jednokolumnowa macierz, która ma tyle wierszy, co A, której każdy wyraz to 1. zeros(5,4) macierz złożona z samych zer. diag(a) zwraca pionowy wektor złożony z wyrazów z przekątnej A, tj. A(n,n) nawet, gdy A nie jest kwadratowa. diag(v) zwraca kwadratową macierz z wektorem v na przekątnej i zerami poza. diag(v,n) zwraca macierz z wektorem v położonym n wierszy nad przekątną i zerami poza. flip(a) odwraca A do góry nogami, a poziomy wektor od końca do początku. Ogólnie, odwraca macierz wzdłuż pierwszego wymiaru nie równego jeden. 2
sum(a) sumuje wyrazy w każdej kolumnie, zwracając poziomy wektor. Jeśli A już jest poziomym wektorem zwyczajnie sumuje wszystkie wyrazy, zwracając jedną liczbę. Żeby sumować wzdluż określonego wymiaru, trzeba go podać po przecinku, np. sum(a,2). Symbol (apostrof) oznaca transpozycję, czyli zamianę wierszy i kolumn macierzy prostokątnej: A, [ 1 : 3 : 2 0 ] Zatem, żeby otrzymać tabliczkę mnożenia wystarczy napisać [ 1 : 1 0 ] [ 1 : 1 0 ] Jest w Matlabie funkcja zwracająca losowe liczby całkowite: randi(m,n), zwraca kwadratową macierz n ˆ n z liczbami z przedziału od 1 do m. Macierz prostokątną otrzymać można wstawiając [j,k] w miejsce m. Ogólniej, randi([a,b],[c,d]) daje macierz c ˆ d z liczbami całkowitymi z przedziału ta,..., bu. reshape(a,r,c) zmienia rozmiar macierzy A na r ˆ c jeśli to możliwe. Zachowany jest następujący porządek wyrazów: ÓÓÓ Lab 3: Skrypty i funkcje użytkownika Zamiast wpisywać komendy bezpośrednio w wierszu poleceń, można tworzyć skrypty i funkcje. stworzyć funkcję wybieramy Home ÞÑ New ÞÑ Function. Oto przykład funkcji 1 function x=area1 ( a, b, c ) 2 s =2.\( a+b+c ) ; 3 x=sqrt ( s ( s a ) ( s b ) ( s c ) ) ; 4 end Żeby Ważne elementy skoro w nagłówku została wybrana zmienna x, gdzieś w funkcji musi być przypisanie x= wszystkie wiersze kończą się średnikami. Nie chcemy by przypisania s= lub x= wyskakiwały w wierszu poleceń funkcje widzą tylko te zmienne, które są im przekazywane. Nazwy zmiennych nie mają znaczenia tylko porządek się liczy. W tym przypadku: 1 a=3; 2 b=4; 3 c =5; 4 d=12; 5 f =13; 6 area1 ( c, d, f ) zmienne a i b nie zostają przekazane funkcji. Lab 4: Pętle & czas W programowaniu możemy wyróżnić dwie podstawowe pętle: pętla iteracyjna, kiedy z góry wiadomo, ile przebiegów ma być wykonanych pętla repetycyjna, kiedy każde wykonanie bloku instrukcji może, ale nie musi wpływać na wynik logicznego testu, który decyduje, czy kolejne powtórzenia będą wykonywane. Różnice między powyższymi typami ilustrują poniższe zadania Znajdź wszystkie liczby pierwsze z przedziału t2, 3,..., 1000u. Znajdź pierwsze 200 liczb pierwszych. 3
Oczywiście wiemy, że w pierwszym przypadku powinniśmy sprawdzić 998 liczb, zaś w drugim trudno przewidzieć, ile dokładnie liczb trzeba przetestować. Użyjmy nastepującego kryterium pierwszości: 1 function x=i s p r i m e 1 ( n ) 2 x=1; 3 for j =2: sqrt ( n ) 4 i f mod(n, j )==0 5 x=0; 6 break 7 end 8 end 9 end Teraz zadanie przesiania liczb ď 1000 możemy rozwiązać w sposób następujący. 1 p = [ ] ; 2 for n =2:1000 3 i f i s p r i m e 1 ( n ) 4 p=[p n ] ; 5 end 6 end Zaś żeby znaleźć pierwsze 200 liczb pierwszych, użyjemy pętli while : 1 p1 = [ ] ; 2 n=2; 3 while size ( p1,1)~=200 4 i f i s p r i m e ( n ) 5 p1=[p1 n ] ; 6 end 7 n=n+1; 8 end Żeby zmierzyć, ile czasu Matlab potrzebuje na wynokanie sekwencji komend, możemy dodać tic na początku oraz t=toc; na końcu. Wtedy zmienna t (oczywiście można użyć dowolnej litery) przechowa czas działania bloku instrucji między tic oraz toc. Lab 5: Interakcje z Excelem i plikami tekstowymi By wysłać macierz do pliku Excela można użyć poniższej składni. xlswrite( plik.xlsx,macierz) umieszcza macierz w pierwszym wolnym arkuszu danego pliku zaczynając od komórki A1. Plik trzeba podać z rozszrzeniem (tu.xlsx ), nazwa nie może zawierać spacji, przecinków, procentów, daszków, skrzatów itp. Jeśli plik o podanej nazwie nie istnieje, zostanie utworzony. Wszystkie dane z obszaru potrzebnego na macierz A zostaną utracone. xlswrite( plik.xlsx,macierz,akrusz) nazwa arkusza powinna być otoczona apostrofami i nie zawierać znaków specjalnych. Jeśli akrusz nie istnieje, zostanie utworzony. xlswrite( plik.xlsx,nazwa,akrusz,komórka) adres początkowej komórki powinien być otoczony apostrofami. Dane z pliku Excela importuje się funkcją xlsread o następującej składni A=xlsread( plik.xlsx,arkusz,komórki) gdzie jak poprzednio, arkusz i komórki to opcjonalne argumenty. Jeśli nie poda się komórek, będą odczytane wszystkie dane z arkusza. Przed odczytem trzeba zapisać i zamknąć plik. Do plików tekstowych używa się poleceń dlmread oraz dlmwrite, gdzie dlm oznacza delimiters (ograniczniki) separatory wierszy/kolumn. Przy zapisie do pliku można użyć ustawień delimiter oraz newline np. tak: dlmwrite(plik,macierz, delimiter,,, newline, ps ). Co więcej, można użyć trybu -append, by uniknąć utraty danych z pliku, tj. zacząć zapis od znacznika end of file (koniec pliku). 4
Lab 6: Logiczne indeksowanie 1 A>0 zwraca logiczną macierz rozmiaru macierzy A z jedynkami tam, gdzie wyrazy A są dodatnie i zerami wszędzie indziej. A(A>0) to pionowy wektor składający sie z dodatnich wyrazów macierzy A. W nawiasie okrągłym można umieścić dowolny logiczny test, np. zawierajcy przeczenie (tylda ~), alternatywę (operator ) lub koniunkcję (operator &). Czasem może być wygodniej zobaczyć indeksy jawnie. Służy temu funkcja find: 1 a = [ 5 : 2 : 9 ] ; 2 f i n d ( a>0) Odpowiedź to r4 5 6 7 8s lista indeksów, dla których wyrazy a są dodatnie. Majac do czynienia z macierzą prostokątną jak b=randi([-1,2],[3,4]) można napisać find(b>0) i otrzymać listę pojedynczych indeksów, jak gdyby b było pionowym wektorem, albo napisać [r,c]=find(b>0) i dostać podwójną listę złożoną z wierszy i kolumn odpowiadającym szukanym wartościom. Lab 7: Liczby losowe i podstawowa statystyka MatLab używa generatora liczb pseudolosowych, który nie jest dokładnie tym samym co geneator liczb losowych. Ten drugi w uproszeczeniu odczytuje ułamek sekundy aktualnego czasu i zwraca go w zapisie dziesiętnym (zakładamy, że użytkownik ani komputer nie mają wpływu na tysięczną część sekundy aktualną w momencie wykonania danej komendy, więc możemy tę i kolejne cyfry uznać za losowe), podczas gdy generator liczb pseudolosowych używa w pełni deterministycznego algorytmu. Oznacza to tyle, że np. jeśli każdego dnia będziemy pracę z MatLabem zaczynać od randi(10,1), zawsze dostaniemy ten sam wynik. Algorytm ten używa tzw. nasionka (seed). Można je chwilowo (na czas działania jednej komendy) przesadzić, pisząc np. rng(665) (można tam użyć dowolnej liczby). Można też zresetować algorytm pisząc rng shuffle. Ma to wpływ na następujące funkcje randi rand(size) zwracającą liczby pseudolosowe z przedziału r0, 1q randperm(n) zwracającą pseudolosową permutację t1,..., nu randperm(n,k) zwracającą k liczb z permutacji zbioru t1,..., nu Żeby zobaczyć wszystkie permutacje wyrazów danego wektora, użyj funkcji perms(v), zaś dla kombinacji (rozmiaru k) użyj nchoosek(v,k) (n po k współczynnik dwumianowy Newtona). Jest dokładnie nchoosek(length(v),k) takich kombinacji. 5