ˇ UNARSKOM INŽENJERSTVU PYTHON U RAC ´ bojan crnkovi c, ´ jerko škifi c´ i marko cavrak ˇ stefan ivi c,
Numeriˇcke metode, priprema, obrada i vizualizacija podataka 19. sijeˇcnja 2014. – v0.1
ˇ Stefan Ivi´c, Bojan Crnkovi´c, Jerko Škifi´c i Marko Cavrak: Python u raˇcunarskom inženjerstvu, Numeriˇcke metode, priprema, obrada i vizualizacija poc 19. sijeˇcnja 2014. dataka,
SADRŽAJ
I 1
osnove pythona uvod 1.1
1.2
1.3
1.2.2
Dodatni paketi na Windows platformi
1.2.3
Instalacija pomo´cu upravitelja paketa
2.2 2.3
2.4
3.2 3.3 3.4 3.5 3.6
4.2 4.3 4.4 4.5 4.6
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . .
. . . . . . . . . Python ljuska kao kalukulator . . . . Python skripte . . . . . . . . . . . 2.3.1 Upotreba posebnih znakova . . Moduli . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . . . . . . . . . ¯ Relacijski operatori ili operatori usporedivanja) . Operatori dodjeljivanja . . . . . . . . . . . . Logiˇcki operatori . . . . . . . . . . . . . . . ˇ Clanski operatori . . . . . . . . . . . . . . . Operatori identiteta . . . . . . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . .
. . . .
. . . .
. String . . Liste . . Tuple . .
. . . . Dictionary . Skupovi . . .
Brojevi
. . . .
. . . . . .
5.2 5.3
6.2 6.3
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
7.2 7.3 7.4
4 4 5 5 5 6
7 7 7 8 8
12 13 14 16 17 18
19 19 20 20 21 21
23 24 24
25 26 27 29
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
funkcije 8.1
4
25
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . elif . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . if
. . . . . while . . . . break . . . . continue . .
4
23
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . raw_input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . print
for
3
19
Aritmetiˇcki operatori
petlje 7.1
3
11
. . . . . .
uvjetna grananja 6.1
3
7
Pokretanje Pythona
osnovne naredbe za unos i ispis podataka 5.1
8
. . . . . . . . . . .
operatori 4.1
7
. . . . . . . . . . .
tipovi podataka 3.1
6
. . . . . . . . . . .
python ljuska i .py skripte 2.1
5
. . . . . . . . . . .
. . . .
. Spyder . . . . . . . PyDev . . . . . . . Kate . . . . . . . .
Editori i razvojna okruženja
1.3.3
4
. . . . . . . . . .
1.3.2
3
3
. . . . . . . . . . . . . . . 1.1.1 Instalacija na Linux platformi . . . 1.1.2 Instalacija na Windows platformi . Dodatni paketi . . . . . . . . . . . . 1.2.1 Dodatni paketi na Linux platformi .
Instalacija
1.3.1
2
1
Definiranje i pozivanje funkcija
29 30 30 31 33
. . . . . . . . . . . . . . . . . . . . . .
33
iii
iv
sadržaj
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
41
. . . . . . . . . . . . . . . . . . . . . . 10.2 Oblikovanje sa metodom format . . . . . . . . . . . . . . . . . . . . .
53
Vra´canje vrijednosti iz funkcije
8.3
Argumenti sa zadanim vrijednostima
8.4 8.5 8.6 8.7
9
. . . . . Keyword i non-keyword argumenti . . Ugnježdena definicija funkcije . . . . Anonimne funkcije . . . . . . . . . Rekurzivne funkcije . . . . . . . . .
8.2
. . . . . .
. . . . . .
. . . . . .
objektno-orijentirano programiranje 9.1
Objektno-orijentirano programiranje
9.2
Klase
9.3
9.4 9.5
9.6
. . . . . . . . . . Atributi . . . . . . . . . 9.3.1 Globalni atributi . 9.3.2 Objektni atributi . Metode . . . . . . . . . Preopterecivanje . . . . .
. . . . . .
. . . . . .
. . . . . . .
. . . . . . 9.5.1 Preopterecivanje funkcija . 9.5.2 Preopterecivanje operatora . ¯ Nasljedivanje . . . . . . . . . .
. . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . 11.5 Preimenovanje, kopiranje i brisanje datoteka . 11.6 Arhiviranje . . . . . . . . . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. 12.2 Matematiˇcke funkcije . . . . . . . . . . . . . 12.3 Datum i vrijeme . . . . . . . . . . . . . . . . 12.4 Vrijeme izvršavanja . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
Otvaranje i zatvaranje datoteka
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
12 python standard library
36 37
42 42 42 43 44 45 46 47 49
55
57 57 58 59 60 60 61
Informacije o platformi i operacijskom sustavu
13 greške u python kodu
61 61 62 62 65
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13.2 Manipulacija greškama - Exception handling . . . . . . . . . . . . . . . . 13.3 Ispravljanje grešaka - DeBugging . . . . . . . . . . . . . . . . . . . . .
65
numpy polja i matrice
69
13.1
II
36
57
. 11.2 Pisanje u datoteke . . . . . . . ˇ 11.3 Citanje iz datoteka . . . . . . . 11.4 Pozicioniranje u datoteci . . . .
12.1
35
53
Oblikovanje sa operatorom %
11 rad sa datotekama 11.1
35
41
10 oblikovanje stringova 10.1
34
Tipovi grešaka
14 zadavanje polja u numpy-u 14.1 14.2 14.3 14.4 14.5 14.6 14.7 14.8
. . arange . linspace . zeros . . ones . . eye . . . diag . .
. . . . . . . meshgrid . array
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
Informacije o polju
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .
16 manipulacije sa numpy poljima
. . . . . . . . . . . . . . . . . . . . 16.2 Transponiranje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16.3 Dodavanje i brisanje elemenata polja . . . . . . . . . . . . . . . . . . . 16.1
67
71
. . . . . . . .
15 informacije o polju i indeksiranje 15.1
66
Manipulacije sa dimenzijama polja
71 72 72 73 73 74 74 75 77 77 79 79 80 80
sadržaj
ˇ 17 u citavanje i spremanje numpy polja
81
. . . . . . . . . . . . . . . . . . . . 17.2 Spremanje u tekstualne datoteke . . . . . . . . . . . . . . . . . . . . . 17.1
Uˇcitavanje iz tekstualnih datoteka
ˇ ˇ 18 matri cni ra cun 18.1
III
priprema, obrada i vizualizacija podataka
85
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . . . . . . . . . . . Mapa boja . . . . . . . . . . . . . Detaljnije podešavanje grafa izolinija . . Primjer . . . . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
Linijski grafovi
Svojstva prozora, prostora crtanja i osi
. 19.5 Podgrafovi . . . . 19.6 Polarni grafovi . . 19.7 tips and tricks . . . 19.4
Spremanje grafova
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . . . . . . .
. . . . . . . . .
20 složeniji 2d grafovi 20.1
Izolinije 20.1.1 20.1.2 20.1.3
22.2
22.4 22.5
. . . . . . Newton-Raphsonova metoda . Sekanta . . . . . . . . . . . Brentova metoda . . . . . . Zadaci . . . . . . . . . . . Metoda bisekcije
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
1D interpolacija
24 regresije Metoda najmanjih kvadrata
25 rješavanje sustava linearnih jednadžbi Metoda Gaussove eliminacije
ˇ 26 numeri cko integriranje
. . 26.2 Simpsonove formule . 26.3 Naprednije metode . 26.4 Zadaci . . . . . . . V
Trapezna formula
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
rješavanje modela temeljenih na odj i pdj
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Runge-Kutta metode . . . . . . . . . . . . . . . . . . . . . . .
Obiˇcne diferencijalne jednadžbe 1. reda 27.1.1 27.1.2
98 99
101 101 102 103
109 111 112 112 113
115 116
Eulerova metoda
119 119 120
123 124 127
. . . .
ˇ ˇ 27 numeri cke metode za rješavanje obi cnih diferencijalnih jednadžbi 27.1
97
123
. . . . . . . . . . . . . . . . . . . . . . . 25.2 LU dekompozicija . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26.1
97
119
. . . . . . . . . . . . . . . . . . . . . . . 24.2 Linearna regresija . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24.3 Zadaci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25.1
92
115
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23.2 2D i N-D interpolacija . . . . . . . . . . . . . . . . . . . . . . . . . . 24.1
90
109
. . . . .
23 interpolacije 23.1
90
107
22 rješavanje nelinearnih jednadžbi
22.3
90
105
ˇ numeri cke metode 22.1
87
101
21 izrada animacija
IV
83
87
. . . . . . . . . . . 19.2 Naprednija kontrola linijskih grafova . 19.2.1 Boje . . . . . . . . . . . . 19.2.2 Markeri . . . . . . . . . . . 19.3
82 83
. . . . . . . . . . . . . . . . . .
Rješavanje sustava linearnih jednadžbi
19 osnovni 2d grafovi 19.1
81
127 129 130 131
133 135 135 135 135
v
vi
sadržaj
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27.3 Obiˇcne diferencijalne jednadžbe višeg reda . . . . . . . . . . . . . . . . 27.1.3
27.2
Rješavanje pomo´cu scipy-a
Sustavi obiˇcnih diferencijalnih jednadžbi 1. reda
ˇ 28 po cetni problemi
137 137
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . ¯ 29.2 Stacionarno provodenje topline u štapu . . . . . . . . . . . . . . . . . .
147
Modeliranje otvorenog vodotoka 28.1.1 28.1.2 28.1.3 28.1.4 28.1.5 28.1.6
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
29 rubni problemi 29.1
31.1
Progib ploˇce
. . . . . . . . . . . . . 34.2 Simpleks metoda . . . . . . . . . . . . . . . 34.3 Rješavanje LP problema pomo´cu modula PuLP . 34.4 Praktiˇcni primjeri LP problema . . . . . . . . . 34.4.1 Teretni zrakoplov . . . . . . . . . . . . Definicija LP problema
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35.2 Nelder-Mead metoda za optimizaciju funkcije dviju varijabli . . . . . . . . Algoritam
36 simulirano kaljenje
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36.2 Primjer simuliranog kaljenja pomo´cu modula inspyred . . . . . . . . . . Algoritam
ˇ 37 optimizacija rojem cestica
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37.2 Korištenje PSO metode pomo´cu modula inspyred . . . . . . . . . . . . . Razvoj metode
ˇ 38 geneti cki algoritmi
. . . . . . . . . . . . . . . . . . . . . . . . . . . 38.2 Korištenje DEAP modula . . . . . . . . . . . . . . . . . . . . . . . . VII a
Evolucijski algoritmi
dodaci bibliografija
149
153
163 164 164 165
. . . . .
35 nelder-mead metoda
38.1
143
163
Optimizacijske varijable
34 linearno programiranje
37.1
142
161
. . . . . . . . . . . . . . . . . . . . . . . . . 33.2 Ciljevi optimizacije i funkcija cilja . . . . . . . . . . . . . . . . . . . . 33.3 Ograniˇcenja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
36.1
142
157
33 definicija optimizacijskog problema
35.1
140
153
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
optimizacijske metode
34.1
139
151
32 metoda linija
33.1
138
147
Savijanje grede
30 klasifikacija parcijalnih diferencijalnih jednadžbi ˇ 31 elipti cke parcijalne diferencijalne jednadžbe
VI
136
. . . . . . .
28.1
. . . . . . . Stacionarno strujanje . . . . . . . . . Maningova formula . . . . . . . . . . Uniformno strujanje i normalna dubina . . Kritiˇcna dubina . . . . . . . . . . . . Hidrauliˇcki skok . . . . . . . . . . . Numeriˇcko rješavanje . . . . . . . . .
135 136
165 166 166 166 167 171 171 172 177 177 177 181 181 182 185 185 186
193 195
POPIS SLIKA
Slika 1.1 Slika 1.2 Slika 6.1 Slika 6.2 Slika 6.3 Slika 7.1 Slika 7.2 Slika 7.3 Slika 19.1 Slika 19.2 Slika 19.3 Slika 19.4 Slika 19.5 Slika 19.6 Slika 19.7 Slika 19.8 Slika 19.9 Slika 19.10 Slika 19.11 Slika 19.12 Slika 20.1 Slika 20.2 Slika 22.1 Slika 22.2 Slika 23.1 Slika 23.2 Slika 24.1 Slika 26.1 Slika 26.2 Slika 27.1 Slika 28.1 Slika 28.2 Slika 28.3 Slika 28.4 Slika 28.5 Slika 28.6 Slika 28.7 Slika 29.1 Slika 29.2 Slika 29.3 Slika 31.1 Slika 32.1 Slika 35.1
Slika 35.2 Slika 36.1 Slika 37.1 Slika 37.2 Slika 38.1
Spyder razvojno okruženje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Kate tekstualni editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dijagram toka if naredbe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . if-else dijagram toka . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dijagram toka za složeni uvjet grananja . . . . . . . . . . . . . . . . . . . . . . . Dijagram toka while petlje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dijagram toka while petlje sa else blokom . . . . . . . . . . . . . . . . . . . . . Dijagram toka while petlje sa continue naredbom . . . . . . . . . . . . . . . . . Matplotlib elementi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ¯ Prozor sa grafom napravljen izvodenjem izvrnog koda 19.1 . . . . . . . . . . . ¯ Graf napravljen izvodenjem izvornog koda 19.2 . . . . . . . . . . . . . . . . . . ¯ Graf napravljen izvodenjem izvornog koda 19.3 . . . . . . . . . . . . . . . . . . Izmijenjene granice grafa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Custom ticks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Custom ticks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Spines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Formatiranje oznaka na osima . . . . . . . . . . . . . . . . . . . . . . . . . . . . Prikaz legende na grafu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Podgrafovi nastali izvršavanjem izvornog koda 19.5 . . . . . . . . . . . . . . . Graf u polarnom koordinatnom sustavu . . . . . . . . . . . . . . . . . . . . . . Predefinirane mape boja u matplotlibu . . . . . . . . . . . . . . . . . . . . . . . ¯ Graf napravljen izvodenjem izvornog koda 20.1 . . . . . . . . . . . . . . . . . . Skica metode biskecije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Newton-Raphsonova metoda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Primjer razliˇcitih 1D interpolacija . . . . . . . . . . . . . . . . . . . . . . . . . . Primjer 2D interpolacije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Regresijski pravac dobiven izvornim kodom 24.1 . . . . . . . . . . . . . . . . . Trapezi na cjelom intervalu [a, b] i na tri podintervala. . . . . . . . . . . . . . . Raˇcunanje površine ispod krivulje pomo´cu trapeza (Izvorni kod 26.1) . . . . . Vizualizacija rješenja iz izvornog koda 27.1. . . . . . . . . . . . . . . . . . . . . Skica popreˇcnog presjeka otvorenog vodotoka . . . . . . . . . . . . . . . . . . . Energetske linije u strujanju fluida otvorenim vodotokom . . . . . . . . . . . . Pravokutni popreˇcni presjek kanala . . . . . . . . . . . . . . . . . . . . . . . . . Trapezni popreˇcni presjek kanala . . . . . . . . . . . . . . . . . . . . . . . . . . . M-krivulje vodnog lica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . S-krivulje vodnog lica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Numeriˇcko rješenje strujanja u otvorenom kanalu pravokutnog presjeka . . . . Savijanje grede . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Rubni uvjeti za razliˇcite oslonce grede . . . . . . . . . . . . . . . . . . . . . . . . Progib elastiˇcne linije grede . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Ploˇca . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Diskretizacija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Toˇcke refleksije, ekspanzije, kontrakcije i redukcije kod Nelder-Mead metode optimizacije za funkciju dvije varijable. Toˇcke refleksije, ekspanzije ili kontrakcije mjenjaju najgoru toˇcku simpleksa, dok toˇcke redukcije mjenjaju dvije nagore toˇcke simpleksa. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izgled simpleksa u 5 iteraciji (za izvorni kod 35.1). . . . . . . . . . . . . . . . . Konvergencija optimizacije pomo´cu simuliranog kaljenja . . . . . . . . . . . . . Ponašanje jedinki u Reynoldsovom modelu. Odvajanje, usmjeravanje i kohezija. . Utjecaj gnjezda na jedinke jata. . . . . . . . . . . . . . . . . . . . . . . . . . . . . Konvergencija optimizacije genetiˇckim algoritmom (Izvorni kod 38.1) . . . . .
5 6 25 26 28 30 31 31 87 88 90 92 93 94 94 95 96 97 98 99 102 104 110 111 116 117 120 127 129 136 137 137 140 141 144 144 145 147 148 149 153 157
172 175 179 181 182 191
vii
P O P I S TA B L I C A
Tablica 3.1 Tablica 4.1 Tablica 4.2 Tablica 4.3 Tablica 4.4 Tablica 5.1 Tablica 10.1 Tablica 10.2 Tablica 12.1 Tablica 12.2 Tablica 19.1 Tablica 19.2 Tablica 19.3 Tablica 19.4 Tablica 28.1
viii
Primjeri oznaˇcavanja brojeva . . . . . . . . . . . . . . . . . . . . . Aritmetiˇcki operatori . . . . . . . . . . . . . . . . . . . . . . . . . . Relacijski operatori . . . . . . . . . . . . . . . . . . . . . . . . . . . Operatori dodjeljivanja . . . . . . . . . . . . . . . . . . . . . . . . . Logiˇcki operatori . . . . . . . . . . . . . . . . . . . . . . . . . . . . printf formatiranje . . . . . . . . . . . . . . . . . . . . . . . . . . . Opcije konverzije . . . . . . . . . . . . . . . . . . . . . . . . . . . . Definiranje tipova podataka . . . . . . . . . . . . . . . . . . . . . . Opis nekih funkcija math modula . . . . . . . . . . . . . . . . . . . Opis nekih funkcija cmath modula . . . . . . . . . . . . . . . . . . Vrste linija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Simboli boja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vrste markera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Pozicija legende . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Vrijednosti Manningovog koeficijenta za razliˇcite izvedbe kanala.
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. 13 . 19 . 20 . 20 . 21 . 23 . 53 . 54 . 61 . 61 . 88 . 89 . 89 . 97 . 139
POPIS IZVORNOG KODA
Izvorni kod 2.1 Izvorni kod 2.2 Izvorni kod 3.1 Izvorni kod 4.1
Podrška za posebne znakove u Python skriptama . . . . . . . . . . . . . . . . . Korištenje objekata modula . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Dodavanje i brisanje elemenata liste . . . . . . . . . . . . . . . . . . . . . . . . . ¯ Primjer kombiniranje operatora dodjeljivanja, operatora usporedivanja i logiˇckih operatora . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 5.1 Razliˇciti primjeri ispisa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 6.1 Jednostavan primjer upotrebe if naredbe . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 6.2 Pisanje složenijeg uvjetovanog grananja . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 6.3 Primjer upotrebe else naredbe . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 6.4 Primjer kombinacije naredbi if, elif i else . . . . . . . . . . . . . . . . . . . . Izvorni kod 7.1 Upotreba for naredbe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 7.2 Naredba for s listom stringova . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 7.3 Naredba for i stirng . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 7.4 Naredba for s listom stringova . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 7.5 Upotreba while naredbe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 7.6 Upotreba else naredbe u petlji . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 7.7 Upotreba break naredbe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 7.8 Upotreba continue naredbe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 8.1 Definicija i pozivanje jednostavne funkcije . . . . . . . . . . . . . . . . . . . . . Izvorni kod 8.2 Definicija funkcije koja prima argument . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 8.3 Definicija funkcije koja prima više argumenata i vra´ca vrijednost . . . . . . . . Izvorni kod 8.4 Funkcija koja vra´ca razliˇcite tipove . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 8.5 Funkcija koja vra´ca više vrijednosti korsite´ci tuple . . . . . . . . . . . . . . . . Izvorni kod 8.6 Funkcija sa zadanim argumentom . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 8.7 Primjer anonimne funkcije u ugnježdenoj definiciji . . . . . . . . . . . . . . . . Izvorni kod 9.1 Definicija klase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 9.2 Primjer definicije klasnih (globalnih) atributa . . . . . . . . . . . . . . . . . . . . Izvorni kod 9.3 Primjer definicije objektnog atributa . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 9.4 Inicijalizacija objekta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 9.5 Definicija metode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 9.6 Preoptere´civanje funkcije print . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 9.7 Preoptere´civanje funkcije print . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 9.8 Preoptere´civanje funkcije print . . . . . . . . . . . . . . . . . . . . . . . . . . . . ¯ Izvorni kod 9.9 Naslijedivanje . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ¯ Izvorni kod 9.10 Naslijedivanje override __init__metode . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 10.1 Primjer formatiranja numeriˇckih podataka sa tupleom i dictionaryjem . . . . . Izvorni kod 10.2 Primjer formatiranja numeriˇckih podataka sa tupleom i dictionaryjem . . . . . Izvorni kod 10.3 Primjer formatiranja numeriˇckih podataka za ispis u stupcima . . . . . . . . . Izvorni kod 11.1 Primjer kreiranja tekstualne datoteke . . . . . . . . . . . . . . . . . . . . . . . . gfx/RadSaDatotekama/info.txt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . gfx/RadSaDatotekama/test.txt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ˇ Izvorni kod 11.2 Citanje sadržaja tekstualne datoteke . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 11.3 Pristupanje sadržaju datoteke preko iteriranja po file objektu . . . . . . . . . gfx/RadSaDatotekama/test.txt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 11.4 Dohva´canje trenutne pozicije u datoteci . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 11.5 Kopiranje, micanje i preimenovanje datoteka . . . . . . . . . . . . . . . . . . . . Izvorni kod 12.1 Primjer mjerenja vremena izvršavanje algoritma . . . . . . . . . . . . . . . . . . ¯ Izvorni kod 12.2 Primjer upotrebe Timer klase za mjerenje vremena izvodenja funkcije . . . . . Izvorni kod 13.1 Upotreba dbg modula . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 14.1 Spremanje elemenata dijagonale matrice u vektor . . . . . . . . . . . . . . . . . Izvorni kod 15.1 Osnovne informacije o NumPy polju . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 16.1 Mijenjanje dimenzija polja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 16.2 Mijenjanje dimenzija polja . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 16.3 Transponiranje matrica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 17.1 Sadržaj datoteke data.txt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 17.2 Uˇcitavanje iz tekstualne datoteke . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 18.1 Rješavanje sustava linearnih jednadžbi . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 19.1 Jednostavan graf . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 19.2 Kontrola linija i markera . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 19.3 Naprednija kontrola linija i markera . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 19.4 Prikaz legende na grafu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 19.5 Primjer crtanja podgrafova . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 19.6 Primjer crtanja grafa u polarnom koordinatnom sustavu . . . . . . . . . . . . . Izvorni kod 20.1 Primjer vizualizacije izolinija . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 21.1 Jednostavan primjer animacije . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 22.1 Primjer pronalaženja nultoˇcke funkcije metodom biskecije . . . . . . . . . . . . Izvorni kod 22.2 Primjer pronalaženja nultoˇcke funkcije metodom tangente . . . . . . . . . . . . Izvorni kod 23.1 Primjer razliˇcitih 1D interpolacija . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 23.2 Primjer linearne i kubiˇcne 2D interpolacije . . . . . . . . . . . . . . . . . . . . . Izvorni kod 24.1 Primjer linearne regresije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . gfx/RjesavanjeSustavaLinJed/A.txt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . gfx/RjesavanjeSustavaLinJed/B.txt . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 25.1 Primjer naivne Gaussove eliminacije . . . . . . . . . . . . . . . . . . . . . . . . . Izvorni kod 25.2 Primjer LU dekompozicije . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ¯ Izvorni kod 26.1 Primjer raˇcunanja odredenog inegrala pomo´cu trapezne formule . . . . . . . .
8 9 16 20 23 25 26 26 27 29 29 29 29 30 30 31 32 33 34 34 34 35 35 37 42 42 43 44 44 46 47 48 49 50 53 54 54 57 58 58 59 59 59 59 60 62 63 68 74 77 79 79 80 81 81 83 87 89 91 97 97 98 103 105 110 112 115 116 119 123 123 124 124 128
ix
x
Popis izvornog koda
Izvorni kod 26.2 Izvorni kod 26.3 Izvorni kod 27.1 Izvorni kod 28.1 Izvorni kod 29.1 Izvorni kod 31.1 Izvorni kod 32.1 Izvorni kod 34.1 Izvorni kod 34.2 Izvorni kod 35.1 Izvorni kod 36.1 Izvorni kod 37.1 Izvorni kod 38.1
Upotreba Simpsonove 1/3 formule . . . . . . . . . . . . . . . . . . . . Numeriˇcko integriranje pomo´cu quad funkcije . . . . . . . . . . . . . . Primjer rješavanja obiˇcnih diferencijalnih jednadžbi 1. reda. . . . . . . Strujanje u pravokutnom kanalu . . . . . . . . . . . . . . . . . . . . . . Rješavanje elastiˇcne linije savijanja . . . . . . . . . . . . . . . . . . . . . Rješavanje problema progiba ploˇce pomo´cu metode konaˇcnih razlika ¯ Primjer rješavanje provodenja topline kroz štap pomo´cu metode linija Primjer rješavanja LP problema pomo´cu modula PuLP . . . . . . . . . Rješavanje problema transportnog zrakoplova . . . . . . . . . . . . . . Primjer 2D optimizacije Nelder-Mead metodom . . . . . . . . . . . . . Primjer simuliranog kaljenja pomo´cu modula inspyred . . . . . . . . . Particle Swarm Optimization na primjeru Rastrigin funkcije . . . . . . Optimizacija Rastrigin funkcije pomo´cu DEAP modula . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
. . . . . . . . . . . . .
130 131 135 143 148 154 158 166 168 173 177 182 186
INDEKS
%, 53
funkcije, 33
alpha, 103 Amoeba, 171 and, 20 anonimne funkcije, 36 append, 15, 80 arange, 72 aritmetiˇcki operatori, 19 array, 71 as, 9 atributi, 42
GA, 185 genetiˇcki algoritmi, 185 genfromtxt, 82 globalni atributi, 42 grid, 96 griddata, 116
bisect, 109 bisekcija, 109 break, 30 brent, 112 Brentova metoda, 112 bvp1lg, 148 capitalize, 14 center, 14 class, 42, 45–47, 49 clock, 62 close, 57 closure, 36 cmath, 61 coding, 8 color, 90 colormap, 101 continue, 31 contour, 101 contourf, 101 copy, 60 count, 13, 15 datoteke, 57 DEAP, 186 debug, 65, 67 decimal, 62 decode, 14 def, 33 del, 11, 15 delete, 80 diag, 74 dpi, 92 draw, 99 easy_install, 4 elastiˇcna linija, 147 elif, 27 Eliptiˇcke parcijalne diferencijalne jednadžbe, 153 else, 26, 30 encode, 14 endswith, 13 error, 66 Euler-Bernoullijeva jednadžba, 147 Eulerova metoda, 135 evolucijski algoritmi, 185 exception, 66 expandtabs, 13 extend, 15 eye, 74 figsize, 92 figure, 92 file, 57 find, 13 flatten, 79 for, 29 format, 55 from, 9
hidrauliˇcki skok, 142 id, 21 if, 25 import, 8 in, 21 index, 13, 15 input, 24 insert, 15, 80 inspyred, 182 integriranje, 127 interp1d, 115 interp2d, 116 interpolacija, 115 is, 21 is not, 21 isalnum, 14 isalpha, 14 isdigit, 14 islower, 14 isspace, 14 istitle, 14 isupper, 14 izolinije, 101 join, 14 Kate, 6 label, 91 lambda, 36 lambda funkcije, 36 legend, 96 legenda, 96 len, 15 linearno programiranje, 165 linspace, 72 list, 14 ljust, 14 loadtxt, 81 logicki operatori, 20 lower, 14 lstrip, 14 LU dekompozicija, 124 M krivulje, 143 Manningov koeficijent trenja, 139 Manningova formula, 138, 139 mapa boja, 101 marker, 90 markeredgecolor, 90 markeredgewidth, 90 markerevery, 90 markerfacecolor, 90 markerfacecoloralt, 90 markersize, 90 math, 61 matrica sustava, 83 meshgrid, 75, 101 metoda Gaussove eliminacije, 123 metoda linija, 157 metoda sekante, 112 metoda tangente, 111 metode, 44 modul, 8
xi
xii
INDEKS
move, 60 naslov, 96 ndarray, 71 ndim, 77 Nelder-Mead metoda, 171 nestacionarno strujanje, 137 neuniformno strujanje, 137 newton, 111 Newton-Raphsonova metoda, 111 Newtonova metoda, 111 normalna dubina, 140 not, 20 not in, 21 objektni atributi, 43 objektno orijentirano programiranje, 41 odeint, 135 ones, 73 ones_like, 73 open, 57 open channel flow, 137 operatori dodjeljivanja, 20 or, 20 otvoreni vodotok, 137 Parcijalne diferencijalne jednadžbe, 151 Particle Swarm Optimization, 181 partition, 14 pdb, 65, 67 perimetar, 137 pip, 4 plot, 87 pop, 15 print, 23 printf, 23 prozirnost, 103 PSO, 181 PuLP, 166 PyDev, 5
S krivulje, 143 savetxt, 82 secant, 112 seek, 59 set, 18 setuptools, 4 shape, 77 show, 87 shutil, 60 simboli, 8 simps, 130 Simpsonova pravila, 129 Simpsonove formule, 129 simulated annealing, 177 simulirano kaljenje, 177 size, 77 skupovi, 18 solve, 83 sort, 15 spines, 94 spline interpolacija, 115 split, 14 splitlines, 14 Spyder, 5 squeeze, 79 stacionarno strujanje, 137, 138 startswith, 13 strip, 14 subplot, 97 sustav linearnih jednadžbi, 123 swapcase, 14 tell, 59 time, 62 Timer, 63 title, 14, 96 translate, 13 trapezna formula, 127 trapz, 127 trim_zeros, 80 type, 12
quad, 130 range, 15 ravel, 79 raw_input, 24 read, 58 readline, 58 readlines, 58 regresija, 119 rekurzija, 37 rekurzivne funkcije, 37 relacijski operatori, 19 remove, 15 rename, 60 replace, 13 reshape, 79 resize, 80 return, 34 reverse, 15 rfind, 13 rindex, 13 rjust, 14 rpartition, 14 rsplit, 14 rstrip, 14 Runge-Kutta metode, 135
ugnježdena definicija funkcije, 36 uniformno strujanje, 137, 140 unique, 80 upper, 14 vektor slobodnih cˇ lanova, 83 Vrijeme izvršavanja, 62 while, 30 write, 57 writelines, 57 xlabel, 92 xlim, 92 xticks, 93 ylabel, 92 ylim, 92 yticks, 93 zeros, 73 zeros_like, 73 zfill, 14
ACRONYMS
DRY
Don’t Repeat Yourself
API
Application Programming Interface
UML
Unified Modeling Language
xiii
Dio I OSNOVE PYTHONA Python je skriptni programski jezik op´ce namjene.
1
UVOD
Zašto Python? Postoje mnogi razlozi zašto odabrati Python kao inženjerski alat ? Odliˇcan za poˇcetnike a istodobno mo´can za struˇcnjake ? Skalabilan, pogodan za velike projekte, kao i one male ? Omogu´cuje brz razvoj ? Cross-platform, omogu´cuje razvoj i izvršavanje koda na gotovo svim platformama i arhitekturama ? Ugradiv u kodove pisane u drugim programskim jezicima ? Proširiv sa drugim programskim jezicima ? Objektno orjentiran ? Uredna i elegantna sintaksa ? Stabilan ? Bogatstvo dostupnih paketa i biblioteka ? Specijelizirani paketi za numeriku, statistiku, obradu podataka i vizualizacije ? Otvoreni besplatni kod koji održava velika zajednica programera i znanstvenika 1.1 1.1.1
instalacija Instalacija na Linux platformi
Gotovo sve Linux distribucije sadže Python pakete u osnovnim repozitorijima, ali i v´cina distribucija ima inicijalno instaliran Python. Na openSUSE distribuciji, Python se može instalirati jednostavnom naredbom: sudo zypper in python
Nakon instalacije Pythona, možemo provjeriti koja je putanja python izvršne datoteke user@machine:~> type python python is /usr/bin/python
1.1.2
Instalacija na Windows platformi
Za instalaciju Pythona na Windows platformi potrebno je preuzeti instalacijsku datoteku sa http://www.python.org. Nakon preuzimanja, pokretanjem insta¯ lacijske datoteke zapoˇcinje isntalacijki program koji omogu´cuje uredivanje postavki Python instalacije. Uobiˇcajena je instalacija Pythona zajedno sa dodatnim paketima, na Windows platformi, preko neke od dostupnih Python distribucija (vidi poglavlje 1.2.2.1).
3
4
uvod
1.2
dodatni paketi
Velika snaga Pythona je dostupnost velikog broja paketa raznih namjena. Za inženjerske potrebe, potrebni su dodatni paketi koji omogu´cavaju matriˇcni raˇcun, numeriˇcke metode, statistiˇcku obradu podataka, vizualizacije, izradu animacija i druge specijalizirane mogu´cnosti. Osnovni paketi, koji c´ e biti korišteni u ovoj skripti, su: ? Numpy (http://www.numpy.org/), ? SciPy (http://www.scipy.org), ? matplotlib (http://matplotlib.org/) i ? IPython (http://ipython.org/). Za instalaciju dodatnih python paketa postoje alati za upravljanje Python paketima. Najpoznatiji su easy_install, koji dolazi sa ve´cinom Python distribucija te pip. pip se može instalirati pomo´cu easy_install-a: user@machine:~> sudo easy_install pip
1.2.1
Dodatni paketi na Linux platformi
Za instalaciju dodatnih paketa na openSUSE distribuciji pokrenite naredbu: user@machine:~> sudo zypper in python-numpy python-scipy \\ python-matplotlib IPython
1.2.2 1.2.2.1
Dodatni paketi na Windows platformi Python distribucije
Python distribucije su objedinjane instalacije pythona, raznih dodatnih paketa te cˇ esto i tekstualnih editora ili razvoijnih okruženja. Distribucije su ve´cinom ciljane za Windows platformu zbog nepraktiˇcne višestruke instalacije svakog pojedinog softwarea. Neke od najpopularnijih Python distribucija su: ? pythonxy (http://code.google.com/p/pythonxy/) ? ActivePython (http://www.activestate.com/activepython) ? Entought Python (http://www.enthought.com/python/) ? winpython (http://code.google.com/p/winpython/) ? PortablePython (http://portablepython.com/) 1.2.3
Instalacija pomo´cu upravitelja paketa
Python upravitelji paketa omogu´cuju jednostavno instalaciju, osvježavanje ili deinstalaciju raznih Python paketa. Iako upravitelji paketa nisu dio Pythona, cˇ esto bar jedan upravitelj dolazi sa osnovnom instalacijom Pythona. Valja izdvojiti dva upravitelja python paketa: ? setuptools https://pypi.python.org/pypi/setuptools ? pip https://pypi.python.org/pypi/pip
1.3 editori i razvojna okruženja
5
Primjer instalacije paketa pomo´cu upravitelja setuptools sa naredbom easy_install: user@machine:~> sudo easy_install ime_paketa
Primjer instalacije paketa sa naredbom pip: user@machine:~> sudo pip install ime_paketa
1.3
editori i razvojna okruženja
Python koristi pokre´ce kod iz obiˇcnih tekstualnih datoteka koje je mogu´ce ¯ uredivati u mnogim tekstualnim editorima. Razvojna okruženja (eng. Integrated Development Environment, IDE), osim ¯ što omogu´cavaju uredivanje koda, sadrže niza alata za lakši i brži razvoj kao što su jednostavno pokretanje koda iz IDE-a, debug-iranje koda, pra´cenje ispisa i dr. 1.3.1
Spyder
Spyder (http://code.google.com/p/spyderlib/) je interaktivno razvojno okruženje za Python namjenjeno za znastvenu i inženjersku primjenu. Spyder je dostupan za ve´cinu platformi.
Slika 1.1: Spyder razvojno okruženje
1.3.2
PyDev
PyDev (http://pydev.org/) je dodatak za Eclipse (http://www.eclipse.org/) razvojno suˇcelje koji nudi mogu´cnosti za rad sa Pythonom.
6
uvod
1.3.3
Kate
Kate (http://kate-editor.org/) je mo´can tekstualni editor, iako radi i na Windows platformi, primarno je namjenjen za Linux platformu. Na openSUSE-u, Kate se može instalirati naredbom: user@machine:~> sudo zypper in kate
Slika 1.2: Kate tekstualni editor
2
PYTHON LJUSKA I .PY SKRIPTE
Python je interpretirani jezik, a jednostavni Python izrazi mogu se izvoditi u interaktivnom programskom okruženju pod nazivom ljuska. 2.1
pokretanje pythona
Najjednostavniji naˇcin za otvaranje Python ljuske (eng. shell) na Windows platformi je pokrenuti IDLE, dok je ne Linux platformi dovoljno pokrenuti Python naredbu u terminalu/konzoli. Nakon pokretanja Pythona prikazuju se osnovne informacije o Pythonu (verzija) te tzv. prompt koji je simboliziran sa tri strelice u desno (> > >). user@machine:~> python Python 2.7.3 (default, Apr 14 2012, 08:58:41) [GCC] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>>
2.2
python ljuska kao kalukulator
Python ljuska odmah izvršava unešene naredbe nakon pritiska na tipku Enter (Return). Najjednostavniji Python izrazi su matematiˇcke operacije pomo´cu kojih možemo koristiti Python ljusku kao kalkulator. Izraˇcun te ispis rezultata matematiˇckih izrazi dešava se u novom retku terminala ili IDLE-a: >>> 1+1 2 >>>
¯ Matematiˇcke operacije, naravno, možemo medusobno kombinirati i pri tome koristiti zagrade za definiranja redoslijeda operacija. >>> 1/5 0 >>> 1./5. 0.2 >>> 1./(5.+2) 0.14285714285714285 >>>
Ljuska može raditi i baziˇcne operacije sa tekstom tj. nizovima znakova (string). >>> "Kratki " + "probni " + "tekst." ’Kratki probni tekst.’ >>>
2.3
python skripte
Python skripte su tekstualne datoteke s ekstenzijom *.py koje sadrže Python kod. Izvršavanje .py skripte, zapravo, se pokre´ce linija po linija kao da se je unosi u Python ljusku. Ovo je oˇcita prednost, pogotovo prilikom pokretanja više od nekoliko naredbi. Datoteke sa ekstenzijom .py, osim kao skripte, koriste se i za definiranje vlastitih modula što je detaljnije opisano u poglavlju 2.4.
7
Oprez! Prilikom dijeljenja cijelih brojeva rezultat je cijeli broj! Kod decimalnih brojeva obavezno koristiti decimalnu toˇcku.
python ljuska i .py skripte
8
Osnovni naˇcin pokretanja python skripte je pokretanje Pythona sa specificiranim .py fajlom: user@machine:~$ python imeskripte.py
Nakon završetka ¯ izvodenja skripte pomo´cu python skripta.py Python se gasi!
Python c´ e se pokrenuti i izvršiti kod zapisan u skripti. Ako je prva linija skripte: 1
#!/usr/bin/python
tada se na Unix sustavima može izvršavati u terminalu. Za pokretanje skripte u terminalu nužno je da skripta koristi Unix oznaku za kraj reda te da ima dozvole za izvršavanje: user@machine:~$ chmod +x imeskripte.py
Ako je .py datoteka izvršna, tada se može direktno izvršavati: user@machine:~$ ./imeskripte.py
Na Windows sustavima datoteke s ekstenzijom *.py su kod intalacije Pythona pridružene programu python.exe. Python skripta se pokre´ce dvostrukim lijevim klikom miša na skriptu. 2.3.1
Upotreba posebnih znakova
Da bi se koristilo posebne znakove (npr. slova sa kvaˇcicama ili simboli) u stringovima, potrebno je u prvoj ili drugoj liniji skripte upisati poseban komentar: # -*- coding: utf-8 -*-
Izvorni kod 2.1: Podrška za posebne znakove u Python skriptama 1 2
#!/usr/bin/python # -*- coding: utf-8 -*-
3 4 5
print ’Sada možemo koristi slova sa kvaˇ cicama!’ print ’Ali i razne simbole kao što su ◦ & $’
2.4
moduli
¯ Modul je Python objekt, definiran u odredenoj datoteci, koji sadrži defini¯ cije varijabli, funkcija i klasa. Obiˇcno su varijable, funkcije i klase odredenog modula specijalizirane namjene, pa se module može interpretirati kao grupiranje koda i najˇceš´ce je taj kod sliˇcne namjene. ¯ u poglavlju 12.2) sadrži varijable pi i e koje Npr. modul math (obraden predstavljaju matematiˇcke konstante te niz matematiˇckih funkcija kao što su sqrt, log, pow, exp, sin, cos itd. ¯ Da bi se objekti odredenog modula mogli koristiti u kodu, potrebno je ¯ uˇcitati (importirati) modul ili uˇcitati odredeni objekt iz modula. Uˇcitavanje modula vrši se pomo´cu naredbe import cˇ ija je osnovna sintaksa import module_name
gdje je module_name ime modula. Nakon što je modul uˇcitan, može se koristiti objekte modula (varijable, funkcija i klase) tako da se unese ime modula, toˇcka te ime objekta koji se želi koristiti. Jednom naredbom import može se uˇcitati više modula na slijede´ci naˇcin:
2.4 moduli
import module1, modul2, modul3
Uˇcitanom modulu se može dodijeliti novo ime. To se može napraviti pomo´cu kljuˇcne rijeˇci as: import module_name as new_name
nakon cˇ ega se modul može koristiti pomo´cu novog imena. Moduli cˇ esto sadržavaju velik broj objekata, a njihovim uˇcitavanjem bespotrebno se troše memorijski i procesorski resursi. Kako bi se izbjeglo uˇcita¯ ¯ vanje cijelog modula, mogu´ce je iz odredenog modula uˇcitati samo odredene objekte: from module_name import object_name
Ako se direktno uˇcita objekte iz modula, tada ih se koristiti samo preko imena objekta. Kao i sam modul, mogu´ce je uˇcitati objekt nekog modula pod novim imenom: from module_name import object_name as object_new_name
¯ Za uˇcitavanje svih objekata odredenog modula koristi se: from module_name import *
Izvorni kod 2.2: Korištenje objekata modula 1
#!/usr/bin/python
2 3 4 5 6
# importiraj sys modula import sys print sys.platform # ispisi platformu (operaticni sustav) print sys.version # ispisi verziju Pythona
7 8 9 10 11
# importiraj modul math kao m import math as m print m.pi # ispisi vrijednost broja pi print m.sin(m.pi/2.0) # ispisi vrijednost sinusa kuta pi/2
12 13 14 15
# iz modula datetime importiraj objekt date from datetime import date print date.today() # ispisi danasnji datum
16 17 18 19
# iz modula random importiraj funkciju random kao nasumicni from random import random as nasumicni print nasumicni() # ispisi nasumicni broj
20 21 22 23 24 25
# Importiraj sve objekte iz modula string from string import * print uppercase # ispis svih velikih slova print lowercase # ispis svih velikih slova print digits # ispis svih znamenaka linux2 2.7.3 (default, Apr 14 2012, 08:58:41) [GCC] 3.14159265359 1.0 2013-03-05 0.952486831091 ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789
9
3
T I P O V I P O D ATA K A
Varijable se ne moraju explicitno deklarirati. Naime, deklaracija se dešava prilikom pridruživanja vrijednosti varijabli. Odnosno, varijable se pridružuju memorijskim lokacijama na kojima je zapisana vrijednost. Znak jednakosti = se koristi za pridruživanje vrijednosti varijablama. Na primjer: 1
#!/usr/bin/python
2 3 4 5
brojac duljina ime
= 100 # Integer = 1000.0 # Float = ’Hrvoje’ # String
6 7 8 9
print brojac print duljina print ime
Ovdje su 100, 1000.0 i Hrvoje vrijednosti pridružene varijablama brojac, duljina i ime. Program c´ e producirati sljede´ci rezultat: 100 1000.0 Hrvoje
Mogu´ce je pridružiti jednu vrijednost u više varijabli. Tada sve varijable gledaju na istu memorijsku lokaciju. Odnosno: 1 2 3 4
#!/usr/bin/python a = b = c = 1 c = 5 print a
što rezultira 1
Varijable a, b ic gledaju na istu lokaciju u memoriji u kojoj piše 1. Brojevi su imutable varijable odnosno nepromjenjive pa kada promijenimo c=5 Python preusmjerava varijablu c na novu lokaciju u memoriji na kojoj piše broj 5, ¯ je mogu´ce a varijable a, b i dalje gledaju na isto mjesto kao i prije. Takoder pridružiti više vrijednosti u više varijabli. 1 2
#!/usr/bin/python a, b, c = 1, 2, ’Hrvoje’
Varijablama a i b se pridružuju memorijske lokacije na kojima su zapisane vrijednosi 1 i 2, dok je varijabli c pridružena memorijska lokacija na kojoj je zapisana vrijednost Hrvoje. Varijable te njihov memorijski prostor mogu´ce je pobrisati naredbom del. >>> a = 10 >>> print a 10 >>> del a >>> print a Traceback (most recent call last): File "
", line 1, in NameError: name ’a’ is not defined >>> b = c = 2 >>> print b, c 2 2 >>> del b
11
12
tipovi podataka
>>> print b, c Traceback (most recent call last): File "", line 1, in NameError: name ’b’ is not defined >>> print c 2
Python podržava pet osnovnih tipova podataka; ? Numbers ? String ? List ? Tuple ? Dictionary ¯ Tip podataka odredene varijable može se dobiti naredbom type: >>> a=10 >>> b=11.2 >>> c=’Rijeka’ >>> type(a), type(b), type(c) (, , )
3.1
brojevi
To su nepromjenjivi(immutable) tipovi podataka, odnosno promjena vrijednosti rezultira novim alociranim objektom. Numeriˇcki tip podatka se kreira pridruživanjem vrijednosti varijabli. Odnosno 1 2 3
#!/usr/bin/python var1 = 1 var2 = 10
¯ je mogu´ce pobrisati referencu na numeriˇcki objekt koriste´ci del Takoder naredbu. Sintaksa izgleda ovako: del var1[,var2[,var3[....,varN]]]]
Primjer: 1 2 3
#!/usr/bin/python del var del var_a, var_b
Python podržava cˇ etiri numeriˇcka tipa ? int ? long ? float ? complex Nekoliko primjera oznaˇcavanja numeriˇckih podataka ja prikazana u Tablici 3.1. Mogu´ce je koristiti i malo slovo L za oznaku long, iako se takvo oznaˇcavanje ne preporuˇca zbog velike sliˇcnosti sa brojem 1.
3.2 string
int
long
float
complex
10
51924361L
0.0
3.14j
100
-0x19323L
15.20
45.j
-783
0122L
-21.9
9.322e-36j
-0490
0xDEFABCECBDAECBFBAEl
-90.
.876j
-0x260
535633629843L
-32.54e100
.6545+0J
0x69
-052318172735L
70.2-E12
4.53e-7j
13
Tablica 3.1: Primjeri oznaˇcavanja brojeva
3.2
string
¯ navodnika, jednostrukih Stringovi su definirani kao slijed znakova izmedu (apostrofi) ili dvostrukih. Jednom zadane stringove je nemogu´ce mijenjati jer su stringovi, u Pythonu, nepromjenjivi (imutable) tip podatka. Niz funkcija koje rade promjene nad string varijabama zapravo kreiraju kopije izvorne string varijable. Dijelove stringova (znakove ili niz znakova - string) je mogu´ce dohvatiti operatorima [] i [:] sa indeksima koji poˇcinju od 0 na poˇcetku stringa sve do -1 na kraju. Znak plus (+) oznaˇcava spajanje (concatenation), a asterisk (∗) je operator ponavljanja. Odnosno: 1
#!/usr/bin/python
2 3 4
str = ’Hello World!’ ime = "Rudi"
# zadavanje sa jednostrukim navodnicima # zadavanje sa dvostrukim navodnicima
print print print print print print
# # # # # #
5 6 7 8 9 10 11
str, ime str[0] str[2:5] str[2:] str * 2 str + ’TEST’
print print print print print print
cijelog stringa prvog znaka u stringu od treceg do petog znaka znakova od treceg do zadnjeg stringa dva puta concatenated string
Što c´ e rezultirati Hello World! Rudi H llo llo World! Hello World!Hello World! Hello World!TEST
Nad stringovima je mogu´ce izvoditi niz specijaliziranih operacija pomo´cu funkcija koje su dostupne za varijable tipa string. Funkcije za pretraživanje stringova: count(sub[, start[, end]]) endswith(suffix[, start[, end]]) find(sub[, start[, end]]) index(sub[, start[, end]]) rfind(sub [,start [,end]]) rindex(sub[, start[, end]]) startswith(prefix[, start[, end]])
Funkcije za mjenjanje znakova: expandtabs([tabsize]) replace(old, new[, count]) translate(table[, deletechars])
Iako je mogu´ce definirati string sa jednostrukim i dvostrukim navodnicima, preporuka je da se koriste jednostruki navodnici.
14
tipovi podataka
Funkcije za provjeru vrste znakova: isalnum() isalpha() isdigit() isspace()
Funkcije za rad sa velikim i malim slovima: capitalize() islower() istitle() isupper() lower() swapcase() title() upper()
Funkcije za poravnanje teksta: center(width[, fillchar] ljust(width[, fillchar]) rjust(width[, fillchar]) zfill(width)
Funkcije za spajanje i razdvajanje stringova: join(seq) partition(sep) rpartition(sep) split([sep [,maxsplit]]) splitlines([keepends]) rsplit([sep [,maxsplit]])
Funkcije za brisanje poˇcetnih i krajnjih znakova: lstrip([chars]) rstrip([chars]) strip([chars])
Funkcije za encoding stringova: decode([encoding[, errors]]) encode([encoding[,errors]])
3.3
Iako lista može biti heterogena (sadržavati razliˇcite tipove podataka), preporuka je koristiti listu kao spremnik homogenih podataka. Za heterogene podatke se preporuˇca tuple (poglavlje 3.4)
liste
¯ Lista sadrži podatke odvojene zarezima i omedene uglatim zagradama. Iako je sliˇcna listama u C jeziku, podaci python liste mogu biti razliˇcitog tipa. Kao i kod stringova, pristupanje vrijednostima u listi je mogu´ce pomo´cu operatora [ ] i [ : ] sa indeksima koji poˇcinju od 0 na poˇcetku stringa sve do -1 na kraju. Znak plus (+) se koristi za operator spajanja (concatenation) stirngova, a asterisk (∗) je operator ponavljanja 1
#!/usr/bin/python
2 3 4
list = [ ’abcd’, 786 , 2.23, ’hrvoje’, 70.2 ] tinylist = [123, ’hrvoje’]
5 6 7 8 9 10 11
print print print print print print
list # list[0] # list[1:3] # list[2:] # tinylist * 2 # list + tinylist
Što c´ e rezultirati
print cijele liste print prvog elementa liste print od drugog do treceg elementa liste print od treceg do zadnjeg elementa print liste dva puta # print concatenated lists
3.3 liste
[’abcd’, 786, 2.23, ’hrvoje’, 70.2] abcd [786, 2.23] [2.23, ’hrvoje’, 70.2] [123, ’hrvoje’, 123, ’hrvoje’] [’abcd’, 786, 2.23, ’hrvoje’, 70.2, 123, ’hrvoje’]
Za manipulaciju listama cˇ esto se koristi naredba len za provjeru broja elemenata liste, naredbom insert se ume´ce novi element u listu te naredba del kojom se brišu pojedini elementi iz liste. 1
#/user/bin/python
2 3 4 5 6 7 8 9
list = [2,3,4,5] print(len(list)) #broj elemnata u listi print list list.insert(0,1) #umetanje elementa 1 u listu na prvu poziciju print list del list[-1] #brisnje zadnjeg elementa iz liste print list 4 [2, 3, 4, 5] [1, 2, 3, 4, 5] [1, 2, 3, 4]
Naredbom range mogu´ce je stvoriti listu brojeva u aritmetiˇckom nizu što je cˇ esto potrebno kod korištenja for petlje (poglavlje 7.1). Sintaksa naredbe range je range(stop), range(start, stop), range(start, stop, step),
gdje je start prvi element, stop je gornja granica i step je korak aritmetickog niza. 1
#/user/bin/python
2 3 4 5 6 7 8
list=range(7) # aritmeticki niz 0,..,6 print list list = range(2,7) # aritmeticki niz 2,..,6 print list list = range(0,7,2) # aritmeticki niz s korakom 2 print list [0, 1, 2, 3, 4, 5, 6] [2, 3, 4, 5, 6] [0, 2, 4, 6]
Naredbe za dodavanje elemenata u listu su: append(x) insert(i, x) extend(L)
append dodaje element x na kraj liste, insert ubacuje element x na poziciju i a extend proširuje postoje´cu listu sa listom L.
Naredbe za brisanje elemenata iz liste su: remove(x) pop(i) del L[index]
remove briše prvi element koji ima vrijednost x a pop briše element na poziciji i. Naredba del L[index] briše element list L na indeksu index. Osim funkcija za brisanje i dodavanje elemenata, Python liste imaju još ¯ ugradenih praktiˇcnih funkcija. index vra´ca indeks prvog elementa koji ima
15
16
tipovi podataka
vrijednost x, count prebrojava sve elemente koji su jednaki x, sort sortira ¯ elemente liste a reverse rasporeduje elemente u obrnutom redosljedu od inicijalnog. index(x) count(x) sort() reverse()
Izvorni kod 3.1: Dodavanje i brisanje elemenata liste 1 2
ljudi = [’Marko’, ’Mirela’, ’Luka’] nadljudi = [’Chuck’,’Arnold’,’Steven’,’Silvester’]
3 4 5 6 7 8 9
ljudi.append(’Igor’) print ljudi nadljudi.insert(1,’Anita’) print ljudi nadljudi.extend(ljudi) print nadljudi
10 11 12 13 14 15 16
nadljudi.pop(1) print nadljudi nadljudi.remove(’Igor’) print nadljudi del nadljudi[4:] print nadljudi
17 18 19 20
print ljudi.index(’Marko’) ljudi.append(’Marko’) print ljudi.count(’Marko’)
21 22 23 24 25
nadljudi.sort() print nadljudi nadljudi.reverse() print nadljudi [’Marko’, ’Mirela’, ’Luka’, ’Igor’] [’Marko’, ’Mirela’, ’Luka’, ’Igor’] [’Chuck’, ’Anita’, ’Arnold’, ’Steven’, ’Silvester’, ’Marko’, ’Mirela’, ’Luka’, ’Igor’] [’Chuck’, ’Arnold’, ’Steven’, ’Silvester’, ’Marko’, ’Mirela’, ’Luka’, ’Igor’] [’Chuck’, ’Arnold’, ’Steven’, ’Silvester’, ’Marko’, ’Mirela’, ’Luka’] [’Chuck’, ’Arnold’, ’Steven’, ’Silvester’] 0 2 [’Arnold’, ’Chuck’, ’Silvester’, ’Steven’] [’Steven’, ’Silvester’, ’Chuck’, ’Arnold’]
3.4
tuple
Tuple je tip podatke sliˇcan listi. Sastoji se od vrijednosti odvojenih zarezom ¯ i za razliku od listi omeden zagradama (). Python dopušta fleksibilnost izostavljanja zagrada prilikom definiranja tuplea. Postoji mnogo sliˇcnosti sa listama, ali i nekoliko temeljnih razlika: ? pristupanje elementima liste i tuplea vrši se na identiˇcan naˇcin (preko indeksa) ? i list i tuple su iterabilni ? lista može mijenjati broj elemenata i vrijednosti elemenata, dok tuple ne može
3.5 dictionary
? nad tupleom se ne mogu provoditi operacije koje mjenjaju sam tuple (sort, remove i sl.) 1
#!/usr/bin/python
2 3 4
tuple = ( ’abcd’, 786 , 2.23, ’hrvoje’, 70.2 tinytuple = (123, ’hrvoje’)
)
5 6 7 8 9 10 11
print print print print print print
tuple tuple[0] tuple[1:3] tuple[2:] tinytuple * 2 tuple + tinytuple
# # # # # #
print liste prints prvog elementa liste print od drugog do treceg elementa liste print od treceg do zadnjeg elementa print liste dva puta print liste nastale spajanjem dvije liste
12 13 14
istotuple = 2, True, ’teskt’ print istotuple
# Zadavanje tuplea bez zagrada
Što c´ e rezultirati (’abcd’, 786, 2.23, ’hrvoje’, 70.200000000000003) abcd (786, 2.23) (2.23, ’hrvoje’, 70.200000000000003) (123, ’hrvoje’, 123, ’hrvoje’) (’abcd’, 786, 2.23, ’hrvoje’, 70.200000000000003, 123, ’hrvoje’) (2, True, ’teskt’)
Sljede´ci kod c´ e producirati grešku u liniji 5, jer smo pokušali promijeniti vrijednost u tuple-u 1
#!/usr/bin/python
2 3 4 5 6
tuple = ( ’abcd’, 786 , 2.23, ’hrvoje’, 70.2 ) list = [ ’abcd’, 786 , 2.23, ’hrvoje’, 70.2 ] tuple[2] = 1000 # greska list[2] = 1000 # ok
Tuple se vrlo cˇ esto koristi za višestruko dodjeljivanje: >>> a, b, c = 3, 10, ’neki tekst’ >>> print a 3 >>> print b 10 >>> print c neki tekst
što se cˇ esto koristi prilikom vra´canja više vrijednosti iz funkcije (poglavlje 8.2) 3.5
dictionary
Dictionary možemo smatrati jednostavnim pridruživanjem odnosno preslikavanjem svih elemenata jednog skupa elementima drugog skupa. 1
#!/usr/bin/python
2 3 4 5
dict = {} dict[’jedan’] = ’Ovo je jedan’ dict[2] = ’Ovo je dva’
6 7
tinydict = {’ime’: ’hrvoje’,’code’:6734, ’odjel’: ’admin’}
8 9 10 11
print dict[’jedan’] print dict[2] print tinydict
# print vrijednosti ’jedan’ # print vrijednosti za 2 # print cijelog dictionary
17
18
tipovi podataka
12 13
print tinydict.keys() # print svih kljuceva print tinydict.values() # print svih vrijednosti
Što c´ e rezultirati Ovo je jedan Ovo je dva {’odjel’: ’admin’, ’code’: 6734, ’ime’: ’hrvoje’} [’odjel’, ’code’, ’ime’] [’admin’, 6734, ’hrvoje’]
Objekti tipa dict nemaju poredane elemente. 3.6
skupovi
>>> basket = [’apple’, ’orange’, ’apple’, ’pear’, ’orange’, ’banana’] >>> fruit = set(basket) # create a set without duplicates >>> fruit set([’orange’, ’pear’, ’apple’, ’banana’]) >>> ’orange’ in fruit # fast membership testing True >>> ’crabgrass’ in fruit False >>> # Demonstrate set operations on unique letters from two words ... >>> a = set(’abracadabra’) >>> b = set(’alacazam’) >>> a # unique letters in a set([’a’, ’r’, ’b’, ’c’, ’d’]) >>> a - b # letters in a but not in b set([’r’, ’d’, ’b’]) >>> a | b # letters in either a or b set([’a’, ’c’, ’r’, ’d’, ’b’, ’m’, ’z’, ’l’]) >>> a & b # letters in both a and b set([’a’, ’c’]) >>> a ^ b # letters in a or b but not both set([’r’, ’d’, ’b’, ’m’, ’z’, ’l’])
4
O P E R AT O R I
Operatori su osnovni dio Pythona i omogu´cuju operacije na varijablama (operandima). Najˇceš´ce se povezuju sa algebarskim matematiˇckim operaci¯ jama, medutim operatori mogu biti i “ne matematiˇcke” naravi. Python operatore možemo podjeliti prema namjeni: ? Aritmetiˇcki operatori ¯ ? Relacijski operatori ili operatori usporedivanja ? Operatori dodjeljivanja ? Logiˇcki operatori ? Bitovni operatori ˇ ? Clanski operatori ? Operatori identiteta ili s obzirom na broj operanada: ? Unarni operatori (jedan operand) ? Binarni operatori (dva operanada) 4.1
ˇ aritmeti cki operatori
Aritmetiˇcki operatori omogu´cuju osnovne matematiˇcke operacije na brojevima. Rezultat aritmetiˇckog operatora je uvijek broj tj. varijabla tipa float ili int, ovisno o tipovima operanada.. Operator
Opis
Primjer za x=9.0 i y=2.0
+
Zbrajanje
x+y daje 11
-
Oduzimanje
x-y daje 7
*
Množenje
x*y daje 18
*
Dijeljenje
x/y daje 4.5
%
Ostatak dijeljenja
x%y daje 1
//
Cjelobrojno dijeljenje
x//y daje 4
**
Potenciranje
x**y daje 81
Tablica 4.1: Aritmetiˇcki operatori
4.2
relacijski operatori ili operatori usporeðivanja)
¯ Relacijski operatori omogu´cavaju usporedivanje vrrijednosti varijabli. Rezultat relacijskih operatora je varijabla tipa bool i može poprimiti vrijednosti (True ili False).
19
20
operatori
Operator
Opis
Primjer za x=9.0 i y=2.0
==
Jednakost
x==y daje False
!=
Nejednakost, razliˇcitost
x!=y daje True
<>
Nejednakost, razliˇcitost
x<>y daje True
>
Ve´ce
x>y daje True
>=
Ve´ce ili jednako
x>=y daje True
<
Manje
x
<=
Manje ili jednako
x<=y daje False
Tablica 4.2: Relacijski operatori
4.3
operatori dodjeljivanja
Operator dodjeljivanja služi za dodjeljivanje vrijednosti varijabli. Postoje, proširenja kojima se može kombinirati aritmetiˇcke operatore i operator dodjeljivanja. Operator
Opis
Primjer za x=9.0 i y=2.0
=
Dodjeljivanje
x=y dodjeljuje vrijednost 2.0 varijabli x
+=
Zbrajanje i dodjeljivanje
x+=y je isto što i x=x+y, x poprima vrijednost 11.0
-=
Oduzimanje i dodjeljivanje
x-=y je isto što i x=x-y, x poprima vrijednost 7.0
*=
Množenje i dodjeljivanje
x*=y je isto što i x=x*y, x poprima vrijednost 18.0
/=
Dijeljenje i dodjeljivanje
x/=y je isto što i x=x/y, x poprima vrijednost 4.5
%=
Ostatak dijeljenja i dodjeljivanje
x%=y je isto što i x=x%y, x poprima vrijednost 1.0
//=
Cjelobrojno dijeljenje i dodjeljivanje
x//=y je isto što i x=x//y, x poprima vrijednost 4.0
**=
Potenciranje i dodjeljivanje
x**=y je isto što i x=x**y, x poprima vrijednost 81.0
Tablica 4.3: Operatori dodjeljivanja
4.4
ˇ logi cki operatori
Logiˇcki operatori and, or i not omogu´cavaju operacije na bool varijablama. and i or su binarni operatori logiˇcko i i logiˇcko ili dok je not unarni operator logiˇcko ne. Rezultat logiˇckih operatora je uvijek bool varijabla. ¯ Izvorni kod 4.1: Primjer kombiniranje operatora dodjeljivanja, operatora usporedivanja i logiˇckih operatora 1
#! /usr/bin/python
2 3 4
a = 10 b = 1
ˇ 4.5 clanski operatori
a
b
a and b
a or b
not b
True
True
True
True
False
True
False
False
True
True
False
True
False
True
False
False
False
False
Tablica 4.4: Logiˇcki operatori
5
c = 15
6 7 8
d = a < b print d
9 10 11
e = a > b and c > b print e
12 13 14
f = a > c or not b > c print f False True True
4.5
ˇ clanski operatori
ˇ ¯ ¯ Clanski opratori služe za odredivanje pripadnosti odredenoj listi. Osnovni cˇ lanski operator je operator in, i može se proširiti sa logiˇckim operatorom not te rvot oprator not in. Rezultat cˇ lanskih opratora je bool varijabla koja daje saznanje da li zadani element pripada listi ili ne pripada list. >>> a >>> 2 True >>> 3 False >>> 5 True
= [1, 2, 3, 8, 6] in a
4.6
operatori identiteta
not in a not in a
¯ Operatori identita usporeduju da li su Python objekti zapisani na istom ¯ mjestu u memoriji. Postoji operator is i is not koji usporeduju id Python objekta. id Python objekta se može dohvatiti naredbom id. >>> a=[1, 2, 3] >>> b=[1, 2, 3] >>> id(a) 139967012502704 >>> id(b) 139967012502848 >>> a is b False >>> b=a >>> id(b) 139967012502704 >>> a is b
21
5
O S N O V N E N A R E D B E Z A U N O S I I S P I S P O D ATA K A
5.1
print
Iz Python koda mogu´ce je ispisivati poruke u konzolu pomo´cu naredbe print. Osnovna sintaksa za ispisivanje je print variable
gdje je variable ima varijable cˇ iju vrijednost se želi ispisati. Mogu´ce je ispisivati vrijednosti više varijabli: print variable1, variable2
Naprednije mogu´cnosti ispisa mogu´ce je kontrolirati pomo´cu ubacivanja vrijednosti varijabli u string pomo´cu printf formata. Simbolom % i pripada¯ ju´cim znakom za tip podatka može se u stringu odreduju pozicije na koje se želi ubaciti vrijednosti varijabli, a nakon stringa i simbola % slijede imena samih varijabli. >>> var_a=7 >>> var_b=13.54592 >>> var_str = ’a iznosi %d, b iznosi %f’ % (var_a, var_b) >>> print var_str a iznosi 7, b iznosi 13.545920
Primjer
Opis
%s
String
%d
Cijeli broj
%f
Decimalni broj
%.2f
Decimalni broj sa dvije decimale
%10.3d
Decimalni broj sa dvije decimale i rezerviranih najmanje 10 znakova Tablica 5.1: printf formatiranje
Izvorni kod 5.1: Razliˇciti primjeri ispisa 1 2
print ’Ispisi ovo na ekranu!’ print ’Ispisi’ + ’ jos’ + ’ ovo.’
3 4 5 6 7 8 9 10
a=12 type(a) print a print ’a=’, a print ’a=’ + str(12) print ’Ovo je a:%d’ % (a) print ’Ovo je a:%.2d’ % (a)
11 12 13 14 15 16 17
b=15.365982 type(b) print ’Ovo je print ’Ovo je print ’Ovo je print ’Ovo je
b:’,b b:’+str(b) b:%f’ % (b) b:%.2f’ % (b)
23
24
osnovne naredbe za unos i ispis podataka
18
print ’Ovo je b:%10.3f’ % (b)
19 20
print ’ovo je a: %d a ovo je b: %f’ % (a,b)
21 22 23 24
print ’a = {broj_a}, b = {broj_b}’.format(broj_a = a, broj_b = b) print ’a = {broj_a}, b = {broj_b:.2f}’.format(broj_a = a, broj_b = b) print ’a = {broj_a:8d}, b = {broj_b:8.2f}’.format(broj_a = a, broj_b = b) Ispisi ovo na ekranu! Ispisi jos ovo. 12 a= 12 a=12 Ovo je a:12 Ovo je a:12 Ovo je b: 15.365982 Ovo je b:15.365982 Ovo je b:15.365982 Ovo je b:15.37 Ovo je b: 15.366 ovo je a: 12 a ovo je b: 15.365982 a = 12, b = 15.365982 a = 12, b = 15.37 a = 12, b = 15.37
5.2
input
5.3
raw_input
6
UVJETNA GRANANJA
¯ Odredene naredbe ili djelove koda mogu´ce je izvršavati ili preskoˇciti ovisno o vrijednosti postavljenog logiˇckog uvjeta. 6.1
if
Ako uvijet nije zadovoljen
Logički uvjet
Ako je uvjet zadovoljen
Naredbe
Slika 6.1: Dijagram toka if naredbe
Slika 6.1 prikazuje jednostavno grananje u programskom kodu. Osnovna sintaksa if naredbe je if condition : command
Navedeni izraz uvjetuje izvršavanje naredbe command (ili više naredbi) na temelju logiˇckog uvjeta condition. Zadane naredbe c´ e se izvršiti samo ako je logiˇcki uvijet zadovoljen. Izvorni kod 6.1: Jednostavan primjer upotrebe if naredbe 1
#!/usr/bin/python
2 3 4 5
a = input("a: ") if a < 0: a = -a print a
Pokretanjem Izvornog koda 6.1 i utipkavanjem pozitivnog broja ispiše se utipkani broj: user@machine:~> python if_01.py a: 5 5
¯ Medutim, utipkavanjem negativnog broja zadovoljava se postavljeni logiˇcki uvjet i izvrši se operacija a = -a te se potom ispiše pozitivna vrijednost utipkanog broja: user@machine:~> python if_01.py a: -11 11
U sluˇcaju kad postoji više naredbi uvjetovanih istim logiˇckim uvjetom, naredbe možemo objediniti pod jednim uvjetom te ih odvojiti sa toˇckazarezom (;). Ako su uvjetovane naredbe kompleksne ili ih ima više, naredbe pišemo u uvuˇcenim recima nakon if naredbe. Sve uvuˇcene naredbe do prvog retka koji je poravnat sa if naredbom su uvjetovane.
25
26
uvjetna grananja
Izvorni kod 6.2: Pisanje složenijeg uvjetovanog grananja 1
#!/usr/bin/python
2 3 4 5
a = 0 b = input("b: ") c = input("c: ")
6 7 8
if b < 0: a = 1; b = -b print a, b
9 10 11 12 13 14 15
if c < b: a = 2 b = c - b c = c +1 a = b + c print a, b, c user@machine:~> python if_02.py b: -6 c: 4 1 6 3 -2 5
6.2
else
Ova naredba omogu´cuje složeniji oblik grananja od naredbe if. Naredba ima dvije grane koje se mogu izvršiti u ovisnosti o uvjetu. Svaka grana/mogu´cnost omogu´cuje izvršavanje pripadaju´cih naredbi (Slika 6.2). Ako je uvjet zadovoljen
Naredbe A
Logički uvjet
Ako uvijet nije zadovoljen
Naredbe B
Slika 6.2: if-else dijagram toka
else naredba koristi se u paru sa if i služi za grananje u sluˇcaju da uvjet nije zadovoljen. Sintaksa naredbe je: if condition : command1 else: command2
Izvorni kod 6.3: Primjer upotrebe else naredbe 1
#!/usr/bin/python
2 3 4
a = input("a: ") b = input("b: ")
5 6 7
if a < b: b = a
6.3 elif
8 9 10 11
a = 0 else: a = b b = 0
12 13
print a, b user@machine:~> python if_else_01.py a: 1 b: 8 0 1 user@machine:~> python if_else_01.py a: 5 b: 3 3 0
6.3
elif
Za dodatna grananja uvjetovana novim logiˇckim uvjetima (Slika 6.3) služi naredba elif. Iako se sa ugnježdenim grananjem može posti´ci isti rezultat, elif omogu´cuje jednostavnije i preglednije grananje algoritma. Naredba elif omogu´cuje grananje u alogritmu samo ako prethodni uvjeti (if ili elif) nisu zadovoljeni. Treba napomenuti da se u sluˇcaju korištenja if-elif-else grananja uvijek izvrši samo jedan set uvjetovanih naredbi. Iz same definicije dodatnog uvjetnog grananja, naredba elif uvijek dolazi u kombinaciji sa naredbom if, te se upotrebljava u sljede´coj osnovnoj sintaksi if condition1 : command1 elif condition2 : command2
Kao ni u sluˇcaju upotrebe else naredbe dodatno grananje se mora napisati u novom retku. Uobiˇcajeno je da se naredbe koje slijede nakon uvjeta pišu u novom uvuˇcenom retku. Proširena upotreba ukljuˇcuje kombinaciju više elif naredbi: if condition1 : command1 elif condition2 : command2 elif condition3 : command3
Grananje se može napraviti i kombinacijom sve tri navedene naredbe: if condition1 : command1 elif condition2 : command2 else : command2
U Izvornom kodu 6.4 napisan je jednostavan primjer grananja koriste´ci navedene naredbe. Izvorni kod 6.4: Primjer kombinacije naredbi if, elif i else 1
#!/usr/bin/python
2 3
a = input("a: ")
4 5 6 7 8 9 10
if a < 0: print ’a je negativan’ elif a > 0: print ’a je pozitivan’ else: print ’a je nula’
27
28
uvjetna grananja
Logički uvjet A
Ako je uvjet zadovoljen
Naredbe A
Ako uvijet nije zadovoljen
Logički uvjet B
Ako je uvjet zadovoljen
Naredbe B
Ako uvijet nije zadovoljen
Logički uvjet C
Ako je uvjet zadovoljen
Naredbe C
Ako uvijet nije zadovoljen Naredbe D
Slika 6.3: Dijagram toka za složeni uvjet grananja
Unosom pozitivnog broja izvršava se naredba koja je uvjetovana uvjetom pod elif naredbom: user@machine:~> python if_elif_else_01.py a: 33 a je pozitivan
7
PETLJE
7.1
for
Naredba for koristi se za iteriranje elemenata u nekom iterabilnom objektu (lista, tuple, string itd.). Njezina osnovna sintaksa je for iter in list : commands
Naredbe commands izvršavaju se jednom za svaki element iz niza list. Objekt iter je iterator koji pokazuje na elemente niza list. Za razliku od jezika C, C++ iter se ne briše nakon što for naredba završi. Izvorni kod 7.1: Upotreba for naredbe 1 2 3
#!/usr/bin/python for num in range(2, 5): print(num)
4 5
print(num) 2 3 4 4
Izvorni kod 7.2: Naredba for s listom stringova 1 2 3 4
#!/usr/bin/python text=[’ide’,’patka’,’preko’,’save’] for r in text: print(r) ide patka preko save
Izvorni kod 7.3: Naredba for i stirng 1 2
#!/usr/bin/python for c in ’patka’: print(c) p a t k a
Izvorni kodovi 7.2 i 7.3 prikazuju upotrebu stringova u for naredbi. Do indeksa elemenata u nizu može se do´ci korištenjem naredbi len i range (poglavlje ??) kao što se može vidjeti na primjeru Izvornog koda 7.4: Izvorni kod 7.4: Naredba for s listom stringova 1 2 3 4
#!/usr/bin/python text=[’ide’,’patka’,’preko’,’save’] for i in range(len(text)): print i, text[i]
29
30
petlje
0 1 2 3
ide patka preko save
7.2
while
Osnovne sintaksa naredbe while je while conditon : commands
Naredbe commands izvršavaju se dokle god je uvjet condition istinit. Naredbe
Ako je uvjet zadovoljen
Logički uvjet
Ako uvijet nije zadovoljen
Slika 7.1: Dijagram toka while petlje
Izvorni kod 7.5: Upotreba while naredbe 1 2 3 4 5
#!/usr/bin/python i=0 while i*i<=9: print i i=i+1 0 1 2
7.3
break
Proširena sintaksa for ili while naredbe ukljuˇcuje i naredbu else: for iter in list : commands1 else : comands2 while condition : commands1 else : comands2
Nakon što se iscrpe svi elemnti niza list ili nakon što uvjet condition postane neistinit, izvršit c´ e se naredbe commands2. Naredbe specificirane u else bloku izvode se kad se petlja završi zbog nezadovoljavanja uvjeta sprecificiranog za while petlju ali ne i u sluˇcaju završavanje tj. prekida petlje zbog break naredbe (Slika 7.2). Izvorni kod 7.6: Upotreba else naredbe u petlji 1 2 3 4
#!/usr/bin/python for num in range(3): print(num) else:print(’Kraj’)
7.4 continue
Break Naredbe
Ako je uvjet zadovoljen
Logički uvjet
"else" naredbe Ako uvijet nije zadovoljen
Slika 7.2: Dijagram toka while petlje sa else blokom
0 1 2 Kraj
Naredbom break se završava for ili while naredba. Na primjeru Izvornog koda 7.7 može se vidjeti da se nakon break naredbe ne izvrši dio koda nakon else naredbe. Izvorni kod 7.7: Upotreba break naredbe 1 2 3 4 5 6 7
#!/usr/bin/python i=0 while i*i<=9: print i i=i+1 if i==2 : break else : print(’Kraj’) 0 1
7.4
continue
Naredbom continue se preskaˇce izvršavnje sljede´cih naredbi u tijelu for ili while naredbe (Slika 7.3).
Naredbe
Naredbe
Ako je uvjet zadovoljen
continue Logički uvjet Ako uvijet nije zadovoljen
Slika 7.3: Dijagram toka while petlje sa continue naredbom
31
32
petlje
Izvorni kod 7.8: Upotreba continue naredbe 1 2 3 4
#!/usr/bin/python for num in range(2, 5): if num==3:continue print(num) 2 4
8
FUNKCIJE
¯ Funkcije su grupirani dio koda koji izvodi odredeni zadatak. Prednosti upotrebe funkcija su: ? Smanjenje ponavljanja istog koda ? Pove´cavanje modularnosti koda - rašˇclanjivanje složenog koda na jednostavnije djelove ? Pove´canje cˇ itkosti koda. Rad sa funkcijama u Pythonu omogu´cuje veliku fleksibilnost. Funkcije ¯ mogu biti dodijeljene varijablama, spremljene u listama i prosljedivane kao argumenti drugim funkcijama. Razlikujemo dva osnovna tipa Python funkcija: ¯ ? Ugradene funkcije su funkcije koje su dio Python programskog jezika ? Funkcije definirane od strane korisnika. 8.1
definiranje i pozivanje funkcija
Kljuˇcna rijeˇc def omogu´cuje definiranje funkije. Najjednostavnija sintaksa koja omogu´cuje definiranje funkcije je: def functionname(): commands
gdje je functionname odabrano ime funkcije a commnds je naredba ili više naredbi koje funkcija izvršava. Prethodno definiranu funkciju možemo izvršiti pozivom te funkcije. Funkcija se poziva pomo´cu imena funkcije nakon kojeg slijede zagrade. Izvorni kod 8.1: Definicija i pozivanje jednostavne funkcije 1
#!/usr/bin/python
2 3 4
def pozdrav(): print ’Pozdrav!’
5 6
pozdrav() Pozdrav!
Funkciju je mogu´ce proširiti na naˇcin da prima jedan ili više argumenata. Argumenti se definiraju pomo´cu imena argumenata razdvojenih zarezom u zagradama nakon imena funkcije: def functionname(arg1, arg2, ... , argn): commands
Funkcija sa argumentima se poziva tako da se u zagradama nakon imena funkcije upišu vrijednosti argumenata. Argumenti se u pozivu funkcije razdvajaju zarezom kao i prilikom definicije funkcije.
33
Poziv funkcije uvijek mora biti nakon definicije funkcije. Ne može se pozvati funkcija koja prethodno nije definirana.
34
funkcije
Izvorni kod 8.2: Definicija funkcije koja prima argument 1
#!/usr/bin/python
2 3 4
def pozdrav( ime ): print ’Pozdrav’, ime, ’!’
5 6 7 8
def zbroji( a, b ): c = a + b print a, ’+’, b, ’=’, c
9 10 11
pozdrav(’Marko’) zbroji(2, 5) Pozdrav Marko ! 2 + 5 = 7
8.2
´ vra canje vrijednosti iz funkcije
Funkcija može vratiti vrijednost nakon poziva funkcije. Vrijednost koju funkcija vra´ca doslovno zamjenjuje funkciju u kontekstu u kojem je ona pozvana, a tip vra´cenog podatka može biti bilo koji Python objekt. Vra´canje vrijednosti se definira naredbom return nakon koje se zaustavlja izvršavanje funkcije: def functionname(arg1, arg2, ... , argn): commands return value
Izvorni kod 8.3: Definicija funkcije koja prima više argumenata i vra´ca vrijednost 1
#!/usr/bin/python
2 3 4 5
def zbroji(a, b): c = a + b return c
6 7 8
x = zbroji(2, 6) y = zbroji(x, -5)
9 10
print x, y 8 3
Funkcija može sadržavati više return naredbi (obiˇcno u razliˇcitim uvjetnim grananjima) i svaka može vratiti razliˇcit tip podatka (Izvorni kod 8.4). Izvorni kod 8.4: Funkcija koja vra´ca razliˇcite tipove 1
#!/usr/bin/python
2 3 4 5 6 7
def luda_funkcija(a, b): if(a > b): return a + b else: return ’malo teksta’
8 9 10
x = luda_funkcija(6, 2) y = luda_funkcija(x, 10)
11 12
print x, y 8 malo teksta
8.3 argumenti sa zadanim vrijednostima
Vrlo cˇ esto, javlja se potreba da funkcija vra´ca više vrijednosti. To se može ostvariti vra´canjem tuplea. Izvorni kod 8.5: Funkcija koja vra´ca više vrijednosti korsite´ci tuple 1
#!/usr/bin/python
2 3 4 5 6
def f(a, b): z = a + b r = a - b return z, r
7 8 9
x = f(6.0, 2.0) print x
10 11 12 13
c, d = f(6.0, 2.0) print c print d (8.0, 4.0) 8.0 4.0
8.3
argumenti sa zadanim vrijednostima
Funkcije mogu biti dfinirane i sa zadanim vrijednostima argumenata. Argumenti sa zadanim vrijednostima mooraju biti definirani nakon argumenata bez zadanih vrijednosti. def functionname(arg1=val1, arg2=val2, ... , argn=valn): commands return value
Prilikom poziva funkcije, mogu´ce je funkciju pozvati bez zadanih argumenata. Izvorni kod 8.6: Funkcija sa zadanim argumentom 1
#!/usr/bin/python
2 3 4 5 6 7
def f(a, b=0.0): if(a > b): return a - b else: return b
8 9 10 11
a = f(6.0, 2.0) b = f(20.0) c = f(-3.0)
12 13
print a, b, c 4.0 20.0 0.0
8.4
keyword i non-keyword argumenti
Funkciju se može pozivati na naˇcin da se, pomo´cu keyword argumenata, toˇcno specificiraju argumenti. Keyword argumenti su oni argumenti koji se, pri pozivu funkcije, zadaju imenom i vrijednoš´cu, za razliku od nonkeyword argumenata koji se zadaju samo kao vrijednost. Redosljed zadavanja keyword argumenata može biti proizvoljan dok kod kombinacije nonkeyword i keyword argumenata prvo moraju biti specificirani non-keyword argumenti.
35
36
funkcije
1 2 3
# Definiranje funkcije def f(x, a, b): return x*(a+b)
4 5 6
# Poziv funkcije sa keyword argumentima f(x=10, b=0, a=8)
7 8 9
# Poziv funkcije sa mjesovitim keyword i non-keyword argumentima f(10, b=0, a=8)
8.5
ugnježdena definicija funkcije
Ugnježdeno definiranje funkcije (eng. closure ili nested function definition) omogu´cuje definiciju funkcije u funkciji. Ugnježdena definicija funkcije je ¯ mogu´ca u Pythonu jer su funkcije objekti te ih je mogu´ce prosljedivati kao argumente drugim funkcijama te vra´cati kao rezultat funkcije. Ugnježdeno definirane funkcije mogu se pokazati korisne jer unutarnja funkcija može koristiti objekte definirane u vanjskoj: >>> ... ... ... ... >>> >>> 15 >>> 20
8.6
def vanjska(vanjski_argument): def unutarnja(unutarnji_argument): return vanjski_argument * unutarnji_argument return unutarnja f = vanjska(5) f(3) f(4)
anonimne funkcije
Lambda funkcije su funkcije bez imena tj. anonimne funkcije. Najˇceš´ce se koriste za definiranje vrlo jednostavnih i kratkih funkcija. Definiranje anonimne funkcije se vrši korištenjem kljuˇcne rijeˇci lambda: lambda argumenti: izraz
Upotrebu jednostavne funkcije koja vra´ca apsolutnu razliku dva broja 1 2
def diff(a, b): return abs(a - b)
3 4
print diff(7, 11) 4
može se zamjeniti lambda funkcijom: 1 2
>>> print (lambda a, b: abs(a - b))(7, 11) 4
Anonimne funkcije se cˇ esto pokriste kao argumenti drugih funkcija koje oˇcekuju objekt tipa funkcija kao argument. sorted funkcija oˇcekuje argument key kao funkciju, koja je ve´cini sluˇcajeva veoma jednostavna funkcija i obiˇcno se koristi anonimna funkcija da se izbjegne posebno definiranje funkcije. U sljede´cem primjeru napravljeno je sortiranje liste tupleova po drugim cˇ lanovima tupleova: >>> sorted([(5, 5), (13, 2), (11, 6), (7, 4)], key=lambda a: a[1]) [(13, 2), (7, 4), (5, 5), (11, 6)]
Još jedan primjer upotrebe anonimnih funkcija je u ugnježdenim definicijama funkcijama.
8.7 rekurzivne funkcije
Izvorni kod 8.7: Primjer anonimne funkcije u ugnježdenoj definiciji 1 2
def poruka(ime): return lambda poruka: ime + ’: ’ + poruka
3 4 5 6
p = poruka(’Mario’) print p(’Bok!’) print p(’Kako ste?’) Mario: Bok! Mario: Kako ste?
8.7
rekurzivne funkcije
Do sada smo se ve´c susreli sa petljama i naˇcinom kako funkcionira iterativni postupak kao sukcesivno pove´cavanje indeksa, tj. brojˇcanika koji sudjeluje u operaciji koja u konaˇcnici daje finalni rezultat. Primjer je suma uzastopnih brojeva od 1 do 100. 1 2 3
suma = 0 for index in range(1,101): suma = suma + index
4 5
print suma
Znaˇci suma se postepeno pove´cava dok se ne iscrpi lista, tj. sekvenca indeksa definirana pozivom na range naredbu. index = 1 suma = index = 2 suma = index = 3 suma = index = 4 suma =
0 + 1 1 + 2 3 + 3 6 + 4
i tako dalje dok index ne postane 100. Drugim rijeˇcima postepeno se na varijablu nadodaju brojevi. Takoder je mogu´ce zapisati isti postupak prema koracima kako je vršeno sumiranje suma = (0) index = 1 : suma = ((0) + 1) index = 2 : suma = (((0) + 1) + 2) index = 3 : suma = ((((0) + 1) + 2) + 3) itd.
Kada bi indeksirali parcijalne sume tada bi dobili slijede´ci izraz sumaindex = sumaindex−1 + index . Tako zapisani izraz daje naslutiti kako je slijede´ca suma zapisana kao suma iz prethodnog koraka na koju se nadodaje vrijednost index iz trenutnog koraka iterativne petlje. Ovakav zapis u biti je obrnuti zapis od prirodnog sukcesivnog pove´cavanja indeksa: suma(100) = suma(99) + 100, gdje je suma(99) = suma(98) + 99, gdje je suma(98) = suma(97) + 98, i tako dalje sve do . . . suma(1) = suma(0) + 1
37
38
Mogu´cnost zapisa funkcije u obliku koji poziva istu funkciju nazivamo rekurzija, a takvu funkciju rekurzivna funkcija.
funkcije
Tipiˇcna rekurzivna funkcija vrši poziv sama na sebe. Primjer je funkcija rsuma : 1 2
def rsuma(x): return rsuma(x)
No, kao što vidite ova funkcija vra´ca poziv na samu sebe koja vra´ca poziv na samu sebe koja vra´ca poziv na samu sebe i tako u beskonaˇcnost. Ovako definirana rekurzivna funkcija nema kraja, a program ulazi u beskonaˇcnu petlju (eng. infinite loop). A gdje je greška? Kako bi sprijeˇcili ovakvo ponašanje potrebno je uvesti uvjet prekida. To je graniˇcna vrijednost nakon koje funkcija više ne´ce vratiti sebe ve´c neku vrijednost. Ako se sada vratimo na sumu brojeva onda bi rekurzivna funkcija sume trebala izgledati ovako: 1 2
def rsuma(n): return rsuma(n - 1) + n
No oznaka prekida je suma(0)=0, tj. kada u 100-tom pozivu funkcije rsuma bude primila za argument 0 potrebno je zaustaviti daljnje pozive rsuma funkcije. To c´ emo posti´ci testiranjem vrijednosti n 1 2 3 4 5
def rsuma(n): if n = 0: return 0 else: return rsuma(n - 1) + n
Na taj naˇcin omogu´cili smo oznaku kraja rekurzivnim pozivima funkcije. Slijedi nekoliko primjera: Primjer 1. Proraˇcun faktorijela broja n. Faktorijel broja n je jednak :
Rekurzivni zapis unosi konciznost i eleganciju u programski kod.
n! = 1 ∗ 2 ∗ 3 ∗ 4 ∗ ... ∗ n Ima rekurzivni zapis n! = (n − 1)! ∗ n 1 2 3 4 5
def factoriel(n): if n = 0: return 1 else: return factoriel(n - 1) * n
Primjer 2. Potenciranje broja x eksponentom n. ¯ je iterativni proces koji može biti zapisan rekurzivno Potenciranje takoder na slijede´ci naˇcin xn = xn−1 ∗ x Primjerice kub je jednak umnošku broja i kvadrata broja, x3 = x2 ∗ x 1 2 3 4 5
def potencija(x,n): if n = 0: return 1 else: return potencija(x, n - 1) * x
Primjer 3. Korisniˇcki unos i formiranje liste Unose se brojevi koji se dodaju na listu dok se ne unese ’0’.
8.7 rekurzivne funkcije
1 2
def rloop(): x = int(raw_input(’Unesi broj ili 0 za kraj’))
3 4
if x: return [x]+rloop()
5 6 7
else: return []
Dok su prethodni primjeri ovisili o smanjivanju broja n do oznake kraja, u ovom primjeru funkcija se poziva tako da ažurira listu novim vrijednostima. Za zakljuˇcak, potrebno je napomenuti da je rekurzivnu funkciju mogu´ce napraviti za svaki poziv petlje, no da li je nužno sve petlje pretvoriti u rekurzivne funkcije To ostaje na procijeni programeru koji mora odvagnuti koliˇcinu elegancije, hijerarhije, strukturiranosti te preglednosti koda.
39
9
OBJEKTNO-ORIJENTIRANO PROGRAMIRANJE
9.1
objektno-orijentirano programiranje
Python je inicijalno zamišljen kao objektno orijentirani programski jezik. Pojam objekt je kljuˇc za razumijevanje objektno-orijentiranog pristupa programiranju. Objekt je kompozicija stanja (atributi, varijable) i ponašanja (metode, funkcije). Stanja jednog objekta cˇ ine njegovi atributi (npr. objekt automobil može imati atribute promjer kotaˇca, snaga motora, trenutni prijenosni omjer) koji su u programu utjelovljeni kao varijable koje poprimaju odre¯ ¯ dene vrijednosti (stanja). Ponašanje ili aktivnosti odredenog objekta utjelov¯ ljene su u programu u obliku funkcija koje izvršavaju odredene radnje važne za objekt ili korisnike koji koriste objekte (npr. metode koje može izvršiti automobil su koˇcenje, ubrzavanje, mijenjanje brzine, skretanje). Tako definirani objekti omogu´cuju proširenje postoje´ce funkcionalnosti programskog ˇ jezika i time programeru olakšavaju pisanje programa. Cesto ih se može susresti prilikom izrade aplikacija sa grafiˇckim suˇceljem ili bilo kojoj drugoj aplikaciji cˇ iji korisnici moraju stvarati objekte, mijenjati njihova stanja i koristiti metode kako bi definirali ponašanje ili uzrokovali neku aktivnost vezanu uz objekt. Najlakše c´ e biti to shvatiti na slijede´cem primjeru. Primjer: "Aplikacija za pisanje teksta" omogu´cava korisniku slijede´ce funkcionalnosti: ? izradu novog dokumenta - (u programskom kodu dokument je objekt) ? mijenjanje sadržaja dokumenta (sadržaj je jedan od atributa objekta) ? mijenjanje naziva dokumenta (sadržaj je jedan od atributa objekta) ? zapis sadržaja dokumenta u datoteku (Save, Save As funkcije kao metode objekta dokumenta) ? otvaranje dokumenta iz datoteke (Open funkcija kao metoda objekta dokumenta) ? lijevo, centralno, podjednako i desno poravnanje teksta u sadržaju (Funkcije Left,Center,Right,Justify kao metode objekta dokumenta) ? itd. Pored ovih stanja i ponašanja jednog dokumenta kao objekta lako biste ¯ mogli poznavaju´ci MS Word ili neku drugu aplikaciju za uredivanje i editiranje teksta osmisliti ili se sjetiti još neke od mnogih stanja i ponašanja koje MS Word posjeduje. ¯ mora omogu´citi i izradu ili uˇcitavanje neAplikacija poput ove takoder ¯ koliko objekata kako bismo mogli usporedivati ili kopirati njihov sadržaj ili recimo spojiti više dokumenata u jedan. Da bi to omogu´cila aplikacija mora posjedovati naˇcin kako da omogu´ci istovremenu pojavu više dokumenata. Što to znaˇci u programu toˇcno. Dokument je opisan kao objekt u programskom kodu. Više dokumenata time cˇ ini više objekta gdje svaki može imati sadržaj, naziv kao svoje atribute te metode Open ,Save, Left, itd. kao ponašanja koja aplikacija omogu´cuje pojedinom dokumentu tj. objektu.
41
42
objektno-orijentirano programiranje
¯ Time dolazimo do problema što svi izradeni dokumenti imaju varijable kao stanja i funkcije kao metode koje su jednake za sve dokumente/objekte. Kako bi aplikacija svim dokumentima omogu´cila tako nešto, mora u aplikaciji postojati zapis koji definira kako c´ e se ponašati svaki pojedini objekt dokumenta te koje c´ e funkcionalnosti svakom dokumentu aplikacija omogu´citi. Taj zapis u objektno-orijentiranim programskim jezicima nazivamo Klasom, a svaki poziv na izradu novog objekta instanciranje. Time je svaki objekt definiran kao jedna instanca klase. 9.2
klase
Klase predstavljaju definiciju svih atributa i metoda koje c´ e instance te klase poprimiti. Za definiranje klase, tj. opisa objekta, koristi se izraz class ime_klase():
nakon kojeg slijede definicije atributa i metoda. Izvorni kod 9.1: Definicija klase 1 2
#!/usr/bin/python # -*- coding: utf-8 -*-
3 4 5 6 7
class Dokument: """ Klasa Dokument omogucuje instanciranje objekata Dokument """ >>> d1 = Dokument() >>> d2 = Dokument() >>> d1 <__main__.Dokument instance at 0x7f050f2c0098> >>> d2 <__main__.Dokument instance at 0x7f05000287e8> >>>
Prikazani izvorni kod i output iz Python konzole pokazuju naˇcin definicije klase te naˇcin instanciranja dva objekta d1 i d2. Printanjem u konzoli objekata d1 i d2 mogu´ce je vidjeti da su oba objekta instance te da je svaka zasebno referencirana u memoriji na drugo adresno mjesto. 9.3
atributi
Atributi omogu´cuju dodjeljivanje stanja objekata. Njihova definicija nalazi se unutar klase i vrijedi za sve objekte instancirane iz klase. Postoje dvije vrste atributa ? Klasni (globalni) atributi ? Objektni (lokalni) atributi 9.3.1
Globalni atributi
Atributi koji pripadaju svim objektima zovu se klasni atributi, i definiraju se odmah poslije definicije klase. To su globalne varijable koje vrijede za sve objekte instancirane iz te klase. Npr. Izvorni kod 9.2: Primjer definicije klasnih (globalnih) atributa
9.3 atributi
1 2
#!/usr/bin/python # -*- coding: utf-8 -*-
3 4 5 6 7
class Dokument: """ Klasa Dokument omogu´ cuje instanciranje objekata Dokument """
8 9 10
ime=’Dokument1’ sadrzaj=’Ovo je prva linija u dokumentu’
11 12 13
d1=Dokument() d2=Dokument() >>> d1.ime ’Dokument1’ >>> d2.ime ’Dokument1’ >>> Dokument.ime ’Dokument1’
Atribut ’ime’ je stoga dostupan svim objektima kao i samoj klasi Dokument. Potrebno je napomenuti da je mogu´ce do´ci do pogreške ako objekt nastoji mijenjati vrijednost klasnom atributu. Naime, takvim cˇ inom nije iz¯ mijenjena vrijednost klasnom atributu ve´c je izraden novi atribut istoga imena, a koji pripada objektu. >>> d2.ime ’Dokument1’ >>> d2.ime=’Doc’ >>> Dokument.ime ’Dokument1’
Svrha postojanja globalnih atributa je u tome da omogu´ce identifikaciju objekata instanciranih iz jedne klase. Slijede´ci primjeri primjene dati su na klasi Parkirališta: ? identifikacijski broj objekta (npr. Parking01,Parking02,...) ? lista objekata (npr. [obj1,obj2,obj3]) ? kumulativne sume (npr. ukupan broj automobila parkiranih na svim parkiralištima) 9.3.2
Objektni atributi
Objektni atributi cˇ ine atribute definirane u klasi unutar posebne metode koja se zove __init__. Ova metoda pripada u kategoriju ’magiˇ cnih metoda klase’ jer omogu´cuju napredne mogu´cnosti. Inicijalizacija je u drugim programskim jezicima prisutna pod nazivom konstruktor. Ona ima za cilj omogu´citi definiciju atributa koji c´ e poprimati stanja definirana prilikom stvaranja objekta. Npr. Izvorni kod 9.3: Primjer definicije objektnog atributa 1 2
#!/usr/bin/python # -*- coding: utf-8 -*-
3 4 5 6 7 8
class Dokument: """ Klasa Dokument omogu´ cuje instanciranje objekata Dokument """ def __init__(self):
43
44
objektno-orijentirano programiranje
self.ime=’’ self.sadrzaj=’’
9 10 11 12 13
d1=Dokument() d2=Dokument()
14 15 16
d1.ime=’Prica01’ d1.sadrzaj=’Bio jednom jedan val.’
17 18 19 20
d2.ime=’ListaSerija’ d2.sadrzaj=’Lud, zbunjen, normalan.\n’ d2.sadrzaj+=’Sila\n’
¯ prihvat argumenata predanih Klasi Metoda __init__omogu´cuje, takoder, prilikom formiranja objekta. To cˇ inimo tako da u argument listu metode __init__predamo vrijednosti koje želimo da pojedini atributi tog objekta poprime. Npr. Izvorni kod 9.4: Inicijalizacija objekta 1 2
#!/usr/bin/python # -*- coding: utf-8 -*-
3 4 5 6 7 8 9 10
class Dokument: """ Klasa Dokument omogu´ cuje instanciranje objekata Dokument """ def __init__(self,name=’Dokument’,content=’’): self.ime=name self.sadrzaj=content
11 12 13 14 15
d1=Dokument(’Esej’,’Prva recenica’) d2=Dokument(’Blog01’) d3=Dokument()
Do ovog koraka ve´c sve uvidjeli da se pozivi atributa unutar metode __init__vrše pomo´cu specifiˇcne rijeˇci self. No, to c´ emo obraditi u sljede´cem poglavlju Metode. 9.4
metode
Metode su funkcije koje koristimo da u klasi definiramo promjenu stanja atributa, izvršimo neke aktivnosti ili obavimo neke druge radnje vezane uz ¯ odredeni objekt. Svaka metoda mora biti definirana kao funkcija i posjedovati minimalno jedan argument, a to je self kao opis objekta za kojega se izvršava metoda. Slijede´ci primjer definira metodu Info koja omogu´cuje printanje naziva i sadržaja objekta koji ju je pozvao. Obratite pažnju na korišteni globalni atribut DokumentList kao listu objekata koja se puni prilikom inicijalizacije. Izvorni kod 9.5: Definicija metode 1 2
#!/usr/bin/python # -*- coding: utf-8 -*-
3 4 5 6 7
class Dokument: """ Klasa Dokument omogucuje instanciranje objekata Dokument """
8 9 10
DokumentList=[]
9.5 preopterecivanje
11 12 13 14
def __init__(self,name=’Dokument’,content=’’): self.ime=name self.sadrzaj=content Dokument.DokumentList.append(self)
15 16 17 18
def Info(self): print ’Ime dokumenta:’,self.ime print ’Sadrzaj:\n’,self.sadrzaj
19 20 21 22
d1=Dokument(’Esej’,’Prva recenica’) d2=Dokument(’Blog01’) d3=Dokument()
23 24 25 26
for d in Dokument.DokumentList: d.Info() print ’\n’
Self prvi put dobiva znaˇcaj kao prvi cˇ lan argument liste metode __init__(def __init__(self,arg1,arg2,...)). Unutar same metode svaki od atributa koji se koriste mora biti zapisan uz pomo´c ’self.’ prefiksa. Možemo to gledati na drugaˇciji naˇcin. Zamislite da je klasa modul koji ima svoje pod-funkcije (metode). Svaka od tih pod-funkcija ima mogu´cnost mijenjati atribute nekom objektu. To je ostvarivo samo ako pod-funkcija može pristupiti objektu i njegovim atributima. Upravo to cˇ inimo predaju´ci self metodi __init__. Predajemo objekt u obliku rijeˇci self, te nakon toga vrijednosti koje želimo dodijeliti atributima. No u stvarnosti Python dozvoljava pozivanje funkcija bez davanja sebe kao prvog cˇ lana argument liste. ¯ Na slijede´cem primjeru usporedujemo dva istovjetna poziva metode gdje je prva na naˇcin da objekt poziva metodu, a druga da Klasnoj metodi predamo objekt kao prvi cˇ lan argument liste te nakon njega sve ostale argumente. >>> d1.Info() Ime dokumenta: Esej Sadrzaj: Prva recenica >>> Dokument.Info(d1) Ime dokumenta: Esej Sadrzaj: Prva recenica
Znaˇci d1.Info() je isto što i Dokument.Info(d1). Prvi omogu´cava jednostavniji poziv metode dok drugi ukazuje naˇcin kako Python ustvari radi, tj. predaje metodi objekt koji u deklaraciji metode stoji kao self. 9.5
preopterecivanje
Jedna od osobina objektno-orjentiranog programiranja je mogu´cnost preoptere´civanja funkcija i operatora kako bi i objektima omogu´cili istu funkcionalnost kao i klasiˇcnim varijablama poput int, float, bool, string, list, itd. Takva osobina cˇ esto je i nužnost kako bi operatore mogli dovoditi u odre¯ dene odnose i operacije ili nad objektima izvršiti radnje poput printanja. ˇ Cesto se za evaluaciju ili grananje služimo operatorima usporedbe (>,>=,<,<=, ==) te logiˇckim operatorima and i or. Istu funkcionalnost mogu´ce je posti´ci ¯ i usporedbom dvaju objekata gdje se objekti pritom usporeduju na naˇcin ¯ da im se toˇcno odredi što i kako se usporeduje (npr. dvije košare vo´ca Kosara01 i Kosara02 su objekti cˇ iji sastav cˇ ini raznovrsno vo´ce gdje svako ima svoju težinu i mogu´ce je u svakom sluˇcaju utvrditi ukupnu težinu košare te pristupiti usporedbi dvaju košarica).
45
46
objektno-orijentirano programiranje
Nadalje, objekti mogu biti tako osmišljeni da je od znaˇcaja primjena osnovnih numeriˇckih operatora (+,-,*,/,itd.) kako bi se kreirali novi objekti sa izmjenjenim atributima na temelju numeriˇckih operatora (npr. ako su one dvije kosare iz prethodnog zadatka bile pune i u njih vise ne stane onda je moguce u novu kosaru dodati sastojke iz prethodne dvije pune kosare). Sva preoptere´cenja u Pythonu predefinirana su u obliku specijalnih metoda koje svaka klasa može implementirati. Specijalne metode imaju naziv ¯ sa dvije donje crte ispred i iza naziva (npr. __str__ili __gt__) omeden 9.5.1
Preopterecivanje funkcija
Izvorni kod 9.6: Preoptere´civanje funkcije print 1 2 3 4
# -*- coding: utf-8 -*""" Created on Sat Jun 1 13:35:55 2013 """
5 6
from math import sqrt
7 8
class Point:
9 10 11 12
def __init__(self,x,y): self.x=x self.y=y
13 14
15
def R(self): # funkcija koja vraca radij vektor tocke, tj. udaljenost od ishodista return sqrt(self.x**2 + self.y**2)
16 17 18 19 20 21 22 23 24 25
# Preoptereceni operatori usporedbe tocka s obzirom na udaljenost od ishodista def __lt__(self,other): # less then return self.R() < other.R() def __le__(self,other): # less or equal return self.R() <= other.R() def __gt__(self,other): # greather then return self.R() > other.R() def __ge__(self,other): # greater or equal return self.R() >= other.R()
26 27 28 29
p1=Point(2,1) p2=Point(1,2) p3=Point(3,0)
30 31 32 33 34 35
print print print print print
p1>p2 p1>=p2 p1<=p2 p1
Opis objekta klase CPoints Ukupan broj tocaka: 2 Opis objekta klase CPoints Ukupan broj tocaka: 4
U ovom primjeru naredba print je preoptere´cena koriste´ci specijalnu funkciju __str__koja vra´ca string koji c´ e biti printan prilikom printanja objekta. p r i n t PTS1 p r i n t PTS2
9.5 preopterecivanje
Potrebno je napomenuti da nije mogu´ce preopteretiti korisniˇcki definirane funkcije tj. sve one koje nemaju svoju specijalnu funkciju. 9.5.2 Preopterecivanje operatora Preoptere´civanje operatora omogu´ceno je u Pythonu korištenjem specijalnih metoda slijede´cih imena Operatori usporedbe ? __gt__ - Ve´ce od - ’>’ ? __ge__ - Ve´ce ili jednako od - ’>=’ ? __lt__ - Manje od - ’<’ ? __le__ - Manje ili jednako od - ’<=’ ? __eq__ - Jednako - ’==’ Izvorni kod 9.7: Preoptere´civanje funkcije print 1 2 3 4
# -*- coding: utf-8 -*""" Created on Sat Jun 1 13:35:55 2013 """
5 6
from math import sqrt
7 8
class RVector:
9 10 11 12
def __init__(self,x,y): self.x=x # atribut x koordinata self.y=y # atribut y koordinata
13 14
15
def R(self): # metoda koja vraca duljinu radij vektora, tj. udaljenost od ishodista return sqrt(self.x**2 + self.y**2)
16 17
18 19 20 21 22 23 24 25 26 27
# Preoptereceni operatori usporedbe radij vektora s obzirom na udaljenost od ishodista def __lt__(self,other): # less then return self.R() < other.R() def __le__(self,other): # less or equal return self.R() <= other.R() def __gt__(self,other): # greather then return self.R() > other.R() def __ge__(self,other): # greater or equal return self.R() >= other.R() def __eq__(self,other): # greater or equal return self.R() == other.R()
28 29 30 31
p1=RVector(2,1) p2=RVector(1,2) p3=RVector(3,0)
32 33 34 35 36 37
print print print print print False True True False True
p1>p2 p1>=p2 p1<=p2 p3
47
48
objektno-orijentirano programiranje
Aritmetiˇcki operatori ? __add__ - zbrajanje - ’+’ ? __sub__ - oduzimanje - ’-’ ? __mul__ - množenje - ’*’ ? __div__ - djeljenje - ’/’ Izvorni kod 9.8: Preoptere´civanje funkcije print 1
# -*- coding: utf-8 -*-
2 3
class Table:
4 5 6 7 8
def __init__(self,a=1.0,b=1.0): self.a = a self.b = b self.Area = self.a * self.b # atribut povrsine stola
9 10 11
def __str__(self): return ’Table = %4.1f x %4.1f \n Area = %6.2f’ % (self.a,self.b,self.Area)
12 13 14 15
def Rotate(self): # rotira stranice a i b tmpA=self.a tmpB=self.b
16 17 18
self.a=tmpB self.b=tmpA
19 20
print ’Stol zarotiran!’
21 22
# Preoptereceni aritmetiˇ cki operatori
23 24 25 26
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
def __add__(self,other): # zbraja dva stola self.a = self.a + other.a # dužinu drugog pridodajemo dužini prvog self.Area = self.Area + other.Area # površinu drugog dodajemo povrsini prvog self.b = self.Area / self.a # izraˇ cunavamo novu prosjeˇ cnu širinu print ’Stolovi spojeni!’ def __sub__(self,other): # oduzima dva stola if self.Area > other.Area: if self.a > other.a: if self.b > other.b: self.Area -= other.Area # oduzima površinu drugoga self.a -= other.a # oduzima dužinu drugoga self.b = float(self.Area)/self.a # izraˇ cunava novu širinu print ’Stolovi oduzeti!’ else: print ’Sirina b je duža kod drugog stola.’ else: print ’Duzina a je duza kod drugog stola.’ else: print ’Povrsina drugog je veca od prvog stola.’
43 44 45 46 47 48 49 50 51 52 53 54
t1=Table(10,20) t2=Table(20,40) print t1 print t2 t1-t2 t2-t1 t1+t2 t1.Rotate() t1-t2 print t1 print t2
9.6 nasljeðivanje
Table = 10.0 x 20.0 Area = 200.00 Table = 20.0 x 40.0 Area = 800.00 Povrsina drugog je veca od prvog stola. Stolovi oduzeti! Stolovi spojeni! Stol zarotiran! Sirina b je duza kod drugog stola. Table = 40.0 x 20.0 Area = 800.00 Table = 10.0 x 60.0 Area = 600.00
Postoji još mnogo specijalnih metoda, ali njihovo izuˇcavanje prepuštamo vama da ih istražite ako smatrate potrebnim. 9.6
nasljeðivanje
Objekti koje je mogu´ce susresti u stvarnom životu najˇceš´ce su kategorizirani u neke grupacije ili klastere, ili su dio neke hijerarhijske strukture. Rijetko ˇ da je neki objekt jedinstven u svoj svojoj unutrašnjosti. Covjek jede, životinja jede, a i biljke jedu tj. izvršavaju jednu od svojih najvažnijih funkcija. Bicikl je kopneno vozilo, kao i automobil, dok je avion ili balon na vru´ci zrak zraˇcno vozilo, a podmornica ili brod pomorsko vozilo. Sva ova prometala su vozila. Na taj naˇcin slijedi hijerarhija koja definira pripadnost pojedinih objekata. Postoje i rekurzivne hijerarhijske veze poput obiteljskih stabala ili svake strukture koja za svoj rezultat ima potomstvo novih objekata. ¯ Nasljedivanje je u pravilu proces kojim od viših hijerarhijskih razina ili grupacija poprimamo neke osobine ili funkcije. ¯ Objektno-orjentirano programiranje omogu´cuje naslijedivanje atributa i ¯ metoda iz nadredenih klasa. Deklaracija klase koja posjeduje nadklasu data je u slijede´coj liniji koda: class Sudoku(Igra):
¯ Klasa Sudoku naslijeduje metode od svoje nadklase Igra koja se cˇ esto zove i bazna (osnovna) klasa. Kao što je Igra nadklasa klasi Sudoku tako je Sudoku klasi Igra podklasa. U slijede´cem primjeru dana je nadklasa Road koja inicijalizira naziv ceste name i duljinu ceste length te definira sadržaj metode Info() koja služi za ispis vrijednosti atributa svakog instanciranog objekta bilo podklase Highway, MainRoad, LoaclRoad ili osnovne nadklase Road. ¯ Naslijedivanje ima još jednu prednost koja se oˇcituje u sistematizaciji izvornog koda. Kada ne bi imali nadklasu, svaka od podklasa trebala bi sama inicijalizirati svoje atribute kao i definirati svoju funkciju Info(). Na taj naˇcin izvorni kod bi bio predugaˇcak, nejasan i neˇcitljiv. ¯ Izvorni kod 9.9: Naslijedivanje 1 2
# -*- coding: utf-8 -*"""
49
50
objektno-orijentirano programiranje
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Created on Sat Jun 1 20:07:45 2013 """ class Road: def __init__(self,name,length): self.name=name self.length=length def Info(self): print "Road definition" print "Ime:\t %15s" % self.name print "Length:\t %15s" % self.length class Highway(Road): pass # Bez lokalnih definicija class MainRoad(Road): pass # Bez lokalnih definicija class LocalRoad(Road): pass # Bez lokalnih definicija
19 20 21 22 23 24 25
h1=Highway(’A1’,1000) m1=MainRoad(’E54’,540) l1=LocalRoad(’S16’,125) h1.Info() m1.Info() l1.Info() Road definition Ime: Length: Road definition Ime: Length: Road definition Ime: Length:
A1 1000 E54 540 S16 125
U situaciji kada pojedina podklasa ipak zahtjeva prilikom inicijalizacije definirati neki vlastiti atribut tada definicija __init__unutar podklase predefinira (override) __init__metodu nadklase. U tom sluˇcaju je potrebno pozvati inicijalizacijsku metodu nadklase unutar inicijalizacijske metode podklase. ¯ Izvorni kod 9.10: Naslijedivanje override __init__metode 1 2 3 4 5 6 7 8
# -*- coding: utf-8 -*""" Created on Sat Jun 1 20:07:45 2013 """ class Road: def __init__(self,name,length): self.name=name self.length=length
9 10 11 12 13
def Info(self): print "Road definition" print "Ime:\t %15s" % self.name print "Length:\t %15s" % self.length
14 15 16 17 18 19 20 21 22 23 24 25 26
class Highway(Road): def __init__(self,name,length): # override __init__ nadklase Road.__init__(self,name,length) # invokacija __init__ metode nadklase self.type=’highway’ self.toll=50 # Kn/100km class MainRoad(Road): def __init__(self,name,length): # override __init__ nadklase Road.__init__(self,name,length) # invokacija __init__ metode nadklase self.type=’mainroad’ class LocalRoad(Road): def __init__(self,name,length): # override __init__ nadklase Road.__init__(self,name,length) # invokacija __init__ metode nadklase
9.6 nasljeðivanje
self.type=’localroad’
27 28 29 30 31
h1=Highway(’A1’,1000) m1=MainRoad(’E54’,540) l1=LocalRoad(’S16’,125)
32 33
print h1.toll 50
¯ ¯ Pored jednostavnih naslijedivanja mogu´ca su i višestruka naslijedivanja iz više nadklasa i definiraju se na slijede´ci naˇcin: class Smartphone(Mobile_device,Computer):
51
10
O B L I K O VA N J E S T R I N G O VA
10.1
oblikovanje sa operatorom %
¯ String objekti imaju ugradeni operator (%) koji omogu´cava ubacivanje vrijednosti unutar stringa na posebno oznaˇcena mjesta. Mjesta na koja treba ¯ ubaciti odredenu vrijednost u stringu oznaˇcavaju se znakom % i posebnim oznakama koje detaljnije definiraju formatiranje ubaˇcene vrijednosti. Nakon stringa i operatora % (Nije isto što i oznaka u samom stringu) u tupleu ili dictionaryju se zadaju vrijenosti ili varijable koje treba umetnuti u string. Izraz koji definira format ubaˇcene vrijednosti sastoji se od: ? znak % koji oznaˇcava poˇcetak izraza za definiranje formata, ? kljuˇc mapiranja (neobavezno) koji definira ime (kljuˇc) vrijednosti koja se ubacuje u string, ? konverzijske opcije (neobavezno), ? minimalni broj rezerviranih znakova (neobavezno), ? preciznost (neobavezno), oznaˇcava broj decimalnih mjesta koje se prikazuju i piše se nakon znaka .. ? tip konverzije. Ako se koristi kljuˇc mapiranja onda vrijednosti treba zadati u dictionaryju dok se inaˇce zadaju u tupleu. Konverzijske opcije se definiraju pomo´cu znakova opisanih u tablici 10.1. Simbol
Opis
’0’
Prazne znakove popunjuje sa nulama
’-’
Poravnanje u lijevo
’ ’
Nezauzete znakove popunjuje razmacima
’+’
Uvijek postavlja predznak (+ ili -) Tablica 10.1: Opcije konverzije
Pomo´cu operatora % u string je mogu´ce ubaciti razne numeriˇcke (i string) formate koji se definiraju pomo´cu simobla danih u tablici 10.2. Primjer u izvornom kodu 10.1 prikazuje ubacivanje i formatiranje decimalnog i cijelog broja u string. Primjer obuhva´ca primjenu tupleova bez kljuˇca mapiranja te na istom primjeru primjenu dictionaryja sa kljuˇcevima mapiranja. Izvorni kod 10.1: Primjer formatiranja numeriˇckih podataka sa tupleom i dictionaryjem >>> >>> a = >>> >>> a = >>> >>> a =
s = ’a = print s 12.37, b s = ’a = print s 12.37, b s = ’a = print s 12.37, a
%.2f, b = %d’ % (12.365, 18) = 18 %(a).2f, b = %(b)d’ % {’a’: 12.365, ’b’: 18} = 18 %(a).2f, a = %(a)+.1f’ % {’a’: 12.365} = +12.4
53
Upotrebom kljuˇceva mapiranja zadavanje argumenata u dictionaryju ne mora biti u istom redosljedu kao i pozicije ubacivanja u samom stringu. Na ovaj se naˇcin argumenti mogu upotrijebiti više puta, bez potrebe da ih se višestruko puta zapisuje unutar dictionaryja.
54
oblikovanje stringova
Simbol
Tip
’d’
Cijeli broj
’o’
Oktalni broj
’x’
Heksadecimalni broj
’e’
Decimalni broj u eksponencijanom obliku
’f’
Decimalni broj
’c’
Tekstualni znak
’s’
String
’%’
Nema konverzije argumenta, rezultat sadrži znak ’%’ Tablica 10.2: Definiranje tipova podataka
Razliˇcite primjene konverzijskih opcija prikazane su u izvornom kodu 10.2. Izvorni kod 10.2: Primjer formatiranja numeriˇckih podataka sa tupleom i dictionaryjem >>> x = >>> x = >>> x = >>> x = >>> x = >>> x = >>> x = >>> x =
print ’x = [%5.2f, %5.2f]’ % (11.14, 7.88) [11.14, 7.88] print ’x = [%f, %f]’ % (11.14, 7.88) [11.140000, 7.880000] print ’x = [%10f, %10f]’ % (11.14, 7.88) [ 11.140000, 7.880000] print ’x = [%010f, %010f]’ % (11.14, 7.88) [011.140000, 007.880000] print ’x = [%+10f, %+10f]’ % (11.14, 7.88) [+11.140000, +7.880000] print ’x = [%-+10f, %-+10f]’ % (11.14, 7.88) [+11.140000, +7.880000 ] print ’x = [%-+10.2f, %-+10.2f]’ % (11.14, 7.88) [+11.14 , +7.88 ] print ’x = [%+10.2f, %+10.2f]’ % (11.14, 7.88) [ +11.14, +7.88]
Izvorni kod 10.3: Primjer formatiranja numeriˇckih podataka za ispis u stupcima 1
from math import sqrt, sin
2 3
l = range(1, 11)
4 5 6 7 8
for i in range(len(l)): s = ’%03d %4.1f %6.1f %5.2f %+6.3f’ % \ (i+1, l[i], l[i]**2.0, sqrt(l[i]), sin(l[i])) print s 001 1.0 002 2.0 003 3.0 004 4.0 005 5.0 006 6.0 007 7.0 008 8.0 009 9.0 010 10.0
1.0 4.0 9.0 16.0 25.0 36.0 49.0 64.0 81.0 100.0
1.00 1.41 1.73 2.00 2.24 2.45 2.65 2.83 3.00 3.16
+0.841 +0.909 +0.141 -0.757 -0.959 -0.279 +0.657 +0.989 +0.412 -0.544
10.2 oblikovanje sa metodom format
10.2
oblikovanje sa metodom format
Svi string objekti sadže metodu format koja omogu´cuje napredno formatiranje i kontrolu stringova.
55
11
R A D S A D AT O T E K A M A
11.1
otvaranje i zatvaranje datoteka
Osnovna manipulacija sa sadržajem datoteka u Pythonu je omogu´cena korištenjem file objekta. ¯ Python ima ugradenu funkciju open za otvaranje postoje´cih ili stvaranje novih datoteka na disku. Funkcija open vra´ca file objekt, koji sadrži metode i atribute za pristup i manipulaciju informacija i sadržaja otvorene datoteke. Sintaksa otvaranja datoteka je: f = open(ime\_datoteke, vrsta\_pristupa, buffering)
gdje je ime_datoteke sting koji sadrži relativnu ili apsolutnu putanju datoteke, vrsta_pristupa je string koji sadrži mod pristupa, buffering je ¯ integer koji oznaˇcava veliˇcinu medupohrane. Argumenti vrsta_pristupa i buffering nisu obavezni. f je novonastali file objekt kreiran pozivom funkcije open. Mod pristupa se definira kao string koji sadrži znakove: ? ’r’, ’w’ ili ’a’ kojima se definira da li c´ e se vršiti cˇ itanje (read), pisanje (write) ili dodavanje (append) ? ’b’ oznaˇcava binarni oblik datoteke. Ako nije specificiran onda je oblik datoteke takstualni (’t’). ? ’+’ omogu´cuje istodobno cˇ itanje i pisanje (ili dodavanje) datoteke. Nakon obavljanja željenih manipulacija, koje su objašnjene u narednim poglavljima, datoteku je potrebno zatvoriti. Za zatvaranje datoteke koristi se close metoda koju ima svaki file objekt: f.close()
Nakon zatvaranja nisu mogu´ce nikakve operacije na datoteci. 11.2
pisanje u datoteke
Za zapisivanje informacija u datoteku koriste se metode write i writelines klase file. write metoda prima string varijablu koju zapisuje u prethodno otvorenu datoteku u modu za pisanje (’w’) ili dodavanje (’a’). Ovu naredbu može se ponavljati kako bi se dodalo još teksta u datoteku. f.write(tekst)
Izvorni kod 11.1: Primjer kreiranja tekstualne datoteke 1 2
#!/usr/bin/python # -*- coding: utf-8 -*-
3 4
datoteka = open(’info.txt’, ’w’)
5 6 7 8
datoteka.write(’Tehniˇ cki fakultet’) datoteka.write(’, Rijeka’) datoteka.write(’\nVukovarska 58’)
9 10
datoteka.close()
57
Poˇcetna pozicija unutar datoteke razlikuje se ovisno o opciji ’r’, ’w’ (poˇcetak datoteke) ili ’a’ (kraj datoteke).
58
rad sa datotekama
Tehniˇ cki fakultet, Rijeka Vukovarska 58
Iako njeno ime na to upu´cuje, writelines ne zapisuje svaki element liste u novi redak!
Funkcija writelines zapisuje listu stringova u datoteku. Postignuti efekt je isti kao da se pozove write za svaki element liste. f.writelines(lista_stringova) l = [’malo’, ’ ’, ’teksta’] f.writelines(l) # isto što i for s in l: f.write(s)
11.3
ˇ citanje iz datoteka
Za cˇ itanje datoteke potrebno je željenu datoteku otvoriti u modu za cˇ itanje ¯ (’r’). Osnovni naˇcin za proˇcitati sadržaj odredene datoteke je preko funkcija: ? read koja vra´ca sadržaj datoteke (od trenutne pozicije) željene veliˇcine u obliku stringa, ? readline koja vra´ca sadržaj trenutne linije u obliku stringa, ? readlines koja vra´ca listu stringova koji predstavljaju pojedine linije datoteke Sintaks metode read je: f.read(size)
Kod cˇ itanja datoteka vrlo cˇ esto je bitna trenutna pozicija u samoj datoteci što je objašnjeno u poglavlju 11.4
gdje je size veliˇcina sadržaja koji treba proˇcitati. Za binarnu datoteku size oznaˇcava broj bitova a za tekstualnu broj znakova. Ukoliko je size negativan ili nije zadan, cˇ ita se cijeli sadržaj datoteke. f.readline(size)
Metoda readline cˇ ita jednu liniju u datoteci i to od trenutne pozicije do kraja lnije (do znaka ’ n’). Argument size definira maksimalnu veliˇcinu proˇcitanih podataka. Za prazne lnije metoda vra´ca string koji sadrži znak za novu liniju ’ n’. Kad je trenutna pozicija na kraju datoteke, metoda vra´ca prazan string. f.readlines(size)
readlines vra´ca sadržaj datoteke kao listu linija. size ima jednak uˇcinak
kao i na dvije prethodno objašnjene metode. Za potrebe primjera, zadana je datoteka test.txt sljede´ceg sadržaja: 123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ 3. linija 4. linija zadnja!
U izvornom kodu 11.2 dani su primjeri upotrebe navedenih funkcija za cˇ itanje sadržaja datoteke.
11.4 pozicioniranje u datoteci
ˇ Izvorni kod 11.2: Citanje sadržaja tekstualne datoteke 1 2 3 4 5 6
data = open(’test.txt’, ’r’) print data.read(5) print data.readline() print data.readline(6) print data.readlines() data.close() 12345 6789 ABCDEF [’GHIJKLMNOPQRSTUVWXYZ\n’, ’3. linija\n’, ’4. linija\n’, ’zadnja!’]
Osim pomo´cu navedenih funkcija, postoji još jedan naˇcin pristupanju linijama neke tekstualne datotetke, a to je iteriraju´ci kroz file objekt kao što je prikazano u izvornom kodu 11.3. Izvorni kod 11.3: Pristupanje sadržaju datoteke preko iteriranja po file objektu 1 2 3 4 5 6
data = open(’test.txt’, ’r’) s = ’’ for line in data: s += line print s data.close() 123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ 3. linija 4. linija zadnja!
11.4
pozicioniranje u datoteci
Trenutnu poziciju u datoteci može se saznati preko metode tell: f.tell()
Metoda tell daje broj bitova (znakova) trenutne pozicije od poˇcetka datoteke (Izvorni kod 11.4). seek momogu´cuje micanje trenutne pozicije u datoteci. Sintaksa metode je: f.seek(offset, from)
offset je broj koim definiramo pomak pozicije. Pozitivan je u naprijed a negativan u nazad. Argumentom from se definira od kuda c´ e se pomak
raˇcunati (0 za poˇcetak datoteke, 1 za trenutni položaj i 2 za kraj datoteke). Izvorni kod 11.4: Dohva´canje trenutne pozicije u datoteci 1 2 3 4 5 6 7 8 9 10 11
data = open(’test.txt’, ’r’) print data.readline() print ’pozicija:’,data.tell() print data.read(3) print ’pozicija:’,data.tell() data.seek(6,1) print data.read(3) data.seek(-3,1) print data.read(5) data.seek(0,0) print data.read(5)
59
60
rad sa datotekama
12 13 14
data.seek(-5,2) print data.read(5) data.close() 123456789 pozicija: 10 ABC pozicija: 13 JKL JKLMN 12345 dnja!
11.5
preimenovanje, kopiranje i brisanje datoteka
http://docs.python.org/2/library/shutil.html
Izvorni kod 11.5: Kopiranje, micanje i preimenovanje datoteka 1 2 3
# simply import os os.rename(’a.txt’,’b.kml’)
4 5 6 7
# or import shutil shutil.move(’a.txt’, ’b.kml’)
8 9 10 11 12
# or if you want to copy.. import shutil shutil.copy(’a.txt’, ’b.kml’)
11.6
1 2 3 4 5 6
arhiviranje
from shutil import make_archive import os archive_name = os.path.expanduser(os.path.join(’~’, ’myarchive’)) root_dir = os.path.expanduser(os.path.join(’~’, ’.ssh’)) make_archive(archive_name, ’gztar’, root_dir) ’/Users/tarek/myarchive.tar.gz’
12
P Y T H O N S TA N D A R D L I B R A R Y
http://docs.python.org/2/library/index.html
12.1
informacije o platformi i operacijskom sustavu
http://www.pythonforbeginners.com/systems-programming/how-to-use-the-platform-module-in-python/
12.2
ˇ matemati cke funkcije
Python modul math sadrži standardne matematiˇcke funkcije za realne brojeve koje su definirane C standrdom, s kojima se najˇceš´ce susre´cemo prilikom pisanja nekog programa. Funkcija
Opis
math.fabs(x)
Funkcija vra´ca apsolutnu vrijednost realnog broja x.
math.fsum(niz)
Funkcija vra´ca sumu elemenata nekog niza brojeva.
math.isnan(x)
Funkcija vra´ca True ako je x tipa NaN.
math.exp(x)
Exponencijalna funkcija ex .
math.log(x, b)
Funkcija logb (x) odnosno ln(x) ako se ne zada b.
math.cos(x)
Funkcija vra´ca kosinus kuta x zadanog u radijanima.
math.acos(x)
Inverz funkcije kosinus.
math.e
Matematiˇcka konstanta e=2.718281828459045... Tablica 12.1: Opis nekih funkcija math modula
Primjer upotrebe nekih funkcija math modula: 1 2 3 4
#!/usr/bin/python from math import log,e,fsum print log(e) print fsum([1,2,3]) 1. 6.
Python modul cmath sadrži standardne matematiˇcke funkcija nad poljem kompleksnih brojeva. Argumenti funkcija mogu biti tipa float ili complex. Funkcija
Opis
cmath.polar(x)Funkcija vra´ca polranu (r,φ) reprezentaciju kompleksnog broja x. cmath.sqrt(x) Funkcija vra´ca korijen kompleksnog broja Tablica 12.2: Opis nekih funkcija cmath modula
Primjer upotrebe nekih funkcija cmath modula: 1 2
from cmath import sqrt sqrt(1.+2.j) (1.272019649514069+0.7861513777574233j)
61
62
python standard library
Python modul decimal omogu´cuje raˇcunanje i pravilno zaokruživanje realnih brojeva u aritmetici s proizvoljnim brojem decimalnih mjesta. Primjer upotrebe nekih funkcija math modula: 1 2 3 4 5 6
#!/usr/bin/python from decimal import * getcontext().prec = 6 print Decimal(1) / Decimal(3) getcontext().prec =30 print Decimal(1) / Decimal(3) 0.333333 0.333333333333333333333333333333
12.3
datum i vrijeme
http://www.tutorialspoint.com/python/python_date_time.htm
12.4
vrijeme izvršavanja
¯ Uˇcinkovitost odredenog algoritma, djela izvornog koda ili pak cijelog izvornog koda vrlo je bitan faktor ukupne kvalitete raˇcunalnog programa. Uˇcin¯ kovitost odredenog izvornog koda se, prije svega, može mjeriti vremenom ¯ izvodenja tog koda. ¯ Treba imati na umu da vrijeme izvodenja ovisi o hardverskim resursima raˇcunala pa su stoga rezultati razliˇciti ovisn o raˇcunalu na kojem se testiranje vrši. Vrijeme izvršavanja ovisi i o trenutnom optere´cenju hardverskih resursa (operativni sustav, sistemski servisi i pokrenute aplikacije), pa c´ e, u manjoj mjeri, testiranja na istom raˇcunalu biti razliˇcita. ¯ Vrlo elegantan naˇcin za mjerenje vremena izvršavanja odredenog djela koda je upotrebom funkcija clock i time iz modula time. time funkcija daje trenutno vrijeme u sekundama od 00:00 1. sijeˇcnja 1970. godine. Funkcija clock je preciznija i primjerenija mjerenju vremena izvršavanja, ali razliˇcito funkcionira na Linux (Unix) i MS Windows platformama:
time.clock() ili time.time() se
? na Linux platofrmi, time.clock() daje utrošeno procesorsko vrijeme, tj. koliko je sekundi procesor bio optere´cen,
mogu pozivati više puta te na taj naˇcin mjeriti vrijeme izvršavanja više djelova izvornog koda.
? na MS Windows platformi, time.clock() daje “ukupno” utrošeno vrijeme koje obuhva´ca vrijeme raˇcunanja (procesor) ali i utrošeno vrijeme na cˇ itanje datoteka (disk) ili npr. utoršeno vrijeme na uspostavljanje konekcije preko nekog mrežnog protokola. Kod mjerenja izvršavanja koda koji radi sa cˇ itanje ili pisanjem datoteka ili koji vrši komunikaciju preko mrežnih protokola, rezultati c´ e biti ovisni i o platformi na kojoj se kod izvršava. Izvorni kod 12.1: Primjer mjerenja vremena izvršavanje algoritma 1 2
#!/usr/bin/python # -*- coding: utf-8 -*-
3 4
import time
5 6 7 8
# dohvati vrijeme poˇ cetka start_c = time.clock() start_t = time.time()
12.4 vrijeme izvršavanja
9 10
print ’Start clock: %.5f’ % start_c print ’Start time: %.5f’ % start_t
11 12 13 14 15 16 17
# Algoritam a = 0.0 for i in range(1000): for j in range(i): a = a + (i - j)**0.3
18 19 20 21 22 23
# dohvati vrijeme završetka stop_c = time.clock() stop_t = time.time() print ’Stop clock: %.5f’ % stop_c print ’Stop time: %.5f’ % stop_t
24 25 26 27
print ’Rezultat: %.2f’ % a print ’Vrijeme izvrsavanja (clock): %.3f ms’ % (stop_c - start_c) print ’Vrijeme izvrsavanja (time): %.3f ms’ % (stop_t - start_t) Start clock: 0.01000 Start time: 1373797428.12780 Stop clock: 0.12000 Stop time: 1373797428.23620 Rezultat: 2656321.74 Vrijeme izvrsavanja (clock): 0.110 ms Vrijeme izvrsavanja (time): 0.109 ms
Python Standard Library sadrži klasu Timer koja omogu´cuje mjerenje vremena izvršavanja Python izraza. ¯ Izvorni kod 12.2: Primjer upotrebe Timer klase za mjerenje vremena izvodenja funkcije 1 2
#!/usr/bin/python # -*- coding: utf-8 -*-
3 4 5
import timeit from math import sqrt
6 7 8 9 10 11
# Algoritam def f(x): s = 0.0 for i in range(x): s = s * sqrt(s+x)
12 13
t = timeit.Timer(stmt=’f(500)’, setup=’from __main__ import f’)
14 15 16
r1 = t.timeit(number=1000) print ’Potrebno vrijeme za 1000 poziva funkcije f(500): %.5f’ % r1
17 18 19 20 21
r5 = t.repeat(number=1000, repeat=5) print ’\nPonavljanje testa (5 puta):’ for r in r5: print ’Potrebno vrijeme za 1000 poziva funkcije f(500): %.5f’ % r Potrebno vrijeme za 1000 poziva funkcije f(500): 0.05833 Ponavljanje testa (5 puta): Potrebno vrijeme za 1000 poziva Potrebno vrijeme za 1000 poziva Potrebno vrijeme za 1000 poziva Potrebno vrijeme za 1000 poziva Potrebno vrijeme za 1000 poziva
funkcije funkcije funkcije funkcije funkcije
f(500): f(500): f(500): f(500): f(500):
0.05900 0.05927 0.05888 0.05953 0.05925
63
13
GREŠKE U PYTHON KODU
13.1
tipovi grešaka
¯ Ve´cina programskih jezika posjeduje odredene usluge prema korisniku koje omogu´cuju identificiranje i manipulaciju grešaka u pisanom izvornom kodu te davaju korisna objašnjenja vezana uz izvor greške ili naˇcin kako ih ukloniti. Python slijedi takvu logiku i omogu´cuje prijavljivanje dva tipa grešaka: ? Sintaksne greške Syntax Error i ? Iznimke (eng. Exceptions) ¯ ¯ Obje greške utvrduju se iskljuˇcivo tijekom izvodenja tj. interpretiranja ¯ koda: sintaksne greške na poˇcetku izvodenja koda, a iznimke za svaki iz¯ vršeni red koda. Nakon što Python identificira prvu grešku na koju naide program stane sa izvršavanjem i objavi poruku slijede´ceg izgleda >>> print c Traceback (most recent call last): File "", line 1, in NameError: name ’c’ is not defined
¯ Traceback obavještava korisnika o tome gdje je greška pronadena i daje opis greške pomo´cu sintaksne greške ili iznimke (eng. exception) koja objašnjava razlog prekida izvršavanja programa. U navedenom primjeru NameError je iznimka koja opisuje grešku pri pozivu imena ’c’. ¯ Sintaksne greške testiraju svaku liniju koda netom prije izvodenja cijelog ¯ programa i utvrduju svaku nepravilnost u sintaksi programskog jezika. Npr. 1
j=1
2 3 4 5 6 7
if j<2: print ’Help’ else: if True print ’Help2’ File "/home/mcavrak/.spyder2/.temp.py", line 7 if True ^ SyntaxError: invalid syntax
¯ prilikom izvodenja ovog koda program nikada niti ne´ce u´ci u else jer je ¯ uvjet if naredbe takav da vra´ca True, medutim program svejedno vra´ca grešku prilikom provere sintakse (’nedostaje dvotoˇ cka iza True’) ¯ na njih. No, iznimke c´ e program objaviti samo ako naide ¯ na grešku (pogrešno upisana varijabla ’i’, trebalo je Primjer kada naide ’j’): 1
j=1
2 3 4 5
if j<2: print ’Help’ print i
65
66
greške u python kodu
Help Traceback (most recent call last): File "/home/mcavrak/.spyder2/.temp.py", line 6, in print i NameError: name ’i’ is not defined
¯ na grešku: Primjer kada ne naide 1
j=1
2 3 4 5 6
if j<2: print ’Help’ else: print i Help
Najˇceš´ce iznimke koje susre´cemo su: ? ZeroDivisionError pokušaj operacije djeljenja sa nulom >>> 10 * (1/0) Traceback (most recent call last): File "", line 1, in ? ZeroDivisionError: integer division or modulo by zero
? NameError pokušaj operacije sa varijablom cˇ ije ime (name) nije u popisu imena (namespace) >>> 4 + i*3 Traceback (most recent call last): File "", line 1, in ? NameError: name ’i’ is not defined
? TypeError Pokušaj izvršavanja operacije na krivom tipu podataka >>> ’2’ + 2 Traceback (most recent call last): File "", line 1, in ? TypeError: cannot concatenate ’str’ and ’int’ objects
Postoji još mnogo iznimaka te ih je mogu´ce prona´ci na http://docs.python.org/ . No, iznimkama možemo manipulirati, tj. mogu´ce je ugraditi u kod identifikaciju greške te djelovanje sukladno tome. O tome više u slijede´cem poglavlju. 2/library/exceptions.html#bltin-exceptions
13.2
manipulacija greškama - exception handling
Iznimkama možemo manipulirati, tj. možemo prihvatiti informaciju o greški te djelovati u skladu sa njom ili granati kod tako da nastavi sa izvršavanjem unatoˇc greški. Razmotrimo primjer kada korisnik unosi brojeve na konzoli pomo´cu raw_input naredbe. 1 2 3
var=raw_input(’Unesi broj:’) a=int(var) print a
Python vra´ca iznimku ValueError jer nije u stanju pretvoriti preuzeti string u cjelobrojnu vrijednost.
13.3 ispravljanje grešaka - debugging
Unesi broj:z Traceback (most recent call last): File "/home/flood/untitled0.py", line 9, in a=int(var) ValueError: invalid literal for int() with base 10: ’z’
Kako bi izbjegli takvu grešku i prihvatili iznimku poslužiti c´ emo se sa try - except formulacijom: 1
var = raw_input(’Unesi broj:’)
2 3 4 5 6 7 8 9
try: a = int(var) print ’SUCCESS’ except ValueError: print ’Nije unešen broj!’ print ’Broj postavljen na defaultnu vrijednost 0.’ a = 0
10 11
print a
U ovom kodu izvršen je prihvat iznimke na naˇcin da je: ? unešena kljuˇcna rijeˇc try cˇ ije se tijelo prvo izvršava ¯ na iznimku tada program preskaˇce dio tijela ? ako program ne naide koji pripada except sekciji i nastavlja sa kodom (’print a’). ¯ na iznimku u try sekciji koda tada se zaustavlja na ? ako program naide mjestu gdje je našao grešku, ne nastavlja dalje sa preostalim djelom koda (’print SUCCESS’) ve´c skaˇce na except sekciju koja odgovara iznimki koju je uhvatio (u ovom sluˇcaju ValueError) te potom nastavlja sa kodom (’print a’) ¯ na vrstu iznimke opisanu u except sekciji ? ukoliko program ne naide tada izbaci grešku u obliku neuhva´cene iznimke (eng. unhandled exception) Pored ovog osnovnog koncepta primjene prihvata iznimaka, mogu´ce je podi´ci iznimku prema korisniˇckoj želji te izraditi korisniˇcki definirane iznimke. Ove funkcionalnosti nadilaze osnove i cˇ itatelj je slobodan potražiti više informacija na http://docs.python.org/2/tutorial/errors.html. 13.3
ispravljanje grešaka - debugging
Python ima modul pdb („Python DeBugger") koji pomaže kod otkrivanja i ispravljanja grešaka u kodu skripte. Ako ne koristite neki specijalizirani editor unutar nekog razvojnog okruženja tada je potrebno pozvati pdb modul na poˇcetku skripte: 1
import pdb
Na nekom kljuˇcnom mjestu u kodu na kojem se želite zaustaviti morate staviti naredbu: 1
pdb.set_trace()
na primjeru 13.1 može se vidjeti upotreba pdb modula. Ako koristite editor Spyder tada nije nužno pozvati pdb modul. Dovoljno je postaviti prekide u kodu dvostrukim lijevim klikom na lijevoj strani dokumenta i pokrenuti skriptu u Debug naˇcinu rada. (Pdb)
67
68
greške u python kodu
Unutar pdb modula mogu´ce je kontrolirati izvršavanje koda, a najˇceš´ce se koriste naredbe: ? n (next) izvršava se sljede´ca naredba u skripti, ? c (continue) izvrešava se ostatak skripte do sljede´ceg prekida, ? s (step into) pdb ulazi u podprogram ili funkciju, ? r (return) sliˇcno kao naredba c, ali pdb izvršava ostatak podprograma ili funkcije do izlaza iz podprograma, ? p var (print) pdb istpis stanja varijable var ? ENTER pdb izvršava zadnju naredbu koja mu je poslana, ? q (quit) zaustavlja izvršavanje skripte. Izvorni kod 13.1: Upotreba dbg modula 1 2
#!/usr/bin/python import pdb
3 4 5 6 7 8 9 10 11 12
pdb.set_trace() a=0 b=1 c=2 pdb.set_trace() a=b+c pdb.set_trace() a=b-c print ’kraj’
Dio II N U M P Y P O L J A I M AT R I C E
14
Z A D AVA N J E P O L J A U N U M P Y- U
Bazni objekt u NumPy-u, ndarray, je homogeno multidimenzionalno polje. Homogenost polja podrazumijeva da su svi podaci u polju istog tipa. U NumPy-u, dimenzije se nazivaju axes a broj dimenzija rank. Elementi polja su indeksirani pozitivnim cijelim brojevima. NumPy polja se mogu zadavati na više naˇcina. Baziˇcno, zadavanje polja se može podjeliti na ruˇcni unos pomo´cu naredbe array te na automatsko generiranje polja. NumPy polja mogu se automatski generirati pomo´cu neke od naredbi za generiranje polja. 14.1
array
Naredba array omogu´cava kreiranje NumPy polja iz obiˇcnih Python listi ili tuple-ova. Prilikom kreiranja polja pomo´cu array naredbe, u argument funkcije upisuju se elementi matrice i to na naˇcin da svaka dimnezija zapoˇcinje otvornemo uglatom zagradom ([) i završava zatvorenom uglatom zagradom (]) dok su elementi razdvojeni zarezom. Najjednostavnija sintaksa naredbe array je: array(object)
Ako je argument naredbe array tuple, onda pojedina dimenzija zapoˇcinje i završava sa zagradama. Pri tome treba paziti da je argumnet naredbe array samo jedan tuple (cijeli tuple mora biti u jednim zagradama). Mogu´ce je kombinirati Python liste i tuple-ove prilikom zadavanja matrice. >>> from numpy import * >>> M1 = array([[1, 2, 3],[4, 5, 6]]) >>> M1 array([[1, 2, 3], [4, 5, 6]]) >>> M2 = array( ( (6,7,8), (9,10,11) ) ) >>> M2 array([[ 6, 7, 8], [ 9, 10, 11]]) >>> M3 = array( ( [6,7,8], (9,10,11) ) ) >>> M3 array([[ 6, 7, 8], [ 9, 10, 11]])
Dodatni, neobavezni argumenti naredbe array su: dtype - željeni tip podataka za elemente polja. Ako argument nije zadan, elementi polja c´ e preuzeti minimalni tip potreban za pohranu podataka iz objekta object. Ovaj argument se može koristiti samo za ’pove´cati’ (eng. upcast) tip zadanog objekta. Za ’smanjiti’ (eng. downcast) tip koristiti .astype(t) naredbu. ¯ copy - bool varijabla (True ili False) koja odreduje da li se objekt kopira. ¯ order - odreduje naˇcin na koji se polje pohranjuje u memoriji. Polje može biti pohranjeno na tri naˇcina: ? ’C’ - elementi polja c´ e biti poredani u memoriji na naˇcin da zadnji indeks varira najbrže (C-povezani poredak) ? ’F’ - elementi polja c´ e biti poredani u memoriji na naˇcin da prvi indeks varira najbrže (Fortran-povezani poredak)
71
72
zadavanje polja u numpy-u
? ’A’ - elementi polja ne´ce imati definiran poredak u memoriji (C-povezani poredak, Fortran-povezani poredak ili cˇ ak nepovezani poredak) subok : bool, optional If True, then sub-classes will be passed-through, otherwise the returned array will be forced to be a base-class array (default). ndmin - minimalni broj dimenzija generiranog polja. Prema potrebi, broj dimenzija c´ e biti pove´can na naˇcina da c´ e jedinice biti dodane u shape polja.
14.2
arange
Naredba arange omogu´cuje kreiranje jednodimenzionalnog polja koje sadrži aritmetiˇcki niz definiran sa prvim cˇ lanom, zadnjim cˇ lanom te korakom. Sintaksa naredbe je arange(start, stop, step, type)
Oprez! Prilikom korištenja ne-cjelobrojnih koraka niza rezultat naredbe array može biti nekonzistentan. U takvim sluˇcajevima bolje je koristiti naredbu linspace (14.3).
gdje je start poˇcetak niza, stop kraj niza, step korak niza a type je tip podataka sadržanih u nizu. Svi argumennti naredbe arange osim stop su neobavezni i ukoliko nisu uneseni imaju zadane vrijednosti: ? start ima zadanu vrijednost 0 ? step ima zadanu vrijednost 1 te zahtijeva i zadavanje argumenta start ? type ako nije zadan, postavlja se tipa na temelju ostalih argumenata. >>> M1 = arange(10, 30, 3) >>> M1 array([10, 13, 16, 19, 22, 25, 28]) >>> M2 = arange(-2, 3) >>> M2 array([-2, -1, 0, 1, 2]) >>> M3 = arange(5) >>> M3 array([0, 1, 2, 3, 4])
14.3
linspace
Naredba linspace ima sliˇcnu namjenu kao i naredba arange (kreiranje aritmetiˇckog niza) samo što se umjesto koraka niza zadaje broj cˇ lanova niza. I sintaksa naredbe je vrlo sliˇcna naredbi arange: linspace(start, stop, num=50, endpoint=True, retstep=False)
gdje je start poˇcetak niza, stop kraj niza, num broj elemenata niza, endpoint je opcija ukljuˇcivanja zadnjeg elementa a retstep je opcija vra´canja korištenog koraka niza. >>> M1=linspace(0,10,21) >>> M1 array([ 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. , 5.5, 6. , 6.5, 7. , 7.5, 8. , 8.5, 9. , 9.5, 10. ]) >>> M2 = linspace(0, 5, 10, endpoint=False) >>> M2 array([ 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5]) >>> M3, step = linspace(0, 1, retstep=True) >>> M3 array([ 0. , 0.02040816, 0.04081633, 0.06122449, 0.08163265, 0.10204082, 0.12244898, 0.14285714, 0.16326531, 0.18367347, 0.20408163, 0.2244898 , 0.24489796, 0.26530612, 0.28571429,
14.4 zeros
0.30612245, 0.40816327, 0.51020408, 0.6122449 , 0.71428571, 0.81632653, 0.91836735, >>> step 0.02040816326530612
14.4
0.32653061, 0.42857143, 0.53061224, 0.63265306, 0.73469388, 0.83673469, 0.93877551,
0.34693878, 0.44897959, 0.55102041, 0.65306122, 0.75510204, 0.85714286, 0.95918367,
0.36734694, 0.46938776, 0.57142857, 0.67346939, 0.7755102 , 0.87755102, 0.97959184,
73
0.3877551 , 0.48979592, 0.59183673, 0.69387755, 0.79591837, 0.89795918, 1. ])
zeros
Naredba zeros omogu´cava generiranje polja koje sadrži nule. Osnovna sintaksa naredbe zeros je zeros(shape)
gdje je shape lista koja sadrži veliˇcine dimenzija. Osim veliˇcine dimnezija, postoje i dodatni neobavezni argumenti za definiranje tipa podataka te naˇcina spremanja polja u memoriju: zeros(shape, dtype=float, order=’C’)
Za generiranje polja nula može poslužiti i naredba zeros_like koja generira polje nula istih dimenzija kao neko postoje´ce polje. Sintaksa naredbe je: zeros_like(a)
gdje je a matrica cˇ ije dimenzije treba preuzeti. >>> from numpy import * >>> a = zeros([3, 5]) >>> print a [[ 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. 0.] [ 0. 0. 0. 0. 0.]] >>> b = array([2, 5, 6, 0]) >>> print b [2 5 6 0] >>> c = zeros_like(b) >>> print c [0 0 0 0]
14.5
Naredba zeros_like ima
dodatne argumente dtype i order. dtype omogu´cuje nametanje tipa podataka za generirano polje, a ako nije specificiran onda generirano polje ¯ nasljeduje tip podataka od argumenta a. order omogu´cuje mijenjanje rasporeda spremanja polja u memoriju.
ones
Za generiranje matrice zadanih dimenzija koja sadrži jedinice koristi se naredba ones. Sintaksa naredbe je vrlo ista kao i kod naredbe zeros: ones(shape, dtype=float, order=’C’)
Za kreiranje matrice, koja sadrži jedinice istih dimenzija kao neka postoje´ca matrice, koristi se ones_like naredba: ones_like(a)
gdje je a matrica cˇ ije dimenzije treba preuzeti. >>> from numpy import * >>> a = ones([2,4]) >>> print a [[ 1. 1. 1. 1.] [ 1. 1. 1. 1.]] >>> b = ones([3, 2],dtype=int) >>> print b
Naredba ones_like ima dodatne argumente dtype i order koji funkcioniraju jednako kao što je opisano za naredbu zeros_like.
74
zadavanje polja u numpy-u
[[1 1] [1 1] [1 1]] >>> c = array([5, 8]) >>> d = ones_like(c) >>> print d [1 1]
14.6
eye
Generiranje dvodimenzionalne jediniˇcne matrice (sadrži jedinice na dijagonali a ostalo su nule) mogu´ce je sa naredbom eye. Potpuna sintaksa naredbe eye je:
Naredba eye omogu´cuje generiranje iskljuˇcivo dvodimenzionalnih jediniˇcnih matrica.
eye(N, M=None, k=0, dtype=)
gdje je N broj redaka generiranog polja, M broj stupaca generiranog polja (ako nije zadano, broj stupaca je jednak broju redaka), k indeks dijagonale (0 je glavna dijagonala, pozitivna vrijednost se odnosi na dijagonale iznad a negativna na dijagonale ispod glavne dijagonale) dok je dtype tip podataka generiranog polja. >>> from numpy import * >>> a = eye(4) >>> print a [[ 1. 0. 0. 0.] [ 0. 1. 0. 0.] [ 0. 0. 1. 0.] [ 0. 0. 0. 1.]] >>> b = eye(5, 3) >>> print b [[ 1. 0. 0.] [ 0. 1. 0.] [ 0. 0. 1.] [ 0. 0. 0.] [ 0. 0. 0.]] >>> c = eye(3, 5, 1) >>> print c [[ 0. 1. 0. 0. 0.] [ 0. 0. 1. 0. 0.] [ 0. 0. 0. 1. 0.]]
14.7
diag
ˇ Cesto su brojevi na dijagonali matrice važni u proraˇcunu i javlja se potreba da ih se spremi u zasebnu varijablu. Naredba diag omogu´cuje upravo to: generira vektor koji sadrži elemenate dijagonale zadane matrice. Sintaksa naredbe je vrlo jednostavna. Funkcija diag obavezno prima, kao argument, matricu iz koje se želi preuzeti dijagonala. Dodatni argument, k, specificira položaj (indeks) dijagonale: 0 je glavna dijagonala, pozitivna vrijednost se odnosi na dijagonale iznad a negativna na dijagonale ispod glavne dijagonale. diag(v, k=0)
Izvorni kod 14.1: Spremanje elemenata dijagonale matrice u vektor 1 2 3 4
from M1 = v1 = v2 =
numpy import * array([[1, 2, 3],[4, 5, 6],[7, 8, 9]]) diag(M1) diag(M1,1)
14.8 meshgrid
5 6 7 8
print M1 print v1 print v2 user@machine:~> python diag01.py [[1 2 3] [4 5 6] [7 8 9]] [1 5 9] [2 6]
14.8
meshgrid
Naredba meshgrid služi za generiranje matrice koordinata na temelju vektora koordinata. >>> import numpy as np >>> x = np.linspace(0, 5, 6) >>> y = np.linspace(10, 50, 5) >>> X, Y = np.meshgrid(x, y) >>> print x [ 0. 1. 2. 3. 4. 5.] >>> print y [ 10. 20. 30. 40. 50.] >>> print X [[ 0. 1. 2. 3. 4. 5.] [ 0. 1. 2. 3. 4. 5.] [ 0. 1. 2. 3. 4. 5.] [ 0. 1. 2. 3. 4. 5.] [ 0. 1. 2. 3. 4. 5.]] >>> print Y [[ 10. 10. 10. 10. 10. 10.] [ 20. 20. 20. 20. 20. 20.] [ 30. 30. 30. 30. 30. 30.] [ 40. 40. 40. 40. 40. 40.] [ 50. 50. 50. 50. 50. 50.]]
meshgrid je vrlo korisna kod evaluacije funkcija na mreži toˇcaka: >>> import numpy >>> x = numpy.linspace(0, 3, 4) >>> y = numpy.linspace(0, 5, 6) >>> xx, yy = numpy.meshgrid(x, y, sparse=True) >>> z = numpy.cos(xx + yy**2) - numpy.sin(xx**2 - yy) >>> z array([[ 1. , -0.30116868, 0.34065566, -1.40211098], [ 1.38177329, -0.41614684, -1.1311125 , -1.64300187], [ 0.25565381, 1.12513317, 0.05087286, 0.09691566], [-0.77001025, 0.0702259 , -0.83704529, 1.12326946], [-1.71446198, -0.13404333, 0.66031671, 1.94762889], [ 0.03227854, -0.10988317, 0.54933218, -0.20580337]])
75
15
INFORMACIJE O POLJU I INDEKSIRANJE
15.1
informacije o polju
Svako NumPy polje ima definiran broj dimenzija, koji se lako može provjeriti pomo´cu ndim atributa polja. ndarray.ndim
ili pomo´cu naredbe ndim ndim(ndarray)
gdje je ndarray numpy polje. ¯ broj elemenata polja. Za svaku dimenziju, polje ima rezerviran odreden Broj elemenata po dimenzijma polja cˇ ini niz koji se može dobiti preko atributa shape ndarray.shape
ili preko naredbe shape shape(ndarray)
gdje je ndarray numpy polje. ¯ Ukupan broj elemenata u polju se odreduje naredbom size size(ndarray)
ili atributom numpy polja ndarray.size
gdje je ndarray numpy polje. Izvorni kod 15.1: Osnovne informacije o NumPy polju 1
from numpy import *
2 3
M1 = array([[1, 2, 3], [4, 5, 6]])
4 5 6 7 8 9 10
print print print print print print
M1.ndim ndim(M1) M1.shape shape(M1) M1.size size(M1)
2 2 (2, 3) (2, 3) 6 6
77
16
MANIPULACIJE SA NUMPY POLJIMA
16.1
manipulacije sa dimenzijama polja
¯ Elementi NumPy polja odredenih dimenzija, mogu se presložiti u NumPy polje drukˇcijih dimenzija. Preslagivanje polja na druge dimenzije vrši se pomo´cu naredbe reshape: reshape(a, newshape, order=’C’)
gdje je a izvorno polje, newshape vektor novih dimenzija a order je naˇcin spremanja polja u matricu. Uvijet za reshape je da broj elemenata polja ostane isti tj. umnožak veliˇcina dimenzija mora biti konstantan. Specifiˇcni sluˇcaj mijenjanja dimenzija polja je kada inicijalno polje želimo transformirati u jednodimenzionalno polje tj. vektor. Iako je to mogu´ce napraviti sa naredbom reshape, postoji specijelizirana naredba ravel za transformaciju n-dimnezionalnih polja u jednodimenzionalna polja. Sintaksa naredba je vrlo sliˇcna kao i za reshape osim što nije potrebno specificirati vektor veliˇcina dimenzija jer je rezultat uvijek jednodimenzionalno polje. ravel(a, order=’C’)
Za pretvorbu matrice u vektor koristi se i naredba flatten. Razlika je što je ovo funkcija ndarray objekta i uvijek kreira kopiju polja. flatten(order=’C’)
Izvorni kod 16.1: Mijenjanje dimenzija polja 1
from numpy import *
2 3 4
M1 = arange(0, 20) print M1
5 6 7 8 9
M2 = reshape(M1, [4, 5]) print M2 M3 = reshape(M2, [2, -1]) print M3
10 11 12
print ravel(M2) print M3.flatten() [ 0 [[ 0 [ 5 [10 [15 [[ 0 [10 [ 0 [ 0
1 1 6 11 16 1 11 1 1
2 2 7 12 17 2 12 2 2
3 3 8 13 18 3 13 3 3
4 5 4] 9] 14] 19]] 4 5 14 15 4 5 4 5
6
7
8
9 10 11 12 13 14 15 16 17 18 19]
6 7 8 9] 16 17 18 19]] 6 7 8 9 10 11 12 13 14 15 16 17 18 19] 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
Brisanje jediniˇcnih dimenzija matrice, koje vrlo cˇ esto znaju biti suvišne, može se napraviti funkcijom squeeze. Izvorni kod 16.2: Mijenjanje dimenzija polja 1
from numpy import *
79
Ukoliko se, kod poziva naredbe reshape, veliˇcina jedna od dimenzija ne specificira, tada se ona automatski raˇcuna na temelju ostalih veliˇcina dimenzija i ukupnog broja elemenata inicijalne matrice.
80
manipulacije sa numpy poljima
2 3
M1 = arange(0, 20)
4 5 6
M2 = reshape(M1, [4, 1, 1, 5]) print M2.shape
7 8 9
M3 = squeeze(M2) print M3.shape (4, 1, 1, 5) (4, 5)
16.2
transponiranje
Transponiranje matrica mogu´ce je izvesti na dva naˇcina: ? funkcijom transpose ? atributom T Izvorni kod 16.3: Transponiranje matrica 1
from numpy import *
2 3 4 5 6 7
M1 = array([ [1, 0, 3, 4], [2, 2, 7 ,8], [6, 8, 3, 0], [9, 8, 2, 1]])
8 9 10
M2 = M1.T print M2
11 12 13
M3 = transpose(M1) print M3 [[1 [0 [3 [4 [[1 [0 [3 [4
2 2 7 8 2 2 7 8
16.3
6 8 3 0 6 8 3 0
9] 8] 2] 1]] 9] 8] 2] 1]]
dodavanje i brisanje elemenata polja
17
ˇ I TAVA N J E I S P R E M A N J E N U M P Y P O L J A UC
Vrlo se cˇ esto dešava da se rezultati raznih proraˇcuna ili mjerenja spremaju u tekstualne datoteke. Takve datoteke, svaka zapisana u svom formatu cˇ esto se uˇcitavaju u Python za daljnju obradu, vizualizaciju ili provjeru. Numpy pruža gotove funkcije za automatizirano uˇcitavanja tabliˇcnih podataka u NumPy polja. Jednako bitno je i mogu´cnost spremanja podataka iz NumPy polja u tekstualne datoteke. Osim tekstualnih datoteka, uˇcitavanje i spremanje NumPy polja mogu´ce je i sa binarnim datotekama. 17.1
ˇ u citavanje iz tekstualnih datoteka
Uˇcitavanje numeriˇckih vrijednosti iz tekstualnih datoteka u numpy polja vrši se sa naredbom loadtxt. Podrazumijeva se da su brojevi u tekstualnoj datoteci zapisani u retcima koji svi imaju jednak broj zapisanih vrijednosti. ¯ Arumenti naredbe loadtxt omogu´cuju detaljnije odredivanje uˇcitavanja tek¯ stualne datoteke pomo´cu razdvojnika, komentara, odredivanja pasivnih pocˇ etnih redaka te odabir stupaca za uˇcitavanje i dr. Sintaksa naredbe sa najˇceš´ce korištenim argumentima je: loadtxt(fname, comments, delimiter, skiprows, usecols)
gdje je fname ime datoteke iz koje se uˇcitavaju podaci, comments je simbol kojim zapoˇcinju pasivni retci (komentari), delimiter je simbol(i) kojim su razdvojene vrijednosti u retcima, skiprows je broj poˇcetnih redaka koji se preskaˇcu prilikom uˇcitavanja a usecols je lista indeksa stupaca koji se uˇcitavaju. Izvorni kod 17.1: Sadržaj datoteke data.txt 1 2
Tehniˇ cki fakultet Zavod za mehaniku fluida i raˇ cunarko inženjerstvo
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
1 2 3 4 5
8.14 28.72 8.37 26.79 4.41 26.55 6.74 22.48 5.30 24.30 * ovo je komentar 6 6.11 22.14 7 2.10 25.96 7.40 24.40 *8 9 0.07 22.04 10 8.45 23.07 11 2.91 22.07 12 9.14 20.70 13 7.62 23.83
-0.12 -0.47 -0.44 -0.55 -0.70
126.04 130.96 125.82 133.24 137.91
5 9 2 0 9
-0.87 -0.90 -0.03 -0.73 -0.47 -0.07 -0.10 -0.51
102.43 137.88 122.03 143.81 137.48 116.26 132.36 111.39
7 2 1 2 0 6 9 1
Izvorni kod 17.2: Uˇcitavanje iz tekstualne datoteke 1
# -*- coding: utf-8 -*-
2 3
from numpy import *
81
Zadana vrijednost argumenta delimiter je None što znaˇci da se redak dijeli na temelju razmaka (podrazumijeva i tabulatore) i više uzastopnih razmaka smatra kao jedan razmak.
ˇ u citavanje i spremanje numpy polja
82
4 5 6
M = loadtxt(’data.txt’, skiprows=4, comments=’*’, usecols=(1, 3, 5)) print M [[ [ [ [ [ [ [ [ [ [ [ [
8.14 8.37 4.41 6.74 5.3 6.11 2.1 0.07 8.45 2.91 9.14 7.62
-0.12 -0.47 -0.44 -0.55 -0.7 -0.87 -0.9 -0.73 -0.47 -0.07 -0.1 -0.51
5. 9. 2. 0. 9. 7. 2. 2. 0. 6. 9. 1.
] ] ] ] ] ] ] ] ] ] ] ]]
Naprednije mogu´cnosti pri uˇcitavanju NumPy polja iz tekstualnih datoteka pruža naredba genfromtxt. http://penandpants.com/2012/03/09/reading-text-tables-with-python/
17.2
spremanje u tekstualne datoteke
Naredba savetxt omogu´cuje jednostavno spremanje NumPy polja u tekstualne datoteke. savetxt(fname, X, fmt, delimiter, newline, header, footer, comments)
18
ˇ NI RAC ˇ UN M AT R I C
18.1
rješavanje sustava linearnih jednadžbi
Za rješavanje sustava linearnih jednadžbi A·x = b
(18.1)
koristi se NumPy naredba solve: solve(a, b)
gdje je a matrica sustava a b vektor slobodnih cˇ lanova. Izvorni kod 18.1: Rješavanje sustava linearnih jednadžbi 1
from numpy import *
2 3 4 5 6 7 8
A = array([ [ 1.0, 3.0, 6.0], [-2.0, 0.0, 3.0], [ 8.0, -2.0, 0.0] ]) b = array([2.0, 6.0, 0.0])
9 10
x = linalg.solve(A, b)
11 12
print x [-0.58823529 -2.35294118
1.60784314]
83
Dio III PRIPREMA, OBRADA I VIZUALIZACIJA P O D ATA K A
19
OSNOVNI 2D GRAFOVI
Terminologija: ? Figure = prozor ? Axes = prostor crtanja ? Axis = osi
Prozor Prostor crtanja
Prostor crtanja
Os y
Os y
Os x
Os x
Slika 19.1: Matplotlib elementi
19.1
linijski grafovi
Osnovna naredba u matplotlibu je plot i služi za crtanje grafova pomo´cu linija ili toˇcaka. Osnovna sintaksa naredbe je plot(y) plot(x, y)
gdje su x i y vektori koordinata toˇcaka koje želimo vizualizirati. U sluˇcaju da vektor x koordinata nije zadan, koristi se uniformni vektor [0, 1, 2, ..., n] gdje je n broj cˇ lanova vektora y. U sluˇcaju da su zadani i vektor x i vektor y, tada oni moraju imati isti broj cˇ lanova. Više uzastopnih plot naredbi c´ e nacrtati više linija na istom grafu. Naredba plot ne prikazuje graf, graf se iscrtava na ekranu pozivom funkcije show. Izvorni kod 19.1 kreira dva linijska grafa koriste´ci naredbu plot a potom, naredbom show, graf prikaže na ekranu (Slika 19.2) Izvorni kod 19.1: Jednostavan graf 1 2
from pylab import * from numpy import *
3 4
plot([3, 6, 3, 2, 4])
5
87
88
osnovni 2d grafovi
6 7 8
x = linspace(0, 4, 100) y = 5*cos(x)/(1 + x**2) plot(x, y)
9 10
show()
¯ Slika 19.2: Prozor sa grafom napravljen izvodenjem izvrnog koda 19.1
Dodatni argument naredbe plot omogu´cuje definiranje izgleda linije i markera pomo´cu znakova. Znakovi za definiranje vrste linije, boje linije te ¯ vrste markera kombiniraju se u stringu koji se prosljeduje funkciji plot. Simboli za definiranje vrste linije, boje linije i vrste markera prikazani su u tablicama 19.1, 19.2 i 19.3. Simboli se mogu kombinirati u proizvoljnom redoslijedu. Ako je izostavljen simbol za boju, primjenjuje se zadana vrijednost boje. Markeri se ne prikazuju izostavljanjem simobla za vrstu markera. Izostavljanjem simbola za vrstu linije, ako je zadana vrsta markera linija se ne prikazuje a puna linija se iscrtava u sluˇcaju da vrsta markera nije zadana. Simbol
Vrsta linije
’-’
Puna linija
’-’
Crtkana linija
’-.’
Crta-toˇcka
’:’
Toˇckasta linija Tablica 19.1: Vrste linija
19.1 linijski grafovi
Simbol
Boja
’b’
Plava
’r’
Crvena
’g’
Zelena
’c’
Cijan
’m’
Magenta
’y’
Žuta
’k’
Crna
’w’
Bijela Tablica 19.2: Simboli boja
Detaljnije i fleksibilnije definiranje boja opisano je u poglavlju (19.2.1). Simbol
Vrsta markera
’.’
Toˇckasti
’,’
Piksel
’o’
Kružni
’v’
Trokutasti prema dolje
’ˆ’
Trokutasti prema gore
’<’
Trokutasti prema lijevo
’>’
Trokutasti prema desno
’s’
Kvadratni
’p’
Peterokutni
’*’
Zvijezdasti
’h’
Šesterokutni 1
’H’
Šesterokutni 2
’+’
Plus
’x’
Križi´c
’D’
Romb
’d’
Tanki romb
’|’
Vertikalna linija
’_’
Horizontalna linija Tablica 19.3: Vrste markera
U izvornom kodu 19.2 upotrebljene su razliˇcite varijante linija, markera i boja (Slika 19.3). Izvorni kod 19.2: Kontrola linija i markera 1 2
from pylab import * from numpy import *
3 4 5 6 7
plot([1, plot([3, plot([2, plot([5,
8 9
show()
6, 2, 3, 4,
3, 1, 5, 2,
2, 3, 6, 4,
4], ’r--o’) 1], ’g-.D’) 2],’r-.x’) 5],’ks:’)
89
90
osnovni 2d grafovi
6 5 4 3 2 10.0
0.5
1.0
1.5
2.0
2.5
3.0
3.5
4.0
¯ Slika 19.3: Graf napravljen izvodenjem izvornog koda 19.2
19.2
naprednija kontrola linijskih grafova
Bolju kontrolu izgleda linijskih grafova u matplotlibu mogu´ce je ostvariti sa dodatnim parametrima naredbe plot. 19.2.1
Boje
Argumentom color (ili skra´ceno c) mogu´ce je preciznije definirati boju linije: plot(x, plot(x, plot(x, plot(x,
y, y, y, y,
color color color color
= = = =
gray_string) hex_string) rgb_tuple) html_string)
gdje je ? gray_string string koji specificira nijansu sive boje kao udio bijele (npr. color = ’0.72’) ? hex_string string koji specificira heksidecimalni zapis RGB boje (npr. color = ’#FF8C00’) ? rgb_tuple tuple kojim se specificiraju udjeli crvene, zelemne i plave (RGB) boje (npr. color = (0.1, 0.5, 0.3)) ? html_string string koji sadrži HTML naziv boje (npr. color=’Cyan’, color=’Crimson’) 19.2.2
Markeri
Izgled markera se može detaljnije specificirati pomo´cu više parametara naredbe plot:
19.2 naprednija kontrola linijskih grafova
? marker za definiranje vrste tj. oblika markera, ? markersize ili ms za definiranje veliˇcine markera, ? markeredgecolor ili mec za definiranje boje ruba markera, ? markeredgewidth ili mew za definiranje debljine ruba markera, ? markerfacecolor ili mfc za definiranje boje lica markera ? markerfacecoloralt ili mfcalt za definiranje izmjenjuju´ce boje lica markera, ? markerevery za definiranje koliko toˇcaka c´ e biti prikazane (npr. svaka peta). 1 2 3 4 5 6
plot(x, y, markeredgecolor = ’r’, markeredgewidth = 2, markerfacecolor = ’b’, markerfacecoloralt = ’g’, markersize = 4, markerevery = 5)
# # # # # #
Boja ruba markera - crvena Debljina ruba Boja lica - plava Izmjenjuju´ ca boja lica - zelena Velicina markera Crtaj svaki peti marker
Argumentom label omogu´cuje se oznaka tj. opis krivulje, koji se prikazuje u legendi grafa. U izvornom kodu 19.3 upotrebljene su razliˇcite varijante linija, markera i boja (Slika 19.4). Izvorni kod 19.3: Naprednija kontrola linija i markera 1 2
from pylab import * from numpy import *
3 4 5 6 7 8 9 10 11
X = np.linspace(-np.pi, np.pi, 256,endpoint=True) C,S = np.cos(X), np.sin(X) X2=[-3, -2, -0.5, 1.2, 2.8] Y2=[0.3, 0.9, 0.5, 0.1, 0.62] plot(X, C, color="blue", linewidth=2.5, linestyle="-") plot(X, S, color="red", linewidth=2.5, linestyle="-") plot(X2, Y2, color="green", linestyle="-", marker="o", markersize=10) show()
91
92
osnovni 2d grafovi
1.0
0.5
0.0
0.5
1.0 4
3
2
1
0
1
2
3
4
¯ Slika 19.4: Graf napravljen izvodenjem izvornog koda 19.3
19.3 Stvaranje prvog prozora nije nužno. Naredbe za crtanje grafova (npr. plot) same c´ e kreirati prozora ako ve´c ne postoji.
svojstva prozora, prostora crtanja i osi
Novi prozor se stvara pomo´cu funkcije figure, koja vra´ca handle na prozor a po potrebi može primati dodatne argumente figure() fig1 = figure() fig1 = figure(figsize = (12, 10), dpi = 300)
Dva argumenta koji se najˇceš´ce koriste su figsize i dpi. figsize prima tuple koji specificira širinu i visinu prozora u inˇcima a pomo´cu argumenta dpi (dots per inch) regulira se rezolucija koja je posebno bitna kod spremanja grafova u raster format ili pri spremanju animacija u video format. Naredbama xlabel i ylabel mogu´ce je dodati naslove osi. Sintaksa obje naredbe je identiˇcna: xlabel(’Opis x osi’) ylabel(’Opis y osi’)
¯ Naredbama xlim i ylim odreduju se granice intervala koji se prikazuje na prostoru crtanja. Sintaksa naredbe je: xlim( (xmin, xmax) ) xlim( xmin, xmax )
Dodaju li se izvornom kodu 19.3 sljede´ce linije, 1 2
xlim(X.min()*1.1, X.max()*1.1) ylim(C.min()*1.1, C.max()*1.1)
mogu´ce je dobiti sljede´ci rezultat:
19.3 svojstva prozora, prostora crtanja i osi
1.0
0.5
0.0
0.5
1.0 3
2
1
0
1
2
3
Slika 19.5: Izmijenjene granice grafa
1 2 3
xlim(0, 5) # Donja i gornja granica ylim(ymax=1) # Samo gornja granica ylim(ymin=-1) # Samo donja granica
Mogu´ce je promijeniti i ticks. U sluˇcaju da je potrebno i izvornom kodu 19.3 prikazati vrijednosti od x os od −π do π s korakom od π/2 i y os od -1 od 1 s korakom od 1, potrebno je dodati sljede´ce linije: 1 2
xticks( [-np.pi, -np.pi/2, 0, np.pi/2, np.pi]) yticks([-1, 0, +1])
Rezultat je prikazan na sljede´coj slici.
93
94
osnovni 2d grafovi
1
0
1 3.142
1.571
0.000
1.571
3.142
Slika 19.6: Custom ticks
Još je potrebno promijeniti oznake na osima: 1 2 3 4
xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi], [r’$-\pi$’, r’$-\pi/2$’, r’$0$’, r’$+\pi/2$’, r’$+\pi$’]) yticks([-1, 0, +1], [r’$-1$’, r’$0$’, r’$+1$’])
što rezultira sljede´cim grafom:
+1
0
−1
−π
−π/2
0
Slika 19.7: Custom ticks
U nekim situacijama je korisno pomaknuti osi:
+ π/2
+π
19.3 svojstva prozora, prostora crtanja i osi
1 2 3 4 5 6 7
ax = gca() ax.spines[’right’].set_color(’none’) ax.spines[’top’].set_color(’none’) ax.xaxis.set_ticks_position(’bottom’) ax.spines[’bottom’].set_position((’data’,0)) ax.yaxis.set_ticks_position(’left’) ax.spines[’left’].set_position((’data’,0))
+1
−π
−π/2
0
0
+ π/2
+π
−1
Slika 19.8: Spines
Oznake na osima su prekrivene linijama s(Slika 19.8) te ih je potrebno uˇciniti cˇ itljivijima: 1 2 3
for label in ax.get_xticklabels() + ax.get_yticklabels(): label.set_fontsize(16) label.set_bbox(dict(facecolor=’white’, edgecolor=’None’, alpha=0.65))
95
96
osnovni 2d grafovi
+1
−π
−π/2
00
+ π/2
+π
−1
Slika 19.9: Formatiranje oznaka na osima
Ukljuˇcivanje i iskljuˇcivanje mreže pomo´cnih linija na prostoru crtanja vrši se naredbom grid. grid(b=None, which=’major’, axis=’both’, **kwargs)
b je argument kojim se kontrolira da li se iskljuˇcuje ili ukljuˇcuje mreža pomo´cnih linija i može poprimiti vrijednosti true ili false ali i ’on’ ili ’off’ (kao i MATLAB). which može biti ’major’, ’minor’ ili ’both’ i služi za kontrolu glavne ili sporedne mreže pomo´cnih linija. Argumentom axis kontorilra se za koje c´ e osi biti postavljena mreža pomo´cnih linija. Vrijednosti za axis mogu biti ’both’, ’x’ ili ’y’. grid može primati dodatne argumente za detaljniju kontrolu mreže pomo´cnih linija: 1
grid(color=’k’, linestyle=’:’, linewidth=0.2)
Dodavanje naslova na prostor crtanja vrši se naredbom title: title(’Text naslova’)
Prikazivanje legende na na prostoru crtanja vrši se pomo´cu naredbe legend uz prethodno definirane opise krivulja (label). legend()
Ako u prethodno nacrtanim grafovima nije specificiran label, legendu se može napraviti i pomo´cu handleova na plotove. U tom sluˇcaju, funkcija legend prima listu handleova i listu pripadaju´cih opisa. plt1, = plot([1,2,3]) plt2, = plot([3,2,1]) legend([plt2, plt1], ["line 2", "line 1"])
¯ Dodatnim keyword argumentom loc odreduje se pozicija legende na prozoru. Vrijednosti koje se daju argumentu loc mogu biti cijeli brojevi ili stringovi koji specificiraju poziciju legende na prozoru (Tablica 19.4).
19.4 spremanje grafova
Pozicija
Broj
String
Gore desno
1
’upper right’
Gore lijevo
2
’upper left’
Dolje lijevo
3
’lower left’
Dolje desno
4
’lower right’
Desno
5
’right’
Na sredini lijevo
6
’center left’
Na sredini desno
7
’center right’
Dolje u sredini
8
’lower center’
Gore u sredini
9
’upper center’
U sredini
10
’center’
Tablica 19.4: Pozicija legende
Izvorni kod 19.4: Prikaz legende na grafu 1 2
from pylab import * from numpy import *
3 4 5 6
x = linspace(0, 10, 100) y1 = sin(x) y2 = cos(x)
7 8 9 10 11 12
figure(1, [8, 2]) plot(x, y1, label=’sinus’) plot(x, y2, label=’kosinus’) legend(loc=’upper center’) # Postavlja legendu gore na sredinu show()
1.0 0.5 0.0 0.5 1.00
sinus kosinus
4
2
6
8
10
Slika 19.10: Prikaz legende na grafu
19.4
spremanje grafova
19.5
podgrafovi
Podgrafovi omogu´cavaju postavljanje grafova u mrežu grafova. Potrebno je specificirati broj redaka i stupaca. Izvorni kod 19.5: Primjer crtanja podgrafova 1 2 3 4 5 6 7
from pylab import * from numpy import * def myticks(): xticks([-np.pi, -np.pi/2, 0, np.pi/2, np.pi], [r’$-\pi$’, r’$-\pi/2$’, r’$0$’, r’$+\pi/2$’, r’$+\pi$’]) yticks([-1, 0, +1], [r’$-1$’, r’$0$’, r’$+1$’])
97
98
osnovni 2d grafovi
8 9 10
X = np.linspace(-np.pi, np.pi, 256,endpoint=True) C,S = np.cos(X), np.sin(X)
11 12 13 14 15 16 17 18
figure(1) subplot(211) plot(X, C, color="blue", linewidth=2.5, linestyle="-") myticks() subplot(212) plot(X, S, color="red", linewidth=2.5, linestyle="-") myticks()
19 20
show()
+1
0
−1
−π
−π/2
0
+ π/2
+π
−π
−π/2
0
+ π/2
+π
+1
0
−1
Slika 19.11: Podgrafovi nastali izvršavanjem izvornog koda 19.5
Podgrafovi se iscrtavaju u slici (figure) koja se sastoji od dva grafa. Naredba subplot definira broj redaka, broj stupaca i broj grafa, koji mora biti broj 1 < fignum < numrows ∗ numcols. Varijable ne moraju biti odvojene zarezom ako vrijedi numrows ∗ numcols < 10. Odnosno, subplot(211) je ekvivalentan izrazu subplot(2,1,1). 19.6
polarni grafovi
Izvorni kod 19.6: Primjer crtanja grafa u polarnom koordinatnom sustavu 1 2
from pylab import * from numpy import *
3 4 5
fig = figure(figsize=[8,8]) ax = fig.add_subplot(111, polar=True)
6 7
subplots_adjust(bottom=0.1,top=0.9,left=0.1,right=0.9)
8 9 10
r = arange(0,1,0.001) theta = 2*2*pi*r
19.7 tips and tricks
11 12 13 14
ax.plot(theta,r, lw=2) grid(True) show()
90°
135°
45°
0.2
180°
0.4
0.6
225°
Slika 19.12: Graf u polarnom koordinatnom sustavu
tips and tricks
Use matplotlib’s calls that won’t block: Using draw(): 1 2 3 4
from matplotlib import plot, draw, show plot([1,2,3]) draw() print ’continue computation’
5 6 7
# at the end call show to ensure window won’t close. show()
Using interactive mode: 1 2 3
from matplotlib import plot, ion, show ion() # enables interactive mode plot([1,2,3]) # result shows immediatelly (implicit draw())
4 5
print ’continue computation’
6 7 8
# at the end call show to ensure window won’t close. show()
1.0
0°
315°
270°
19.7
0.8
99
20
SLOŽENIJI 2D GRAFOVI
20.1
izolinije
Prilikom vizualizacije ovisnosti funkcije (ili podataka) o dvije varijable (2D) cˇ esto se koriste izolinije. Izolinije su krivulje koje povezuju toˇcke iste (skalarne) vrijednosti. Izolinija je skup rješenja jednadžbe f(x, y) = ci
(20.1)
¯ gdje je ci konstanta za koju se odreduje izolinija. Ako za dani ci postoji rješenje jednadžbe (20.1), to rješenje predstavlja jednu ili više krivulja u ravnini x − y. Za više parametara c = (c1 , c2 , ..., cn ) dobiva se familija krivulja koje služe za 2D vizualizaciju funkcija dvije varijable. ¯ Matplotlib nudi mogu´cnost naprednog uredivanja i kontrolabilnost izolinijskih grafova. Funkcija contour služi za crtanje izolinija a countourf za ¯ izolinija. bojanje površina izmedu matplotlib.pyplot.contour matplotlib.pyplot.contourf
Obje navedene funkcije imaju identiˇcnu osnovnu sintaksu, a razlikuju se u svega nekoliko argumenta koji su specifiˇcni za stiliziranje linija odnsno bojanje ploha. U najjednostavnijoj varijanti, funkcije primaju jedan argumenti i to ma¯ tricu Z na temelju cˇ ijih vrijednosti se crtaju izolinije i plohe. Razmaci izmedu ¯ redaka i stupaca su jednaki 1 a broj izolinija se odreduje automatski. matplotlib.pyplot.contour(Z) matplotlib.pyplot.contourf(Z)
Broj nivo linija se može specificirati cijelim brojem n ili se mogu odrediti željene vrijednosti pomo´cu vektora V za koje c´ e se crtati izolinije. matplotlib.pyplot.contour(Z, n) matplotlib.pyplot.contourf(Z, n) matplotlib.pyplot.contour(Z, V) matplotlib.pyplot.contourf(Z, V)
¯ stupaca i redaka mogu se zadati pomo´cu matrica X i Y: Razmaci izmedu matplotlib.pyplot.contour(X, Y, Z) matplotlib.pyplot.contour(X, Y, Z, n) matplotlib.pyplot.contourf(X, Y, Z, n) matplotlib.pyplot.contour(X, Y, Z, V) matplotlib.pyplot.contourf(X, Y, Z, V)
Matrice X i Y sadrže x i y kordinate pripadaju´cih elemenata u matrici Z te sve tri matrice moraju biti istog oblika/dimenzija. Za jednostavljeno kreiranje takvih matrica na temelju vektora koordinata koristi se funkcija meshgrid (vidi poglavlje 14.8). 20.1.1
Mapa boja
Mapa boja (eng. colormap) je naˇcin na koji se numeriˇcka vrijednost sa intervala [0, 1] pretvara u RGBA (Red, Green, Blue, Alpha) specifikaciju boje kojom se definira udio crvene, zelene i plave boje te prozirnost.
101
102
složeniji 2d grafovi
Mapiranje boja se odvija u dva koraka: podaci koje treba vizualizirati su prvo mapirani na interval [0, 1] koriste´ci klasu matplotlib.colors.Normalize ili neku od njenih podklasa; onda se broj sa intervala [0, 1] mapira u odre¯ denu boju koriste´ci mapu boja. Matplotlib sadrži unaprijed definirane mape boja koje se nalaze u matplotlib.pyplot.cm modulu (Slika 20.1). Accent BrBG BuPu Dark2 Greens OrRd PRGn Pastel1 PiYG PuBuGn PuRd RdBu RdPu RdYlGn Set1 Set3 YlGn YlOrBr afmhot binary brg cool copper flag gist_gray gist_ncar gist_stern gnuplot gray hsv nipy_spectral pink rainbow spectral summer
Blues BuGn CMRmap GnBu Greys Oranges Paired Pastel2 PuBu PuOr Purples RdGy RdYlBu Reds Set2 Spectral YlGnBu YlOrRd autumn bone bwr coolwarm cubehelix gist_earth gist_heat gist_rainbow gist_yarg gnuplot2 hot jet ocean prism seismic spring terrain
Slika 20.1: Predefinirane mape boja u matplotlibu
Mapa boja se postavlja pomo´cu keyword argumenta cmap: matplotlib.pyplot.contour(X, Y, Z, cmap=matplotlib.pyplot.cm.hot)
Osim predefiniranih mapa boja, mogu se koristiti i ruˇcno definirane mape boja. 20.1.2
Detaljnije podešavanje grafa izolinija
Podešavanje boja u grafovima izolinija mogu´ce je se keyword argumentom colors u contour i contourf funkcijama. U funkciji contour boje se aplici¯ raju na izolinije a u funkciji contourf boje se apliciraju na površine izmedu
izolinija. Tri su osnovna naˇcina zadavanja boje: ? colors = None, boje se preuzimaju iz postavljene mape boja (vidi 20.1.1) ? colors = ’r’, postavlja se jedna boja za sve izolinije ili površine iz¯ izolinija. medu
20.1 izolinije
? colors = [’r’, ’g’, ’b’], postavlja se lista (ili tuple) boja. Boje iz liste se ponavljaju, ako ima više izolinija nego specificiranih boja. Pojedinu boju ili boju u listi se može zadavati na više naˇcina, kao što je opisano u poglavlju (19.2.1). Kada u istom prostoru crtanja postoji više grafova, bolja vidljivost svih ¯ njih grafova se postiže prozirnoš´cu. Prozirnost izolinija ili površina izmedu postavlja se pomo´cu keyword argumenta alpha. alpha može primiti decimalni broj sa intervala [0, 1] gdje je 0 potpuno prozirno (nevidljivo) a 1 je potpuno neprozirna boja. 20.1.3
Primjer
Izvorni kod 20.1: Primjer vizualizacije izolinija 1 2 3
# -*- coding: utf-8 -*import numpy as np import matplotlib.pyplot as pl
4 5 6 7
# Definiranje funckije def f(x,y): return (1 - np.sin(x) - np.sin(y)**3) * np.exp(-np.cos(x) -np.sin(y)**2)
8 9 10
# Gusto´ ca vizualizacijskih toˇ caka (po svakoj dimenziji) n = 256
11 12 13 14 15
# Diskretizacija x = np.linspace(-4, 0, n) y = np.linspace(-3, 1, n) X,Y = np.meshgrid(x, y)
16 17 18
# Ukljuˇ civanje mreže pomo´ cnih linija pl.grid()
19 20 21 22
# Crtanje površina izme¯ du izolinija # 8 - broj izolinija, alpha - prozirnost, cmap - kolormapa Cf = pl.contourf(X, Y, f(X, Y), 8, alpha=.75, cmap=pl.cm.jet)
23 24 25 26
# Crtanje izolinija # colors - boja linija, linewidth - debljina linija Cl = pl.contour(X, Y, f(X, Y), 8, colors=’black’, linewidth=.5)
27 28 29
# Dodavanje oznaka na izolinije pl.clabel(Cl, inline=1, fontsize=10)
30 31
pl.show()
103
složeniji 2d grafovi
0 0.50
0.0
3.500
00
0 2.50
0.5
1.5 00
0.5
0
0.00
3.0
1.0
1.0 1.5 2.0
0
00
3.5
3.0
2.5
2.0
1.5
1.0
0
3.0
0.50
00
3.0 4.0
00 1.0
2.0
1.000
2.5
2.50
104
0.5
¯ Slika 20.2: Graf napravljen izvodenjem izvornog koda 20.1
0.0
21
IZRADA ANIMACIJA
Izvorni kod 21.1: Jednostavan primjer animacije 1 2 3 4
# -*- coding: utf-8 -*""" Nelder-Mead metoda """
5 6 7 8
import numpy as np import matplotlib.pyplot as plt from matplotlib import animation
9 10 11 12 13
fig = plt.figure() linija, = plt.plot([], [], ’-o’) plt.xlim([0, 10]) plt.ylim([-1, 1])
14 15 16 17
def init(): linija, = plt.plot([], [], ’-o’)
18 19
return linija
20 21
def draw_frame(it):
22 23 24 25
xline = np.linspace(0.0,10.0,50) yline = np.sin(xline + it/10.0)/(1.0 +xline**2.0) linija.set_data(xline, yline)
26 27
return linija
28 29 30
Writer = animation.writers[’ffmpeg’] writer = Writer(fps=5, metadata=dict(artist=’sim.riteh.hr’), bitrate=3600)
31 32 33
anim = animation.FuncAnimation(fig, draw_frame, init_func=init, frames=500, interval=2, repeat=False)
34 35 36
anim.save(’nelder-mead.avi’, writer=writer) plt.show()
105
Dio IV ˇ KE METODE NUMERIC
22
R J E Š AVA N J E N E L I N E A R N I H J E D N A D Ž B I
Cilj numeriˇckih metoda za rješavnje nelinearnih jednadžbi (eng. root finding) je odrediti nultoˇcku neprekidne realne funkcije f : R → R to jest riješiti jednadžbu f(x) = 0.
(22.1)
Mogu´ce je da funkcija f ima više realnih nultoˇcaka i da su neke višestruke. ¯ funkcija f možda uop´ce nema realnih nultoˇcaka. Takoder, Ako za neprekidnu funkciju vrijedi f(a) f(b) 6 0 tada funkcija na intervalu [a, b] mijenja predznak pa postoji barem jedna nultoˇcka na odabranom intervalu. Ako je poznato da je funkcija i monotona na intervalu [a, b] tada je nultoˇcka jedinstvena. Osnovni korak numeriˇckih metoda je separirati jedan korijen ξ jednadžbe (22.1). Nakon što smo izolirali jedno rješenje, nekom odabranom numeriˇckom metodom formiramo niz aproksimacija xi → ξ. Numeriˇcku metodu zaustavljamo kada je zadovoljen zadani kriterij toˇcnosti |ξ − xi | < . Postoji više numeriˇckih metoda za rješavanje nelinearnih funkcija, a neko¯ liko najznaˇcajnijih c´ e biti obradeno u ovom poglavlju. Numeriˇcke metode se razlikuju po stabilnosti, naˇcinu primjene i brzini konvergencije (red konvergencije). Definicija 22.1 Neka niz (xi ), dobiven nekom iterativnom metodom, konvergira prema ξ Ako postoje dvije pozitivne konstante C, r takve da vrijedi |ξ − xi+1 | 6C i→∞ |ξ − xi |r lim
tada kažemo da metoda ima red konvergencije r. S obzirom na red konvergencije r, iterativna numeriˇcka metoda konvergira: 1. linearno ako je r = 1, 2. superlinearno ako je 1 < r < 2, 3. kvadratiˇcno ako je r = 2, 4. kubiˇcno ako je r = 2. 22.1
metoda bisekcije
Metoda bisekcije namjenjena je rješavnju jednadžbe f(x) = 0 na intervalu ¯ [xl , xd ] koriste´ci ogradivanje (eng. bracketing) Da bi se metoda mogla primjeniti, funkcija f(x) mora biti neprekidna te mora vrijediti f(xl ) · f(xd ) 6 0.
109
110
rješavanje nelinearnih jednadžbi
Zbog navedenih uvjeta, funkcija f(x) ima bar jedan korijen x0 na intervalu [xl , xd ]. ¯ Biskecija je jedna od metoda ogradivanja, u kojoj se u svakom koraku raˇcuna vrijednost funkcije na polovici intervala.
xs =
xl + xd 2
Na temelju vrijednosti funkcije u rubnim toˇckama te u centralnoj toˇcki, ¯ odreduje se novi, dvostruko uži, interval. Ako je f(xl ) · f(xs ) < 0 tada je x0 ∈ [xl , xs ], a ako je f(xs ) · f(xd ) < 0 tada je x0 ∈ [xs , xd ]. Prepolavljanje se iterativno ponavlja (Slika 22.1). U sluˇcaju da je f(xs ) = 0, ¯ traženi korijen funkcije. tada je pronaden
f(x)
xd xl
x f(x)
Slika 22.1: Skica metode biskecije
Metoda biskecije, ako su navedeni uvjeti zadovoljeni, c´ e sigurno konvergirati u jedan od korijena funkcije f(x) na intervalu [xl , xd ]. Apsolutna greška se prepolavlja u svakom koraku iteracije pa metoda konvegira linearno, što je, u odnosu na druge metode, relativno sporo. Osnovna sintaksa: bisect(f, a, b)
gdje je f funkcija, a a i b su granice intervala na kojem se traži korijen funkcije. Dodatni argumenti omogu´cuju kontrolu i pregled konvergencije:
optimize.bisect
poziva _zeros._bisect,
args=() xtol=1e-12 rtol=4.4408920985006262e-16 maxiter=100 full_output=False disp=True
koja je implementirana u C-u.
gdje je xtol apsolutna tolerancija, rtol relativna tolerancija, maxiter maksimalni broj iteracija, full_output omogu´cuje dohva´canje dodatnih informacija o konvergenciji i disp omogu´cuje podizanje RuntimeError u sluˇcaju da metoda ne konvergira. Izvorni kod 22.1: Primjer pronalaženja nultoˇcke funkcije metodom biskecije 1 2 3
#!/usr/bin/python import scipy.optimize as optimize from numpy import cos
4 5
def f(x):
22.2 newton-raphsonova metoda
6
111
return cos(x)**2 + 6 - x
7 8 9 10 11 12
# 0<=cos(x)**2<=1, so the root has to be near x=7 x0, S = optimize.bisect(f,6,8,full_output=True) print x0 print S.iterations print S.function_calls 6.77609231632 41 43
22.2
newton-raphsonova metoda
Za razliku od nelinearne funkcije, traženje nultoˇcke linearne funkcije je bitno lakši zadatak. Osnovna ideja Newton-Raphsonove metode je lokalna aproksimacija nelinearne funkcije f(x) najboljom linearnom aproksimacijom. Ako je poznata derivacija funkcije f(x) tada je u blizini x1 mogu´ce funkciju f(x) aproksimirati tangentom f(x) ≈ T (x) = f(x1 ) + f 0 (x1 )(x − x1 ). x1 je poˇcetna aproksimacija nultoˇcke, a x0 − f(x1 )/f 0 (x1 ) (nultoˇcka tangente T (x)) bi trebala biti bolja aproksimacija nultoˇcke. Niz aproksimacija xi+1 = xi −
f(xi ) f 0 (xi )
(22.2)
bi trebao konvergirati nultoˇcki funkcije f(x). . Za ovu iterativnu metodu potrebno je zadati dobru poˇcetnu aproksimaciju nultoˇcke i derivaciju funkcije (Slika 22.2). f(x)
y
x3
x4 x2
x1
x
Slika 22.2: Newton-Raphsonova metoda
Osnovna sintaksa: newton(func, x0, fprime)
gdje je func funkcija, x0 poˇcetna aproksimacija nultoˇcke i fprime prva derivacija funkcije. Dodatni argumenti omogu´cuju kontrolu i konvergencije: args=() tol=1e-12 maxiter=100 fprime2=None
gdje je tol apsolutna tolerancija, maxiter maksimalni broj iteracija i fprime2 je druga derivacija funkcije koja omogu´cuje ubrzanje konvergencije.
NewthonRaphsonova metoda je poznata i kao Newtonova metoda ili metoda tangente
112
rješavanje nelinearnih jednadžbi
Izvorni kod 22.2: Primjer pronalaženja nultoˇcke funkcije metodom tangente 1
from scipy import optimize
2 3 4 5 6
def fun(t): return t**2-2 def fprim(t): return 2*t
7 8
print optimize.newton(fun, 1., fprim,
tol=1.e-5)
1.41421356237
Newton-Raphsonova metoda konvergira kvadratiˇcno pa je znatno je brža od metode bisekcije, ali je bisekcija stabilnija i robusnija. Iz jednadžbe (22.2) može se zakljuˇciti da c´ e Newton-Raphsonova metoda biti nestabilna kada ¯ f 0 (x) u je f 0 (x) ≈ 0 odnosno kada je tangenta skoro horizontalna. Takoder, mnogim sluˇcajevima nije poznata ili je vrlo zahtjevna za raˇcunanje. 22.3
sekanta
Kada derivacija funkcije nije poznata tada je mogu´ce modificirati metodu tangente na naˇcin da se funkcija f(x) aproksimira nekom sekantom koja dobro aproksimira tangentu. U tom sluˇcaju moraju se zadati dvije poˇcetne aproksimacije nultoˇcke funkcije, ali derivacija funkcije nije potrebna jer je mogu´ce aproksimirati derivaciju: f(x) ≈ S(x) = f(x2 ) +
f(x2 ) − f(x1 ) (x − x2 ). x2 − x1
Odnosno mogu´ce je formirati niz aproksimacija xi+1 = xi −
f(xi )(xi − xi−1 ) . f(xi ) − f(xi−1 )
(22.3)
Osnovna sintaksa: newton(func, x0)
gdje je func funkcija, a x0 poˇcetna aproksimacija. Metoda sekante je nešto sporija od metode tangenete, ali je ipak znatno ¯ brža od bisekcije. Kažemo da sekanta konvergira superlinearno. Takoder, metoda sekante postaje nestabilna u sluˇcaju kada je sekanta skoro horizontalna. 22.4
brentova metoda
Osnovna sintaksa: brent(func, a, b)
22.5 zadaci
22.5
zadaci
Zadatak 22.1 Lopta (sfera) je uronjena u vodu i postiže stanje ravnoteže.
Volumen uronjenog dijela lopte iznosi ZH V(H) =
πr(h)2 dh
0
ZH V(H) =
R2 − (h − R)2 dh =
0
ZH
2Rh − h2 dh
0
H3 3 Uzgon koji daje uronjeni dio lopte iznosi V(H) = RH2 −
U(H) = V(H) · ρ · g U stanju ravnoteže, uzgon je jednak težini lopte. U(H) = m · g H3 = m·g 3 Lopta mase m = 0.4kg i promjera R = 0.22m stavljena je u vodu gusto´ce ρ = 1024kg/m3 . Koliko c´ e lopta biti uronjena (u stanju ravnoteže)? RH2 −
113
23
INTERPOLACIJE
ˇ Cesto se javlja potreba da na temelju nepotpunih ili rijetkih podataka treba procjeniti odnosno izraˇcunati vrijednosti u željenim toˇckama. Interpolacija je metoda konstrukcije novi toˇcaka unutar raspona diskretnog skupa poznatih toˇcaka podataka. Interpolacije možemo klasificirati s obzirom na : ? broj dimenzija danog interpolacijskog problema, ? interpolacijsku funkciju (linearna, spline itd.), ? na strukturu zadanih diskretnih podataka (zadani na mreži toˇcaka ili na nepravilno razbacanim toˇckama (scatterd)) 23.1
1d interpolacija
Klasa interp1d u modulu scipy.interpolate omogu´cuje 1D interpolaciju. interp1d(x, y, kind, axis, copy, bounds_error, fill_value)
gdje je x 1D monotono rastu´ce polje polje a y n-dimenzionalno polje. Dimenzija y-a duž koje se vrši interpolacija treba biti iste dužine kao i x. kind može biti ’linear’, ’nearest’, ’zero’, ’slinear’, ’quadratic’, ’cubic’ ¯ ili cijeli broj koji specificira red spline inerpolacije. Parametar axis odreduje dimenziju y-a duž koje se vrši interpolacija. Pozivanja interpolacije izvan intervala zadanih toˇcaka može se kontrolirati parametrima bounds_error i ¯ fill_value. bounds_error odreduje da li se podiže error u sluˇcaju pokušaja interpolacije van granica a fill_value definira vrijednost koju interpolacija u tom sluˇcaju vra´ca. Izvorni kod 23.1: Primjer razliˇcitih 1D interpolacija 1 2 3
from numpy.random import * from scipy import interpolate from pylab import *
4 5 6
X = linspace(0., 10., 6) Y = array([1.6, 4., 3.4, 1.6, 1.8, 1.2])
7 8
x = linspace(0., 10., 101)
9 10 11
f1 = interpolate.interp1d(X, Y, kind=’linear’) y1 = f1(x)
12 13 14
f2 = interpolate.interp1d(X, Y, kind=2) y2 = f2(x)
15 16 17
f3 = interpolate.interp1d(X, Y, kind=3) y3 = f3(x)
18 19 20 21 22 23 24
figure(1, figsize=[8, 3]) plot(X, Y, ’o’) plot(x, y1, label=’linearna’) plot(x, y2, label=’spline 2. reda’) plot(x, y3, label=’spline 3. reda’) subplots_adjust(bottom=0.1,top=0.95,left=0.05,right=0.98)
115
116
interpolacije
25 26
legend() show()
4.5 4.0 3.5 3.0 2.5 2.0 1.5 1.00
linearna spline 2. reda spline 3. reda
2
4
6
8
10
Slika 23.1: Primjer razliˇcitih 1D interpolacija
23.2
2d i n-d interpolacija
U sluˇcaju dvo-dimenzionalne (ili više) interpolacije, mogu´ce je interpolacijski problem postaviti na diskretnim podacima zadanim na mreži toˇcaka ili nepravilno razbacanim toˇckama (scatterd). Za interpolaciju vrijednosti zadanih na N-D nestrukturiranim toˇckama koristi se funkcija griddata:
Parametar values može biti 2D polje, pa se na istim zadanim toˇckama može zadati više veliˇcina koje se mogu interpolirati preko jednog poziva interpolacijske funkcije.
griddata(points, values, xi, method, fill_value)
gdje je points numpy polje koje sadrži koordinate zadanih diskretnih podataka. Oblik polja points je (broj_tocaka, broj_dimenzija). Pripadaju´ce vrijednosti zadaju se preko numpy polja values. xi je polje toˇcaka za koje je potrebno interpolirati zadane podatke. method specificira metodu interpolacije i podržane su sljede´ce metode: ? nearest ? linear ? cubic Parametrom fill_value definira se vrijednost koju vra´ca interpolacijska funkcija za toˇcke izvan podruˇcja zadanih podataka. Interpolacija na podacima zadanim na pravilnoj mreži toˇcaka se vrši pomo´cu klase interp2d. interp2d(x, y, z, kind, copy, bounds_error, fill_value)
U izvornom kodu 23.2 rješen je problem intepolacije dvo-dimenzionalnog polja zadanog vrijednostima u 25 toˇcaka (uniformna mreža 5x5). Zadane toˇcke te rješenje linearne i kubiˇcne interpolacije prikazani su na slici 23.2 na kojo jse jasno vidi razlika u glatko´ci linearne i kubiˇcne interpolacijske funkcije. Izvorni kod 23.2: Primjer linearne i kubiˇcne 2D interpolacije 1 2 3 4 5
from from from from
numpy.random import * scipy import interpolate pylab import * mpl_toolkits.mplot3d import Axes3D
23.2 2d i n-d interpolacija
6 7 8 9 10 11 12 13 14
X = linspace(0., 2., 5) Y = linspace(0., 4., 5) Z = array([ [1.3, 1.4, 1.1, 1.0, [1.6, 1.1, 1.2, 1.3, [1.2, 1.5, 1.6, 1.5, [1.2, 1.4, 1.5, 1.4, [1.3, 1.2, 1.1, 1.1, ])
0.8], 1.5], 1.6], 1.3], 1.2]
15 16
XX, YY = np.meshgrid(X, Y)
17 18 19
f1 = interpolate.interp2d(X, Y, Z, kind=’linear’) f2 = interpolate.interp2d(X, Y, Z, kind=’cubic’)
20 21 22 23
x = linspace(0., 2., 51) y = linspace(0., 4., 31) xx, yy = meshgrid(x, y)
24 25 26
z1 = f1(x, y) z2 = f2(x, y)
27 28
fig = plt.figure(figsize=[8, 3])
29 30 31 32 33
subplot(1, 3, 1) scatter(XX, YY, c=Z, marker = ’s’, s = 100, cmap = cm.Purples) xlim(0, 2) ylim(0, 4)
34 35 36 37 38
subplot(1, 3, 2) CS = plt.contourf(xx, yy, z1, cmap = cm.Purples) xlim(0, 2) ylim(0, 4)
39 40 41 42 43
subplot(1, 3, 3) CS = plt.contourf(xx, yy, z2, cmap = cm.Purples) xlim(0, 2) ylim(0, 4)
44 45 46 47
subplots_adjust(bottom=0.3,top=0.95,left=0.05,right=0.95) cax = fig.add_axes([0.05, 0.1, 0.9, 0.1]) fig.colorbar(CS, cax=cax, orientation=’horizontal’)
48 49
show()
4.0 4.0 4.0 3.5 3.5 3.5 3.0 3.0 3.0 2.5 2.5 2.5 2.0 2.0 2.0 1.5 1.5 1.5 1.0 1.0 1.0 0.5 0.5 0.5 0.00.0 0.5 1.0 1.5 2.00.00.0 0.5 1.0 1.5 2.00.00.0 0.5 1.0 1.5 2.0 0.75
0.90
1.05
1.20
1.35
Slika 23.2: Primjer 2D interpolacije
1.50
1.65
117
24
REGRESIJE
¯ U inženjerskoj praksi, prilikom odredivanja relativno jednostavne veze iz¯ dvije veliˇcine cˇ esto se nailazi na veliki broj podataka koji zapravo medu predefiniraju tu vezu. Takvi podaci su, najˇceš´ce, dobiveni eksperimentom i mjerenjima. U takvim sluˇcajevima potrebno je odrediti sve parametre modela (funkcije) da se što toˇcnije i preciznije opišu podaci. Primjer Poznat je zakon koji povezuje silu istezanja opruge F i promjenu duljine opruge ∆l: F = k · ∆l gdje je k konstanta opruge. Potrebno je odrediti nepoznatu konstante k na osnovu jednostavnog mjerenja sile i promjene duljine opruge. Nizom mjerenja dobiveni su sljede´ci podaci: F [N]
7.0
11.0
12.0
16.0
18.0
20.0
21.0
24.0
∆l[mm]
3.0
6.5
7.0
7.5
8.5
10.5
11.0
12.5
24.1
metoda najmanjih kvadrata
24.2
linearna regresija
Izvorni kod 24.1: Primjer linearne regresije 1 2 3 4
# -*- coding: utf-8 -*""" Linearna regresija """
5 6
from pylab import *
7 8
X = [1.0, 0.6, 1.065, 1.5, 1.72, 2.06, 2.84, 3.1, 3.15, 3.26, 3.55, 3.61, 4.0]
119
120
regresije
9
Y = [10.0, 10.6, 11.5, 10.8, 11.0, 20.6, 20.8, 30.1, 32.7, 33.4, 38.0, 37.0, 48.2]
10 11 12
k = np.polyfit(X,Y,1) print ’Regresijski pravac: y=%.3fx%+.3f’ % (k[0], k[1])
13 14 15
xr = np.linspace(np.min(X), np.max(X), 100) yr = xr*k[0] + k[1]
16 17 18
plot(X, Y, ’ro’, label=u’Toˇ cke’) plot(xr, yr, ’b-’, lw=2, label=u’Regresijski pravac’)
19 20 21 22
legend(loc=2) grid() show() Regresijski pravac: y=10.846x-2.035
50
To ke Regresijski pravac
40 30 20 10 0 0.5
1.0
1.5
2.0
2.5
3.0
3.5
4.0
Slika 24.1: Regresijski pravac dobiven izvornim kodom 24.1
24.3
zadaci
Zadatak 24.1 U laboratoriju se koristi skupi termometar T2 cˇ ije je mjerenje pouzdano i znatno jeftiniji i robusniji termometar T1 cˇ ije mjerenje trebamo ko¯ T1 i rigirati u odnosu na termometar T1. Pretpostavlja se da je veza izmedu T2 linearna. U tablici su dana mjerenja istog objekta u isto vrijeme s termometrima T1 i T2. T1
[◦ C]
19.1
22.9
31.5
42.2
50.2
T2
[◦ C]
18.5
22.2
30.6
41.1
49.1
Ako termometru T1 pokazuje 35◦ C kolika bi temperatura bila na termometru T2? Ako termometru T1 pokazuje 12◦ C kolika bi temperatura bila na termometru T2?
24.3 zadaci
Zadatak 24.2 Vrijednost gravitacijskog ubranje Zemlje g se minjenja s visinom, odnosno udaljenoš´cu od zemljine površine h, kako je dano u tablici. Izraˇcunaj vrijednost gravitacijskog ubrzanja na visini h = 126 km, koriste´ci kvadratnu regresiju. h[km] h i g sm2
0.1
20.0
40
60
80
100
120
140
9.81
9.7486
9.6789
9.6728
9.5681
9.5091
9.4506
9.3926
121
25
R J E Š AVA N J E S U S TAVA L I N E A R N I H J E D N A D Ž B I
Sustav linearnih jednadžbi a11 · x1
+
a12 · x2
+ ...
+
a1n · xn
=
b1
a21 · x1 .. .
+
a22 · x2 .. .
+ ...
+
a2n · xn .. .
=
b2 .. .
am1 · x1
+ an2 · x2
+ ...
+ ann · xn
se može zapisati matriˇcno b x a11 a21 . . . a1n 1 1 a 12 a22 . . . a2n x2 b2 = · . .. .. .. .. .. .. . . . . . bn xn an2 an2 . . . ann
(25.1)
= bn
(25.2)
odnsono A·x = b
(25.3)
Matrica A se naziva matrica sustava, x je vektor nepozanica a b je vektor slobodnih cˇ lanova. Primjer Ulaznice za sajam se prodaju po cjeni od 5 kn za djecu i 20 kn za odrasle. ¯ Na sajmu je bilo ukupno 341 osoba i od ulaznica je zaradeno 4810 kn. Koliko je bilo odraslih a koliko djece na sajmu? Rješenje Neka je d broj djece a o broj odraslih. Ukupan broj ljudi na sajmu je ¯ od ulaznica: 5 · d + 20 · o = 4810. Dvije d + o = 341. Novac zaraden navedene linearne jednadžbe tvore sustav: # " # " # " 341 1 1 d = · 5 20 o 4810
25.1
metoda gaussove eliminacije
Matrica sustava zapisana u datoteci A.txt: 12 2 3 4 1 22 1 2 0 2 7 1 1 2 0.5 8
Vektor slobodnih cˇ lanova zapisan u datoteci B.txt: -0.5 2.3 0.8 3.1
123
124
rješavanje sustava linearnih jednadžbi
Izvorni kod 25.1: Primjer naivne Gaussove eliminacije 1 2 3 4
# -*- coding: utf-8 -*""" GAUSSOVA ELIMINACIJA """
5 6 7
from numpy import * from scipy.optimize import *
8 9 10
A = loadtxt(’A.txt’) B = loadtxt(’B.txt’)
11 12
n = len(B)
13 14 15 16 17 18 19 20
# Naivna eliminacija for k in range(0,n): for i in range(k+1,n): faktor = A[i,k]/A[k,k] for j in range(k+1,n): A[i,j] = A[i,j] - faktor*A[k,j] B[i] = B[i] - faktor*B[k]
21 22 23 24 25 26 27 28
# Supstitucija unatrag X = empty(shape(B)) for i in range(n-1,-1,-1): suma = 0 for j in range(i+1,n): suma = suma + A[i,j]*X[j] X[i] = (B[i]-suma)/A[i,i]
29 30
print X
31 32 33 34 35
# Scipy rjesenje A = loadtxt(’A.txt’) B = loadtxt(’B.txt’) print linalg.solve(A,B)
¯ Izvodenje izvornog koda 25.1 vidimo da su oba ispisana rješenja (Gaussova eliminacija i numpy funkcija linalg.solve) identiˇcna: [-0.19367432 [-0.19367432
25.2
0.07619065 0.07619065
0.03675057 0.03675057
0.39036472] 0.39036472]
lu dekompozicija
Primjer LU dekompozicije u izvornom kodu 25.2 koristi datoteke A.txt i B.txt iz prethodnog poglavlja (25.1). Izvorni kod 25.2: Primjer LU dekompozicije 1 2 3 4
# -*- coding: utf-8 -*""" LU DEKOMPOZICIJA """
5 6
from numpy import *
7 8 9
A = loadtxt(’A.txt’) B = loadtxt(’B.txt’)
10 11
n = len(B)
12 13
# LU dekompozicija
14 15
L = zeros([n,n])
25.2 lu dekompozicija
16
U = zeros([n,n])
17 18 19 20 21 22 23 24 25 26 27 28
for k in range(0,n): for i in range(k,n): suma = 0 for m in range(0,k): suma = suma + L[i,m]*U[m,k] L[i,k] = A[i,k] - suma for j in range(k+1,n): suma = 0 for m in range(0,k): suma = suma + L[k,m]*U[m,j] U[k,j] = (A[k,j]-suma)/L[k,k]
29 30 31
for i in range(0,n): U[i,i] = 1
32 33
# rjesavanje sustava
34 35 36
C = empty(shape(B)) X = empty(shape(B))
37 38 39 40 41 42
for i in range(0,n): suma = 0 for j in range(0,i): suma = suma + L[i,j]*C[j] C[i] = (B[i]-suma)/L[i,i]
43 44 45 46 47 48
for i in range(n-1,-1,-1): suma = 0 for j in range(i+1,n): suma = suma + U[i,j]*X[j] X[i] = C[i] - suma
49 50
print X
51 52 53
# Scipy rjesenje print linalg.solve(A,B) [-0.19367432 [-0.19367432
0.07619065 0.07619065
0.03675057 0.03675057
0.39036472] 0.39036472]
125
26
ˇ KO INTEGRIRANJE NUMERIC
¯ Numeriˇckim integriranjem rješava se odredeni integral funkcije f(x) na intervalu [a, b] Zb f(x)dx (26.1) I= a
26.1
trapezna formula
¯ Najjednostavniji naˇcin za aproksimiranje odredenog integrala je izraˇcun površine ispod najjednostavnije aproksimacijske krivulje - pravca. Pravac je definiran poˇcetnom i krajnjom toˇckom intervala inegrala te zatvara površinu sa x-osi oblika trapeza. Izraˇcun površine ispod pravca temelji se na trapeznoj formuli tj. izraˇcunu površine trapeza: Zb f(a) + f(b) f(x) dx ≈ (b − a) . (26.2) 2 a ¯ Svojstvo odredenog integrala je da ga možemo rastaviti na konaˇcni broj ¯ djelova, te je tada odredeni integral nad poˇcetnim intervalom jednak zbroju integrala na djelovima tog integrala: Zc
Zb f(x)dx = a
Zb f(x)dx + f(x)dx.
a
(26.3)
c
¯ Uzevši u obzir rastavljanje odredenog integrala (26.3), trapeznu formulu (26.2) može se koristiti po djelovima intervala [a, b]: Zb f(x) dx ≈ a
N 1X (xk+1 − xk ) (f(xk+1 ) + f(xk )) 2
(26.4)
k=1
gdje je N broj podintervala za koje vrijedi a < x1 < x2 < · · · < xN−1 < xN < b .
Slika 26.1: Trapezi na cjelom intervalu [a, b] i na tri podintervala.
Za unifomnu podjelu intervala [a, b], gdje su svi podintervali jednako široki, trapezna formula (26.4) se može pojednostaviti: Zb f(x) dx ≈ a
N hX (f(xk+1 ) + f(xk )) 2
(26.5)
k=1
gdje je h širina podintervala. Modul numpy.integrate sadrži funkciju trapz za numeriˇcku integraciju pomo´cu trapezne formule.
127
ˇ numeri cko integriranje
128
scipy.integrate.trapz(y, x=None, dx=1.0)
Funkcija prima set (vektor) vrijednosti podintegralne funkcije u toˇckama diskretiziranog intervala [a, b]. Za neuniformnu diskretizaciju intervala [a, b] potrebno je funkciji proslijediti vrijednosti diskretizirane varijable integracije (vektor x-eva) a za uniformnu diskretizaciju dovoljno je specificirati širinu ¯ samo vektor y, pretpospodintervala. Ukoliko je funkciji trapz proslijeden tavlja se da je rijeˇc o uniformnoj diskretizaciji sa širinom podintervala 1. ¯ integral na uniformno diskretiU izvornom kodu 26.1 rješen je odreden ziranom intervalu implementacijom trapezne formule (26.5) te korištenjem funkcije trapz sa vektorom diskretizirane varijable integracije i sa širinom podintervala. ¯ Izvorni kod 26.1: Primjer raˇcunanja odredenog inegrala pomo´cu trapezne formule 1
# -*- coding: utf-8 -*-
2 3 4
import numpy as np import matplotlib.pyplot as plt
5 6 7
def f(x): return -25.0*x +200.0*x**2 +400.0*x**4 -500.0*x**5
8 9 10 11
# Granice integrala # granice (a,b)=(0.0,1.0) a, b = 0.0, 1.0
12 13 14
# Broj podintervala n = 10
15 16 17
# Osiguravanje ispravnih tipova varijabli a, b, n = float(a), float(b), int (n)
18 19 20
# Sirina intervala h = (b-a)/n
21 22 23 24
# Diskretizacija, racunanje x-a i y-a za svaku tocku X = np.linspace(a,b,n+1) Y = f(X)
25 26 27 28 29
# Rucno rjesavanje odre¯ denog integrala pomocu trapezne formule I = 0. for i in range(n): I += 0.5*h*(Y[i]+Y[i+1])
30 31
print ’Rjesenje 1: %f’ % I
32 33 34 35
# Rjesavanje pomo´ cu numpy.trapz funkcije print ’Rjesenje 2: %f’ %np.trapz(Y, X) # pomocu vektora X print ’Rjesenje 3: %f’ %np.trapz(Y, dx=h) # pomocu razmaka dx
36 37 38 39 40 41 42 43 44 45
# Crtanje plt.figure(figsize=(8,5)) Xplt = np.linspace(min(X), max(X), 1000) plt.plot(Xplt,f(Xplt), lw=2) plt.plot(X, Y, ’ro’) for i in range(n+1): plt.plot([X[i], X[i]], [0.0, Y[i]], ’k--’) plt.fill_between(X,f(X),color=’DarkSeaGreen’) plt.show() Rjesenje 1: 50.419500 Rjesenje 2: 50.419500 Rjesenje 3: 50.419500
26.2 simpsonove formule
129
120 100 80 60 40 20 0 20 0.0
0.2
0.4
0.6
0.8
1.0
Slika 26.2: Raˇcunanje površine ispod krivulje pomo´cu trapeza (Izvorni kod 26.1)
26.2
simpsonove formule
Simpsonova pravila (ili Simpsonove formule) koriste kvadratni ili kubni polinom za aproksimaciju funkcije prilikom numeriˇcke integracije. Zbog nemo¯ gu´cnosti odredivanja aproksimacijkog polinoma na jendom intervalu (dvije toˇcke), Simpsonove formule se korsite obuhva´caju´ci dva podinervala (za aproksimaciju kvadratnim polinomom) ili na tri podintervala (za aproksimaciju kubnim polinomom). Za aproksimaciju kvadratnim polinomom na intervalu [xi , xi+2 ] vrijedi: Z xi+2 h f(x)dx = (f(xi ) + 4f(xi+1 ) + f(xi+2 )) (26.6) 3 xi gdje je x uniformno diskretiziran (xi+2 − xi+1 = xi+1 − xi = h). Izraz (26.6) cˇ esto se naziva Simpsonova 1/3 formula a dobiven je integracijom kvadratnog polinoma koji prolazi kroz toˇcke (xi , f(xi )), (xi+1 , f(xi+1 )), (xi+2 , f(xi+2 )). Višestrukom primjenom na sve parove uniformno diskretiziranih podintervala na [a, b] dobiva se Zb n−2 n−1 X X 1 f(x)dx = h f(x0 ) + 4 f(xi ) + 2 f(xi ) + f(xn ) (26.7) 3 a i=1,3
i=2,4
poznato kao kompozitno Simpsonovo pravilo. Kompozitno pravilo se može zapisati i pomo´cu vektorskog produkta: Zb h f(x)dx = (cT f) (26.8) 3 a gdje je c = [1 4 2 4 2 ... 2 4 1]T i f = [f1 f2 f3 ... fn ]T . Pove´canjem stupnja aproksimacijkog polinoma potrebno je više toˇcaka za njegovo definiranje. Za aproksimacijom polinomom 3 stupnja potrebne su cˇ etri toˇcke tj. 3 intervala. Integriranjem polinoma dobiva se izraz za aprok¯ simaciju odredenog integrala: Z xi+3 3 f(x)dx = h(f(xi ) + 3f(xi+1 ) + 3f(xi+2 ) + f(xi+3 )) (26.9) 8 xi
Simposonova 1/3 formula je definirana na parovima podintervala, što uvjetuje da za njeno korištenje podruˇcje ¯ odredenog integrala [a, b] treba podjeliti na paran broj podintervala.
ˇ numeri cko integriranje
130
koji se naziva Simpsonova 3/8 formula. Scipy ima implementiranu Simpsonovu 1/3 formulu u funkciji simps: scipy.integrate.simps(y, x=None, dx=1, even=’avg’)
Funkciju simps se može koristit za poznate vrijednosti podintegralne funkcije y u toˇckama x ili za razmak dx uniformne diskretizacije. Argumentom ¯ ¯ even odreduje se naˇcin na koji se raˇcuna odredeni integral nad parnim brojem toˇcaka (neparni broj podintervala): ? even = ’first’, prvi podinterval se raˇcuna pomo´cu trapezne formule ? even = ’last’, zadnji podinterval se raˇcuna pomo´cu trapezne formule ? even = ’avg’, rezultat integracije je prosjeˇcna vrijednost integrala izraˇcunatih sa opcijom even = ’first’ i even = ’last’. ¯ U izvornom kodu 26.2 dan je primjer raˇcunanja odredenog integrala pomo´cu Simpsonove 1/3 formule. Izvorni kod 26.2: Upotreba Simpsonove 1/3 formule 1 2 3 4
# -*- coding: utf-8 -*""" SIMPSONOVA 1/3 FORMULA """
5 6 7
from numpy import * from scipy.integrate import *
8 9 10 11
# Podintegralna funkcija def f(x): return 20.0*sqrt(x) - 0.2*x**2 - 2.0*sin(x)
12 13 14
# Granice odred ¯enog integrala a, b = 0.0, 10.0
15 16 17
# Broj podintervala n = 40
18 19 20 21
h = (b-a)/n X = linspace(a,b,n+1) Y = f(X)
22 23 24 25
INT = 0.0 for i in range(0, n - 1, 2): INT = INT + (1.0/3.0)*h*(Y[i] + 4*Y[i+1] + Y[i+2])
26 27 28
# "Ruˇ cno" rješenje print INT
29 30 31
# Scipy rjesenje print simps(Y,X) 351.089170175 351.089170175
26.3
quad se zansiva na
QUADPACK-u Fortran biblioteci za numeriˇcku integraciju jednodimenzionalnih funkcija.
naprednije metode
Scipy nudi funkciju quad koja koristi napredniju adaptivnu metodu za numeriˇcku integraciju. Osnovna upotreba funkcije quad zahtjeva podintegralnu funkciju f te gra¯ nice odredenog integrala a i b.
26.4 zadaci
scipy.integrate.quad(f, a, b)
¯ U izvornom kodu 26.3 rješen je isti odredeni integral kao i u 26.2. Izvorni kod 26.3: Numeriˇcko integriranje pomo´cu quad funkcije 1
# -*- coding: utf-8 -*-
2 3 4
from numpy import * from scipy.integrate import *
5 6 7 8
# Podintegralna funkcija def f(x): return 20.0*sqrt(x) - 0.2*x**2 - 2.0*sin(x)
9 10 11
# Rješavanje odre¯ denog integrala na intervalu [0, 10] rj, gr = quad(f, 0, 10)
12 13
print rj 351.292211631
26.4
zadaci
¯ Zadatak 26.1 Lim je izrezan u obliku štita koji je omeden: ? parabolom y = x2 ? parabolom y = 2 − 0.1x2 Kolika je površina izrezanog lima? Zadatak 26.2 Oborinske vode sa krova zgrade odlaze u spremnik (cisterna). Na ulazu u spremnik postavljen je mjeraˇc protoka. Tijekom 15 minutnog pljuska svake minute zabilježen je protok oborinske vode. Vrijeme [min]
Protok [l/s]
Vrijeme [min]
Protok [l/s]
0
0.0
8
10.6
1
0.0
9
11.2
2
2.8
10
10.0
3
4.2
11
9.5
4
6.9
12
4.3
5
10.1
13
1.8
6
10.5
14
0.2
7
11.0
15
0.0
Ako vrijedi ZT Q(t)dt
V= 0
koliki je ukupni volumen vode koja je ušla u spremnik?
131
Dio V R J E Š AVA N J E M O D E L A T E M E L J E N I H N A O D J I PDJ
27
ˇ K E M E T O D E Z A R J E Š AVA N J E O B I C ˇ NIH NUMERIC DIFERENCIJALNIH JEDNADŽBI
ˇ obi cne diferencijalne jednadžbe 1. reda
27.1
y0 =
dy = f(x, y) dx
y(x0 ) = y0 27.1.1
(27.1)
(27.2)
Eulerova metoda
Eulerova metoda služi za numeriˇcko rješavanje diferencijalne jednadžbe prvog reda (27.1) sa zadanim poˇcetnim uvjetom (27.2) a temelji se na aproksimaciji funkcije y(x) pomo´cu prvog cˇ lana Taylorovog reda u okolini toˇcke x: y(x + ∆x) ≈ y(x) + y 0 (x) ∆x
(27.3)
gdje je ∆x konaˇcni odmak od x. 27.1.2
Runge-Kutta metode
27.1.3
Rješavanje pomo´cu scipy-a
Rješavanje obiˇcnih diferencijalnih jednadžbi mogu´ce je korištenjem odeint funkcije iz modula scipy. Iako funkcija odeint ima znatno širu primjenu, u ovom poglavlju c´ e se opisati samo primjena na obiˇcne diferencijalne jednadžbe prvog reda. Osnovna sintaksa odeint funkcije je: scipy.integrate.odeint(f, y0, x)
gdje je f funkcija kojom je definiran diferencijalna jednadžba (27.1), y0 je poˇcetni uvjet a x je vektor koji predstavlja diskretiziran interval varijable x. Poˇcetni uvjet y0 vrijedi u poˇcetnoj vrijednosti vektora x. Primjer rješavanje obiˇcne diferencijalne jednadžbe 1. reda dan je u izvornom kodu 27.1. Izvorni kod 27.1: Primjer rješavanja obiˇcnih diferencijalnih jednadžbi 1. reda. 1
# -*- coding: utf-8 -*-
2 3 4 5
import numpy as np import matplotlib.pyplot as plt import scipy.integrate as intgr
6 7 8 9
# ODJ dy/dx = f(y,x) def f(y, x): return -y + np.sin(x)*np.cos(y)
10 11
# Poˇ cetni uvjet
135
Pri upotrebi odeint metode oˇcekuje se da je funkcija f definirana kao f(y,x), što je neuobiˇcajen redoslijed argumenata te cˇ esto može dovesti do pogreške.
ˇ ˇ numeri cke metode za rješavanje obi cnih diferencijalnih jednadžbi
136
12 13
x0 = 0. y0 = 20.
14 15 16
# Krajnja toˇ cka intervala xf = 10
17 18 19
# Diskretizacija X = np.linspace(x0, xf, 200)
20 21 22
# Rješavanje ODJ Y = intgr.odeint(f, y0, X)
23
25 26 27 28 29
# Vizualizacija plt.plot(X, Y, ’r’, lw = 2) plt.xlabel(’x’) plt.ylabel(’y(x)’) plt.grid() plt.show()
20 15 10 y(x)
24
5 0 5 0
2
4
x
6
8
10
Slika 27.1: Vizualizacija rješenja iz izvornog koda 27.1.
27.2
ˇ sustavi obi cnih diferencijalnih jednadžbi 1. reda
27.3
ˇ obi cne diferencijalne jednadžbe višeg reda
28
ˇ ETNI PROBLEMI POC
28.1
modeliranje otvorenog vodotoka
Promatrajmo strujanje fluida u otvorenom vodotoku[3, 13] (eng. open channel flow). Popreˇcni presjeci kanala mogu biti razliˇciti npr. pravokutni, trapezni i sl., dok se kod prirodnih vodotoka pojavljuju popreˇcni presjeci nepravilnih oblika. Ukoliko je popreˇcni presjek kanala jednak na proizvoljnom presjeku, te je nagib dna jednak u bilo kojoj toˇcki, govorimo o prizmatiˇcnom kanalu.
Slika 28.1: Skica popreˇcnog presjeka otvorenog vodotoka
Na popreˇcnom presjeku kanala definiramo sljede´ce veliˇcine: ? A - površina omoˇcenog presjeka kanala (A = A(x, y) ? P - perimetar odnosno opseg omoˇcenog presjeka (P = P(x, y)) ? R - hidrauliˇcki radijus (R =
A ) P
Klasifikacija strujanja se može napraviti prema razliˇcitim kriterijima. Ako se brzina strujanja ne mijenja u ovisnosti o vremenu, onda je strujanje stacionarno, u suprotnom se radi o nestacionarnom strujanju. Nadalje, ako se brzina strujanja ne mijenja s obzirom na udaljenost u kanalu (od neke referentne toˇcke) onda je strujanje uniformno, a inaˇce se radi o neuniformnom strujanju. idealan fluid
enegetska linija
vodno lice
referentna ravnina Slika 28.2: Energetske linije u strujanju fluida otvorenim vodotokom
137
138
ˇ po cetni problemi
Pretpostavke: ? kut Φ je mali ? strujanje je izrazito jednodimenzionalno ? tlak je iskljuˇcivo hidrostatski Op´cenito se strujanje u kanalu opisuje sustavom parcijalnih diferencijalnih jednadžbi, koje proizlaze iz zakona oˇcuvanja mase i zakona oˇcuvanja koliˇcine gibanja. Ako pretpostavimo da se radi o prizmatiˇcnom kanalu, možemo ih zapisati u obliku: ∂A ∂Q + =0 ∂t ∂x ∂ ∂v +g ∂t ∂x
(28.1)
v2 y+ = g(S0 − Sf ) 2g
(28.2)
Q y je dubina vode, v brzina, a Q protok, pri cˇ emu vrijedi relacija v = . A dH Sf je pad energetske linije , definiran Manningovom formulom (koja je dx prikazana u nastavku). Uvedimo oznaku dH = −Sf dx S S0 smo oznaˇcili nagib dna kanala, tj. S0 = − 28.1.1
(28.3) dz = −tan(Φ). dx
Stacionarno strujanje
Nadalje, ukoliko promatramo stacionarno strujanje fluida, oˇcito je da zbog ∂v ∂A = 0i = 0, iz prve jednadžbe neovisnosti varijabli o vremenu tj. 0 ∂t ∂t sustava (28.1) slijedi: Q = konst. odnosno iz druge jednanžbe dz dy d v2 + + = Sf dx dx dx 2g
(28.4)
(28.5)
Zapravo se ova jednadžbe može dobiti i ako krenemo od poznate nam Bernoullijeve jednažbe z+
p v2 + =H ρg 2g
(28.6)
prema kojoj je ukupna energija konstantna duž strujnice. Vrijednost energetske linije oznaˇcimo s H. Uvažavanjem jednakosti p = ρgy , slijedi z + y + v2 = H, odnosno deriviranjem po x dobijemo diferencijalnu jednadžbu za 2g dubinu vode y = y(x): 2 dz dy d Q dH + + = (28.7) dx dx dx 2gA2 dx
28.1 modeliranje otvorenog vodotoka
Vrsta kanala
Manningov koeficijent
Betonski kanal
0.015
Prirodni kanali (glina)
0.030
Rijeˇcni tokovi
0.030 - 0.070
139
Tablica 28.1: Vrijednosti Manningovog koeficijenta za razliˇcite izvedbe kanala.
Nadalje, kod stacionarnog toka (Q = konst.) u prizmatiˇcnom kanalu vrijedi d dx
Q2 2gA2
Q2 d = 2g dx
1 A2
Q2 d 2g dy
1 A2
=
dy dx
Q2 dA dy =− 3 gA dy dx Q2 B dy =− gA3 dx
(28.8)
Kod druge smo jednakosti uvažili cˇ injenicu da je kanal prizmatiˇcan, što znaˇci da se popreˇcni profili ne mijenjaju s obzirom na udaljenost x u kanalu, dA dH = B. Pad energetske linije = −Sf dok zadnja jednakost slijedi iz dy dx definiran je Manningovom formulom, pomo´cu koje se modeliraju gubici nastali zbog trenja 28.1.2
Maningova formula
The Manning formula, known also as the Gauckler–Manning formula, or Gauckler–Manning–Strickler formula in Europe, is an empirical formula for open channel flow, or free-surface flow driven by gravity. It was first presented by the French engineer Philippe Gauckler in 1867,[1] and later redeveloped by the Irish engineer Robert Manning in 1890.
Sf =
Q2 n2 2 R4/3)A
Robert Manning (1816-1897) was an Irish engineer.
(28.9)
A gdje je n Manningov koeficijent trenja, R = je hidrauliˇcki radijus, a P P perimetar. dy S − Sf = 0 dx BQ2 1− gA3 BQ2 Opazimo da jednadžba (28.10) vrijedi za 6= 1 gA3 (28.10) je diferencijalna jednadžba prvog reda oblika dy = f(x, y(x)) dx
(28.10) Zadatak: Za poˇcetni uvjet y(x0 ) = y0 odrediti dubinu vode y(x) iz diferencijalne jednadžbe (28.10).
140
ˇ po cetni problemi
za koju analitiˇcko rješenje znamo odrediti samo u nekim posebnim sluˇcajevima, za razliku od numeriˇckog rješenja koje znamo odrediti u podruˇcju u kojem je diferencijalna jednadžba dobro definirana. Da bi problem bio u potpunosti modeliran potrebno je zadati i poˇcetne uvjete. Uniformno strujanje i normalna dubina
28.1.3
Kao što smo ve´c spomenuli, kod uniformnog strujanja su brzina i dubina dy = 0, slijedi: vode konstantne veliˇcine pa iz jednadžbe (28.10), zbog dx (28.11)
S0 = Sf
Iz Manningove formule (28.9) potom proizlazi da kod uniformnog toka vrijedi: Q=
1 1/2 AR2/3 S0 n
(28.12)
Na osnovu te jednadžbe može se odrediti dubina vode kod uniformnog toka, tzv. normalna dubina koju c´ emo oznaˇciti yn . 28.1.3.1
Prizmatiˇcni kanal s pravokutnim popreˇcnim presjekom
B - širina kanala
A(y) = B · y ⇒
dA =B dy
P(y) = B + 2y
(28.13)
(28.14)
Slika 28.3: Pravokutni popreˇcni presjek kanala
Kod zadavanja podataka, obiˇcno su nam poznate veliˇcine: Q, n, S0 , B. Normalnu dubinu potom možemo odrediti iz sljede´ceg izraza: 1 1/2 Q = AR2/3 S0 n 2/3 1 Byn 1/2 S0 = Byn n B + 2yn koriste´ci neku od numeriˇckih metoda
(28.15)
28.1 modeliranje otvorenog vodotoka
28.1.3.2
Trapezni kanal
B0 - širina kanala Z - nagib boˇcnih stranica kanala (tangens kuta nagiba boˇcnih stranica kanala) A(y) = (B0 + yZ) · y ⇒
P(y) = B0 + 2y
p
dA = B0 + 2yZ dy
1 + Z2
(28.16)
(28.17)
Slika 28.4: Trapezni popreˇcni presjek kanala
Zadatak 28.1 Odrediti normalnu dubinu vode yn u trapeznom kanalu, s boˇcnim nagibom Z = 2, te širinom dna B0 = 10m. Nagib dna kanala je konstandz = 0.001 (1m po km duljine) a Manningov koeficijent tan i jednak S0 = − dx n = 0.013. Rješenje Dubinu vode oznaˇcimo s y. Iz sliˇcnosti trokuta slijedi 1 : z = y : x, pa je x = zy. Površina omoˇcenog presjeka trapeza √ je A = (B0 + zy)y. Opseg omoˇcenog presjeka trapeza je P = B0 + 2y 1 + z2 . Hidrauliˇcki radijus je R=
A (B0 + zy)y √ . = P B0 + 2y 1 + z2
¯ Normalnu dubinu vode potom odredujemo iz jednadžbe (28.12), koja ¯ nakon uvrštavanja dobivenih izraza i i sredivanja poprimi oblik [(B0 + zyn ) yn ]5/3 nQ −h i2/3 = 0 √ S0 B0 + 2yn 1 + z2 Nakon uvrštavanja poznatih vrijednosti dobijemo F(yn ) = 12.33(10 + 4.47yn )2/3 − ((10 + 2yn )yn )5/3 = 0 Nul toˇcka funkcije F(y) predstavlja rješenje gornje jednadžbe. Može se odrediti pomo´cu neke od numeriˇckih metoda npr. bisekcijom ili Newtonovom metodom. Rješenje je yn = 1.09m
141
142
ˇ po cetni problemi
28.1.4
Kritiˇcna dubina
Nadalje, definirajmo kritiˇcnu dubinu yc . To je dubina kod koje je Froudov broj jednak 1, tj. v Fr = √ =1 gyc
(28.18)
Opazimo da je u sluˇcaju kritiˇcne dubine nazivnik u diferencijalnoj jednadžbi (28.10) jednak 0 te da diferencijalna jednadžba u toj toˇcki ne vrijedi. Kritiˇcnu dubinu možemo izraziti iz (28.18) te dobijemo s s 2 2 Q 3 q 3 (28.19) yc = = 2 g gA Q . Karakteristika kritiˇcne dubine je da je to dubina kod koje je A specifiˇcna energija fluida minimalna. √ Vrijednost c = gy nazivamo brzina širenja poreme´caja. To je zapravo relativna brzina širenja vala u odnosu na medij unutar kojeg taj val putuje. Apsolutne brzine širenja vala su zapravo jednake v − c i v + c. Ako je v < c onda govorimo o podkritiˇcnom toku, za v = c je tok kritiˇcan, dok je za v > c tok nadkritiˇcan. Uoˇcimo da kod podkritiˇcnog toka vrijedi v − c < 0 , a v + c > 0 što znaˇci da se jedan kraj vala putuje uzvodno, a drugi nizvodno. Kod kritiˇcnog je toka v − c = 0 , pa je jedna strana vala stacionarna, dok druga putuje nizvodno brzinom v + c. Za razliku od toga, kod nadkritiˇcnog toka se obje strane vala gibaju nizvodno, jer je v − c > 0 i v + c > 0. Dakle, kod nadkritiˇcnog toka poreme´caj putuje iskljuˇcivo nizvodno, što znaˇci da ¯ nizvodno. tok uzvodno od promatrane lokacije uop´ce ’ne zna’ što se dogada gdje je q =
28.1.5
Hidrauliˇcki skok
Hidrauliˇcki skok (jump) se pojavljuje kod prijelaza strujanja iz nadkritiˇcnog u pdkritiˇcno. U toˇcki u kojoj je Froudov broj jednak 1 dogodi se hidrauliˇcki skok. Kod hidrauliˇckog skoka dolazi do gubitka energije (zbog turbulencije) i do naglog skoka u vodnom licu. Kako gubitak energije na skoku nije unaprijed poznat, jednadžbu oˇcuvanja energije ne možemo primijeniti direktno. ¯ da u toˇcki skoka diferencijalna jednadžba (28.10) ne vrijedi Uoˇcimo takoder jer je nazivnik desne strane jednak nula. U nastavku c´ emo promatrati rješenja jednadžbe (28.10) uz postavljeni pocˇ etni uvjet y(x0 ) = y0 , tj. poznatu dubinu vode u nekoj toˇcki. Kako analitiˇcka rješenja jednadžbe nisu poznata, osim u nekim posebnim sluˇcajevima, za rješavanje c´ emo koristiti numeriˇcke metode. Prisjetimo se, da su standardne numeriˇcke metode za rješavanje diferencijalne jednadžbe prvog reda: Eulerova metoda, poboljšana Eulerova metoda i razliˇcite Runge-Kutta metode. Koju c´ emo od spomenutih metoda odabrati ovisi o toˇcnosti koju želimo posti´ci. Pritom treba svakako voditi raˇcuna i o stabilnosti pojedinih metoda. Rješenja postavljenog poˇcetnog problema mogu biti razliˇcitog oblika, u zavisnosti o poˇcetnom uvjetu, nagibu kanala i trenju u kanalu. Promatrati c´ emo razliˇcite sluˇcajeve u tzv. kanalima s blagim nagibom (mild slope). Takav je nagib okarakteriziran uvjetom yc < yn
(28.20)
28.1 modeliranje otvorenog vodotoka
U tom se sluˇcaju linija kritiˇcne dubine nalazi ispod linije normalne dubine. Tim je dvjema linijama podruˇcje strujanja podijeljeno u tri zone (vidi sliku 3.). Oblik rješenja, dakle vodno lice, ovisi o poˇcetnom uvjetu. Tražena se ¯ rješenja odreduju iz diferencijalne jednadžbe (28.10), koja se za promatrani pravokutni prizmatiˇcni kanal može zapisati u obliku: yn 10/3 y 3 yc 1− y
dy = S0 dx
1+
(28.21)
U ovisnosti o zoni u kojoj se nalazi poˇcetni uvjet, dakle poˇcetna dubina ovisi sami oblik rješenja. Znaˇcajno je naglasiti da dubina vode, odnosno rješenje ne može prije´ci diferencijalne jednadžbe iz jedne u drugu zonu – dakle, ako je poˇcetni uvjet u zoni 1, vodno lice ostati c´ e u zoni 1. Pripadaju´ca se krivulja naziva M1 krivulja. Razlikujemo M1, M2 i M3 krivulje (Slika 28.5). Vrijedi: ? za yc < yn < y0 rješenje je M1-krivulja ? za yc < y0 < yn rješenje je M2-krivulja ? za y0 < yc < yn rješenje je M3-krivulja U toˇckama u kojima se dogodi prijelaz iz jedne u drugu zonu, rješenje zapravo ne zadovoljava diferencijalnu jednadžbu (to su sluˇcajevi u kojima je nazivnik u diferencijalnoj jednadžbi jednak 0, dakle toˇcke u kojima se dostigne kritiˇcan tok). Primjeri u kojima se pojavljuju promatrane krivulje: ? M1-krivulja – podkritiˇcno strujanje (Fr<1) - utok u jezero; ? M2-krivulja – prijelaz iz podkritiˇcnog u nadkritiˇcno strujanje kod kanala cˇ iji se nagib pove´ca; strujanje prije prijelaza u nadkritiˇcno ima oblik M2-krivulje; ? M3-krivulja – prijelaz iz nadkritiˇcnog u podkritiˇcno strujanje npr. strujanje ispod zapornice; dio krivulje prije prijelaza u podkritiˇcni tok ima oblik M3-krivulje. Na sliˇcan se naˇcin rješenja mogu dobiti i za ve´ce nagibe kanala (steep slope) – kada je yc > yn . U tom sluˇcaju rješenja imaju oblik tzv. S-krivulja (Slika 28.6). 28.1.6
Numeriˇcko rješavanje
Izvorni kod 28.1: Strujanje u pravokutnom kanalu 1 2 3 4 5 6
# -*- coding: utf-8 -*""" pravokutni kanal transkritiˇ cno strujanje rješavanje ODJ """
7 8 9 10
from numpy import * from scipy.optimize import * from scipy.integrate import *
143
ˇ po cetni problemi
144
Slika 28.5: M-krivulje vodnog lica
11
Slika 28.6: S-krivulje vodnog lica
from matplotlib.pyplot import *
12 13
g = 9.81
14 15 16 17 18
# ulazni podaci o kanalu B = 15.0 S0 = 0.001 n = 0.012
19 20
Q = 10.0
21 22 23
yc = ((Q/B)**2/g)**(1.0/3.0) print(’yc = ’+str(yc))
24 25 26 27 28 29
# osnovne veliˇ cine A = lambda y: B*y P = lambda y: B+2*y R = lambda y: A(y)/P(y) Sf = lambda y: (n*Q/(R(y)**(2.0/3.0)*A(y)))**2
30 31 32
yn = fsolve((lambda y: Sf(y)-S0),yc) print(’yn = ’+str(yn[0]))
33 34 35 36 37
# raˇ cunanje razine vode x0 = 0.0 y0 = 0.42 x1 = 30.0
38 39
X = linspace(x0,x1,100)
40 41 42
dydx = lambda y,x: (S0-Sf(y))/(1.0-B*Q**2/(A(y)**3*g)) Y = odeint(dydx,y0,X)
43 44 45
#dydx_2 = lambda y,x: S0*(1.0-(yn/y)**(10.0/3.0))/(1.0-(yc/y)**3) #Y_2 = odeint(dydx_2,y0,X)
46 47 48 49 50 51
#crtanje figure(1, [8, 3]) Ydno = -(X-x0)*S0 plot(X,Y[:,0]+Ydno) plot(X,Ydno)
28.1 modeliranje otvorenog vodotoka
52 53 54 55
#plot(X,Y_2[:,0]-(X-x0)*S0); legend((’razina vode’,’dno’),loc=’best’); subplots_adjust(bottom=0.08,top=0.95,left=0.05,right=0.98) show()
0.5 0.4 0.3
razina vode dno
0.2 0.1 0.0 0.10
5
10
15
20
25
Slika 28.7: Numeriˇcko rješenje strujanja u otvorenom kanalu pravokutnog presjeka
30
145
29
RUBNI PROBLEMI
Uvod, op´cenito o rubnim problemima 29.1
savijanje grede
Za rješavanje ovog primjer korišten je rješavaˇc bvp1lg. Prije instalacije modula bvp1lg potrebno je instalirati pakete koje on koristi: sudo zypper in python-numpy-devel fparser-devel \ libatlas3 libatlas3-devel lapack-devel
nakon cˇ ega se može instalirati i sam modul: sudo pip install scikits.bvp1lg bvp1lg zahtjeva Fortran compiler!
q(x)
u(x) E, I Slika 29.1: Savijanje grede
¯ progiba elastiˇcne linije i postavljenog optere´cenja opisana je Veza izmedu Euler-Bernoullijevom jednadžbom (Diferencijalna jednadžba elastiˇcne linije):
EI ·
d2 u = −M(x) d x2
(29.1)
ili prošireno d2 d x2
d2 u EI · d x2
! = q(x)
(29.2)
gdje je E Youngov modul, I osni moment tromosti popreˇcnog presjeka, u je progib grede, M je moment savijanja, q je kontinuirano popreˇcno optere´cenje, a x je os nedeformirane grede. Ako je E · I konstantno duž grede, jednadžba (29.2) se pojednostavljuje: E·I·
d4 u = q(x) d x4
(29.3)
Pomo´cu supstitucija: w1 (x) = u(x) du dx d2 u w3 (x) = d x2 d3 u w4 (x) = d x3 w2 (x) =
(29.4)
147
148
rubni problemi
obiˇcnu diferencijalnu jednadžbu 4. reda (29.3) može se zapisati kao sustav 4 obiˇcne diferencijalne jednadžbe 1. reda. d w1 dx d w2 dx d w3 dx d w4 dx
= w2 (x) = w3 (x) (29.5) = w4 (x) =
1 q(x) EI
Za sustav (29.5) potrebno je postaviti 4 rubna uvjeta kako bi se moglo dobiti rješenje savijanja grede. Rubni uvjeti koje je mogu´ce postaviti na krajeve grede (Slika 29.2): ? Rubni uvjet progiba u|xbc = ubc . U toˇcki xbc postavlja se vrijednost progiba ubc . = vbc . U toˇcki xbc postavlja se vrijednost ? Rubni uvjet nagiba dd u x xbc
nagiba vbc . ? Rubni uvjet momenta
d2 u d x2 x
nost momenta Mbc . ? Rubni uvjet popreˇcne sile
= Mbc . U toˇcki xbc postavlja se vrijedbc
d3 u d x3 x
vrijednost popreˇcne sile Qbc .
= Qbc . U toˇcki xbc postavlja se bc
Slika 29.2: Rubni uvjeti za razliˇcite oslonce grede
U izvornom kodu 29.1 prikazan je primjer rješavanja savijanja grede koriste´ci bvp1lg paket koji je specijaliziran rješavaˇc za rubne probleme. U danom primjeru korišteni su sljede´ci rubni uvjeti: lijevi rub je uklješten (nema progiba ni rotacije/nagiba) dok na desnom rubu zglob (nema pomaka ni momenta). Greda je optere´cenja konstantnim kontinuiranim optere´cenjem duž cijele dužine. Izvorni kod 29.1: Rješavanje elastiˇcne linije savijanja 1 2
from pylab import * import scikits.bvp1lg as bvp
3 4 5 6 7 8 9
# Definiranje problema EI = 1.0 # Youngov modul i moment otpora L = 1.0 # Duzina grede # Opterecenja qq=-1.0
29.2 stacionarno provoðenje topline u štapu
10 11
# Kontinuirana sila, poprecna sila i moment savijanja def q(x): return qq
12 13
degrees = [1, 1, 1, 1]
14 15 16 17 18 19 20 21
# Sustav diferencijalnih jednadzbi def function(x , y): u, du, d2u, d3u = y return ([ du, d2u, d3u, q(x)/EI])
22 23 24 25 26 27
# Rubni uvjeti boundary_points = [0.0, 0.0, L, L] def boundary_conditions(y): u, du, d2u, d3u = y return [u[0], du[1], u[2], d2u[3]]
28 29
tol = [1e-15, 1e-15, 1e-15, 1e-15]
30 31 32 33 34 35
# Rjesavanje rubnog problema solution = bvp.colnew.solve( boundary_points, degrees, function, boundary_conditions, is_linear=False, tolerances=tol, vectorized=False, maximum_mesh_size=10000)
36
38 39 40 41 42 43 44 45 46
# Vizualizacija rjesenja figure(1, figsize=(8, 3)) x = solution.mesh plot(x, solution(x)[:,0], ’b-’, linewidth=2) xlabel(’x’) ylabel(’y’) grid() subplots_adjust(bottom=0.15,top=0.95,left=0.13,right=0.98) savefig(’greda.pdf’) show()
Rješenje dobiveno izvornim kodom 29.1 je prikazano na slici 29.3.
y
37
0.000 0.001 0.002 0.003 0.004 0.005 0.0060.0
0.2
0.4
x
0.6
Slika 29.3: Progib elastiˇcne linije grede
29.2
stacionarno provoðenje topline u štapu
0.8
1.0
149
30
K L A S I F I K A C I J A PA R C I J A L N I H D I F E R E N C I J A L N I H JEDNADŽBI
Za danu funkciju u = u(x, y) se parcijalne derivacije definiraju s ∂u u(x + ∆x, y) − u(x, y) (x, y) = lim ∂x ∆x ∆x→0
(30.1)
u(x, y + ∆y) − u(x, y) ∂u (x, y) = lim ∂y ∆y ∆y→0
(30.2)
i
Parcijalna diferencijalna jednadžba je jednadžba koja sadrži parcijalne derivacije nepoznate funkcije dviju ili više nezavisnih varijabli. Op´ceniti oblik linearne PDJ drugog reda s konstantnim koeficijentima je A
∂2 u ∂2 u ∂2 u +C 2 +D +B 2 ∂x∂y ∂x ∂y
(30.3)
¯ je predznakom izraza B− 4AC. Parcijalna Tip jednadžbe (30.3) odreden diferencijalna jednadžba (30.3) je ? eliptiˇcka za B2 − 4AC < 0 ? paraboliˇcka za B2 − 4AC = 0 ? hiperboliˇcka za B2 − 4AC > 0 Zbog veoma raširene pojave jednadžbi ovakvog tipa u matematiˇckom modeliranju fizikalnih pojava, a time i u inženjerstvu, upoznat c´ emo neke od numeriˇckih metoda koje se koriste pri rješavanju jednadžbi oblika (30.3). Numeriˇcke se metode bitno razlikuju u zavisnosti o tipu jednadžbe.
151
ˇ K E PA R C I J A L N E D I F E R E N C I J A L N E J E D N A D Ž B E ELIPTIC
Tpiˇcni predstavnici PDJ eliptiˇckog tipa su: Laplaceova jednadžba ∆u =
∂2 u ∂2 u + 2 =0 ∂x2 ∂y
(31.1)
Poissonova jednadžba ∆u =
∂2 u ∂2 u + 2 = f(x, y) ∂x2 ∂y
Kvaziharmoniˇcka PDJ ∂u ∂ ∂u ∂ kx · + ky · = f(x, y) ∂x ∂x ∂y ∂y
(31.2)
(31.3)
ˇ progib plo ce
31.1
q x
n
y z
Slika 31.1: Ploˇca
Promatramo ploˇcu jednostavno poduprtu na rubovima, s površinskim optere´cenjem q (Slika 31.1). Progib tako slobodno oslonjene ploˇce u smjeru z može se odrediti iz PDJ eliptiˇckog tipa ∂4 z ∂4 z ∂4 z q + 2 + = D ∂x4 ∂x2 ∂y2 ∂y4
(31.4)
koja vrijedi u unutarnjim toˇckama podruˇcja Ω, te rubnih uvjeta z|∂Ω = 0
(31.5)
∂2 z =0 ∂n2 ∂Ω
(31.6)
i
Parametar D definiran je s D=
Et3 2(1 − σ2 )
(31.7)
gdje je E Youngov modul, t debljina ploˇce a σ Poissonov broj.
153
31
ˇ elipti cke parcijalne diferencijalne jednadžbe
154
Ako se definira nova varijabla u = ∆z =
∂2 z ∂2 z + ∂x2 ∂y2
(31.8)
jednadžba (31.4) može se zapisati u obliku q ∂2 u ∂2 u + 2 = D ∂x2 ∂y
(31.9)
pa se problem (31.4) svodi na rješavanje dviju Poissonovih jednadžbi (31.8) i (31.9). ¯ Iz rubnih uvjeta (31.5) i (31.6) odreduju se rubni uvjeti koji pripadaju dobivnenim jednadžbama 2. reda: u|∂Ω = 0
(31.10)
z|∂Ω = 0
(31.11)
i
Naravno, prvo se rješava jednadžba (31.9) a onda se dobiveno rješenje koristi za rješavanje jednadžbe (31.8). Izvorni kod 31.1: Rješavanje problema progiba ploˇce pomo´cu metode konaˇcnih razlika 1 2 3 4 5 6
# -*- coding: utf-8 -*""" progib ploˇ ce rješavanje PDJ konaˇ cne razlike """
7 8 9 10 11
from from from from
numpy import * scipy.linalg import * matplotlib.pyplot import * mpl_toolkits.mplot3d import Axes3D
12 13 14 15 16 17 18
# ulazni podaci q = 10000.0 # [N/m^2] d = 0.01 # [m] L = 2.0 # [m] E = 2.0*10**11 # modul elastiˇ cnosti pbr = 0.3 # Poissonov broj
19 20
D = E*d**3/(12.0*(1.0-pbr**2))
# fleksna krutost
21 22
nm = 50
# broj toˇ caka po dimenziji
23 24 25
h = L/(nm-1) n = (nm-2)
# udaljenost od tocke do tocke
26 27 28 29 30 31 32 33 34
# izgradnja matrice sustava i vektora d.s. Adblok = zeros([n,n]) + diag(-4*ones(n)) + \ diag(ones(n-1),k=1) + diag(ones(n-1),k=-1) A=empty([0,0]) for i in range(n): A = block_diag(A, Adblok) A = A + diag(ones([n**2-n]),k=n) + diag(ones([n**2-n]),k=-n) b = h**2*q/D*ones(n**2)
35 36 37 38
# rješavanje u = solve(A,b) z = solve(A,u*h**2)
ˇ 31.1 progib plo ce
39 40 41 42 43
# pakiranje rezultata z = reshape(z,[n,n]) # ili: z = z.reshape([n,n]) Z = zeros([nm,nm]) Z[1:(nm-1),1:(nm-1)] = -z
44 45 46 47
# prikaz pcolor(Z) colorbar()
48 49 50 51 52 53
# 3d l = linspace(0,L,nm) X, Y = meshgrid(l,l) figure().gca(projection=’3d’).plot_surface(X,Y,Z, \ rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0)
54 55
show()
155
32
METODA LINIJA
Metoda linija je op´ca tehnika za rješavanje parcijalnih diferencijalnih jednadžbi (PDE) koje obiˇcno koriste konaˇcne razlike za odnose prostornih derivacija i obiˇcne diferencijalne jednadžbe za vremensku derivaciju. Za ilustraciju i detaljnije pojašnjenje ove metode koristit c´ e se primjena metode na problem nestacionarnog progrijavanja štapa. Parcijalna diferencijalna jednadžvba koja opisuje promjenu temperature duž osi štapa i u vremenu je: ∂2 T ∂T =D 2 ∂t ∂x
(32.1)
Lijevi rub je izoliran i u toj toˇcki vrijedi Neumannov rubni uvjet: ∂T =0 ∂x 0
(32.2)
Na desnom rubu zadana je konstantna temperatura i vrijedi Dirichleov rubni uvjet: T |L = 0
(32.3)
. Osnovna ideja metode linija je da se parcijalnu diferencijalnu jednadžbu (32.1) svede na sustav obiˇcnih diferencijalnih jednadžbi.
"ghost" point i=1
i-1
i
i=n
i+1 Δx
x=0
x=L Slika 32.1: Diskretizacija
Diskretizacijom prostorne koordinate (Slika 32.1) te aproksimacijom konaˇcnim razlikama, vrijedi: ∂2 T T (x + ∆x) − 2T (x) + T (x − ∆x) (x) = ∂x2 ∆x2
(32.4)
Jednadžba (32.4) vrijedi za svaku unutarnju diskretizacijsku toˇcku i ovisna je o susjednim toˇckama: T − 2Ti + Ti−1 ∂Ti = D i+1 ∂t ∆x2
(32.5)
Na lijevom rubu, iz (32.2) vrijedi: T1 = T0
(32.6)
157
158
metoda linija
pa se može korigirati jednadžbu za prvu toˇcku: ∂T1 T − 2T1 + T0 T −T =D 2 =D 2 21 2 ∂t ∆x ∆x
(32.7)
Desni rub se ne mjenja u vremenu, pa u krajnjoj toˇcki vrijedi: ∂Tn =0 ∂t
(32.8)
Jednadžbe (32.4), (32.7) i (32.8) tvore sustav obiˇcnih diferencijalnih jednadžbi koje se može rješiti prikladinim rješavaˇcem. ¯ Izvorni kod 32.1: Primjer rješavanje provodenja topline kroz štap pomo´cu metode linija 1 2
#!/usr/bin/python # -*- coding: utf-8 -*-
3 4 5 6 7
from from from from
scipy import * scipy.integrate import * matplotlib.pyplot import * matplotlib.animation import *
8 9 10 11 12 13
nx = 50 x = linspace(0, 1, nx) A = diag(ones(nx)*(-2.0), k=0) + \ diag(ones(nx-1)*1.0, k=1) + \ diag(ones(nx-1)*1.0, k=-1)
14 15 16 17 18 19
""" Resetiraj jednadžbu za prvu i zadnju toˇ cku """ A[0,:] = 0 A[-1,:] = 0
20 21 22 23 24 25 26 27
""" Prva toˇ cka: izolacija dT0/dx = 0 ==> T_-1 = T_0 dT0/dt = k*(T_1 - 2*T_0 +T_-1)/dx^2 = k*(T_1 - T_0)/dx^2 """ A[0,0] = -1 A[0,1] = 1
28 29 30 31 32
""" Zadnja toˇ cka: fiksna temperatura dT/dt = 0 """ A[-1,-1] = 0
33 34 35 36 37 38
dx=0.1; k=0.01; nt = 11 t = linspace(0.0, 100., nt)
39 40 41
T0 = sin(x*pi) print shape(dot(A,T0))
42 43 44 45 46 47 48
""" Postavi sustav ODJ """ def dT_dt(T, t): dT = (k/dx**2.0)*dot(A,T) return dT
49 50 51 52
""" Rješi sustav ODJ """
metoda linija
53
rez = odeint(dT_dt, T0, t)
54 55 56 57 58 59 60
""" Crtanje i animacija rješenja """ fig1 = figure() lineGeom, = plot([], [], ’r-’, lw=2) titl = title(’’)
61 62 63 64 65 66
def update_line(i): lineGeom.set_data(x, rez[i,:]) titl.set_text(’t=%f’ % t[i]) #fig1.savefig(’img_%03d.png’ % i) return
67 68 69
anim = FuncAnimation(fig1, update_line, nt, interval=1000, repeat_delay=0) show()
159
Dio VI OPTIMIZACIJSKE METODE
33
DEFINICIJA OPTIMIZACIJSKOG PROBLEMA Optimizacijski problem se može postaviti kao pronalaženje vektora x∗ = (x∗1 , x∗2 , ..., x∗n ) za koji vrijedi f(x∗ ) 6 f(x), ∀x ∈ Ω
(33.1)
gdje je f funkcija cilja, x = (x1 , x2 , ..., xn ) vekor optimizacijskih varijabli a x∗ vektor rješenja optimizacijskog problema. Ω je prostor pretraživanja. Izraz (33.1) pretpostavlja da je rijeˇc o minimizacijskom problemu. U slucˇ aju maksimizacije, problem se definira kao f(x∗ ) > f(x), ∀x ∈ Ω 33.1
(33.2)
optimizacijske varijable
Optimizacijske varijable (eng. optimization variables, design variables, design parameters, decision variables) su varijable cˇ ije vrijednosti treba odrediti a da zadovoljavaju ciljeve i ograniˇcenja optimizacijskog problema. Zbog jednostavnosti zapisa, cˇ esto se koristi vektor optimizacijskih varijabli (eng. design vector): x = (x1 , x2 , ..., xn )
(33.3)
gdje je n broj optimizacijskih varijabli. ¯ Domena pretraživanja ili prostor pretraživanja odreduje mogu´ce vrijed¯ je s obzirom na tip varijabli (kontinosti optimizacijskih varijabli; a odreden nuirane ili diskretne) te s obzirom na propisane granice varijabli. Prostor pretraživanja ¯ Za optimizaciju sa kontinuiranim neomedenim varijablama vrijedi x ∈ Rn
(33.4)
¯ ¯ Uvodenjem omedenosti, prostor pretraživanja sužava se na Ω x ∈ Ω ⊂ Rn
(33.5)
¯ Omedenost (bound) kontinuiranih optimizacijskih varijabli je postavljanje granica varijabli tj. definiranje dopuštenog intervala varijabli. Za svaku kontinuiranu varijablu xi može se postaviti donja granica (lower bound) xmin te i gornja granica (upper bound) xmax i onda vrijedi: i i h xi ∈ xmin , xmax , ∀i = 1, . . . , n (33.6) i i ¯ Uvodenjem diskretnih varijabli, najˇceš´ce indeksiranih pomo´cu cijelih ili prirodnih brojeva, prostor pretraživanja se definira na skupu cijelih brojeva x ∈ Zn
(33.7)
ili na skupu prirodnih brojeva x ∈ Nn
(33.8)
163
164
definicija optimizacijskog problema
U relanim primjenama, diskretne varijable su gotovo uvijek definirane na konaˇcnom skupu brojeva xi ∈ {i = 1, 2, . . . , ki } , ∀i = 1, . . . , n
(33.9)
gdje je ki broj mogu´cih vrijednsoti diskretne varijable xi . Optimizacijske probleme, s obzirom na tip optimizacijskih varijabli, možemo klasificirati na: ? kontinuirane ? diskretne ? mješovite ¯ a s obizirom na omedenost na: ¯ ? omedene (bounded) i ¯ ? neomedene (unbounded). 33.2
ciljevi optimizacije i funkcija cilja f(x)
33.3
ˇ ograni cenja
(33.10)
34
LINEARNO PROGRAMIRANJE
Linearno programiranje je matematiˇcka metoda pronalaska optimuma linearne funkcije više varijabli poštuju´ci ograniˇcenja zadana linearnim nejednakostima i jednakostima. Linearno programiranje je razvijeno kao disciplina u 1940-ima, u poˇcetku motivirano zbog potrebe za rješavanje složenih problema planiranja u ratnim operacijama. Njegov razvoj ubrzano raste u poslijeratnom razdoblju, kad mnoge industrije pronalaze korisne primjene linearnog programiranja. Iako je problem linearnog programiranja formulirao još Furier, jedna od prvih praktiˇcnih upotreba imao je ruski matematiˇcar Kantoroviˇc ([5]) u pokušaju poboljšanja ekonomskih planiranja 1939. godine u SSSR-u. 34.1
definicija lp problema
Problem linearnog programiranje može se razluˇciti na funkciju cilja te na ograniˇcenja. Funkcija cilja je linerna jednadžba n varijabli (x1 , x2 , ..., xn ) definirana koeficijetima c1 , c2 , ..., cn . f(x1 , x2 , ..., xn ) =
n X
ci · xi
(34.1)
i=1
Jednadžba (34.1) može se zapisati u vektorskom obliku: f(x) = c · x
(34.2)
gdje je x = (x1 , x2 , ..., xn ) vekor varijabli a c = (c1 , c2 , ..., cn ) vektor koeficijenata linearne jednadžbe. Vektor x ∈ Ω ⊂ Rn predstavlja optimizacijske varijable za koje se traži optimalno rješenje x∗ za koje vrijedi f(x∗ ) 6 f(x), ∀x ∈ Ω
(34.3)
Ograniˇcenja problema se mogu zadati kao sustav linearnih nejednadžbi: a11 · x1 + a12 · x2 + . . . + a1n · xn
> b1
a21 · x1 + a22 · x2 + . . . + a2n · xn .. .
> b2 .. .
am1 · x1 + am2 · x2 + . . . + amn · xn
> bm
gdje je m broj ograniˇcenja. Sustav linearnih nejednadžbi (34.6) se može jednostavnije zapisati vektorski A·x > b
(34.4)
165
Nejednadžbe se mogu zadavati sa razliˇcitim operatorima ¯ usporedivanja (> i 6), a mjenjanje operatora se može posti´ci množenjem cijele nejednandžbe sa -1.
166
linearno programiranje
Osim ograniˇcenja zadanih nejednakostima, ograniˇcenja se mogu zadati i lineanrim jednadžbama d11 · x1 + d12 · x2 + . . . + d1n · xn
= e1
d21 · x1 + d22 · x2 + . . . + d2n · xn .. .
= e2 .. .
dp1 · x1 + dp2 · x2 + . . . + dpn · xn
= ep
gdje je p broj ograniˇcenja. U vektorskom zapisu sustav linearnih jednadžbi (34.6) glasi
Ograniˇcenja zadan jednakostima mogu se zadavati i kao dvije identiˇcne nejednakosti sa suprotnim znakom nejednakosti (npr. x1 + x2 > 0 i x1 + x2 6 0 je isto što i x1 + x2 = 0)
D·x = E 34.2
(34.5)
simpleks metoda
George Dantzig je 1947. godine, zajedno sa suradnicima iz ameriˇckog ratnog zrakoplovstva razvio simpleks metodu [15, 16]. 34.3
´ modula pulp rješavanje lp problema pomo cu
http://code.google.com/p/pulp-or/
Kako instaliraty PuLP: user@machine:~>sudo pip install pulp user@machine:~>sudo zypper in glpk
Izvorni kod 34.1: Primjer rješavanja LP problema pomo´cu modula PuLP 1
# -*- coding: utf-8 -*-
2 3
from pulp import *
4 5 6 7
# Varijable x = LpVariable("x", 0, 3) y = LpVariable("y", 0, 1)
8 9 10
# LP problem prob = LpProblem("myProblem", LpMinimize)
11 12 13
# Cilj prob += -4*x + y
14 15 16 17
# Ogranicenja prob += x + y <= 2 prob += x == y
18 19 20
# Rjesavanje status = prob.solve()
21 22 23 24 25
# Ispis print LpStatus[status] print value(x) print value(y)
34.4
ˇ prakti cni primjeri lp problema
ˇ 34.4 prakti cni primjeri lp problema
34.4.1
Teretni zrakoplov
Zadatak 34.1 Teretni zrakoplov ima tri odjeljka za teret: prednji, centralni i stražnji odjeljak. Odjeljci zrakoplova imaju ograniˇcenja s obzirom na masu i volumen tereta koji mogu prihvatiti. Odjeljak Dopuštena masa tereta [t]
Skladišni prostor [m3 ]
Prednji 10
6800
Centralni16
8700
Stražnji 8
5300
¯ Masa tereta rasporedenog po odjeljcima mora biti proporcionalna dopuštenoj masi tereta za te odjeljke kako bi se zadržao balans zrakoplova. Za transport zrakoplovom su dostupne cˇ etri vrste tereta, koji svaki ima specificiranu masu, obujam i profit. Teret
Masa [t]
Obujam [m3 ]
Zarada [A C]
C1
18
480
310
C2
15
650
380
C3
23
580
350
C4
12
390
285
Bilo koja koliˇcina tereta je prihvatljiva. Cilj je prona´ci koliko svakog pojedinog tereta treba ukrcati te kako ih distribuirati u odjeljek zrakoplova kako bi se maksimizirao ukupan profit leta. Rješenje Potrebno je odrediti mase svakog od cˇ etri vrste tereta koje treba ukrcati u svaki od tri odjeljaka. Neka je xij masa tereta i koji se ukrcava u odjeljak j. x = (x11 , x12 , x13 , x21 , x22 , x23 , x31 , x32 , x33 , x41 , x42 , x43 ) U zrakoplov se ne može ukrcati više tereta nego što ga ima na raspolaganju. To vrijedi za svaki od cˇ etri vrste tereta. x11 + x12 + x13 6 18 x21 + x22 + x23 6 15 x31 + x32 + x33 6 23 x41 + x42 + x43 6 12 Dopuštena masa tereta u svakom odjeljku ne smije biti prekoraˇcena. x11 + x21 + x31 + x41 6 10 x12 + x22 + x32 + x42 6 16 x13 + x23 + x33 + x43 6
8
167
168
linearno programiranje
¯ Prostorni (volumni) kapacitet odjeljaka odreduje koliˇcine tereta koji se mogu ukrcati. 480x11 + 650x21 + 580x31 + 390x41 6 6800 480x12 + 650x22 + 580x32 + 390x42 6 8700 480x13 + 650x23 + 580x33 + 390x43 6 5300 Da bi se zadovoljio balans masa u odjeljcima i stabilnost zrakoplova, mase u odjeljcima moraju biti proporcionalne. x11 + x21 + x31 + x41 = 10 x12 + x22 + x32 + x42 = 16 x13 + x23 + x33 + x43 8 Potrebno je maksimizirati ukupno profit ostvaren prijevozom tereta. f(x) = (x11 + x12 + x13 ) · 310 + (x21 + x22 + x23 ) · 380 +
(34.6)
(x31 + x32 + x33 ) · 350 + (x41 + x42 + x43 ) · 285 Izvorni kod 34.2: Rješavanje problema transportnog zrakoplova 1
# -*- coding: utf-8 -*-
2 3
from pulp import *
4 5 6 7 8
# Varijable x11 = LpVariable("x11", 0) x12 = LpVariable("x12", 0) x13 = LpVariable("x13", 0)
9 10 11 12
x21 = LpVariable("x21", 0) x22 = LpVariable("x22", 0) x23 = LpVariable("x23", 0)
13 14 15 16
x31 = LpVariable("x31", 0) x32 = LpVariable("x32", 0) x33 = LpVariable("x33", 0)
17 18 19 20
x41 = LpVariable("x41", 0) x42 = LpVariable("x42", 0) x43 = LpVariable("x43", 0)
21 22 23
# LP problem prob = LpProblem("Plane Cargo", LpMaximize)
24 25 26
# Cilj prob += (x11 + x12 + x13)*310 + (x21 + x22 + x23)*380 + (x31 + x32 + x33)*350 + ( x41 + x42 + x43)*285
27 28 29 30 31 32 33
# Ogranicenja prob += x11 + prob += x21 + prob += x31 + prob += x41 +
x12 x22 x32 x42
+ + + +
x13 x23 x33 x43
<= <= <= <=
18 15 23 12
ˇ 34.4 prakti cni primjeri lp problema
34 35 36
prob += x11 + x21 + x31 + x41 <= 10 prob += x12 + x22 + x32 + x42 <= 16 prob += x13 + x23 + x33 + x43 <= 8
37 38 39 40
prob += 480*x11 + 650*x21 + 580*x31 + 390*x41 <= 6800 prob += 480*x12 + 650*x22 + 580*x32 + 390*x42 <= 8700 prob += 480*x13 + 650*x23 + 580*x33 + 390*x43 <= 5300
41 42 43
prob += (x11 + x21 + x31 + x41)/10 == (x12 + x22 + x32 + x42)/16 prob += (x12 + x22 + x32 + x42)/16 == (x13 + x23 + x33 + x43)/8
44 45 46
# Rjesavanje status = prob.solve()
47 48 49 50
# Ispis rjesenja print "\n--------------------------------------\n" print ’Status:’, LpStatus[status]
51 52 53
for v in prob.variables(): print v.name, "=", v.varValue
54 55
print "Total profit = ", value(prob.objective) GLPSOL: GLPK LP/MIP Solver, v4.52 Parameter(s) specified in the command line: --cpxlp /tmp/7285-pulp.lp -o /tmp/7285-pulp.sol Reading problem data from ’/tmp/7285-pulp.lp’... 12 rows, 12 columns, 36 non-zeros 18 lines were read GLPK Simplex Optimizer, v4.52 12 rows, 12 columns, 36 non-zeros Preprocessing... 10 rows, 12 columns, 36 non-zeros Scaling... A: min|aij| = 1.000e+00 max|aij| = 6.500e+02 ratio = GM: min|aij| = 8.801e-01 max|aij| = 1.136e+00 ratio = EQ: min|aij| = 7.746e-01 max|aij| = 1.000e+00 ratio = Constructing initial basis... Size of triangular part is 10 0: obj = 0.000000000e+00 infeas = 0.000e+00 (0) * 6: obj = 1.215157895e+04 infeas = 0.000e+00 (0) * OPTIMAL LP SOLUTION FOUND Time used: 0.0 secs Memory used: 0.0 Mb (43410 bytes) Writing basic solution to ‘/tmp/7285-pulp.sol’... -------------------------------------Status: Optimal x11 = 0.0 x12 = 0.0 x13 = 0.0 x21 = 10.0 x22 = 0.0 x23 = 5.0 x31 = 0.0 x32 = 12.9474 x33 = 3.0 x41 = 0.0 x42 = 3.05263 x43 = 0.0 Total profit = 12151.58955
6.500e+02 1.291e+00 1.291e+00
169
35
NELDER-MEAD METODA
Nelder-Mead metoda, poznata kao Downhill simplex metoda ili Amoeba metoda. Nelder-Mead metoda je tehnika za minimizaciju funkcije cilja u višedimenzionalnom prostoru. Osnovnu ideju metode su osmislili John Nelder i Roger Mead 1965. godine [8]. Pregled metode Metoda koristi koncept simpleksa, što je specijalni politop od n toˇcaka u n dimenzija. Politop je geometrijski oblik sa ravnim stranicama koji ekzistira u bilo kojem broju dimenzija. Poligon je politop u dvije dimenzije. Primjeri simpleksa su dužina na pravcu (1D), trokut u ravnini (2D), tetraedron u prosotru (3D) itd. Metoda se zasniva na traže¯ nju uzorka koji usporeduje vrijednosti funkcije u svim toˇckama simpleksa. Najgora toˇcka se odbacuje i uvodi se nova toˇcka koja sa ostalima cˇ ini novi simpleks. Nalaženje nove toˇce simpleksa u svakoj iteraciji može uzrokovati širenje ili smanjivanje raspona simpleksa. Smanjivanje simpleksa dovodi do konvergencije (svih toˇcaka simpleksa) ka optimumu. 35.1
algoritam
Algoritam Nelder-Mead metode je unificiran za bilo koji broj optimizacijskih varijabli. 1. Odredi n toˇcaka poˇcetnog simpleksa x1 , x2 , ..., xn+1 2. Izraˇcunaj vrijednost funkcije cilja za sve toˇcke simpleksa 3. Sortiraj toˇcke simpleksa prema vrijednosti funkcije cilja u toˇckama: f(x1 ) 6 f(x2 ) 6 ... 6 f(xn+1 ) 4. Refleksija ? Izraˇcunaj težište svih toˇcaka osim najgore n P xi x0 = i=1 n ? Izraˇcunaj toˇcku refleksije i funkciju cilja u toˇcki refleksije xr = x0 + α(x0 − xn+1 )
Pod najgorom toˇckom se podrazumijeva toˇcka u kojoj je vrijednost funkcije najve´ca (kod problema minimizacije).
? Ako je funkcija cilja u toˇcki refleksije nije bolja od najbolje toˇcke simpleksa a bolja je od druge najgore toˇcke simpleksa f(x1 ) 6 f(xr ) 6 f(xn ) onda: – nova toˇcka simpleksa je toˇcka refleksije xr i mjenja najgoru toˇcku xn+1 – idi na korak 1 5. Ekspanzija Ako je toˇcka refleksije najbolja f(xr ) < f(x1 ) onda:
171
Pod najboljom toˇckom se podrazumijeva toˇcka u kojoj je vrijednost funkcije najmanja (kod problema minimizacije).
172
nelder-mead metoda
? izraˇcunaj toˇcku ekspanzije i funkciju cilja u toˇcki ekspanzije xe = x0 + γ(x0 − xn+1 ) ? Ako je toˇcka ekspanzije bolja od toˇcke refleksije f(xe ) < f(xr ) onda – nova toˇcka simpleksa postaje toˇcka ekspanzije xe – idi na korak 1 inaˇce – nova toˇcka simpleksa postaje toˇcka refleksije xr – idi na korak 1 6. Kontrakcija f(xr ) > f(xn ) Izraˇcunaj toˇcku kontrakcije i funkciju cilja u toˇcki kontrakcije xc = xn+1 + ρ(x0 − xn+1 ) Ako je toˇcka kontrakcije bolja od najgore toˇcke f(xc ) < f(x( n + 1)) onda ? nova toˇcka simpleksa postaje toˇcka kontrakcije xc ? idi na korak 1 7. Redukcija Za sve toˇcke osim najbolje izraˇcunaj nove: xi = x1 + σ(xi − x1 ) za i = 2, ..., n + 1 Idi na korak 1 α, γ, ρ i σ su koeficijenti refleksije, ekspanzije, kontrakcije i redukcije. Standardno korištene vrijendosti su α = 1, γ = 2, ρ = 1/2 i σ = 1/2. 35.2
nelder-mead metoda za optimizaciju funkcije dviju varijabli
Slika 35.1: Toˇcke refleksije, ekspanzije, kontrakcije i redukcije kod Nelder-Mead metode optimizacije za funkciju dvije varijable. Toˇcke refleksije, ekspanzije ili kontrakcije mjenjaju najgoru toˇcku simpleksa, dok toˇcke redukcije mjenjaju dvije nagore toˇcke simpleksa.
35.2 nelder-mead metoda za optimizaciju funkcije dviju varijabli
Simpleks koji se koristi kod Nelder-Mead metode optimizacije funkcije dviju varijabli jest trokut (Slika 35.1). Za svaki korak iteracije izraˇcunava se novi simpleks ondnosno trokut na naˇcin da se mjenja najgora toˇcka starog trokuta, odnosno dvije najgore toˇcke u sluˇcaju redukcije. Izvornom kodu 35.1 vizualizira svaki korak metode na primjeru rješavanje 2D funkcije cilja. Izvorni kod 35.1: Primjer 2D optimizacije Nelder-Mead metodom 1 2 3 4
# -*- coding: utf-8 -*""" Nelder-Mead metoda """
5 6 7 8
import numpy as np import matplotlib.pyplot as plt from matplotlib import animation
9 10 11 12
def f(x): return np.sin(x[0]/20.0)/(x[0]**2.0/1000.0 + 1)*np.cos(x[1]/50.0) #return x[0]**2.0 + x[1]**2.0
13 14 15 16
X,Y = np.meshgrid(np.arange(-60,60,2), np.arange(-60,60,2)) Z = np.sin(X/20.0)/(X**2.0/1000.0 + 1)*np.cos(Y/50.0)
17 18 19 20 21 22 23
fig = plt.figure() contour_plot = plt.contourf(X, Y, Z, 150, # [-1, -0.1, 0, 0.1], #alpha=0.5, #cmap=plt.cm.bone, #origin=origin )
24 25 26 27 28 29 30 31 32
# Postavke metode alpha = 1.0 beta = 0.5 gamma = 2.0 delta = 0.5 maxiter = 15 eps = 0.0001
33 34 35 36 37
# Poˇ cetne toˇ cke A0 = [-50, 50] B0 = [-50, -50] C0 = [50, 50]
38 39 40 41
A0.append(f(A0)) B0.append(f(B0)) C0.append(f(C0))
42 43 44 45 46 47
# Formiranje trokuta pomo´ cu matrice T = [A0, B0, C0] xline = [A0[0], B0[0], C0[0], A0[0]] yline = [A0[1], B0[1], C0[1], A0[1]] simpleks, = plt.plot(xline, yline, ’k-o’)
48 49 50 51 52
def init(): xline = [A0[0], B0[0], C0[0], A0[0]] yline = [A0[1], B0[1], C0[1], A0[1]] simpleks, = plt.plot(xline, yline, ’-o’)
53 54
return simpleks
55 56 57
# Glavna petlja metode def iteration(it):
173
174
nelder-mead metoda
58
Ts = sorted(T, key=lambda point: point[2])
59 60 61 62
B = np.array(Ts[0]) S = np.array(Ts[1]) W = np.array(Ts[2])
63 64
M = (B + S) / 2.0
65 66 67 68
# Refleksija R = M + alpha * (M - W) R[2] = f(R)
69 70 71
if R[2] >= B[2] and R[2] < S[2]: W = np.copy(R)
72 73 74 75 76
elif R[2] < B[2]: # Ekspanzija E = M + gamma * (R - M) E[2] = f(E)
77 78 79 80 81
if E[2] < R[2]: W = np.copy(E) else: W = np.copy(R)
82 83
elif R[2] >= S[2]:
84 85 86 87 88
if R[2]< W[2]: # Kontrakcija vanjska C = M + beta*(W-M) C[2] = f(C)
89 90 91 92 93 94 95
if C[2] <= R[2]: W = np.copy(C) else: # Shrink W = B + delta * (W - B) W[2] = f(W)
96
S = B + delta * (S - B) S[2] = f(S)
97 98 99 100 101 102 103
else: # Kontrakcija unutarnja C = M - beta * (W - M) C[2] = f(C)
104 105 106 107 108 109 110
if C[2] < W[2]: W = np.copy(C) else: # Shrink W = B + delta * (W - B) W[2] = f(W)
111
S = B + delta * (S - B) S[2] = f(S)
112 113 114 115 116 117
T[0] = B T[1] = S T[2] = W
118 119 120 121
xline = [B[0], S[0], W[0], B[0]] yline = [B[1], S[1], W[1], B[1]] simpleks.set_data(xline, yline)
122 123 124
#plt.savefig(’iteration%02d.pdf’ % it) return simpleks
35.2 nelder-mead metoda za optimizaciju funkcije dviju varijabli
125 126 127
Writer = animation.writers[’ffmpeg’] writer = Writer(fps=2, metadata=dict(artist=’Stefan’), bitrate=3600)
128 129 130
anim = animation.FuncAnimation(fig, iteration, #init_func=init, frames=maxiter, interval=2, repeat=False)
131 132 133
anim.save(’nelder-mead.avi’, writer=writer) plt.show()
134 135 136 137 138
Ts = sorted(T, key=lambda point: point[2]) print Ts[0] print Ts[1] print Ts[2] [ -2.08786964e+01 [ -2.08750000e+01 [ -2.08756335e+01
4.72068787e-03 -2.99504027e-03 8.40537250e-03
-6.01976050e-01] -6.01976025e-01] -6.01976024e-01]
40 20 0 20 40 60
60
40
20
0
20
40
Slika 35.2: Izgled simpleksa u 5 iteraciji (za izvorni kod 35.1).
175
36
SIMULIRANO KALJENJE
Simulirano kaljenje je stohastiˇcka optimizacijska metoda namjenjena rješavanju problema globalne optimizacije. 1983. godine su Kirkpatrick, Gelatt i ˇ Vecchi [7], te Cern y` 1985. [2] godine su osmislili i postavili osnovnu ideju metode. Metoda emulira proces kaljenja cˇ elika gdje se zagrijano tijelo polako hladi ¯ i mijenja svoju strukturu te u konaˇcnom ohladenom stanju doseže konfiguraciju minimalne energije. 36.1
algoritam
? Postavi poˇcetnu temperaturu T0 za (i = 1) ? Generiraj nasumiˇcno poˇcetno stanje x0 ? Evaluiraj stanje f0 = f(x0 ) ? Ponavljaj dok se na zadovolji kriterij zaustavljanja : 1. Generiraj novo stanje xi+1 = xi + ´x 2. Evaluiraj stanje fi+1 = f(xi+1 ) 3. Izraˇcunaj razliku energije ∆f = fi+1 − fi 4. Odredi vjerojatnost prihva´canja novog stanja (xi+1 ) 1 ako je ∆f < 0 p(T ) = ∆f − Ti ako je ∆f > 0 e 5. (Ne)prihva´canje novog stanja ¯ 6. Proces hladenja Ti+1 = α(Ti ) 7. Sljede´ca iteracija i = i + 1 ∆x je nasumiˇcni vektor pomaka kojim dobivamo novu toˇcku u blizini stare. Ve´cina algoritama simuliranog kaljenja automatski reducira ∆x tijekom samog procesa optimizacije kako bi se u poˇcetku pokrivalo što ve´ce podruˇcje (global search) a kasnije osigurala što brža konvergencija (local search). ¯ Funkcija α(T ) je funkcija hladenja i najˇceš´ce se kostiti α(T ) = r · T gdje je 0 < r < 1. 36.2
´ modula inspyred primjer simuliranog kaljenja pomo cu
Izvorni kod 36.1: Primjer simuliranog kaljenja pomo´cu modula inspyred 1 2 3 4
# -*- coding: utf-8 -*""" Simulirano kaljenje """
5 6
from random import Random
177
178
simulirano kaljenje
7 8 9 10
from time import time import inspyred from numpy import * from matplotlib.pyplot import *
11 12
F=[]
13 14 15 16 17 18
def f(X): fit = 10.0 * len(X) for x in X: fit += (x**2.0 - 10.0*cos(2.0*pi*x)) return float(fit)
19 20 21 22
def generate(random, args): size = args.get(’num_inputs’, 10) return [random.uniform(-5.12, 5.12) for i in range(size)]
23 24 25 26 27 28
def evaluate(candidates, args): fitness = [] for cs in candidates: fitness.append(f(cs)) return fitness
29 30 31 32 33
def observe(population, num_generations, num_evaluations, args): best = min(population) #print ’%10d > %.4e’ % (num_generations, best.fitness) F.append(best.fitness)
34 35 36
prng = Random() prng.seed(time())
37 38 39 40 41 42 43 44 45 46 47
ea = inspyred.ec.SA(prng) ea.terminator = inspyred.ec.terminators.evaluation_termination ea.observer = observe final_pop = ea.evolve(evaluator = evaluate, generator = generate, maximize = False, bounder = inspyred.ec.Bounder(-5.12, 5.12), max_evaluations = 3000, temperature = 1000.0, cooling_rate = 0.5)
48 49 50
best = min(final_pop) print(’Najbolje rjesenje: \n{0}’.format(str(best)))
51 52 53 54 55 56
plot(F) xlabel(’iteracije’) xlabel(’f’) grid() show() Najbolje rjesenje: [-0.007675196458353489, -0.004919287254415098, -0.013702756782375067, 0.007230016365494668, 0.0016173493554606094, -0.02186560269034206, -0.04488667414508021, 0.008940404646539009, -0.006383384005716428, 0.0035534794190288585] : 0.58284052168
´ modula inspyred 36.2 primjer simuliranog kaljenja pomo cu
200
150
100
50
0 0
500
1000
1500 f
2000
2500
Slika 36.1: Konvergencija optimizacije pomo´cu simuliranog kaljenja
3000
179
37
ˇ ESTICA OPTIMIZACIJA ROJEM C
37.1
razvoj metode
Optimizacija rojem cˇ estica (Particle Swarm Optimization, PSO) je stohastiˇcka optimizacijska metoda temeljena na idejama opaženim na kretanju jata i rojeva. Reynolds[11] je 1987. godine predložio model ponašanja jata, prema kojem se svaki cˇ lan jata ponaša prema slijede´cim pravilima: ? Držanje razmaka - svaki cˇ lan jata se pokušava udaljiti od susjednih ako su mu oni preblizu, ¯ ? Prilagodavanje smjera - svaki cˇ lan jata giba se u usrednjenom smjeru kretanja svojih susjeda, ? Kohezija - svaki cˇ lan jata ostaje blizu svojih susjeda tj. ostaje u jatu. Kennedy i Eberhart[6] su dodali ’gnijezdo’ u pojednostavljenu simulaciju temeljenu na Reynoldsovom modelu. Simulacija je obuhva´cala sljede´ce utjecaje gnijezda na jedinke jata: ? gnijezdo privlaˇci svaku jedinku, ? Svaka jedinka pamti gdje je bila najbliža gnijezdu. ? Svaka jedinka razmijenjuje informacije sa susjedima o lokaciji najbližoj gnijezdu. ¯ Nakon dovoljno vremena provodenja simulacije, sve su jedinke došle do ’legla’. Postavlja se pitanje što se dešava sa sustavom ako se gnjezdo giba prema nepoznatoj funkciji? Da li c´ e jedinke sti´ci do gnjezda? vt+1 = vti + φ1 Ut1 (pbti − xti ) + φ2 Ut2 (gbt − xti ) i
(37.1)
xt+1 = xti + vt+1 i i
(37.2)
Shi i Eberhart[12] uvode inerciju cˇ estice koja je kontrolirana preko faktora inercije wt . vt+1 = wt vti + φ1 Ut1 (pbti − xti ) + φ2 Ut2 (gbt − xti ) i
(37.3)
Slika 37.1: Ponašanje jedinki u Reynoldsovom modelu. Odvajanje, usmjeravanje i kohezija.
181
ˇ optimizacija rojem cestica
182
Slika 37.2: Utjecaj gnjezda na jedinke jata.
U osnovnom obliku, faktor inercije je konstantan u vremenu wt = w. U slucˇ aju w > 1, brzine cˇ estica rastu u vremenu (ˇcestice ubrzavaju) a formacija roja divergira. Usporavanje cˇ estica i smanjivanje brzine do nule postiže se sa w < 1. Ve´ci faktor inercije omogu´cava lakše globalno pretraživanje, sa povec´ anjem rasapa cˇ estica, dok manji w omogu´cuje bolje lokalno pretraživanje i bržu konvergenciju. Odabir faktora inercije treba temeljiti na karkateristikama funkcije cilja i svodi se na balansiranje širine pretraživanja i brzine konvergencije. Prema [14] w>
c1 + c2 −1 2
(37.4)
garantira konvergenciju putanja cˇ estica, a prema [1] preporuˇceni faktor inercije je w = 0.73. 37.2
´ modula inspyred korištenje pso metode pomo cu
Kako instaliraty inspyred: http://inspyred.github.com/index.html user@machine:~>sudo pip install inspyred
Izvorni kod 37.1: Particle Swarm Optimization na primjeru Rastrigin funkcije 1 2 3 4 5
from random import Random from time import time from math import cos, pi import inspyred
6 7 8 9 10
# Random generiranje def generate_rastrigin(random, args): size = args.get(’num_inputs’, 10) return [random.uniform(-5.12, 5.12) for i in range(size)]
11 12 13 14 15 16
17 18
# Evaluacija (funkcija cilja) def evaluate_rastrigin(candidates, args): fitness = [] for cs in candidates: fit = 10 * len(cs) + sum([((x - 1)**2 - 10 * cos(2 * pi * (x - 1))) for x in cs]) fitness.append(fit) return fitness
19 20 21 22 23 24
rand = Random() rand.seed(int(time())) pso = inspyred.swarm.PSO(rand) pso.terminator = inspyred.ec.terminators.evaluation_termination
´ modula inspyred 37.2 korištenje pso metode pomo cu
25 26 27 28 29 30 31 32 33
final_pop = pso.evolve(generator=generate_rastrigin, evaluator=evaluate_rastrigin, pop_size=100, maximize=False, bounder=inspyred.ec.Bounder(-5.12, 5.12), max_evaluations=20000, mutation_rate=0.25, num_inputs=5)
34 35 36 37
# Sort and print the best individual, who will be at index 0. final_pop.sort(reverse=True) print(final_pop[0])
183
38
ˇ KI ALGORITMI GENETIC
Genetiˇcki algoritam (GA) je adaptivni heuristiˇcni algoritam traženja baziran na evolucijskim idejama prirodne selekcije i genetike. Kao takav predstavlja inteligentno iskorištavanje nasumiˇcnog traženja za rješavanje optimizacijskih problema. 38.1
evolucijski algoritmi
50-ih i 60-ih godina 20. stoljeda nekoliko znanstvenika na podruˇcju raˇcunarstva nezavisno su prouˇcavali evolucijske sustave sa idejom da se evolucija koristi kao optimizacijski alat za inženjerske probleme. Ideja u svim tim sustavima bila je da populacija kandidacijskih rješenja evoluira ka optimalnom rješenju zadanog problema, koriste´ci operatore inspirirane prirodnom genetskom varijacijom i prirodnom selekcijom. Profesor John Holland, na sveuˇcilištu u Michiganu, došao na ideju genetskog algoritma, koju je razvijao 60-ih i 70-ih godina zajedno sa svojim studentima i kolegama. Hollandov cilj nije bilo dizajniranje algoritma za rješavanje specifiˇcnih problema, ve´c prouˇcavanje fenomena adaptacije kakav se pojavljuje u prirodi, te razviti naˇcine kako mehanizme prirodne adaptacije primjeniti u raˇcunalnim sustavima. 1975 Holland je prvi koristio naziv „genetski algoritam“ u knjizi „Adaptation in Natural and Artificial Systems“. John Henry Holland smatra se ocem genetskih algoritama. 1989 David Goldberg sa sveuˇcilišta u Illinoisu primijenio je Hollandovu ideju na razliˇcita inženjerska podruˇcja. Goldberg: „Three billion years of evolution can’t be wrong. It’s the most powerful algorithm there is.“. Današnji moderni genetski algoritam svrstava se u evolucijske algoritme, koji sadržavaju široki spektar mehanizama koji oponašaju procese prirodne evolucije, gdje je glavni koncept opstanak najjaˇceg. Današnji najkorišteniji evolucijski algoritmi su: ? Genetski algoritmi koji modeliraju genetsku evoluciju ? Genetsko programiranje koje je bazirano na genetskim algoritmima, ali jedinke su programi (struktura hijerarhijskog stabla). ? Evolucijsko programiranje je izvedeno iz simuliranja adaptivnog ponašanja u evoluciji (phenotypic evolution). ? Evolucijske strategije su usmjerene prema modeliranju strategije parametara koji kontroliraju varijaciju u evoluciji, cˇ esto nazivano „Evolucija evolucije“. ? Diferencijalna evolucija, koja je sliˇcna genetskim algoritmima ali razlikuje se po korištenim mehanizmima reprodukcije. ? Kulturalna evolucija, modelira evoluciju kulture populacije i kako kultura utjeˇce na genetsku i fenotipnu evoluciju jedinki. ? Koevolucija, namjerno „glupe“ jedinke evoluiraju kroz kooperaciju, ili kroz nadmetanje jedne sa drugom, a pritom stjeˇcu potrebne karakteristike kako bi preživjele.
185
ˇ geneti cki algoritmi
186
38.2
korištenje deap modula
DEAP je Python modul za evolucijsko raˇcunanje. [9, 4] Namjenjen je razvoju novih algoritama te brzo i lako testiranje novih ideja. Osim mogu´cnosti izrade vlastitih algoritma, DEAP nudi gotove algoritme: ? Genetiˇcki algoritam (GA) ? Genetiˇcko programiranje (GP) ? Evolucijske strategije (ES) ? Optimizacija rojem cˇ estica (PSO) (vidi poglavlje 37) Osim podrške za evolucijske metode, DEAP pruža mogu´cnost detaljnog i fleksibilnog statistiˇckog pra´cenja i testiranja optimizacijskih procesa. Kako instaliraty DEAP: http://code.google.com/p/deap/ user@machine:~>sudo pip install deap
Izvorni kod 38.1: Optimizacija Rastrigin funkcije pomo´cu DEAP modula 1 2 3
# -*- coding: utf-8 -*""" Created on Wed Dec 18 15:15:56 2013
4 5 6
@author: stefan """
7 8
import random
9 10 11 12 13 14 15
from deap import base from deap import creator from deap import tools from deap import algorithms import matplotlib.pyplot as plt import numpy as np
16 17 18 19
DIMS = 10 LB = -100.0*np.ones(DIMS) UB = 100*np.ones(DIMS)
20 21 22 23 24 25 26
# Funkcija cilja # Rosenbrock funkcija def evaluate(x): x = np.array(x) s = sum(100.0*(x[1:]-x[:-1]**2.0)**2.0 + (1-x[:-1])**2.0) return s,
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
# Definicija funkcije korekcije # Korigira gornju i donju granicu varijabli def checkBounds(lb, ub): def decorator(func): def wrapper(*args, **kargs): offspring = func(*args, **kargs) for child in offspring: for i in xrange(len(child)): if child[i] > ub[i]: child[i] = ub[i] elif child[i] < lb[i]: child[i] = lb[i] return offspring return wrapper return decorator
38.2 korištenje deap modula
44 45 46 47
# Kreiranje minimizacijskog problema creator.create("FitnessMax", base.Fitness, weights=(-1.0,)) # Definicija jedinki creator.create("Individual", list, fitness=creator.FitnessMax)
48 49
toolbox = base.Toolbox()
50 51 52 53 54
55 56
# Registracija optimizacijske varijable toolbox.register("attr_float", random.uniform, -100.0, 100.0) # Registriracija jedinke toolbox.register("individual", tools.initRepeat, creator.Individual, toolbox. attr_float, DIMS) # Registracija populacije toolbox.register("population", tools.initRepeat, list, toolbox.individual)
57 58 59 60 61 62 63 64 65 66 67 68 69 70
# Registracija funkcije cilja toolbox.register("evaluate", evaluate) # Registracija operatora križanja toolbox.register("mate", tools.cxTwoPoints) # Registracija korekcije poslije križanja toolbox.decorate("mate", checkBounds(LB, UB)) # Resgistracija mutacije toolbox.register("mutate", tools.mutGaussian, mu=0, sigma=1, indpb=0.1) # Registracija korekcije poslije mutacije toolbox.decorate("mutate", checkBounds(LB, UB)) # Registracija metode selekcije toolbox.register("select", tools.selTournament, tournsize=3)
71 72 73 74 75
# Kreiranje populacije jedinki pop = toolbox.population(n=250) # Definiraj pam´ cenje jedne najbolje jedinke hof = tools.HallOfFame(1)
76 77 78 79 80 81 82
# Statistiˇ cko pra´ cenje algoritma stats = tools.Statistics(lambda ind: ind.fitness.values) stats.register("avg", tools.mean) stats.register("std", tools.std) stats.register("min", min) stats.register("max", max)
83 84 85 86
# Pokretanje algoritma algorithms.eaSimple(pop, toolbox, cxpb=0.75, mutpb=0.8, ngen=200, stats=stats, halloffame=hof, verbose=True)
87 88 89
# Ispis najbolje jedinke print hof
90 91 92 93 94 95 96 97 98 99 100
# Crtanje grafa konvergencije fig = plt.figure() ax = fig.add_subplot(1,1,1) ax.set_yscale(’log’) plt.plot(stats.data[’min’][0], ’-g’, label = ’min’) plt.plot(stats.data[’avg’][0], ’-b’, label = ’avg’) plt.plot(stats.data[’max’][0], ’-r’, label = ’max’) plt.grid() plt.legend() plt.show() gen 0 1 2 3 4 5 6
evals 250 241 240 238 237 235 239
std max avg [8.138e+09] [4.366e+10] [5.711e+09] [2.543e+10] [3.454e+09] [1.832e+10] [1.913e+09] [1.194e+10] [9.443e+08] [4.473e+09] [5.374e+08] [3.477e+09] [2.739e+08] [1.794e+09]
min [1.676e+10] [9.85e+08] [1.055e+10] [6.183e+08] [6.01e+09] [6.183e+08] [3.19e+09] [3.502e+08] [1.735e+09] [2.265e+08] [1.015e+09] [1.64e+08] [6.411e+08] [1.211e+08]
187
188
ˇ geneti cki algoritmi
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
237 238 234 244 234 236 241 238 243 230 235 239 235 235 233 234 236 241 235 238 236 234 234 237 242 234 234 237 242 237 235 241 244 234 246 235 238 239 239 234 232 241 237 238 242 229 239 239 225 233 230 242 238 233 240 240 231 240 236 241 240 233 238 236 230 242 236
[1.672e+08] [9.866e+08] [4.233e+08] [1.249e+08] [9.335e+07] [6.107e+08] [3.006e+08] [9.78e+07] [6.907e+07] [4.452e+08] [2.184e+08] [8.422e+07] [4.674e+07] [3.436e+08] [1.652e+08] [4.803e+07] [3.899e+07] [2.573e+08] [1.259e+08] [4.305e+07] [3.2e+07] [2.203e+08] [9.343e+07] [3.412e+07] [1.952e+07] [1.377e+08] [6.896e+07] [2.664e+07] [1.461e+07] [1.085e+08] [5.295e+07] [1.134e+07] [1.133e+07] [8.049e+07] [4.122e+07] [1.115e+07] [8.692e+06] [5.624e+07] [3.121e+07] [8.309e+06] [7.148e+06] [5.685e+07] [2.289e+07] [5.22e+06] [5.664e+06] [3.561e+07] [1.715e+07] [5.233e+06] [4.503e+06] [2.791e+07] [1.25e+07] [4.354e+06] [2.689e+06] [2.033e+07] [8.937e+06] [4.219e+06] [1.738e+06] [1.318e+07] [6.871e+06] [3.476e+06] [9.617e+05] [9.931e+06] [5.427e+06] [3.49e+06] [6.41e+05] [7.87e+06] [4.707e+06] [3.324e+06] [5.806e+05] [5.958e+06] [4.204e+06] [2.497e+06] [6.607e+05] [6.073e+06] [3.807e+06] [1.906e+06] [5.783e+05] [5.22e+06] [3.303e+06] [1.797e+06] [5.321e+05] [5.234e+06] [2.786e+06] [1.639e+06] [4.515e+05] [3.899e+06] [2.35e+06] [1.186e+06] [3.543e+05] [3.36e+06] [1.991e+06] [8.656e+05] [2.97e+05] [2.796e+06] [1.738e+06] [8.762e+05] [2.645e+05] [2.49e+06] [1.509e+06] [7.125e+05] [2.519e+05] [2.296e+06] [1.293e+06] [6.843e+05] [2.091e+05] [1.684e+06] [1.108e+06] [6.358e+05] [1.942e+05] [1.68e+06] [9.355e+05] [4.7e+05] [1.551e+05] [1.439e+06] [8.028e+05] [4.176e+05] [1.357e+05] [1.268e+06] [6.795e+05] [3.876e+05] [1.102e+05] [8.952e+05] [5.743e+05] [3.197e+05] [9.698e+04] [8.459e+05] [4.92e+05] [2.626e+05] [7.705e+04] [7.722e+05] [4.153e+05] [2.147e+05] [7.128e+04] [6.02e+05] [3.643e+05] [1.835e+05] [6.495e+04] [5.171e+05] [3.15e+05] [1.489e+05] [5.698e+04] [4.734e+05] [2.66e+05] [1.359e+05] [5.898e+04] [6.019e+05] [2.248e+05] [1.102e+05] [3.92e+04] [3.411e+05] [1.868e+05] [1.063e+05] [3.232e+04] [3.309e+05] [1.6e+05] [8.606e+04] [2.677e+04] [2.427e+05] [1.392e+05] [6.186e+04] [2.274e+04] [2.095e+05] [1.215e+05] [6.204e+04] [2.193e+04] [1.912e+05] [1.061e+05] [5.615e+04] [1.737e+04] [1.565e+05] [9.149e+04] [4.468e+04] [1.688e+04] [1.627e+05] [7.915e+04] [4.597e+04] [1.307e+04] [1.44e+05] [6.853e+04] [4.181e+04] [1.245e+04] [1.222e+05] [6.11e+04] [3.93e+04] [1.075e+04] [1.124e+05] [5.482e+04] [3.562e+04] [8887] [1.352e+05] [4.914e+04] [3.23e+04] [7171] [7.923e+04] [4.539e+04] [3.234e+04] [7837] [1.011e+05] [4.241e+04] [3.092e+04] [6770] [9.115e+04] [3.89e+04] [2.606e+04] [4400] [5.14e+04] [3.55e+04] [2.345e+04] [5340] [6.22e+04] [3.342e+04] [2.177e+04] [7401] [8.657e+04] [3.168e+04] [2.028e+04] [5802] [6.033e+04] [2.803e+04] [1.973e+04] [6684] [8.118e+04] [2.584e+04] [1.533e+04] [5612] [7.537e+04] [2.368e+04] [1.533e+04] [5351] [5.62e+04] [2.216e+04] [1.386e+04] [3744] [4.749e+04] [2.02e+04] [1.244e+04] [4260] [5.345e+04] [1.885e+04] [1.27e+04] [3062] [3.483e+04] [1.725e+04] [1.239e+04] [2475] [2.889e+04] [1.555e+04] [1.041e+04] [3295] [4.651e+04] [1.477e+04] [1.041e+04] [2922] [3.337e+04] [1.401e+04] [8998] [2645] [3.777e+04] [1.323e+04] [8433] [3215] [4.977e+04] [1.244e+04] [7378] [2562] [3.043e+04] [1.152e+04] [6977]
38.2 korištenje deap modula
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
237 238 239 238 239 235 234 241 240 238 242 237 244 241 238 243 230 244 239 241 243 234 239 235 239 237 233 239 238 230 239 238 243 239 240 238 238 241 236 237 236 241 236 232 235 236 239 240 238 235 238 240 241 241 232 239 245 236 238 241 243 235 242 237 231 240 238
[2283] [2489] [2032] [1637] [2292] [2040] [3623] [1986] [2757] [1986] [2064] [1369] [3604] [2782] [1717] [1238] [2571] [4126] [1784] [3300] [2112] [1190] [1216] [1446] [1419] [2335] [1694] [2725] [904.7] [1020] [1850] [1275] [1501] [1411] [588.3] [1348] [1954] [876.8] [1800] [1454] [1755] [1623] [1154] [1236] [1733] [964.4] [886] [855.8] [958.2] [1769] [1070] [629.2] [1230] [1356] [1345] [1718] [884.6] [2529] [991.9] [1205] [1302] [931.8] [2047] [1823] [1165] [1321] [1145]
[2.74e+04] [1.072e+04] [6996] [2.563e+04] [1.008e+04] [4771] [2.137e+04] [9035] [4002] [1.356e+04] [8000] [3826] [1.971e+04] [7353] [3792] [2.641e+04] [6200] [3739] [3.688e+04] [5974] [2730] [1.705e+04] [4968] [2022] [2.914e+04] [4753] [1755] [1.912e+04] [4180] [1001] [1.878e+04] [3743] [1017] [1.267e+04] [3069] [804.6] [4.884e+04] [3013] [908.5] [3.149e+04] [2625] [856] [1.656e+04] [2124] [686.6] [1.472e+04] [1745] [715] [2.544e+04] [1894] [436.2] [5.141e+04] [1922] [315.4] [1.27e+04] [1471] [275.5] [4.286e+04] [1414] [132.2] [2.661e+04] [1246] [90.83] [9698] [956.8] [81.2] [9830] [816.8] [76.04] [1.128e+04] [736.9] [81.2] [1.155e+04] [638.8] [31.3] [3.506e+04] [636] [29.87] [1.367e+04] [808.3] [29.93] [3.562e+04] [677] [24.3] [6506] [439.6] [33.82] [7747] [422.4] [24.77] [1.988e+04] [643.3] [12.46] [1.218e+04] [459.7] [10.9] [1.328e+04] [563.6] [10.9] [1.284e+04] [524.7] [10.9] [4070] [288.2] [10.2] [1.315e+04] [445.2] [10.2] [1.643e+04] [634.8] [10.95] [7940] [345.1] [8.495] [2.136e+04] [537.7] [8.495] [1.53e+04] [538.4] [8.495] [1.268e+04] [584.9] [8.495] [1.681e+04] [521.7] [7.986] [1.077e+04] [427.5] [9.09] [1.046e+04] [507.4] [7.984] [1.446e+04] [531.4] [7.984] [1.038e+04] [334.3] [7.829] [6653] [316.1] [7.829] [4878] [351.3] [7.829] [9124] [341.1] [7.829] [1.818e+04] [526.3] [7.829] [1.007e+04] [330.1] [8.119] [5382] [263.6] [8.119] [1.394e+04] [365.8] [8.379] [1.548e+04] [423.5] [6.521] [1.174e+04] [428.2] [6.521] [1.816e+04] [501] [6.521] [8338] [339.4] [6.435] [3.469e+04] [522.1] [7.612] [7635] [363.4] [5.994] [1.271e+04] [371.4] [5.602] [1.004e+04] [451.9] [5.486] [7436] [376] [4.942] [2.631e+04] [584.8] [4.822] [1.76e+04] [605.4] [4.942] [1.159e+04] [393.9] [4.946] [1.059e+04] [510.3] [5.019] [1.02e+04] [418] [4.946]
189
190
ˇ geneti cki algoritmi
141 243 [1129] [1.223e+04] [339.6] [4.498] 142 233 [1841] [1.926e+04] [503.9] [4.498] 143 227 [2081] [2.256e+04] [440.2] [4.498] 144 237 [1637] [1.377e+04] [463.4] [4.812] 145 227 [822.9] [5511] [331.5] [4.812] 146 241 [1353] [1.136e+04] [456.5] [4.511] 147 241 [2742] [4.17e+04] [552.9] [4.359] 148 239 [1607] [1.535e+04] [511.9] [4.501] 149 240 [1390] [2.069e+04] [288.1] [4.207] 150 236 [2938] [4.022e+04] [644.6] [4.207] 151 235 [1182] [8947] [463.4] [4.325] 152 240 [1623] [2.288e+04] [419.3] [4.137] 153 235 [1488] [1.018e+04] [488.9] [4.137] 154 237 [1428] [1.126e+04] [406.1] [4.173] 155 238 [1028] [1.098e+04] [407.9] [4.173] 156 242 [1936] [2.189e+04] [512.9] [4.173] 157 239 [1401] [1.565e+04] [482.9] [4.349] 158 231 [1646] [1.815e+04] [470.4] [4.173] 159 240 [1213] [1.234e+04] [380.1] [4.173] 160 237 [2538] [2.251e+04] [663.3] [4.12] 161 238 [1553] [1.415e+04] [555.3] [4.12] 162 242 [958.1] [6383] [399.8] [4.12] 163 238 [2865] [4.117e+04] [588.5] [4.12] 164 239 [1653] [2.155e+04] [407.9] [4.12] 165 238 [1852] [2.361e+04] [475.2] [4.149] 166 235 [1891] [1.527e+04] [607.9] [4.12] 167 236 [3473] [5.273e+04] [625] [3.956] 168 239 [1542] [1.697e+04] [463] [3.956] 169 239 [807.2] [6581] [350.1] [3.934] 170 241 [1412] [1.861e+04] [425.3] [3.89] 171 231 [1155] [9384] [384.7] [3.771] 172 238 [1163] [1.102e+04] [399.2] [3.771] 173 235 [1219] [1.679e+04] [298.3] [3.705] 174 238 [1162] [1.117e+04] [374.7] [3.705] 175 236 [1362] [1.645e+04] [381.5] [3.546] 176 237 [1214] [1.07e+04] [409.8] [3.546] 177 236 [1791] [1.927e+04] [552.3] [3.488] 178 239 [848.6] [5107] [369.8] [3.488] 179 237 [830.2] [4992] [382] [3.488] 180 243 [2064] [2.391e+04] [454.4] [3.488] 181 236 [1035] [9859] [340.8] [3.488] 182 239 [1009] [7094] [379.3] [3.488] 183 238 [2095] [2.451e+04] [513] [3.418] 184 241 [1196] [1.205e+04] [422.7] [3.418] 185 232 [1858] [1.774e+04] [531.3] [3.48] 186 243 [1039] [7818] [369.3] [3.48] 187 241 [2927] [3.483e+04] [681.6] [3.48] 188 239 [1053] [1.037e+04] [337.1] [3.48] 189 237 [1260] [1.353e+04] [440.2] [3.352] 190 233 [1493] [1.131e+04] [541.1] [3.352] 191 238 [1221] [1.254e+04] [363] [3.352] 192 239 [1183] [1.012e+04] [402] [3.352] 193 237 [661.4] [6206] [207.8] [3.352] 194 229 [973.4] [1.098e+04] [311.9] [3.352] 195 239 [819.5] [8727] [309.5] [3.352] 196 241 [1426] [1.023e+04] [544] [3.352] 197 231 [1554] [1.574e+04] [460.7] [3.299] 198 230 [871.4] [7335] [357] [3.299] 199 230 [1274] [1.564e+04] [360.9] [3.337] 200 237 [1132] [1.33e+04] [335.3] [3.299] [[0.9766898231038279, 0.9607527096530896, 0.9065456124364575, 0.7944737905585467, 0.6248374250078815, 0.4065051529287608, 0.1803529539435661, 0.042390694202784074, 0.020730481699758788, -0.0009199868286795705]] [deap.creator.FitnessMax((3.2990264400893148,))]
38.2 korištenje deap modula
1011
min avg max
1010 109 108 107 106 105 104 103 102 101 100 0
50
100
150
200
Slika 38.1: Konvergencija optimizacije genetiˇckim algoritmom (Izvorni kod 38.1)
191
Dio VII DODACI
A
BIBLIOGRAFIJA
[1] Daniel Bratton and James Kennedy. Defining a standard for particle swarm optimization. In Swarm Intelligence Symposium, 2007. SIS 2007. IEEE, pages 120–127. IEEE, 2007. ˇ [2] Vladimír Cern y. ` Thermodynamical approach to the traveling salesman problem: An efficient simulation algorithm. Journal of optimization theory and applications, 45(1):41–51, 1985. [3] M.H. Chaudry. Open-channel flow. Springer Science+Business Media, 2008. [4] Félix-Antoine Fortin, François-Michel De Rainville, Marc-André Gardner, Marc Parizeau, and Christian Gagné. Deap: Evolutionary algorithms made easy. Journal of Machine Learning Research, 13:2171–2175, 2012. [5] L. V. Kantorovic. Mathematical methods of organizing and planning prodution. Management Science, 6: 363–422, 1960. (in Russian 1939). [6] J. Kennedy and R. Eberhart. Particle swarm optimization. In Neural Networks, 1995. Proceedings., IEEE International Conference on, volume 4, pages 1942–1948. IEEE, 1995. [7] Scott Kirkpatrick, D. Gelatt Jr., and Mario P Vecchi. Optimization by simmulated annealing. science, 220(4598):671–680, 1983. [8] J. A. Nelder and R. Mead. A simplex method for function minimization. Computer Journal, 7:308–313, 1965. [9] De Rainville, Félix-Antoine Fortin, Marc-André Gardner, Marc Parizeau, Christian Gagné, et al. Deap: A python framework for evolutionary algorithms. In Proceedings of the fourteenth international conference on Genetic and evolutionary computation conference companion, pages 85–92. ACM, 2012. [10] S.S. Rao and S.S. Rao. Engineering Optimization: Theory and Practice. Wiley, 2009. ISBN 9780470183526. [11] C.W. Reynolds. Flocks, herds and schools: A distributed behavioral model. In ACM SIGGRAPH Computer Graphics, volume 21, pages 25–34. ACM, 1987. [12] Y. Shi and R. Eberhart. A modified particle swarm optimizer. In Evolutionary Computation Proceedings, 1998. IEEE World Congress on Computational Intelligence., The 1998 IEEE International Conference on, pages 69–73. IEEE, 1998. [13] R. Szymkiewicz. Numerical modeling in open channel hydraulics (Water science & technology library). Recherche, 67:02, 2010. [14] F van den Bergh. An Analysis of Particle Swarm Optimizers., Submitted Ph. D. PhD thesis, thesis, University of Pretoria, Pretoria, 2001. [15] M. K. Wood and G. B. Dantzig. Programming of Interdependent Activities. I. General Discussion. Econometrica, 17:193–199, 1949. [16] M. K. Wood and G. B. Dantzig. Programming of Interdependent Activities. I. Mathematical Model. Econometrica, 17:200–211, 1949.
195
colophon This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License. http://creativecommons.org/licenses/by-sa/3.0/
This document was typeset using the typographical look-and-feel classicthesis developed by André Miede. The style was inspired by Robert Bringhurst’s seminal book on typography “The Elements of Typographic Style”. classicthesis is available for both LATEX and LYX: http://code.google.com/p/classicthesis/
Final Version as of 19. sijeˇcnja 2014. (classicthesis v0.1).