četvrtak, 26 decembra, 2024
Kako da...?

Numerička obrada i simulacije (4. deo)

Autor: Stefan Nožinić

U prethodnom delu smo se upoznali sa nekim osnovnim delovima biblioteke koju ćemo koristiti. Ta osnova nije dovoljna bez dobrog razumevanja matematičke teorije. Ovo nije potrebno samo radi razumevanja procesa i metoda koje ćemo opisati, već i zbog toga što se mnoge stvari ne mogu uraditi bez dobrog matematičkog alata.

Vektor

Postoji dosta definicija vektora – naravno, sve su ekvivalentne. Radi boljeg razumevanja metoda koje ćemo koristiti, izabrali smo definiciju koja najbolje leže uz strukturu podataka pomoću koje ćemo predstavljati vektore. Vektor je niz brojeva i može predstavljati konačan broj podataka. Naprimer, tačka na ravni se može predstaviti vektorom tako što ćemo navesti njene koordinate. Te koordinate ne moraju biti uobičajene koordinate koje poznajemo, odnosno ne moraju biti koordinate u Dekartovom pravouglom koordinatnom sistemu. Drugi primer bio bi, recimo, skup nekih merenja. Naprimer, želimo da izmerimo visinu na uzorku od 100 ljudi; to merenje možemo zapisati kao vektor (niz) od 100 elemenata. Ovde moramo paziti da je redosled bitan – jer, ako promenimo redosled elementima, to više nije vektor.

Vektore ćemo predstavljati na sledeći način:

Ovo je vektor od n članova. Primetite da smo počeli sa indeksiranjem od nule. Ovu konvenciju koristimo kako bismo se lakše mogli prebaciti na konkretnu implementaciju kasnije.

Sledi primer kako vektore koristimo u Pajtonu, uz biblioteku NumPaj (eng. NumPy)

>>> import numpy as np >>> a = np.array([1,2,3]) >>> a array([1, 2, 3]) >>> b = np.zeros(50) >>> b array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0., 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0., 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0., 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]) >>> c = np.ones(10) >>> c array([ 1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.,  1.]) >>>

Primetite da funkcijama np.zeros(…) i np.ones(…) dodeljujemo broj elemenata koliko želimo da taj vektor ima. U ovom kontekstu, vektor i niz su isti.

Sabiranje i oduzimanje vektora se vrši tako što saberemo i oduzmemo element po element. Tačnije:

ako je onda za i=ti element važi:

a u kodu bismo to ovako implementirali:

>>> a = np.array([1,2,3]) >>> b = np.array([0,2,1]) >>> c = a - b >>> c array([1, 0, 2])

Potrebno je primetiti da vektori moraju imati istu veličinu, odnosno broj elemenata.

Takođe, moguće je i množenje po elementu, odnosno i-ti element novog vektora je jednak proizvodu i-tih elemenata ova dva vektora. U kodu se to implementira isto jako jednostavno:

>>> d = a*b >>> d array([0, 4, 3])

Slično je i za deljenje po elementu.

Imamo još dve operacije koje ne postoje kada pričamo o skalarima (pojedinačnim brojevima), a to su skalarni i vektorski proizvod.

Skalarni proizvod kao rezultat ne daje vektor, već skalar, odnosno broj:

Ovo na prvi ogled može stvarati konfuziju jer je teško razlikovati skalarni proizvod od proizvoda elemenata. Zbog ovoga ćemo skalarni proizvod obeležavati kao , a proizvod po elementima kao

Poslednja operacija sa vektorima koju ćemo obraditi je vektorski proizvod:

koji kao rezultat daje vektor. Zasada nećemo ulaziti u detalje kako se ova operacija vrši, jer nam trenutno nije potrebna.

Matrice

Druga struktura koja će nam biti potrebna jesu matrice. One mogu predstavljati linearnu transformaciju, tačnije transformaciju jednog vektora u drugi. Matrice ćemo obeležavati velikim slovima.

Kao što smo rekli, matrice predstavljaju transformaciju vektora zbog operacije množenja matrica koja je definisana na sledeći način:

ako je onda element na poziciji (i,j) ima sledeću vrednost:

Ovo može delovati komplikovano, pa je najbolje da to pogledamo kroz primer:

>>> A = np.array([[1,2,3], [4,5,6], [7,8,9]]) >>> A array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) >>> B = np.array([[1,7,8], [8,2,1], [1,5,10]]) >>> B array([[ 1,  7,  8], [ 8,  2,  1], [ 1,  5, 10]]) >>> C = np.dot(A,B) >>> C array([[ 20,  26,  40], [ 50,  68,  97], [ 80, 110, 154]]) >>>

Potrebno je primetiti kako se definiše matrica: kao argument np.array(…) metode ubacujemo grupu vitičastih zagrada, pa u njih više grupa vitičastih zagrada u kojima navodimo elemente. Prva grupa označava prvi red, druga grupa je drugi, itd.

Ako želimo da zadamo matricu nula, to možemo uraditi na sledeći način:

>>> Z = np.zeros([5,5]) >>> Z array([[ 0.,  0.,  0.,  0.,  0.], [ 0.,  0.,  0.,  0.,  0.], [ 0.,  0.,  0.,  0.,  0.], [ 0.,  0.,  0.,  0.,  0.], [ 0.,  0.,  0.,  0.,  0.]]) >>>

Dakle, kao argument navodimo vektor u kojem su dimenzije matrice.

Kod proizvoda dve matrice je bitno napomenuti dve stvari:

1. Broj kolona prve matrice mora biti jednak broju redova druge matrice.

2. Iz gornjeg uslova lako je zaključiti da ne važi pravilo komutativnosti, tačnije: .

Jedinična matrica je matrica za koju važi , a možemo je dobiti vrlo lako:

array([[ 1.,  0.,  0.,  0.,  0.], [ 0.,  1.,  0.,  0.,  0.], [ 0.,  0.,  1.,  0.,  0.], [ 0.,  0.,  0.,  1.,  0.], [ 0.,  0.,  0.,  0.,  1.]]) >>>

Kako ova matrica ima jednak broj kolona i redova, dovoljno je kao argument navesti samo broj koji označava broj redova (kolona).

Sada se postavlja pitanje da li postoje matrice tako da je

Odgovor je: i da i ne. Ne postoje uvek, ali kad postoje, te dve matrice su inverzne jedna drugoj. Inverznu matricu ćemo obeležavati sa -1u eksponentu, tako da važi za datu matricu. Matrice koje nemaju svog inverznog partnera zovemo neinvertabilne matrice.

Sada vektor možemo posmatrati i kao matricu koja ima N redova i jednu kolonu. U tom slučaju proizvod matrice i vektora daje nam vektor na sledeći način gde je

Poslednja stvar koju bi trebalo da pojasnimo pre nego što pređemo na nešto konkretnije – jeste transponovanje matrica. Ova operacija je vrlo jednostavna – ona samo „rotira matricu”, tj. ako je onda . U kodu to izgleda ovako:

>>> A = np.array([[1,2,3], [4,5,6], [7,8,9]]) >>> A array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) >>> A.T array([[1, 4, 7], [2, 5, 8], [3, 6, 9]]) >>>

Za razmišljanje

U narednom broju krećemo konkretnije da se bavimo samom temom ovog serijala. Nadamo se da ćete nas čitati. Do tada, ostavljamo vas da razmislite kako da skalarni proizvod dva vektora predstavite u matričnoj notaciji koristeći proizvod matrica koji smo opisali, i transponovanje. Hint: vektori se isto mogu transponovati.