From 34a5dc863d5aa41e55375106a37c50f6f6157b02 Mon Sep 17 00:00:00 2001
From: Jiri Kalvoda <jirikalvoda@kam.mff.cuni.cz>
Date: Thu, 2 May 2024 09:31:11 +0200
Subject: [PATCH] prace: Drobnosti

---
 prace/bakalarka/index.md | 446 ++++++++++++++++++++-------------------
 1 file changed, 233 insertions(+), 213 deletions(-)

diff --git a/prace/bakalarka/index.md b/prace/bakalarka/index.md
index 9b64deaf0..d8d647ae4 100755
--- a/prace/bakalarka/index.md
+++ b/prace/bakalarka/index.md
@@ -17,9 +17,10 @@ ft:
         proto bychom rádi pro danou posloupnost aut provedli co nejméně změn.
         Je známé, že úloha je NP-těžká a za určitých předpokladů dokonce neaproximovatelná,
         proto je na místě zkoumat řešení, co se chovají dobře na náhodném vstupu.
-        V této práci je představen nový algoritmus založený na semidefinitním programování, který dle provedených měření pro náhodné vstupy s až 400 typy aut dosahuje výsledků okolo 0.33-násobku počtu typů aut.
-        O algoritmu jsme dokázali, že pro každý vstup vrátí řešení nejhůře o 0.212 násobek počtu typů aut horší než optimum.
-        Bohužel se mi nepodařilo dokázat žádný netriviální horní odhad na střední hodnotu počtu změn na náhodném vstupu.
+        V této práci je představen nový algoritmus založený na semidefinitním programování,
+        který dle provedených měření pro náhodné vstupy dosahuje výsledků okolo 0.34-násobku počtu typů aut.
+        O algoritmu jsme dokázali, že pro každý vstup vrátí ve střední hodnotě řešení nejhůře o 0.212 násobek počtu typů aut horší než optimum.
+        Bohužel se nám nepodařilo dokázat žádný netriviální horní odhad na střední hodnotu počtu změn na náhodném vstupu.
     keywords: [binární paint shop problém, aproximační algoritmus]
     year: 2024
     study_programme: Informatika
@@ -28,7 +29,19 @@ ft:
         keywords: [binary paint shop problem, approximation algorithm]
         department: Computer Science Institute of Charles University
         department_type: Institute
-        abstract: TODO (en)
+        abstract: |
+            The Binary Paint Shop represents an optimization problem:
+            A line of cars enters a paint shop.
+            There are exactly two cars of each type.
+            The aim is to color one of these two cars red and the other blue.
+            It is hard to change the current color in paint shop
+            so for a given sequence of cars we would like to minimize number of color changes.
+            This task is known to be NP-hard, and under specific conditions, it defies polynomial time approximations.
+            Therefore, it is a good idea to find some algorithms which behave well on randomly generated input.
+            In this thesis is introduced new algorithm based on semidefinite programming
+            which considered to madden test on random inputs reach solutions near to 0.34 times number of car types.
+            We proved that for each input this algorithm returns a solution with expected deviation from optimum of at most 0.212 times the number of car types.
+            We can't prove any nontrivial upper bound on the expected number of color changes on random input.
 ---
 ``` {c=cmt}
 Algoritmus na Maximální řez: rozčlenit na věty a podobné
@@ -37,8 +50,6 @@ Opravit tvrzení o skoropotimáľníĺ řešení SDP
 Klikaci věci + generování obsahu formátítkem
 Více řezů
 složitost je n^c pro jaké c?
-intervaly *[]* <>
-
 ```
 
 ::: {only=html}
@@ -102,6 +113,7 @@ Chceme tedy nají obarvení aut tak, aby od každého typu bylo jedno červené
 :::
 
 Počet změn barev řešení považujeme za skóre algoritmu.
+Relativní skóre pak je poměr skóre a počtu typů aut.
 
 Problém můžeme chápat buď jako optimalizační problém, kde účelová funkce je počet změn v řešení a snažíme se ji minimalizovat,
 nebo jako rozhodovací problém, kde se ptáme, jestli existuje řešení s nejvýše nějakým zadaným počtem změn.
@@ -118,7 +130,7 @@ Struktura práce
 
 Nejprve si zavedeme notaci potřebnou pro pohodlnou práci s BPS
 a definujeme si aproximační algoritmy.
-Dále následuji shrnutí doposud známých algoritmů a jiných výsledků ohledně BPS.
+Dále následují shrnutí doposud známých algoritmů a jiných výsledků ohledně BPS.
 V následující kapitole je představen princip semidefinitního programování,
 které má uplatnění v algoritmu představeném o kapitolu dál.
 Poslední kapitola se věnuje praktické implementaci tohoto algoritmu
@@ -144,11 +156,11 @@ auta na pozici $i$.
 
 Pro algoritmus $\alg$ označíme skóre na vstupu $\alpha$
 pomocí $\gamma_{\alg}(\alpha)$.
-Dále označme všechny vstupy délky $n$ jako $w_n$.
+Dále označme všechny vstupy délky $n$ jako $W_n$.
 Průměrné skóre algoritmu na všech vstupech délky $n$ tedy bude
-$$\gamma_{\alg}(n) = {\sum_{\alpha \in w_n} \gamma_{\alg} (\alpha) \over |w_n|}.$$
+$$\gamma_{\alg}(n) = {\sum_{\alpha \in W_n} \gamma_{\alg} (\alpha) \over |W_n|}.$$
 Tuto hodnotu mimo jiné můžeme chápat jako střední hodnotu skóre pro uniformně náhodný vstup délky $n$.
-K tomu ještě zavedeme $\delta_{\alg}(\alpha) = \gamma_{\alg}(\alpha)/n_{\alpha}$ a analogicky $\delta_{\alg}(n) = \gamma_{\alg}(n)/n$.
+K tomu ještě zavedeme notaci pro relativní skóre $\delta_{\alg}(\alpha) = \gamma_{\alg}(\alpha)/n_{\alpha}$ a analogicky průměrné relativní skóre $\delta_{\alg}(n) = \gamma_{\alg}(n)/n$.
 Nakonec označme $\delta_{\alg} = \lim_{n\to\infty} \delta_{\alg}(n) = \lim_{n\to\infty} \gamma_{\alg}(n)/n$.
 Protože limita nemusí vždy existovat, zavedeme ještě limes superior a limes inferior:
 $\delta^+_{\alg} = \limsup_{n\to\infty} \delta_{\alg}(n)$ a
@@ -163,7 +175,7 @@ Definice aproximačních algoritmů
 --------------------------------
 
 Protože ne na všechny problémy známe polynomiální algoritmus, co je schopný je vyřešit,
-zajímavý výsledek může být, i když se k řešení zvládneme jen v nějakém smysl alespoň přiblížit.
+zajímavý výsledek může být, i když se k řešení zvládneme jen v nějakém smyslu alespoň přiblížit.
 Na to nejprve musíme říct, co pro nás znamená, že nějaké řešení je několikrát horší než jiné. To nám poskytne obecná definice optimalizačního problému.
 
 ::: {c=box t=def name="Optimalizační problém"}
@@ -172,35 +184,35 @@ přípustných řešení $F(I)$.
 Dále existuje účelová funkce $f$, která pro každý vstup a jeho přípustné řešení určuje reálné nezáporné číslo -- jeho hodnotu.
 
 Pokud se jedná o minimalizační problém, tak pod pojmem _optimum_ daného vstupu (značíme $\opt(I)$) myslíme infimum hodnot účelové funkce přes všechny přípustné řešení, tedy $\inf f[F(i)]$.
-Pro minimalizační problém analogicky použijeme supremum.
+Pro maximalizační problém analogicky použijeme supremum.
 :::
 
 A nyní již přejdeme k samotným definicím algoritmů blížících se optimu.
 
 ::: {c=box t=def name="Aproximační algoritmus"}
 Algoritmus $\alg$ je $g(n)$-aproximační na minimalizačním problému,
-pokud pro každý vstup $I$ algoritmus vrátí přípustné řešení $\algo(I)$, pro které platí, že $f(\algo(I)) \le g(|I|) \cdot \opt(I)$.
+pokud pro každý vstup $I$ algoritmus vrátí přípustné řešení $\alg(I)$, pro které platí, že $f(\alg(I)) \le g(|I|) \cdot \opt(I)$.
 :::
 
 Předešlá definice záleží na tom, co považujeme za velikost vstupu, což se pro různé problémy a jejich interpretace může lišit.
 Naštěstí nás většinou budou zajímat $c$-aproximace, tedy
-aproximace, kde $f(n)$ je konstantní funkce rovna $c$.
+aproximace, kde $g(n)$ je konstantní funkce rovna $c$.
 
 U maximalizačních problémů je drobný problém v terminologii,
 protože není shoda na tom, jestli má platit 
 $f(A(I)) \ge g(|I|) \cdot \opt(I)$
 nebo
 $f(A(I)) \ge {1\over g(|I|)} \cdot \opt(I)$.
-Na štěstí podle kontextu jde snadno rozžnout, která definice se používá,
+Naštěstí podle kontextu jde snadno rozhodnout, která definice se používá,
 protože je potřeba násobit optimum číslem menším rovno jedné (jinak by pro
 kladné hodnoty účelové funkce nemohl existovat žádný vyhovující algoritmus).
 
 Bohužel někdy asi ani s aproximačními algoritmy nevystačíme a proto zavedeme
-pravděpodobností relaxaci.
+pravděpodobnostní relaxaci.
 
 ::: {c=box t=def name="Pravděpodobnostní aproximační algoritmus"}
-Algoritmus $\alg$ je pravděpodobnostně $g(n)$-aproximační, existuje konstanta $p \in (0,1)$, taková, že pro každý vstup $I$ algoritmus vrátí přípustně řešení,
-pro které s pravděpodobností $\ge p$ platí, že $f(\alg(I)) \le g(|I|) \cdot \opt(I)$.
+Algoritmus $\alg$ je pravděpodobnostně $g(n)$-aproximační, existuje-li konstanta $p \in (0,1)$, taková, že pro každý vstup $I$ algoritmus vrátí přípustně řešení,
+pro které s pravděpodobností alespoň $p$ platí, že $f(\alg(I)) \le g(|I|) \cdot \opt(I)$.
 :::
 
 Všimněme si, že na konstantě $p$ příliš nezáleží.
@@ -209,9 +221,9 @@ z dodaných řešení zvládneme $p$ libovolně těsně přiblížit k jedné.
 
 Pokud řešíme složitost algoritmů a úloh,
 většinou vyžadujeme, aby účelová funkce i rozhodování přípustnosti řešení byly vyčíslitelné v polynomiálním čase.
-Navíc chceme, aby všechny přípustné řešení měli omezenou délku nějakým polynomem v délce vstupu.
+Navíc chceme, aby všechna přípustná řešení měla omezenou délku nějakým polynomem v délce vstupu.
 Snadno nahlédneme, že za takovýchto podmínek je rozhodovací verze,
-jestli je optimum alespoň zadané číslo v $NP$.
+jestli je optimum alespoň zadané číslo, v $NP$.
 Pro takovou úlohu většinou hledáme polynomiální aproximační algoritmus.
 Binární paint shop vyhovuje všem těchto podmínkám.
 
@@ -220,11 +232,12 @@ Doposud známé výsledky
 
 Bonsmaa, Epping, a Hochstättler [@apx] dokázali, že optimalizační verze BPS je $\APX$-těžký problém,
 což je silnější tvrzení, než že rozhodovací verze je $\NP$-těžká.
-Za předpokladu, že $\P \neq \NP$, víme že kromě polynomiálního algoritmu na rozhodovací verzi nemůže existovat
+Za předpokladu $\P \neq \NP$ víme, že kromě polynomiálního algoritmu na rozhodovací verzi nemůže existovat
 ani polynomiální aproximační schéma na optimalizační verzi.
 
-Snadno nahlédneme, že rozhodovací problém patří do $\NP$. Když nám někdo dá přiřazení barev autům.
-V lineárním čase jsme schopni ověřit, že počet změn je dostatečně malý a od každého typu a barvy auta
+Snadno nahlédneme, že rozhodovací problém patří do $\NP$.
+Když nám někdo dá přiřazení barev autům,
+v lineárním čase jsme schopni ověřit, že počet změn je dostatečně malý a od každého typu a barvy auta
 je právě jeden výskyt. Tedy rozhodovací problém je $\NP$-úplný.
 
 Dále pak Gupta a spol. [@neaprox] ukázali, že za předpokladu  Unique games conjecture je NP-těžké i problém libovolně konstantně aproximovat.
@@ -236,7 +249,7 @@ ovšem aproximovatelnost se na nich chová drasticky jinak.
 V momentě, kdy jsou skoro všechny hrany v řezu, tak přidání další hrany do řezu skoro nezmění počet hran v něm. Ovšem odebrání hrany z ne-řezu bude mít velký vliv (procentuálně) na počet hran v ne-řezu.
 
 Vzhledem k předešlým výsledkům je na místě zkoumat různé heuristiky a obecně algoritmy, co
-jsou nás schopny k řešení alespoň částečně přiblížit.
+jsou nás schopny k optimálnímu řešení alespoň částečně přiblížit.
 
 Jedním z takových algoritmů je hladový algoritmus popsaný Andresem and Hoch\-stättlerem [@gr]:
 
@@ -271,7 +284,7 @@ fig.update_layout(
     showlegend=False
 )
 ```
-Graf střední hodnoty skóre hladového řešení $\delta_{\algo g}(n)$ v závislosti na $n$.
+Graf střední hodnoty relativního skóre hladového řešení $\delta_{\algo g}(n)$ v závislosti na $n$.
 :::
 
 U hladového řešení je tedy střední hodnota skóre přes uniformně náhodný vstup přesně vyčíslená.
@@ -308,13 +321,13 @@ musí použít aspoň $\Omega(n)$ změn barev.
 Nemůže tedy například existovat algoritmus, kterému by stačilo
 jen $\O(n / \log n)$ změn.
 To také říká, že odhadovat algoritmy pomocí $\lim_{n\to\infty} \gamma_{\alg}/n$,
-je alespoň co se týče asymptoticky dostačující, protože vystihuje
+je alespoň co se týče asymptotiky dostačující, protože vystihuje
 konstantu nejvýznačnějšího členu polynomiální aproximace.
 
 Dále si představíme několik algoritmů, které se snaží konstruktivně zlepšit horní odhad na $\delta^+$.
 
 ::: {c=box t=algo name="Rekurzivní hladové řešení" notation="rg"}
-Z řady aut odstraníme první auto a auto stejného typu.
+Z řady aut odstraníme první auto v řadě a druhé auto příslušného typu.
 Zbytek aut rekurzivně obarvíme a pak do řady přidáme odebranou dvojici tak,
 aby byl počet změn co možná nejmenší možný.
 :::
@@ -323,32 +336,32 @@ Autoři algoritmu, Andres and Hochstättler [@gr], o něm dokázali, že
 ${2\over 5}\ n - {8\over 15} \le \gamma_{\algo{rg}}(n)  \le {2\over 5}\ n + {7\over 10}$,
 tedy $\delta_{\algo{rg}} = 2/5 = 0.4$.
 
-Dále se o zlepšení tohoto algoritmu pokusili Hančl a kol.
+Dále se o zlepšení tohoto algoritmu pokusili Hančl a kol. [@docw].
 Ti si všimli, že ve výstupu rekurzivního řešení se občas stane,
 že přebarvením dvojic typů aut se zlepší skóre. Ukázali, že
 takových dvojic je vždy ve výstupu lineárně mnoho a z toho pak
-ukázali horní odhad $\delta^+ \le 0.4 - \varepsilon < 0.4$ (pro $\varepsilon$ zhruba $2\cdot 10^6$).
+ukázali horní odhad $\delta^+ \le 0.4 - \varepsilon < 0.4$ (pro $\varepsilon$ zhruba $2\cdot 10^{-6}$).
 
-Hančl a kol. přišli ještě s dalším způsobem, jak vylepšit rekurzivní hladové řešení.
+Hančl a kol. [@docw] přišli ještě s dalším způsobem, jak vylepšit rekurzivní hladové řešení.
 Při běhu hladového řešení se občas stane, že některá dvojice aut stejného typu
 si může prohodit barvy bez změny skóre řešení.
 Když přidáváme auto do okolí takovéto dvojice, v některých případech můžeme provést toto prohození
 a tím snížit počet nově vytvořených změn barev.
-Budeme si tedy bude udržovat některé z takovýchto dvojic
-a pokud se budeme přidávat auto do okolí evidované dvojice, tak, že
+Budeme si tedy udržovat některé z takovýchto dvojic
+a pokud budeme přidávat auto do okolí evidované dvojice tak, že
 prohození barev dané dvojice by pomohlo, prohodíme její barvy.
 
 Budeme pracovat nad rozšířenou abecedou barev o znak "$*$" reprezentující neurčenou barvu.
 Při rekurzi budeme udržovat invariant, že pro každý typ obě auta buď budou označeny $*$ a nebo ani jedno z nich nebude označeno $*$ a pak nutně budou mít různé barvy.
 Navíc bude platit, že $*$ nikdy není na okrajích a nejsou dvě vedle sebe.
-Specificky tedy na $*$ se budeme přebarvovat dvojice aut v momentě, kdy získá všechny sousedy.
+Specificky tedy na $*$ budeme přebarvovat dvojici aut v momentě, kdy získá všechny sousedy.
 
 Pro popis algoritmu zavedeme notaci $N(i)$,
 což bude reprezentovat multimnožinu barev aut sousedících s autem na pozici $0<i<2n-1$,
 tedy $\{c(i-1), c(i+1)\}$.
 
 ::: {c=box t=algo name="Hvězdičkové rekurzivní řešení" notation="rsg"}
-Bude pracovat nad rozšířenou škálou barev $\{0,1,*\}$.
+Budeme pracovat nad rozšířenou škálou barev $\{0,1,*\}$.
 Ze vstupu odebereme auta typu $t_0$ a zarekurzíme se na zbytek.
 Tím získáme nějaké obarvení, které může použít na původní vstup s tím,
 že auta typu $t_0$ zatím nebudou obarvená, ty dobarvíme dle následujících pravidel:
@@ -395,7 +408,7 @@ Z něj pochází motivace k binární verzi.
 V řadě je $m$​ aut $n$ různých typů -- nyní však již od každého typu libovolný počet.
 Dále máme definováno pro každou kombinaci typu a barvy (kterých také může být více než dvě), kolik aut daného typu má být nabarveno
 na danou barvu.
-Chceme tedy nají obarvení aut tak, aby počet změn barev v řadě byl co nejmenší.
+Chceme tedy najít obarvení aut tak, aby počet změn barev v řadě byl co nejmenší.
 :::
 
 Binární verze problému je tedy speciální případ obecného paint shop problému,
@@ -436,7 +449,7 @@ Nejprve zavedeme a připomeneme notaci důležitou v této kapitole.
 Nechť $\R^{n\times m}$ značí množinu $n$ řádkových $m$ sloupcových matic
 složených z reálných čísel.
 Řádky i sloupce indexujeme od $0$,
-tedy matice $A\in R^{n\times m}$ obsahuje prvky $A_{i,j}$ pro všechna $0\le i < n$ a $0 \le j < m$.
+tedy matice $A\in \R^{n\times m}$ obsahuje prvky $A_{i,j}$ pro všechna $0\le i < n$ a $0 \le j < m$.
 Nechť $\SYM_n = \{X \in \R^{n\times n} \mid x_{i,j} = x_{j,i} \hbox{\ pro všechna\ } 0 \le i,j < n\}$ je třída všech symetrických matic a nechť $X \circ Y = \sum_{0\le i<n} \sum_{0\le j<0} x_{i,j} y_{i,j}$ značí součet součinu matic po složkách.
 Nakonec $X \succeq 0$ bude značit skutečnost, že matice $X$ je pozitivně semidefinitní (bude vysvětleno později).
 
@@ -481,7 +494,7 @@ Představíme si pravděpodobnostní aproximační algoritmus založený na semi
 
 ::: {c=box t=task}
 Nechť $G=(V, E)$ je graf s hranami ohodnocenými nezápornými čísly dle $h: E \rightarrow \R^+_0$.
-Řezem grafu rozumím rozdělení vrcholů na dvě disjunktní množiny $A \cup B = V$.
+Řezem grafu rozumíme rozdělení vrcholů na dvě disjunktní množiny $A \cup B = V$.
 Hodnotou daného řezu je pak součet cen hran vedoucích mezi $A$ a $B$. Tedy:
 $$
 H(A,B) = \sum_{\{u,v\}\in E\atop u\in A, v\in B} h({u,v})
@@ -504,8 +517,6 @@ Triviální algoritmus je $0.5$ aproximační pravděpodobnostní algoritmus.
 :::
 
 ::: {c=proof}
-Algoritmus zjevně běží v polynomiálním čase.
-Dále ukážeme, že ve střední hodnotě bude součet řešení alespoň $1/2$ optimálního součtu vah hran.
 Každá hrana bude v řezu s pravděpodobností $1/2$ -- při umisťování druhého vrcholu dané hrany
 máme pravděpodobnost $1/2$, že ho umístíme do stejné množiny a tedy hrna nebude součásti řezu
 a pravděpodobnost $1/2$ že do opačné a tedy bude součástí řezu.
@@ -535,7 +546,7 @@ různá znaménka a $0$ pokud stejná.
 
 Takovýto optimalizační problém bohužel ani pomocí semidefinitního programování neumíme řešit.
 Na to, abychom uměli vyjádřit nějaký součin, musíme použít semidefinitního programování v dekomponovaném tvaru.
-Pak ale místo toho, abychom měli pro každý vektor jen jednu proměnnou budeme mít pro každý vrchol celý vektor proměnných
+Pak ale místo toho, abychom měli pro každý vektor jen jednu proměnnou, budeme mít pro každý vrchol celý vektor proměnných
 a místo součinu proměnných budeme mít skalární součin těchto vektorů.
 Již ale současně neumíme zařídit, aby tyto vektory byly buď $(1,0,\dots,0)$ nebo $(-1,0,\dots,0)$.
 Můžeme ale přidat podmínku na to, aby délka každého vektoru byla $1$.
@@ -569,18 +580,18 @@ To nám zaručí, že dvojice bodů daleko od sebe budou mít velkou pravděpodo
 Semidefinitní programování se tedy snaží dostat dvojice bodů odpovídající vrcholům spojených hranou daleko od sebe a
 podle toho se zvyšuje pravděpodobnost toho, že vrcholy budou v jiných množinách a tedy hrana bude v řezu.
 
-Výběr nadroviny a rozdělování bodů jde implementovat pomocí výběru vektoru $\vec{z}$ kolmého na nadrovinu. Pro každý bod pak stačí
+Výběr nadroviny a rozdělování bodů jde implementovat pomocí výběru vektoru $\vec{z}$ kolmého na nadrovinu. Pro každý bod pak stačí
 spočítat skalární součin se $\vec{z}$ a podle znaménka víme,
 do kterého poloprostoru patří.
-Pokud vybereme uniformě náhodný jednotkový vektor, tak jsme uniformám náhodně vybrali nadrovinu.
-Jednotkový vektor můžeme generovat tak, že vygenerujeme náhodný vektor z normálního rozdělení a pak ho znormujeme.
+Pokud vybereme uniformě náhodný jednotkový vektor, tak jsme uniformě náhodně vybrali nadrovinu.
+Jednotkový vektor můžeme generovat tak, že vygenerujeme náhodný vektor nezávisle po složkách z normálního rozdělení, a pak ho znormujeme.
 Povšimne si, že normalizace ani není potřeba,
 protože to na znaménku součinů nic nemění.
 
 Nyní pojďme precizněji spočítat pravděpodobnost toho, že se dvojice bodů (vektorů) $\vec{u}$,
 $\vec{v}$ rozdělí náhodnou nadrovinou $\rho$ v závislosti na hodnotě skalárního
 součinu mezi nimi.
-Můžeme se podívat na rovinu, ve které leží počátek a oba vektory $\vec{u}$, $\vec{v}$.
+Můžeme se podívat na rovinu, ve které leží počátek a oba vektory $\vec{u}$, $\vec{v}$ (viz obrázek [](#gw-cut)).
 Průnik náhodné nadroviny s touto rovinou tvoří rovnoměrně náhodně vybranou přímku procházející počátkem.
 
 ::: {#gw-cut c=figure}
@@ -598,7 +609,7 @@ label("$\vec{v}$", v, E);
 draw(scale(0.2)*rotate(-15)*subpath(unitcircle, 0, 85/90));
 label("$\alpha$", (0.2, 0), 0.7*ENE);
 ```
-Znázornění řezu rovinou obsahující $vec{u}$ i $vec{v}$.
+Znázornění řezu rovinou obsahující $vec{u}$ i $vec{v}$. TODO
 :::
 
 
@@ -662,13 +673,13 @@ Vrcholům jedné množiny přidělíme vektory $(1,0,\dots,0)$ a druhé $(-1,0,\
 Bohužel na rozdíl od lineárního programování, u semidefinitního programování nejsme schopní v polynomiálním čase najít optimální řešení.
 Naštěstí však platí, že v polynomiálním čase za určitých podmínek jsme schopní se mu libovolně přiblížit.
 Přesněji řečeno, pro každé $\varepsilon > 0$ jsme schopní najít řešení s účelovou funkcí nejdále $\varepsilon$ od optima.
-Ovšem musí platit, že všechny přípustná řešení jsou dostatečně málá.
-Přesněji řečeno, musí platit, že Fobeniova norma všech přípustných matic je omezena konstantou s polinomiální délkou zápisu.
-Tohoto výsledku jde dosáhnout pomocí elipsoidové metody, která má nejlepší teoretické výsledky. V prakxi se však často používají jiné algoritmy.
+Ovšem musí platit, že všechna přípustná řešení jsou dostatečně malá.
+Přesněji řečeno, musí platit, že Fobeniova norma všech přípustných matic je omezena konstantou s polynomiální délkou zápisu.
+Tohoto výsledku jde dosáhnout pomocí elipsoidové metody, která má nejlepší teoretické výsledky. V praxi se však často používají jiné algoritmy.
 Všechny naše programy budou splňovat podmínky na řešení, protože každá z hodnot hledané matice nutně bude ležet v intervalu $[-1, -1]$.
 
 ::: {c=box t=theorem}
-Goemans-Williamsonův algoritmus je $0.878$ pravděpodobnostní aproximační algoritmus.
+Goemans-Williamsonův algoritmus je pravděpodobnostní $0.878$-aproxi\-mační algoritmus.
 :::
 ::: {c=proof}
 Využitím předešlých pozorování a elipsoidové metody získáme:
@@ -690,10 +701,6 @@ vynutíme $\vec{y_i} = -\vec{y_j}$. Na to nám stačí jediná podmínka -- ří
 
 Účelovou funkcí pak řekneme, že sousední auta mají preferovat stejnou barvu, tedy jejich body na sféře mají být blízko sebe, což znamená, že skalární součin má být co největší.
 
-Finální program 
-
-semidefinitní program v dekomponovaném tvaru tedy vypadá takto:
-
 :::{c=box t=algo name="Řešení pomocí semidefinitního programování" notation="sdp"}
 \hfil{\penalty-10000}\relax Vyřešíme následující semidefinitní program v dekomponovaném tvaru:
 $$\progline{maximalizuj}{\sum_{0\le i<2n-1} \vec{y_i}^{\rm T} \vec{y_{i+1}}}{}$$
@@ -701,7 +708,7 @@ $$\progline{za podmínek}{\vec{y_{a_{i,0}}} = -\vec{y_{a_{i,1}}}}{0\le i < n}$$
 $$\progline{}{|y_i| = 1}{0\le i < 2n}$$
 Dále uniformě náhodně zvolíme jednotkový vektor $z\in \R^{2n}$
 a červeně obarvíme právě ty auta $i$, pro které $y_i^{\rm T} z \ge 0$.
-Náhodných výběrů vektoru je možné provézt vícero a pak vybrat nejlepší nalezené řešení.
+Náhodných výběrů vektoru je možné provést vícero a pak vybrat nejlepší nalezené řešení.
 :::
 
 Pro každou dvojici do účelové funkce přičteme číslo mezi $-1$ a $1$, kde $1$ značí, že vektory jsou stejné,
@@ -709,7 +716,7 @@ a $-1$, že jsou protilehlé.
 Účelovou funkci můžeme ekvivalentně zapsat jako
 $$ \hbox{minimalizuj}\qquad \sum_{0\le i < 2n-1} \frac{1}{2} - \frac{\vec{y_i}^{\rm T} \vec{y_{i+1}}}{2} = \frac{2n-1}2 - \frac12 \sum_{0 \le i < 2n-1} \vec{y_i}^{\rm T} \vec{y_{i+1}} $$
 
-Nyní tedy pro každou dvojici sousedních aut sčítáme číslo mezi $0$ a $1$, kde $0$ nastane pro stejné vektory
+Nyní tedy pro každou dvojici sousedních aut přičítáme číslo mezi $0$ a $1$, kde $0$ nastane pro stejné vektory,
 mezi nimiž nikdy nebude změna barvy a $1$ nastane v případě opačných vektorů, mezi nimiž se nutně barva změní.
 Účelovou funkci se snažíme minimalizovat.
 
@@ -717,14 +724,14 @@ mezi nimiž nikdy nebude změna barvy a $1$ nastane v případě opačných vekt
 Optimum semidefinitního programu, který minimalizuje účelovou funkci $\frac{2n-1}2 - \frac12 \sum_{0 \le i < 2n-1} \vec{y_i}^{\rm T} \vec{y_{i+1}}$ je menší rovno počtu změn v optimálním obarvení aut.
 :::
 ::: {c=proof}
-Podíváme se na optimální obarvení aut a každému červenému autu přiřadit vektor $(1,0,\dots,0)$ a modrému $(-1,0,\dots,0)$.
+Podíváme se na optimální obarvení aut a každému červenému autu přiřadíme vektor $(1,0,\dots,0)$ a modrému $(-1,0,\dots,0)$.
 Toto je validní řešení semidefinitního programu.
 Účelová funkce za každou změnu barev přičte $1$ a zbytek součtu je $0$, takže její hodnota je přesně počet změn barev.
 :::
 
 Nyní by se hodilo odhadnout střední hodnotu počtu změn barev stejně jako u maximálního řezu.
-Jeho důkaz vycházel z pozorování ohledně poměru pravděpodobností výběru a účelové funkce.
-Přesněji řečeno z toho, že tento poměr umíme zdola odhadnout.
+Jeho důkaz vycházel z pozorování ohledně poměru pravděpodobností výběru a účelové funkce,
+přesněji řečeno z toho, že tento poměr umíme zdola odhadnout.
 Ovšem v našem případě místo maximalizace děláme minimalizaci účelové funkce a pravděpodobnosti.
 Tedy abychom mohli tvrdit, že pravděpodobnost je menší než nějaký násobek účelové funkce,
 potřebovali bychom horní odhad poměru. Ovšem tento poměr je neomezený (viz obrázky [](#gw-func) a [](#gw-frac)).
@@ -773,9 +780,9 @@ Střední hodnota (vzhledem k náhodným bitům generovaným algoritmem)
 počtu změn v $\algo{sdp}$ řešení je nejvýše o $0.212n$ horší než optimum.
 :::
 ::: {c=proof}
-Když je účelová funkce pro sousední dvojici aut je $r$, tak pravděpodobnost změny barev je nejvýše $d + r$.
+Když účelová funkce pro sousední dvojici aut je $r$, tak pravděpodobnost změny barev je nejvýše $d + r$.
 Sečtením přes všechny hrany (z linearity středních hodnot) tedy získáme, že
-střední hodnota součtu změn je nejvýše $c(2n-1) + R$, kde $R = \sum_i^{2n-1} \frac{1}{2} - \frac{\vec{y_i}^{\rm T} \vec{y_{i+1}}}{2}$, tedy jedno z ekvivalentních vyjádření účelové funkce.
+střední hodnota součtu změn je nejvýše $d(2n-1) + R$, kde $R = \sum_i^{2n-1} \frac{1}{2} - \frac{\vec{y_i}^{\rm T} \vec{y_{i+1}}}{2}$, tedy jedno z ekvivalentních vyjádření účelové funkce.
 
 Celkově tedy víme:
 $$ \hskip -2pt \E[\gamma_{\algo{sdp}}(\alpha)] \le  2dn + \hbox{Řeš. SDP} \le 2dn + \hbox{Opt. SDP} + \varepsilon \le 2dn + \gamma(\alpha) + \varepsilon$$
@@ -811,15 +818,115 @@ proto v implementační části práce využijeme této formy programu.
 Měření SDP řešení
 =================
 
+Součástí práce je implementace algoritmů řešících Binární paint shop problém.
+Každý z nich byl následně spuštěn pro různé velikosti, pokaždé na 100 nezávisle náhodně vybraných vstupech.
+Celý test běžel jedno vláknově zhruba dva dny a využíval nejvýše 16 GB operační paměti.
+Na následujících stranách jsou zpracovaná různá naměřená data.
+
+Praktické řešení semidef. programů
+-----------------------------------------
+U triviálních algoritmů byla implementace poměrně přímočará.
+Ovšem u řešení semidefinitního programování je většina složitosti algoritmu schovaná právě v řešení semidefinitních programů,
+což už svojí složitostí nepatří mezi algoritmy, které bych chtěl (re)implementovat.
+Proto je nutné se spolehnout na funkčnost již existujících implementací.
+Bohužel kvalita dostupných řešičů semidefinitních programů je poměrně nízká.
+
+
+### SDPA-C
+Jedním z použitých programů byl SDPA-C [@sdpa-web].
+Jedná se o knihovnu v C`++`
+založenou na metodě vnitřních bodů v primárním a duálním problému. Dle autorů projektu [@sdpa-web]:
+
+::: {.group lang=cs}
+> SDPA (SemiDefinite Programming Algorithm) is one of the most efficient and stable software packages for solving SDPs based on the primal-dual interior-point method. It fully exploits the sparsity of given problems.
+:::
+
+Pro účely práce byla použita verze SDPA-C ze dne 2023-06-21 (soubor `sdpa-c.7.3.8.src.20180125.tar.gz`).
+Kompilace je poměrně komplikovaná.
+Jednak vyžaduje velké množství nainstalovaného software (například překladač Fortranu), ale také poskytnutý `Makefile` není plně kompatibilní s moderními verzemi překladačů.
+
+Bohužel i po úspěšné kompilaci stále není vyhráno.
+Dodaný program přeložený aktuálním kompilátorem bohužel
+nefunguje.
+
+Při spuštění i na malých vstupech program rychle spadne s chybou Segmentation Fault
+ve funkci `Newton::compute_bMatgVec_dense_threads_SDP`.
+
+Při následujícím ladění programu bylo zjištěno, že se program zacyklí v dané funkci ve smyčce, při které inkrementuje hodnotu proměnné
+`Column_Number` až do doby, kdy přeteče, což už přímo vede k pádu programu.
+Pohledem na kód to vypadá, že toto by se nemělo dít.
+Program už mnohokrát měl ukončit smyčku a doběhnout na konec funkce, ovšem po přidání dostatečného počtu debugovacích výpisů je
+je vidět, že program cyklus opustí, provede příkazy mezi cyklem a koncem funkce a pak se zase objeví uprostřed cyklu.
+
+Problém byl v tom, že funkce vracející `void*`
+dle normy [@cpp-norm] bodu 6.6.3
+musí skončit pomocí `return` a nemůže jen tak opustit funkci dojitím na její konec.
+Pokud se tak stane, jedná se o nedefinované chování,
+nikoliv jen o nedefinovanou hodnotu navrácenou z funkce.
+Kdyby se jednalo jen o nedefinovanou hodnotu,
+tak se nic zásadního neděje. Funkce může vrátit cokoliv, ale to je nám jedno, protože výsledek se ignoruje.
+
+Ovšem jelikož se jedná o nedefinované chování, překladač může program
+přeložit tak, že v takovémto případě udělá prakticky cokoliv.
+A v tomto případě optimalizace překladače přeložili program tak,
+že v případě opuštění funkce se vykonávání programu vrátí zpět dovnitř a pokračuje se v iterování smyčky.
+To je důsledkem toho, jakým způsobem se snaží překladač optimalizovat kód.
+Překladače nemusí dodržovat naprogramovanou strukturu programu.
+Tedy není problém přesunout část za smyčkou do ní na místo, kde se smyčka opouští.
+No a když překladač ví, že v korektním programu by se tudy nemělo opouštět funkci, nemusí se překladač obtěžovat umísťováním explicitního návratu z funkce na dané místo.
+
+Naštěstí oprava tohoto problému je přímočará -- stačí do takovýchto funkcí explicitně dopsat `return NULL;`.
+
+
+Toto bohužel není jediný problém s SDPA-C.
+Na některých vstupech knihovna dojde do stavu, kdy nemá semidefinitní matici a výpočet spadne s následující chybou:
+
+TODO SAZBA blockquote
+```
+CHOLMOD warning: matrix not positive definite.
+file: ../Supernodal/t_cholmod_super_numeric.c line: 911
+getMinEigenValue:: cannot decomposition ::
+line 193 in sdpa_linear.cpp
+```
+
+Tedy během výpočtu program něco spočte špatně a jako mezivýsledek mu vyjde matice, co není pozitivně semidefinitní, se kterou již dále nejde pokračovat.
+Příčinu této chyby se bohužel nepodařilo odhalit, protože na rozdíl od předchozího problému vůbec není jasné, kde začít hledat.
+Detekce nesemidefinitnosti matice totiž může být v úplně jiné části kódu, než kde nastane chyba.
+
+Problém se projevuje například na vstupu s $n=5$ a seedem $19$.
+
+Další problém (nebo ten stejný) se projevuje zejména u větších vstupů.
+Uprostřed algoritmu se také objeví chybová hláška o nesemidefinitnosti matice.
+Následně program udělá mnoho iterací s nekonečnou účelovou funkcí, dokud se nepřekročí maximální počet iterací a pak je vrácena matice
+ze samých $\pm \infty$, což dokonce porušuje zadané podmínky.
+Toto se stává například na seedu $18$ pro $n = 150$.
+
+Vzhledem k výše uvedeným problémům dává smysl se porozhlédnout po alternativách.
+
+### Sage
+
+SageMath  je dle oficiálních stránek [@sagemath] open-source software pro matematické výpočty založený na rozšířené syntaxi pythonu,
+takže je poměrně snadné ho využívat i jako programovací jazyk.
+Sage mimo jiné obsahuje rozhraní pro řešení semidefinitních programů.
+Rozhraní je navrženo tak, aby bylo schopné pracovat s více různými backendy pro řešení semidefinitních programů.
+Bohužel z dokumentace [@sage-semidef-doc] nebylo zřejmé, jaké backendy sage podporuje.
+Při zavolání `default_sdp_solver("")` se objeví chybová hláška, která tvrdí, že backend by mělo jít nastavit na
+`CVXOPT` (což je výchozí hodnota) nebo `Matrix`, případně uživatelem dodanou třídu.
+Ovšem při přepnutí na `Matrix` spuštění řešení spadne na `NotImplementedError`, tedy zdá se, že ani tento backend není implementovaný (alespoň ve verzi, co mám k dispozici) a tedy jediná možnost je `CVXOPT`.
+
+Drobným problémem je, že dle dokumentace [@sage-semidef-doc] rozhraní sage vyžaduje formulování vstupu jako primárního semidefinitního programu,
+ovšem náš algoritmus je založený na řešení duálního semidefinitního programu.
+Mezi nimi však lze snadno přecházet pomocí triviální úpravy, ovšem výsledný kód pak vypadá velice neintuitivně.
+
 Hodnoty skalárních součinů
 --------------------------
 
-V odhadu střední hodnoty počtu změn barev v řešení jsme využívali toho, že funkce rozdílu pravděpodobnosti řezu a účelové funkce (funkce $f$) je nejvýše $d = 0.1053$.
+V odhadu střední hodnoty počtu změn barev v $\algo{sdp}$ řešení jsme využívali toho, že funkce rozdílu pravděpodobnosti řezu a účelové funkce (funkce $f$) je nejvýše $d = 0.1053$.
 Ovšem tato funkce nenabývá takto vysokých hodnot zdaleka všude, na polovině definičního oboru je dokonce záporná (viz obrázek [](#sdp-diff)). Kdyby tedy alespoň část optimalizovaných skalárních součinů se vyskytovala mimo oblast, kde $f$ nabývá vysokých hodnot, šel by odhad zlepšit.
 
 Bohužel dle naměřených dat to vypadá, že hodnoty skalárních součinů se
 koncentrují pouze poblíž maxima $f$. Viz obrázek [](#scalar_products_200).
-Tento výsledek intuitivně dává smysl, protože jenom tato může semidefinitní
+Tento výsledek intuitivně dává smysl, protože jenom takto může semidefinitní
 program dosáhnout lepší účelové funkce než počet změn barev v optimálním řešení.
 Ovšem náš jediný dolní odhad je hodnota semidefinitního programu a tedy nejsme schopní více přiblížit dolní a horní odhad k sobě.
 
@@ -846,7 +953,7 @@ Distribuce skalárních součinů $100$ běhů algoritmu pro $n=200$.
 :::
 
 Z grafu jde vidět, že skoro nikdy semidefinitní program neumístí sousední body do protilehlých částí. Drobnou výjimku tvoří hodnota skalárního součinu okolo $-1$, kterých semidefinitní program
-za $100$ bodů vyrobil zhruba $100$.
+za $100$ běhů vyrobil zhruba $100$.
 K tomuto mohl být donucen existencí dvojic aut stejného typu hned vedle sebe, kdy nemá jinou možnost než mezi nimi mít skalární součin $-1$.
 
 ::: {c=box t=lemma}
@@ -855,15 +962,14 @@ Střední hodnota počtu sousedních aut stejného typu je $1$.
 ::: {c=proof}
 Pro každý typ auta máme ${2n \choose 2} = {2n(2n-1) \over 2} = n (2n-1)$ možných pozic, kde se mohou
 nacházet a z toho $2n-1$ z nich jsou vedle sebe.
-Střední hodnota indikátoru souslednosti aut daného typu je tedy ${2n-1 \over n (2n-1)} = n$.
+Střední hodnota indikátoru souslednosti aut daného typu je tedy ${2n-1 \over n (2n-1)} = {1\over n}$.
 Z linearity střední hodnoty tedy počet sousedících aut stejného typu je $n/n = 1$.
 :::
 
-Ve 100 vstupech by tedy sousedních aut stejného typu mělo být ve střední hodnotě zhruba 100, což z části vysvětluje pozorovanou anomalitu.
+Ve 100 vstupech by tedy sousedních aut stejného typu mělo být ve střední hodnotě zhruba 100, což z části vysvětluje pozorovanou anomálii.
 Není však vyloučeno, že hodnoty skalárního součinu $-1$ nebo blízké program dosáhne i jinak.
 
 
-
 Dimenze řešení
 --------------
 
@@ -939,13 +1045,13 @@ fig = g.nonzero_coords(50, range(2001, 2101))
 Počet vektorů s danou souřadnicí větší než $0.05$ pro $n=50$.
 :::
 
-Nevíme o žádné hypotéze, proč program generuje řešení s malou dimenzí ani není jasné, jestli či jak by toho šlo využit pro získání lepšího řešení či dolního odhadu.
-Z naměřených dat však vychází, že průměrná dimenze je mnohem menší než $n$, ovšem nejspíše není omezena žádnou konstantou, tedy s rostoucím $n$ také roste, ale mnohem pomaleji.
-Hypotéza zní, že průměrná dimenze se pohybuje okolo $\log_2 n - 3$.
-
+Nevíme o žádné hypotéze, proč program generuje řešení s malou dimenzí.
+Taktéž není jasné, jestli či jak by toho šlo využit pro získání lepšího řešení či dolního odhadu.
+Z naměřených dat zobrazených na obrázcích [](#max_coords_400) až [](#nonzero_coords_50) na následujících stranách však vychází, že průměrná dimenze je mnohem menší než $n$, ovšem nejspíše není omezena žádnou konstantou, tedy s rostoucím $n$ také roste, ale mnohem pomaleji.
+Hypotéza zní, že průměrná dimenze leží v $\Theta(\log n)$.
 
 Malá dimenze má ale zásadní výhodu pro vizualizaci řešení, protože trojrozměrný prostor (tedy sféru dimenze 2) si zvládne člověk snadno představit. Z čehož plyne, že zhruba polovinu řešení pro $n=50$ jsme schopni
-zakreslit jen s drobným zkreslením.
+zakreslit jen s drobným zkreslením, tak, jak je ukázáno na obrázku [](#sdp-visualize_50).
 
 ::: {#sdp-visualize_50 c=figure}
 ```python {.run}
@@ -956,115 +1062,16 @@ return processor.transform([pf.CodeBlock(sdp_visualize.visualize("semidef_prog_n
 Vizualizace jednoho z řešení pro $n=50$, které se vejde do 3D.
 :::
 
-Praktické řešení semidef. programů
------------------------------------------
-Ve své práci jsem se pokusil implementovat jednotlivé algoritmy řešící Binární paint shop problém.
-U triviálních algoritmů byla implementace poměrně přímočará.
-Ovšem u řešení semidefinitního programování je většina složitosti algoritmu schovaná právě v řešení semidefinitních programů,
-což už svojí složitostí nepatří mezi algoritmy, které bych chtěl (re)implementovat.
-Proto je nutné se spolehnout na funkčnost již existujících implementací.
-Bohužel kvalita dostupných řešičů semidefinitních programů je poměrně nízká.
-
-
-### SDPA-C
-Jedním z použitých programů byl SDPA-C [@sdpa-web].
-Jedná se o knihovnu v C`++`
-založenou na metodě vnitřních bodů v primárním a duálním problému. Dle autorů projektu [@sdpa-web]:
-
-::: {.group lang=cs}
-> SDPA (SemiDefinite Programming Algorithm) is one of the most efficient and stable software packages for solving SDPs based on the primal-dual interior-point method. It fully exploits the sparsity of given problems.
-:::
-
-Stáhl jsem si verzi SDPA-C (soubor `sdpa-c.7.3.8.src.20180125.tar.gz`) ze dne 2023-06-21.
-Kompilace je poměrně komplikovaná.
-Jednak vyžaduje velké množství nainstalovaného software (například překladač Fortranu), ale také poskytnutý `Makefile` není plně kompatibilní s moderními verzemi překladačů.
-
-Bohužel i po úspěšné kompilaci stále není vyhráno.
-Dodaný program přeložený aktuálním kompilátorem bohužel
-nefunguje.
-
-Při spuštění i na malých vstupech program rychle spadne s chybou segmentation fail
-ve funkci `Newton::compute_bMatgVec_dense_threads_SDP`.
-
-Při následujícím debugování jsem zjistil, že se program zacyklí v dané funkci ve smyčce, při které inkrementuje hodnotu proměnné
-`Column_Number` až do doby, kdy přeteče, což už přímo vede k pádu programu.
-Pohledem na kód to vypadá, že toto by se nemělo dít.
-Program už mnohokrát měl ukončit smyčku a doběhnout na konec funkce, ovšem po přidání dostatečného počtu debugovacích výpisů je
-je vidět, že program cyklus opustí, provede příkazy mezi cyklem a koncem funkce a pak se zase objeví uprostřed cyklu.
-
-Problém byl v tom, že funkce vracející `void*`
-dle normy [@cpp-norm] bodu 6.6.3
-musí skončit pomocí `return` a nemůže jen tak opustit funkci dojitím na její konec.
-Pokud se tak stane, jedná se o nedefinované chování,
-nikoliv jen o nedefinovanou hodnotu navrácenou z funkce.
-Kdyby se jednalo jen o nedefinovanou hodnotu,
-tak se nic zásadního neděje. Funkce může vrátit cokoliv, ale to je nám jedno, protože výsledek se ignoruje.
-Ovšem jelikož se jedná o nedefinované chování překladač může program
-přeložit tak, že v takovémto případě udělá prakticky cokoliv.
-A v tomto případě optimalizace překladače přeložili program tak,
-že v případě opuštění funkce se vykonávání programu vrátí zpět dovnitř a pokračuje se v iterování smyčky.
-To je důsledkem toho, jakým způsobem se snaží překladač optimalizovat kód.
-Překladače nemusí dodržovat naprogramovanou strukturu programu.
-Tedy není problém přesunout část za smyčkou do ní na místo, kde se smyčka opouští.
-No a když překladač ví, že v korektním programu by se tudy nemělo opouštět funkci, nemusí se překladač obtěžovat umísťováním explicitního návratu z funkce na dané místo.
-
-Naštěstí oprava tohoto problému je přímočará -- stačí do takovýchto funkcí explicitně dopsat `return NULL;`.
-
-
-Toto bohužel není jediný problém s SDPA-C.
-Na některých vstupech knihovna dojde do stavu, kdy nemá semidefinitní matici a výpočet spadne s následující chybou:
-
-TODO SAZBA blockquote
-```
-CHOLMOD warning: matrix not positive definite.
-file: ../Supernodal/t_cholmod_super_numeric.c line: 911
-getMinEigenValue:: cannot decomposition ::
-line 193 in sdpa_linear.cpp
-```
-
-Tedy během výpočtu program něco spočte špatně a jako mezivýsledek mu vyjde matice, co není semidefinitní, se kterou již dále nejde pokračovat.
-Příčinu této chyby se mi bohužel nepodařilo odhalit, protože na rozdíl od předchozího problému vůbec není jasné, kde začít hledat.
-Detekce nesemidefinitnosti matice totiž může být v úplně jiné části kódu, než kde nastane chyba.
-
-Problém se projevuje například na vstupu s $n=5$ a seedem $19$.
-
-Další problém (nebo ten stejný) se projevuje zejména u větších vstupů.
-Uprostřed algoritmu se také objeví chybová hláška o nesemidefinitnosti matice.
-Následně program udělá mnoho iterací s nekonečnou účelovou funkcí dokud se nepřekročí maximální počet iterací a pak je vrácena matice
-ze samých $\pm \infty$, což dokonce porušuje zadané podmínky.
-Toto se stává například na seedu $18$ pro $n = 150$.
-
-Vzhledem k výše uvedeným problémům jsem se rozhodl přestat využívat SDPA-C a podívat se po alternativách.
-
-### Sage
-
-SageMath  je dle oficiálních stránek [@sagemath] open-source software pro matematické výpočty založený na rozšířené syntaxi pythonu,
-takže je poměrně snadné ho využívat i jako programovací jazyk.
-Sage mimo jiné obsahuje rozhraní pro řešení semidefinitních programů.
-Rozhraní je navrženo tak, aby bylo schopné pracovat s více různými backendy pro řešení semidefinitních programů.
-Bohužel v dokumentaci se mi nepodařilo pořádně najít, jaké backendy sage podporuje.
-Při zavolání `default_sdp_solver("")` se objeví chybová hláška, která tvrdí, že backend by mělo jít nastavit na
-`CVXOPT` (což je výchozí hodnota) nebo `Matrix`, případně uživatelem dodanou třídu.
-Ovšem při přepnutí na `Matrix` spuštění řešení spadne na `NotImplementedError`, tedy zdá se, že ani tento backend není implementovaný (alespoň ve verzi, co mám k dispozici) a tedy jediná možnost je `CVXOPT`.
-
-Drobným problémem je, že dle dokumentace [@sage-semidef-doc] rozhraní sage vyžaduje formulování vstupu jako primárního semidefinitního programu,
-ovšem náš algoritmus je založený na řešení duálního semidefinitního programu.
-Mezi nimi však lze snadno přecházet pomocí triviální úpravy, ovšem výsledný kód pak vypadá velice neintuitivně.
+\vfil\supereject
 
 ## Časová složitost
 
-Celý algoritmus má polynomiální časovou složitost, protože
-vstupem semidefiního programu je polynomiálně mnoho čísel konstantní velikosti.
+Víme, že existuje implementace algoritmu $\algo{sdp}$ s polynomiální časové složitosti (za použití elipsoidové metody).
+Použité řešiče však využívají jiných metod řešení semidefinitních programů.
+Bohužel ani jeden z nich moc neslibuje, jakou přesně složitost má.
+Proto je na místě změřit, jak rychlé řešení jsou.
 
-Řešení založená na semidefiním programování nemůže být moc rychlé.
-Již samotný vstup pro řešič semidefinitních programů má kubickou složitost vzhledem k délce vstupu Binárního paint shop problému.
-Program totiž obsahuje $n$ podmínek na délku vektoru
-a každá z nich se zapisuje pomocí matice $n \times n$.
-
-
-
-
-::: {#tmp c=figure}
+::: {#tmp2 c=figure}
 ```python {c=plotly}
 from bakalarka import g, data_lib
 
@@ -1072,73 +1079,69 @@ data = g.load_main_test()
 d = data_lib.group_by_n(data.pipelines["semidef_prog_sage.sage(10, CVXOPT)"])
 
 fig = go.Figure(data=[go.Box(
-    x=[n for _ in dd],
-    y=[i.score/n for i in dd],
-    name=f"{n}"
-    ) for n, dd in d.items()])
+    x=[i.n for i in d],
+    y=[i.resources_cpu_time_s for i in d],
+    name=name
+    ) for d,name in [
+        [data.pipelines["semidef_prog(10)"], "SDPA-C"],
+        [data.pipelines["semidef_prog_sage.sage(10, CVXOPT)"], "Sage"],
+    ]])
 
 fig.update_layout(
     xaxis=dict(showgrid=False, type="log"),
-    yaxis=dict(range=[0, 1]),
-    showlegend=False
+    yaxis=dict(type="log"),
 )
 ```
-
-Naměřená závislost skóre SDP řešení ($\delta_{\algo{sdp}}$) na velikosti vstupu.
+Závislost času řešení na velikosti vstupu.
 :::
 
-::: {#tmp2 c=figure}
+Skóre
+-----
+
+::: {#tmp c=figure}
 ```python {c=plotly}
 from bakalarka import g, data_lib
 
 data = g.load_main_test()
-d = data_lib.group_by_n(data.pipelines["semidef_prog_sage.sage(10, CVXOPT)"])
+hd = data_lib.group_by_n(data.pipelines["semidef_prog_sage.sage(10, CVXOPT)"])
 
 fig = go.Figure(data=[go.Box(
     x=[i.n for i in d],
-    y=[i.resources_cpu_time_s for i in d],
+    y=[i.score/i.n for i in d],
     name=name
     ) for d,name in [
-        [data.pipelines["semidef_prog(10)"], "SDPA-C"],
-        [data.pipelines["semidef_prog_sage.sage(10, CVXOPT)"], "Sage"],
+        [data.pipelines["semidef_prog(10)"], "sdp – SDPA-C"],
+        [data.pipelines["semidef_prog_sage.sage(10, CVXOPT)"], "sdp – Sage"],
+        [data.pipelines["rg"], "rg"],
+        [data.pipelines["rsg"], "rsg"],
     ]])
 
+fig.add_hline(y=0.34,
+              annotation_text="0.34", annotation_position="top left",
+              fillcolor="green")
 fig.update_layout(
     xaxis=dict(showgrid=False, type="log"),
-    yaxis=dict(type="log"),
+    yaxis=dict(range=[0, 1]),
 )
 ```
-Závislost času řešení na velikosti vstupu.
-:::
-
-
-Seznam zkratek {-}
-==================
-
--------  -----------------------------------
-Zkratka  Vysvětlení
--------  -----------------------------------
-Řeš.     Řešení                    
-
-Opt.     Optimum                   
-
-SDP      Semidefinitní programování
-
-MC       Max cut - Maximální řez   
-
-BPS      Binární paint shop problém
--------  -----------------------------------
-
 
+Naměřená závislost relativního skóre řešení na velikosti vstupu.
+:::
 
+Dolní odhad
+-----------
 
+Výstup z každého algoritmu nám dává hodní odhad na optimum daného vstupu.
+Ovšem semidefinitní programování nám navíc dává i dolní odhad na optimum, protože víme,
+že optimum jednho z ekvivalentních vyjádření účelové funkce je vždy menši rovno optimu BPS.
+Použité řešiče semidefinitních programů nám navíc dají i horní odhad na optimum SDP (řešení duálního programu).
 
 Závěr {-}
 =========
 
-V této práci jsem představil algoritmus ${\bf sdp}$ na BPS založený na semidefinitním programování.
+V této práci jsme představili algoritmus ${\bf sdp}$ na BPS založený na semidefinitním programování.
 Bohužel se nám nepodařilo dokázat žádný netriviální odhad na $\delta_{\algo{sdp}}^+$.
-Nicméně dle naměřených dat můžeme soudit, že $\delta_{\algo{sdp}}^+$ se pohybuje okolo 0.33.
+Nicméně dle naměřených dat můžeme soudit, že $\delta_{\algo{sdp}}^+$ se pohybuje okolo 0.34.
 Místo toho jsme však dokázali, že pro libovolný vstup bude střední hodnota
 (přes náhodné čísla generovaná algoritmem nikoliv přes vstup)
 skóre řešení nejhůře $0.212 n$ od optima, tedy, že platí $$\forall \alpha:\qquad\E[\delta_{\algo{sdp}}(\alpha)] \le \delta(\alpha) + 0.212 n.$$
@@ -1151,6 +1154,23 @@ A druhak jsme si všimli, že dimenze řešení semidefinitního programování
 Stále však zůstává otevřená otázka, kolik přesně je $\delta^+$ a $\delta^-$ (a případně zda se rovnají)
 a jaké nejlepší $\delta^+_{\alg}$ jsme schopní dosáhnout polynomiálním algoritmem $\alg$.
 
+Seznam zkratek {-}
+==================
+
+-------  -----------------------------------
+Zkratka  Vysvětlení
+-------  -----------------------------------
+Řeš.     Řešení                    
+
+Opt.     Optimum                   
+
+SDP      Semidefinitní programování
+
+MC       Max cut - Maximální řez   
+
+BPS      Binární paint shop problém
+-------  -----------------------------------
+
 
 Seznam použité literatury {-}
 =============================
-- 
GitLab