From 6614ac837e077911b7c3c2616e2e293c14d190e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1n=20Malinovsk=C3=BD?= Date: Wed, 21 Oct 2026 14:14:51 +0200 Subject: [PATCH] Prvy --- README.md | 28 + config/default.yaml | 10 + docs/report.md | 14 + notebooks/analysis.ipynb | 0 requirements.txt | 7 + results/figures/error_distribution.png | Bin 0 -> 40048 bytes results/figures/single_positions.png | Bin 0 -> 55482 bytes results/tables/monte_carlo_errors.csv | 1441 ++++++++++++++++++++++ results/tables/monte_carlo_metrics.csv | 91 ++ results/tables/single_node_positions.csv | 17 + scripts/run_monte_carlo.py | 20 + scripts/run_remote_carlo.py | 18 + scripts/run_single.py | 20 + scripts/run_sweep.py | 16 + src/mdsmap_sim/__init__.py | 5 + src/mdsmap_sim/experiment.py | 55 + src/mdsmap_sim/lateration.py | 47 + src/mdsmap_sim/mds_map.py | 28 + src/mdsmap_sim/metrics.py | 18 + src/mdsmap_sim/network.py | 33 + src/mdsmap_sim/plots.py | 36 + src/mdsmap_sim/ranging.py | 27 + src/mdsmap_sim/shortest_path.py | 9 + src/mdsmap_sim/utils.py | 22 + tests/test_lateration.py | 13 + tests/test_mds_map.py | 10 + tests/ttest_metrics.py | 10 + 27 files changed, 1995 insertions(+) create mode 100644 README.md create mode 100644 config/default.yaml create mode 100644 docs/report.md create mode 100644 notebooks/analysis.ipynb create mode 100644 requirements.txt create mode 100644 results/figures/error_distribution.png create mode 100644 results/figures/single_positions.png create mode 100644 results/tables/monte_carlo_errors.csv create mode 100644 results/tables/monte_carlo_metrics.csv create mode 100644 results/tables/single_node_positions.csv create mode 100644 scripts/run_monte_carlo.py create mode 100644 scripts/run_remote_carlo.py create mode 100644 scripts/run_single.py create mode 100644 scripts/run_sweep.py create mode 100644 src/mdsmap_sim/__init__.py create mode 100644 src/mdsmap_sim/experiment.py create mode 100644 src/mdsmap_sim/lateration.py create mode 100644 src/mdsmap_sim/mds_map.py create mode 100644 src/mdsmap_sim/metrics.py create mode 100644 src/mdsmap_sim/network.py create mode 100644 src/mdsmap_sim/plots.py create mode 100644 src/mdsmap_sim/ranging.py create mode 100644 src/mdsmap_sim/shortest_path.py create mode 100644 src/mdsmap_sim/utils.py create mode 100644 tests/test_lateration.py create mode 100644 tests/test_mds_map.py create mode 100644 tests/ttest_metrics.py diff --git a/README.md b/README.md new file mode 100644 index 0000000..e50490a --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +# MDS-MAP localization simulation + +This project simulates localization in an ad-hoc/sensor network using MDS-MAP +and two anchor-only baselines: circular lateration (nonlinear least squares) +and square lateration (min-max bounds). + +## Install and run + +Use Python 3.10 or newer: + +```powershell +python -m pip install -r requirements.txt +python scripts/run_single.py +python scripts/run_remote_carlo.py +pytest +``` + +The default experiment places 4 anchors and 16 unknown nodes in a 100 m +square, uses a 55 m radio range, Gaussian ranging noise, and 30 repetitions. +Outputs are written to `results/figures` and `results/tables`. Edit +`config/default.yaml` to change the experiment. A connected graph is required +for shortest-path completion; increase `radio_range` if a random run is +disconnected. + +The position figure compares actual unknown positions with all estimates and +anchors. The error-distribution figure is a histogram over all unknown nodes +and repetitions. The metrics CSV contains RMSE, MAE, mean, standard deviation, +median, maximum, and 95th percentile errors for every repetition and method. \ No newline at end of file diff --git a/config/default.yaml b/config/default.yaml new file mode 100644 index 0000000..9345e9b --- /dev/null +++ b/config/default.yaml @@ -0,0 +1,10 @@ +area_size: [100.0, 100.0] +anchor_count: 4 +unknown_count: 16 +radio_range: 55.0 +noise_model: gaussian +noise_sigma: 1.0 +multiplicative_sigma: 0.02 +repetitions: 30 +seed: 2026 +output_dir: results \ No newline at end of file diff --git a/docs/report.md b/docs/report.md new file mode 100644 index 0000000..c97ae00 --- /dev/null +++ b/docs/report.md @@ -0,0 +1,14 @@ +# First-version report + +The pipeline generates random node positions, measures only radio-connected +links, completes the distance matrix using all-pairs shortest paths, and +applies classical two-dimensional MDS. An SVD-based Procrustes similarity +transform maps the relative MDS coordinates to the known anchor coordinates. + +Circular lateration estimates each unknown by minimizing range residuals. +Square lateration intersects axis-aligned square bounds around the anchors and +uses the center of the intersection. Both baselines use only direct +anchor-to-unknown measurements. + +The Monte Carlo script records per-node errors and the metrics table, allowing +methods to be compared under the same generated networks and noise settings. \ No newline at end of file diff --git a/notebooks/analysis.ipynb b/notebooks/analysis.ipynb new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..f0a55a3 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +numpy>=1.24 +scipy>=1.10 +matplotlib>=3.7 +pandas>=2.0 +networkx>=3.0 +PyYAML>=6.0 +pytest>=7.0 \ No newline at end of file diff --git a/results/figures/error_distribution.png b/results/figures/error_distribution.png new file mode 100644 index 0000000000000000000000000000000000000000..545af902a107c3002adfbe239050ac7b4b89c438 GIT binary patch literal 40048 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�Xl`pK<$wrXx3)t|4CEB-pO+hAK>`L?7;fX>b247EVtRe z{0yTO7Z=?Gf|&EYwk}@15wFe3@?UDa@domB$(2vxm7 z@J4+Yw7Axh48m}e5O?93<7H6at_8`|DgbHpvp>>qS`!CLnpXNxcPV7a;|*8Os^oVl z6ow_tXFZ^7ipr--kU}F+X)Y8LV)@)QL8V+)f9p#7wG;KIcCv2;fM>VO{)#Q#)iu<) z#=D{vo#@UXP+)TaD{nh)P;+s0q?Rw+bt_C%F-cY8v6;G+SVAv>(-;jU7H`s3impKc zV?^NAeDs_<7fY*MLnwDPAl9`2t#cTzH)xIkG+ZCX(!3iA&P;1c2UaqzEY^iNhkRu> zhplERI~7+@jlK0TN%n12g4Uy ziSPejV&29tRi|35L Gd8Dq+(=E`vbAJ)@_I_5ZQbF0|yj z*+43B+xEuB4jbH#BHyERj)G~LF7|9gl9l6Bo&w5mD(LxTRuf;y^jQXfJ#}|IgXsg) zqSGmB>;YGM(Re`P5?m4j7P6wMP=Ugjc3*ZdJ>=V| zHXsQ*AX>1Q9|f4WU| zrr?ikALUvTAE8?bM`xq~dsxbA-P8zqk^H9@FVu#xpdkQ2T^(iM|}2vduf%X(|asao~{ z=Y4YC{HKsJPA7-#b$8Wd#uj}tDE_6h?Lq2@wGnoKz*5eaP-fT>;?lVvQClk#RbW_vPa&Ku-R89-%pnT(@I#K)?O#65ICbcx>o5T1w_ZbvBJttOzgapiI z%`$uM2Th>cc}N0U3GK8TZmg?|P0u*w#Eu|uN>NFGbN~C0>A*ebXyG>3I}r>&LkG*< zEiK+0^yWVU{Tnu%nl0V%I~mBi^AJT*Fm@BUIa^gRqUEL7bbuGV3uy>MUdg0LJ@IWuAzy~G9%tJMpCeEHduPkccF>^gRP*tHp zd0c3_RRxA?)2u<@u6fz4pTM;{+aGb%$T^AM60v{N43{84vvadSK)FyS#=ewgQ#eR8 zU=_3=*MdM1aiD^SKtff!?q(?cdRZ)6EZG{AD+MzpNY7)qVzex0UFNqJg7b!8p98*lk?qCm}CO#@VL1dDrgB0e|>B%8I*_8c*S z;?$QAs8mCRr7@hZaA031=2kP{k<-6Yq;FD*|`PRW3>#(pJc&?Ax)t?QoHkDa=Uj!#dj5<|p z=sU4WqW3SG<1g;{hLXtAb1q8VTg0iftRVDwmyG9Ln8XDHrCdxek3hy`)cHw8-?a?A z=@k>cof&u70QhJG0r4(I2ff4KgZ1|m<=`yWx+H0PK!j(iN@ z_lLthpb*tHzXNS)N%(UFikkXs>lCp&$VEZhAr2 z<%t+c2J|POrAXQY@$NwbH^N!aFTk=X+u@CFXi%#mj&jE_l9Y%4hJ~M0TNA@fb!tJp zjY^1vXo{-I8hn%S9;k?=&>LatlJCdM&R^||7RxhAjN!UdS4qI_sR7PE1oYGXbws(jEfAN{S5@Vr#V?bJi2ud;O+Mgv4&1iDdZQtu|)wddM(P)$8xR8`lK|4uAEnJEC;y!E-~jfp5CVyGN_&K`Ta3 zI=29}kd=G@y&QRxQCExH`7#(eu$<%!rLe4MLc>WV0f)*MFHf{7hAA2EV1Hamh4+j? zFK-QB(L&ZLY3QqgWY;Kl2U)?R!e3}{za7Nwn2t8I=W;U3S_r5~^aT*BCg=q&v5xXv zE}h0yLr})Yg3hJe6y-xX?TPGLa%j`unJ5JV@2t}yRQEq9PfT8=d@S=pm%0+QSv!b_ zYd{Uro3dpEs(@cDu^e1ckFV4R!C^)a4yMCpgu+1?)FHeRw=*hRZ?X*nIe|EOri3UC zEfaB{R50|%uJ-XjrpG8EBJyvxf01q;m`k?cON%$7JXU+N?|=Cl&BaFG%$@+RjY6-+ zD_>AvBuHwO`KvE|Fw|+*G`!^*g?uFlgbh550tT#TDQ(Wy4D^q(GNE*-Wb`w|5L%|g zkPGNpNF!*i3*yv#@R?1pdI@5)P@cTP!$_M zOJM9~i^m^jY^dUfI@{;|c)EvFgK#p9F`Q_$@La6yBut=K4VZf`9zZ5|6}J+o?zeeU z(d2jw;L#7fWiC-LQKVIf)*JocpP+pZ^M!}bMoTp&biwBWeP)FE-m!?1j??8Hvs;I%y_NU()0tn{A zy%T6_KOY=^1*J+Cel9vpjHzb-o@@5mrM_-F}PB!!BK>9uMY@dwhyB5wGk2T)KWr~jHzR_zk{Z? z^|gChp$J!0`yE`LB5qg+;ZMY88(i(aSEKrss8Uo@4PW&~xj zy(Cluf+j1@@K`J~yAD{X+rl|S3-BX?Hh{VCvQqqx>jT6Y9@&&{{f%&M9hy<42iP7b zXNkaW;NfVvZ$E1L-UdC?7koTY@&}<@@Cz@kRT`=l61D0%`1URK<1QiCt+Y{7Gph7n z9$X0`+^_TwU!_8pb-*E`$DIU%T%_e1fECahkT6@G(m#hP82`}Gy3_pofCZ=A_u&sL41z6+ zkdof#4=nsIA5i${-|;9G|jyMGl(k zs9^D8M3AOWy+wkk2!^oO7pOauR#7f1da00qb-M!N7JU48tlRYVLdKxrS>W&Ng;; zb_==eLF9<-;CkYG(PEcpUIf9o&wSmN=9PmTcG*}YjWDcw%vbe~z9V{GC`HS;mU*cl zh`qaRGsgcNbmB))HRw$FIRLU0re+Ns^phtu zrt9I`JQ-^xRLu_6rIRtnI}lJsqm1zGu&U3h%q99Qm^8l4!E2Q%JBGeFd6d^*gtC`y z)pe9E&yu1)1o*Hy`eRp7Pv`T%rB#(UcqT)sKY$`8MTLWS_fY5~DsyP1QC-V7Yx}4d zwb4LD!vd=D?-j`cYmXfV)px&(A-5+gxJ~#`fp7ucrd>a6*v6Vsg>!D+G~Vu7>9Jm6 z43?N$5qvTqaL7)xpv+{fVnjepkFh1)AY5@%MU0gf^5rd1o|eo(!9gfW^C@fW)h(>; zKFSmEqhN(hox&F>CRU6ke|xRcRw3*qv+{nPr)f2kbHnUQoiATdaNS6_=FDNcB^94{ zuzeqSD$GQ!v1#aZpTdM4M9!tn&$T&~35m+CYK8QRy*w5I^{UlJ6m14=W_o(2ak$Vk zwCS0dK~LJ$cWY@M$|iemtSo<^LPB?-iH^zX{7p;#P0IlF!s70y1Q7^BKc%MnKcS=Q zct;Vl2Cnsj;t;n3Ovp*M^ipbfmYhzLO9K2cx{IUPEoqdO1uA6L?M91ek&k z@NRe|)W&BWzsaAf_prJQDeyc4n1fRoIGVM_{Wa=ZkfQBK4>EfQCV=C%%nsnG@{ zUD6~{R!*$1VKhLvm-}`Ob z_v4#iI>VfE#&N9J*S_{uf4RRmddAt*%5ySfPxC*XKg1|NLI>V3_TV)>(s|aclZiGR za*Pu8)PeD~1G?7E~cTlKX%}N8yG2yW5A{PD99i zW1^*WAlX5K7y_;eZN@p^V3JA;{JOc|~ zjnLXP`ExU`lfQ`ltkESgcE|!8*#3KN{-7SB6vndk?wQPTkcs! zhfmc{Ee#Eah3yDBWCupl5WwgA5H|flVnlqXa%U}yaUY9%HW2ep=>;IIMLla&d&D_B z0pT)PM%PrY=|C|}Ag%b4Ds<+jpjN}@uM4f(M_h*9Kt2YtX@Sssg|f4ZMkUF+i;cN} zLl#D-ku%in8@oO^6{4gYa@vE#bB2v=a85| z$E-m6{c^TJP=c{pT6w{n>J7!NywS7h>yb6ogekutYl!O8Vw46Irtg{1xs5Yg9B)RV zjz}T%ur(gCn^4DHJ?XdQ$od9ud#DI9kzjW+y4y1TW>Uf9@aO+z{oZ6wk#ALI?z!@v zetk_pnDckVVi6EH(pFO#-1TGP^=r|{l%NbuZ#-k9@M zVlPG8^6wkBEIvSC-4BxGOJRy@ApTh-tZM>!Rr}@(QBR33sPYAO=OVIV$Q)cl^=%)^b@{56v8~GewGK;KXtbwBff2O4>zI1GT$w1~Nm( z_i0K>B;Hj58Y@#ntV|bTux8ywZ1lT%5E|x-V!A-;B6D5%^HqC~PcIL6F;$_k*Wu?H z^S(Uy`QhQY@?97>g^}aztJjisa)_1Is9@AWKZ_EC>+iU}2MQWnauCaG<$Az$oi9rZ;sfnCV6BnAIu6ADpFJnKzHTa&Qqa`WVrxP zkgdM>DLYkssTb&~Z=^lTC42Tk3b>&u_-Qn|@pX8J_vU(?`s2)-^7NkfQ3hB-qr~`fj{Xz92KE*?JtHS|@ zNr=5Mw(^7>ym4XpKfA*GSttxo9RYA71D4XAL6XR5`qw>Gg*)T@35bu&MDKM7T6l}$ z!MuWPP`lv_M~MuLg>G@Bm0$01p$*R6`*7ZY8{hdQ&$zO~u@u72ixlN>`D_M2srE4Z zHO3+Sr_Cl}b3k|8cI#-QzBe-sxvY8TbqoysNa!gDznF)Yd`$!DaiKssA zg=e6`{zSc%W8p004IIsmB;D>W>`AEa5Xcj^bnE?vI+ZRxR&z%GbDfCh_k zC|TqkuTu#qBnltE#Lbck8o9w2&zxVZ2mUA1mZEmL_?qTTghDd`ij6%0DruMn*6*`3 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 literal 0 HcmV?d00001 diff --git a/results/tables/monte_carlo_errors.csv b/results/tables/monte_carlo_errors.csv new file mode 100644 index 0000000..37330c1 --- /dev/null +++ b/results/tables/monte_carlo_errors.csv @@ -0,0 +1,1441 @@ +repetition,method,error +0,MDS-MAP,1.8096425019264493 +0,MDS-MAP,3.361252643359399 +0,MDS-MAP,1.1827705234761403 +0,MDS-MAP,0.4288318423413857 +0,MDS-MAP,3.0055677264833345 +0,MDS-MAP,2.293319946919274 +0,MDS-MAP,1.5152592540856946 +0,MDS-MAP,1.9215616050147621 +0,MDS-MAP,3.499173190314767 +0,MDS-MAP,0.955203166961077 +0,MDS-MAP,3.9786433573742683 +0,MDS-MAP,0.46135450637631126 +0,MDS-MAP,3.0108812602656734 +0,MDS-MAP,1.0653952746719206 +0,MDS-MAP,0.4219347489504768 +0,MDS-MAP,0.6232689663899446 +0,Circular lateration,20.758475463238277 +0,Circular lateration,52.1329531491847 +0,Circular lateration,34.59046753517319 +0,Circular lateration,60.39303493086488 +0,Circular lateration,4.402844137632711 +0,Circular lateration,37.73289795096564 +0,Circular lateration,13.778634845094956 +0,Circular lateration,96.88504803126659 +0,Circular lateration,43.141969902354454 +0,Circular lateration,38.31555181141581 +0,Circular lateration,17.87494648634003 +0,Circular lateration,89.49105753148085 +0,Circular lateration,2.2522969682493965 +0,Circular lateration,2.082827254184974 +0,Circular lateration,0.6275591455762581 +0,Circular lateration,0.8431505332481255 +0,Square lateration,19.90699669820593 +0,Square lateration,74.6598885796099 +0,Square lateration,35.80418388655937 +0,Square lateration,65.30917398105493 +0,Square lateration,3.6890176407479194 +0,Square lateration,42.41742903949016 +0,Square lateration,8.128972386611114 +0,Square lateration,82.22363715665422 +0,Square lateration,22.596618845924425 +0,Square lateration,25.244087913520477 +0,Square lateration,16.208957052938743 +0,Square lateration,92.82196959355585 +0,Square lateration,20.5207973670589 +0,Square lateration,15.66095198263396 +0,Square lateration,3.4056890459748512 +0,Square lateration,15.706251579536975 +1,MDS-MAP,132.10038459753554 +1,MDS-MAP,1.7074847744006385 +1,MDS-MAP,154.42495044494277 +1,MDS-MAP,21.884829993120533 +1,MDS-MAP,119.10333780771364 +1,MDS-MAP,7.915783343694788 +1,MDS-MAP,152.86096461963848 +1,MDS-MAP,66.26907826191153 +1,MDS-MAP,85.50358431476509 +1,MDS-MAP,13.01524666482672 +1,MDS-MAP,119.61862223594748 +1,MDS-MAP,119.22035110933433 +1,MDS-MAP,127.70496897237668 +1,MDS-MAP,154.50445738294167 +1,MDS-MAP,9.45234566212284 +1,MDS-MAP,115.76034396470213 +1,Circular lateration,58.98004785001234 +1,Circular lateration,63.738100152107236 +1,Circular lateration,63.18781377146729 +1,Circular lateration,61.26528877087669 +1,Circular lateration,44.556634015378904 +1,Circular lateration,42.61942235235798 +1,Circular lateration,58.77522073886943 +1,Circular lateration,105.70269235241321 +1,Circular lateration,23.18498984994899 +1,Circular lateration,113.07254488237886 +1,Circular lateration,71.91890409773157 +1,Circular lateration,24.67476615237944 +1,Circular lateration,38.39120027132589 +1,Circular lateration,62.25808132686654 +1,Circular lateration,1.2392377171293019 +1,Circular lateration,34.019087253905084 +1,Square lateration,61.399731999816574 +1,Square lateration,54.477318764587146 +1,Square lateration,83.03762636505944 +1,Square lateration,69.75356638874216 +1,Square lateration,60.284040957715625 +1,Square lateration,44.3277395689281 +1,Square lateration,82.39759709596703 +1,Square lateration,40.87132416788545 +1,Square lateration,52.233204905958154 +1,Square lateration,29.243908934296016 +1,Square lateration,79.13180895838039 +1,Square lateration,59.15571722496001 +1,Square lateration,62.86266683942511 +1,Square lateration,86.93801531391847 +1,Square lateration,17.269572256975234 +1,Square lateration,54.237510854802494 +2,MDS-MAP,7.829825196837947 +2,MDS-MAP,6.866196764095104 +2,MDS-MAP,4.2706787314804435 +2,MDS-MAP,13.558096423887427 +2,MDS-MAP,11.98917950334393 +2,MDS-MAP,6.222798552655802 +2,MDS-MAP,10.31011136305071 +2,MDS-MAP,10.705872558048224 +2,MDS-MAP,8.528985313979986 +2,MDS-MAP,1.1155820791413054 +2,MDS-MAP,5.6894959258693 +2,MDS-MAP,0.6216641750146675 +2,MDS-MAP,6.762333104465965 +2,MDS-MAP,7.039053558968506 +2,MDS-MAP,13.65028634375217 +2,MDS-MAP,1.5633326496860807 +2,Circular lateration,37.88560735033533 +2,Circular lateration,72.31097936692525 +2,Circular lateration,88.26532416876486 +2,Circular lateration,66.28609551922167 +2,Circular lateration,15.695554256057997 +2,Circular lateration,87.7284072636327 +2,Circular lateration,44.61065767253721 +2,Circular lateration,36.11236507918839 +2,Circular lateration,92.35989879083971 +2,Circular lateration,94.71083181490397 +2,Circular lateration,79.17903686077149 +2,Circular lateration,19.05429293633071 +2,Circular lateration,2.4397731834647924 +2,Circular lateration,19.928611628992307 +2,Circular lateration,27.35242981264306 +2,Circular lateration,12.145438579253478 +2,Square lateration,52.36039008166723 +2,Square lateration,66.99794719836423 +2,Square lateration,49.12439628608602 +2,Square lateration,58.06951369032889 +2,Square lateration,46.764121599357246 +2,Square lateration,82.0436751907646 +2,Square lateration,45.127701253846965 +2,Square lateration,42.269072491580246 +2,Square lateration,74.37929074697249 +2,Square lateration,52.45126767568141 +2,Square lateration,40.74355393247123 +2,Square lateration,28.789240903606732 +2,Square lateration,32.79673423420238 +2,Square lateration,48.36099249832547 +2,Square lateration,40.408946054242705 +2,Square lateration,27.242789177213073 +3,MDS-MAP,2.7623259553190764 +3,MDS-MAP,7.7470435979913725 +3,MDS-MAP,0.4646437159602584 +3,MDS-MAP,10.496007008331187 +3,MDS-MAP,1.5455652779651414 +3,MDS-MAP,2.4130156263240807 +3,MDS-MAP,4.734136106176655 +3,MDS-MAP,1.9834256899595046 +3,MDS-MAP,8.256503061421554 +3,MDS-MAP,3.119590597497269 +3,MDS-MAP,2.2372572811807863 +3,MDS-MAP,1.220213215883376 +3,MDS-MAP,3.085556709658804 +3,MDS-MAP,3.3962330007578543 +3,MDS-MAP,1.604006433835543 +3,MDS-MAP,3.5332682089191425 +3,Circular lateration,45.769598750385825 +3,Circular lateration,74.70901861348932 +3,Circular lateration,62.114207059816614 +3,Circular lateration,53.829314051399194 +3,Circular lateration,14.342486955253113 +3,Circular lateration,21.054413874870328 +3,Circular lateration,55.545380810385645 +3,Circular lateration,58.54698554994547 +3,Circular lateration,34.41577316444151 +3,Circular lateration,49.58249870790591 +3,Circular lateration,21.479113018188542 +3,Circular lateration,18.43381484349875 +3,Circular lateration,2.0662150909893326 +3,Circular lateration,77.21968011045794 +3,Circular lateration,2.098826887948533 +3,Circular lateration,2.0799197787777026 +3,Square lateration,26.40695768368223 +3,Square lateration,67.26928046498466 +3,Square lateration,18.92181174589812 +3,Square lateration,58.676540645368995 +3,Square lateration,37.19188717780813 +3,Square lateration,23.69163645748182 +3,Square lateration,47.64478126857779 +3,Square lateration,58.287284131048516 +3,Square lateration,56.49627509104648 +3,Square lateration,52.346984313501956 +3,Square lateration,26.49561255170193 +3,Square lateration,17.388551856668684 +3,Square lateration,27.010240465011172 +3,Square lateration,38.163925372035436 +3,Square lateration,12.148194949909042 +3,Square lateration,13.368590003484467 +4,MDS-MAP,57.19032812340169 +4,MDS-MAP,25.068756746814756 +4,MDS-MAP,9.990889918414283 +4,MDS-MAP,20.504789173844436 +4,MDS-MAP,3.0607287142615895 +4,MDS-MAP,88.2057668995198 +4,MDS-MAP,48.99241634717416 +4,MDS-MAP,63.592673407163375 +4,MDS-MAP,9.960206214542811 +4,MDS-MAP,29.027122648578935 +4,MDS-MAP,0.9083598509093511 +4,MDS-MAP,2.0458645673332465 +4,MDS-MAP,26.845940735844774 +4,MDS-MAP,40.76220993148557 +4,MDS-MAP,9.138937284603387 +4,MDS-MAP,26.697784437548457 +4,Circular lateration,43.0341788567584 +4,Circular lateration,63.88951680632521 +4,Circular lateration,46.494998201114484 +4,Circular lateration,47.419609666424705 +4,Circular lateration,19.759949223127684 +4,Circular lateration,35.372251805258365 +4,Circular lateration,38.21912116432985 +4,Circular lateration,59.845113537227206 +4,Circular lateration,18.739642763650707 +4,Circular lateration,60.819152144119364 +4,Circular lateration,29.3090528302453 +4,Circular lateration,14.27824490545149 +4,Circular lateration,4.303088300150597 +4,Circular lateration,1.690910677539593 +4,Circular lateration,2.6942966476158046 +4,Circular lateration,3.1631822248535055 +4,Square lateration,30.766237438892578 +4,Square lateration,46.40982732464278 +4,Square lateration,45.254712569936444 +4,Square lateration,41.583150914807895 +4,Square lateration,7.559790694441616 +4,Square lateration,25.26140633935527 +4,Square lateration,39.09104641675703 +4,Square lateration,38.53933564011563 +4,Square lateration,43.88616110034728 +4,Square lateration,55.700989968264395 +4,Square lateration,1.1841973899478846 +4,Square lateration,30.31493251247525 +4,Square lateration,32.032162334008355 +4,Square lateration,6.768111404826375 +4,Square lateration,29.852699425879344 +4,Square lateration,27.849912422979035 +5,MDS-MAP,1.4437532876216972 +5,MDS-MAP,1.900906472742613 +5,MDS-MAP,2.3875295752802486 +5,MDS-MAP,5.413479298540223 +5,MDS-MAP,3.3419026659774462 +5,MDS-MAP,4.3109015977572644 +5,MDS-MAP,4.084519461814833 +5,MDS-MAP,3.174506569153364 +5,MDS-MAP,2.030420942851835 +5,MDS-MAP,3.886113575400758 +5,MDS-MAP,1.0862241702316766 +5,MDS-MAP,1.9917997106323118 +5,MDS-MAP,2.8995216902524583 +5,MDS-MAP,4.37794132975626 +5,MDS-MAP,32.773206869979084 +5,MDS-MAP,0.6944435367701574 +5,Circular lateration,78.19831453470195 +5,Circular lateration,59.31389672300617 +5,Circular lateration,88.93101709649824 +5,Circular lateration,98.6286881422611 +5,Circular lateration,72.28450640655156 +5,Circular lateration,24.16626479009583 +5,Circular lateration,35.90143099000641 +5,Circular lateration,71.91760358263454 +5,Circular lateration,54.66156043587596 +5,Circular lateration,91.8186765882566 +5,Circular lateration,86.44748850944421 +5,Circular lateration,72.74711146495815 +5,Circular lateration,0.8816342843370123 +5,Circular lateration,4.462124634712609 +5,Circular lateration,3.2313575031796957 +5,Circular lateration,2.569209649594056 +5,Square lateration,69.78715953054835 +5,Square lateration,29.58815434022797 +5,Square lateration,54.978439439270836 +5,Square lateration,84.61054214239813 +5,Square lateration,49.33522197905439 +5,Square lateration,36.194878059611014 +5,Square lateration,41.26936045295859 +5,Square lateration,62.26365687765068 +5,Square lateration,43.72204995961108 +5,Square lateration,58.387674010806585 +5,Square lateration,57.93462940911668 +5,Square lateration,52.060238683902504 +5,Square lateration,15.659037851381587 +5,Square lateration,55.693192897519864 +5,Square lateration,57.1497139104787 +5,Square lateration,23.69903820096558 +6,MDS-MAP,1.5855296523448221 +6,MDS-MAP,2.6715225085002907 +6,MDS-MAP,2.0523766099035434 +6,MDS-MAP,2.850739169910647 +6,MDS-MAP,2.9054190099254087 +6,MDS-MAP,1.6455699483630721 +6,MDS-MAP,2.6264716674621775 +6,MDS-MAP,0.6376198446994558 +6,MDS-MAP,0.9036431569287987 +6,MDS-MAP,0.8221205698059109 +6,MDS-MAP,1.166590441723271 +6,MDS-MAP,2.838889862882747 +6,MDS-MAP,3.86694194821288 +6,MDS-MAP,0.5791512351965046 +6,MDS-MAP,0.3305327751889383 +6,MDS-MAP,1.1522320833008155 +6,Circular lateration,21.686168758458425 +6,Circular lateration,55.75158034269187 +6,Circular lateration,60.877592489466714 +6,Circular lateration,24.083169601350317 +6,Circular lateration,80.80282359292899 +6,Circular lateration,24.09060438363944 +6,Circular lateration,48.95305446505832 +6,Circular lateration,52.99927979336321 +6,Circular lateration,77.87860930767216 +6,Circular lateration,46.40618197914462 +6,Circular lateration,21.0778480037609 +6,Circular lateration,36.473388410182515 +6,Circular lateration,1.3800450257815564 +6,Circular lateration,0.7054472030863675 +6,Circular lateration,1.251038191863526 +6,Circular lateration,1.3733282859698113 +6,Square lateration,20.690156959675218 +6,Square lateration,59.828020786034415 +6,Square lateration,46.949306864590035 +6,Square lateration,28.114877153271017 +6,Square lateration,74.69818358853158 +6,Square lateration,31.009255926189294 +6,Square lateration,43.31249573911364 +6,Square lateration,10.23589428439797 +6,Square lateration,60.316994448812885 +6,Square lateration,46.0254122472428 +6,Square lateration,34.84779323216061 +6,Square lateration,54.77103332195379 +6,Square lateration,28.061089690685996 +6,Square lateration,5.283279718203744 +6,Square lateration,29.314774700595525 +6,Square lateration,20.893514149254866 +7,MDS-MAP,14.663935653020317 +7,MDS-MAP,7.949156209107183 +7,MDS-MAP,16.554267620021584 +7,MDS-MAP,4.725000035952799 +7,MDS-MAP,4.073435123822658 +7,MDS-MAP,3.0516631719994427 +7,MDS-MAP,0.7507748786015223 +7,MDS-MAP,6.261968031191885 +7,MDS-MAP,9.85705753341575 +7,MDS-MAP,2.0982339392812723 +7,MDS-MAP,1.4229735823289709 +7,MDS-MAP,2.2708605180572734 +7,MDS-MAP,4.585697053191991 +7,MDS-MAP,3.9773433708568104 +7,MDS-MAP,8.237349527366533 +7,MDS-MAP,2.430922487810637 +7,Circular lateration,6.087532548251693 +7,Circular lateration,42.689339074117825 +7,Circular lateration,91.15678801909966 +7,Circular lateration,40.032591373082916 +7,Circular lateration,96.17515806770614 +7,Circular lateration,46.52073925389471 +7,Circular lateration,54.3490382237322 +7,Circular lateration,50.95963388463303 +7,Circular lateration,81.45326146322353 +7,Circular lateration,40.62896731010867 +7,Circular lateration,39.43994740013365 +7,Circular lateration,13.528020306911145 +7,Circular lateration,1.474880076867908 +7,Circular lateration,0.546456620050474 +7,Circular lateration,3.350602983608745 +7,Circular lateration,0.34691923661795654 +7,Square lateration,51.57964366203661 +7,Square lateration,44.607802467238145 +7,Square lateration,68.35651600837703 +7,Square lateration,17.219631501913312 +7,Square lateration,90.19680481386244 +7,Square lateration,43.58841075978496 +7,Square lateration,57.68738636533378 +7,Square lateration,50.94853487924663 +7,Square lateration,68.45551472474094 +7,Square lateration,38.955701651605494 +7,Square lateration,35.07895814118272 +7,Square lateration,14.79797272040091 +7,Square lateration,18.303085225128413 +7,Square lateration,21.21312132868551 +7,Square lateration,12.2568160837197 +7,Square lateration,6.574579847626256 +8,MDS-MAP,3.0952060144925855 +8,MDS-MAP,1.0795331733760243 +8,MDS-MAP,1.5072279756202698 +8,MDS-MAP,1.2233717051985553 +8,MDS-MAP,1.400428386284577 +8,MDS-MAP,5.277335426175595 +8,MDS-MAP,1.5796272478211404 +8,MDS-MAP,2.355066684936711 +8,MDS-MAP,1.975606010474347 +8,MDS-MAP,1.8064009380788337 +8,MDS-MAP,1.723864634201643 +8,MDS-MAP,2.032068445427485 +8,MDS-MAP,1.9243728621128133 +8,MDS-MAP,1.9834790026348066 +8,MDS-MAP,2.25772760787079 +8,MDS-MAP,3.1322236708700646 +8,Circular lateration,51.38920541396284 +8,Circular lateration,47.121534761262005 +8,Circular lateration,51.46258114160135 +8,Circular lateration,18.08713092017517 +8,Circular lateration,77.2192568520714 +8,Circular lateration,57.73543006271733 +8,Circular lateration,65.84272873574695 +8,Circular lateration,63.56597172310178 +8,Circular lateration,26.10586266414753 +8,Circular lateration,63.02074715842679 +8,Circular lateration,63.689897276093106 +8,Circular lateration,43.884641164419754 +8,Circular lateration,1.6866491615734005 +8,Circular lateration,3.059743138579226 +8,Circular lateration,1.5673706001427898 +8,Circular lateration,4.6926472871947675 +8,Square lateration,53.324908030918664 +8,Square lateration,43.302585877844 +8,Square lateration,23.33483364565785 +8,Square lateration,29.39119502415623 +8,Square lateration,79.44514858379279 +8,Square lateration,27.83332935171038 +8,Square lateration,73.44858460570282 +8,Square lateration,28.385876271532876 +8,Square lateration,33.82288144606667 +8,Square lateration,70.12444997255425 +8,Square lateration,19.891388945160728 +8,Square lateration,61.929215630758684 +8,Square lateration,32.18271731906434 +8,Square lateration,11.96128330065889 +8,Square lateration,51.33458334769087 +8,Square lateration,29.25380043141019 +9,MDS-MAP,7.983742820083919 +9,MDS-MAP,34.39874449949074 +9,MDS-MAP,80.11262037098052 +9,MDS-MAP,66.3548743704071 +9,MDS-MAP,50.925626160752046 +9,MDS-MAP,7.550891413575943 +9,MDS-MAP,58.95324208124569 +9,MDS-MAP,123.03355597499362 +9,MDS-MAP,3.760726454659019 +9,MDS-MAP,54.0799915408295 +9,MDS-MAP,11.558849154599825 +9,MDS-MAP,80.75910161149602 +9,MDS-MAP,72.96270286352754 +9,MDS-MAP,17.42246526320295 +9,MDS-MAP,56.7698767237573 +9,MDS-MAP,34.31831801709722 +9,Circular lateration,31.622115148135066 +9,Circular lateration,20.850992101469863 +9,Circular lateration,59.01057931454149 +9,Circular lateration,103.85513225229437 +9,Circular lateration,31.507460946012703 +9,Circular lateration,37.992891986456826 +9,Circular lateration,58.154755683488794 +9,Circular lateration,23.766364799556477 +9,Circular lateration,34.48307626266331 +9,Circular lateration,47.188627841848565 +9,Circular lateration,65.08063755678214 +9,Circular lateration,43.59976780170616 +9,Circular lateration,0.7712032343141402 +9,Circular lateration,3.5308767175178244 +9,Circular lateration,0.5840035998921177 +9,Circular lateration,44.890338736492915 +9,Square lateration,20.321149718114214 +9,Square lateration,25.365644881107745 +9,Square lateration,36.123500669698466 +9,Square lateration,51.92775175745584 +9,Square lateration,32.02094880740199 +9,Square lateration,28.613343048281866 +9,Square lateration,49.86270570155219 +9,Square lateration,51.09445692925334 +9,Square lateration,9.652849437775242 +9,Square lateration,45.53278750133929 +9,Square lateration,63.88645630943104 +9,Square lateration,54.954884253618275 +9,Square lateration,26.86614894478585 +9,Square lateration,3.016350179293921 +9,Square lateration,19.44416376288595 +9,Square lateration,22.081227210773157 +10,MDS-MAP,1.2721292770460417 +10,MDS-MAP,1.383709681771458 +10,MDS-MAP,1.3213038084129944 +10,MDS-MAP,1.2340795301453522 +10,MDS-MAP,2.4998667422435097 +10,MDS-MAP,1.6363810774349408 +10,MDS-MAP,1.1417828103504428 +10,MDS-MAP,3.2477428625751004 +10,MDS-MAP,0.7379467930771975 +10,MDS-MAP,1.4142124578247797 +10,MDS-MAP,0.8217612860164205 +10,MDS-MAP,1.180378926006657 +10,MDS-MAP,1.0203432032836641 +10,MDS-MAP,2.372516570957 +10,MDS-MAP,2.8783893218434593 +10,MDS-MAP,2.810904058221609 +10,Circular lateration,63.941646296831074 +10,Circular lateration,44.95144090358834 +10,Circular lateration,41.989620357350844 +10,Circular lateration,41.484767025649 +10,Circular lateration,114.8385863544283 +10,Circular lateration,87.21606644078808 +10,Circular lateration,53.88581292886004 +10,Circular lateration,49.19346204822347 +10,Circular lateration,69.84749832028486 +10,Circular lateration,69.74884035932648 +10,Circular lateration,45.67363238063904 +10,Circular lateration,80.79866946643023 +10,Circular lateration,1.1784157500880366 +10,Circular lateration,2.1919978671309006 +10,Circular lateration,1.7482926519102338 +10,Circular lateration,2.523099345733022 +10,Square lateration,40.73169411992031 +10,Square lateration,33.86676189143993 +10,Square lateration,40.75702775112633 +10,Square lateration,22.647388235478374 +10,Square lateration,89.45446667558086 +10,Square lateration,60.40275865268304 +10,Square lateration,51.49081155761267 +10,Square lateration,42.57208273237824 +10,Square lateration,62.25810657235215 +10,Square lateration,39.888001870253355 +10,Square lateration,46.36191960774366 +10,Square lateration,48.186639394178776 +10,Square lateration,13.36327218021413 +10,Square lateration,36.818612836610725 +10,Square lateration,5.4445319988465615 +10,Square lateration,35.14001540558485 +11,MDS-MAP,3.141286739110067 +11,MDS-MAP,0.7616697346637401 +11,MDS-MAP,3.463238376924719 +11,MDS-MAP,2.672920018252081 +11,MDS-MAP,5.355327598862131 +11,MDS-MAP,4.172213712309137 +11,MDS-MAP,2.0945319359037704 +11,MDS-MAP,11.475930347382185 +11,MDS-MAP,4.373220835386713 +11,MDS-MAP,4.035007903329198 +11,MDS-MAP,2.0916752568315817 +11,MDS-MAP,4.719174476761389 +11,MDS-MAP,1.673144295289258 +11,MDS-MAP,1.1677418010787775 +11,MDS-MAP,2.2761244881149287 +11,MDS-MAP,4.801414599883582 +11,Circular lateration,39.448691141038445 +11,Circular lateration,34.83818633655431 +11,Circular lateration,10.506243530068273 +11,Circular lateration,63.547411123946105 +11,Circular lateration,19.57655510342637 +11,Circular lateration,63.10389993040152 +11,Circular lateration,55.88090730875343 +11,Circular lateration,59.753178932455214 +11,Circular lateration,29.47486893740696 +11,Circular lateration,59.56957434041198 +11,Circular lateration,79.62054347862745 +11,Circular lateration,8.273568517418411 +11,Circular lateration,1.3508644847308553 +11,Circular lateration,74.37087061289031 +11,Circular lateration,0.7836865900332055 +11,Circular lateration,0.46735291222530695 +11,Square lateration,33.45694738337565 +11,Square lateration,4.3518491016797185 +11,Square lateration,11.265580314180264 +11,Square lateration,14.65480479142615 +11,Square lateration,17.896642365118606 +11,Square lateration,67.94645160288945 +11,Square lateration,40.681355427629974 +11,Square lateration,74.25605309539402 +11,Square lateration,29.25385437728017 +11,Square lateration,23.996219589471288 +11,Square lateration,80.93635896211804 +11,Square lateration,37.22183210165265 +11,Square lateration,8.591003619769111 +11,Square lateration,40.30992580314805 +11,Square lateration,4.1544414865661325 +11,Square lateration,38.81718193755445 +12,MDS-MAP,30.45062835292178 +12,MDS-MAP,69.74931407993141 +12,MDS-MAP,62.23926759225582 +12,MDS-MAP,49.44651551886821 +12,MDS-MAP,84.3422848043104 +12,MDS-MAP,31.568245524171076 +12,MDS-MAP,65.56625957973635 +12,MDS-MAP,72.6219085092033 +12,MDS-MAP,53.05818813262967 +12,MDS-MAP,95.0659939561794 +12,MDS-MAP,9.233838967914892 +12,MDS-MAP,3.492045765570928 +12,MDS-MAP,9.42907481494203 +12,MDS-MAP,22.93018168801703 +12,MDS-MAP,63.78425680970562 +12,MDS-MAP,4.193088141325295 +12,Circular lateration,75.6029268872449 +12,Circular lateration,40.34858657864962 +12,Circular lateration,61.89563065502907 +12,Circular lateration,60.328859352382416 +12,Circular lateration,90.70643165184782 +12,Circular lateration,55.17886711544589 +12,Circular lateration,66.86170376560396 +12,Circular lateration,35.824076433210045 +12,Circular lateration,79.32221873638835 +12,Circular lateration,79.338220464669 +12,Circular lateration,30.232523661787344 +12,Circular lateration,14.356228683122248 +12,Circular lateration,6.183846673619549 +12,Circular lateration,1.5445865704670791 +12,Circular lateration,1.198560992679868 +12,Circular lateration,6.293793058569835 +12,Square lateration,71.49018544207341 +12,Square lateration,44.697781464304924 +12,Square lateration,44.69112156026866 +12,Square lateration,44.61007713278827 +12,Square lateration,84.1085157934101 +12,Square lateration,52.580290145880596 +12,Square lateration,60.32753788427287 +12,Square lateration,36.52581724053823 +12,Square lateration,73.37700357454791 +12,Square lateration,64.4292753529277 +12,Square lateration,7.989046271499952 +12,Square lateration,12.331262812502086 +12,Square lateration,4.055718956914249 +12,Square lateration,15.20839741215472 +12,Square lateration,24.82904494340541 +12,Square lateration,2.182831754201394 +13,MDS-MAP,1.5814416170597438 +13,MDS-MAP,0.9180798313425734 +13,MDS-MAP,2.4209600524292507 +13,MDS-MAP,1.7567859801659185 +13,MDS-MAP,0.33549048148724053 +13,MDS-MAP,1.7088766740756194 +13,MDS-MAP,1.3848697873672449 +13,MDS-MAP,1.651195990981782 +13,MDS-MAP,3.2219358867319587 +13,MDS-MAP,0.7379089329112927 +13,MDS-MAP,2.047507333510048 +13,MDS-MAP,0.5290950887677678 +13,MDS-MAP,4.730287165926998 +13,MDS-MAP,9.572599566724628 +13,MDS-MAP,1.3701174644650604 +13,MDS-MAP,0.9515309787293078 +13,Circular lateration,34.587238531077965 +13,Circular lateration,64.55003348759055 +13,Circular lateration,60.387018334225864 +13,Circular lateration,61.72538481850007 +13,Circular lateration,67.50563711226016 +13,Circular lateration,34.21664868459413 +13,Circular lateration,30.581230523967527 +13,Circular lateration,43.54026465984893 +13,Circular lateration,50.3478783022907 +13,Circular lateration,52.59431492033957 +13,Circular lateration,76.71289949529327 +13,Circular lateration,60.48116221106656 +13,Circular lateration,1.4196330770815988 +13,Circular lateration,2.436902554599474 +13,Circular lateration,0.9083292656917942 +13,Circular lateration,1.6580270660702563 +13,Square lateration,42.25738379667419 +13,Square lateration,61.25343235507883 +13,Square lateration,59.752093196714654 +13,Square lateration,41.55078303541329 +13,Square lateration,61.20236652758884 +13,Square lateration,36.073018333370946 +13,Square lateration,28.55441927618469 +13,Square lateration,44.288816441544384 +13,Square lateration,34.60825917129634 +13,Square lateration,48.63094470633982 +13,Square lateration,63.09338958846434 +13,Square lateration,53.9187311103894 +13,Square lateration,65.84431477484452 +13,Square lateration,18.046922222125843 +13,Square lateration,17.96051965640158 +13,Square lateration,16.5981196992404 +14,MDS-MAP,3.0092330414308774 +14,MDS-MAP,2.283693391830993 +14,MDS-MAP,1.6620001751301339 +14,MDS-MAP,2.639384466605923 +14,MDS-MAP,1.877096010991359 +14,MDS-MAP,2.3360001768618384 +14,MDS-MAP,1.729127892165237 +14,MDS-MAP,5.572865068980912 +14,MDS-MAP,3.3926601531090435 +14,MDS-MAP,9.001952922608695 +14,MDS-MAP,15.192536389037334 +14,MDS-MAP,3.5116823771862005 +14,MDS-MAP,3.5542950237629616 +14,MDS-MAP,1.1089582505968292 +14,MDS-MAP,2.2910353823656147 +14,MDS-MAP,3.2735833772266623 +14,Circular lateration,79.63666556574412 +14,Circular lateration,6.872630128810055 +14,Circular lateration,29.97334009610381 +14,Circular lateration,41.508787585992124 +14,Circular lateration,36.05499127168008 +14,Circular lateration,41.31557674191374 +14,Circular lateration,63.86074904221249 +14,Circular lateration,12.119604298109447 +14,Circular lateration,63.082874667073916 +14,Circular lateration,34.69341300681079 +14,Circular lateration,76.29822697075733 +14,Circular lateration,14.98235378693217 +14,Circular lateration,1.400127256558628 +14,Circular lateration,1.706179749247172 +14,Circular lateration,1.6392957927936 +14,Circular lateration,5.569678698810957 +14,Square lateration,84.57357738605965 +14,Square lateration,10.41486532104026 +14,Square lateration,37.989652387131166 +14,Square lateration,45.62265457886259 +14,Square lateration,40.14772362801795 +14,Square lateration,16.08347376181171 +14,Square lateration,60.81374894132389 +14,Square lateration,6.74411069429528 +14,Square lateration,63.01338958278507 +14,Square lateration,32.51185441963381 +14,Square lateration,81.1032566560281 +14,Square lateration,15.27217048023191 +14,Square lateration,7.9759232824637945 +14,Square lateration,3.0781319399799956 +14,Square lateration,4.5663340628504585 +14,Square lateration,4.331136705547868 +15,MDS-MAP,0.6050955761281581 +15,MDS-MAP,1.6652078461386268 +15,MDS-MAP,0.7282144156885123 +15,MDS-MAP,1.447001073098149 +15,MDS-MAP,1.9872661653019128 +15,MDS-MAP,1.040355880571539 +15,MDS-MAP,0.9144477624704205 +15,MDS-MAP,1.6212552529932966 +15,MDS-MAP,1.4292171473190833 +15,MDS-MAP,0.8109909519761752 +15,MDS-MAP,0.9200867397816094 +15,MDS-MAP,0.7386040155561924 +15,MDS-MAP,1.253433463765034 +15,MDS-MAP,0.7123812352726058 +15,MDS-MAP,2.447716323126961 +15,MDS-MAP,1.2013551170204673 +15,Circular lateration,81.71574767085636 +15,Circular lateration,64.34716562423742 +15,Circular lateration,85.63387597380695 +15,Circular lateration,60.01070454122429 +15,Circular lateration,49.557928378026865 +15,Circular lateration,28.564610054572057 +15,Circular lateration,58.19379123769278 +15,Circular lateration,69.30072929929273 +15,Circular lateration,46.772868439145924 +15,Circular lateration,53.61912523577675 +15,Circular lateration,49.68467150358579 +15,Circular lateration,69.57356558334693 +15,Circular lateration,23.448254724815627 +15,Circular lateration,1.6884799230796133 +15,Circular lateration,56.08270517476422 +15,Circular lateration,92.56010223504823 +15,Square lateration,63.931401275998496 +15,Square lateration,51.551229843270285 +15,Square lateration,33.71833935631521 +15,Square lateration,33.27920242405495 +15,Square lateration,39.51830992234479 +15,Square lateration,28.148511660798466 +15,Square lateration,53.281999175062076 +15,Square lateration,48.40753763821248 +15,Square lateration,31.041862465281614 +15,Square lateration,40.88217072408648 +15,Square lateration,13.25027661624868 +15,Square lateration,23.92173179443448 +15,Square lateration,17.211678025618582 +15,Square lateration,32.970470399471445 +15,Square lateration,39.25961089217 +15,Square lateration,47.64179255335014 +16,MDS-MAP,28.743719124538348 +16,MDS-MAP,40.47839007757884 +16,MDS-MAP,71.44220878591807 +16,MDS-MAP,17.71944103410247 +16,MDS-MAP,55.83328332780149 +16,MDS-MAP,4.89117033019484 +16,MDS-MAP,31.726988961469022 +16,MDS-MAP,14.957762539163923 +16,MDS-MAP,101.33507969494782 +16,MDS-MAP,44.86378027770342 +16,MDS-MAP,108.21902501556505 +16,MDS-MAP,131.29314676931065 +16,MDS-MAP,74.68525084010209 +16,MDS-MAP,85.41302629596969 +16,MDS-MAP,64.58963949391887 +16,MDS-MAP,0.6695351432114817 +16,Circular lateration,41.80411567632386 +16,Circular lateration,64.3366678305219 +16,Circular lateration,65.64263660644352 +16,Circular lateration,53.238126824218206 +16,Circular lateration,24.68572320950283 +16,Circular lateration,18.38981858566279 +16,Circular lateration,69.11883605120283 +16,Circular lateration,77.90649951769777 +16,Circular lateration,99.15759476797687 +16,Circular lateration,64.24534309217597 +16,Circular lateration,22.517119083064095 +16,Circular lateration,74.96625532770148 +16,Circular lateration,0.6920889798874553 +16,Circular lateration,1.4087185481265159 +16,Circular lateration,0.4991385956614281 +16,Circular lateration,0.9582622755300052 +16,Square lateration,24.292827349306958 +16,Square lateration,63.10781599155121 +16,Square lateration,43.48063687802796 +16,Square lateration,54.32454811847847 +16,Square lateration,27.207403818852924 +16,Square lateration,10.175092973534959 +16,Square lateration,31.13322349371747 +16,Square lateration,48.83714730823657 +16,Square lateration,64.18244781009933 +16,Square lateration,35.583511255324396 +16,Square lateration,44.45548586674477 +16,Square lateration,74.32996795543133 +16,Square lateration,40.92950051874058 +16,Square lateration,29.89373121573352 +16,Square lateration,22.30774248285812 +16,Square lateration,1.8598373462400815 +17,MDS-MAP,1.514672992497411 +17,MDS-MAP,1.7098555122972223 +17,MDS-MAP,0.49182061073665473 +17,MDS-MAP,2.6240475510222425 +17,MDS-MAP,3.043659419755073 +17,MDS-MAP,1.9862728073695466 +17,MDS-MAP,2.223447426334696 +17,MDS-MAP,6.341403276845636 +17,MDS-MAP,4.875756235965961 +17,MDS-MAP,1.716885652016475 +17,MDS-MAP,3.3887505649202954 +17,MDS-MAP,1.7459744357963747 +17,MDS-MAP,3.0095095464338053 +17,MDS-MAP,4.532419547502806 +17,MDS-MAP,2.4400495897876033 +17,MDS-MAP,1.459174758674573 +17,Circular lateration,57.70465190123326 +17,Circular lateration,80.28978675266092 +17,Circular lateration,35.88585692901826 +17,Circular lateration,70.22844266859067 +17,Circular lateration,98.33996430050375 +17,Circular lateration,39.740569801502055 +17,Circular lateration,31.986038213786433 +17,Circular lateration,56.064381224018035 +17,Circular lateration,95.10188308945837 +17,Circular lateration,45.426122981118546 +17,Circular lateration,30.30843274208632 +17,Circular lateration,38.98253067254318 +17,Circular lateration,1.698652394027199 +17,Circular lateration,4.30283370066899 +17,Circular lateration,5.023212150874325 +17,Circular lateration,2.1376545437161045 +17,Square lateration,65.15703084017771 +17,Square lateration,56.50954100715878 +17,Square lateration,37.92112799687124 +17,Square lateration,40.05102637585243 +17,Square lateration,63.97199176245357 +17,Square lateration,30.519415141468887 +17,Square lateration,54.83827473642154 +17,Square lateration,59.833315480261525 +17,Square lateration,76.66926777515424 +17,Square lateration,48.302991214261446 +17,Square lateration,26.44416770362301 +17,Square lateration,12.225133978954611 +17,Square lateration,32.98127696253789 +17,Square lateration,22.625324149340447 +17,Square lateration,53.58096981760492 +17,Square lateration,43.00158016881512 +18,MDS-MAP,53.11103415593215 +18,MDS-MAP,37.9608102036034 +18,MDS-MAP,21.251865349187028 +18,MDS-MAP,87.38504909112143 +18,MDS-MAP,47.72272219153767 +18,MDS-MAP,55.939115862402076 +18,MDS-MAP,14.03711506192164 +18,MDS-MAP,41.16191658147403 +18,MDS-MAP,59.147618483920574 +18,MDS-MAP,39.843383853896974 +18,MDS-MAP,0.7798119418255631 +18,MDS-MAP,15.483447204568524 +18,MDS-MAP,38.334579065423355 +18,MDS-MAP,73.88838392499672 +18,MDS-MAP,94.0302941222651 +18,MDS-MAP,23.925891313380472 +18,Circular lateration,65.86259877624741 +18,Circular lateration,29.05688892309742 +18,Circular lateration,9.335202608240687 +18,Circular lateration,68.14795669855297 +18,Circular lateration,70.24345430809842 +18,Circular lateration,20.944138941380906 +18,Circular lateration,6.27048831217129 +18,Circular lateration,35.83565475894172 +18,Circular lateration,103.98084517106099 +18,Circular lateration,64.64739550578054 +18,Circular lateration,87.7610988570487 +18,Circular lateration,35.756725106227876 +18,Circular lateration,5.833950587197409 +18,Circular lateration,1.4203797417941944 +18,Circular lateration,2.8280841950876714 +18,Circular lateration,0.48802086904114167 +18,Square lateration,54.1885162849634 +18,Square lateration,16.58946454842943 +18,Square lateration,15.642152600345872 +18,Square lateration,57.77683348785427 +18,Square lateration,54.309929307313936 +18,Square lateration,26.92174847102946 +18,Square lateration,9.849127844688317 +18,Square lateration,38.15168295996093 +18,Square lateration,88.58172204599529 +18,Square lateration,65.04043086848701 +18,Square lateration,67.02150613104143 +18,Square lateration,36.98360536018487 +18,Square lateration,19.422443111282476 +18,Square lateration,0.6764895558148041 +18,Square lateration,25.07292504962557 +18,Square lateration,7.240974273238235 +19,MDS-MAP,0.4673303469152433 +19,MDS-MAP,0.7408258700991665 +19,MDS-MAP,1.5644413207541485 +19,MDS-MAP,2.098417950599192 +19,MDS-MAP,1.6340748309293727 +19,MDS-MAP,1.4780535613897001 +19,MDS-MAP,3.5978247075835905 +19,MDS-MAP,1.032455161119772 +19,MDS-MAP,1.6339288574558457 +19,MDS-MAP,2.3639162587710314 +19,MDS-MAP,0.9803829410402427 +19,MDS-MAP,2.6485059418588155 +19,MDS-MAP,3.2440858313393695 +19,MDS-MAP,2.344205899701721 +19,MDS-MAP,1.1126652341328638 +19,MDS-MAP,1.6852885384516367 +19,Circular lateration,25.605243050000787 +19,Circular lateration,27.69708282997426 +19,Circular lateration,32.527244836408386 +19,Circular lateration,56.5876157915094 +19,Circular lateration,24.667321557525646 +19,Circular lateration,43.199792513426544 +19,Circular lateration,52.70949187041597 +19,Circular lateration,54.267051322733735 +19,Circular lateration,36.20888102444059 +19,Circular lateration,49.71051543490964 +19,Circular lateration,22.047472910878692 +19,Circular lateration,20.48918194004584 +19,Circular lateration,1.3084236927886288 +19,Circular lateration,1.780430319866706 +19,Circular lateration,1.7917232672433678 +19,Circular lateration,76.09233791394873 +19,Square lateration,14.171460429792392 +19,Square lateration,12.297999034603059 +19,Square lateration,20.25730934210159 +19,Square lateration,69.09042188907085 +19,Square lateration,28.795372912603323 +19,Square lateration,37.2536216683044 +19,Square lateration,53.434145705133034 +19,Square lateration,47.74051005900028 +19,Square lateration,37.357759073197464 +19,Square lateration,57.61990533416098 +19,Square lateration,1.9610784328450475 +19,Square lateration,57.93887081805741 +19,Square lateration,16.59292754980268 +19,Square lateration,8.56073923985013 +19,Square lateration,22.315755803751188 +19,Square lateration,35.87694393593071 +20,MDS-MAP,9.117857526928214 +20,MDS-MAP,42.22669017721573 +20,MDS-MAP,57.25748727695468 +20,MDS-MAP,73.22968280145018 +20,MDS-MAP,71.80973670029086 +20,MDS-MAP,102.08110726231311 +20,MDS-MAP,113.509781745756 +20,MDS-MAP,45.754682388953746 +20,MDS-MAP,15.841472632962564 +20,MDS-MAP,97.28503697614332 +20,MDS-MAP,65.57827732048806 +20,MDS-MAP,15.665161997113923 +20,MDS-MAP,28.892769620001687 +20,MDS-MAP,22.290592893664016 +20,MDS-MAP,39.01637631588058 +20,MDS-MAP,50.980054225051106 +20,Circular lateration,40.14854224224834 +20,Circular lateration,38.61027844507328 +20,Circular lateration,24.238963685973783 +20,Circular lateration,84.95198958516787 +20,Circular lateration,36.073942168480784 +20,Circular lateration,1.1155858150225741 +20,Circular lateration,92.71719695510292 +20,Circular lateration,60.54784311437401 +20,Circular lateration,24.778818016447673 +20,Circular lateration,62.922089043643275 +20,Circular lateration,53.42044540284632 +20,Circular lateration,57.406797818237976 +20,Circular lateration,2.399361171981224 +20,Circular lateration,2.2549098020946325 +20,Circular lateration,0.3856480650784374 +20,Circular lateration,0.4929122057857174 +20,Square lateration,26.75825968020585 +20,Square lateration,19.413090691067904 +20,Square lateration,12.096375002049077 +20,Square lateration,47.134643542092334 +20,Square lateration,35.03386153519866 +20,Square lateration,25.9899549953368 +20,Square lateration,57.6455479427844 +20,Square lateration,40.38583963223083 +20,Square lateration,24.306589717334006 +20,Square lateration,49.176996849476915 +20,Square lateration,57.199722471941236 +20,Square lateration,21.966247506775385 +20,Square lateration,3.1492696569822387 +20,Square lateration,18.637116102149175 +20,Square lateration,4.878507853232023 +20,Square lateration,36.56701405802016 +21,MDS-MAP,41.135932187723675 +21,MDS-MAP,25.50438441095066 +21,MDS-MAP,122.69000685998019 +21,MDS-MAP,31.64429994379402 +21,MDS-MAP,120.95497370764222 +21,MDS-MAP,64.3526436081159 +21,MDS-MAP,29.839056360356672 +21,MDS-MAP,54.27785577237416 +21,MDS-MAP,59.484172814160836 +21,MDS-MAP,19.314573152199905 +21,MDS-MAP,56.69968802445737 +21,MDS-MAP,72.67499884577218 +21,MDS-MAP,46.69703994394017 +21,MDS-MAP,29.72011136794991 +21,MDS-MAP,47.45008123752416 +21,MDS-MAP,0.4468478612244815 +21,Circular lateration,49.068127842178754 +21,Circular lateration,19.604109622671373 +21,Circular lateration,52.538552094315314 +21,Circular lateration,21.88118236422285 +21,Circular lateration,83.71874032272832 +21,Circular lateration,28.971177682191655 +21,Circular lateration,34.718748774993 +21,Circular lateration,68.123018799166 +21,Circular lateration,11.37327194128522 +21,Circular lateration,21.251903637496 +21,Circular lateration,24.437296805958553 +21,Circular lateration,35.542502764595945 +21,Circular lateration,0.8132851928227479 +21,Circular lateration,1.3300037401077716 +21,Circular lateration,1.1676739591112169 +21,Circular lateration,1.2745309146676143 +21,Square lateration,16.50917613122958 +21,Square lateration,18.76444860273923 +21,Square lateration,61.208627072246784 +21,Square lateration,19.04676480036681 +21,Square lateration,78.46165875539442 +21,Square lateration,32.11399530132271 +21,Square lateration,36.11523456160722 +21,Square lateration,39.88121459532336 +21,Square lateration,24.279479680179314 +21,Square lateration,7.709090213068808 +21,Square lateration,32.74581372587489 +21,Square lateration,38.47115994721153 +21,Square lateration,12.893940522869885 +21,Square lateration,23.98895952410933 +21,Square lateration,19.655010334786972 +21,Square lateration,12.662822101958975 +22,MDS-MAP,1.1314334351583022 +22,MDS-MAP,3.290513602643628 +22,MDS-MAP,0.7646035320090528 +22,MDS-MAP,4.204940503082699 +22,MDS-MAP,2.402050709495825 +22,MDS-MAP,0.4492167968978389 +22,MDS-MAP,0.7086558270321177 +22,MDS-MAP,1.8330794533660328 +22,MDS-MAP,1.9030750964733032 +22,MDS-MAP,1.0176304315238514 +22,MDS-MAP,1.1660538312036353 +22,MDS-MAP,1.6840267142739858 +22,MDS-MAP,2.578995453257712 +22,MDS-MAP,1.9296704228736115 +22,MDS-MAP,1.8652093742007128 +22,MDS-MAP,3.8199699502199085 +22,Circular lateration,27.786475413744885 +22,Circular lateration,54.29212869969182 +22,Circular lateration,51.328861371945464 +22,Circular lateration,52.6953073838022 +22,Circular lateration,32.36737760405231 +22,Circular lateration,55.68016808292707 +22,Circular lateration,21.6492434251116 +22,Circular lateration,66.20315741928451 +22,Circular lateration,31.886578079775212 +22,Circular lateration,13.308606416310013 +22,Circular lateration,4.512191096358083 +22,Circular lateration,84.9502592125001 +22,Circular lateration,1.2394538697795994 +22,Circular lateration,3.296010437088151 +22,Circular lateration,3.4104477098087433 +22,Circular lateration,1.5345022319205415 +22,Square lateration,49.57188480028902 +22,Square lateration,56.980081994450906 +22,Square lateration,39.72822879889151 +22,Square lateration,42.45175017273396 +22,Square lateration,31.69963476829511 +22,Square lateration,63.7693353671699 +22,Square lateration,29.673554250149245 +22,Square lateration,57.93698469650087 +22,Square lateration,40.88360871603828 +22,Square lateration,13.329802192154181 +22,Square lateration,6.2603358667323175 +22,Square lateration,76.8495999708694 +22,Square lateration,12.008414320489498 +22,Square lateration,13.833427336191827 +22,Square lateration,7.036986634983064 +22,Square lateration,47.08282292442138 +23,MDS-MAP,2.946230730460074 +23,MDS-MAP,4.339670262505556 +23,MDS-MAP,2.265784352296047 +23,MDS-MAP,3.7057631288632087 +23,MDS-MAP,2.5070233306281535 +23,MDS-MAP,4.849031517294981 +23,MDS-MAP,2.2469177659462716 +23,MDS-MAP,2.719722271010889 +23,MDS-MAP,2.119784505761398 +23,MDS-MAP,2.785725687426313 +23,MDS-MAP,4.135514071255931 +23,MDS-MAP,2.0717999717546953 +23,MDS-MAP,3.2576630973783427 +23,MDS-MAP,4.5431475810843045 +23,MDS-MAP,2.756222239921567 +23,MDS-MAP,1.9641221749212714 +23,Circular lateration,67.13422125364228 +23,Circular lateration,97.64322600984542 +23,Circular lateration,28.140342154250096 +23,Circular lateration,43.854805240361515 +23,Circular lateration,67.88517556962218 +23,Circular lateration,44.07300757165231 +23,Circular lateration,55.97818035460755 +23,Circular lateration,51.06911971134757 +23,Circular lateration,56.32756153369408 +23,Circular lateration,19.35833726901824 +23,Circular lateration,64.17374115228657 +23,Circular lateration,70.59875440337206 +23,Circular lateration,1.819684337568812 +23,Circular lateration,41.86399605247777 +23,Circular lateration,49.859315387894355 +23,Circular lateration,13.663952576577543 +23,Square lateration,68.95591495229476 +23,Square lateration,90.60077168231615 +23,Square lateration,23.147567470908278 +23,Square lateration,24.18980847316066 +23,Square lateration,42.95012623948193 +23,Square lateration,49.53097903957901 +23,Square lateration,21.94362783943184 +23,Square lateration,51.644129837475305 +23,Square lateration,59.47651532175785 +23,Square lateration,37.76398169244784 +23,Square lateration,45.17357334234201 +23,Square lateration,68.71153863520559 +23,Square lateration,42.08721307366177 +23,Square lateration,22.0368640823992 +23,Square lateration,24.30512729007005 +23,Square lateration,7.9472482184262825 +24,MDS-MAP,4.374575748025075 +24,MDS-MAP,2.8652641655371953 +24,MDS-MAP,4.507446770168268 +24,MDS-MAP,3.1883058751723916 +24,MDS-MAP,1.1306269052347275 +24,MDS-MAP,1.7252124430754079 +24,MDS-MAP,2.7832300950695665 +24,MDS-MAP,2.293167215223234 +24,MDS-MAP,1.1850921832978738 +24,MDS-MAP,5.426110622622798 +24,MDS-MAP,3.6804699229034226 +24,MDS-MAP,2.3418933281772962 +24,MDS-MAP,1.146434938204854 +24,MDS-MAP,1.4108568539690587 +24,MDS-MAP,1.2034779051800744 +24,MDS-MAP,7.254101956700976 +24,Circular lateration,96.62673680815409 +24,Circular lateration,69.0378520677268 +24,Circular lateration,26.633690067582002 +24,Circular lateration,65.52538934762981 +24,Circular lateration,34.35771777475692 +24,Circular lateration,65.28595752161173 +24,Circular lateration,52.851910242495826 +24,Circular lateration,59.667771551182106 +24,Circular lateration,44.5603519075226 +24,Circular lateration,69.22127172316036 +24,Circular lateration,13.336441797844314 +24,Circular lateration,45.794390272287366 +24,Circular lateration,0.7059179926296151 +24,Circular lateration,1.138449597496588 +24,Circular lateration,0.6226127638133266 +24,Circular lateration,8.185608531011333 +24,Square lateration,69.99097068057958 +24,Square lateration,63.94834443473513 +24,Square lateration,21.503236618281452 +24,Square lateration,63.8407531888733 +24,Square lateration,35.40343204748949 +24,Square lateration,59.47590766303715 +24,Square lateration,28.313661482344152 +24,Square lateration,60.80749952671574 +24,Square lateration,38.43807277165695 +24,Square lateration,65.48647919899193 +24,Square lateration,54.913215402769666 +24,Square lateration,21.228289592620627 +24,Square lateration,13.241203050189558 +24,Square lateration,9.120552284231382 +24,Square lateration,42.16394076666998 +24,Square lateration,57.949480653936845 +25,MDS-MAP,1.9818472253431767 +25,MDS-MAP,2.455645041139276 +25,MDS-MAP,1.191918597375824 +25,MDS-MAP,3.2053757394060503 +25,MDS-MAP,2.2215532694811664 +25,MDS-MAP,0.5892651958340627 +25,MDS-MAP,1.283696199831959 +25,MDS-MAP,1.2678388062833732 +25,MDS-MAP,0.9899597234529104 +25,MDS-MAP,1.4360359658626807 +25,MDS-MAP,0.15335390921487368 +25,MDS-MAP,1.698685412073158 +25,MDS-MAP,1.1686823662001027 +25,MDS-MAP,1.142474843113804 +25,MDS-MAP,1.932283757110502 +25,MDS-MAP,1.7473378478867516 +25,Circular lateration,58.193223105655235 +25,Circular lateration,49.19428304755718 +25,Circular lateration,71.91993969813228 +25,Circular lateration,100.64479219243462 +25,Circular lateration,41.76787607338637 +25,Circular lateration,14.885557713691828 +25,Circular lateration,66.48344327905635 +25,Circular lateration,26.50421845708952 +25,Circular lateration,35.1517199650461 +25,Circular lateration,14.603470998836055 +25,Circular lateration,80.94309720231453 +25,Circular lateration,39.12463184383552 +25,Circular lateration,1.0102357274325606 +25,Circular lateration,1.0978989756289343 +25,Circular lateration,1.9701005188750624 +25,Circular lateration,4.841102820505347 +25,Square lateration,54.528547390313676 +25,Square lateration,80.1747882643584 +25,Square lateration,72.37860489304602 +25,Square lateration,86.53432907821617 +25,Square lateration,66.9146155882158 +25,Square lateration,31.422449840071216 +25,Square lateration,48.563389105665934 +25,Square lateration,40.33239274042587 +25,Square lateration,40.885933303964606 +25,Square lateration,35.73082022519667 +25,Square lateration,34.13770557297621 +25,Square lateration,32.67422047578089 +25,Square lateration,13.48940304223426 +25,Square lateration,22.338252675496733 +25,Square lateration,69.88245158506247 +25,Square lateration,23.890329212249316 +26,MDS-MAP,11.63293837464996 +26,MDS-MAP,40.193074180115424 +26,MDS-MAP,52.73827099768758 +26,MDS-MAP,160.35701624075972 +26,MDS-MAP,52.99576846752935 +26,MDS-MAP,15.139457247366462 +26,MDS-MAP,66.67577163260371 +26,MDS-MAP,70.29591626828888 +26,MDS-MAP,65.71701818567425 +26,MDS-MAP,0.6808515939304786 +26,MDS-MAP,56.868708260497776 +26,MDS-MAP,13.495207975457584 +26,MDS-MAP,133.83379057954843 +26,MDS-MAP,23.25290611124651 +26,MDS-MAP,13.602447144839045 +26,MDS-MAP,6.500238230306064 +26,Circular lateration,24.358584586282742 +26,Circular lateration,13.287779497655839 +26,Circular lateration,58.82188038930167 +26,Circular lateration,112.57535412463584 +26,Circular lateration,55.90852573006228 +26,Circular lateration,40.9987941098011 +26,Circular lateration,37.15975960181108 +26,Circular lateration,69.3085272913823 +26,Circular lateration,103.96609069217446 +26,Circular lateration,16.887236320253088 +26,Circular lateration,32.758492189437135 +26,Circular lateration,36.88671711938151 +26,Circular lateration,8.583063356562155 +26,Circular lateration,1.7981810445490451 +26,Circular lateration,1.3896507881841451 +26,Circular lateration,1.3075207766939076 +26,Square lateration,16.311379468545347 +26,Square lateration,35.76671873235115 +26,Square lateration,42.712497087301145 +26,Square lateration,104.69810184851322 +26,Square lateration,25.487307030738272 +26,Square lateration,43.09142443312215 +26,Square lateration,49.04172760167667 +26,Square lateration,49.64988823383055 +26,Square lateration,50.75132042932953 +26,Square lateration,11.846649758411898 +26,Square lateration,28.95901498799316 +26,Square lateration,71.29369311436 +26,Square lateration,52.18181641213668 +26,Square lateration,6.412557359468619 +26,Square lateration,27.714713021623414 +26,Square lateration,36.44942190588798 +27,MDS-MAP,42.68079462983385 +27,MDS-MAP,99.86052295368206 +27,MDS-MAP,3.545251662182522 +27,MDS-MAP,82.69183469751236 +27,MDS-MAP,7.934389515160054 +27,MDS-MAP,54.71596109554526 +27,MDS-MAP,99.49127099926878 +27,MDS-MAP,113.88425855038005 +27,MDS-MAP,38.511923003386 +27,MDS-MAP,20.477030537866934 +27,MDS-MAP,16.505616324329118 +27,MDS-MAP,101.39269709282358 +27,MDS-MAP,22.65907491834107 +27,MDS-MAP,52.95335356350707 +27,MDS-MAP,14.735543961480511 +27,MDS-MAP,68.80659969857739 +27,Circular lateration,75.3333097924693 +27,Circular lateration,43.520806046509485 +27,Circular lateration,53.637244590803974 +27,Circular lateration,38.288722997747065 +27,Circular lateration,57.6108532032378 +27,Circular lateration,57.76715851496237 +27,Circular lateration,78.66703287525907 +27,Circular lateration,85.82836079828114 +27,Circular lateration,37.91680449328673 +27,Circular lateration,34.58127700124481 +27,Circular lateration,67.76359896249048 +27,Circular lateration,86.27533864289673 +27,Circular lateration,17.630108022065123 +27,Circular lateration,0.4880156502566974 +27,Circular lateration,0.5233155584928728 +27,Circular lateration,2.8346114660048736 +27,Square lateration,53.8319003732019 +27,Square lateration,64.79479511033875 +27,Square lateration,15.281870571593192 +27,Square lateration,33.88869072146075 +27,Square lateration,56.50842554815788 +27,Square lateration,52.54094245670175 +27,Square lateration,62.43300284438112 +27,Square lateration,74.46262949393181 +27,Square lateration,31.225839720349644 +27,Square lateration,21.476809097463956 +27,Square lateration,66.05724702214226 +27,Square lateration,85.34970490364616 +27,Square lateration,11.335232238392269 +27,Square lateration,15.818882328663422 +27,Square lateration,2.7474438797065748 +27,Square lateration,23.73251350805657 +28,MDS-MAP,30.500128813021202 +28,MDS-MAP,102.43708339974626 +28,MDS-MAP,89.66569265207025 +28,MDS-MAP,43.652393626759746 +28,MDS-MAP,9.70264368763485 +28,MDS-MAP,51.23464001972041 +28,MDS-MAP,45.97895699252704 +28,MDS-MAP,116.92626058392128 +28,MDS-MAP,81.1536279870134 +28,MDS-MAP,100.55119105625111 +28,MDS-MAP,93.54662145828814 +28,MDS-MAP,111.65621083779494 +28,MDS-MAP,43.014250401231756 +28,MDS-MAP,51.42542068618485 +28,MDS-MAP,3.4730596931521864 +28,MDS-MAP,1.8879590892769398 +28,Circular lateration,40.52344887006936 +28,Circular lateration,29.484251408563637 +28,Circular lateration,29.759331100590817 +28,Circular lateration,82.9816460488956 +28,Circular lateration,37.59803699600615 +28,Circular lateration,76.60131878478882 +28,Circular lateration,70.33211834540052 +28,Circular lateration,114.69136410055505 +28,Circular lateration,59.17469401923126 +28,Circular lateration,41.805659160473624 +28,Circular lateration,48.367682460351176 +28,Circular lateration,61.34284697831364 +28,Circular lateration,1.9072095561914577 +28,Circular lateration,2.131761256227453 +28,Circular lateration,0.4264876771382929 +28,Circular lateration,1.4645842750376394 +28,Square lateration,38.760328173063115 +28,Square lateration,50.19858645390992 +28,Square lateration,45.985831180291434 +28,Square lateration,15.538206842525446 +28,Square lateration,12.446418852616908 +28,Square lateration,21.880330095356726 +28,Square lateration,26.68753908025812 +28,Square lateration,64.81990641003765 +28,Square lateration,68.27469321910384 +28,Square lateration,52.794993360845126 +28,Square lateration,46.75860383915221 +28,Square lateration,56.834053371212775 +28,Square lateration,24.720836617059007 +28,Square lateration,17.639405212189413 +28,Square lateration,10.37770484016742 +28,Square lateration,17.536247642231544 +29,MDS-MAP,68.9363186050703 +29,MDS-MAP,78.54905729672839 +29,MDS-MAP,95.30407809279569 +29,MDS-MAP,47.812976571002864 +29,MDS-MAP,81.61752373549706 +29,MDS-MAP,28.91973389829186 +29,MDS-MAP,93.89215840349235 +29,MDS-MAP,67.6659883445706 +29,MDS-MAP,5.794889844664516 +29,MDS-MAP,48.30913767023259 +29,MDS-MAP,95.08459858634909 +29,MDS-MAP,30.47461579568944 +29,MDS-MAP,59.5121225789394 +29,MDS-MAP,43.27215982414858 +29,MDS-MAP,15.284900467613198 +29,MDS-MAP,14.647578100567465 +29,Circular lateration,97.48409624108919 +29,Circular lateration,35.25232304656789 +29,Circular lateration,28.04238763255003 +29,Circular lateration,57.6018549595341 +29,Circular lateration,47.40663179920113 +29,Circular lateration,101.6580199083523 +29,Circular lateration,99.74281824298546 +29,Circular lateration,25.916652376130088 +29,Circular lateration,48.11018487802395 +29,Circular lateration,9.543046153094837 +29,Circular lateration,70.45446566240952 +29,Circular lateration,76.37258270035672 +29,Circular lateration,2.4994837689084313 +29,Circular lateration,12.04016209997336 +29,Circular lateration,2.2499410825352406 +29,Circular lateration,1.0430406465255266 +29,Square lateration,59.95906924064238 +29,Square lateration,36.71791616927682 +29,Square lateration,39.0707207054637 +29,Square lateration,31.081992244121942 +29,Square lateration,41.603553565142334 +29,Square lateration,85.22654740570816 +29,Square lateration,85.11668475121868 +29,Square lateration,32.599713321163726 +29,Square lateration,49.90777939080009 +29,Square lateration,7.0093020607128 +29,Square lateration,72.06293279866672 +29,Square lateration,70.28881322155365 +29,Square lateration,20.205905307357348 +29,Square lateration,4.3792947522206065 +29,Square lateration,7.33192611049785 +29,Square lateration,9.417298779036654 diff --git a/results/tables/monte_carlo_metrics.csv b/results/tables/monte_carlo_metrics.csv new file mode 100644 index 0000000..6433cef --- /dev/null +++ b/results/tables/monte_carlo_metrics.csv @@ -0,0 +1,91 @@ +repetition,method,rmse,mae,mean,std,median,max,p95 +0,MDS-MAP,2.185218449708254,1.8458787821819298,1.8458787821819298,1.1695773571833123,1.662450878006072,3.9786433573742683,3.6190407320796423 +0,Circular lateration,43.78947366843516,32.206482229766934,32.206482229766934,29.669184460350156,27.674471499205733,96.88504803126659,91.33955515642728 +0,Square lateration,44.0939637244304,34.019038921879854,34.019038921879854,28.05321064981703,21.558708106491665,92.82196959355585,84.87322026587962 +1,MDS-MAP,104.12076076763218,87.56542088437342,87.56542088437342,56.33320413550988,117.43184088620788,154.50445738294167,154.44482717944248 +1,Circular lateration,60.89413219933657,54.2240019721968,54.2240019721968,27.71015962475634,58.87763429444088,113.07254488237886,107.54515548490463 +1,Square lateration,61.569113134199235,58.60133441233858,58.60133441233858,18.884896007791138,59.719879091337816,86.93801531391847,84.01272360227419 +2,MDS-MAP,8.309204011897831,7.295218265267347,7.295218265267347,3.9777709553779834,6.952625161531805,13.65028634375217,13.581143903853613 +2,Circular lateration,58.90527147459289,49.75408151774144,49.75408151774144,31.533512012166153,41.24813251143627,94.71083181490397,92.94763204685577 +2,Square lateration,51.428699145885744,49.24560206341943,49.24560206341943,14.825038726740953,47.562557048841356,82.0436751907646,76.29538685792052 +3,MDS-MAP,4.562718714542838,3.6624244679488505,3.6624244679488505,2.7212219837067737,2.9239413324889405,10.496007008331187,8.816379048148963 +3,Circular lateration,44.731144318040506,37.08045295423461,37.08045295423461,25.01829891719581,40.092685957413664,77.21968011045794,75.33668398773148 +3,Square lateration,40.37648518063248,36.344284636138084,36.344284636138084,17.58844876130954,32.10106382140965,67.26928046498466,60.82472560027291 +4,MDS-MAP,37.731531242875896,28.874548437590043,28.874548437590043,24.288452039135517,25.883270592181606,88.2057668995198,69.74594678025248 +4,Circular lateration,37.232108800794904,30.564519359637014,30.564519359637014,21.261234255531907,32.34065231775183,63.88951680632521,61.58674330967082 +4,Square lateration,34.70763712101917,31.378417118604823,31.378417118604823,14.832903075770295,31.399199886450468,55.700989968264395,48.73261798554818 +5,MDS-MAP,8.745454088470565,4.7373231721726405,4.7373231721726405,7.351240465114897,3.037014129702911,32.773206869979084,12.253411191399938 +5,Circular lateration,63.12743447788416,52.88505533350713,52.88505533350713,34.470913914943516,65.61575015282035,98.6286881422611,93.52117947675772 +5,Square lateration,52.329087777359454,49.52081173409391,49.52081173409391,16.91220366501711,53.51933906158667,84.61054214239813,73.4930051835108 +6,MDS-MAP,2.062801521780494,1.7897094052718303,1.7897094052718303,1.0257145621182693,1.6155498003539472,3.86694194821288,3.1457997444972765 +6,Circular lateration,43.42985452935746,34.73688498965117,34.73688498965117,26.067241619643962,30.281996396910976,80.80282359292899,78.60966287898637 +6,Square lateration,41.53781614889254,37.147005175669584,37.147005175669584,18.58736605595249,32.928524579174955,74.69818358853158,63.912291733742556 +7,MDS-MAP,7.329853096812777,5.806914921001663,5.806914921001663,4.472860999528612,4.329566088507324,16.554267620021584,15.136518644770634 +7,Circular lateration,49.22768079299547,38.04624224012751,38.04624224012751,31.238566030831056,40.33077934159579,96.17515806770614,92.41138053125128 +7,Square lateration,46.23994292584898,39.98878001130518,39.98878001130518,23.217015204224907,41.27205620569523,90.19680481386244,73.89083724702131 +8,MDS-MAP,2.360876038225514,2.1470962365985153,2.1470962365985153,0.9816890641399094,1.9499894362935801,5.277335426175595,3.668501609696447 +8,Circular lateration,47.55326094328507,40.008212378826016,40.008212378826016,25.703220976969288,49.25537008761242,77.2192568520714,68.68686076482805 +8,Square lateration,46.351806700557724,41.81042386154252,41.81042386154252,20.00945878638461,33.0027993825655,79.44514858379279,74.94772560022531 +9,MDS-MAP,57.52895101157319,47.55908308254369,47.55908308254369,32.36840775879616,52.50280885079077,123.03355597499362,91.32771520237043 +9,Circular lateration,45.87120443806874,37.9305514989483,37.9305514989483,25.796136524385343,36.23798412456007,103.85513225229437,74.77426123066019 +9,Square lateration,37.80148521481428,33.79777306954802,33.79777306954802,16.931119868016896,30.317145927841928,63.88645630943104,57.18777726757146 +10,MDS-MAP,1.85488763269496,1.685840525450664,1.685840525450664,0.7736600368850265,1.3525067450922261,3.2477428625751004,2.9707277070263696 +10,Circular lateration,58.140560551166196,48.20074053107887,48.20074053107887,32.5117423934712,47.43354721443126,114.8385863544283,94.12169641919814 +10,Square lateration,45.98335566739533,41.83650571762525,41.83650571762525,19.083390363698168,40.74436093552332,89.45446667558086,69.05719659815932 +11,MDS-MAP,4.374690752867252,3.642163882505203,3.642163882505203,2.4233368391944325,3.302262558017393,11.475930347382185,6.885478285992145 +11,Circular lateration,46.32486086309956,37.53540020502426,37.53540020502426,27.1493363718931,37.14343873879638,79.62054347862745,75.6832888293246 +11,Square lateration,40.447821876509984,32.986906372453355,32.986906372453355,23.40705668231006,31.35540088032791,80.93635896211804,75.92612956207503 +12,MDS-MAP,53.8776564431605,45.4481932648552,45.4481932648552,28.935507473821914,51.25235182574894,95.0659939561794,87.02321209227765 +12,Circular lateration,53.40237345336564,44.07606633004481,44.07606633004481,30.15151517456828,47.76372684704776,90.70643165184782,82.18027326146371 +12,Square lateration,47.78124737925289,40.21461923385566,40.21461923385566,25.803720681199604,44.650599346528466,84.1085157934101,76.05988162926346 +13,MDS-MAP,3.0838168228627265,2.1824176770422774,2.1824176770422774,2.1787563608408704,1.616318804020763,9.572599566724628,5.940865266126406 +13,Circular lateration,47.58794103662907,40.22828769028115,40.22828769028115,25.42237206898008,46.94407148106981,76.71289949529327,69.80745270801845 +13,Square lateration,46.34668603920483,43.3520946182295,43.3520946182295,16.389362374073634,43.27310011910929,65.84431477484452,63.78112088505939 +14,MDS-MAP,5.199427827353785,3.9022565062431633,3.9022565062431633,3.4360506240950226,2.8243087540184,15.192536389037334,10.549598789215855 +14,Circular lateration,41.46548551790006,31.919655916221906,31.919655916221906,26.467377192029808,32.333376551457306,79.63666556574412,77.13283661950402 +14,Square lateration,42.09475799999618,32.14012523925396,32.14012523925396,27.184204985309258,24.297664090722762,84.57357738605965,81.97083683853599 +15,MDS-MAP,1.3196834826611386,1.2201643103880464,1.2201643103880464,0.5027559547771608,1.120855498796003,2.447716323126961,2.102378704758175 +15,Circular lateration,60.13036542114176,55.67214534995453,55.67214534995453,22.72164337836453,57.138248206228496,92.56010223504823,87.36543253911728 +15,Square lateration,39.60950104561243,37.37600779791989,37.37600779791989,13.112841575044081,36.48897512424261,63.931401275998496,55.94434970029618 +16,MDS-MAP,66.39400918244505,54.80384048196851,54.80384048196851,37.47937464453679,50.348531802752454,131.29314676931065,113.98755545400145 +16,Circular lateration,52.98274188678472,42.47293406073109,42.47293406073109,31.673661141624283,47.52112125027104,99.15759476797687,83.21927333026754 +16,Square lateration,42.989345265532585,38.50630752392992,38.50630752392992,19.114080862853633,38.25650588703249,74.32996795543133,66.71932784643234 +17,MDS-MAP,3.0582610407542914,2.693981245497273,2.693981245497273,1.4475585108397115,2.3317485080611497,6.341403276845636,5.24216799618588 +17,Circular lateration,53.038800761023275,43.326313379112904,43.326313379112904,30.593217469603054,39.36155023702261,98.33996430050375,95.91140339221971 +17,Square lateration,48.394089022730206,45.28952719443483,45.28952719443483,17.0542246626601,45.65228569153828,76.66926777515424,68.03509007392185 +18,MDS-MAP,50.81648323314002,44.00018990046605,44.00018990046605,25.422396757719888,40.5026502176855,94.0302941222651,89.04636034890734 +18,Circular lateration,50.38968903699181,38.02580520999808,38.02580520999808,33.062953579134685,32.40680701466265,103.98084517106099,91.81603543555177 +18,Square lateration,44.02894711317046,36.466846993765955,36.466846993765955,24.67219597497605,31.952676915607164,88.58172204599529,72.4115601097799 +19,MDS-MAP,1.9813880538858075,1.789150203258857,1.789150203258857,0.8513754578681362,1.6340018441926092,3.5978247075835905,3.3325205504004245 +19,Circular lateration,39.02490480403007,32.918113142257305,32.918113142257305,20.96046330874287,30.112163833191325,76.09233791394873,61.46379632211923 +19,Square lateration,37.99462125118168,32.57905132676278,32.57905132676278,19.54985060477196,32.33615842426702,69.09042188907085,60.72675858581077 +20,MDS-MAP,61.63224191111844,53.15854799132299,53.15854799132299,31.18817113017105,48.36736830700242,113.509781745756,104.93827588317383 +20,Circular lateration,46.90803333848101,36.404082721097424,36.404082721097424,29.5821965533248,37.34211030677703,92.71719695510292,86.89329142765163 +20,Square lateration,34.27778241046017,30.02118982730481,30.02118982730481,16.543715674895484,26.374107337771324,57.6455479427844,57.31117883965203 +21,MDS-MAP,60.5847543897754,51.43041663113541,51.43041663113541,32.022253350088285,47.073560590732164,122.69000685998019,121.38873199572672 +21,Circular lateration,37.225869399929884,28.48838290365702,28.48838290365702,23.961998917353664,23.159239585090702,83.71874032272832,72.02194918005658 +21,Square lateration,34.736442305808644,29.656712241893114,29.656712241893114,18.08590177642022,24.13421960214432,78.46165875539442,65.5218849930337 +22,MDS-MAP,2.200947200025575,1.9218203208570137,1.9218203208570137,1.0727419221981882,1.8491444137833728,4.204940503082699,3.916212588435606 +22,Circular lateration,40.7644238161979,31.63379802838127,31.63379802838127,25.71071899745676,29.83652674676005,84.9502592125001,70.88993286758841 +22,Square lateration,42.41850774493398,36.81852830064753,36.81852830064753,21.064799383840366,40.305918757464894,76.8495999708694,67.03940151809478 +23,MDS-MAP,3.211103347989262,3.075882668031813,3.075882668031813,0.9220252295731095,2.77097396367394,4.849031517294981,4.619618565136974 +23,Circular lateration,53.693177933212304,48.34021378613865,48.34021378613865,23.370517488451295,50.46421754962096,97.64322600984542,77.3598723049904 +23,Square lateration,47.54432223995426,42.529061699434905,42.529061699434905,21.254211070333046,42.51866965657185,90.60077168231615,74.36712913480011 +24,MDS-MAP,3.3758453649322036,2.9072666830351386,2.9072666830351386,1.71584741793905,2.5625617116234314,7.254101956700976,5.883108456142343 +24,Circular lateration,50.01471051173797,40.84700437293155,40.84700437293155,28.8616267963305,45.17737108990498,96.62673680815409,76.0726379944088 +24,Square lateration,48.37527761305981,44.11406496019518,44.11406496019518,19.8523740854409,48.53857808471982,69.99097068057958,66.61260206938884 +25,MDS-MAP,1.688195866735363,1.5291221187256046,1.5291221187256046,0.7153955762279225,1.35986608284732,3.2053757394060503,2.6430777157059695 +25,Circular lateration,48.57854970451968,38.02097447621735,38.02097447621735,30.23707974116083,37.138175904440814,100.64479219243462,85.86852094984455 +25,Square lateration,51.77768437386115,47.11738956207964,47.11738956207964,21.46812055058415,40.60916302219523,86.53432907821617,81.76467346782285 +26,MDS-MAP,65.7106616279215,48.99871134315633,48.99871134315633,43.78375655753212,46.4656725889015,160.35701624075972,140.46459699485126 +26,Circular lateration,50.930548543361965,38.49975985113552,38.49975985113552,33.342004533810545,34.82260465440932,112.57535412463584,106.1184065502898 +26,Square lateration,46.90830731876349,40.77301446408061,40.77301446408061,23.19376181268218,39.58095949659456,104.69810184851322,79.6447952978983 +27,MDS-MAP,63.881520230218655,52.55288270024229,52.55288270024229,36.31863360340543,47.81707409667046,113.88425855038005,104.5155874572127 +27,Circular lateration,54.26294140659503,46.16665991350053,46.16665991350053,28.51501924471994,48.57902531865673,86.27533864289673,85.94010525943503 +27,Square lateration,48.67524865466301,41.96787061363675,41.96787061363675,24.657203161557426,43.21481658908125,85.34970490364616,77.1843983463604 +28,MDS-MAP,71.71949947564966,61.05038381153715,61.05038381153715,37.63691328339394,51.33003035295263,116.92626058392128,112.97372327432653 +28,Circular lateration,54.21449099352405,43.66202756486465,43.66202756486465,32.13780301470372,41.16455401527149,114.69136410055505,90.90907556181045 +28,Square lateration,40.410864637426094,35.70335532437629,35.70335532437629,18.929035879455295,32.72393362666062,68.27469321910384,65.6836031123042 +29,MDS-MAP,61.93888214183786,54.69236486347834,54.69236486347834,29.071813610792166,53.91063012458599,95.30407809279569,95.13946846296074 +29,Circular lateration,56.68547804599702,44.71360569988986,44.71360569988986,34.84159707329714,41.32947742288451,101.6580199083523,100.22161865932718 +29,Square lateration,48.7219906646825,40.74871561397397,40.74871561397397,26.709072431308492,37.89431843737026,85.22654740570816,85.14415041484105 diff --git a/results/tables/single_node_positions.csv b/results/tables/single_node_positions.csv new file mode 100644 index 0000000..46a4008 --- /dev/null +++ b/results/tables/single_node_positions.csv @@ -0,0 +1,17 @@ +node,actual_x,actual_y,mdsmap_x,mdsmap_y,mdsmap_error,circular_lateration_x,circular_lateration_y,circular_lateration_error,square_lateration_x,square_lateration_y,square_lateration_error +4,65.27848026851319,29.830276735556925,65.65635742866027,31.60002667173938,1.8096425019264493,45.22271872981485,35.18571627500968,20.758475463238277,46.72684011434851,37.050052710804806,19.90699669820593 +5,96.69622001623905,91.98501605372782,94.65231618317293,94.6534381443402,3.361252643359399,61.65627696232398,53.38388660349702,52.1329531491847,42.1214436463396,41.03707451635823,74.6598885796099 +6,63.587080414465134,75.27320970790866,63.89069512631613,76.41634759020968,1.1827705234761403,52.415884672274515,42.53630652523831,34.59046753517319,49.948882459523645,42.16823817304116,35.80418388655937 +7,51.51536963223518,82.589525837557,51.43669862062896,83.01107965492646,0.4288318423413857,93.40686018098665,39.08755245973734,60.39303493086488,74.53976989458292,21.47352794300486,65.30917398105493 +8,44.83805454001032,33.881245331376185,47.32380386998021,35.57076823060911,3.0055677264833345,46.80673119048737,37.819436381357534,4.402844137632711,46.72684011434851,37.050052710804806,3.6890176407479194 +9,27.789921550015904,22.633305684340343,29.543834536888305,24.11083930947994,2.293319946919274,22.262720946818927,59.959190017735665,37.73289795096564,18.36902871671778,63.991316571515455,42.41742903949016 +10,52.58168433452484,43.09120606844314,53.08388149707605,44.520824415072006,1.5152592540856946,44.47226904506267,31.951719461893354,13.778634845094956,47.142506255827556,37.050052710804806,8.128972386611114 +11,66.31806204725955,1.2840482366806572,66.40619703129819,3.203587563304474,1.9215616050147621,22.05073587047681,87.46476745611605,96.88504803126659,30.436372117522012,75.26533529668862,82.22363715665422 +12,44.77019015387208,36.51808011323914,48.06032430961217,37.70939461959338,3.499173190314767,81.46146959597802,59.21124163729637,43.141969902354454,65.17929821604753,46.217332217109416,22.596618845924425 +13,19.539759987155403,59.486587100605284,19.165142406868064,58.607909253660154,0.955203166961077,32.59813654362682,95.50825158633785,38.31555181141581,35.49173343096512,79.0518245853265,25.244087913520477 +14,43.531315595064456,29.999150374514983,46.533994145758776,32.60942325036123,3.9786433573742683,55.75639682122007,43.039898087104824,17.87494648634003,52.93283670992049,43.20300168657272,16.208957052938743 +15,20.941612123621955,87.46240571921795,21.10127395440427,87.89525220510524,0.46135450637631126,90.72908375752743,31.441354488009765,89.49105753148085,82.61843345326878,18.094634024447277,92.82196959355585 +16,79.74623155214327,60.6709676684979,82.57515955749263,61.70177914688235,3.0108812602656734,81.46146959597802,59.21124163729637,2.2522969682493965,65.17929821604753,46.217332217109416,20.5207973670589 +17,34.51005786672921,94.68197909796484,34.000057208416735,95.61737549512173,1.0653952746719206,32.59813654362682,95.50825158633785,2.082827254184974,35.49173343096512,79.0518245853265,15.66095198263396 +18,56.33773745025456,43.2762739619952,56.342564645803634,43.69818109698468,0.4219347489504768,55.75639682122007,43.039898087104824,0.6275591455762581,52.93283670992049,43.20300168657272,3.4056890459748512 +19,90.0449599004222,31.93418039018624,90.19968543561002,31.330421983846723,0.6232689663899446,90.72908375752743,31.441354488009765,0.8431505332481255,82.61843345326878,18.094634024447277,15.706251579536975 diff --git a/scripts/run_monte_carlo.py b/scripts/run_monte_carlo.py new file mode 100644 index 0000000..52a40cc --- /dev/null +++ b/scripts/run_monte_carlo.py @@ -0,0 +1,20 @@ +"""Run repeated experiments and save error distributions and metrics.""" + +from pathlib import Path +import sys + +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) + +from mdsmap_sim.experiment import run_monte_carlo +from mdsmap_sim.plots import plot_error_distribution +from mdsmap_sim.utils import ensure_output_dirs, load_config + + +root = Path(__file__).resolve().parents[1] +config = load_config(root / "config" / "default.yaml") +figures, tables = ensure_output_dirs(root / config["output_dir"]) +metrics, errors = run_monte_carlo(config) +metrics.to_csv(tables / "monte_carlo_metrics.csv", index=False) +errors.to_csv(tables / "monte_carlo_errors.csv", index=False) +plot_error_distribution(errors, figures / "error_distribution.png") +print(metrics.groupby("method").mean(numeric_only=True).to_string()) diff --git a/scripts/run_remote_carlo.py b/scripts/run_remote_carlo.py new file mode 100644 index 0000000..9d5c999 --- /dev/null +++ b/scripts/run_remote_carlo.py @@ -0,0 +1,18 @@ +from pathlib import Path +import sys + +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) + +from mdsmap_sim.experiment import run_monte_carlo +from mdsmap_sim.plots import plot_error_distribution +from mdsmap_sim.utils import ensure_output_dirs, load_config + + +root = Path(__file__).resolve().parents[1] +config = load_config(root / "config" / "default.yaml") +figures, tables = ensure_output_dirs(root / config["output_dir"]) +metrics, errors = run_monte_carlo(config) +metrics.to_csv(tables / "monte_carlo_metrics.csv", index=False) +errors.to_csv(tables / "monte_carlo_errors.csv", index=False) +plot_error_distribution(errors, figures / "error_distribution.png") +print(metrics.groupby("method").mean(numeric_only=True).to_string()) \ No newline at end of file diff --git a/scripts/run_single.py b/scripts/run_single.py new file mode 100644 index 0000000..32aaa25 --- /dev/null +++ b/scripts/run_single.py @@ -0,0 +1,20 @@ +from pathlib import Path +import sys + +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) + +from mdsmap_sim.experiment import run_single_experiment +from mdsmap_sim.plots import plot_positions +from mdsmap_sim.utils import ensure_output_dirs, load_config + + +root = Path(__file__).resolve().parents[1] +config = load_config(root / "config" / "default.yaml") +figures, tables = ensure_output_dirs(root / config["output_dir"]) +result = run_single_experiment(config) +result["node_table"].to_csv(tables / "single_node_positions.csv", index=False) +plot_positions(result, figures / "single_positions.png") +print(result["node_table"].to_string(index=False)) +print("\nMetrics:") +for method, metrics in result["metrics"].items(): + print(method, metrics) \ No newline at end of file diff --git a/scripts/run_sweep.py b/scripts/run_sweep.py new file mode 100644 index 0000000..f3f3218 --- /dev/null +++ b/scripts/run_sweep.py @@ -0,0 +1,16 @@ +"""Small noise sweep built on the main Monte Carlo pipeline.""" +from pathlib import Path +import sys + +sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src")) + +from mdsmap_sim.experiment import run_monte_carlo +from mdsmap_sim.utils import load_config + +root = Path(__file__).resolve().parents[1] +config = load_config(root / "config" / "default.yaml") +for sigma in (0.0, 0.5, 1.0, 2.0, 5.0): + config["noise_sigma"] = sigma + metrics, _ = run_monte_carlo(config) + summary = metrics.groupby("method")["rmse"].mean() + print(f"sigma={sigma:.1f}\n{summary.to_string()}\n") \ No newline at end of file diff --git a/src/mdsmap_sim/__init__.py b/src/mdsmap_sim/__init__.py new file mode 100644 index 0000000..9904d20 --- /dev/null +++ b/src/mdsmap_sim/__init__.py @@ -0,0 +1,5 @@ +"""MDS-MAP localization simulation.""" + +from .experiment import run_monte_carlo, run_single_experiment + +__all__ = ["run_monte_carlo", "run_single_experiment"] \ No newline at end of file diff --git a/src/mdsmap_sim/experiment.py b/src/mdsmap_sim/experiment.py new file mode 100644 index 0000000..3b397cf --- /dev/null +++ b/src/mdsmap_sim/experiment.py @@ -0,0 +1,55 @@ +from typing import Any + +import numpy as np +import pandas as pd + +from .lateration import estimate_all +from .mds_map import classical_mds, procrustes_align +from .metrics import error_metrics, localization_errors +from .network import generate_network +from .ranging import measure_distances +from .shortest_path import complete_distances + + +def run_single_experiment(config: dict[str, Any], seed: int | None = None) -> dict[str, Any]: + rng = np.random.default_rng(config["seed"] if seed is None else seed) + area = tuple(config["area_size"]) + network = generate_network( + area, config["anchor_count"], config["unknown_count"], config["radio_range"], rng + ) + measured = measure_distances( + network.distances, network.adjacency, rng, config["noise_model"], + config["noise_sigma"], config["multiplicative_sigma"], + ) + completed = complete_distances(measured) + mds = procrustes_align(classical_mds(completed), network.positions, network.anchors) + # The completed anchor ranges keep the baselines defined when an + # unknown is not directly connected to every anchor. + baseline_ranges = completed[np.ix_(network.unknowns, network.anchors)] + circular, square = estimate_all( + network.positions, network.anchors, network.unknowns, baseline_ranges + ) + actual = network.positions[network.unknowns] + estimates = {"MDS-MAP": mds[network.unknowns], "Circular lateration": circular, "Square lateration": square} + errors = {name: localization_errors(actual, estimate) for name, estimate in estimates.items()} + rows = [] + for node_offset, node in enumerate(network.unknowns): + row = {"node": int(node), "actual_x": actual[node_offset, 0], "actual_y": actual[node_offset, 1]} + for name, estimate in estimates.items(): + key = name.lower().replace(" ", "_").replace("-", "") + row.update({f"{key}_x": estimate[node_offset, 0], f"{key}_y": estimate[node_offset, 1], + f"{key}_error": errors[name][node_offset]}) + rows.append(row) + return {"network": network, "estimates": estimates, "errors": errors, "node_table": pd.DataFrame(rows), + "metrics": {name: error_metrics(values) for name, values in errors.items()}} + + +def run_monte_carlo(config: dict[str, Any]) -> tuple[pd.DataFrame, pd.DataFrame]: + metric_rows, error_rows = [], [] + for repetition in range(int(config["repetitions"])): + result = run_single_experiment(config, int(config["seed"]) + repetition) + for method, metrics in result["metrics"].items(): + metric_rows.append({"repetition": repetition, "method": method, **metrics}) + error_rows.extend({"repetition": repetition, "method": method, "error": error} + for error in result["errors"][method]) + return pd.DataFrame(metric_rows), pd.DataFrame(error_rows) \ No newline at end of file diff --git a/src/mdsmap_sim/lateration.py b/src/mdsmap_sim/lateration.py new file mode 100644 index 0000000..a011034 --- /dev/null +++ b/src/mdsmap_sim/lateration.py @@ -0,0 +1,47 @@ +import numpy as np +from scipy.optimize import least_squares + + +def circular_lateration( + anchors: np.ndarray, anchor_indices: np.ndarray, distances: np.ndarray +) -> np.ndarray: + """Estimate a point from anchor ranges by nonlinear least squares.""" + if len(anchor_indices) < 3: + raise ValueError("Circular lateration requires at least 3 anchors.") + anchor_points = anchors[anchor_indices] + initial = anchor_points.mean(axis=0) + + def residual(point: np.ndarray) -> np.ndarray: + return np.linalg.norm(point - anchor_points, axis=1) - distances + + return least_squares(residual, initial).x + + +def square_lateration( + anchors: np.ndarray, anchor_indices: np.ndarray, distances: np.ndarray +) -> np.ndarray: + """Min-max (square intersection) lateration using anchor distance bounds.""" + if len(anchor_indices) < 3: + raise ValueError("Square lateration requires at least 3 anchors.") + anchor_points = anchors[anchor_indices] + lower = np.max(anchor_points - distances[:, None], axis=0) + upper = np.min(anchor_points + distances[:, None], axis=0) + if np.any(lower > upper): + return np.mean(anchor_points, axis=0) + return (lower + upper) / 2.0 + + +def estimate_all( + positions: np.ndarray, + anchor_indices: np.ndarray, + unknown_indices: np.ndarray, + measured_distances: np.ndarray, +) -> tuple[np.ndarray, np.ndarray]: + anchor_points = positions[anchor_indices] + circular, square = [], [] + for offset, node in enumerate(unknown_indices): + row = node if measured_distances.shape[0] > node else offset + ranges = measured_distances[row, anchor_indices] + circular.append(circular_lateration(anchor_points, np.arange(len(anchor_points)), ranges)) + square.append(square_lateration(anchor_points, np.arange(len(anchor_points)), ranges)) + return np.asarray(circular), np.asarray(square) \ No newline at end of file diff --git a/src/mdsmap_sim/mds_map.py b/src/mdsmap_sim/mds_map.py new file mode 100644 index 0000000..9cf884d --- /dev/null +++ b/src/mdsmap_sim/mds_map.py @@ -0,0 +1,28 @@ +import numpy as np + + +def classical_mds(distances: np.ndarray, dimensions: int = 2) -> np.ndarray: + n = distances.shape[0] + centering = np.eye(n) - np.ones((n, n)) / n + gram = -0.5 * centering @ (distances**2) @ centering + eigenvalues, eigenvectors = np.linalg.eigh((gram + gram.T) / 2) + order = np.argsort(eigenvalues)[::-1] + eigenvalues = np.maximum(eigenvalues[order[:dimensions]], 0.0) + return eigenvectors[:, order[:dimensions]] * np.sqrt(eigenvalues) + + +def procrustes_align( + estimated: np.ndarray, reference: np.ndarray, indices: np.ndarray +) -> np.ndarray: + """Align an MDS map to known anchors using a similarity transform.""" + x = estimated[indices] + y = reference[indices] + x_mean, y_mean = x.mean(axis=0), y.mean(axis=0) + xc, yc = x - x_mean, y - y_mean + u, singular_values, vt = np.linalg.svd(xc.T @ yc) + rotation = u @ vt + if np.linalg.det(rotation) < 0: + vt[-1, :] *= -1 + rotation = u @ vt + scale = singular_values.sum() / max(np.sum(xc**2), 1e-12) + return (estimated - x_mean) @ rotation * scale + y_mean \ No newline at end of file diff --git a/src/mdsmap_sim/metrics.py b/src/mdsmap_sim/metrics.py new file mode 100644 index 0000000..b87311c --- /dev/null +++ b/src/mdsmap_sim/metrics.py @@ -0,0 +1,18 @@ +import numpy as np + + +def localization_errors(actual: np.ndarray, estimated: np.ndarray) -> np.ndarray: + return np.linalg.norm(actual - estimated, axis=1) + + +def error_metrics(errors: np.ndarray) -> dict[str, float]: + errors = np.asarray(errors, dtype=float) + return { + "rmse": float(np.sqrt(np.mean(errors**2))), + "mae": float(np.mean(np.abs(errors))), + "mean": float(np.mean(errors)), + "std": float(np.std(errors)), + "median": float(np.median(errors)), + "max": float(np.max(errors)), + "p95": float(np.percentile(errors, 95)), + } \ No newline at end of file diff --git a/src/mdsmap_sim/network.py b/src/mdsmap_sim/network.py new file mode 100644 index 0000000..d3f1a0b --- /dev/null +++ b/src/mdsmap_sim/network.py @@ -0,0 +1,33 @@ +from dataclasses import dataclass + +import numpy as np + + +@dataclass(frozen=True) +class Network: + positions: np.ndarray + anchors: np.ndarray + unknowns: np.ndarray + adjacency: np.ndarray + distances: np.ndarray + + +def generate_network( + area_size: tuple[float, float], + anchor_count: int, + unknown_count: int, + radio_range: float, + rng: np.random.Generator, +) -> Network: + if anchor_count < 3 or unknown_count < 5: + raise ValueError("At least 3 anchors and 5 unknown nodes are required.") + positions = rng.uniform([0.0, 0.0], area_size, size=(anchor_count + unknown_count, 2)) + distances = np.linalg.norm(positions[:, None, :] - positions[None, :, :], axis=2) + adjacency = (distances <= radio_range) & ~np.eye(len(positions), dtype=bool) + return Network( + positions=positions, + anchors=np.arange(anchor_count), + unknowns=np.arange(anchor_count, anchor_count + unknown_count), + adjacency=adjacency, + distances=distances, + ) \ No newline at end of file diff --git a/src/mdsmap_sim/plots.py b/src/mdsmap_sim/plots.py new file mode 100644 index 0000000..7c64315 --- /dev/null +++ b/src/mdsmap_sim/plots.py @@ -0,0 +1,36 @@ +from pathlib import Path + +import matplotlib.pyplot as plt +import pandas as pd + + +def plot_positions(result: dict, path: str | Path) -> None: + network, estimates = result["network"], result["estimates"] + fig, ax = plt.subplots(figsize=(8, 7)) + ax.scatter(network.positions[network.unknowns, 0], network.positions[network.unknowns, 1], + marker="o", label="Actual unknowns", color="black") + ax.scatter(network.positions[network.anchors, 0], network.positions[network.anchors, 1], + marker="^", s=90, label="Anchors", color="tab:green") + styles = {"MDS-MAP": ("tab:blue", "x"), "Circular lateration": ("tab:orange", "+"), + "Square lateration": ("tab:red", "s")} + for method, estimate in estimates.items(): + color, marker = styles[method] + ax.scatter(estimate[:, 0], estimate[:, 1], marker=marker, color=color, label=method) + ax.set(xlabel="x (m)", ylabel="y (m)", title="Actual and estimated node positions") + ax.legend() + ax.grid(alpha=0.25) + fig.tight_layout() + fig.savefig(path, dpi=160) + plt.close(fig) + + +def plot_error_distribution(errors: pd.DataFrame, path: str | Path) -> None: + fig, ax = plt.subplots(figsize=(8, 5)) + for method, group in errors.groupby("method"): + ax.hist(group["error"], bins=20, alpha=0.55, label=method) + ax.set(xlabel="Localization error (m)", ylabel="Node count", title="Localization error distribution") + ax.legend() + ax.grid(alpha=0.25) + fig.tight_layout() + fig.savefig(path, dpi=160) + plt.close(fig) \ No newline at end of file diff --git a/src/mdsmap_sim/ranging.py b/src/mdsmap_sim/ranging.py new file mode 100644 index 0000000..f6a0d6c --- /dev/null +++ b/src/mdsmap_sim/ranging.py @@ -0,0 +1,27 @@ +import numpy as np + + +def measure_distances( + distances: np.ndarray, + adjacency: np.ndarray, + rng: np.random.Generator, + model: str = "gaussian", + sigma: float = 1.0, + multiplicative_sigma: float = 0.02, +) -> np.ndarray: + """Measure connected links and represent unavailable links by infinity.""" + measured = np.full_like(distances, np.inf, dtype=float) + np.fill_diagonal(measured, 0.0) + links = adjacency.astype(bool) + if model == "gaussian": + noise = rng.normal(0.0, sigma, size=distances.shape) + values = distances + noise + elif model == "multiplicative": + values = distances * (1.0 + rng.normal(0.0, multiplicative_sigma, size=distances.shape)) + elif model == "none": + values = distances.copy() + else: + raise ValueError(f"Unknown noise model: {model}") + measured[links] = np.maximum(values[links], 1e-9) + measured[links] = measured[links.T] + return measured \ No newline at end of file diff --git a/src/mdsmap_sim/shortest_path.py b/src/mdsmap_sim/shortest_path.py new file mode 100644 index 0000000..39bf744 --- /dev/null +++ b/src/mdsmap_sim/shortest_path.py @@ -0,0 +1,9 @@ +import numpy as np +from scipy.sparse.csgraph import shortest_path + + +def complete_distances(measured_distances: np.ndarray) -> np.ndarray: + completed = shortest_path(measured_distances, directed=False, unweighted=False) + if not np.isfinite(completed).all(): + raise ValueError("Network is disconnected; increase radio_range or retry.") + return completed \ No newline at end of file diff --git a/src/mdsmap_sim/utils.py b/src/mdsmap_sim/utils.py new file mode 100644 index 0000000..31990a1 --- /dev/null +++ b/src/mdsmap_sim/utils.py @@ -0,0 +1,22 @@ +from pathlib import Path +from typing import Any + +import yaml + + +def load_config(path: str | Path) -> dict[str, Any]: + """Load a YAML configuration and fail clearly for malformed files.""" + with Path(path).open(encoding="utf-8") as handle: + config = yaml.safe_load(handle) + if not isinstance(config, dict): + raise ValueError(f"Configuration must be a mapping: {path}") + return config + + +def ensure_output_dirs(root: str | Path) -> tuple[Path, Path]: + root_path = Path(root) + figures = root_path / "figures" + tables = root_path / "tables" + figures.mkdir(parents=True, exist_ok=True) + tables.mkdir(parents=True, exist_ok=True) + return figures, tables \ No newline at end of file diff --git a/tests/test_lateration.py b/tests/test_lateration.py new file mode 100644 index 0000000..c32f7b3 --- /dev/null +++ b/tests/test_lateration.py @@ -0,0 +1,13 @@ +import numpy as np + +from mdsmap_sim.lateration import circular_lateration, square_lateration + + +def test_lateration_noise_free(): + anchors = np.array([[0, 0], [10, 0], [0, 10], [10, 10]], dtype=float) + target = np.array([4.0, 6.0]) + distances = np.linalg.norm(anchors - target, axis=1) + assert np.linalg.norm(circular_lateration(anchors, np.arange(4), distances) - target) < 1e-7 + estimate = square_lateration(anchors, np.arange(4), distances) + assert np.all(np.isfinite(estimate)) + assert np.linalg.norm(estimate - target) < 1.0 \ No newline at end of file diff --git a/tests/test_mds_map.py b/tests/test_mds_map.py new file mode 100644 index 0000000..9f30620 --- /dev/null +++ b/tests/test_mds_map.py @@ -0,0 +1,10 @@ +import numpy as np + +from mdsmap_sim.mds_map import classical_mds, procrustes_align + + +def test_noise_free_mds_alignment_is_exact(): + points = np.array([[0, 0], [10, 0], [0, 10], [7, 4], [3, 8]], dtype=float) + distances = np.linalg.norm(points[:, None] - points[None, :], axis=2) + aligned = procrustes_align(classical_mds(distances), points, np.array([0, 1, 2])) + assert np.max(np.linalg.norm(aligned - points, axis=1)) < 1e-8 \ No newline at end of file diff --git a/tests/ttest_metrics.py b/tests/ttest_metrics.py new file mode 100644 index 0000000..c3597b6 --- /dev/null +++ b/tests/ttest_metrics.py @@ -0,0 +1,10 @@ +import numpy as np + +from mdsmap_sim.metrics import error_metrics + + +def test_error_metrics(): + metrics = error_metrics(np.array([1.0, 2.0, 3.0])) + assert metrics["mae"] == 2.0 + assert metrics["median"] == 2.0 + assert metrics["max"] == 3.0 \ No newline at end of file