]> mj.ucw.cz Git - ads1.git/commitdiff
Trideni a Strassen: Zapisky od Karla
authorMartin Mares <mj@ucw.cz>
Mon, 30 May 2011 11:38:38 +0000 (13:38 +0200)
committerMartin Mares <mj@ucw.cz>
Mon, 30 May 2011 11:38:38 +0000 (13:38 +0200)
13-trideni/13-trideni.tex [new file with mode: 0644]
13-trideni/Makefile [new file with mode: 0644]
13-trideni/RozhodovaciStrom.eps [new file with mode: 0644]
13-trideni/nasobeni-matic-2.eps [new file with mode: 0644]
13-trideni/nasobeni-matic.eps [new file with mode: 0644]
2007/3-strassen/nasobeni-matic-2.eps [deleted file]
2007/3-strassen/nasobeni-matic.eps [deleted file]
2007/5-qs/RozhodovaciStrom.eps [deleted file]

diff --git a/13-trideni/13-trideni.tex b/13-trideni/13-trideni.tex
new file mode 100644 (file)
index 0000000..46914df
--- /dev/null
@@ -0,0 +1,445 @@
+\input ../lecnotes.tex
+
+\prednaska{13}{Tøídící algoritmy a násobení matic}{}
+
+Minulou pøedná¹ku jsme probírali QuickSort, jeden z historicky prvních tøídících algoritmù,
+které pøekonaly kvadratickou slo¾itost aspoò v~prùmìrném pøípadì.
+
+Proè se dodnes pou¾ívá, kdy¾ známe algoritmy, které mají slo¾itost $\Theta(n\log n)$ i
+v nejhor¹ím pøípadì? Proto¾e QuickSort se k pamìti chová témìø sekvenènì, tak¾e na
+dne¹ních poèítaèích bì¾í rychle.
+
+Podívejme se na pár nápadù pro skuteèné naprogramování tohoto algoritmu.
+
+Urèitì nám vadí pøekopírovávat z a do pomocných polí. Na¹tìstí mù¾eme pøerovnávat
+pøímo v pùvodním poli. Zleva budeme dávat prvky men¹í ne¾ pivot, zprava vìt¹í ne¾
+pivot. Na toto staèí udr¾ovat si dva indexy $a$ a $b$, které znaèí, jak daleko vlevo
+(vpravo) u¾ jsou správné prvky.
+
+Rekurzivní programy mohou být pro poèítaè zátì¾í. Proto implementujme vlastní zásobník
+na hranice úsekù, které zbývá setøídit. V¾dy vìt¹í interval vlo¾íme na zásobník a men¹í
+rovnou zpracujeme. Na zásobníku tedy bude maximálnì $\log n$ polo¾ek.
+
+Malé podproblémy dotøídíme nìjakým triviálním algoritmem napøíklad InsertSortem.
+Odhadem pro $n=10$ je to pro dne¹ní poèítaèe výhodné.
+
+\h{Zoo tøídících algoritmù}
+
+Porovnejme nyní známé tøídící algoritmy.
+
+Bude nás zajímat i jejich stabilita, tedy jestli zachovají poøadí polo¾ek se stejným
+klíèem. Stabilita je dùle¾itá pøi lexikografickém tøídìní, kde se napøed tøídí podle
+nejménì významné slo¾ky a pak podle významìj¹ích.
+
+\s{Definice:} {\it Stabilní tøídìní} øíkáme takovému, které u~prvkù se stejnou hodnotou
+klíèe zachová jejich vzájemné poøadí, v~jakém byly na~vstupu.
+
+\medskip
+
+\settabs 4 \columns
+\+             & \<Èas>                & \<Pomocná pamì»>      & \<Stabilní> \cr
+\smallskip
+\+ InsertSort  & $\Theta (n^2)$        & $\Theta (1)$          & $+$ \cr
+\+ MergeSort   & $\Theta (n\log n)$    & $\Theta (n)$          & $+$ \cr
+\+ HeapSort    & $\Theta (n\log n)$    & $\Theta (1)$          & $-$ \cr
+\+ QuickSort   & $\Theta (n\log n)$    & $\Theta (\log n)$     & $-$ \cr
+
+\medskip
+
+\>Poznámky k tabulce:
+\itemize\ibull
+\:QuickSort má jen prùmìrnou èasovou slo¾itost $\Theta (\log n)$. Mù¾eme ale øíct, ¾e
+porovnáváme prùmìrné èasové slo¾itosti, proto¾e u ostatních algoritmù vyjdou stejnì
+jako jejich èasové slo¾itosti v~nejhor¹ím pøípadì.
+\:HeapSort -- tøídìní pomocí haldy. Do haldy vlo¾íme v¹echny prvky a pak je vybereme.
+Celkem $n$ operací s haldou, ka¾dá za $\log n$. Navíc tuto haldu mohu stavìt i boøit
+v poli, ve kterém dostanu vstup.
+\:MergeSort jde implementovat s konstantní pamì»ovou slo¾itostí.
+\:MergeSort je stabilní, kdy¾ dìlím pole na poloviny. Není pøi tøídìní spojových seznamù
+s~rozdìlováním prvkù na sudé a liché.
+\:QuickSort se dá naprogramovat stabilnì, ale potøebuje lineárnì pomocné pamìti.
+\endlist
+
+\>®ádný algoritmus v tabulce netøídil rychleji ne¾ $\Theta(n\log n)$. To není náhoda
+-- nasledující vìta nám øíká, ¾e to nejde:
+
+{\bf XXX: Letos jsem vìtu dokazoval trochu jinak, nutno pøedìlat.}
+
+\s{Vìta:}
+Ka¾dý tøídící algoritmus zalo¾ený na porovnávání a prohazování prvkù
+potøebuje na vstup délky $n$ v nejhor¹ím pøípadì $\Omega (n \log n)$ porovnání.
+
+\proof
+Bez újmy na obecnosti budeme nejdøíve pøedpokládat o algoritmu dvì vìci:
+Jednak to, ¾e algoritmus nejprve porovnává, a teprve potom prohazuje.\foot{Algoritmus
+mù¾eme upravit tak, aby si pamatoval aktuální permutaci prvkù a podle ní prohazoval a¾ na konci.}
+Také pøedpokládáme, ¾e vstup algoritmu je permutace na mno¾inì $\{1, \ldots, n\}$.
+
+Chování tohoto algoritmu popí¹eme rozhodovacím stromem. V rozhodovacím stromu vnitøní vrcholy
+urèují jednotlivá porovnání prvkù a listy odpovídají okam¾ikùm, kdy algoritmus pøestal porovnávat a zaèal prohazovat.
+
+\figure{RozhodovaciStrom.eps}{Rozhodovací Strom}{0.3\hsize}
+
+Vstup je permutace $n$ prvkù, a víme ¾e poèet rùzných permutací je $n!$. Existuje tedy právì $n!$ rùzných vstupù.
+Dále si v¹imneme, ¾e nemohou existovat dvì vstupní permutace, pro které by algoritmus skonèil v tém¾e listu rozhodovacího stromu.
+Listù stromu je tedy alespoò tolik, kolik je rùzných vstupù, tedy $n!$.
+
+{\narrower
+  \s{Lemmátko:} Binární strom hloubky $k$ má nejvý¹e $2^k$ listù.
+  \par\noindent {\sl Dùkazík:} Uva¾me binární strom hloubky $k$ s maximálním poètem
+  listù. V takovém stromu budou v¹echny listy urèitì le¾et na poslední hladinì
+  (kdyby nele¾ely, mù¾eme pod nìkterý list na vy¹¹í hladinì pøidat dal¹í dva vrcholy a získat
+  tak \uv{listnatìj¹í} strom stejné hloubky). Jeliko¾ na $i$-té hladinì je nejvý¹e $2^i$
+  vrcholù, v¹ech listù je nejvý¹e $2^k$.
+  \qed
+}
+
+\>Z~tohoto lemmátka plyne, ¾e rozhodovací strom musí být hluboký alespoò $\log n!$.
+
+\>Zbytek je u¾ snadné cvièení z diskrétní matematiky:
+
+{\narrower
+  \s{Lemmátko:} $ n! \ge n^{n / 2}$.
+  \par\noindent {\sl Dùkazík:} $n! = \sqrt{(n!)^2} = \sqrt{1(n-1)\cdot 2(n-2) \cdot \ldots \cdot n\cdot 1}$,
+  co¾ mù¾eme také zapsat jako $\sqrt{1(n-1)}\cdot \sqrt{2(n-2)} \cdot \ldots \cdot \sqrt{n\cdot 1}$.
+  Pøitom pro ka¾dé $1\le k\le n$ je $k(n+1-k) = kn + k - k^2 = n + (k-1)n + k(1-k) = n + (k-1)(n-k) \ge n$.
+  Proto je ka¾dá z~odmocnin vìt¹í nebo rovna $n^{1/2}$ a $n!\ge (n^{1/2})^n = n^{n/2}$.
+  \qed
+}
+
+\>Hloubka stromu tedy èiní minimálnì $\log n! \ge \log(n^{n/2}) = n/2 \cdot \log n = \Omega(n\log n)$,
+co¾ také zdola odhaduje poèet porovnání, který algoritmus provede v nejhor¹ím pøípadì.
+\qed
+
+Ukázali jsme si tøídìní v èase $ \O(N\log{N}) $ a také dokázali, ¾e líp to v obecném
+pøípadì nejde. Na¹e tøídící algoritmy jsou tedy optimální (a¾ na multiplikativní konstantu).
+Opravdu?
+
+Pøekvapivì mù¾eme tøídit i rychleji -- vìta omezuje pouze tøídìní pomocí porovnávaní.
+Co kdy¾ o~vstupu víme víc, tøeba ¾e je tvoøen èísly z~omezeného rozsahu.
+
+\h{Counting sort}
+
+Counting sort je algoritmus pro tøídìní $N$ celých èísel s maximálním rozsahem hodnot
+$R$. Tøídí v èase $ \O(N + R) $ s~pamì»ovou nároèností $ \O(R) $.
+
+Algoritmus postupnì prochází vstup a poèítá si ke ka¾dému prvku z~rozsahu kolikrát jej
+vidìl. Poté a¾ projde celý vstup, projde poèítadla a indexy u~tech, kde nìco napoèítal
+vydá jako výstup.
+
+\s{Algoritmus:} (tøídìní posloupnosti $\left ( x_i \right )_0^N$ pomocí {\it Counting sort}u)
+
+\algo
+\:Pro $ i \leftarrow 1 $ do $R$ opakuj:
+\::$ p_i \leftarrow 0 $
+\:Pro $ i \leftarrow 1 $ do $N$ opakuj:
+\::$ p_{x_i} \leftarrow p_{x_i} + 1 $
+\:$ j \leftarrow 1 $
+\:Pro $ i \leftarrow 1 $ do $R$ opakuj:
+\::Pokud $ p_i \neq 0 $
+\:::$ v_j \leftarrow i $
+\:::$ j \leftarrow j + 1 $
+\:Vra» $v$
+\endalgo
+
+\h{Pøihrádkové tøídìní}
+
+Counting sort nám moc nepomù¾e, pokud chceme tøídit neco jiného ne¾ celá èísla, ale i
+to se dá øe¹it. Pøihrádkové, popøípadì kbelíkové tøídìní, neboli bucket-sort umí
+tøídit mno¾inu prvkù oèíslovaných èísly $ 1 \ldots R $.
+
+\>Potøebuje k tomu èas $ \O(N + R) $ a pamì» $ \O(N + R) $.
+
+Bucket sort ma je¹tì jednu pøíjemnou vlastnost: jedná se o stabilní tøídìní.
+
+\s{Algoritmus:} (tøídìní mno¾iny $x_1, x_2, \ldots, x_n $ oèíslované $c_1, c_2, \ldots, c_n$ pomocí {\it bucket-sort}u)
+\algo
+\:$P_1 \dots P_R \leftarrow \emptyset$
+\:Pro $i=1\dots n$:
+\::vlo¾ $x_i$ do $P_{x_i}$
+\:Pro $j=1\dots R$
+\::vypi¹ co je v $P_j$
+\endalgo
+
+\h{Lexikografické tøídìní k-tic}
+Mìjme $n$ uspoøádaných $k$-tic prvkù z mno¾iny $ \{1 \ldots R \}^k $. Úkol zní seøadit
+\hbox{$k$-tice} slovníkovì (lexikograficky). Mù¾eme pou¾ít metodu rozdìl a panuj,
+tak¾e prvky setøídíme nejprve podle první souøadnice $k$-tic a pak se rekurzivnì
+zavoláme na ka¾dou pøihrádku a tøídíme podle následující souøadnice.
+% a dal??
+Nebo mù¾eme vyu¾ít toho, ¾e bucket-sort je stabilní a tøídit takto:
+
+\s{Algoritmus: } (tøídìní $k$-tic $ x_1, x_2, \ldots ,x_n $ lexikograficky pomocí {\it Bucket-sort}u)
+\algo
+\:$ S \leftarrow \{x_1, x_2, \dots, x_n\} $
+\:Pro $ i \leftarrow k $ do $ 1 $ opakuj:
+\::$ S \leftarrow $ bucket-sort $ S $ podle $i$-té souøadnice
+\:vysledek $ S $
+\endalgo
+
+Pro pøehlednost v následujícím pozorování oznaème $ l = k - i + 1 $, co¾ pøesnì odpovídá tomu, v kolikátém prùchodu cyklu jsme.
+
+\s{Pozorování:}
+Po $l$-tém prùchodu cyklem jsou prvky uspoøádány lexikograficky podle $i$-té a¾ $k$-té souøadnice.
+
+\proof
+Indukcí podle $l$:
+\itemize\ibull
+\:Pro $ l = 1 $ jsou prvky uspoøádány podle poslední souøadnice.
+\:Po $l$ prùchodech ji¾ máme prvky setøídìny lexikograficky podle $i$-té a¾ $k$-té souøadnice a spou¹tíme $(l + 1)$-ní prùchod, tj. budeme tøídít podle $(i - 1)$-ní souøadnice.
+Proto¾e bucket-sort tøídí stabilnì, zùstanou prvky se stejnou $(i - 1)$-ní souøadnicí vùèi sobì seøazeny tak, jak byly seøazeny na vstupu.
+Z IP tam v¹ak byly seøazeny lexikograficky podle $i$-té a¾ $k$-té souøadnice. Tudí¾ po $(l + 1)$-ním prùchodu jsou prvky seøazeny podle $(i - 1)$-ní a¾ $k$-té souøadnice.
+\endlist
+\qed
+
+Èasová slo¾itost je $\O( k \cdot (n + R))$, co¾ je lineární s délkou vstupu $(k \cdot n)$ pro pevné $k$; pamì»ová slo¾itost èiní $\O(n + R)$.
+
+\h{Tøídìní èísel $ 1 \ldots R $ podruhé (Radix sort)}
+Zvolíme základ $Z$ a èísla zapí¹eme v soustavì o základu $Z$, èím¾ získáme $ ( \lfloor \log_z{R} \rfloor +1) $-tice, na které spustíme pøedcházející algoritmus.
+Díky tomu budeme tøídít v èase $\O({\log{R} \over \log{Z}} \cdot (n + Z))$. A jak zvolit vhodnì $Z$?
+
+Pokud bychom zvolili $Z$ konstantní, èasová slo¾itost bude $\O(\log{R} \cdot n) $, co¾ mù¾e být $ n \log{n} $ nebo i víc.
+Zvolíme-li $ Z = n $, dostáváme $ \O({\log{R} \over \log{n}} \cdot n) $, co¾ pro $ R \leq n^\alpha $ znamená $ \O(\alpha n) $.
+
+\h{Tøídìní øetìzcù}
+
+\>{\I (Na pøedná¹ce letos nebylo, ale pro úplnost uvádíme.)}
+
+Mìjme $n$ øetìzcù $ r_1, r_2 \dots r_n $ dlouhých $ l_1, l_2 \dots
+l_n $ Oznaème si $ L = \max_{1 \leq i \leq n} l_i $ délku nejdel¹ího øetìzce a $R$
+poèet znakù abecedy.
+
+Problém je, ¾e øetìzce nemusí být stejnì dlouhé (pokud by byly, lze se na øetìzce
+dívat jako na $k$-tice, které u¾ tøídít umíme). S tím se mù¾eme pokusit vypoøádat
+doplnìním øetìzcù mezerami tak, aby mìly v¹echny stejnou délku, a spustit na nìj
+algoritmus pro $k$-tice. Tím dostaneme algoritmus, který bude mít èasovou slo¾itost $
+\O(Ln) $, co¾ bohu¾el mù¾e být a¾ kvadratické vzhledem k velikosti vstupu.
+
+Pøíklad: na vstupu mìjme k øetìzcù, kde prvních $k-1$ z nich bude mít délku $1$ a
+poslední øetìzec bude dlouhý pøesnì $k$. Vstup má tedy celkovou délku $2k-1$ a my teï
+doplníme prvních $k-1$ øetìzcù mezerami. Vidíme, ¾e algoritmus teï bude pracovat v
+èase $ \O(k^2) $. To, co nám nejvíce zpùsobovalo problémy u pøedchozího pøíkladu, bylo
+velké mno¾ství èasu zabraného porovnáváním doplnìných mezer. Zkusíme proto øe¹it ná¹
+problem trochu chytøeji a koncové mezery do øetìzù vùbec pøidávat nebudeme.
+
+Nejprve roztøídíme bucket-sortem øetìzce do pøihrádek (mno¾in) $ P_i $ podle jejich
+délek, kde $i$ znaèí délku øetìzcù v dané pøihrádce, neboli definujme $ P_i = \left\{
+r_j \vert l_j = i \right\} $. Dále si zavedeme seznam setøídìných øetìzcù $S$
+takový, ¾e v nìm po $k$-tém prùchodu tøídícím cyklem budou øetìzce s délkou
+alespoò $ L - k + 1 $ (oznaème $l$) a zároveò v nìm tyto øetìzce budou
+setøídìny lexikograficky od $l$-tého znaku po $L$-tý. Z definice tohoto
+seznamu je patrné, ¾e po $L$ krocích tøídícího cyklu bude tento seznam
+obsahovat v¹echny øetìzce a tyto øetìzce v nìm budou lexikograficky seøazeny.
+
+Zbývá u¾ jen popsat, jak tento cyklus pracuje. Nejprve vezme $l$-tou mno¾inu $ P_l $ a
+její øetìzce roztøídí do pøihrádek $ Q_j $ (kde index $j$ znaèí j-tý znak abecedy)
+podle jejich $l$-tého (neboli posledního) znaku. Dále vezme seznam $S$ a jeho øetìzce
+pøidá opìt podle jejich $l$-tého znaku do stejných pøihrádek $ Q_j $ za ji¾ døíve
+pøidané øetìzce z $ P_l $. Na závìr postupnì projde v¹echny pøihrádky $ Q_j $ a
+øetìzce v nich pøesune do seznamu $S$. Proto¾e øetìzce z pøihrádek $ Q_j $ bude brát
+ve stejném poøadí, v jakém do nich byly umístìny, a proto¾e ze seznamu $S$, který je
+setøízený podle $ (l + 1) $-ního znaku po $L$-tý, bude také brát øetìzce postupnì,
+bude seznam $S$ po $k$-tém prùchodu pøesnì takový, jaký jsme chtìli (indukcí bychom
+dokázali, ¾e cyklus pracuje skuteènì správnì). Zároveò z popisu algoritmu je jasné, ¾e
+bìhem tøídìní ka¾dý znak ka¾dého øetìzce pou¾ijeme právì jednou, tudí¾ algoritmus bude
+lineární s délkou vstupu (pro úplnost dodejme, ¾e popsaný algoritmus funguje v
+pøípadech, kdy abeceda má pevnou velikost).
+
+Algoritmus: (tøídìní øetìzcù)
+\algo 
+\:$L \leftarrow \max(l_1, l_2,\ldots,l_n)$
+\:Pro $ i \leftarrow 1 $ do $L$ opakuj:
+\::$ P_i \leftarrow \emptyset $
+\:Pro $ i \leftarrow 1 $ do $ n $ opakuj:
+\::$ \<pridej>(P_{l_i}, r_i) $
+
+\:$ S \leftarrow \emptyset $
+\:Pro $ i \leftarrow L $ do $ 1 $ opakuj:
+\::Pro $ j \leftarrow 1 $ do $ R $ opakuj:
+\:::$ Q_j \leftarrow \emptyset $
+
+\::Pro $ j \leftarrow 1 $ do velikost($P_i$) opakuj:
+\:::$ \<vezmi>(P_i, r) $
+\:::$ \<pridej>(Q_{r[i]}, r) $
+\::Pro $ j \leftarrow 1 $ do velikost($S$) opakuj:
+\:::$ \<vezmi>(S, r) $
+\:::$ \<pridej>(Q_{r[i]}, r) $
+
+\::$ S \leftarrow \emptyset $
+\::Pro $ j \leftarrow 1 $ do $ R $ opakuj:
+\:::Pro $ k \leftarrow 1 $ do velikost($Q_j$) opakuj:
+\::::$ \<vezmi>(Q_j, r) $
+\::::$ \<pridej>(S, r) $
+
+\:výsledek $S$
+\endalgo
+
+Èasová slo¾itost tohoto algoritmu tedy bude $ \O(RN) $, kde $N$ je délka vstupu a $R$ poèet znakù abecedy.
+
+\h{Zoo tøídících algoritmù podruhé}
+
+\>Doplòme tedy na¹i tabulku:
+
+\medskip
+
+\settabs 4 \columns
+\+             & \<Èas>                & \<Pomocná pamì»>      & \<Stabilní> \cr
+\smallskip
+\+ InsertSort  & $\Theta (n^2)$        & $\Theta (1)$          & $+$ \cr
+\+ MergeSort   & $\Theta (n\log n)$    & $\Theta (n)$          & $+$ \cr
+\+ HeapSort    & $\Theta (n\log n)$    & $\Theta (1)$          & $-$ \cr
+\+ QuickSort   & $\Theta (n\log n)$    & $\Theta (\log n)$     & $-$ \cr
+\+ BucketSort  & $\Theta (n+R)$        & $\Theta (n+R)$        & $+$ \cr
+\+ k-tice      & $\Theta (k(n+R))$     & $\Theta (n+R)$        & $+$ \cr
+\+ RadixSort   & $\Theta (n\log _n R)$ & $\Theta (n)$          & $+$ \cr
+
+\smallskip
+
+\h{K èemu je vlastnì tøídìní dobré?} Díky nìmu mù¾eme rychle vyhledávat prvky v
+mno¾inì, konkrétnì v èase $ \O(\log n) $ napø. pomocí pùlení intervalù. Dal¹ím
+problémem, na který se hodí pou¾ít tøídìní, je zji¹tìní, zda se v posloupnosti nìjaké
+její hodnoty opakují. Dá se dokázat, ¾e tuto úlohu nelze vyøe¹it lépe (rychleji), ne¾
+tak, ¾e hodnoty nejprve setøídíme a poté setøidìnou posloupnost projdeme.
+
+\h{Násobení matic n$\times$n a Strassenùv algoritmus}
+
+Nejdøíve si pøipomeneme definici násobení dvou ètvercových matic typu $n \times n$.
+Platí, ¾e prvek v $i$-tém øádku a $j$-tém sloupci výsledné matice $Z$ se rovná
+standardnímu skalárnímu souèinu $i$-tého øádku první matice $X$ a $j$-tého sloupce
+druhé matice~$Y$. Formálnì zapsáno:
+
+$$ Z_{ij} = \sum_{k=1}^n X_{ik} \cdot Y_{kj}. $$
+
+\figure{nasobeni-matic.eps}{Násobení matic}{\epsfxsize}
+
+Algoritmus, který by násobil matice podle této definice, by mìl èasovou slo¾itost $
+\Theta(n^3) $, proto¾e poèet prvkù ve výsledné matici je $n^2$ a jeden skalární souèin
+vektorù dimenze $n$ vy¾aduje lineární poèet operací.
+
+My se s touto èasovou slo¾itostí ov¹em nespokojíme a budeme postupovat podobnì jako
+pøi vylep¹ování algoritmu na násobení velkých èísel. Bez újmy na obecnosti
+pøedpokládejme, ¾e budeme násobit dvì matice typu $n \times n$, kde $n=2^k, k \in \bb
+N$. Obì tyto matice rozdìlíme na ètvrtiny a tyto èásti
+postupnì oznaèíme u matice $X$ písmeny $A$, $B$, $C$ a $D$, u matice $Y$ písmeny $P$,
+$Q$, $R$ a $S$. Z~definice násobení matic zjistíme, ¾e ètvrtiny výsledné matice $Z$
+mù¾eme zapsat pomocí souèinù èástí násobených matic. Levá horní ètvrtina bude
+odpovídat výsledku operací $AP+BR$, pravá horní ètvrtina bude $AQ+BS$, levá dolní
+$CP+DR$ a zbylá $CQ+DS$ (viz obrázek).
+
+\figure{nasobeni-matic-2.eps}{Násobení rozètvrcených matic}{\epsfxsize}
+
+Pøevedli jsme tedy problém násobení ètvercových matic øádu $n$ na násobení ètvercových
+matic øádu ${n/2}$. Tímto rozdìlováním bychom mohli pokraèovat, dokud bychom se
+nedostali na matice øádu 1, jejich¾ vynásobení je triviální. Dostali jsme tedy
+klasický algoritmus typu {\it rozdìl a panuj}. Pomohli jsme si ale nìjak? V ka¾dém
+kroku provádíme 8 násobení matic polovièního øádu a navíc konstantní poèet operací na
+$n^2$ prvcích. Dostáváme tedy rekurentní zápis èasové slo¾itosti:
+
+$$ T(n) = 8T\left({n \over 2}\right) + \Theta(n^2). $$
+
+Pou¾itím Master Theoremu lehce dojdeme k závìru, ¾e slo¾itost je stále $\Theta(n^3)$, tedy stejná jako pøi násobení matic z definice. Zdánlivì jsme si tedy nepomohli, ale stejnì jako tomu bylo u násobení velkých èísel, i teï mù¾eme zredukovat poèet násobení matic polovièního øádu, které nejvíce ovlivòuje èasovou slo¾itost algoritmu. Není to bohu¾el nic triviálního, a proto si radìji rovnou øekneme správné øe¹ení. Jedná se o Strassenùv algoritmus, který redukuje potøebný poèet násobení na~7, a je¹tì pøed tím, ne¾ si uká¾eme, jak funguje, doká¾eme si, jak nám to s èasovou slo¾itostí vlastnì pomù¾e:
+
+$$ T(n) = 7T\left({n \over 2}\right) + \Theta(n^2) \Longrightarrow \Theta(n^{\log_2 7}) = \O(n^{2.808}). $$
+
+Výsledná slo¾itost Strassenova algoritmu je tedy $\O(n^{2.808})$, co¾ je sice malé, ale pro velké matice znatelné zlep¹ení oproti algoritmu vycházejícímu pøímo z~definice.
+
+\s{Lemma:} (vzorce pro násobení blokových matic ve~Strassenovì algoritmu)
+
+\def\\{\noalign{\vskip 7pt}}
+
+$$
+\pmatrix{A & B \cr\\ C & D \cr}
+\cdot
+\pmatrix{P & Q \cr\\ R & S \cr}
+=
+\pmatrix{
+T_1 + T_4 - T_5 + T_7 &
+T_3 + T_5 \cr\\
+T_2 + T_4 &
+T_1 - T_2 + T_3 + T_6 \cr
+},$$
+
+kde:
+
+$$\vbox{\halign{$#$\hfil\qquad &$#$\hfil\qquad \cr
+T_1 = (A+D)\cdot(P+S)          & T_5 = (A+B)\cdot S \cr\\
+T_2 = (C+D)\cdot P             & T_6 = (C-A)\cdot (P+Q) \cr\\
+T_3 = A\cdot(Q-S)              & T_7 = (B-D)\cdot (R+S) \cr\\
+T_4 = D\cdot(R-P)                                       \cr
+}}$$
+
+\medskip
+
+\proof Do ètvercù $4 \times 4$ si napí¹eme znaky $+$ nebo $-$ podle toho, jestli se pøi výpoètu dané matice pøièítá nebo odeèítá pøíslu¹ný souèin dvou matic. Øádky znamenají matice $A$, $B$, $C$ a $D$ a sloupce znaèí matice $P$, $Q$, $R$ a $S$. Pokud se tedy v prvním øádku a prvním sloupci vyskytuje znak $+$, znamená to ¾e pøièteme souèin matic $A$~a~$P$. Nejdøíve si spoèítáme pomocné matice $T_1$ a¾ $T_7$ a z nich pak dopoèítáme, co bude na pøíslu¹ných místech ve výsledné matici.
+
+\def\bbb#1{\vbox to 10pt{\vss\hbox to 10pt{\hss\tenrm #1\hss}\vss}}
+\def\bb#1{\ifx#1.\bbb{$\cdot$}\else\bbb#1\fi}
+\def\zz#1#2#3#4{\bb#1\bb#2\bb#3\bb#4}
+\def\qq#1#2#3#4{{\offinterlineskip\vcenter{\halign{\vrule ##\vrule \cr\noalign{\hrule}\zz#1\cr\zz#2\cr\zz#3\cr\zz#4\cr\noalign{\hrule}}}}}
+
+$$
+T_1 = \qq{+..+}{....}{....}{+..+} \qquad
+T_2 = \qq{....}{....}{+...}{+...} \qquad
+T_3 = \qq{.+.-}{....}{....}{....} \qquad
+T_4 = \qq{....}{....}{....}{-.+.}
+$$
+$$
+T_5 = \qq{...+}{...+}{....}{....} \qquad
+T_6 = \qq{--..}{....}{++..}{....} \qquad
+T_7 = \qq{....}{..++}{....}{..--}
+$$
+
+\medskip
+
+\def\\{\noalign{\vskip 7pt}}
+$$
+\eqalign{
+T_1 + T_4 - T_5 + T_7 &= \qq{+...}{..+.}{....}{....} = AP + BR \cr\\
+T_3 + T_5 &= \qq{.+..}{...+}{....}{....} = AQ + BS \cr\\
+T_2 + T_4 &= \qq{....}{....}{+...}{..+.} = CP + DR \cr\\
+T_1 - T_2 + T_3 + T_6 &= \qq{....}{....}{.+..}{...+} = CQ + DS \cr
+}
+$$
+
+% konec slidu z prednasky
+
+Jak je vidìt, výsledná matice je tvoøena stejnými èástmi jako pøi obyèejném násobení. Touto kapitolou jsme tedy dokázali následující vìtu:
+
+\s{Vìta:}
+Strassenùv algoritmus pro násobení matic $n \times n$ má èasovou slo¾itost
+v nejhor¹ím pøípadì $\O(n^{2.808})$. \qed
+
+\s{Poznámka:}
+Zatím nejlep¹í dokázaný algoritmus má èasovou slo¾itost $\O(n^{2.376})$, leè s velkou multiplikativní konstantou.
+
+\h{Dosa¾itelnost v grafech pomocí Strassenova algoritmu}
+
+Matice mohou souviset s mnoha na první pohled nesouvisejícími problémy.
+
+\s{Lemma:} Nech» $A$ je matice sousednosti grafu, nech» $S^{(k)}_{z,j}$
+oznaèíme poèet sledù délky~$k$ z vrcholu~$j$ do vrcholu $i$. Pak $S^{(k)}=A^k$.
+
+\proof
+Indukcí podle~$k$:
+
+\itemize\ibull
+\:$S^{(1)}=A$
+\:$S^{(k+1)}_{i,j}=\sum_{z:(i, z)\in E(G)} S^{(k)}_{z, j} = \sum _{z=1}^n A_{i, z}
+S_{z, j}^{(k)}=(AS^{(k)})_{i, j}$
+\endlist
+\qed
+
+Pøidáním smyèek do matice $A$ zjistíme dostupnost vrcholù po cestách dlouhých $k$ nebo
+krat¹ích.
+
+Staèí tedy spoèítat matici $B=(A+E)^k$ pro libovolné $k\geq n$ ($E$ je jednotková matice).
+Pak $B_{i,j}\neq 0$ právì kdy¾ existuje cesta z vrcholu $i$ do vrcholu $j$.
+
+Pro vypoèítání $B$ nám staèí $\lceil \log n \rceil$ umocnìní matice na druhou, co¾ je
+speciální pøípad násobení matic. Èasová slo¾itost celého algoritmu tedy èiní $\O(n^{\log _2 7} \cdot \log n)$.
+
+Musíme v¹ak dávat pozor a normovat èísla (nulu necháme, nenulová nahradíme pøi ka¾dém
+násobení jednièkou), aby nám nepøerostla pøes hlavu a hlavnì pøes maximální
+integer.
+
+\bye
diff --git a/13-trideni/Makefile b/13-trideni/Makefile
new file mode 100644 (file)
index 0000000..ed75925
--- /dev/null
@@ -0,0 +1,3 @@
+P=13-trideni
+
+include ../Makerules
diff --git a/13-trideni/RozhodovaciStrom.eps b/13-trideni/RozhodovaciStrom.eps
new file mode 100644 (file)
index 0000000..e4e3f76
Binary files /dev/null and b/13-trideni/RozhodovaciStrom.eps differ
diff --git a/13-trideni/nasobeni-matic-2.eps b/13-trideni/nasobeni-matic-2.eps
new file mode 100644 (file)
index 0000000..4d705b9
Binary files /dev/null and b/13-trideni/nasobeni-matic-2.eps differ
diff --git a/13-trideni/nasobeni-matic.eps b/13-trideni/nasobeni-matic.eps
new file mode 100644 (file)
index 0000000..0f285e3
Binary files /dev/null and b/13-trideni/nasobeni-matic.eps differ
diff --git a/2007/3-strassen/nasobeni-matic-2.eps b/2007/3-strassen/nasobeni-matic-2.eps
deleted file mode 100644 (file)
index 4d705b9..0000000
Binary files a/2007/3-strassen/nasobeni-matic-2.eps and /dev/null differ
diff --git a/2007/3-strassen/nasobeni-matic.eps b/2007/3-strassen/nasobeni-matic.eps
deleted file mode 100644 (file)
index 0f285e3..0000000
Binary files a/2007/3-strassen/nasobeni-matic.eps and /dev/null differ
diff --git a/2007/5-qs/RozhodovaciStrom.eps b/2007/5-qs/RozhodovaciStrom.eps
deleted file mode 100644 (file)
index e4e3f76..0000000
Binary files a/2007/5-qs/RozhodovaciStrom.eps and /dev/null differ