diff --git a/prace/bakalarka/bakalarka.py b/prace/bakalarka/bakalarka.py index bf93fbb6689b068f80706a451e2786a48deef28e..9728dfe097757094a4b4f2d116550fe006b3f351 100644 --- a/prace/bakalarka/bakalarka.py +++ b/prace/bakalarka/bakalarka.py @@ -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 diff --git a/prace/bakalarka/formatitko_commands.py b/prace/bakalarka/formatitko_commands.py index 54742264f55c008879873fa8ad204ff689847c30..26cb10b86c6186d7162528bab25dd6de86df36dc 100644 --- a/prace/bakalarka/formatitko_commands.py +++ b/prace/bakalarka/formatitko_commands.py @@ -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): diff --git a/prace/bakalarka/g.py b/prace/bakalarka/g.py index e7909a105ae0a55e5b374013bc60563d0b7b4767..236a59f0db5df18cf6b40d93f928b83b749fd33e 100644 --- a/prace/bakalarka/g.py +++ b/prace/bakalarka/g.py @@ -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 diff --git a/prace/bakalarka/index.md b/prace/bakalarka/index.md index 3b1aae778bee7ea2f73ad0e74946acf8c7134d2a..3c2b84534bd796bd2af3ace112cc7c17b9bc1aa8 100755 --- a/prace/bakalarka/index.md +++ b/prace/bakalarka/index.md @@ -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á. @@ -636,9 +629,17 @@ U každé hrany $uv$ optimalizujeme $-h(u,v) \vec{y_u}^{\rm T}\vec{y_v}$, což j 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. ::: @@ -652,9 +653,15 @@ $$ $$ ::: {#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 +760,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 +784,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$. ::: @@ -962,14 +983,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 +1025,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) 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, 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 +1111,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) 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, 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 +1126,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"), ) @@ -1158,6 +1199,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 +1256,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]), ) diff --git a/prace/bakalarka/ksp.asy b/prace/bakalarka/ksp.asy deleted file mode 100644 index 16f634b2247e793027b2c5d7510e833852a57713..0000000000000000000000000000000000000000 --- a/prace/bakalarka/ksp.asy +++ /dev/null @@ -1,56 +0,0 @@ -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); diff --git a/prace/bakalarka/sdp_visualize.py b/prace/bakalarka/sdp_visualize.py index 39024c1dcc728fd4b54158e09ae3f01e6a8df049..500eed45e27eb4617ef88da4789571213fcef381 100644 --- a/prace/bakalarka/sdp_visualize.py +++ b/prace/bakalarka/sdp_visualize.py @@ -1,20 +1,44 @@ 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) diff --git a/prace/pyproject.toml b/prace/pyproject.toml index 68a311b16d5cb5269308e911149b2745f2c81c19..9d882d4dad8fa4e6f7a4a5cc4b18f78adb4cf468 100644 --- a/prace/pyproject.toml +++ b/prace/pyproject.toml @@ -22,6 +22,7 @@ dependencies = [ "kaleido", "mathjax", "scipy", + "scikit-learn", ] [project.urls]