====== Laboratorium 1 - Wprowadzenie do GNU Octave ====== Środowisko Octave jest wolnym odpowiednikiem pakietu MATLAB. [[http://www.gnu.org/software/octave/doc/interpreter/index.html|Dokumentacja]] ===== Instalacja i uruchamianie ===== W przypadku większości systemów Linux, pakiet Octave można zainstalować bezpośrednio z repozytorium: $ sudo apt-get install octave W przypadku systemu Windows i OS X, oprogramowanie Octave można ściągnąć ze strony projektu: [[http://www.gnu.org/software/octave/download.html|GNU Octave]]. W systemie Linux uruchamiamy środowisko za pomocą polecenia $ octave W konsoli Octave możemy wykonywać wszystkie podstawowe polecenia umożliwiające nawigację w systemie plików (cd, ls, etc). ===== Składnia ===== ==== Typy i zmienne ==== W języku Octave, nie prototypujemy zmiennych. Typy określane są automatycznie, tak jak w PHP, czy Bashu. zmienna = 'moja zmienna'; zmienna = 12.34; zmienna = [2 3 4; 3 4 5]; Jednym z podstawowych //typów// danych w Octave są wektory i macierze. Definiujemy je za pomocą nawiasów kwadratowych. Wartości w **wierszach** oddzielamy spacjami lub przecinkami. Wiersze oddzielamy znakiem średnika. Załóżmy że chcemy zdefiniować następującą macierz i przypisać ją do zmiennej M: $$M = \begin{bmatrix} 5 & 6 & 0 \\ 6 & 0 & 1 \\ 0 & 6 & 1 \end{bmatrix}$$ W Octave zapiszemy ją jako:M = [5 6 0; 6 0 1; 0 6 1] Aby odwołać się do danego elementu macierzy, lub wektora używamy nawiasów okrągłych.\\ **Uwaga :!:** W Octave indeksowanie rozpoczyna się od 1 a nie jak w popularnych językach programowania od 0! Np. Aby pobrać/przypisać wartość elementu z pierwszego wiersza i drugiej kolumny macierzy M, piszemy: M(1,2)=7 Jako wynik otrzymujemy: $$M = \begin{bmatrix} 5 & 7 & 0 \\ 6 & 0 & 1 \\ 0 & 6 & 1 \end{bmatrix}$$ Octave umozliwia równiez odwoływanie się do całych kolumn i wierszy w danej macierzy: M(:,3) % zwróci [0;1;1] M(2,:) % zwróci [6 0 1] Sprawdź co jak zadziała poniższy kod: M = [5 6 0; 6 0 1; 0 6 1]; M([2 3],[1 2]) ==== Zakresy ==== Zakresy tworzy się za pomocą znaku dwukropka. Służą one do definiowania prostych zestawów danych, a także do odwoływania się do danych w wektorach i macierzach. Przetestuj działanie poniższych poleceń zeros(1,10) zeros(2,10) ones(1,10) range = [1:10] range = [1:0.3:10] range(5:10) ==== Operatory arytmetyczne==== Octave udostępnia podstawowe operatory arytmetyczne zarówno dla macierzy jak i skalarów. Pełny zbiór operatorów dostępny jest w [[http://www.gnu.org/software/octave/doc/interpreter/Arithmetic-Ops.html#Arithmetic-Ops|dokumentacji Octave]]. **Uwaga :!:** Zwróć uwagę na działanie operatorów połączonych z kropką! \\ Przetestuj działanie poniższego kodu. A = [0.5 0.5; 1 1]; B = [2 2; 2 2]; A * B A .* B B ^ 2 B .^ D ==== Instrukcje sterujące ==== Octave udostępnia powszechnie znane z innych języków programowania instrukcje sterujące. Pełny opis instrukcji sterujących można znaleźć w [[http://www.gnu.org/software/octave/doc/interpreter/Statements.html#Statements|dokumentacji Octave]] ==== Definiowanie funkcji ==== Szczegółowe dane na temat definiowania funkcji można znaleźć w [[http://www.gnu.org/software/octave/doc/interpreter/Functions-and-Scripts.html#Functions-and-Scripts|dokumentacji Octave]]. Poniżej kilka podstawowych infromacji: * Funkcje najczęściej definiujemy w osobnych plikach z rozszerzeniem **.m** * Nazwa funkcji musi zgadzać się z nazwą pliku! * Wywoływanie funkcji odbywa się poprzez podanie jej nazwy i listy argumentów. * Podczas wywoływania funkcji musimy znajdować się w katalogu w którym dana funkcja jest zapisana. * W Octave nie zwracamy wartości za pomocą **return**. Po prostu przypisujemy ją do zmiennej podanej jako element zwracany * Komentarze w kodzie wstawiamy za pomocą % Przykładowa definicja funkcji: function W = srednia(dane) % funkcja obliczająca średnią elementów w wektorze W = sum(dane)/length(dane); end Aby wywołać funkcje z przykładu powyżej wykonujemy polecenie: Wynik = srednia([2 3 4 5 6 7 8]); Jeśli funkcja ma zwracać więcej niż jeden argument, zapisujemy to w ten sposób: function [IndexX,IndexY] = myFind(M,V) % Funkcja poszukująca wartości V w macierzy M % Funkcja zwraca indeksy znalezionej wartości, lub -1,-1 [rows,cols] = size(M); IndexX = IndexY =-1; for i=1:rows, for j=1:cols if M(i,j) == V IndexX = i; IndexY = j; return; endif end end end Aby pobrać wartości zwracane przez funkcję powyżej wpisujemy np.: [X,Y] = myFind(M,6); ==== Rysowanie wykresów ==== Do rysowania wykresów używamy funkcji: * plot - rysowanie wykresów 2D * plot3d - rysowanie wykresów 3D * mesh - rysowanie płaszczyzn Porównaj działanie funkcji na poniższych przykładach. Jaka jest różnica pomiędzy plot3 a mesh? **Plot2** x = [0:0.01:10]; y = sin(x); plot(x,y); **Plot3** t = 0:0.1:10*pi; r = linspace (0, 1, numel (t)); z = linspace (0, 1, numel (t)); plot3 (r.*sin(t), r.*cos(t), z); **Mesh** tx = ty = linspace (-8, 8, 41)'; [xx, yy] = meshgrid (tx, ty); r = sqrt (xx .^ 2 + yy .^ 2) + eps; tz = sin (r) ./ r; mesh (tx, ty, tz); ===== Dobre praktyki ===== * Jeśli tylko jest to możliwe, używaj funkcji wbudowanych. Na przykład zamiast pisać swoją własną funkcję **srednia** lepiej było wykorzystać wbudowaną funkcję **mean**. * Jeśli to tylko możliwe, staraj się wykorzystywać operacje na macierzach, zamiast pętli. * Zawsze definiuj wcześniej wektor/macierz z która pracujesz (chyba że jest ona bezpośrednim wynikiem jakichś operacji). Np.:M = zeros(3,3); [x,y] = size(M); for i=1:x for j=1:y M(i,j) = rand; end end ===== Ćwiczenia ===== ==== Operacje podstawowe I==== Zakładając, że mamy następującą macierz $$A = \begin{bmatrix} 16 & 2 & 3 & 13 \\ 5 & 11& 10 & 8 \\ 9 & 7 & 6 & 12 \\ 4 & 14 & 15 & 1 \end{bmatrix}$$ Jakie indeksowanie macierzy A pozwoli na wyciągnięcie z niej następującej macierzy: $$B = \begin{bmatrix} 16 & 2 \\ 5 & 11 \\ 9 & 7 \\ 4 & 14 \end{bmatrix}$$ ==== Operacje podstawowe II==== Napisz funkcję znajdującą najmniejszy i największy element w macierzy i zwracającą te wartości. **Podpowiedź** użyj zbudowanych funkcji //min// i //max//. ==== Wartość wektora ==== Napisz funkcje wyznaczającą długość (normę) wektora podanego jako parametr, która określona jest wzorem: $$|A| = \sqrt{\sum\limits_{i=1}^n a_i^2} $$ ==== Odchylenie standardowe I==== Napisz funkcję wyznaczającą [[http://pl.wikipedia.org/wiki/Odchylenie_standardowe|odchylenie standardowe]] dla wartości wektora podanego jako parametr. Odchylenie standardowe dane jest wzorem: $$\sigma = \sqrt{\frac{\sum\limits_{i=1}^{N} \left(x_{i} - \mu)^{2}} {N-1}}$$ Gdzie $\mu$ to średnia, a N to liczba wszystkich elementów w probie. ==== Odchylenie standardowe II==== Przyjmij, że tym razem parametrem funkcji nie jest wektor, ale macierz. Funkcja powinna obliczyć odchylenia standardowe dla każdego wiersza macierzy osobno i zwrócić wektor odchylen standardowych. **Uwaga** Pamiętaj o zadaniu [[#Operacje_podstawowe_i|Operacje Podstawowe I i II]]! ==== Wydajność I==== Dla funkcji napisanych w poprzednich dwóch zadaniach ([[#dlugosc_wektora|Długość wektora]] oraz [[#odchylenie_standardowe_i|Odchylenie Standardowe I]]) dopisz ich odpowiedniki wektorowe (lub z użyciem pętli) i przetestuj ich działanie na wygenerowanym losowo zbiorze $10^6$ liczb. Aby wygenerować dane użyj: data = rand(1,10^6); Porównaj czasy wykonywania funkcji: timestart = time(); %Wywolanie funkcji timestop = time(); printf('Czas wykonania to %d sekund.\n',(timestop-timestart)); Jak zmienią się czasy gdy zmienimy ilość danych z $10^6$ na $10^8$? O ile wolniej (procentowo) wykonuje się algorytm wyznaczający odchylenie standardowe wykorzystujący wbudowaną funkcję obliczającą średnią od tego, który wykorzystuje funkcję //srednia// napisaną przez nas? ==== Wydajność II ==== Jak poprawic wydajnośc następujących fragmentów kodu: **Przykład I** A = zeros(10,10) v = zeros(10, 1); x = zeros(10, 1); for i = 1:10 for j = 1:10 x(i) = v(i) + A(i, j) * v(j); end end **Przykład II** for i = 1:7 for j = 1:7 A(i, j) = log (X(i, j)); B(i, j) = X(i, j) ^ 2; C(i, j) = X(i, j) + 1; D(i, j) = X(i, j) / 4; end end ==== Rysowanie wykresu funkcji ==== Napisz funkcję która będzie wyznaczała wartości funkcji z obrazka poniżej. Wyrysuj wartości tej funkcji na wykresie w przedziale od -10 do 10 z krokiem 0.5. {{:pl:dydaktyka:ml:absfun.png|Wartość bezwzględna}}