Informatika
Od bitů a algoritmů
po hranice toho, co lze spočítat
Na pozadí hledá algoritmus cestu bludištěm. Prohledávání do šířky se šíří po vrstvách jako vlna na vodě: nejdřív všechna pole ve vzdálenosti 1, pak 2, 3… Jakmile vlna dorazí do cíle, oranžová čára ukáže nejkratší možnou cestu. Kapitola 8 vysvětluje proč.
Jak průvodce používat
Informatika není nauka o ovládání počítačů, stejně jako astronomie není nauka o dalekohledech. Je to věda o informaci a o postupech, jak ji uchovat, přenést a zpracovat. Průvodce začíná u jednoho bitu a algoritmu, který zvládne i dítě s tužkou, a končí u otázek, na které neodpoví žádný počítač, ať je jakkoli rychlý.
Tři patra každé kapitoly. Nahoře krátké vysvětlení a laboratoř: převodník čísel, robot ovládaný vlastním programem, řadicí algoritmy v pohybu, šifra, kterou sami prolomíte, Turingův stroj. Pod ní mise za XP, od bitu až po Turingova mistra. Dole rozbalovací teorie pro ty, kdo chtějí jít do hloubky: definice, pseudokód, důkazy, řešené příklady a příklady k procvičení s úplným řešením. Barevná tečka v obsahu ukazuje úroveň. Postup se ukládá jen ve vašem prohlížeči.
Mapa průvodce
| Kapitola | Úroveň | Co se naučíte |
|---|---|---|
| 1 Informace a bity | základy | dvojkovou a šestnáctkovou soustavu, bajty, jak se ukládá text (ASCII, Unicode, UTF-8), obrázek a zvuk |
| 2 Algoritmy | základy | co je algoritmus, pseudokód, vývojový diagram, větvení a cykly; naprogramujete robota |
| 3 Počítač, internet a bezpečnost | základy | procesor, paměť, operační systém, IP, DNS, HTTPS; silná hesla, dvoufázové ověření, phishing |
| 4 Programování | střední škola | proměnné, typy, funkce, rekurzi a ladění na příkladech v Pythonu a JavaScriptu |
| 5 Řazení a vyhledávání | střední škola | bublinkové řazení, vkládáním, slučováním, rychlé řazení a binární vyhledávání |
| 6 Složitost algoritmů | střední škola | O-notaci, růst funkcí a proč dobrý algoritmus porazí rychlejší počítač |
| 7 Datové struktury | střední škola | pole, seznam, zásobník, frontu, strom, binární vyhledávací strom, hašovací tabulku a graf |
| 8 Grafové algoritmy | střední škola | prohledávání do šířky a do hloubky, Dijkstrův algoritmus, minimální kostru (Borůvka, Jarník) |
| 9 Kryptografie | střední škola | od Caesarovy šifry po AES, hašovací funkce, RSA na malých číslech, digitální podpis |
| 10 Databáze a data | vysoká škola | relační model, SQL (SELECT, JOIN, GROUP BY), normalizaci, indexy a transakce |
| 11 Vyčíslitelnost a složitost | vysoká škola | Turingův stroj, problém zastavení, třídy P a NP, NP-úplnost a redukce |
| 12 Umělá inteligence a software | vysoká škola | prohledávání a hry, perceptron, princip jazykových modelů, verzování, testování, etika |
Co budete potřebovat
Pro první tři kapitoly stačí základní škola: násobení, mocniny a trocha trpělivosti. Od kapitoly 4 se hodí středoškolská matematika (funkce, logaritmus, posloupnosti), od kapitoly 9 dělitelnost a počítání se zbytky. Programovat umět nemusíte; ukázky kódu jsou krátké a vysvětlené řádek po řádku. Kdo chce zkoušet, vystačí si s prohlížečem: v jeho vývojářské konzoli lze spouštět JavaScript.
Průvodce navazuje na sousední obory a odkazuje na ně textem. Logaritmy, kombinatoriku a důkazy vykládá průvodce Matematika, výrokovou logiku a formální úsudek Logika a kritické myšlení, logické obvody a polovodiče, ze kterých je procesor postavený, Elektrotechnika. Strojové učení tu najdete jen stručně; do hloubky ho rozebírá průvodce Statistika a modely. Otázky vědomí a mysli strojů patří průvodci Filozofie, ekonomiku platforem a digitálních trhů průvodci Ekonomie.
Čtyři druhy rámečků
Výpočet nebo postup krok za krokem. Čísla v příkladech jsou přepočítaná skriptem, kód je vyzkoušený.
Kde se látka používá, jak vznikla a co se stalo, když se na ni zapomnělo.
Rychlé pravidlo nebo způsob, jak si věc zapamatovat.
Místo, kde se nejčastěji chybuje: v kódu, v úvaze i v představě o tom, co počítač „umí“.
Studijní materiál, nenahrazuje učebnici ani výuku. Průvodce nejmenuje komerční produkty ani firmy; domény v příkladech (alfabanka.example a podobně) jsou smyšlené a podle RFC 2606 vyhrazené pro ukázky. Kapitoly o bezpečnosti a kryptografii vykládají principy a obranu, ne postupy útoků. Normy, protokoly a údaje mají v příloze C zdroj a datum ověření 13. 10. 2026.
Rozsahem odpovídá: kapitoly 1–3 vzdělávací oblasti Informatika v RVP ZV (data a informace, algoritmizace, informační systémy, digitální technologie), kapitoly 4–9 vzdělávací oblasti Informatika v RVP G a typickému maturitnímu rozsahu informatiky a programování, kapitoly 10–12 úvodním vysokoškolským kurzům: algoritmy a datové struktury, databázové systémy, automaty a vyčíslitelnost, úvod do umělé inteligence a softwarového inženýrství.
Informace a bityzáklady
Počítač rozlišuje jen dva stavy: proud teče, nebo neteče; náboj je, nebo není. Říkáme jim 0 a 1. Všechno ostatní – čísla, písmena, fotografie, hudba – je dohoda o tom, jak dlouhou řadu nul a jedniček číst a co znamená.
Představte si chodbu s osmi vypínači. Každý buď svítí, nebo ne. Jeden vypínač rozliší dvě situace, dva vypínače čtyři, osm vypínačů už 256. Kdybyste se se sousedem domluvili, že rozsvícená kombinace znamená určité písmeno, můžete si přes chodbu posílat zprávy. Přesně to dělá počítač, jen má vypínačů miliardy a přepíná je miliardkrát za sekundu.
+Teorie: bit, soustavy, kódování čísel, textu, obrazu a zvuku
1.1Bit a množství informace
Bit je nejmenší jednotka informace: odpověď na jednu otázku typu ano/ne, kde jsou obě odpovědi stejně pravděpodobné. Slovo vzniklo zkrácením binary digit, dvojková číslice; v tisku ho poprvé použil Claude Shannon v roce 1948 a připsal ho kolegovi Johnu Tukeymu.bit, binary digit
Řada \(n\) bitů může nabýt \(2^{n}\) různých hodnot. Obráceně: abychom rozlišili \(N\) stejně pravděpodobných možností, potřebujeme \(\log_2 N\) bitů, v praxi zaokrouhleno nahoru.
Ve hře „myslím si…“ smíte položit 20 otázek ano/ne. Kolik předmětů lze takto spolehlivě rozlišit? \(2^{20} = 1\,048\,576\), tedy přes milion. Každá dobrá otázka rozdělí zbývající možnosti napůl – stejný trik uvidíte v kapitole 5 jako binární vyhledávání.
Hod kostkou nese \(\log_2 6 = 2{,}585\) bitu informace, tah karty z balíčku 52 karet \(\log_2 52 = 5{,}700\) bitu. Na zápis výsledku kostky ale potřebujeme celé 3 bity, protože bit nelze rozpůlit.
Entropie (rozšíření)
Když možnosti nejsou stejně pravděpodobné, nese zpráva v průměru méně informace. Shannon (1948) ji měří entropií: \(H = -\sum_i p_i \log_2 p_i\) bitů na zprávu. Mince, která padá v 90 % případů na líc, má entropii \(H = -(0{,}9\log_2 0{,}9 + 0{,}1\log_2 0{,}1) = 0{,}469\) bitu. Proto jde dobře komprimovat text: písmena v něm nejsou stejně častá a dají se kódovat úsporněji. Entropie je dolní mez průměrné délky bezeztrátového kódu.entropy, source coding
1.2Poziční číselné soustavy
V desítkové soustavě znamená zápis 2026 součet \(2\cdot10^{3} + 0\cdot10^{2} + 2\cdot10^{1} + 6\cdot10^{0}\). Hodnota číslice závisí na její pozici. Stejně funguje každá poziční soustava se základem \(z\): číslice \(c_k\) na \(k\)-té pozici zprava (počítáno od nuly) má váhu \(z^{k}\).positional numeral system, radix
Dvojková (binární) soustava má základ 2 a číslice 0 a 1. Šestnáctková (hexadecimální) má základ 16 a číslice 0–9 a A–F. Šestnáctková soustava je zkratka pro dvojkovou: jedna šestnáctková číslice odpovídá přesně čtyřem bitům, protože \(16 = 2^{4}\). Bajt se tak zapíše dvěma znaky.binary, hexadecimal
Převod z desítkové soustavy
Číslo opakovaně dělíme základem a zapisujeme zbytky. Zbytky čtené odspodu (od posledního k prvnímu) dávají zápis v nové soustavě. Funguje to proto, že zbytek po dělení dvěma je právě nejnižší bit a podíl je číslo posunuté o jedno místo doprava.
2026 : 2 = 1013 zb. 0; 1013 : 2 = 506 zb. 1; 506 : 2 = 253 zb. 0; 253 : 2 = 126 zb. 1; 126 : 2 = 63 zb. 0; 63 : 2 = 31 zb. 1; 31 : 2 = 15 zb. 1; 15 : 2 = 7 zb. 1; 7 : 2 = 3 zb. 1; 3 : 2 = 1 zb. 1; 1 : 2 = 0 zb. 1.
Odspodu: \(2026 = 11111101010_2\). Rozdělením do čtveřic zprava \(111\ 1110\ 1010\) dostaneme \(7\,\text{E}\,\text{A}\), tedy \(2026 = 7\text{EA}_{16}\). Kontrola: \(7\cdot256 + 14\cdot16 + 10 = 2026\).
Mocniny dvojky stojí za to znát nazpaměť aspoň do \(2^{10} = 1\,024\): 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1 024. Převod do dvojkové soustavy pak jde i „shora“: od čísla odečítejte největší mocninu dvojky, která se vejde, a na její místo napište 1. To je přesně postup z minihry.
1.3Bajty a předpony
Bajt (B) je skupina 8 bitů a nejmenší jednotka, kterou běžné počítače adresují v paměti. Pro větší množství se používají předpony. Desítkové předpony soustavy SI znamenají mocniny tisíce: 1 kB = 1 000 B, 1 MB = \(10^{6}\) B, 1 GB = \(10^{9}\) B, 1 TB = \(10^{12}\) B. Protože paměti rostou po mocninách dvojky, zavedla norma IEC dvojkové předpony: 1 KiB (kibibajt) = 1 024 B, 1 MiB = \(2^{20}\) B, 1 GiB = \(2^{30}\) B.byte, binary prefixes (KiB, MiB, GiB)
Disk prodávaný jako 1 TB má \(10^{12}\) bajtů. Operační systém, který počítá ve dvojkových jednotkách, ukáže \(10^{12}/2^{30} = 931{,}3\) „GB“ (správně GiB). Nic nechybí, jen se počítá jinou jednotkou; rozdíl je 6,9 %.
Malé b znamená bit, velké B bajt. Rychlost připojení se udává v bitech za sekundu: 100 Mbit/s je nejvýš 12,5 MB/s. Soubor o velikosti 1 GB se tedy při 100 Mbit/s stahuje nejméně 80 sekund.
1.4Celá čísla se znaménkem a desetinná čísla
Záporná čísla ukládají počítače ve dvojkovém doplňku: nejvyšší bit má zápornou váhu. U bajtu je to \(-128\) místo \(+128\), takže 8 bitů pokryje čísla od \(-128\) do \(127\). Opačné číslo se získá převrácením všech bitů a přičtením jedničky. Výhoda: sčítání funguje stejně pro kladná i záporná čísla, procesor nepotřebuje zvláštní obvod na odčítání.two's complement
\(5 = 00000101_2\). Převrácením bitů dostaneme \(11111010\), přičtením jedničky \(11111011\). Kontrola: \(-128 + 64 + 32 + 16 + 8 + 2 + 1 = -5\). Bajt \(10110110\) z obr. 1.1 je tedy bez znaménka 182, se znaménkem \(182 - 256 = -74\).
Když výsledek nevejde do daného počtu bitů, nastane přetečení: v bajtu se znaménkem dá \(127 + 1\) výsledek \(-128\). Programovací jazyky se k tomu chovají různě – některé tiše „přetočí“ hodnotu, jiné ohlásí chybu, Python má celá čísla libovolné délky.integer overflow
Desetinná čísla se ukládají v plovoucí řádové čárce podle normy IEEE 754: znaménko, exponent a mantisa, podobně jako vědecký zápis \(6{,}022\cdot10^{23}\), jen se základem 2. Nejběžnější formát má 64 bitů (1 znaménko, 11 exponent, 52 mantisa) a přesnost zhruba 15–17 platných desítkových číslic.floating point, IEEE 754 double precision
Číslo 0,1 nemá ve dvojkové soustavě konečný zápis (stejně jako 1/3 v desítkové), takže se uloží zaokrouhleně. Proto v Pythonu i JavaScriptu vyjde 0.1 + 0.2 jako 0,30000000000000004 a test 0.1 + 0.2 == 0.3 je nepravdivý. Desetinná čísla porovnávejte s tolerancí a peníze počítejte v celých haléřích nebo v desítkovém typu.
Při prvním letu rakety Ariane 5 (1996) převáděl řídicí program 64bitové desetinné číslo s horizontální rychlostí na 16bitové celé číslo se znaménkem. Hodnota se nevešla do rozsahu do 32 767, převod skončil chybou, navigační systém se vypnul a raketa se necelých 40 sekund po startu rozpadla. Kód byl převzatý z Ariane 4, která letěla pomaleji (zpráva vyšetřovací komise, 1996).
1.5Text: ASCII, Unicode a UTF-8
Text je posloupnost znaků a každý znak má domluvené číslo. ASCII (americká norma z roku 1963) používá 7 bitů, tedy 128 kódů: 33 řídicích (konec řádku, tabulátor…) a 95 tisknutelných znaků včetně mezery. Písmeno A má kód 65, a má 97, číslice 0 kód 48. Velké a malé písmeno se liší jediným bitem s hodnotou 32.ASCII, character encoding
Pro češtinu ASCII nestačilo, a tak vznikla desítka vzájemně nekompatibilních osmibitových tabulek; text napsaný v jedné se v druhé zobrazil jako „rozsypaný čaj“. Řešením je Unicode: jediný katalog znaků všech písem. Každý znak má kódový bod zapisovaný U+ a šestnáctkovým číslem, například Č je U+010C, € je U+20AC. Prostor má \(17 \cdot 65\,536 = 1\,114\,112\) kódových bodů (U+0000 až U+10FFFF). Verze 18.0 z 16. 9. 2026 jich obsazuje 172 808.Unicode, code point
Unicode říká, jaké číslo znak má, ne jak ho zapsat do bajtů. To dělá kódování. Na webu převládá UTF-8 (RFC 3629): znaky ASCII zapíše jedním bajtem beze změny, ostatní dvěma až čtyřmi bajty. První bajt vícebajtové sekvence začíná tolika jedničkami, kolik bajtů sekvence má; každý následující bajt začíná 10.UTF-8, variable-length encoding
| Kódové body | Bajty | Bitový vzor | Příklad |
|---|---|---|---|
| U+0000 – U+007F | 1 | 0xxxxxxx | A = 41 |
| U+0080 – U+07FF | 2 | 110xxxxx 10xxxxxx | Č = C4 8C |
| U+0800 – U+FFFF | 3 | 1110xxxx 10xxxxxx 10xxxxxx | € = E2 82 AC |
| U+10000 – U+10FFFF | 4 | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx | 😀 = F0 9F 98 80 |
„Ahoj“ má 4 znaky a 4 bajty. „kůň“ má 3 znaky, ale 5 bajtů: k = 6B, ů = C5 AF, ň = C5 88. Věta „Žluťoučký kůň“ má 13 znaků a 19 bajtů, protože 6 písmen s diakritikou zabere po dvou bajtech.
Délka textu „ve znacích“ není jednoznačná. Emoji 😀 je jeden kódový bod, 4 bajty v UTF-8, ale 2 jednotky v UTF-16, které JavaScript vrací jako "😀".length. Písmeno é lze navíc zapsat jedním kódovým bodem (U+00E9) i dvěma (e + kombinující čárka); vypadají stejně, ale jako řetězce se nerovnají, dokud je normalizace nepřevede na stejný tvar.
1.6Obrázek a zvuk
Rastrový obrázek je mřížka bodů (pixelů). Barva každého pixelu se obvykle skládá ze tří složek: červené, zelené a modré (RGB), každá 0–255, tedy 1 bajt. Tři bajty dají \(2^{24} = 16\,777\,216\) barev. Ve webových stránkách se barva píše šestnáctkově: oranžová tohoto průvodce je #EB6834, tedy R = 235, G = 104, B = 52.raster image, pixel, RGB
Obraz 1 920 × 1 080 pixelů po 3 bajtech má \(1\,920\cdot1\,080\cdot3 = 6\,220\,800\) B, tedy 6,2 MB (5,93 MiB). Video s 25 snímky za sekundu by bez komprese potřebovalo přes 155 MB každou sekundu. Proto se obrázky a video komprimují: bezeztrátově (po rozbalení přesně stejná data; vhodné pro grafiku a text) nebo ztrátově (vynechá detaily, kterých si oko nevšimne; fotografie a video).
Zvuk je kmitání tlaku vzduchu. Mikrofon ho převede na spojitý elektrický signál a převodník ho vzorkuje: v pravidelných intervalech změří okamžitou hodnotu a kvantuje ji na nejbližší z konečně mnoha úrovní. Vzorkovací věta (Nyquist, Shannon) říká, že signál obsahující frekvence do \(f_{\max}\) lze z ideálně změřených vzorků přesně obnovit, je-li vzorkovací frekvence větší než \(2f_{\max}\).sampling, quantization, Nyquist–Shannon theorem
CD vzorkuje 44 100krát za sekundu (lidské ucho slyší zhruba do 20 kHz, dvojnásobek je 40 kHz), 16 bitů na vzorek, 2 kanály: \(44\,100\cdot16\cdot2 = 1\,411\,200\) bit/s. Minuta zvuku zabere 10 584 000 B, asi 10,6 MB, třiapůlminutová píseň 37,0 MB. Ztrátově komprimovaná verze s 128 kbit/s má 3,36 MB, jedenáctkrát méně.
1.7Procvičení
- \(n\) bitů rozliší \(2^{n}\) možností; bajt má 8 bitů a 256 hodnot.
- Dvojková soustava je řeč stroje, šestnáctková její zkratka: čtyři bity na číslici.
- Čísla, text, obraz i zvuk jsou bity plus dohoda o jejich výkladu. Unicode číslo znaku, UTF-8 jeho bajty.
- Počítač počítá s omezenou přesností: celá čísla mohou přetéct, desetinná se zaokrouhlují.
Algoritmyzáklady
Algoritmus je návod tak přesný, že ho může provést i někdo, kdo vůbec nerozumí, k čemu slouží. Počítač je přesně takový vykonavatel: neumí si nic domyslet, ale cokoli jednoznačně popíšete, provede bez únavy a bez chyby.
Recept na palačinky je skoro algoritmus: suroviny jsou vstup, palačinky výstup, kroky jdou po sobě a některé se opakují („smažte, dokud těsto nedojde“). Jenže „osolte podle chuti“ nebo „pánev dobře rozpalte“ by počítač neprovedl. Algoritmus nesmí nechat nic na odhadu.
krok, vlevo, vpravo, opakuj 3 { … }, dokud podmínka { … }, když podmínka { … } jinak { … }. Podmínky: volno, zeď, vpravo-volno, vlevo-volno, cíl, necíl. Čtyři úrovně, každá učí něco nového.+Teorie: vlastnosti algoritmu, pseudokód, diagramy, Euklides a správnost
2.1Co je algoritmus
Algoritmus je konečný a jednoznačný postup, který ze vstupních údajů v konečném počtu kroků vytvoří výsledek. Slovo pochází ze jména perského matematika al-Chvárizmího (9. století), jehož spis o počítání s indickými číslicemi se v latinském překladu šířil Evropou. Nejstarší algoritmus, který se dodnes běžně používá, popsal Eukleidés v Základech kolem roku 300 př. n. l.algorithm
Česká školní tradice vyjmenovává tyto vlastnosti:
- Elementárnost: skládá se z kroků, které vykonavatel umí provést.
- Determinovanost (jednoznačnost): po každém kroku je jasné, co následuje.
- Konečnost: pro každý přípustný vstup skončí po konečném počtu kroků.
- Rezultativnost: dává výsledek (výstup).
- Hromadnost (obecnost): řeší celou třídu úloh, ne jeden konkrétní případ. Postup „sečti 3 a 5“ není algoritmus sčítání; „sečti čísla \(a\) a \(b\)“ ano.
Knuth v The Art of Computer Programming uvádí pět podobných rysů: konečnost, určitost, vstup, výstup a efektivitu (kroky jsou tak jednoduché, že by je člověk zvládl s tužkou a papírem). Formální definici „postupu“ dal až Turing v roce 1936; k ní se vrátíme v kapitole 11.
Program a algoritmus nejsou totéž. Algoritmus je myšlenka postupu; program je její zápis v konkrétním jazyce. Jeden algoritmus lze zapsat v Pythonu, JavaScriptu i v robotím jazyce z laboratoře. A ne každý program je algoritmem v přísném smyslu: operační systém nebo webový server běží záměrně „donekonečna“.
2.2Jak algoritmus zapsat
Algoritmus lze popsat slovy, ale přirozený jazyk bývá dvojznačný. Proto se používá pseudokód: strukturovaný zápis podobný programu, který se nedrží syntaxe žádného jazyka a nechává stranou podrobnosti. V tomto průvodci píšeme přiřazení šipkou \(\leftarrow\), bloky odsazením a operaci zbytku po dělení jako mod.pseudocode
funkce NSD(a, b): dokud b ≠ 0: r ← a mod b # zbytek po dělení a ← b b ← r vrať a
Druhou možností je vývojový diagram: grafický zápis, ve kterém tvar značky říká, o jaký krok jde. Symboly popisuje norma ISO 5807. Ovál je začátek a konec, obdélník zpracování, kosodélník vstup a výstup, kosočtverec rozhodnutí se dvěma východy.flowchart
2.3Posloupnost, větvení, cyklus
Každý algoritmus lze sestavit ze tří stavebních kamenů: posloupnosti (kroky jdou za sebou), větvení (podle podmínky se pokračuje jednou, nebo druhou cestou) a cyklu (část se opakuje, dokud platí podmínka). Že nic dalšího není potřeba, dokázali Böhm a Jacopini (1966). Na jejich výsledek navázal Dijkstra (1968) výzvou psát programy bez skoků goto; tak vzniklo strukturované programování.sequence, selection, iteration; structured programming
Cykly mají dvě podoby. Cyklus s pevným počtem opakování (opakuj 4, v Pythonu for i in range(4)) zná počet průchodů předem. Cyklus s podmínkou (dokud volno, while) se opakuje, dokud podmínka platí, a počet průchodů závisí na datech. Právě proto úroveň 3 laboratoře nejde vyřešit počítáním kroků: chodby jsou různě dlouhé a program musí reagovat na to, co robot „vidí“.
Vstup: seznam čísel \(x_1, \dots, x_n\) (\(n \ge 1\)). Výstup: největší z nich.
m ← x[1] pro i od 2 do n: když x[i] > m: m ← x[i] vrať m
Posloupnost (přiřazení), cyklus (projdi zbytek seznamu) a větvení (je prvek větší?). Algoritmus provede přesně \(n-1\) porovnání. Pro seznam 7, 3, 9, 2, 9, 4 nabývá \(m\) postupně hodnot 7, 7, 9, 9, 9, 9 a vrátí 9.
2.4Euklidův algoritmus
Největší společný dělitel (NSD) dvou přirozených čísel je největší číslo, které dělí obě. Euklidův algoritmus stojí na pozorování, že \(\mathrm{NSD}(a, b) = \mathrm{NSD}(b, a \bmod b)\): každé číslo, které dělí \(a\) i \(b\), dělí i zbytek \(a - q\,b\), a naopak. Čísla se tak zmenšují, ale jejich NSD zůstává stejný. Když zbytek vyjde 0, je NSD poslední nenulové číslo.greatest common divisor (GCD), Euclidean algorithm
\(1071 = 2\cdot462 + 147\), \(462 = 3\cdot147 + 21\), \(147 = 7\cdot21 + 0\). Tři dělení, \(\mathrm{NSD}(1071, 462) = 21\). Kontrola: \(1071 = 51\cdot21\), \(462 = 22\cdot21\) a 51 a 22 nemají společného dělitele.
Hledat NSD rozkladem na prvočísla je pro velká čísla beznadějné (kapitola 9 ukáže, že na tom stojí šifra RSA). Euklidův algoritmus je rychlý i pro čísla se stovkami číslic.
Jak rychlý? Nejhůř se algoritmu daří s dvojicemi po sobě jdoucích Fibonacciho čísel (1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89…), kde každý podíl vyjde 1 a čísla klesají nejpomaleji. \(\mathrm{NSD}(89, 55)\) potřebuje 9 dělení. Lamé (1844) dokázal, že počet dělení nepřesáhne pětinásobek počtu desítkových číslic menšího čísla; jde o jeden z prvních odhadů složitosti algoritmu v dějinách. Počet kroků tedy roste s počtem číslic, ne s velikostí čísel – to je v řeči kapitoly 6 logaritmická složitost.Lamé's theorem
Euklidův algoritmus a jeho rozšířená verze (která najde i čísla \(x, y\) s \(ax + by = \mathrm{NSD}(a, b)\)) běží pokaždé, když se ve vašem prohlížeči navazuje šifrované spojení: počítají se s nimi inverze v modulární aritmetice, bez kterých by RSA ani další šifry nefungovaly.
2.5Správnost a konečnost
Že algoritmus funguje na několika příkladech, nic nedokazuje. Správnost se dokazuje dvěma nástroji. Invariant je tvrzení, které platí před každým průchodem cyklem; z něj a z podmínky ukončení plyne správnost výsledku. Variant (také konvergentní funkce) je nezáporné celé číslo, které se každým průchodem zmenší; protože nemůže klesat donekonečna, cyklus skončí.loop invariant, loop variant, termination
Invariant: NSD aktuálních hodnot \(a, b\) se rovná NSD původních vstupů (plyne z rovnosti \(\mathrm{NSD}(a, b) = \mathrm{NSD}(b, a \bmod b)\)). Když cyklus skončí, je \(b = 0\) a \(\mathrm{NSD}(a, 0) = a\), takže výsledek je správný.
Variant: hodnota \(b\). Nový \(b\) je zbytek \(a \bmod b\), tedy menší než starý \(b\), a přitom nezáporný. Klesající posloupnost přirozených čísel je konečná, cyklus proto skončí.
U každého cyklu se zeptejte: (1) Co platí pokaždé, když jsem na začátku cyklu? (2) Co se každým průchodem zmenšuje? Když na druhou otázku nemáte odpověď, cyklus se možná zacyklí. Robot z úrovně 4 laboratoře nemá variant zaručený obecně: pravidlo pravé ruky projde každé bludiště bez kruhových chodeb, ale v bludišti s ostrůvkem kolem cíle by kroužilo věčně.
2.6Procvičení
opakuj 4 { opakuj 3 { krok } vpravo }. Kde skončí a kolik kroků ujede?d ← 2; dokud d·d ≤ n: když n mod d = 0: vrať „složené“; d ← d + 1; vrať „prvočíslo“. Stačí zkoušet dělitele do \(\sqrt{n}\): má-li \(n\) dělitele větší než \(\sqrt{n}\), má i menšího. Pro 97 zkusí \(d = 2, 3, \dots, 9\) (protože \(10\cdot10 = 100 \gt 97\)), tedy 8 dělení, a ohlásí prvočíslo.- Algoritmus je konečný, jednoznačný a obecný postup od vstupu k výstupu.
- Stačí tři stavební kameny: posloupnost, větvení a cyklus.
- Cyklus s podmínkou reaguje na data; proto program funguje i na vstupech, které jste předem neviděli.
- Správnost cyklu dokazuje invariant, konečnost variant. Euklidův algoritmus je rychlý, protože počet kroků roste s počtem číslic.
Počítač, internet a bezpečnostzáklady
Počítač je stroj, který podle programu uloženého v paměti zpracovává data uložená v téže paměti. Internet je síť sítí, ve které si počítače předávají malé balíčky dat podle společných pravidel – protokolů. Kdo rozumí oběma, lépe pozná, kdy mu na síti hrozí nebezpečí.
Internet funguje jako pošta. IP adresa je adresa domu, DNS je telefonní seznam, který ke jménu najde adresu, a velký balík se posílá jako řada malých dopisů (paketů), z nichž každý může jet jinou cestou. HTTPS je dopis v zalepené obálce s ověřeným odesílatelem: pošťák vidí, komu ho nese, ale nepřečte ho.
+Teorie: architektura počítače, operační systém, sítě, DNS, HTTPS a bezpečnost uživatele
3.1Z čeho se skládá počítač
Téměř všechny dnešní počítače vycházejí z von Neumannovy architektury, popsané v roce 1945 ve zprávě o počítači EDVAC. Jejím jádrem je myšlenka uloženého programu: instrukce programu leží ve stejné paměti jako data a dají se načíst, změnit i vytvořit jiným programem.von Neumann architecture, stored program
Procesor pracuje v cyklu načti – dekóduj – proveď: z adresy v čítači instrukcí načte instrukci, zjistí, co znamená (sečti, porovnej, skoč jinam, ulož do paměti…), provede ji a posune čítač na další. Rytmus udávají takty. Při frekvenci 3 GHz trvá takt \(1/(3\cdot10^{9})\ \text{s} = 0{,}33\) ns; světlo za tu dobu urazí jen 10 cm. Moderní procesor zvládne v jednom taktu i několik instrukcí najednou a má víc jader, z nichž každé je samostatný procesor.fetch–decode–execute cycle, clock, core
Procesor se skládá z miliard tranzistorů zapojených do logických hradel (AND, OR, NOT). Jak se z hradel postaví sčítačka a paměťová buňka, vysvětluje průvodce Elektrotechnika; logiku, na které hradla stojí, průvodce Logika a kritické myšlení.
3.2Paměťová hierarchie
Rychlá paměť je drahá a malá, levná paměť velká a pomalá. Počítač proto skládá několik úrovní: registry, vyrovnávací paměti procesoru (cache L1, L2, L3), operační paměť RAM a trvalé úložiště (SSD, pevný disk). Co program právě potřebuje, se drží co nejblíž procesoru. Funguje to díky lokalitě: programy často sahají na stejná data znovu (časová lokalita) a na data uložená vedle sebe (prostorová lokalita).memory hierarchy, cache, locality of reference
| Kde data leží | Řádově | Kdyby 1 ns byla 1 s |
|---|---|---|
| cache L1 | 1 ns | 1 s |
| cache L2 | 4 ns | 4 s |
| operační paměť RAM | 100 ns | 1,7 min |
| SSD (náhodné čtení) | 100 µs | 1,2 dne |
| pevný disk (vystavení hlavy) | 10 ms | 116 dní |
| paket přes oceán a zpět | 150 ms | 4,8 roku |
Pro programátora z tabulky plyne jednoduché pravidlo: práce s daty, která už jsou v paměti, je levná; každé čekání na disk nebo síť je drahé. Rychlé programy proto čtou data po velkých blocích, ukládají si výsledky (mezipaměť, cache) a posílají po síti méně požadavků.
3.3Operační systém
Operační systém je program, který spravuje hardware a nabízí ostatním programům jednotné služby. Jeho jádro běží ve zvláštním privilegovaném režimu procesoru; aplikace o jeho služby žádají systémovým voláním. Hlavní úlohy:operating system, kernel, system call
- Procesy a plánování: každý spuštěný program je proces. Plánovač je střídá po milisekundách, takže se zdá, že běží současně, i když jader je méně než procesů.
- Správa paměti: každý proces vidí vlastní virtuální paměť; systém ji mapuje na fyzickou RAM a odděluje procesy od sebe, takže chyba jednoho programu nepřepíše data druhého.
- Souborový systém: uspořádá bajty na disku do souborů a složek (stromová struktura, kapitola 7).
- Ovladače a vstup/výstup: skryjí rozdíly mezi tisíci typy zařízení.
- Oprávnění a bezpečnost: kdo smí číst které soubory, která aplikace smí k mikrofonu nebo poloze.
3.4Sítě a internet
Data se po síti posílají v paketech, kousky o velikosti zhruba do 1 500 bajtů. Každý paket nese adresu odesílatele i příjemce a směrovače ho předávají dál, každý podle své tabulky „kterým směrem je to blíž“. Pakety jedné zprávy mohou jet různými cestami a dorazit v jiném pořadí. Této metodě se říká přepojování paketů; díky ní síť přežije výpadek části linek.packet switching, router
Komunikaci řídí vrstvy protokolů; každá řeší jednu starost a spoléhá na vrstvu pod sebou. Model TCP/IP má čtyři vrstvy:
- Linková (Ethernet, Wi-Fi): přenos rámce k sousednímu zařízení.
- Síťová (IP): doručení paketu přes mnoho sítí na cílovou IP adresu. IPv4 (RFC 791) má 32bitové adresy, tedy \(2^{32} = 4\,294\,967\,296\) adres, což je dnes málo. IPv6 (RFC 8200) má 128 bitů, \(2^{128} \approx 3{,}4\cdot10^{38}\) adres.
- Transportní (TCP, UDP): TCP (RFC 9293) z nespolehlivých paketů skládá spolehlivý proud bajtů: čísluje je, potvrzuje, ztracené posílá znovu a řadí. UDP (RFC 768) posílá samostatné zprávy bez záruk; hodí se tam, kde je pozdní data lepší zahodit (hovor, hra).
- Aplikační (HTTP, DNS, e-mail…): pravidla konkrétní služby.
3.5DNS: telefonní seznam internetu
Lidé si pamatují jména (skola.example), počítače potřebují IP adresy. Převod zajišťuje systém doménových jmen (DNS), popsaný v RFC 1034 a 1035 (1987). Jména jsou hierarchická a čtou se zprava: kořen, doména nejvyšší úrovně (.cz, .org), doména druhé úrovně (název organizace), případně další úrovně. Váš počítač se zeptá rekurzivního resolveru (obvykle u poskytovatele připojení) a ten postupně obejde servery kořene, nejvyšší úrovně a dané domény. Odpovědi se ukládají do mezipaměti na dobu, kterou určí správce domény (TTL).Domain Name System, resolver, time to live
O tom, komu doména patří, rozhoduje její konec, ne začátek. Adresa alfabanka.example.overeni-klienta.example patří vlastníkovi domény overeni-klienta.example; slovo „alfabanka“ na začátku si může napsat kdokoli. Podvodníci toho využívají spolu s doménami, které se liší jedním písmenem nebo znakem z jiné abecedy.
3.6HTTP a HTTPS
HTTP je protokol webu: prohlížeč pošle požadavek (metoda GET pro čtení, POST pro odeslání formuláře, cesta, hlavičky) a server vrátí odpověď se stavovým kódem a obsahem. Kódy 2xx znamenají úspěch (200 OK), 3xx přesměrování (301), 4xx chybu klienta (404 Nenalezeno, 403 Zakázáno), 5xx chybu serveru (500). Význam protokolu popisuje RFC 9110 (2022), verze HTTP/1.1, HTTP/2 a HTTP/3 se liší jen způsobem přenosu.HTTP request, response, status code
HTTPS je HTTP přenášené přes šifrovaný kanál TLS (aktuální verze 1.3, RFC 8446, 2018). TLS zajišťuje tři věci: důvěrnost (obsah nikdo po cestě nepřečte), integritu (nikdo ho nezmění bez odhalení) a ověření serveru: server předloží certifikát podepsaný certifikační autoritou, které váš prohlížeč důvěřuje, a dokáže, že vlastní k němu patřící soukromý klíč. Jak to funguje matematicky, ukáže kapitola 9.HTTPS, TLS, certificate authority
RTT 50 ms, DNS se musí zeptat, TLS 1.3: čtyři cesty tam a zpět, \(4\cdot50 = 200\) ms do prvního bajtu. Stránka 2 MB při rychlosti 50 Mbit/s se přenáší \(2\cdot8/50 = 0{,}32\) s. Celkem 0,52 s. Se servery na druhé straně oceánu (RTT 150 ms) by čekání na první bajt trvalo 600 ms – víc než samotný přenos. Proto se obsah webů kopíruje na servery blízko uživatelů.
Zámek v adresním řádku říká jen to, že spojení je šifrované a vede na server, který vlastní certifikát pro zobrazenou doménu. Neříká, že je stránka poctivá. Certifikát si zdarma pořídí i podvodník pro svou doménu overeni-klienta.example. Kontrolujte doménu, ne zámek.
3.7Bezpečnost a soukromí uživatele
Většina útoků na běžné uživatele nevyužívá chyby v šifrování, ale lidskou důvěřivost a slabá nebo opakovaná hesla. Obrana je proto hlavně v návycích.
Hesla
Síla náhodného hesla se měří entropií: \(L\) znaků vybraných náhodně z \(N\) možností dává \(L\log_2 N\) bitů. Každý bit navíc zdvojnásobí počet pokusů. Délka pomáhá víc než složitost: 15 náhodných malých písmen má 70,5 bitu, 8 náhodných znaků ze všech 94 tisknutelných jen 52,4 bitu. Americký standard NIST SP 800-63B-4 (2025) proto žádá u hesla, které je jediným ověřovacím faktorem, aspoň 15 znaků, u hesla doplněného druhým faktorem aspoň 8; služby mají přijímat aspoň 64 znaků, nemají vynucovat pravidla typu „velké písmeno a číslice“ ani pravidelnou změnu hesla, ale mají odmítat hesla ze seznamů uniklých a běžných hesel.password entropy, passphrase
Deset náhodných znaků z písmen a číslic: \(10\log_2 62 = 59{,}5\) bitu. Pět náhodných slov ze seznamu 7 776 slov: \(5\log_2 7\,776 = 64{,}6\) bitu – víc, a přitom se pět slov pamatuje snáz. Při miliardě pokusů za sekundu (\(10^{9}\)) by průměrné uhodnutí pěti slov trvalo \(2^{64{,}6}/2/10^{9}\) s, tedy asi 450 let; při \(10^{10}\) pokusech 45 let. Kdo si heslo vymyslí sám, má entropii mnohem menší, protože lidé volí předvídatelně.
- Každá služba jiné heslo. Když uniknou hesla z jedné služby, útočníci je zkoušejí jinde. Správce hesel vygeneruje a zapamatuje náhodná hesla; vy si pamatujete jedno silné hlavní heslo.
- Dvoufázové ověření (2FA) kombinuje dva různé faktory: něco, co znáte (heslo), něco, co máte (telefon, bezpečnostní klíč), nebo něco, čím jste (otisk prstu). Ukradené heslo samo nestačí.two-factor authentication
- Přístupové klíče (passkeys, standard WebAuthn) nahrazují heslo dvojicí kryptografických klíčů vázanou na doménu služby. Na podvodné doméně nefungují, takže odolávají phishingu.
Phishing a sociální inženýrství
Varovné znaky: nátlak a spěch („do 24 hodin“), žádost o heslo, kód nebo údaje karty, odkaz na nečekanou doménu, příliš výhodná nabídka, zpráva od „banky“ nebo „kurýra“, kterou jste nečekali. Banka ani úřad po vás nikdy nebude chtít heslo nebo kód z SMS. Obrana: odkaz neotvírat, do služby se přihlásit sami (záložka, aplikace), při telefonátu zavěsit a zavolat zpět na oficiální číslo. Kód z SMS, který přišel, aniž jste o něj žádali, nikomu nesdělujte – znamená, že někdo zkouší vaše heslo.phishing, social engineering
Další návyky
- Aktualizace opravují známé bezpečnostní chyby; instalujte je z nastavení systému nebo oficiálního obchodu s aplikacemi.
- Zálohy podle pravidla 3-2-1: tři kopie, na dvou různých médiích, jedna mimo domov (a odpojená, aby ji nezašifroval vyděračský program).
- Soukromí: aplikacím povolujte jen oprávnění, která potřebují; v nastavení cookies volte odmítnutí nepotřebných. Práva vůči firmám, které o vás zpracovávají údaje (přístup, oprava, výmaz), upravuje obecné nařízení EU o ochraně osobních údajů (GDPR).
- Při podezření na podvod volejte banku na číslo z jejích oficiálních stránek nebo z platební karty a věc oznamte Policii ČR (158). Doporučení pro uživatele vydává Národní úřad pro kybernetickou a informační bezpečnost (NÚKIB).
3.8Procvičení
https://prihlaseni.alfabanka.example.platby-overeni.example/ucet?platby-overeni.example: jméno se čte zprava, „.example“ je doména nejvyšší úrovně a „platby-overeni“ doména druhé úrovně. Vše vlevo jsou subdomény, které si vlastník pojmenuje libovolně. Odkaz s bankou Alfa nesouvisí.- Procesor v cyklu čte a provádí instrukce uložené v paměti spolu s daty; rychlá paměť je malá, velká je pomalá.
- Operační systém střídá procesy, odděluje jejich paměť a hlídá oprávnění.
- Internet předává pakety; IP adresuje, TCP zajišťuje spolehlivost, DNS překládá jména, TLS šifruje a ověřuje server.
- Bezpečnost uživatele stojí na návycích: dlouhá a různá hesla, správce hesel, druhý faktor, kontrola domény, aktualizace a zálohy.
Programovánístřední škola
Programovat znamená zapsat algoritmus v jazyce, kterému rozumí počítač, a pak hledat, proč dělá něco jiného, než jste chtěli. Proměnné, typy, podmínky, cykly a funkce jsou ve všech běžných jazycích stejné myšlenky v různém pravopisu.
Proměnná je krabička se jmenovkou, funkce je recept, který si pojmenujete a pak jen zavoláte („udělej palačinky pro čtyři“). Rekurze je recept, který odkazuje sám na sebe: „Jak sníst kupu palačinek? Sněz jednu a pak sněz zbytek kupy. Když už žádná nezbývá, jsi hotový.“ Ta poslední věta je nejdůležitější.
while s nečekaně divokým chováním: je-li číslo sudé, vydělte ho dvěma, je-li liché, vynásobte třemi a přičtěte jedna. Opakujte, dokud nedostanete 1. Zda to skončí pro každé kladné celé číslo, dodnes nikdo nedokázal.def collatz(n): kroky = 0 while n != 1: if n % 2 == 0: n = n // 2 else: n = 3 * n + 1 kroky += 1 return kroky
+Teorie: proměnné a typy, řízení běhu, funkce, rekurze, ladění a testování
4.1Proměnné a typy
Proměnná je pojmenované místo pro hodnotu. Přiřazení x = 5 (v pseudokódu \(x \leftarrow 5\)) neznamená rovnost jako v matematice, ale příkaz „ulož do \(x\) hodnotu 5“. Proto dává smysl x = x + 1: vezmi starou hodnotu, přičti 1 a výsledek ulož zpět.variable, assignment
Každá hodnota má typ, který určuje, jaké operace s ní lze dělat: celé číslo (int), desetinné číslo (float), logická hodnota (True/False), text neboli řetězec (str), seznam či pole. Jazyky se liší tím, kdy typy kontrolují. Při statickém typování (C, Java) zná typ každé proměnné už překladač a chybu ohlásí před spuštěním. Při dynamickém typování (Python, JavaScript) se typ zjišťuje až za běhu.data type, static and dynamic typing
Jazyky se liší i tím, jak ochotně typy samy převádějí. Python je přísný: "5" + 3 skončí chybou TypeError. JavaScript převádí potichu, a výsledky pak překvapí:
| Výraz | Python | JavaScript | Proč |
|---|---|---|---|
"5" + 3 | chyba TypeError | "53" | JS převede číslo na text a spojí |
"5" - 3 | chyba TypeError | 2 | odčítání textů neexistuje, JS převede text na číslo |
7 / 2 | 3.5 | 3.5 | obyčejné dělení |
| celočíselně \(-7 : 2\) | -7 // 2 = −4 | Math.trunc(-7/2) = −3 | Python zaokrouhluje dolů, trunc k nule |
-7 % 2 | 1 | -1 | znaménko zbytku podle dělitele, resp. dělence |
0.1 + 0.2 | 0.30000000000000004 | dvojková reprezentace (oddíl 1.4) | |
Hodnota z formuláře nebo z klávesnice je vždy text. V JavaScriptu pak vek + 1 pro zadaných „17“ dá „171“. Vstup převádějte na číslo výslovně (Number(vek), v Pythonu int(vek)) a kontrolujte, že převod uspěl.
4.2Řízení běhu
Tři struktury z kapitoly 2 mají v každém jazyce svou podobu. Větvení if … elif … else, cyklus s pevným počtem opakování for, cyklus s podmínkou while. Příkaz break cyklus ukončí předčasně, continue přeskočí zbytek aktuálního průchodu. Tentýž program ve dvou jazycích:
# Python: součet sudých čísel s = 0 for x in [3, 8, 5, 12, 7]: if x % 2 == 0: s = s + x print(s) # 20
// JavaScript: totéž let s = 0; for (const x of [3, 8, 5, 12, 7]) { if (x % 2 === 0) s = s + x; } console.log(s); // 20
Python vyznačuje bloky odsazením, JavaScript složenými závorkami. JavaScript má dvě porovnání: == s převodem typů a === bez něj; používejte to druhé.
4.3Funkce
Funkce je pojmenovaný kus programu s parametry (vstupy) a návratovou hodnotou (výstupem). Funkce zkracují program, protože se kód nepíše dvakrát, a hlavně ho zpřehledňují: kdo volá prumer(znamky), nemusí vědět, jak se průměr počítá. Proměnné vytvořené uvnitř funkce jsou lokální: existují jen během jejího běhu a nejsou vidět zvenku. Oblasti, ve které je jméno platné, se říká rozsah platnosti.function, parameter, return value, local variable, scope
Funkce, která jen z argumentů spočítá výsledek a nic jiného nemění, se nazývá čistá. Funkce, která navíc něco vypíše, zapíše do souboru nebo změní globální proměnnou, má vedlejší efekt. Čisté funkce se snáz testují: pro stejné vstupy vždy vrátí totéž.pure function, side effect
Při každém volání si počítač na zásobník volání uloží rámec: hodnoty parametrů, lokální proměnné a místo, kam se má vrátit. Po návratu rámec odebere. Zásobník funguje jako stoh talířů: poslední přidaný se bere první (kapitola 7).call stack, stack frame
fakt(n) = n · fakt(n − 1), fakt(1) = 1. Rámce přibývají, dokud se nedojde k základnímu případu; pak se výsledky vracejí a rámce mizí v opačném pořadí.4.4Rekurze
Rekurzivní funkce volá sama sebe na menší verzi téže úlohy. Musí mít základní případ, který se vyřeší přímo, a rekurzivní krok, který úlohu zmenší směrem k základnímu případu. Bez základního případu se funkce volá, dokud nedojde paměť na zásobníku; Python v tom případě ve výchozím nastavení skončí po 1 000 úrovních chybou RecursionError.recursion, base case
def fakt(n): if n <= 1: # základní případ return 1 return n * fakt(n - 1)
def fib(n, pamet={}): if n < 2: return n if n not in pamet: pamet[n] = fib(n-1) + fib(n-2) return pamet[n]
Rekurze se hodí na úlohy, které se přirozeně rozpadají na menší kopie sebe sama: procházení stromu složek, řazení slučováním (kapitola 5), hledání v bludišti. Každou rekurzi lze přepsat na cyklus se zásobníkem a naopak.
Hanojské věže
Na první tyči leží \(n\) kotoučů od největšího po nejmenší. Úkol: přenést je na třetí tyč, vždy jen jeden kotouč a nikdy větší na menší. Rekurzivní řešení: přeneste \(n-1\) horních kotoučů na pomocnou tyč, největší kotouč na cílovou a pak \(n-1\) kotoučů z pomocné na cílovou. Počet tahů splňuje \(T(n) = 2T(n-1) + 1\), \(T(1) = 1\), tedy \(T(n) = 2^{n} - 1\).Tower of Hanoi, recurrence
Pro 10 kotoučů je třeba \(2^{10}-1 = 1\,023\) tahů. Pro 64 kotoučů z legendy \(2^{64}-1 = 18\,446\,744\,073\,709\,551\,615\) tahů; při jednom tahu za sekundu by to trvalo \(5{,}85\cdot10^{11}\) let, přes čtyřicetinásobek dosavadního stáří vesmíru. Algoritmus je přitom optimální: méně tahů nestačí.
Paměť místo opakování
Naivní rekurzivní Fibonacci počítá \(F(n-2)\) jednou přímo a jednou uvnitř \(F(n-1)\); počet volání roste zhruba jako \(1{,}618^{n}\). Pro \(n = 30\) je to 2 692 537 volání, pro \(n = 40\) už 331 160 281. Verze s pamětí (memoizací) spočítá každou hodnotu jednou: pro \(n = 40\) jen 79 volání. Obecný postup – rozložit úlohu na podúlohy, každou vyřešit jednou a výsledky skládat – se nazývá dynamické programování.memoization, dynamic programming
4.5Ladění a testování
Chyby jsou trojího druhu. Syntaktické (chybějící závorka) odhalí překladač nebo interpret ještě před spuštěním. Běhové (dělení nulou, index mimo rozsah) program za běhu shodí. Nejzrádnější jsou logické: program běží, ale počítá něco jiného.syntax error, runtime error, logic error
- Zopakujte chybu spolehlivě a najděte co nejmenší vstup, na kterém nastane.
- Vyslovte hypotézu, kde je problém, a ověřte ji: ladicím výpisem hodnot, nebo v debuggeru, kde program zastavíte na zarážce (breakpoint) a krokujete.
- Opravte příčinu, ne projev, a napište test, který chybu zachytí, kdyby se vrátila.
def prumer(cisla): return sum(cisla) / len(cisla) # jednoduché testy: když neplatí, program ohlásí AssertionError assert prumer([1, 2, 3]) == 2 assert prumer([5]) == 5 # prumer([]) skončí ZeroDivisionError: co má funkce vrátit pro prázdný seznam?
Slovo „bug“ (brouk) pro technickou závadu používali inženýři už v 19. století. Proslavila ho ale událost z 9. září 1947: tým kolem Grace Hopperové našel v reléovém počítači Mark II na Harvardu zachycenou můru a vlepil ji do provozního deníku s poznámkou o „prvním skutečném případu nalezeného brouka“. Deník je dnes ve sbírkách Smithsonian Institution.
Metoda gumové kachničky: vysvětlete svůj kód řádek po řádku někomu, kdo nerozumí programování, třeba hračce na stole. Při převádění do slov si chyby všimnete sami častěji, než byste čekali.
4.6Paradigmata programování
Jazyky podporují různé styly myšlení. Imperativní program je posloupnost příkazů měnících stav (proměnné). Objektově orientovaný styl seskupuje data a funkce, které s nimi pracují, do objektů (student má jméno a umí spočítat průměr známek). Funkcionální styl skládá čisté funkce a vyhýbá se změnám stavu. Deklarativní styl popisuje, co chceme, ne jak to získat: typický příklad je SQL v kapitole 10. Python i JavaScript umožňují všechny tři první styly.imperative, object-oriented, functional, declarative programming
4.7Procvičení
s = 0, for i in range(1, 5): s += i * i, print(s)?range(1, 5) dává 1, 2, 3, 4 (horní mez se nezahrnuje). \(s = 1 + 4 + 9 + 16 = 30\).def cs(n): return n if n < 10 else n % 10 + cs(n // 10). Základní případ je jednociferné číslo, krok odtrhne poslední cifru. \(cs(2026) = 6 + cs(202) = 6 + 2 + cs(20) = 8 + 0 + cs(2) = 10\).def posledni(a): return a[len(a)] má vrátit poslední prvek seznamu. Co je špatně a jak ji otestovat?len(a) - 1, takže a[len(a)] skončí chybou IndexError (chyba o jedna). Správně a[len(a) - 1] nebo v Pythonu a[-1]. Testy: assert posledni([4, 7, 9]) == 9, assert posledni([5]) == 5 a rozhodnout, co dělat s prázdným seznamem.- Přiřazení není rovnost; typ hodnoty určuje, co s ní lze dělat, a jazyky se liší v převodech typů.
- Funkce s parametry a návratovou hodnotou dělí program na srozumitelné části; volání se ukládají na zásobník.
- Rekurze potřebuje základní případ a krok, který se k němu blíží. Opakované výpočty ušetří paměť (memoizace).
- Ladění je metoda: zopakovat, zmenšit, ověřit hypotézu, opravit příčinu, napsat test.
Řazení a vyhledávánístřední škola
Seřadit data je jedna z nejčastějších úloh vůbec, a přitom na ní nejlépe vidět, jak velký rozdíl dělá volba algoritmu. Seřazená data se pak dají prohledávat bleskově: v milionu jmen najdete to správné na dvacet pohledů.
Když řadíte karty v ruce, berete jednu po druhé a zasouváte ji na správné místo mezi už seřazené. To je řazení vkládáním. Když hledáte slovo ve slovníku, otevřete ho uprostřed, podíváte se, jestli je hledané slovo před, nebo za, a půlku zahodíte. To je binární vyhledávání. Obojí děláte intuitivně; informatika umí spočítat, kolik vás to stojí.
+Teorie: řazení výměnou, vkládáním, slučováním, rychlé řazení, dolní mez a binární vyhledávání
5.1Úloha řazení
Řazení uspořádá posloupnost \(a_1, \dots, a_n\) tak, aby \(a_1 \le a_2 \le \dots \le a_n\). Algoritmy porovnáváme podle počtu porovnání a přesunů v nejlepším, průměrném a nejhorším případě a podle dalších vlastností. Stabilní řazení zachová pořadí prvků se stejným klíčem (seřadíte-li žáky podle známky stabilně, zůstanou se stejnou známkou v abecedním pořadí). Řazení na místě potřebuje jen konstantní paměť navíc.sorting, stable sort, in-place
5.2Bublinkové řazení
Procházíme pole a prohazujeme sousedy ve špatném pořadí. Po prvním průchodu „vybublá“ největší prvek na konec, po druhém druhý největší a tak dál. Počet porovnání je \((n-1) + (n-2) + \dots + 1 = n(n-1)/2\); pro 10 prvků 45. Algoritmus je stabilní a na místě, ale pomalý; hodí se jako první příklad, ne do praxe.bubble sort
pro k od n−1 dolů do 1: pro i od 1 do k: když a[i] > a[i+1]: prohoď a[i], a[i+1]
5.3Řazení vkládáním
Levá část pole je seřazená. Vezmeme další prvek a posouváme ho doleva, dokud nenarazíme na menší. V nejhorším případě (obrácené pole) to stojí \(n(n-1)/2\) porovnání, v nejlepším (seřazené pole) jen \(n-1\). Počet posunů se přesně rovná počtu inverzí, tedy dvojic prvků ve špatném pořadí. Na téměř seřazených datech je proto řazení vkládáním velmi rychlé.insertion sort, inversion
Pole 5, 2, 4, 6, 1, 3. Postupně: 2 5 4 6 1 3 → 2 4 5 6 1 3 → 2 4 5 6 1 3 → 1 2 4 5 6 3 → 1 2 3 4 5 6. Celkem 12 porovnání a 9 posunů; pole má právě 9 inverzí (například 5 > 2, 5 > 4, 5 > 1…).
5.4Řazení slučováním
Metoda rozděl a panuj: pole rozdělíme na dvě poloviny, každou seřadíme (rekurzivně) a obě seřazené poloviny sloučíme: opakovaně bereme menší z dvou čel. Sloučení dvou úseků o celkové délce \(m\) stojí nejvýš \(m-1\) porovnání. Algoritmus popsal John von Neumann v roce 1945.merge sort, divide and conquer
Hloubka rekurze je \(\lceil\log_2 n\rceil\) a na každé úrovni se sloučí dohromady \(n\) prvků. Odtud rekurence a výsledek:
Přesně je to v nejhorším případě \(n\lceil\log_2 n\rceil - 2^{\lceil\log_2 n\rceil} + 1\) porovnání: pro \(n = 8\) jde o 17, pro \(n = 1\,000\) o 8 977. Algoritmus je stabilní a jeho čas nezávisí na datech, potřebuje ale pomocné pole velikosti \(n\).
5.5Rychlé řazení
Hoare (1962) zvolil jiný postup: vybrat pivot, přeskupit pole tak, aby menší prvky byly vlevo a větší vpravo (rozdělení), a obě části seřadit rekurzivně. Sloučení odpadá, pivot už stojí na svém místě.quicksort, pivot, partition
Pole 7, 2, 1, 6, 8, 5, 3, 4, pivot je poslední prvek 4. Po rozdělení (7 porovnání) vznikne 2, 1, 3, 4, 8, 5, 7, 6: vlevo od pivotu jen menší, vpravo jen větší čísla. Dále se řadí zvlášť úseky 2, 1, 3 a 8, 5, 7, 6.
Při dobrém pivotu (blízko mediánu) se pole dělí napůl a čas je \(n\log n\). Průměrný počet porovnání přes všechna pořadí vstupu je \(2(n+1)H_n - 4n\), kde \(H_n = 1 + \tfrac12 + \dots + \tfrac1n\); asymptoticky \(2n\ln n \approx 1{,}39\,n\log_2 n\). Pro \(n = 1\,000\) vychází průměrně 10 986 porovnání. V nejhorším případě, když pivot je vždy nejmenší nebo největší prvek, je to \(n(n-1)/2\). Při volbě posledního prvku jako pivotu nastane nejhorší případ právě na seřazeném poli. Obrana: náhodný pivot nebo medián ze tří prvků.
Knihovny programovacích jazyků používají hybridy. Rychlé řazení přepne na řazení haldou, když se rekurze příliš prohloubí (introsort), a krátké úseky dořeší vkládáním. Python (a pro objekty i některé další jazyky) používá stabilní algoritmus Timsort, který v datech hledá už seřazené úseky a slučuje je; na reálných, částečně seřazených datech je proto často rychlejší než \(n\log n\).
5.6Rychleji to nejde: dolní mez
Každé řazení, které o prvcích zjišťuje informace jen porovnáváním, lze znázornit rozhodovacím stromem: v uzlech porovnání, v listech výsledná pořadí. Strom musí mít aspoň \(n!\) listů (každé pořadí vstupu vyžaduje jinou přestavbu) a binární strom s \(n!\) listy má hloubku aspoň \(\log_2 n!\). Nejhorší případ tedy potřebuje aspoň \(\lceil\log_2 n!\rceil\) porovnání.decision tree, lower bound
Pro 10 prvků je \(\log_2 10! = 21{,}8\), takže aspoň 22 porovnání; bublinkové řazení jich spotřebuje 45. Pro 1 000 prvků je mez 8 530 a řazení slučováním s 8 977 porovnáními v nejhorším případě je jí velmi blízko. Řazení slučováním je tedy asymptoticky optimální. Rychleji než \(n\log n\) umějí řadit jen algoritmy, které o klíčích vědí víc (například řazení počítáním pro malá celá čísla).
5.7Binární vyhledávání
V seřazeném poli hledáme hodnotu \(x\). Porovnáme ji s prostředním prvkem: je-li menší, hledáme dál jen v levé polovině, je-li větší, v pravé. Invariant: pokud \(x\) v poli je, leží v aktuálním úseku. Každý krok úsek aspoň způlí, takže stačí \(\lfloor\log_2 n\rfloor + 1\) porovnání: pro 1 000 prvků 10, pro milion 20, pro miliardu 30.binary search
def hledej(a, x): lo, hi = 0, len(a) - 1 while lo <= hi: m = (lo + hi) // 2 if a[m] == x: return m if a[m] < x: lo = m + 1 else: hi = m - 1 return -1 # není v poli
Binární vyhledávání se snadno napíše špatně: lo = m místo lo = m + 1 vede k zacyklení, < místo <= přehlédne poslední prvek. V jazycích s pevnou šířkou celých čísel přetéká výraz (lo + hi) / 2 pro velká pole; bezpečně je lo + (hi − lo) / 2. Tato chyba přežila v rozšířených knihovnách desítky let, než ji v roce 2006 popsal Joshua Bloch.
| Algoritmus | nejlepší | průměrný | nejhorší | paměť navíc | stabilní |
|---|---|---|---|---|---|
| bublinkové | \(n^{2}/2\)* | \(n^{2}/2\) | \(n^{2}/2\) | \(O(1)\) | ano |
| vkládáním | \(n\) | \(n^{2}/4\) | \(n^{2}/2\) | \(O(1)\) | ano |
| slučováním | \(\tfrac12 n\log_2 n\) | \(n\log_2 n\) | \(n\log_2 n\) | \(O(n)\) | ano |
| rychlé | \(n\log_2 n\) | \(1{,}39\,n\log_2 n\) | \(n^{2}/2\) | \(O(\log n)\) | ne |
5.8Procvičení
- Jednoduché řazení (bublinkové, vkládáním) potřebuje řádově \(n^{2}\) porovnání; vkládání je ale skvělé na téměř seřazená data.
- Rozděl a panuj: slučování a rychlé řazení zvládnou \(n\log n\), rychleji porovnáváním řadit nejde.
- Volba pivotu rozhoduje: špatný pivot vrátí rychlé řazení na \(n^{2}\).
- Seřazená data prohledá binární vyhledávání za \(\log_2 n\) kroků: milion prvků, dvacet porovnání.
Složitost algoritmůstřední škola
Rychlost programu v sekundách závisí na počítači, jazyce i náhodě. Složitost algoritmu ne: popisuje, jak rychle roste počet kroků, když roste velikost vstupu. A právě růst rozhoduje. Algoritmus, který roste pomalu, porazí na velkých datech i tisíckrát rychlejší počítač.
Do sousední vesnice dojdete pěšky rychleji, než se dostanete na letiště a odbavíte. Do Austrálie už ne. U malých vstupů je jedno, jaký algoritmus zvolíte; konstanty a režie rozhodují víc. U velkých vstupů rozhoduje jen to, jak cena roste se vzdáleností – a pěšky to do Austrálie nejde, ať jste jakkoli zdatní.
x += 1. Python, rozsahy podle range.+Teorie: O-notace, hierarchie růstu, rekurence, mistrovská věta a amortizace
6.1Jak měřit rychlost algoritmu
Místo sekund počítáme elementární operace: přiřazení, porovnání, aritmetiku, přístup do pole. Předpokládáme, že každá trvá konstantní dobu (model počítače RAM). Časová složitost je funkce \(T(n)\), která velikosti vstupu \(n\) přiřadí počet operací. Protože pro stejně velké vstupy se počet liší (seřazené a obrácené pole), rozlišujeme nejhorší, průměrný a nejlepší případ. Nejčastěji se uvádí nejhorší: je to záruka.time complexity, worst case, average case
6.2O-notace
Zajímá nás chování pro velká \(n\), proto zanedbáváme konstanty a menší členy. Formálně:Big O, Big Omega, Big Theta
\(O\) je horní odhad („roste nejvýš tak rychle jako“), \(\Omega\) dolní, \(\Theta\) přesný řád. Rovnítko se tu čte „patří do třídy“, není to symetrická rovnost.
Zvolíme \(c = 4\). Nerovnost \(3n^{2} + 10n + 5 \le 4n^{2}\) je ekvivalentní s \(n^{2} - 10n - 5 \ge 0\), což platí pro \(n \ge 5 + \sqrt{30} \approx 10{,}48\), tedy od \(n_0 = 11\). Stejně dobře by šlo \(c = 18\), \(n_0 = 1\), protože \(3n^{2} + 10n + 5 \le 3n^{2} + 10n^{2} + 5n^{2}\). Obě volby dokazují totéž. A protože zároveň \(3n^{2} + 10n + 5 \ge 3n^{2}\), platí i \(\Theta(n^{2})\).
Ve výrazu ponechte jen nejrychleji rostoucí člen a škrtněte jeho konstantu: \(5n^{3} + 100n^{2}\log n + 10^{6} = \Theta(n^{3})\). Základ logaritmu je jedno, protože \(\log_a n = \log_b n / \log_b a\) se liší jen konstantou; proto se píše prostě \(O(\log n)\).
6.3Hierarchie růstu
Pro velká \(n\) platí \(1 \prec \log n \prec \sqrt{n} \prec n \prec n\log n \prec n^{2} \prec n^{3} \prec 2^{n} \prec n! \prec n^{n}\), kde \(f \prec g\) znamená, že podíl \(f/g\) jde k nule. Algoritmy s polynomiální složitostí (\(n^{k}\)) považujeme za prakticky použitelné, exponenciální za použitelné jen pro malá \(n\). Tabulka ukazuje proč.
| \(f(n)\) | \(n = 10\) | \(n = 100\) | \(n = 1\,000\) | \(n = 10^{6}\) |
|---|---|---|---|---|
| \(\log_2 n\) | 3 ns | 7 ns | 10 ns | 20 ns |
| \(n\) | 10 ns | 100 ns | 1 µs | 1 ms |
| \(n\log_2 n\) | 33 ns | 664 ns | 10 µs | 20 ms |
| \(n^{2}\) | 100 ns | 10 µs | 1 ms | 16,7 min |
| \(n^{3}\) | 1 µs | 1 ms | 1 s | 31,7 let |
| \(2^{n}\) | 1 µs | \(4\cdot10^{13}\) let | \(3\cdot10^{284}\) let | – |
| \(n!\) | 3,6 ms | \(3\cdot10^{141}\) let | – | – |
6.4Algoritmus, nebo hardware?
Gordon Moore v roce 1965 předpověděl, že počet tranzistorů na čipu se bude pravidelně zdvojnásobovat (od roku 1975 uváděl zhruba každé dva roky). Výkon počítačů tak po desetiletí rostl exponenciálně. Přesto lepší algoritmus obvykle přinese víc než lepší počítač: tisíckrát rychlejší stroj zvětší zvládnutelný vstup u algoritmu \(n^{2}\) jen \(\sqrt{1\,000} \approx 31{,}6\)krát, u \(n^{3}\) desetkrát a u \(2^{n}\) jen o 10 (\(\log_2 1\,000 \approx 9{,}97\)).Moore's law
| \(f(n)\) | \(10^{9}\) op/s | \(10^{12}\) op/s (1 000× rychleji) | zlepšení |
|---|---|---|---|
| \(n\log_2 n\) | \(9{,}9\cdot10^{10}\) | \(7{,}8\cdot10^{13}\) | 791× |
| \(n^{2}\) | 1 897 366 | 60 000 000 | 31,6× |
| \(n^{3}\) | 15 326 | 153 261 | 10× |
| \(2^{n}\) | 41 | 51 | +10 |
| \(n!\) | 15 | 17 | +2 |
Řadit milion prvků algoritmem \(n^{2}\) znamená \(10^{12}\) operací, na počítači s \(10^{9}\) operacemi za sekundu 1 000 s, tedy 16,7 min. Algoritmus \(n\log_2 n\) potřebuje \(2\cdot10^{7}\) operací, tedy 0,02 s, i na stroji tisíckrát pomalejším by skončil za 20 s.
6.5Jak složitost určit
- Posloupnost kroků: složitosti se sčítají a vítězí největší, \(O(n) + O(n^{2}) = O(n^{2})\).
- Cyklus: počet průchodů krát cena těla. Vnořené cykly přes \(n\) dávají \(n\cdot n\); vnitřní cyklus „do \(i\)“ dává \(0 + 1 + \dots + (n-1) = n(n-1)/2\), tedy také \(\Theta(n^{2})\).
- Půlení: cyklus, který \(n\) pokaždé vydělí dvěma, proběhne \(\lfloor\log_2 n\rfloor + 1\)krát; pro \(n = 1\,000\) desetkrát.
- Rekurze vede na rekurenci, rovnici, ve které je \(T(n)\) vyjádřeno přes \(T\) menších vstupů.
Mistrovská věta (rozšíření)
Pro algoritmy „rozděl a panuj“, které úlohu velikosti \(n\) rozdělí na \(a\) podúloh velikosti \(n/b\) a rozdělení a složení stojí \(\Theta(n^{d})\), platí:master theorem
Řazení slučováním: \(a = 2\), \(b = 2\), \(d = 1 = \log_2 2\), tedy \(\Theta(n\log n)\). Binární vyhledávání: \(a = 1\), \(b = 2\), \(d = 0 = \log_2 1\), tedy \(\Theta(\log n)\). Karacubovo násobení velkých čísel (1960) převádí násobení dvou \(n\)-ciferných čísel na tři násobení polovičních: \(a = 3\), \(b = 2\), \(d = 1 \lt \log_2 3\), tedy \(\Theta(n^{\log_2 3}) = \Theta(n^{1{,}585})\) místo školních \(n^{2}\).
6.6Paměť a amortizace
Paměťová složitost měří spotřebu paměti navíc ke vstupu: řazení slučováním potřebuje \(\Theta(n)\), rychlé řazení \(\Theta(\log n)\) na zásobník rekurze. Často se dá čas vyměnit za paměť, jako u memoizace v kapitole 4.space complexity, amortized analysis
Amortizovaná složitost je průměrná cena operace v nejhorší posloupnosti operací. Typický příklad je dynamické pole (seznam v Pythonu): když se zaplní, alokuje se pole dvojnásobné velikosti a prvky se zkopírují. Jednotlivé přidání tak občas stojí \(\Theta(n)\), ale při \(n\) přidáních se kopíruje nejvýš \(1 + 2 + 4 + \dots \lt 2n\) prvků. Průměrně tedy přidání stojí \(O(1)\).
6.7Procvičení
for i in range(n): for j in range(i, n): x += 1.while n > 1: n = n // 2 pro \(n = 1\,000\,000\)?- Složitost popisuje růst počtu kroků s velikostí vstupu; konstanty a menší členy zanedbáváme.
- \(O\) je horní odhad, \(\Omega\) dolní, \(\Theta\) přesný řád.
- Polynomiální algoritmy škálují, exponenciální ne. Tisíckrát rychlejší počítač přidá algoritmu \(2^{n}\) jen deset prvků vstupu.
- Rekurze vedou na rekurence; „rozděl a panuj“ řeší mistrovská věta.
Datové strukturystřední škola
Datová struktura je způsob, jak data uspořádat v paměti, aby s nimi šly rychle dělat operace, které potřebujete. Neexistuje nejlepší struktura, jen vhodná pro danou úlohu: co je u jedné zadarmo, stojí u druhé celý průchod daty.
Talíře v kuchyni berete shora: poslední položený jde první (zásobník). U pokladny jde první ten, kdo přišel první (fronta). V knihovně nehledáte knihu tak, že projdete všechny regály, ale podle signatury jdete rovnou k polici (hašovací tabulka), a rodokmen kreslíte jako strom. Každá z těchto organizací se v informatice jmenuje a má spočítanou cenu.
+Teorie: pole a seznamy, zásobník a fronta, stromy, halda, hašování, grafy
7.1Abstraktní datový typ a jeho implementace
Abstraktní datový typ říká, jaké operace s daty lze dělat (vlož, odeber, najdi), a ne, jak jsou data uložena. Datová struktura je konkrétní uspořádání v paměti, které operace implementuje. Tentýž abstraktní typ „množina“ lze implementovat polem, stromem i hašovací tabulkou, s velmi rozdílnou cenou operací.abstract data type (ADT), data structure
7.2Pole a spojový seznam
Pole ukládá prvky v paměti těsně za sebou. Adresu \(i\)-tého prvku spočítá procesor jedním násobením, proto je přístup podle indexu \(O(1)\). Vložení doprostřed ale vyžaduje posunout všechny následující prvky, \(O(n)\). Spojový seznam ukládá každý prvek zvlášť spolu s ukazatelem (adresou) na další prvek. Vložení za známý prvek je \(O(1)\) – stačí přepojit ukazatele –, ale k \(i\)-tému prvku se musíme „dokrokovat“, \(O(n)\).array, linked list, pointer
Pole pevné velikosti se v praxi nahrazuje dynamickým polem (seznam v Pythonu, pole v JavaScriptu), které se při zaplnění zdvojnásobí. Přidání na konec stojí amortizovaně \(O(1)\) (oddíl 6.6). Díky souvislému uložení je pole navíc přátelské k vyrovnávací paměti procesoru (oddíl 3.2) a v praxi bývá rychlejší, než by napovídala O-notace.
7.3Zásobník a fronta
Zásobník má operace vlož na vrchol (push) a odeber z vrcholu (pop); poslední vložený prvek odchází první (LIFO). Používá se pro zásobník volání funkcí (oddíl 4.3), tlačítko Zpět, vyhodnocování výrazů a párování závorek. Fronta vkládá na konec a odebírá z čela; první vložený odchází první (FIFO). Používá se pro tiskové úlohy, zpracování požadavků na serveru a prohledávání do šířky (kapitola 8). Obě operace mají v obou strukturách složitost \(O(1)\); fronta se v poli realizuje jako kruhový buffer, kde se čelo i konec posouvají dokola.stack (LIFO), queue (FIFO), circular buffer
Výraz ([)]: vložíme ( a [. Přijde ), ale na vrcholu je [, která k ní nepatří: chyba na pozici 3, i když počty závorek souhlasí. Výraz (a[b]{c}) projde: zásobník se zaplní na (, [, pak se [ odebere, přidá se {, odebere se } a nakonec ). Pouhé počítání závorek nestačí; je potřeba zásobník, protože poslední otevřená závorka se musí zavřít první.
7.4Stromy
Strom je hierarchická struktura: má kořen, každý uzel kromě kořene má právě jednoho rodiče a uzly bez potomků jsou listy. Hloubka uzlu je počet hran od kořene, výška stromu je největší hloubka. Stromy jsou složky na disku, struktura webové stránky (DOM), rozbor věty i rodokmen. Binární strom má u každého uzlu nejvýš dva potomky: levého a pravého.tree, root, leaf, depth, height, binary tree
Binární vyhledávací strom (BVS) splňuje invariant: všechny hodnoty v levém podstromu uzlu jsou menší než hodnota uzlu, všechny v pravém větší. Hledání, vkládání i mazání sledují jedinou cestu od kořene, stojí tedy \(O(h)\), kde \(h\) je výška. Ta je mezi \(\lceil\log_2(n+1)\rceil - 1\) (vyvážený strom; pro milion uzlů 19) a \(n - 1\) (strom zdegenerovaný v řetěz, například při vkládání seřazených hodnot). Při vkládání v náhodném pořadí je průměrná hloubka uzlu asi \(2\ln n \approx 1{,}39\log_2 n\).binary search tree (BST)
Vyvážené stromy po každém vložení nebo smazání strom lokálně přestaví (rotace), aby výška zůstala \(O(\log n)\). Nejstarší jsou AVL stromy (Adelson-Velskij a Landis, 1962), v knihovnách jsou běžné červeno-černé stromy. Databáze používají B-stromy s mnoha potomky v uzlu (kapitola 10).balanced tree, AVL tree, red-black tree
7.5Halda a prioritní fronta
Prioritní fronta vrací vždy prvek s nejvyšší prioritou (nejmenším klíčem): pohotovost ošetřuje nejvážnější případy, plánovač procesů nejdůležitější úlohy, Dijkstrův algoritmus nejbližší vrchol. Implementuje se binární haldou: téměř úplným binárním stromem, ve kterém je každý rodič menší nebo roven svým potomkům. Minimum je v kořeni; vložení i odebrání minima opraví haldu výměnami po jedné cestě, \(O(\log n)\). Halda se ukládá do pole bez ukazatelů: potomci prvku na indexu \(i\) jsou na indexech \(2i+1\) a \(2i+2\).priority queue, binary heap
7.6Hašovací tabulka
Hašovací tabulka ukládá dvojice klíč–hodnota do pole \(m\) přihrádek. Hašovací funkce \(h\) spočítá z klíče číslo přihrádky; dobrá funkce rozhází klíče rovnoměrně. Když dva klíče padnou do stejné přihrádky, nastane kolize. Řeší se řetězením (přihrádka drží seznam) nebo otevřeným adresováním (hledá se jiná volná přihrádka). Poměr \(\alpha = n/m\) se nazývá faktor naplnění. Při rovnoměrném hašování je průměrná délka řetězce \(\alpha\) a hledání trvá v průměru \(O(1 + \alpha)\). Když \(\alpha\) překročí mez (typicky kolem 0,75), tabulka se zvětší a klíče se přehašují.hash table, hash function, collision, chaining, load factor
Hašovací funkce „součet kódů znaků mod 7“: pes = 112 + 101 + 115 = 328, 328 mod 7 = 6. Kočka dá 691 mod 7 = 5, myš 583 mod 7 = 2, kůň 802 mod 7 = 4, koza 437 mod 7 = 3, ovce 429 mod 7 = 2. Myš a ovce kolidují v přihrádce 2. Součet je mimochodem špatná funkce: všechny přesmyčky (kos, sok) mají stejný haš.
Narozeninový paradox
Kolize přicházejí dřív, než by se zdálo. Pravděpodobnost, že mezi \(k\) lidmi mají aspoň dva narozeniny ve stejný den (365 dní, rovnoměrně), je
Pro 23 lidí vychází 50,7 %, pro 50 lidí 97,0 %, pro 70 lidí 99,9 %. Obecně se první kolize v tabulce s \(m\) přihrádkami čeká už kolem \(\sqrt{m}\) klíčů. Stejná úvaha určuje, jak dlouhý musí být kryptografický haš (kapitola 9).birthday paradox
7.7Grafy
Graf \(G = (V, E)\) je množina vrcholů \(V\) a hran \(E\) mezi nimi. Hrany mohou být orientované (jednosměrky, odkazy mezi stránkami) nebo neorientované (přátelství), a ohodnocené (délka silnice). Stromy jsou zvláštní případ grafu: souvislý graf bez cyklů. Ukládá se dvojím způsobem:graph, vertex, edge, adjacency matrix, adjacency list
Silniční síť s milionem křižovatek, každá má v průměru 10 sousedů. Matice sousednosti by měla \(10^{12}\) políček, i po jednom bitu 125 GB. Seznamy sousedů mají \(10^{7}\) položek, při 4 bajtech na položku asi 40 MB. Skutečné grafy (silnice, sociální sítě, web) jsou skoro vždy řídké.
| Struktura | přístup / hledání | vložení | smazání | poznámka |
|---|---|---|---|---|
| pole (nesetříděné) | \(O(1)\) index, \(O(n)\) hodnota | \(O(1)\)* na konec | \(O(n)\) | * amortizovaně |
| setříděné pole | \(O(\log n)\) | \(O(n)\) | \(O(n)\) | binární vyhledávání |
| spojový seznam | \(O(n)\) | \(O(1)\) | \(O(1)\) | známe-li místo |
| zásobník, fronta | jen vrchol / čelo | \(O(1)\) | \(O(1)\) | |
| vyvážený BVS | \(O(\log n)\) | \(O(\log n)\) | \(O(\log n)\) | udržuje pořadí |
| binární halda | \(O(1)\) minimum | \(O(\log n)\) | \(O(\log n)\) minimum | prioritní fronta |
| hašovací tabulka | \(O(1)\) | \(O(1)\) | \(O(1)\) | průměrně; nejhůř \(O(n)\), bez pořadí |
7.8Procvičení
- Pole má rychlý přístup podle indexu, spojový seznam rychlé vkládání; žádná struktura není nejlepší na všechno.
- Zásobník (LIFO) a fronta (FIFO) jsou jednoduché a všudypřítomné.
- Binární vyhledávací strom hledá za \(O(\text{výška})\); bez vyvažování může zdegenerovat na seznam.
- Hašovací tabulka hledá v průměru za konstantní čas, kolize jsou ale nevyhnutelné a přicházejí brzy.
- Grafy se ukládají maticí nebo seznamy sousedů; řídké grafy patří do seznamů.
Grafové algoritmystřední škola
Mapa, bludiště, síť počítačů, rozvodná síť i vztahy mezi lidmi jsou grafy. Na grafech stojí navigace, směrování paketů na internetu i plánování elektrických vedení. Čtyři základní algoritmy této kapitoly zvládnou většinu z toho.
Když hodíte kámen do rybníka, vlna dorazí nejdřív k nejbližším stéblům, pak k vzdálenějším. Prohledávání do šířky dělá totéž: první dosažení každého místa je zároveň nejkratší cestou. Navigace v telefonu přidává jen to, že silnice mají různou délku a rychlost – a to už je Dijkstrův algoritmus.
+Teorie: prohledávání do šířky a do hloubky, Dijkstra, A*, minimální kostra
8.1Cesty a souvislost
Cesta v grafu je posloupnost vrcholů spojených hranami, cyklus je cesta, která se vrací do výchozího vrcholu. Graf je souvislý, když mezi každými dvěma vrcholy vede cesta. Stupeň vrcholu je počet hran, které z něj vycházejí; součet stupňů všech vrcholů je \(2m\), protože každá hrana se počítá u obou konců. Teorie grafů začala Eulerovou úvahou o sedmi mostech v Královci (1736): projít každý most právě jednou nejde, protože všechny čtyři části města měly lichý počet mostů, a takový tah existuje, jen když lichý stupeň mají nejvýš dva vrcholy.path, cycle, connected graph, degree
8.2Prohledávání do šířky (BFS)
BFS začne ve výchozím vrcholu a navštěvuje vrcholy po vrstvách: nejdřív všechny ve vzdálenosti 1, pak 2 a tak dál. Pomocí fronty: z čela vezmeme vrchol, jeho dosud nenavštívené sousedy označíme a zařadíme na konec. Protože vrstvy přicházejí v pořadí vzdálenosti, první návštěva každého vrcholu proběhne po nejkratší cestě (v počtu hran). Každý vrchol i hrana se zpracují jednou, složitost je \(O(n + m)\).breadth-first search (BFS)
BFS(G, s): vzd[s] ← 0; fronta ← [s] dokud fronta není prázdná: u ← odeber z čela fronty pro každého souseda v vrcholu u: když v ještě nemá vzdálenost: vzd[v] ← vzd[u] + 1; před[v] ← u vlož v na konec fronty
8.3Prohledávání do hloubky (DFS)
DFS jde co nejdál jedním směrem a teprve ve slepé uličce se vrací k poslední odbočce. Používá zásobník, nejčastěji skrytě v podobě rekurze. Najde nějakou cestu, ne nutně nejkratší. Hodí se ale na mnoho jiných úloh: zjistit, zda je graf souvislý a zda obsahuje cyklus, najít komponenty souvislosti, generovat bludiště nebo topologicky uspořádat úkoly, které na sobě závisejí (co se musí udělat dřív). Složitost je také \(O(n + m)\).depth-first search (DFS), topological sort
BFS = fronta = vlna = nejkratší cesta v počtu kroků. DFS = zásobník = průzkumník s klubkem nití, který se vrací jen ze slepých uliček. Kód obou algoritmů se liší jedinou datovou strukturou.
8.4Dijkstrův algoritmus
Když mají hrany různou délku (nezápornou), nejkratší cestu najde algoritmus, který Edsger Dijkstra publikoval v roce 1959. Udržuje odhad vzdálenosti \(d(v)\) každého vrcholu; na začátku \(d(s) = 0\) a ostatní \(\infty\). Opakovaně vybere nezpracovaný vrchol s nejmenším odhadem, prohlásí ho za hotový a relaxuje jeho hrany: když \(d(u) + w(u, v) \lt d(v)\), sníží \(d(v)\). Výběr nejbližšího vrcholu zajišťuje prioritní fronta (halda, oddíl 7.5); složitost je pak \(O((n + m)\log n)\).Dijkstra's algorithm, relaxation
| Krok | hotový vrchol | A | B | C | D | T |
|---|---|---|---|---|---|---|
| 1 | S (0) | 4 | 2 | ∞ | ∞ | ∞ |
| 2 | B (2) | 3 | – | 10 | 12 | ∞ |
| 3 | A (3) | – | – | 8 | 12 | ∞ |
| 4 | C (8) | – | – | – | 10 | 14 |
| 5 | D (10) | – | – | – | – | 12 |
| 6 | T (12) | – | – | – | – | – |
Proč je to správně: když vybereme vrchol \(u\) s nejmenším odhadem, žádná jiná cesta do \(u\) nemůže být kratší, protože by musela vést přes nějaký jiný nezpracovaný vrchol s odhadem aspoň \(d(u)\) a hrany nemají zápornou délku.
Se zápornými hranami Dijkstrův algoritmus selhává: „hotový“ vrchol by se dal později zlevnit. Pro záporné hrany slouží Bellmanův–Fordův algoritmus se složitostí \(O(nm)\), který navíc odhalí záporný cyklus (cestu, která by šla zkracovat donekonečna).
8.5A*: Dijkstra s kompasem
Algoritmus A* (Hart, Nilsson, Raphael, 1968) vybírá vrchol podle součtu \(f(v) = g(v) + h(v)\), kde \(g\) je známá cena cesty ze startu a \(h\) heuristika, odhad zbývající ceny do cíle. Je-li heuristika přípustná (nikdy nepřecení skutečnou cenu), najde A* nejkratší cestu a obvykle prozkoumá mnohem méně vrcholů než Dijkstra, protože se „táhne“ k cíli. Na mřížce se používá manhattanská vzdálenost, na mapě vzdušná čára. Při \(h = 0\) je A* totéž co Dijkstra.A* search, admissible heuristic
Navigační aplikace pracují s grafy o desítkách milionů vrcholů. Čistý Dijkstra by na dotaz přes celý kontinent byl pomalý, proto se graf předzpracuje: spočítají se zkratky mezi důležitými křižovatkami a hledá se z obou konců. Směrovače na internetu počítají cesty Dijkstrovým algoritmem v protokolu OSPF.
8.6Minimální kostra
Kostra souvislého grafu je podmnožina hran, která propojí všechny vrcholy a neobsahuje cyklus; má vždy \(n - 1\) hran. Minimální kostra má nejmenší součet ohodnocení. Úlohu poprvé formuloval a vyřešil brněnský matematik Otakar Borůvka (1926) při návrhu elektrické sítě na Moravě; Vojtěch Jarník (1930) v dopise Borůvkovi popsal jiný postup, který později znovu objevil Prim (1957). Kruskal (1956) přidal třetí. Všechny jsou hladové a správné díky jedné vlastnosti:minimum spanning tree (MST), Borůvka's, Jarník's (Prim's), Kruskal's algorithm
- Kruskal: hrany seřadí od nejlehčí a postupně přidává každou, která nevytvoří cyklus. Cykly hlídá struktura union-find. Složitost \(O(m\log m)\), hlavně řazení.
- Jarník (Prim): strom roste z jednoho vrcholu; vždy přidá nejlehčí hranu, která vede ze stromu ven. S haldou \(O(m\log n)\).
- Borůvka: každá komponenta najednou přidá svou nejlehčí odchozí hranu; počet komponent se v každém kole aspoň způlí, kol je nejvýš \(\log_2 n\). Dobře se paralelizuje.
Hrany: A–B 1, B–C 2, A–C 3, C–D 4, B–D 5. Přidáme A–B (1), B–C (2); A–C (3) by uzavřela cyklus A–B–C, přeskočíme; přidáme C–D (4). Máme \(n - 1 = 3\) hrany, kostra stojí 7. Hrana B–D (5) už se nezkoumá.
8.7Procvičení
- BFS (fronta) najde nejkratší cesty v počtu hran, DFS (zásobník) prozkoumá graf do hloubky; obě za \(O(n + m)\).
- Dijkstra najde nejkratší cesty pro nezáporné délky hran; A* k tomu přidá odhad zbývající vzdálenosti.
- Minimální kostru najdou hladové algoritmy Borůvky, Jarníka a Kruskala; dva z nich jsou česká stopa v dějinách informatiky.
Kryptografiestřední škola
Kryptografie chrání zprávy před zvědavci, padělateli a podvodníky. Dva tisíce let to byla hra důvtipu, kterou šifranti většinou prohrávali. Dnešní šifry stojí na matematických úlohách, které umíme jedním směrem spočítat snadno a opačným směrem prakticky vůbec – a na zásadě, že tajný má být jen klíč.
Představte si visací zámek, který zaklapne každý, ale otevře jen majitel klíče. Rozdáte otevřené zámky celému světu; kdo vám chce poslat tajnou zprávu, zamkne ji do krabičky vaším zámkem. Nikdo jiný ji neotevře, ani odesílatel. Tak funguje šifrování veřejným klíčem, bez kterého by nešlo bezpečně nakupovat ani se přihlásit k bance.
+Teorie: klasické šifry, AES, hašovací funkce, Diffie–Hellman, RSA, podpis a certifikáty
9.1Co kryptografie chrání
Kryptografie zajišťuje čtyři vlastnosti: důvěrnost (zprávu přečte jen oprávněný), integritu (změna zprávy se pozná), autenticitu (víme, kdo zprávu poslal) a nepopiratelnost (odesílatel nemůže zapřít, že zprávu podepsal). Otevřený text se pomocí klíče převádí na šifrový text. Auguste Kerckhoffs v roce 1883 formuloval zásadu, která platí dodnes: systém má zůstat bezpečný, i když nepřítel zná vše kromě klíče. Utajený algoritmus není ochrana, jen odklad.confidentiality, integrity, authenticity, non-repudiation, Kerckhoffs's principle
Kapitola vykládá principy a obranu. Vlastní šifrovací algoritmy pro skutečné použití nepište: i drobná chyba v implementaci (časování, generátor náhodných čísel, opakovaný klíč) bývá fatální. Používejte ověřené knihovny a protokoly.
9.2Klasické šifry a jejich pád
Caesarova šifra posune každé písmeno o \(k\) míst: \(c = (m + k) \bmod 26\). Klíčů je jen 25, takže se dá vyzkoušet všechny. Obecná záměna (každé písmeno nahradí jiné podle tabulky) má \(26! \approx 4{,}03\cdot10^{26}\) klíčů, přesto padne frekvenční analýzou, kterou v 9. století popsal arabský učenec al-Kindí: v každém jazyce jsou některá písmena častější (v textu tohoto průvodce E 9,7 %, A 9,1 %, O 8,7 %), a záměna písmen rozložení četností nezmění, jen ho přejmenuje.Caesar cipher, substitution cipher, frequency analysis
Vigenèrova šifra (16. století) střídá několik posunů podle klíčového slova a jednoduchou frekvenční analýzu odolá; v 19. století ji prolomil Kasiski hledáním opakování. Šifrovací stroj Enigma z druhé světové války měl astronomický počet nastavení, přesto ho prolomili polští matematici v čele s Marianem Rejewskim (1932) a pak tým v Bletchley Parku včetně Alana Turinga – díky chybám v provozu a matematice permutací.
Jedinou dokazatelně nerozluštitelnou šifrou je jednorázová tabulka (one-time pad): klíč je stejně dlouhý jako zpráva, zcela náhodný a použije se jen jednou; šifruje se operací XOR. Shannon (1949) dokázal, že šifrový text pak o zprávě neprozradí nic. Nevýhoda je zřejmá: předat tak dlouhý klíč bezpečně je stejně těžké jako předat samotnou zprávu.one-time pad, perfect secrecy
9.3Symetrické šifry: AES
V symetrické kryptografii mají odesílatel i příjemce stejný tajný klíč. Dnešním standardem je AES (norma FIPS 197 z roku 2001, algoritmus Rijndael belgických autorů Daemena a Rijmena). Šifruje bloky po 128 bitech klíčem o délce 128, 192 nebo 256 bitů; v mnoha kolech střídá záměnu bajtů, přeskupení a míchání s klíčem. AES je rychlý (procesory na něj mají instrukce) a šifruje disky, Wi-Fi i obsah spojení TLS.symmetric encryption, AES, block cipher
Klíč o 128 bitech má \(2^{128} \approx 3{,}4\cdot10^{38}\) možností. Kdyby útočník zkoušel bilion (\(10^{12}\)) klíčů za sekundu, prošel by celý prostor za \(1{,}1\cdot10^{19}\) let, průměrně za polovinu. Pro srovnání: starší šifra DES s 56bitovým klíčem padne stejnou rychlostí za \(2^{56}/10^{12} = 72\,058\) s, tedy za 20 hodin. Délka klíče rozhoduje exponenciálně.
Blokovou šifru je třeba použít ve vhodném režimu. Nejjednodušší režim, šifrovat každý blok zvlášť (ECB), prozradí opakující se vzory. Dnes se používá autentizované šifrování (například AES-GCM), které současně zajistí důvěrnost i integritu.
9.4Hašovací funkce
Kryptografická hašovací funkce převede libovolně dlouhá data na otisk pevné délky (SHA-256: 256 bitů). Musí být jednosměrná (z otisku nejde najít vstup), odolná vůči kolizím (nejde najít dva vstupy se stejným otiskem) a mít lavinový efekt: změna jediného bitu vstupu změní zhruba polovinu bitů otisku.cryptographic hash function, preimage resistance, collision resistance, avalanche effect
SHA-256("abc") = ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad (testovací vektor normy FIPS 180).SHA-256("abd") = a52d159f262b2c6ddb724a61840befc36eb30c88877a4030b65cbe86298449c9.
Vstupy se liší posledním písmenem, otisky ve 122 bitech z 256, tedy téměř přesně v polovině.
Kvůli narozeninovému paradoxu (oddíl 7.6) stačí na nalezení kolize u \(n\)-bitového haše zhruba \(2^{n/2}\) pokusů; proto se používají haše aspoň 256bitové. Starší funkce MD5 a SHA-1 jsou prolomené: pro SHA-1 byla v roce 2017 veřejně předvedena kolize dvou různých dokumentů PDF. Platnými standardy jsou SHA-2 (FIPS 180-4) a SHA-3 (FIPS 202).
Jak bezpečně ukládat hesla
Služba nemá znát vaše heslo; ukládá jen jeho otisk a při přihlášení porovná otisk zadaného hesla. Ke každému heslu přidá náhodnou sůl, aby stejná hesla měla různé otisky, a použije záměrně pomalou funkci (Argon2 podle RFC 9106, bcrypt, PBKDF2), která i po úniku databáze zpomalí hádání na tisíce pokusů za sekundu místo miliard. To je rozdíl, se kterým počítala laboratoř v kapitole 3.salt, password hashing, key stretching
9.5Asymetrická kryptografie
Symetrická šifra má jeden zásadní problém: jak si klíč předat, když zatím nemáme bezpečný kanál? Řešení publikovali Whitfield Diffie a Martin Hellman v roce 1976: dvě strany se mohou na tajném čísle dohodnout veřejně, protože některé matematické operace jdou snadno jedním směrem a prakticky ne zpět. Umocnit číslo modulo prvočíslo je snadné; z výsledku zjistit exponent (diskrétní logaritmus) pro velká čísla neumíme.public-key cryptography, Diffie–Hellman key exchange, discrete logarithm
Veřejně dohodnuto: prvočíslo \(p = 23\), základ \(g = 5\). Alice si tajně zvolí \(a = 6\) a pošle \(A = 5^{6} \bmod 23 = 8\). Bob zvolí \(b = 15\) a pošle \(B = 5^{15} \bmod 23 = 19\). Alice spočítá \(19^{6} \bmod 23 = 2\), Bob \(8^{15} \bmod 23 = 2\). Oba mají společné tajemství 2, přestože po síti šla jen čísla 23, 5, 8 a 19.
RSA
Rivest, Shamir a Adleman popsali v roce 1977 (publikováno 1978) systém, ve kterém má každý pár klíčů. Bezpečnost stojí na tom, že vynásobit dvě velká prvočísla je snadné, ale rozložit jejich součin zpět na činitele neumíme.RSA, integer factorization
- Zvolíme dvě různá prvočísla \(p, q\) a spočítáme \(n = pq\) a \(\varphi(n) = (p-1)(q-1)\).
- Zvolíme \(e\) nesoudělné s \(\varphi(n)\) a najdeme \(d\) tak, aby \(e\cdot d \equiv 1 \pmod{\varphi(n)}\) (rozšířeným Euklidovým algoritmem, kapitola 2).
- Veřejný klíč je \((n, e)\), soukromý \(d\). Šifrování \(c = m^{e} \bmod n\), dešifrování \(m = c^{d} \bmod n\).
Poslední krok plyne z Eulerovy věty \(m^{\varphi(n)} \equiv 1 \pmod n\) pro \(m\) nesoudělné s \(n\) (platí i pro ostatní \(m \lt n\), jak se ověří přes čínskou větu o zbytcích). Kdo zná \(p\) a \(q\), spočítá \(\varphi(n)\) a z \(e\) snadno \(d\). Kdo zná jen \(n\), musí \(n\) nejdřív rozložit.
\(n = 3\,233\), \(\varphi(n) = 60\cdot52 = 3\,120\). Zvolíme \(e = 17\) (nesoudělné s 3 120). Inverze: \(d = 2\,753\), protože \(17\cdot2\,753 = 46\,801 = 15\cdot3\,120 + 1\). Zpráva \(m = 65\): \(c = 65^{17} \bmod 3\,233 = 2\,790\). Dešifrování: \(2\,790^{2\,753} \bmod 3\,233 = 65\). Mocniny se počítají opakovaným umocňováním na druhou, takže i exponent s 600 číslicemi stojí jen pár tisíc násobení.
9.6Digitální podpis a certifikáty
Digitální podpis obrací role klíčů: podepisuje se soukromým klíčem, ověřuje veřejným. Podepisuje se otisk dokumentu: \(s = h(M)^{d} \bmod n\). Ověřovatel spočítá \(s^{e} \bmod n\) a porovná s otiskem \(h(M)\), který si sám vypočte z dokumentu. Shoda dokazuje, že dokument podepsal držitel soukromého klíče (autenticita, nepopiratelnost) a že se od podpisu nezměnil (integrita).digital signature
Zbývá otázka, komu veřejný klíč patří. Odpovídá na ni certifikát: dokument „tento veřejný klíč patří doméně skola.example“ podepsaný certifikační autoritou, jejíž veřejný klíč má prohlížeč předinstalovaný. Řetěz podpisů od kořenové autority k serveru tvoří infrastrukturu veřejných klíčů (PKI). Na stejném principu stojí zaručený elektronický podpis, který v EU upravuje nařízení eIDAS (č. 910/2014).certificate, certificate authority, public key infrastructure (PKI)
9.7Kvantové počítače a postkvantová kryptografie
Peter Shor (1994) ukázal, že dostatečně velký kvantový počítač by rozložil čísla na prvočinitele i spočítal diskrétní logaritmus v polynomiálním čase. RSA i Diffie–Hellman (včetně variant na eliptických křivkách) by pak padly. Symetrické šifry ohrožuje Groverův algoritmus jen tak, že efektivně půlí délku klíče; AES-256 zůstává bezpečný. Takový kvantový počítač zatím neexistuje, ale data zachycená dnes by mohla být rozšifrována později. Americký úřad NIST proto v srpnu 2024 vydal první normy postkvantové kryptografie (FIPS 203, 204 a 205), založené na úlohách, pro které kvantový algoritmus neznáme, například na mřížkách.Shor's algorithm, post-quantum cryptography
9.8Procvičení
- Tajný má být jen klíč (Kerckhoffs). Klasické šifry padly na frekvenční analýze, ne na počtu klíčů.
- Symetrické šifry (AES) jsou rychlé, ale klíč je třeba předat; asymetrické (RSA, Diffie–Hellman) řeší předání klíče matematikou jednosměrných funkcí.
- Haš je otisk dat: jednosměrný, odolný vůči kolizím. Hesla se ukládají jen jako solené pomalé otisky.
- Podpis = haš podepsaný soukromým klíčem; certifikát svazuje veřejný klíč se jménem.
Databáze a datavysoká škola
Za rozvrhem, e-shopem, bankovním účtem i elektronickou žákovskou knížkou stojí databáze. Relační model z roku 1970 do ní přinesl matematiku: data jsou tabulky, dotaz je výraz nad nimi a databázový systém sám vymyslí, jak ho spočítat co nejrychleji.
Školní kartotéka: v jedné krabici karty žáků, v druhé předměty, ve třetí známky, kde je jen číslo žáka, číslo předmětu a známka. Žádný údaj není zapsaný dvakrát, a přesto z krabic poskládáte cokoli: „průměr z matematiky ve 3.A“ nebo „kdo nemá žádnou známku z fyziky“. SQL je jazyk, kterým o takovou sestavu požádáte.
studenti(id, jmeno, trida, rok), predmety(id, nazev) a znamky(student_id, predmet_id, znamka). Napište dotaz SELECT nebo vyberte ukázku. Pod laboratoří jsou tři úkoly; za jejich splnění jsou body.+Teorie: relační model, relační algebra, SQL, NULL, normalizace, indexy a transakce
10.1Proč databáze
Databázový systém (DBMS) spravuje data trvale, umožní k nim přístup mnoha uživatelům najednou, hlídá pravidla (každá známka patří existujícímu žákovi) a odpovídá na dotazy. Aplikace neřeší, jak jsou data uložena na disku; to je datová nezávislost. Změny se provádějí v transakcích s vlastnostmi ACID (Härder a Reuter, 1983): atomičnost (provede se celá, nebo vůbec), konzistence (zachová pravidla), izolovanost (souběžné transakce se navzájem neruší) a trvanlivost (potvrzená změna přežije i výpadek proudu).database management system, transaction, ACID
Převod 1 000 Kč z účtu A na účet B jsou dvě změny: A − 1 000 a B + 1 000. Kdyby systém po první změně spadl, peníze by zmizely. Transakce zaručí, že po obnovení se buď provedou obě, nebo žádná (atomičnost), a že souběžný převod ze stejného účtu neuvidí rozpracovaný stav (izolovanost).
10.2Relační model
Edgar F. Codd (1970) navrhl ukládat data jako relace: tabulky, jejichž řádky (n-tice) jsou množinou a sloupce (atributy) mají doménu přípustných hodnot. Primární klíč jednoznačně určuje řádek (studenti.id). Cizí klíč odkazuje na primární klíč jiné tabulky (znamky.student_id → studenti.id); databáze hlídá, aby odkaz vedl na existující řádek (referenční integrita).relation, tuple, attribute, primary key, foreign key, referential integrity
10.3Relační algebra
Dotazy nad relacemi lze skládat z několika operací, jejichž výsledkem je opět relace. Selekce \(\sigma_{p}(R)\) vybere řádky splňující podmínku \(p\); projekce \(\pi_{A}(R)\) ponechá sloupce \(A\); kartézský součin \(R \times S\) spojí každý řádek \(R\) s každým řádkem \(S\); spojení \(R \bowtie_{p} S = \sigma_{p}(R \times S)\); dále sjednocení, rozdíl a přejmenování. SQL je nad touto algebrou uživatelsky přívětivý jazyk a databáze dotaz do algebry přeloží a přestaví do co nejlevnější podoby (optimalizace dotazu).relational algebra, selection, projection, join, query optimization
10.4SQL
SQL (norma ISO/IEC 9075, poslední verze SQL:2023) je deklarativní: popisuje, jaký výsledek chceme, ne jak ho spočítat. Má část pro definici dat (CREATE TABLE), pro změny dat (INSERT, UPDATE, DELETE) a dotaz SELECT. Klauzule dotazu se píší v jiném pořadí, než v jakém se logicky vyhodnocují:SQL, declarative language
WHERE nelze použít agregaci (skupiny ještě neexistují) a podmínka na skupiny patří do HAVING.SELECT p.nazev, AVG(z.znamka) AS prumer, COUNT(*) FROM predmety p JOIN znamky z ON p.id = z.predmet_id GROUP BY p.nazev ORDER BY prumer;
| nazev | prumer | COUNT(*) |
|---|---|---|
| Informatika | 1,67 | 6 |
| Dějepis | 2,00 | 3 |
| Matematika | 2,29 | 7 |
| Fyzika | 2,50 | 4 |
Spojení a NULL
Vnitřní spojení (JOIN) vrátí jen dvojice řádků, které splní podmínku ON. Levé vnější spojení (LEFT JOIN) vrátí navíc každý řádek levé tabulky, který žádný protějšek nemá, a chybějící hodnoty doplní hodnotou NULL („neznámá / chybí“). NULL se chová zvláštně: jakékoli porovnání s ní dá výsledek neznámo, ne pravda ani nepravda (tříhodnotová logika). Proto WHERE x = NULL nevrátí nic a správně se píše WHERE x IS NULL.inner join, left outer join, NULL, three-valued logic
SELECT s.jmeno FROM studenti s LEFT JOIN znamky z ON s.id = z.student_id AND z.predmet_id = 3 WHERE z.znamka IS NULL vrátí Báru, Danu, Filipa a Gitu. Vnitřní spojení by tyto žáky vůbec neukázalo.
COUNT(*) počítá řádky, COUNT(sloupec) jen řádky, kde sloupec není NULL. Po LEFT JOIN je rozdíl zásadní: žák bez známky má jeden řádek s NULL, takže COUNT(*) dá 1, ale COUNT(z.znamka) správně 0.
10.5Normalizace
Tabulka, která ukládá stejný fakt vícekrát, trpí anomáliemi. Představte si jedinou tabulku vysvedceni(jmeno, trida, tridni_ucitel, predmet, znamka): změna třídního učitele 3.A se musí provést v mnoha řádcích (aktualizační anomálie, stačí jeden přehlédnout a data si odporují); smazáním poslední známky žáka zmizí i informace, do které třídy chodí (mazací anomálie); novou třídu nejde zapsat, dokud v ní není žák se známkou (vkládací anomálie).normalization, update/delete/insert anomaly
Příčinou je funkční závislost \(X \to Y\) („hodnota \(X\) určuje hodnotu \(Y\)“), jejíž levá strana není klíčem: trida → tridni_ucitel. Normální formy takové závislosti postupně odstraňují:
- 1NF: hodnoty jsou atomické (žádné seznamy známek v jedné buňce).
- 2NF: 1NF a žádný neklíčový atribut nezávisí jen na části složeného klíče.
- 3NF: 2NF a žádný neklíčový atribut nezávisí na jiném neklíčovém atributu (tranzitivně).
- BCNF: levá strana každé netriviální funkční závislosti je nadklíč.
Rozklad vysvedceni na studenti(id, jmeno, trida), tridy(trida, tridni_ucitel), predmety(id, nazev) a znamky(student_id, predmet_id, znamka) je v BCNF: každý fakt je uložen jednou a původní tabulku vrátí spojení. V analytických databázích se naopak někdy záměrně denormalizuje, aby čtení nemuselo spojovat tabulky.
10.6Indexy
Bez indexu musí databáze najít řádky s jmeno = 'Dana' průchodem celé tabulky. Index je pomocná struktura, nejčastěji B-strom (Bayer a McCreight, 1972): vyvážený strom, jehož uzel zabírá celou stránku disku a má stovky potomků. Při větvení 200 má strom pro \(10^{8}\) řádků hloubku \(\lceil\log_{200}10^{8}\rceil = 4\), binární strom by měl 27 úrovní. Index zrychlí hledání, spojování a řazení podle indexovaného sloupce, ale zpomalí zápisy (každý INSERT a UPDATE musí upravit i index) a zabere místo.index, B-tree
jmeno (zjednodušeně, větvení 3). Klíče v uzlu rozdělují rozsah hodnot; hledání čte jeden uzel na každé úrovni. Skutečné uzly mají stovky klíčů, takže i miliarda řádků vystačí se čtyřmi až pěti úrovněmi.10.7Bezpečnost a další modely dat
Hodnoty zadané uživatelem se nikdy nesmějí vkládat do textu dotazu skládáním řetězců: kdo by do formuláře napsal kus SQL, mohl by změnit význam dotazu (SQL injection, jedna z nejčastějších zranitelností webů). Obranou jsou parametrizované dotazy, kde se dotaz a data posílají databázi odděleně, a oprávnění, která aplikaci dovolí jen to, co nutně potřebuje.SQL injection, parameterized query
# správně: hodnota jde odděleně jako parametr, nikdy ne vlepená do textu dotazu cur.execute("SELECT jmeno FROM studenti WHERE trida = ?", (trida,))
Pro data, která se do tabulek nehodí, vznikly databáze NoSQL: dokumentové (záznamy jako stromy JSON), klíč–hodnota (obří hašovací tabulky), grafové (vztahy jako hrany) a sloupcové pro analytiku. Distribuované databáze naráží na větu CAP (Brewer 2000, důkaz Gilbert a Lynch 2002): při výpadku spojení mezi servery musí systém volit mezi konzistencí a dostupností. Statistické zpracování velkých dat rozebírá průvodce Statistika a modely.NoSQL, CAP theorem
10.8Procvičení
SELECT jmeno, rok FROM studenti WHERE rok < 2009 ORDER BY rok, jmeno. Výsledek: Filip 2007, Bára 2008, Emil 2008, Hana 2008.SELECT s.jmeno, p.nazev FROM studenti s JOIN znamky z ON s.id = z.student_id JOIN predmety p ON p.id = z.predmet_id WHERE z.znamka = 4. Cyril z fyziky a Emil z matematiky.SELECT s.trida, AVG(z.znamka) FROM studenti s JOIN znamky z ON s.id = z.student_id GROUP BY s.trida. 3.A: 13/8 = 1,625; 3.B: 12/5 = 2,4; 4.A: 17/7 = 2,43.SELECT trida, AVG(rok) FROM studenti GROUP BY trida HAVING COUNT(*) >= 3. 3.A: (2009 + 2008 + 2009)/3 = 2 008,67; 4.A: (2008 + 2007 + 2008)/3 = 2 007,67. Třída 3.B má jen dva žáky a vypadne v HAVING.objednavky(cislo, zakaznik, adresa_zakaznika, zbozi, cena_zbozi, mnozstvi) s klíčem (cislo, zbozi). Jaké funkční závislosti porušují normální formy a jak ji rozložit?zakaznici(zakaznik, adresa), zbozi(zbozi, cena), objednavky(cislo, zakaznik), polozky(cislo, zbozi, mnozstvi). Pozor: kdyby se cena měnila v čase a objednávka měla držet cenu z doby nákupu, patří cena do položek.- Relační model: data jsou tabulky s klíči, dotaz je výraz relační algebry; SQL je deklarativní.
- Logické pořadí dotazu: FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY. NULL vyžaduje IS NULL.
- Normalizace ukládá každý fakt jednou a odstraňuje anomálie; spojení tabulky zase složí.
- Index (B-strom) mění hledání z průchodu milionů stránek na pár čtení, ale zpomaluje zápis.
- Transakce ACID chrání data při souběhu i výpadku; parametrizované dotazy chrání před SQL injection.
Vyčíslitelnost a složitostvysoká škola
Co vůbec znamená „spočítat“? Alan Turing v roce 1936 odpověděl strojem tak jednoduchým, že se dá nakreslit na papír, a hned dokázal, že některé otázky žádný stroj nikdy nezodpoví. O třicet let později přibyla jemnější otázka: které úlohy jsou sice řešitelné, ale ne v čase, kterého se dožijeme.
Kdyby existoval program, který o libovolném programu spolehlivě pozná, zda se někdy zastaví, mohli bychom napsat program, který se ho na sebe sama zeptá a udělá opak. Ten by se zastavil, právě když se nezastaví. Takový program tedy existovat nemůže – stejně jako holič, který holí právě ty, kdo se neholí sami.
+Teorie: Turingův stroj, Church–Turingova teze, problém zastavení, P a NP, redukce, NP-úplnost
11.1Turingův stroj
David Hilbert v roce 1928 položil otázku (Entscheidungsproblem), zda existuje mechanický postup, který o každém matematickém tvrzení rozhodne, zda je dokazatelné. Aby na ni šlo odpovědět, bylo třeba přesně definovat „mechanický postup“. Alan Turing (1936) navrhl abstraktní stroj, který napodobuje počtáře s tužkou: nekonečnou pásku rozdělenou na políčka, hlavu, která čte a píše po jednom políčku, a konečnou množinu stavů „mysli“.Turing machine, Entscheidungsproblem
Formálně (Sipser) je Turingův stroj sedmice \((Q, \Sigma, \Gamma, \delta, q_0, q_{\text{acc}}, q_{\text{rej}})\): konečná množina stavů \(Q\), vstupní abeceda \(\Sigma\), pásková abeceda \(\Gamma \supseteq \Sigma \cup \{\_\}\), přechodová funkce \(\delta: Q \times \Gamma \to Q \times \Gamma \times \{L, R\}\), počáteční stav a přijímající a zamítající stav. Stroj přijme vstup, když dojde do \(q_{\text{acc}}\), zamítne ho v \(q_{\text{rej}}\) – nebo může běžet donekonečna. Jazyk je rozhodnutelný, když ho rozpoznává stroj, který se na každém vstupu zastaví.decidable language, configuration
Vstup 111+11 (3 + 2). Stav \(q_0\): jdi doprava přes jedničky; na + napiš 1 a přejdi do \(q_1\). Stav \(q_1\): jdi doprava přes jedničky; na prázdném políčku couvni doleva do \(q_2\). Stav \(q_2\): poslední jedničku smaž a zastav. Na pásce zůstane 11111, tedy 5. Stroj udělá 8 kroků; obecně pro \(a + b\) jich udělá \(a + b + 3\).
11.2Church–Turingova teze
Ve stejném roce popsal Alonzo Church jiný model výpočtu, λ-kalkul, a brzy se ukázalo, že oba modely – i všechny později navržené (stroje RAM, rekurzivní funkce, běžné programovací jazyky) – spočítají přesně tytéž funkce. Church–Turingova teze tvrdí, že vše, co lze spočítat jakýmkoli mechanickým postupem, spočítá Turingův stroj. Je to teze, ne věta: „mechanický postup“ je intuitivní pojem. Jazyk nebo systém, který umí simulovat Turingův stroj, se nazývá Turingovsky úplný.Church–Turing thesis, Turing complete
Turing také sestrojil univerzální stroj, který na vstupu dostane popis jiného stroje a jeho vstup a odsimuluje ho. To je teoretický předobraz počítače s uloženým programem z kapitoly 3: jeden stroj, mnoho programů.universal Turing machine
11.3Problém zastavení
Problém zastavení: dostaneme program \(P\) a vstup \(x\); zastaví se \(P\) na \(x\)? Turing dokázal, že žádný algoritmus tuto otázku nerozhoduje pro všechny dvojice \((P, x)\).halting problem, undecidability
- Předpokládejme, že existuje program
H(P, x), který vždy skončí a vrátí ano, právě když \(P\) se na \(x\) zastaví. - Sestrojíme program
D(P): zavoláH(P, P); vyjde-li ano, zacyklí se; vyjde-li ne, skončí. - Co udělá
D(D)? Zastaví-li se, pakH(D, D)vrátilo ano aDse zacyklilo – spor. Nezastaví-li se, vrátiloHne aDskončilo – spor. - Předpoklad byl chybný: program
Hneexistuje.
Je to diagonální argument, stejný trik, kterým Cantor dokázal, že reálných čísel je víc než přirozených. Z problému zastavení plyne mnoho dalších nerozhodnutelných otázek. Riceova věta (1953) říká, že každá netriviální vlastnost chování programů je nerozhodnutelná: zda program někdy vypíše „ahoj“, zda počítá stejnou funkci jako jiný program, zda obsahuje nekonečný cyklus.diagonal argument, Rice's theorem
Nástroje, které hledají chyby v kódu nebo škodlivé programy, proto nemohou být dokonalé: buď některé problémy přehlédnou, nebo občas ohlásí falešný poplach, nebo se u některých programů nevysloví. Užitečné jsou přesto, protože skutečné programy bývají mnohem jednodušší než nejhorší případ. Hranici dobře ilustruje funkce „pilný bobr“ (busy beaver): nejdelší možný běh zastavujícího se stroje s \(n\) stavy. Roste rychleji než jakákoli vyčíslitelná funkce; pro \(n = 5\) ji v roce 2024 určila spolupráce bbchallenge na 47 176 870 kroků s formálním počítačově ověřeným důkazem.
11.4Třídy P a NP
Složitost (kapitola 6) třídí rozhodnutelné úlohy podle času. Uvažujeme rozhodovací úlohy s odpovědí ano/ne. Třída P obsahuje úlohy řešitelné deterministickým algoritmem v polynomiálním čase \(O(n^{k})\): řazení, nejkratší cesta, test prvočíselnosti (algoritmus AKS, 2002). Třída NP obsahuje úlohy, u kterých lze kladnou odpověď ověřit v polynomiálním čase, dostaneme-li vhodný certifikát: u sudoku vyplněnou mřížku, u obchodního cestujícího okruh kratší než zadaná mez. Každá úloha z P je v NP (certifikát ani nepotřebujeme), tedy \(\mathrm{P} \subseteq \mathrm{NP}\).decision problem, class P, class NP, certificate, verifier
Zda \(\mathrm{P} = \mathrm{NP}\), tedy zda je hledání řešení vždy jen polynomiálně těžší než jeho kontrola, je nejslavnější otevřená otázka informatiky. Clayův matematický institut ji v roce 2000 zařadil mezi sedm problémů tisíciletí s odměnou milion dolarů. Většina odborníků se domnívá, že \(\mathrm{P} \ne \mathrm{NP}\).
11.5Redukce a NP-úplnost
Úloha \(A\) se polynomiálně redukuje na úlohu \(B\) (\(A \le_p B\)), když každou instanci \(A\) umíme v polynomiálním čase přeložit na instanci \(B\) se stejnou odpovědí. Pak je \(B\) aspoň tak těžká jako \(A\): kdo umí rychle \(B\), umí rychle i \(A\). Úloha je NP-těžká, když se na ni redukuje každá úloha z NP, a NP-úplná, když je navíc sama v NP.polynomial-time reduction, NP-hard, NP-complete
Stephen Cook (1971) a nezávisle Leonid Levin (1973) dokázali, že NP-úplná je splnitelnost logických formulí (SAT): dá se proměnným přiřadit pravda/nepravda tak, aby formule platila? Richard Karp (1972) pak redukcemi ukázal NP-úplnost 21 dalších úloh, mezi nimi kliky, pokrytí vrcholů, Hamiltonovy kružnice a barvení grafu. Dnes jich známe tisíce. Kdyby jediná z nich měla polynomiální algoritmus, platilo by \(\mathrm{P} = \mathrm{NP}\).Cook–Levin theorem, SAT
Redukce se dělá ze známé těžké úlohy na novou, ne naopak. Kdo chce ukázat, že jeho úloha \(B\) je NP-těžká, musí na ni převést známou NP-úplnou úlohu \(A\). Převést \(B\) na SAT dokazuje jen to, že \(B\) je v NP, nikoli že je těžká.
11.6Co dělat s těžkými úlohami
- Malé instance řešit přesně. Prohledávání s ořezáváním (branch and bound) zvládne i stovky prvků, i když v nejhorším případě exponenciálně.
- Aproximace se zárukou. Pokrytí vrcholů jde v polynomiálním čase najít nejvýš dvakrát větší než optimum; pro obchodního cestujícího s trojúhelníkovou nerovností dává Christofidesův algoritmus (1976) okruh nejvýš o polovinu delší.
- Heuristiky bez záruky, ale prakticky dobré: hladové volby, lokální vylepšování, simulované žíhání.
- Speciální případy bývají snadné: barvení dvěma barvami je v P, třemi NP-úplné; SAT s klauzulemi o dvou proměnných je v P.
- Řešiče SAT zvládají průmyslové formule s miliony proměnných, protože skutečné instance mají strukturu, kterou nejhorší případ nemá.
Těžkost je někdy výhoda: kryptografie (kapitola 9) stojí na úlohách, které považujeme za těžké. Rozklad na prvočinitele ale není známý jako NP-úplný a kvantový počítač by ho zvládl (Shor); proto se pro postkvantové šifry hledají úlohy jiného typu.
| Měst \(n\) | okruhů | čas |
|---|---|---|
| 10 | 181 440 | 0,2 ms |
| 15 | 43 589 145 600 | 44 s |
| 20 | \(6{,}1\cdot10^{16}\) | 1,9 roku |
| 25 | \(3{,}1\cdot10^{23}\) | 9,8 milionu let |
11.7Procvičení
- Turingův stroj je přesná definice algoritmu; podle Church–Turingovy teze spočítá vše, co je vůbec spočitatelné.
- Problém zastavení je nerozhodnutelný; každá netriviální vlastnost chování programů také (Riceova věta).
- P: rychle vyřešit; NP: rychle ověřit. Zda P = NP, nikdo neví.
- NP-úplné úlohy jsou navzájem převoditelné redukcemi; v praxi se řeší přesně pro malá data, aproximací a heuristikami.
Umělá inteligence a softwarevysoká škola
Umělá inteligence není jedna technologie, ale sedmdesát let snahy přimět stroje k úlohám, které vyžadují úsudek: hrát hry, poznávat obrázky, psát text. Za každým takovým systémem stojí algoritmy z předchozích kapitol, data a lidé, kteří software navrhují, testují a nesou za něj odpovědnost.
Šachový program nepřemýšlí jako velmistr: prochází miliony pozic a počítá. Jazykový model nerozumí světu jako člověk: odhaduje, jaké slovo nejspíš následuje. Obojí může působit inteligentně a obojí může selhat způsobem, který by člověka nenapadl. Kdo ví, jak systém funguje uvnitř, ví také, kdy mu nevěřit.
+Teorie: prohledávání a hry, perceptron, jazykové modely, vývoj softwaru, testování a etika
12.1Co je umělá inteligence
Alan Turing (1950) navrhl místo otázky „umí stroj myslet?“ zkoušku: pozná tazatel v písemném rozhovoru, zda odpovídá člověk, nebo stroj? Obor dostal jméno na letní dílně v Dartmouthu (1956). Učebnice Russella a Norviga definuje umělou inteligenci jako studium agentů, kteří vnímají prostředí a jednají tak, aby co nejlépe splnili svůj cíl. Obor prošel vlnami: symbolické uvažování a prohledávání, expertní systémy s ručně psanými pravidly, strojové učení z dat a od 2010. let hluboké neuronové sítě. Otázky vědomí a porozumění strojů rozebírá průvodce Filozofie.artificial intelligence, Turing test, rational agent
12.2Prohledávání a hry
Mnoho úloh lze formulovat jako hledání cesty ve stavovém prostoru: stavy jsou vrcholy grafu, tahy hrany (kapitola 8). U her pro dva hráče se prohledává herní strom. Minimax: hráč MAX volí tah s nejvyšší hodnotou, protivník MIN s nejnižší, hodnoty se počítají od listů (výhra +1, remíza 0, prohra −1) nahoru.state space, game tree, minimax
Alfa-beta ořezávání přeskakuje větve, které výsledek nemohou ovlivnit; výsledek je stejný jako u úplného minimaxu. Při dobrém pořadí tahů zmenší počet prohledaných pozic zhruba na odmocninu (Knuth a Moore, 1975). Celý strom piškvorek 3 × 3 má 549 946 uzlů a 255 168 různých partií; s alfa-beta ořezáváním (tahy zkoumané v pořadí políček) stačí k vyhodnocení prázdné desky 18 297 uzlů. Výsledek: při bezchybné hře obou stran remíza.alpha-beta pruning
U šachů Shannon (1950) odhadl strom zhruba na \(10^{120}\) partií, takže úplné prohledání nepřichází v úvahu. Programy prohledávají do omezené hloubky a pozice hodnotí hodnoticí funkcí. V roce 1997 porazil šachový počítač mistra světa Garriho Kasparova; v roce 2016 porazil program pro hru go Lee Se-dola, tentokrát díky kombinaci prohledávání s neuronovými sítěmi naučenými na milionech partií.evaluation function
12.3Strojové učení stručně
Strojové učení hledá pravidla z dat místo z ručně psaného kódu. Při učení s učitelem má každý příklad správnou odpověď (obrázek a popisek), při učení bez učitele hledá model strukturu sám (shluky), při zpětnovazebním učení se agent učí z odměn. Úspěšnost se měří na testovacích datech, která model při učení neviděl; model, který si zapamatoval trénovací data a na nových selhává, je přeučený.machine learning, supervised, unsupervised, reinforcement learning, overfitting
Perceptron se učí jednoduchým pravidlem: když se splete, přičte k vahám \(\eta\,(y - \hat y)\,x\). Novikoff (1962) dokázal, že na lineárně oddělitelných datech pravidlo po konečném počtu chyb najde oddělující přímku. Minsky a Papert (1969) upozornili, že funkci XOR jediný perceptron nespočítá, protože body (0, 1), (1, 0) nejde oddělit od (0, 0), (1, 1) přímkou. Řešením jsou vícevrstvé sítě s nelineárními funkcemi, které se učí zpětným šířením chyby (Rumelhart, Hinton a Williams, 1986).perceptron, perceptron convergence theorem, backpropagation
Začneme s \(w = (0, 0)\), \(b = 0\), \(\eta = 1\) a procházíme body (0,0)→0, (0,1)→0, (1,0)→0, (1,1)→1. V první epoše se splete jen na (1,1) a váhy se změní na \(w = (1, 1)\), \(b = 1\). Pak chybuje i na nulových bodech a váhy se dolaďují; počty chyb v epochách jsou 1, 3, 3, 2, 1 a šestá epocha proběhne bez chyby s \(w = (2, 1)\), \(b = -2\). Kontrola: \(2\cdot1 + 1\cdot1 - 2 = 1 \gt 0\), ale \(2\cdot1 + 0 - 2 = 0\), takže (1, 0) dá 0.
12.4Velké jazykové modely v principu
Jazykový model přiřazuje pravděpodobnost pokračování textu. Text se rozdělí na tokeny (slova nebo jejich části) a model se učí odhadovat rozdělení pravděpodobnosti dalšího tokenu podle předchozích. Generuje se opakovaně: vybere se token (podle pravděpodobností a teploty), připojí se k textu a postup se opakuje. Dnešní velké jazykové modely používají architekturu transformer (Vaswani a kol., 2017), jejíž mechanismus pozornosti umí při odhadu vážit vztahy mezi vzdálenými částmi textu. Mají miliardy parametrů a učí se nejdřív na obrovském množství textu (předtrénování), pak se dolaďují na příkladech a podle hodnocení lidí.language model, token, transformer, attention, pretraining, fine-tuning
Model generuje pravděpodobný text, ne nutně pravdivý. Umí sebejistě uvést neexistující zdroj, číslo nebo citaci (tzv. halucinace), přebírá zkreslení z trénovacích dat a o událostech po ukončení trénování neví, pokud nemá přístup k aktuálním zdrojům. Výstupy u faktů, výpočtů a citací ověřujte v původních zdrojích a do konverzace nevkládejte osobní údaje, hesla ani důvěrné informace.
12.5Jak se dělá software
Software se nevytváří jen psaním kódu. Životní cyklus zahrnuje sběr požadavků (co má systém dělat), návrh (z jakých částí se skládá), implementaci, testování, nasazení a dlouhou údržbu. Starší vodopádový model procházel fázemi postupně jednou; dnes převládají agilní přístupy (manifest agilního vývoje, 2001), které dodávají funkční software v krátkých iteracích a průběžně ho upravují podle zpětné vazby.software engineering, requirements, agile
Správa verzí uchovává celou historii změn: každá uložená změna (commit) má autora, čas a popis, k jakékoli starší verzi se lze vrátit. Nejrozšířenější je svobodný systém Git (2005). Nová funkce se vyvíjí ve větvi, po kontrole kódu kolegou (code review) se sloučí do hlavní větve.version control, commit, branch, merge, code review
Testování má úrovně: jednotkové testy ověřují jednotlivé funkce (jako assert v kapitole 4), integrační jejich spolupráci, systémové celek a akceptační splnění požadavků zákazníka. Testy se spouštějí automaticky při každé změně (průběžná integrace). Dijkstra připomínal, že testy mohou dokázat přítomnost chyb, nikdy jejich nepřítomnost; kde jde o životy, doplňují se formálními důkazy správnosti.unit, integration, system, acceptance testing; continuous integration
Ozařovací přístroj Therac-25 v letech 1985–1987 několikrát podal pacientům mnohonásobnou dávku záření; příčinou byla mimo jiné chyba souběhu v řídicím programu a odstranění hardwarových pojistek, na které starší model spoléhal. Sonda Mars Climate Orbiter se v roce 1999 ztratila, protože jedna část softwaru počítala v anglických jednotkách a druhá v metrických. Ani jedna chyba nebyla složitá; obě prošly, protože chyběla kontrola na rozhraní.
12.6Etika a odpovědnost
Software rozhoduje o úvěrech, přijetí na školu, lékařské péči i o tom, co lidé vidí na sociálních sítích. Proto se od něj očekává:
- Ochrana soukromí: sbírat jen nezbytné údaje a chránit je; v EU to vyžaduje obecné nařízení o ochraně osobních údajů (GDPR, nařízení (EU) 2016/679).
- Férovost: model naučený na zkreslených datech zkreslení zopakuje (například horší rozpoznávání skupin, které byly v datech málo zastoupené). Je třeba to měřit a opravovat.
- Průhlednost a dohledatelnost: člověk má vědět, že jedná se strojem, a rozhodnutí má jít vysvětlit a napadnout.
- Odpovědnost a bezpečnost: za systém odpovídají lidé, kteří ho navrhli a nasadili; profesní zásady shrnuje například etický kodex ACM (2018).
Evropská unie upravuje umělou inteligenci nařízením (EU) 2024/1689 (AI Act), které třídí systémy podle rizika. Zákazy nepřijatelných praktik platí od 2. 2. 2025, pravidla pro modely pro obecné účely od 2. 8. 2025; povinnosti pro vysoce rizikové systémy byly změnou z roku 2026 odloženy na 2. 12. 2027, respektive 2. 8. 2028 (stav k 13. 10. 2026, podrobnosti v příloze C). Ekonomické dopady digitálních platforem rozebírá průvodce Ekonomie, filozofické otázky odpovědnosti průvodce Filozofie.GDPR, AI Act, algorithmic fairness, accountability
12.7Procvičení
prumer z kapitoly 4 projde všemi vašimi testy. Znamená to, že je správná?- Hry a plánování jsou prohledávání stavového prostoru; minimax s alfa-beta ořezáváním hraje bezchybně tam, kde lze strom prohledat.
- Perceptron se učí oddělit data přímkou; složitější vzory potřebují vícevrstvé sítě.
- Jazykové modely odhadují další token; jejich text je pravděpodobný, ne zaručeně pravdivý.
- Software vzniká v týmu: verzování, kontrola kódu a automatické testy jsou základ, odpovědnost za dopady nese člověk.
Slovníček
Složitosti a pseudokód
| Algoritmus | Složitost | Kapitola |
|---|---|---|
| Euklidův algoritmus NSD(a, b) | \(O(\log \min(a, b))\) dělení | 2 |
| lineární hledání / binární vyhledávání | \(O(n)\) / \(O(\log n)\) | 5 |
| bublinkové řazení, řazení vkládáním | \(O(n^{2})\); vkládání na téměř seřazených datech \(O(n + \text{inverze})\) | 5 |
| řazení slučováním | \(\Theta(n\log n)\), paměť \(O(n)\) | 5 |
| rychlé řazení | průměrně \(O(n\log n)\), nejhůř \(O(n^{2})\) | 5 |
| dolní mez řazení porovnáváním | \(\Omega(n\log n)\) | 5 |
| BFS, DFS, topologické uspořádání | \(O(n + m)\) | 8 |
| Dijkstra (s haldou) / Bellman–Ford | \(O((n + m)\log n)\) / \(O(nm)\) | 8 |
| Kruskal / Jarník (Prim) / Borůvka | \(O(m\log m)\) / \(O(m\log n)\) / \(O(m\log n)\) | 8 |
| modulární umocňování \(a^{e} \bmod n\) | \(O(\log e)\) násobení | 9 |
| spojení tabulek vnořenými cykly / přes index | \(O(|R|\cdot|S|)\) / \(O(|R|\log |S|)\) | 10 |
| Turingův stroj na palindromy (1 páska) | \(\Theta(n^{2})\) | 11 |
| obchodní cestující hrubou silou / SAT hrubou silou | \(O(n!)\) / \(O(2^{n}\cdot\text{délka formule})\) | 11 |
| minimax / alfa-beta (strom s větvením \(b\), hloubka \(d\)) | \(O(b^{d})\) / nejlépe \(O(b^{d/2})\) | 12 |
Pseudokód: Dijkstrův algoritmus
Dijkstra(G, s): pro každý vrchol v: d[v] ← ∞; d[s] ← 0 Q ← prioritní fronta všech vrcholů podle d dokud Q není prázdná: u ← odeber z Q vrchol s nejmenším d pro každou hranu (u, v) s délkou w ≥ 0: když d[u] + w < d[v]: d[v] ← d[u] + w; před[v] ← u; sniž klíč v v Q
Pseudokód: Kruskalův algoritmus
Kruskal(G): seřaď hrany podle délky vzestupně; T ← ∅ pro každý vrchol v: vytvoř množinu {v} # union-find pro každou hranu (u, v): když najdi(u) ≠ najdi(v): # nevznikne cyklus T ← T ∪ {(u, v)}; sjednoť(u, v) vrať T
Pseudokód: rychlé modulární umocňování
mocnina(a, e, n): # spočítá a^e mod n r ← 1; a ← a mod n dokud e > 0: když e je liché: r ← r · a mod n a ← a · a mod n; e ← ⌊e / 2⌋ vrať r
Vzorce na jednom místě
Zdroje
Normy, protokoly a předpisy
- The Unicode Standard, Version 18.0.0 (Unicode Consortium, vydáno 16. 9. 2026): 172 808 kódovaných znaků; kódový prostor U+0000 až U+10FFFF (1 114 112 kódových bodů). Ověřeno 13. 10. 2026 na unicode.org.
- RFC 3629 UTF-8 (2003); RFC 2606 vyhrazená jména domén pro příklady (.example, .test; 1999).
- RFC 791 IPv4 (1981), RFC 8200 IPv6 (2017), RFC 9293 TCP (2022), RFC 768 UDP (1980), RFC 1034 a 1035 DNS (1987), RFC 9110 sémantika HTTP (2022), RFC 9000 QUIC (2021), RFC 9114 HTTP/3 (2022), RFC 8446 TLS 1.3 (2018), RFC 9106 Argon2 (2021). Čísla a roky uvedeny podle řady RFC; jednotlivě je ověřte na rfc-editor.org.
- NIST FIPS 197 (AES, 2001, aktualizace 2023), FIPS 180-4 (SHA-2, 2015), FIPS 202 (SHA-3, 2015), FIPS 203, 204 a 205 (postkvantová kryptografie, srpen 2024).
- NIST SP 800-63B-4 (2025), oddíl 3.1.1.2: heslo jako jediný faktor aspoň 15 znaků, s dalším faktorem aspoň 8; přijímat aspoň 64 znaků; nevynucovat pravidla skladby ani pravidelnou změnu; porovnávat se seznamem zakázaných hesel. Ověřeno 13. 10. 2026 na pages.nist.gov.
- IEEE 754-2019 (aritmetika v plovoucí řádové čárce), ISO/IEC 9075:2023 (SQL), ISO 5807 (symboly vývojových diagramů), IEC 80000-13 (dvojkové předpony KiB, MiB, GiB).
- Nařízení (EU) 2016/679 (GDPR) a nařízení (EU) č. 910/2014 (eIDAS, elektronická identifikace a služby vytvářející důvěru).
- Nařízení (EU) 2024/1689 (akt o umělé inteligenci): zákazy a povinnost gramotnosti v AI od 2. 2. 2025, pravidla pro modely pro obecné účely od 2. 8. 2025. Změnové nařízení (tzv. digitální omnibus k AI) vstoupilo v platnost 27. 7. 2026 a odložilo povinnosti pro vysoce rizikové systémy podle přílohy III na 2. 12. 2027 a podle přílohy I na 2. 8. 2028. Ověřeno 13. 10. 2026 na stránkách Evropské komise (digital-strategy.ec.europa.eu); znění se může dále měnit.
- Rámcové vzdělávací programy: revize RVP ZV (2021) zavedla vzdělávací oblast Informatika, povinně na 1. stupni od 1. 9. 2023 a na 2. stupni od 1. 9. 2024; revize RVP G (2021) s novou informatikou, na nižším stupni víceletých gymnázií nejpozději od 1. 9. 2025 (MŠMT, NPI ČR; Eurydice). Podrobnosti ověřte v aktuálním znění na edu.cz.
- Pilný bobr BB(5) = 47 176 870: oznámeno spoluprací bbchallenge 2. 7. 2024, formální důkaz v systému Coq (Rocq); článek arXiv:2509.12337 (2025). Ověřeno 13. 10. 2026.
Literatura
- Cormen, T. H.; Leiserson, C. E.; Rivest, R. L.; Stein, C. (2022): Introduction to Algorithms, 4. vyd. MIT Press.
- Sipser, M. (2012): Introduction to the Theory of Computation, 3. vyd. Cengage Learning.
- Knuth, D. E. (1968–2022): The Art of Computer Programming, sv. 1–4B. Addison-Wesley.
- Tanenbaum, A. S.; Feamster, N.; Wetherall, D. J. (2021): Computer Networks, 6. vyd. Pearson.
- Silberschatz, A.; Korth, H. F.; Sudarshan, S. (2019): Database System Concepts, 7. vyd. McGraw-Hill.
- Russell, S.; Norvig, P. (2020): Artificial Intelligence: A Modern Approach, 4. vyd. Pearson.
- Mareš, M.; Valla, T. (2017): Průvodce labyrintem algoritmů. Praha: CZ.NIC.
- Turing, A. M. (1936): On Computable Numbers, with an Application to the Entscheidungsproblem. Proceedings of the London Mathematical Society s2-42, 230–265.
- Turing, A. M. (1950): Computing Machinery and Intelligence. Mind 59(236), 433–460.
- Shannon, C. E. (1948): A Mathematical Theory of Communication. Bell System Technical Journal 27, 379–423 a 623–656.
- Dijkstra, E. W. (1959): A Note on Two Problems in Connexion with Graphs. Numerische Mathematik 1, 269–271.
- Borůvka, O. (1926): O jistém problému minimálním. Práce moravské přírodovědecké společnosti 3, 37–58. Jarník, V. (1930): O jistém problému minimálním. Tamtéž 6, 57–63.
- Hoare, C. A. R. (1962): Quicksort. The Computer Journal 5(1), 10–16.
- Böhm, C.; Jacopini, G. (1966): Flow Diagrams, Turing Machines and Languages with Only Two Formation Rules. Communications of the ACM 9(5), 366–371.
- Hart, P. E.; Nilsson, N. J.; Raphael, B. (1968): A Formal Basis for the Heuristic Determination of Minimum Cost Paths. IEEE Transactions on Systems Science and Cybernetics 4(2), 100–107.
- Codd, E. F. (1970): A Relational Model of Data for Large Shared Data Banks. Communications of the ACM 13(6), 377–387.
- Cook, S. A. (1971): The Complexity of Theorem-Proving Procedures. Proceedings of the 3rd Annual ACM Symposium on Theory of Computing, 151–158.
- Karp, R. M. (1972): Reducibility Among Combinatorial Problems. In: Miller, R. E.; Thatcher, J. W. (eds.): Complexity of Computer Computations. Plenum, 85–103.
- Bayer, R.; McCreight, E. (1972): Organization and Maintenance of Large Ordered Indexes. Acta Informatica 1, 173–189.
- Knuth, D. E.; Moore, R. W. (1975): An Analysis of Alpha-Beta Pruning. Artificial Intelligence 6(4), 293–326.
- Diffie, W.; Hellman, M. E. (1976): New Directions in Cryptography. IEEE Transactions on Information Theory 22(6), 644–654.
- Rivest, R. L.; Shamir, A.; Adleman, L. (1978): A Method for Obtaining Digital Signatures and Public-Key Cryptosystems. Communications of the ACM 21(2), 120–126.
- Kerckhoffs, A. (1883): La cryptographie militaire. Journal des sciences militaires 9, 5–38 a 161–191.
- Rosenblatt, F. (1958): The Perceptron: A Probabilistic Model for Information Storage and Organization in the Brain. Psychological Review 65(6), 386–408.
- Härder, T.; Reuter, A. (1983): Principles of Transaction-Oriented Database Recovery. ACM Computing Surveys 15(4), 287–317.
- Vaswani, A. a kol. (2017): Attention Is All You Need. Advances in Neural Information Processing Systems 30.
- Lions, J.-L. a kol. (1996): ARIANE 5 Flight 501 Failure. Report by the Inquiry Board. ESA a CNES.
- Leveson, N. G.; Turner, C. S. (1993): An Investigation of the Therac-25 Accidents. IEEE Computer 26(7), 18–41.
Modelové předpoklady laboratoří
Laboratoře jsou zjednodušené modely, ne měření skutečných systémů. Časy přístupu do paměti a sítě jsou řádové hodnoty; model načtení stránky nezahrnuje pomalý rozjezd TCP, ztráty paketů ani dobu zpracování na serveru; síla hesla platí jen pro náhodně generovaná hesla. Řadicí, grafové a databázové algoritmy počítají přesně, ale na malých datech. Mini SQL a robotí jazyk jsou vlastní zjednodušené interprety; RSA je učebnicové bez doplňování a s malými prvočísly, k ničemu jinému než k pochopení principu se nehodí. Referenční četnosti písmen v kapitole 9 jsou spočítané z textu tohoto průvodce. Všechna čísla v příkladech a procvičení jsou přepočítaná skriptem (Python, JavaScript) nebo databází SQLite.