Fakulta Informatiky Masarykova Univerzita Úvod do Informatiky (FI: IBOOO) Doc. RNDr. Petr Hliněný, Ph.D. hlinenyOfi.muni.cz 15. března 2010 N^tis mPo % '^AS u^ Obsažný a dobře přístupný úvod do nezbytných formálních matematických základů moderní informatiky, doplněný řadou interaktivních cvičení v IS MU. Výukový text pro předmět IB000 na FI MU od roku 2006, vycházející z původních přednáškových slidů prof. Antonína Kučery z roku 2005. Verze 1.20 (2010). © 2006 2010 Petr Hliněný, FI MU. 0.1 O tomto textu a jeho studiu Vážení čtenáři, dostává se vám do rukou výukový text Úvodu do Informatiky, který je primárně určený pro studenty stejnojmenného předmětu na FI MU Brno. Seznamuje čtenáře s několika formálními matematickými oblastmi důležitými pro úspěšné studium moderní informatiky. Náš text svým obsahem navazuje na původní slidy předmětu IB000 sepsané A. Kučerou do roku 2005, je však výrazně rozšířený o volný text a komentáře. Mimo textu samotného (jak jej zde vidíte) jsou z téhož zdoje vytvářeny i přednáškové slidy předmětu, které najdete například v IS MU. Slidy však pochopitelně obsahují jen část textu a jsou jinak formátovány. Učební text je psán strukturovaným matematickým přístupem, s velkým důrazem na přesnost a formalitu vyjadřování v nutných partiích. Na druhou stranu jsou strohá matematická vyjádření pokud možno doplněna obsáhlými neformálními komentáři, které mají studentům ulehčit pochopení látky. V žádném případě však čtenáři nemají zaměňovat neformální komentáře za matematické definice - v případě nejasností vždy platí to, co přesně říká formální definice. Interaktivní osnova http://is.muni.cz/el/1433/podzim2010/IB000/index.qwarp IB000, Úvod do informatiky, jaro 2008 Editovat | Zobrazit osnovu podle aktuálního dooorLič&n učitri* | JBQQQ 11 Nápověda id Rozbalit všechny podosnovv ( Titulní strana předmětu IB000 Úvod do informatiky O- Oficiální uCebni text IBOOQ [wraeod M07)g ■lein433 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é j:,j/£Q, kde x < y, existuje z € (Q takové, že x < z < y. - Množina racionálních čísel je hustá. 1.2 Význam matematických vět První krok formálního důkazu je uvědomit si, co říká věta, která se má dokázat; tedy co je předpoklad a co závěr dokazovaného tvrzení. Pravdivost takového tvrzení pak je třeba chápat v následujícím významu: Pro každou situaci, ve které jsou splněny všechny předpoklady, je platný i závěr tvrzení. Komentář: Příklady běžné formulace matematických vět: * Konečná množina má konečně mnoho podmnožin. * sin2(a) + cos2(a) = 1. 2 * Graf je rovinný jestliže neobsahuje podrozdělení K$ nebo Ks^. Č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í. Všimněte si také, jaký je správný logický význam matematického tvrzení vysloveného touto formou implikace („jestliže ..., pak ..."). Především, pokud předpoklady nejsou splněny nebo jsou sporné, tak celé tvrzení je platné bez ohledu na pravdivost závěru! Příklad 1.4. Je pravdivé následující matematické tvrzení? Věta. Mějme dvě kuličky, červenou a modrou. Jestliže červená kulička je těžší než modrá a zároveň je modrá kulička těžší než ta červená, tak jsou obě kuličky ve skutečnosti zelené. „To přece nemůže být pravda, jak může být jedna kulička těžší než druhá a naopak zároveň? Jak mohou být nakonec obě zelené? To je nějaká blbost..." Ano, výše uvedené jsou typické laické reakce na uvedenou větu. Přesto však tato věta pravdivá je! Stačí se vrátit o kousek výše ke kritériu - Pro každou situaci, ve které jsou splněny všechny předpoklady je platný i závěr tvrzení - které je zjevně naplněno. Nenaleznete totiž situaci, ve které by byly splněny oba předpoklady zároveň, a tudíž ve všech takových neexistujících situacích si můžete říkat cokoliv, třeba že kuličky jsou zelené. □ 1.3 Struktura matematických vět a důkazů Jak „moc formální1 mají správné matematické důkazy vlastně být? • 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. A jak na správný matematický důkaz mohu přijít? • No..., nalézání matematických důkazů je tvůrčí činnost, která není vůbec snadná a vyžaduje od vás přímo „umělecké11 vlohy. Přesto se jí alespoň trochu musíte naučit. 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.5. čistě existenčního důkazu. Věta. Existuje program, který vypíše na obrazovku čísla tažená ve 45. tahu sportky v roce 2010. 3 Důkaz: Existuje pouze konečně mnoho možných výsledků losování 45. tahu sportky v roce 2010. 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 ve 45. tahu sportky v roce 2010 skutečně vylosován. Komentář: To je ale „podvod11, ž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.6. „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 miner 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_ra. 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 =------ -»O. yn-\ Jelikož je toto číslo (pravděpodobnost) pro n > 7 menší než 1, bude existovat obarvení bez jednobarevných zvolených podmnožin. D 1.4 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 natolik 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 Jľuringova stroje existují i jiné matematické modely výpočtů, jako třeba stroj RAM, který je abstrakcí skutečného strojového kódu, nebo také třeba Definice 9.2 v našem textu. Konvence 1.7. Zjednodušeně zde algoritmem rozumíme konečnou posloupnost elementárních výpočetních kroků, ve které každý další krok vhodně1 využívá (neboli závisí na) vstupní údaje či hodnoty vypočtené v předchozích krocích. Tuto závislost přitom pojímáme zcela obecně nejen na operandy, ale i na vykonávané instrukce v krocích. Pro zápis algoritmu a jeho zpřehlednění a zkrácení využíváme řídící konstrukce -podmíněná větvení a cykly. '■Zvídaví studenti si mohou na tomto místě uvědomit, že ve slůvku „vhodně" se skrývá celá hloubka Church-Turingovy teze. V žádném případě tak nelze uvedené obracet, že by každá posloupnost kroků atd ... byla algoritmem ve smyslu této teze (viz také Lekce 11). 4 Komentář: Vidíte, jak blízké si jsou konstruktivní matematické důkazy a algoritmy v našem pojetí? Jedná se nakonec o jeden ze záměrů našeho přístupu... Příklad 1.8. 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.9. Průměr z daného pole a[] s n prvky. sum <— 0; foreach 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 zápisu algoritmů v předmětu FI: IBOOO 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 elementární 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). * Pevný cyklus uvedeme klíčovými slovy foreach ... do ... done, kde část za foreach 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, foreach, 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. 5 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ů? Odpověď může naznačit tato tabulka: zcela formální běžná úroveň matematika algoritmy programování formální rozepsání všech elem. kroků (Příklad 1.2) rozepsání všech elem. kroků ve výpočetním modelu assembler / 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.9), 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... Navazující studium Látka této úvodní lekce má velmi široký záběr. S potřebou formálního zápisu tvrzení a důkazů se setkáte asi ve všech matematických předmětech, které zároveň studujete či budete studovat, a principy budou stále stejné. Taktéž schopnost formálně rozepisovat a správně chápat algoritmy je nezbytná pro celé příští studium informatiky. Blíže se formálním zápisům algoritmů a jejich dokazování budeme věnovat i v Lekcích 8,9,10. 6 2 Důkazové techniky, Indukce Uvod Náš hlubší úvod do matematických formalismů pro informatiku pokračujeme základním přehledem technik matematických důkazů. Třebaže matematické dokazování a příslušné techniky mohou někomu připadat neprůhledné (a možná zbytečné), jejich pochopení a zvládnutí není samoúčelné, neboť nám pomáhá si mnoho uvědomit o studovaných problémech samotných. Konečně, jak si můžeme být jisti svými poznatky, když bychom pro ně nebyli schopni poskytnout důkazy? Během studia tohoto předmětu poznáte (a ti méně šťastní až s překvapením u zkoušek), že vlastně vše, k čemu naším výkladem směřujeme, se dá neformálně shrnout slovy „naučit se přesně vyjadřovat a být si svými tvrzeními naprosto jisti" a analogicky „naučit se navrhovat správné algoritmy a být si i svými programy naprosto jisti". Z důkazových postupů je pro nás informatiky asi nejdůležitější technika důkazů matematickou indukcí, která je svou podstatou velmi blízká počítačovým programům (coby iterace cyklů). V dalším výkladu budeme indukci hojně využívat, především v Lekcích 8 a 10. 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. Každý student by se měl alespoň naučit formálně psané důkazy číst a pochopit. (Pro vysvětlení, z Lekce 1 víme, že matematický důkaz má „jednotnou formu" Defínice 1.1, ale nyní se věnujeme takříkajíc šablonám, podle nichž takový korektní důkaz 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... 7 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 & Bu. 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. 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 \[2 = 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č?). 8 - Jelikož r je dělitelné dvěma, je r2 dělitelné dokonce čtyřmi, tedy r2 = 4 • to pro nějaké to. Pak ale také 4 • to = 2 • s2, tedy 2 • to = 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. 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 > ko platíT(n).íl Zde ko 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 > k0 platíT(n).íl stačí ověřit platnost těchto dvou tvrzení: • T (ho) (tzv. báze neboli základ indukce) • Pro každé n > ko; jestliže platí T(n), (indukční předpoklad) pak platí také T(n + 1). (indukční krok) 9 (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ť jfn 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 g __ i i J ^ P n 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 1 2 n P n n P n n a stejně pro pravděpodobnost celkového lichého součtu. □ Příklad 2.6. Ukázka důkazové „síly11 principu matematické indukce. Věta. Pro každé n > 0 platí, že n přímek dělí rovinu nejvýše na 1 -n(n + 1) + 1 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 oblastí: -n(n+1) + 1 + (ra + 1) = -n{n + 1) + - • 2(n + 1) + 1 = -(ra + l)(ra +2) + 1 D Příklad 2.7. Další indukční důkaz rozepsaný v podrobných krocích. Věta. Pro každé n > 0 platí YTj=o J n ■ __ ri(ri+l) 10 Důkaz indukcí vzhledem k n. * Báze: Musíme dokázat tvrzení T(0), což je v tomto případě rovnost ^J=0 j = Tato rovnost (zjevně) platí. * Indukční krok: Musíme dokázat následující tvrzení: Jestliže platí Yľj=oJ = t ^de i > 0, pak platí Yľj=oJ = 2 • Předpokládejme tedy, že Yľj=oJ = 2 a pokusme se dokázat, že pak také YľjLoJ = t+ 2 = 2 ■ T° u^ plyne úpravou: £, = £,+„ + !) = ííi±M + («+D = "' + 1);2" + 1) = ko je indukční krok univerzálně platný... 11 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í SW = TÍ2 + 2Í3 + 3Í4 + --- + ^TT) 1 platí s(n) < 1- ^ < 1. To platí pro n = 1 (nezapomeňte ověřit!) a dále už úpravou jen dokončíme zesílený indukční krok: s(n+l) = s(n) + -------—------— < 1 (n+l)(n + 2) - n+1 (n + l)(n + 2) 1 ~(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. - 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 + 1,..., 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. Nectí 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: 12 Pro každé n > 0; jestliže platí T (n); neboli f(n) = n + l,a zároveň platí T (n +1); f (n + 1) = n + 2, pak plat/ také T(ra + 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) = 2/(ra + 1) - f(n) = 2-(ra + l + l)-(ra+l) = ra + 3 = ra + 2 + l. 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 = {Ki,... ,Kn+i} 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+i) 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? Navazující studium Jak jsme již řekli, matematické důkazy a jejich chápání jsou nezbytné ke studiu vysokoškolských matematických předmětů. Bez schopnosti přesného vyjadřování a chápání defínic a vět se v informatice neobejdete, ani pokud se zaměřujete čistě aplikovaným směrem. Na druhou stranu umění "tvořit" nové matematické důkazy je dosti obtížné a nedá se jemu jen tak snadno naučit - vyžaduje to mnoho pokročilé praxe. Jelikož je schopnost formálního matematického dokazování nezbytná (převážně jen) v teoretických informatických disciplínách, není tato část kritická v celém předmětu (a u zkoušek se objevíš menším důrazem), ale to neznamená, že byste se jí mohli zcela vyhýbat. Obzvláště techniku matematické indukce by měl každý informatik aspoň trochu ovládat, neboi s jejím použitím se zajisté ještě mnohokráte setkáte v budoucím studiu. 13 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. Netradiční sousloví „datové typy" matematiky zde volíme záměrně, abychom zdůraznili jejich fundamentálnost pro výstavbu navazující teorie v analogii k programování. 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á;, 1 + cos a;2, atd. Jak uvidíte, 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í) defínicí relace, funkce a posloupnosti, uvedeme si příklady rekurzivně defínovaných funkcí a posloupností. Látku relací a funkcí pak dále rozvedeme v následuj ich třech 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 i} pro každé i £ N. Pak f]ie]N Bi = 0. Definice: Rozdíl \ a symetrický rozdíl A dvou množin A, B definujeme A\B = {i | x G i a současně x £~ B} , AAB = (A \ B) U (B \ A) . 15 * Příklady {a, b, c} \ {a, b, d} = {c}, {a, b, c}A{a, b, d} = {c, d}. * Vždy platí například A \ (B n C) = (A \ B) U (A \ C) apod. Definice: Nechť A C M. Doplněk A vzhledem A; M je množina A = M \ A. Komentář: Jedná se o poněkud specifickou operaci, která musí být vztažena vzhledem k nosné množině M! * Je-li M = {a, b, c}, pak {a, b} = {c}. Je-li M = {a, b}, pak {a, b} = 0. * Vždy pro ACM platí A = A („dvojí" doplněk). * Vždy pro A,B C M platí AU B = ~Är\~B a AílB = ~Ä\JB. (Viz Vennovy diagramy.) Uspořádané dvojice a kartézský součin Zatímco prvky v množinách jsou zcela neuspořádané, jsou mnohé situace, kdy musíme pracovat se „seřazenými" výčty prvků. V teorii množin lze takovéto seřazení definovat oklikou, například následovně: Definice: Uspořádaná dvojice (a,b) je zadána množinou {{a}, {a, b}}. Fakt: Platí (a, b) = (c, d) právě když a = c a současně b = d. Příklad 3.1. Co je podle deůnice (a, a)? (a, a) = {{a}, {a, a}} = {{a}, {a}} = {{a}}. D Definice 3.2. Kartézský součin dvou množin A, B definujeme jako množinu všech uspořádaných dvojic ze složek z A a B Ax B = {(a, b) I a G A, b G B} . * Příklady {a, b} x {a} = {(a, a), (b, a)}, {c, d} x {a, b} = {(c, a), (c, b), (d, a), (d, b)}. * Platí 0 x X = 0 pro každou množinu X. * Mnemotechnická pomůcka \Ax B\ = \A\- \B\. Definice: Pro každé k G N, k > 0 definujeme uspořádanou k-tici («i, • • • , ßfc) induktivně takto - (ai) = ai, - (ai, • • • ,uí, ßj+i) = ((«i, • • • ,o>i), ßj+i)-Fakt: Platí («i, • • • , ßfc) = (&i, • "" > ^fc) právě když aj = bi pro každé i G IN kde 1 < i < k. Definice kartézského součinu více množin: Pro každé k G N definujeme Ai x • • • x Ak = {(ai, • • • , ß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°l {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. 16 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í°>6> = {0, {a}, {&}, {a, b}}: * 20 = {0})2^W} = {0,{0},{{0}},{0,{0}}}) * 2{a}xM = {0, {(a, a)}, {(a, &)}, {(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íž 2^u{6}| = 2 . Ml = 2lAl+1 = 2lAu{b}l. n 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í A U B = A n B. Důkaz v obou směrech rovnosti. . Al) B C Af] B: Pro x e M platí x E A U B, právě když x E~ Al) B, neboli když zároveň x G" A a x G" B. To znamená x E A a zároveň x E B, z čehož vyplývá požadované x E AC\ B. * AU B D Aľ\ B: Pro x E M platí x G A H 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. n 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) U(A\C): Je-li x E A \ (B n C), pak x E A a zároveň x G" (£> n C), neboli x G" B nebo x E" C. Pro první možnost máme x£(A\ß), pro druhou x E (A\C). . Naopak A \ (B n C) D (A \ S) U (A \ C): Je-li x E (A\ B) U (A \ C), pak x G (A \ £>) nebo 3; 6 (A \ C). Pro první možnost máme x E A a zároveň x G" £>, z čehož plyne x G A a zároveň x G" (B n C), a tudíž x G A \ (£> n C). Druhá možnost je analogická. n 17 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 j>i + j) \h j G IN} Je ternární relace na N. * {3 • i | i G N} je unární relace na N. * Jaký význam vlastně mají unární a nulární relace na Al Uvědomme si, jak obecně je relace definována - její definice umožňuje podchytit skutečně libovolné „vztahy" mezi prvky téže i různých množin. V praxi se relace velmi široce využívají třeba v relačních databázích... Funkce mezi množinami Tradiční „školní" pojetí pojmu funkce jej obvykle identifikuje s nějakým výpočetním (analytickým) předpisem či vzorcem. Pojem funkce je však daleko obecnější a zcela abstraktní. Definice 3.10. (Totální) funkce z množiny A do množiny B je relace / mezi A a B taková, že pro každé x G A existuje právě jedno y G B takové, že {x, y) G /. Množina A se nazývá definiční obor a množina B obor hodnot funkce /. Komentář: Neformálně řečeno, ve funkci / je každé „vstupní" hodnotě x přiřazena jednoznačně „výstupní" hodnota y. (V obecné relaci počty „přiřazených" dvojic neomezujeme. ..) Značení: Místo (x,y) G / píšeme obvykle f(x) = y. Zápis / : A —► B říká, že / je funkce s definičním oborem A a oborem hodnot B. Funkcím se také říká zobrazení Komentář: Příklady funkcí. * Definujeme funkci / : N —> N předpisem f (x) = x + 8. Tj. / = {(x, x + 8) | x G N}. * Definujeme funkci plus :NxN-»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. 19 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 , . _ í 3 + x jestliže x > 0. JW = \ J_ jinak. Tj. / = {(x,3 + x) | x éN}. * Také funkce / : R —> R daná běžným analytickým předpisem f(x) = Jx 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 začínat od nuly nebo i od jedničky, jak je v aplikacích potřeba. • 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ů ir. * 1, —1, 1, —1,... je posloupnost určená vztahem pi = (—1)*, i > 0. * Pokud chceme stejnou posloupnost 1, —1, 1, —1,... zadat jako <&, i > 1, tak ji určíme vzorcem Qí = (—l)t_1. • Posloupnost je rostoucí (či klesající), pokud pn+\ > pn (pn+i < 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. 20 • Zadáme-li posloupnost pn vztahy p0 = 1 a pn = 2pn_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 f\ = f2 = 1 a fn = fn-\ + /ra_2 pro n> 2. Příklad 3.11. Posloupnost f je zadaná rekurentní deůnicí /(O) = 3 a f(n+l) = 2-f(n) + l pro všechna přirozená n. Určete hodnotu f(n) explicitním vzorcem v závislosti na n. Řešení: V první fázi řešení takového příkladu musíme nějak „uhodnout" hledaný vzorec pro f(n). Jak? Zkusíme vypočítat několik prvních hodnot a uvidíme... /(I) = 2 ■ /(O) + 1 = 2-3 + 1 = 7 /(2) = 2-/(l) + l = 2.7+1 = 15 /(3) = 2-/(2) + l = 2-15 + 1 = 31 /(4) = 2-/(3) + l = 2-31 + 1 = 63 Nepřipomínají nám tato čísla něco? Co třeba posloupnost 8 — 1, 16 — 1, 32 — 1, 64—1...? Bystrému čtenáři se již asi podařilo uhodnout, že půjde o mocniny dvou snížené o 1. Přesněji, f(n) = 2n+2 — 1 (proč tento exponent n + 2? inu proto, aby správně vyšlo zadané /(O)). Ve druhé nesmíme ale zapomenout správnost našeho „věštění" dokázat, nejlépe matematickou indukcí podle n. . Báze: /(O) = 2°+2 -1 = 4-1 = 3 platí. • Indukční krok: za využití indukčního předpokladu f(n + 1) = 2 • f(n) + 1 = 2- (2ra+2 - 1) + 1 = 2 • 2n+2 - 2 + 1 = 2(ra+1)+2 - 1, což také platí. Podle principu matematické indukce je nyní dokázáno, že pro zadanou rekurentní posloupnost / platí f(n) = 2n+2 — 1 pro všechna přirozená n. □ Navazující studium I když jste se s "množinami" setkávali už od základní školy, do matematické teorie množin asi nahlédnete na VŠ poprvé. Nezaleknete se na úvod formality vyjadřování, která je bohužel nezbytná, a naučte se s množinami a relacemi dobře pracovat aspoň na zde ukázané naivní úrovni konečné teorie množin. (Lehký náhled na obecně nekonečné množiny a jejich zdánlivé paradoxy i informatické aplikace si ukážeme později v Lekci 11...) Mějte na paměti, že na pojmech množin, relací a funkcí jsou vystavěny prakticky všechny datové struktury používané v dnešní informatice, což asi nej explicitnej i můžete vidět na relačních databázích (viz také Lekce 4 a 6) ana často se vyskytujících induktivních defínicích (Oddů 6.5). 21 4 Binární relace, Ekvivalence Uvod 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 dat a databází. Není to však jen oblast relačních 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. 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 PŘÍJMENÍ x VEK. Relaci „typu" ZAMESTNANEC pak lze reprezentovat tabulkou: JMÉNO příjmení VEK Jan Novák 42 Petr Vichr 28 Pavel Zima 26 Stanislav Novotný 52 D 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. 22 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,ď), (b,e), (b, f), (d,c). (e, c), (/, c), (e, d), (e, /), (/, b)}, pak: / 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). Značení: Binární relaci i? C M x M lze jednoznačně zapsat také pomocí tabulky relace - matice typu M x M s hodnotami z {0,1}. /O 1 0 0 0 0\ 0 0 1111 0 0 0 0 0 0 0 0 10 0 0 0 0 110 1 \0 1 1 0 0 0/ 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 E M platí (a, a) G R: • ireflexivní, právě když pro každé a E M platí (a, a) G" R: 23 symetrická, právě když pro každé a,b E M platí, že jestliže (a, b) E R, pak také (b, a) G R; > antisymetrická, právě když pro každé a, b E M platí, že jestliže (a, b), (b, a) G R, pak a = b: > tranzitivní, právě když pro každé a, b, c G M platí, že jestliže (a, b), (b, c) G R, pak také (a, c) G R. Následují dva základní typy binárních relací, R 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á(I), neboť tyto vlastnosti se nevylučují. Příklad 4.3. Několik příkladů relací deůnovaných v přirozeném jazyce. Buď M množina všech studentů f. 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: * (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ď i?C NxN 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.) 24 • Nechť F = {/ I / : N —> N} je množina funkcí. Buď R (Z F x F definovaná takto (f, g) G R právě když /(x) < g (x) pro všechna x. (Antisymetrická a tranzitivní, ale ne reflexivní - není uspořádání.) □ 4.3 Relace ekvivalence • Relace ňCMxMje ekvivalence právě když i? je reflexivní, symetrická a tranzitivní. Tyto tři vlastnosti je tedy třeba ověřit k důkazu toho, že daná relace R je ekvivalence. • Jak vypadá graf ekvivalence? • Neformálně řečeno: ekvivalence je relace R C M x M, taková, že (x, y) G R právě 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) G R právě když x má stejnou výšku jako y; * (x, y) 2, pak množinu A\ x ■ ■ ■ x An lze uspořádat po složkách nebo lexikograůcky. Všimněte si, že třeba 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, C) uspořádaná množina. • x G M je minimální právě když pro každé y G M platí, že jestliže y ^ x, pak x Q y. (Tj. x je minimální právě když neexistuje žádný prvek ostře menší než x.) x \ i x G M je maximální právě když pro každé y G M platí, že jestliže xCj/, pak |/Ci, (Tj. x je maximální právě když neexistuje žádný prvek ostře větší než x.) 29 x E M je nejmenší právě když pro každé y E M platí, že x C ?/. x . x G M je největší právě když pro každé y E M platí, že y |Z x. . x G M pokrýva y E M právě když x ^ y, y Q x a neexistuje žádné z E M takové, že y x E M je dolní závora (mez) množiny ACM právě když x Q y pro každé y E A. x E M je horní závora (mez) množiny A E M právě když y ^ x pro každé y E A. x E M je ínfimum množiny A E M právě když x je největší dolní závora množiny A. > x E M je supremum množiny A C M, právě když x je nejmenší horní závora množiny A. ' A C M je řetězec v uspořádání jZ právě když (A, C) je lineárně uspořádaná množina. Komentář: Tuto dlouhou definici se sluší poněkud neformálně okomentovat. Za prvé, s pojmy nejmenšího a největšího prvku jste se už intuitivně setkali mnohokrát, ale (matematicky slabší) pojmy minimálního a maximálního působí někdy problémy. Zapamatujte si proto dobře, že minimálních prvků může mít množina několik, jsou to prostě všechny ty "vespod", ale nejmenší prvek existuje nejvýše jeden a je to pouze ten unikátní minimální prvek množiny. Stejně pro maximální... Další poznámka se vztahuje k infimu a supremu množiny. Jak jsme napsali (a asi totéž znáte z matematické analýzy), množina nemusí mít nejmenší ani největší prvek, ale v mnoha případech je lze "nahradit" po řadě infimem a supremem, které hrají v jistých ohledech podobnou roli. Avšak ani supremum a infimum nemusí vždy existovat. 30 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... Příklad 5.5. Proč má každá uspořádaná množina nejvýše jeden největší prvek? Tvrzení dokážeme sporem: Nechť m i n jsou největší prvky uspořádané množiny (M, Q). Pak podle Definice 5.4 platí n jZ m i m jZ n zároveň. Ovšem jelikož uspořádání musí být antisymetrické, pak platí m = n a největší prvek je jen jeden. D Relace předuspořádání Definice: Relace R C M x M je předuspořádání (také kvaziuspořádám, nebo polouspořádání) právě když R 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 „cykly". Tvrzení 5.6. Je-li |Z předuspořádání na M, můžeme definovat relaci ~ na M předpisem x ~ y právě když x jZ y a y jZ x. Pak ~ je ekvivalence na M, která se nazývá jádro předuspořádání'fZ. Na rozkladu M j ~ pak lze zavést relaci -< definovanou takto [x] Z: [y] právě když x jZ y. Pak [Mj ~, zí) je uspořádaná množina. Komentář: Pro ukázku si vezměme relaci dělitelnosti na 7L. Pak třeba —2 ~ 2. Jádrem zde jsou dvojice čísel stejné absolutní hodnoty. Důkaz (náznak): Tranzitivita a reflexivita relace ~ vyplývá z tranzitivity a reflexivity relace fZ. Symetrie ~ pak je přímým důsledkem její definice. Tudíž ~ skutečně je relací ekvivalence a M j ~ je platný rozklad. Tranzitivita a reflexivita relace -< se opět dědí z relace fZ. Její antisymetrie vyplývá následující úvahou: Pokud [x] zí [y] a [y] zí [x], pak podle naší definice x jZ y a y fZ x, neboli x ~ y a [x] = [y] podle definice tříd rozkladu. Pozor, nejdůležitější částí této větve důkazu je však ještě zdůvodnit, že naše podaná definice vztahu [x] zí [y] je korektní, což znamená, že její platnost nezávisí na konkrétní volbě reprezentantů x z [x] a y z [y\. D 5.3 Hasseovské diagramy Motivace: tzv. Hasseovské diagramy uspořádaných množin jsou přehlednější než grafy relací. Například si srovnejte: » t o o 9 A Ä a b 31 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, C). (Tj. které nepokrývají nic. Pojem pokrývání prvku najdete v Definici 5.4.) - 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.7. Relaci dělitelnosti na množině {1,2,...,12} zakreslíme: 12 dělitelnost: 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 „vrstvy" 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ť I je množina a nechť Ri C M x M je relace mající vlastnost V pro každé i E I. Pak relace f]ieI R% má vlastnost V. Fakt: Libovolná kombinace vlastností reflexivita, symetrie, tranzitivita je uzavíratelná vlastnost. Antisymetrie není uzavíratelná vlastnost. Věta 5.8. Nechí V je uzavíratelná vlastnost binárních relací. Buď M množina a R libovolná binární relace na M. Pak pro množinu všech relací S I) R na M majících vlastnost V existuje infimum Ry (vzhledem k množinové inkluzi), které samo má vlastnost V. Definice: Tuto „nejmenší" relaci Ry s vlastností V nazýváme V-uzávěr relace R. Tvrzení 5.9. Buď R binární relace na M. 32 * Reflexivní uzávěr R je přesně relace R U {(x, x) \ x G M}. * 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ž i-krát iterovaná aplikace funkce T. i * Tranzitivní uzávěr R je přesně relace R+ = \J°lľ Tl(R). * Reflexivní a tranzitivní uzávěr i? je přesně relace R* = Uí^i ^%{Q)i kde Q je reflexivní uzávěr R. * 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 R. 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 v R se lze „dostat po šipkách" z x do z. Nakreslete si to na papír pro nějakou jednoduchou relaci, abyste význam tranzitivního uzávěru lépe pochopili. A jak bylo dříve řečeno, antisymetrický uzávěr relace prostě nemá smysl. Například buď fiCNxN definovaná takto: R = {(i, i + 1) | i G N}. Pak R* je běžné lineární uspořádání < přirozených čísel. Příklad 5.10. Proč při výpočtu tranzitivního uzávěru relace na konečné množině podle vzorce R+ = \J°liTl(R) vždy stačí uvažovat konečně mnoho členů tohoto sjednocení? Pro odpověď si uvědomme zásadní fakt — pokud T%+1 = Tl, tak už platí Tt+k = T% pro všechna přirozená k. Neboli je potřeba sjednotit jen tolik prvních členů, dokud se ony „zvětšují", což může nastat jen konečně krát nad konečnou množinou. Mimo jiné tak vidíme, že uvedený popis tranzitivního uzávěru je konstruktivní. D Rozšiřující studium Jedny z prvních algoritmů, které se studenti informatiky obvykle učí, jsou různé třídící algoritmy, takže s pojmem uspořádání se setkáváte hned v začátcích. Jenže ne všechna uspořádání jsou lineární, nýbrž jen částečná, a ke správnému uchopení a použití částečných uspořádání a předuspořádání v aplikacích je potřeba se už opřít o přesné formální defínice, či o poměrně názorný pojem Hasseova diagramu. Jmenovitě dále upozorňujeme na pojmy uzávěru relace, které mimo nepříliš dobře čitelné formální defínice mají i dobré neformální vysvětlení a použití. Co se týče praktického určení symetrického nebo tranzitivního uzávěru relace, odkazujeme na budoucí Algoritmy 8.5 a 8.6. 33 6 Skládání relací a funkcí Ú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 „postupných" (induktivních a rekurentních) defínic a vztahů. Jedná se vlastně o matematické analogie rekurzivních programů a jejich správné formální pochopení oceníme mimo jiné i při programování samotném. Cíle V této lekci defínujeme 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í (jako model nám poslouží permutace). 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) ^ f (y); - surjektivní (nebo také „na") právě když pro každé y G B existuje x G A takové, že f (x) = y; - bijektivní (vzáj. jednoznačná) právě když je injektivní a současně surjektivní. Komentář: Ukázky vlastností funkcí. * Funkce plus : N x N —> N je surjektivní, ale není prostá. * Funkce g : % —> N daná předpisem , . j —2x — 1 jestliže x < 0. ^ ' ~ \ 2x jinak je bijektivní. * Funkce 0 : 0 —> 0 je bijektivní. * Funkce 0 : 0 —> {a, b} je injektivní, ale není surjektivní. * Dokázali byste nalézt bijektivní funkci NxN^ N? 6.2 Inverzní relace a skládání relací Definice: Nechť R C A x B je binární relace mezi A a, B. Inverzní relace k relaci R se značí R~x a je definována takto: R'1 = {(&, a) | (a, b) e R} (i?-1 je tedy relace mezi B a A.) 34 Komentář: Příklady inverzí pro relace-funkce. * Inverzí bijektivnífunkce f(x) = x + 1 na % je funkce f~l(x) = x — 1. * Inverzí prosté funkce f(x) = ex na R je parciální funkce f~l(x) = \nx. * Funkce g(x) = x mod 3 není prostá na N, a proto její inverzí je „jen" relace g~l = {(a, 6) | a = 6 mod 3}. Konkrétně «r1 = {(0, 0), (0, 3), (0, 6),... , (1,1), (1, 4),... , (2, 2), (2, 5),... }. Tvrzení 6.1. Mějme funkci f : A —► £>. PaA; je/Y inverzní relace f~x 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í relací R a S (v tomto pořadí!) je relace S o R C A x C definovaná takto: S o R = {(a, c) I existuje b E B takové, že (a, b) G R, (b, c) G S*} Složení relací čteme „R složeno s S" nebo (pozor na pořadí!) „S po Ru. Komentář: Příklady skládání relací. * Je-li - 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) = x + 1 na R vznikne funkce foh{x) = f(h{x)) = x2 + 1. * Složením těchže funkcí „naopak" ale vznikne funkce ho f (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í...) 35 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ě. R: student (učo) předmět (kód) předmět (kód) fakulta MU 121334 MA010 MAO 10 FI 133935 M4135 S: IB000 FI 133935 IA102 IA102 FI 155878 M1050 M1050 PřF 155878 IB000 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: SoR: D student (učo) fakulta MU 121334 FI 133935 FI 133935 PřF 155878 FI 155878 PřF 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áni relaci vyšši 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 = L\ x • • • x Lm a C = Lm+i 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, č) G B x C I (bi,...bm,cm+i,...c£) G U}. * Nakonec přirozeně položme U om T ~ S o R, takže vyjde UomT = {(a, č) I ex. b G B, že (ai,... ak-m, 61, • • • bm) G T a (61,... bm, cm+i, ...ce)eU}. Schematicky pro snažší orientaci ve složkách našich relací: rc Kí x • • X Afc_TOX ľ^-k—rr +1 x • ■ x Kk uc U x • ■ ■ X _LTO xLm+i x • ■ ■ x L t UomTC Kí x • • • X Afc_m X x Lm+\ x ■' ■ x Le A B c 36 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. UooT: 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 ČSA 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, J2{x) = x + 1, fz{x) = log x a /^(x) = 2x. * A jak bychom obdobně vyjádřili složením funkcí aritmetický výraz siná; + cos a; ? Opět je odpověď přímočará, vezmeme „elementární" funkce g\{x) = siná; a #20*0 — COS Xj Q. 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. 37 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 n množiny {1,2, ...,n} je určena seřazením jejích prvků (pí,... ,Pn)- Pak 7T je zároveň bijektivním zobrazením {1,..., 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 {1,2,... ,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 ("inkrement"). Často se třeba lze setkat (aniž si to mnohdy uvědomujeme) 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ť 7T je permutace na množině A. Cyklem v n rozumíme posloupnost (a\, ci2, ■ ■ ■, cik) různých prvků A takovou, že 7r(aj) = a^+i pro i = 1,2,...,k — 1 a 7i(ak) = ai. Jak název napovídá, v zápise cyklu (cii, a2, • • •, dk) 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). Komentář: Nakreslete si (vámi zvolenou) permutaci tt obrázkem, ve kterém vedete šipku vždy od prvku i k prvku 7r(í). 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í látku. 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žině A lze zapsat jako složeni cyklů na disjunktních podmnožinách (rozkladu) A. Důkaz: Vezmeme libovolný prvek cii 1. Takto získáme první cyklus (a\,..., au)- 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ů (a\, ■ ■ ■, cik), (b\,..., h) až třeba (z\,..., zm). Pak zapíšeme vr = ((ai,..., ak) (61,..., h)... (zi,..., zm)). 38 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. 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 (bazických) prvků ci\, ci2, ■ ■ ■, «fc G M. • Je dán soubor induktivních pravidel typu Jsou-li (libovolné prvky) X\,... , xe G M, pak také y G M. V tomto případě je y typicky funkcí y = fi(x\,... ,xi). 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.8.) Pro nejbližší příklad induktivní definice se obrátíme na množinu všech přirozených čísel. -OéN - Je-li i G N, pak také í + lGN. Pro každé y G N můžeme definovat jinou množinu My C N induktivně takto: - y e My. - Jestliže x G My a x + 1 je liché, pak x + 2 G My. Pak například M3 = {3}, nebo M4 = {4 + 2% \ i G N}. Definice: Řekneme, že daná induktivní definice množiny M je jednoznačná^ právě když každý prvek M lze odvodit z bázických prvků pomocí induktivních pravidel právě jedním způsobem. Komentář: Definujme množinu M C N induktivně takto: 39 - 2,3 e M. - Jestliže x, y G M a x < y, 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ů ai,a2,---,«fc G M je určeno T{clí) = 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 ^-"(/(xi,... ,xe)) na základě hodnot ^(xi),... ,T{xi). Komentář: Pro příklad se podívejme třeba do manuálových stránek unixového příkazu test EXPRESSION: 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 Uvidíte, jak tato ukázka koresponduje s Definicí 6.8? Induktivní definice se „strukturální" indukcí Příklad 6.9. Jednoduché aritmetické výrazy Nechť (abeceda) S = {0,1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, (,)}. Definujme množinu jednoduchých výrazů SExp C S* 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. 40 Věta. Pro každý výraz s G S Exp 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 n", 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 S formalizací pojmu funkce a jejími vlastnostmi se setkáváte především v matematice, avšak například na bijektivní funkce narazíte při ukládání dat při volbě klíče apod. Pro informatiku jsou spíše důležitější relace a jejich skládání, na nichž je založena mimo jiné práce s relačními databázemi. Poslední částí lekce je problematika induktivních defínic, které ač ve formálním podání mohou nejprve vypadat nepochopitelně, jsou ve skutečnosti zcela přirozenou popisnou metodou v mnoha aplikačních sférách informatiky a jejich alespoň intuitivní chápání pro vás bude v dalším studiu nezbytné. Schválně, zkuste se podívat zrovna do vaší oblíbené oblasti informatiky, kde všude induktivní definice (třebaže nepřímo) najdete. 41 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 fílozofícká disciplína se intenzivně 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 kvantifíkace. 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 FI: 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. Poslední příklad už zase výrokem je. 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řijela ve 12:00 a šli jsme 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á tato kráva 10 nohou, mají všechny domy modrou střechu. Zastavme se na chvíli nad posledním výrokem. Co nám říká? Je pravdivý? Skutečně mají všechny domy modrou střechu a před námi stojí kráva s 10 nohama? Tuto problematiku jsme již neformálně nakousli v Lekci 1 a přesnou odpověď poskytne Definice 7.3 (ANO, výrok je pravdivý). 42 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. 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 deůnována induktivně následujícími pravidly: (1) ATC$. (2) Jestliže p/tp E $, pak také -n(ip) E $ a (p) =>- (ip) 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) => (^(B))) => ((^(B)) => (C)) A také příklady několika ne zcela správně utvořených formulí: A =>B, A=>B=>C, ~^A=>B Z těchto nesprávných ukázek je „nejhorší" ta prostřední, neboť daný zápis neumožňuje ani odhadnout, která z implikací se má vyhodnotit jako první. Abychom si ujasnili, která zjednodušení formálního zápisu formule jsou ještě přijatelná beze ztráty smyslu, přistoupíme k následující dohodě. 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 * p V tp (disjunkce) je jiný zápis formule -up =>- rtp, * p ľ\r(p (konjunkce) je jiný zápis formule ^(^pV^ý), * p ^ r(p (ekvivalence) je jiný zápis formule (p =>- rtp) A (tp =>- p). Komentář: Například formule (~^((A) => (B))) => {(^(B)) => (C)) se dá s naší konvencí zapsat jako (A^ B)V BVC. 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) = v(A) pro každé A E AT. ~ , \ _ / true jestliže Sv(p) = false: \ false jinak. ~ , ,\ _ [ false jestliže Sv(p) = true a Sv(rtp) = false: \ true jinak. 43 Tvrzení 7.4. Důsledkem této definice je následovné: * Sv(

- ijj) = true právě když platí jedna z následujících podmínek - Sv{ip) = true a současně Sv(íp) = true, - Sv(- B) V B V C? A B c A ^B (A^> B)VBVC 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 Definice: Formule

- ý. Tvrzení 7.6. Nékolik užitečných tautologií: * \^ AV^A * \= -n^A <=>■ A * ^(AA(A^B))^B * |= (-iß => -lA) => (A => B) * |= (-iA=> (5A-.5)) =>A Komentář: Kde jsme se s užitím takových tautologií už setkali? 44 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 tzv. normálním tvaru, kde se negace vyskytují pouze u výrokových proměnných, formálně: Definice: Formule p G $ je v normálním tvaru, pokud se v ní operátor negace aplikuje pouze na výrokové proměnné. 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." Tvrzení 7.7. Každou výrokov, formuli lze převést do normálního tvaru, pokud k =>- povolíme i užívání odvozených spojek A a V. Komentář: Pro ilustraci k —i(A => B) je ekvivalentní A A -*B, k -.(C A {-*A => B)) je ekvivalentní -.C V (-.A A -.£) a k -.((A => B) => C) je ekvivalentní (A => B) A -.C). Poznámka: Při dalším studiu logiky či logického programování se setkáte s různými jinými „normálními formami" výrokových formulí, například s konjunktivní či disjunktivní normální formou. S naší definicí mají všechny důležitý styčný bod - použití negací jen u proměnných. Normální tvar (formální postup) „Znegováním formule pcc se obvykle myslí převod její negace ~np do normálního tvaru. Jak jsme již demonstrovali na příkladě, normální tvar formule je „výrazně čitelnější" než formule používající zanořené negace. Proto následující formální postup induktivně definuje právě způsob převodu libovolné výrokové formule do našeho normálního tvaru. Metoda 7.8. Převod formule p do normálního tvaru T{p). Definujeme fvnktory T a Q pro náš převod induktivními předpisy T {A) = A g{A) = ^A T{-^p) = Q{p) Q^p) = T{p) T{(A => ->(B V ->(C => ->Ä))). Užitím postupu 7.8 získáme: f(n(A=>n(5Vn(C=>nA)))) = ff(A => n(ß V n(C => ni))) = f(4)AÖHßVn(C=>nA))) = 4Af(5Vn(C^nA)) AA(-F(5)V-F(-.(C=>--A))) = AA(BVG(C=>^A)) A A (B V (-F(C) A Q{^A))) = A A (B V (C A T{A))) AA(B\J(C A A)) 45 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. Důkaz tohoto tvrzení je zároveň velmi hezkou ukázkou použití strukturální matematické indukce. Věta 7.9. Pro libovolnou výrokovou formuli p platí, že a) F(p) je jí ekvivalentní formule v normálním tvaru b) a G(p) je formule v normálním tvaru ekvivalentní negaci -up. Důkaz povedeme tzv. „indukcí ke struktuře formule", tedy indukci povedeme podle „délky" í - počtu aplikací induktivních pravidel (Definice 7.1) při sestavování formule A je ekvivalentní ->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 F(ip) = F(p\ =^ P2) = F(p\) =>- T{$2). Podle indukčního předpokladu jsou F(p\) i F{$2) formule v normálním tvaru ekvivalentní p\ a p2. Potom i F(p\) =>- 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(ip) = G(p\ =>- P2) = F(p\) A G(p2)- Jelikož A je pro nás jen zkratka, výraz dále rozepíšeme G(ip) = ~n(F(pi) =>- ~^G(p2))- Podle indukčního předpokladu (a dvojí negace) jsou F(p\) a ~^G(p2) po řadě ekvivalentní formulím p\ a p2. Tudíž nakonec odvodíme, že G(tp) je ekvivalentní negaci formule p\^ p2l což jsme zde měli dokázat. tp = (pi\/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(ip) = F{-^pi =>- p2) = F{-^pi) =>- F(p2) je ekvivalentní formuli (~^p\ =>- p2) = tp, což bylo třeba dokázat. Stejně tak G(ip) = G(~^P\ =>■ P 2) = F(-npi) A G (p 2) je podle předchozích případů důkazu ekvivalentní (~^p\ A -1^2) = ~~,V'- tp = (pí A p2) a tp = (pí •£>• p2) 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í 46 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.

2) => Li{n). • Každé číslo n > 1, které není prvočíslem, je dělitelné nějakým číslem y kde n/p y> b VneN. (n > 1 A-iPr(n)) =>■ By(y\ n A n^y A y>l). 47 • Jsou-li R a S ekvivalence na M, je také Rö 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(BUS), kdežto ve druhém je i množina M parametrem VMVE,S : (Eq(M,R)AEq(M,S)) => Eq(M,RUS). D Příklad 7.13. Vpytlíku máme různobarevné kuličky. Vytáhneme libovolné tři z nich. Zamyslete se, proč je pak matematicky pravdivé následující tvrzení: • Je-li první kulička (z vytažených) větší než druhá a zároveň je druhá kulička větší než první, tak je třetí kulička červená. Řešení: Tento příklad je podobný Příkladu 1.4. Opět lze „selským rozumem" namítat, že je to přece úplná blbost - nemůže být první kulička větší než druhá a zároveň naopak, také nemůže být pravda, že třetí vytažená kulička je vždy červená. Jenže je potřeba se na uvedené tvrzení podívat matematicky. V prvé řadě, slova „libovolné tři" (z kuliček) vyjadřují všeobecnou kvantifikaci (V). Neboli uvedené tvrzení má být pravdivé pro každou trojici kuliček. Tvrzení samo je vysloveno jako implikace, takže je pravdivé vždy s výjimkou případů, kdy jsou splněny předpoklady a nepravdivý závěr. Jenže předpoklady (první kulička větší než druhá a zároveň naopak) nejsou splněny pro žádnou trojici kuliček a tudíž je naše tvrzení univerzálně platné. □ Jak „negovat" formule predikátové logiky? Metoda 7.14. Převod predikátové formule ip do normálního tvaru T(P(xi,...,xn) T^/x.ip) = Mx.T{(p) G(Vx. 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)). Rozšiřující studium Základem každého počítače jsou logické obvody, které jsou jen praktickou funkční implementací vhodných formulí výrokové logiky. Tudíž se dá směle říci, že bez výrokové logiky by nebylo ani počítačů, ani informatiky. Nadto se informatici setkávají po teoretické stránce 48 s výrokovou i predikátovou logikou nejen v matematice, ale i v logickém programování a nakonec i při psaní obyčejných složených podmínek v příkazu „ if "... IVa druhou stranu zájemce o studium matematických hlubin logiky a třeba slavných Godelových poznatků můžeme později odkázat na předmět Matematická logika MA007. 49 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 FI: IB000. Cíle IVa podkladě formálního zápisu algoritmů z Oddílu 1.4 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.4. 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í. 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. foreach i<— 1,2,3,...,n-l,n do 50 foreach 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 8.2 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 no a položme n = no + 1. Prvních no 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 + 1) + n0 + 1 = -(n0 + 1 + l)(n0 + 1) = -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"; foreach 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 2n° — 1 znaků ' z' a proměnná st bude obsahovat řetězec 2n° znaků 'z'. V poslední iteraci cyklu (pro i ^n=n0+l) vytiskneme dalších 2n° 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° = 2n°+l — 1 = 2n — 1 znaků ' z' a v st bude uloženo 2 • 2no = 2no+1 = 2n znaků 'z'. D 51 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 = {ci\, a2, • • •, cin} vytvoříme její symetrický uzávěr R takto: R +- R; foreach i<— 1,2,...,n-l,n do foreach j <— 1,2,...,n-l,n do if (ai}aj) G R A (a,j,ai) G" R then R <— R U{(a,-, 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é ko > 0 a dokažme jej i pro k = ko + 1. Zřejmě stačí uvažovat případ ko < n. Každá dvojice (a^, o,-) přidaná do R+ uvnitř cyklů musí náležet do fc-částečně tranzitivního uzávěru podle definice. Zbývá zdůvodnit, proč každá dvojice (a», cij) náležející do fc-částečně tranzitivního uzávěru, ale ne do fc0-částečně tranzitivního uzávěru, bude do R+ v k-té iteraci přidána. Není těžké ověřit, že (cii,aj) 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 cij, 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 (o^o,-) náleží do fc0-částečně tranzitivního uzávěru R. V k-té iteraci tudíž bude příslušná if podmínka splněná a (cii,aj) 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 f oreach cykly, přitom podle naší konvence obsahuje f oreach cyklus předem danou konečnou množinu hodnot pro řídící proměnnou, neboli náš f oreach 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či, 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 „parametry11 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 uy 0 do x <— min (U); (nejmenší prvek množiny) začínáme výpis cyklu ' (' ; while xGU do vytiskneme x; U <- U\{x} ; x <- vr(x) ; done ukončíme výpis cyklu ')' ; done 53 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ý. Podlé 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 U 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 = x^ dojde k ukončení našeho while cyklu. Nadto je tt prostá, a proto nemůže nastat x^ = Xj = tt(xj-i) pro j > 1. Takto byl nalezen a odebrán z U cyklus (cii, ■ ■ ■, CLk-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 „zbytkové" umocňování na velmi vysoké exponenty je podkladem 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 b > 0 do if b mod 2 > 0 then c <— (c-a) mod m; b <— |_b/2j ; a <— (a-a) mod m; done výsledek c ; Zde použijeme k důkazu správnosti algoritmu indukci podle délky í binárního zápisu čísla b. 54 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\ a d = (ab mod 2) 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 = d ■a'b' mod m = (ab mod 2 • a2L&/2j) 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é přirozené číslo x vypočteme dolní celou část jeho odmocniny r p^x; r <— 0; 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 f oreach 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 'f oreach i <— 1, . . .b do c <— c-a mod m 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 Smyslem této lekce bylo především ukázat, že u jednoduchých algoritmů lze (a je vhodné) matematicky dokazovat jejich správnost. Samozřejmé je iluzorní předpokládat, že obdobné důkazy správnosti podáme i pro velké softwarové projekty čítající až milióny řádků, ale postupy a techniky naučené při ověřování jednoduchých algoritmů s úspěchem využijete i při kontrole a ladění jednotlivých částí velkých projektů. Mimoto jsme se na příkladech pokusili ukázat několik zajímavých myšlenek a triků návrhu algoritmů, z nichž zvláště binární umocňování či centrální myšlenka „dynamického" Algoritmu 8.6 pro tranzitivní uzávěr se opakují v mnoha jiných algoritmech. O mnoha různých pokročilých technikách tzv. formální verifikace programů se v případě zájmu dozvíte v pokračujícím studiu. Tyto techniky jsou schopny na vhodném „modelu" rutinně a matematicky přesně ověřovat (ne)existenci různých běžných programátorských chyb. LV^J- 55 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í. Cíle Naším hlavním cílem je podání matematicky zcela přesné defínice 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é Vrat 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 FLIB000). * 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 N existuje nekonečně mnoho / G Fun s aritou a. 56 * Množina výrazů Exp je (induktivně) definována následující abstraktní syntaktickou rovnicí: E ::= x | n E\ -j- E/2 | E\ — E/2 | E\ * E/2 | -Ei ~r~ E2 (£-i) if £"i then £"2 else E3 fi V uvedené rovnici je x G Var, n G JVkto, £í G Exp jsou výrazy, / G Fun a a G IN je arita funkce /. Poznámka: Taková 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 a? — 1 then (2 + f (y)) else g(x, x) fi (Vyhodnocenípodmínky v „if" testuje nenulovost argumentu.) Definice: Deklarace (v jazyce Definice 9.1) je konečný systém rovnic tvaru JiyXi, , xai) kde pro každé 1 < i < n platí, že f i G Fun je funkce arity a,i, že x\,...,xai G Var jsou proměnné a Ei je výraz, v němž se mohou vyskytovat pouze proměnné X\,..., 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 a; then a; */(a; — 1) else 1 fi f(x) = g(x-l,x) g(x,y) = \f x then f (y) else 3 fi (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 fi • fix) = fix) (Nezapisuje toto náhodou „nekonečnou smyčku"?) = E, 57 Deklarace nám 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í. Neformálně řečeno, deklarace je tedy souborem pravidel pro určení hodnot funkcí s argumenty stojících na levé straně. Hodnoty jsou určeny běžnými aritmetickými výrazy používajícími číselné konstanty, argumenty funkce a hodnoty jiných zde deklarovaných funkcí. Tento poslední aspekt zavádí do deklarací „rekurzivnost" a dává tak deklaracím jejich „výpočetní sílu". Nedívejte se na deklarace v žádném případě pohledem procedurálního programování (tedy nejsou to žádná přiřazení hodnot proměnným), lépe na ně nahlédněte pohledem funkcionálního programování. 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 v následujících dvou definicích. Srovnejte si Definici 9.2 také s neformálním pojetím algoritmů jako konečných posloupností elementárních kroků v Oddíle 1.4. 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. - Jestliže E obsahuje funkční symbol /, pak / byl v A deklarován (tj. na levé straně některé rovnice A). Komentář: Dívejte se na množinu Exp(A) jako na soubor „platných vstupů" (jako u programu) pro deklaraci A, nad kterými bude prováděn výpočet. Fakt: Množinu Exp(A) lze definovat také induktivně: E ::= n | (Ei) | E\ -\- E2 | E\ — E2 | E\ * E2 | E\ -j- E2 /(.Ei, ■■■ ,Ea) | if Ei then E2 else E3 fi 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" \—> : Exp (A) —► Exp (A) definujeme induktivně takto; místo i—> (E) = F budeme psát E i—> F. • nun pro každé n G Num. • Pro E = (.Ei) definujeme krok výpočtu takto: * Jestliže Ei \—> F G Num, pak (Ei) \—> F. * Jestliže Ei \—> F G" Num, pak (Ei) i—> (F). • Pro E = Ex + E2 definujeme krok výpočtu takto: * Jestliže Ei,E2 G Num, pak Ei + E2 i—> z, kde z je dekadický zápis čísla Ei + E2. * Jestliže Ei g Num, pak Ex + E2 \-+ F + E2, kde Ex \-+ F. * Jestliže Ei G Num a E2 G" Num, pak Ex + E2 i—> Ex + F, kde E2 i—> F. • Pro E = E\ — E2 definujeme krok výpočtu takto: 58 * Jestliže Ei,E2 G Num, pak E\ — £2h->z, kde z je dekadický zápis čísla max{0, Ei — E2}. (Pozor na nezápornost výsledku odčítání!) * Jestliže Ei G" Num, pak Ex - E2 i—> F - E2, kde Ex i—> F. * Jestliže Ei G Num a E2 G" Num, pak Ei — E2 \—> Ei — F, kde E2 i—> F. • Pro E = E\ * E2 definujeme krok výpočtu takto: * Jestliže Ei, E2 G Num, pak E\ * E2 \—> z, kde z je dekadický zápis čísla E\ * E2. * Jestliže Ei G" Num, pak £1 * £2 i—>■ £ * £2, kde £1 i—> F. * Jestliže Ei G Num a £2 G" Num, pak £1 * E2 \—> Eľ * F, kde £"2 1—> £• • Pro E = E1 -^- E2 definujeme krok výpočtu takto: * Jestliže Ei,E2 G Num, pak Ei 4- £2 1—> 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" ÍVkto, pak £: 4- £2 1—>■ £ 4- £2, kde £1 1—> £. * Jestliže £1 G JVkto a £2 G" ÍVkto, pak £i 4- £2 1—> £1 4- £, kde £2 1—> £. • Pro E = if í^i then .E2 else .E3 fi definujeme krok výpočtu takto: * Jestliže £1 G JVkto a Ex = 0, pak if Ex then £2 else £3 f i 1—> (£3). * Jestliže £1 G JVkto a £1 ^ 0, pak if £1 then £2 else £3 fi 1—> (£2). * Jestliže £1 G" JVkto, pak if £1 then £2 else £3 f i 1—> if £ then £2 else £3 fi, kde Ei \-+F. • Pro E = /(.Ei, • • • , Ek) definujeme krok výpočtu takto: * Jestliže Ei,- ■ ■ , Ek G Num, pak f (Ei, ■ ■ ■ ,Ek) 1—> (£/(xi f£i,- • • ,xk \Ek)). (V tomto formálním zápise se jedná o prosté „textové" dosazení hodnot Ei za proměnné x i v deklaraci £/ funkce f v A.) * Jinak f (Ei, ■ ■ ■ ,Ek)\-^ f(E1, ■■■ , £j_i, £, Ei+1, ■ ■■ ,Ek),kdei je nejmenší index pro který platí £» G" JVkto a £» 1—> F. V zápise jednotlivých bodů vždy platí, že £i,£2, • • • 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 zleva. Reßexivni a tranzitivní uzávěr relace 1—> značíme 1—>* („výpočet11). 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 £, a to na prvním možném místě zleva. Mimo jiné je takto „definována" nejvyšší priorita vyhodnocení uzávorkovaného výrazu. 59 Uvědomte si dobře, že definice výpočetního kroku i—> je (poněkud skrytě) rekurzivní. Třeba krok (2 * 1) i—> 2 je ve 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 fi. Pak třeba /(3) h->* 6, neboť /(3) \-> if 3 then 3 * /(3 - 1) else 1 fi (->■ 3 */(3 - 1) i-> 3*/(2) (->■ 3 * (if 2 then 2 */(2 - 1) else 1 fi) (->■ 3 * (2 */(2 - 1)) i-> 3* (2*/(l)) (->■ 3 * (2 * (if 1 then 1 */(l - 1) else 1 fi)) (->■ 3*(2*(1*/(l-l))) i-> 3*(2*(l*/(0))) i->-3*(2*(l*(if0 then 0*/(0-l) else 1 fi))) 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 fi. Pak například /(3)—*/(3), neboť /(3) i-»- g (3 - 1, 3) i-»- g(2, 3) i-»- if 2 then /(3) else 3 f i i—>■ /(3). Uvažme deklaraci f (x) = f (x). Pak pro každé n G Num platí /(n) -, /(n) a podobně /(/(n)) -, /(/(n)). Ale /(/(2 + 3)) k-, /(/(5)) k-, /(/(5)). D Poznámka: Všimněte si, že při našich úpravách výrazů si dovolujeme vynechávat zbytečné „vnější" závorky kolem celého výrazu. Příklad 9.4. Jak bude přesně vyhodnocen následující výraz? 1+2-3+4-5 Řešení: Klíčem k řešení tohoto je správné pochopení Definice 9.2. Prvním použitelným pravidlem našeho deklarativního jazyka je to pro E = E\ + E2. Je použito na prvním místě zleva, tj. pro E\ = 1 a E2 = 2 — 3 + 4 — 5. Podle definice je tedy nutno upravit E\ G Num i E2 $. Num, neboli definici aplikovat (rekurzivně) na výraz E2. Při vyhodnocování E2 = E' = 2 — 3 + 4 — 5 je prvním použitelným pravidlem opět to pro E' = E[ + E'2, přičemž E[ = 2 — 3 a E'2 = 4 — 5. Podle definice je nutno v tomto místě vyhodnotit výraz E[ \—> 0. Celkem v prvním kroce 1 + 2-3 + 4-5 i-»- 1+0+4-5. Nakonec stejným postupem získáme: 1 + 0 + 4-5^1 + 0 + 0^1 + 0^1 D 60 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.5. Pro ukázku uvažme deklaraci A obsahující pouze rovnici f(x) = if x then x * f (x — 1) else 1 fi. 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 1 fi ■->• 1 a také 0! = 1. • Indukční krok. Nechť n + 1 = k. Pak /(k) ^ if k then k * /(k - 1) else 1 fi ■->• k * /(k - 1) ■->• k * /(w), kde w = k — 1 = n. Podle LP. platí /(w) i—>* u, kde u = n\. Proto k * /(w) i—>* k * u i—> 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.6. Buď A deklarace. Pro každé i G N definujeme relaci \—>% C Exp(A)xExp(A) předpisem \—>% = vi—> o • • • o i—>y Dále definňoricky klademe \—> ° = {(E,E) \ E G i Exp(A)}. Pak (relace „výpočet") platí \—>* = \J°10 i—>%. Podle předchozí věty platí, že E \—>* F právě když E i—> * F 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.7. 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 IN takové, že /(n) i—>% m. Jelikož výrazy /(n) a m jsou různé, platí i > 0. Jelikož i—>% = i—> *—1 o i—> a /(n) i—> /(n), platí /(n) i—> t~1 m, což je spor s minimalitou i. □ Rozšiřující studium Místo suchého studia si pro lepší seznámení s naším deklarativním jazykem mohou čtenáři pohrát s jeho online interpretem poskytnutým Vaškem Brožkem na http://arran.fi.muni.cz/ibOOO/web_vyhodnot.cgi. Také je velmi vhodné si srovnat zde předloženou látku s předměty vyučujícími tzv. funkcionální programování (na FI třeba IB015). K samotnému pokročilému dokazování vlastností deklarativních algoritmů přistoupíme v příští lekci. 61 10 Důkazové postupy pro algoritmy Úvod Nakonec 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. Soustřeďte se v ukázkách důkazů na pochopení, jak jednotlivé formální matematické kroky korespondují s průběhem algoritmů. 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 fi. Věta. Pro každé m, n G IN platí g (m, n) i—>* z, kde z = m ■ n. Důkaz: Budiž n G IN 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 fi h-> 0. * Indukční krok. Nechť m + 1 = k. Pak fif(k, n) i—> if k then n + n + g(k — l,n) i—> n + g(w,n). kde je w = m. Podle LP. platí g(w, n) i—>* u pro u = m ■ n. Dále n + g(w, n) i—>* n + u i—> v, kde v = n + (m • n) = (m + 1) • n = k ■ n, a tím jsme dohromady hotovi s důkazem 9(K n) h->* v. D 10.2 Technika „indukce k součtu parametru" 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) else 0 fi) else 0 fi. 62 Věta. Pro každé m, n G IN platí g (m, n) i—>* 0. 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) h->* 0. Platí 0(0, 0) i-»- if 0 then (if 0 then g(0 -1,0)+ g(0, 0-1) else 0 fi) else 0 fi ■->• 0 . Indukční krok. Nechť z + 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) h^ if 0 then (if n then g(0 - 1, n) + g(0, n - 1) else 0 fi) else 0 fi \-^> 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 fi) else 0 f i i—> h^ if 0 then g(m - 1,0) +g(m, 0 - 1) else 0 fi \-^> 0. * Pro m > 0, n > 0 platí fif(m, n) i—> if m then (if n then g (m — 1, n) + g(m, n — 1) else 0 fi) else 0 f i i—> i—>■ if n then g (m — 1, n) + g(m, n — 1) else 0 fi i—> g (no. — 1, n) + g(m, n — 1). Podle LP. platí g(m — l,n) i—>* 0 a současně g(m,n — 1) i—>* 0, proto <7(m — l,n) + <7(m, n — 1) i—>* 0 + g(m, n — 1) i—>* 0 + 0 i—> 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) else 1 fi) else 1 fi. Věta. Pro každé m, n G N platí g (m, n) i—>* k, kde k = ("^ra) (kombinační číslo). 63 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 a + 1\ / a \ fa 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) \—>* 1. Platí 0(0, 0) i-»- if 0 then (if 0 then g(0 -1,0)+ g(0, 0-1) else 1 fi) else 1 fi ■->• 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í (™) = 1 a g(0, n) i—> if 0 then (if n then g(0 — 1, n) + g(0, n — 1) else 1 fi) else 1 fi i—> 1. * Pro m > 0, n = 0 platí Q = 1 a fif(m, 0) i—> if m then (if 0 then g (m — 1,0)+ g(m, 0 — 1) else 1 fi) else 1 fi i—> i—> if 0 then g (m — 1,0)+ g(m, 0 — 1) else 1 fi i—> 1. * Pro m > 0, n > 0 platí fif(m, n) i—> if m then (if n then g (m — 1, n) + g(m, n — 1) else 1 fi) else 1 fi i—> i—>■ if n then g (m — 1, n) + g(m, n — 1) else 1 fi i—> g (no. — 1, n) + g(m, n — 1). Podle LP. platí g (m — l,n) i—>* kí, kde kí = ("l?^_HL"'), a současně g(m,n — 1) i—>* k2, kde k2 = (m^~ )• Přitom z Pascalova trojúhelníka plyne m + n — 1\ /m + n — l\ f{m + n — 1) + l\ fm + n m — l/V m J \ m J \ m a proto /Tí- + 77 gr(m — 1, n) + g(m, n — 1) i—>* kí + k2 i—>* k D 10.3 Technika „zesílení dokazovaného tvrzení" 55 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: f(x) = if x then h(x) else 1 fi h(x) = if x then f (x — 1) + h(x — 1) else 1 fi 64 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í f (n) \—>* m a h(n) \—>* m, kde m = 2n. Důkaz, již poměrně snadno indukcí vzhledem k n: * Báze n = 0. Platí /(O) i—*- if 0 then h(0) else 1 fi i—> 1, kde 2° = 1. h(0) i-»- if 0 then /(O - 1) + h(0 - 1) else 1 fi ■->• 1. * Indukční krok: Nechť n + 1 = k, pak platí /(k) i—> if k: then h(k) else 1 f i •—> h(k) \-^ ^ if k then /(k - 1) + h(k - 1) else 1 fi ^ f(k-l)+h(k-l) ^ /(w)+/i(k-l), 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 f(w) + h(k—l) \—** m + h(k—l) i—>* m + /i(w) i-^-* m + m i-^- q. kde q = m + m = 2m = 2 • 2ra = 2n+l = 2k. Proto tranzitivně f (k) \—> 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) + h(k - 1) else 1 f i i—> /(k-l) + fc(k-l) ^* /(w) + Mk-l), kde w = k — 1 = n. Podle LP. platí /(w) i—>* m, kde m = 2n, a také /i(w) i—>* m, tudíž opět f(w) + h(k—l) \—** m + h(k—l) \—>* m + h(w) \—^* m + m i-^- q. kde q = m + m = 2-2n = 2n+1 = 2k. Proto h(k) i-> qai druhá část našeho tvrzení platí pro n + 1 = k. □ 10.4 Dva dobře známé školní algoritmy Následuje příklad, který zajisté každý, kdo přičichl k programování, už v nějaké podobě pozná. My si jej uvádíme především z výukových důvodů. Číslice dekadického zápisu Příklad 10.5. Mějme přirozené číslo x. Jednotlivé číslice i-tého řádu jeho dekadického zápisu získáme deklarací c(x, i) = if i then c(x 4- 10, i — 1) else x — 10 * (x 4- 10) fi. Dokažte: 65 Věta. Pro každá m, i G IN platí c(m, i) i—>* s, kde s je číslice řádu i (počítáno od nultého zprava) v dekadickém zápise čísla m, nebo s = 0 v případě, že dekadický zápis čísla m má méně než i + 1 číslic. Důkaz: Použijeme techniku fixace parametru m při indukci podle i. * Báze i = 0. Platí c(m, 0) i—>* m — 10 * (m 4- 10) i—>* t, kde t = m mod 10 . V tomto výsledku mod znamená známou funkci modulo definovanou vztahem x = [x/y\ ■ y + (x mod y). Tudíž t je poslední číslici dekadického zápisu m. * Indukční krok: Nechť i + 1 = j, pak platí c(m, j) i—> if j then c(m 4- 10, j — 1) else m — 10 * (m 4- 10) fi i—> K^c(m4 10, j - 1) i-^*c(p,w), kde p = |_?tt./10J a w = j — 1 = i. Podle LP. platí c(p, w) i—>* t a ŕ je číslice z-tého řádu dekadického zápisu čísla p. Jelikož m = lOp + (m mod 10) a násobení deseti v dekadické soustavě znamená posun číslic v zápise „o jedno doleva", je t zároveň číslice i + 1 = j-tého řádu dekadického zápisu čísla m. To je přesně co bylo třeba dokázat.n Euklidův algoritmus Již z dávných dob antiky pochází následující zajímavý a koneckonců velmi jednoduchý algoritmus teorie čísel. (Víte, pro zajímavost, jestli se tehdy vůbec mluvilo o algoritmech a programech, nebo jako to bylo?) Věta 10.6. 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 fi) fi. Pak pro každé nenulové m, n G 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) h^ if 1 - 1 then g(l - 1,1) else (if 1 - 1 then g(l, 1-1) else 1 fi) fi ^ \-^> if 0 then g(l - 1,1) else (if 1 - 1 then g(l, 1-1) else 1 fi) fi \-^> h^ if 1 - 1 then g(l, 1-1) else 1 fi \-^> if 0 then g(l, 1-1) else 1 fi \-^> 1. Indukční krok. Nechť i + 1 = m + n kde m, n G 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 fi) fi i—> if 0 then g (m — n, n) else (if n — m then g(m, n — m) else m fi) fi i—> if n — m then g(m, n — m) else m fi i—> if 0 then g(m, n — m) else m fi i—> m . 66 * m if m — n then g (m — n, n) else (if n — m then g(m, n — m) else m fi) fi i—> if O then g (m — n, n) else (if n — m then g(m, n — m) else m fi) fi i—> if n — m then g(m, n — m) else m fi i—> if z then g(m, n — m) else m fi i—> gf(m, n — m) i—> g(m, k). kde k = n —m. Platí m+fc = m + {n — m) = n < i, takže podle LP. také platí g(m, k) i—>* 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 fif(m,n) h^* #(m-n,n) h^ #(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. g 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? 67 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 sprá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 in-jektivní 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: 9(0) = 0. 1 5427578325... 9(1) = 0. 2 9(2) = 0. 1 2(3) = 0. 3 2(4) = 0. 9 68 Nyní sestrojíme číslo a G (0,1) následovně; jeho z-tá číslice za desetinnou čárkou bude 1, pokud v z-tém řádku tabulky na diagonále není 1, jinak to bude 2. V našem příkladě « = 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 G M takové, že g (x) = K. Nyní rozlišíme dvě možnosti: - x G 5f(x). Tj. x E K. Pak ale x G" g (x) z definice X, spor. - x G" fif(x). To podle definice X znamená, že x G X, tj. x G která je spočetně nekonečná. Existuje tedy bijekce / mezi množinou N a množinou všech programů. Pro každé i6N označme symbolem Pí program f (i). Pro každý program P tedy existuje j G N takové, že P = P j. * Každý možný vstup každého možného programu lze zapsat jako konečnou posloupnost symbolů z konečné mnočiny V. Množina všech možných vstupů je tedy spočetně nekonečná a existuje bijekce g mezi množinou N a množinou všech vstupů. Pro každé i G N označme symbolem Ví vstup g (i). 70 * Předpokládejme, že existuje program Halt, který pro dané i, j G N zastaví s výstupem ano/ne podle toho, zda Pí pro vstup Vj zastaví, nebo ne. * Tento předpoklad dále dovedeme ke sporu dokazujícímu, že problém zastavení nemá algoritmické řešení. Tvrzení 11.4. Předpoklad existence programu Halt vede ke sporu. Důkaz: Uvažme program Ľiag s následujícím kódem: input k; if iía/ŕ(k,k) =ano then while true do ; done (Program Diag(k) má na rozdíl od Halt jen jeden vstup k, což bude důležité.) Fungování programu Diag lze znázornit za pomocí následující tabulky: _____Pq P\ f2 Pj Vo V - - V ■■■ Vi V - - V ■■■ v2 - y - y ••• Vs - - V V ••■ Symbol \J resp. — říká, že program uvedený v záhlaví sloupce zastaví resp. nezastaví pro vstup uvedený v záhlaví řádku. Program Diag „zneguje" diagonálu této tabulky. Podle našeho předpokladu {Diag je program a posloupnost Pí zahrnuje všechny programy) existuje j G N takové, že Diag = Pj. Zastaví Diag pro vstup Vp. - Ano. Podle kódu Diag pak ale tento program vstoupí do nekonečné smyčky, tedy nezastaví. - JVe. Podle kódu Diag pak ale if test neuspěje, a tento program tedy zastaví. Předpoklad existence programu Halt tedy vede ke sporu. □ Komentář: Otázkami algoritmické (ne)řešitelnosti problémů se zabývá teorie vyčíslitelnosti. Metoda diagonalizace se také často využívá v teorii složitosti k důkazu toho, že dané dvě složitostní třídy jsou různé. Rozšiřující studium Látka této lekce zabrousila až do teoretických hlubin matematické logiky a teorie množin. Další studium v těchto oblastech se dá očekávat hlavně u studentů specifícky zaměřených teoretickým směrem (a mířících spíše do akademické než aplikační sféry), zajímajících se o matematiku samotnou nebo o teorii vyčíslitelnosti. Proto také uvedené pokročilé poznatky nebudou vyžadovány u zkoušky tohoto předmětu. 71 12 Délka výpočtu algoritmu Úvod Mimo samotné správnosti výsledku vypočteného zapsaným algoritmem je ještě jedno neméně důležité hledisko k posouzení vhodnosti algoritmu k řešení zadané úlohy. Jedná se o čas, který algoritmus stráví výpočtem. Asi netřeba argumentovat, že přehnaně dlouhá doba odezvy programu je každému uživateli nepříjemná. A co třeba v real-time systémech, kde si zdržení prostě nemůžeme dovolit. Obligátní odpověď „kupme si rychlejší počítač" bohužel není vždy řešením, jak při pokročilém studiu složitosti algoritmů sami poznáte. Mnohem větší potenciál zrychlení se skrývá v algoritmech samotných a jejich efektivním návrhu. Cíle V této lekci defínujeme délku výpočtu algoritmu, přičemž deňnici postavíme na deklarativním jazyce z Lekce 9. Poté si ukážeme, jak se matematicky popisuje asymptotické chování funkcí, což se využívá především pro zjednodušené studium složitosti výpočtu algoritmu. 12.1 O významu délky výpočtu algoritmu Uvažme deklarativní jazyk Definice 9.1. Definice: Délkou výpočtu výrazu F nad deklarací A rozumíme nejmenší přirozené k takové, že pro něj existuje m G Num pro něž F \—> 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*6 h+ 3 + 4-30 h+ 3 + 0 h+ 3. * 3 + (5 - 4) * (6 4- 2); tentokrát čtyři kroky 3 + (5 - 4) * (6 4 2) h+ 3 + 1 * (6 4 2) h+ 3 + 1*3 h+ 3 + 3 h+ 6. * 2010 ; žá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 fi. 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í /(0) i—> if 0 then 0 * /(O — 1) else 1 fi i—> 1, což jsou přesně 2 kroky, tj. 4-0 + 2. • Indukční krok. Nechť n + 1 = k. Pak /(k) i-»- if k then k */(k - 1) else 1 fi ■->• 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 72 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é. 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(ri) = n2 roste (zhruba) stejně rychle jako fin) = lOOOOOOOOn2 i jako f"(n) = O.OOOOOOOln2 - lOOOOOOOOn - fOOOOOO. 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 : R —► IR je daná funkce. Pro funkci / : R, —► R, píšeme f £ 0(g) pokud existují konstanty A, B > 0 takové, že Vne R+ : f(n) < A ■ g(n) + B . V praxi se obvykle (i když matematicky méně přesně) píše místo f E 0(g) výraz f(n) = 0(g(n)). Znamená to, slovně řečeno, že funkce / neroste rychleji než funkce g. (I když pro malá n třeba může být f(n) mnohem větší než gin).) Poznámka: Kromě vlastnosti / G O(g) se někdy setkáte i s vlastností / € o(g), která znamená linvj^oo ^y = 0 (funkce / roste striktně pomaleji než g). Definice: Píšeme / G n( 0 je polynomiálnífunkce, * f(n) = ^(cra) pro nějaké c > 1 je exponenciální funkce. Příklad 12.2. Příklady růstů různých funkcí. Funkce f(n) = @(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 + \fn, atd. Funkce f(n) = @(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 ^ 10300 byste už na řádek nenapsali. Pro n = 10000 je rozdíl ještě mnohem výraznější! □ Příklad 12.3. (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.4. foreach i<— 1,2,3,...,n-l,n do foreach j <— 1,2,3,...,i-l,i do vytiskni 'x' ; done done 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 po 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). □ 12.3 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ů. Lema 12.5. Nechi cii,..., a^, c > 0 jsou klaáné konstanty takové, že a\ + • • • + a^ < l, a funkce T : N —► IN splňuje nerovnost T(n) < T(\ain\) + T(\a2n\) + ••• + T(\akn\) + cn . PakT(n) = 0(n). 74 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 > n0. 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 ri\ > no je libovolné. Nyní dokážeme i pro n\ T {ni) < T{ \ain{\) -\--------\-T{ \akn{\) + cnx < < d ■ \aiiii\ + • • • + d ■ [ßfcni] + cn\ < < d ■ (1 — e)n\ + cri\ < dri\ — {ed — c)ri\ < dri\. D Lema 12.6. Nechi k > 2 a ai,..., a,k, c> 0 jsou kladné konstanty takové, že a\ + • • • + cik = 1, a funkce T : N —► N splňuje nerovnost T{n) < T{\am]) + T(\a2n]) + ••• + T(\akn\) + cn . (1) Pak T{n) = 0{n ■ logn). Důkaz (poněkud 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 {ni) na levé straně). Jelikož a\ + • • • + ak = 1, součet hodnot argumentů všech T(-) ve zpracovávaném výrazu bude stále zhruba n. Navíc po zhruba t = 6(logn) 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' {^) + n. □ V obecnosti je známo: Lema 12.7. Nechť a > 1, b > 1 jsou konstanty, f : N —► IN je funkce a pro funkci T : N —► IN platí rekurentní vztah T{n) 1 a T(n) = O(nlog23) ~ 0(nL585), což je výrazně rychlejší než školní postup v čase 0(n2) pro velká n. □ Rozšiřující studium Poslední lekce našeho učiva nás dovedla do zajímavé a užitečné oblasti výpočetní složitosti. S problematikou zjišťování délky výpočtu („rychlosti") algoritmu se studenti určitě setkají v předmětech zabývajících se návrhem algoritmů. Alespoň základní znalost problematiky složitosti by měl mít každý programátor, aby dokázal psát rozumně efektivní programy. Na otázky rychlosti algoritmů pokročile navazuje teorie výpočetní složitosti, která se dále zabývá otázkami, proč pro mnohé problémy efektivní algoritmy neexistují (a existovat nejspíše ani nemohou). Později se tak studenti setkají třeba s pojmem NP-úplnosti -základním kritériem „ efektivní neřešitelnosti" problému. 77 Závěrem Gratulujeme všem, kteří se naším nelehkým učebním textem „prokousali" až sem, a přejeme mnoho úspěchů v dalším studiu informatiky. Konečně znovu připomínáme, že nedílnou součástí našeho studijního textu je Interaktivní osnova předmětu IBOOO v IS MU a v ní přiložené online odpovědníky určené k procvičování přednesené látky. http://is.muni.cz/el/1433/podzim2010/IB000/index.qwarp 78