WYKŁAD 16 i 17 Podstawy programowania w języku MATLAB Patrz przykłady zamieszczone na tej stronie: prog1.m... prog7.m oraz cw_0.m... cw_12.m Tomasz Zieliński
KOMPILATOR vs. INTERPRETER (przypomnienie) C/C++ = kompilatory tłumaczą od razu cały program na kod maszynowy potem dopiero program jest wykonywany stosowane kiedy jest już znany algorytm rozwiązania Basic = interpretery Matlab tłumaczona i wykonywana jest linia po linii programu stosowane kiedy jest poszukiwany algorytm rozwiązania Kompilator Interpreter Zalety Szybkie działanie programu Możliwość optymalizacji kodu programu, np. minimalizacji potrzebnej pamięci Krótka droga do pomysłu do jego weryfikacji Wady Długa droga do pomysłu do jego weryfikacji Wolne działanie programu
PRACA NAD PROGRAMEM: kompilator vs. interpreter f1.obj, f2.obj,... statyczne (lib) i dynamiczne (dll) dołączanie bibliotek system.lib Lib Maker Konsolidator my.lib system.dll my.dll wykonanie całego programu Edytor tekstu KOMPILATOR programu Linker System operacyjny prog.c prog.obj prog.exe INTERPRETER to oddzielny program / aplikacja 1 2 Edytor linii Program czyli zbiór linii 1 2 INTERPRETER Interpreter linii >>...?... (CR) Egzekutor linii
SZYBKOŚĆ PISANIA vs. SZYBKOŚĆ DZIAŁANIA czas napisania i uruchamiania (usunięcia błędów) programu czas wykonania programu Asembler Język C/C++ Matlab Simulink WNIOSEK: kiedy poszukuję rozwiązania problemu, wybieram język wysokiego poziomu, nawet graficzny, z dużą liczbą bibliotek (szybko piszę program, który wolno działa) kiedy znam rozwiązanie problemu wybieram język niskiego poziomu (wolno piszę program, który szybko działa)
ZALETY MATLABA: 1) Obliczenia numeryczne (inżynierskie): zapis wektorowo-macierzowy: A*x = b, x = inv(a)*b, C = A*B olbrzymia, wiarygodna biblioteka funkcji matematycznych: algebra liniowa, całkowanie, różniczkowanie, optymalizacja,... kompromis pomiędzy prostotą, dokładnością, szybkością 2) Zaawansowana wizualizacja 2D/3D danych, prosta w użyciu. 3) Biblioteki specjalistyczne (toolboxes) pisane przez ekspertów światowych z zakresu elektroniki, telekomunikacji, automatyki,... 4) Simulink, Stateflow, SimEvent, SimPower, Link to ModelSim (VHDL, FPGA, ASIC) - okienkowo-zorientowane środowiska graficzne do uruchamiania algorytmów na podstawie ich schematów blokowych, wyposażone w liczne biblioteki (blocksets). 5) Otwarta architektura: m-zbiory dostępne w kodzie źródłowym łatwość dołączania swoich funkcji mnogość interfejsów do różnych typów danych (wav, avi, DICOM,...) 6) C-maker, Real-Time Workshop, procesory DSP (TI Composer Studio)
Z języka C do Matlaba (1) Zbiór dyskowy: prog1.m %-------------------------------------------------------------------------------------------- % Program prog1: budżet rodziny osoby = 3; kasa = 1500.45; moje = kasa/osoby, % liczba osób % łączny przychód % moje kieszonkowe disp('moje kieszonkowe = '), disp(moje), % display %-------------------------------------------------------------------------------------------- Uwagi: 1) Brak jest specjalnych słów początku i końca programu. Program jest zbiorem linii zapisanych w osobnym zbiorze na dysku o rozszerzeniu *.m 2) Brak deklaracji zmiennych. Wszystkie są typu double. 3) % stanowi znak początku komentarza (za nim do końca linii). 4) Znak ; informuje, żeby nie wyświetlać wyniku operacji. 5) Znak... na końcu linii informuje, że następna linia jest kontynuacją bieżącej. 6) Instrukcja disp() służy do wyświetlania tekstu lub wartości zmiennej. Zbiór dyskowy: prog2.m %-------------------------------------------------------------------------------------------- % Program prog2: budżet rodziny osoby = 3; % liczba osób kasa = input('ile do podziału? '); % komunikat, czytaj z klawiatury moje = kasa/osoby, % oblicz, pokaż wynik gdyż brak ; %-------------------------------------------------------------------------------------------- Uwagi: 1) W instrukcji input po wyświetleniu na ekranie tekstu ile do podziału? jest wczytywana liczba z klawiatury, której wartość jest podstawiana do zmiennej kasa.
Z języka C do Matlaba (2) Zbiór dyskowy: prog3.m %----------------------------------------------------------------------------------------- osoby = 3; kasa = input('ile do podziału? '); moje = wzor3( kasa, osoby ), % wywołanie funkcji wzor3() %---------------------------------------------------------------------------------------- Zbiór dyskowy: wzor3.m %---------------------------------------------------------------------------------------- function kieszen = wzor3( forsa, osoby ) % Moja funkcja, licząca kieszonkowe % Wejście: forsa - budzet rodzinny % Wyjście: kieszen - moje kieszonkowe kieszen = forsa/osoby; % wyjście = funkcja wejścia %---------------------------------------------------------------------------------------- Uwagi: 1) Każda funkcja jest osobnym plikiem na dysku. Od programu różni się tym, że rozpoczyna ją słowo function. 2) Przykładowa budowa: function [ x, y, z ] = zróbcoś( a, b, c) % komentarz co funkcja robi, wyświetlany podczas help zróbcoś x = a + b; % wyraź parametry wyjściowe {x, y, z} y = a - b; % poprzez parametry wejściowe {a, b, c} z = c; % czyli {x, y, z } = funkcja( a, b, c)
Z języka C do Matlaba (3) Zbiór dyskowy: prog4.m %----------------------------------------------------------------------------------------- clear all; % wyzeruj wszystkie zmienne global osoby; % deklaracja zmiennej globalnej, % dostępnej także w funkcjach osoby = 3; % ustaw liczbę osób kasa = input(' ile do podziału? '); % wczytaj wartość budżetu moje = wzor4( kasa ), % oblicz moje kieszonkowe %----------------------------------------------------------------------------------------- Zbiór dyskowy: wzor4.m %----------------------------------------------------------------------------------------- function kieszen = wzor4( forsa ) global osoby kieszen = forsa/osoby; %----------------------------------------------------------------------------------------- Uwagi: 1) Aby wartość zmiennej była dostępna w także w funkcji, zmienna ta musi być zadeklarowana jako global (w programie i w funkcji)
Z języka C do Matlaba (4) Zbiór dyskowy: prog5.m %------------------------------------------------------------------------------------------- clear all; % wyzeruj wszystkie zmienne global osoby; % deklaracja zmiennej globalnej osoby = 3; % ustaw liczbę osób kasa = input('ile do podziału? '); % wczytaj wartość budżetu [tata, mama, ja] = wzor5( kasa ), % kilka zwracanych wartości %------------------------------------------------------------------------------------------- Zbiór dyskowy: wzor5.m %------------------------------------------------------------------------------------------- function [osoba1, osoba2, osoba3] = wzor5( forsa ) % Moja funkcja, licząca kieszonkowe % Wejście: forsa - budżet rodzinny % Wyjście: osoba1, osoba2, osoba3 - kieszonkowe trzech osób global osoby srednia = forsa/osoby; osoba1 = 1.25 * srednia; osoba2 = 1.00 * srednia; osoba3 = 0.75 * srednia; %-------------------------------------------------------------------------------------- Uwagi: 1) W tym przypadku obliczamy w funkcji kieszonkowe dla wszystkich członków rodziny, które zwracamy do programu głównego.
Z języka C do Matlaba (5) Zbiór dyskowy: prog6.m %------------------------------------------------------------------------------------------- clear all; % wyzeruj wszystkie zmienne global osoby; % zadeklaruj zmienną globalną osoby imiona = [ 'tata'; 'mama'; 'ja ' ]; osoby = 3; kasa = input('ile do podziału? '); rodzina = wzor6( kasa ), % imiona członków rodziny % liczb osób % wczytaj budżet, wstaw do kasy % funkcja teraz zwraca tablicę disp('tata = '); disp( rodzina(1) ); % kieszonkowe taty disp('mama = '); disp( rodzina(2) ); % kieszonkowe mamy disp('ja = '); disp( rodzina(3) ); % kieszonkowe moje for i = 1 : osoby % pętla for-end: wyświetlanie % if( i == 2) break; end % break to wyjście z pętli for disp( ['osoba nr ' num2str(i) ',czyli ' imiona(i,:) ' = ' num2str(rodzina(i))]); end if( rodzina(2) > rodzina(3) ) % warunek logiczny if-else-end disp('mama ma więcej niż ja!'); else disp('mam co najmniej tyle co mama'); end while( rodzina(1) > rodzina(2) ) % pętla while-end; break ją kończy disp('tata ma więcej od mamy'); break; end plot( 1:osoby, rodzina, 'b*--'); % rysunek (x, y) xlabel( 'nr czlonka rodziny' ); % opis osi x ylabel( 'kieszonkowe [PLN]' ); % opis osi y title( 'BUDŻET RODZINNY' ); % tytuł % pauza %-------------------------------------------------------------------------------------------
Z języka C do Matlaba (6) Zbiór dyskowy: wzor6.m %------------------------------------------------------------------------------------------- function czlonkowie = wzor6( forsa ) % Moja funkcja, licząca kieszonkowe % Wejście: forsa - budżet rodzinny % Wyjście: czlonkowie[] - kieszonkowe członków rodziny global osoby srednia = forsa/osoby; czlonkowie( 1 ) = 1.25 * srednia; czlonkowie( 2 ) = 1.00 * srednia; czlonkowie( 3 ) = 0.75 * srednia; %------------------------------------------------------------------------------------------- Zbiór dyskowy: prog7.m %------------------------------------------------------------------------------------------- load rodzina.dat % wczytaj ze zbioru rodzina.dat dwie liczby kasa = rodzina(1); % podstaw pierwszą z nich do zmiennej kasa osoby = rodzina(2); % a drugą - do zmiennej osoby moje = kasa/osoby, % oblicz moje kieszonkowe save kieszonkowe.dat moje /ascii % zapisz je do zbioru % kieszonkowe.dat %------------------------------------------------------------------------------------------- Zbiór dyskowy: rodzina.dat %------------------------------------------------------------------------------------------- 1500.45 3 %------------------------------------------------------------------------------------------- Zbiór dyskowy: kieszonkowe.dat %------------------------------------------------------------------------------------------- 5.0015000e+002 %-------------------------------------------------------------------------------------------
» Cw_0_demo <ENTER> Macierze w Matlabie (1) A = [ 1 2 3; 4 5 6; 7 8 0 ] % definicja macierzy A 3 x3 % wydruk, gdyż brak na końcu A = 1 2 3 % średnika 4 5 6 7 8 0 B = A' % 1) transpozycja i sprzężenie zespolone % elementów macierzy B = 1 4 7 % 2) dla macierzy o elementach rzeczywistych 2 5 8 % tylko sprzężenie 3 6 0 % 3) jeśli. to tylko transpozycja C = A + B % suma dwóch macierzy C = 2 6 10 % 10 = 3 + 7 6 10 14 10 14 0 C = A * B % mnożenie dwóch macierzy C = 14 32 23 % 14 = 1*1 + 2*2 + 3*3 32 77 68 % 32 = 4*1 + 5*2 + 6*3 23 68 113 % 23 = 7*1 + 8*2 + 0*3 inv(a) ans = -1.7778 0.8889-0.1111 1.5556-0.7778 0.2222-0.1111 0.2222-0.1111 % macierz odwrotna det(a) % wyznacznik macierzy ans = 27 rank(a) % rząd macierzy ans = 3 cond(a) % uwarunkowanie macierzy ans = 35.1059 % (max sv) / (min sv )
Macierze w Matlabie (2) eig(a) % wartości własne ans = -0.3884 12.1229-5.7345 [v,d] = eig(a) v = 0.7471-0.2998-0.2763-0.6582-0.7075-0.3884 0.0931-0.6400 0.8791 % wektory i wartości własne d = -0.3884 0 0 0 12.1229 0 0 0-5.7345 svd(a) ans = 13.2015 5.4388 0.3760 % wartości osobliwe expm(a) % eksponenta macierzy ans = 1.0e+004 * 3.1591 3.9741 2.7487 7.4540 9.3775 6.4858 6.7431 8.4830 5.8672 p = poly(a) % wielomian charakterystyczny p = 1.0000-6.0000-72.0000-27.0000 roots(p) ans = 12.1229-5.7345-0.3884 % pierwiastki tego wielomianu % czyli wartości własne macierzy A
Wektory w Matlabie x = [ 1 2 3 ] % definicja wektora poziomego x = 1 2 3 % y = [ 4; 5; 6 ] % definicja wektora pionowego y = 4 % 5 % 6 % x * y % iloczyn skalarny ans = 32 % 1*4 + 2*5 + 3*6 y * x % iloczyn wektorowy ans = 4 8 12 % 4 * [ 1 2 3 ] 5 10 15 % 5 * [ 1 2 3 ] 6 12 18 % 6 * [ 1 2 3 ] x.* y' % iloczyn odpowiadających sobie ans = 4 10 18 % elementów: [ 1*4, 2*5, 3*6 ] x + y' % suma odpowiadających sobie ans = 5 7 9 % elementów: [ 1+4, 2+5, 3+6 ]
Laboratorium w Matlabie (1) % W wyniku pomiaru otrzymano następujące liczby : % ( x = numer pomiaru, y = wartość ) x = [ 1 2 3 4 5 6 7 8 9 10 ]; y = [ 0.912 0.945 0.978 0.997 1.013 1.035 1.057 1.062 1.082 1.097 ]; % W celu lepszej obserwacji przedstawiamy je na rysunku : plot( x, y, b* ) ; % wykres y = funkcja(x), niebieskie * title( 'DANE POMIAROWE' ); % tytuł xlabel( 'numer probki' ); % podpis pod osią x xlabel( 'wartosc' ); % podpis pod osią y grid; % siatka 1.15 DANE POMIAROWE 1.1 1.05 wartosc 1 0.95 0.9 1 2 3 4 5 6 7 8 9 10 numer probki clf % naciśnij jakiś klawisz % wyzeruj rysunek
Laboratorium w Matlabie (2) % Interesuje nas wartość średnia tych liczb % oraz ich rozrzut wokół wyliczonej wartości średniej : srednia = mean( y ) % srednia = sum( y ) / length( y ) % srednia = % ponieważ brak średnika % powyżej, 1.0178 % jest wyświetlany wynik rozrzut = std( y ) % rozrzut =... %... sqrt( sum( ( y - srednia ).^2 ) / length( y ) ) rozrzut = % ponieważ brak jest średnika % powyżej, 0.0603 % to jest wyświetlany wynik % Dodatkowo chcielibyśmy wyznaczyć współczynniki a i b linii prostej % y = a * x + b % najlepiej aproksymującej otrzymane dane (prosta regresji liniowej). xm = mean( x ); ym = mean( y ); xr = x - xm; yr = y - ym; % średnia wartość wektora x % średnia wartość wektora y % wektor x - średnia x (od każdego elementu) % wektor y - średnia y (od każdego elementu) a = (xr * yr') / (xr * xr') % obliczenie wsp a prostej, to samo % inaczej: a = sum( xr.* yr ) / sum( xr.* xr ) a = 0.0197 b = ym - a * xm b = 0.9096 % N ( ) ( ) n= 1, x n= 1 N n= 1 x( n) x * y( n) y x( n) a = = ( xn ( ) x) *( xn ( ) x) % obliczenie wsp b prostej N N
Laboratorium w Matlabie (3) % Teraz porównamy punkty eksperymentalne z linią regresji liniowej plot( x, y, 'bx', x, a*x+b, 'k-' ) title( 'DANE POMIAROWE' ) xlabel( 'numer próbki' ) ylabel( 'wartość' ) grid % niebieskie krzyżyki, linia czarna % tytuł % podpis pod osią x % podpis pod osią y % siatka 1.15 DANE POMIAROWE I PROSTA REGRESJI LINIOWEJ 1.1 1.05 wartosc 1 0.95 0.9 1 2 3 4 5 6 7 8 9 10 numer probki clf echo off % naciśnij cokolwiek % wyzeruj rysunek % nie wyświetlaj komend na monitorze
MATLAB - skrót 1) - przewijanie ostatnich linii w linii komend >>... 2) % - znak komentarza, za nim do końca linii 3)... - znak kontynuacji w następnej linii 4) brak ; na końcu instrukcji oznacza polecenia wyświetlenia wyniku operacji 5) help instrukcja - funkcja pomocy help: jak się używa instrukcji? 6)! - znak wywołania programu zewnętrznego wewnątrz Matlaba!edit prog.m - uruchomienie zewnętrznego edytora i wczytanie prog.m 7) zerowanie: clear all - zawartości wszystkich zmiennych (np. na początku prog) clc - okna komend clf - okien graficznych z rysunkami 8) format - dokładność wydruku wyniku obliczeń format short 1.3333 short e 1.3333*E+000 long 1.33333333333338 long e 1.33333333333338 * E+000 9) Stałe predefiniowane - pi = 3.14159..., eps = 2.22*10^(-16) (dokładność) i, j = sqrt(-1) 10) Inicjalizacja: liczby rzeczywiste: n = 1; m = 10; a = 1.2345; b = 1.2*10^(-6); liczby zespolone: z = 3 + 4*i; z = 3 + 4*j; (dla macierzy: Z = A + B*i lub Z = A + B*i) wektory poziome: x = [ 1.2 3.4 5.6 ]; y = 0. : 0.1 : 0.4; otrzymujemy: od krok do 0., 0.1, 0.2, 0.3, 0.4 z = rand(1, 5); wektor 1x5 wartości losowych z = sin( 0 : pi/2 : 2*pi ); 0, 1, 0, -1, 0 z = sin( x ); z = x(1 : 2); wektor 1x3 wartości sin dla x % podwektor, pobranie wybranych elementów od-do otrzymujemy: [ 1.2 3.4 ] wektory pionowe: y = [ 1.2; 3.4; 5.6 ]; otrzymujemy: y = [ 1.2 3.4 znak nowego wiersza 5.6 ] macierze: A = [ 1 2 3; 4 5 6; 7 8 9 ]; otrzymujemy: A = [ 1 2 3 4 5 6 7 8 9 ]
B = rand(5,5); % macierz liczb losowych o wymiarach 5 x 5 C = eye(10); % macierz diagonalna o wymiarach 10 x 10 D = A(1 : 2, 2 : 3); % podmacierz A, otrzymujemy [ 2 3; 5 6] B = A ; % transpozycja, sprzężenie elementów 11) whos - lista zmiennych w pamięci, ich wymiary 12) Operatory arytmetyczne są domyślnie wektorowo-macierzowe. Jeśli chcemy działać na elementach wektorów/macierzy, to operator poprzedzamy kropką, np..* +, -, *, \ (lewe dzielenie), / (prawe), ^(potęga), liczby: c = a op b, gdzie op = +, -, *, /, ^ wektory: z = x op y, gdzie op = +, -, *, /,.*,./ macierze: C = A op B, gdzie op = +, -, *, /, \,.*,./ X = A\B takie, że A*X=B X = A/B takie, że X*B=A; np. x = [ 1 2 3 ]; y = [ 4 5 6 ]; x + y = [ 5 7 9 ] y - x = [ 3 3 3 ] x * y = 1*4 + 2*5 + 3*6 = 32 x * y = [ 4 5 6 8 10 12 12 15 18 ] x.* y = [ 4 10 18 ] x.\ y = [ 4 2.5 2 ] x.^ y = [ 1 32 739 ] x./ y = [ 0.25 0.4 0.5 ] x.^2 = [ 1 4 9 ] x / y = 0.4156 13) Operatory logiczne: <, <=, >, >=, ==, ~=, & (AND), (OR, ~ (NOT) np. if( (a > b) & ( c ~= d) ) i = 0; x=y; while( i <= 10 ) end i = i+1; end 14) Zapisywanie zmiennych na dysk i ich odczytywanie (save, load): save temp X Y Z; % X, Y, Z temp.mat (zbiór binarny Matlaba) load temp % inicjalizacja X, Y, Z xy = [x y ]; save temp.dat xy /ascii load temp.dat x = temp(:,1); y = temp(:,2); % złóż wektory w macierz dwu-kolumnową % zapisz zmienną xy do zbioru ASCII temp.dat % wczytaj dane ze zbioru temp.dat % x = pierwsza kolumna macierzy temp % y = druga kolumna macierzy temp
15) Przykłady funkcji matematycznych (użyj help funkcja, aby szczegóły): sqrt(), log2(), log10(), log()=ln(), exp(), sin(), cos(), tan(), atan(), atan2() - jeśli na macierzach, to na ich elementach mean(), std(), min(), max(), median(), sort(), prod(), cumsum(), cumprod() - jeśli na macierzach, to w kolumnach expm(a), logm(a), sqrtm(a) - na całych macierzach poly(a), det(a), trace(a), kron(a), eig(a), svd(a) diff(), hist(), corrcoef(), cov(), cplxpair() abs(), angle(), conv(), deconv(), xcorr(), fft(), ifft(), fftshift(), spectrum(), psd(), filter() 16) Przykłady funkcji graficznych (użyj help funkcja, aby szczegóły): 2D: plot(x,y), loglog(x,y), semilog(x,y), polar(x,y), stem(x,y), bar(x,y), stairs(x,y) kolory: r, g, b, k, w, i (red, green, blue, black, white, invisible) linie: - / -- / -. / : (ciągła, przerywana, kreska-kropka, kropkowana) symbole: +, *, x, o np. plot(x1, y1, ro, x2, y2, b--, x3, y3, k: 3D: mesh(a), meshc(a), meshz(a), contour(a), surf(a), surfl(a), waterfall(a), image(a), imagesc(a) ogólne: title(), xlabel(), ylabel(), text(), axis(),subplot(), hold, grid; 17) Instrukcje sterujące (pozostałe to:, break, error, return): for-end for m = 1 : M for n = 1 : N A(m, n) = 1 / (m+n-1); end end while-end if-elseif-else-end n=1; while( prod(n) < 1*E+100) n=n+1; end if( x==1 ) a=b; elseif( y<5 ) c=d; else e=f; end 18) Funkcje program.m ---------------------------------------------- a1 = 10; a2 = 20; a3 = 30; [ b1, b2, b3 ] = funkcja( a1, a2, a3); ---------------------------------------------- funkcja.m ---------------------------------------------- function [x, y, z] = funkcja( a, b, c) % co robi ta funkcja? x = a + b; y = b - c; z = b * c;
DODATKOWE PRZYKŁADY W JĘZYKU MATLAB
% PRZYKLAD 1 % Inicjalizacja danych, zapis i odczyt z dysku, rysunek % Zapisywanie danych na dysk i ich odczytywanie z dysku x = [ 1 2 3 4 5 ]; % pierwszy wektor y = [ 0.1 0.2 0.3 0.2 0.1 ]; % drugi wektor x = x'; y = y'; % odwrócenie obu wektorów do pionu plot(x, y, 'b' ) title('y=f(x)') xy = [ x y ]; save wy.dat xy /ascii load wy.dat x1 = wy(:,1); y1 = wy(:,2); plot( x, y, 'b', x1, y1, 'r') title('y=f(x) oraz y1=f(x1)') % rysunek y=f(x), niebieska linia % tytuł % czekaj % złożenie dwóch kolumn w macierz xy % czekaj % zapis xy na dysk do zbioru wy.dat % przeczytaj zbiór z dysku % podstaw pierwsza kolumnę do x1 % podstaw druga kolumnę do y1 % rysunek y=f(x) i y1=f(x1) - porównanie % tytuł % czekaj
% PRZYKLAD 2 - przyklady grafiki dwuwymiarowej % pojedynczy rysunek - pojedyncza krzywa ================= subplot(111); % jeden wiersz, jedna kolumna, jeden rysunek x = 1 : 0.1 : 25 ; % definicja zmiennej x: od 1 co 0.1 do 25 y = 500 + 400*sin(x); % oblicz y dla każdego x plot( x, y, 'k' ) % narysuj wykres y=f(x), linia czarna title('sinusoida') % tytuł xlabel('argument x') % opis osi x ylabel('wartość y') % opis osi y grid % siatka % czekaj na naciśnięcie klawisza % pojedynczy rysunek z kilkoma krzywymi ================== plot( x, y, 'r-', x, 2*y, 'b-' ) % pierwsza RED, druga BLUE; obie ciągłe title('dwie SINUSOIDY') % tytuł % 4 rysunki z pojedynczą krzywą % leżące na szachownicy: dwa wiersze, dwie kolumny (22) % numer rysunków: 1, 2, 3, 4 (kolejno, wierszami) subplot(221), plot(x,y,'b--') title('skala linia, kreska-kreska') subplot(222), plot(x,y,'r-.') title('skala linia, kreska-kropka') subplot(223), loglog(x,y) title('skala log x/y') subplot(224), semilogx(x,y) title('skala log x ') clf % RYS - LEWY GÓRNY % linia niebieska kreska-kreska % RYS - PRAWY GÓRNY % linia czerwona kreska-kropka % RYS - LEWY DOLNY % skala logarytmiczna x i y % RYS - PRAWY DOLNY % skala logarytmiczna osi x % czekaj % wyzeruj ekran graficzny
% PRZYKLAD 3 - prosta grafika trójwymiarowa subplot(111); % jeden wiersz, jedna kolumna, jeden rysunek % definicja X i Y [ X, Y ] = meshdom( -2 : 0.05 : 2, -2 : 0.05 : 2 ); % def Z = f( X, Y ) Z = sin( 5*(X.^2 +Y.^2) ).* exp( -0.5*X.^2-0.5*Y.^2 ); mesh( Z ) % jeden rysunek 3D title('mapa 3D') % % czekaj contour( Z ) % jeden rysunek POZIOMICE title('poziomice 3D') % % czekaj subplot(211); mesh( Z ); title('rys A'); % kilka RYS na raz subplot(212); contour( Z ); title('rys B'); % subplot(111), meshc( Z ), title('funkcja MESHC'), meshz( Z ), title('funkcja MESHZ'), surf( Z ), title('funkcja SURF'), surfl( Z ), title('funkcja SURFL'), waterfall( Z ), title('funkcja WATERFALL'), imagesc( Z ), colormap('gray'), colorbar, title('funkcja IMAGE (GRAY)'), imagesc( Z ), colormap('autumn'), colorbar, title('funkcja IMAGE (AUTUMN)'),
% Przykład 4 - rozwiązanie równania algebraicznego: A * x = b A = [ 14 32 23; 32 77 68; 23 68 113 ] % zdefiniuj macierz A x = [ 1 2 3 ] % zdefiniuj wektor x b = A * x' clc x = inv(a) * b x = A \ b % OBLICZ b (x: wiersz --> kolumna) % czekaj % wyczyść ekran % ODTWÓRZ x - na podstawie A i b % za pomocą macierzy odwrotnej % oraz poprzez dzielenie macierzowe % czekaj
% PRZYKLAD 5 - rozkład sygnału na sumę sinusoid clear all, clf; % wyzeruj pamięć i ekran graficzny % Podaj parametry sygnału ============================== N = 256; % długość sygnału fs1 = 250; % częstotliwość składowej 1 w Hz fs2 = 500; % częstotliwość składowej 2 w Hz fp = 8000; % częstotliwość próbkowania w Hz dt = 1/fp; % odległość między próbkami w sekundach % Wygeneruj i narysuj analizowane sygnały ================= t = 0 : dt : (N-1)*dt; % definicja zmiennej czasu t y1 = 0.4*sin(2*pi*fs1*t + pi/2); % oblicz składową 1, y1 dla każdego t y2 = 0.2*sin(2*pi*fs2*t + pi/4); % oblicz składową 2, y2 dla każdego t y = y1 + y2; % suma składowych plot( t, y,'b') title('suma DWOCH SINUSOID') xlabel('czas') ylabel('sygnał') grid % narysuj wykres y=f(t) % tytuł % opis osi x % opis osi y % siatka % czekaj na klawisz % Rozłóż sygnał na składowe sinusoidalne, transformata Fouriera Y = fft( y, N ); % widmo sygnału, transformata Fouriera % SKALOWANIE WYNIKU Y = 2*abs( Y )/N; % wartość bezwzględna liczby zespolonej Y = Y( 1 : N/2 +1 ); % ważna tylko polowa, reszta symetryczna df = 1/(N*dt); % co ile herców prążek widma f = 0 : df : N/2*df; % częstotliwości prążków widma % POKAŻ WYNIK plot( f, Y ); % rysunek widma title('rozkład sygnału na sumę sinusoid') % podpis xlabel('częstotliwość w [Hz]') % opis osi x ylabel('amplituda') % opis osi y % czekaj % Zsyntezuj sygnał ze składowych sinusoidalnych ys = real( ifft( Y ) ); ys=ys ; % odwrotna transformacja Fouriera plot( t, y, 'r', t, ys, 'b' ); % porównaj oryginał i kopię
% PRZYKLAD 6 - znajdowanie miejsca zerowego funkcji %!!! danej wzorem!!! % Funkcja FZERO służy do znajdowania miejsca zerowego funkcji % % Załóżmy, że interesuje nas funkcja fun_zero(x), zdefiniowana % w zbiorze fun_zero.m na dysku x = 0 :.02 : 2; y = fun_zero(x); % zmienność argumentu % zmienność funkcji plot( x, y, 'b' ) % rysunek title( 'Funkcja y=f(x) - zauważ zero w pobliżu x = 1.2' ), grid % tytuł % czekaj % Aby znaleźć zero funkcji w otoczeniu x = 1.2, wołamy FZERO xokolica = 1.2; xtoler = eps; % x, w pobliżu którego szukamy zera % wymagana tolerancja rozwiązania z = fzero( 'fun_zero', xokolica, xtoler); % wyznaczmy argument zera x = 0.8 :.01 : 1.6; y = fun_zero(x); plot( x, y, z, fun_zero(z), 'ro') title( 'Zero funkcji fun_zero(x)' ) grid, z fun_zero(z) % x w otoczeniu zera % y w otoczeniu zera % rysujemy funkcje i obliczone zero % tytuł % siatka, czekanie % wypisz argument zera % wypisz wartość zera % ###################################################### function y = fun_zero( x ) % funkcja, w której miejsc zerowych poszukujemy y = 1./ ((x-.3).^2 +.01) + 1./ ((x-.9).^2 +.04) - 6;
% PRZYKLAD 7 % wyznaczanie parametrów znanej funkcji % jak najlepsze dopasowanie do danych doświadczalnych global dane % zmienna globalna - widziana z innych *.m zbiorów dane =... % pary punktów (x,y) otrzymanych doświadczalnie [ -5 25.5 % np. podczas laboratorium z fizyki -4 15.2 % pierwsza kolumna to argument x -3 8.5 % zaś druga, to wartość y -2 4.3 % jest to zaszumiona funkcja postaci y = a*x^2 + b -1 0.8 0 0.0 1 0.9 2 4.1 3 8.7 4 15.7 5 24.9 ]; x = dane(:,1); y = dane(:,2); plot(x,y,'ro') % pobranie wektora argumentów x % pobranie wektora wartości funkcji y % wykres y w funkcji x, czerwone "o" % Załóżmy, że zjawisko opisuje zależność: y = f(x;a,b) = a*x^2 + b % DWIE PARY PUNKTÓW (x1,y1) (x2,y2) wystarczą, aby obliczyć a,b % Ale ponieważ dane eksperymentalne są ZASZUMIONE, % przeprowadza się więcej pomiarów. % Następnie stara się znaleźć takie wartości a i b, aby błąd: % błąd = SQRT ( S U M A [ y - f(x; a,b) ]^2 / M ) % m=1...m % był jak najmniejszy, tzn. aby funkcja była "jak najlepiej" dopasowana params = [1 0]'; % startowe wartości a i b toler = 0.05; % wymagany błąd blad = fminsearch('fun_fi', params, toler); % procedura minimalizuj a = blad( 1 ) % wynikowe a b = blad( 2 ) % wynikowe b fy = a * x.^2 + b; % oblicz wartości funkcji f(x) % dla obliczonych a i b blad = std( fy-y ) % oblicz końcowy błąd
function blad = fun_fi( params ) global dane % Funkcja wykorzystywana przez przykład cw_7.m % Ma ona nastepujaca postac : y = a*x^2 + b % Wejście : parametry a i b % Wyjście : błąd dopasowania funkcji do danych eksperymentalnych a = params(1); b = params(2); x = dane(:,1); y = dane(:,2); fy = a * x.^2 + b; blad = std( fy-y ); % szukane parametry % dane z programu głównego % oblicz wartości funkcji f(x) % dla aktualnych parametrów a i b % błąd dopasowania % Pokaż postęp w dopasowaniu parametrów funkcji do danych plot( x, fy, 'b', x, y, 'ro'), grid xt = 0; yt = 3/4*max(y); text( xt, 1.2*yt, ['a = ' num2str( a ) ] ) text( xt, 1.1*yt, ['b = ' num2str( b ) ] ) text( xt, 1.0*yt, ['blad = ' num2str( blad ) ] )
% PRZYKLAD 8 - dopasowanie funkcji do danych % jak w przykładzie 7 tylko trudniej global dane % zmienna globalna - widziana z innych *.m zbiorów dane =... % pary punktów (x,y), otrzymane z dośw. [ 0.0000 5.8955 % np. podczas laboratorium z fizyki 0.1000 3.5639 % pierwsza kolumna argument x, np. czas 0.2000 2.5173 % druga kolumna wartość y, np. napięcie... 1.0000 0.6856... 2.0000 0.2636 ]; x = dane(:,1); y = dane(:,2); plot( x, y, 'ro' ) % pobranie wektora argumentów x % pobranie wektora wartości funkcji y % wykres y w funkcji x, czerwone "o" % pauza % Z teorii wynika, ze dane zjawisko opisuje teoretyczna zależność: % y = f( x ) = c(1) * exp(-lambda(1)*x) + c(2) * exp(-lambda(2)*x) % Powyższa funkcja ma dwa parametry liniowe: c(1) i c(2) % oraz dwa parametry nieliniowe: lambda(1) i lambda(2) % % Chcemy wyznaczyć takie wartości tych parametrów, aby funkcja % y=f(x) była najlepiej dopasowana do danych pomiarowych (x,y) lambda = [1 0]'; % startowe wartości lambda(1) i (2) toler = 0.1; % wymagany tolerancja błędu blad = fminsearch('fun_fit', lambda, toler); % procedura minimalizuj lambda = blad % wynikowe lambda(1) i (2) A = zeros( length(x), length(lambda) ); % obliczenia jak w fun_fit.m for j = 1 : size(lambda) % dla każdego x i lambda A(:,j) = exp( -lambda(j) * x ); % end % c = A \ y % fy = A * c; % blad = std(fy-y) %
function blad = fun_fit(lambda) global dane % Funkcja wykorzystywana przez cw_8.m % Ma ona następującą postać : % % y = c(1)*exp(-lambda(1)*x) +... + c(n)*exp(-lambda(n)*x) % % oraz posiada n parametrów liniowych c(i) i nieliniowych lambda(i) % % Wejście : zestaw parametrów lambda % Wyjście : błąd aproksymacji danych eksperymentalnych przez % aktualny zestaw parametrów lambda % % Parametry c(i) są wyznaczane na podstawie lambda i danych dośw. x = dane(:,1); y = dane(:,2); % podstaw dane % w programie głównym A = zeros( length(x), length(lambda) ); % utwórz macierz A, wyzeruj ją % wierszy tyle ile danych, % kolumn tyle ile lambda for j = 1:size(lambda) % dla każdego x i lambda A(:,j) = exp( -lambda(j) *x ); % oblicz wartości macierzy A, end % takiej że y = A * c c = A \ y; fy = A * c; blad = std(fy-y); % oblicz wektor optymalnych parametrów c % minimalizujących błąd średniokwadratowy % oblicz wartości funkcji fy dla tego c % oblicz błąd dopasowania % jak wartości funkcji różnią się od danych dośw. % Pokaż postęp w dopasowaniu parametrów funkcji do danych plot( x, fy, 'w', x, y, 'wo' ), grid xt = max(x)/2; yt = max(y)/2; text(xt,1.0*yt,['blad = ' num2str( blad )])
% PRZYKLAD 10 - rozw. numeryczne równania różniczkowego % Funkcje ODE23, ODE45 służą do numerycznego rozwiązywania zwyczajnych % równań różniczkowych. Metoda rozwiązania Rungego-Kutty-Fehlberga, % w której krok całkowania numerycznego jest zmieniany automatycznie % ODE23 wykorzystuje zależności 2 i 3 rzędu - średnia dokładność, % ODE45 wykorzystuje zależności 4 i 5 rzędu - duża dokładność. % Załóżmy, że interesuje nas rozwiązanie równania różniczkowego % van der Pola drugiego rzędu postaci : % y'' + (y^2-1)*y' + y = 0 % gdzie ' oznacza operator różniczkowania. % Po przedstawieniu w postaci: % y'' = -(y^2-1)*y' - y % równanie to można zastąpić układem dwóch równań rzędu pierwszego % y1' = -(y2^2-1)*y1 - y2 % y2' = y1 % gdzie y1 i y2 nazywane są tzw. zmiennymi stanu % % Aby zasymulować układ dynamiczny opisany równaniem różniczkowym, % tworzy się *.m funkcję, która: % otrzymuje wartości czasu i zmiennych stanu, % zaś zwraca pochodne wartości zmiennych stanu. % % Załóżmy, że nasza funkcja nazywa się fun_diff.m % % Aby zasymulować równanie różniczkowe Van Der Pola w przedziale % czasu 0 < t < 20, wywołujemy funkcję MATLABA ODE23: t0 = 0; % czas początkowy obserwacji tfinal = 20; % czas końcowy obserwacji y0 = [ 0 0.25 ]'; % wartości początkowe zmiennych stanu tol = 1.e-3; % dokładność rozwiązania trace = 1; % śledzenie [t,y] = ode23( 'fun_diff', t0, tfinal, y0, tol, trace ); % [t,y] = ode45( 'fun_diff', t0, tfinal, y0, tol, trace ); plot(t,y), title('historia czasowa równania van der Pola'), grid, % funkcja pomocnicza ##################################### function yprime = fun_diff(t,y); % zwraca pochodne zmiennych stanu y1 i y2 równania Van der Pola yprime = [ ( (y(2).^2-1).*y(1) - y(2) ); y(1) ];