1 theory Cas14_vezbe_resenja
   2   imports Complex_Main "HOL-Library.Code_Target_Nat" "HOL-Library.Multiset"
   3 
   4 begin
   5 
   6 section Aksiomatsko zasnivanje teorija, korišćenje lokala
   7 
   8 text Aksiomatsko rezonovanje, koje smo navikli da viđamo u matematici, ima
   9 svoje primene i u verifikaciji softvera. Jedan deo formalne semantike
  10 programskih jezika se obrađuje aksiomatskim pristupom. Pod ovim se podrazumeva
  11 definisanje svojstava funkcije, odnosno \emph{dovoljnih uslova} koje funkcija
  12 treba da ispunjava i nezavisno dokazivanje teorema koje opisuju ta svojstva uz
  13 pomoć interaktivnih i automatskih dokazivača teorema.
  14 
  15 text U ovom poglavlju ćemo prikazati primenu aksiomatskog metoda u razvoju
  16 formalno verifikovanog softvera. Korektnost sofvera je lakše dokazati ako se
  17 razvija korak po korak, umesto odjednom. Prvo kreiramo specifikaciju programa i
  18 program koji neke detalje ostavlja nerazrešenim i ostavljamo njihovu
  19 implementaciju za kasnije dok ne dođemo do konačne izvršive verzije.
  20 
  21 Ovaj pristup se naziva razvoj softvera profinjavanjem \emph{eng: refinement}
  22 (izučava se od 70-tih godina), i nije ograničen na formalno verifikovanje
  23 softvera. Krećemo od glavne funkcije na veoma apstraktnom nivou i specifikujemo
  24 sve više i više detalja softvera dok ne dođemo do konačne verzije.
  25 
  26 Pogledaćemo kako izgleda ovaj pristup na primeru implementacije funkcije
  27 sortiranja objedinjavanjem koji je obrađen u materijalu iz (pretprošlog)
  28 poglavlja \ref{rekurzija}.
  29 
  30 subsection Sortiranje objedinjavanjem
  31 
  32 text Ponovimo prvo definiciju funkciju objedinjavanja dve sortirane liste, i
  33 svojstva koja ta funkcija mora da zadovoljava:
  34 
  35 fun spoji :: "nat list ⇒ nat list ⇒ nat list" where
  36 "spoji [] ys = ys" | 
  37 "spoji xs [] = xs" | 
  38 "spoji (x # xs) (y # ys) = 
  39     (if x ≤ y then
  40         x # spoji xs (y # ys)
  41      else
  42         y # spoji (x # xs) ys)"
  43 
  44 value "spoji [2, 5, 8, 13] [1, 3, 9, 34, 40]"
  45 
  46 textPonavljamo dokaze da su multiskup i skup očuvani, kao i da je rezultujuća
  47 lista sortirana. Pošto smo prve dve leme dodali u simplifikator, treća lema
  48 prolazi automatski.
  49 
  50 lemma mset_spoji[simp]:
  51   shows "mset (spoji xs ys) = mset xs + mset ys"
  52   by (induction xs ys rule: spoji.induct, auto)
  53 
  54 lemma set_spoji[simp]:
  55   shows "set (spoji xs ys) = set xs ∪ set ys"
  56   by (induction xs ys rule: spoji.induct, auto)
  57   
  58 lemma sorted_spoji [simp]:
  59   assumes "sorted xs" "sorted ys"
  60   shows "sorted (spoji xs ys)"
  61   using assms
  62   by (induction xs ys rule: spoji.induct) auto
  63 
  64 textPrilikom implementacije sortiranja objedinjavanjem koristiće se ova
  65 funkcija. Međutim, u funkciji sortiranja prvi korak je deljenje liste na dva
  66 dela, nakon čega sledi rekurzivno sortiranje ta dva dela i nakon toga sledi
  67 objedinjavanje funkcijom koja spaja dve sortirane liste.
  68 
  69 Zbog efikasnosti koda, ta dva dela liste bi trebala da budu jednake dužine. Ali,
  70 primetimo da je ova pretpostavka o dužinama ta dva dela liste vezana samo za
  71 efikasnost sortiranja ali ne i za korektnost funkcije sortiranja.
  72 
  73 Sada je na redu korak u kome treba da implementiramo neki algoritam deljenja
  74 originalne liste na dve liste. Postoji više načina kako to možemo da uradimo:
  75 npr. prva polovina liste i druga polovina liste, ili elementi na neparnim i
  76 elementi na parnim pozicijama i slično. Međutim, ispostavlja se da pitanje
  77 deljenja liste na dve liste, odnosno sam izbor algoritma za deljenje na dve
  78 liste možemo ostaviti za kasnije. Za sada je potrebno da primetimo da je
  79 neophodno da algoritam deljenja liste ima naredne dve osobine:
  80 
  81  korektnost - da je podela na dve liste urađena tako da su tačno svi elementi
  82 liste raspoređeni u njih i,
  83 
  84  zaustavljanje - da su obe nove liste kraće od polazne liste.
  85 
  86 textOve osobine deljenja liste ćemo nadalje nazivati aksiome.
  87 
  88 Pre nego što preciziramo algoritam deljenja, možemo dokazati malo jači oblik
  89 funkcije sortiranja objedinjavanjem. Dokazaćemo korektnost funkcije
  90 objedinjavanja u odnosu na apstraktnu funkciju podele liste na dva dela.
  91 Funkciju podele na dve liste ćemo zadati apstraktno pomoću njene specifikacije.
  92 
  93 Koristimo nov koncept \emph{lokala} (engl. locale) - to je skup konstanti,
  94 odnosno skup pojedinačnih elemenata nekog tipa ili funkcije. Prilikom zadavanja
  95 lokala, prvo se fiksiraju određeni elementi nakon čega se navode njihove osobine
  96 kroz navođenje nekih aksioma. U narednom lokalu ćemo fiksirati funkciju
  97 \emph{split} (ključnom rečju \verb!fixes!) koja od date liste pravi uređeni par
  98 listi. Nakon ovoga zadajemo aksiome (ključnom rečju \verb!assumes!) koje moraju
  99 da važe da bi algoritam sortiranja objedinjavanjem koji koristi ovu funkciju
 100 \emph{split} mogao da se isprogramira. To su aksiome koje obezbeđuju korektnost
 101 algoritma i njegovo zaustavljanje.
 102 
 103 Umesto običnog univerzalnog kvantifikatora @{text ()}, implikacije @{text
 104 ()} i konjunkcije @{text ()} koristimo veznike meta-logike i Isabelle
 105 sintaksa zapisa @{text ()}, @{text ()} i @{text (, )}, zbog kasnijeg
 106 lakšeg instanciranja ovih aksioma.
 107 
 108 Pošto se lista deli na polovine samo ako ima više od jednog elementa, dovoljno
 109 je zahtevati da ove aksiome važe samo za takve liste, pa uslov da je dužina
 110 liste veća od 1 stavljamo u premise obe aksiome.
 111 
 112 Nakon navođenja aksioma, između ključnih reči \verb!begin! i \verb!end! navodi
 113 se blok koji sadrži lokalne definicije i teoreme i u kome smemo da koristimo
 114 aksiome koje su uvedene. Na ovom mestu se definiše algoritam sortiranja
 115 objedinjavanjem. Kako nam u algoritmu treba poređenje elemenata, da bismo
 116 pojednostavili primer zapisaćemo definiciju za liste prirodnih brojeva. Ova
 117 definicija i dokaz korektnosti je isti kao u prošlom poglavlju pa ga nećemo
 118 ponovo objašnjavati.
 119 
 120 
 121 locale MergeSort = 
 122  prvo se navode konstante
 123   fixes split :: "nat list ⇒ nat list × nat list"
 124  pa onda aksiome
 125   assumes split_length:
 126      "⋀ xs ys zs. ⟦length xs > 1; (ys, zs) = split xs⟧ ⟹ 
 127                      length ys < length xs ∧ length zs < length xs"
 128   assumes split_mset: 
 129      "⋀ xs ys zs. ⟦length xs > 1; (ys, zs) = split xs⟧ ⟹ 
 130                      mset xs = mset ys + mset zs"
 131 
 132  Između begin i end uvode se lokalne definicije i dokazuju se lokalna tvrđenja
 133 (u njima mogu da se koriste konstante i aksiome lokala). 
 134 
 135 begin
 136 
 137 function (sequential) mergesort :: "nat list ⇒ nat list" where
 138 "mergesort [] = []" | 
 139 "mergesort [x] = [x]" | 
 140 "mergesort xs = 
 141     (let (ys, zs) = split xs 
 142       in spoji (mergesort ys) (mergesort zs))"
 143   by pat_completeness auto
 144 termination
 145   apply (relation "measure (λ xs. length xs)")
 146     apply simp
 147    apply (metis One_nat_def in_measure length_Cons lessI linorder_not_less list.size(4) split_length trans_le_add2)
 148   apply (metis One_nat_def impossible_Cons in_measure linorder_not_less list.size(4) split_length trans_le_add2)
 149   done
 150 
 151 Unutar lokala ne možemo pozvati funkciju \emph{mergesort} jer funkcija
 152 \emph{split} nije definisana. Ali možemo pokazati da važe još neke osobine te
 153 funkcije: da se mset ne menja i da je rezultujuća lista sortirana:
 154 
 155 lemma mset_mergesort_auto:
 156   "mset (mergesort xs) = mset xs"
 157   apply (induction xs rule: mergesort.induct) 
 158   apply simp
 159    apply simp
 160     apply (auto split: prod.split)
 161    sledgehammer
 162   by (metis (mono_tags, hide_lams) One_nat_def Suc_eq_plus1 length_Cons 
 163   less_Suc_eq_0_disj mset.simps(2) mset_append split_mset zero_less_Suc)
 164 
 165 lemma mset_mergesort:
 166   "mset (mergesort xs) = mset xs"
 167 proof (induction xs rule: mergesort.induct) 
 168   case 1
 169   then show ?case
 170     by simp
 171 next
 172   case (2 x)
 173   then show ?case
 174     by simp
 175 next
 176   case (3 x0 x1 xs)
 177   then show ?case
 178     using split_mset[of "x0 # x1 # xs"]
 179     by (simp split: prod.split)
 180 qed
 181 
 182 lemma sorted_mergesort:
 183   "sorted (mergesort xs)"
 184   by (induction xs rule: mergesort.induct) (auto split: prod.split)
 185 end
 186 
 187 textDokazali smo da je funkcija mergesort korektna ako funkcija \verb!split!
 188 zadovoljava navedene aksiome koje su ekspliticno navedene u prethodnom lokalu.
 189 Primetimo da je ovo urađeno bez implementacije funkcije \verb!split!. U ovom
 190 trenutku imamo slobodu da razrešimo detalje te implementacije.
 191 
 192 Sada ćemo prikazati dve različite implementacije funkcije \verb!split!.
 193 
 194 subsubsection Razdvajanje uzimanjem prve i druge polovine niza
 195 
 196 textNaredna funkcija izdvaja, na osnovu dužine liste, prvu polovinu odnosno
 197 drugu polovinu liste.
 198 
 199 definition split_half :: "nat list ⇒ nat list × nat list" where
 200   "split_half xs = (let n = length xs div 2 in (take n xs, drop n xs))"  
 201 
 202 value "split_half [3::nat, 4, 8, 1, 2, 0, 5]"
 203 
 204 text Sada nam treba način da povežemo ovu konretnu implementaciju sa opštom
 205 implementacijom algoritma za sortiranje koji smo naveli uz pomoć lokala.
 206 
 207 Koristimo interpretaciju lokala i ključnu reč \verb!global_interpretation! nakon
 208 čega navodimo novo ime lokala, pa ime osnovnog lokala iz koga izvodimo novi
 209 lokal, ključnu reč \verb!where! i ime apstraktne funkcije (konstante lokala)
 210 koju sada zamenjujemo konkretnom funkcijom koju smo sada implementirali. Za tu
 211 konkretnu funkciju treba da dokažemo da važe aksiome koje su navedene u lokalu,
 212 odnosno treba da dokažemo da ovakva funkcija podele zadovoljava potrebna
 213 svojstva. Ovaj dokaz se navodi između \verb!proof! i \verb!qed! bloka, pri čemu
 214 su dokazi različitih aksioma razdvojeni ključnom rečju \verb!next!.
 215 
 216 Napomenimo da je red koji počinje sa ključnom rečju \verb!defines! neophodan da
 217 bi funkcija @{text mergesort_half} mogla da se izvršava. Nakon ključne reči se
 218 navodi ime funkcije (koje ćemo koristiti u nastavku), ime funkcije iz lokala i
 219 konkretnu funkciju za deljenje liste koju ćemo koristiti u ovoj interpretaciji.
 220 
 221 global_interpretation MergeSort_half: MergeSort where 
 222   split = "split_half"
 223    Naredni red je potrebno navesti da bi funkcija mergesort mogla da se izvršava
 224   defines mergesort_half = "MergeSort.mergesort split_half"
 225 proof
 226   fix xs ys zs :: "nat list"
 227   assume "length xs > 1" "(ys, zs) = split_half xs"
 228   then show "length ys < length xs ∧ length zs < length xs"
 229     unfolding split_half_def Let_def
 230     by auto
 231 next
 232   fix xs ys zs :: "nat list"
 233   assume "length xs > 1" "(ys, zs) = split_half xs"
 234   then show "mset xs = mset ys + mset zs"
 235     unfolding split_half_def Let_def
 236      sledgehammer
 237     by (simp add: union_code)
 238 qed
 239 
 240 textSada možemo pozvati ovako intepretiranu funkciju:
 241 
 242 value "mergesort_half [3, 8, 4, 2, 1]"
 243 
 244 textAli imamo i dve teoreme dobijene u ovom lokalu. Jedna teorema koja tvrdi da
 245 zaista ova kombinacija sortira listu i druga koja tvrdi da je multiskup
 246 elemenata nepromenjen.
 247 
 248 thm "MergeSort_half.mset_mergesort"
 249 thm "MergeSort_half.sorted_mergesort"
 250 
 251 textOvako interpretirana funkcija može da se eksportuje u neki drugi programski
 252 jezik:
 253 
 254 export_code mergesort_half in Haskell
 255 
 256 textOvde ponovo možemo da primetimo problem sa brzinom izvršavanja ovakvog koda
 257 zbog načina na koji su implementirani prirodni brojevi i gubi se puno vremena na
 258 poređenje prirodnih brojeva (koji su predstavljeni preko Suc). Tako da je u
 259 situacijama kada želimo da eksportujemo kod potrebno uključiti na početku fajla
 260 teoriju \verb!Code_Target_Nat!.
 261 
 262 value "length (mergesort_half [0..<4000])"
 263 
 264 subsubsection Razdvajanje naizmeničnim uzimanjem elemenata
 265 
 266 textPokazaćemo kako izgleda interpretacija ovog istog lokala sa drugom
 267 funkcijom za deljenje na dve liste, kada uzimamo elemente naizmenično. Funkciju
 268 ćemo nazvati \verb!split_zigzag!, definisaćemo je rekurzijom i dokazi će
 269 koristiti indukciju po pravilu \verb!split_zigzag.induct!.
 270 
 271 fun split_zigzag :: "nat list ⇒ nat list × nat list" where
 272 "split_zigzag [] = ([], [])" | 
 273 "split_zigzag [x] = ([x], [])" | 
 274 "split_zigzag (x0 # x1 # xs) = 
 275       (let (ys, zs) = split_zigzag xs 
 276         in (x0 # ys, x1 # zs))"
 277 
 278 value "split_zigzag [3::nat, 2, 8, 4, 1, 5, 6]"
 279 
 280 global_interpretation MergeSort_zigzag: MergeSort 
 281   where split = "split_zigzag"
 282    Naredni red je potrebno navesti da bi funkcija @{text mergesort_zigzag} mogla da se izvršava
 283   defines mergesort_zigzag = "MergeSort.mergesort split_zigzag"
 284 proof
 285   fix xs ys zs :: "nat list"
 286   assume "length xs > 1" "(ys, zs) = split_zigzag xs"
 287   then show "length ys < length xs ∧ length zs < length xs"
 288   proof (induction xs arbitrary: ys zs rule: split_zigzag.induct)
 289     case 1
 290     then show ?case
 291       by simp
 292   next
 293     case (2 x)
 294     then show ?case
 295       by simp
 296   next
 297     case (3 x0 x1 xs)
 298     show ?case
 299     proof (cases "xs = []")
 300       case True
 301       thus ?thesis
 302         using 3(3)
 303         by simp
 304     next
 305       case False
 306       show ?thesis
 307       proof (cases "length xs = 1")
 308         case True
 309         then obtain x where "xs = [x]"
 310           by (metis One_nat_def length_0_conv length_Suc_conv)
 311         thus ?thesis
 312           using 3(3)
 313           by simp
 314       next
 315         case False
 316         then have "length xs > 1"
 317           using `xs ≠ []`
 318           using not_less_iff_gr_or_eq by auto
 319         then obtain ys' zs' where *: "(ys', zs') = split_zigzag xs"
 320           by (metis surj_pair)
 321         then have **: "ys = x0 # ys'" "zs = x1 # zs'"
 322           using 3(3)
 323           by (metis Pair_inject prod.simps(2) split_zigzag.simps(3))+
 324         then have "length ys' < length xs ∧ length zs' < length xs"
 325           using * 3(1) `length xs > 1`
 326           by simp
 327         then show ?thesis
 328           using **
 329           by simp
 330       qed
 331     qed
 332   qed
 333 next
 334   fix xs ys zs :: "nat list"
 335   assume "(ys, zs) = split_zigzag xs"
 336   then show "mset xs = mset ys + mset zs"
 337     by (induction xs arbitrary: ys zs rule: split_zigzag.induct)
 338        (auto split: prod.split_asm)
 339 qed
 340 
 341 textOvako interpretirana funkcija se sada može pozvati:
 342 
 343 value "mergesort_zigzag [3, 8, 1, 4, 2, 5, 6]"
 344 
 345 textI opet imamo dve teoreme koje tvrde da ova funkcija zaista sortira listu i
 346 da je multiskup elemenata nepromenjen:
 347 
 348 thm "MergeSort_zigzag.mset_mergesort"
 349 thm "MergeSort_zigzag.sorted_mergesort"
 350 
 351 subsectionApstrakcija topološkog prostora
 352 
 353 textSličan pristup, uvođenje apstraktnog modela, dokazivanje određenih
 354 svojstava i naknadno instanciranje se primenjuje i u matematici. Na taj način
 355 možemo izbeći ponavljanje dokaza određenih osobina sličnih struktura.
 356 Detaljnije, ovim postižemo da uvođenjem odgovarajućih apstrakcija i dokazivanjem
 357 teorema u apstraktnom obliku, dobijamo opciju da upotrebimo konkretne instance
 358 dokazanih teorema na strukturama za koje je dokazano da zadovoljavaju osobine
 359 odgovarajuće apstrakcije.
 360 
 361 Na primer, umesto da se zajedničke teoreme dokažu prvo za polje realnih, a zatim
 362 za polje kompleksnih brojeva, teoreme se mogu dokazati na apstraktnom nivou, za
 363 sva polja. Nakon toga, pošto pokažemo da, na primer, realni brojevi čine polje u
 364 odnosu na odgovarajuće operacije, sve teoreme dokazane za polja važiće i u
 365 odgovarajućoj strukturi realnih brojeva.
 366 
 367 textIlustrujmo ovaj postupak uvođenjem apstrakcije topološkog
 368 prostora.\footnote{Jedna odlična, veoma lako čitljiva knjiga o topologiji: @{url
 369 http://www.topologywithouttears.net/topbook.pdf}.}\footnote{Malo kraći
 370 materijal o topološkim prostorima može se naći na: @{url
 371 https://www.dmi.uns.ac.rs/site/dmi/download/master/primenjena_matematika/MilijanaMilovanovic.pdf}}
 372 
 373 \emph{Topološki prostor} (na nekom skupu X) je par @{text (X,τ)}, gde X
 374 predstavlja dati skup, a @{text τ} predstavlja familiju podskupova skupa X.
 375 Podskupove koji pripadaju familiji @{text τ} nazvaćemo otvorenim podskupovima.
 376 Ova familija treba da zadovoljava sledeće uslove:
 377 
 378   Prazan skup i ceo skup X moraju biti otvoreni skupovi 
 379  aksiome @{text empty} i @{text univ}
 380 
 381   Unija proizvoljnog broja otvorenih skupova je otvoren skup 
 382  aksioma @{text union}
 383 
 384   Presek dva otvorena skupa je otvoren skup  aksioma @{text inter}
 385 
 386 Pored ove četiri aksiome potrebno je eksplicitno navesti da elementi skupa
 387 @{text τ} moraju biti podskupovi skupa X (obrnuto neće važiti), i to tvrđenje
 388 ćemo predstaviti u narednom lokalu aksiomom sa imenom @{text subsets}.
 389 Napomenimo još sintaksu koju ćemo koristiti. Skup S je element skupa @{text τ}
 390 pišemo uobičajeno @{text S  τ}. Zanimljivo je to da proizvoljan broj
 391 otvorenih skupova u stvari predstavlja podskup skupa @{text τ}, pa ćemo
 392 rečenicu tipa skup @{text τ'} sadrži proizvoljan broj otvorenih skupova
 393 jednostavno zapisivati sa @{text τ'  τ}. A uniju nad tim skupom, odnosno
 394 uniju proizvoljnog broja otvorenih skupova ćemo zapisati sa @{text  τ'}.
 395 
 396 Formalizacija ovoj pojma vrši se kroz koncept lokala. Lokal uvodi određeni broj
 397 konstanti/funkcija (koje se kasnije konkretizuju) i aksioma koje te
 398 konstante/funkcije moraju da zadovolje. Svaki topološki prostor fiksira
 399 konstantu X (skup nosilac) i konstantu @{text τ} (skup svih otvorenih
 400 podskupova).
 401 
 402 Ovako definisana familija @{text τ} se naziva i \emph{topologija} nad skupom X.
 403 
 404 Može se pokazati da je familija @{text τ} zatvorena u odnosu na konačne
 405 preseke. Ovo tvrđenje ćemo nezavisno formulisati i dokazati kao lemu u narednom
 406 lokalu (lema @{text inter_finite}). Da bi smo proverili da li je skup konačan
 407 koristićemo funkciju @{text finite :: 'a set  bool} koja vraća vrednost
 408 @{text True} ako je njen argument konačan. Dokaz te leme će se izvoditi
 409 indukcijom nad konačnim skupom @{text τ'}. Pravilo indukcije na koje se
 410 pozivamo se u ovom slučaju naziva @{text finite.induct:} @{thm[mode=Proof]
 411 finite.induct [no_vars]} i ovako se zapisuje u Isabelle-u. U dokazu ćemo
 412 razlikovati slučaj praznog skupa i slučaj nepraznog skupa (koji se dobija
 413 ubacivanjem elementa u skup funkcijom @{text insert :: 'a  'a set  'a set}).
 414 
 415 Pored pojma otvorenog skupa, koji smo definisali kao elemente familije @{text
 416 τ}, uvodimo i pojam \emph{zatvorenog skupa} - skup je zatvoren ako i samo ako
 417 je njegov komplement u odnosu na skup X otvoren skup. Ova dva pojma ćemo uvesti
 418 pojedinačno u narednom lokalu.
 419 
 420 Primetimo da se na sličan način može definisati i topologija uz pomoć zatvorenih
 421 skupova. To možemo i dokazati na osnovu već navedenih aksioma za otvorene
 422 skupove i de Morganovih zakona. Tako da ćemo formulisati (i dokazati) dualne
 423 teoreme za zatvorene skupove: prazan skup i ceo prostor su zatvoreni skupovi
 424 (leme @{text closed_empty} i @{text closed_univ}), presek dva zatvorena
 425 skupa je zatvoren skup (lema @{text closed_inter}), presek konačno mnogo
 426 zatvorenih skupova je zatvoren skup (lema @{text closed_inter_finite}) i unija
 427 konačno mnogo zatvorenih skupova je zatvoren skup (lema @{text
 428 closed_union_finite}). 
 429 
 430 locale topological_space =
 431    konstante
 432   fixes X :: "'a set"   skup nosilac
 433   fixes τ :: "'a set set"  kolekcija otvorenih skupova
 434 
 435    aksiome
 436   assumes subsets: "⋀ S. S ∈ τ ⟹ S ⊆ X"
 437   assumes univ: "X ∈ τ"
 438   assumes empty: "{} ∈ τ"
 439   assumes inter: "⋀ S1 S2. ⟦S1 ∈ τ; S2 ∈ τ⟧ ⟹ S1 ∩ S2 ∈ τ"
 440   assumes union: "⋀ τ'. ⟦τ' ≠ {}; τ' ⊆ τ⟧ ⟹ ⋃ τ' ∈ τ"
 441 begin
 442 
 443  Skup je otvoren ako i samo ako pripada @{text τ}.
 444 abbreviation open_set :: "'a set ⇒ bool" where
 445   "open_set S ≡ S ∈ τ"
 446 
 447  U narednom dokazu ćemo koristiti pravilo indukcije nad konačnim skupom.
 448 term finite
 449 thm finite.induct
 450 
 451  Dokazujemo da je presek konačno mnogo otvorenih skupova otvoren skup:
 452 lemma inter_finite:
 453   assumes "finite τ'" "τ' ≠ {}" "∀ S ∈ τ'. open_set S"
 454   shows "open_set (⋂ τ')"
 455   using assms
 456 proof (induction τ' rule: finite.induct)
 457   case emptyI
 458   then show ?case
 459     by simp
 460 next
 461   case (insertI A a)
 462   thm insertI  obratite pažnju na to kako izgleda korak indukcije u ovakvom dokazu
 463   term insert  funkcija koja ubacuje element u skup
 464   show ?case
 465   proof (cases "A = {}")
 466     case True
 467     then show ?thesis
 468       using insertI
 469       by simp
 470   next
 471     case False
 472     then show ?thesis
 473       using insertI inter  pozivamo se na induktivnu pretpostavku i aksiomu inter
 474       by simp
 475   qed
 476 qed
 477 
 478  Skup je zatvoren ako i samo ako mu je komplement (u odnosu na X) otvoren:
 479 definition closed_set :: "'a set ⇒ bool" where
 480   "closed_set S ⟷ open_set (X - S)"
 481 
 482  Zatvoreni skupovi takođe definišu topologiju nad skupom X:
 483 lemma closed_empty:
 484   "closed_set {}"
 485   unfolding closed_set_def
 486   using univ
 487   by simp
 488 
 489 lemma closed_univ:
 490   "closed_set X"
 491   unfolding closed_set_def
 492   using empty
 493   by simp
 494 
 495 lemma closed_inter:
 496   assumes "closed_set S1" "closed_set S2"
 497   shows "closed_set (S1 ∩ S2)"
 498   using assms union[of "{X - S1, X - S2}"]
 499   unfolding closed_set_def
 500   by (simp add: Diff_Int)
 501 
 502 lemma closed_inter_finite:
 503   assumes "finite τ'" "τ' ≠ {}" "∀ S ∈ τ'. closed_set S"
 504   shows "closed_set (⋂ τ')"
 505 proof-
 506   have "X - (⋂ τ') = ⋃ {X - S | S . S ∈ τ'}"
 507     using assms
 508     by auto
 509   thus ?thesis
 510     using assms
 511     unfolding closed_set_def
 512     using union[of "{X - S |S. S ∈ τ'}"]
 513     by auto
 514 qed
 515 
 516 lemma closed_union_finite:
 517   assumes "finite τ'" "τ' ≠ {}" "∀ S ∈ τ'. closed_set S"
 518   shows "closed_set (⋃ τ')"
 519 proof-
 520   have "X - ⋃ τ' = ⋂ {X - S | S . S ∈ τ'}"
 521     using `τ' ≠ {}`
 522     by auto
 523   thus ?thesis
 524     using assms
 525     using inter_finite[of "{X - S | S. S ∈ τ'}"]
 526     unfolding closed_set_def
 527     by auto
 528 qed
 529 
 530 end
 531 
 532 subsubsection Ograničen skup prirodnih brojeva
 533 
 534 text U nastavku je dat jedan (prilično veštački) primer topološkog prostora:
 535 
 536 definition X_ex1 :: "nat set" where
 537   "X_ex1 = {0::nat, 1, 2, 3, 4, 5}" 
 538 
 539 definition τ_ex1 :: "nat set set" where
 540   "τ_ex1 = {{0::nat, 1, 2, 3, 4, 5}, {}, {0}, {2, 3}, {0, 2, 3}, {1, 2, 3, 4, 5}}"
 541 
 542 text Komandom \verb!global_interpretation! dokazujemo da neke konkretne
 543 konstante interpretiraju ranije uvedenu apstrakciju. Odnosno, treba da pokažemo
 544 (da ih formalno dokažemo) da važe aksiome koje smo naveli u lokalu.
 545 
 546 declare [[quick_and_dirty=true]]
 547 
 548 global_interpretation topological_space where
 549   X = "X_ex1" and
 550   τ = "τ_ex1"
 551 proof
 552   fix S
 553   assume "S ∈ τ_ex1"
 554   thus "S ⊆ X_ex1"
 555     unfolding τ_ex1_def X_ex1_def
 556     by auto
 557 next
 558   show "X_ex1 ∈ τ_ex1" "{} ∈ τ_ex1"
 559     unfolding X_ex1_def τ_ex1_def
 560     by auto
 561 next
 562   fix S1 S2
 563   assume "S1 ∈ τ_ex1" "S2 ∈ τ_ex1"
 564   thus "S1 ∩ S2 ∈ τ_ex1"
 565     unfolding τ_ex1_def
 566      ovi dokazi su krajnje neinteresantni, a ne mogu se dokazati automatski
 567     sorry
 568 next
 569   fix τ'
 570   assume "τ' ≠ {}" "τ' ⊆ τ_ex1" 
 571   thus "⋃ τ' ∈ τ_ex1"
 572     unfolding τ_ex1_def
 573      ovi dokazi su krajnje neinteresantni, a ne mogu se dokazati automatski
 574     sorry
 575 qed
 576 
 577 subsubsectionSkup realnih brojeva
 578 
 579 text Mnogo interesantniji primer topološkog prostora je skup realnih brojeva sa
 580 tzv. euklidskom topologijom.
 581 
 582 text Otvoreni interval (a, b) se zadaje na sledeći način:
 583 
 584 definition open_interval :: "real ⇒ real ⇒ real set" where
 585   "open_interval a b = {x. a < x ∧ x < b}"
 586 
 587 lemma open_interval_empty_iff:
 588   "open_interval a b = {} ⟷ a ≥ b"
 589   unfolding open_interval_def
 590   by (metis (no_types, lifting) dense_le dual_order.strict_implies_order
 591   empty_Collect_eq leD le_less_linear order.strict_trans1)
 592 
 593 text Nakon ovoga ćemo definisati otvoren skup - skup je otvoren ako i samo ako
 594 se svaka njegova tačka može okružiti nekim otvorenim intervalom koji ceo pripada
 595 tom skupu.
 596 
 597 definition is_real_open_set where 
 598   "is_real_open_set S ⟷ 
 599       (∀ x ∈ S. ∃ a b. x ∈ open_interval a b ∧ open_interval a b ⊆ S)"
 600 
 601 text Dokazujemo da skup realnih brojeva sa ovako uvedenom definicijom otvorenog
 602 skupa zaista predstavlja jedan topološki prostor. 
 603 
 604 U narednoj interpretaciji se koristi UNIV - skup svih elemenata nekog tipa.
 605 
 606 global_interpretation Euclidean_topology: topological_space where
 607  X = "UNIV :: real set"  and
 608  τ = "{S. is_real_open_set S}"
 609 proof
 610   fix S
 611   assume "S ∈ {S. is_real_open_set S}"
 612   then show "S ⊆ UNIV"
 613     by simp
 614 next
 615   have "∀ x. ∃ a b. x ∈ open_interval a b"
 616   proof-
 617     have "∀ x. x ∈ open_interval (x - 1) (x + 1)"
 618       unfolding open_interval_def
 619       by simp
 620     then show ?thesis
 621       by auto
 622   qed
 623   then show "UNIV ∈ {S. is_real_open_set S}"
 624     unfolding is_real_open_set_def
 625     by auto
 626 next
 627   show "{} ∈ {S. is_real_open_set S}"
 628     unfolding is_real_open_set_def
 629     by simp
 630 next
 631   fix τ'
 632   assume *: "τ' ⊆ {S. is_real_open_set S}"
 633   show "⋃ τ' ∈ {S. is_real_open_set S}"
 634   proof
 635     show "is_real_open_set (⋃ τ')"
 636       unfolding is_real_open_set_def
 637     proof
 638       fix x
 639       assume "x ∈ ⋃ τ'"
 640       then obtain S where "S ∈ τ'" "x ∈ S"
 641         by auto
 642       hence "is_real_open_set S"
 643         using *
 644         by auto
 645       then obtain a b where "x ∈ open_interval a b" "open_interval a b ⊆ S"
 646         using `x ∈ S`
 647         unfolding is_real_open_set_def
 648         by auto
 649       thus "∃a b. x ∈ open_interval a b ∧ open_interval a b ⊆ ⋃ τ'"
 650         using `S ∈ τ'`
 651         by auto
 652     qed
 653   qed
 654 next
 655   fix S1 S2
 656   assume *: "S1 ∈ {S. is_real_open_set S}" "S2 ∈ {S. is_real_open_set S}"
 657   show "S1 ∩ S2 ∈ {S. is_real_open_set S}"
 658   proof
 659     show "is_real_open_set (S1 ∩ S2)"
 660       unfolding is_real_open_set_def
 661     proof
 662       fix x
 663       assume "x ∈ S1 ∩ S2"
 664       then obtain a1 b1 a2 b2 where 
 665       **: "x ∈ open_interval a1 b1" "open_interval a1 b1 ⊆ S1"
 666           "x ∈ open_interval a2 b2" "open_interval a2 b2 ⊆ S2"
 667         using *
 668         unfolding is_real_open_set_def
 669         by blast
 670       let ?a = "max a1 a2" 
 671       let ?b = "min b1 b2"
 672       have "x ∈ open_interval ?a ?b"
 673         using **
 674         unfolding open_interval_def
 675         by auto
 676       moreover
 677       have "open_interval ?a ?b ⊆ S1 ∩ S2"
 678         using **
 679         unfolding open_interval_def
 680         by auto
 681       ultimately
 682       show "∃a b. x ∈ open_interval a b ∧ open_interval a b ⊆ S1 ∩ S2"
 683         by auto
 684     qed
 685   qed
 686 qed
 687 
 688 text Kada smo dokazali da realni brojevi predstavljaju topološki prostor, na
 689 raspolaganju imamo sve definicije i teoreme dokazane o topološkim prostorima.
 690 
 691 thm Euclidean_topology.closed_set_def
 692 thm Euclidean_topology.closed_inter
 693 thm Euclidean_topology.closed_union_finite
 694 
 695 lemma "Euclidean_topology.open_set A ⟷ is_real_open_set A"
 696   by simp
 697 
 698 
 699 end
 700