theory Indukcija_IV_cas (* imports Main *) (* Real numbers are not included by Main.thy. Theory Complex_Main.thy imports Main.thy together with many more theories containing, for example, all the basic properties of real and complex numbers. *) imports Complex_Main (* imports HOL.Real -- Samo realne, bez kompleksnih *) begin (* Pravilo indukcije koje zadovoljava uslov n\m *) thm nat_induct_at_least (* Zahvaljujuci ovom pravilu mozemo zapisati dokaze sa proslog casa tako da vise lice na dokaze u udzbeniku *) (* Zadatak 11 - pomocno tvrdjenje *) lemma n2_2np1_at_least: fixes n::nat assumes "n \ 3" shows "n^2 > 2*n + 1" using assms proof (induction n rule: nat_induct_at_least) (* bazni slucaj *) case base thus ?case by simp next case (Suc n) have "2 * (Suc n) + 1 < 2 * (Suc n) + 2 * n" using `n \ 3` by simp also have "... = 2 * n + 1 + 2 * n + 1" by simp also have "... < n^2 + 2 * n + 1" using Suc by simp also have "... = (Suc n)^2" by (simp add: power2_eq_square) finally show ?case . qed (* Primeri sa realnim brojevima *) (* 4. zadatak - Matematicka indukcija *) lemma fixes x::real and n::nat assumes "x > -1" shows "(1 + x)^n \ 1 + n * x" (* bez using assms da bi bili jednostavniji dokazi, pa cemo se pozivati na pretpostavku samo na onom mestu u dokazu gde cemo je eksplicitno koristiti *) proof (induction n) case 0 show ?case by simp next case (Suc n) show ?case proof- have "1 + (n + 1) * x \ 1 + (n + 1) * x + n * x^2" by simp also have "... = (1 + x) * (1 + n * x)" by (simp add: algebra_simps power2_eq_square) also have "... \ (1 + x) * (1 + x) ^ n" using Suc `x > -1` (* ovde se pozivamo na pretpostavku *) by simp also have "... = (1 + x) ^ (Suc n)" by simp finally show ?thesis by simp qed qed (* Zadatak 5 *) primrec zbir_naizmenicno:: "nat \ int" where "zbir_naizmenicno 0 = 0" | "zbir_naizmenicno (Suc n) = zbir_naizmenicno (n) + (-1)^(Suc n) * (2 * (Suc n) - 1)" (* eventualno int(Suc n) kada je potrebno eksplicitno prebaciti u int zbog oduzimanja *) (* nakon raspisivanja dokaza na papiru, vidimo da su nam potrebne neke teoreme odredjenog formata *) find_theorems "_ ^ Suc _" find_theorems " _ * ( _ + _ ) = _ * _ + _ * _ " thm int_distrib lemma zad5: "zbir_naizmenicno n = (-1)^n * n" proof (induction n) case 0 then show ?case by simp next case (Suc n) show ?case proof - have "zbir_naizmenicno (Suc n) = zbir_naizmenicno (n) + (-1)^(Suc n) * (2 * (Suc n) - 1)" by (simp only: zbir_naizmenicno.simps) also have "... = (-1)^n * n + (-1)^(n+1)*(2*(n+1)-1)" using Suc by simp also have "... = (-1)^n *(-1)*(-1)*n + (-1)^(n+1)*(2*n+1)" by simp also have "... = (-1)^(n+1)*(-1)*n + (-1)^(n+1)*(2*n+1)" by simp also have "... = (-1)^(n+1) * ((-1)*n + (2*n+1))" (* Naredni korak se moze dokazati na nekoliko nacina: (1) Eksplicitna naredba kojom kazemo Isabelle-u da unutar onoga sto dokazujemo (unutar cilja) pronadje unifikacijom levu stranu teoreme koju navodimo i zameni desnom stranom te teoreme. *) (* apply (subst int_distrib) apply simp *) (* Slicno bi pozvali i "apply (subst ime_teoreme[symmetric])" gde se izdaje naredba da se unutar cilja pronadje desna strana navedene teoreme i da se zameni levom. *) (* (2) *) (* by (subst int_distrib, simp)*) (* (3) Koriscenje simp add ne ubacuje teoremu u pretpostavke, vec je da simplifikatoru kao rewrite pravilo, sto znaci da se ona ne simplifikuje pre primene. *) (* by (simp add: int_distrib)*) (* (4) Koriscenje using ubacuje teoremu u svoje pretpostavke i onda se simplifikator primenjuje i na nju *) using int_distrib by simp also have "... = (-1)^(n+1) * (n+1)" by simp finally show ?thesis by simp qed qed (* Neke teoreme vezane za deljivost *) find_theorems "_ dvd _" find_theorems "_ dvd _ * _" find_theorems "_ dvd _ + _" find_theorems "_ \ _ dvd _ + _" thm nat_induct thm dvd_def thm dvd_add thm dvd_refl find_theorems "_ ^ _" thm power_0 thm power_one_right (* Zadatak 9 *) (* mora biti naglaseno da je n tipa nat. Mozemo to zapisati na dva nacina: lemma deljivost_sa_6 : shows "6 dvd (n::nat)*(n+1)*(2*n+1)" *) lemma deljivost_sa_6: fixes n :: nat shows "6 dvd n*(n+1)*(2*n+1)" (* koriscenje naredne naredbe moze da otkrije potrebu za uvodjenjem tipova u teoremi using [[show_types]] nakon utvrdjivanja tipova, naredba moze da se obrise. *) proof (induction n) case 0 then show ?case by simp (* apply simp --- ispisuje sta dobije, ovu naredbu mozete pozvati bilo gde*) next case (Suc n) then show ?case proof - have "Suc n * (Suc n + 1) * (2 * Suc n + 1) = (n+1)*(n+2)*(2*n+3)" by (simp add: algebra_simps) also have "... = n*(n+1)*(2*n+3) + 2*(n+1)*(2*n+3)" by (simp add: algebra_simps) also have "... = n*(n+1)*(2*n+1) + 2*n*(n+1) + 2*(n+1)*(2*n+3)" by (simp add: algebra_simps) also have "... = n*(n+1)*(2*n+1) + 2*(n+1)*(3*n+3)" by (simp add: algebra_simps) also have "... = n*(n+1)*(2*n+1) + 6*(n+1)*(n+1)" by (simp add: algebra_simps) (* sledgehammer --- mozete pokusati kada nemate ideju kako dalje dokazati *) finally show ?thesis using Suc thm One_nat_def (* using [[simp_trace]] by simp --- mozete pokrenuti i ovako da bi se videlo sta je tacno primenjivano tokom simplifikacije. Ako krene pogresnim putem onda se moze obrisati teorema koja u stvari nije potrebna za ispravan dokaz. *) by (simp del: One_nat_def) (* drugi nacin: imenujemo izvedenu jednakost da bi se dobio oblik primeren za primenu dvd_add finally have *: "Suc n * (Suc n + 1) * (2 * Suc n + 1) = n*(n+1)*(2*n+1) + 6*(n+1)*(n+1)" . show ?thesis using Suc by (subst *, rule dvd_add, simp) --- ovde je prikazana kombinacija vise metoda koji se nalaze u zagradi iza by, primenjuju se redom jedan po jedan. Metode mozete primeniti i pomocu apply i tada se vidi sta se dobilo primenom metoda --- detaljnije: Cilj je oblika 6 dvd izraz1. Pre toga je dokazana jednakost izraz1 = izraz2 + izraz3 i nazvali smo je *. Kada se primeni metod subst * cilj postaje 6 dvd izraz1 + izraz2 (subst u cilju menja levu stranu date jednakosti desnom stranom). Nakon toga primenjujemo metod rule dvd_add. Metod rule cilj unifikuje sa desnom stranom date teoreme, unifikujuci pri tom premise teoreme sa premisama u trenutnom cilju. Sve premise koje nisu na taj nacin pronadjene postaju novi ciljevi koje je potrebno dokazati. U nasem primeru dvd_add ima dve premise. Jedna se uspesno unifikuje sa nasim Suc i ona je time automatski dokazana, a druga postaje novi cilj koji treba dokazati. Taj cilj je trivijalan i simp ga automatski dokazuje.  *) qed qed (* Zadatak 10 *) lemma deljivost_sa_3: fixes n :: nat shows "(3::nat) dvd 5^n + 2^(n+1)" (* using [[show_types]] *) proof (induct n) case 0 thus ?case (* sledgehammer daje slicno resenje *) (* Naredba apply simp sugerise da je potrebno koristiti pravilo narednog tipa *) (* apply simp find_theorems "3 = _" thm numeral_3_eq_3 *) by (simp add: numeral_3_eq_3) next case (Suc n) (* Konvertovanje je neophodno kada iz konteksta nije moguce zakljuciti tip. Operator ^ je polimorfan i primenjuje se na objekte razlicitih tipova. U situaciji kada ne prolazi dokaz koji deluje da bi trebalo da prodje automatski moguce je da tipovi nisu u redu i da se moraju precizirati. *) have "(5::nat) ^ Suc n + 2 ^ (Suc n + 1) = 5 * 5 ^ n + 2 * 2 ^ (n + 1)" using[[show_types]] (* pokrenite ovu naredbu bez ::nat u prethodnom redu *) by simp also have "... = 3 * 5 ^ n + 2 * (5 ^ n + 2 ^ (n + 1))" by simp finally show ?case (* ispis teorema koje se koriste thm Suc thm dvd_triv_left thm dvd_mult thm dvd_add *) using dvd_add[OF dvd_triv_left[of "3::nat" "5^n"] dvd_mult[OF Suc, of 2]] by simp (* dvd_triv_left[of...] sluzi da instanciramo promenljive dvd_mult[OF Suc, of 2] omogucava da istovremeno zadamo premisu i instanciramo jednu promenljivu. dvd_add[OF...] nam omogucava da zadamo premise teoreme dvd_add, to su dve cinjenice koje dobijamo uz pomoc teorema dvd_triv_left i dvd_mult. *) qed (* Funkcije za kastovanje izmedju razlicitih tipova se mogu naci narednim naredbama *) find_consts "nat \ int" find_consts "nat \ real" find_consts "real \ complex" (* Primer funkcije int. Tip i funkcija mogu imati isto ime. Ovde int predstavlja funkciju koja slika nat u int *) term "3::nat" term "int (3::nat)" term "int 3" (* @{term t} prints a well-typed term t. @{value t} evaluates a term t and prints its result *) value "int (3::nat)" term "3::nat" value "3::nat" thm Re_complex_of_real thm Im_complex_of_real thm complex_of_real_def (* 12 zadatak - Moavrova formula *) lemma fixes r \ :: real and n :: nat shows "(r * (cos \ + \ * sin \))^n = r^n * (cos (n * \) + \ * sin(n * \))" proof (induction n) case 0 show ?case by simp next case (Suc n) show ?case proof- have "(r * (cos \ + \ * sin \)) ^ Suc n = (r * (cos \ + \ * sin \)) ^ n * r * (cos \ + \ * sin \)" by simp also have "... = r^n * (cos (n * \) + \ * sin (n * \)) * r * (cos \ + \ * sin \)" using Suc by simp also have "... = r^(Suc n) * ((cos (n * \) * cos \ - sin (n * \) * sin \) + \ * (sin(n * \) * cos \ + cos (n * \) * sin \))" by (simp add: algebra_simps) also have "... = r^(Suc n) * (cos (n * \ + \) + \ * sin (n * \ + \))" thm cos_add thm sin_add (* apply (subst cos_add[of "n * \" \, symmetric]) apply (subst sin_add[of "n * \" \, symmetric]) by simp *) using cos_add[of "n * \" \, symmetric] sin_add[of "n * \" \, symmetric] by simp finally show ?thesis by (simp add: algebra_simps) qed qed (* Princip jake indukcije Prvi je opstiji (radi za bilo koji wellfounded order), ali drugi je specificniji i zadovoljava nase potrebe *) thm less_induct thm nat_less_induct (* (⋀x. (⋀y. y < x ⟹ ?P y) ⟹ ?P x) ⟹ ?P ?a *) (* Zadatak 6 *) definition gm where "gm = (1 + sqrt 5) / 2" fun fib :: "nat \ nat" where "fib 0 = 0" | "fib (Suc 0) = 1" | "fib (Suc (Suc n)) = fib (Suc n) + fib n" lemma fibonaci: shows "fib (n + 1) \ gm ^ n" proof (induction n rule: nat_less_induct) case (1 n) thm 1 show ?case proof (cases "n = 0") case True thus ?thesis by simp next case False show ?thesis proof (cases "n = 1") case True have "fib 2 = 1" (* by eval --- drugi nacin uz pomoc metoda koji izracunava tu rekurzivnu funkciju *) by (simp add: numeral_2_eq_2) thus ?thesis using `n = 1` by (simp add: gm_def) next case False show ?thesis proof- obtain m where "m = n - 2" by auto have "n > 1" using `n \ 0` `n \ 1` by simp have "fib (m + 3) = fib (m + 2) + fib (m + 1)" by (simp add: numeral_3_eq_3) also have "... \ gm ^ (m + 1) + gm ^ m" (* modifikator [rule_format] od "\forall x. P x" pravi "P ?x" na koji onda mozemo dalje da primenimo of da bi ubacili vrednost za x. To se obicno koristi kada imamo premisu sa univerzalnim kvantifikatorom koju hocemo da instanciramo. *) using 1[rule_format, of "m+1"] 1[rule_format, of m] `m = n - 2` `n > 1` by force also have "... = gm ^ m * (gm + 1)" by (simp add: algebra_simps) also have "... = gm ^ m * (gm ^ 2)" (* drugi nacin: unfolding gm_def by (simp add: power2_eq_square algebra_simps) naredba unfolding prikazuje raspisanu definiciju *) by (simp add: power2_eq_square algebra_simps gm_def) also have "... = gm ^ (m + 2)" by (simp add: power_add power2_eq_square) finally show ?thesis using `m = n - 2` `n > 1` by (simp add: numeral_2_eq_2 Suc_diff_Suc) qed qed qed qed end