Skip to content
Snippets Groups Projects
Commit e0d16f15 authored by Jiří Kalvoda's avatar Jiří Kalvoda
Browse files

Merge branch 'master' of gitlab.kam.mff.cuni.cz:jirikalvoda/binary-paint-shop-problem

parents 39a041df 7a9a5ef9
No related branches found
No related tags found
No related merge requests found
......@@ -85,7 +85,12 @@ def main(build_dir=Path("build_pdf"), link_out=True):
exec(code, globals)
fig = globals["fig"]
fig.update_layout(margin = {'l':0,'r':0,'t':0,'b':0})
fig.update_layout(
margin = {'l':0,'r':0,'t':0,'b':0},
font=dict(
size=10,
),
)
file = get_name(element, context) + ".pdf"
......@@ -101,7 +106,7 @@ def main(build_dir=Path("build_pdf"), link_out=True):
code = element.text
file = get_name(element, context) + ".pdf"
r = sage.all.sage_eval("r", cmds=code)
r.save(build_dir/file, figsize=3)
r.save(str(build_dir/file), figsize=3)
return img_from_source(element, context, processor, file)
@formatitko_command
......@@ -109,11 +114,13 @@ def main(build_dir=Path("build_pdf"), link_out=True):
code = element.text
file = get_name(element, context)
with open(build_dir/(file+".asy"), "w") as f:
f.write('include "ksp.asy";\n')
f.write('include "jk_web.asy";\n')
f.write(code)
env = os.environ.copy()
env = os.environ.copy()
env["ASYMPTOTE_DIR"]=f".:{d}"
d_jk_web = Path("/".join(jk_web.__file__.split("/")[:-1]))
env["ASYMPTOTE_DIR"]=f".:{d_jk_web}"
d_formatitko = Path("/".join(formatitko.__file__.split("/")[:-1]))
env["TEXINPUTS"]=".:"+os.getcwd()+":"+str(d_formatitko/"tex")+":"+env.get("TEXINPUTS", "")
subprocess.run(["asy", file+".asy", "-f", "pdf", "-tex", "pdftex"], check=True, cwd=build_dir, env=env)
return img_from_source(element, context, processor, file+".pdf")
......@@ -220,7 +227,6 @@ def main(build_dir=Path("build_pdf"), link_out=True):
env = os.environ.copy()
d_formatitko = Path("/".join(formatitko.__file__.split("/")[:-1]))
env["TEXINPUTS"]=".:"+os.getcwd()+":"+str(d_formatitko/"tex")+":"+env.get("TEXINPUTS", "")
print(env["TEXINPUTS"])
with open(build_dir/"toc.aux", "w") as f:
pass
......
......@@ -84,8 +84,8 @@ def cmt(element, content, processor):
def figure(element, content, processor):
data = element.content[:-1]
caption = element.content[-1].content
x = processor.transform([pf.Figure(*data, caption=pf.Caption(pf.Plain(*caption)), identifier=element.identifier, attributes=element.attributes)])
x[0].content = remove_div_para_to_plain(*x[0].content)
fig = pf.Figure(*data, caption=pf.Caption(pf.Plain(*caption)), identifier=element.identifier, attributes=element.attributes)
x = processor.transform([fig])
return x
def copy(e, *content):
......
......@@ -33,16 +33,17 @@ def draw_algo_graph(fig, data, algo, n, val_getter=lambda x:x.score, name=None,
for i in d:
y[val_getter(i)] += 1
fig.add_trace(go.Histogram(x=[val_getter(i) for i in d], name=name or algo_to_name[algo], xbins=dict(size=1), marker=dict(color=color or algo_to_color[algo])))
fig.add_trace(go.Box(x=[val_getter(i) for i in d], name=name or algo_to_name[algo], showlegend=False, marker=dict(color=color or algo_to_color[algo]), boxmean=True), row=2, col=1)
fig.add_trace(go.Box(x=[val_getter(i) for i in d], name="", showlegend=False, marker=dict(color=color or algo_to_color[algo]), boxmean=True), row=2, col=1)
fig.update_xaxes(range=[0, 2*n])
# xaxis=np.arange(0, 2*n)
fig.update_layout(yaxis_title="Počet řešení")
fig.update_xaxes(title_text="Skóre", row=2, col=1)
fig.update_layout(yaxis_title="Počet řešení.")
fig.update_xaxes(title_text="Skóre.", row=2, col=1)
def intro_graph(algo):
fig = plotly.subplots.make_subplots(rows=2, cols=1, row_heights=[0.8, 0.2], shared_xaxes=True, vertical_spacing = 0.05)
draw_algo_graph(fig, load_main_test(), algo, 200)
fig.update_layout(showlegend=False)
return fig
def nonzero_coords(n, seeds, max_dim=20):
......@@ -59,6 +60,8 @@ def nonzero_coords(n, seeds, max_dim=20):
)])
fig.update_layout(
xaxis_title="Index souřadnice.",
yaxis_title="Počet bodů s hodnotou dané souřadnice ≥ 0.05.",
xaxis=dict(showgrid=False),
yaxis=dict(range=[0, n]),
showlegend=False
......@@ -79,6 +82,8 @@ def max_coords(n, seeds, max_dim=20):
)])
fig.update_layout(
xaxis_title="Index souřadnice.",
yaxis_title="Max. hodnota dané souřadnice všech bodů řešení.",
xaxis=dict(showgrid=False),
yaxis=dict(range=[0, 1]),
showlegend=False
......
......@@ -44,19 +44,17 @@ ft:
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.
---
``` {c=cmt}
Obrázek koule
Klikaci věci + generování obsahu formátítkem
Algoritmy velké písmena
Popisky obrázků
Popisky os
Obsah bez změn velikostí
barevné schéma grafu
font grafů
Velikost poznámky pod čárou
složitost je n^c pro jaké c?
Absolutní číslování ve struktuře
Vizualizace: více pohledů a správné pořadí hran.
Jednotná TeXlib pro asymptote
Velikost \vec
```
::: {only=html}
......@@ -73,15 +71,8 @@ $\def\progline#1#2#3{\hbox{#1}\hskip 1cm\relax #2 \hskip 1cm\relax #3}
\protected\def\P{{\rm P}}
\protected\def\NP{{\rm NP}}
\protected\def\APX{{\rm APX}}
\protected\def\vec#1{\overrightarrow{#1\,}}
\protected\def\vec#1{\vecoverrightarrow{#1}}
\let\rightarrowfillreal\rightarrowfill
\catcode`@=11
\def\overrightarrow#1{\vbox{\m@th\ialign{##\crcr
\rightarrowfill\crcr\noalign{\kern-\p@\kern 0.09em\nointerlineskip}
$\hfil\displaystyle{#1}\hfil$\crcr}}}
\def\rightarrowfill{$\settextsize{5}\m@th\smash-\mkern-7mu%
\cleaders\hbox{$\mkern-2mu\smash-\mkern-2mu$}\hfill
\settextsize{5}\mkern-7mu\mathord\rightarrow$}
\protected\def\opt{{\rm opt}}
\protected\def\algo#1{{\bf #1}}
\protected\def\alg{\algo{alg}}
......@@ -287,13 +278,15 @@ fig = go.Figure(data=[go.Scatter(
mode = 'markers',
)])
fig.update_layout(
xaxis_title="n",
xaxis_title="Počet typů aut.",
yaxis_title="Relativní skóre.",
xaxis=dict(range=[0,None]),
yaxis=dict(range=[0, 2]),
showlegend=False
showlegend=False,
)
```
Graf střední hodnoty relativního skóre hladového řešení $\delta_{\algo g}(n)$ v závislosti na $n$.
Graf střední hodnoty rel. 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á.
......@@ -442,12 +435,9 @@ Auta pro nás budou drahokamy. Barva auta bude označovat, který loupežník z
Minimalizovat počet intervalů je to stejné jako minimalizovat počet hranic mezi nimi (kterých je o jedna méně něž intervalů).
Ve vstupu problému dělení náhrdelníku navíc musí platit, pro každý typ má být stejný počet aut obarvený jednotlivými barvami
(a tedy počet aut daného typu musí být násobkem $k$).
Naopak binární paint shop problém je speciálním případem dělení náhrdelníku
pro dva lupiče, kde navíc platí, že všechna $a_i$ jsou 1 (tedy od každého drahokamu jsou na náhrdelníku právě dva drahokamy).
V této práci se budeme věnovat pouze binárnímu paint shop problému.
Semidefinitní programování
==========================
......@@ -597,10 +587,10 @@ Jednotkový vektor můžeme generovat tak, že vygenerujeme náhodný vektor nez
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
Nyní pojďme precizněji spočítat pravděpodobnost toho, že se dvojice bodů (vektorů) $\vec{y_u}$,
$\vec{y_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}$ (viz obrázek [](#gw-cut)).
Můžeme se podívat na rovinu, ve které leží počátek a oba vektory $\vec{y_u}$, $\vec{y_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}
......@@ -612,49 +602,63 @@ label("$\rho$", (-2,-1), N);
pair u = rotate(70)*(1,0);
pair v = rotate(-15)*(1,0);
draw((0,0)--u,Arrow);
label("$\vec{u}$", u, N);
label("$\vecoverrightarrow{y_u}$", u, N);
draw((0,0)--v,Arrow);
label("$\vec{v}$", v, E);
label("$\vecoverrightarrow{y_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{y_u}$ i $\vec{y_v}$.
:::
Zajímá nás tedy, jaká je pravděpodobnost toho, že jedno z ramen nadroviny bude uvnitř konvexního úhlu
mezi $\vec{u}$ a $\vec{v}$.
mezi $\vec{y_u}$ a $\vec{y_v}$.
Velikost tohoto úhlu označme $\alpha$.
Víme, že $\vec{u}^{\rm\, T}\vec{v} = 1 \cdot 1 \cdot \cos a$.
Víme, že $\vec{y_u}^{\rm\, T}\vec{y_v} = 1 \cdot 1 \cdot \cos \alpha$.
Náhodnou přímku můžeme vygenerovat jako náhodný úhel $\beta$ mezi $0$ a $2\pi$ s tím, že
přímka pak povede směrem $\beta$ a $(\beta + \pi) \mod 2\pi$. Nikdy však uvnitř konvexního úhlu nebudou obě
ramena přímky, tedy pravděpodobnost, že alespoň jedno bude uvnitř a tedy body budou oddělené je:
$$ \frac{2 \cdot \alpha}{2\pi} = \frac{\alpha}{\pi} = \frac{\arccos \vec{u}^{\rm\,T}\vec{v}}{\pi}$$
$$ \frac{2 \cdot \alpha}{2\pi} = \frac{\alpha}{\pi} = \frac{\arccos \vec{y_u}^{\rm\,T}\vec{y_v}}{\pi}$$
U každé hrany $uv$ optimalizujeme $-h(u,v) \vec{y_u}^{\rm T}\vec{y_v}$, což je ekvivalentní
optimalizování $h(u,v)\cdot\left(\frac{1}{2} - \frac{\vec{y_u}^{\rm T}\vec{y_v}}{2}\right)$.
::: {#gw-func c=figure}
```python {c=sage}
x = var('x')
r = plot([1/2 - x/2, arccos(x)/pi], xmin=-1, xmax=1)
```asy {c=asy}
import graph;
size(380,180,IgnoreAspect);
real f(real x) {return 1/2-x/2;}
real g(real x) {return acos(x)/pi;}
draw(graph(f, -1, 1),red,"\vbox{\hbox{Pravděpodobnost řezu}\vskip 2pt\hbox{$\frac{1 - \vecoverrightarrow{y_u}^{\rm T}\vecoverrightarrow{y_v}}{2}$}}");
real g(real x) {return acos(x)/pi;}
draw(graph(g, -1, 1),blue,"\vbox{\hbox{Účelová funkce}\vskip 2pt\hbox{$\frac{\arccos \vecoverrightarrow{y_u}^{\rm\,T} \vecoverrightarrow{y_v}}{\pi}$}}");
xaxis("$\vecoverrightarrow{y_u}^{\rm T}\vecoverrightarrow{y_v}$",BottomTop,LeftTicks);
yaxis(LeftRight,RightTicks);
add(legend(linelength=15pt),point(E),10E);
```
Graf funkcí pravděpodobnosti řezu a účelové funkce.
:::
Nyní se podívejme na poměr mezi pravděpodobností toho, že hrana bude v řezu, a účelovou funkcí před vynásobením hodnotou hrany jakožto funkci proměnné $x = \vec{u}^{\rm\,T} \vec{v}$ v intervalu $\left[ -1, 1 \right]$:
Nyní se podívejme na poměr mezi pravděpodobností toho, že hrana bude v řezu, a účelovou funkcí před vynásobením hodnotou hrany jakožto funkci proměnné $x = \vec{y_u}^{\rm\,T} \vec{y_v}$ v intervalu $\left[ -1, 1 \right]$:
$$
\frac{\arccos \vec{u}^{\rm\,T} \vec{v}}{\pi} / \frac{1 - \vec{y_u}^{\rm T}\vec{y_v}}{2}
\frac{\arccos \vec{y_u}^{\rm\,T} \vec{y_v}}{\pi} / \frac{1 - \vec{y_u}^{\rm T}\vec{y_v}}{2}
=
\frac{\arccos x}{\pi} / \frac{1 - x}{2}
$$
::: {#gw-frac c=figure}
```python {c=sage}
x = var('x')
r = plot(arccos(x)/pi / (1/2 - x/2), xmin=-1, xmax=1, ymin=0, ymax=5)
```asy {c=asy}
import graph;
size(350,180,IgnoreAspect);
real f(real x) {return acos(x)/pi/(1/2-x/2);}
draw(graph(f, -1, 0.99),red,"$\frac{\frac{\arccos \vecoverrightarrow{y_u}^{\rm\,T} \vecoverrightarrow{y_v}}{\pi}}{\frac{1 - \vecoverrightarrow{y_u}^{\rm T}\vecoverrightarrow{y_v}}{2}}$");
ylimits(0,2, Crop);
xaxis("$\vecoverrightarrow{y_u}^{\rm T}\vecoverrightarrow{y_v}$",BottomTop,LeftTicks, xmax=1);
yaxis(LeftRight,RightTicks);
add(legend(linelength=15pt),point(E),10E);
```
Graf poměru pravděpodobnosti řezu a účelové funkce.
:::
......@@ -753,9 +757,15 @@ postupu by nás ani neměla zaskočit, protože v případě, že by šlo uděla
Místo toho se podíváme na rozdíl pravděpodobnosti a účelové funkce.
::: {#sdp-diff c=figure}
```python {c=sage}
x = var('x')
r = plot(arccos(x)/pi - (1/2 - x/2), xmin=-1, xmax=1)
```asy {c=asy}
import graph;
size(400,180,IgnoreAspect);
real f(real x) {return acos(x)/pi - (1/2-x/2);}
draw(graph(f, -1, 1),red,"$\frac{\arccos \vecoverrightarrow{u}^{\rm\,T} \vecoverrightarrow{v}}{\pi} - \frac{1 - \vecoverrightarrow{y_u}^{\rm T}\vecoverrightarrow{y_v}}{2}$");
ylimits(-0.2,0.2, Crop);
xaxis("$\vecoverrightarrow{x_i}^{\rm T}\vecoverrightarrow{y_i}$",BottomTop,LeftTicks, xmax=1);
yaxis(LeftRight,RightTicks);
add(legend(linelength=15pt),point(E),10E);
```
Graf rozdílu pravděpodobnosti řezu a účelové funkce.
:::
......@@ -771,9 +781,17 @@ Zderivováním získáme:
$$f'(x) = - \frac{1}{\pi \sqrt{-x^2 +1}} + \frac12 ,$$
::: {#sdp-derivative c=figure}
```python {c=sage}
x = var('x')
r = plot(derivative(arccos(x)/pi - (1/2 - x/2)), xmin=-1, xmax=1, ymin=-1, ymax=0.3)
```asy {c=asy}
import graph;
size(350,180,IgnoreAspect);
real f(real x) {return -1/(pi*sqrt(-x*x+1))+ 1/2;}
real g(real x) {return 0;}
draw(graph(f, -0.99, 0.99),red,"$f'(x)$");
draw(graph(g, -1, 1));
ylimits(-0.5,0.25, Crop);
xaxis("$\vecoverrightarrow{x_i}^{\rm T}\vecoverrightarrow{y_i}$",BottomTop,LeftTicks, xmin=-1, xmax=1);
yaxis(LeftRight,RightTicks);
add(legend(linelength=15pt),point(E),10E);
```
Derivace funkce $f$.
:::
......@@ -829,13 +847,13 @@ Měření řešení BPS
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 s počtem typů aut
10, 20, 50, 100, 200, 400, 566, 800, 1131, 1600, 2263 a 3200 (jedna z implementací $\algo{sdp}$ vyžaduje moc paměti a proto byla spuštěna jen na vstupech do velikosti $566$).
10, 20, 50, 100, 200, 400, 566, 800, 1131, 1600, 2263 a 3200 (jedna z implementací $\algo{sdp}$ -- pomocí sage vyžaduje moc paměti a proto byla spuštěna jen na vstupech do velikosti $566$).
Celý test běžel jednovláknově zhruba dva dny a využíval nejvýše 16 GB operační paměti.
U $\algo{sdp}$ řešení bylo použito 10 náhodných řezů a vždy byl vybraný nejlepší z nich.
Gitový repozitář s implementací i naměřenými daty je dostupný na <https://gitlab.kam.mff.cuni.cz/jirikalvoda/binary-paint-shop-problem>.
Gitový repozitář s implementací i naměřenými daty je k dispozici na <https://gitlab.kam.mff.cuni.cz/jirikalvoda/binary-paint-shop-problem>.
Na následujících stranách jsou zpracovaná různá naměřená data.
Pro reprodukovatelnost vygenerovaných řešení byly vstupy generovány ze seedů.
Pro reprodukovatelnost byly vstupy generovány deterministicky ze seedů.
Se stejným seedem se tedy vždy vygeneruje stejný vstup a ideálně i stejné řešení.
Pro různé algoritmy a velikosti vstupů byly použité různé seedy.
......@@ -962,14 +980,15 @@ d = pathlib.Path("/".join(__file__.split("/")[:-1]))
fig = plotly.subplots.make_subplots(rows=2, cols=1, row_heights=[0.8, 0.5], shared_xaxes=True, vertical_spacing = 0.05)
scalar_products = sum(([float(i) for i in open(d/f"semidef_prog_scalar_products/n200_seed{i:04}").read().split()] for i in range(1,101)), start=[])
fig.add_trace(go.Histogram(x=scalar_products, name="Hodnoty skalárních součinů", xbins=dict(size=0.01), marker=dict(color="blue")))
fig.add_trace(go.Histogram(x=scalar_products, name="Naměřený počet výskytů", xbins=dict(size=0.01), marker=dict(color="blue")))
x_vals = [i/500 for i in range(-500, 500+1)]
fig.add_trace(go.Scatter(x=x_vals, y=[math.acos(x)/math.pi - (1/2 - x/2) for x in x_vals], mode='lines', name="Rozdíl pravděpodobnosti řezu a účelové funkce"), row=2, col=1)
fig.update_xaxes(range=[-1, 1])
fig.update_layout(
legend=dict(
orientation="h",
),
xaxis2_title="Hodnota skalárního součinu vektorů sousedních aut.",
xaxis2_title_standoff = 0,
margin_b = 15,
legend=dict(orientation="h"),
)
```
Distribuce skalárních součinů $100$ běhů algoritmu pro $n=200$.
......@@ -1003,6 +1022,27 @@ všechny vektory v něm mají několik prvních souřadnic velké hodnoty
a ve zbylých souřadnic mají hodnoty blízké nule.
Tedy kdybychom vektory promítli na méně dimenzionální sféru (vzali místo nich nejbližší bod na ní), tak se účelová funkce moc nezmění.
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)[](#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, tak, jak je ukázáno na obrázku [](#sdp-visualize_50).
::: {#sdp-visualize_50 c=figure}
```python {.run}
from bakalarka import sdp_visualize
return processor.transform([pf.CodeBlock(sdp_visualize.visualize("semidef_prog_n50_seed2"), attributes=dict(c="asy"))])
```
Světlá barva bodu značí bod na zadní straně sféry.
Černé čáry spojují sousední auta a šedé jsou jim středově simetrické (protože dvojice aut, jejichž druhá auta stejného typu jsou vedle sebe, je také přitahována k sobě).
Vizualizace jednoho z řešení pro $n=50$, které se vejde do 3D.
:::
::: {#max_coords_400 c=figure floatpage=400}
```python {c=plotly}
from bakalarka import g
......@@ -1068,23 +1108,6 @@ 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í.
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)[](#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, tak, jak je ukázáno na obrázku [](#sdp-visualize_50).
::: {#sdp-visualize_50 c=figure}
```python {.run}
from bakalarka import sdp_visualize
return processor.transform([pf.CodeBlock(sdp_visualize.visualize("semidef_prog_n50_seed2"), attributes=dict(c="asy"))])
```
Vizualizace jednoho z řešení pro $n=50$, které se vejde do 3D.
:::
\vfil\supereject
## Časová složitost algoritmu $\algo{sdp}$
......@@ -1100,21 +1123,36 @@ Během výpočtu na stoji neběželo nic kromě výpočtu a základních funkcí
::: {#tmp2 c=figure}
```python {c=plotly}
from math import log, exp
from bakalarka import g, data_lib
from sklearn.linear_model import LinearRegression
def gen(d, name, minim, color, color_line):
pred_x = list(range(minim, max(i.n for i in d)+1))
regr = LinearRegression()
regr_res = regr.fit([[log(i.n)] for i in d if i.resources_cpu_time_s and i.n>minim], [log(i.resources_cpu_time_s) for i in d if i.resources_cpu_time_s and i.n>minim])
predict = [exp(i) for i in regr.predict([[log(i)] for i in pred_x])]
return [
go.Box(
x=[i.n for i in d],
y=[i.resources_cpu_time_s for i in d],
name=name,
marker_color=color,
),
go.Scatter(x=pred_x, y=predict, mode="lines", marker_color=color_line, name=f"n^{regr.coef_[0]:.3} * {exp(regr.intercept_):.1g}".replace("-0", "-")),
]
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=[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 = go.Figure(data=[
*gen(data.pipelines["semidef_prog(10)"], "SDPA-C", 400, "blue", "lightblue"),
*gen(data.pipelines["semidef_prog_sage.sage(10, CVXOPT)"], "Sage", 100, "red", "pink"),
])
fig.update_layout(
xaxis_title="Počet typů aut (logaritmická stupnice)",
yaxis_title="Čas běhu v sekundách (logaritmická stupnice)",
xaxis=dict(showgrid=False, type="log"),
yaxis=dict(type="log"),
)
......@@ -1122,7 +1160,8 @@ fig.update_layout(
Závislost času řešení na velikosti vstupu.
:::
TODO proložit přímkou a udělat závěr.
Dle výše uvedeného grafu můžeme usuzovat, že časová složitost obou algoritmů je v $\O(n^4) \cap \Omega(n^3)$.
Implementace pomocí SDPA-C má menší multiplikativní konstantu a navíc mnohem rychlejší čas startu, který se zejména projevuje na malých instancích.
\vfil\supereject
......@@ -1158,6 +1197,8 @@ fig.add_hline(y=0.34,
annotation_text="0.34", annotation_position="top left",
fillcolor="green")
fig.update_layout(
xaxis_title="Počet typů aut (logaritmická stupnice)",
yaxis_title="Relativní skóre",
xaxis=dict(showgrid=False, type="log"),
yaxis=dict(range=[0, 1]),
)
......@@ -1213,6 +1254,8 @@ fig.add_hline(y=0.214,
annotation_text="0.214", annotation_position="top left",
fillcolor="green")
fig.update_layout(
xaxis_title="Počet typů aut (logaritmická stupnice)",
yaxis_title="Relativní skóre",
xaxis=dict(showgrid=False, type="log"),
yaxis=dict(range=[0, 1]),
)
......
import settings;
outformat="pdf";
settings.texcommand = "luatex";
texpreamble("
\input luatex85.sty
\input ucwmac2.tex
\input ltluatex.tex
\ucwmodule{luaofs}
\ucwmodule{verb}
\ucwmodule{link}
\clickablefalse
% Fonty
\ofsdeclarefamily [Pagella] {%
\loadtextfam qplr;%
qplb;%
qpli;%
qplbi;;%
}
\def\MSfeat#1{:mode=node;script=latn;+tlig}
\registertfm qplr - file:texgyrepagella-regular.otf\MSfeat{}
\registertfm qplb - file:texgyrepagella-bold.otf\MSfeat{}
\registertfm qpli - file:texgyrepagella-italic.otf\MSfeat{}
\registertfm qplbi - file:texgyrepagella-bolditalic.otf\MSfeat{}
\settextsize{12}
\uselanguage{czech}\frenchspacing\lefthyphenmin=2\righthyphenmin=2{}
\input glyphtounicode.tex
\pdfgentounicode=1
");
defaultpen(fontcommand("\relax"));
pen ksp_pen[] = {
linewidth(0.15pt),
linewidth(0.4pt),
linewidth(0.8pt),
linewidth(1.2pt),
};
pen ksp_thin_pen = ksp_pen[0];
pen ksp_normal_pen = ksp_pen[1];
pen ksp_thick_pen = ksp_pen[2];
pen ksp_fat_pen = ksp_pen[3];
defaultpen(ksp_normal_pen);
pen ksp_short_dashed = linetype(new real[] { 1, 4 });
pen ksp_mid_dashed = linetype(new real[] { 4, 4 });
pen ksp_fine_dotted = ksp_thin_pen + 0.3mm + linetype(new real[] { 0, 2.5 });
pen ksp_gray = gray(0.6);
pen ksp_area_gray = gray(0.75);
import pathlib
import numpy as np
d = pathlib.Path("/".join(__file__.split("/")[:-1]))
from scipy.spatial.transform import Rotation
import numpy as np
from numpy.linalg import norm
def visualize(filename):
def car_place(i, sgn=1):
coord = [x*sign[i]*sgn for x in cholesky[inp[i]]]
return place(coord)
def place(coord):
coord = np.array(coord)
coord = np.array(coord[:3])
coord = coord / norm(coord)
return rot.apply(coord)
def format_place(coord):
return f"({coord[0]}, {coord[1]})"
def f_car_place(*args, **kwargs):
return format_place(car_place(*args, **kwargs))
def is_front_car(i):
return car_place(i)[2] > 0
def car_color(i):
return "blue" if sum(a*b*sign[i] for a,b in zip(cholesky[inp[i]], cut)) > 0 else "red"
with open(d/filename) as f:
data = f.read().split("\n")
inp = list(map(int, data[0].split()))
n = len(inp)//2
cholesky = [list(map(float, i.split())) for i in data[1:n+1]]
cut = list(map(float, data[n+2].split()))
rot = Rotation.align_vectors([(1,0,0)], [cut])[0]
print(rot)
print(cut)
print(rot.apply(cut))
for i in cholesky:
assert sum(x**2 for x in i) > 0.99, f"Dimension higher then input ({sum(x**2 for x in i)})"
......@@ -25,8 +49,28 @@ def visualize(filename):
type_sum[inp[i]] += i
sign = [-1 if type_sum[inp[i]] > 2*i else 1 for i in range(2*n)]
out.append("unitsize(80);")
out.append("""
path edge_path(pair a, pair b)
{
path pa = a--b;
real x = intersections(pa,circle(a, 0.017))[0][0];
real y = intersections(pa,circle(b, 0.017)).pop()[0];
return subpath(pa,x,y);
}
""")
for i in range(2*n):
if not is_front_car(i):
out.append(f"filldraw(circle({f_car_place(i)},0.015), light{car_color(i)});")
for i in range(2*n-1):
out.append(f"draw(edge_path({f_car_place(i, -1)}, {f_car_place(i+1, -1)}), gray(0.8));")
for i in range(2*n-1):
out.append(f"draw({car_place(i)} -- {car_place(i+1)});")
out.append(f"draw({car_place(i, -1)} -- {car_place(i+1, -1)}, green);")
out.append(f"filldraw(circle({place(cut)},0.01));")
out.append(f"draw(edge_path({f_car_place(i)}, {f_car_place(i+1)}));")
out.append(f"draw(circle((0,0),1));")
out.append(f"draw((0,-1.1)-- (0, 1.1));")
for i in range(2*n):
if is_front_car(i):
out.append(f"filldraw(circle({f_car_place(i)},0.015), {car_color(i)});")
# out.append(f"filldraw(circle({format_place(place(cut))},0.01));")
return "\n".join(out)
......@@ -22,6 +22,7 @@ dependencies = [
"kaleido",
"mathjax",
"scipy",
"scikit-learn",
]
[project.urls]
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment