Úvod do Informatiky (IBOOO "Úv.Inf.") Doc. RNDr. Petr Hliněný, Ph.D. hlinenyOfi.muni.cz 19. prosince 2006 %m.^ Verze 0.95. Copyright © 2006-2006 Petr Hliněný. Obsah 1 Základní formalismy: Důkaz a Algoritmus 1 1.1 Úvod do matematického dokazování..................... 1 1.2 Struktura matematických vět a důkazů................... 2 1.3 Formální popis algoritmu........................... 4 2 Důkazové techniky, Indukce 5 2.1 Přehled základních důkazových technik................... 6 2.2 Věty typu „tehdy a jen tehdy"........................ 7 2.3 Matematická indukce............................. 8 2.4 Komentáře k matematické indukci...................... 10 3 Množiny, Relace a Funkce 12 3.1 Pojem množiny................................ 12 3.2 Množinové operace.............................. 13 3.3 Porovnávání a určení množin......................... 15 3.4 Relace a funkce mezi (nad) množinami................... 17 3.5 Posloupnosti a rekurentní vztahy ...................... 18 4 Binární relace, Ekvivalence 19 4.1 Reprezentace konečných relací........................ 20 4.2 Vlastnosti binárních relací.......................... 21 4.3 Relace ekvivalence .............................. 22 4.4 Rozklady a jejich vztah k ekvivalencím................... 23 5 Uspořádané množiny, Uzávěry 24 5.1 Uspořádané množiny............................. 24 5.2 Další pojmy uspořádaných množin ..................... 26 5.3 Hasseovské diagramy............................. 27 5.4 Uzávěry relací................................. 28 6 Vlastnosti funkcí a Skládání relací 29 6.1 Vlastnosti funkcí ............................... 29 6.2 Inverzní relace a skládání relací....................... 30 6.3 Skládání relací „v praxi"........................... 31 6.4 Skládání funkcí, permutace.......................... 33 6.5 Induktivní definice množin a funkcí..................... 34 7 Jemný úvod do Logiky 37 7.1 Výroky v „přirozené" podobě........................ 37 7.2 (Formální) výroková logika.......................... 38 7.3 Jak správně „znegovat formuli"?....................... 39 7.4 Predikátová logika, kvantifikace....................... 41 n 8 Dokazování vlastností algoritmů 43 8.1 O „správnosti" programů........................... 43 8.2 Jednoduché indukční dokazování....................... 43 8.3 Algoritmy pro relace............................. 45 8.4 Zajímavé algoritmy aritmetiky........................ 47 9 Jednoduchý deklarativní jazyk 48 9.1 Popis jednoduchého deklarativního jazyka................. 49 9.2 Formalizace pojmu „výpočet"........................ 50 9.3 Příklady výpočtů a důkazů.......................... 52 10 Důkazové postupy pro algoritmy 54 10.1 Technika „fixace parametru"......................... 54 10.2 Technika „indukce k součtu parametrů"................... 54 10.3 Technika „zesílení dokazovaného tvrzení".................. 56 10.4 Dva „klasické" algoritmy........................... 57 11 Nekonečné množiny a zastavení algoritmu 60 11.1 O kardinalitě a nekonečných množinách................... 60 11.2 Algoritmická neřešitelnost problému zastavení............... 62 12 Délka výpočtu algoritmu 63 12.1 O významu délky výpočtu algoritmu.................... 64 12.2 Asymptotické značení a odhady funkcí................... 64 m 1 Základní formalismy: Důkaz a Algoritmus Úvod Začněme nejprve několika obecnými poznámkami ke smyslu a směřování celého našeho předmětu: Jak sami poznáte, studium informatiky neznamená jen „naučit se nějaký programovací jazyk", nýbrž zahrnuje celý soubor dalších relevantních předmětů, mezi nimiž najdeme i matematicko-teoretické (formální) základy moderní informatiky. Právě odborný nadhled nad celou informatikou včetně nezbytné formální teorie nejspíše odliší řadového „programátora", kterých jsou dnes spousty i bez VS vzdělání, od skutečného (a mnohem lépe placeného) IT experta. A na tomto místě přichází náš předmět Úvod do Informatiky, který (i přes svůj nepříliš obsažný název) vás právě na studium těchto formálních základů moderní informatiky připraví. Cíle Prvním cílem této lekce je formálně rozebrat struktury matematických tvrzení (vět) a jejich formálních důkazů. V druhém sledu se naučíme obdobným způsobem formálně přesně zapisovat algoritmy. 1.1 Úvod do matematického dokazování Matematika (a tudíž i teoretická informatika jako její součást) se vyznačuje velmi přísnými formálními požadavky na korektnost argumentace. Takto korektně postavená argumentace vede od přijatých předpokladů v elementárních směrem k požadovanému závěru (a nikdy ne naopak!). Definice 1.1. Matematický důkaz . Uvažme matematickou větu (neboli tvrzení) tvaru „Jestliže platí předpoklady, pak platí závěr. Důkaz této věty je konečná posloupnost tvrzení, kde • každé tvrzení je bud * předpoklad, nebo * obecně přijatá „pravda" - axiom, nebo * plyne z předchozích a dříve dokázaných tvrzení podle nějakého „akceptovaného" logického principu - odvozovacího pravidla: • poslední tvrzení je závěr. Komentář: O potřebné úrovni formality matematických důkazů a o běžných důkazových technikách se dozvíme dále v této a příští lekci... Nyní si prostě celou problematiku uvedeme názornými příklady. Příklad 1.2. Uvažujme následující matematické tvrzení (které jistě už znáte). Věta. Jestliže x je součtem dvou lichých čísel, pak x je sudé. 1 Poznámka pro připomenutí: - Sudé číslo je celé číslo dělitelné 2, tj. tvaru 2k. - Liché číslo je celé číslo nedělitelné 2, tj. tvaru 2k + l. Důkaz postupuje v následujících formálních krocích: tvrzení zdůvodnění 1) a = 2k + 1, k celé předpoklad 2) b = 21 + 1, / celé předpoklad 3) x = a + b = 2k + 21 + 1 + 1 1,2) a komutativita sčítání (axiom) 4) x = 2{k + /) + 2 • 1 3) a distributivnost násobení 5) x = 2{k + / + 1) 4) a opět distributivnost násobení D Příklad 1.3. Dokažte následující tvrzení: Věta. Jestliže x a y jsou racionální čísla pro která platí x < y, pak existuje racionální číslo z pro které platí x < z < y. Důkaz po krocích (s již trochu méně formálním zápisem) zní: . Nechť z = ^=x + ^=y-^. • Číslo z je racionální, neboť x a y jsou racionální. . Platí z > x, neboť ^ > 0. • Dále platí z < y, opět neboť ^^ > 0. • Celkem x < z < y. n Poznámka. Alternativní formulace Věty z Příkladu 1.3 mohou znít: - Pro každé x, y € (Q, kde x < y, existuje z € (Q takové, že x < z < y. - Množina racionálních čísel je hustá. 1.2 Struktura matematických vět a důkazů První krok formálního důkazu je uvědomit si, co se má dokázat, tedy co je předpoklad a co závěr dokazovaného tvrzení. Komentář: Příklady formulace matematických vět: * Konečná množina má konečně mnoho podmnožin. * sin2(o;) +cos2(a) = 1. * Graf je rovinný jestliže neobsahuje podrozdělení K^ nebo K§*,. Často nám k lepšímu pochopení toho, co je třeba dokázat, pomůže pouhé rozepsání definic pojmů, které se v dané větě vyskytují. Jak „moc formální" mají důkazy vlastně být? 2 • Záleží na tom, komu je důkaz určen — „konzument" musí být schopen „snadno" ověřit korektnost každého tvrzení v důkazu a plně pochopit, z čeho vyplývá. • Je tedy hlavně na vás zvolit tu správnou úroveň formálnosti zápisu vět i důkazů podle situace. Konstruktivní a existenční důkazy Z hlediska praktické využitelnosti je potřeba rozlišit tyto dvě kategorie důkazů (třebaže z formálně-matematického pohledu mezi nimi kvalitativní rozdíl není). • Důkaz Věty 1.3 je konstruktivní Dokázali jsme nejen, že číslo z existuje, ale podali jsme také návod, jak ho pro dané x a y sestrojit. • Existenční důkaz je takový, kde se prokáže existence nějakého objektu bez toho, aby byl podán návod na jeho konstrukci. Příklad 1.4. čistě existenčního důkazu. Věta. Existuje program, který vypíše na obrazovku čísla tažená v 45. tahu sportky v roce 2006. Důkaz: Existuje pouze konečně mnoho možných výsledků losování 45. tahu sportky v roce 2006. Pro každý možný výsledek existuje program, který tento daný výsledek vypíše na obrazovku. Mezi těmito programy je tedy jistě ten, který vypíše právě ten výsledek, který bude v 25. tahu sportky v roce 2006 skutečně vylosován. D Komentář: To je ale „podvod", že? A přece není... Formálně správně to je prostě tak a tečka. Fakt. Pro informatické i další aplikované disciplíny je důležitá konstruktivnost důkazů vět, které se zde objevují. V matematice ale jsou mnohé příklady užitečných a nenahraditelných existenčních důkazů, třeba tzv. pravděpodobnostní důkazy. Příklad 1.5. „pravděpodobnostního" existenčního důkazu. Věta. Na dané množině bodů je zvoleno libovolně n2 podmnožin, každá o n prvcích. Dokažte pro dostatečně velká n, že všechny body lze obarvit dvěma barvami tak, aby žádná množina nebyla jednobarevná. Důkaz: U každého bodu si „hodíme mincí" a podle výsledku zvolíme barvu červeně nebo modře. (Nezávislé volby s pravděpodobností \.) Pravděpodobnost, že zvolených n bodů vyjde jednobarevných, je jen ^ = 21~n. Pro n2 podmnožin tak je pravděpodobnost, že některá z nich vyjde jednobarevná, shora ohraničená součtem 77 2l~n + ... + 2l~n =-----r-»O. --------------v--------------' 2n~l n2 Jelikož je toto číslo (pravděpodobnost) pro n > 7 menší než 1, bude existovat obarvení bez jednobarevných zvolených podmnožin. D 3 1.3 Formální popis algoritmu Položme si otázku, co je vlastně algoritmus? Když se na tím zamyslíte, asi zjistíte, že to není tak jednoduché přesně říci. Dokonce je to tolik obtížná otázka, že si zde podáme jen zjednodušenou odpověď. Poznámka: Za definici algoritmu je obecně přijímána tzv. Church-Turing ova teze tvrdící, že všechny algoritmy lze „simulovat" na Turingově stroji. Jedná se sice o přesnou, ale značně nepraktickou definici. Mimo Turingova stroje existují i jiné matematické modely výpočtů, jako třeba stroj RAM, který je abstrakcí skutečného strojového kódu. Konvence 1.6. Zjednodušeně zde algoritmem rozumíme konečnou posloupnost elementárních (výpočetních) kroků, ve které každý další krok využívá vstupní údaje či hodnoty vypočtené v předchozích krocích. Pro zpřehlednění a zkrácení zápisu algoritmu využíváme řídící konstrukce - podmíněná větvení a cykly. Komentář: Vidíte, jak blízké si jsou konstruktivní matematické důkazy a algoritmy (v našem pojetí)? Příklad 1.7. Zápis algoritmu pro výpočet průměru z daného pole a[] s n prvky. Algoritmus. • Inicializujeme sum <— 0 : • postupně pro i=0,l,2, . . . ,n-l provedeme * sum <— sum+a[i]: • vypíšeme podíl (sum/n) . D Ve „vyšší úrovni" formálnosti (s jasnějším vyznačením řídících struktur algoritmu) se totéž dá zapsat jako: Algoritmus 1.8. Průměr z daného pole a[] s n prvky. sum <— 0; for i<— 0,1,2,...,n-l do sum <— sum+a[i]; done res <— sum/n; output res; Značení. Pro potřeby symbolického formálního popisu algoritmů v předmětu IB000 si zavedeme následovnou konvenci: * Proměnné nebudeme deklarovat ani typovat, pole odlišíme závorkami p[]. * Přiřazení hodnoty zapisujeme a^ b, případně a:=b, ale nikdy ne a=b. * Jako elem. operace je možné použít jakékoliv aritmetické výrazy v běžném matematickém zápise. Rozsahem a přesností čísel se zde nezabýváme. * Podmíněné větvení uvedeme klíčovými slovy if ... then . . . else ... f i , kde else větev lze vynechat (a někdy, na jednom řádku, i f i). 4 * Pevný cyklus uvedeme klíčovými slovy for ... do ... done , kde část za for musí obsahovat předem danou množinu hodnot pro přiřazování do řídící proměnné. * Podmíněný cyklus uvedeme klíčovými slovy while ... do ... done . Zde se může za while vyskytovat jakákoliv logická podmínka. * V zápise používáme jasné odsazování (zleva) podle úrovně zanoření řídících struktur (což jsou if, for, while). * Pokud je to dostatečně jasné, elementární operace nebo podmínky můžeme i ve formálním zápise popsat běžným jazykem. Malé srovnání závěrem Jak to tedy je s vhodnou a únosnou mírou formalizace u matematických důkazů i u zápisu algoritmů? zcela formální běžná úroveň matematika algoritmy programováni formální rozepsání všech elem. kroků (Příklad 1.2) rozepsání všech elem. kroků ve výpočetním modelu asembler / strojový kód (kde se s ním dnes běžně setkáte?) strukturovaný a matem, přesný text v běžném jazyce strukturovaný rozpis kroků (Algoritmus 1.8), i s využitím běžného jazyka „vyšší" (strukturované) programovací jazyky, například Java Komentář: Pochopitelně se ve všech třech bodech obvykle držíme druhého přístupu, tedy běžné úrovně formality, pokud si specifické podmínky výslovně nevyžadují přístup nejvyšší formality... Rozšiřující studium 2 Důkazové techniky, Indukce Úvod IVa náš hlubší úvod do matematických formalismů pro informatiku pokračujeme základním přehledem technik matematických důkazů. Z nich pro nás asi nejdůležitější je technika důkazů matematickou indukcí, která je svou podstatou velmi blízká počítačovým programům (jako iterace cyklů). Cíle Cílem této lekce je popsat základní techniky matematických důkazů, z nichž největší důraz klademe na matematickou indukci. (Pro vysvětlení, z Lekce 1 víme, že matematický 5 důkaz má „jednotnou formu" Definice 1.1, ale nyní se věnujeme způsobům, jak takový korektní důkaz vlastně sestavíme.) 2.1 Přehled základních důkazových technik V matematice je často používaných několik následujících způsobů - technik, jak k danému tvrzení nalézt korektní formální důkaz. (Uvědomme si, že jedno tvrzení mívá mnoho různých, stejně korektních, důkazů; ty se však mohou výrazně lišit svou složitostí.) Tyto techniky si v bodech shrneme zde: • Přímé odvození. To je způsob, o kterém jsme se dosud bavili. Postupujeme přímo od předpokladů k závěru, ale sami poznáte, že taková „přímá" cesta je obtížně k nalezení. • Kontrapozice (také obrácením či nepřímý důkaz). Místo věty „Jestliže platí předpoklady, pak platí závěr." budeme dokazovat ekvivalentní větu „Jestliže neplatí závěr, pak neplatí alespoň jeden z předpokladů." • Důkaz sporem. Místo věty „Jestliže platí předpoklady, pak platí závěr." budeme dokazovat větu „Jestliže platí předpoklady a platí opak závěru, pak platí opak jednoho z předpokladů (nebo platí jiné zjevně nepravdivé tvrzení)." • Matematická indukce. Pokročilá technika, kterou zde popíšeme později... Tyto techniky jsou asi nejlépe ilustrovány následovnými příklady důkazů. Příklad důkazu kontrapozicí Definice: Prvočíslo p > 1 nemá jiné dělitele než lap. Příklad 2.1. na důkaz kontrapozicí (obrácením). Věta. Jestliže p je prvočíslo větší než 2, pak p je liché. Důkaz: Obráceného tvrzení - budeme tedy dokazovat, že je-li p sudé, pak p buď není větší než 2, nebo p není prvočíslo. Jsou dvě možnosti: • p < 2. Pak p není větší než 2. • p > 2. Pak p = 2.k pro nějaké celé k > 1, tedy p není prvočíslo. n Poznámka: Důkazy kontrapozicí pracují s negací (opakem) předpokladů a závěru. Je-li např. závěr komplikované tvrzení tvaru „z toho, že z A a B plyne C vyplývá, že z A nebo C plyne A a B", není pouhou intuicí snadné zjistit, co je vlastně jeho negací. Jak uvidíme v pozdějších lekcích, užitím jednoduché induktivní metody lze podobná tvrzení negovat zcela mechanicky. 6 Příklady důkazu sporem Příklad 2.2. Jiný přístup k Důkazu 2.1. Věta. Jestliže p je prvočíslo větší než 2, pak p je liché. Důkaz sporem: Nechť tedy p je prvočíslo větší než 2, které je sudé. Pak p = 2 • k pro nějaké k > 1, tedy p není prvočíslo, spor (s předpokladem, že p je prvočíslo). ,-, Důkaz sporem je natolik specifický a důležitý v matematice, že si zaslouží širší vysvětlení. Co je vlastně jeho podstatou? Je to (zcela přirozený) předpoklad, že v konzistentní teorii nelze zároveň odvodit tvrzení i jeho negaci. Jestliže tedy ve schématu „Jestliže platí předpoklady a platí opak závěru, pak platí opak jednoho z předpokladů, nebo platí jiné zjevně nepravdivé tvrzení." odvodíme k některému předpokladu jeho spor, nebo případně jiné tvrzení, které odporuje všeobecně přijatým faktům (například 0 = 1), pak něco musí být „špatně". Co však v našem tvrzení může (nezapomeňte předpoklad konzistence) být chybné? Původní předpoklady byly dány, takže zbývá jedině náš dodatečný předpoklad, že platí opak závěru. Tudíž opak závěru nemůže nikdy platit a dvojí negací odvodíme, že platí původní závěr. Příklad 2.3. Věta. Číslo V2 není racionální. Důkaz sporem: Nechť tedy \[2 je racionální, tj. nechť existují nesoudělná celá kladná čísla r, s taková, že \f7i = r/s. - Pak 2 = r2/'s2, tedy r2 = 2 • s2, proto r2 je dělitelné dvěma. Z toho plyne, že i r je dělitelné dvěma (proč?). - Jelikož r je dělitelné dvěma, je r2 dělitelné dokonce čtyřmi, tedy r2 = 4 • m pro nějaké m. Pak ale také 4 • m = 2 • s2, tedy 2 • m = s2 a proto s2 je dělitelné dvěma. - Z toho plyne, že s je také dělitelné dvěma. Celkem dostáváme, že r i s jsou dělitelné dvěma, jsou tedy soudělná a to je spor (s definicí racionálního čísla). d Komentář: „Nevíte-li, jak nějakou větu dokázat, zkuste důkaz sporem... " 2.2 Věty typu „tehdy a jen tehdy" Uvažujme nyní (v matematice poměrně hojné) věty tvaru „Nechť platí předpoklady P. Pak tvrzení A platí tehdy a jen tehdy, platí-li tvrzení B." Příklady jiných formulací téže věty jsou: * Za předpokladů P je tvrzení B nutnou a postačující podmínkou pro platnost tvrzení A. * Za předpokladů P je tvrzení A nutnou a postačující podmínkou pro platnost tvrzení B. * Nechť platí předpoklady P. Pak tvrzení A platí právč tehdy když platí tvrzení B. 7 Fakt: Důkaz vět tohoto tvaru má vždy dvě části(!). Je třeba dokázat: * Jestliže platí předpoklady P a tvrzení A, pak platí tvrzení B. * Jestliže platí předpoklady P a tvrzení B, pak platí tvrzení A. 2.3 Matematická indukce Pokud se souhrnně podíváme na důkazové techniky v matematice, všimneme si, že matematická indukce je skoro „dvorní" důkazovou technikou diskrétní matematiky. To proto, že umožňuje pohodlně dokazovat i složitá tvrzení po jednotlivých (diskrétních) krocích od počátečního. Uvažme tedy větu ve tvaru: „Pro každé přirozené (celé) n > k0 platíT(n).u Zde k0 je nějaké pevné přir. číslo a T(n) je tvrzení parametrizované čís. n. Příkladem je třeba tvrzení: Pro každé n > 0 platí, že n přímek dělí rovinu nejvýše na \n(n + 1) + 1 oblastí. Definice 2.4. Princip matematické indukce říká, že k důkazu věty „Pro každé přirozené (celé) n > ko platí T(n)." stačí ověřit platnost těchto dvou tvrzení: • T(ko) (tzv. báze neboli základ indukce) • Pro každé n > k0; jestliže platí T(n), (indukční předpoklad) pak platí také T(n+ 1). (indukční krok) (Formálně řečeno, matematická indukce je axiomem aritmetiky přirozených čísel.) Poznámka: Pozor, v tomto předmětu počítáme 0 za přirozené číslo! Opět jako v předešlém si tuto techniku ilustrujeme množstvím názorných příkladů. Příklady důkazů indukcí Příklad 2.5. Velmi jednoduchá a přímočará indukce. Věta. Pro každé n > 1 je stejná pravděpodobnost, že při současném hodu n kostkami bude výsledný součet sudý, jako, že bude lichý. Důkaz: Základ indukce je zde zřejmý: Na jedné kostce (poctivé!) jsou tři lichá a tři sudá čísla, takže obě skupiny padají se stejnou pravděpodobností. Indukční krok pro n > 1: Nechť psn pravděpodobnost, že při hodu n kostkami bude výsledný součet sudý, a pln je pravděpodobnost lichého. Podle indukčního předpokladu je s __ l __ 1 Pn P n 2' Hoďme navíc (n + l)-ní kostkou. Podle toho, zda na ní padne liché nebo sudé číslo, je pravděpodobnost celkového sudého součtu rovna 3; 3 s 1 6Pn + 6Pn == 2 a stejně pro pravděpodobnost celkového lichého součtu. □ Příklad 2.6. Ukázka důkazové „síly" principu matematické indukce. Věta. Pro každé n > 0 platí, že n přímek dělí rovinu nejvýše na 1 2n(n + X) oblastí. Důkaz: Pro bázi indukce stačí, že 0 přímek dělí rovinu na jednu část. (Všimněte si také, že 1 přímka dělí rovinu na dvě části, jen pro lepší pochopení důkazu.) Mějme nyní rovinu rozdělenou n přímkami na nejvýše ^n(n+l) + l částí. Další, (n+1)-ní přímka je rozdělena průsečíky s předchozími přímkami na nejvýše n+1 úseků a každý z nich oddělí novou část roviny. Celkem tedy bude rovina rozdělena našimi přímkami na nejvýše tento počet částí: -n(n+1) + 1 + (n+1) = -n(n + 1) + - • 2(n + 1) + 1 = -(n + l)(n + 2) + 1 D Příklad 2.7. Další indukční důkaz rozepsaný v podrobných krocích. ^n ■ __ n(n+ '3=0 J ~ 2 Věta. Pro každé n>0 platí £?=0 j ~ '^^ Důkaz indukcí vzhledem k n. • Báze: Musíme dokázat tvrzení T(0), což je v tomto případě rovnost J2°j=oJ = 2 ■ Tato rovnost (zjevně) platí. • Indukční krok: Musíme dokázat následující tvrzení: Jestliže platí E*=0 j = ^ kdei>0, pak platí E*ť0 j = {l+1f+2). Předpokládejme tedy, že E}=o j = 2 a P°kusme se dokázat, že pak také E}=oJ = ^+ '2 + ' = ^+ >(t+ >. To už plyne úpravou: £, = ±j+{(+1) = iíi±u + (< + i) = '" + 1):2" + 1) = k0 je indukční krok univerzálně platný... Zesílení indukčního kroku Příklad 2.8. Když je nutno indukční krok zesílit... Věta. Pro každé n > 1 platí Důkaz: Báze indukce je zřejmá, neboť -^ < 1. Co však indukční krok? Předpoklad s(n) < 1 je sám o sobě „příliš slabý" na to, aby bylo možno tvrdit s(n + 1) = s(n) + (ra+1)1(ra+2) < 1- Neznamená to ještě, že by tvrzení nebylo platné, jen je potřeba náš indukční předpoklad zesílit. Budeme dokazovat Tvrzení. Pro každé přirozené n > 1 platí s(n) < 1 — ^-j- < 1. To platí pro n = 1 (nezapomeňte ověřit!) a dále už úpravou jen dokončíme zesílený indukční krok: 1 1 " s(n+l) = s(n) + -------—------— < 1 (n+l)(n + 2) - ra+1 (77+l)(77 + 2) x ~(n + 2) + l _ 1 (t7+1)(t7 + 2) n + 2 D Rozšíření báze a předpokladu Mimo zesilování tvrzení indukčního kroku jsme někdy okolnostmi nuceni i k rozšiřování samotné báze indukce a s ní indukčního předpokladu na více než jednu hodnotu parametru n. 10 - Můžeme například předpokládat platnost (parametrizovaných) tvrzení T(n) i T(n+1) zároveň, a pak odvozovat platnost T(n + 2). Toto lze samozřejmě zobecnit na jakýkoliv počet předpokládaných parametrů. - Můžeme dokonce předpokládat platnost tvrzení T(j) pro všechna j = ko,ko + l,... ,n najednou a dokazovat T(n + 1). (Toto typicky využijeme v případech, kdy indukční krok „rozdělí" problém T(n + 1) na dvě menší části a z nich pak odvodí platnost T(n + 1).) Fakt: Obě prezentovaná „rozšíření" jsou v konečném důsledku jen speciálními instancemi základní matematické indukce; použité rozšířené možnosti pouze zjednodušují formální zápis důkazu. Příklad 2.9. Když je nutno rozšířit bázi a indukční předpoklad... Věta. Nechť funkce f pro každé n > 0 splňuje vztah f(n + 2) = 2f(n + 1) — f(n). Pokud platí /(O) = 1 a zároveň /(l) = 2, tak platí f(n) = n + 1 pro všechna přirozená n > 0. Důkaz: Už samotný pohled na daný vztah f(n + 2) = 2f(n + 1) — f(n) naznačuje, že bychom měli rozšířit indukční předpoklad (a krok) zhruba takto: Pro každé n > 0; jestliže platí T(n); neboli f(n) = n + 1, a zároveň platí T(n + 1); f(n+l) = n + 2, pak platí také T(n + 2); f(n + 2) = n + 3. Báze indukce - pozor, zde už musíme ověřit dvě hodnoty /(O) =0 + 1 = 1, /(l) = 1 + 1 = 2. Náš indukční krok tak nyní může využít celého rozšířeného předpokladu, znalosti hodnot f(n) i f(n+ 1), pro ověření f(n + 2) = 2f(n + 1) - f(n) = 2 ■ (n + 1 + 1) - (n + 1) = n + 3 = n + 2 + 1. D Komentář: Jak by tento důkaz měl být formulován v „tradiční" indukci? („Substitucí" nového tvrzení.) Závěrem malý „problém" Příklad 2.10. Aneb jak snadno lze v matematické indukci udělat chybu. Věta. („nevěta") V každém stádu o n > 1 koních mají všichni koně stejnou barvu. Důkaz indukcí vzhledem k n. Báze: Ve stádu o jednom koni mají všichni koně stejnou barvu. Indukční krok: Nechť S = {K\,... ,Kn+í} je stádo o n + 1 koních. Dokážeme, že všichni koně mají stejnou barvu. Uvažme dvě menší stáda: - S' = {KuK2,...,Kn) - S" = {K2,...,Kn,Kn+1} 11 Podle indukčního předpokladu mají všichni koně ve stádu S' stejnou barvu B'. Podobně všichni koně ve stádu S" mají podle indukčního předpokladu stejnou barvu B". Dokážeme, že B' = B", tedy že všichni koně ve stádu S mají stejnou barvu. To ale plyne z toho, že koně K2,..., Kn patří jak do stáda S', tak i do stáda S". □ Komentář: Ale to už je podvod! Vidíte, kde? Rozšiřující studium 3 Množiny, Relace a Funkce Úvod V přehledu matematických formalismů informatiky se v této lekci zaměříme na základní „datové typy" matematiky tj. na množiny relace a funkce. O množinách jste sice zajisté slyšeli už na základní škole, ale podstatou našeho předmětu je uvést povětšinou neformálně známé pojmy na patřičnou formální úroveň nutnou pro teoretické základy informatiky. S pojmem funkce jste se také již setkali na nižších stupních škol, ale povětšinou si je asi spojujete jen s aritmetickými a analytickými funkcemi typu x + 1, x2 — y, či sin x, 1 + cos x2, atd. Pojem funkce je však zcela abstraktní a neváže se na žádný analytický vzorec výpočtu. Cíle V této lekci si ukážeme první krok k seriózně vybudované matematické teorii množin - tzv. naivní teorii množin, která nám velmi dobře poslouží ve všech konečných případech. Na to navážeme (abstraktní) definicí relace, funkce a posloupnosti, uvedeme si příklady rekurzivně definovaných funkcí a posloupností. Látku relací a funkcí pak dále rozvedeme v následujích dvou lekcích. 3.1 Pojem množiny Položme si hned na úvod tu nejdůležitější otázku: Co je vlastně množina? Na tuto otázku bohužel není zcela jednoduchá odpověď... Abychom se vůbec někam v našem úvodu dostali, spokojíme se zatím jen s přirozeným „naivním pohledem". Definice naivní teorie množin: „Množina je soubor prvků a je svými prvky plně určena." Komentář: Pozor, není skutečného rozdílu mezi „množinami" a „prvky". Množiny mohou být prvky jiných množin! Příklady: 0, {a, b}, {b,a}, {a,b,a}, {{a,b}}, {0, {0}, {{0}}}, {a; | a; je liché přirozené číslo} Značení: Počet prvků (mohutnost) množiny A zapisujeme \A\. * |0| = O, |{0}| = 1, \{a,b,c}\ = 3, \{{a,b},c}\=2 Značení množin a jejich prvků: * x G M „x je prvkem množiny M". * některé vlastnosti a G {a, b}, a G" {{a, b}}, {a,b} G {{a, b}}. 12 * prázdná množina 0, a G" 0, 0 G {0}, 0 G" 0, * rovnost množin {a, b} = {b, a} = {a, b, a}, {a, b} ^ {{a, b}}. Definice: Množina A je podmnožinou množiny B, právě když každý prvek A je prvkem B. Píšeme A C B nebo také B D A; říkáme také, že se jedná o inkluzi. * Platí {a} C {a} C {a, b} £ {{a, b}}, 0 C {0}, * A C B právě když A C B & A =£ B (A je vlastnípodmnožinou B). Definice: Dvě množiny jsou si rovny A = B právě když A C B a B C A. * Podle definice jsou množiny A a B stejné, mají-li stejné prvky. * Důkaz rovnosti množin A = B má obvykle dvě části: Odděleně se dokáží inkluze AC B a B C A. Značení: Některé běžné množiny v matematice se značí * N = {0,1, 2, 3,...} je množina přirozených čísel, * Z = {..., —2, —1, 0,1, 2, 3,...} je množina celých čísel, * Z+ = {1, 2, 3,...} je množina celých kladných čísel, * Q je množina racionálních čísel (zlomků). * R je množina reálných čísel. Poznámka: Tyto uvedené číselné množiny jsou vesměs nekonečné, na rozdíl od konečných množin uvažovaných v předchozím „naivním" pohledu. Pojem nekonečné množiny se přímo v matematice objevil až teprve v 19. století a bylo s ním spojeno několik paradoxů ukazujících, že naivní pohled na teorii množin pro nekonečné množiny nedostačuje. My se k problematice nekonečných množin, Kantorově větě a Russelově paradoxu vrátíme v závěru našeho předmětu. 3.2 Množinové operace Začněme se základními operacemi, které zajisté na intuitivní úrovni již ovládáte. Definice: Sjednocení U a průnik n dvou množin A, B definujeme Al) B = {x \ x e A nebo x e B} . Aľ\ B = {x \ x E A a současně x G B} . * Příklady {a, b, c} U {a, d} = {a, b, c, d}, {a, b, c} n {a, d} = {a}. * Vždy platí „distributive" A n (B U C) = (A n B) U (A n C) a A U (B n C) = {A U B) n (A U C). Definice: Pro libovolný počet množin indexovaných pomocí / rozšířeně definujeme [J. jAí = {x | x G Ai pro nějaké i E 1} . P) Aj = {x I x G Ai pro každé i G /} . 13 Komentář: Nechť Ai = {2.i} pro každé i G N. Pak IJísn ^ Je množina všech sudých přirozených čísel. Nechť Bí = {x \ x G N, x > i} pro každé i G N. Pak Hísn -^í = 0- Definice: Rozdíl \ a symetrický rozdíl A dvou množin A, B definujeme A\B = {x \ x 0 definujeme uspořádanou k-tici (a\, • • •, ak) induktivně takto - (ai) = au - (ai, • • •, ai, ßi+i) = ((«i, ■ ■ ■ ,ai), aj+i). 14 Fakt: Platí (cii, ■ ■ ■, a^) = (b\, ■ ■ ■, bk) právě když a^ = bi pro každé i E N kde 1 < i < k. Definice kartézského součinu více množin: Pro každé k E IN definujeme Ai x • • • x Ak = {(«i, • • •, (ífc) | di G Ai pro každé 1 < i < k} . * Příklad Z3 = ZxZxZ = {(i, j, k) | i, j, k G 1}. * Co je A°? {0}, neboť jediná uspořádaná 0-tice je právě prázdná 0. Poznámka: Podle uvedené definice není součin asociativní, tj. obecně nemusí platit, že Ax(BxC) = (AxB)xC. V matematické praxi je někdy výhodnější uvažovat „upravenou" definici, podle níž součin asociativní je. Pro účely této přednášky není podstatné, k jaké definici se přikloníme. Prezentované definice a věty „fungují" pro obě varianty. Potenční množina Definice 3.3. Potenční množina množiny A. neboli množina všech podmnožin, je definovaná vztahem 2A = {B\BCA}. * Platí například 2Ía'6> = {0, {a}, {b}, {a, b}}, * 20 = {0}, 2»> = {0,{0},{{0}},{0,{0}}}; * 2WxM = {0, {(a, á)},{(a,b)}, {(a, a), (a, &)}}. Věta 3.4. Počet prvků potenční množiny splňuje \2A\ = 2^. Důkaz: Stručně indukcí podle \A\: Pro A = 0 platí \2A\ = |{0}| = 1. Pro každý další prvek b G" A rozdělíme všechny podmnožiny A U {b} napolovic na ty neobsahující b a na ty obsahující b, tudíž \2AU^\ =2- \2A\ = 2^+1. a 3.3 Porovnávání a určení množin Pro obecnou ilustraci formálního množinového kalkulu si ukažme dva důkazy rovností mezi množinovými výrazy. Podobně lze (rozepsáním příslušných definic) rutinně dokazovat další množinové vztahy. Věta 3.5. Pro každé dvě množiny A, B C M platí AU B = Aľ\ B. Důkaz v obou směrech rovnosti. . AU B CÄnß: Pro x e M platí x G AU B, právě když x g. AU B, neboli když zároveň x ^ A a. x ^ B. To znamená x G A a zároveň x E B, z čehož vyplývá požadované x E Aľ\ B. * AU B D A U B: Pro x E M platí x G A U B, právě když x G A a zároveň x E B, neboli když zároveň x E~ A a. x E~ B. To znamená x G" A U B, z čehož vyplývá požadované x E AU B. 15 D Věta 3.6. Pro každé tři množiny A, B, C platí A\(BC\C) = (A\B) U(A\C). Důkaz. . A \ (B n C) C (A\B) l)(A\C): Je-li x G A \ (B n C), pak x G A a zároveň x^(5ílC), neboli x ^ B nebo x ^ C. Pro první možnost máme x £ (A \ ß), pro druhou x G (A \ C). . Naopak A \ {B n C) D (A \ S) U (A \ C): Je-li x G (A \ S) U (A \ C), pak x G (A \ B) nebo i£ (j4\C). Pro první možnost máme x G A a zároveň x ^ B, z čehož plyne x G A a zároveň x G" (S fl C), a tudíž x G A \ (B n C). Druhá možnost je analogická. n Charakteristický vektor (pod)množiny V případech, kdy všechny uvažované množiny jsou podmnožinami nějaké nosné množiny X, což není neobvyklé v programátorských aplikacích, s výhodou využijeme následující reprezentaci množin. Definice: Mějme nosnou množinu X = {x\,X2, ■ ■ ■ ,xn}. Pro A N předpisem f (x) = x + 8. Tj. / = {(x, x + 8) | x G N}. * Definujeme funkci plus : N x N —> N předpisem plus(i,j) = i + j. Tj.plus = {(i,j,i + j) | í, j G N}. Definice: Pokud naší definici funkce upravíme tak, že požadujeme pro každé x G A nejvýše jedno y G B takové, že (x, y) G /, obdržíme definici parciální funkce z A do B. Komentář: V parciální funkci p nemusí být pro některé „vstupní" hodnoty x funkční hodnota definována. Pro nedefinovanou hodnotu používáme znak _L. Komentář: Další příklady funkcí. * Definujeme parciální funkci / : % —> N předpisem m 3 + x jestliže x > 0. _L jinak. Tj. / = {(x,3 + x) | x éN}. * Také funkce / : R —> R daná běžným analytickým předpisem /O) = Ví je jen parciální - není definována pro x < 0. * Co je relace, přiřazující lidem v ČR jejich rodná čísla? 3.5 Posloupnosti a rekurentní vztahy Specifickým případem funkcí jsou ty, jež jsou definovány z přirozených čísel - u nich totiž funkční hodnoty můžeme snadno jednu po druhé vypsat jako /(O), /(l), /(2),... a také takto jednoduše je zadat. Definice: Funkce p : N —► R se nazývá posloupnost. Mimo „funkčního" zápisu p(n) často používáme „indexovou" formu zápisu funkční hodnoty pn. Poznámka: Obor hodnot posloupnosti může být i jiný než reálná čísla. Na posloupnost se také díváme jako na „seřazení" vybraných prvků z oboru hodnot, s povoleným opakováním hodnot (nemusí být prostá). Také definiční obor posloupnosti může být od nuly nebo i od jedničky, jak je v aplikacích potřeba. 18 • Příklady posloupností: * Po = 0, pí = 2,... ,pi = 2i,... je posloupnost sudých nezáporných čísel. * 3, 3.1, 3.14, 3.141,... je posloupnost postupných dekadických rozvojů tt. * 1, —1, 1, —1,... je posloupnost určená vztahem pi = (—1)*, i > 0. * Pokud chceme stejnou posloupnost 1, —1, 1, —1,... zadat jako qi, i > 1, tak ji určíme vzorcem Qí = (—l)1-1. • Posloupnost je rostoucí či klesající, pokud pn+\ > pn či pn+\ < pn pro všechna n. Rekurentní definice posloupnosti Slovem rekurentní označujeme takové definice (či popisy), které se v jistých bodech odvolávají samy na sebe. (Už jste se setkali s „rekurzí" při programování? A víte, co znamená?) Místo nepřehledných formálních definic si rekurentní vztahy uvedeme několika názornými ukázkami. • Zadáme-li posloupnost pn vztahy p0 = 1 a pn = 2pra_i pro n > 0, pak platí pn = 2n pro všechna n. • Obdobně můžeme zadat posloupnost qn vztahy q1 = 1 a qn = qn_\ + n pro n > 1. Potom platí qn = \n(n + 1) pro všechna n. Uměli byste toto dokázat indukcí? Viz Příklad 2.7. • Známá Fibonacciho posloupnost je zadaná vztahy fx = f2 = 1 a /„ = /ra_i + /ra_2 pro n> 2. Rozšiřující studium 4 Binární relace, Ekvivalence Úvod V návaznosti na předchozí lekci si podrobně rozebereme matematické formalismy relací. Na rozdíl od množin, které se v jisté velmi naivní formě objevují už na základní škole, se relacím v jejich abstraktní podobě moc pozornosti nevěnuje. Avšak na pojem relace velmi brzo narazí (snad) každý informatik při studiu relačních databází. Není to však jen oblast databází, ale i jiná místa informatiky, kde se relace skrývají či přímo explicitně objevují. Nejčastěji se takto setkáme s binárními relacemi, například vždy když rozdělujeme objekty podle „shodných" znaků (relace ekvivalence), nebo když objekty mezi sebou „srovnáváme" (relace uspořádání). Na tyto dvě základní oblasti se dále zaměříme. Cíle Úkolem této lekce je vybudovat matematickou teorii (konečných) relací, s primárním zaměřením na binární relace jako ekvivalence a uspořádání. Ve vztahu k binárním relacím je zavedeno množství pojmů, které jsou později užitečné v různých oblastech matematiky i informatiky. Látka pak plynule pokračuje Lekcí 5. 19 4.1 Reprezentace konečných relací Oblast, kde informatici nejčastěji potkají relace, je bezesporu ukládání dat. (Neboť shromažďovaná data, stejně jako relace, především sledují vztahy mezi danými objekty...) Příklad 4.1. Tabulky relační databáze. Definujme následující množiny („elementární typy") * ZNAK = {a, ■ ■ ■, z, A, ■ ■ ■, Z, mezera}. * ČÍSLICE = {0,1,2,3,4,5,6,7,8,9}. Dále definujeme tyto množiny („odvozené typy") * JMÉNO = ZNAK15, PŘÍJMENÍ = ZNAK20, * VEK = ČÍSLICE3, * ZAMESTNANEC = JMÉNO x PRIJMEM x VEK. Relaci „typu" ZAMESTNANEC pak lze reprezentovat tabulkou: JMÉNO příjmení VEK Jan Novák 42 Petr Vichr 28 Pavel Zima 26 D Definice: Relační databáze je konečná množina tabulek. Schéma databáze je (zjednodušeně řečeno) množina „typů" jednotlivých tabulek. Reprezentace binárních relací na množině Jistě čtenáři uznají, že zadání relace výčtem jejích složek není pro člověka (na rozdíl od počítače) tím nejpříjemnějším způsobem. Je tedy přirozené se ptát, jak co nejnázorněji takovou relaci, alespoň v její nejčastější binární podobě, ukázat. Značení: Binární relaci i? C M x M lze jednoznačně znázornit jejím grafem. • Prvky M znázorníme jako body v rovině. • Prvek (a, b) G R znázorníme jako orientovanou hranu („šipku") z a do b. Je-li a = b. pak je touto hranou „smyčka" na a. Komentář: Pozor, nejedná se o „grafy funkcí" známé z analýzy. Například mějme M = {a, b, c, d, e, f} a R = {(a,b), (b, c), (b, d), (b, e), (b, f), (d, c). (e, c), (/, c), (e, d), (e, /), (/, b)}, pak: 20 V případě, že R je nekonečná nebo „velká", může být reprezentace R jejím grafem nepraktická (záleží pak na míře „pravidelnosti" R). 4.2 Vlastnosti binárních relací Definice 4.2. Nechť R C M x M. Binární relace R je • reflexivní, právě když pro každé a G M platí (a, a) G R: • ireflexivní, právě když pro každé a G M platí (a, a) G" i?; symetrická, právě když pro každé a,b E M platí, že jestliže (a, 6) G i?, pak také (6, a) G E; » antisymetrická, právě když pro každé a,b E M platí, že jestliže (a, 6), (b, a) G i?, pak a = b: > tranzitivní, právě když pro každé a,b,c G M platí, že jestliže (a, b), (b,c) G i?, pak také (a, c) G R. Následují dva základní typy binárních relací, i? je • relace ekvivalence, právě když je R reflexivní, symetrická a tranzitivní: • částečné uspořádání, právě když je R reflexivní, antisymetrická a tranzitivní (často říkáme jen uspořádání). Poznámka: Pozor, může být relace symetrická i antisymetrická zároveň? Ano! Vezměte si relaci R = {(x, x) \ x G M}, která obě jmenované vlastnosti splňuje. Proto pokud jste třeba dotázáni, zda relace je symetrická, nestačí se v odpovědi odvolávat na fakt, že je antisymetrická(!), neboť tyto vlastnosti se nevylučují. Příklad 4.3. Několik příkladů relací defínovaných v přirozeném jazyce. Buď M množina všech studentů 1. ročníku FL Uvažme postupně relace R C M x M definované takto * (x, y) E R právě když x a y mají stejné rodné číslo: 21 * (x, y) E R právě když x má stejnou výšku jako y (dejme tomu na celé mm): * (x, y) E R právě když výška x a y se neliší více jak o 2 mm: * (x, y) E R právě když x má alespoň takovou výšku jako y: * (x, y) E R právě když x má jinou výšku než y (dejme tomu na celé mm): * (x, y) E R právě když x je zamilován (a) do y. Zamyslete se podrobně, které z definovaných vlastností tyto relace mají. □ Příklad 4.4. Jaké vlastnosti mají následující relace? * Buď ňCNxN definovaná takto (x, y) E R právě když x dělí y. (Částečné uspořádání. ale ne každá dvě čísla jsou porovnatelná.) * Buď fiCNxN definovaná takto (x, y) E R právě když x a y mají stejný zbytek po dělení číslem 5. (Ekvivalence.) * Nechť F = {/ | / : N —► N} je množina funkcí. Buď R E F x F definovaná takto (f, g) E R právě když f (x) < g (x) pro všechna x. (Antisymetrická a tranzitivní, ale ne reflexivní - není uspořádání.) □ 4.3 Relace ekvivalence * Relace RE M x M je ekvivalence právě když R je reflexivní, symetrická a tranzitivní. Tyto tři vlastnosti je tedy třeba ověřit k důkazu toho, že daná relace i? je ekvivalence. * Jak vypadá graf ekvivalence? Neformálně řečeno: ekvivalence je relace R E M x M, taková, že (x, y) E R práve když x a y jsou v nějakém smyslu „stejné". Komentář: Buď M množina všech studentů 1. ročníku FI. Uvažme postupně relace R C M x M definované takto * (x, y) E R právě když x má stejnou výšku jako y: * (x, y) E R právě když x má stejnou barvu vlasů jako y: * (x, y) E R právě když x, y mají stejnou výšku a stejnou barvu vlasů: * (x, y) E R právě když x, y mají buď stejnou výšku nebo stejnou barvu vlasů. (Tato relace obecně lení ekvivalence! Proč?) binární relace definovaná takto: (x,y) E R právě když Příklad 4.5. Buď R E N x \x — y\ je dělitelné třemi. V jakém smyslu jsou zde x a y „stejné"? Dávají stejný zbytek po dělení třemi. D 22 Příklad 4.6. Buď R binární relace mezi všemi studenty na přednášce IBOOO defíno-vaná takto: (x, y) E R právě když x i y sedí v první lavici. Proč se v tomto případě nejedná o relaci ekvivalence? Protože není reflexivní pro studenty sedící v dalších lavicích. (Takže si dávejte dobrý pozor na správné pochopení definic.) □ 4.4 Rozklady a jejich vztah k ekvivalencím Náplní této části je ukázat jiný přirozený pohled na ekvivalence. Definice 4.7. Rozklad. Buď M množina. Rozklad (na) M je množina podmnožin Aí C 2M splňující následující tři podmínky: - 0 G" Aí (tj. každý prvek Aí je neprázdná podmnožina M); - pokud A,BeAÍ, pak buď A = B nebo A n B = 0: Prvkům Aí se také říká třídy rozkladu. Komentář: * Buď M = {a, b, c, d}. Pak TV = {{a}, {b, c}, {d}} je rozklad na M. * Nechť A0 = {k G N | k mod 3 = 0}, Aľ = {k G N | k mod 3 = 1}, A2 = {k G N | k mod 3 = 2}. Pak TV = {Aq, Ai,A2} je rozklad všech přirozených čísel N podle zbytkových tříd. * Každý rozklad TV na M jednoznačně určuje jistou ekvivalenci R^f na M. Věta 4.8. Buď M množina a Aí rozklad na M. Necht Rj^ C M x M je relace na M definovaná takto (x, y) G R_\f právě když existuje A E Aí taková, že x, y E A. Pak Rj^f je ekvivalence na M. Důkaz: Dokážeme, že Rjsf je reňexivní, symetrická a tranzitivní (Dennice 4.2). • Reflexivita: Buď x E M libovolné. Jelikož Aí je rozklad na M, musí existovat A E Aí takové, že x E A (jinak spor se třetí podmínkou z Deßnice 4.7). Proto (x,x) E Rj^. tedy Rtf je reflexivní. • Symetrie: Nechť (x, y) E R_\f. Podle definice R_\f pak existuje A E Aí taková, že x,y E A. To ale znamená, že také (y,x) E Rj^ podle definice R^-, tedy R^f je symetrická. • Tranzitivita: Nechť (x,y), (y,z) E R_\f. Podle definice R_\f existují A, B E Aí takové, že x, y E A a y, z E B. Jelikož Anß^i, podle druhé podmínky z Deßnice 4.7 platí A = B. Tedy x, z E A = B, proto (x, z) E Rj^f podle definice Rj^f. n Věta 4.9. Buď M množina a R ekvivalence na M. Prv každé x E M definujeme množinu [x] = {yEM\ (x,y)ER}. Pak {[x] | x E M} je rozklad na M, který znaěíme M j R. 23 Důkaz: Dokážeme, že M/R splňuje podmínky Dennice 4.7. • Pro každé [x] G M/R platí [x] ^ 0, neboť x G [x]. • Nechť [x], [y] G M j R. Ukážeme, že pokud [x] n [y] 7^ 0, pak [x] = [y]. Jestliže [x] Pi [y] 7^ 0, existuje z E M takové, že z G [x] a z G [y]. Podle definice [x] a [y] to znamená, že (x, z), (y, z) G R. Jelikož R je symetrická a (y, z) G i?, platí (z, y) G i?. Jelikož (x, z), (z, y) G R a R je tranzitivní, platí (x, y) G i?. Proto také (y, x) G R (opět ze symetrie i?). Nyní dokážeme, že [y] = [x]: * ,,[x] C [y]:" Nechť v G [x]. Pak (x, v) G -R podle definice [x]. Dále (y,a;) G -R (viz výše). tedy (y, v) G R neboť E je tranzitivní. To podle definice [y] znamená, že v G [y]. * ,,[y] C [#]:" Nechť v G [y]. Pak (y, v) G -R podle definice [y]. Dále (a;,y) G -R (viz výše). tedy (x, v) G -R neboť _R je tranzitivní. To podle definice [x] znamená, že v G [a;]. . Platí Ufxi gm/äW = ^) neboť x G [x] pro každé x G M. □ Rozšiřující studium 5 Uspořádané množiny, Uzávěry Úvod V této lekci dále pokračujeme probíráním binárních relací na množinách jako nástroji vyjadřujícími vztahy mezi objekty. Zaměřujeme se nyní především na relace „srovnávající" objekty podle jejich vlastností. Takto vágně opsané relace mívají jasné společné znaky které se objevují ve zde uvedené formální definici relace uspořádání. Následně se také zabýváme způsobem, jak libovolnou relaci „obohatit" o nějakou vlastnost. Tnto úkol vede na rozšiřování naší relace (tj. přidávání dvojic) do jejího takzvaného uzávěru. Cíle Definujeme relace uspořádání a pojmy k nim se vztahující. Dále ukážeme operátory uzávěrů relací. 5.1 Uspořádané množiny Zopakujme si na úvod... 24 • Relace R C. M x M je (částečné) uspořádání právě když i? je reflexivní, antisymetrická a tranzitivní.Tyto tři vlastnosti je tedy třeba ověřit k důkazu toho, že daná relace R je uspořádání. • Neformálně řečeno: uspořádání je taková relace R C M x M, kde (x, y) G R právě když x je v nějakém smyslu „menší nebo rovno11 než y. Mohou ovšem existovat taková x,y E M, kde neplatí (x, y) G R ani (y, x) G R. (Pak říkáme, že x a y jsou nesrovnatelné.) Komentář: Zajisté jste se již neformálně setkali s „neostrým" uspořádáním čísel < a „ostrým" uspořádáním <.Všimněte si dobře, že námi definované uspořádání je vždy „neostré". Avšak pokud byste chtěli definovat „ostré" uspořádání, mělo by vlastnosti ireflexivní, antisymetrická a tranzitivní. (Příliš se však toto nepoužívá.) • Jak názorně zobrazit (částečné) uspořádání? Příklad zjednodušeného zakreslení (jsou vynechány šipky vyplývající z reflexivity a tranzitivity, viz Oddíl 5.3): 12 dělitelnost: 1 Všimněte si, že je zvykem „větší" prvky kreslit nad ty „menší". Definice 5.1. Uspořádaná množina je dvojice (M, C). kde M je množina a Q je (částečné) uspořádání na M. Definice: Uspořádání i? na M je lineární (nebo také úplné), pokud každé dva prvky M jsou v R srovnatelné. Komentář: Buď M množina všech studentů 1. ročníku FL Uvažme postupně relace uspořádání R C M x M definované takto: * {x, y) G R právě když x rak alespoň takovou výšku jako y: * (x, y) G R právě když y má alespoň takovou výšku jako x: * (x, y) G R právě když x a y mají stejné rodné číslo. (Dobře si promyslete, proč se jedná o uspořádání. Které dvojice jsou vůbec porovnatelné?) Další ukázky uspořádaných množin následují zde: * (IN, <) je lineárně uspořádaná množina, kde < má „obvyklý" význam. * (N, |), kde | je relace dělitelnosti, je uspořádaná množina. Toto uspořádání není lineární. * Buď M množina. Pak (2 , C) je uspořádaná množina (říkáme inkluzí). Příklad 5.2. Uspořádání „po složkách". Nechť (A, 2, pak množinu Ai x ■ ■ ■ x An lze uspořádat po složkách nebo lexikograficky. Všimněte si, že lexikograficky se řadí slova ve slovníku... 5.2 Další pojmy uspořádaných množin K tématu uspořádaných množin se vztahuje množství drobných pojmů, které potkáte v různých oblastech matematiky i informatiky. Definice 5.4. Buď (M, |Z) uspořádaná množina. • x G M je minimální právě když pro každé y G M platí, že jestliže y Q x, pak x ^ y. (Tj. x je minimální právě když neexistuje žádný prvek ostře menší než x.) x \ x G M je maximální^právě když pro každé y G M platí, že jestliže xCj/, pak y ^ x. (Tj. x je maximální právě když neexistuje žádný prvek ostře větší než x.) x G M je nejmenší právě když pro každé y G M platí, že x Q y. x > x E M je největší právě když pro každé y E M platí, že y Q x. > x G M pokrývá y E M právě když x ^ y, y Q x a neexistuje žádné z G M takové, že Xy^Zy^yay^z^x. x y x G M je horní závora (mez) množiny A x G M je infimum množiny A C M právě když x je největší dolní závora množiny A. A C M je řetězec v uspořádání jZ právě když (A, C.) je lineámě uspořádaná množina. Komentář: Pozor! Některé uvedené definice mají dosti „netriviální chování" na nekonečných množinách. Proto je budeme obvykle uvažovat jen nad konečnými množinami... Relace předuspořádání Definice: Relace R C M x M je předuspořádání (také kvaziuspořádání, nebo polouspo-řádání) právě když i? je reßexivni a tranzitivní. Komentář: Rozdíl mezi uspořádáním a předuspořádáním je (neformálně řečeno!) v tom, že u předuspořádání srovnáváme prvky podle kritéria, které není pro daný prvek jedinečné. V předuspořádání takto mohou vznikat „cyklýc. Tvrzení 5.5. Je-li |Z předuspořádání na M, můžeme definovat relaci ~ na M předpisem x ~ y právě když x ^ y a y ^ x. Pak ~ je ekvivalence na M, která se nazývá jádro předuspořádání Q. Na rozkladu M j ~ pak lze zavést relaci -< definovanou takto [%] ^ [v] právě když x ^ y. Pak (M/ ~, :<) je uspořádaná množina. □ Komentář: Pro příklad si vezměme relaci dělitelnosti na Z. Pak třeba —2 ~ 2. Jádrem zde jsou dvojice čísel stejné absolutní hodnoty. 5.3 Hasseovské diagramy Hasseovské diagramy uspořádaných množin jsou přehlednější než grafy relací. Například: 27 Definice: Hasseovský diagram konečné uspořádané množiny (M, C.) je (jednoznačné) grafické znázornění vzniklé takto: - Do první „horizontální vrstvy" zakreslíme body odpovídající mininálním prvkům {M, Q (tj. které nepokrývají nic). - Máme-li již zakreslenu „vrstvu" i, pak do „vrstvy" i + 1 (která je „nad" vrstvou i) zakreslíme všechny nezakreslené prvky které pokrývají pouze prvky „vrstev" < i. Pokud prvek x „vrstvy" i + 1 pokrývá prvek y „vrstvy" < i, spojíme x a y neorientovanou hranou (tj. „čárou"). Příklad 5.6. Relaci dělitelnosti na množině {1,2,..., 12} zakreslíme: 12 9 10 11 D Komentář: Jak vidíme, v Hasseově diagramu „vynecháváme" ty hrany relace C, které vyplývají z reůexivity či tranzitivity. To celý obrázek výrazně zpřehlední, a přitom nedochází ke ztrátě informace. Lze vynechat i šipky na hranách, neboť dle definice všechny míří „vzhůru". Také pojem „vrstvy1 v definici je jen velmi neformální, důležité je, že větší (pokrývající) prvky jsou nad menšími (pokrývanými). 5.4 Uzávěry relací Buď V (nějaká) vlastnost binárních relací. Řekneme, že V je uzavíratelná, pokud splňuje následující podmínky: - Pro každou množinu M a každou relaci R C M x M existuje alespoň jedna relace S* C M x M, která má vlastnost V a pro kterou platí R C S. - Nechť / je množina a nechť ft C M x ¥ je relace mající vlastnost V pro každé i E I. Pak relace f]i&1 Rí má vlastnost V. Fakt: Libovolná kombinace vlastností reüexivita, symetrie, tranzitivita je uzavíratelná vlastnost. Antisymetrie není uzavíratelná vlastnost. Věta 5.7. N echt V je uzavíratelná vlastnost binárních relací. Bud M množina a R libovolná binární relace na M. Pak pro množinu všech relací S D R na M majících vlastnost V existuje infimum Rv (vzhledem k množinové inkluzi), které samo má vlastnost V. Tuto „nejmenší" relaci Ry s vlastností V nazýváme V-uzávér relace R. Tvrzení 5.8. Buď R binární relace na M. * Reflexivní uzávér R je přesně relace R U {(x, x) \ x G M}. 28 * Symetrický uzávěr R je přesně relace R= {(x,y) \ (x,y) G R nebo (y, x) G R}. Buď T funkce, která pro každou binární relaci S vrátí relaci T (S) = S U {(x, z) | existuje y takové, že (x, y), (y, z) G S} a T% = T o • • • o T budiž z-krát iterovaná aplikace funkce T. i * Tranzitivní uzávěr R je přesně relace R+ = U£i Tl(R). * Reflexivní a tranzitivní uzávěr i? je přesně relace R* = U^i Tl(Q), kde Q je reflexivní uzávěr i?. * Reflexivní, symetrický a tranzitivní uzávěr R (tj. nejmenší ekvivalence obsahující R) je přesně relace (Q)+, kde Q je reflexivní uzávěr i?. Komentář: Význam reflexivních a symetrických uzávěrů je z předchozího docela zřejmý. Význam tranzitivního uzávěru R+ je následovný: Do R+ přidáme všechny ty dvojice (x, z) takové, že y R se lze „dostat po šipkách" z x do z. A jak bylo dříve řečeno, antisymetrický uzávěr relace prostě nemá smysl. Buď JÍCNxN definovaná takto: R = {(í, í + 1) | í G N}. Pak E* je běžné <. Rozšiřující studium 6 Vlastnosti funkcí a Skládání relací Úvod Vraťme se nyní k látce Lekce 3. Z jejího pokročilého obsahu jsme doposud velmi detailně probírali relace a jejich jednotlivé vlastnosti. Nyní se podívejme, jak lze relace mezi sebou „skládat", což je například základní technika práce s relačními databázemi. Je však i jiné místo, kde jste se zajisté se skládáním relací setkali - jedná se o skládání funkcí. Jak například spočítáte na kalkulačce výsledek složitějšího vzorce? Mimo to se ještě zobecněně vrátíme k problematice rekurentních defínic (vztahů). Cíle V této lekci definujeme základní vlastnosti funkcí a především popíšeme a podrobně rozebereme skládání relací a návazně skládání funkcí jako relací. Na závěr se stručně podíváme na problematiku induktivních defínic funkcí, coby na rozšíření rekurentních vztahů z Oddílu 3.5. 6.1 Vlastnosti funkcí Definice: Funkce / : A —► B je - injektivní (nebo také prostá) právě když pro každé x,y G A, x ^ y platí, že f(x) ^ /(i/); 29 - surjektivní (nebo také „na") právě když pro každé y G B existuje x G A takové, že f (%) = y; - bijektivní (vzáj. jednoznačná) právě když je injektivní a současně surjektivní. Komentář: Ukázky vlastností funkcí. * Funkce plus :NxN^Nje surjektivní, ale není prostá. * Funkce g : 7L —>■ N daná předpisem , , _ [ —2x — 1 jestliže x < 0. ^ \ 2a; jinak je bijektivní. * Funkce 0 : 0 —> 0 je bijektivní. * Funkce 0 : 0 —> {a, 6} je injektivní, ale není surjektivní. 6.2 Inverzní relace a skládání relací Definice: Nechť R . PaA; její inverzní relace f~l je a) parciální funkce právě když f je prostá, b) funkce právě když f je bijektivní. Důkaz vyplývá přímo z definic funkce a inverze relace. □ Definice 6.2. Složení (kompozice) relací R a S. Nechť RCAxB&SCBxC jsou binární relace. Složenírel&cí R a S (v tomto pořadí!) je relace S o R C A x C definovaná takto: S'oi? = {(a,c) | existuje b G B takové, že (a, b) G i?, (6, c) G S*} Složení relací čteme „R složeno s S" nebo (pozor na pořadí!) „S po R". Komentář: Příklady skládání relací. * Je-li 30 -A = {a,b}, B = {1,2}, C = {X), - R = {(a,l),(b,l),(b,2)}, S = {(1,X)}, pak složením vznikne relace - SoR = {(a,X),(b,X)}. * Složením funkcí h(x) = x2 a f{x) = a; + 1 na IR vznikne funkce foh{x) = f(h(x)) = x2 + 1. * Složením těchže funkcí „naopak1 ale vznikne funkce h o / (x) = h(f(x)) = (x + l)2. Poznámka: Nepříjemné je, že v některých oblastech matematiky (například v algebře při skládání zobrazení) se setkáme s právě opačným zápisem skládání, kdy se místo S o R píše R ■ S nebo jen RS. Proto je si vždy dobré slovně ujasnit, které pořadí skládaných relací máme na mysli. My zde zásadně budeme používat pořadí S o R. 6.3 Skládání relací „v praxi" Podívejme se nyní, jak se skládání relací přirozeně objevuje v práci s relačními databázemi. (Dá se zjednodušeně říci, že právě v operátoru skládání tabulkových relací je hlavní smysl relačních databází...) Příklad 6.3. Skládání v relační databázi studentů, jejich předmětů a fakult. Mějme dvě binární relace - jednu R přiřazující studentům MU kódy jejich zapsaných předmětů, druhou S přiřazující kódy předmětů jejich mateřským fakultám. Malý výsek z těchto relací může v tabulkové reprezentaci vypadat třeba následovně. student (učo) předmět (kód) 121334 MA010 133935 M4135 133935 IA102 155878 M1050 155878 IB000 předmět (kód) fakulta MU MAO 10 FI IB000 FI IA102 FI M1050 PřF M4135 PřF Jak z těchto „tabulkových" relací zjistíme, kteří studenti mají zapsané předměty na kterých fakultách (třeba na FI)? Jedná se jednoduše o složení relací S o R. V našem příkladě tabulkové reprezentace vyjde výsek: ____________________________ student (učo) fakulta MU 121334 FI 133935 FI 133935 PřF 155878 FI 155878 PřF 31 Zobecněné skládání relací V praktických použitích relačních tabulek povětšinou nevystačíme jen s binárními relacemi, takže je přirozené se ptát, jestli lze podobně skládat i více-ární relace. Odpověď je snadná - lze to a ani nepotřebujeme novou definici, vystačíme s tou, kterou už máme výše uvedenou. Fakt (skládání relací vyšší arity): Mějme relace T C K\ x K2 x ... x Kk a U C L\ x L2 x ... x Lg, přičemž pro nějaké m < mm(k,£) platí L\ = Kk-m+i, L2 = Kk_m+2, • • •, Lm = Kk. Pak relaci T lze složit s relací U na zvolených m složkách Li,... , Lm („překrytí") s použitím Dennice 6.2 takto: * Položme A = Kí x ... x Kk_m, B = Lx x ... x Lm a C = Lm+Í x ... x L£. * Příslušné relace pak jsou R = {(a, b) G A x B \ (cii,... cik-m, bi,... bm) G T} a S = {{b,Č) e B x C \ (bi,...bm,cm+i,...ce) G U}. * Nakonec přirozeně položme U om T ~ A o B, takže vyjde UomT = {(a, č) I ex. 6 e -B, že (ai,... ak-m, bi,...bm) G T a (61, Schematicky pro snažší orientaci ve složkách našich relací: Cm+i,...Ci) G U} . T C Kí x ... x Kk_mx Kk_m+i x ... x Kk U C Li x ... x Lm U om T C Kí x ... x Kk_m x ^____________j xL„ x Lr, iX...xL< Hx ... x L£ B C Opět je nejjednodušší si koncept skládání vícečetných relací ilustrovat příkladem. Příklad 6.4. Skládání v relační databázi pasažérů a letů u leteckých společností. Podívejme se na příklad hypotetické rezervace letů pro cestující, relace T. Jak známo (tzv. codeshare), letecké společnosti si mezi sebou „dělí" místa v letadlech, takže různé lety (podle kódů) jsou ve skutečnosti realizovány stejným letadlem jedné ze společností. To zase ukazuje relace U. T : pasažér datum let Petr 5.11. OK535 Pavel 6.11. OK535 Jan 5.11. AF2378 Josef 5.11. DL5457 Alena 6.11. AF2378 U datum let letadlo 5.11. OK535 CSA 5.11. AF2378 CSA 5.11. DL5457 CSA 6.11. OK535 AirFrance 6.11. AF2378 AirFrance Ptáme-li se nyní, setkají se Petr a Josef na palubě stejného letadla? Případně, čí letadlo to bude? Odpovědi nám dá zase složení relací U o2 T, jak je posáno výše. U00T Zkuste se zamyslet, lze tyto dvě relace skládat ještě jinak? Co by pak bylo významem? D pasažér letadlo Petr Josef CSA CSA 32 6.4 Skládání funkcí, permutace Soustřeďme se nyní na další oblast, kde běžně a přirozeně používáme skládání relací, aniž si to uvědomujeme. Fakt: Mějme zobrazení (funkce) / : A —► B a g : B —► C. Pak jejich složením coby relací v tomto pořadí vznikne zobrazení (g o f) : A —► C definované Í9°f)(x) =g(f(x)). Komentář: * Jak například na běžné kalkulačce vypočteme hodnotu funkce sin2 x ? Složíme (v tomto pořadí) „elementární" funkce f(x) = siná; a g(x) = x2. * Jak bychom na „elementární" funkce rozložili aritmetický výraz 2 log(a;2 + 1) ? Ve správném pořadí složíme funkce f\(x) = x2, f2(x) = x + 1, fz(x) = log x a fi(x) = 2x. * A jak bychom obdobně vyjádřili složením funkcí aritmetický výraz siná; + cosa;? Opět je odpověď přímočará, vezmeme „elementární" funkce g\{x) = siná; a g2{x) — COS X] 9-pak je „složíme" další funkcí h(x, y) = x + y. Vidíme však, že takto pojaté „skládání" už nezapadá hladce do našeho formalismu skládání relací. Pro nedostatek prostoru si skládání funkcí s více parametry nedefinujeme, ale sami vidíte, že obdobné skládání se v programátorské praxi vyskytuje doslova „na každém rohu" a ani se nad tím nepozastavujeme. Skládání permutací Po zbytek tohoto oddílu se zaměříme na permutace coby speciální případ (bijektivních) zobrazení. Definice: Nechť permutace tt množiny [1, n] je určena seřazením jejích prvků (p\,... ,pn)-Pak 7T je zároveň bijektivním zobrazením [l,n] —► [1, n] definovaným předpisem ir(i) = Pí. Tudíž lze permutace skládat jako relace podle Definice 6.2. Poznámka: Všechny permutace množiny [l,n] spolu s operací skládání tvoří grupu, zvanou symetrická grupa Sn. Permutační grupy (podgrupy symetrické grupy) jsou velice důležité v algebře, neboť každá grupa je vlastně isomorfní některé permutační grupě. Komentář: Příkladem permutace vyskytujícím se v programátorské praxi je třeba zobrazení i i—> (i + 1) mod n. Často se programátor setkává (aniž si to mnohdy uvědomuje) s permutacemi při indexaci prvků polí. V kontextu pohledu na funkce a jejich skládání coby relací si zavedeme jiný, názornější, způsob zápisu permutací - pomocí jejich cyklů. Definice: Nechť n je permutace na množině A. Cyklem v n rozumíme posloupnost (ai, a2, ■ ■ ■, ßfc) různých prvků A takovou, že 7r(aj) = ai+\ pro i = 1,2,...,k — 1 a 7i(ak) = ai. Jak název napovídá, v zápise cyklu (a\, a2, ■ ■ ■, au) není důležité, kterým prvkem začneme, ale jen dodržení cyklického pořadí. Cyklus v permutaci může mít i jen jeden prvek (zobrazený na sebe). 33 Komentář: Nakreslete si (vámi zvolenou) permutaci tt obrázkem, ve kterém vedete šipku vždy od prvku i k prvku tt(í). Pak uvidíte, že cykly dle naší definice jsou právě cykly tvořené šipkami ve vašem obrázku. S tímto grafickým zobrazením pro vás nebude problém pochopit následující tvrzení. Například permutaci (5, 3, 4, 8, 6,1, 7, 2) si lze obrázkem nakreslit takto: Věta 6.5. Každou permutaci n na konečné množine A lze zapsat jako složení cyklů na disjunktních podmnožinách (rozkladu) A. Důkaz: Vezmeme libovolný prvek a\ E A& iterujeme zobrazení a2 = ti"(«i), ci3 = 7r(a2); atd., až se dostaneme „zpět" k a,k+i = 7r(ak) = ci\. Proč tento proces skončí? Protože A je konečná a tudíž ke zopakování některého prvku ßfc+i musí dojít. Nadto je tt prostá, a proto nemůže nastat 7r(ak) = cij pro j > 1. Takto získáme první cyklus (a\,..., o^). Induktivně pokračujeme s hledáním dalších cyklů ve zbylé množině A \ {a\,..., a^}. dokud nezůstane prázdná. □ Značení permutací cykly: Nechť se permutace tt podle Věty 6.5 skládá z cyklů (ai,..., ßfc), (&!,..., bi) až třeba (z\,..., zm). Pak zapíšeme vr = ((ai,..., ak) (&!, ...,k)...{zi,...,zm)). Komentář: Primitivní pseudonáhodné generátory v počítačích iterují z náhodného počátku permutaci danou vztahem i i—> (i + p) mod q. Je pochopitelné, že tato permutace nesmí obsahovat krátké cykly, lépe řečeno, měla by se skládat z jediného (dlouhého) cyklu. (Pro úplnost, jedná se o permutaci množiny {0,1,... ,q — 1}). Příklad 6.6. Ukázka skládání permutací daných svými cykly. Vezměme 7-prvkovou permutaci (5, 3, 4, 2, 6,1, 7). Ta se rozkládá na tři cykly (1, 5, 6). (2, 3, 4) a (7). Jiná permutace (3, 4, 5, 6, 7,1, 2) se skládá z jediného cyklu (1, 3, 5, 7, 2, 4, 6). Nyní určíme složení těchto dvou permutací (zápisem cykly): «1,5,6)<2,3,4)<7»o ((1,3,5,7,2,4,6)) = «1, 4><2><3, 6, 5, 7)) (Nezapomínejme, že první se ve složení aplikuje pravá permutace!) Postup skládání jsme použili následovný: 1 se zobrazí v permutaci vpravo na 3 a pak vlevo na 4. Následně 4 se zobrazí na 6 a pak na 1. Tím „uzavřeme" první cyklus (1,4). Dále se 2 zobrazí na 4 a pak hned zpět na 2, tj. má samostatný cyklus. Zbylý cyklus (3, 6, 5, 7) určíme analogicky. D 6.5 Induktivní definice množin a funkcí Vzpomeňme si na definici posloupnosti rekurentním vztahem z Oddílu 3.5. Přímým zobecněním rekurentních definic je následující koncept. 34 Definice 6.7. Induktivní definice množiny. Jedná se obecně o popis (nějaké) množiny M v následujícím tvaru: • Je dáno několik pevných (bázických) prvků a\, a2, ■ ■ ■, a^ G M. • Je dán soubor induktivních "pravidel typu Jsou-li (libovolné prvky) x\,..., Xg G M, pak také y G M. V tomto případě je y typicky funkcí y = fi(x\,..., Xg). Pak naše induktivně definovaná množina M je určena jako nejmenší (inkluzí) množina vyhovující těmto pravidlům. Komentář: Vidíte podobnost této definice s uzávěrem relace? (Věta 5.7.) Pro nejbližší příklad induktivní definice se obrátíme na množinu všech přirozených čísel. -OéN - Je-li í € N, pak také í + 1 € N. Pro každé y € N můžeme definovat jinou množinu My C N induktivně takto: - y € My. - Jestliže x G My a x + 1 je liché, pak x + 2 e My. Pak například M3 = {3}, nebo M4 = {4 + 2í \ í € N}. Definice: Řekneme, že daná induktivní definice množiny M je jednoznačná, právě když každý prvek M lze odvodit z bázových prvků pomocí induktivních pravidel právě jedním způsobem. Komentář: Definujme množinu M C N induktivně takto: - 2,3 € M. - Jestliže x,y G M, pak také x2 + y2 a x.y jsou prvky M. Proč tato induktivní definice není jednoznačná? Například číslo 8 € M lze odvodit způsobem 8 = 2 • (2 • 2), ale zároveň zcela jinak 8 = 22 + 22. V čem tedy spočívá důležitost jednoznačných induktivních definic množin? Definice 6.8. Induktivní definice funkce z induktivní množiny. Nechť množina M je dána jednoznačnou induktivní definicí. Pak říkáme, že funkce T : M —► X je definována induktivně (vzhledem k induktivní definici M), pokud je řečeno: • Pro každý z bázických prvků a\,a2, ■ ■ ■ ,a^ G M je určeno T(ai) = Cí, kde c» je konstanta. • Pro každé induktivní pravidlo typu "Jsou-li (libovolné prvky) X\,..., Xg G M, pak také f(x\,..., Xg) G M" je definováno T( f(x\,..., xg)) na základě hodnot ^(xi),..., T{xg). Komentář: Pro příklad se podívejme třeba do manuálových stránek unixového příkazu test EXPRESSION: 35 EXPRESSION is true or false and sets exit status. It is one of: ! EXPRESSION EXPRESSION is false EXPRESSI0N1 -a EXPRESSI0N2 both EXPRESSI0N1 and EXPRESSI0N2 are true EXPRESSI0N1 -o EXPRESSI0N2 either EXPRESSI0N1 or EXPRESSI0N2 is true [-n] STRING the length of STRING is nonzero STRING1 = STRING2 the strings are equal Induktivní definice se „strukturální" indukcí Příklad 6.9. Jednoduché aritmetické výrazy Nechť (abeceda) E = {0,1, 2, 3, 4, 5, 6, 7, 8, 9, 0, ©, (,)}. Definujme množinu jednoduchých výrazů SExp C E* induktivně takto: - Dekadický zápis každého přirozeného čísla n je prvek SExp. - Jestliže x, y G SExp, pak také (x) © (y) a (x) © (y) jsou prvky SExp. (Jak vidíme, díky „závorkování" je tato induktivní definice jednoznačná.) Pro „vyhodnocení" výrazu pak definujme funkci Val: SExp —► N induktivně takto: - Bázické prvky: Val(n) = n, kde n je dekadický zápis přirozeného čísla n. - První induktivní pravidlo: Val((x) © (y)) = Val(x) + Val(y). - Druhé induktivní pravidlo: Val((x) © (y)) = Val(x) ■ Val(y). (Tímto způsobem jsme našim výrazům vlastně přiřadili jejich „význam", sémantiku.) □ Příklad 6.10. Důkaz správnosti přiřazeného „významu" Val: SExp —► N. Věta. Pro každý výraz s G SExp je hodnota Val(s) číselně rovna výsledku vyhodnocení výrazu s podle běžných zvyklostí aritmetiky. Jelikož pojednáváme o induktivně definované funkci Val, je přirozené pro důkaz jejích vlastností aplikovat matematickou indukci. Na rozdíl od dříve probíraných příkladů zde nevidíme žádný celočíselný „parametr nu, a proto si jej budeme muset nejprve definovat. Naši indukci tedy povedeme podle „délky í odvození výrazu s" definované jako počet aplikací induktivních pravidel potřebných k odvození s G SExp. Takto aplikované matematické indukci se často říká strukturální indukce. Důkaz: V bázi indukce ověříme vyhodnocení bázických prvků, což jsou zde dekadizké zápisy přirozených čísel. Platí Val(n) = n, což skutečně odpovídá zvyklostem aritmetiky. V indukčním kroku se podíváme na vyhodnocení Val((x) © (y)) = Val(x) + Val(y). Podle běžných zvyklostí aritmetiky by hodnota Val((x) © (y)) měla být rovna součtu vyhodnocení výrazu x, což je podle indukčního předpokladu rovno Val(x) (x má zřejmě kratší délku odvození), a vyhodnocení výrazu y, což je podle indukčního předpokladu rovno Val(y). Takže skutečně Val((x) © (y)) = Val(x) + Val(y). Druhé pravidlo Val((x) G (y)) se dořeší analogicky. D Rozšiřující studium 36 7 Jemný úvod do Logiky Úvod Základem přesného matematického vyjadřování je správné používání (matematické) logiky a logických úsudků. Logika jako filozofická disciplína se intenzívne vyvíjí už od dob antiky avšak ke skutečnému rozmachu logiky coby součásti matematiky došlo až začátkem 20. století. (S přispěním třeba Russelova paradoxu.) Dnes se samozřejmě základní logický kalkulus používá nejen v matematice, ale „stojí" na něm veškeré logické obvody a počítače. Proto se také studenti informatiky s logikou setkávají záhy při svém studiu a mnohokrát se k tématu také vracejí. Cíle Následující lekce přináší (skutečně velmi jemný a trochu i povrchní) úvod do moderní matematické logiky která je solidním základem matematiky a nakonec i celé informatiky. Zavedeme si základy výrokové logiky a výrokového počtu a velmi stručně si uvedeme problematiku predikátové logiky a kvantifikace. 7.1 Výroky v „přirozené" podobě Definice: V přirozené mluvě za výrok považujeme (každé) tvrzení, o kterém má smysl prohlásit, že je buď pravdivé nebo nepravdivé. Komentář: Několik příkladů, které z nich jsou výroky? * Dnes už v Brně pršelo. * Předmět IB000 se vyučuje v prvním ročníku. * Platí 2 + 3 = 6. * To je bez problémů. (Co?) * Platí x > 3. * Pro každé celé číslo x platí, že x > 3. Všimněte si, že pravdivost výroku by mělo být možné rozhodnout bez skrytých souvislostí (kontextu), a proto čtvrtý a pátý příklad za výroky nepovažujeme. Fakt: Z jednoduchých výroků můžeme vytvářet výroky složitější pomocí tzv. logických spojek. Komentář: Několik dalších příkladů. * Kateřina přijede ve 12:00 a půjdeme spolu do kina. * Množina {a, b} má více než jeden prvek a není nekonečná. * Jestliže má Karel přes 90 kilo váhy, nepojedu s ním výtahem. * Jestliže má kráva 10 nohou, mají všechny domy modrou střechu. Schopnost porozumět takovýmto větám je součást lidského způsobu uvažování a z tohoto hlediska nemá přímou souvislost s matematikou (je to „přirozená logika"). Formální (matematická) logika pak definuje jazyk matematiky a odstraňuje nejednoznačnosti přirozeného jazyka. 37 7.2 (Formální) výroková logika Definice 7.1. Syntaxe výrokové logiky. Buď AT = {A,B,C,...} spočetně nekonečná množina výrokových proměnných (tzv. atomů). Množina výrokových formulí í> je definována induktivně následujícími pravi-dly: (1) ÍTC$. (2) Jestliže ip,ip E í>, pak také -n(ip) 6 $ a (^ 4 (i/j) E í>. (3) Každý prvek í> vznikne konečně mnoha aplikacemi pravidel (1) a (2). Značení: Symbol -i je zván negací a =>- je nazýván implikací. Komentář: Příklady několika správně utvořených formulí: A, (A) => (B), ((A) => MB))) => (h(B)) => (C)) A také příklady několika ne zcela správně utvořených formulí: A =>B, A=>B=>C, ~^A=>B Konvence 7.2. Pro zvýšení čitelnosti budeme závorky vynechávat, pokud to nepovede k nejednoznačnostem za předpokladu, že negace -i má „vyšší prioritu" než =>. (Touto úmluvou se nemění množina í>; mění se jen způsob reprezentace jejích prvků. Dále si zavedeme, že *

if), *

ip), * p ^ r(p (ekvivalence) je jiný zápis formule (

- rtp) A (tp =>- (B))) => ((-i(B)) => (C)) se dá s naší konvencí zapsat jako (A^B)VBVC. Definice 7.3. Sémantika výrokové logiky. Valuace (ohodnocení) je funkce v : AT —► {true, false}.Pro každou valuaci v definujeme funkci Sv : í> —► {true, false} (vyhodnocení) induktivně takto: * SV(A) = u (A) pro každé A E AT. ~ , \ _ í true jestliže Sv(tp) = false; 1 false jinak. „ , ,, false jestliže Sv(tp) = trues, Sv(é) = false: * sv(tp => V) = { , •• i true jmak. Tvrzení 7.4. Důsledkem této definice je následovně: * Sv(

• r(p) = true právě když platí jedna z následujících podmínek - Sv(- B) V B V C? A B c A ^B (A^B)V BVG 0 0 0 1 1 0 1 0 1 1 1 0 0 0 0 1 1 0 1 1 0 0 1 1 1 0 1 1 1 1 1 0 1 0 1 1 1 1 1 1 D Definice: Formule

je splnitelná, pokud pro některou valuaci v platí, že Sv( je vždy pravdivá (také výroková tautologie), psáno |= - if). Tvrzení 7.6. Několik užitečných tautologií: * ^ AV^A * \= -n^Ao A * |= (A A (A => B)) => B * (=(-.£=> -lA) => (A => 5) 7.3 Jak správně „znegovať formuli"? Přesný význam formulí se zanořenými negacemi je někdy obtížné zjistit (podobně jako v běžné řeči). „ Není pravda, že nemohu neříct, že není pravda, že tě nemám nerad." Výrokové formule se proto obvykle prezentují v normálním tvaru, kde se negace vyskytují pouze u výrokových proměnných. Komentář: Například, pokud přijmeme pravidlo „dvojí negace" (-1-1A <^ A), tak výše napsanou větu si převedeme na lépe srozumitelný tvar: „Nemusím říct, že tě mám nerad." 39 Tvrzení 7.7. Každou výrokou formuli lze převést do normálního tvaru, pokud povolíme užívání odvozených spojek A a V. „Znegováním formule (A => B) je ekvivalentní AA->B, -i(CA(-iA => B)) je ekvivalentní Formální postup negace Metoda 7.8. Převod formule í> do normálního tvaru T{&). Definujeme funkce T a Q pro náš převod induktivními předpisy T{A) = A g(A) = ^a T^ip) = Q{*!>) = F{) G('P^Íj) = F(ip)AG(ip) J={ip Aip) = T{p) A T{$) 0() Ö( -i(B V -i(C => -^A))). Užitím postupu 7.8 získáme: JF(- -.(5 V -.(C => -.A)))) = Q{A^^{BV^{C^^Ä))) = 5(A)AÖ(n(BVn(C=> ^A))) = A A F(B V ^(C => ^A)) AA(f(B)VfKC^- iA))) = A A (B \J g(c ^ ^A)) aa{b\j {r{c) a g(^A))) a a (b v (c a f(A))) A A (B V (CA A)) Formuli A A (B V (C A A)) lze dále zjednodušit na (ekvivalentní) formuli A A (B V C). To ale je již z našeho pohledu matematicky neformální (heuristický) postup. Uvedené formální předpisy takto vyjadřují „intuitivní postup negace" v matematicky přesném tvaru. Věta 7.9. Pro libovolnou výrokovou formuli

A. • V indukčním kroku předpokládejme, že a) i b) platí pro všechny formule

- p2). Podle výše uvedeného induktivního předpisuje T{ý) = ^{pi =^ p2) = F{- T\p2)- Podle indukčního předpokladu jsou T{- F (^2) je v normálním tvaru dle definice a podle sémantiky =>- je ta ekvivalentní formuli (pí => p2) = ip. Obdobně rozepíšeme G(ift) = G(pi =>■ P2) = F{- p2, což jsme zde měli dokázat. * íp = (px \/p2). Zde si musíme opět uvědomit, že spojka V je pro nás jen zkratka, a přepsat tp = (—ic/?i =>- p2). Potom podle předchozích dokázaných případů víme, že F(r(p) = T{-^pi =>- p2) = ^{~^P\) =>■ ^(P2) je ekvivalentní formuli (-k/?i =>- ^2) = ^, což bylo třeba dokázat. Stejně tak G(ift) = G(~^Pi =>- ^2) = -^("^í) Aö(^) je podle předchozích případů důkazu ekvivalentní (~^pi A -1^2) = -,V'- * -0 = {(fi A (^2) a -0 = (<£i ^ ^2) už dokončíme analogicky. 7.4 Predikátová logika, kvantifikace Výše popsaná výroková logika je velmi omezená faktem, že každý výrok musí být („absolutně") vyhodnocen jako pravda nebo nepravda. Co když však chceme zpracovat tvrzení typu „den D v Brně pršelo" ? Jeho pravdivostní hodnota přece závisí na tom, co dosadíme za den D, a tudíž jej nelze považovat za výrok výrokové logiky. • Predikátová logika je obecnější než logika výroková] každá formule výrokové logiky je i formulí predikátové logiky, ale ne obráceně. • Predikátová logika pracuje s predikáty. Predikáty jsou „parametrizované výroky", které jsou buď pravdivé nebo nepravdivé pro každou konkrétní volbu parametrů. Výrokové proměnné lze chápat jako predikáty bez parametrů. Komentář: Pro neformální přiblížení si uvedeme několik ukázek predikátů: * x > 3 (parameterem je zde x), * R je ekvivalence na M (parametr R), * čísla x a y jsou nesoudělná (parametry x,y), * obecně psáno P(x,y). Definice 7.10. Syntaxe i sémantika predikátové logiky. Z predikátů lze vytvářet predikátové formule pomocí už známých (viz Definice 7.1) výrokových spojek a následujících tzv. kvantifikátorů: • \/x. p „pro každou volbu parametru x platí formule pu, • 3x . p „existuje alespoň jedna volba parametru x, pro kterou platí pu. Fakt: Je-li každá proměnná v dané formuli kvantifikovaná (tj. formule je uzavřená), pak je celá formule buď pravdivá nebo nepravdivá. 41 Konvence 7.11. Pro lepší srozumitelnost zápisu formulí predikátové logiky se domluvíme na následujícím. * Parametry vyskytující se v predikátech ve formuli

2) => Li(n). • Každé číslo n, které není prvočíslem, je dělitelné nějakým číslem y kde n ^ y a y > 1. VnGN. (-iPr(n) =>■ 3y . (y\n A n^y A y>l)). • Jsou-li R a S ekvivalence na M, je také R U S ekvivalence na M. Zde například můžeme mít dva pohledy na toto tvrzení - v jednom bereme množinu M za pevnou VE, S : (EqM(R)AEqM(S)) => EqM(RliS), kdežto ve druhém je i množina M parametrem VMVE,S : (Eq(M,R)AEq(M,S)) => Eq(M,RUS). D Jak „negovat" formule predikátové logiky? Metoda 7.13. Převod predikátové formule í> do normálního tvaru Jr(^). Dřívější Metodu 7.8 rozšíříme o následující indukční pravidla: Jr(P(xi,...,xn)) = P(xi,...,xn) G(P(xi,...,xn)) = ->P(xi,...,xn) TWx.tp) = Vx.T{ Eq(M,RUS)). Pak ^(^(VMVií,5 : (Eq(M,R)AEq(M,S)) => Eq(M,RUS))) = g(VMVR,S : (Eq(M,R)AEq(M,S)) => Eq(M,RuS)) 3M3R,S : Q((Eq(M, R) A Eq(M, S)) => Eq(M,RuS)) 3M 3R, S : (Eq(M, R) A Eq(M, S) A ~^Eq{M, RUS)). 42 Rozšiřující studium 8 Dokazování vlastností algoritmů Úvod Po předchozí převážně matematické látce se náš výklad obrací zase k informatice a navazuje na druhý pilíř celého předmětu z Lekce 1 - algoritmy a jejich zápis. Jak jste asi již poznali, umění programovat není zdaleka jen o tom naučit se syntaxi programovacího jazyka, ale především o schopnosti vytvářet a správně formálně zapisovat algoritmy. Přitom situace, kdy programátorem zapsaný algoritmus počítá něco trochu jiného, než si programátor představuje, je určitě nejčastější programátorskou chybou, o to zákeřnější, že ji žádný „chytrý" překladač nemůže odhalit. Proto již na počátku (seriózního) studia informatiky je dobré klást důraz na správné chápání zápisu algoritmů i na důkazy jejich vlastností a správnosti. A to je téma, kterému se tedy budeme věnovat po převážný zbytek předmětu IB000. Cíle IVa podkladě formálního zápisu algoritmů z Oddílu 1.3 si ukážeme, jak využít předchozí nabyté matematické znalosti při dokazování vlastností a správnosti různých jednoduchých algoritmů. (Nejčastějším nástrojem nám při tom bude matematická indukce.) 8.1 O „správnosti" programů Jak se máme přesvědčit, že je daný program „správný"? * Co třeba ladění programů? Jelikož počet možných vstupních hodnot je (v principu) neohraničený, nelze otestovat všechna možná vstupní data. * Situace je zvláště komplikovaná v případě paralelních, randomizovaných, interaktivních a nekončících programů (operační systémy, systémy řízení provozu apod.). Takové systémy mají nedeterministické chování a opakované experimenty tudíž vedou k různým výsledkům. (Nelze je rozumně ladit, respektive ladění poskytne jen velmi nedostatečnou záruku správného chování za jiných okolností.) * V některých případech je však třeba mít naprostou jistotu, že program funguje tak jak má, případně že splňuje základní bezpečnostní požadavky. Narůstající složitost programových systémů a zvýšené požadavky na jejich bezpečnost si vynucují vývoj „spolehlivých" formálních verifikačních metod. 8.2 Jednoduché indukční dokazování Pro svezení znalostí se nejprve podívejte zpět na naše konvence formálního zápisu algoritmů do Oddílu 1.3. Náš výklad začneme s několika skutečně jednoduchými algoritmy, jejichž jediný účel je v demonstraci využití matematické indukce pro dokazování vlastností. 43 Příklad 8.1. Zjistěte, kolik znaků 'x' v závislosti na celočíselné hodnotě n vstupního parametru n vypíše následující algoritmus. Algoritmus 8.2. for i<— 1,2,3,...,n-l,n do for j <— 1,2,3,...,i-l,i do vytiskni 'x' ; done done Nejprve si uvědomíme, že druhý (vnořený) cyklus vždy vytiskne celkem i znaků 'x'. Proto iterací prvního cyklu (nejspíše) dostaneme postupně 1 + 2 + ... + n znaků 'x' na výstupu, což již víme (Příklad 2.7), že je celkem \n(n + 1). Budeme tedy dokazovat následující tvrzení: Věta. Pro každé přirozené n Algoritmus 12.3 vypíše právě ^n(n+ 1) znaků 'x'. Důkaz: Postupujeme indukcí podle n. Báze pro n = 0 je zřejmá, neprovede se ani jedna iterace cyklu a tudíž bude vytištěno 0 znaků 'x', což máme dokázat. Nechť tedy tvrzení platí pro jakékoliv n0 a položme n = n0 + 1. Prvních n0 iterací vnějšího cyklu podle indukčního předpokladu vypíše (ve vnitřním cyklu) celkem ^no(n0 + 1) znaků 'x'. Pak již následuje jen jedna poslední iterace vnějšího cyklu s i ^n=n0+l a v ní se vnitřní cyklus j <— 1,2, . . . ,i=n iteruje celkem n = no + 1 -krát. Celkem tedy bude vytištěn tento počet znaků ' x': -n0(n0 + l) + n0 + l = -(n0 + l + l)(n0 + l) = -n(n + 1) Důkaz indukčního kroku je hotov. □ Příklad 8.3. Zjistěte, kolik znaků ' z' v závislosti na celočíselné hodnotě n vstupního parametru n vypíše následující algoritmus. Algoritmus 8.4. st ^"z"; for i<— 1,2,3,...,n-l,n do vytiskni řetězec s t; st <— st+st ; (zřetězení dvou kopií st za sebou) done Zkusíme-li si výpočet simulovat pro n = 0,1,2,3,4..., postupně dostaneme počty 'z' jako 0,1,3,7,15.... Na základě toho již není obtížné „uhodnout", že počet ' z' bude (asi) obecně určen vztahem 2n — 1. Toto je však třeba dokázat! Komentář: Jak záhy zjistíme, matematická indukce na naše tvrzení přímo „nezabírá", ale mnohem lépe se nám povede s následujícím přirozeným zesílením dokazovaného tvrzení: Věta. Pro každé přirozené n Algoritmus 8.4 vypíše právě 2n — 1 znaků 'z' a proměnná st bude na konci výpočtu obsahovat řetězec 2n znaků 'z'. Důkaz: Postupujeme indukcí podle n. Báze pro n = 0 je zřejmá, neprovede se ani jedna iterace cyklu a tudíž bude vytištěno 0 znaků 'z', což máme dokázat. Nechť tedy tvrzení platí pro jakékoliv no a položme n = no + 1. Podle indukčního předpokladu po prvních no iteracích bude vytištěno 2no — 1 znaků ' z' a proměnná st bude 44 obsahovat řetězec 2no znaků 'z'. V poslední iteraci cyklu (pro i ^n=n0+l) vytiskneme dalších 2ra° znaků 'z' (z proměnné st) a dále řetězec st „zdvojnásobíme". Proto po n iteracích bude vytištěno celkem 2n° — 1 + 2n° = 2no+1 — 1 = 2n — 1 znaků ' z' a v st bude uloženo 2 • 2no = 2n znaků ' z'. D 8.3 Algoritmy pro relace Relace jsou velice vhodnou strukturou pro algoritmické zpracování. Proto si uvedeme ukázky tří „abstraktních" algoritmů pro práci s relacemi, včetně jejich důkazů. (Pilní studenti si zajisté dokážou navrhnout sami i další podobné algoritmy.) Algoritmus 8.5. Symetrický uzávěr. Pro danou relaci R na n-prvkové množině A = {a\, a2, • • •, cin} vytvoříme její symetrický uzávěr R takto: R +- R; for i<— 1,2,...,n-l,n do for j <— 1,2,...,n-l,n do if (ai,a,j) G R A (a.,-, a;) G" R then i? <— R U{(ai, a»)} ; done done Důkaz: Zde není důkaz vůbec obtížný. Relace R je zřejmě symetrická, neboť (vnitřní) tělo cyklu pro všechny dvojice (a», a,j) G R přidá i (a,j, ai). Z druhé strany všechny dvojice „přidané" v R \R musí být obsaženy podle definice symetrické relace, takže i? je skutečně symetrickým uzávěrem podle definice uzávěru relace. □ Poznámka: Všimněte si, že jsme tento algoritmus zapsali abstraktně- vůbec jsme nekonkretizovali datové typy a struktury pro zápis relací. (Náš algoritmus jako takový tyto konkretizace nepotřebuje.) Na jednu stranu je to výhodné, neboť algoritmus můžeme pak použít na libovolně implementován relace. V neposlední řadě je takový abstraktní zápis i přehlednější a snadněji pochopitelný. Na druhou stranu však programátor sám musí teď zvolit vhodnou implementaci relace, například jako dvourozměrné pole R, kde R [i, j]=0 právě když (a», a.,-) $. R. Následně je třeba zdůvodnit i správnost zvolené implementaceQ). Algoritmus 8.6. Tranzitivní uzávěr. Pro danou relaci R na n-prvkové množině A = {a\, a2, ■ ■ ■, an} vytvoříme její tranzitivní uzávěr R+ takto: R+ i- R; for k<— 1,2,...,n-l,n do for i<— 1,2,...,n-l,n do for j <— 1,2,...,n-l,n do if (a,i,ak) G R+ A (dkjCij) G R+ then if (ai,aj)<^R+ then R+ <— R+ U {(ah a j)} ; fi done done Jak by se dala dokázat správnost popsaného algoritmu? Přímá aplikace indukce podle n nevypadá přínosně... (Zkuste si sami!) Nejkratší cesta k cíli vede použitím indukce 45 (podle proměnné k vnějšího cyklu) na vhodně zesíleném tvrzení. Pro jeho formulaci si definujeme, že relace S na A je k-částečně tranzitivní, pokud pro libovolná i, j a pro í < k platí, že z (a^ ae), (ae, aj) G S vyplývá (a», a,j) G S. (Všimněte si, že pro k = 0 tato definice neříká nic a pro k = n znamená běžnou tranzitivní relaci.) Věta. Po každých k > 0 iteracích vnějšího cyklu Algoritmu 8.6 aktuální hodnota relace R+ udává fc-částečně tranzitivní uzávěr relace R na A. Důkaz: Báze indukce pro k = 0 jasně platí, neboť věta v tom případě nic neříká. Předpokládejme nyní, že tvrzení platí pro nějaké k0 > 0 a dokažme jej i pro k = k0 +1. Zřejmě stačí uvažovat případ k0 < n. Každá dvojice (a^o,-) přidaná do R+ uvnitř cyklu musí náležet do fc-částečně tranzitivního uzávěru podle definice. Zbývá zdůvodnit, proč každá dvojice (a^, o,-) náležející do fc-částečně tranzitivního uzávěru, ale ne do fco-částečně tranzitivního uzávěru, bude do R+ v k-té iteraci přidána. Není těžké ověřit, že (a^o,-) náleží do fc-částečně tranzitivního uzávěru, právě když v relaci R nalezneme takovou cestu „po šipkách" z a^ do a,j, která přechází pouze přes prvky ag kde £ < k. V naší situaci vyplývá, že taková cesta musí použít i prvek au (jen jednou!), a proto (a,i,ak) i («fc,«?) náleží do fco-částečně tranzitivního uzávěru R. V k-té iteraci tudíž bude příslušná if podmínka splněná a (a^o,-) bude přidána do R+. □ Dokazování konečnosti algoritmu Komentář: Všimněte si, že jsme se zatím v důkazech vůbec nezamýšleli nad tím, zda náš algoritmus vůbec skončí. (To jistě není samozřejmé a důkaz konečnosti je nutno v obecnosti podávat!) Prozatím jsme však ukazovali algoritmy využívající jen for cykly, přitom podle naší konvence obsahuje for cyklus předem danou konečnou množinu hodnot pro řídící proměnnou, neboli náš for cyklus vždy musí skončit. Ale už v příštím algoritmu využijeme while cyklus, u kterého vůbec není jasné kdy a jestli skončí, a tudíž bude potřebný i důkaz konečnosti. Metoda 8.7. Důkaz konečnosti. Máme-li za úkol dokázat, že algoritmus skončí, postupujeme nejlépe následovně: * Sledujeme zvolený celočíselný a zdola ohraničený parametr algoritmu (třeba přirozené číslo) a dokážeme, že se jeho hodnota v průběhu algoritmu neustále ostře zmenšuje. * Případně předchozí přístup rozšíříme na zvolenou k-tici přirozených parametrů a dokážeme, že se jejich hodnoty v průběhu algoritmu lexikograficky ostře zmenšují. Pozor, naše „parametry" vůbec nemusejí být proměnnými v programu. Algoritmus 8.8. Cykly permutace. Pro danou permutaci tt na n-prvkové neprázdné množině A = {1,2,... ,n} vypíšeme její cykly (viz Oddíl 6.4) takto: U ^ {1,2,. ..,n}; while U^ 0 do x <— min(U); (nejmenší prvek množiny) začínáme výpis cyklu ' (' ; while xGU do vytiskneme x; 46 U i- U\{x} ; x i- vr(x) ; done ukončíme výpis cyklu ')' ; done Jak dokážeme správnost tohoto algoritmu? Opět platí, že přímá aplikace indukce podle n nepřinese nic podstatného. Důkaz si tentokrát rozdělíme na dvě části (podle dvou while cyklů). Všimněte se navíc, že tentokrát je nezbytnou součástí důkazu správnosti algoritmu i důkaz, že oba while cykly vždy skončí. Věta. Za předpokladu, že vnitřní while cyklus pro jakoukoliv počáteční volbu x skončí, vypíše cyklus permutace tt obsahující x a odebere všechny prvky tohoto cyklu z množiny U, Algoritmus 8.8 vždy skončí se správným výsledkem. Důkaz: Postupujeme indukcí podle počtu cyklů v permutaci tt. Jediný cyklus v tt (báze indukce) je vypsán dle předpokladu věty a množina U zůstane prázdná, tudíž vnější while cyklus skončí po první iteraci a výsledek je správný. Podle Věty 6.5 se každá permutace dá zapsat jako složení disjunktních cyklů. Nechť tt je tedy složena z í > 1 cyklů. Po první iteraci while cyklu zbude v restrikci permutace tt na množinu U celkem í — 1 cyklů. Podle indukčního předpokladu pak tyto zbylé cykly budou správně vypsány a algoritmus skončí. □ Komentář: Vidíte, že v tomto důkaze indukcí je indukční krok zcela triviální a důležitý je zde především základ indukce? Věta. Pokud tt je permutace, tak vnitřní while cyklus vždy skončí a nalezne v tt cyklus obsahující libovolný počáteční prvek x G U. Navíc všechny prvky nalezeného cyklu odebere z množiny U. Důkaz: Zde přímo zopakujeme argument důkazu Věty 6.5: Vezmeme libovolný prvek x = X\ G A a iterujeme zobrazení xi+\ = tt(xí) pro i = 1, 2..., až dojde ke zopakování prvku Xk = Xj pro k > j > 1. (To musí nastat, neboť A je konečná.) Jelikož prvek x j byl již odebrán z U, v kroku x = Xk dojde k ukončení našeho while cyklu. Nadto je tt prostá, a proto nemůže nastat Xk = Xj = tt(xj-\) pro j > 1. Takto byl nalezen a odebrán z U cyklus (ai,..., ßfc-i) a důkaz je hotov. □ 8.4 Zajímavé algoritmy aritmetiky Pro další ukázky důkazových technik pro algoritmy se podíváme na některé méně známé krátké algoritmy z oblasti aritmetiky. Například celočíselné umocňování na velmi vysoké exponenty je základem známé RSA šifry: Algoritmus 8.9. Binární postup umocňování. Pro daná číslo a, b vypočteme jejich celočíselnou mocninu (omezenou na zbytkové třídy modulo m kvůli prevenci přetečení rozsahu celých čísel v počítači), tj. c = ab mod m. c<-l; while 1 o> 0 do if b mod 2 > 0 then C 4— (c- a) mod m; b 4- - Lb/2J ; a 4— (a-a) mod m ) done výsledek c ; 47 Zde použijeme k důkazu správnosti algoritmu indukci podle délky í binárního zápisu čísla 6. Věta. Algoritmus 8.9 skončí a vždy správně vypočte hodnotu mocniny c = ab mod m. Důkaz: Báze indukce je pro í = 1, kdy 6 = 0 nebo 6=1. Přitom pro 6 = 0 se cyklus vůbec nevykoná a výsledek je c = 1. Pro 6 = 1 se vykoná jen jedna iterace cyklu a výsledek je c = a mod m. Nechť tvrzení platí pro £0 > 1 a uvažme í = £0 + 1. Pak zřejmě 6 > 2 a vykonají se alespoň dvě iterace cyklu. Po první iteraci bude a' = a2, b' = [b/2\ ac' = (abmod2) mod m. Tudíž délka binárního zápisu b' bude jen £0 a podle indukčního předpokladu zbylé iterace algoritmu skončí s výsledkem c = c' ■ a'b' mod m = (abmod2 ■ a2^2^ mod m = ab mod m. D Na závěr lekce si ukážeme jeden netradiční krátký algoritmus a jeho analýzu a důkaz ponecháme zde otevřené. Dokážete popsat, na čem je algoritmus založen? Algoritmus 8.10. Celočíselná odmocnina. Pro dané číslo x vypočteme dolní celou část jeho odmocniny r = [^/x\ ■ p^x; r^O; while p > 0 do while (r + p)2 < x do r <— r+p ; p ^ Lp/2J ; done výsledek r ; Poznámka: Zamysleli jste se, jaký mají algoritmy v tomto oddíle vlastně význam? Vždyť stejné úlohy jistě sami vyřešíte každý jednou jednoduchou for smyčkou. Podívejte se však (alespoň velmi zhruba) na počet kroků, které zde uvedené algoritmy potřebují vykonat k získání výsledku, a srovnejte si to s počty kroků oněch „jednoduchých" algoritmů. Pro skutečně velká vstupní čísla zjistíte propastný rozdíl - s takovým „jednoduchým" algoritmem, třeba 'for i <— 1, . . .b do c <— c-amodm done', se pro obrovské hodnoty b výsledku nikdy nedočkáte, kdežto Algoritmus 8.9 stále poběží velmi rychle. (Spočítáte, jak rychle?) Rozšiřující studium 9 Jednoduchý deklarativní jazyk Úvod Pokračujeme dále v tématu předchozí lekce, tj. budeme se zabývat matematickým dokazováním vlastností a správnosti algoritmů. Třebaže mnohým mohla přijít už Lekce 8 více než dost formální, není tomu úplně tak; nyní si ukážeme (ještě) přesnější přístup založený na myšlenkách funkcionálního programování. 48 Cíle Naším hlavním cílem je podání matematicky zcela přesné definice jednoduchého deklarativního „programovacího" jazyka pro potřeby formálního dokazování příslušně zapsaných algoritmů. (Na tomto jazyce pak v příští lekci postavíme přehled důkazových technik pro algoritmy.) O „správnosti" programů, podruhé Vraťme se k otázce, jak se máme přesvědčit, že program funguje „správně"? * V některých případech, jak už jsme zmínili, je třeba mít naprostou jistotu, že program funguje tak jak má, například v řídících systémech, na nichž závisí lidské životy. V takovém případě je jedinou „dostatečně spolehlivou" možností podat formální matematický důkaz chování algoritmu. * A co tedy důkazy vlastností symbolicky zapsaných (procedurálních) algoritmů z Lekce 8? Všimli jste si, co v nich bylo problematickým bodem? Náš procedurální zápis algoritmu totiž přesně nedefinuje, co je to „elementární krok" výpočtu - to je sice většinou docela zřejmé, někdy však může hlavní problém nastat právě zde. Sice by bylo možné použít k definici některý z přesných teoretických modelů výpočtu jako je Turingův stroj (nebo třeba i některý vhodný z reálných programovacích jazyků), avšak pak by se formální důkazy staly velmi složitými. * Vhodnějším řešením (pro potřeby formálního dokazování) se jeví příklon k „funkcionálnímu" zápisu algoritmů pomocí matematicky zcela přesných deklarací 9.1 Popis jednoduchého deklarativního jazyka Z těchto výše popsaných důvodů se nyní soustředíme na podání matematicky zcela přesné definice jednoduchého deklarativního „programovacího" jazyka. Začneme jeho syntaxí a poté přejdeme k jeho sémantice - tedy k formalizaci takto zapsaných pojmů „výpočetního kroku" a „výpočtu". Definice 9.1. Deklarativní programovací jazyk (pro přednášky IB000). * Nechť Var = {x, y, z,...} je spočetná množina proměnných. * Nechť Num = {0,1,... 52,... 397,...} je množina všech dekadických zápisů přirozených čísel. * Nechť Fun = {f, g, h,...} je spočetná množina funkčních symbolů. Ke každému / G Fun je přiřazeno číslo a G N, které nazýváme arita f. Dále předpokládáme, že pro každé a G IN existuje nekonečně mnoho / G Fun s aritou a. * Množina výrazů Exp je (induktivně) definována následující abstraktní syntaktickou rovnicí: £ ::= x | n E\ + £-2 | E\ — £-2 | E\ * £-2 | E\ -ŕ- £2 (E\ J /(£i, ••-,£„) if Ei then £2 else £3 V uvedené rovnici je x G Var, n G Num, Ei G Exp jsou výrazy, / G Fun a a G IN je arita funkce /. 49 Poznámka: Takováto specifikace syntaxe je abstraktní v tom smyslu, že se nezabývá tím, jak výrazy jednoznačně zapsat do řádku jako posloupnost symbolů. Je na nás, abychom napsali dostatečně mnoho závorek a případně stanovili prioritu operátorů tak, aby bylo zcela jasné, jak daný výraz podle uvedené rovnice vznikl. (Ve smyslu Lekce 6 tato induktivní definice není jednoznačná. To nám však nebude v Definici 9.2 vadit.) Komentář: Pro lepší pochopení uvádíme několik příkladů výrazů (Exp) z definice. . 254 . 2 + 3*4 • /(2)-<7(5) . f(2 + x,g(y,3*y)) • if x — 1 then (2 + f (y)) else g(x, x) (Vyhodnocení podmínky v „if" testuje nenulovost argumentu.) Definice: Deklarace (v jazyce Definice 9.1) je konečný systém rovnic tvaru fi(xi,---,xai) = Ex : : ; jn\Xl-, ■ ■ ■ ,Xan) ĽJn kde pro každé 1 < i < n platí, že f i G Fun je funkce arity G Var jsou proměnné a Ei je výraz, v němž se mohou vyskytovat pouze proměnné Xi,... , xai a funkční symboly fu ... , fn. Komentář: Opět uvádíme pro osvětení několik příkladů deklarací z naší definice. • f(x) = if x then x * f (x — 1) else 1 f (x) = g(x-l,x) g(x,y) = if a; then f (y) else 3 (Jak uvidíme formálně později, konvencí našich výpočtů je neužívat záporná čísla, místo toho 0-l„="0.j • g(x, y) = if x — y then x else y • fix) = f{x) (Nezapisuje toto náhodou „nekonečnou smyčku"?) Deklarace tedy udává „soubor pravidel", podle kterých vyhodnocujeme (Definice 9.2) daný výraz. Jinak také lze deklaraci chápat jako zobecnění rekurentních defínic funkcí. 9.2 Formalizace pojmu „výpočet" Za výpočet (nad A) budeme považovat posloupnost úprav výrazů, které jsou „postaveny" na naší uvažované deklaraci A. To je formálně podchyceno následujícíma dvěma definicema. Definice: Buď A deklarace. Symbolem Exp (A) označíme množinu všech výrazů E, které splňují zároveň tyto dvě podmínky: - E neobsahuje žádnou proměnnou. 50 - Jestliže E obsahuje funkční symbol /, pak / byl v A deklarován (tj. na levé straně některé rovnice A). Fakt: Množinu Exp (A) lze definovat také induktivně: E ::= n | (£i) \ E\ + E2 \ E\ — E2 \ E\ * E2 \ E\ -ŕ- E2 f(E1}- ■■ ,Ea) I if £1 then E2 else £3 V uvedené zápise je n G Num, f G Fun je funkční symbol deklarovaný v A a a G IN je arita tohoto /. Definice 9.2. Výpočet a krok výpočtu v našem deklarativním jazyce. Funkci „krok výpočtu" 1—> : Exp (A) —► Exp (A) definujeme induktivně takto; místo *—*(E) = F budeme psát E\—*F. • ni—>n pro každé n G Num. • Pro E = (.Ei) definujeme krok výpočtu takto: * Jestliže E\\-^F G Num, pak (£1)1—>£. * Jestliže Ei\—*F G" Num, pak (£1)1—>■(£). • Pro E = E\ + E2 definujeme krok výpočtu takto: * Jestliže Ei,E2 G Num, pak Ex + £2i—>z, kde z je dekadický zápis čísla Ex + E2. * Jestliže Ei G" Num, pak Ex + £2i—>£ + £2, kde E1>-^F. * Jestliže Ei G iVwm a £2 G" Num, pak £: + E2>—>E1 + F, kde £2i—>■£. • Pro E = E1 — E2 definujeme krok výpočtu takto: * Jestliže E\,E2 G Num, pak £1—£2i—>z, kde z je dekadický zápis čísla max{0, E\ — E2}. (Pozor na nezápornost výsledku odčítání!) * Jestliže Ei G" Num, pak Ei - £2i—>■£ - E2, kde EX\-^F. * Jestliže Ei G Num a E2 G" iVwm, pak Ei — E2i—*Ei — F, kde E2\—*F. • Pro E = Eí * E2 definujeme krok výpočtu takto: * Jestliže Ei,E2 G iVwm, pak Ex * £2i—>z, kde z je dekadický zápis čísla Ex * £2. * Jestliže Ei G" iVwm, pak E^ * E2\—>F * £"2, kde EX\-^F. * Jestliže Ei G Num a £2 G" Num, pak £1 * E2\—>Ei * F, kde E2\—>F. • Pro E = E1 -^- E2 definujeme krok výpočtu takto: * Jestliže Ei,E2 G Num, pak £1 4- £2i—>z, kde z je dekadický zápis (celé části) čísla \Ei/E2\. Pokud E2 = 0, je z = 0 (dělení nulou!). * Jestliže Ei G" Num, pak £: 4- £2i—>■£ 4- £2, kde ü^i—>F. * Jestliže £1 G iVwm a £2 G" iVwm, pak Ei 4- £2i—>£i 4- F, kde £2i—>£. • Pro £7 = if .Ei then E2 else E73 definujeme krok výpočtu takto: * Jestliže £1 G iVwm a £1 = 0, pak if Ex then £2 else £3i—>£3. * Jestliže £1 G iVwm a £1 ^ 0, pak if £1 then £2 else £3i—>£2. 51 * Jestliže Ei ^ Num, pak if Eľ then E2 else £73i—>if F then E2 else E3, kde Ex\-+F. • Pro £7 = f (Ei, • • •, £7fc) definujeme krok výpočtu takto: * Jestliže Ei,- ■ ■ ,Ek e Num, pak f(Ex,- ■ ■ ,Ek)<-^(Ef(xi \EX,- ■ ■ ,xk \Ek)). (V tomto formálním zápise se jedná o prosté „textové" dosazení hodnot Ei za proměnné x i v deklaraci E f funkce / v A.) * Jinak f (Ei, ■ ■ ■, Ek)\-^-f(Ei, ■ ■ ■, Ei_i, F, Ei+Í, ■ ■ ■, Ek), kde i je nejmenší index pro který platí Ei ^ Num a Ei\—*F. V zápise jednotlivých bodů vždy platí, že E\,E2,... G Exp (A). Znak = zde znamená „textovou" rovnost na množině výrazů Exp. Při nejednoznačnosti vždy aplikujeme první použitelné pravidlo naší definice. Reňexivní a tranzitivní uzávěr relace i—> značíme i—>* („výpočet). Tato rozsáhlá a důležitá definice si zaslouží několik podstatných připomínek. Za prvé si dobře povšimněte některých „aritmetických" aspektů výpočtu. Výsledek odečítání je vždy nezáporný, neboli všechna záporná čísla jsou nahrazena nulou. - Výsledek dělení je vždy celočíselný, počítáme jeho dolní celou část. - Dělení nulou je definováno (není chybou), výsledkem je opět nula. Další připomínka se týká pořadí vyhodnocování ve výrazu -- to je přesně dáno pořadím pravidel v Definici 9.2, neboli vždy aplikujeme první pravidlo, které aktuálně lze použít na výraz E, a to na prvním možném místě. Mimo jiné je takto „definována" nejvyšší priorita vyhodnocení uzávorkovaného výrazu. Uvědomte si dobře, že definice výpočetního kroku i—> je (poněkud skrytě) rekurzivní. Třeba krok (2 * l)i—>2jeve skutečnosti jediným krokem, přestože „vyvolá" použití dvou pravidel v sobě - vyhodnocení součinu i odstranění závorek. Ještě si uveďme, že naše definice připouští jistý nedeterminismus (poznámka jen pro čtenáře, kteří o nedeterminismu už slyšeli): Je možné mít v deklaraci A zadaných více rovnic pro tutéž funkci /(), pak se však z i—> stává pouhá relace. My se touto možností nebudeme zabývat. 9.3 Příklady výpočtů a důkazů Příklad 9.3. Ukážeme si několik ilustrativních „výpočtů" nad různými deklaracemi. Uvažme deklaraci f(x) = if x then x * f (x — 1) else 1. Pak třeba /(3)i—>*6, neboť /(3) i-^ if 3 then 3 * /(3 - 1) else 1 i->- 3 * /(3 - 1) i-> 3 * /(2) (->■ 3 * (if 2 then 2* f (2- 1) else 1) i->- 3 * (2 * /(2 - 1)) i-> 3* (2*/(l)) (->■ 3 * (2 * (if 1 then 1 */(l - 1) else 1)) (->■ 3* (2* (1* f (1-1))) \-> 3*(2*(l*/(0))) (->■ 3*(2*(l*(if0 then 0*/(0-l) else 1))) i-» 3 * (2 * (1 * 1)) i-> 3* (2*1) i-^3*2 i-^6. Uvažme deklaraci f (x) = g (x — l,x) a g(x,y) = if x then f (y) else 3. Pak například /(3)—*/(3), neboť /(3)i->0(3 - 1, 3)\-*g(2, 3)i->if 2 then /(3) else 3i->/(3). 52 Uvažme deklaraci f (x) = f (x). Pak pro každé n G Num platí /(n)i—>/(n) a podobně /(/(n))~/(/(n)). Ale/(/(2 + 3))^/(/(5))^/(/(5)). D Důkaz správnosti programu Celá naše formalizace deklarativního jazyka směřuje k přesným matematickým důkazům algoritmů, takže si takové hned názorně ukážeme. Příklad 9.4. Pro ukázku uvažme deklaraci A obsahující pouze rovnici f(x) = if x then x * f (x — 1) else 1. Věta. Pro každé n G N platí /(n)i—>*m, kde m = n\. Důkaz povedeme indukcí podle n: . Báze n = 0. Platí /(O) ^ if 0 then 0 * /(O - 1) else lwla platí 0! = 1. • Indukční krok. Nechť n + 1 = k. Pak /(k) ^ if k then k * /(k - 1) else 1 ■->• k * /(k - 1) ■->• k * /(w). kde w = k — 1 = n. Podle LP. platí /(w) i—>* u, kde u = n\. Proto k * /(w) i—>*k * uh-»v, kde v = (n + 1) • n\ = (n + 1)!. n Komentář: Vidíte, jak „hutný" a přitom formálně zcela přesný zápis důkazu naše formalizace umožňuje? Promyslete si podrobně všechny jeho kroky ještě jednou a dobře si uvědomte, co z čeho vyplývá a jak na sebe navazují. Důkazy „neukončenosti" výpočtů Jinou otázkou je, jak zdůvodnit, že některý výpočet neskončí. K tomu využijeme následující tvrzení: Věta 9.5. Buď A deklarace. Pro každé i G IN definujeme relaci \—>l C Exp(A) x Exp(A) předpisem \—>l = j—> o • • • o i—>. Dále definitoricky klademe \—>° = {(E,E) \ E G i Exp (A)}. Pak (relace „výpočet") platí \—>* = U^o1-*'*- Podle předchozí věty platí, že E\—**F právě když E\-^-lF pro nějaké ígN. Navíc musí existovat nejmenší i s touto vlastností. Toto pozorování bývá velmi užitečné v důkazech „neukončenosti" výpočtů. Příklad 9.6. Uvažme deklaraci f(x) = f(x). Věta. Pro každé n G Num platí, že neexistuje žádné m G Num takové, že /(n)i—>*m. Důkaz sporem: Předpokládejme, že existují n, m G Num takové, že /(n)i—>*m. Pak existuje nejmenší i G N takové, že /(n)i—>lm. Jelikož výrazy /(n) a m jsou různé, platí i > 0. Jelikož i—>l = i—>l~1o\—> a /(n)i—>/(n), platí /(n)i—»t_1m, což je spor s minimalitou i. □ Rozšiřující studium 53 10 Důkazové postupy pro algoritmy Úvod Nyní si ukážeme, jak formální deklarativní jazyk z Lekce 9 využít k formálně přesným induktivním důkazům vybraných algoritmů. Dá se říci, že tato lekce je „vrcholem" v naší snaze o matematické dokazování algoritmů v informatice. Cíle IVa podkladě jednotlivých variant důkazů matematickou indukcí z Lekce 2 si ukážeme přehled formálních indukčních důkazových technik aplikovaných na vybrané algoritmy (v zápisech deklarativního jazyka). 10.1 Technika „fixace parametru" Tato technika je vhodná pro případy, kdy je sice v algoritmu více parametrů, ale „zjevně" dochází ke změně jen jednoho (nebo části) z nich a chování algoritmu ke zbylým „neměnným" parametrům je dobře „předvídatelné". Příklad 10.1. Uvažme deklaraci A obsahující pouze rovnici g(x, y) = if x then y + g (x — 1, y) else 0 . Věta. Pro každé m, n G IN platí g(m, n) i—>* z, kde z = m ■ n. Důkaz: Budiž n G N libovolné ale pro další úvahy pevné. Dokážeme, že pro každé m G IN platí g(m, n) i—>* z, kde z = m ■ n, indukcí vzhledem k m. * Báze m = 0. Platí g(0, n) i—> if 0 then n + g(0 — 1, n) else 0 i—> 0. * Indukční krok. Nechť m + 1 = k. Pak g (k, n) i—> if k then n + g (k — 1, n) else 0i->n + g (k — 1, n) i—> n + g(w, n). kde je w = m. Podle LP. platí * u pro u = m-n. Dále n+g(w, n) i—>* n + u i—> v. kde v = n+(m-n) = (m+í)-n = k-n, a tím jsme dohromady hotovi s důkazem g (k, n) i—>* vj 10.2 Technika „indukce k součtu parametrů" Toto lze použít především v případech, kdy se v průběhu algoritmu vždy některý parametr zmenšuje, ale pokaždé je to některý jiný parametr, takže v indukci se nelze zaměřit jen na jeden z nich. Příklad 10.2. Uvažme deklaraci A obsahující pouze rovnici g(x, y) = if x then (if y then g (x — 1, y) + g (x, y — 1) eise 0) eise 0 . Věta. Pro každé m, n G IN platí g(m, n) i—>* 0. 54 Tvrzení této věty přímo nelze dokázat indukcí vzhledem k m, ani indukcí vzhledem k n, neboť u žádného z m,n nemáme zaručeno, že se vždy zmenší. Důkaz lze ovšem postavit na faktu, že se vždy zmenší alespoň jeden z m, n, neboli se vždy zmenší součet m a n. To znamená, že výše uvedené tvrzení nejprve přeformulujeme do následující (matematicky ekvivalentní) podoby: Věta. Pro každé i E N platí, že jestliže i = m + n pro kterákoliv m, n G N. pak g(m, n) i—>* 0. Důkaz indukcí vzhledem k i: Báze i = 0 znamená, že 0 = m + n pro m, n G N, neboli m = n = 0. Dokazujeme tedy, že g(0, 0) i—>* 0. Platí 0(0, 0) ■->■ if 0 then (if 0 then #(0-1,0)+ g(0, 0-1) else 0) else 0 ■->■ 0 . Indukční krok. Nechť i + 1 = m+n, kde m, n G N. Nyní rozlišíme tři možnosti (z nichž první dvě jsou svým způsobem jen rozšířeními předchozí báze indukce): * Pro m = 0 platí g(0, n) i—> if 0 then (if n then g(0 — 1, n) + g(0, n — 1) else 0) else 0 i—> 0 . * Pro m > 0, n = 0 platí fif(m, 0) i—> if m then (if 0 then g(m — 1,0)+ g(m, 0 — 1) else 0) else 0 i—> i—> if 0 then g(m — 1,0)+ g(m, 0 — 1) else 0 i—> 0 . * Pro m > 0, n > 0 platí gr(m, n) i—> if m then (if n then g(m — 1, n) + g(m, n — 1) else 0) else 0 i—> i—> if n then g(m — 1, n) + #(m, n — 1) else 0 i—> #(m — 1, n) + g(m, n — 1). Podle LP. platí g(m — 1, n) i—>* 0 a současně g(m, n — 1) i—>* 0, proto fif(m - 1, n) + (/(m, n - 1) i—>* 0 + ^(m, n - 1) i—>* 0 + 0i->0. Tím jsme s důkazem matematickou indukcí hotovi. □ Zajímavější verze Udělejme si předchozí nudný příklad trochu zajímavějším (ale co se týče důkazu stále v podstatě stejným...). Příklad 10.3. Uvažme deklaraci A obsahující pouze rovnici g(x,y) = if x then (if y then g (x — 1, y) + g(x,y — 1) eise 1) eise 1. Věta. Pro každé m, n G N platí g(m, n)i—>*k, kde k = [^j (kombinační číslo). 55 Toto tvrzení opět budeme dokazovat indukcí vzhledem k i = m + n. Vzpomeňte si nejprve na známý Pascalův trojúhelník kombinačních čísel, který je definovaný rekurentním vztahem fa + l\ ( a \ (a\ \b+l) = \b+l) + \b)' Nepřipomíná to trochu naši deklaraci? Je však třeba správně „nastavit" význam parametrů a, b. Důkaz indukcí vzhledem k i: Báze i = 0 znamená, že 0 = m + n pro m, n G N, neboli m = n = 0. Dokazujeme tedy, že g(0, 0) i—>* 1. Platí 0(0, 0) ■->■ if 0 then (if 0 then #(0-1,0)+ g(0, 0-1) else 1) else 1 ■->■ 1. Indukční krok. Nechť i+ 1 = m + n, kde m, n G N. Opět rozlišíme stejné tři možnosti: * Pro m = 0 platí g(0, n) i—> if 0 then (if n then g(0 — 1, n) + g(0, n — 1) else 1) else 1 i—> 1. * Pro m > 0, n = 0 platí fif(m, 0) i—> if m then (if 0 then g(m — 1,0)+ g(m, 0 — 1) else 1) else 1 i—> i—> if 0 then g(m — 1,0)+ #(m, 0 — 1) else 1 i—> 1. * Pro m > 0, n > 0 platí gr(m, n) i—> if m then (if n then g(m — 1, n) + #(m, n — 1) else 1) else 1 i—> i—> if n then g(m — 1, n) + g(m, n — 1) else 1 i—> #(m — 1, n) + g(m, n — 1). Podle LP. platí g(m - 1, n) i—>* kí, kde ki = (m?^™71), a současně #(m, n - 1) i—>* k2, kde k2 = (m^_1)- Přitom z Pascalova trojúhelníka plyne im + n — 1 \ /m + n — 1 \ __ (m + n — 1 + l\ __ (m + n\ \ m — l ) \ m / \ m / \ m ' a proto g (m — 1, n) + g(m, n - 1) i—>* kí + k2 i—>* k = D 10.3 Technika „zesílení dokazovaného tvrzení" Velmi častou situací při dokazování algoritmu je, že se zajímáme o hodnoty některých proměnných nebo „výstupy" některé funkce, ale ke správnému matematickému důkazu musíme „postihnout" i chování jiných funkcí a proměnných v algoritmu. Taková situace pak typicky vede na potřebu zesílení požadovaného tvrzení v matematické indukci. Příklad 10.4. Uvažme deklaraci A obsahující tyto rovnice: 56 f (x) = if x then h(x) else 1 h(x) = if x then f(x—l) + h(x — 1) else 1 Věta. Pro každé n G N platí /(n)i—>*m, kde m = 2n. Požadované tvrzení bohužel nelze přímo dokázat indukcí podle n. Řešením je přeformulování dokazovaného tvrzení do silnější podoby, kterou již indukcí dokázat lze: Věta. Pro každé n G N platí /(n) i—>* m a h(n) \—>* m, kde m = 2n. Důkaz, již poměrně snadno indukcí vzhledem k n: * Báze n = 0. Platí /(O) ^ if 0 then h(0) else 1^1, h(0) ^ if 0 then /(O - 1) + h(0 - 1) else 1^1. * Indukční krok: Nechť n + 1 = k, pak platí /(k) i—> if k then h(k.) else 1 i—> h(k.) \—> ^ if k then /(k- 1) + h(k- 1) else li->/(k-l) + h(k- 1) •-»• /(w) + h(k- 1). kde w = k — 1 = n. Podle LP. platí /(w) i—>* m, kde m = 2n. Zároveň také (naše „zesílení") platí i h(w) \—>* m, a proto /(w) + /?,(w) i—>* m + /?,(w) i—>* m + m i—> q . kde q = m + m = 2m = 2 • 2ra = 2ra+1 = 2fc. Proto tranzitivně /(k) i—> q a první část našeho tvrzení platí i pro n + 1 = k. Podobně je třeba ještě dokončit druhou část tvrzení. h(k) ^ if k then f (k - 1) + fr(k - 1) else 1 ■-> /(k - 1) + fc(k - 1) ^* /(w) + fe(k - 1) ; kde w = k — 1 = n. Podle LP. platí /(w) i—>* m, kde m = 2n, a také /i(w) i—>* m, a proto /(w) + h(w) i—>* m + m i—> q . kde q = m + m = 2-2n = 2n+l = 2k. Proto h(k) \—> q a i druhá část našeho tvrzení platí pro n + 1 = k. □ 10.4 Dva „klasické" algoritmy Již z dávných dob antiky pochází tento zajímavý a koneckonců velmi jednoduchý algoritmus teorie čísel. (Víte, jestli tehdy vůbec mluvili o algoritmech a programech nebo jako to bylo?) 57 Euklidův algoritmus Věta 10.5. Uvažme deklaraci A obsahující pouze rovnici g(x, y) = if x — y then g (x — y, y) else (if y — x then g(x, y — x) else x). Pak pro každé nenulové m, n E N platí g (m, n) i—>* z, kde z je největší společný dělitel čísel m, n. Důkaz indukcí k i = m + n. (Tj. dokazujeme následující tvrzení: Pro každé i > 2 platí, že jestliže i = m + n, kde m, n G N, m, n > 0, pak z je největší společný dělitel čísel m, n.) V bázi pro i = 2 je m,n = 1 a platí 0(1,1) i-> if 1 - 1 then g(l - 1,1) else (if 1 - 1 then g(l, 1-1) else 1) ^ h^ if 0 then g(l - 1,1) else (if 1 - 1 then g(l, 1-1) else 1) h+ i—> if 1 — 1 then g(l, 1 — 1) else 1 i—^ if 0 then g(l, 1 — 1) else 1 i—> 1. Indukční krok. Nechť i + 1 = m + n kde m, n € N. Probereme tři možnosti: * m = n. Pak g(m, n) i—> if m — n then g (m — n, n) else (if n — m then g(m, n — m) else m) i—> if 0 then g (m — n, n) else (if n — m then g(m, n — m) else m) i—> if n — m then g(m, n — m) else m i—> if 0 then g(m, n — m) else m i—> m. * m < n. Pak fif(m, n) i—> if m — n then g (m — n, n) else (if n — m then g(m, n — m) else m) i—> if 0 then g (m — n, n) else (if n — m then g(m, n — m) else m) i—> if n — m then g(m, n — m) else m i-> if z then g(m, n — m) else m i—> fif(m, n — m) i—> g(m, k). kde k = n — m. Platí m + k = m + (n — m) = n < i, takže podle LP. také platí * z, kde z je největší společný dělitel čísel m a n — m. Ověříme, že z je největší společný dělitel čísel man. - Jelikož číslo z dělí čísla m a n — m, dělí i jejich součet (n — m) + m = n. Celkem z je společným dělitelem man. - Buď d nějaký společný dělitel čísel man. Pak d dělí také rozdíl n — m. Tedy d je společný dělitel čísel man — m. Jelikož z je největší společný dělitel čísel man — m. nutně d dělí z a závěr platí. * m > n. Pak g(m, n) h^* g(m - n, n) ■-»• g(k, n), kde k = m — n. Podle LP. platí g (k, n)i—>*z, kde z je největší společný dělitel čísel m — n a n. Podobně jako výše ověříme, že z je také největší společný dělitel čísel man. n Poznámka: Jak byste výše uvedený zápis Euklidova algoritmu vylepšili, aby správně „počítal" největšího společného dělitele i v případech, že m = 0 nebo n = 0? Co v takových případech selže při současném zápise? 58 Inkrementace dekadického zápisu Následuje příklad algoritmu, který všichni dobře znají už od dob základní školy - sčítání vícemístných čísel. My si ukážeme jeho zjednodušenou verzi coby inkremenaci čísla (tj. přičtení 1 k číslu). Příklad 10.6. Mějme přirozené číslo m dekadicky zapsané pomocí číslic (cfc_iCfc_2 • • • CiQ))io (kde zleva se implicitně vyplňují nuly). Pak dekadický zápis čísla m! = m + 1 získáme takto: Algoritmus . Inkrementace. k <— počet číslic m; P - l; for i <— 0,1,..., k — 1, k do cí <— (Ci+p) mod 10; if c- ^ 0 then p <— 0; done Zapišme tento kód formální deklarací našeho jazyka. Řešení: * Jelikož nyní nejsou k dispozici proměnné typu pole, „pomůžeme si" funkčním zápisem číslic g (i) a g'(i) místo Cj, c^. * Cyklus for nahradíme rekurzí (běžný postup). * Nakonec „trikově" nahradíme proměnnou p, která vyjadřuje přenos do z-tého řádu, zavedením nové funkce p(i), což výrazně zjednoduší zápis deklarace. Celá formální deklarace A bude vypadat například následovně: 9*(i) = (9(i) + pW) mod 10 p(i) = if i then (if g'(i — 1) then 0 else 1) else 1 0(0) = co, g(l) =c1, ... g(k-l) = ck_! Všimněte si zvláštního posledního řádku, kde jsou rovnice deklarující konstantní hodnoty jednotlivých číslic vstupního čísla m. (Proč to tak je zapsáno?) Věta. Pro každé i G N platí, že g'(i) udává dekadickou číslici z-tého řádu zprava čísla m + 1, kde m má dekadický zápis po číslicích (ck-i ■ ■ ■ CiC0)io- Dokažte si tvrzení sami za domácí úkol (diskutujte na IS). Je potřeba použít matematickou indukci se zesíleným předpokladem, který se bude vhodně vyjadřovat i o významu hodnoty p(i) („přenos"). Pochopitelně je třeba pro úplnou správnost řešení ještě rozepsat operaci „modulo" pomocí povolených aritmetických operací, což si také za úkol vyzkoušejte. □ Rozšiřující studium 59 11 Nekonečné množiny a zastavení algoritmu Úvod Bystrého čtenáře může snadno napadnout myšlenka, proč se vlastně zabýváme dokazováním zprávnosti algoritmů a programů, když by to přece (snad?) mohl za nás dělat automaticky počítač samotný. Bohužel to však nejde a je hlavním cílem této lekce ukázat důvody proč. Konkrétně si dokážeme, že nelze algoritmicky rozhodnout, zda se daný algoritmus na svém vstupu zastaví nebo ne. Hlavními nástroji, které použijeme, budou nekonečné množiny a důkazová technika tzv. Cantorovy diagonály, která se ve velké míře používá právě v teoretické informatice. (Pro zvídavé; obdobně, ale mnohem složitěji, lze dokázat že ani matematické důkazy nelze obecně algoritmicky konstruovat. ..) Cíle Zavedeme si v „naivním pohledu" nekonečné množiny a techniku důkazu Cantorovou diagonálou. Pak tuto techniku využijeme k důkazu algoritmické neřešitelnosti problému zastavení. 11.1 O kardinalitě a nekonečných množinách Definice: Množina A je „nejvýše tak velká" jako množina B, právě když existuje injek-tivní funkce / : A —► B. Množiny A a. B jsou „stejně velké" právě když mezi nimi existuje bijekce. V případech nekonečných množin místo "velikosti" mluvíme formálně o jejich kardinalitě. Komentář: Tyto definice kardinality množin „fungují" dobře i pro nekonečné množiny. * Například N a 7L mají stejnou kardinalitu („stejně velké"), tzv. spočetně nekonečné). * Lze snadno ukázat, že i Q je spočetně nekonečná, tj. existuje bijekce / : N —> (Q. * Existují ale i nekonečné množiny, které jsou „striktně větší" než libovolná spočetná množina (příkladem je IR). * Později dokážeme, že existuje nekonečná posloupnost nekonečných množin, z nichž každá je striktně větší než všechny předchozí. Věta 11.1. Neexistuje žádné surjektivní (tudíž ani bijektivní) zobrazení g : IN —► R. Neformálně řečeno, reálných čísel je striktně více než přirozených. Důkaz sporem. Nechť takové g existuje a pro zjednodušení se omezme jen na funkční hodnoty v intervalu (0,1). Podle hodnot zobrazení g si takto můžeme „uspořádat" dekadické zápisy všech reálných čísel v intervalu (0,1) po řádcích do tabulky: 7 5 7 8 3 2 5 9(0) = 0. 15 4 2 2(1) = 0. 2 2(2) = 0. 1 2(3) = 0. 3 2(4) = 0. 60 Nyní sestrojíme číslo a G (0,1) následovně; jeho i-tá číslice za desetinnou čárkou bude 1, pokud v i-tém řádku tabulky na diagonále není 1, jinak to bude 2. V našem příkladě a = 0.21211... Kde se naše číslo a v tabulce nachází? (Nezapomeňme, g byla surjektivní, takže tam a musí být!) Kostrukce však ukazuje, že a se od každého čísla v tabulce liší na aspoň jednom desetinném místě, to je spor. (Až na drobný technický detail s rozvojem ... 9.) D V obecnosti lze dokonce analogickým způsobem dokázat následovné. Věta 11.2. Buď M libovolná množina. Pak existuje injektivní zobrazení f : M —► 2M, ale neexistuje žádné bijektivní zobrazení g : M —► 2M. Důkaz: Dokážeme nejprve existenci /. Stačí ale položit f(x) = {x} pro každé x G M. Pak / : M —► 2M je zjevně injektivní. Neexistenci g dokážeme sporem. Předpokládejme tedy naopak, že existuje bijekce g : M —► 2M. Uvažme množinu K C M definovanou takto: K = {x G M | x & g(x)}. Jelikož g je bijektivní a K G 2M, musí existovat x E M takové, že g (x) = K. Nyní rozlišíme dvě možnosti: - x G g (x). Tj. x G K. Pak ale x G" g (x) z definice K, spor. - x G" 5f(x). To podle definice X znamená, že x G X, tj. x G k m. (Když takové m neexistuje, klademe k = oo.) Komentář: Jaká je délka výpočtu následujících výrazů? * 3 + 4-5*6; Tři kroky 3 + 4-5*6h^3 + 4-30i-^3 + 0i-^3. * 3 + (5 - 4) * (6 4- 2); Tentokrát čtyři kroky 3 + (5 - 4) * (6 4 2) h+ 3 + 1 * (6 4 2) ^3 + 1*3^3 + 3^6. * 2007; Žádný krok, tj. k = 0. Příklad 12.1. Pro ukázku uvažme deklaraci A obsahující pouze rovnici f(x) = if x then x * f (x — 1) else 1. Věta. Pro každé n G N je délka výpočtu výrazu /(n) rovna An + 2. Důkaz povedeme indukcí podle n: • Báze n = 0. Platí /(O) i—> if 0 then 0*7(0— 1) else 1 i—> 1, což jsou přesně 2 kroky, tj. 4-0 + 2. • Indukční krok. Nechť n + 1 = k. Pak /(k) ^ if k then k * /(k - 1) else 1 ■->■ k * /(k - 1) ■->■ k * /(w), kde w = k — 1 = n. To jsou přesně 3 kroky. Podle LP. je délka výpočtu výrazu /(w) rovna 4n + 2. Poté následuje ještě jeden poslední krok vynásobení k. Celkem se provedlo 3 + An + 2 + 1 = 4(n + 1) + 2 = Ak + 2 kroků. D Počítat přesně nebo raději ne? Komentář: Jaký má smysl určení přesného počtu kroků algoritmu při dnešních CPU? Copak jsme dnes schopni jednoznačně říci, jak dlouho jedna instrukce CPU trvá? Z druh strany, i když víme, že algoritmus A třeba potřebuje 2n kroků výpočtu a algoritmus B třeba potřebuje 3n kroků, je mezi nimi až takový rozdíl? Stačí, když B spustíme na dvakrát rychlejším počítači a poměr se hned obrátí. Obě tyto prakticky motivované úvahy nás povedou k poznání, že aditivní a multiplikativní faktory funkce počtu kroků algoritmu jsou vlastně zanedbatelné. 64 12.2 Asymptotické značení a odhady funkcí Zajímá-li nás jen rychlost růstu funkce f(n) v závislosti na n, zaměřujeme se především na tzv. asymptotické chování f při velkých hodnotách n. V popisu / nás tedy nezajímají ani různé přičtené "drobné členy", které se významněji projevují jen pro malá n, ani konstanty, kterými je / násobena a které jen ovlivňují číselnou hodnotu f(n), ale ne rychlost růstu. Komentář: Tak například funkce f(rí) = n2 roste (zhruba) stejně rychle jako f'(n) = lOOOOOOOOn2 i jako f"(n) = O.OOOOOOOln2 - lOOOOOOOOn - 1000000. Naopak h{n) = O.OOOOOOOOOOln3 roste mnohem rychleji než f'(n) = lOOOOOOOOn2. Pro porovnávání rychlostí růstů funkcí nám slouží následující terminologie. Definice: Nechť g : N —► IN je daná funkce. Pro funkci / : IN —► N píšeme / e 0(g) pokud existují konstanty A, B > 0 takové, že VneN: f(n) 0 je polynomiální funkce, * f(n) = 0(cra) pro nějaké c > 1 je exponenciální funkce. Příklad 12.2. (opakovaný) Zjistěte, kolik znaků 'x' v závislosti na celočíselné hodnotě n vstupního parametru n vypíše následující algoritmus. Algoritmus 12.3. for i<— 1,2,3,...,n-l,n do for j <— 1,2,3,...,i-l,i do vytiskni 'x' ; done done 65 Zatímco v Lekci 8 jsme trochu zdlouhavě indukcí dokazovali, že výsledkem je \n(n + 1) 'x', nyní si mnohem snadněji odvodíme, že počet 'x' je 0(n2), což je dostačující asymptotická odpověď ve většině informatických aplikací. Důkaz: Shora hned odhadneme, že každá z n iterací vnějšího cyklu vytiskne i < n znaků 'x', takže celkem je nejvýše n2 'x'. Naopak zdola hned vidíme, že posledních n/2 iterací vnějšího cyklu vytiskne i > n/2 znaků 'x', takže celkem je alespoň (n/2) ■ (n/2) = n2/4 'x'. Z toho podle definice hned vyjde asymptotický odhad 0(n2). □ Příklad 12.4. Příklady růstů různých funkcí. Funkce f(n) = 0(n): pokud n vzroste na dvojnásobek, tak hodnota f(n) taktéž vzroste (zhruba) na dvojnásobek. To platí jak pro funkci f(n) = n, tak i pro lOOOOOOOOOn nebo n + i/ň, atd. Funkce f(n) = 0(n2): pokud n vzroste na dvojnásobek, tak hodnota f(n) vzroste (zhruba) na čtyřnásobek. To platí jak pro funkci f(n) = n2, tak i pro lOOOn2 + lOOOn nebo n2 - 99999999^ - 99999999, atd. Naopak pro funkci f(n) = 0(2""): pokud n vzroste byť jen o 1, tak hodnota f(n) už vzroste (zhruba) na dvojnásobek. To je obrovský rozdíl exponenciálních proti polynomiálním funkcím. Pokud vám třeba funkce 999999n2 připadá velká, jak stojí ve srovnání s 2ra? Zvolme třeba n = 1000, kdy 999999n2 = 999999000000 je ještě rozumně zapsatelné číslo, ale 21000 ^ io300 byste už na řádek nenapsali. Pro n = 10000 je rozdíl ještě mnohem výraznější! □ Rekurentní odhady V tomto oddíle si uvedeme krátký přehled některých rekurentních vzorců, se kterými se můžete setkat při řešení časové složitosti (převážně rekurzivních) algoritmů. Leraa 12.5. Nechť cii,..., ak, c > 0 jsou kladné konstanty takové, že a\ + ... + ak < 1, a funkce T : IN —► N splňuje nerovnost T(n) < T(\ain]) + T(\a2n\) + ... + T(\akn\) + cn. PakT(n) = 0(n). Důkaz: Zvolme e > 0 takové, že a\ + ... + ak < 1 — 2e. Pak pro dostatečně velká n platí (i se zaokrouhlením nahoru) \a\n\ + ... + \akn] < (1 — e)n, řekněme pro všechna n > no. Dále zvolme dostatečně velké d > 0 tak, že ed > c a zároveň d > max{^T(n) : n = l,...,n0}. Dále už snadno indukcí podle n dokážeme T(n) < dn pro všechna n > 1: • Pro n < no je T(n) < dn podle naší volby d. • Předpokládejme, že T(n) < dn platí pro všechna n < n\, kde n\ > no je libovolné. Nyní dokážeme i pro n\ T (ni) < T(\ain{\) + ... + T(\akn{\) + cnx < < d ■ \a\ni\ + ... + d ■ \akni] + cri\ < < d ■ (1 — s)rii + crii < dni — (ed — c)n\ < dni ■ 66 D Leraa 12.6. Nechť k > 2 a ai,..., o^, c > O jsou kladné konstanty takové, že a\ + ... + (Zfc = 1, a funkce T : IN —► IN splňuje nerovnost T (n) < T( [ainl) + T( M) + ... + T( [a^]) + en. (1) Pak T (n) = O (n ■ log n). Důkaz (nematematický náznak): Bylo by možno postupovat obdobně jako v předchozím důkaze, ale výpočty by byly složitější. Místo formálního důkazu indukcí nyní předestřeme poměrně jednoduchou úvahu zdůvodňující řešení T(n) = 0(n ■ logn). Představme si, že upravujeme pravou stranu výrazu (1) v následujících krocích: V každém kroku rozepíšeme každý člen T{m) s dostatečně velkým argumentem m rekurzivní aplikací výrazu (1) (s T{m) na levé straně). Jelikož a\ + ... + au = 1, součet hodnot argumentů všech T(-) ve zpracovávaném výrazu bude stále zhruba n. Navíc po zhruba t = ©(log n) krocích už budou hodnoty argumentů všech T(-) "malé" (nebude dále co rozepisovat), neboť 0 < a^ < 1 a tudíž a\-n< 1 pro všechna i. Při každém z kroků našeho rozpisu se ve výrazu (1) přičte hodnota cn = 0(n), takže po t krocích bude výsledná hodnota T{n) = t ■ O (n) + O (n) = O (n ■ log n). Vyzkoušejte si tento postup sami na konkrétním příkladě T'(n) < 2T" (f) + n- n V obecnosti je známo: Leraa 12.7. Nechť a > 1, b > 1 jsou konstanty, f : N —► N je funkce a pro funkci T : N —► IN platí rekurentní vztah T(n)