1 theory Cas9_vezbe_resenja
   2 imports Complex_Main
   3 begin
   4 
   5 section Prirodni brojevi i matematička indukcija
   6 
   7 textZadaci su preuzeti iz materijala profesora Ikodinovića: 
   8 @{url http://www.matf.bg.ac.rs/p/files/43-matematicka_indukcija.pdf}.
   9 
  10 text
  11 U narednim primerima ćemo koristiti ugrađen tip prirodnih brojeva @{type nat}.
  12 Tip prirodnih brojeva je rekurzivno definisan tip sa konstruktorima nula i 
  13 sledbenik. Posebno se dobro slaže sa induktivnim dokazima i primitivno 
  14 rekurzivnim definicijama.
  15 
  16 Teorija prirodnih brojeva moze se naći na: 
  17 @{url https://isabelle.in.tum.de/library/HOL/HOL/Nat.html}
  18 
  19 Postoji jako puno teorema nad prirodnim brojevima koje možemo koristiti po 
  20 potrebi. Za pretraživanje skupa teorema možemo koristiti naredbu 
  21 \verb!find_theorems! koja nam nudi pretragu po imenu (uz ključnu reč \verb!name!, 
  22 ili pretragu po šablonu koji nam treba. Na primer, uz pomoć narednih
  23 dveju naredbi možemo pronaći teoreme @{text Suc_eq_plus1:} @{thm Suc_eq_plus1 
  24 [no_vars]} i @{text add_mult_distrib2:} @{thm add_mult_distrib2 [no_vars]}.
  25 
  26 find_theorems name: "Suc_eq"
  27 thm Suc_eq_plus1 (* Suc n = n+1 *)  @{thm Suc_eq_plus1 [no_vars]}
  28 
  29 find_theorems "_ * (_ + _) = _ * _ + _ * _" 
  30 thm add_mult_distrib2   @{thm add_mult_distrib2 [no_vars]}
  31 
  32 textU dokazima će nam često trebati teoreme vezane za sabiranje, oduzimanje i 
  33 množenje. Nekoliko najčešće korišćenih se nalaze u skupu teorema sa imenom 
  34 \verb!algebra_simps!. Teoreme vezane za deljenje se nalaze u posebnom skupu 
  35 teorema koji se zove \verb!field_simps! (ovaj skup je nadskup prethodnog skupa).
  36 
  37 thm algebra_simps
  38 
  39 thm field_simps
  40 
  41 textKada se neka od potrebnih lema, ili ceo skup lema, dodaje automatskim 
  42 alatima ključne reči koje se koriste za metod @{text auto} su 
  43 @{text simp add} i @{text simp del}.
  44 
  45 text
  46 \begin{exmp}
  47 Dokazati da važi $1 + \ldots + n = n * (n+1) div 2$.
  48 \footnote{Zadatak 1 iz dodatnog materijala.}
  49 \end{exmp}
  50 
  51 Sada kada radimo sa prirodnim brojevima, možemo ponovo definisati neke od 
  52 funkcija koje smo videli na prošlom času:
  53 
  54 primrec zbir_do :: "nat ⇒ nat" where               
  55 "zbir_do 0 = 0" |
  56 "zbir_do (Suc n) = Suc n + (zbir_do n)"
  57 
  58 textSada uz pomoć automatskih alata, i skupa lema \verb!algebra_simps! možemo 
  59 dokazati narednu lemu. Primetite da smo na prošlom času koristili dodatnu 
  60 funkciju \verb!duplo!, zato što nismo definisali operaciju \verb!div! u 
  61 našem izvedenom skupu prirodnih brojeva. Sada kada radimo sa ugrađenim tipom 
  62 prirodnih brojeva, na raspolaganju imamo i operaciju \verb!div! pa lemu možemo 
  63 zapisati na sledeći način i dokazati je na sledeći način:
  64 
  65 lemma suma_do_n_automatski: "zbir_do n = n * (n+1) div 2"
  66 by (induction n, auto simp add: algebra_simps)
  67 
  68 textDokaz iste leme u Isar-u:
  69 
  70 lemma suma_do_n_isar: "zbir_do n = n * (n+1) div 2"
  71 proof (induction n)
  72 case 0
  73   show ?case 
  74     by (simp only: zbir_do.simps(1))
  75 next
  76 case (Suc n)
  77 thm Suc
  78   show ?case 
  79   proof - 
  80     have "zbir_do (Suc n) = Suc n + zbir_do (n)" 
  81       by (simp only: zbir_do.simps(2))
  82     also have "... = Suc n + n * (n+1) div 2" 
  83     using Suc by simp
  84     also have "... = 2 * (Suc n) div 2 + (Suc n) * n div 2" 
  85     by simp
  86     also have "... = (Suc n) * (2 + n) div 2" 
  87     by simp
  88     finally show ?thesis by simp
  89   qed
  90 qed
  91 
  92 text
  93 \begin{exmp}
  94 Dokazati da važi $1 + 3 + 5 + \ldots + (2*n - 1) = n*n$.
  95 \footnote{Zadatak 2 iz dodatnog materijala.}
  96 \end{exmp}
  97 
  98 
  99 value "1 + 3 + 5 + 7 + 9::nat"
 100 value "5*5::nat"
 101 
 102 textU ovom zadatku prvo je potrebno definisati funkciju sa leve strane date 
 103 jednačine. U pitanju je zbir prvih $n$ neparnih brojeva, što možemo definisati 
 104 primitivnom rekurzijom na sledeći način:
 105 
 106 
 107 primrec zbir_neparnih :: "nat ⇒ nat" where               
 108 "zbir_neparnih 0 = 0" |
 109 "zbir_neparnih (Suc n) = 2*(Suc n) - 1 + (zbir_neparnih n)"
 110 
 111 textSada možemo dokazati traženu lemu i automatski i raspisano u Isar-u.
 112 
 113 lemma neparni_auto: "zbir_neparnih n = n*n"
 114 by (induction n, auto simp add: algebra_simps)
 115 
 116 lemma neparni_isar: "zbir_neparnih n = n*n"
 117 proof (induction n)
 118   case 0
 119   show ?case by (simp only: zbir_neparnih.simps(1))
 120 next
 121   case (Suc n)
 122   show ?case
 123   proof - 
 124     have "zbir_neparnih (Suc n) = 2*(Suc n) - 1 + zbir_neparnih n"
 125       by (simp only: zbir_neparnih.simps(2))
 126     also have "... = 2*(Suc n) - 1 + n*n" using Suc by simp
 127     also have "... = 2*n + 1 + n*n" by simp
 128     finally show ?thesis by simp
 129   qed
 130 qed
 131 
 132 text
 133 \begin{exmp}
 134 Dokazati da važi: $-1 + 3 - 5 + \ldots + (-1)^n * (2*n-1) = (-1)^n * n$.
 135 \footnote{Zadatak 5 iz dodatnog materijala.}
 136 \end{exmp}
 137 
 138 Prvi korak je definisanje funkcije koja opisuje izraz sa leve strane:
 139 
 140 
 141 primrec zbir_naizmenicno:: "nat ⇒ int" where
 142 "zbir_naizmenicno 0 = 0" | 
 143 "zbir_naizmenicno (Suc n) = zbir_naizmenicno n + (-1)^(Suc n) * (2 * (Suc n) - 1)"
 144 
 145 textKada se radi sa celim brojevima, oduzimanje može u nekim situacijama 
 146 napraviti problem i biće potrebna konverzija u ceo broj, na primer: 
 147 @{text int(Suc n)}. 
 148 
 149 Nakon raspisivanja dokaza na papiru, vidimo da su nam potrebne neke teoreme 
 150 određenog formata. Pretragu po formatu smo već koristili: 
 151 
 152 find_theorems "_ ^ Suc _"
 153 find_theorems " _ * ( _ + _ ) = _ * _ + _ * _ "
 154 thm int_distrib
 155 
 156 lemma zad5: "zbir_naizmenicno n = (-1)^n * n"
 157 proof (induction n)
 158   case 0
 159   then show ?case 
 160     by simp
 161 next
 162   case (Suc n)
 163   show ?case
 164   proof -
 165     have "zbir_naizmenicno (Suc n) = zbir_naizmenicno (n) + (-1)^(Suc n) * (2 * (Suc n) - 1)"
 166       by (simp only: zbir_naizmenicno.simps)
 167     also have "... = (-1)^n * n + (-1)^(n+1)*(2*(n+1)-1)"
 168       using Suc by simp
 169     also have "... = (-1)^n *(-1)*(-1)*n + (-1)^(n+1)*(2*n+1)"
 170       by simp
 171     also have "... = (-1)^(n+1)*(-1)*n + (-1)^(n+1)*(2*n+1)" 
 172       by simp
 173     also have "... = (-1)^(n+1) * ((-1)*n + (2*n+1))"
 174       by (simp add: int_distrib)  ili @{text using int_distrib by simp}
 175     also have "... = (-1)^(n+1) * (n+1)" by simp
 176     finally show ?thesis by simp
 177   qed
 178 qed
 179 
 180 subsectionZbir kvadrata
 181 
 182 text
 183 \begin{exmp}
 184 Dokazati da važi da je $1 + 2^2 + ... + n^2 = n * (n+1) * (2*n+1) div 6$.
 185 \footnote{Zadatak 8 iz dodatnog materijala.}
 186 \end{exmp}
 187 
 188 Prvo je potrebno definisati funkciju koja opisuje levu stranu ovog izraza.
 189 Postoji više načina da definišemo funkciju koja računa zbir kvadrata od 1 do n. 
 190 Prvi način je da koristimo primitivnu rekurziju, drugi način je da koristimo 
 191 bibliotečke funkcije za rad sa listama.
 192 
 193 \paragraph{Primitivna rekurzija:}
 194 Prvo definišemo primitivnom rekurzijom funkciju koja izračunava zbir kvadrata:
 195 
 196 
 197 primrec zbir_kvadrata :: "nat ⇒ nat" where 
 198 "zbir_kvadrata 0 = 0" |
 199 "zbir_kvadrata (Suc n) = zbir_kvadrata n + (Suc n) ^ 2"
 200 
 201 value "zbir_kvadrata 1"
 202 value "zbir_kvadrata 2"
 203 value "zbir_kvadrata 3"
 204 
 205 text
 206 \paragraph{Ugrađene funkcije za rad sa listama:}
 207 Korišćenjem ugrađene podrške za liste brojeva, možemo slično kao na prošlom času 
 208 zapisati izraz za zbir kvadrata. Listu elemenata od 0 do 4, odnosno njihov zbir, 
 209 možemo dobiti narednim dvema naredbama:
 210 
 211 value "[0..<5]"
 212 value "sum_list [0..<5]"
 213 
 214 textMožemo umesto 0 napisati 1 i dobiti upravo ono što nam treba u postavci ovog 
 215 zadatka, listu brojeva od 1 do n, odnosno zbir brojeva od 1 do n (iako je u ovom 
 216 slučaju svejedno jer 0 ne utiče na vrednost izraza):
 217 
 218 value "[1..<5]"
 219 value "sum_list [1..<5]"
 220 
 221 textMeđutim, nama treba zbir kvadrata pa uvodimo elemente \emph{funkcionalnog 
 222 programiranja}. Isabelle je funkcionalni programski jezik i postoji funkcional 
 223 višeg reda \emph{map} koji datu funkciju primenjuje na svaki element liste. Prvo 
 224 ćemo ključnom rečju @{text definition} definisati novu funkciju koja kvadrira 
 225 vrednost svog argumenta:
 226 
 227 definition kvadrat :: "nat ⇒ nat" where 
 228 "kvadrat x = x * x"
 229 
 230 textNaredna naredba prikazuje korišćenje funkcionala @{text map} i primenjuje 
 231 funkciju kvadriranja na elemente liste. Rezultat te naredbe je nova lista čiji 
 232 elementi su jednaki kvadratima elemenata polazne liste. Funkcija @{text 
 233 sum_list} sumira elemente tako dobijene liste.
 234 
 235 value "map kvadrat [1..<5]" 
 236 value "sum_list (map kvadrat [1..<5])"
 237 
 238 textIsti efekat se može dobiti i bez definicije, ali sada primenjujemo 
 239 \emph{anonimnu funkciju} definisanu pomoću lambda @{text (λ)} izraza:
 240 
 241 value "sum_list (map (λ x. x ^ 2) [1..<5])"
 242 
 243 textLambda izraz predstavlja anonimnu funkciju čiji se parametar navodi odmah 
 244 iza @{text λ}, a nakon tačke se nalazi telo funkcije. Sada funkciju koja 
 245 izračunava zbir kvadrata možemo definisati i direktno bez primitivne rekurzije:
 246 
 247 definition zbir_kvadrata' :: "nat ⇒ nat" where
 248 "zbir_kvadrata' n = sum_list (map (λ x. x ^ 2) [1..<Suc n])"
 249 
 250 textU Isabelle-u postoji skraćeni zapis (blizak matematičkom zapisu na koji smo 
 251 navikli). @{text } se zapisuje kao \verb!\!\verb!<Sum>!, @{text } se 
 252 zapisuje kao \verb!\!\verb!<leftarrow>!. Leva strana (pre tačke) navodi opseg 
 253 vrednosti za x, a desna strana (posle tačke) navodi na koji način se te vrednosti 
 254 transformišu:
 255 
 256 value "∑ x ← [1..<5]. x ^ 2"
 257 
 258 textAko bismo ovu istu funkciju prosledili kao parametar funkciji @{text term} 
 259 možemo videti da u pozadini sistem ipak koristi raspisani oblik koji smo malopre 
 260 pokazali @{term  x  [1..<5]. x ^ 2}. Jedina razlika je što sistem koristi 
 261 već ugrađenu funkciju @{text power2} koja izračunava kvadrat broja.
 262 
 263 term "∑ x ← [1..<5]. x ^ 2"
 264 
 265 text
 266 \begin{exmp}
 267 Pokazati da su ove definicije ekvivalentne, odnosno pokazati da važi: 
 268 \verb!zbir_kvadrata n = zbir_kvadrata' n!.
 269 \end{exmp}
 270 
 271 Prvo pokušavamo sa indukcijom, što očekivano rezultuje sa dva cilja. Nakon toga 
 272 pokušavamo sa auto, ali automatski alati ne prolaze. Razlog za to je što funkcije 
 273 definisane primitivnom rekurzijom automatski ulaze u simplifikator i njihova 
 274 pravila se automatski primenjuju, ali funkcije definisane pomoću ključne reči 
 275 \emph{definition} nisu deo simplifikatora i moramo ih eksplicitno dodati.
 276 
 277 thm zbir_kvadrata.simps  ove teoreme su automatski ukljucene u proces simplifikacije
 278 thm zbir_kvadrata'_def  ova teorema nije automatski ukljucena u proces simplifikacije
 279 
 280 lemma "zbir_kvadrata n = zbir_kvadrata' n"
 281 apply (induction n)
 282 apply auto
 283 apply (auto simp add: zbir_kvadrata'_def)
 284 done
 285 ili skraćeno @{text by (induction n) (auto simp add: zbir_kvadrata'_def)}
 286 
 287 textDrugi način na koji možemo zapisati ovu lemu je bez uvođenja definicije, i 
 288 sada nema potrebe za dodavanjem dodatne leme (zato što smo već raspisali 
 289 definiciju sami):
 290 
 291 lemma "zbir_kvadrata n = (∑ x ← [1..<Suc n]. x ^ 2)"
 292 by (induction n) auto
 293   
 294 text
 295 \begin{exmp}
 296 Dokazati da važi: $1 + 2^2 + ... + n^2 = n * (n+1) * (2*n+1) div 6$
 297 \end{exmp}
 298 
 299 Ovaj dokaz neće proci korišćenjem samo automatskih metoda već moramo da 
 300 simuliramo dokaz koji je naveden u matematičkom udžbeniku.
 301 
 302 textPogledajmo prvo kako izgleda princip indukcije za prirodne brojeve. Postoji 
 303 ugrađena teorema indukcije koja se zove @{text nat.induct}, 
 304 @{thm nat.induct [no_vars]}, koja je već dokazana u sistemu i deo je biblioteke 
 305 teorema koje mi možemo koristiti:
 306 
 307 thm nat.induct
 308 
 309 textI po njoj vidimo: da bismo dokazali da svojstvo P važi za proizvoljan 
 310 prirodan broj, dovoljno je da dokažemo da to svojstvo P važi za nulu, i kada 
 311 fiksiramo proizvoljni prirodni broj, ako pretpostavimo da upravo za taj broj važi 
 312 svojstvo P i iz toga uspemo da izvedemo da i njegov sledbenik ima svojstvo P.
 313 
 314 lemma "zbir_kvadrata n = (n * (n + 1) * (2*n + 1)) div 6"
 315 proof (induction n)
 316   case 0
 317   then show ?case 
 318   by auto
 319 next
 320   case (Suc n)
 321   have "zbir_kvadrata (Suc n) = zbir_kvadrata n + (Suc n) ^ 2"
 322     by simp na osnovu @{text zbir_kvadrata.simps}
 323   also have "... = zbir_kvadrata n + (n+1)*(n+1)"
 324     by (simp add: power2_eq_square) neophodna nam je ova lema @{thm power2_eq_square [no_vars]}
 325   also have "... = (n * (n + 1) * (2*n + 1)) div 6 + (n+1)*(n+1)"
 326     using Suc
 327     by simp na osnovu induktivne hipoteze
 328   also have "... = (n * (n + 1) * (2*n + 1) + 6 * (n+1) * (n+1)) div 6"
 329     by (simp add: algebra_simps) za algebarske manipulacije koristimo skup teorema
 330   also have "... = ((n + 1) * (n + 2) * (2*n + 3)) div 6"
 331     by (simp add: algebra_simps)
 332   finally 
 333   show ?case 
 334     by (simp add: algebra_simps)
 335 qed
 336 
 337 textU ovim dokazima možemo korisititi ili samo \emph{simp} ili \emph{auto} koji 
 338 je malo moćniji. On svakako prvo poziva \emph{simp} ali ima još neke dodatne 
 339 mogućnosti koje nekada mogu biti korisne.
 340 
 341 subsectionRad sa matricama
 342 
 343 textU narednom primeru ćemo pokazati množenje matrica u isabelle-u. Prvo moramo 
 344 matricu zapisati na neki način, u ovom primeru nam olakšava to što je dimenzija 
 345 matrice fiksna pa je najjednostavnije da matricu predstavimo uređenom četvorkom 
 346 njenih elemenata. Elemente pišemo po vrstama i eksplicitno navodimo tip ove 
 347 matrice i koristimo operator @{text ×} (koji se zapisuje sa 
 348 \verb!\!\verb!<times>!) pomoću kog kreiramo tip uređenog para, odnosno uređene 
 349 n-torke.
 350 
 351 term "(1, 1, 0, 1) :: nat × nat × nat × nat"
 352 
 353 textDa ne bismo stalno navodili ovu četvorku, možemo koristiti sinonime 
 354 (skraćenice) za već postojeće tipove. Oni se raspisuju nakon parsiranja teksta i 
 355 nisu deo interne reprezentacije niti ispisa. Sinonimi služe udobnosti zapisa 
 356 korisnika. Matricu ćemo navesti na sledeći način:
 357 
 358 type_synonym mat2 = "nat × nat × nat × nat"
 359 term "(1, 1, 0, 1) :: mat2"
 360 
 361 
 362 text
 363 \begin{exmp}
 364 Dokazati da važi $(1,1,0,1)^n = (1,n,0,1)$.
 365 \footnote{Zadatak 3 iz dodatnog materijala.}
 366 \end{exmp}
 367 
 368 Sledeći korak je da definišemo sve pojmove koji su nam se javljali u
 369 dokazu iz udžbenika: jediničnu matricu, množenje matrica, stepenovanje matrica. 
 370 
 371 Jediničnu matricu uvodimo narednom definicijom:
 372 
 373 definition eye :: mat2 where
 374 "eye = (1, 0, 0, 1)"
 375 
 376 textNakon ovoga definišemo proizvod dve matrice i uvodimo novi način definisanja 
 377 objekata. Definicija (odnosno ključna reč @{text definition}) ne može da se 
 378 koristi na ovom mestu zato što argument funkcije koja se uvodi definicijom mora 
 379 biti jedna promenljiva (na primer @{text mat_mul m1 m2}, nakon čega bi bilo 
 380 potrebno da mi sami nekim novim operatorima vadimo element po element). Zbog toga 
 381 ovde koristimo ključnu reč @{text fun} koja koristi uklapanje šablona 
 382 \emph{(pattern matching)}. Sada umesto da sa leve strane imamo samo imena 
 383 promenljivih, imamo mogućnost da na tom mestu zadamo stukturu vrednosti koje 
 384 te promenljive predstavljaju.
 385 
 386 fun mat_mul :: "mat2 ⇒ mat2 ⇒ mat2" where
 387   "mat_mul (a1, b1, c1, d1) (a2, b2, c2, d2) = (a1*a2 + b1*c2, a1*b2 + b1*d2, c1*a2 + d1*c2, c1*b2 + d1*d2)"
 388 
 389 textU buduće ćemo @{text fun} koristiti za definisanje funkcija običnom 
 390 rekurzijom.
 391 
 392 Sada definišemo stepenovanje matrica korišćenjem primitivne rekurzije. I 
 393 korišćenjem funkcije @{text value} proveravamo da li je definicija dobra.
 394 
 395 
 396 primrec mat_pow :: "mat2 ⇒ nat ⇒ mat2" where
 397 "mat_pow A 0 = eye" |
 398 "mat_pow A (Suc n) = mat_mul A (mat_pow A n)"
 399 
 400 value "mat_pow (1, 1, 0, 1) 3"
 401 
 402 thm mat_pow.simps 
 403 
 404 lemma "mat_pow (1, 1, 0, 1) n = (1, n, 0, 1)"
 405   by (induction n, auto simp add: eye_def)  dodajemo zato što se definicije ne raspliću automatski
 406 
 407 lemma "mat_pow (1, 1, 0, 1) n = (1, n, 0, 1)"
 408 proof (induct n)
 409   case 0
 410   show ?case
 411     by (simp add: eye_def)
 412 next
 413   case (Suc n)
 414   show ?case
 415   proof-
 416     have "mat_pow (1, 1, 0, 1) (Suc n) = mat_mul (1, 1, 0, 1) (mat_pow (1, 1, 0, 1) n)"
 417       by simp 
 418     also have "... = mat_mul (1, 1, 0, 1) (1, n, 0, 1)"
 419       using Suc
 420       by simp 
 421     also have "... = (1*1+n*0, 1*1+n*1, 0*1+1*0, 0*1+1*1)"
 422       by simp
 423     finally show ?thesis
 424       by simp
 425   qed
 426 qed 
 427 
 428 subsection Deljivost
 429 
 430 textNeke teoreme vezane za deljivost možemo dobiti pretragom skupa teorema:
 431 
 432 find_theorems "_ dvd _"
 433 find_theorems "_ dvd _ * _"
 434 find_theorems "_ dvd _ + _"
 435 find_theorems "_ ⟹  _ dvd _ + _"
 436 
 437 thm nat_induct
 438 thm dvd_def
 439 thm dvd_add
 440 
 441 thm dvd_refl
 442 find_theorems "_ ^ _"
 443 thm power_0
 444 thm power_one_right
 445 
 446 text\begin{exmp}
 447 Dokazati da za svaki prirodan broj n važi: $6 | n * (n + 1) * (2n + 1)$.
 448 \footnote{Zadatak 9 iz dodatnog materijala.}
 449 \end{exmp}
 450 
 451 U postavci ovog zadatka mora biti naglašeno da je u pitanju prirodan broj. U 
 452 dokazima teorema sa celim brojevima, tipovi su često problem, pa se može 
 453 iskoristiti nareda @{text using [[show_types]]} koja može da otkrije potrebu za 
 454 uvođenjem tipova u teoremi. Nakon utvrđivanja tipova, naredba može da se 
 455 obriše.
 456 
 457 Ako bismo prvo pokušali da formulišemo teoremu na sledeći način (namerno menjamo 
 458 tvrđenje teoreme da ne bi zbunili sledgehammer kasnije sa identičnim tvrđenjem), 
 459 i pokušali sa pravilom indukcije dobili bismo poruku o grešci: \emph{Unable to 
 460 figure out induct rule}. Ako sada dodamo naredbu @{text using [[show_types]]}, 
 461 odmah nakon tvrđenja teoreme (pre poziva indukcije), vidimo da isabelle nije u 
 462 stanju da ustanovi kog tipa su vrednost 6 i 2. Pa dodajemo sa @{text fixes} 
 463 informaciju da je n prirodan broj. Sada ako ponovo pogledamo izlaz nakon naredbe 
 464 @{text using [[show_types]]} možemo primetiti da isabelle sada može da zaključi 
 465 tip i za vrednosti 6 i 2.
 466 
 467 declare [[quick_and_dirty=true]]
 468 
 469 lemma deljivost_primer:
 470 shows "6 dvd 2*3*n" 
 471 using [[show_types]]  
 472 @{text proof (induction n)}
 473   sorry
 474 
 475 lemma deljivost_sa_6:
 476 fixes n :: nat 
 477 shows "6 dvd n*(n+1)*(2*n+1)" 
 478  @{text using [[show_types]]}
 479 proof (induction n)
 480   case 0
 481   then show ?case
 482     by simp 
 483 next
 484   case (Suc n)
 485   then show ?case 
 486   proof - 
 487     have "Suc n * (Suc n + 1) * (2 * Suc n + 1) = (n+1)*(n+2)*(2*n+3)" 
 488       by (simp add: algebra_simps)
 489     also have "... = n*(n+1)*(2*n+3) + 2*(n+1)*(2*n+3)" 
 490       by (simp add: algebra_simps)
 491     also have "... = n*(n+1)*(2*n+1) + 2*n*(n+1) + 2*(n+1)*(2*n+3)"
 492       by (simp add: algebra_simps)
 493     also have "... = n*(n+1)*(2*n+1) + 2*(n+1)*(3*n+3)"
 494       by (simp add: algebra_simps)
 495     also have "... = n*(n+1)*(2*n+1) + 6*(n+1)*(n+1)"
 496       by (simp add: algebra_simps)
 497     finally show ?thesis
 498       using Suc
 499       na ovakvom mestu mozemo pokusati i sledgehammer
 500       thm One_nat_def
 501  a možemo pokušati i @{text using [[simp_trace]] by simp} i dobijamo 
 502 poruku: "Term does not become smaller". Ovaj izlaz nam prikazuje šta je tačno 
 503 primenjivano tokom simplifikacije. Ako krene pogrešnim putem onda se može 
 504 obrisati teorema koja u stvari nije potrebna za ispravan dokaz. Ovde je to 
 505 teorema @{text One_nat_def:} @{thm One_nat_def [no_vars]}.
 506   by (simp del: One_nat_def)   
 507   qed
 508   qed
 509 
 510 
 511 text
 512 \begin{exmp}
 513 Dokazati da za svaki prirodan broj n važi: $3 | 5^n + 2^{n+1}$.
 514 \footnote{Zadatak 10 iz dodatnog materijala.}
 515 \end{exmp}
 516 
 517 
 518 lemma deljivost_sa_3:
 519 fixes n :: nat 
 520 shows "(3::nat) dvd 5^n + 2^(n+1)" 
 521 (* using [[show_types]] *)
 522 proof (induct n)
 523   case 0
 524   thus ?case
 525 sledgehammer daje slično rešenje
 526 drugi način je da pokušamo sa automatskim dokazivačima sami, i naredba 
 527 @{text apply simp} sugeriše da je potrebno koristiti pravilo narednog tipa 
 528 @{thm numeral_3_eq_3 [no_vars]}
 529   (* apply simp 
 530   find_theorems "3 = _"
 531   thm numeral_3_eq_3 *)
 532     by (simp add: numeral_3_eq_3)
 533 next
 534   case (Suc n)
 535  u narednom redu se koristi konvertovanje u tip nat. Konvertovanje je neophodno 
 536 kada iz konteksta nije moguće zaključiti tip. Operator stepenovanja @{text (^)} 
 537 je polimorfan i primenjuje se na objekte različitih tipova. U situaciji kada ne 
 538 prolazi dokaz koji deluje da bi trebalo da prođe automatski moguće je da tipovi 
 539 nisu u redu i da se moraju precizirati.
 540      
 541   have "(5::nat) ^ Suc n + 2 ^ (Suc n + 1) = 5 * 5 ^ n + 2 * 2 ^ (n + 1)"
 542   using[[show_types]]  pokrenite ovu naredbu bez ::nat u prethodnom redu
 543   by simp
 544   
 545   also have "... = 3 * 5 ^ n + 2 * (5 ^ n + 2 ^ (n + 1))"
 546     by simp
 547   finally 
 548   show ?case
 549 ovde se može iskoristiti sledgehammer, ili možemo pogledati sam oblik koji 
 550 nam treba i napakovati sledeći korak:
 551 ispis teorema koje se koriste: 
 552   thm Suc
 553   thm dvd_triv_left
 554   thm dvd_mult
 555   thm dvd_add 
 556     using dvd_add[OF dvd_triv_left[of "3::nat" "5^n"] dvd_mult[OF Suc, of 2]]
 557     by simp
 558 qed
 559 
 560 textObjašnjenje korišćenih naredbi:
 561 
 562 @{text dvd_triv_left[of...]} - \verb!of! služi da instanciramo promenljive u 
 563 lemi, navodimo ih onim redom kojim se javljaju u njoj.
 564         
 565 @{text dvd_add[OF...]} nam omogućava da zadamo premise teoreme 
 566 @{text dvd_add}, premise su u stvari dve činjenice koje dobijamo uz pomoć 
 567 teorema @{text dvd_triv_left} i @{text dvd_mult}.
 568 
 569 @{text dvd_mult[OF Suc, of 2]} - \verb!OF! omogućava nam da zadamo premisu 
 570 našoj lemi, ovako istovremeno zadajemo i premisu i instanciramo jednu 
 571 promenljivu (sa \verb!of!).
 572 
 573 
 574 
 575 subsectionNejednakosti sa celim brojevima
 576 
 577 text
 578 \begin{exmp}
 579 Dokazati da za svaki prirodan broj $n \geq 5$ važi $n^2 < 2^n$.
 580 \footnote{Zadatak 11 iz dodatnog materijala.}
 581 \end{exmp}
 582 
 583 U udžbeniku možemo da primetimo da se u dokazu ovog tvrđenja koristi pomoćno 
 584 tvrđenje koje prvo moramo dokazati. Prilikom formulisanja ovih tvrđenja moramo 
 585 naglasiti da je n prirodan broj, zato što to ne može da se zaključi iz konteksta 
 586 a ta informacija nam je neophodna da bismo mogli u dokazima da koristimo princip 
 587 matematičke indukcije. To radimo ključnom rečju @{text fixes}.
 588 
 589 Ključna reč @{text fixes} nam omogućava da navedemo tip promenljivih unapred, 
 590 pre navođenja tvrđenja teoreme (naspram korišćenja @{text n::nat} negde u 
 591 zapisu teoreme). Pored toga ovde nam znači da koristimo struktuirani zapis 
 592 tvrđenja i ključne reči @{text assumes} i @{text shows} koje nam dozvoljavaju 
 593 da imenujemo pretpostavke teoreme (ako imamo više različitih pretpostavki možemo 
 594 ih razdvojiti ključnom rečju @{text and}) i sa @{text shows} da izdvojimo 
 595 cilj teoreme.
 596 
 597 Sledeći detalj koji moramo naglasiti jeste da nam je u ovom dokazu neophodno da 
 598 uključimo pretpostavke pre pozivanja indukcije. To radimo korišćenjem ključnih 
 599 reči @{text using assms} i sada je uslov $n > 2$ uključen i u princip 
 600 indukcije. U ovakvim dokazima induktivni korak se sastoji iz dva dela, prvi deo 
 601 je standardni (da tvrđenje važi za n), a drugi deo se sastoji od tvrđenja da 
 602 sledbenik broja n zadovoljava pretpostavke koje se nalaze medju @{text assms}.
 603 
 604 Sada moramo obratiti pažnju na dva nivoa baze indukcije, prvi obrađuje šta se 
 605 dešava sa nulom (automatski je ispunjen uslov zato što nula ne zadovoljava 
 606 pretpostavke teoreme), a drugi nivo obrađuje šta se stvarno dešava sa minimalnim 
 607 brojem n za koji je ispunjen preduslov našeg tvrđenja. U ovom primeru to je broj 
 608 3. Pa sada treba na neki način posebno obraditi slučaj trojke, i slučaj 
 609 sledbenika.
 610 
 611 Ovakva induktivna hipoteza je uslovna, uslov koji mora da važi je da je 
 612 @{text Sled n  3}, odnosno @{text n  2}. Dakle razlikujemo slučaj kada je 
 613 @{text Sled n = 3} i slučaj kada je @{text Sled n > 3}. Slučaj kada je 
 614 @{text Sled n = 3}, je stvarna baza indukcije. I moramo da izvršimo analizu 
 615 slučajeva prema ova dva slučaja.
 616 
 617 \emph{Rezonovanje po slučajevima} se dobija metodom @{text cases} i u ovom 
 618 slučaju poziva se naredbom @{text proof (cases "Suc n = 3")}. Dobijamo dva 
 619 slučaja @{text case True} i @{text case False}. U ovom dokazu takođe moramo 
 620 naglasiti da je \emph{also have} rezonovanje pogodno za operator @{text } ali 
 621 nije pogodan za lanac koji u sebi ima @{text } (kao što je navedeno u dokazu u 
 622 udžbeniku), pa se vodi računa o smeru u kom izvodimo formule.
 623 
 624 thm power2_eq_square
 625 
 626 lemma n2_2np1:
 627   fixes n::nat
 628   assumes "n > 2"
 629   shows "n^2 > 2*n + 1"
 630   using assms
 631 proof (induction n)
 632   case 0
 633   thus ?case  slučaj 0 se lako dokazuje zato što leva strana nije zadovoljena 
 634 pa je i desna automatski tačna, šta god pisalo na tom mestu
 635   by simp
 636 next
 637   case (Suc n) 
 638   thm Suc
 639   show ?case
 640   proof (cases "n = 2")
 641     case True
 642     thus ?thesis
 643       by simp
 644   next
 645     case False
 646     (*from this and Suc
 647     have "n > 2" 
 648     by simp*)
 649     hence "n > 2"  
 650       using Suc(2)
 651       by simp
 652 
 653     have "2 * (Suc n) + 1 < 2 * (Suc n) + 2 * n"
 654       using `n > 2`
 655       by simp
 656     also have "... = 2 * n + 1 + 2 * n + 1"
 657       by simp
 658     also have "... < n^2 + 2 * n + 1"
 659       using Suc(1) `n > 2`
 660       by simp
 661     also have "... = (Suc n)^2"
 662       by (simp add: power2_eq_square)
 663     finally
 664     show ?thesis
 665       .
 666   qed
 667 qed
 668 
 669 textSada prelazimio na dokaz glavnog tvrđenja koji je slične strukture. Jedina 
 670 nova stvar u ovom dokazu je instanciranje promenljive iz leme uz pomoć naredbe 
 671 @{text [of n]}. U uglastim zagradama se navodi ime promenljive.
 672 
 673 lemma 
 674   assumes "n ≥ 5"
 675   shows "2^n > n^2"
 676   using assms
 677 proof (induction n)
 678   case 0
 679   thus ?case
 680     by simp
 681 next
 682   case (Suc n)
 683   show ?case
 684   proof (cases "n = 4")  suštinska baza indukcije
 685     case True
 686     thus ?thesis
 687       by simp
 688   next
 689     case False
 690     hence "n ≥ 5"
 691       using Suc(2)
 692       by simp
 693 
 694     have "(Suc n)^2 = n^2 + 2*n + 1"
 695       by (simp add: power2_eq_square algebra_simps)
 696     also have "... < n^2 + n^2"
 697       using Suc(2) n2_2np1[of n]  instanciranje promenljive
 698       by simp 
 699     also have "... = 2 * n^2"
 700       by simp
 701     also have "... < 2 * 2^n"
 702       using Suc(1) `n ≥ 5`
 703       by simp
 704     also have "... = 2^(n+1)"
 705       by simp
 706     finally
 707     show ?thesis
 708       by simp
 709   qed
 710 qed
 711 
 712 subsection Pravilo indukcije koje počinje pozitivnim brojem
 713 
 714 text Pravilo indukcije koje zadovoljava uslov $n \geq m$ zove se @{text 
 715 nat_induct_at_least:} @{thm[mode=Proof] nat_induct_at_least [no_vars]} i ovako 
 716 se zapisuje u Isabelle-u. Zahvaljujući ovom pravilu možemo zapisati prethodne 
 717 dokaze tako da više liče na dokaze iz udžbenika.
 718 
 719 thm nat_induct_at_least
 720 
 721 (* Zadatak 11 - pomocno tvrdjenje *)
 722 
 723 lemma n2_2np1_at_least:
 724   fixes n::nat
 725   assumes "n ≥ 3"
 726   shows "n^2 > 2*n + 1"
 727   using assms
 728 proof (induction n rule: nat_induct_at_least)
 729 bazni slučaj
 730   case base
 731   thus ?case
 732     by simp
 733 next
 734   case (Suc n)
 735   have "2 * (Suc n) + 1 < 2 * (Suc n) + 2 * n"
 736     using `n ≥ 3`
 737     by simp
 738   also have "... = 2 * n + 1 + 2 * n + 1"
 739     by simp
 740   also have "... < n^2 + 2 * n + 1"
 741     using Suc
 742     by simp
 743   also have "... = (Suc n)^2"
 744     by (simp add: power2_eq_square)
 745   finally
 746   show ?case
 747   .
 748 qed
 749 
 750 subsection Princip jake indukcije
 751 
 752 textPostoje dva metoda: \verb!less_induct:! @{thm less_induct [no_vars]} i 
 753 \verb!nat_less_induct:! @{thm nat_less_induct}. 
 754 Prvi je opštiji (i radi za bilo koje potpuno uređenje), ali drugi je specifičniji 
 755 i zadovoljava naše potrebe za sada.
 756 
 757 thm less_induct (* (⋀x. (⋀y. y < x ⟹ ?P y) ⟹ ?P x) ⟹ ?P ?a *)
 758 thm nat_less_induct (* (⋀n. ∀m<n. ?P m ⟹ ?P n) ⟹ ?P ?n *)
 759 
 760 text
 761 \begin{exmp}
 762 Niz fibonačijevih brojeva zadat je jednačinama: $f_1 = 1$, $f_2 = 1$, 
 763 $f_n = f_{n-1} + f_{n-2}$, za $n>2$. 
 764 
 765 Dokazati da važi nejednakost:
 766 $$f_n \leq \varphi ^ {n-1}$$
 767 za svaki prirodan broj n, gde je $\varphi = \frac{1 + \sqrt{5}}{2}$.
 768 \footnote{Zadatak 6 iz dodatnog materijala.}
 769 \end{exmp}
 770 
 771 definition gm where
 772  "gm = (1 + sqrt 5) / 2"
 773 
 774 fun fib :: "nat ⇒ nat" where
 775 "fib 0 = 0" |
 776 "fib (Suc 0) = 1" |
 777 "fib (Suc (Suc n)) = fib (Suc n) + fib n"
 778 
 779 lemma fibonaci:
 780 shows "fib (n + 1) ≤ gm ^ n"
 781 proof (induction n rule: nat_less_induct)
 782 case (1 n)
 783 thm 1
 784   show ?case
 785   proof (cases "n = 0")
 786     case True
 787     thus ?thesis
 788       by simp
 789   next
 790     case False
 791     show ?thesis
 792     proof (cases "n = 1")
 793       case True
 794       have "fib 2 = 1"
 795         by (simp add: numeral_2_eq_2)
 796         thus ?thesis
 797         using `n = 1`
 798         by (simp add: gm_def)
 799     next
 800       case False
 801       show ?thesis
 802       proof-
 803         obtain m where "m = n - 2"
 804           by auto
 805           have "n > 1" using `n ≠ 0` `n ≠ 1`
 806           by simp
 807         have "fib (m + 3) = fib (m + 2) + fib (m + 1)"
 808           by (simp add: numeral_3_eq_3)             
 809         also have "... ≤ gm ^ (m + 1) + gm ^ m"
 810 modifikator @{text [rule_format]} od $\forall x. P x$ pravi "P ?x" 
 811 na koji onda možemo dalje da primenimo of da bi ubacili vrednost za x. 
 812 Obično se koristi kada imamo premisu sa univerzalnim kvantifikatorom 
 813 koju hoćemo da instanciramo prilikom primene.
 814           using 1[rule_format, of "m+1"] 1[rule_format, of m] `m = n - 2` `n > 1`
 815           by force
 816         also have "... = gm ^ m * (gm + 1)"       
 817           by (simp add: algebra_simps)
 818         also have "... = gm ^ m * (gm ^ 2)"
 819           by (simp add: power2_eq_square algebra_simps gm_def) 
 820         also have "... = gm ^ (m + 2)"
 821           by (simp add: power_add power2_eq_square)
 822         finally
 823         show ?thesis
 824           using `m = n - 2` `n > 1`
 825           by (simp add: numeral_2_eq_2 Suc_diff_Suc)
 826       qed
 827     qed
 828   qed
 829 qed
 830 
 831 
 832 
 833 section  Primeri sa realnim brojevima 
 834 
 835 textRealni brojevi nisu uključeni u teoriju @{text Main}. Da bi mogli da 
 836 radimo sa realnim brojevima potrebno je da uključimo @{text HOL.Real} a ako 
 837 želimo da radimo i sa kompleksnim brojevima potrebno je da uključimo @{text 
 838 MainComplex_Main}
 839 
 840 \begin{exmp}
 841 Dokazati da važi Bernulijeva nejednakost $(1 + x)^n \geq 1 + nx$, za $x > -1$.
 842 \footnote{Zadatak 4 iz dodatnog materijala.}
 843 \end{exmp}
 844 
 845 U narednom dokazu, nećemo koristiti @{text using assms} da bi bili 
 846 jednostavniji dokazi, pa ćemo se pozivati na pretpostavku samo na onim mestima u 
 847 dokazu gde ćemo je eksplicitno koristiti.
 848 
 849 
 850 
 851 lemma bernulijeva_nejednakost:
 852   fixes x::real and n::nat
 853   assumes "x > -1"
 854   shows "(1 + x)^n ≥ 1 + n * x"
 855 proof (induction n)
 856   case 0
 857   show ?case
 858     by simp
 859 next
 860   case (Suc n)
 861   show ?case
 862   proof-
 863     have "1 + (n + 1) * x ≤ 1 + (n + 1) * x + n * x^2"
 864       by simp
 865     also have "... = (1 + x) * (1 + n * x)"
 866       by (simp add: algebra_simps power2_eq_square)
 867     also have "... ≤ (1 + x) * (1 + x) ^ n"
 868       using Suc `x > -1`  ovde se pozivamo na pretpostavku
 869       by simp
 870     also have "... = (1 + x) ^ (Suc n)"
 871       by simp
 872     finally
 873     show ?thesis
 874       by simp
 875   qed
 876 qed                                            
 877 
 878 text Funkcije za kastovanje izmedju razlicitih tipova se mogu naci narednim 
 879 naredbama. Funkcije se zovu @{text "int"}, @{text real}, 
 880 @{text real_of_nat},...
 881 
 882 find_consts "nat ⇒ int"
 883 find_consts "nat ⇒ real"
 884 find_consts "real ⇒ complex"                                 
 885 
 886 textPrimer funkcije @{text int}. Tip i funkcija mogu imati isto ime. Ovde int 
 887 predstavlja funkciju koja slika tip @{typ nat} u tip @{typ int}. 
 888 
 889 term "3::nat"
 890 term "int (3::nat)"
 891 term "int 3"
 892 
 893 textPoziv \verb!@!\verb!{term t}! štampa dobro definisan term t. Poziv funkcije 
 894 \verb!@!\verb!{value t}! računa vrednost terma t i štampa rezultat.
 895 
 896 value "int (3::nat)"
 897 term "3::nat"
 898 value "3::nat"
 899 
 900 thm Re_complex_of_real
 901 thm Im_complex_of_real
 902 thm complex_of_real_def
 903 
 904 text
 905 \begin{exmp}
 906 Dokazati Moavrovu formulu: neka je dat kompleksan broj u trigonometrijskom obliku
 907 $z = r (\cos \theta + i* \sin \theta)$. Tada se $n$-ti stepen broja $z$ računa po 
 908 formuli:
 909 
 910 $$z^n = r^n (\cos n \theta + i \sin n \theta)$$
 911 \footnote{Zadatak 12 iz dodatnog materijala. }
 912 \end{exmp}
 913 
 914 lemma moavrova_formula:
 915   fixes r φ :: real and n :: nat
 916   shows "(r * (cos φ + \ * sin φ))^n = r^n * (cos (n * φ) + \ * sin(n * φ))"
 917 proof (induction n)
 918   case 0
 919   show ?case
 920     by simp
 921 next
 922   case (Suc n)
 923   show ?case
 924   proof-
 925     have "(r * (cos φ + \ * sin φ)) ^ Suc n = 
 926           (r * (cos φ + \ * sin φ)) ^ n * r * (cos φ + \ * sin φ)"
 927       by simp
 928     also have "... = r^n * (cos (n * φ) + \ * sin (n * φ)) * r * (cos φ + \ * sin φ)"
 929       using Suc
 930       by simp
 931     also have "... = r^(Suc n) * ((cos (n * φ) * cos φ - sin (n * φ) * sin φ) + \ * (sin(n * φ) * cos φ + cos (n * φ) * sin φ))"
 932       by (simp add: algebra_simps)
 933       also have "... = r^(Suc n) * (cos (n * φ + φ) + \ * sin (n * φ + φ))"
 934       thm cos_add
 935       thm sin_add
 936     using cos_add[of "n * φ" φ, symmetric] sin_add[of "n * φ" φ, symmetric]
 937     by simp
 938     finally
 939     show ?thesis
 940       by (simp add: algebra_simps)
 941   qed
 942 qed
 943 
 944 end