Úvod do Informatiky (FI: IBOOO) Doc. RNDr. Petr Hliněný, Ph.D. hlinenySf i.muni.cz 16. listopadu 2007 N^tis mPo % '^AS u^ Lehký a dobře přístupný úvod do nezbytných formálních základů moderní informatiky; učební text pro předmět IBOOO na FI MU od roku 2006... Postaveno na původních přednáškových slidech Doc.RNDr. Antonína Kučery, Ph.D., FI MU 2005. Verze 0.999. © 2006-2007 Petr Hliněný. 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. 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. Doplňkovou součástí celého výukového textu jsou interaktivní osnova předmětu IB000 v IS MU a z ní odkazované online odpovědníky sloužící k procvičování probrané látky na jednoduchých i složitějších příkladech. To je také důvod, proč texto text obsahuje jen velmi málo příkladů k probírané látce; od každého studenta očekáváme, že si látku bude procvičovat online na zmíněných odpovědnících, obsahujících až tisíce příkladů desítek typů. (K praktickému pochopení přednesených znalostí i k jejich budoucím aplikacím je takové procvičení zcela nezbytné!) n Obsah 0.1 O tomto textu a jeho studiu......................... ii 1 Základní formalismy: Důkaz a Algoritmus 1 1.1 Úvod do matematického dokazování..................... 1 1.2 Struktura matematických vět a důkazů................... 2 1.3 Formální popis algoritmu........................... 4 2 Důkazové techniky, Indukce 5 2.1 Přehled základních důkazových technik................... 6 2.2 Věty typu „tehdy a jen tehdy"........................ 7 2.3 Matematická indukce............................. 8 2.4 Komentáře k matematické indukci...................... 10 3 Množiny, Relace a Funkce 12 3.1 Pojem množiny................................ 12 3.2 Množinové operace.............................. 14 3.3 Porovnávání a určení množin......................... 16 3.4 Relace a funkce mezi (nad) množinami................... 17 3.5 Posloupnosti a rekurentní vztahy ...................... 19 4 Binární relace, Ekvivalence 20 4.1 Reprezentace konečných relací........................ 20 4.2 Vlastnosti binárních relací.......................... 21 4.3 Relace ekvivalence .............................. 23 4.4 Rozklady a jejich vztah k ekvivalencím................... 23 5 Uspořádané množiny, Uzávěry 25 5.1 Uspořádané množiny............................. 25 5.2 Další pojmy uspořádaných množin ..................... 27 5.3 Hasseovské diagramy............................. 29 5.4 Uzávěry relací................................. 29 6 Vlastnosti funkcí a Skládání relací 30 6.1 Vlastnosti funkcí ............................... 31 6.2 Inverzní relace a skládání relací....................... 31 6.3 Skládání relací „v praxi"........................... 32 6.4 Skládání funkcí, permutace.......................... 34 6.5 Induktivní definice množin a funkcí..................... 36 7 Jemný úvod do Logiky 38 7.1 Výroky v „přirozené" podobě........................ 38 7.2 (Formální) výroková logika.......................... 39 7.3 Jak správně „znegovat formuli"?....................... 40 7.4 Predikátová logika, kvantifikace....................... 42 m 8 Dokazování vlastností algoritmů 44 8.1 O „správnosti" programů........................... 44 8.2 Jednoduché indukční dokazování....................... 44 8.3 Algoritmy pro relace............................. 46 8.4 Zajímavé algoritmy aritmetiky........................ 48 9 Jednoduchý deklarativní jazyk 49 9.1 Popis jednoduchého deklarativního jazyka................. 50 9.2 Formalizace pojmu „výpočet"........................ 52 9.3 Příklady výpočtů a důkazů.......................... 54 10 Důkazové postupy pro algoritmy 55 10.1 Technika „fixace parametru"......................... 55 10.2 Technika „indukce k součtu parametrů"................... 56 10.3 Technika „zesílení dokazovaného tvrzení".................. 58 10.4 Dva „klasické" algoritmy........................... 58 11 Nekonečné množiny a zastavení algoritmu 61 11.1 O kardinalitě a nekonečných množinách................... 61 11.2 Algoritmická neřešitelnost problému zastavení............... 63 12 Délka výpočtu algoritmu 64 12.1 O významu délky výpočtu algoritmu.................... 65 12.2 Asymptotické značení a odhady funkcí................... 66 IV 1 Základní formalismy: Důkaz a Algoritmus Úvod Začněme nejprve několika obecnými poznámkami ke smyslu a směřování celého našeho předmětu: Jak sami poznáte, studium informatiky neznamená jen „naučit se nějaký programovací jazyk", nýbrž zahrnuje celý soubor dalších relevantních předmětů, mezi nimiž najdeme i matematicko-teoretické (formální) základy moderní informatiky. Právě odborný nadhled nad celou informatikou včetně nezbytné formální teorie nejspíše odliší řadového „programátora", kterých jsou dnes spousty i bez VS vzdělání, od skutečného (a mnohem lépe placeného) IT experta. A na tomto místě nyní přichází náš předmět Úvod do Informatiky, který (i přes svůj nepříliš obsažný název) vás právě na studium těchto formálních základů moderní informatiky připraví. Cíle Prvním cílem této lekce je formálně rozebrat struktury matematických tvrzení (vět) a jejich formálních důkazů. V druhém sledu se naučíme obdobným způsobem formálně přesně zapisovat postupy, čili algoritmy. 1.1 Úvod do matematického dokazování Matematika (a tudíž i teoretická informatika jako její součást) se vyznačuje velmi přísnými formálními požadavky na korektnost argumentace. Takto korektně postavená argumentace vede od přijatých předpokladů v elementárních směrem k požadovanému závěru (a nikdy ne naopak!). Definice 1.1. Matematický důkaz . Uvažme matematickou větu (neboli tvrzení) tvaru „Jestliže platí předpoklady, pak platí závěr. Důkaz této věty je konečná posloupnost tvrzení, kde • každé tvrzení je bud * předpoklad, nebo * obecně přijatá „pravda" - axiom, nebo * plyne z předchozích a dříve dokázaných tvrzení podle nějakého „akceptovaného" logického principu - odvozovacího pravidla: • poslední tvrzení je závěr. Komentář: O potřebné úrovni formality matematických důkazů a o běžných důkazových technikách se dozvíme dále v této a příští lekci... Nyní si prostě celou problematiku uvedeme názornými příklady. Příklad 1.2. Uvažujme následující matematické tvrzení (které jistě už znáte). Věta. Jestliže x je součtem dvou lichých čísel, pak x je sudé. Poznámka pro připomenutí: 1 - Sudé číslo je celé číslo dělitelné 2, tj. tvaru 2k. - Liché číslo je celé číslo nedělitelné 2, tj. tvaru 2k + 1. Důkaz postupuje v následujících formálních krocích: tvrzení zdůvodnění 1) a = 2k + 1, k celé předpoklad 2) b = 21+ 1,1 celé předpoklad 3) x = a + b = 2k + 2l + l + l 1,2) a komutativita sčítání (axiom) 4) x = 2(k + l) + 2-l 3) a distributivnost násobení 5) x = 2(k + l + l) 4) a opět distributivnost násobení 6) x = 2m, m celé 5) am = fc + l + 1 je celé číslo (axiom) Příklad 1.3. Dokažte následující tvrzení: Věta. Jestliže x a y jsou racionální čísla pro která platí x < y, pak existuje racionální číslo z pro které platí x < z < y. Důkaz po krocích (s již trochu méně formálním zápisem) zní: . Nechť z = ^=x + ^=y-^. • Číslo z je racionální, neboť x a y jsou racionální. . Platí z > x, neboť ^ > 0. • Dále platí z < y, opět neboť ^^ > 0. • Celkem x < z < y. n Poznámka. Alternativní formulace Věty z Příkladu 1.3 mohou znít: - Pro každé x, y € (Q, kde x < y, existuje z € (Q takové, že x < z < y. - Množina racionálních čísel je hustá. 1.2 Struktura matematických vět a důkazů První krok formálního důkazu je uvědomit si, co se má dokázat, tedy co je předpoklad a co závěr dokazovaného tvrzení. Komentář: Příklady formulace matematických vět: * Konečná množina má konečně mnoho podmnožin. * sin2(a) +cos2(a) = 1. * Graf je rovinný jestliže neobsahuje podrozdělení K^ nebo K§*,. Často nám k lepšímu pochopení toho, co je třeba dokázat, pomůže pouhé rozepsání definic pojmů, které se v dané větě vyskytují. Jak „moc formální" mají důkazy vlastně být? 2 • Záleží na tom, komu je důkaz určen — „konzument" musí být schopen „snadno" ověřit korektnost každého tvrzení v důkazu a plně pochopit, z čeho vyplývá. • Je tedy hlavně na vás zvolit tu správnou úroveň formálnosti zápisu vět i důkazů podle situace. Konstruktivní a existenční důkazy Z hlediska praktické využitelnosti je potřeba rozlišit tyto dvě kategorie důkazů (třebaže z formálně-matematického pohledu mezi nimi kvalitativní rozdíl není). • Důkaz Věty 1.3 je konstruktivní Dokázali jsme nejen, že číslo z existuje, ale podali jsme také návod, jak ho pro dané x a y sestrojit. • Existenční důkaz je takový, kde se prokáže existence nějakého objektu bez toho, aby byl podán návod na jeho konstrukci. Příklad 1.4. čistě existenčního důkazu. Věta. Existuje program, který vypíše na obrazovku čísla tažená ve 45. tahu sportky v roce 2007. Důkaz: Existuje pouze konečně mnoho možných výsledků losování 45. tahu sportky v roce 2007. 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 2007 skutečně vylosován. D Komentář: To je ale „podvod", že? A přece není... Formálně správně to je prostě tak a tečka. Fakt. Pro informatické i další aplikované disciplíny je důležitá konstruktivnost důkazů vět, které se zde objevují. V matematice ale jsou mnohé příklady užitečných a nenahraditelných existenčních důkazů, třeba tzv. pravděpodobnostní důkazy. Příklad 1.5. „pravděpodobnostního" existenčního důkazu. Věta. Na dané množině bodů je zvoleno libovolně n2 podmnožin, každá o n prvcích. Dokažte pro dostatečně velká n, že všechny body lze obarvit dvěma barvami tak, aby žádná množina nebyla jednobarevná. Důkaz: U každého bodu si „hodíme mincí" a podle výsledku zvolíme barvu červeně nebo modře. (Nezávislé volby s pravděpodobností \.) Pravděpodobnost, že zvolených n bodů vyjde jednobarevných, je jen ^ = 21~n. Pro n2 podmnožin tak je pravděpodobnost, že některá z nich vyjde jednobarevná, shora ohraničená součtem 77 2l~n + ... + 2l~n =-----r-»O. --------------v--------------' 2n~l n2 Jelikož je toto číslo (pravděpodobnost) pro n > 7 menší než 1, bude existovat obarvení bez jednobarevných zvolených podmnožin. D 3 1.3 Formální popis algoritmu Položme si otázku, co je vlastně algoritmus? Když se na tím zamyslíte, asi zjistíte, že to není tak jednoduché přesně říci. Dokonce je to 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 Turingova stroje existují i jiné matematické modely výpočtů, jako třeba stroj RAM, který je abstrakcí skutečného strojového kódu. Konvence 1.6. Zjednodušeně zde algoritmem rozumíme konečnou posloupnost elementárních (výpočetních) kroků, ve které každý další krok využívá vstupní údaje či hodnoty vypočtené v předchozích krocích. Pro zpřehlednění a zkrácení zápisu algoritmu využíváme řídící konstrukce - podmíněná větvení a cykly. Komentář: Vidíte, jak blízké si jsou konstruktivní matematické důkazy a algoritmy (v našem pojetí)? Příklad 1.7. Zápis algoritmu pro výpočet průměru z daného pole a[] s n prvky. Algoritmus. • Inicializujeme sum <— 0 : • postupně pro i=0,l,2, . . . ,n-l provedeme * sum <— sum+a[i]: • vypíšeme podíl (sum/n) . D Ve „vyšší úrovni" formálnosti (s jasnějším vyznačením řídících struktur algoritmu) se totéž dá zapsat jako: Algoritmus 1.8. Průměr z daného pole a[] s n prvky. sum <— 0; for i<— 0,1,2,...,n-l do sum <— sum+a[i]; done res <— sum/n; output res; Značení. Pro potřeby symbolického formálního popisu algoritmů v předmětu FI: IB000 si zavedeme následovnou konvenci: * Proměnné nebudeme deklarovat ani typovat, pole odlišíme závorkami p[]. * Přiřazení hodnoty zapisujeme a^ b, případně a:=b, ale nikdy ne a=b. * Jako 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). 4 * Pevný cyklus uvedeme klíčovými slovy for ... do ... done , kde část za for musí obsahovat předem danou množinu hodnot pro přiřazování do řídící proměnné. * Podmíněný cyklus uvedeme klíčovými slovy while ... do ... done . Zde se může za while vyskytovat jakákoliv logická podmínka. * V zápise používáme jasné odsazování (zleva) podle úrovně zanoření řídících struktur (což jsou if, for, while). * Pokud je to dostatečně jasné, elementární operace nebo podmínky můžeme i ve formálním zápise popsat běžným jazykem. Malé srovnání závěrem Jak to tedy je s vhodnou a únosnou mírou formalizace u matematických důkazů i u zápisu algoritmů? Odpověď může naznačit tato tabulka: zcela formální běžná úroveň matematika algoritmy programováni formální rozepsání všech elem. kroků (Příklad 1.2) rozepsání všech elem. kroků ve výpočetním modelu 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.8), i s využitím běžného jazyka „vyšší" (strukturované) programovací jazyky, například Java Komentář: Pochopitelně se ve všech třech bodech obvykle držíme druhého přístupu, tedy běžné úrovně formality, pokud si specifické podmínky výslovně nevyžadují přístup nejvyšší formality... 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. 2 Důkazové techniky, Indukce Úvod 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. 5 Z důkazových postupů je pro nás asi nejdůležitější technika důkazů matematickou indukcí, která je svou podstatou velmi blízká počítačovým programům (jako 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. (Pro vysvětlení, z Lekce 1 víme, že matematický důkaz má „jednotnou formu" Definice 1.1, ale nyní se věnujeme způsobům, jak takový korektní důkaz vlastně sestavíme.) 2.1 Přehled základních důkazových technik V matematice je často používaných několik následujících způsobů - technik, jak k danému tvrzení nalézt korektní formální důkaz. (Uvědomme si, že jedno tvrzení mívá mnoho různých, stejně korektních, důkazů; ty se však mohou výrazně lišit svou složitostí.) Tyto techniky si v bodech shrneme zde: • Přímé odvození. To je způsob, o kterém jsme se dosud bavili. Postupujeme přímo od předpokladů k závěru, ale sami poznáte, že taková „přímá" cesta je obtížně k nalezení. • Kontrapozice (také obrácením či nepřímý důkaz). Místo věty „Jestliže platí předpoklady, pak platí závěr." budeme dokazovat ekvivalentní větu „Jestliže neplatí závěr, pak neplatí alespoň jeden z předpokladů." • Důkaz sporem. Místo věty „Jestliže platí předpoklady, pak platí závěr." budeme dokazovat větu „Jestliže platí předpoklady a platí opak závěru, pak platí opak jednoho z předpokladů (nebo platí jiné zjevně nepravdivé tvrzení)." • Matematická indukce. Pokročilá technika, kterou zde popíšeme později... Tyto techniky jsou asi nejlépe ilustrovány následovnými příklady důkazů. Příklad důkazu kontrapozicí Definice: Prvočíslo p > 1 nemá jiné dělitele než lap. Příklad 2.1. na důkaz kontrapozicí (obrácením). Věta. Jestliže p je prvočíslo větší než 2, pak p je liché. Důkaz: Obráceného tvrzení - budeme tedy dokazovat, že je-li p sudé, pak p buď není větší než 2, nebo p není prvočíslo. Jsou dvě možnosti: • p < 2. Pak p není větší než 2. • p > 2. Pak p = 2.k pro nějaké celé k > 1, tedy p není prvočíslo. n 6 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 \fi je racionální, tj. nechť existují nesoudělná celá kladná čísla r, s taková, že \f7i = r/s. - Pak 2 = r2/'s2, tedy r2 = 2 • s2, proto r2 je dělitelné dvěma. Z toho plyne, že i r je dělitelné dvěma (proč?). - Jelikož r je dělitelné dvěma, je r2 dělitelné dokonce čtyřmi, tedy r2 = 4 • m pro nějaké m. Pak ale také 4 • m = 2 • s2, tedy 2 • m = s2 a proto s2 je dělitelné dvěma. - Z toho plyne, že s je také dělitelné dvěma. Celkem dostáváme, že r i s jsou dělitelné dvěma, jsou tedy soudělná a to je spor (s definicí racionálního čísla). d Komentář: „Nevíte-li, jak nějakou větu dokázat, zkuste důkaz sporem... " 2.2 Věty typu „tehdy a jen tehdy" Uvažujme nyní (v matematice poměrně hojné) věty tvaru „Nechť platí předpoklady P. Pak tvrzení A platí tehdy a jen tehdy, platí-li tvrzení B." Příklady jiných formulací téže věty jsou: 7 * 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)." Zde k0 je nějaké pevné přir. číslo a T(n) je tvrzení parametrizované čís. n. Příkladem je třeba tvrzení: Pro každé n > 0 platí, že n přímek dělí rovinu nejvýše na \n(n + 1) + 1 oblastí. Definice 2.4. Princip matematické indukce říká, že k důkazu věty „Pro každé přirozené (celé) n > ko platí T(n)." stačí ověřit platnost těchto dvou tvrzení: • T(ko) (tzv. báze neboli základ indukce) • Pro každé n > ko; jestliže platí T(n), (indukční předpoklad) pak platí také T(n+ 1). (indukční krok) (Formálně řečeno, matematická indukce je axiomem aritmetiky přirozených čísel.) Poznámka: Pozor, v tomto předmětu počítáme 0 za přirozené číslo! Opět jako v předešlém si tuto techniku ilustrujeme množstvím názorných příkladů. Příklady důkazů indukcí Příklad 2.5. Velmi jednoduchá a přímočará indukce. Věta. Pro každé n > 1 je stejná pravděpodobnost, že při současném hodu n kostkami bude výsledný součet sudý, jako, že bude lichý. Důkaz: Základ indukce je zde zřejmý: Na jedné kostce (poctivé!) jsou tři lichá a tři sudá čísla, takže obě skupiny padají se stejnou pravděpodobností. 8 Indukční krok pro n > 1: Nechť psn pravděpodobnost, že při hodu n kostkami bude výsledný součet sudý, a pln je pravděpodobnost lichého. Podle indukčního předpokladu je P ----- ffy ----- _ n r n 2' Hoďme navíc (n + l)-ní kostkou. Podle toho, zda na ní padne liché nebo sudé číslo, je pravděpodobnost celkového sudého součtu rovna 3 j 3 a 1 6Pn + 6Pn ---- 2 a stejně pro pravděpodobnost celkového lichého součtu. □ Příklad 2.6. Ukázka důkazové „síly" principu matematické indukce. Věta. Pro každé n > 0 platí, že n přímek dělí rovinu nejvýše na -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+l) + l + (n+1) = -n(n + 1) + - • 2(n + 1) + 1 = -(n + l)(n + 2) + 1 D Příklad 2.7. Další indukční důkaz rozepsaný v podrobných krocích. Věta. Pro každé n>0 platí E™=0 j = '[±f11-Důkaz indukcí vzhledem k n. • Báze: Musíme dokázat tvrzení T(0), což je v tomto případě rovnost J2j=oJ -Tato rovnost (zjevně) platí. • Indukční krok: Musíme dokázat následující tvrzení: Jestliže platí E}=0 j = ^ kdei>0, pak platí E}ť0 j = (m)2(*+2) ■ 9 Předpokládejme tedy, že Yl)=o3 = X a pokusme se dokázat, že pak také Z^io3 (i+l)(i+l+l) __ (i+l)(i+2) 2 2 . To už plyne úpravou: £, = £í+(<+d = iíi±u+(<+i) = '"+i):2"+i» = <í±m±s J=0 3=0 Z Z Z Podle principu matematické indukce je celý důkaz hotov. □ 2.4 Komentáře k matematické indukci Pro správné a úspěšné použití indukce v dokazování je vhodné si zapamatovat několik cenných rad: * Základní trik všech důkazů matematickou indukcí je vhodná reformulace tvrzení T(n+ 1) tak, aby se „odvolávalo" na tvrzení T(n). - Dobře se vždy podívejte, v čem se liší tvrzení T(n + 1) od tvrzení T(n). Tento „rozdíl" budete muset v důkaze zdůvodnit. * Pozor, občas je potřeba „zesílit" tvrzení T(n), aby indukční krok správně „fungoval". - Velkým problémem bohužel je, že není možno podat návod, jak vhodné „zesílení" nalézt (ani kdy jej vůbec hledat). Jedná se vlastně o pokusy a „hádání z křišťálové koule". * Často se chybuje v důkazu indukčního kroku, neboť ten bývá většinou výrazně obtížnější než báze, ale o to zrádnější jsou chyby v samotné zdánlivě snadné bázi! - Dejte si dobrý pozor, od které hodnoty n > k0 je indukční krok univerzálně platný... Zesílení indukčního kroku Příklad 2.8. Když je nutno indukční krok zesílit... Věta. Pro každé n > 1 platí Důkaz: Báze indukce je zřejmá, neboť -^ < 1. Co však indukční krok? Předpoklad s(n) < 1 je sám o sobě „příliš slabý" na to, aby bylo možno tvrdit s(n + 1) = s(n) + (ra+1)1(ra+2) < 1- Neznamená to ještě, že by tvrzení nebylo platné, jen je potřeba náš indukční předpoklad zesílit. Budeme dokazovat Tvrzení. Pro každé přirozené n > 1 platí s(n) < 1 — -^- < 1. To platí pro n = 1 (nezapomeňte ověřit!) a dále už úpravou jen dokončíme zesílený indukční krok: 1 t r s(n+l) = s(n) + -------—------— < 1 (n+l)(n + 2) - ra+1 (77+l)(77 + 2) (77 + 2) + 1 i 1 (t7+1)(t7+2) 77 + 2 10 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 + l,... ,n najednou a dokazovat T(n + 1). (Toto typicky využijeme v případech, kdy indukční krok „rozdělí" problém T(n + 1) na dvě menší části a z nich pak odvodí platnost T(n + 1).) Fakt: Obě prezentovaná „rozšíření" jsou v konečném důsledku jen speciálními instancemi základní matematické indukce; použité rozšířené možnosti pouze zjednodušují formální zápis důkazu. Příklad 2.9. Když je nutno rozšířit bázi a indukční předpoklad... Věta. Nechť funkce f pro každé n > 0 splňuje vztah f(n + 2) = 2f(n + 1) — f(n). Pokud platí /(O) = 1 a zároveň /(l) = 2, tak platí f(n) = n + 1 pro všechna přirozená n > 0. Důkaz: Už samotný pohled na daný vztah f(n + 2) = 2f(n + 1) — f(n) naznačuje, že bychom měli rozšířit indukční předpoklad (a krok) zhruba takto: Pro každé n > 0; jestliže platí T(n); neboli f(n) = n + 1, a zároveň platí T(n + 1); f(n+l) = n + 2, pak platí také T(n + 2); f(n + 2) = n + 3. Báze indukce - pozor, zde už musíme ověřit dvě hodnoty /(O) =0 + 1 = 1, /(l) = 1 + 1 = 2. Náš indukční krok tak nyní může využít celého rozšířeného předpokladu, znalosti hodnot f(n) i f(n+ 1), pro ověření f(n + 2) = 2f(n + 1) - f(n) = 2 ■ (n + 1 + 1) - (n + 1) = n + 3 = n + 2 + 1. Komentář: Jak by tento důkaz měl být formulován v „tradiční" indukci? („Substitucí" nového tvrzení.) Závěrem malý „problém" Příklad 2.10. Aneb jak snadno lze v matematické indukci udělat chybu. Věta. („nevěta") V každém stádu o n > 1 koních mají všichni koně stejnou barvu. Důkaz indukcí vzhledem k n. Báze: Ve stádu o jednom koni mají všichni koně stejnou barvu. Indukční krok: Nechť S = {K\,... ,Kn+í} je stádo o n + 1 koních. Dokážeme, že všichni koně mají stejnou barvu. Uvažme dvě menší stáda: 11 - 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í je nezbytné ke studiu vysokoškolských matematických předmětů. Umění "tvořit" nové matematické důkazy však je dosti obtížné a nedá se jemu jen tak snadno naučit - vyžaduje to mnoho pokročilé praxe. Jelikož je schopnost 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í s menším důrazem), ale to neznamená, že byste se jí mohli vyhýbat. Obzvláště techniku matematické indukce by měl každý informatik aspoň trochu ovládat, s jejím použitím se zajisté ještě mnohokráte setkáte v budoucnosti. 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í) definicí relace, funkce a posloupnosti, uvedeme si příklady rekurzivně definovaných funkcí a posloupností. Látku relací a funkcí pak dále rozvedeme v následujích dvou lekcích. 3.1 Pojem množiny Položme si hned na úvod tu nejdůležitější otázku: Co je vlastně množina? Na tuto otázku bohužel není zcela jednoduchá odpověď... Abychom se vůbec někam v našem úvodu dostali, spokojíme se zatím jen s přirozeným „naivním pohledem". 12 Definice naivní teorie množin: „Množina je soubor prvků a je svými prvky plně určena." Komentář: Pozor, není skutečného rozdílu mezi „množinami" a „prvky". Množiny mohou být prvky jiných množin! Příklady: 0, {a, b}, {b,a}, {a,b,a}, {{a,b}}, {0, {0}, {{0}}}, {a; | a; je liché přirozené číslo} Značení: Počet prvků (mohutnost) množiny A zapisujeme \A\. * |0| = O, |{0}| = 1, \{a,b,c}\ = 3, \{{a,b},c}\=2 Značení množin a jejich prvků: * x G M „x je prvkem množiny M". * některé vlastnosti a G {a, b}, a G" {{a, b}}, {a,b} G {{a, b}}, * prázdná množina 0, a ^ 0, 0 G {0}, 0 G" 0, * rovnost množin {a, b} = {b, a} = {a, b, a}, {a, b} ^ {{a, b}}. Definice: Množina A je podmnožinou množiny B, právě když každý prvek A je prvkem B. Píšeme A C B nebo také B D A; říkáme také, že se jedná o inkluzi. * Platí {a} C {a} C {a, b} £ {{a, b}}, 0 C {0}, * A C B právě když A C B & A =£ B (A je vlastnípodmnožinou B). Definice: Dvě množiny jsou si rovny A = B právě když A C B a B C A. * Podle definice jsou množiny A a B stejné, mají-li stejné prvky. * Důkaz rovnosti množin A = B má obvykle dvě části: Odděleně se dokáží inkluze AC B a B C A. Značení: Některé běžné množiny v matematice se značí * N = {0,1, 2, 3,...} je množina přirozených čísel, * Z = {..., —2, —1, 0,1, 2, 3,...} je množina celých čísel, * Z+ = {1, 2, 3,...} je množina celých kladných čísel, * Q je množina racionálních čísel (zlomků). * R je množina reálných čísel. Poznámka: Tyto uvedené číselné množiny jsou vesměs nekonečné, na rozdíl od konečných množin uvažovaných v předchozím „naivním" pohledu. Pojem nekonečné množiny se přímo v matematice objevil až teprve v 19. století a bylo s ním spojeno několik paradoxů ukazujících, že naivní pohled na teorii množin pro nekonečné množiny nedostačuje. My se k problematice nekonečných množin, Kantorově větě a Russelově paradoxu vrátíme v závěru našeho předmětu. 13 3.2 Množinové operace Začněme se základními operacemi, které zajisté na intuitivní úrovni již ovládáte. Definice: Sjednocení U a průnik n dvou množin A, B definujeme Al) B = {x \ x e A nebo x e B} . Aľ\ B = {x \ x E A a současně x G B} . * Příklady {a, b, c} U {a, d} = {a, b, c, d}, {a, b, c} f) {a, d} = {a}. * Vždy platí „distributive" A n (B U C) = (A n B) U (A n C) a A U (B n C) = {A u s) n (A u C). Definice: Pro libovolný počet množin indexovaných pomocí / rozšířeně definujeme [J. jAí = {x | x G Ai pro nějaké i G /} . P| Aj = {x I x G Aj pro každé že/}. Komentář: Nechť Aj = {2i} pro každé ž G N. Pak IJísn ^* Je množina všech sudých přirozených čísel. Nechť Bi = {x \ x G N, x > i} pro každé i G N. Pak HíeN ^ = $■ Definice: Rozdíl \ a symetrický rozdíl A dvou množin A, £> definujeme A\£> = {i | x G A a současně x G" B} . AAB = (A\B)U(B\A). * 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 k 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í A U B = Ä D B a A n B = Äl)B. (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 dennice (a, a)? (a, a) = {{a}, {a, a}} = {{a}, {a}} = {{a}}. D 14 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 A x B = {(a,b) | 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 (a\, ■ ■ ■, ak) induktivně takto - (ai) = ai, - (ai, • • •, cti, ßi+i) = ((«i, • • • ,a,i), ßj+i). Fakt: Platí (a\, ■ ■ ■, a^) = (b\,- ■ ■ ,bk) právě když aj = bi pro každé i G N kde 1 < i < k. Definice kartézského součinu více množin: Pro každé k G IN definujeme Ai x • • • x Ak = {(a\, ■ ■ ■, at) \ ai G Ai pro každé 1 < i < k} . * Příklad Z3 = ZxZxZ = {(i, j, k) | i, j, k G 1}. * Co je A°? {0}, neboť jediná uspořádaná 0-tice je právě prázdná 0. Poznámka: Podle uvedené definice není součin asociativní, tj. obecně nemusí platit, že Ax(B xC) = (AxB)xC. V matematické praxi je někdy výhodnější uvažovat „upravenou" definici, podle níž součin asociativní je. Pro účely této přednášky není podstatné, k jaké definici se přikloníme. Prezentované definice a věty „fungují" pro obě varianty. Potenční množina Definice 3.3. Potenční množina množiny A. neboli množina všech podmnožin, je definovaná vztahem 2A = {B\BCA}. * Platí například 2Ía'6> = {0, {a}, {b}, {a, b}}, * 20 = {0}, 2»} = {0,{0},{{0}},{0,{0}}}; * 2WxM = {0, {(a, á)},{(a,b)}, {(a, a), (a, &)}}. Věta 3.4. Počet prvků potenční množiny splňuje \2A\ = 2^. Důkaz: Stručně indukcí podle \A\: Pro A = 0 platí \2A\ = |{0}| = 1. Pro každý další prvek b G" A rozdělíme všechny podmnožiny A U {b} „napolovic" na ty neobsahující b a na ty obsahující b, tudíž \2AU^\ =2- \2A\ = 2^+1. D 15 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. . AU B C Ä n B: Pro x E M platí x E AU B, právě když x g. AU 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 AU B. • AU B D A U B: Pro x E M platí x G A U B, právě když x G A a zároveň x E B, neboli když zároveň x E~ A a. x E~ B. To znamená x G" A U B, z čehož vyplývá požadované x E AU B. 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" (B Pi C), neboli x E~ B nebo x E" C. Pro první možnost máme x £ (A \ ß), pro druhou x G (A \ C). . Naopak A \ {B n C) D (A \ S) U (A \ C): Je-li x E (A \ B) U (A \ C), pak x E (A\ B) nebo i£ (j4\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 U C), a tudíž x E A \ (B U C). Druhá možnost je analogická. n Charakteristický vektor (pod)množiny V případech, kdy všechny uvažované množiny jsou podmnožinami nějaké nosné množiny X, což není neobvyklé v programátorských aplikacích, s výhodou využijeme následující reprezentaci množin. Definice: Mějme nosnou množinu X = {x\,X2, ■ ■ ■ ,xn}. Pro A E X definujeme charakteristický vektor x a jako Xa = (ci, c2,..., cn), kde c» = 1 pro Xí E A a c» = 0 jinak. Užitečnost této reprezentace je ilustrována také následovnými fakty. • Platí A = B právě když Xa = Xb- • Množinové operace jsou realizovány „bitovými funkcemi" sjednocení ~ OR, průnik ~ AND, symetrický rozdíl ~ XOR. 16 Princip inkluze a exkluze Tento důležitý a zajímavý kombinatorický princip je někdy také nazýván „princip zapojení a vypojení1. Používá se ke zjišťování počtů prvků množin s neprázdnými průniky. A z" X -\ B " Věta 3.7. Počet prvků ve sjednocení dvou či tří množin spočítáme: \Al)B\ = \A\ + \B\- \AnB\ \A u b u c\ = \A\ + \b\ + \c\ - \A n b\ - \A n c\ - \b n c\ + \A n b n c\ Komentář: Všimněte si, že větu lze stejně tak využít k výpočtu počtu prvků v průniku množin... Příklad 3.8. Z 1000 televizí jich při první kontrole na výrobní lince má 5 vadnou obrazovku, 10 je poškrábaných a 12 má jinou závadu. Přitom 3 televize mají současně všechny tři vady a 4 jiné jsou poškrábané a mají jinou vadu. Kolik televizí je celkem vadných ? Řešení: Dosazením \A\ = 5, \B\ = 10, \C\ = 12, \A n B n C\ = 3, (zde pozor:) \A n B\ = 3 + 0, \A n C\ = 3 + 0, \B n C\ = 3 + 4 do Věty 3.7 zjistíme výsledek 17. D Poznámka. Jen stručně, bez důkazu a bližšího vysvětlení, si uvedeme obecnou formu principu inkluze a exkluze: LU E (-i)|Jhl- $^IC{l,...,n} (Jeho znalost nebude v předmětu vyžadována.) 3.4 Relace a funkce mezi (nad) množinami Dalším důležitým základním „datovým typem" matematiky jsou relace, kterým vzhledem k jejich rozsáhlému použití v informatice věnujeme zvýšenou pozornost. (Hlavní látka o relacích přijde až v následujících lekcích.) Definice 3.9. Relace mezi množinami A\, ■ ■ ■, Ak, pro k G N, je libovolná podmnožina kartézského součinu R C Ai x • • • x Ak . Pokud Ai = ■ ■ ■ = Ak = A, hovoříme o k-ární relaci R na A. Komentář: Příklady relací. * {(1, a), (2, a)} je relace mezi {1,2,3} a {a, b}. * {(i, 2.Í) I i e N} je binární relace na N. 17 * {{h h i + j) I h 3 G ^} Je ternární relace na N. * {3i | 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, v) e /. 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 = {(í, j, í + j) | i, j G N}. Definice: Pokud naší definici funkce upravíme tak, že požadujeme pro každé x G A nejvýše jedno y G B takové, že (x, y) G /, obdržíme definici parciální funkce z A do B. Komentář: V parciální funkci p nemusí být pro některé „vstupní" hodnoty x funkční hodnota definována. Pro nedefinovanou hodnotu používáme znak _L. Komentář: Další příklady funkcí. * Definujeme parciální funkci / : % —> N předpisem , , _ | 3 + x jestliže x > 0. Í{X) - \ ± jinak. Tj. / = {(x,2, + x) | x éN}. * Také funkce / : R —> R daná běžným analytickým předpisem /O) = ^fx je jen parciální - není definována pro x < 0. * Co je relace, přiřazující lidem v ČR jejich rodná čísla? 18 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ů tt. * 1, —1, 1, —1,... je posloupnost určená vztahem pi = (—1)*, i > 0. * Pokud chceme stejnou posloupnost 1, —1, 1, —1,... zadat jako qi, i > 1, tak ji určíme vzorcem Qí = (—l)1-1. • Posloupnost je rostoucí či klesající, pokud pn+\ > pn či pn+\ < pn pro všechna n. Rekurentní definice posloupnosti Slovem rekurentní označujeme takové definice (či popisy), které se v jistých bodech odvolávají samy na sebe. (Už jste se setkali s „rekurzí" při programování? A víte, co znamená?) Místo nepřehledných formálních definic si rekurentní vztahy uvedeme několika názornými ukázkami. • Zadáme-li posloupnost pn vztahy p0 = 1 a pn = 2pn_i pro n > 0, pak platí pn = 2n pro všechna n. • Obdobně můžeme zadat posloupnost qn vztahy q\ = 1 a qn = qn-\ + n pro n > 1. Potom platí qn = \n(n + 1) pro všechna n. Uměli byste toto dokázat indukcí? Viz Příklad 2.7. • Známá Fibonacciho posloupnost je zadaná vztahy fx = f2 = 1 a /„ = /ra_i + /ra_2 pro n> 2. 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 VS poprvé. Nezalekněte 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 6). 19 4 Binární relace, Ekvivalence Úvod V návaznosti na předchozí lekci si podrobně rozebereme matematické formalismy relací. Na rozdíl od množin, které se v jisté velmi naivní formě objevují už na základní škole, se relacím v jejich abstraktní podobě moc pozornosti nevěnuje. Avšak na pojem relace velmi brzo narazí (snad) každý informatik při studiu relačních databází. Není to však jen oblast databází, ale i jiná místa informatiky, kde se relace skrývají či přímo explicitně objevují. Nejčastěji se takto setkáme s binárními relacemi, například vždy když rozdělujeme objekty podle „shodných" znaků (relace ekvivalence), nebo když objekty mezi sebou „srovnáváme" (relace uspořádání). Na tyto dvě základní oblasti se dále zaměříme. Cíle Úkolem této lekce je vybudovat matematickou teorii (konečných) relací, s primárním zaměřením na binární relace jako ekvivalence a uspořádání. Ve vztahu k binárním relacím je zavedeno množství pojmů, které jsou později užitečné v různých oblastech matematiky i informatiky. Látka pak plynule pokračuje Lekcí 5. 4.1 Reprezentace konečných relací Oblast, kde informatici nejčastěji potkají relace, je bezesporu ukládání dat. (Neboť shromažďovaná data, stejně jako relace, především sledují vztahy mezi danými objekty...) Příklad 4.1. Tabulky relační databáze. Definujme následující množiny („elementární typy") * ZNAK = {a, ■ ■ ■, z, A, ■ ■ ■, Z, mezera}. * ČÍSLICE = {0,1,2,3,4,5,6,7,8,9}. Dále definujeme tyto množiny („odvozené typy") * JMÉNO = ZNAK15, PŘÍJMENÍ = ZNAK20, * VEK = ČÍSLICE3, * ZAMESTNANEC ~ JMÉNO x PRIJMEM x VEK. Relaci „typu" ZAMESTNANEC pak lze reprezentovat tabulkou: JMÉNO příjmení VEK Jan Petr Pavel Novák Vichr Zima 42 28 26 D Definice: Relační databáze je konečná množina tabulek. Schéma databáze je (zjednodušeně řečeno) množina „typů" jednotlivých tabulek. 20 Reprezentace binárních relací na množině Jistě čtenáři uznají, že zadání relace výčtem jejích složek není pro člověka (na rozdíl od počítače) tím nejpříjemnějším způsobem. Je tedy přirozené se ptát, jak co nejnázorněji takovou relaci, alespoň v její nejčastější binární podobě, ukázat. Značení: Binární relaci i? C M x M lze jednoznačně znázornit jejím grafem. • Prvky M znázorníme jako body v rovině. • Prvek (a, b) G R znázorníme jako orientovanou hranu („šipku") z a do b. Je-li a = b. pak je touto hranou „smyčka" na a. Komentář: Pozor, nejedná se o „grafy funkcí" známé z analýzy. Například mějme M = {a,b,c,d,e,f} a R = {(a,b), (b, c), (b, d), (b, e), (b, f), (d, c). (e, c), (/, c), (e, d), (e, /), (/, b)}, pak: / V případě, že R je nekonečná nebo „velká", může být reprezentace R jejím grafem nepraktická (záleží pak na míře „pravidelnosti" R). 4.2 Vlastnosti binárních relací Definice 4.2. Nechť R C M x M. Binární relace R je • reflexivní, právě když pro každé a G M platí (a, a) G R: • ireflexivní, právě když pro každé a G M platí (a, a) G" R] symetrická, právě když pro každé a, b G M platí, že jestliže (a, b) G R, pak také (6, a) G R; > antisymetrická, právě když pro každé a, b G M platí, že jestliže (a, b), (b, a) G R, pak a = b: 21 » tranzitivní, právě když pro každé a,b,c E M platí, že jestliže (a, b), (b,c) E R, pak také (a, c) G R. Následují dva základní typy binárních relací, i? je • relace ekvivalence, právě když je R reflexivní, symetrická a tranzitivní: • částečné uspořádání, právě když je R reflexivní, antisymetrická a tranzitivní (často říkáme jen uspořádání). Poznámka: Pozor, může být relace symetrická i antisymetrická zároveň? Ano! Vezměte si relaci R = {(x, x) \ x G M}, která obě jmenované vlastnosti splňuje. Proto pokud jste třeba dotázáni, zda relace je symetrická, nestačí se v odpovědi odvolávat na fakt, že je antisymetrická(!), neboť tyto vlastnosti se nevylučují. Příklad 4.3. Několik příkladů relací defínovaných v přirozeném jazyce. Buď M množina všech studentů 1. ročníku FL Uvažme postupně relace R C M x M definované takto * (x, y) E R právě když x a y mají stejné rodné číslo: * (x, y) E R právě když x má stejnou výšku jako y (dejme tomu na celé mm): * (x, y) E R právě když výška x a y se neliší více jak o 2 mm: * (x, y) E R právě když x má alespoň takovou výšku jako y: * (x, y) E R právě když x má jinou výšku než y (dejme tomu na celé mm): * (x, y) E R právě když x je zamilován (a) do y. Zamyslete se podrobně, které z definovaných vlastností tyto relace mají. □ Příklad 4.4. Jaké vlastnosti mají následující relace? * Buď ňCNxN definovaná takto (x, y) E R právě když x dělí y. (Částečné uspořádání, ale ne každá dvě čísla jsou porovnatelná.) Buď fiCNxN definovaná takto (x, y) E R právě když x a y mají stejný zbytek po dělení číslem 5. (Ekvivalence.) Nechť F = {/ | / : N —► N} je množina funkcí. Buď R E F x F definovaná takto (f, g) E R právě když f (x) < g (x) pro všechna x. (Antisymetrická a tranzitivní, ale ne reflexivní - není uspořádání.) n * * 22 4.3 Relace ekvivalence • Relace R C M x M je ekvivalence právě když R je reflexivní, symetrická a tranzitivní. Tyto tři vlastnosti je tedy třeba ověřit k důkazu toho, že daná relace 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) , , C) je uspořádaná množina. Toto uspořádání se nazývá „po složkách". □ Příklad 5.3. Lexikografické uspořádání. Nechť (A, <^) a (£>, , ^) je uspořádaná množina. Navíc pokud 2, pak množinu Ai x • • • x An lze uspořádat po složkách nebo lexikogmfícky. Všimněte si, že lexikograficky se řadí slova ve slovníku... 26 5.2 Další pojmy uspořádaných množin K tématu uspořádaných množin se vztahuje množství drobných pojmů, které potkáte v různých oblastech matematiky i informatiky. Definice 5.4. Buď (M, |Z) uspořádaná množina. • x E M je minimální právě když pro každé y E M platí, že jestliže y Q x, pak x \Cy. (Tj. x je minimální právě když neexistuje žádný prvek ostře menší než x.) x * \ • x E M je maximální právě když pro každé y E M platí, že jestliže xCj/, pak y ^ x. (Tj. x je maximální právě když neexistuje žádný prvek ostře větší než x.) • x E M je nejmenší právě když pro každé y E M platí, že x C y. • x G M je největší právě když pro každé y E M platí, že y |Z x. • x E M pokrývá y E M právě když x ^ y, y Q x a neexistuje žádné z E M takové, že Xy^Zy^yay^z^x. x 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 • 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 infimum 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 E M je řetězec v uspořádání jZ právě když (A, C.) je lineárně uspořádaná množina. 27 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. 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, C). Pak podle Definice 5.4 platí n Q m i m Q 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řadání Definice: Relace R C M x M je předuspořadání (také kvaziuspořádání, nebo polouspo-Ťádání) právě když i? je reßexivni a tranzitivní. Komentář: Rozdíl mezi uspořádáním a předuspořádáním je (neformálně řečeno!) v tom, že u předuspořadání srovnáváme prvky podle kritéria, které není pro daný prvek jedinečné. V předuspořadání takto mohou vznikat „cykly1. Tvrzení 5.6. Je-li |Z předuspořadání na M, můžeme definovat relaci ~ na M předpisem x ~ y právě když x ^ y a y ^ x. Pak ~ je ekvivalence na M, která se nazývá jádro předuspořadání Q. Na rozkladu M j ~ pak lze zavést relaci -< definovanou takto [%] ^ [v] právě když x ^ y. Pak (M/ ~, :<) je uspořádaná množina. Komentář: Pro příklad si vezměme relaci dělitelnosti na Z. Pak třeba —2 ~ 2. Jádrem zde jsou dvojice čísel stejné absolutní hodnoty. Důkaz (náznak): Tranzitivita a reflexivita relace ~ vyplývá z tranzitivity a reflexivity relace Q. 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 Q. Její antisymetrie vyplývá následující úvahou: Pokud [x] ^ [y] a [y] ^ [x], pak podle naší definice x Q y a y Q 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] ^ [y] je korektní, což znamená, že její platnost nezávisí na konkrétní volbě reprezentantů x z [x] a y z [y\. D 28 5.3 Hasseovské diagramy Hasseovské diagramy uspořádaných množin jsou přehlednější než grafy relací. Například: 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: 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ť /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 Ri má vlastnost V. 29 Fakt: Libovolná kombinace vlastností renexivita, 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 D R na M majících vlastnost V existuje infimum Rv (vzhledem k množinové inkluzi), které samo má vlastnost V. Definice: Tuto „nejmenší" relaci Ry s vlastností V nazýváme V-uzávérrelace R. Tvrzení 5.9. Buď R binární relace na M. * 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ž z-krát iterovaná aplikace funkce T. i * Tranzitivní uzávér R je přesně relace R+ = Uí^i T1 (R). * Reflexivní a tranzitivní uzávěr i? je přesně relace R* = U^i T1 (Q), 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 y 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. Rozšiřující studium Taicé s relacemi uspořádání a předuspořádání se v informatice setkáváme doslova na každém kroku... 6 Vlastnosti funkcí a Skládání relací Úvod Vraťme se nyní k látce Lekce 3. Z jejího pokročilého obsahu jsme doposud velmi detailně probírali relace a jejich jednotlivé vlastnosti. Nyní se podívejme, jak lze relace mezi sebou „skládat", což je například základní technika práce s relačními databázemi. Je však i jiné místo, kde jste se zajisté se skládáním relací setkali - jedná se o skládání funkcí. Jak například spočítáte na kalkulačce výsledek složitějšího vzorce? 30 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 definujeme základní vlastnosti funkcí a především popíšeme a podrobně rozebereme skládání relací a návazně skládání funkcí jako relací. Na závěr se stručně podíváme na problematiku induktivních defínic funkcí, coby na rozšíření rekurentních vztahů z Oddílu 3.5. 6.1 Vlastnosti funkcí Definice: Funkce / : A —► B je - injektivní (nebo také prostá) právě když pro každé x,y G A, x ^ y platí, že f(x) ^ /(i/); - surjektivní (nebo také „na") právě když pro každé y G B existuje x G A takové, že f (%) = y; - bijektivní (vzáj. jednoznačná) právě když je injektivní a současně surjektivní. Komentář: Ukázky vlastností funkcí. * Funkce plus :NxN^Nje surjektivní, ale není prostá. * Funkce g : 7L —>■ N daná předpisem , , _ [ —2x — 1 jestliže x < 0. ^ \ 2a; jinak je bijektivní. * Funkce 0 : 0 —> 0 je bijektivní. * Funkce 0 : 0 —> {a, b} je injektivní, ale není surjektivní. 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~l a je definována takto: R-1 = {(b,a) | (a,b) e R} (R~ľ je tedy relace mezi B a A.) 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) = lna;. * Funkce g(x) = a; mod 3 není prostá na N, a proto její inverzí je „jen" relace g~l = {(a, b) \ a = b mod 3}. Konkrétně5-1 = {(0,0),(0,3),(0,6),...,(l,l),(l,4),...,(2,2),(2,5),...}. 31 Tvrzení 6.1. Mějme funkci f : A —► B. Pak její inverzní relace f l je a) parciální funkce právě když f je prostá, b) funkce právě když f je bijektivní. Důkaz vyplývá přímo z definic funkce a inverze relace. □ Definice 6.2. Složení (kompozice) relací R a S. Nechť RCAxB&SCBxC jsou binární relace. Složení relací R a S (v tomto pořadí!) je relace S o R C A x C definovaná takto: S'oi? = {(a,c) | existuje b G B takové, že (a, b) G R, (6, c) G S} Složení relací čteme „R složeno s S" nebo (pozor na pořadí!) „S po R". Komentář: Příklady skládání relací. * Je-li -A = {a,b}, B = {1,2}, C = {X}, - E = {(a,l),(M),(M)}, S = {(1,X)}, pak složením vznikne relace - SoR = {(a,X),(b,X)}. * Složením funkcí h(x) = x2 a /(#) = a; + 1 na R vznikne funkce foh{x) = f(h(x)) = x2 + 1. * Složením těchže funkcí „naopak1 ale vznikne funkce h o / (x) = h(f(x)) = (x + l)2. Poznámka: Nepříjemné je, že v některých oblastech matematiky (například v algebře při skládání zobrazení) se setkáme s právě opačným zápisem skládání, kdy se místo S o R píše R ■ S nebo jen RS. Proto je si vždy dobré slovně ujasnit, které pořadí skládaných relací máme na mysli. My zde zásadně budeme používat pořadí S o R. 6.3 Skládání relací „v praxi" Podívejme se nyní, jak se skládání relací přirozeně objevuje v práci s relačními databázemi. (Dá se zjednodušeně říci, že právě v operátoru skládání tabulkových relací je hlavní smysl relačních databází...) Příklad 6.3. Skládání v relační databázi studentů, jejich předmětů a fakult. Mějme dvě binární relace - jednu R přiřazující studentům MU kódy jejich zapsaných předmětů, druhou S přiřazující kódy předmětů jejich mateřským fakultám. Malý výsek z těchto relací může v tabulkové reprezentaci vypadat třeba následovně. student (učo) předmět (kód) 121334 MA010 133935 M4135 133935 IA102 155878 M1050 155878 IB000 32 předmět (kód) fakulta MU MAO 10 FI IB000 FI IA102 FI M1050 PřF M4135 PřF Jak z těchto „tabulkových" relací zjistíme, kteří studenti mají zapsané předměty na kterých fakultách (třeba na FI)? Jedná se jednoduše o složení relací S o R. V našem příkladě tabulkové reprezentace vyjde výsek: ____________________________ student (učo) fakulta MU 121334 FI 133935 FI 133935 PřF 155878 FI 155878 PřF Zobecněné skládání relací V praktických použitích relačních tabulek povětšinou nevystačíme jen s binárními relacemi, takže je přirozené se ptát, jestli lze podobně skládat i více-ární relace. Odpověď je snadná - lze to a ani nepotřebujeme novou definici, vystačíme s tou, kterou už máme výše uvedenou. Fakt (skládání relací vyšší arity): Mějme relace T C K\ x K2 x ... x Kk a U C Li x L2 x ... x Lg, přičemž pro nějaké m < mm(k,£) platí Lx = Kk_m+i, L2 = Kk_m+2,..., Lm = Kk. Pak relaci T lze složit s relací U na zvolených m složkách Li,... , Lm („překrytí") s použitím Dennice 6.2 takto: * Položme A = Kí x ... x Kk_m, B = Lx x ... x Lm a C = Lm+Í x ... x L£. * Příslušné relace pak jsou R = {(a, b) G A x B \ (a\,... ak-m, b\,... bm) G T} a S= {(b, c) eBx C\ (bi,...bm,cm+i,...ce) G U}. * Nakonec přirozeně položme U om T ~ A o B, takže vyjde UomT = {(ä, č) | ex. b G B, že (a1}... ak-m, bi,...bm) G T a (bi, ...bm, cm+i, ...ce)eU}. Schematicky pro snažší orientaci ve složkách našich relací: T C KiX...xKk_mx Kk_m+i x ... x Kk U C Li x ... x Lm xLm+i x ... x Li U om T C Kí x ... x Kk_m x v______________t x Lm+i x ...x Li 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. pasažér datum let Petr 5.11. OK535 Pavel 6.11. OK535 Jan 5.11. AF2378 Josef 5.11. DL5457 Alena 6.11. AF2378 datum let letadlo 5.11. OK535 CSA 5.11. AF2378 CSA 5.11. DL5457 CSA 6.11. OK535 AirFrance 6.11. AF2378 AirFrance 33 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. pasažér letadlo Petr Josef CSA CSA Zkuste se zamyslet, lze tyto dvě relace skládat ještě jinak? Co by pak bylo významem? D 6.4 Skládání funkcí, permutace Soustřeďme se nyní na další oblast, kde běžně a přirozeně používáme skládání relací, aniž si to uvědomujeme. Fakt: Mějme zobrazení (funkce) / : A —► B a g : B —► C. Pak jejich složením coby relací v tomto pořadí vznikne zobrazení (g o f) : A —► C definované Í9°f)(x) =g(f(x)). Komentář: * Jak například na běžné kalkulačce vypočteme hodnotu funkce sin2 x ? Složíme (v tomto pořadí) „elementární" funkce f(x) = siná; a g(x) = x2. * Jak bychom na „elementární" funkce rozložili aritmetický výraz 2 log(a;2 + 1) ? Ve správném pořadí složíme funkce f\(x) = x2, f2(x) = x + 1, fz(x) = log x a fi(x) = 2x. * A jak bychom obdobně vyjádřili složením funkcí aritmetický výraz siná; + cosa;? Opět je odpověď přímočará, vezmeme „elementární" funkce g\{x) = siná; a g2{x) — COS X] 9-pak je „složíme" další funkcí h(x, y) = x + y. Vidíme však, že takto pojaté „skládání" už nezapadá hladce do našeho formalismu skládání relací. Pro nedostatek prostoru si skládání funkcí s více parametry nedefinujeme, ale sami vidíte, že obdobné skládání se v programátorské praxi vyskytuje doslova „na každém rohu" a ani se nad tím nepozastavujeme. Skládání permutací Po zbytek tohoto oddílu se zaměříme na permutace coby speciální případ (bijektivních) zobrazení. Definice: Nechť permutace ir množiny [1, n] je určena seřazením jejích prvků (pí,... ,pn)-Pak 7T je zároveň bijektivním zobrazením [l,n] —► [1, n] definovaným předpisem ir(i) = Pí. Tudíž lze permutace skládat jako relace podle Definice 6.2. Poznámka: Všechny permutace množiny [l,n] spolu s operací skládání tvoří grupu, zvanou symetrická grupa Sn. Permutační grupy (podgrupy symetrické grupy) jsou velice důležité v algebře, neboť každá grupa je vlastně isomorfní některé permutační grupě. Komentář: Příkladem permutace vyskytujícím se v programátorské praxi je třeba zobrazení i i—> (i + í) 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ů. 34 Definice: Nechť 7r je permutace na množině A. Cyklem v n rozumíme posloupnost (ai, a2, ■ ■ ■, ßfc) různých prvků A takovou, že 7r(aj) = ai+\ pro i = 1,2,...,k — 1 a 7r(afc) = av Jak název napovídá, v zápise cyklu (a\, a2, ■ ■ ■, au) není důležité, kterým prvkem začneme, ale jen dodržení cyklického pořadí. Cyklus v permutaci může mít i jen jeden prvek (zobrazený na sebe). Komentář: Nakreslete si (vámi zvolenou) permutaci tt obrázkem, ve kterém vedete šipku vždy od prvku i k prvku tt(í). Pak uvidíte, že cykly dle naší definice jsou právě cykly tvořené šipkami ve vašem obrázku. S tímto grafickým zobrazením pro vás nebude problém pochopit následující tvrzení. Například permutaci (5, 3, 4, 8, 6,1, 7, 2) si lze obrázkem nakreslit takto: Věta 6.5. Každou permutaci n na konečné množine A lze zapsat jako složení cyklů na disjunktních podmnožinách (rozkladu) A. Důkaz: Vezmeme libovolný prvek a\ E A& iterujeme zobrazení a2 = 7r(«i), «3 = 7r(a2), atd., až se dostaneme „zpět" k afc+1 = 7r(ßfc) = a\. Proč tento proces skončí? Protože A je konečná a tudíž ke zopakování některého prvku a^+i musí dojít. Nadto je tt prostá, a proto nemůže nastat 7r(ak) = cij pro j > 1. Takto získáme první cyklus (a\,..., 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ů (ai,..., ßfc), (&!,..., bi) až třeba (z\,..., zm). Pak zapíšeme 7T = ((ai,..., ak) (bi,... ,bi) ...(zi,... ,zm)). Komentář: Primitivní pseudonáhodné generátory v počítačích iterují z náhodného počátku permutaci danou vztahem i i—> (i + p) mod q. Je pochopitelné, že tato permutace nesmí obsahovat krátké cykly, lépe řečeno, měla by se skládat z jediného (dlouhého) cyklu. (Pro úplnost, jedná se o permutaci množiny {0,1,... ,q — 1}). Příklad 6.6. Ukázka skládání permutací daných svými cykly. Vezměme 7-prvkovou permutaci (5, 3, 4, 2, 6,1, 7). Ta se rozkládá na tři cykly (1, 5, 6), (2, 3, 4) a (7). Jiná permutace (3, 4, 5, 6, 7,1, 2) se skládá z jediného cyklu (1, 3, 5, 7, 2, 4, 6). Nyní určíme složení těchto dvou permutací (zápisem cykly): ((l,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 35 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 (bázických) prvků ai, a2, • • •, «fc G M. • Je dán soubor induktivních pravidel typu Jsou-li (libovolné prvky) X\,..., Xg G M, pak také y G M. V tomto případě je y typicky funkcí y = fí(x\,..., Xg). Pak naše induktivně definovaná množina M je určena jako nejmenší (inkluzí) množina vyhovující těmto pravidlům. Komentář: Vidíte podobnost této definice s uzávěrem relace? (Věta 5.8.) Pro nejbližší příklad induktivní definice se obrátíme na množinu všech přirozených čísel. - 0 éN - Je-li i G N, pak také i + 1 G N. 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í \ í 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ázových prvků pomocí induktivních pravidel právě jedním způsobem. Komentář: Definujme množinu M C N induktivně takto: - 2,3 GM. - Jestliže x,y G M, pak také x2 + y2 a x.y jsou prvky M. Proč tato induktivní definice není jednoznačná? Například číslo 8 G 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,a,2, ■ ■ ■ ,cik G M je určeno T(ai) = Ci, kde q je konstanta. • Pro každé induktivní pravidlo typu "Jsou-li (libovolné prvky) x\,..., Xg G M, pak také f(x\,..., Xg) G M" je definováno T( f(xi,..., Xi)) na základě hodnot ^(xi),..., T{xl). 36 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) E = {0,1, 2, 3, 4, 5, 6, 7, 8, 9, 0, ©, (,)}. Definujme množinu jednoduchých výrazů SExp C E* induktivně takto: - Dekadický zápis každého přirozeného čísla n je prvek SExp. - Jestliže x, y G SExp, pak také (x) © (y) a (x) © (y) jsou prvky SExp. (Jak vidíme, díky „závorkování" je tato induktivní definice jednoznačná.) Pro „vyhodnocení" výrazu pak definujme funkci Val: SExp —► N induktivně takto: - Bázické prvky: Val(n) = n, kde n je dekadický zápis přirozeného čísla n. - První induktivní pravidlo: Val((x) © (y)) = Val(x) + Val(y). - Druhé induktivní pravidlo: Val((x) © (y)) = Val(x) ■ Val(y). (Tímto způsobem jsme našim výrazům vlastně přiřadili jejich „význam", sémantiku.) □ Příklad 6.10. Důkaz správnosti přiřazeného „významu" Val: SExp —► N. Věta. Pro každý výraz s G SExp je hodnota Val(s) číselně rovna výsledku vyhodnocení výrazu s podle běžných zvyklostí aritmetiky. Jelikož pojednáváme o induktivně definované funkci Val, je přirozené pro důkaz jejích vlastností aplikovat matematickou indukci. Na rozdíl od dříve probíraných příkladů zde nevidíme žádný celočíselný „parametr nu, a proto si jej budeme muset nejprve definovat. Naši indukci tedy povedeme podle „délky í odvození výrazu s" definované jako počet aplikací induktivních pravidel potřebných k odvození s G SExp. Takto aplikované matematické indukci se často říká strukturální indukce. Důkaz: V bázi indukce ověříme vyhodnocení bázických prvků, což jsou zde dekadizké zápisy přirozených čísel. Platí Val(n) = n, což skutečně odpovídá zvyklostem aritmetiky. V indukčním kroku se podíváme na vyhodnocení Val((x) © (y)) = Val(x) + Val(y). Podle běžných zvyklostí aritmetiky by hodnota Val((x) © (y)) měla být rovna součtu vyhodnocení výrazu x, což je podle indukčního předpokladu rovno Val(x) (x má zřejmě kratší délku odvození), a vyhodnocení výrazu y, což je podle indukčního předpokladu rovno Val(y). Takže skutečně Val((x) © (y)) = Val(x) + Val(y). Druhé pravidlo Val((x) G (y)) se dořeší analogicky. D Rozšiřující studium 37 7 Jemný úvod do Logiky Úvod Základem přesného matematického vyjadřování je správné používání (matematické) logiky a logických úsudků. Logika jako filozofická disciplína se intenzívne vyvíjí už od dob antiky avšak ke skutečnému rozmachu logiky coby součásti matematiky došlo až začátkem 20. století. (S přispěním třeba Russelova paradoxu.) Dnes se samozřejmě základní logický kalkulus používá nejen v matematice, ale „stojí" na něm veškeré logické obvody a počítače. Proto se také studenti informatiky s logikou setkávají záhy při svém studiu a mnohokrát se k tématu také vracejí. Cíle Následující lekce přináší (skutečně velmi jemný a trochu i povrchní) úvod do moderní matematické logiky která je solidním základem matematiky a nakonec i celé informatiky. Zavedeme si základy výrokové logiky a výrokového počtu a velmi stručně si uvedeme problematiku predikátové logiky a kvantifikace. 7.1 Výroky v „přirozené" podobě Definice: V přirozené mluvě za výrok považujeme (každé) tvrzení, o kterém má smysl prohlásit, že je buď pravdivé nebo nepravdivé. Komentář: Několik příkladů, které z nich jsou výroky? * Dnes už v Brně pršelo. * Předmět 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. Fakt: Z jednoduchých výroků můžeme vytvářet výroky složitější pomocí tzv. logických spojek. Komentář: Několik dalších příkladů. * Kateřina přijede ve 12:00 a půjdeme spolu do kina. * Množina {a, b} má více než jeden prvek a není nekonečná. * Jestliže má Karel přes 90 kilo váhy, nepojedu s ním výtahem. * Jestliže má kráva 10 nohou, mají všechny domy modrou střechu. Schopnost porozumět takovýmto větám je součást lidského způsobu uvažování a z tohoto hlediska nemá přímou souvislost s matematikou (je to „přirozená logika"). Formální (matematická) logika pak definuje jazyk matematiky a odstraňuje nejednoznačnosti přirozeného jazyka. 38 7.2 (Formální) výroková logika Definice 7.1. Syntaxe výrokové logiky. Buď AT = {A,B,C,...} spočetně nekonečná množina výrokových proměnných (tzv. atomů). Množina výrokových formulí í> je definována induktivně následujícími pravi-dly: (1) ÍTC$. (2) Jestliže ip,ip E í>, pak také -n(ip) 6 $ a (^ 4 (i/j) E í>. (3) Každý prvek í> vznikne konečně mnoha aplikacemi pravidel (1) a (2). Značení: Symbol -i je zván negací a =>- je nazýván implikací. Komentář: Příklady několika správně utvořených formulí: A, (A) => (B), ((A) => MB))) => (h(B)) => (C)) A také příklady několika ne zcela správně utvořených formulí: A =>B, A=>B=>C, ~^A=>B Konvence 7.2. Pro zvýšení čitelnosti budeme závorky vynechávat, pokud to nepovede k nejednoznačnostem za předpokladu, že negace -i má „vyšší prioritu" než =>. (Touto úmluvou se nemění množina í>; mění se jen způsob reprezentace jejích prvků. Dále si zavedeme, že *

if), *

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

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

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

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

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

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

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